diff options
Diffstat (limited to 'llvm/lib/Target/X86/X86InstrArithmetic.td')
-rw-r--r-- | llvm/lib/Target/X86/X86InstrArithmetic.td | 179 |
1 files changed, 173 insertions, 6 deletions
diff --git a/llvm/lib/Target/X86/X86InstrArithmetic.td b/llvm/lib/Target/X86/X86InstrArithmetic.td index 1e399a894490a..f7f22285bd15d 100644 --- a/llvm/lib/Target/X86/X86InstrArithmetic.td +++ b/llvm/lib/Target/X86/X86InstrArithmetic.td @@ -605,16 +605,16 @@ def invalid_node : SDNode<"<<invalid_node>>", SDTIntLeaf,[],"<<invalid_node>>">; def Xi8 : X86TypeInfo<i8, "b", GR8, loadi8, i8mem, - Imm8, i8imm, relocImm8_su, i8imm, invalid_node, + Imm8, i8imm, imm_su, i8imm, invalid_node, 0, OpSizeFixed, 0>; def Xi16 : X86TypeInfo<i16, "w", GR16, loadi16, i16mem, - Imm16, i16imm, relocImm16_su, i16i8imm, i16immSExt8_su, + Imm16, i16imm, imm_su, i16i8imm, i16immSExt8_su, 1, OpSize16, 0>; def Xi32 : X86TypeInfo<i32, "l", GR32, loadi32, i32mem, - Imm32, i32imm, relocImm32_su, i32i8imm, i32immSExt8_su, + Imm32, i32imm, imm_su, i32i8imm, i32immSExt8_su, 1, OpSize32, 0>; def Xi64 : X86TypeInfo<i64, "q", GR64, loadi64, i64mem, - Imm32S, i64i32imm, i64relocImmSExt32_su, i64i8imm, i64immSExt8_su, + Imm32S, i64i32imm, i64immSExt32_su, i64i8imm, i64immSExt8_su, 1, OpSizeFixed, 1>; /// ITy - This instruction base class takes the type info for the instruction. @@ -1217,6 +1217,146 @@ def : Pat<(store (X86adc_flag GR64:$src, (loadi64 addr:$dst), EFLAGS), addr:$dst), (ADC64mr addr:$dst, GR64:$src)>; +// Patterns for basic arithmetic ops with relocImm for the immediate field. +multiclass ArithBinOp_RF_relocImm_Pats<SDNode OpNodeFlag, SDNode OpNode> { + def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2), + (!cast<Instruction>(NAME#"8ri") GR8:$src1, relocImm8_su:$src2)>; + def : Pat<(OpNodeFlag GR16:$src1, i16relocImmSExt8_su:$src2), + (!cast<Instruction>(NAME#"16ri8") GR16:$src1, i16relocImmSExt8_su:$src2)>; + def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2), + (!cast<Instruction>(NAME#"16ri") GR16:$src1, relocImm16_su:$src2)>; + def : Pat<(OpNodeFlag GR32:$src1, i32relocImmSExt8_su:$src2), + (!cast<Instruction>(NAME#"32ri8") GR32:$src1, i32relocImmSExt8_su:$src2)>; + def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2), + (!cast<Instruction>(NAME#"32ri") GR32:$src1, relocImm32_su:$src2)>; + def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt8_su:$src2), + (!cast<Instruction>(NAME#"64ri8") GR64:$src1, i64relocImmSExt8_su:$src2)>; + def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2), + (!cast<Instruction>(NAME#"64ri32") GR64:$src1, i64relocImmSExt32_su:$src2)>; + + def : Pat<(store (OpNode (load addr:$dst), relocImm8_su:$src), addr:$dst), + (!cast<Instruction>(NAME#"8mi") addr:$dst, relocImm8_su:$src)>; + def : Pat<(store (OpNode (load addr:$dst), i16relocImmSExt8_su:$src), addr:$dst), + (!cast<Instruction>(NAME#"16mi8") addr:$dst, i16relocImmSExt8_su:$src)>; + def : Pat<(store (OpNode (load addr:$dst), relocImm16_su:$src), addr:$dst), + (!cast<Instruction>(NAME#"16mi") addr:$dst, relocImm16_su:$src)>; + def : Pat<(store (OpNode (load addr:$dst), i32relocImmSExt8_su:$src), addr:$dst), + (!cast<Instruction>(NAME#"32mi8") addr:$dst, i32relocImmSExt8_su:$src)>; + def : Pat<(store (OpNode (load addr:$dst), relocImm32_su:$src), addr:$dst), + (!cast<Instruction>(NAME#"32mi") addr:$dst, relocImm32_su:$src)>; + def : Pat<(store (OpNode (load addr:$dst), i64relocImmSExt8_su:$src), addr:$dst), + (!cast<Instruction>(NAME#"64mi8") addr:$dst, i64relocImmSExt8_su:$src)>; + def : Pat<(store (OpNode (load addr:$dst), i64relocImmSExt32_su:$src), addr:$dst), + (!cast<Instruction>(NAME#"64mi32") addr:$dst, i64relocImmSExt32_su:$src)>; +} + +multiclass ArithBinOp_RFF_relocImm_Pats<SDNode OpNodeFlag> { + def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2, EFLAGS), + (!cast<Instruction>(NAME#"8ri") GR8:$src1, relocImm8_su:$src2)>; + def : Pat<(OpNodeFlag GR16:$src1, i16relocImmSExt8_su:$src2, EFLAGS), + (!cast<Instruction>(NAME#"16ri8") GR16:$src1, i16relocImmSExt8_su:$src2)>; + def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2, EFLAGS), + (!cast<Instruction>(NAME#"16ri") GR16:$src1, relocImm16_su:$src2)>; + def : Pat<(OpNodeFlag GR32:$src1, i32relocImmSExt8_su:$src2, EFLAGS), + (!cast<Instruction>(NAME#"32ri8") GR32:$src1, i32relocImmSExt8_su:$src2)>; + def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2, EFLAGS), + (!cast<Instruction>(NAME#"32ri") GR32:$src1, relocImm32_su:$src2)>; + def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt8_su:$src2, EFLAGS), + (!cast<Instruction>(NAME#"64ri8") GR64:$src1, i64relocImmSExt8_su:$src2)>; + def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2, EFLAGS), + (!cast<Instruction>(NAME#"64ri32") GR64:$src1, i64relocImmSExt32_su:$src2)>; + + def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm8_su:$src, EFLAGS), addr:$dst), + (!cast<Instruction>(NAME#"8mi") addr:$dst, relocImm8_su:$src)>; + def : Pat<(store (OpNodeFlag (load addr:$dst), i16relocImmSExt8_su:$src, EFLAGS), addr:$dst), + (!cast<Instruction>(NAME#"16mi8") addr:$dst, i16relocImmSExt8_su:$src)>; + def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm16_su:$src, EFLAGS), addr:$dst), + (!cast<Instruction>(NAME#"16mi") addr:$dst, relocImm16_su:$src)>; + def : Pat<(store (OpNodeFlag (load addr:$dst), i32relocImmSExt8_su:$src, EFLAGS), addr:$dst), + (!cast<Instruction>(NAME#"32mi8") addr:$dst, i32relocImmSExt8_su:$src)>; + def : Pat<(store (OpNodeFlag (load addr:$dst), relocImm32_su:$src, EFLAGS), addr:$dst), + (!cast<Instruction>(NAME#"32mi") addr:$dst, relocImm32_su:$src)>; + def : Pat<(store (OpNodeFlag (load addr:$dst), i64relocImmSExt8_su:$src, EFLAGS), addr:$dst), + (!cast<Instruction>(NAME#"64mi8") addr:$dst, i64relocImmSExt8_su:$src)>; + def : Pat<(store (OpNodeFlag (load addr:$dst), i64relocImmSExt32_su:$src, EFLAGS), addr:$dst), + (!cast<Instruction>(NAME#"64mi32") addr:$dst, i64relocImmSExt32_su:$src)>; +} + +multiclass ArithBinOp_F_relocImm_Pats<SDNode OpNodeFlag> { + def : Pat<(OpNodeFlag GR8:$src1, relocImm8_su:$src2), + (!cast<Instruction>(NAME#"8ri") GR8:$src1, relocImm8_su:$src2)>; + def : Pat<(OpNodeFlag GR16:$src1, i16relocImmSExt8_su:$src2), + (!cast<Instruction>(NAME#"16ri8") GR16:$src1, i16relocImmSExt8_su:$src2)>; + def : Pat<(OpNodeFlag GR16:$src1, relocImm16_su:$src2), + (!cast<Instruction>(NAME#"16ri") GR16:$src1, relocImm16_su:$src2)>; + def : Pat<(OpNodeFlag GR32:$src1, i32relocImmSExt8_su:$src2), + (!cast<Instruction>(NAME#"32ri8") GR32:$src1, i32relocImmSExt8_su:$src2)>; + def : Pat<(OpNodeFlag GR32:$src1, relocImm32_su:$src2), + (!cast<Instruction>(NAME#"32ri") GR32:$src1, relocImm32_su:$src2)>; + def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt8_su:$src2), + (!cast<Instruction>(NAME#"64ri8") GR64:$src1, i64relocImmSExt8_su:$src2)>; + def : Pat<(OpNodeFlag GR64:$src1, i64relocImmSExt32_su:$src2), + (!cast<Instruction>(NAME#"64ri32") GR64:$src1, i64relocImmSExt32_su:$src2)>; + + def : Pat<(OpNodeFlag (loadi8 addr:$src1), relocImm8_su:$src2), + (!cast<Instruction>(NAME#"8mi") addr:$src1, relocImm8_su:$src2)>; + def : Pat<(OpNodeFlag (loadi16 addr:$src1), i16relocImmSExt8_su:$src2), + (!cast<Instruction>(NAME#"16mi8") addr:$src1, i16relocImmSExt8_su:$src2)>; + def : Pat<(OpNodeFlag (loadi16 addr:$src1), relocImm16_su:$src2), + (!cast<Instruction>(NAME#"16mi") addr:$src1, relocImm16_su:$src2)>; + def : Pat<(OpNodeFlag (loadi32 addr:$src1), i32relocImmSExt8_su:$src2), + (!cast<Instruction>(NAME#"32mi8") addr:$src1, i32relocImmSExt8_su:$src2)>; + def : Pat<(OpNodeFlag (loadi32 addr:$src1), relocImm32_su:$src2), + (!cast<Instruction>(NAME#"32mi") addr:$src1, relocImm32_su:$src2)>; + def : Pat<(OpNodeFlag (loadi64 addr:$src1), i64relocImmSExt8_su:$src2), + (!cast<Instruction>(NAME#"64mi8") addr:$src1, i64relocImmSExt8_su:$src2)>; + def : Pat<(OpNodeFlag (loadi64 addr:$src1), i64relocImmSExt32_su:$src2), + (!cast<Instruction>(NAME#"64mi32") addr:$src1, i64relocImmSExt32_su:$src2)>; +} + +defm AND : ArithBinOp_RF_relocImm_Pats<X86and_flag, and>; +defm OR : ArithBinOp_RF_relocImm_Pats<X86or_flag, or>; +defm XOR : ArithBinOp_RF_relocImm_Pats<X86xor_flag, xor>; +defm ADD : ArithBinOp_RF_relocImm_Pats<X86add_flag, add>; +defm SUB : ArithBinOp_RF_relocImm_Pats<X86sub_flag, sub>; + +defm ADC : ArithBinOp_RFF_relocImm_Pats<X86adc_flag>; +defm SBB : ArithBinOp_RFF_relocImm_Pats<X86sbb_flag>; + +defm CMP : ArithBinOp_F_relocImm_Pats<X86cmp>; + +// ADC is commutable, but we can't indicate that to tablegen. So manually +// reverse the operands. +def : Pat<(X86adc_flag GR8:$src1, relocImm8_su:$src2, EFLAGS), + (ADC8ri relocImm8_su:$src2, GR8:$src1)>; +def : Pat<(X86adc_flag i16relocImmSExt8_su:$src2, GR16:$src1, EFLAGS), + (ADC16ri8 GR16:$src1, i16relocImmSExt8_su:$src2)>; +def : Pat<(X86adc_flag relocImm16_su:$src2, GR16:$src1, EFLAGS), + (ADC16ri GR16:$src1, relocImm16_su:$src2)>; +def : Pat<(X86adc_flag i32relocImmSExt8_su:$src2, GR32:$src1, EFLAGS), + (ADC32ri8 GR32:$src1, i32relocImmSExt8_su:$src2)>; +def : Pat<(X86adc_flag relocImm32_su:$src2, GR32:$src1, EFLAGS), + (ADC32ri GR32:$src1, relocImm32_su:$src2)>; +def : Pat<(X86adc_flag i64relocImmSExt8_su:$src2, GR64:$src1, EFLAGS), + (ADC64ri8 GR64:$src1, i64relocImmSExt8_su:$src2)>; +def : Pat<(X86adc_flag i64relocImmSExt32_su:$src2, GR64:$src1, EFLAGS), + (ADC64ri32 GR64:$src1, i64relocImmSExt32_su:$src2)>; + +def : Pat<(store (X86adc_flag relocImm8_su:$src, (load addr:$dst), EFLAGS), addr:$dst), + (ADC8mi addr:$dst, relocImm8_su:$src)>; +def : Pat<(store (X86adc_flag i16relocImmSExt8_su:$src, (load addr:$dst), EFLAGS), addr:$dst), + (ADC16mi8 addr:$dst, i16relocImmSExt8_su:$src)>; +def : Pat<(store (X86adc_flag relocImm16_su:$src, (load addr:$dst), EFLAGS), addr:$dst), + (ADC16mi addr:$dst, relocImm16_su:$src)>; +def : Pat<(store (X86adc_flag i32relocImmSExt8_su:$src, (load addr:$dst), EFLAGS), addr:$dst), + (ADC32mi8 addr:$dst, i32relocImmSExt8_su:$src)>; +def : Pat<(store (X86adc_flag relocImm32_su:$src, (load addr:$dst), EFLAGS), addr:$dst), + (ADC32mi addr:$dst, relocImm32_su:$src)>; +def : Pat<(store (X86adc_flag i64relocImmSExt8_su:$src, (load addr:$dst), EFLAGS), addr:$dst), + (ADC64mi8 addr:$dst, i64relocImmSExt8_su:$src)>; +def : Pat<(store (X86adc_flag i64relocImmSExt32_su:$src, (load addr:$dst), EFLAGS), addr:$dst), + (ADC64mi32 addr:$dst, i64relocImmSExt32_su:$src)>; + //===----------------------------------------------------------------------===// // Semantically, test instructions are similar like AND, except they don't // generate a result. From an encoding perspective, they are very different: @@ -1247,7 +1387,6 @@ let isCompare = 1 in { def TEST8ri : BinOpRI_F<0xF6, "test", Xi8 , X86testpat, MRM0r>; def TEST16ri : BinOpRI_F<0xF6, "test", Xi16, X86testpat, MRM0r>; def TEST32ri : BinOpRI_F<0xF6, "test", Xi32, X86testpat, MRM0r>; - let Predicates = [In64BitMode] in def TEST64ri32 : BinOpRI_F<0xF6, "test", Xi64, X86testpat, MRM0r>; def TEST8mi : BinOpMI_F<0xF6, "test", Xi8 , X86testpat, MRM0m>; @@ -1267,6 +1406,25 @@ let isCompare = 1 in { "{$src, %rax|rax, $src}">; } // isCompare +// Patterns to match a relocImm into the immediate field. +def : Pat<(X86testpat GR8:$src1, relocImm8_su:$src2), + (TEST8ri GR8:$src1, relocImm8_su:$src2)>; +def : Pat<(X86testpat GR16:$src1, relocImm16_su:$src2), + (TEST16ri GR16:$src1, relocImm16_su:$src2)>; +def : Pat<(X86testpat GR32:$src1, relocImm32_su:$src2), + (TEST32ri GR32:$src1, relocImm32_su:$src2)>; +def : Pat<(X86testpat GR64:$src1, i64relocImmSExt32_su:$src2), + (TEST64ri32 GR64:$src1, i64relocImmSExt32_su:$src2)>; + +def : Pat<(X86testpat (loadi8 addr:$src1), relocImm8_su:$src2), + (TEST8mi addr:$src1, relocImm8_su:$src2)>; +def : Pat<(X86testpat (loadi16 addr:$src1), relocImm16_su:$src2), + (TEST16mi addr:$src1, relocImm16_su:$src2)>; +def : Pat<(X86testpat (loadi32 addr:$src1), relocImm32_su:$src2), + (TEST32mi addr:$src1, relocImm32_su:$src2)>; +def : Pat<(X86testpat (loadi64 addr:$src1), i64relocImmSExt32_su:$src2), + (TEST64mi32 addr:$src1, i64relocImmSExt32_su:$src2)>; + //===----------------------------------------------------------------------===// // ANDN Instruction // @@ -1306,7 +1464,6 @@ let Predicates = [HasBMI], AddedComplexity = -6 in { multiclass bmi_mulx<string mnemonic, RegisterClass RC, X86MemOperand x86memop, X86FoldableSchedWrite sched> { let hasSideEffects = 0 in { - let isCommutable = 1 in def rr : I<0xF6, MRMSrcReg, (outs RC:$dst1, RC:$dst2), (ins RC:$src), !strconcat(mnemonic, "\t{$src, $dst2, $dst1|$dst1, $dst2, $src}"), []>, T8XD, VEX_4V, Sched<[sched, WriteIMulH]>; @@ -1314,7 +1471,17 @@ let hasSideEffects = 0 in { let mayLoad = 1 in def rm : I<0xF6, MRMSrcMem, (outs RC:$dst1, RC:$dst2), (ins x86memop:$src), !strconcat(mnemonic, "\t{$src, $dst2, $dst1|$dst1, $dst2, $src}"), + []>, T8XD, VEX_4V, Sched<[sched.Folded, WriteIMulH]>; + + // Pseudo instructions to be used when the low result isn't used. The + // instruction is defined to keep the high if both destinations are the same. + def Hrr : PseudoI<(outs RC:$dst), (ins RC:$src), + []>, Sched<[sched]>; + + let mayLoad = 1 in + def Hrm : PseudoI<(outs RC:$dst), (ins x86memop:$src), + []>, Sched<[sched.Folded]>; } } |