Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions flang/include/flang/Optimizer/Analysis/TBAAForest.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,25 @@ struct TBAATree {
// |- "any data access"
// |
// |- "dummy arg data"
// |- "target data"
// |
// |- "allocated data"
// |- "direct data"
// |- "global data"
// |
// |- <dummy arg name 1>
// |- <dummy arg name 2>
// |- "target data" <-- Any POINTER variable or TARGET dummy arg
// |
// |- <target name 1> <--- any TARGET variable which isn't a dummy arg
// |- <target name 2>
// |- "allocated data"
// |
// |- <allocated name 1>
// |- <allocated name 2>
// |- "direct data"
// |
// |- <direct name 1>
// |- <direct name 2>
// |- "global data"
// |
// |- <global name 1>
// |- <global name 2>
static TBAATree buildTree(mlir::StringAttr functionName);

private:
Expand Down
9 changes: 3 additions & 6 deletions flang/lib/Optimizer/Analysis/TBAAForest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,9 @@ fir::TBAATree::TBAATree(mlir::LLVM::TBAATypeDescriptorAttr anyAccess,
mlir::LLVM::TBAATypeDescriptorAttr dataRoot,
mlir::LLVM::TBAATypeDescriptorAttr boxMemberTypeDesc)
: targetDataTree(dataRoot.getContext(), "target data", dataRoot),
globalDataTree(dataRoot.getContext(), "global data",
targetDataTree.getRoot()),
allocatedDataTree(dataRoot.getContext(), "allocated data",
targetDataTree.getRoot()),
globalDataTree(dataRoot.getContext(), "global data", dataRoot),
allocatedDataTree(dataRoot.getContext(), "allocated data", dataRoot),
dummyArgDataTree(dataRoot.getContext(), "dummy arg data", dataRoot),
directDataTree(dataRoot.getContext(), "direct data",
targetDataTree.getRoot()),
directDataTree(dataRoot.getContext(), "direct data", dataRoot),
anyAccessDesc(anyAccess), boxMemberTypeDesc(boxMemberTypeDesc),
anyDataTypeDesc(dataRoot) {}
59 changes: 47 additions & 12 deletions flang/lib/Optimizer/Transforms/AddAliasTags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ static llvm::cl::opt<unsigned> localAllocsThreshold(
llvm::cl::desc("If present, stops generating TBAA tags for accesses of "
"local allocations after N accesses in a module"));

// Defined in AliasAnalysis.cpp
extern llvm::cl::opt<bool> supportCrayPointers;

namespace {

// Return the size and alignment (in bytes) for the given type.
Expand Down Expand Up @@ -668,6 +671,7 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
LLVM_DEBUG(llvm::dbgs() << "Analysing " << op << "\n");

const fir::AliasAnalysis::Source &source = state.getSource(memref);
LLVM_DEBUG(llvm::dbgs() << "Got source " << source << "\n");

// Process the scopes, if not processed yet.
state.processFunctionScopes(func);
Expand All @@ -686,14 +690,22 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
}

mlir::LLVM::TBAATagAttr tag;
// TBAA for dummy arguments
if (enableDummyArgs &&
source.kind == fir::AliasAnalysis::SourceKind::Argument) {
// Cray pointer/pointee is a special case. These might alias with any data.
if (supportCrayPointers && source.isCrayPointerOrPointee()) {
LLVM_DEBUG(llvm::dbgs().indent(2)
<< "Found reference to Cray pointer/pointee at " << *op << "\n");
mlir::LLVM::TBAATypeDescriptorAttr anyDataDesc =
state.getFuncTreeWithScope(func, scopeOp).anyDataTypeDesc;
tag = mlir::LLVM::TBAATagAttr::get(anyDataDesc, anyDataDesc, /*offset=*/0);
// TBAA for dummy arguments
} else if (enableDummyArgs &&
source.kind == fir::AliasAnalysis::SourceKind::Argument) {
LLVM_DEBUG(llvm::dbgs().indent(2)
<< "Found reference to dummy argument at " << *op << "\n");
std::string name = getFuncArgName(llvm::cast<mlir::Value>(source.origin.u));
// 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.
// POINTERS can alias with any POINTER or TARGET. Assume that TARGET dummy
// arguments might alias with each other (because of the "TARGET" hole for
// dummy arguments). See flang/docs/Aliasing.md.
if (source.isTargetOrPointer()) {
tag = state.getFuncTreeWithScope(func, scopeOp).targetDataTree.getTag();
} else if (!name.empty()) {
Expand All @@ -715,13 +727,10 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
LLVM_DEBUG(llvm::dbgs().indent(2)
<< "Found reference to global " << globalName.str() << " at "
<< *op << "\n");
if (source.isPointer()) {
tag = state.getFuncTreeWithScope(func, scopeOp).targetDataTree.getTag();
} else {
// In general, place the tags under the "global data" root.
fir::TBAATree::SubtreeState *subTree =
&state.getMutableFuncTreeWithScope(func, scopeOp).globalDataTree;

// Add a named tag inside the given subtree, disambiguating members of a
// common block
auto addTagUsingStorageDesc = [&](fir::TBAATree::SubtreeState *subTree) {
mlir::Operation *instantiationPoint = source.origin.instantiationPoint;
auto storageIface =
mlir::dyn_cast_or_null<fir::FortranVariableStorageOpInterface>(
Expand Down Expand Up @@ -766,6 +775,19 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
LLVM_DEBUG(llvm::dbgs()
<< "Tagged under '" << globalName << "' root\n");
}
};

if (source.isPointer()) {
// Pointers can alias with any pointer or target.
tag = state.getFuncTreeWithScope(func, scopeOp).targetDataTree.getTag();
} else if (source.isTarget()) {
// Targets could alias with any pointer but not with each other.
addTagUsingStorageDesc(
&state.getMutableFuncTreeWithScope(func, scopeOp).targetDataTree);
} else {
// In general, place the tags under the "global data" root.
addTagUsingStorageDesc(
&state.getMutableFuncTreeWithScope(func, scopeOp).globalDataTree);
}

// TBAA for global variables with descriptors
Expand All @@ -776,9 +798,17 @@ 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");
// Pointer can alias with any pointer or target so that gets the root.
if (source.isPointer())
tag = state.getFuncTreeWithScope(func, scopeOp).targetDataTree.getTag();
// Targets could alias with any pointer but not with each other so they
// get their own node inside of the target data tree.
else if (source.isTarget())
tag = state.getFuncTreeWithScope(func, scopeOp)
.targetDataTree.getTag(name);
else
// Boxes that are not pointers or targets cannot alias with those that
// are. Put them under global data.
tag = state.getFuncTreeWithScope(func, scopeOp)
.directDataTree.getTag(name);
} else {
Expand Down Expand Up @@ -815,8 +845,13 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
<< "\n");
} else if (source.isPointer() && state.attachLocalAllocTag()) {
LLVM_DEBUG(llvm::dbgs().indent(2)
<< "Found reference to allocation at " << *op << "\n");
<< "Found reference to POINTER allocation at " << *op << "\n");
tag = state.getFuncTreeWithScope(func, scopeOp).targetDataTree.getTag();
} else if (source.isTarget() && state.attachLocalAllocTag()) {
LLVM_DEBUG(llvm::dbgs().indent(2)
<< "Found reference to TARGET allocation at " << *op << "\n");
tag = state.getFuncTreeWithScope(func, scopeOp)
.targetDataTree.getTag(*name);
} else if (name && state.attachLocalAllocTag()) {
LLVM_DEBUG(llvm::dbgs().indent(2) << "Found reference to allocation "
<< name << " at " << *op << "\n");
Expand Down
8 changes: 4 additions & 4 deletions flang/test/Driver/tco-test-gen.fir
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,13 @@ func.func @_QPtest(%arg0: !fir.ref<i32> {fir.bindc_name = "num"}, %arg1: !fir.re
// CHECK: llvm.cond_br %[[VAL_17]], ^bb2, ^bb3
// CHECK: ^bb2:

// AA: llvm.store %[[VAL_15]], %[[VAL_1]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : i32, !llvm.ptr
// AA: llvm.store %[[VAL_15]], %[[VAL_1]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : i32, !llvm.ptr
// NOAA: llvm.store %[[VAL_15]], %{{.*}} : i32, !llvm.ptr

// AA: %[[VAL_18:.*]] = llvm.load %[[ARG0]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "dummy arg data/_QFtestEnum", members = {<#llvm.tbaa_type_desc<id = "dummy arg data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "dummy arg data/_QFtestEnum", members = {<#llvm.tbaa_type_desc<id = "dummy arg data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : !llvm.ptr -> i32
// NOAA: %[[VAL_18:.*]] = llvm.load %[[ARG0]] : !llvm.ptr -> i32

// AA: %[[VAL_19:.*]] = llvm.load %[[VAL_1]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : !llvm.ptr -> i32
// AA: %[[VAL_19:.*]] = llvm.load %[[VAL_1]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : !llvm.ptr -> i32
// NOAA: %[[VAL_19:.*]] = llvm.load %{{.*}} : !llvm.ptr -> i32

// CHECK: %[[VAL_20:.*]] = llvm.add %[[VAL_18]], %[[VAL_19]] : i32
Expand All @@ -92,15 +92,15 @@ func.func @_QPtest(%arg0: !fir.ref<i32> {fir.bindc_name = "num"}, %arg1: !fir.re

// CHECK: %[[VAL_21:.*]] = llvm.trunc %[[VAL_10]] : i64 to i32

// AA: %[[VAL_22:.*]] = llvm.load %[[VAL_1]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : !llvm.ptr -> i32
// AA: %[[VAL_22:.*]] = llvm.load %[[VAL_1]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : !llvm.ptr -> i32
// NOAA: %[[VAL_22:.*]] = llvm.load %{{.*}} : !llvm.ptr -> i32

// CHECK: %[[VAL_23:.*]] = llvm.add %[[VAL_22]], %[[VAL_21]] overflow<nsw> : i32
// CHECK: %[[VAL_24:.*]] = llvm.sub %[[VAL_16]], %{{.*}} : i64
// CHECK: llvm.br ^bb1(%[[VAL_23]], %[[VAL_24]] : i32, i64)
// CHECK: ^bb3:

// AA: llvm.store %[[VAL_15]], %[[VAL_1]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : i32, !llvm.ptr
// AA: llvm.store %[[VAL_15]], %[[VAL_1]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : i32, !llvm.ptr
// NOAA: llvm.store %[[VAL_15]], %{{.*}} : i32, !llvm.ptr

// CHECK: llvm.return
Expand Down
1 change: 0 additions & 1 deletion flang/test/Fir/tbaa-codegen2.fir
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,3 @@ module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.targ
// CHECK: ![[TMP_DATA_ACCESS_TAG]] = !{![[TMP_DATA_ACCESS_TYPE:.*]], ![[TMP_DATA_ACCESS_TYPE]], i64 0}
// CHECK: ![[TMP_DATA_ACCESS_TYPE]] = !{!"allocated data/", ![[TMP_ACCESS_TYPE:.*]], i64 0}
// CHECK: ![[TMP_ACCESS_TYPE]] = !{!"allocated data", ![[TARGET_ACCESS_TAG:.*]], i64 0}
// CHECK: ![[TARGET_ACCESS_TAG]] = !{!"target data", ![[DATA_ACCESS_TYPE]], i64 0}
43 changes: 43 additions & 0 deletions flang/test/Transforms/tbaa-cray-pointer.fir
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// RUN: fir-opt -funsafe-cray-pointers --fir-add-alias-tags %s | FileCheck %s

// Fortran source:
// subroutine test()
// real :: a, b
// pointer(p, a)
// p = loc(b)
// b = 2
// end subroutine

// CHECK: #[[TBAA_ROOT:.*]] = #llvm.tbaa_root<id = "Flang function root _QPtest">
// CHECK-NEXT: #[[ANY_ACCESS:.*]] = #llvm.tbaa_type_desc<id = "any access", members = {<#[[TBAA_ROOT]], 0>}>
// CHECK-NEXT: #[[ANY_DATA:.*]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[ANY_ACCESS]], 0>}>
// CHECK-NEXT: #[[ANY_DATA_TAG:.*]] = #llvm.tbaa_tag<base_type = #[[ANY_DATA]], access_type = #[[ANY_DATA]], offset = 0>
// CHECK-NEXT: #[[ALLOCATED_DATA:.*]] = #llvm.tbaa_type_desc<id = "allocated data", members = {<#[[ANY_DATA]], 0>}>
// CHECK-NEXT: #[[B:.*]] = #llvm.tbaa_type_desc<id = "allocated data/_QFtestEb", members = {<#[[ALLOCATED_DATA]], 0>}>
// CHECK-NEXT: #[[B_TAG:.*]] = #llvm.tbaa_tag<base_type = #[[B]], access_type = #[[B]], offset = 0>

module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr<270> = dense<32> : vector<4xi64>, !llvm.ptr<271> = dense<32> : vector<4xi64>, !llvm.ptr<272> = dense<64> : vector<4xi64>, i8 = dense<[8, 32]> : vector<2xi64>, i16 = dense<[16, 32]> : vector<2xi64>, i64 = dense<64> : vector<2xi64>, i128 = dense<128> : vector<2xi64>, !llvm.ptr = dense<64> : vector<4xi64>, i1 = dense<8> : vector<2xi64>, i32 = dense<32> : vector<2xi64>, f16 = dense<16> : vector<2xi64>, f64 = dense<64> : vector<2xi64>, f128 = dense<128> : vector<2xi64>, "dlti.endianness" = "little", "dlti.mangling_mode" = "e", "dlti.legal_int_widths" = array<i32: 32, 64>, "dlti.stack_alignment" = 128 : i64, "dlti.function_pointer_alignment" = #dlti.function_pointer_alignment<32, function_dependent = true>>, fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"} {
// CHECK-LABEL: func.func @_QPtest()
func.func @_QPtest() {
%cst = arith.constant 2.000000e+00 : f32
%0 = fir.alloca !fir.box<!fir.ptr<f32>>
%1 = fir.dummy_scope : !fir.dscope
%2 = fir.alloca i64 {bindc_name = "p", uniq_name = "_QFtestEp"}
%3 = fir.declare %2 {fortran_attrs = #fir.var_attrs<cray_pointer>, uniq_name = "_QFtestEp"} : (!fir.ref<i64>) -> !fir.ref<i64>
%4 = fir.alloca f32 {bindc_name = "b", uniq_name = "_QFtestEb"}
%5 = fir.declare %4 {uniq_name = "_QFtestEb"} : (!fir.ref<f32>) -> !fir.ref<f32>
%6 = fir.declare %0 {fortran_attrs = #fir.var_attrs<pointer, cray_pointee>, uniq_name = "_QFtestEa"} : (!fir.ref<!fir.box<!fir.ptr<f32>>>) -> !fir.ref<!fir.box<!fir.ptr<f32>>>
%7 = fir.zero_bits !fir.ptr<f32>
%8 = fir.embox %7 : (!fir.ptr<f32>) -> !fir.box<!fir.ptr<f32>>
fir.store %8 to %6 : !fir.ref<!fir.box<!fir.ptr<f32>>>
// Descriptor tagged in codegen
// CHECK: fir.store %{{.*}} to %{{.*}} : !fir.ref<!fir.box<!fir.ptr<f32>>
%9 = fir.convert %5 : (!fir.ref<f32>) -> i64
fir.store %9 to %3 : !fir.ref<i64>
// CHECK: fir.store {{.*}} to {{.*}} {tbaa = [#[[ANY_DATA_TAG]]]} : !fir.ref<i64>
fir.store %cst to %5 : !fir.ref<f32>
// CHECK: fir.store {{.*}} to {{.*}} {tbaa = [#[[B_TAG]]]} : !fir.ref<f32>
return
}
}

Loading