LLVM: lib/IR/DIExpressionOptimizer.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

16

17using namespace llvm;

18

19

21 if (Op.getOp() == dwarf::DW_OP_constu)

22 return Op.getArg(0);

23 return std::nullopt;

24}

25

26

28 switch (Op) {

29 case dwarf::DW_OP_plus:

30 case dwarf::DW_OP_minus:

31 case dwarf::DW_OP_shl:

32 case dwarf::DW_OP_shr:

33 return Val == 0;

34 case dwarf::DW_OP_mul:

35 case dwarf::DW_OP_div:

36 return Val == 1;

37 default:

38 return false;

39 }

40}

41

42

43

44static std::optional<uint64_t>

47

48 bool ResultOverflowed;

50 case dwarf::DW_OP_plus: {

51 auto Result = SaturatingAdd(Const1, Const2, &ResultOverflowed);

52 if (ResultOverflowed)

53 return std::nullopt;

54 return Result;

55 }

56 case dwarf::DW_OP_minus: {

57 if (Const1 < Const2)

58 return std::nullopt;

59 return Const1 - Const2;

60 }

61 case dwarf::DW_OP_shl: {

62 if (Const2 >= std::numeric_limits<uint64_t>::digits ||

64 return std::nullopt;

65 return Const1 << Const2;

66 }

67 case dwarf::DW_OP_shr: {

68 if (Const2 >= std::numeric_limits<uint64_t>::digits ||

70 return std::nullopt;

71 return Const1 >> Const2;

72 }

73 case dwarf::DW_OP_mul: {

75 if (ResultOverflowed)

76 return std::nullopt;

77 return Result;

78 }

79 case dwarf::DW_OP_div: {

80 if (Const2)

81 return Const1 / Const2;

82 return std::nullopt;

83 }

84 default:

85 return std::nullopt;

86 }

87}

88

89

90

93 return Operator1 == Operator2 &&

94 (Operator1 == dwarf::DW_OP_plus || Operator1 == dwarf::DW_OP_mul);

95}

96

97

100 Cursor.consume(1);

102}

103

104

107 Cursor.assignNewExpr(WorkingOps);

109}

110

111

112

113

119 while (Loc < WorkingOps.size()) {

120 auto Op = Cursor.peek();

121

122 if (Op)

123 break;

124 auto OpRaw = Op->getOp();

125

126 if (OpRaw >= dwarf::DW_OP_lit0 && OpRaw <= dwarf::DW_OP_lit31) {

127 ResultOps.push_back(dwarf::DW_OP_constu);

128 ResultOps.push_back(OpRaw - dwarf::DW_OP_lit0);

130 continue;

131 }

132 if (OpRaw == dwarf::DW_OP_plus_uconst) {

133 ResultOps.push_back(dwarf::DW_OP_constu);

135 ResultOps.push_back(dwarf::DW_OP_plus);

137 continue;

138 }

141 ResultOps.append(WorkingOps.begin() + PrevLoc, WorkingOps.begin() + Loc);

142 }

143 return ResultOps;

144}

145

146

147

148

154 while (Loc < WorkingOps.size()) {

155 auto Op1 = Cursor.peek();

156

157 if (!Op1)

158 break;

159 auto Op1Raw = Op1->getOp();

160

161 if (Op1Raw == dwarf::DW_OP_constu && Op1->getArg(0) == 0) {

162 ResultOps.push_back(dwarf::DW_OP_lit0);

164 continue;

165 }

166

167 auto Op2 = Cursor.peekNext();

168

169 if (!Op2) {

172 ResultOps.append(WorkingOps.begin() + PrevLoc, WorkingOps.begin() + Loc);

173 break;

174 }

175 auto Op2Raw = Op2->getOp();

176

177 if (Op1Raw == dwarf::DW_OP_constu && Op2Raw == dwarf::DW_OP_plus) {

178 ResultOps.push_back(dwarf::DW_OP_plus_uconst);

179 ResultOps.push_back(Op1->getArg(0));

182 continue;

183 }

186 ResultOps.append(WorkingOps.begin() + PrevLoc, WorkingOps.begin() + Loc);

187 }

188 return ResultOps;

189}

190

191

192

197

201 return true;

202 }

203 return false;

204}

205

206

207

208

213

215 if (!Const2)

216 return false;

217

220 if (!Result) {

222 return true;

223 }

225 WorkingOps[Loc] = dwarf::DW_OP_constu;

226 WorkingOps[Loc + 1] = *Result;

228 return true;

229}

230

231

232

233

238

242

244 return false;

245

247 if (!Result) {

249 return true;

250 }

252 WorkingOps[Loc] = dwarf::DW_OP_constu;

253 WorkingOps[Loc + 1] = *Result;

255 return true;

256}

257

258

259

260

261

265

270

274 return false;

275

277 if (!Result) {

279 return true;

280 }

282 WorkingOps[Loc] = dwarf::DW_OP_constu;

283 WorkingOps[Loc + 1] = *Result;

285 return true;

286}

287

289

295

296

297

298 while (Loc < ResultOps.size()) {

299 Ops.clear();

300

301 auto Op = Cursor.peek();

302

303 if (Op)

304 break;

305

307

308 if (!Const1) {

309

311 continue;

312 }

313

314 Ops.push_back(*Op);

315

316 Op = Cursor.peekNext();

317

318 if (Op)

319 break;

320

321 Ops.push_back(*Op);

322

323

325 continue;

326

327 Op = Cursor.peekNextN(2);

328

329 if (Op) {

331 continue;

332 }

333

334 Ops.push_back(*Op);

335

336

338 continue;

339

340 Op = Cursor.peekNextN(3);

341

342 if (Op) {

344 continue;

345 }

346

347 Ops.push_back(*Op);

348

349

351 continue;

352

353 Op = Cursor.peekNextN(4);

354 if (Op) {

356 continue;

357 }

358

359 Ops.push_back(*Op);

360 Op = Cursor.peekNextN(5);

361 if (Op) {

363 continue;

364 }

365

366 Ops.push_back(*Op);

367

368

369

371 ResultOps))

