Index: lib/CodeGen/SelectionDAG/TargetLowering.cpp =================================================================== --- lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -1200,6 +1200,32 @@ return CN->isNullValue(); } +// setcc (setcc), [0|1], [eq|ne] -> setcc +static SDValue setCCSetCCCombine(const TargetLowering *TLI, + TargetLowering::DAGCombinerInfo &DCI, + SDLoc dl, + SDValue N0, const ConstantSDNode *N1C, + ISD::CondCode Cond) { + SelectionDAG &DAG = DCI.DAG; + EVT VT = N0.getValueType(); + + if (!TLI->isTypeLegal(VT) || !VT.bitsLE(N0.getValueType())) + return SDValue(); + + bool TrueWhenTrue = (Cond == ISD::SETEQ) ^ (N1C->getAPIntValue() != 1); + if (TrueWhenTrue) + return DAG.getNode(ISD::TRUNCATE, dl, VT, N0); + + // Invert the condition. + ISD::CondCode CC = cast(N0.getOperand(2))->get(); + CC = ISD::getSetCCInverse(CC, N0.getOperand(0).getValueType().isInteger()); + if (DCI.isBeforeLegalizeOps() || + TLI->isCondCodeLegal(CC, N0.getOperand(0).getSimpleValueType())) + return DAG.getSetCC(dl, VT, N0.getOperand(0), N0.getOperand(1), CC); + + return SDValue(); +} + /// SimplifySetCC - Try to simplify a setcc built with the specified operands /// and cc. If it is unable to simplify it, return a null SDValue. SDValue @@ -1462,19 +1488,19 @@ Cond); } else if ((N1C->isNullValue() || N1C->getAPIntValue() == 1) && (Cond == ISD::SETEQ || Cond == ISD::SETNE)) { - // SETCC (SETCC), [0|1], [EQ|NE] -> SETCC - if (N0.getOpcode() == ISD::SETCC && - isTypeLegal(VT) && VT.bitsLE(N0.getValueType())) { - bool TrueWhenTrue = (Cond == ISD::SETEQ) ^ (N1C->getAPIntValue() != 1); - if (TrueWhenTrue) - return DAG.getNode(ISD::TRUNCATE, dl, VT, N0); - // Invert the condition. - ISD::CondCode CC = cast(N0.getOperand(2))->get(); - CC = ISD::getSetCCInverse(CC, - N0.getOperand(0).getValueType().isInteger()); - if (DCI.isBeforeLegalizeOps() || - isCondCodeLegal(CC, N0.getOperand(0).getSimpleValueType())) - return DAG.getSetCC(dl, VT, N0.getOperand(0), N0.getOperand(1), CC); + if (N0.getOpcode() == ISD::SETCC) { + // setcc (setcc), [0|1], [eq|ne] -> setcc + SDValue Ret = setCCSetCCCombine(this, DCI, dl, N0, N1C, Cond); + if (Ret) + return Ret; + } else if (N0.getOpcode() == ISD::SIGN_EXTEND) { + // setcc (sext (setcc)), [0|1], [eq|ne] -> setcc + SDValue N00 = N0.getOperand(0); + if (N00.getOpcode() == ISD::SETCC) { + SDValue Ret = setCCSetCCCombine(this, DCI, dl, N00, N1C, Cond); + if (Ret) + return Ret; + } } if ((N0.getOpcode() == ISD::XOR || Index: lib/Target/R600/SIISelLowering.cpp =================================================================== --- lib/Target/R600/SIISelLowering.cpp +++ lib/Target/R600/SIISelLowering.cpp @@ -1237,30 +1237,10 @@ DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; SDLoc DL(N); - EVT VT = N->getValueType(0); switch (N->getOpcode()) { - default: return AMDGPUTargetLowering::PerformDAGCombine(N, DCI); - case ISD::SETCC: { - SDValue Arg0 = N->getOperand(0); - SDValue Arg1 = N->getOperand(1); - SDValue CC = N->getOperand(2); - ConstantSDNode * C = nullptr; - ISD::CondCode CCOp = dyn_cast(CC)->get(); - - // i1 setcc (sext(i1), 0, setne) -> i1 setcc(i1, 0, setne) - if (VT == MVT::i1 - && Arg0.getOpcode() == ISD::SIGN_EXTEND - && Arg0.getOperand(0).getValueType() == MVT::i1 - && (C = dyn_cast(Arg1)) - && C->isNullValue() - && CCOp == ISD::SETNE) { - return SimplifySetCC(VT, Arg0.getOperand(0), - DAG.getConstant(0, MVT::i1), CCOp, true, DCI, DL); - } - break; - } - + default: + return AMDGPUTargetLowering::PerformDAGCombine(N, DCI); case AMDGPUISD::CVT_F32_UBYTE0: case AMDGPUISD::CVT_F32_UBYTE1: case AMDGPUISD::CVT_F32_UBYTE2: Index: test/CodeGen/R600/setcc-opt.ll =================================================================== --- test/CodeGen/R600/setcc-opt.ll +++ test/CodeGen/R600/setcc-opt.ll @@ -13,3 +13,17 @@ store i1 %icmp1, i1 addrspace(1)* %out ret void } + +; SI-LABEL: @sext_bool_icmp_eq +; SI: V_CMP_EQ_I32 +; SI-NEXT: V_CNDMASK_B32 +; SI-NOT: CMP +; SI-NOT: CNDMASK +; SI: S_ENDPGM +define void @sext_bool_icmp_eq(i1 addrspace(1)* %out, i32 %a, i32 %b) nounwind { + %icmp0 = icmp eq i32 %a, %b + %ext = sext i1 %icmp0 to i32 + %icmp1 = icmp eq i32 %ext, 1 + store i1 %icmp1, i1 addrspace(1)* %out + ret void +}