[flang-commits] [flang] [flang] Fix ICE when lowering IBM vector() array through fir.box (PR #214219)

Daniel Chen via flang-commits flang-commits at lists.llvm.org
Wed Aug 5 21:06:18 PDT 2026


https://github.com/DanielCChen updated https://github.com/llvm/llvm-project/pull/214219

>From dacb1a97bb3de9bf52015dd9998653c11f27036e Mon Sep 17 00:00:00 2001
From: Daniel Chen <cdchen at ca.ibm.com>
Date: Wed, 5 Aug 2026 08:28:11 -0400
Subject: [PATCH] [flang] Fix ICE when lowering IBM vector() array through
 fir.box

---
 flang/lib/Optimizer/CodeGen/CodeGen.cpp       |  2 +-
 flang/lib/Optimizer/Dialect/FIRType.cpp       |  5 ++-
 flang/lib/Semantics/compute-offsets.cpp       |  4 +-
 flang/test/Fir/embox-ppc-vector.fir           | 40 +++++++++++++++++++
 .../test/Lower/PowerPC/ppc-vec-array-box.f90  | 39 ++++++++++++++++++
 5 files changed, 87 insertions(+), 3 deletions(-)
 create mode 100644 flang/test/Fir/embox-ppc-vector.fir
 create mode 100644 flang/test/Lower/PowerPC/ppc-vec-array-box.f90

diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 55c6afee45996..32361c15fad06 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -1820,7 +1820,7 @@ struct EmboxCommonConversion : public fir::FIROpConversion<OP> {
       return {genTypeStrideInBytes(loc, i64Ty, rewriter, ptrTy, dataLayout),
               typeCodeVal};
     }
-    if (mlir::isa<fir::RecordType>(boxEleTy))
+    if (mlir::isa<fir::RecordType, fir::VectorType>(boxEleTy))
       return {genTypeStrideInBytes(loc, i64Ty, rewriter,
                                    this->convertType(boxEleTy), dataLayout),
               typeCodeVal};
diff --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp
index 178860239e17d..8b80f1d60146a 100644
--- a/flang/lib/Optimizer/Dialect/FIRType.cpp
+++ b/flang/lib/Optimizer/Dialect/FIRType.cpp
@@ -584,7 +584,10 @@ int getTypeCode(mlir::Type ty, const fir::KindMapping &kindMap) {
   }
   if (fir::isa_ref_type(ty))
     return CFI_type_cptr;
-  if (mlir::isa<fir::RecordType>(ty))
+  // fir::VectorType is the IBM Fortran vector() extension type used as a
+  // fir.box element type. Use CFI_type_struct as the accepted fallback
+  // for opaque aggregate types in internal descriptors
+  if (mlir::isa<fir::RecordType, fir::VectorType>(ty))
     return CFI_type_struct;
   llvm_unreachable("unsupported type");
 }
