[flang-commits] [flang] [flang] handle passing bind(c) derived type by value for ppc64le and powerpc64-aix (PR #128780)

Kelvin Li via flang-commits flang-commits at lists.llvm.org
Wed Feb 26 07:13:40 PST 2025


https://github.com/kkwli updated https://github.com/llvm/llvm-project/pull/128780

>From d918a943a41b9284127ab31ce9cd4ea7e7f6f480 Mon Sep 17 00:00:00 2001
From: Kelvin Li <kli at ca.ibm.com>
Date: Thu, 11 Apr 2024 11:19:50 -0400
Subject: [PATCH 1/2] [flang] handle passing bind(c) derived type by value for
 ppc64le and powerpc64-aix

---
 flang/lib/Optimizer/CodeGen/Target.cpp        | 162 +++++++++++++++++-
 .../struct-passing-powerpc64-aix-byval.fir    |  25 +++
 .../test/Fir/struct-passing-ppc64le-byval.fir |  79 +++++++++
 .../test/Fir/struct-return-powerpc64-aix.fir  | 109 ++++++++++++
 flang/test/Fir/struct-return-ppc64le.fir      | 107 ++++++++++++
 5 files changed, 481 insertions(+), 1 deletion(-)
 create mode 100644 flang/test/Fir/struct-passing-powerpc64-aix-byval.fir
 create mode 100644 flang/test/Fir/struct-passing-ppc64le-byval.fir
 create mode 100644 flang/test/Fir/struct-return-powerpc64-aix.fir
 create mode 100644 flang/test/Fir/struct-return-ppc64le.fir

diff --git a/flang/lib/Optimizer/CodeGen/Target.cpp b/flang/lib/Optimizer/CodeGen/Target.cpp
index 2a1eb0bc33f5c..59dfee1a9d5e2 100644
--- a/flang/lib/Optimizer/CodeGen/Target.cpp
+++ b/flang/lib/Optimizer/CodeGen/Target.cpp
@@ -1049,6 +1049,29 @@ struct TargetPPC64 : public GenericTarget<TargetPPC64> {
         AT{});
     return marshal;
   }
+
+  CodeGenSpecifics::Marshalling
+  structType(mlir::Location loc, fir::RecordType ty, bool isResult) const {
+    CodeGenSpecifics::Marshalling marshal;
+    auto sizeAndAlign{
+        fir::getTypeSizeAndAlignmentOrCrash(loc, ty, getDataLayout(), kindMap)};
+    unsigned short align{
+        std::max(sizeAndAlign.second, static_cast<unsigned short>(8))};
+    marshal.emplace_back(fir::ReferenceType::get(ty),
+                         AT{align, /*byvale*/ !isResult, /*sret*/ isResult});
+    return marshal;
+  }
+
+  CodeGenSpecifics::Marshalling
+  structArgumentType(mlir::Location loc, fir::RecordType ty,
+                     const Marshalling &previousArguments) const override {
+    return structType(loc, ty, false);
+  }
+
+  CodeGenSpecifics::Marshalling
+  structReturnType(mlir::Location loc, fir::RecordType ty) const override {
+    return structType(loc, ty, true);
+  }
 };
 } // namespace
 
