================
@@ -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)*/) {
+        auto *CCValid1 = dyn_cast<ConstantSDNode>(XOROp1->getOperand(2));
+        auto *CCMask1 = dyn_cast<ConstantSDNode>(XOROp1->getOperand(3));
+        SDValue XORReg = XOROp1->getOperand(4);
+        if (!CCValid1 || !CCMask1)
+          return false;
+        int CCValidVal = CCValid1->getZExtValue();
+        int CCMaskVal = CCMask1->getZExtValue();
+        if (combineCCMask(XORReg, CCValidVal, CCMaskVal)) {
+          // CC == 0 || CC == 2 for bit 28 Test Under Mask.
+          CCMask = SystemZ::CCMASK_CMP_GE;
+          CCMask ^= CCMaskVal;
+          if (Invert)
+            CCMask ^= CCValid;
+          CCReg = XORReg;
+          return true;
+        }
+      }
+    }
+  }
+  // Optimize (AND (SRL (IPM (CC)))).
+  if (CCNode->getOpcode() == ISD::AND) {
+    auto *N = CCNode->getOperand(0).getNode();
+    if (!isSRL_IPM_CCSequence(N))
       return false;
-    auto *FalseVal = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(1));
-    if (!FalseVal)
+    auto *ANDConst = dyn_cast<ConstantSDNode>(CCNode->getOperand(1));
+    if (!ANDConst)
       return false;
-    if (CompareRHS->getAPIntValue() == FalseVal->getAPIntValue())
-      Invert = !Invert;
-    else if (CompareRHS->getAPIntValue() != TrueVal->getAPIntValue())
+    // Bit 28 false (CC == 0) || (CC == 2).
+    // Caller can invert it depending on CCmask there.
+    if (ANDConst->getZExtValue() == 1) {
+      CCMask = SystemZ::CCMASK_0 | SystemZ::CCMASK_2;
+      CCValid = SystemZ::CCMASK_ANY;
+      return true;
+    }
+    return false;
+  }
+  // (SELECT_CCMASK (ICMP (SRL (IPM (CC)))))
+  if (CCNode->getOpcode() == SystemZISD::SELECT_CCMASK) {
+    auto *CCValidNode = dyn_cast<ConstantSDNode>(CCNode->getOperand(2));
+    auto *CCMaskNode = dyn_cast<ConstantSDNode>(CCNode->getOperand(3));
+    if (!CCValidNode || !CCMaskNode)
       return false;
 
-    // Compute the effective CC mask for the new branch or select.
-    auto *NewCCValid = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(2));
-    auto *NewCCMask = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(3));
-    if (!NewCCValid || !NewCCMask)
+    int CCValidVal = CCValidNode->getZExtValue();
+    int CCMaskVal = CCMaskNode->getZExtValue();
+    SDValue CCRegOp = CCNode->getOperand(4);
+    if (combineCCMask(CCRegOp, CCValidVal, CCMaskVal)) {
+      CCMask = CCMaskVal;
+      CCValid = SystemZ::CCMASK_ANY;
+      CCReg = CCRegOp;
+      return true;
+    }
+    return false;
+  }
+
+  // Both oerands of XOR are (SELECT_CCMASK (ICMP (SRL (IPM (CC))))).
+  if (CCNode->getOpcode() == ISD::XOR) {
----------------
uweigand wrote:

And once again an ISD::XOR cannot be an input to combineCCMask.

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

Reply via email to