[clang] [llvm] Add support for flag output operand "=@cc" for SystemZ. (PR #125970)
Ulrich Weigand via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 11 01:46:37 PDT 2025
================
@@ -8702,61 +8738,264 @@ SDValue SystemZTargetLowering::combineSETCC(
return SDValue();
}
+static SmallSet<int, 4> convertCCMaskToCCValsSet(int Mask) {
+ SmallSet<int, 4> CCVals;
+ size_t Pos = 0;
+ while (Mask) {
+ if (Mask & 0x1)
+ CCVals.insert(3 - Pos);
+ Mask >>= 1;
+ ++Pos;
+ }
+ return CCVals;
+}
+
+static std::pair<SDValue, int> findCCUse(const SDValue &Val) {
+ auto *N = Val.getNode();
+ if (!N)
+ return {Val, SystemZ::CCMASK_NONE};
+ if (isa<ConstantSDNode>(Val))
+ return std::make_pair(SDValue(), SystemZ::CCMASK_NONE);
+ else if (N->getOpcode() == ISD::CopyFromReg && N->getNumOperands() > 1) {
+ if (auto *RN = cast<RegisterSDNode>(N->getOperand(1))) {
+ if (RN->getReg() == SystemZ::CC)
+ return {Val, SystemZ::CCMASK_ANY};
+ }
+ } else if (N->getOpcode() == SystemZISD::IPM)
+ return std::make_pair(N->getOperand(0), SystemZ::CCMASK_ANY);
+ else if (N->getOpcode() == ISD::SRL)
+ return findCCUse(N->getOperand(0));
+ else if (N->getOpcode() == SystemZISD::ICMP)
+ return findCCUse(N->getOperand(0));
+ else if (N->getOpcode() == SystemZISD::TM)
+ return findCCUse(N->getOperand(0));
+ else if (N->getOpcode() == SystemZISD::SELECT_CCMASK) {
+ SDValue SelectCCReg = N->getOperand(4);
+ auto [OpCC, OpCCValid] = findCCUse(SelectCCReg);
+ auto *OpCCNode = OpCC.getNode();
+ if (OpCCNode && OpCCNode != SelectCCReg.getNode())
+ return std::make_pair(OpCC, OpCCValid);
+ auto *CCValid = dyn_cast<ConstantSDNode>(N->getOperand(2));
+ if (CCValid)
+ return std::make_pair(SelectCCReg, CCValid->getZExtValue());
+ } else if (N->getOpcode() == ISD::ADD || N->getOpcode() == ISD::AND ||
+ N->getOpcode() == ISD::OR || N->getOpcode() == ISD::XOR ||
+ N->getOpcode() == ISD::AND) {
+ auto [Op0CC, Op0CCValid] = findCCUse(N->getOperand(0));
+ if (isa<ConstantSDNode>(N->getOperand(1)))
+ return std::make_pair(Op0CC, Op0CCValid);
+ auto [Op1CC, Op1CCValid] = findCCUse(N->getOperand(1));
+ auto *N0 = Op0CC.getNode(), *N1 = Op1CC.getNode();
+ if (N0 && N1 && N0 == N1 && Op0CCValid == Op1CCValid)
+ return std::make_pair(Op0CC, Op0CCValid);
+ }
+ return {SDValue(), SystemZ::CCMASK_ANY};
+}
+
+static bool combineCCMask(SDValue &CCReg, int &CCValid, int &CCMask);
+
+static SmallVector<int, 4> simplifyAssumingCCVal(SDValue &Val, SDValue &CC) {
+ const auto isValidBinaryOperation = [](const SDValue &Op, SDValue &Op0,
+ SDValue &Op1, unsigned &Opcode) {
+ auto *N = Op.getNode();
+ if (!N)
+ return false;
+ Opcode = N->getOpcode();
+ if (Opcode != ISD::ADD && Opcode != ISD::AND && Opcode != ISD::OR &&
+ Opcode != ISD::XOR)
+ return false;
+ Op0 = N->getOperand(0);
+ Op1 = N->getOperand(1);
+ return true;
+ };
+ auto *C = dyn_cast<ConstantSDNode>(Val);
+ if (C) {
+ int ConstVal = C->getZExtValue();
+ return {ConstVal, ConstVal, ConstVal, ConstVal};
+ }
+ auto *N = Val.getNode(), *CCNode = CC.getNode();
+ if (!N || !CCNode)
+ return {};
+ if (N == CCNode)
+ return {0, 1, 2, 3};
+ if (N->getOpcode() == SystemZISD::IPM) {
+ SDValue IPMOp0 = N->getOperand(0);
+ auto &&CCVals = simplifyAssumingCCVal(IPMOp0, CC);
+ if (CCVals.empty())
+ return CCVals;
+ auto ShiftAmount = SystemZ::IPM_CC;
+ std::for_each(CCVals.begin(), CCVals.end(),
+ [&ShiftAmount](auto &V) { V <<= ShiftAmount; });
+ return CCVals;
+ }
+ if (N->getOpcode() == ISD::SRL) {
+ SDValue Op0 = N->getOperand(0);
+ auto *SRLCount = dyn_cast<ConstantSDNode>(N->getOperand(1));
+ if (!SRLCount)
+ return {};
+ auto SRLCountVal = SRLCount->getZExtValue();
+ auto &&CCVals = simplifyAssumingCCVal(Op0, CC);
+ if (CCVals.empty())
+ return CCVals;
+ std::for_each(CCVals.begin(), CCVals.end(),
+ [SRLCountVal](auto &V) { V >>= SRLCountVal; });
+ return CCVals;
----------------
uweigand wrote:
If we use SDValue instead of int, we can simply call DAG.getNode and let the common constant folding code handle the simplification for us.
https://github.com/llvm/llvm-project/pull/125970
More information about the cfe-commits
mailing list