//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "float2int"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/EquivalenceClasses.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/EquivalenceClasses.h"
#include "llvm/ADT/MapVector.h"
-#include "llvm/IR/Constants.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"
#include "llvm/IR/Instructions.h"
-#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Scalar.h"
-#include <functional> // For std::function
#include <deque>
+#include <functional> // For std::function
using namespace llvm;
// The algorithm is simple. Start at instructions that convert from the
// 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
+// 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.
bool runOnFunction(Function &F) override;
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesCFG();
+ AU.addPreserved<GlobalsAAWrapperPass>();
}
void findRoots(Function &F, SmallPtrSet<Instruction*,8> &Roots);
}
char Float2Int::ID = 0;
-INITIALIZE_PASS(Float2Int, "float2int", "Float to int", false, false)
+INITIALIZE_PASS_BEGIN(Float2Int, "float2int", "Float to int", false, false)
+INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
+INITIALIZE_PASS_END(Float2Int, "float2int", "Float to int", false, false)
// Given a FCmp predicate, return a matching ICmp predicate if one
// exists, otherwise return BAD_ICMP_PREDICATE.
// Find the roots - instructions that convert from the FP domain to
// integer domain.
void Float2Int::findRoots(Function &F, SmallPtrSet<Instruction*,8> &Roots) {
- for (auto &I : inst_range(F)) {
+ for (auto &I : instructions(F)) {
switch (I.getOpcode()) {
default: break;
case Instruction::FPToUI:
// - 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
+// 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<Instruction*> &Roots) {
std::deque<Instruction*> Worklist(Roots.begin(), Roots.end());
default:
// Path terminated uncleanly.
seen(I, badRange());
- continue;
+ break;
case Instruction::UIToFP: {
// Path terminated cleanly.
case Instruction::FPToUI:
case Instruction::FPToSI:
case Instruction::FCmp:
+ seen(I, unknownRange());
break;
}
-
- seen(I, unknownRange());
+
for (Value *O : I->operands()) {
if (Instruction *OI = dyn_cast<Instruction>(O)) {
// Unify def-use chains if they interfere.
ECs.unionSets(I, OI);
- Worklist.push_back(OI);
+ if (SeenInsts.find(I)->second != badRange())
+ Worklist.push_back(OI);
} else if (!isa<ConstantFP>(O)) {
// Not an instruction or ConstantFP? we can't do anything.
seen(I, badRange());
- break;
}
}
}
// Walk forwards down the list of seen instructions, so we visit defs before
// uses.
void Float2Int::walkForwards() {
- for (auto It = SeenInsts.rbegin(), E = SeenInsts.rend(); It != E; ++It) {
- if (It->second != unknownRange())
+ for (auto &It : make_range(SeenInsts.rbegin(), SeenInsts.rend())) {
+ if (It.second != unknownRange())
continue;
- Instruction *I = It->first;
+ Instruction *I = It.first;
std::function<ConstantRange(ArrayRef<ConstantRange>)> Op;
switch (I->getOpcode()) {
// FIXME: Handle select and phi nodes.
for (Value *O : I->operands()) {
if (Instruction *OI = dyn_cast<Instruction>(O)) {
assert(SeenInsts.find(OI) != SeenInsts.end() &&
- "def not seen before use!");
+ "def not seen before use!");
OpRanges.push_back(SeenInsts.find(OI)->second);
} else if (ConstantFP *CF = dyn_cast<ConstantFP>(O)) {
// Work out if the floating point number can be losslessly represented
APFloat F = CF->getValueAPF();
// First, weed out obviously incorrect values. Non-finite numbers
- // can't be represented and neither can negative zero, unless
+ // can't be represented and neither can negative zero, unless
// we're in fast math mode.
if (!F.isFinite() ||
(F.isZero() && F.isNegative() && isa<FPMathOperator>(I) &&
- !I->hasNoSignedZeros())) {
+ !I->hasNoSignedZeros())) {
seen(I, badRange());
Abort = true;
break;
MI != ME; ++MI) {
Instruction *I = *MI;
auto SeenI = SeenInsts.find(I);
- assert (SeenI != SeenInsts.end() && "Didn't see this instruction?");
+ if (SeenI == SeenInsts.end())
+ continue;
R = R.unionWith(SeenI->second);
// We need to ensure I has no users that have not been seen.
R.isFullSet() || R.isSignWrappedSet())
continue;
assert(ConvertedToTy && "Must have set the convertedtoty by this point!");
-
+
// The number of bits required is the maximum of the upper and
// lower limits, plus one so it can be signed.
unsigned MinBW = std::max(R.getLower().getMinSignedBits(),
} else if (Instruction *VI = dyn_cast<Instruction>(V)) {
NewOperands.push_back(convert(VI, ToTy));
} else if (ConstantFP *CF = dyn_cast<ConstantFP>(V)) {
- APSInt Val(ToTy->getPrimitiveSizeInBits(), true);
+ APSInt Val(ToTy->getPrimitiveSizeInBits(), /*IsUnsigned=*/false);
bool Exact;
CF->getValueAPF().convertToInteger(Val,
APFloat::rmNearestTiesToEven,
// Perform dead code elimination on the instructions we just modified.
void Float2Int::cleanup() {
- for (auto I = ConvertedInsts.rbegin(), E = ConvertedInsts.rend();
- I != E; ++I)
- I->first->eraseFromParent();
+ for (auto &I : make_range(ConvertedInsts.rbegin(), ConvertedInsts.rend()))
+ I.first->eraseFromParent();
}
bool Float2Int::runOnFunction(Function &F) {
+ if (skipOptnoneFunction(F))
+ return false;
+
DEBUG(dbgs() << "F2I: Looking at function " << F.getName() << "\n");
// Clear out all state.
ECs = EquivalenceClasses<Instruction*>();
return Modified;
}
-FunctionPass *llvm::createFloat2IntPass() {
- return new Float2Int();
-}
-
+FunctionPass *llvm::createFloat2IntPass() { return new Float2Int(); }