1b12f81b5SShubham Sandeep Rastogi //===- DIExpressionOptimizer.cpp - Constant folding of DIExpressions ------===// 2b12f81b5SShubham Sandeep Rastogi // 3b12f81b5SShubham Sandeep Rastogi // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4b12f81b5SShubham Sandeep Rastogi // See https://llvm.org/LICENSE.txt for license information. 5b12f81b5SShubham Sandeep Rastogi // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6b12f81b5SShubham Sandeep Rastogi // 7b12f81b5SShubham Sandeep Rastogi //===----------------------------------------------------------------------===// 8b12f81b5SShubham Sandeep Rastogi // 9b12f81b5SShubham Sandeep Rastogi // This file implements functions to constant fold DIExpressions. Which were 10b12f81b5SShubham Sandeep Rastogi // declared in DIExpressionOptimizer.h 11b12f81b5SShubham Sandeep Rastogi // 12b12f81b5SShubham Sandeep Rastogi //===----------------------------------------------------------------------===// 13b12f81b5SShubham Sandeep Rastogi 14b12f81b5SShubham Sandeep Rastogi #include "llvm/BinaryFormat/Dwarf.h" 15b12f81b5SShubham Sandeep Rastogi #include "llvm/IR/DebugInfoMetadata.h" 16b12f81b5SShubham Sandeep Rastogi 17b12f81b5SShubham Sandeep Rastogi using namespace llvm; 18b12f81b5SShubham Sandeep Rastogi 19b12f81b5SShubham Sandeep Rastogi /// Returns true if the Op is a DW_OP_constu. 20b12f81b5SShubham Sandeep Rastogi static std::optional<uint64_t> isConstantVal(DIExpression::ExprOperand Op) { 21b12f81b5SShubham Sandeep Rastogi if (Op.getOp() == dwarf::DW_OP_constu) 22b12f81b5SShubham Sandeep Rastogi return Op.getArg(0); 23b12f81b5SShubham Sandeep Rastogi return std::nullopt; 24b12f81b5SShubham Sandeep Rastogi } 25b12f81b5SShubham Sandeep Rastogi 26b12f81b5SShubham Sandeep Rastogi /// Returns true if an operation and operand result in a No Op. 27b12f81b5SShubham Sandeep Rastogi static bool isNeutralElement(uint64_t Op, uint64_t Val) { 28b12f81b5SShubham Sandeep Rastogi switch (Op) { 29b12f81b5SShubham Sandeep Rastogi case dwarf::DW_OP_plus: 30b12f81b5SShubham Sandeep Rastogi case dwarf::DW_OP_minus: 31b12f81b5SShubham Sandeep Rastogi case dwarf::DW_OP_shl: 32b12f81b5SShubham Sandeep Rastogi case dwarf::DW_OP_shr: 33b12f81b5SShubham Sandeep Rastogi return Val == 0; 34b12f81b5SShubham Sandeep Rastogi case dwarf::DW_OP_mul: 35b12f81b5SShubham Sandeep Rastogi case dwarf::DW_OP_div: 36b12f81b5SShubham Sandeep Rastogi return Val == 1; 37b12f81b5SShubham Sandeep Rastogi default: 38b12f81b5SShubham Sandeep Rastogi return false; 39b12f81b5SShubham Sandeep Rastogi } 40b12f81b5SShubham Sandeep Rastogi } 41b12f81b5SShubham Sandeep Rastogi 42b12f81b5SShubham Sandeep Rastogi /// Try to fold \p Const1 and \p Const2 by applying \p Operator and returning 43b12f81b5SShubham Sandeep Rastogi /// the result, if there is an overflow, return a std::nullopt. 44b12f81b5SShubham Sandeep Rastogi static std::optional<uint64_t> 45b12f81b5SShubham Sandeep Rastogi foldOperationIfPossible(uint64_t Const1, uint64_t Const2, 46b12f81b5SShubham Sandeep Rastogi dwarf::LocationAtom Operator) { 47b12f81b5SShubham Sandeep Rastogi 48b12f81b5SShubham Sandeep Rastogi bool ResultOverflowed; 49b12f81b5SShubham Sandeep Rastogi switch (Operator) { 50b12f81b5SShubham Sandeep Rastogi case dwarf::DW_OP_plus: { 51b12f81b5SShubham Sandeep Rastogi auto Result = SaturatingAdd(Const1, Const2, &ResultOverflowed); 52b12f81b5SShubham Sandeep Rastogi if (ResultOverflowed) 53b12f81b5SShubham Sandeep Rastogi return std::nullopt; 54b12f81b5SShubham Sandeep Rastogi return Result; 55b12f81b5SShubham Sandeep Rastogi } 56b12f81b5SShubham Sandeep Rastogi case dwarf::DW_OP_minus: { 57b12f81b5SShubham Sandeep Rastogi if (Const1 < Const2) 58b12f81b5SShubham Sandeep Rastogi return std::nullopt; 59b12f81b5SShubham Sandeep Rastogi return Const1 - Const2; 60b12f81b5SShubham Sandeep Rastogi } 61b12f81b5SShubham Sandeep Rastogi case dwarf::DW_OP_shl: { 62*dc087d1aSTom Honermann if (Const2 >= std::numeric_limits<uint64_t>::digits || 63*dc087d1aSTom Honermann static_cast<uint64_t>(countl_zero(Const1)) < Const2) 64b12f81b5SShubham Sandeep Rastogi return std::nullopt; 65b12f81b5SShubham Sandeep Rastogi return Const1 << Const2; 66b12f81b5SShubham Sandeep Rastogi } 67b12f81b5SShubham Sandeep Rastogi case dwarf::DW_OP_shr: { 68*dc087d1aSTom Honermann if (Const2 >= std::numeric_limits<uint64_t>::digits || 69*dc087d1aSTom Honermann static_cast<uint64_t>(countr_zero(Const1)) < Const2) 70b12f81b5SShubham Sandeep Rastogi return std::nullopt; 71b12f81b5SShubham Sandeep Rastogi return Const1 >> Const2; 72b12f81b5SShubham Sandeep Rastogi } 73b12f81b5SShubham Sandeep Rastogi case dwarf::DW_OP_mul: { 74b12f81b5SShubham Sandeep Rastogi auto Result = SaturatingMultiply(Const1, Const2, &ResultOverflowed); 75b12f81b5SShubham Sandeep Rastogi if (ResultOverflowed) 76b12f81b5SShubham Sandeep Rastogi return std::nullopt; 77b12f81b5SShubham Sandeep Rastogi return Result; 78b12f81b5SShubham Sandeep Rastogi } 79b12f81b5SShubham Sandeep Rastogi case dwarf::DW_OP_div: { 80b12f81b5SShubham Sandeep Rastogi if (Const2) 81b12f81b5SShubham Sandeep Rastogi return Const1 / Const2; 82b12f81b5SShubham Sandeep Rastogi return std::nullopt; 83b12f81b5SShubham Sandeep Rastogi } 84b12f81b5SShubham Sandeep Rastogi default: 85b12f81b5SShubham Sandeep Rastogi return std::nullopt; 86b12f81b5SShubham Sandeep Rastogi } 87b12f81b5SShubham Sandeep Rastogi } 88b12f81b5SShubham Sandeep Rastogi 89b12f81b5SShubham Sandeep Rastogi /// Returns true if the two operations \p Operator1 and \p Operator2 are 90b12f81b5SShubham Sandeep Rastogi /// commutative and can be folded. 91b12f81b5SShubham Sandeep Rastogi static bool operationsAreFoldableAndCommutative(dwarf::LocationAtom Operator1, 92b12f81b5SShubham Sandeep Rastogi dwarf::LocationAtom Operator2) { 93b12f81b5SShubham Sandeep Rastogi return Operator1 == Operator2 && 94b12f81b5SShubham Sandeep Rastogi (Operator1 == dwarf::DW_OP_plus || Operator1 == dwarf::DW_OP_mul); 95b12f81b5SShubham Sandeep Rastogi } 96b12f81b5SShubham Sandeep Rastogi 97b12f81b5SShubham Sandeep Rastogi /// Consume one operator and its operand(s). 98b12f81b5SShubham Sandeep Rastogi static void consumeOneOperator(DIExpressionCursor &Cursor, uint64_t &Loc, 99b12f81b5SShubham Sandeep Rastogi const DIExpression::ExprOperand &Op) { 100b12f81b5SShubham Sandeep Rastogi Cursor.consume(1); 101b12f81b5SShubham Sandeep Rastogi Loc = Loc + Op.getSize(); 102b12f81b5SShubham Sandeep Rastogi } 103b12f81b5SShubham Sandeep Rastogi 104b12f81b5SShubham Sandeep Rastogi /// Reset the Cursor to the beginning of the WorkingOps. 105b12f81b5SShubham Sandeep Rastogi void startFromBeginning(uint64_t &Loc, DIExpressionCursor &Cursor, 106b12f81b5SShubham Sandeep Rastogi ArrayRef<uint64_t> WorkingOps) { 107b12f81b5SShubham Sandeep Rastogi Cursor.assignNewExpr(WorkingOps); 108b12f81b5SShubham Sandeep Rastogi Loc = 0; 109b12f81b5SShubham Sandeep Rastogi } 110b12f81b5SShubham Sandeep Rastogi 111b12f81b5SShubham Sandeep Rastogi /// This function will canonicalize: 112b12f81b5SShubham Sandeep Rastogi /// 1. DW_OP_plus_uconst to DW_OP_constu <const-val> DW_OP_plus 113b12f81b5SShubham Sandeep Rastogi /// 2. DW_OP_lit<n> to DW_OP_constu <n> 114b12f81b5SShubham Sandeep Rastogi static SmallVector<uint64_t> 115b12f81b5SShubham Sandeep Rastogi canonicalizeDwarfOperations(ArrayRef<uint64_t> WorkingOps) { 116b12f81b5SShubham Sandeep Rastogi DIExpressionCursor Cursor(WorkingOps); 117b12f81b5SShubham Sandeep Rastogi uint64_t Loc = 0; 118b12f81b5SShubham Sandeep Rastogi SmallVector<uint64_t> ResultOps; 119b12f81b5SShubham Sandeep Rastogi while (Loc < WorkingOps.size()) { 120b12f81b5SShubham Sandeep Rastogi auto Op = Cursor.peek(); 121b12f81b5SShubham Sandeep Rastogi /// Expression has no operations, break. 122b12f81b5SShubham Sandeep Rastogi if (!Op) 123b12f81b5SShubham Sandeep Rastogi break; 124b12f81b5SShubham Sandeep Rastogi auto OpRaw = Op->getOp(); 125b12f81b5SShubham Sandeep Rastogi 126b12f81b5SShubham Sandeep Rastogi if (OpRaw >= dwarf::DW_OP_lit0 && OpRaw <= dwarf::DW_OP_lit31) { 127b12f81b5SShubham Sandeep Rastogi ResultOps.push_back(dwarf::DW_OP_constu); 128b12f81b5SShubham Sandeep Rastogi ResultOps.push_back(OpRaw - dwarf::DW_OP_lit0); 129b12f81b5SShubham Sandeep Rastogi consumeOneOperator(Cursor, Loc, *Cursor.peek()); 130b12f81b5SShubham Sandeep Rastogi continue; 131b12f81b5SShubham Sandeep Rastogi } 132b12f81b5SShubham Sandeep Rastogi if (OpRaw == dwarf::DW_OP_plus_uconst) { 133b12f81b5SShubham Sandeep Rastogi ResultOps.push_back(dwarf::DW_OP_constu); 134b12f81b5SShubham Sandeep Rastogi ResultOps.push_back(Op->getArg(0)); 135b12f81b5SShubham Sandeep Rastogi ResultOps.push_back(dwarf::DW_OP_plus); 136b12f81b5SShubham Sandeep Rastogi consumeOneOperator(Cursor, Loc, *Cursor.peek()); 137b12f81b5SShubham Sandeep Rastogi continue; 138b12f81b5SShubham Sandeep Rastogi } 139b12f81b5SShubham Sandeep Rastogi uint64_t PrevLoc = Loc; 140b12f81b5SShubham Sandeep Rastogi consumeOneOperator(Cursor, Loc, *Cursor.peek()); 141b12f81b5SShubham Sandeep Rastogi ResultOps.append(WorkingOps.begin() + PrevLoc, WorkingOps.begin() + Loc); 142b12f81b5SShubham Sandeep Rastogi } 143b12f81b5SShubham Sandeep Rastogi return ResultOps; 144b12f81b5SShubham Sandeep Rastogi } 145b12f81b5SShubham Sandeep Rastogi 146b12f81b5SShubham Sandeep Rastogi /// This function will convert: 147b12f81b5SShubham Sandeep Rastogi /// 1. DW_OP_constu <const-val> DW_OP_plus to DW_OP_plus_uconst 148b12f81b5SShubham Sandeep Rastogi /// 2. DW_OP_constu, 0 to DW_OP_lit0 149b12f81b5SShubham Sandeep Rastogi static SmallVector<uint64_t> 150b12f81b5SShubham Sandeep Rastogi optimizeDwarfOperations(ArrayRef<uint64_t> WorkingOps) { 151b12f81b5SShubham Sandeep Rastogi DIExpressionCursor Cursor(WorkingOps); 152b12f81b5SShubham Sandeep Rastogi uint64_t Loc = 0; 153b12f81b5SShubham Sandeep Rastogi SmallVector<uint64_t> ResultOps; 154b12f81b5SShubham Sandeep Rastogi while (Loc < WorkingOps.size()) { 155b12f81b5SShubham Sandeep Rastogi auto Op1 = Cursor.peek(); 156b12f81b5SShubham Sandeep Rastogi /// Expression has no operations, exit. 157b12f81b5SShubham Sandeep Rastogi if (!Op1) 158b12f81b5SShubham Sandeep Rastogi break; 159b12f81b5SShubham Sandeep Rastogi auto Op1Raw = Op1->getOp(); 160b12f81b5SShubham Sandeep Rastogi 161b12f81b5SShubham Sandeep Rastogi if (Op1Raw == dwarf::DW_OP_constu && Op1->getArg(0) == 0) { 162b12f81b5SShubham Sandeep Rastogi ResultOps.push_back(dwarf::DW_OP_lit0); 163b12f81b5SShubham Sandeep Rastogi consumeOneOperator(Cursor, Loc, *Cursor.peek()); 164b12f81b5SShubham Sandeep Rastogi continue; 165b12f81b5SShubham Sandeep Rastogi } 166b12f81b5SShubham Sandeep Rastogi 167b12f81b5SShubham Sandeep Rastogi auto Op2 = Cursor.peekNext(); 168b12f81b5SShubham Sandeep Rastogi /// Expression has no more operations, copy into ResultOps and exit. 169b12f81b5SShubham Sandeep Rastogi if (!Op2) { 170b12f81b5SShubham Sandeep Rastogi uint64_t PrevLoc = Loc; 171b12f81b5SShubham Sandeep Rastogi consumeOneOperator(Cursor, Loc, *Cursor.peek()); 172b12f81b5SShubham Sandeep Rastogi ResultOps.append(WorkingOps.begin() + PrevLoc, WorkingOps.begin() + Loc); 173b12f81b5SShubham Sandeep Rastogi break; 174b12f81b5SShubham Sandeep Rastogi } 175b12f81b5SShubham Sandeep Rastogi auto Op2Raw = Op2->getOp(); 176b12f81b5SShubham Sandeep Rastogi 177b12f81b5SShubham Sandeep Rastogi if (Op1Raw == dwarf::DW_OP_constu && Op2Raw == dwarf::DW_OP_plus) { 178b12f81b5SShubham Sandeep Rastogi ResultOps.push_back(dwarf::DW_OP_plus_uconst); 179b12f81b5SShubham Sandeep Rastogi ResultOps.push_back(Op1->getArg(0)); 180b12f81b5SShubham Sandeep Rastogi consumeOneOperator(Cursor, Loc, *Cursor.peek()); 181b12f81b5SShubham Sandeep Rastogi consumeOneOperator(Cursor, Loc, *Cursor.peek()); 182b12f81b5SShubham Sandeep Rastogi continue; 183b12f81b5SShubham Sandeep Rastogi } 184b12f81b5SShubham Sandeep Rastogi uint64_t PrevLoc = Loc; 185b12f81b5SShubham Sandeep Rastogi consumeOneOperator(Cursor, Loc, *Cursor.peek()); 186b12f81b5SShubham Sandeep Rastogi ResultOps.append(WorkingOps.begin() + PrevLoc, WorkingOps.begin() + Loc); 187b12f81b5SShubham Sandeep Rastogi } 188b12f81b5SShubham Sandeep Rastogi return ResultOps; 189b12f81b5SShubham Sandeep Rastogi } 190b12f81b5SShubham Sandeep Rastogi 191b12f81b5SShubham Sandeep Rastogi /// {DW_OP_constu, 0, DW_OP_[plus, minus, shl, shr]} -> {} 192b12f81b5SShubham Sandeep Rastogi /// {DW_OP_constu, 1, DW_OP_[mul, div]} -> {} 193b12f81b5SShubham Sandeep Rastogi static bool tryFoldNoOpMath(uint64_t Const1, 194b12f81b5SShubham Sandeep Rastogi ArrayRef<DIExpression::ExprOperand> Ops, 195b12f81b5SShubham Sandeep Rastogi uint64_t &Loc, DIExpressionCursor &Cursor, 196b12f81b5SShubham Sandeep Rastogi SmallVectorImpl<uint64_t> &WorkingOps) { 197b12f81b5SShubham Sandeep Rastogi 198b12f81b5SShubham Sandeep Rastogi if (isNeutralElement(Ops[1].getOp(), Const1)) { 199b12f81b5SShubham Sandeep Rastogi WorkingOps.erase(WorkingOps.begin() + Loc, WorkingOps.begin() + Loc + 3); 200b12f81b5SShubham Sandeep Rastogi startFromBeginning(Loc, Cursor, WorkingOps); 201b12f81b5SShubham Sandeep Rastogi return true; 202b12f81b5SShubham Sandeep Rastogi } 203b12f81b5SShubham Sandeep Rastogi return false; 204b12f81b5SShubham Sandeep Rastogi } 205b12f81b5SShubham Sandeep Rastogi 206b12f81b5SShubham Sandeep Rastogi /// {DW_OP_constu, Const1, DW_OP_constu, Const2, DW_OP_[plus, 207b12f81b5SShubham Sandeep Rastogi /// minus, mul, div, shl, shr] -> {DW_OP_constu, Const1 [+, -, *, /, <<, >>] 208b12f81b5SShubham Sandeep Rastogi /// Const2} 209b12f81b5SShubham Sandeep Rastogi static bool tryFoldConstants(uint64_t Const1, 210b12f81b5SShubham Sandeep Rastogi ArrayRef<DIExpression::ExprOperand> Ops, 211b12f81b5SShubham Sandeep Rastogi uint64_t &Loc, DIExpressionCursor &Cursor, 212b12f81b5SShubham Sandeep Rastogi SmallVectorImpl<uint64_t> &WorkingOps) { 213b12f81b5SShubham Sandeep Rastogi 214b12f81b5SShubham Sandeep Rastogi auto Const2 = isConstantVal(Ops[1]); 215b12f81b5SShubham Sandeep Rastogi if (!Const2) 216b12f81b5SShubham Sandeep Rastogi return false; 217b12f81b5SShubham Sandeep Rastogi 218b12f81b5SShubham Sandeep Rastogi auto Result = foldOperationIfPossible( 219b12f81b5SShubham Sandeep Rastogi Const1, *Const2, static_cast<dwarf::LocationAtom>(Ops[2].getOp())); 220b12f81b5SShubham Sandeep Rastogi if (!Result) { 221b12f81b5SShubham Sandeep Rastogi consumeOneOperator(Cursor, Loc, Ops[0]); 222b12f81b5SShubham Sandeep Rastogi return true; 223b12f81b5SShubham Sandeep Rastogi } 224b12f81b5SShubham Sandeep Rastogi WorkingOps.erase(WorkingOps.begin() + Loc + 2, WorkingOps.begin() + Loc + 5); 225b12f81b5SShubham Sandeep Rastogi WorkingOps[Loc] = dwarf::DW_OP_constu; 226b12f81b5SShubham Sandeep Rastogi WorkingOps[Loc + 1] = *Result; 227b12f81b5SShubham Sandeep Rastogi startFromBeginning(Loc, Cursor, WorkingOps); 228b12f81b5SShubham Sandeep Rastogi return true; 229b12f81b5SShubham Sandeep Rastogi } 230b12f81b5SShubham Sandeep Rastogi 231b12f81b5SShubham Sandeep Rastogi /// {DW_OP_constu, Const1, DW_OP_[plus, mul], DW_OP_constu, Const2, 232b12f81b5SShubham Sandeep Rastogi /// DW_OP_[plus, mul]} -> {DW_OP_constu, Const1 [+, *] Const2, DW_OP_[plus, 233b12f81b5SShubham Sandeep Rastogi /// mul]} 234b12f81b5SShubham Sandeep Rastogi static bool tryFoldCommutativeMath(uint64_t Const1, 235b12f81b5SShubham Sandeep Rastogi ArrayRef<DIExpression::ExprOperand> Ops, 236b12f81b5SShubham Sandeep Rastogi uint64_t &Loc, DIExpressionCursor &Cursor, 237b12f81b5SShubham Sandeep Rastogi SmallVectorImpl<uint64_t> &WorkingOps) { 238b12f81b5SShubham Sandeep Rastogi 239b12f81b5SShubham Sandeep Rastogi auto Const2 = isConstantVal(Ops[2]); 240b12f81b5SShubham Sandeep Rastogi auto Operand1 = static_cast<dwarf::LocationAtom>(Ops[1].getOp()); 241b12f81b5SShubham Sandeep Rastogi auto Operand2 = static_cast<dwarf::LocationAtom>(Ops[3].getOp()); 242b12f81b5SShubham Sandeep Rastogi 243b12f81b5SShubham Sandeep Rastogi if (!Const2 || !operationsAreFoldableAndCommutative(Operand1, Operand2)) 244b12f81b5SShubham Sandeep Rastogi return false; 245b12f81b5SShubham Sandeep Rastogi 246b12f81b5SShubham Sandeep Rastogi auto Result = foldOperationIfPossible(Const1, *Const2, Operand1); 247b12f81b5SShubham Sandeep Rastogi if (!Result) { 248b12f81b5SShubham Sandeep Rastogi consumeOneOperator(Cursor, Loc, Ops[0]); 249b12f81b5SShubham Sandeep Rastogi return true; 250b12f81b5SShubham Sandeep Rastogi } 251b12f81b5SShubham Sandeep Rastogi WorkingOps.erase(WorkingOps.begin() + Loc + 3, WorkingOps.begin() + Loc + 6); 252b12f81b5SShubham Sandeep Rastogi WorkingOps[Loc] = dwarf::DW_OP_constu; 253b12f81b5SShubham Sandeep Rastogi WorkingOps[Loc + 1] = *Result; 254b12f81b5SShubham Sandeep Rastogi startFromBeginning(Loc, Cursor, WorkingOps); 255b12f81b5SShubham Sandeep Rastogi return true; 256b12f81b5SShubham Sandeep Rastogi } 257b12f81b5SShubham Sandeep Rastogi 258b12f81b5SShubham Sandeep Rastogi /// {DW_OP_constu, Const1, DW_OP_[plus, mul], DW_OP_LLVM_arg, Arg1, 259b12f81b5SShubham Sandeep Rastogi /// DW_OP_[plus, mul], DW_OP_constu, Const2, DW_OP_[plus, mul]} -> 260b12f81b5SShubham Sandeep Rastogi /// {DW_OP_constu, Const1 [+, *] Const2, DW_OP_[plus, mul], DW_OP_LLVM_arg, 261b12f81b5SShubham Sandeep Rastogi /// Arg1, DW_OP_[plus, mul]} 262b12f81b5SShubham Sandeep Rastogi static bool tryFoldCommutativeMathWithArgInBetween( 263b12f81b5SShubham Sandeep Rastogi uint64_t Const1, ArrayRef<DIExpression::ExprOperand> Ops, uint64_t &Loc, 264b12f81b5SShubham Sandeep Rastogi DIExpressionCursor &Cursor, SmallVectorImpl<uint64_t> &WorkingOps) { 265b12f81b5SShubham Sandeep Rastogi 266b12f81b5SShubham Sandeep Rastogi auto Const2 = isConstantVal(Ops[4]); 267b12f81b5SShubham Sandeep Rastogi auto Operand1 = static_cast<dwarf::LocationAtom>(Ops[1].getOp()); 268b12f81b5SShubham Sandeep Rastogi auto Operand2 = static_cast<dwarf::LocationAtom>(Ops[3].getOp()); 269b12f81b5SShubham Sandeep Rastogi auto Operand3 = static_cast<dwarf::LocationAtom>(Ops[5].getOp()); 270b12f81b5SShubham Sandeep Rastogi 271b12f81b5SShubham Sandeep Rastogi if (!Const2 || Ops[2].getOp() != dwarf::DW_OP_LLVM_arg || 272b12f81b5SShubham Sandeep Rastogi !operationsAreFoldableAndCommutative(Operand1, Operand2) || 273b12f81b5SShubham Sandeep Rastogi !operationsAreFoldableAndCommutative(Operand2, Operand3)) 274b12f81b5SShubham Sandeep Rastogi return false; 275b12f81b5SShubham Sandeep Rastogi 276b12f81b5SShubham Sandeep Rastogi auto Result = foldOperationIfPossible(Const1, *Const2, Operand1); 277b12f81b5SShubham Sandeep Rastogi if (!Result) { 278b12f81b5SShubham Sandeep Rastogi consumeOneOperator(Cursor, Loc, Ops[0]); 279b12f81b5SShubham Sandeep Rastogi return true; 280b12f81b5SShubham Sandeep Rastogi } 281b12f81b5SShubham Sandeep Rastogi WorkingOps.erase(WorkingOps.begin() + Loc + 6, WorkingOps.begin() + Loc + 9); 282b12f81b5SShubham Sandeep Rastogi WorkingOps[Loc] = dwarf::DW_OP_constu; 283b12f81b5SShubham Sandeep Rastogi WorkingOps[Loc + 1] = *Result; 284b12f81b5SShubham Sandeep Rastogi startFromBeginning(Loc, Cursor, WorkingOps); 285b12f81b5SShubham Sandeep Rastogi return true; 286b12f81b5SShubham Sandeep Rastogi } 287b12f81b5SShubham Sandeep Rastogi 288b12f81b5SShubham Sandeep Rastogi DIExpression *DIExpression::foldConstantMath() { 289b12f81b5SShubham Sandeep Rastogi 290b12f81b5SShubham Sandeep Rastogi SmallVector<uint64_t, 8> WorkingOps(Elements.begin(), Elements.end()); 291b12f81b5SShubham Sandeep Rastogi uint64_t Loc = 0; 292b12f81b5SShubham Sandeep Rastogi SmallVector<uint64_t> ResultOps = canonicalizeDwarfOperations(WorkingOps); 293b12f81b5SShubham Sandeep Rastogi DIExpressionCursor Cursor(ResultOps); 294b12f81b5SShubham Sandeep Rastogi SmallVector<DIExpression::ExprOperand, 8> Ops; 295b12f81b5SShubham Sandeep Rastogi 296b12f81b5SShubham Sandeep Rastogi // Iterate over all Operations in a DIExpression to match the smallest pattern 297b12f81b5SShubham Sandeep Rastogi // that can be folded. 298b12f81b5SShubham Sandeep Rastogi while (Loc < ResultOps.size()) { 299b12f81b5SShubham Sandeep Rastogi Ops.clear(); 300b12f81b5SShubham Sandeep Rastogi 301b12f81b5SShubham Sandeep Rastogi auto Op = Cursor.peek(); 302b12f81b5SShubham Sandeep Rastogi // Expression has no operations, exit. 303b12f81b5SShubham Sandeep Rastogi if (!Op) 304b12f81b5SShubham Sandeep Rastogi break; 305b12f81b5SShubham Sandeep Rastogi 306b12f81b5SShubham Sandeep Rastogi auto Const1 = isConstantVal(*Op); 307b12f81b5SShubham Sandeep Rastogi 308b12f81b5SShubham Sandeep Rastogi if (!Const1) { 309b12f81b5SShubham Sandeep Rastogi // Early exit, all of the following patterns start with a constant value. 310b12f81b5SShubham Sandeep Rastogi consumeOneOperator(Cursor, Loc, *Op); 311b12f81b5SShubham Sandeep Rastogi continue; 312b12f81b5SShubham Sandeep Rastogi } 313b12f81b5SShubham Sandeep Rastogi 314b12f81b5SShubham Sandeep Rastogi Ops.push_back(*Op); 315b12f81b5SShubham Sandeep Rastogi 316b12f81b5SShubham Sandeep Rastogi Op = Cursor.peekNext(); 317b12f81b5SShubham Sandeep Rastogi // All following patterns require at least 2 Operations, exit. 318b12f81b5SShubham Sandeep Rastogi if (!Op) 319b12f81b5SShubham Sandeep Rastogi break; 320b12f81b5SShubham Sandeep Rastogi 321b12f81b5SShubham Sandeep Rastogi Ops.push_back(*Op); 322b12f81b5SShubham Sandeep Rastogi 323b12f81b5SShubham Sandeep Rastogi // Try to fold a constant no-op, such as {+ 0} 324b12f81b5SShubham Sandeep Rastogi if (tryFoldNoOpMath(*Const1, Ops, Loc, Cursor, ResultOps)) 325b12f81b5SShubham Sandeep Rastogi continue; 326b12f81b5SShubham Sandeep Rastogi 327b12f81b5SShubham Sandeep Rastogi Op = Cursor.peekNextN(2); 328b12f81b5SShubham Sandeep Rastogi // Op[1] could still match a pattern, skip iteration. 329b12f81b5SShubham Sandeep Rastogi if (!Op) { 330b12f81b5SShubham Sandeep Rastogi consumeOneOperator(Cursor, Loc, Ops[0]); 331b12f81b5SShubham Sandeep Rastogi continue; 332b12f81b5SShubham Sandeep Rastogi } 333b12f81b5SShubham Sandeep Rastogi 334b12f81b5SShubham Sandeep Rastogi Ops.push_back(*Op); 335b12f81b5SShubham Sandeep Rastogi 336b12f81b5SShubham Sandeep Rastogi // Try to fold a pattern of two constants such as {C1 + C2}. 337b12f81b5SShubham Sandeep Rastogi if (tryFoldConstants(*Const1, Ops, Loc, Cursor, ResultOps)) 338b12f81b5SShubham Sandeep Rastogi continue; 339b12f81b5SShubham Sandeep Rastogi 340b12f81b5SShubham Sandeep Rastogi Op = Cursor.peekNextN(3); 341b12f81b5SShubham Sandeep Rastogi // Op[1] and Op[2] could still match a pattern, skip iteration. 342b12f81b5SShubham Sandeep Rastogi if (!Op) { 343b12f81b5SShubham Sandeep Rastogi consumeOneOperator(Cursor, Loc, Ops[0]); 344b12f81b5SShubham Sandeep Rastogi continue; 345b12f81b5SShubham Sandeep Rastogi } 346b12f81b5SShubham Sandeep Rastogi 347b12f81b5SShubham Sandeep Rastogi Ops.push_back(*Op); 348b12f81b5SShubham Sandeep Rastogi 349b12f81b5SShubham Sandeep Rastogi // Try to fold commutative constant math, such as {C1 + C2 +}. 350b12f81b5SShubham Sandeep Rastogi if (tryFoldCommutativeMath(*Const1, Ops, Loc, Cursor, ResultOps)) 351b12f81b5SShubham Sandeep Rastogi continue; 352b12f81b5SShubham Sandeep Rastogi 353b12f81b5SShubham Sandeep Rastogi Op = Cursor.peekNextN(4); 354b12f81b5SShubham Sandeep Rastogi if (!Op) { 355b12f81b5SShubham Sandeep Rastogi consumeOneOperator(Cursor, Loc, Ops[0]); 356b12f81b5SShubham Sandeep Rastogi continue; 357b12f81b5SShubham Sandeep Rastogi } 358b12f81b5SShubham Sandeep Rastogi 359b12f81b5SShubham Sandeep Rastogi Ops.push_back(*Op); 360b12f81b5SShubham Sandeep Rastogi Op = Cursor.peekNextN(5); 361b12f81b5SShubham Sandeep Rastogi if (!Op) { 362b12f81b5SShubham Sandeep Rastogi consumeOneOperator(Cursor, Loc, Ops[0]); 363b12f81b5SShubham Sandeep Rastogi continue; 364b12f81b5SShubham Sandeep Rastogi } 365b12f81b5SShubham Sandeep Rastogi 366b12f81b5SShubham Sandeep Rastogi Ops.push_back(*Op); 367b12f81b5SShubham Sandeep Rastogi 368b12f81b5SShubham Sandeep Rastogi // Try to fold commutative constant math with an LLVM_Arg in between, such 369b12f81b5SShubham Sandeep Rastogi // as {C1 + Arg + C2 +}. 370b12f81b5SShubham Sandeep Rastogi if (tryFoldCommutativeMathWithArgInBetween(*Const1, Ops, Loc, Cursor, 371b12f81b5SShubham Sandeep Rastogi ResultOps)) 372b12f81b5SShubham Sandeep Rastogi continue; 373b12f81b5SShubham Sandeep Rastogi 374b12f81b5SShubham Sandeep Rastogi consumeOneOperator(Cursor, Loc, Ops[0]); 375b12f81b5SShubham Sandeep Rastogi } 376b12f81b5SShubham Sandeep Rastogi ResultOps = optimizeDwarfOperations(ResultOps); 377b12f81b5SShubham Sandeep Rastogi auto *Result = DIExpression::get(getContext(), ResultOps); 378b12f81b5SShubham Sandeep Rastogi assert(Result->isValid() && "concatenated expression is not valid"); 379b12f81b5SShubham Sandeep Rastogi return Result; 380b12f81b5SShubham Sandeep Rastogi } 381