Skip to content

Commit c9e8bbd

Browse files
committed
floor(x) <= x --> true
1 parent 8861328 commit c9e8bbd

File tree

2 files changed

+147
-5
lines changed

2 files changed

+147
-5
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4130,19 +4130,47 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
41304130
//
41314131
// This catches the 2 variable input case, constants are handled below as a
41324132
// class-like compare.
4133+
KnownFPClass LHSClass = computeKnownFPClass(LHS, fcAllFlags, /*Depth=*/0, Q);
4134+
KnownFPClass RHSClass = computeKnownFPClass(RHS, fcAllFlags, /*Depth=*/0, Q);
41334135
if (Pred == FCmpInst::FCMP_ORD || Pred == FCmpInst::FCMP_UNO) {
4134-
KnownFPClass RHSClass =
4135-
computeKnownFPClass(RHS, fcAllFlags, /*Depth=*/0, Q);
4136-
KnownFPClass LHSClass =
4137-
computeKnownFPClass(LHS, fcAllFlags, /*Depth=*/0, Q);
4138-
41394136
if (FMF.noNaNs() ||
41404137
(RHSClass.isKnownNeverNaN() && LHSClass.isKnownNeverNaN()))
41414138
return ConstantInt::get(RetTy, Pred == FCmpInst::FCMP_ORD);
41424139

41434140
if (RHSClass.isKnownAlwaysNaN() || LHSClass.isKnownAlwaysNaN())
41444141
return ConstantInt::get(RetTy, Pred == CmpInst::FCMP_UNO);
41454142
}
4143+
// floor(x) <= x --> true; x <= ceil(x) --> true
4144+
if (LHSClass.isKnownNeverNaN() &&
4145+
match(LHS, m_Intrinsic<Intrinsic::floor>(m_Specific(RHS))) ||
4146+
RHSClass.isKnownNeverNaN() &&
4147+
match(RHS, m_Intrinsic<Intrinsic::ceil>(m_Specific(LHS)))) {
4148+
switch (Pred) {
4149+
case FCmpInst::FCMP_OLE:
4150+
case FCmpInst::FCMP_ULE:
4151+
return getTrue(RetTy);
4152+
case FCmpInst::FCMP_OGT:
4153+
case FCmpInst::FCMP_UGT:
4154+
return getFalse(RetTy);
4155+
default:
4156+
break;
4157+
}
4158+
}
4159+
if (RHSClass.isKnownNeverNaN() &&
4160+
match(RHS, m_Intrinsic<Intrinsic::floor>(m_Specific(LHS))) ||
4161+
LHSClass.isKnownNeverNaN() &&
4162+
match(LHS, m_Intrinsic<Intrinsic::ceil>(m_Specific(RHS)))) {
4163+
switch (Pred) {
4164+
case FCmpInst::FCMP_OGE:
4165+
case FCmpInst::FCMP_UGE:
4166+
return getTrue(RetTy);
4167+
case FCmpInst::FCMP_OLT:
4168+
case FCmpInst::FCMP_ULT:
4169+
return getFalse(RetTy);
4170+
default:
4171+
break;
4172+
}
4173+
}
41464174

