[llvm] [X86][CodeGen] Support lowering for NDD ADD/SUB/ADC/SBB/OR/XOR/NEG/NOT/INC/DEC/IMUL (PR #77564)

Shengchen Kan via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 10 19:40:29 PST 2024


https://github.com/KanRobert updated https://github.com/llvm/llvm-project/pull/77564

>From bf6d30e8220a42c6a18b644a2de17d110bb7af84 Mon Sep 17 00:00:00 2001
From: Shengchen Kan <shengchen.kan at intel.com>
Date: Wed, 3 Jan 2024 15:20:01 +0800
Subject: [PATCH 1/2] [X86][CodeGen] Support lowering for NDD
 ADD/SUB/ADC/SBB/OR/XOR/NEG/NOT/INC/DEC/IMUL

---
 llvm/lib/Target/X86/X86InstrArithmetic.td | 110 ++--
 llvm/lib/Target/X86/X86InstrCompiler.td   | 380 +++++++-------
 llvm/test/CodeGen/X86/apx/adc.ll          | 485 +++++++++++++++++
 llvm/test/CodeGen/X86/apx/add.ll          | 595 +++++++++++++++++++++
 llvm/test/CodeGen/X86/apx/dec.ll          | 137 +++++
 llvm/test/CodeGen/X86/apx/imul.ll         | 139 +++++
 llvm/test/CodeGen/X86/apx/inc.ll          | 193 +++++++
 llvm/test/CodeGen/X86/apx/neg.ll          | 233 +++++++++
 llvm/test/CodeGen/X86/apx/not.ll          | 137 +++++
 llvm/test/CodeGen/X86/apx/or.ll           | 593 +++++++++++++++++++++
 llvm/test/CodeGen/X86/apx/sbb.ll          | 433 +++++++++++++++
 llvm/test/CodeGen/X86/apx/sub.ll          | 609 ++++++++++++++++++++++
 llvm/test/CodeGen/X86/apx/xor.ll          | 545 +++++++++++++++++++
 13 files changed, 4378 insertions(+), 211 deletions(-)
 create mode 100644 llvm/test/CodeGen/X86/apx/adc.ll
 create mode 100644 llvm/test/CodeGen/X86/apx/add.ll
 create mode 100644 llvm/test/CodeGen/X86/apx/dec.ll
 create mode 100644 llvm/test/CodeGen/X86/apx/imul.ll
 create mode 100644 llvm/test/CodeGen/X86/apx/inc.ll
 create mode 100644 llvm/test/CodeGen/X86/apx/neg.ll
 create mode 100644 llvm/test/CodeGen/X86/apx/not.ll
 create mode 100644 llvm/test/CodeGen/X86/apx/or.ll
 create mode 100644 llvm/test/CodeGen/X86/apx/sbb.ll
 create mode 100644 llvm/test/CodeGen/X86/apx/sub.ll
 create mode 100644 llvm/test/CodeGen/X86/apx/xor.ll

diff --git a/llvm/lib/Target/X86/X86InstrArithmetic.td b/llvm/lib/Target/X86/X86InstrArithmetic.td
index 5cfa95e085e34a..d493e5db878267 100644
--- a/llvm/lib/Target/X86/X86InstrArithmetic.td
+++ b/llvm/lib/Target/X86/X86InstrArithmetic.td
@@ -1107,43 +1107,85 @@ def : Pat<(store (X86adc_flag GR64:$src, (loadi64 addr:$dst), EFLAGS),
 
 // Patterns for basic arithmetic ops with relocImm for the immediate field.
 multiclass ArithBinOp_RF_relocImm_Pats<SDNode OpNodeFlag, SDNode OpNode> {
-  def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2),
-            (!cast<Instruction>(NAME#"8ri") GR8:$src1, relocImm8_su:$src2)>;
-  def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2),
-            (!cast<Instruction>(NAME#"16ri") GR16:$src1, relocImm16_su:$src2)>;
-  def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2),
-            (!cast<Instruction>(NAME#"32ri") GR32:$src1, relocImm32_su:$src2)>;
-  def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2),
-            (!cast<Instruction>(NAME#"64ri32") GR64:$src1, i64relocImmSExt32_su:$src2)>;
-
-  def : Pat<(store (OpNode (load addr:$dst), relocImm8_su:$src), addr:$dst),
-            (!cast<Instruction>(NAME#"8mi") addr:$dst, relocImm8_su:$src)>;
-  def : Pat<(store (OpNode (load addr:$dst), relocImm16_su:$src), addr:$dst),
-            (!cast<Instruction>(NAME#"16mi") addr:$dst, relocImm16_su:$src)>;
-  def : Pat<(store (OpNode (load addr:$dst), relocImm32_su:$src), addr:$dst),
-            (!cast<Instruction>(NAME#"32mi") addr:$dst, relocImm32_su:$src)>;
-  def : Pat<(store (OpNode (load addr:$dst), i64relocImmSExt32_su:$src), addr:$dst),
-            (!cast<Instruction>(NAME#"64mi32") addr:$dst, i64relocImmSExt32_su:$src)>;
+  let Predicates = [NoNDD] in {
+    def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2),
+              (!cast<Instruction>(NAME#"8ri") GR8:$src1, relocImm8_su:$src2)>;
+    def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2),
+              (!cast<Instruction>(NAME#"16ri") GR16:$src1, relocImm16_su:$src2)>;
+    def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2),
+              (!cast<Instruction>(NAME#"32ri") GR32:$src1, relocImm32_su:$src2)>;
+    def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2),
+              (!cast<Instruction>(NAME#"64ri32") GR64:$src1, i64relocImmSExt32_su:$src2)>;
+
+    def : Pat<(store (OpNode (load addr:$dst), relocImm8_su:$src), addr:$dst),
+              (!cast<Instruction>(NAME#"8mi") addr:$dst, relocImm8_su:$src)>;
+    def : Pat<(store (OpNode (load addr:$dst), relocImm16_su:$src), addr:$dst),
+              (!cast<Instruction>(NAME#"16mi") addr:$dst, relocImm16_su:$src)>;
+    def : Pat<(store (OpNode (load addr:$dst), relocImm32_su:$src), addr:$dst),
+              (!cast<Instruction>(NAME#"32mi") addr:$dst, relocImm32_su:$src)>;
+    def : Pat<(store (OpNode (load addr:$dst), i64relocImmSExt32_su:$src), addr:$dst),
+              (!cast<Instruction>(NAME#"64mi32") addr:$dst, i64relocImmSExt32_su:$src)>;
+  }
+  let Predicates = [HasNDD] in {
+    def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2),
+	      (!cast<Instruction>(NAME#"8ri_ND") GR8:$src1, relocImm8_su:$src2)>;
+    def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2),
+	      (!cast<Instruction>(NAME#"16ri_ND") GR16:$src1, relocImm16_su:$src2)>;
+    def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2),
+	      (!cast<Instruction>(NAME#"32ri_ND") GR32:$src1, relocImm32_su:$src2)>;
+    def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2),
+	      (!cast<Instruction>(NAME#"64ri32_ND") GR64:$src1, i64relocImmSExt32_su:$src2)>;
+
+    def : Pat<(OpNode (load addr:$dst), relocImm8_su:$src),
+	      (!cast<Instruction>(NAME#"8mi_ND") addr:$dst, relocImm8_su:$src)>;
+    def : Pat<(OpNode (load addr:$dst), relocImm16_su:$src),
+	      (!cast<Instruction>(NAME#"16mi_ND") addr:$dst, relocImm16_su:$src)>;
+    def : Pat<(OpNode (load addr:$dst), relocImm32_su:$src),
+	      (!cast<Instruction>(NAME#"32mi_ND") addr:$dst, relocImm32_su:$src)>;
+    def : Pat<(OpNode (load addr:$dst), i64relocImmSExt32_su:$src),
+	      (!cast<Instruction>(NAME#"64mi32_ND") addr:$dst, i64relocImmSExt32_su:$src)>;
+  }
 }
 
 multiclass ArithBinOp_RFF_relocImm_Pats<SDNode OpNodeFlag> {
-  def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2, EFLAGS),
-            (!cast<Instruction>(NAME#"8ri") GR8:$src1, relocImm8_su:$src2)>;
-  def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2, EFLAGS),
-            (!cast<Instruction>(NAME#"16ri") GR16:$src1, relocImm16_su:$src2)>;
-  def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2, EFLAGS),
-            (!cast<Instruction>(NAME#"32ri") GR32:$src1, relocImm32_su:$src2)>;
-  def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2, EFLAGS),
-            (!cast<Instruction>(NAME#"64ri32") GR64:$src1, i64relocImmSExt32_su:$src2)>;
-
-  def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm8_su:$src, EFLAGS), addr:$dst),
-            (!cast<Instruction>(NAME#"8mi") addr:$dst, relocImm8_su:$src)>;
-  def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm16_su:$src, EFLAGS), addr:$dst),
-            (!cast<Instruction>(NAME#"16mi") addr:$dst, relocImm16_su:$src)>;
-  def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm32_su:$src, EFLAGS), addr:$dst),
-            (!cast<Instruction>(NAME#"32mi") addr:$dst, relocImm32_su:$src)>;
-  def : Pat<(store (OpNodeFlag (load addr:$dst), i64relocImmSExt32_su:$src, EFLAGS), addr:$dst),
-            (!cast<Instruction>(NAME#"64mi32") addr:$dst, i64relocImmSExt32_su:$src)>;
+  let Predicates = [NoNDD] in {
+    def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2, EFLAGS),
+              (!cast<Instruction>(NAME#"8ri") GR8:$src1, relocImm8_su:$src2)>;
+    def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2, EFLAGS),
+              (!cast<Instruction>(NAME#"16ri") GR16:$src1, relocImm16_su:$src2)>;
+    def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2, EFLAGS),
+              (!cast<Instruction>(NAME#"32ri") GR32:$src1, relocImm32_su:$src2)>;
+    def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2, EFLAGS),
+              (!cast<Instruction>(NAME#"64ri32") GR64:$src1, i64relocImmSExt32_su:$src2)>;
+
+    def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm8_su:$src, EFLAGS), addr:$dst),
+              (!cast<Instruction>(NAME#"8mi") addr:$dst, relocImm8_su:$src)>;
+    def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm16_su:$src, EFLAGS), addr:$dst),
+              (!cast<Instruction>(NAME#"16mi") addr:$dst, relocImm16_su:$src)>;
+    def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm32_su:$src, EFLAGS), addr:$dst),
+              (!cast<Instruction>(NAME#"32mi") addr:$dst, relocImm32_su:$src)>;
+    def : Pat<(store (OpNodeFlag (load addr:$dst), i64relocImmSExt32_su:$src, EFLAGS), addr:$dst),
+              (!cast<Instruction>(NAME#"64mi32") addr:$dst, i64relocImmSExt32_su:$src)>;
+  }
+  let Predicates = [HasNDD] in {
+    def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2, EFLAGS),
+              (!cast<Instruction>(NAME#"8ri_ND") GR8:$src1, relocImm8_su:$src2)>;
+    def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2, EFLAGS),
+              (!cast<Instruction>(NAME#"16ri_ND") GR16:$src1, relocImm16_su:$src2)>;
+    def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2, EFLAGS),
+              (!cast<Instruction>(NAME#"32ri_ND") GR32:$src1, relocImm32_su:$src2)>;
+    def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2, EFLAGS),
+              (!cast<Instruction>(NAME#"64ri32_ND") GR64:$src1, i64relocImmSExt32_su:$src2)>;
+
+    def : Pat<(OpNodeFlag (load addr:$dst), relocImm8_su:$src, EFLAGS),
+              (!cast<Instruction>(NAME#"8mi_ND") addr:$dst, relocImm8_su:$src)>;
+    def : Pat<(OpNodeFlag (load addr:$dst), relocImm16_su:$src, EFLAGS),
+              (!cast<Instruction>(NAME#"16mi_ND") addr:$dst, relocImm16_su:$src)>;
+    def : Pat<(OpNodeFlag (load addr:$dst), relocImm32_su:$src, EFLAGS),
+              (!cast<Instruction>(NAME#"32mi_ND") addr:$dst, relocImm32_su:$src)>;
+    def : Pat<(OpNodeFlag (load addr:$dst), i64relocImmSExt32_su:$src, EFLAGS),
+              (!cast<Instruction>(NAME#"64mi32_ND") addr:$dst, i64relocImmSExt32_su:$src)>;
+  }
 }
 
 multiclass ArithBinOp_F_relocImm_Pats<SDNode OpNodeFlag> {
diff --git a/llvm/lib/Target/X86/X86InstrCompiler.td b/llvm/lib/Target/X86/X86InstrCompiler.td
index c77c77ee4a3eeb..84457e4e161502 100644
--- a/llvm/lib/Target/X86/X86InstrCompiler.td
+++ b/llvm/lib/Target/X86/X86InstrCompiler.td
@@ -1550,13 +1550,24 @@ def : Pat<(X86add_flag_nocf GR64:$src1, 0x0000000080000000),
 
 // AddedComplexity is needed to give priority over i64immSExt8 and i64immSExt32.
 let AddedComplexity = 1 in {
-def : Pat<(and GR64:$src, i64immZExt32:$imm),
-          (SUBREG_TO_REG
-            (i64 0),
-            (AND32ri
-              (EXTRACT_SUBREG GR64:$src, sub_32bit),
-              (i32 (GetLo32XForm imm:$imm))),
-            sub_32bit)>;
+  let Predicates = [NoNDD] in {
+    def : Pat<(and GR64:$src, i64immZExt32:$imm),
+              (SUBREG_TO_REG
+                (i64 0),
+                (AND32ri
+                  (EXTRACT_SUBREG GR64:$src, sub_32bit),
+                  (i32 (GetLo32XForm imm:$imm))),
+                sub_32bit)>;
+  }
+  let Predicates = [HasNDD] in {
+    def : Pat<(and GR64:$src, i64immZExt32:$imm),
+              (SUBREG_TO_REG
+                (i64 0),
+                (AND32ri_ND
+                  (EXTRACT_SUBREG GR64:$src, sub_32bit),
+                  (i32 (GetLo32XForm imm:$imm))),
+                sub_32bit)>;
+  }
 } // AddedComplexity = 1
 
 
@@ -1762,10 +1773,18 @@ def : Pat<(X86xor_flag (i8 (trunc GR32:$src)),
 // where the least significant bit is not 0. However, the probability of this
 // happening is considered low enough that this is officially not a
 // "real problem".
-def : Pat<(shl GR8 :$src1, (i8 1)), (ADD8rr  GR8 :$src1, GR8 :$src1)>;
-def : Pat<(shl GR16:$src1, (i8 1)), (ADD16rr GR16:$src1, GR16:$src1)>;
-def : Pat<(shl GR32:$src1, (i8 1)), (ADD32rr GR32:$src1, GR32:$src1)>;
-def : Pat<(shl GR64:$src1, (i8 1)), (ADD64rr GR64:$src1, GR64:$src1)>;
+let Predicates = [HasNDD] in {
+  def : Pat<(shl GR8 :$src1, (i8 1)), (ADD8rr_ND  GR8 :$src1, GR8 :$src1)>;
+  def : Pat<(shl GR16:$src1, (i8 1)), (ADD16rr_ND GR16:$src1, GR16:$src1)>;
+  def : Pat<(shl GR32:$src1, (i8 1)), (ADD32rr_ND GR32:$src1, GR32:$src1)>;
+  def : Pat<(shl GR64:$src1, (i8 1)), (ADD64rr_ND GR64:$src1, GR64:$src1)>;
+}
+let Predicates = [NoNDD] in {
+  def : Pat<(shl GR8 :$src1, (i8 1)), (ADD8rr  GR8 :$src1, GR8 :$src1)>;
+  def : Pat<(shl GR16:$src1, (i8 1)), (ADD16rr GR16:$src1, GR16:$src1)>;
+  def : Pat<(shl GR32:$src1, (i8 1)), (ADD32rr GR32:$src1, GR32:$src1)>;
+  def : Pat<(shl GR64:$src1, (i8 1)), (ADD64rr GR64:$src1, GR64:$src1)>;
+}
 
 // Shift amount is implicitly masked.
 multiclass MaskedShiftAmountPats<SDNode frag, string name> {
@@ -1937,75 +1956,179 @@ defm : one_bit_patterns<GR64, i64, BTR64rr, BTS64rr, BTC64rr, shiftMask64>;
 // EFLAGS-defining Patterns
 //===----------------------------------------------------------------------===//
 
-// add reg, reg
-def : Pat<(add GR8 :$src1, GR8 :$src2), (ADD8rr  GR8 :$src1, GR8 :$src2)>;
-def : Pat<(add GR16:$src1, GR16:$src2), (ADD16rr GR16:$src1, GR16:$src2)>;
-def : Pat<(add GR32:$src1, GR32:$src2), (ADD32rr GR32:$src1, GR32:$src2)>;
-def : Pat<(add GR64:$src1, GR64:$src2), (ADD64rr GR64:$src1, GR64:$src2)>;
-
-// add reg, mem
-def : Pat<(add GR8:$src1, (loadi8 addr:$src2)),
-          (ADD8rm GR8:$src1, addr:$src2)>;
-def : Pat<(add GR16:$src1, (loadi16 addr:$src2)),
-          (ADD16rm GR16:$src1, addr:$src2)>;
-def : Pat<(add GR32:$src1, (loadi32 addr:$src2)),
-          (ADD32rm GR32:$src1, addr:$src2)>;
-def : Pat<(add GR64:$src1, (loadi64 addr:$src2)),
-          (ADD64rm GR64:$src1, addr:$src2)>;
-
-// add reg, imm
-def : Pat<(add GR8 :$src1, imm:$src2), (ADD8ri  GR8:$src1 , imm:$src2)>;
-def : Pat<(add GR16:$src1, imm:$src2), (ADD16ri GR16:$src1, imm:$src2)>;
-def : Pat<(add GR32:$src1, imm:$src2), (ADD32ri GR32:$src1, imm:$src2)>;
-def : Pat<(add GR64:$src1, i64immSExt32:$src2), (ADD64ri32 GR64:$src1, i64immSExt32:$src2)>;
-
-// sub reg, reg
-def : Pat<(sub GR8 :$src1, GR8 :$src2), (SUB8rr  GR8 :$src1, GR8 :$src2)>;
-def : Pat<(sub GR16:$src1, GR16:$src2), (SUB16rr GR16:$src1, GR16:$src2)>;
-def : Pat<(sub GR32:$src1, GR32:$src2), (SUB32rr GR32:$src1, GR32:$src2)>;
-def : Pat<(sub GR64:$src1, GR64:$src2), (SUB64rr GR64:$src1, GR64:$src2)>;
-
-// sub reg, mem
-def : Pat<(sub GR8:$src1, (loadi8 addr:$src2)),
-          (SUB8rm GR8:$src1, addr:$src2)>;
-def : Pat<(sub GR16:$src1, (loadi16 addr:$src2)),
-          (SUB16rm GR16:$src1, addr:$src2)>;
-def : Pat<(sub GR32:$src1, (loadi32 addr:$src2)),
-          (SUB32rm GR32:$src1, addr:$src2)>;
-def : Pat<(sub GR64:$src1, (loadi64 addr:$src2)),
-          (SUB64rm GR64:$src1, addr:$src2)>;
-
-// sub reg, imm
-def : Pat<(sub GR8:$src1, imm:$src2),
-          (SUB8ri GR8:$src1, imm:$src2)>;
-def : Pat<(sub GR16:$src1, imm:$src2),
-          (SUB16ri GR16:$src1, imm:$src2)>;
-def : Pat<(sub GR32:$src1, imm:$src2),
-          (SUB32ri GR32:$src1, imm:$src2)>;
-def : Pat<(sub GR64:$src1, i64immSExt32:$src2),
-          (SUB64ri32 GR64:$src1, i64immSExt32:$src2)>;
-
-// sub 0, reg
-def : Pat<(X86sub_flag 0, GR8 :$src), (NEG8r  GR8 :$src)>;
-def : Pat<(X86sub_flag 0, GR16:$src), (NEG16r GR16:$src)>;
-def : Pat<(X86sub_flag 0, GR32:$src), (NEG32r GR32:$src)>;
-def : Pat<(X86sub_flag 0, GR64:$src), (NEG64r GR64:$src)>;
-
-// mul reg, reg
-def : Pat<(mul GR16:$src1, GR16:$src2),
-          (IMUL16rr GR16:$src1, GR16:$src2)>;
-def : Pat<(mul GR32:$src1, GR32:$src2),
-          (IMUL32rr GR32:$src1, GR32:$src2)>;
-def : Pat<(mul GR64:$src1, GR64:$src2),
-          (IMUL64rr GR64:$src1, GR64:$src2)>;
-
-// mul reg, mem
-def : Pat<(mul GR16:$src1, (loadi16 addr:$src2)),
-          (IMUL16rm GR16:$src1, addr:$src2)>;
-def : Pat<(mul GR32:$src1, (loadi32 addr:$src2)),
-          (IMUL32rm GR32:$src1, addr:$src2)>;
-def : Pat<(mul GR64:$src1, (loadi64 addr:$src2)),
-          (IMUL64rm GR64:$src1, addr:$src2)>;
+multiclass EFLAGSDefiningPats<string suffix, Predicate p> {
+  let Predicates = [p] in {
+    // add reg, reg
+    def : Pat<(add GR8 :$src1, GR8 :$src2), (!cast<Instruction>(ADD8rr#suffix) GR8 :$src1, GR8 :$src2)>;
+    def : Pat<(add GR16:$src1, GR16:$src2), (!cast<Instruction>(ADD16rr#suffix) GR16:$src1, GR16:$src2)>;
+    def : Pat<(add GR32:$src1, GR32:$src2), (!cast<Instruction>(ADD32rr#suffix) GR32:$src1, GR32:$src2)>;
+    def : Pat<(add GR64:$src1, GR64:$src2), (!cast<Instruction>(ADD64rr#suffix) GR64:$src1, GR64:$src2)>;
+
+    // add reg, mem
+    def : Pat<(add GR8:$src1, (loadi8 addr:$src2)),
+              (!cast<Instruction>(ADD8rm#suffix) GR8:$src1, addr:$src2)>;
+    def : Pat<(add GR16:$src1, (loadi16 addr:$src2)),
+              (!cast<Instruction>(ADD16rm#suffix) GR16:$src1, addr:$src2)>;
+    def : Pat<(add GR32:$src1, (loadi32 addr:$src2)),
+              (!cast<Instruction>(ADD32rm#suffix) GR32:$src1, addr:$src2)>;
+    def : Pat<(add GR64:$src1, (loadi64 addr:$src2)),
+              (!cast<Instruction>(ADD64rm#suffix) GR64:$src1, addr:$src2)>;
+
+    // add reg, imm
+    def : Pat<(add GR8 :$src1, imm:$src2), (!cast<Instruction>(ADD8ri#suffix) GR8:$src1 , imm:$src2)>;
+    def : Pat<(add GR16:$src1, imm:$src2), (!cast<Instruction>(ADD16ri#suffix) GR16:$src1, imm:$src2)>;
+    def : Pat<(add GR32:$src1, imm:$src2), (!cast<Instruction>(ADD32ri#suffix) GR32:$src1, imm:$src2)>;
+    def : Pat<(add GR64:$src1, i64immSExt32:$src2), (!cast<Instruction>(ADD64ri32#suffix) GR64:$src1, i64immSExt32:$src2)>;
+
+    // sub reg, reg
+    def : Pat<(sub GR8 :$src1, GR8 :$src2), (!cast<Instruction>(SUB8rr#suffix)  GR8 :$src1, GR8 :$src2)>;
+    def : Pat<(sub GR16:$src1, GR16:$src2), (!cast<Instruction>(SUB16rr#suffix) GR16:$src1, GR16:$src2)>;
+    def : Pat<(sub GR32:$src1, GR32:$src2), (!cast<Instruction>(SUB32rr#suffix) GR32:$src1, GR32:$src2)>;
+    def : Pat<(sub GR64:$src1, GR64:$src2), (!cast<Instruction>(SUB64rr#suffix) GR64:$src1, GR64:$src2)>;
+
+    // sub reg, mem
+    def : Pat<(sub GR8:$src1, (loadi8 addr:$src2)),
+              (!cast<Instruction>(SUB8rm#suffix) GR8:$src1, addr:$src2)>;
+    def : Pat<(sub GR16:$src1, (loadi16 addr:$src2)),
+              (!cast<Instruction>(SUB16rm#suffix) GR16:$src1, addr:$src2)>;
+    def : Pat<(sub GR32:$src1, (loadi32 addr:$src2)),
+              (!cast<Instruction>(SUB32rm#suffix) GR32:$src1, addr:$src2)>;
+    def : Pat<(sub GR64:$src1, (loadi64 addr:$src2)),
+              (!cast<Instruction>(SUB64rm#suffix) GR64:$src1, addr:$src2)>;
+
+    // sub reg, imm
+    def : Pat<(sub GR8:$src1, imm:$src2),
+              (!cast<Instruction>(SUB8ri#suffix) GR8:$src1, imm:$src2)>;
+    def : Pat<(sub GR16:$src1, imm:$src2),
+              (!cast<Instruction>(SUB16ri#suffix) GR16:$src1, imm:$src2)>;
+    def : Pat<(sub GR32:$src1, imm:$src2),
+              (!cast<Instruction>(SUB32ri#suffix) GR32:$src1, imm:$src2)>;
+    def : Pat<(sub GR64:$src1, i64immSExt32:$src2),
+              (!cast<Instruction>(SUB64ri32#suffix) GR64:$src1, i64immSExt32:$src2)>;
+
+    // sub 0, reg
+    def : Pat<(X86sub_flag 0, GR8 :$src), (!cast<Instruction>(NEG8r#suffix)  GR8 :$src)>;
+    def : Pat<(X86sub_flag 0, GR16:$src), (!cast<Instruction>(NEG16r#suffix) GR16:$src)>;
+    def : Pat<(X86sub_flag 0, GR32:$src), (!cast<Instruction>(NEG32r#suffix) GR32:$src)>;
+    def : Pat<(X86sub_flag 0, GR64:$src), (!cast<Instruction>(NEG64r#suffix) GR64:$src)>;
+
+    // mul reg, reg
+    def : Pat<(mul GR16:$src1, GR16:$src2),
+              (!cast<Instruction>(IMUL16rr#suffix) GR16:$src1, GR16:$src2)>;
+    def : Pat<(mul GR32:$src1, GR32:$src2),
+              (!cast<Instruction>(IMUL32rr#suffix) GR32:$src1, GR32:$src2)>;
+    def : Pat<(mul GR64:$src1, GR64:$src2),
+              (!cast<Instruction>(IMUL64rr#suffix) GR64:$src1, GR64:$src2)>;
+
+    // mul reg, mem
+    def : Pat<(mul GR16:$src1, (loadi16 addr:$src2)),
+              (!cast<Instruction>(IMUL16rm#suffix) GR16:$src1, addr:$src2)>;
+    def : Pat<(mul GR32:$src1, (loadi32 addr:$src2)),
+              (!cast<Instruction>(IMUL32rm#suffix) GR32:$src1, addr:$src2)>;
+    def : Pat<(mul GR64:$src1, (loadi64 addr:$src2)),
+              (!cast<Instruction>(IMUL64rm#suffix) GR64:$src1, addr:$src2)>;
+
+    // or reg/reg.
+    def : Pat<(or GR8 :$src1, GR8 :$src2), (!cast<Instruction>(OR8rr#suffix)  GR8 :$src1, GR8 :$src2)>;
+    def : Pat<(or GR16:$src1, GR16:$src2), (!cast<Instruction>(OR16rr#suffix) GR16:$src1, GR16:$src2)>;
+    def : Pat<(or GR32:$src1, GR32:$src2), (!cast<Instruction>(OR32rr#suffix) GR32:$src1, GR32:$src2)>;
+    def : Pat<(or GR64:$src1, GR64:$src2), (!cast<Instruction>(OR64rr#suffix) GR64:$src1, GR64:$src2)>;
+
+    // or reg/mem
+    def : Pat<(or GR8:$src1, (loadi8 addr:$src2)),
+              (!cast<Instruction>(OR8rm#suffix) GR8:$src1, addr:$src2)>;
+    def : Pat<(or GR16:$src1, (loadi16 addr:$src2)),
+              (!cast<Instruction>(OR16rm#suffix) GR16:$src1, addr:$src2)>;
+    def : Pat<(or GR32:$src1, (loadi32 addr:$src2)),
+              (!cast<Instruction>(OR32rm#suffix) GR32:$src1, addr:$src2)>;
+    def : Pat<(or GR64:$src1, (loadi64 addr:$src2)),
+              (!cast<Instruction>(OR64rm#suffix) GR64:$src1, addr:$src2)>;
+
+    // or reg/imm
+    def : Pat<(or GR8:$src1 , imm:$src2), (!cast<Instruction>(OR8ri#suffix)  GR8 :$src1, imm:$src2)>;
+    def : Pat<(or GR16:$src1, imm:$src2), (!cast<Instruction>(OR16ri#suffix) GR16:$src1, imm:$src2)>;
+    def : Pat<(or GR32:$src1, imm:$src2), (!cast<Instruction>(OR32ri#suffix) GR32:$src1, imm:$src2)>;
+    def : Pat<(or GR64:$src1, i64immSExt32:$src2),
+              (!cast<Instruction>(OR64ri32#suffix) GR64:$src1, i64immSExt32:$src2)>;
+
+    // xor reg/reg
+    def : Pat<(xor GR8 :$src1, GR8 :$src2), (!cast<Instruction>(XOR8rr#suffix)  GR8 :$src1, GR8 :$src2)>;
+    def : Pat<(xor GR16:$src1, GR16:$src2), (!cast<Instruction>(XOR16rr#suffix) GR16:$src1, GR16:$src2)>;
+    def : Pat<(xor GR32:$src1, GR32:$src2), (!cast<Instruction>(XOR32rr#suffix) GR32:$src1, GR32:$src2)>;
+    def : Pat<(xor GR64:$src1, GR64:$src2), (!cast<Instruction>(XOR64rr#suffix) GR64:$src1, GR64:$src2)>;
+
+    // xor reg/mem
+    def : Pat<(xor GR8:$src1, (loadi8 addr:$src2)),
+              (!cast<Instruction>(XOR8rm#suffix) GR8:$src1, addr:$src2)>;
+    def : Pat<(xor GR16:$src1, (loadi16 addr:$src2)),
+              (!cast<Instruction>(XOR16rm#suffix) GR16:$src1, addr:$src2)>;
+    def : Pat<(xor GR32:$src1, (loadi32 addr:$src2)),
+              (!cast<Instruction>(XOR32rm#suffix) GR32:$src1, addr:$src2)>;
+    def : Pat<(xor GR64:$src1, (loadi64 addr:$src2)),
+              (!cast<Instruction>(XOR64rm#suffix) GR64:$src1, addr:$src2)>;
+
+    // xor reg/imm
+    def : Pat<(xor GR8:$src1, imm:$src2),
+              (!cast<Instruction>(XOR8ri#suffix) GR8:$src1, imm:$src2)>;
+    def : Pat<(xor GR16:$src1, imm:$src2),
+              (!cast<Instruction>(XOR16ri#suffix) GR16:$src1, imm:$src2)>;
+    def : Pat<(xor GR32:$src1, imm:$src2),
+              (!cast<Instruction>(XOR32ri#suffix) GR32:$src1, imm:$src2)>;
+    def : Pat<(xor GR64:$src1, i64immSExt32:$src2),
+              (!cast<Instruction>(XOR64ri32#suffix) GR64:$src1, i64immSExt32:$src2)>;
+
+    // and reg/reg
+    def : Pat<(and GR8 :$src1, GR8 :$src2), (!cast<Instruction>(AND8rr#suffix)  GR8 :$src1, GR8 :$src2)>;
+    def : Pat<(and GR16:$src1, GR16:$src2), (!cast<Instruction>(AND16rr#suffix) GR16:$src1, GR16:$src2)>;
+    def : Pat<(and GR32:$src1, GR32:$src2), (!cast<Instruction>(AND32rr#suffix) GR32:$src1, GR32:$src2)>;
+    def : Pat<(and GR64:$src1, GR64:$src2), (!cast<Instruction>(AND64rr#suffix) GR64:$src1, GR64:$src2)>;
+
+    // and reg/mem
+    def : Pat<(and GR8:$src1, (loadi8 addr:$src2)),
+              (!cast<Instruction>(AND8rm#suffix) GR8:$src1, addr:$src2)>;
+    def : Pat<(and GR16:$src1, (loadi16 addr:$src2)),
+              (!cast<Instruction>(AND16rm#suffix) GR16:$src1, addr:$src2)>;
+    def : Pat<(and GR32:$src1, (loadi32 addr:$src2)),
+              (!cast<Instruction>(AND32rm#suffix) GR32:$src1, addr:$src2)>;
+    def : Pat<(and GR64:$src1, (loadi64 addr:$src2)),
+              (!cast<Instruction>(AND64rm#suffix) GR64:$src1, addr:$src2)>;
+
+    // and reg/imm
+    def : Pat<(and GR8:$src1, imm:$src2),
+              (!cast<Instruction>(AND8ri#suffix) GR8:$src1, imm:$src2)>;
+    def : Pat<(and GR16:$src1, imm:$src2),
+              (!cast<Instruction>(AND16ri#suffix) GR16:$src1, imm:$src2)>;
+    def : Pat<(and GR32:$src1, imm:$src2),
+              (!cast<Instruction>(AND32ri#suffix) GR32:$src1, imm:$src2)>;
+    def : Pat<(and GR64:$src1, i64immSExt32:$src2),
+              (!cast<Instruction>(AND64ri32#suffix) GR64:$src1, i64immSExt32:$src2)>;
+  }
+
+  // Increment/Decrement reg.
+  // Do not make INC/DEC if it is slow
+  let Predicates = [UseIncDec, p] in {
+    def : Pat<(add GR8:$src, 1),   (!cast<Instruction>(INC8r#suffix) GR8:$src)>;
+    def : Pat<(add GR16:$src, 1),  (!cast<Instruction>(INC16r#suffix) GR16:$src)>;
+    def : Pat<(add GR32:$src, 1),  (!cast<Instruction>(INC32r#suffix) GR32:$src)>;
+    def : Pat<(add GR64:$src, 1),  (!cast<Instruction>(INC64r#suffix) GR64:$src)>;
+    def : Pat<(add GR8:$src, -1),  (!cast<Instruction>(DEC8r#suffix) GR8:$src)>;
+    def : Pat<(add GR16:$src, -1), (!cast<Instruction>(DEC16r#suffix) GR16:$src)>;
+    def : Pat<(add GR32:$src, -1), (!cast<Instruction>(DEC32r#suffix) GR32:$src)>;
+    def : Pat<(add GR64:$src, -1), (!cast<Instruction>(DEC64r#suffix) GR64:$src)>;
+
+    def : Pat<(X86add_flag_nocf GR8:$src, -1),  (!cast<Instruction>(DEC8r#suffix) GR8:$src)>;
+    def : Pat<(X86add_flag_nocf GR16:$src, -1), (!cast<Instruction>(DEC16r#suffix) GR16:$src)>;
+    def : Pat<(X86add_flag_nocf GR32:$src, -1), (!cast<Instruction>(DEC32r#suffix) GR32:$src)>;
+    def : Pat<(X86add_flag_nocf GR64:$src, -1), (!cast<Instruction>(DEC64r#suffix) GR64:$src)>;
+    def : Pat<(X86sub_flag_nocf GR8:$src, -1),  (!cast<Instruction>(INC8r#suffix) GR8:$src)>;
+    def : Pat<(X86sub_flag_nocf GR16:$src, -1), (!cast<Instruction>(INC16r#suffix) GR16:$src)>;
+    def : Pat<(X86sub_flag_nocf GR32:$src, -1), (!cast<Instruction>(INC32r#suffix) GR32:$src)>;
+    def : Pat<(X86sub_flag_nocf GR64:$src, -1), (!cast<Instruction>(INC64r#suffix) GR64:$src)>;
+  }
+}
+
+defm : EFLAGSDefiningPats<"", NoNDD>;
+defm : EFLAGSDefiningPats<"_ND", HasNDD>;
 
 // mul reg, imm
 def : Pat<(mul GR16:$src1, imm:$src2),
@@ -2023,103 +2146,6 @@ def : Pat<(mul (loadi32 addr:$src1), imm:$src2),
 def : Pat<(mul (loadi64 addr:$src1), i64immSExt32:$src2),
           (IMUL64rmi32 addr:$src1, i64immSExt32:$src2)>;
 
-// Increment/Decrement reg.
-// Do not make INC/DEC if it is slow
-let Predicates = [UseIncDec] in {
-  def : Pat<(add GR8:$src, 1),   (INC8r GR8:$src)>;
-  def : Pat<(add GR16:$src, 1),  (INC16r GR16:$src)>;
-  def : Pat<(add GR32:$src, 1),  (INC32r GR32:$src)>;
-  def : Pat<(add GR64:$src, 1),  (INC64r GR64:$src)>;
-  def : Pat<(add GR8:$src, -1),  (DEC8r GR8:$src)>;
-  def : Pat<(add GR16:$src, -1), (DEC16r GR16:$src)>;
-  def : Pat<(add GR32:$src, -1), (DEC32r GR32:$src)>;
-  def : Pat<(add GR64:$src, -1), (DEC64r GR64:$src)>;
-
-  def : Pat<(X86add_flag_nocf GR8:$src, -1),  (DEC8r GR8:$src)>;
-  def : Pat<(X86add_flag_nocf GR16:$src, -1), (DEC16r GR16:$src)>;
-  def : Pat<(X86add_flag_nocf GR32:$src, -1), (DEC32r GR32:$src)>;
-  def : Pat<(X86add_flag_nocf GR64:$src, -1), (DEC64r GR64:$src)>;
-  def : Pat<(X86sub_flag_nocf GR8:$src, -1),  (INC8r GR8:$src)>;
-  def : Pat<(X86sub_flag_nocf GR16:$src, -1), (INC16r GR16:$src)>;
-  def : Pat<(X86sub_flag_nocf GR32:$src, -1), (INC32r GR32:$src)>;
-  def : Pat<(X86sub_flag_nocf GR64:$src, -1), (INC64r GR64:$src)>;
-}
-
-// or reg/reg.
-def : Pat<(or GR8 :$src1, GR8 :$src2), (OR8rr  GR8 :$src1, GR8 :$src2)>;
-def : Pat<(or GR16:$src1, GR16:$src2), (OR16rr GR16:$src1, GR16:$src2)>;
-def : Pat<(or GR32:$src1, GR32:$src2), (OR32rr GR32:$src1, GR32:$src2)>;
-def : Pat<(or GR64:$src1, GR64:$src2), (OR64rr GR64:$src1, GR64:$src2)>;
-
-// or reg/mem
-def : Pat<(or GR8:$src1, (loadi8 addr:$src2)),
-          (OR8rm GR8:$src1, addr:$src2)>;
-def : Pat<(or GR16:$src1, (loadi16 addr:$src2)),
-          (OR16rm GR16:$src1, addr:$src2)>;
-def : Pat<(or GR32:$src1, (loadi32 addr:$src2)),
-          (OR32rm GR32:$src1, addr:$src2)>;
-def : Pat<(or GR64:$src1, (loadi64 addr:$src2)),
-          (OR64rm GR64:$src1, addr:$src2)>;
-
-// or reg/imm
-def : Pat<(or GR8:$src1 , imm:$src2), (OR8ri  GR8 :$src1, imm:$src2)>;
-def : Pat<(or GR16:$src1, imm:$src2), (OR16ri GR16:$src1, imm:$src2)>;
-def : Pat<(or GR32:$src1, imm:$src2), (OR32ri GR32:$src1, imm:$src2)>;
-def : Pat<(or GR64:$src1, i64immSExt32:$src2),
-          (OR64ri32 GR64:$src1, i64immSExt32:$src2)>;
-
-// xor reg/reg
-def : Pat<(xor GR8 :$src1, GR8 :$src2), (XOR8rr  GR8 :$src1, GR8 :$src2)>;
-def : Pat<(xor GR16:$src1, GR16:$src2), (XOR16rr GR16:$src1, GR16:$src2)>;
-def : Pat<(xor GR32:$src1, GR32:$src2), (XOR32rr GR32:$src1, GR32:$src2)>;
-def : Pat<(xor GR64:$src1, GR64:$src2), (XOR64rr GR64:$src1, GR64:$src2)>;
-
-// xor reg/mem
-def : Pat<(xor GR8:$src1, (loadi8 addr:$src2)),
-          (XOR8rm GR8:$src1, addr:$src2)>;
-def : Pat<(xor GR16:$src1, (loadi16 addr:$src2)),
-          (XOR16rm GR16:$src1, addr:$src2)>;
-def : Pat<(xor GR32:$src1, (loadi32 addr:$src2)),
-          (XOR32rm GR32:$src1, addr:$src2)>;
-def : Pat<(xor GR64:$src1, (loadi64 addr:$src2)),
-          (XOR64rm GR64:$src1, addr:$src2)>;
-
-// xor reg/imm
-def : Pat<(xor GR8:$src1, imm:$src2),
-          (XOR8ri GR8:$src1, imm:$src2)>;
-def : Pat<(xor GR16:$src1, imm:$src2),
-          (XOR16ri GR16:$src1, imm:$src2)>;
-def : Pat<(xor GR32:$src1, imm:$src2),
-          (XOR32ri GR32:$src1, imm:$src2)>;
-def : Pat<(xor GR64:$src1, i64immSExt32:$src2),
-          (XOR64ri32 GR64:$src1, i64immSExt32:$src2)>;
-
-// and reg/reg
-def : Pat<(and GR8 :$src1, GR8 :$src2), (AND8rr  GR8 :$src1, GR8 :$src2)>;
-def : Pat<(and GR16:$src1, GR16:$src2), (AND16rr GR16:$src1, GR16:$src2)>;
-def : Pat<(and GR32:$src1, GR32:$src2), (AND32rr GR32:$src1, GR32:$src2)>;
-def : Pat<(and GR64:$src1, GR64:$src2), (AND64rr GR64:$src1, GR64:$src2)>;
-
-// and reg/mem
-def : Pat<(and GR8:$src1, (loadi8 addr:$src2)),
-          (AND8rm GR8:$src1, addr:$src2)>;
-def : Pat<(and GR16:$src1, (loadi16 addr:$src2)),
-          (AND16rm GR16:$src1, addr:$src2)>;
-def : Pat<(and GR32:$src1, (loadi32 addr:$src2)),
-          (AND32rm GR32:$src1, addr:$src2)>;
-def : Pat<(and GR64:$src1, (loadi64 addr:$src2)),
-          (AND64rm GR64:$src1, addr:$src2)>;
-
-// and reg/imm
-def : Pat<(and GR8:$src1, imm:$src2),
-          (AND8ri GR8:$src1, imm:$src2)>;
-def : Pat<(and GR16:$src1, imm:$src2),
-          (AND16ri GR16:$src1, imm:$src2)>;
-def : Pat<(and GR32:$src1, imm:$src2),
-          (AND32ri GR32:$src1, imm:$src2)>;
-def : Pat<(and GR64:$src1, i64immSExt32:$src2),
-          (AND64ri32 GR64:$src1, i64immSExt32:$src2)>;
-
 // Bit scan instruction patterns to match explicit zero-undef behavior.
 def : Pat<(cttz_zero_undef GR16:$src), (BSF16rr GR16:$src)>;
 def : Pat<(cttz_zero_undef GR32:$src), (BSF32rr GR32:$src)>;
diff --git a/llvm/test/CodeGen/X86/apx/adc.ll b/llvm/test/CodeGen/X86/apx/adc.ll
new file mode 100644
index 00000000000000..8e2df5c2772019
--- /dev/null
+++ b/llvm/test/CodeGen/X86/apx/adc.ll
@@ -0,0 +1,485 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs | FileCheck %s
+
+define i8 @adc8rr(i8 %a, i8 %b, i8 %x, i8 %y) nounwind {
+; CHECK-LABEL: adc8rr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subb %dl, %cl, %al
+; CHECK-NEXT:    adcb %sil, %dil, %al
+; CHECK-NEXT:    retq
+  %s = add i8 %a, %b
+  %k = icmp ugt i8 %x, %y
+  %z = zext i1 %k to i8
+  %r = add i8 %s, %z
+  ret i8 %r
+}
+
+define i16 @adc16rr(i16 %a, i16 %b, i16 %x, i16 %y) nounwind {
+; CHECK-LABEL: adc16rr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subw %dx, %cx, %ax
+; CHECK-NEXT:    adcw %si, %di, %ax
+; CHECK-NEXT:    retq
+  %s = add i16 %a, %b
+  %k = icmp ugt i16 %x, %y
+  %z = zext i1 %k to i16
+  %r = add i16 %s, %z
+  ret i16 %r
+}
+
+define i32 @adc32rr(i32 %a, i32 %b, i32 %x, i32 %y) nounwind {
+; CHECK-LABEL: adc32rr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subl %edx, %ecx, %eax
+; CHECK-NEXT:    adcl %esi, %edi, %eax
+; CHECK-NEXT:    retq
+  %s = add i32 %a, %b
+  %k = icmp ugt i32 %x, %y
+  %z = zext i1 %k to i32
+  %r = add i32 %s, %z
+  ret i32 %r
+}
+
+define i64 @adc64rr(i64 %a, i64 %b, i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: adc64rr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subq %rdx, %rcx, %rax
+; CHECK-NEXT:    adcq %rsi, %rdi, %rax
+; CHECK-NEXT:    retq
+  %s = add i64 %a, %b
+  %k = icmp ugt i64 %x, %y
+  %z = zext i1 %k to i64
+  %r = add i64 %s, %z
+  ret i64 %r
+}
+
+define i8 @adc8rm(i8 %a, ptr %ptr, i8 %x, i8 %y) nounwind {
+; CHECK-LABEL: adc8rm:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subb %dl, %cl, %al
+; CHECK-NEXT:    adcb (%rsi), %dil, %al
+; CHECK-NEXT:    retq
+  %b = load i8, ptr %ptr
+  %s = add i8 %a, %b
+  %k = icmp ugt i8 %x, %y
+  %z = zext i1 %k to i8
+  %r = add i8 %s, %z
+  ret i8 %r
+}
+
+define i16 @adc16rm(i16 %a, ptr %ptr, i16 %x, i16 %y) nounwind {
+; CHECK-LABEL: adc16rm:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subw %dx, %cx, %ax
+; CHECK-NEXT:    adcw (%rsi), %di, %ax
+; CHECK-NEXT:    retq
+  %b = load i16, ptr %ptr
+  %s = add i16 %a, %b
+  %k = icmp ugt i16 %x, %y
+  %z = zext i1 %k to i16
+  %r = add i16 %s, %z
+  ret i16 %r
+}
+
+define i32 @adc32rm(i32 %a, ptr %ptr, i32 %x, i32 %y) nounwind {
+; CHECK-LABEL: adc32rm:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subl %edx, %ecx, %eax
+; CHECK-NEXT:    adcl (%rsi), %edi, %eax
+; CHECK-NEXT:    retq
+  %b = load i32, ptr %ptr
+  %s = add i32 %a, %b
+  %k = icmp ugt i32 %x, %y
+  %z = zext i1 %k to i32
+  %r = add i32 %s, %z
+  ret i32 %r
+}
+
+define i64 @adc64rm(i64 %a, ptr %ptr, i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: adc64rm:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subq %rdx, %rcx, %rax
+; CHECK-NEXT:    adcq (%rsi), %rdi, %rax
+; CHECK-NEXT:    retq
+  %b = load i64, ptr %ptr
+  %s = add i64 %a, %b
+  %k = icmp ugt i64 %x, %y
+  %z = zext i1 %k to i64
+  %r = add i64 %s, %z
+  ret i64 %r
+}
+
+define i16 @adc16ri8(i16 %a, i16 %x, i16 %y) nounwind {
+; CHECK-LABEL: adc16ri8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subw %si, %dx, %ax
+; CHECK-NEXT:    adcw $0, %di, %ax
+; CHECK-NEXT:    addl $123, %eax, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+  %s = add i16 %a, 123
+  %k = icmp ugt i16 %x, %y
+  %z = zext i1 %k to i16
+  %r = add i16 %s, %z
+  ret i16 %r
+}
+
+define i32 @adc32ri8(i32 %a, i32 %x, i32 %y) nounwind {
+; CHECK-LABEL: adc32ri8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subl %esi, %edx, %eax
+; CHECK-NEXT:    adcl $123, %edi, %eax
+; CHECK-NEXT:    retq
+  %s = add i32 %a, 123
+  %k = icmp ugt i32 %x, %y
+  %z = zext i1 %k to i32
+  %r = add i32 %s, %z
+  ret i32 %r
+}
+
+define i64 @adc64ri8(i64 %a, i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: adc64ri8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subq %rsi, %rdx, %rax
+; CHECK-NEXT:    adcq $123, %rdi, %rax
+; CHECK-NEXT:    retq
+  %s = add i64 %a, 123
+  %k = icmp ugt i64 %x, %y
+  %z = zext i1 %k to i64
+  %r = add i64 %s, %z
+  ret i64 %r
+}
+
+define i8 @adc8ri(i8 %a, i8 %x, i8 %y) nounwind {
+; CHECK-LABEL: adc8ri:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subb %sil, %dl, %al
+; CHECK-NEXT:    adcb $123, %dil, %al
+; CHECK-NEXT:    retq
+  %s = add i8 %a, 123
+  %k = icmp ugt i8 %x, %y
+  %z = zext i1 %k to i8
+  %r = add i8 %s, %z
+  ret i8 %r
+}
+
+define i16 @adc16ri(i16 %a, i16 %x, i16 %y) nounwind {
+; CHECK-LABEL: adc16ri:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subw %si, %dx, %ax
+; CHECK-NEXT:    adcw $0, %di, %ax
+; CHECK-NEXT:    addl $1234, %eax, %eax # imm = 0x4D2
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+  %s = add i16 %a, 1234
+  %k = icmp ugt i16 %x, %y
+  %z = zext i1 %k to i16
+  %r = add i16 %s, %z
+  ret i16 %r
+}
+
+define i32 @adc32ri(i32 %a, i32 %x, i32 %y) nounwind {
+; CHECK-LABEL: adc32ri:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subl %esi, %edx, %eax
+; CHECK-NEXT:    adcl $123456, %edi, %eax # imm = 0x1E240
+; CHECK-NEXT:    retq
+  %s = add i32 %a, 123456
+  %k = icmp ugt i32 %x, %y
+  %z = zext i1 %k to i32
+  %r = add i32 %s, %z
+  ret i32 %r
+}
+
+define i64 @adc64ri(i64 %a, i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: adc64ri:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subq %rsi, %rdx, %rax
+; CHECK-NEXT:    adcq $123456, %rdi, %rax # imm = 0x1E240
+; CHECK-NEXT:    retq
+  %s = add i64 %a, 123456
+  %k = icmp ugt i64 %x, %y
+  %z = zext i1 %k to i64
+  %r = add i64 %s, %z
+  ret i64 %r
+}
+
+define i8 @adc8mr(i8 %a, ptr %ptr, i8 %x, i8 %y) nounwind {
+; CHECK-LABEL: adc8mr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subb %dl, %cl, %al
+; CHECK-NEXT:    adcb %dil, (%rsi), %al
+; CHECK-NEXT:    retq
+  %b = load i8, ptr %ptr
+  %s = add i8 %b, %a
+  %k = icmp ugt i8 %x, %y
+  %z = zext i1 %k to i8
+  %r = add i8 %s, %z
+  ret i8 %r
+}
+
+define i16 @adc16mr(i16 %a, ptr %ptr, i16 %x, i16 %y) nounwind {
+; CHECK-LABEL: adc16mr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subw %dx, %cx, %ax
+; CHECK-NEXT:    adcw %di, (%rsi), %ax
+; CHECK-NEXT:    retq
+  %b = load i16, ptr %ptr
+  %s = add i16 %b, %a
+  %k = icmp ugt i16 %x, %y
+  %z = zext i1 %k to i16
+  %r = add i16 %s, %z
+  ret i16 %r
+}
+
+define i32 @adc32mr(i32 %a, ptr %ptr, i32 %x, i32 %y) nounwind {
+; CHECK-LABEL: adc32mr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subl %edx, %ecx, %eax
+; CHECK-NEXT:    adcl %edi, (%rsi), %eax
+; CHECK-NEXT:    retq
+  %b = load i32, ptr %ptr
+  %s = add i32 %b, %a
+  %k = icmp ugt i32 %x, %y
+  %z = zext i1 %k to i32
+  %r = add i32 %s, %z
+  ret i32 %r
+}
+
+define i64 @adc64mr(i64 %a, ptr %ptr, i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: adc64mr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subq %rdx, %rcx, %rax
+; CHECK-NEXT:    adcq %rdi, (%rsi), %rax
+; CHECK-NEXT:    retq
+  %b = load i64, ptr %ptr
+  %s = add i64 %b, %a
+  %k = icmp ugt i64 %x, %y
+  %z = zext i1 %k to i64
+  %r = add i64 %s, %z
+  ret i64 %r
+}
+
+define i16 @adc16mi8(ptr %ptr, i16 %x, i16 %y) nounwind {
+; CHECK-LABEL: adc16mi8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subw %si, %dx, %ax
+; CHECK-NEXT:    adcw $0, (%rdi), %ax
+; CHECK-NEXT:    addl $123, %eax, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+  %a = load i16, ptr %ptr
+  %s = add i16 %a, 123
+  %k = icmp ugt i16 %x, %y
+  %z = zext i1 %k to i16
+  %r = add i16 %s, %z
+  ret i16 %r
+}
+
+define i32 @adc32mi8(ptr %ptr, i32 %x, i32 %y) nounwind {
+; CHECK-LABEL: adc32mi8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subl %esi, %edx, %eax
+; CHECK-NEXT:    adcl $123, (%rdi), %eax
+; CHECK-NEXT:    retq
+  %a = load i32, ptr %ptr
+  %s = add i32 %a, 123
+  %k = icmp ugt i32 %x, %y
+  %z = zext i1 %k to i32
+  %r = add i32 %s, %z
+  ret i32 %r
+}
+
+define i64 @adc64mi8(ptr %ptr, i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: adc64mi8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subq %rsi, %rdx, %rax
+; CHECK-NEXT:    adcq $123, (%rdi), %rax
+; CHECK-NEXT:    retq
+  %a = load i64, ptr %ptr
+  %s = add i64 %a, 123
+  %k = icmp ugt i64 %x, %y
+  %z = zext i1 %k to i64
+  %r = add i64 %s, %z
+  ret i64 %r
+}
+
+define i8 @adc8mi(ptr %ptr, i8 %x, i8 %y) nounwind {
+; CHECK-LABEL: adc8mi:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subb %sil, %dl, %al
+; CHECK-NEXT:    adcb $123, (%rdi), %al
+; CHECK-NEXT:    retq
+  %a = load i8, ptr %ptr
+  %s = add i8 %a, 123
+  %k = icmp ugt i8 %x, %y
+  %z = zext i1 %k to i8
+  %r = add i8 %s, %z
+  ret i8 %r
+}
+
+define i16 @adc16mi(ptr %ptr, i16 %x, i16 %y) nounwind {
+; CHECK-LABEL: adc16mi:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subw %si, %dx, %ax
+; CHECK-NEXT:    adcw $0, (%rdi), %ax
+; CHECK-NEXT:    addl $1234, %eax, %eax # imm = 0x4D2
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+  %a = load i16, ptr %ptr
+  %s = add i16 %a, 1234
+  %k = icmp ugt i16 %x, %y
+  %z = zext i1 %k to i16
+  %r = add i16 %s, %z
+  ret i16 %r
+}
+
+define i32 @adc32mi(ptr %ptr, i32 %x, i32 %y) nounwind {
+; CHECK-LABEL: adc32mi:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subl %esi, %edx, %eax
+; CHECK-NEXT:    adcl $123456, (%rdi), %eax # imm = 0x1E240
+; CHECK-NEXT:    retq
+  %a = load i32, ptr %ptr
+  %s = add i32 %a, 123456
+  %k = icmp ugt i32 %x, %y
+  %z = zext i1 %k to i32
+  %r = add i32 %s, %z
+  ret i32 %r
+}
+
+define i64 @adc64mi(ptr %ptr, i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: adc64mi:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subq %rsi, %rdx, %rax
+; CHECK-NEXT:    adcq $123456, (%rdi), %rax # imm = 0x1E240
+; CHECK-NEXT:    retq
+  %a = load i64, ptr %ptr
+  %s = add i64 %a, 123456
+  %k = icmp ugt i64 %x, %y
+  %z = zext i1 %k to i64
+  %r = add i64 %s, %z
+  ret i64 %r
+}
+
+define void @adc8mr_legacy(i8 %a, ptr %ptr, i8 %x, i8 %y) nounwind {
+; CHECK-LABEL: adc8mr_legacy:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subb %dl, %cl, %al
+; CHECK-NEXT:    adcb %dil, (%rsi)
+; CHECK-NEXT:    retq
+  %b = load i8, ptr %ptr
+  %s = add i8 %b, %a
+  %k = icmp ugt i8 %x, %y
+  %z = zext i1 %k to i8
+  %r = add i8 %s, %z
+  store i8 %r, ptr %ptr
+  ret void
+}
+
+define void @adc16mr_legacy(i16 %a, ptr %ptr, i16 %x, i16 %y) nounwind {
+; CHECK-LABEL: adc16mr_legacy:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subw %dx, %cx, %ax
+; CHECK-NEXT:    adcw %di, (%rsi)
+; CHECK-NEXT:    retq
+  %b = load i16, ptr %ptr
+  %s = add i16 %b, %a
+  %k = icmp ugt i16 %x, %y
+  %z = zext i1 %k to i16
+  %r = add i16 %s, %z
+  store i16 %r, ptr %ptr
+  ret void
+}
+
+define void @adc32mr_legacy(i32 %a, ptr %ptr, i32 %x, i32 %y) nounwind {
+; CHECK-LABEL: adc32mr_legacy:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subl %edx, %ecx, %eax
+; CHECK-NEXT:    adcl %edi, (%rsi)
+; CHECK-NEXT:    retq
+  %b = load i32, ptr %ptr
+  %s = add i32 %b, %a
+  %k = icmp ugt i32 %x, %y
+  %z = zext i1 %k to i32
+  %r = add i32 %s, %z
+  store i32 %r, ptr %ptr
+  ret void
+}
+
+define void @adc64mr_legacy(i64 %a, ptr %ptr, i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: adc64mr_legacy:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subq %rdx, %rcx, %rax
+; CHECK-NEXT:    adcq %rdi, (%rsi)
+; CHECK-NEXT:    retq
+  %b = load i64, ptr %ptr
+  %s = add i64 %b, %a
+  %k = icmp ugt i64 %x, %y
+  %z = zext i1 %k to i64
+  %r = add i64 %s, %z
+  store i64 %r, ptr %ptr
+  ret void
+}
+
+define void @adc8mi_legacy(ptr %ptr, i8 %x, i8 %y) nounwind {
+; CHECK-LABEL: adc8mi_legacy:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subb %sil, %dl, %al
+; CHECK-NEXT:    adcb $123, (%rdi)
+; CHECK-NEXT:    retq
+  %a = load i8, ptr %ptr
+  %s = add i8 %a, 123
+  %k = icmp ugt i8 %x, %y
+  %z = zext i1 %k to i8
+  %r = add i8 %s, %z
+  store i8 %r, ptr %ptr
+  ret void
+}
+
+define void @adc16mi_legacy(ptr %ptr, i16 %x, i16 %y) nounwind {
+; CHECK-LABEL: adc16mi_legacy:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subw %si, %dx, %ax
+; CHECK-NEXT:    adcw $0, (%rdi), %ax
+; CHECK-NEXT:    addl $1234, %eax, %eax # imm = 0x4D2
+; CHECK-NEXT:    movw %ax, (%rdi)
+; CHECK-NEXT:    retq
+  %a = load i16, ptr %ptr
+  %s = add i16 %a, 1234
+  %k = icmp ugt i16 %x, %y
+  %z = zext i1 %k to i16
+  %r = add i16 %s, %z
+  store i16 %r, ptr %ptr
+  ret void
+}
+
+define void @adc32mi_legacy(ptr %ptr, i32 %x, i32 %y) nounwind {
+; CHECK-LABEL: adc32mi_legacy:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subl %esi, %edx, %eax
+; CHECK-NEXT:    adcl $123456, (%rdi) # imm = 0x1E240
+; CHECK-NEXT:    retq
+  %a = load i32, ptr %ptr
+  %s = add i32 %a, 123456
+  %k = icmp ugt i32 %x, %y
+  %z = zext i1 %k to i32
+  %r = add i32 %s, %z
+  store i32 %r, ptr %ptr
+  ret void
+}
+
+define void @adc64mi_legacy(ptr %ptr, i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: adc64mi_legacy:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subq %rsi, %rdx, %rax
+; CHECK-NEXT:    adcq $123456, (%rdi) # imm = 0x1E240
+; CHECK-NEXT:    retq
+  %a = load i64, ptr %ptr
+  %s = add i64 %a, 123456
+  %k = icmp ugt i64 %x, %y
+  %z = zext i1 %k to i64
+  %r = add i64 %s, %z
+  store i64 %r, ptr %ptr
+  ret void
+}
diff --git a/llvm/test/CodeGen/X86/apx/add.ll b/llvm/test/CodeGen/X86/apx/add.ll
new file mode 100644
index 00000000000000..7502cde2df3cef
--- /dev/null
+++ b/llvm/test/CodeGen/X86/apx/add.ll
@@ -0,0 +1,595 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs | FileCheck %s
+
+define i8 @add8rr(i8 noundef %a, i8 noundef %b) {
+; CHECK-LABEL: add8rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addb %sil, %dil, %al
+; CHECK-NEXT:    retq
+entry:
+    %add = add i8 %a, %b
+    ret i8 %add
+}
+
+define i16 @add16rr(i16 noundef %a, i16 noundef %b) {
+; CHECK-LABEL: add16rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl %esi, %edi, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %add = add i16 %a, %b
+    ret i16 %add
+}
+
+define i32 @add32rr(i32 noundef %a, i32 noundef %b) {
+; CHECK-LABEL: add32rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl %esi, %edi, %eax
+; CHECK-NEXT:    retq
+entry:
+    %add = add i32 %a, %b
+    ret i32 %add
+}
+
+define i64 @add64rr(i64 noundef %a, i64 noundef %b) {
+; CHECK-LABEL: add64rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addq %rsi, %rdi, %rax
+; CHECK-NEXT:    retq
+entry:
+    %add = add i64 %a, %b
+    ret i64 %add
+}
+
+define i8 @add8rm(i8 noundef %a, ptr %ptr) {
+; CHECK-LABEL: add8rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addb (%rsi), %dil, %al
+; CHECK-NEXT:    retq
+entry:
+    %b = load i8, ptr %ptr
+    %add = add i8 %a, %b
+    ret i8 %add
+}
+
+define i16 @add16rm(i16 noundef %a, ptr %ptr) {
+; CHECK-LABEL: add16rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addw (%rsi), %di, %ax
+; CHECK-NEXT:    retq
+entry:
+    %b = load i16, ptr %ptr
+    %add = add i16 %a, %b
+    ret i16 %add
+}
+
+define i32 @add32rm(i32 noundef %a, ptr %ptr) {
+; CHECK-LABEL: add32rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl (%rsi), %edi, %eax
+; CHECK-NEXT:    retq
+entry:
+    %b = load i32, ptr %ptr
+    %add = add i32 %a, %b
+    ret i32 %add
+}
+
+define i64 @add64rm(i64 noundef %a, ptr %ptr) {
+; CHECK-LABEL: add64rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addq (%rsi), %rdi, %rax
+; CHECK-NEXT:    retq
+entry:
+    %b = load i64, ptr %ptr
+    %add = add i64 %a, %b
+    ret i64 %add
+}
+
+define i16 @add16ri8(i16 noundef %a) {
+; CHECK-LABEL: add16ri8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl $123, %edi, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %add = add i16 %a, 123
+    ret i16 %add
+}
+
+define i32 @add32ri8(i32 noundef %a) {
+; CHECK-LABEL: add32ri8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl $123, %edi, %eax
+; CHECK-NEXT:    retq
+entry:
+    %add = add i32 %a, 123
+    ret i32 %add
+}
+
+define i64 @add64ri8(i64 noundef %a) {
+; CHECK-LABEL: add64ri8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addq $123, %rdi, %rax
+; CHECK-NEXT:    retq
+entry:
+    %add = add i64 %a, 123
+    ret i64 %add
+}
+
+define i8 @add8ri(i8 noundef %a) {
+; CHECK-LABEL: add8ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addb $123, %dil, %al
+; CHECK-NEXT:    retq
+entry:
+    %add = add i8 %a, 123
+    ret i8 %add
+}
+
+define i16 @add16ri(i16 noundef %a) {
+; CHECK-LABEL: add16ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl $1234, %edi, %eax # imm = 0x4D2
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %add = add i16 %a, 1234
+    ret i16 %add
+}
+
+define i32 @add32ri(i32 noundef %a) {
+; CHECK-LABEL: add32ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl $123456, %edi, %eax # imm = 0x1E240
+; CHECK-NEXT:    retq
+entry:
+    %add = add i32 %a, 123456
+    ret i32 %add
+}
+
+define i64 @add64ri(i64 noundef %a) {
+; CHECK-LABEL: add64ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addq $123456, %rdi, %rax # imm = 0x1E240
+; CHECK-NEXT:    retq
+entry:
+    %add = add i64 %a, 123456
+    ret i64 %add
+}
+
+define i8 @add8mr(ptr %a, i8 noundef %b) {
+; CHECK-LABEL: add8mr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addb %sil, (%rdi), %al
+; CHECK-NEXT:    retq
+entry:
+  %t= load i8, ptr %a
+  %add = add nsw i8 %t, %b
+  ret i8 %add
+}
+
+define i16 @add16mr(ptr %a, i16 noundef %b) {
+; CHECK-LABEL: add16mr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addw %si, (%rdi), %ax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i16, ptr %a
+  %add = add nsw i16 %t, %b
+  ret i16 %add
+}
+
+define i32 @add32mr(ptr %a, i32 noundef %b) {
+; CHECK-LABEL: add32mr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl %esi, (%rdi), %eax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i32, ptr %a
+  %add = add nsw i32 %t, %b
+  ret i32 %add
+}
+
+define i64 @add64mr(ptr %a, i64 noundef %b) {
+; CHECK-LABEL: add64mr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addq %rsi, (%rdi), %rax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i64, ptr %a
+  %add = add nsw i64 %t, %b
+  ret i64 %add
+}
+
+define i16 @add16mi8(ptr %a) {
+; CHECK-LABEL: add16mi8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    movzwl (%rdi), %eax
+; CHECK-NEXT:    addl $123, %eax, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i16, ptr %a
+  %add = add nsw i16 %t, 123
+  ret i16 %add
+}
+
+define i32 @add32mi8(ptr %a) {
+; CHECK-LABEL: add32mi8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl $123, (%rdi), %eax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i32, ptr %a
+  %add = add nsw i32 %t, 123
+  ret i32 %add
+}
+
+define i64 @add64mi8(ptr %a) {
+; CHECK-LABEL: add64mi8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addq $123, (%rdi), %rax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i64, ptr %a
+  %add = add nsw i64 %t, 123
+  ret i64 %add
+}
+
+define i8 @add8mi(ptr %a) {
+; CHECK-LABEL: add8mi:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addb $123, (%rdi), %al
+; CHECK-NEXT:    retq
+entry:
+  %t= load i8, ptr %a
+  %add = add nsw i8 %t, 123
+  ret i8 %add
+}
+
+define i16 @add16mi(ptr %a) {
+; CHECK-LABEL: add16mi:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    movzwl (%rdi), %eax
+; CHECK-NEXT:    addl $1234, %eax, %eax # imm = 0x4D2
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i16, ptr %a
+  %add = add nsw i16 %t, 1234
+  ret i16 %add
+}
+
+define i32 @add32mi(ptr %a) {
+; CHECK-LABEL: add32mi:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl $123456, (%rdi), %eax # imm = 0x1E240
+; CHECK-NEXT:    retq
+entry:
+  %t= load i32, ptr %a
+  %add = add nsw i32 %t, 123456
+  ret i32 %add
+}
+
+define i64 @add64mi(ptr %a) {
+; CHECK-LABEL: add64mi:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addq $123456, (%rdi), %rax # imm = 0x1E240
+; CHECK-NEXT:    retq
+entry:
+  %t= load i64, ptr %a
+  %add = add nsw i64 %t, 123456
+  ret i64 %add
+}
+
+declare i8 @llvm.uadd.sat.i8(i8, i8)
+declare i16 @llvm.uadd.sat.i16(i16, i16)
+declare i32 @llvm.uadd.sat.i32(i32, i32)
+declare i64 @llvm.uadd.sat.i64(i64, i64)
+
+define i8 @addflag8rr(i8 noundef %a, i8 noundef %b) {
+; CHECK-LABEL: addflag8rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addb %sil, %dil, %al
+; CHECK-NEXT:    movzbl %al, %ecx
+; CHECK-NEXT:    movl $255, %eax
+; CHECK-NEXT:    cmovael %ecx, %eax
+; CHECK-NEXT:    # kill: def $al killed $al killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %add = call i8 @llvm.uadd.sat.i8(i8 %a, i8 %b)
+    ret i8 %add
+}
+
+define i16 @addflag16rr(i16 noundef %a, i16 noundef %b) {
+; CHECK-LABEL: addflag16rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addw %si, %di, %cx
+; CHECK-NEXT:    movl $65535, %eax # imm = 0xFFFF
+; CHECK-NEXT:    cmovael %ecx, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %add = call i16 @llvm.uadd.sat.i16(i16 %a, i16 %b)
+    ret i16 %add
+}
+
+define i32 @addflag32rr(i32 noundef %a, i32 noundef %b) {
+; CHECK-LABEL: addflag32rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl %esi, %edi, %ecx
+; CHECK-NEXT:    movl $-1, %eax
+; CHECK-NEXT:    cmovael %ecx, %eax
+; CHECK-NEXT:    retq
+entry:
+    %add = call i32 @llvm.uadd.sat.i32(i32 %a, i32 %b)
+    ret i32 %add
+}
+
+define i64 @addflag64rr(i64 noundef %a, i64 noundef %b) {
+; CHECK-LABEL: addflag64rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addq %rsi, %rdi, %rcx
+; CHECK-NEXT:    movq $-1, %rax
+; CHECK-NEXT:    cmovaeq %rcx, %rax
+; CHECK-NEXT:    retq
+entry:
+    %add = call i64 @llvm.uadd.sat.i64(i64 %a, i64 %b)
+    ret i64 %add
+}
+
+define i8 @addflag8rm(i8 noundef %a, ptr %b) {
+; CHECK-LABEL: addflag8rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addb (%rsi), %dil, %al
+; CHECK-NEXT:    movzbl %al, %ecx
+; CHECK-NEXT:    movl $255, %eax
+; CHECK-NEXT:    cmovael %ecx, %eax
+; CHECK-NEXT:    # kill: def $al killed $al killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %t = load i8, ptr %b
+    %add = call i8 @llvm.uadd.sat.i8(i8 %a, i8 %t)
+    ret i8 %add
+}
+
+define i16 @addflag16rm(i16 noundef %a, ptr %b) {
+; CHECK-LABEL: addflag16rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addw (%rsi), %di, %cx
+; CHECK-NEXT:    movl $65535, %eax # imm = 0xFFFF
+; CHECK-NEXT:    cmovael %ecx, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %t = load i16, ptr %b
+    %add = call i16 @llvm.uadd.sat.i16(i16 %a, i16 %t)
+    ret i16 %add
+}
+
+define i32 @addflag32rm(i32 noundef %a, ptr %b) {
+; CHECK-LABEL: addflag32rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl (%rsi), %edi, %ecx
+; CHECK-NEXT:    movl $-1, %eax
+; CHECK-NEXT:    cmovael %ecx, %eax
+; CHECK-NEXT:    retq
+entry:
+    %t = load i32, ptr %b
+    %add = call i32 @llvm.uadd.sat.i32(i32 %a, i32 %t)
+    ret i32 %add
+}
+
+define i64 @addflag64rm(i64 noundef %a, ptr %b) {
+; CHECK-LABEL: addflag64rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addq (%rsi), %rdi, %rcx
+; CHECK-NEXT:    movq $-1, %rax
+; CHECK-NEXT:    cmovaeq %rcx, %rax
+; CHECK-NEXT:    retq
+entry:
+    %t = load i64, ptr %b
+    %add = call i64 @llvm.uadd.sat.i64(i64 %a, i64 %t)
+    ret i64 %add
+}
+
+define i16 @addflag16ri8(i16 noundef %a) {
+; CHECK-LABEL: addflag16ri8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addw $123, %di, %cx
+; CHECK-NEXT:    movl $65535, %eax # imm = 0xFFFF
+; CHECK-NEXT:    cmovael %ecx, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %add = call i16 @llvm.uadd.sat.i16(i16 %a, i16 123)
+    ret i16 %add
+}
+
+define i32 @addflag32ri8(i32 noundef %a) {
+; CHECK-LABEL: addflag32ri8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl $123, %edi, %ecx
+; CHECK-NEXT:    movl $-1, %eax
+; CHECK-NEXT:    cmovael %ecx, %eax
+; CHECK-NEXT:    retq
+entry:
+    %add = call i32 @llvm.uadd.sat.i32(i32 %a, i32 123)
+    ret i32 %add
+}
+
+define i64 @addflag64ri8(i64 noundef %a) {
+; CHECK-LABEL: addflag64ri8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addq $123, %rdi, %rcx
+; CHECK-NEXT:    movq $-1, %rax
+; CHECK-NEXT:    cmovaeq %rcx, %rax
+; CHECK-NEXT:    retq
+entry:
+    %add = call i64 @llvm.uadd.sat.i64(i64 %a, i64 123)
+    ret i64 %add
+}
+
+define i8 @addflag8ri(i8 noundef %a) {
+; CHECK-LABEL: addflag8ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addb $123, %dil, %al
+; CHECK-NEXT:    movzbl %al, %ecx
+; CHECK-NEXT:    movl $255, %eax
+; CHECK-NEXT:    cmovael %ecx, %eax
+; CHECK-NEXT:    # kill: def $al killed $al killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %add = call i8 @llvm.uadd.sat.i8(i8 %a, i8 123)
+    ret i8 %add
+}
+
+define i16 @addflag16ri(i16 noundef %a) {
+; CHECK-LABEL: addflag16ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addw $1234, %di, %cx # imm = 0x4D2
+; CHECK-NEXT:    movl $65535, %eax # imm = 0xFFFF
+; CHECK-NEXT:    cmovael %ecx, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %add = call i16 @llvm.uadd.sat.i16(i16 %a, i16 1234)
+    ret i16 %add
+}
+
+define i32 @addflag32ri(i32 noundef %a) {
+; CHECK-LABEL: addflag32ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl $123456, %edi, %ecx # imm = 0x1E240
+; CHECK-NEXT:    movl $-1, %eax
+; CHECK-NEXT:    cmovael %ecx, %eax
+; CHECK-NEXT:    retq
+entry:
+    %add = call i32 @llvm.uadd.sat.i32(i32 %a, i32 123456)
+    ret i32 %add
+}
+
+define i64 @addflag64ri(i64 noundef %a) {
+; CHECK-LABEL: addflag64ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addq $123456, %rdi, %rcx # imm = 0x1E240
+; CHECK-NEXT:    movq $-1, %rax
+; CHECK-NEXT:    cmovaeq %rcx, %rax
+; CHECK-NEXT:    retq
+entry:
+    %add = call i64 @llvm.uadd.sat.i64(i64 %a, i64 123456)
+    ret i64 %add
+}
+
+ at val = external dso_local global i16, align 4
+
+define i1 @add64ri_reloc(i16 %k) {
+; CHECK-LABEL: add64ri_reloc:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
+; CHECK-NEXT:    movswq %di, %rax
+; CHECK-NEXT:    addq %rax, %rax, %rax
+; CHECK-NEXT:    addq $val, %rax, %rax
+; CHECK-NEXT:    setne %al
+; CHECK-NEXT:    retq
+  %g = getelementptr inbounds i16, ptr @val, i16 %k
+  %cmp = icmp ne ptr %g, null
+  ret i1 %cmp
+}
+
+define void @add8mr_legacy(ptr %a, i8 noundef %b) {
+; CHECK-LABEL: add8mr_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addb %sil, (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %t= load i8, ptr %a
+  %add = add i8 %t, %b
+  store i8 %add, ptr %a
+  ret void
+}
+
+define void @add16mr_legacy(ptr %a, i16 noundef %b) {
+; CHECK-LABEL: add16mr_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addw %si, (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %t= load i16, ptr %a
+  %add = add i16 %t, %b
+  store i16 %add, ptr %a
+  ret void
+}
+
+define void @add32mr_legacy(ptr %a, i32 noundef %b) {
+; CHECK-LABEL: add32mr_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl %esi, (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %t= load i32, ptr %a
+  %add = add i32 %t, %b
+  store i32 %add, ptr %a
+  ret void
+}
+
+define void @add64mr_legacy(ptr %a, i64 noundef %b) {
+; CHECK-LABEL: add64mr_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addq %rsi, (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %t= load i64, ptr %a
+  %add = add i64 %t, %b
+  store i64 %add, ptr %a
+  ret void
+}
+
+define void @add8mi_legacy(ptr %a) {
+; CHECK-LABEL: add8mi_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addb $123, (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %t= load i8, ptr %a
+  %add = add nsw i8 %t, 123
+  store i8 %add, ptr %a
+  ret void
+}
+
+define void @add16mi_legacy(ptr %a) {
+; CHECK-LABEL: add16mi_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addw $1234, (%rdi) # imm = 0x4D2
+; CHECK-NEXT:    retq
+entry:
+  %t= load i16, ptr %a
+  %add = add nsw i16 %t, 1234
+  store i16 %add, ptr %a
+  ret void
+}
+
+define void @add32mi_legacy(ptr %a) {
+; CHECK-LABEL: add32mi_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl $123456, (%rdi) # imm = 0x1E240
+; CHECK-NEXT:    retq
+entry:
+  %t= load i32, ptr %a
+  %add = add nsw i32 %t, 123456
+  store i32 %add, ptr %a
+  ret void
+}
+
+define void @add64mi_legacy(ptr %a) {
+; CHECK-LABEL: add64mi_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addq $123456, (%rdi) # imm = 0x1E240
+; CHECK-NEXT:    retq
+entry:
+  %t= load i64, ptr %a
+  %add = add nsw i64 %t, 123456
+  store i64 %add, ptr %a
+  ret void
+}
diff --git a/llvm/test/CodeGen/X86/apx/dec.ll b/llvm/test/CodeGen/X86/apx/dec.ll
new file mode 100644
index 00000000000000..d79f1f5886bad6
--- /dev/null
+++ b/llvm/test/CodeGen/X86/apx/dec.ll
@@ -0,0 +1,137 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs | FileCheck %s
+
+define i8 @dec8r(i8 noundef %a) {
+; CHECK-LABEL: dec8r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    decb %dil, %al
+; CHECK-NEXT:    retq
+entry:
+  %dec = sub i8 %a, 1
+  ret i8 %dec
+}
+
+define i16 @dec16r(i16 noundef %a) {
+; CHECK-LABEL: dec16r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    decl %edi, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+  %dec = sub i16 %a, 1
+  ret i16 %dec
+}
+
+define i32 @dec32r(i32 noundef %a) {
+; CHECK-LABEL: dec32r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    decl %edi, %eax
+; CHECK-NEXT:    retq
+entry:
+  %dec = sub i32 %a, 1
+  ret i32 %dec
+}
+
+define i64 @dec64r(i64 noundef %a) {
+; CHECK-LABEL: dec64r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    decq %rdi, %rax
+; CHECK-NEXT:    retq
+entry:
+  %dec = sub i64 %a, 1
+  ret i64 %dec
+}
+
+define i8 @dec8m(ptr %ptr) {
+; CHECK-LABEL: dec8m:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    decb (%rdi), %al
+; CHECK-NEXT:    retq
+entry:
+  %a = load i8, ptr %ptr
+  %dec = sub i8 %a, 1
+  ret i8 %dec
+}
+
+define i16 @dec16m(ptr %ptr) {
+; CHECK-LABEL: dec16m:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    movzwl (%rdi), %eax
+; CHECK-NEXT:    decl %eax, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+  %a = load i16, ptr %ptr
+  %dec = sub i16 %a, 1
+  ret i16 %dec
+}
+
+define i32 @dec32m(ptr %ptr) {
+; CHECK-LABEL: dec32m:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    decl (%rdi), %eax
+; CHECK-NEXT:    retq
+entry:
+  %a = load i32, ptr %ptr
+  %dec = sub i32 %a, 1
+  ret i32 %dec
+}
+
+define i64 @dec64m(ptr %ptr) {
+; CHECK-LABEL: dec64m:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    decq (%rdi), %rax
+; CHECK-NEXT:    retq
+entry:
+  %a = load i64, ptr %ptr
+  %dec = sub i64 %a, 1
+  ret i64 %dec
+}
+
+define void @dec8m_legacy(ptr %ptr) {
+; CHECK-LABEL: dec8m_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    decb (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %a = load i8, ptr %ptr
+  %dec = sub i8 %a, 1
+  store i8 %dec, ptr %ptr
+  ret void
+}
+
+define void @dec16m_legacy(ptr %ptr) {
+; CHECK-LABEL: dec16m_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    decw (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %a = load i16, ptr %ptr
+  %dec = sub i16 %a, 1
+  store i16 %dec, ptr %ptr
+  ret void
+}
+
+define void @dec32m_legacy(ptr %ptr) {
+; CHECK-LABEL: dec32m_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    decl (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %a = load i32, ptr %ptr
+  %dec = sub i32 %a, 1
+  store i32 %dec, ptr %ptr
+  ret void
+}
+
+define void @dec64m_legacy(ptr %ptr) {
+; CHECK-LABEL: dec64m_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    decq (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %a = load i64, ptr %ptr
+  %dec = sub i64 %a, 1
+  store i64 %dec, ptr %ptr
+  ret void
+}
diff --git a/llvm/test/CodeGen/X86/apx/imul.ll b/llvm/test/CodeGen/X86/apx/imul.ll
new file mode 100644
index 00000000000000..2963a6477be4c1
--- /dev/null
+++ b/llvm/test/CodeGen/X86/apx/imul.ll
@@ -0,0 +1,139 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs | FileCheck %s
+
+define i16 @mul16rr(i16 noundef %a, i16 noundef %b) {
+; CHECK-LABEL: mul16rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    imull %esi, %edi, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+  %mul = mul i16 %a, %b
+  ret i16 %mul
+}
+
+define i32 @mul32rr(i32 noundef %a, i32 noundef %b) {
+; CHECK-LABEL: mul32rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    imull %esi, %edi, %eax
+; CHECK-NEXT:    retq
+entry:
+  %mul = mul i32 %a, %b
+  ret i32 %mul
+}
+
+define i64 @mul64rr(i64 noundef %a, i64 noundef %b) {
+; CHECK-LABEL: mul64rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    imulq %rsi, %rdi, %rax
+; CHECK-NEXT:    retq
+entry:
+  %mul = mul i64 %a, %b
+  ret i64 %mul
+}
+
+define i16 @smul16rr(i16 noundef %a, i16 noundef %b) {
+; CHECK-LABEL: smul16rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    imulw %si, %di, %ax
+; CHECK-NEXT:    retq
+entry:
+  %t = call {i16, i1} @llvm.smul.with.overflow.i16(i16 %a, i16 %b)
+  %mul = extractvalue {i16, i1} %t, 0
+  ret i16 %mul
+}
+
+define i32 @smul32rr(i32 noundef %a, i32 noundef %b) {
+; CHECK-LABEL: smul32rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    imull %esi, %edi, %eax
+; CHECK-NEXT:    retq
+entry:
+  %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %a, i32 %b)
+  %mul = extractvalue {i32, i1} %t, 0
+  ret i32 %mul
+}
+
+define i64 @smul64rr(i64 noundef %a, i64 noundef %b) {
+; CHECK-LABEL: smul64rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    imulq %rsi, %rdi, %rax
+; CHECK-NEXT:    retq
+entry:
+  %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %a, i64 %b)
+  %mul = extractvalue {i64, i1} %t, 0
+  ret i64 %mul
+}
+
+define i16 @mul16rm(i16 noundef %a, ptr %ptr) {
+; CHECK-LABEL: mul16rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    imulw (%rsi), %di, %ax
+; CHECK-NEXT:    retq
+entry:
+  %b = load i16, ptr %ptr
+  %mul = mul i16 %a, %b
+  ret i16 %mul
+}
+
+define i32 @mul32rm(i32 noundef %a, ptr %ptr) {
+; CHECK-LABEL: mul32rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    imull (%rsi), %edi, %eax
+; CHECK-NEXT:    retq
+entry:
+  %b = load i32, ptr %ptr
+  %mul = mul i32 %a, %b
+  ret i32 %mul
+}
+
+define i64 @mul64rm(i64 noundef %a, ptr %ptr) {
+; CHECK-LABEL: mul64rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    imulq (%rsi), %rdi, %rax
+; CHECK-NEXT:    retq
+entry:
+  %b = load i64, ptr %ptr
+  %mul = mul i64 %a, %b
+  ret i64 %mul
+}
+
+define i16 @smul16rm(i16 noundef %a, ptr %ptr) {
+; CHECK-LABEL: smul16rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    imulw (%rsi), %di, %ax
+; CHECK-NEXT:    retq
+entry:
+  %b = load i16, ptr %ptr
+  %t = call {i16, i1} @llvm.smul.with.overflow.i16(i16 %a, i16 %b)
+  %mul = extractvalue {i16, i1} %t, 0
+  ret i16 %mul
+}
+
+define i32 @smul32rm(i32 noundef %a, ptr %ptr) {
+; CHECK-LABEL: smul32rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    imull (%rsi), %edi, %eax
+; CHECK-NEXT:    retq
+entry:
+  %b = load i32, ptr %ptr
+  %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %a, i32 %b)
+  %mul = extractvalue {i32, i1} %t, 0
+  ret i32 %mul
+}
+
+define i64 @smul64rm(i64 noundef %a, ptr %ptr) {
+; CHECK-LABEL: smul64rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    imulq (%rsi), %rdi, %rax
+; CHECK-NEXT:    retq
+entry:
+  %b = load i64, ptr %ptr
+  %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %a, i64 %b)
+  %mul = extractvalue {i64, i1} %t, 0
+  ret i64 %mul
+}
+
+declare { i16, i1 } @llvm.smul.with.overflow.i16(i16, i16) nounwind readnone
+declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32) nounwind readnone
+declare { i64, i1 } @llvm.smul.with.overflow.i64(i64, i64) nounwind readnone
diff --git a/llvm/test/CodeGen/X86/apx/inc.ll b/llvm/test/CodeGen/X86/apx/inc.ll
new file mode 100644
index 00000000000000..28dbf75f5ada5c
--- /dev/null
+++ b/llvm/test/CodeGen/X86/apx/inc.ll
@@ -0,0 +1,193 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs | FileCheck %s
+
+define i8 @inc8r(i8 noundef %a) {
+; CHECK-LABEL: inc8r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    incb %dil, %al
+; CHECK-NEXT:    retq
+entry:
+  %inc = add i8 %a, 1
+  ret i8 %inc
+}
+
+define i16 @inc16r(i16 noundef %a) {
+; CHECK-LABEL: inc16r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    incl %edi, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+  %inc = add i16 %a, 1
+  ret i16 %inc
+}
+
+define i32 @inc32r(i32 noundef %a) {
+; CHECK-LABEL: inc32r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    incl %edi, %eax
+; CHECK-NEXT:    retq
+entry:
+  %inc = add i32 %a, 1
+  ret i32 %inc
+}
+
+define i64 @inc64r(i64 noundef %a) {
+; CHECK-LABEL: inc64r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    incq %rdi, %rax
+; CHECK-NEXT:    retq
+entry:
+  %inc = add i64 %a, 1
+  ret i64 %inc
+}
+
+define i8 @inc8m(ptr %ptr) {
+; CHECK-LABEL: inc8m:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    incb (%rdi), %al
+; CHECK-NEXT:    retq
+entry:
+  %a = load i8, ptr %ptr
+  %inc = add i8 %a, 1
+  ret i8 %inc
+}
+
+define i16 @inc16m(ptr %ptr) {
+; CHECK-LABEL: inc16m:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    movzwl (%rdi), %eax
+; CHECK-NEXT:    incl %eax, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+  %a = load i16, ptr %ptr
+  %inc = add i16 %a, 1
+  ret i16 %inc
+}
+
+define i32 @inc32m(ptr %ptr) {
+; CHECK-LABEL: inc32m:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    incl (%rdi), %eax
+; CHECK-NEXT:    retq
+entry:
+  %a = load i32, ptr %ptr
+  %inc = add i32 %a, 1
+  ret i32 %inc
+}
+
+define i64 @inc64m(ptr %ptr) {
+; CHECK-LABEL: inc64m:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    incq (%rdi), %rax
+; CHECK-NEXT:    retq
+entry:
+  %a = load i64, ptr %ptr
+  %inc = add i64 %a, 1
+  ret i64 %inc
+}
+
+define i8 @uinc8r(i8 noundef %a) {
+; CHECK-LABEL: uinc8r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    incb %dil, %al
+; CHECK-NEXT:    movzbl %al, %ecx
+; CHECK-NEXT:    movl $255, %eax
+; CHECK-NEXT:    cmovnel %ecx, %eax
+; CHECK-NEXT:    # kill: def $al killed $al killed $eax
+; CHECK-NEXT:    retq
+entry:
+  %inc = call i8 @llvm.uadd.sat.i8(i8 %a, i8 1)
+  ret i8 %inc
+}
+
+define i16 @uinc16r(i16 noundef %a) {
+; CHECK-LABEL: uinc16r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    incw %di, %cx
+; CHECK-NEXT:    movl $65535, %eax # imm = 0xFFFF
+; CHECK-NEXT:    cmovnel %ecx, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+  %inc = call i16 @llvm.uadd.sat.i16(i16 %a, i16 1)
+  ret i16 %inc
+}
+
+define i32 @uinc32r(i32 noundef %a) {
+; CHECK-LABEL: uinc32r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    incl %edi, %ecx
+; CHECK-NEXT:    movl $-1, %eax
+; CHECK-NEXT:    cmovnel %ecx, %eax
+; CHECK-NEXT:    retq
+entry:
+  %inc = call i32 @llvm.uadd.sat.i32(i32 %a, i32 1)
+  ret i32 %inc
+}
+
+define i64 @uinc64r(i64 noundef %a) {
+; CHECK-LABEL: uinc64r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    incq %rdi, %rcx
+; CHECK-NEXT:    movq $-1, %rax
+; CHECK-NEXT:    cmovneq %rcx, %rax
+; CHECK-NEXT:    retq
+entry:
+  %inc = call i64 @llvm.uadd.sat.i64(i64 %a, i64 1)
+  ret i64 %inc
+}
+
+declare i8 @llvm.uadd.sat.i8(i8, i8)
+declare i16 @llvm.uadd.sat.i16(i16, i16)
+declare i32 @llvm.uadd.sat.i32(i32, i32)
+declare i64 @llvm.uadd.sat.i64(i64, i64)
+
+define void @inc8m_legacy(ptr %ptr) {
+; CHECK-LABEL: inc8m_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    incb (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %a = load i8, ptr %ptr
+  %inc = add i8 %a, 1
+  store i8 %inc, ptr %ptr
+  ret void
+}
+
+define void @inc16m_legacy(ptr %ptr) {
+; CHECK-LABEL: inc16m_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    incw (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %a = load i16, ptr %ptr
+  %inc = add i16 %a, 1
+  store i16 %inc, ptr %ptr
+  ret void
+}
+
+define void @inc32m_legacy(ptr %ptr) {
+; CHECK-LABEL: inc32m_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    incl (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %a = load i32, ptr %ptr
+  %inc = add i32 %a, 1
+  store i32 %inc, ptr %ptr
+  ret void
+}
+
+define void @inc64m_legacy(ptr %ptr) {
+; CHECK-LABEL: inc64m_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    incq (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %a = load i64, ptr %ptr
+  %inc = add i64 %a, 1
+  store i64 %inc, ptr %ptr
+  ret void
+}
diff --git a/llvm/test/CodeGen/X86/apx/neg.ll b/llvm/test/CodeGen/X86/apx/neg.ll
new file mode 100644
index 00000000000000..c1c53fbdaebd82
--- /dev/null
+++ b/llvm/test/CodeGen/X86/apx/neg.ll
@@ -0,0 +1,233 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs | FileCheck %s
+
+define i8 @neg8r(i8 noundef %a) {
+; CHECK-LABEL: neg8r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    negb %dil, %al
+; CHECK-NEXT:    retq
+entry:
+  %neg = sub i8 0, %a
+  ret i8 %neg
+}
+
+define i16 @neg16r(i16 noundef %a) {
+; CHECK-LABEL: neg16r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    negl %edi, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+  %neg = sub i16 0, %a
+  ret i16 %neg
+}
+
+define i32 @neg32r(i32 noundef %a) {
+; CHECK-LABEL: neg32r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    negl %edi, %eax
+; CHECK-NEXT:    retq
+entry:
+  %neg = sub i32 0, %a
+  ret i32 %neg
+}
+
+define i64 @neg64r(i64 noundef %a) {
+; CHECK-LABEL: neg64r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    negq %rdi, %rax
+; CHECK-NEXT:    retq
+entry:
+  %neg = sub i64 0, %a
+  ret i64 %neg
+}
+
+define i8 @neg8m(ptr %ptr) {
+; CHECK-LABEL: neg8m:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    negb (%rdi), %al
+; CHECK-NEXT:    retq
+entry:
+  %a = load i8, ptr %ptr
+  %neg = sub i8 0, %a
+  ret i8 %neg
+}
+
+define i16 @neg16m(ptr %ptr) {
+; CHECK-LABEL: neg16m:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    negw (%rdi), %ax
+; CHECK-NEXT:    retq
+entry:
+  %a = load i16, ptr %ptr
+  %neg = sub i16 0, %a
+  ret i16 %neg
+}
+
+define i32 @neg32m(ptr %ptr) {
+; CHECK-LABEL: neg32m:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    negl (%rdi), %eax
+; CHECK-NEXT:    retq
+entry:
+  %a = load i32, ptr %ptr
+  %neg = sub i32 0, %a
+  ret i32 %neg
+}
+
+define i64 @neg64m(ptr %ptr) {
+; CHECK-LABEL: neg64m:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    negq (%rdi), %rax
+; CHECK-NEXT:    retq
+entry:
+  %a = load i64, ptr %ptr
+  %neg = sub i64 0, %a
+  ret i64 %neg
+}
+
+define i8 @uneg8r(i8 noundef %a) {
+; CHECK-LABEL: uneg8r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    negb %dil, %al
+; CHECK-NEXT:    retq
+entry:
+  %t = call {i8, i1} @llvm.usub.with.overflow.i8(i8 0, i8 %a)
+  %neg = extractvalue {i8, i1} %t, 0
+  ret i8 %neg
+}
+
+define i16 @uneg16r(i16 noundef %a) {
+; CHECK-LABEL: uneg16r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    negl %edi, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+  %t = call {i16, i1} @llvm.usub.with.overflow.i16(i16 0, i16 %a)
+  %neg = extractvalue {i16, i1} %t, 0
+  ret i16 %neg
+}
+
+define i32 @uneg32r(i32 noundef %a) {
+; CHECK-LABEL: uneg32r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    negl %edi, %eax
+; CHECK-NEXT:    retq
+entry:
+  %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 0, i32 %a)
+  %neg = extractvalue {i32, i1} %t, 0
+  ret i32 %neg
+}
+
+define i64 @uneg64r(i64 noundef %a) {
+; CHECK-LABEL: uneg64r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    negq %rdi, %rax
+; CHECK-NEXT:    retq
+entry:
+  %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 0, i64 %a)
+  %neg = extractvalue {i64, i1} %t, 0
+  ret i64 %neg
+}
+
+define i8 @uneg8m(ptr %ptr) {
+; CHECK-LABEL: uneg8m:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    negb (%rdi), %al
+; CHECK-NEXT:    retq
+entry:
+  %a = load i8, ptr %ptr
+  %t = call {i8, i1} @llvm.usub.with.overflow.i8(i8 0, i8 %a)
+  %neg = extractvalue {i8, i1} %t, 0
+  ret i8 %neg
+}
+
+define i16 @uneg16m(ptr %ptr) {
+; CHECK-LABEL: uneg16m:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    negw (%rdi), %ax
+; CHECK-NEXT:    retq
+entry:
+  %a = load i16, ptr %ptr
+  %t = call {i16, i1} @llvm.usub.with.overflow.i16(i16 0, i16 %a)
+  %neg = extractvalue {i16, i1} %t, 0
+  ret i16 %neg
+}
+
+define i32 @uneg32m(ptr %ptr) {
+; CHECK-LABEL: uneg32m:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    negl (%rdi), %eax
+; CHECK-NEXT:    retq
+entry:
+  %a = load i32, ptr %ptr
+  %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 0, i32 %a)
+  %neg = extractvalue {i32, i1} %t, 0
+  ret i32 %neg
+}
+
+define i64 @uneg64m(ptr %ptr) {
+; CHECK-LABEL: uneg64m:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    negq (%rdi), %rax
+; CHECK-NEXT:    retq
+entry:
+  %a = load i64, ptr %ptr
+  %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 0, i64 %a)
+  %neg = extractvalue {i64, i1} %t, 0
+  ret i64 %neg
+}
+
+declare {i8, i1} @llvm.usub.with.overflow.i8(i8, i8)
+declare {i16, i1} @llvm.usub.with.overflow.i16(i16, i16)
+declare {i32, i1} @llvm.usub.with.overflow.i32(i32, i32)
+declare {i64, i1} @llvm.usub.with.overflow.i64(i64, i64)
+
+define void @neg8m_legacy(ptr %ptr) {
+; CHECK-LABEL: neg8m_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    negb (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %a = load i8, ptr %ptr
+  %neg = sub i8 0, %a
+  store i8 %neg, ptr %ptr
+  ret void
+}
+
+define void @neg16m_legacy(ptr %ptr) {
+; CHECK-LABEL: neg16m_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    negw (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %a = load i16, ptr %ptr
+  %neg = sub i16 0, %a
+  store i16 %neg, ptr %ptr
+  ret void
+}
+
+define void @neg32m_legacy(ptr %ptr) {
+; CHECK-LABEL: neg32m_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    negl (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %a = load i32, ptr %ptr
+  %neg = sub i32 0, %a
+  store i32 %neg, ptr %ptr
+  ret void
+}
+
+define void @neg64m_legacy(ptr %ptr) {
+; CHECK-LABEL: neg64m_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    negq (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %a = load i64, ptr %ptr
+  %neg = sub i64 0, %a
+  store i64 %neg, ptr %ptr
+  ret void
+}
diff --git a/llvm/test/CodeGen/X86/apx/not.ll b/llvm/test/CodeGen/X86/apx/not.ll
new file mode 100644
index 00000000000000..5369819d512920
--- /dev/null
+++ b/llvm/test/CodeGen/X86/apx/not.ll
@@ -0,0 +1,137 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs | FileCheck %s
+
+define i8 @not8r(i8 noundef %a) {
+; CHECK-LABEL: not8r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    notb %dil, %al
+; CHECK-NEXT:    retq
+entry:
+  %not = xor i8 %a, -1
+  ret i8 %not
+}
+
+define i16 @not16r(i16 noundef %a) {
+; CHECK-LABEL: not16r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    notl %edi, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+  %not = xor i16 %a, -1
+  ret i16 %not
+}
+
+define i32 @not32r(i32 noundef %a) {
+; CHECK-LABEL: not32r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    notl %edi, %eax
+; CHECK-NEXT:    retq
+entry:
+  %not = xor i32 %a, -1
+  ret i32 %not
+}
+
+define i64 @not64r(i64 noundef %a) {
+; CHECK-LABEL: not64r:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    notq %rdi, %rax
+; CHECK-NEXT:    retq
+entry:
+  %not = xor i64 %a, -1
+  ret i64 %not
+}
+
+define i8 @not8m(ptr %ptr) {
+; CHECK-LABEL: not8m:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    notb (%rdi), %al
+; CHECK-NEXT:    retq
+entry:
+  %a = load i8, ptr %ptr
+  %not = xor i8 %a, -1
+  ret i8 %not
+}
+
+define i16 @not16m(ptr %ptr) {
+; CHECK-LABEL: not16m:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    movzwl (%rdi), %eax
+; CHECK-NEXT:    notl %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+  %a = load i16, ptr %ptr
+  %not = xor i16 %a, -1
+  ret i16 %not
+}
+
+define i32 @not32m(ptr %ptr) {
+; CHECK-LABEL: not32m:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    notl (%rdi), %eax
+; CHECK-NEXT:    retq
+entry:
+  %a = load i32, ptr %ptr
+  %not = xor i32 %a, -1
+  ret i32 %not
+}
+
+define i64 @not64m(ptr %ptr) {
+; CHECK-LABEL: not64m:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    notq (%rdi), %rax
+; CHECK-NEXT:    retq
+entry:
+  %a = load i64, ptr %ptr
+  %not = xor i64 %a, -1
+  ret i64 %not
+}
+
+define void @not8m_legacy(ptr %ptr) {
+; CHECK-LABEL: not8m_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    notb (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %a = load i8, ptr %ptr
+  %not = xor i8 %a, -1
+  store i8 %not, ptr %ptr
+  ret void
+}
+
+define void @not16m_legacy(ptr %ptr) {
+; CHECK-LABEL: not16m_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    notw (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %a = load i16, ptr %ptr
+  %not = xor i16 %a, -1
+  store i16 %not, ptr %ptr
+  ret void
+}
+
+define void @not32m_legacy(ptr %ptr) {
+; CHECK-LABEL: not32m_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    notl (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %a = load i32, ptr %ptr
+  %not = xor i32 %a, -1
+  store i32 %not, ptr %ptr
+  ret void
+}
+
+define void @not64m_legacy(ptr %ptr) {
+; CHECK-LABEL: not64m_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    notq (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %a = load i64, ptr %ptr
+  %not = xor i64 %a, -1
+  store i64 %not, ptr %ptr
+  ret void
+}
diff --git a/llvm/test/CodeGen/X86/apx/or.ll b/llvm/test/CodeGen/X86/apx/or.ll
new file mode 100644
index 00000000000000..bd814981820309
--- /dev/null
+++ b/llvm/test/CodeGen/X86/apx/or.ll
@@ -0,0 +1,593 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs | FileCheck %s
+
+define i8 @or8rr(i8 noundef %a, i8 noundef %b) {
+; CHECK-LABEL: or8rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orl %esi, %edi, %eax
+; CHECK-NEXT:    # kill: def $al killed $al killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %or = or i8 %a, %b
+    ret i8 %or
+}
+
+define i16 @or16rr(i16 noundef %a, i16 noundef %b) {
+; CHECK-LABEL: or16rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orl %esi, %edi, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %or = or i16 %a, %b
+    ret i16 %or
+}
+
+define i32 @or32rr(i32 noundef %a, i32 noundef %b) {
+; CHECK-LABEL: or32rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orl %esi, %edi, %eax
+; CHECK-NEXT:    retq
+entry:
+    %or = or i32 %a, %b
+    ret i32 %or
+}
+
+define i64 @or64rr(i64 noundef %a, i64 noundef %b) {
+; CHECK-LABEL: or64rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orq %rsi, %rdi, %rax
+; CHECK-NEXT:    retq
+entry:
+    %or = or i64 %a, %b
+    ret i64 %or
+}
+
+define i8 @or8rm(i8 noundef %a, ptr %b) {
+; CHECK-LABEL: or8rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orb (%rsi), %dil, %al
+; CHECK-NEXT:    retq
+entry:
+    %t = load i8, ptr %b
+    %or = or i8 %a, %t
+    ret i8 %or
+}
+
+define i16 @or16rm(i16 noundef %a, ptr %b) {
+; CHECK-LABEL: or16rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orw (%rsi), %di, %ax
+; CHECK-NEXT:    retq
+entry:
+    %t = load i16, ptr %b
+    %or = or i16 %a, %t
+    ret i16 %or
+}
+
+define i32 @or32rm(i32 noundef %a, ptr %b) {
+; CHECK-LABEL: or32rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orl (%rsi), %edi, %eax
+; CHECK-NEXT:    retq
+entry:
+    %t = load i32, ptr %b
+    %or = or i32 %a, %t
+    ret i32 %or
+}
+
+define i64 @or64rm(i64 noundef %a, ptr %b) {
+; CHECK-LABEL: or64rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orq (%rsi), %rdi, %rax
+; CHECK-NEXT:    retq
+entry:
+    %t = load i64, ptr %b
+    %or = or i64 %a, %t
+    ret i64 %or
+}
+
+define i16 @or16ri8(i16 noundef %a) {
+; CHECK-LABEL: or16ri8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orl $123, %edi, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %or = or i16 %a, 123
+    ret i16 %or
+}
+
+define i32 @or32ri8(i32 noundef %a) {
+; CHECK-LABEL: or32ri8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orl $123, %edi, %eax
+; CHECK-NEXT:    retq
+entry:
+    %or = or i32 %a, 123
+    ret i32 %or
+}
+
+define i64 @or64ri8(i64 noundef %a) {
+; CHECK-LABEL: or64ri8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orq $123, %rdi, %rax
+; CHECK-NEXT:    retq
+entry:
+    %or = or i64 %a, 123
+    ret i64 %or
+}
+
+define i8 @or8ri(i8 noundef %a) {
+; CHECK-LABEL: or8ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orb $123, %dil, %al
+; CHECK-NEXT:    retq
+entry:
+    %or = or i8 %a, 123
+    ret i8 %or
+}
+
+define i16 @or16ri(i16 noundef %a) {
+; CHECK-LABEL: or16ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orl $1234, %edi, %eax # imm = 0x4D2
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %or = or i16 %a, 1234
+    ret i16 %or
+}
+
+define i32 @or32ri(i32 noundef %a) {
+; CHECK-LABEL: or32ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orl $123456, %edi, %eax # imm = 0x1E240
+; CHECK-NEXT:    retq
+entry:
+    %or = or i32 %a, 123456
+    ret i32 %or
+}
+
+define i64 @or64ri(i64 noundef %a) {
+; CHECK-LABEL: or64ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orq $123456, %rdi, %rax # imm = 0x1E240
+; CHECK-NEXT:    retq
+entry:
+    %or = or i64 %a, 123456
+    ret i64 %or
+}
+
+define i8 @or8mr(ptr %a, i8 noundef %b) {
+; CHECK-LABEL: or8mr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orb %sil, (%rdi), %al
+; CHECK-NEXT:    retq
+entry:
+  %t= load i8, ptr %a
+  %or = or i8 %t, %b
+  ret i8 %or
+}
+
+define i16 @or16mr(ptr %a, i16 noundef %b) {
+; CHECK-LABEL: or16mr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orw %si, (%rdi), %ax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i16, ptr %a
+  %or = or i16 %t, %b
+  ret i16 %or
+}
+
+define i32 @or32mr(ptr %a, i32 noundef %b) {
+; CHECK-LABEL: or32mr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orl %esi, (%rdi), %eax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i32, ptr %a
+  %or = or i32 %t, %b
+  ret i32 %or
+}
+
+define i64 @or64mr(ptr %a, i64 noundef %b) {
+; CHECK-LABEL: or64mr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orq %rsi, (%rdi), %rax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i64, ptr %a
+  %or = or i64 %t, %b
+  ret i64 %or
+}
+
+define i16 @or16mi8(ptr %a) {
+; CHECK-LABEL: or16mi8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    movzwl (%rdi), %eax
+; CHECK-NEXT:    orl $123, %eax, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i16, ptr %a
+  %or = or i16 %t, 123
+  ret i16 %or
+}
+
+define i32 @or32mi8(ptr %a) {
+; CHECK-LABEL: or32mi8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orl $123, (%rdi), %eax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i32, ptr %a
+  %or = or i32 %t, 123
+  ret i32 %or
+}
+
+define i64 @or64mi8(ptr %a) {
+; CHECK-LABEL: or64mi8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orq $123, (%rdi), %rax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i64, ptr %a
+  %or = or i64 %t, 123
+  ret i64 %or
+}
+
+define i8 @or8mi(ptr %a) {
+; CHECK-LABEL: or8mi:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orb $123, (%rdi), %al
+; CHECK-NEXT:    retq
+entry:
+  %t= load i8, ptr %a
+  %or = or i8 %t, 123
+  ret i8 %or
+}
+
+define i16 @or16mi(ptr %a) {
+; CHECK-LABEL: or16mi:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    movzwl (%rdi), %eax
+; CHECK-NEXT:    orl $1234, %eax, %eax # imm = 0x4D2
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i16, ptr %a
+  %or = or i16 %t, 1234
+  ret i16 %or
+}
+
+define i32 @or32mi(ptr %a) {
+; CHECK-LABEL: or32mi:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orl $123456, (%rdi), %eax # imm = 0x1E240
+; CHECK-NEXT:    retq
+entry:
+  %t= load i32, ptr %a
+  %or = or i32 %t, 123456
+  ret i32 %or
+}
+
+define i64 @or64mi(ptr %a) {
+; CHECK-LABEL: or64mi:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orq $123456, (%rdi), %rax # imm = 0x1E240
+; CHECK-NEXT:    retq
+entry:
+  %t= load i64, ptr %a
+  %or = or i64 %t, 123456
+  ret i64 %or
+}
+
+ at d64 = dso_local global i64 0
+
+define i1 @orflag8rr(i8 %a, i8 %b) {
+; CHECK-LABEL: orflag8rr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    notb %sil, %al
+; CHECK-NEXT:    orb %al, %dil, %cl
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movb %cl, d64(%rip)
+; CHECK-NEXT:    retq
+  %xor = xor i8 %b, -1
+  %v0 = or i8 %a, %xor  ; 0xff << 50
+  %v1 = icmp eq i8 %v0, 0
+  store i8 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @orflag16rr(i16 %a, i16 %b) {
+; CHECK-LABEL: orflag16rr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    notl %esi, %eax
+; CHECK-NEXT:    orw %ax, %di, %cx
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movw %cx, d64(%rip)
+; CHECK-NEXT:    retq
+  %xor = xor i16 %b, -1
+  %v0 = or i16 %a, %xor  ; 0xff << 50
+  %v1 = icmp eq i16 %v0, 0
+  store i16 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @orflag32rr(i32 %a, i32 %b) {
+; CHECK-LABEL: orflag32rr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    orl %esi, %edi, %ecx
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movl %ecx, d64(%rip)
+; CHECK-NEXT:    retq
+  %v0 = or i32 %a, %b  ; 0xff << 50
+  %v1 = icmp eq i32 %v0, 0
+  store i32 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @orflag64rr(i64 %a, i64 %b) {
+; CHECK-LABEL: orflag64rr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    orq %rsi, %rdi, %rcx
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movq %rcx, d64(%rip)
+; CHECK-NEXT:    retq
+  %v0 = or i64 %a, %b  ; 0xff << 50
+  %v1 = icmp eq i64 %v0, 0
+  store i64 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @orflag8rm(ptr %ptr, i8 %b) {
+; CHECK-LABEL: orflag8rm:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    notb %sil, %al
+; CHECK-NEXT:    orb (%rdi), %al, %cl
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movb %cl, d64(%rip)
+; CHECK-NEXT:    retq
+  %a = load i8, ptr %ptr
+  %xor = xor i8 %b, -1
+  %v0 = or i8 %a, %xor  ; 0xff << 50
+  %v1 = icmp eq i8 %v0, 0
+  store i8 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @orflag16rm(ptr %ptr, i16 %b) {
+; CHECK-LABEL: orflag16rm:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    notl %esi, %eax
+; CHECK-NEXT:    orw (%rdi), %ax, %cx
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movw %cx, d64(%rip)
+; CHECK-NEXT:    retq
+  %a = load i16, ptr %ptr
+  %xor = xor i16 %b, -1
+  %v0 = or i16 %a, %xor  ; 0xff << 50
+  %v1 = icmp eq i16 %v0, 0
+  store i16 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @orflag32rm(ptr %ptr, i32 %b) {
+; CHECK-LABEL: orflag32rm:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    orl (%rdi), %esi, %ecx
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movl %ecx, d64(%rip)
+; CHECK-NEXT:    retq
+  %a = load i32, ptr %ptr
+  %v0 = or i32 %a, %b  ; 0xff << 50
+  %v1 = icmp eq i32 %v0, 0
+  store i32 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @orflag64rm(ptr %ptr, i64 %b) {
+; CHECK-LABEL: orflag64rm:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    orq (%rdi), %rsi, %rcx
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movq %rcx, d64(%rip)
+; CHECK-NEXT:    retq
+  %a = load i64, ptr %ptr
+  %v0 = or i64 %a, %b  ; 0xff << 50
+  %v1 = icmp eq i64 %v0, 0
+  store i64 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @orflag8ri(i8 %a) {
+; CHECK-LABEL: orflag8ri:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    orb $-124, %dil, %cl
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movb %cl, d64(%rip)
+; CHECK-NEXT:    retq
+  %xor = xor i8 123, -1
+  %v0 = or i8 %a, %xor  ; 0xff << 50
+  %v1 = icmp eq i8 %v0, 0
+  store i8 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @orflag16ri(i16 %a) {
+; CHECK-LABEL: orflag16ri:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    orw $-1235, %di, %cx # imm = 0xFB2D
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movw %cx, d64(%rip)
+; CHECK-NEXT:    retq
+  %xor = xor i16 1234, -1
+  %v0 = or i16 %a, %xor  ; 0xff << 50
+  %v1 = icmp eq i16 %v0, 0
+  store i16 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @orflag32ri(i32 %a) {
+; CHECK-LABEL: orflag32ri:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    orl $123456, %edi, %ecx # imm = 0x1E240
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movl %ecx, d64(%rip)
+; CHECK-NEXT:    retq
+  %v0 = or i32 %a, 123456  ; 0xff << 50
+  %v1 = icmp eq i32 %v0, 0
+  store i32 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @orflag64ri(i64 %a) {
+; CHECK-LABEL: orflag64ri:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    orq $123456, %rdi, %rcx # imm = 0x1E240
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movq %rcx, d64(%rip)
+; CHECK-NEXT:    retq
+  %v0 = or i64 %a, 123456  ; 0xff << 50
+  %v1 = icmp eq i64 %v0, 0
+  store i64 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @orflag16ri8(i16 %a) {
+; CHECK-LABEL: orflag16ri8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    orw $-124, %di, %cx
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movw %cx, d64(%rip)
+; CHECK-NEXT:    retq
+  %xor = xor i16 123, -1
+  %v0 = or i16 %a, %xor  ; 0xff << 50
+  %v1 = icmp eq i16 %v0, 0
+  store i16 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @orflag32ri8(i32 %a) {
+; CHECK-LABEL: orflag32ri8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    orl $123, %edi, %ecx
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movl %ecx, d64(%rip)
+; CHECK-NEXT:    retq
+  %v0 = or i32 %a, 123  ; 0xff << 50
+  %v1 = icmp eq i32 %v0, 0
+  store i32 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @orflag64ri8(i64 %a) {
+; CHECK-LABEL: orflag64ri8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    orq $123, %rdi, %rcx
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movq %rcx, d64(%rip)
+; CHECK-NEXT:    retq
+  %v0 = or i64 %a, 123  ; 0xff << 50
+  %v1 = icmp eq i64 %v0, 0
+  store i64 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define void @or8mr_legacy(ptr %a, i8 noundef %b) {
+; CHECK-LABEL: or8mr_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orb %sil, (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %t= load i8, ptr %a
+  %or = or i8 %t, %b
+  store i8 %or, ptr %a
+  ret void
+}
+
+define void @or16mr_legacy(ptr %a, i16 noundef %b) {
+; CHECK-LABEL: or16mr_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orw %si, (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %t= load i16, ptr %a
+  %or = or i16 %t, %b
+  store i16 %or, ptr %a
+  ret void
+}
+
+define void @or32mr_legacy(ptr %a, i32 noundef %b) {
+; CHECK-LABEL: or32mr_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orl %esi, (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %t= load i32, ptr %a
+  %or = or i32 %t, %b
+  store i32 %or, ptr %a
+  ret void
+}
+
+define void @or64mr_legacy(ptr %a, i64 noundef %b) {
+; CHECK-LABEL: or64mr_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orq %rsi, (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %t= load i64, ptr %a
+  %or = or i64 %t, %b
+  store i64 %or, ptr %a
+  ret void
+}
+
+define void @or8mi_legacy(ptr %a) {
+; CHECK-LABEL: or8mi_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orb $123, (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %t= load i8, ptr %a
+  %or = or i8 %t, 123
+  store i8 %or, ptr %a
+  ret void
+}
+
+define void @or16mi_legacy(ptr %a) {
+; CHECK-LABEL: or16mi_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orw $1234, (%rdi) # imm = 0x4D2
+; CHECK-NEXT:    retq
+entry:
+  %t= load i16, ptr %a
+  %or = or i16 %t, 1234
+  store i16 %or, ptr %a
+  ret void
+}
+
+define void @or32mi_legacy(ptr %a) {
+; CHECK-LABEL: or32mi_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orl $123456, (%rdi) # imm = 0x1E240
+; CHECK-NEXT:    retq
+entry:
+  %t= load i32, ptr %a
+  %or = or i32 %t, 123456
+  store i32 %or, ptr %a
+  ret void
+}
+
+define void @or64mi_legacy(ptr %a) {
+; CHECK-LABEL: or64mi_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    orq $123456, (%rdi) # imm = 0x1E240
+; CHECK-NEXT:    retq
+entry:
+  %t= load i64, ptr %a
+  %or = or i64 %t, 123456
+  store i64 %or, ptr %a
+  ret void
+}
diff --git a/llvm/test/CodeGen/X86/apx/sbb.ll b/llvm/test/CodeGen/X86/apx/sbb.ll
new file mode 100644
index 00000000000000..72a488e70b2c99
--- /dev/null
+++ b/llvm/test/CodeGen/X86/apx/sbb.ll
@@ -0,0 +1,433 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs | FileCheck %s
+
+define i8 @sbb8rr(i8 %a, i8 %b, i8 %x, i8 %y) nounwind {
+; CHECK-LABEL: sbb8rr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subb %dl, %cl, %al
+; CHECK-NEXT:    sbbb %sil, %dil, %al
+; CHECK-NEXT:    retq
+  %s = sub i8 %a, %b
+  %k = icmp ugt i8 %x, %y
+  %z = zext i1 %k to i8
+  %r = sub i8 %s, %z
+  ret i8 %r
+}
+
+define i16 @sbb16rr(i16 %a, i16 %b, i16 %x, i16 %y) nounwind {
+; CHECK-LABEL: sbb16rr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subw %dx, %cx, %ax
+; CHECK-NEXT:    sbbw %si, %di, %ax
+; CHECK-NEXT:    retq
+  %s = sub i16 %a, %b
+  %k = icmp ugt i16 %x, %y
+  %z = zext i1 %k to i16
+  %r = sub i16 %s, %z
+  ret i16 %r
+}
+
+define i32 @sbb32rr(i32 %a, i32 %b, i32 %x, i32 %y) nounwind {
+; CHECK-LABEL: sbb32rr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subl %edx, %ecx, %eax
+; CHECK-NEXT:    sbbl %esi, %edi, %eax
+; CHECK-NEXT:    retq
+  %s = sub i32 %a, %b
+  %k = icmp ugt i32 %x, %y
+  %z = zext i1 %k to i32
+  %r = sub i32 %s, %z
+  ret i32 %r
+}
+
+define i64 @sbb64rr(i64 %a, i64 %b, i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: sbb64rr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subq %rdx, %rcx, %rax
+; CHECK-NEXT:    sbbq %rsi, %rdi, %rax
+; CHECK-NEXT:    retq
+  %s = sub i64 %a, %b
+  %k = icmp ugt i64 %x, %y
+  %z = zext i1 %k to i64
+  %r = sub i64 %s, %z
+  ret i64 %r
+}
+
+define i8 @sbb8rm(i8 %a, ptr %ptr, i8 %x, i8 %y) nounwind {
+; CHECK-LABEL: sbb8rm:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subb %dl, %cl, %al
+; CHECK-NEXT:    sbbb (%rsi), %dil, %al
+; CHECK-NEXT:    retq
+  %b = load i8, ptr %ptr
+  %s = sub i8 %a, %b
+  %k = icmp ugt i8 %x, %y
+  %z = zext i1 %k to i8
+  %r = sub i8 %s, %z
+  ret i8 %r
+}
+
+define i16 @sbb16rm(i16 %a, ptr %ptr, i16 %x, i16 %y) nounwind {
+; CHECK-LABEL: sbb16rm:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subw %dx, %cx, %ax
+; CHECK-NEXT:    sbbw (%rsi), %di, %ax
+; CHECK-NEXT:    retq
+  %b = load i16, ptr %ptr
+  %s = sub i16 %a, %b
+  %k = icmp ugt i16 %x, %y
+  %z = zext i1 %k to i16
+  %r = sub i16 %s, %z
+  ret i16 %r
+}
+
+define i32 @sbb32rm(i32 %a, ptr %ptr, i32 %x, i32 %y) nounwind {
+; CHECK-LABEL: sbb32rm:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subl %edx, %ecx, %eax
+; CHECK-NEXT:    sbbl (%rsi), %edi, %eax
+; CHECK-NEXT:    retq
+  %b = load i32, ptr %ptr
+  %s = sub i32 %a, %b
+  %k = icmp ugt i32 %x, %y
+  %z = zext i1 %k to i32
+  %r = sub i32 %s, %z
+  ret i32 %r
+}
+
+define i64 @sbb64rm(i64 %a, ptr %ptr, i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: sbb64rm:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subq %rdx, %rcx, %rax
+; CHECK-NEXT:    sbbq (%rsi), %rdi, %rax
+; CHECK-NEXT:    retq
+  %b = load i64, ptr %ptr
+  %s = sub i64 %a, %b
+  %k = icmp ugt i64 %x, %y
+  %z = zext i1 %k to i64
+  %r = sub i64 %s, %z
+  ret i64 %r
+}
+
+define i16 @sbb16ri8(i16 %a, i16 %x, i16 %y) nounwind {
+; CHECK-LABEL: sbb16ri8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subw %si, %dx, %ax
+; CHECK-NEXT:    sbbw $0, %di, %ax
+; CHECK-NEXT:    addl $-123, %eax, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+  %s = sub i16 %a, 123
+  %k = icmp ugt i16 %x, %y
+  %z = zext i1 %k to i16
+  %r = sub i16 %s, %z
+  ret i16 %r
+}
+
+define i32 @sbb32ri8(i32 %a, i32 %x, i32 %y) nounwind {
+; CHECK-LABEL: sbb32ri8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subl %esi, %edx, %eax
+; CHECK-NEXT:    sbbl $0, %edi, %eax
+; CHECK-NEXT:    addl $-123, %eax, %eax
+; CHECK-NEXT:    retq
+  %s = sub i32 %a, 123
+  %k = icmp ugt i32 %x, %y
+  %z = zext i1 %k to i32
+  %r = sub i32 %s, %z
+  ret i32 %r
+}
+
+define i64 @sbb64ri8(i64 %a, i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: sbb64ri8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subq %rsi, %rdx, %rax
+; CHECK-NEXT:    sbbq $0, %rdi, %rax
+; CHECK-NEXT:    addq $-123, %rax, %rax
+; CHECK-NEXT:    retq
+  %s = sub i64 %a, 123
+  %k = icmp ugt i64 %x, %y
+  %z = zext i1 %k to i64
+  %r = sub i64 %s, %z
+  ret i64 %r
+}
+
+define i8 @sbb8ri(i8 %a, i8 %x, i8 %y) nounwind {
+; CHECK-LABEL: sbb8ri:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subb %sil, %dl, %al
+; CHECK-NEXT:    sbbb $0, %dil, %al
+; CHECK-NEXT:    addb $-123, %al, %al
+; CHECK-NEXT:    retq
+  %s = sub i8 %a, 123
+  %k = icmp ugt i8 %x, %y
+  %z = zext i1 %k to i8
+  %r = sub i8 %s, %z
+  ret i8 %r
+}
+
+define i16 @sbb16ri(i16 %a, i16 %x, i16 %y) nounwind {
+; CHECK-LABEL: sbb16ri:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subw %si, %dx, %ax
+; CHECK-NEXT:    sbbw $0, %di, %ax
+; CHECK-NEXT:    addl $-1234, %eax, %eax # imm = 0xFB2E
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+  %s = sub i16 %a, 1234
+  %k = icmp ugt i16 %x, %y
+  %z = zext i1 %k to i16
+  %r = sub i16 %s, %z
+  ret i16 %r
+}
+
+define i32 @sbb32ri(i32 %a, i32 %x, i32 %y) nounwind {
+; CHECK-LABEL: sbb32ri:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subl %esi, %edx, %eax
+; CHECK-NEXT:    sbbl $0, %edi, %eax
+; CHECK-NEXT:    addl $-123456, %eax, %eax # imm = 0xFFFE1DC0
+; CHECK-NEXT:    retq
+  %s = sub i32 %a, 123456
+  %k = icmp ugt i32 %x, %y
+  %z = zext i1 %k to i32
+  %r = sub i32 %s, %z
+  ret i32 %r
+}
+
+define i64 @sbb64ri(i64 %a, i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: sbb64ri:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subq %rsi, %rdx, %rax
+; CHECK-NEXT:    sbbq $0, %rdi, %rax
+; CHECK-NEXT:    addq $-123456, %rax, %rax # imm = 0xFFFE1DC0
+; CHECK-NEXT:    retq
+  %s = sub i64 %a, 123456
+  %k = icmp ugt i64 %x, %y
+  %z = zext i1 %k to i64
+  %r = sub i64 %s, %z
+  ret i64 %r
+}
+
+define i8 @sbb8mr(i8 %a, ptr %ptr, i8 %x, i8 %y) nounwind {
+; CHECK-LABEL: sbb8mr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subb %dl, %cl, %al
+; CHECK-NEXT:    sbbb %dil, (%rsi), %al
+; CHECK-NEXT:    retq
+  %b = load i8, ptr %ptr
+  %s = sub i8 %b, %a
+  %k = icmp ugt i8 %x, %y
+  %z = zext i1 %k to i8
+  %r = sub i8 %s, %z
+  ret i8 %r
+}
+
+define i16 @sbb16mr(i16 %a, ptr %ptr, i16 %x, i16 %y) nounwind {
+; CHECK-LABEL: sbb16mr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subw %dx, %cx, %ax
+; CHECK-NEXT:    sbbw %di, (%rsi), %ax
+; CHECK-NEXT:    retq
+  %b = load i16, ptr %ptr
+  %s = sub i16 %b, %a
+  %k = icmp ugt i16 %x, %y
+  %z = zext i1 %k to i16
+  %r = sub i16 %s, %z
+  ret i16 %r
+}
+
+define i32 @sbb32mr(i32 %a, ptr %ptr, i32 %x, i32 %y) nounwind {
+; CHECK-LABEL: sbb32mr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subl %edx, %ecx, %eax
+; CHECK-NEXT:    sbbl %edi, (%rsi), %eax
+; CHECK-NEXT:    retq
+  %b = load i32, ptr %ptr
+  %s = sub i32 %b, %a
+  %k = icmp ugt i32 %x, %y
+  %z = zext i1 %k to i32
+  %r = sub i32 %s, %z
+  ret i32 %r
+}
+
+define i64 @sbb64mr(i64 %a, ptr %ptr, i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: sbb64mr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subq %rdx, %rcx, %rax
+; CHECK-NEXT:    sbbq %rdi, (%rsi), %rax
+; CHECK-NEXT:    retq
+  %b = load i64, ptr %ptr
+  %s = sub i64 %b, %a
+  %k = icmp ugt i64 %x, %y
+  %z = zext i1 %k to i64
+  %r = sub i64 %s, %z
+  ret i64 %r
+}
+
+define i16 @sbb16mi8(ptr %ptr, i16 %x, i16 %y) nounwind {
+; CHECK-LABEL: sbb16mi8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subw %si, %dx, %ax
+; CHECK-NEXT:    sbbw $0, (%rdi), %ax
+; CHECK-NEXT:    addl $-123, %eax, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+  %a = load i16, ptr %ptr
+  %s = sub i16 %a, 123
+  %k = icmp ugt i16 %x, %y
+  %z = zext i1 %k to i16
+  %r = sub i16 %s, %z
+  ret i16 %r
+}
+
+define i32 @sbb32mi8(ptr %ptr, i32 %x, i32 %y) nounwind {
+; CHECK-LABEL: sbb32mi8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subl %esi, %edx, %eax
+; CHECK-NEXT:    sbbl $0, (%rdi), %eax
+; CHECK-NEXT:    addl $-123, %eax, %eax
+; CHECK-NEXT:    retq
+  %a = load i32, ptr %ptr
+  %s = sub i32 %a, 123
+  %k = icmp ugt i32 %x, %y
+  %z = zext i1 %k to i32
+  %r = sub i32 %s, %z
+  ret i32 %r
+}
+
+define i64 @sbb64mi8(ptr %ptr, i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: sbb64mi8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subq %rsi, %rdx, %rax
+; CHECK-NEXT:    sbbq $0, (%rdi), %rax
+; CHECK-NEXT:    addq $-123, %rax, %rax
+; CHECK-NEXT:    retq
+  %a = load i64, ptr %ptr
+  %s = sub i64 %a, 123
+  %k = icmp ugt i64 %x, %y
+  %z = zext i1 %k to i64
+  %r = sub i64 %s, %z
+  ret i64 %r
+}
+
+define i8 @sbb8mi(ptr %ptr, i8 %x, i8 %y) nounwind {
+; CHECK-LABEL: sbb8mi:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subb %sil, %dl, %al
+; CHECK-NEXT:    sbbb $0, (%rdi), %al
+; CHECK-NEXT:    addb $-123, %al, %al
+; CHECK-NEXT:    retq
+  %a = load i8, ptr %ptr
+  %s = sub i8 %a, 123
+  %k = icmp ugt i8 %x, %y
+  %z = zext i1 %k to i8
+  %r = sub i8 %s, %z
+  ret i8 %r
+}
+
+define i16 @sbb16mi(ptr %ptr, i16 %x, i16 %y) nounwind {
+; CHECK-LABEL: sbb16mi:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subw %si, %dx, %ax
+; CHECK-NEXT:    sbbw $0, (%rdi), %ax
+; CHECK-NEXT:    addl $-1234, %eax, %eax # imm = 0xFB2E
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+  %a = load i16, ptr %ptr
+  %s = sub i16 %a, 1234
+  %k = icmp ugt i16 %x, %y
+  %z = zext i1 %k to i16
+  %r = sub i16 %s, %z
+  ret i16 %r
+}
+
+define i32 @sbb32mi(ptr %ptr, i32 %x, i32 %y) nounwind {
+; CHECK-LABEL: sbb32mi:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subl %esi, %edx, %eax
+; CHECK-NEXT:    sbbl $0, (%rdi), %eax
+; CHECK-NEXT:    addl $-123456, %eax, %eax # imm = 0xFFFE1DC0
+; CHECK-NEXT:    retq
+  %a = load i32, ptr %ptr
+  %s = sub i32 %a, 123456
+  %k = icmp ugt i32 %x, %y
+  %z = zext i1 %k to i32
+  %r = sub i32 %s, %z
+  ret i32 %r
+}
+
+define i64 @sbb64mi(ptr %ptr, i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: sbb64mi:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subq %rsi, %rdx, %rax
+; CHECK-NEXT:    sbbq $0, (%rdi), %rax
+; CHECK-NEXT:    addq $-123456, %rax, %rax # imm = 0xFFFE1DC0
+; CHECK-NEXT:    retq
+  %a = load i64, ptr %ptr
+  %s = sub i64 %a, 123456
+  %k = icmp ugt i64 %x, %y
+  %z = zext i1 %k to i64
+  %r = sub i64 %s, %z
+  ret i64 %r
+}
+
+define void @sbb8mr_legacy(i8 %a, ptr %ptr, i8 %x, i8 %y) nounwind {
+; CHECK-LABEL: sbb8mr_legacy:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subb %dl, %cl, %al
+; CHECK-NEXT:    sbbb %dil, (%rsi)
+; CHECK-NEXT:    retq
+  %b = load i8, ptr %ptr
+  %s = sub i8 %b, %a
+  %k = icmp ugt i8 %x, %y
+  %z = zext i1 %k to i8
+  %r = sub i8 %s, %z
+  store i8 %r, ptr %ptr
+  ret void
+}
+
+define void @sbb16mr_legacy(i16 %a, ptr %ptr, i16 %x, i16 %y) nounwind {
+; CHECK-LABEL: sbb16mr_legacy:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subw %dx, %cx, %ax
+; CHECK-NEXT:    sbbw %di, (%rsi)
+; CHECK-NEXT:    retq
+  %b = load i16, ptr %ptr
+  %s = sub i16 %b, %a
+  %k = icmp ugt i16 %x, %y
+  %z = zext i1 %k to i16
+  %r = sub i16 %s, %z
+  store i16 %r, ptr %ptr
+  ret void
+}
+
+define void @sbb32mr_legacy(i32 %a, ptr %ptr, i32 %x, i32 %y) nounwind {
+; CHECK-LABEL: sbb32mr_legacy:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subl %edx, %ecx, %eax
+; CHECK-NEXT:    sbbl %edi, (%rsi)
+; CHECK-NEXT:    retq
+  %b = load i32, ptr %ptr
+  %s = sub i32 %b, %a
+  %k = icmp ugt i32 %x, %y
+  %z = zext i1 %k to i32
+  %r = sub i32 %s, %z
+  store i32 %r, ptr %ptr
+  ret void
+}
+
+define void @sbb64mr_legacy(i64 %a, ptr %ptr, i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: sbb64mr_legacy:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subq %rdx, %rcx, %rax
+; CHECK-NEXT:    sbbq %rdi, (%rsi)
+; CHECK-NEXT:    retq
+  %b = load i64, ptr %ptr
+  %s = sub i64 %b, %a
+  %k = icmp ugt i64 %x, %y
+  %z = zext i1 %k to i64
+  %r = sub i64 %s, %z
+  store i64 %r, ptr %ptr
+  ret void
+}
diff --git a/llvm/test/CodeGen/X86/apx/sub.ll b/llvm/test/CodeGen/X86/apx/sub.ll
new file mode 100644
index 00000000000000..a6c76fe081b2d8
--- /dev/null
+++ b/llvm/test/CodeGen/X86/apx/sub.ll
@@ -0,0 +1,609 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs | FileCheck %s
+
+define i8 @sub8rr(i8 noundef %a, i8 noundef %b) {
+; CHECK-LABEL: sub8rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    subb %sil, %dil, %al
+; CHECK-NEXT:    retq
+entry:
+    %sub = sub i8 %a, %b
+    ret i8 %sub
+}
+
+define i16 @sub16rr(i16 noundef %a, i16 noundef %b) {
+; CHECK-LABEL: sub16rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    subl %esi, %edi, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %sub = sub i16 %a, %b
+    ret i16 %sub
+}
+
+define i32 @sub32rr(i32 noundef %a, i32 noundef %b) {
+; CHECK-LABEL: sub32rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    subl %esi, %edi, %eax
+; CHECK-NEXT:    retq
+entry:
+    %sub = sub i32 %a, %b
+    ret i32 %sub
+}
+
+define i64 @sub64rr(i64 noundef %a, i64 noundef %b) {
+; CHECK-LABEL: sub64rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    subq %rsi, %rdi, %rax
+; CHECK-NEXT:    retq
+entry:
+    %sub = sub i64 %a, %b
+    ret i64 %sub
+}
+
+define i8 @sub8rm(i8 noundef %a, ptr %ptr) {
+; CHECK-LABEL: sub8rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    subb (%rsi), %dil, %al
+; CHECK-NEXT:    retq
+entry:
+    %b = load i8, ptr %ptr
+    %sub = sub i8 %a, %b
+    ret i8 %sub
+}
+
+define i16 @sub16rm(i16 noundef %a, ptr %ptr) {
+; CHECK-LABEL: sub16rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    subw (%rsi), %di, %ax
+; CHECK-NEXT:    retq
+entry:
+    %b = load i16, ptr %ptr
+    %sub = sub i16 %a, %b
+    ret i16 %sub
+}
+
+define i32 @sub32rm(i32 noundef %a, ptr %ptr) {
+; CHECK-LABEL: sub32rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    subl (%rsi), %edi, %eax
+; CHECK-NEXT:    retq
+entry:
+    %b = load i32, ptr %ptr
+    %sub = sub i32 %a, %b
+    ret i32 %sub
+}
+
+define i64 @sub64rm(i64 noundef %a, ptr %ptr) {
+; CHECK-LABEL: sub64rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    subq (%rsi), %rdi, %rax
+; CHECK-NEXT:    retq
+entry:
+    %b = load i64, ptr %ptr
+    %sub = sub i64 %a, %b
+    ret i64 %sub
+}
+
+define i16 @sub16ri8(i16 noundef %a) {
+; CHECK-LABEL: sub16ri8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl $-123, %edi, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %sub = sub i16 %a, 123
+    ret i16 %sub
+}
+
+define i32 @sub32ri8(i32 noundef %a) {
+; CHECK-LABEL: sub32ri8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl $-123, %edi, %eax
+; CHECK-NEXT:    retq
+entry:
+    %sub = sub i32 %a, 123
+    ret i32 %sub
+}
+
+define i64 @sub64ri8(i64 noundef %a) {
+; CHECK-LABEL: sub64ri8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addq $-123, %rdi, %rax
+; CHECK-NEXT:    retq
+entry:
+    %sub = sub i64 %a, 123
+    ret i64 %sub
+}
+
+define i8 @sub8ri(i8 noundef %a) {
+; CHECK-LABEL: sub8ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addb $-123, %dil, %al
+; CHECK-NEXT:    retq
+entry:
+    %sub = sub i8 %a, 123
+    ret i8 %sub
+}
+
+define i16 @sub16ri(i16 noundef %a) {
+; CHECK-LABEL: sub16ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl $-1234, %edi, %eax # imm = 0xFB2E
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %sub = sub i16 %a, 1234
+    ret i16 %sub
+}
+
+define i32 @sub32ri(i32 noundef %a) {
+; CHECK-LABEL: sub32ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl $-123456, %edi, %eax # imm = 0xFFFE1DC0
+; CHECK-NEXT:    retq
+entry:
+    %sub = sub i32 %a, 123456
+    ret i32 %sub
+}
+
+define i64 @sub64ri(i64 noundef %a) {
+; CHECK-LABEL: sub64ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addq $-123456, %rdi, %rax # imm = 0xFFFE1DC0
+; CHECK-NEXT:    retq
+entry:
+    %sub = sub i64 %a, 123456
+    ret i64 %sub
+}
+
+define i8 @sub8mr(ptr %a, i8 noundef %b) {
+; CHECK-LABEL: sub8mr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    subb %sil, (%rdi), %al
+; CHECK-NEXT:    retq
+entry:
+  %t= load i8, ptr %a
+  %sub = sub nsw i8 %t, %b
+  ret i8 %sub
+}
+
+define i16 @sub16mr(ptr %a, i16 noundef %b) {
+; CHECK-LABEL: sub16mr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    movzwl (%rdi), %eax
+; CHECK-NEXT:    subl %esi, %eax, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i16, ptr %a
+  %sub = sub nsw i16 %t, %b
+  ret i16 %sub
+}
+
+define i32 @sub32mr(ptr %a, i32 noundef %b) {
+; CHECK-LABEL: sub32mr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    subl %esi, (%rdi), %eax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i32, ptr %a
+  %sub = sub nsw i32 %t, %b
+  ret i32 %sub
+}
+
+define i64 @sub64mr(ptr %a, i64 noundef %b) {
+; CHECK-LABEL: sub64mr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    subq %rsi, (%rdi), %rax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i64, ptr %a
+  %sub = sub nsw i64 %t, %b
+  ret i64 %sub
+}
+
+define i16 @sub16mi8(ptr %a) {
+; CHECK-LABEL: sub16mi8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    movzwl (%rdi), %eax
+; CHECK-NEXT:    addl $-123, %eax, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i16, ptr %a
+  %sub = sub nsw i16 %t, 123
+  ret i16 %sub
+}
+
+define i32 @sub32mi8(ptr %a) {
+; CHECK-LABEL: sub32mi8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl $-123, (%rdi), %eax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i32, ptr %a
+  %sub = sub nsw i32 %t, 123
+  ret i32 %sub
+}
+
+define i64 @sub64mi8(ptr %a) {
+; CHECK-LABEL: sub64mi8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addq $-123, (%rdi), %rax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i64, ptr %a
+  %sub = sub nsw i64 %t, 123
+  ret i64 %sub
+}
+
+define i8 @sub8mi(ptr %a) {
+; CHECK-LABEL: sub8mi:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addb $-123, (%rdi), %al
+; CHECK-NEXT:    retq
+entry:
+  %t= load i8, ptr %a
+  %sub = sub nsw i8 %t, 123
+  ret i8 %sub
+}
+
+define i16 @sub16mi(ptr %a) {
+; CHECK-LABEL: sub16mi:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    movzwl (%rdi), %eax
+; CHECK-NEXT:    addl $-1234, %eax, %eax # imm = 0xFB2E
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i16, ptr %a
+  %sub = sub nsw i16 %t, 1234
+  ret i16 %sub
+}
+
+define i32 @sub32mi(ptr %a) {
+; CHECK-LABEL: sub32mi:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl $-123456, (%rdi), %eax # imm = 0xFFFE1DC0
+; CHECK-NEXT:    retq
+entry:
+  %t= load i32, ptr %a
+  %sub = sub nsw i32 %t, 123456
+  ret i32 %sub
+}
+
+define i64 @sub64mi(ptr %a) {
+; CHECK-LABEL: sub64mi:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addq $-123456, (%rdi), %rax # imm = 0xFFFE1DC0
+; CHECK-NEXT:    retq
+entry:
+  %t= load i64, ptr %a
+  %sub = sub nsw i64 %t, 123456
+  ret i64 %sub
+}
+
+declare i8 @llvm.usub.sat.i8(i8, i8)
+declare i16 @llvm.usub.sat.i16(i16, i16)
+declare i32 @llvm.usub.sat.i32(i32, i32)
+declare i64 @llvm.usub.sat.i64(i64, i64)
+
+define i8 @subflag8rr(i8 noundef %a, i8 noundef %b) {
+; CHECK-LABEL: subflag8rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %ecx, %ecx
+; CHECK-NEXT:    subb %sil, %dil, %al
+; CHECK-NEXT:    movzbl %al, %eax
+; CHECK-NEXT:    cmovbl %ecx, %eax
+; CHECK-NEXT:    # kill: def $al killed $al killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %sub = call i8 @llvm.usub.sat.i8(i8 %a, i8 %b)
+    ret i8 %sub
+}
+
+define i16 @subflag16rr(i16 noundef %a, i16 noundef %b) {
+; CHECK-LABEL: subflag16rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %ecx, %ecx
+; CHECK-NEXT:    subw %si, %di, %ax
+; CHECK-NEXT:    cmovbl %ecx, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %sub = call i16 @llvm.usub.sat.i16(i16 %a, i16 %b)
+    ret i16 %sub
+}
+
+define i32 @subflag32rr(i32 noundef %a, i32 noundef %b) {
+; CHECK-LABEL: subflag32rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %ecx, %ecx
+; CHECK-NEXT:    subl %esi, %edi, %eax
+; CHECK-NEXT:    cmovbl %ecx, %eax
+; CHECK-NEXT:    retq
+entry:
+    %sub = call i32 @llvm.usub.sat.i32(i32 %a, i32 %b)
+    ret i32 %sub
+}
+
+define i64 @subflag64rr(i64 noundef %a, i64 noundef %b) {
+; CHECK-LABEL: subflag64rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    subq %rsi, %rdi, %rcx
+; CHECK-NEXT:    cmovaeq %rcx, %rax
+; CHECK-NEXT:    retq
+entry:
+    %sub = call i64 @llvm.usub.sat.i64(i64 %a, i64 %b)
+    ret i64 %sub
+}
+
+define i8 @subflag8rm(i8 noundef %a, ptr %b) {
+; CHECK-LABEL: subflag8rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %ecx, %ecx
+; CHECK-NEXT:    subb (%rsi), %dil, %al
+; CHECK-NEXT:    movzbl %al, %eax
+; CHECK-NEXT:    cmovbl %ecx, %eax
+; CHECK-NEXT:    # kill: def $al killed $al killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %t = load i8, ptr %b
+    %sub = call i8 @llvm.usub.sat.i8(i8 %a, i8 %t)
+    ret i8 %sub
+}
+
+define i16 @subflag16rm(i16 noundef %a, ptr %b) {
+; CHECK-LABEL: subflag16rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %ecx, %ecx
+; CHECK-NEXT:    subw (%rsi), %di, %ax
+; CHECK-NEXT:    cmovbl %ecx, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %t = load i16, ptr %b
+    %sub = call i16 @llvm.usub.sat.i16(i16 %a, i16 %t)
+    ret i16 %sub
+}
+
+define i32 @subflag32rm(i32 noundef %a, ptr %b) {
+; CHECK-LABEL: subflag32rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %ecx, %ecx
+; CHECK-NEXT:    subl (%rsi), %edi, %eax
+; CHECK-NEXT:    cmovbl %ecx, %eax
+; CHECK-NEXT:    retq
+entry:
+    %t = load i32, ptr %b
+    %sub = call i32 @llvm.usub.sat.i32(i32 %a, i32 %t)
+    ret i32 %sub
+}
+
+define i64 @subflag64rm(i64 noundef %a, ptr %b) {
+; CHECK-LABEL: subflag64rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    subq (%rsi), %rdi, %rcx
+; CHECK-NEXT:    cmovaeq %rcx, %rax
+; CHECK-NEXT:    retq
+entry:
+    %t = load i64, ptr %b
+    %sub = call i64 @llvm.usub.sat.i64(i64 %a, i64 %t)
+    ret i64 %sub
+}
+
+define i16 @subflag16ri8(i16 noundef %a) {
+; CHECK-LABEL: subflag16ri8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %ecx, %ecx
+; CHECK-NEXT:    subw $123, %di, %ax
+; CHECK-NEXT:    cmovbl %ecx, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %sub = call i16 @llvm.usub.sat.i16(i16 %a, i16 123)
+    ret i16 %sub
+}
+
+define i32 @subflag32ri8(i32 noundef %a) {
+; CHECK-LABEL: subflag32ri8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %ecx, %ecx
+; CHECK-NEXT:    subl $123, %edi, %eax
+; CHECK-NEXT:    cmovbl %ecx, %eax
+; CHECK-NEXT:    retq
+entry:
+    %sub = call i32 @llvm.usub.sat.i32(i32 %a, i32 123)
+    ret i32 %sub
+}
+
+define i64 @subflag64ri8(i64 noundef %a) {
+; CHECK-LABEL: subflag64ri8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    subq $123, %rdi, %rcx
+; CHECK-NEXT:    cmovaeq %rcx, %rax
+; CHECK-NEXT:    retq
+entry:
+    %sub = call i64 @llvm.usub.sat.i64(i64 %a, i64 123)
+    ret i64 %sub
+}
+
+define i8 @subflag8ri(i8 noundef %a) {
+; CHECK-LABEL: subflag8ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %ecx, %ecx
+; CHECK-NEXT:    subb $123, %dil, %al
+; CHECK-NEXT:    movzbl %al, %eax
+; CHECK-NEXT:    cmovbl %ecx, %eax
+; CHECK-NEXT:    # kill: def $al killed $al killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %sub = call i8 @llvm.usub.sat.i8(i8 %a, i8 123)
+    ret i8 %sub
+}
+
+define i16 @subflag16ri(i16 noundef %a) {
+; CHECK-LABEL: subflag16ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %ecx, %ecx
+; CHECK-NEXT:    subw $1234, %di, %ax # imm = 0x4D2
+; CHECK-NEXT:    cmovbl %ecx, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %sub = call i16 @llvm.usub.sat.i16(i16 %a, i16 1234)
+    ret i16 %sub
+}
+
+define i32 @subflag32ri(i32 noundef %a) {
+; CHECK-LABEL: subflag32ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %ecx, %ecx
+; CHECK-NEXT:    subl $123456, %edi, %eax # imm = 0x1E240
+; CHECK-NEXT:    cmovbl %ecx, %eax
+; CHECK-NEXT:    retq
+entry:
+    %sub = call i32 @llvm.usub.sat.i32(i32 %a, i32 123456)
+    ret i32 %sub
+}
+
+define i64 @subflag64ri(i64 noundef %a) {
+; CHECK-LABEL: subflag64ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    subq $123456, %rdi, %rcx # imm = 0x1E240
+; CHECK-NEXT:    cmovaeq %rcx, %rax
+; CHECK-NEXT:    retq
+entry:
+    %sub = call i64 @llvm.usub.sat.i64(i64 %a, i64 123456)
+    ret i64 %sub
+}
+
+ at val = external hidden global i8
+
+declare void @f()
+
+define void @sub64ri_reloc(i64 %val) {
+; CHECK-LABEL: sub64ri_reloc:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subq $val, %rdi, %rax
+; CHECK-NEXT:    jbe .LBB41_2
+; CHECK-NEXT:  # %bb.1: # %t
+; CHECK-NEXT:    pushq %rax
+; CHECK-NEXT:    .cfi_def_cfa_offset 16
+; CHECK-NEXT:    callq f at PLT
+; CHECK-NEXT:    popq %rax
+; CHECK-NEXT:    .cfi_def_cfa_offset 8
+; CHECK-NEXT:  .LBB41_2: # %f
+; CHECK-NEXT:    retq
+  %cmp = icmp ugt i64 %val, ptrtoint (ptr @val to i64)
+  br i1 %cmp, label %t, label %f
+
+t:
+  call void @f()
+  ret void
+
+f:
+  ret void
+}
+
+define void @sub8mr_legacy(ptr %a, i8 noundef %b) {
+; CHECK-LABEL: sub8mr_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    subb %sil, (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %t= load i8, ptr %a
+  %sub = sub i8 %t, %b
+  store i8 %sub, ptr %a
+  ret void
+}
+
+define void @sub16mr_legacy(ptr %a, i16 noundef %b) {
+; CHECK-LABEL: sub16mr_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    subw %si, (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %t= load i16, ptr %a
+  %sub = sub i16 %t, %b
+  store i16 %sub, ptr %a
+  ret void
+}
+
+define void @sub32mr_legacy(ptr %a, i32 noundef %b) {
+; CHECK-LABEL: sub32mr_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    subl %esi, (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %t= load i32, ptr %a
+  %sub = sub i32 %t, %b
+  store i32 %sub, ptr %a
+  ret void
+}
+
+define void @sub64mr_legacy(ptr %a, i64 noundef %b) {
+; CHECK-LABEL: sub64mr_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    subq %rsi, (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %t= load i64, ptr %a
+  %sub = sub i64 %t, %b
+  store i64 %sub, ptr %a
+  ret void
+}
+
+define void @sub8mi_legacy(ptr %a) {
+; CHECK-LABEL: sub8mi_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addb $-123, (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %t= load i8, ptr %a
+  %sub = sub nsw i8 %t, 123
+  store i8 %sub, ptr %a
+  ret void
+}
+
+define void @sub16mi_legacy(ptr %a) {
+; CHECK-LABEL: sub16mi_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addw $-1234, (%rdi) # imm = 0xFB2E
+; CHECK-NEXT:    retq
+entry:
+  %t= load i16, ptr %a
+  %sub = sub nsw i16 %t, 1234
+  store i16 %sub, ptr %a
+  ret void
+}
+
+define void @sub32mi_legacy(ptr %a) {
+; CHECK-LABEL: sub32mi_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addl $-123456, (%rdi) # imm = 0xFFFE1DC0
+; CHECK-NEXT:    retq
+entry:
+  %t= load i32, ptr %a
+  %sub = sub nsw i32 %t, 123456
+  store i32 %sub, ptr %a
+  ret void
+}
+
+define void @sub64mi_legacy(ptr %a) {
+; CHECK-LABEL: sub64mi_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addq $-123456, (%rdi) # imm = 0xFFFE1DC0
+; CHECK-NEXT:    retq
+entry:
+  %t= load i64, ptr %a
+  %sub = sub nsw i64 %t, 123456
+  store i64 %sub, ptr %a
+  ret void
+}
diff --git a/llvm/test/CodeGen/X86/apx/xor.ll b/llvm/test/CodeGen/X86/apx/xor.ll
new file mode 100644
index 00000000000000..53f26f04333108
--- /dev/null
+++ b/llvm/test/CodeGen/X86/apx/xor.ll
@@ -0,0 +1,545 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs | FileCheck %s
+
+define i8 @xor8rr(i8 noundef %a, i8 noundef %b) {
+; CHECK-LABEL: xor8rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %esi, %edi, %eax
+; CHECK-NEXT:    # kill: def $al killed $al killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %xor = xor i8 %a, %b
+    ret i8 %xor
+}
+
+define i16 @xor16rr(i16 noundef %a, i16 noundef %b) {
+; CHECK-LABEL: xor16rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %esi, %edi, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %xor = xor i16 %a, %b
+    ret i16 %xor
+}
+
+define i32 @xor32rr(i32 noundef %a, i32 noundef %b) {
+; CHECK-LABEL: xor32rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %esi, %edi, %eax
+; CHECK-NEXT:    retq
+entry:
+    %xor = xor i32 %a, %b
+    ret i32 %xor
+}
+
+define i64 @xor64rr(i64 noundef %a, i64 noundef %b) {
+; CHECK-LABEL: xor64rr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorq %rsi, %rdi, %rax
+; CHECK-NEXT:    retq
+entry:
+    %xor = xor i64 %a, %b
+    ret i64 %xor
+}
+
+define i8 @xor8rm(i8 noundef %a, ptr %b) {
+; CHECK-LABEL: xor8rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorb (%rsi), %dil, %al
+; CHECK-NEXT:    retq
+entry:
+    %t = load i8, ptr %b
+    %xor = xor i8 %a, %t
+    ret i8 %xor
+}
+
+define i16 @xor16rm(i16 noundef %a, ptr %b) {
+; CHECK-LABEL: xor16rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorw (%rsi), %di, %ax
+; CHECK-NEXT:    retq
+entry:
+    %t = load i16, ptr %b
+    %xor = xor i16 %a, %t
+    ret i16 %xor
+}
+
+define i32 @xor32rm(i32 noundef %a, ptr %b) {
+; CHECK-LABEL: xor32rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl (%rsi), %edi, %eax
+; CHECK-NEXT:    retq
+entry:
+    %t = load i32, ptr %b
+    %xor = xor i32 %a, %t
+    ret i32 %xor
+}
+
+define i64 @xor64rm(i64 noundef %a, ptr %b) {
+; CHECK-LABEL: xor64rm:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorq (%rsi), %rdi, %rax
+; CHECK-NEXT:    retq
+entry:
+    %t = load i64, ptr %b
+    %xor = xor i64 %a, %t
+    ret i64 %xor
+}
+
+define i16 @xor16ri8(i16 noundef %a) {
+; CHECK-LABEL: xor16ri8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl $123, %edi, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %xor = xor i16 %a, 123
+    ret i16 %xor
+}
+
+define i32 @xor32ri8(i32 noundef %a) {
+; CHECK-LABEL: xor32ri8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl $123, %edi, %eax
+; CHECK-NEXT:    retq
+entry:
+    %xor = xor i32 %a, 123
+    ret i32 %xor
+}
+
+define i64 @xor64ri8(i64 noundef %a) {
+; CHECK-LABEL: xor64ri8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorq $123, %rdi, %rax
+; CHECK-NEXT:    retq
+entry:
+    %xor = xor i64 %a, 123
+    ret i64 %xor
+}
+
+define i8 @xor8ri(i8 noundef %a) {
+; CHECK-LABEL: xor8ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorb $123, %dil, %al
+; CHECK-NEXT:    retq
+entry:
+    %xor = xor i8 %a, 123
+    ret i8 %xor
+}
+
+define i16 @xor16ri(i16 noundef %a) {
+; CHECK-LABEL: xor16ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl $1234, %edi, %eax # imm = 0x4D2
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+    %xor = xor i16 %a, 1234
+    ret i16 %xor
+}
+
+define i32 @xor32ri(i32 noundef %a) {
+; CHECK-LABEL: xor32ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl $123456, %edi, %eax # imm = 0x1E240
+; CHECK-NEXT:    retq
+entry:
+    %xor = xor i32 %a, 123456
+    ret i32 %xor
+}
+
+define i64 @xor64ri(i64 noundef %a) {
+; CHECK-LABEL: xor64ri:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorq $123456, %rdi, %rax # imm = 0x1E240
+; CHECK-NEXT:    retq
+entry:
+    %xor = xor i64 %a, 123456
+    ret i64 %xor
+}
+
+define i8 @xor8mr(ptr %a, i8 noundef %b) {
+; CHECK-LABEL: xor8mr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorb %sil, (%rdi), %al
+; CHECK-NEXT:    retq
+entry:
+  %t= load i8, ptr %a
+  %xor = xor i8 %t, %b
+  ret i8 %xor
+}
+
+define i16 @xor16mr(ptr %a, i16 noundef %b) {
+; CHECK-LABEL: xor16mr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorw %si, (%rdi), %ax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i16, ptr %a
+  %xor = xor i16 %t, %b
+  ret i16 %xor
+}
+
+define i32 @xor32mr(ptr %a, i32 noundef %b) {
+; CHECK-LABEL: xor32mr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %esi, (%rdi), %eax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i32, ptr %a
+  %xor = xor i32 %t, %b
+  ret i32 %xor
+}
+
+define i64 @xor64mr(ptr %a, i64 noundef %b) {
+; CHECK-LABEL: xor64mr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorq %rsi, (%rdi), %rax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i64, ptr %a
+  %xor = xor i64 %t, %b
+  ret i64 %xor
+}
+
+define i16 @xor16mi8(ptr %a) {
+; CHECK-LABEL: xor16mi8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    movzwl (%rdi), %eax
+; CHECK-NEXT:    xorl $123, %eax, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i16, ptr %a
+  %xor = xor i16 %t, 123
+  ret i16 %xor
+}
+
+define i32 @xor32mi8(ptr %a) {
+; CHECK-LABEL: xor32mi8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl $123, (%rdi), %eax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i32, ptr %a
+  %xor = xor i32 %t, 123
+  ret i32 %xor
+}
+
+define i64 @xor64mi8(ptr %a) {
+; CHECK-LABEL: xor64mi8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorq $123, (%rdi), %rax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i64, ptr %a
+  %xor = xor i64 %t, 123
+  ret i64 %xor
+}
+
+define i8 @xor8mi(ptr %a) {
+; CHECK-LABEL: xor8mi:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorb $123, (%rdi), %al
+; CHECK-NEXT:    retq
+entry:
+  %t= load i8, ptr %a
+  %xor = xor i8 %t, 123
+  ret i8 %xor
+}
+
+define i16 @xor16mi(ptr %a) {
+; CHECK-LABEL: xor16mi:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    movzwl (%rdi), %eax
+; CHECK-NEXT:    xorl $1234, %eax, %eax # imm = 0x4D2
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+entry:
+  %t= load i16, ptr %a
+  %xor = xor i16 %t, 1234
+  ret i16 %xor
+}
+
+define i32 @xor32mi(ptr %a) {
+; CHECK-LABEL: xor32mi:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl $123456, (%rdi), %eax # imm = 0x1E240
+; CHECK-NEXT:    retq
+entry:
+  %t= load i32, ptr %a
+  %xor = xor i32 %t, 123456
+  ret i32 %xor
+}
+
+define i64 @xor64mi(ptr %a) {
+; CHECK-LABEL: xor64mi:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorq $123456, (%rdi), %rax # imm = 0x1E240
+; CHECK-NEXT:    retq
+entry:
+  %t= load i64, ptr %a
+  %xor = xor i64 %t, 123456
+  ret i64 %xor
+}
+
+ at d64 = dso_local global i64 0
+
+define i1 @xorflag8rr(i8 %a, i8 %b) {
+; CHECK-LABEL: xorflag8rr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorl %edi, %esi, %eax
+; CHECK-NEXT:    xorb $-1, %al, %cl
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movb %cl, d64(%rip)
+; CHECK-NEXT:    retq
+  %xor = xor i8 %b, -1
+  %v0 = xor i8 %a, %xor  ; 0xff << 50
+  %v1 = icmp eq i8 %v0, 0
+  store i8 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @xorflag16rr(i16 %a, i16 %b) {
+; CHECK-LABEL: xorflag16rr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorl %edi, %esi, %eax
+; CHECK-NEXT:    xorw $-1, %ax, %cx
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movw %cx, d64(%rip)
+; CHECK-NEXT:    retq
+  %xor = xor i16 %b, -1
+  %v0 = xor i16 %a, %xor  ; 0xff << 50
+  %v1 = icmp eq i16 %v0, 0
+  store i16 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @xorflag32rr(i32 %a, i32 %b) {
+; CHECK-LABEL: xorflag32rr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorl %esi, %edi, %ecx
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movl %ecx, d64(%rip)
+; CHECK-NEXT:    retq
+  %v0 = xor i32 %a, %b  ; 0xff << 50
+  %v1 = icmp eq i32 %v0, 0
+  store i32 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @xorflag64rr(i64 %a, i64 %b) {
+; CHECK-LABEL: xorflag64rr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorq %rsi, %rdi, %rcx
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movq %rcx, d64(%rip)
+; CHECK-NEXT:    retq
+  %v0 = xor i64 %a, %b  ; 0xff << 50
+  %v1 = icmp eq i64 %v0, 0
+  store i64 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @xorflag8rm(ptr %ptr, i8 %b) {
+; CHECK-LABEL: xorflag8rm:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorb (%rdi), %sil, %al
+; CHECK-NEXT:    xorb $-1, %al, %cl
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movb %cl, d64(%rip)
+; CHECK-NEXT:    retq
+  %a = load i8, ptr %ptr
+  %xor = xor i8 %b, -1
+  %v0 = xor i8 %a, %xor  ; 0xff << 50
+  %v1 = icmp eq i8 %v0, 0
+  store i8 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @xorflag16rm(ptr %ptr, i16 %b) {
+; CHECK-LABEL: xorflag16rm:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorw (%rdi), %si, %ax
+; CHECK-NEXT:    xorw $-1, %ax, %cx
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movw %cx, d64(%rip)
+; CHECK-NEXT:    retq
+  %a = load i16, ptr %ptr
+  %xor = xor i16 %b, -1
+  %v0 = xor i16 %a, %xor  ; 0xff << 50
+  %v1 = icmp eq i16 %v0, 0
+  store i16 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @xorflag32rm(ptr %ptr, i32 %b) {
+; CHECK-LABEL: xorflag32rm:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorl (%rdi), %esi, %ecx
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movl %ecx, d64(%rip)
+; CHECK-NEXT:    retq
+  %a = load i32, ptr %ptr
+  %v0 = xor i32 %a, %b  ; 0xff << 50
+  %v1 = icmp eq i32 %v0, 0
+  store i32 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @xorflag64rm(ptr %ptr, i64 %b) {
+; CHECK-LABEL: xorflag64rm:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorq (%rdi), %rsi, %rcx
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movq %rcx, d64(%rip)
+; CHECK-NEXT:    retq
+  %a = load i64, ptr %ptr
+  %v0 = xor i64 %a, %b  ; 0xff << 50
+  %v1 = icmp eq i64 %v0, 0
+  store i64 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @xorflag8ri(i8 %a) {
+; CHECK-LABEL: xorflag8ri:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorb $-124, %dil, %cl
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movb %cl, d64(%rip)
+; CHECK-NEXT:    retq
+  %xor = xor i8 123, -1
+  %v0 = xor i8 %a, %xor  ; 0xff << 50
+  %v1 = icmp eq i8 %v0, 0
+  store i8 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @xorflag16ri(i16 %a) {
+; CHECK-LABEL: xorflag16ri:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorw $-1235, %di, %cx # imm = 0xFB2D
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movw %cx, d64(%rip)
+; CHECK-NEXT:    retq
+  %xor = xor i16 1234, -1
+  %v0 = xor i16 %a, %xor  ; 0xff << 50
+  %v1 = icmp eq i16 %v0, 0
+  store i16 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @xorflag32ri(i32 %a) {
+; CHECK-LABEL: xorflag32ri:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorl $123456, %edi, %ecx # imm = 0x1E240
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movl %ecx, d64(%rip)
+; CHECK-NEXT:    retq
+  %v0 = xor i32 %a, 123456  ; 0xff << 50
+  %v1 = icmp eq i32 %v0, 0
+  store i32 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @xorflag64ri(i64 %a) {
+; CHECK-LABEL: xorflag64ri:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorq $123456, %rdi, %rcx # imm = 0x1E240
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movq %rcx, d64(%rip)
+; CHECK-NEXT:    retq
+  %v0 = xor i64 %a, 123456  ; 0xff << 50
+  %v1 = icmp eq i64 %v0, 0
+  store i64 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @xorflag16ri8(i16 %a) {
+; CHECK-LABEL: xorflag16ri8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorw $-124, %di, %cx
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movw %cx, d64(%rip)
+; CHECK-NEXT:    retq
+  %xor = xor i16 123, -1
+  %v0 = xor i16 %a, %xor  ; 0xff << 50
+  %v1 = icmp eq i16 %v0, 0
+  store i16 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @xorflag32ri8(i32 %a) {
+; CHECK-LABEL: xorflag32ri8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorl $123, %edi, %ecx
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movl %ecx, d64(%rip)
+; CHECK-NEXT:    retq
+  %v0 = xor i32 %a, 123  ; 0xff << 50
+  %v1 = icmp eq i32 %v0, 0
+  store i32 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define i1 @xorflag64ri8(i64 %a) {
+; CHECK-LABEL: xorflag64ri8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorq $123, %rdi, %rcx
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    movq %rcx, d64(%rip)
+; CHECK-NEXT:    retq
+  %v0 = xor i64 %a, 123  ; 0xff << 50
+  %v1 = icmp eq i64 %v0, 0
+  store i64 %v0, ptr @d64
+  ret i1 %v1
+}
+
+define void @xor8mr_legacy(ptr %a, i8 noundef %b) {
+; CHECK-LABEL: xor8mr_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorb %sil, (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %t= load i8, ptr %a
+  %xor = xor i8 %t, %b
+  store i8 %xor, ptr %a
+  ret void
+}
+
+define void @xor16mr_legacy(ptr %a, i16 noundef %b) {
+; CHECK-LABEL: xor16mr_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorw %si, (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %t= load i16, ptr %a
+  %xor = xor i16 %t, %b
+  store i16 %xor, ptr %a
+  ret void
+}
+
+define void @xor32mr_legacy(ptr %a, i32 noundef %b) {
+; CHECK-LABEL: xor32mr_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %esi, (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %t= load i32, ptr %a
+  %xor = xor i32 %t, %b
+  store i32 %xor, ptr %a
+  ret void
+}
+
+define void @xor64mr_legacy(ptr %a, i64 noundef %b) {
+; CHECK-LABEL: xor64mr_legacy:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorq %rsi, (%rdi)
+; CHECK-NEXT:    retq
+entry:
+  %t= load i64, ptr %a
+  %xor = xor i64 %t, %b
+  store i64 %xor, ptr %a
+  ret void
+}

>From 89316567e50255b1f1c1d34d2c2503f5344e3247 Mon Sep 17 00:00:00 2001
From: Shengchen Kan <shengchen.kan at intel.com>
Date: Thu, 11 Jan 2024 11:39:19 +0800
Subject: [PATCH 2/2] address review comment - reorder pattern

---
 llvm/lib/Target/X86/X86InstrCompiler.td | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Target/X86/X86InstrCompiler.td b/llvm/lib/Target/X86/X86InstrCompiler.td
index 84457e4e161502..422391a6e02ae0 100644
--- a/llvm/lib/Target/X86/X86InstrCompiler.td
+++ b/llvm/lib/Target/X86/X86InstrCompiler.td
@@ -1773,18 +1773,18 @@ def : Pat<(X86xor_flag (i8 (trunc GR32:$src)),
 // where the least significant bit is not 0. However, the probability of this
 // happening is considered low enough that this is officially not a
 // "real problem".
-let Predicates = [HasNDD] in {
-  def : Pat<(shl GR8 :$src1, (i8 1)), (ADD8rr_ND  GR8 :$src1, GR8 :$src1)>;
-  def : Pat<(shl GR16:$src1, (i8 1)), (ADD16rr_ND GR16:$src1, GR16:$src1)>;
-  def : Pat<(shl GR32:$src1, (i8 1)), (ADD32rr_ND GR32:$src1, GR32:$src1)>;
-  def : Pat<(shl GR64:$src1, (i8 1)), (ADD64rr_ND GR64:$src1, GR64:$src1)>;
-}
 let Predicates = [NoNDD] in {
   def : Pat<(shl GR8 :$src1, (i8 1)), (ADD8rr  GR8 :$src1, GR8 :$src1)>;
   def : Pat<(shl GR16:$src1, (i8 1)), (ADD16rr GR16:$src1, GR16:$src1)>;
   def : Pat<(shl GR32:$src1, (i8 1)), (ADD32rr GR32:$src1, GR32:$src1)>;
   def : Pat<(shl GR64:$src1, (i8 1)), (ADD64rr GR64:$src1, GR64:$src1)>;
 }
+let Predicates = [HasNDD] in {
+  def : Pat<(shl GR8 :$src1, (i8 1)), (ADD8rr_ND  GR8 :$src1, GR8 :$src1)>;
+  def : Pat<(shl GR16:$src1, (i8 1)), (ADD16rr_ND GR16:$src1, GR16:$src1)>;
+  def : Pat<(shl GR32:$src1, (i8 1)), (ADD32rr_ND GR32:$src1, GR32:$src1)>;
+  def : Pat<(shl GR64:$src1, (i8 1)), (ADD64rr_ND GR64:$src1, GR64:$src1)>;
+}
 
 // Shift amount is implicitly masked.
 multiclass MaskedShiftAmountPats<SDNode frag, string name> {



More information about the llvm-commits mailing list