[flang-commits] [flang] 49c08a2 - [Flang] Add the FIR LLVMPointer Type

Kiran Chandramohan via flang-commits flang-commits at lists.llvm.org
Mon Nov 15 07:58:20 PST 2021


Author: Kiran Chandramohan
Date: 2021-11-15T15:57:59Z
New Revision: 49c08a22edc36abc3c6bf381565bf1963338a57d

URL: https://github.com/llvm/llvm-project/commit/49c08a22edc36abc3c6bf381565bf1963338a57d
DIFF: https://github.com/llvm/llvm-project/commit/49c08a22edc36abc3c6bf381565bf1963338a57d.diff

LOG: [Flang] Add the FIR LLVMPointer Type

Add a fir.llvm_ptr type to allow any level of indirections

Currently, fir pointer types (fir.ref, fir.ptr, and fir.heap) carry
a special Fortran semantics, and cannot be freely combined/nested.

When implementing some features, lowering sometimes needs more liberty
regarding the number of indirection levels. Add a fir.llvm_ptr that has
no constraints.

Allow its usage in fir.coordinate_op, fir.load, and fir.store.

Convert the FIR LLVMPointer to an LLVMPointer in the LLVM dialect.

Reviewed By: clementval

Differential Revision: https://reviews.llvm.org/D113755

Co-authored-by: Jean Perier <jperier at nvidia.com>

Added: 
    

Modified: 
    flang/include/flang/Optimizer/Dialect/FIROps.td
    flang/include/flang/Optimizer/Dialect/FIRType.h
    flang/include/flang/Optimizer/Dialect/FIRTypes.td
    flang/lib/Optimizer/CodeGen/TypeConverter.h
    flang/lib/Optimizer/Dialect/FIROps.cpp
    flang/lib/Optimizer/Dialect/FIRType.cpp
    flang/test/Fir/fir-ops.fir
    flang/test/Fir/fir-types.fir
    flang/test/Fir/types-to-llvm.fir

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td
index 8257c8a4f2f4..2d4261ea49b5 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROps.td
+++ b/flang/include/flang/Optimizer/Dialect/FIROps.td
@@ -1661,7 +1661,7 @@ def fir_CoordinateOp : fir_Op<"coordinate_of", [NoSideEffect]> {
     TypeAttr:$baseType
   );
 
-  let results = (outs fir_ReferenceType);
+  let results = (outs RefOrLLVMPtr);
 
   let parser =  "return parseCoordinateCustom(parser, result);";
   let printer = "::print(p, *this);";

diff  --git a/flang/include/flang/Optimizer/Dialect/FIRType.h b/flang/include/flang/Optimizer/Dialect/FIRType.h
index f5a0f0081b80..e78b4cc66280 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRType.h
+++ b/flang/include/flang/Optimizer/Dialect/FIRType.h
@@ -59,7 +59,8 @@ bool isa_fir_or_std_type(mlir::Type t);
 
 /// Is `t` a FIR dialect type that implies a memory (de)reference?
 inline bool isa_ref_type(mlir::Type t) {
-  return t.isa<ReferenceType>() || t.isa<PointerType>() || t.isa<HeapType>();
+  return t.isa<ReferenceType>() || t.isa<PointerType>() || t.isa<HeapType>() ||
+         t.isa<fir::LLVMPointerType>();
 }
 
 /// Is `t` a boxed type?

diff  --git a/flang/include/flang/Optimizer/Dialect/FIRTypes.td b/flang/include/flang/Optimizer/Dialect/FIRTypes.td
index 28ad6df503d5..b57f4182b929 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRTypes.td
+++ b/flang/include/flang/Optimizer/Dialect/FIRTypes.td
@@ -224,6 +224,22 @@ def fir_LogicalType : FIR_Type<"Logical", "logical"> {
   }];
 }
 
