Hi,
For thumb1, arm-gcc rewrites move insn into subtract of ZERO in peephole2
pass intentionally, then executes
pass_if_after_reload/pass_regrename/pass_cprop_hardreg sequentially.

In this scenario, copy propagation opportunities are missed because:
  1. the move insns are re-written.
  2. pass_cprop_hardreg currently don't notice the subtract of ZERO.

This patch fixes the problem and the logic is:
  1. notice the plus/subtract of ZERO in pass_cprop_hardreg.
  2. if the last insn providing information about conditional codes is in
the form of "dest_reg = src_reg - 0", record the src_reg in newly added
field thumb1_cc_op0_src of structure machine_function.
  3. in pattern "cbranchsi4_insn", check thumb1_cc_op0_src along with
thumb1_cc_op0 to save one comparison insn.

I measured the patch on CSiBE, about 600 bytes are saved for both O2 and Os
on cortex-m0 without any regression.

I also tested the patch on
arm-none-eabi+cortex-m0/arm-none-eabi+cortex-m3/i686-pc-linux and no
regressions introduced.

So is it OK?

Thanks

2012-08-13  Bin Cheng  <bin.ch...@arm.com>

        * regcprop.c (copyprop_hardreg_forward_1) Notice copies in the form
of
        subtract of ZERO.
        * config/arm/arm.h (thumb1_cc_op0_src) New field.
        * config/arm/arm.c (thumb1_final_prescan_insn) Record
thumb1_cc_op0_src.
        * config/arm/arm.md (cbranchsi4_insn) Check thumb1_cc_op0_src along
with
        thumb1_cc_op0.
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c        (revision 189835)
+++ gcc/config/arm/arm.c        (working copy)
@@ -21663,6 +21663,8 @@
       if (cfun->machine->thumb1_cc_insn)
        {
          if (modified_in_p (cfun->machine->thumb1_cc_op0, insn)
+             || (cfun->machine->thumb1_cc_op0_src != NULL_RTX
+                 && modified_in_p (cfun->machine->thumb1_cc_op0_src, insn))
              || modified_in_p (cfun->machine->thumb1_cc_op1, insn))
            CC_STATUS_INIT;
        }
@@ -21672,13 +21674,18 @@
          rtx set = single_set (insn);
          cfun->machine->thumb1_cc_insn = insn;
          cfun->machine->thumb1_cc_op0 = SET_DEST (set);
+         cfun->machine->thumb1_cc_op0_src = NULL_RTX;
          cfun->machine->thumb1_cc_op1 = const0_rtx;
          cfun->machine->thumb1_cc_mode = CC_NOOVmode;
          if (INSN_CODE (insn) == CODE_FOR_thumb1_subsi3_insn)
            {
              rtx src1 = XEXP (SET_SRC (set), 1);
              if (src1 == const0_rtx)
-               cfun->machine->thumb1_cc_mode = CCmode;
+               {
+                 cfun->machine->thumb1_cc_mode = CCmode;
+                 /* Record the minuend in thumb1_subsi3_insn pattern.  */
+                 cfun->machine->thumb1_cc_op0_src = XEXP (SET_SRC (set), 0);
+               }
            }
        }
       else if (conds != CONDS_NOCOND)
Index: gcc/config/arm/arm.h
===================================================================
--- gcc/config/arm/arm.h        (revision 189835)
+++ gcc/config/arm/arm.h        (working copy)
@@ -1459,9 +1459,17 @@
      is not needed.  */
   int return_used_this_function;
   /* When outputting Thumb-1 code, record the last insn that provides
-     information about condition codes, and the comparison operands.  */
+     information about condition codes, and the comparison operands.
+
+     If the last insn that provides information about condition codes
+     is in the form of "dest_reg = src_reg - 0", record the src_reg in
+     thumb1_cc_op0_src, and for following insn sequence:
+        dest_reg = src_reg - 0;
+        if (src_reg ?= 0) goto label;
+     the comparison insn can also be saved.  */
   rtx thumb1_cc_insn;
   rtx thumb1_cc_op0;
+  rtx thumb1_cc_op0_src;
   rtx thumb1_cc_op1;
   /* Also record the CC mode that is supported.  */
   enum machine_mode thumb1_cc_mode;
Index: gcc/config/arm/arm.md
===================================================================
--- gcc/config/arm/arm.md       (revision 189835)
+++ gcc/config/arm/arm.md       (working copy)
@@ -7018,7 +7018,8 @@
   rtx t = cfun->machine->thumb1_cc_insn;
   if (t != NULL_RTX)
     {
-      if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
+      if ((!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
+          && !rtx_equal_p (cfun->machine->thumb1_cc_op0_src, operands[1]))
          || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
        t = NULL_RTX;
       if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
@@ -7034,6 +7035,7 @@
       output_asm_insn ("cmp\t%1, %2", operands);
       cfun->machine->thumb1_cc_insn = insn;
       cfun->machine->thumb1_cc_op0 = operands[1];
+      cfun->machine->thumb1_cc_op0_src = NULL_RTX;
       cfun->machine->thumb1_cc_op1 = operands[2];
       cfun->machine->thumb1_cc_mode = CCmode;
     }
Index: gcc/regcprop.c
===================================================================
--- gcc/regcprop.c      (revision 189835)
+++ gcc/regcprop.c      (working copy)
@@ -1019,8 +1019,18 @@
       note_stores (PATTERN (insn), kill_set_value, &ksvd);
 
       /* Notice copies.  */
-      if (set && REG_P (SET_DEST (set)) && REG_P (SET_SRC (set)))
-       copy_value (SET_DEST (set), SET_SRC (set), vd);
+      if (set && REG_P (SET_DEST (set)))
+       {
+         if (REG_P (SET_SRC (set)))
+           copy_value (SET_DEST (set), SET_SRC (set), vd);
+         /* ARM backend intentionally rewrite move insn into subtract of 0 if
+            the condition codes will be useful, so also notice this case.  */
+         else if ((GET_CODE (SET_SRC (set)) == PLUS
+                   || GET_CODE (SET_SRC (set)) == MINUS)
+                  && REG_P (XEXP (SET_SRC (set), 0))
+                  && XEXP (SET_SRC (set), 1) == const0_rtx)
+           copy_value (SET_DEST (set), XEXP (SET_SRC (set), 0), vd);
+       }
 
       if (insn == BB_END (bb))
        break;

Reply via email to