Skip to content

Commit

Permalink
[Flang] Cray pointer Lowering
Browse files Browse the repository at this point in the history
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
  • Loading branch information
madanial0 committed Aug 22, 2023
1 parent d3d4d78 commit a1c736e
Show file tree
Hide file tree
Showing 4 changed files with 519 additions and 2 deletions.
4 changes: 4 additions & 0 deletions flang/include/flang/Lower/ConvertExpr.h
Expand Up @@ -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
20 changes: 20 additions & 0 deletions flang/lib/Lower/Bridge.cpp
Expand Up @@ -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);
Expand Down
93 changes: 91 additions & 2 deletions flang/lib/Lower/ConvertExpr.cpp
Expand Up @@ -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 different types
// tags all result variables with one of the largest types to allow
Expand All @@ -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;
}

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
}

0 comments on commit a1c736e

Please sign in to comment.