[clang] [llvm] Add support for flag output operand "=@cc" for SystemZ. (PR #125970)
Ulrich Weigand via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 25 07:30:34 PDT 2025
================
@@ -8694,66 +8726,455 @@ SDValue SystemZTargetLowering::combineSETCC(
return SDValue();
}
+// Combine IPM sequence for flag output operands.
static bool combineCCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
- // We have a SELECT_CCMASK or BR_CCMASK comparing the condition code
- // set by the CCReg instruction using the CCValid / CCMask masks,
- // If the CCReg instruction is itself a ICMP testing the condition
- // code set by some other instruction, see whether we can directly
- // use that condition code.
-
- // Verify that we have an ICMP against some constant.
- if (CCValid != SystemZ::CCMASK_ICMP)
- return false;
- auto *ICmp = CCReg.getNode();
- if (ICmp->getOpcode() != SystemZISD::ICMP)
+ // CCMask for ICmp is equal to 0, 1, 2 or 3.
+ const auto CCMaskForICmpEQCCVal = [](unsigned CC) {
+ assert(CC < 4 && "CC out of range");
+ return 1 << (3 - CC);
+ };
+ // Convert CCVal to CCMask and update it.
+ const auto convertCCValToCCMask = [&](int CCVal) {
+ bool Invert = false;
+ if (CCMask == SystemZ::CCMASK_CMP_NE)
+ Invert = !Invert;
+ if (CCMask == SystemZ::CCMASK_CMP_EQ || CCMask == SystemZ::CCMASK_CMP_NE) {
+ CCMask = CCMaskForICmpEQCCVal(CCVal);
+ if (Invert)
+ CCMask ^= SystemZ::CCMASK_ANY;
+ return true;
+ } else if (CCMask == SystemZ::CCMASK_CMP_LT) {
+ // CC in range [0, CCVal).
+ CCMask = ((~0U << (4 - CCVal)) & SystemZ::CCMASK_ANY);
+ return true;
+ } else if (CCMask == SystemZ::CCMASK_CMP_GT) {
+ // CC in range (CCVal, 3].
+ CCMask = (~(~0U << (3 - CCVal))) & SystemZ::CCMASK_ANY;
+ return true;
+ }
return false;
- auto *CompareLHS = ICmp->getOperand(0).getNode();
- auto *CompareRHS = dyn_cast<ConstantSDNode>(ICmp->getOperand(1));
- if (!CompareRHS)
+ };
+ // Check (SRL (IPM (CC))) and update CCReg to combine.
+ const auto isSRL_IPM_CCSequence = [&CCReg](SDNode *N) {
+ if (!N || N->getOpcode() != ISD::SRL)
+ return false;
+ auto *SRLCount = dyn_cast<ConstantSDNode>(N->getOperand(1));
+ if (!SRLCount || SRLCount->getZExtValue() != SystemZ::IPM_CC)
+ return false;
+ auto *IPM = N->getOperand(0).getNode();
+ if (!IPM || IPM->getOpcode() != SystemZISD::IPM)
+ return false;
+ CCReg = IPM->getOperand(0);
+ return true;
+ };
+ // Check if select_cc has already been combined and uses the same ipm/cc
+ // as CCOp and return evaluated mask CCMaskVal. (SELECT_CCMASK (CC)).
+ const auto isSameCCIPMOp = [](SDValue &CCOp, SDNode *N, int &CCValidVal,
+ int &CCMaskVal) {
+ if (!N || N->getOpcode() != SystemZISD::SELECT_CCMASK)
+ return false;
+ auto *CCValidNode = dyn_cast<ConstantSDNode>(N->getOperand(2));
+ auto *CCMaskNode = dyn_cast<ConstantSDNode>(N->getOperand(3));
+ if (!CCValidNode || !CCMaskNode)
+ return false;
+
+ CCValidVal = CCValidNode->getZExtValue();
+ // Already been combined.
+ if (CCValidVal != SystemZ::CCMASK_ANY)
+ return false;
+ CCMaskVal = CCMaskNode->getZExtValue();
+ SDValue CCRegOp = N->getOperand(4);
+ auto *CCOpNode = CCOp.getNode(), *CCRegOpNode = CCRegOp.getNode();
+ // Uses the same ipm/cc.
+ return CCOpNode && CCRegOpNode && CCOpNode == CCRegOpNode;
+ };
+ auto *CCNode = CCReg.getNode();
+ if (!CCNode)
return false;
- // Optimize the case where CompareLHS is a SELECT_CCMASK.
- if (CompareLHS->getOpcode() == SystemZISD::SELECT_CCMASK) {
- // Verify that we have an appropriate mask for a EQ or NE comparison.
+ // Optimize (TM (IPM (CC)))
----------------
uweigand wrote:
Adding a case to optimize (TM (IPM)) in addition to (ICMP (IPM)) does make sense in general. However, you need to take care that the optimization is correct for *all possible* inputs to TM, not just the ones the come up in the "good case" you're looking at. That doesn't appear to be the case here.
https://github.com/llvm/llvm-project/pull/125970
More information about the cfe-commits
mailing list