Skip to content

Commit 83f8721

Browse files
authored
[flang] handle passing bind(c) derived type by value for ppc64le and powerpc64-aix (llvm#128780)
1 parent 4fd5d93 commit 83f8721

File tree

6 files changed

+476
-2
lines changed

6 files changed

+476
-2
lines changed

flang/lib/Optimizer/CodeGen/Target.cpp

Lines changed: 161 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1049,6 +1049,29 @@ struct TargetPPC64 : public GenericTarget<TargetPPC64> {
10491049
AT{});
10501050
return marshal;
10511051
}
1052+
1053+
CodeGenSpecifics::Marshalling
1054+
structType(mlir::Location loc, fir::RecordType ty, bool isResult) const {
1055+
CodeGenSpecifics::Marshalling marshal;
1056+
auto sizeAndAlign{
1057+
fir::getTypeSizeAndAlignmentOrCrash(loc, ty, getDataLayout(), kindMap)};
1058+
unsigned short align{
1059+
std::max(sizeAndAlign.second, static_cast<unsigned short>(8))};
1060+
marshal.emplace_back(fir::ReferenceType::get(ty),
1061+
AT{align, /*byval*/ !isResult, /*sret*/ isResult});
1062+
return marshal;
1063+
}
1064+
1065+
CodeGenSpecifics::Marshalling
1066+
structArgumentType(mlir::Location loc, fir::RecordType ty,
1067+
const Marshalling &previousArguments) const override {
1068+
return structType(loc, ty, false);
1069+
}
1070+
1071+
CodeGenSpecifics::Marshalling
1072+
structReturnType(mlir::Location loc, fir::RecordType ty) const override {
1073+
return structType(loc, ty, true);
1074+
}
10521075
};
10531076
} // namespace
10541077

