[llvm] [InstCombine] Optimize selects feeding into BinOp (PR #224478)

Antonio Frighetto via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 21 01:55:48 PDT 2026


================
@@ -1396,17 +1396,40 @@ Value *InstCombinerImpl::SimplifySelectsFeedingBinaryOp(BinaryOperator &I,
     return nullptr;
   };
 
-  if (LHSIsSelect && RHSIsSelect && A == D) {
-    // (A ? B : C) op (A ? E : F) -> A ? (B op E) : (C op F)
-    Cond = A;
-    True = simplifyBinOp(Opcode, B, E, FMF, Q);
-    False = simplifyBinOp(Opcode, C, F, FMF, Q);
-
-    if (LHS->hasOneUse() && RHS->hasOneUse()) {
-      if (False && !True)
-        True = Builder.CreateBinOp(Opcode, B, E);
-      else if (True && !False)
-        False = Builder.CreateBinOp(Opcode, C, F);
+  if (LHSIsSelect && RHSIsSelect) {
+    if (A == D) {
+      // (A ? B : C) op (A ? E : F) -> A ? (B op E) : (C op F)
+      Cond = A;
+      True = simplifyBinOp(Opcode, B, E, FMF, Q);
+      False = simplifyBinOp(Opcode, C, F, FMF, Q);
+
+      if (LHS->hasOneUse() && RHS->hasOneUse()) {
+        if (False && !True)
+          True = Builder.CreateBinOp(Opcode, B, E);
+        else if (True && !False)
+          False = Builder.CreateBinOp(Opcode, C, F);
+      }
+    } else if (A->getType() == D->getType() && LHS->hasOneUse()) {
+      // (A ? B : C) op (D ? E : F) ->
+      // A ? (B op (D ? E : F)) : (C op (D ? E : F))
+      // only if D can be implied by A
+      Cond = A;
+      Value *TrueRHS = RHS, *FalseRHS = RHS;
+      bool SimplifiedRHS = false;
+      if (std::optional<bool> Implied = isImpliedCondition(A, D, DL, true)) {
+        TrueRHS = *Implied ? E : F;
+        SimplifiedRHS = true;
+      }
+      if (std::optional<bool> Implied = isImpliedCondition(A, D, DL, false)) {
+        FalseRHS = *Implied ? E : F;
+        SimplifiedRHS = true;
+      }
+      if (SimplifiedRHS) {
+        True = simplifyBinOp(Opcode, B, TrueRHS, FMF, Q);
+        False = simplifyBinOp(Opcode, C, FalseRHS, FMF, Q);
+        if (Value *NewSel = foldAddNegate(B, C, RHS))
----------------
antoniofrighetto wrote:

Yeah, I think it should be dead code now. I'm not sure why we restructured the first check based on whether ` A != D` though. Maybe I'm missing something, but I would expect the new handling to be inside both cases:
```cpp
  else if (LHSIsSelect && LHS->hasOneUse()) {
    // ...
  } else if (RHSIsSelect && RHS->hasOneUse()) {
    // ...
  }
```
So you would handle both symmetrically. You'd still handle the case where one is a select and the other may be a select (the case we are interested in, and in this latter case we would know from the first condition that `A != D`).

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


More information about the llvm-commits mailing list