LLVM: lib/Transforms/Scalar/Float2Int.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

26#include

27

28#define DEBUG_TYPE "float2int"

29

30using namespace llvm;

31

32

33

34

35

36

37

38

39

40

41

42

43

46 cl::desc("Max integer bitwidth to consider in float2int"

47 "(default=64)"));

48

49

50

52 switch (P) {

71 default:

73 }

74}

75

76

77

79 switch (Opcode) {

81 case Instruction::FAdd: return Instruction::Add;

82 case Instruction::FSub: return Instruction::Sub;

83 case Instruction::FMul: return Instruction::Mul;

84 }

85}

86

87

88

90 for (BasicBlock &BB : F) {

91

92

94 continue;

95

96 for (Instruction &I : BB) {

98 continue;

99 switch (I.getOpcode()) {

100 default: break;

101 case Instruction::FPToUI:

102 case Instruction::FPToSI:

103 Roots.insert(&I);

104 break;

105 case Instruction::FCmp:

108 Roots.insert(&I);

109 break;

110 }

111 }

112 }

113}

114

115

118 SeenInsts.insert_or_assign(I, std::move(R));

119}

120

121

123 return ConstantRange::getFull(MaxIntegerBW + 1);

124}

126 return ConstantRange::getEmpty(MaxIntegerBW + 1);

127}

130 return badRange();

131 return R;

132}

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148void Float2IntPass::walkBackwards() {

149 std::deque<Instruction*> Worklist(Roots.begin(), Roots.end());

150 while (!Worklist.empty()) {

152 Worklist.pop_back();

153

154 if (SeenInsts.contains(I))

155

156 continue;

157

158 switch (I->getOpcode()) {

159

160 default:

161

162 seen(I, badRange());

163 break;

164

165 case Instruction::UIToFP:

166 case Instruction::SIToFP: {

167

168

169 unsigned BW = I->getOperand(0)->getType()->getPrimitiveSizeInBits();

170 auto Input = ConstantRange::getFull(BW);

172 seen(I, validateRange(Input.castOp(CastOp, MaxIntegerBW+1)));

173 continue;

174 }

175

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());

184 break;

185 }

186

187 for (Value *O : I->operands()) {

189

190 ECs.unionSets(I, OI);

191 if (SeenInsts.find(I)->second != badRange())

192 Worklist.push_back(OI);

194

195 seen(I, badRange());

196 }

197 }

198 }

199}

200

201

202

203std::optional 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())

210 return std::nullopt;

211 OpRanges.push_back(OpIt->second);

213

214

215

216

217

218

219

220

221

222 const APFloat &F = CF->getValueAPF();

223

224

225

226

227 if (F.isFinite() ||

229 I->hasNoSignedZeros()))

230 return badRange();

231

235 return badRange();

236

237

239 bool Exact;

242

243

246 else

247 return badRange();

248 } else {

249 llvm_unreachable("Should have already marked this as badRange!");

250 }

251 }

252

253 switch (I->getOpcode()) {

254

255 default:

256 case Instruction::UIToFP:

257 case Instruction::SIToFP:

258 llvm_unreachable("Should have been handled in walkForwards!");

259

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]);

265 }

266

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]);

273 }

274

275

276

277

278

279 case Instruction::FPToUI:

280 case Instruction::FPToSI: {

281 assert(OpRanges.size() == 1 && "FPTo[US]I is a unary operator!");

282

283

285 return OpRanges[0].castOp(CastOp, MaxIntegerBW+1);

286 }

287

288 case Instruction::FCmp:

289 assert(OpRanges.size() == 2 && "FCmp is a binary operator!");

290 return OpRanges[0].unionWith(OpRanges[1]);

291 }

292}

293

294

295

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);

301

302 while (!Worklist.empty()) {

304 Worklist.pop_back();

305

306 if (std::optional Range = calcRange(I))

308 else

309 Worklist.push_front(I);

310 }

311}

312

313

