[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