diff options
| author | Craig Topper <craig.topper@intel.com> | 2018-12-24 01:10:13 +0000 |
|---|---|---|
| committer | Craig Topper <craig.topper@intel.com> | 2018-12-24 01:10:13 +0000 |
| commit | e8c50fc6afa235a8737ce92a2d579eefd2b82718 (patch) | |
| tree | 4d2007e1f92f5dd23ab38e85a32317f82a333813 /llvm/lib | |
| parent | 2ea656f3aba465411a67287e968a00f571c8e0c3 (diff) | |
| download | bcm5719-llvm-e8c50fc6afa235a8737ce92a2d579eefd2b82718.tar.gz bcm5719-llvm-e8c50fc6afa235a8737ce92a2d579eefd2b82718.zip | |
[X86] Remove the ANDN check from EmitTest.
Remove the TESTmr isel patterns and add another postprocessing combine for TESTrr+ANDrm->TESTmr. We already have a postprocessing combine for TESTrr+ANDrr->TESTrr. With this we can give ANDN a chance to match first. And clean it up during post processing if we ended up with just a regular AND.
This is another step towards my plan to gut EmitTest and do more flag handling during isel matching or by using optimizeCompare.
llvm-svn: 350038
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 24 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 79 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86InstrArithmetic.td | 10 |
3 files changed, 67 insertions, 46 deletions
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp index 0274867459d..90fc39f97a4 100644 --- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -921,6 +921,30 @@ void X86DAGToDAGISel::PostprocessISelDAG() { MadeChange = true; continue; } + if (N0Opc == X86::AND8rm || N0Opc == X86::AND16rm || + N0Opc == X86::AND32rm || N0Opc == X86::AND64rm) { + unsigned NewOpc; + switch (N0Opc) { + case X86::AND8rm: NewOpc = X86::TEST8mr; break; + case X86::AND16rm: NewOpc = X86::TEST16mr; break; + case X86::AND32rm: NewOpc = X86::TEST32mr; break; + case X86::AND64rm: NewOpc = X86::TEST64mr; break; + } + + // Need to swap the memory and register operand. + SDValue Ops[] = { And.getOperand(1), + And.getOperand(2), + And.getOperand(3), + And.getOperand(4), + And.getOperand(5), + And.getOperand(0), + And.getOperand(6) /* Chain */ }; + MachineSDNode *Test = CurDAG->getMachineNode(NewOpc, SDLoc(N), + MVT::i32, MVT::Other, Ops); + ReplaceUses(N, Test); + MadeChange = true; + continue; + } } // Attempt to remove vectors moves that were inserted to zero upper bits. diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 6e2a592c80b..c2230ee598c 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -18696,57 +18696,52 @@ static SDValue EmitTest(SDValue Op, unsigned X86CC, const SDLoc &dl, SDValue Op0 = ArithOp->getOperand(0); SDValue Op1 = ArithOp->getOperand(1); EVT VT = ArithOp.getValueType(); - bool isAndn = isBitwiseNot(Op0) || isBitwiseNot(Op1); - bool isLegalAndnType = VT == MVT::i32 || VT == MVT::i64; - bool isProperAndn = isAndn && isLegalAndnType && Subtarget.hasBMI(); - - // If we cannot select an ANDN instruction, check if we can replace - // AND+IMM64 with a shift before giving up. This is possible for masks - // like 0xFF000000 or 0x00FFFFFF and if we care only about the zero flag. - if (!isProperAndn) { - if (!ZeroCheck) - break; - // And with cosntant should be canonicalized unless we're dealing - // with opaque constants. - assert((!isa<ConstantSDNode>(Op0) || - (isa<ConstantSDNode>(Op1) && - (cast<ConstantSDNode>(Op0)->isOpaque() || - cast<ConstantSDNode>(Op1)->isOpaque()))) && - "AND node isn't canonicalized"); - auto *CN = dyn_cast<ConstantSDNode>(Op1); - if (!CN) - break; + // Check if we can replace AND+IMM64 with a shift before giving up. This + // is possible for masks/ like 0xFF000000 or 0x00FFFFFF and if we care + // only about the zero flag. + if (!ZeroCheck) + break; - const APInt &Mask = CN->getAPIntValue(); - if (Mask.isSignedIntN(ShiftToAndMaxMaskWidth)) - break; // Prefer TEST instruction. + // And with constant should be canonicalized unless we're dealing + // with opaque constants. + assert((!isa<ConstantSDNode>(Op0) || + (isa<ConstantSDNode>(Op1) && + (cast<ConstantSDNode>(Op0)->isOpaque() || + cast<ConstantSDNode>(Op1)->isOpaque()))) && + "AND node isn't canonicalized"); + auto *CN = dyn_cast<ConstantSDNode>(Op1); + if (!CN) + break; - unsigned BitWidth = Mask.getBitWidth(); - unsigned LeadingOnes = Mask.countLeadingOnes(); - unsigned TrailingZeros = Mask.countTrailingZeros(); + const APInt &Mask = CN->getAPIntValue(); + if (Mask.isSignedIntN(ShiftToAndMaxMaskWidth)) + break; // Prefer TEST instruction. - if (LeadingOnes + TrailingZeros == BitWidth) { - assert(TrailingZeros < VT.getSizeInBits() && - "Shift amount should be less than the type width"); - SDValue ShAmt = DAG.getConstant(TrailingZeros, dl, MVT::i8); - Op = DAG.getNode(ISD::SRL, dl, VT, Op0, ShAmt); - break; - } + unsigned BitWidth = Mask.getBitWidth(); + unsigned LeadingOnes = Mask.countLeadingOnes(); + unsigned TrailingZeros = Mask.countTrailingZeros(); - unsigned LeadingZeros = Mask.countLeadingZeros(); - unsigned TrailingOnes = Mask.countTrailingOnes(); + if (LeadingOnes + TrailingZeros == BitWidth) { + assert(TrailingZeros < VT.getSizeInBits() && + "Shift amount should be less than the type width"); + SDValue ShAmt = DAG.getConstant(TrailingZeros, dl, MVT::i8); + Op = DAG.getNode(ISD::SRL, dl, VT, Op0, ShAmt); + break; + } - if (LeadingZeros + TrailingOnes == BitWidth) { - assert(LeadingZeros < VT.getSizeInBits() && - "Shift amount should be less than the type width"); - SDValue ShAmt = DAG.getConstant(LeadingZeros, dl, MVT::i8); - Op = DAG.getNode(ISD::SHL, dl, VT, Op0, ShAmt); - break; - } + unsigned LeadingZeros = Mask.countLeadingZeros(); + unsigned TrailingOnes = Mask.countTrailingOnes(); + if (LeadingZeros + TrailingOnes == BitWidth) { + assert(LeadingZeros < VT.getSizeInBits() && + "Shift amount should be less than the type width"); + SDValue ShAmt = DAG.getConstant(LeadingZeros, dl, MVT::i8); + Op = DAG.getNode(ISD::SHL, dl, VT, Op0, ShAmt); break; } + + break; } LLVM_FALLTHROUGH; case ISD::SUB: diff --git a/llvm/lib/Target/X86/X86InstrArithmetic.td b/llvm/lib/Target/X86/X86InstrArithmetic.td index 02379af4b4d..9b9e75ce9e1 100644 --- a/llvm/lib/Target/X86/X86InstrArithmetic.td +++ b/llvm/lib/Target/X86/X86InstrArithmetic.td @@ -1221,10 +1221,12 @@ let isCompare = 1 in { def TEST64rr : BinOpRR_F<0x84, "test", Xi64, null_frag>; } // isCommutable - def TEST8mr : BinOpMR_F<0x84, "test", Xi8 , X86testpat>; - def TEST16mr : BinOpMR_F<0x84, "test", Xi16, X86testpat>; - def TEST32mr : BinOpMR_F<0x84, "test", Xi32, X86testpat>; - def TEST64mr : BinOpMR_F<0x84, "test", Xi64, X86testpat>; + let hasSideEffects = 0, mayLoad = 1 in { + def TEST8mr : BinOpMR_F<0x84, "test", Xi8 , null_frag>; + def TEST16mr : BinOpMR_F<0x84, "test", Xi16, null_frag>; + def TEST32mr : BinOpMR_F<0x84, "test", Xi32, null_frag>; + def TEST64mr : BinOpMR_F<0x84, "test", Xi64, null_frag>; + } def TEST8ri : BinOpRI_F<0xF6, "test", Xi8 , X86testpat, MRM0r>; def TEST16ri : BinOpRI_F<0xF6, "test", Xi16, X86testpat, MRM0r>; |

