[flang-commits] [flang] a1c736e - [Flang] Cray pointer Lowering
Mark Danial via flang-commits
flang-commits at lists.llvm.org
Tue Aug 22 09:11:50 PDT 2023
Author: Mark Danial
Date: 2023-08-22T12:10:49-04:00
New Revision: a1c736ec08f25e83552b20c94a5b2afdcd021a40
URL: https://github.com/llvm/llvm-project/commit/a1c736ec08f25e83552b20c94a5b2afdcd021a40
DIFF: https://github.com/llvm/llvm-project/commit/a1c736ec08f25e83552b20c94a5b2afdcd021a40.diff
LOG: [Flang] Cray pointer Lowering
This patch is to add cray pointer (aka integer pointer) support to flang. Syntax and semantic checking were already available in flang.
Cray pointers reference (https://gcc.gnu.org/onlinedocs/gfortran/Cray-pointers.html)
In order to implement the feature we create the following sequence for a simple scalar load and store:
```
integer pte, i
pointer(ptr, pte)
i = pte
```
```
%1 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"}
%2 = fir.alloca i32 {bindc_name = "pte", uniq_name = "_QFEpte"}
%3 = fir.alloca i64 {bindc_name = "ptr", uniq_name = "_QFEptr"}
...
%7 = fir.embox %3 : (!fir.ref<i64>) -> !fir.box<i64>
%8 = fir.box_addr %7 : (!fir.box<i64>) -> !fir.ref<i64>
%9 = fir.convert %8 : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<i32>>
%10 = fir.load %9 : !fir.ref<!fir.ptr<i32>>
%11 = fir.load %10 : !fir.ptr<i32>
fir.store %11 to %1 : !fir.ref<i32>
```
```
integer pte, i
pointer(ptr, pte)
pte = i
```
```
%1 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"}
%2 = fir.alloca i32 {bindc_name = "pte", uniq_name = "_QFEpte"}
%3 = fir.alloca i64 {bindc_name = "ptr", uniq_name = "_QFEptr"}
%7 = fir.load %1 : !fir.ref<i32>
%8 = fir.embox %3 : (!fir.ref<i64>) -> !fir.box<i64>
%9 = fir.box_addr %8 : (!fir.box<i64>) -> !fir.ref<i64>
%10 = fir.convert %9 : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<i32>>
%11 = fir.load %10 : !fir.ref<!fir.ptr<i32>>
fir.store %7 to %11 : !fir.ptr<i32>
```
The sequence is very similar for array element cases with the addition of fir.coordinate_of for the specific element.
The whole array case is slightly different but uses the same sequence before the fir.array_load and fir.array_merge_store.
Reviewed By: kkwli0
Differential Revision: https://reviews.llvm.org/D151478
Added:
flang/test/Lower/cray-pointer.f90
Modified:
flang/include/flang/Lower/ConvertExpr.h
flang/lib/Lower/Bridge.cpp
flang/lib/Lower/ConvertExpr.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Lower/ConvertExpr.h b/flang/include/flang/Lower/ConvertExpr.h
index a4a8a524e9ada3..64a18092014c6c 100644
--- a/flang/include/flang/Lower/ConvertExpr.h
+++ b/flang/include/flang/Lower/ConvertExpr.h
@@ -234,6 +234,10 @@ inline mlir::NamedAttribute getAdaptToByRefAttr(fir::FirOpBuilder &builder) {
builder.getUnitAttr()};
}
+Fortran::semantics::SymbolRef getPointer(Fortran::semantics::SymbolRef sym);
+mlir::Value addCrayPointerInst(mlir::Location loc, fir::FirOpBuilder &builder,
+ mlir::Value ptrVal, mlir::Type ptrTy,
+ mlir::Type pteTy);
} // namespace Fortran::lower
#endif // FORTRAN_LOWER_CONVERTEXPR_H
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 4b9e1ca3841948..be6004d57b36fc 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -3578,6 +3578,26 @@ class FirConverter : public Fortran::lower::AbstractConverter {
// to a result variable of one of the other types requires
// conversion to the actual type.
mlir::Type toTy = genType(assign.lhs);
+
+ // If Cray pointee, need to handle the address
+ // Array is handled in genCoordinateOp.
+ if (sym->test(Fortran::semantics::Symbol::Flag::CrayPointee) &&
+ sym->Rank() == 0) {
+ // get the corresponding Cray pointer
+
+ auto ptrSym = Fortran::lower::getPointer(*sym);
+ fir::ExtendedValue ptr =
+ getSymbolExtendedValue(ptrSym, nullptr);
+ mlir::Value ptrVal = fir::getBase(ptr);
+ mlir::Type ptrTy = genType(*ptrSym);
+
+ fir::ExtendedValue pte =
+ getSymbolExtendedValue(*sym, nullptr);
+ mlir::Value pteVal = fir::getBase(pte);
+ mlir::Value cnvrt = Fortran::lower::addCrayPointerInst(
+ loc, *builder, ptrVal, ptrTy, pteVal.getType());
+ addr = builder->create<fir::LoadOp>(loc, cnvrt);
+ }
mlir::Value cast =
isVector ? val
: builder->convertWithSemantics(loc, toTy, val);
diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp
index ea952198251c9b..5ca76f0f061687 100644
--- a/flang/lib/Lower/ConvertExpr.cpp
+++ b/flang/lib/Lower/ConvertExpr.cpp
@@ -849,7 +849,7 @@ class ScalarExprLowering {
ExtValue genval(Fortran::semantics::SymbolRef sym) {
mlir::Location loc = getLoc();
ExtValue var = gen(sym);
- if (const fir::UnboxedValue *s = var.getUnboxed())
+ if (const fir::UnboxedValue *s = var.getUnboxed()) {
if (fir::isa_ref_type(s->getType())) {
// A function with multiple entry points returning
diff erent types
// tags all result variables with one of the largest types to allow
@@ -861,9 +861,23 @@ class ScalarExprLowering {
if (addr.getType() != resultType)
addr = builder.createConvert(loc, builder.getRefType(resultType),
addr);
+ } else if (sym->test(Fortran::semantics::Symbol::Flag::CrayPointee)) {
+ // get the corresponding Cray pointer
+ auto ptrSym = Fortran::lower::getPointer(sym);
+ ExtValue ptr = gen(ptrSym);
+ mlir::Value ptrVal = fir::getBase(ptr);
+ mlir::Type ptrTy = converter.genType(*ptrSym);
+
+ ExtValue pte = gen(sym);
+ mlir::Value pteVal = fir::getBase(pte);
+
+ mlir::Value cnvrt = Fortran::lower::addCrayPointerInst(
+ loc, builder, ptrVal, ptrTy, pteVal.getType());
+ addr = builder.create<fir::LoadOp>(loc, cnvrt);
}
return genLoad(addr);
}
+ }
return var;
}
@@ -1553,6 +1567,21 @@ class ScalarExprLowering {
args.push_back(builder.create<mlir::arith::SubIOp>(loc, ty, val, lb));
}
mlir::Value base = fir::getBase(array);
+
+ auto baseSym = getFirstSym(aref);
+ if (baseSym.test(Fortran::semantics::Symbol::Flag::CrayPointee)) {
+ // get the corresponding Cray pointer
+ auto ptrSym = Fortran::lower::getPointer(baseSym);
+
+ fir::ExtendedValue ptr = gen(ptrSym);
+ mlir::Value ptrVal = fir::getBase(ptr);
+ mlir::Type ptrTy = ptrVal.getType();
+
+ mlir::Value cnvrt = Fortran::lower::addCrayPointerInst(
+ loc, builder, ptrVal, ptrTy, base.getType());
+ base = builder.create<fir::LoadOp>(loc, cnvrt);
+ }
+
mlir::Type eleTy = fir::dyn_cast_ptrOrBoxEleTy(base.getType());
if (auto classTy = eleTy.dyn_cast<fir::ClassType>())
eleTy = classTy.getEleTy();
@@ -5632,7 +5661,8 @@ class ArrayExprLowering {
}
/// Base case of generating an array reference,
- CC genarr(const ExtValue &extMemref, ComponentPath &components) {
+ CC genarr(const ExtValue &extMemref, ComponentPath &components,
+ mlir::Value CrayPtr = nullptr) {
mlir::Location loc = getLoc();
mlir::Value memref = fir::getBase(extMemref);
mlir::Type arrTy = fir::dyn_cast_ptrOrBoxEleTy(memref.getType());
@@ -5777,6 +5807,16 @@ class ArrayExprLowering {
}
auto arrLoad = builder.create<fir::ArrayLoadOp>(
loc, arrTy, memref, shape, slice, fir::getTypeParams(extMemref));
+
+ if (CrayPtr) {
+ mlir::Type ptrTy = CrayPtr.getType();
+ mlir::Value cnvrt = Fortran::lower::addCrayPointerInst(
+ loc, builder, CrayPtr, ptrTy, memref.getType());
+ auto addr = builder.create<fir::LoadOp>(loc, cnvrt);
+ arrLoad = builder.create<fir::ArrayLoadOp>(loc, arrTy, addr, shape, slice,
+ fir::getTypeParams(extMemref));
+ }
+
mlir::Value arrLd = arrLoad.getResult();
if (isProjectedCopyInCopyOut()) {
// Semantics are projected copy-in copy-out.
@@ -6930,6 +6970,21 @@ class ArrayExprLowering {
return genImplicitArrayAccess(x.GetComponent(), components);
}
+ CC genImplicitArrayAccess(const Fortran::semantics::Symbol &x,
+ ComponentPath &components) {
+ mlir::Value ptrVal = nullptr;
+ if (x.test(Fortran::semantics::Symbol::Flag::CrayPointee)) {
+ auto ptrSym = Fortran::lower::getPointer(x);
+ ExtValue ptr = converter.getSymbolExtendedValue(ptrSym);
+ ptrVal = fir::getBase(ptr);
+ }
+ components.reversePath.push_back(ImplicitSubscripts{});
+ ExtValue exv = asScalarRef(x);
+ lowerPath(exv, components);
+ auto lambda = genarr(exv, components, ptrVal);
+ return [=](IterSpace iters) { return lambda(components.pc(iters)); };
+ }
+
template <typename A>
CC genAsScalar(const A &x) {
mlir::Location loc = getLoc();
@@ -7573,3 +7628,37 @@ void Fortran::lower::createArrayMergeStores(
esp.resetBindings();
esp.incrementCounter();
}
+
+Fortran::semantics::SymbolRef
+Fortran::lower::getPointer(Fortran::semantics::SymbolRef sym) {
+ assert(!sym->owner().crayPointers().empty() &&
+ "empty Cray pointer/pointee map");
+ for (const auto &[pointee, pointer] : sym->owner().crayPointers()) {
+ if (pointee == sym->name()) {
+ Fortran::semantics::SymbolRef v{pointer.get()};
+ return v;
+ }
+ }
+ llvm_unreachable("corresponding Cray pointer cannot be found");
+}
+
+mlir::Value Fortran::lower::addCrayPointerInst(mlir::Location loc,
+ fir::FirOpBuilder &builder,
+ mlir::Value ptrVal,
+ mlir::Type ptrTy,
+ mlir::Type pteTy) {
+
+ mlir::Value empty;
+ mlir::ValueRange emptyRange;
+ auto boxTy = fir::BoxType::get(ptrTy);
+ auto box = builder.create<fir::EmboxOp>(loc, boxTy, ptrVal, empty, empty,
+ emptyRange);
+ mlir::Value addrof =
+ (ptrTy.isa<fir::ReferenceType>())
+ ? builder.create<fir::BoxAddrOp>(loc, ptrTy, box)
+ : builder.create<fir::BoxAddrOp>(loc, builder.getRefType(ptrTy), box);
+
+ auto refPtrTy =
+ builder.getRefType(fir::PointerType::get(fir::dyn_cast_ptrEleTy(pteTy)));
+ return builder.createConvert(loc, refPtrTy, addrof);
+}
diff --git a/flang/test/Lower/cray-pointer.f90 b/flang/test/Lower/cray-pointer.f90
new file mode 100644
index 00000000000000..f0c0c0f73f2a64
--- /dev/null
+++ b/flang/test/Lower/cray-pointer.f90
@@ -0,0 +1,404 @@
+! RUN: bbc %s -emit-fir -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+! Test Cray Pointers
+
+! Test Scalar Case
+
+! CHECK-LABEL: func.func @_QPcray_scalar() {
+subroutine cray_scalar()
+ integer :: i, pte
+ integer :: data = 3
+ integer :: j = -3
+ pointer(ptr, pte)
+ ptr = loc(data)
+
+! CHECK: %[[data:.*]] = fir.address_of(@_QFcray_scalarEdata) {{.*}}
+! CHECK: %[[i:.*]] = fir.alloca i32 {{.*}}
+! CHECK: %[[j:.*]] = fir.address_of(@_QFcray_scalarEj) {{.*}}
+! CHECK: %[[ptr:.*]] = fir.alloca i64 {{.*}}
+! CHECK: %[[databox:.*]] = fir.embox %[[data]] : (!fir.ref<i32>) -> !fir.box<i32>
+! CHECK: %[[dataaddr:.*]] = fir.box_addr %[[databox]] : (!fir.box<i32>) -> !fir.ref<i32>
+! CHECK: %[[dataaddrval:.*]] = fir.convert %[[dataaddr]] : (!fir.ref<i32>) -> i64
+! CHECK: fir.store %[[dataaddrval]] to %[[ptr]] : !fir.ref<i64>
+
+ i = pte
+ print *, i
+
+! CHECK: %[[ptrbox:.*]] = fir.embox %[[ptr]] : (!fir.ref<i64>) -> !fir.box<i64>
+! CHECK: %[[ptraddr:.*]] = fir.box_addr %[[ptrbox]] : (!fir.box<i64>) -> !fir.ref<i64>
+! CHECK: %[[ptraddrval:.*]] = fir.convert %[[ptraddr]] : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<i32>>
+! CHECK: %[[ptrld:.*]] = fir.load %[[ptraddrval]] : !fir.ref<!fir.ptr<i32>>
+! CHECK: %[[ptrldd:.*]] = fir.load %[[ptrld]] : !fir.ptr<i32>
+! CHECK: fir.store %[[ptrldd]] to %[[i]] : !fir.ref<i32>
+
+ pte = j
+ print *, data, pte
+
+! CHECK: %[[jld:.*]] = fir.load %[[j]] : !fir.ref<i32>
+! CHECK: %[[ptrbox1:.*]] = fir.embox %[[ptr]] : (!fir.ref<i64>) -> !fir.box<i64>
+! CHECK: %[[ptraddr1:.*]] = fir.box_addr %[[ptrbox1]] : (!fir.box<i64>) -> !fir.ref<i64>
+! CHECK: %[[ptraddrval1:.*]] = fir.convert %[[ptraddr1]] : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<i32>>
+! CHECK: %[[ptrld1:.*]] = fir.load %[[ptraddrval1]] : !fir.ref<!fir.ptr<i32>>
+! CHECK: fir.store %[[jld]] to %[[ptrld1]] : !fir.ptr<i32>
+
+end
+
+! Test Derived Type Case
+
+! CHECK-LABEL: func.func @_QPcray_derivedtype() {
+subroutine cray_derivedType()
+ integer :: pte, k
+ type dt
+ integer :: i, j
+ end type
+ type(dt) :: xdt
+ pointer(ptr, pte)
+ xdt = dt(-1, -3)
+ ptr = loc(xdt)
+
+! CHECK: %[[dt:.*]] = fir.alloca !fir.type<_QFcray_derivedtypeTdt{i:i32,j:i32}>
+! CHECK: %[[k:.*]] = fir.alloca i32 {{.*}}
+! CHECK: %[[pte:.*]] = fir.alloca i32 {{.*}}
+! CHECK: %[[ptr:.*]] = fir.alloca i64 {{.*}}
+! CHECK: %[[xdt:.*]] = fir.alloca !fir.type<_QFcray_derivedtypeTdt{i:i32,j:i32}> {{.*}}
+! CHECK: %[[xdtbox:.*]] = fir.embox %[[xdt]] : (!fir.ref<!fir.type<_QFcray_derivedtypeTdt{i:i32,j:i32}>>) -> !fir.box<!fir.type<_QFcray_derivedtypeTdt{i:i32,j:i32}>>
+! CHECK: %[[xdtaddr:.*]] = fir.box_addr %[[xdtbox]] : (!fir.box<!fir.type<_QFcray_derivedtypeTdt{i:i32,j:i32}>>) -> !fir.ref<!fir.type<_QFcray_derivedtypeTdt{i:i32,j:i32}>>
+! CHECK: %[[xdtaddrval:.*]] = fir.convert %[[xdtaddr]] : (!fir.ref<!fir.type<_QFcray_derivedtypeTdt{i:i32,j:i32}>>) -> i64
+! CHECK: fir.store %[[xdtaddrval]] to %[[ptr]] : !fir.ref<i64>
+
+ k = pte
+ print *, k
+
+! CHECK: %[[ptrbox:.*]] = fir.embox %[[ptr]] : (!fir.ref<i64>) -> !fir.box<i64>
+! CHECK: %[[ptraddr:.*]] = fir.box_addr %[[ptrbox]] : (!fir.box<i64>) -> !fir.ref<i64>
+! CHECK: %[[ptraddrval:.*]] = fir.convert %[[ptraddr]] : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<i32>>
+! CHECK: %[[ptrld:.*]] = fir.load %[[ptraddrval]] : !fir.ref<!fir.ptr<i32>>
+! CHECK: %[[ptrldd:.*]] = fir.load %[[ptrld]] : !fir.ptr<i32>
+! CHECK: fir.store %[[ptrldd]] to %[[k]] : !fir.ref<i32>
+
+ pte = k + 2
+ print *, xdt, pte
+
+! CHECK: %[[kld:.*]] = fir.load %[[k]] : !fir.ref<i32>
+! CHECK: %[[kld1:.*]] = fir.load %[[k]] : !fir.ref<i32>
+! CHECK: %[[const:.*]] = arith.constant 2 : i32
+! CHECK: %[[add:.*]] = arith.addi %[[kld1]], %[[const]] : i32
+! CHECK: %[[ptrbox1:.*]] = fir.embox %[[ptr]] : (!fir.ref<i64>) -> !fir.box<i64>
+! CHECK: %[[ptraddr1:.*]] = fir.box_addr %[[ptrbox1]] : (!fir.box<i64>) -> !fir.ref<i64>
+! CHECK: %[[ptraddrval1:.*]] = fir.convert %[[ptraddr1]] : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<i32>>
+! CHECK: %[[ptrld1:.*]] = fir.load %[[ptraddrval1]] : !fir.ref<!fir.ptr<i32>>
+! CHECK: fir.store %[[add]] to %[[ptrld1]] : !fir.ptr<i32>
+
+end
+
+! Test Ptr arithmetic Case
+
+! CHECK-LABEL: func.func @_QPcray_ptrarth() {
+subroutine cray_ptrArth()
+ integer :: pte, i
+ pointer(ptr, pte)
+ type dt
+ integer :: x, y, z
+ end type
+ type(dt) :: xdt
+ xdt = dt(5, 11, 2)
+ ptr = loc(xdt)
+
+! CHECK: %[[dt:.*]] = fir.alloca !fir.type<_QFcray_ptrarthTdt{x:i32,y:i32,z:i32}>
+! CHECK: %[[i:.*]] = fir.alloca i32 {{.*}}
+! CHECK: %[[pte:.*]] = fir.alloca i32 {{.*}}
+! CHECK: %[[ptr:.*]] = fir.alloca i64 {{.*}}
+! CHECK: %[[xdt:.*]] = fir.alloca !fir.type<_QFcray_ptrarthTdt{x:i32,y:i32,z:i32}> {{.*}}
+! CHECK: %[[xdtbox:.*]] = fir.embox %[[xdt]] : (!fir.ref<!fir.type<_QFcray_ptrarthTdt{x:i32,y:i32,z:i32}>>) -> !fir.box<!fir.type<_QFcray_ptrarthTdt{x:i32,y:i32,z:i32}>>
+! CHECK: %[[xdtaddr:.*]] = fir.box_addr %[[xdtbox]] : (!fir.box<!fir.type<_QFcray_ptrarthTdt{x:i32,y:i32,z:i32}>>) -> !fir.ref<!fir.type<_QFcray_ptrarthTdt{x:i32,y:i32,z:i32}>>
+! CHECK: %[[xdtaddrval:.*]] = fir.convert %[[xdtaddr]] : (!fir.ref<!fir.type<_QFcray_ptrarthTdt{x:i32,y:i32,z:i32}>>) -> i64
+! CHECK: fir.store %[[xdtaddrval]] to %[[ptr]] : !fir.ref<i64>
+
+ ptr = ptr + 4
+ i = pte
+ print *, i
+
+! CHECK: %[[ptrbox:.*]] = fir.embox %[[ptr]] : (!fir.ref<i64>) -> !fir.box<i64>
+! CHECK: %[[ptraddr:.*]] = fir.box_addr %[[ptrbox]] : (!fir.box<i64>) -> !fir.ref<i64>
+! CHECK: %[[ptraddrval:.*]] = fir.convert %[[ptraddr]] : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<i32>>
+! CHECK: %[[ptrld:.*]] = fir.load %[[ptraddrval]] : !fir.ref<!fir.ptr<i32>>
+! CHECK: %[[ptrldd:.*]] = fir.load %[[ptrld]] : !fir.ptr<i32>
+! CHECK: fir.store %[[ptrldd]] to %[[i]] : !fir.ref<i32>
+
+ ptr = ptr + 4
+ pte = -7
+ print *, xdt
+
+! CHECK: %[[ld:.*]] = fir.load %[[ptr]] : !fir.ref<i64>
+! CHECK: %[[const:.*]] = arith.constant 4 : i64
+! CHECK: %[[add:.*]] = arith.addi %[[ld]], %[[const]] : i64
+! CHECK: fir.store %[[add]] to %[[ptr]] : !fir.ref<i64>
+! CHECK: %[[const1:.*]] = arith.constant -7 : i32
+! CHECK: %[[ptrbox1:.*]] = fir.embox %[[ptr]] : (!fir.ref<i64>) -> !fir.box<i64>
+! CHECK: %[[ptraddr1:.*]] = fir.box_addr %[[ptrbox1]] : (!fir.box<i64>) -> !fir.ref<i64>
+! CHECK: %[[ptraddrval1:.*]] = fir.convert %[[ptraddr1]] : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<i32>>
+! CHECK: %[[ptrld1:.*]] = fir.load %[[ptraddrval1]] : !fir.ref<!fir.ptr<i32>>
+! CHECK: fir.store %[[const1]] to %[[ptrld1]] : !fir.ptr<i32>
+
+end
+
+! Test Array element Case
+
+! CHECK-LABEL: func.func @_QPcray_arrayelement() {
+subroutine cray_arrayElement()
+ integer :: pte, k, data(5)
+ pointer (ptr, pte(3))
+ data = [ 1, 2, 3, 4, 5 ]
+ ptr = loc(data(2))
+
+! CHECK: %[[data:.*]] = fir.alloca !fir.array<5xi32> {{.*}}
+! CHECK: %[[k:.*]] = fir.alloca i32 {{.*}}
+! CHECK: %[[pte:.*]] = fir.alloca !fir.array<3xi32> {{.*}}
+! CHECK: %[[ptr:.*]] = fir.alloca i64 {{.*}}
+! CHECK: %[[c2:.*]] = arith.constant 2 : i64
+! CHECK: %[[c1:.*]] = arith.constant 1 : i64
+! CHECK: %[[sub:.*]] = arith.subi %[[c2]], %[[c1]] : i64
+! CHECK: %[[cor:.*]] = fir.coordinate_of %[[data]], %[[sub]] : (!fir.ref<!fir.array<5xi32>>, i64) -> !fir.ref<i32>
+! CHECK: %[[box:.*]] = fir.embox %[[cor]] : (!fir.ref<i32>) -> !fir.box<i32>
+! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<i32>) -> !fir.ref<i32>
+! CHECK: %[[val:.*]] = fir.convert %[[addr]] : (!fir.ref<i32>) -> i64
+! CHECK: fir.store %[[val]] to %[[ptr]] : !fir.ref<i64>
+
+ k = pte(3)
+ print *, k
+
+! CHECK: %[[c3:.*]] = arith.constant 3 : i64
+! CHECK: %[[c1:.*]] = arith.constant 1 : i64
+! CHECK: %[[sub:.*]] = arith.subi %[[c3]], %[[c1]] : i64
+! CHECK: %[[box:.*]] = fir.embox %[[ptr]] : (!fir.ref<i64>) -> !fir.box<!fir.ref<i64>>
+! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.ref<i64>>) -> !fir.ref<i64>
+! CHECK: %[[val:.*]] = fir.convert %[[addr]] : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<!fir.array<3xi32>>>
+! CHECK: %[[ld1:.*]] = fir.load %[[val]] : !fir.ref<!fir.ptr<!fir.array<3xi32>>>
+! CHECK: %[[cor:.*]] = fir.coordinate_of %[[ld1]], %[[sub]] : (!fir.ptr<!fir.array<3xi32>>, i64) -> !fir.ref<i32>
+! CHECK: %[[ld2:.*]] = fir.load %[[cor]] : !fir.ref<i32>
+! CHECK: fir.store %[[ld2]] to %[[k]] : !fir.ref<i32>
+
+ pte(2) = -2
+ print *, data
+
+! CHECK: %[[c2n:.*]] = arith.constant -2 : i32
+! CHECK: %[[c2:.*]] = arith.constant 2 : i64
+! CHECK: %[[c1:.*]] = arith.constant 1 : i64
+! CHECK: %[[sub:.*]] = arith.subi %[[c2]], %[[c1]] : i64
+! CHECK: %[[box:.*]] = fir.embox %[[ptr]] : (!fir.ref<i64>) -> !fir.box<!fir.ref<i64>>
+! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.ref<i64>>) -> !fir.ref<i64>
+! CHECK: %[[val:.*]] = fir.convert %[[addr]] : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<!fir.array<3xi32>>>
+! CHECK: %[[ld1:.*]] = fir.load %[[val]] : !fir.ref<!fir.ptr<!fir.array<3xi32>>>
+! CHECK: %[[cor:.*]] = fir.coordinate_of %[[ld1]], %[[sub]] : (!fir.ptr<!fir.array<3xi32>>, i64) -> !fir.ref<i32>
+! CHECK: fir.store %[[c2n]] to %[[cor]] : !fir.ref<i32>
+
+end
+
+! Test 2d Array element Case
+
+! CHECK-LABEL: func.func @_QPcray_2darrayelement() {
+subroutine cray_2darrayElement()
+ integer :: pte, k, data(2,4)
+ pointer (ptr, pte(2,3))
+ data = reshape([1,2,3,4,5,6,7,8], [2,4])
+ ptr = loc(data(2,2))
+
+! CHECK: %[[data:.*]] = fir.alloca !fir.array<2x4xi32> {{.*}}
+! CHECK: %[[k:.*]] = fir.alloca i32 {{.*}}
+! CHECK: %[[pte:.*]] = fir.alloca !fir.array<2x3xi32> {{.*}}
+! CHECK: %[[ptr:.*]] = fir.alloca i64 {{.*}}
+! CHECK: %[[c2:.*]] = arith.constant 2 : i64
+! CHECK: %[[c1:.*]] = arith.constant 1 : i64
+! CHECK: %[[sub1:.*]] = arith.subi %[[c2]], %[[c1]] : i64
+! CHECK: %[[c22:.*]] = arith.constant 2 : i64
+! CHECK: %[[c12:.*]] = arith.constant 1 : i64
+! CHECK: %[[sub2:.*]] = arith.subi %[[c22]], %[[c12]] : i64
+! CHECK: %[[cor:.*]] = fir.coordinate_of %[[data]], %[[sub1]], %[[sub2]] : (!fir.ref<!fir.array<2x4xi32>>, i64, i64) -> !fir.ref<i32>
+! CHECK: %[[box:.*]] = fir.embox %[[cor]] : (!fir.ref<i32>) -> !fir.box<i32>
+! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<i32>) -> !fir.ref<i32>
+! CHECK: %[[val:.*]] = fir.convert %[[addr]] : (!fir.ref<i32>) -> i64
+! CHECK: fir.store %[[val]] to %[[ptr]] : !fir.ref<i64>
+
+ k = pte(1,1)
+ print *, k
+
+! CHECK: %[[c2:.*]] = arith.constant 1 : i64
+! CHECK: %[[c1:.*]] = arith.constant 1 : i64
+! CHECK: %[[sub1:.*]] = arith.subi %[[c2]], %[[c1]] : i64
+! CHECK: %[[c22:.*]] = arith.constant 1 : i64
+! CHECK: %[[c12:.*]] = arith.constant 1 : i64
+! CHECK: %[[sub2:.*]] = arith.subi %[[c22]], %[[c12]] : i64
+! CHECK: %[[box:.*]] = fir.embox %[[ptr]] : (!fir.ref<i64>) -> !fir.box<!fir.ref<i64>>
+! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.ref<i64>>) -> !fir.ref<i64>
+! CHECK: %[[val:.*]] = fir.convert %[[addr]] : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<!fir.array<2x3xi32>>>
+! CHECK: %[[ld1:.*]] = fir.load %[[val]] : !fir.ref<!fir.ptr<!fir.array<2x3xi32>>>
+! CHECK: %[[cor:.*]] = fir.coordinate_of %[[ld1]], %[[sub1]], %[[sub2]] : (!fir.ptr<!fir.array<2x3xi32>>, i64, i64) -> !fir.ref<i32>
+! CHECK: %[[ld2:.*]] = fir.load %[[cor]] : !fir.ref<i32>
+! CHECK: fir.store %[[ld2]] to %[[k]] : !fir.ref<i32>
+
+ pte(1,2) = -2
+ print *, data
+
+! CHECK: %[[c2n:.*]] = arith.constant -2 : i32
+! CHECK: %[[c2:.*]] = arith.constant 1 : i64
+! CHECK: %[[c1:.*]] = arith.constant 1 : i64
+! CHECK: %[[sub1:.*]] = arith.subi %[[c2]], %[[c1]] : i64
+! CHECK: %[[c22:.*]] = arith.constant 2 : i64
+! CHECK: %[[c12:.*]] = arith.constant 1 : i64
+! CHECK: %[[sub2:.*]] = arith.subi %[[c22]], %[[c12]] : i64
+! CHECK: %[[box:.*]] = fir.embox %[[ptr]] : (!fir.ref<i64>) -> !fir.box<!fir.ref<i64>>
+! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.ref<i64>>) -> !fir.ref<i64>
+! CHECK: %[[val:.*]] = fir.convert %[[addr]] : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<!fir.array<2x3xi32>>>
+! CHECK: %[[ld1:.*]] = fir.load %[[val]] : !fir.ref<!fir.ptr<!fir.array<2x3xi32>>>
+! CHECK: %[[cor:.*]] = fir.coordinate_of %[[ld1]], %[[sub1]], %[[sub2]] : (!fir.ptr<!fir.array<2x3xi32>>, i64, i64) -> !fir.ref<i32>
+! CHECK: fir.store %[[c2n]] to %[[cor]] : !fir.ref<i32>
+
+end
+
+! Test Whole Array case
+
+! CHECK-LABEL: func.func @_QPcray_array() {
+subroutine cray_array()
+ integer :: pte, k(3), data(5)
+ pointer (ptr, pte(3))
+ data = [ 1, 2, 3, 4, 5 ]
+ ptr = loc(data(2))
+
+! CHECK: %[[data:.*]] = fir.alloca !fir.array<5xi32> {{.*}}
+! CHECK: %[[c3:.*]] = arith.constant 3 : index
+! CHECK: %[[k:.*]] = fir.alloca !fir.array<3xi32> {{.*}}
+! CHECK: %[[c31:.*]] = arith.constant 3 : index
+! CHECK: %[[pte:.*]] = fir.alloca !fir.array<3xi32> {{.*}}
+! CHECK: %[[ptr:.*]] = fir.alloca i64 {{.*}}
+! CHECK: %[[c2:.*]] = arith.constant 2 : i64
+! CHECK: %[[c1:.*]] = arith.constant 1 : i64
+! CHECK: %[[sub:.*]] = arith.subi %[[c2]], %[[c1]] : i64
+! CHECK: %[[cor:.*]] = fir.coordinate_of %[[data]], %[[sub]] : (!fir.ref<!fir.array<5xi32>>, i64) -> !fir.ref<i32>
+! CHECK: %[[box:.*]] = fir.embox %[[cor]] : (!fir.ref<i32>) -> !fir.box<i32>
+! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<i32>) -> !fir.ref<i32>
+! CHECK: %[[val:.*]] = fir.convert %[[addr]] : (!fir.ref<i32>) -> i64
+! CHECK: fir.store %[[val]] to %[[ptr]] : !fir.ref<i64>
+
+ k = pte
+ print *, k
+
+! CHECK: %[[shape1:.*]] = fir.shape %[[c3]] : (index) -> !fir.shape<1>
+! CHECK: %[[arrayld1:.*]] = fir.array_load %[[k]](%[[shape1]]) : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> !fir.array<3xi32>
+! CHECK: %[[shape:.*]] = fir.shape %[[c31]] : (index) -> !fir.shape<1>
+! CHECK: %[[box:.*]] = fir.embox %[[ptr]] : (!fir.ref<i64>) -> !fir.box<!fir.ref<i64>>
+! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.ref<i64>>) -> !fir.ref<i64>
+! CHECK: %[[val:.*]] = fir.convert %[[addr]] : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<!fir.array<3xi32>>>
+! CHECK: %[[ld:.*]] = fir.load %[[val]] : !fir.ref<!fir.ptr<!fir.array<3xi32>>>
+! CHECK: %[[arrayld:.*]] = fir.array_load %[[ld]](%[[shape]]) : (!fir.ptr<!fir.array<3xi32>>, !fir.shape<1>) -> !fir.array<3xi32>
+! CHECK: %[[c1:.*]] = arith.constant 1 : index
+! CHECK: %[[c0:.*]] = arith.constant 0 : index
+! CHECK: %[[sub:.*]] = arith.subi %[[c3]], %[[c1]] : index
+! CHECK: %[[doloop:.*]] = fir.do_loop %arg0 = %[[c0]] to %[[sub]] step %[[c1]] unordered iter_args(%arg1 = %[[arrayld1]]) -> (!fir.array<3xi32>) {
+! CHECK: %[[arrayfetch:.*]] = fir.array_fetch %[[arrayld]], %arg0 : (!fir.array<3xi32>, index) -> i32
+! CHECK: %[[arrayupdate:.*]] = fir.array_update %arg1, %[[arrayfetch]], %arg0 : (!fir.array<3xi32>, i32, index) -> !fir.array<3xi32>
+! CHECK: fir.result %[[arrayupdate]] : !fir.array<3xi32>
+! CHECK: fir.array_merge_store %[[arrayld1]], %[[doloop]] to %[[k]] : !fir.array<3xi32>, !fir.array<3xi32>, !fir.ref<!fir.array<3xi32>>
+
+ pte = -2
+ print *, data
+
+! CHECK: %[[shape:.*]] = fir.shape %[[c31]] : (index) -> !fir.shape<1>
+! CHECK: %[[box:.*]] = fir.embox %[[ptr]] : (!fir.ref<i64>) -> !fir.box<!fir.ref<i64>>
+! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.ref<i64>>) -> !fir.ref<i64>
+! CHECK: %[[val:.*]] = fir.convert %[[addr]] : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<!fir.array<3xi32>>>
+! CHECK: %[[ld:.*]] = fir.load %[[val]] : !fir.ref<!fir.ptr<!fir.array<3xi32>>>
+! CHECK: %[[arrayld:.*]] = fir.array_load %[[ld]](%[[shape]]) : (!fir.ptr<!fir.array<3xi32>>, !fir.shape<1>) -> !fir.array<3xi32>
+! CHECK: %[[c2n:.*]] = arith.constant -2 : i32
+! CHECK: %[[c1:.*]] = arith.constant 1 : index
+! CHECK: %[[c0:.*]] = arith.constant 0 : index
+! CHECK: %[[sub1:.*]] = arith.subi %[[c31]], %[[c1]] : index
+! CHECK: %[[doloop:.*]] = fir.do_loop %arg0 = %[[c0]] to %[[sub1]] step %[[c1]] unordered iter_args(%arg1 = %[[arrayld]]) -> (!fir.array<3xi32>) {
+! CHECK: %[[arrayupdate:.*]] = fir.array_update %arg1, %[[c2n]], %arg0 : (!fir.array<3xi32>, i32, index) -> !fir.array<3xi32>
+! CHECK: fir.result %[[arrayupdate]] : !fir.array<3xi32>
+! CHECK: fir.array_merge_store %[[arrayld]], %[[doloop]] to %[[ld]] : !fir.array<3xi32>, !fir.array<3xi32>, !fir.ptr<!fir.array<3xi32>>
+end
+
+! Test Array Section case
+
+! CHECK-LABEL: func.func @_QPcray_arraysection() {
+subroutine cray_arraySection()
+ integer :: pte, k(2), data(5)
+ pointer (ptr, pte(3))
+ data = [ 1, 2, 3, 4, 5 ]
+ ptr = loc(data(2))
+
+! CHECK: %[[c5:.*]] = arith.constant 5 : index
+! CHECK: %[[data:.*]] = fir.alloca !fir.array<5xi32> {{.*}}
+! CHECK: %[[c2:.*]] = arith.constant 2 : index
+! CHECK: %[[k:.*]] = fir.alloca !fir.array<2xi32> {{.*}}
+! CHECK: %[[c3:.*]] = arith.constant 3 : index
+! CHECK: %[[pte:.*]] = fir.alloca !fir.array<3xi32> {{.*}}
+! CHECK: %[[ptr:.*]] = fir.alloca i64 {{.*}}
+! CHECK: %[[c1:.*]] = arith.constant 2 : i64
+! CHECK: %[[c0:.*]] = arith.constant 1 : i64
+! CHECK: %[[sub:.*]] = arith.subi %[[c1]], %[[c0]] : i64
+! CHECK: %[[cor:.*]] = fir.coordinate_of %[[data]], %[[sub]] : (!fir.ref<!fir.array<5xi32>>, i64) -> !fir.ref<i32>
+! CHECK: %[[box:.*]] = fir.embox %[[cor]] : (!fir.ref<i32>) -> !fir.box<i32>
+! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<i32>) -> !fir.ref<i32>
+! CHECK: %[[val:.*]] = fir.convert %[[addr]] : (!fir.ref<i32>) -> i64
+! CHECK: fir.store %[[val]] to %[[ptr]] : !fir.ref<i64>
+
+ k = pte(2:3)
+ print *, k
+
+! CHECK: %[[shape1:.*]] = fir.shape %[[c2]] : (index) -> !fir.shape<1>
+! CHECK: %[[arrayld1:.*]] = fir.array_load %[[k]](%[[shape1]]) : (!fir.ref<!fir.array<2xi32>>, !fir.shape<1>) -> !fir.array<2xi32>
+! CHECK: %[[c2i64:.*]] = arith.constant 2 : i64
+! CHECK: %[[conv:.*]] = fir.convert %[[c2i64]] : (i64) -> index
+! CHECK: %[[c1i64:.*]] = arith.constant 1 : i64
+! CHECK: %[[conv1:.*]] = fir.convert %[[c1i64]] : (i64) -> index
+! CHECK: %[[c3i64:.*]] = arith.constant 3 : i64
+! CHECK: %[[conv2:.*]] = fir.convert %[[c3i64]] : (i64) -> index
+! CHECK: %[[shape:.*]] = fir.shape %[[c3]] : (index) -> !fir.shape<1>
+! CHECK: %[[slice:.*]] = fir.slice %[[conv]], %[[conv2]], %[[conv1]] : (index, index, index) -> !fir.slice<1>
+! CHECK: %[[box:.*]] = fir.embox %[[ptr]] : (!fir.ref<i64>) -> !fir.box<!fir.ref<i64>>
+! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.ref<i64>>) -> !fir.ref<i64>
+! CHECK: %[[val:.*]] = fir.convert %[[addr]] : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<!fir.array<3xi32>>>
+! CHECK: %[[ld:.*]] = fir.load %[[val]] : !fir.ref<!fir.ptr<!fir.array<3xi32>>>
+! CHECK: %[[arrayld:.*]] = fir.array_load %[[ld]](%[[shape]]) [%[[slice]]] : (!fir.ptr<!fir.array<3xi32>>, !fir.shape<1>, !fir.slice<1>) -> !fir.array<3xi32>
+! CHECK: %[[c1_3:.*]] = arith.constant 1 : index
+! CHECK: %[[c0_4:.*]] = arith.constant 0 : index
+! CHECK: %[[sub:.*]] = arith.subi %[[c2]], %[[c1_3]] : index
+! CHECK: %[[doloop:.*]] = fir.do_loop %arg0 = %[[c0_4]] to %[[sub]] step %[[c1_3]] unordered iter_args(%arg1 = %[[arrayld1]]) -> (!fir.array<2xi32>) {
+! CHECK: %[[arrayfetch:.*]] = fir.array_fetch %[[arrayld]], %arg0 : (!fir.array<3xi32>, index) -> i32
+! CHECK: %[[arrayupdate:.*]] = fir.array_update %arg1, %[[arrayfetch]], %arg0 : (!fir.array<2xi32>, i32, index) -> !fir.array<2xi32>
+! CHECK: fir.result %[[arrayupdate]] : !fir.array<2xi32>
+! CHECK: fir.array_merge_store %[[arrayld1]], %[[doloop]] to %[[k]] : !fir.array<2xi32>, !fir.array<2xi32>, !fir.ref<!fir.array<2xi32>>
+
+ pte(1:2) = -2
+ print *, data
+
+! CHECK: %[[c1_5:.*]] = arith.constant 1 : i64
+! CHECK: %[[conv:.*]] = fir.convert %[[c1_5]] : (i64) -> index
+! CHECK: %[[c1_6:.*]] = arith.constant 1 : i64
+! CHECK: %[[conv1:.*]] = fir.convert %[[c1_6]] : (i64) -> index
+! CHECK: %[[c2_7:.*]] = arith.constant 2 : i64
+! CHECK: %[[conv2:.*]] = fir.convert %[[c2_7]] : (i64) -> index
+! CHECK: %[[c0_8:.*]] = arith.constant 0 : index
+! CHECK: %[[sub:.*]] = arith.subi %[[conv2]], %[[conv]] : index
+! CHECK: %[[add:.*]] = arith.addi %[[sub]], %[[conv1]] : index
+! CHECK: %[[div:.*]] = arith.divsi %[[add]], %[[conv1]] : index
+! CHECK: %[[cmp:.*]] = arith.cmpi sgt, %[[div]], %[[c0_8]] : index
+! CHECK: %[[sel:.*]] = arith.select %[[cmp]], %[[div]], %[[c0_8]] : index
+! CHECK: %[[shape:.*]] = fir.shape %[[c3]] : (index) -> !fir.shape<1>
+! CHECK: %[[slice:.*]] = fir.slice %[[conv]], %[[conv2]], %[[conv1]] : (index, index, index) -> !fir.slice<1>
+! CHECK: %[[box:.*]] = fir.embox %[[ptr]] : (!fir.ref<i64>) -> !fir.box<!fir.ref<i64>>
+! CHECK: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.ref<i64>>) -> !fir.ref<i64>
+! CHECK: %[[val:.*]] = fir.convert %[[addr]] : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<!fir.array<3xi32>>>
+! CHECK: %[[ld:.*]] = fir.load %[[val]] : !fir.ref<!fir.ptr<!fir.array<3xi32>>>
+! CHECK: %[[arrayld:.*]] = fir.array_load %[[ld]](%[[shape]]) [%[[slice]]] : (!fir.ptr<!fir.array<3xi32>>, !fir.shape<1>, !fir.slice<1>) -> !fir.array<3xi32>
+! CHECK: %[[c2n:.*]] = arith.constant -2 : i32
+! CHECK: %[[c1_9:.*]] = arith.constant 1 : index
+! CHECK: %[[c0_8:.*]] = arith.constant 0 : index
+! CHECK: %[[sub1:.*]] = arith.subi %[[sel]], %[[c1_9]] : index
+! CHECK: %[[doloop:.*]] = fir.do_loop %arg0 = %[[c0_8]] to %[[sub1]] step %[[c1_9]] unordered iter_args(%arg1 = %[[arrayld]]) -> (!fir.array<3xi32>) {
+! CHECK: %[[arrayupdate:.*]] = fir.array_update %arg1, %[[c2n]], %arg0 : (!fir.array<3xi32>, i32, index) -> !fir.array<3xi32>
+! CHECK: fir.result %[[arrayupdate]] : !fir.array<3xi32>
+! CHECK: fir.array_merge_store %[[arrayld]], %[[doloop]] to %[[ld]][%[[slice]]] : !fir.array<3xi32>, !fir.array<3xi32>, !fir.ptr<!fir.array<3xi32>>, !fir.slice<1>
+end
More information about the flang-commits
mailing list