21 if (
Op.getOp() == dwarf::DW_OP_constu)
29 case dwarf::DW_OP_plus:
30 case dwarf::DW_OP_minus:
31 case dwarf::DW_OP_shl:
32 case dwarf::DW_OP_shr:
34 case dwarf::DW_OP_mul:
35 case dwarf::DW_OP_div:
44static std::optional<uint64_t>
48 bool ResultOverflowed;
50 case dwarf::DW_OP_plus: {
51 auto Result =
SaturatingAdd(Const1, Const2, &ResultOverflowed);
56 case dwarf::DW_OP_minus: {
59 return Const1 - Const2;
61 case dwarf::DW_OP_shl: {
64 return Const1 << Const2;
66 case dwarf::DW_OP_shr: {
69 return Const1 >> Const2;
71 case dwarf::DW_OP_mul: {
77 case dwarf::DW_OP_div: {
79 return Const1 / Const2;
91 return Operator1 == Operator2 &&
92 (Operator1 == dwarf::DW_OP_plus || Operator1 == dwarf::DW_OP_mul);
99 Loc = Loc +
Op.getSize();
117 while (Loc < WorkingOps.
size()) {
122 auto OpRaw =
Op->getOp();
124 if (OpRaw >= dwarf::DW_OP_lit0 && OpRaw <= dwarf::DW_OP_lit31) {
125 ResultOps.
push_back(dwarf::DW_OP_constu);
126 ResultOps.
push_back(OpRaw - dwarf::DW_OP_lit0);
130 if (OpRaw == dwarf::DW_OP_plus_uconst) {
131 ResultOps.
push_back(dwarf::DW_OP_constu);
152 while (Loc < WorkingOps.
size()) {
153 auto Op1 = Cursor.
peek();
157 auto Op1Raw = Op1->getOp();
159 if (Op1Raw == dwarf::DW_OP_constu && Op1->getArg(0) == 0) {
173 auto Op2Raw = Op2->getOp();
175 if (Op1Raw == dwarf::DW_OP_constu && Op2Raw == dwarf::DW_OP_plus) {
176 ResultOps.
push_back(dwarf::DW_OP_plus_uconst);
197 WorkingOps.
erase(WorkingOps.
begin() + Loc, WorkingOps.
begin() + Loc + 3);
222 WorkingOps.
erase(WorkingOps.
begin() + Loc + 2, WorkingOps.
begin() + Loc + 5);
223 WorkingOps[Loc] = dwarf::DW_OP_constu;
224 WorkingOps[Loc + 1] = *Result;
249 WorkingOps.
erase(WorkingOps.
begin() + Loc + 3, WorkingOps.
begin() + Loc + 6);
250 WorkingOps[Loc] = dwarf::DW_OP_constu;
251 WorkingOps[Loc + 1] = *Result;
279 WorkingOps.
erase(WorkingOps.
begin() + Loc + 6, WorkingOps.
begin() + Loc + 9);
280 WorkingOps[Loc] = dwarf::DW_OP_constu;
281 WorkingOps[Loc + 1] = *Result;
296 while (Loc < ResultOps.
size()) {
376 assert(Result->isValid() &&
"concatenated expression is not valid");
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,...
static bool operationsAreFoldableAndCommutative(dwarf::LocationAtom Operator1, dwarf::LocationAtom Operator2)
Returns true if the two operations Operator1 and Operator2 are commutative and can be folded.
static bool isNeutralElement(uint64_t Op, uint64_t Val)
Returns true if an operation and operand result in a No Op.
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,...
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]} -> {DW_OP_constu,...
void startFromBeginning(uint64_t &Loc, DIExpressionCursor &Cursor, ArrayRef< uint64_t > WorkingOps)
Reset the Cursor to the beginning of the WorkingOps.
static SmallVector< uint64_t > optimizeDwarfOperations(ArrayRef< uint64_t > WorkingOps)
This function will convert:
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],...
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...
static void consumeOneOperator(DIExpressionCursor &Cursor, uint64_t &Loc, const DIExpression::ExprOperand &Op)
Consume one operator and its operand(s).
static std::optional< uint64_t > isConstantVal(DIExpression::ExprOperand Op)
Returns true if the Op is a DW_OP_constu.
static SmallVector< uint64_t > canonicalizeDwarfOperations(ArrayRef< uint64_t > WorkingOps)
This function will canonicalize:
This file contains constants used for implementing Dwarf debug support.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
std::optional< DIExpression::ExprOperand > peekNext() const
Return the next operation.
std::optional< DIExpression::ExprOperand > peekNextN(unsigned N) const
std::optional< DIExpression::ExprOperand > peek() const
Return the current operation.
void consume(unsigned N)
Consume N operations.
void assignNewExpr(ArrayRef< uint64_t > Expr)
A lightweight wrapper around an expression operand.
DIExpression * foldConstantMath()
Try to shorten an expression with constant math operations that can be evaluated at compile time.
This class represents an Operation in the Expression.
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.
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.