[llvm] [SelectOptimize] Reject Not as BinOp SelectLike aux (fix #226417) (PR #226539)

Atharva Ajmera via llvm-commits llvm-commits at lists.llvm.org
Sat Sep 26 02:01:54 PDT 2026


https://github.com/atharvaajmera updated https://github.com/llvm/llvm-project/pull/226539

>From 163aff05b390a2ad0a1c511bcfdd050bd9a24c0f Mon Sep 17 00:00:00 2001
From: atharvaajmera <atharvaajmera06 at gmail.com>
Date: Fri, 25 Sep 2026 22:35:02 +0530
Subject: [PATCH] [SelectOptimize] Reject Not as BinOp SelectLike aux (fix
 #226417)

getTrueOrFalseValue() only supports ZExt, SExt, and Shift auxiliaries for BinOp SelectLikes. Skip other auxiliary kinds (such as Not/xor) when forming BinOp groups to prevent hitting an unexpected opcode assertion during conversion.

Fixes #226417
---
 llvm/lib/CodeGen/SelectOptimize.cpp           |  5 ++
 .../CodeGen/AArch64/selectopt-issue226417.ll  | 81 +++++++++++++++++++
 2 files changed, 86 insertions(+)
 create mode 100644 llvm/test/CodeGen/AArch64/selectopt-issue226417.ll

diff --git a/llvm/lib/CodeGen/SelectOptimize.cpp b/llvm/lib/CodeGen/SelectOptimize.cpp
index ac2ebcc620051e..95c4dbad4a4a89 100644
--- a/llvm/lib/CodeGen/SelectOptimize.cpp
+++ b/llvm/lib/CodeGen/SelectOptimize.cpp
@@ -884,6 +884,11 @@ void SelectOptimizeImpl::collectSelectGroups(BasicBlock &BB,
         auto *Op = I->getOperand(Idx);
         auto It = SelectInfo.find(Op);
         if (It != SelectInfo.end() && It->second.IsAuxiliary) {
+          // getTrueOrFalseValue only supports ZExt, SExt, and Shift auxiliaries for BinOps.
+          auto *OpI = dyn_cast<Instruction>(Op);
+          if (!OpI || (!isa<ZExtInst>(OpI) && !isa<SExtInst>(OpI) &&
+                       !isa<LShrOperator>(OpI) && !isa<AShrOperator>(OpI)))
+            continue;
           Cond = It->second.Cond;
           bool Inverted = It->second.IsInverted;
           return SelectInfo.insert({I, {Cond, false, Inverted, Idx}}).first;
diff --git a/llvm/test/CodeGen/AArch64/selectopt-issue226417.ll b/llvm/test/CodeGen/AArch64/selectopt-issue226417.ll
new file mode 100644
index 00000000000000..a4e7dd70b256ac
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/selectopt-issue226417.ll
@@ -0,0 +1,81 @@
+; RUN: opt -passes='require<profile-summary>,function(select-optimize)' -mtriple=aarch64-linux-gnu -mcpu=generic -S < %s | FileCheck %s
+
+; Test that xor auxiliaries are not grouped into BinOp SelectLikes (#226417).
+
+define void @not_xor_add_not_selectlike(i32 %n, i1 %c, i1 %v, i32 %a, i32 %b) {
+; CHECK-LABEL: @not_xor_add_not_selectlike(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[OUTER:%.*]]
+; CHECK:       outer:
+; CHECK:       latch:
+; CHECK-NEXT:    [[NC:%.*]] = xor i1 [[C:%.*]], true
+; CHECK-NEXT:    [[SH:%.*]] = lshr i1 [[V:%.*]], 0
+; CHECK-NEXT:    [[S0:%.*]] = select i1 [[C]], i32 [[A:%.*]], i32 [[B:%.*]]
+; CHECK-NEXT:    [[ADD:%.*]] = add i1 [[NC]], [[SH]]
+; CHECK-NEXT:    [[S2:%.*]] = select i1 [[C]], i32 [[A]], i32 [[B]]
+; CHECK-NOT: select.end
+; CHECK-NOT: freeze
+;
+entry:
+  br label %outer
+
+outer:
+  %i = phi i32 [ 0, %entry ], [ %i.next, %latch ]
+  br label %inner
+
+inner:
+  %j = phi i32 [ 0, %outer ], [ %j.next, %inner ]
+  %j.next = add i32 %j, 1
+  %ic = icmp slt i32 %j.next, %n
+  br i1 %ic, label %inner, label %latch
+
+latch:
+  %nc = xor i1 %c, true
+  %sh = lshr i1 %v, 0
+  %s0 = select i1 %c, i32 %a, i32 %b
+  %add = add i1 %nc, %sh
+  %s2 = select i1 %c, i32 %a, i32 %b
+  %i.next = add i32 %i, 1
+  %oc = icmp slt i32 %i.next, %n
+  br i1 %oc, label %outer, label %exit
+
+exit:
+  ret void
+}
+
+define void @not_xor_sub_not_selectlike(i32 %n, i1 %c, i1 %v, i32 %a, i32 %b) {
+; CHECK-LABEL: @not_xor_sub_not_selectlike(
+; CHECK:       latch:
+; CHECK-NEXT:    [[NC:%.*]] = xor i1 [[C:%.*]], true
+; CHECK-NEXT:    [[SH:%.*]] = lshr i1 [[V:%.*]], 0
+; CHECK-NEXT:    [[SUB:%.*]] = sub i1 [[SH]], [[NC]]
+; CHECK-NEXT:    [[S0:%.*]] = select i1 [[C]], i32 [[A:%.*]], i32 [[B:%.*]]
+; CHECK-NEXT:    [[S2:%.*]] = select i1 [[C]], i32 [[A]], i32 [[B]]
+; CHECK-NOT: select.end
+;
+entry:
+  br label %outer
+
+outer:
+  %i = phi i32 [ 0, %entry ], [ %i.next, %latch ]
+  br label %inner
+
+inner:
+  %j = phi i32 [ 0, %outer ], [ %j.next, %inner ]
+  %j.next = add i32 %j, 1
+  %ic = icmp slt i32 %j.next, %n
+  br i1 %ic, label %inner, label %latch
+
+latch:
+  %nc = xor i1 %c, true
+  %sh = lshr i1 %v, 0
+  %sub = sub i1 %sh, %nc
+  %s0 = select i1 %c, i32 %a, i32 %b
+  %s2 = select i1 %c, i32 %a, i32 %b
+  %i.next = add i32 %i, 1
+  %oc = icmp slt i32 %i.next, %n
+  br i1 %oc, label %outer, label %exit
+
+exit:
+  ret void
+}



More information about the llvm-commits mailing list