Skip to content

[flang] Add flags controlling whether to run the fir alias tags pass #68595

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 15 commits 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
3 changes: 3 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -6247,6 +6247,9 @@ defm stack_arrays : BoolOptionWithoutMarshalling<"f", "stack-arrays",
defm loop_versioning : BoolOptionWithoutMarshalling<"f", "version-loops-for-stride",
PosFlag<SetTrue, [], [ClangOption], "Create unit-strided versions of loops">,
NegFlag<SetFalse, [], [ClangOption], "Do not create unit-strided loops (default)">>;
defm alias_analysis : BoolOptionWithoutMarshalling<"f", "alias-analysis",
PosFlag<SetTrue, [], [], "Pass alias information on to LLVM (default when optimizing for speed)">,
NegFlag<SetFalse, [], [], "Do not pass alias information on to LLVM (default for unoptimized builds)">>;
} // let Visibility = [FC1Option, FlangOption]

def J : JoinedOrSeparate<["-"], "J">,
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/Driver/ToolChains/Flang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,9 @@ void Flang::addCodegenOptions(const ArgList &Args,
Args.AddAllArgs(CmdArgs, {options::OPT_flang_experimental_hlfir,
options::OPT_flang_experimental_polymorphism,
options::OPT_fno_ppc_native_vec_elem_order,
options::OPT_fppc_native_vec_elem_order});
options::OPT_fppc_native_vec_elem_order,
options::OPT_falias_analysis,
options::OPT_fno_alias_analysis});
}

void Flang::addPicOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
Expand Down
1 change: 1 addition & 0 deletions flang/include/flang/Frontend/CodeGenOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ CODEGENOPT(PrepareForThinLTO , 1, 0) ///< Set when -flto=thin is enabled on the
///< compile step.
CODEGENOPT(StackArrays, 1, 0) ///< -fstack-arrays (enable the stack-arrays pass)
CODEGENOPT(LoopVersioning, 1, 0) ///< Enable loop versioning.
CODEGENOPT(AliasAnalysis, 1, 0) ///< Enable alias analysis pass

CODEGENOPT(Underscoring, 1, 1)
ENUM_CODEGENOPT(RelocationModel, llvm::Reloc::Model, 3, llvm::Reloc::PIC_) ///< Name of the relocation model to use.
Expand Down
104 changes: 104 additions & 0 deletions flang/include/flang/Optimizer/Analysis/TBAAForest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//===-- TBAAForest.h - A TBAA tree for each function -----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef FORTRAN_OPTIMIZER_ANALYSIS_TBAA_FOREST_H
#define FORTRAN_OPTIMIZER_ANALYSIS_TBAA_FOREST_H

#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/IR/MLIRContext.h"
#include "llvm/ADT/DenseMap.h"
#include <string>

namespace fir {

//===----------------------------------------------------------------------===//
// TBAATree
//===----------------------------------------------------------------------===//
/// Per-function TBAA tree. Each tree contains branches for data (of various
/// kinds) and descriptor access
struct TBAATree {
//===----------------------------------------------------------------------===//
// TBAAForrest::TBAATree::SubtreeState
//===----------------------------------------------------------------------===//
/// This contains a TBAA subtree based on some parent. New tags can be added
/// under the parent using getTag.
class SubtreeState {
friend TBAATree; // only allow construction by TBAATree
public:
SubtreeState() = delete;
SubtreeState(const SubtreeState &) = delete;
SubtreeState(SubtreeState &&) = default;

mlir::LLVM::TBAATagAttr getTag(llvm::StringRef uniqueId) const;

private:
SubtreeState(mlir::MLIRContext *ctx, std::string name,
mlir::LLVM::TBAANodeAttr grandParent)
: parentId{std::move(name)}, context(ctx) {
parent = mlir::LLVM::TBAATypeDescriptorAttr::get(
context, parentId, mlir::LLVM::TBAAMemberAttr::get(grandParent, 0));
}

const std::string parentId;
mlir::MLIRContext *const context;
mlir::LLVM::TBAATypeDescriptorAttr parent;
llvm::DenseMap<llvm::StringRef, mlir::LLVM::TBAATagAttr> tagDedup;
};

SubtreeState globalDataTree;
SubtreeState allocatedDataTree;
SubtreeState dummyArgDataTree;
mlir::LLVM::TBAATypeDescriptorAttr anyAccessDesc;
mlir::LLVM::TBAATypeDescriptorAttr boxMemberTypeDesc;
mlir::LLVM::TBAATypeDescriptorAttr anyDataTypeDesc;

static TBAATree buildTree(mlir::StringAttr functionName);

private:
TBAATree(mlir::LLVM::TBAATypeDescriptorAttr anyAccess,
mlir::LLVM::TBAATypeDescriptorAttr dataRoot,
mlir::LLVM::TBAATypeDescriptorAttr boxMemberTypeDesc);
};

//===----------------------------------------------------------------------===//
// TBAAForrest
//===----------------------------------------------------------------------===//
/// Collection of TBAATrees, usually indexed by function (so that each function
/// 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::LLVM::LLVMFuncOp func) {
return getFuncTree(func.getSymNameAttr());
}

