31#define DEBUG_TYPE "float2int"
49 cl::desc(
"Max integer bitwidth to consider in float2int"
84 case Instruction::FAdd:
return Instruction::Add;
85 case Instruction::FSub:
return Instruction::Sub;
86 case Instruction::FMul:
return Instruction::Mul;
100 if (isa<VectorType>(
I.getType()))
102 switch (
I.getOpcode()) {
104 case Instruction::FPToUI:
105 case Instruction::FPToSI:
108 case Instruction::FCmp:
121 auto IT = SeenInsts.find(
I);
122 if (
IT != SeenInsts.end())
123 IT->second = std::move(R);
125 SeenInsts.insert(std::make_pair(
I, std::move(R)));
155void Float2IntPass::walkBackwards() {
156 std::deque<Instruction*> Worklist(Roots.begin(), Roots.end());
157 while (!Worklist.empty()) {
161 if (SeenInsts.contains(
I))
165 switch (
I->getOpcode()) {
172 case Instruction::UIToFP:
173 case Instruction::SIToFP: {
176 unsigned BW =
I->getOperand(0)->getType()->getPrimitiveSizeInBits();
177 auto Input = ConstantRange::getFull(BW);
179 seen(
I, validateRange(Input.castOp(CastOp,
MaxIntegerBW+1)));
183 case Instruction::FNeg:
184 case Instruction::FAdd:
185 case Instruction::FSub:
186 case Instruction::FMul:
187 case Instruction::FPToUI:
188 case Instruction::FPToSI:
189 case Instruction::FCmp:
190 seen(
I, unknownRange());
194 for (
Value *O :
I->operands()) {
197 ECs.unionSets(
I, OI);
198 if (SeenInsts.find(
I)->second != badRange())
199 Worklist.push_back(OI);
200 }
else if (!isa<ConstantFP>(O)) {
210std::optional<ConstantRange> Float2IntPass::calcRange(
Instruction *
I) {
212 for (
Value *O :
I->operands()) {
214 auto OpIt = SeenInsts.find(OI);
215 assert(OpIt != SeenInsts.end() &&
"def not seen before use!");
216 if (OpIt->second == unknownRange())
219 }
else if (
ConstantFP *CF = dyn_cast<ConstantFP>(O)) {
229 const APFloat &
F = CF->getValueAPF();
235 (
F.isZero() &&
F.isNegative() && isa<FPMathOperator>(
I) &&
236 !
I->hasNoSignedZeros()))
247 CF->getValueAPF().convertToInteger(
Int,
256 switch (
I->getOpcode()) {
259 case Instruction::UIToFP:
260 case Instruction::SIToFP:
263 case Instruction::FNeg: {
264 assert(OpRanges.
size() == 1 &&
"FNeg is a unary operator!");
265 unsigned Size = OpRanges[0].getBitWidth();
267 return Zero.sub(OpRanges[0]);
270 case Instruction::FAdd:
271 case Instruction::FSub:
272 case Instruction::FMul: {
273 assert(OpRanges.
size() == 2 &&
"its a binary operator!");
275 return OpRanges[0].binaryOp(BinOp, OpRanges[1]);
282 case Instruction::FPToUI:
283 case Instruction::FPToSI: {
284 assert(OpRanges.
size() == 1 &&
"FPTo[US]I is a unary operator!");
291 case Instruction::FCmp:
292 assert(OpRanges.
size() == 2 &&
"FCmp is a binary operator!");
293 return OpRanges[0].unionWith(OpRanges[1]);
299void Float2IntPass::walkForwards() {
300 std::deque<Instruction *> Worklist;
301 for (
const auto &Pair : SeenInsts)
302 if (Pair.second == unknownRange())
305 while (!Worklist.empty()) {
309 if (std::optional<ConstantRange> Range = calcRange(
I))
312 Worklist.push_front(
I);
317bool Float2IntPass::validateAndTransform() {
318 bool MadeChange =
false;
321 for (
auto It = ECs.begin(),
E = ECs.end(); It !=
E; ++It) {
324 Type *ConvertedToTy =
nullptr;
327 for (
auto MI = ECs.member_begin(It), ME = ECs.member_end();
330 auto SeenI = SeenInsts.find(
I);
331 if (SeenI == SeenInsts.end())
334 R =
R.unionWith(SeenI->second);
339 if (!Roots.contains(
I)) {
342 ConvertedToTy =
I->getType();
343 for (
User *U :
I->users()) {
345 if (!UI || !SeenInsts.contains(UI)) {
358 if (ECs.member_begin(It) == ECs.member_end() ||
Fail ||
359 R.isFullSet() ||
R.isSignWrappedSet())
361 assert(ConvertedToTy &&
"Must have set the convertedtoty by this point!");
365 unsigned MinBW = std::max(
R.getLower().getSignificantBits(),
366 R.getUpper().getSignificantBits()) +
368 LLVM_DEBUG(
dbgs() <<
"F2I: MinBitwidth=" << MinBW <<
", R: " << R <<
"\n");
376 unsigned MaxRepresentableBits
378 if (MinBW > MaxRepresentableBits) {
379 LLVM_DEBUG(
dbgs() <<
"F2I: Value not guaranteed to be representable!\n");
384 dbgs() <<
"F2I: Value requires more than 64 bits to represent!\n");
392 for (
auto MI = ECs.member_begin(It), ME = ECs.member_end();
402 if (ConvertedInsts.contains(
I))
404 return ConvertedInsts[
I];
407 for (
Value *V :
I->operands()) {
409 if (
I->getOpcode() == Instruction::UIToFP ||
410 I->getOpcode() == Instruction::SIToFP) {
412 }
else if (
Instruction *VI = dyn_cast<Instruction>(V)) {
414 }
else if (
ConstantFP *CF = dyn_cast<ConstantFP>(V)) {
417 CF->getValueAPF().convertToInteger(Val,
428 Value *NewV =
nullptr;
429 switch (
I->getOpcode()) {
432 case Instruction::FPToUI:
433 NewV = IRB.CreateZExtOrTrunc(NewOperands[0],
I->getType());
436 case Instruction::FPToSI:
437 NewV = IRB.CreateSExtOrTrunc(NewOperands[0],
I->getType());
440 case Instruction::FCmp: {
443 NewV = IRB.CreateICmp(
P, NewOperands[0], NewOperands[1],
I->getName());
447 case Instruction::UIToFP:
448 NewV = IRB.CreateZExtOrTrunc(NewOperands[0], ToTy);
451 case Instruction::SIToFP:
452 NewV = IRB.CreateSExtOrTrunc(NewOperands[0], ToTy);
455 case Instruction::FNeg:
456 NewV = IRB.CreateNeg(NewOperands[0],
I->getName());
459 case Instruction::FAdd:
460 case Instruction::FSub:
461 case Instruction::FMul:
463 NewOperands[0], NewOperands[1],
470 I->replaceAllUsesWith(NewV);
472 ConvertedInsts[
I] = NewV;
477void Float2IntPass::cleanup() {
478 for (
auto &
I :
reverse(ConvertedInsts))
479 I.first->eraseFromParent();
483 LLVM_DEBUG(
dbgs() <<
"F2I: Looking at function " <<
F.getName() <<
"\n");
487 ConvertedInsts.clear();
490 Ctx = &
F.getParent()->getContext();
497 bool Modified = validateAndTransform();
This file implements a class to represent arbitrary precision integral constant values and operations...
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static CmpInst::Predicate mapFCmpPred(CmpInst::Predicate P)
static Instruction::BinaryOps mapBinOpcode(unsigned Opcode)
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.
This is the interface for a simple mod/ref and alias analysis over globals.
Module.h This file contains the declarations for the Module class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
opStatus roundToIntegral(roundingMode RM)
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
An arbitrary precision integer that knows its signedness.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
LLVM Basic Block Representation.
Represents analyses that only rely on functions' control flow.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
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.
This class represents a range of values.
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
EquivalenceClasses - This represents a collection of equivalence classes and supports three efficient...
bool runImpl(Function &F, const DominatorTree &DT)
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void preserveSet()
Mark an analysis set as preserved.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
The instances of the Type class are immutable: once they are created, they are never changed.
const fltSemantics & getFltSemantics() const
static IntegerType * getInt32Ty(LLVMContext &C)
static IntegerType * getInt64Ty(LLVMContext &C)
TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
LLVM Value Representation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Predicate getPredicate(unsigned Condition, unsigned Hint)
Return predicate consisting of specified condition and hint bits.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto reverse(ContainerTy &&C)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static constexpr roundingMode rmNearestTiesToEven
static unsigned int semanticsPrecision(const fltSemantics &)