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;
90 for (BasicBlock &BB :
F) {
96 for (Instruction &
I : BB) {
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);
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())
222 const APFloat &
F = CF->getValueAPF();
229 !
I->hasNoSignedZeros()))
253 switch (
I->getOpcode()) {
256 case Instruction::UIToFP:
257 case Instruction::SIToFP:
260 case Instruction::FNeg: {
261 assert(OpRanges.
size() == 1 &&
"FNeg is a unary operator!");
262 unsigned Size = OpRanges[0].getBitWidth();
264 return Zero.sub(OpRanges[0]);
267 case Instruction::FAdd:
268 case Instruction::FSub:
269 case Instruction::FMul: {
270 assert(OpRanges.
size() == 2 &&
"its a binary operator!");
272 return OpRanges[0].binaryOp(BinOp, OpRanges[1]);
279 case Instruction::FPToUI:
280 case Instruction::FPToSI: {
281 assert(OpRanges.
size() == 1 &&
"FPTo[US]I is a unary operator!");
288 case Instruction::FCmp:
289 assert(OpRanges.
size() == 2 &&
"FCmp is a binary operator!");
290 return OpRanges[0].unionWith(OpRanges[1]);
296void Float2IntPass::walkForwards() {
297 std::deque<Instruction *> Worklist;
298 for (
const auto &Pair : SeenInsts)
299 if (Pair.second == unknownRange())
300 Worklist.push_back(Pair.first);
302 while (!Worklist.empty()) {
306 if (std::optional<ConstantRange>
Range = calcRange(
I))
309 Worklist.push_front(
I);
314bool Float2IntPass::validateAndTransform(
const DataLayout &
DL) {
315 bool MadeChange =
false;
318 for (
const auto &
E : ECs) {
324 Type *ConvertedToTy =
nullptr;
327 for (Instruction *
I : ECs.members(*
E)) {
328 auto *SeenI = SeenInsts.find(
I);
329 if (SeenI == SeenInsts.end())
332 R =
R.unionWith(SeenI->second);
337 if (!Roots.contains(
I)) {
340 ConvertedToTy =
I->getType();
341 for (User *U :
I->users()) {
343 if (!UI || !SeenInsts.contains(UI)) {
356 if (ECs.member_begin(*
E) == ECs.member_end() ||
Fail ||
R.isFullSet() ||
357 R.isSignWrappedSet())
359 assert(ConvertedToTy &&
"Must have set the convertedtoty by this point!");
363 unsigned MinBW =
R.getMinSignedBits() + 1;
364 LLVM_DEBUG(
dbgs() <<
"F2I: MinBitwidth=" << MinBW <<
", R: " << R <<
"\n");
372 unsigned MaxRepresentableBits
374 if (MinBW > MaxRepresentableBits) {
375 LLVM_DEBUG(
dbgs() <<
"F2I: Value not guaranteed to be representable!\n");
381 Type *Ty =
DL.getSmallestLegalIntType(*Ctx, MinBW);
387 }
else if (MinBW <= 64) {
390 LLVM_DEBUG(
dbgs() <<
"F2I: Value requires more bits to represent than "
391 "the target supports!\n");
396 for (Instruction *
I : ECs.members(*
E))
405 if (
auto It = ConvertedInsts.find(
I); It != ConvertedInsts.end())
410 for (
Value *V :
I->operands()) {
412 if (
I->getOpcode() == Instruction::UIToFP ||
413 I->getOpcode() == Instruction::SIToFP) {
416 NewOperands.
push_back(convert(VI, ToTy));
420 CF->getValueAPF().convertToInteger(Val,
423 NewOperands.
push_back(ConstantInt::get(ToTy, Val));
431 Value *NewV =
nullptr;
432 switch (
I->getOpcode()) {
435 case Instruction::FPToUI:
436 NewV = IRB.CreateZExtOrTrunc(NewOperands[0],
I->getType());
439 case Instruction::FPToSI:
440 NewV = IRB.CreateSExtOrTrunc(NewOperands[0],
I->getType());
443 case Instruction::FCmp: {
446 NewV = IRB.CreateICmp(
P, NewOperands[0], NewOperands[1],
I->getName());
450 case Instruction::UIToFP:
451 NewV = IRB.CreateZExtOrTrunc(NewOperands[0], ToTy);
454 case Instruction::SIToFP:
455 NewV = IRB.CreateSExtOrTrunc(NewOperands[0], ToTy);
458 case Instruction::FNeg:
459 NewV = IRB.CreateNeg(NewOperands[0],
I->getName());
462 case Instruction::FAdd:
463 case Instruction::FSub:
464 case Instruction::FMul:
466 NewOperands[0], NewOperands[1],
473 I->replaceAllUsesWith(NewV);
475 ConvertedInsts[
I] = NewV;
480void Float2IntPass::cleanup() {
481 for (
auto &
I :
reverse(ConvertedInsts))
482 I.first->eraseFromParent();
486 LLVM_DEBUG(
dbgs() <<
"F2I: Looking at function " <<
F.getName() <<
"\n");
490 ConvertedInsts.clear();
493 Ctx = &
F.getParent()->getContext();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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
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.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
This file defines the SmallVector class.
static constexpr roundingMode rmNearestTiesToEven
static LLVM_ABI unsigned int semanticsPrecision(const fltSemantics &)
opStatus
IEEE-754R 7: Default exception handling.
opStatus roundToIntegral(roundingMode RM)
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
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
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.
LLVM_ABI 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)
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.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
void push_back(const T &Elt)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
LLVM_ABI const fltSemantics & getFltSemantics() const
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)
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.