diff --git a/flang/lib/Semantics/compute-offsets.cpp b/flang/lib/Semantics/compute-offsets.cpp
index e427586301dea..5e7d0debb3257 100644
--- a/flang/lib/Semantics/compute-offsets.cpp
+++ b/flang/lib/Semantics/compute-offsets.cpp
@@ -417,7 +417,9 @@ auto ComputeOffsetsHelper::GetSizeAndAlignment(
     auto dyType{evaluate::DynamicType::From(symbol)};
     const auto *derived{evaluate::GetDerivedTypeSpec(dyType)};
     int lenParams{derived ? CountLenParameters(*derived) : 0};
-    bool needAddendum{derived || (dyType && dyType->IsUnlimitedPolymorphic())};
+    // Prevents over-sizing descriptor for vector variables
+    bool needAddendum{(derived && !derived->IsVectorType()) ||
+        (dyType && dyType->IsUnlimitedPolymorphic())};
 
     // FIXME: Get descriptor size from targetCharacteristics instead
     // overapproximation
diff --git a/flang/test/Fir/embox-ppc-vector.fir b/flang/test/Fir/embox-ppc-vector.fir
new file mode 100644
index 0000000000000..14f163e8b970e
--- /dev/null
+++ b/flang/test/Fir/embox-ppc-vector.fir
@@ -0,0 +1,40 @@
+// Test emboxing PPC vector type to a descriptor
+//RUN: fir-opt -cg-rewrite --fir-to-llvm-ir %s | FileCheck %s
+
+func.func @test1() {
+  %0 = fir.alloca !fir.box<!fir.heap<!fir.vector<4:i32>>>
+  %1 = fir.zero_bits !fir.heap<!fir.vector<4:i32>>
+  %2 = fir.embox %1 : (!fir.heap<!fir.vector<4:i32>>) -> !fir.box<!fir.heap<!fir.vector<4:i32>>>
+  fir.store %2 to %0 : !fir.ref<!fir.box<!fir.heap<!fir.vector<4:i32>>>>
+  return
+}
+
+//CHECK-LABEL: llvm.func @test1()
+//CHECK: %[[TYPE_VAL:.*]] = llvm.mlir.constant(42 : i32) : i32
+//CHECK: %[[ELEM_LEN_VAL:.*]] = llvm.mlir.constant(16 : i64) : i64
+//CHECK: %[[DSC_1:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>
+//CHECK: %[[DSC_2:.*]] = llvm.insertvalue %[[ELEM_LEN_VAL]], %[[DSC_1]][1] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>
+//CHECK: %[[RANK_VAL:.*]] = llvm.mlir.constant(0 : i32) : i32
+//CHECK: %[[DSC_3:.*]] = llvm.trunc %[[RANK_VAL]] : i32 to i8
+//CHECK: %[[DSC_4:.*]] = llvm.insertvalue %[[DSC_3]], %11[3] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>
+//CHECK: %[[DSC_5:.*]] = llvm.trunc %[[TYPE_VAL]] : i32 to i8
+//CHECK: %[[DSC_6:.*]] = llvm.insertvalue %[[DSC_5]], %[[DSC_4]][4] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>
+
+func.func @test2() {
+  %0 = fir.alloca !fir.box<!fir.heap<!fir.vector<2:f64>>>
+  %1 = fir.zero_bits !fir.heap<!fir.vector<2:f64>>
+  %2 = fir.embox %1 : (!fir.heap<!fir.vector<2:f64>>) -> !fir.box<!fir.heap<!fir.vector<2:f64>>>
+  fir.store %2 to %0 : !fir.ref<!fir.box<!fir.heap<!fir.vector<2:f64>>>>
+  return
+}
+
+//CHECK-LABEL: llvm.func @test2()
+//CHECK: %[[TYPE_VAL:.*]] = llvm.mlir.constant(42 : i32) : i32
+//CHECK: %[[ELEM_LEN_VAL:.*]] = llvm.mlir.constant(16 : i64) : i64
+//CHECK: %[[DSC_1:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>
+//CHECK: %[[DSC_2:.*]] = llvm.insertvalue %[[ELEM_LEN_VAL]], %[[DSC_1]][1] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>
+//CHECK: %[[RANK_VAL:.*]] = llvm.mlir.constant(0 : i32) : i32
+//CHECK: %[[DSC_3:.*]] = llvm.trunc %[[RANK_VAL]] : i32 to i8
+//CHECK: %[[DSC_4:.*]] = llvm.insertvalue %[[DSC_3]], %11[3] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>
+//CHECK: %[[DSC_5:.*]] = llvm.trunc %[[TYPE_VAL]] : i32 to i8
+//CHECK: %[[DSC_6:.*]] = llvm.insertvalue %[[DSC_5]], %[[DSC_4]][4] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>
diff --git a/flang/test/Lower/PowerPC/ppc-vec-array-box.f90 b/flang/test/Lower/PowerPC/ppc-vec-array-box.f90
new file mode 100644
index 0000000000000..fcd824704e501
--- /dev/null
+++ b/flang/test/Lower/PowerPC/ppc-vec-array-box.f90
@@ -0,0 +1,39 @@
+! RUN: %flang_fc1 -triple powerpc64-ibm-aix7.2.0.0 -emit-fir -o - %s | FileCheck %s --check-prefix=FIR
+! RUN: %flang_fc1 -triple powerpc64-ibm-aix7.2.0.0 -emit-llvm -O0 -o - %s | FileCheck %s --check-prefix=LLVMIR
+! REQUIRES: target=powerpc{{.*}}
+
+! Test that merge() on an array of IBM vector() type lowers correctly through
+! a fir.box descriptor at -O0.
+!
+! At -O0, HLFIR bufferization creates a temporary array and wraps it in a
+! fir.box<!fir.array<Nx!fir.vector<...>>>.  Before the fix, both:
+!   - getTypeCode()        in FIRType.cpp  hit llvm_unreachable("unsupported type")
+!   - getSizeAndTypeCode() in CodeGen.cpp  hit fir::emitFatalError(...)
+! because neither handled fir::VectorType as a fir.box element type.
+!
+! Additionally, getTypeCode() must return CFI_type_struct (not CFI_type_other)
+! for fir::VectorType. CFI_type_other is rejected at runtime by
+! VerifyEstablishParameters for internal (compiler-generated) descriptors,
+! causing a fatal error: "CFI_establish returned 15 for CFI_type_t(-1)".
+!
+! At -O3, hlfir::createInlineHLFIRCopy inlines the copy element-by-element,
+! avoiding the fir.box entirely, which is why -O3 always passed.
+
+subroutine vec_merge_array(va, vb, mask, res)
+  vector(integer(4)), intent(in)  :: va(2), vb(2)
+  logical,            intent(in)  :: mask(2)
+  vector(integer(4)), intent(out) :: res(2)
+  res = merge(va, vb, mask)
+end subroutine
+
+! FIR-LABEL: func.func @_QPvec_merge_array
+
+! Verify the temporary array and its fir.embox are generated with
+! fir.vector<4:i32> as the element type — this is the type that previously
+! triggered the ICE in getTypeCode() and getSizeAndTypeCode().
+! FIR: fir.allocmem !fir.array<2x!fir.vector<4:i32>>
+! FIR: fir.embox {{.*}} : ({{.*}}!fir.array<2x!fir.vector<4:i32>>{{.*}}) -> !fir.box<!fir.array<2x!fir.vector<4:i32>>>
+
+! LLVMIR-LABEL: define void @vec_merge_array_
+! Verify CodeGen completes and produces correct vector stores.
+! LLVMIR: store <4 x i32>



More information about the flang-commits mailing list