@@ -1060,7 +1083,7 @@ namespace {
 struct TargetPPC64le : public GenericTarget<TargetPPC64le> {
   using GenericTarget::GenericTarget;
 
-  static constexpr int defaultWidth = 64;
+  static constexpr int defaultWidth{64};
 
   CodeGenSpecifics::Marshalling
   complexArgumentType(mlir::Location, mlir::Type eleTy) const override {
@@ -1081,6 +1104,143 @@ struct TargetPPC64le : public GenericTarget<TargetPPC64le> {
         AT{});
     return marshal;
   }
+
+  unsigned getElemWidth(mlir::Type ty) const {
+    unsigned width{};
+    llvm::TypeSwitch<mlir::Type>(ty)
+        .template Case<mlir::ComplexType>([&](mlir::ComplexType cmplx) {
+          auto elemType{
+              mlir::dyn_cast<mlir::FloatType>(cmplx.getElementType())};
+          width = elemType.getWidth();
+        })
+        .template Case<mlir::FloatType>(
+            [&](mlir::FloatType real) { width = real.getWidth(); });
+    return width;
+  }
+
+  // Determine if all derived types components are of the same float type with
+  // the same width. Complex(4) is considered 2 floats and complex(8) 2 doubles.
+  bool hasSameFloatAndWidth(
+      fir::RecordType recTy,
+      std::pair<mlir::Type, unsigned> &firstTypeAndWidth) const {
+    for (auto comp : recTy.getTypeList()) {
+      mlir::Type compType{comp.second};
+      if (mlir::isa<fir::RecordType>(compType)) {
+        auto rc{hasSameFloatAndWidth(mlir::cast<fir::RecordType>(compType),
+                                     firstTypeAndWidth)};
+        if (!rc)
+          return false;
+      } else {
+        mlir::Type ty;
+        bool isFloatType{false};
+        if (mlir::isa<mlir::FloatType, mlir::ComplexType>(compType)) {
+          ty = compType;
+          isFloatType = true;
+        } else if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(compType)) {
+          ty = seqTy.getEleTy();
+          isFloatType = mlir::isa<mlir::FloatType, mlir::ComplexType>(ty);
+        }
+
+        if (!isFloatType) {
+          return false;
+        }
+        auto width{getElemWidth(ty)};
+        if (firstTypeAndWidth.first == nullptr) {
+          firstTypeAndWidth.first = ty;
+          firstTypeAndWidth.second = width;
+        } else if (width != firstTypeAndWidth.second) {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
+
+  CodeGenSpecifics::Marshalling
+  passOnTheStack(mlir::Location loc, mlir::Type ty, bool isResult) const {
+    CodeGenSpecifics::Marshalling marshal;
+    auto sizeAndAlign{
+        fir::getTypeSizeAndAlignmentOrCrash(loc, ty, getDataLayout(), kindMap)};
+    unsigned short align{
+        std::max(sizeAndAlign.second, static_cast<unsigned short>(8))};
+    marshal.emplace_back(fir::ReferenceType::get(ty),
+                         AT{align, /*byval=*/!isResult, /*sret=*/isResult});
+    return marshal;
+  }
+
+  CodeGenSpecifics::Marshalling
+  structType(mlir::Location loc, fir::RecordType recTy, bool isResult) const {
+    CodeGenSpecifics::Marshalling marshal;
+    auto sizeAndAlign{fir::getTypeSizeAndAlignmentOrCrash(
+        loc, recTy, getDataLayout(), kindMap)};
+    auto recordTypeSize{sizeAndAlign.first};
+    mlir::Type seqTy;
+    std::pair<mlir::Type, unsigned> firstTyAndWidth{nullptr, 0};
+
+    // If there are less than or equal to 8 floats, the structure is flatten as
+    // an array of floats.
+    constexpr uint64_t maxNoOfFloats{8};
+
+    // i64 type
+    mlir::Type elemTy{mlir::IntegerType::get(recTy.getContext(), defaultWidth)};
+    uint64_t nElem{static_cast<uint64_t>(
+        std::ceil(static_cast<float>(recordTypeSize * 8) / defaultWidth))};
+
+    // If the derived type components contains are all floats with the same
+    // width, the argument is passed as an array of floats.
+    if (hasSameFloatAndWidth(recTy, firstTyAndWidth)) {
+      uint64_t n{};
+      auto firstType{firstTyAndWidth.first};
+
+      // Type is either float or complex
+      if (auto cmplx = mlir::dyn_cast<mlir::ComplexType>(firstType)) {
+        auto fltType{mlir::dyn_cast<mlir::FloatType>(cmplx.getElementType())};
+        n = static_cast<uint64_t>(8 * recordTypeSize / fltType.getWidth());
+        if (n <= maxNoOfFloats) {
+          nElem = n;
+          elemTy = fltType;
+        }
+      } else if (mlir::isa<mlir::FloatType>(firstType)) {
+        auto elemSizeAndAlign{fir::getTypeSizeAndAlignmentOrCrash(
+            loc, firstType, getDataLayout(), kindMap)};
+        n = static_cast<uint64_t>(recordTypeSize / elemSizeAndAlign.first);
+        if (n <= maxNoOfFloats) {
+          nElem = n;
+          elemTy = firstType;
+        }
+      }
+      // Neither float nor complex
+      assert(n > 0 && "unexpected type");
+    }
+
+    // For function returns, only flattened if there are less than 8
+    // floats in total.
+    if (isResult &&
+        ((mlir::isa<mlir::FloatType>(elemTy) && nElem > maxNoOfFloats) ||
+         !mlir::isa<mlir::FloatType>(elemTy))) {
+      return passOnTheStack(loc, recTy, isResult);
+    }
+
+    seqTy = fir::SequenceType::get(nElem, elemTy);
+    marshal.emplace_back(seqTy, AT{});
+    return marshal;
+  }
+
+  CodeGenSpecifics::Marshalling
+  structArgumentType(mlir::Location loc, fir::RecordType recType,
+                     const Marshalling &previousArguments) const override {
+    auto sizeAndAlign{fir::getTypeSizeAndAlignmentOrCrash(
+        loc, recType, getDataLayout(), kindMap)};
+    if (sizeAndAlign.first > 64) {
+      return passOnTheStack(loc, recType, false);
+    }
+    return structType(loc, recType, false);
+  }
+
+  CodeGenSpecifics::Marshalling
+  structReturnType(mlir::Location loc, fir::RecordType recType) const override {
+    return structType(loc, recType, true);
+  }
 };
 } // namespace
 
diff --git a/flang/test/Fir/struct-passing-powerpc64-aix-byval.fir b/flang/test/Fir/struct-passing-powerpc64-aix-byval.fir
new file mode 100644
index 0000000000000..0fd6d836761cb
--- /dev/null
+++ b/flang/test/Fir/struct-passing-powerpc64-aix-byval.fir
@@ -0,0 +1,25 @@
+// Test powerpc64 rewrite of struct passed by value (BIND(C), VALUE derived types).
+//
+// RUN: fir-opt --target-rewrite="target=powerpc64-ibm-aix" %s | FileCheck %s
+// REQUIRES: powerpc-registered-target
+
+// character type
+func.func @csubch(%arg0: !fir.type<_QFcsubchTdt<{c:!fir.char<1>}>> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubch"} { return }
+//CHECK-LABEL: func.func @csubch(%arg0: !fir.ref<!fir.type<_QFcsubchTdt<{c:!fir.char<1>}>>> {fir.bindc_name = "arg", llvm.align = 8 : i32, llvm.byval = !fir.type<_QFcsubchTdt<{c:!fir.char<1>}>>}) attributes {fir.bindc_name = "csubch"}
+
+// integer type
+func.func @csubi1(%arg0: !fir.type<_QFcsubi1Tdt<{i:i32}>> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubi1"} { return }
+//CHECK-LABEL: func.func @csubi1(%arg0: !fir.ref<!fir.type<_QFcsubi1Tdt<{i:i32}>>> {fir.bindc_name = "arg", llvm.align = 8 : i32, llvm.byval = !fir.type<_QFcsubi1Tdt<{i:i32}>>}) attributes {fir.bindc_name = "csubi1"}
+
+// real type (scalar)
+func.func @csubr1(%arg0: !fir.type<_QFcsubr1Tdt<{r1:f32,r2:f32,r3:f32}>> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr1"} { return }
+//CHECK-LABEL: func.func @csubr1(%arg0: !fir.ref<!fir.type<_QFcsubr1Tdt<{r1:f32,r2:f32,r3:f32}>>> {fir.bindc_name = "arg", llvm.align = 8 : i32, llvm.byval = !fir.type<_QFcsubr1Tdt<{r1:f32,r2:f32,r3:f32}>>}) attributes {fir.bindc_name = "csubr1"}
+
+// real type (array)
+func.func @csubr5(%arg0: !fir.type<_QFcsubr5Tdt<{r:!fir.array<8xf32>}>> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr5"} { return }
+//CHECK-LABEL: func.func @csubr5(%arg0: !fir.ref<!fir.type<_QFcsubr5Tdt<{r:!fir.array<8xf32>}>>> {fir.bindc_name = "arg", llvm.align = 8 : i32, llvm.byval = !fir.type<_QFcsubr5Tdt<{r:!fir.array<8xf32>}>>}) attributes {fir.bindc_name = "csubr5"}
+
+// mixed types
+func.func @csub1(%arg0: !fir.type<_QFcsub1Tdt<{c:!fir.char<1>,r:f32,i:i64}>> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub1"} { return }
+//CHECK-LABEL: func.func @csub1(%arg0: !fir.ref<!fir.type<_QFcsub1Tdt<{c:!fir.char<1>,r:f32,i:i64}>>> {fir.bindc_name = "arg", llvm.align = 8 : i32, llvm.byval = !fir.type<_QFcsub1Tdt<{c:!fir.char<1>,r:f32,i:i64}>>}) attributes {fir.bindc_name = "csub1"}
+
diff --git a/flang/test/Fir/struct-passing-ppc64le-byval.fir b/flang/test/Fir/struct-passing-ppc64le-byval.fir
new file mode 100644
index 0000000000000..697f060c671f1
--- /dev/null
+++ b/flang/test/Fir/struct-passing-ppc64le-byval.fir
@@ -0,0 +1,79 @@
+// Test ppc64le rewrite of struct passed by value (BIND(C), VALUE derived types).
+//
+// RUN: fir-opt --target-rewrite="target=ppc64le-unknown-linux" %s | FileCheck %s
+// REQUIRES: powerpc-registered-target
+
+// character type
+func.func @csubch(%arg0: !fir.type<_QFcsubchTdt{c:!fir.char<1>}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubch"} { return }
+//CHECK-LABEL: func.func @csubch(%arg0: !fir.array<1xi64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubch"}
+
+// integer type
+func.func @csubi1(%arg0: !fir.type<_QFcsubi1Tdt{i:i32}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubi1"} { return }
+//CHECK-LABEL: func.func @csubi1(%arg0: !fir.array<1xi64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubi1"}
+
+// integer type with size > 64 bytes
+func.func @csubi2(%arg0: !fir.type<_QFcsubi2Tdt{i:!fir.array<17xi32>}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubi2"} { return }
+//CHECK-LABEL: func.func @csubi2(%arg0: !fir.ref<!fir.type<_QFcsubi2Tdt{i:!fir.array<17xi32>}>> {fir.bindc_name = "arg", llvm.align = 8 : i32, llvm.byval = !fir.type<_QFcsubi2Tdt{i:!fir.array<17xi32>}>}) attributes {fir.bindc_name = "csubi2"}
+
+// real type (scalar)
+func.func @csubr1(%arg0: !fir.type<_QFcsubr1Tdt{r1:f32,r2:f32,r3:f32}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr1"} { return }
+//CHECK-LABEL: func.func @csubr1(%arg0: !fir.array<3xf32> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr1"}
+
+// real type (< 8 floats and <= 64 bytes)
+func.func @csubr2(%arg0: !fir.type<_QFcsubr2Tdt{r1:f64,r2:f64,r3:f64,r4:f64,r5:f64,r6:f64,r7:f64,r8:f64}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr2"} { return }
+//CHECK-LABEL: func.func @csubr2(%arg0: !fir.array<8xf64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr2"}
+
+// real type (> 8 floats and <= 64 bytes)
+func.func @csubr3(%arg0: !fir.type<_QFcsubr3Tdt{r1:f32,r2:f32,r3:f32,r4:f32,r5:f32,r6:f32,r7:f32,r8:f32,r9:f32}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr3"} { return }
+//CHECK-LABEL: func.func @csubr3(%arg0: !fir.array<5xi64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr3"}
+
+// real type (> 8 floats and > 64 bytes)
+func.func @csubr4(%arg0: !fir.type<_QFcsubr4Tdt{r1:f32,r2:f32,r3:f32,r4:f32,r5:f32,r6:f32,r7:f32,r8:f32,r9:f32,r10:f32,r11:f32,r12:f32,r13:f32,r14:f32,r15:f32,r16:f32,r17:f32}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr4"} { return }
+//CHECK-LABEL: func.func @csubr4(%arg0: !fir.ref<!fir.type<_QFcsubr4Tdt{r1:f32,r2:f32,r3:f32,r4:f32,r5:f32,r6:f32,r7:f32,r8:f32,r9:f32,r10:f32,r11:f32,r12:f32,r13:f32,r14:f32,r15:f32,r16:f32,r17:f32}>> {fir.bindc_name = "arg", llvm.align = 8 : i32, llvm.byval = !fir.type<_QFcsubr4Tdt{r1:f32,r2:f32,r3:f32,r4:f32,r5:f32,r6:f32,r7:f32,r8:f32,r9:f32,r10:f32,r11:f32,r12:f32,r13:f32,r14:f32,r15:f32,r16:f32,r17:f32}>}) attributes {fir.bindc_name = "csubr4"}
+
+// real type (array)
+func.func @csubr5(%arg0: !fir.type<_QFcsubr5Tdt{r:!fir.array<8xf32>}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr5"} { return }
+//CHECK-LABEL: func.func @csubr5(%arg0: !fir.array<8xf32> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr5"}
+
+// real type (array componets and > 64 bytes)
+func.func @csubr6(%arg0: !fir.type<_QFcsubr6Tdt{r:!fir.array<9xf64>}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr6"} { return }
+//CHECK-LABEL: func.func @csubr6(%arg0: !fir.ref<!fir.type<_QFcsubr6Tdt{r:!fir.array<9xf64>}>> {fir.bindc_name = "arg", llvm.align = 8 : i32, llvm.byval = !fir.type<_QFcsubr6Tdt{r:!fir.array<9xf64>}>}) attributes {fir.bindc_name = "csubr6"}
+
+// real type with different kinds
+func.func @csubr7(%arg0: !fir.type<_QFcsubr7Tdt{r1:f32,r2:f64,r3:f64}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr7"} { return }
+//CHECK-LABEL: func.func @csubr7(%arg0: !fir.array<3xi64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr7"}
+
+// complex type
+func.func @csubc1(%arg0: !fir.type<_QFcsubc1Tdt{r1:complex<f32>,r2:complex<f32>}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubc1"} { return }
+//CHECK-LABEL: func.func @csubc1(%arg0: !fir.array<4xf32> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubc1"}
+
+func.func @csubc2(%arg0: !fir.type<_QFcsubc2Tdt{r1:complex<f64>,r2:complex<f64>,r3:complex<f64>,r4:complex<f64>}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubc2"} { return }
+//CHECK-LABEL: func.func @csubc2(%arg0: !fir.array<8xf64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubc2"}
+
+// complex type (> 8 floats and size < 64 bytes)
+func.func @csubc3(%arg0: !fir.type<_QFcsubc3Tdt{r:!fir.array<5xcomplex<f32>>}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubc3"} { return }
+//CHECK-LABEL: func.func @csubc3(%arg0: !fir.array<5xi64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubc3"}
+
+// complex type (size > 64 bytes)
+func.func @csubc4(%arg0: !fir.type<_QFcsubc4Tdt{r:!fir.array<9xcomplex<f32>>}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubc4"} { return }
+//CHECK-LABEL: func.func @csubc4(%arg0: !fir.ref<!fir.type<_QFcsubc4Tdt{r:!fir.array<9xcomplex<f32>>}>> {fir.bindc_name = "arg", llvm.align = 8 : i32, llvm.byval = !fir.type<_QFcsubc4Tdt{r:!fir.array<9xcomplex<f32>>}>}) attributes {fir.bindc_name = "csubc4"}
+
+// mixed type
+func.func @csub1(%arg0: !fir.type<_QFcsub1Tdt{c:!fir.char<1>,r:f32,i:i64}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub1"} { return }
+//CHECK-LABEL: func.func @csub1(%arg0: !fir.array<2xi64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub1"}
+
+// nested derived types
+func.func @csub2(%arg0: !fir.type<_QFcsub2Tdt1{xdt0:!fir.type<_QFcsub2Tdt0{f1:f32,f2:f32,f3:f32}>,x1:f32,x2:f32,x3:f32,x4:f32,x5:f32}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub2"} { return }
+//CHECK-LABEL: func.func @csub2(%arg0: !fir.array<8xf32> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub2"}
+
+func.func @csub3(%arg0: !fir.type<_QFcsub3Tdt1{xdt0:!fir.type<_QFcsub3Tdt0{f1:f32,f2:f32,f3:f32}>,x1:f32,x2:f32,i:i32}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub3"} { return }
+//CHECK-LABEL: func.func @csub3(%arg0: !fir.array<3xi64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub3"}
+
+func.func @csub4(%arg0: !fir.type<_QFcsub4Tdt1{xdt0:!fir.type<_QFcsub4Tdt0{f1:f32}>,x1:f64}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub4"} { return }
+//CHECK-LABEL: func.func @csub4(%arg0: !fir.array<2xi64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub4"}
+
+func.func @csub5(%arg0: !fir.type<_QFcsub5Tdt1{xdt0:!fir.type<_QFcsub5Tdt0{f1:complex<f32>}>,x1:f32}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub5"} { return }
+//CHECK-LABEL: func.func @csub5(%arg0: !fir.array<3xf32> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub5"}
+
+func.func @csub6(%arg0: !fir.type<_QFcsub6Tdt1{xdt0:!fir.type<_QFcsub6Tdt0{f1:complex<f32>}>,x1:f64}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub6"} { return }
+//CHECK-LABEL: func.func @csub6(%arg0: !fir.array<2xi64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub6"}
\ No newline at end of file
diff --git a/flang/test/Fir/struct-return-powerpc64-aix.fir b/flang/test/Fir/struct-return-powerpc64-aix.fir
new file mode 100644
index 0000000000000..6d24285711643
--- /dev/null
+++ b/flang/test/Fir/struct-return-powerpc64-aix.fir
@@ -0,0 +1,109 @@
+// Test powerpc64 ABI rewrite of struct returned by value (BIND(C), VALUE derived types).
+//
+// RUN: fir-opt --target-rewrite="target=powerpc64-ibm-aix" %s | FileCheck %s
+// REQUIRES: powerpc-registered-target
+
+// character type
+!t1 = !fir.type<t1<{c:!fir.char<1>}>>
+func.func private @test_t1() -> !t1
+//CHECK-LABEL: func.func private @test_t1(!fir.ref<!fir.type<t1<{c:!fir.char<1>}>>> {llvm.align = 8 : i32, llvm.sret = !fir.type<t1<{c:!fir.char<1>}>>})
+func.func @test_call_t1(%arg0 : !fir.ref<!t1>) {
+//CHECK-LABEL: func.func @test_call_t1(
+//CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.type<t1<{c:!fir.char<1>}>>>)
+  %out = fir.call @test_t1() : () -> !t1
+  fir.store %out to %arg0 : !fir.ref<!t1>
+  return
+  //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
+  //CHECK: %[[ARG:.*]] = fir.alloca !fir.type<t1<{c:!fir.char<1>}>>
+  //CHECK: fir.call @test_t1(%[[ARG]]) : (!fir.ref<!fir.type<t1<{c:!fir.char<1>}>>>) -> ()
+
+  //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref<!fir.type<t1<{c:!fir.char<1>}>>>) -> !fir.ref<!fir.type<t1<{c:!fir.char<1>}>>>
+  //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref<!fir.type<t1<{c:!fir.char<1>}>>>
+  //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr
+  //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref<!fir.type<t1<{c:!fir.char<1>}>>>
+  //CHECK: return
+}
+
+// integer type
+!t2 = !fir.type<t2<{i:i32}>>
+func.func private @test_t2() -> !t2
+//CHECK-LABEL: func.func private @test_t2(!fir.ref<!fir.type<t2<{i:i32}>>> {llvm.align = 8 : i32, llvm.sret = !fir.type<t2<{i:i32}>>})
+func.func @test_call_t2(%arg0 : !fir.ref<!t2>) {
+//CHECK-LABEL: func.func @test_call_t2(
+//CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.type<t2<{i:i32}>>>)
+  %out = fir.call @test_t2() : () -> !t2
+  fir.store %out to %arg0 : !fir.ref<!t2>
+  return
+  //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
+  //CHECK: %[[ARG:.*]] = fir.alloca !fir.type<t2<{i:i32}>>
+  //CHECK: fir.call @test_t2(%[[ARG]]) : (!fir.ref<!fir.type<t2<{i:i32}>>>) -> ()
+
+  //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref<!fir.type<t2<{i:i32}>>>) -> !fir.ref<!fir.type<t2<{i:i32}>>>
+  //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref<!fir.type<t2<{i:i32}>>>
+  //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr
+  //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref<!fir.type<t2<{i:i32}>>>
+  //CHECK: return
+}
+
+// real type (scalar)
+!t3 = !fir.type<t3<{r1:f32,r2:f32,r3:f32}>>
+func.func private @test_t3() -> !t3
+//CHECK-LABEL: func.func private @test_t3(!fir.ref<!fir.type<t3<{r1:f32,r2:f32,r3:f32}>>> {llvm.align = 8 : i32, llvm.sret = !fir.type<t3<{r1:f32,r2:f32,r3:f32}>>})
+func.func @test_call_t3(%arg0 : !fir.ref<!t3>) {
+//CHECK-LABEL: func.func @test_call_t3(
+//CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.type<t3<{r1:f32,r2:f32,r3:f32}>>>)
+  %out = fir.call @test_t3() : () -> !t3
+  fir.store %out to %arg0 : !fir.ref<!t3>
+  return
+  //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
+  //CHECK: %[[ARG:.*]] = fir.alloca !fir.type<t3<{r1:f32,r2:f32,r3:f32}>>
+  //CHECK: fir.call @test_t3(%[[ARG]]) : (!fir.ref<!fir.type<t3<{r1:f32,r2:f32,r3:f32}>>>) -> ()
+
+  //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref<!fir.type<t3<{r1:f32,r2:f32,r3:f32}>>>) -> !fir.ref<!fir.type<t3<{r1:f32,r2:f32,r3:f32}>>>
+  //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref<!fir.type<t3<{r1:f32,r2:f32,r3:f32}>>>
+  //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr
+  //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref<!fir.type<t3<{r1:f32,r2:f32,r3:f32}>>>
+  //CHECK: return
+}
+
+// real type (array)
+!t4 = !fir.type<t4<{r:!fir.array<8xf32>}>>
+func.func private @test_t4() -> !t4
+//CHECK-LABEL: func.func private @test_t4(!fir.ref<!fir.type<t4<{r:!fir.array<8xf32>}>>> {llvm.align = 8 : i32, llvm.sret = !fir.type<t4<{r:!fir.array<8xf32>}>>})
+func.func @test_call_t4(%arg0 : !fir.ref<!t4>) {
+//CHECK-LABEL: func.func @test_call_t4(
+//CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.type<t4<{r:!fir.array<8xf32>}>>>)
+  %out = fir.call @test_t4() : () -> !t4
+  fir.store %out to %arg0 : !fir.ref<!t4>
+  return
+  //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
+  //CHECK: %[[ARG:.*]] = fir.alloca !fir.type<t4<{r:!fir.array<8xf32>}>>
+  //CHECK: fir.call @test_t4(%[[ARG]]) : (!fir.ref<!fir.type<t4<{r:!fir.array<8xf32>}>>>) -> ()
+
+  //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref<!fir.type<t4<{r:!fir.array<8xf32>}>>>) -> !fir.ref<!fir.type<t4<{r:!fir.array<8xf32>}>>>
+  //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref<!fir.type<t4<{r:!fir.array<8xf32>}>>>
+  //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr
+  //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref<!fir.type<t4<{r:!fir.array<8xf32>}>>>
+  //CHECK: return
+}
+
+// mixed types
+!t5 = !fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>
+func.func private @test_t5() -> !t5
+//CHECK-LABEL: func.func private @test_t5(!fir.ref<!fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>> {llvm.align = 8 : i32, llvm.sret = !fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>})
+func.func @test_call_t5(%arg0 : !fir.ref<!t5>) {
+//CHECK-LABEL: func.func @test_call_t5(
+//CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>>)
+  %out = fir.call @test_t5() : () -> !t5
+  fir.store %out to %arg0 : !fir.ref<!t5>
+  return
+  //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
+  //CHECK: %[[ARG:.*]] = fir.alloca !fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>
+  //CHECK: fir.call @test_t5(%[[ARG]]) : (!fir.ref<!fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>>) -> ()
+
+  //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref<!fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>>) -> !fir.ref<!fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>>
+  //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref<!fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>>
+  //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr
+  //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref<!fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>>
+  //CHECK: return
+}
diff --git a/flang/test/Fir/struct-return-ppc64le.fir b/flang/test/Fir/struct-return-ppc64le.fir
new file mode 100644
index 0000000000000..ae74a4a1cc315
--- /dev/null
+++ b/flang/test/Fir/struct-return-ppc64le.fir
@@ -0,0 +1,107 @@
+// Test ppc64le ABI rewrite of struct returned by value (BIND(C), VALUE derived types).
+//
+// RUN: fir-opt --target-rewrite="target=ppc64le-ibm-linux" %s | FileCheck %s
+// REQUIRES: powerpc-registered-target
+
+// character type
+!t1 = !fir.type<t1{c:!fir.char<1>}>
+func.func private @test_t1() -> !t1
+//CHECK-LABEL: func.func private @test_t1(!fir.ref<!fir.type<t1{c:!fir.char<1>}>> {llvm.align = 8 : i32, llvm.sret = !fir.type<t1{c:!fir.char<1>}>})
+func.func @test_call_t1(%arg0 : !fir.ref<!t1>) {
+//CHECK-LABEL: func.func @test_call_t1(
+//CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.type<t1{c:!fir.char<1>}>>)
+  %out = fir.call @test_t1() : () -> !t1
+  fir.store %out to %arg0 : !fir.ref<!t1>
+  return
+  //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
+  //CHECK: %[[ARG:.*]] = fir.alloca !fir.type<t1{c:!fir.char<1>}>
+  //CHECK: fir.call @test_t1(%[[ARG]]) : (!fir.ref<!fir.type<t1{c:!fir.char<1>}>>) -> ()
+
+  //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref<!fir.type<t1{c:!fir.char<1>}>>) -> !fir.ref<!fir.type<t1{c:!fir.char<1>}>>
+  //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref<!fir.type<t1{c:!fir.char<1>}>>
+  //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr
+  //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref<!fir.type<t1{c:!fir.char<1>}>>
+  //CHECK: return
+}
+
+// integer type
+!t2 = !fir.type<t2{i:i32}>
+func.func private @test_t2() -> !t2
+//CHECK-LABEL: func.func private @test_t2(!fir.ref<!fir.type<t2{i:i32}>> {llvm.align = 8 : i32, llvm.sret = !fir.type<t2{i:i32}>})
+func.func @test_call_t2(%arg0 : !fir.ref<!t2>) {
+//CHECK-LABEL: func.func @test_call_t2(
+//CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.type<t2{i:i32}>>)
+  %out = fir.call @test_t2() : () -> !t2
+  fir.store %out to %arg0 : !fir.ref<!t2>
+  return
+  //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
+  //CHECK: %[[ARG:.*]] = fir.alloca !fir.type<t2{i:i32}>
+  //CHECK: fir.call @test_t2(%[[ARG]]) : (!fir.ref<!fir.type<t2{i:i32}>>) -> ()
+
+  //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref<!fir.type<t2{i:i32}>>) -> !fir.ref<!fir.type<t2{i:i32}>>
+  //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref<!fir.type<t2{i:i32}>>
+  //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr
+  //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref<!fir.type<t2{i:i32}>>
+  //CHECK: return
+}
+
+// real type (scalar)
+!t3 = !fir.type<t3{r1:f32,r2:f32,r3:f32}>
+func.func private @test_t3() -> !t3
+//CHECK-LABEL: func.func private @test_t3() -> !fir.array<3xf32>
+func.func @test_call_t3(%arg0 : !fir.ref<!t3>) {
+//CHECK-LABEL: func.func @test_call_t3(
+//CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.type<t3{r1:f32,r2:f32,r3:f32}>>)
+  %out = fir.call @test_t3() : () -> !t3
+  fir.store %out to %arg0 : !fir.ref<!t3>
+  return
+  //CHECK: %[[RET:.*]] = fir.call @test_t3() : () -> !fir.array<3xf32>
+  //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
+  //CHECK: %[[ARG:.*]] = fir.alloca !fir.array<3xf32>
+  //CHECK: fir.store %[[RET]] to %[[ARG]] : !fir.ref<!fir.array<3xf32>>
+  //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref<!fir.array<3xf32>>) -> !fir.ref<!fir.type<t3{r1:f32,r2:f32,r3:f32}>>
+  //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref<!fir.type<t3{r1:f32,r2:f32,r3:f32}>>
+  //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr
+  //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref<!fir.type<t3{r1:f32,r2:f32,r3:f32}>>
+  //CHECK: return
+}
+
+// real type (> 8 floats)
+!t4 = !fir.type<t4{r:!fir.array<9xf32>}>
+func.func private @test_t4() -> !t4
+//CHECK-LABEL: func.func private @test_t4(!fir.ref<!fir.type<t4{r:!fir.array<9xf32>}>> {llvm.align = 8 : i32, llvm.sret = !fir.type<t4{r:!fir.array<9xf32>}>})
+func.func @test_call_t4(%arg0 : !fir.ref<!t4>) {
+//CHECK-LABEL: func.func @test_call_t4(
+//CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.type<t4{r:!fir.array<9xf32>}>>)
+  %out = fir.call @test_t4() : () -> !t4
+  fir.store %out to %arg0 : !fir.ref<!t4>
+  return
+  //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
+  //CHECK: %[[ARG:.*]] = fir.alloca !fir.type<t4{r:!fir.array<9xf32>}>
+  //CHECK: fir.call @test_t4(%[[ARG]]) : (!fir.ref<!fir.type<t4{r:!fir.array<9xf32>}>>) -> ()
+  //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref<!fir.type<t4{r:!fir.array<9xf32>}>>) -> !fir.ref<!fir.type<t4{r:!fir.array<9xf32>}>>
+  //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref<!fir.type<t4{r:!fir.array<9xf32>}>>
+  //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr
+  //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref<!fir.type<t4{r:!fir.array<9xf32>}>>
+  //CHECK: return
+}
+
+// mixed types
+!t5 = !fir.type<t5{c:!fir.char<1>,r:f32,i:i64}>
+func.func private @test_t5() -> !t5
+//CHECK-LABEL: func.func private @test_t5(!fir.ref<!fir.type<t5{c:!fir.char<1>,r:f32,i:i64}>> {llvm.align = 8 : i32, llvm.sret = !fir.type<t5{c:!fir.char<1>,r:f32,i:i64}>})
+func.func @test_call_t5(%arg0 : !fir.ref<!t5>) {
+//CHECK-LABEL: func.func @test_call_t5(
+//CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.type<t5{c:!fir.char<1>,r:f32,i:i64}>>)
+  %out = fir.call @test_t5() : () -> !t5
+  fir.store %out to %arg0 : !fir.ref<!t5>
+  return
+  //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
+  //CHECK: %[[ARG:.*]] = fir.alloca !fir.type<t5{c:!fir.char<1>,r:f32,i:i64}>
+  //CHECK: fir.call @test_t5(%[[ARG]]) : (!fir.ref<!fir.type<t5{c:!fir.char<1>,r:f32,i:i64}>>) -> ()
+  //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref<!fir.type<t5{c:!fir.char<1>,r:f32,i:i64}>>) -> !fir.ref<!fir.type<t5{c:!fir.char<1>,r:f32,i:i64}>>
+  //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref<!fir.type<t5{c:!fir.char<1>,r:f32,i:i64}>>
+  //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr
+  //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref<!fir.type<t5{c:!fir.char<1>,r:f32,i:i64}>>
+  //CHECK: return
+}

>From 435543bbf246566b4c8de33973e3bc8d802f3fdf Mon Sep 17 00:00:00 2001
From: Kelvin Li <kli at ca.ibm.com>
Date: Wed, 26 Feb 2025 10:12:39 -0500
Subject: [PATCH 2/2] Address review comments

---
 flang/lib/Optimizer/CodeGen/Target.cpp        |  2 +-
 .../Fir/struct-passing-loongarch64-byreg.fir  |  1 -
 .../struct-passing-powerpc64-aix-byval.fir    |  5 +-
 .../test/Fir/struct-passing-ppc64le-byval.fir |  9 ++-
 .../test/Fir/struct-return-powerpc64-aix.fir  | 55 ++++++++-----------
 flang/test/Fir/struct-return-ppc64le.fir      | 52 ++++++++----------
 6 files changed, 59 insertions(+), 65 deletions(-)

diff --git a/flang/lib/Optimizer/CodeGen/Target.cpp b/flang/lib/Optimizer/CodeGen/Target.cpp
index 59dfee1a9d5e2..e2f8fb9d239a1 100644
--- a/flang/lib/Optimizer/CodeGen/Target.cpp
+++ b/flang/lib/Optimizer/CodeGen/Target.cpp
@@ -1058,7 +1058,7 @@ struct TargetPPC64 : public GenericTarget<TargetPPC64> {
     unsigned short align{
         std::max(sizeAndAlign.second, static_cast<unsigned short>(8))};
     marshal.emplace_back(fir::ReferenceType::get(ty),
-                         AT{align, /*byvale*/ !isResult, /*sret*/ isResult});
+                         AT{align, /*byval*/ !isResult, /*sret*/ isResult});
     return marshal;
   }
 
diff --git a/flang/test/Fir/struct-passing-loongarch64-byreg.fir b/flang/test/Fir/struct-passing-loongarch64-byreg.fir
index 585884504aacf..f2f54e12eac46 100644
--- a/flang/test/Fir/struct-passing-loongarch64-byreg.fir
+++ b/flang/test/Fir/struct-passing-loongarch64-byreg.fir
@@ -7,7 +7,6 @@
 /// only the first example in each category checks the entire invocation process,
 /// while the other examples only check the signatures.
 
-// REQUIRES: loongarch-registered-target
 // RUN: fir-opt --split-input-file --target-rewrite="target=loongarch64-unknown-linux-gnu" %s | FileCheck %s
 
 
diff --git a/flang/test/Fir/struct-passing-powerpc64-aix-byval.fir b/flang/test/Fir/struct-passing-powerpc64-aix-byval.fir
index 0fd6d836761cb..b6e9b2834b913 100644
--- a/flang/test/Fir/struct-passing-powerpc64-aix-byval.fir
+++ b/flang/test/Fir/struct-passing-powerpc64-aix-byval.fir
@@ -1,7 +1,8 @@
 // Test powerpc64 rewrite of struct passed by value (BIND(C), VALUE derived types).
 //
 // RUN: fir-opt --target-rewrite="target=powerpc64-ibm-aix" %s | FileCheck %s
-// REQUIRES: powerpc-registered-target
+
+module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "E-m:a-Fi64-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512", llvm.target_triple = "powerpc64-ibm-aix7.2.0.0"} {
 
 // character type
 func.func @csubch(%arg0: !fir.type<_QFcsubchTdt<{c:!fir.char<1>}>> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubch"} { return }
@@ -23,3 +24,5 @@ func.func @csubr5(%arg0: !fir.type<_QFcsubr5Tdt<{r:!fir.array<8xf32>}>> {fir.bin
 func.func @csub1(%arg0: !fir.type<_QFcsub1Tdt<{c:!fir.char<1>,r:f32,i:i64}>> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub1"} { return }
 //CHECK-LABEL: func.func @csub1(%arg0: !fir.ref<!fir.type<_QFcsub1Tdt<{c:!fir.char<1>,r:f32,i:i64}>>> {fir.bindc_name = "arg", llvm.align = 8 : i32, llvm.byval = !fir.type<_QFcsub1Tdt<{c:!fir.char<1>,r:f32,i:i64}>>}) attributes {fir.bindc_name = "csub1"}
 
+}
+
diff --git a/flang/test/Fir/struct-passing-ppc64le-byval.fir b/flang/test/Fir/struct-passing-ppc64le-byval.fir
index 697f060c671f1..b9be67fbe97bf 100644
--- a/flang/test/Fir/struct-passing-ppc64le-byval.fir
+++ b/flang/test/Fir/struct-passing-ppc64le-byval.fir
@@ -1,7 +1,8 @@
 // Test ppc64le rewrite of struct passed by value (BIND(C), VALUE derived types).
 //
-// RUN: fir-opt --target-rewrite="target=ppc64le-unknown-linux" %s | FileCheck %s
-// REQUIRES: powerpc-registered-target
+// RUN: fir-opt --target-rewrite="target=ppc64le-ibm-linux" %s | FileCheck %s
+
+module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "e-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512", llvm.target_triple = "powerpc64le-unknown-linux-gnu"} {
 
 // character type
 func.func @csubch(%arg0: !fir.type<_QFcsubchTdt{c:!fir.char<1>}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubch"} { return }
@@ -76,4 +77,6 @@ func.func @csub5(%arg0: !fir.type<_QFcsub5Tdt1{xdt0:!fir.type<_QFcsub5Tdt0{f1:co
 //CHECK-LABEL: func.func @csub5(%arg0: !fir.array<3xf32> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub5"}
 
 func.func @csub6(%arg0: !fir.type<_QFcsub6Tdt1{xdt0:!fir.type<_QFcsub6Tdt0{f1:complex<f32>}>,x1:f64}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub6"} { return }
-//CHECK-LABEL: func.func @csub6(%arg0: !fir.array<2xi64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub6"}
\ No newline at end of file
+//CHECK-LABEL: func.func @csub6(%arg0: !fir.array<2xi64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub6"}
+
+}
diff --git a/flang/test/Fir/struct-return-powerpc64-aix.fir b/flang/test/Fir/struct-return-powerpc64-aix.fir
index 6d24285711643..3058ef6b7e965 100644
--- a/flang/test/Fir/struct-return-powerpc64-aix.fir
+++ b/flang/test/Fir/struct-return-powerpc64-aix.fir
@@ -1,22 +1,21 @@
 // Test powerpc64 ABI rewrite of struct returned by value (BIND(C), VALUE derived types).
 //
 // RUN: fir-opt --target-rewrite="target=powerpc64-ibm-aix" %s | FileCheck %s
-// REQUIRES: powerpc-registered-target
+
+module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "E-m:a-Fi64-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512", llvm.target_triple = "powerpc64-ibm-aix7.2.0.0"} {
 
 // character type
-!t1 = !fir.type<t1<{c:!fir.char<1>}>>
-func.func private @test_t1() -> !t1
+func.func private @test_t1() -> !fir.type<t1<{c:!fir.char<1>}>>
 //CHECK-LABEL: func.func private @test_t1(!fir.ref<!fir.type<t1<{c:!fir.char<1>}>>> {llvm.align = 8 : i32, llvm.sret = !fir.type<t1<{c:!fir.char<1>}>>})
-func.func @test_call_t1(%arg0 : !fir.ref<!t1>) {
+func.func @test_call_t1(%arg0 : !fir.ref<!fir.type<t1<{c:!fir.char<1>}>>>) {
 //CHECK-LABEL: func.func @test_call_t1(
 //CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.type<t1<{c:!fir.char<1>}>>>)
-  %out = fir.call @test_t1() : () -> !t1
-  fir.store %out to %arg0 : !fir.ref<!t1>
+  %out = fir.call @test_t1() : () -> !fir.type<t1<{c:!fir.char<1>}>>
+  fir.store %out to %arg0 : !fir.ref<!fir.type<t1<{c:!fir.char<1>}>>>
   return
   //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
   //CHECK: %[[ARG:.*]] = fir.alloca !fir.type<t1<{c:!fir.char<1>}>>
   //CHECK: fir.call @test_t1(%[[ARG]]) : (!fir.ref<!fir.type<t1<{c:!fir.char<1>}>>>) -> ()
-
   //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref<!fir.type<t1<{c:!fir.char<1>}>>>) -> !fir.ref<!fir.type<t1<{c:!fir.char<1>}>>>
   //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref<!fir.type<t1<{c:!fir.char<1>}>>>
   //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr
@@ -25,19 +24,17 @@ func.func @test_call_t1(%arg0 : !fir.ref<!t1>) {
 }
 
 // integer type
-!t2 = !fir.type<t2<{i:i32}>>
-func.func private @test_t2() -> !t2
+func.func private @test_t2() -> !fir.type<t2<{i:i32}>>
 //CHECK-LABEL: func.func private @test_t2(!fir.ref<!fir.type<t2<{i:i32}>>> {llvm.align = 8 : i32, llvm.sret = !fir.type<t2<{i:i32}>>})
-func.func @test_call_t2(%arg0 : !fir.ref<!t2>) {
+func.func @test_call_t2(%arg0 : !fir.ref<!fir.type<t2<{i:i32}>>>) {
 //CHECK-LABEL: func.func @test_call_t2(
 //CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.type<t2<{i:i32}>>>)
-  %out = fir.call @test_t2() : () -> !t2
-  fir.store %out to %arg0 : !fir.ref<!t2>
+  %out = fir.call @test_t2() : () -> !fir.type<t2<{i:i32}>>
+  fir.store %out to %arg0 : !fir.ref<!fir.type<t2<{i:i32}>>>
   return
   //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
   //CHECK: %[[ARG:.*]] = fir.alloca !fir.type<t2<{i:i32}>>
   //CHECK: fir.call @test_t2(%[[ARG]]) : (!fir.ref<!fir.type<t2<{i:i32}>>>) -> ()
-
   //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref<!fir.type<t2<{i:i32}>>>) -> !fir.ref<!fir.type<t2<{i:i32}>>>
   //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref<!fir.type<t2<{i:i32}>>>
   //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr
@@ -46,19 +43,17 @@ func.func @test_call_t2(%arg0 : !fir.ref<!t2>) {
 }
 
 // real type (scalar)
-!t3 = !fir.type<t3<{r1:f32,r2:f32,r3:f32}>>
-func.func private @test_t3() -> !t3
+func.func private @test_t3() -> !fir.type<t3<{r1:f32,r2:f32,r3:f32}>>
 //CHECK-LABEL: func.func private @test_t3(!fir.ref<!fir.type<t3<{r1:f32,r2:f32,r3:f32}>>> {llvm.align = 8 : i32, llvm.sret = !fir.type<t3<{r1:f32,r2:f32,r3:f32}>>})
-func.func @test_call_t3(%arg0 : !fir.ref<!t3>) {
+func.func @test_call_t3(%arg0 : !fir.ref<!fir.type<t3<{r1:f32,r2:f32,r3:f32}>>>) {
 //CHECK-LABEL: func.func @test_call_t3(
 //CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.type<t3<{r1:f32,r2:f32,r3:f32}>>>)
-  %out = fir.call @test_t3() : () -> !t3
-  fir.store %out to %arg0 : !fir.ref<!t3>
+  %out = fir.call @test_t3() : () -> !fir.type<t3<{r1:f32,r2:f32,r3:f32}>>
+  fir.store %out to %arg0 : !fir.ref<!fir.type<t3<{r1:f32,r2:f32,r3:f32}>>>
   return
   //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
   //CHECK: %[[ARG:.*]] = fir.alloca !fir.type<t3<{r1:f32,r2:f32,r3:f32}>>
   //CHECK: fir.call @test_t3(%[[ARG]]) : (!fir.ref<!fir.type<t3<{r1:f32,r2:f32,r3:f32}>>>) -> ()
-
   //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref<!fir.type<t3<{r1:f32,r2:f32,r3:f32}>>>) -> !fir.ref<!fir.type<t3<{r1:f32,r2:f32,r3:f32}>>>
   //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref<!fir.type<t3<{r1:f32,r2:f32,r3:f32}>>>
   //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr
@@ -67,19 +62,17 @@ func.func @test_call_t3(%arg0 : !fir.ref<!t3>) {
 }
 
 // real type (array)
-!t4 = !fir.type<t4<{r:!fir.array<8xf32>}>>
-func.func private @test_t4() -> !t4
+func.func private @test_t4() -> !fir.type<t4<{r:!fir.array<8xf32>}>>
 //CHECK-LABEL: func.func private @test_t4(!fir.ref<!fir.type<t4<{r:!fir.array<8xf32>}>>> {llvm.align = 8 : i32, llvm.sret = !fir.type<t4<{r:!fir.array<8xf32>}>>})
-func.func @test_call_t4(%arg0 : !fir.ref<!t4>) {
+func.func @test_call_t4(%arg0 : !fir.ref<!fir.type<t4<{r:!fir.array<8xf32>}>>>) {
 //CHECK-LABEL: func.func @test_call_t4(
 //CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.type<t4<{r:!fir.array<8xf32>}>>>)
-  %out = fir.call @test_t4() : () -> !t4
-  fir.store %out to %arg0 : !fir.ref<!t4>
+  %out = fir.call @test_t4() : () -> !fir.type<t4<{r:!fir.array<8xf32>}>>
+  fir.store %out to %arg0 : !fir.ref<!fir.type<t4<{r:!fir.array<8xf32>}>>>
   return
   //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
   //CHECK: %[[ARG:.*]] = fir.alloca !fir.type<t4<{r:!fir.array<8xf32>}>>
   //CHECK: fir.call @test_t4(%[[ARG]]) : (!fir.ref<!fir.type<t4<{r:!fir.array<8xf32>}>>>) -> ()
-
   //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref<!fir.type<t4<{r:!fir.array<8xf32>}>>>) -> !fir.ref<!fir.type<t4<{r:!fir.array<8xf32>}>>>
   //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref<!fir.type<t4<{r:!fir.array<8xf32>}>>>
   //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr
@@ -88,22 +81,22 @@ func.func @test_call_t4(%arg0 : !fir.ref<!t4>) {
 }
 
 // mixed types
-!t5 = !fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>
-func.func private @test_t5() -> !t5
+func.func private @test_t5() -> !fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>
 //CHECK-LABEL: func.func private @test_t5(!fir.ref<!fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>> {llvm.align = 8 : i32, llvm.sret = !fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>})
-func.func @test_call_t5(%arg0 : !fir.ref<!t5>) {
+func.func @test_call_t5(%arg0 : !fir.ref<!fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>>) {
 //CHECK-LABEL: func.func @test_call_t5(
 //CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>>)
-  %out = fir.call @test_t5() : () -> !t5
-  fir.store %out to %arg0 : !fir.ref<!t5>
+  %out = fir.call @test_t5() : () -> !fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>
+  fir.store %out to %arg0 : !fir.ref<!fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>>
   return
   //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
   //CHECK: %[[ARG:.*]] = fir.alloca !fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>
   //CHECK: fir.call @test_t5(%[[ARG]]) : (!fir.ref<!fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>>) -> ()
-
   //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref<!fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>>) -> !fir.ref<!fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>>
   //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref<!fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>>
   //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr
   //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref<!fir.type<t5<{c:!fir.char<1>,r:f32,i:i64}>>>
   //CHECK: return
 }
+
+}
diff --git a/flang/test/Fir/struct-return-ppc64le.fir b/flang/test/Fir/struct-return-ppc64le.fir
index ae74a4a1cc315..a5906280a0ef8 100644
--- a/flang/test/Fir/struct-return-ppc64le.fir
+++ b/flang/test/Fir/struct-return-ppc64le.fir
@@ -1,22 +1,21 @@
 // Test ppc64le ABI rewrite of struct returned by value (BIND(C), VALUE derived types).
 //
 // RUN: fir-opt --target-rewrite="target=ppc64le-ibm-linux" %s | FileCheck %s
-// REQUIRES: powerpc-registered-target
+
+module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "e-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512", llvm.target_triple = "powerpc64le-unknown-linux-gnu"} {
 
 // character type
-!t1 = !fir.type<t1{c:!fir.char<1>}>
-func.func private @test_t1() -> !t1
+func.func private @test_t1() -> !fir.type<t1{c:!fir.char<1>}>
 //CHECK-LABEL: func.func private @test_t1(!fir.ref<!fir.type<t1{c:!fir.char<1>}>> {llvm.align = 8 : i32, llvm.sret = !fir.type<t1{c:!fir.char<1>}>})
-func.func @test_call_t1(%arg0 : !fir.ref<!t1>) {
+func.func @test_call_t1(%arg0 : !fir.ref<!fir.type<t1{c:!fir.char<1>}>>) {
 //CHECK-LABEL: func.func @test_call_t1(
 //CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.type<t1{c:!fir.char<1>}>>)
-  %out = fir.call @test_t1() : () -> !t1
-  fir.store %out to %arg0 : !fir.ref<!t1>
+  %out = fir.call @test_t1() : () -> !fir.type<t1{c:!fir.char<1>}>
+  fir.store %out to %arg0 : !fir.ref<!fir.type<t1{c:!fir.char<1>}>>
   return
   //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
   //CHECK: %[[ARG:.*]] = fir.alloca !fir.type<t1{c:!fir.char<1>}>
   //CHECK: fir.call @test_t1(%[[ARG]]) : (!fir.ref<!fir.type<t1{c:!fir.char<1>}>>) -> ()
-
   //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref<!fir.type<t1{c:!fir.char<1>}>>) -> !fir.ref<!fir.type<t1{c:!fir.char<1>}>>
   //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref<!fir.type<t1{c:!fir.char<1>}>>
   //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr
@@ -25,19 +24,17 @@ func.func @test_call_t1(%arg0 : !fir.ref<!t1>) {
 }
 
 // integer type
-!t2 = !fir.type<t2{i:i32}>
-func.func private @test_t2() -> !t2
+func.func private @test_t2() -> !fir.type<t2{i:i32}>
 //CHECK-LABEL: func.func private @test_t2(!fir.ref<!fir.type<t2{i:i32}>> {llvm.align = 8 : i32, llvm.sret = !fir.type<t2{i:i32}>})
-func.func @test_call_t2(%arg0 : !fir.ref<!t2>) {
+func.func @test_call_t2(%arg0 : !fir.ref<!fir.type<t2{i:i32}>>) {
 //CHECK-LABEL: func.func @test_call_t2(
 //CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.type<t2{i:i32}>>)
-  %out = fir.call @test_t2() : () -> !t2
-  fir.store %out to %arg0 : !fir.ref<!t2>
+  %out = fir.call @test_t2() : () -> !fir.type<t2{i:i32}>
+  fir.store %out to %arg0 : !fir.ref<!fir.type<t2{i:i32}>>
   return
   //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
   //CHECK: %[[ARG:.*]] = fir.alloca !fir.type<t2{i:i32}>
   //CHECK: fir.call @test_t2(%[[ARG]]) : (!fir.ref<!fir.type<t2{i:i32}>>) -> ()
-
   //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref<!fir.type<t2{i:i32}>>) -> !fir.ref<!fir.type<t2{i:i32}>>
   //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref<!fir.type<t2{i:i32}>>
   //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr
@@ -46,14 +43,13 @@ func.func @test_call_t2(%arg0 : !fir.ref<!t2>) {
 }
 
 // real type (scalar)
-!t3 = !fir.type<t3{r1:f32,r2:f32,r3:f32}>
-func.func private @test_t3() -> !t3
+func.func private @test_t3() -> !fir.type<t3{r1:f32,r2:f32,r3:f32}>
 //CHECK-LABEL: func.func private @test_t3() -> !fir.array<3xf32>
-func.func @test_call_t3(%arg0 : !fir.ref<!t3>) {
+func.func @test_call_t3(%arg0 : !fir.ref<!fir.type<t3{r1:f32,r2:f32,r3:f32}>>) {
 //CHECK-LABEL: func.func @test_call_t3(
 //CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.type<t3{r1:f32,r2:f32,r3:f32}>>)
-  %out = fir.call @test_t3() : () -> !t3
-  fir.store %out to %arg0 : !fir.ref<!t3>
+  %out = fir.call @test_t3() : () -> !fir.type<t3{r1:f32,r2:f32,r3:f32}>
+  fir.store %out to %arg0 : !fir.ref<!fir.type<t3{r1:f32,r2:f32,r3:f32}>>
   return
   //CHECK: %[[RET:.*]] = fir.call @test_t3() : () -> !fir.array<3xf32>
   //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
@@ -67,14 +63,13 @@ func.func @test_call_t3(%arg0 : !fir.ref<!t3>) {
 }
 
 // real type (> 8 floats)
-!t4 = !fir.type<t4{r:!fir.array<9xf32>}>
-func.func private @test_t4() -> !t4
+func.func private @test_t4() -> !fir.type<t4{r:!fir.array<9xf32>}>
 //CHECK-LABEL: func.func private @test_t4(!fir.ref<!fir.type<t4{r:!fir.array<9xf32>}>> {llvm.align = 8 : i32, llvm.sret = !fir.type<t4{r:!fir.array<9xf32>}>})
-func.func @test_call_t4(%arg0 : !fir.ref<!t4>) {
+func.func @test_call_t4(%arg0 : !fir.ref<!fir.type<t4{r:!fir.array<9xf32>}>>) {
 //CHECK-LABEL: func.func @test_call_t4(
 //CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.type<t4{r:!fir.array<9xf32>}>>)
-  %out = fir.call @test_t4() : () -> !t4
-  fir.store %out to %arg0 : !fir.ref<!t4>
+  %out = fir.call @test_t4() : () -> !fir.type<t4{r:!fir.array<9xf32>}>
+  fir.store %out to %arg0 : !fir.ref<!fir.type<t4{r:!fir.array<9xf32>}>>
   return
   //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
   //CHECK: %[[ARG:.*]] = fir.alloca !fir.type<t4{r:!fir.array<9xf32>}>
@@ -87,14 +82,13 @@ func.func @test_call_t4(%arg0 : !fir.ref<!t4>) {
 }
 
 // mixed types
-!t5 = !fir.type<t5{c:!fir.char<1>,r:f32,i:i64}>
-func.func private @test_t5() -> !t5
+func.func private @test_t5() -> !fir.type<t5{c:!fir.char<1>,r:f32,i:i64}>
 //CHECK-LABEL: func.func private @test_t5(!fir.ref<!fir.type<t5{c:!fir.char<1>,r:f32,i:i64}>> {llvm.align = 8 : i32, llvm.sret = !fir.type<t5{c:!fir.char<1>,r:f32,i:i64}>})
-func.func @test_call_t5(%arg0 : !fir.ref<!t5>) {
+func.func @test_call_t5(%arg0 : !fir.ref<!fir.type<t5{c:!fir.char<1>,r:f32,i:i64}>>) {
 //CHECK-LABEL: func.func @test_call_t5(
 //CHECK-SAME:    %[[ARG0:.*]]: !fir.ref<!fir.type<t5{c:!fir.char<1>,r:f32,i:i64}>>)
-  %out = fir.call @test_t5() : () -> !t5
-  fir.store %out to %arg0 : !fir.ref<!t5>
+  %out = fir.call @test_t5() : () -> !fir.type<t5{c:!fir.char<1>,r:f32,i:i64}>
+  fir.store %out to %arg0 : !fir.ref<!fir.type<t5{c:!fir.char<1>,r:f32,i:i64}>>
   return
   //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
   //CHECK: %[[ARG:.*]] = fir.alloca !fir.type<t5{c:!fir.char<1>,r:f32,i:i64}>
@@ -105,3 +99,5 @@ func.func @test_call_t5(%arg0 : !fir.ref<!t5>) {
   //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref<!fir.type<t5{c:!fir.char<1>,r:f32,i:i64}>>
   //CHECK: return
 }
+
+}



More information about the flang-commits mailing list