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

1

2

3

4

5

6

7

8

9

10

11

12

26

27#include

28

29using namespace llvm;

30

31#define DEBUG_TYPE "lower-expect-intrinsic"

32

34 "Number of 'expect' intrinsic instructions handled");

35

36

37

38

39

40

41

42

43

44

45

46

47

50 cl::desc("Weight of the branch likely to be taken (default = 2000)"));

53 cl::desc("Weight of the branch unlikely to be taken (default = 1)"));

54

55static std::tuple<uint32_t, uint32_t>

57 if (IntrinsicID == Intrinsic::expect) {

58

61 } else {

62

64 "expect with probability must have 3 arguments");

65 auto *Confidence = cast(CI->getArgOperand(2));

66 double TrueProb = Confidence->getValueAPF().convertToDouble();

67 assert((TrueProb >= 0.0 && TrueProb <= 1.0) &&

68 "probability value must be in the range [0.0, 1.0]");

69 double FalseProb = (1.0 - TrueProb) / (BranchCount - 1);

70 uint32_t LikelyBW = ceil((TrueProb * (double)(INT32_MAX - 1)) + 1.0);

71 uint32_t UnlikelyBW = ceil((FalseProb * (double)(INT32_MAX - 1)) + 1.0);

72 return std::make_tuple(LikelyBW, UnlikelyBW);

73 }

74}

75

77 CallInst *CI = dyn_cast(SI.getCondition());

78 if (!CI)

79 return false;

80

82 if (!Fn || (Fn->getIntrinsicID() != Intrinsic::expect &&

83 Fn->getIntrinsicID() != Intrinsic::expect_with_probability))

84 return false;

85

88 if (!ExpectedValue)

89 return false;

90

92 unsigned n = SI.getNumCases();

93 uint32_t LikelyBranchWeightVal, UnlikelyBranchWeightVal;

94 std::tie(LikelyBranchWeightVal, UnlikelyBranchWeightVal) =

96

98

100 Weights[Index] = LikelyBranchWeightVal;

101

103

104 SI.setCondition(ArgValue);

106 return true;

107}

108

109

110

111

112

113

114

115

119 if (!ExpectedValue)

120 return;

121 const APInt &ExpectedPhiValue = ExpectedValue->getValue();

122 bool ExpectedValueIsLikely = true;

124

125

126

127

128 if (Fn->getIntrinsicID() == Intrinsic::expect_with_probability) {

129 auto *Confidence = cast(Expect->getArgOperand(2));

130 double TrueProb = Confidence->getValueAPF().convertToDouble();

131 ExpectedValueIsLikely = (TrueProb > 0.5);

132 }

133

134

135

136

137

138

139

140

141

142

143

146 while (!isa(V)) {

147 if (ZExtInst *ZExt = dyn_cast(V)) {

148 V = ZExt->getOperand(0);

150 continue;

151 }

152

153 if (SExtInst *SExt = dyn_cast(V)) {

154 V = SExt->getOperand(0);

156 continue;

157 }

158

160 if (!BinOp || BinOp->getOpcode() != Instruction::Xor)

161 return;

162

164 if (!CInt)

165 return;

166

169 }

170

171

172 auto ApplyOperations = [&](const APInt &Value) {

175 switch (Op->getOpcode()) {

176 case Instruction::Xor:

177 Result ^= cast(Op->getOperand(1))->getValue();

178 break;

179 case Instruction::ZExt:

180 Result = Result.zext(Op->getType()->getIntegerBitWidth());

181 break;

182 case Instruction::SExt:

183 Result = Result.sext(Op->getType()->getIntegerBitWidth());

184 break;

185 default:

187 }

188 }

189 return Result;

190 };

191

192 auto *PhiDef = cast(V);

193

194

195

196 auto GetDomConditional = [&](unsigned i) -> BranchInst * {

197 BasicBlock *BB = PhiDef->getIncomingBlock(i);

200 return BI;

202 if (!BB)

203 return nullptr;

206 return nullptr;

207 return BI;

208 };

209

210

211

212

