Index: include/llvm/InitializePasses.h =================================================================== --- include/llvm/InitializePasses.h +++ include/llvm/InitializePasses.h @@ -124,7 +124,7 @@ void initializeExternalAAWrapperPassPass(PassRegistry&); void initializeFinalizeMachineBundlesPass(PassRegistry&); void initializeFlattenCFGPassPass(PassRegistry&); -void initializeFloat2IntPass(PassRegistry&); +void initializeFloat2IntLegacyPassPass(PassRegistry&); void initializeForceFunctionAttrsLegacyPassPass(PassRegistry&); void initializeForwardControlFlowIntegrityPass(PassRegistry&); void initializeFuncletLayoutPass(PassRegistry &); Index: include/llvm/Transforms/Scalar/Float2Int.h =================================================================== --- include/llvm/Transforms/Scalar/Float2Int.h +++ include/llvm/Transforms/Scalar/Float2Int.h @@ -0,0 +1,52 @@ +//===-- Float2Int.h - Demote floating point ops to work on integers -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the Float2Int pass, which aims to demote floating +// point operations to work on integers, where that is losslessly possible. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_SCALAR_FLOAT2INT_H +#define LLVM_TRANSFORMS_SCALAR_FLOAT2INT_H + +#include "llvm/ADT/EquivalenceClasses.h" +#include "llvm/ADT/MapVector.h" +#include "llvm/IR/ConstantRange.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { +/// Pass to remove unused function declarations. +class Float2IntPass : public PassInfoMixin { +public: + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); + + // Glue for old PM. + bool runImpl(Function &F); + +private: + void findRoots(Function &F, SmallPtrSet &Roots); + ConstantRange seen(Instruction *I, ConstantRange R); + ConstantRange badRange(); + ConstantRange unknownRange(); + ConstantRange validateRange(ConstantRange R); + void walkBackwards(const SmallPtrSetImpl &Roots); + void walkForwards(); + bool validateAndTransform(); + Value *convert(Instruction *I, Type *ToTy); + void cleanup(); + + MapVector SeenInsts; + SmallPtrSet Roots; + EquivalenceClasses ECs; + MapVector ConvertedInsts; + LLVMContext *Ctx; +}; +} +#endif // LLVM_TRANSFORMS_SCALAR_FLOAT2INT_H Index: lib/Passes/PassBuilder.cpp =================================================================== --- lib/Passes/PassBuilder.cpp +++ lib/Passes/PassBuilder.cpp @@ -75,6 +75,7 @@ #include "llvm/Transforms/Scalar/DCE.h" #include "llvm/Transforms/Scalar/DeadStoreElimination.h" #include "llvm/Transforms/Scalar/EarlyCSE.h" +#include "llvm/Transforms/Scalar/Float2Int.h" #include "llvm/Transforms/Scalar/GVN.h" #include "llvm/Transforms/Scalar/GuardWidening.h" #include "llvm/Transforms/Scalar/IndVarSimplify.h" Index: lib/Passes/PassRegistry.def =================================================================== --- lib/Passes/PassRegistry.def +++ lib/Passes/PassRegistry.def @@ -129,6 +129,7 @@ FUNCTION_PASS("early-cse", EarlyCSEPass()) FUNCTION_PASS("instcombine", InstCombinePass()) FUNCTION_PASS("invalidate", InvalidateAllAnalysesPass()) +FUNCTION_PASS("float2int", Float2IntPass()) FUNCTION_PASS("no-op-function", NoOpFunctionPass()) FUNCTION_PASS("loweratomic", LowerAtomicPass()) FUNCTION_PASS("lower-expect", LowerExpectIntrinsicPass()) Index: lib/Transforms/Scalar/Float2Int.cpp =================================================================== --- lib/Transforms/Scalar/Float2Int.cpp +++ lib/Transforms/Scalar/Float2Int.cpp @@ -13,14 +13,13 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "float2int" + +#include "llvm/Transforms/Scalar/Float2Int.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" -#include "llvm/ADT/EquivalenceClasses.h" -#include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/GlobalsModRef.h" -#include "llvm/IR/ConstantRange.h" #include "llvm/IR/Constants.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstIterator.h" @@ -52,10 +51,10 @@ "(default=64)")); namespace { - struct Float2Int : public FunctionPass { + struct Float2IntLegacyPass : public FunctionPass { static char ID; // Pass identification, replacement for typeid - Float2Int() : FunctionPass(ID) { - initializeFloat2IntPass(*PassRegistry::getPassRegistry()); + Float2IntLegacyPass() : FunctionPass(ID) { + initializeFloat2IntLegacyPassPass(*PassRegistry::getPassRegistry()); } bool runOnFunction(Function &F) override; @@ -63,30 +62,17 @@ AU.setPreservesCFG(); AU.addPreserved(); } - - void findRoots(Function &F, SmallPtrSet &Roots); - ConstantRange seen(Instruction *I, ConstantRange R); - ConstantRange badRange(); - ConstantRange unknownRange(); - ConstantRange validateRange(ConstantRange R); - void walkBackwards(const SmallPtrSetImpl &Roots); - void walkForwards(); - bool validateAndTransform(); - Value *convert(Instruction *I, Type *ToTy); - void cleanup(); - - MapVector SeenInsts; - SmallPtrSet Roots; - EquivalenceClasses ECs; - MapVector ConvertedInsts; - LLVMContext *Ctx; }; + + Float2IntPass Impl; } -char Float2Int::ID = 0; -INITIALIZE_PASS_BEGIN(Float2Int, "float2int", "Float to int", false, false) +char Float2IntLegacyPass::ID = 0; +INITIALIZE_PASS_BEGIN(Float2IntLegacyPass, "float2int", "Float to int", false, + false) INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass) -INITIALIZE_PASS_END(Float2Int, "float2int", "Float to int", false, false) +INITIALIZE_PASS_END(Float2IntLegacyPass, "float2int", "Float to int", false, + false) // Given a FCmp predicate, return a matching ICmp predicate if one // exists, otherwise return BAD_ICMP_PREDICATE. @@ -128,7 +114,7 @@ // Find the roots - instructions that convert from the FP domain to // integer domain. -void Float2Int::findRoots(Function &F, SmallPtrSet &Roots) { +void Float2IntPass::findRoots(Function &F, SmallPtrSet &Roots) { for (auto &I : instructions(F)) { if (isa(I.getType())) continue; @@ -148,7 +134,7 @@ } // Helper - mark I as having been traversed, having range R. -ConstantRange Float2Int::seen(Instruction *I, ConstantRange R) { +ConstantRange Float2IntPass::seen(Instruction *I, ConstantRange R) { DEBUG(dbgs() << "F2I: " << *I << ":" << R << "\n"); if (SeenInsts.find(I) != SeenInsts.end()) SeenInsts.find(I)->second = R; @@ -158,13 +144,13 @@ } // Helper - get a range representing a poison value. -ConstantRange Float2Int::badRange() { +ConstantRange Float2IntPass::badRange() { return ConstantRange(MaxIntegerBW + 1, true); } -ConstantRange Float2Int::unknownRange() { +ConstantRange Float2IntPass::unknownRange() { return ConstantRange(MaxIntegerBW + 1, false); } -ConstantRange Float2Int::validateRange(ConstantRange R) { +ConstantRange Float2IntPass::validateRange(ConstantRange R) { if (R.getBitWidth() > MaxIntegerBW + 1) return badRange(); return R; @@ -184,7 +170,7 @@ // 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 Float2Int::walkBackwards(const SmallPtrSetImpl &Roots) { +void Float2IntPass::walkBackwards(const SmallPtrSetImpl &Roots) { std::deque Worklist(Roots.begin(), Roots.end()); while (!Worklist.empty()) { Instruction *I = Worklist.back(); @@ -245,7 +231,7 @@ // Walk forwards down the list of seen instructions, so we visit defs before // uses. -void Float2Int::walkForwards() { +void Float2IntPass::walkForwards() { for (auto &It : reverse(SeenInsts)) { if (It.second != unknownRange()) continue; @@ -356,7 +342,7 @@ } // If there is a valid transform to be done, do it. -bool Float2Int::validateAndTransform() { +bool Float2IntPass::validateAndTransform() { bool MadeChange = false; // Iterate over every disjoint partition of the def-use graph. @@ -438,7 +424,7 @@ return MadeChange; } -Value *Float2Int::convert(Instruction *I, Type *ToTy) { +Value *Float2IntPass::convert(Instruction *I, Type *ToTy) { if (ConvertedInsts.find(I) != ConvertedInsts.end()) // Already converted this instruction. return ConvertedInsts[I]; @@ -510,15 +496,12 @@ } // Perform dead code elimination on the instructions we just modified. -void Float2Int::cleanup() { +void Float2IntPass::cleanup() { for (auto &I : reverse(ConvertedInsts)) I.first->eraseFromParent(); } -bool Float2Int::runOnFunction(Function &F) { - if (skipFunction(F)) - return false; - +bool Float2IntPass::runImpl(Function &F) { DEBUG(dbgs() << "F2I: Looking at function " << F.getName() << "\n"); // Clear out all state. ECs = EquivalenceClasses(); @@ -539,4 +522,26 @@ return Modified; } -FunctionPass *llvm::createFloat2IntPass() { return new Float2Int(); } + +bool Float2IntLegacyPass::runOnFunction(Function &F) { + if (skipFunction(F)) + return false; + + return Impl.runImpl(F); +} + +namespace llvm { +FunctionPass *createFloat2IntPass() { return new Float2IntLegacyPass(); } + +PreservedAnalyses Float2IntPass::run(Function &F, FunctionAnalysisManager &) { + //FIXME: skipFunction is not currently supported in the new PM. + if (!Impl.runImpl(F)) + return PreservedAnalyses::all(); + else { + //FIXME: setPreservesCFG is not currently supported in the new PM. + PreservedAnalyses PA; + PA.preserve(); + return PA; + } +} +} // End namespace llvm Index: lib/Transforms/Scalar/Scalar.cpp =================================================================== --- lib/Transforms/Scalar/Scalar.cpp +++ lib/Transforms/Scalar/Scalar.cpp @@ -84,7 +84,7 @@ initializeLoadCombinePass(Registry); initializePlaceBackedgeSafepointsImplPass(Registry); initializePlaceSafepointsPass(Registry); - initializeFloat2IntPass(Registry); + initializeFloat2IntLegacyPassPass(Registry); initializeLoopDistributePass(Registry); initializeLoopLoadEliminationPass(Registry); initializeLoopSimplifyCFGLegacyPassPass(Registry); Index: test/Transforms/Float2Int/basic.ll =================================================================== --- test/Transforms/Float2Int/basic.ll +++ test/Transforms/Float2Int/basic.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -float2int -S | FileCheck %s +; RUN: opt < %s -passes='float2int' -S | FileCheck %s ; ; Positive tests