[llvm] Introduce DIExpression::foldConstantMath() (PR #71718)
Adrian Prantl via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 10 17:55:12 PST 2023
================
@@ -1998,6 +1997,286 @@ DIExpression::constantFold(const ConstantInt *CI) {
ConstantInt::get(getContext(), NewInt)};
}
+static bool isConstOperation(uint64_t Op) {
+ return Op == dwarf::DW_OP_constu || Op == dwarf::DW_OP_consts;
+}
+
+static bool operationIsNoOp(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;
+ }
+}
+
+static std::optional<uint64_t>
+foldOperationIfPossible(uint64_t Op, uint64_t Operand1, uint64_t Operand2) {
+ switch (Op) {
+ case dwarf::DW_OP_plus:
+ return Operand1 + Operand2;
+ case dwarf::DW_OP_minus:
+ return Operand1 - Operand2;
+ case dwarf::DW_OP_shl:
+ return Operand1 << Operand2;
+ case dwarf::DW_OP_shr:
+ return Operand1 >> Operand2;
+ case dwarf::DW_OP_mul:
+ return Operand1 * Operand2;
+ case dwarf::DW_OP_div:
+ return Operand1 / Operand2;
+ default:
+ return std::nullopt;
+ }
+}
+
+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;
+ }
+}
+
+static void moveCursorAndLocPos(DIExpressionCursor &Cursor, uint64_t &Loc,
+ const DIExpression::ExprOperand &Op) {
+ Cursor.consume(1);
+ Loc = Loc + Op.getSize();
+}
+
+DIExpression *DIExpression::foldConstantMath() {
+
+ SmallVector<uint64_t, 8> WorkingOps;
+ WorkingOps.append(Elements.begin(), Elements.end());
+ uint64_t Loc = 0;
+ DIExpressionCursor Cursor(WorkingOps);
+
+ 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);
+
+ // {DW_OP_plus_uconst, 0} -> {}
+ if (Op1Raw == dwarf::DW_OP_plus_uconst && Op1Arg == 0) {
+ WorkingOps.erase(WorkingOps.begin() + Loc, WorkingOps.begin() + Loc + 2);
+ moveCursorAndLocPos(Cursor, Loc, *Op1);
+ continue;
+ }
+
+ if (!isConstOperation(Op1Raw) && Op1Raw != dwarf::DW_OP_plus_uconst) {
+ // Early exit, all of the following patterns start with a constant value
+ moveCursorAndLocPos(Cursor, Loc, *Op1);
+ continue;
+ }
+
+ auto Op2 = Cursor.peekNext();
+ // All following patterns require at least 2 Operations, exit
+ if (!Op2)
+ break;
+ auto Op2Raw = Op2->getOp();
+
+ // {DW_OP_const[u, s], 0, DW_OP_[plus, minus, shl, shr]} -> {}
+ // {DW_OP_const[u, s], 1, DW_OP_[mul, div]} -> {}
+ if (isConstOperation(Op1Raw) && operationIsNoOp(Op2Raw, Op1Arg)) {
----------------
adrian-prantl wrote:
I think the proper alegbraic term for IsNoOp is "isNeutralElement"?
https://github.com/llvm/llvm-project/pull/71718
More information about the llvm-commits
mailing list