Index: lib/Target/PowerPC/PPCISelDAGToDAG.cpp =================================================================== --- lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -72,6 +72,14 @@ "Number of (sext(setcc)) nodes expanded into GPR sequence."); STATISTIC(NumZextSetcc, "Number of (zext(setcc)) nodes expanded into GPR sequence."); +STATISTIC(NumSelectSetcc, + "Number of (select (setcc), PwrOf2, 0) nodes calculated in GPR."); +STATISTIC(NumSelectCCPow2True, + "Number of (select_cc a, b, PwrOf2, 0) nodes calculated in GPR."); +STATISTIC(NumSelectCCPow2False, + "Number of (select_cc a, b, 0, PwrOf2) nodes calculated in GPR."); +STATISTIC(NumComparisonOps, + "Number of cmp(a, b) => { 0, 1, -1 } calculated in GPR."); STATISTIC(SignExtensionsAdded, "Number of sign extensions for compare inputs added."); STATISTIC(ZeroExtensionsAdded, @@ -2503,7 +2511,44 @@ // Handle select (setcc), pwrOf2, 0. bool PPCDAGToDAGISel::trySELECT(SDNode *N) { - return false; + if (TM.getOptLevel() == CodeGenOpt::None || !TM.isPPC64()) + return false; + if (N->getOperand(0).getOpcode() != ISD::SETCC) + return false; + SDValue TrueVal = N->getOperand(1); + SDValue FalseVal = N->getOperand(2); + ConstantSDNode *TrueConst = dyn_cast(TrueVal); + ConstantSDNode *FalseConst = dyn_cast(FalseVal); + if (!TrueConst || !FalseConst || !isPowerOf2_64(TrueConst->getSExtValue()) || + !FalseConst->isNullValue()) + return false; + + // Get the result of the comparison in a GPR. + SDValue SCCInGPR = getSETCCInGPR(N->getOperand(0), false); + if (!SCCInGPR) + return false; + + SDLoc dl(N); + EVT InputVT = SCCInGPR.getValueType(); + EVT OutputVT = N->getValueType(0); + bool Input32Bit = InputVT == MVT::i32; + bool Output32Bit = OutputVT == MVT::i32; + + SDValue ConvOp = addExtOrTrunc(SCCInGPR, Input32Bit, Output32Bit); + + // Shift the result of the comparison as required. + if (Output32Bit) { + uint32_t ShAmt = Log2_32(TrueConst->getSExtValue()); + SDValue Ops[] = { ConvOp, getI32Imm(ShAmt, dl), getI32Imm(0, dl), + getI32Imm(31 - ShAmt, dl) }; + CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops); + } else { + uint64_t ShAmt = Log2_64(TrueConst->getSExtValue()); + CurDAG->SelectNodeTo(N, PPC::RLDICR, MVT::i64, ConvOp, + getI64Imm(ShAmt, dl), getI64Imm(63 - ShAmt, dl)); + } + NumSelectSetcc++; + return true; } /// If this node is a sign/zero extension of an integer comparison, @@ -2541,13 +2586,141 @@ // Is this a comparison operator (i.e. returns 0 if the values are equal, // -1 if the first value is less and 1 if the first value is greater)? static bool isComparisonOp(SDNode *N) { + if (N->getOpcode() != ISD::SELECT_CC) + return false; + SDValue DefFalse = N->getOperand(3); + SDValue MyLHS = N->getOperand(0); + SDValue MyRHS = N->getOperand(1); + ISD::CondCode MyCC = cast(N->getOperand(4))->get(); + ConstantSDNode *MyTrueConst = dyn_cast(N->getOperand(2)); + if (!MyTrueConst) + return false; + + // The false value may be a zero/sign extended result of a setcc. + if (DefFalse.getOpcode() == ISD::ZERO_EXTEND || + DefFalse.getOpcode() == ISD::SIGN_EXTEND) { + if (DefFalse.getOperand(0).getOpcode() != ISD::SETCC) + return false; + SDValue SetCC = DefFalse.getOperand(0); + if (SetCC.getOperand(0) != MyLHS || SetCC.getOperand(1) != MyRHS) + return false; + ISD::CondCode DefCC = cast(SetCC.getOperand(2))->get(); + if (MyTrueConst->getSExtValue() == 1 && MyCC == ISD::SETUGT && + DefFalse.getOpcode() == ISD::SIGN_EXTEND && + (DefCC == ISD::SETNE || DefCC == ISD::SETULT)) + return true; + if (MyTrueConst->isAllOnesValue() && MyCC == ISD::SETULT && + DefFalse.getOpcode() == ISD::ZERO_EXTEND && + DefCC == ISD::SETNE) + return true; + return false; + } + + if (DefFalse.getOpcode() != ISD::SELECT_CC) + return false; + SDValue DefLHS = DefFalse.getOperand(0); + SDValue DefRHS = DefFalse.getOperand(1); + if (MyLHS != DefLHS || MyRHS != DefRHS) + return false; + ConstantSDNode *DefTrueConst = + dyn_cast(DefFalse.getOperand(2)); + ConstantSDNode *DefFalseConst = + dyn_cast(DefFalse.getOperand(3)); + ISD::CondCode DefCC = cast(DefFalse.getOperand(4))->get(); + if (!DefTrueConst || !DefFalseConst || !MyTrueConst) + return false; + if (MyTrueConst->isNullValue() && MyCC == ISD::SETEQ && + DefTrueConst->isAllOnesValue() && DefFalseConst->getSExtValue() == 1 && + DefCC == ISD::SETULT) + return true; + if (MyTrueConst->isNullValue() && MyCC == ISD::SETEQ && + DefTrueConst->getSExtValue() == 1 && DefFalseConst->isAllOnesValue() && + DefCC == ISD::SETUGT) + return true; return false; } // Handle select_cc %a, %b, pwrOf2, 0 // and select_cc %a, %b, 0, pwrOf2 bool PPCDAGToDAGISel::trySELECT_CC(SDNode *N) { - return false; + if (TM.getOptLevel() == CodeGenOpt::None || !TM.isPPC64()) + return false; + SDValue TrueVal = N->getOperand(2); + SDValue FalseVal = N->getOperand(3); + ConstantSDNode *TrueConst = dyn_cast(TrueVal); + ConstantSDNode *FalseConst = dyn_cast(FalseVal); + EVT InputVT = N->getOperand(0).getValueType(); + EVT OutputVT = TrueVal.getValueType(); + SDLoc dl(N); + + // Can only do this if comparing and returning integers. + if ((InputVT != MVT::i32 && InputVT != MVT::i64) || + (OutputVT != MVT::i32 && OutputVT != MVT::i64)) + return false; + + bool Input32Bit = InputVT == MVT::i32; + bool Output32Bit = OutputVT == MVT::i32; + + // Comparison operators will typically be in the DAG as SELECT_CC nodes. + if (isComparisonOp(N)) { + SDValue LHS = N->getOperand(0); + SDValue RHS = N->getOperand(1); + SDValue Subtract = + SDValue(CurDAG->getMachineNode(Input32Bit ? PPC::SUBF : PPC::SUBF8, dl, + InputVT, RHS, LHS), 0); + SDValue SubC = + SDValue(CurDAG->getMachineNode(Input32Bit ? PPC::SUBFC : PPC::SUBFC8, dl, + InputVT, MVT::Glue, LHS, RHS), 1); + SDValue SubExt1 = + SDValue(CurDAG->getMachineNode(Input32Bit ? PPC::SUBFE : PPC::SUBFE8, dl, + InputVT, MVT::Glue, RHS, LHS, SubC), 0); + SDValue SubExt2 = + SDValue(CurDAG->getMachineNode(Input32Bit ? PPC::SUBFE : PPC::SUBFE8, dl, + InputVT, SubExt1, Subtract, + SubExt1.getValue(1)), 0); + SDValue ConvOp = addExtOrTrunc(SubExt2, Input32Bit, Output32Bit); + ReplaceNode(N, ConvOp.getNode()); + NumComparisonOps++; + return true; + } + + if (!TrueConst || !FalseConst) + return false; + + SDValue SCCInGPR; + uint64_t ShAmt = 0; + // Is this select_cc %a, %b, 0, pwrOf2 + if (TrueConst->isNullValue() && + isPowerOf2_64(FalseConst->getSExtValue())) { + SCCInGPR = getSETCCInGPR(SDValue(N, 0), false, true); + if (!SCCInGPR) + return false; + NumSelectCCPow2False++; + ShAmt = Log2_64(FalseConst->getSExtValue()); + } else if (FalseConst->isNullValue() && + isPowerOf2_64(TrueConst->getSExtValue())) { + // Is this select_cc %a, %b, pwrOf2, 0 + SCCInGPR = getSETCCInGPR(SDValue(N, 0), false); + if (!SCCInGPR) + return false; + NumSelectCCPow2True++; + ShAmt = Log2_64(TrueConst->getSExtValue()); + } else + return false; + + SDValue ConvOp = addExtOrTrunc(SCCInGPR, Input32Bit, Output32Bit); + + if (ShAmt && Output32Bit) { + SDValue Ops[] = { ConvOp, getI32Imm(ShAmt, dl), getI32Imm(0, dl), + getI32Imm(31 - ShAmt, dl) }; + CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops); + } else if (ShAmt) { + CurDAG->SelectNodeTo(N, PPC::RLDICR, MVT::i64, ConvOp, + getI64Imm(ShAmt, dl), getI64Imm(63 - ShAmt, dl)); + } else + ReplaceNode(N, ConvOp.getNode()); + + return true; } static bool isLogicOp(unsigned Opc) { Index: test/CodeGen/PowerPC/comparisonOps32.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/comparisonOps32.ll @@ -0,0 +1,449 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s + +@ga = common local_unnamed_addr global i32 0, align 4 + +; Function Attrs: norecurse nounwind readnone +define signext i32 @compOp1(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: compOp1: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r5, r3, r4 +; CHECK-NEXT: subf r5, r4, r3 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: subfe r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp eq i32 %a, %b + %cmp1 = icmp ult i32 %a, %b + %. = select i1 %cmp1, i32 -1, i32 1 + %retval.0 = select i1 %cmp, i32 0, i32 %. + ret i32 %retval.0 +} + +; Function Attrs: norecurse nounwind readnone +define signext i32 @compOp2(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: compOp2: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r5, r3, r4 +; CHECK-NEXT: subf r5, r4, r3 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: subfe r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp eq i32 %a, %b + %cmp1 = icmp ugt i32 %a, %b + %. = select i1 %cmp1, i32 1, i32 -1 + %retval.0 = select i1 %cmp, i32 0, i32 %. + ret i32 %retval.0 +} + +; Function Attrs: norecurse nounwind readnone +; FIXME: the extsw is unnecessary but is in the DAG as well. +define signext i32 @compOp3(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: compOp3: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r5, r3, r4 +; CHECK-NEXT: subf r5, r4, r3 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: subfe r3, r3, r5 +; CHECK-NEXT: extsw r3, r3 +; CHECK-NEXT: blr +entry: + %cmp = icmp ugt i32 %a, %b + %not.cmp1 = icmp ne i32 %a, %b + %. = sext i1 %not.cmp1 to i32 + %retval.0 = select i1 %cmp, i32 1, i32 %. + ret i32 %retval.0 +} + +; Function Attrs: norecurse nounwind readnone +; FIXME: the extsw is unnecessary but is in the DAG as well. +define signext i32 @compOp4(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: compOp4: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r5, r3, r4 +; CHECK-NEXT: subf r5, r4, r3 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: subfe r3, r3, r5 +; CHECK-NEXT: extsw r3, r3 +; CHECK-NEXT: blr +entry: + %cmp = icmp ugt i32 %a, %b + %cmp1 = icmp ult i32 %a, %b + %. = sext i1 %cmp1 to i32 + %retval.0 = select i1 %cmp, i32 1, i32 %. + ret i32 %retval.0 +} + +; Function Attrs: norecurse nounwind readnone +; FIXME: the extsw is unnecessary but is in the DAG as well. +define signext i32 @compOp5(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: compOp5: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r5, r3, r4 +; CHECK-NEXT: subf r5, r4, r3 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: subfe r3, r3, r5 +; CHECK-NEXT: extsw r3, r3 +; CHECK-NEXT: blr +entry: + %cmp = icmp ult i32 %a, %b + %not.cmp1 = icmp ne i32 %a, %b + %. = zext i1 %not.cmp1 to i32 + %retval.0 = select i1 %cmp, i32 -1, i32 %. + ret i32 %retval.0 +} + +; Function Attrs: norecurse nounwind readnone +; FIXME: this is still done with compares, we may fix that in the future +define signext i32 @compOp6(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: compOp6: +entry: + %cmp = icmp ult i32 %a, %b + %cmp1 = icmp ugt i32 %a, %b + %. = zext i1 %cmp1 to i32 + %retval.0 = select i1 %cmp, i32 -1, i32 %. + ret i32 %retval.0 +} + +; Function Attrs: norecurse nounwind readnone +define signext i32 @compOp7(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: compOp7: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r5, r3, r4 +; CHECK-NEXT: subf r5, r4, r3 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: subfe r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp eq i32 %a, %b + %cmp1 = icmp ult i32 %a, %b + %cond = select i1 %cmp1, i32 -1, i32 1 + %cond2 = select i1 %cmp, i32 0, i32 %cond + ret i32 %cond2 +} + +; Function Attrs: norecurse nounwind readnone +define signext i32 @compOp8(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: compOp8: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r5, r3, r4 +; CHECK-NEXT: subf r5, r4, r3 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: subfe r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp eq i32 %a, %b + %cmp1 = icmp ugt i32 %a, %b + %cond = select i1 %cmp1, i32 1, i32 -1 + %cond2 = select i1 %cmp, i32 0, i32 %cond + ret i32 %cond2 +} + +; Function Attrs: norecurse nounwind readnone +; FIXME: the extsw is unnecessary but is in the DAG as well. +define signext i32 @compOp9(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: compOp9: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r5, r3, r4 +; CHECK-NEXT: subf r5, r4, r3 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: subfe r3, r3, r5 +; CHECK-NEXT: extsw r3, r3 +; CHECK-NEXT: blr +entry: + %cmp = icmp ult i32 %a, %b + %not.cmp1 = icmp ne i32 %a, %b + %cond = zext i1 %not.cmp1 to i32 + %cond2 = select i1 %cmp, i32 -1, i32 %cond + ret i32 %cond2 +} + +; Function Attrs: norecurse nounwind readnone +; FIXME: this is still done with compares, we may fix that in the future +define signext i32 @compOp10(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: compOp10: +entry: + %cmp = icmp ult i32 %a, %b + %cmp1 = icmp ugt i32 %a, %b + %cond = zext i1 %cmp1 to i32 + %cond2 = select i1 %cmp, i32 -1, i32 %cond + ret i32 %cond2 +} + +; Function Attrs: norecurse nounwind readnone +; FIXME: the extsw is unnecessary but is in the DAG as well. +define signext i32 @compOp11(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: compOp11: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r5, r3, r4 +; CHECK-NEXT: subf r5, r4, r3 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: subfe r3, r3, r5 +; CHECK-NEXT: extsw r3, r3 +; CHECK-NEXT: blr +entry: + %cmp = icmp ugt i32 %a, %b + %not.cmp1 = icmp ne i32 %a, %b + %cond = sext i1 %not.cmp1 to i32 + %cond2 = select i1 %cmp, i32 1, i32 %cond + ret i32 %cond2 +} + +; Function Attrs: norecurse nounwind readnone +; FIXME: the extsw is unnecessary but is in the DAG as well. +define signext i32 @compOp12(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: compOp12: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r5, r3, r4 +; CHECK-NEXT: subf r5, r4, r3 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: subfe r3, r3, r5 +; CHECK-NEXT: extsw r3, r3 +; CHECK-NEXT: blr +entry: + %cmp = icmp ugt i32 %a, %b + %cmp1 = icmp ult i32 %a, %b + %cond = sext i1 %cmp1 to i32 + %cond2 = select i1 %cmp, i32 1, i32 %cond + ret i32 %cond2 +} + +; Function Attrs: norecurse nounwind +define void @store1(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: store1: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addis r5, r2, .LC0@toc@ha +; CHECK-NEXT: subfc r6, r3, r4 +; CHECK-NEXT: ld r5, .LC0@toc@l(r5) +; CHECK-NEXT: subf r6, r4, r3 +; CHECK-NEXT: subfe r12, r4, r3 +; CHECK-NEXT: subfe r3, r12, r6 +; CHECK-NEXT: stw r3, 0(r5) +; CHECK-NEXT: blr +entry: + %cmp.i = icmp eq i32 %a, %b + %cmp1.i = icmp ult i32 %a, %b + %..i = select i1 %cmp1.i, i32 -1, i32 1 + %retval.0.i = select i1 %cmp.i, i32 0, i32 %..i + store i32 %retval.0.i, i32* @ga, align 4 + ret void +} + +; Function Attrs: norecurse nounwind +define void @store2(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: store2: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addis r5, r2, .LC0@toc@ha +; CHECK-NEXT: subfc r6, r3, r4 +; CHECK-NEXT: ld r5, .LC0@toc@l(r5) +; CHECK-NEXT: subf r6, r4, r3 +; CHECK-NEXT: subfe r12, r4, r3 +; CHECK-NEXT: subfe r3, r12, r6 +; CHECK-NEXT: stw r3, 0(r5) +; CHECK-NEXT: blr +entry: + %cmp.i = icmp eq i32 %a, %b + %cmp1.i = icmp ugt i32 %a, %b + %..i = select i1 %cmp1.i, i32 1, i32 -1 + %retval.0.i = select i1 %cmp.i, i32 0, i32 %..i + store i32 %retval.0.i, i32* @ga, align 4 + ret void +} + +; Function Attrs: norecurse nounwind +define void @store3(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: store3: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addis r5, r2, .LC0@toc@ha +; CHECK-NEXT: subfc r6, r3, r4 +; CHECK-NEXT: ld r5, .LC0@toc@l(r5) +; CHECK-NEXT: subf r6, r4, r3 +; CHECK-NEXT: subfe r12, r4, r3 +; CHECK-NEXT: subfe r3, r12, r6 +; CHECK-NEXT: stw r3, 0(r5) +; CHECK-NEXT: blr +entry: + %cmp.i = icmp ugt i32 %a, %b + %not.cmp1.i = icmp ne i32 %a, %b + %..i = sext i1 %not.cmp1.i to i32 + %retval.0.i = select i1 %cmp.i, i32 1, i32 %..i + store i32 %retval.0.i, i32* @ga, align 4 + ret void +} + +; Function Attrs: norecurse nounwind +define void @store4(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: store4: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addis r5, r2, .LC0@toc@ha +; CHECK-NEXT: subfc r6, r3, r4 +; CHECK-NEXT: ld r5, .LC0@toc@l(r5) +; CHECK-NEXT: subf r6, r4, r3 +; CHECK-NEXT: subfe r12, r4, r3 +; CHECK-NEXT: subfe r3, r12, r6 +; CHECK-NEXT: stw r3, 0(r5) +; CHECK-NEXT: blr +entry: + %cmp.i = icmp ugt i32 %a, %b + %cmp1.i = icmp ult i32 %a, %b + %..i = sext i1 %cmp1.i to i32 + %retval.0.i = select i1 %cmp.i, i32 1, i32 %..i + store i32 %retval.0.i, i32* @ga, align 4 + ret void +} + +; Function Attrs: norecurse nounwind +define void @store5(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: store5: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addis r5, r2, .LC0@toc@ha +; CHECK-NEXT: subfc r6, r3, r4 +; CHECK-NEXT: ld r5, .LC0@toc@l(r5) +; CHECK-NEXT: subf r6, r4, r3 +; CHECK-NEXT: subfe r12, r4, r3 +; CHECK-NEXT: subfe r3, r12, r6 +; CHECK-NEXT: stw r3, 0(r5) +; CHECK-NEXT: blr +entry: + %cmp.i = icmp ult i32 %a, %b + %not.cmp1.i = icmp ne i32 %a, %b + %..i = zext i1 %not.cmp1.i to i32 + %retval.0.i = select i1 %cmp.i, i32 -1, i32 %..i + store i32 %retval.0.i, i32* @ga, align 4 + ret void +} + +; Function Attrs: norecurse nounwind +; FIXME: this is still done with compares, we may fix that in the future +define void @store6(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: store6: +entry: + %cmp.i = icmp ult i32 %a, %b + %cmp1.i = icmp ugt i32 %a, %b + %..i = zext i1 %cmp1.i to i32 + %retval.0.i = select i1 %cmp.i, i32 -1, i32 %..i + store i32 %retval.0.i, i32* @ga, align 4 + ret void +} + +; Function Attrs: norecurse nounwind +define void @store7(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: store7: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addis r5, r2, .LC0@toc@ha +; CHECK-NEXT: subfc r6, r3, r4 +; CHECK-NEXT: ld r5, .LC0@toc@l(r5) +; CHECK-NEXT: subf r6, r4, r3 +; CHECK-NEXT: subfe r12, r4, r3 +; CHECK-NEXT: subfe r3, r12, r6 +; CHECK-NEXT: stw r3, 0(r5) +; CHECK-NEXT: blr +entry: + %cmp.i = icmp eq i32 %a, %b + %cmp1.i = icmp ult i32 %a, %b + %cond.i = select i1 %cmp1.i, i32 -1, i32 1 + %cond2.i = select i1 %cmp.i, i32 0, i32 %cond.i + store i32 %cond2.i, i32* @ga, align 4 + ret void +} + +; Function Attrs: norecurse nounwind +define void @store8(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: store8: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addis r5, r2, .LC0@toc@ha +; CHECK-NEXT: subfc r6, r3, r4 +; CHECK-NEXT: ld r5, .LC0@toc@l(r5) +; CHECK-NEXT: subf r6, r4, r3 +; CHECK-NEXT: subfe r12, r4, r3 +; CHECK-NEXT: subfe r3, r12, r6 +; CHECK-NEXT: stw r3, 0(r5) +; CHECK-NEXT: blr +entry: + %cmp.i = icmp eq i32 %a, %b + %cmp1.i = icmp ugt i32 %a, %b + %cond.i = select i1 %cmp1.i, i32 1, i32 -1 + %cond2.i = select i1 %cmp.i, i32 0, i32 %cond.i + store i32 %cond2.i, i32* @ga, align 4 + ret void +} + +; Function Attrs: norecurse nounwind +define void @store9(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: store9: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addis r5, r2, .LC0@toc@ha +; CHECK-NEXT: subfc r6, r3, r4 +; CHECK-NEXT: ld r5, .LC0@toc@l(r5) +; CHECK-NEXT: subf r6, r4, r3 +; CHECK-NEXT: subfe r12, r4, r3 +; CHECK-NEXT: subfe r3, r12, r6 +; CHECK-NEXT: stw r3, 0(r5) +; CHECK-NEXT: blr +entry: + %cmp.i = icmp ult i32 %a, %b + %not.cmp1.i = icmp ne i32 %a, %b + %cond.i = zext i1 %not.cmp1.i to i32 + %cond2.i = select i1 %cmp.i, i32 -1, i32 %cond.i + store i32 %cond2.i, i32* @ga, align 4 + ret void +} + +; Function Attrs: norecurse nounwind +; FIXME: this is still done with compares, we may fix that in the future +define void @store10(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: store10: +entry: + %cmp.i = icmp ult i32 %a, %b + %cmp1.i = icmp ugt i32 %a, %b + %cond.i = zext i1 %cmp1.i to i32 + %cond2.i = select i1 %cmp.i, i32 -1, i32 %cond.i + store i32 %cond2.i, i32* @ga, align 4 + ret void +} + +; Function Attrs: norecurse nounwind +define void @store11(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: store11: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addis r5, r2, .LC0@toc@ha +; CHECK-NEXT: subfc r6, r3, r4 +; CHECK-NEXT: ld r5, .LC0@toc@l(r5) +; CHECK-NEXT: subf r6, r4, r3 +; CHECK-NEXT: subfe r12, r4, r3 +; CHECK-NEXT: subfe r3, r12, r6 +; CHECK-NEXT: stw r3, 0(r5) +; CHECK-NEXT: blr +entry: + %cmp.i = icmp ugt i32 %a, %b + %not.cmp1.i = icmp ne i32 %a, %b + %cond.i = sext i1 %not.cmp1.i to i32 + %cond2.i = select i1 %cmp.i, i32 1, i32 %cond.i + store i32 %cond2.i, i32* @ga, align 4 + ret void +} + +; Function Attrs: norecurse nounwind +define void @store12(i32 zeroext %a, i32 zeroext %b) { +; CHECK-LABEL: store12: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addis r5, r2, .LC0@toc@ha +; CHECK-NEXT: subfc r6, r3, r4 +; CHECK-NEXT: ld r5, .LC0@toc@l(r5) +; CHECK-NEXT: subf r6, r4, r3 +; CHECK-NEXT: subfe r12, r4, r3 +; CHECK-NEXT: subfe r3, r12, r6 +; CHECK-NEXT: stw r3, 0(r5) +; CHECK-NEXT: blr +entry: + %cmp.i = icmp ugt i32 %a, %b + %cmp1.i = icmp ult i32 %a, %b + %cond.i = sext i1 %cmp1.i to i32 + %cond2.i = select i1 %cmp.i, i32 1, i32 %cond.i + store i32 %cond2.i, i32* @ga, align 4 + ret void +} Index: test/CodeGen/PowerPC/comparisonOps64.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/comparisonOps64.ll @@ -0,0 +1,437 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s + +@ga = common local_unnamed_addr global i64 0, align 8 + +; Function Attrs: norecurse nounwind readnone +define i64 @compOp1(i64 %a, i64 %b) { +; CHECK-LABEL: compOp1: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r5, r3, r4 +; CHECK-NEXT: sub r5, r3, r4 +; CHECK-NEXT: subfe r12, r4, r3 +; CHECK-NEXT: subfe r3, r12, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp eq i64 %a, %b + %cmp1 = icmp ult i64 %a, %b + %. = select i1 %cmp1, i64 -1, i64 1 + %retval.0 = select i1 %cmp, i64 0, i64 %. + ret i64 %retval.0 +} + +; Function Attrs: norecurse nounwind readnone +define i64 @compOp2(i64 %a, i64 %b) { +; CHECK-LABEL: compOp2: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r5, r3, r4 +; CHECK-NEXT: sub r5, r3, r4 +; CHECK-NEXT: subfe r12, r4, r3 +; CHECK-NEXT: subfe r3, r12, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp eq i64 %a, %b + %cmp1 = icmp ugt i64 %a, %b + %. = select i1 %cmp1, i64 1, i64 -1 + %retval.0 = select i1 %cmp, i64 0, i64 %. + ret i64 %retval.0 +} + +; Function Attrs: norecurse nounwind readnone +define i64 @compOp3(i64 %a, i64 %b) { +; CHECK-LABEL: compOp3: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r5, r3, r4 +; CHECK-NEXT: sub r5, r3, r4 +; CHECK-NEXT: subfe r12, r4, r3 +; CHECK-NEXT: subfe r3, r12, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ugt i64 %a, %b + %not.cmp1 = icmp ne i64 %a, %b + %. = sext i1 %not.cmp1 to i64 + %retval.0 = select i1 %cmp, i64 1, i64 %. + ret i64 %retval.0 +} + +; Function Attrs: norecurse nounwind readnone +define i64 @compOp4(i64 %a, i64 %b) { +; CHECK-LABEL: compOp4: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r5, r3, r4 +; CHECK-NEXT: sub r5, r3, r4 +; CHECK-NEXT: subfe r12, r4, r3 +; CHECK-NEXT: subfe r3, r12, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ugt i64 %a, %b + %cmp1 = icmp ult i64 %a, %b + %. = sext i1 %cmp1 to i64 + %retval.0 = select i1 %cmp, i64 1, i64 %. + ret i64 %retval.0 +} + +; Function Attrs: norecurse nounwind readnone +define i64 @compOp5(i64 %a, i64 %b) { +; CHECK-LABEL: compOp5: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r5, r3, r4 +; CHECK-NEXT: sub r5, r3, r4 +; CHECK-NEXT: subfe r12, r4, r3 +; CHECK-NEXT: subfe r3, r12, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ult i64 %a, %b + %not.cmp1 = icmp ne i64 %a, %b + %. = zext i1 %not.cmp1 to i64 + %retval.0 = select i1 %cmp, i64 -1, i64 %. + ret i64 %retval.0 +} + +; Function Attrs: norecurse nounwind readnone +; FIXME: this is still done with compares, we may fix that in the future +define i64 @compOp6(i64 %a, i64 %b) { +; CHECK-LABEL: compOp6: +entry: + %cmp = icmp ult i64 %a, %b + %cmp1 = icmp ugt i64 %a, %b + %. = zext i1 %cmp1 to i64 + %retval.0 = select i1 %cmp, i64 -1, i64 %. + ret i64 %retval.0 +} + +; Function Attrs: norecurse nounwind readnone +define i64 @compOp7(i64 %a, i64 %b) { +; CHECK-LABEL: compOp7: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r5, r3, r4 +; CHECK-NEXT: sub r5, r3, r4 +; CHECK-NEXT: subfe r12, r4, r3 +; CHECK-NEXT: subfe r3, r12, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp eq i64 %a, %b + %cmp1 = icmp ult i64 %a, %b + %phitmp = select i1 %cmp1, i64 -1, i64 1 + %cond2 = select i1 %cmp, i64 0, i64 %phitmp + ret i64 %cond2 +} + +; Function Attrs: norecurse nounwind readnone +define i64 @compOp8(i64 %a, i64 %b) { +; CHECK-LABEL: compOp8: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r5, r3, r4 +; CHECK-NEXT: sub r5, r3, r4 +; CHECK-NEXT: subfe r12, r4, r3 +; CHECK-NEXT: subfe r3, r12, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp eq i64 %a, %b + %cmp1 = icmp ugt i64 %a, %b + %phitmp = select i1 %cmp1, i64 1, i64 -1 + %cond2 = select i1 %cmp, i64 0, i64 %phitmp + ret i64 %cond2 +} + +; Function Attrs: norecurse nounwind readnone +define i64 @compOp9(i64 %a, i64 %b) { +; CHECK-LABEL: compOp9: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r5, r3, r4 +; CHECK-NEXT: sub r5, r3, r4 +; CHECK-NEXT: subfe r12, r4, r3 +; CHECK-NEXT: subfe r3, r12, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ult i64 %a, %b + %not.cmp1 = icmp ne i64 %a, %b + %phitmp = zext i1 %not.cmp1 to i64 + %cond2 = select i1 %cmp, i64 -1, i64 %phitmp + ret i64 %cond2 +} + +; Function Attrs: norecurse nounwind readnone +; FIXME: this is still done with compares, we may fix that in the future +define i64 @compOp10(i64 %a, i64 %b) { +; CHECK-LABEL: compOp10: +entry: + %cmp = icmp ult i64 %a, %b + %cmp1 = icmp ugt i64 %a, %b + %phitmp = zext i1 %cmp1 to i64 + %cond2 = select i1 %cmp, i64 -1, i64 %phitmp + ret i64 %cond2 +} + +; Function Attrs: norecurse nounwind readnone +define i64 @compOp11(i64 %a, i64 %b) { +; CHECK-LABEL: compOp11: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r5, r3, r4 +; CHECK-NEXT: sub r5, r3, r4 +; CHECK-NEXT: subfe r12, r4, r3 +; CHECK-NEXT: subfe r3, r12, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ugt i64 %a, %b + %not.cmp1 = icmp ne i64 %a, %b + %phitmp = sext i1 %not.cmp1 to i64 + %cond2 = select i1 %cmp, i64 1, i64 %phitmp + ret i64 %cond2 +} + +; Function Attrs: norecurse nounwind readnone +define i64 @compOp12(i64 %a, i64 %b) { +; CHECK-LABEL: compOp12: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r5, r3, r4 +; CHECK-NEXT: sub r5, r3, r4 +; CHECK-NEXT: subfe r12, r4, r3 +; CHECK-NEXT: subfe r3, r12, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ugt i64 %a, %b + %cmp1 = icmp ult i64 %a, %b + %phitmp = sext i1 %cmp1 to i64 + %cond2 = select i1 %cmp, i64 1, i64 %phitmp + ret i64 %cond2 +} + +; Function Attrs: norecurse nounwind +define void @store1(i64 %a, i64 %b) { +; CHECK-LABEL: store1: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addis r5, r2, .LC0@toc@ha +; CHECK-NEXT: subfc r6, r3, r4 +; CHECK-NEXT: ld r5, .LC0@toc@l(r5) +; CHECK-NEXT: sub r6, r3, r4 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: subfe r3, r3, r6 +; CHECK-NEXT: std r3, 0(r5) +; CHECK-NEXT: blr +entry: + %cmp.i = icmp eq i64 %a, %b + %cmp1.i = icmp ult i64 %a, %b + %..i = select i1 %cmp1.i, i64 -1, i64 1 + %retval.0.i = select i1 %cmp.i, i64 0, i64 %..i + store i64 %retval.0.i, i64* @ga, align 8 + ret void +} + +; Function Attrs: norecurse nounwind +define void @store2(i64 %a, i64 %b) { +; CHECK-LABEL: store2: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addis r5, r2, .LC0@toc@ha +; CHECK-NEXT: subfc r6, r3, r4 +; CHECK-NEXT: ld r5, .LC0@toc@l(r5) +; CHECK-NEXT: sub r6, r3, r4 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: subfe r3, r3, r6 +; CHECK-NEXT: std r3, 0(r5) +; CHECK-NEXT: blr +entry: + %cmp.i = icmp eq i64 %a, %b + %cmp1.i = icmp ugt i64 %a, %b + %..i = select i1 %cmp1.i, i64 1, i64 -1 + %retval.0.i = select i1 %cmp.i, i64 0, i64 %..i + store i64 %retval.0.i, i64* @ga, align 8 + ret void +} + +; Function Attrs: norecurse nounwind +define void @store3(i64 %a, i64 %b) { +; CHECK-LABEL: store3: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addis r5, r2, .LC0@toc@ha +; CHECK-NEXT: subfc r6, r3, r4 +; CHECK-NEXT: ld r5, .LC0@toc@l(r5) +; CHECK-NEXT: sub r6, r3, r4 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: subfe r3, r3, r6 +; CHECK-NEXT: std r3, 0(r5) +; CHECK-NEXT: blr +entry: + %cmp.i = icmp ugt i64 %a, %b + %not.cmp1.i = icmp ne i64 %a, %b + %..i = sext i1 %not.cmp1.i to i64 + %retval.0.i = select i1 %cmp.i, i64 1, i64 %..i + store i64 %retval.0.i, i64* @ga, align 8 + ret void +} + +; Function Attrs: norecurse nounwind +define void @store4(i64 %a, i64 %b) { +; CHECK-LABEL: store4: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addis r5, r2, .LC0@toc@ha +; CHECK-NEXT: subfc r6, r3, r4 +; CHECK-NEXT: ld r5, .LC0@toc@l(r5) +; CHECK-NEXT: sub r6, r3, r4 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: subfe r3, r3, r6 +; CHECK-NEXT: std r3, 0(r5) +; CHECK-NEXT: blr +entry: + %cmp.i = icmp ugt i64 %a, %b + %cmp1.i = icmp ult i64 %a, %b + %..i = sext i1 %cmp1.i to i64 + %retval.0.i = select i1 %cmp.i, i64 1, i64 %..i + store i64 %retval.0.i, i64* @ga, align 8 + ret void +} + +; Function Attrs: norecurse nounwind +define void @store5(i64 %a, i64 %b) { +; CHECK-LABEL: store5: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addis r5, r2, .LC0@toc@ha +; CHECK-NEXT: subfc r6, r3, r4 +; CHECK-NEXT: ld r5, .LC0@toc@l(r5) +; CHECK-NEXT: sub r6, r3, r4 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: subfe r3, r3, r6 +; CHECK-NEXT: std r3, 0(r5) +; CHECK-NEXT: blr +entry: + %cmp.i = icmp ult i64 %a, %b + %not.cmp1.i = icmp ne i64 %a, %b + %..i = zext i1 %not.cmp1.i to i64 + %retval.0.i = select i1 %cmp.i, i64 -1, i64 %..i + store i64 %retval.0.i, i64* @ga, align 8 + ret void +} + +; Function Attrs: norecurse nounwind +; FIXME: this is still done with compares, we may fix that in the future +define void @store6(i64 %a, i64 %b) { +; CHECK-LABEL: store6: +entry: + %cmp.i = icmp ult i64 %a, %b + %cmp1.i = icmp ugt i64 %a, %b + %..i = zext i1 %cmp1.i to i64 + %retval.0.i = select i1 %cmp.i, i64 -1, i64 %..i + store i64 %retval.0.i, i64* @ga, align 8 + ret void +} + +; Function Attrs: norecurse nounwind +define void @store7(i64 %a, i64 %b) { +; CHECK-LABEL: store7: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addis r5, r2, .LC0@toc@ha +; CHECK-NEXT: subfc r6, r3, r4 +; CHECK-NEXT: ld r5, .LC0@toc@l(r5) +; CHECK-NEXT: sub r6, r3, r4 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: subfe r3, r3, r6 +; CHECK-NEXT: std r3, 0(r5) +; CHECK-NEXT: blr +entry: + %cmp.i = icmp eq i64 %a, %b + %cmp1.i = icmp ult i64 %a, %b + %phitmp.i = select i1 %cmp1.i, i64 -1, i64 1 + %cond2.i = select i1 %cmp.i, i64 0, i64 %phitmp.i + store i64 %cond2.i, i64* @ga, align 8 + ret void +} + +; Function Attrs: norecurse nounwind +define void @store8(i64 %a, i64 %b) { +; CHECK-LABEL: store8: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addis r5, r2, .LC0@toc@ha +; CHECK-NEXT: subfc r6, r3, r4 +; CHECK-NEXT: ld r5, .LC0@toc@l(r5) +; CHECK-NEXT: sub r6, r3, r4 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: subfe r3, r3, r6 +; CHECK-NEXT: std r3, 0(r5) +; CHECK-NEXT: blr +entry: + %cmp.i = icmp eq i64 %a, %b + %cmp1.i = icmp ugt i64 %a, %b + %phitmp.i = select i1 %cmp1.i, i64 1, i64 -1 + %cond2.i = select i1 %cmp.i, i64 0, i64 %phitmp.i + store i64 %cond2.i, i64* @ga, align 8 + ret void +} + +; Function Attrs: norecurse nounwind +define void @store9(i64 %a, i64 %b) { +; CHECK-LABEL: store9: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addis r5, r2, .LC0@toc@ha +; CHECK-NEXT: subfc r6, r3, r4 +; CHECK-NEXT: ld r5, .LC0@toc@l(r5) +; CHECK-NEXT: sub r6, r3, r4 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: subfe r3, r3, r6 +; CHECK-NEXT: std r3, 0(r5) +; CHECK-NEXT: blr +entry: + %cmp.i = icmp ult i64 %a, %b + %not.cmp1.i = icmp ne i64 %a, %b + %phitmp.i = zext i1 %not.cmp1.i to i64 + %cond2.i = select i1 %cmp.i, i64 -1, i64 %phitmp.i + store i64 %cond2.i, i64* @ga, align 8 + ret void +} + +; Function Attrs: norecurse nounwind +; FIXME: this is still done with compares, we may fix that in the future +define void @store10(i64 %a, i64 %b) { +; CHECK-LABEL: store10: +entry: + %cmp.i = icmp ult i64 %a, %b + %cmp1.i = icmp ugt i64 %a, %b + %phitmp.i = zext i1 %cmp1.i to i64 + %cond2.i = select i1 %cmp.i, i64 -1, i64 %phitmp.i + store i64 %cond2.i, i64* @ga, align 8 + ret void +} + +; Function Attrs: norecurse nounwind +define void @store11(i64 %a, i64 %b) { +; CHECK-LABEL: store11: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addis r5, r2, .LC0@toc@ha +; CHECK-NEXT: subfc r6, r3, r4 +; CHECK-NEXT: ld r5, .LC0@toc@l(r5) +; CHECK-NEXT: sub r6, r3, r4 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: subfe r3, r3, r6 +; CHECK-NEXT: std r3, 0(r5) +; CHECK-NEXT: blr +entry: + %cmp.i = icmp ugt i64 %a, %b + %not.cmp1.i = icmp ne i64 %a, %b + %phitmp.i = sext i1 %not.cmp1.i to i64 + %cond2.i = select i1 %cmp.i, i64 1, i64 %phitmp.i + store i64 %cond2.i, i64* @ga, align 8 + ret void +} + +; Function Attrs: norecurse nounwind +define void @store12(i64 %a, i64 %b) { +; CHECK-LABEL: store12: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addis r5, r2, .LC0@toc@ha +; CHECK-NEXT: subfc r6, r3, r4 +; CHECK-NEXT: ld r5, .LC0@toc@l(r5) +; CHECK-NEXT: sub r6, r3, r4 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: subfe r3, r3, r6 +; CHECK-NEXT: std r3, 0(r5) +; CHECK-NEXT: blr +entry: + %cmp.i = icmp ugt i64 %a, %b + %cmp1.i = icmp ult i64 %a, %b + %phitmp.i = sext i1 %cmp1.i to i64 + %cond2.i = select i1 %cmp.i, i64 1, i64 %phitmp.i + store i64 %cond2.i, i64* @ga, align 8 + ret void +} Index: test/CodeGen/PowerPC/i1-ext-fold.ll =================================================================== --- test/CodeGen/PowerPC/i1-ext-fold.ll +++ test/CodeGen/PowerPC/i1-ext-fold.ll @@ -13,18 +13,10 @@ ; CHECK-LABEL: @foo ; CHECK-NO-ISEL-LABEL: @foo -; CHECK-DAG: cmpw -; CHECK-DAG: li [[REG1:[0-9]+]], 0 -; CHECK-DAG: li [[REG2:[0-9]+]], 16 -; CHECK: isel 3, [[REG2]], [[REG1]], +; CHECK-DAG: subf [[REG1:[0-9]+]], 4, 3 +; CHECK-DAG: rldicl [[REG2:[0-9]+]], [[REG1]], 1, 63 +; CHECK-DAG: sldi [[REG3:[0-9]+]], [[REG2]], 4 ; CHECK: blr - -; CHECK-NO-ISEL: bc 12, 0, [[TRUE:.LBB[0-9]+]] -; CHECK-NO-ISEL: ori 3, 5, 0 -; CHECK-NO-ISEL-NEXT: blr -; CHECK-NO-ISEL-NEXT: [[TRUE]] -; CHECK-NO-ISEL-NEXT: addi 3, 12, 0 -; CHECK-NO-ISEL-NEXT: blr } ; Function Attrs: nounwind readnone @@ -60,19 +52,13 @@ %shl = shl nuw nsw i32 %conv, 4 ret i32 %shl -; CHECK-LABEL: @foo3 -; CHECK-NO-ISEL-LABEL: @foo3 -; CHECK-DAG: cmpw -; CHECK-DAG: li [[REG1:[0-9]+]], 16 -; CHECK: isel 3, 0, [[REG1]], -; CHECK: blr +; CHECK-ALL-LABEL: @foo3 +; CHECK-ALL: subf [[SUB:[0-9]+]], 3, 4 +; CHECK-ALL: rldicl [[SH:[0-9]+]], [[SUB]], 33, 63 +; CHECK-ALL: xori [[FLIP:[0-9]+]], [[SH]], 1 +; CHECK-ALL: sldi 3, [[FLIP]], 4 +; CHECK-ALL: blr -; CHECK-NO-ISEL: bc 12, 1, [[TRUE:.LBB[0-9]+]] -; CHECK-NO-ISEL: ori 3, 5, 0 -; CHECK-NO-ISEL-NEXT: blr -; CHECK-NO-ISEL-NEXT: [[TRUE]] -; CHECK-NO-ISEL-NEXT: addi 3, 0, 0 -; CHECK-NO-ISEL-NEXT: blr } attributes #0 = { nounwind readnone } Index: test/CodeGen/PowerPC/ppc-crbits-onoff.ll =================================================================== --- test/CodeGen/PowerPC/ppc-crbits-onoff.ll +++ test/CodeGen/PowerPC/ppc-crbits-onoff.ll @@ -12,19 +12,14 @@ %and = zext i1 %and3 to i32 ret i32 %and -; CHECK-LABEL: @crbitsoff -; CHECK-NO-ISEL-LABEL: @crbitsoff -; CHECK-DAG: cmplwi {{[0-9]+}}, 3, 0 -; CHECK-DAG: li [[REG2:[0-9]+]], 1 -; CHECK-DAG: cntlzw [[REG3:[0-9]+]], -; CHECK: isel [[REG4:[0-9]+]], 0, [[REG2]] -; CHECK-NO-ISEL: bc 12, 2, [[TRUE:.LBB[0-9]+]] -; CHECK-NO-ISEL: ori 4, 5, 0 -; CHECK-NO-ISEL-NEXT: b [[SUCCESSOR:.LBB[0-9]+]] -; CHECK-NO-ISEL: [[TRUE]] -; CHECK-NO-ISEL-NEXT: addi 4, 0, 0 -; CHECK: and 3, [[REG4]], [[REG3]] -; CHECK: blr +; CHECK-ALL-LABEL: @crbitsoff +; CHECK-ALL-DAG: cntlzw [[CNTv1:[0-9]+]], 3 +; CHECK-ALL-DAG: cntlzw [[CNTv2:[0-9]+]], 4 +; CHECK-ALL-DAG: srwi [[SH:[0-9]+]], [[CNTv1]], 5 +; CHECK-ALL-DAG: xori [[FLIP:[0-9]+]], [[SH]], 1 +; CHECK-ALL-DAG: rlwinm [[SH2:[0-9]+]], [[CNTv2]], 27, 5, 31 +; CHECK-ALL: and 3, [[FLIP]], [[SH2]] +; CHECK-ALL: blr } define signext i32 @crbitson(i32 signext %v1, i32 signext %v2) #1 { Index: test/CodeGen/PowerPC/testSelectSetCCEQ.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/testSelectSetCCEQ.ll @@ -0,0 +1,131 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ +; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ +; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl + +define i64 @set_flagi64(i64 %a, i64 %b, i64 %flags) { +; CHECK-LABEL: set_flagi64: +; CHECK: xor r3, r3, r4 +; CHECK-NEXT: cntlzd r3, r3 +; CHECK-NEXT: rldicl r3, r3, 58, 63 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp eq i64 %a, %b + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i32 @set_flagi32(i32 %a, i32 %b, i32 %flags) { +; CHECK-LABEL: set_flagi32: +; CHECK: xor r3, r3, r4 +; CHECK-NEXT: cntlzw r3, r3 +; CHECK-NEXT: srwi r3, r3, 5 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp eq i32 %a, %b + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i32 @set_flagi64i32(i64 %a, i64 %b, i32 %flags) { +; CHECK-LABEL: set_flagi64i32: +; CHECK: xor r3, r3, r4 +; CHECK-NEXT: cntlzd r3, r3 +; CHECK-NEXT: rldicl r3, r3, 58, 63 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp eq i64 %a, %b + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i64 @set_flagi32i64(i32 %a, i32 %b, i64 %flags) { +; CHECK-LABEL: set_flagi32i64: +; CHECK: xor r3, r3, r4 +; CHECK-NEXT: cntlzw r3, r3 +; CHECK-NEXT: srwi r3, r3, 5 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp eq i32 %a, %b + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i64 @set_flagi64_z(i64 %a, i64 %flags) { +; CHECK-LABEL: set_flagi64_z: +; CHECK: cntlzd r3, r3 +; CHECK-NEXT: rldicl r3, r3, 58, 63 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp eq i64 %a, 0 + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i32 @set_flagi32_z(i32 %a, i32 %flags) { +; CHECK-LABEL: set_flagi32_z: +; CHECK: cntlzw r3, r3 +; CHECK-NEXT: srwi r3, r3, 5 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp eq i32 %a, 0 + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i32 @set_flagi64i32_z(i64 %a, i32 %flags) { +; CHECK-LABEL: set_flagi64i32_z: +; CHECK: cntlzd r3, r3 +; CHECK-NEXT: rldicl r3, r3, 58, 63 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp eq i64 %a, 0 + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i64 @set_flagi32i64_z(i32 %a, i64 %flags) { +; CHECK-LABEL: set_flagi32i64_z: +; CHECK: cntlzw r3, r3 +; CHECK-NEXT: srwi r3, r3, 5 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp eq i32 %a, 0 + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} Index: test/CodeGen/PowerPC/testSelectSetCCGE.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/testSelectSetCCGE.ll @@ -0,0 +1,142 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ +; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ +; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl + +define i64 @set_flagi64(i64 %a, i64 %b, i64 %flags) { +; CHECK-LABEL: set_flagi64: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: sradi r6, r3, 63 +; CHECK-NEXT: rldicl r7, r4, 1, 63 +; CHECK-NEXT: subfc r3, r4, r3 +; CHECK-NEXT: adde r3, r6, r7 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp sge i64 %a, %b + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i32 @set_flagi32(i32 signext %a, i32 signext %b, i32 %flags) { +; CHECK-LABEL: set_flagi32: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subf r3, r4, r3 +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: xori r3, r3, 1 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp sge i32 %a, %b + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i32 @set_flagi64i32(i64 %a, i64 %b, i32 %flags) { +; CHECK-LABEL: set_flagi64i32: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: sradi r6, r3, 63 +; CHECK-NEXT: rldicl r7, r4, 1, 63 +; CHECK-NEXT: subfc r3, r4, r3 +; CHECK-NEXT: adde r3, r6, r7 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp sge i64 %a, %b + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i64 @set_flagi32i64(i32 signext %a, i32 signext %b, i64 %flags) { +; CHECK-LABEL: set_flagi32i64: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subf r3, r4, r3 +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: xori r3, r3, 1 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp sge i32 %a, %b + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i64 @set_flagi64_z(i64 %a, i64 %flags) { +; CHECK-LABEL: set_flagi64_z: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: li r5, 8 +; CHECK-NEXT: rldicl r3, r3, 4, 60 +; CHECK-NEXT: andc r3, r5, r3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp sge i64 %a, 0 + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i32 @set_flagi32_z(i32 signext %a, i32 %flags) { +; CHECK-LABEL: set_flagi32_z: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: srwi r3, r3, 28 +; CHECK-NEXT: nor r3, r3, r3 +; CHECK-NEXT: rlwinm r3, r3, 0, 28, 28 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp sge i32 %a, 0 + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i32 @set_flagi64i32_z(i64 %a, i32 %flags) { +; CHECK-LABEL: set_flagi64i32_z: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: xori r3, r3, 1 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp sge i64 %a, 0 + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i64 @set_flagi32i64_z(i32 signext %a, i64 %flags) { +; CHECK-LABEL: set_flagi32i64_z: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: nor r3, r3, r3 +; CHECK-NEXT: srwi r3, r3, 31 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp sge i32 %a, 0 + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + Index: test/CodeGen/PowerPC/testSelectSetCCGT.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/testSelectSetCCGT.ll @@ -0,0 +1,143 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ +; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ +; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl + +define i64 @set_flagi64(i64 %a, i64 %b, i64 %flags) { +; CHECK-LABEL: set_flagi64: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: sradi r6, r4, 63 +; CHECK-NEXT: rldicl r7, r3, 1, 63 +; CHECK-NEXT: subfc r12, r3, r4 +; CHECK-NEXT: adde r3, r7, r6 +; CHECK-NEXT: xori r3, r3, 1 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp sgt i64 %a, %b + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i32 @set_flagi32(i32 signext %a, i32 signext %b, i32 %flags) { +; CHECK-LABEL: set_flagi32: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subf r3, r3, r4 +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp sgt i32 %a, %b + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i32 @set_flagi64i32(i64 %a, i64 %b, i32 %flags) { +; CHECK-LABEL: set_flagi64i32: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: sradi r6, r4, 63 +; CHECK-NEXT: rldicl r7, r3, 1, 63 +; CHECK-NEXT: subfc r12, r3, r4 +; CHECK-NEXT: adde r3, r7, r6 +; CHECK-NEXT: xori r3, r3, 1 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp sgt i64 %a, %b + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i64 @set_flagi32i64(i32 signext %a, i32 signext %b, i64 %flags) { +; CHECK-LABEL: set_flagi32i64: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subf r3, r3, r4 +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp sgt i32 %a, %b + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i64 @set_flagi64_z(i64 %a, i64 %flags) { +; CHECK-LABEL: set_flagi64_z: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addi r5, r3, -1 +; CHECK-NEXT: nor r3, r5, r3 +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp sgt i64 %a, 0 + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i32 @set_flagi32_z(i32 signext %a, i32 %flags) { +; CHECK-LABEL: set_flagi32_z: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: neg r3, r3 +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp sgt i32 %a, 0 + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i32 @set_flagi64i32_z(i64 %a, i32 %flags) { +; CHECK-LABEL: set_flagi64i32_z: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addi r5, r3, -1 +; CHECK-NEXT: nor r3, r5, r3 +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp sgt i64 %a, 0 + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i64 @set_flagi32i64_z(i32 signext %a, i64 %flags) { +; CHECK-LABEL: set_flagi32i64_z: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: neg r3, r3 +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp sgt i32 %a, 0 + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} Index: test/CodeGen/PowerPC/testSelectSetCCLE.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/testSelectSetCCLE.ll @@ -0,0 +1,145 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ +; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ +; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl + +define i64 @set_flagi64(i64 %a, i64 %b, i64 %flags) { +; CHECK-LABEL: set_flagi64: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: sradi r6, r4, 63 +; CHECK-NEXT: rldicl r7, r3, 1, 63 +; CHECK-NEXT: subfc r12, r3, r4 +; CHECK-NEXT: adde r3, r6, r7 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp sle i64 %a, %b + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i32 @set_flagi32(i32 signext %a, i32 signext %b, i32 %flags) { +; CHECK-LABEL: set_flagi32: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subf r3, r3, r4 +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: xori r3, r3, 1 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp sle i32 %a, %b + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i32 @set_flagi64i32(i64 %a, i64 %b, i32 %flags) { +; CHECK-LABEL: set_flagi64i32: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: sradi r6, r4, 63 +; CHECK-NEXT: rldicl r7, r3, 1, 63 +; CHECK-NEXT: subfc r12, r3, r4 +; CHECK-NEXT: adde r3, r6, r7 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp sle i64 %a, %b + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i64 @set_flagi32i64(i32 signext %a, i32 signext %b, i64 %flags) { +; CHECK-LABEL: set_flagi32i64: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subf r3, r3, r4 +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: xori r3, r3, 1 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp sle i32 %a, %b + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i64 @set_flagi64_z(i64 %a, i64 %flags) { +; CHECK-LABEL: set_flagi64_z: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addi r5, r3, -1 +; CHECK-NEXT: or r3, r5, r3 +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp sle i64 %a, 0 + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i32 @set_flagi32_z(i32 signext %a, i32 %flags) { +; CHECK-LABEL: set_flagi32_z: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: neg r3, r3 +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: xori r3, r3, 1 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp sle i32 %a, 0 + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i32 @set_flagi64i32_z(i64 %a, i32 %flags) { +; CHECK-LABEL: set_flagi64i32_z: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addi r5, r3, -1 +; CHECK-NEXT: or r3, r5, r3 +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp sle i64 %a, 0 + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i64 @set_flagi32i64_z(i32 signext %a, i64 %flags) { +; CHECK-LABEL: set_flagi32i64_z: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: neg r3, r3 +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: xori r3, r3, 1 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp sle i32 %a, 0 + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} Index: test/CodeGen/PowerPC/testSelectSetCCLT.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/testSelectSetCCLT.ll @@ -0,0 +1,137 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ +; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ +; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl + +define i64 @set_flagi64(i64 %a, i64 %b, i64 %flags) { +; CHECK-LABEL: set_flagi64: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: sradi r6, r3, 63 +; CHECK-NEXT: rldicl r7, r4, 1, 63 +; CHECK-NEXT: subfc r3, r4, r3 +; CHECK-NEXT: adde r3, r7, r6 +; CHECK-NEXT: xori r3, r3, 1 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp slt i64 %a, %b + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i32 @set_flagi32(i32 signext %a, i32 signext %b, i32 zeroext %flags) { +; CHECK-LABEL: set_flagi32: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subf r3, r4, r3 +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp slt i32 %a, %b + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i32 @set_flagi64i32(i64 %a, i64 %b, i32 zeroext %flags) { +; CHECK-LABEL: set_flagi64i32: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: sradi r6, r3, 63 +; CHECK-NEXT: rldicl r7, r4, 1, 63 +; CHECK-NEXT: subfc r3, r4, r3 +; CHECK-NEXT: adde r3, r7, r6 +; CHECK-NEXT: xori r3, r3, 1 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp slt i64 %a, %b + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i64 @set_flagi32i64(i32 signext %a, i32 signext %b, i64 %flags) { +; CHECK-LABEL: set_flagi32i64: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subf r3, r4, r3 +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp slt i32 %a, %b + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i64 @set_flagi64_z(i64 %a, i64 %flags) { +; CHECK-LABEL: set_flagi64_z: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: rotldi r3, r3, 1 +; CHECK-NEXT: rldic r3, r3, 3, 60 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp slt i64 %a, 0 + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i32 @set_flagi32_z(i32 signext %a, i32 %flags) { +; CHECK-LABEL: set_flagi32_z: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: rlwinm r3, r3, 4, 28, 28 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp slt i32 %a, 0 + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i32 @set_flagi64i32_z(i64 %a, i32 %flags) { +; CHECK-LABEL: set_flagi64i32_z: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp slt i64 %a, 0 + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i64 @set_flagi32i64_z(i32 signext %a, i64 %flags) { +; CHECK-LABEL: set_flagi32i64_z: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: srwi r3, r3, 31 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp slt i32 %a, 0 + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + Index: test/CodeGen/PowerPC/testSelectSetCCNE.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/testSelectSetCCNE.ll @@ -0,0 +1,135 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ +; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ +; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl + +define i64 @set_flagi64(i64 %a, i64 %b, i64 %flags) { +; CHECK-LABEL: set_flagi64: +; CHECK: xor r3, r3, r4 +; CHECK-NEXT: addic r4, r3, -1 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ne i64 %a, %b + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i32 @set_flagi32(i32 %a, i32 %b, i32 %flags) { +; CHECK-LABEL: set_flagi32: +; CHECK: xor r3, r3, r4 +; CHECK-NEXT: cntlzw r3, r3 +; CHECK-NEXT: srwi r3, r3, 5 +; CHECK-NEXT: xori r3, r3, 1 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ne i32 %a, %b + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i32 @set_flagi64i32(i64 %a, i64 %b, i32 %flags) { +; CHECK-LABEL: set_flagi64i32: +; CHECK: xor r3, r3, r4 +; CHECK-NEXT: addic r4, r3, -1 +; CHECK-NEXT: subfe r3, r4, r3 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ne i64 %a, %b + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i64 @set_flagi32i64(i32 %a, i32 %b, i64 %flags) { +; CHECK-LABEL: set_flagi32i64: +; CHECK: xor r3, r3, r4 +; CHECK-NEXT: cntlzw r3, r3 +; CHECK-NEXT: srwi r3, r3, 5 +; CHECK-NEXT: xori r3, r3, 1 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ne i32 %a, %b + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i64 @set_flagi64_z(i64 %a, i64 %flags) { +; CHECK-LABEL: set_flagi64_z: +; CHECK: addic r5, r3, -1 +; CHECK-NEXT: subfe r3, r5, r3 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp ne i64 %a, 0 + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i32 @set_flagi32_z(i32 %a, i32 %flags) { +; CHECK-LABEL: set_flagi32_z: +; CHECK: cntlzw r3, r3 +; CHECK-NEXT: srwi r3, r3, 5 +; CHECK-NEXT: xori r3, r3, 1 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp ne i32 %a, 0 + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i32 @set_flagi64i32_z(i64 %a, i32 %flags) { +; CHECK-LABEL: set_flagi64i32_z: +; CHECK: addic r5, r3, -1 +; CHECK-NEXT: subfe r3, r5, r3 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp ne i64 %a, 0 + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i64 @set_flagi32i64_z(i32 %a, i64 %flags) { +; CHECK-LABEL: set_flagi32i64_z: +; CHECK: cntlzw r3, r3 +; CHECK-NEXT: srwi r3, r3, 5 +; CHECK-NEXT: xori r3, r3, 1 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp ne i32 %a, 0 + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} Index: test/CodeGen/PowerPC/testSelectSetCCUGE.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/testSelectSetCCUGE.ll @@ -0,0 +1,131 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ +; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ +; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl + +define i64 @set_flagi64(i64 %a, i64 %b, i64 %flags) { +; CHECK-LABEL: set_flagi64: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r3, r4, r3 +; CHECK-NEXT: subfe r3, r4, r4 +; CHECK-NEXT: addi r3, r3, 1 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp uge i64 %a, %b + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i32 @set_flagi32(i32 %a, i32 %b, i32 %flags) { +; CHECK-LABEL: set_flagi32: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: clrldi r3, r3, 32 +; CHECK-NEXT: clrldi r4, r4, 32 +; CHECK-NEXT: sub r3, r3, r4 +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: xori r3, r3, 1 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp uge i32 %a, %b + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i32 @set_flagi64i32(i64 %a, i64 %b, i32 %flags) { +; CHECK-LABEL: set_flagi64i32: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r3, r4, r3 +; CHECK-NEXT: subfe r3, r4, r4 +; CHECK-NEXT: addi r3, r3, 1 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp uge i64 %a, %b + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i64 @set_flagi32i64(i32 %a, i32 %b, i64 %flags) { +; CHECK-LABEL: set_flagi32i64: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: clrldi r3, r3, 32 +; CHECK-NEXT: clrldi r4, r4, 32 +; CHECK-NEXT: li r6, 8 +; CHECK-NEXT: sub r3, r3, r4 +; CHECK-NEXT: rldicl r3, r3, 4, 60 +; CHECK-NEXT: andc r3, r6, r3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp uge i32 %a, %b + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i64 @set_flagi64_z(i64 %a, i64 %flags) { +; CHECK-LABEL: set_flagi64_z: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: ori r3, r4, 8 +; CHECK-NEXT: blr +entry: + %cmp = icmp uge i64 %a, 0 + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i32 @set_flagi32_z(i32 %a, i32 %flags) { +; CHECK-LABEL: set_flagi32_z: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: ori r3, r4, 8 +; CHECK-NEXT: blr +entry: + %cmp = icmp uge i32 %a, 0 + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i32 @set_flagi64i32_z(i64 %a, i32 %flags) { +; CHECK-LABEL: set_flagi64i32_z: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: ori r3, r4, 8 +; CHECK-NEXT: blr +entry: + %cmp = icmp uge i64 %a, 0 + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i64 @set_flagi32i64_z(i32 %a, i64 %flags) { +; CHECK-LABEL: set_flagi32i64_z: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: ori r3, r4, 8 +; CHECK-NEXT: blr +entry: + %cmp = icmp uge i32 %a, 0 + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} Index: test/CodeGen/PowerPC/testSelectSetCCUGT.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/testSelectSetCCUGT.ll @@ -0,0 +1,133 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ +; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ +; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl + +define i64 @set_flagi64(i64 %a, i64 %b, i64 %flags) { +; CHECK-LABEL: set_flagi64: +; CHECK: subfc r3, r3, r4 +; CHECK-NEXT: subfe r3, r4, r4 +; CHECK-NEXT: neg r3, r3 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ugt i64 %a, %b + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i32 @set_flagi32(i32 %a, i32 %b, i32 %flags) { +; CHECK-LABEL: set_flagi32: +; CHECK: sub r3, r4, r3 +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ugt i32 %a, %b + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i32 @set_flagi64i32(i64 %a, i64 %b, i32 %flags) { +; CHECK-LABEL: set_flagi64i32: +; CHECK: subfc r3, r3, r4 +; CHECK-NEXT: subfe r3, r4, r4 +; CHECK-NEXT: neg r3, r3 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ugt i64 %a, %b + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i64 @set_flagi32i64(i32 %a, i32 %b, i64 %flags) { +; CHECK-LABEL: set_flagi32i64: +; CHECK: clrldi r4, r4, 32 +; CHECK-NEXT: clrldi r3, r3, 32 +; CHECK-NEXT: sub r3, r4, r3 +; CHECK-NEXT: rotldi r3, r3, 1 +; CHECK-NEXT: rldic r3, r3, 3, 60 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ugt i32 %a, %b + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i64 @set_flagi64_z(i64 %a, i64 %flags) { +; CHECK-LABEL: set_flagi64_z: +; CHECK: addic r5, r3, -1 +; CHECK-NEXT: subfe r3, r5, r3 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp ugt i64 %a, 0 + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i32 @set_flagi32_z(i32 %a, i32 %flags) { +; CHECK-LABEL: set_flagi32_z: +; CHECK: cntlzw r3, r3 +; CHECK-NEXT: srwi r3, r3, 5 +; CHECK-NEXT: xori r3, r3, 1 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp ugt i32 %a, 0 + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i32 @set_flagi64i32_z(i64 %a, i32 %flags) { +; CHECK-LABEL: set_flagi64i32_z: +; CHECK: addic r5, r3, -1 +; CHECK-NEXT: subfe r3, r5, r3 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp ugt i64 %a, 0 + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i64 @set_flagi32i64_z(i32 %a, i64 %flags) { +; CHECK-LABEL: set_flagi32i64_z: +; CHECK: cntlzw r3, r3 +; CHECK-NEXT: srwi r3, r3, 5 +; CHECK-NEXT: xori r3, r3, 1 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r4 +; CHECK-NEXT: blr +entry: + %cmp = icmp ugt i32 %a, 0 + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} Index: test/CodeGen/PowerPC/testSelectSetCCULE.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/testSelectSetCCULE.ll @@ -0,0 +1,79 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ +; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ +; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl + +define i64 @set_flagi64(i64 %a, i64 %b, i64 %flags) { +; CHECK-LABEL: set_flagi64: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r4, r3, r4 +; CHECK-NEXT: subfe r3, r3, r3 +; CHECK-NEXT: addi r3, r3, 1 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ule i64 %a, %b + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i32 @set_flagi32(i32 %a, i32 %b, i32 %flags) { +; CHECK-LABEL: set_flagi32: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: clrldi r4, r4, 32 +; CHECK-NEXT: clrldi r3, r3, 32 +; CHECK-NEXT: sub r3, r4, r3 +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: xori r3, r3, 1 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ule i32 %a, %b + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i32 @set_flagi64i32(i64 %a, i64 %b, i32 %flags) { +; CHECK-LABEL: set_flagi64i32: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r4, r3, r4 +; CHECK-NEXT: subfe r3, r3, r3 +; CHECK-NEXT: addi r3, r3, 1 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ule i64 %a, %b + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i64 @set_flagi32i64(i32 %a, i32 %b, i64 %flags) { +; CHECK-LABEL: set_flagi32i64: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: clrldi r4, r4, 32 +; CHECK-NEXT: clrldi r3, r3, 32 +; CHECK-NEXT: li r6, 8 +; CHECK-NEXT: sub r3, r4, r3 +; CHECK-NEXT: rldicl r3, r3, 4, 60 +; CHECK-NEXT: andc r3, r6, r3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ule i32 %a, %b + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} Index: test/CodeGen/PowerPC/testSelectSetCCULT.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/testSelectSetCCULT.ll @@ -0,0 +1,77 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ +; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -O2 \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ +; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl + +define i64 @set_flagi64(i64 %a, i64 %b, i64 %flags) { +; CHECK-LABEL: set_flagi64: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r4, r4, r3 +; CHECK-NEXT: subfe r3, r3, r3 +; CHECK-NEXT: neg r3, r3 +; CHECK-NEXT: sldi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ult i64 %a, %b + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +} + +define i32 @set_flagi32(i32 %a, i32 %b, i32 %flags) { +; CHECK-LABEL: set_flagi32: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: clrldi r3, r3, 32 +; CHECK-NEXT: clrldi r4, r4, 32 +; CHECK-NEXT: sub r3, r3, r4 +; CHECK-NEXT: rldicl r3, r3, 1, 63 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ult i32 %a, %b + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i32 @set_flagi64i32(i64 %a, i64 %b, i32 %flags) { +; CHECK-LABEL: set_flagi64i32: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: subfc r4, r4, r3 +; CHECK-NEXT: subfe r3, r3, r3 +; CHECK-NEXT: neg r3, r3 +; CHECK-NEXT: slwi r3, r3, 3 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ult i64 %a, %b + %conv = zext i1 %cmp to i32 + %shl = shl nuw nsw i32 %conv, 3 + %or = or i32 %shl, %flags + ret i32 %or +} + +define i64 @set_flagi32i64(i32 %a, i32 %b, i64 %flags) { +; CHECK-LABEL: set_flagi32i64: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: clrldi r3, r3, 32 +; CHECK-NEXT: clrldi r4, r4, 32 +; CHECK-NEXT: sub r3, r3, r4 +; CHECK-NEXT: rotldi r3, r3, 1 +; CHECK-NEXT: rldic r3, r3, 3, 60 +; CHECK-NEXT: or r3, r3, r5 +; CHECK-NEXT: blr +entry: + %cmp = icmp ult i32 %a, %b + %conv = zext i1 %cmp to i64 + %shl = shl nuw nsw i64 %conv, 3 + %or = or i64 %shl, %flags + ret i64 %or +}