Index: flang/include/flang/Optimizer/CodeGen/TBAABuilder.h =================================================================== --- flang/include/flang/Optimizer/CodeGen/TBAABuilder.h +++ 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,73 @@ mlir::LLVM::GEPOp gep); private: - // Return unique string name based on `basename`. - std::string getNewTBAANodeName(llvm::StringRef basename); + // Find or create TBAATagAttr attribute (TBAA access tag) with the specified + // components and return it. + mlir::LLVM::TBAATagAttr + getAccessTag(mlir::LLVM::TBAANodeInterface baseTypeDesc, + mlir::LLVM::TBAANodeInterface accessTypeDesc, int64_t offset); - // 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: + // 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, + mlir::LLVM::TBAATagAttr> tagsMap; }; Index: flang/lib/Optimizer/CodeGen/TBAABuilder.cpp =================================================================== --- flang/lib/Optimizer/CodeGen/TBAABuilder.cpp +++ flang/lib/Optimizer/CodeGen/TBAABuilder.cpp @@ -37,107 +37,59 @@ 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, 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, ArrayRef{flangTBAARoot}, + ArrayRef{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, + ArrayRef{anyAccessTypeDesc}, ArrayRef{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, + ArrayRef{anyAccessTypeDesc}, ArrayRef{0}); } -SymbolRefAttr TBAABuilder::getAccessTag(SymbolRefAttr baseTypeDesc, - SymbolRefAttr accessTypeDesc, - int64_t offset) { - SymbolRefAttr &tag = tagsMap[{baseTypeDesc, accessTypeDesc, offset}]; +TBAATagAttr TBAABuilder::getAccessTag(TBAANodeInterface baseTypeDesc, + TBAANodeInterface 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 +106,7 @@ LLVM_DEBUG(llvm::dbgs() << "Attaching TBAA tag #" << tagAttachmentCounter << "\n"); - SymbolRefAttr tbaaTagSym; + TBAATagAttr tbaaTagSym; if (baseFIRType.isa()) tbaaTagSym = getBoxAccessTag(baseFIRType, accessFIRType, gep); else Index: flang/lib/Optimizer/CodeGen/TypeConverter.cpp =================================================================== --- flang/lib/Optimizer/CodeGen/TypeConverter.cpp +++ 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. Index: flang/test/Fir/tbaa.fir =================================================================== --- flang/test/Fir/tbaa.fir +++ 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: } Index: mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt =================================================================== --- mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt +++ mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt @@ -31,6 +31,8 @@ mlir_tablegen(LLVMInterfaces.cpp.inc -gen-op-interface-defs) mlir_tablegen(LLVMTypeInterfaces.h.inc -gen-type-interface-decls) mlir_tablegen(LLVMTypeInterfaces.cpp.inc -gen-type-interface-defs) +mlir_tablegen(LLVMAttrInterfaces.h.inc -gen-attr-interface-decls) +mlir_tablegen(LLVMAttrInterfaces.cpp.inc -gen-attr-interface-defs) add_public_tablegen_target(MLIRLLVMInterfacesIncGen) set(LLVM_TARGET_DEFINITIONS LLVMOps.td) Index: mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td =================================================================== --- mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td +++ mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td @@ -10,6 +10,7 @@ #define LLVMIR_ATTRDEFS include "mlir/Dialect/LLVMIR/LLVMDialect.td" +include "mlir/Dialect/LLVMIR/LLVMInterfaces.td" include "mlir/IR/AttrTypeBase.td" // All of the attributes will extend this class. @@ -685,4 +686,113 @@ let constBuilderCall = ?; } +//===----------------------------------------------------------------------===// +// TBAARootAttr +//===----------------------------------------------------------------------===// + +def LLVM_TBAARootAttr : LLVM_Attr<"TBAARoot", "tbaa_root", + [LLVM_TBAANodeInterface]> { + let parameters = (ins StringRefParameter<>:$id); + + let summary = "LLVM dialect TBAA root metadata"; + let description = [{ + Defines a TBAA root node. + + Example: + ```mlir + #tbaa_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_TBAATypeDescriptorAttr : LLVM_Attr<"TBAATypeDescriptor", + "tbaa_type_desc", [LLVM_TBAANodeInterface]> { + let parameters = (ins + StringRefParameter<>:$id, + ArrayRefParameter<"TBAANodeInterface">:$members, + ArrayRefParameter<"int64_t">:$offsets + ); + + 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 = [{ + `<` `id` `=` $id `,` `members` `=` + custom($members, $offsets) `>` + }]; +} + +//===----------------------------------------------------------------------===// +// TBAATagAttr +//===----------------------------------------------------------------------===// + +def LLVM_TBAATagAttr : LLVM_Attr<"TBAATag", "tbaa_tag"> { + let parameters = (ins + "TBAANodeInterface":$base_type, + "TBAANodeInterface":$access_type, + "int64_t":$offset, + DefaultValuedParameter<"bool", "false">:$constant + ); + + let builders = [ + AttrBuilderWithInferredContext<(ins "TBAANodeInterface":$baseType, + "TBAANodeInterface":$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 Index: mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h =================================================================== --- mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h +++ mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h @@ -70,6 +70,8 @@ } // namespace LLVM } // namespace mlir +#include "mlir/Dialect/LLVMIR/LLVMAttrInterfaces.h.inc" + #define GET_ATTRDEF_CLASSES #include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.h.inc" Index: mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td =================================================================== --- mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td +++ mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td @@ -219,4 +219,26 @@ ]; } +//===----------------------------------------------------------------------===// +// LLVM dialect attr interfaces. +//===----------------------------------------------------------------------===// + +// An interface for LLVM TBAA node. +def LLVM_TBAANodeInterface : AttrInterface<"TBAANodeInterface"> { + let cppNamespace = "::mlir::LLVM"; + + let description = [{ + Interface for non-leaf attributes participating in the TBAA graph. + }]; + + let methods = [ + InterfaceMethod< + /*description=*/"Returns the identifier of a TBAA node.", + /*retTy=*/"llvm::StringRef", + /*methodName=*/"getId", + /*args=*/(ins) + > + ]; +} + #endif // LLVMIR_INTERFACES Index: mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td =================================================================== --- mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td +++ 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, Index: mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td =================================================================== --- mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ 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", Index: mlir/include/mlir/Target/LLVMIR/ModuleImport.h =================================================================== --- mlir/include/mlir/Target/LLVMIR/ModuleImport.h +++ 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 symbols pointing to the converted attribute. + /// 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. @@ -326,8 +319,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 +343,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; Index: mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h =================================================================== --- mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h +++ 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 an 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. Index: mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp =================================================================== --- mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp +++ mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp @@ -22,10 +22,6 @@ using namespace mlir; using namespace mlir::LLVM; -#include "mlir/Dialect/LLVMIR/LLVMOpsEnums.cpp.inc" -#define GET_ATTRDEF_CLASSES -#include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.cpp.inc" - //===----------------------------------------------------------------------===// // LLVMDialect registration //===----------------------------------------------------------------------===// @@ -101,3 +97,40 @@ return false; return true; } + +//===----------------------------------------------------------------------===// +// TBAATypeDescriptorAttr +//===----------------------------------------------------------------------===// + +static LogicalResult +parseTBAAMembers(AsmParser &parser, SmallVectorImpl &members, + SmallVectorImpl &offsets) { + auto parseMembers = [&]() -> ParseResult { + // Parse a pair of `<#tbaa_type_desc_sym, integer-offset>`. + return failure( + parser.parseLess() || parser.parseAttribute(members.emplace_back()) || + parser.parseComma() || parser.parseInteger(offsets.emplace_back()) || + parser.parseGreater()); + }; + return failure(parser.parseLBrace() || + parser.parseCommaSeparatedList(parseMembers) || + parser.parseRBrace()); +} + +static void printTBAAMembers(AsmPrinter &printer, + ArrayRef members, + ArrayRef offsets) { + printer << "{"; + llvm::interleaveComma(llvm::zip(members, offsets), printer, + [&](auto &&tuple) { + auto &&[member, offset] = tuple; + printer << '<' << member << ", " << offset << '>'; + }); + printer << "}"; +} + +#include "mlir/Dialect/LLVMIR/LLVMAttrInterfaces.cpp.inc" + +#include "mlir/Dialect/LLVMIR/LLVMOpsEnums.cpp.inc" +#define GET_ATTRDEF_CLASSES +#include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.cpp.inc" \ No newline at end of file Index: mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp =================================================================== --- mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ 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; }) Index: mlir/lib/Dialect/LLVMIR/IR/LLVMInterfaces.cpp =================================================================== --- mlir/lib/Dialect/LLVMIR/IR/LLVMInterfaces.cpp +++ 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 ") + << Attr::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,24 @@ LogicalResult mlir::LLVM::detail::verifyAliasAnalysisOpInterface(Operation *op) { auto iface = cast(op); - if (failed(verifySymbolRefsPointTo( - iface, "tbaa tags", iface.getTBAATagsOrNull()))) + ArrayAttr tags = iface.getTBAATagsOrNull(); + if (!tags) + return success(); + + if (failed(isArrayOf(op, tags))) return failure(); - return success(); + + AttrTypeWalker walker; + walker.addWalk([&](TBAANodeInterface node) { + if (node.getId().empty()) { + op->emitError("expected non-empty \"id\""); + return WalkResult::interrupt(); + } + + return WalkResult::advance(); + }); + + return failure(walker.walk(tags).wasInterrupted()); } #include "mlir/Dialect/LLVMIR/LLVMInterfaces.cpp.inc" Index: mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp =================================================================== --- mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp +++ 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(); Index: mlir/lib/Target/LLVMIR/ModuleImport.cpp =================================================================== --- mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ 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,21 +174,6 @@ 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. @@ -231,7 +198,7 @@ // true is returned). auto isTypeDescriptorNode = [&](const llvm::MDNode *node, StringRef *identity = nullptr, - SmallVectorImpl *memberTypes = nullptr, + SmallVectorImpl *memberTypes = nullptr, SmallVectorImpl *memberOffsets = nullptr) -> std::optional { unsigned numOperands = node->getNumOperands(); @@ -281,7 +248,8 @@ } if (memberTypes) - memberTypes->push_back(tbaaMapping.lookup(memberNode)); + memberTypes->push_back( + cast(tbaaMapping.lookup(memberNode))); if (memberOffsets) memberOffsets->push_back(offset); } @@ -297,8 +265,8 @@ // 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, + [&](const llvm::MDNode *node, TBAANodeInterface *baseSymRef = nullptr, + TBAANodeInterface *accessSymRef = nullptr, int64_t *offset = nullptr, bool *isConstant = nullptr) -> std::optional { // Access tag, e.g.: // !3 = !{!1, !1, i64 0} /* scalar int access */ @@ -336,9 +304,9 @@ isConst = isConstantCI->getValue()[0]; } if (baseSymRef) - *baseSymRef = tbaaMapping.lookup(baseMD); + *baseSymRef = cast(tbaaMapping.lookup(baseMD)); if (accessSymRef) - *accessSymRef = tbaaMapping.lookup(accessMD); + *accessSymRef = cast(tbaaMapping.lookup(accessMD)); if (offset) *offset = offsetCI->getZExtValue(); if (isConstant) @@ -346,22 +314,46 @@ 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()); + // 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 *opNode = dyn_cast_or_null(operand.get())) + if (!tbaaMapping.contains(opNode)) { + workList.push_back(opNode); + 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()); + + continue; + } + + // Otherwise simply import the current node. + workList.pop_back(); - // 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: " @@ -369,65 +361,37 @@ // 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"))); + tbaaMapping.insert({current, builder.getAttr(*identity)}); 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")))); - 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 memberTypes; SmallVector memberOffsets; if (std::optional isValid = isTypeDescriptorNode( current, &identity, &memberTypes, &memberOffsets)) { 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, memberTypes, memberOffsets)}); continue; } - SymbolRefAttr baseSymRef, accessSymRef; + + TBAANodeInterface baseSymRef, accessSymRef; int64_t offset; bool isConstant; if (std::optional isValid = isTagNode( current, &baseSymRef, &accessSymRef, &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(baseSymRef, accessSymRef, + offset, isConstant)}); continue; } - } + return emitError(loc) << "unsupported TBAA node format: " + << diagMD(current, llvmModule.get()); + } return success(); } Index: mlir/lib/Target/LLVMIR/ModuleTranslation.cpp =================================================================== --- mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ 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,52 @@ 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 (auto &&[member, offset] : + llvm::zip(descriptor.getMembers(), descriptor.getOffsets())) { + operands.push_back(tbaaMetadataMapping.lookup(member)); + operands.push_back(llvm::ConstantAsMetadata::get( + llvm::ConstantInt::get(offsetTy, offset))); } - } - // 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(); } Index: mlir/test/Dialect/LLVMIR/tbaa-invalid.mlir =================================================================== --- mlir/test/Dialect/LLVMIR/tbaa-invalid.mlir +++ mlir/test/Dialect/LLVMIR/tbaa-invalid.mlir @@ -1,169 +1,34 @@ // 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_tag = #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.func @test(%arg : !llvm.ptr) { + %0 = llvm.mlir.constant(0 : i32) : i32 + // expected-error@below {{expected non-empty "id"}} + llvm.store %0, %arg {tbaa = [#tbaa_tag]} : i32, !llvm.ptr llvm.return } // ----- -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 -} +#tbaa_root = #llvm.tbaa_root +#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 `TBAANodeInterface`}} +#tbaa_tag2 = #llvm.tbaa_tag // ----- -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 - } -} +#tbaa_root = #llvm.tbaa_root +#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 `TBAANodeInterface`}} +#tbaa_tag2 = #llvm.tbaa_tag // ----- -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_tag = #llvm.tbaa_tag +// expected-error@below {{invalid kind of attribute specified}} +#tbaa_desc = #llvm.tbaa_type_desc}> Index: mlir/test/Dialect/LLVMIR/tbaa-roundtrip.mlir =================================================================== --- mlir/test/Dialect/LLVMIR/tbaa-roundtrip.mlir +++ mlir/test/Dialect/LLVMIR/tbaa-roundtrip.mlir @@ -1,99 +1,79 @@ // RUN: mlir-opt %s | mlir-opt | FileCheck %s +#tbaa_root_0 = #llvm.tbaa_root +#tbaa_root_1 = #llvm.tbaa_root +#tbaa_tag_0 = #llvm.tbaa_tag +#tbaa_tag_1 = #llvm.tbaa_tag +#tbaa_type_desc_0 = #llvm.tbaa_type_desc}> +#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 + +// CHECK: #[[$ROOT_0:.*]] = #llvm.tbaa_root +// CHECK: #[[$ROOT_1:.*]] = #llvm.tbaa_root +// CHECK: #[[$TAG_0:.*]] = #llvm.tbaa_tag +// CHECK: #[[$TAG_1:.*]] = #llvm.tbaa_tag +// CHECK: #[[$DESC_0:.*]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$DESC_1:.*]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$DESC_2:.*]] = #llvm.tbaa_type_desc}> +// CHECK: #[[$DESC_3:.*]] = #llvm.tbaa_type_desc, <#[[$DESC_1]], 8>}> +// CHECK: #[[$DESC_4:.*]] = #llvm.tbaa_type_desc, <#[[$DESC_2]], 4>}> +// CHECK: #[[$TAG_2:.*]] = #llvm.tbaa_tag +// CHECK: #[[$TAG_3:.*]] = #llvm.tbaa_tag + 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.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 + %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::@tbaa_tag_7]} : i32, !llvm.ptr + 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.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: } // CHECK: llvm.func @tbaa1(%[[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_0]], #[[$TAG_1]]]} : i8, !llvm.ptr // CHECK: llvm.return // CHECK: } Index: mlir/test/Target/LLVMIR/Import/import-failure.ll =================================================================== --- mlir/test/Target/LLVMIR/Import/import-failure.ll +++ mlir/test/Target/LLVMIR/Import/import-failure.ll @@ -107,7 +107,7 @@ ; // ----- ; CHECK: import-failure.ll -; CHECK-SAME: error: unsupported TBAA node format: !0 = !{!1, !1, i64 0, i64 4} +; CHECK-SAME: error: unsupported TBAA node format: !{{.*}} = !{!{{.*}}, i64 1, !"omnipotent char"} define dso_local void @tbaa(ptr %0) { store i32 1, ptr %0, align 4, !tbaa !2 ret void @@ -120,6 +120,18 @@ ; // ----- +; CHECK: import-failure.ll +; 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 = !{!3, i64 4, !"int"} + +; // ----- + ; CHECK: import-failure.ll ; CHECK-SAME: warning: expected an access group node to be empty and distinct ; CHECK: error: unsupported access group node: !0 = !{} Index: mlir/test/Target/LLVMIR/Import/metadata-tbaa.ll =================================================================== --- mlir/test/Target/LLVMIR/Import/metadata-tbaa.ll +++ 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 } Index: mlir/test/Target/LLVMIR/tbaa.mlir =================================================================== --- mlir/test/Target/LLVMIR/tbaa.mlir +++ mlir/test/Target/LLVMIR/tbaa.mlir @@ -1,26 +1,25 @@ // RUN: mlir-translate -mlir-to-llvmir -split-input-file %s | FileCheck %s +#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 + 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 + %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::@tbaa_tag_7]} : i32, !llvm.ptr + llvm.store %4, %5 {tbaa = [#tbaa_tag_7]} : i32, !llvm.ptr llvm.return } } @@ -39,44 +38,44 @@ // 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. + +#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 + 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 + %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::@tbaa_tag_7]} : i32, !llvm.ptr + 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::@tbaa_tag_7]} : !llvm.ptr, i32 + %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::@tbaa_tag_7]} : !llvm.ptr, i32 + %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::@tbaa_tag_7]} : (!llvm.ptr, !llvm.ptr, i32) -> () + "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::@tbaa_tag_7]} : (!llvm.ptr, i8, i32) -> () + "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::@tbaa_tag_7]} : (!llvm.ptr) -> () + llvm.call @foo(%arg1) {tbaa = [#tbaa_tag_7]} : (!llvm.ptr) -> () llvm.return } } Index: mlir/test/mlir-tblgen/llvm-intrinsics.td =================================================================== --- mlir/test/mlir-tblgen/llvm-intrinsics.td +++ 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 //---------------------------------------------------------------------------// Index: mlir/tools/mlir-tblgen/LLVMIRIntrinsicGen.cpp =================================================================== --- mlir/tools/mlir-tblgen/LLVMIRIntrinsicGen.cpp +++ 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.