1ff0cc061SDimitry Andric //===- Float2Int.cpp - Demote floating point ops to work on integers ------===//
2ff0cc061SDimitry Andric //
3ff0cc061SDimitry Andric //                     The LLVM Compiler Infrastructure
4ff0cc061SDimitry Andric //
5ff0cc061SDimitry Andric // This file is distributed under the University of Illinois Open Source
6ff0cc061SDimitry Andric // License. See LICENSE.TXT for details.
7ff0cc061SDimitry Andric //
8ff0cc061SDimitry Andric //===----------------------------------------------------------------------===//
9ff0cc061SDimitry Andric //
10ff0cc061SDimitry Andric // This file implements the Float2Int pass, which aims to demote floating
11ff0cc061SDimitry Andric // point operations to work on integers, where that is losslessly possible.
12ff0cc061SDimitry Andric //
13ff0cc061SDimitry Andric //===----------------------------------------------------------------------===//
14ff0cc061SDimitry Andric 
15ff0cc061SDimitry Andric #define DEBUG_TYPE "float2int"
163ca95b02SDimitry Andric 
173ca95b02SDimitry Andric #include "llvm/Transforms/Scalar/Float2Int.h"
18ff0cc061SDimitry Andric #include "llvm/ADT/APInt.h"
19ff0cc061SDimitry Andric #include "llvm/ADT/APSInt.h"
20ff0cc061SDimitry Andric #include "llvm/ADT/SmallVector.h"
217d523365SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h"
227d523365SDimitry Andric #include "llvm/Analysis/GlobalsModRef.h"
23ff0cc061SDimitry Andric #include "llvm/IR/Constants.h"
24ff0cc061SDimitry Andric #include "llvm/IR/IRBuilder.h"
25ff0cc061SDimitry Andric #include "llvm/IR/InstIterator.h"
26ff0cc061SDimitry Andric #include "llvm/IR/Instructions.h"
27ff0cc061SDimitry Andric #include "llvm/IR/Module.h"
28ff0cc061SDimitry Andric #include "llvm/Pass.h"
29ff0cc061SDimitry Andric #include "llvm/Support/Debug.h"
30ff0cc061SDimitry Andric #include "llvm/Support/raw_ostream.h"
31ff0cc061SDimitry Andric #include "llvm/Transforms/Scalar.h"
32ff0cc061SDimitry Andric #include <deque>
33ff0cc061SDimitry Andric #include <functional> // For std::function
34ff0cc061SDimitry Andric using namespace llvm;
35ff0cc061SDimitry Andric 
36ff0cc061SDimitry Andric // The algorithm is simple. Start at instructions that convert from the
37ff0cc061SDimitry Andric // float to the int domain: fptoui, fptosi and fcmp. Walk up the def-use
38ff0cc061SDimitry Andric // graph, using an equivalence datastructure to unify graphs that interfere.
39ff0cc061SDimitry Andric //
40ff0cc061SDimitry Andric // Mappable instructions are those with an integer corrollary that, given
41ff0cc061SDimitry Andric // integer domain inputs, produce an integer output; fadd, for example.
42ff0cc061SDimitry Andric //
43ff0cc061SDimitry Andric // If a non-mappable instruction is seen, this entire def-use graph is marked
44ff0cc061SDimitry Andric // as non-transformable. If we see an instruction that converts from the
45ff0cc061SDimitry Andric // integer domain to FP domain (uitofp,sitofp), we terminate our walk.
46ff0cc061SDimitry Andric 
47ff0cc061SDimitry Andric /// The largest integer type worth dealing with.
48ff0cc061SDimitry Andric static cl::opt<unsigned>
49ff0cc061SDimitry Andric MaxIntegerBW("float2int-max-integer-bw", cl::init(64), cl::Hidden,
50ff0cc061SDimitry Andric              cl::desc("Max integer bitwidth to consider in float2int"
51ff0cc061SDimitry Andric                       "(default=64)"));
52ff0cc061SDimitry Andric 
53ff0cc061SDimitry Andric namespace {
543ca95b02SDimitry Andric   struct Float2IntLegacyPass : public FunctionPass {
55ff0cc061SDimitry Andric     static char ID; // Pass identification, replacement for typeid
Float2IntLegacyPass__anondba6a98b0111::Float2IntLegacyPass563ca95b02SDimitry Andric     Float2IntLegacyPass() : FunctionPass(ID) {
573ca95b02SDimitry Andric       initializeFloat2IntLegacyPassPass(*PassRegistry::getPassRegistry());
58ff0cc061SDimitry Andric     }
59ff0cc061SDimitry Andric 
runOnFunction__anondba6a98b0111::Float2IntLegacyPass603ca95b02SDimitry Andric     bool runOnFunction(Function &F) override {
613ca95b02SDimitry Andric       if (skipFunction(F))
623ca95b02SDimitry Andric         return false;
633ca95b02SDimitry Andric 
643ca95b02SDimitry Andric       return Impl.runImpl(F);
653ca95b02SDimitry Andric     }
663ca95b02SDimitry Andric 
getAnalysisUsage__anondba6a98b0111::Float2IntLegacyPass67ff0cc061SDimitry Andric     void getAnalysisUsage(AnalysisUsage &AU) const override {
68ff0cc061SDimitry Andric       AU.setPreservesCFG();
697d523365SDimitry Andric       AU.addPreserved<GlobalsAAWrapperPass>();
70ff0cc061SDimitry Andric     }
71ff0cc061SDimitry Andric 
723ca95b02SDimitry Andric   private:
733ca95b02SDimitry Andric     Float2IntPass Impl;
74ff0cc061SDimitry Andric   };
753dac3a9bSDimitry Andric }
76ff0cc061SDimitry Andric 
773ca95b02SDimitry Andric char Float2IntLegacyPass::ID = 0;
783ca95b02SDimitry Andric INITIALIZE_PASS(Float2IntLegacyPass, "float2int", "Float to int", false, false)
79ff0cc061SDimitry Andric 
80ff0cc061SDimitry Andric // Given a FCmp predicate, return a matching ICmp predicate if one
81ff0cc061SDimitry Andric // exists, otherwise return BAD_ICMP_PREDICATE.
mapFCmpPred(CmpInst::Predicate P)82ff0cc061SDimitry Andric static CmpInst::Predicate mapFCmpPred(CmpInst::Predicate P) {
83ff0cc061SDimitry Andric   switch (P) {
84ff0cc061SDimitry Andric   case CmpInst::FCMP_OEQ:
85ff0cc061SDimitry Andric   case CmpInst::FCMP_UEQ:
86ff0cc061SDimitry Andric     return CmpInst::ICMP_EQ;
87ff0cc061SDimitry Andric   case CmpInst::FCMP_OGT:
88ff0cc061SDimitry Andric   case CmpInst::FCMP_UGT:
89ff0cc061SDimitry Andric     return CmpInst::ICMP_SGT;
90ff0cc061SDimitry Andric   case CmpInst::FCMP_OGE:
91ff0cc061SDimitry Andric   case CmpInst::FCMP_UGE:
92ff0cc061SDimitry Andric     return CmpInst::ICMP_SGE;
93ff0cc061SDimitry Andric   case CmpInst::FCMP_OLT:
94ff0cc061SDimitry Andric   case CmpInst::FCMP_ULT:
95ff0cc061SDimitry Andric     return CmpInst::ICMP_SLT;
96ff0cc061SDimitry Andric   case CmpInst::FCMP_OLE:
97ff0cc061SDimitry Andric   case CmpInst::FCMP_ULE:
98ff0cc061SDimitry Andric     return CmpInst::ICMP_SLE;
99ff0cc061SDimitry Andric   case CmpInst::FCMP_ONE:
100ff0cc061SDimitry Andric   case CmpInst::FCMP_UNE:
101ff0cc061SDimitry Andric     return CmpInst::ICMP_NE;
102ff0cc061SDimitry Andric   default:
103ff0cc061SDimitry Andric     return CmpInst::BAD_ICMP_PREDICATE;
104ff0cc061SDimitry Andric   }
105ff0cc061SDimitry Andric }
106ff0cc061SDimitry Andric 
107ff0cc061SDimitry Andric // Given a floating point binary operator, return the matching
108ff0cc061SDimitry Andric // integer version.
mapBinOpcode(unsigned Opcode)109ff0cc061SDimitry Andric static Instruction::BinaryOps mapBinOpcode(unsigned Opcode) {
110ff0cc061SDimitry Andric   switch (Opcode) {
111ff0cc061SDimitry Andric   default: llvm_unreachable("Unhandled opcode!");
112ff0cc061SDimitry Andric   case Instruction::FAdd: return Instruction::Add;
113ff0cc061SDimitry Andric   case Instruction::FSub: return Instruction::Sub;
114ff0cc061SDimitry Andric   case Instruction::FMul: return Instruction::Mul;
115ff0cc061SDimitry Andric   }
116ff0cc061SDimitry Andric }
117ff0cc061SDimitry Andric 
118ff0cc061SDimitry Andric // Find the roots - instructions that convert from the FP domain to
119ff0cc061SDimitry Andric // integer domain.
findRoots(Function & F,SmallPtrSet<Instruction *,8> & Roots)1203ca95b02SDimitry Andric void Float2IntPass::findRoots(Function &F, SmallPtrSet<Instruction*,8> &Roots) {
1217d523365SDimitry Andric   for (auto &I : instructions(F)) {
1227d523365SDimitry Andric     if (isa<VectorType>(I.getType()))
1237d523365SDimitry Andric       continue;
124ff0cc061SDimitry Andric     switch (I.getOpcode()) {
125ff0cc061SDimitry Andric     default: break;
126ff0cc061SDimitry Andric     case Instruction::FPToUI:
127ff0cc061SDimitry Andric     case Instruction::FPToSI:
128ff0cc061SDimitry Andric       Roots.insert(&I);
129ff0cc061SDimitry Andric       break;
130ff0cc061SDimitry Andric     case Instruction::FCmp:
131ff0cc061SDimitry Andric       if (mapFCmpPred(cast<CmpInst>(&I)->getPredicate()) !=
132ff0cc061SDimitry Andric           CmpInst::BAD_ICMP_PREDICATE)
133ff0cc061SDimitry Andric         Roots.insert(&I);
134ff0cc061SDimitry Andric       break;
135ff0cc061SDimitry Andric     }
136ff0cc061SDimitry Andric   }
137ff0cc061SDimitry Andric }
138ff0cc061SDimitry Andric 
139ff0cc061SDimitry Andric // Helper - mark I as having been traversed, having range R.
seen(Instruction * I,ConstantRange R)1400f5676f4SDimitry Andric void Float2IntPass::seen(Instruction *I, ConstantRange R) {
141*4ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << "F2I: " << *I << ":" << R << "\n");
1420f5676f4SDimitry Andric   auto IT = SeenInsts.find(I);
1430f5676f4SDimitry Andric   if (IT != SeenInsts.end())
1440f5676f4SDimitry Andric     IT->second = std::move(R);
145ff0cc061SDimitry Andric   else
1460f5676f4SDimitry Andric     SeenInsts.insert(std::make_pair(I, std::move(R)));
147ff0cc061SDimitry Andric }
148ff0cc061SDimitry Andric 
149ff0cc061SDimitry Andric // Helper - get a range representing a poison value.
badRange()1503ca95b02SDimitry Andric ConstantRange Float2IntPass::badRange() {
151ff0cc061SDimitry Andric   return ConstantRange(MaxIntegerBW + 1, true);
152ff0cc061SDimitry Andric }
unknownRange()1533ca95b02SDimitry Andric ConstantRange Float2IntPass::unknownRange() {
154ff0cc061SDimitry Andric   return ConstantRange(MaxIntegerBW + 1, false);
155ff0cc061SDimitry Andric }
validateRange(ConstantRange R)1563ca95b02SDimitry Andric ConstantRange Float2IntPass::validateRange(ConstantRange R) {
157ff0cc061SDimitry Andric   if (R.getBitWidth() > MaxIntegerBW + 1)
158ff0cc061SDimitry Andric     return badRange();
159ff0cc061SDimitry Andric   return R;
160ff0cc061SDimitry Andric }
161ff0cc061SDimitry Andric 
162ff0cc061SDimitry Andric // The most obvious way to structure the search is a depth-first, eager
163ff0cc061SDimitry Andric // search from each root. However, that require direct recursion and so
164ff0cc061SDimitry Andric // can only handle small instruction sequences. Instead, we split the search
165ff0cc061SDimitry Andric // up into two phases:
166ff0cc061SDimitry Andric //   - walkBackwards:  A breadth-first walk of the use-def graph starting from
167ff0cc061SDimitry Andric //                     the roots. Populate "SeenInsts" with interesting
168ff0cc061SDimitry Andric //                     instructions and poison values if they're obvious and
169ff0cc061SDimitry Andric //                     cheap to compute. Calculate the equivalance set structure
170ff0cc061SDimitry Andric //                     while we're here too.
171ff0cc061SDimitry Andric //   - walkForwards:  Iterate over SeenInsts in reverse order, so we visit
172ff0cc061SDimitry Andric //                     defs before their uses. Calculate the real range info.
173ff0cc061SDimitry Andric 
174ff0cc061SDimitry Andric // Breadth-first walk of the use-def graph; determine the set of nodes
175ff0cc061SDimitry Andric // we care about and eagerly determine if some of them are poisonous.
walkBackwards(const SmallPtrSetImpl<Instruction * > & Roots)1763ca95b02SDimitry Andric void Float2IntPass::walkBackwards(const SmallPtrSetImpl<Instruction*> &Roots) {
177ff0cc061SDimitry Andric   std::deque<Instruction*> Worklist(Roots.begin(), Roots.end());
178ff0cc061SDimitry Andric   while (!Worklist.empty()) {
179ff0cc061SDimitry Andric     Instruction *I = Worklist.back();
180ff0cc061SDimitry Andric     Worklist.pop_back();
181ff0cc061SDimitry Andric 
182ff0cc061SDimitry Andric     if (SeenInsts.find(I) != SeenInsts.end())
183ff0cc061SDimitry Andric       // Seen already.
184ff0cc061SDimitry Andric       continue;
185ff0cc061SDimitry Andric 
186ff0cc061SDimitry Andric     switch (I->getOpcode()) {
187ff0cc061SDimitry Andric       // FIXME: Handle select and phi nodes.
188ff0cc061SDimitry Andric     default:
189ff0cc061SDimitry Andric       // Path terminated uncleanly.
190ff0cc061SDimitry Andric       seen(I, badRange());
191ff0cc061SDimitry Andric       break;
192ff0cc061SDimitry Andric 
193d88c1a5aSDimitry Andric     case Instruction::UIToFP:
194ff0cc061SDimitry Andric     case Instruction::SIToFP: {
195d88c1a5aSDimitry Andric       // Path terminated cleanly - use the type of the integer input to seed
196d88c1a5aSDimitry Andric       // the analysis.
197ff0cc061SDimitry Andric       unsigned BW = I->getOperand(0)->getType()->getPrimitiveSizeInBits();
198d88c1a5aSDimitry Andric       auto Input = ConstantRange(BW, true);
199d88c1a5aSDimitry Andric       auto CastOp = (Instruction::CastOps)I->getOpcode();
200d88c1a5aSDimitry Andric       seen(I, validateRange(Input.castOp(CastOp, MaxIntegerBW+1)));
201ff0cc061SDimitry Andric       continue;
202ff0cc061SDimitry Andric     }
203ff0cc061SDimitry Andric 
204ff0cc061SDimitry Andric     case Instruction::FAdd:
205ff0cc061SDimitry Andric     case Instruction::FSub:
206ff0cc061SDimitry Andric     case Instruction::FMul:
207ff0cc061SDimitry Andric     case Instruction::FPToUI:
208ff0cc061SDimitry Andric     case Instruction::FPToSI:
209ff0cc061SDimitry Andric     case Instruction::FCmp:
210ff0cc061SDimitry Andric       seen(I, unknownRange());
211ff0cc061SDimitry Andric       break;
212ff0cc061SDimitry Andric     }
213ff0cc061SDimitry Andric 
214ff0cc061SDimitry Andric     for (Value *O : I->operands()) {
215ff0cc061SDimitry Andric       if (Instruction *OI = dyn_cast<Instruction>(O)) {
216ff0cc061SDimitry Andric         // Unify def-use chains if they interfere.
217ff0cc061SDimitry Andric         ECs.unionSets(I, OI);
218ff0cc061SDimitry Andric         if (SeenInsts.find(I)->second != badRange())
219ff0cc061SDimitry Andric           Worklist.push_back(OI);
220ff0cc061SDimitry Andric       } else if (!isa<ConstantFP>(O)) {
221ff0cc061SDimitry Andric         // Not an instruction or ConstantFP? we can't do anything.
222ff0cc061SDimitry Andric         seen(I, badRange());
223ff0cc061SDimitry Andric       }
224ff0cc061SDimitry Andric     }
225ff0cc061SDimitry Andric   }
226ff0cc061SDimitry Andric }
227ff0cc061SDimitry Andric 
228ff0cc061SDimitry Andric // Walk forwards down the list of seen instructions, so we visit defs before
229ff0cc061SDimitry Andric // uses.
walkForwards()2303ca95b02SDimitry Andric void Float2IntPass::walkForwards() {
2313ca95b02SDimitry Andric   for (auto &It : reverse(SeenInsts)) {
2327d523365SDimitry Andric     if (It.second != unknownRange())
233ff0cc061SDimitry Andric       continue;
234ff0cc061SDimitry Andric 
2357d523365SDimitry Andric     Instruction *I = It.first;
236ff0cc061SDimitry Andric     std::function<ConstantRange(ArrayRef<ConstantRange>)> Op;
237ff0cc061SDimitry Andric     switch (I->getOpcode()) {
238ff0cc061SDimitry Andric       // FIXME: Handle select and phi nodes.
239ff0cc061SDimitry Andric     default:
240ff0cc061SDimitry Andric     case Instruction::UIToFP:
241ff0cc061SDimitry Andric     case Instruction::SIToFP:
242ff0cc061SDimitry Andric       llvm_unreachable("Should have been handled in walkForwards!");
243ff0cc061SDimitry Andric 
244ff0cc061SDimitry Andric     case Instruction::FAdd:
245ff0cc061SDimitry Andric     case Instruction::FSub:
246ff0cc061SDimitry Andric     case Instruction::FMul:
247d88c1a5aSDimitry Andric       Op = [I](ArrayRef<ConstantRange> Ops) {
248d88c1a5aSDimitry Andric         assert(Ops.size() == 2 && "its a binary operator!");
249d88c1a5aSDimitry Andric         auto BinOp = (Instruction::BinaryOps) I->getOpcode();
250d88c1a5aSDimitry Andric         return Ops[0].binaryOp(BinOp, Ops[1]);
251ff0cc061SDimitry Andric       };
252ff0cc061SDimitry Andric       break;
253ff0cc061SDimitry Andric 
254ff0cc061SDimitry Andric     //
255ff0cc061SDimitry Andric     // Root-only instructions - we'll only see these if they're the
256ff0cc061SDimitry Andric     //                          first node in a walk.
257ff0cc061SDimitry Andric     //
258ff0cc061SDimitry Andric     case Instruction::FPToUI:
259ff0cc061SDimitry Andric     case Instruction::FPToSI:
260d88c1a5aSDimitry Andric       Op = [I](ArrayRef<ConstantRange> Ops) {
261ff0cc061SDimitry Andric         assert(Ops.size() == 1 && "FPTo[US]I is a unary operator!");
262d88c1a5aSDimitry Andric         // Note: We're ignoring the casts output size here as that's what the
263d88c1a5aSDimitry Andric         // caller expects.
264d88c1a5aSDimitry Andric         auto CastOp = (Instruction::CastOps)I->getOpcode();
265d88c1a5aSDimitry Andric         return Ops[0].castOp(CastOp, MaxIntegerBW+1);
266ff0cc061SDimitry Andric       };
267ff0cc061SDimitry Andric       break;
268ff0cc061SDimitry Andric 
269ff0cc061SDimitry Andric     case Instruction::FCmp:
270ff0cc061SDimitry Andric       Op = [](ArrayRef<ConstantRange> Ops) {
271ff0cc061SDimitry Andric         assert(Ops.size() == 2 && "FCmp is a binary operator!");
272ff0cc061SDimitry Andric         return Ops[0].unionWith(Ops[1]);
273ff0cc061SDimitry Andric       };
274ff0cc061SDimitry Andric       break;
275ff0cc061SDimitry Andric     }
276ff0cc061SDimitry Andric 
277ff0cc061SDimitry Andric     bool Abort = false;
278ff0cc061SDimitry Andric     SmallVector<ConstantRange,4> OpRanges;
279ff0cc061SDimitry Andric     for (Value *O : I->operands()) {
280ff0cc061SDimitry Andric       if (Instruction *OI = dyn_cast<Instruction>(O)) {
281ff0cc061SDimitry Andric         assert(SeenInsts.find(OI) != SeenInsts.end() &&
282ff0cc061SDimitry Andric                "def not seen before use!");
283ff0cc061SDimitry Andric         OpRanges.push_back(SeenInsts.find(OI)->second);
284ff0cc061SDimitry Andric       } else if (ConstantFP *CF = dyn_cast<ConstantFP>(O)) {
285ff0cc061SDimitry Andric         // Work out if the floating point number can be losslessly represented
286ff0cc061SDimitry Andric         // as an integer.
287ff0cc061SDimitry Andric         // APFloat::convertToInteger(&Exact) purports to do what we want, but
288ff0cc061SDimitry Andric         // the exactness can be too precise. For example, negative zero can
289ff0cc061SDimitry Andric         // never be exactly converted to an integer.
290ff0cc061SDimitry Andric         //
291ff0cc061SDimitry Andric         // Instead, we ask APFloat to round itself to an integral value - this
292ff0cc061SDimitry Andric         // preserves sign-of-zero - then compare the result with the original.
293ff0cc061SDimitry Andric         //
2943ca95b02SDimitry Andric         const APFloat &F = CF->getValueAPF();
295ff0cc061SDimitry Andric 
296ff0cc061SDimitry Andric         // First, weed out obviously incorrect values. Non-finite numbers
297ff0cc061SDimitry Andric         // can't be represented and neither can negative zero, unless
298ff0cc061SDimitry Andric         // we're in fast math mode.
299ff0cc061SDimitry Andric         if (!F.isFinite() ||
300ff0cc061SDimitry Andric             (F.isZero() && F.isNegative() && isa<FPMathOperator>(I) &&
301ff0cc061SDimitry Andric              !I->hasNoSignedZeros())) {
302ff0cc061SDimitry Andric           seen(I, badRange());
303ff0cc061SDimitry Andric           Abort = true;
304ff0cc061SDimitry Andric           break;
305ff0cc061SDimitry Andric         }
306ff0cc061SDimitry Andric 
307ff0cc061SDimitry Andric         APFloat NewF = F;
308ff0cc061SDimitry Andric         auto Res = NewF.roundToIntegral(APFloat::rmNearestTiesToEven);
309ff0cc061SDimitry Andric         if (Res != APFloat::opOK || NewF.compare(F) != APFloat::cmpEqual) {
310ff0cc061SDimitry Andric           seen(I, badRange());
311ff0cc061SDimitry Andric           Abort = true;
312ff0cc061SDimitry Andric           break;
313ff0cc061SDimitry Andric         }
314ff0cc061SDimitry Andric         // OK, it's representable. Now get it.
315ff0cc061SDimitry Andric         APSInt Int(MaxIntegerBW+1, false);
316ff0cc061SDimitry Andric         bool Exact;
317ff0cc061SDimitry Andric         CF->getValueAPF().convertToInteger(Int,
318ff0cc061SDimitry Andric                                            APFloat::rmNearestTiesToEven,
319ff0cc061SDimitry Andric                                            &Exact);
320ff0cc061SDimitry Andric         OpRanges.push_back(ConstantRange(Int));
321ff0cc061SDimitry Andric       } else {
322ff0cc061SDimitry Andric         llvm_unreachable("Should have already marked this as badRange!");
323ff0cc061SDimitry Andric       }
324ff0cc061SDimitry Andric     }
325ff0cc061SDimitry Andric 
326ff0cc061SDimitry Andric     // Reduce the operands' ranges to a single range and return.
327ff0cc061SDimitry Andric     if (!Abort)
328ff0cc061SDimitry Andric       seen(I, Op(OpRanges));
329ff0cc061SDimitry Andric   }
330ff0cc061SDimitry Andric }
331ff0cc061SDimitry Andric 
332ff0cc061SDimitry Andric // If there is a valid transform to be done, do it.
validateAndTransform()3333ca95b02SDimitry Andric bool Float2IntPass::validateAndTransform() {
334ff0cc061SDimitry Andric   bool MadeChange = false;
335ff0cc061SDimitry Andric 
336ff0cc061SDimitry Andric   // Iterate over every disjoint partition of the def-use graph.
337ff0cc061SDimitry Andric   for (auto It = ECs.begin(), E = ECs.end(); It != E; ++It) {
338ff0cc061SDimitry Andric     ConstantRange R(MaxIntegerBW + 1, false);
339ff0cc061SDimitry Andric     bool Fail = false;
340ff0cc061SDimitry Andric     Type *ConvertedToTy = nullptr;
341ff0cc061SDimitry Andric 
342ff0cc061SDimitry Andric     // For every member of the partition, union all the ranges together.
343ff0cc061SDimitry Andric     for (auto MI = ECs.member_begin(It), ME = ECs.member_end();
344ff0cc061SDimitry Andric          MI != ME; ++MI) {
345ff0cc061SDimitry Andric       Instruction *I = *MI;
346ff0cc061SDimitry Andric       auto SeenI = SeenInsts.find(I);
347ff0cc061SDimitry Andric       if (SeenI == SeenInsts.end())
348ff0cc061SDimitry Andric         continue;
349ff0cc061SDimitry Andric 
350ff0cc061SDimitry Andric       R = R.unionWith(SeenI->second);
351ff0cc061SDimitry Andric       // We need to ensure I has no users that have not been seen.
352ff0cc061SDimitry Andric       // If it does, transformation would be illegal.
353ff0cc061SDimitry Andric       //
354ff0cc061SDimitry Andric       // Don't count the roots, as they terminate the graphs.
355ff0cc061SDimitry Andric       if (Roots.count(I) == 0) {
356ff0cc061SDimitry Andric         // Set the type of the conversion while we're here.
357ff0cc061SDimitry Andric         if (!ConvertedToTy)
358ff0cc061SDimitry Andric           ConvertedToTy = I->getType();
359ff0cc061SDimitry Andric         for (User *U : I->users()) {
360ff0cc061SDimitry Andric           Instruction *UI = dyn_cast<Instruction>(U);
361ff0cc061SDimitry Andric           if (!UI || SeenInsts.find(UI) == SeenInsts.end()) {
362*4ba319b5SDimitry Andric             LLVM_DEBUG(dbgs() << "F2I: Failing because of " << *U << "\n");
363ff0cc061SDimitry Andric             Fail = true;
364ff0cc061SDimitry Andric             break;
365ff0cc061SDimitry Andric           }
366ff0cc061SDimitry Andric         }
367ff0cc061SDimitry Andric       }
368ff0cc061SDimitry Andric       if (Fail)
369ff0cc061SDimitry Andric         break;
370ff0cc061SDimitry Andric     }
371ff0cc061SDimitry Andric 
372ff0cc061SDimitry Andric     // If the set was empty, or we failed, or the range is poisonous,
373ff0cc061SDimitry Andric     // bail out.
374ff0cc061SDimitry Andric     if (ECs.member_begin(It) == ECs.member_end() || Fail ||
375ff0cc061SDimitry Andric         R.isFullSet() || R.isSignWrappedSet())
376ff0cc061SDimitry Andric       continue;
377ff0cc061SDimitry Andric     assert(ConvertedToTy && "Must have set the convertedtoty by this point!");
378ff0cc061SDimitry Andric 
379ff0cc061SDimitry Andric     // The number of bits required is the maximum of the upper and
380ff0cc061SDimitry Andric     // lower limits, plus one so it can be signed.
381ff0cc061SDimitry Andric     unsigned MinBW = std::max(R.getLower().getMinSignedBits(),
382ff0cc061SDimitry Andric                               R.getUpper().getMinSignedBits()) + 1;
383*4ba319b5SDimitry Andric     LLVM_DEBUG(dbgs() << "F2I: MinBitwidth=" << MinBW << ", R: " << R << "\n");
384ff0cc061SDimitry Andric 
385ff0cc061SDimitry Andric     // If we've run off the realms of the exactly representable integers,
386ff0cc061SDimitry Andric     // the floating point result will differ from an integer approximation.
387ff0cc061SDimitry Andric 
388ff0cc061SDimitry Andric     // Do we need more bits than are in the mantissa of the type we converted
389ff0cc061SDimitry Andric     // to? semanticsPrecision returns the number of mantissa bits plus one
390ff0cc061SDimitry Andric     // for the sign bit.
391ff0cc061SDimitry Andric     unsigned MaxRepresentableBits
392ff0cc061SDimitry Andric       = APFloat::semanticsPrecision(ConvertedToTy->getFltSemantics()) - 1;
393ff0cc061SDimitry Andric     if (MinBW > MaxRepresentableBits) {
394*4ba319b5SDimitry Andric       LLVM_DEBUG(dbgs() << "F2I: Value not guaranteed to be representable!\n");
395ff0cc061SDimitry Andric       continue;
396ff0cc061SDimitry Andric     }
397ff0cc061SDimitry Andric     if (MinBW > 64) {
398*4ba319b5SDimitry Andric       LLVM_DEBUG(
399*4ba319b5SDimitry Andric           dbgs() << "F2I: Value requires more than 64 bits to represent!\n");
400ff0cc061SDimitry Andric       continue;
401ff0cc061SDimitry Andric     }
402ff0cc061SDimitry Andric 
403ff0cc061SDimitry Andric     // OK, R is known to be representable. Now pick a type for it.
404ff0cc061SDimitry Andric     // FIXME: Pick the smallest legal type that will fit.
405ff0cc061SDimitry Andric     Type *Ty = (MinBW > 32) ? Type::getInt64Ty(*Ctx) : Type::getInt32Ty(*Ctx);
406ff0cc061SDimitry Andric 
407ff0cc061SDimitry Andric     for (auto MI = ECs.member_begin(It), ME = ECs.member_end();
408ff0cc061SDimitry Andric          MI != ME; ++MI)
409ff0cc061SDimitry Andric       convert(*MI, Ty);
410ff0cc061SDimitry Andric     MadeChange = true;
411ff0cc061SDimitry Andric   }
412ff0cc061SDimitry Andric 
413ff0cc061SDimitry Andric   return MadeChange;
414ff0cc061SDimitry Andric }
415ff0cc061SDimitry Andric 
convert(Instruction * I,Type * ToTy)4163ca95b02SDimitry Andric Value *Float2IntPass::convert(Instruction *I, Type *ToTy) {
417ff0cc061SDimitry Andric   if (ConvertedInsts.find(I) != ConvertedInsts.end())
418ff0cc061SDimitry Andric     // Already converted this instruction.
419ff0cc061SDimitry Andric     return ConvertedInsts[I];
420ff0cc061SDimitry Andric 
421ff0cc061SDimitry Andric   SmallVector<Value*,4> NewOperands;
422ff0cc061SDimitry Andric   for (Value *V : I->operands()) {
423ff0cc061SDimitry Andric     // Don't recurse if we're an instruction that terminates the path.
424ff0cc061SDimitry Andric     if (I->getOpcode() == Instruction::UIToFP ||
425ff0cc061SDimitry Andric         I->getOpcode() == Instruction::SIToFP) {
426ff0cc061SDimitry Andric       NewOperands.push_back(V);
427ff0cc061SDimitry Andric     } else if (Instruction *VI = dyn_cast<Instruction>(V)) {
428ff0cc061SDimitry Andric       NewOperands.push_back(convert(VI, ToTy));
429ff0cc061SDimitry Andric     } else if (ConstantFP *CF = dyn_cast<ConstantFP>(V)) {
430ff0cc061SDimitry Andric       APSInt Val(ToTy->getPrimitiveSizeInBits(), /*IsUnsigned=*/false);
431ff0cc061SDimitry Andric       bool Exact;
432ff0cc061SDimitry Andric       CF->getValueAPF().convertToInteger(Val,
433ff0cc061SDimitry Andric                                          APFloat::rmNearestTiesToEven,
434ff0cc061SDimitry Andric                                          &Exact);
435ff0cc061SDimitry Andric       NewOperands.push_back(ConstantInt::get(ToTy, Val));
436ff0cc061SDimitry Andric     } else {
437ff0cc061SDimitry Andric       llvm_unreachable("Unhandled operand type?");
438ff0cc061SDimitry Andric     }
439ff0cc061SDimitry Andric   }
440ff0cc061SDimitry Andric 
441ff0cc061SDimitry Andric   // Now create a new instruction.
442ff0cc061SDimitry Andric   IRBuilder<> IRB(I);
443ff0cc061SDimitry Andric   Value *NewV = nullptr;
444ff0cc061SDimitry Andric   switch (I->getOpcode()) {
445ff0cc061SDimitry Andric   default: llvm_unreachable("Unhandled instruction!");
446ff0cc061SDimitry Andric 
447ff0cc061SDimitry Andric   case Instruction::FPToUI:
448ff0cc061SDimitry Andric     NewV = IRB.CreateZExtOrTrunc(NewOperands[0], I->getType());
449ff0cc061SDimitry Andric     break;
450ff0cc061SDimitry Andric 
451ff0cc061SDimitry Andric   case Instruction::FPToSI:
452ff0cc061SDimitry Andric     NewV = IRB.CreateSExtOrTrunc(NewOperands[0], I->getType());
453ff0cc061SDimitry Andric     break;
454ff0cc061SDimitry Andric 
455ff0cc061SDimitry Andric   case Instruction::FCmp: {
456ff0cc061SDimitry Andric     CmpInst::Predicate P = mapFCmpPred(cast<CmpInst>(I)->getPredicate());
457ff0cc061SDimitry Andric     assert(P != CmpInst::BAD_ICMP_PREDICATE && "Unhandled predicate!");
458ff0cc061SDimitry Andric     NewV = IRB.CreateICmp(P, NewOperands[0], NewOperands[1], I->getName());
459ff0cc061SDimitry Andric     break;
460ff0cc061SDimitry Andric   }
461ff0cc061SDimitry Andric 
462ff0cc061SDimitry Andric   case Instruction::UIToFP:
463ff0cc061SDimitry Andric     NewV = IRB.CreateZExtOrTrunc(NewOperands[0], ToTy);
464ff0cc061SDimitry Andric     break;
465ff0cc061SDimitry Andric 
466ff0cc061SDimitry Andric   case Instruction::SIToFP:
467ff0cc061SDimitry Andric     NewV = IRB.CreateSExtOrTrunc(NewOperands[0], ToTy);
468ff0cc061SDimitry Andric     break;
469ff0cc061SDimitry Andric 
470ff0cc061SDimitry Andric   case Instruction::FAdd:
471ff0cc061SDimitry Andric   case Instruction::FSub:
472ff0cc061SDimitry Andric   case Instruction::FMul:
473ff0cc061SDimitry Andric     NewV = IRB.CreateBinOp(mapBinOpcode(I->getOpcode()),
474ff0cc061SDimitry Andric                            NewOperands[0], NewOperands[1],
475ff0cc061SDimitry Andric                            I->getName());
476ff0cc061SDimitry Andric     break;
477ff0cc061SDimitry Andric   }
478ff0cc061SDimitry Andric 
479ff0cc061SDimitry Andric   // If we're a root instruction, RAUW.
480ff0cc061SDimitry Andric   if (Roots.count(I))
481ff0cc061SDimitry Andric     I->replaceAllUsesWith(NewV);
482ff0cc061SDimitry Andric 
483ff0cc061SDimitry Andric   ConvertedInsts[I] = NewV;
484ff0cc061SDimitry Andric   return NewV;
485ff0cc061SDimitry Andric }
486ff0cc061SDimitry Andric 
487ff0cc061SDimitry Andric // Perform dead code elimination on the instructions we just modified.
cleanup()4883ca95b02SDimitry Andric void Float2IntPass::cleanup() {
4893ca95b02SDimitry Andric   for (auto &I : reverse(ConvertedInsts))
4907d523365SDimitry Andric     I.first->eraseFromParent();
491ff0cc061SDimitry Andric }
492ff0cc061SDimitry Andric 
runImpl(Function & F)4933ca95b02SDimitry Andric bool Float2IntPass::runImpl(Function &F) {
494*4ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << "F2I: Looking at function " << F.getName() << "\n");
495ff0cc061SDimitry Andric   // Clear out all state.
496ff0cc061SDimitry Andric   ECs = EquivalenceClasses<Instruction*>();
497ff0cc061SDimitry Andric   SeenInsts.clear();
498ff0cc061SDimitry Andric   ConvertedInsts.clear();
499ff0cc061SDimitry Andric   Roots.clear();
500ff0cc061SDimitry Andric 
501ff0cc061SDimitry Andric   Ctx = &F.getParent()->getContext();
502ff0cc061SDimitry Andric 
503ff0cc061SDimitry Andric   findRoots(F, Roots);
504ff0cc061SDimitry Andric 
505ff0cc061SDimitry Andric   walkBackwards(Roots);
506ff0cc061SDimitry Andric   walkForwards();
507ff0cc061SDimitry Andric 
508ff0cc061SDimitry Andric   bool Modified = validateAndTransform();
509ff0cc061SDimitry Andric   if (Modified)
510ff0cc061SDimitry Andric     cleanup();
511ff0cc061SDimitry Andric   return Modified;
512ff0cc061SDimitry Andric }
513ff0cc061SDimitry Andric 
5143ca95b02SDimitry Andric namespace llvm {
createFloat2IntPass()5153ca95b02SDimitry Andric FunctionPass *createFloat2IntPass() { return new Float2IntLegacyPass(); }
5163ca95b02SDimitry Andric 
run(Function & F,FunctionAnalysisManager &)5173ca95b02SDimitry Andric PreservedAnalyses Float2IntPass::run(Function &F, FunctionAnalysisManager &) {
5183ca95b02SDimitry Andric   if (!runImpl(F))
5193ca95b02SDimitry Andric     return PreservedAnalyses::all();
5207a7e6055SDimitry Andric 
5213ca95b02SDimitry Andric   PreservedAnalyses PA;
5227a7e6055SDimitry Andric   PA.preserveSet<CFGAnalyses>();
5233ca95b02SDimitry Andric   PA.preserve<GlobalsAA>();
5243ca95b02SDimitry Andric   return PA;
5253ca95b02SDimitry Andric }
5263ca95b02SDimitry Andric } // End namespace llvm
527