summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2016-01-28 03:40:06 -0200
committerAlexandre Oliva <aoliva@redhat.com>2016-01-28 03:40:06 -0200
commit3e30e53eba02493e4ebfe1801873f2f8c0c418db (patch)
treed4846180fa004cbe948cf22a676c3139b3413af8
parent4e03fd0d699b62d6a852b19e5e55b254d1159a43 (diff)
downloadgcc-aoliva/pr69461.tar.gz
[PR69461] LRA: check modes in reg class membership testaoliva/pr69461
for gcc/ChangeLog PR target/69461 * lra-constraints.c (in_class_p): Split... (available_regs_for_mode_in_class_p): ... this out. Test HARD_REGNO_MODE_OK. (simplify_operand_subreg): Proceed with simplification from valid to invalid MEM address if no REGs are available with the needed mode in the goal class. for gcc/testsuite/ChangeLog PR target/69461 * gcc.dg/torture/pr69461.c: New.
-rw-r--r--gcc/lra-constraints.c59
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr69461.c14
2 files changed, 51 insertions, 22 deletions
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index fb194165d49..df76c3d9cd6 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -240,6 +240,39 @@ get_reg_class (int regno)
return NO_REGS;
}
+/* Return TRUE iff there are any registers of REG_MODE available for
+ allocation in COMMON_CLASS. */
+
+static bool
+available_regs_for_mode_in_class_p (enum machine_mode reg_mode,
+ enum reg_class common_class)
+{
+ if (hard_reg_set_subset_p (reg_class_contents[common_class],
+ lra_no_alloc_regs))
+ return false;
+
+ /* Check that there are enough allocatable regs. */
+ int class_size = ira_class_hard_regs_num[common_class];
+ for (int i = 0; i < class_size; i++)
+ {
+ int hard_regno = ira_class_hard_regs[common_class][i];
+ if (!HARD_REGNO_MODE_OK (hard_regno, reg_mode))
+ continue;
+ int nregs = hard_regno_nregs[hard_regno][reg_mode];
+ if (nregs == 1)
+ return true;
+ int j;
+ for (j = 0; j < nregs; j++)
+ if (TEST_HARD_REG_BIT (lra_no_alloc_regs, hard_regno + j)
+ || ! TEST_HARD_REG_BIT (reg_class_contents[common_class],
+ hard_regno + j))
+ break;
+ if (j >= nregs)
+ return true;
+ }
+ return false;
+}
+
/* Return true if REG satisfies (or will satisfy) reg class constraint
CL. Use elimination first if REG is a hard register. If REG is a
reload pseudo created by this constraints pass, assume that it will
@@ -253,7 +286,6 @@ in_class_p (rtx reg, enum reg_class cl, enum reg_class *new_class)
{
enum reg_class rclass, common_class;
machine_mode reg_mode;
- int class_size, hard_regno, nregs, i, j;
int regno = REGNO (reg);
if (new_class != NULL)
@@ -292,26 +324,7 @@ in_class_p (rtx reg, enum reg_class cl, enum reg_class *new_class)
common_class = ira_reg_class_subset[rclass][cl];
if (new_class != NULL)
*new_class = common_class;
- if (hard_reg_set_subset_p (reg_class_contents[common_class],
- lra_no_alloc_regs))
- return false;
- /* Check that there are enough allocatable regs. */
- class_size = ira_class_hard_regs_num[common_class];
- for (i = 0; i < class_size; i++)
- {
- hard_regno = ira_class_hard_regs[common_class][i];
- nregs = hard_regno_nregs[hard_regno][reg_mode];
- if (nregs == 1)
- return true;
- for (j = 0; j < nregs; j++)
- if (TEST_HARD_REG_BIT (lra_no_alloc_regs, hard_regno + j)
- || ! TEST_HARD_REG_BIT (reg_class_contents[common_class],
- hard_regno + j))
- break;
- if (j >= nregs)
- return true;
- }
- return false;
+ return available_regs_for_mode_in_class_p (reg_mode, common_class);
}
}
@@ -1409,7 +1422,9 @@ simplify_operand_subreg (int nop, machine_mode reg_mode)
if (! valid_address_p (innermode, XEXP (reg, 0),
MEM_ADDR_SPACE (reg))
|| valid_address_p (GET_MODE (subst), XEXP (subst, 0),
- MEM_ADDR_SPACE (subst)))
+ MEM_ADDR_SPACE (subst))
+ || ! available_regs_for_mode_in_class_p (GET_MODE (subst),
+ goal_alt [nop]))
return true;
/* If the address was valid and became invalid, prefer to reload
the memory. Typical case is when the index scale should
diff --git a/gcc/testsuite/gcc.dg/torture/pr69461.c b/gcc/testsuite/gcc.dg/torture/pr69461.c
new file mode 100644
index 00000000000..24bdcc4da11
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr69461.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-mlra" } */
+
+typedef struct {
+ double real;
+ double imag;
+} Py_complex;
+Py_complex a;
+Py_complex fn1();
+Py_complex fn2() { return fn1(); }
+void fn3() {
+ _setjmp();
+ a = fn2();
+}