[llvm] [InstCombine] narrow select to match trunc condition operand size (PR #219794)

Andreas Jonson via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 30 04:02:52 PDT 2026


https://github.com/andjo403 created https://github.com/llvm/llvm-project/pull/219794

changed to matches the cmp handling

first two commits is from https://github.com/llvm/llvm-project/pull/219789 needed to avoid infinit loop



>From a9bdca428fbca36a2be1f281312eda3e0d178e11 Mon Sep 17 00:00:00 2001
From: Andreas Jonson <andjo403 at hotmail.com>
Date: Sun, 30 Aug 2026 11:42:44 +0200
Subject: [PATCH 1/4] [InstCombine] pre commit test (NFC)

---
 .../Transforms/InstCombine/cast-select.ll     | 77 +++++++++++++++++++
 1 file changed, 77 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/cast-select.ll b/llvm/test/Transforms/InstCombine/cast-select.ll
index 0bc7cdaf7eb22..de400fc906709 100644
--- a/llvm/test/Transforms/InstCombine/cast-select.ll
+++ b/llvm/test/Transforms/InstCombine/cast-select.ll
@@ -131,3 +131,80 @@ define <2 x float> @fptrunc_vec(<2 x double> %x, <2 x double> %y, <2 x double> %
   ret <2 x float> %r
 }
 
+define i64 @zext_trunc_cond(i32 %x, i32 %z) {
+; CHECK-LABEL: @zext_trunc_cond(
+; CHECK-NEXT:    [[CMP:%.*]] = trunc i32 [[X:%.*]] to i1
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[Z:%.*]] to i64
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP]], i64 0, i64 [[TMP1]]
+; CHECK-NEXT:    ret i64 [[R]]
+;
+  %cmp = trunc i32 %x to i1
+  %sel = select i1 %cmp, i32 0, i32 %z
+  %r = zext i32 %sel to i64
+  ret i64 %r
+}
+
+define <2 x i32> @zext_trunc_cond_vec(<2 x i8> %x, <2 x i8> %z) {
+; CHECK-LABEL: @zext_trunc_cond_vec(
+; CHECK-NEXT:    [[CMP:%.*]] = trunc <2 x i8> [[X:%.*]] to <2 x i1>
+; CHECK-NEXT:    [[TMP1:%.*]] = zext <2 x i8> [[Z:%.*]] to <2 x i32>
+; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[TMP1]], <2 x i32> <i32 42, i32 7>
+; CHECK-NEXT:    ret <2 x i32> [[R]]
+;
+  %cmp = trunc <2 x i8> %x to <2 x i1>
+  %sel = select <2 x i1> %cmp, <2 x i8> %z, <2 x i8> <i8 42, i8 7>
+  %r = zext <2 x i8> %sel to <2 x i32>
+  ret <2 x i32> %r
+}
+
+define i64 @sext_trunc_cond(i8 %x, i8 %z) {
+; CHECK-LABEL: @sext_trunc_cond(
+; CHECK-NEXT:    [[CMP:%.*]] = trunc i8 [[X:%.*]] to i1
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i8 [[Z:%.*]] to i64
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP]], i64 42, i64 [[TMP1]]
+; CHECK-NEXT:    ret i64 [[R]]
+;
+  %cmp = trunc i8 %x to i1
+  %sel = select i1 %cmp, i8 42, i8 %z
+  %r = sext i8 %sel to i64
+  ret i64 %r
+}
+
+define <2 x i32> @sext_trunc_cond_vec(<2 x i8> %x, <2 x i8> %z) {
+; CHECK-LABEL: @sext_trunc_cond_vec(
+; CHECK-NEXT:    [[CMP:%.*]] = trunc <2 x i8> [[X:%.*]] to <2 x i1>
+; CHECK-NEXT:    [[TMP1:%.*]] = sext <2 x i8> [[Z:%.*]] to <2 x i32>
+; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[TMP1]], <2 x i32> <i32 42, i32 7>
+; CHECK-NEXT:    ret <2 x i32> [[R]]
+;
+  %cmp = trunc <2 x i8> %x to <2 x i1>
+  %sel = select <2 x i1> %cmp, <2 x i8> %z, <2 x i8> <i8 42, i8 7>
+  %r = sext <2 x i8> %sel to <2 x i32>
+  ret <2 x i32> %r
+}
+
+define i16 @trunc_trunc_cond(i32 %x, i32 %z) {
+; CHECK-LABEL: @trunc_trunc_cond(
+; CHECK-NEXT:    [[CMP:%.*]] = trunc i32 [[X:%.*]] to i1
+; CHECK-NEXT:    [[TMP1:%.*]] = trunc i32 [[Z:%.*]] to i16
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP]], i16 42, i16 [[TMP1]]
+; CHECK-NEXT:    ret i16 [[R]]
+;
+  %cmp = trunc i32 %x to i1
+  %sel = select i1 %cmp, i32 42, i32 %z
+  %r = trunc i32 %sel to i16
+  ret i16 %r
+}
+
+define <2 x i32> @trunc_trunc_cond_vec(<2 x i64> %x, <2 x i64> %z) {
+; CHECK-LABEL: @trunc_trunc_cond_vec(
+; CHECK-NEXT:    [[CMP:%.*]] = trunc <2 x i64> [[X:%.*]] to <2 x i1>
+; CHECK-NEXT:    [[TMP1:%.*]] = trunc <2 x i64> [[Z:%.*]] to <2 x i32>
+; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[TMP1]], <2 x i32> <i32 42, i32 7>
+; CHECK-NEXT:    ret <2 x i32> [[R]]
+;
+  %cmp = trunc <2 x i64> %x to <2 x i1>
+  %sel = select <2 x i1> %cmp, <2 x i64> %z, <2 x i64> <i64 42, i64 7>
+  %r = trunc <2 x i64> %sel to <2 x i32>
+  ret <2 x i32> %r
+}

