//===- Float2Int.cpp - Demote floating point ops to work on integers ------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements the Float2Int pass, which aims to demote floating // point operations to work on integers, where that is losslessly possible. // //===----------------------------------------------------------------------===// #include "llvm/Transforms/Scalar/Float2Int.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/GlobalsModRef.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Module.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include <deque> #define DEBUG_TYPE … usingnamespacellvm; // The algorithm is simple. Start at instructions that convert from the // float to the int domain: fptoui, fptosi and fcmp. Walk up the def-use // graph, using an equivalence datastructure to unify graphs that interfere. // // Mappable instructions are those with an integer corrollary that, given // integer domain inputs, produce an integer output; fadd, for example. // // If a non-mappable instruction is seen, this entire def-use graph is marked // as non-transformable. If we see an instruction that converts from the // integer domain to FP domain (uitofp,sitofp), we terminate our walk. /// The largest integer type worth dealing with. static cl::opt<unsigned> MaxIntegerBW("float2int-max-integer-bw", cl::init(64), cl::Hidden, cl::desc("Max integer bitwidth to consider in float2int" "(default=64)")); // Given a FCmp predicate, return a matching ICmp predicate if one // exists, otherwise return BAD_ICMP_PREDICATE. static CmpInst::Predicate mapFCmpPred(CmpInst::Predicate P) { … } // Given a floating point binary operator, return the matching // integer version. static Instruction::BinaryOps mapBinOpcode(unsigned Opcode) { … } // Find the roots - instructions that convert from the FP domain to // integer domain. void Float2IntPass::findRoots(Function &F, const DominatorTree &DT) { … } // Helper - mark I as having been traversed, having range R. void Float2IntPass::seen(Instruction *I, ConstantRange R) { … } // Helper - get a range representing a poison value. ConstantRange Float2IntPass::badRange() { … } ConstantRange Float2IntPass::unknownRange() { … } ConstantRange Float2IntPass::validateRange(ConstantRange R) { … } // The most obvious way to structure the search is a depth-first, eager // search from each root. However, that require direct recursion and so // can only handle small instruction sequences. Instead, we split the search // up into two phases: // - walkBackwards: A breadth-first walk of the use-def graph starting from // the roots. Populate "SeenInsts" with interesting // instructions and poison values if they're obvious and // cheap to compute. Calculate the equivalance set structure // while we're here too. // - walkForwards: Iterate over SeenInsts in reverse order, so we visit // defs before their uses. Calculate the real range info. // Breadth-first walk of the use-def graph; determine the set of nodes // we care about and eagerly determine if some of them are poisonous. void Float2IntPass::walkBackwards() { … } // Calculate result range from operand ranges. // Return std::nullopt if the range cannot be calculated yet. std::optional<ConstantRange> Float2IntPass::calcRange(Instruction *I) { … } // Walk forwards down the list of seen instructions, so we visit defs before // uses. void Float2IntPass::walkForwards() { … } // If there is a valid transform to be done, do it. bool Float2IntPass::validateAndTransform(const DataLayout &DL) { … } Value *Float2IntPass::convert(Instruction *I, Type *ToTy) { … } // Perform dead code elimination on the instructions we just modified. void Float2IntPass::cleanup() { … } bool Float2IntPass::runImpl(Function &F, const DominatorTree &DT) { … } PreservedAnalyses Float2IntPass::run(Function &F, FunctionAnalysisManager &AM) { … }