213 for (unsigned i = 0, e = PhiDef->getNumIncomingValues(); i != e; ++i) {

214

215 Value *PhiOpnd = PhiDef->getIncomingValue(i);

216 ConstantInt *CI = dyn_cast(PhiOpnd);

217 if (!CI)

218 continue;

219

220

221

222

223

224

225 const APInt &CurrentPhiValue = ApplyOperations(CI->getValue());

226 if (ExpectedValueIsLikely == (ExpectedPhiValue == CurrentPhiValue))

227 continue;

228

229 BranchInst *BI = GetDomConditional(i);

230 if (!BI)

231 continue;

232

233 MDBuilder MDB(PhiDef->getContext());

234

235

236

237

238

239

240

241

242

243 auto *OpndIncomingBB = PhiDef->getIncomingBlock(i);

244 auto IsOpndComingFromSuccessor = [&](BasicBlock *Succ) {

245 if (OpndIncomingBB == Succ)

246

247

248 return true;

249 if (OpndIncomingBB == BI->getParent() && Succ == PhiDef->getParent())

250

251

252

253 return true;

254 return false;

255 };

256 uint32_t LikelyBranchWeightVal, UnlikelyBranchWeightVal;

257 std::tie(LikelyBranchWeightVal, UnlikelyBranchWeightVal) = getBranchWeight(

259 if (!ExpectedValueIsLikely)

260 std::swap(LikelyBranchWeightVal, UnlikelyBranchWeightVal);

261

262 if (IsOpndComingFromSuccessor(BI->getSuccessor(1)))

265 UnlikelyBranchWeightVal,

266 true));

267 else if (IsOpndComingFromSuccessor(BI->getSuccessor(0)))

270 LikelyBranchWeightVal,

271 true));

272 }

273}

274

275

277

278

279

280

281

282

283

284

285

286

288

289 ICmpInst *CmpI = dyn_cast(BSI.getCondition());

292 if (!CmpI) {

293 CI = dyn_cast(BSI.getCondition());

295 } else {

298 return false;

299

300 CmpConstOperand = dyn_cast(CmpI->getOperand(1));

301 if (!CmpConstOperand)

302 return false;

303 CI = dyn_cast(CmpI->getOperand(0));

304 }

305

306 if (!CI)

307 return false;

308

309 uint64_t ValueComparedTo = 0;

310 if (CmpConstOperand) {

312 return false;

313 ValueComparedTo = CmpConstOperand->getZExtValue();

314 }

315

317 if (!Fn || (Fn->getIntrinsicID() != Intrinsic::expect &&

318 Fn->getIntrinsicID() != Intrinsic::expect_with_probability))

319 return false;

320

323 if (!ExpectedValue)

324 return false;

325

328

329 uint32_t LikelyBranchWeightVal, UnlikelyBranchWeightVal;

330 std::tie(LikelyBranchWeightVal, UnlikelyBranchWeightVal) =

332

334 if ((ExpectedValue->getZExtValue() == ValueComparedTo) ==

337 LikelyBranchWeightVal, UnlikelyBranchWeightVal, true);

338 ExpectedWeights = {LikelyBranchWeightVal, UnlikelyBranchWeightVal};

339 } else {

341 LikelyBranchWeightVal, true);

342 ExpectedWeights = {UnlikelyBranchWeightVal, LikelyBranchWeightVal};

343 }

344

345 if (CmpI)

347 else

348 BSI.setCondition(ArgValue);

349

351

352 BSI.setMetadata(LLVMContext::MD_prof, Node);

353

354 return true;

355}

356

359 return false;

360

361 return handleBrSelExpect(BI);

362}

363

365 bool Changed = false;

366

368

369 if (BranchInst *BI = dyn_cast(BB.getTerminator())) {

371 ExpectIntrinsicsHandled++;

372 } else if (SwitchInst *SI = dyn_cast(BB.getTerminator())) {

374 ExpectIntrinsicsHandled++;

375 }

376

377

378

379

381 CallInst *CI = dyn_cast(&Inst);

382 if (!CI) {

383 if (SelectInst *SI = dyn_cast(&Inst)) {

385 ExpectIntrinsicsHandled++;

386 }

387 continue;

388 }

389

391 if (Fn && (Fn->getIntrinsicID() == Intrinsic::expect ||

392 Fn->getIntrinsicID() == Intrinsic::expect_with_probability)) {

393

394

395

400 Changed = true;

401 }

402 }

403 }