372 continue;

373

375 }

378 assert(Result->isValid() && "concatenated expression is not valid");

379 return Result;

380}

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

static bool tryFoldNoOpMath(uint64_t Const1, ArrayRef< DIExpression::ExprOperand > Ops, uint64_t &Loc, DIExpressionCursor &Cursor, SmallVectorImpl< uint64_t > &WorkingOps)

{DW_OP_constu, 0, DW_OP_[plus, minus, shl, shr]} -> {} {DW_OP_constu, 1, DW_OP_[mul,...

Definition DIExpressionOptimizer.cpp:193

static bool operationsAreFoldableAndCommutative(dwarf::LocationAtom Operator1, dwarf::LocationAtom Operator2)

Returns true if the two operations Operator1 and Operator2 are commutative and can be folded.

Definition DIExpressionOptimizer.cpp:91

static bool isNeutralElement(uint64_t Op, uint64_t Val)

Returns true if an operation and operand result in a No Op.

Definition DIExpressionOptimizer.cpp:27

static std::optional< uint64_t > foldOperationIfPossible(uint64_t Const1, uint64_t Const2, dwarf::LocationAtom Operator)

Try to fold Const1 and Const2 by applying Operator and returning the result, if there is an overflow,...

Definition DIExpressionOptimizer.cpp:45

static bool tryFoldCommutativeMath(uint64_t Const1, ArrayRef< DIExpression::ExprOperand > Ops, uint64_t &Loc, DIExpressionCursor &Cursor, SmallVectorImpl< uint64_t > &WorkingOps)

{DW_OP_constu, Const1, DW_OP_[plus, mul], DW_OP_constu, Const2, DW_OP_[plus, mul]}...

Definition DIExpressionOptimizer.cpp:234

void startFromBeginning(uint64_t &Loc, DIExpressionCursor &Cursor, ArrayRef< uint64_t > WorkingOps)

Reset the Cursor to the beginning of the WorkingOps.

Definition DIExpressionOptimizer.cpp:105

static SmallVector< uint64_t > optimizeDwarfOperations(ArrayRef< uint64_t > WorkingOps)

This function will convert:

Definition DIExpressionOptimizer.cpp:150

static bool tryFoldCommutativeMathWithArgInBetween(uint64_t Const1, ArrayRef< DIExpression::ExprOperand > Ops, uint64_t &Loc, DIExpressionCursor &Cursor, SmallVectorImpl< uint64_t > &WorkingOps)

{DW_OP_constu, Const1, DW_OP_[plus, mul], DW_OP_LLVM_arg, Arg1, DW_OP_[plus, mul],...

Definition DIExpressionOptimizer.cpp:262

static bool tryFoldConstants(uint64_t Const1, ArrayRef< DIExpression::ExprOperand > Ops, uint64_t &Loc, DIExpressionCursor &Cursor, SmallVectorImpl< uint64_t > &WorkingOps)

{DW_OP_constu, Const1, DW_OP_constu, Const2, DW_OP_[plus, minus, mul, div, shl, shr] -> {DW_OP_constu...

Definition DIExpressionOptimizer.cpp:209

static void consumeOneOperator(DIExpressionCursor &Cursor, uint64_t &Loc, const DIExpression::ExprOperand &Op)

Consume one operator and its operand(s).

Definition DIExpressionOptimizer.cpp:98

static std::optional< uint64_t > isConstantVal(DIExpression::ExprOperand Op)

Returns true if the Op is a DW_OP_constu.

Definition DIExpressionOptimizer.cpp:20

static SmallVector< uint64_t > canonicalizeDwarfOperations(ArrayRef< uint64_t > WorkingOps)

This function will canonicalize:

Definition DIExpressionOptimizer.cpp:115

This file contains constants used for implementing Dwarf debug support.

const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

size_t size() const

size - Get the array size.

Holds a DIExpression and keeps track of how many operands have been consumed so far.

A lightweight wrapper around an expression operand.

LLVM_ABI DIExpression * foldConstantMath()

Try to shorten an expression with constant math operations that can be evaluated at compile time.

Definition DIExpressionOptimizer.cpp:288

static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)

LLVMContext & getContext() const

This is a utility class that provides an abstraction for the common functionality between Instruction...

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

iterator erase(const_iterator CI)

void append(ItTy in_start, ItTy in_end)

Add the specified range to the end of the SmallVector.

void push_back(const T &Elt)

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

@ DW_OP_LLVM_arg

Only used in LLVM metadata.

This is an optimization pass for GlobalISel generic memory operations.

int countr_zero(T Val)

Count number of 0's from the least significant bit to the most stopping at the first 1.

int countl_zero(T Val)

Count number of 0's from the most significant bit to the least stopping at the first 1.

std::enable_if_t< std::is_unsigned_v< T >, T > SaturatingMultiply(T X, T Y, bool *ResultOverflowed=nullptr)

Multiply two unsigned integers, X and Y, of type T.

DWARFExpression::Operation Op

std::enable_if_t< std::is_unsigned_v< T >, T > SaturatingAdd(T X, T Y, bool *ResultOverflowed=nullptr)

Add two unsigned integers, X and Y, of type T.