[flang-commits] [flang] b668de2 - [flang] fix optional pointer TARGET argument lowering in ASSOCIATED

Jean Perier via flang-commits flang-commits at lists.llvm.org
Tue Sep 20 01:17:53 PDT 2022


Author: Jean Perier
Date: 2022-09-20T10:16:58+02:00
New Revision: b668de2de2c2216a744454dd5144b35a68698031

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

LOG: [flang] fix optional pointer TARGET argument lowering in ASSOCIATED

The TARGET argument of ASSOCIATED has a special lowering to deal with
POINTER and ALLOCATABLE optional actual arguments because they may be
dynamically absent. The previous code was doing a ternary
(mlir::SelectOp) to deal with this case, but generated invalid
code for the unused argument (loading a nullptr fir.ref<fir.box>). This
was not detected until D133779 was merged and modified how fir.load are
lowered to LLVM for fir.box types.

Replace the select by a proper if to prevent the fir.load from being
reachable in context where it should not.

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

Added: 
    

Modified: 
    flang/lib/Lower/IntrinsicCall.cpp
    flang/test/Lower/Intrinsics/associated.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp
index aa86215f43813..cd5c1bbfc7131 100644
--- a/flang/lib/Lower/IntrinsicCall.cpp
+++ b/flang/lib/Lower/IntrinsicCall.cpp
@@ -2404,7 +2404,7 @@ IntrinsicLibrary::genAssociated(mlir::Type resultType,
   if (isStaticallyAbsent(target))
     return fir::factory::genIsAllocatedOrAssociatedTest(builder, loc, *pointer);
 
-  mlir::Value targetBox = builder.createBox(loc, target);
+  mlir::Value targetBox;
   if (fir::valueHasFirAttribute(fir::getBase(target),
                                 fir::getOptionalAttrName())) {
     // Subtle: contrary to other intrinsic optional arguments, disassociated
@@ -2416,11 +2416,26 @@ IntrinsicLibrary::genAssociated(mlir::Type resultType,
     // to rerun false.  The runtime deals with the disassociated/unallocated
     // case. Simply ensures that TARGET that are OPTIONAL get conditionally
     // emboxed here to convey the optional aspect to the runtime.
+    mlir::Type boxType = fir::BoxType::get(builder.getNoneType());
     auto isPresent = builder.create<fir::IsPresentOp>(loc, builder.getI1Type(),
                                                       fir::getBase(target));
-    auto absentBox = builder.create<fir::AbsentOp>(loc, targetBox.getType());
-    targetBox = builder.create<mlir::arith::SelectOp>(loc, isPresent, targetBox,
-                                                      absentBox);
+    targetBox = builder
+                    .genIfOp(loc, {boxType}, isPresent,
+                             /*withElseRegion=*/true)
+                    .genThen([&]() {
+                      mlir::Value box = builder.createBox(loc, target);
+                      mlir::Value cast =
+                          builder.createConvert(loc, boxType, box);
+                      builder.create<fir::ResultOp>(loc, cast);
+                    })
+                    .genElse([&]() {
+                      mlir::Value absentBox =
+                          builder.create<fir::AbsentOp>(loc, boxType);
+                      builder.create<fir::ResultOp>(loc, absentBox);
+                    })
+                    .getResults()[0];
+  } else {
+    targetBox = builder.createBox(loc, target);
   }
   mlir::Value pointerBoxRef =
       fir::factory::getMutableIRBox(builder, loc, *pointer);

diff  --git a/flang/test/Lower/Intrinsics/associated.f90 b/flang/test/Lower/Intrinsics/associated.f90
index 5c784574e73fa..ae55a0a99d9af 100644
--- a/flang/test/Lower/Intrinsics/associated.f90
+++ b/flang/test/Lower/Intrinsics/associated.f90
@@ -47,15 +47,19 @@ subroutine test_optional_target_1(p, optionales_ziel)
     real, optional, target :: optionales_ziel(10)
     print *, associated(p, optionales_ziel)
   ! CHECK:  %[[VAL_2:.*]] = arith.constant 10 : index
-  ! CHECK:  %[[VAL_8:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
-  ! CHECK:  %[[VAL_9:.*]] = fir.embox %[[VAL_1]](%[[VAL_8]]) : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<10xf32>>
-  ! CHECK:  %[[VAL_10:.*]] = fir.is_present %[[VAL_1]] : (!fir.ref<!fir.array<10xf32>>) -> i1
-  ! CHECK:  %[[VAL_11:.*]] = fir.absent !fir.box<!fir.array<10xf32>>
-  ! CHECK:  %[[VAL_12:.*]] = arith.select %[[VAL_10]], %[[VAL_9]], %[[VAL_11]] : !fir.box<!fir.array<10xf32>>
+  ! CHECK:  %[[VAL_3:.*]] = fir.is_present %[[VAL_1]] : (!fir.ref<!fir.array<10xf32>>) -> i1
+  ! CHECK:  %[[VAL_4:.*]] = fir.if %[[VAL_3]] -> (!fir.box<none>) {
+  ! CHECK:    %[[VAL_5:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
+  ! CHECK:    %[[VAL_6:.*]] = fir.embox %[[VAL_1]](%[[VAL_5]]) : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<10xf32>>
+  ! CHECK:    %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (!fir.box<!fir.array<10xf32>>) -> !fir.box<none>
+  ! CHECK:    fir.result %[[VAL_7]] : !fir.box<none>
+  ! CHECK:  } else {
+  ! CHECK:    %[[VAL_8:.*]] = fir.absent !fir.box<none>
+  ! CHECK:    fir.result %[[VAL_8]] : !fir.box<none>
+  ! CHECK:  }
   ! CHECK:  %[[VAL_13:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
   ! CHECK:  %[[VAL_14:.*]] = fir.convert %[[VAL_13]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>) -> !fir.box<none>
-  ! CHECK:  %[[VAL_15:.*]] = fir.convert %[[VAL_12]] : (!fir.box<!fir.array<10xf32>>) -> !fir.box<none>
-  ! CHECK:  fir.call @_FortranAPointerIsAssociatedWith(%[[VAL_14]], %[[VAL_15]]) : (!fir.box<none>, !fir.box<none>) -> i1
+  ! CHECK:  fir.call @_FortranAPointerIsAssociatedWith(%[[VAL_14]], %[[VAL_4]]) : (!fir.box<none>, !fir.box<none>) -> i1
   end subroutine
   
   ! CHECK-LABEL: func @_QPtest_optional_target_2(
@@ -66,12 +70,16 @@ subroutine test_optional_target_2(p, optionales_ziel)
     real, optional, target :: optionales_ziel(:)
     print *, associated(p, optionales_ziel)
   ! CHECK:  %[[VAL_7:.*]] = fir.is_present %[[VAL_1]] : (!fir.box<!fir.array<?xf32>>) -> i1
-  ! CHECK:  %[[VAL_8:.*]] = fir.absent !fir.box<!fir.array<?xf32>>
-  ! CHECK:  %[[VAL_9:.*]] = arith.select %[[VAL_7]], %[[VAL_1]], %[[VAL_8]] : !fir.box<!fir.array<?xf32>>
+  ! CHECK:  %[[VAL_8:.*]] = fir.if %[[VAL_7]] -> (!fir.box<none>) {
+  ! CHECK:    %[[VAL_9:.*]] = fir.convert %[[VAL_1]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none>
+  ! CHECK:    fir.result %[[VAL_9]] : !fir.box<none>
+  ! CHECK:  } else {
+  ! CHECK:    %[[VAL_10:.*]] = fir.absent !fir.box<none>
+  ! CHECK:    fir.result %[[VAL_10]] : !fir.box<none>
+  ! CHECK:  }
   ! CHECK:  %[[VAL_10:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
   ! CHECK:  %[[VAL_11:.*]] = fir.convert %[[VAL_10]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>) -> !fir.box<none>
-  ! CHECK:  %[[VAL_12:.*]] = fir.convert %[[VAL_9]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none>
-  ! CHECK:  fir.call @_FortranAPointerIsAssociatedWith(%[[VAL_11]], %[[VAL_12]]) : (!fir.box<none>, !fir.box<none>) -> i1
+  ! CHECK:  fir.call @_FortranAPointerIsAssociatedWith(%[[VAL_11]], %[[VAL_8]]) : (!fir.box<none>, !fir.box<none>) -> i1
   end subroutine
   
   ! CHECK-LABEL: func @_QPtest_optional_target_3(
@@ -81,14 +89,18 @@ subroutine test_optional_target_3(p, optionales_ziel)
     real, pointer :: p(:)
     real, optional, pointer :: optionales_ziel(:)
     print *, associated(p, optionales_ziel)
-  ! CHECK:  %[[VAL_7:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
   ! CHECK:  %[[VAL_8:.*]] = fir.is_present %[[VAL_1]] : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> i1
-  ! CHECK:  %[[VAL_9:.*]] = fir.absent !fir.box<!fir.ptr<!fir.array<?xf32>>>
-  ! CHECK:  %[[VAL_10:.*]] = arith.select %[[VAL_8]], %[[VAL_7]], %[[VAL_9]] : !fir.box<!fir.ptr<!fir.array<?xf32>>>
+  ! CHECK:  %[[VAL_9:.*]] = fir.if %[[VAL_8]] -> (!fir.box<none>) {
+  ! CHECK:    %[[VAL_10:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+  ! CHECK:    %[[VAL_11:.*]] = fir.convert %[[VAL_10]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>) -> !fir.box<none>
+  ! CHECK:    fir.result %[[VAL_11]] : !fir.box<none>
+  ! CHECK:  } else {
+  ! CHECK:    %[[VAL_12:.*]] = fir.absent !fir.box<none>
+  ! CHECK:    fir.result %[[VAL_12]] : !fir.box<none>
+  ! CHECK:  }
   ! CHECK:  %[[VAL_11:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
   ! CHECK:  %[[VAL_12:.*]] = fir.convert %[[VAL_11]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>) -> !fir.box<none>
-  ! CHECK:  %[[VAL_13:.*]] = fir.convert %[[VAL_10]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>) -> !fir.box<none>
-  ! CHECK:  fir.call @_FortranAPointerIsAssociatedWith(%[[VAL_12]], %[[VAL_13]]) : (!fir.box<none>, !fir.box<none>) -> i1
+  ! CHECK:  fir.call @_FortranAPointerIsAssociatedWith(%[[VAL_12]], %[[VAL_9]]) : (!fir.box<none>, !fir.box<none>) -> i1
   end subroutine
   
   ! CHECK-LABEL: func @_QPtest_optional_target_4(
@@ -98,14 +110,18 @@ subroutine test_optional_target_4(p, optionales_ziel)
     real, pointer :: p(:)
     real, optional, allocatable, target :: optionales_ziel(:)
     print *, associated(p, optionales_ziel)
-  ! CHECK:  %[[VAL_7:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
   ! CHECK:  %[[VAL_8:.*]] = fir.is_present %[[VAL_1]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> i1
-  ! CHECK:  %[[VAL_9:.*]] = fir.absent !fir.box<!fir.heap<!fir.array<?xf32>>>
-  ! CHECK:  %[[VAL_10:.*]] = arith.select %[[VAL_8]], %[[VAL_7]], %[[VAL_9]] : !fir.box<!fir.heap<!fir.array<?xf32>>>
+  ! CHECK:  %[[VAL_9:.*]] = fir.if %[[VAL_8]] -> (!fir.box<none>) {
+  ! CHECK:    %[[VAL_10:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+  ! CHECK:    %[[VAL_11:.*]] = fir.convert %[[VAL_10]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.box<none>
+  ! CHECK:    fir.result %[[VAL_11]] : !fir.box<none>
+  ! CHECK:  } else {
+  ! CHECK:    %[[VAL_12:.*]] = fir.absent !fir.box<none>
+  ! CHECK:    fir.result %[[VAL_12]] : !fir.box<none>
+  ! CHECK:  }
   ! CHECK:  %[[VAL_11:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
   ! CHECK:  %[[VAL_12:.*]] = fir.convert %[[VAL_11]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>) -> !fir.box<none>
-  ! CHECK:  %[[VAL_13:.*]] = fir.convert %[[VAL_10]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.box<none>
-  ! CHECK:  fir.call @_FortranAPointerIsAssociatedWith(%[[VAL_12]], %[[VAL_13]]) : (!fir.box<none>, !fir.box<none>) -> i1
+  ! CHECK:  fir.call @_FortranAPointerIsAssociatedWith(%[[VAL_12]], %[[VAL_9]]) : (!fir.box<none>, !fir.box<none>) -> i1
   end subroutine
   
   ! CHECK-LABEL: func @_QPtest_pointer_target(


        


More information about the flang-commits mailing list