[llvm] [InstCombine] Fold `(select C, (x bin_op a), x) bin_op b` into `x bin_op select C, (a bin_op b), b` (PR #173511)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 26 23:52:10 PST 2025


================
@@ -1876,6 +1876,47 @@ static Value *simplifyInstructionWithPHI(Instruction &I, PHINode *PN,
   return nullptr;
 }
 
+// In some cases it is beneficial to fold a select into a binary operator.
+// For example:
+//   %1 = or %in, 4
+//   %2 = select %cond, %1, %in
+//   %3 = or %2, 1
+// =>
+//   %1 = select i1 %cond, 5, 1
+//   %2 = or %1, %in
+Instruction *InstCombinerImpl::foldSelectIntoBinOp(BinaryOperator &Op) {
+  assert(Op.isAssociative() && "The operation must be associative!");
+
+  SelectInst *SI = dyn_cast<SelectInst>(Op.getOperand(0));
+  Constant *Const = dyn_cast<Constant>(Op.getOperand(1));
+  if (!SI || !Const || !Op.hasOneUse() || !SI->hasOneUse())
+    return nullptr;
+
+  // TODO: Maybe hasOneUse the other bin op too?
----------------
dtcxzyw wrote:

Did you remove the one-use check on the select? We are discussing whether to add the one-use check on the first op, right? Without your last commit the IR diff in PGOProfiles/chr.ll looks like this:

<img width="2680" height="884" alt="image" src="https://github.com/user-attachments/assets/33fd362b-cb03-41b1-9454-4d5a5706a562" />

Perhaps a select instruction with both constant arms is slightly more expensive to materialize in the backend. So I don't have a strong objection to adding one-use checks on all intermediate expressions.


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


More information about the llvm-commits mailing list