diff mbox series

[05/16,APX,NDD] Support APX NDD for adc insns

Message ID 20231115094705.3976553-6-hongyu.wang@intel.com
State New
Headers show
Series Support Intel APX NDD | expand

Commit Message

Hongyu Wang Nov. 15, 2023, 9:46 a.m. UTC
From: Kong Lingling <lingling.kong@intel.com>

Legacy adc patterns are commonly adopted to TImode add, when extending TImode
add to NDD version, operands[0] and operands[1] can be different, so extra move
should be emitted if those patterns have optimization when adding const0_rtx.

gcc/ChangeLog:

	* config/i386/i386.md (*add<dwi>3_doubleword): Add ndd constraints, and
	move operands[1] to operands[0] when they are not equal.
	(*add<dwi>3_doubleword_cc_overflow_1): Likewise.
	(*add<dwi>3_doubleword_zext): Add ndd constraints.
	(*addv<dwi>4_doubleword): Likewise.
	(*addv<dwi>4_doubleword_1): Likewise.
	(addv<mode>4_overflow_1): Likewise.
	(*addv<mode>4_overflow_2): Likewise.
	(@add<mode>3_carry): Likewise.
	(*add<mode>3_carry_0): Likewise.
	(*addsi3_carry_zext): Likewise.
	(*addsi3_carry_zext_0): Likewise.
	(addcarry<mode>): Likewise.
	(addcarry<mode>_0): Likewise.
	(*addcarry<mode>_1): Likewise.
	(*add<mode>3_eq): Likewise.
	(*add<mode>3_ne): Likewise.

gcc/testsuite/ChangeLog:

	* gcc.target/i386/apx-ndd-adc.c: New test.
---
 gcc/config/i386/i386.md                     | 203 +++++++++++++-------
 gcc/testsuite/gcc.target/i386/apx-ndd-adc.c |  15 ++
 2 files changed, 146 insertions(+), 72 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-adc.c
diff mbox series

Patch

diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index ecd06625a7d..f23859d1172 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -6235,12 +6235,13 @@  (define_expand "add<mode>3"
 				ix86_can_use_ndd_p (PLUS)); DONE;")
 
 (define_insn_and_split "*add<dwi>3_doubleword"
-  [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r")
+  [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,r,r")
 	(plus:<DWI>
-	  (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0")
-	  (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o")))
+	  (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,r")
+	  (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r<di>,r")))
    (clobber (reg:CC FLAGS_REG))]
-  "ix86_binary_operator_ok (PLUS, <DWI>mode, operands)"
+  "ix86_binary_operator_ok (PLUS, <DWI>mode, operands,
+			    ix86_can_use_ndd_p (PLUS))"
   "#"
   "&& reload_completed"
   [(parallel [(set (reg:CCC FLAGS_REG)
@@ -6260,24 +6261,35 @@  (define_insn_and_split "*add<dwi>3_doubleword"
   split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], &operands[3]);
   if (operands[2] == const0_rtx)
     {
+      /* Under NDD op0 and op1 may not equal, do not delete insn then.  */
+
+      bool emit_insn_deleted_note_p = true;
+      if (!rtx_equal_p (operands[0], operands[1]))
+	{
+	  emit_move_insn (operands[0], operands[1]);
+	  emit_insn_deleted_note_p = false;
+	}
       if (operands[5] != const0_rtx)
-	ix86_expand_binary_operator (PLUS, <MODE>mode, &operands[3]);
+	ix86_expand_binary_operator (PLUS, <MODE>mode, &operands[3],
+				     ix86_can_use_ndd_p (PLUS));
       else if (!rtx_equal_p (operands[3], operands[4]))
 	emit_move_insn (operands[3], operands[4]);
-      else
+      else if (emit_insn_deleted_note_p)
 	emit_note (NOTE_INSN_DELETED);
       DONE;
     }
-})
+}
+[(set_attr "isa" "*,*,apx_ndd,apx_ndd")])
 
 (define_insn_and_split "*add<dwi>3_doubleword_zext"
-  [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=r,o")
+  [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=r,o,r,r")
 	(plus:<DWI>
 	  (zero_extend:<DWI>
-	    (match_operand:DWIH 2 "nonimmediate_operand" "rm,r")) 
-	  (match_operand:<DWI> 1 "nonimmediate_operand" "0,0")))
+	    (match_operand:DWIH 2 "nonimmediate_operand" "rm,r,rm,r"))
+	  (match_operand:<DWI> 1 "nonimmediate_operand" "0,0,r,m")))
    (clobber (reg:CC FLAGS_REG))]
-  "ix86_binary_operator_ok (UNKNOWN, <DWI>mode, operands)"
+  "ix86_binary_operator_ok (UNKNOWN, <DWI>mode, operands,
+			  ix86_can_use_ndd_p (PLUS))"
   "#"
   "&& reload_completed"
   [(parallel [(set (reg:CCC FLAGS_REG)
@@ -6293,7 +6305,8 @@  (define_insn_and_split "*add<dwi>3_doubleword_zext"
 		       (match_dup 4))
 		     (const_int 0)))
 	      (clobber (reg:CC FLAGS_REG))])]
- "split_double_mode (<DWI>mode, &operands[0], 2, &operands[0], &operands[3]);")
+ "split_double_mode (<DWI>mode, &operands[0], 2, &operands[0], &operands[3]);"
+ [(set_attr "isa" "*,*,apx_ndd,apx_ndd")])
 
 (define_insn_and_split "*add<dwi>3_doubleword_concat"
   [(set (match_operand:<DWI> 0 "register_operand" "=&r")
@@ -7269,14 +7282,15 @@  (define_insn_and_split "*addv<dwi>4_doubleword"
 	(eq:CCO
 	  (plus:<QPWI>
 	    (sign_extend:<QPWI>
-	      (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0"))
+	      (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,r"))
 	    (sign_extend:<QPWI>
-	      (match_operand:<DWI> 2 "nonimmediate_operand" "r,o")))
+	      (match_operand:<DWI> 2 "nonimmediate_operand" "r,o,r,o")))
 	  (sign_extend:<QPWI>
 	    (plus:<DWI> (match_dup 1) (match_dup 2)))))
-   (set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r")
+   (set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,r,r")
 	(plus:<DWI> (match_dup 1) (match_dup 2)))]
-  "ix86_binary_operator_ok (PLUS, <DWI>mode, operands)"
+  "ix86_binary_operator_ok (PLUS, <DWI>mode, operands,
+			    ix86_can_use_ndd_p (PLUS))"
   "#"
   "&& reload_completed"
   [(parallel [(set (reg:CCC FLAGS_REG)
@@ -7306,22 +7320,24 @@  (define_insn_and_split "*addv<dwi>4_doubleword"
 		     (match_dup 5)))])]
 {
   split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], &operands[3]);
-})
+}
+[(set_attr "isa" "*,*,apx_ndd,apx_ndd")])
 
 (define_insn_and_split "*addv<dwi>4_doubleword_1"
   [(set (reg:CCO FLAGS_REG)
 	(eq:CCO
 	  (plus:<QPWI>
 	    (sign_extend:<QPWI>
-	      (match_operand:<DWI> 1 "nonimmediate_operand" "%0"))
-	    (match_operand:<QPWI> 3 "const_scalar_int_operand" "n"))
+	      (match_operand:<DWI> 1 "nonimmediate_operand" "%0,rm"))
+	    (match_operand:<QPWI> 3 "const_scalar_int_operand" "n,n"))
 	  (sign_extend:<QPWI>
 	    (plus:<DWI>
 	      (match_dup 1)
-	      (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "<di>")))))
-   (set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro")
+	      (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "<di>,<di>")))))
+   (set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r")
 	(plus:<DWI> (match_dup 1) (match_dup 2)))]
-  "ix86_binary_operator_ok (PLUS, <DWI>mode, operands)
+  "ix86_binary_operator_ok (PLUS, <DWI>mode, operands,
+			    ix86_can_use_ndd_p (PLUS))
    && CONST_SCALAR_INT_P (operands[2])
    && rtx_equal_p (operands[2], operands[3])"
   "#"
@@ -7359,7 +7375,8 @@  (define_insn_and_split "*addv<dwi>4_doubleword_1"
 				    operands[5]));
       DONE;
     }
