Index: llvm/lib/Target/PowerPC/P9InstrResources.td =================================================================== --- llvm/lib/Target/PowerPC/P9InstrResources.td +++ llvm/lib/Target/PowerPC/P9InstrResources.td @@ -111,11 +111,11 @@ (instregex "CNT(L|T)Z(D|W)(8)?(o)?$"), (instregex "POPCNT(D|W)$"), (instregex "CMPB(8)?$"), + (instregex "SETB(8)?$"), XSTDIVDP, XSTSQRTDP, XSXSIGDP, XSCVSPDPN, - SETB, BPERMD )>; Index: llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -81,6 +81,8 @@ "Number of logical ops on i1 values calculated in GPR."); STATISTIC(OmittedForNonExtendUses, "Number of compares not eliminated as they have non-extending uses."); +STATISTIC(NumP9Setb, + "Number of compares lowered to setb"); // FIXME: Remove this once the bug has been fixed! cl::opt ANDIGlueBug("expose-ppc-andi-glue-bug", @@ -4095,6 +4097,146 @@ llvm_unreachable("Unsupported vector data type for flipSignBit"); } +static bool mayUseP9Setb(SDNode *N, const ISD::CondCode &CC, SelectionDAG *DAG, + bool &NeedSwapOps, bool &IsUnCmp) { + + assert(N->getOpcode() == ISD::SELECT_CC && "Expecting a SELECT_CC here."); + + SDValue LHS = N->getOperand(0); + SDValue RHS = N->getOperand(1); + SDValue TrueRes = N->getOperand(2); + SDValue FalseRes = N->getOperand(3); + ConstantSDNode *TrueConst = dyn_cast(TrueRes); + if (!TrueConst) + return false; + + assert((N->getSimpleValueType(0) == MVT::i64 || + N->getSimpleValueType(0) == MVT::i32) && + "Expecting either i64 or i32 here."); + + // We are looking for any of: + // (select_cc lhs, rhs, 1, (sext (setcc [lr]hs, [lr]hs, cc2)), cc1) + // (select_cc lhs, rhs, -1, (zext (setcc [lr]hs, [lr]hs, cc2)), cc1) + // (select_cc lhs, rhs, 0, (select_cc [lr]hs, [lr]hs, 1, -1, cc2), seteq) + // (select_cc lhs, rhs, 0, (select_cc [lr]hs, [lr]hs, -1, 1, cc2), seteq) + int64_t TrueResVal = TrueConst->getSExtValue(); + if ((TrueResVal < -1 || TrueResVal > 1) || + (TrueResVal == -1 && FalseRes.getOpcode() != ISD::ZERO_EXTEND) || + (TrueResVal == 1 && FalseRes.getOpcode() != ISD::SIGN_EXTEND) || + (TrueResVal == 0 && + (FalseRes.getOpcode() != ISD::SELECT_CC || CC != ISD::SETEQ))) + return false; + + bool InnerIsSel = FalseRes.getOpcode() == ISD::SELECT_CC; + SDValue SetOrSelCC = InnerIsSel ? FalseRes : FalseRes.getOperand(0); + if (SetOrSelCC.getOpcode() != ISD::SETCC && + SetOrSelCC.getOpcode() != ISD::SELECT_CC) + return false; + + // Without this setb optimization, the outer SELECT_CC will be manually + // selected to SELECT_CC_I4/SELECT_CC_I8 Pseudo, then expand-isel-pseudos pass + // transforms pseduo instruction to isel instruction. When there are more than + // one use for result like zext/sext, with current optimization we only see + // isel is replaced by setb but can't see any significant gain. Since + // setb has longer latency than original isel, we should avoid this. Another + // point is that setb requires comparison always kept, it can break the + // oppotunity to get the comparison away if we have in future. + if (!SetOrSelCC.hasOneUse() || (!InnerIsSel && !FalseRes.hasOneUse())) + return false; + + SDValue InnerLHS = SetOrSelCC.getOperand(0); + SDValue InnerRHS = SetOrSelCC.getOperand(1); + ISD::CondCode InnerCC = + cast(SetOrSelCC.getOperand(InnerIsSel ? 4 : 2))->get(); + // If the inner comparison is a select_cc, make sure the true/false values are + // 1/-1 and canonicalize it if needed. + if (InnerIsSel) { + ConstantSDNode *SelCCTrueConst = + dyn_cast(SetOrSelCC.getOperand(2)); + ConstantSDNode *SelCCFalseConst = + dyn_cast(SetOrSelCC.getOperand(3)); + if (!SelCCTrueConst || !SelCCFalseConst) + return false; + int64_t SelCCTVal = SelCCTrueConst->getSExtValue(); + int64_t SelCCFVal = SelCCFalseConst->getSExtValue(); + // The values must be -1/1 (requiring a swap) or 1/-1. + if (SelCCTVal == -1 && SelCCFVal == 1) { + std::swap(InnerLHS, InnerRHS); + } else if (SelCCTVal != 1 || SelCCFVal != -1) + return false; + } + + // Canonicalize unsigned case + if (InnerCC == ISD::SETULT || InnerCC == ISD::SETUGT) { + IsUnCmp = true; + InnerCC = (InnerCC == ISD::SETULT) ? ISD::SETLT : ISD::SETGT; + } + + bool InnerSwapped = false; + if (LHS == InnerRHS && RHS == InnerLHS) + InnerSwapped = true; + else if (LHS != InnerLHS || RHS != InnerRHS) + return false; + + switch (CC) { + // (select_cc lhs, rhs, 0, \ + // (select_cc [lr]hs, [lr]hs, 1, -1, setlt/setgt), seteq) + case ISD::SETEQ: + if (!InnerIsSel) + return false; + if (InnerCC != ISD::SETLT && InnerCC != ISD::SETGT) + return false; + NeedSwapOps = (InnerCC == ISD::SETGT) ? InnerSwapped : !InnerSwapped; + break; + + // (select_cc lhs, rhs, -1, (zext (setcc [lr]hs, [lr]hs, setne)), setu?lt) + // (select_cc lhs, rhs, -1, (zext (setcc lhs, rhs, setgt)), setu?lt) + // (select_cc lhs, rhs, -1, (zext (setcc rhs, lhs, setlt)), setu?lt) + // (select_cc lhs, rhs, 1, (sext (setcc [lr]hs, [lr]hs, setne)), setu?lt) + // (select_cc lhs, rhs, 1, (sext (setcc lhs, rhs, setgt)), setu?lt) + // (select_cc lhs, rhs, 1, (sext (setcc rhs, lhs, setlt)), setu?lt) + case ISD::SETULT: + if (!IsUnCmp && InnerCC != ISD::SETNE) + return false; + IsUnCmp = true; + LLVM_FALLTHROUGH; + case ISD::SETLT: + if (InnerCC == ISD::SETNE || (InnerCC == ISD::SETGT && !InnerSwapped) || + (InnerCC == ISD::SETLT && InnerSwapped)) + NeedSwapOps = (TrueResVal == 1); + else + return false; + break; + + // (select_cc lhs, rhs, 1, (sext (setcc [lr]hs, [lr]hs, setne)), setu?gt) + // (select_cc lhs, rhs, 1, (sext (setcc lhs, rhs, setlt)), setu?gt) + // (select_cc lhs, rhs, 1, (sext (setcc rhs, lhs, setgt)), setu?gt) + // (select_cc lhs, rhs, -1, (zext (setcc [lr]hs, [lr]hs, setne)), setu?gt) + // (select_cc lhs, rhs, -1, (zext (setcc lhs, rhs, setlt)), setu?gt) + // (select_cc lhs, rhs, -1, (zext (setcc rhs, lhs, setgt)), setu?gt) + case ISD::SETUGT: + if (!IsUnCmp && InnerCC != ISD::SETNE) + return false; + IsUnCmp = true; + LLVM_FALLTHROUGH; + case ISD::SETGT: + if (InnerCC == ISD::SETNE || (InnerCC == ISD::SETLT && !InnerSwapped) || + (InnerCC == ISD::SETGT && InnerSwapped)) + NeedSwapOps = (TrueResVal == -1); + else + return false; + break; + + default: + return false; + } + + LLVM_DEBUG(dbgs() << "Found a node that can be lowered to a SETB: "); + LLVM_DEBUG(N->dump()); + + return true; +} + // Select - Convert the specified operand from a target-independent to a // target-specific node if it hasn't already been changed. void PPCDAGToDAGISel::Select(SDNode *N) { @@ -4557,6 +4699,25 @@ N->getOperand(0).getValueType() == MVT::i1) break; + if (PPCSubTarget->isISA3_0() && PPCSubTarget->isPPC64()) { + bool NeedSwapOps = false; + bool IsUnCmp = false; + if (mayUseP9Setb(N, CC, CurDAG, NeedSwapOps, IsUnCmp)) { + SDValue LHS = N->getOperand(0); + SDValue RHS = N->getOperand(1); + if (NeedSwapOps) + std::swap(LHS, RHS); + // Specify setgt here to avoid possible seteq optimization in SelectCC + SDValue GenCC = + SelectCC(LHS, RHS, IsUnCmp ? ISD::SETUGT : ISD::SETGT, dl); + CurDAG->SelectNodeTo( + N, N->getSimpleValueType(0) == MVT::i64 ? PPC::SETB8 : PPC::SETB, + N->getValueType(0), GenCC); + NumP9Setb++; + return; + } + } + // Handle the setcc cases here. select_cc lhs, 0, 1, 0, cc if (!isPPC64) if (ConstantSDNode *N1C = dyn_cast(N->getOperand(1))) Index: llvm/lib/Target/PowerPC/PPCInstr64Bit.td =================================================================== --- llvm/lib/Target/PowerPC/PPCInstr64Bit.td +++ llvm/lib/Target/PowerPC/PPCInstr64Bit.td @@ -773,8 +773,12 @@ "maddhdu $RT, $RA, $RB, $RC", IIC_IntMulHD, []>, isPPC64; def MADDLD : VAForm_1a<51, (outs g8rc :$RT), (ins g8rc:$RA, g8rc:$RB, g8rc:$RC), "maddld $RT, $RA, $RB, $RC", IIC_IntMulHD, []>, isPPC64; -def SETB : XForm_44<31, 128, (outs g8rc:$RT), (ins crrc:$BFA), - "setb $RT, $BFA", IIC_IntGeneral>, isPPC64; +def SETB : XForm_44<31, 128, (outs gprc:$RT), (ins crrc:$BFA), + "setb $RT, $BFA", IIC_IntGeneral>, isPPC64; +let Interpretation64Bit = 1, isCodeGenOnly = 1 in { + def SETB8 : XForm_44<31, 128, (outs g8rc:$RT), (ins crrc:$BFA), + "setb $RT, $BFA", IIC_IntGeneral>, isPPC64; +} def DARN : XForm_45<31, 755, (outs g8rc:$RT), (ins i32imm:$L), "darn $RT, $L", IIC_LdStLD>, isPPC64; def ADDPCIS : DXForm<19, 2, (outs g8rc:$RT), (ins i32imm:$D), Index: llvm/lib/Target/PowerPC/PPCInstrInfo.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -3140,6 +3140,7 @@ Opcode == PPC::EXTSH || Opcode == PPC::EXTSHo || Opcode == PPC::EXTSB8 || Opcode == PPC::EXTSH8 || Opcode == PPC::EXTSW || Opcode == PPC::EXTSWo || + Opcode == PPC::SETB || Opcode == PPC::SETB8 || Opcode == PPC::EXTSH8_32_64 || Opcode == PPC::EXTSW_32_64 || Opcode == PPC::EXTSB8_32_64) return true; Index: llvm/test/CodeGen/PowerPC/ppc64-P9-setb.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/PowerPC/ppc64-P9-setb.ll @@ -0,0 +1,1021 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mcpu=pwr9 -mtriple=powerpc64le-unknown-unknown \ +; RUN: -enable-ppc-quad-precision -ppc-asm-full-reg-names < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -mcpu=pwr8 -mtriple=powerpc64le-unknown-unknown \ +; RUN: -ppc-asm-full-reg-names < %s | FileCheck %s -check-prefix=CHECK-PWR8 \ +; RUN: -implicit-check-not "\" + +; Test different patterns with type i64 + +; select_cc lhs, rhs, -1, (zext (setcc lhs, rhs, setne)), setlt +define i64 @setb1(i64 %a, i64 %b) { + %t1 = icmp slt i64 %a, %b + %t2 = icmp ne i64 %a, %b + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb1 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb1 +; CHECK-PWR8-DAG: cmpd +; CHECK-PWR8-DAG: addic +; CHECK-PWR8-DAG: subfe +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, -1, (zext (setcc rhs, lhs, setne)), setgt +define i64 @setb2(i64 %a, i64 %b) { + %t1 = icmp sgt i64 %b, %a + %t2 = icmp ne i64 %a, %b + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb2 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb2 +; CHECK-PWR8-DAG: cmpd +; CHECK-PWR8-DAG: addic +; CHECK-PWR8-DAG: subfe +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, -1, (zext (setcc rhs, lhs, setne)), setlt +define i64 @setb3(i64 %a, i64 %b) { + %t1 = icmp slt i64 %a, %b + %t2 = icmp ne i64 %b, %a + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb3 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb3 +; CHECK-PWR8-DAG: cmpd +; CHECK-PWR8-DAG: addic +; CHECK-PWR8-DAG: subfe +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, -1, (zext (setcc lhs, rhs, setne)), setgt +define i64 @setb4(i64 %a, i64 %b) { + %t1 = icmp sgt i64 %b, %a + %t2 = icmp ne i64 %b, %a + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb4 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb4 +; CHECK-PWR8-DAG: cmpd +; CHECK-PWR8-DAG: addic +; CHECK-PWR8-DAG: subfe +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, -1, (zext (setcc lhs, rhs, setgt)), setlt +define i64 @setb5(i64 %a, i64 %b) { + %t1 = icmp slt i64 %a, %b + %t2 = icmp sgt i64 %a, %b + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb5 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb5 +; CHECK-PWR8-DAG: cmpd +; CHECK-PWR8-DAG: subfc +; CHECK-PWR8-DAG: adde +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, -1, (zext (setcc rhs, lhs, setgt)), setgt +define i64 @setb6(i64 %a, i64 %b) { + %t1 = icmp sgt i64 %b, %a + %t2 = icmp sgt i64 %a, %b + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb6 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb6 +; CHECK-PWR8-DAG: cmpd +; CHECK-PWR8-DAG: subfc +; CHECK-PWR8-DAG: adde +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, -1, (zext (setcc rhs, lhs, setlt)), setlt +define i64 @setb7(i64 %a, i64 %b) { + %t1 = icmp slt i64 %a, %b + %t2 = icmp slt i64 %b, %a + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb7 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb7 +; CHECK-PWR8-DAG: cmpd +; CHECK-PWR8-DAG: subfc +; CHECK-PWR8-DAG: adde +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, -1, (zext (setcc lhs, rhs, setlt)), setgt +define i64 @setb8(i64 %a, i64 %b) { + %t1 = icmp sgt i64 %b, %a + %t2 = icmp slt i64 %b, %a + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb8 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb8 +; CHECK-PWR8-DAG: cmpd +; CHECK-PWR8-DAG: subfc +; CHECK-PWR8-DAG: adde +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 1, (sext (setcc lhs, rhs, setne)), setgt +define i64 @setb9(i64 %a, i64 %b) { + %t1 = icmp sgt i64 %a, %b + %t2 = icmp ne i64 %a, %b + %t3 = sext i1 %t2 to i64 + %t4 = select i1 %t1, i64 1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb9 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb9 +; CHECK-PWR8-DAG: cmpd +; CHECK-PWR8-DAG: subfic +; CHECK-PWR8-DAG: subfe +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 1, (sext (setcc rhs, lhs, setne)), setlt +define i64 @setb10(i64 %a, i64 %b) { + %t1 = icmp slt i64 %b, %a + %t2 = icmp ne i64 %a, %b + %t3 = sext i1 %t2 to i64 + %t4 = select i1 %t1, i64 1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb10 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb10 +; CHECK-PWR8-DAG: cmpd +; CHECK-PWR8-DAG: subfic +; CHECK-PWR8-DAG: subfe +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 1, (sext (setcc rhs, lhs, setne)), setgt +define i64 @setb11(i64 %a, i64 %b) { + %t1 = icmp sgt i64 %a, %b + %t2 = icmp ne i64 %b, %a + %t3 = sext i1 %t2 to i64 + %t4 = select i1 %t1, i64 1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb11 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb11 +; CHECK-PWR8-DAG: cmpd +; CHECK-PWR8-DAG: subfic +; CHECK-PWR8-DAG: subfe +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 1, (sext (setcc lhs, rhs, setne)), setlt +define i64 @setb12(i64 %a, i64 %b) { + %t1 = icmp slt i64 %b, %a + %t2 = icmp ne i64 %b, %a + %t3 = sext i1 %t2 to i64 + %t4 = select i1 %t1, i64 1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb12 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb12 +; CHECK-PWR8-DAG: cmpd +; CHECK-PWR8-DAG: subfic +; CHECK-PWR8-DAG: subfe +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 1, (sext (setcc lhs, rhs, setlt)), setgt +define i64 @setb13(i64 %a, i64 %b) { + %t1 = icmp sgt i64 %a, %b + %t2 = icmp slt i64 %a, %b + %t3 = sext i1 %t2 to i64 + %t4 = select i1 %t1, i64 1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb13 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb13 +; CHECK-PWR8-DAG: cmpd +; CHECK-PWR8-DAG: subfc +; CHECK-PWR8-DAG: adde +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 1, (sext (setcc rhs, lhs, setlt)), setlt +define i64 @setb14(i64 %a, i64 %b) { + %t1 = icmp slt i64 %b, %a + %t2 = icmp slt i64 %a, %b + %t3 = sext i1 %t2 to i64 + %t4 = select i1 %t1, i64 1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb14 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb14 +; CHECK-PWR8-DAG: cmpd +; CHECK-PWR8-DAG: subfc +; CHECK-PWR8-DAG: adde +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 1, (sext (setcc rhs, lhs, setgt)), setgt +define i64 @setb15(i64 %a, i64 %b) { + %t1 = icmp sgt i64 %a, %b + %t2 = icmp sgt i64 %b, %a + %t3 = sext i1 %t2 to i64 + %t4 = select i1 %t1, i64 1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb15 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb15 +; CHECK-PWR8-DAG: cmpd +; CHECK-PWR8-DAG: subfc +; CHECK-PWR8-DAG: adde +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 1, (sext (setcc lhs, rhs, setgt)), setlt +define i64 @setb16(i64 %a, i64 %b) { + %t1 = icmp slt i64 %b, %a + %t2 = icmp sgt i64 %b, %a + %t3 = sext i1 %t2 to i64 + %t4 = select i1 %t1, i64 1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb16 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb16 +; CHECK-PWR8-DAG: cmpd +; CHECK-PWR8-DAG: subfc +; CHECK-PWR8-DAG: adde +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 0, (select_cc lhs, rhs, 1, -1, setgt), seteq +define i64 @setb17(i64 %a, i64 %b) { + %t1 = icmp eq i64 %a, %b + %t2 = icmp sgt i64 %a, %b + %t3 = select i1 %t2, i64 1, i64 -1 + %t4 = select i1 %t1, i64 0, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb17 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb17 +; CHECK-PWR8: cmpd +; CHECK-PWR8: isel +; CHECK-PWR8: cmpld +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 0, (select_cc rhs, lhs, 1, -1, setgt), seteq +define i64 @setb18(i64 %a, i64 %b) { + %t1 = icmp eq i64 %b, %a + %t2 = icmp sgt i64 %a, %b + %t3 = select i1 %t2, i64 1, i64 -1 + %t4 = select i1 %t1, i64 0, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb18 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb18 +; CHECK-PWR8: cmpd +; CHECK-PWR8: isel +; CHECK-PWR8: cmpld +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 0, (select_cc rhs, lhs, 1, -1, setlt), seteq +define i64 @setb19(i64 %a, i64 %b) { + %t1 = icmp eq i64 %a, %b + %t2 = icmp slt i64 %b, %a + %t3 = select i1 %t2, i64 1, i64 -1 + %t4 = select i1 %t1, i64 0, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb19 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb19 +; CHECK-PWR8: cmpd +; CHECK-PWR8: isel +; CHECK-PWR8: cmpld +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 0, (select_cc lhs, rhs, 1, -1, setlt), seteq +define i64 @setb20(i64 %a, i64 %b) { + %t1 = icmp eq i64 %b, %a + %t2 = icmp slt i64 %b, %a + %t3 = select i1 %t2, i64 1, i64 -1 + %t4 = select i1 %t1, i64 0, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb20 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb20 +; CHECK-PWR8: cmpd +; CHECK-PWR8: isel +; CHECK-PWR8: cmpld +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 0, (select_cc lhs, rhs, -1, 1, setlt), seteq +define i64 @setb21(i64 %a, i64 %b) { + %t1 = icmp eq i64 %a, %b + %t2 = icmp slt i64 %a, %b + %t3 = select i1 %t2, i64 -1, i64 1 + %t4 = select i1 %t1, i64 0, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb21 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb21 +; CHECK-PWR8: cmpd +; CHECK-PWR8: isel +; CHECK-PWR8: cmpld +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 0, (select_cc rhs, lhs, -1, 1, setlt), seteq +define i64 @setb22(i64 %a, i64 %b) { + %t1 = icmp eq i64 %b, %a + %t2 = icmp slt i64 %a, %b + %t3 = select i1 %t2, i64 -1, i64 1 + %t4 = select i1 %t1, i64 0, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb22 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb22 +; CHECK-PWR8: cmpd +; CHECK-PWR8: isel +; CHECK-PWR8: cmpld +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 0, (select_cc rhs, lhs, -1, 1, setgt), seteq +define i64 @setb23(i64 %a, i64 %b) { + %t1 = icmp eq i64 %a, %b + %t2 = icmp sgt i64 %b, %a + %t3 = select i1 %t2, i64 -1, i64 1 + %t4 = select i1 %t1, i64 0, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb23 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb23 +; CHECK-PWR8: cmpd +; CHECK-PWR8: isel +; CHECK-PWR8: cmpld +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 0, (select_cc lhs, rhs, -1, 1, setgt), seteq +define i64 @setb24(i64 %a, i64 %b) { + %t1 = icmp eq i64 %b, %a + %t2 = icmp sgt i64 %b, %a + %t3 = select i1 %t2, i64 -1, i64 1 + %t4 = select i1 %t1, i64 0, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb24 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb24 +; CHECK-PWR8: cmpd +; CHECK-PWR8: isel +; CHECK-PWR8: cmpld +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} +; end all patterns testing for i64 + +; Test with swapping the input parameters + +; select_cc lhs, rhs, -1, (zext (setcc lhs, rhs, setne)), setlt +define i64 @setb25(i64 %a, i64 %b) { + %t1 = icmp slt i64 %b, %a + %t2 = icmp ne i64 %b, %a + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb25 +; CHECK: cmpd {{c?r?(0, )?}}r4, r3 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb25 +; CHECK-PWR8-DAG: cmpd +; CHECK-PWR8-DAG: addic +; CHECK-PWR8-DAG: subfe +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, -1, (zext (setcc rhs, lhs, setne)), setgt +define i64 @setb26(i64 %a, i64 %b) { + %t1 = icmp sgt i64 %a, %b + %t2 = icmp ne i64 %b, %a + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setb26 +; CHECK: cmpd {{c?r?(0, )?}}r4, r3 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb26 +; CHECK-PWR8-DAG: cmpd +; CHECK-PWR8-DAG: addic +; CHECK-PWR8-DAG: subfe +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; Test with different scalar integer type for selected value +; i32/i16/i8 rather than i64 above + +; select_cc lhs, rhs, -1, (zext (setcc rhs, lhs, setne)), setlt +define i64 @setb27(i64 %a, i64 %b) { + %t1 = icmp slt i64 %a, %b + %t2 = icmp ne i64 %b, %a + %t3 = zext i1 %t2 to i32 + %t4 = select i1 %t1, i32 -1, i32 %t3 + %t5 = sext i32 %t4 to i64 + ret i64 %t5 +; CHECK-LABEL: setb27 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb27 +; CHECK-PWR8-DAG: cmpd +; CHECK-PWR8-DAG: addic +; CHECK-PWR8-DAG: subfe +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, -1, (zext (setcc lhs, rhs, setne)), setgt +define i64 @setb28(i64 %a, i64 %b) { + %t1 = icmp sgt i64 %b, %a + %t2 = icmp ne i64 %b, %a + %t3 = zext i1 %t2 to i16 + %t4 = select i1 %t1, i16 -1, i16 %t3 + %t5 = sext i16 %t4 to i64 + ret i64 %t5 +; CHECK-LABEL: setb28 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb28 +; CHECK-PWR8-DAG: cmpd +; CHECK-PWR8-DAG: addic +; CHECK-PWR8-DAG: subfe +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, -1, (zext (setcc lhs, rhs, setgt)), setlt +define i64 @setb29(i64 %a, i64 %b) { + %t1 = icmp slt i64 %a, %b + %t2 = icmp sgt i64 %a, %b + %t3 = zext i1 %t2 to i8 + %t4 = select i1 %t1, i8 -1, i8 %t3 + %t5 = zext i8 %t4 to i64 + ret i64 %t5 +; CHECK-LABEL: setb29 +; CHECK: cmpd {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setb29 +; CHECK-PWR8-DAG: cmpd +; CHECK-PWR8-DAG: subfc +; CHECK-PWR8-DAG: adde +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; Testings to cover different comparison opcodes +; Test with integer type i32/i16/i8 for input parameter + +; select_cc lhs, rhs, -1, (zext (setcc lhs, rhs, setne)), setlt +define i64 @setbsw1(i32 %a, i32 %b) { + %t1 = icmp slt i32 %a, %b + %t2 = icmp ne i32 %a, %b + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbsw1 +; CHECK: cmpw {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setbsw1 +; CHECK-PWR8-DAG: cntlzw +; CHECK-PWR8-DAG: cmpw +; CHECK-PWR8-DAG: srwi +; CHECK-PWR8-DAG: xori +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, -1, (zext (setcc rhs, lhs, setne)), setgt +define i64 @setbsw2(i32 %a, i32 %b) { + %t1 = icmp sgt i32 %b, %a + %t2 = icmp ne i32 %a, %b + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbsw2 +; CHECK: cmpw {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setbsw2 +; CHECK-PWR8-DAG: cntlzw +; CHECK-PWR8-DAG: cmpw +; CHECK-PWR8-DAG: srwi +; CHECK-PWR8-DAG: xori +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 0, (select_cc rhs, lhs, -1, 1, setgt), seteq +define i64 @setbsw3(i32 %a, i32 %b) { + %t1 = icmp eq i32 %a, %b + %t2 = icmp sgt i32 %b, %a + %t3 = select i1 %t2, i64 -1, i64 1 + %t4 = select i1 %t1, i64 0, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbsw3 +; CHECK: cmpw {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setbsw3 +; CHECK-PWR8: cmpw +; CHECK-PWR8: isel +; CHECK-PWR8: cmplw +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, -1, (zext (setcc rhs, lhs, setne)), setlt +define i64 @setbsh1(i16 signext %a, i16 signext %b) { + %t1 = icmp slt i16 %a, %b + %t2 = icmp ne i16 %b, %a + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbsh1 +; CHECK: cmpw {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setbsh1 +; CHECK-PWR8-DAG: cntlzw +; CHECK-PWR8-DAG: cmpw +; CHECK-PWR8-DAG: srwi +; CHECK-PWR8-DAG: xori +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, -1, (zext (setcc lhs, rhs, setne)), setgt +define i64 @setbsh2(i16 signext %a, i16 signext %b) { + %t1 = icmp sgt i16 %b, %a + %t2 = icmp ne i16 %b, %a + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbsh2 +; CHECK: cmpw {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setbsh2 +; CHECK-PWR8-DAG: cmpw +; CHECK-PWR8-DAG: cntlzw +; CHECK-PWR8-DAG: srwi +; CHECK-PWR8-DAG: xori +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, -1, (zext (setcc lhs, rhs, setgt)), setlt +define i64 @setbsc1(i8 %a, i8 %b) { + %t1 = icmp slt i8 %a, %b + %t2 = icmp sgt i8 %a, %b + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbsc1 +; CHECK-DAG: extsb [[RA:r[0-9]+]], r3 +; CHECK-DAG: extsb [[RB:r[0-9]+]], r4 +; CHECK: cmpw {{c?r?(0, )?}}[[RA]], [[RB]] +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setbsc1 +; CHECK-PWR8-DAG: extsb +; CHECK-PWR8-DAG: extsb +; CHECK-PWR8-DAG: extsw +; CHECK-PWR8-DAG: extsw +; CHECK-PWR8-DAG: cmpw +; CHECK-PWR8-DAG: rldicl +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, -1, (zext (setcc rhs, lhs, setgt)), setgt +define i64 @setbsc2(i8 %a, i8 %b) { + %t1 = icmp sgt i8 %b, %a + %t2 = icmp sgt i8 %a, %b + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbsc2 +; CHECK-DAG: extsb [[RA:r[0-9]+]], r3 +; CHECK-DAG: extsb [[RB:r[0-9]+]], r4 +; CHECK: cmpw {{c?r?(0, )?}}[[RA]], [[RB]] +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setbsc2 +; CHECK-PWR8-DAG: extsb +; CHECK-PWR8-DAG: extsb +; CHECK-PWR8-DAG: extsw +; CHECK-PWR8-DAG: extsw +; CHECK-PWR8-DAG: cmpw +; CHECK-PWR8-DAG: rldicl +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, -1, (zext (setcc rhs, lhs, setlt)), setlt +define i64 @setbsc3(i4 %a, i4 %b) { + %t1 = icmp slt i4 %a, %b + %t2 = icmp slt i4 %b, %a + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbsc3 +; CHECK-DAG: slwi [[RA:r[0-9]+]], r3, 28 +; CHECK-DAG: slwi [[RB:r[0-9]+]], r4, 28 +; CHECK-DAG: srawi [[RA1:r[0-9]+]], [[RA]], 28 +; CHECK-DAG: srawi [[RB1:r[0-9]+]], [[RB]], 28 +; CHECK: cmpw {{c?r?(0, )?}}[[RA1]], [[RB1]] +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setbsc3 +; CHECK-PWR8-DAG: slwi +; CHECK-PWR8-DAG: slwi +; CHECK-PWR8-DAG: srawi +; CHECK-PWR8-DAG: srawi +; CHECK-PWR8-DAG: extsw +; CHECK-PWR8-DAG: extsw +; CHECK-PWR8-DAG: cmpw +; CHECK-PWR8-DAG: rldicl +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; Test with unsigned integer type i64/i32/i16/i8 for input parameter + +; select_cc lhs, rhs, -1, (zext (setcc lhs, rhs, setult)), setugt +define i64 @setbud1(i64 %a, i64 %b) { + %t1 = icmp ugt i64 %b, %a + %t2 = icmp ult i64 %b, %a + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbud1 +; CHECK: cmpld {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setbud1 +; CHECK-PWR8-DAG: subfc +; CHECK-PWR8-DAG: subfe +; CHECK-PWR8-DAG: cmpld +; CHECK-PWR8-DAG: neg +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 1, (sext (setcc lhs, rhs, setne)), setugt +define i64 @setbud2(i64 %a, i64 %b) { + %t1 = icmp ugt i64 %a, %b + %t2 = icmp ne i64 %a, %b + %t3 = sext i1 %t2 to i64 + %t4 = select i1 %t1, i64 1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbud2 +; CHECK: cmpld {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setbud2 +; CHECK-PWR8-DAG: cmpld +; CHECK-PWR8-DAG: subfic +; CHECK-PWR8-DAG: subfe +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 0, (select_cc lhs, rhs, -1, 1, setugt), seteq +define i64 @setbud3(i64 %a, i64 %b) { + %t1 = icmp eq i64 %b, %a + %t2 = icmp ugt i64 %b, %a + %t3 = select i1 %t2, i64 -1, i64 1 + %t4 = select i1 %t1, i64 0, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbud3 +; CHECK: cmpld {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setbud3 +; CHECK-PWR8-DAG: cmpld +; CHECK-PWR8-DAG: li +; CHECK-PWR8-DAG: li +; CHECK-PWR8: isel +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 1, (sext (setcc rhs, lhs, setne)), setult +define i64 @setbuw1(i32 %a, i32 %b) { + %t1 = icmp ult i32 %b, %a + %t2 = icmp ne i32 %a, %b + %t3 = sext i1 %t2 to i64 + %t4 = select i1 %t1, i64 1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbuw1 +; CHECK: cmplw {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setbuw1 +; CHECK-PWR8-DAG: cntlzw +; CHECK-PWR8-DAG: cmplw +; CHECK-PWR8-DAG: srwi +; CHECK-PWR8-DAG: xori +; CHECK-PWR8-DAG: neg +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 1, (sext (setcc rhs, lhs, setne)), setugt +define i64 @setbuw2(i32 %a, i32 %b) { + %t1 = icmp ugt i32 %a, %b + %t2 = icmp ne i32 %b, %a + %t3 = sext i1 %t2 to i64 + %t4 = select i1 %t1, i64 1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbuw2 +; CHECK: cmplw {{c?r?(0, )?}}r3, r4 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setbuw2 +; CHECK-PWR8-DAG: cntlzw +; CHECK-PWR8-DAG: cmplw +; CHECK-PWR8-DAG: srwi +; CHECK-PWR8-DAG: xori +; CHECK-PWR8-DAG: neg +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 1, (sext (setcc lhs, rhs, setne)), setult +define i64 @setbuh(i16 %a, i16 %b) { + %t1 = icmp ult i16 %b, %a + %t2 = icmp ne i16 %b, %a + %t3 = sext i1 %t2 to i64 + %t4 = select i1 %t1, i64 1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbuh +; CHECK-DAG: rlwinm [[RA:r[0-9]+]], r3, 0, 16, 31 +; CHECK-DAG: rlwinm [[RB:r[0-9]+]], r4, 0, 16, 31 +; CHECK: cmplw {{c?r?(0, )?}}[[RA]], [[RB]] +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setbuh +; CHECK-PWR8: rlwinm +; CHECK-PWR8: rlwinm +; CHECK-PWR8-DAG: cmplw +; CHECK-PWR8-DAG: cntlzw +; CHECK-PWR8: srwi +; CHECK-PWR8: xori +; CHECK-PWR8: neg +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 1, (sext (setcc lhs, rhs, setult)), setugt +define i64 @setbuc(i8 %a, i8 %b) { + %t1 = icmp ugt i8 %a, %b + %t2 = icmp ult i8 %a, %b + %t3 = sext i1 %t2 to i64 + %t4 = select i1 %t1, i64 1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbuc +; CHECK-DAG: rlwinm [[RA:r[0-9]+]], r3, 0, 24, 31 +; CHECK-DAG: rlwinm [[RB:r[0-9]+]], r4, 0, 24, 31 +; CHECK: cmplw {{c?r?(0, )?}}[[RA]], [[RB]] +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setbuc +; CHECK-PWR8: rlwinm +; CHECK-PWR8: rlwinm +; CHECK-PWR8-DAG: clrldi +; CHECK-PWR8-DAG: clrldi +; CHECK-PWR8-DAG: cmplw +; CHECK-PWR8: sradi +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; Test with float/double/float128 for input parameter + +; select_cc lhs, rhs, -1, (zext (setcc rhs, lhs, setlt)), setlt +define i64 @setbf1(float %a, float %b) { + %t1 = fcmp fast olt float %a, %b + %t2 = fcmp fast olt float %b, %a + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbf1 +; CHECK: fcmpu cr0, f1, f2 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setbf1 +; CHECK-PWR8: isel +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, -1, (zext (setcc lhs, rhs, setlt)), setgt +define i64 @setbf2(float %a, float %b) { + %t1 = fcmp fast ogt float %b, %a + %t2 = fcmp fast olt float %b, %a + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbf2 +; CHECK: fcmpu cr0, f1, f2 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setbf2 +; CHECK-PWR8: isel +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 0, (select_cc lhs, rhs, -1, 1, setgt), seteq +define i64 @setbdf1(double %a, double %b) { + %t1 = fcmp fast oeq double %b, %a + %t2 = fcmp fast ogt double %b, %a + %t3 = select i1 %t2, i64 -1, i64 1 + %t4 = select i1 %t1, i64 0, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbdf1 +; CHECK: xscmpudp cr0, f1, f2 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setbdf1 +; CHECK-PWR8: isel +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; select_cc lhs, rhs, 1, (sext (setcc lhs, rhs, setgt)), setlt +define i64 @setbdf2(double %a, double %b) { + %t1 = fcmp fast olt double %b, %a + %t2 = fcmp fast ogt double %b, %a + %t3 = sext i1 %t2 to i64 + %t4 = select i1 %t1, i64 1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbdf2 +; CHECK: xscmpudp cr0, f1, f2 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setbdf2 +; CHECK-PWR8: isel +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +define i64 @setbf128(fp128 %a, fp128 %b) { + %t1 = fcmp fast ogt fp128 %a, %b + %t2 = fcmp fast olt fp128 %a, %b + %t3 = sext i1 %t2 to i64 + %t4 = select i1 %t1, i64 1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbf128 +; CHECK: xscmpuqp cr0, v2, v3 +; CHECK-NEXT: setb r3, cr0 +; CHECK: blr +; CHECK-PWR8-LABEL: setbf128 +; CHECK-PWR8: isel +; CHECK-PWR8: blr +} + +; Some cases we can't leverage setb + +define i64 @setbn1(i64 %a, i64 %b) { + %t1 = icmp slt i64 %a, %b + %t2 = icmp eq i64 %a, %b + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbn1 +; CHECK-NOT: {{\}} +; CHECK: isel +; CHECK: blr +} + +define i64 @setbn2(double %a, double %b) { + %t1 = fcmp olt double %a, %b + %t2 = fcmp one double %a, %b + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbn2 +; CHECK-NOT: {{\}} +; CHECK: isel +; CHECK: blr +} + +define i64 @setbn3(float %a, float %b) { + %t1 = fcmp ult float %a, %b + %t2 = fcmp une float %a, %b + %t3 = zext i1 %t2 to i64 + %t4 = select i1 %t1, i64 -1, i64 %t3 + ret i64 %t4 +; CHECK-LABEL: setbn3 +; CHECK-NOT: {{\}} +; CHECK: isel +; CHECK: blr +}