[flang-commits] [flang] [Flang][HLFIR] Bail out of EOSHIFT simplification for polymorphic arrays (PR #223118)

via flang-commits flang-commits at lists.llvm.org
Fri Sep 11 20:36:41 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-fir-hlfir

Author: Daniel Chen (DanielCChen)

<details>
<summary>Changes</summary>

Consider the following code
```
module m
    type Base
        integer :: i = 8
    end type

    type, extends(Base) :: Child
        integer :: j = 9
    end type
end module

program argumentKeyword002
use m
    class(*), pointer :: b1(:,:,:), boundVal

    allocate(b1(3,2,2), SOURCE=reshape((/(i,i=1,12)/), &
     (/3,2,2/)))

    allocate (boundVal, source=0)

    select type(name1=>eoshift(SHIFT=reshape((/1,-2,2,-1/),(/2,2/)), &
     ARRAY=b1,DIM=1, BOUNDARY=boundVal))
        type is (integer)
            print *, name1
            print *, shape(name1)
        class default
            ERROR STOP(1_4)
    end select
end
```

it passed at `-O0` but failed at `-O3` as
```
argumentKeyword002.f":38:5): error: 'fir.result' op types mismatch between result op and its parent
error: Lowering to LLVM IR failed
```

The reason is that the `SimplifyHLFIRIntrinsics` is trying to inline `EOSHIFT` of a `CLASS(*)` array as an `hlfir.elemental` produces a `fir.if` with mismatched types on the branches (e.g., `!fir.class<none>` vs. pointer-qualified `!fir.class<!fir.ptr<none>>`).

By looking at the code, we currently bail-out derived type array so it falls back to the runtime code. Polymorphic array should be bailed-out also for now and handled with derived type together in the future. 

---
Full diff: https://github.com/llvm/llvm-project/pull/223118.diff


2 Files Affected:

- (modified) flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp (+5-4) 
- (modified) flang/test/HLFIR/simplify-hlfir-intrinsics-eoshift.fir (+34) 


``````````diff
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp b/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp
index 716737bb80ff4f..0e28a91afbd90b 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp
@@ -1461,10 +1461,11 @@ class ArrayShiftConversion : public mlir::OpRewritePattern<Op> {
           return rewriter.notifyMatchFailure(
               op, "EOSHIFT with BOUNDARY being CHARACTER expression");
       }
-      // TODO: selecting between ARRAY and BOUNDARY values with derived types
-      // need more work.
-      if (fir::isa_derived(expr.getEleTy()))
-        return rewriter.notifyMatchFailure(op, "EOSHIFT of derived type");
+      // TODO: selecting between ARRAY and BOUNDARY values with derived or
+      // polymorphic types need more work.
+      if (fir::isa_derived(expr.getEleTy()) || expr.isPolymorphic())
+        return rewriter.notifyMatchFailure(
+            op, "EOSHIFT of derived or polymorphic type");
     }
 
     // When DIM==1 and the contiguity of the input array is not statically
diff --git a/flang/test/HLFIR/simplify-hlfir-intrinsics-eoshift.fir b/flang/test/HLFIR/simplify-hlfir-intrinsics-eoshift.fir
index 14064b51312686..e2a9fdb9a82e2a 100644
--- a/flang/test/HLFIR/simplify-hlfir-intrinsics-eoshift.fir
+++ b/flang/test/HLFIR/simplify-hlfir-intrinsics-eoshift.fir
@@ -2160,3 +2160,37 @@ func.func @_QPeoshift1d(%arg0: !fir.ref<i32> {fir.bindc_name = "n"}, %arg1: !fir
 }
 // CHECK-LABEL:   func.func @_QPeoshift1d(
 // CHECK: hlfir.eoshift
+
+// ! Test CLASS(*) (unlimited polymorphic) array.
+// ! Since unlimited polymorphic arrays can dynamically hold derived types
+// ! and have runtime-determined types, EOSHIFT simplification must be skipped
+// ! (bail-out).
+// CHECK-LABEL:   func.func @_QQmain_eoshift_unlimited_poly(
+// CHECK:           hlfir.eoshift
+func.func @_QQmain_eoshift_unlimited_poly(
+    %arg0: !fir.class<!fir.ptr<!fir.array<?x?x?xnone>>> {fir.bindc_name = "b1"},
+    %arg1: !fir.class<!fir.ptr<none>> {fir.bindc_name = "boundval"}) {
+  %c1_i32 = arith.constant 1 : i32
+  %0 = fir.dummy_scope : !fir.dscope
+  %1:2 = hlfir.declare %arg0 dummy_scope %0 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QQmainEb1"} : (!fir.class<!fir.ptr<!fir.array<?x?x?xnone>>>, !fir.dscope) -> (!fir.class<!fir.array<?x?x?xnone>>, !fir.class<!fir.array<?x?x?xnone>>)
+  %2:2 = hlfir.declare %arg1 dummy_scope %0 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QQmainEboundval"} : (!fir.class<!fir.ptr<none>>, !fir.dscope) -> (!fir.class<none>, !fir.class<none>)
+  %4 = hlfir.eoshift %1#0 %c1_i32 boundary %2#0 dim %c1_i32 : (!fir.class<!fir.array<?x?x?xnone>>, i32, !fir.class<none>, i32) -> !hlfir.expr<?x?x?xnone?>
+  hlfir.destroy %4 : !hlfir.expr<?x?x?xnone?>
+  return
+}
+
+// ! Test CLASS(T) (bounded polymorphic) array.
+// ! Bounded polymorphic arrays also bail out.
+// CHECK-LABEL:   func.func @_QQmain_eoshift_bounded_poly(
+// CHECK:           hlfir.eoshift
+func.func @_QQmain_eoshift_bounded_poly(
+    %arg0: !fir.class<!fir.ptr<!fir.array<?x?x?x!fir.type<_QMmTbase{i:i32}>>>> {fir.bindc_name = "b1"},
+    %arg1: !fir.class<!fir.ptr<!fir.type<_QMmTbase{i:i32}>>> {fir.bindc_name = "boundval"}) {
+  %c1_i32 = arith.constant 1 : i32
+  %0 = fir.dummy_scope : !fir.dscope
+  %1:2 = hlfir.declare %arg0 dummy_scope %0 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QQmainEb1_bounded"} : (!fir.class<!fir.ptr<!fir.array<?x?x?x!fir.type<_QMmTbase{i:i32}>>>>, !fir.dscope) -> (!fir.class<!fir.array<?x?x?x!fir.type<_QMmTbase{i:i32}>>>, !fir.class<!fir.array<?x?x?x!fir.type<_QMmTbase{i:i32}>>>)
+  %2:2 = hlfir.declare %arg1 dummy_scope %0 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QQmainEboundval_bounded"} : (!fir.class<!fir.ptr<!fir.type<_QMmTbase{i:i32}>>>, !fir.dscope) -> (!fir.class<!fir.type<_QMmTbase{i:i32}>>, !fir.class<!fir.type<_QMmTbase{i:i32}>>)
+  %4 = hlfir.eoshift %1#0 %c1_i32 boundary %2#0 dim %c1_i32 : (!fir.class<!fir.array<?x?x?x!fir.type<_QMmTbase{i:i32}>>>, i32, !fir.class<!fir.type<_QMmTbase{i:i32}>>, i32) -> !hlfir.expr<?x?x?x!fir.type<_QMmTbase{i:i32}>?>
+  hlfir.destroy %4 : !hlfir.expr<?x?x?x!fir.type<_QMmTbase{i:i32}>?>
+  return
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/223118


More information about the flang-commits mailing list