@@ -1060,7 +1083,7 @@ namespace {
10601083
struct TargetPPC64le : public GenericTarget<TargetPPC64le> {
10611084
using GenericTarget::GenericTarget;
10621085

1063-
static constexpr int defaultWidth = 64;
1086+
static constexpr int defaultWidth{64};
10641087

10651088
CodeGenSpecifics::Marshalling
10661089
complexArgumentType(mlir::Location, mlir::Type eleTy) const override {
@@ -1081,6 +1104,143 @@ struct TargetPPC64le : public GenericTarget<TargetPPC64le> {
10811104
AT{});
10821105
return marshal;
10831106
}
1107+
1108+
unsigned getElemWidth(mlir::Type ty) const {
1109+
unsigned width{};
1110+
llvm::TypeSwitch<mlir::Type>(ty)
1111+
.template Case<mlir::ComplexType>([&](mlir::ComplexType cmplx) {
1112+
auto elemType{
1113+
mlir::dyn_cast<mlir::FloatType>(cmplx.getElementType())};
1114+
width = elemType.getWidth();
1115+
})
1116+
.template Case<mlir::FloatType>(
1117+
[&](mlir::FloatType real) { width = real.getWidth(); });
1118+
return width;
1119+
}
1120+
1121+
// Determine if all derived types components are of the same float type with
1122+
// the same width. Complex(4) is considered 2 floats and complex(8) 2 doubles.
1123+
bool hasSameFloatAndWidth(
1124+
fir::RecordType recTy,
1125+
std::pair<mlir::Type, unsigned> &firstTypeAndWidth) const {
1126+
for (auto comp : recTy.getTypeList()) {
1127+
mlir::Type compType{comp.second};
1128+
if (mlir::isa<fir::RecordType>(compType)) {
1129+
auto rc{hasSameFloatAndWidth(mlir::cast<fir::RecordType>(compType),
1130+
firstTypeAndWidth)};
1131+
if (!rc)
1132+
return false;
1133+
} else {
1134+
mlir::Type ty;
1135+
bool isFloatType{false};
1136+
if (mlir::isa<mlir::FloatType, mlir::ComplexType>(compType)) {
1137+
ty = compType;
1138+
isFloatType = true;
1139+
} else if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(compType)) {
1140+
ty = seqTy.getEleTy();
1141+
isFloatType = mlir::isa<mlir::FloatType, mlir::ComplexType>(ty);
1142+
}
1143+
1144+
if (!isFloatType) {
1145+
return false;
1146+
}
1147+
auto width{getElemWidth(ty)};
1148+
if (firstTypeAndWidth.first == nullptr) {
1149+
firstTypeAndWidth.first = ty;
1150+
firstTypeAndWidth.second = width;
1151+
} else if (width != firstTypeAndWidth.second) {
1152+
return false;
1153+
}
1154+
}
1155+
}
1156+
return true;
1157+
}
1158+
1159+
CodeGenSpecifics::Marshalling
1160+
passOnTheStack(mlir::Location loc, mlir::Type ty, bool isResult) const {
1161+
CodeGenSpecifics::Marshalling marshal;
1162+
auto sizeAndAlign{
1163+
fir::getTypeSizeAndAlignmentOrCrash(loc, ty, getDataLayout(), kindMap)};
1164+
unsigned short align{
1165+
std::max(sizeAndAlign.second, static_cast<unsigned short>(8))};
1166+
marshal.emplace_back(fir::ReferenceType::get(ty),
1167+
AT{align, /*byval=*/!isResult, /*sret=*/isResult});
1168+
return marshal;
1169+
}
1170+
1171+
CodeGenSpecifics::Marshalling
1172+
structType(mlir::Location loc, fir::RecordType recTy, bool isResult) const {
1173+
CodeGenSpecifics::Marshalling marshal;
1174+
auto sizeAndAlign{fir::getTypeSizeAndAlignmentOrCrash(
1175+
loc, recTy, getDataLayout(), kindMap)};
1176+
auto recordTypeSize{sizeAndAlign.first};
1177+
mlir::Type seqTy;
1178+
std::pair<mlir::Type, unsigned> firstTyAndWidth{nullptr, 0};
1179+
1180+
// If there are less than or equal to 8 floats, the structure is flatten as
1181+
// an array of floats.
1182+
constexpr uint64_t maxNoOfFloats{8};
1183+
1184+
// i64 type
1185+
mlir::Type elemTy{mlir::IntegerType::get(recTy.getContext(), defaultWidth)};
1186+
uint64_t nElem{static_cast<uint64_t>(
1187+
std::ceil(static_cast<float>(recordTypeSize * 8) / defaultWidth))};
1188+
1189+
// If the derived type components contains are all floats with the same
1190+
// width, the argument is passed as an array of floats.
1191+
if (hasSameFloatAndWidth(recTy, firstTyAndWidth)) {
1192+
uint64_t n{};
1193+
auto firstType{firstTyAndWidth.first};
1194+
1195+
// Type is either float or complex
1196+
if (auto cmplx = mlir::dyn_cast<mlir::ComplexType>(firstType)) {
1197+
auto fltType{mlir::dyn_cast<mlir::FloatType>(cmplx.getElementType())};
1198+
n = static_cast<uint64_t>(8 * recordTypeSize / fltType.getWidth());
1199+
if (n <= maxNoOfFloats) {
1200+
nElem = n;
1201+
elemTy = fltType;
1202+
}
1203+
} else if (mlir::isa<mlir::FloatType>(firstType)) {
1204+
auto elemSizeAndAlign{fir::getTypeSizeAndAlignmentOrCrash(
1205+
loc, firstType, getDataLayout(), kindMap)};
1206+
n = static_cast<uint64_t>(recordTypeSize / elemSizeAndAlign.first);
1207+
if (n <= maxNoOfFloats) {
1208+
nElem = n;
1209+
elemTy = firstType;
1210+
}
1211+
}
1212+
// Neither float nor complex
1213+
assert(n > 0 && "unexpected type");
1214+
}
1215+
1216+
// For function returns, only flattened if there are less than 8
1217+
// floats in total.
1218+
if (isResult &&
1219+
((mlir::isa<mlir::FloatType>(elemTy) && nElem > maxNoOfFloats) ||
1220+
!mlir::isa<mlir::FloatType>(elemTy))) {
1221+
return passOnTheStack(loc, recTy, isResult);
1222+
}
1223+
1224+
seqTy = fir::SequenceType::get(nElem, elemTy);
1225+
marshal.emplace_back(seqTy, AT{});
1226+
return marshal;
1227+
}
1228+
1229+
CodeGenSpecifics::Marshalling
1230+
structArgumentType(mlir::Location loc, fir::RecordType recType,
1231+
const Marshalling &previousArguments) const override {
1232+
auto sizeAndAlign{fir::getTypeSizeAndAlignmentOrCrash(
1233+
loc, recType, getDataLayout(), kindMap)};
1234+
if (sizeAndAlign.first > 64) {
1235+
return passOnTheStack(loc, recType, false);
1236+
}
1237+
return structType(loc, recType, false);
1238+
}
1239+
1240+
CodeGenSpecifics::Marshalling
1241+
structReturnType(mlir::Location loc, fir::RecordType recType) const override {
1242+
return structType(loc, recType, true);
1243+
}
10841244
};
10851245
} // namespace
10861246

flang/test/Fir/struct-passing-loongarch64-byreg.fir

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
/// only the first example in each category checks the entire invocation process,
88
/// while the other examples only check the signatures.
99

10-
// REQUIRES: loongarch-registered-target
1110
// RUN: fir-opt --split-input-file --target-rewrite="target=loongarch64-unknown-linux-gnu" %s | FileCheck %s
1211