-})
+}
+[(set_attr "isa" "*,apx_ndd")])
 
 (define_insn "*addv<mode>4_overflow_1"
   [(set (reg:CCO FLAGS_REG)
@@ -7369,9 +7386,9 @@  (define_insn "*addv<mode>4_overflow_1"
 	      (match_operator:<DWI> 4 "ix86_carry_flag_operator"
 		[(match_operand 3 "flags_reg_operand") (const_int 0)])
 	      (sign_extend:<DWI>
-		(match_operand:SWI 1 "nonimmediate_operand" "%0,0")))
+		(match_operand:SWI 1 "nonimmediate_operand" "%0,0,rm,r")))
 	    (sign_extend:<DWI>
-	      (match_operand:SWI 2 "<general_sext_operand>" "rWe,m")))
+	      (match_operand:SWI 2 "<general_sext_operand>" "rWe,m,rWe,m")))
 	  (sign_extend:<DWI>
 	    (plus:SWI
 	      (plus:SWI
@@ -7379,15 +7396,22 @@  (define_insn "*addv<mode>4_overflow_1"
 		  [(match_dup 3) (const_int 0)])
 		(match_dup 1))
 	      (match_dup 2)))))
-   (set (match_operand:SWI 0 "nonimmediate_operand" "=rm,r")
+   (set (match_operand:SWI 0 "nonimmediate_operand" "=rm,r,r,r")
 	(plus:SWI
 	  (plus:SWI
 	    (match_op_dup 5 [(match_dup 3) (const_int 0)])
 	    (match_dup 1))
 	  (match_dup 2)))]
-  "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
-  "adc{<imodesuffix>}\t{%2, %0|%0, %2}"
-  [(set_attr "type" "alu")
+  "ix86_binary_operator_ok (PLUS, <MODE>mode, operands,
+			    ix86_can_use_ndd_p (PLUS))"
+{
+  if (which_alternative == 2 || which_alternative == 3)
+    return "adc{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}";
+  else
+    return "adc{<imodesuffix>}\t{%2, %0|%0, %2}";
+}
+  [(set_attr "isa" "*,*,apx_ndd,apx_ndd")
+   (set_attr "type" "alu")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "*addv<mode>4_overflow_2"
@@ -7398,26 +7422,30 @@  (define_insn "*addv<mode>4_overflow_2"
 	      (match_operator:<DWI> 4 "ix86_carry_flag_operator"
 		[(match_operand 3 "flags_reg_operand") (const_int 0)])
 	      (sign_extend:<DWI>
-		(match_operand:SWI 1 "nonimmediate_operand" "%0")))
-	    (match_operand:<DWI> 6 "const_int_operand" "n"))
+		(match_operand:SWI 1 "nonimmediate_operand" "%0,rm")))
+	    (match_operand:<DWI> 6 "const_int_operand" "n,n"))
 	  (sign_extend:<DWI>
 	    (plus:SWI
 	      (plus:SWI
 		(match_operator:SWI 5 "ix86_carry_flag_operator"
 		  [(match_dup 3) (const_int 0)])
 		(match_dup 1))
-	      (match_operand:SWI 2 "x86_64_immediate_operand" "e")))))
-   (set (match_operand:SWI 0 "nonimmediate_operand" "=rm")
+	      (match_operand:SWI 2 "x86_64_immediate_operand" "e,e")))))
+   (set (match_operand:SWI 0 "nonimmediate_operand" "=rm,r")
 	(plus:SWI
 	  (plus:SWI
 	    (match_op_dup 5 [(match_dup 3) (const_int 0)])
 	    (match_dup 1))
 	  (match_dup 2)))]
-  "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)
+  "ix86_binary_operator_ok (PLUS, <MODE>mode, operands,
+			    ix86_can_use_ndd_p (PLUS))
    && CONST_INT_P (operands[2])
    && INTVAL (operands[2]) == INTVAL (operands[6])"
