[flang-commits] [PATCH] D147239: [flang] Fix context less NULL() lowering

Jean Perier via Phabricator via flang-commits flang-commits at lists.llvm.org
Thu Mar 30 08:46:25 PDT 2023


jeanPerier created this revision.
jeanPerier added reviewers: vzakhari, clementval.
jeanPerier added a project: Flang.
Herald added subscribers: sunshaoce, mehdi_amini, jdoerfert.
Herald added a project: All.
jeanPerier requested review of this revision.

The current context less lowering of NULL is producing invalid code
(can lead to reading outside of allocated memory): it is casting
a simple pointer to a descriptor address.
Later, reads are made to this descriptor. It used to be "OK" when
fir.load of fir.box were no-ops, but this was incorrect, and the
fir.load codegen is known doing a copy, and read the whole descriptor
data, not only the base address.

The previous patch that allowed fir.box<None> allocation, this
code fix this by allocating an actual fir.box<None>.

Note: this is still an overkill way to lower foo(null()). HLFIR
lowering always contextualize NULL() lowering leading to much simpler
code:

  %absent = fir.absent fir.box<T>
  fir.call @foo(%absent)

Depends on: D147237 <https://reviews.llvm.org/D147237>


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D147239

Files:
  flang/lib/Lower/ConvertExpr.cpp
  flang/test/Lower/dummy-argument-optional.f90
  flang/test/Lower/polymorphic.f90


