diff options
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 72 | ||||
| -rw-r--r-- | llvm/test/CodeGen/X86/cmp.ll | 3 |
2 files changed, 51 insertions, 24 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 62972f58721..757fe86935c 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -18630,27 +18630,6 @@ static SDValue EmitTest(SDValue Op, unsigned X86CC, const SDLoc &dl, Opcode = X86ISD::ADD; NumOperands = 2; break; - case ISD::SHL: - case ISD::SRL: - // If we have a constant logical shift that's only used in a comparison - // against zero turn it into an equivalent AND. This allows turning it into - // a TEST instruction later. - if (ZeroCheck && Op->hasOneUse() && - isa<ConstantSDNode>(Op->getOperand(1)) && !hasNonFlagsUse(Op)) { - EVT VT = Op.getValueType(); - unsigned BitWidth = VT.getSizeInBits(); - unsigned ShAmt = Op->getConstantOperandVal(1); - if (ShAmt >= BitWidth) // Avoid undefined shifts. - break; - APInt Mask = ArithOp.getOpcode() == ISD::SRL - ? APInt::getHighBitsSet(BitWidth, BitWidth - ShAmt) - : APInt::getLowBitsSet(BitWidth, BitWidth - ShAmt); - if (!Mask.isSignedIntN(ShiftToAndMaxMaskWidth)) - break; - Op = DAG.getNode(ISD::AND, dl, VT, Op->getOperand(0), - DAG.getConstant(Mask, dl, VT)); - } - break; case ISD::AND: // If the primary 'and' result isn't used, don't bother using X86ISD::AND, @@ -39952,6 +39931,32 @@ static bool needCarryOrOverflowFlag(SDValue Flags) { return false; } +static bool onlyZeroFlagUsed(SDValue Flags) { + assert(Flags.getValueType() == MVT::i32 && "Unexpected VT!"); + + for (SDNode::use_iterator UI = Flags->use_begin(), UE = Flags->use_end(); + UI != UE; ++UI) { + SDNode *User = *UI; + + unsigned CCOpNo; + switch (User->getOpcode()) { + default: + // Be conservative. + return false; + case X86ISD::SETCC: CCOpNo = 0; break; + case X86ISD::SETCC_CARRY: CCOpNo = 0; break; + case X86ISD::BRCOND: CCOpNo = 2; break; + case X86ISD::CMOV: CCOpNo = 2; break; + } + + X86::CondCode CC = (X86::CondCode)User->getConstantOperandVal(CCOpNo); + if (CC != X86::COND_E && CC != X86::COND_NE) + return false; + } + + return true; +} + static SDValue combineCMP(SDNode *N, SelectionDAG &DAG) { // Only handle test patterns. if (!isNullConstant(N->getOperand(1))) @@ -39961,9 +39966,33 @@ static SDValue combineCMP(SDNode *N, SelectionDAG &DAG) { // and use its flags directly. // TODO: Maybe we should try promoting compares that only use the zero flag // first if we can prove the upper bits with computeKnownBits? + SDLoc dl(N); SDValue Op = N->getOperand(0); EVT VT = Op.getValueType(); + // If we have a constant logical shift that's only used in a comparison + // against zero turn it into an equivalent AND. This allows turning it into + // a TEST instruction later. + if ((Op.getOpcode() == ISD::SRL || Op.getOpcode() == ISD::SHL) && + Op.hasOneUse() && isa<ConstantSDNode>(Op.getOperand(1)) && + onlyZeroFlagUsed(SDValue(N, 0))) { + EVT VT = Op.getValueType(); + unsigned BitWidth = VT.getSizeInBits(); + unsigned ShAmt = Op.getConstantOperandVal(1); + if (ShAmt < BitWidth) { // Avoid undefined shifts. + APInt Mask = Op.getOpcode() == ISD::SRL + ? APInt::getHighBitsSet(BitWidth, BitWidth - ShAmt) + : APInt::getLowBitsSet(BitWidth, BitWidth - ShAmt); + if (Mask.isSignedIntN(32)) { + Op = DAG.getNode(ISD::AND, dl, VT, Op.getOperand(0), + DAG.getConstant(Mask, dl, VT)); + return DAG.getNode(X86ISD::CMP, dl, MVT::i32, Op, + DAG.getConstant(0, dl, VT)); + } + } + } + + // Look for a truncate with a single use. if (Op.getOpcode() != ISD::TRUNCATE || !Op.hasOneUse()) return SDValue(); @@ -40001,7 +40030,6 @@ static SDValue combineCMP(SDNode *N, SelectionDAG &DAG) { } // We found an op we can narrow. Truncate its inputs. - SDLoc dl(N); SDValue Op0 = DAG.getNode(ISD::TRUNCATE, dl, VT, Op.getOperand(0)); SDValue Op1 = DAG.getNode(ISD::TRUNCATE, dl, VT, Op.getOperand(1)); diff --git a/llvm/test/CodeGen/X86/cmp.ll b/llvm/test/CodeGen/X86/cmp.ll index a12d599a1de..2747eca6b9a 100644 --- a/llvm/test/CodeGen/X86/cmp.ll +++ b/llvm/test/CodeGen/X86/cmp.ll @@ -469,9 +469,8 @@ entry: define { i64, i64 } @pr39968(i64, i64, i32) { ; CHECK-LABEL: pr39968: ; CHECK: # %bb.0: -; CHECK-NEXT: andl $64, %edx # encoding: [0x83,0xe2,0x40] ; CHECK-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] -; CHECK-NEXT: shrl $6, %edx # encoding: [0xc1,0xea,0x06] +; CHECK-NEXT: testb $64, %dl # encoding: [0xf6,0xc2,0x40] ; CHECK-NEXT: cmovneq %rdi, %rsi # encoding: [0x48,0x0f,0x45,0xf7] ; CHECK-NEXT: cmovneq %rdi, %rax # encoding: [0x48,0x0f,0x45,0xc7] ; CHECK-NEXT: movq %rsi, %rdx # encoding: [0x48,0x89,0xf2] |

