===================================================================
@@ -4198,7 +4198,7 @@ split_reg (bool before_p, int original_r
{
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_r
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_r
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");
===================================================================
@@ -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;
+}