diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -354,6 +354,7 @@ private: bool trySETCC(SDNode *N); + bool tryFoldSqrtTestBr(SDNode *N); bool tryAsSingleRLDICL(SDNode *N); bool tryAsSingleRLDICR(SDNode *N); bool tryAsSingleRLWINM(SDNode *N); @@ -4380,6 +4381,62 @@ return true; } +static bool isTestSqrtOpcode(SDValue N) { + if (N.getOpcode() == PPCISD::FTSQRT) + return true; + if (!isa(N.getOperand(0))) + return false; + switch (N.getConstantOperandVal(0)) { + case Intrinsic::ppc_vsx_xvtdivdp: + case Intrinsic::ppc_vsx_xvtdivsp: + case Intrinsic::ppc_vsx_xvtsqrtdp: + case Intrinsic::ppc_vsx_xvtsqrtsp: + return true; + } + return false; +} + +bool PPCDAGToDAGISel::tryFoldSqrtTestBr(SDNode *N) { + // We are looking for following patterns. + // (br_cc seteq, (and TestOp, 2), 0) -> (BCC PRED_NE, TestOp) + // (br_cc seteq, (and TestOp, 4), 0) -> (BCC PRED_LE, TestOp) + // (br_cc seteq, (and TestOp, 8), 0) -> (BCC PRED_GE, TestOp) + // (br_cc setne, (and TestOp, 2), 0) -> (BCC PRED_EQ, TestOp) + // (br_cc setne, (and TestOp, 4), 0) -> (BCC PRED_GT, TestOp) + // (br_cc setne, (and TestOp, 8), 0) -> (BCC PRED_LT, TestOp) + SDValue CmpLHS = N->getOperand(2); + ISD::CondCode CC = cast(N->getOperand(1))->get(); + if (!isa(N->getOperand(3)) || + N->getConstantOperandVal(3) != 0 || + (CC != ISD::SETEQ && CC != ISD::SETNE) || + CmpLHS.getOpcode() != ISD::AND || + !isa(CmpLHS.getOperand(1)) || + !isTestSqrtOpcode(CmpLHS.getOperand(0))) + return false; + + unsigned PCC; + bool IsCCNE = CC == ISD::SETNE; + switch (CmpLHS.getConstantOperandVal(1)) { + case 2: + PCC = IsCCNE ? PPC::PRED_EQ : PPC::PRED_NE; + break; + case 4: + PCC = IsCCNE ? PPC::PRED_GT : PPC::PRED_LE; + break; + case 8: + PCC = IsCCNE ? PPC::PRED_LT : PPC::PRED_GE; + break; + default: + return false; + } + + SDLoc dl(N); + SDValue Ops[] = {getI32Imm(PCC, dl), CmpLHS.getOperand(0), N->getOperand(4), + N->getOperand(0)}; + CurDAG->SelectNodeTo(N, PPC::BCC, MVT::Other, Ops); + return true; +} + bool PPCDAGToDAGISel::tryAsSingleRLWINM(SDNode *N) { assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected"); unsigned Imm; @@ -5249,6 +5306,8 @@ return; } case ISD::BR_CC: { + if (tryFoldSqrtTestBr(N)) + return; ISD::CondCode CC = cast(N->getOperand(1))->get(); unsigned PCC = getPredicateForSetCC(CC, N->getOperand(2).getValueType(), Subtarget); diff --git a/llvm/test/CodeGen/PowerPC/branch_test.ll b/llvm/test/CodeGen/PowerPC/branch_test.ll --- a/llvm/test/CodeGen/PowerPC/branch_test.ll +++ b/llvm/test/CodeGen/PowerPC/branch_test.ll @@ -9,10 +9,7 @@ ; CHECK-LABEL: xvtsqrtdp_and_2_eq: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xvtsqrtdp cr0, v2 -; CHECK-NEXT: mfocrf r3, 128 -; CHECK-NEXT: srwi r3, r3, 28 -; CHECK-NEXT: andi. r3, r3, 2 -; CHECK-NEXT: beq cr0, .LBB0_2 +; CHECK-NEXT: bne cr0, .LBB0_2 ; CHECK-NEXT: # %bb.1: # %if.then ; CHECK-NEXT: addis r3, r2, .LC0@toc@ha ; CHECK-NEXT: li r4, 100 @@ -39,10 +36,7 @@ ; CHECK-LABEL: xvtsqrtdp_and_4_eq: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xvtsqrtdp cr0, v2 -; CHECK-NEXT: mfocrf r3, 128 -; CHECK-NEXT: srwi r3, r3, 28 -; CHECK-NEXT: andi. r3, r3, 4 -; CHECK-NEXT: beq cr0, .LBB1_2 +; CHECK-NEXT: ble cr0, .LBB1_2 ; CHECK-NEXT: # %bb.1: # %if.then ; CHECK-NEXT: addis r3, r2, .LC0@toc@ha ; CHECK-NEXT: li r4, 100 @@ -69,10 +63,7 @@ ; CHECK-LABEL: xvtsqrtdp_and_8_eq: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xvtsqrtdp cr0, v2 -; CHECK-NEXT: mfocrf r3, 128 -; CHECK-NEXT: srwi r3, r3, 28 -; CHECK-NEXT: andi. r3, r3, 8 -; CHECK-NEXT: beq cr0, .LBB2_2 +; CHECK-NEXT: bge cr0, .LBB2_2 ; CHECK-NEXT: # %bb.1: # %if.then ; CHECK-NEXT: addis r3, r2, .LC0@toc@ha ; CHECK-NEXT: li r4, 100 @@ -99,10 +90,7 @@ ; CHECK-LABEL: xvtsqrtdp_and_2_ne: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xvtsqrtdp cr0, v2 -; CHECK-NEXT: mfocrf r3, 128 -; CHECK-NEXT: srwi r3, r3, 28 -; CHECK-NEXT: andi. r3, r3, 2 -; CHECK-NEXT: bne cr0, .LBB3_2 +; CHECK-NEXT: beq cr0, .LBB3_2 ; CHECK-NEXT: # %bb.1: # %if.then ; CHECK-NEXT: addis r3, r2, .LC0@toc@ha ; CHECK-NEXT: li r4, 100 @@ -129,10 +117,7 @@ ; CHECK-LABEL: xvtsqrtdp_and_4_ne: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xvtsqrtdp cr0, v2 -; CHECK-NEXT: mfocrf r3, 128 -; CHECK-NEXT: srwi r3, r3, 28 -; CHECK-NEXT: andi. r3, r3, 4 -; CHECK-NEXT: bne cr0, .LBB4_2 +; CHECK-NEXT: bgt cr0, .LBB4_2 ; CHECK-NEXT: # %bb.1: # %if.then ; CHECK-NEXT: addis r3, r2, .LC0@toc@ha ; CHECK-NEXT: li r4, 100 @@ -159,10 +144,7 @@ ; CHECK-LABEL: xvtsqrtdp_and_8_ne: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xvtsqrtdp cr0, v2 -; CHECK-NEXT: mfocrf r3, 128 -; CHECK-NEXT: srwi r3, r3, 28 -; CHECK-NEXT: andi. r3, r3, 8 -; CHECK-NEXT: bne cr0, .LBB5_2 +; CHECK-NEXT: blt cr0, .LBB5_2 ; CHECK-NEXT: # %bb.1: # %if.then ; CHECK-NEXT: addis r3, r2, .LC0@toc@ha ; CHECK-NEXT: li r4, 100