>From c9c2a94959e886b09ea2d705637401a319a9e09b Mon Sep 17 00:00:00 2001
From: Andreas Jonson <andjo403 at hotmail.com>
Date: Sun, 30 Aug 2026 11:49:33 +0200
Subject: [PATCH 2/4] [InstCombine] Don't change the size of a select if it
 would mismatch its trunc condition operand size

matching handling as for icmp.
---
 .../InstCombine/InstCombineCasts.cpp          |  5 ++--
 .../Transforms/InstCombine/cast-select.ll     | 30 +++++++++----------
 2 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index d66e226e73723..1b160f18c5c62 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -248,8 +248,9 @@ Instruction *InstCombinerImpl::commonCastTransforms(CastInst &CI) {
     // or the select is likely better done in a narrow type.
     // Creating a select with operands that are different sizes than its
     // condition may inhibit other folds and lead to worse codegen.
-    auto *Cmp = dyn_cast<CmpInst>(Sel->getCondition());
-    if (!Cmp || Cmp->getOperand(0)->getType() != Sel->getType() ||
+    Value *Cond = Sel->getCondition();
+    if (!isa<CmpInst, TruncInst>(Cond) ||
+        cast<Instruction>(Cond)->getOperand(0)->getType() != Sel->getType() ||
         (CI.getOpcode() == Instruction::Trunc &&
          shouldChangeType(CI.getSrcTy(), CI.getType()))) {
 
diff --git a/llvm/test/Transforms/InstCombine/cast-select.ll b/llvm/test/Transforms/InstCombine/cast-select.ll
index de400fc906709..d3b1ac1563344 100644
--- a/llvm/test/Transforms/InstCombine/cast-select.ll
+++ b/llvm/test/Transforms/InstCombine/cast-select.ll
@@ -134,9 +134,9 @@ define <2 x float> @fptrunc_vec(<2 x double> %x, <2 x double> %y, <2 x double> %
 define i64 @zext_trunc_cond(i32 %x, i32 %z) {
 ; CHECK-LABEL: @zext_trunc_cond(
 ; CHECK-NEXT:    [[CMP:%.*]] = trunc i32 [[X:%.*]] to i1
-; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[Z:%.*]] to i64
-; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP]], i64 0, i64 [[TMP1]]
-; CHECK-NEXT:    ret i64 [[R]]
+; CHECK-NEXT:    [[Z:%.*]] = select i1 [[CMP]], i32 0, i32 [[Z1:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[Z]] to i64
+; CHECK-NEXT:    ret i64 [[TMP1]]
 ;
   %cmp = trunc i32 %x to i1
   %sel = select i1 %cmp, i32 0, i32 %z
@@ -147,9 +147,9 @@ define i64 @zext_trunc_cond(i32 %x, i32 %z) {
 define <2 x i32> @zext_trunc_cond_vec(<2 x i8> %x, <2 x i8> %z) {
 ; CHECK-LABEL: @zext_trunc_cond_vec(
 ; CHECK-NEXT:    [[CMP:%.*]] = trunc <2 x i8> [[X:%.*]] to <2 x i1>
-; CHECK-NEXT:    [[TMP1:%.*]] = zext <2 x i8> [[Z:%.*]] to <2 x i32>
-; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[TMP1]], <2 x i32> <i32 42, i32 7>
-; CHECK-NEXT:    ret <2 x i32> [[R]]
+; CHECK-NEXT:    [[Z:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[Z1:%.*]], <2 x i8> <i8 42, i8 7>
+; CHECK-NEXT:    [[TMP1:%.*]] = zext <2 x i8> [[Z]] to <2 x i32>
+; CHECK-NEXT:    ret <2 x i32> [[TMP1]]
 ;
   %cmp = trunc <2 x i8> %x to <2 x i1>
   %sel = select <2 x i1> %cmp, <2 x i8> %z, <2 x i8> <i8 42, i8 7>
@@ -160,9 +160,9 @@ define <2 x i32> @zext_trunc_cond_vec(<2 x i8> %x, <2 x i8> %z) {
 define i64 @sext_trunc_cond(i8 %x, i8 %z) {
 ; CHECK-LABEL: @sext_trunc_cond(
 ; CHECK-NEXT:    [[CMP:%.*]] = trunc i8 [[X:%.*]] to i1
-; CHECK-NEXT:    [[TMP1:%.*]] = sext i8 [[Z:%.*]] to i64
-; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP]], i64 42, i64 [[TMP1]]
-; CHECK-NEXT:    ret i64 [[R]]
+; CHECK-NEXT:    [[Z:%.*]] = select i1 [[CMP]], i8 42, i8 [[Z1:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i8 [[Z]] to i64
+; CHECK-NEXT:    ret i64 [[TMP1]]
 ;
   %cmp = trunc i8 %x to i1
   %sel = select i1 %cmp, i8 42, i8 %z
@@ -173,9 +173,9 @@ define i64 @sext_trunc_cond(i8 %x, i8 %z) {
 define <2 x i32> @sext_trunc_cond_vec(<2 x i8> %x, <2 x i8> %z) {
 ; CHECK-LABEL: @sext_trunc_cond_vec(
 ; CHECK-NEXT:    [[CMP:%.*]] = trunc <2 x i8> [[X:%.*]] to <2 x i1>
-; CHECK-NEXT:    [[TMP1:%.*]] = sext <2 x i8> [[Z:%.*]] to <2 x i32>
-; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[TMP1]], <2 x i32> <i32 42, i32 7>
-; CHECK-NEXT:    ret <2 x i32> [[R]]
+; CHECK-NEXT:    [[Z:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[Z1:%.*]], <2 x i8> <i8 42, i8 7>
+; CHECK-NEXT:    [[TMP1:%.*]] = sext <2 x i8> [[Z]] to <2 x i32>
+; CHECK-NEXT:    ret <2 x i32> [[TMP1]]
 ;
   %cmp = trunc <2 x i8> %x to <2 x i1>
   %sel = select <2 x i1> %cmp, <2 x i8> %z, <2 x i8> <i8 42, i8 7>
@@ -199,9 +199,9 @@ define i16 @trunc_trunc_cond(i32 %x, i32 %z) {
 define <2 x i32> @trunc_trunc_cond_vec(<2 x i64> %x, <2 x i64> %z) {
 ; CHECK-LABEL: @trunc_trunc_cond_vec(
 ; CHECK-NEXT:    [[CMP:%.*]] = trunc <2 x i64> [[X:%.*]] to <2 x i1>
-; CHECK-NEXT:    [[TMP1:%.*]] = trunc <2 x i64> [[Z:%.*]] to <2 x i32>
-; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[TMP1]], <2 x i32> <i32 42, i32 7>
-; CHECK-NEXT:    ret <2 x i32> [[R]]
+; CHECK-NEXT:    [[Z:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[Z1:%.*]], <2 x i64> <i64 42, i64 7>
+; CHECK-NEXT:    [[TMP1:%.*]] = trunc <2 x i64> [[Z]] to <2 x i32>
+; CHECK-NEXT:    ret <2 x i32> [[TMP1]]
 ;
   %cmp = trunc <2 x i64> %x to <2 x i1>
   %sel = select <2 x i1> %cmp, <2 x i64> %z, <2 x i64> <i64 42, i64 7>

>From 5235eaf42f54cde23d290e1eb4aae0923406292d Mon Sep 17 00:00:00 2001
From: Andreas Jonson <andjo403 at hotmail.com>
Date: Sun, 30 Aug 2026 12:29:27 +0200
Subject: [PATCH 3/4] [InstCombine] Pre commit test (NFC)

---
 .../Transforms/InstCombine/select-bitext.ll   | 26 +++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/select-bitext.ll b/llvm/test/Transforms/InstCombine/select-bitext.ll
index 553d5ae155153..b722f95067963 100644
--- a/llvm/test/Transforms/InstCombine/select-bitext.ll
+++ b/llvm/test/Transforms/InstCombine/select-bitext.ll
@@ -646,5 +646,31 @@ define <2 x i32> @zext_false_val_must_be_zero_vec(<2 x i1> %x) {
   ret <2 x i32> %sel
 }
 
+define i32 @sel_trunc_cond_zext_const(i8 %a, i8 %x) {
+; CHECK-LABEL: @sel_trunc_cond_zext_const(
+; CHECK-NEXT:    [[COND:%.*]] = trunc i8 [[X:%.*]] to i1
+; CHECK-NEXT:    [[A_EXT:%.*]] = zext i8 [[A:%.*]] to i32
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[COND]], i32 [[A_EXT]], i32 127
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %cond = trunc i8 %x to i1
+  %a.ext = zext i8 %a to i32
+  %r = select i1 %cond, i32 %a.ext, i32 127
+  ret i32 %r
+}
+
+define i32 @sel_trunc_cond_sext_const(i8 %a, i8 %x) {
+; CHECK-LABEL: @sel_trunc_cond_sext_const(
+; CHECK-NEXT:    [[COND:%.*]] = trunc i8 [[X:%.*]] to i1
+; CHECK-NEXT:    [[A_EXT:%.*]] = sext i8 [[A:%.*]] to i32
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[COND]], i32 [[A_EXT]], i32 -4
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %cond = trunc i8 %x to i1
+  %a.ext = sext i8 %a to i32
+  %r = select i1 %cond, i32 %a.ext, i32 -4
+  ret i32 %r
+}
+
 !0 = !{!"branch_weights", i32 3, i32 5}
 

>From 1aa16af9410d72d10a279035fc485cf5d33e949c Mon Sep 17 00:00:00 2001
From: Andreas Jonson <andjo403 at hotmail.com>
Date: Sun, 30 Aug 2026 12:30:47 +0200
Subject: [PATCH 4/4] [InstCombine] narrow select to match trunc condition
 operand size

matches cmp handling.
---
 .../lib/Transforms/InstCombine/InstCombineSelect.cpp |  4 ++--
 llvm/test/Transforms/InstCombine/select-bitext.ll    | 12 ++++++------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index f785ea182a389..81d949fd1fb28 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -2718,9 +2718,9 @@ Instruction *InstCombinerImpl::foldSelectExtConst(SelectInst &Sel) {
   Value *X = ExtInst->getOperand(0);
   Type *SmallType = X->getType();
   Value *Cond = Sel.getCondition();
-  auto *Cmp = dyn_cast<CmpInst>(Cond);
   if (!SmallType->isIntOrIntVectorTy(1) &&
-      (!Cmp || Cmp->getOperand(0)->getType() != SmallType))
+      (!isa<CmpInst, TruncInst>(Cond) ||
+       cast<Instruction>(Cond)->getOperand(0)->getType() != SmallType))
     return nullptr;
 
   // If the constant is the same after truncation to the smaller type and
diff --git a/llvm/test/Transforms/InstCombine/select-bitext.ll b/llvm/test/Transforms/InstCombine/select-bitext.ll
index b722f95067963..ea02ea69222e2 100644
--- a/llvm/test/Transforms/InstCombine/select-bitext.ll
+++ b/llvm/test/Transforms/InstCombine/select-bitext.ll
@@ -649,9 +649,9 @@ define <2 x i32> @zext_false_val_must_be_zero_vec(<2 x i1> %x) {
 define i32 @sel_trunc_cond_zext_const(i8 %a, i8 %x) {
 ; CHECK-LABEL: @sel_trunc_cond_zext_const(
 ; CHECK-NEXT:    [[COND:%.*]] = trunc i8 [[X:%.*]] to i1
-; CHECK-NEXT:    [[A_EXT:%.*]] = zext i8 [[A:%.*]] to i32
-; CHECK-NEXT:    [[R:%.*]] = select i1 [[COND]], i32 [[A_EXT]], i32 127
-; CHECK-NEXT:    ret i32 [[R]]
+; CHECK-NEXT:    [[A:%.*]] = select i1 [[COND]], i8 [[A1:%.*]], i8 127
+; CHECK-NEXT:    [[A_EXT:%.*]] = zext i8 [[A]] to i32
+; CHECK-NEXT:    ret i32 [[A_EXT]]
 ;
   %cond = trunc i8 %x to i1
   %a.ext = zext i8 %a to i32
@@ -662,9 +662,9 @@ define i32 @sel_trunc_cond_zext_const(i8 %a, i8 %x) {
 define i32 @sel_trunc_cond_sext_const(i8 %a, i8 %x) {
 ; CHECK-LABEL: @sel_trunc_cond_sext_const(
 ; CHECK-NEXT:    [[COND:%.*]] = trunc i8 [[X:%.*]] to i1
-; CHECK-NEXT:    [[A_EXT:%.*]] = sext i8 [[A:%.*]] to i32
-; CHECK-NEXT:    [[R:%.*]] = select i1 [[COND]], i32 [[A_EXT]], i32 -4
-; CHECK-NEXT:    ret i32 [[R]]
+; CHECK-NEXT:    [[A:%.*]] = select i1 [[COND]], i8 [[A1:%.*]], i8 -4
+; CHECK-NEXT:    [[A_EXT:%.*]] = sext i8 [[A]] to i32
+; CHECK-NEXT:    ret i32 [[A_EXT]]
 ;
   %cond = trunc i8 %x to i1
   %a.ext = sext i8 %a to i32



More information about the llvm-commits mailing list