404

405 return Changed;

406}

407

412

414}

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

static cl::opt< uint32_t > UnlikelyBranchWeight("unlikely-branch-weight", cl::Hidden, cl::init(1), cl::desc("Weight of the branch unlikely to be taken (default = 1)"))

static bool handleBranchExpect(BranchInst &BI)

static std::tuple< uint32_t, uint32_t > getBranchWeight(Intrinsic::ID IntrinsicID, CallInst *CI, int BranchCount)

static bool handleBrSelExpect(BrSelInst &BSI)

static cl::opt< uint32_t > LikelyBranchWeight("likely-branch-weight", cl::Hidden, cl::init(2000), cl::desc("Weight of the branch likely to be taken (default = 2000)"))

static bool handleSwitchExpect(SwitchInst &SI)

static bool lowerExpectIntrinsic(Function &F)

static void handlePhiDef(CallInst *Expect)

Handler for PHINodes that define the value argument to an @llvm.expect call.

The header file for the LowerExpectIntrinsic pass as used by the new pass manager.

This file contains the declarations for profiling metadata utility functions.

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

This file defines the SmallVector class.

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

Class for arbitrary precision integers.

A container for analyses that lazily runs them and caches their results.

LLVM Basic Block Representation.

const BasicBlock * getSinglePredecessor() const

Return the predecessor of this block if it has a single predecessor block.

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...

BinaryOps getOpcode() const

Conditional or Unconditional Branch instruction.

bool isConditional() const

BasicBlock * getSuccessor(unsigned i) const

bool isUnconditional() const

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

This class represents a function call, abstracting a target machine's calling convention.

Predicate

This enumeration lists the possible predicates for CmpInst subclasses.

Predicate getPredicate() const

Return the predicate for this instruction.

This is the shared class of boolean and integer constants.

unsigned getBitWidth() const

getBitWidth - Return the scalar bitwidth of this constant.

uint64_t getZExtValue() const

Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...

const APInt & getValue() const

Return the constant as an APInt value reference.

This class represents an Operation in the Expression.

Intrinsic::ID getIntrinsicID() const LLVM_READONLY

getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...

This instruction compares its operands according to the predicate given to the constructor.

InstListType::iterator eraseFromParent()

This method unlinks 'this' from the containing basic block and deletes it.

void setMetadata(unsigned KindID, MDNode *Node)

Set the metadata of the specified kind to the specified node.

MDNode * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight, bool IsExpected=false)

Return metadata containing two branch weights.

A set of analyses that are preserved following a run of a transformation pass.

static PreservedAnalyses none()

Convenience factory function for the empty preserved set.

static PreservedAnalyses all()

Construct a special preserved set that preserves all passes.

This class represents a sign extension of integer types.

This class represents the LLVM 'select' instruction.

void push_back(const T &Elt)

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

unsigned getCaseIndex() const

Returns number of current case.

void setOperand(unsigned i, Value *Val)

Value * getOperand(unsigned i) const

unsigned getNumOperands() const

LLVM Value Representation.

void replaceAllUsesWith(Value *V)

Change all uses of this to point to a new Value.

LLVMContext & getContext() const

All values hold a context through their type.

This class represents zero extension of integer types.

const ParentTy * getParent() const

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

initializer< Ty > init(const Ty &Val)

void checkFrontendInstrumentation(Instruction &I, const ArrayRef< uint32_t > ExpectedWeights)

checkFrontendInstrumentation - compares PGO counters to the thresholds used for llvm....

void checkExpectAnnotations(Instruction &I, const ArrayRef< uint32_t > ExistingWeights, bool IsFrontend)

checkExpectAnnotations - compares PGO counters to the thresholds used for llvm.expect and warns if th...

This is an optimization pass for GlobalISel generic memory operations.

iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)

Make a range that does early increment to allow mutation of the underlying range without disrupting i...

auto reverse(ContainerTy &&C)

void setBranchWeights(Instruction &I, ArrayRef< uint32_t > Weights, bool IsExpected)

Create a new branch_weights metadata node and add or overwrite a prof metadata reference to instructi...

void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)

Implement std::swap in terms of BitVector swap.

PreservedAnalyses run(Function &F, FunctionAnalysisManager &)

Run the pass over the function.