[llvm] Use DIExpression::foldConstantMath() at the result of an appendOpsToArg() (PR #71721)
Shubham Sandeep Rastogi via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 17 20:11:57 PDT 2024
https://github.com/rastogishubham updated https://github.com/llvm/llvm-project/pull/71721
>From 8923f81c48acae874506b32c1684ee28e930c2d7 Mon Sep 17 00:00:00 2001
From: Shubham Sandeep Rastogi <srastogi22 at apple.com>
Date: Wed, 4 Oct 2023 11:34:19 -0700
Subject: [PATCH 1/5] [NFC] Move DIExpressionCursor to DebugInfoMetadata.h
---
llvm/include/llvm/IR/DebugInfoMetadata.h | 61 +++++++++++++++++++
llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h | 61 -------------------
2 files changed, 61 insertions(+), 61 deletions(-)
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 2805f6c4780578..e1ac2b7c907139 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -3145,6 +3145,67 @@ template <> struct DenseMapInfo<DIExpression::FragmentInfo> {
static bool isEqual(const FragInfo &A, const FragInfo &B) { return A == B; }
};
+/// Holds a DIExpression and keeps track of how many operands have been consumed
+/// so far.
+class DIExpressionCursor {
+ DIExpression::expr_op_iterator Start, End;
+
+public:
+ DIExpressionCursor(const DIExpression *Expr) {
+ if (!Expr) {
+ assert(Start == End);
+ return;
+ }
+ Start = Expr->expr_op_begin();
+ End = Expr->expr_op_end();
+ }
+
+ DIExpressionCursor(ArrayRef<uint64_t> Expr)
+ : Start(Expr.begin()), End(Expr.end()) {}
+
+ DIExpressionCursor(const DIExpressionCursor &) = default;
+
+ /// Consume one operation.
+ std::optional<DIExpression::ExprOperand> take() {
+ if (Start == End)
+ return std::nullopt;
+ return *(Start++);
+ }
+
+ /// Consume N operations.
+ void consume(unsigned N) { std::advance(Start, N); }
+
+ /// Return the current operation.
+ std::optional<DIExpression::ExprOperand> peek() const {
+ if (Start == End)
+ return std::nullopt;
+ return *(Start);
+ }
+
+ /// Return the next operation.
+ std::optional<DIExpression::ExprOperand> peekNext() const {
+ if (Start == End)
+ return std::nullopt;
+
+ auto Next = Start.getNext();
+ if (Next == End)
+ return std::nullopt;
+
+ return *Next;
+ }
+
+ /// Determine whether there are any operations left in this expression.
+ operator bool() const { return Start != End; }
+
+ DIExpression::expr_op_iterator begin() const { return Start; }
+ DIExpression::expr_op_iterator end() const { return End; }
+
+ /// Retrieve the fragment information, if any.
+ std::optional<DIExpression::FragmentInfo> getFragmentInfo() const {
+ return DIExpression::getFragmentInfo(Start, End);
+ }
+};
+
/// Global variables.
///
/// TODO: Remove DisplayName. It's always equal to Name.
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
index 667a9efc6f6c04..4daa78b15b8e29 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
@@ -31,67 +31,6 @@ class DIELoc;
class TargetRegisterInfo;
class MachineLocation;
-/// Holds a DIExpression and keeps track of how many operands have been consumed
-/// so far.
-class DIExpressionCursor {
- DIExpression::expr_op_iterator Start, End;
-
-public:
- DIExpressionCursor(const DIExpression *Expr) {
- if (!Expr) {
- assert(Start == End);
- return;
- }
- Start = Expr->expr_op_begin();
- End = Expr->expr_op_end();
- }
-
- DIExpressionCursor(ArrayRef<uint64_t> Expr)
- : Start(Expr.begin()), End(Expr.end()) {}
-
- DIExpressionCursor(const DIExpressionCursor &) = default;
-
- /// Consume one operation.
- std::optional<DIExpression::ExprOperand> take() {
- if (Start == End)
- return std::nullopt;
- return *(Start++);
- }
-
- /// Consume N operations.
- void consume(unsigned N) { std::advance(Start, N); }
-
- /// Return the current operation.
- std::optional<DIExpression::ExprOperand> peek() const {
- if (Start == End)
- return std::nullopt;
- return *(Start);
- }
-
- /// Return the next operation.
- std::optional<DIExpression::ExprOperand> peekNext() const {
- if (Start == End)
- return std::nullopt;
-
- auto Next = Start.getNext();
- if (Next == End)
- return std::nullopt;
-
- return *Next;
- }
-
- /// Determine whether there are any operations left in this expression.
- operator bool() const { return Start != End; }
-
- DIExpression::expr_op_iterator begin() const { return Start; }
- DIExpression::expr_op_iterator end() const { return End; }
-
- /// Retrieve the fragment information, if any.
- std::optional<DIExpression::FragmentInfo> getFragmentInfo() const {
- return DIExpression::getFragmentInfo(Start, End);
- }
-};
-
/// Base class containing the logic for constructing DWARF expressions
/// independently of whether they are emitted into a DIE or into a .debug_loc
/// entry.
>From a3c91263383e71cbccc90bb1585ddaa424a8d4dc Mon Sep 17 00:00:00 2001
From: Shubham Sandeep Rastogi <srastogi22 at apple.com>
Date: Wed, 1 Nov 2023 17:25:26 -0700
Subject: [PATCH 2/5] Add functions peekNextN(unsigned) and
assignNewExpr(ArrayRef<uint64_t>) to DIExpressionCursor
This commit adds two functions to the DIExpressionCursor class.
peekNextN(unsigned) works like peekNext, but lets you peek the next Nth
element
assignNewExpr(ArrayRef<uint64_t>) lets you assign a new expression to
the same DIExpressionCursor object
---
llvm/include/llvm/IR/DebugInfoMetadata.h | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index e1ac2b7c907139..04a987767ed980 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -3194,6 +3194,23 @@ class DIExpressionCursor {
return *Next;
}
+ std::optional<DIExpression::ExprOperand> peekNextN(unsigned N) const {
+ if (Start == End)
+ return std::nullopt;
+ DIExpression::expr_op_iterator Nth = Start;
+ for (unsigned I = 0; I < N; I++) {
+ Nth = Nth.getNext();
+ if (Nth == End)
+ return std::nullopt;
+ }
+ return *Nth;
+ }
+
+ void assignNewExpr(ArrayRef<uint64_t> Expr) {
+ this->Start = DIExpression::expr_op_iterator(Expr.begin());
+ this->End = DIExpression::expr_op_iterator(Expr.end());
+ }
+
/// Determine whether there are any operations left in this expression.
operator bool() const { return Start != End; }
>From 836d8fcd47dae9ee6cc326aa98c3cb78aa33f608 Mon Sep 17 00:00:00 2001
From: Shubham Sandeep Rastogi <srastogi22 at apple.com>
Date: Fri, 20 Oct 2023 10:44:22 -0700
Subject: [PATCH 3/5] Introduce DIExpression::foldConstantMath()
DIExpressions can get very long and have a lot of redundant operations.
This function uses simple pattern matching to fold constant math that
can be evaluated at compile time.
---
llvm/include/llvm/IR/DebugInfoMetadata.h | 5 +
llvm/lib/IR/DebugInfoMetadata.cpp | 343 +++++++++++++++-
llvm/unittests/IR/MetadataTest.cpp | 486 +++++++++++++++++++++++
3 files changed, 833 insertions(+), 1 deletion(-)
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 04a987767ed980..63aaf210797cbb 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -3116,6 +3116,11 @@ class DIExpression : public MDNode {
/// expression and constant on failure.
std::pair<DIExpression *, const ConstantInt *>
constantFold(const ConstantInt *CI);
+
+ /// Try to shorten an expression with constant math operations that can be
+ /// evaluated at compile time. Returns a new expression on success, or the old
+ /// expression if there is nothing to be reduced.
+ SmallVector<uint64_t> foldConstantMath(ArrayRef<uint64_t> WorkingOps);
};
inline bool operator==(const DIExpression::FragmentInfo &A,
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index 570515505607fb..a18747f7e583a8 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -22,6 +22,7 @@
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
+#include <bit>
#include <numeric>
#include <optional>
@@ -1880,7 +1881,6 @@ DIExpression *DIExpression::append(const DIExpression *Expr,
}
Op.appendToVector(NewOps);
}
-
NewOps.append(Ops.begin(), Ops.end());
auto *result = DIExpression::get(Expr->getContext(), NewOps);
assert(result->isValid() && "concatenated expression is not valid");
@@ -2022,6 +2022,347 @@ DIExpression::constantFold(const ConstantInt *CI) {
ConstantInt::get(getContext(), NewInt)};
}
+/// Returns true if the Op is a DW_OP_constu.
+static bool isConstantVal(uint64_t Op) { return Op == dwarf::DW_OP_constu; }
+
+/// Returns true if an operation and operand result in a No Op.
+static bool isNeutralElement(uint64_t Op, uint64_t Val) {
+ switch (Op) {
+ case dwarf::DW_OP_plus:
+ case dwarf::DW_OP_minus:
+ case dwarf::DW_OP_shl:
+ case dwarf::DW_OP_shr:
+ return Val == 0;
+ case dwarf::DW_OP_mul:
+ case dwarf::DW_OP_div:
+ return Val == 1;
+ default:
+ return false;
+ }
+}
+
+/// Try to fold constant math operations and return the result if possible.
+static std::optional<uint64_t>
+foldOperationIfPossible(uint64_t Op, uint64_t Operand1, uint64_t Operand2) {
+ bool ResultOverflowed;
+ switch (Op) {
+ case dwarf::DW_OP_plus: {
+ auto Result = SaturatingAdd(Operand1, Operand2, &ResultOverflowed);
+ if (ResultOverflowed)
+ return std::nullopt;
+ return Result;
+ }
+ case dwarf::DW_OP_minus: {
+ if (Operand1 < Operand2)
+ return std::nullopt;
+ return Operand1 - Operand2;
+ }
+ case dwarf::DW_OP_shl: {
+ if ((uint64_t)countl_zero(Operand1) < Operand2)
+ return std::nullopt;
+ return Operand1 << Operand2;
+ }
+ case dwarf::DW_OP_shr: {
+ if ((uint64_t)countr_zero(Operand1) < Operand2)
+ return std::nullopt;
+ return Operand1 >> Operand2;
+ }
+ case dwarf::DW_OP_mul: {
+ auto Result = SaturatingMultiply(Operand1, Operand2, &ResultOverflowed);
+ if (ResultOverflowed)
+ return std::nullopt;
+ return Result;
+ }
+ case dwarf::DW_OP_div: {
+ if (Operand2)
+ return Operand1 / Operand2;
+ return std::nullopt;
+ }
+ default:
+ return std::nullopt;
+ }
+}
+
+/// Returns true if the two operations are commutative and can be folded.
+static bool operationsAreFoldableAndCommutative(uint64_t Op1, uint64_t Op2) {
+ if (Op1 != Op2)
+ return false;
+ switch (Op1) {
+ case dwarf::DW_OP_plus:
+ case dwarf::DW_OP_mul:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/// Consume one operator and its operand(s).
+static void consumeOneOperator(DIExpressionCursor &Cursor, uint64_t &Loc,
+ const DIExpression::ExprOperand &Op) {
+ Cursor.consume(1);
+ Loc = Loc + Op.getSize();
+}
+
+/// Reset the Cursor to the beginning of the WorkingOps.
+static void startFromBeginning(uint64_t &Loc, DIExpressionCursor &Cursor,
+ ArrayRef<uint64_t> WorkingOps) {
+ Cursor.assignNewExpr(WorkingOps);
+ Loc = 0;
+}
+
+/// This function will canonicalize:
+/// 1. DW_OP_plus_uconst to DW_OP_constu <const-val> DW_OP_plus
+/// 2. DW_OP_lit<n> to DW_OP_constu <n>
+static SmallVector<uint64_t>
+canonicalizeDwarfOperations(ArrayRef<uint64_t> WorkingOps) {
+ DIExpressionCursor Cursor(WorkingOps);
+ uint64_t Loc = 0;
+ SmallVector<uint64_t> ResultOps;
+ while (Loc < WorkingOps.size()) {
+ auto Op = Cursor.peek();
+ /// Expression has no operations, break.
+ if (!Op)
+ break;
+ auto OpRaw = Op->getOp();
+ auto OpArg = Op->getArg(0);
+
+ if (OpRaw >= dwarf::DW_OP_lit0 && OpRaw <= dwarf::DW_OP_lit31) {
+ ResultOps.push_back(dwarf::DW_OP_constu);
+ ResultOps.push_back(OpRaw - dwarf::DW_OP_lit0);
+ consumeOneOperator(Cursor, Loc, *Cursor.peek());
+ continue;
+ }
+ if (OpRaw == dwarf::DW_OP_plus_uconst) {
+ ResultOps.push_back(dwarf::DW_OP_constu);
+ ResultOps.push_back(OpArg);
+ ResultOps.push_back(dwarf::DW_OP_plus);
+ consumeOneOperator(Cursor, Loc, *Cursor.peek());
+ continue;
+ }
+ uint64_t PrevLoc = Loc;
+ consumeOneOperator(Cursor, Loc, *Cursor.peek());
+ ResultOps.append(WorkingOps.begin() + PrevLoc, WorkingOps.begin() + Loc);
+ }
+ return ResultOps;
+}
+
+/// This function will convert:
+/// 1. DW_OP_constu <const-val> DW_OP_plus to DW_OP_plus_uconst
+/// 2. DW_OP_constu, 0 to DW_OP_lit0
+static SmallVector<uint64_t>
+optimizeDwarfOperations(ArrayRef<uint64_t> WorkingOps) {
+ DIExpressionCursor Cursor(WorkingOps);
+ uint64_t Loc = 0;
+ SmallVector<uint64_t> ResultOps;
+ while (Loc < WorkingOps.size()) {
+ auto Op1 = Cursor.peek();
+ /// Expression has no operations, exit.
+ if (!Op1)
+ break;
+ auto Op1Raw = Op1->getOp();
+ auto Op1Arg = Op1->getArg(0);
+
+ if (Op1Raw == dwarf::DW_OP_constu && Op1Arg == 0) {
+ ResultOps.push_back(dwarf::DW_OP_lit0);
+ consumeOneOperator(Cursor, Loc, *Cursor.peek());
+ continue;
+ }
+
+ auto Op2 = Cursor.peekNext();
+ /// Expression has no more operations, copy into ResultOps and exit.
+ if (!Op2) {
+ uint64_t PrevLoc = Loc;
+ consumeOneOperator(Cursor, Loc, *Cursor.peek());
+ ResultOps.append(WorkingOps.begin() + PrevLoc, WorkingOps.begin() + Loc);
+ break;
+ }
+ auto Op2Raw = Op2->getOp();
+
+ if (Op1Raw == dwarf::DW_OP_constu && Op2Raw == dwarf::DW_OP_plus) {
+ ResultOps.push_back(dwarf::DW_OP_plus_uconst);
+ ResultOps.push_back(Op1Arg);
+ consumeOneOperator(Cursor, Loc, *Cursor.peek());
+ consumeOneOperator(Cursor, Loc, *Cursor.peek());
+ continue;
+ }
+ uint64_t PrevLoc = Loc;
+ consumeOneOperator(Cursor, Loc, *Cursor.peek());
+ ResultOps.append(WorkingOps.begin() + PrevLoc, WorkingOps.begin() + Loc);
+ }
+ return ResultOps;
+}
+
+/// {DW_OP_constu, 0, DW_OP_[plus, minus, shl, shr]} -> {}
+/// {DW_OP_constu, 1, DW_OP_[mul, div]} -> {}
+static bool tryFoldNoOpMath(uint64_t Op1Raw, uint64_t Op1Arg, uint64_t Op2Raw,
+ uint64_t &Loc, DIExpressionCursor &Cursor,
+ SmallVectorImpl<uint64_t> &WorkingOps) {
+ if (isConstantVal(Op1Raw) && isNeutralElement(Op2Raw, Op1Arg)) {
+ WorkingOps.erase(WorkingOps.begin() + Loc, WorkingOps.begin() + Loc + 3);
+ startFromBeginning(Loc, Cursor, WorkingOps);
+ return true;
+ }
+ return false;
+}
+
+/// {DW_OP_constu, Const1, DW_OP_constu, Const2, DW_OP_[plus,
+/// minus, mul, div, shl, shr] -> {DW_OP_constu, Const1 [+, -, *, /, <<, >>]
+/// Const2}
+static bool tryFoldConstants(std::optional<DIExpression::ExprOperand> Op1,
+ uint64_t Op1Raw, uint64_t Op1Arg, uint64_t Op2Raw,
+ uint64_t Op2Arg, uint64_t Op3Raw, uint64_t &Loc,
+ DIExpressionCursor &Cursor,
+ SmallVectorImpl<uint64_t> &WorkingOps) {
+ if (isConstantVal(Op1Raw) && isConstantVal(Op2Raw)) {
+ auto Result = foldOperationIfPossible(Op3Raw, Op1Arg, Op2Arg);
+ if (!Result) {
+ consumeOneOperator(Cursor, Loc, *Op1);
+ return true;
+ }
+ WorkingOps.erase(WorkingOps.begin() + Loc + 2,
+ WorkingOps.begin() + Loc + 5);
+ WorkingOps[Loc] = dwarf::DW_OP_constu;
+ WorkingOps[Loc + 1] = *Result;
+ startFromBeginning(Loc, Cursor, WorkingOps);
+ return true;
+ }
+ return false;
+}
+
+/// {DW_OP_constu, Const1, DW_OP_[plus, mul], DW_OP_constu, Const2,
+/// DW_OP_[plus, mul]} -> {DW_OP_constu, Const1 [+, *] Const2, DW_OP_[plus,
+/// mul]}
+static bool tryFoldCommutativeMath(uint64_t Op1Raw, uint64_t Op1Arg,
+ uint64_t Op2Raw, uint64_t Op2Arg,
+ uint64_t Op3Raw, uint64_t Op3Arg,
+ uint64_t Op4Raw, uint64_t &Loc,
+ DIExpressionCursor &Cursor,
+ SmallVectorImpl<uint64_t> &WorkingOps) {
+
+ if (isConstantVal(Op1Raw) && isConstantVal(Op3Raw) &&
+ operationsAreFoldableAndCommutative(Op2Raw, Op4Raw)) {
+ auto Result = foldOperationIfPossible(Op2Raw, Op1Arg, Op3Arg);
+ if (!Result)
+ return false;
+ WorkingOps.erase(WorkingOps.begin() + Loc + 3,
+ WorkingOps.begin() + Loc + 6);
+ WorkingOps[Loc] = dwarf::DW_OP_constu;
+ WorkingOps[Loc + 1] = *Result;
+ startFromBeginning(Loc, Cursor, WorkingOps);
+ return true;
+ }
+ return false;
+}
+
+/// {DW_OP_constu, Const1, DW_OP_[plus, mul], DW_OP_LLVM_arg, Arg1,
+/// DW_OP_[plus, mul], DW_OP_constu, Const2, DW_OP_[plus, mul]} ->
+/// {DW_OP_constu, Const1 [+, *] Const2, DW_OP_[plus, mul], DW_OP_LLVM_arg,
+/// Arg1, DW_OP_[plus, mul]}
+static bool tryFoldCommutativeMathWithArgInBetween(
+ uint64_t Op1Raw, uint64_t Op1Arg, uint64_t Op2Raw, uint64_t Op3Raw,
+ uint64_t Op4Raw, uint64_t Op5Raw, uint64_t Op5Arg, uint64_t Op6Raw,
+ uint64_t &Loc, DIExpressionCursor &Cursor,
+ SmallVectorImpl<uint64_t> &WorkingOps) {
+ if (isConstantVal(Op1Raw) && Op3Raw == dwarf::DW_OP_LLVM_arg &&
+ isConstantVal(Op5Raw) &&
+ operationsAreFoldableAndCommutative(Op2Raw, Op4Raw) &&
+ operationsAreFoldableAndCommutative(Op4Raw, Op6Raw)) {
+ auto Result = foldOperationIfPossible(Op2Raw, Op1Arg, Op5Arg);
+ if (!Result)
+ return false;
+ WorkingOps.erase(WorkingOps.begin() + Loc + 6,
+ WorkingOps.begin() + Loc + 9);
+ WorkingOps[Loc] = dwarf::DW_OP_constu;
+ WorkingOps[Loc + 1] = *Result;
+ startFromBeginning(Loc, Cursor, WorkingOps);
+ return true;
+ }
+ return false;
+}
+
+SmallVector<uint64_t>
+DIExpression::foldConstantMath(ArrayRef<uint64_t> WorkingOps) {
+
+ uint64_t Loc = 0;
+ SmallVector<uint64_t> ResultOps = canonicalizeDwarfOperations(WorkingOps);
+ DIExpressionCursor Cursor(ResultOps);
+
+ while (Loc < ResultOps.size()) {
+
+ auto Op1 = Cursor.peek();
+ // Expression has no operations, exit.
+ if (!Op1)
+ break;
+ auto Op1Raw = Op1->getOp();
+ auto Op1Arg = Op1->getArg(0);
+
+ if (!isConstantVal(Op1Raw)) {
+ // Early exit, all of the following patterns start with a constant value.
+ consumeOneOperator(Cursor, Loc, *Op1);
+ continue;
+ }
+
+ auto Op2 = Cursor.peekNext();
+ // All following patterns require at least 2 Operations, exit.
+ if (!Op2)
+ break;
+ auto Op2Raw = Op2->getOp();
+
+ if (tryFoldNoOpMath(Op1Raw, Op1Arg, Op2Raw, Loc, Cursor, ResultOps))
+ continue;
+
+ auto Op2Arg = Op2->getArg(0);
+
+ auto Op3 = Cursor.peekNextN(2);
+ // Op2 could still match a pattern, skip iteration.
+ if (!Op3) {
+ consumeOneOperator(Cursor, Loc, *Op1);
+ continue;
+ }
+ auto Op3Raw = Op3->getOp();
+
+ if (tryFoldConstants(Op1, Op1Raw, Op1Arg, Op2Raw, Op2Arg, Op3Raw, Loc,
+ Cursor, ResultOps))
+ continue;
+
+ auto Op3Arg = Op3->getArg(0);
+
+ auto Op4 = Cursor.peekNextN(3);
+ // Op2 and Op3 could still match a pattern, skip iteration.
+ if (!Op4) {
+ consumeOneOperator(Cursor, Loc, *Op1);
+ continue;
+ }
+ auto Op4Raw = Op4->getOp();
+
+ if (tryFoldCommutativeMath(Op1Raw, Op1Arg, Op2Raw, Op2Arg, Op3Raw, Op3Arg,
+ Op4Raw, Loc, Cursor, ResultOps))
+ continue;
+
+ auto Op5 = Cursor.peekNextN(4);
+ if (!Op5) {
+ consumeOneOperator(Cursor, Loc, *Op1);
+ continue;
+ }
+ auto Op5Raw = Op5->getOp();
+ auto Op5Arg = Op5->getArg(0);
+ auto Op6 = Cursor.peekNextN(5);
+ if (!Op6) {
+ consumeOneOperator(Cursor, Loc, *Op1);
+ continue;
+ }
+ auto Op6Raw = Op6->getOp();
+ if (tryFoldCommutativeMathWithArgInBetween(Op1Raw, Op1Arg, Op2Raw, Op3Raw,
+ Op4Raw, Op5Raw, Op5Arg, Op6Raw,
+ Loc, Cursor, ResultOps))
+ continue;
+
+ consumeOneOperator(Cursor, Loc, *Op1);
+ }
+ ResultOps = optimizeDwarfOperations(ResultOps);
+ return ResultOps;
+}
+
uint64_t DIExpression::getNumLocationOperands() const {
uint64_t Result = 0;
for (auto ExprOp : expr_ops())
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index 4c2e5f77a54038..73eda16b6267c7 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -3153,6 +3153,492 @@ TEST_F(DIExpressionTest, get) {
EXPECT_EQ(N0WithPrependedOps, N2);
}
+TEST_F(DIExpressionTest, Fold) {
+
+ // Remove a No-op DW_OP_plus_uconst from an expression.
+ SmallVector<uint64_t, 8> Ops = {dwarf::DW_OP_plus_uconst, 0};
+ auto *Expr = DIExpression::get(Context, Ops);
+ auto ReturnOps = Expr->foldConstantMath(Ops);
+ auto *E = DIExpression::get(Context, ReturnOps);
+ SmallVector<uint64_t, 8> ResOps;
+ auto *EmptyExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, EmptyExpr);
+
+ // Remove a No-op add from an expression.
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(0);
+ Ops.push_back(dwarf::DW_OP_plus);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ EXPECT_EQ(E, EmptyExpr);
+
+ // Remove a No-op subtract from an expression.
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(0);
+ Ops.push_back(dwarf::DW_OP_minus);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ EXPECT_EQ(E, EmptyExpr);
+
+ // Remove a No-op shift left from an expression.
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(0);
+ Ops.push_back(dwarf::DW_OP_shl);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ EXPECT_EQ(E, EmptyExpr);
+
+ // Remove a No-op shift right from an expression.
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(0);
+ Ops.push_back(dwarf::DW_OP_shr);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ EXPECT_EQ(E, EmptyExpr);
+
+ // Remove a No-op multiply from an expression.
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(1);
+ Ops.push_back(dwarf::DW_OP_mul);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ EXPECT_EQ(E, EmptyExpr);
+
+ // Remove a No-op divide from an expression.
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(1);
+ Ops.push_back(dwarf::DW_OP_div);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ EXPECT_EQ(E, EmptyExpr);
+
+ // Test fold {DW_OP_plus_uconst, Const1, DW_OP_plus_uconst, Const2} ->
+ // {DW_OP_plus_uconst, Const1 + Const2}
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
+ Ops.push_back(2);
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
+ Ops.push_back(3);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.push_back(dwarf::DW_OP_plus_uconst);
+ ResOps.push_back(5);
+ auto *ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+
+ // Test {DW_OP_constu, Const1, DW_OP_plus_uconst, Const2} -> {DW_OP_constu,
+ // Const1 + Const2}
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(2);
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
+ Ops.push_back(3);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.clear();
+ ResOps.push_back(dwarf::DW_OP_constu);
+ ResOps.push_back(5);
+ ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+
+ // Test {DW_OP_constu, Const1, DW_OP_constu, Const2, DW_OP_plus} ->
+ // {DW_OP_constu, Const1 + Const2}
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(8);
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(2);
+ Ops.push_back(dwarf::DW_OP_plus);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.clear();
+ ResOps.push_back(dwarf::DW_OP_constu);
+ ResOps.push_back(10);
+ ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+
+ // Test {DW_OP_constu, Const1, DW_OP_constu, Const2, DW_OP_minus} ->
+ // {DW_OP_constu, Const1 - Const2}
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(8);
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(2);
+ Ops.push_back(dwarf::DW_OP_minus);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.clear();
+ ResOps.push_back(dwarf::DW_OP_constu);
+ ResOps.push_back(6);
+ ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+
+ // Test {DW_OP_constu, Const1, DW_OP_constu, Const2, DW_OP_mul} ->
+ // {DW_OP_constu, Const1 * Const2}
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(8);
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(2);
+ Ops.push_back(dwarf::DW_OP_mul);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.clear();
+ ResOps.push_back(dwarf::DW_OP_constu);
+ ResOps.push_back(16);
+ ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+
+ // Test {DW_OP_constu, Const1, DW_OP_constu, Const2, DW_OP_div} ->
+ // {DW_OP_constu, Const1 / Const2}
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(8);
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(2);
+ Ops.push_back(dwarf::DW_OP_div);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.clear();
+ ResOps.push_back(dwarf::DW_OP_constu);
+ ResOps.push_back(4);
+ ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+
+ // Test {DW_OP_constu, Const1, DW_OP_constu, Const2, DW_OP_shl} ->
+ // {DW_OP_constu, Const1 << Const2}
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(8);
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(2);
+ Ops.push_back(dwarf::DW_OP_shl);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.clear();
+ ResOps.push_back(dwarf::DW_OP_constu);
+ ResOps.push_back(32);
+ ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+
+ // Test {DW_OP_constu, Const1, DW_OP_constu, Const2, DW_OP_shr} ->
+ // {DW_OP_constu, Const1 >> Const2}
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(8);
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(2);
+ Ops.push_back(dwarf::DW_OP_shr);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.clear();
+ ResOps.push_back(dwarf::DW_OP_constu);
+ ResOps.push_back(2);
+ ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+
+ // Test {DW_OP_plus_uconst, Const1, DW_OP_constu, Const2, DW_OP_plus} ->
+ // {DW_OP_plus_uconst, Const1 + Const2}
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
+ Ops.push_back(8);
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(2);
+ Ops.push_back(dwarf::DW_OP_plus);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.clear();
+ ResOps.push_back(dwarf::DW_OP_plus_uconst);
+ ResOps.push_back(10);
+ ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+
+ // Test {DW_OP_constu, Const1, DW_OP_plus, DW_OP_plus_uconst, Const2} ->
+ // {DW_OP_plus_uconst, Const1 + Const2}
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(8);
+ Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
+ Ops.push_back(2);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.clear();
+ ResOps.push_back(dwarf::DW_OP_plus_uconst);
+ ResOps.push_back(10);
+ ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+
+ // Test {DW_OP_constu, Const1, DW_OP_plus, DW_OP_constu, Const2, DW_OP_plus}
+ // -> {DW_OP_plus_uconst, Const1 + Const2}
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(8);
+ Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(2);
+ Ops.push_back(dwarf::DW_OP_plus);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.clear();
+ ResOps.push_back(dwarf::DW_OP_plus_uconst);
+ ResOps.push_back(10);
+ ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+
+ // Test {DW_OP_constu, Const1, DW_OP_mul, DW_OP_constu, Const2, DW_OP_mul} ->
+ // {DW_OP_constu, Const1 * Const2, DW_OP_mul}
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(8);
+ Ops.push_back(dwarf::DW_OP_mul);
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(2);
+ Ops.push_back(dwarf::DW_OP_mul);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.clear();
+ ResOps.push_back(dwarf::DW_OP_constu);
+ ResOps.push_back(16);
+ ResOps.push_back(dwarf::DW_OP_mul);
+ ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+
+ // Test {DW_OP_plus_uconst, Const1, DW_OP_plus, DW_OP_LLVM_arg, Arg,
+ // DW_OP_plus, DW_OP_constu, Const2, DW_OP_plus} -> {DW_OP_plus_uconst, Const1
+ // + Const2, DW_OP_LLVM_arg, Arg, DW_OP_plus}
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
+ Ops.push_back(8);
+ Ops.push_back(dwarf::DW_OP_LLVM_arg);
+ Ops.push_back(0);
+ Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(2);
+ Ops.push_back(dwarf::DW_OP_plus);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.clear();
+ ResOps.push_back(dwarf::DW_OP_plus_uconst);
+ ResOps.push_back(10);
+ ResOps.push_back(dwarf::DW_OP_LLVM_arg);
+ ResOps.push_back(0);
+ ResOps.push_back(dwarf::DW_OP_plus);
+ ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+
+ // Test {DW_OP_constu, Const1, DW_OP_plus, DW_OP_LLVM_arg, Arg, DW_OP_plus,
+ // DW_OP_plus_uconst, Const2} -> {DW_OP_constu, Const1 + Const2, DW_OP_plus,
+ // DW_OP_LLVM_arg, Arg, DW_OP_plus}
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(8);
+ Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_LLVM_arg);
+ Ops.push_back(0);
+ Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
+ Ops.push_back(2);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.clear();
+ ResOps.push_back(dwarf::DW_OP_plus_uconst);
+ ResOps.push_back(10);
+ ResOps.push_back(dwarf::DW_OP_LLVM_arg);
+ ResOps.push_back(0);
+ ResOps.push_back(dwarf::DW_OP_plus);
+ ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+
+ // Test {DW_OP_constu, Const1, DW_OP_plus, DW_OP_LLVM_arg, Arg, DW_OP_plus,
+ // DW_OP_constu, Const2, DW_OP_plus} -> {DW_OP_constu, Const1 + Const2,
+ // DW_OP_plus, DW_OP_LLVM_arg, Arg, DW_OP_plus}
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(8);
+ Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_LLVM_arg);
+ Ops.push_back(0);
+ Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(2);
+ Ops.push_back(dwarf::DW_OP_plus);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.clear();
+ ResOps.push_back(dwarf::DW_OP_plus_uconst);
+ ResOps.push_back(10);
+ ResOps.push_back(dwarf::DW_OP_LLVM_arg);
+ ResOps.push_back(0);
+ ResOps.push_back(dwarf::DW_OP_plus);
+ ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+
+ // Test {DW_OP_constu, Const1, DW_OP_mul, DW_OP_LLVM_arg, Arg, DW_OP_mul,
+ // DW_OP_constu, Const2, DW_OP_mul} -> {DW_OP_constu, Const1 * Const2,
+ // DW_OP_mul, DW_OP_LLVM_arg, Arg, DW_OP_mul}
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(8);
+ Ops.push_back(dwarf::DW_OP_mul);
+ Ops.push_back(dwarf::DW_OP_LLVM_arg);
+ Ops.push_back(0);
+ Ops.push_back(dwarf::DW_OP_mul);
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(2);
+ Ops.push_back(dwarf::DW_OP_mul);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.clear();
+ ResOps.push_back(dwarf::DW_OP_constu);
+ ResOps.push_back(16);
+ ResOps.push_back(dwarf::DW_OP_mul);
+ ResOps.push_back(dwarf::DW_OP_LLVM_arg);
+ ResOps.push_back(0);
+ ResOps.push_back(dwarf::DW_OP_mul);
+ ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+
+ // Test an overflow addition.
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
+ Ops.push_back(UINT64_MAX);
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
+ Ops.push_back(2);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.clear();
+ ResOps.push_back(dwarf::DW_OP_plus_uconst);
+ ResOps.push_back(UINT64_MAX);
+ ResOps.push_back(dwarf::DW_OP_plus_uconst);
+ ResOps.push_back(2);
+ ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+
+ // Test an underflow subtraction.
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(1);
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(2);
+ Ops.push_back(dwarf::DW_OP_minus);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.clear();
+ ResOps.push_back(dwarf::DW_OP_constu);
+ ResOps.push_back(1);
+ ResOps.push_back(dwarf::DW_OP_constu);
+ ResOps.push_back(2);
+ ResOps.push_back(dwarf::DW_OP_minus);
+ ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+
+ // Test a left shift greater than 64.
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(1);
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(65);
+ Ops.push_back(dwarf::DW_OP_shl);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.clear();
+ ResOps.push_back(dwarf::DW_OP_constu);
+ ResOps.push_back(1);
+ ResOps.push_back(dwarf::DW_OP_constu);
+ ResOps.push_back(65);
+ ResOps.push_back(dwarf::DW_OP_shl);
+ ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+
+ // Test a right shift greater than 64.
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(1);
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(65);
+ Ops.push_back(dwarf::DW_OP_shr);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.clear();
+ ResOps.push_back(dwarf::DW_OP_constu);
+ ResOps.push_back(1);
+ ResOps.push_back(dwarf::DW_OP_constu);
+ ResOps.push_back(65);
+ ResOps.push_back(dwarf::DW_OP_shr);
+ ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+
+ // Test an overflow multiplication.
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(UINT64_MAX);
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(2);
+ Ops.push_back(dwarf::DW_OP_mul);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.clear();
+ ResOps.push_back(dwarf::DW_OP_constu);
+ ResOps.push_back(UINT64_MAX);
+ ResOps.push_back(dwarf::DW_OP_constu);
+ ResOps.push_back(2);
+ ResOps.push_back(dwarf::DW_OP_mul);
+ ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+
+ // Test a divide by 0.
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(2);
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(0);
+ Ops.push_back(dwarf::DW_OP_div);
+ Expr = DIExpression::get(Context, Ops);
+ ReturnOps = Expr->foldConstantMath(Ops);
+ E = DIExpression::get(Context, ReturnOps);
+ ResOps.clear();
+ ResOps.push_back(dwarf::DW_OP_constu);
+ ResOps.push_back(2);
+ ResOps.push_back(dwarf::DW_OP_lit0);
+ ResOps.push_back(dwarf::DW_OP_div);
+ ResExpr = DIExpression::get(Context, ResOps);
+ EXPECT_EQ(E, ResExpr);
+}
+
TEST_F(DIExpressionTest, isValid) {
#define EXPECT_VALID(...) \
do { \
>From a067e43585e16c338c5df506a4a20266279ad6c8 Mon Sep 17 00:00:00 2001
From: Shubham Sandeep Rastogi <srastogi22 at apple.com>
Date: Fri, 8 Mar 2024 11:28:34 -0800
Subject: [PATCH 4/5] Use DIExpression:foldConstantMath() at the result of an
append()
---
llvm/include/llvm/IR/DebugInfoMetadata.h | 1 +
llvm/lib/IR/DebugInfoMetadata.cpp | 38 +++++
llvm/test/Bitcode/upgrade-dbg-addr.ll | 2 +-
.../MIR/AArch64/dbgcall-site-expr-chain.mir | 4 +-
llvm/unittests/IR/MetadataTest.cpp | 138 ++++++++++++++++++
5 files changed, 180 insertions(+), 3 deletions(-)
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 63aaf210797cbb..342f6bedfcc6a3 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -3121,6 +3121,7 @@ class DIExpression : public MDNode {
/// evaluated at compile time. Returns a new expression on success, or the old
/// expression if there is nothing to be reduced.
SmallVector<uint64_t> foldConstantMath(ArrayRef<uint64_t> WorkingOps);
+ static constexpr unsigned MaxRuleOpSize = 6;
};
inline bool operator==(const DIExpression::FragmentInfo &A,
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index a18747f7e583a8..82b0539dbfa0fa 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -1870,6 +1870,7 @@ DIExpression *DIExpression::append(const DIExpression *Expr,
// Copy Expr's current op list.
SmallVector<uint64_t, 16> NewOps;
+ uint64_t OpCount = 0;
for (auto Op : Expr->expr_ops()) {
// Append new opcodes before DW_OP_{stack_value, LLVM_fragment}.
if (Op.getOp() == dwarf::DW_OP_stack_value ||
@@ -1880,10 +1881,47 @@ DIExpression *DIExpression::append(const DIExpression *Expr,
Ops = std::nullopt;
}
Op.appendToVector(NewOps);
+ OpCount++;
}
NewOps.append(Ops.begin(), Ops.end());
auto *result = DIExpression::get(Expr->getContext(), NewOps);
assert(result->isValid() && "concatenated expression is not valid");
+
+ // Instead of applying a foldConstantMath on the entire expression, apply it
+ // only to the new operations to be added to the expression + the the
+ // preceding operations totalling to the longest foldable pattern.
+ uint64_t NewOpCount = 0;
+ for (auto It = result->expr_op_begin(); It != result->expr_op_end(); It++)
+ NewOpCount++;
+
+ // This is the number of new operations that were added to the expression,
+ // i.e. the number of operations in the Ops argument.
+ unsigned NumOfAddedOps = NewOpCount - OpCount;
+ // This is the number of operations that DIExpression::foldConstantMath should
+ // be applied upon, which is the number of new operations added + the
+ // preceding operations totalling to the longest foldable pattern.
+ unsigned NumOfOpsToBeFolded = 0;
+ if (OpCount < DIExpression::MaxRuleOpSize)
+ NumOfOpsToBeFolded = 0;
+ else
+ NumOfOpsToBeFolded =
+ NewOpCount - NumOfAddedOps - DIExpression::MaxRuleOpSize;
+ SmallVector<uint64_t> FoldedOps;
+
+ unsigned Count = 0;
+ SmallVector<uint64_t> OpsToBeFolded;
+ for (auto Op : result->expr_ops()) {
+ if (Count < NumOfOpsToBeFolded) {
+ Op.appendToVector(FoldedOps);
+ Count++;
+ } else
+ Op.appendToVector(OpsToBeFolded);
+ }
+
+ OpsToBeFolded = result->foldConstantMath(OpsToBeFolded);
+ FoldedOps.append(OpsToBeFolded);
+ result = DIExpression::get(Expr->getContext(), FoldedOps);
+ assert(result->isValid() && "concatenated expression is not valid");
return result;
}
diff --git a/llvm/test/Bitcode/upgrade-dbg-addr.ll b/llvm/test/Bitcode/upgrade-dbg-addr.ll
index 06a411c2c83486..de35609713f933 100644
--- a/llvm/test/Bitcode/upgrade-dbg-addr.ll
+++ b/llvm/test/Bitcode/upgrade-dbg-addr.ll
@@ -9,7 +9,7 @@ entry:
%num.addr = alloca i32, align 4
store i32 %num, ptr %num.addr, align 4
; CHECK-NOT: call void @llvm.dbg.addr
- ; CHECK: call void @llvm.dbg.value(metadata ptr %num.addr, metadata ![[#]], metadata !DIExpression(DW_OP_plus_uconst, 0, DW_OP_deref))
+ ; CHECK: call void @llvm.dbg.value(metadata ptr %num.addr, metadata ![[#]], metadata !DIExpression(DW_OP_deref))
call void @llvm.dbg.addr(metadata ptr %num.addr, metadata !16, metadata !DIExpression(DW_OP_plus_uconst, 0)), !dbg !17
%0 = load i32, ptr %num.addr, align 4
ret i32 %0
diff --git a/llvm/test/DebugInfo/MIR/AArch64/dbgcall-site-expr-chain.mir b/llvm/test/DebugInfo/MIR/AArch64/dbgcall-site-expr-chain.mir
index cb3e780664404c..02f4ce1200ca17 100644
--- a/llvm/test/DebugInfo/MIR/AArch64/dbgcall-site-expr-chain.mir
+++ b/llvm/test/DebugInfo/MIR/AArch64/dbgcall-site-expr-chain.mir
@@ -105,7 +105,7 @@ body: |
# CHECK: DW_TAG_GNU_call_site_parameter
# CHECK-NEXT: DW_AT_location (DW_OP_reg2 W2)
-# CHECK-NEXT: DW_AT_GNU_call_site_value (DW_OP_breg19 W19+700, DW_OP_plus_uconst 0x9, DW_OP_plus_uconst 0x50)
+# CHECK-NEXT: DW_AT_GNU_call_site_value (DW_OP_breg19 W19+789)
# CHECK: DW_TAG_GNU_call_site_parameter
# CHECK-NEXT: DW_AT_location (DW_OP_reg1 W1)
@@ -113,4 +113,4 @@ body: |
# CHECK: DW_TAG_GNU_call_site_parameter
# CHECK-NEXT: DW_AT_location (DW_OP_reg0 W0)
-# CHECK-NEXT: DW_AT_GNU_call_site_value (DW_OP_breg19 W19+100, DW_OP_plus_uconst 0x17)
+# CHECK-NEXT: DW_AT_GNU_call_site_value (DW_OP_breg19 W19+123)
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index 73eda16b6267c7..5f3299f0a20ba5 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -3639,6 +3639,144 @@ TEST_F(DIExpressionTest, Fold) {
EXPECT_EQ(E, ResExpr);
}
+TEST_F(DIExpressionTest, Append) {
+ // Test appending a {dwarf::DW_OP_constu, <const>, DW_OP_plus} to a DW_OP_plus
+ // expression
+ SmallVector<uint64_t, 8> Ops = {dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_constu,
+ 2, dwarf::DW_OP_plus};
+ auto *Expr = DIExpression::get(Context, Ops);
+ SmallVector<uint64_t, 8> AppendOps = {dwarf::DW_OP_constu, 3,
+ dwarf::DW_OP_plus};
+ auto *AppendExpr = DIExpression::append(Expr, AppendOps);
+ SmallVector<uint64_t, 8> OpsRes = {dwarf::DW_OP_LLVM_arg, 0,
+ dwarf::DW_OP_plus_uconst, 5};
+ auto *ResExpr = DIExpression::get(Context, OpsRes);
+ EXPECT_EQ(ResExpr, AppendExpr);
+
+ // Test appending a {dwarf::DW_OP_plus_uconst, <const>} to a DW_OP_plus
+ // expression uint64_t PlusUConstOps[] = {dwarf::DW_OP_plus_uconst, 3};
+ AppendOps.clear();
+ AppendOps.push_back(dwarf::DW_OP_plus_uconst);
+ AppendOps.push_back(3);
+ AppendExpr = DIExpression::append(Expr, AppendOps);
+ OpsRes.clear();
+ OpsRes.push_back(dwarf::DW_OP_LLVM_arg);
+ OpsRes.push_back(0);
+ OpsRes.push_back(dwarf::DW_OP_plus_uconst);
+ OpsRes.push_back(5);
+ ResExpr = DIExpression::get(Context, OpsRes);
+ EXPECT_EQ(ResExpr, AppendExpr);
+
+ // Test appending a {dwarf::DW_OP_constu, 0, DW_OP_plus} to an expression
+ AppendOps.clear();
+ AppendOps.push_back(dwarf::DW_OP_constu);
+ AppendOps.push_back(0);
+ AppendOps.push_back(dwarf::DW_OP_plus);
+ AppendExpr = DIExpression::append(Expr, AppendOps);
+ OpsRes.clear();
+ OpsRes.push_back(dwarf::DW_OP_LLVM_arg);
+ OpsRes.push_back(0);
+ OpsRes.push_back(dwarf::DW_OP_plus_uconst);
+ OpsRes.push_back(2);
+ ResExpr = DIExpression::get(Context, OpsRes);
+ EXPECT_EQ(ResExpr, AppendExpr);
+
+ // Test appending a {dwarf::DW_OP_constu, 0, DW_OP_minus} to an expression
+ AppendOps.clear();
+ AppendOps.push_back(dwarf::DW_OP_constu);
+ AppendOps.push_back(0);
+ AppendOps.push_back(dwarf::DW_OP_minus);
+ AppendExpr = DIExpression::append(Expr, AppendOps);
+ OpsRes.clear();
+ OpsRes.push_back(dwarf::DW_OP_LLVM_arg);
+ OpsRes.push_back(0);
+ OpsRes.push_back(dwarf::DW_OP_plus_uconst);
+ OpsRes.push_back(2);
+ ResExpr = DIExpression::get(Context, OpsRes);
+ EXPECT_EQ(ResExpr, AppendExpr);
+
+ // Test appending a {dwarf::DW_OP_constu, 0, DW_OP_shl} to an expression
+ AppendOps.clear();
+ AppendOps.push_back(dwarf::DW_OP_constu);
+ AppendOps.push_back(0);
+ AppendOps.push_back(dwarf::DW_OP_shl);
+ AppendExpr = DIExpression::append(Expr, AppendOps);
+ OpsRes.clear();
+ OpsRes.push_back(dwarf::DW_OP_LLVM_arg);
+ OpsRes.push_back(0);
+ OpsRes.push_back(dwarf::DW_OP_plus_uconst);
+ OpsRes.push_back(2);
+ ResExpr = DIExpression::get(Context, OpsRes);
+ EXPECT_EQ(ResExpr, AppendExpr);
+
+ // Test appending a {dwarf::DW_OP_constu, 0, DW_OP_shr} to an expression
+ AppendOps.clear();
+ AppendOps.push_back(dwarf::DW_OP_constu);
+ AppendOps.push_back(0);
+ AppendOps.push_back(dwarf::DW_OP_shr);
+ AppendExpr = DIExpression::append(Expr, AppendOps);
+ OpsRes.clear();
+ OpsRes.push_back(dwarf::DW_OP_LLVM_arg);
+ OpsRes.push_back(0);
+ OpsRes.push_back(dwarf::DW_OP_plus_uconst);
+ OpsRes.push_back(2);
+ ResExpr = DIExpression::get(Context, OpsRes);
+ EXPECT_EQ(ResExpr, AppendExpr);
+
+ // Test appending a {dwarf::DW_OP_constu, <const>, DW_OP_mul} to a DW_OP_mul
+ // expression
+ Ops.clear();
+ Ops.push_back(dwarf::DW_OP_LLVM_arg);
+ Ops.push_back(0);
+ Ops.push_back(dwarf::DW_OP_constu);
+ Ops.push_back(2);
+ Ops.push_back(dwarf::DW_OP_mul);
+ Expr = DIExpression::get(Context, Ops);
+ AppendOps.clear();
+ AppendOps.push_back(dwarf::DW_OP_constu);
+ AppendOps.push_back(3);
+ AppendOps.push_back(dwarf::DW_OP_mul);
+ AppendExpr = DIExpression::append(Expr, AppendOps);
+ OpsRes.clear();
+ OpsRes.push_back(dwarf::DW_OP_LLVM_arg);
+ OpsRes.push_back(0);
+ OpsRes.push_back(dwarf::DW_OP_constu);
+ OpsRes.push_back(6);
+ OpsRes.push_back(dwarf::DW_OP_mul);
+ ResExpr = DIExpression::get(Context, OpsRes);
+ EXPECT_EQ(ResExpr, AppendExpr);
+
+ // Test appending a {dwarf::DW_OP_constu, 1, DW_OP_mul} to an expression
+ AppendOps.clear();
+ AppendOps.push_back(dwarf::DW_OP_constu);
+ AppendOps.push_back(1);
+ AppendOps.push_back(dwarf::DW_OP_mul);
+ AppendExpr = DIExpression::append(Expr, AppendOps);
+ OpsRes.clear();
+ OpsRes.push_back(dwarf::DW_OP_LLVM_arg);
+ OpsRes.push_back(0);
+ OpsRes.push_back(dwarf::DW_OP_constu);
+ OpsRes.push_back(2);
+ OpsRes.push_back(dwarf::DW_OP_mul);
+ ResExpr = DIExpression::get(Context, OpsRes);
+ EXPECT_EQ(ResExpr, AppendExpr);
+
+ // Test appending a {dwarf::DW_OP_constu, 1, DW_OP_div} to an expression
+ AppendOps.clear();
+ AppendOps.push_back(dwarf::DW_OP_constu);
+ AppendOps.push_back(1);
+ AppendOps.push_back(dwarf::DW_OP_div);
+ AppendExpr = DIExpression::append(Expr, AppendOps);
+ OpsRes.clear();
+ OpsRes.push_back(dwarf::DW_OP_LLVM_arg);
+ OpsRes.push_back(0);
+ OpsRes.push_back(dwarf::DW_OP_constu);
+ OpsRes.push_back(2);
+ OpsRes.push_back(dwarf::DW_OP_mul);
+ ResExpr = DIExpression::get(Context, OpsRes);
+ EXPECT_EQ(ResExpr, AppendExpr);
+}
+
TEST_F(DIExpressionTest, isValid) {
#define EXPECT_VALID(...) \
do { \
>From b4d7e1cb2a81c465afe3d1cdae5712b393cc1ce9 Mon Sep 17 00:00:00 2001
From: Shubham Sandeep Rastogi <srastogi22 at apple.com>
Date: Fri, 8 Mar 2024 17:47:17 -0800
Subject: [PATCH 5/5] Use DIExpression:foldConstantMath() at the result of an
appendOpsToArg()
---
llvm/lib/IR/DebugInfoMetadata.cpp | 85 ++++++++++++++++++-
.../MIR/InstrRef/deref-spills-with-size.mir | 24 +++---
.../InstrRef/follow-spill-of-indir-value.mir | 4 +-
llvm/test/DebugInfo/salvage-icmp.ll | 2 +-
.../test/DebugInfo/salvage-limit-expr-size.ll | 8 +-
.../Transforms/Coroutines/swift-async-dbg.ll | 8 +-
.../Transforms/InstCombine/cast-mul-select.ll | 2 +-
.../Transforms/InstCombine/debuginfo-dce.ll | 2 +-
.../Transforms/InstCombine/debuginfo-sink.ll | 62 +++++++-------
llvm/unittests/IR/MetadataTest.cpp | 19 +++++
llvm/unittests/Transforms/Utils/LocalTest.cpp | 3 +-
11 files changed, 158 insertions(+), 61 deletions(-)
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index 82b0539dbfa0fa..85b6147c87dfa3 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -1779,17 +1779,55 @@ DIExpression *DIExpression::appendOpsToArg(const DIExpression *Expr,
unsigned ArgNo, bool StackValue) {
assert(Expr && "Can't add ops to this expression");
+ unsigned OpCount = 0;
+
// Handle non-variadic intrinsics by prepending the opcodes.
if (!any_of(Expr->expr_ops(),
[](auto Op) { return Op.getOp() == dwarf::DW_OP_LLVM_arg; })) {
assert(ArgNo == 0 &&
"Location Index must be 0 for a non-variadic expression.");
+
+ for (auto It = Expr->expr_op_begin(); It != Expr->expr_op_end(); It++)
+ OpCount++;
SmallVector<uint64_t, 8> NewOps(Ops.begin(), Ops.end());
- return DIExpression::prependOpcodes(Expr, NewOps, StackValue);
+ auto *Result = DIExpression::prependOpcodes(Expr, NewOps, StackValue);
+
+ // Instead of applying a foldConstantMath on the entire expression, apply it
+ // only on operations that are preppended + the succeeding operations
+ // totalling to the maximum foldable pattern.
+ uint64_t NewOpCount = 0;
+ for (auto It = Result->expr_op_begin(); It != Result->expr_op_end(); It++)
+ NewOpCount++;
+
+ // This is the number of new operations that were added to the expression,
+ // i.e. the number of operations in the Ops argument.
+ unsigned NumOfAddedOps = NewOpCount - OpCount;
+ // This is the number of operations that DIExpression::foldConstantMath
+ // should be applied upon, which is the number of new operations added + the
+ // succeeding operations totalling to the longest foldable pattern.
+ unsigned NumOfOpsToBeFolded = NumOfAddedOps + DIExpression::MaxRuleOpSize;
+ unsigned Count = 0;
+ SmallVector<uint64_t> OpsToBeFolded;
+ SmallVector<uint64_t> FoldedOps;
+
+ for (auto Op : Result->expr_ops()) {
+ if (Count < NumOfOpsToBeFolded) {
+ Op.appendToVector(OpsToBeFolded);
+ Count++;
+ } else {
+ Op.appendToVector(FoldedOps);
+ }
+ }
+
+ OpsToBeFolded = Result->foldConstantMath(OpsToBeFolded);
+ OpsToBeFolded.append(FoldedOps);
+ return DIExpression::get(Result->getContext(), OpsToBeFolded);
}
+ unsigned ArgPos;
SmallVector<uint64_t, 8> NewOps;
for (auto Op : Expr->expr_ops()) {
+ OpCount++;
// A DW_OP_stack_value comes at the end, but before a DW_OP_LLVM_fragment.
if (StackValue) {
if (Op.getOp() == dwarf::DW_OP_stack_value)
@@ -1800,13 +1838,54 @@ DIExpression *DIExpression::appendOpsToArg(const DIExpression *Expr,
}
}
Op.appendToVector(NewOps);
- if (Op.getOp() == dwarf::DW_OP_LLVM_arg && Op.getArg(0) == ArgNo)
+ if (Op.getOp() == dwarf::DW_OP_LLVM_arg && Op.getArg(0) == ArgNo) {
NewOps.insert(NewOps.end(), Ops.begin(), Ops.end());
+ ArgPos = OpCount;
+ }
}
if (StackValue)
NewOps.push_back(dwarf::DW_OP_stack_value);
- return DIExpression::get(Expr->getContext(), NewOps);
+ auto *Result = DIExpression::get(Expr->getContext(), NewOps);
+
+ // Instead of applying a foldConstantMath on the entire expression, apply it
+ // only on operations that are inserted to the ArgNo + the preceeding
+ // operations totalling to the maximum foldable pattern.
+ unsigned NewOpCount = 0;
+ for (auto It = Result->expr_op_begin(); It != Result->expr_op_end(); It++)
+ NewOpCount++;
+
+ unsigned Count = 0;
+ SmallVector<uint64_t> OpsToBeFolded;
+ SmallVector<uint64_t> FoldedOps;
+ SmallVector<uint64_t> RemainingOps;
+
+ // This is the number of operations we can consider already folded in the
+ // expression, which precede the ArgNo that the Ops are appended to.
+ unsigned FoldedOpCount = ArgPos > DIExpression::MaxRuleOpSize
+ ? ArgPos - DIExpression::MaxRuleOpSize
+ : 0;
+ // This is the number of operations that DIExpression::foldConstantMath should
+ // be applied upon, which is the number of new operations added + the
+ // preceeding operations totalling to the maximum foldable pattern.
+ unsigned OpsToBeFoldedCount =
+ NewOpCount - OpCount + DIExpression::MaxRuleOpSize;
+
+ for (auto Op : Result->expr_ops()) {
+ if (Count < FoldedOpCount) {
+ Op.appendToVector(FoldedOps);
+ Count++;
+ } else if (Count >= FoldedOpCount && Count < OpsToBeFoldedCount) {
+ Op.appendToVector(OpsToBeFolded);
+ Count++;
+ } else
+ Op.appendToVector(RemainingOps);
+ }
+
+ OpsToBeFolded = Result->foldConstantMath(OpsToBeFolded);
+ FoldedOps.append(OpsToBeFolded);
+ FoldedOps.append(RemainingOps);
+ return DIExpression::get(Result->getContext(), FoldedOps);
}
DIExpression *DIExpression::replaceArg(const DIExpression *Expr,
diff --git a/llvm/test/DebugInfo/MIR/InstrRef/deref-spills-with-size.mir b/llvm/test/DebugInfo/MIR/InstrRef/deref-spills-with-size.mir
index 0253c95cc1324b..0ab3ec62f35467 100644
--- a/llvm/test/DebugInfo/MIR/InstrRef/deref-spills-with-size.mir
+++ b/llvm/test/DebugInfo/MIR/InstrRef/deref-spills-with-size.mir
@@ -83,9 +83,9 @@
# DWARF-NEXT: DW_OP_breg7 RSP-8
# DWARF-NEXT: DW_OP_breg7 RSP-8, DW_OP_deref_size 0x1, DW_OP_stack_value
## scalar / stack value with various sizes.
-# DWARF-NEXT: DW_OP_breg7 RSP-8, DW_OP_deref_size 0x8, DW_OP_lit1, DW_OP_plus, DW_OP_stack_value
-# DWARF-NEXT: DW_OP_breg7 RSP-8, DW_OP_deref, DW_OP_lit1, DW_OP_plus, DW_OP_stack_value
-# DWARF-NEXT: DW_OP_breg7 RSP-8, DW_OP_deref_size 0x1, DW_OP_lit1, DW_OP_plus, DW_OP_stack_value)
+# DWARF-NEXT: DW_OP_breg7 RSP-8, DW_OP_deref_size 0x8, DW_OP_plus_uconst 0x1, DW_OP_stack_value
+# DWARF-NEXT: DW_OP_breg7 RSP-8, DW_OP_deref, DW_OP_plus_uconst 0x1, DW_OP_stack_value
+# DWARF-NEXT: DW_OP_breg7 RSP-8, DW_OP_deref_size 0x1, DW_OP_plus_uconst 0x1, DW_OP_stack_value)
# DWARF: DW_AT_name ("flannel")
# Variable with fragments.
@@ -96,9 +96,9 @@
# DWARF-NEXT: DW_OP_breg7 RSP-8, DW_OP_piece 0x4
# DWARF-NEXT: DW_OP_breg7 RSP-8, DW_OP_deref_size 0x1, DW_OP_stack_value, DW_OP_piece 0x4
## Scalar / stack value with various sizes.
-# DWARF-NEXT: DW_OP_breg7 RSP-8, DW_OP_deref_size 0x8, DW_OP_lit1, DW_OP_plus, DW_OP_stack_value, DW_OP_piece 0x4
-# DWARF-NEXT: DW_OP_breg7 RSP-8, DW_OP_deref_size 0x4, DW_OP_lit1, DW_OP_plus, DW_OP_stack_value, DW_OP_piece 0x4
-# DWARF-NEXT: DW_OP_breg7 RSP-8, DW_OP_deref_size 0x1, DW_OP_lit1, DW_OP_plus, DW_OP_stack_value, DW_OP_piece 0x4)
+# DWARF-NEXT: DW_OP_breg7 RSP-8, DW_OP_deref_size 0x8, DW_OP_plus_uconst 0x1, DW_OP_stack_value, DW_OP_piece 0x4
+# DWARF-NEXT: DW_OP_breg7 RSP-8, DW_OP_deref_size 0x4, DW_OP_plus_uconst 0x1, DW_OP_stack_value, DW_OP_piece 0x4
+# DWARF-NEXT: DW_OP_breg7 RSP-8, DW_OP_deref_size 0x1, DW_OP_plus_uconst 0x1, DW_OP_stack_value, DW_OP_piece 0x4)
# DWARF: DW_AT_name ("shoes")
--- |
@@ -308,7 +308,7 @@ body: |
$rax = MOV64ri 0, debug-location !7
DBG_INSTR_REF !8, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_constu, 1, DW_OP_plus, DW_OP_stack_value), dbg-instr-ref(16, 0), debug-location !7
; CHECK: DBG_VALUE_LIST ![[VARNUM]],
- ; CHECK-SAME: !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_constu, 8, DW_OP_minus, DW_OP_deref_size, 8, DW_OP_constu, 1, DW_OP_plus, DW_OP_stack_value), $rsp
+ ; CHECK-SAME: !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_constu, 8, DW_OP_minus, DW_OP_deref_size, 8, DW_OP_plus_uconst, 1, DW_OP_stack_value), $rsp
$eax = MOV32ri 0, debug-location !7
DBG_VALUE $noreg, $noreg, !8, !DIExpression(), debug-location !7
; CHECK: DBG_VALUE $noreg, $noreg
@@ -319,7 +319,7 @@ body: |
$rax = MOV64ri 0, debug-location !7
DBG_INSTR_REF !8, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_constu, 1, DW_OP_plus, DW_OP_stack_value), dbg-instr-ref(17, 0), debug-location !7
; CHECK: DBG_VALUE_LIST ![[VARNUM]],
- ; CHECK-SAME: !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_constu, 8, DW_OP_minus, DW_OP_deref, DW_OP_constu, 1, DW_OP_plus, DW_OP_stack_value), $rsp
+ ; CHECK-SAME: !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_constu, 8, DW_OP_minus, DW_OP_deref, DW_OP_plus_uconst, 1, DW_OP_stack_value), $rsp
$eax = MOV32ri 0, debug-location !7
DBG_VALUE $noreg, $noreg, !8, !DIExpression(), debug-location !7
; CHECK: DBG_VALUE $noreg, $noreg
@@ -330,7 +330,7 @@ body: |
$rax = MOV64ri 0, debug-location !7
DBG_INSTR_REF !8, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_constu, 1, DW_OP_plus, DW_OP_stack_value), dbg-instr-ref(18, 0), debug-location !7
; CHECK: DBG_VALUE_LIST ![[VARNUM]],
- ; CHECK-SAME: !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_constu, 8, DW_OP_minus, DW_OP_deref_size, 1, DW_OP_constu, 1, DW_OP_plus, DW_OP_stack_value), $rsp
+ ; CHECK-SAME: !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_constu, 8, DW_OP_minus, DW_OP_deref_size, 1, DW_OP_plus_uconst, 1, DW_OP_stack_value), $rsp
$eax = MOV32ri 0, debug-location !7
DBG_VALUE $noreg, $noreg, !8, !DIExpression(), debug-location !7
; CHECK: DBG_VALUE $noreg, $noreg
@@ -341,7 +341,7 @@ body: |
$rax = MOV64ri 0, debug-location !7
DBG_INSTR_REF !10, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_constu, 1, DW_OP_plus, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 32), dbg-instr-ref(19, 0), debug-location !7
; CHECK: DBG_VALUE_LIST ![[VARNUM2]],
- ; CHECK-SAME: !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_constu, 8, DW_OP_minus, DW_OP_deref_size, 8, DW_OP_constu, 1, DW_OP_plus, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 32), $rsp
+ ; CHECK-SAME: !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_constu, 8, DW_OP_minus, DW_OP_deref_size, 8, DW_OP_plus_uconst, 1, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 32), $rsp
$eax = MOV32ri 0, debug-location !7
DBG_VALUE $noreg, $noreg, !10, !DIExpression(DW_OP_LLVM_fragment, 0, 32), debug-location !7
; CHECK: DBG_VALUE $noreg, $noreg
@@ -352,7 +352,7 @@ body: |
$rax = MOV64ri 0, debug-location !7
DBG_INSTR_REF !10, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_constu, 1, DW_OP_plus, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 32), dbg-instr-ref(20, 0), debug-location !7
; CHECK: DBG_VALUE_LIST ![[VARNUM2]],
- ; CHECK-SAME: !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_constu, 8, DW_OP_minus, DW_OP_deref_size, 4, DW_OP_constu, 1, DW_OP_plus, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 32), $rsp
+ ; CHECK-SAME: !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_constu, 8, DW_OP_minus, DW_OP_deref_size, 4, DW_OP_plus_uconst, 1, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 32), $rsp
$eax = MOV32ri 0, debug-location !7
DBG_VALUE $noreg, $noreg, !10, !DIExpression(DW_OP_LLVM_fragment, 0, 32), debug-location !7
; CHECK: DBG_VALUE $noreg, $noreg
@@ -363,7 +363,7 @@ body: |
$rax = MOV64ri 0, debug-location !7
DBG_INSTR_REF !10, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_constu, 1, DW_OP_plus, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 32), dbg-instr-ref(21, 0), debug-location !7
; CHECK: DBG_VALUE_LIST ![[VARNUM2]],
- ; CHECK-SAME: !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_constu, 8, DW_OP_minus, DW_OP_deref_size, 1, DW_OP_constu, 1, DW_OP_plus, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 32), $rsp
+ ; CHECK-SAME: !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_constu, 8, DW_OP_minus, DW_OP_deref_size, 1, DW_OP_plus_uconst, 1, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 32), $rsp
$eax = MOV32ri 0, debug-location !7
DBG_VALUE $noreg, $noreg, !10, !DIExpression(DW_OP_LLVM_fragment, 0, 32), debug-location !7
; CHECK: DBG_VALUE $noreg, $noreg
diff --git a/llvm/test/DebugInfo/MIR/InstrRef/follow-spill-of-indir-value.mir b/llvm/test/DebugInfo/MIR/InstrRef/follow-spill-of-indir-value.mir
index e3b8df27785434..d3541b4845721b 100644
--- a/llvm/test/DebugInfo/MIR/InstrRef/follow-spill-of-indir-value.mir
+++ b/llvm/test/DebugInfo/MIR/InstrRef/follow-spill-of-indir-value.mir
@@ -27,7 +27,7 @@
##
## Second location, variable pointed to by the register value plus eight.
##
-# DWARF-NEXT: DW_OP_breg7 RSP-8, DW_OP_deref, DW_OP_lit8, DW_OP_plus)
+# DWARF-NEXT: DW_OP_breg7 RSP-8, DW_OP_deref, DW_OP_plus_uconst 0x8)
##
## Spilt to stack: push stack location and deref the pointer onto the dwarf
## expr stack. Then add eight to it, and it points to the variable.
@@ -135,7 +135,7 @@ body: |
; CHECK: DBG_VALUE $rdi,
MOV64mr $rsp, 1, $noreg, -8, $noreg, $rdi :: (store (s64) into %stack.0)
$rdi = MOV64ri 0
- ; CHECK: DBG_VALUE $rsp, 0, ![[VARNUM]], !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_deref, DW_OP_constu, 8, DW_OP_plus),
+ ; CHECK: DBG_VALUE $rsp, 0, ![[VARNUM]], !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_deref, DW_OP_plus_uconst, 8),
renamable $rax = MOV64rm $rsp, 1, $noreg, -8, $noreg :: (load (s64) from %stack.0)
renamable $eax = MOV32rm killed renamable $rax, 1, $noreg, 0, $noreg, debug-location !24 :: (load (s32) from %ir.i1, !tbaa !25)
diff --git a/llvm/test/DebugInfo/salvage-icmp.ll b/llvm/test/DebugInfo/salvage-icmp.ll
index ce9e809e12c1a8..f47c20e7992e65 100644
--- a/llvm/test/DebugInfo/salvage-icmp.ll
+++ b/llvm/test/DebugInfo/salvage-icmp.ll
@@ -5,7 +5,7 @@
; CHECK: call void @llvm.dbg.value(metadata i32 %a,
; CHECK-SAME: ![[VAR_C:[0-9]+]],
-; CHECK-SAME: !DIExpression(DW_OP_constu, 0, DW_OP_ne, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_constu, 0, DW_OP_eq, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_constu, 1, DW_OP_gt, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_consts, 18446744073709551615, DW_OP_gt, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_constu, 2, DW_OP_ge, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_consts, 18446744073709551614, DW_OP_ge, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_constu, 3, DW_OP_lt, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_consts, 18446744073709551613, DW_OP_lt, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_constu, 4, DW_OP_le, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_consts, 18446744073709551612, DW_OP_le, DW_OP_stack_value))
+; CHECK-SAME: !DIExpression(DW_OP_lit0, DW_OP_ne, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_lit0, DW_OP_eq, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_constu, 1, DW_OP_gt, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_consts, 18446744073709551615, DW_OP_gt, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_constu, 2, DW_OP_ge, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_consts, 18446744073709551614, DW_OP_ge, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_constu, 3, DW_OP_lt, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_consts, 18446744073709551613, DW_OP_lt, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_constu, 4, DW_OP_le, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_consts, 18446744073709551612, DW_OP_le, DW_OP_stack_value))
; CHECK: call void @llvm.dbg.value(metadata !DIArgList(i32 %a, i32 %a, i32 %a, i32 %b, i32 %a, i32 %b, i32 %b, i32 %a, i32 %a, i32 %b, i32 %b),
; CHECK-SAME: ![[VAR_C:[0-9]+]],
diff --git a/llvm/test/DebugInfo/salvage-limit-expr-size.ll b/llvm/test/DebugInfo/salvage-limit-expr-size.ll
index 94e451327b2148..4d021f5b192fd9 100644
--- a/llvm/test/DebugInfo/salvage-limit-expr-size.ll
+++ b/llvm/test/DebugInfo/salvage-limit-expr-size.ll
@@ -11,13 +11,13 @@ entry:
;; These expressions should salvage successfully, up to exactly 128 elements.
; CHECK: call void @llvm.dbg.value(metadata i32 %a, metadata ![[VAR_C:[0-9]+]]
; CHECK-NEXT: call void @llvm.dbg.value(metadata !DIArgList(i32 %a, i32 %b), metadata ![[VAR_C]]
- call void @llvm.dbg.value(metadata i32 %add.1, metadata !12, metadata !DIExpression(DW_OP_constu, 1, DW_OP_plus, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_stack_value)), !dbg !13
- call void @llvm.dbg.value(metadata i32 %add.2, metadata !12, metadata !DIExpression(DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_stack_value)), !dbg !13
+ call void @llvm.dbg.value(metadata i32 %add.1, metadata !12, metadata !DIExpression(DW_OP_lit0, DW_OP_ne, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !13
+ call void @llvm.dbg.value(metadata i32 %add.2, metadata !12, metadata !DIExpression(DW_OP_lit0, DW_OP_ne, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !13
;; These expressions should be set undef, as they would salvage up to exactly 129 elements.
; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 poison, metadata ![[VAR_C]]
; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 poison, metadata ![[VAR_C]]
- call void @llvm.dbg.value(metadata i32 %add.1, metadata !12, metadata !DIExpression(DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_stack_value)), !dbg !13
- call void @llvm.dbg.value(metadata i32 %add.2, metadata !12, metadata !DIExpression(DW_OP_constu, 1, DW_OP_plus, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_plus_uconst, 1, DW_OP_stack_value)), !dbg !13
+ call void @llvm.dbg.value(metadata i32 %add.1, metadata !12, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !13
+ call void @llvm.dbg.value(metadata i32 %add.2, metadata !12, metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !13
%mul = mul nsw i32 %a, %b, !dbg !15
ret i32 %mul, !dbg !15
}
diff --git a/llvm/test/Transforms/Coroutines/swift-async-dbg.ll b/llvm/test/Transforms/Coroutines/swift-async-dbg.ll
index 74edf7a3f3a540..548b3eddb39d37 100644
--- a/llvm/test/Transforms/Coroutines/swift-async-dbg.ll
+++ b/llvm/test/Transforms/Coroutines/swift-async-dbg.ll
@@ -30,7 +30,7 @@ define swifttailcc void @coroutineA(ptr swiftasync %arg) !dbg !48 {
; CHECK-LABEL: define {{.*}} @coroutineA(
; CHECK-SAME: ptr swiftasync %[[frame_ptr:.*]])
; CHECK: @llvm.dbg.declare(metadata ptr %[[frame_ptr]], {{.*}} !DIExpression(
-; CHECK-SAME: DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8)
+; CHECK-SAME: DW_OP_plus_uconst, 24)
; CHECK: @llvm.dbg.value(metadata ptr %[[frame_ptr]], {{.*}} !DIExpression(
; CHECK-SAME: DW_OP_plus_uconst, 16, DW_OP_deref)
; CHECK: call {{.*}} @swift_task_switch
@@ -49,7 +49,7 @@ define swifttailcc void @coroutineA(ptr swiftasync %arg) !dbg !48 {
; CHECK-LABEL: define {{.*}} @coroutineATY0_(
; CHECK-SAME: ptr swiftasync %[[frame_ptr:.*]])
; CHECK: @llvm.dbg.declare(metadata ptr %[[frame_ptr]], {{.*}} !DIExpression(
-; CHECK-SAME: DW_OP_LLVM_entry_value, 1, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8)
+; CHECK-SAME: DW_OP_LLVM_entry_value, 1, DW_OP_plus_uconst, 24)
; CHECK: @llvm.dbg.value(metadata ptr %[[frame_ptr]], {{.*}} !DIExpression(
; CHECK-SAME: DW_OP_LLVM_entry_value, 1, DW_OP_plus_uconst, 16, DW_OP_deref)
; CHECK: @llvm.dbg.value(metadata !DIArgList(ptr %[[frame_ptr]], i32 %{{.*}}), {{.*}} !DIExpression(
@@ -70,7 +70,7 @@ define swifttailcc void @coroutineA(ptr swiftasync %arg) !dbg !48 {
; CHECK-SAME: ptr swiftasync %[[frame_ptr:.*]])
; Note the extra level of indirection that shows up here!
; CHECK: @llvm.dbg.declare(metadata ptr %[[frame_ptr]], {{.*}} !DIExpression(
-; CHECK-SAME: DW_OP_LLVM_entry_value, 1, DW_OP_deref, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8)
+; CHECK-SAME: DW_OP_LLVM_entry_value, 1, DW_OP_deref, DW_OP_plus_uconst, 24)
; CHECK: @llvm.dbg.value(metadata ptr %[[frame_ptr]], {{.*}} !DIExpression(
; CHECK-SAME: DW_OP_LLVM_entry_value, 1, DW_OP_deref, DW_OP_plus_uconst, 16, DW_OP_deref)
; CHECK: call {{.*}} @swift_task_switch
@@ -85,7 +85,7 @@ define swifttailcc void @coroutineA(ptr swiftasync %arg) !dbg !48 {
; CHECK-LABEL: define {{.*}} @coroutineATY2_(
; CHECK-SAME: ptr swiftasync %[[frame_ptr:.*]])
; CHECK: @llvm.dbg.declare(metadata ptr %[[frame_ptr]], {{.*}} !DIExpression(
-; CHECK-SAME: DW_OP_LLVM_entry_value, 1, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8)
+; CHECK-SAME: DW_OP_LLVM_entry_value, 1, DW_OP_plus_uconst, 24)
}
; Everything from here on is just support code for the coroutines.
diff --git a/llvm/test/Transforms/InstCombine/cast-mul-select.ll b/llvm/test/Transforms/InstCombine/cast-mul-select.ll
index 50769ebe76f5c5..79d7ac9e6d0bed 100644
--- a/llvm/test/Transforms/InstCombine/cast-mul-select.ll
+++ b/llvm/test/Transforms/InstCombine/cast-mul-select.ll
@@ -207,7 +207,7 @@ define void @PR36225(i32 %a, i32 %b, i1 %c1, i3 %v1, i3 %v2) {
; DBGINFO-NEXT: entry:
; DBGINFO-NEXT: br label [[WHILE_BODY:%.*]], !dbg [[DBG94:![0-9]+]]
; DBGINFO: while.body:
-; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i32 [[B:%.*]], metadata [[META89:![0-9]+]], metadata !DIExpression(DW_OP_constu, 0, DW_OP_eq, DW_OP_stack_value)), !dbg [[DBG95:![0-9]+]]
+; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i32 [[B:%.*]], metadata [[META89:![0-9]+]], metadata !DIExpression(DW_OP_lit0, DW_OP_eq, DW_OP_stack_value)), !dbg [[DBG95:![0-9]+]]
; DBGINFO-NEXT: br i1 [[C1:%.*]], label [[FOR_BODY3_US:%.*]], label [[FOR_BODY3:%.*]], !dbg [[DBG96:![0-9]+]]
; DBGINFO: for.body3.us:
; DBGINFO-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[B]], 0, !dbg [[DBG95]]
diff --git a/llvm/test/Transforms/InstCombine/debuginfo-dce.ll b/llvm/test/Transforms/InstCombine/debuginfo-dce.ll
index 257222cb70c238..27e0580804cae7 100644
--- a/llvm/test/Transforms/InstCombine/debuginfo-dce.ll
+++ b/llvm/test/Transforms/InstCombine/debuginfo-dce.ll
@@ -61,7 +61,7 @@ entry:
; CHECK: define void @salvage_gep0
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @llvm.dbg.value(metadata ptr %queue,
-; CHECK-SAME: metadata !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_plus_uconst, 0, DW_OP_stack_value))
+; CHECK-SAME: metadata !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_stack_value))
store ptr %1, ptr %im_not_dead, align 8
ret void, !dbg !26
}
diff --git a/llvm/test/Transforms/InstCombine/debuginfo-sink.ll b/llvm/test/Transforms/InstCombine/debuginfo-sink.ll
index 0c7d30d70c366b..63f09d26cce4f9 100644
--- a/llvm/test/Transforms/InstCombine/debuginfo-sink.ll
+++ b/llvm/test/Transforms/InstCombine/debuginfo-sink.ll
@@ -54,33 +54,33 @@ sink2:
ret i32 %extract
}
-; This GEP is sunk, and has multiple debug uses in the same block. Check that
-; only the last use is cloned into the sunk block, and that both of the
-; original dbg.values are salvaged.
-;
-; CHECK-LABEL: define i32 @baz(ptr
-; CHECK: call void @llvm.dbg.value(metadata ptr %a, metadata !{{[0-9]+}},
-; CHECK-SAME: metadata !DIExpression(DW_OP_plus_uconst, 4, DW_OP_stack_value))
-; CHECK-NEXT: call void @llvm.dbg.value(metadata ptr %a, metadata !{{[0-9]+}},
-; CHECK-SAME: metadata !DIExpression(DW_OP_plus_uconst, 4, DW_OP_plus_uconst, 5, DW_OP_stack_value))
-; CHECK-NEXT: br label %sink1
-
-define i32 @baz(ptr %a) !dbg !80 {
-entry:
- %gep = getelementptr i32, ptr %a, i32 1
- call void @llvm.dbg.value(metadata ptr %gep, metadata !83, metadata !12), !dbg !84
- call void @llvm.dbg.value(metadata ptr %gep, metadata !83, metadata !DIExpression(DW_OP_plus_uconst, 5)), !dbg !85
- br label %sink1
-
-sink1:
-; CHECK-LABEL: sink1:
-; CHECK: call void @llvm.dbg.value(metadata ptr %gep,
-; CHECK-SAME: metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_plus_uconst, 5))
-; CHECK-NEXT: load
- %0 = load i32, ptr %gep, align 4, !dbg !85
- ret i32 %0, !dbg !85
-}
-
+; This GEP is sunk, and has multiple debug uses in the same block. Check that
+; only the last use is cloned into the sunk block, and that both of the
+; original dbg.values are salvaged.
+;
+; CHECK-LABEL: define i32 @baz(ptr
+; CHECK: call void @llvm.dbg.value(metadata ptr %a, metadata !{{[0-9]+}},
+; CHECK-SAME: metadata !DIExpression(DW_OP_plus_uconst, 4, DW_OP_stack_value))
+; CHECK-NEXT: call void @llvm.dbg.value(metadata ptr %a, metadata !{{[0-9]+}},
+; CHECK-SAME: metadata !DIExpression(DW_OP_plus_uconst, 9, DW_OP_stack_value))
+; CHECK-NEXT: br label %sink1
+
+define i32 @baz(ptr %a) !dbg !80 {
+entry:
+ %gep = getelementptr i32, ptr %a, i32 1
+ call void @llvm.dbg.value(metadata ptr %gep, metadata !83, metadata !12), !dbg !84
+ call void @llvm.dbg.value(metadata ptr %gep, metadata !83, metadata !DIExpression(DW_OP_plus_uconst, 5)), !dbg !85
+ br label %sink1
+
+sink1:
+; CHECK-LABEL: sink1:
+; CHECK: call void @llvm.dbg.value(metadata ptr %gep,
+; CHECK-SAME: metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_plus_uconst, 5))
+; CHECK-NEXT: load
+ %0 = load i32, ptr %gep, align 4, !dbg !85
+ ret i32 %0, !dbg !85
+}
+
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4, !5}
!llvm.ident = !{!6}
@@ -105,7 +105,7 @@ sink1:
!72 = !{!10, !10, !10}
!73 = !DILocalVariable(name: "k", scope: !70, file: !1, line: 2, type: !10)
!74 = !DILocation(line: 5, column: 3, scope: !70)
-!80 = distinct !DISubprogram(name: "baz", scope: !1, file: !1, line: 2, type: !8, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
-!83 = !DILocalVariable(name: "l", scope: !80, file: !1, line: 2, type: !10)
-!84 = !DILocation(line: 5, column: 3, scope: !80)
-!85 = !DILocation(line: 6, column: 3, scope: !80)
+!80 = distinct !DISubprogram(name: "baz", scope: !1, file: !1, line: 2, type: !8, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
+!83 = !DILocalVariable(name: "l", scope: !80, file: !1, line: 2, type: !10)
+!84 = !DILocation(line: 5, column: 3, scope: !80)
+!85 = !DILocation(line: 6, column: 3, scope: !80)
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index 5f3299f0a20ba5..b92e6e30b01f68 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -3652,6 +3652,9 @@ TEST_F(DIExpressionTest, Append) {
dwarf::DW_OP_plus_uconst, 5};
auto *ResExpr = DIExpression::get(Context, OpsRes);
EXPECT_EQ(ResExpr, AppendExpr);
+ auto *AppendToArgExpr =
+ DIExpression::appendOpsToArg(Expr, AppendOps, 0, false);
+ EXPECT_EQ(ResExpr, AppendToArgExpr);
// Test appending a {dwarf::DW_OP_plus_uconst, <const>} to a DW_OP_plus
// expression uint64_t PlusUConstOps[] = {dwarf::DW_OP_plus_uconst, 3};
@@ -3666,6 +3669,8 @@ TEST_F(DIExpressionTest, Append) {
OpsRes.push_back(5);
ResExpr = DIExpression::get(Context, OpsRes);
EXPECT_EQ(ResExpr, AppendExpr);
+ AppendToArgExpr = DIExpression::appendOpsToArg(Expr, AppendOps, 0, false);
+ EXPECT_EQ(ResExpr, AppendToArgExpr);
// Test appending a {dwarf::DW_OP_constu, 0, DW_OP_plus} to an expression
AppendOps.clear();
@@ -3680,6 +3685,8 @@ TEST_F(DIExpressionTest, Append) {
OpsRes.push_back(2);
ResExpr = DIExpression::get(Context, OpsRes);
EXPECT_EQ(ResExpr, AppendExpr);
+ AppendToArgExpr = DIExpression::appendOpsToArg(Expr, AppendOps, 0, false);
+ EXPECT_EQ(ResExpr, AppendToArgExpr);
// Test appending a {dwarf::DW_OP_constu, 0, DW_OP_minus} to an expression
AppendOps.clear();
@@ -3694,6 +3701,8 @@ TEST_F(DIExpressionTest, Append) {
OpsRes.push_back(2);
ResExpr = DIExpression::get(Context, OpsRes);
EXPECT_EQ(ResExpr, AppendExpr);
+ AppendToArgExpr = DIExpression::appendOpsToArg(Expr, AppendOps, 0, false);
+ EXPECT_EQ(ResExpr, AppendToArgExpr);
// Test appending a {dwarf::DW_OP_constu, 0, DW_OP_shl} to an expression
AppendOps.clear();
@@ -3708,6 +3717,8 @@ TEST_F(DIExpressionTest, Append) {
OpsRes.push_back(2);
ResExpr = DIExpression::get(Context, OpsRes);
EXPECT_EQ(ResExpr, AppendExpr);
+ AppendToArgExpr = DIExpression::appendOpsToArg(Expr, AppendOps, 0, false);
+ EXPECT_EQ(ResExpr, AppendToArgExpr);
// Test appending a {dwarf::DW_OP_constu, 0, DW_OP_shr} to an expression
AppendOps.clear();
@@ -3722,6 +3733,8 @@ TEST_F(DIExpressionTest, Append) {
OpsRes.push_back(2);
ResExpr = DIExpression::get(Context, OpsRes);
EXPECT_EQ(ResExpr, AppendExpr);
+ AppendToArgExpr = DIExpression::appendOpsToArg(Expr, AppendOps, 0, false);
+ EXPECT_EQ(ResExpr, AppendToArgExpr);
// Test appending a {dwarf::DW_OP_constu, <const>, DW_OP_mul} to a DW_OP_mul
// expression
@@ -3745,6 +3758,8 @@ TEST_F(DIExpressionTest, Append) {
OpsRes.push_back(dwarf::DW_OP_mul);
ResExpr = DIExpression::get(Context, OpsRes);
EXPECT_EQ(ResExpr, AppendExpr);
+ AppendToArgExpr = DIExpression::appendOpsToArg(Expr, AppendOps, 0, false);
+ EXPECT_EQ(ResExpr, AppendToArgExpr);
// Test appending a {dwarf::DW_OP_constu, 1, DW_OP_mul} to an expression
AppendOps.clear();
@@ -3760,6 +3775,8 @@ TEST_F(DIExpressionTest, Append) {
OpsRes.push_back(dwarf::DW_OP_mul);
ResExpr = DIExpression::get(Context, OpsRes);
EXPECT_EQ(ResExpr, AppendExpr);
+ AppendToArgExpr = DIExpression::appendOpsToArg(Expr, AppendOps, 0, false);
+ EXPECT_EQ(ResExpr, AppendToArgExpr);
// Test appending a {dwarf::DW_OP_constu, 1, DW_OP_div} to an expression
AppendOps.clear();
@@ -3775,6 +3792,8 @@ TEST_F(DIExpressionTest, Append) {
OpsRes.push_back(dwarf::DW_OP_mul);
ResExpr = DIExpression::get(Context, OpsRes);
EXPECT_EQ(ResExpr, AppendExpr);
+ AppendToArgExpr = DIExpression::appendOpsToArg(Expr, AppendOps, 0, false);
+ EXPECT_EQ(ResExpr, AppendToArgExpr);
}
TEST_F(DIExpressionTest, isValid) {
diff --git a/llvm/unittests/Transforms/Utils/LocalTest.cpp b/llvm/unittests/Transforms/Utils/LocalTest.cpp
index a86775a1366b05..0b4f9d2a66c006 100644
--- a/llvm/unittests/Transforms/Utils/LocalTest.cpp
+++ b/llvm/unittests/Transforms/Utils/LocalTest.cpp
@@ -544,8 +544,7 @@ struct SalvageDebugInfoTest : ::testing::Test {
const auto &CI = *cast<ConstantInt>(DI.getVariableLocationOp(0));
if (CI.isZero())
return DI.getExpression()->getElements().equals(
- {dwarf::DW_OP_plus_uconst, 1, dwarf::DW_OP_plus_uconst, 2,
- dwarf::DW_OP_stack_value});
+ {dwarf::DW_OP_plus_uconst, 3, dwarf::DW_OP_stack_value});
else if (CI.isOneValue())
return DI.getExpression()->getElements().equals(
{dwarf::DW_OP_plus_uconst, 2, dwarf::DW_OP_stack_value});
More information about the llvm-commits
mailing list