Skip to content

Commit 2f66c89

Browse files
committed
[mlir] Support TBAA metadata in LLVMIR dialect.
This change introduces new LLVMIR dialect operations to represent TBAA root, type descriptor and access tag metadata nodes. For the purpose of importing TBAA metadata from LLVM IR it only supports the current version of TBAA format described in https://llvm.org/docs/LangRef.html#tbaa-metadata (i.e. size-aware representation introduced in D41501 is not supported). TBAA attribute support is only added for LLVM::LoadOp and LLVM::StoreOp. Support for intrinsics operations (e.g. LLVM::MemcpyOp) may be added later. The TBAA attribute is represented as an array of access tags, though, LLVM IR supports only single access tag per memory accessing instruction. I implemented it as an array anticipating similar support in LLVM IR to combine TBAA graphs with different roots for Flang - one of the options described in https://docs.google.com/document/d/16kKZVmI585wth01VSaJAqZMZpoX68rcdBmgfj0kNAt0/edit#heading=h.jzzheaz9vqac It should be easy to restrict MLIR operation to a single access tag, if we end up using a different approach for Flang. Differential Revision: https://reviews.llvm.org/D140768
1 parent 1b12d7d commit 2f66c89

File tree

13 files changed

+1333
-7
lines changed

13 files changed

+1333
-7
lines changed

mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ def LLVM_Dialect : Dialect {
5252
static StringRef getNoUndefAttrName() { return "llvm.noundef"; }
5353
static StringRef getSExtAttrName() { return "llvm.signext"; }
5454
static StringRef getZExtAttrName() { return "llvm.zeroext"; }
55+
static StringRef getTBAAAttrName() { return "llvm.tbaa"; }
5556

5657
/// Verifies if the attribute is a well-formed value for "llvm.struct_attrs"
5758
static LogicalResult verifyStructAttr(

mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td

Lines changed: 154 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,10 @@ class MemoryOpWithAlignmentAndAttributes : MemoryOpWithAlignmentBase {
205205
code setAliasScopeMetadataCode = [{
206206
moduleTranslation.setAliasScopeMetadata(op, inst);
207207
}];
208+
209+
code setTBAAMetadataCode = [{
210+
moduleTranslation.setTBAAMetadata(op, inst);
211+
}];
208212
}
209213

210214
// Memory-related operations.
@@ -360,6 +364,7 @@ def LLVM_LoadOp : LLVM_Op<"load">, MemoryOpWithAlignmentAndAttributes {
360364
# setNonTemporalMetadataCode
361365
# setAccessGroupsMetadataCode
362366
# setAliasScopeMetadataCode
367+
# setTBAAMetadataCode
363368
# [{
364369
$res = inst;
365370
}];
@@ -397,7 +402,8 @@ def LLVM_StoreOp : LLVM_Op<"store">, MemoryOpWithAlignmentAndAttributes {
397402
}] # setAlignmentCode
398403
# setNonTemporalMetadataCode
399404
# setAccessGroupsMetadataCode
400-
# setAliasScopeMetadataCode;
405+
# setAliasScopeMetadataCode
406+
# setTBAAMetadataCode;
401407
// FIXME: Import attributes.
402408
string mlirBuilder = [{
403409
$_op = $_builder.create<LLVM::StoreOp>($_location, $value, $addr);
@@ -992,6 +998,7 @@ def LLVM_MetadataOp : LLVM_Op<"metadata", [
992998
}];
993999
let regions = (region SizedRegion<1>:$body);
9941000
let assemblyFormat = "$sym_name attr-dict-with-keyword $body";
1001+
let hasRegionVerifier = 1;
9951002
}
9961003

