LLVM: lib/Analysis/FunctionPropertiesAnalysis.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

24#include

25

26using namespace llvm;

27

28namespace llvm {

31 cl::desc("Whether or not to compute detailed function properties."));

32

35 cl::desc("The minimum number of instructions a basic block should contain "

36 "before being considered big."));

37

40 cl::desc("The minimum number of instructions a basic block should contain "

41 "before being considered medium-sized."));

42}

43

46 cl::desc("The minimum number of arguments a function call must have before "

47 "it is considered having many arguments."));

48

49namespace {

50int64_t getNumBlocksFromCond(const BasicBlock &BB) {

51 int64_t Ret = 0;

52 if (const auto *BI = dyn_cast(BB.getTerminator())) {

53 if (BI->isConditional())

54 Ret += BI->getNumSuccessors();

55 } else if (const auto *SI = dyn_cast(BB.getTerminator())) {

56 Ret += (SI->getNumCases() + (nullptr != SI->getDefaultDest()));

57 }

58 return Ret;

59}

60

61int64_t getUses(const Function &F) {

62 return ((F.hasLocalLinkage()) ? 1 : 0) + F.getNumUses();

63}

64}

65

66void FunctionPropertiesInfo::reIncludeBB(const BasicBlock &BB) {

67 updateForBB(BB, +1);

68}

69

70void FunctionPropertiesInfo::updateForBB(const BasicBlock &BB,

75 (Direction * getNumBlocksFromCond(BB));

76 for (const auto &I : BB) {

77 if (auto *CS = dyn_cast(&I)) {

78 const auto *Callee = CS->getCalledFunction();

79 if (Callee && Callee->isIntrinsic() && Callee->isDeclaration())

81 }

82 if (I.getOpcode() == Instruction::Load) {

84 } else if (I.getOpcode() == Instruction::Store) {

86 }

87 }

89

91 unsigned SuccessorCount = succ_size(&BB);

92 if (SuccessorCount == 1)

94 else if (SuccessorCount == 2)

96 else if (SuccessorCount > 2)

98

99 unsigned PredecessorCount = pred_size(&BB);

100 if (PredecessorCount == 1)

102 else if (PredecessorCount == 2)

104 else if (PredecessorCount > 2)

106

111 else

113

114

115

116

117 if (SuccessorCount > 1) {

121 }

122 }

123

125

126 if (const auto *BI = dyn_cast(BB.getTerminator())) {

127 if (!BI->isConditional())

129 }

130

131 for (const Instruction &I : BB.instructionsWithoutDebug()) {

132 if (I.isCast())

134

135 if (I.getType()->isFloatTy())

137 else if (I.getType()->isIntegerTy())

139

140 if (isa(I))

142

143 if (const auto *Call = dyn_cast(&I)) {

144 if (Call->isIndirectCall())

146 else

148

149 if (Call->getType()->isIntegerTy())

151 else if (Call->getType()->isFloatingPointTy())

153 else if (Call->getType()->isPointerTy())

155 else if (Call->getType()->isVectorTy()) {

156 if (Call->getType()->getScalarType()->isIntegerTy())

158 else if (Call->getType()->getScalarType()->isFloatingPointTy())

160 else if (Call->getType()->getScalarType()->isPointerTy())

162 }

163

166

167 for (const auto &Arg : Call->args()) {

168 if (Arg->getType()->isPointerTy()) {

170 break;

171 }

172 }

173 }

174

175#define COUNT_OPERAND(OPTYPE) \

176 if (isa(Operand)) { \

177 OPTYPE##OperandCount += Direction; \

178 continue; \

179 }

180

181 for (unsigned int OperandIndex = 0; OperandIndex < I.getNumOperands();

182 ++OperandIndex) {

183 Value *Operand = I.getOperand(OperandIndex);

192

193

194

196 }

197

198#undef CHECK_OPERAND

199 }

200 }

201}

202

203void FunctionPropertiesInfo::updateAggregateStats(const Function &F,

205

206 Uses = getUses(F);

209 std::deque<const Loop *> Worklist;

211 while (!Worklist.empty()) {

212 const auto *L = Worklist.front();

214 std::max(MaxLoopDepth, static_cast<int64_t>(L->getLoopDepth()));

215 Worklist.pop_front();

217 }

218}

219

224}

225

228

230 for (const auto &BB : F)

232 FPI.reIncludeBB(BB);

233 FPI.updateAggregateStats(F, LI);

234 return FPI;

235}

236

238#define PRINT_PROPERTY(PROP_NAME) OS << #PROP_NAME ": " << PROP_NAME << "\n";

239

249

286 }

287

288#undef PRINT_PROPERTY

289

290 OS << "\n";

291}

