LLVM: lib/Transforms/Scalar/Float2Int.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
26#include
27
28#define DEBUG_TYPE "float2int"
29
30using namespace llvm;
31
32
33
34
35
36
37
38
39
40
41
42
43
46 cl::desc("Max integer bitwidth to consider in float2int"
47 "(default=64)"));
48
49
50
52 switch (P) {
71 default:
73 }
74}
75
76
77
79 switch (Opcode) {
81 case Instruction::FAdd: return Instruction::Add;
82 case Instruction::FSub: return Instruction::Sub;
83 case Instruction::FMul: return Instruction::Mul;
84 }
85}
86
87
88
90 for (BasicBlock &BB : F) {
91
92
94 continue;
95
96 for (Instruction &I : BB) {
98 continue;
99 switch (I.getOpcode()) {
100 default: break;
101 case Instruction::FPToUI:
102 case Instruction::FPToSI:
103 Roots.insert(&I);
104 break;
105 case Instruction::FCmp:
108 Roots.insert(&I);
109 break;
110 }
111 }
112 }
113}
114
115
118 SeenInsts.insert_or_assign(I, std::move(R));
119}
120
121
123 return ConstantRange::getFull(MaxIntegerBW + 1);
124}
126 return ConstantRange::getEmpty(MaxIntegerBW + 1);
127}
130 return badRange();
131 return R;
132}
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148void Float2IntPass::walkBackwards() {
149 std::deque<Instruction*> Worklist(Roots.begin(), Roots.end());
150 while (!Worklist.empty()) {
152 Worklist.pop_back();
153
154 if (SeenInsts.contains(I))
155
156 continue;
157
158 switch (I->getOpcode()) {
159
160 default:
161
162 seen(I, badRange());
163 break;
164
165 case Instruction::UIToFP:
166 case Instruction::SIToFP: {
167
168
169 unsigned BW = I->getOperand(0)->getType()->getPrimitiveSizeInBits();
170 auto Input = ConstantRange::getFull(BW);
172 seen(I, validateRange(Input.castOp(CastOp, MaxIntegerBW+1)));
173 continue;
174 }
175
176 case Instruction::FNeg:
177 case Instruction::FAdd:
178 case Instruction::FSub:
179 case Instruction::FMul:
180 case Instruction::FPToUI:
181 case Instruction::FPToSI:
182 case Instruction::FCmp:
183 seen(I, unknownRange());
184 break;
185 }
186
187 for (Value *O : I->operands()) {
189
190 ECs.unionSets(I, OI);
191 if (SeenInsts.find(I)->second != badRange())
192 Worklist.push_back(OI);
194
195 seen(I, badRange());
196 }
197 }
198 }
199}
200
201
202
203std::optional Float2IntPass::calcRange(Instruction *I) {
205 for (Value *O : I->operands()) {
207 auto OpIt = SeenInsts.find(OI);
208 assert(OpIt != SeenInsts.end() && "def not seen before use!");
209 if (OpIt->second == unknownRange())
210 return std::nullopt;
211 OpRanges.push_back(OpIt->second);
213
214
215
216
217
218
219
220
221
222 const APFloat &F = CF->getValueAPF();
223
224
225
226
227 if (.isFinite() ||
229 ->hasNoSignedZeros()))
230 return badRange();
231
235 return badRange();
236
237
239 bool Exact;
242
243
246 else
247 return badRange();
248 } else {
249 llvm_unreachable("Should have already marked this as badRange!");
250 }
251 }
252
253 switch (I->getOpcode()) {
254
255 default:
256 case Instruction::UIToFP:
257 case Instruction::SIToFP:
258 llvm_unreachable("Should have been handled in walkForwards!");
259
260 case Instruction::FNeg: {
261 assert(OpRanges.size() == 1 && "FNeg is a unary operator!");
262 unsigned Size = OpRanges[0].getBitWidth();
264 return Zero.sub(OpRanges[0]);
265 }
266
267 case Instruction::FAdd:
268 case Instruction::FSub:
269 case Instruction::FMul: {
270 assert(OpRanges.size() == 2 && "its a binary operator!");
272 return OpRanges[0].binaryOp(BinOp, OpRanges[1]);
273 }
274
275
276
277
278
279 case Instruction::FPToUI:
280 case Instruction::FPToSI: {
281 assert(OpRanges.size() == 1 && "FPTo[US]I is a unary operator!");
282
283
285 return OpRanges[0].castOp(CastOp, MaxIntegerBW+1);
286 }
287
288 case Instruction::FCmp:
289 assert(OpRanges.size() == 2 && "FCmp is a binary operator!");
290 return OpRanges[0].unionWith(OpRanges[1]);
291 }
292}
293
294
295
296void Float2IntPass::walkForwards() {
297 std::deque<Instruction *> Worklist;
298 for (const auto &Pair : SeenInsts)
299 if (Pair.second == unknownRange())
300 Worklist.push_back(Pair.first);
301
302 while (!Worklist.empty()) {
304 Worklist.pop_back();
305
306 if (std::optional Range = calcRange(I))
308 else
309 Worklist.push_front(I);
310 }
311}
312
313
314bool Float2IntPass::validateAndTransform(const DataLayout &DL) {
315 bool MadeChange = false;
316
317
318 for (const auto &E : ECs) {
319 if (->isLeader())
320 continue;
321
323 bool Fail = false;
324 Type *ConvertedToTy = nullptr;
325
326
327 for (Instruction *I : ECs.members(*E)) {
328 auto *SeenI = SeenInsts.find(I);
329 if (SeenI == SeenInsts.end())
330 continue;
331
332 R = R.unionWith(SeenI->second);
333
334
335
336
337 if (!Roots.contains(I)) {
338
339 if (!ConvertedToTy)
340 ConvertedToTy = I->getType();
341 for (User *U : I->users()) {
343 if (!UI || !SeenInsts.contains(UI)) {
344 LLVM_DEBUG(dbgs() << "F2I: Failing because of " << *U << "\n");
346 break;
347 }
348 }
349 }
351 break;
352 }
353
354
355
356 if (ECs.member_begin(*E) == ECs.member_end() || Fail || R.isFullSet() ||
357 R.isSignWrappedSet())
358 continue;
359 assert(ConvertedToTy && "Must have set the convertedtoty by this point!");
360
361
362
363 unsigned MinBW = R.getMinSignedBits() + 1;
364 LLVM_DEBUG(dbgs() << "F2I: MinBitwidth=" << MinBW << ", R: " << R << "\n");
365
366
367
368
369
370
371
372 unsigned MaxRepresentableBits
374 if (MinBW > MaxRepresentableBits) {
375 LLVM_DEBUG(dbgs() << "F2I: Value not guaranteed to be representable!\n");
376 continue;
377 }
378
379
380
381 Type *Ty = DL.getSmallestLegalIntType(*Ctx, MinBW);
382 if (!Ty) {
383
384
385 if (MinBW <= 32) {
387 } else if (MinBW <= 64) {
389 } else {
390 LLVM_DEBUG(dbgs() << "F2I: Value requires more bits to represent than "
391 "the target supports!\n");
392 continue;
393 }
394 }
395
396 for (Instruction *I : ECs.members(*E))
397 convert(I, Ty);
398 MadeChange = true;
399 }
400
401 return MadeChange;
402}
403
405 if (auto It = ConvertedInsts.find(I); It != ConvertedInsts.end())
406
407 return It->second;
408
410 for (Value *V : I->operands()) {
411
412 if (I->getOpcode() == Instruction::UIToFP ||
413 I->getOpcode() == Instruction::SIToFP) {
416 NewOperands.push_back(convert(VI, ToTy));
419 bool Exact;
420 CF->getValueAPF().convertToInteger(Val,
422 &Exact);
423 NewOperands.push_back(ConstantInt::get(ToTy, Val));
424 } else {
426 }
427 }
428
429
431 Value *NewV = nullptr;
432 switch (I->getOpcode()) {
434
435 case Instruction::FPToUI:
436 NewV = IRB.CreateZExtOrTrunc(NewOperands[0], I->getType());
437 break;
438
439 case Instruction::FPToSI:
440 NewV = IRB.CreateSExtOrTrunc(NewOperands[0], I->getType());
441 break;
442
443 case Instruction::FCmp: {
446 NewV = IRB.CreateICmp(P, NewOperands[0], NewOperands[1], I->getName());
447 break;
448 }
449
450 case Instruction::UIToFP:
451 NewV = IRB.CreateZExtOrTrunc(NewOperands[0], ToTy);
452 break;
453
454 case Instruction::SIToFP:
455 NewV = IRB.CreateSExtOrTrunc(NewOperands[0], ToTy);
456 break;
457
458 case Instruction::FNeg:
459 NewV = IRB.CreateNeg(NewOperands[0], I->getName());
460 break;
461
462 case Instruction::FAdd:
463 case Instruction::FSub:
464 case Instruction::FMul:
465 NewV = IRB.CreateBinOp(mapBinOpcode(I->getOpcode()),
466 NewOperands[0], NewOperands[1],
467 I->getName());
468 break;
469 }
470
471
472 if (Roots.count(I))
473 I->replaceAllUsesWith(NewV);
474
475 ConvertedInsts[I] = NewV;
476 return NewV;
477}
478
479
480void Float2IntPass::cleanup() {
481 for (auto &I : reverse(ConvertedInsts))
482 I.first->eraseFromParent();
483}
484
486 LLVM_DEBUG(dbgs() << "F2I: Looking at function " << F.getName() << "\n");
487
489 SeenInsts.clear();
490 ConvertedInsts.clear();
491 Roots.clear();
492
493 Ctx = &F.getParent()->getContext();
494
495 findRoots(F, DT);
496
497 walkBackwards();
498 walkForwards();
499
501 bool Modified = validateAndTransform(DL);
503 cleanup();
505}
506
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static CmpInst::Predicate mapFCmpPred(CmpInst::Predicate P)
Definition Float2Int.cpp:51
static Instruction::BinaryOps mapBinOpcode(unsigned Opcode)
Definition Float2Int.cpp:78
static cl::opt< unsigned > MaxIntegerBW("float2int-max-integer-bw", cl::init(64), cl::Hidden, cl::desc("Max integer bitwidth to consider in float2int" "(default=64)"))
The largest integer type worth dealing with.
This is the interface for a simple mod/ref and alias analysis over globals.
Module.h This file contains the declarations for the Module class.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
This file defines the SmallVector class.
static constexpr roundingMode rmNearestTiesToEven
static LLVM_ABI unsigned int semanticsPrecision(const fltSemantics &)
opStatus
IEEE-754R 7: Default exception handling.
opStatus roundToIntegral(roundingMode RM)
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represents analyses that only rely on functions' control flow.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
This class represents a range of values.
A parsed version of the target data layout string in and methods for querying it.
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
EquivalenceClasses - This represents a collection of equivalence classes and supports three efficient...
bool runImpl(Function &F, const DominatorTree &DT)
Definition Float2Int.cpp:485
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Definition Float2Int.cpp:507
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
void push_back(const T &Elt)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
LLVM_ABI const fltSemantics & getFltSemantics() const
LLVM Value Representation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Predicate getPredicate(unsigned Condition, unsigned Hint)
Return predicate consisting of specified condition and hint bits.
initializer< Ty > init(const Ty &Val)
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.