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: {
62 if (Const2 >= std::numeric_limits<uint64_t>::digits ||
65 return Const1 << Const2;
67 case dwarf::DW_OP_shr: {
68 if (Const2 >= std::numeric_limits<uint64_t>::digits ||
71 return Const1 >> Const2;
73 case dwarf::DW_OP_mul: {
79 case dwarf::DW_OP_div: {
81 return Const1 / Const2;
93 return Operator1 == Operator2 &&
94 (Operator1 == dwarf::DW_OP_plus || Operator1 == dwarf::DW_OP_mul);
101 Loc = Loc +
Op.getSize();
119 while (Loc < WorkingOps.
size()) {
124 auto OpRaw =
Op->getOp();
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);
132 if (OpRaw == dwarf::DW_OP_plus_uconst) {
133 ResultOps.
push_back(dwarf::DW_OP_constu);
154 while (Loc < WorkingOps.
size()) {
155 auto Op1 = Cursor.
peek();
159 auto Op1Raw = Op1->getOp();
161 if (Op1Raw == dwarf::DW_OP_constu && Op1->getArg(0) == 0) {
175 auto Op2Raw = Op2->getOp();
177 if (Op1Raw == dwarf::DW_OP_constu && Op2Raw == dwarf::DW_OP_plus) {
178 ResultOps.
push_back(dwarf::DW_OP_plus_uconst);
199 WorkingOps.
erase(WorkingOps.
begin() + Loc, WorkingOps.
begin() + Loc + 3);
224 WorkingOps.
erase(WorkingOps.
begin() + Loc + 2, WorkingOps.
begin() + Loc + 5);
225 WorkingOps[Loc] = dwarf::DW_OP_constu;
226 WorkingOps[Loc + 1] = *Result;
251 WorkingOps.
erase(WorkingOps.
begin() + Loc + 3, WorkingOps.
begin() + Loc + 6);
252 WorkingOps[Loc] = dwarf::DW_OP_constu;
253 WorkingOps[Loc + 1] = *Result;
281 WorkingOps.
erase(WorkingOps.
begin() + Loc + 6, WorkingOps.
begin() + Loc + 9);
282 WorkingOps[Loc] = dwarf::DW_OP_constu;
283 WorkingOps[Loc + 1] = *Result;
298 while (Loc < ResultOps.
size()) {
378 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.