+def fir_LLVMPointerType : FIR_Type<"LLVMPointer", "llvm_ptr"> {
+  let summary = "Like LLVM pointer type";
+
+  let description = [{
+    A pointer type that does not have any of the constraints and semantics
+    of other FIR pointer types and that translates to llvm pointer types.
+    It is meant to implement indirection that cannot be expressed directly
+    in Fortran, but are needed to implement some Fortran features (e.g,
+    double indirections).
+  }];
+
+  let parameters = (ins "mlir::Type":$eleTy);
+
+  let assemblyFormat = "`<` $eleTy `>`";
+}
+
 def fir_PointerType : FIR_Type<"Pointer", "ptr"> {
   let summary = "Reference to a POINTER attribute type";
 
@@ -516,7 +532,11 @@ def AnyCompositeLike : TypeConstraint<Or<[fir_RecordType.predicate,
 
 // Reference types
 def AnyReferenceLike : TypeConstraint<Or<[fir_ReferenceType.predicate,
-    fir_HeapType.predicate, fir_PointerType.predicate]>, "any reference">;
+    fir_HeapType.predicate, fir_PointerType.predicate,
+    fir_LLVMPointerType.predicate]>, "any reference">;
+
+def RefOrLLVMPtr : TypeConstraint<Or<[fir_ReferenceType.predicate,
+    fir_LLVMPointerType.predicate]>, "fir.ref or fir.llvm_ptr">;
 
 def AnyBoxLike : TypeConstraint<Or<[fir_BoxType.predicate,
     fir_BoxCharType.predicate, fir_BoxProcType.predicate]>, "any box">;

diff  --git a/flang/lib/Optimizer/CodeGen/TypeConverter.h b/flang/lib/Optimizer/CodeGen/TypeConverter.h
index ba10280b3325..87b47f749d04 100644
--- a/flang/lib/Optimizer/CodeGen/TypeConverter.h
+++ b/flang/lib/Optimizer/CodeGen/TypeConverter.h
@@ -65,6 +65,9 @@ class LLVMTypeConverter : public mlir::LLVMTypeConverter {
       return mlir::IntegerType::get(
           &getContext(), kindMapping.getLogicalBitsize(boolTy.getFKind()));
     });
