LLVM: lib/Transforms/IPO/CalledValuePropagation.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

27

28using namespace llvm;

29

30#define DEBUG_TYPE "called-value-propagation"

31

32

33

34

35

36

37

38

41 cl::desc("The maximum number of functions to track per lattice value"));

42

43namespace {

44

45

46

47

48

49

51

52

54

55

56

57class CVPLatticeVal {

58public:

59

60

61

62 enum CVPLatticeStateTy { Undefined, FunctionSet, Overdefined, Untracked };

63

64

65

66 struct Compare {

67 bool operator()(const Function *LHS, const Function *RHS) const {

69 }

70 };

71

72 CVPLatticeVal() = default;

73 CVPLatticeVal(CVPLatticeStateTy LatticeState) : LatticeState(LatticeState) {}

74 CVPLatticeVal(std::vector<Function *> &&Functions)

75 : LatticeState(FunctionSet), Functions(std::move(Functions)) {

77 }

78

79

80

81 const std::vector<Function *> &getFunctions() const {

82 return Functions;

83 }

84

85

86 bool isFunctionSet() const { return LatticeState == FunctionSet; }

87

89 return LatticeState == RHS.LatticeState && Functions == RHS.Functions;

90 }

91

93 return LatticeState != RHS.LatticeState || Functions != RHS.Functions;

94 }

95

96private:

97

98 CVPLatticeStateTy LatticeState = Undefined;

99

100

101

102

103

104

105

106

107 std::vector<Function *> Functions;

108};

109

110

111

112

113

114

115class CVPLatticeFunc

117public:

118 CVPLatticeFunc()

119 : AbstractLatticeFunction(CVPLatticeVal(CVPLatticeVal::Undefined),

120 CVPLatticeVal(CVPLatticeVal::Overdefined),

121 CVPLatticeVal(CVPLatticeVal::Untracked)) {}

122

123

124 CVPLatticeVal ComputeLatticeVal(CVPLatticeKey Key) override {

125 switch (Key.getInt()) {

126 case IPOGrouping::Register:

128 return getUndefVal();

131 return getUndefVal();

133 return computeConstant(C);

134 }

135 return getOverdefinedVal();

136 case IPOGrouping::Memory:

137 case IPOGrouping::Return:

140 return computeConstant(GV->getInitializer());

143 return getUndefVal();

144 }

145 return getOverdefinedVal();

146 }

147

148

149

150

151

152

153 CVPLatticeVal MergeValues(CVPLatticeVal X, CVPLatticeVal Y) override {

154 if (X == getOverdefinedVal() || Y == getOverdefinedVal())

155 return getOverdefinedVal();

156 if (X == getUndefVal() && Y == getUndefVal())

157 return getUndefVal();

158 std::vector<Function *> Union;

159 std::set_union(X.getFunctions().begin(), X.getFunctions().end(),

160 Y.getFunctions().begin(), Y.getFunctions().end(),

161 std::back_inserter(Union), CVPLatticeVal::Compare{});

163 return getOverdefinedVal();

164 return CVPLatticeVal(std::move(Union));

165 }

166

167

168

169

170

171 void ComputeInstructionState(

172 Instruction &I,

173 SmallDenseMap<CVPLatticeKey, CVPLatticeVal, 16> &ChangedValues,

174 SparseSolver<CVPLatticeKey, CVPLatticeVal> &SS) override {

175 switch (I.getOpcode()) {

176 case Instruction::Call:

177 case Instruction::Invoke:

178 return visitCallBase(cast(I), ChangedValues, SS);

179 case Instruction::Load:

180 return visitLoad(*cast(&I), ChangedValues, SS);

181 case Instruction::Ret:

183 case Instruction::Select:

185 case Instruction::Store:

187 default:

188 return visitInst(I, ChangedValues, SS);

189 }

190 }

191

192

193 void PrintLatticeVal(CVPLatticeVal LV, raw_ostream &OS) override {

194 if (LV == getUndefVal())

195 OS << "Undefined ";

196 else if (LV == getOverdefinedVal())

197 OS << "Overdefined";

198 else if (LV == getUntrackedVal())

199 OS << "Untracked ";

200 else

201 OS << "FunctionSet";

202 }

203

204

