================ @@ -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))) + if (CCNode->getOpcode() == SystemZISD::TM) { bool Invert = false; - if (CCMask == SystemZ::CCMASK_CMP_NE) + if (CCMask == SystemZ::CCMASK_TM_SOME_1) Invert = !Invert; ---------------- uweigand wrote:
There's four possible CCMask values for TM. It doesn't look all four are handled correctly. (You can of course bail out if there's some mask value you don't support, but you shouldn't make any silent assumptions.) https://github.com/llvm/llvm-project/pull/125970 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits