diff --git a/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h b/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h index c71988d081dd0..30dd5f754d0b5 100644 --- a/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h +++ b/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h @@ -155,6 +155,12 @@ struct AliasAnalysis { /// Return true, if Target or Pointer attribute is set. bool isTargetOrPointer() const; + /// Return true, if Target attribute is set. + bool isTarget() const; + + /// Return true, if Pointer attribute is set. + bool isPointer() const; + bool isDummyArgument() const; bool isData() const; bool isBoxData() const; diff --git a/flang/include/flang/Optimizer/Analysis/TBAAForest.h b/flang/include/flang/Optimizer/Analysis/TBAAForest.h index f95fcffd96e93..4d2281642b43d 100644 --- a/flang/include/flang/Optimizer/Analysis/TBAAForest.h +++ b/flang/include/flang/Optimizer/Analysis/TBAAForest.h @@ -40,6 +40,12 @@ struct TBAATree { mlir::LLVM::TBAATagAttr getTag(llvm::StringRef uniqueId) const; + /// Create a TBAA tag pointing to the root of this subtree, + /// i.e. all the children tags will alias with this tag. + mlir::LLVM::TBAATagAttr getTag() const; + + mlir::LLVM::TBAATypeDescriptorAttr getRoot() const { return parent; } + private: SubtreeState(mlir::MLIRContext *ctx, std::string name, mlir::LLVM::TBAANodeAttr grandParent) @@ -51,17 +57,44 @@ struct TBAATree { const std::string parentId; mlir::MLIRContext *const context; mlir::LLVM::TBAATypeDescriptorAttr parent; - llvm::DenseMap tagDedup; }; + /// A subtree for POINTER/TARGET variables data. + /// Any POINTER variable must use a tag that points + /// to the root of this subtree. + /// A TARGET dummy argument must also point to this root. + SubtreeState targetDataTree; + /// A subtree for global variables data (e.g. user module variables). SubtreeState globalDataTree; + /// A subtree for variables allocated via fir.alloca or fir.allocmem. SubtreeState allocatedDataTree; + /// A subtree for subprogram's dummy arguments. + /// It only contains children for the dummy arguments + /// that are not POINTER/TARGET. They all do not conflict + /// with each other and with any other data access, except + /// with unknown data accesses (FIR alias analysis uses + /// SourceKind::Indirect for sources of such accesses). SubtreeState dummyArgDataTree; + /// A subtree for global variables descriptors. SubtreeState directDataTree; mlir::LLVM::TBAATypeDescriptorAttr anyAccessDesc; mlir::LLVM::TBAATypeDescriptorAttr boxMemberTypeDesc; mlir::LLVM::TBAATypeDescriptorAttr anyDataTypeDesc; + // Structure of the created tree: + // Function root + // | + // "any access" + // | + // |- "descriptor member" + // |- "any data access" + // | + // |- "dummy arg data" + // |- "target data" + // | + // |- "allocated data" + // |- "direct data" + // |- "global data" static TBAATree buildTree(mlir::StringAttr functionName); private: diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp index bda98871a1c7a..cbfc8b63ab64d 100644 --- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp +++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp @@ -110,6 +110,14 @@ bool AliasAnalysis::Source::isTargetOrPointer() const { attributes.test(Attribute::Target); } +bool AliasAnalysis::Source::isTarget() const { + return attributes.test(Attribute::Target); +} + +bool AliasAnalysis::Source::isPointer() const { + return attributes.test(Attribute::Pointer); +} + bool AliasAnalysis::Source::isDummyArgument() const { if (auto v = origin.u.dyn_cast()) { return fir::isDummyArgument(v); diff --git a/flang/lib/Optimizer/Analysis/TBAAForest.cpp b/flang/lib/Optimizer/Analysis/TBAAForest.cpp index 786c4932ea89e..cce50e0de1bc7 100644 --- a/flang/lib/Optimizer/Analysis/TBAAForest.cpp +++ b/flang/lib/Optimizer/Analysis/TBAAForest.cpp @@ -11,9 +11,6 @@ mlir::LLVM::TBAATagAttr fir::TBAATree::SubtreeState::getTag(llvm::StringRef uniqueName) const { - // mlir::LLVM::TBAATagAttr &tag = tagDedup[uniqueName]; - // if (tag) - // return tag; std::string id = (parentId + "/" + uniqueName).str(); mlir::LLVM::TBAATypeDescriptorAttr type = mlir::LLVM::TBAATypeDescriptorAttr::get( @@ -22,6 +19,10 @@ fir::TBAATree::SubtreeState::getTag(llvm::StringRef uniqueName) const { // return tag; } +mlir::LLVM::TBAATagAttr fir::TBAATree::SubtreeState::getTag() const { + return mlir::LLVM::TBAATagAttr::get(parent, parent, 0); +} + fir::TBAATree fir::TBAATree::buildTree(mlir::StringAttr func) { llvm::StringRef funcName = func.getValue(); std::string rootId = ("Flang function root " + funcName).str(); @@ -53,9 +54,13 @@ fir::TBAATree fir::TBAATree::buildTree(mlir::StringAttr func) { fir::TBAATree::TBAATree(mlir::LLVM::TBAATypeDescriptorAttr anyAccess, mlir::LLVM::TBAATypeDescriptorAttr dataRoot, mlir::LLVM::TBAATypeDescriptorAttr boxMemberTypeDesc) - : globalDataTree(dataRoot.getContext(), "global data", dataRoot), - allocatedDataTree(dataRoot.getContext(), "allocated data", dataRoot), + : targetDataTree(dataRoot.getContext(), "target data", dataRoot), + globalDataTree(dataRoot.getContext(), "global data", + targetDataTree.getRoot()), + allocatedDataTree(dataRoot.getContext(), "allocated data", + targetDataTree.getRoot()), dummyArgDataTree(dataRoot.getContext(), "dummy arg data", dataRoot), - directDataTree(dataRoot.getContext(), "direct data", dataRoot), + directDataTree(dataRoot.getContext(), "direct data", + targetDataTree.getRoot()), anyAccessDesc(anyAccess), boxMemberTypeDesc(boxMemberTypeDesc), anyDataTypeDesc(dataRoot) {} diff --git a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp index e6fc2ed992e38..66b4b84998801 100644 --- a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp +++ b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp @@ -198,12 +198,6 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op, LLVM_DEBUG(llvm::dbgs() << "Analysing " << op << "\n"); const fir::AliasAnalysis::Source &source = state.getSource(memref); - if (source.isTargetOrPointer()) { - LLVM_DEBUG(llvm::dbgs().indent(2) << "Skipping TARGET/POINTER\n"); - // These will get an "any data access" tag in TBAABuilder (CodeGen): causing - // them to "MayAlias" with all non-box accesses - return; - } // Process the scopes, if not processed yet. state.processFunctionScopes(func); @@ -228,15 +222,21 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op, LLVM_DEBUG(llvm::dbgs().indent(2) << "Found reference to dummy argument at " << *op << "\n"); std::string name = getFuncArgName(llvm::cast(source.origin.u)); - if (!name.empty()) + // If it is a TARGET or POINTER, then we do not care about the name, + // because the tag points to the root of the subtree currently. + if (source.isTargetOrPointer()) { + tag = state.getFuncTreeWithScope(func, scopeOp).targetDataTree.getTag(); + } else if (!name.empty()) { tag = state.getFuncTreeWithScope(func, scopeOp) .dummyArgDataTree.getTag(name); - else + } else { LLVM_DEBUG(llvm::dbgs().indent(2) << "WARN: couldn't find a name for dummy argument " << *op << "\n"); + tag = state.getFuncTreeWithScope(func, scopeOp).dummyArgDataTree.getTag(); + } - // TBAA for global variables + // TBAA for global variables without descriptors } else if (enableGlobals && source.kind == fir::AliasAnalysis::SourceKind::Global && !source.isBoxData()) { @@ -244,9 +244,13 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op, const char *name = glbl.getRootReference().data(); LLVM_DEBUG(llvm::dbgs().indent(2) << "Found reference to global " << name << " at " << *op << "\n"); - tag = state.getFuncTreeWithScope(func, scopeOp).globalDataTree.getTag(name); + if (source.isPointer()) + tag = state.getFuncTreeWithScope(func, scopeOp).targetDataTree.getTag(); + else + tag = + state.getFuncTreeWithScope(func, scopeOp).globalDataTree.getTag(name); - // TBAA for SourceKind::Direct + // TBAA for global variables with descriptors } else if (enableDirect && source.kind == fir::AliasAnalysis::SourceKind::Global && source.isBoxData()) { @@ -254,11 +258,12 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op, const char *name = glbl.getRootReference().data(); LLVM_DEBUG(llvm::dbgs().indent(2) << "Found reference to direct " << name << " at " << *op << "\n"); - tag = - state.getFuncTreeWithScope(func, scopeOp).directDataTree.getTag(name); + if (source.isPointer()) + tag = state.getFuncTreeWithScope(func, scopeOp).targetDataTree.getTag(); + else + tag = state.getFuncTreeWithScope(func, scopeOp) + .directDataTree.getTag(name); } else { - // SourceKind::Direct is likely to be extended to cases which are not a - // SymbolRefAttr in the future LLVM_DEBUG(llvm::dbgs().indent(2) << "Can't get name for direct " << source << " at " << *op << "\n"); } @@ -269,11 +274,23 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op, std::optional name; mlir::Operation *sourceOp = llvm::cast(source.origin.u).getDefiningOp(); + bool unknownAllocOp = false; if (auto alloc = mlir::dyn_cast_or_null(sourceOp)) name = alloc.getUniqName(); else if (auto alloc = mlir::dyn_cast_or_null(sourceOp)) name = alloc.getUniqName(); - if (name) { + else + unknownAllocOp = true; + + if (unknownAllocOp) { + LLVM_DEBUG(llvm::dbgs().indent(2) + << "WARN: unknown defining op for SourceKind::Allocate " << *op + << "\n"); + } else if (source.isPointer()) { + LLVM_DEBUG(llvm::dbgs().indent(2) + << "Found reference to allocation at " << *op << "\n"); + tag = state.getFuncTreeWithScope(func, scopeOp).targetDataTree.getTag(); + } else if (name) { LLVM_DEBUG(llvm::dbgs().indent(2) << "Found reference to allocation " << name << " at " << *op << "\n"); tag = state.getFuncTreeWithScope(func, scopeOp) @@ -282,6 +299,8 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op, LLVM_DEBUG(llvm::dbgs().indent(2) << "WARN: couldn't find a name for allocation " << *op << "\n"); + tag = + state.getFuncTreeWithScope(func, scopeOp).allocatedDataTree.getTag(); } } else { if (source.kind != fir::AliasAnalysis::SourceKind::Argument && diff --git a/flang/test/Transforms/tbaa-with-dummy-scope.fir b/flang/test/Transforms/tbaa-with-dummy-scope.fir index 738692814cde5..7624de9431e08 100644 --- a/flang/test/Transforms/tbaa-with-dummy-scope.fir +++ b/flang/test/Transforms/tbaa-with-dummy-scope.fir @@ -2,7 +2,7 @@ // subroutine test(x, y) // real, target :: x, y -// x = y ! the load/store do not have TBAA due to TARGET +// x = y // call inner(x, y) ! the inlined load/store go to Scope 1 // call inner(x, y) ! the inlined load/store go to Scope 2 // contains @@ -12,25 +12,30 @@ // end subroutine inner // end subroutine test +// CHECK: #[[TEST1ROOT:.+]] = #llvm.tbaa_root // CHECK: #[[$ATTR_0:.+]] = #llvm.tbaa_root // CHECK: #[[$ATTR_1:.+]] = #llvm.tbaa_root -// CHECK: #[[$ATTR_2:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_3:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_4:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_5:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_6:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_7:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_8:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_9:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_10:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_11:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_12:.+]] = #llvm.tbaa_tag -// CHECK: #[[$ATTR_13:.+]] = #llvm.tbaa_tag -// CHECK: #[[$ATTR_14:.+]] = #llvm.tbaa_tag -// CHECK: #[[$ATTR_15:.+]] = #llvm.tbaa_tag +// CHECK: #[[TEST1ANYACCESS:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_2:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_3:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[TEST1ANYDATA:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_4:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_5:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[TARGETDATA:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_6:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_7:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[TARGETTAG:.+]] = #llvm.tbaa_tag +// CHECK: #[[$ATTR_8:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_9:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_10:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_11:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_12:.+]] = #llvm.tbaa_tag +// CHECK: #[[$ATTR_13:.+]] = #llvm.tbaa_tag +// CHECK: #[[$ATTR_14:.+]] = #llvm.tbaa_tag +// CHECK: #[[$ATTR_15:.+]] = #llvm.tbaa_tag // CHECK: func.func @test1( -// CHECK: %[[VAL_5:.*]] = fir.load %{{.*}} : !fir.ref -// CHECK: fir.store %{{.*}} : !fir.ref +// CHECK: %[[VAL_5:.*]] = fir.load %{{.*}} {tbaa = [#[[TARGETTAG]]]} : !fir.ref +// CHECK: fir.store %{{.*}} {tbaa = [#[[TARGETTAG]]]} : !fir.ref // CHECK: %[[VAL_6:.*]] = fir.dummy_scope : !fir.dscope // CHECK: %[[VAL_9:.*]] = fir.load %{{.*}} {tbaa = [#[[$ATTR_12]]]} : !fir.ref // CHECK: fir.store %{{.*}} {tbaa = [#[[$ATTR_13]]]} : !fir.ref @@ -58,102 +63,6 @@ func.func @test1(%arg0: !fir.ref {fir.bindc_name = "x", fir.target}, %arg1: // ----- -// Check that without proper fir.dummy_scope placement -// we just put everything into the root scope. - -// CHECK: #[[$ATTR_16:.+]] = #llvm.tbaa_root -// CHECK: #[[$ATTR_17:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_18:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_19:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_20:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_21:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_22:.+]] = #llvm.tbaa_tag -// CHECK: #[[$ATTR_23:.+]] = #llvm.tbaa_tag -// CHECK: func.func @test2( -// CHECK: %[[VAL_4:.*]] = fir.load %{{.*}} {tbaa = [#[[$ATTR_22]]]} : !fir.ref -// CHECK: fir.store %{{.*}} {tbaa = [#[[$ATTR_23]]]} : !fir.ref -// CHECK: %[[VAL_5:.*]] = fir.declare -// CHECK: %[[VAL_6:.*]] = fir.declare -// CHECK: %[[VAL_7:.*]] = fir.load %{{.*}} {tbaa = [#[[$ATTR_22]]]} : !fir.ref -// CHECK: fir.store %{{.*}} {tbaa = [#[[$ATTR_23]]]} : !fir.ref -func.func @test2(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}) { - %0 = fir.declare %arg0 {uniq_name = "_QFtestEx"} : (!fir.ref) -> !fir.ref - %1 = fir.declare %arg1 {uniq_name = "_QFtestEy"} : (!fir.ref) -> !fir.ref - %2 = fir.load %1 : !fir.ref - fir.store %2 to %0 : !fir.ref - %3 = fir.declare %0 {uniq_name = "_QFtestFinnerEx"} : (!fir.ref) -> !fir.ref - %4 = fir.declare %1 {uniq_name = "_QFtestFinnerEy"} : (!fir.ref) -> !fir.ref - %5 = fir.load %4 : !fir.ref - fir.store %5 to %3 : !fir.ref - return -} - -// ----- - -// module test -// real :: x, y -// contains -// subroutine caller -// x = y ! the load/store go to the root scope -// call callee -// end subroutine caller -// subroutine callee -// x = y ! the load/store go to the root scope -// ! Since there are no dummy arguments in callee, -// ! it is better to put the load/store into the -// ! enclosing root scope, so that they can be -// ! disambiguated using TBAA with the loads/stores -// ! in the enclosing scope. -// end subroutine callee -// end module test - -// CHECK: #[[$ATTR_24:.+]] = #llvm.tbaa_root -// CHECK: #[[$ATTR_25:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_26:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_27:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_28:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_29:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_30:.+]] = #llvm.tbaa_tag -// CHECK: #[[$ATTR_31:.+]] = #llvm.tbaa_tag -// CHECK: func.func @_QMtestPcaller() { -// CHECK: %[[VAL_0:.*]] = fir.address_of(@_QMtestEx) : !fir.ref -// CHECK: %[[VAL_1:.*]] = fir.declare %[[VAL_0]] {uniq_name = "_QMtestEx"} : (!fir.ref) -> !fir.ref -// CHECK: %[[VAL_2:.*]] = fir.address_of(@_QMtestEy) : !fir.ref -// CHECK: %[[VAL_3:.*]] = fir.declare %[[VAL_2]] {uniq_name = "_QMtestEy"} : (!fir.ref) -> !fir.ref -// CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]] {tbaa = [#[[$ATTR_30]]]} : !fir.ref -// CHECK: fir.store %[[VAL_4]] to %[[VAL_1]] {tbaa = [#[[$ATTR_31]]]} : !fir.ref -// CHECK: %[[VAL_5:.*]] = fir.address_of(@_QMtestEx) : !fir.ref -// CHECK: %[[VAL_6:.*]] = fir.declare %[[VAL_5]] {uniq_name = "_QMtestEx"} : (!fir.ref) -> !fir.ref -// CHECK: %[[VAL_7:.*]] = fir.address_of(@_QMtestEy) : !fir.ref -// CHECK: %[[VAL_8:.*]] = fir.declare %[[VAL_7]] {uniq_name = "_QMtestEy"} : (!fir.ref) -> !fir.ref -// CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_8]] {tbaa = [#[[$ATTR_30]]]} : !fir.ref -// CHECK: fir.store %[[VAL_9]] to %[[VAL_6]] {tbaa = [#[[$ATTR_31]]]} : !fir.ref -func.func @_QMtestPcaller() { - %0 = fir.address_of(@_QMtestEx) : !fir.ref - %1 = fir.declare %0 {uniq_name = "_QMtestEx"} : (!fir.ref) -> !fir.ref - %2 = fir.address_of(@_QMtestEy) : !fir.ref - %3 = fir.declare %2 {uniq_name = "_QMtestEy"} : (!fir.ref) -> !fir.ref - %4 = fir.load %3 : !fir.ref - fir.store %4 to %1 : !fir.ref - %5 = fir.address_of(@_QMtestEx) : !fir.ref - %6 = fir.declare %5 {uniq_name = "_QMtestEx"} : (!fir.ref) -> !fir.ref - %7 = fir.address_of(@_QMtestEy) : !fir.ref - %8 = fir.declare %7 {uniq_name = "_QMtestEy"} : (!fir.ref) -> !fir.ref - %9 = fir.load %8 : !fir.ref - fir.store %9 to %6 : !fir.ref - return -} -fir.global @_QMtestEx : f32 { - %0 = fir.zero_bits f32 - fir.has_value %0 : f32 -} -fir.global @_QMtestEy : f32 { - %0 = fir.zero_bits f32 - fir.has_value %0 : f32 -} - -// ----- - // module test // real :: x, y // contains @@ -170,23 +79,25 @@ fir.global @_QMtestEy : f32 { // CHECK: #[[$ATTR_32:.+]] = #llvm.tbaa_root // CHECK: #[[$ATTR_33:.+]] = #llvm.tbaa_root -// CHECK: #[[$ATTR_34:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_35:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_36:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_37:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_38:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_39:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_40:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_41:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_42:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_43:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_44:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_45:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_46:.+]] = #llvm.tbaa_tag -// CHECK: #[[$ATTR_47:.+]] = #llvm.tbaa_tag -// CHECK: #[[$ATTR_48:.+]] = #llvm.tbaa_tag -// CHECK: #[[$ATTR_49:.+]] = #llvm.tbaa_tag -// CHECK: #[[$ATTR_50:.+]] = #llvm.tbaa_tag +// CHECK: #[[$ATTR_34:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_35:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_36:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_37:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[CALLERTARGETDATA:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[CALLEETARGETDATA:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_40:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_38:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_39:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_45:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_50:.+]] = #llvm.tbaa_tag +// CHECK: #[[$ATTR_41:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_42:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_43:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_44:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_46:.+]] = #llvm.tbaa_tag +// CHECK: #[[$ATTR_47:.+]] = #llvm.tbaa_tag +// CHECK: #[[$ATTR_48:.+]] = #llvm.tbaa_tag +// CHECK: #[[$ATTR_49:.+]] = #llvm.tbaa_tag // CHECK: func.func @_QMtestPcaller( // CHECK-SAME: %[[VAL_0:.*]]: !fir.ref {fir.bindc_name = "z"}) { // CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope diff --git a/flang/test/Transforms/tbaa-with-dummy-scope2.fir b/flang/test/Transforms/tbaa-with-dummy-scope2.fir index a28b4d56f442c..c8f419fbee652 100644 --- a/flang/test/Transforms/tbaa-with-dummy-scope2.fir +++ b/flang/test/Transforms/tbaa-with-dummy-scope2.fir @@ -44,10 +44,11 @@ func.func @_QPtest1() attributes {noinline} { // CHECK: #[[$ATTR_1:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[$ATTR_2:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[$ATTR_3:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_4:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[TARGETDATA:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[$ATTR_5:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_6:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_4:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[$ATTR_7:.+]] = #llvm.tbaa_tag +// CHECK: #[[$ATTR_6:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[$ATTR_8:.+]] = #llvm.tbaa_tag // CHECK-LABEL: func.func @_QPtest1() attributes {noinline} { // CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFtest1FinnerEy"} @@ -87,10 +88,11 @@ func.func @_QPtest2() attributes {noinline} { // CHECK: #[[$ATTR_4:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[$ATTR_5:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[$ATTR_6:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_7:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[TARGETDATA:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[$ATTR_8:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[$ATTR_9:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$ATTR_7:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[$ATTR_10:.+]] = #llvm.tbaa_tag +// CHECK: #[[$ATTR_9:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[$ATTR_11:.+]] = #llvm.tbaa_tag // CHECK-LABEL: func.func @_QPtest2() attributes {noinline} { // CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFtest2FinnerEy"} diff --git a/flang/test/Transforms/tbaa.fir b/flang/test/Transforms/tbaa.fir index f8e16b174e9c7..88e200f43b4ef 100644 --- a/flang/test/Transforms/tbaa.fir +++ b/flang/test/Transforms/tbaa.fir @@ -108,9 +108,10 @@ // CHECK: #[[TARGET_ANY_ACCESS:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[TARGET_ANY_DATA:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[TARGET_ANY_ARG:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[TARGET_TARGET_DATA:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[TARGET_A_TAG:.+]] = #llvm.tbaa_tag // CHECK: #[[TARGET_B:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[TARGET_B_TAG:.+]] = #llvm.tbaa_tag -// No entry for "dummy arg data/a" because that pointer should get "any data access" becase it has the TARGET attribute // CHECK-LABEL: func.func @_QPtargetarg( // CHECK-SAME: %[[VAL_0:.*]]: !fir.box> {fir.bindc_name = "a", fir.target}, @@ -124,8 +125,7 @@ // CHECK: %[[VAL_7:.*]] = fir.array_coor %[[VAL_6]] %[[VAL_2]] : (!fir.box>, index) -> !fir.ref // CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_7]] {tbaa = [#[[TARGET_B_TAG]]]} : !fir.ref // CHECK: %[[VAL_9:.*]] = fir.array_coor %[[VAL_4]] %[[VAL_2]] : (!fir.box>, index) -> !fir.ref -// "any data access" tag is added by TBAABuilder during CodeGen -// CHECK: fir.store %[[VAL_8]] to %[[VAL_9]] : !fir.ref +// CHECK: fir.store %[[VAL_8]] to %[[VAL_9]] {tbaa = [#[[TARGET_A_TAG]]]} : !fir.ref // CHECK: return // CHECK: } @@ -157,9 +157,10 @@ // CHECK: #[[POINTER_ANY_ACCESS:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[POINTER_ANY_DATA:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[POINTER_ANY_ARG:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[POINTER_TARGET_DATA:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[POINTER_A_TAG:.+]] = #llvm.tbaa_tag // CHECK: #[[POINTER_B:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[POINTER_B_TAG:.+]] = #llvm.tbaa_tag -// No entry for "dummy arg data/a" because that pointer should get "any data access" becase it has the POINTER attribute // CHECK-LABEL: func.func @_QPpointerarg( // CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>>> {fir.bindc_name = "a"}, @@ -177,8 +178,7 @@ // CHECK: %[[VAL_10:.*]]:3 = fir.box_dims %[[VAL_9]], %[[VAL_2]] : (!fir.box>>, index) -> (index, index, index) // CHECK: %[[VAL_11:.*]] = fir.shift %[[VAL_10]]#0 : (index) -> !fir.shift<1> // CHECK: %[[VAL_12:.*]] = fir.array_coor %[[VAL_9]](%[[VAL_11]]) %[[VAL_3]] : (!fir.box>>, !fir.shift<1>, index) -> !fir.ref -// "any data access" tag is added by TBAABuilder during CodeGen -// CHECK: fir.store %[[VAL_8]] to %[[VAL_12]] : !fir.ref +// CHECK: fir.store %[[VAL_8]] to %[[VAL_12]] {tbaa = [#[[POINTER_A_TAG]]]} : !fir.ref // CHECK: return // CHECK: } diff --git a/flang/test/Transforms/tbaa2.fir b/flang/test/Transforms/tbaa2.fir index 5c2503d69a8be..4678a1cd4a686 100644 --- a/flang/test/Transforms/tbaa2.fir +++ b/flang/test/Transforms/tbaa2.fir @@ -47,32 +47,35 @@ // CHECK: #[[ROOT:.+]] = #llvm.tbaa_root // CHECK: #[[ANY_ACCESS:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[ANY_DATA:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[ANY_GLBL:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[TARGETDATA:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[ANY_ARG:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[ANY_DIRECT:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[ANY_GLBL:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[ARG_LOW:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[ANY_DIRECT:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[ARG_Z:.+]] = #llvm.tbaa_type_desc}> +// CHECK: #[[ARG_Y:.+]] = #llvm.tbaa_type_desc}> + +// CHECK: #[[ARG_LOW_TAG:.+]] = #llvm.tbaa_tag +// CHECK: #[[ARG_Z_TAG:.+]] = #llvm.tbaa_tag +// CHECK: #[[ARG_Y_TAG:.+]] = #llvm.tbaa_tag + // CHECK: #[[GLBL_ZSTART:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[GLBL_ZSTOP:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[GLBL_YSTART:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[GLBL_YSTOP:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[GLBL_XSTART:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[ARG_LOW:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[DIRECT_A:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[DIRECT_B:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[ARG_Z:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[GLBL_DYINV:.+]] = #llvm.tbaa_type_desc}> -// CHECK: #[[ARG_Y:.+]] = #llvm.tbaa_type_desc}> // CHECK: #[[GLBL_ZSTART_TAG:.+]] = #llvm.tbaa_tag // CHECK: #[[GLBL_ZSTOP_TAG:.+]] = #llvm.tbaa_tag // CHECK: #[[GLBL_YSTART_TAG:.+]] = #llvm.tbaa_tag // CHECK: #[[GLBL_YSTOP_TAG:.+]] = #llvm.tbaa_tag // CHECK: #[[GLBL_XSTART_TAG:.+]] = #llvm.tbaa_tag -// CHECK: #[[ARG_LOW_TAG:.+]] = #llvm.tbaa_tag // CHECK: #[[DIRECT_A_TAG:.+]] = #llvm.tbaa_tag // CHECK: #[[DIRECT_B_TAG:.+]] = #llvm.tbaa_tag -// CHECK: #[[ARG_Z_TAG:.+]] = #llvm.tbaa_tag // CHECK: #[[GLBL_DYINV_TAG:.+]] = #llvm.tbaa_tag -// CHECK: #[[ARG_Y_TAG:.+]] = #llvm.tbaa_tag func.func @_QMmodPcallee(%arg0: !fir.box> {fir.bindc_name = "z"}, %arg1: !fir.box> {fir.bindc_name = "y"}, %arg2: !fir.ref>>> {fir.bindc_name = "low"}) { %c2 = arith.constant 2 : index diff --git a/flang/test/Transforms/tbaa3.fir b/flang/test/Transforms/tbaa3.fir new file mode 100644 index 0000000000000..28ff8f7c5fa83 --- /dev/null +++ b/flang/test/Transforms/tbaa3.fir @@ -0,0 +1,331 @@ +// RUN: fir-opt --fir-add-alias-tags %s | FileCheck --check-prefixes=ALL,DEFAULT %s +// RUN: fir-opt --fir-add-alias-tags --local-alloc-tbaa %s | FileCheck --check-prefixes=ALL,LOCAL %s + +// Test AddAliasTagsPass creating sub-tree for TARGET/POINTER variables. + +// module data +// real :: glob(10) +// real, target :: globt(10) +// real, allocatable :: globa(:) +// real, allocatable, target :: globat(:) +// real, pointer :: globp(:) +// end module data +// subroutine test1(dummyf, dummyft, dummyas, dummyast, dummya, dummyat, dummyp) +// use data +// real :: dummyf(10) +// real, target :: dummyft(10) +// real :: dummyas(:) +// real, target :: dummyast(:) +// real, allocatable :: dummya(:) +// real, allocatable, target :: dummyat(:) +// real, pointer :: dummyp(:) +// real :: local(10) +// real, target :: localt(10) +// real, allocatable :: locala(:) +// real, allocatable, target :: localat(:) +// real, pointer :: localp(:) +// glob(1) = 1.0 +// globt(1) = 1.0 +// globa(1) = 1.0 +// globat(1) = 1.0 +// globp(1) = 1.0 +// dummyf(1) = 1.0 +// dummyft(1) = 1.0 +// dummyas(1) = 1.0 +// dummyast(1) = 1.0 +// dummya(1) = 1.0 +// dummyat(1) = 1.0 +// dummyp(1) = 1.0 +// local(1) = 1.0 +// localt(1) = 1.0 +// locala(1) = 1.0 +// localat(1) = 1.0 +// localp(1) = 1.0 +// end subroutine test1 + +// "Flang function root _QPtest1" +// | +// "any access" +// | +// |- "descriptor member" +// |- "any data access" +// | +// |- "dummy arg data" +// | | +// | |- "dummy arg data/_QFtest1Edummyf" +// | |- "dummy arg data/_QFtest1Edummyas" +// | |- "dummy arg data/_QFtest1Edummya" +// | +// |- "target data" <- all pointers and taget dummys +// | +// |- "global data" +// | | +// | |- "global data/_QMdataEglob" +// | |- "global data/_QMdataEglobt" +// | +// |- "direct data" +// | | +// | |- "direct data/_QMdataEgloba" +// | |- "direct data/_QMdataEglobat" +// | +// |- "allocated data" +// | +// |- "allocated data/_QFtest1Elocal" +// |- "allocated data/_QFtest1Elocalt" +// |- "allocated data/_QFtest1Elocala" +// |- "allocated data/_QFtest1Elocalat" + +// ALL: #[[FUNCROOT:.+]] = #llvm.tbaa_root +// ALL: #[[ANYACCESS:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[ANYDATA:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[TARGETDATA:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[DUMMYDATA:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[TARGETTAG:.+]] = #llvm.tbaa_tag +// ALL: #[[GLOBALDATA:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[DIRECTDATA:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[DUMMYFVAR:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[DUMMYASVAR:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[DUMMYAVAR:.+]] = #llvm.tbaa_type_desc}> +// LOCAL: #[[LOCALDATA:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[DUMMYFTAG:.+]] = #llvm.tbaa_tag +// ALL: #[[DUMMYASTAG:.+]] = #llvm.tbaa_tag +// ALL: #[[DUMMYATAG:.+]] = #llvm.tbaa_tag +// ALL: #[[GLOBVAR:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[GLOBTVAR:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[GLOBAVAR:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[GLOBATVAR:.+]] = #llvm.tbaa_type_desc}> +// LOCAL: #[[LOCALVAR:.+]] = #llvm.tbaa_type_desc}> +// LOCAL: #[[LOCALTVAR:.+]] = #llvm.tbaa_type_desc}> +// LOCAL: #[[LOCALAVAR:.+]] = #llvm.tbaa_type_desc}> +// LOCAL: #[[LOCALATVAR:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[GLOBTAG:.+]] = #llvm.tbaa_tag +// ALL: #[[GLOBTTAG:.+]] = #llvm.tbaa_tag +// ALL: #[[GLOBATAG:.+]] = #llvm.tbaa_tag +// ALL: #[[GLOBATTAG:.+]] = #llvm.tbaa_tag +// LOCAL: #[[LOCALTAG:.+]] = #llvm.tbaa_tag +// LOCAL: #[[LOCALTTAG:.+]] = #llvm.tbaa_tag +// LOCAL: #[[LOCALATAG:.+]] = #llvm.tbaa_tag +// LOCAL: #[[LOCALATTAG:.+]] = #llvm.tbaa_tag + +module { + fir.global @_QMdataEglob : !fir.array<10xf32> { + %0 = fir.zero_bits !fir.array<10xf32> + fir.has_value %0 : !fir.array<10xf32> + } + fir.global @_QMdataEgloba : !fir.box>> { + %c0 = arith.constant 0 : index + %0 = fir.zero_bits !fir.heap> + %1 = fir.shape %c0 : (index) -> !fir.shape<1> + %2 = fir.embox %0(%1) : (!fir.heap>, !fir.shape<1>) -> !fir.box>> + fir.has_value %2 : !fir.box>> + } + fir.global @_QMdataEglobat target : !fir.box>> { + %c0 = arith.constant 0 : index + %0 = fir.zero_bits !fir.heap> + %1 = fir.shape %c0 : (index) -> !fir.shape<1> + %2 = fir.embox %0(%1) : (!fir.heap>, !fir.shape<1>) -> !fir.box>> + fir.has_value %2 : !fir.box>> + } + fir.global @_QMdataEglobp : !fir.box>> { + %c0 = arith.constant 0 : index + %0 = fir.zero_bits !fir.ptr> + %1 = fir.shape %c0 : (index) -> !fir.shape<1> + %2 = fir.embox %0(%1) : (!fir.ptr>, !fir.shape<1>) -> !fir.box>> + fir.has_value %2 : !fir.box>> + } + fir.global @_QMdataEglobt target : !fir.array<10xf32> { + %0 = fir.zero_bits !fir.array<10xf32> + fir.has_value %0 : !fir.array<10xf32> + } + +// ALL-LABEL: func.func @_QPtest1( + func.func @_QPtest1(%arg0: !fir.ref> {fir.bindc_name = "dummyf"}, %arg1: !fir.ref> {fir.bindc_name = "dummyft", fir.target}, %arg2: !fir.box> {fir.bindc_name = "dummyas"}, %arg3: !fir.box> {fir.bindc_name = "dummyast", fir.target}, %arg4: !fir.ref>>> {fir.bindc_name = "dummya"}, %arg5: !fir.ref>>> {fir.bindc_name = "dummyat", fir.target}, %arg6: !fir.ref>>> {fir.bindc_name = "dummyp"}) { + %c0_i64 = arith.constant 0 : i64 + %c1 = arith.constant 1 : index + %cst = arith.constant 1.000000e+00 : f32 + %c0 = arith.constant 0 : index + %c10 = arith.constant 10 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.declare %arg4 dummy_scope %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest1Edummya"} : (!fir.ref>>>, !fir.dscope) -> !fir.ref>>> + %2 = fir.declare %arg2 dummy_scope %0 {uniq_name = "_QFtest1Edummyas"} : (!fir.box>, !fir.dscope) -> !fir.box> + %3 = fir.declare %arg3 dummy_scope %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest1Edummyast"} : (!fir.box>, !fir.dscope) -> !fir.box> + %4 = fir.declare %arg5 dummy_scope %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest1Edummyat"} : (!fir.ref>>>, !fir.dscope) -> !fir.ref>>> + %5 = fir.shape %c10 : (index) -> !fir.shape<1> + %6 = fir.declare %arg0(%5) dummy_scope %0 {uniq_name = "_QFtest1Edummyf"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> !fir.ref> + %7 = fir.declare %arg1(%5) dummy_scope %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest1Edummyft"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> !fir.ref> + %8 = fir.declare %arg6 dummy_scope %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest1Edummyp"} : (!fir.ref>>>, !fir.dscope) -> !fir.ref>>> + %9 = fir.address_of(@_QMdataEglob) : !fir.ref> + %10 = fir.declare %9(%5) {uniq_name = "_QMdataEglob"} : (!fir.ref>, !fir.shape<1>) -> !fir.ref> + %11 = fir.address_of(@_QMdataEgloba) : !fir.ref>>> + %12 = fir.declare %11 {fortran_attrs = #fir.var_attrs, uniq_name = "_QMdataEgloba"} : (!fir.ref>>>) -> !fir.ref>>> + %13 = fir.address_of(@_QMdataEglobat) : !fir.ref>>> + %14 = fir.declare %13 {fortran_attrs = #fir.var_attrs, uniq_name = "_QMdataEglobat"} : (!fir.ref>>>) -> !fir.ref>>> + %15 = fir.address_of(@_QMdataEglobp) : !fir.ref>>> + %16 = fir.declare %15 {fortran_attrs = #fir.var_attrs, uniq_name = "_QMdataEglobp"} : (!fir.ref>>>) -> !fir.ref>>> + %17 = fir.address_of(@_QMdataEglobt) : !fir.ref> + %18 = fir.declare %17(%5) {fortran_attrs = #fir.var_attrs, uniq_name = "_QMdataEglobt"} : (!fir.ref>, !fir.shape<1>) -> !fir.ref> + %19 = fir.alloca !fir.array<10xf32> {bindc_name = "local", uniq_name = "_QFtest1Elocal"} + %20 = fir.declare %19(%5) {uniq_name = "_QFtest1Elocal"} : (!fir.ref>, !fir.shape<1>) -> !fir.ref> + %21 = fir.alloca !fir.box>> {bindc_name = "locala", uniq_name = "_QFtest1Elocala"} + %22 = fir.zero_bits !fir.heap> + %23 = fir.shape %c0 : (index) -> !fir.shape<1> + %24 = fir.embox %22(%23) : (!fir.heap>, !fir.shape<1>) -> !fir.box>> +// ALL-NOT: fir.store{{.*}}tbaa + fir.store %24 to %21 : !fir.ref>>> + %25 = fir.declare %21 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest1Elocala"} : (!fir.ref>>>) -> !fir.ref>>> + %26 = fir.alloca !fir.box>> {bindc_name = "localat", fir.target, uniq_name = "_QFtest1Elocalat"} +// ALL-NOT: fir.store{{.*}}tbaa + fir.store %24 to %26 : !fir.ref>>> + %27 = fir.declare %26 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest1Elocalat"} : (!fir.ref>>>) -> !fir.ref>>> + %28 = fir.alloca !fir.box>> {bindc_name = "localp", uniq_name = "_QFtest1Elocalp"} + %29 = fir.zero_bits !fir.ptr> + %30 = fir.embox %29(%23) : (!fir.ptr>, !fir.shape<1>) -> !fir.box>> +// ALL-NOT: fir.store{{.*}}tbaa + fir.store %30 to %28 : !fir.ref>>> + %31 = fir.declare %28 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest1Elocalp"} : (!fir.ref>>>) -> !fir.ref>>> + %32 = fir.alloca !fir.array<10xf32> {bindc_name = "localt", fir.target, uniq_name = "_QFtest1Elocalt"} + %33 = fir.declare %32(%5) {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest1Elocalt"} : (!fir.ref>, !fir.shape<1>) -> !fir.ref> + %34 = fir.array_coor %10(%5) %c1 : (!fir.ref>, !fir.shape<1>, index) -> !fir.ref +// module data :: real :: glob(10) +// ALL: fir.store{{.*}}{tbaa = [#[[GLOBTAG]]]} : !fir.ref + fir.store %cst to %34 : !fir.ref + %35 = fir.array_coor %18(%5) %c1 : (!fir.ref>, !fir.shape<1>, index) -> !fir.ref +// module data :: real, target :: globt(10) +// ALL: fir.store{{.*}}{tbaa = [#[[GLOBTTAG]]]} : !fir.ref + fir.store %cst to %35 : !fir.ref +// ALL-NOT: fir.load{{.*}}tbaa + %36 = fir.load %12 : !fir.ref>>> + %37 = fir.box_addr %36 : (!fir.box>>) -> !fir.heap> + %38:3 = fir.box_dims %36, %c0 : (!fir.box>>, index) -> (index, index, index) + %39 = fir.shape_shift %38#0, %38#1 : (index, index) -> !fir.shapeshift<1> + %40 = fir.array_coor %37(%39) %c1 : (!fir.heap>, !fir.shapeshift<1>, index) -> !fir.ref +// module data :: real, allocatable :: globa(:) +// ALL: fir.store{{.*}}{tbaa = [#[[GLOBATAG]]]} : !fir.ref + fir.store %cst to %40 : !fir.ref +// ALL-NOT: fir.load{{.*}}tbaa + %41 = fir.load %14 : !fir.ref>>> + %42 = fir.box_addr %41 : (!fir.box>>) -> !fir.heap> + %43:3 = fir.box_dims %41, %c0 : (!fir.box>>, index) -> (index, index, index) + %44 = fir.shape_shift %43#0, %43#1 : (index, index) -> !fir.shapeshift<1> + %45 = fir.array_coor %42(%44) %c1 : (!fir.heap>, !fir.shapeshift<1>, index) -> !fir.ref +// module data :: real, allocatable, target :: globat(:) +// ALL: fir.store{{.*}}{tbaa = [#[[GLOBATTAG]]]} : !fir.ref + fir.store %cst to %45 : !fir.ref +// ALL-NOT: fir.load{{.*}}tbaa + %46 = fir.load %16 : !fir.ref>>> + %47:3 = fir.box_dims %46, %c0 : (!fir.box>>, index) -> (index, index, index) + %48 = fir.shift %47#0 : (index) -> !fir.shift<1> + %49 = fir.array_coor %46(%48) %c1 : (!fir.box>>, !fir.shift<1>, index) -> !fir.ref +// module data :: real, pointer :: globp(:) +// ALL: fir.store{{.*}}{tbaa = [#[[TARGETTAG]]]} : !fir.ref + fir.store %cst to %49 : !fir.ref + %50 = fir.array_coor %6(%5) %c1 : (!fir.ref>, !fir.shape<1>, index) -> !fir.ref +// real :: dummyf(10) +// ALL: fir.store{{.*}}{tbaa = [#[[DUMMYFTAG]]]} : !fir.ref + fir.store %cst to %50 : !fir.ref + %51 = fir.array_coor %7(%5) %c1 : (!fir.ref>, !fir.shape<1>, index) -> !fir.ref +// real, target :: dummyft(10) +// ALL: fir.store{{.*}}{tbaa = [#[[TARGETTAG]]]} : !fir.ref + fir.store %cst to %51 : !fir.ref + %52 = fir.array_coor %2 %c1 : (!fir.box>, index) -> !fir.ref +// real :: dummyas(:) +// ALL: fir.store{{.*}}{tbaa = [#[[DUMMYASTAG]]]} : !fir.ref + fir.store %cst to %52 : !fir.ref + %53 = fir.array_coor %3 %c1 : (!fir.box>, index) -> !fir.ref +// real, target :: dummyast(:) +// ALL: fir.store{{.*}}{tbaa = [#[[TARGETTAG]]]} : !fir.ref + fir.store %cst to %53 : !fir.ref +// ALL-NOT: fir.load{{.*}}tbaa + %54 = fir.load %1 : !fir.ref>>> + %55 = fir.box_addr %54 : (!fir.box>>) -> !fir.heap> + %56:3 = fir.box_dims %54, %c0 : (!fir.box>>, index) -> (index, index, index) + %57 = fir.shape_shift %56#0, %56#1 : (index, index) -> !fir.shapeshift<1> + %58 = fir.array_coor %55(%57) %c1 : (!fir.heap>, !fir.shapeshift<1>, index) -> !fir.ref +// real, allocatable :: dummya(:) +// ALL: fir.store{{.*}}{tbaa = [#[[DUMMYATAG]]]} : !fir.ref + fir.store %cst to %58 : !fir.ref +// ALL-NOT: fir.load{{.*}}tbaa + %59 = fir.load %4 : !fir.ref>>> + %60 = fir.box_addr %59 : (!fir.box>>) -> !fir.heap> + %61:3 = fir.box_dims %59, %c0 : (!fir.box>>, index) -> (index, index, index) + %62 = fir.shape_shift %61#0, %61#1 : (index, index) -> !fir.shapeshift<1> + %63 = fir.array_coor %60(%62) %c1 : (!fir.heap>, !fir.shapeshift<1>, index) -> !fir.ref +// real, allocatable, target :: dummyat(:) +// ALL: fir.store{{.*}}{tbaa = [#[[TARGETTAG]]]} : !fir.ref + fir.store %cst to %63 : !fir.ref +// ALL-NOT: fir.load{{.*}}tbaa + %64 = fir.load %8 : !fir.ref>>> + %65:3 = fir.box_dims %64, %c0 : (!fir.box>>, index) -> (index, index, index) + %66 = fir.shift %65#0 : (index) -> !fir.shift<1> + %67 = fir.array_coor %64(%66) %c1 : (!fir.box>>, !fir.shift<1>, index) -> !fir.ref +// real, pointer :: dummyp(:) +// ALL: fir.store{{.*}}{tbaa = [#[[TARGETTAG]]]} : !fir.ref + fir.store %cst to %67 : !fir.ref + %68 = fir.array_coor %20(%5) %c1 : (!fir.ref>, !fir.shape<1>, index) -> !fir.ref +// real :: local(10) +// DEFAULT-NOT: fir.store{{.*}}tbaa +// LOCAL: fir.store{{.*}}{tbaa = [#[[LOCALTAG]]]} : !fir.ref + fir.store %cst to %68 : !fir.ref + %69 = fir.array_coor %33(%5) %c1 : (!fir.ref>, !fir.shape<1>, index) -> !fir.ref +// real, target :: localt(10) +// DEFAULT-NOT: fir.store{{.*}}tbaa +// LOCAL: fir.store{{.*}}{tbaa = [#[[LOCALTTAG]]]} : !fir.ref + fir.store %cst to %69 : !fir.ref +// ALL-NOT: fir.load{{.*}}tbaa + %70 = fir.load %25 : !fir.ref>>> + %71 = fir.box_addr %70 : (!fir.box>>) -> !fir.heap> + %72:3 = fir.box_dims %70, %c0 : (!fir.box>>, index) -> (index, index, index) + %73 = fir.shape_shift %72#0, %72#1 : (index, index) -> !fir.shapeshift<1> + %74 = fir.array_coor %71(%73) %c1 : (!fir.heap>, !fir.shapeshift<1>, index) -> !fir.ref +// real, allocatable :: locala(:) +// DEFAULT-NOT: fir.store{{.*}}tbaa +// LOCAL: fir.store{{.*}}{tbaa = [#[[LOCALATAG]]]} : !fir.ref + fir.store %cst to %74 : !fir.ref +// ALL-NOT: fir.load{{.*}}tbaa + %75 = fir.load %27 : !fir.ref>>> + %76 = fir.box_addr %75 : (!fir.box>>) -> !fir.heap> + %77:3 = fir.box_dims %75, %c0 : (!fir.box>>, index) -> (index, index, index) + %78 = fir.shape_shift %77#0, %77#1 : (index, index) -> !fir.shapeshift<1> + %79 = fir.array_coor %76(%78) %c1 : (!fir.heap>, !fir.shapeshift<1>, index) -> !fir.ref +// real, allocatable, target :: localat(:) +// DEFAULT-NOT: fir.store{{.*}}tbaa +// LOCAL: fir.store{{.*}}{tbaa = [#[[LOCALATTAG]]]} : !fir.ref + fir.store %cst to %79 : !fir.ref +// ALL-NOT: fir.load{{.*}}tbaa + %80 = fir.load %31 : !fir.ref>>> + %81:3 = fir.box_dims %80, %c0 : (!fir.box>>, index) -> (index, index, index) + %82 = fir.shift %81#0 : (index) -> !fir.shift<1> + %83 = fir.array_coor %80(%82) %c1 : (!fir.box>>, !fir.shift<1>, index) -> !fir.ref +// real, pointer :: localp(:) +// DEFAULT-NOT: fir.store{{.*}}tbaa +// LOCAL: fir.store{{.*}}{tbaa = [#[[TARGETTAG]]]} : !fir.ref + fir.store %cst to %83 : !fir.ref +// ALL-NOT: fir.load{{.*}}tbaa + %84 = fir.load %27 : !fir.ref>>> + %85 = fir.box_addr %84 : (!fir.box>>) -> !fir.heap> + %86 = fir.convert %85 : (!fir.heap>) -> i64 + %87 = arith.cmpi ne, %86, %c0_i64 : i64 + fir.if %87 { +// ALL-NOT: fir.load{{.*}}tbaa + %92 = fir.load %27 : !fir.ref>>> + %93 = fir.box_addr %92 : (!fir.box>>) -> !fir.heap> + fir.freemem %93 : !fir.heap> +// ALL-NOT: fir.store{{.*}}tbaa + fir.store %24 to %27 : !fir.ref>>> + } +// ALL-NOT: fir.load{{.*}}tbaa + %88 = fir.load %25 : !fir.ref>>> + %89 = fir.box_addr %88 : (!fir.box>>) -> !fir.heap> + %90 = fir.convert %89 : (!fir.heap>) -> i64 + %91 = arith.cmpi ne, %90, %c0_i64 : i64 + fir.if %91 { +// ALL-NOT: fir.load{{.*}}tbaa + %92 = fir.load %25 : !fir.ref>>> + %93 = fir.box_addr %92 : (!fir.box>>) -> !fir.heap> + fir.freemem %93 : !fir.heap> +// ALL-NOT: fir.store{{.*}}tbaa + fir.store %24 to %25 : !fir.ref>>> + } + return + } +} diff --git a/flang/test/Transforms/tbaa4.fir b/flang/test/Transforms/tbaa4.fir new file mode 100644 index 0000000000000..6fa8fff02b6a6 --- /dev/null +++ b/flang/test/Transforms/tbaa4.fir @@ -0,0 +1,177 @@ +// Test TBAA tags for common and equivalence. +// RUN: fir-opt --fir-add-alias-tags --split-input-file %s | FileCheck --check-prefixes=ALL,DEFAULT %s +// RUN: fir-opt --fir-add-alias-tags --local-alloc-tbaa --split-input-file %s | FileCheck --check-prefixes=ALL,LOCAL %s + +// ALL: #[[ROOT:.+]] = #llvm.tbaa_root +// ALL: #[[ANY:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[ANYDATA:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[TARGETDATA:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[GLOBALDATA:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[BLK:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[TAG:.+]] = #llvm.tbaa_tag + +module { +// ALL-LABEL: fir.global common @blk_(dense<0> : vector<48xi8>) {alignment = 4 : i64} : !fir.array<48xi8> + fir.global common @blk_(dense<0> : vector<48xi8>) {alignment = 4 : i64} : !fir.array<48xi8> + +// ALL-LABEL: func.func @_QPtest_common() { +// ALL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ref +// ALL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ref +// ALL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ref + func.func @_QPtest_common() { + %c1 = arith.constant 1 : index + %c1_i32 = arith.constant 1 : i32 + %cst = arith.constant 1.000000e+00 : f32 + %c10 = arith.constant 10 : index + %c8 = arith.constant 8 : index + %c4 = arith.constant 4 : index + %c0 = arith.constant 0 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.address_of(@blk_) : !fir.ref> + %2 = fir.convert %1 : (!fir.ref>) -> !fir.ref> + %3 = fir.coordinate_of %2, %c0 : (!fir.ref>, index) -> !fir.ref + %4 = fir.convert %3 : (!fir.ref) -> !fir.ref + %5 = fir.declare %4 {uniq_name = "_QFtest_commonEa"} : (!fir.ref) -> !fir.ref + %6 = fir.coordinate_of %2, %c4 : (!fir.ref>, index) -> !fir.ref + %7 = fir.convert %6 : (!fir.ref) -> !fir.ref + %8 = fir.declare %7 {uniq_name = "_QFtest_commonEb"} : (!fir.ref) -> !fir.ref + %9 = fir.coordinate_of %2, %c8 : (!fir.ref>, index) -> !fir.ref + %10 = fir.convert %9 : (!fir.ref) -> !fir.ref> + %11 = fir.shape %c10 : (index) -> !fir.shape<1> + %12 = fir.declare %10(%11) {uniq_name = "_QFtest_commonEc"} : (!fir.ref>, !fir.shape<1>) -> !fir.ref> + fir.store %cst to %5 : !fir.ref + %13 = fir.array_coor %12(%11) %c1 : (!fir.ref>, !fir.shape<1>, index) -> !fir.ref + fir.store %c1_i32 to %13 : !fir.ref + fir.store %cst to %8 : !fir.ref + return + } +} + +// ----- + +// LOCAL: #[[ROOT:.+]] = #llvm.tbaa_root +// LOCAL: #[[ANY:.+]] = #llvm.tbaa_type_desc}> +// LOCAL: #[[ANYDATA:.+]] = #llvm.tbaa_type_desc}> +// LOCAL: #[[TARGETDATA:.+]] = #llvm.tbaa_type_desc}> +// LOCAL: #[[ALLOCATEDDATA:.+]] = #llvm.tbaa_type_desc}> +// LOCAL: #[[EQUIV:.+]] = #llvm.tbaa_type_desc}> +// LOCAL: #[[$ATTR_13:.+]] = #llvm.tbaa_tag + +// ALL-LABEL: func.func @_QPtest_local_equiv() { +// LOCAL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ptr +// LOCAL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ref +// LOCAL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ptr +// DEFAULT-NOT: fir.store{{.}}tbaa +func.func @_QPtest_local_equiv() { + %c1 = arith.constant 1 : index + %c1_i32 = arith.constant 1 : i32 + %cst = arith.constant 1.000000e+00 : f32 + %c10 = arith.constant 10 : index + %c0 = arith.constant 0 : index + %c8 = arith.constant 8 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.alloca !fir.array<40xi8> {uniq_name = "_QFtest_local_equivEa"} + %2 = fir.coordinate_of %1, %c8 : (!fir.ref>, index) -> !fir.ref + %3 = fir.convert %2 : (!fir.ref) -> !fir.ptr + %4 = fir.declare %3 {uniq_name = "_QFtest_local_equivEa"} : (!fir.ptr) -> !fir.ptr + %5 = fir.declare %3 {uniq_name = "_QFtest_local_equivEb"} : (!fir.ptr) -> !fir.ptr + %6 = fir.coordinate_of %1, %c0 : (!fir.ref>, index) -> !fir.ref + %7 = fir.convert %6 : (!fir.ref) -> !fir.ptr> + %8 = fir.shape %c10 : (index) -> !fir.shape<1> + %9 = fir.declare %7(%8) {uniq_name = "_QFtest_local_equivEc"} : (!fir.ptr>, !fir.shape<1>) -> !fir.ptr> + fir.store %cst to %4 : !fir.ptr + %10 = fir.array_coor %9(%8) %c1 : (!fir.ptr>, !fir.shape<1>, index) -> !fir.ref + fir.store %c1_i32 to %10 : !fir.ref + fir.store %cst to %5 : !fir.ptr + return +} + +// ----- + +// ALL: #[[ROOT:.+]] = #llvm.tbaa_root +// ALL: #[[ANY:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[ANYDATA:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[TARGETDATA:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[GLOBALDATA:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[EQUIV:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[TAG:.+]] = #llvm.tbaa_tag +module { +// ALL-LABEL: fir.global internal @_QFtest_save_equivEa : !fir.array<40xi8> { + fir.global internal @_QFtest_save_equivEa : !fir.array<40xi8> { + %0 = fir.zero_bits !fir.array<40xi8> + fir.has_value %0 : !fir.array<40xi8> + } + +// ALL-LABEL: func.func @_QPtest_save_equiv() { +// ALL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ptr +// ALL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ref +// ALL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ptr + func.func @_QPtest_save_equiv() { + %c1 = arith.constant 1 : index + %c1_i32 = arith.constant 1 : i32 + %cst = arith.constant 1.000000e+00 : f32 + %c10 = arith.constant 10 : index + %c0 = arith.constant 0 : index + %c8 = arith.constant 8 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.address_of(@_QFtest_save_equivEa) : !fir.ref> + %2 = fir.coordinate_of %1, %c8 : (!fir.ref>, index) -> !fir.ref + %3 = fir.convert %2 : (!fir.ref) -> !fir.ptr + %4 = fir.declare %3 {uniq_name = "_QFtest_save_equivEa"} : (!fir.ptr) -> !fir.ptr + %5 = fir.declare %3 {uniq_name = "_QFtest_save_equivEb"} : (!fir.ptr) -> !fir.ptr + %6 = fir.coordinate_of %1, %c0 : (!fir.ref>, index) -> !fir.ref + %7 = fir.convert %6 : (!fir.ref) -> !fir.ptr> + %8 = fir.shape %c10 : (index) -> !fir.shape<1> + %9 = fir.declare %7(%8) {uniq_name = "_QFtest_save_equivEc"} : (!fir.ptr>, !fir.shape<1>) -> !fir.ptr> + fir.store %cst to %4 : !fir.ptr + %10 = fir.array_coor %9(%8) %c1 : (!fir.ptr>, !fir.shape<1>, index) -> !fir.ref + fir.store %c1_i32 to %10 : !fir.ref + fir.store %cst to %5 : !fir.ptr + return + } +} + +// ----- + +// ALL: #[[ROOT:.+]] = #llvm.tbaa_root +// ALL: #[[ANY:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[ANYDATA:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[TARGETDATA:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[GLOBALDATA:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[EQUIV:.+]] = #llvm.tbaa_type_desc}> +// ALL: #[[TAG:.+]] = #llvm.tbaa_tag + +module { +// ALL-LABEL: fir.global @_QMdataEa : !fir.array<40xi8> { + fir.global @_QMdataEa : !fir.array<40xi8> { + %0 = fir.zero_bits !fir.array<40xi8> + fir.has_value %0 : !fir.array<40xi8> + } +// ALL-LABEL: func.func @_QPtest_global_equiv() { +// ALL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ptr +// ALL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ref +// ALL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ptr + func.func @_QPtest_global_equiv() { + %c1 = arith.constant 1 : index + %c1_i32 = arith.constant 1 : i32 + %cst = arith.constant 1.000000e+00 : f32 + %c10 = arith.constant 10 : index + %c0 = arith.constant 0 : index + %c8 = arith.constant 8 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.address_of(@_QMdataEa) : !fir.ref> + %2 = fir.coordinate_of %1, %c8 : (!fir.ref>, index) -> !fir.ref + %3 = fir.convert %2 : (!fir.ref) -> !fir.ptr + %4 = fir.declare %3 {uniq_name = "_QMdataEa"} : (!fir.ptr) -> !fir.ptr + %5 = fir.declare %3 {uniq_name = "_QMdataEb"} : (!fir.ptr) -> !fir.ptr + %6 = fir.coordinate_of %1, %c0 : (!fir.ref>, index) -> !fir.ref + %7 = fir.convert %6 : (!fir.ref) -> !fir.ptr> + %8 = fir.shape %c10 : (index) -> !fir.shape<1> + %9 = fir.declare %7(%8) {uniq_name = "_QMdataEc"} : (!fir.ptr>, !fir.shape<1>) -> !fir.ptr> + fir.store %cst to %4 : !fir.ptr + %10 = fir.array_coor %9(%8) %c1 : (!fir.ptr>, !fir.shape<1>, index) -> !fir.ref + fir.store %c1_i32 to %10 : !fir.ref + fir.store %cst to %5 : !fir.ptr + return + } +}