diff options
author | Alexandre Oliva <aoliva@redhat.com> | 2016-01-28 03:40:06 -0200 |
---|---|---|
committer | Alexandre Oliva <aoliva@redhat.com> | 2016-01-28 03:40:06 -0200 |
commit | 3e30e53eba02493e4ebfe1801873f2f8c0c418db (patch) | |
tree | d4846180fa004cbe948cf22a676c3139b3413af8 | |
parent | 4e03fd0d699b62d6a852b19e5e55b254d1159a43 (diff) | |
download | gcc-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.c | 59 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr69461.c | 14 |
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(); +} |