-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[InstCombine] Fix frexp(frexp(x)) -> frexp(x)
fold
#138837
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-backend-amdgpu @llvm/pr-subscribers-llvm-analysis Author: Iris Shi (el-ev) ChangesFixes #138819 When frexp is applied twice, the second result should be zero. Full diff: https://github.com/llvm/llvm-project/pull/138837.diff 3 Files Affected:
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 5a2943de9066e..85e3be9cc45c3 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -6377,15 +6377,6 @@ static Value *simplifyUnaryIntrinsic(Function *F, Value *Op0,
if (isSplatValue(Op0))
return Op0;
break;
- case Intrinsic::frexp: {
- // Frexp is idempotent with the added complication of the struct return.
- if (match(Op0, m_ExtractValue<0>(m_Value(X)))) {
- if (match(X, m_Intrinsic<Intrinsic::frexp>(m_Value())))
- return X;
- }
-
- break;
- }
default:
break;
}
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 3e78b20e41f0d..624c97cf39de3 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3799,6 +3799,18 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
}
break;
}
+ case Intrinsic::frexp: {
+ Value *X;
+ // Frexp is idempotent with the added complication of the struct return.
+ if (match(II->getArgOperand(0), m_ExtractValue<0>(m_Value(X)))) {
+ if (match(X, m_Intrinsic<Intrinsic::frexp>(m_Value()))) {
+ X = Builder.CreateInsertValue(
+ X, ConstantInt::get(II->getType()->getStructElementType(1), 0), 1);
+ return replaceInstUsesWith(*II, X);
+ }
+ }
+ break;
+ }
default: {
// Handle target specific intrinsics
std::optional<Instruction *> V = targetInstCombineIntrinsic(*II);
diff --git a/llvm/test/Transforms/InstSimplify/frexp.ll b/llvm/test/Transforms/InstCombine/frexp.ll
similarity index 96%
rename from llvm/test/Transforms/InstSimplify/frexp.ll
rename to llvm/test/Transforms/InstCombine/frexp.ll
index 34cfce92bac43..6541f0d77a093 100644
--- a/llvm/test/Transforms/InstSimplify/frexp.ll
+++ b/llvm/test/Transforms/InstCombine/frexp.ll
@@ -1,5 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
-; RUN: opt -S -passes=instsimplify %s | FileCheck %s
+; RUN: opt -S -passes=instcombine %s | FileCheck %s
declare { float, i32 } @llvm.frexp.f32.i32(float)
declare { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float>)
@@ -12,7 +12,8 @@ define { float, i32 } @frexp_frexp(float %x) {
; CHECK-LABEL: define { float, i32 } @frexp_frexp(
; CHECK-SAME: float [[X:%.*]]) {
; CHECK-NEXT: [[FREXP0:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
-; CHECK-NEXT: ret { float, i32 } [[FREXP0]]
+; CHECK-NEXT: [[FREXP1:%.*]] = insertvalue { float, i32 } [[FREXP0]], i32 0, 1
+; CHECK-NEXT: ret { float, i32 } [[FREXP1]]
;
%frexp0 = call { float, i32 } @llvm.frexp.f32.i32(float %x)
%frexp0.0 = extractvalue { float, i32 } %frexp0, 0
@@ -24,7 +25,8 @@ define { <2 x float>, <2 x i32> } @frexp_frexp_vector(<2 x float> %x) {
; CHECK-LABEL: define { <2 x float>, <2 x i32> } @frexp_frexp_vector(
; CHECK-SAME: <2 x float> [[X:%.*]]) {
; CHECK-NEXT: [[FREXP0:%.*]] = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> [[X]])
-; CHECK-NEXT: ret { <2 x float>, <2 x i32> } [[FREXP0]]
+; CHECK-NEXT: [[FREXP1:%.*]] = insertvalue { <2 x float>, <2 x i32> } [[FREXP0]], <2 x i32> zeroinitializer, 1
+; CHECK-NEXT: ret { <2 x float>, <2 x i32> } [[FREXP1]]
;
%frexp0 = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> %x)
%frexp0.0 = extractvalue { <2 x float>, <2 x i32> } %frexp0, 0
@@ -47,7 +49,8 @@ define { <vscale x 2 x float>, <vscale x 2 x i32> } @frexp_frexp_scalable_vector
; CHECK-LABEL: define { <vscale x 2 x float>, <vscale x 2 x i32> } @frexp_frexp_scalable_vector(
; CHECK-SAME: <vscale x 2 x float> [[X:%.*]]) {
; CHECK-NEXT: [[FREXP0:%.*]] = call { <vscale x 2 x float>, <vscale x 2 x i32> } @llvm.frexp.nxv2f32.nxv2i32(<vscale x 2 x float> [[X]])
-; CHECK-NEXT: ret { <vscale x 2 x float>, <vscale x 2 x i32> } [[FREXP0]]
+; CHECK-NEXT: [[FREXP1:%.*]] = insertvalue { <vscale x 2 x float>, <vscale x 2 x i32> } [[FREXP0]], <vscale x 2 x i32> zeroinitializer, 1
+; CHECK-NEXT: ret { <vscale x 2 x float>, <vscale x 2 x i32> } [[FREXP1]]
;
%frexp0 = call { <vscale x 2 x float>, <vscale x 2 x i32> } @llvm.frexp.nxv2f32.nxv2i32(<vscale x 2 x float> %x)
%frexp0.0 = extractvalue { <vscale x 2 x float>, <vscale x 2 x i32> } %frexp0, 0
|
You can test this locally with the following command:git diff -U0 --pickaxe-regex -S '([^a-zA-Z0-9#_-]undef[^a-zA-Z0-9_-]|UndefValue::get)' 'HEAD~1' HEAD llvm/lib/Analysis/InstructionSimplify.cpp llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp llvm/test/CodeGen/AMDGPU/frexp-constant-fold.ll llvm/test/Transforms/InstCombine/frexp.ll The following files introduce new uses of undef:
Undef is now deprecated and should only be used in the rare cases where no replacement is possible. For example, a load of uninitialized memory yields In tests, avoid using For example, this is considered a bad practice: define void @fn() {
...
br i1 undef, ...
} Please use the following instead: define void @fn(i1 %cond) {
...
br i1 %cond, ...
} Please refer to the Undefined Behavior Manual for more information. |
Fixes #138819
When frexp is applied twice, the second result should be zero.