diff mbox

[GCC/THUMB1] New define_insn_and_split pattern to enable optimizing out certain unnecessary uxtb instruction

Message ID 000401cf4192$00bc12f0$023438d0$@arm.com
State New
Headers show

Commit Message

Terry Guo March 17, 2014, 3:35 a.m. UTC
Hi

The existing test case gcc.target/arm/unsigned-extend-1.c fails for Thumb1
target like cortex-m0 because the thumb1_addsi3_addgeu insn pattern isn't
friendly to gcc combine pass. Before combine pass, we have such insn for
this test case:

(insn 10 9 12 2 (set (reg:SI 118)
        (plus:SI (plus:SI (reg:SI 120)
                (reg:SI 120))
            (geu:SI (reg:SI 119)
                (reg:SI 117))))

When the operand (reg:SI 120) is zero and operand (reg:SI 119) is constant
9, combine pass will turn this insn into:

(insn 10 9 12 2 (set (reg:SI 118)
                     (leu:SI (reg:SI 116) (const_int 9))))

Unfortunately this new insn doesn't match any existing patterns, this causes
combine pass to undo all attempts and results in sub-optimal code. The
attached patch intends to legitimize the new insn.

Tested with gcc regression test and no new regression.

Is it OK to trunk?

BR,
Terry

2014-03-17  Terry Guo  <terry.guo@arm.com>

        * config/arm/arm.md (cstoresi_leu_thumb1): New define_insn_and_split
pattern.
        (cstoresi4): Use above new pattern.
diff mbox

Patch

diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 2ddda02..905a5b8 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -8755,18 +8755,14 @@ 
 
     case LEU:
       op3 = force_reg (SImode, operands[3]);
-      scratch = force_reg (SImode, const0_rtx);
-      emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
-					  op3, operands[2]));
+      emit_insn (gen_cstoresi_leu_thumb1 (operands[0], operands[2], op3));
       break;
 
     case GEU:
       op3 = operands[3];
       if (!thumb1_cmp_operand (op3, SImode))
         op3 = force_reg (SImode, op3);
-      scratch = force_reg (SImode, const0_rtx);
-      emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
-					  operands[2], op3));
+      emit_insn (gen_cstoresi_leu_thumb1 (operands[0], op3, operands[2]));
       break;
 
     case LTU:
@@ -8909,6 +8905,34 @@ 
    (set_attr "type" "multiple")]
 )
 
+(define_insn_and_split "cstoresi_leu_thumb1"
+  [(set (match_operand:SI 0 "s_register_operand" "=l")
+	(leu:SI (match_operand:SI 1 "s_register_operand" "l")
+		(match_operand:SI 2 "thumb1_cmp_operand" "lI")))]
+  "TARGET_THUMB1"
+  "#"
+  "TARGET_THUMB1"
+  [(set (match_dup 3) (const_int 0))
+   (set (match_dup 0)
+	(plus:SI (plus:SI (match_dup 3)
+			  (match_dup 3))
+		 (geu:SI (match_dup 4)
+			 (match_dup 1))))]
+  "
+    operands[3] = gen_reg_rtx (SImode);
+
+    if (CONST_INT_P (operands[2]))
+      {
+        operands[4] = gen_reg_rtx (SImode);
+        emit_move_insn (operands[4], operands[2]);
+      }
+    else
+      operands[4] = operands[2];
+  "
+  [(set_attr "length" "4")
+   (set_attr "type" "multiple")]
+)
+
 
 ;; Conditional move insns