[llvm-branch-commits] [llvm] [InstCombine] Fold fpto[su]i of llvm.trunc (PR #231414)
Harrison Hao via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Oct 13 05:55:41 PDT 2026
https://github.com/harrisonGPU updated https://github.com/llvm/llvm-project/pull/231414
>From 1f6d91a80f1c4f56eadf107fa929b39d372eb29b Mon Sep 17 00:00:00 2001
From: Harrison Hao <tsworld1314 at gmail.com>
Date: Tue, 13 Oct 2026 16:13:30 +0800
Subject: [PATCH 1/3] [InstCombine] Fold fpto[su]i of llvm.trunc
fptoui and fptosi already round toward zero, so a preceding llvm.trunc
is redundant and the conversion can take the untruncated value. NaN,
infinity, and out of range inputs produce poison in both forms.
```llvm
%t = call float @llvm.trunc.f32(float %x)
%r = fptosi float %t to i32
-->
%r = fptosi float %x to i32
```
The trunc may have other users; only the conversion operand is replaced.
---
.../Transforms/InstCombine/InstCombineCasts.cpp | 5 +++++
llvm/test/Transforms/InstCombine/fpcast.ll | 16 ++++++----------
2 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index c217b59be9ea08..9c0c9cbc82f638 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -2592,6 +2592,11 @@ static Instruction *foldFPtoI(Instruction &FI, InstCombiner &IC) {
if (FPClass.isKnownNever(Mask))
return IC.replaceInstUsesWith(FI, ConstantInt::getNullValue(FI.getType()));
+ // fpto{u/s}i (trunc X) --> fpto{u/s}i X
+ Value *Src = nullptr;
+ if (match(FI.getOperand(0), m_Intrinsic<Intrinsic::trunc>(m_Value(Src))))
+ return IC.replaceOperand(FI, 0, Src);
+
// fpto{u/s}i (fdiv ({u/s}itofp X to F), C_fp) --> {u/s}div X, C
//
// F has precision p (significand bits incl. hidden bit); C_fp is the exact FP
diff --git a/llvm/test/Transforms/InstCombine/fpcast.ll b/llvm/test/Transforms/InstCombine/fpcast.ll
index 715c7eceb9da8a..4e6eb207e97d19 100644
--- a/llvm/test/Transforms/InstCombine/fpcast.ll
+++ b/llvm/test/Transforms/InstCombine/fpcast.ll
@@ -798,8 +798,7 @@ define <4 x i32> @neg_fptoui_sat_fptrunc(<4 x double> %a) {
define i32 @fptoui_trunc(float %x) {
; CHECK-LABEL: @fptoui_trunc(
-; CHECK-NEXT: [[T:%.*]] = call float @llvm.trunc.f32(float [[X:%.*]])
-; CHECK-NEXT: [[R:%.*]] = fptoui float [[T]] to i32
+; CHECK-NEXT: [[R:%.*]] = fptoui float [[T:%.*]] to i32
; CHECK-NEXT: ret i32 [[R]]
;
%t = call float @llvm.trunc.f32(float %x)
@@ -809,8 +808,7 @@ define i32 @fptoui_trunc(float %x) {
define i32 @fptosi_trunc(float %x) {
; CHECK-LABEL: @fptosi_trunc(
-; CHECK-NEXT: [[T:%.*]] = call float @llvm.trunc.f32(float [[X:%.*]])
-; CHECK-NEXT: [[R:%.*]] = fptosi float [[T]] to i32
+; CHECK-NEXT: [[R:%.*]] = fptosi float [[T:%.*]] to i32
; CHECK-NEXT: ret i32 [[R]]
;
%t = call float @llvm.trunc.f32(float %x)
@@ -820,8 +818,7 @@ define i32 @fptosi_trunc(float %x) {
define <2 x i64> @fptoui_trunc_vec(<2 x double> %x) {
; CHECK-LABEL: @fptoui_trunc_vec(
-; CHECK-NEXT: [[T:%.*]] = call <2 x double> @llvm.trunc.v2f64(<2 x double> [[X:%.*]])
-; CHECK-NEXT: [[R:%.*]] = fptoui <2 x double> [[T]] to <2 x i64>
+; CHECK-NEXT: [[R:%.*]] = fptoui <2 x double> [[T:%.*]] to <2 x i64>
; CHECK-NEXT: ret <2 x i64> [[R]]
;
%t = call <2 x double> @llvm.trunc.v2f64(<2 x double> %x)
@@ -831,8 +828,7 @@ define <2 x i64> @fptoui_trunc_vec(<2 x double> %x) {
define <2 x i64> @fptosi_trunc_vec(<2 x double> %x) {
; CHECK-LABEL: @fptosi_trunc_vec(
-; CHECK-NEXT: [[T:%.*]] = call <2 x double> @llvm.trunc.v2f64(<2 x double> [[X:%.*]])
-; CHECK-NEXT: [[R:%.*]] = fptosi <2 x double> [[T]] to <2 x i64>
+; CHECK-NEXT: [[R:%.*]] = fptosi <2 x double> [[T:%.*]] to <2 x i64>
; CHECK-NEXT: ret <2 x i64> [[R]]
;
%t = call <2 x double> @llvm.trunc.v2f64(<2 x double> %x)
@@ -844,7 +840,7 @@ define i32 @fptoui_trunc_multi_use(float %x) {
; CHECK-LABEL: @fptoui_trunc_multi_use(
; CHECK-NEXT: [[T:%.*]] = call float @llvm.trunc.f32(float [[X:%.*]])
; CHECK-NEXT: call void @use(float [[T]])
-; CHECK-NEXT: [[R:%.*]] = fptoui float [[T]] to i32
+; CHECK-NEXT: [[R:%.*]] = fptoui float [[X]] to i32
; CHECK-NEXT: ret i32 [[R]]
;
%t = call float @llvm.trunc.f32(float %x)
@@ -857,7 +853,7 @@ define i32 @fptosi_trunc_multi_use(float %x) {
; CHECK-LABEL: @fptosi_trunc_multi_use(
; CHECK-NEXT: [[T:%.*]] = call float @llvm.trunc.f32(float [[X:%.*]])
; CHECK-NEXT: call void @use(float [[T]])
-; CHECK-NEXT: [[R:%.*]] = fptosi float [[T]] to i32
+; CHECK-NEXT: [[R:%.*]] = fptosi float [[X]] to i32
; CHECK-NEXT: ret i32 [[R]]
;
%t = call float @llvm.trunc.f32(float %x)
>From 71404b1d01ac861483a0ce2b37ecb16f8de56584 Mon Sep 17 00:00:00 2001
From: Harrison Hao <tsworld1314 at gmail.com>
Date: Tue, 13 Oct 2026 17:00:37 +0800
Subject: [PATCH 2/3] Update for comments
---
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | 2 +-
llvm/test/Transforms/InstCombine/fpcast.ll | 6 ++----
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index 9c0c9cbc82f638..775ff358f00bb8 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -2593,7 +2593,7 @@ static Instruction *foldFPtoI(Instruction &FI, InstCombiner &IC) {
return IC.replaceInstUsesWith(FI, ConstantInt::getNullValue(FI.getType()));
// fpto{u/s}i (trunc X) --> fpto{u/s}i X
- Value *Src = nullptr;
+ Value *Src;
if (match(FI.getOperand(0), m_Intrinsic<Intrinsic::trunc>(m_Value(Src))))
return IC.replaceOperand(FI, 0, Src);
diff --git a/llvm/test/Transforms/InstCombine/fpcast.ll b/llvm/test/Transforms/InstCombine/fpcast.ll
index 4e6eb207e97d19..b47bc1c5f648cf 100644
--- a/llvm/test/Transforms/InstCombine/fpcast.ll
+++ b/llvm/test/Transforms/InstCombine/fpcast.ll
@@ -864,8 +864,7 @@ define i32 @fptosi_trunc_multi_use(float %x) {
define i32 @fptoui_trunc_fmf(float %x) {
; CHECK-LABEL: @fptoui_trunc_fmf(
-; CHECK-NEXT: [[T:%.*]] = call nnan ninf nsz float @llvm.trunc.f32(float [[X:%.*]])
-; CHECK-NEXT: [[R:%.*]] = fptoui float [[T]] to i32
+; CHECK-NEXT: [[R:%.*]] = fptoui float [[T:%.*]] to i32
; CHECK-NEXT: ret i32 [[R]]
;
%t = call nnan ninf nsz float @llvm.trunc.f32(float %x)
@@ -875,8 +874,7 @@ define i32 @fptoui_trunc_fmf(float %x) {
define i32 @fptosi_trunc_fmf(float %x) {
; CHECK-LABEL: @fptosi_trunc_fmf(
-; CHECK-NEXT: [[T:%.*]] = call nnan ninf nsz float @llvm.trunc.f32(float [[X:%.*]])
-; CHECK-NEXT: [[R:%.*]] = fptosi float [[T]] to i32
+; CHECK-NEXT: [[R:%.*]] = fptosi float [[T:%.*]] to i32
; CHECK-NEXT: ret i32 [[R]]
;
%t = call nnan ninf nsz float @llvm.trunc.f32(float %x)
>From 777294565adaf69ce738258009f9613f3307b27b Mon Sep 17 00:00:00 2001
From: Harrison Hao <tsworld1314 at gmail.com>
Date: Tue, 13 Oct 2026 18:01:44 +0800
Subject: [PATCH 3/3] Fix lit test issue.
---
.../CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll
index 80c073c7b94d7e..ecc9bc6f75d772 100644
--- a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll
+++ b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll
@@ -5785,8 +5785,7 @@ define float @test_pow_f32__y_known_integral_trunc_ninf_use(float %x, float %y.a
define float @test_pow_afn_f32_nnan_ninf__y_known_integral_trunc(float %x, float %y.arg) {
; PRELINK-LABEL: define float @test_pow_afn_f32_nnan_ninf__y_known_integral_trunc
; PRELINK-SAME: (float [[X:%.*]], float [[Y_ARG:%.*]]) {
-; PRELINK-NEXT: [[Y:%.*]] = call float @llvm.trunc.f32(float [[Y_ARG]])
-; PRELINK-NEXT: [[TMP1:%.*]] = fptosi float [[Y]] to i32
+; PRELINK-NEXT: [[TMP1:%.*]] = fptosi float [[Y_ARG]] to i32
; PRELINK-NEXT: [[__FABS:%.*]] = call nnan ninf afn float @llvm.fabs.f32(float [[X]])
; PRELINK-NEXT: [[__LOG2:%.*]] = call nnan ninf afn float @llvm.log2.f32(float [[__FABS]])
; PRELINK-NEXT: [[POWNI2F:%.*]] = sitofp nnan ninf afn i32 [[TMP1]] to float
@@ -5801,12 +5800,12 @@ define float @test_pow_afn_f32_nnan_ninf__y_known_integral_trunc(float %x, float
;
; NOPRELINK-LABEL: define float @test_pow_afn_f32_nnan_ninf__y_known_integral_trunc
; NOPRELINK-SAME: (float [[X:%.*]], float [[Y_ARG:%.*]]) {
-; NOPRELINK-NEXT: [[Y:%.*]] = call float @llvm.trunc.f32(float [[Y_ARG]])
+; NOPRELINK-NEXT: [[Y:%.*]] = call nnan ninf float @llvm.trunc.f32(float [[Y_ARG]])
; NOPRELINK-NEXT: [[__FABS:%.*]] = call nnan ninf afn float @llvm.fabs.f32(float [[X]])
; NOPRELINK-NEXT: [[__LOG2:%.*]] = call nnan ninf afn float @llvm.log2.f32(float [[__FABS]])
; NOPRELINK-NEXT: [[__YLOGX:%.*]] = fmul nnan ninf afn float [[Y]], [[__LOG2]]
; NOPRELINK-NEXT: [[__EXP2:%.*]] = call nnan ninf afn nofpclass(nan ninf nzero nsub nnorm) float @llvm.exp2.f32(float [[__YLOGX]])
-; NOPRELINK-NEXT: [[__YTOU:%.*]] = fptosi float [[Y]] to i32
+; NOPRELINK-NEXT: [[__YTOU:%.*]] = fptosi float [[Y_ARG]] to i32
; NOPRELINK-NEXT: [[__YEVEN:%.*]] = shl i32 [[__YTOU]], 31
; NOPRELINK-NEXT: [[TMP1:%.*]] = bitcast float [[X]] to i32
; NOPRELINK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP1]]
@@ -5822,8 +5821,7 @@ define float @test_pow_afn_f32_nnan_ninf__y_known_integral_trunc(float %x, float
define float @test_pow_afn_f32__y_known_integral_trunc(float %x, float nofpclass(inf nan) %y.arg) {
; PRELINK-LABEL: define float @test_pow_afn_f32__y_known_integral_trunc
; PRELINK-SAME: (float [[X:%.*]], float nofpclass(nan inf) [[Y_ARG:%.*]]) {
-; PRELINK-NEXT: [[Y:%.*]] = call float @llvm.trunc.f32(float [[Y_ARG]])
-; PRELINK-NEXT: [[TMP1:%.*]] = fptosi float [[Y]] to i32
+; PRELINK-NEXT: [[TMP1:%.*]] = fptosi float [[Y_ARG]] to i32
; PRELINK-NEXT: [[POW:%.*]] = tail call afn float @_Z11__pown_fastfi(float [[X]], i32 [[TMP1]])
; PRELINK-NEXT: ret float [[POW]]
;
@@ -5911,8 +5909,7 @@ define float @test_pow_f32__y_known_integral_ceil(float %x, float nofpclass(inf
define float @test_pow_f32__y_known_integral_trunc(float %x, float nofpclass(inf nan) %y.arg) {
; PRELINK-LABEL: define float @test_pow_f32__y_known_integral_trunc
; PRELINK-SAME: (float [[X:%.*]], float nofpclass(nan inf) [[Y_ARG:%.*]]) {
-; PRELINK-NEXT: [[Y:%.*]] = call float @llvm.trunc.f32(float [[Y_ARG]])
-; PRELINK-NEXT: [[TMP1:%.*]] = fptosi float [[Y]] to i32
+; PRELINK-NEXT: [[TMP1:%.*]] = fptosi float [[Y_ARG]] to i32
; PRELINK-NEXT: [[POW:%.*]] = tail call float @_Z4pownfi(float [[X]], i32 [[TMP1]])
; PRELINK-NEXT: ret float [[POW]]
;
More information about the llvm-branch-commits
mailing list