[llvm] [InstSimplify] Fold expression using basic properties of floor and ceiling function (PR #107107)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 3 06:34:12 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-analysis
Author: None (c8ef)
<details>
<summary>Changes</summary>
alive2: https://alive2.llvm.org/ce/z/giSGaj
---
Full diff: https://github.com/llvm/llvm-project/pull/107107.diff
2 Files Affected:
- (modified) llvm/lib/Analysis/InstructionSimplify.cpp (+33-5)
- (added) llvm/test/Transforms/InstSimplify/fp-floor-ceil.ll (+114)
``````````diff
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 32a9f1ab34fb3f..e67a2875733416 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4130,12 +4130,9 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
//
// This catches the 2 variable input case, constants are handled below as a
// class-like compare.
+ KnownFPClass LHSClass = computeKnownFPClass(LHS, fcAllFlags, /*Depth=*/0, Q);
+ KnownFPClass RHSClass = computeKnownFPClass(RHS, fcAllFlags, /*Depth=*/0, Q);
if (Pred == FCmpInst::FCMP_ORD || Pred == FCmpInst::FCMP_UNO) {
- KnownFPClass RHSClass =
- computeKnownFPClass(RHS, fcAllFlags, /*Depth=*/0, Q);
- KnownFPClass LHSClass =
- computeKnownFPClass(LHS, fcAllFlags, /*Depth=*/0, Q);
-
if (FMF.noNaNs() ||
(RHSClass.isKnownNeverNaN() && LHSClass.isKnownNeverNaN()))
return ConstantInt::get(RetTy, Pred == FCmpInst::FCMP_ORD);
@@ -4143,6 +4140,37 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
if (RHSClass.isKnownAlwaysNaN() || LHSClass.isKnownAlwaysNaN())
return ConstantInt::get(RetTy, Pred == CmpInst::FCMP_UNO);
}
+ // floor(x) <= x --> true; x <= ceil(x) --> true
+ if (LHSClass.isKnownNeverNaN() &&
+ match(LHS, m_Intrinsic<Intrinsic::floor>(m_Specific(RHS))) ||
+ RHSClass.isKnownNeverNaN() &&
+ match(RHS, m_Intrinsic<Intrinsic::ceil>(m_Specific(LHS)))) {
+ switch (Pred) {
+ case FCmpInst::FCMP_OLE:
+ case FCmpInst::FCMP_ULE:
+ return getTrue(RetTy);
+ case FCmpInst::FCMP_OGT:
+ case FCmpInst::FCMP_UGT:
+ return getFalse(RetTy);
+ default:
+ break;
+ }
+ }
+ if (RHSClass.isKnownNeverNaN() &&
+ match(RHS, m_Intrinsic<Intrinsic::floor>(m_Specific(LHS))) ||
+ LHSClass.isKnownNeverNaN() &&
+ match(LHS, m_Intrinsic<Intrinsic::ceil>(m_Specific(RHS)))) {
+ switch (Pred) {
+ case FCmpInst::FCMP_OGE:
+ case FCmpInst::FCMP_UGE:
+ return getTrue(RetTy);
+ case FCmpInst::FCMP_OLT:
+ case FCmpInst::FCMP_ULT:
+ return getFalse(RetTy);
+ default:
+ break;
+ }
+ }
const APFloat *C = nullptr;
match(RHS, m_APFloatAllowPoison(C));
diff --git a/llvm/test/Transforms/InstSimplify/fp-floor-ceil.ll b/llvm/test/Transforms/InstSimplify/fp-floor-ceil.ll
new file mode 100644
index 00000000000000..fe78656b014ae0
--- /dev/null
+++ b/llvm/test/Transforms/InstSimplify/fp-floor-ceil.ll
@@ -0,0 +1,114 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
+
+define i1 @x_floor_ole(float %0) {
+; CHECK-LABEL: @x_floor_ole(
+; CHECK-NEXT: ret i1 true
+;
+ %2 = call nnan float @llvm.floor.f32(float %0)
+ %3 = fcmp ole float %2, %0
+ ret i1 %3
+}
+
+define i1 @x_floor_ule(float %0) {
+; CHECK-LABEL: @x_floor_ule(
+; CHECK-NEXT: ret i1 true
+;
+ %2 = call nnan float @llvm.floor.f32(float %0)
+ %3 = fcmp ule float %2, %0
+ ret i1 %3
+}
+
+define i1 @x_floor_ogt(float %0) {
+; CHECK-LABEL: @x_floor_ogt(
+; CHECK-NEXT: ret i1 false
+;
+ %2 = call nnan float @llvm.floor.f32(float %0)
+ %3 = fcmp ogt float %2, %0
+ ret i1 %3
+}
+
+define i1 @x_floor_ugt(float %0) {
+; CHECK-LABEL: @x_floor_ugt(
+; CHECK-NEXT: ret i1 false
+;
+ %2 = call nnan float @llvm.floor.f32(float %0)
+ %3 = fcmp ugt float %2, %0
+ ret i1 %3
+}
+
+define i1 @x_floor_ueq(float %0) {
+; CHECK-LABEL: @x_floor_ueq(
+; CHECK-NEXT: [[TMP2:%.*]] = call nnan float @llvm.floor.f32(float [[TMP0:%.*]])
+; CHECK-NEXT: [[TMP3:%.*]] = fcmp ueq float [[TMP2]], [[TMP0]]
+; CHECK-NEXT: ret i1 [[TMP3]]
+;
+ %2 = call nnan float @llvm.floor.f32(float %0)
+ %3 = fcmp ueq float %2, %0
+ ret i1 %3
+}
+
+define <2 x i1> @x_floor_ugt_vec(<2 x float> %0) {
+; CHECK-LABEL: @x_floor_ugt_vec(
+; CHECK-NEXT: ret <2 x i1> zeroinitializer
+;
+ %2 = call nnan <2 x float> @llvm.floor.v2f32(<2 x float> %0)
+ %3 = fcmp ugt <2 x float> %2, %0
+ ret <2 x i1> %3
+}
+
+define i1 @x_ceil_ole(float %0) {
+; CHECK-LABEL: @x_ceil_ole(
+; CHECK-NEXT: ret i1 false
+;
+ %2 = call nnan float @llvm.ceil.f32(float %0)
+ %3 = fcmp olt float %2, %0
+ ret i1 %3
+}
+
+define i1 @x_ceil_ule(float %0) {
+; CHECK-LABEL: @x_ceil_ule(
+; CHECK-NEXT: ret i1 false
+;
+ %2 = call nnan float @llvm.ceil.f32(float %0)
+ %3 = fcmp ult float %2, %0
+ ret i1 %3
+}
+
+define i1 @x_ceil_ogt(float %0) {
+; CHECK-LABEL: @x_ceil_ogt(
+; CHECK-NEXT: ret i1 true
+;
+ %2 = call nnan float @llvm.ceil.f32(float %0)
+ %3 = fcmp oge float %2, %0
+ ret i1 %3
+}
+
+define i1 @x_ceil_ugt(float %0) {
+; CHECK-LABEL: @x_ceil_ugt(
+; CHECK-NEXT: ret i1 true
+;
+ %2 = call nnan float @llvm.ceil.f32(float %0)
+ %3 = fcmp uge float %2, %0
+ ret i1 %3
+}
+
+define i1 @x_ceil_ueq(float %0) {
+; CHECK-LABEL: @x_ceil_ueq(
+; CHECK-NEXT: [[TMP2:%.*]] = call nnan float @llvm.ceil.f32(float [[TMP0:%.*]])
+; CHECK-NEXT: [[TMP3:%.*]] = fcmp ueq float [[TMP2]], [[TMP0]]
+; CHECK-NEXT: ret i1 [[TMP3]]
+;
+ %2 = call nnan float @llvm.ceil.f32(float %0)
+ %3 = fcmp ueq float %2, %0
+ ret i1 %3
+}
+
+define <2 x i1> @x_ceil_ugt_vec(<2 x float> %0) {
+; CHECK-LABEL: @x_ceil_ugt_vec(
+; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
+;
+ %2 = call nnan <2 x float> @llvm.ceil.f32(<2 x float> %0)
+ %3 = fcmp uge <2 x float> %2, %0
+ ret <2 x i1> %3
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/107107
More information about the llvm-commits
mailing list