-  "adc{<imodesuffix>}\t{%2, %0|%0, %2}"
-  [(set_attr "type" "alu")
+  "@
+  adc{<imodesuffix>}\t{%2, %0|%0, %2}
+  adc{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}"
+  [(set_attr "isa" "*,apx_ndd")
+   (set_attr "type" "alu")
    (set_attr "mode" "<MODE>")
    (set (attr "length_immediate")
      (if_then_else (match_test "IN_RANGE (INTVAL (operands[2]), -128, 127)")
@@ -8143,17 +8171,24 @@  (define_insn "*subsi_3_zext"
 ;; Add with carry and subtract with borrow
 
 (define_insn "@add<mode>3_carry"
-  [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
+  [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>,r,r")
 	(plus:SWI
 	  (plus:SWI
 	    (match_operator:SWI 4 "ix86_carry_flag_operator"
 	     [(match_operand 3 "flags_reg_operand") (const_int 0)])
-	    (match_operand:SWI 1 "nonimmediate_operand" "%0,0"))
-	  (match_operand:SWI 2 "<general_operand>" "<r><i>,<m>")))
+	    (match_operand:SWI 1 "nonimmediate_operand" "%0,0,rm,r"))
+	  (match_operand:SWI 2 "<general_operand>" "<r><i>,<m>,r<i>,<m>")))
    (clobber (reg:CC FLAGS_REG))]
-  "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
-  "adc{<imodesuffix>}\t{%2, %0|%0, %2}"
-  [(set_attr "type" "alu")
+  "ix86_binary_operator_ok (PLUS, <MODE>mode, operands,
+			    ix86_can_use_ndd_p (PLUS))"
+{
+  if (which_alternative == 2 || which_alternative == 3)
+    return "adc{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}";
+  else
+    return "adc{<imodesuffix>}\t{%2, %0|%0, %2}";
+}
+  [(set_attr "isa" "*,*,apx_ndd,apx_ndd")
+   (set_attr "type" "alu")
    (set_attr "use_carry" "1")
    (set_attr "pent_pair" "pu")
    (set_attr "mode" "<MODE>")])
@@ -8240,31 +8275,38 @@  (define_insn "*add<mode>3_carry_0r"
    (set_attr "mode" "<MODE>")])
 
 (define_insn "*addsi3_carry_zext"
-  [(set (match_operand:DI 0 "register_operand" "=r")
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
 	(zero_extend:DI
 	  (plus:SI
 	    (plus:SI (match_operator:SI 3 "ix86_carry_flag_operator"
 		      [(reg FLAGS_REG) (const_int 0)])
-		     (match_operand:SI 1 "register_operand" "%0"))
-	    (match_operand:SI 2 "x86_64_general_operand" "rBMe"))))
+		     (match_operand:SI 1 "register_operand" "%0i,r"))
+	    (match_operand:SI 2 "x86_64_general_operand" "rBMe,rBMe"))))
    (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
-  "adc{l}\t{%2, %k0|%k0, %2}"
-  [(set_attr "type" "alu")
+  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands,
+					    ix86_can_use_ndd_p (PLUS))"
+  "@
+  adc{l}\t{%2, %k0|%k0, %2}
+  adc{l}\t{%2, %1, %k0|%k0, %1, %2}"
+  [(set_attr "isa" "*,apx_ndd")
+   (set_attr "type" "alu")
    (set_attr "use_carry" "1")
    (set_attr "pent_pair" "pu")
    (set_attr "mode" "SI")])
 
 (define_insn "*addsi3_carry_zext_0"
-  [(set (match_operand:DI 0 "register_operand" "=r")
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
 	(zero_extend:DI
 	  (plus:SI (match_operator:SI 2 "ix86_carry_flag_operator"
 		    [(reg FLAGS_REG) (const_int 0)])
-		   (match_operand:SI 1 "register_operand" "0"))))
+		   (match_operand:SI 1 "register_operand" "0,r"))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT"
-  "adc{l}\t{$0, %k0|%k0, 0}"
-  [(set_attr "type" "alu")
+  "@
+  adc{l}\t{$0, %k0|%k0, 0}
+  adc{l}\t{$0, %1, %k0|%k0, %1, 0}"
+  [(set_attr "isa" "*,apx_ndd")
+   (set_attr "type" "alu")
    (set_attr "use_carry" "1")
    (set_attr "pent_pair" "pu")
    (set_attr "mode" "SI")])
@@ -8293,20 +8335,26 @@  (define_insn "addcarry<mode>"
 	      (plus:SWI48
 		(match_operator:SWI48 5 "ix86_carry_flag_operator"
 		  [(match_operand 3 "flags_reg_operand") (const_int 0)])
-		(match_operand:SWI48 1 "nonimmediate_operand" "%0,0"))
-	      (match_operand:SWI48 2 "nonimmediate_operand" "r,rm")))
+		(match_operand:SWI48 1 "nonimmediate_operand" "%0,0,rm,r"))
+	      (match_operand:SWI48 2 "nonimmediate_operand" "r,rm,r,m")))
 	  (plus:<DWI>
 	    (zero_extend:<DWI> (match_dup 2))
 	    (match_operator:<DWI> 4 "ix86_carry_flag_operator"
 	      [(match_dup 3) (const_int 0)]))))
