[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