[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