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 <[email protected]>
* config/arm/arm.md (cstoresi_leu_thumb1): New define_insn_and_split
pattern.
(cstoresi4): Use above new pattern.
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