314bool Float2IntPass::validateAndTransform(const DataLayout &DL) {

315 bool MadeChange = false;

316

317

318 for (const auto &E : ECs) {

319 if (E->isLeader())

320 continue;

321

323 bool Fail = false;

324 Type *ConvertedToTy = nullptr;

325

326

327 for (Instruction *I : ECs.members(*E)) {

328 auto *SeenI = SeenInsts.find(I);

329 if (SeenI == SeenInsts.end())

330 continue;

331

332 R = R.unionWith(SeenI->second);

333

334

335

336

337 if (!Roots.contains(I)) {

338

339 if (!ConvertedToTy)

340 ConvertedToTy = I->getType();

341 for (User *U : I->users()) {

343 if (!UI || !SeenInsts.contains(UI)) {

344 LLVM_DEBUG(dbgs() << "F2I: Failing because of " << *U << "\n");

346 break;

347 }

348 }

349 }

351 break;

352 }

353

354

355

356 if (ECs.member_begin(*E) == ECs.member_end() || Fail || R.isFullSet() ||

357 R.isSignWrappedSet())

358 continue;

359 assert(ConvertedToTy && "Must have set the convertedtoty by this point!");

360

361

362

363 unsigned MinBW = R.getMinSignedBits() + 1;

364 LLVM_DEBUG(dbgs() << "F2I: MinBitwidth=" << MinBW << ", R: " << R << "\n");

365

366

367

368

369

370

371

372 unsigned MaxRepresentableBits

374 if (MinBW > MaxRepresentableBits) {

375 LLVM_DEBUG(dbgs() << "F2I: Value not guaranteed to be representable!\n");

376 continue;

377 }

378

379

380

381 Type *Ty = DL.getSmallestLegalIntType(*Ctx, MinBW);

382 if (!Ty) {

383

384

385 if (MinBW <= 32) {

387 } else if (MinBW <= 64) {

389 } else {

390 LLVM_DEBUG(dbgs() << "F2I: Value requires more bits to represent than "

391 "the target supports!\n");

392 continue;

393 }

394 }

395

396 for (Instruction *I : ECs.members(*E))

397 convert(I, Ty);

398 MadeChange = true;

399 }

400

401 return MadeChange;

402}

403

405 if (auto It = ConvertedInsts.find(I); It != ConvertedInsts.end())

406

407 return It->second;

408

410 for (Value *V : I->operands()) {

411

412 if (I->getOpcode() == Instruction::UIToFP ||

413 I->getOpcode() == Instruction::SIToFP) {

416 NewOperands.push_back(convert(VI, ToTy));

419 bool Exact;

420 CF->getValueAPF().convertToInteger(Val,

422 &Exact);

423 NewOperands.push_back(ConstantInt::get(ToTy, Val));

424 } else {

426 }

427 }

428

429

431 Value *NewV = nullptr;

432 switch (I->getOpcode()) {

434

435 case Instruction::FPToUI:

436 NewV = IRB.CreateZExtOrTrunc(NewOperands[0], I->getType());

437 break;

438

439 case Instruction::FPToSI:

440 NewV = IRB.CreateSExtOrTrunc(NewOperands[0], I->getType());

441 break;

442

443 case Instruction::FCmp: {

446 NewV = IRB.CreateICmp(P, NewOperands[0], NewOperands[1], I->getName());

447 break;

448 }

449

450 case Instruction::UIToFP:

451 NewV = IRB.CreateZExtOrTrunc(NewOperands[0], ToTy);

452 break;

453

454 case Instruction::SIToFP:

455 NewV = IRB.CreateSExtOrTrunc(NewOperands[0], ToTy);

456 break;

457

458 case Instruction::FNeg:

459 NewV = IRB.CreateNeg(NewOperands[0], I->getName());

460 break;

461

462 case Instruction::FAdd:

463 case Instruction::FSub:

464 case Instruction::FMul:

465 NewV = IRB.CreateBinOp(mapBinOpcode(I->getOpcode()),

466 NewOperands[0], NewOperands[1],

467 I->getName());

468 break;

469 }

470

471

472 if (Roots.count(I))

473 I->replaceAllUsesWith(NewV);

474

475 ConvertedInsts[I] = NewV;

476 return NewV;

477}

478

479

480void Float2IntPass::cleanup() {

481 for (auto &I : reverse(ConvertedInsts))

482 I.first->eraseFromParent();

483}

484

486 LLVM_DEBUG(dbgs() << "F2I: Looking at function " << F.getName() << "\n");

487

489 SeenInsts.clear();

490 ConvertedInsts.clear();

491 Roots.clear();

492

493 Ctx = &F.getParent()->getContext();

494

495 findRoots(F, DT);

496

497 walkBackwards();

498 walkForwards();

499

501 bool Modified = validateAndTransform(DL);

503 cleanup();

505}

506

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)

Definition Float2Int.cpp:51

static Instruction::BinaryOps mapBinOpcode(unsigned Opcode)

Definition Float2Int.cpp:78

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)

Definition Float2Int.cpp:485

PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)

Definition Float2Int.cpp:507

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 - 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 - 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 - Return the argument parameter cast to the specified type.

AnalysisManager< Function > FunctionAnalysisManager

Convenience typedef for the Function analysis manager.