llvm.org GIT mirror llvm / 1638b83
Reorganize FastMathFlags to be a wrapper around unsigned, and streamline some interfaces. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@169712 91177308-0d34-0410-b5e6-96231b3b80d8 Michael Ilseman 7 years ago
8 changed file(s) with 84 addition(s) and 83 deletion(s). Raw diff Collapse all Expand all
2424 class DominatorTree;
2525 class Instruction;
2626 class DataLayout;
27 struct FastMathFlags;
27 class FastMathFlags;
2828 class TargetLibraryInfo;
2929 class Type;
3030 class Value;
2020
2121 namespace llvm {
2222
23 struct FastMathFlags;
23 class FastMathFlags;
2424 class LLVMContext;
2525 class MDNode;
2626
164164 };
165165
166166 /// Convenience struct for specifying and reasoning about fast-math flags.
167 struct FastMathFlags {
168 bool UnsafeAlgebra : 1;
169 bool NoNaNs : 1;
170 bool NoInfs : 1;
171 bool NoSignedZeros : 1;
172 bool AllowReciprocal : 1;
173
174 FastMathFlags() : UnsafeAlgebra(false), NoNaNs(false), NoInfs(false),
175 NoSignedZeros(false), AllowReciprocal(false)
176 { }
177
178 /// Whether any flag is set
179 bool any() {
180 return UnsafeAlgebra || NoNaNs || NoInfs || NoSignedZeros ||
181 AllowReciprocal;
182 }
183
184 /// Set all the flags to false
185 void clear() {
186 UnsafeAlgebra = NoNaNs = NoInfs = NoSignedZeros = AllowReciprocal = false;
187 }
188 };
189
190
191 /// FPMathOperator - Utility class for floating point operations which can have
192 /// information about relaxed accuracy requirements attached to them.
193 class FPMathOperator : public Operator {
167 class FastMathFlags {
168 private:
169 friend class FPMathOperator;
170 unsigned Flags;
171 FastMathFlags(unsigned F) : Flags(F) { }
172
194173 public:
195174 enum {
196175 UnsafeAlgebra = (1 << 0),
200179 AllowReciprocal = (1 << 4)
201180 };
202181
182 FastMathFlags() : Flags(0)
183 { }
184
185 /// Whether any flag is set
186 bool any() { return Flags != 0; }
187
188 /// Set all the flags to false
189 void clear() { Flags = 0; }
190
191 /// Flag queries
192 bool noNaNs() { return 0 != (Flags & NoNaNs); }
193 bool noInfs() { return 0 != (Flags & NoInfs); }
194 bool noSignedZeros() { return 0 != (Flags & NoSignedZeros); }
195 bool allowReciprocal() { return 0 != (Flags & AllowReciprocal); }
196 bool unsafeAlgebra() { return 0 != (Flags & UnsafeAlgebra); }
197
198 /// Flag setters
199 void setNoNaNs() { Flags |= NoNaNs; }
200 void setNoInfs() { Flags |= NoInfs; }
201 void setNoSignedZeros() { Flags |= NoSignedZeros; }
202 void setAllowReciprocal() { Flags |= AllowReciprocal; }
203 void setUnsafeAlgebra() {
204 Flags |= UnsafeAlgebra;
205 setNoNaNs();
206 setNoInfs();
207 setNoSignedZeros();
208 setAllowReciprocal();
209 }
210 };
211
212
213 /// FPMathOperator - Utility class for floating point operations which can have
214 /// information about relaxed accuracy requirements attached to them.
215 class FPMathOperator : public Operator {
203216 private:
204217 friend class Instruction;
205218
206219 void setHasUnsafeAlgebra(bool B) {
207220 SubclassOptionalData =
208 (SubclassOptionalData & ~UnsafeAlgebra) | (B * UnsafeAlgebra);
221 (SubclassOptionalData & ~FastMathFlags::UnsafeAlgebra) |
222 (B * FastMathFlags::UnsafeAlgebra);
209223
210224 // Unsafe algebra implies all the others
211225 if (B) {
217231 }
218232 void setHasNoNaNs(bool B) {
219233 SubclassOptionalData =
220 (SubclassOptionalData & ~NoNaNs) | (B * NoNaNs);
234 (SubclassOptionalData & ~FastMathFlags::NoNaNs) |
235 (B * FastMathFlags::NoNaNs);
221236 }
222237 void setHasNoInfs(bool B) {
223238 SubclassOptionalData =
224 (SubclassOptionalData & ~NoInfs) | (B * NoInfs);
239 (SubclassOptionalData & ~FastMathFlags::NoInfs) |
240 (B * FastMathFlags::NoInfs);
225241 }
226242 void setHasNoSignedZeros(bool B) {
227243 SubclassOptionalData =
228 (SubclassOptionalData & ~NoSignedZeros) | (B * NoSignedZeros);
244 (SubclassOptionalData & ~FastMathFlags::NoSignedZeros) |
245 (B * FastMathFlags::NoSignedZeros);
229246 }
230247 void setHasAllowReciprocal(bool B) {
231248 SubclassOptionalData =
232 (SubclassOptionalData & ~AllowReciprocal) | (B * AllowReciprocal);
249 (SubclassOptionalData & ~FastMathFlags::AllowReciprocal) |
250 (B * FastMathFlags::AllowReciprocal);
233251 }
234252
235253 /// Convenience function for setting all the fast-math flags
236254 void setFastMathFlags(FastMathFlags FMF) {
237 if (FMF.UnsafeAlgebra) {
238 // Set all the bits to true
239 setHasUnsafeAlgebra(true);
240 return;
241 }
242
243 setHasUnsafeAlgebra(FMF.UnsafeAlgebra);
244 setHasNoNaNs(FMF.NoNaNs);
245 setHasNoInfs(FMF.NoInfs);
246 setHasNoSignedZeros(FMF.NoSignedZeros);
247 setHasAllowReciprocal(FMF.AllowReciprocal);
255 SubclassOptionalData |= FMF.Flags;
248256 }
249257
250258 public:
251259 /// Test whether this operation is permitted to be
252260 /// algebraically transformed, aka the 'A' fast-math property.
253261 bool hasUnsafeAlgebra() const {
254 return (SubclassOptionalData & UnsafeAlgebra) != 0;
262 return (SubclassOptionalData & FastMathFlags::UnsafeAlgebra) != 0;
255263 }
256264
257265 /// Test whether this operation's arguments and results are to be
258266 /// treated as non-NaN, aka the 'N' fast-math property.
259267 bool hasNoNaNs() const {
260 return (SubclassOptionalData & NoNaNs) != 0;
268 return (SubclassOptionalData & FastMathFlags::NoNaNs) != 0;
261269 }
262270
263271 /// Test whether this operation's arguments and results are to be
264272 /// treated as NoN-Inf, aka the 'I' fast-math property.
265273 bool hasNoInfs() const {
266 return (SubclassOptionalData & NoInfs) != 0;
274 return (SubclassOptionalData & FastMathFlags::NoInfs) != 0;
267275 }
268276
269277 /// Test whether this operation can treat the sign of zero
270278 /// as insignificant, aka the 'S' fast-math property.
271279 bool hasNoSignedZeros() const {
272 return (SubclassOptionalData & NoSignedZeros) != 0;
280 return (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0;
273281 }
274282
275283 /// Test whether this operation is permitted to use
276284 /// reciprocal instead of division, aka the 'R' fast-math property.
277285 bool hasAllowReciprocal() const {
278 return (SubclassOptionalData & AllowReciprocal) != 0;
286 return (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0;
279287 }
280288
281289 /// Convenience function for getting all the fast-math flags
282290 FastMathFlags getFastMathFlags() const {
283 FastMathFlags FMF;
284 FMF.UnsafeAlgebra = hasUnsafeAlgebra();
285 FMF.NoNaNs = hasNoNaNs();
286 FMF.NoInfs = hasNoInfs();
287 FMF.NoSignedZeros = hasNoSignedZeros();
288 FMF.AllowReciprocal = hasAllowReciprocal();
289 return FMF;
290 }
291
291 return FastMathFlags(SubclassOptionalData);
292 }
292293
293294 /// \brief Get the maximum error permitted by this operation in ULPs. An
294295 /// accuracy of 0.0 means that the operation should be performed with the
899899 }
900900
901901 // Check for some fast-math optimizations
902 if (FMF.NoNaNs) {
903 if (FMF.NoSignedZeros) {
902 if (FMF.noNaNs()) {
903 if (FMF.noSignedZeros()) {
904904 // fmul N S 0, x ==> 0
905905 if (match(Op0, m_Zero()))
906906 return Op0;
159159 FastMathFlags FMF;
160160 while (true)
161161 switch (Lex.getKind()) {
162 case lltok::kw_fast: FMF.UnsafeAlgebra = true; Lex.Lex(); continue;
163 case lltok::kw_nnan: FMF.NoNaNs = true; Lex.Lex(); continue;
164 case lltok::kw_ninf: FMF.NoInfs = true; Lex.Lex(); continue;
165 case lltok::kw_nsz: FMF.NoSignedZeros = true; Lex.Lex(); continue;
166 case lltok::kw_arcp: FMF.AllowReciprocal = true; Lex.Lex(); continue;
162 case lltok::kw_fast: FMF.setUnsafeAlgebra(); Lex.Lex(); continue;
163 case lltok::kw_nnan: FMF.setNoNaNs(); Lex.Lex(); continue;
164 case lltok::kw_ninf: FMF.setNoInfs(); Lex.Lex(); continue;
165 case lltok::kw_nsz: FMF.setNoSignedZeros(); Lex.Lex(); continue;
166 case lltok::kw_arcp: FMF.setAllowReciprocal(); Lex.Lex(); continue;
167167 default: return FMF;
168168 }
169169 return FMF;
20462046 cast(I)->setIsExact(true);
20472047 } else if (isa(I)) {
20482048 FastMathFlags FMF;
2049 FMF.UnsafeAlgebra =
2050 0 != (Record[OpNum] & FPMathOperator::UnsafeAlgebra);
2051 FMF.NoNaNs =
2052 0 != (Record[OpNum] & FPMathOperator::NoNaNs);
2053 FMF.NoInfs =
2054 0 != (Record[OpNum] & FPMathOperator::NoInfs);
2055 FMF.NoSignedZeros =
2056 0 != (Record[OpNum] & FPMathOperator::NoSignedZeros);
2057 FMF.AllowReciprocal =
2058 0 != (Record[OpNum] & FPMathOperator::AllowReciprocal);
2049 if (0 != (Record[OpNum] & FastMathFlags::UnsafeAlgebra))
2050 FMF.setUnsafeAlgebra();
2051 if (0 != (Record[OpNum] & FastMathFlags::NoNaNs))
2052 FMF.setNoNaNs();
2053 if (0 != (Record[OpNum] & FastMathFlags::NoInfs))
2054 FMF.setNoInfs();
2055 if (0 != (Record[OpNum] & FastMathFlags::NoSignedZeros))
2056 FMF.setNoSignedZeros();
2057 if (0 != (Record[OpNum] & FastMathFlags::AllowReciprocal))
2058 FMF.setAllowReciprocal();
20592059 if (FMF.any())
20602060 I->setFastMathFlags(FMF);
20612061 }
551551 } else if (const FPMathOperator *FPMO =
552552 dyn_cast(V)) {
553553 if (FPMO->hasUnsafeAlgebra())
554 Flags |= FPMathOperator::UnsafeAlgebra;
554 Flags |= FastMathFlags::UnsafeAlgebra;
555555 if (FPMO->hasNoNaNs())
556 Flags |= FPMathOperator::NoNaNs;
556 Flags |= FastMathFlags::NoNaNs;
557557 if (FPMO->hasNoInfs())
558 Flags |= FPMathOperator::NoInfs;
558 Flags |= FastMathFlags::NoInfs;
559559 if (FPMO->hasNoSignedZeros())
560 Flags |= FPMathOperator::NoSignedZeros;
560 Flags |= FastMathFlags::NoSignedZeros;
561561 if (FPMO->hasAllowReciprocal())
562 Flags |= FPMathOperator::AllowReciprocal;
562 Flags |= FastMathFlags::AllowReciprocal;
563563 }
564564
565565 return Flags;
128128 F = Builder.CreateFAdd(F, F);
129129 EXPECT_FALSE(Builder.getFastMathFlags().any());
130130
131 FMF.UnsafeAlgebra = true;
131 FMF.setUnsafeAlgebra();
132132 Builder.SetFastMathFlags(FMF);
133133
134134 F = Builder.CreateFAdd(F, F);
152152 EXPECT_FALSE(FDiv->hasAllowReciprocal());
153153
154154 FMF.clear();
155 FMF.AllowReciprocal = true;
155 FMF.setAllowReciprocal();
156156 Builder.SetFastMathFlags(FMF);
157157
158158 F = Builder.CreateFDiv(F, F);