[llvm-branch-commits] [flang] 352b872 - Add list input test to GTest suite

2021-04-05 Thread Asher Mancinelli via llvm-branch-commits

Author: Asher Mancinelli
Date: 2021-03-30T11:16:23-07:00
New Revision: 352b872f8f717a98328eb48b57f0a4d83c686d9f

URL: 
https://github.com/llvm/llvm-project/commit/352b872f8f717a98328eb48b57f0a4d83c686d9f
DIFF: 
https://github.com/llvm/llvm-project/commit/352b872f8f717a98328eb48b57f0a4d83c686d9f.diff

LOG: Add list input test to GTest suite

Added: 
flang/unittests/RuntimeGTest/ListInputTest.cpp

Modified: 
flang/unittests/RuntimeGTest/CMakeLists.txt

Removed: 




diff  --git a/flang/unittests/RuntimeGTest/CMakeLists.txt 
b/flang/unittests/RuntimeGTest/CMakeLists.txt
index d4ad6b2e15201..3e48b67f5a098 100644
--- a/flang/unittests/RuntimeGTest/CMakeLists.txt
+++ b/flang/unittests/RuntimeGTest/CMakeLists.txt
@@ -5,6 +5,7 @@ add_flang_unittest(FlangRuntimeTests
   NumericalFormatTest.cpp
   RuntimeCrashTest.cpp
   CrashHandlerFixture.cpp
+  ListInputTest.cpp
 )
 
 target_link_libraries(FlangRuntimeTests

diff  --git a/flang/unittests/RuntimeGTest/ListInputTest.cpp 
b/flang/unittests/RuntimeGTest/ListInputTest.cpp
new file mode 100644
index 0..f1f62197ae07e
--- /dev/null
+++ b/flang/unittests/RuntimeGTest/ListInputTest.cpp
@@ -0,0 +1,76 @@
+//===-- flang/unittests/RuntimeGTest/ListInputTest.cpp --*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+
+#include "CrashHandlerFixture.h"
+#include "../../runtime/descriptor.h"
+#include "../../runtime/io-api.h"
+#include "../../runtime/io-error.h"
+
+using namespace Fortran::runtime;
+using namespace Fortran::runtime::io;
+
+// Pads characters with whitespace when needed
+void SetCharacter(char *to, std::size_t n, const char *from) {
+  auto len{std::strlen(from)};
+  std::memcpy(to, from, std::min(len, n));
+  if (len < n) {
+std::memset(to + len, ' ', n - len);
+  }
+}
+
+struct InputTest : CrashHandlerFixture {};
+
+TEST(InputTest, TestListInput) {
+  static constexpr int numBuffers{4};
+  static constexpr int maxBufferLength{32};
+  static char buffer[numBuffers][maxBufferLength];
+  int j{0};
+  for (const char *p : {"1 2 2*3  ,", ",6,,8,1*",
+   "2*'abcdefghijklmnopqrstuvwxyzABC", "DEFGHIJKLMNOPQRSTUVWXYZ'"}) {
+SetCharacter(buffer[j++], maxBufferLength, p);
+  }
+
+  static StaticDescriptor<1> staticDescriptor;
+  static Descriptor &whole{staticDescriptor.descriptor()};
+  static SubscriptValue extent[]{numBuffers};
+  whole.Establish(TypeCode{CFI_type_char}, maxBufferLength, &buffer, 1, extent,
+  CFI_attribute_pointer);
+  whole.Dump();
+  whole.Check();
+
+  static auto cookie{IONAME(BeginInternalArrayListInput)(whole)};
+  static constexpr int listInputLength{9};
+  static std::int64_t n[listInputLength]{-1, -2, -3, -4, 5, -6, 7, -8, 9};
+  static const std::int64_t want[listInputLength]{1, 2, 3, 3, 5, 6, 7, 8, 9};
+  for (j = 0; j < listInputLength; ++j) {
+IONAME(InputInteger)(cookie, n[j]);
+  }
+
+  static constexpr int numInputBuffers{2};
+  static constexpr int inputBufferLength{54};
+  static char inputBuffers[numInputBuffers][inputBufferLength]{};
+  IONAME(InputAscii)(cookie, inputBuffers[0], inputBufferLength - 1);
+  IONAME(InputAscii)(cookie, inputBuffers[1], inputBufferLength - 1);
+
+  static const auto status{IONAME(EndIoStatement)(cookie)};
+  ASSERT_EQ(status, 0) << "list-directed input failed, status "
+ << static_cast(status) << '\n';
+
+  for (j = 0; j < listInputLength; ++j) {
+ASSERT_EQ(n[j], want[j])
+<< "wanted n[" << j << "]==" << want[j] << ", got " << n[j] << '\n';
+  }
+
+  for (j = 0; j < numInputBuffers; ++j) {
+ASSERT_EQ(std::strcmp(inputBuffers[j],
+  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ "),
+0)
+<< "wanted asc[" << j << "]=alphabets, got '" << inputBuffers[j] << 
"'\n";
+  }
+}
+



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [flang] ee822a6 - Remove legacy list-input test

2021-04-05 Thread Asher Mancinelli via llvm-branch-commits

Author: Asher Mancinelli
Date: 2021-03-30T11:25:42-07:00
New Revision: ee822a6bda40f6b17ba7b4c6d414827c665c9480

URL: 
https://github.com/llvm/llvm-project/commit/ee822a6bda40f6b17ba7b4c6d414827c665c9480
DIFF: 
https://github.com/llvm/llvm-project/commit/ee822a6bda40f6b17ba7b4c6d414827c665c9480.diff

LOG: Remove legacy list-input test

Added: 


Modified: 
flang/unittests/Runtime/CMakeLists.txt

Removed: 
flang/unittests/Runtime/list-input.cpp



diff  --git a/flang/unittests/Runtime/CMakeLists.txt 
b/flang/unittests/Runtime/CMakeLists.txt
index cc7ac72771839..03998fa55d143 100644
--- a/flang/unittests/Runtime/CMakeLists.txt
+++ b/flang/unittests/Runtime/CMakeLists.txt
@@ -37,11 +37,6 @@ add_flang_nongtest_unittest(external-io
   FortranRuntime
 )
 
-add_flang_nongtest_unittest(list-input
-  RuntimeTesting
-  FortranRuntime
-)
-
 add_flang_nongtest_unittest(buffer
   RuntimeTesting
   FortranRuntime

diff  --git a/flang/unittests/Runtime/list-input.cpp 
b/flang/unittests/Runtime/list-input.cpp
deleted file mode 100644
index 9ec77080203a2..0
--- a/flang/unittests/Runtime/list-input.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-// Basic sanity tests for list-directed input
-
-#include "testing.h"
-#include "../../runtime/descriptor.h"
-#include "../../runtime/io-api.h"
-#include "../../runtime/io-error.h"
-#include 
-#include 
-
-using namespace Fortran::runtime;
-using namespace Fortran::runtime::io;
-
-int main() {
-  StartTests();
-
-  char buffer[4][32];
-  int j{0};
-  for (const char *p : {"1 2 2*3  ,", ",6,,8,1*",
-   "2*'abcdefghijklmnopqrstuvwxyzABC", "DEFGHIJKLMNOPQRSTUVWXYZ'"}) {
-SetCharacter(buffer[j++], sizeof buffer[0], p);
-  }
-  for (; j < 4; ++j) {
-SetCharacter(buffer[j], sizeof buffer[0], "");
-  }
-
-  StaticDescriptor<1> staticDescriptor;
-  Descriptor &whole{staticDescriptor.descriptor()};
-  SubscriptValue extent[]{4};
-  whole.Establish(TypeCode{CFI_type_char}, sizeof buffer[0], &buffer, 1, 
extent,
-  CFI_attribute_pointer);
-  whole.Dump();
-  whole.Check();
-
-  try {
-auto cookie{IONAME(BeginInternalArrayListInput)(whole)};
-std::int64_t n[9]{-1, -2, -3, -4, 5, -6, 7, -8, 9};
-std::int64_t want[9]{1, 2, 3, 3, 5, 6, 7, 8, 9};
-for (j = 0; j < 9; ++j) {
-  IONAME(InputInteger)(cookie, n[j]);
-}
-char asc[2][54]{};
-IONAME(InputAscii)(cookie, asc[0], sizeof asc[0] - 1);
-IONAME(InputAscii)(cookie, asc[1], sizeof asc[1] - 1);
-if (auto status{IONAME(EndIoStatement)(cookie)}) {
-  Fail() << "list-directed input failed, status "
- << static_cast(status) << '\n';
-} else {
-  for (j = 0; j < 9; ++j) {
-if (n[j] != want[j]) {
-  Fail() << "wanted n[" << j << "]==" << want[j] << ", got " << n[j]
- << '\n';
-}
-  }
-  for (j = 0; j < 2; ++j) {
-if (std::strcmp(asc[j],
-"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ") != 0) 
{
-  Fail() << "wanted asc[" << j << "]=alphabets, got '" << asc[j]
- << "'\n";
-}
-  }
-}
-  } catch (const std::string &crash) {
-Fail() << "crash: " << crash << '\n';
-  }
-
-  return EndTests();
-}



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [flang] bc26c5f - Clang-format list input test

2021-04-05 Thread Asher Mancinelli via llvm-branch-commits

Author: Asher Mancinelli
Date: 2021-03-30T11:31:39-07:00
New Revision: bc26c5fb2a5601971691a69c6d8bf9f7b5cd7326

URL: 
https://github.com/llvm/llvm-project/commit/bc26c5fb2a5601971691a69c6d8bf9f7b5cd7326
DIFF: 
https://github.com/llvm/llvm-project/commit/bc26c5fb2a5601971691a69c6d8bf9f7b5cd7326.diff

LOG: Clang-format list input test

Added: 


Modified: 
flang/unittests/RuntimeGTest/ListInputTest.cpp

Removed: 




diff  --git a/flang/unittests/RuntimeGTest/ListInputTest.cpp 
b/flang/unittests/RuntimeGTest/ListInputTest.cpp
index f1f62197ae07e..5d693d77f2114 100644
--- a/flang/unittests/RuntimeGTest/ListInputTest.cpp
+++ b/flang/unittests/RuntimeGTest/ListInputTest.cpp
@@ -59,7 +59,7 @@ TEST(InputTest, TestListInput) {
 
   static const auto status{IONAME(EndIoStatement)(cookie)};
   ASSERT_EQ(status, 0) << "list-directed input failed, status "
- << static_cast(status) << '\n';
+   << static_cast(status) << '\n';
 
   for (j = 0; j < listInputLength; ++j) {
 ASSERT_EQ(n[j], want[j])
@@ -70,7 +70,7 @@ TEST(InputTest, TestListInput) {
 ASSERT_EQ(std::strcmp(inputBuffers[j],
   "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ "),
 0)
-<< "wanted asc[" << j << "]=alphabets, got '" << inputBuffers[j] << 
"'\n";
+<< "wanted asc[" << j << "]=alphabets, got '" << inputBuffers[j]
+<< "'\n";
   }
 }
-



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [flang] 679fe69 - Apply first pass at diag handler structure

2021-04-05 Thread Asher Mancinelli via llvm-branch-commits

Author: Asher Mancinelli
Date: 2021-04-05T09:00:33-07:00
New Revision: 679fe69e92f192ef8d3b014dcf7e1624e16c9c77

URL: 
https://github.com/llvm/llvm-project/commit/679fe69e92f192ef8d3b014dcf7e1624e16c9c77
DIFF: 
https://github.com/llvm/llvm-project/commit/679fe69e92f192ef8d3b014dcf7e1624e16c9c77.diff

LOG: Apply first pass at diag handler structure

Added: 
flang/include/flang/Common/colors.h
flang/include/flang/Parser/diagnostics-engine.h

Modified: 
flang/include/flang/Parser/message.h
flang/lib/Parser/message.cpp

Removed: 




diff  --git a/flang/include/flang/Common/colors.h 
b/flang/include/flang/Common/colors.h
new file mode 100644
index 0..feb259c22c674
--- /dev/null
+++ b/flang/include/flang/Common/colors.h
@@ -0,0 +1,34 @@
+//===-- include/flang/Parser/colors.h ---*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+//
+// Defines colors used for diagnostics.
+//
+//===--===//
+
+#ifndef FORTRAN_PARSER_COLORS_H_
+#define FORTRAN_PARSER_COLORS_H_
+
+#include "llvm/Support/raw_ostream.h"
+
+namespace Fortran::common {
+
+static constexpr enum llvm::raw_ostream::Colors noteColor =
+llvm::raw_ostream::BLACK;
+static constexpr enum llvm::raw_ostream::Colors remarkColor =
+llvm::raw_ostream::BLUE;
+static constexpr enum llvm::raw_ostream::Colors warningColor =
+llvm::raw_ostream::MAGENTA;
+static constexpr enum llvm::raw_ostream::Colors errorColor = 
llvm::raw_ostream::RED;
+static constexpr enum llvm::raw_ostream::Colors fatalColor = 
llvm::raw_ostream::RED;
+// Used for changing only the bold attribute.
+static constexpr enum llvm::raw_ostream::Colors savedColor =
+llvm::raw_ostream::SAVEDCOLOR;
+
+} // namespace Fortran::common
+
+#endif
\ No newline at end of file

diff  --git a/flang/include/flang/Parser/diagnostics-engine.h 
b/flang/include/flang/Parser/diagnostics-engine.h
new file mode 100644
index 0..beb03d77aeeb0
--- /dev/null
+++ b/flang/include/flang/Parser/diagnostics-engine.h
@@ -0,0 +1,20 @@
+//===-- include/flang/Parser/characters.h ---*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+
+#ifndef FORTRAN_PARSER_CHARACTERS_H_
+#define FORTRAN_PARSER_CHARACTERS_H_
+
+namespace Fortran::parser {
+
+class DiagnosticsEngine {
+
+};
+
+} // namespace Fortran::parser
+
+#endif
\ No newline at end of file

diff  --git a/flang/include/flang/Parser/message.h 
b/flang/include/flang/Parser/message.h
index 13f30879dc4fb..fbba0b922e018 100644
--- a/flang/include/flang/Parser/message.h
+++ b/flang/include/flang/Parser/message.h
@@ -29,34 +29,46 @@
 
 namespace Fortran::parser {
 
+enum class DiagnosticLevel {
+  Note=0,
+  Remark,
+  Warning,
+  Error,
+  Fatal,
+};
+
 // Use "..."_err_en_US and "..."_en_US literals to define the static
 // text and fatality of a message.
 class MessageFixedText {
 public:
   constexpr MessageFixedText(
-  const char str[], std::size_t n, bool isFatal = false)
-  : text_{str, n}, isFatal_{isFatal} {}
+  const char str[], std::size_t n, DiagnosticLevel diagnosticLevel = 
DiagnosticLevel::Remark)
+  : text_{str, n}, diagnosticLevel_{diagnosticLevel} {}
+  constexpr MessageFixedText(
+  const char str[], std::size_t n, bool isFatal)
+  : text_{str, n}, diagnosticLevel_{isFatal ? DiagnosticLevel::Fatal : 
DiagnosticLevel::Remark} {}
   constexpr MessageFixedText(const MessageFixedText &) = default;
   constexpr MessageFixedText(MessageFixedText &&) = default;
   constexpr MessageFixedText &operator=(const MessageFixedText &) = default;
   constexpr MessageFixedText &operator=(MessageFixedText &&) = default;
 
   CharBlock text() const { return text_; }
-  bool isFatal() const { return isFatal_; }
+  bool isFatal() const { return diagnosticLevel_ == DiagnosticLevel::Fatal; }
+  DiagnosticLevel GetDiagnosticLevel() const { return diagnosticLevel_; }
 
 private:
   CharBlock text_;
-  bool isFatal_{false};
+  DiagnosticLevel diagnosticLevel_{DiagnosticLevel::Remark};
 };
 
 inline namespace literals {
 constexpr MessageFixedText operator""_en_US(const char str[], std::size_t n) {
-  return MessageFixedText{str, n, false /* not fatal */};
+  return MessageFixedText{str, n, DiagnosticLevel::Remark};
 }
 
 constexpr MessageFixedText operator""_err_en_US(
 const char str[], std::size_t n) 

[llvm-branch-commits] [flang] [flang] translate derived type array init to attribute if possible (PR #140268)

2025-05-16 Thread Asher Mancinelli via llvm-branch-commits


@@ -0,0 +1,204 @@
+//===-- LLVMInsertChainFolder.cpp 
-===//
+//
+// 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
+//
+//===--===//
+
+#include "flang/Optimizer/CodeGen/LLVMInsertChainFolder.h"
+#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/IR/Builders.h"
+#include "llvm/Support/Debug.h"
+
+#define DEBUG_TYPE "flang-insert-folder"
+
+#include 
+
+namespace {
+// Helper class to construct the attribute elements of an aggregate value being
+// folded without creating a full mlir::Attribute representation for each step
+// of the insert value chain, which would both be expensive in terms of
+// compilation time and memory (since the intermediate Attribute would survive,
+// unused, inside the mlir context).
+class InsertChainBackwardFolder {
+  // Type for the current value of an element of the aggregate value being
+  // constructed by the insert chain.
+  // At any point of the insert chain, the value of an element is either:
+  //  - nullptr: not yet known, the insert has not yet been seen.
+  //  - an mlir::Attribute: the element is fully defined.
+  //  - a nested InsertChainBackwardFolder: the element is itself an aggregate
+  //and its sub-elements have been partially defined (insert with mutliple
+  //indices have been seen).
+
+  // The insertion folder assumes backward walk of the insert chain. Once an
+  // element or sub-element has been defined, it is not overriden by new
+  // insertions (last insert wins).
+  using InFlightValue =
+  llvm::PointerUnion;
+
+public:
+  InsertChainBackwardFolder(
+  mlir::Type type, std::deque *folderStorage)
+  : values(getNumElements(type), mlir::Attribute{}),
+folderStorage{folderStorage}, type{type} {}
+
+  /// Push
+  bool pushValue(mlir::Attribute val, llvm::ArrayRef at);
+
+  mlir::Attribute finalize(mlir::Attribute defaultFieldValue);
+
+private:
+  static int64_t getNumElements(mlir::Type type) {
+if (auto structTy =
+llvm::dyn_cast_if_present(type))
+  return structTy.getBody().size();
+if (auto arrayTy =
+llvm::dyn_cast_if_present(type))
+  return arrayTy.getNumElements();
+return 0;
+  }
+
+  static mlir::Type getSubElementType(mlir::Type type, int64_t field) {
+if (auto arrayTy =
+llvm::dyn_cast_if_present(type))
+  return arrayTy.getElementType();
+if (auto structTy =
+llvm::dyn_cast_if_present(type))
+  return structTy.getBody()[field];
+return {};
+  }
+
+  // Current element value of the aggregate value being built.
+  llvm::SmallVector values;
+  // std::deque is used to allocate storage for nested list and guarantee the
+  // stability of the InsertChainBackwardFolder* used as element value.
+  std::deque *folderStorage;
+  // Type of the aggregate value being built.
+  mlir::Type type;
+};
+} // namespace
+
+// Helper to fold the value being inserted by an llvm.insert_value.
+// This may call tryFoldingLLVMInsertChain if the value is an aggregate and
+// was itself constructed by a different insert chain.
+static mlir::Attribute getAttrIfConstant(mlir::Value val,
+ mlir::OpBuilder &rewriter) {
+  if (auto cst = val.getDefiningOp())
+return cst.getValue();
+  if (auto insert = val.getDefiningOp())
+return fir::tryFoldingLLVMInsertChain(val, rewriter);
+  if (val.getDefiningOp())
+return mlir::LLVM::ZeroAttr::get(val.getContext());
+  if (val.getDefiningOp())
+return mlir::LLVM::UndefAttr::get(val.getContext());
+  if (mlir::Operation *op = val.getDefiningOp()) {
+unsigned resNum = llvm::cast(val).getResultNumber();
+llvm::SmallVector results;
+if (mlir::succeeded(rewriter.tryFold(op, results)) &&
+results.size() > resNum) {
+  if (auto cst = results[resNum].getDefiningOp())
+return cst.getValue();
+}
+  }
+  if (auto trunc = val.getDefiningOp())
+if (auto attr = getAttrIfConstant(trunc.getArg(), rewriter))
+  if (auto intAttr = llvm::dyn_cast(attr))
+return mlir::IntegerAttr::get(trunc.getType(), intAttr.getInt());
+  LLVM_DEBUG(llvm::dbgs() << "cannot fold insert value operand: " << val
+  << "\n");
+  return {};
+}
+
+mlir::Attribute
+InsertChainBackwardFolder::finalize(mlir::Attribute defaultFieldValue) {
+  std::vector attrs;
+  attrs.reserve(values.size());
+  for (InFlightValue &inFlight : values) {
+if (!inFlight) {
+  attrs.push_back(defaultFieldValue);
+} else if (auto attr = llvm::dyn_cast(inFlight)) {
+  attrs.push_back(attr);
+} else {
+  auto *inFlightList = llvm::cast(inFlight);
+  attrs.push_back(inFlightList->finalize(defaul

[llvm-branch-commits] [flang] [flang] translate derived type array init to attribute if possible (PR #140268)

2025-05-16 Thread Asher Mancinelli via llvm-branch-commits

https://github.com/ashermancinelli edited 
https://github.com/llvm/llvm-project/pull/140268
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [flang] [flang] translate derived type array init to attribute if possible (PR #140268)

2025-05-16 Thread Asher Mancinelli via llvm-branch-commits


@@ -0,0 +1,204 @@
+//===-- LLVMInsertChainFolder.cpp 
-===//
+//
+// 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
+//
+//===--===//
+
+#include "flang/Optimizer/CodeGen/LLVMInsertChainFolder.h"
+#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/IR/Builders.h"
+#include "llvm/Support/Debug.h"
+
+#define DEBUG_TYPE "flang-insert-folder"
+
+#include 
+
+namespace {
+// Helper class to construct the attribute elements of an aggregate value being
+// folded without creating a full mlir::Attribute representation for each step
+// of the insert value chain, which would both be expensive in terms of
+// compilation time and memory (since the intermediate Attribute would survive,
+// unused, inside the mlir context).
+class InsertChainBackwardFolder {
+  // Type for the current value of an element of the aggregate value being
+  // constructed by the insert chain.
+  // At any point of the insert chain, the value of an element is either:
+  //  - nullptr: not yet known, the insert has not yet been seen.
+  //  - an mlir::Attribute: the element is fully defined.
+  //  - a nested InsertChainBackwardFolder: the element is itself an aggregate
+  //and its sub-elements have been partially defined (insert with mutliple
+  //indices have been seen).
+
+  // The insertion folder assumes backward walk of the insert chain. Once an
+  // element or sub-element has been defined, it is not overriden by new
+  // insertions (last insert wins).
+  using InFlightValue =
+  llvm::PointerUnion;
+
+public:
+  InsertChainBackwardFolder(
+  mlir::Type type, std::deque *folderStorage)
+  : values(getNumElements(type), mlir::Attribute{}),
+folderStorage{folderStorage}, type{type} {}
+
+  /// Push
+  bool pushValue(mlir::Attribute val, llvm::ArrayRef at);
+
+  mlir::Attribute finalize(mlir::Attribute defaultFieldValue);
+
+private:
+  static int64_t getNumElements(mlir::Type type) {
+if (auto structTy =
+llvm::dyn_cast_if_present(type))
+  return structTy.getBody().size();
+if (auto arrayTy =
+llvm::dyn_cast_if_present(type))
+  return arrayTy.getNumElements();
+return 0;
+  }
+
+  static mlir::Type getSubElementType(mlir::Type type, int64_t field) {
+if (auto arrayTy =
+llvm::dyn_cast_if_present(type))
+  return arrayTy.getElementType();
+if (auto structTy =
+llvm::dyn_cast_if_present(type))
+  return structTy.getBody()[field];
+return {};
+  }
+
+  // Current element value of the aggregate value being built.
+  llvm::SmallVector values;
+  // std::deque is used to allocate storage for nested list and guarantee the
+  // stability of the InsertChainBackwardFolder* used as element value.
+  std::deque *folderStorage;
+  // Type of the aggregate value being built.
+  mlir::Type type;
+};
+} // namespace
+
+// Helper to fold the value being inserted by an llvm.insert_value.
+// This may call tryFoldingLLVMInsertChain if the value is an aggregate and
+// was itself constructed by a different insert chain.
+static mlir::Attribute getAttrIfConstant(mlir::Value val,
+ mlir::OpBuilder &rewriter) {
+  if (auto cst = val.getDefiningOp())
+return cst.getValue();
+  if (auto insert = val.getDefiningOp())
+return fir::tryFoldingLLVMInsertChain(val, rewriter);
+  if (val.getDefiningOp())
+return mlir::LLVM::ZeroAttr::get(val.getContext());
+  if (val.getDefiningOp())
+return mlir::LLVM::UndefAttr::get(val.getContext());
+  if (mlir::Operation *op = val.getDefiningOp()) {
+unsigned resNum = llvm::cast(val).getResultNumber();
+llvm::SmallVector results;
+if (mlir::succeeded(rewriter.tryFold(op, results)) &&
+results.size() > resNum) {
+  if (auto cst = results[resNum].getDefiningOp())
+return cst.getValue();
+}
+  }
+  if (auto trunc = val.getDefiningOp())
+if (auto attr = getAttrIfConstant(trunc.getArg(), rewriter))
+  if (auto intAttr = llvm::dyn_cast(attr))
+return mlir::IntegerAttr::get(trunc.getType(), intAttr.getInt());
+  LLVM_DEBUG(llvm::dbgs() << "cannot fold insert value operand: " << val
+  << "\n");
+  return {};
+}
+
+mlir::Attribute
+InsertChainBackwardFolder::finalize(mlir::Attribute defaultFieldValue) {
+  std::vector attrs;
+  attrs.reserve(values.size());
+  for (InFlightValue &inFlight : values) {
+if (!inFlight) {
+  attrs.push_back(defaultFieldValue);
+} else if (auto attr = llvm::dyn_cast(inFlight)) {
+  attrs.push_back(attr);
+} else {
+  auto *inFlightList = llvm::cast(inFlight);
+  attrs.push_back(inFlightList->finalize(defaul

[llvm-branch-commits] [flang] [flang] translate derived type array init to attribute if possible (PR #140268)

2025-05-16 Thread Asher Mancinelli via llvm-branch-commits

https://github.com/ashermancinelli approved this pull request.

Thanks, this is a really interesting fix! My review comments are just 
nits/questions.

https://github.com/llvm/llvm-project/pull/140268
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [flang] [flang] translate derived type array init to attribute if possible (PR #140268)

2025-05-16 Thread Asher Mancinelli via llvm-branch-commits


@@ -0,0 +1,204 @@
+//===-- LLVMInsertChainFolder.cpp 
-===//
+//
+// 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
+//
+//===--===//
+
+#include "flang/Optimizer/CodeGen/LLVMInsertChainFolder.h"
+#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/IR/Builders.h"
+#include "llvm/Support/Debug.h"
+
+#define DEBUG_TYPE "flang-insert-folder"
+
+#include 
+
+namespace {
+// Helper class to construct the attribute elements of an aggregate value being
+// folded without creating a full mlir::Attribute representation for each step
+// of the insert value chain, which would both be expensive in terms of
+// compilation time and memory (since the intermediate Attribute would survive,
+// unused, inside the mlir context).
+class InsertChainBackwardFolder {
+  // Type for the current value of an element of the aggregate value being
+  // constructed by the insert chain.
+  // At any point of the insert chain, the value of an element is either:
+  //  - nullptr: not yet known, the insert has not yet been seen.
+  //  - an mlir::Attribute: the element is fully defined.
+  //  - a nested InsertChainBackwardFolder: the element is itself an aggregate
+  //and its sub-elements have been partially defined (insert with mutliple
+  //indices have been seen).
+
+  // The insertion folder assumes backward walk of the insert chain. Once an
+  // element or sub-element has been defined, it is not overriden by new
+  // insertions (last insert wins).
+  using InFlightValue =
+  llvm::PointerUnion;
+
+public:
+  InsertChainBackwardFolder(
+  mlir::Type type, std::deque *folderStorage)
+  : values(getNumElements(type), mlir::Attribute{}),
+folderStorage{folderStorage}, type{type} {}
+
+  /// Push
+  bool pushValue(mlir::Attribute val, llvm::ArrayRef at);
+
+  mlir::Attribute finalize(mlir::Attribute defaultFieldValue);
+
+private:
+  static int64_t getNumElements(mlir::Type type) {
+if (auto structTy =
+llvm::dyn_cast_if_present(type))
+  return structTy.getBody().size();
+if (auto arrayTy =
+llvm::dyn_cast_if_present(type))
+  return arrayTy.getNumElements();
+return 0;
+  }
+
+  static mlir::Type getSubElementType(mlir::Type type, int64_t field) {
+if (auto arrayTy =
+llvm::dyn_cast_if_present(type))
+  return arrayTy.getElementType();
+if (auto structTy =
+llvm::dyn_cast_if_present(type))
+  return structTy.getBody()[field];
+return {};
+  }

ashermancinelli wrote:

What does a default-constructed `mlir::Type` indicate here?

https://github.com/llvm/llvm-project/pull/140268
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits