[llvm] [SystemZ] Improve CCMask optimization (PR #171137)

via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 8 06:39:26 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-systemz

Author: Dominik Steenken (dominik-steenken)

<details>
<summary>Changes</summary>

This commit addresses a shortcoming in the implementation of `combineBR_CCMASK` and `combineSELECT_CCMASK`. In cases where `combineCCMask` was able to reduce the ccmask going into the select or branch to either true (`ccvalid`) or false (`0`), a trivial instruction would be emitted (i.e. either a select that would only ever select one side, or a conditional branch with `true` or `false` as the branch condition).
This led under certain circumstances to, e.g., `BRC` instructions being emitted that triggered an assert in the AsmPrinter meant to exclude such branch conditions.
For the select case, this commit introduces an early bailout that simply returns the value that would "always" be selected. For the branch case, the commit introduces an additional guard that prevents the DAGCombine from taking effect, thereby preventing the illegal instruction from being emitted.

---
Full diff: https://github.com/llvm/llvm-project/pull/171137.diff


2 Files Affected:

- (modified) llvm/lib/Target/SystemZ/SystemZISelLowering.cpp (+15-3) 
- (added) llvm/test/CodeGen/SystemZ/condfolding.ll (+28) 


``````````diff
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 2511d08a6d0ef..428069a3c9d0f 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -8887,7 +8887,12 @@ SDValue SystemZTargetLowering::combineBR_CCMASK(SDNode *N,
   int CCMaskVal = CCMask->getZExtValue();
   SDValue Chain = N->getOperand(0);
   SDValue CCReg = N->getOperand(4);
-  if (combineCCMask(CCReg, CCValidVal, CCMaskVal, DAG))
+  // If combineCMask was able to merge or simplify ccvalid or ccmask, re-emit
+  // the modified BR_CCMASK with the new values.
+  // In order to avoid conditional branches with full or empty cc masks, do not
+  // do this if ccmask is 0 or equal to ccvalid.
+  if (combineCCMask(CCReg, CCValidVal, CCMaskVal, DAG) && CCMaskVal != 0 &&
+      CCMaskVal != CCValidVal)
     return DAG.getNode(SystemZISD::BR_CCMASK, SDLoc(N), N->getValueType(0),
                        Chain,
                        DAG.getTargetConstant(CCValidVal, SDLoc(N), MVT::i32),
@@ -8932,10 +8937,17 @@ SDValue SystemZTargetLowering::combineSELECT_CCMASK(
     }
     return SmallVector<SDValue, 4>{Val, Val, Val, Val};
   };
-  // Attempting to optimize TrueVal/FalseVal in outermost select_ccmask either
-  // with CCReg found by combineCCMask or original CCReg.
+
+  // Attempting to optimize TrueVal/FalseVal in outermost select_ccmask.
   SDValue TrueVal = N->getOperand(0);
   SDValue FalseVal = N->getOperand(1);
+  // First, if the condition is trivially false or trivially true after
+  // combineCCMask, just collapse this SELECT_CCMASK to the indicated value.
+  if (CCMaskVal == 0)
+    return FalseVal;
+  if (CCMaskVal == CCValidVal)
+    return TrueVal;
+  // Now, optimize with either CCReg found by combineCCMask or original CCReg.
   auto &&TrueSDVals = simplifyAssumingCCVal(TrueVal, CCReg, DAG);
   auto &&FalseSDVals = simplifyAssumingCCVal(FalseVal, CCReg, DAG);
   // TrueSDVals/FalseSDVals might be empty in case of non-constant
diff --git a/llvm/test/CodeGen/SystemZ/condfolding.ll b/llvm/test/CodeGen/SystemZ/condfolding.ll
new file mode 100644
index 0000000000000..07d8a242fc1f5
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/condfolding.ll
@@ -0,0 +1,28 @@
+; Test that a conditional branch with a discoverably trivial condition
+; does not result in an invalid conditional branch instruction.
+;
+; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -mcpu=z13 \
+; RUN:   --stop-after=systemz-isel | FileCheck %s
+
+ at g_1 = dso_local local_unnamed_addr global i64 0, align 8
+ at g_2 = dso_local local_unnamed_addr global i32 0, align 4
+
+define dso_local void @f1() local_unnamed_addr #1 {
+entry:
+;CHECK-LABEL: f1
+;CHECK-NOT: BRC 14, 0, %bb.2
+  %0 = load i64, ptr @g_1, align 8
+  %tobool.not = icmp eq i64 %0, 0
+  %sub.i = select i1 %tobool.not, i8 4, i8 3
+  %conv1 = zext nneg i8 %sub.i to i32
+  store i32 %conv1, ptr @g_2, align 4
+  %.pr = load i32, ptr @g_2, align 4
+  %tobool5.not = icmp eq i32 %.pr, 0
+  br i1 %tobool5.not, label %for.cond, label %lbl_1
+
+lbl_1:
+  br label %lbl_1
+
+for.cond:
+  br label %for.cond
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/171137


More information about the llvm-commits mailing list