@@ -108,11 +108,114 @@ ConstantFPRange ConstantFPRange::getNonNaN(const fltSemantics &Sem) {
108108 /* MayBeQNaN=*/ false , /* MayBeSNaN=*/ false );
109109}
110110
111+ // / Return true for ULT/UGT/OLT/OGT
112+ static bool fcmpPredExcludesEqual (FCmpInst::Predicate Pred) {
113+ return !(Pred & FCmpInst::FCMP_OEQ);
114+ }
115+
116+ // / Return [-inf, V) or [-inf, V]
117+ static ConstantFPRange makeLessThan (APFloat V, FCmpInst::Predicate Pred) {
118+ const fltSemantics &Sem = V.getSemantics ();
119+ if (fcmpPredExcludesEqual (Pred)) {
120+ if (V.isNegInfinity ())
121+ return ConstantFPRange::getEmpty (Sem);
122+ V.next (/* nextDown=*/ true );
123+ }
124+ return ConstantFPRange::getNonNaN (APFloat::getInf (Sem, /* Negative=*/ true ),
125+ std::move (V));
126+ }
127+
128+ // / Return (V, +inf] or [V, +inf]
129+ static ConstantFPRange makeGreaterThan (APFloat V, FCmpInst::Predicate Pred) {
130+ const fltSemantics &Sem = V.getSemantics ();
131+ if (fcmpPredExcludesEqual (Pred)) {
132+ if (V.isPosInfinity ())
133+ return ConstantFPRange::getEmpty (Sem);
134+ V.next (/* nextDown=*/ false );
135+ }
136+ return ConstantFPRange::getNonNaN (std::move (V),
137+ APFloat::getInf (Sem, /* Negative=*/ false ));
138+ }
139+
140+ // / Make sure that +0/-0 are both included in the range.
141+ static ConstantFPRange extendZeroIfEqual (const ConstantFPRange &CR,
142+ FCmpInst::Predicate Pred) {
143+ if (fcmpPredExcludesEqual (Pred))
144+ return CR;
145+
146+ APFloat Lower = CR.getLower ();
147+ APFloat Upper = CR.getUpper ();
148+ if (Lower.isPosZero ())
149+ Lower = APFloat::getZero (Lower.getSemantics (), /* Negative=*/ true );
150+ if (Upper.isNegZero ())
151+ Upper = APFloat::getZero (Upper.getSemantics (), /* Negative=*/ false );
152+ return ConstantFPRange (std::move (Lower), std::move (Upper), CR.containsQNaN (),
153+ CR.containsSNaN ());
154+ }
155+
156+ static ConstantFPRange setNaNField (const ConstantFPRange &CR,
157+ FCmpInst::Predicate Pred) {
158+ bool ContainsNaN = FCmpInst::isUnordered (Pred);
159+ return ConstantFPRange (CR.getLower (), CR.getUpper (),
160+ /* MayBeQNaN=*/ ContainsNaN, /* MayBeSNaN=*/ ContainsNaN);
161+ }
162+
111163ConstantFPRange
112164ConstantFPRange::makeAllowedFCmpRegion (FCmpInst::Predicate Pred,
113165 const ConstantFPRange &Other) {
114- // TODO
115- return getFull (Other.getSemantics ());
166+ if (Other.isEmptySet ())
167+ return Other;
168+ if (Other.containsNaN () && FCmpInst::isUnordered (Pred))
169+ return getFull (Other.getSemantics ());
170+ if (Other.isNaNOnly () && FCmpInst::isOrdered (Pred))
171+ return getEmpty (Other.getSemantics ());
172+
173+ switch (Pred) {
174+ case FCmpInst::FCMP_TRUE:
175+ return getFull (Other.getSemantics ());
176+ case FCmpInst::FCMP_FALSE:
177+ return getEmpty (Other.getSemantics ());
178+ case FCmpInst::FCMP_ORD:
179+ return getNonNaN (Other.getSemantics ());
180+ case FCmpInst::FCMP_UNO:
181+ return getNaNOnly (Other.getSemantics (), /* MayBeQNaN=*/ true ,
182+ /* MayBeSNaN=*/ true );
183+ case FCmpInst::FCMP_OEQ:
184+ case FCmpInst::FCMP_UEQ:
185+ return setNaNField (extendZeroIfEqual (Other, Pred), Pred);
186+ case FCmpInst::FCMP_ONE:
187+ case FCmpInst::FCMP_UNE:
188+ if (const APFloat *SingleElement =
189+ Other.getSingleElement (/* ExcludesNaN=*/ true )) {
190+ const fltSemantics &Sem = SingleElement->getSemantics ();
191+ if (SingleElement->isPosInfinity ())
192+ return setNaNField (
193+ getNonNaN (APFloat::getInf (Sem, /* Negative=*/ true ),
194+ APFloat::getLargest (Sem, /* Negative=*/ false )),
195+ Pred);
196+ if (SingleElement->isNegInfinity ())
197+ return setNaNField (
198+ getNonNaN (APFloat::getLargest (Sem, /* Negative=*/ true ),
199+ APFloat::getInf (Sem, /* Negative=*/ false )),
200+ Pred);
201+ }
202+ return Pred == FCmpInst::FCMP_ONE ? getNonNaN (Other.getSemantics ())
203+ : getFull (Other.getSemantics ());
204+ case FCmpInst::FCMP_OLT:
205+ case FCmpInst::FCMP_OLE:
206+ case FCmpInst::FCMP_ULT:
207+ case FCmpInst::FCMP_ULE:
208+ return setNaNField (
209+ extendZeroIfEqual (makeLessThan (Other.getUpper (), Pred), Pred), Pred);
210+ case FCmpInst::FCMP_OGT:
211+ case FCmpInst::FCMP_OGE:
212+ case FCmpInst::FCMP_UGT:
213+ case FCmpInst::FCMP_UGE:
214+ return setNaNField (
215+ extendZeroIfEqual (makeGreaterThan (Other.getLower (), Pred), Pred), Pred);
216+ default :
217+ llvm_unreachable (" Unexpected predicate" );
218+ }
116219}
117220
118221ConstantFPRange
0 commit comments