Index: flang/test/Lower/polymorphic.f90
===================================================================
--- flang/test/Lower/polymorphic.f90
+++ flang/test/Lower/polymorphic.f90
@@ -843,15 +843,19 @@
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMpolymorphic_testPtest_call_with_null() {
-! CHECK: %[[NULL_LLVM_PTR:.*]] = fir.alloca !fir.llvm_ptr<none>
-! CHECK: %[[NULL_BOX_NONE:.*]] = fir.convert %[[NULL_LLVM_PTR]] : (!fir.ref<!fir.llvm_ptr<none>>) -> !fir.ref<!fir.box<none>>
-! CHECK: %[[BOX_NONE:.*]] = fir.load %[[NULL_BOX_NONE]] : !fir.ref<!fir.box<none>>
-! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_NONE]] : (!fir.box<none>) -> !fir.ref<none>
-! CHECK: %[[BOX_ADDR_I64:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.ref<none>) -> i64
+! CHECK: %[[NULL_PTR:.*]] = fir.alloca !fir.box<!fir.ptr<none>>
+! CHECK: %[[NULL:.*]] = fir.zero_bits !fir.ptr<none>
+! CHECK: %[[NULL_BOX:.*]] = fir.embox %[[NULL]] : (!fir.ptr<none>) -> !fir.box<!fir.ptr<none>>
+! CHECK: fir.store %[[NULL_BOX]] to %[[NULL_PTR]] : !fir.ref<!fir.box<!fir.ptr<none>>>
+! CHECK: %[[BOX_NONE:.*]] = fir.load %[[NULL_PTR]] : !fir.ref<!fir.box<!fir.ptr<none>>>
+! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_NONE]] : (!fir.box<!fir.ptr<none>>) -> !fir.ptr<none>
+! CHECK: %[[BOX_ADDR_I64:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.ptr<none>) -> i64
 ! CHECK: %[[C0:.*]] = arith.constant 0 : i64
 ! CHECK: %[[IS_ALLOCATED_OR_ASSOCIATED:.*]] = arith.cmpi ne, %[[BOX_ADDR_I64]], %[[C0]] : i64
 ! CHECK: %[[ABSENT:.*]] = fir.absent !fir.class<none>
-! CHECK: %[[BOX_NONE:.*]] = fir.load %[[NULL_BOX_NONE]] : !fir.ref<!fir.box<none>>
+! CHECK: %[[PTR_LOAD2:.*]] = fir.load %[[NULL_PTR]] : !fir.ref<!fir.box<!fir.ptr<none>>>
+! CHECK: %[[BOX_ADDR2:.*]] = fir.box_addr %[[PTR_LOAD2]] : (!fir.box<!fir.ptr<none>>) -> !fir.ptr<none>
+! CHECK: %[[BOX_NONE:.*]] = fir.embox %[[BOX_ADDR2]] : (!fir.ptr<none>) -> !fir.box<none>
 ! CHECK: %[[CLASS_NONE:.*]] = fir.convert %[[BOX_NONE]] : (!fir.box<none>) -> !fir.class<none>
 ! CHECK: %[[ARG:.*]] = arith.select %[[IS_ALLOCATED_OR_ASSOCIATED]], %[[CLASS_NONE]], %[[ABSENT]] : !fir.class<none>
 ! CHECK: fir.call @_QMpolymorphic_testPsub_with_poly_optional(%[[ARG]]) {{.*}} : (!fir.class<none>) -> ()
Index: flang/test/Lower/dummy-argument-optional.f90
===================================================================
--- flang/test/Lower/dummy-argument-optional.f90
+++ flang/test/Lower/dummy-argument-optional.f90
@@ -195,9 +195,10 @@
 
 ! CHECK-LABEL: func @_QMoptPnull_as_optional() {
 subroutine null_as_optional
-  ! CHECK: %[[temp:.*]] = fir.alloca !fir.llvm_ptr<none>
-  ! CHECK: %[[null:.*]] = fir.zero_bits !fir.ref<none>
-  ! CHECK: fir.store %{{.*}} to %[[temp]] : !fir.ref<!fir.llvm_ptr<none>>
+  ! CHECK: %[[null_ptr:.*]] = fir.alloca !fir.box<!fir.ptr<none>>
+  ! CHECK: %[[null:.*]] = fir.zero_bits !fir.ptr<none>
+  ! CHECK: %[[null_box:.*]] = fir.embox %[[null]] : (!fir.ptr<none>) -> !fir.box<!fir.ptr<none>>
+  ! CHECK: fir.store %[[null_box]] to %[[null_ptr]] : !fir.ref<!fir.box<!fir.ptr<none>>>
   ! CHECK: fir.call @_QMoptPassumed_shape(%{{.*}}) {{.*}}: (!fir.box<!fir.array<?xf32>>) -> ()
  call assumed_shape(null())
 end subroutine null_as_optional
Index: flang/lib/Lower/ConvertExpr.cpp
===================================================================
--- flang/lib/Lower/ConvertExpr.cpp
+++ flang/lib/Lower/ConvertExpr.cpp
@@ -711,20 +711,22 @@
   }
 
   /// A `NULL()` in a position where a mutable box is expected has the same
-  /// semantics as an absent optional box value.
+  /// semantics as an absent optional box value. Note: this code should
+  /// be depreciated because the rank information is not known here. A
+  /// scalar fir.box is created: it should not be cast to an array box type
+  /// later, but there is no way to enforce that here.
   ExtValue genMutableBoxValueImpl(const Fortran::evaluate::NullPointer &) {
     mlir::Location loc = getLoc();
-    auto nullConst = builder.createNullConstant(loc);
-    auto noneTy = mlir::NoneType::get(builder.getContext());
-    auto polyRefTy = fir::LLVMPointerType::get(noneTy);
-    // MutableBoxValue will dereference the box, so create a bogus temporary for
-    // the `nullptr`. The LLVM optimizer will garbage collect the temp.
-    auto temp =
-        builder.createTemporary(loc, polyRefTy, /*shape=*/mlir::ValueRange{});
-    auto nullPtr = builder.createConvert(loc, polyRefTy, nullConst);
-    builder.create<fir::StoreOp>(loc, nullPtr, temp);
+    mlir::Type noneTy = mlir::NoneType::get(builder.getContext());
+    mlir::Type polyRefTy = fir::PointerType::get(noneTy);
+    mlir::Type boxType = fir::BoxType::get(polyRefTy);
+    mlir::Value nullConst = builder.createNullConstant(loc, polyRefTy);
+    mlir::Value tempBox =
+        builder.createTemporary(loc, boxType, /*shape=*/mlir::ValueRange{});
+    mlir::Value nullBox = builder.create<fir::EmboxOp>(loc, boxType, nullConst);
+    builder.create<fir::StoreOp>(loc, nullBox, tempBox);
     auto nullBoxTy = builder.getRefType(fir::BoxType::get(noneTy));
-    return fir::MutableBoxValue(builder.createConvert(loc, nullBoxTy, temp),
+    return fir::MutableBoxValue(tempBox,
                                 /*lenParameters=*/mlir::ValueRange{},
                                 /*mutableProperties=*/{});
   }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D147239.509688.patch
Type: text/x-patch
Size: 5297 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/flang-commits/attachments/20230330/5e293c45/attachment-0001.bin>


More information about the flang-commits mailing list