[flang-commits] [flang] [flang][CodeGen] Add initial SystemZ ABI support (PR #208618)
via flang-commits
flang-commits at lists.llvm.org
Thu Jul 9 21:27:35 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-openmp
Author: anoopkg6
<details>
<summary>Changes</summary>
Add initial implementation to enable target-specific code generation and rewriting support for SystemZ architecture in Flang.
@<!-- -->uweigand @<!-- -->dominik-steenken
---
Patch is 46.84 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/208618.diff
16 Files Affected:
- (modified) flang/lib/Frontend/CompilerInvocation.cpp (+6)
- (modified) flang/lib/Optimizer/CodeGen/Target.cpp (+79)
- (added) flang/test/Driver/code-gen-systemz.f90 (+9)
- (added) flang/test/Driver/emit-asm-systemz.f90 (+11)
- (added) flang/test/Driver/predefined-macros-systemz.f90 (+23)
- (added) flang/test/Fir/struct-passing-systemz-byval.fir (+51)
- (added) flang/test/Fir/struct-return-systemz.fir (+63)
- (modified) flang/test/Fir/target-rewrite-boxchar.fir (+1)
- (modified) flang/test/Fir/target-rewrite-char-proc.fir (+1)
- (modified) flang/test/Fir/target-rewrite-complex.fir (+83)
- (added) flang/test/Fir/target-rewrite-complex16-systemz.fir (+69)
- (modified) flang/test/Fir/target-rewrite-indirect-calls.fir (+1)
- (modified) flang/test/Fir/target-rewrite-integer.fir (+18)
- (modified) flang/test/Fir/target-rewrite-selective.fir (+7)
- (added) flang/test/Lower/OpenMP/simd_systemz.f90 (+16)
- (added) flang/test/Semantics/realkinds-systemz-01.f90 (+12)
``````````diff
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 79ad08353b64c..339b83f351152 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -1899,6 +1899,12 @@ void CompilerInvocation::setDefaultPredefinitions() {
fortranOptions.predefinitions.emplace_back("__aarch64__", "1");
fortranOptions.predefinitions.emplace_back("__aarch64", "1");
break;
+ case llvm::Triple::ArchType::systemz:
+ fortranOptions.predefinitions.emplace_back("__s390__", "1");
+ fortranOptions.predefinitions.emplace_back("__s390x__", "1");
+ fortranOptions.predefinitions.emplace_back("__s390x", "1");
+ fortranOptions.predefinitions.emplace_back("__zarch__", "1");
+ break;
}
}
diff --git a/flang/lib/Optimizer/CodeGen/Target.cpp b/flang/lib/Optimizer/CodeGen/Target.cpp
index 48946d78d900c..37838e9e2e558 100644
--- a/flang/lib/Optimizer/CodeGen/Target.cpp
+++ b/flang/lib/Optimizer/CodeGen/Target.cpp
@@ -1893,6 +1893,81 @@ struct TargetLoongArch64 : public GenericTarget<TargetLoongArch64> {
};
} // namespace
+//===----------------------------------------------------------------------===//
+// SystemZ target specifics.
+//===----------------------------------------------------------------------===//
+
+namespace {
+struct TargetSystemZ : public GenericTarget<TargetSystemZ> {
+ using GenericTarget::GenericTarget;
+
+ static constexpr int defaultWidth = 64;
+
+ auto complexType(mlir::Type eleTy, bool isResult) const {
+ assert(fir::isa_real(eleTy));
+ CodeGenSpecifics::Marshalling marshal;
+ unsigned short align{std::max(
+ static_cast<unsigned short>(getDataLayout().getTypeABIAlignment(eleTy)),
+ static_cast<unsigned short>(8))};
+ marshal.emplace_back(
+ fir::ReferenceType::get(mlir::TupleType::get(
+ eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})),
+ AT{/*align=*/align, /*byval=*/!isResult, /*sret=*/isResult});
+ return marshal;
+ }
+
+ CodeGenSpecifics::Marshalling
+ complexArgumentType(mlir::Location /*loc*/, mlir::Type eleTy) const override {
+ return complexType(eleTy, false);
+ }
+
+ CodeGenSpecifics::Marshalling
+ complexReturnType(mlir::Location /*loc*/, mlir::Type eleTy) const override {
+ return complexType(eleTy, true);
+ }
+
+ CodeGenSpecifics::Marshalling
+ integerArgumentType(mlir::Location loc,
+ mlir::IntegerType argTy) const override {
+ if (argTy.getWidth() == 32) {
+ AT::IntegerExtension intExt = argTy.isUnsigned()
+ ? AT::IntegerExtension::Zero
+ : AT::IntegerExtension::Sign;
+ CodeGenSpecifics::Marshalling marshal;
+ marshal.emplace_back(argTy, AT{/*alignment=*/0, /*byval=*/false,
+ /*sret=*/false, /*append=*/false,
+ /*intExt=*/intExt});
+ return marshal;
+ }
+ return GenericTarget::integerArgumentType(loc, argTy);
+ }
+
+ 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=*/align, /*byval=*/!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
+
// Instantiate the overloaded target instance based on the triple value.
// TODO: Add other targets to this file as needed.
std::unique_ptr<fir::CodeGenSpecifics> fir::CodeGenSpecifics::get(
@@ -1960,6 +2035,10 @@ std::unique_ptr<fir::CodeGenSpecifics> fir::CodeGenSpecifics::get(
return std::make_unique<TargetLoongArch64>(ctx, std::move(trp),
std::move(kindMap), targetCPU,
targetFeatures, targetABI, dl);
+ case llvm::Triple::ArchType::systemz:
+ return std::make_unique<TargetSystemZ>(ctx, std::move(trp),
+ std::move(kindMap), targetCPU,
+ targetFeatures, targetABI, dl);
}
TODO(mlir::UnknownLoc::get(ctx), "target not implemented");
}
diff --git a/flang/test/Driver/code-gen-systemz.f90 b/flang/test/Driver/code-gen-systemz.f90
new file mode 100644
index 0000000000000..8344fe9e7929b
--- /dev/null
+++ b/flang/test/Driver/code-gen-systemz.f90
@@ -0,0 +1,9 @@
+! Test -emit-obj for SystemZ (s390x)
+
+! REQUIRES: systemz-registered-target
+
+! RUN: %flang_fc1 -triple s390x-unknown-linux-gnu -emit-obj %s -o - | \
+! RUN: llvm-readobj -h - | FileCheck %s
+
+! CHECK: Arch: s390x
+end program
diff --git a/flang/test/Driver/emit-asm-systemz.f90 b/flang/test/Driver/emit-asm-systemz.f90
new file mode 100644
index 0000000000000..af0e250b54e85
--- /dev/null
+++ b/flang/test/Driver/emit-asm-systemz.f90
@@ -0,0 +1,11 @@
+! Test -S (SystemZ)
+
+! REQUIRES: systemz-registered-target
+
+! RUN: %flang_fc1 -S -triple s390x-unknown-linux-gnu %s -o - | FileCheck %s
+! RUN: %flang -S -target s390x-unknown-linux-gnu %s -o - | FileCheck %s
+
+! CHECK-LABEL: _QQmain:
+! CHECK: br %r14
+
+end program
diff --git a/flang/test/Driver/predefined-macros-systemz.f90 b/flang/test/Driver/predefined-macros-systemz.f90
new file mode 100644
index 0000000000000..4babe8bcba3d8
--- /dev/null
+++ b/flang/test/Driver/predefined-macros-systemz.f90
@@ -0,0 +1,23 @@
+! Test predefined macros for SystemZ architecture
+! REQUIRES: systemz-registered-target
+
+! RUN: %flang_fc1 -triple s390x-unknown-linux-gnu -cpp -E %s | FileCheck %s
+
+! CHECK: integer :: var1 = 1
+! CHECK: integer :: var2 = 1
+! CHECK: integer :: var3 = 1
+! CHECK: integer :: var4 = 1
+
+#if __s390__
+ integer :: var1 = __s390__
+#endif
+#if __s390x__
+ integer :: var2 = __s390x__
+#endif
+#if __s390x
+ integer :: var3 = __s390x
+#endif
+#if __zarch__
+ integer :: var4 = __zarch__
+#endif
+end program
diff --git a/flang/test/Fir/struct-passing-systemz-byval.fir b/flang/test/Fir/struct-passing-systemz-byval.fir
new file mode 100644
index 0000000000000..3fc35e4f16b60
--- /dev/null
+++ b/flang/test/Fir/struct-passing-systemz-byval.fir
@@ -0,0 +1,51 @@
+// Test SystemZ ABI rewrite of struct passed by value (BIND(C), VALUE derived types).
+// RUN: fir-opt --target-rewrite="target=s390x-unknown-linux-gnu" %s | FileCheck %s
+
+module attributes {
+ fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:128-v128:64-a:8:16-n32:64", llvm.target_triple = "s390x-unknown-linux-gnu" } {
+
+// CHECK-LABEL: func.func private @test_i32(!fir.ref<!fir.type<t1{i:i32}>>
+// CHECK-SAME: {llvm.align = 8 : i32, llvm.byval = !fir.type<t1{i:i32}>})
+func.func private @test_i32(%arg0: !fir.type<t1{i:i32}>)
+
+// CHECK-LABEL: func.func @test_call_i32(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<t1{i:i32}>>) {
+// CHECK: %[[IN:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.type<t1{i:i32}>>
+// CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
+// CHECK: %[[TMP:.*]] = fir.alloca !fir.type<t1{i:i32}>
+// CHECK: fir.store %[[IN]] to %[[TMP]] : !fir.ref<!fir.type<t1{i:i32}>>
+// CHECK: fir.call @test_i32(%[[TMP]]) : (!fir.ref<!fir.type<t1{i:i32}>> {llvm.align = 8 : i32, llvm.byval = !fir.type<t1{i:i32}>}) -> ()
+// CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr
+// CHECK: return
+func.func @test_call_i32(%arg0: !fir.ref<!fir.type<t1{i:i32}>>) {
+ %in = fir.load %arg0 : !fir.ref<!fir.type<t1{i:i32}>>
+ fir.call @test_i32(%in) : (!fir.type<t1{i:i32}>) -> ()
+ return
+}
+
+// CHECK-LABEL: func.func private @test_i64(!fir.ref<!fir.type<t2{i:i64}>>
+// CHECK-SAME: {llvm.align = 8 : i32, llvm.byval = !fir.type<t2{i:i64}>})
+func.func private @test_i64(%arg0: !fir.type<t2{i:i64}>)
+
+// CHECK-LABEL: func.func private @test_f32_f32(!fir.ref<!fir.type<t3{r:f32,i:f32}>>
+// CHECK-SAME: {llvm.align = 8 : i32, llvm.byval = !fir.type<t3{r:f32,i:f32}>})
+func.func private @test_f32_f32(%arg0: !fir.type<t3{r:f32,i:f32}>)
+
+// CHECK-LABEL: func.func private @test_f64_f64(!fir.ref<!fir.type<t4{r:f64,i:f64}>>
+// CHECK-SAME: {llvm.align = 8 : i32, llvm.byval = !fir.type<t4{r:f64,i:f64}>})
+func.func private @test_f64_f64(%arg0: !fir.type<t4{r:f64,i:f64}>)
+
+// CHECK-LABEL: func.func private @test_large(!fir.ref<!fir.type<t5{i:!fir.array<8xi32>}>>
+// CHECK-SAME: {llvm.align = 8 : i32, llvm.byval = !fir.type<t5{i:!fir.array<8xi32>}>})
+func.func private @test_large(%arg0: !fir.type<t5{i:!fir.array<8xi32>}>)
+
+// CHECK-LABEL: func.func private @test_mixed(!fir.ref<!fir.type<t6{i:i32,r:f64}>>
+// CHECK-SAME: {llvm.align = 8 : i32, llvm.byval = !fir.type<t6{i:i32,r:f64}>})
+func.func private @test_mixed(%arg0: !fir.type<t6{i:i32,r:f64}>)
+
+// Struct with f128 field — alignment is 16, not clamped down to 8.
+// CHECK-LABEL: func.func private @test_f128(!fir.ref<!fir.type<t7{r:f128}>>
+// CHECK-SAME: {llvm.align = 16 : i32, llvm.byval = !fir.type<t7{r:f128}>})
+func.func private @test_f128(%arg0: !fir.type<t7{r:f128}>)
+
+} // end module
diff --git a/flang/test/Fir/struct-return-systemz.fir b/flang/test/Fir/struct-return-systemz.fir
new file mode 100644
index 0000000000000..d8caac40fbdb3
--- /dev/null
+++ b/flang/test/Fir/struct-return-systemz.fir
@@ -0,0 +1,63 @@
+// Test SystemZ ABI rewrite of struct returned by value (BIND(C), VALUE derived types).
+// RUN: fir-opt --target-rewrite="target=s390x-unknown-linux-gnu" %s | FileCheck %s
+
+module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:128-v128:64-a:8:16-n32:64", llvm.target_triple = "s390x-unknown-linux-gnu"} {
+
+// CHECK-LABEL: func.func private @test_i32(!fir.ref<!fir.type<t1{i:i32}>>
+// CHECK-SAME: {llvm.align = 8 : i32, llvm.sret = !fir.type<t1{i:i32}>})
+func.func private @test_i32() -> !fir.type<t1{i:i32}>
+
+// CHECK-LABEL: func.func @test_call_i32(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<t1{i:i32}>>)
+func.func @test_call_i32(%arg0 : !fir.ref<!fir.type<t1{i:i32}>>) {
+ // CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
+ // CHECK: %[[ARG:.*]] = fir.alloca !fir.type<t1{i:i32}>
+ // CHECK: fir.call @test_i32(%[[ARG]]) : (!fir.ref<!fir.type<t1{i:i32}>> {llvm.align = 8 : i32, llvm.sret = !fir.type<t1{i:i32}>}) -> ()
+ // CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref<!fir.type<t1{i:i32}>>) -> !fir.ref<!fir.type<t1{i:i32}>>
+ // CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref<!fir.type<t1{i:i32}>>
+ // CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr
+ // CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref<!fir.type<t1{i:i32}>>
+ // CHECK: return
+ %out = fir.call @test_i32() : () -> !fir.type<t1{i:i32}>
+ fir.store %out to %arg0 : !fir.ref<!fir.type<t1{i:i32}>>
+ return
+}
+
+// CHECK-LABEL: func.func private @test_i64(!fir.ref<!fir.type<t2{i:i64}>>
+// CHECK-SAME: {llvm.align = 8 : i32, llvm.sret = !fir.type<t2{i:i64}>})
+func.func private @test_i64() -> !fir.type<t2{i:i64}>
+
+// CHECK-LABEL: func.func @test_call_i64(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<t2{i:i64}>>)
+func.func @test_call_i64(%arg0 : !fir.ref<!fir.type<t2{i:i64}>>) {
+ // CHECK: %[[STCK:.*]] = llvm.intr.stacksave : !llvm.ptr
+ // CHECK: %[[ARG:.*]] = fir.alloca !fir.type<t2{i:i64}>
+ // CHECK: fir.call @test_i64(%[[ARG]]) : (!fir.ref<!fir.type<t2{i:i64}>> {llvm.align = 8 : i32, llvm.sret = !fir.type<t2{i:i64}>}) -> ()
+ // CHECK: %[[CVT:.*]] = fir.convert %[[ARG]] : (!fir.ref<!fir.type<t2{i:i64}>>) -> !fir.ref<!fir.type<t2{i:i64}>>
+ // CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref<!fir.type<t2{i:i64}>>
+ // CHECK: llvm.intr.stackrestore %[[STCK]] : !llvm.ptr
+ // CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref<!fir.type<t2{i:i64}>>
+ // CHECK: return
+ %out = fir.call @test_i64() : () -> !fir.type<t2{i:i64}>
+ fir.store %out to %arg0 : !fir.ref<!fir.type<t2{i:i64}>>
+ return
+}
+
+// CHECK-LABEL: func.func private @test_f32_f32(!fir.ref<!fir.type<t3{r:f32,i:f32}>>
+// CHECK-SAME: {llvm.align = 8 : i32, llvm.sret = !fir.type<t3{r:f32,i:f32}>})
+func.func private @test_f32_f32() -> !fir.type<t3{r:f32,i:f32}>
+
+// CHECK-LABEL: func.func private @test_f64_f64(!fir.ref<!fir.type<t4{r:f64,i:f64}>>
+// CHECK-SAME: {llvm.align = 8 : i32, llvm.sret = !fir.type<t4{r:f64,i:f64}>})
+func.func private @test_f64_f64() -> !fir.type<t4{r:f64,i:f64}>
+
+// CHECK-LABEL: func.func private @test_large(!fir.ref<!fir.type<t5{i:!fir.array<8xi32>}>>
+// CHECK-SAME: {llvm.align = 8 : i32, llvm.sret = !fir.type<t5{i:!fir.array<8xi32>}>})
+func.func private @test_large() -> !fir.type<t5{i:!fir.array<8xi32>}>
+
+// Struct with f128 field — alignment is 16, not clamped down to 8.
+// CHECK-LABEL: func.func private @test_f128(!fir.ref<!fir.type<t7{r:f128}>>
+// CHECK-SAME: {llvm.align = 16 : i32, llvm.sret = !fir.type<t7{r:f128}>})
+func.func private @test_f128() -> !fir.type<t7{r:f128}>
+
+} // end module
diff --git a/flang/test/Fir/target-rewrite-boxchar.fir b/flang/test/Fir/target-rewrite-boxchar.fir
index 681536cde6a05..228ee7a367b71 100644
--- a/flang/test/Fir/target-rewrite-boxchar.fir
+++ b/flang/test/Fir/target-rewrite-boxchar.fir
@@ -5,6 +5,7 @@
// RUN: fir-opt --target-rewrite="target=amdgcn-amd-amdhsa" %s | FileCheck %s --check-prefix=INT64
// RUN: fir-opt --target-rewrite="target=nvptx64-nvidia-cuda" %s | FileCheck %s --check-prefix=INT64
// RUN: fir-opt --target-rewrite="target=loongarch64-unknown-linux-gnu" %s | FileCheck %s --check-prefix=INT64
+// RUN: fir-opt --target-rewrite="target=s390x-unknown-linux-gnu" %s | FileCheck %s --check-prefix=INT64
// Test that we rewrite the signatures and bodies of functions that take boxchar
// parameters.
diff --git a/flang/test/Fir/target-rewrite-char-proc.fir b/flang/test/Fir/target-rewrite-char-proc.fir
index ccb1fc06f6f0d..62655cd081c53 100644
--- a/flang/test/Fir/target-rewrite-char-proc.fir
+++ b/flang/test/Fir/target-rewrite-char-proc.fir
@@ -2,6 +2,7 @@
// arguments: one for the function address, and one for the length. The length
// argument is added after other characters.
// RUN: fir-opt --target-rewrite="target=x86_64-unknown-linux-gnu" %s | FileCheck %s
+// RUN: fir-opt --target-rewrite="target=s390x-unknown-linux-gnu" %s | FileCheck %s
// CHECK: func private @takes_char_proc(() -> () {fir.char_proc}, i64)
func.func private @takes_char_proc(tuple<() -> (), i64> {fir.char_proc})
diff --git a/flang/test/Fir/target-rewrite-complex.fir b/flang/test/Fir/target-rewrite-complex.fir
index c8cf867713632..9b0d0464d88d6 100644
--- a/flang/test/Fir/target-rewrite-complex.fir
+++ b/flang/test/Fir/target-rewrite-complex.fir
@@ -10,6 +10,7 @@
// RUN: fir-opt --target-rewrite="target=powerpc64-ibm-aix7.2.0.0" %s | FileCheck %s --check-prefix=PPC64
// RUN: fir-opt --target-rewrite="target=powerpc-ibm-aix7.2.0.0" %s | FileCheck %s --check-prefix=PPC
// RUN: fir-opt --target-rewrite="target=loongarch64-unknown-linux-gnu" %s | FileCheck %s --check-prefix=LOONGARCH64
+// RUN: fir-opt --target-rewrite="target=s390x-unknown-linux-gnu" %s | FileCheck %s --check-prefix=SYSTEMZ
// Test that we rewrite the signature and body of a function that returns a
// complex<4>.
@@ -24,6 +25,8 @@
// PPC64-LABEL: func @returncomplex4() -> tuple<f32, f32>
// PPC-LABEL: func @returncomplex4() -> tuple<f32, f32>
// LOONGARCH64-LABEL: func @returncomplex4() -> tuple<f32, f32>
+// SYSTEMZ-LABEL: func @returncomplex4
+// SYSTEMZ-SAME: ([[ARG0:%[0-9A-Za-z]+]]: !fir.ref<tuple<f32, f32>> {llvm.align = 8 : i32, llvm.sret = tuple<f32, f32>})
func.func @returncomplex4() -> complex<f32> {
// I32: fir.insert_value
// I32: [[VAL:%[0-9A-Za-z]+]] = fir.insert_value
@@ -47,6 +50,8 @@ func.func @returncomplex4() -> complex<f32> {
// PPC: [[VAL:%[0-9A-Za-z]+]] = fir.insert_value
// LOONGARCH64: fir.insert_value
// LOONGARCH64: [[VAL:%[0-9A-Za-z]+]] = fir.insert_value
+ // SYSTEMZ: fir.insert_value
+ // SYSTEMZ: [[VAL:%[0-9A-Za-z]+]] = fir.insert_value
%1 = fir.undefined complex<f32>
%2 = arith.constant 2.0 : f32
%3 = fir.convert %2 : (f32) -> f32
@@ -105,6 +110,9 @@ func.func @returncomplex4() -> complex<f32> {
// PPC: return [[RES]] : tuple<f32, f32>
// LOONGARCH64: [[ADDRT:%[0-9A-Za-z]+]] = fir.alloca tuple<f32, f32>
// LOONGARCH64: [[ADDRC:%[0-9A-Za-z]+]] = fir.convert [[ADDRT]] : (!fir.ref<tuple<f32, f32>>) -> !fir.ref<complex<f32>>
+ // SYSTEMZ: [[ADDR:%[0-9A-Za-z]+]] = fir.convert [[ARG0]] : (!fir.ref<tuple<f32, f32>>) -> !fir.ref<complex<f32>>
+ // SYSTEMZ: fir.store [[VAL]] to [[ADDR]] : !fir.ref<complex<f32>>
+ // SYSTEMZ: return
return %6 : complex<f32>
}
@@ -124,6 +132,8 @@ func.func @returncomplex4() -> complex<f32> {
// PPC64-LABEL: func @returncomplex8() -> tuple<f64, f64>
// PPC-LABEL: func @returncomplex8() -> tuple<f64, f64>
// LOONGARCH64-LABEL: func @returncomplex8() -> tuple<f64, f64>
+// SYSTEMZ-LABEL: func @returncomplex8
+// SYSTEMZ-SAME: ([[ARG0:%[0-9A-Za-z]+]]: !fir.ref<tuple<f64, f64>> {llvm.align = 8 : i32, llvm.sret = tuple<f64, f64>})
func.func @returncomplex8() -> complex<f64> {
// I32: fir.insert_value
// I32: [[VAL:%[0-9A-Za-z]+]] = fir.insert_value {{.*}}
@@ -147,6 +157,8 @@ func.func @returncomplex8() -> complex<f64> {
// PPC: [[VAL:%[0-9A-Za-z]+]] = fir.insert_value {{.*}}
// LOONGARCH64: fir.insert_value
// LOONGARCH64: [[VAL:%[0-9A-Za-z]+]] = fir.insert_value {{.*}}
+ // SYSTEMZ: fir.insert_value
+ // SYSTEMZ: [[VAL:%[0-9A-Za-z]+]] = fir.insert_value {{.*}}
%1 = fir.undefined complex<f64>
%2 = arith.constant 1.0 : f64
%3 = arith.constant -4.0 : f64
@@ -204,6 +216,9 @@ func.func @returncomplex8() -> complex<f64> {
// LOONGARCH64: fir.store [[VAL]] to [[ADDRC]] : !fir.ref<complex<f64>>
// LOONGARCH64: [[RES:%[0-9A-Za-z]+]] = fir.load [[ADDRT]] : !fir.ref<tuple<f64, f64>>
// LOONGARCH64: return [[RES]] : tuple<f64, f64>
+ // SYSTEMZ: [[ADDRC:%[0-9A-Za-z]+]] = fir.convert [[ARG0]] : (!fir.ref<tuple<f64, f64>>) -> !fir.ref<complex<f64>>
+ // SYSTEMZ: fir.store [[VAL]] to [[ADDRC]] : !fir.ref<complex<f64>>
+ // SYSTEMZ: return
return %5 : complex<f64>
}
@@ -219,6 +234,7 @@ func.func @returncomplex8() -> complex<f64> {
// PPC64-LABEL: func private @paramcomplex4(f32, f32)
// PPC-LABEL: func private @paramcomplex4(f32, f32)
// LOONGARCH64-LABEL: func private @paramcomplex4(f32, f32)
+// SYSTEMZ-LABEL: func private @paramcomplex4(!fir.ref<tuple<f32, f32>> {llvm.align = 8 : i32, llvm.byval = tuple<f32, f32>})
func.func private @paramcomplex4(complex<f32>) -> ()
// Test that we rewrite calls to functions that return or accept complex<4>.
@@ -233,6 +249,7 @@ func.func private @paramcomplex4(complex<f32>) -> ()
// PPC64-LABEL: func @callcomplex4
// PPC-LABEL: func @callcomplex4
// LOONGARCH64-LABEL: func @callcomplex4
+// SYSTEMZ-LABEL: func @callcomplex4
func.func @callcomplex4(%arg0 : !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) {
// I32: [[RES:%[0-9A-Za-z]+]] = fir.call @returncomplex4() : () -> i64
@@ -246,6 +263,9 @@ func.func @callcomplex4(%arg0 : !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i3
// PPC64: [[RES:%[0-9A-Za-z]+]] = fir.call @returncomplex4() : () -> tuple<f32, f32>
// PPC: [[RES:%[0-9A-Za-z]+]] = fir.call @returncomplex4() : () -> tuple<f32, f32>
// LOONGARCH64: [[RES:%[0-9A-Za-z]+]] = fir.call @returncomplex4() : () -> tuple<f32, f32>
+ // SYSTEMZ: [[STCK:%[0-9A-Za-z]+]] = llvm.intr.stacksave : !llvm.ptr
+ // SYSTEMZ: [[RES:%[0-9A-Za-z]+]] = fir.alloca tuple<f32, f32>
+ // SYSTEMZ: fir.call @returncomplex4([[RES]]) : (!fir.ref<tuple<f32, f32>> {llvm.align = 8 : i32, llvm.sret = tuple<f32, f32>}) -> ()
%1 = fir.call @returncomplex4() : () -> complex<f32>
// I32: [[ADDRI64:%[0-9A-Za-z]+]] = fir.alloca i64
@@ -343,6 +363,13 @@ func.func @callcomplex...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/208618
More information about the flang-commits
mailing list