From d918a943a41b9284127ab31ce9cd4ea7e7f6f480 Mon Sep 17 00:00:00 2001 From: Kelvin Li 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 { 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(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 { 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 { AT{}); return marshal; } + + unsigned getElemWidth(mlir::Type ty) const { + unsigned width{}; + llvm::TypeSwitch(ty) + .template Case([&](mlir::ComplexType cmplx) { + auto elemType{ + mlir::dyn_cast(cmplx.getElementType())}; + width = elemType.getWidth(); + }) + .template Case( + [&](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 &firstTypeAndWidth) const { + for (auto comp : recTy.getTypeList()) { + mlir::Type compType{comp.second}; + if (mlir::isa(compType)) { + auto rc{hasSameFloatAndWidth(mlir::cast(compType), + firstTypeAndWidth)}; + if (!rc) + return false; + } else { + mlir::Type ty; + bool isFloatType{false}; + if (mlir::isa(compType)) { + ty = compType; + isFloatType = true; + } else if (auto seqTy = mlir::dyn_cast(compType)) { + ty = seqTy.getEleTy(); + isFloatType = mlir::isa(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(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 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( + std::ceil(static_cast(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(firstType)) { + auto fltType{mlir::dyn_cast(cmplx.getElementType())}; + n = static_cast(8 * recordTypeSize / fltType.getWidth()); + if (n <= maxNoOfFloats) { + nElem = n; + elemTy = fltType; + } + } else if (mlir::isa(firstType)) { + auto elemSizeAndAlign{fir::getTypeSizeAndAlignmentOrCrash( + loc, firstType, getDataLayout(), kindMap)}; + n = static_cast(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(elemTy) && nElem > maxNoOfFloats) || + !mlir::isa(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.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.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.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.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,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.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.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.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,r2:complex}> {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,r2:complex,r3:complex,r4:complex}> {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>}> {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>}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubc4"} { return } +//CHECK-LABEL: func.func @csubc4(%arg0: !fir.ref>}>> {fir.bindc_name = "arg", llvm.align = 8 : i32, llvm.byval = !fir.type<_QFcsubc4Tdt{r:!fir.array<9xcomplex>}>}) 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}>,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}>,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}>> +func.func private @test_t1() -> !t1 +//CHECK-LABEL: func.func private @test_t1(!fir.ref}>>> {llvm.align = 8 : i32, llvm.sret = !fir.type}>>}) +func.func @test_call_t1(%arg0 : !fir.ref) { +//CHECK-LABEL: func.func @test_call_t1( +//CHECK-SAME: %[[ARG0:.*]]: !fir.ref}>>>) + %out = fir.call @test_t1() : () -> !t1 + fir.store %out to %arg0 : !fir.ref + return + //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr + //CHECK: %[[ARG:.*]] = fir.alloca !fir.type}>> + //CHECK: fir.call @test_t1(%[[ARG]]) : (!fir.ref}>>>) -> () + + //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref}>>>) -> !fir.ref}>>> + //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref}>>> + //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr + //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref}>>> + //CHECK: return +} + +// integer type +!t2 = !fir.type> +func.func private @test_t2() -> !t2 +//CHECK-LABEL: func.func private @test_t2(!fir.ref>> {llvm.align = 8 : i32, llvm.sret = !fir.type>}) +func.func @test_call_t2(%arg0 : !fir.ref) { +//CHECK-LABEL: func.func @test_call_t2( +//CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>) + %out = fir.call @test_t2() : () -> !t2 + fir.store %out to %arg0 : !fir.ref + return + //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr + //CHECK: %[[ARG:.*]] = fir.alloca !fir.type> + //CHECK: fir.call @test_t2(%[[ARG]]) : (!fir.ref>>) -> () + + //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref>>) -> !fir.ref>> + //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref>> + //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr + //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref>> + //CHECK: return +} + +// real type (scalar) +!t3 = !fir.type> +func.func private @test_t3() -> !t3 +//CHECK-LABEL: func.func private @test_t3(!fir.ref>> {llvm.align = 8 : i32, llvm.sret = !fir.type>}) +func.func @test_call_t3(%arg0 : !fir.ref) { +//CHECK-LABEL: func.func @test_call_t3( +//CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>) + %out = fir.call @test_t3() : () -> !t3 + fir.store %out to %arg0 : !fir.ref + return + //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr + //CHECK: %[[ARG:.*]] = fir.alloca !fir.type> + //CHECK: fir.call @test_t3(%[[ARG]]) : (!fir.ref>>) -> () + + //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref>>) -> !fir.ref>> + //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref>> + //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr + //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref>> + //CHECK: return +} + +// real type (array) +!t4 = !fir.type}>> +func.func private @test_t4() -> !t4 +//CHECK-LABEL: func.func private @test_t4(!fir.ref}>>> {llvm.align = 8 : i32, llvm.sret = !fir.type}>>}) +func.func @test_call_t4(%arg0 : !fir.ref) { +//CHECK-LABEL: func.func @test_call_t4( +//CHECK-SAME: %[[ARG0:.*]]: !fir.ref}>>>) + %out = fir.call @test_t4() : () -> !t4 + fir.store %out to %arg0 : !fir.ref + return + //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr + //CHECK: %[[ARG:.*]] = fir.alloca !fir.type}>> + //CHECK: fir.call @test_t4(%[[ARG]]) : (!fir.ref}>>>) -> () + + //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref}>>>) -> !fir.ref}>>> + //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref}>>> + //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr + //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref}>>> + //CHECK: return +} + +// mixed types +!t5 = !fir.type,r:f32,i:i64}>> +func.func private @test_t5() -> !t5 +//CHECK-LABEL: func.func private @test_t5(!fir.ref,r:f32,i:i64}>>> {llvm.align = 8 : i32, llvm.sret = !fir.type,r:f32,i:i64}>>}) +func.func @test_call_t5(%arg0 : !fir.ref) { +//CHECK-LABEL: func.func @test_call_t5( +//CHECK-SAME: %[[ARG0:.*]]: !fir.ref,r:f32,i:i64}>>>) + %out = fir.call @test_t5() : () -> !t5 + fir.store %out to %arg0 : !fir.ref + return + //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr + //CHECK: %[[ARG:.*]] = fir.alloca !fir.type,r:f32,i:i64}>> + //CHECK: fir.call @test_t5(%[[ARG]]) : (!fir.ref,r:f32,i:i64}>>>) -> () + + //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref,r:f32,i:i64}>>>) -> !fir.ref,r:f32,i:i64}>>> + //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref,r:f32,i:i64}>>> + //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr + //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref,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}> +func.func private @test_t1() -> !t1 +//CHECK-LABEL: func.func private @test_t1(!fir.ref}>> {llvm.align = 8 : i32, llvm.sret = !fir.type}>}) +func.func @test_call_t1(%arg0 : !fir.ref) { +//CHECK-LABEL: func.func @test_call_t1( +//CHECK-SAME: %[[ARG0:.*]]: !fir.ref}>>) + %out = fir.call @test_t1() : () -> !t1 + fir.store %out to %arg0 : !fir.ref + return + //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr + //CHECK: %[[ARG:.*]] = fir.alloca !fir.type}> + //CHECK: fir.call @test_t1(%[[ARG]]) : (!fir.ref}>>) -> () + + //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref}>>) -> !fir.ref}>> + //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref}>> + //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr + //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref}>> + //CHECK: return +} + +// integer type +!t2 = !fir.type +func.func private @test_t2() -> !t2 +//CHECK-LABEL: func.func private @test_t2(!fir.ref> {llvm.align = 8 : i32, llvm.sret = !fir.type}) +func.func @test_call_t2(%arg0 : !fir.ref) { +//CHECK-LABEL: func.func @test_call_t2( +//CHECK-SAME: %[[ARG0:.*]]: !fir.ref>) + %out = fir.call @test_t2() : () -> !t2 + fir.store %out to %arg0 : !fir.ref + return + //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr + //CHECK: %[[ARG:.*]] = fir.alloca !fir.type + //CHECK: fir.call @test_t2(%[[ARG]]) : (!fir.ref>) -> () + + //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref>) -> !fir.ref> + //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref> + //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr + //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref> + //CHECK: return +} + +// real type (scalar) +!t3 = !fir.type +func.func private @test_t3() -> !t3 +//CHECK-LABEL: func.func private @test_t3() -> !fir.array<3xf32> +func.func @test_call_t3(%arg0 : !fir.ref) { +//CHECK-LABEL: func.func @test_call_t3( +//CHECK-SAME: %[[ARG0:.*]]: !fir.ref>) + %out = fir.call @test_t3() : () -> !t3 + fir.store %out to %arg0 : !fir.ref + 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> + //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref>) -> !fir.ref> + //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref> + //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr + //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref> + //CHECK: return +} + +// real type (> 8 floats) +!t4 = !fir.type}> +func.func private @test_t4() -> !t4 +//CHECK-LABEL: func.func private @test_t4(!fir.ref}>> {llvm.align = 8 : i32, llvm.sret = !fir.type}>}) +func.func @test_call_t4(%arg0 : !fir.ref) { +//CHECK-LABEL: func.func @test_call_t4( +//CHECK-SAME: %[[ARG0:.*]]: !fir.ref}>>) + %out = fir.call @test_t4() : () -> !t4 + fir.store %out to %arg0 : !fir.ref + return + //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr + //CHECK: %[[ARG:.*]] = fir.alloca !fir.type}> + //CHECK: fir.call @test_t4(%[[ARG]]) : (!fir.ref}>>) -> () + //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref}>>) -> !fir.ref}>> + //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref}>> + //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr + //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref}>> + //CHECK: return +} + +// mixed types +!t5 = !fir.type,r:f32,i:i64}> +func.func private @test_t5() -> !t5 +//CHECK-LABEL: func.func private @test_t5(!fir.ref,r:f32,i:i64}>> {llvm.align = 8 : i32, llvm.sret = !fir.type,r:f32,i:i64}>}) +func.func @test_call_t5(%arg0 : !fir.ref) { +//CHECK-LABEL: func.func @test_call_t5( +//CHECK-SAME: %[[ARG0:.*]]: !fir.ref,r:f32,i:i64}>>) + %out = fir.call @test_t5() : () -> !t5 + fir.store %out to %arg0 : !fir.ref + return + //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr + //CHECK: %[[ARG:.*]] = fir.alloca !fir.type,r:f32,i:i64}> + //CHECK: fir.call @test_t5(%[[ARG]]) : (!fir.ref,r:f32,i:i64}>>) -> () + //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref,r:f32,i:i64}>>) -> !fir.ref,r:f32,i:i64}>> + //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref,r:f32,i:i64}>> + //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr + //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref,r:f32,i:i64}>> + //CHECK: return +} From 435543bbf246566b4c8de33973e3bc8d802f3fdf Mon Sep 17 00:00:00 2001 From: Kelvin Li 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 { unsigned short align{ std::max(sizeAndAlign.second, static_cast(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,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}>,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}>> -func.func private @test_t1() -> !t1 +func.func private @test_t1() -> !fir.type}>> //CHECK-LABEL: func.func private @test_t1(!fir.ref}>>> {llvm.align = 8 : i32, llvm.sret = !fir.type}>>}) -func.func @test_call_t1(%arg0 : !fir.ref) { +func.func @test_call_t1(%arg0 : !fir.ref}>>>) { //CHECK-LABEL: func.func @test_call_t1( //CHECK-SAME: %[[ARG0:.*]]: !fir.ref}>>>) - %out = fir.call @test_t1() : () -> !t1 - fir.store %out to %arg0 : !fir.ref + %out = fir.call @test_t1() : () -> !fir.type}>> + fir.store %out to %arg0 : !fir.ref}>>> return //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr //CHECK: %[[ARG:.*]] = fir.alloca !fir.type}>> //CHECK: fir.call @test_t1(%[[ARG]]) : (!fir.ref}>>>) -> () - //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref}>>>) -> !fir.ref}>>> //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref}>>> //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr @@ -25,19 +24,17 @@ func.func @test_call_t1(%arg0 : !fir.ref) { } // integer type -!t2 = !fir.type> -func.func private @test_t2() -> !t2 +func.func private @test_t2() -> !fir.type> //CHECK-LABEL: func.func private @test_t2(!fir.ref>> {llvm.align = 8 : i32, llvm.sret = !fir.type>}) -func.func @test_call_t2(%arg0 : !fir.ref) { +func.func @test_call_t2(%arg0 : !fir.ref>>) { //CHECK-LABEL: func.func @test_call_t2( //CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>) - %out = fir.call @test_t2() : () -> !t2 - fir.store %out to %arg0 : !fir.ref + %out = fir.call @test_t2() : () -> !fir.type> + fir.store %out to %arg0 : !fir.ref>> return //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr //CHECK: %[[ARG:.*]] = fir.alloca !fir.type> //CHECK: fir.call @test_t2(%[[ARG]]) : (!fir.ref>>) -> () - //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref>>) -> !fir.ref>> //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref>> //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr @@ -46,19 +43,17 @@ func.func @test_call_t2(%arg0 : !fir.ref) { } // real type (scalar) -!t3 = !fir.type> -func.func private @test_t3() -> !t3 +func.func private @test_t3() -> !fir.type> //CHECK-LABEL: func.func private @test_t3(!fir.ref>> {llvm.align = 8 : i32, llvm.sret = !fir.type>}) -func.func @test_call_t3(%arg0 : !fir.ref) { +func.func @test_call_t3(%arg0 : !fir.ref>>) { //CHECK-LABEL: func.func @test_call_t3( //CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>) - %out = fir.call @test_t3() : () -> !t3 - fir.store %out to %arg0 : !fir.ref + %out = fir.call @test_t3() : () -> !fir.type> + fir.store %out to %arg0 : !fir.ref>> return //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr //CHECK: %[[ARG:.*]] = fir.alloca !fir.type> //CHECK: fir.call @test_t3(%[[ARG]]) : (!fir.ref>>) -> () - //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref>>) -> !fir.ref>> //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref>> //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr @@ -67,19 +62,17 @@ func.func @test_call_t3(%arg0 : !fir.ref) { } // real type (array) -!t4 = !fir.type}>> -func.func private @test_t4() -> !t4 +func.func private @test_t4() -> !fir.type}>> //CHECK-LABEL: func.func private @test_t4(!fir.ref}>>> {llvm.align = 8 : i32, llvm.sret = !fir.type}>>}) -func.func @test_call_t4(%arg0 : !fir.ref) { +func.func @test_call_t4(%arg0 : !fir.ref}>>>) { //CHECK-LABEL: func.func @test_call_t4( //CHECK-SAME: %[[ARG0:.*]]: !fir.ref}>>>) - %out = fir.call @test_t4() : () -> !t4 - fir.store %out to %arg0 : !fir.ref + %out = fir.call @test_t4() : () -> !fir.type}>> + fir.store %out to %arg0 : !fir.ref}>>> return //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr //CHECK: %[[ARG:.*]] = fir.alloca !fir.type}>> //CHECK: fir.call @test_t4(%[[ARG]]) : (!fir.ref}>>>) -> () - //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref}>>>) -> !fir.ref}>>> //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref}>>> //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr @@ -88,22 +81,22 @@ func.func @test_call_t4(%arg0 : !fir.ref) { } // mixed types -!t5 = !fir.type,r:f32,i:i64}>> -func.func private @test_t5() -> !t5 +func.func private @test_t5() -> !fir.type,r:f32,i:i64}>> //CHECK-LABEL: func.func private @test_t5(!fir.ref,r:f32,i:i64}>>> {llvm.align = 8 : i32, llvm.sret = !fir.type,r:f32,i:i64}>>}) -func.func @test_call_t5(%arg0 : !fir.ref) { +func.func @test_call_t5(%arg0 : !fir.ref,r:f32,i:i64}>>>) { //CHECK-LABEL: func.func @test_call_t5( //CHECK-SAME: %[[ARG0:.*]]: !fir.ref,r:f32,i:i64}>>>) - %out = fir.call @test_t5() : () -> !t5 - fir.store %out to %arg0 : !fir.ref + %out = fir.call @test_t5() : () -> !fir.type,r:f32,i:i64}>> + fir.store %out to %arg0 : !fir.ref,r:f32,i:i64}>>> return //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr //CHECK: %[[ARG:.*]] = fir.alloca !fir.type,r:f32,i:i64}>> //CHECK: fir.call @test_t5(%[[ARG]]) : (!fir.ref,r:f32,i:i64}>>>) -> () - //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref,r:f32,i:i64}>>>) -> !fir.ref,r:f32,i:i64}>>> //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref,r:f32,i:i64}>>> //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref,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}> -func.func private @test_t1() -> !t1 +func.func private @test_t1() -> !fir.type}> //CHECK-LABEL: func.func private @test_t1(!fir.ref}>> {llvm.align = 8 : i32, llvm.sret = !fir.type}>}) -func.func @test_call_t1(%arg0 : !fir.ref) { +func.func @test_call_t1(%arg0 : !fir.ref}>>) { //CHECK-LABEL: func.func @test_call_t1( //CHECK-SAME: %[[ARG0:.*]]: !fir.ref}>>) - %out = fir.call @test_t1() : () -> !t1 - fir.store %out to %arg0 : !fir.ref + %out = fir.call @test_t1() : () -> !fir.type}> + fir.store %out to %arg0 : !fir.ref}>> return //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr //CHECK: %[[ARG:.*]] = fir.alloca !fir.type}> //CHECK: fir.call @test_t1(%[[ARG]]) : (!fir.ref}>>) -> () - //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref}>>) -> !fir.ref}>> //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref}>> //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr @@ -25,19 +24,17 @@ func.func @test_call_t1(%arg0 : !fir.ref) { } // integer type -!t2 = !fir.type -func.func private @test_t2() -> !t2 +func.func private @test_t2() -> !fir.type //CHECK-LABEL: func.func private @test_t2(!fir.ref> {llvm.align = 8 : i32, llvm.sret = !fir.type}) -func.func @test_call_t2(%arg0 : !fir.ref) { +func.func @test_call_t2(%arg0 : !fir.ref>) { //CHECK-LABEL: func.func @test_call_t2( //CHECK-SAME: %[[ARG0:.*]]: !fir.ref>) - %out = fir.call @test_t2() : () -> !t2 - fir.store %out to %arg0 : !fir.ref + %out = fir.call @test_t2() : () -> !fir.type + fir.store %out to %arg0 : !fir.ref> return //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr //CHECK: %[[ARG:.*]] = fir.alloca !fir.type //CHECK: fir.call @test_t2(%[[ARG]]) : (!fir.ref>) -> () - //CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref>) -> !fir.ref> //CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref> //CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr @@ -46,14 +43,13 @@ func.func @test_call_t2(%arg0 : !fir.ref) { } // real type (scalar) -!t3 = !fir.type -func.func private @test_t3() -> !t3 +func.func private @test_t3() -> !fir.type //CHECK-LABEL: func.func private @test_t3() -> !fir.array<3xf32> -func.func @test_call_t3(%arg0 : !fir.ref) { +func.func @test_call_t3(%arg0 : !fir.ref>) { //CHECK-LABEL: func.func @test_call_t3( //CHECK-SAME: %[[ARG0:.*]]: !fir.ref>) - %out = fir.call @test_t3() : () -> !t3 - fir.store %out to %arg0 : !fir.ref + %out = fir.call @test_t3() : () -> !fir.type + fir.store %out to %arg0 : !fir.ref> 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) { } // real type (> 8 floats) -!t4 = !fir.type}> -func.func private @test_t4() -> !t4 +func.func private @test_t4() -> !fir.type}> //CHECK-LABEL: func.func private @test_t4(!fir.ref}>> {llvm.align = 8 : i32, llvm.sret = !fir.type}>}) -func.func @test_call_t4(%arg0 : !fir.ref) { +func.func @test_call_t4(%arg0 : !fir.ref}>>) { //CHECK-LABEL: func.func @test_call_t4( //CHECK-SAME: %[[ARG0:.*]]: !fir.ref}>>) - %out = fir.call @test_t4() : () -> !t4 - fir.store %out to %arg0 : !fir.ref + %out = fir.call @test_t4() : () -> !fir.type}> + fir.store %out to %arg0 : !fir.ref}>> return //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr //CHECK: %[[ARG:.*]] = fir.alloca !fir.type}> @@ -87,14 +82,13 @@ func.func @test_call_t4(%arg0 : !fir.ref) { } // mixed types -!t5 = !fir.type,r:f32,i:i64}> -func.func private @test_t5() -> !t5 +func.func private @test_t5() -> !fir.type,r:f32,i:i64}> //CHECK-LABEL: func.func private @test_t5(!fir.ref,r:f32,i:i64}>> {llvm.align = 8 : i32, llvm.sret = !fir.type,r:f32,i:i64}>}) -func.func @test_call_t5(%arg0 : !fir.ref) { +func.func @test_call_t5(%arg0 : !fir.ref,r:f32,i:i64}>>) { //CHECK-LABEL: func.func @test_call_t5( //CHECK-SAME: %[[ARG0:.*]]: !fir.ref,r:f32,i:i64}>>) - %out = fir.call @test_t5() : () -> !t5 - fir.store %out to %arg0 : !fir.ref + %out = fir.call @test_t5() : () -> !fir.type,r:f32,i:i64}> + fir.store %out to %arg0 : !fir.ref,r:f32,i:i64}>> return //CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr //CHECK: %[[ARG:.*]] = fir.alloca !fir.type,r:f32,i:i64}> @@ -105,3 +99,5 @@ func.func @test_call_t5(%arg0 : !fir.ref) { //CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref,r:f32,i:i64}>> //CHECK: return } + +}