205 void PrintLatticeKey(CVPLatticeKey Key, raw_ostream &OS) override {

206 if (Key.getInt() == IPOGrouping::Register)

207 OS << " ";

208 else if (Key.getInt() == IPOGrouping::Memory)

209 OS << " ";

210 else if (Key.getInt() == IPOGrouping::Return)

211 OS << " ";

213 OS << Key.getPointer()->getName();

214 else

215 OS << *Key.getPointer();

216 }

217

218

219

220 SmallPtrSetImpl<CallBase *> &getIndirectCalls() { return IndirectCalls; }

221

222private:

223

224

225

226 SmallPtrSet<CallBase *, 32> IndirectCalls;

227

228

229

230

231

232 CVPLatticeVal computeConstant(Constant *C) {

234 return CVPLatticeVal(CVPLatticeVal::FunctionSet);

236 return CVPLatticeVal({F});

237 return getOverdefinedVal();

238 }

239

240

241

242 void

243 visitReturn(ReturnInst &I,

244 SmallDenseMap<CVPLatticeKey, CVPLatticeVal, 16> &ChangedValues,

245 SparseSolver<CVPLatticeKey, CVPLatticeVal> &SS) {

246 Function *F = I.getParent()->getParent();

247 if (F->getReturnType()->isVoidTy())

248 return;

249 auto RegI = CVPLatticeKey(I.getReturnValue(), IPOGrouping::Register);

250 auto RetF = CVPLatticeKey(F, IPOGrouping::Return);

251 ChangedValues[RetF] =

252 MergeValues(SS.getValueState(RegI), SS.getValueState(RetF));

253 }

254

255

256

257

258

259 void

260 visitCallBase(CallBase &CB,

261 SmallDenseMap<CVPLatticeKey, CVPLatticeVal, 16> &ChangedValues,

262 SparseSolver<CVPLatticeKey, CVPLatticeVal> &SS) {

264 auto RegI = CVPLatticeKey(&CB, IPOGrouping::Register);

265

266

267

268 if (F)

269 IndirectCalls.insert(&CB);

270

271

273

274

276 return;

277 ChangedValues[RegI] = getOverdefinedVal();

278 return;

279 }

280

281

282

283 SS.MarkBlockExecutable(&F->front());

284 auto RetF = CVPLatticeKey(F, IPOGrouping::Return);

285 for (Argument &A : F->args()) {

286 auto RegFormal = CVPLatticeKey(&A, IPOGrouping::Register);

287 auto RegActual =

288 CVPLatticeKey(CB.getArgOperand(A.getArgNo()), IPOGrouping::Register);

289 ChangedValues[RegFormal] =

290 MergeValues(SS.getValueState(RegFormal), SS.getValueState(RegActual));

291 }

292

293

294

296 return;

297

298 ChangedValues[RegI] =

299 MergeValues(SS.getValueState(RegI), SS.getValueState(RetF));

300 }

301

302

303

304 void

305 visitSelect(SelectInst &I,

306 SmallDenseMap<CVPLatticeKey, CVPLatticeVal, 16> &ChangedValues,

307 SparseSolver<CVPLatticeKey, CVPLatticeVal> &SS) {

308 auto RegI = CVPLatticeKey(&I, IPOGrouping::Register);

309 auto RegT = CVPLatticeKey(I.getTrueValue(), IPOGrouping::Register);

310 auto RegF = CVPLatticeKey(I.getFalseValue(), IPOGrouping::Register);

311 ChangedValues[RegI] =

312 MergeValues(SS.getValueState(RegT), SS.getValueState(RegF));

313 }

314

315

316

317

318 void visitLoad(LoadInst &I,

319 SmallDenseMap<CVPLatticeKey, CVPLatticeVal, 16> &ChangedValues,

320 SparseSolver<CVPLatticeKey, CVPLatticeVal> &SS) {

321 auto RegI = CVPLatticeKey(&I, IPOGrouping::Register);

323 auto MemGV = CVPLatticeKey(GV, IPOGrouping::Memory);

324 ChangedValues[RegI] =

325 MergeValues(SS.getValueState(RegI), SS.getValueState(MemGV));

326 } else {

327 ChangedValues[RegI] = getOverdefinedVal();

328 }

329 }

330

331

332

333

334 void

