diff mbox series

[21/29,arm] Improve code generation for addvsi4.

Message ID 20191018194900.34795-22-Richard.Earnshaw@arm.com
State New
Headers show
Series Rewrite DImode arithmetic support | expand

Commit Message

Richard Earnshaw (lists) Oct. 18, 2019, 7:48 p.m. UTC
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.
---
 gcc/config/arm/arm.c  |  8 ++++++
 gcc/config/arm/arm.md | 63 ++++++++++++++++++++++++++++++++++++-------
 2 files changed, 61 insertions(+), 10 deletions(-)
diff mbox series

Patch

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index eebbdc3d9c2..638c82df25f 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -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);
 
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 9f0e43571fd..b5214c79c35 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -488,14 +488,30 @@  (define_expand "adddi3"
   "
 )
 
-(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;
@@ -770,21 +786,48 @@  (define_insn "adddi3_compareV"
    (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