diff options
author | vmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-04-24 20:27:33 +0000 |
---|---|---|
committer | vmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-04-24 20:27:33 +0000 |
commit | 74855d080d0657185317ae63bac158040908c3fe (patch) | |
tree | b6ddc9d79010428fd98fc997fa4e36e433e28267 | |
parent | 6c4ccb7bca11fdd0ba462e36d013e80d040aa9ae (diff) | |
download | gcc-74855d080d0657185317ae63bac158040908c3fe.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@198263 138bc75d-0d04-0410-961f-82ee72b054a4
-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 875a7479e4b..b812431d1d4 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 24782dcdec7..d364ef3407f 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 e3b4a56f73a..2eaa45366e0 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 00000000000..0aa43f9df6a --- /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; +} |