================ @@ -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; - else if (CCMask != SystemZ::CCMASK_CMP_EQ) + auto *N = CCNode->getOperand(0).getNode(); + auto Shift = dyn_cast<ConstantSDNode>(CCNode->getOperand(1)); + if (!N || !Shift) return false; - - // Verify that the ICMP compares against one of select values. - auto *TrueVal = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(0)); - if (!TrueVal) + if (N->getOpcode() == SystemZISD::IPM) { + auto ShiftVal = Shift->getZExtValue(); + if (ShiftVal == (1 << SystemZ::IPM_CC)) + CCMask = SystemZ::CCMASK_CMP_GE; + if (Invert) + CCMask ^= CCValid; + // Return the updated CCReg link. + CCReg = N->getOperand(0); + return true; + } else if (N->getOpcode() == ISD::XOR) { + // Optimize (TM (XOR (OP1 OP2))). + auto *XOROp1 = N->getOperand(0).getNode(); + auto *XOROp2 = N->getOperand(1).getNode(); + if (!XOROp1 || !XOROp2) + return false; + // OP1. (SELECT_CCMASK (ICMP (SRL (IPM (CC))))). + // OP2. (SRL (IPM (CC))). + if (XOROp1->getOpcode() == SystemZISD::SELECT_CCMASK /*&& + isSRL_IPM_CCSequence(XOROp2)*/) { ---------------- uweigand wrote:
I don't even fully understand what optimization you're attempting here - but this code completely ignores Op2, which is obviously incorrect. 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