[clang] [llvm] Add support for flag output operand "=@cc" for SystemZ. (PR #125970)
Ulrich Weigand via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 14 07:45:25 PDT 2025
================
@@ -8703,51 +8738,256 @@ SDValue SystemZTargetLowering::combineSETCC(
}
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
+ // 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 based on 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;
+ };
+ // 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;
+ };
+ const auto isOneBitSet = [](int Mask) {
+ return Mask && !(Mask & (Mask - 1));
+ };
+
+ // Only one-bit set.
+ const auto log2CCMaskToCCVal = [](int Mask) {
+ size_t Pos = 0;
+ while (!(Mask & 1)) {
+ Mask >>= 1;
+ ++Pos;
+ };
+ assert(Pos < 4 && "CC out of range");
+ return (3 - Pos);
+ };
+
+ auto *CCNode = CCReg.getNode();
+ if (!CCNode)
+ return false;
+
+ // Optimize (TM (IPM (CC)))
+ if (CCNode->getOpcode() == SystemZISD::TM) {
+ bool Invert = false;
+ if (CCValid != SystemZ::CCMASK_TM)
+ return false;
+ if (CCMask == SystemZ::CCMASK_TM_SOME_1)
+ Invert = !Invert;
+ else if (CCMask != SystemZ::CCMASK_TM_ALL_0)
+ return false;
+ auto *N = CCNode->getOperand(0).getNode();
+ auto *TMOp1Const = dyn_cast<ConstantSDNode>(CCNode->getOperand(1));
+ if (!N || !TMOp1Const)
+ return false;
+ auto TMConstVal = TMOp1Const->getZExtValue();
+ if (N->getOpcode() == SystemZISD::IPM) {
+ if (TMConstVal == (1 << SystemZ::IPM_CC))
+ CCMask = SystemZ::CCMASK_CMP_GE;
+ else if (TMConstVal == (1 << (SystemZ::IPM_CC + 1)))
+ CCMask = SystemZ::CCMASK_CMP_LE;
+ else
+ return false;
+ if (Invert)
+ CCMask ^= CCValid;
+ // Return the updated CCReg link.
+ CCReg = N->getOperand(0);
+ return true;
+ }
+ }
+
+ // Rest of the code has sequence starting with opcode SystemZISD::ICMP.
+ // or SystemZISD::TM. 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)
+ if (CCValid != SystemZ::CCMASK_ICMP && CCValid != SystemZ::CCMASK_TM)
return false;
- auto *ICmp = CCReg.getNode();
- if (ICmp->getOpcode() != SystemZISD::ICMP)
+ if (CCNode->getOpcode() != SystemZISD::ICMP &&
+ CCNode->getOpcode() != SystemZISD::TM)
return false;
- auto *CompareLHS = ICmp->getOperand(0).getNode();
- auto *CompareRHS = dyn_cast<ConstantSDNode>(ICmp->getOperand(1));
+ auto *CompareLHS = CCNode->getOperand(0).getNode();
+ auto *CompareRHS = dyn_cast<ConstantSDNode>(CCNode->getOperand(1));
if (!CompareRHS)
return false;
+ // Optimize (ICMP (SRL (IPM))).
+ int CmpVal = CompareRHS->getZExtValue();
+ if (isSRL_IPM_CCSequence(CompareLHS)) {
----------------
uweigand wrote:
This needs to check for ICMP now, I guess? The code does not look correct for TM as-is.
https://github.com/llvm/llvm-project/pull/125970
More information about the llvm-commits
mailing list