diff --git a/llvm/lib/Target/X86/X86InstrArithmetic.td b/llvm/lib/Target/X86/X86InstrArithmetic.td index 5cfa95e085e34..76b0fe5f5cad1 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 { - def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2), - (!cast(NAME#"8ri") GR8:$src1, relocImm8_su:$src2)>; - def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2), - (!cast(NAME#"16ri") GR16:$src1, relocImm16_su:$src2)>; - def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2), - (!cast(NAME#"32ri") GR32:$src1, relocImm32_su:$src2)>; - def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2), - (!cast(NAME#"64ri32") GR64:$src1, i64relocImmSExt32_su:$src2)>; - - def : Pat<(store (OpNode (load addr:$dst), relocImm8_su:$src), addr:$dst), - (!cast(NAME#"8mi") addr:$dst, relocImm8_su:$src)>; - def : Pat<(store (OpNode (load addr:$dst), relocImm16_su:$src), addr:$dst), - (!cast(NAME#"16mi") addr:$dst, relocImm16_su:$src)>; - def : Pat<(store (OpNode (load addr:$dst), relocImm32_su:$src), addr:$dst), - (!cast(NAME#"32mi") addr:$dst, relocImm32_su:$src)>; - def : Pat<(store (OpNode (load addr:$dst), i64relocImmSExt32_su:$src), addr:$dst), - (!cast(NAME#"64mi32") addr:$dst, i64relocImmSExt32_su:$src)>; + let Predicates = [NoNDD] in { + def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2), + (!cast(NAME#"8ri") GR8:$src1, relocImm8_su:$src2)>; + def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2), + (!cast(NAME#"16ri") GR16:$src1, relocImm16_su:$src2)>; + def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2), + (!cast(NAME#"32ri") GR32:$src1, relocImm32_su:$src2)>; + def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2), + (!cast(NAME#"64ri32") GR64:$src1, i64relocImmSExt32_su:$src2)>; + + def : Pat<(store (OpNode (load addr:$dst), relocImm8_su:$src), addr:$dst), + (!cast(NAME#"8mi") addr:$dst, relocImm8_su:$src)>; + def : Pat<(store (OpNode (load addr:$dst), relocImm16_su:$src), addr:$dst), + (!cast(NAME#"16mi") addr:$dst, relocImm16_su:$src)>; + def : Pat<(store (OpNode (load addr:$dst), relocImm32_su:$src), addr:$dst), + (!cast(NAME#"32mi") addr:$dst, relocImm32_su:$src)>; + def : Pat<(store (OpNode (load addr:$dst), i64relocImmSExt32_su:$src), addr:$dst), + (!cast(NAME#"64mi32") addr:$dst, i64relocImmSExt32_su:$src)>; + } + let Predicates = [HasNDD] in { + def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2), + (!cast(NAME#"8ri_ND") GR8:$src1, relocImm8_su:$src2)>; + def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2), + (!cast(NAME#"16ri_ND") GR16:$src1, relocImm16_su:$src2)>; + def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2), + (!cast(NAME#"32ri_ND") GR32:$src1, relocImm32_su:$src2)>; + def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2), + (!cast(NAME#"64ri32_ND") GR64:$src1, i64relocImmSExt32_su:$src2)>; + + def : Pat<(OpNode (load addr:$dst), relocImm8_su:$src), + (!cast(NAME#"8mi_ND") addr:$dst, relocImm8_su:$src)>; + def : Pat<(OpNode (load addr:$dst), relocImm16_su:$src), + (!cast(NAME#"16mi_ND") addr:$dst, relocImm16_su:$src)>; + def : Pat<(OpNode (load addr:$dst), relocImm32_su:$src), + (!cast(NAME#"32mi_ND") addr:$dst, relocImm32_su:$src)>; + def : Pat<(OpNode (load addr:$dst), i64relocImmSExt32_su:$src), + (!cast(NAME#"64mi32_ND") addr:$dst, i64relocImmSExt32_su:$src)>; + } } multiclass ArithBinOp_RFF_relocImm_Pats { - def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2, EFLAGS), - (!cast(NAME#"8ri") GR8:$src1, relocImm8_su:$src2)>; - def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2, EFLAGS), - (!cast(NAME#"16ri") GR16:$src1, relocImm16_su:$src2)>; - def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2, EFLAGS), - (!cast(NAME#"32ri") GR32:$src1, relocImm32_su:$src2)>; - def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2, EFLAGS), - (!cast(NAME#"64ri32") GR64:$src1, i64relocImmSExt32_su:$src2)>; - - def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm8_su:$src, EFLAGS), addr:$dst), - (!cast(NAME#"8mi") addr:$dst, relocImm8_su:$src)>; - def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm16_su:$src, EFLAGS), addr:$dst), - (!cast(NAME#"16mi") addr:$dst, relocImm16_su:$src)>; - def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm32_su:$src, EFLAGS), addr:$dst), - (!cast(NAME#"32mi") addr:$dst, relocImm32_su:$src)>; - def : Pat<(store (OpNodeFlag (load addr:$dst), i64relocImmSExt32_su:$src, EFLAGS), addr:$dst), - (!cast(NAME#"64mi32") addr:$dst, i64relocImmSExt32_su:$src)>; + let Predicates = [NoNDD] in { + def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2, EFLAGS), + (!cast(NAME#"8ri") GR8:$src1, relocImm8_su:$src2)>; + def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2, EFLAGS), + (!cast(NAME#"16ri") GR16:$src1, relocImm16_su:$src2)>; + def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2, EFLAGS), + (!cast(NAME#"32ri") GR32:$src1, relocImm32_su:$src2)>; + def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2, EFLAGS), + (!cast(NAME#"64ri32") GR64:$src1, i64relocImmSExt32_su:$src2)>; + + def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm8_su:$src, EFLAGS), addr:$dst), + (!cast(NAME#"8mi") addr:$dst, relocImm8_su:$src)>; + def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm16_su:$src, EFLAGS), addr:$dst), + (!cast(NAME#"16mi") addr:$dst, relocImm16_su:$src)>; + def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm32_su:$src, EFLAGS), addr:$dst), + (!cast(NAME#"32mi") addr:$dst, relocImm32_su:$src)>; + def : Pat<(store (OpNodeFlag (load addr:$dst), i64relocImmSExt32_su:$src, EFLAGS), addr:$dst), + (!cast(NAME#"64mi32") addr:$dst, i64relocImmSExt32_su:$src)>; + } + let Predicates = [HasNDD] in { + def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2, EFLAGS), + (!cast(NAME#"8ri_ND") GR8:$src1, relocImm8_su:$src2)>; + def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2, EFLAGS), + (!cast(NAME#"16ri_ND") GR16:$src1, relocImm16_su:$src2)>; + def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2, EFLAGS), + (!cast(NAME#"32ri_ND") GR32:$src1, relocImm32_su:$src2)>; + def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2, EFLAGS), + (!cast(NAME#"64ri32_ND") GR64:$src1, i64relocImmSExt32_su:$src2)>; + + def : Pat<(OpNodeFlag (load addr:$dst), relocImm8_su:$src, EFLAGS), + (!cast(NAME#"8mi_ND") addr:$dst, relocImm8_su:$src)>; + def : Pat<(OpNodeFlag (load addr:$dst), relocImm16_su:$src, EFLAGS), + (!cast(NAME#"16mi_ND") addr:$dst, relocImm16_su:$src)>; + def : Pat<(OpNodeFlag (load addr:$dst), relocImm32_su:$src, EFLAGS), + (!cast(NAME#"32mi_ND") addr:$dst, relocImm32_su:$src)>; + def : Pat<(OpNodeFlag (load addr:$dst), i64relocImmSExt32_su:$src, EFLAGS), + (!cast(NAME#"64mi32_ND") addr:$dst, i64relocImmSExt32_su:$src)>; + } } multiclass ArithBinOp_F_relocImm_Pats { diff --git a/llvm/lib/Target/X86/X86InstrCompiler.td b/llvm/lib/Target/X86/X86InstrCompiler.td index c77c77ee4a3ee..422391a6e02ae 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 = [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 { @@ -1937,75 +1956,179 @@ defm : one_bit_patterns; // 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 { + let Predicates = [p] in { + // add reg, reg + def : Pat<(add GR8 :$src1, GR8 :$src2), (!cast(ADD8rr#suffix) GR8 :$src1, GR8 :$src2)>; + def : Pat<(add GR16:$src1, GR16:$src2), (!cast(ADD16rr#suffix) GR16:$src1, GR16:$src2)>; + def : Pat<(add GR32:$src1, GR32:$src2), (!cast(ADD32rr#suffix) GR32:$src1, GR32:$src2)>; + def : Pat<(add GR64:$src1, GR64:$src2), (!cast(ADD64rr#suffix) GR64:$src1, GR64:$src2)>; + + // add reg, mem + def : Pat<(add GR8:$src1, (loadi8 addr:$src2)), + (!cast(ADD8rm#suffix) GR8:$src1, addr:$src2)>; + def : Pat<(add GR16:$src1, (loadi16 addr:$src2)), + (!cast(ADD16rm#suffix) GR16:$src1, addr:$src2)>; + def : Pat<(add GR32:$src1, (loadi32 addr:$src2)), + (!cast(ADD32rm#suffix) GR32:$src1, addr:$src2)>; + def : Pat<(add GR64:$src1, (loadi64 addr:$src2)), + (!cast(ADD64rm#suffix) GR64:$src1, addr:$src2)>; + + // add reg, imm + def : Pat<(add GR8 :$src1, imm:$src2), (!cast(ADD8ri#suffix) GR8:$src1 , imm:$src2)>; + def : Pat<(add GR16:$src1, imm:$src2), (!cast(ADD16ri#suffix) GR16:$src1, imm:$src2)>; + def : Pat<(add GR32:$src1, imm:$src2), (!cast(ADD32ri#suffix) GR32:$src1, imm:$src2)>; + def : Pat<(add GR64:$src1, i64immSExt32:$src2), (!cast(ADD64ri32#suffix) GR64:$src1, i64immSExt32:$src2)>; + + // sub reg, reg + def : Pat<(sub GR8 :$src1, GR8 :$src2), (!cast(SUB8rr#suffix) GR8 :$src1, GR8 :$src2)>; + def : Pat<(sub GR16:$src1, GR16:$src2), (!cast(SUB16rr#suffix) GR16:$src1, GR16:$src2)>; + def : Pat<(sub GR32:$src1, GR32:$src2), (!cast(SUB32rr#suffix) GR32:$src1, GR32:$src2)>; + def : Pat<(sub GR64:$src1, GR64:$src2), (!cast(SUB64rr#suffix) GR64:$src1, GR64:$src2)>; + + // sub reg, mem + def : Pat<(sub GR8:$src1, (loadi8 addr:$src2)), + (!cast(SUB8rm#suffix) GR8:$src1, addr:$src2)>; + def : Pat<(sub GR16:$src1, (loadi16 addr:$src2)), + (!cast(SUB16rm#suffix) GR16:$src1, addr:$src2)>; + def : Pat<(sub GR32:$src1, (loadi32 addr:$src2)), + (!cast(SUB32rm#suffix) GR32:$src1, addr:$src2)>; + def : Pat<(sub GR64:$src1, (loadi64 addr:$src2)), + (!cast(SUB64rm#suffix) GR64:$src1, addr:$src2)>; + + // sub reg, imm + def : Pat<(sub GR8:$src1, imm:$src2), + (!cast(SUB8ri#suffix) GR8:$src1, imm:$src2)>; + def : Pat<(sub GR16:$src1, imm:$src2), + (!cast(SUB16ri#suffix) GR16:$src1, imm:$src2)>; + def : Pat<(sub GR32:$src1, imm:$src2), + (!cast(SUB32ri#suffix) GR32:$src1, imm:$src2)>; + def : Pat<(sub GR64:$src1, i64immSExt32:$src2), + (!cast(SUB64ri32#suffix) GR64:$src1, i64immSExt32:$src2)>; + + // sub 0, reg + def : Pat<(X86sub_flag 0, GR8 :$src), (!cast(NEG8r#suffix) GR8 :$src)>; + def : Pat<(X86sub_flag 0, GR16:$src), (!cast(NEG16r#suffix) GR16:$src)>; + def : Pat<(X86sub_flag 0, GR32:$src), (!cast(NEG32r#suffix) GR32:$src)>; + def : Pat<(X86sub_flag 0, GR64:$src), (!cast(NEG64r#suffix) GR64:$src)>; + + // mul reg, reg + def : Pat<(mul GR16:$src1, GR16:$src2), + (!cast(IMUL16rr#suffix) GR16:$src1, GR16:$src2)>; + def : Pat<(mul GR32:$src1, GR32:$src2), + (!cast(IMUL32rr#suffix) GR32:$src1, GR32:$src2)>; + def : Pat<(mul GR64:$src1, GR64:$src2), + (!cast(IMUL64rr#suffix) GR64:$src1, GR64:$src2)>; + + // mul reg, mem + def : Pat<(mul GR16:$src1, (loadi16 addr:$src2)), + (!cast(IMUL16rm#suffix) GR16:$src1, addr:$src2)>; + def : Pat<(mul GR32:$src1, (loadi32 addr:$src2)), + (!cast(IMUL32rm#suffix) GR32:$src1, addr:$src2)>; + def : Pat<(mul GR64:$src1, (loadi64 addr:$src2)), + (!cast(IMUL64rm#suffix) GR64:$src1, addr:$src2)>; + + // or reg/reg. + def : Pat<(or GR8 :$src1, GR8 :$src2), (!cast(OR8rr#suffix) GR8 :$src1, GR8 :$src2)>; + def : Pat<(or GR16:$src1, GR16:$src2), (!cast(OR16rr#suffix) GR16:$src1, GR16:$src2)>; + def : Pat<(or GR32:$src1, GR32:$src2), (!cast(OR32rr#suffix) GR32:$src1, GR32:$src2)>; + def : Pat<(or GR64:$src1, GR64:$src2), (!cast(OR64rr#suffix) GR64:$src1, GR64:$src2)>; + + // or reg/mem + def : Pat<(or GR8:$src1, (loadi8 addr:$src2)), + (!cast(OR8rm#suffix) GR8:$src1, addr:$src2)>; + def : Pat<(or GR16:$src1, (loadi16 addr:$src2)), + (!cast(OR16rm#suffix) GR16:$src1, addr:$src2)>; + def : Pat<(or GR32:$src1, (loadi32 addr:$src2)), + (!cast(OR32rm#suffix) GR32:$src1, addr:$src2)>; + def : Pat<(or GR64:$src1, (loadi64 addr:$src2)), + (!cast(OR64rm#suffix) GR64:$src1, addr:$src2)>; + + // or reg/imm + def : Pat<(or GR8:$src1 , imm:$src2), (!cast(OR8ri#suffix) GR8 :$src1, imm:$src2)>; + def : Pat<(or GR16:$src1, imm:$src2), (!cast(OR16ri#suffix) GR16:$src1, imm:$src2)>; + def : Pat<(or GR32:$src1, imm:$src2), (!cast(OR32ri#suffix) GR32:$src1, imm:$src2)>; + def : Pat<(or GR64:$src1, i64immSExt32:$src2), + (!cast(OR64ri32#suffix) GR64:$src1, i64immSExt32:$src2)>; + + // xor reg/reg + def : Pat<(xor GR8 :$src1, GR8 :$src2), (!cast(XOR8rr#suffix) GR8 :$src1, GR8 :$src2)>; + def : Pat<(xor GR16:$src1, GR16:$src2), (!cast(XOR16rr#suffix) GR16:$src1, GR16:$src2)>; + def : Pat<(xor GR32:$src1, GR32:$src2), (!cast(XOR32rr#suffix) GR32:$src1, GR32:$src2)>; + def : Pat<(xor GR64:$src1, GR64:$src2), (!cast(XOR64rr#suffix) GR64:$src1, GR64:$src2)>; + + // xor reg/mem + def : Pat<(xor GR8:$src1, (loadi8 addr:$src2)), + (!cast(XOR8rm#suffix) GR8:$src1, addr:$src2)>; + def : Pat<(xor GR16:$src1, (loadi16 addr:$src2)), + (!cast(XOR16rm#suffix) GR16:$src1, addr:$src2)>; + def : Pat<(xor GR32:$src1, (loadi32 addr:$src2)), + (!cast(XOR32rm#suffix) GR32:$src1, addr:$src2)>; + def : Pat<(xor GR64:$src1, (loadi64 addr:$src2)), + (!cast(XOR64rm#suffix) GR64:$src1, addr:$src2)>; + + // xor reg/imm + def : Pat<(xor GR8:$src1, imm:$src2), + (!cast(XOR8ri#suffix) GR8:$src1, imm:$src2)>; + def : Pat<(xor GR16:$src1, imm:$src2), + (!cast(XOR16ri#suffix) GR16:$src1, imm:$src2)>; + def : Pat<(xor GR32:$src1, imm:$src2), + (!cast(XOR32ri#suffix) GR32:$src1, imm:$src2)>; + def : Pat<(xor GR64:$src1, i64immSExt32:$src2), + (!cast(XOR64ri32#suffix) GR64:$src1, i64immSExt32:$src2)>; + + // and reg/reg + def : Pat<(and GR8 :$src1, GR8 :$src2), (!cast(AND8rr#suffix) GR8 :$src1, GR8 :$src2)>; + def : Pat<(and GR16:$src1, GR16:$src2), (!cast(AND16rr#suffix) GR16:$src1, GR16:$src2)>; + def : Pat<(and GR32:$src1, GR32:$src2), (!cast(AND32rr#suffix) GR32:$src1, GR32:$src2)>; + def : Pat<(and GR64:$src1, GR64:$src2), (!cast(AND64rr#suffix) GR64:$src1, GR64:$src2)>; + + // and reg/mem + def : Pat<(and GR8:$src1, (loadi8 addr:$src2)), + (!cast(AND8rm#suffix) GR8:$src1, addr:$src2)>; + def : Pat<(and GR16:$src1, (loadi16 addr:$src2)), + (!cast(AND16rm#suffix) GR16:$src1, addr:$src2)>; + def : Pat<(and GR32:$src1, (loadi32 addr:$src2)), + (!cast(AND32rm#suffix) GR32:$src1, addr:$src2)>; + def : Pat<(and GR64:$src1, (loadi64 addr:$src2)), + (!cast(AND64rm#suffix) GR64:$src1, addr:$src2)>; + + // and reg/imm + def : Pat<(and GR8:$src1, imm:$src2), + (!cast(AND8ri#suffix) GR8:$src1, imm:$src2)>; + def : Pat<(and GR16:$src1, imm:$src2), + (!cast(AND16ri#suffix) GR16:$src1, imm:$src2)>; + def : Pat<(and GR32:$src1, imm:$src2), + (!cast(AND32ri#suffix) GR32:$src1, imm:$src2)>; + def : Pat<(and GR64:$src1, i64immSExt32:$src2), + (!cast(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(INC8r#suffix) GR8:$src)>; + def : Pat<(add GR16:$src, 1), (!cast(INC16r#suffix) GR16:$src)>; + def : Pat<(add GR32:$src, 1), (!cast(INC32r#suffix) GR32:$src)>; + def : Pat<(add GR64:$src, 1), (!cast(INC64r#suffix) GR64:$src)>; + def : Pat<(add GR8:$src, -1), (!cast(DEC8r#suffix) GR8:$src)>; + def : Pat<(add GR16:$src, -1), (!cast(DEC16r#suffix) GR16:$src)>; + def : Pat<(add GR32:$src, -1), (!cast(DEC32r#suffix) GR32:$src)>; + def : Pat<(add GR64:$src, -1), (!cast(DEC64r#suffix) GR64:$src)>; + + def : Pat<(X86add_flag_nocf GR8:$src, -1), (!cast(DEC8r#suffix) GR8:$src)>; + def : Pat<(X86add_flag_nocf GR16:$src, -1), (!cast(DEC16r#suffix) GR16:$src)>; + def : Pat<(X86add_flag_nocf GR32:$src, -1), (!cast(DEC32r#suffix) GR32:$src)>; + def : Pat<(X86add_flag_nocf GR64:$src, -1), (!cast(DEC64r#suffix) GR64:$src)>; + def : Pat<(X86sub_flag_nocf GR8:$src, -1), (!cast(INC8r#suffix) GR8:$src)>; + def : Pat<(X86sub_flag_nocf GR16:$src, -1), (!cast(INC16r#suffix) GR16:$src)>; + def : Pat<(X86sub_flag_nocf GR32:$src, -1), (!cast(INC32r#suffix) GR32:$src)>; + def : Pat<(X86sub_flag_nocf GR64:$src, -1), (!cast(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 0000000000000..8e2df5c277201 --- /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 0000000000000..7502cde2df3ce --- /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 +} + +@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 0000000000000..d79f1f5886bad --- /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 0000000000000..2963a6477be4c --- /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 0000000000000..28dbf75f5ada5 --- /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 0000000000000..c1c53fbdaebd8 --- /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 0000000000000..5369819d51292 --- /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 0000000000000..bd81498182030 --- /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 +} + +@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 0000000000000..72a488e70b2c9 --- /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 0000000000000..a6c76fe081b2d --- /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 +} + +@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@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 0000000000000..53f26f0433310 --- /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 +} + +@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 +}