diff --git a/flang/include/flang/Optimizer/CodeGen/TBAABuilder.h b/flang/include/flang/Optimizer/CodeGen/TBAABuilder.h index b94782bb9ea984..3aeb124f911867 100644 --- a/flang/include/flang/Optimizer/CodeGen/TBAABuilder.h +++ b/flang/include/flang/Optimizer/CodeGen/TBAABuilder.h @@ -188,6 +188,9 @@ class TBAABuilder { // Returns TBAATagAttr representing access tag: // < , , 0 > mlir::LLVM::TBAATagAttr getAnyDataAccessTag(); + // Returns TBAATagAttr representing access tag: + // < , , 0 > + mlir::LLVM::TBAATagAttr getAnyAccessTag(); // Returns TBAATagAttr representing access tag described by the base and // access FIR types and the LLVM::GepOp representing the access in terms of diff --git a/flang/include/flang/Optimizer/Dialect/FIRType.h b/flang/include/flang/Optimizer/Dialect/FIRType.h index 77807ea2a308c6..7d1415f4e9ca14 100644 --- a/flang/include/flang/Optimizer/Dialect/FIRType.h +++ b/flang/include/flang/Optimizer/Dialect/FIRType.h @@ -349,6 +349,10 @@ mlir::Type unwrapInnerType(mlir::Type ty); /// Return true iff `ty` is a RecordType with members that are allocatable. bool isRecordWithAllocatableMember(mlir::Type ty); +/// Return true iff `ty` is a scalar/array of RecordType +/// with members that are descriptors. +bool isRecordWithDescriptorMember(mlir::Type ty); + /// Return true iff `ty` is a RecordType with type parameters. inline bool isRecordWithTypeParameters(mlir::Type ty) { if (auto recTy = ty.dyn_cast_or_null()) diff --git a/flang/lib/Optimizer/CodeGen/TBAABuilder.cpp b/flang/lib/Optimizer/CodeGen/TBAABuilder.cpp index 04259c0e4c7213..1a5ae8cf7aac62 100644 --- a/flang/lib/Optimizer/CodeGen/TBAABuilder.cpp +++ b/flang/lib/Optimizer/CodeGen/TBAABuilder.cpp @@ -92,6 +92,10 @@ TBAATagAttr TBAABuilder::getDataAccessTag(Type baseFIRType, Type accessFIRType, return getAnyDataAccessTag(); } +TBAATagAttr TBAABuilder::getAnyAccessTag() { + return getAccessTag(anyAccessTypeDesc, anyAccessTypeDesc, /*offset=*/0); +} + void TBAABuilder::attachTBAATag(AliasAnalysisOpInterface op, Type baseFIRType, Type accessFIRType, GEPOp gep) { if (!enableTBAA) @@ -106,10 +110,17 @@ void TBAABuilder::attachTBAATag(AliasAnalysisOpInterface op, Type baseFIRType, << "\n"); TBAATagAttr tbaaTagSym; - if (baseFIRType.isa()) + if (fir::isRecordWithDescriptorMember(baseFIRType)) { + // A memory access that addresses an aggregate that contains + // a mix of data members and descriptor members may alias + // with both data and descriptor accesses. + // Conservatively set any-access tag if there is any descriptor member. + tbaaTagSym = getAnyAccessTag(); + } else if (baseFIRType.isa()) { tbaaTagSym = getBoxAccessTag(baseFIRType, accessFIRType, gep); - else + } else { tbaaTagSym = getDataAccessTag(baseFIRType, accessFIRType, gep); + } if (!tbaaTagSym) return; diff --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp index dd79aa27645452..b1896579267049 100644 --- a/flang/lib/Optimizer/Dialect/FIRType.cpp +++ b/flang/lib/Optimizer/Dialect/FIRType.cpp @@ -360,6 +360,18 @@ bool isRecordWithAllocatableMember(mlir::Type ty) { return false; } +bool isRecordWithDescriptorMember(mlir::Type ty) { + ty = unwrapSequenceType(ty); + if (auto recTy = ty.dyn_cast()) + for (auto [field, memTy] : recTy.getTypeList()) { + if (mlir::isa(memTy)) + return true; + if (memTy.isa() && isRecordWithDescriptorMember(memTy)) + return true; + } + return false; +} + mlir::Type unwrapAllRefAndSeqType(mlir::Type ty) { while (true) { mlir::Type nt = unwrapSequenceType(unwrapRefType(ty)); diff --git a/flang/test/Fir/tbaa.fir b/flang/test/Fir/tbaa.fir index f8a52b2e98db0c..eabc9f30127fa3 100644 --- a/flang/test/Fir/tbaa.fir +++ b/flang/test/Fir/tbaa.fir @@ -351,3 +351,37 @@ func.func @tbaa(%arg0: !fir.box>) { // CHECK: %[[VAL_14:.*]] = llvm.bitcast %[[VAL_13]] : !llvm.ptr to !llvm.ptr // CHECK: llvm.return // CHECK: } + +// ----- + +// Check that the scalar aggregate load/store with a descriptor member +// is mapped to any-access. +// CHECK-DAG: #[[ROOT:.*]] = #llvm.tbaa_root +// CHECK-DAG: #[[ANYACC:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[$ANYT:.*]] = #llvm.tbaa_tag + +func.func @tbaa(%arg0: !fir.ref>}>>, %arg1: !fir.ref>}>>) { + %0 = fir.load %arg0 : !fir.ref>}>> + fir.store %0 to %arg1 : !fir.ref>}>> + return +} +// CHECK-LABEL: llvm.func @tbaa( +// CHECK: llvm.load{{.*}}{tbaa = [#[[$ANYT]]]} +// CHECK: llvm.store{{.*}}{tbaa = [#[[$ANYT]]]} + +// ----- + +// Check that the array aggregate load/store with a descriptor member +// is mapped to any-access. +// CHECK-DAG: #[[ROOT:.*]] = #llvm.tbaa_root +// CHECK-DAG: #[[ANYACC:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[$ANYT:.*]] = #llvm.tbaa_tag + +func.func @tbaa(%arg0: !fir.ref>}>>>, %arg1: !fir.ref>}>>>) { + %0 = fir.load %arg0 : !fir.ref>}>>> + fir.store %0 to %arg1 : !fir.ref>}>>> + return +} +// CHECK-LABEL: llvm.func @tbaa( +// CHECK: llvm.load{{.*}}{tbaa = [#[[$ANYT]]]} +// CHECK: llvm.store{{.*}}{tbaa = [#[[$ANYT]]]}