diff --git a/flang/include/flang/Optimizer/CodeGen/TBAABuilder.h b/flang/include/flang/Optimizer/CodeGen/TBAABuilder.h --- a/flang/include/flang/Optimizer/CodeGen/TBAABuilder.h +++ b/flang/include/flang/Optimizer/CodeGen/TBAABuilder.h @@ -164,7 +164,7 @@ // < ``, ``, 0 > class TBAABuilder { public: - TBAABuilder(mlir::ModuleOp module, bool applyTBAA); + TBAABuilder(mlir::MLIRContext *context, bool applyTBAA); TBAABuilder(TBAABuilder const &) = delete; TBAABuilder &operator=(TBAABuilder const &) = delete; @@ -175,95 +175,74 @@ mlir::LLVM::GEPOp gep); private: - // Return unique string name based on `basename`. - std::string getNewTBAANodeName(llvm::StringRef basename); - - // Find or create TBAATagOp operation (TBAA access tag) with the specified - // components and return the symbol it defines. - mlir::SymbolRefAttr getAccessTag(mlir::SymbolRefAttr baseTypeDesc, - mlir::SymbolRefAttr accessTypeDesc, - int64_t offset); - // Returns symbol of TBAATagOp representing access tag: + // Find or create TBAATagAttr attribute (TBAA access tag) with the specified + // components and return it. + mlir::LLVM::TBAATagAttr + getAccessTag(mlir::LLVM::TBAATypeDescriptorAttr baseTypeDesc, + mlir::LLVM::TBAATypeDescriptorAttr accessTypeDesc, + int64_t offset); + + // Returns TBAATagAttr representing access tag: // < , , 0 > - mlir::SymbolRefAttr getAnyBoxAccessTag(); - // Returns symbol of TBAATagOp representing access tag: + mlir::LLVM::TBAATagAttr getAnyBoxAccessTag(); + // Returns TBAATagAttr representing access tag: // < , , 0 > - mlir::SymbolRefAttr getAnyDataAccessTag(); - - // Returns symbol of TBAATagOp 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::SymbolRefAttr getBoxAccessTag(mlir::Type baseFIRType, - mlir::Type accessFIRType, - mlir::LLVM::GEPOp gep); - - // Returns symbol of TBAATagOp 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::SymbolRefAttr getDataAccessTag(mlir::Type baseFIRType, - mlir::Type accessFIRType, - mlir::LLVM::GEPOp gep); + mlir::LLVM::TBAATagAttr getAnyDataAccessTag(); + + // 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); + + // 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); // Set to true, if TBAA builder is active, otherwise, all public // methods are no-ops. bool enableTBAA; - // LLVM::MetadataOp holding the TBAA operations. - mlir::LLVM::MetadataOp tbaaMetaOp; - // Symbol name of tbaaMetaOp. - static constexpr llvm::StringRef tbaaMetaOpName = "__flang_tbaa"; - - // Base names for TBAA operations: - // TBAARootMetadataOp: - static constexpr llvm::StringRef kRootSymBasename = "root"; - // TBAATypeDescriptorOp: - static constexpr llvm::StringRef kTypeDescSymBasename = "type_desc"; - // TBAATagOp: - static constexpr llvm::StringRef kTagSymBasename = "tag"; - - // Symbol defined by the LLVM::TBAARootMetadataOp identifying - // Flang's TBAA root. - mlir::SymbolRefAttr flangTBAARoot; + // 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"; - // Symbol defined by LLVM::TBAATypeDescriptorOp identifying - // "any access". - mlir::SymbolRefAttr anyAccessTypeDesc; + // LLVM::TBAATypeDescriptorAttr identifying "any access". + mlir::LLVM::TBAATypeDescriptorAttr anyAccessTypeDesc; // Identity string for "any access" type descriptor. static constexpr llvm::StringRef anyAccessTypeDescId = "any access"; - // Symbol defined by LLVM::TBAATypeDescriptorOp identifying - // "any data access" (i.e. non-box memory access). - mlir::SymbolRefAttr anyDataAccessTypeDesc; + // 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"; - // Symbol defined by LLVM::TBAATypeDescriptorOp identifying - // "descriptor member" access, i.e. any access within the bounds - // of a box/descriptor. - mlir::SymbolRefAttr boxMemberTypeDesc; + // 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"; - // Counter for unique naming of TBAA operations' symbols. - unsigned tbaaNodeCounter = 0; - // Number of attached TBAA tags (used for debugging). unsigned tagAttachmentCounter = 0; - // Mapping from a FIR type to the symbol defined by the corresponding - // TBAATypeDescriptorOp. It must be populated during the type conversion. - // Currently unused. - llvm::DenseMap typeDescMap; + // Mapping from a FIR type to the corresponding TBAATypeDescriptorAttr. It + // must be populated during the type conversion. Currently unused. + llvm::DenseMap typeDescMap; // Each TBAA tag is a tuple of . - // This map holds TBAATagOp symbol for each unique tuple. - llvm::DenseMap, - mlir::SymbolRefAttr> + // This map holds a TBAATagAttr for each unique tuple. + llvm::DenseMap< + std::tuple, + mlir::LLVM::TBAATagAttr> tagsMap; }; diff --git a/flang/lib/Optimizer/CodeGen/TBAABuilder.cpp b/flang/lib/Optimizer/CodeGen/TBAABuilder.cpp --- a/flang/lib/Optimizer/CodeGen/TBAABuilder.cpp +++ b/flang/lib/Optimizer/CodeGen/TBAABuilder.cpp @@ -37,107 +37,58 @@ llvm::cl::init(kTagAttachmentUnlimited)); namespace fir { -std::string TBAABuilder::getNewTBAANodeName(llvm::StringRef basename) { - return (llvm::Twine(basename) + llvm::Twine('_') + - llvm::Twine(tbaaNodeCounter++)) - .str(); -} -TBAABuilder::TBAABuilder(mlir::ModuleOp module, bool applyTBAA) +TBAABuilder::TBAABuilder(MLIRContext *context, bool applyTBAA) : enableTBAA(applyTBAA && !disableTBAA) { if (!enableTBAA) return; - // In the usual Flang compilation flow, FIRToLLVMPass is run once, - // and the MetadataOp holding TBAA operations is created at the beginning - // of the pass. With tools like tco it is possible to invoke - // FIRToLLVMPass on already converted MLIR, so the MetadataOp - // already exists and creating a new one with the same name would - // be incorrect. If the TBAA MetadataOp is already present, - // we just disable all TBAABuilder actions (e.g. attachTBAATag() - // is a no-op). - if (llvm::any_of( - module.getBodyRegion().getOps(), - [&](auto metaOp) { return metaOp.getSymName() == tbaaMetaOpName; })) { - enableTBAA = false; - return; - } - - LLVM_DEBUG(llvm::dbgs() << "Creating TBAA MetadataOp for module '" - << module.getName().value_or("") << "'\n"); - - // Create TBAA MetadataOp with the root and basic type descriptors. - Location loc = module.getLoc(); - MLIRContext *context = module.getContext(); - OpBuilder builder(module.getBody(), module.getBody()->end()); - tbaaMetaOp = builder.create(loc, tbaaMetaOpName); - builder.setInsertionPointToStart(&tbaaMetaOp.getBody().front()); - // Root node. - auto rootOp = builder.create( - loc, getNewTBAANodeName(kRootSymBasename), flangTBAARootId); - flangTBAARoot = FlatSymbolRefAttr::get(rootOp); + flangTBAARoot = + TBAARootAttr::get(context, StringAttr::get(context, flangTBAARootId)); // Any access node. - auto anyAccessOp = builder.create( - loc, getNewTBAANodeName(kTypeDescSymBasename), - StringAttr::get(context, anyAccessTypeDescId), - ArrayAttr::get(context, flangTBAARoot), ArrayRef{0}); - anyAccessTypeDesc = FlatSymbolRefAttr::get(anyAccessOp); + anyAccessTypeDesc = TBAATypeDescriptorAttr::get( + context, anyAccessTypeDescId, TBAAMemberAttr::get(flangTBAARoot, 0)); // Any data access node. - auto anyDataAccessOp = builder.create( - loc, getNewTBAANodeName(kTypeDescSymBasename), - StringAttr::get(context, anyDataAccessTypeDescId), - ArrayAttr::get(context, anyAccessTypeDesc), ArrayRef{0}); - anyDataAccessTypeDesc = FlatSymbolRefAttr::get(anyDataAccessOp); + anyDataAccessTypeDesc = + TBAATypeDescriptorAttr::get(context, anyDataAccessTypeDescId, + TBAAMemberAttr::get(anyAccessTypeDesc, 0)); // Box member access node. - auto boxMemberOp = builder.create( - loc, getNewTBAANodeName(kTypeDescSymBasename), - StringAttr::get(context, boxMemberTypeDescId), - ArrayAttr::get(context, anyAccessTypeDesc), ArrayRef{0}); - boxMemberTypeDesc = FlatSymbolRefAttr::get(boxMemberOp); + boxMemberTypeDesc = TBAATypeDescriptorAttr::get( + context, boxMemberTypeDescId, TBAAMemberAttr::get(anyAccessTypeDesc, 0)); } -SymbolRefAttr TBAABuilder::getAccessTag(SymbolRefAttr baseTypeDesc, - SymbolRefAttr accessTypeDesc, - int64_t offset) { - SymbolRefAttr &tag = tagsMap[{baseTypeDesc, accessTypeDesc, offset}]; +TBAATagAttr TBAABuilder::getAccessTag(TBAATypeDescriptorAttr baseTypeDesc, + TBAATypeDescriptorAttr accessTypeDesc, + int64_t offset) { + TBAATagAttr &tag = tagsMap[{baseTypeDesc, accessTypeDesc, offset}]; if (tag) return tag; // Initialize new tag. - Location loc = tbaaMetaOp.getLoc(); - OpBuilder builder(&tbaaMetaOp.getBody().back(), - tbaaMetaOp.getBody().back().end()); - auto tagOp = builder.create( - loc, getNewTBAANodeName(kTagSymBasename), baseTypeDesc.getLeafReference(), - accessTypeDesc.getLeafReference(), offset); - // TBAATagOp symbols must be referenced by their fully qualified - // names, so create a path to TBAATagOp symbol. - StringAttr metaOpName = SymbolTable::getSymbolName(tbaaMetaOp); - tag = SymbolRefAttr::get(builder.getContext(), metaOpName, - FlatSymbolRefAttr::get(tagOp)); + tag = TBAATagAttr::get(baseTypeDesc, accessTypeDesc, offset); return tag; } -SymbolRefAttr TBAABuilder::getAnyBoxAccessTag() { +TBAATagAttr TBAABuilder::getAnyBoxAccessTag() { return getAccessTag(boxMemberTypeDesc, boxMemberTypeDesc, /*offset=*/0); } -SymbolRefAttr TBAABuilder::getBoxAccessTag(Type baseFIRType, Type accessFIRType, - GEPOp gep) { +TBAATagAttr TBAABuilder::getBoxAccessTag(Type baseFIRType, Type accessFIRType, + GEPOp gep) { return getAnyBoxAccessTag(); } -SymbolRefAttr TBAABuilder::getAnyDataAccessTag() { +TBAATagAttr TBAABuilder::getAnyDataAccessTag() { return getAccessTag(anyDataAccessTypeDesc, anyDataAccessTypeDesc, /*offset=*/0); } -SymbolRefAttr TBAABuilder::getDataAccessTag(Type baseFIRType, - Type accessFIRType, GEPOp gep) { +TBAATagAttr TBAABuilder::getDataAccessTag(Type baseFIRType, Type accessFIRType, + GEPOp gep) { return getAnyDataAccessTag(); } @@ -154,7 +105,7 @@ LLVM_DEBUG(llvm::dbgs() << "Attaching TBAA tag #" << tagAttachmentCounter << "\n"); - SymbolRefAttr tbaaTagSym; + TBAATagAttr tbaaTagSym; if (baseFIRType.isa()) tbaaTagSym = getBoxAccessTag(baseFIRType, accessFIRType, gep); else diff --git a/flang/lib/Optimizer/CodeGen/TypeConverter.cpp b/flang/lib/Optimizer/CodeGen/TypeConverter.cpp --- a/flang/lib/Optimizer/CodeGen/TypeConverter.cpp +++ b/flang/lib/Optimizer/CodeGen/TypeConverter.cpp @@ -37,7 +37,7 @@ specifics(CodeGenSpecifics::get(module.getContext(), getTargetTriple(module), getKindMapping(module))), - tbaaBuilder(module, applyTBAA) { + tbaaBuilder(module->getContext(), applyTBAA) { LLVM_DEBUG(llvm::dbgs() << "FIR type converter\n"); // Each conversion should return a value of type mlir::Type. diff --git a/flang/test/Fir/tbaa.fir b/flang/test/Fir/tbaa.fir --- a/flang/test/Fir/tbaa.fir +++ b/flang/test/Fir/tbaa.fir @@ -20,6 +20,13 @@ } } +// CHECK-DAG: #[[ROOT:.*]] = #llvm.tbaa_root +// CHECK-DAG: #[[ANYACC:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[ANYDACC:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[BOXMEM:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[$BOXT:.*]] = #llvm.tbaa_tag +// CHECK-DAG: #[[$DATAT:.*]] = #llvm.tbaa_tag + // CHECK-LABEL: llvm.func @tbaa( // CHECK-SAME: %[[VAL_0:.*]]: !llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>> {fir.bindc_name = "a"}) { // CHECK: %[[VAL_1:.*]] = llvm.mlir.constant(1 : i32) : i32 @@ -28,10 +35,10 @@ // CHECK: %[[VAL_4:.*]] = llvm.mlir.constant(0 : i64) : i64 // CHECK: %[[VAL_5:.*]] = llvm.mlir.constant(10 : i32) : i32 // CHECK: %[[VAL_6:.*]] = llvm.getelementptr %[[VAL_0]][0, 0] : (!llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>>) -> !llvm.ptr>> -// CHECK: %[[VAL_7:.*]] = llvm.load %[[VAL_6]] {tbaa = [@__flang_tbaa::@[[BOXT:tag_[0-9]*]]]} : !llvm.ptr>> +// CHECK: %[[VAL_7:.*]] = llvm.load %[[VAL_6]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr>> // CHECK: %[[VAL_8:.*]] = llvm.mlir.constant(0 : i64) : i64 // CHECK: %[[VAL_9:.*]] = llvm.getelementptr %[[VAL_0]][0, 7, 0, 2] : (!llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>>) -> !llvm.ptr -// CHECK: %[[VAL_10:.*]] = llvm.load %[[VAL_9]] {tbaa = [@__flang_tbaa::@[[BOXT]]]} : !llvm.ptr +// CHECK: %[[VAL_10:.*]] = llvm.load %[[VAL_9]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr // CHECK: %[[VAL_11:.*]] = llvm.mul %[[VAL_4]], %[[VAL_10]] : i64 // CHECK: %[[VAL_12:.*]] = llvm.add %[[VAL_11]], %[[VAL_8]] : i64 // CHECK: %[[VAL_13:.*]] = llvm.bitcast %[[VAL_7]] : !llvm.ptr> to !llvm.ptr @@ -40,11 +47,11 @@ // CHECK: %[[VAL_16:.*]] = llvm.mlir.constant(0 : i64) : i64 // CHECK: %[[VAL_17:.*]] = llvm.mlir.constant(-1 : i32) : i32 // CHECK: %[[VAL_18:.*]] = llvm.getelementptr %[[VAL_0]][0, 8] : (!llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>>) -> !llvm.ptr> -// CHECK: %[[VAL_19:.*]] = llvm.load %[[VAL_18]] {tbaa = [@__flang_tbaa::@[[BOXT]]]} : !llvm.ptr> +// CHECK: %[[VAL_19:.*]] = llvm.load %[[VAL_18]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr> // CHECK: %[[VAL_20:.*]] = llvm.getelementptr %[[VAL_0]][0, 1] : (!llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>>) -> !llvm.ptr -// CHECK: %[[VAL_21:.*]] = llvm.load %[[VAL_20]] {tbaa = [@__flang_tbaa::@[[BOXT]]]} : !llvm.ptr +// CHECK: %[[VAL_21:.*]] = llvm.load %[[VAL_20]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr // CHECK: %[[VAL_22:.*]] = llvm.getelementptr %[[VAL_0]][0, 4] : (!llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>>) -> !llvm.ptr -// CHECK: %[[VAL_23:.*]] = llvm.load %[[VAL_22]] {tbaa = [@__flang_tbaa::@[[BOXT]]]} : !llvm.ptr +// CHECK: %[[VAL_23:.*]] = llvm.load %[[VAL_22]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr // CHECK: %[[VAL_24:.*]] = llvm.mlir.undef : !llvm.struct<(ptr>, i64, i32, i8, i8, i8, i8, ptr, array<1 x i64>)> // CHECK: %[[VAL_25:.*]] = llvm.insertvalue %[[VAL_21]], %[[VAL_24]][1] : !llvm.struct<(ptr>, i64, i32, i8, i8, i8, i8, ptr, array<1 x i64>)> // CHECK: %[[VAL_26:.*]] = llvm.mlir.constant(20180515 : i32) : i32 @@ -64,29 +71,20 @@ // CHECK: %[[VAL_40:.*]] = llvm.insertvalue %[[VAL_39]], %[[VAL_38]][7] : !llvm.struct<(ptr>, i64, i32, i8, i8, i8, i8, ptr, array<1 x i64>)> // CHECK: %[[VAL_41:.*]] = llvm.bitcast %[[VAL_15]] : !llvm.ptr> to !llvm.ptr> // CHECK: %[[VAL_42:.*]] = llvm.insertvalue %[[VAL_41]], %[[VAL_40]][0] : !llvm.struct<(ptr>, i64, i32, i8, i8, i8, i8, ptr, array<1 x i64>)> -// CHECK: llvm.store %[[VAL_42]], %[[VAL_2]] {tbaa = [@__flang_tbaa::@[[BOXT]]]} : !llvm.ptr>, i64, i32, i8, i8, i8, i8, ptr, array<1 x i64>)>> +// CHECK: llvm.store %[[VAL_42]], %[[VAL_2]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr>, i64, i32, i8, i8, i8, i8, ptr, array<1 x i64>)>> // CHECK: %[[VAL_43:.*]] = llvm.getelementptr %[[VAL_2]][0, 4] : (!llvm.ptr>, i64, i32, i8, i8, i8, i8, ptr, array<1 x i64>)>>) -> !llvm.ptr -// CHECK: %[[VAL_44:.*]] = llvm.load %[[VAL_43]] {tbaa = [@__flang_tbaa::@[[BOXT]]]} : !llvm.ptr +// CHECK: %[[VAL_44:.*]] = llvm.load %[[VAL_43]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr // CHECK: %[[VAL_45:.*]] = llvm.icmp "eq" %[[VAL_44]], %[[VAL_3]] : i8 // CHECK: llvm.cond_br %[[VAL_45]], ^bb1, ^bb2 // CHECK: ^bb1: // CHECK: %[[VAL_46:.*]] = llvm.getelementptr %[[VAL_2]][0, 0] : (!llvm.ptr>, i64, i32, i8, i8, i8, i8, ptr, array<1 x i64>)>>) -> !llvm.ptr> -// CHECK: %[[VAL_47:.*]] = llvm.load %[[VAL_46]] {tbaa = [@__flang_tbaa::@[[BOXT]]]} : !llvm.ptr> -// CHECK: llvm.store %[[VAL_5]], %[[VAL_47]] {tbaa = [@__flang_tbaa::@[[DATAT:tag_[0-9]*]]]} : !llvm.ptr +// CHECK: %[[VAL_47:.*]] = llvm.load %[[VAL_46]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr> +// CHECK: llvm.store %[[VAL_5]], %[[VAL_47]] {tbaa = [#[[$DATAT]]]} : !llvm.ptr // CHECK: llvm.br ^bb2 // CHECK: ^bb2: // CHECK: llvm.return // CHECK: } -// CHECK-LABEL: llvm.metadata @__flang_tbaa { -// CHECK: llvm.tbaa_root @[[ROOT:root_[0-9]*]] {id = "Flang Type TBAA Root"} -// CHECK: llvm.tbaa_type_desc @[[ANYACC:type_desc_[0-9]*]] {id = "any access", members = {<@[[ROOT]], 0>}} -// CHECK: llvm.tbaa_type_desc @[[ANYDACC:type_desc_[0-9]*]] {id = "any data access", members = {<@[[ANYACC]], 0>}} -// CHECK: llvm.tbaa_type_desc @[[BOXMEM:type_desc_[0-9]*]] {id = "descriptor member", members = {<@[[ANYACC]], 0>}} -// CHECK: llvm.tbaa_tag @[[BOXT]] {access_type = @[[BOXMEM]], base_type = @[[BOXMEM]], offset = 0 : i64} -// CHECK: llvm.tbaa_tag @[[DATAT]] {access_type = @[[ANYDACC]], base_type = @[[ANYDACC]], offset = 0 : i64} -// CHECK: } - // ----- module { @@ -121,6 +119,11 @@ } } +// CHECK-DAG: #[[ROOT:.*]] = #llvm.tbaa_root +// CHECK-DAG: #[[ANYACC:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[BOXMEM:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[$BOXT:.*]] = #llvm.tbaa_tag + // CHECK-LABEL: llvm.func @tbaa() { // CHECK: %[[VAL_0:.*]] = llvm.mlir.constant(1 : i32) : i32 // CHECK: %[[VAL_1:.*]] = llvm.alloca %[[VAL_0]] x !llvm.struct<(ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>> @@ -133,24 +136,24 @@ // CHECK: %[[VAL_8:.*]] = llvm.mlir.addressof @_QQcl.2E2F64756D6D792E66393000 : !llvm.ptr> // CHECK: %[[VAL_9:.*]] = llvm.bitcast %[[VAL_8]] : !llvm.ptr> to !llvm.ptr // CHECK: %[[VAL_10:.*]] = llvm.call @_FortranAioBeginExternalListOutput(%[[VAL_6]], %[[VAL_9]], %[[VAL_5]]) {fastmathFlags = #llvm.fastmath} : (i32, !llvm.ptr, i32) -> !llvm.ptr -// CHECK: %[[VAL_11:.*]] = llvm.load %[[VAL_7]] {tbaa = [@__flang_tbaa::@[[BOXT:tag_[0-9]*]]]} : !llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>> -// CHECK: llvm.store %[[VAL_11]], %[[VAL_3]] {tbaa = [@__flang_tbaa::@[[BOXT]]]} : !llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>> +// CHECK: %[[VAL_11:.*]] = llvm.load %[[VAL_7]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>> +// CHECK: llvm.store %[[VAL_11]], %[[VAL_3]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>> // CHECK: %[[VAL_12:.*]] = llvm.getelementptr %[[VAL_3]][0, 7, %[[VAL_4]], 0] : (!llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>>, i64) -> !llvm.ptr -// CHECK: %[[VAL_13:.*]] = llvm.load %[[VAL_12]] {tbaa = [@__flang_tbaa::@[[BOXT]]]} : !llvm.ptr +// CHECK: %[[VAL_13:.*]] = llvm.load %[[VAL_12]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr // CHECK: %[[VAL_14:.*]] = llvm.getelementptr %[[VAL_3]][0, 7, %[[VAL_4]], 1] : (!llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>>, i64) -> !llvm.ptr -// CHECK: %[[VAL_15:.*]] = llvm.load %[[VAL_14]] {tbaa = [@__flang_tbaa::@[[BOXT]]]} : !llvm.ptr +// CHECK: %[[VAL_15:.*]] = llvm.load %[[VAL_14]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr // CHECK: %[[VAL_16:.*]] = llvm.getelementptr %[[VAL_3]][0, 7, %[[VAL_4]], 2] : (!llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>>, i64) -> !llvm.ptr -// CHECK: %[[VAL_17:.*]] = llvm.load %[[VAL_16]] {tbaa = [@__flang_tbaa::@[[BOXT]]]} : !llvm.ptr +// CHECK: %[[VAL_17:.*]] = llvm.load %[[VAL_16]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr // CHECK: %[[VAL_18:.*]] = llvm.getelementptr %[[VAL_3]][0, 8] : (!llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>>) -> !llvm.ptr> -// CHECK: %[[VAL_19:.*]] = llvm.load %[[VAL_18]] {tbaa = [@__flang_tbaa::@[[BOXT]]]} : !llvm.ptr> +// CHECK: %[[VAL_19:.*]] = llvm.load %[[VAL_18]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr> // CHECK: %[[VAL_20:.*]] = llvm.mlir.constant(0 : i64) : i64 // CHECK: %[[VAL_21:.*]] = llvm.mlir.constant(-1 : i32) : i32 // CHECK: %[[VAL_22:.*]] = llvm.getelementptr %[[VAL_3]][0, 1] : (!llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>>) -> !llvm.ptr -// CHECK: %[[VAL_23:.*]] = llvm.load %[[VAL_22]] {tbaa = [@__flang_tbaa::@[[BOXT]]]} : !llvm.ptr +// CHECK: %[[VAL_23:.*]] = llvm.load %[[VAL_22]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr // CHECK: %[[VAL_24:.*]] = llvm.getelementptr %[[VAL_3]][0, 4] : (!llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>>) -> !llvm.ptr -// CHECK: %[[VAL_25:.*]] = llvm.load %[[VAL_24]] {tbaa = [@__flang_tbaa::@[[BOXT]]]} : !llvm.ptr +// CHECK: %[[VAL_25:.*]] = llvm.load %[[VAL_24]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr // CHECK: %[[VAL_26:.*]] = llvm.getelementptr %[[VAL_3]][0, 8] : (!llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>>) -> !llvm.ptr> -// CHECK: %[[VAL_27:.*]] = llvm.load %[[VAL_26]] {tbaa = [@__flang_tbaa::@[[BOXT]]]} : !llvm.ptr> +// CHECK: %[[VAL_27:.*]] = llvm.load %[[VAL_26]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr> // CHECK: %[[VAL_28:.*]] = llvm.mlir.undef : !llvm.struct<(ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)> // CHECK: %[[VAL_29:.*]] = llvm.insertvalue %[[VAL_23]], %[[VAL_28]][1] : !llvm.struct<(ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)> // CHECK: %[[VAL_30:.*]] = llvm.mlir.constant(20180515 : i32) : i32 @@ -169,13 +172,13 @@ // CHECK: %[[VAL_43:.*]] = llvm.bitcast %[[VAL_27]] : !llvm.ptr to !llvm.ptr // CHECK: %[[VAL_44:.*]] = llvm.insertvalue %[[VAL_43]], %[[VAL_42]][8] : !llvm.struct<(ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)> // CHECK: %[[VAL_45:.*]] = llvm.getelementptr %[[VAL_3]][0, 7, 0, 0] : (!llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>>) -> !llvm.ptr -// CHECK: %[[VAL_46:.*]] = llvm.load %[[VAL_45]] {tbaa = [@__flang_tbaa::@[[BOXT]]]} : !llvm.ptr +// CHECK: %[[VAL_46:.*]] = llvm.load %[[VAL_45]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr // CHECK: %[[VAL_47:.*]] = llvm.getelementptr %[[VAL_3]][0, 7, 0, 1] : (!llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>>) -> !llvm.ptr -// CHECK: %[[VAL_48:.*]] = llvm.load %[[VAL_47]] {tbaa = [@__flang_tbaa::@[[BOXT]]]} : !llvm.ptr +// CHECK: %[[VAL_48:.*]] = llvm.load %[[VAL_47]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr // CHECK: %[[VAL_49:.*]] = llvm.getelementptr %[[VAL_3]][0, 7, 0, 2] : (!llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>>) -> !llvm.ptr -// CHECK: %[[VAL_50:.*]] = llvm.load %[[VAL_49]] {tbaa = [@__flang_tbaa::@[[BOXT]]]} : !llvm.ptr +// CHECK: %[[VAL_50:.*]] = llvm.load %[[VAL_49]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr // CHECK: %[[VAL_51:.*]] = llvm.getelementptr %[[VAL_3]][0, 0] : (!llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>>) -> !llvm.ptr>> -// CHECK: %[[VAL_52:.*]] = llvm.load %[[VAL_51]] {tbaa = [@__flang_tbaa::@[[BOXT]]]} : !llvm.ptr>> +// CHECK: %[[VAL_52:.*]] = llvm.load %[[VAL_51]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr>> // CHECK: %[[VAL_53:.*]] = llvm.mlir.constant(0 : i64) : i64 // CHECK: %[[VAL_54:.*]] = llvm.mlir.constant(1 : i64) : i64 // CHECK: %[[VAL_55:.*]] = llvm.icmp "eq" %[[VAL_48]], %[[VAL_53]] : i64 @@ -185,7 +188,7 @@ // CHECK: %[[VAL_59:.*]] = llvm.insertvalue %[[VAL_50]], %[[VAL_58]][7, 0, 2] : !llvm.struct<(ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)> // CHECK: %[[VAL_60:.*]] = llvm.bitcast %[[VAL_52]] : !llvm.ptr> to !llvm.ptr> // CHECK: %[[VAL_61:.*]] = llvm.insertvalue %[[VAL_60]], %[[VAL_59]][0] : !llvm.struct<(ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)> -// CHECK: llvm.store %[[VAL_61]], %[[VAL_1]] {tbaa = [@__flang_tbaa::@[[BOXT]]]} : !llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>> +// CHECK: llvm.store %[[VAL_61]], %[[VAL_1]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>> // CHECK: %[[VAL_62:.*]] = llvm.bitcast %[[VAL_1]] : !llvm.ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)>> to !llvm.ptr>, i64, i32, i8, i8, i8, i8, ptr, array<1 x i64>)>> // CHECK: %[[VAL_63:.*]] = llvm.call @_FortranAioOutputDescriptor(%[[VAL_10]], %[[VAL_62]]) {fastmathFlags = #llvm.fastmath} : (!llvm.ptr, !llvm.ptr>, i64, i32, i8, i8, i8, i8, ptr, array<1 x i64>)>>) -> i1 // CHECK: %[[VAL_64:.*]] = llvm.call @_FortranAioEndIoStatement(%[[VAL_10]]) {fastmathFlags = #llvm.fastmath} : (!llvm.ptr) -> i32 @@ -235,14 +238,6 @@ // CHECK: llvm.return %[[VAL_30]] : !llvm.struct<(ptr>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)> // CHECK: } -// CHECK-LABEL: llvm.metadata @__flang_tbaa { -// CHECK: llvm.tbaa_root @[[ROOT:root_[0-9]*]] {id = "Flang Type TBAA Root"} -// CHECK: llvm.tbaa_type_desc @[[ANYACC:type_desc_[0-9]*]] {id = "any access", members = {<@[[ROOT]], 0>}} -// CHECK: llvm.tbaa_type_desc @[[ANYDACC:type_desc_[0-9]*]] {id = "any data access", members = {<@[[ANYACC]], 0>}} -// CHECK: llvm.tbaa_type_desc @[[BOXMEM:type_desc_[0-9]*]] {id = "descriptor member", members = {<@[[ANYACC]], 0>}} -// CHECK: llvm.tbaa_tag @[[BOXT]] {access_type = @[[BOXMEM]], base_type = @[[BOXMEM]], offset = 0 : i64} -// CHECK: } - // ----- func.func @tbaa(%arg0: !fir.box>) -> i32 { @@ -250,21 +245,18 @@ return %0 : i32 } +// CHECK-DAG: #[[ROOT:.*]] = #llvm.tbaa_root +// CHECK-DAG: #[[ANYACC:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[BOXMEM:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[$BOXT:.*]] = #llvm.tbaa_tag + // CHECK-LABEL: llvm.func @tbaa( // CHECK-SAME: %[[VAL_0:.*]]: !llvm.ptr, i64, i32, i8, i8, i8, i8)>>) -> i32 { // CHECK: %[[VAL_1:.*]] = llvm.getelementptr %[[VAL_0]][0, 3] : (!llvm.ptr, i64, i32, i8, i8, i8, i8)>>) -> !llvm.ptr -// CHECK: %[[VAL_2:.*]] = llvm.load %[[VAL_1]] {tbaa = [@__flang_tbaa::@[[BOXT:tag_[0-9]*]]]} : !llvm.ptr +// CHECK: %[[VAL_2:.*]] = llvm.load %[[VAL_1]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr // CHECK: llvm.return %[[VAL_2]] : i32 // CHECK: } -// CHECK-LABEL: llvm.metadata @__flang_tbaa { -// CHECK: llvm.tbaa_root @[[ROOT:root_[0-9]*]] {id = "Flang Type TBAA Root"} -// CHECK: llvm.tbaa_type_desc @[[ANYACC:type_desc_[0-9]*]] {id = "any access", members = {<@[[ROOT]], 0>}} -// CHECK: llvm.tbaa_type_desc @[[ANYDACC:type_desc_[0-9]*]] {id = "any data access", members = {<@[[ANYACC]], 0>}} -// CHECK: llvm.tbaa_type_desc @[[BOXMEM:type_desc_[0-9]*]] {id = "descriptor member", members = {<@[[ANYACC]], 0>}} -// CHECK: llvm.tbaa_tag @[[BOXT]] {access_type = @[[BOXMEM]], base_type = @[[BOXMEM]], offset = 0 : i64} -// CHECK: } - // ----- func.func @tbaa(%arg0: !fir.box>) -> i1 { @@ -272,23 +264,20 @@ return %0 : i1 } +// CHECK-DAG: #[[ROOT:.*]] = #llvm.tbaa_root +// CHECK-DAG: #[[ANYACC:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[BOXMEM:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[$BOXT:.*]] = #llvm.tbaa_tag + // CHECK-LABEL: llvm.func @tbaa( // CHECK-SAME: %[[VAL_0:.*]]: !llvm.ptr, i64, i32, i8, i8, i8, i8)>>) -> i1 { // CHECK: %[[VAL_1:.*]] = llvm.getelementptr %[[VAL_0]][0, 3] : (!llvm.ptr, i64, i32, i8, i8, i8, i8)>>) -> !llvm.ptr -// CHECK: %[[VAL_2:.*]] = llvm.load %[[VAL_1]] {tbaa = [@__flang_tbaa::@[[BOXT:tag_[0-9]*]]]} : !llvm.ptr +// CHECK: %[[VAL_2:.*]] = llvm.load %[[VAL_1]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr // CHECK: %[[VAL_3:.*]] = llvm.mlir.constant(0 : i32) : i32 // CHECK: %[[VAL_4:.*]] = llvm.icmp "ne" %[[VAL_2]], %[[VAL_3]] : i32 // CHECK: llvm.return %[[VAL_4]] : i1 // CHECK: } -// CHECK-LABEL: llvm.metadata @__flang_tbaa { -// CHECK: llvm.tbaa_root @[[ROOT:root_[0-9]*]] {id = "Flang Type TBAA Root"} -// CHECK: llvm.tbaa_type_desc @[[ANYACC:type_desc_[0-9]*]] {id = "any access", members = {<@[[ROOT]], 0>}} -// CHECK: llvm.tbaa_type_desc @[[ANYDACC:type_desc_[0-9]*]] {id = "any data access", members = {<@[[ANYACC]], 0>}} -// CHECK: llvm.tbaa_type_desc @[[BOXMEM:type_desc_[0-9]*]] {id = "descriptor member", members = {<@[[ANYACC]], 0>}} -// CHECK: llvm.tbaa_tag @[[BOXT]] {access_type = @[[BOXMEM]], base_type = @[[BOXMEM]], offset = 0 : i64} -// CHECK: } - // ----- func.func @tbaa(%arg0: !fir.box) -> i32 { @@ -296,21 +285,18 @@ return %0 : i32 } +// CHECK-DAG: #[[ROOT:.*]] = #llvm.tbaa_root +// CHECK-DAG: #[[ANYACC:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[BOXMEM:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[$BOXT:.*]] = #llvm.tbaa_tag + // CHECK-LABEL: llvm.func @tbaa( // CHECK-SAME: %[[VAL_0:.*]]: !llvm.ptr, i64, i32, i8, i8, i8, i8)>>) -> i32 { // CHECK: %[[VAL_1:.*]] = llvm.getelementptr %[[VAL_0]][0, 1] : (!llvm.ptr, i64, i32, i8, i8, i8, i8)>>) -> !llvm.ptr -// CHECK: %[[VAL_2:.*]] = llvm.load %[[VAL_1]] {tbaa = [@__flang_tbaa::@[[BOXT:tag_[0-9]*]]]} : !llvm.ptr +// CHECK: %[[VAL_2:.*]] = llvm.load %[[VAL_1]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr // CHECK: llvm.return %[[VAL_2]] : i32 // CHECK: } -// CHECK-LABEL: llvm.metadata @__flang_tbaa { -// CHECK: llvm.tbaa_root @[[ROOT:root_[0-9]*]] {id = "Flang Type TBAA Root"} -// CHECK: llvm.tbaa_type_desc @[[ANYACC:type_desc_[0-9]*]] {id = "any access", members = {<@[[ROOT]], 0>}} -// CHECK: llvm.tbaa_type_desc @[[ANYDACC:type_desc_[0-9]*]] {id = "any data access", members = {<@[[ANYACC]], 0>}} -// CHECK: llvm.tbaa_type_desc @[[BOXMEM:type_desc_[0-9]*]] {id = "descriptor member", members = {<@[[ANYACC]], 0>}} -// CHECK: llvm.tbaa_tag @[[BOXT]] {access_type = @[[BOXMEM]], base_type = @[[BOXMEM]], offset = 0 : i64} -// CHECK: } - // ----- func.func @tbaa(%arg0: !fir.box>) -> i1 { @@ -318,10 +304,15 @@ return %0 : i1 } +// CHECK-DAG: #[[ROOT:.*]] = #llvm.tbaa_root +// CHECK-DAG: #[[ANYACC:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[BOXMEM:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[$BOXT:.*]] = #llvm.tbaa_tag + // CHECK-LABEL: llvm.func @tbaa( // CHECK-SAME: %[[VAL_0:.*]]: !llvm.ptr, i64, i32, i8, i8, i8, i8)>>) -> i1 { // CHECK: %[[VAL_1:.*]] = llvm.getelementptr %[[VAL_0]][0, 5] : (!llvm.ptr, i64, i32, i8, i8, i8, i8)>>) -> !llvm.ptr -// CHECK: %[[VAL_2:.*]] = llvm.load %[[VAL_1]] {tbaa = [@__flang_tbaa::@[[BOXT:tag_[0-9]*]]]} : !llvm.ptr +// CHECK: %[[VAL_2:.*]] = llvm.load %[[VAL_1]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr // CHECK: %[[VAL_3:.*]] = llvm.mlir.constant(2 : i32) : i32 // CHECK: %[[VAL_4:.*]] = llvm.and %[[VAL_2]], %[[VAL_3]] : i32 // CHECK: %[[VAL_5:.*]] = llvm.mlir.constant(0 : i32) : i32 @@ -329,14 +320,6 @@ // CHECK: llvm.return %[[VAL_6]] : i1 // CHECK: } -// CHECK-LABEL: llvm.metadata @__flang_tbaa { -// CHECK: llvm.tbaa_root @[[ROOT:root_[0-9]*]] {id = "Flang Type TBAA Root"} -// CHECK: llvm.tbaa_type_desc @[[ANYACC:type_desc_[0-9]*]] {id = "any access", members = {<@[[ROOT]], 0>}} -// CHECK: llvm.tbaa_type_desc @[[ANYDACC:type_desc_[0-9]*]] {id = "any data access", members = {<@[[ANYACC]], 0>}} -// CHECK: llvm.tbaa_type_desc @[[BOXMEM:type_desc_[0-9]*]] {id = "descriptor member", members = {<@[[ANYACC]], 0>}} -// CHECK: llvm.tbaa_tag @[[BOXT]] {access_type = @[[BOXMEM]], base_type = @[[BOXMEM]], offset = 0 : i64} -// CHECK: } - // ----- func.func @tbaa(%arg0: !fir.box>) { @@ -345,6 +328,11 @@ return } +// CHECK-DAG: #[[ROOT:.*]] = #llvm.tbaa_root +// CHECK-DAG: #[[ANYACC:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[BOXMEM:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[$BOXT:.*]] = #llvm.tbaa_tag + // CHECK-LABEL: llvm.func @tbaa( // CHECK-SAME: %[[VAL_0:.*]]: !llvm.ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>>) { // CHECK: %[[VAL_1:.*]] = llvm.mlir.constant(0 : i64) : i64 @@ -353,21 +341,13 @@ // CHECK: %[[VAL_4:.*]] = llvm.sub %[[VAL_1]], %[[VAL_2]] : i64 // CHECK: %[[VAL_5:.*]] = llvm.mul %[[VAL_4]], %[[VAL_2]] : i64 // CHECK: %[[VAL_6:.*]] = llvm.getelementptr %[[VAL_0]][0, 7, 0, 2] : (!llvm.ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>>) -> !llvm.ptr -// CHECK: %[[VAL_7:.*]] = llvm.load %[[VAL_6]] {tbaa = [@__flang_tbaa::@[[BOXT:tag_[0-9]*]]]} : !llvm.ptr +// CHECK: %[[VAL_7:.*]] = llvm.load %[[VAL_6]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr // CHECK: %[[VAL_8:.*]] = llvm.mul %[[VAL_5]], %[[VAL_7]] : i64 // CHECK: %[[VAL_9:.*]] = llvm.add %[[VAL_8]], %[[VAL_3]] : i64 // CHECK: %[[VAL_10:.*]] = llvm.getelementptr %[[VAL_0]][0, 0] : (!llvm.ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>>) -> !llvm.ptr> -// CHECK: %[[VAL_11:.*]] = llvm.load %[[VAL_10]] {tbaa = [@__flang_tbaa::@[[BOXT]]]} : !llvm.ptr> +// CHECK: %[[VAL_11:.*]] = llvm.load %[[VAL_10]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr> // CHECK: %[[VAL_12:.*]] = llvm.bitcast %[[VAL_11]] : !llvm.ptr to !llvm.ptr // CHECK: %[[VAL_13:.*]] = llvm.getelementptr %[[VAL_12]]{{\[}}%[[VAL_9]]] : (!llvm.ptr, i64) -> !llvm.ptr // CHECK: %[[VAL_14:.*]] = llvm.bitcast %[[VAL_13]] : !llvm.ptr to !llvm.ptr // CHECK: llvm.return // CHECK: } - -// CHECK-LABEL: llvm.metadata @__flang_tbaa { -// CHECK: llvm.tbaa_root @[[ROOT:root_[0-9]*]] {id = "Flang Type TBAA Root"} -// CHECK: llvm.tbaa_type_desc @[[ANYACC:type_desc_[0-9]*]] {id = "any access", members = {<@[[ROOT]], 0>}} -// CHECK: llvm.tbaa_type_desc @[[ANYDACC:type_desc_[0-9]*]] {id = "any data access", members = {<@[[ANYACC]], 0>}} -// CHECK: llvm.tbaa_type_desc @[[BOXMEM:type_desc_[0-9]*]] {id = "descriptor member", members = {<@[[ANYACC]], 0>}} -// CHECK: llvm.tbaa_tag @[[BOXT]] {access_type = @[[BOXMEM]], base_type = @[[BOXMEM]], offset = 0 : i64} -// CHECK: } diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td @@ -685,4 +685,149 @@ let constBuilderCall = ?; } +//===----------------------------------------------------------------------===// +// TBAARootAttr +//===----------------------------------------------------------------------===// + +def LLVM_TBAARootAttr : LLVM_Attr<"TBAARoot", "tbaa_root", [], "TBAANodeAttr"> { + let parameters = (ins OptionalParameter<"StringAttr">:$id); + + let summary = "LLVM dialect TBAA root metadata"; + let description = [{ + Defines a TBAA root node. + + Example: + ```mlir + #cpp_root = #llvm.tbaa_root + #other_root = #llvm.tbaa_root + ``` + + See the following link for more details: + https://llvm.org/docs/LangRef.html#tbaa-metadata + }]; + + let assemblyFormat = "(`<` struct(params)^ `>`)?"; +} + +//===----------------------------------------------------------------------===// +// TBAATypeDescriptorAttr +//===----------------------------------------------------------------------===// + +def LLVM_TBAAMemberAttr : LLVM_Attr<"TBAAMember", "tbaa_member"> { + let parameters = (ins + "TBAANodeAttr":$typeDesc, + "int64_t":$offset + ); + + let builders = [ + AttrBuilderWithInferredContext<(ins "TBAANodeAttr":$typeDesc, + "int64_t":$offset), [{ + return $_get(typeDesc.getContext(), typeDesc, offset); + }]> + ]; + + let assemblyFormat = "`<` params `>`"; +} + +def LLVM_TBAAMemberAttrArray : ArrayRefParameter<"TBAAMemberAttr"> { + let printer = [{ + $_printer << '{'; + llvm::interleaveComma($_self, $_printer, [&](TBAAMemberAttr attr) { + $_printer.printStrippedAttrOrType(attr); + }); + $_printer << '}'; + }]; + + let parser = [{ + [&]() -> FailureOr> { + using Result = SmallVector; + if ($_parser.parseLBrace()) + return failure(); + FailureOr result = FieldParser::parse($_parser); + if (failed(result)) + return failure(); + if ($_parser.parseRBrace()) + return failure(); + return result; + }() + }]; +} + +def LLVM_TBAATypeDescriptorAttr : LLVM_Attr<"TBAATypeDescriptor", + "tbaa_type_desc", [], "TBAANodeAttr"> { + let parameters = (ins + StringRefParameter<>:$id, + LLVM_TBAAMemberAttrArray:$members + ); + + let summary = "LLVM dialect TBAA type metadata"; + + let description = [{ + Defines a TBAA node describing a type. + + Example: + ```mlir + #tbaa_root = #llvm.tbaa_root + #tbaa_type_desc1 = #llvm.tbaa_type_desc}> + #tbaa_type_desc2 = #llvm.tbaa_type_desc}> + #tbaa_type_desc3 = #llvm.tbaa_type_desc, <#tbaa_type_desc2, 8>}> + #tbaa_type_desc4 = #llvm.tbaa_type_desc}> + #tbaa_type_desc5 = #llvm.tbaa_type_desc, <#tbaa_type_desc4, 4>}> + ``` + + See the following link for more details: + https://llvm.org/docs/LangRef.html#tbaa-metadata + }]; + + let assemblyFormat = "`<` struct(params) `>`"; +} + +//===----------------------------------------------------------------------===// +// TBAATagAttr +//===----------------------------------------------------------------------===// + +def LLVM_TBAATagAttr : LLVM_Attr<"TBAATag", "tbaa_tag"> { + let parameters = (ins + "TBAATypeDescriptorAttr":$base_type, + "TBAATypeDescriptorAttr":$access_type, + "int64_t":$offset, + DefaultValuedParameter<"bool", "false">:$constant + ); + + let builders = [ + AttrBuilderWithInferredContext<(ins "TBAATypeDescriptorAttr":$baseType, + "TBAATypeDescriptorAttr":$accessType, + "int64_t":$offset), [{ + return $_get(baseType.getContext(), baseType, accessType, offset, + /*constant=*/false); + }]> + ]; + + let summary = "LLVM dialect TBAA tag metadata"; + + let description = [{ + Defines a TBAA node describing a memory access. + + Example: + ```mlir + #tbaa_root = #llvm.tbaa_root + #tbaa_type_desc1 = #llvm.tbaa_type_desc}> + #tbaa_type_desc2 = #llvm.tbaa_type_desc}> + #tbaa_type_desc3 = #llvm.tbaa_type_desc, <#tbaa_type_desc4, 4>}> + #tbaa_tag = #llvm.tbaa_tag + ``` + + See the following link for more details: + https://llvm.org/docs/LangRef.html#tbaa-metadata + }]; + + let assemblyFormat = "`<` struct(params) `>`"; +} + +def LLVM_TBAATagArrayAttr + : TypedArrayAttrBase { + let constBuilderCall = ?; +} + #endif // LLVMIR_ATTRDEFS diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h @@ -60,6 +60,20 @@ static bool classof(Attribute attr); }; +/// Base class for LLVM attributes participating in the TBAA graph. +class TBAANodeAttr : public Attribute { +public: + using Attribute::Attribute; + + /// Support LLVM type casting. + static bool classof(Attribute attr); + + /// Required by DenseMapInfo to create empty and tombstone key. + static TBAANodeAttr getFromOpaquePointer(const void *pointer) { + return TBAANodeAttr(reinterpret_cast(pointer)); + } +}; + // Inline the LLVM generated Linkage enum and utility. // This is only necessary to isolate the "enum generated code" from the // attribute definition itself. diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td @@ -281,7 +281,7 @@ dag aliasAttrs = (ins OptionalAttr:$access_groups, OptionalAttr:$alias_scopes, OptionalAttr:$noalias_scopes, - OptionalAttr:$tbaa); + OptionalAttr:$tbaa); } // Base class for LLVM intrinsics operation. It is similar to LLVM_Op, but @@ -326,7 +326,7 @@ !if(!gt(requiresAliasAnalysis, 0), (ins OptionalAttr:$alias_scopes, OptionalAttr:$noalias_scopes, - OptionalAttr:$tbaa), + OptionalAttr:$tbaa), (ins ))); string resultPattern = !if(!gt(numResults, 1), LLVM_IntrPatterns.structResult, diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -1096,156 +1096,6 @@ ]; let hasCustomAssemblyFormat = 1; - let hasRegionVerifier = 1; -} - -def LLVM_TBAARootMetadataOp : LLVM_Op<"tbaa_root", [ - HasParent<"MetadataOp">, Symbol -]> { - let arguments = (ins - SymbolNameAttr:$sym_name, - StrAttr:$identity - ); - let summary = "LLVM dialect TBAA root node metadata."; - let description = [{ - Defines a TBAA root node. - - Example: - ```mlir - llvm.metadata @tbaa { - llvm.tbaa_root @tbaa_root_0 {identity = "Simple C/C++ TBAA"} - } - ``` - - See the following link for more details: - https://llvm.org/docs/LangRef.html#tbaa-metadata - }]; - let assemblyFormat = [{ - $sym_name ` ` `{` `id` `=` $identity `}` attr-dict - }]; - let hasVerifier = 1; -} - -def LLVM_TBAATypeDescriptorOp : LLVM_Op<"tbaa_type_desc", [ - HasParent<"MetadataOp">, Symbol -]> { - let arguments = (ins - SymbolNameAttr:$sym_name, - OptionalAttr:$identity, - FlatSymbolRefArrayAttr:$members, - DenseI64ArrayAttr:$offsets - ); - let summary = "LLVM dialect TBAA node describing a type."; - let description = [{ - Defines a TBAA node describing a type. - - Example: - ```mlir - llvm.metadata @tbaa { - llvm.tbaa_root @tbaa_root_0 {identity = "Simple C/C++ TBAA"} - llvm.tbaa_type_desc @tbaa_type_desc_1 { - identity = "omnipotent char", - members = [@tbaa_root_0], - offsets = array - } - llvm.tbaa_type_desc @tbaa_type_desc_2 { - identity = "long long", - members = [@tbaa_type_desc_1], - offsets = array - } - llvm.tbaa_type_desc @tbaa_type_desc_3 { - identity = "agg2_t", - members = [@tbaa_type_desc_2, @tbaa_type_desc_2], - offsets = array - } - llvm.tbaa_type_desc @tbaa_type_desc_5 { - identity = "int", - members = [@tbaa_type_desc_1], - offsets = array - } - llvm.tbaa_type_desc @tbaa_type_desc_6 { - identity = "agg1_t", - members = [@tbaa_type_desc_5, @tbaa_type_desc_5], - offsets = array - } - } - ``` - - See the following link for more details: - https://llvm.org/docs/LangRef.html#tbaa-metadata - }]; - - // Interleave member types and offsets for better matching - // LLVM IR text representation. - let assemblyFormat = [{ - $sym_name ` ` `{` - ( `id` `=` $identity^ )? `,` - `members` `=` `{` custom($members, $offsets) `}` - `}` attr-dict - }]; - let hasVerifier = 1; -} - -def LLVM_TBAATagOp : LLVM_Op<"tbaa_tag", [ - HasParent<"MetadataOp">, Symbol -]> { - let arguments = (ins - SymbolNameAttr:$sym_name, - FlatSymbolRefAttr:$base_type, - FlatSymbolRefAttr:$access_type, - I64Attr:$offset, - UnitAttr:$constant - ); - let summary = "LLVM dialect TBAA node describing a memory access."; - let description = [{ - Defines a TBAA node describing a memory access. - - Example: - ```mlir - llvm.metadata @tbaa { - llvm.tbaa_root @tbaa_root_0 {identity = "Simple C/C++ TBAA"} - llvm.tbaa_type_desc @tbaa_type_desc_1 { - identity = "omnipotent char", - members = [@tbaa_root_0], - offsets = array - } - llvm.tbaa_type_desc @tbaa_type_desc_2 { - identity = "long long", - members = [@tbaa_type_desc_1], - offsets = array - } - llvm.tbaa_type_desc @tbaa_type_desc_3 { - identity = "agg2_t", - members = [@tbaa_type_desc_2, @tbaa_type_desc_2], - offsets = array - } - llvm.tbaa_tag @tbaa_tag_4 { - access_type = @tbaa_type_desc_2, - base_type = @tbaa_type_desc_3, - offset = 8 : i64 - } - llvm.tbaa_type_desc @tbaa_type_desc_5 { - identity = "int", - members = [@tbaa_type_desc_1], - offsets = array - } - llvm.tbaa_type_desc @tbaa_type_desc_6 { - identity = "agg1_t", - members = [@tbaa_type_desc_5, @tbaa_type_desc_5], - offsets = array - } - llvm.tbaa_tag @tbaa_tag_7 { - access_type = @tbaa_type_desc_5, - base_type = @tbaa_type_desc_6, - offset = 0 : i64 - } - } - ``` - - See the following link for more details: - https://llvm.org/docs/LangRef.html#tbaa-metadata - }]; - let assemblyFormat = "$sym_name attr-dict"; } def LLVM_GlobalOp : LLVM_Op<"mlir.global", diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h --- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h +++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h @@ -176,18 +176,15 @@ /// implement the fastmath interface. void setFastmathFlagsAttr(llvm::Instruction *inst, Operation *op) const; - /// Converts all LLVM metadata nodes that translate to operations nested in a - /// global metadata operation, such as alias analysis or access group - /// metadata, and builds a map from the metadata nodes to the symbols pointing - /// to the converted operations. Returns success if all conversions succeed - /// and failure otherwise. - // Note: All metadata is nested inside a single global metadata operation to - // minimize the number of symbols that pollute the global namespace. + /// Converts all LLVM metadata nodes that translate to attributes such as + /// alias analysis or access group metadata, and builds a map from the + /// metadata nodes to the converted attributes. + /// Returns success if all conversions succeed and failure otherwise. LogicalResult convertMetadata(); - /// Returns the MLIR symbol reference mapped to the given LLVM TBAA + /// Returns the MLIR attribute mapped to the given LLVM TBAA /// metadata `node`. - SymbolRefAttr lookupTBAAAttr(const llvm::MDNode *node) const { + Attribute lookupTBAAAttr(const llvm::MDNode *node) const { return tbaaMapping.lookup(node); } @@ -288,10 +285,6 @@ /// them fails. All operations are inserted at the start of the current /// function entry block. FailureOr convertConstantExpr(llvm::Constant *constant); - /// Returns a global metadata operation that serves as a container for LLVM - /// metadata that converts to MLIR operations. Creates the global metadata - /// operation on the first invocation. - MetadataOp getGlobalMetadataOp(); /// Returns a global comdat operation that serves as a container for LLVM /// comdat selectors. Creates the global comdat operation on the first /// invocation. @@ -304,14 +297,13 @@ LogicalResult processTBAAMetadata(const llvm::MDNode *node); /// Converts all LLVM access groups starting from `node` to MLIR access group /// operations and stores a mapping from every nested access group node to the - /// symbol pointing to the translated operation. Returns success if all - /// conversions succeed and failure otherwise. + /// translated attribute. Returns success if all conversions succeed and + /// failure otherwise. LogicalResult processAccessGroupMetadata(const llvm::MDNode *node); /// Converts all LLVM alias scopes and domains starting from `node` to MLIR - /// alias scope and domain operations and stores a mapping from every nested - /// alias scope or alias domain node to the symbol pointing to the translated - /// operation. Returns success if all conversions succeed and failure - /// otherwise. + /// alias scope and domain attributes and stores a mapping from every nested + /// alias scope or alias domain node to the translated attribute. Returns + /// success if all conversions succeed and failure otherwise. LogicalResult processAliasScopeMetadata(const llvm::MDNode *node); /// Converts the given LLVM comdat struct to an MLIR comdat selector operation /// and stores a mapping from the struct to the symbol pointing to the @@ -326,8 +318,6 @@ Operation *constantInsertionOp = nullptr; /// Operation to insert the next global after. Operation *globalInsertionOp = nullptr; - /// Operation to insert metadata operations into. - MetadataOp globalMetadataOp = nullptr; /// Operation to insert comdat selector operations into. ComdatOp globalComdatOp = nullptr; /// The current context. @@ -352,9 +342,9 @@ /// Mapping between LLVM alias scope and domain metadata nodes and /// attributes in the LLVM dialect corresponding to these nodes. DenseMap aliasScopeMapping; - /// Mapping between LLVM TBAA metadata nodes and symbol references to the LLVM - /// dialect TBAA operations corresponding to these nodes. - DenseMap tbaaMapping; + /// Mapping between LLVM TBAA metadata nodes and LLVM dialect TBAA attributes + /// corresponding to these nodes. + DenseMap tbaaMapping; /// Mapping between LLVM comdat structs and symbol references to LLVM dialect /// comdat selector operations corresponding to these structs. DenseMap comdatMapping; diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h --- a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h +++ b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h @@ -282,9 +282,9 @@ /// metadata nodes for them and their domains. LogicalResult createAliasScopeMetadata(); - /// Returns the LLVM metadata corresponding to a symbol reference to an mlir - /// LLVM dialect TBAATagOp operation. - llvm::MDNode *getTBAANode(Operation *op, SymbolRefAttr tagRef) const; + /// Returns the LLVM metadata corresponding to the given mlir LLVM dialect + /// TBAATagAttr. + llvm::MDNode *getTBAANode(TBAATagAttr tbaaAttr) const; /// Process tbaa LLVM Metadata operations and create LLVM /// metadata nodes for them. @@ -332,9 +332,9 @@ /// This map is populated on module entry. DenseMap aliasScopeMetadataMapping; - /// Mapping from a tbaa metadata operation to its LLVM metadata. + /// Mapping from a tbaa attribute to its LLVM metadata. /// This map is populated on module entry. - DenseMap tbaaMetadataMapping; + DenseMap tbaaMetadataMapping; /// Mapping from a comdat selector operation to its LLVM comdat struct. /// This map is populated on module entry. diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp @@ -77,6 +77,14 @@ DIDerivedTypeAttr, DISubroutineTypeAttr>(attr); } +//===----------------------------------------------------------------------===// +// TBAANodeAttr +//===----------------------------------------------------------------------===// + +bool TBAANodeAttr::classof(Attribute attr) { + return llvm::isa(attr); +} + //===----------------------------------------------------------------------===// // MemoryEffectsAttr //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -2828,227 +2828,6 @@ printer.printRegion(getBody()); } -namespace { -// A node of the TBAA graph. -struct TBAAGraphNode { - // Symbol name defined by a TBAA operation. - StringRef symbol; - // Operands (if any) of the TBAA operation. - SmallVector operands; -}; - -// TBAA graph. -class TBAAGraph { -public: - using iterator = SmallVectorImpl::iterator; - - // Creates a new graph with nodes corresponding to `symbolNames` defined by a - // set of TBAA operations. - TBAAGraph(ArrayRef symbolNames) { - for (auto symbol : symbolNames) { - TBAAGraphNode &node = nodeMap[symbol]; - assert(node.symbol.empty() && "node is already in the graph"); - node.symbol = symbol; - } - - // Fill the graph operands once all nodes were added. Otherwise, - // reallocation can lead to pointer invalidation. - for (auto symbol : symbolNames) - root.operands.push_back(&nodeMap[symbol]); - } - - iterator begin() { return root.operands.begin(); } - iterator end() { return root.operands.end(); } - TBAAGraphNode *getEntryNode() { return &root; } - - // Get a pointer to TBAAGraphNode corresponding - // to `symbol`. The node must be already in the graph. - TBAAGraphNode *operator[](StringAttr symbol) { - auto it = nodeMap.find(symbol); - assert(it != nodeMap.end() && "node must be in the graph"); - return &it->second; - } - -private: - // Mapping between symbol names defined by TBAA - // operations and corresponding TBAAGraphNode's. - DenseMap nodeMap; - // Synthetic root node that has all graph nodes - // in its operands list. - TBAAGraphNode root; -}; -} // end anonymous namespace - -namespace llvm { -// GraphTraits definitions for using TBAAGraph with -// scc_iterator. -template <> -struct GraphTraits { - using NodeRef = TBAAGraphNode *; - using ChildIteratorType = SmallVectorImpl::iterator; - static ChildIteratorType child_begin(NodeRef ref) { - return ref->operands.begin(); - } - static ChildIteratorType child_end(NodeRef ref) { - return ref->operands.end(); - } -}; -template <> -struct GraphTraits : public GraphTraits { - static NodeRef getEntryNode(TBAAGraph *graph) { - return graph->getEntryNode(); - } - static ChildIteratorType nodes_begin(TBAAGraph *graph) { - return graph->begin(); - } - static ChildIteratorType nodes_end(TBAAGraph *graph) { return graph->end(); } -}; -} // end namespace llvm - -LogicalResult MetadataOp::verifyRegions() { - // Verify correctness of TBAA-related symbol references. - Region &body = getBody(); - // Symbol names defined by TBAARootMetadataOp and TBAATypeDescriptorOp. - llvm::SmallDenseSet definedGraphSymbols; - - // Collection of symbol names to ensure a stable ordering of the pointers. - // Otherwise, error messages might not be deterministic. - SmallVector symbolNames; - - for (Operation &op : body.getOps()) { - if (isa(op) || - isa(op)) { - StringAttr symbolDef = cast(op).getNameAttr(); - definedGraphSymbols.insert(symbolDef); - symbolNames.push_back(symbolDef); - } else if (auto tagOp = dyn_cast(op)) { - symbolNames.push_back(tagOp.getSymNameAttr()); - } - } - - // Complete TBAA graph consisting of TBAARootMetadataOp, - // TBAATypeDescriptorOp, and TBAATagOp symbols. It is used - // for detecting cycles in the TBAA graph, which is illegal. - TBAAGraph tbaaGraph(symbolNames); - - // Verify that TBAA metadata operations refer symbols - // from definedGraphSymbols only. Note that TBAATagOp - // cannot refer a symbol defined by TBAATagOp. - auto verifyReference = [&](Operation &op, StringAttr symbolName, - StringAttr referencingAttr) -> LogicalResult { - if (definedGraphSymbols.contains(symbolName)) - return success(); - return op.emitOpError() - << "expected " << referencingAttr << " to reference a symbol from '" - << (*this)->getName() << " @" << getSymName() - << "' defined by either '" - << LLVM::TBAARootMetadataOp::getOperationName() << "' or '" - << LLVM::TBAATypeDescriptorOp::getOperationName() - << "' while it references '@" << symbolName.getValue() << "'"; - }; - for (Operation &op : body.getOps()) { - if (auto tdOp = dyn_cast(op)) { - SmallVectorImpl &operands = - tbaaGraph[tdOp.getSymNameAttr()]->operands; - for (Attribute attr : tdOp.getMembers()) { - StringAttr symbolRef = llvm::cast(attr).getAttr(); - if (failed(verifyReference(op, symbolRef, tdOp.getMembersAttrName()))) - return failure(); - - // Since the reference is valid, we have to be able - // to find TBAAGraphNode corresponding to the operand. - operands.push_back(tbaaGraph[symbolRef]); - } - } - - if (auto tagOp = dyn_cast(op)) { - SmallVectorImpl &operands = - tbaaGraph[tagOp.getSymNameAttr()]->operands; - if (failed(verifyReference(op, tagOp.getBaseTypeAttr().getAttr(), - tagOp.getBaseTypeAttrName()))) - return failure(); - if (failed(verifyReference(op, tagOp.getAccessTypeAttr().getAttr(), - tagOp.getAccessTypeAttrName()))) - return failure(); - - operands.push_back(tbaaGraph[tagOp.getBaseTypeAttr().getAttr()]); - operands.push_back(tbaaGraph[tagOp.getAccessTypeAttr().getAttr()]); - } - } - - // Detect cycles in the TBAA graph. - for (llvm::scc_iterator sccIt = llvm::scc_begin(&tbaaGraph); - !sccIt.isAtEnd(); ++sccIt) { - if (!sccIt.hasCycle()) - continue; - auto diagOut = emitOpError() << "has cycle in TBAA graph (graph closure: <"; - llvm::interleaveComma( - *sccIt, diagOut, [&](TBAAGraphNode *node) { diagOut << node->symbol; }); - return diagOut << ">)"; - } - return success(); -} - -//===----------------------------------------------------------------------===// -// Utilities for TBAA related operations/attributes -//===----------------------------------------------------------------------===// - -static ParseResult parseTBAAMembers(OpAsmParser &parser, ArrayAttr &members, - DenseI64ArrayAttr &offsets) { - SmallVector membersVec; - SmallVector offsetsVec; - auto parseMembers = [&]() { - // Parse a pair of `<@tbaa_type_desc_sym, integer-offset>`. - FlatSymbolRefAttr member; - int64_t offset; - if (parser.parseLess() || parser.parseAttribute(member, Type()) || - parser.parseComma() || parser.parseInteger(offset) || - parser.parseGreater()) - return failure(); - - membersVec.push_back(member); - offsetsVec.push_back(offset); - return success(); - }; - - if (parser.parseCommaSeparatedList(parseMembers)) - return failure(); - - members = ArrayAttr::get(parser.getContext(), membersVec); - offsets = DenseI64ArrayAttr::get(parser.getContext(), offsetsVec); - return success(); -} - -static void printTBAAMembers(OpAsmPrinter &printer, - LLVM::TBAATypeDescriptorOp tdOp, ArrayAttr members, - DenseI64ArrayAttr offsets) { - llvm::interleaveComma( - llvm::zip(members, offsets.asArrayRef()), printer, [&](auto it) { - // Print `<@tbaa_type_desc_sym, integer-offset>`. - printer << '<' << std::get<0>(it) << ", " << std::get<1>(it) << '>'; - }); -} - -LogicalResult TBAARootMetadataOp::verify() { - if (!getIdentity().empty()) - return success(); - return emitOpError() << "expected non-empty " << getIdentityAttrName(); -} - -LogicalResult TBAATypeDescriptorOp::verify() { - // Verify that the members and offsets arrays have the same - // number of elements. - ArrayAttr members = getMembers(); - StringAttr membersName = getMembersAttrName(); - if (members.size() != getOffsets().size()) - return emitOpError() << "expected the same number of elements in " - << membersName << " and " << getOffsetsAttrName() - << ": " << members.size() - << " != " << getOffsets().size(); - - return success(); -} - //===----------------------------------------------------------------------===// // OpAsmDialectInterface //===----------------------------------------------------------------------===// @@ -3067,7 +2846,8 @@ LoopAnnotationAttr, LoopVectorizeAttr, LoopInterleaveAttr, LoopUnrollAttr, LoopUnrollAndJamAttr, LoopLICMAttr, LoopDistributeAttr, LoopPipelineAttr, LoopPeeledAttr, - LoopUnswitchAttr>([&](auto attr) { + LoopUnswitchAttr, TBAARootAttr, TBAATagAttr, + TBAATypeDescriptorAttr>([&](auto attr) { os << decltype(attr)::getMnemonic(); return AliasResult::OverridableAlias; }) diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMInterfaces.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMInterfaces.cpp --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMInterfaces.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMInterfaces.cpp @@ -16,71 +16,16 @@ using namespace mlir; using namespace mlir::LLVM; -/// Verifies the given array attribute contains symbol references and checks the -/// referenced symbol types using the provided verification function. -static LogicalResult -verifySymbolRefs(Operation *op, StringRef name, ArrayAttr symbolRefs, - llvm::function_ref - verifySymbolType) { - assert(symbolRefs && "expected a non-null attribute"); - - // Verify that the attribute is a symbol ref array attribute, - // because this constraint is not verified for all attribute - // names processed here (e.g. 'tbaa'). This verification - // is redundant in some cases. - if (!llvm::all_of(symbolRefs, [](Attribute attr) { - return attr && llvm::isa(attr); - })) - return op->emitOpError() << name - << " attribute failed to satisfy constraint: " - "symbol ref array attribute"; - - for (SymbolRefAttr symbolRef : symbolRefs.getAsRange()) { - StringAttr metadataName = symbolRef.getRootReference(); - StringAttr symbolName = symbolRef.getLeafReference(); - // We want @metadata::@symbol, not just @symbol - if (metadataName == symbolName) { - return op->emitOpError() << "expected '" << symbolRef - << "' to specify a fully qualified reference"; - } - auto metadataOp = SymbolTable::lookupNearestSymbolFrom( - op->getParentOp(), metadataName); - if (!metadataOp) - return op->emitOpError() - << "expected '" << symbolRef << "' to reference a metadata op"; - Operation *symbolOp = - SymbolTable::lookupNearestSymbolFrom(metadataOp, symbolName); - if (!symbolOp) - return op->emitOpError() - << "expected '" << symbolRef << "' to be a valid reference"; - if (failed(verifySymbolType(symbolOp, symbolRef))) { - return failure(); - } - } - +/// Verifies that all elements of `array` are instances of `Attr`. +template +static LogicalResult isArrayOf(Operation *op, ArrayAttr array) { + for (Attribute iter : array) + if (!isa(iter)) + return op->emitOpError("expected op to return array of ") + << AttrT::getMnemonic() << " attributes"; return success(); } -/// Verifies the given array attribute contains symbol references that point to -/// metadata operations of the given type. -template -LogicalResult verifySymbolRefsPointTo(Operation *op, StringRef name, - ArrayAttr symbolRefs) { - if (!symbolRefs) - return success(); - - auto verifySymbolType = [op](Operation *symbolOp, - SymbolRefAttr symbolRef) -> LogicalResult { - if (!isa(symbolOp)) { - return op->emitOpError() - << "expected '" << symbolRef << "' to resolve to a " - << OpTy::getOperationName(); - } - return success(); - }; - return verifySymbolRefs(op, name, symbolRefs, verifySymbolType); -} - //===----------------------------------------------------------------------===// // AccessGroupOpInterface //===----------------------------------------------------------------------===// @@ -90,11 +35,8 @@ ArrayAttr accessGroups = iface.getAccessGroupsOrNull(); if (!accessGroups) return success(); - for (Attribute iter : accessGroups) - if (!isa(iter)) - return op->emitOpError("expected op to return array of ") - << AccessGroupAttr::getMnemonic() << " attributes"; - return success(); + + return isArrayOf(op, accessGroups); } //===----------------------------------------------------------------------===// @@ -104,10 +46,20 @@ LogicalResult mlir::LLVM::detail::verifyAliasAnalysisOpInterface(Operation *op) { auto iface = cast(op); - if (failed(verifySymbolRefsPointTo( - iface, "tbaa tags", iface.getTBAATagsOrNull()))) - return failure(); - return success(); + + if (auto aliasScopes = iface.getAliasScopesOrNull()) + if (failed(isArrayOf(op, aliasScopes))) + return failure(); + + if (auto noAliasScopes = iface.getNoAliasScopesOrNull()) + if (failed(isArrayOf(op, noAliasScopes))) + return failure(); + + ArrayAttr tags = iface.getTBAATagsOrNull(); + if (!tags) + return success(); + + return isArrayOf(op, tags); } #include "mlir/Dialect/LLVMIR/LLVMInterfaces.cpp.inc" diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp --- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp @@ -134,12 +134,12 @@ .Default([](auto) { return failure(); }); } -/// Searches the symbol reference pointing to the metadata operation that -/// maps to the given TBAA metadata `node` and attaches it to the imported -/// operation if the lookup succeeds. Returns failure otherwise. +/// Searches for the attribute that maps to the given TBAA metadata `node` and +/// attaches it to the imported operation if the lookup succeeds. Returns +/// failure otherwise. static LogicalResult setTBAAAttr(const llvm::MDNode *node, Operation *op, LLVM::ModuleImport &moduleImport) { - SymbolRefAttr tbaaTagSym = moduleImport.lookupTBAAAttr(node); + Attribute tbaaTagSym = moduleImport.lookupTBAAAttr(node); if (!tbaaTagSym) return failure(); @@ -151,10 +151,9 @@ return success(); } -/// Looks up all the symbol references pointing to the access group operations -/// that map to the access group nodes starting from the access group metadata -/// `node`, and attaches all of them to the imported operation if the lookups -/// succeed. Returns failure otherwise. +/// Looks up all the access group attributes that map to the access group nodes +/// starting from the access group metadata `node`, and attaches all of them to +/// the imported operation if the lookups succeed. Returns failure otherwise. static LogicalResult setAccessGroupsAttr(const llvm::MDNode *node, Operation *op, LLVM::ModuleImport &moduleImport) { @@ -209,10 +208,9 @@ return success(); } -/// Looks up all the symbol references pointing to the alias scope operations -/// that map to the alias scope nodes starting from the noalias metadata `node`, -/// and attaches all of them to the imported operation if the lookups succeed. -/// Returns failure otherwise. +/// Looks up all the alias scope attributes that map to the alias scope nodes +/// starting from the noalias metadata `node`, and attaches all of them to the +/// imported operation if the lookups succeed. Returns failure otherwise. static LogicalResult setNoaliasScopesAttr(const llvm::MDNode *node, Operation *op, LLVM::ModuleImport &moduleImport) { diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -76,12 +76,6 @@ return "llvm.global_dtors"; } -/// Returns the symbol name for the module-level metadata operation. It must not -/// conflict with the user namespace. -static constexpr StringRef getGlobalMetadataOpName() { - return "__llvm_global_metadata"; -} - /// Returns the symbol name for the module-level comdat operation. It must not /// conflict with the user namespace. static constexpr StringRef getGlobalComdatOpName() { @@ -166,18 +160,6 @@ builder.setInsertionPointToStart(mlirModule.getBody()); } -MetadataOp ModuleImport::getGlobalMetadataOp() { - if (globalMetadataOp) - return globalMetadataOp; - - OpBuilder::InsertionGuard guard(builder); - builder.setInsertionPointToEnd(mlirModule.getBody()); - globalMetadataOp = builder.create(mlirModule.getLoc(), - getGlobalMetadataOpName()); - globalInsertionOp = globalMetadataOp; - return globalMetadataOp; -} - ComdatOp ModuleImport::getGlobalComdatOp() { if (globalComdatOp) return globalComdatOp; @@ -192,34 +174,21 @@ LogicalResult ModuleImport::processTBAAMetadata(const llvm::MDNode *node) { Location loc = mlirModule.getLoc(); - SmallVector workList; - SetVector nodesToConvert; - workList.push_back(node); - while (!workList.empty()) { - const llvm::MDNode *current = workList.pop_back_val(); - if (tbaaMapping.contains(current)) - continue; - // Allow cycles in TBAA metadata. Just import it as-is, - // and diagnose the problem during LLVMIR dialect verification. - if (!nodesToConvert.insert(current)) - continue; - for (const llvm::MDOperand &operand : current->operands()) - if (auto *opNode = dyn_cast_or_null(operand.get())) - workList.push_back(opNode); - } - // If `node` is a valid TBAA root node, then return its identity - // string, otherwise return std::nullopt. + // If `node` is a valid TBAA root node, then return its optional identity + // string, otherwise return failure. auto getIdentityIfRootNode = - [&](const llvm::MDNode *node) -> std::optional { + [&](const llvm::MDNode *node) -> FailureOr> { // Root node, e.g.: // !0 = !{!"Simple C/C++ TBAA"} - if (node->getNumOperands() != 1) - return std::nullopt; + // !1 = !{} + if (node->getNumOperands() > 1) + return failure(); // If the operand is MDString, then assume that this is a root node. - if (const auto *op0 = dyn_cast(node->getOperand(0))) - return op0->getString(); - return std::nullopt; + if (node->getNumOperands() == 1) + if (const auto *op0 = dyn_cast(node->getOperand(0))) + return std::optional{op0->getString()}; + return std::optional{}; }; // If `node` looks like a TBAA type descriptor metadata, @@ -229,11 +198,10 @@ // If `identity` and `memberTypes/Offsets` are non-null, then they will // contain the converted metadata operands for a valid TBAA node (i.e. when // true is returned). - auto isTypeDescriptorNode = - [&](const llvm::MDNode *node, StringRef *identity = nullptr, - SmallVectorImpl *memberTypes = nullptr, - SmallVectorImpl *memberOffsets = - nullptr) -> std::optional { + auto isTypeDescriptorNode = [&](const llvm::MDNode *node, + StringRef *identity = nullptr, + SmallVectorImpl *members = + nullptr) -> std::optional { unsigned numOperands = node->getNumOperands(); // Type descriptor, e.g.: // !1 = !{!"int", !0, /*optional*/i64 0} /* scalar int type */ @@ -280,10 +248,9 @@ offset = offsetCI->getZExtValue(); } - if (memberTypes) - memberTypes->push_back(tbaaMapping.lookup(memberNode)); - if (memberOffsets) - memberOffsets->push_back(offset); + if (members) + members->push_back(TBAAMemberAttr::get( + cast(tbaaMapping.lookup(memberNode)), offset)); } return true; @@ -296,10 +263,11 @@ // If the other arguments are non-null, then they will contain // the converted metadata operands for a valid TBAA node (i.e. when true is // returned). - auto isTagNode = - [&](const llvm::MDNode *node, SymbolRefAttr *baseSymRef = nullptr, - SymbolRefAttr *accessSymRef = nullptr, int64_t *offset = nullptr, - bool *isConstant = nullptr) -> std::optional { + auto isTagNode = [&](const llvm::MDNode *node, + TBAATypeDescriptorAttr *baseAttr = nullptr, + TBAATypeDescriptorAttr *accessAttr = nullptr, + int64_t *offset = nullptr, + bool *isConstant = nullptr) -> std::optional { // Access tag, e.g.: // !3 = !{!1, !1, i64 0} /* scalar int access */ // !4 = !{!2, !1, i64 0} /* agg_t::x access */ @@ -335,10 +303,10 @@ } isConst = isConstantCI->getValue()[0]; } - if (baseSymRef) - *baseSymRef = tbaaMapping.lookup(baseMD); - if (accessSymRef) - *accessSymRef = tbaaMapping.lookup(accessMD); + if (baseAttr) + *baseAttr = cast(tbaaMapping.lookup(baseMD)); + if (accessAttr) + *accessAttr = cast(tbaaMapping.lookup(accessMD)); if (offset) *offset = offsetCI->getZExtValue(); if (isConstant) @@ -346,88 +314,84 @@ return true; }; - // Helper to compute a unique symbol name that includes the given `baseName`. - // Uses the size of the mapping to unique the symbol name. - auto getUniqueSymbolName = [&](StringRef baseName) { - return (Twine("tbaa_") + Twine(baseName) + Twine('_') + - Twine(tbaaMapping.size())) - .str(); - }; + // Do a post-order walk over the TBAA Graph. Since a correct TBAA Graph is a + // DAG, a post-order walk guarantees that we convert any metadata node we + // depend on, prior to converting the current node. + DenseSet seen; + SmallVector workList; + workList.push_back(node); + while (!workList.empty()) { + const llvm::MDNode *current = workList.back(); + if (tbaaMapping.contains(current)) { + // Already converted. Just pop from the worklist. + workList.pop_back(); + continue; + } - // Insert new operations at the end of the MetadataOp. - OpBuilder::InsertionGuard guard(builder); - builder.setInsertionPointToEnd(&getGlobalMetadataOp().getBody().back()); - StringAttr metadataOpName = SymbolTable::getSymbolName(getGlobalMetadataOp()); - - // On the first walk, create SymbolRefAttr's and map them - // to nodes in `nodesToConvert`. - for (const auto *current : nodesToConvert) { - if (std::optional identity = getIdentityIfRootNode(current)) { - if (identity.value().empty()) - return emitError(loc) << "TBAA root node must have non-empty identity: " + // If any child of this node is not yet converted, don't pop the current + // node from the worklist but push the not-yet-converted children in the + // front of the worklist. + bool anyChildNotConverted = false; + for (const llvm::MDOperand &operand : current->operands()) + if (auto *childNode = dyn_cast_or_null(operand.get())) + if (!tbaaMapping.contains(childNode)) { + workList.push_back(childNode); + anyChildNotConverted = true; + } + + if (anyChildNotConverted) { + // If this is the second time we failed to convert an element in the + // worklist it must be because a child is dependent on it being converted + // and we have a cycle in the graph. Cycles are not allowed in TBAA + // graphs. + if (!seen.insert(current).second) + return emitError(loc) << "has cycle in TBAA graph: " << diagMD(current, llvmModule.get()); - // The root nodes do not have operands, so we can create - // the TBAARootMetadataOp on the first walk. - auto rootNode = builder.create( - loc, getUniqueSymbolName("root"), identity.value()); - tbaaMapping.try_emplace(current, FlatSymbolRefAttr::get(rootNode)); - continue; - } - if (std::optional isValid = isTypeDescriptorNode(current)) { - if (!isValid.value()) - return failure(); - tbaaMapping.try_emplace( - current, FlatSymbolRefAttr::get(builder.getContext(), - getUniqueSymbolName("type_desc"))); continue; } - if (std::optional isValid = isTagNode(current)) { - if (!isValid.value()) - return failure(); - // TBAATagOp symbols must be referred by their fully qualified - // names, so create a path to TBAATagOp symbol. - tbaaMapping.try_emplace( - current, SymbolRefAttr::get( - builder.getContext(), metadataOpName, - FlatSymbolRefAttr::get(builder.getContext(), - getUniqueSymbolName("tag")))); + + // Otherwise simply import the current node. + workList.pop_back(); + + FailureOr> rootNodeIdentity = + getIdentityIfRootNode(current); + if (succeeded(rootNodeIdentity)) { + StringAttr stringAttr = *rootNodeIdentity + ? builder.getStringAttr(**rootNodeIdentity) + : nullptr; + // The root nodes do not have operands, so we can create + // the TBAARootMetadataOp on the first walk. + tbaaMapping.insert({current, builder.getAttr(stringAttr)}); continue; } - return emitError(loc) << "unsupported TBAA node format: " - << diagMD(current, llvmModule.get()); - } - // On the second walk, create TBAA operations using the symbol names from the - // map. - for (const auto *current : nodesToConvert) { StringRef identity; - SmallVector memberTypes; - SmallVector memberOffsets; - if (std::optional isValid = isTypeDescriptorNode( - current, &identity, &memberTypes, &memberOffsets)) { + SmallVector members; + if (std::optional isValid = + isTypeDescriptorNode(current, &identity, &members)) { assert(isValid.value() && "type descriptor node must be valid"); - builder.create( - loc, tbaaMapping.lookup(current).getLeafReference(), - builder.getStringAttr(identity), builder.getArrayAttr(memberTypes), - memberOffsets); + tbaaMapping.insert({current, builder.getAttr( + identity, members)}); continue; } - SymbolRefAttr baseSymRef, accessSymRef; + + TBAATypeDescriptorAttr baseAttr, accessAttr; int64_t offset; bool isConstant; - if (std::optional isValid = isTagNode( - current, &baseSymRef, &accessSymRef, &offset, &isConstant)) { + if (std::optional isValid = + isTagNode(current, &baseAttr, &accessAttr, &offset, &isConstant)) { assert(isValid.value() && "access tag node must be valid"); - builder.create( - loc, tbaaMapping.lookup(current).getLeafReference(), - baseSymRef.getLeafReference(), accessSymRef.getLeafReference(), - offset, isConstant); + tbaaMapping.insert( + {current, builder.getAttr(baseAttr, accessAttr, offset, + isConstant)}); continue; } - } + return emitError(loc) << "unsupported TBAA node format: " + << diagMD(current, llvmModule.get()); + } return success(); } diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp --- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp @@ -1159,14 +1159,8 @@ llvm::LLVMContext::MD_noalias); } -llvm::MDNode *ModuleTranslation::getTBAANode(Operation *op, - SymbolRefAttr tagRef) const { - StringAttr metadataName = tagRef.getRootReference(); - StringAttr tagName = tagRef.getLeafReference(); - auto metadataOp = SymbolTable::lookupNearestSymbolFrom( - op->getParentOp(), metadataName); - Operation *tagOp = SymbolTable::lookupNearestSymbolFrom(metadataOp, tagName); - return tbaaMetadataMapping.lookup(tagOp); +llvm::MDNode *ModuleTranslation::getTBAANode(TBAATagAttr tbaaAttr) const { + return tbaaMetadataMapping.lookup(tbaaAttr); } void ModuleTranslation::setTBAAMetadata(AliasAnalysisOpInterface op, @@ -1185,8 +1179,7 @@ return; } - SymbolRefAttr tagRef = cast(tagRefs[0]); - llvm::MDNode *node = getTBAANode(op, tagRef); + llvm::MDNode *node = getTBAANode(cast(tagRefs[0])); inst->setMetadata(llvm::LLVMContext::MD_tbaa, node); } @@ -1194,90 +1187,51 @@ llvm::LLVMContext &ctx = llvmModule->getContext(); llvm::IntegerType *offsetTy = llvm::IntegerType::get(ctx, 64); - // Walk TBAA metadata and create MDNode's with placeholder - // operands for the references of other TBAA nodes. - for (auto metadata : getModuleBody(mlirModule).getOps()) { - for (auto &op : metadata.getBody().getOps()) { - SmallVector operands; - if (auto rootOp = dyn_cast(op)) { - operands.push_back(llvm::MDString::get(ctx, rootOp.getIdentity())); - } else if (auto tdOp = dyn_cast(op)) { - operands.push_back(llvm::MDString::get( - ctx, tdOp.getIdentity().value_or(llvm::StringRef{}))); - for (int64_t offset : tdOp.getOffsets()) { - // Use temporary MDNode as the placeholder for the member type - // to prevent uniquing the type descriptor nodes until they are - // finalized. - operands.push_back( - llvm::MDNode::getTemporary(ctx, std::nullopt).release()); - operands.push_back(llvm::ConstantAsMetadata::get( - llvm::ConstantInt::get(offsetTy, offset))); - } - } else if (auto tagOp = dyn_cast(op)) { - // Use temporary MDNode's as the placeholders for the base and access - // types to prevent uniquing the tag nodes until they are finalized. - operands.push_back( - llvm::MDNode::getTemporary(ctx, std::nullopt).release()); - operands.push_back( - llvm::MDNode::getTemporary(ctx, std::nullopt).release()); - operands.push_back(llvm::ConstantAsMetadata::get( - llvm::ConstantInt::get(offsetTy, tagOp.getOffset()))); - if (tagOp.getConstant()) - operands.push_back(llvm::ConstantAsMetadata::get( - llvm::ConstantInt::get(offsetTy, 1))); - } - - if (operands.empty()) - continue; + // Walk the entire module and create all metadata nodes for the TBAA + // attributes. The code below relies on two invariants of the + // `AttrTypeWalker`: + // 1. Attributes are visited in post-order: Since the attributes create a DAG, + // this ensures that any lookups into `tbaaMetadataMapping` for child + // attributes succeed. + // 2. Attributes are only ever visited once: This way we don't leak any + // LLVM metadata instances. + AttrTypeWalker walker; + walker.addWalk([&](TBAARootAttr root) { + tbaaMetadataMapping.insert( + {root, llvm::MDNode::get(ctx, llvm::MDString::get(ctx, root.getId()))}); + }); - tbaaMetadataMapping.insert({&op, llvm::MDNode::get(ctx, operands)}); + walker.addWalk([&](TBAATypeDescriptorAttr descriptor) { + SmallVector operands; + operands.push_back(llvm::MDString::get(ctx, descriptor.getId())); + for (TBAAMemberAttr member : descriptor.getMembers()) { + operands.push_back(tbaaMetadataMapping.lookup(member.getTypeDesc())); + operands.push_back(llvm::ConstantAsMetadata::get( + llvm::ConstantInt::get(offsetTy, member.getOffset()))); } - } - // Walk TBAA metadata second time and update the placeholder - // references. - for (auto metadata : getModuleBody(mlirModule).getOps()) { - for (auto &op : metadata.getBody().getOps()) { - SmallVector refNames; - SmallVector operandIndices; - if (auto tdOp = dyn_cast(op)) { - // The type references are in 1, 3, 5, etc. positions. - unsigned opNum = 1; - for (Attribute typeAttr : tdOp.getMembers()) { - refNames.push_back(cast(typeAttr).getValue()); - operandIndices.push_back(opNum); - opNum += 2; - } - } else if (auto tagOp = dyn_cast(op)) { - refNames.push_back(tagOp.getBaseType()); - operandIndices.push_back(0); - refNames.push_back(tagOp.getAccessType()); - operandIndices.push_back(1); - } + tbaaMetadataMapping.insert({descriptor, llvm::MDNode::get(ctx, operands)}); + }); - if (refNames.empty()) - continue; + walker.addWalk([&](TBAATagAttr tag) { + SmallVector operands; - llvm::MDNode *descNode = tbaaMetadataMapping.lookup(&op); - for (auto [refName, opNum] : llvm::zip(refNames, operandIndices)) { - // refDef availability in the parent MetadataOp - // is checked by module verifier. - Operation *refDef = SymbolTable::lookupSymbolIn(metadata, refName); - llvm::MDNode *refNode = tbaaMetadataMapping.lookup(refDef); - if (!refNode) { - op.emitOpError() << "llvm::MDNode missing for the member '@" - << refName << "'"; - return failure(); - } - auto *tempMD = cast(descNode->getOperand(opNum).get()); - descNode->replaceOperandWith(opNum, refNode); - // Deallocate temporary MDNode's explicitly. - // Note that each temporary node has a single use by creation, - // so it is valid to deallocate it here. - llvm::MDNode::deleteTemporary(tempMD); - } - } - } + operands.push_back(tbaaMetadataMapping.lookup(tag.getBaseType())); + operands.push_back(tbaaMetadataMapping.lookup(tag.getAccessType())); + + operands.push_back(llvm::ConstantAsMetadata::get( + llvm::ConstantInt::get(offsetTy, tag.getOffset()))); + if (tag.getConstant()) + operands.push_back( + llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(offsetTy, 1))); + + tbaaMetadataMapping.insert({tag, llvm::MDNode::get(ctx, operands)}); + }); + + mlirModule->walk([&](AliasAnalysisOpInterface analysisOpInterface) { + if (auto attr = analysisOpInterface.getTBAATagsOrNull()) + walker.walk(attr); + }); return success(); } diff --git a/mlir/test/Dialect/LLVMIR/tbaa-invalid.mlir b/mlir/test/Dialect/LLVMIR/tbaa-invalid.mlir --- a/mlir/test/Dialect/LLVMIR/tbaa-invalid.mlir +++ b/mlir/test/Dialect/LLVMIR/tbaa-invalid.mlir @@ -1,169 +1,27 @@ // RUN: mlir-opt -split-input-file -verify-diagnostics %s -module { - llvm.metadata @__tbaa { - llvm.tbaa_root @tbaa_root_0 {id = "Simple C/C++ TBAA"} - llvm.tbaa_tag @tbaa_tag_1 {access_type = @tbaa_root_0, base_type = @tbaa_root_0, offset = 0 : i64} - } - llvm.func @tbaa(%arg0: !llvm.ptr) { - %0 = llvm.mlir.constant(1 : i8) : i8 - // expected-error@below {{expected '@tbaa_tag_1' to specify a fully qualified reference}} - llvm.store %0, %arg0 {tbaa = [@tbaa_tag_1]} : i8, !llvm.ptr - llvm.return - } -} +#tbaa_root = #llvm.tbaa_root +#tbaa_desc = #llvm.tbaa_type_desc}> +#tbaa_tag = #llvm.tbaa_tag +// expected-error@+2 {{invalid kind of attribute specified}} +// expected-error@below {{failed to parse LLVM_TBAATagAttr parameter 'access_type' which is to be a `TBAATypeDescriptorAttr`}} +#tbaa_tag2 = #llvm.tbaa_tag // ----- -llvm.func @tbaa(%arg0: !llvm.ptr) { - %0 = llvm.mlir.constant(1 : i8) : i8 - // expected-error@below {{attribute 'tbaa' failed to satisfy constraint: symbol ref array attribute}} - llvm.store %0, %arg0 {tbaa = ["sym"]} : i8, !llvm.ptr - llvm.return -} +#tbaa_root = #llvm.tbaa_root +#tbaa_desc = #llvm.tbaa_type_desc}> +#tbaa_tag = #llvm.tbaa_tag +// expected-error@+2 {{invalid kind of attribute specified}} +// expected-error@below {{failed to parse LLVM_TBAATagAttr parameter 'base_type' which is to be a `TBAATypeDescriptorAttr`}} +#tbaa_tag2 = #llvm.tbaa_tag // ----- -module { - llvm.func @tbaa(%arg0: !llvm.ptr) { - %0 = llvm.mlir.constant(1 : i8) : i8 - // expected-error@below {{expected '@metadata::@group1' to resolve to a llvm.tbaa_tag}} - llvm.store %0, %arg0 {tbaa = [@metadata::@group1]} : i8, !llvm.ptr - llvm.return - } - llvm.metadata @metadata { - llvm.func @group1() - } -} - -// ----- - -module { - llvm.func @tbaa(%arg0: !llvm.ptr) { - %0 = llvm.mlir.constant(1 : i8) : i8 - // expected-error@below {{expected '@metadata::@sym' to be a valid reference}} - llvm.store %0, %arg0 {tbaa = [@metadata::@sym]} : i8, !llvm.ptr - llvm.return - } - llvm.metadata @metadata { - } -} - -// ----- - -llvm.func @tbaa(%arg0: !llvm.ptr) { - %0 = llvm.mlir.constant(1 : i8) : i8 - // expected-error@below {{expected '@tbaa::@sym' to reference a metadata op}} - llvm.store %0, %arg0 {tbaa = [@tbaa::@sym]} : i8, !llvm.ptr - llvm.return -} - -// ----- - -llvm.func @tbaa() { - // expected-error@below {{expects parent op 'llvm.metadata'}} - llvm.tbaa_root @tbaa_root_0 {id = "Simple C/C++ TBAA"} - llvm.return -} - -// ----- - -module { - llvm.metadata @__tbaa { - llvm.tbaa_root @tbaa_root_0 {id = "Simple C/C++ TBAA"} - } - - llvm.func @tbaa() { - // expected-error@below {{expects parent op 'llvm.metadata'}} - llvm.tbaa_type_desc @tbaa_type_desc_1 {id = "omnipotent char", members = {<@tbaa_root_0, 0>}} - llvm.return - } -} - -// ----- - -module { - llvm.metadata @__tbaa { - llvm.tbaa_root @tbaa_root_0 {id = "Simple C/C++ TBAA"} - } - - llvm.func @tbaa() { - // expected-error@below {{expects parent op 'llvm.metadata'}} - llvm.tbaa_tag @tbaa_tag_1 {access_type = @tbaa_root_0, base_type = @tbaa_root_0, offset = 0 : i64} - llvm.return - } -} - -// ----- - -module { - llvm.metadata @__tbaa { - // expected-error@below {{expected non-empty "identity"}} - llvm.tbaa_root @tbaa_root_0 {id = ""} - } -} - -// ----- - - "builtin.module"() ({ - "llvm.metadata"() ({ - "llvm.tbaa_root"() {identity = "Simple C/C++ TBAA", sym_name = "tbaa_root_0"} : () -> () - "llvm.tbaa_type_desc"() {identity = "omnipotent char", members = [@tbaa_root_0], offsets = array, sym_name = "tbaa_type_desc_1"} : () -> () - // expected-error@below {{expected the same number of elements in "members" and "offsets": 2 != 1}} - "llvm.tbaa_type_desc"() {identity = "agg_t", members = [@tbaa_type_desc_1, @tbaa_type_desc_1], offsets = array, sym_name = "tbaa_type_desc_2"} : () -> () - }) {sym_name = "__tbaa"} : () -> () - }) : () -> () - -// ----- - -module { - llvm.metadata @__tbaa { - llvm.tbaa_root @tbaa_root_0 {id = "Simple C/C++ TBAA"} - // expected-error@below {{expected "base_type" to reference a symbol from 'llvm.metadata @__tbaa' defined by either 'llvm.tbaa_root' or 'llvm.tbaa_type_desc' while it references '@tbaa_root_2'}} - llvm.tbaa_tag @tbaa_tag_1 {access_type = @tbaa_root_0, base_type = @tbaa_root_2, offset = 0 : i64} - } -} - -// ----- - -module { - llvm.metadata @__tbaa { - llvm.tbaa_root @tbaa_root_0 {id = "Simple C/C++ TBAA"} - // expected-error@below {{expected "access_type" to reference a symbol from 'llvm.metadata @__tbaa' defined by either 'llvm.tbaa_root' or 'llvm.tbaa_type_desc' while it references '@tbaa_root_2'}} - llvm.tbaa_tag @tbaa_tag_1 {access_type = @tbaa_root_2, base_type = @tbaa_root_0, offset = 0 : i64} - } -} - -// ----- - -module { - llvm.metadata @__tbaa { - llvm.tbaa_root @tbaa_root_0 {id = "Simple C/C++ TBAA"} - llvm.tbaa_type_desc @tbaa_type_desc_1 {id = "omnipotent char", members = {<@tbaa_root_0, 0>}} - llvm.tbaa_type_desc @tbaa_type_desc_2 {id = "long long", members = {<@tbaa_type_desc_1, 0>}} - // expected-error@below {{expected "members" to reference a symbol from 'llvm.metadata @__tbaa' defined by either 'llvm.tbaa_root' or 'llvm.tbaa_type_desc' while it references '@tbaa_type_desc_4'}} - llvm.tbaa_type_desc @tbaa_type_desc_3 {id = "agg2_t", members = {<@tbaa_type_desc_2, 0>, <@tbaa_type_desc_4, 8>}} - } -} - -// ----- - -module { - llvm.metadata @__tbaa { - llvm.tbaa_root @tbaa_root_0 {id = "Simple C/C++ TBAA"} - llvm.tbaa_tag @tbaa_tag_1 {access_type = @tbaa_root_0, base_type = @tbaa_root_0, offset = 0 : i64} - // expected-error@below {{expected "access_type" to reference a symbol from 'llvm.metadata @__tbaa' defined by either 'llvm.tbaa_root' or 'llvm.tbaa_type_desc' while it references '@tbaa_tag_1'}} - llvm.tbaa_tag @tbaa_tag_2 {access_type = @tbaa_tag_1, base_type = @tbaa_root_0, offset = 0 : i64} - } -} - -// ----- - -module { - // expected-error@below {{has cycle in TBAA graph (graph closure: )}} - llvm.metadata @__tbaa { - llvm.tbaa_root @tbaa_root_0 {id = "Simple C/C++ TBAA"} - llvm.tbaa_type_desc @tbaa_type_desc_1 {id = "omnipotent char", members = {<@tbaa_type_desc_2, 0>}} - llvm.tbaa_type_desc @tbaa_type_desc_2 {id = "long long", members = {<@tbaa_type_desc_1, 0>}} - } -} +#tbaa_root = #llvm.tbaa_root +#tbaa_desc = #llvm.tbaa_type_desc}> +#tbaa_tag = #llvm.tbaa_tag +// expected-error@+3 {{invalid kind of attribute specified}} +// expected-error@+2 {{failed to parse LLVM_TBAAMemberAttr parameter 'typeDesc' which is to be a `TBAANodeAttr`}} +// expected-error@below {{failed to parse LLVM_TBAATypeDescriptorAttr parameter 'members' which is to be a `::llvm::ArrayRef`}} +#tbaa_desc2 = #llvm.tbaa_type_desc}> diff --git a/mlir/test/Dialect/LLVMIR/tbaa-roundtrip.mlir b/mlir/test/Dialect/LLVMIR/tbaa-roundtrip.mlir --- a/mlir/test/Dialect/LLVMIR/tbaa-roundtrip.mlir +++ b/mlir/test/Dialect/LLVMIR/tbaa-roundtrip.mlir @@ -1,99 +1,94 @@ // RUN: mlir-opt %s | mlir-opt | FileCheck %s -module { - llvm.metadata @__tbaa { - llvm.tbaa_root @tbaa_root_0 {id = "Simple C/C++ TBAA"} - llvm.tbaa_tag @tbaa_tag_1 {access_type = @tbaa_root_0, base_type = @tbaa_root_0, offset = 0 : i64} - llvm.tbaa_root @tbaa_root_2 {id = "Other language TBAA"} - llvm.tbaa_tag @tbaa_tag_3 {access_type = @tbaa_root_2, base_type = @tbaa_root_2, offset = 0 : i64} - } - llvm.func @tbaa1(%arg0: !llvm.ptr, %arg1: !llvm.ptr) { - %0 = llvm.mlir.constant(1 : i8) : i8 - llvm.store %0, %arg0 {tbaa = [@__tbaa::@tbaa_tag_1]} : i8, !llvm.ptr - llvm.store %0, %arg1 {tbaa = [@__tbaa::@tbaa_tag_3]} : i8, !llvm.ptr - llvm.return - } +#tbaa_root_0 = #llvm.tbaa_root +#tbaa_root_1 = #llvm.tbaa_root +#tbaa_root_2 = #llvm.tbaa_root +#tbaa_type_desc_0 = #llvm.tbaa_type_desc}> +#tbaa_tag_0 = #llvm.tbaa_tag +#tbaa_type_desc_1 = #llvm.tbaa_type_desc}> +#tbaa_type_desc_2 = #llvm.tbaa_type_desc}> +#tbaa_type_desc_3 = #llvm.tbaa_type_desc, <#tbaa_type_desc_1, 8>}> +#tbaa_type_desc_4 = #llvm.tbaa_type_desc, <#tbaa_type_desc_2, 4>}> +#tbaa_tag_2 = #llvm.tbaa_tag +#tbaa_tag_3 = #llvm.tbaa_tag +#tbaa_type_desc_5 = #llvm.tbaa_type_desc}> +#tbaa_type_desc_6 = #llvm.tbaa_type_desc}> +#tbaa_tag_4 = #llvm.tbaa_tag +#tbaa_tag_1 = #llvm.tbaa_tag + +// CHECK-DAG: #[[$ROOT_0:.*]] = #llvm.tbaa_root +// CHECK-DAG: #[[$ROOT_1:.*]] = #llvm.tbaa_root +// CHECK-DAG: #[[$ROOT_2:.*]] = #llvm.tbaa_root +// CHECK-NOT: <{{.*}}> +// CHECK-DAG: #[[$DESC_0:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[$DESC_1:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[$DESC_2:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[$DESC_3:.*]] = #llvm.tbaa_type_desc, <#[[$DESC_1]], 8>}> +// CHECK-DAG: #[[$DESC_4:.*]] = #llvm.tbaa_type_desc, <#[[$DESC_2]], 4>}> +// CHECK-DAG: #[[$DESC_5:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[$DESC_6:.*]] = #llvm.tbaa_type_desc}> +// CHECK-DAG: #[[$TAG_0:.*]] = #llvm.tbaa_tag +// CHECK-DAG: #[[$TAG_1:.*]] = #llvm.tbaa_tag +// CHECK-DAG: #[[$TAG_2:.*]] = #llvm.tbaa_tag +// CHECK-DAG: #[[$TAG_3:.*]] = #llvm.tbaa_tag +// CHECK-DAG: #[[$TAG_4:.*]] = #llvm.tbaa_tag + +llvm.func @tbaa1(%arg0: !llvm.ptr, %arg1: !llvm.ptr) { + %0 = llvm.mlir.constant(1 : i8) : i8 + llvm.store %0, %arg0 {tbaa = [#tbaa_tag_0]} : i8, !llvm.ptr + llvm.store %0, %arg1 {tbaa = [#tbaa_tag_1]} : i8, !llvm.ptr + llvm.return } -// CHECK-LABEL: llvm.metadata @__tbaa { -// CHECK: llvm.tbaa_root @tbaa_root_0 {id = "Simple C/C++ TBAA"} -// CHECK: llvm.tbaa_tag @tbaa_tag_1 {access_type = @tbaa_root_0, base_type = @tbaa_root_0, offset = 0 : i64} -// CHECK: llvm.tbaa_root @tbaa_root_2 {id = "Other language TBAA"} -// CHECK: llvm.tbaa_tag @tbaa_tag_3 {access_type = @tbaa_root_2, base_type = @tbaa_root_2, offset = 0 : i64} -// CHECK: } // CHECK: llvm.func @tbaa1(%[[VAL_0:.*]]: !llvm.ptr, %[[VAL_1:.*]]: !llvm.ptr) { // CHECK: %[[VAL_2:.*]] = llvm.mlir.constant(1 : i8) : i8 -// CHECK: llvm.store %[[VAL_2]], %[[VAL_0]] {tbaa = [@__tbaa::@tbaa_tag_1]} : i8, !llvm.ptr -// CHECK: llvm.store %[[VAL_2]], %[[VAL_1]] {tbaa = [@__tbaa::@tbaa_tag_3]} : i8, !llvm.ptr +// CHECK: llvm.store %[[VAL_2]], %[[VAL_0]] {tbaa = [#[[$TAG_0]]]} : i8, !llvm.ptr +// CHECK: llvm.store %[[VAL_2]], %[[VAL_1]] {tbaa = [#[[$TAG_1]]]} : i8, !llvm.ptr // CHECK: llvm.return // CHECK: } -module { - llvm.metadata @__tbaa { - llvm.tbaa_root @tbaa_root_0 {id = "Simple C/C++ TBAA"} - llvm.tbaa_type_desc @tbaa_type_desc_1 {id = "omnipotent char", members = {<@tbaa_root_0, 0>}} - llvm.tbaa_type_desc @tbaa_type_desc_2 {id = "long long", members = {<@tbaa_type_desc_1, 0>}} - llvm.tbaa_type_desc @tbaa_type_desc_3 {id = "agg2_t", members = {<@tbaa_type_desc_2, 0>, <@tbaa_type_desc_2, 8>}} - llvm.tbaa_tag @tbaa_tag_4 {access_type = @tbaa_type_desc_2, base_type = @tbaa_type_desc_3, offset = 8 : i64} - llvm.tbaa_type_desc @tbaa_type_desc_5 {id = "int", members = {<@tbaa_type_desc_1, 0>}} - llvm.tbaa_type_desc @tbaa_type_desc_6 {id = "agg1_t", members = {<@tbaa_type_desc_5, 0>, <@tbaa_type_desc_5, 4>}} - llvm.tbaa_tag @tbaa_tag_7 {access_type = @tbaa_type_desc_5, base_type = @tbaa_type_desc_6, offset = 0 : i64} - } - llvm.func @tbaa2(%arg0: !llvm.ptr, %arg1: !llvm.ptr) { - %0 = llvm.mlir.constant(0 : i32) : i32 - %1 = llvm.mlir.constant(1 : i32) : i32 - %2 = llvm.getelementptr inbounds %arg1[%0, 1] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<"struct.agg2_t", (i64, i64)> - %3 = llvm.load %2 {tbaa = [@__tbaa::@tbaa_tag_4]} : !llvm.ptr -> i64 - %4 = llvm.trunc %3 : i64 to i32 - %5 = llvm.getelementptr inbounds %arg0[%0, 0] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<"struct.agg1_t", (i32, i32)> - llvm.store %4, %5 {tbaa = [@__tbaa::@tbaa_tag_7]} : i32, !llvm.ptr - llvm.return - } +llvm.func @tbaa2(%arg0: !llvm.ptr, %arg1: !llvm.ptr) { + %0 = llvm.mlir.constant(0 : i32) : i32 + %1 = llvm.mlir.constant(1 : i32) : i32 + %2 = llvm.getelementptr inbounds %arg1[%0, 1] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<"struct.agg2_t", (i64, i64)> + %3 = llvm.load %2 {tbaa = [#tbaa_tag_2]} : !llvm.ptr -> i64 + %4 = llvm.trunc %3 : i64 to i32 + %5 = llvm.getelementptr inbounds %arg0[%0, 0] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<"struct.agg1_t", (i32, i32)> + llvm.store %4, %5 {tbaa = [#tbaa_tag_3]} : i32, !llvm.ptr + llvm.return } -// CHECK-LABEL: llvm.metadata @__tbaa { -// CHECK: llvm.tbaa_root @tbaa_root_0 {id = "Simple C/C++ TBAA"} -// CHECK: llvm.tbaa_type_desc @tbaa_type_desc_1 {id = "omnipotent char", members = {<@tbaa_root_0, 0>}} -// CHECK: llvm.tbaa_type_desc @tbaa_type_desc_2 {id = "long long", members = {<@tbaa_type_desc_1, 0>}} -// CHECK: llvm.tbaa_type_desc @tbaa_type_desc_3 {id = "agg2_t", members = {<@tbaa_type_desc_2, 0>, <@tbaa_type_desc_2, 8>}} -// CHECK: llvm.tbaa_tag @tbaa_tag_4 {access_type = @tbaa_type_desc_2, base_type = @tbaa_type_desc_3, offset = 8 : i64} -// CHECK: llvm.tbaa_type_desc @tbaa_type_desc_5 {id = "int", members = {<@tbaa_type_desc_1, 0>}} -// CHECK: llvm.tbaa_type_desc @tbaa_type_desc_6 {id = "agg1_t", members = {<@tbaa_type_desc_5, 0>, <@tbaa_type_desc_5, 4>}} -// CHECK: llvm.tbaa_tag @tbaa_tag_7 {access_type = @tbaa_type_desc_5, base_type = @tbaa_type_desc_6, offset = 0 : i64} -// CHECK: } // CHECK: llvm.func @tbaa2(%[[VAL_0:.*]]: !llvm.ptr, %[[VAL_1:.*]]: !llvm.ptr) { // CHECK: %[[VAL_2:.*]] = llvm.mlir.constant(0 : i32) : i32 // CHECK: %[[VAL_3:.*]] = llvm.mlir.constant(1 : i32) : i32 // CHECK: %[[VAL_4:.*]] = llvm.getelementptr inbounds %[[VAL_1]]{{\[}}%[[VAL_2]], 1] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<"struct.agg2_t", (i64, i64)> -// CHECK: %[[VAL_5:.*]] = llvm.load %[[VAL_4]] {tbaa = [@__tbaa::@tbaa_tag_4]} : !llvm.ptr -> i64 +// CHECK: %[[VAL_5:.*]] = llvm.load %[[VAL_4]] {tbaa = [#[[$TAG_2]]]} : !llvm.ptr -> i64 // CHECK: %[[VAL_6:.*]] = llvm.trunc %[[VAL_5]] : i64 to i32 // CHECK: %[[VAL_7:.*]] = llvm.getelementptr inbounds %[[VAL_0]]{{\[}}%[[VAL_2]], 0] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<"struct.agg1_t", (i32, i32)> -// CHECK: llvm.store %[[VAL_6]], %[[VAL_7]] {tbaa = [@__tbaa::@tbaa_tag_7]} : i32, !llvm.ptr +// CHECK: llvm.store %[[VAL_6]], %[[VAL_7]] {tbaa = [#[[$TAG_3]]]} : i32, !llvm.ptr // CHECK: llvm.return // CHECK: } -module { - llvm.metadata @__tbaa { - llvm.tbaa_root @tbaa_root_0 {id = "Simple C/C++ TBAA"} - llvm.tbaa_tag @tbaa_tag_1 {access_type = @tbaa_root_0, base_type = @tbaa_root_0, offset = 0 : i64} - llvm.tbaa_root @tbaa_root_2 {id = "Other language TBAA"} - llvm.tbaa_tag @tbaa_tag_3 {access_type = @tbaa_root_2, base_type = @tbaa_root_2, offset = 0 : i64} - } - llvm.func @tbaa1(%arg0: !llvm.ptr) { - %0 = llvm.mlir.constant(1 : i8) : i8 - llvm.store %0, %arg0 {tbaa = [@__tbaa::@tbaa_tag_1, @__tbaa::@tbaa_tag_3]} : i8, !llvm.ptr - llvm.return - } +llvm.func @tbaa3(%arg0: !llvm.ptr) { + %0 = llvm.mlir.constant(1 : i8) : i8 + llvm.store %0, %arg0 {tbaa = [#tbaa_tag_0, #tbaa_tag_1]} : i8, !llvm.ptr + llvm.return } -// CHECK-LABEL: llvm.metadata @__tbaa { -// CHECK: llvm.tbaa_root @tbaa_root_0 {id = "Simple C/C++ TBAA"} -// CHECK: llvm.tbaa_tag @tbaa_tag_1 {access_type = @tbaa_root_0, base_type = @tbaa_root_0, offset = 0 : i64} -// CHECK: llvm.tbaa_root @tbaa_root_2 {id = "Other language TBAA"} -// CHECK: llvm.tbaa_tag @tbaa_tag_3 {access_type = @tbaa_root_2, base_type = @tbaa_root_2, offset = 0 : i64} +// CHECK: llvm.func @tbaa3(%[[VAL_0:.*]]: !llvm.ptr) { +// CHECK: %[[VAL_1:.*]] = llvm.mlir.constant(1 : i8) : i8 +// CHECK: llvm.store %[[VAL_1]], %[[VAL_0]] {tbaa = [#[[$TAG_0]], #[[$TAG_1]]]} : i8, !llvm.ptr +// CHECK: llvm.return // CHECK: } -// CHECK: llvm.func @tbaa1(%[[VAL_0:.*]]: !llvm.ptr) { + +llvm.func @tbaa4(%arg0: !llvm.ptr) { + %0 = llvm.mlir.constant(1 : i8) : i8 + llvm.store %0, %arg0 {tbaa = [#tbaa_tag_4]} : i8, !llvm.ptr + llvm.return +} + +// CHECK: llvm.func @tbaa4(%[[VAL_0:.*]]: !llvm.ptr) { // CHECK: %[[VAL_1:.*]] = llvm.mlir.constant(1 : i8) : i8 -// CHECK: llvm.store %[[VAL_1]], %[[VAL_0]] {tbaa = [@__tbaa::@tbaa_tag_1, @__tbaa::@tbaa_tag_3]} : i8, !llvm.ptr +// CHECK: llvm.store %[[VAL_1]], %[[VAL_0]] {tbaa = [#[[$TAG_4]]]} : i8, !llvm.ptr // CHECK: llvm.return // CHECK: } diff --git a/mlir/test/Target/LLVMIR/Import/import-failure.ll b/mlir/test/Target/LLVMIR/Import/import-failure.ll --- a/mlir/test/Target/LLVMIR/Import/import-failure.ll +++ b/mlir/test/Target/LLVMIR/Import/import-failure.ll @@ -94,29 +94,28 @@ ; // ----- ; CHECK: import-failure.ll -; CHECK-SAME: error: TBAA root node must have non-empty identity: !2 = !{!""} +; CHECK-SAME: error: unsupported TBAA node format: !{{.*}} = !{!{{.*}}, i64 1, !"omnipotent char"} define dso_local void @tbaa(ptr %0) { - store i8 1, ptr %0, align 4, !tbaa !2 + store i32 1, ptr %0, align 4, !tbaa !2 ret void } -!0 = !{!""} -!1 = !{!"omnipotent char", !0, i64 0} -!2 = !{!1, !1, i64 0} +!2 = !{!3, !3, i64 0, i64 4} +!3 = !{!4, i64 4, !"int"} +!4 = !{!5, i64 1, !"omnipotent char"} +!5 = !{!"Simple C++ TBAA"} ; // ----- ; CHECK: import-failure.ll -; CHECK-SAME: error: unsupported TBAA node format: !0 = !{!1, !1, i64 0, i64 4} +; CHECK-SAME: error: has cycle in TBAA graph: ![[ID:.*]] = distinct !{![[ID]], i64 4, !"int"} define dso_local void @tbaa(ptr %0) { store i32 1, ptr %0, align 4, !tbaa !2 ret void } !2 = !{!3, !3, i64 0, i64 4} -!3 = !{!4, i64 4, !"int"} -!4 = !{!5, i64 1, !"omnipotent char"} -!5 = !{!"Simple C++ TBAA"} +!3 = !{!3, i64 4, !"int"} ; // ----- diff --git a/mlir/test/Target/LLVMIR/Import/metadata-tbaa.ll b/mlir/test/Target/LLVMIR/Import/metadata-tbaa.ll --- a/mlir/test/Target/LLVMIR/Import/metadata-tbaa.ll +++ b/mlir/test/Target/LLVMIR/Import/metadata-tbaa.ll @@ -1,19 +1,18 @@ ; RUN: mlir-translate -import-llvm -split-input-file %s | FileCheck %s -; CHECK-LABEL: llvm.metadata @__llvm_global_metadata { -; CHECK-DAG: llvm.tbaa_root @[[R0:tbaa_root_[0-9]+]] {id = "Simple C/C++ TBAA"} -; CHECK-DAG: llvm.tbaa_type_desc @[[D0:tbaa_type_desc_[0-9]+]] {id = "scalar type", members = {<@[[R0]], 0>}} -; CHECK-DAG: llvm.tbaa_tag @[[T0:tbaa_tag_[0-9]+]] {access_type = @[[D0]], base_type = @[[D0]], offset = 0 : i64} -; CHECK-DAG: llvm.tbaa_root @[[R1:tbaa_root_[0-9]+]] {id = "Other language TBAA"} -; CHECK-DAG: llvm.tbaa_type_desc @[[D1:tbaa_type_desc_[0-9]+]] {id = "other scalar type", members = {<@[[R1]], 0>}} -; CHECK-DAG: llvm.tbaa_tag @[[T1:tbaa_tag_[0-9]+]] {access_type = @[[D1]], base_type = @[[D1]], offset = 0 : i64} -; CHECK-NEXT: } -; CHECK: llvm.func @tbaa1 +; CHECK-DAG: #[[R0:.*]] = #llvm.tbaa_root +; CHECK-DAG: #[[D0:.*]] = #llvm.tbaa_type_desc}> +; CHECK-DAG: #[[$T0:.*]] = #llvm.tbaa_tag +; CHECK-DAG: #[[R1:.*]] = #llvm.tbaa_root +; CHECK-DAG: #[[D1:.*]] = #llvm.tbaa_type_desc}> +; CHECK-DAG: #[[$T1:.*]] = #llvm.tbaa_tag + +; CHECK-LABEL: llvm.func @tbaa1 ; CHECK: llvm.store %{{.*}}, %{{.*}} { -; CHECK-SAME: tbaa = [@__llvm_global_metadata::@[[T0]]] +; CHECK-SAME: tbaa = [#[[$T0]]] ; CHECK-SAME: } : i8, !llvm.ptr ; CHECK: llvm.store %{{.*}}, %{{.*}} { -; CHECK-SAME: tbaa = [@__llvm_global_metadata::@[[T1]]] +; CHECK-SAME: tbaa = [#[[$T1]]] ; CHECK-SAME: } : i8, !llvm.ptr define dso_local void @tbaa1(ptr %0, ptr %1) { store i8 1, ptr %0, align 4, !tbaa !0 @@ -31,22 +30,21 @@ ; // ----- -; CHECK-LABEL: llvm.metadata @__llvm_global_metadata { -; CHECK-NEXT: llvm.tbaa_root @[[R0:tbaa_root_[0-9]+]] {id = "Simple C/C++ TBAA"} -; CHECK-NEXT: llvm.tbaa_tag @[[T0:tbaa_tag_[0-9]+]] {access_type = @[[D1:tbaa_type_desc_[0-9]+]], base_type = @[[D2:tbaa_type_desc_[0-9]+]], offset = 8 : i64} -; CHECK-NEXT: llvm.tbaa_type_desc @[[D1]] {id = "long long", members = {<@[[D0:tbaa_type_desc_[0-9]+]], 0>}} -; CHECK-NEXT: llvm.tbaa_type_desc @[[D0]] {id = "omnipotent char", members = {<@[[R0]], 0>}} -; CHECK-NEXT: llvm.tbaa_type_desc @[[D2]] {id = "agg2_t", members = {<@[[D1]], 0>, <@[[D1]], 8>}} -; CHECK-NEXT: llvm.tbaa_tag @[[T1:tbaa_tag_[0-9]+]] {access_type = @[[D3:tbaa_type_desc_[0-9]+]], base_type = @[[D4:tbaa_type_desc_[0-9]+]], offset = 0 : i64} -; CHECK-NEXT: llvm.tbaa_type_desc @[[D3]] {id = "int", members = {<@[[D0]], 0>}} -; CHECK-NEXT: llvm.tbaa_type_desc @[[D4]] {id = "agg1_t", members = {<@[[D3]], 0>, <@[[D3]], 4>}} -; CHECK-NEXT: } -; CHECK: llvm.func @tbaa2 +; CHECK-DAG: #[[R0:.*]] = #llvm.tbaa_root +; CHECK-DAG: #[[$T0:.*]] = #llvm.tbaa_tag +; CHECK-DAG: #[[D1]] = #llvm.tbaa_type_desc}> +; CHECK-DAG: #[[D0]] = #llvm.tbaa_type_desc}> +; CHECK-DAG: #[[D2]] = #llvm.tbaa_type_desc, <#[[D1]], 8>}> +; CHECK-DAG: #[[$T1:.*]] = #llvm.tbaa_tag +; CHECK-DAG: #[[D3]] = #llvm.tbaa_type_desc}> +; CHECK-DAG: #[[D4]] = #llvm.tbaa_type_desc, <#[[D3]], 4>}> + +; CHECK-LABEL: llvm.func @tbaa2 ; CHECK: llvm.load %{{.*}} { -; CHECK-SAME: tbaa = [@__llvm_global_metadata::@[[T0]]] +; CHECK-SAME: tbaa = [#[[$T0]]] ; CHECK-SAME: } : !llvm.ptr -> i64 ; CHECK: llvm.store %{{.*}}, %{{.*}} { -; CHECK-SAME: tbaa = [@__llvm_global_metadata::@[[T1]]] +; CHECK-SAME: tbaa = [#[[$T1]]] ; CHECK-SAME: } : i32, !llvm.ptr %struct.agg2_t = type { i64, i64 } %struct.agg1_t = type { i32, i32 } @@ -97,3 +95,20 @@ !0 = !{!1, !1, i64 0} !1 = !{!"scalar type", !2, i64 0} !2 = !{!"Simple C/C++ TBAA"} + +; // ----- + +; CHECK: #llvm.tbaa_root +; CHECK-NOT: <{{.*}}> +; CHECK: {{[[:space:]]}} + +define void @nameless_root(ptr %arg1) { + ; CHECK: llvm.load {{.*}}tbaa = + %1 = load i32, ptr %arg1, !tbaa !0 + ret void +} + +!0 = !{!1, !1, i64 0} +!1 = !{!"scalar type", !2, i64 0} +!2 = !{} + diff --git a/mlir/test/Target/LLVMIR/tbaa.mlir b/mlir/test/Target/LLVMIR/tbaa.mlir --- a/mlir/test/Target/LLVMIR/tbaa.mlir +++ b/mlir/test/Target/LLVMIR/tbaa.mlir @@ -1,28 +1,25 @@ // RUN: mlir-translate -mlir-to-llvmir -split-input-file %s | FileCheck %s -module { - llvm.metadata @__tbaa { - llvm.tbaa_root @tbaa_root_0 {id = "Simple C/C++ TBAA"} - llvm.tbaa_type_desc @tbaa_type_desc_1 {id = "omnipotent char", members = {<@tbaa_root_0, 0>}} - llvm.tbaa_type_desc @tbaa_type_desc_2 {id = "long long", members = {<@tbaa_type_desc_1, 0>}} - llvm.tbaa_type_desc @tbaa_type_desc_3 {id = "agg2_t", members = {<@tbaa_type_desc_2, 0>, <@tbaa_type_desc_2, 8>}} - llvm.tbaa_tag @tbaa_tag_4 {access_type = @tbaa_type_desc_2, base_type = @tbaa_type_desc_3, offset = 8 : i64} - llvm.tbaa_type_desc @tbaa_type_desc_5 {id = "int", members = {<@tbaa_type_desc_1, 0>}} - llvm.tbaa_type_desc @tbaa_type_desc_6 {id = "agg1_t", members = {<@tbaa_type_desc_5, 0>, <@tbaa_type_desc_5, 4>}} - llvm.tbaa_tag @tbaa_tag_7 {access_type = @tbaa_type_desc_5, base_type = @tbaa_type_desc_6, offset = 0 : i64, constant} - } - llvm.func @tbaa2(%arg0: !llvm.ptr, %arg1: !llvm.ptr) { - %0 = llvm.mlir.constant(0 : i32) : i32 - %1 = llvm.mlir.constant(1 : i32) : i32 - %2 = llvm.getelementptr inbounds %arg1[%0, 1] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<"struct.agg2_t", (i64, i64)> - // CHECK: load i64, ptr %{{.*}},{{.*}}!tbaa ![[LTAG:[0-9]*]] - %3 = llvm.load %2 {tbaa = [@__tbaa::@tbaa_tag_4]} : !llvm.ptr -> i64 - %4 = llvm.trunc %3 : i64 to i32 - %5 = llvm.getelementptr inbounds %arg0[%0, 0] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<"struct.agg1_t", (i32, i32)> - // CHECK: store i32 %{{.*}}, ptr %{{.*}},{{.*}}!tbaa ![[STAG:[0-9]*]] - llvm.store %4, %5 {tbaa = [@__tbaa::@tbaa_tag_7]} : i32, !llvm.ptr - llvm.return - } +#tbaa_root_0 = #llvm.tbaa_root +#tbaa_type_desc_1 = #llvm.tbaa_type_desc}> +#tbaa_type_desc_2 = #llvm.tbaa_type_desc}> +#tbaa_type_desc_3 = #llvm.tbaa_type_desc, <#tbaa_type_desc_2, 8>}> +#tbaa_tag_4 = #llvm.tbaa_tag +#tbaa_type_desc_5 = #llvm.tbaa_type_desc}> +#tbaa_type_desc_6 = #llvm.tbaa_type_desc, <#tbaa_type_desc_5, 4>}> +#tbaa_tag_7 = #llvm.tbaa_tag + +llvm.func @tbaa2(%arg0: !llvm.ptr, %arg1: !llvm.ptr) { + %0 = llvm.mlir.constant(0 : i32) : i32 + %1 = llvm.mlir.constant(1 : i32) : i32 + %2 = llvm.getelementptr inbounds %arg1[%0, 1] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<"struct.agg2_t", (i64, i64)> + // CHECK: load i64, ptr %{{.*}},{{.*}}!tbaa ![[LTAG:[0-9]*]] + %3 = llvm.load %2 {tbaa = [#tbaa_tag_4]} : !llvm.ptr -> i64 + %4 = llvm.trunc %3 : i64 to i32 + %5 = llvm.getelementptr inbounds %arg0[%0, 0] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<"struct.agg1_t", (i32, i32)> + // CHECK: store i32 %{{.*}}, ptr %{{.*}},{{.*}}!tbaa ![[STAG:[0-9]*]] + llvm.store %4, %5 {tbaa = [#tbaa_tag_7]} : i32, !llvm.ptr + llvm.return } // CHECK-DAG: ![[LTAG]] = !{![[AGG2T:[0-9]*]], ![[I64T:[0-9]*]], i64 8} @@ -39,48 +36,48 @@ // Verify that the MDNode's created for the access tags are not uniqued // before they are finalized. In the process of creating the MDNodes for // the tag operations we used to produce incomplete MDNodes like: -// @__tbaa::@tbaa_tag_4 => !{!null, !null, i64 0} -// @__tbaa::@tbaa_tag_7 => !{!null, !null, i64 0} +// #tbaa_tag_4 => !{!null, !null, i64 0} +// #tbaa_tag_7 => !{!null, !null, i64 0} // This caused the two tags to map to the same incomplete MDNode due to // uniquing. To prevent this, we have to use temporary MDNodes // instead of !null's. -module { - llvm.metadata @__tbaa { - llvm.tbaa_root @tbaa_root_0 {id = "Simple C/C++ TBAA"} - llvm.tbaa_type_desc @tbaa_type_desc_1 {id = "omnipotent char", members = {<@tbaa_root_0, 0>}} - llvm.tbaa_type_desc @tbaa_type_desc_2 {id = "float", members = {<@tbaa_type_desc_1, 0>}} - llvm.tbaa_type_desc @tbaa_type_desc_3 {id = "agg2_t", members = {<@tbaa_type_desc_2, 0>, <@tbaa_type_desc_2, 4>}} - llvm.tbaa_tag @tbaa_tag_4 {access_type = @tbaa_type_desc_2, base_type = @tbaa_type_desc_3, offset = 0 : i64} - llvm.tbaa_type_desc @tbaa_type_desc_5 {id = "int", members = {<@tbaa_type_desc_1, 0>}} - llvm.tbaa_type_desc @tbaa_type_desc_6 {id = "agg1_t", members = {<@tbaa_type_desc_5, 0>, <@tbaa_type_desc_5, 4>}} - llvm.tbaa_tag @tbaa_tag_7 {access_type = @tbaa_type_desc_5, base_type = @tbaa_type_desc_6, offset = 0 : i64} - } - llvm.func @foo(%arg0: !llvm.ptr) - llvm.func @tbaa2(%arg0: !llvm.ptr, %arg1: !llvm.ptr) { - %0 = llvm.mlir.constant(0 : i32) : i32 - %1 = llvm.mlir.constant(1 : i32) : i32 - %2 = llvm.getelementptr inbounds %arg1[%0, 0] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<"struct.agg2_t", (f32, f32)> - // CHECK: load float, ptr %{{.*}},{{.*}}!tbaa ![[LTAG:[0-9]*]] - %3 = llvm.load %2 {tbaa = [@__tbaa::@tbaa_tag_4]} : !llvm.ptr -> f32 - %4 = llvm.fptosi %3 : f32 to i32 - %5 = llvm.getelementptr inbounds %arg0[%0, 0] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<"struct.agg1_t", (i32, i32)> - // CHECK: store i32 %{{.*}}, ptr %{{.*}},{{.*}}!tbaa ![[STAG:[0-9]*]] - llvm.store %4, %5 {tbaa = [@__tbaa::@tbaa_tag_7]} : i32, !llvm.ptr - // CHECK: atomicrmw add ptr %{{.*}}, i32 %{{.*}} !tbaa ![[STAG]] - %6 = llvm.atomicrmw add %5, %4 monotonic {tbaa = [@__tbaa::@tbaa_tag_7]} : !llvm.ptr, i32 - // CHECK: cmpxchg ptr %{{.*}}, i32 %{{.*}}, i32 %{{.*}} !tbaa ![[STAG]] - %7 = llvm.cmpxchg %5, %6, %4 acq_rel monotonic {tbaa = [@__tbaa::@tbaa_tag_7]} : !llvm.ptr, i32 - %9 = llvm.mlir.constant(42 : i8) : i8 - // CHECK: llvm.memcpy{{.*}} !tbaa ![[STAG]] - "llvm.intr.memcpy"(%arg1, %arg1, %0) <{isVolatile = false}> {tbaa = [@__tbaa::@tbaa_tag_7]} : (!llvm.ptr, !llvm.ptr, i32) -> () - // CHECK: llvm.memset{{.*}} !tbaa ![[STAG]] - "llvm.intr.memset"(%arg1, %9, %0) <{isVolatile = false}> {tbaa = [@__tbaa::@tbaa_tag_7]} : (!llvm.ptr, i8, i32) -> () - // CHECK: call void @foo({{.*}} !tbaa ![[STAG]] - llvm.call @foo(%arg1) {tbaa = [@__tbaa::@tbaa_tag_7]} : (!llvm.ptr) -> () - llvm.return - } + +#tbaa_root_0 = #llvm.tbaa_root +#tbaa_type_desc_1 = #llvm.tbaa_type_desc}> +#tbaa_type_desc_2 = #llvm.tbaa_type_desc}> +#tbaa_type_desc_3 = #llvm.tbaa_type_desc, <#tbaa_type_desc_2, 4>}> +#tbaa_tag_4 = #llvm.tbaa_tag +#tbaa_type_desc_5 = #llvm.tbaa_type_desc}> +#tbaa_type_desc_6 = #llvm.tbaa_type_desc, <#tbaa_type_desc_5, 4>}> +#tbaa_tag_7 = #llvm.tbaa_tag + + +llvm.func @foo(%arg0: !llvm.ptr) +llvm.func @tbaa2(%arg0: !llvm.ptr, %arg1: !llvm.ptr) { + %0 = llvm.mlir.constant(0 : i32) : i32 + %1 = llvm.mlir.constant(1 : i32) : i32 + %2 = llvm.getelementptr inbounds %arg1[%0, 0] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<"struct.agg2_t", (f32, f32)> + // CHECK: load float, ptr %{{.*}},{{.*}}!tbaa ![[LTAG:[0-9]*]] + %3 = llvm.load %2 {tbaa = [#tbaa_tag_4]} : !llvm.ptr -> f32 + %4 = llvm.fptosi %3 : f32 to i32 + %5 = llvm.getelementptr inbounds %arg0[%0, 0] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<"struct.agg1_t", (i32, i32)> + // CHECK: store i32 %{{.*}}, ptr %{{.*}},{{.*}}!tbaa ![[STAG:[0-9]*]] + llvm.store %4, %5 {tbaa = [#tbaa_tag_7]} : i32, !llvm.ptr + // CHECK: atomicrmw add ptr %{{.*}}, i32 %{{.*}} !tbaa ![[STAG]] + %6 = llvm.atomicrmw add %5, %4 monotonic {tbaa = [#tbaa_tag_7]} : !llvm.ptr, i32 + // CHECK: cmpxchg ptr %{{.*}}, i32 %{{.*}}, i32 %{{.*}} !tbaa ![[STAG]] + %7 = llvm.cmpxchg %5, %6, %4 acq_rel monotonic {tbaa = [#tbaa_tag_7]} : !llvm.ptr, i32 + %9 = llvm.mlir.constant(42 : i8) : i8 + // CHECK: llvm.memcpy{{.*}} !tbaa ![[STAG]] + "llvm.intr.memcpy"(%arg1, %arg1, %0) <{isVolatile = false}> {tbaa = [#tbaa_tag_7]} : (!llvm.ptr, !llvm.ptr, i32) -> () + // CHECK: llvm.memset{{.*}} !tbaa ![[STAG]] + "llvm.intr.memset"(%arg1, %9, %0) <{isVolatile = false}> {tbaa = [#tbaa_tag_7]} : (!llvm.ptr, i8, i32) -> () + // CHECK: call void @foo({{.*}} !tbaa ![[STAG]] + llvm.call @foo(%arg1) {tbaa = [#tbaa_tag_7]} : (!llvm.ptr) -> () + llvm.return } + // CHECK-DAG: ![[LTAG]] = !{![[AGG2T:[0-9]*]], ![[F32T:[0-9]*]], i64 0} // CHECK-DAG: ![[AGG2T]] = !{!"agg2_t", ![[F32T]], i64 0, ![[F32T]], i64 4} // CHECK-DAG: ![[I64T]] = !{!"float", ![[CHART:[0-9]*]], i64 0} diff --git a/mlir/test/mlir-tblgen/llvm-intrinsics.td b/mlir/test/mlir-tblgen/llvm-intrinsics.td --- a/mlir/test/mlir-tblgen/llvm-intrinsics.td +++ b/mlir/test/mlir-tblgen/llvm-intrinsics.td @@ -74,7 +74,7 @@ // It has alias scopes, noalias, and tbaa. // ALIAS: OptionalAttr:$alias_scopes // ALIAS: OptionalAttr:$noalias_scopes -// ALIAS: OptionalAttr:$tbaa +// ALIAS: OptionalAttr:$tbaa //---------------------------------------------------------------------------// diff --git a/mlir/tools/mlir-tblgen/LLVMIRIntrinsicGen.cpp b/mlir/tools/mlir-tblgen/LLVMIRIntrinsicGen.cpp --- a/mlir/tools/mlir-tblgen/LLVMIRIntrinsicGen.cpp +++ b/mlir/tools/mlir-tblgen/LLVMIRIntrinsicGen.cpp @@ -223,7 +223,7 @@ operands.push_back("OptionalAttr:$alias_scopes"); operands.push_back( "OptionalAttr:$noalias_scopes"); - operands.push_back("OptionalAttr:$tbaa"); + operands.push_back("OptionalAttr:$tbaa"); } // Emit the definition.