From 54a11176f6a5e07e243f1d87ba19ac3f4681976b Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 14 Oct 2011 07:06:56 +0000 Subject: [PATCH] Add X86 ANDN instruction. Including instruction selection. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141947 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelLowering.cpp | 20 +++++++++++++++++++- lib/Target/X86/X86ISelLowering.h | 2 ++ lib/Target/X86/X86InstrArithmetic.td | 20 +++++++++++++++++++- lib/Target/X86/X86InstrInfo.td | 1 + test/CodeGen/X86/bmi.ll | 15 +++++++++++++++ test/MC/Disassembler/X86/simple-tests.txt | 12 ++++++++++++ test/MC/Disassembler/X86/x86-32.txt | 12 ++++++++++++ utils/TableGen/X86RecognizableInstr.cpp | 2 ++ 8 files changed, 82 insertions(+), 2 deletions(-) diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index f85c201d01c..a3e4692860a 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -10702,6 +10702,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { case X86ISD::OR: return "X86ISD::OR"; case X86ISD::XOR: return "X86ISD::XOR"; case X86ISD::AND: return "X86ISD::AND"; + case X86ISD::ANDN: return "X86ISD::ANDN"; case X86ISD::MUL_IMM: return "X86ISD::MUL_IMM"; case X86ISD::PTEST: return "X86ISD::PTEST"; case X86ISD::TESTP: return "X86ISD::TESTP"; @@ -13295,11 +13296,28 @@ static SDValue PerformAndCombine(SDNode *N, SelectionDAG &DAG, if (R.getNode()) return R; + EVT VT = N->getValueType(0); + + // Create ANDN instructions + if (Subtarget->hasBMI() && (VT == MVT::i32 || VT == MVT::i64)) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + DebugLoc DL = N->getDebugLoc(); + + // Check LHS for not + if (N0.getOpcode() == ISD::XOR && isAllOnes(N0.getOperand(1))) + return DAG.getNode(X86ISD::ANDN, DL, VT, N0.getOperand(0), N1); + // Check RHS for not + if (N1.getOpcode() == ISD::XOR && isAllOnes(N1.getOperand(1))) + return DAG.getNode(X86ISD::ANDN, DL, VT, N1.getOperand(0), N0); + + return SDValue(); + } + // Want to form ANDNP nodes: // 1) In the hopes of then easily combining them with OR and AND nodes // to form PBLEND/PSIGN. // 2) To match ANDN packed intrinsics - EVT VT = N->getValueType(0); if (VT != MVT::v2i64 && VT != MVT::v4i64) return SDValue(); diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index 90255b554ec..342a5e61754 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -228,6 +228,8 @@ namespace llvm { ADD, SUB, ADC, SBB, SMUL, INC, DEC, OR, XOR, AND, + ANDN, // ANDN - Bitwise AND NOT with FLAGS results. + UMUL, // LOW, HI, FLAGS = umul LHS, RHS // MUL_IMM - X86 specific multiply by immediate. diff --git a/lib/Target/X86/X86InstrArithmetic.td b/lib/Target/X86/X86InstrArithmetic.td index f6ed722c071..74b647a4f6b 100644 --- a/lib/Target/X86/X86InstrArithmetic.td +++ b/lib/Target/X86/X86InstrArithmetic.td @@ -1151,5 +1151,23 @@ let Defs = [EFLAGS] in { let isPseudo = 1 in def TEST8ri_NOREX : I<0, Pseudo, (outs), (ins GR8_NOREX:$src, i8imm:$mask), "", []>; -} +} +//===----------------------------------------------------------------------===// +// ANDN Instruction +// +multiclass bmi_andn { + def rr : I<0xF2, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, RC:$src2), + !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), + [(set RC:$dst, EFLAGS, (X86andn_flag RC:$src1, RC:$src2))]>; + def rm : I<0xF2, MRMSrcMem, (outs RC:$dst), (ins RC:$src1, x86memop:$src2), + !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), + [(set RC:$dst, EFLAGS, + (X86andn_flag RC:$src1, (ld_frag addr:$src2)))]>; +} + +let Predicates = [HasBMI], Defs = [EFLAGS] in { + defm ANDN32 : bmi_andn<"andn{l}", GR32, i32mem, loadi32>, T8, VEX_4V; + defm ANDN64 : bmi_andn<"andn{q}", GR64, i64mem, loadi64>, T8, VEX_4V, VEX_W; +} diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index cc358feb97e..d54bf275c04 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -224,6 +224,7 @@ def X86xor_flag : SDNode<"X86ISD::XOR", SDTBinaryArithWithFlags, [SDNPCommutative]>; def X86and_flag : SDNode<"X86ISD::AND", SDTBinaryArithWithFlags, [SDNPCommutative]>; +def X86andn_flag : SDNode<"X86ISD::ANDN", SDTBinaryArithWithFlags>; def X86mul_imm : SDNode<"X86ISD::MUL_IMM", SDTIntBinOp>; diff --git a/test/CodeGen/X86/bmi.ll b/test/CodeGen/X86/bmi.ll index e0d1b583aa9..88c09e3acdc 100644 --- a/test/CodeGen/X86/bmi.ll +++ b/test/CodeGen/X86/bmi.ll @@ -36,3 +36,18 @@ define i8 @t4(i8 %x) nounwind { declare i8 @llvm.cttz.i8(i8) nounwind readnone +define i32 @andn32(i32 %x, i32 %y) nounwind readnone { + %tmp1 = xor i32 %x, -1 + %tmp2 = and i32 %y, %tmp1 + ret i32 %tmp2 +; CHECK: andn32: +; CHECK: andnl +} + +define i64 @andn64(i64 %x, i64 %y) nounwind readnone { + %tmp1 = xor i64 %x, -1 + %tmp2 = and i64 %tmp1, %y + ret i64 %tmp2 +; CHECK: andn64: +; CHECK: andnq +} diff --git a/test/MC/Disassembler/X86/simple-tests.txt b/test/MC/Disassembler/X86/simple-tests.txt index 8ca3015c2cd..2dc918cb0dc 100644 --- a/test/MC/Disassembler/X86/simple-tests.txt +++ b/test/MC/Disassembler/X86/simple-tests.txt @@ -506,3 +506,15 @@ # CHECK: tzcntq %rax, %rax 0xf3 0x48 0x0f 0xbc 0xc0 + +# CHECK: andnl %ecx, %r15d, %eax +0xc4 0xe2 0x00 0xf2 0xc1 + +# CHECK: andnq %rax, %r15, %rax +0xc4 0xe2 0x80 0xf2 0xc0 + +# CHECK: andnl (%rax), %r15d, %eax +0xc4 0xe2 0x00 0xf2 0x00 + +# CHECK: andnq (%rax), %r15, %rax +0xc4 0xe2 0x80 0xf2 0x00 diff --git a/test/MC/Disassembler/X86/x86-32.txt b/test/MC/Disassembler/X86/x86-32.txt index e58356bd432..c4437ba35d7 100644 --- a/test/MC/Disassembler/X86/x86-32.txt +++ b/test/MC/Disassembler/X86/x86-32.txt @@ -483,3 +483,15 @@ # CHECK: tzcntw %ax, %ax 0x66 0xf3 0x0f 0xbc 0xc0 + +# CHECK: andnl %ecx, %edi, %eax +0xc4 0xe2 0x00 0xf2 0xc1 + +# CHECK: andnl (%eax), %edi, %eax +0xc4 0xe2 0x00 0xf2 0x00 + +# CHECK: andnl %ecx, %edi, %eax +0xc4 0xe2 0x80 0xf2 0xc1 + +# CHECK: andnl (%eax), %edi, %eax +0xc4 0xe2 0x80 0xf2 0x00 diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index e7092c762c4..cae82374924 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -1142,6 +1142,8 @@ OperandEncoding RecognizableInstr::roRegisterEncodingFromString OperandEncoding RecognizableInstr::vvvvRegisterEncodingFromString (const std::string &s, bool hasOpSizePrefix) { + ENCODING("GR32", ENCODING_VVVV) + ENCODING("GR64", ENCODING_VVVV) ENCODING("FR32", ENCODING_VVVV) ENCODING("FR64", ENCODING_VVVV) ENCODING("VR128", ENCODING_VVVV)