xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Scalar/Float2Int.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- Float2Int.cpp - Demote floating point ops to work on integers ------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the Float2Int pass, which aims to demote floating
100b57cec5SDimitry Andric // point operations to work on integers, where that is losslessly possible.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/Float2Int.h"
150b57cec5SDimitry Andric #include "llvm/ADT/APInt.h"
160b57cec5SDimitry Andric #include "llvm/ADT/APSInt.h"
170b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
180b57cec5SDimitry Andric #include "llvm/Analysis/GlobalsModRef.h"
190b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
2081ad6265SDimitry Andric #include "llvm/IR/Dominators.h"
210b57cec5SDimitry Andric #include "llvm/IR/IRBuilder.h"
220b57cec5SDimitry Andric #include "llvm/IR/Module.h"
2381ad6265SDimitry Andric #include "llvm/Support/CommandLine.h"
240b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
250b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
260b57cec5SDimitry Andric #include <deque>
27fe6060f1SDimitry Andric 
28fe6060f1SDimitry Andric #define DEBUG_TYPE "float2int"
29fe6060f1SDimitry Andric 
300b57cec5SDimitry Andric using namespace llvm;
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric // The algorithm is simple. Start at instructions that convert from the
330b57cec5SDimitry Andric // float to the int domain: fptoui, fptosi and fcmp. Walk up the def-use
340b57cec5SDimitry Andric // graph, using an equivalence datastructure to unify graphs that interfere.
350b57cec5SDimitry Andric //
360b57cec5SDimitry Andric // Mappable instructions are those with an integer corrollary that, given
370b57cec5SDimitry Andric // integer domain inputs, produce an integer output; fadd, for example.
380b57cec5SDimitry Andric //
390b57cec5SDimitry Andric // If a non-mappable instruction is seen, this entire def-use graph is marked
400b57cec5SDimitry Andric // as non-transformable. If we see an instruction that converts from the
410b57cec5SDimitry Andric // integer domain to FP domain (uitofp,sitofp), we terminate our walk.
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric /// The largest integer type worth dealing with.
440b57cec5SDimitry Andric static cl::opt<unsigned>
450b57cec5SDimitry Andric MaxIntegerBW("float2int-max-integer-bw", cl::init(64), cl::Hidden,
460b57cec5SDimitry Andric              cl::desc("Max integer bitwidth to consider in float2int"
470b57cec5SDimitry Andric                       "(default=64)"));
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric // Given a FCmp predicate, return a matching ICmp predicate if one
500b57cec5SDimitry Andric // exists, otherwise return BAD_ICMP_PREDICATE.
510b57cec5SDimitry Andric static CmpInst::Predicate mapFCmpPred(CmpInst::Predicate P) {
520b57cec5SDimitry Andric   switch (P) {
530b57cec5SDimitry Andric   case CmpInst::FCMP_OEQ:
540b57cec5SDimitry Andric   case CmpInst::FCMP_UEQ:
550b57cec5SDimitry Andric     return CmpInst::ICMP_EQ;
560b57cec5SDimitry Andric   case CmpInst::FCMP_OGT:
570b57cec5SDimitry Andric   case CmpInst::FCMP_UGT:
580b57cec5SDimitry Andric     return CmpInst::ICMP_SGT;
590b57cec5SDimitry Andric   case CmpInst::FCMP_OGE:
600b57cec5SDimitry Andric   case CmpInst::FCMP_UGE:
610b57cec5SDimitry Andric     return CmpInst::ICMP_SGE;
620b57cec5SDimitry Andric   case CmpInst::FCMP_OLT:
630b57cec5SDimitry Andric   case CmpInst::FCMP_ULT:
640b57cec5SDimitry Andric     return CmpInst::ICMP_SLT;
650b57cec5SDimitry Andric   case CmpInst::FCMP_OLE:
660b57cec5SDimitry Andric   case CmpInst::FCMP_ULE:
670b57cec5SDimitry Andric     return CmpInst::ICMP_SLE;
680b57cec5SDimitry Andric   case CmpInst::FCMP_ONE:
690b57cec5SDimitry Andric   case CmpInst::FCMP_UNE:
700b57cec5SDimitry Andric     return CmpInst::ICMP_NE;
710b57cec5SDimitry Andric   default:
720b57cec5SDimitry Andric     return CmpInst::BAD_ICMP_PREDICATE;
730b57cec5SDimitry Andric   }
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric // Given a floating point binary operator, return the matching
770b57cec5SDimitry Andric // integer version.
780b57cec5SDimitry Andric static Instruction::BinaryOps mapBinOpcode(unsigned Opcode) {
790b57cec5SDimitry Andric   switch (Opcode) {
800b57cec5SDimitry Andric   default: llvm_unreachable("Unhandled opcode!");
810b57cec5SDimitry Andric   case Instruction::FAdd: return Instruction::Add;
820b57cec5SDimitry Andric   case Instruction::FSub: return Instruction::Sub;
830b57cec5SDimitry Andric   case Instruction::FMul: return Instruction::Mul;
840b57cec5SDimitry Andric   }
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric // Find the roots - instructions that convert from the FP domain to
880b57cec5SDimitry Andric // integer domain.
895ffd83dbSDimitry Andric void Float2IntPass::findRoots(Function &F, const DominatorTree &DT) {
908bcb0991SDimitry Andric   for (BasicBlock &BB : F) {
918bcb0991SDimitry Andric     // Unreachable code can take on strange forms that we are not prepared to
928bcb0991SDimitry Andric     // handle. For example, an instruction may have itself as an operand.
938bcb0991SDimitry Andric     if (!DT.isReachableFromEntry(&BB))
948bcb0991SDimitry Andric       continue;
958bcb0991SDimitry Andric 
968bcb0991SDimitry Andric     for (Instruction &I : BB) {
970b57cec5SDimitry Andric       if (isa<VectorType>(I.getType()))
980b57cec5SDimitry Andric         continue;
990b57cec5SDimitry Andric       switch (I.getOpcode()) {
1000b57cec5SDimitry Andric       default: break;
1010b57cec5SDimitry Andric       case Instruction::FPToUI:
1020b57cec5SDimitry Andric       case Instruction::FPToSI:
1030b57cec5SDimitry Andric         Roots.insert(&I);
1040b57cec5SDimitry Andric         break;
1050b57cec5SDimitry Andric       case Instruction::FCmp:
1060b57cec5SDimitry Andric         if (mapFCmpPred(cast<CmpInst>(&I)->getPredicate()) !=
1070b57cec5SDimitry Andric             CmpInst::BAD_ICMP_PREDICATE)
1080b57cec5SDimitry Andric           Roots.insert(&I);
1090b57cec5SDimitry Andric         break;
1100b57cec5SDimitry Andric       }
1110b57cec5SDimitry Andric     }
1120b57cec5SDimitry Andric   }
1138bcb0991SDimitry Andric }
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric // Helper - mark I as having been traversed, having range R.
1160b57cec5SDimitry Andric void Float2IntPass::seen(Instruction *I, ConstantRange R) {
1170b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "F2I: " << *I << ":" << R << "\n");
1180b57cec5SDimitry Andric   auto IT = SeenInsts.find(I);
1190b57cec5SDimitry Andric   if (IT != SeenInsts.end())
1200b57cec5SDimitry Andric     IT->second = std::move(R);
1210b57cec5SDimitry Andric   else
1220b57cec5SDimitry Andric     SeenInsts.insert(std::make_pair(I, std::move(R)));
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric // Helper - get a range representing a poison value.
1260b57cec5SDimitry Andric ConstantRange Float2IntPass::badRange() {
1270b57cec5SDimitry Andric   return ConstantRange::getFull(MaxIntegerBW + 1);
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric ConstantRange Float2IntPass::unknownRange() {
1300b57cec5SDimitry Andric   return ConstantRange::getEmpty(MaxIntegerBW + 1);
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric ConstantRange Float2IntPass::validateRange(ConstantRange R) {
1330b57cec5SDimitry Andric   if (R.getBitWidth() > MaxIntegerBW + 1)
1340b57cec5SDimitry Andric     return badRange();
1350b57cec5SDimitry Andric   return R;
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric // The most obvious way to structure the search is a depth-first, eager
1390b57cec5SDimitry Andric // search from each root. However, that require direct recursion and so
1400b57cec5SDimitry Andric // can only handle small instruction sequences. Instead, we split the search
1410b57cec5SDimitry Andric // up into two phases:
1420b57cec5SDimitry Andric //   - walkBackwards:  A breadth-first walk of the use-def graph starting from
1430b57cec5SDimitry Andric //                     the roots. Populate "SeenInsts" with interesting
1440b57cec5SDimitry Andric //                     instructions and poison values if they're obvious and
1450b57cec5SDimitry Andric //                     cheap to compute. Calculate the equivalance set structure
1460b57cec5SDimitry Andric //                     while we're here too.
1470b57cec5SDimitry Andric //   - walkForwards:  Iterate over SeenInsts in reverse order, so we visit
1480b57cec5SDimitry Andric //                     defs before their uses. Calculate the real range info.
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric // Breadth-first walk of the use-def graph; determine the set of nodes
1510b57cec5SDimitry Andric // we care about and eagerly determine if some of them are poisonous.
1525ffd83dbSDimitry Andric void Float2IntPass::walkBackwards() {
1530b57cec5SDimitry Andric   std::deque<Instruction*> Worklist(Roots.begin(), Roots.end());
1540b57cec5SDimitry Andric   while (!Worklist.empty()) {
1550b57cec5SDimitry Andric     Instruction *I = Worklist.back();
1560b57cec5SDimitry Andric     Worklist.pop_back();
1570b57cec5SDimitry Andric 
15806c3fb27SDimitry Andric     if (SeenInsts.contains(I))
1590b57cec5SDimitry Andric       // Seen already.
1600b57cec5SDimitry Andric       continue;
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric     switch (I->getOpcode()) {
1630b57cec5SDimitry Andric       // FIXME: Handle select and phi nodes.
1640b57cec5SDimitry Andric     default:
1650b57cec5SDimitry Andric       // Path terminated uncleanly.
1660b57cec5SDimitry Andric       seen(I, badRange());
1670b57cec5SDimitry Andric       break;
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric     case Instruction::UIToFP:
1700b57cec5SDimitry Andric     case Instruction::SIToFP: {
1710b57cec5SDimitry Andric       // Path terminated cleanly - use the type of the integer input to seed
1720b57cec5SDimitry Andric       // the analysis.
1730b57cec5SDimitry Andric       unsigned BW = I->getOperand(0)->getType()->getPrimitiveSizeInBits();
1740b57cec5SDimitry Andric       auto Input = ConstantRange::getFull(BW);
1750b57cec5SDimitry Andric       auto CastOp = (Instruction::CastOps)I->getOpcode();
1760b57cec5SDimitry Andric       seen(I, validateRange(Input.castOp(CastOp, MaxIntegerBW+1)));
1770b57cec5SDimitry Andric       continue;
1780b57cec5SDimitry Andric     }
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric     case Instruction::FNeg:
1810b57cec5SDimitry Andric     case Instruction::FAdd:
1820b57cec5SDimitry Andric     case Instruction::FSub:
1830b57cec5SDimitry Andric     case Instruction::FMul:
1840b57cec5SDimitry Andric     case Instruction::FPToUI:
1850b57cec5SDimitry Andric     case Instruction::FPToSI:
1860b57cec5SDimitry Andric     case Instruction::FCmp:
1870b57cec5SDimitry Andric       seen(I, unknownRange());
1880b57cec5SDimitry Andric       break;
1890b57cec5SDimitry Andric     }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric     for (Value *O : I->operands()) {
1920b57cec5SDimitry Andric       if (Instruction *OI = dyn_cast<Instruction>(O)) {
1930b57cec5SDimitry Andric         // Unify def-use chains if they interfere.
1940b57cec5SDimitry Andric         ECs.unionSets(I, OI);
1950b57cec5SDimitry Andric         if (SeenInsts.find(I)->second != badRange())
1960b57cec5SDimitry Andric           Worklist.push_back(OI);
1970b57cec5SDimitry Andric       } else if (!isa<ConstantFP>(O)) {
1980b57cec5SDimitry Andric         // Not an instruction or ConstantFP? we can't do anything.
1990b57cec5SDimitry Andric         seen(I, badRange());
2000b57cec5SDimitry Andric       }
2010b57cec5SDimitry Andric     }
2020b57cec5SDimitry Andric   }
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric 
20581ad6265SDimitry Andric // Calculate result range from operand ranges.
206bdd1243dSDimitry Andric // Return std::nullopt if the range cannot be calculated yet.
207bdd1243dSDimitry Andric std::optional<ConstantRange> Float2IntPass::calcRange(Instruction *I) {
2080b57cec5SDimitry Andric   SmallVector<ConstantRange, 4> OpRanges;
2090b57cec5SDimitry Andric   for (Value *O : I->operands()) {
2100b57cec5SDimitry Andric     if (Instruction *OI = dyn_cast<Instruction>(O)) {
21181ad6265SDimitry Andric       auto OpIt = SeenInsts.find(OI);
21281ad6265SDimitry Andric       assert(OpIt != SeenInsts.end() && "def not seen before use!");
21381ad6265SDimitry Andric       if (OpIt->second == unknownRange())
214bdd1243dSDimitry Andric         return std::nullopt; // Wait until operand range has been calculated.
21581ad6265SDimitry Andric       OpRanges.push_back(OpIt->second);
2160b57cec5SDimitry Andric     } else if (ConstantFP *CF = dyn_cast<ConstantFP>(O)) {
2170b57cec5SDimitry Andric       // Work out if the floating point number can be losslessly represented
2180b57cec5SDimitry Andric       // as an integer.
2190b57cec5SDimitry Andric       // APFloat::convertToInteger(&Exact) purports to do what we want, but
2200b57cec5SDimitry Andric       // the exactness can be too precise. For example, negative zero can
2210b57cec5SDimitry Andric       // never be exactly converted to an integer.
2220b57cec5SDimitry Andric       //
2230b57cec5SDimitry Andric       // Instead, we ask APFloat to round itself to an integral value - this
2240b57cec5SDimitry Andric       // preserves sign-of-zero - then compare the result with the original.
2250b57cec5SDimitry Andric       //
2260b57cec5SDimitry Andric       const APFloat &F = CF->getValueAPF();
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric       // First, weed out obviously incorrect values. Non-finite numbers
2290b57cec5SDimitry Andric       // can't be represented and neither can negative zero, unless
2300b57cec5SDimitry Andric       // we're in fast math mode.
2310b57cec5SDimitry Andric       if (!F.isFinite() ||
2320b57cec5SDimitry Andric           (F.isZero() && F.isNegative() && isa<FPMathOperator>(I) &&
23381ad6265SDimitry Andric            !I->hasNoSignedZeros()))
23481ad6265SDimitry Andric         return badRange();
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric       APFloat NewF = F;
2370b57cec5SDimitry Andric       auto Res = NewF.roundToIntegral(APFloat::rmNearestTiesToEven);
23881ad6265SDimitry Andric       if (Res != APFloat::opOK || NewF != F)
23981ad6265SDimitry Andric         return badRange();
24081ad6265SDimitry Andric 
2410b57cec5SDimitry Andric       // OK, it's representable. Now get it.
2420b57cec5SDimitry Andric       APSInt Int(MaxIntegerBW+1, false);
2430b57cec5SDimitry Andric       bool Exact;
2440b57cec5SDimitry Andric       CF->getValueAPF().convertToInteger(Int,
2450b57cec5SDimitry Andric                                          APFloat::rmNearestTiesToEven,
2460b57cec5SDimitry Andric                                          &Exact);
2470b57cec5SDimitry Andric       OpRanges.push_back(ConstantRange(Int));
2480b57cec5SDimitry Andric     } else {
2490b57cec5SDimitry Andric       llvm_unreachable("Should have already marked this as badRange!");
2500b57cec5SDimitry Andric     }
2510b57cec5SDimitry Andric   }
2520b57cec5SDimitry Andric 
25381ad6265SDimitry Andric   switch (I->getOpcode()) {
25481ad6265SDimitry Andric   // FIXME: Handle select and phi nodes.
25581ad6265SDimitry Andric   default:
25681ad6265SDimitry Andric   case Instruction::UIToFP:
25781ad6265SDimitry Andric   case Instruction::SIToFP:
25881ad6265SDimitry Andric     llvm_unreachable("Should have been handled in walkForwards!");
25981ad6265SDimitry Andric 
26081ad6265SDimitry Andric   case Instruction::FNeg: {
26181ad6265SDimitry Andric     assert(OpRanges.size() == 1 && "FNeg is a unary operator!");
26281ad6265SDimitry Andric     unsigned Size = OpRanges[0].getBitWidth();
26381ad6265SDimitry Andric     auto Zero = ConstantRange(APInt::getZero(Size));
26481ad6265SDimitry Andric     return Zero.sub(OpRanges[0]);
26581ad6265SDimitry Andric   }
26681ad6265SDimitry Andric 
26781ad6265SDimitry Andric   case Instruction::FAdd:
26881ad6265SDimitry Andric   case Instruction::FSub:
26981ad6265SDimitry Andric   case Instruction::FMul: {
27081ad6265SDimitry Andric     assert(OpRanges.size() == 2 && "its a binary operator!");
27181ad6265SDimitry Andric     auto BinOp = (Instruction::BinaryOps) I->getOpcode();
27281ad6265SDimitry Andric     return OpRanges[0].binaryOp(BinOp, OpRanges[1]);
27381ad6265SDimitry Andric   }
27481ad6265SDimitry Andric 
27581ad6265SDimitry Andric   //
27681ad6265SDimitry Andric   // Root-only instructions - we'll only see these if they're the
27781ad6265SDimitry Andric   //                          first node in a walk.
27881ad6265SDimitry Andric   //
27981ad6265SDimitry Andric   case Instruction::FPToUI:
28081ad6265SDimitry Andric   case Instruction::FPToSI: {
28181ad6265SDimitry Andric     assert(OpRanges.size() == 1 && "FPTo[US]I is a unary operator!");
28281ad6265SDimitry Andric     // Note: We're ignoring the casts output size here as that's what the
28381ad6265SDimitry Andric     // caller expects.
28481ad6265SDimitry Andric     auto CastOp = (Instruction::CastOps)I->getOpcode();
28581ad6265SDimitry Andric     return OpRanges[0].castOp(CastOp, MaxIntegerBW+1);
28681ad6265SDimitry Andric   }
28781ad6265SDimitry Andric 
28881ad6265SDimitry Andric   case Instruction::FCmp:
28981ad6265SDimitry Andric     assert(OpRanges.size() == 2 && "FCmp is a binary operator!");
29081ad6265SDimitry Andric     return OpRanges[0].unionWith(OpRanges[1]);
29181ad6265SDimitry Andric   }
29281ad6265SDimitry Andric }
29381ad6265SDimitry Andric 
29481ad6265SDimitry Andric // Walk forwards down the list of seen instructions, so we visit defs before
29581ad6265SDimitry Andric // uses.
29681ad6265SDimitry Andric void Float2IntPass::walkForwards() {
29781ad6265SDimitry Andric   std::deque<Instruction *> Worklist;
29881ad6265SDimitry Andric   for (const auto &Pair : SeenInsts)
29981ad6265SDimitry Andric     if (Pair.second == unknownRange())
30081ad6265SDimitry Andric       Worklist.push_back(Pair.first);
30181ad6265SDimitry Andric 
30281ad6265SDimitry Andric   while (!Worklist.empty()) {
30381ad6265SDimitry Andric     Instruction *I = Worklist.back();
30481ad6265SDimitry Andric     Worklist.pop_back();
30581ad6265SDimitry Andric 
306bdd1243dSDimitry Andric     if (std::optional<ConstantRange> Range = calcRange(I))
30781ad6265SDimitry Andric       seen(I, *Range);
30881ad6265SDimitry Andric     else
30981ad6265SDimitry Andric       Worklist.push_front(I); // Reprocess later.
3100b57cec5SDimitry Andric   }
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric // If there is a valid transform to be done, do it.
314*0fca6ea1SDimitry Andric bool Float2IntPass::validateAndTransform(const DataLayout &DL) {
3150b57cec5SDimitry Andric   bool MadeChange = false;
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric   // Iterate over every disjoint partition of the def-use graph.
3180b57cec5SDimitry Andric   for (auto It = ECs.begin(), E = ECs.end(); It != E; ++It) {
3190b57cec5SDimitry Andric     ConstantRange R(MaxIntegerBW + 1, false);
3200b57cec5SDimitry Andric     bool Fail = false;
3210b57cec5SDimitry Andric     Type *ConvertedToTy = nullptr;
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric     // For every member of the partition, union all the ranges together.
3240b57cec5SDimitry Andric     for (auto MI = ECs.member_begin(It), ME = ECs.member_end();
3250b57cec5SDimitry Andric          MI != ME; ++MI) {
3260b57cec5SDimitry Andric       Instruction *I = *MI;
3270b57cec5SDimitry Andric       auto SeenI = SeenInsts.find(I);
3280b57cec5SDimitry Andric       if (SeenI == SeenInsts.end())
3290b57cec5SDimitry Andric         continue;
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric       R = R.unionWith(SeenI->second);
3320b57cec5SDimitry Andric       // We need to ensure I has no users that have not been seen.
3330b57cec5SDimitry Andric       // If it does, transformation would be illegal.
3340b57cec5SDimitry Andric       //
3350b57cec5SDimitry Andric       // Don't count the roots, as they terminate the graphs.
336349cc55cSDimitry Andric       if (!Roots.contains(I)) {
3370b57cec5SDimitry Andric         // Set the type of the conversion while we're here.
3380b57cec5SDimitry Andric         if (!ConvertedToTy)
3390b57cec5SDimitry Andric           ConvertedToTy = I->getType();
3400b57cec5SDimitry Andric         for (User *U : I->users()) {
3410b57cec5SDimitry Andric           Instruction *UI = dyn_cast<Instruction>(U);
34206c3fb27SDimitry Andric           if (!UI || !SeenInsts.contains(UI)) {
3430b57cec5SDimitry Andric             LLVM_DEBUG(dbgs() << "F2I: Failing because of " << *U << "\n");
3440b57cec5SDimitry Andric             Fail = true;
3450b57cec5SDimitry Andric             break;
3460b57cec5SDimitry Andric           }
3470b57cec5SDimitry Andric         }
3480b57cec5SDimitry Andric       }
3490b57cec5SDimitry Andric       if (Fail)
3500b57cec5SDimitry Andric         break;
3510b57cec5SDimitry Andric     }
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric     // If the set was empty, or we failed, or the range is poisonous,
3540b57cec5SDimitry Andric     // bail out.
3550b57cec5SDimitry Andric     if (ECs.member_begin(It) == ECs.member_end() || Fail ||
3560b57cec5SDimitry Andric         R.isFullSet() || R.isSignWrappedSet())
3570b57cec5SDimitry Andric       continue;
3580b57cec5SDimitry Andric     assert(ConvertedToTy && "Must have set the convertedtoty by this point!");
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric     // The number of bits required is the maximum of the upper and
3610b57cec5SDimitry Andric     // lower limits, plus one so it can be signed.
362*0fca6ea1SDimitry Andric     unsigned MinBW = R.getMinSignedBits() + 1;
3630b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "F2I: MinBitwidth=" << MinBW << ", R: " << R << "\n");
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric     // If we've run off the realms of the exactly representable integers,
3660b57cec5SDimitry Andric     // the floating point result will differ from an integer approximation.
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric     // Do we need more bits than are in the mantissa of the type we converted
3690b57cec5SDimitry Andric     // to? semanticsPrecision returns the number of mantissa bits plus one
3700b57cec5SDimitry Andric     // for the sign bit.
3710b57cec5SDimitry Andric     unsigned MaxRepresentableBits
3720b57cec5SDimitry Andric       = APFloat::semanticsPrecision(ConvertedToTy->getFltSemantics()) - 1;
3730b57cec5SDimitry Andric     if (MinBW > MaxRepresentableBits) {
3740b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "F2I: Value not guaranteed to be representable!\n");
3750b57cec5SDimitry Andric       continue;
3760b57cec5SDimitry Andric     }
377*0fca6ea1SDimitry Andric 
378*0fca6ea1SDimitry Andric     // OK, R is known to be representable.
379*0fca6ea1SDimitry Andric     // Pick the smallest legal type that will fit.
380*0fca6ea1SDimitry Andric     Type *Ty = DL.getSmallestLegalIntType(*Ctx, MinBW);
381*0fca6ea1SDimitry Andric     if (!Ty) {
382*0fca6ea1SDimitry Andric       // Every supported target supports 64-bit and 32-bit integers,
383*0fca6ea1SDimitry Andric       // so fallback to a 32 or 64-bit integer if the value fits.
384*0fca6ea1SDimitry Andric       if (MinBW <= 32) {
385*0fca6ea1SDimitry Andric         Ty = Type::getInt32Ty(*Ctx);
386*0fca6ea1SDimitry Andric       } else if (MinBW <= 64) {
387*0fca6ea1SDimitry Andric         Ty = Type::getInt64Ty(*Ctx);
388*0fca6ea1SDimitry Andric       } else {
389*0fca6ea1SDimitry Andric         LLVM_DEBUG(dbgs() << "F2I: Value requires more bits to represent than "
390*0fca6ea1SDimitry Andric                              "the target supports!\n");
3910b57cec5SDimitry Andric         continue;
3920b57cec5SDimitry Andric       }
393*0fca6ea1SDimitry Andric     }
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric     for (auto MI = ECs.member_begin(It), ME = ECs.member_end();
3960b57cec5SDimitry Andric          MI != ME; ++MI)
3970b57cec5SDimitry Andric       convert(*MI, Ty);
3980b57cec5SDimitry Andric     MadeChange = true;
3990b57cec5SDimitry Andric   }
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric   return MadeChange;
4020b57cec5SDimitry Andric }
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric Value *Float2IntPass::convert(Instruction *I, Type *ToTy) {
40506c3fb27SDimitry Andric   if (ConvertedInsts.contains(I))
4060b57cec5SDimitry Andric     // Already converted this instruction.
4070b57cec5SDimitry Andric     return ConvertedInsts[I];
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric   SmallVector<Value*,4> NewOperands;
4100b57cec5SDimitry Andric   for (Value *V : I->operands()) {
4110b57cec5SDimitry Andric     // Don't recurse if we're an instruction that terminates the path.
4120b57cec5SDimitry Andric     if (I->getOpcode() == Instruction::UIToFP ||
4130b57cec5SDimitry Andric         I->getOpcode() == Instruction::SIToFP) {
4140b57cec5SDimitry Andric       NewOperands.push_back(V);
4150b57cec5SDimitry Andric     } else if (Instruction *VI = dyn_cast<Instruction>(V)) {
4160b57cec5SDimitry Andric       NewOperands.push_back(convert(VI, ToTy));
4170b57cec5SDimitry Andric     } else if (ConstantFP *CF = dyn_cast<ConstantFP>(V)) {
4180b57cec5SDimitry Andric       APSInt Val(ToTy->getPrimitiveSizeInBits(), /*isUnsigned=*/false);
4190b57cec5SDimitry Andric       bool Exact;
4200b57cec5SDimitry Andric       CF->getValueAPF().convertToInteger(Val,
4210b57cec5SDimitry Andric                                          APFloat::rmNearestTiesToEven,
4220b57cec5SDimitry Andric                                          &Exact);
4230b57cec5SDimitry Andric       NewOperands.push_back(ConstantInt::get(ToTy, Val));
4240b57cec5SDimitry Andric     } else {
4250b57cec5SDimitry Andric       llvm_unreachable("Unhandled operand type?");
4260b57cec5SDimitry Andric     }
4270b57cec5SDimitry Andric   }
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric   // Now create a new instruction.
4300b57cec5SDimitry Andric   IRBuilder<> IRB(I);
4310b57cec5SDimitry Andric   Value *NewV = nullptr;
4320b57cec5SDimitry Andric   switch (I->getOpcode()) {
4330b57cec5SDimitry Andric   default: llvm_unreachable("Unhandled instruction!");
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric   case Instruction::FPToUI:
4360b57cec5SDimitry Andric     NewV = IRB.CreateZExtOrTrunc(NewOperands[0], I->getType());
4370b57cec5SDimitry Andric     break;
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric   case Instruction::FPToSI:
4400b57cec5SDimitry Andric     NewV = IRB.CreateSExtOrTrunc(NewOperands[0], I->getType());
4410b57cec5SDimitry Andric     break;
4420b57cec5SDimitry Andric 
4430b57cec5SDimitry Andric   case Instruction::FCmp: {
4440b57cec5SDimitry Andric     CmpInst::Predicate P = mapFCmpPred(cast<CmpInst>(I)->getPredicate());
4450b57cec5SDimitry Andric     assert(P != CmpInst::BAD_ICMP_PREDICATE && "Unhandled predicate!");
4460b57cec5SDimitry Andric     NewV = IRB.CreateICmp(P, NewOperands[0], NewOperands[1], I->getName());
4470b57cec5SDimitry Andric     break;
4480b57cec5SDimitry Andric   }
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric   case Instruction::UIToFP:
4510b57cec5SDimitry Andric     NewV = IRB.CreateZExtOrTrunc(NewOperands[0], ToTy);
4520b57cec5SDimitry Andric     break;
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric   case Instruction::SIToFP:
4550b57cec5SDimitry Andric     NewV = IRB.CreateSExtOrTrunc(NewOperands[0], ToTy);
4560b57cec5SDimitry Andric     break;
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric   case Instruction::FNeg:
4590b57cec5SDimitry Andric     NewV = IRB.CreateNeg(NewOperands[0], I->getName());
4600b57cec5SDimitry Andric     break;
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric   case Instruction::FAdd:
4630b57cec5SDimitry Andric   case Instruction::FSub:
4640b57cec5SDimitry Andric   case Instruction::FMul:
4650b57cec5SDimitry Andric     NewV = IRB.CreateBinOp(mapBinOpcode(I->getOpcode()),
4660b57cec5SDimitry Andric                            NewOperands[0], NewOperands[1],
4670b57cec5SDimitry Andric                            I->getName());
4680b57cec5SDimitry Andric     break;
4690b57cec5SDimitry Andric   }
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric   // If we're a root instruction, RAUW.
4720b57cec5SDimitry Andric   if (Roots.count(I))
4730b57cec5SDimitry Andric     I->replaceAllUsesWith(NewV);
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric   ConvertedInsts[I] = NewV;
4760b57cec5SDimitry Andric   return NewV;
4770b57cec5SDimitry Andric }
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric // Perform dead code elimination on the instructions we just modified.
4800b57cec5SDimitry Andric void Float2IntPass::cleanup() {
4810b57cec5SDimitry Andric   for (auto &I : reverse(ConvertedInsts))
4820b57cec5SDimitry Andric     I.first->eraseFromParent();
4830b57cec5SDimitry Andric }
4840b57cec5SDimitry Andric 
4858bcb0991SDimitry Andric bool Float2IntPass::runImpl(Function &F, const DominatorTree &DT) {
4860b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "F2I: Looking at function " << F.getName() << "\n");
4870b57cec5SDimitry Andric   // Clear out all state.
4880b57cec5SDimitry Andric   ECs = EquivalenceClasses<Instruction*>();
4890b57cec5SDimitry Andric   SeenInsts.clear();
4900b57cec5SDimitry Andric   ConvertedInsts.clear();
4910b57cec5SDimitry Andric   Roots.clear();
4920b57cec5SDimitry Andric 
4930b57cec5SDimitry Andric   Ctx = &F.getParent()->getContext();
4940b57cec5SDimitry Andric 
4955ffd83dbSDimitry Andric   findRoots(F, DT);
4960b57cec5SDimitry Andric 
4975ffd83dbSDimitry Andric   walkBackwards();
4980b57cec5SDimitry Andric   walkForwards();
4990b57cec5SDimitry Andric 
500*0fca6ea1SDimitry Andric   const DataLayout &DL = F.getDataLayout();
501*0fca6ea1SDimitry Andric   bool Modified = validateAndTransform(DL);
5020b57cec5SDimitry Andric   if (Modified)
5030b57cec5SDimitry Andric     cleanup();
5040b57cec5SDimitry Andric   return Modified;
5050b57cec5SDimitry Andric }
5060b57cec5SDimitry Andric 
5078bcb0991SDimitry Andric PreservedAnalyses Float2IntPass::run(Function &F, FunctionAnalysisManager &AM) {
5088bcb0991SDimitry Andric   const DominatorTree &DT = AM.getResult<DominatorTreeAnalysis>(F);
5098bcb0991SDimitry Andric   if (!runImpl(F, DT))
5100b57cec5SDimitry Andric     return PreservedAnalyses::all();
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric   PreservedAnalyses PA;
5130b57cec5SDimitry Andric   PA.preserveSet<CFGAnalyses>();
5140b57cec5SDimitry Andric   return PA;
5150b57cec5SDimitry Andric }
516