[llvm] [InstCombine] Match a new form of truncating saturation (PR #189703)

David Sherwood via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 2 07:55:16 PDT 2026


================
@@ -1171,6 +1171,33 @@ Instruction *InstCombinerImpl::visitTrunc(TruncInst &Trunc) {
     }
   }
 
+  // trunc (select(icmp_ult(A, DestTy_umax+1), A, sext(icmp_sgt(A, 0)))) -->
+  // trunc (smin(smax(0, A), DestTy_umax))
+  if (SrcTy->isIntegerTy() && isPowerOf2_64(SrcTy->getPrimitiveSizeInBits()) &&
+      DestTy->isIntegerTy() &&
+      isPowerOf2_64(DestTy->getPrimitiveSizeInBits()) &&
+      match(Src,
+            m_OneUse(m_Select(
+                m_SpecificICmp(ICmpInst::ICMP_ULT, m_Value(A), m_Constant(C)),
+                m_Deferred(A),
+                m_SExt(m_SpecificICmp(ICmpInst::ICMP_SGT, m_Deferred(A),
+                                      m_Zero())))))) {
+    APInt UpperBound = C->getUniqueInteger();
+    APInt TruncatedMax = APInt::getAllOnes(DestTy->getIntegerBitWidth());
----------------
david-arm wrote:

According to the LangRef the bit size of the type you're truncating must be greater than the bit size of the destination type. Also, since A is one the selected inputs then the result of the select must have the same type as A. That means A must have a bigger size than the dest type and given we're comparing A against C then by definition C must also have a bigger type than the dest type. I think that means you can just do

```
  APInt UpperBound = C->getUniqueInteger();
  APInt TruncatedMax = APInt::getAllOnes(DestTy->getIntegerBitWidth());
  TruncatedMax = TruncatedMax.zext(UpperBound.getBitWidth());
```

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


More information about the llvm-commits mailing list