[llvm] [InstCombine] Fold reconstruction across select (PR #145102)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 6 06:16:24 PDT 2025


================
@@ -1349,6 +1349,41 @@ Value *InstCombinerImpl::SimplifySelectsFeedingBinaryOp(BinaryOperator &I,
     return nullptr;
   };
 
+  // Special case for reconstructing across a select:
+  // (Cond ? V1 : (X & Mask)) |
+  // zext (Cond ? V2 : trunc X)
+  // -> (Cond ? (V1 | zext V2) : X)
+  auto foldReconstruction = [&](Value *V1, Value *Masked,
+                                Value *ZExtSel) -> Value * {
+    if (Opcode != Instruction::Or)
+      return nullptr;
+
+    Value *X;
+    const APInt *C;
+    if (!match(Masked, m_OneUse(m_And(m_Value(X), m_APInt(C)))))
+      return nullptr;
+
+    Value *V2, *Trunc;
+    if (!match(ZExtSel, m_ZExt(m_OneUse(m_Select(m_Specific(Cond), m_Value(V2),
+                                                 m_Value(Trunc))))))
+      return nullptr;
+
+    if (*C != APInt::getBitsSetFrom(X->getType()->getScalarSizeInBits(),
+                                    Trunc->getType()->getScalarSizeInBits())) {
+      return nullptr;
+    }
+
+    if (!match(Trunc, m_Trunc(m_Specific(X))))
+      return nullptr;
+
+    Value *ZExtTrue = Builder.CreateZExt(V2, V1->getType());
----------------
nikic wrote:

This can abort the transform after creating a new instruction. We should not do this, as it risks infinite loops.

Do I see correctly that in the motivating cases (and all tests) V2 is actually a constant? In that case we can specialize to that.

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


More information about the llvm-commits mailing list