28#define DEBUG_TYPE "float2int"
46 cl::desc(
"Max integer bitwidth to consider in float2int"
81 case Instruction::FAdd:
return Instruction::Add;
82 case Instruction::FSub:
return Instruction::Sub;
83 case Instruction::FMul:
return Instruction::Mul;
97 if (isa<VectorType>(
I.getType()))
99 switch (
I.getOpcode()) {
101 case Instruction::FPToUI:
102 case Instruction::FPToSI:
105 case Instruction::FCmp:
118 SeenInsts.insert_or_assign(
I, std::move(R));
148void Float2IntPass::walkBackwards() {
149 std::deque<Instruction*> Worklist(Roots.begin(), Roots.end());
150 while (!Worklist.empty()) {
154 if (SeenInsts.contains(
I))
158 switch (
I->getOpcode()) {
165 case Instruction::UIToFP:
166 case Instruction::SIToFP: {
169 unsigned BW =
I->getOperand(0)->getType()->getPrimitiveSizeInBits();
170 auto Input = ConstantRange::getFull(BW);
172 seen(
I, validateRange(Input.castOp(CastOp,
MaxIntegerBW+1)));
176 case Instruction::FNeg:
177 case Instruction::FAdd:
178 case Instruction::FSub:
179 case Instruction::FMul:
180 case Instruction::FPToUI:
181 case Instruction::FPToSI:
182 case Instruction::FCmp:
183 seen(
I, unknownRange());
187 for (
Value *O :
I->operands()) {
190 ECs.unionSets(
I, OI);
191 if (SeenInsts.find(
I)->second != badRange())
192 Worklist.push_back(OI);
193 }
else if (!isa<ConstantFP>(O)) {
203std::optional<ConstantRange> Float2IntPass::calcRange(
Instruction *
I) {
205 for (
Value *O :
I->operands()) {
207 auto OpIt = SeenInsts.find(OI);
208 assert(OpIt != SeenInsts.end() &&
"def not seen before use!");
209 if (OpIt->second == unknownRange())
212 }
else if (
ConstantFP *CF = dyn_cast<ConstantFP>(O)) {
222 const APFloat &
F = CF->getValueAPF();
228 (
F.isZero() &&
F.isNegative() && isa<FPMathOperator>(
I) &&
229 !
I->hasNoSignedZeros()))
240 CF->getValueAPF().convertToInteger(
Int,
249 switch (
I->getOpcode()) {
252 case Instruction::UIToFP:
253 case Instruction::SIToFP:
256 case Instruction::FNeg: {
257 assert(OpRanges.
size() == 1 &&
"FNeg is a unary operator!");
258 unsigned Size = OpRanges[0].getBitWidth();
260 return Zero.sub(OpRanges[0]);
263 case Instruction::FAdd:
264 case Instruction::FSub:
265 case Instruction::FMul: {
266 assert(OpRanges.
size() == 2 &&
"its a binary operator!");
268 return OpRanges[0].binaryOp(BinOp, OpRanges[1]);
275 case Instruction::FPToUI:
276 case Instruction::FPToSI: {
277 assert(OpRanges.
size() == 1 &&
"FPTo[US]I is a unary operator!");
284 case Instruction::FCmp:
285 assert(OpRanges.
size() == 2 &&
"FCmp is a binary operator!");
286 return OpRanges[0].unionWith(OpRanges[1]);
292void Float2IntPass::walkForwards() {
293 std::deque<Instruction *> Worklist;
294 for (
const auto &Pair : SeenInsts)
295 if (Pair.second == unknownRange())
298 while (!Worklist.empty()) {
302 if (std::optional<ConstantRange>
Range = calcRange(
I))
305 Worklist.push_front(
I);
310bool Float2IntPass::validateAndTransform(
const DataLayout &
DL) {
311 bool MadeChange =
false;
314 for (
auto It = ECs.begin(), E = ECs.end(); It != E; ++It) {
317 Type *ConvertedToTy =
nullptr;
320 for (
auto MI = ECs.member_begin(It), ME = ECs.member_end();
323 auto SeenI = SeenInsts.find(
I);
324 if (SeenI == SeenInsts.end())
327 R =
R.unionWith(SeenI->second);
332 if (!Roots.contains(
I)) {
335 ConvertedToTy =
I->getType();
336 for (
User *U :
I->users()) {
338 if (!UI || !SeenInsts.contains(UI)) {
351 if (ECs.member_begin(It) == ECs.member_end() ||
Fail ||
352 R.isFullSet() ||
R.isSignWrappedSet())
354 assert(ConvertedToTy &&
"Must have set the convertedtoty by this point!");
358 unsigned MinBW =
R.getMinSignedBits() + 1;
359 LLVM_DEBUG(
dbgs() <<
"F2I: MinBitwidth=" << MinBW <<
", R: " << R <<
"\n");
367 unsigned MaxRepresentableBits
369 if (MinBW > MaxRepresentableBits) {
370 LLVM_DEBUG(
dbgs() <<
"F2I: Value not guaranteed to be representable!\n");
376 Type *Ty =
DL.getSmallestLegalIntType(*Ctx, MinBW);
382 }
else if (MinBW <= 64) {
385 LLVM_DEBUG(
dbgs() <<
"F2I: Value requires more bits to represent than "
386 "the target supports!\n");
391 for (
auto MI = ECs.member_begin(It), ME = ECs.member_end();
401 if (
auto It = ConvertedInsts.find(
I); It != ConvertedInsts.end())
406 for (
Value *V :
I->operands()) {
408 if (
I->getOpcode() == Instruction::UIToFP ||
409 I->getOpcode() == Instruction::SIToFP) {
411 }
else if (
Instruction *VI = dyn_cast<Instruction>(V)) {
413 }
else if (
ConstantFP *CF = dyn_cast<ConstantFP>(V)) {
416 CF->getValueAPF().convertToInteger(Val,
419 NewOperands.
push_back(ConstantInt::get(ToTy, Val));
427 Value *NewV =
nullptr;
428 switch (
I->getOpcode()) {
431 case Instruction::FPToUI:
432 NewV = IRB.CreateZExtOrTrunc(NewOperands[0],
I->getType());
435 case Instruction::FPToSI:
436 NewV = IRB.CreateSExtOrTrunc(NewOperands[0],
I->getType());
439 case Instruction::FCmp: {
442 NewV = IRB.CreateICmp(
P, NewOperands[0], NewOperands[1],
I->getName());
446 case Instruction::UIToFP:
447 NewV = IRB.CreateZExtOrTrunc(NewOperands[0], ToTy);
450 case Instruction::SIToFP:
451 NewV = IRB.CreateSExtOrTrunc(NewOperands[0], ToTy);
454 case Instruction::FNeg:
455 NewV = IRB.CreateNeg(NewOperands[0],
I->getName());
458 case Instruction::FAdd:
459 case Instruction::FSub:
460 case Instruction::FMul:
462 NewOperands[0], NewOperands[1],
469 I->replaceAllUsesWith(NewV);
471 ConvertedInsts[
I] = NewV;
476void Float2IntPass::cleanup() {
477 for (
auto &
I :
reverse(ConvertedInsts))
478 I.first->eraseFromParent();
482 LLVM_DEBUG(
dbgs() <<
"F2I: Looking at function " <<
F.getName() <<
"\n");
486 ConvertedInsts.clear();
489 Ctx = &
F.getParent()->getContext();
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...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
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.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
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].
This class represents a range of values.
A parsed version of the target data layout string in and methods for querying it.
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 &)