1312

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Test powerpc64 rewrite of struct passed by value (BIND(C), VALUE derived types).
2+
//
3+
// RUN: fir-opt --target-rewrite="target=powerpc64-ibm-aix" %s | FileCheck %s
4+
5+
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"} {
6+
7+
// character type
8+
func.func @csubch(%arg0: !fir.type<_QFcsubchTdt<{c:!fir.char<1>}>> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubch"} { return }
9+
//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"}
10+
11+
// integer type
12+
func.func @csubi1(%arg0: !fir.type<_QFcsubi1Tdt<{i:i32}>> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubi1"} { return }
13+
//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"}
14+
15+
// real type (scalar)
16+
func.func @csubr1(%arg0: !fir.type<_QFcsubr1Tdt<{r1:f32,r2:f32,r3:f32}>> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr1"} { return }
17+
//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"}
18+
19+
// real type (array)
20+
func.func @csubr5(%arg0: !fir.type<_QFcsubr5Tdt<{r:!fir.array<8xf32>}>> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr5"} { return }
21+
//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"}
22+
23+
// mixed types
24+
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 }
25+
//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"}
26+
27+
}
28+
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Test ppc64le rewrite of struct passed by value (BIND(C), VALUE derived types).
2+
//
3+
// RUN: fir-opt --target-rewrite="target=ppc64le-ibm-linux" %s | FileCheck %s
4+
5+
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"} {
6+
7+
// character type
8+
func.func @csubch(%arg0: !fir.type<_QFcsubchTdt{c:!fir.char<1>}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubch"} { return }
9+
//CHECK-LABEL: func.func @csubch(%arg0: !fir.array<1xi64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubch"}
10+
11+
// integer type
12+
func.func @csubi1(%arg0: !fir.type<_QFcsubi1Tdt{i:i32}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubi1"} { return }
13+
//CHECK-LABEL: func.func @csubi1(%arg0: !fir.array<1xi64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubi1"}
14+
15+
// integer type with size > 64 bytes
16+
func.func @csubi2(%arg0: !fir.type<_QFcsubi2Tdt{i:!fir.array<17xi32>}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubi2"} { return }
17+
//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"}
18+
19+
// real type (scalar)
20+
func.func @csubr1(%arg0: !fir.type<_QFcsubr1Tdt{r1:f32,r2:f32,r3:f32}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr1"} { return }
21+
//CHECK-LABEL: func.func @csubr1(%arg0: !fir.array<3xf32> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr1"}
22+
23+
// real type (< 8 floats and <= 64 bytes)
24+
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 }
25+
//CHECK-LABEL: func.func @csubr2(%arg0: !fir.array<8xf64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr2"}
26+
27+
// real type (> 8 floats and <= 64 bytes)
28+
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 }
29+
//CHECK-LABEL: func.func @csubr3(%arg0: !fir.array<5xi64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr3"}
30+
31+
// real type (> 8 floats and > 64 bytes)
32+
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 }
33+
//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"}
34+
35+
// real type (array)
36+
func.func @csubr5(%arg0: !fir.type<_QFcsubr5Tdt{r:!fir.array<8xf32>}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr5"} { return }
37+
//CHECK-LABEL: func.func @csubr5(%arg0: !fir.array<8xf32> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr5"}
38+
39+
// real type (array componets and > 64 bytes)
40+
func.func @csubr6(%arg0: !fir.type<_QFcsubr6Tdt{r:!fir.array<9xf64>}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr6"} { return }
41+
//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"}
42+
43+
// real type with different kinds
44+
func.func @csubr7(%arg0: !fir.type<_QFcsubr7Tdt{r1:f32,r2:f64,r3:f64}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr7"} { return }
45+
//CHECK-LABEL: func.func @csubr7(%arg0: !fir.array<3xi64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubr7"}
46+
47+
// complex type
48+
func.func @csubc1(%arg0: !fir.type<_QFcsubc1Tdt{r1:complex<f32>,r2:complex<f32>}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubc1"} { return }
49+
//CHECK-LABEL: func.func @csubc1(%arg0: !fir.array<4xf32> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubc1"}
50+
51+
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 }
52+
//CHECK-LABEL: func.func @csubc2(%arg0: !fir.array<8xf64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubc2"}
53+
54+
// complex type (> 8 floats and size < 64 bytes)
55+
func.func @csubc3(%arg0: !fir.type<_QFcsubc3Tdt{r:!fir.array<5xcomplex<f32>>}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubc3"} { return }
56+
//CHECK-LABEL: func.func @csubc3(%arg0: !fir.array<5xi64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubc3"}
57+
58+
// complex type (size > 64 bytes)
59+
func.func @csubc4(%arg0: !fir.type<_QFcsubc4Tdt{r:!fir.array<9xcomplex<f32>>}> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csubc4"} { return }
60+
//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"}
61+
62+
// mixed type
63+
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 }
64+
//CHECK-LABEL: func.func @csub1(%arg0: !fir.array<2xi64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub1"}
65+
66+
// nested derived types
67+
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 }
68+
//CHECK-LABEL: func.func @csub2(%arg0: !fir.array<8xf32> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub2"}
69+
70+
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 }
71+
//CHECK-LABEL: func.func @csub3(%arg0: !fir.array<3xi64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub3"}
72+
73+
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 }
74+
//CHECK-LABEL: func.func @csub4(%arg0: !fir.array<2xi64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub4"}
75+
76+
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 }
77+
//CHECK-LABEL: func.func @csub5(%arg0: !fir.array<3xf32> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub5"}
78+
79+
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 }
80+
//CHECK-LABEL: func.func @csub6(%arg0: !fir.array<2xi64> {fir.bindc_name = "arg"}) attributes {fir.bindc_name = "csub6"}
81+
82+
}

0 commit comments

Comments
 (0)