[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:33:38 PDT 2024
https://github.com/c8ef created https://github.com/llvm/llvm-project/pull/107107
None
>From c9e8bbd1d93bbd0c2f87320e0cb73a463036ecae Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Tue, 3 Sep 2024 21:30:53 +0800
Subject: [PATCH] floor(x) <= x --> true
---
llvm/lib/Analysis/InstructionSimplify.cpp | 38 +++++-
.../Transforms/InstSimplify/fp-floor-ceil.ll | 114 ++++++++++++++++++
2 files changed, 147 insertions(+), 5 deletions(-)
create mode 100644 llvm/test/Transforms/InstSimplify/fp-floor-ceil.ll
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
+}
More information about the llvm-commits
mailing list