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....@arm.com> * 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