private:
const TBAATree &getFuncTree(mlir::StringAttr symName) {
if (!separatePerFunction)
symName = mlir::StringAttr::get(symName.getContext(), "");
if (!trees.contains(symName))
trees.insert({symName, TBAATree::buildTree(symName)});
return trees.at(symName);
}

// Should each function use a different tree?
const bool separatePerFunction;
// TBAA tree per function
llvm::DenseMap<mlir::StringAttr, TBAATree> trees;
};

} // namespace fir

#endif // FORTRAN_OPTIMIZER_ANALYSIS_TBAA_FOREST_H
3 changes: 3 additions & 0 deletions flang/include/flang/Optimizer/CodeGen/CodeGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ struct FIRToLLVMPassOptions {

// Generate TBAA information for FIR types and memory accessing operations.
bool applyTBAA = false;

// Force the usage of a unified tbaa tree in TBAABuilder.
bool forceUnifiedTBAATree = false;
};

/// Convert FIR to the LLVM IR dialect with default options.
Expand Down
49 changes: 18 additions & 31 deletions flang/include/flang/Optimizer/CodeGen/TBAABuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
#ifndef FORTRAN_OPTIMIZER_CODEGEN_TBAABUILDER_H
#define FORTRAN_OPTIMIZER_CODEGEN_TBAABUILDER_H

#include "flang/Optimizer/Analysis/TBAAForest.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/IR/BuiltinAttributes.h"

