15 #define DEBUG_TYPE "float2int"
50 cl::desc(
"Max integer bitwidth to consider in float2int"
60 bool runOnFunction(
Function &
F)
override {
64 return Impl.runImpl(F);
78 INITIALIZE_PASS(Float2IntLegacyPass,
"float2int",
"Float to int",
false,
false)
113 case Instruction::FSub:
return Instruction::Sub;
114 case Instruction::FMul:
return Instruction::Mul;
122 if (isa<VectorType>(
I.getType()))
124 switch (
I.getOpcode()) {
126 case Instruction::FPToUI:
127 case Instruction::FPToSI:
130 case Instruction::FCmp:
141 DEBUG(
dbgs() <<
"F2I: " << *I <<
":" << R <<
"\n");
142 if (SeenInsts.find(I) != SeenInsts.end())
143 SeenInsts.find(I)->second = R;
145 SeenInsts.insert(std::make_pair(I, R));
177 std::deque<Instruction*> Worklist(Roots.
begin(), Roots.
end());
178 while (!Worklist.empty()) {
182 if (SeenInsts.find(I) != SeenInsts.end())
193 case Instruction::UIToFP:
194 case Instruction::SIToFP: {
200 seen(I, validateRange(Input.castOp(CastOp,
MaxIntegerBW+1)));
204 case Instruction::FAdd:
205 case Instruction::FSub:
206 case Instruction::FMul:
207 case Instruction::FPToUI:
208 case Instruction::FPToSI:
209 case Instruction::FCmp:
210 seen(I, unknownRange());
217 ECs.unionSets(I, OI);
218 if (SeenInsts.find(I)->second != badRange())
219 Worklist.push_back(OI);
220 }
else if (!isa<ConstantFP>(O)) {
230 void Float2IntPass::walkForwards() {
231 for (
auto &It :
reverse(SeenInsts)) {
232 if (It.second != unknownRange())
236 std::function<ConstantRange(ArrayRef<ConstantRange>)>
Op;
240 case Instruction::UIToFP:
241 case Instruction::SIToFP:
244 case Instruction::FAdd:
245 case Instruction::FSub:
246 case Instruction::FMul:
248 assert(Ops.size() == 2 &&
"its a binary operator!");
250 return Ops[0].binaryOp(BinOp, Ops[1]);
258 case Instruction::FPToUI:
259 case Instruction::FPToSI:
261 assert(Ops.size() == 1 &&
"FPTo[US]I is a unary operator!");
269 case Instruction::FCmp:
271 assert(Ops.size() == 2 &&
"FCmp is a binary operator!");
272 return Ops[0].unionWith(Ops[1]);
281 assert(SeenInsts.find(OI) != SeenInsts.end() &&
282 "def not seen before use!");
283 OpRanges.
push_back(SeenInsts.find(OI)->second);
284 }
else if (
ConstantFP *CF = dyn_cast<ConstantFP>(O)) {
294 const APFloat &F = CF->getValueAPF();
317 CF->getValueAPF().convertToInteger(Int,
328 seen(I,
Op(OpRanges));
333 bool Float2IntPass::validateAndTransform() {
334 bool MadeChange =
false;
337 for (
auto It = ECs.begin(),
E = ECs.end(); It !=
E; ++It) {
340 Type *ConvertedToTy =
nullptr;
343 for (
auto MI = ECs.member_begin(It), ME = ECs.member_end();
346 auto SeenI = SeenInsts.find(I);
347 if (SeenI == SeenInsts.end())
355 if (Roots.
count(I) == 0) {
361 if (!UI || SeenInsts.find(UI) == SeenInsts.end()) {
362 DEBUG(
dbgs() <<
"F2I: Failing because of " << *U <<
"\n");
374 if (ECs.member_begin(It) == ECs.member_end() || Fail ||
377 assert(ConvertedToTy &&
"Must have set the convertedtoty by this point!");
383 DEBUG(
dbgs() <<
"F2I: MinBitwidth=" << MinBW <<
", R: " << R <<
"\n");
391 unsigned MaxRepresentableBits
393 if (MinBW > MaxRepresentableBits) {
394 DEBUG(
dbgs() <<
"F2I: Value not guaranteed to be representable!\n");
398 DEBUG(
dbgs() <<
"F2I: Value requires more than 64 bits to represent!\n");
406 for (
auto MI = ECs.member_begin(It), ME = ECs.member_end();
416 if (ConvertedInsts.find(I) != ConvertedInsts.end())
418 return ConvertedInsts[I];
423 if (I->
getOpcode() == Instruction::UIToFP ||
428 }
else if (
ConstantFP *CF = dyn_cast<ConstantFP>(V)) {
431 CF->getValueAPF().convertToInteger(Val,
442 Value *NewV =
nullptr;
446 case Instruction::FPToUI:
447 NewV = IRB.CreateZExtOrTrunc(NewOperands[0], I->
getType());
450 case Instruction::FPToSI:
451 NewV = IRB.CreateSExtOrTrunc(NewOperands[0], I->
getType());
454 case Instruction::FCmp: {
457 NewV = IRB.CreateICmp(P, NewOperands[0], NewOperands[1], I->
getName());
461 case Instruction::UIToFP:
462 NewV = IRB.CreateZExtOrTrunc(NewOperands[0], ToTy);
465 case Instruction::SIToFP:
466 NewV = IRB.CreateSExtOrTrunc(NewOperands[0], ToTy);
469 case Instruction::FAdd:
470 case Instruction::FSub:
471 case Instruction::FMul:
473 NewOperands[0], NewOperands[1],
482 ConvertedInsts[
I] = NewV;
487 void Float2IntPass::cleanup() {
488 for (
auto &I :
reverse(ConvertedInsts))
497 ConvertedInsts.clear();
504 walkBackwards(Roots);
507 bool Modified = validateAndTransform();
Legacy wrapper pass to provide the GlobalsAAResult object.
opStatus roundToIntegral(roundingMode RM)
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
void push_back(const T &Elt)
This class is the base class for the comparison instructions.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
This is the interface for a simple mod/ref and alias analysis over globals.
uint32_t getBitWidth() const
Get the bit width of this ConstantRange.
size_type count(PtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
FunctionPass * createFloat2IntPass()
0 1 0 0 True if ordered and less than
1 1 1 0 True if unordered or not equal
static IntegerType * getInt64Ty(LLVMContext &C)
bool runImpl(Function &F)
StringRef getName() const
Return a constant reference to the value's name.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
1 0 0 1 True if unordered or equal
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
0 1 0 1 True if ordered and less than or equal
This file implements a class to represent arbitrary precision integral constant values and operations...
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
ConstantRange unionWith(const ConstantRange &CR) const
Return the range that results from the union of this range with another range.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
unsigned getMinSignedBits() const
Get the minimum bit size for this signed APInt.
static CmpInst::Predicate mapFCmpPred(CmpInst::Predicate P)
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
initializer< Ty > init(const Ty &Val)
A set of analyses that are preserved following a run of a transformation pass.
bool isFullSet() const
Return true if this set contains all of the elements possible for this data-type. ...
The instances of the Type class are immutable: once they are created, they are never changed...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
ConstantFP - Floating Point Values [float, double].
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
EquivalenceClasses - This represents a collection of equivalence classes and supports three efficient...
Represent the analysis usage information of a pass.
Analysis pass providing a never-invalidated alias analysis result.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
FunctionPass class - This class is used to implement most global optimizations.
Value * getOperand(unsigned i) const
void initializeFloat2IntLegacyPassPass(PassRegistry &)
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
1 1 0 1 True if unordered, less than, or equal
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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)"))
The largest integer type worth dealing with.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
0 0 1 0 True if ordered and greater than
bool isSignWrappedSet() const
Return true if this set wraps around the INT_MIN of its bitwidth.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
1 1 0 0 True if unordered or less than
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
This class represents a range of values.
const APInt & getLower() const
Return the lower value for this range.
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
const fltSemantics & getFltSemantics() const
static unsigned int semanticsPrecision(const fltSemantics &)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
iterator_range< user_iterator > users()
static Instruction::BinaryOps mapBinOpcode(unsigned Opcode)
static IntegerType * getInt32Ty(LLVMContext &C)
0 1 1 0 True if ordered and operands are unequal
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
void preserve()
Mark an analysis as preserved.
bool hasNoSignedZeros() const
Determine whether the no-signed-zeros flag is set.
1 0 1 0 True if unordered or greater than
const APInt & getUpper() const
Return the upper value for this range.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
unsigned getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
0 0 0 1 True if ordered and equal
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
1 0 1 1 True if unordered, greater than, or equal
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
cmpResult compare(const APFloat &RHS) const
inst_range instructions(Function *F)
A container for analyses that lazily runs them and caches their results.
0 0 1 1 True if ordered and greater than or equal
LLVMContext & getContext() const
Get the global data context.