diff options
author | Richard Earnshaw <rearnsha@arm.com> | 2019-10-18 19:04:46 +0000 |
---|---|---|
committer | Richard Earnshaw <rearnsha@gcc.gnu.org> | 2019-10-18 19:04:46 +0000 |
commit | a79048f6250febc1acce09d790035276d534e754 (patch) | |
tree | f1e52a3111c47fb41bbec05a282a1f88a986cbd6 | |
parent | fa62df0e600ef617bce549d64026c0e5cc817c31 (diff) | |
download | gcc-a79048f6250febc1acce09d790035276d534e754.zip gcc-a79048f6250febc1acce09d790035276d534e754.tar.gz gcc-a79048f6250febc1acce09d790035276d534e754.tar.bz2 |
[arm] Improve constant handling for usubvsi4.
This patch improves the expansion of usubvsi4 by allowing suitable
constants to be passed directly. Unlike normal subtraction, either
operand may be a constant (and indeed I have seen cases where both can
be with LTO enabled). One interesting testcase that improves as a
result of this is:
unsigned f6 (unsigned a)
{
unsigned x;
return __builtin_sub_overflow (5U, a, &x) ? 0 : x;
}
Which previously compiled to:
rsbs r3, r0, #5
cmp r0, #5
movls r0, r3
movhi r0, #0
but now generates the optimal sequence:
rsbs r0, r0, #5
movcc r0, #0
* config/arm/arm.md (usubv<mode>4): Delete expansion.
(usubvsi4): New pattern. Allow some immediate values for inputs.
(usubvdi4): New pattern.
From-SVN: r277187
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/config/arm/arm.md | 46 |
2 files changed, 47 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8275411..9e4e2d7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2019-10-18 Richard Earnshaw <rearnsha@arm.com> + * config/arm/arm.md (usubv<mode>4): Delete expansion. + (usubvsi4): New pattern. Allow some immediate values for inputs. + (usubvdi4): New pattern. + +2019-10-18 Richard Earnshaw <rearnsha@arm.com> + * config/arm/arm.c (arm_select_cc_mode): Allow either the first or second operand of the PLUS inside a DImode equality test to be sign-extend when selecting CC_Vmode. diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index e9e0ca9..a465bf8 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -1352,14 +1352,50 @@ DONE; }) -(define_expand "usubv<mode>4" - [(match_operand:SIDI 0 "register_operand") - (match_operand:SIDI 1 "register_operand") - (match_operand:SIDI 2 "register_operand") +(define_expand "usubvsi4" + [(match_operand:SI 0 "s_register_operand") + (match_operand:SI 1 "arm_rhs_operand") + (match_operand:SI 2 "arm_add_operand") (match_operand 3 "")] "TARGET_32BIT" { - emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2])); + machine_mode mode = CCmode; + if (CONST_INT_P (operands[1]) && CONST_INT_P (operands[2])) + { + /* If both operands are constants we can decide the result statically. */ + wi::overflow_type overflow; + wide_int val = wi::sub (rtx_mode_t (operands[1], SImode), + rtx_mode_t (operands[2], SImode), + UNSIGNED, &overflow); + emit_move_insn (operands[0], GEN_INT (val.to_shwi ())); + if (overflow != wi::OVF_NONE) + emit_jump_insn (gen_jump (operands[3])); + DONE; + } + else if (CONST_INT_P (operands[2])) + emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2], + GEN_INT (-INTVAL (operands[2])))); + else if (CONST_INT_P (operands[1])) + { + mode = CC_RSBmode; + emit_insn (gen_rsb_imm_compare (operands[0], operands[1], operands[2], + GEN_INT (~UINTVAL (operands[1])))); + } + else + emit_insn (gen_subsi3_compare1 (operands[0], operands[1], operands[2])); + arm_gen_unlikely_cbranch (LTU, mode, operands[3]); + + DONE; +}) + +(define_expand "usubvdi4" + [(match_operand:DI 0 "s_register_operand") + (match_operand:DI 1 "s_register_operand") + (match_operand:DI 2 "s_register_operand") + (match_operand 3 "")] + "TARGET_32BIT" +{ + emit_insn (gen_subdi3_compare1 (operands[0], operands[1], operands[2])); arm_gen_unlikely_cbranch (LTU, CCmode, operands[3]); DONE; |