[llvm] Use DIExpression::foldConstantMath at the result of a Salvaged expression (PR #71721)
Shubham Sandeep Rastogi via llvm-commits
llvm-commits at lists.llvm.org
Thu May 23 14:42:19 PDT 2024
================
@@ -0,0 +1,349 @@
+//===- DIExpressionOptimizer.cpp - Constant folding of DIExpressions ------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements functions to constant fold DIExpressions. Which were
+// declared in DIExpressionOptimizer.h
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/IR/DebugInfoMetadata.h"
+
+using namespace llvm;
+
+static std::optional<uint64_t> isConstantVal(DIExpression::ExprOperand Op) {
+ if (Op.getOp() == dwarf::DW_OP_constu)
+ return Op.getArg(0);
+ return std::nullopt;
+}
+
+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;
+ }
+}
+
+static std::optional<uint64_t> foldOperationIfPossible(
+ DIExpression::ExprOperand Op1, DIExpression::ExprOperand Op2,
+ DIExpression::ExprOperand Op3, bool &ConstantValCheckFailed) {
+
+ auto Operand1 = isConstantVal(Op1);
+ auto Operand2 = isConstantVal(Op2);
+
+ if (!Operand1 || !Operand2) {
+ ConstantValCheckFailed = true;
+ return std::nullopt;
+ }
+
+ auto Oper1 = *Operand1;
+ auto Oper2 = *Operand2;
+
+ bool ResultOverflowed;
+ switch (Op3.getOp()) {
+ case dwarf::DW_OP_plus: {
+ auto Result = SaturatingAdd(Oper1, Oper2, &ResultOverflowed);
+ if (ResultOverflowed)
+ return std::nullopt;
+ return Result;
+ }
+ case dwarf::DW_OP_minus: {
+ if (Oper1 < Oper2)
+ return std::nullopt;
+ return Oper1 - Oper2;
+ }
+ case dwarf::DW_OP_shl: {
+ if ((uint64_t)countl_zero(Oper1) < Oper2)
+ return std::nullopt;
+ return Oper1 << Oper2;
+ }
+ case dwarf::DW_OP_shr: {
+ if ((uint64_t)countr_zero(Oper1) < Oper2)
+ return std::nullopt;
+ return Oper1 >> Oper2;
+ }
+ case dwarf::DW_OP_mul: {
+ auto Result = SaturatingMultiply(Oper1, Oper2, &ResultOverflowed);
+ if (ResultOverflowed)
+ return std::nullopt;
+ return Result;
+ }
+ case dwarf::DW_OP_div: {
+ if (Oper2)
+ return Oper1 / Oper2;
+ return std::nullopt;
+ }
+ default:
+ return std::nullopt;
+ }
+}
+
+static bool operationsAreFoldableAndCommutative(uint64_t Op1, uint64_t Op2) {
+ return Op1 == Op2 && (Op1 == dwarf::DW_OP_plus || Op1 == dwarf::DW_OP_mul);
+}
+
+static void consumeOneOperator(DIExpressionCursor &Cursor, uint64_t &Loc,
+ const DIExpression::ExprOperand &Op) {
+ Cursor.consume(1);
+ Loc = Loc + Op.getSize();
+}
+
+void startFromBeginning(uint64_t &Loc, DIExpressionCursor &Cursor,
+ ArrayRef<uint64_t> WorkingOps) {
+ Cursor.assignNewExpr(WorkingOps);
+ Loc = 0;
+}
+
+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);
----------------
rastogishubham wrote:
That is a great catch! Thank you so much!
https://github.com/llvm/llvm-project/pull/71721
More information about the llvm-commits
mailing list