292

294

298}

299

302 OS << "Printing analysis results of CFA for function "

303 << "'" << F.getName() << "':"

304 << "\n";

307}

308

311 : FPI(FPI), CallSiteBB(*CB.getParent()), Caller(*CallSiteBB.getParent()) {

312 assert(isa(CB) || isa(CB));

313

314

315

317

318

319 LikelyToChangeBBs.insert(&CallSiteBB);

320

321

322 LikelyToChangeBBs.insert(&*Caller.begin());

323

324

325

326

328

329

330

331

332

333

335 for (auto *Succ : successors(&CallSiteBB))

336 if (Inserted.insert(Succ).second)

337 DomTreeUpdates.emplace_back(DominatorTree::UpdateKind::Delete,

338 const_cast<BasicBlock *>(&CallSiteBB),

340

341

342 Inserted.clear();

343

344

345

346

347

348

349

350 if (const auto *II = dyn_cast(&CB)) {

351 const auto *UnwindDest = II->getUnwindDest();

353

354 for (auto *Succ : successors(UnwindDest))

355 if (Inserted.insert(Succ).second)

356 DomTreeUpdates.emplace_back(DominatorTree::UpdateKind::Delete,

357 const_cast<BasicBlock *>(UnwindDest),

359 }

360

361

362

363

364

365

366 Successors.erase(&CallSiteBB);

367

368 for (const auto *BB : Successors)

369 LikelyToChangeBBs.insert(BB);

370

371

372

373

374

375 for (const auto *BB : LikelyToChangeBBs)

376 FPI.updateForBB(*BB, -1);

377}

378

379DominatorTree &FunctionPropertiesUpdater::getUpdatedDominatorTree(

381 auto &DT =

383

385

387 for (auto *Succ : successors(&CallSiteBB))

388 if (Inserted.insert(Succ).second)

389 FinalDomTreeUpdates.push_back({DominatorTree::UpdateKind::Insert,

390 const_cast<BasicBlock *>(&CallSiteBB),

392

393

394

395 for (auto &Upd : DomTreeUpdates)

397 FinalDomTreeUpdates.push_back(Upd);

398

400#ifdef EXPENSIVE_CHECKS

401 assert(DT.verify(DominatorTree::VerificationLevel::Full));

402#endif

403 return DT;

404}

405

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430

433 auto &DT = getUpdatedDominatorTree(FAM);

434

435 if (&CallSiteBB != &*Caller.begin())

437

438

439 for (const auto *Succ : Successors)

441 Reinclude.insert(Succ);

442 else

443 Unreachable.insert(Succ);

444

445

446

447

448

449 const auto IncludeSuccessorsMark = Reinclude.size();

450 bool CSInsertion = Reinclude.insert(&CallSiteBB);

451 (void)CSInsertion;

453 for (size_t I = 0; I < Reinclude.size(); ++I) {

454 const auto *BB = Reinclude[I];

455 FPI.reIncludeBB(*BB);

456 if (I >= IncludeSuccessorsMark)

458 }

459

460

461

462

463

464 const auto AlreadyExcludedMark = Unreachable.size();

465 for (size_t I = 0; I < Unreachable.size(); ++I) {

466 const auto *U = Unreachable[I];

467 if (I >= AlreadyExcludedMark)

468 FPI.updateForBB(*U, -1);

469 for (const auto *Succ : successors(U))

471 Unreachable.insert(Succ);

472 }

473

475 FPI.updateAggregateStats(Caller, LI);

476#ifdef EXPENSIVE_CHECKS

477 assert(isUpdateValid(Caller, FPI, FAM));

478#endif

479}

480

481bool FunctionPropertiesUpdater::isUpdateValid(Function &F,

485 DominatorTree::VerificationLevel::Full))

486 return false;

490 return FPI == Fresh;

491}

static const Function * getParent(const Value *V)

This file contains the declarations for the subclasses of Constant, which represent the different fla...

#define PRINT_PROPERTY(PROP_NAME)

static cl::opt< unsigned > CallWithManyArgumentsThreshold("call-with-many-arguments-threshold", cl::Hidden, cl::init(4), cl::desc("The minimum number of arguments a function call must have before " "it is considered having many arguments."))

#define COUNT_OPERAND(OPTYPE)

This file provides various utilities for inspecting and working with the control flow graph in LLVM I...

uint64_t IntrinsicInst * II

FunctionAnalysisManager FAM

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

This file implements a set that has insertion order iteration characteristics.

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.

This class represents an incoming formal argument to a Function.

LLVM Basic Block Representation.

const Instruction * getTerminator() const LLVM_READONLY

Returns the terminator instruction if the block is well formed or null if the block is not well forme...

Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...

ConstantFP - Floating Point Values [float, double].

This is the shared class of boolean and integer constants.

This is an important base class in LLVM.

Implements a dense probed hash-table based set.

Analysis pass which computes a DominatorTree.

bool verify(VerificationLevel VL=VerificationLevel::Full) const

verify - checks if the tree is correct.

void applyUpdates(ArrayRef< UpdateType > Updates)

Inform the dominator tree about a sequence of CFG edge insertions and deletions and perform a batch u...

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.

FunctionPropertiesInfo run(Function &F, FunctionAnalysisManager &FAM)

int64_t BasicBlocksWithMoreThanTwoSuccessors

int64_t BasicBlocksWithSinglePredecessor

int64_t CallReturnsVectorPointerCount

int64_t CallReturnsPointerCount

int64_t CallWithManyArgumentsCount

int64_t CallReturnsVectorIntCount

int64_t CallReturnsVectorFloatCount

int64_t CastInstructionCount

int64_t BasicBlockCount

Number of basic blocks.

int64_t CriticalEdgeCount

int64_t Uses

Number of uses of this function, plus 1 if the function is callable outside the module.

int64_t InlineAsmOperandCount

int64_t ConstantFPOperandCount

int64_t BasicBlocksWithTwoSuccessors

int64_t InstructionOperandCount

int64_t CallWithPointerArgumentCount

int64_t FloatingPointInstructionCount

int64_t TopLevelLoopCount

int64_t CallReturnsIntegerCount

int64_t BlocksReachedFromConditionalInstruction

Number of blocks reached from a conditional instruction, or that are 'cases' of a SwitchInstr.

static FunctionPropertiesInfo getFunctionPropertiesInfo(const Function &F, const DominatorTree &DT, const LoopInfo &LI)

int64_t GlobalValueOperandCount

int64_t UnconditionalBranchCount

int64_t ArgumentOperandCount

int64_t BasicBlocksWithSingleSuccessor

int64_t BasicBlockOperandCount

int64_t ControlFlowEdgeCount

int64_t BasicBlocksWithTwoPredecessors

int64_t MediumBasicBlocks

int64_t IntegerInstructionCount

int64_t CallReturnsFloatCount

void print(raw_ostream &OS) const

int64_t TotalInstructionCount

int64_t BasicBlocksWithMoreThanTwoPredecessors

int64_t ConstantOperandCount

int64_t ConstantIntOperandCount

int64_t UnknownOperandCount

int64_t DirectCallsToDefinedFunctions

Number of direct calls made from this function to other functions defined in this module.

int64_t IndirectCallCount

PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)

