[llvm] [X86][CodeGen] Support lowering for CCMP/CTEST (PR #91747)
Shengchen Kan via llvm-commits
llvm-commits at lists.llvm.org
Tue May 14 23:12:32 PDT 2024
================
@@ -54508,7 +54513,97 @@ static bool onlyZeroFlagUsed(SDValue Flags) {
return true;
}
+static SDValue
+combineX86SubCmpToCcmpHelper(SDNode *N, SDValue Flag, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const X86Subtarget &ST) {
+ // sub(and(setcc(cc0, flag0), setcc(cc1, sub (X, Y))), 1)
+ // brcond ne
+ //
+ // OR
+ //
+ // sub(and(setcc(cc0, flag0), setcc(cc1, sub (X, Y))), 1)
+ // brcond ne
+ //
+ // ->
+ //
+ // ccmp(X, Y, cflags, cc0, flag0)
+ // brcond cc1
+ //
+ // if only flag has users, where cflags is determined by cc1.
+
+ SDValue LHS = N->getOperand(0);
+
+ if (!ST.hasCCMP() || LHS.getOpcode() != ISD::AND || !Flag.hasOneUse())
+ return SDValue();
+
+ SDValue SetCC0 = LHS.getOperand(0);
+ SDValue SetCC1 = LHS.getOperand(1);
+ if (SetCC0.getOpcode() != X86ISD::SETCC ||
+ SetCC1.getOpcode() != X86ISD::SETCC)
+ return SDValue();
+
+ // and is commutable. Try to commute the operands and then test again.
+ if (SetCC1.getOperand(1).getOpcode() != X86ISD::SUB) {
+ std::swap(SetCC0, SetCC1);
+ if (SetCC1.getOperand(1).getOpcode() != X86ISD::SUB)
+ return SDValue();
+ }
+ SDValue Sub = SetCC1.getOperand(1);
+
+ SDNode *BrCond = *Flag->uses().begin();
+ if (BrCond->getOpcode() != X86ISD::BRCOND)
+ return SDValue();
+
+ X86::CondCode CC0 =
+ static_cast<X86::CondCode>(SetCC0.getConstantOperandVal(0));
+ if (CC0 == X86::COND_P || CC0 == X86::COND_NP)
+ return SDValue();
+
+ SDValue CFlags = DAG.getTargetConstant(
+ X86::getCondFlagsFromCondCode(X86::GetOppositeBranchCondition(
+ static_cast<X86::CondCode>(SetCC1.getConstantOperandVal(0)))),
+ SDLoc(BrCond), MVT::i8);
+ SDValue CCMP = DAG.getNode(X86ISD::CCMP, SDLoc(N), Flag.getValueType(),
+ {Sub.getOperand(0), Sub.getOperand(1), CFlags,
+ SetCC0.getOperand(0), SetCC0.getOperand(1)});
+ DAG.ReplaceAllUsesOfValueWith(Flag, CCMP);
+
+ SmallVector<SDValue> Ops(BrCond->op_values());
+ unsigned CondNo = 2;
+ X86::CondCode OldCC =
+ static_cast<X86::CondCode>(BrCond->getConstantOperandVal(CondNo));
+ assert(OldCC == X86::COND_NE && "Unexpected CC");
+ if (Ops[CondNo] != SetCC1.getOperand(0)) {
+ Ops[CondNo] = SetCC1.getOperand(0);
+ SDValue NewBrCond = DAG.getNode(X86ISD::BRCOND, SDLoc(BrCond),
+ BrCond->getValueType(0), Ops);
+ DAG.ReplaceAllUsesWith(BrCond, &NewBrCond);
+ DCI.recursivelyDeleteUnusedNodes(BrCond);
+ }
+ return CCMP;
+}
+
+static SDValue combineX86CmpToCcmp(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const X86Subtarget &ST) {
+
+ return combineX86SubCmpToCcmpHelper(N, SDValue(N, 0), DAG, DCI, ST);
+}
+
+static SDValue combineX86SubToCcmp(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const X86Subtarget &ST) {
+
+ if (N->getOpcode() != X86ISD::SUB || !isOneConstant(N->getOperand(1)) ||
+ N->hasAnyUseOfValue(0))
+ return SDValue();
+
+ return combineX86SubCmpToCcmpHelper(N, SDValue(N, 1), DAG, DCI, ST);
----------------
KanRobert wrote:
That's why I still mark it a draft. IIRC, the code was covered by the test ccmp.ll before rebasing...
I am traiging.
https://github.com/llvm/llvm-project/pull/91747
More information about the llvm-commits
mailing list