@@ -3405,6 +3405,9 @@ X86TargetLowering::getJumpConditionMergingParams(Instruction::BinaryOps Opc,
3405
3405
const Value *Rhs) const {
3406
3406
using namespace llvm::PatternMatch;
3407
3407
int BaseCost = BrMergingBaseCostThresh.getValue();
3408
+ // With CCMP, branches can be merged in a more efficient way.
3409
+ if (BaseCost >= 0 && Subtarget.hasCCMP())
3410
+ BaseCost += 6;
3408
3411
// a == b && a == c is a fast pattern on x86.
3409
3412
ICmpInst::Predicate Pred;
3410
3413
if (BaseCost >= 0 && Opc == Instruction::And &&
@@ -33931,6 +33934,8 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
33931
33934
NODE_NAME_CASE(TESTUI)
33932
33935
NODE_NAME_CASE(FP80_ADD)
33933
33936
NODE_NAME_CASE(STRICT_FP80_ADD)
33937
+ NODE_NAME_CASE(CCMP)
33938
+ NODE_NAME_CASE(CTEST)
33934
33939
}
33935
33940
return nullptr;
33936
33941
#undef NODE_NAME_CASE
@@ -54566,7 +54571,187 @@ static bool onlyZeroFlagUsed(SDValue Flags) {
54566
54571
return true;
54567
54572
}
54568
54573
54574
+ static SDValue combineX86SubCmpToCcmpCtestHelper(
54575
+ SDNode *N, SDValue Flag, SDValue SetCC0, SDValue SetCC1, SelectionDAG &DAG,
54576
+ TargetLowering::DAGCombinerInfo &DCI, unsigned NewOpc) {
54577
+ SDValue LHS = N->getOperand(0);
54578
+ SDValue Sub = SetCC1.getOperand(1);
54579
+
54580
+ SDNode *BrCond = *Flag->uses().begin();
54581
+ if (BrCond->getOpcode() != X86ISD::BRCOND)
54582
+ return SDValue();
54583
+ unsigned CondNo = 2;
54584
+ if (static_cast<X86::CondCode>(BrCond->getConstantOperandVal(CondNo)) !=
54585
+ X86::COND_NE)
54586
+ return SDValue();
54587
+
54588
+ X86::CondCode CC0 =
54589
+ static_cast<X86::CondCode>(SetCC0.getConstantOperandVal(0));
54590
+ // CCMP/CTEST is not conditional when the source condition is COND_P/COND_NP.
54591
+ if (CC0 == X86::COND_P || CC0 == X86::COND_NP)
54592
+ return SDValue();
54593
+
54594
+ bool IsOR = LHS.getOpcode() == ISD::OR;
54595
+
54596
+ SDValue SCC =
54597
+ IsOR ? DAG.getTargetConstant(X86::GetOppositeBranchCondition(CC0),
54598
+ SDLoc(SetCC0.getOperand(0)), MVT::i8)
54599
+ : SetCC0.getOperand(0);
54600
+
54601
+ SDValue CC1N = SetCC1.getOperand(0);
54602
+ X86::CondCode CC1 =
54603
+ static_cast<X86::CondCode>(CC1N->getAsAPIntVal().getSExtValue());
54604
+ X86::CondCode OppositeCC1 = X86::GetOppositeBranchCondition(CC1);
54605
+ X86::CondCode CFlagsCC = IsOR ? CC1 : OppositeCC1;
54606
+ SDValue CFlags = DAG.getTargetConstant(
54607
+ X86::getCondFlagsFromCondCode(CFlagsCC), SDLoc(BrCond), MVT::i8);
54608
+ SDValue CCMP = (NewOpc == X86ISD::CCMP)
54609
+ ? DAG.getNode(X86ISD::CCMP, SDLoc(N), Flag.getValueType(),
54610
+ {Sub.getOperand(0), Sub.getOperand(1),
54611
+ CFlags, SCC, SetCC0.getOperand(1)})
54612
+ : DAG.getNode(X86ISD::CTEST, SDLoc(N), Flag.getValueType(),
54613
+ {Sub.getOperand(0), Sub.getOperand(0),
54614
+ CFlags, SCC, SetCC0.getOperand(1)});
54615
+ DAG.ReplaceAllUsesOfValueWith(Flag, CCMP);
54616
+
54617
+ SmallVector<SDValue> Ops(BrCond->op_values());
54618
+ if (isNullConstant(N->getOperand(1)) && Ops[CondNo] != CC1N)
54619
+ Ops[CondNo] = CC1N;
54620
+ else if (isOneConstant(N->getOperand(1)))
54621
+ Ops[CondNo] = DAG.getTargetConstant(OppositeCC1, SDLoc(BrCond), MVT::i8);
54622
+
54623
+ SDValue NewBrCond =
54624
+ DAG.getNode(X86ISD::BRCOND, SDLoc(BrCond), BrCond->getValueType(0), Ops);
54625
+ if (BrCond != NewBrCond.getNode()) {
54626
+ DAG.ReplaceAllUsesWith(BrCond, &NewBrCond);
54627
+ DCI.recursivelyDeleteUnusedNodes(BrCond);
54628
+ }
54629
+ return CCMP;
54630
+ }
54631
+
54632
+ static SDValue combineX86SubCmpToCcmp(SDNode *N, SDValue Flag,
54633
+ SelectionDAG &DAG,
54634
+ TargetLowering::DAGCombinerInfo &DCI,
54635
+ const X86Subtarget &ST) {
54636
+ // cmp(and/or(setcc(cc0, flag0), setcc(cc1, sub (X, Y))), 0)
54637
+ // brcond ne
54638
+ //
54639
+ // ->
54640
+ //
54641
+ // ccmp(X, Y, cflags/~cflags, cc0/~cc0, flag0)
54642
+ // brcond cc1
54643
+ //
54644
+ //
54645
+ // sub(and/or(setcc(cc0, flag0), setcc(cc1, sub (X, Y))), 1)
54646
+ // brcond ne
54647
+ //
54648
+ // ->
54649
+ //
54650
+ // ccmp(X, Y, cflags/~cflags, cc0/~cc0, flag0)
54651
+ // brcond ~cc1
54652
+ //
54653
+ // if only flag has users, where cflags is determined by cc1.
54654
+
54655
+ SDValue LHS = N->getOperand(0);
54656
+
54657
+ if (!ST.hasCCMP() ||
54658
+ (LHS.getOpcode() != ISD::AND && LHS.getOpcode() != ISD::OR) ||
54659
+ !Flag.hasOneUse())
54660
+ return SDValue();
54661
+
54662
+ SDValue SetCC0 = LHS.getOperand(0);
54663
+ SDValue SetCC1 = LHS.getOperand(1);
54664
+ if (SetCC0.getOpcode() != X86ISD::SETCC ||
54665
+ SetCC1.getOpcode() != X86ISD::SETCC)
54666
+ return SDValue();
54667
+
54668
+ // and/or is commutable. Try to commute the operands and then test again.
54669
+ if (SetCC1.getOperand(1).getOpcode() != X86ISD::SUB) {
54670
+ std::swap(SetCC0, SetCC1);
54671
+ if (SetCC1.getOperand(1).getOpcode() != X86ISD::SUB)
54672
+ return SDValue();
54673
+ }
54674
+
54675
+ return combineX86SubCmpToCcmpCtestHelper(N, Flag, SetCC0, SetCC1, DAG, DCI,
54676
+ X86ISD::CCMP);
54677
+ }
54678
+
54679
+ static SDValue combineX86SubCmpToCtest(SDNode *N, SDValue Flag,
54680
+ SelectionDAG &DAG,
54681
+ TargetLowering::DAGCombinerInfo &DCI,
54682
+ const X86Subtarget &ST) {
54683
+ // cmp(and/or(setcc(cc0, flag0), setcc(cc1, cmp (X, 0))), 0)
54684
+ // brcond ne
54685
+ //
54686
+ // ->
54687
+ //
54688
+ // ctest(X, X, cflags/~cflags, cc0/~cc0, flag0)
54689
+ // brcond cc1
54690
+ //
54691
+ //
54692
+ // sub(and/or(setcc(cc0, flag0), setcc(cc1, cmp (X, 0))), 1)
54693
+ // brcond ne
54694
+ //
54695
+ // ->
54696
+ //
54697
+ // ctest(X, X, cflags/~cflags, cc0/~cc0, flag0)
54698
+ // brcond ~cc1
54699
+ //
54700
+ // if only flag has users, where cflags is determined by cc1.
54701
+
54702
+ SDValue LHS = N->getOperand(0);
54703
+
54704
+ if (!ST.hasCCMP() ||
54705
+ (LHS.getOpcode() != ISD::AND && LHS.getOpcode() != ISD::OR) ||
54706
+ !Flag.hasOneUse())
54707
+ return SDValue();
54708
+
54709
+ SDValue SetCC0 = LHS.getOperand(0);
54710
+ SDValue SetCC1 = LHS.getOperand(1);
54711
+ if (SetCC0.getOpcode() != X86ISD::SETCC ||
54712
+ SetCC1.getOpcode() != X86ISD::SETCC)
54713
+ return SDValue();
54714
+
54715
+ auto IsOp1CmpZero = [&](SDValue V) {
54716
+ SDValue Op = V.getOperand(1);
54717
+ return Op.getOpcode() == X86ISD::CMP && isNullConstant(Op.getOperand(1));
54718
+ };
54719
+ // and/or is commutable. Try to commute the operands and then test again.
54720
+ if (!IsOp1CmpZero(SetCC1)) {
54721
+ std::swap(SetCC0, SetCC1);
54722
+ if (!IsOp1CmpZero(SetCC1))
54723
+ return SDValue();
54724
+ }
54725
+
54726
+ return combineX86SubCmpToCcmpCtestHelper(N, Flag, SetCC0, SetCC1, DAG, DCI,
54727
+ X86ISD::CTEST);
54728
+ }
54729
+
54730
+ static bool isOnlyFlagUsedX86SubOne(SDNode *N) {
54731
+ return N->getOpcode() == X86ISD::SUB && isOneConstant(N->getOperand(1)) &&
54732
+ !N->hasAnyUseOfValue(0);
54733
+ }
54734
+
54735
+ static SDValue combineX86SubToCcmp(SDNode *N, SelectionDAG &DAG,
54736
+ TargetLowering::DAGCombinerInfo &DCI,
54737
+ const X86Subtarget &ST) {
54738
+ if (!isOnlyFlagUsedX86SubOne(N))
54739
+ return SDValue();
54740
+
54741
+ return combineX86SubCmpToCcmp(N, SDValue(N, 1), DAG, DCI, ST);
54742
+ }
54743
+
54744
+ static SDValue combineX86SubToCtest(SDNode *N, SelectionDAG &DAG,
54745
+ TargetLowering::DAGCombinerInfo &DCI,
54746
+ const X86Subtarget &ST) {
54747
+ if (!isOnlyFlagUsedX86SubOne(N))
54748
+ return SDValue();
54749
+
54750
+ return combineX86SubCmpToCtest(N, SDValue(N, 1), DAG, DCI, ST);
54751
+ }
54752
+
54569
54753
static SDValue combineCMP(SDNode *N, SelectionDAG &DAG,
54754
+ TargetLowering::DAGCombinerInfo &DCI,
54570
54755
const X86Subtarget &Subtarget) {
54571
54756
// Only handle test patterns.
54572
54757
if (!isNullConstant(N->getOperand(1)))
@@ -54581,6 +54766,14 @@ static SDValue combineCMP(SDNode *N, SelectionDAG &DAG,
54581
54766
EVT VT = Op.getValueType();
54582
54767
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
54583
54768
54769
+ if (SDValue CCMP =
54770
+ combineX86SubCmpToCcmp(N, SDValue(N, 0), DAG, DCI, Subtarget))
54771
+ return CCMP;
54772
+
54773
+ if (SDValue CTEST =
54774
+ combineX86SubCmpToCtest(N, SDValue(N, 0), DAG, DCI, Subtarget))
54775
+ return CTEST;
54776
+
54584
54777
// If we have a constant logical shift that's only used in a comparison
54585
54778
// against zero turn it into an equivalent AND. This allows turning it into
54586
54779
// a TEST instruction later.
@@ -54709,7 +54902,8 @@ static SDValue combineCMP(SDNode *N, SelectionDAG &DAG,
54709
54902
}
54710
54903
54711
54904
static SDValue combineX86AddSub(SDNode *N, SelectionDAG &DAG,
54712
- TargetLowering::DAGCombinerInfo &DCI) {
54905
+ TargetLowering::DAGCombinerInfo &DCI,
54906
+ const X86Subtarget &ST) {
54713
54907
assert((X86ISD::ADD == N->getOpcode() || X86ISD::SUB == N->getOpcode()) &&
54714
54908
"Expected X86ISD::ADD or X86ISD::SUB");
54715
54909
@@ -54720,6 +54914,12 @@ static SDValue combineX86AddSub(SDNode *N, SelectionDAG &DAG,
54720
54914
bool IsSub = X86ISD::SUB == N->getOpcode();
54721
54915
unsigned GenericOpc = IsSub ? ISD::SUB : ISD::ADD;
54722
54916
54917
+ if (SDValue CCMP = combineX86SubToCcmp(N, DAG, DCI, ST))
54918
+ return CCMP;
54919
+
54920
+ if (SDValue CTEST = combineX86SubToCtest(N, DAG, DCI, ST))
54921
+ return CTEST;
54922
+
54723
54923
// If we don't use the flag result, simplify back to a generic ADD/SUB.
54724
54924
if (!N->hasAnyUseOfValue(1)) {
54725
54925
SDValue Res = DAG.getNode(GenericOpc, DL, VT, LHS, RHS);
@@ -57018,11 +57218,11 @@ SDValue X86TargetLowering::PerformDAGCombine(SDNode *N,
57018
57218
case X86ISD::BLENDV: return combineSelect(N, DAG, DCI, Subtarget);
57019
57219
case ISD::BITCAST: return combineBitcast(N, DAG, DCI, Subtarget);
57020
57220
case X86ISD::CMOV: return combineCMov(N, DAG, DCI, Subtarget);
57021
- case X86ISD::CMP: return combineCMP(N, DAG, Subtarget);
57221
+ case X86ISD::CMP: return combineCMP(N, DAG, DCI, Subtarget);
57022
57222
case ISD::ADD: return combineAdd(N, DAG, DCI, Subtarget);
57023
57223
case ISD::SUB: return combineSub(N, DAG, DCI, Subtarget);
57024
57224
case X86ISD::ADD:
57025
- case X86ISD::SUB: return combineX86AddSub(N, DAG, DCI);
57225
+ case X86ISD::SUB: return combineX86AddSub(N, DAG, DCI, Subtarget );
57026
57226
case X86ISD::SBB: return combineSBB(N, DAG);
57027
57227
case X86ISD::ADC: return combineADC(N, DAG, DCI);
57028
57228
case ISD::MUL: return combineMul(N, DAG, DCI, Subtarget);
0 commit comments