This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug target/43597] Move and compare with 0 can be combined



------- Comment #7 from carrot at google dot com  2010-04-22 12:26 -------
(In reply to comment #6)
> I can't see how it would hurt to allow combine to always merge insns that are
> known to be consecutive (ie to ignore CLASS_LIKELY_SPILLED_P if
> prev_nonenote_insn(consumer) == producer).
> 

I implemented the following patch

Index: combine.c
===================================================================
--- combine.c   (revision 158539)
+++ combine.c   (working copy)
@@ -384,6 +384,7 @@ static void do_SUBST_INT (int *, int);
 static void init_reg_last (void);
 static void setup_incoming_promotions (rtx);
 static void set_nonzero_bits_and_sign_copies (rtx, const_rtx, void *);
+static bool reg_likely_spilled_p (rtx, rtx, bool);
 static int cant_combine_insn_p (rtx);
 static int can_combine_p (rtx, rtx, rtx, rtx, rtx *, rtx *);
 static int combinable_i3pat (rtx, rtx *, rtx, rtx, int, rtx *);
@@ -1987,6 +1988,22 @@ contains_muldiv (rtx x)
     }
 }

+
+static bool
+reg_likely_spilled_p (rtx insn, rtx reg, bool reg_set)
+{
+  unsigned regno = REGNO (reg);
+  if (!reg_set)
+    {
+      rtx prev_insn = prev_nonnote_insn_bb (insn);
+      if ((prev_insn != NULL_RTX) && df_reg_defined (prev_insn, reg))
+        return false;
+    }
+
+  return ((regno < FIRST_PSEUDO_REGISTER) && !fixed_regs[regno]
+          && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (regno)));
+}
+
 /* Determine whether INSN can be used in a combination.  Return nonzero if
    not.  This is used in try_combine to detect early some cases where we
    can't perform combinations.  */
@@ -2020,12 +2037,8 @@ cant_combine_insn_p (rtx insn)
   if (GET_CODE (dest) == SUBREG)
     dest = SUBREG_REG (dest);
   if (REG_P (src) && REG_P (dest)
-      && ((REGNO (src) < FIRST_PSEUDO_REGISTER
-          && ! fixed_regs[REGNO (src)]
-          && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (REGNO (src))))
-         || (REGNO (dest) < FIRST_PSEUDO_REGISTER
-             && ! fixed_regs[REGNO (dest)]
-             && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (REGNO (dest))))))
+      && (reg_likely_spilled_p (insn, src, false)
+         || reg_likely_spilled_p (insn, dest, true)))
     return 1;

   return 0;

It can indeed combine the mov and cmp instructions. But it causes an x86
failure. Compile the following code with options -march=x86-64 -O2

extern long xxx (long);
int
gen_type (long x, long y)
{
  int size = (xxx (x) / xxx (y));
  return size;
}

GCC generates:

c-aux-info.i:7:1: error: unable to find a register to spill in class 'AREG'
c-aux-info.i:7:1: error: this is the insn:
(insn 13 12 19 2 c-aux-info.i:5 (parallel [
            (set (reg:DI 0 ax [67])
                (div:DI (reg:DI 3 bx [orig:58 D.2722 ] [58])
                    (reg:DI 0 ax)))
            (set (reg:DI 1 dx [68])
                (mod:DI (reg:DI 3 bx [orig:58 D.2722 ] [58])
                    (reg:DI 0 ax)))
            (clobber (reg:CC 17 flags))
        ]) 353 {*divmoddi4} (expr_list:REG_DEAD (reg:DI 3 bx [orig:58 D.2722 ]
[58])
        (expr_list:REG_DEAD (reg:DI 0 ax)
            (expr_list:REG_UNUSED (reg:DI 1 dx [68])
                (expr_list:REG_UNUSED (reg:CC 17 flags)
                    (nil))))))
c-aux-info.i:7:1: internal compiler error: in spill_failure, at reload1.c:2158

The root cause is with this patch, the original code sequence

(insn 12 11 13 2 c-aux-info.i:5 (set (reg:DI 59 [ D.2723 ])
        (reg:DI 0 ax)) 89 {*movdi_1_rex64} (expr_list:REG_DEAD (reg:DI 0 ax)
        (nil)))

(insn 13 12 19 2 c-aux-info.i:5 (parallel [
            (set (reg:DI 67)
                (div:DI (reg:DI 58 [ D.2722 ])
                    (reg:DI 59 [ D.2723 ])))
            (set (reg:DI 68)
                (mod:DI (reg:DI 58 [ D.2722 ])
                    (reg:DI 59 [ D.2723 ])))
            (clobber (reg:CC 17 flags))
        ]) 353 {*divmoddi4} (expr_list:REG_DEAD (reg:DI 59 [ D.2723 ])
        (expr_list:REG_DEAD (reg:DI 58 [ D.2722 ])
            (expr_list:REG_UNUSED (reg:DI 68)
                (expr_list:REG_UNUSED (reg:CC 17 flags)
                    (nil))))))

is merged into

(insn 13 12 19 2 c-aux-info.i:5 (parallel [
            (set (reg:DI 67)
                (div:DI (reg:DI 58 [ D.2722 ])
                    (reg:DI 0 ax)))
            (set (reg:DI 68)
                (mod:DI (reg:DI 58 [ D.2722 ])
                    (reg:DI 0 ax)))
            (clobber (reg:CC 17 flags))
        ]) 353 {*divmoddi4} (expr_list:REG_DEAD (reg:DI 0 ax)
        (expr_list:REG_UNUSED (reg:CC 17 flags)
            (expr_list:REG_UNUSED (reg:DI 68)
                (expr_list:REG_DEAD (reg:DI 58 [ D.2722 ])
                    (nil))))))

and it failed in register allocation.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43597


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]