[llvm] [InstCombine] Fix invalid fshl -> lshr fold when shift is vector with constant zero lane (PR #210606)

Benji Smith via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 19 08:54:01 PDT 2026


https://github.com/Benjins created https://github.com/llvm/llvm-project/pull/210606

For vectors, this is not valid if a subset of the lanes are constant zero. Doing this fold introduces poison in those lanes. A similar fix was done for fshr in 46957a138dea339799059ea5bf032e40042ff185 however the same issue seems to apply to fshl

Fixes https://github.com/llvm/llvm-project/issues/210605

>From a2f6cd0682629161dbccf487be2fd75743d77b36 Mon Sep 17 00:00:00 2001
From: Benji Smith <6193112+Benjins at users.noreply.github.com>
Date: Sun, 19 Jul 2026 11:29:51 -0400
Subject: [PATCH] Fix invalid fshl -> lshr fold

For vectors, this is not valid if a subset of the lanes are constant zero.
Doing this fold introduces poison in those lanes. A similar fix was done for
fshr in 46957a138dea339799059ea5bf032e40042ff185 however the same issue seems
to apply to fshl

Fixes https://github.com/llvm/llvm-project/issues/210605
---
 llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp | 4 +++-
 llvm/test/Transforms/InstCombine/fsh.ll              | 9 +++++++++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 9e3f0e01c002b..9caafb1728cf8 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -2668,7 +2668,9 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
 
       // fshl(0, X, C) --> lshr X, (BW-C)
       // fshl(undef, X, C) --> lshr X, (BW-C)
-      if (match(Op0, m_ZeroInt()) || match(Op0, m_Undef()))
+      // Similar to fshr -> fshl fold above, this is only valid if C is not zero
+      if ((match(Op0, m_ZeroInt()) || match(Op0, m_Undef())) &&
+          isKnownNonZero(ShAmtC, SQ.getWithInstruction(II)))
         return BinaryOperator::CreateLShr(Op1,
                                           ConstantExpr::getSub(WidthC, ShAmtC));
 
diff --git a/llvm/test/Transforms/InstCombine/fsh.ll b/llvm/test/Transforms/InstCombine/fsh.ll
index 79d3f94182b0b..fd2f8b90b0e0b 100644
--- a/llvm/test/Transforms/InstCombine/fsh.ll
+++ b/llvm/test/Transforms/InstCombine/fsh.ll
@@ -1072,6 +1072,15 @@ define <2 x i32> @fshr_vec_zero_elem(<2 x i32> %x, <2 x i32> %y) {
   ret <2 x i32> %fsh
 }
 
+define <2 x i32> @fshl_vec_zero_elem(<2 x i32> %x) {
+; CHECK-LABEL: @fshl_vec_zero_elem(
+; CHECK-NEXT:    [[FSH:%.*]] = call <2 x i32> @llvm.fshl.v2i32(<2 x i32> zeroinitializer, <2 x i32> [[X:%.*]], <2 x i32> <i32 2, i32 0>)
+; CHECK-NEXT:    ret <2 x i32> [[FSH]]
+;
+  %fsh = call <2 x i32> @llvm.fshl.v2i32(<2 x i32> zeroinitializer, <2 x i32> %x, <2 x i32> <i32 2, i32 0>)
+  ret <2 x i32> %fsh
+}
+
 define i16 @fshl_i16_shl(i16 %x, i16 %y) {
 ; CHECK-LABEL: @fshl_i16_shl(
 ; CHECK-NEXT:  entry:



More information about the llvm-commits mailing list