[llvm] [AggressiveInstCombine] Add shufflevector support to TruncInstCombine (PR #220218)
Laxman Gupta via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 8 06:55:31 PDT 2026
https://github.com/laxman-gupta1006 updated https://github.com/llvm/llvm-project/pull/220218
>From a2b40c90982b5b5d16b275d8c4cf87531d51a8a7 Mon Sep 17 00:00:00 2001
From: laxman-gupta1006 <laxman.gupta1006 at gmail.com>
Date: Tue, 1 Sep 2026 16:39:01 +0530
Subject: [PATCH 1/2] [test] Update TruncInstCombine tests to show
shufflevector optimization
Update test expectations for shufflevector patterns in TruncInstCombine.
Tests now show optimized behavior with reduced bitwidth operations.
---
.../AggressiveInstCombine/trunc_vector_instrs.ll | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/llvm/test/Transforms/AggressiveInstCombine/trunc_vector_instrs.ll b/llvm/test/Transforms/AggressiveInstCombine/trunc_vector_instrs.ll
index fd84dce33c092..5099c07bf37a6 100644
--- a/llvm/test/Transforms/AggressiveInstCombine/trunc_vector_instrs.ll
+++ b/llvm/test/Transforms/AggressiveInstCombine/trunc_vector_instrs.ll
@@ -3,10 +3,9 @@
define <4 x i16> @shuffle(<2 x i8> %a, <2 x i8> %b) {
; CHECK-LABEL: @shuffle(
-; CHECK-NEXT: [[ZEXTA:%.*]] = zext <2 x i8> [[A:%.*]] to <2 x i32>
-; CHECK-NEXT: [[ZEXTB:%.*]] = zext <2 x i8> [[B:%.*]] to <2 x i32>
-; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <2 x i32> [[ZEXTA]], <2 x i32> [[ZEXTB]], <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; CHECK-NEXT: [[TRUNC:%.*]] = trunc <4 x i32> [[SHUF]] to <4 x i16>
+; CHECK-NEXT: [[ZEXTA:%.*]] = zext <2 x i8> [[A:%.*]] to <2 x i16>
+; CHECK-NEXT: [[ZEXTB:%.*]] = zext <2 x i8> [[B:%.*]] to <2 x i16>
+; CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <2 x i16> [[ZEXTA]], <2 x i16> [[ZEXTB]], <4 x i32> <i32 3, i32 2, i32 1, i32 0>
; CHECK-NEXT: ret <4 x i16> [[TRUNC]]
;
%zexta = zext <2 x i8> %a to <2 x i32>
@@ -18,9 +17,8 @@ define <4 x i16> @shuffle(<2 x i8> %a, <2 x i8> %b) {
define <2 x i16> @unary_shuffle(<2 x i8> %a) {
; CHECK-LABEL: @unary_shuffle(
-; CHECK-NEXT: [[ZEXTA:%.*]] = zext <2 x i8> [[A:%.*]] to <2 x i32>
-; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <2 x i32> [[ZEXTA]], <2 x i32> poison, <2 x i32> <i32 1, i32 0>
-; CHECK-NEXT: [[TRUNC:%.*]] = trunc <2 x i32> [[SHUF]] to <2 x i16>
+; CHECK-NEXT: [[ZEXTA:%.*]] = zext <2 x i8> [[A:%.*]] to <2 x i16>
+; CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <2 x i16> [[ZEXTA]], <2 x i16> poison, <2 x i32> <i32 1, i32 0>
; CHECK-NEXT: ret <2 x i16> [[TRUNC]]
;
%zexta = zext <2 x i8> %a to <2 x i32>
@@ -31,9 +29,7 @@ define <2 x i16> @unary_shuffle(<2 x i8> %a) {
define <4 x i16> @const_shuffle() {
; CHECK-LABEL: @const_shuffle(
-; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <2 x i32> <i32 1, i32 2>, <2 x i32> <i32 3, i32 7>, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-; CHECK-NEXT: [[TRUNC:%.*]] = trunc <4 x i32> [[SHUF]] to <4 x i16>
-; CHECK-NEXT: ret <4 x i16> [[TRUNC]]
+; CHECK-NEXT: ret <4 x i16> <i16 7, i16 3, i16 2, i16 1>
;
%shuf = shufflevector <2 x i32> <i32 1, i32 2>, <2 x i32> <i32 3, i32 7>, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
%trunc = trunc <4 x i32> %shuf to <4 x i16>
>From d728aa0729a675381ca14b23e1ccd1583b3a6dd7 Mon Sep 17 00:00:00 2001
From: laxman-gupta1006 <laxman.gupta1006 at gmail.com>
Date: Tue, 1 Sep 2026 16:39:37 +0530
Subject: [PATCH 2/2] [AggressiveInstCombine] Add shufflevector support to
TruncInstCombine
This patch extends TruncInstCombine to handle shufflevector operations,
enabling expression graphs containing shuffle operations to be reduced to
smaller bit-widths.
Changes:
1. isRelevantOperand() - Mark shufflevector operands as relevant to the
optimization graph (line ~76)
2. buildTruncExpressionGraph() - Add shufflevector to expression DAG
traversal and remove from TODO list (line ~152)
3. ReduceExpressionGraph() - Implement shufflevector IR generation for
reduced-bitwidth operations, preserving the original shuffle mask
(line ~470)
Example optimization:
Before: zext to i32 -> shuffle i32 -> trunc to i16
After: zext to i16 -> shuffle i16 (no trunc needed)
This closes the shufflevector TODO in the pass and improves optimization
for vectorized code patterns.
---
.../AggressiveInstCombine/TruncInstCombine.cpp | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Transforms/AggressiveInstCombine/TruncInstCombine.cpp b/llvm/lib/Transforms/AggressiveInstCombine/TruncInstCombine.cpp
index e07012938e09c..4b29e33c2e7f7 100644
--- a/llvm/lib/Transforms/AggressiveInstCombine/TruncInstCombine.cpp
+++ b/llvm/lib/Transforms/AggressiveInstCombine/TruncInstCombine.cpp
@@ -73,6 +73,8 @@ static bool isRelevantOperand(const Instruction *I, unsigned OpNo) {
return OpNo != 0;
case Instruction::PHI:
return true;
+ case Instruction::ShuffleVector:
+ return true;
default:
llvm_unreachable("Unreachable!");
}
@@ -147,7 +149,8 @@ bool TruncInstCombine::buildTruncExpressionGraph() {
case Instruction::URem:
case Instruction::InsertElement:
case Instruction::ExtractElement:
- case Instruction::Select: {
+ case Instruction::Select:
+ case Instruction::ShuffleVector: {
SmallVector<Value *, 2> Operands;
getRelevantOperands(I, Operands);
append_range(Worklist, Operands);
@@ -164,8 +167,7 @@ bool TruncInstCombine::buildTruncExpressionGraph() {
}
default:
// TODO: Can handle more cases here:
- // 1. shufflevector
- // 2. sdiv, srem
+ // 1. sdiv, srem
// ...
return false;
}
@@ -352,7 +354,6 @@ Type *TruncInstCombine::getBestTruncatedType() {
if (MinBitWidth >= OrigBitWidth ||
(DesiredBitWidth && DesiredBitWidth != MinBitWidth))
return nullptr;
-
return IntegerType::get(CurrentTruncInst->getContext(), MinBitWidth);
}
@@ -466,6 +467,13 @@ void TruncInstCombine::ReduceExpressionGraph(Type *SclTy) {
Res = Builder.CreateSelect(Op0, LHS, RHS, "", I);
break;
}
+ case Instruction::ShuffleVector: {
+ Value *LHS = getReducedOperand(I->getOperand(0), SclTy);
+ Value *RHS = getReducedOperand(I->getOperand(1), SclTy);
+ auto *SI = cast<ShuffleVectorInst>(I);
+ Res = Builder.CreateShuffleVector(LHS, RHS, SI->getShuffleMask());
+ break;
+ }
case Instruction::PHI: {
Res = Builder.CreatePHI(getReducedType(I, SclTy), I->getNumOperands());
OldNewPHINodes.push_back(
More information about the llvm-commits
mailing list