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