Go to the documentation of this file.
31 #define DEBUG_TYPE "float2int"
49 cl::desc(
"Max integer bitwidth to consider in float2int"
63 const DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
64 return Impl.runImpl(
F, DT);
79 INITIALIZE_PASS(Float2IntLegacyPass,
"float2int",
"Float to int",
false,
false)
114 case Instruction::FSub:
return Instruction::Sub;
129 if (isa<VectorType>(
I.getType()))
131 switch (
I.getOpcode()) {
133 case Instruction::FPToUI:
134 case Instruction::FPToSI:
137 case Instruction::FCmp:
150 auto IT = SeenInsts.find(
I);
151 if (
IT != SeenInsts.end())
154 SeenInsts.insert(std::make_pair(
I,
std::move(R)));
184 void Float2IntPass::walkBackwards() {
185 std::deque<Instruction*> Worklist(Roots.begin(), Roots.end());
186 while (!Worklist.empty()) {
190 if (SeenInsts.find(
I) != SeenInsts.end())
194 switch (
I->getOpcode()) {
201 case Instruction::UIToFP:
202 case Instruction::SIToFP: {
205 unsigned BW =
I->getOperand(0)->getType()->getPrimitiveSizeInBits();
206 auto Input = ConstantRange::getFull(BW);
212 case Instruction::FNeg:
213 case Instruction::FAdd:
214 case Instruction::FSub:
215 case Instruction::FMul:
216 case Instruction::FPToUI:
217 case Instruction::FPToSI:
218 case Instruction::FCmp:
219 seen(
I, unknownRange());
223 for (
Value *
O :
I->operands()) {
226 ECs.unionSets(
I, OI);
227 if (SeenInsts.find(
I)->second != badRange())
228 Worklist.push_back(OI);
229 }
else if (!isa<ConstantFP>(
O)) {
241 for (
Value *
O :
I->operands()) {
243 auto OpIt = SeenInsts.find(OI);
244 assert(OpIt != SeenInsts.end() &&
"def not seen before use!");
245 if (OpIt->second == unknownRange())
247 OpRanges.push_back(OpIt->second);
248 }
else if (
ConstantFP *CF = dyn_cast<ConstantFP>(
O)) {
258 const APFloat &
F = CF->getValueAPF();
264 (
F.isZero() &&
F.isNegative() && isa<FPMathOperator>(
I) &&
265 !
I->hasNoSignedZeros()))
276 CF->getValueAPF().convertToInteger(Int,
285 switch (
I->getOpcode()) {
288 case Instruction::UIToFP:
289 case Instruction::SIToFP:
292 case Instruction::FNeg: {
293 assert(OpRanges.size() == 1 &&
"FNeg is a unary operator!");
294 unsigned Size = OpRanges[0].getBitWidth();
296 return Zero.sub(OpRanges[0]);
299 case Instruction::FAdd:
300 case Instruction::FSub:
301 case Instruction::FMul: {
302 assert(OpRanges.size() == 2 &&
"its a binary operator!");
304 return OpRanges[0].binaryOp(BinOp, OpRanges[1]);
311 case Instruction::FPToUI:
312 case Instruction::FPToSI: {
313 assert(OpRanges.size() == 1 &&
"FPTo[US]I is a unary operator!");
320 case Instruction::FCmp:
321 assert(OpRanges.size() == 2 &&
"FCmp is a binary operator!");
322 return OpRanges[0].unionWith(OpRanges[1]);
328 void Float2IntPass::walkForwards() {
329 std::deque<Instruction *> Worklist;
330 for (
const auto &Pair : SeenInsts)
331 if (Pair.second == unknownRange())
332 Worklist.push_back(Pair.first);
334 while (!Worklist.empty()) {
341 Worklist.push_front(
I);
346 bool Float2IntPass::validateAndTransform() {
347 bool MadeChange =
false;
350 for (
auto It = ECs.begin(),
E = ECs.end(); It !=
E; ++It) {
353 Type *ConvertedToTy =
nullptr;
356 for (
auto MI = ECs.member_begin(It), ME = ECs.member_end();
359 auto SeenI = SeenInsts.find(
I);
360 if (SeenI == SeenInsts.end())
363 R =
R.unionWith(SeenI->second);
368 if (!Roots.contains(
I)) {
371 ConvertedToTy =
I->getType();
372 for (
User *U :
I->users()) {
374 if (!UI || SeenInsts.find(UI) == SeenInsts.end()) {
387 if (ECs.member_begin(It) == ECs.member_end() ||
Fail ||
388 R.isFullSet() ||
R.isSignWrappedSet())
390 assert(ConvertedToTy &&
"Must have set the convertedtoty by this point!");
394 unsigned MinBW =
std::max(
R.getLower().getMinSignedBits(),
395 R.getUpper().getMinSignedBits()) + 1;
396 LLVM_DEBUG(
dbgs() <<
"F2I: MinBitwidth=" << MinBW <<
", R: " << R <<
"\n");
404 unsigned MaxRepresentableBits
406 if (MinBW > MaxRepresentableBits) {
407 LLVM_DEBUG(
dbgs() <<
"F2I: Value not guaranteed to be representable!\n");
412 dbgs() <<
"F2I: Value requires more than 64 bits to represent!\n");
420 for (
auto MI = ECs.member_begin(It), ME = ECs.member_end();
430 if (ConvertedInsts.find(
I) != ConvertedInsts.end())
432 return ConvertedInsts[
I];
435 for (
Value *V :
I->operands()) {
437 if (
I->getOpcode() == Instruction::UIToFP ||
438 I->getOpcode() == Instruction::SIToFP) {
439 NewOperands.push_back(V);
441 NewOperands.push_back(convert(
VI, ToTy));
442 }
else if (
ConstantFP *CF = dyn_cast<ConstantFP>(V)) {
445 CF->getValueAPF().convertToInteger(Val,
456 Value *NewV =
nullptr;
457 switch (
I->getOpcode()) {
460 case Instruction::FPToUI:
461 NewV = IRB.CreateZExtOrTrunc(NewOperands[0],
I->getType());
464 case Instruction::FPToSI:
465 NewV = IRB.CreateSExtOrTrunc(NewOperands[0],
I->getType());
468 case Instruction::FCmp: {
471 NewV = IRB.CreateICmp(
P, NewOperands[0], NewOperands[1],
I->getName());
475 case Instruction::UIToFP:
476 NewV = IRB.CreateZExtOrTrunc(NewOperands[0], ToTy);
479 case Instruction::SIToFP:
480 NewV = IRB.CreateSExtOrTrunc(NewOperands[0], ToTy);
483 case Instruction::FNeg:
484 NewV = IRB.CreateNeg(NewOperands[0],
I->getName());
487 case Instruction::FAdd:
488 case Instruction::FSub:
489 case Instruction::FMul:
491 NewOperands[0], NewOperands[1],
498 I->replaceAllUsesWith(NewV);
500 ConvertedInsts[
I] = NewV;
505 void Float2IntPass::cleanup() {
506 for (
auto &
I :
reverse(ConvertedInsts))
507 I.first->eraseFromParent();
511 LLVM_DEBUG(
dbgs() <<
"F2I: Looking at function " <<
F.getName() <<
"\n");
515 ConvertedInsts.clear();
518 Ctx = &
F.getParent()->getContext();
525 bool Modified = validateAndTransform();
A set of analyses that are preserved following a run of a transformation pass.
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
This is an optimization pass for GlobalISel generic memory operations.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
EquivalenceClasses - This represents a collection of equivalence classes and supports three efficient...
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
const fltSemantics & getFltSemantics() const
void initializeFloat2IntLegacyPassPass(PassRegistry &)
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
@ ICMP_SGT
signed greater than
The instances of the Type class are immutable: once they are created, they are never changed.
auto reverse(ContainerTy &&C, std::enable_if_t< has_rbegin< ContainerTy >::value > *=nullptr)
@ ICMP_SLE
signed less or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
static IntegerType * getInt32Ty(LLVMContext &C)
LLVM Basic Block Representation.
@ FCMP_ULT
1 1 0 0 True if unordered or less than
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createFloat2IntPass()
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Represent the analysis usage information of a pass.
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
Legacy analysis pass which computes a DominatorTree.
An arbitrary precision integer that knows its signedness.
ConstantFP - Floating Point Values [float, double].
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.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
static Instruction::BinaryOps mapBinOpcode(unsigned Opcode)
This class is the base class for the comparison instructions.
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
opStatus roundToIntegral(roundingMode RM)
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
initializer< Ty > init(const Ty &Val)
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::ZeroOrMore, cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
@ ICMP_SLT
signed less than
void setPreservesCFG()
This function should be called by the pass, iff they do not:
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Represents analyses that only rely on functions' control flow.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
bool runImpl(Function &F, const DominatorTree &DT)
static bool runOnFunction(Function &F, bool PostInlining)
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
static IntegerType * getInt64Ty(LLVMContext &C)
Predicate getPredicate(unsigned Condition, unsigned Hint)
Return predicate consisting of specified condition and hint bits.
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.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
static CmpInst::Predicate mapFCmpPred(CmpInst::Predicate P)
@ ICMP_SGE
signed greater or equal
This class represents a range of values.
Analysis pass which computes a DominatorTree.
static constexpr roundingMode rmNearestTiesToEven
void preserveSet()
Mark an analysis set as preserved.
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
static unsigned int semanticsPrecision(const fltSemantics &)
Legacy wrapper pass to provide the GlobalsAAResult object.
Align max(MaybeAlign Lhs, Align Rhs)
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
A container for analyses that lazily runs them and caches their results.
FunctionPass class - This class is used to implement most global optimizations.
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
AnalysisUsage & addRequired()
LLVM Value Representation.
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.