diff options
author | Vladimir Makarov <vmakarov@redhat.com> | 2013-04-24 20:27:33 +0000 |
---|---|---|
committer | Vladimir Makarov <vmakarov@gcc.gnu.org> | 2013-04-24 20:27:33 +0000 |
commit | 77bce07cce1eee85627b0deb61f3ecf6e0da461f (patch) | |
tree | b6ddc9d79010428fd98fc997fa4e36e433e28267 /gcc | |
parent | 0db63e7fd0cb07d6882cd78f79fcfe067145a334 (diff) | |
download | gcc-77bce07cce1eee85627b0deb61f3ecf6e0da461f.zip gcc-77bce07cce1eee85627b0deb61f3ecf6e0da461f.tar.gz gcc-77bce07cce1eee85627b0deb61f3ecf6e0da461f.tar.bz2 |
re PR rtl-optimization/57046 (wrong code generated by gcc 4.8.0 on i686)
2013-04-24 Vladimir Makarov <vmakarov@redhat.com>
PR rtl-optimizations/57046
* lra-constraints (split_reg): Set up lra_risky_transformations_p
for multi-reg splits.
2013-04-24 Vladimir Makarov <vmakarov@redhat.com>
PR rtl-optimizations/57046
* gcc.target/i386/pr57046.c: New test.
From-SVN: r198263
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/lra-constraints.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr57046.c | 77 |
4 files changed, 98 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 875a747..b812431 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2013-04-24 Vladimir Makarov <vmakarov@redhat.com> + + PR rtl-optimizations/57046 + * lra-constraints (split_reg): Set up lra_risky_transformations_p + for multi-reg splits. + 2013-04-24 H.J. Lu <hongjiu.lu@intel.com> * config/i386/x86-64.h (ASM_SPEC): Support -mx32. diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index 24782dc..d364ef3 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -4198,7 +4198,7 @@ split_reg (bool before_p, int original_regno, rtx insn, rtx next_usage_insns) { enum reg_class rclass; rtx original_reg; - int hard_regno; + int hard_regno, nregs; rtx new_reg, save, restore, usage_insn; bool after_p; bool call_save_p; @@ -4208,10 +4208,12 @@ split_reg (bool before_p, int original_regno, rtx insn, rtx next_usage_insns) rclass = ira_allocno_class_translate[REGNO_REG_CLASS (original_regno)]; hard_regno = original_regno; call_save_p = false; + nregs = 1; } else { hard_regno = reg_renumber[original_regno]; + nregs = hard_regno_nregs[hard_regno][PSEUDO_REGNO_MODE (original_regno)]; rclass = lra_get_allocno_class (original_regno); original_reg = regno_reg_rtx[original_regno]; call_save_p = need_for_call_save_p (original_regno); @@ -4324,6 +4326,13 @@ split_reg (bool before_p, int original_regno, rtx insn, rtx next_usage_insns) before_p ? NULL_RTX : save, call_save_p ? "Add save<-reg" : "Add split<-reg"); + if (nregs > 1) + /* If we are trying to split multi-register. We should check + conflicts on the next assignment sub-pass. IRA can allocate on + sub-register levels, LRA do this on pseudos level right now and + this discrepancy may create allocation conflicts after + splitting. */ + lra_risky_transformations_p = true; if (lra_dump_file != NULL) fprintf (lra_dump_file, " ))))))))))))))))))))))))))))))))))))))))))))))))\n"); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e3b4a56..2eaa453 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2013-04-24 Vladimir Makarov <vmakarov@redhat.com> + + PR rtl-optimizations/57046 + * gcc.target/i386/pr57046.c: New test. + 2013-04-24 Paolo Carlini <paolo.carlini@oracle.com> * g++.dg/cpp1y/cplusplus.C: New. diff --git a/gcc/testsuite/gcc.target/i386/pr57046.c b/gcc/testsuite/gcc.target/i386/pr57046.c new file mode 100644 index 0000000..0aa43f9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr57046.c @@ -0,0 +1,77 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +struct emac { + unsigned reg[23]; +}; + +struct mop { + unsigned long long addr; + unsigned int size; +}; + +unsigned int __attribute__((__noinline__)) +level(const struct emac *obj) +{ + return 0; +} + +void __attribute__((__noinline__)) +info(struct emac *dev, unsigned long long addr) +{ + asm("" : : : "memory"); +} + +unsigned long long __attribute__((__noinline__)) +get_value(const struct mop *mop) +{ + return 0x1234567890abcdefull; +} + +int __attribute__((__noinline__)) +emac_operation(struct emac *obj, struct mop *mop) +{ + unsigned long long addr = mop->addr; + int index = addr >> 2; + unsigned int value, old_value; + + if (mop->size != 4) + return 0; + + if (index >= 23) { + if (level(obj) >= 1) + info(obj, addr); + return 0; + } + + value = get_value(mop); + old_value = obj->reg[index]; + + info(obj, 0); + + switch (index) { + case 0: + obj->reg[0] = old_value; + break; + case 7: + case 8: + obj->reg[index] = value; + break; + } + + return 0; +} + +int main(void) +{ + struct emac e = { { 0 } }; + struct mop mop = { 32, 4 }; + + e.reg[8] = 0xdeadbeef; + emac_operation(&e, &mop); + + if (e.reg[8] != 0x90abcdef) + __builtin_abort(); + + return 0; +} |