[llvm] [InstCombine] Propagate poison through fshl and fshr intrinsics (PR #172859)

Sayan Sivakumaran via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 18 06:38:10 PST 2025


https://github.com/sivakusayan created https://github.com/llvm/llvm-project/pull/172859

Currently these intrinsics output `undef` on poison, which triggers CI errors on PRs that want to add poison tests for funnel shifts (such as #172723). Let's make `fshl` and `fshr` propagate poison instead.

>From c46dbe2f2552e7cd42d179887568d7c98427c752 Mon Sep 17 00:00:00 2001
From: Sayan Sivakumaran <sivakusayan at gmail.com>
Date: Wed, 17 Dec 2025 20:51:44 -0600
Subject: [PATCH] Propagate poison through fshl and fshr intrinsics

---
 llvm/lib/Analysis/ValueTracking.cpp           |  2 ++
 llvm/test/Transforms/InstSimplify/call.ll     | 33 ++++++++-----------
 llvm/unittests/Analysis/ValueTrackingTest.cpp | 12 +++----
 3 files changed, 22 insertions(+), 25 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 045cbab221ac3..95a39d6ac3fc2 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -8147,6 +8147,8 @@ bool llvm::intrinsicPropagatesPoison(Intrinsic::ID IID) {
   case Intrinsic::roundeven:
   case Intrinsic::lrint:
   case Intrinsic::llrint:
+  case Intrinsic::fshl:
+  case Intrinsic::fshr:
     return true;
   default:
     return false;
diff --git a/llvm/test/Transforms/InstSimplify/call.ll b/llvm/test/Transforms/InstSimplify/call.ll
index de71af414c25d..cea597b4892ce 100644
--- a/llvm/test/Transforms/InstSimplify/call.ll
+++ b/llvm/test/Transforms/InstSimplify/call.ll
@@ -862,12 +862,10 @@ define i9 @fshr_shift_undef(i9 %x, i9 %y) {
   ret i9 %r
 }
 
-; If one of operands is poison, the result is poison
-; TODO: these should be poison
+; If one of the operands is poison, the result is poison
 define i8 @fshl_ops_poison(i8 %b, i8 %shamt) {
 ; CHECK-LABEL: @fshl_ops_poison(
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.fshl.i8(i8 poison, i8 [[B:%.*]], i8 [[SHAMT:%.*]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 poison
 ;
   %r = call i8 @llvm.fshl.i8(i8 poison, i8 %b, i8 %shamt)
   ret i8 %r
@@ -875,7 +873,7 @@ define i8 @fshl_ops_poison(i8 %b, i8 %shamt) {
 
 define i8 @fshl_ops_poison2(i8 %shamt) {
 ; CHECK-LABEL: @fshl_ops_poison2(
-; CHECK-NEXT:    ret i8 undef
+; CHECK-NEXT:    ret i8 poison
 ;
   %r = call i8 @llvm.fshl.i8(i8 poison, i8 undef, i8 %shamt)
   ret i8 %r
@@ -883,8 +881,7 @@ define i8 @fshl_ops_poison2(i8 %shamt) {
 
 define i8 @fshl_ops_poison3(i8 %a, i8 %shamt) {
 ; CHECK-LABEL: @fshl_ops_poison3(
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.fshl.i8(i8 [[A:%.*]], i8 poison, i8 [[SHAMT:%.*]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 poison
 ;
   %r = call i8 @llvm.fshl.i8(i8 %a, i8 poison, i8 %shamt)
   ret i8 %r
@@ -892,7 +889,7 @@ define i8 @fshl_ops_poison3(i8 %a, i8 %shamt) {
 
 define i8 @fshl_ops_poison4(i8 %shamt) {
 ; CHECK-LABEL: @fshl_ops_poison4(
-; CHECK-NEXT:    ret i8 undef
+; CHECK-NEXT:    ret i8 poison
 ;
   %r = call i8 @llvm.fshl.i8(i8 undef, i8 poison, i8 %shamt)
   ret i8 %r
@@ -900,7 +897,7 @@ define i8 @fshl_ops_poison4(i8 %shamt) {
 
 define i8 @fshl_ops_poison5(i8 %a, i8 %b) {
 ; CHECK-LABEL: @fshl_ops_poison5(
-; CHECK-NEXT:    ret i8 [[A:%.*]]
+; CHECK-NEXT:    ret i8 poison
 ;
   %r = call i8 @llvm.fshl.i8(i8 %a, i8 %b, i8 poison)
   ret i8 %r
@@ -908,7 +905,7 @@ define i8 @fshl_ops_poison5(i8 %a, i8 %b) {
 
 define i8 @fshl_ops_poison6() {
 ; CHECK-LABEL: @fshl_ops_poison6(
-; CHECK-NEXT:    ret i8 undef
+; CHECK-NEXT:    ret i8 poison
 ;
   %r = call i8 @llvm.fshl.i8(i8 undef, i8 undef, i8 poison)
   ret i8 %r
@@ -916,8 +913,7 @@ define i8 @fshl_ops_poison6() {
 
 define i9 @fshr_ops_poison(i9 %b, i9 %shamt) {
 ; CHECK-LABEL: @fshr_ops_poison(
-; CHECK-NEXT:    [[R:%.*]] = call i9 @llvm.fshr.i9(i9 poison, i9 [[B:%.*]], i9 [[SHAMT:%.*]])
-; CHECK-NEXT:    ret i9 [[R]]
+; CHECK-NEXT:    ret i9 poison
 ;
   %r = call i9 @llvm.fshr.i9(i9 poison, i9 %b, i9 %shamt)
   ret i9 %r
@@ -925,7 +921,7 @@ define i9 @fshr_ops_poison(i9 %b, i9 %shamt) {
 
 define i9 @fshr_ops_poison2(i9 %shamt) {
 ; CHECK-LABEL: @fshr_ops_poison2(
-; CHECK-NEXT:    ret i9 undef
+; CHECK-NEXT:    ret i9 poison
 ;
   %r = call i9 @llvm.fshr.i9(i9 poison, i9 undef, i9 %shamt)
   ret i9 %r
@@ -933,8 +929,7 @@ define i9 @fshr_ops_poison2(i9 %shamt) {
 
 define i9 @fshr_ops_poison3(i9 %a, i9 %shamt) {
 ; CHECK-LABEL: @fshr_ops_poison3(
-; CHECK-NEXT:    [[R:%.*]] = call i9 @llvm.fshr.i9(i9 [[A:%.*]], i9 poison, i9 [[SHAMT:%.*]])
-; CHECK-NEXT:    ret i9 [[R]]
+; CHECK-NEXT:    ret i9 poison
 ;
   %r = call i9 @llvm.fshr.i9(i9 %a, i9 poison, i9 %shamt)
   ret i9 %r
@@ -942,7 +937,7 @@ define i9 @fshr_ops_poison3(i9 %a, i9 %shamt) {
 
 define i9 @fshr_ops_poison4(i9 %shamt) {
 ; CHECK-LABEL: @fshr_ops_poison4(
-; CHECK-NEXT:    ret i9 undef
+; CHECK-NEXT:    ret i9 poison
 ;
   %r = call i9 @llvm.fshr.i9(i9 undef, i9 poison, i9 %shamt)
   ret i9 %r
@@ -950,7 +945,7 @@ define i9 @fshr_ops_poison4(i9 %shamt) {
 
 define i9 @fshr_ops_poison5(i9 %a, i9 %b) {
 ; CHECK-LABEL: @fshr_ops_poison5(
-; CHECK-NEXT:    ret i9 [[B:%.*]]
+; CHECK-NEXT:    ret i9 poison
 ;
   %r = call i9 @llvm.fshr.i9(i9 %a, i9 %b, i9 poison)
   ret i9 %r
@@ -958,7 +953,7 @@ define i9 @fshr_ops_poison5(i9 %a, i9 %b) {
 
 define i9 @fshr_ops_poison6() {
 ; CHECK-LABEL: @fshr_ops_poison6(
-; CHECK-NEXT:    ret i9 undef
+; CHECK-NEXT:    ret i9 poison
 ;
   %r = call i9 @llvm.fshr.i9(i9 undef, i9 undef, i9 poison)
   ret i9 %r
@@ -1379,7 +1374,7 @@ declare float @fmaxf(float, float)
 
 define float @nobuiltin_fmax() {
 ; CHECK-LABEL: @nobuiltin_fmax(
-; CHECK-NEXT:    [[M:%.*]] = call float @fmaxf(float 0.000000e+00, float 1.000000e+00) #[[ATTR3:[0-9]+]]
+; CHECK-NEXT:    [[M:%.*]] = call float @fmaxf(float 0.000000e+00, float 1.000000e+00) #[[ATTR4:[0-9]+]]
 ; CHECK-NEXT:    [[R:%.*]] = call float @llvm.fabs.f32(float [[M]])
 ; CHECK-NEXT:    ret float [[R]]
 ;
diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp
index 89a0faefc5988..4171e383e1bf1 100644
--- a/llvm/unittests/Analysis/ValueTrackingTest.cpp
+++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp
@@ -905,12 +905,12 @@ TEST(ValueTracking, propagatesPoison) {
       {true, "call i32 @llvm.umin.i32(i32 %x, i32 %y)", 0},
       {true, "call i32 @llvm.bitreverse.i32(i32 %x)", 0},
       {true, "call i32 @llvm.bswap.i32(i32 %x)", 0},
-      {false, "call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 %shamt)", 0},
-      {false, "call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 %shamt)", 1},
-      {false, "call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 %shamt)", 2},
-      {false, "call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 %shamt)", 0},
-      {false, "call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 %shamt)", 1},
-      {false, "call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 %shamt)", 2},
+      {true, "call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 %shamt)", 0},
+      {true, "call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 %shamt)", 1},
+      {true, "call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 %shamt)", 2},
+      {true, "call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 %shamt)", 0},
+      {true, "call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 %shamt)", 1},
+      {true, "call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 %shamt)", 2},
       {true, "call float @llvm.sqrt.f32(float %fx)", 0},
       {true, "call float @llvm.powi.f32.i32(float %fx, i32 %x)", 0},
       {true, "call float @llvm.sin.f32(float %fx)", 0},



More information about the llvm-commits mailing list