From a79048f6250febc1acce09d790035276d534e754 Mon Sep 17 00:00:00 2001 From: Richard Earnshaw Date: Fri, 18 Oct 2019 19:04:46 +0000 Subject: [PATCH] [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 (usubv4): Delete expansion. (usubvsi4): New pattern. Allow some immediate values for inputs. (usubvdi4): New pattern. From-SVN: r277187 --- gcc/ChangeLog | 6 ++++++ gcc/config/arm/arm.md | 46 ++++++++++++++++++++++++++++++++++++++----- 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8275411b671..9e4e2d721a8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-10-18 Richard Earnshaw + + * config/arm/arm.md (usubv4): Delete expansion. + (usubvsi4): New pattern. Allow some immediate values for inputs. + (usubvdi4): New pattern. + 2019-10-18 Richard Earnshaw * config/arm/arm.c (arm_select_cc_mode): Allow either the first diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index e9e0ca925d2..a465bf8e7a3 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -1352,14 +1352,50 @@ DONE; }) -(define_expand "usubv4" - [(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_sub3_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; -- 2.30.2