[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