-   (set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r")
+   (set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r,r,r")
 	(plus:SWI48 (plus:SWI48 (match_op_dup 5
 				 [(match_dup 3) (const_int 0)])
 				(match_dup 1))
 		    (match_dup 2)))]
-  "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
-  "adc{<imodesuffix>}\t{%2, %0|%0, %2}"
-  [(set_attr "type" "alu")
+  "ix86_binary_operator_ok (PLUS, <MODE>mode, operands,
+			    ix86_can_use_ndd_p (PLUS))"
+  "@
+  adc{<imodesuffix>}\t{%2, %0|%0, %2}
+  adc{<imodesuffix>}\t{%2, %0|%0, %2}
+  adc{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}
+  adc{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}"
+  [(set_attr "isa" "*,*,apx_ndd,apx_ndd")
+   (set_attr "type" "alu")
    (set_attr "use_carry" "1")
    (set_attr "pent_pair" "pu")
    (set_attr "mode" "<MODE>")])
@@ -8464,7 +8512,8 @@  (define_expand "addcarry<mode>_0"
 	     (match_dup 1)))
       (set (match_operand:SWI48 0 "nonimmediate_operand")
 	   (plus:SWI48 (match_dup 1) (match_dup 2)))])]
-  "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)")
+  "ix86_binary_operator_ok (PLUS, <MODE>mode, operands,
+			    ix86_can_use_ndd_p (PLUS))")
 
 (define_insn "*addcarry<mode>_1"
   [(set (reg:CCC FLAGS_REG)
@@ -8474,18 +8523,19 @@  (define_insn "*addcarry<mode>_1"
 	      (plus:SWI48
 		(match_operator:SWI48 5 "ix86_carry_flag_operator"
 		  [(match_operand 3 "flags_reg_operand") (const_int 0)])
-		(match_operand:SWI48 1 "nonimmediate_operand" "%0"))
-	      (match_operand:SWI48 2 "x86_64_immediate_operand" "e")))
+		(match_operand:SWI48 1 "nonimmediate_operand" "%0,rm"))
+	      (match_operand:SWI48 2 "x86_64_immediate_operand" "e,e")))
 	  (plus:<DWI>
 	    (match_operand:<DWI> 6 "const_scalar_int_operand")
 	    (match_operator:<DWI> 4 "ix86_carry_flag_operator"
 	      [(match_dup 3) (const_int 0)]))))
-   (set (match_operand:SWI48 0 "nonimmediate_operand" "=rm")
+   (set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r")
 	(plus:SWI48 (plus:SWI48 (match_op_dup 5
 				 [(match_dup 3) (const_int 0)])
 				(match_dup 1))
 		    (match_dup 2)))]
-  "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)
+  "ix86_binary_operator_ok (PLUS, <MODE>mode, operands,
+			    ix86_can_use_ndd_p (PLUS))
    && CONST_INT_P (operands[2])
    /* Check that operands[6] is operands[2] zero extended from
       <MODE>mode to <DWI>mode.  */
@@ -8498,8 +8548,11 @@  (define_insn "*addcarry<mode>_1"
 	  && ((unsigned HOST_WIDE_INT) CONST_WIDE_INT_ELT (operands[6], 0)
 	      == UINTVAL (operands[2]))
 	  && CONST_WIDE_INT_ELT (operands[6], 1) == 0))"