9971004
def LLVM_AliasScopeDomainMetadataOp : LLVM_Op<"alias_scope_domain", [
@@ -1074,6 +1081,152 @@ def LLVM_AccessGroupMetadataOp : LLVM_Op<"access_group", [
10741081
let assemblyFormat = "$sym_name attr-dict";
10751082
}
10761083

1084+
def LLVM_TBAARootMetadataOp : LLVM_Op<"tbaa_root", [
1085+
HasParent<"MetadataOp">, Symbol
1086+
]> {
1087+
let arguments = (ins
1088+
SymbolNameAttr:$sym_name,
1089+
StrAttr:$identity
1090+
);
1091+
let summary = "LLVM dialect TBAA root node metadata.";
1092+
let description = [{
1093+
Defines a TBAA root node.
1094+
1095+
Example:
1096+
llvm.metadata @tbaa {
1097+
llvm.tbaa_root @tbaa_root_0 {identity = "Simple C/C++ TBAA"}
1098+
llvm.return
1099+
}
1100+
1101+
See the following link for more details:
1102+
https://llvm.org/docs/LangRef.html#tbaa-metadata
1103+
}];
1104+
let assemblyFormat = [{
1105+
$sym_name ` ` `{` `id` `=` $identity `}` attr-dict
1106+
}];
1107+
let hasVerifier = 1;
1108+
}
1109+
1110+
def LLVM_TBAATypeDescriptorOp : LLVM_Op<"tbaa_type_desc", [
1111+
HasParent<"MetadataOp">, Symbol
1112+
]> {
1113+
let arguments = (ins
1114+
SymbolNameAttr:$sym_name,
1115+
OptionalAttr<StrAttr>:$identity,
1116+
FlatSymbolRefArrayAttr:$members,
1117+
DenseI64ArrayAttr:$offsets
1118+
);
1119+
let summary = "LLVM dialect TBAA node describing a type.";
1120+
let description = [{
1121+
Defines a TBAA node describing a type.
1122+
1123+
Example:
1124+
llvm.metadata @tbaa {
1125+
llvm.tbaa_root @tbaa_root_0 {identity = "Simple C/C++ TBAA"}
1126+
llvm.tbaa_type_desc @tbaa_type_desc_1 {
1127+
identity = "omnipotent char",
1128+
members = [@tbaa_root_0],
1129+
offsets = array<i64: 0>
1130+
}
1131+
llvm.tbaa_type_desc @tbaa_type_desc_2 {
1132+
identity = "long long",
1133+
members = [@tbaa_type_desc_1],
1134+
offsets = array<i64: 0>
1135+
}
1136+
llvm.tbaa_type_desc @tbaa_type_desc_3 {
1137+
identity = "agg2_t",
1138+
members = [@tbaa_type_desc_2, @tbaa_type_desc_2],
1139+
offsets = array<i64: 0, 8>
1140+
}
1141+
llvm.tbaa_type_desc @tbaa_type_desc_5 {
1142+
identity = "int",
1143+
members = [@tbaa_type_desc_1],
1144+
offsets = array<i64: 0>
1145+
}
1146+
llvm.tbaa_type_desc @tbaa_type_desc_6 {
1147+
identity = "agg1_t",
1148+
members = [@tbaa_type_desc_5, @tbaa_type_desc_5],
1149+
offsets = array<i64: 0, 4>
1150+
}
1151+
llvm.return
1152+
}
1153+
1154+
See the following link for more details:
1155+
https://llvm.org/docs/LangRef.html#tbaa-metadata
1156+
}];
1157+
1158+
// Interleave member types and offsets for better matching
1159+
// LLVM IR text representation.
1160+
let assemblyFormat = [{
1161+
$sym_name ` ` `{`
1162+
( `id` `=` $identity^ )? `,`
1163+
`members` `=` `{` custom<TBAAMembers>($members, $offsets) `}`
1164+
`}` attr-dict
1165+
}];
1166+
let hasVerifier = 1;
1167+
}
1168+
1169+
def LLVM_TBAATagOp : LLVM_Op<"tbaa_tag", [
1170+
HasParent<"MetadataOp">, Symbol
1171+
]> {
1172+
let arguments = (ins
1173+
SymbolNameAttr:$sym_name,
1174+
FlatSymbolRefAttr:$base_type,
1175+
FlatSymbolRefAttr:$access_type,
1176+
I64Attr:$offset,
1177+
UnitAttr:$constant
1178+
);
1179+
let summary = "LLVM dialect TBAA node describing a memory access.";
1180+
let description = [{
1181+
Defines a TBAA node describing a memory access.
1182+
1183+
Example:
1184+
llvm.metadata @tbaa {
1185+
llvm.tbaa_root @tbaa_root_0 {identity = "Simple C/C++ TBAA"}
1186+
llvm.tbaa_type_desc @tbaa_type_desc_1 {
1187+
identity = "omnipotent char",
1188+
members = [@tbaa_root_0],
1189+
offsets = array<i64: 0>
1190+
}
1191+
llvm.tbaa_type_desc @tbaa_type_desc_2 {
1192+
identity = "long long",
1193+
members = [@tbaa_type_desc_1],
1194+
offsets = array<i64: 0>
1195+
}
1196+
llvm.tbaa_type_desc @tbaa_type_desc_3 {
1197+
identity = "agg2_t",
1198+
members = [@tbaa_type_desc_2, @tbaa_type_desc_2],
1199+
offsets = array<i64: 0, 8>
1200+
}
1201+
llvm.tbaa_tag @tbaa_tag_4 {
1202+
access_type = @tbaa_type_desc_2,
1203+
base_type = @tbaa_type_desc_3,
1204+
offset = 8 : i64
1205+
}
1206+
llvm.tbaa_type_desc @tbaa_type_desc_5 {
1207+
identity = "int",
1208+
members = [@tbaa_type_desc_1],
1209+
offsets = array<i64: 0>
1210+
}
1211+
llvm.tbaa_type_desc @tbaa_type_desc_6 {
1212+
identity = "agg1_t",
1213+
members = [@tbaa_type_desc_5, @tbaa_type_desc_5],
1214+
offsets = array<i64: 0, 4>
1215+
}
1216+
llvm.tbaa_tag @tbaa_tag_7 {
1217+
access_type = @tbaa_type_desc_5,
1218+
base_type = @tbaa_type_desc_6,
1219+
offset = 0 : i64
1220+
}
1221+
llvm.return
1222+
}
1223+
1224+
See the following link for more details:
1225+
https://llvm.org/docs/LangRef.html#tbaa-metadata
1226+
}];
1227+
let assemblyFormat = "$sym_name attr-dict";
1228+
}
1229+
10771230
def LLVM_GlobalOp : LLVM_Op<"mlir.global",
10781231
[IsolatedFromAbove, SingleBlockImplicitTerminator<"ReturnOp">, Symbol]> {
10791232
let arguments = (ins

mlir/include/mlir/Target/LLVMIR/ModuleImport.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,17 @@ class ModuleImport {
149149
/// implement the fastmath interface.
150150
void setFastmathFlagsAttr(llvm::Instruction *inst, Operation *op) const;
151151

152+
/// Converts LLVM metadata to corresponding MLIR representation,
153+
/// e.g. metadata nodes referenced via !tbaa are converted to
154+
/// TBAA operations hosted inside a MetadataOp.
155+
LogicalResult convertMetadata();
156+
157+
/// Returns SymbolRefAttr representing TBAA metadata `node`
158+
/// in `tbaaMapping`.
159+
SymbolRefAttr lookupTBAAAttr(const llvm::MDNode *node) {
160+
return tbaaMapping.lookup(node);
161+
}
162+
152163
private:
153164
/// Clears the block and value mapping before processing a new region.
154165
void clearBlockAndValueMapping() {
@@ -219,6 +230,25 @@ class ModuleImport {
219230
/// them fails. All operations are inserted at the start of the current
220231
/// function entry block.
221232
FailureOr<Value> convertConstantExpr(llvm::Constant *constant);
233+
/// Returns symbol name to be used for MetadataOp containing
234+
/// TBAA metadata operations. It must not conflict with the user
235+
/// name space.
236+
StringRef getTBAAMetadataOpName() const { return "__tbaa"; }
237+
/// Returns a terminated MetadataOp into which TBAA metadata
238+
/// operations can be placed. The MetadataOp is created
239+
/// on the first invocation of this function.
240+
MetadataOp getTBAAMetadataOp();
241+
/// Performs conversion of LLVM TBAA metadata starting from
242+
/// `node`. On exit from this function all nodes reachable
243+
/// from `node` are converted, and tbaaMapping map is updated
244+
/// (unless all dependencies have been converted by a previous
245+
/// invocation of this function).
246+
LogicalResult processTBAAMetadata(const llvm::MDNode *node);
247+
/// Returns unique string name of a symbol that may be used
248+
/// for a TBAA metadata operation. The name will contain
249+
/// the provided `basename` and will be uniqued via
250+
/// tbaaNodeCounter (see below).
251+
std::string getNewTBAANodeName(StringRef basename);
222252

223253
/// Builder pointing at where the next instruction should be generated.
224254
OpBuilder builder;
@@ -251,6 +281,16 @@ class ModuleImport {
251281
LLVM::TypeFromLLVMIRTranslator typeTranslator;
252282
/// Stateful debug information importer.
253283
std::unique_ptr<detail::DebugImporter> debugImporter;
284+
/// A terminated MetadataOp where TBAA metadata operations
285+
/// can be inserted.
286+
MetadataOp tbaaMetadataOp{};
287+
/// Mapping between LLVM TBAA metadata nodes and symbol references
288+
/// to the LLVMIR dialect TBAA operations corresponding to these
289+
/// nodes.
290+
DenseMap<const llvm::MDNode *, SymbolRefAttr> tbaaMapping;
291+
/// A counter to be used as a unique suffix for symbols
292+
/// defined by TBAA operations.
293+
unsigned tbaaNodeCounter = 0;
254294
};
255295

256296
} // namespace LLVM

mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ class ModuleTranslation {
148148
// Sets LLVM metadata for memory operations that have alias scope information.
149149
void setAliasScopeMetadata(Operation *op, llvm::Instruction *inst);
150150

151+
/// Sets LLVM TBAA metadata for memory operations that have
152+
/// TBAA attributes.
153+
void setTBAAMetadata(Operation *op, llvm::Instruction *inst);
154+
151155
/// Converts the type from MLIR LLVM dialect to LLVM.
152156
llvm::Type *convertType(Type type);
153157

@@ -291,6 +295,14 @@ class ModuleTranslation {
291295
/// metadata nodes for them and their domains.
292296
LogicalResult createAliasScopeMetadata();
293297

298+
/// Returns the LLVM metadata corresponding to a reference to an mlir LLVM
299+
/// dialect TBAATagOp operation.
300+
llvm::MDNode *getTBAANode(Operation &memOp, SymbolRefAttr tagRef) const;
301+
302+
/// Process tbaa LLVM Metadata operations and create LLVM
303+
/// metadata nodes for them.
304+
LogicalResult createTBAAMetadata();
305+
294306
/// Translates dialect attributes attached to the given operation.
295307
LogicalResult convertDialectAttributes(Operation *op);
296308

@@ -333,10 +345,14 @@ class ModuleTranslation {
333345
/// attribute.
334346
DenseMap<Attribute, llvm::MDNode *> loopOptionsMetadataMapping;
335347

336-
/// Mapping from an access scope metadata operation to its LLVM metadata.
348+
/// Mapping from an alias scope metadata operation to its LLVM metadata.
337349
/// This map is populated on module entry.
338350
DenseMap<Operation *, llvm::MDNode *> aliasScopeMetadataMapping;
339351

352+
/// Mapping from a tbaa metadata operation to its LLVM metadata.
353+
/// This map is populated on module entry.
354+
DenseMap<const Operation *, llvm::MDNode *> tbaaMetadataMapping;
355+
340356
/// Stack of user-specified state elements, useful when translating operations
341357
/// with regions.
342358
SmallVector<std::unique_ptr<StackFrame>> stack;

0 commit comments

Comments
 (0)