From 3543ac9ab52df77af55a2ebdeeddfb76aba15d29 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 20 Feb 2020 08:49:09 -0800 Subject: [PATCH] [X86] Rewrite LowerBRCOND to remove dead code and handle ISD::SETCC and overflow ops directly. There's a lot of old leftover code in LowerBRCOND. Especially the detecting or AND or OR of X86ISD::SETCC nodes. Those were needed before LegalizeDAG was changed to visit nodes before their operands. It also relied on reversing the output of LowerSETCC to find the flags producing node to use for the X86ISD::BRCOND node. Rather than using LowerSETCC this patch uses emitFlagsForSetcc to handle the integer ISD::SETCC case. This gives the flag producer and the comparison code to use directly. I've removed the addTest flag and just produce a X86ISD::BRCOND and return immediately. Floating point ISD::SETCC case is just an X86ISD::FCMP with special care for OEQ and UNE derived from the previous code. I've left f128 out so it will emit a test. And LowerSETCC will be called later to produce a libcall and X86ISD::SETCC. We have combines that can merge the test and X86ISD::SETCC. We need to handle two cases for overflow ops. Either they are used directly or they have a seteq 0 or setne 1 to invert the overflow. The old code did not handle the setne 1 case, but I think some other combines were making up for it. If we fail to find a condition, we'll wrap an AND with 1 on the original condition and tell emitFlagsForSetcc to emit a compare with 0. This will pickup the LowerAndToBT and or the EmitTest case. I kept the isTruncWithZeroHighBitsInput call, but we might be able to fold that in to emitFlagsForSetcc. Differential Revision: https://reviews.llvm.org/D74750 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 258 +++++++++----------------------- 1 file changed, 74 insertions(+), 184 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 9af50ff..aecf4bb 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -23102,163 +23102,44 @@ static bool isAndOrOfSetCCs(SDValue Op, unsigned &Opc) { Op.getOperand(1).hasOneUse()); } -/// Return true if node is an ISD::XOR of a X86ISD::SETCC and 1 and that the -/// SETCC node has a single use. -static bool isXor1OfSetCC(SDValue Op) { - if (Op.getOpcode() != ISD::XOR) - return false; - if (isOneConstant(Op.getOperand(1))) - return Op.getOperand(0).getOpcode() == X86ISD::SETCC && - Op.getOperand(0).hasOneUse(); - return false; -} - SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const { - bool addTest = true; SDValue Chain = Op.getOperand(0); SDValue Cond = Op.getOperand(1); SDValue Dest = Op.getOperand(2); SDLoc dl(Op); - SDValue CC; - bool Inverted = false; - if (Cond.getOpcode() == ISD::SETCC) { - // Check for setcc([su]{add,sub,mul}o == 0). - if (cast(Cond.getOperand(2))->get() == ISD::SETEQ && - isNullConstant(Cond.getOperand(1)) && - Cond.getOperand(0).getResNo() == 1 && - (Cond.getOperand(0).getOpcode() == ISD::SADDO || - Cond.getOperand(0).getOpcode() == ISD::UADDO || - Cond.getOperand(0).getOpcode() == ISD::SSUBO || - Cond.getOperand(0).getOpcode() == ISD::USUBO || - Cond.getOperand(0).getOpcode() == ISD::SMULO || - Cond.getOperand(0).getOpcode() == ISD::UMULO)) { - Inverted = true; - Cond = Cond.getOperand(0); - } else { - if (SDValue NewCond = LowerSETCC(Cond, DAG)) - Cond = NewCond; - } - } -#if 0 - // FIXME: LowerXALUO doesn't handle these!! - else if (Cond.getOpcode() == X86ISD::ADD || - Cond.getOpcode() == X86ISD::SUB || - Cond.getOpcode() == X86ISD::SMUL || - Cond.getOpcode() == X86ISD::UMUL) - Cond = LowerXALUO(Cond, DAG); -#endif + if (Cond.getOpcode() == ISD::SETCC && + Cond.getOperand(0).getValueType() != MVT::f128) { + SDValue LHS = Cond.getOperand(0); + SDValue RHS = Cond.getOperand(1); + ISD::CondCode CC = cast(Cond.getOperand(2))->get(); - // Look pass (and (setcc_carry (cmp ...)), 1). - if (Cond.getOpcode() == ISD::AND && - Cond.getOperand(0).getOpcode() == X86ISD::SETCC_CARRY && - isOneConstant(Cond.getOperand(1))) - Cond = Cond.getOperand(0); + // Special case for + // setcc([su]{add,sub,mul}o == 0) + // setcc([su]{add,sub,mul}o != 1) + if (ISD::isOverflowIntrOpRes(LHS) && + (CC == ISD::SETEQ || CC == ISD::SETNE) && + (isNullConstant(RHS) || isOneConstant(RHS))) { + SDValue Value, Overflow; + X86::CondCode X86Cond; + std::tie(Value, Overflow) = getX86XALUOOp(X86Cond, LHS.getValue(0), DAG); - // If condition flag is set by a X86ISD::CMP, then use it as the condition - // setting operand in place of the X86ISD::SETCC. - unsigned CondOpcode = Cond.getOpcode(); - if (CondOpcode == X86ISD::SETCC || - CondOpcode == X86ISD::SETCC_CARRY) { - CC = Cond.getOperand(0); + if (CC == ISD::SETEQ == isNullConstant(RHS)) + X86Cond = X86::GetOppositeBranchCondition(X86Cond); - SDValue Cmp = Cond.getOperand(1); - unsigned Opc = Cmp.getOpcode(); - // FIXME: WHY THE SPECIAL CASING OF LogicalCmp?? - if (isX86LogicalCmp(Cmp) || Opc == X86ISD::BT) { - Cond = Cmp; - addTest = false; - } else { - switch (cast(CC)->getZExtValue()) { - default: break; - case X86::COND_O: - case X86::COND_B: - // These can only come from an arithmetic instruction with overflow, - // e.g. SADDO, UADDO. - Cond = Cond.getOperand(1); - addTest = false; - break; - } + SDValue CCVal = DAG.getTargetConstant(X86Cond, dl, MVT::i8); + return DAG.getNode(X86ISD::BRCOND, dl, MVT::Other, Chain, Dest, CCVal, + Overflow); } - } - CondOpcode = Cond.getOpcode(); - if (CondOpcode == ISD::UADDO || CondOpcode == ISD::SADDO || - CondOpcode == ISD::USUBO || CondOpcode == ISD::SSUBO || - CondOpcode == ISD::UMULO || CondOpcode == ISD::SMULO) { - SDValue Value; - X86::CondCode X86Cond; - std::tie(Value, Cond) = getX86XALUOOp(X86Cond, Cond.getValue(0), DAG); - if (Inverted) - X86Cond = X86::GetOppositeBranchCondition(X86Cond); + if (LHS.getSimpleValueType().isInteger()) { + SDValue CCVal; + SDValue EFLAGS = emitFlagsForSetcc(LHS, RHS, CC, SDLoc(Cond), DAG, CCVal); + return DAG.getNode(X86ISD::BRCOND, dl, MVT::Other, Chain, Dest, CCVal, + EFLAGS); + } - CC = DAG.getTargetConstant(X86Cond, dl, MVT::i8); - addTest = false; - } else { - unsigned CondOpc; - if (Cond.hasOneUse() && isAndOrOfSetCCs(Cond, CondOpc)) { - SDValue Cmp = Cond.getOperand(0).getOperand(1); - if (CondOpc == ISD::OR) { - // Also, recognize the pattern generated by an FCMP_UNE. We can emit - // two branches instead of an explicit OR instruction with a - // separate test. - if (Cmp == Cond.getOperand(1).getOperand(1) && - isX86LogicalCmp(Cmp)) { - CC = Cond.getOperand(0).getOperand(0); - Chain = DAG.getNode(X86ISD::BRCOND, dl, Op.getValueType(), - Chain, Dest, CC, Cmp); - CC = Cond.getOperand(1).getOperand(0); - Cond = Cmp; - addTest = false; - } - } else { // ISD::AND - // Also, recognize the pattern generated by an FCMP_OEQ. We can emit - // two branches instead of an explicit AND instruction with a - // separate test. However, we only do this if this block doesn't - // have a fall-through edge, because this requires an explicit - // jmp when the condition is false. - if (Cmp == Cond.getOperand(1).getOperand(1) && - isX86LogicalCmp(Cmp) && - Op.getNode()->hasOneUse()) { - X86::CondCode CCode0 = - (X86::CondCode)Cond.getOperand(0).getConstantOperandVal(0); - CCode0 = X86::GetOppositeBranchCondition(CCode0); - CC = DAG.getTargetConstant(CCode0, dl, MVT::i8); - SDNode *User = *Op.getNode()->use_begin(); - // Look for an unconditional branch following this conditional branch. - // We need this because we need to reverse the successors in order - // to implement FCMP_OEQ. - if (User->getOpcode() == ISD::BR) { - SDValue FalseBB = User->getOperand(1); - SDNode *NewBR = - DAG.UpdateNodeOperands(User, User->getOperand(0), Dest); - assert(NewBR == User); - (void)NewBR; - Dest = FalseBB; - - Chain = DAG.getNode(X86ISD::BRCOND, dl, Op.getValueType(), Chain, - Dest, CC, Cmp); - X86::CondCode CCode1 = - (X86::CondCode)Cond.getOperand(1).getConstantOperandVal(0); - CCode1 = X86::GetOppositeBranchCondition(CCode1); - CC = DAG.getTargetConstant(CCode1, dl, MVT::i8); - Cond = Cmp; - addTest = false; - } - } - } - } else if (Cond.hasOneUse() && isXor1OfSetCC(Cond)) { - // Recognize for xorb (setcc), 1 patterns. The xor inverts the condition. - // It should be transformed during dag combiner except when the condition - // is set by a arithmetics with overflow node. - X86::CondCode CCode = - (X86::CondCode)Cond.getOperand(0).getConstantOperandVal(0); - CCode = X86::GetOppositeBranchCondition(CCode); - CC = DAG.getTargetConstant(CCode, dl, MVT::i8); - Cond = Cond.getOperand(0).getOperand(1); - addTest = false; - } else if (Cond.getOpcode() == ISD::SETCC && - cast(Cond.getOperand(2))->get() == ISD::SETOEQ) { + if (CC == ISD::SETOEQ) { // For FCMP_OEQ, we can emit // two branches instead of an explicit AND instruction with a // separate test. However, we only do this if this block doesn't @@ -23277,56 +23158,65 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const { (void)NewBR; Dest = FalseBB; - SDValue Cmp = DAG.getNode(X86ISD::FCMP, dl, MVT::i32, - Cond.getOperand(0), Cond.getOperand(1)); - CC = DAG.getTargetConstant(X86::COND_NE, dl, MVT::i8); - Chain = DAG.getNode(X86ISD::BRCOND, dl, Op.getValueType(), - Chain, Dest, CC, Cmp); - CC = DAG.getTargetConstant(X86::COND_P, dl, MVT::i8); - Cond = Cmp; - addTest = false; + SDValue Cmp = + DAG.getNode(X86ISD::FCMP, SDLoc(Cond), MVT::i32, LHS, RHS); + SDValue CCVal = DAG.getTargetConstant(X86::COND_NE, dl, MVT::i8); + Chain = DAG.getNode(X86ISD::BRCOND, dl, MVT::Other, Chain, Dest, + CCVal, Cmp); + CCVal = DAG.getTargetConstant(X86::COND_P, dl, MVT::i8); + return DAG.getNode(X86ISD::BRCOND, dl, MVT::Other, Chain, Dest, CCVal, + Cmp); } } - } else if (Cond.getOpcode() == ISD::SETCC && - cast(Cond.getOperand(2))->get() == ISD::SETUNE) { + } else if (CC == ISD::SETUNE) { // For FCMP_UNE, we can emit // two branches instead of an explicit OR instruction with a // separate test. - SDValue Cmp = DAG.getNode(X86ISD::FCMP, dl, MVT::i32, - Cond.getOperand(0), Cond.getOperand(1)); - CC = DAG.getTargetConstant(X86::COND_NE, dl, MVT::i8); - Chain = DAG.getNode(X86ISD::BRCOND, dl, Op.getValueType(), - Chain, Dest, CC, Cmp); - CC = DAG.getTargetConstant(X86::COND_P, dl, MVT::i8); - Cond = Cmp; - addTest = false; + SDValue Cmp = DAG.getNode(X86ISD::FCMP, SDLoc(Cond), MVT::i32, LHS, RHS); + SDValue CCVal = DAG.getTargetConstant(X86::COND_NE, dl, MVT::i8); + Chain = + DAG.getNode(X86ISD::BRCOND, dl, MVT::Other, Chain, Dest, CCVal, Cmp); + CCVal = DAG.getTargetConstant(X86::COND_P, dl, MVT::i8); + return DAG.getNode(X86ISD::BRCOND, dl, MVT::Other, Chain, Dest, CCVal, + Cmp); + } else { + X86::CondCode X86Cond = + TranslateX86CC(CC, dl, /*IsFP*/ true, LHS, RHS, DAG); + SDValue Cmp = DAG.getNode(X86ISD::FCMP, SDLoc(Cond), MVT::i32, LHS, RHS); + SDValue CCVal = DAG.getTargetConstant(X86Cond, dl, MVT::i8); + return DAG.getNode(X86ISD::BRCOND, dl, MVT::Other, Chain, Dest, CCVal, + Cmp); } } - if (addTest) { - // Look pass the truncate if the high bits are known zero. - if (isTruncWithZeroHighBitsInput(Cond, DAG)) - Cond = Cond.getOperand(0); + if (ISD::isOverflowIntrOpRes(Cond)) { + SDValue Value, Overflow; + X86::CondCode X86Cond; + std::tie(Value, Overflow) = getX86XALUOOp(X86Cond, Cond.getValue(0), DAG); - // We know the result of AND is compared against zero. Try to match - // it to BT. - if (Cond.getOpcode() == ISD::AND && Cond.hasOneUse()) { - SDValue BTCC; - if (SDValue BT = LowerAndToBT(Cond, ISD::SETNE, dl, DAG, BTCC)) { - CC = BTCC; - Cond = BT; - addTest = false; - } - } + SDValue CCVal = DAG.getTargetConstant(X86Cond, dl, MVT::i8); + return DAG.getNode(X86ISD::BRCOND, dl, MVT::Other, Chain, Dest, CCVal, + Overflow); } - if (addTest) { - X86::CondCode X86Cond = Inverted ? X86::COND_E : X86::COND_NE; - CC = DAG.getTargetConstant(X86Cond, dl, MVT::i8); - Cond = EmitTest(Cond, X86Cond, dl, DAG, Subtarget); - } - return DAG.getNode(X86ISD::BRCOND, dl, Op.getValueType(), - Chain, Dest, CC, Cond); + // Look past the truncate if the high bits are known zero. + if (isTruncWithZeroHighBitsInput(Cond, DAG)) + Cond = Cond.getOperand(0); + + EVT CondVT = Cond.getValueType(); + + // Add an AND with 1 if we don't already have one. + if (!(Cond.getOpcode() == ISD::AND && isOneConstant(Cond.getOperand(1)))) + Cond = + DAG.getNode(ISD::AND, dl, CondVT, Cond, DAG.getConstant(1, dl, CondVT)); + + SDValue LHS = Cond; + SDValue RHS = DAG.getConstant(0, dl, CondVT); + + SDValue CCVal; + SDValue EFLAGS = emitFlagsForSetcc(LHS, RHS, ISD::SETNE, dl, DAG, CCVal); + return DAG.getNode(X86ISD::BRCOND, dl, MVT::Other, Chain, Dest, CCVal, + EFLAGS); } // Lower dynamic stack allocation to _alloca call for Cygwin/Mingw targets. -- 2.7.4