[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