[arm] Improve code generation for addvsi4.
authorRichard Earnshaw <rearnsha@arm.com>
Fri, 18 Oct 2019 19:04:22 +0000 (19:04 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Fri, 18 Oct 2019 19:04:22 +0000 (19:04 +0000)
Similar to the improvements for uaddvsi4, this patch improves the code
generation for addvsi4 to handle immediates and to add alternatives
that better target thumb2.  To do this we separate out the expansion
of uaddvsi4 from that of uaddvdi4 and then add an additional pattern
to handle constants.  Also, while doing this I've fixed the incorrect
usage of NE instead of COMPARE in the generated RTL.

* config/arm/arm.md (addv<mode>4): Delete.
(addvsi4): New pattern.  Handle immediate values that the architecture
supports.
(addvdi4): New pattern.
(addsi3_compareV): Rename to ...
(addsi3_compareV_reg): ... this.  Add constraints for thumb2 variants
and use COMPARE rather than NE.
(addsi3_compareV_imm): New pattern.
* config/arm/arm.c (arm_select_cc_mode): Return CC_Vmode for
a signed-overflow check.

From-SVN: r277184

gcc/ChangeLog
gcc/config/arm/arm.c
gcc/config/arm/arm.md

index 902cf51a37c8aa9d6d5061aa820592122aa2cc10..4c82758a060b937779da4ddf9f4f4a8d57fc97d0 100644 (file)
@@ -1,3 +1,16 @@
+2019-10-18  Richard Earnshaw  <rearnsha@arm.com>
+
+       * config/arm/arm.md (addv<mode>4): Delete.
+       (addvsi4): New pattern.  Handle immediate values that the architecture
+       supports.
+       (addvdi4): New pattern.
+       (addsi3_compareV): Rename to ...
+       (addsi3_compareV_reg): ... this.  Add constraints for thumb2 variants
+       and use COMPARE rather than NE.
+       (addsi3_compareV_imm): New pattern.
+       * config/arm/arm.c (arm_select_cc_mode): Return CC_Vmode for
+       a signed-overflow check.
+
 2019-10-18  Richard Earnshaw  <rearnsha@arm.com>
 
        * config/arm/arm-modes.def (CC_ADC): New CC mode.
index fb1a68106519ae2cbefe81ad535e2a9f39545433..ba23970d060a8e6e5e115062fea63bb1af5b4b2f 100644 (file)
@@ -15411,6 +15411,14 @@ arm_select_cc_mode (enum rtx_code op, rtx x, rtx y)
          || arm_borrow_operation (y, DImode)))
     return CC_Bmode;
 
+  if (GET_MODE (x) == DImode
+      && (op == EQ || op == NE)
+      && GET_CODE (x) == PLUS
+      && GET_CODE (XEXP (x, 0)) == SIGN_EXTEND
+      && GET_CODE (y) == SIGN_EXTEND
+      && GET_CODE (XEXP (y, 0)) == PLUS)
+    return CC_Vmode;
+
   if (GET_MODE_CLASS (GET_MODE (x)) == MODE_CC)
     return GET_MODE (x);
 
index 9f0e43571fdbb99b3bf1980ff7b082fbd8d2fe84..b5214c79c3580f1db8457962e261bc9320ef8305 100644 (file)
   "
 )
 
-(define_expand "addv<mode>4"
-  [(match_operand:SIDI 0 "register_operand")
-   (match_operand:SIDI 1 "register_operand")
-   (match_operand:SIDI 2 "register_operand")
+(define_expand "addvsi4"
+  [(match_operand:SI 0 "s_register_operand")
+   (match_operand:SI 1 "s_register_operand")
+   (match_operand:SI 2 "arm_add_operand")
    (match_operand 3 "")]
   "TARGET_32BIT"
 {
-  emit_insn (gen_add<mode>3_compareV (operands[0], operands[1], operands[2]));
+  if (CONST_INT_P (operands[2]))
+    emit_insn (gen_addsi3_compareV_imm (operands[0], operands[1], operands[2]));
+  else
+    emit_insn (gen_addsi3_compareV_reg (operands[0], operands[1], operands[2]));
+  arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
+
+  DONE;
+})
+
+(define_expand "addvdi4"
+  [(match_operand:DI 0 "register_operand")
+   (match_operand:DI 1 "register_operand")
+   (match_operand:DI 2 "register_operand")
+   (match_operand 3 "")]
+  "TARGET_32BIT"
+{
+  emit_insn (gen_adddi3_compareV (operands[0], operands[1], operands[2]));
   arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
 
   DONE;
    (set_attr "type" "multiple")]
 )
 
-(define_insn "addsi3_compareV"
+(define_insn "addsi3_compareV_reg"
   [(set (reg:CC_V CC_REGNUM)
-       (ne:CC_V
+       (compare:CC_V
          (plus:DI
-           (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
-           (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
+           (sign_extend:DI (match_operand:SI 1 "register_operand" "%l,0,r"))
+           (sign_extend:DI (match_operand:SI 2 "register_operand" "l,r,r")))
          (sign_extend:DI (plus:SI (match_dup 1) (match_dup 2)))))
-   (set (match_operand:SI 0 "register_operand" "=r")
+   (set (match_operand:SI 0 "register_operand" "=l,r,r")
        (plus:SI (match_dup 1) (match_dup 2)))]
   "TARGET_32BIT"
   "adds%?\\t%0, %1, %2"
   [(set_attr "conds" "set")
+   (set_attr "arch" "t2,t2,*")
+   (set_attr "length" "2,2,4")
    (set_attr "type" "alus_sreg")]
 )
 
+(define_insn "addsi3_compareV_imm"
+  [(set (reg:CC_V CC_REGNUM)
+       (compare:CC_V
+         (plus:DI
+           (sign_extend:DI
+            (match_operand:SI 1 "register_operand" "l,0,l,0,r,r"))
+           (match_operand 2 "arm_addimm_operand" "Pd,Py,Px,Pw,I,L"))
+         (sign_extend:DI (plus:SI (match_dup 1) (match_dup 2)))))
+   (set (match_operand:SI 0 "register_operand" "=l,l,l,l,r,r")
+       (plus:SI (match_dup 1) (match_dup 2)))]
+  "TARGET_32BIT
+   && INTVAL (operands[2]) == ARM_SIGN_EXTEND (INTVAL (operands[2]))"
+  "@
+   adds%?\\t%0, %1, %2
+   adds%?\\t%0, %0, %2
+   subs%?\\t%0, %1, #%n2
+   subs%?\\t%0, %0, #%n2
+   adds%?\\t%0, %1, %2
+   subs%?\\t%0, %1, #%n2"
+  [(set_attr "conds" "set")
+   (set_attr "arch" "t2,t2,t2,t2,*,*")
+   (set_attr "length" "2,2,2,2,4,4")
+   (set_attr "type" "alus_imm")]
+)
+
 (define_insn "addsi3_compare0"
   [(set (reg:CC_NOOV CC_REGNUM)
        (compare:CC_NOOV