[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