-  "adc{<imodesuffix>}\t{%2, %0|%0, %2}"
-  [(set_attr "type" "alu")
+  "@
+  adc{<imodesuffix>}\t{%2, %0|%0, %2}
+  adc{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}"
+  [(set_attr "isa" "*,apx_ndd")
+   (set_attr "type" "alu")
    (set_attr "use_carry" "1")
    (set_attr "pent_pair" "pu")
    (set_attr "mode" "<MODE>")
@@ -9146,12 +9199,13 @@  (define_insn_and_split "*add<dwi>3_doubleword_cc_overflow_1"
   [(set (reg:CCC FLAGS_REG)
 	(compare:CCC
 	  (plus:<DWI>
-	    (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0")
-	    (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o"))
+	    (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,r")
+	    (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r<di>,o"))
 	  (match_dup 1)))
-   (set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r")
+   (set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,r,r")
 	(plus:<DWI> (match_dup 1) (match_dup 2)))]
-  "ix86_binary_operator_ok (PLUS, <DWI>mode, operands)"
+  "ix86_binary_operator_ok (PLUS, <DWI>mode, operands,
+			    ix86_can_use_ndd_p (PLUS))"
   "#"
   "&& reload_completed"
   [(parallel [(set (reg:CCC FLAGS_REG)
@@ -9180,6 +9234,8 @@  (define_insn_and_split "*add<dwi>3_doubleword_cc_overflow_1"
   split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], &operands[3]);
   if (operands[2] == const0_rtx)
     {
+      if (!rtx_equal_p (operands[0], operands[1]))
+	emit_move_insn (operands[0], operands[1]);
       emit_insn (gen_addcarry<mode>_0 (operands[3], operands[4], operands[5]));
       DONE;
     }
@@ -9188,7 +9244,8 @@  (define_insn_and_split "*add<dwi>3_doubleword_cc_overflow_1"
 					    operands[5], <MODE>mode);
   else
     operands[6] = gen_rtx_ZERO_EXTEND (<DWI>mode, operands[5]);
-})
+}
+[(set_attr "isa" "*,*,apx_ndd,apx_ndd")])
 
 ;; x == 0 with zero flag test can be done also as x < 1U with carry flag
 ;; test, where the latter is preferrable if we have some carry consuming
@@ -9203,7 +9260,8 @@  (define_insn_and_split "*add<mode>3_eq"
 	    (match_operand:SWI 1 "nonimmediate_operand"))
 	  (match_operand:SWI 2 "<general_operand>")))
    (clobber (reg:CC FLAGS_REG))]
-  "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)
+  "ix86_binary_operator_ok (PLUS, <MODE>mode, operands,
+			    ix86_can_use_ndd_p (PLUS))
    && ix86_pre_reload_split ()"
   "#"
   "&& 1"
@@ -9227,7 +9285,8 @@  (define_insn_and_split "*add<mode>3_ne"
   "CONST_INT_P (operands[2])
    && (<MODE>mode != DImode
        || INTVAL (operands[2]) != HOST_WIDE_INT_C (-0x80000000))
-   && ix86_binary_operator_ok (PLUS, <MODE>mode, operands)
+   && ix86_binary_operator_ok (PLUS, <MODE>mode, operands,
+			       ix86_can_use_ndd_p (PLUS))
    && ix86_pre_reload_split ()"
   "#"
   "&& 1"
diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-adc.c b/gcc/testsuite/gcc.target/i386/apx-ndd-adc.c
new file mode 100644
index 00000000000..9d5991457da
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/apx-ndd-adc.c
@@ -0,0 +1,15 @@ 
+/* { dg-do compile { target { int128 && { ! ia32 } } } } */
+/* { dg-options "-mapxf -O2" } */
+
+#include "pr91681-1.c"
+// *addti3_doubleword
+// *addti3_doubleword_zext
+// *adddi3_cc_overflow_1
+// *adddi3_carry
+
+int foo3 (int *a, int b) 
+{				 	  
+  int c = *a + b + (a > b); /* { dg-warning "comparison between pointer and integer" } */
+  return c;			 	  
+}			
+/* { dg-final { scan-assembler-not "xor" } } */