FunctionPropertiesUpdater(FunctionPropertiesInfo &FPI, CallBase &CB)

void finish(FunctionAnalysisManager &FAM) const

Analysis pass that exposes the LoopInfo for a function.

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.

A vector that has set insertion semantics.

size_type size() const

Determine the number of elements in the SetVector.

bool insert(const value_type &X)

Insert a new element into the SetVector.

std::pair< iterator, bool > insert(PtrType Ptr)

Inserts Ptr if and only if there is no element in the container equal to Ptr.

SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.

reference emplace_back(ArgTypes &&... Args)

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

LLVM Value Representation.

This class implements an extremely fast bulk output stream that can only output to a stream.

initializer< Ty > init(const Ty &Val)

This is an optimization pass for GlobalISel generic memory operations.

auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)

Get the size of a range.

auto successors(const MachineBasicBlock *BB)

cl::opt< bool > EnableDetailedFunctionProperties("enable-detailed-function-properties", cl::Hidden, cl::init(false), cl::desc("Whether or not to compute detailed function properties."))

void append_range(Container &C, Range &&R)

Wrapper function to append range R to container C.

auto pred_size(const MachineBasicBlock *BB)

Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr)

auto succ_size(const MachineBasicBlock *BB)

RNSuccIterator< NodeRef, BlockT, RegionT > succ_begin(NodeRef Node)

cl::opt< unsigned > BigBasicBlockInstructionThreshold("big-basic-block-instruction-threshold", cl::Hidden, cl::init(500), cl::desc("The minimum number of instructions a basic block should contain " "before being considered big."))

RNSuccIterator< NodeRef, BlockT, RegionT > succ_end(NodeRef Node)

bool is_contained(R &&Range, const E &Element)

Returns true if Element is found in Range.

cl::opt< unsigned > MediumBasicBlockInstructionThreshold("medium-basic-block-instruction-threshold", cl::Hidden, cl::init(15), cl::desc("The minimum number of instructions a basic block should contain " "before being considered medium-sized."))

A special type used by analysis passes to provide an address that identifies that particular analysis...

Direction

An enum for the direction of the loop.