41474175
const APFloat *C = nullptr;
41484176
match(RHS, m_APFloatAllowPoison(C));
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
3+
4+
define i1 @x_floor_ole(float %0) {
5+
; CHECK-LABEL: @x_floor_ole(
6+
; CHECK-NEXT: ret i1 true
7+
;
8+
%2 = call nnan float @llvm.floor.f32(float %0)
9+
%3 = fcmp ole float %2, %0
10+
ret i1 %3
11+
}
12+
13+
define i1 @x_floor_ule(float %0) {
14+
; CHECK-LABEL: @x_floor_ule(
15+
; CHECK-NEXT: ret i1 true
16+
;
17+
%2 = call nnan float @llvm.floor.f32(float %0)
18+
%3 = fcmp ule float %2, %0
19+
ret i1 %3
20+
}
21+
22+
define i1 @x_floor_ogt(float %0) {
23+
; CHECK-LABEL: @x_floor_ogt(
24+
; CHECK-NEXT: ret i1 false
25+
;
26+
%2 = call nnan float @llvm.floor.f32(float %0)
27+
%3 = fcmp ogt float %2, %0
28+
ret i1 %3
29+
}
30+
31+
define i1 @x_floor_ugt(float %0) {
32+
; CHECK-LABEL: @x_floor_ugt(
33+
; CHECK-NEXT: ret i1 false
34+
;
35+
%2 = call nnan float @llvm.floor.f32(float %0)
36+
%3 = fcmp ugt float %2, %0
37+
ret i1 %3
38+
}
39+
40+
define i1 @x_floor_ueq(float %0) {
41+
; CHECK-LABEL: @x_floor_ueq(
42+
; CHECK-NEXT: [[TMP2:%.*]] = call nnan float @llvm.floor.f32(float [[TMP0:%.*]])
43+
; CHECK-NEXT: [[TMP3:%.*]] = fcmp ueq float [[TMP2]], [[TMP0]]
44+
; CHECK-NEXT: ret i1 [[TMP3]]
45+
;
46+
%2 = call nnan float @llvm.floor.f32(float %0)
47+
%3 = fcmp ueq float %2, %0
48+
ret i1 %3
49+
}
50+
51+
define <2 x i1> @x_floor_ugt_vec(<2 x float> %0) {
52+
; CHECK-LABEL: @x_floor_ugt_vec(
53+
; CHECK-NEXT: ret <2 x i1> zeroinitializer
54+
;
55+
%2 = call nnan <2 x float> @llvm.floor.v2f32(<2 x float> %0)
56+
%3 = fcmp ugt <2 x float> %2, %0
57+
ret <2 x i1> %3
58+
}
59+
60+
define i1 @x_ceil_ole(float %0) {
61+
; CHECK-LABEL: @x_ceil_ole(
62+
; CHECK-NEXT: ret i1 false
63+
;
64+
%2 = call nnan float @llvm.ceil.f32(float %0)
65+
%3 = fcmp olt float %2, %0
66+
ret i1 %3
67+
}
68+
69+
define i1 @x_ceil_ule(float %0) {
70+
; CHECK-LABEL: @x_ceil_ule(
71+
; CHECK-NEXT: ret i1 false
72+
;
73+
%2 = call nnan float @llvm.ceil.f32(float %0)
74+
%3 = fcmp ult float %2, %0
75+
ret i1 %3
76+
}
77+
78+
define i1 @x_ceil_ogt(float %0) {
79+
; CHECK-LABEL: @x_ceil_ogt(
80+
; CHECK-NEXT: ret i1 true
81+
;
82+
%2 = call nnan float @llvm.ceil.f32(float %0)
83+
%3 = fcmp oge float %2, %0
84+
ret i1 %3
85+
}
86+
87+
define i1 @x_ceil_ugt(float %0) {
88+
; CHECK-LABEL: @x_ceil_ugt(
89+
; CHECK-NEXT: ret i1 true
90+
;
91+
%2 = call nnan float @llvm.ceil.f32(float %0)
92+
%3 = fcmp uge float %2, %0
93+
ret i1 %3
94+
}
95+
96+
define i1 @x_ceil_ueq(float %0) {
97+
; CHECK-LABEL: @x_ceil_ueq(
98+
; CHECK-NEXT: [[TMP2:%.*]] = call nnan float @llvm.ceil.f32(float [[TMP0:%.*]])
99+
; CHECK-NEXT: [[TMP3:%.*]] = fcmp ueq float [[TMP2]], [[TMP0]]
100+
; CHECK-NEXT: ret i1 [[TMP3]]
101+
;
102+
%2 = call nnan float @llvm.ceil.f32(float %0)
103+
%3 = fcmp ueq float %2, %0
104+
ret i1 %3
105+
}
106+
107+
define <2 x i1> @x_ceil_ugt_vec(<2 x float> %0) {
108+
; CHECK-LABEL: @x_ceil_ugt_vec(
109+
; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
110+
;
111+
%2 = call nnan <2 x float> @llvm.ceil.f32(<2 x float> %0)
112+
%3 = fcmp uge <2 x float> %2, %0
113+
ret <2 x i1> %3
114+
}

0 commit comments

Comments
 (0)