335 visitStore(StoreInst &I,

336 SmallDenseMap<CVPLatticeKey, CVPLatticeVal, 16> &ChangedValues,

337 SparseSolver<CVPLatticeKey, CVPLatticeVal> &SS) {

339 if (!GV)

340 return;

341 auto RegI = CVPLatticeKey(I.getValueOperand(), IPOGrouping::Register);

342 auto MemGV = CVPLatticeKey(GV, IPOGrouping::Memory);

343 ChangedValues[MemGV] =

344 MergeValues(SS.getValueState(RegI), SS.getValueState(MemGV));

345 }

346

347

348

349 void visitInst(Instruction &I,

350 SmallDenseMap<CVPLatticeKey, CVPLatticeVal, 16> &ChangedValues,

351 SparseSolver<CVPLatticeKey, CVPLatticeVal> &SS) {

352

353 if (I.use_empty())

354 return;

355 auto RegI = CVPLatticeKey(&I, IPOGrouping::Register);

356 ChangedValues[RegI] = getOverdefinedVal();

357 }

358};

359}

360

361namespace llvm {

362

363

364

367 return Key.getPointer();

368 }

370 return CVPLatticeKey(V, IPOGrouping::Register);

371 }

372};

373}

374

376

377 CVPLatticeFunc Lattice;

379

380

381

385

386

387

389

390

391

394 for (CallBase *C : Lattice.getIndirectCalls()) {

395 auto RegI = CVPLatticeKey(C->getCalledOperand(), IPOGrouping::Register);

397 if (!LV.isFunctionSet() || LV.getFunctions().empty())

398 continue;

400 C->setMetadata(LLVMContext::MD_callees, Callees);

402 }

403

405}

406

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static cl::opt< unsigned > MaxFunctionsPerValue("cvp-max-functions-per-value", cl::Hidden, cl::init(4), cl::desc("The maximum number of functions to track per lattice value"))

The maximum number of functions to track per lattice value.

static bool runCVP(Module &M)

Definition CalledValuePropagation.cpp:375

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

Module.h This file contains the declarations for the Module class.

static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")

static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")

AbstractLatticeFunction - This class is implemented by the dataflow instance to specify what the latt...

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

Function * getCalledFunction() const

Returns the function called, or null if this is an indirect function invocation or the function signa...

Value * getArgOperand(unsigned i) const

PreservedAnalyses run(Module &M, ModuleAnalysisManager &)

Definition CalledValuePropagation.cpp:407

LLVM_ABI MDNode * createCallees(ArrayRef< Function * > Callees)

Return metadata indicating the possible callees of indirect calls.

A Module instance is used to store all the information related to an LLVM module.

PointerIntPair - This class implements a pair of a pointer and small integer.

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.

Wrapper class representing virtual and physical registers.

SparseSolver - This class is a general purpose solver for Sparse Conditional Propagation with a progr...

void MarkBlockExecutable(BasicBlock *BB)

MarkBlockExecutable - This method can be used by clients to mark all of the blocks that are known to ...

void Solve()

Solve - Solve for constants and executable blocks.

LatticeVal getExistingValueState(LatticeKey Key) const

getExistingValueState - Return the LatticeVal object corresponding to the given value from the ValueS...

bool isVoidTy() const

Return true if this is 'void'.

LLVM Value Representation.

Type * getType() const

All values are typed, get the type of this value.

LLVM_ABI StringRef getName() const

Return a constant reference to the value's name.

This class provides various memory handling functions that manipulate MemoryBlock instances.

@ C

The default llvm calling convention, compatible with C.

initializer< Ty > init(const Ty &Val)

This is an optimization pass for GlobalISel generic memory operations.

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

bool operator!=(uint64_t V1, const APInt &V2)

bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)

bool canTrackGlobalVariableInterprocedurally(GlobalVariable *GV)

Determine if the value maintained in the given global variable can be tracked interprocedurally.

bool is_sorted(R &&Range, Compare C)

Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key

bool canTrackReturnsInterprocedurally(Function *F)

Determine if the values of the given function's returns can be tracked interprocedurally.

OutputIt move(R &&Range, OutputIt Out)

Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

bool canTrackArgumentsInterprocedurally(Function *F)

Determine if the values of the given function's arguments can be tracked interprocedurally.

AnalysisManager< Module > ModuleAnalysisManager

Convenience typedef for the Module analysis manager.

static CVPLatticeKey getLatticeKeyFromValue(Value *V)

Definition CalledValuePropagation.cpp:369

static Value * getValueFromLatticeKey(CVPLatticeKey Key)

Definition CalledValuePropagation.cpp:366

A template for translating between LLVM Values and LatticeKeys.