Skip to content

[flang][AddAliasTags] Generalise tbaa tags beyond functions #92379

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
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
8 changes: 4 additions & 4 deletions flang/include/flang/Optimizer/Analysis/TBAAForest.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,15 @@ struct TBAATree {
//===----------------------------------------------------------------------===//
// TBAAForrest
//===----------------------------------------------------------------------===//
/// Collection of TBAATrees, usually indexed by function (so that each function
/// has a different TBAATree)
/// Collection of TBAATrees, usually indexed by symbol (so that each
/// function-like container operation has a different TBAATree)
class TBAAForrest {
public:
explicit TBAAForrest(bool separatePerFunction = true)
: separatePerFunction{separatePerFunction} {}

inline const TBAATree &operator[](mlir::func::FuncOp func) {
return getFuncTree(func.getSymNameAttr());
inline const TBAATree &operator[](mlir::SymbolOpInterface sym) {
return getFuncTree(sym.getNameAttr());
}
inline const TBAATree &operator[](mlir::LLVM::LLVMFuncOp func) {
// the external name conversion pass may rename some functions. Their old
Expand Down
37 changes: 28 additions & 9 deletions flang/lib/Optimizer/Transforms/AddAliasTags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ static llvm::cl::opt<bool> enableLocalAllocs(
"local-alloc-tbaa", llvm::cl::init(false), llvm::cl::Hidden,
llvm::cl::desc("Add TBAA tags to local allocations. UNSAFE."));

// Run on function-like top-level operations (e.g. omp.declare_reduction).
// This needs more testing before enabling by default:
static llvm::cl::opt<bool> runOnNonFunctions(
"nonfunc-tbaa", llvm::cl::init(false), llvm::cl::Hidden,
llvm::cl::desc("Add TBAA tags to operations insode of container operations "
"other than func.func"));

namespace {

/// Shared state per-module
Expand All @@ -61,9 +68,9 @@ class PassState {
return analysisCache[value];
}

/// get the per-function TBAATree for this function
inline const fir::TBAATree &getFuncTree(mlir::func::FuncOp func) {
return forrest[func];
/// get the per-function TBAATree for this function-like op
inline const fir::TBAATree &getFuncTree(mlir::SymbolOpInterface symbol) {
return forrest[symbol];
}

private:
Expand Down Expand Up @@ -113,10 +120,22 @@ static std::string getFuncArgName(mlir::Value arg) {
return attr.str();
}

static mlir::SymbolOpInterface getTopLevelSymbolParent(mlir::Operation *op) {
mlir::SymbolOpInterface parent =
op->getParentOfType<mlir::SymbolOpInterface>();
mlir::SymbolOpInterface oldParent = parent;
while (parent) {
parent = getTopLevelSymbolParent(parent);
if (parent)
oldParent = parent;
}
return oldParent;
}

void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
PassState &state) {
mlir::func::FuncOp func = op->getParentOfType<mlir::func::FuncOp>();
if (!func)
mlir::SymbolOpInterface parent = getTopLevelSymbolParent(op);
if (!runOnNonFunctions && !mlir::isa<mlir::func::FuncOp>(parent))
return;

llvm::SmallVector<mlir::Value> accessedOperands = op.getAccessedOperands();
Expand Down Expand Up @@ -147,7 +166,7 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
<< "Found reference to dummy argument at " << *op << "\n");
std::string name = getFuncArgName(source.u.get<mlir::Value>());
if (!name.empty())
tag = state.getFuncTree(func).dummyArgDataTree.getTag(name);
tag = state.getFuncTree(parent).dummyArgDataTree.getTag(name);
else
LLVM_DEBUG(llvm::dbgs().indent(2)
<< "WARN: couldn't find a name for dummy argument " << *op
Expand All @@ -160,7 +179,7 @@ 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.getFuncTree(func).globalDataTree.getTag(name);
tag = state.getFuncTree(parent).globalDataTree.getTag(name);

// TBAA for SourceKind::Direct
} else if (enableDirect &&
Expand All @@ -170,7 +189,7 @@ 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.getFuncTree(func).directDataTree.getTag(name);
tag = state.getFuncTree(parent).directDataTree.getTag(name);
} else {
// SourceKind::Direct is likely to be extended to cases which are not a
// SymbolRefAttr in the future
Expand All @@ -190,7 +209,7 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
if (name) {
LLVM_DEBUG(llvm::dbgs().indent(2) << "Found reference to allocation "
<< name << " at " << *op << "\n");
tag = state.getFuncTree(func).allocatedDataTree.getTag(*name);
tag = state.getFuncTree(parent).allocatedDataTree.getTag(*name);
} else {
LLVM_DEBUG(llvm::dbgs().indent(2)
<< "WARN: couldn't find a name for allocation " << *op
Expand Down
72 changes: 72 additions & 0 deletions flang/test/Transforms/tbaa3.fir
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Test experimental option to add tbaa trees for things that aren't functions

// RUN: fir-opt --nonfunc-tbaa --fir-add-alias-tags %s | FileCheck %s


// CHECK: #[[TBAA_ROOT:.*]] = #llvm.tbaa_root<id = "Flang function root add_reduction_byref_box_3xi32">
// CHECK: #[[ANY_ACCESS:.*]] = #llvm.tbaa_type_desc<id = "any access", members = {<#[[TBAA_ROOT]], 0>}>
// CHECK: #[[ANY_DATA:.*]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[ANY_ACCESS]], 0>}>
// CHECK: #[[DIRECT_DATA:.*]] = #llvm.tbaa_type_desc<id = "direct data", members = {<#[[ANY_DATA]], 0>}>
// CHECK: #[[GLOBAL_A:.*]] = #llvm.tbaa_type_desc<id = "direct data/_QMmodEa", members = {<#[[DIRECT_DATA]], 0>}>
// CHECK: #[[GLOBAL_A_TAG:.*]] = #llvm.tbaa_tag<base_type = #[[GLOBAL_A]], access_type = #[[GLOBAL_A]], offset = 0>

fir.global @_QMmodEa : !fir.box<!fir.heap<!fir.array<?xi32>>> {
%c0 = arith.constant 0 : index
%0 = fir.zero_bits !fir.heap<!fir.array<?xi32>>
%1 = fir.shape %c0 : (index) -> !fir.shape<1>
%2 = fir.embox %0(%1) : (!fir.heap<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xi32>>>
fir.has_value %2 : !fir.box<!fir.heap<!fir.array<?xi32>>>
}

// nonsense reduction to give us something that we can generate TBAA tags for
omp.declare_reduction @add_reduction_byref_box_3xi32 : !fir.ref<!fir.box<!fir.array<3xi32>>> init {
^bb0(%arg0: !fir.ref<!fir.box<!fir.array<3xi32>>>):
%c0_i32 = arith.constant 0 : i32
%0 = fir.load %arg0 : !fir.ref<!fir.box<!fir.array<3xi32>>>
%1 = fir.address_of(@_QMmodEa) : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
%c3 = arith.constant 3 : index
%2 = fir.shape %c3 : (index) -> !fir.shape<1>
%3 = fir.allocmem !fir.array<3xi32> {bindc_name = ".tmp", uniq_name = ""}
%true = arith.constant true
%4:2 = hlfir.declare %3(%2) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<3xi32>>, !fir.shape<1>) -> (!fir.heap<!fir.array<3xi32>>, !fir.heap<!fir.array<3xi32>>)
%c0 = arith.constant 0 : index
%5:3 = fir.box_dims %0, %c0 : (!fir.box<!fir.array<3xi32>>, index) -> (index, index, index)
%6 = fir.shape_shift %5#0, %5#1 : (index, index) -> !fir.shapeshift<1>
%7 = fir.embox %4#0(%6) : (!fir.heap<!fir.array<3xi32>>, !fir.shapeshift<1>) -> !fir.box<!fir.array<3xi32>>
hlfir.assign %c0_i32 to %7 : i32, !fir.box<!fir.array<3xi32>>
%8 = fir.convert %7 : (!fir.box<!fir.array<3xi32>>) -> !fir.box<!fir.heap<!fir.array<?xi32>>>
fir.store %8 to %1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
%9 = fir.convert %1 : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.array<3xi32>>>
omp.yield(%9 : !fir.ref<!fir.box<!fir.array<3xi32>>>)
} combiner {
^bb0(%arg0: !fir.ref<!fir.box<!fir.array<3xi32>>>, %arg1: !fir.ref<!fir.box<!fir.array<3xi32>>>):
%0 = fir.load %arg0 : !fir.ref<!fir.box<!fir.array<3xi32>>>
%1 = fir.address_of(@_QMmodEa) : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
%a = fir.load %1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
%c0 = arith.constant 0 : index
%2:3 = fir.box_dims %0, %c0 : (!fir.box<!fir.array<3xi32>>, index) -> (index, index, index)
%3 = fir.shape_shift %2#0, %2#1 : (index, index) -> !fir.shapeshift<1>
%c1 = arith.constant 1 : index
fir.do_loop %arg2 = %c1 to %2#1 step %c1 unordered {
%4 = fir.array_coor %0(%3) %arg2 : (!fir.box<!fir.array<3xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32>
%5 = fir.array_coor %a(%3) %arg2 : (!fir.box<!fir.heap<!fir.array<?xi32>>>, !fir.shapeshift<1>, index) -> !fir.ref<i32>
%6 = fir.load %4 : !fir.ref<i32>
%7 = fir.load %5 : !fir.ref<i32>
// CHECK: fir.load %{{.*}} {tbaa = [#[[GLOBAL_A_TAG]]]} : !fir.ref<i32>
%8 = arith.addi %6, %7 : i32
fir.store %8 to %4 : !fir.ref<i32>
}
omp.yield(%arg0 : !fir.ref<!fir.box<!fir.array<3xi32>>>)
} cleanup {
^bb0(%arg0: !fir.ref<!fir.box<!fir.array<3xi32>>>):
%0 = fir.load %arg0 : !fir.ref<!fir.box<!fir.array<3xi32>>>
%1 = fir.box_addr %0 : (!fir.box<!fir.array<3xi32>>) -> !fir.ref<!fir.array<3xi32>>
%2 = fir.convert %1 : (!fir.ref<!fir.array<3xi32>>) -> i64
%c0_i64 = arith.constant 0 : i64
%3 = arith.cmpi ne, %2, %c0_i64 : i64
fir.if %3 {
%4 = fir.convert %1 : (!fir.ref<!fir.array<3xi32>>) -> !fir.heap<!fir.array<3xi32>>
fir.freemem %4 : !fir.heap<!fir.array<3xi32>>
}
omp.yield
}
Loading