+    addConversion([&](fir::LLVMPointerType pointer) {
+      return convertPointerLike(pointer);
+    });
     addConversion(
         [&](fir::PointerType pointer) { return convertPointerLike(pointer); });
     addConversion(

diff  --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp
index 2e30d1e9afce..32c3e8fd747d 100644
--- a/flang/lib/Optimizer/Dialect/FIROps.cpp
+++ b/flang/lib/Optimizer/Dialect/FIROps.cpp
@@ -824,8 +824,9 @@ bool fir::ConvertOp::isFloatCompatible(mlir::Type ty) {
 
 bool fir::ConvertOp::isPointerCompatible(mlir::Type ty) {
   return ty.isa<fir::ReferenceType>() || ty.isa<fir::PointerType>() ||
-         ty.isa<fir::HeapType>() || ty.isa<mlir::MemRefType>() ||
-         ty.isa<mlir::FunctionType>() || ty.isa<fir::TypeDescType>();
+         ty.isa<fir::HeapType>() || ty.isa<fir::LLVMPointerType>() ||
+         ty.isa<mlir::MemRefType>() || ty.isa<mlir::FunctionType>() ||
+         ty.isa<fir::TypeDescType>();
 }
 
 static mlir::LogicalResult verify(fir::ConvertOp &op) {
@@ -1755,16 +1756,8 @@ void fir::LoadOp::build(mlir::OpBuilder &builder, mlir::OperationState &result,
   result.addTypes(eleTy);
 }
 
-/// Get the element type of a reference like type; otherwise null
-static mlir::Type elementTypeOf(mlir::Type ref) {
-  return llvm::TypeSwitch<mlir::Type, mlir::Type>(ref)
-      .Case<ReferenceType, PointerType, HeapType>(
-          [](auto type) { return type.getEleTy(); })
-      .Default([](mlir::Type) { return mlir::Type{}; });
-}
-
 mlir::ParseResult fir::LoadOp::getElementOf(mlir::Type &ele, mlir::Type ref) {
-  if ((ele = elementTypeOf(ref)))
+  if ((ele = fir::dyn_cast_ptrEleTy(ref)))
     return mlir::success();
   return mlir::failure();
 }

diff  --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp
index c90a88b78113..88890b208698 100644
--- a/flang/lib/Optimizer/Dialect/FIRType.cpp
+++ b/flang/lib/Optimizer/Dialect/FIRType.cpp
@@ -200,15 +200,15 @@ bool isa_fir_or_std_type(mlir::Type t) {
 
 mlir::Type dyn_cast_ptrEleTy(mlir::Type t) {
   return llvm::TypeSwitch<mlir::Type, mlir::Type>(t)
-      .Case<fir::ReferenceType, fir::PointerType, fir::HeapType>(
-          [](auto p) { return p.getEleTy(); })
+      .Case<fir::ReferenceType, fir::PointerType, fir::HeapType,
+            fir::LLVMPointerType>([](auto p) { return p.getEleTy(); })
       .Default([](mlir::Type) { return mlir::Type{}; });
 }
 
 mlir::Type dyn_cast_ptrOrBoxEleTy(mlir::Type t) {
   return llvm::TypeSwitch<mlir::Type, mlir::Type>(t)
-      .Case<fir::ReferenceType, fir::PointerType, fir::HeapType>(
-          [](auto p) { return p.getEleTy(); })
+      .Case<fir::ReferenceType, fir::PointerType, fir::HeapType,
+            fir::LLVMPointerType>([](auto p) { return p.getEleTy(); })
       .Case<fir::BoxType>([](auto p) {
         auto eleTy = p.getEleTy();
         if (auto ty = fir::dyn_cast_ptrEleTy(eleTy))
@@ -864,7 +864,7 @@ bool fir::VectorType::isValidElementType(mlir::Type t) {
 void FIROpsDialect::registerTypes() {
   addTypes<BoxType, BoxCharType, BoxProcType, CharacterType, fir::ComplexType,
            FieldType, HeapType, fir::IntegerType, LenType, LogicalType,
-           PointerType, RealType, RecordType, ReferenceType, SequenceType,
-           ShapeType, ShapeShiftType, ShiftType, SliceType, TypeDescType,
-           fir::VectorType>();
+           LLVMPointerType, PointerType, RealType, RecordType, ReferenceType,
+           SequenceType, ShapeType, ShapeShiftType, ShiftType, SliceType,
+           TypeDescType, fir::VectorType>();
 }

diff  --git a/flang/test/Fir/fir-ops.fir b/flang/test/Fir/fir-ops.fir
index e15682fb8a80..bbb59a0216e1 100644
--- a/flang/test/Fir/fir-ops.fir
+++ b/flang/test/Fir/fir-ops.fir
@@ -707,3 +707,18 @@ func @slice_substr() {
   // CHECK: fir.slice %{{.*}}, %{{.*}}, %{{.*}} substr %{{.*}}, %{{.*}} : (index, index, index, index, index) -> !fir.slice<1>
   return
 }
+
+// Test load, store, coordinate_of with llvmptr type
+// CHECK-LABEL: llvm_ptr_load_store_coordinate
+// CHECK-SAME: (%[[ARG0:.*]]: !fir.ref<tuple<!fir.ref<!fir.box<!fir.ptr<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>>>, %[[ARG1:.*]]: !fir.ref<!fir.box<!fir.ptr<f32>>>)
+func @llvm_ptr_load_store_coordinate(%arg0: !fir.ref<tuple<!fir.ref<!fir.box<!fir.ptr<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>>>, %arg1: !fir.ref<!fir.box<!fir.ptr<f32>>>) -> !fir.ref<!fir.box<!fir.ptr<f32>>> {
+  // CHECK-NEXT: %[[C0:.*]] = arith.constant 0 : i32
+  %c0_i32 = arith.constant 0 : i32
+  // CHECK-NEXT: %[[LLVMPTR:.*]] = fir.coordinate_of %[[ARG0]], %[[C0]] : (!fir.ref<tuple<!fir.ref<!fir.box<!fir.ptr<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>>>, i32) -> !fir.llvm_ptr<!fir.ref<!fir.box<!fir.ptr<f32>>>>
+  %0 = fir.coordinate_of %arg0, %c0_i32 : (!fir.ref<tuple<!fir.ref<!fir.box<!fir.ptr<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>>>, i32) -> !fir.llvm_ptr<!fir.ref<!fir.box<!fir.ptr<f32>>>>
+  // CHECK-NEXT: fir.store %[[ARG1]] to %[[LLVMPTR]] : !fir.llvm_ptr<!fir.ref<!fir.box<!fir.ptr<f32>>>>
+  fir.store %arg1 to %0 : !fir.llvm_ptr<!fir.ref<!fir.box<!fir.ptr<f32>>>>
+  // CHECK-NEXT: fir.load %[[LLVMPTR]] : !fir.llvm_ptr<!fir.ref<!fir.box<!fir.ptr<f32>>>>
+  %1 = fir.load %0 : !fir.llvm_ptr<!fir.ref<!fir.box<!fir.ptr<f32>>>>
+  return %1 : !fir.ref<!fir.box<!fir.ptr<f32>>>
+}

diff  --git a/flang/test/Fir/fir-types.fir b/flang/test/Fir/fir-types.fir
index 82345d621331..cab8fcfa051e 100644
--- a/flang/test/Fir/fir-types.fir
+++ b/flang/test/Fir/fir-types.fir
@@ -55,10 +55,14 @@ func private @arr7() -> !fir.array<1x2x?x4x5x6x7x8x9xf32>
 // CHECK-LABEL: func private @mem2() -> !fir.ptr<i32>
 // CHECK-LABEL: func private @mem3() -> !fir.heap<i32>
 // CHECK-LABEL: func private @mem4() -> !fir.ref<() -> ()>
+// CHECK-LABEL: func private @mem5() -> !fir.llvm_ptr<!fir.ref<f32>>
+// CHECK-LABEL: func private @mem6() -> !fir.llvm_ptr<i8>
 func private @mem1() -> !fir.ref<i32>
 func private @mem2() -> !fir.ptr<i32>
 func private @mem3() -> !fir.heap<i32>
 func private @mem4() -> !fir.ref<() -> ()>
+func private @mem5() -> !fir.llvm_ptr<!fir.ref<f32>>
+func private @mem6() -> !fir.llvm_ptr<i8>
 
 // FIR box types (descriptors)
 // CHECK-LABEL: func private @box1() -> !fir.box<!fir.array<?xf32>>

diff  --git a/flang/test/Fir/types-to-llvm.fir b/flang/test/Fir/types-to-llvm.fir
index d1e93a4fa1ee..4eed1ca2dfdc 100644
--- a/flang/test/Fir/types-to-llvm.fir
+++ b/flang/test/Fir/types-to-llvm.fir
@@ -176,6 +176,26 @@ func private @foo4(%arg0: !fir.logical<16>)
 
 // -----
 
+// Test `!fir.llvm_ptr` conversion.
+
+func private @foo0(%arg0: !fir.llvm_ptr<i8>)
+// CHECK-LABEL: foo0
+// CHECK-SAME: !llvm.ptr<i8>
+
+func private @foo1(%arg0: !fir.llvm_ptr<!fir.ref<f32>>)
+// CHECK-LABEL: foo1
+// CHECK-SAME: !llvm.ptr<ptr<f32>>
+
+func private @foo2(%arg0: !fir.llvm_ptr<!fir.ref<!fir.box<!fir.ptr<i32>>>>)
+// CHECK-LABEL: foo2
+// CHECK-SAME: !llvm.ptr<ptr<struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>>>
+
+func private @foo3(%arg0: !fir.llvm_ptr<!fir.ptr<f32>>)
+// CHECK-LABEL: foo3
+// CHECK-SAME: !llvm.ptr<ptr<f32>>
+
+// -----
+
 // Test `!fir.complex<KIND>` conversion.
 
 func private @foo0(%arg0: !fir.complex<2>)


        


More information about the flang-commits mailing list