[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