namespace fir {

Expand All @@ -25,9 +25,9 @@ namespace fir {
//
// TBAA type information is represented with LLVM::MetadataOp operation
// with specific symbol name `TBAABuilder::tbaaMetaOpName`. The basic
// TBAA tree used for Flang consists of the following nodes:
// TBAA trees used for Flang consists of the following nodes:
// llvm.metadata @__flang_tbaa {
// llvm.tbaa_root @root_0 {id = "Flang Type TBAA Root"}
// llvm.tbaa_root @root_0 {id = "Flang Type TBAA Function Root funcName"}
// llvm.tbaa_type_desc @type_desc_1 {id = "any access",
// members = {<@root_0, 0>}}
// llvm.tbaa_type_desc @type_desc_2 {id = "any data access",
Expand Down Expand Up @@ -162,9 +162,14 @@ namespace fir {
// Given the storage association, all non-box accesses are represented
// with the conservative data access tag:
// < `<any data access>`, `<any data access>`, 0 >

// additional tags are added in flang/Optimizer/Transforms/AddAliasTags.cpp
// (before CodeGen)
class TBAABuilder {
public:
TBAABuilder(mlir::MLIRContext *context, bool applyTBAA);
/// if forceUnifiedTree is true, functions will not have different TBAA trees
TBAABuilder(mlir::MLIRContext *context, bool applyTBAA,
bool forceUnifiedTree = false);
TBAABuilder(TBAABuilder const &) = delete;
TBAABuilder &operator=(TBAABuilder const &) = delete;

Expand All @@ -184,56 +189,36 @@ class TBAABuilder {

// Returns TBAATagAttr representing access tag:
// < <descriptor member>, <descriptor member>, 0 >
mlir::LLVM::TBAATagAttr getAnyBoxAccessTag();
mlir::LLVM::TBAATagAttr getAnyBoxAccessTag(mlir::LLVM::LLVMFuncOp func);
// Returns TBAATagAttr representing access tag:
// < <any data access>, <any data access>, 0 >
mlir::LLVM::TBAATagAttr getAnyDataAccessTag();
mlir::LLVM::TBAATagAttr getAnyDataAccessTag(mlir::LLVM::LLVMFuncOp func);
// Returns TBAATagAttr representing access tag:
// < <any access>, <any access>, 0 >
mlir::LLVM::TBAATagAttr getAnyAccessTag();
mlir::LLVM::TBAATagAttr getAnyAccessTag(mlir::LLVM::LLVMFuncOp func);

// Returns TBAATagAttr representing access tag described by the base and
// access FIR types and the LLVM::GepOp representing the access in terms of
// the FIR types converted to LLVM types. The base type must be derivative of
// fir::BaseBoxType.
mlir::LLVM::TBAATagAttr getBoxAccessTag(mlir::Type baseFIRType,
mlir::Type accessFIRType,
mlir::LLVM::GEPOp gep);
mlir::LLVM::GEPOp gep,
mlir::LLVM::LLVMFuncOp func);

// Returns TBAATagAttr representing access tag described by the base and
// access FIR types and the LLVM::GepOp representing the access in terms of
// the FIR types converted to LLVM types. The FIR types must describe the
// "data" access, i.e. not an access of any box/descriptor member.
mlir::LLVM::TBAATagAttr getDataAccessTag(mlir::Type baseFIRType,
mlir::Type accessFIRType,
mlir::LLVM::GEPOp gep);
mlir::LLVM::GEPOp gep,
mlir::LLVM::LLVMFuncOp func);

// Set to true, if TBAA builder is active, otherwise, all public
// methods are no-ops.
bool enableTBAA;

// LLVM::TBAARootAttr identifying Flang's TBAA root.
mlir::LLVM::TBAARootAttr flangTBAARoot;
// Identity string for Flang's TBAA root.
static constexpr llvm::StringRef flangTBAARootId = "Flang Type TBAA Root";

// LLVM::TBAATypeDescriptorAttr identifying "any access".
mlir::LLVM::TBAATypeDescriptorAttr anyAccessTypeDesc;
// Identity string for "any access" type descriptor.
static constexpr llvm::StringRef anyAccessTypeDescId = "any access";

// LLVM::TBAATypeDescriptorAttr identifying "any data access" (i.e. non-box
// memory access).
mlir::LLVM::TBAATypeDescriptorAttr anyDataAccessTypeDesc;
// Identity string for "any data access" type descriptor.
static constexpr llvm::StringRef anyDataAccessTypeDescId = "any data access";

// LLVM::TBAATypeDescriptorAttr identifying "descriptor member" access, i.e.
// any access within the bounds of a box/descriptor.
mlir::LLVM::TBAATypeDescriptorAttr boxMemberTypeDesc;
// Identity string for "descriptor member" type descriptor.
static constexpr llvm::StringRef boxMemberTypeDescId = "descriptor member";

// Number of attached TBAA tags (used for debugging).
unsigned tagAttachmentCounter = 0;

Expand All @@ -247,6 +232,8 @@ class TBAABuilder {
std::tuple<mlir::LLVM::TBAANodeAttr, mlir::LLVM::TBAANodeAttr, int64_t>,
mlir::LLVM::TBAATagAttr>
tagsMap;

TBAAForrest trees;
};

} // namespace fir
Expand Down
3 changes: 2 additions & 1 deletion flang/include/flang/Optimizer/CodeGen/TypeConverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ namespace fir {
/// This converts FIR types to LLVM types (for now)
class LLVMTypeConverter : public mlir::LLVMTypeConverter {
public:
LLVMTypeConverter(mlir::ModuleOp module, bool applyTBAA);
LLVMTypeConverter(mlir::ModuleOp module, bool applyTBAA,
bool forceUnifiedTBAATree);

// i32 is used here because LLVM wants i32 constants when indexing into struct
// types. Indexing into other aggregate types is more flexible.
Expand Down
4 changes: 4 additions & 0 deletions flang/include/flang/Optimizer/Dialect/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ set(LLVM_TARGET_DEFINITIONS FortranVariableInterface.td)
mlir_tablegen(FortranVariableInterface.h.inc -gen-op-interface-decls)
mlir_tablegen(FortranVariableInterface.cpp.inc -gen-op-interface-defs)

set(LLVM_TARGET_DEFINITIONS FirAliasTagOpInterface.td)
mlir_tablegen(FirAliasTagOpInterface.h.inc -gen-op-interface-decls)
mlir_tablegen(FirAliasTagOpInterface.cpp.inc -gen-op-interface-defs)

set(LLVM_TARGET_DEFINITIONS CanonicalizationPatterns.td)
mlir_tablegen(CanonicalizationPatterns.inc -gen-rewriters)
add_public_tablegen_target(CanonicalizationPatternsIncGen)
Expand Down
4 changes: 3 additions & 1 deletion flang/include/flang/Optimizer/Dialect/FIRDialect.td
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ def fir_Dialect : Dialect {
let dependentDialects = [
// Arith dialect provides FastMathFlagsAttr
// supported by some FIR operations.
"arith::ArithDialect"
"arith::ArithDialect",
// TBAA Tag types
"LLVM::LLVMDialect"
];
}

Expand Down
1 change: 1 addition & 0 deletions flang/include/flang/Optimizer/Dialect/FIROps.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "flang/Optimizer/Dialect/FIRAttr.h"
#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Optimizer/Dialect/FirAliasTagOpInterface.h"
#include "flang/Optimizer/Dialect/FortranVariableInterface.h"
#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
Expand Down
17 changes: 12 additions & 5 deletions flang/include/flang/Optimizer/Dialect/FIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@

include "mlir/Dialect/Arith/IR/ArithBase.td"
include "mlir/Dialect/Arith/IR/ArithOpsInterfaces.td"
include "mlir/Dialect/LLVMIR/LLVMAttrDefs.td"
include "flang/Optimizer/Dialect/FIRDialect.td"
include "flang/Optimizer/Dialect/FIRTypes.td"
include "flang/Optimizer/Dialect/FIRAttr.td"
include "flang/Optimizer/Dialect/FortranVariableInterface.td"
include "flang/Optimizer/Dialect/FirAliasTagOpInterface.td"
include "mlir/IR/BuiltinAttributes.td"

// Base class for FIR operations.
Expand Down Expand Up @@ -258,7 +260,7 @@ def fir_FreeMemOp : fir_Op<"freemem", [MemoryEffects<[MemFree]>]> {
let assemblyFormat = "$heapref attr-dict `:` qualified(type($heapref))";
}

def fir_LoadOp : fir_OneResultOp<"load", []> {
def fir_LoadOp : fir_OneResultOp<"load", [FirAliasTagOpInterface]> {
let summary = "load a value from a memory reference";
let description = [{
Load a value from a memory reference into an ssa-value (virtual register).
Expand All @@ -274,9 +276,11 @@ def fir_LoadOp : fir_OneResultOp<"load", []> {
or null.
}];

let arguments = (ins Arg<AnyReferenceLike, "", [MemRead]>:$memref);
let arguments = (ins Arg<AnyReferenceLike, "", [MemRead]>:$memref,
OptionalAttr<LLVM_TBAATagArrayAttr>:$tbaa);

let builders = [OpBuilder<(ins "mlir::Value":$refVal)>];
let builders = [OpBuilder<(ins "mlir::Value":$refVal)>,
OpBuilder<(ins "mlir::Type":$resTy, "mlir::Value":$refVal)>];

let hasCustomAssemblyFormat = 1;

Expand All @@ -285,7 +289,7 @@ def fir_LoadOp : fir_OneResultOp<"load", []> {
}];
}

def fir_StoreOp : fir_Op<"store", []> {
def fir_StoreOp : fir_Op<"store", [FirAliasTagOpInterface]> {
let summary = "store an SSA-value to a memory location";

let description = [{
Expand All @@ -305,7 +309,10 @@ def fir_StoreOp : fir_Op<"store", []> {
}];

let arguments = (ins AnyType:$value,
Arg<AnyReferenceLike, "", [MemWrite]>:$memref);
Arg<AnyReferenceLike, "", [MemWrite]>:$memref,
OptionalAttr<LLVM_TBAATagArrayAttr>:$tbaa);

let builders = [OpBuilder<(ins "mlir::Value":$value, "mlir::Value":$memref)>];

let hasCustomAssemblyFormat = 1;
let hasVerifier = 1;
Expand Down
27 changes: 27 additions & 0 deletions flang/include/flang/Optimizer/Dialect/FirAliasTagOpInterface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//===- FirAliasTagOpInterface.h ---------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains an interface for adding alias analysis information to
// loads and stores
//
//===----------------------------------------------------------------------===//

#ifndef FORTRAN_OPTIMIZER_DIALECT_FIR_ALIAS_TAG_OP_INTERFACE_H
#define FORTRAN_OPTIMIZER_DIALECT_FIR_ALIAS_TAG_OP_INTERFACE_H

#include "mlir/IR/OpDefinition.h"
#include "mlir/IR/Operation.h"
#include "mlir/Support/LogicalResult.h"

namespace fir::detail {
mlir::LogicalResult verifyFirAliasTagOpInterface(mlir::Operation *op);
} // namespace fir::detail

#include "flang/Optimizer/Dialect/FirAliasTagOpInterface.h.inc"

#endif // FORTRAN_OPTIMIZER_DIALECT_FIR_ALIAS_TAG_OP_INTERFACE_H
Loading