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()))
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())
296 Worklist.push_back(Pair.first);
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 (
const auto &
E : ECs) {
320 Type *ConvertedToTy =
nullptr;
323 for (Instruction *
I : ECs.members(*
E)) {
324 auto *SeenI = SeenInsts.find(
I);
325 if (SeenI == SeenInsts.end())
328 R =
R.unionWith(SeenI->second);
333 if (!Roots.contains(
I)) {
336 ConvertedToTy =
I->getType();
337 for (User *U :
I->users()) {
339 if (!UI || !SeenInsts.contains(UI)) {
352 if (ECs.member_begin(*
E) == ECs.member_end() ||
Fail ||
R.isFullSet() ||
353 R.isSignWrappedSet())
355 assert(ConvertedToTy &&
"Must have set the convertedtoty by this point!");
359 unsigned MinBW =
R.getMinSignedBits() + 1;
360 LLVM_DEBUG(
dbgs() <<
"F2I: MinBitwidth=" << MinBW <<
", R: " << R <<
"\n");
368 unsigned MaxRepresentableBits
370 if (MinBW > MaxRepresentableBits) {
371 LLVM_DEBUG(
dbgs() <<
"F2I: Value not guaranteed to be representable!\n");
377 Type *Ty =
DL.getSmallestLegalIntType(*Ctx, MinBW);
383 }
else if (MinBW <= 64) {
386 LLVM_DEBUG(
dbgs() <<
"F2I: Value requires more bits to represent than "
387 "the target supports!\n");
392 for (Instruction *
I : ECs.members(*
E))
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) {
412 NewOperands.
push_back(convert(VI, ToTy));
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();
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.
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.
static constexpr roundingMode rmNearestTiesToEven
static LLVM_ABI unsigned int semanticsPrecision(const fltSemantics &)