[llvm] [InstCombine] Fold `fpto{s|u}i non-norm` to zero (PR #85569)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 19 01:28:29 PDT 2024


https://github.com/dtcxzyw updated https://github.com/llvm/llvm-project/pull/85569

>From b291c4919653e8f7aac2a6ec1f6194027e8ee2f2 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Tue, 19 Mar 2024 16:13:26 +0800
Subject: [PATCH 1/2] [InstCombine] Add pre-commit tests. NFC.

---
 llvm/test/Transforms/InstCombine/fpcast.ll | 94 ++++++++++++++++++++++
 1 file changed, 94 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/fpcast.ll b/llvm/test/Transforms/InstCombine/fpcast.ll
index 88ca556f4d8f8b..7a5e511f4e428d 100644
--- a/llvm/test/Transforms/InstCombine/fpcast.ll
+++ b/llvm/test/Transforms/InstCombine/fpcast.ll
@@ -347,3 +347,97 @@ define double @masked_uint_to_fpext3(i32 %x) {
   %r = fpext float %f to double
   ret double %r
 }
+
+define i32 @fptosi_nonnorm(float nofpclass(norm) %x) {
+; CHECK-LABEL: @fptosi_nonnorm(
+; CHECK-NEXT:    [[RET:%.*]] = fptosi float [[X:%.*]] to i32
+; CHECK-NEXT:    ret i32 [[RET]]
+;
+  %ret = fptosi float %x to i32
+  ret i32 %ret
+}
+
+define i32 @fptoui_nonnorm(float nofpclass(pnorm) %x) {
+; CHECK-LABEL: @fptoui_nonnorm(
+; CHECK-NEXT:    [[RET:%.*]] = fptoui float [[X:%.*]] to i32
+; CHECK-NEXT:    ret i32 [[RET]]
+;
+  %ret = fptoui float %x to i32
+  ret i32 %ret
+}
+
+define i32 @fptosi_nonnnorm(float nofpclass(nnorm) %x) {
+; CHECK-LABEL: @fptosi_nonnnorm(
+; CHECK-NEXT:    [[RET:%.*]] = fptosi float [[X:%.*]] to i32
+; CHECK-NEXT:    ret i32 [[RET]]
+;
+  %ret = fptosi float %x to i32
+  ret i32 %ret
+}
+
+define i32 @fptoui_nonnnorm(float nofpclass(nnorm) %x) {
+; CHECK-LABEL: @fptoui_nonnnorm(
+; CHECK-NEXT:    [[RET:%.*]] = fptoui float [[X:%.*]] to i32
+; CHECK-NEXT:    ret i32 [[RET]]
+;
+  %ret = fptoui float %x to i32
+  ret i32 %ret
+}
+
+define i32 @fptosi_nonnorm_copysign(float %x) {
+; CHECK-LABEL: @fptosi_nonnorm_copysign(
+; CHECK-NEXT:    [[VAL:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[X:%.*]])
+; CHECK-NEXT:    [[RET:%.*]] = fptosi float [[VAL]] to i32
+; CHECK-NEXT:    ret i32 [[RET]]
+;
+  %val = call float @llvm.copysign.f32(float 0.0, float %x)
+  %ret = fptosi float %val to i32
+  ret i32 %ret
+}
+
+define <2 x i32> @fptosi_nonnorm_copysign_vec(<2 x float> %x) {
+; CHECK-LABEL: @fptosi_nonnorm_copysign_vec(
+; CHECK-NEXT:    [[VAL:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> zeroinitializer, <2 x float> [[X:%.*]])
+; CHECK-NEXT:    [[RET:%.*]] = fptosi <2 x float> [[VAL]] to <2 x i32>
+; CHECK-NEXT:    ret <2 x i32> [[RET]]
+;
+  %val = call <2 x float> @llvm.copysign.v2f32(<2 x float> zeroinitializer, <2 x float> %x)
+  %ret = fptosi <2 x float> %val to <2 x i32>
+  ret <2 x i32> %ret
+}
+
+define i32 @fptosi_nonnorm_fmul(float %x) {
+; CHECK-LABEL: @fptosi_nonnorm_fmul(
+; CHECK-NEXT:    [[SEL:%.*]] = fmul float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[RET:%.*]] = fptosi float [[SEL]] to i32
+; CHECK-NEXT:    ret i32 [[RET]]
+;
+  %sel = fmul float %x, 0.000000e+00
+  %ret = fptosi float %sel to i32
+  ret i32 %ret
+}
+
+define i32 @fptosi_select(i1 %cond) {
+; CHECK-LABEL: @fptosi_select(
+; CHECK-NEXT:    [[RET:%.*]] = select i1 [[COND:%.*]], i32 1, i32 -1
+; CHECK-NEXT:    ret i32 [[RET]]
+;
+  %sel = select i1 %cond, float 1.0, float -1.0
+  %ret = fptosi float %sel to i32
+  ret i32 %ret
+}
+
+define i32 @mul_pos_zero_convert(i32 %a) {
+; CHECK-LABEL: @mul_pos_zero_convert(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[FP:%.*]] = sitofp i32 [[A:%.*]] to float
+; CHECK-NEXT:    [[RET:%.*]] = fmul float [[FP]], 0.000000e+00
+; CHECK-NEXT:    [[CONV:%.*]] = fptosi float [[RET]] to i32
+; CHECK-NEXT:    ret i32 [[CONV]]
+;
+entry:
+  %fp = sitofp i32 %a to float
+  %ret = fmul float %fp, 0.000000e+00
+  %conv = fptosi float %ret to i32
+  ret i32 %conv
+}

>From 442fe3338f6fd3d2a77a09603651d5326bbed816 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Tue, 19 Mar 2024 16:18:40 +0800
Subject: [PATCH 2/2] [InstCombine] Fold `fpto{s|u}i non-norm` to zero

---
 .../InstCombine/InstCombineCasts.cpp          | 19 +++++++++++++++++++
 llvm/test/Transforms/InstCombine/fpcast.ll    | 14 ++++----------
 2 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index 381cd858d26293..b19da1e075819c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -1923,10 +1923,26 @@ Instruction *InstCombinerImpl::foldItoFPtoI(CastInst &FI) {
   return replaceInstUsesWith(FI, X);
 }
 
+static Instruction *foldFPtoI(Instruction &FI, InstCombiner &IC) {
+  // fpto{u/s}i non-norm --> 0
+  FPClassTest Mask =
+      FI.getOpcode() == Instruction::FPToUI ? fcPosNormal : fcNormal;
+  KnownFPClass FPClass =
+      computeKnownFPClass(FI.getOperand(0), Mask, /*Depth=*/0,
+                          IC.getSimplifyQuery().getWithInstruction(&FI));
+  if (FPClass.isKnownNever(Mask))
+    return IC.replaceInstUsesWith(FI, ConstantInt::getNullValue(FI.getType()));
+
+  return nullptr;
+}
+
 Instruction *InstCombinerImpl::visitFPToUI(FPToUIInst &FI) {
   if (Instruction *I = foldItoFPtoI(FI))
     return I;
 
+  if (Instruction *I = foldFPtoI(FI, *this))
+    return I;
+
   return commonCastTransforms(FI);
 }
 
@@ -1934,6 +1950,9 @@ Instruction *InstCombinerImpl::visitFPToSI(FPToSIInst &FI) {
   if (Instruction *I = foldItoFPtoI(FI))
     return I;
 
+  if (Instruction *I = foldFPtoI(FI, *this))
+    return I;
+
   return commonCastTransforms(FI);
 }
 
diff --git a/llvm/test/Transforms/InstCombine/fpcast.ll b/llvm/test/Transforms/InstCombine/fpcast.ll
index 7a5e511f4e428d..1f0bfbc40ac1b6 100644
--- a/llvm/test/Transforms/InstCombine/fpcast.ll
+++ b/llvm/test/Transforms/InstCombine/fpcast.ll
@@ -350,8 +350,7 @@ define double @masked_uint_to_fpext3(i32 %x) {
 
 define i32 @fptosi_nonnorm(float nofpclass(norm) %x) {
 ; CHECK-LABEL: @fptosi_nonnorm(
-; CHECK-NEXT:    [[RET:%.*]] = fptosi float [[X:%.*]] to i32
-; CHECK-NEXT:    ret i32 [[RET]]
+; CHECK-NEXT:    ret i32 0
 ;
   %ret = fptosi float %x to i32
   ret i32 %ret
@@ -359,8 +358,7 @@ define i32 @fptosi_nonnorm(float nofpclass(norm) %x) {
 
 define i32 @fptoui_nonnorm(float nofpclass(pnorm) %x) {
 ; CHECK-LABEL: @fptoui_nonnorm(
-; CHECK-NEXT:    [[RET:%.*]] = fptoui float [[X:%.*]] to i32
-; CHECK-NEXT:    ret i32 [[RET]]
+; CHECK-NEXT:    ret i32 0
 ;
   %ret = fptoui float %x to i32
   ret i32 %ret
@@ -386,9 +384,7 @@ define i32 @fptoui_nonnnorm(float nofpclass(nnorm) %x) {
 
 define i32 @fptosi_nonnorm_copysign(float %x) {
 ; CHECK-LABEL: @fptosi_nonnorm_copysign(
-; CHECK-NEXT:    [[VAL:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[X:%.*]])
-; CHECK-NEXT:    [[RET:%.*]] = fptosi float [[VAL]] to i32
-; CHECK-NEXT:    ret i32 [[RET]]
+; CHECK-NEXT:    ret i32 0
 ;
   %val = call float @llvm.copysign.f32(float 0.0, float %x)
   %ret = fptosi float %val to i32
@@ -397,9 +393,7 @@ define i32 @fptosi_nonnorm_copysign(float %x) {
 
 define <2 x i32> @fptosi_nonnorm_copysign_vec(<2 x float> %x) {
 ; CHECK-LABEL: @fptosi_nonnorm_copysign_vec(
-; CHECK-NEXT:    [[VAL:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> zeroinitializer, <2 x float> [[X:%.*]])
-; CHECK-NEXT:    [[RET:%.*]] = fptosi <2 x float> [[VAL]] to <2 x i32>
-; CHECK-NEXT:    ret <2 x i32> [[RET]]
+; CHECK-NEXT:    ret <2 x i32> zeroinitializer
 ;
   %val = call <2 x float> @llvm.copysign.v2f32(<2 x float> zeroinitializer, <2 x float> %x)
   %ret = fptosi <2 x float> %val to <2 x i32>



More information about the llvm-commits mailing list