From c94c04e5a104283e984c83b3b3f996de59f86673 Mon Sep 17 00:00:00 2001 From: PikachuHy Date: Thu, 19 Dec 2024 00:48:12 +0800 Subject: [PATCH] [CIR][CIRGen][TBAA] Add support for scalar types (#1220) --- .../CIR/Dialect/Builder/CIRBaseBuilder.h | 6 +- .../include/clang/CIR/Dialect/IR/CIRAttrs.td | 8 +- clang/include/clang/CIR/Dialect/IR/CIROps.td | 6 +- .../clang/CIR/Dialect/IR/CIRTBAAAttrs.td | 38 +++++ .../include/clang/CIR/Dialect/IR/CIRTypes.td | 29 ++++ clang/include/clang/CIR/MissingFeatures.h | 7 +- clang/lib/CIR/CodeGen/CIRGenBuilder.h | 2 +- clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp | 2 +- clang/lib/CIR/CodeGen/CIRGenModule.cpp | 2 +- clang/lib/CIR/CodeGen/CIRGenModule.h | 2 +- clang/lib/CIR/CodeGen/CIRGenTBAA.cpp | 128 ++++++++++++++- clang/lib/CIR/CodeGen/CIRGenTBAA.h | 6 +- clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 13 +- clang/lib/CIR/Dialect/IR/CIRMemorySlot.cpp | 2 +- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 83 +++++++++- clang/test/CIR/CodeGen/const-alloca.cpp | 6 +- clang/test/CIR/CodeGen/tbaa-scalar.c | 148 ++++++++++++++++++ clang/test/CIR/CodeGen/tbaa-struct.cpp | 35 +++++ clang/test/CIR/CodeGen/tbaa-vptr.cpp | 18 +++ clang/test/CIR/CodeGen/tbaa.c | 22 --- 20 files changed, 505 insertions(+), 58 deletions(-) create mode 100644 clang/include/clang/CIR/Dialect/IR/CIRTBAAAttrs.td create mode 100644 clang/test/CIR/CodeGen/tbaa-scalar.c create mode 100644 clang/test/CIR/CodeGen/tbaa-struct.cpp create mode 100644 clang/test/CIR/CodeGen/tbaa-vptr.cpp delete mode 100644 clang/test/CIR/CodeGen/tbaa.c diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h index 771b7dd33cd4..48d1f1faf53f 100644 --- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -170,7 +170,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { /*alignment=*/intAttr, /*mem_order=*/ cir::MemOrderAttr{}, - /*tbaa=*/mlir::ArrayAttr{}); + /*tbaa=*/cir::TBAAAttr{}); } mlir::Value createAlignedLoad(mlir::Location loc, mlir::Value ptr, @@ -357,7 +357,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { val.getType()) dst = createPtrBitcast(dst, val.getType()); return create(loc, val, dst, _volatile, align, order, - /*tbaa=*/mlir::ArrayAttr{}); + /*tbaa=*/cir::TBAAAttr{}); } mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType, @@ -405,7 +405,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { cir::CopyOp createCopy(mlir::Value dst, mlir::Value src, bool isVolatile = false) { return create(dst.getLoc(), dst, src, isVolatile, - /*tbaa=*/mlir::ArrayAttr{}); + /*tbaa=*/cir::TBAAAttr{}); } cir::MemCpyOp createMemCpy(mlir::Location loc, mlir::Value dst, diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index e54b52b96c91..e968d4c27fd5 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -24,8 +24,9 @@ include "clang/CIR/Interfaces/ASTAttrInterfaces.td" // CIR Attrs //===----------------------------------------------------------------------===// -class CIR_Attr traits = []> - : AttrDef { +class CIR_Attr traits = [], + string baseCppClass = "::mlir::Attribute"> + : AttrDef { let mnemonic = attrMnemonic; } @@ -1294,8 +1295,7 @@ def GlobalAnnotationValuesAttr : CIR_Attr<"GlobalAnnotationValues", let genVerifyDecl = 1; } -def CIR_TBAAAttr : CIR_Attr<"TBAA", "tbaa", []> { -} +include "clang/CIR/Dialect/IR/CIRTBAAAttrs.td" include "clang/CIR/Dialect/IR/CIROpenCLAttrs.td" diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index e02194ad15e0..36793ba97d52 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -588,7 +588,7 @@ def LoadOp : CIR_Op<"load", [ UnitAttr:$is_volatile, OptionalAttr:$alignment, OptionalAttr:$mem_order, - OptionalAttr:$tbaa + OptionalAttr:$tbaa ); let results = (outs CIR_AnyType:$result); @@ -657,7 +657,7 @@ def StoreOp : CIR_Op<"store", [ UnitAttr:$is_volatile, OptionalAttr:$alignment, OptionalAttr:$mem_order, - OptionalAttr:$tbaa); + OptionalAttr:$tbaa); let assemblyFormat = [{ (`volatile` $is_volatile^)? @@ -4068,7 +4068,7 @@ def CopyOp : CIR_Op<"copy", let arguments = (ins Arg:$dst, Arg:$src, UnitAttr:$is_volatile, - OptionalAttr:$tbaa); + OptionalAttr:$tbaa); let summary = "Copies contents from a CIR pointer to another"; let description = [{ Given two CIR pointers, `src` and `dst`, `cir.copy` will copy the memory diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTBAAAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRTBAAAttrs.td new file mode 100644 index 000000000000..d46880e8541e --- /dev/null +++ b/clang/include/clang/CIR/Dialect/IR/CIRTBAAAttrs.td @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// TBAAAttr +//===----------------------------------------------------------------------===// + +def CIR_TBAAAttr : CIR_Attr<"TBAA", "tbaa", []> { + let summary = "CIR dialect TBAA base attribute"; +} + +//===----------------------------------------------------------------------===// +// TBAAScalarAttr +//===----------------------------------------------------------------------===// + +def CIR_TBAAScalarAttr : CIR_Attr<"TBAAScalar", "tbaa_scalar", [], "TBAAAttr"> { + let summary = "Describes a scalar type in TBAA with an identifier."; + + let parameters = (ins CIR_AnyScalarType : $type); + + let description = [{ + Define a TBAA attribute. + + Example: + ```mlir + // CIR_TBAAScalarAttr + #tbaa_scalar = #cir.tbaa_scalar + #tbaa_scalar1 = #cir.tbaa_scalar + ``` + + See the following link for more details: + https://llvm.org/docs/LangRef.html#tbaa-metadata + }]; + + let assemblyFormat = "`<` struct(params) `>`"; +} + +def CIR_AnyTBAAAttr : AnyAttrOf<[ + CIR_TBAAAttr, + CIR_TBAAScalarAttr +]>; diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td index d3f49716301d..68b27a053176 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -74,6 +74,28 @@ def CIR_IntType : CIR_Type<"Int", "int", static bool isValidPrimitiveIntBitwidth(unsigned width) { return width == 8 || width == 16 || width == 32 || width == 64; } + + llvm::StringRef getTBAATypeName() const { + switch (getWidth()) { + case 1: + case 8: { + return "omnipotent char"; + } + case 16: { + return "short"; + } + case 32: { + return "int"; + } + case 64: { + return "long"; + } + default: { + llvm::errs() << "unknown type: " << *this << "\n"; + return "unknown"; + } + } + } }]; let genVerifyDecl = 1; } @@ -609,4 +631,11 @@ def CIR_AnyType : AnyTypeOf<[ CIR_ComplexType ]>; +def CIR_AnyScalarType : AnyTypeOf<[ + CIR_IntType, CIR_PointerType, CIR_DataMemberType, CIR_MethodType, + CIR_BoolType, CIR_ArrayType, CIR_VectorType, CIR_FuncType, CIR_VoidType, + CIR_ExceptionType, CIR_AnyFloat, CIR_FP16, CIR_BFloat16, + CIR_ComplexType +]>; + #endif // MLIR_CIR_DIALECT_CIR_TYPES diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index c0707d687fca..346719691a5d 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -58,7 +58,12 @@ struct MissingFeatures { // sanitizer related type check features static bool emitTypeCheck() { return false; } static bool tbaa() { return false; } - static bool tbaa_struct() { return false; } + static bool tbaaStruct() { return false; } + static bool tbaaTagForStruct() { return false; } + static bool tbaaVTablePtr() { return false; } + static bool tbaaIncompleteType() { return false; } + static bool tbaaMergeTBAAInfo() { return false; } + static bool tbaaMayAlias() { return false; } static bool cleanups() { return false; } static bool emitNullabilityCheck() { return false; } static bool ptrAuth() { return false; } diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h index 28be733f62d7..3019ca8ef62b 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h @@ -839,7 +839,7 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { return create( loc, addr.getElementType(), addr.getPointer(), /*isDeref=*/false, /*is_volatile=*/isVolatile, /*alignment=*/mlir::IntegerAttr{}, - /*mem_order=*/cir::MemOrderAttr{}, /*tbaa=*/mlir::ArrayAttr{}); + /*mem_order=*/cir::MemOrderAttr{}, /*tbaa=*/cir::TBAAAttr{}); } mlir::Value createAlignedLoad(mlir::Location loc, mlir::Type ty, diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp index 46f89bf60d18..df4e97f7a179 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp @@ -1716,7 +1716,7 @@ void CIRGenFunction::emitAggregateCopy(LValue Dest, LValue Src, QualType Ty, // Determine the metadata to describe the position of any padding in this // memcpy, as well as the TBAA tags for the members of the struct, in case // the optimizer wishes to expand it in to scalar memory operations. - assert(!cir::MissingFeatures::tbaa_struct() && "tbaa.struct NYI"); + assert(!cir::MissingFeatures::tbaaStruct() && "tbaa.struct NYI"); if (CGM.getCodeGenOpts().NewStructPathTBAA) { TBAAAccessInfo TBAAInfo = CGM.mergeTBAAInfoForMemoryTransfer( Dest.getTBAAInfo(), Src.getTBAAInfo()); diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index b7197afeb896..81d60477cae0 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -3988,7 +3988,7 @@ cir::TBAAAttr CIRGenModule::getTBAABaseTypeInfo(QualType QTy) { return tbaa->getBaseTypeInfo(QTy); } -mlir::ArrayAttr CIRGenModule::getTBAAAccessTagInfo(TBAAAccessInfo tbaaInfo) { +cir::TBAAAttr CIRGenModule::getTBAAAccessTagInfo(TBAAAccessInfo tbaaInfo) { if (!tbaa) { return nullptr; } diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h index 905754a4ad3a..dd8a0c98b081 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -525,7 +525,7 @@ class CIRGenModule : public CIRGenTypeCache { /// type is not suitable for use in TBAA access tags. cir::TBAAAttr getTBAABaseTypeInfo(QualType QTy); - mlir::ArrayAttr getTBAAAccessTagInfo(TBAAAccessInfo tbaaInfo); + cir::TBAAAttr getTBAAAccessTagInfo(TBAAAccessInfo tbaaInfo); /// Get merged TBAA information for the purposes of type casts. TBAAAccessInfo mergeTBAAInfoForCast(TBAAAccessInfo SourceInfo, diff --git a/clang/lib/CIR/CodeGen/CIRGenTBAA.cpp b/clang/lib/CIR/CodeGen/CIRGenTBAA.cpp index a6efc05e4110..ce2969d130ff 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTBAA.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenTBAA.cpp @@ -1,11 +1,12 @@ #include "CIRGenTBAA.h" -#include "CIRGenCXXABI.h" #include "CIRGenTypes.h" #include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/MLIRContext.h" #include "mlir/Interfaces/DataLayoutInterfaces.h" #include "clang/AST/ASTContext.h" #include "clang/AST/RecordLayout.h" +#include "clang/CIR/Dialect/IR/CIRTypes.h" +#include "clang/CIR/MissingFeatures.h" #include "llvm/Support/ErrorHandling.h" namespace clang::CIRGen { @@ -21,44 +22,159 @@ CIRGenTBAA::CIRGenTBAA(mlir::MLIRContext *mlirContext, : mlirContext(mlirContext), astContext(astContext), types(types), moduleOp(moduleOp), codeGenOpts(codeGenOpts), features(features) {} +cir::TBAAAttr CIRGenTBAA::getChar() { + return cir::TBAAScalarAttr::get(mlirContext, + cir::IntType::get(mlirContext, 1, true)); +} + +static bool typeHasMayAlias(clang::QualType qty) { + // Tagged types have declarations, and therefore may have attributes. + if (auto *td = qty->getAsTagDecl()) + if (td->hasAttr()) + return true; + + // Also look for may_alias as a declaration attribute on a typedef. + // FIXME: We should follow GCC and model may_alias as a type attribute + // rather than as a declaration attribute. + while (auto *tt = qty->getAs()) { + if (tt->getDecl()->hasAttr()) + return true; + qty = tt->desugar(); + } + return false; +} + +/// Check if the given type is a valid base type to be used in access tags. +static bool isValidBaseType(clang::QualType qty) { + if (const clang::RecordType *tty = qty->getAs()) { + const clang::RecordDecl *rd = tty->getDecl()->getDefinition(); + // Incomplete types are not valid base access types. + if (!rd) + return false; + if (rd->hasFlexibleArrayMember()) + return false; + // rd can be struct, union, class, interface or enum. + // For now, we only handle struct and class. + if (rd->isStruct() || rd->isClass()) + return true; + } + return false; +} + cir::TBAAAttr CIRGenTBAA::getTypeInfo(clang::QualType qty) { - return tbaa_NYI(mlirContext); + // At -O0 or relaxed aliasing, TBAA is not emitted for regular types. + if (codeGenOpts.OptimizationLevel == 0 || codeGenOpts.RelaxedAliasing) { + return nullptr; + } + + // If the type has the may_alias attribute (even on a typedef), it is + // effectively in the general char alias class. + if (typeHasMayAlias(qty)) { + assert(!cir::MissingFeatures::tbaaMayAlias()); + return getChar(); + } + // We need this function to not fall back to returning the "omnipotent char" + // type node for aggregate and union types. Otherwise, any dereference of an + // aggregate will result into the may-alias access descriptor, meaning all + // subsequent accesses to direct and indirect members of that aggregate will + // be considered may-alias too. + // function. + if (isValidBaseType(qty)) { + // TODO(cir): support TBAA with struct + return tbaa_NYI(mlirContext); + } + + const clang::Type *ty = astContext.getCanonicalType(qty).getTypePtr(); + if (metadataCache.contains(ty)) { + return metadataCache[ty]; + } + + // Note that the following helper call is allowed to add new nodes to the + // cache, which invalidates all its previously obtained iterators. So we + // first generate the node for the type and then add that node to the + // cache. + auto typeNode = cir::TBAAScalarAttr::get(mlirContext, types.ConvertType(qty)); + return metadataCache[ty] = typeNode; } TBAAAccessInfo CIRGenTBAA::getAccessInfo(clang::QualType accessType) { - return TBAAAccessInfo(); + // Pointee values may have incomplete types, but they shall never be + // dereferenced. + if (accessType->isIncompleteType()) { + assert(!cir::MissingFeatures::tbaaIncompleteType()); + return TBAAAccessInfo::getIncompleteInfo(); + } + + if (typeHasMayAlias(accessType)) { + assert(!cir::MissingFeatures::tbaaMayAlias()); + return TBAAAccessInfo::getMayAliasInfo(); + } + + uint64_t size = astContext.getTypeSizeInChars(accessType).getQuantity(); + return TBAAAccessInfo(getTypeInfo(accessType), size); } TBAAAccessInfo CIRGenTBAA::getVTablePtrAccessInfo(mlir::Type vtablePtrType) { + // TODO(cir): support vtable ptr + assert(!cir::MissingFeatures::tbaaVTablePtr()); return TBAAAccessInfo(); } mlir::ArrayAttr CIRGenTBAA::getTBAAStructInfo(clang::QualType qty) { - return mlir::ArrayAttr::get(mlirContext, {}); + assert(!cir::MissingFeatures::tbaaStruct() && "tbaa.struct NYI"); + return mlir::ArrayAttr(); } cir::TBAAAttr CIRGenTBAA::getBaseTypeInfo(clang::QualType qty) { return tbaa_NYI(mlirContext); } -mlir::ArrayAttr CIRGenTBAA::getAccessTagInfo(TBAAAccessInfo tbaaInfo) { - return mlir::ArrayAttr::get(mlirContext, {tbaa_NYI(mlirContext)}); +cir::TBAAAttr CIRGenTBAA::getAccessTagInfo(TBAAAccessInfo tbaaInfo) { + assert(!tbaaInfo.isIncomplete() && + "Access to an object of an incomplete type!"); + + if (tbaaInfo.isMayAlias()) { + assert(!cir::MissingFeatures::tbaaMayAlias()); + tbaaInfo = TBAAAccessInfo(getChar(), tbaaInfo.size); + } + if (!tbaaInfo.accessType) { + return nullptr; + } + + if (!codeGenOpts.StructPathTBAA) + tbaaInfo = TBAAAccessInfo(tbaaInfo.accessType, tbaaInfo.size); + + if (!tbaaInfo.baseType) { + tbaaInfo.baseType = tbaaInfo.accessType; + assert(!tbaaInfo.offset && + "Nonzero offset for an access with no base type!"); + } + if (codeGenOpts.NewStructPathTBAA) { + llvm_unreachable("NYI"); + } + if (tbaaInfo.baseType == tbaaInfo.accessType) { + return tbaaInfo.accessType; + } + return tbaa_NYI(mlirContext); } TBAAAccessInfo CIRGenTBAA::mergeTBAAInfoForCast(TBAAAccessInfo sourceInfo, TBAAAccessInfo targetInfo) { + assert(!cir::MissingFeatures::tbaaMergeTBAAInfo()); return TBAAAccessInfo(); } TBAAAccessInfo CIRGenTBAA::mergeTBAAInfoForConditionalOperator(TBAAAccessInfo infoA, TBAAAccessInfo infoB) { + assert(!cir::MissingFeatures::tbaaMergeTBAAInfo()); return TBAAAccessInfo(); } TBAAAccessInfo CIRGenTBAA::mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo destInfo, TBAAAccessInfo srcInfo) { + assert(!cir::MissingFeatures::tbaaMergeTBAAInfo()); return TBAAAccessInfo(); } diff --git a/clang/lib/CIR/CodeGen/CIRGenTBAA.h b/clang/lib/CIR/CodeGen/CIRGenTBAA.h index 3f59a0e6538b..03b9b75113c9 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTBAA.h +++ b/clang/lib/CIR/CodeGen/CIRGenTBAA.h @@ -104,6 +104,10 @@ class CIRGenTBAA { [[maybe_unused]] const clang::CodeGenOptions &codeGenOpts; [[maybe_unused]] const clang::LangOptions &features; + llvm::DenseMap metadataCache; + + cir::TBAAAttr getChar(); + public: CIRGenTBAA(mlir::MLIRContext *mlirContext, clang::ASTContext &astContext, CIRGenTypes &types, mlir::ModuleOp moduleOp, @@ -129,7 +133,7 @@ class CIRGenTBAA { cir::TBAAAttr getBaseTypeInfo(clang::QualType qty); /// Get TBAA tag for a given memory access. - mlir::ArrayAttr getAccessTagInfo(TBAAAccessInfo tbaaInfo); + cir::TBAAAttr getAccessTagInfo(TBAAAccessInfo tbaaInfo); /// Get merged TBAA information for the purpose of type casts. TBAAAccessInfo mergeTBAAInfoForCast(TBAAAccessInfo sourceInfo, diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 1c5a6467f538..242afd4f00b8 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -17,6 +17,7 @@ #include "clang/CIR/Dialect/IR/CIRTypes.h" #include "clang/CIR/Interfaces/CIRLoopOpInterface.h" #include "clang/CIR/MissingFeatures.h" +#include "llvm/ADT/TypeSwitch.h" #include "llvm/Support/ErrorHandling.h" #include #include @@ -106,12 +107,12 @@ struct CIROpAsmDialectInterface : public OpAsmDialectInterface { os << dynCastInfoAttr.getAlias(); return AliasResult::FinalAlias; } - if (auto tbaaAttr = mlir::dyn_cast(attr)) { - os << tbaaAttr.getMnemonic(); - return AliasResult::OverridableAlias; - } - - return AliasResult::NoAlias; + return TypeSwitch(attr) + .Case([&](auto attr) { + os << decltype(attr)::getMnemonic(); + return AliasResult::OverridableAlias; + }) + .Default([](Attribute) { return AliasResult::NoAlias; }); } }; } // namespace diff --git a/clang/lib/CIR/Dialect/IR/CIRMemorySlot.cpp b/clang/lib/CIR/Dialect/IR/CIRMemorySlot.cpp index 80963353a304..bb99d53e0ad8 100644 --- a/clang/lib/CIR/Dialect/IR/CIRMemorySlot.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRMemorySlot.cpp @@ -151,7 +151,7 @@ DeletionKind cir::CopyOp::removeBlockingUses( if (loadsFrom(slot)) builder.create(getLoc(), reachingDefinition, getDst(), false, mlir::IntegerAttr{}, cir::MemOrderAttr(), - mlir::ArrayAttr{}); + cir::TBAAAttr{}); return DeletionKind::Delete; } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index c0400de4418f..7aa8cfbbc1bf 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -18,6 +18,7 @@ #include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h" #include "mlir/Dialect/DLTI/DLTI.h" #include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/Dialect/LLVMIR/LLVMAttrs.h" #include "mlir/Dialect/LLVMIR/Transforms/Passes.h" #include "mlir/IR/Attributes.h" #include "mlir/IR/Builders.h" @@ -41,6 +42,9 @@ #include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h" #include "mlir/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.h" #include "mlir/Target/LLVMIR/Export.h" +#include "clang/CIR/Dialect/IR/CIRAttrs.h" +#include "clang/CIR/Dialect/IR/CIRDialect.h" +#include "clang/CIR/Dialect/IR/CIRTypes.h" #include "clang/CIR/Dialect/Passes.h" #include "clang/CIR/LoweringHelpers.h" #include "clang/CIR/MissingFeatures.h" @@ -51,6 +55,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/ADT/TypeSwitch.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/Support/Casting.h" @@ -666,6 +671,67 @@ mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, mlir::Attribute attr, llvm_unreachable("unhandled attribute type"); } +mlir::LLVM::TBAATypeDescriptorAttr +createScalarTypeNode(mlir::MLIRContext *ctx, llvm::StringRef typeName, + mlir::LLVM::TBAANodeAttr parent, int64_t offset) { + llvm::SmallVector members; + members.push_back(mlir::LLVM::TBAAMemberAttr::get(ctx, parent, offset)); + return mlir::LLVM::TBAATypeDescriptorAttr::get( + ctx, typeName, llvm::ArrayRef(members)); +} + +mlir::LLVM::TBAARootAttr getRoot(mlir::MLIRContext *ctx) { + return mlir::LLVM::TBAARootAttr::get( + ctx, mlir::StringAttr::get(ctx, "Simple C/C++ TBAA")); +} + +mlir::LLVM::TBAATypeDescriptorAttr getChar(mlir::MLIRContext *ctx) { + return createScalarTypeNode(ctx, "omnipotent char", getRoot(ctx), 0); +} + +// FIXME(cir): This should be moved and use tablegen approach +// see https://github.com/llvm/clangir/pull/1220#discussion_r1889187867 +StringRef getTypeName(mlir::Type type) { + return TypeSwitch(type) + .Case([](cir::IntType ty) { return ty.getTBAATypeName(); }) + .Case([](cir::SingleType) { return "float"; }) + .Case([](cir::DoubleType) { return "double"; }) + .Case([](cir::FP80Type) { return "f80"; }) + .Case([](cir::FP128Type) { return "f128"; }) + .Case( + [](cir::LongDoubleType) { return "long double"; }) + .Case([](cir::BoolType) { return "bool"; }) + .Case([](cir::PointerType) { return "any pointer"; }) + .Default([](auto ty) { + llvm::errs() << "unknown type: " << ty << "\n"; + return "unknown"; + }); +} + +mlir::LLVM::TBAATypeDescriptorAttr +lowerScalarType(mlir::MLIRContext *ctx, cir::TBAAScalarAttr scalarAttr) { + // special handle for omnipotent char + if (auto intTy = mlir::dyn_cast_or_null(scalarAttr.getType())) { + if (intTy.getWidth() == 1 || intTy.getWidth() == 8) { + return getChar(ctx); + } + } + auto name = getTypeName(scalarAttr.getType()); + return createScalarTypeNode(ctx, name, getChar(ctx), 0); +} + +mlir::ArrayAttr lowerCIRTBAAAttr(mlir::Attribute tbaa, + mlir::ConversionPatternRewriter &rewriter) { + auto *ctx = rewriter.getContext(); + if (auto scalarAttr = mlir::dyn_cast(tbaa)) { + auto accessType = lowerScalarType(ctx, scalarAttr); + auto tag = mlir::LLVM::TBAATagAttr::get(accessType, accessType, 0); + return mlir::ArrayAttr::get(ctx, {tag}); + } + assert(!cir::MissingFeatures::tbaaTagForStruct()); + return mlir::ArrayAttr(); +} + //===----------------------------------------------------------------------===// mlir::LLVM::Linkage convertLinkage(cir::GlobalLinkageKind linkage) { @@ -1512,10 +1578,14 @@ mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite( } // TODO: nontemporal, syncscope. - rewriter.replaceOpWithNewOp( - op, llvmTy, adaptor.getAddr(), /* alignment */ alignment, + auto loadOp = rewriter.create( + op->getLoc(), llvmTy, adaptor.getAddr(), /* alignment */ alignment, op.getIsVolatile(), /* nontemporal */ false, /* invariant */ false, /* invariantGroup */ invariant, ordering); + rewriter.replaceOp(op, loadOp); + if (auto tbaa = op.getTbaaAttr()) { + loadOp.setTBAATags(lowerCIRTBAAAttr(tbaa, rewriter)); + } return mlir::LogicalResult::success(); } @@ -1547,9 +1617,14 @@ mlir::LogicalResult CIRToLLVMStoreOpLowering::matchAndRewrite( } // TODO: nontemporal, syncscope. - rewriter.replaceOpWithNewOp( - op, adaptor.getValue(), adaptor.getAddr(), alignment, op.getIsVolatile(), + auto storeOp = rewriter.create( + op->getLoc(), adaptor.getValue(), adaptor.getAddr(), alignment, + op.getIsVolatile(), /* nontemporal */ false, /* invariantGroup */ invariant, ordering); + rewriter.replaceOp(op, storeOp); + if (auto tbaa = op.getTbaaAttr()) { + storeOp.setTBAATags(lowerCIRTBAAAttr(tbaa, rewriter)); + } return mlir::LogicalResult::success(); } diff --git a/clang/test/CIR/CodeGen/const-alloca.cpp b/clang/test/CIR/CodeGen/const-alloca.cpp index 9247b2692474..7cc9a5b57517 100644 --- a/clang/test/CIR/CodeGen/const-alloca.cpp +++ b/clang/test/CIR/CodeGen/const-alloca.cpp @@ -66,8 +66,8 @@ int local_const_load_store() { // LLVM-LABEL: @_Z22local_const_load_storev // LLVM: %[[#INIT:]] = call i32 @_Z11produce_intv() -// LLVM-NEXT: store i32 %[[#INIT]], ptr %[[#SLOT:]], align 4, !invariant.group !{{.+}} -// LLVM-NEXT: %{{.+}} = load i32, ptr %[[#SLOT]], align 4, !invariant.group !{{.+}} +// LLVM-NEXT: store i32 %[[#INIT]], ptr %[[#SLOT:]], align 4, !tbaa !{{.*}}, !invariant.group !{{.+}} +// LLVM-NEXT: %{{.+}} = load i32, ptr %[[#SLOT]], align 4, !tbaa !{{.*}}, !invariant.group !{{.+}} // LLVM: } int local_const_optimize() { @@ -80,7 +80,7 @@ int local_const_optimize() { // LLVM-LABEL: @_Z20local_const_optimizev() // LLVM-NEXT: %[[#slot:]] = alloca i32, align 4 // LLVM-NEXT: %[[#init:]] = tail call i32 @_Z11produce_intv() -// LLVM-NEXT: store i32 %[[#init]], ptr %[[#slot]], align 4, !invariant.group !{{.+}} +// LLVM-NEXT: store i32 %[[#init]], ptr %[[#slot]], align 4, !tbaa !{{.*}}, !invariant.group !{{.+}} // LLVM-NEXT: call void @_Z8blackboxRKi(ptr nonnull %[[#slot]]) // LLVM-NEXT: call void @_Z8blackboxRKi(ptr nonnull %[[#slot]]) // LLVM-NEXT: ret i32 %[[#init]] diff --git a/clang/test/CIR/CodeGen/tbaa-scalar.c b/clang/test/CIR/CodeGen/tbaa-scalar.c new file mode 100644 index 000000000000..b2f893b4f4ac --- /dev/null +++ b/clang/test/CIR/CodeGen/tbaa-scalar.c @@ -0,0 +1,148 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir -O1 +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -O1 +// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -O1 -relaxed-aliasing +// RUN: FileCheck --check-prefix=NO-TBAA --input-file=%t.ll %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -O0 +// RUN: FileCheck --check-prefix=NO-TBAA --input-file=%t.ll %s + +// NO-TBAA-NOT: !tbaa + +// CIR: #tbaa[[FLOAT_PTR:.*]] = #cir.tbaa_scalar> +// CIR: #tbaa[[FLOAT:.*]] = #cir.tbaa_scalar +// CIR: #tbaa[[DOUBLE_PTR:.*]] = #cir.tbaa_scalar> +// CIR: #tbaa[[DOUBLE:.*]] = #cir.tbaa_scalar +// CIR: #tbaa[[LONG_DOUBLE_PTR:.*]] = #cir.tbaa_scalar>> +// CIR: #tbaa[[LONG_DOUBLE:.*]] = #cir.tbaa_scalar> +// CIR: #tbaa[[INT:.*]] = #cir.tbaa_scalar +// CIR: #tbaa[[LONG:.*]] = #cir.tbaa_scalar +// CIR: #tbaa[[CHAR:.*]] = #cir.tbaa_scalar +// CIR: #tbaa[[INT_PTR:.*]] = #cir.tbaa_scalar> +// CIR: #tbaa[[LONG_PTR:.*]] = #cir.tbaa_scalar> +// CIR: #tbaa[[CHAR_PTR:.*]] = #cir.tbaa_scalar> + +void test_int_and_float(int *a, float *b) { + // CIR-LABEL: cir.func @test_int_and_float + // CIR: cir.scope + // CIR: %[[TMP1:.*]] = cir.load deref %{{.*}} : !cir.ptr>, !cir.ptr tbaa(#tbaa[[INT_PTR]]) + // CIR: %[[TMP2:.*]] = cir.load %[[TMP1]] : !cir.ptr, !s32i tbaa(#tbaa[[INT]]) + // CIR: cir.if + // CIR: %[[C2:.*]] = cir.const #cir.fp<2 + // CIR: %[[TMP3:.*]] = cir.load deref %[[ARG_b:.*]] : !cir.ptr>, !cir.ptr tbaa(#tbaa[[FLOAT_PTR]]) + // CIR: cir.store %[[C2]], %[[TMP3]] : !cir.float, !cir.ptr tbaa(#tbaa[[FLOAT]]) + // CIR: else + // CIR: %[[C3:.*]] = cir.const #cir.fp<3 + // CIR: %[[TMP4:.*]] = cir.load deref %[[ARG_b]] : !cir.ptr>, !cir.ptr tbaa(#tbaa[[FLOAT_PTR]]) + // CIR: cir.store %[[C3]], %[[TMP4]] : !cir.float, !cir.ptr tbaa(#tbaa[[FLOAT]]) + + // LLVM-LABEL: void @test_int_and_float + // LLVM: %[[ARG_a:.*]] = load i32, ptr %{{.*}}, align 4, !tbaa ![[TBAA_INT:.*]] + // LLVM: %[[COND:.*]] = icmp eq i32 %[[ARG_a]], 1 + // LLVM: %[[RET:.*]] = select i1 %[[COND]], float 2.000000e+00, float 3.000000e+00 + // LLVM: store float %[[RET]], ptr %{{.*}}, align 4, !tbaa ![[TBAA_FLOAT:.*]] + // LLVM: ret void + if (*a == 1) { + *b = 2.0f; + } else { + *b = 3.0f; + } +} + +void test_long_and_double(long *a, double *b) { + // CIR-LABEL: cir.func @test_long_and_double + // CIR: cir.scope + // CIR: %[[TMP1:.*]] = cir.load deref %{{.*}} : !cir.ptr>, !cir.ptr tbaa(#tbaa[[LONG_PTR]]) + // CIR: %[[TMP2:.*]] = cir.load %[[TMP1]] : !cir.ptr, !s64i tbaa(#tbaa[[LONG]]) + // CIR: cir.if + // CIR: %[[C2:.*]] = cir.const #cir.fp<2 + // CIR: %[[TMP3:.*]] = cir.load deref %[[ARG_b:.*]] : !cir.ptr>, !cir.ptr tbaa(#tbaa[[DOUBLE_PTR]]) + // CIR: cir.store %[[C2]], %[[TMP3]] : !cir.double, !cir.ptr tbaa(#tbaa[[DOUBLE]]) + // CIR: else + // CIR: %[[C3:.*]] = cir.const #cir.fp<3 + // CIR: %[[TMP4:.*]] = cir.load deref %[[ARG_b]] : !cir.ptr>, !cir.ptr tbaa(#tbaa[[DOUBLE_PTR]]) + // CIR: cir.store %[[C3]], %[[TMP4]] : !cir.double, !cir.ptr tbaa(#tbaa[[DOUBLE]]) + + // LLVM-LABEL: void @test_long_and_double + // LLVM: %[[ARG_a:.*]] = load i64, ptr %{{.*}}, align 8, !tbaa ![[TBAA_LONG:.*]] + // LLVM: %[[COND:.*]] = icmp eq i64 %[[ARG_a]], 1 + // LLVM: %[[RET:.*]] = select i1 %[[COND]], double 2.000000e+00, double 3.000000e+00 + // LLVM: store double %[[RET]], ptr %{{.*}}, align 8, !tbaa ![[TBAA_DOUBLE:.*]] + // LLVM: ret void + if (*a == 1L) { + *b = 2.0; + } else { + *b = 3.0; + } +} +void test_long_long_and_long_double(long long *a, long double *b) { + // CIR-LABEL: cir.func @test_long_long_and_long_double + // CIR: cir.scope + // CIR: %[[TMP1:.*]] = cir.load deref %{{.*}} : !cir.ptr>, !cir.ptr tbaa(#tbaa[[LONG_PTR]]) + // CIR: %[[TMP2:.*]] = cir.load %[[TMP1]] : !cir.ptr, !s64i tbaa(#tbaa[[LONG]]) + // CIR: cir.if + // CIR: %[[C2:.*]] = cir.const #cir.fp<2 + // CIR: %[[TMP3:.*]] = cir.load deref %[[ARG_b:.*]] : !cir.ptr>>, !cir.ptr> tbaa(#tbaa[[LONG_DOUBLE_PTR]]) + // CIR: cir.store %[[C2]], %[[TMP3]] : !cir.long_double, !cir.ptr> tbaa(#tbaa[[LONG_DOUBLE]]) + // CIR: else + // CIR: %[[C3:.*]] = cir.const #cir.fp<3 + // CIR: %[[TMP4:.*]] = cir.load deref %[[ARG_b]] : !cir.ptr>>, !cir.ptr> tbaa(#tbaa[[LONG_DOUBLE_PTR]]) + // CIR: cir.store %[[C3]], %[[TMP4]] : !cir.long_double, !cir.ptr> tbaa(#tbaa[[LONG_DOUBLE]]) + + // LLVM-LABEL: void @test_long_long_and_long_double + // LLVM: %[[ARG_a:.*]] = load i64, ptr %{{.*}}, align 8, !tbaa ![[TBAA_LONG_LONG:.*]] + // LLVM: %[[COND:.*]] = icmp eq i64 %[[ARG_a]], 1 + // LLVM: %[[RET:.*]] = select i1 %[[COND]], x86_fp80 0xK40008000000000000000, x86_fp80 0xK4000C000000000000000 + // LLVM: store x86_fp80 %[[RET]], ptr %{{.*}}, align 16, !tbaa ![[TBAA_LONG_DOUBLE:.*]] + // LLVM: ret void + if (*a == 1L) { + *b = 2.0L; + } else { + *b = 3.0L; + } +} + +void test_char(char *a, char* b) { + // CIR-LABEL: cir.func @test_char + // CIR: cir.scope + // CIR: %[[TMP1:.*]] = cir.load deref %{{.*}} : !cir.ptr>, !cir.ptr tbaa(#tbaa[[CHAR_PTR]]) + // CIR: %[[TMP2:.*]] = cir.load %[[TMP1]] : !cir.ptr, !s8i tbaa(#tbaa[[CHAR]]) + // CIR: cir.if + // CIR: %[[C2:.*]] = cir.const #cir.int<98> : !s32i + // CIR: %[[C2_CHAR:.*]] = cir.cast(integral, %[[C2]] : !s32i), !s8i + // CIR: %[[TMP3:.*]] = cir.load deref %[[ARG_b:.*]] : !cir.ptr>, !cir.ptr tbaa(#tbaa[[CHAR_PTR]]) + // CIR: cir.store %[[C2_CHAR]], %[[TMP3]] : !s8i, !cir.ptr tbaa(#tbaa[[CHAR]]) + // CIR: else + // CIR: %[[C3:.*]] = cir.const #cir.int<0> : !s32i + // CIR: %[[C3_CHAR:.*]] = cir.cast(integral, %[[C3]] : !s32i), !s8i + // CIR: %[[TMP4:.*]] = cir.load deref %[[ARG_b]] : !cir.ptr>, !cir.ptr tbaa(#tbaa[[CHAR_PTR]]) + // CIR: cir.store %[[C3_CHAR]], %[[TMP4]] : !s8i, !cir.ptr tbaa(#tbaa[[CHAR]]) + + + // LLVM-LABEL: void @test_char + // LLVM: %[[ARG_a:.*]] = load i8, ptr %{{.*}}, align 1, !tbaa ![[TBAA_CHAR:.*]] + // LLVM: %[[COND:.*]] = icmp eq i8 %[[ARG_a]], 97 + // LLVM: %[[RET:.*]] = select i1 %[[COND]], i8 98, i8 0 + // LLVM: store i8 %[[RET]], ptr %{{.*}}, align 1, !tbaa ![[TBAA_CHAR]] + // LLVM: ret void + if (*a == 'a') { + *b = 'b'; + } + else { + *b = '\0'; + } +} + +// LLVM: ![[TBAA_INT]] = !{![[TBAA_INT_PARENT:.*]], ![[TBAA_INT_PARENT]], i64 0} +// LLVM: ![[TBAA_INT_PARENT]] = !{!"int", ![[CHAR:.*]], i64 0} +// LLVM: ![[CHAR]] = !{!"omnipotent char", ![[ROOT:.*]], i64 0} +// LLVM: ![[ROOT]] = !{!"Simple C/C++ TBAA"} +// LLVM: ![[TBAA_FLOAT]] = !{![[TBAA_FLOAT_PARENT:.*]], ![[TBAA_FLOAT_PARENT]], i64 0} +// LLVM: ![[TBAA_FLOAT_PARENT]] = !{!"float", ![[CHAR]], i64 0} +// LLVM: ![[TBAA_LONG]] = !{![[TBAA_LONG_PARENT:.*]], ![[TBAA_LONG_PARENT]], i64 0} +// LLVM: ![[TBAA_LONG_PARENT]] = !{!"long", ![[CHAR]], i64 0} +// LLVM: ![[TBAA_DOUBLE]] = !{![[TBAA_DOUBLE_PARENT:.*]], ![[TBAA_DOUBLE_PARENT]], i64 0} +// LLVM: ![[TBAA_DOUBLE_PARENT]] = !{!"double", ![[CHAR]], i64 0} +// LLVM: ![[TBAA_LONG_DOUBLE]] = !{![[TBAA_LONG_DOUBLE_PARENT:.*]], ![[TBAA_LONG_DOUBLE_PARENT]], i64 0} +// LLVM: ![[TBAA_LONG_DOUBLE_PARENT]] = !{!"long double", ![[CHAR]], i64 0} +// LLVM: ![[TBAA_CHAR]] = !{![[CHAR]], ![[CHAR]], i64 0} diff --git a/clang/test/CIR/CodeGen/tbaa-struct.cpp b/clang/test/CIR/CodeGen/tbaa-struct.cpp new file mode 100644 index 000000000000..84c49df6b455 --- /dev/null +++ b/clang/test/CIR/CodeGen/tbaa-struct.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir -O1 +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s + +// CIR: #tbaa[[tbaa_NYI:.*]] = #cir.tbaa +// CIR: #tbaa[[INT:.*]] = #cir.tbaa_scalar +// CIR: #tbaa[[INT_PTR:.*]] = #cir.tbaa_scalar> +// CIR: #tbaa[[StructA_PTR:.*]] = #cir.tbaa_scalar> + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; +typedef struct +{ + uint16_t f16; + uint32_t f32; + uint16_t f16_2; + uint32_t f32_2; +} StructA; + +uint32_t g(uint32_t *s, StructA *A) { + // CIR-LABEL: cir.func @_Z1g + // CIR: %[[INT_1:.*]] = cir.const #cir.int<1> : !s32i + // CIR: %[[UINT_1:.*]] = cir.cast(integral, %[[INT_1]] : !s32i), !u32i + // CIR: cir.store %[[UINT_1]], %{{.*}} : !u32i, !cir.ptr tbaa(#tbaa[[INT]]) + // CIR: %[[INT_4:.*]] = cir.const #cir.int<4> : !s32i + // CIR: %[[UINT_4:.*]] = cir.cast(integral, %[[INT_4]] : !s32i), !u32i + // CIR: %[[pointer_to_StructA:.*]] = cir.load %{{.*}} : !cir.ptr>, !cir.ptr tbaa(#tbaa[[StructA_PTR]]) + // CIR: %[[A_f32:.*]] = cir.get_member %[[pointer_to_StructA]][1] {name = "f32"} : !cir.ptr -> !cir.ptr + // CIR: cir.store %[[UINT_4]], %[[A_f32]] : !u32i, !cir.ptr tbaa(#tbaa[[tbaa_NYI]]) + + *s = 1; + A->f32 = 4; + return *s; +} diff --git a/clang/test/CIR/CodeGen/tbaa-vptr.cpp b/clang/test/CIR/CodeGen/tbaa-vptr.cpp new file mode 100644 index 000000000000..dbe28be626a2 --- /dev/null +++ b/clang/test/CIR/CodeGen/tbaa-vptr.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir -O1 +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s + +// CIR-NOT: #tbaa + +struct Member { + ~Member(); +}; + +struct A { + virtual ~A(); +}; + +struct B : A { + Member m; + virtual ~B(); +}; +B::~B() { } diff --git a/clang/test/CIR/CodeGen/tbaa.c b/clang/test/CIR/CodeGen/tbaa.c deleted file mode 100644 index 43cdde47ecb7..000000000000 --- a/clang/test/CIR/CodeGen/tbaa.c +++ /dev/null @@ -1,22 +0,0 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir -O1 -// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s - -// CIR: #tbaa[[TBAA_NO:.*]] = #cir.tbaa -void f(int *a, float *b) { - // CIR: cir.scope - // CIR: %[[TMP1:.*]] = cir.load deref %{{.*}} : !cir.ptr>, !cir.ptr tbaa([#tbaa[[TBAA_NO]]]) - // CIR: %[[TMP2:.*]] = cir.load %[[TMP1]] : !cir.ptr, !s32i tbaa([#tbaa[[TBAA_NO]]]) - // CIR: cir.if - // CIR: %[[C2:.*]] = cir.const #cir.fp<2 - // CIR: %[[TMP3:.*]] = cir.load deref %[[ARG_b:.*]] : !cir.ptr>, !cir.ptr tbaa([#tbaa[[TBAA_NO]]]) - // CIR: cir.store %[[C2]], %[[TMP3]] : !cir.float, !cir.ptr tbaa([#tbaa[[TBAA_NO]]]) - // CIR: else - // CIR: %[[C3:.*]] = cir.const #cir.fp<3 - // CIR: %[[TMP4:.*]] = cir.load deref %[[ARG_b]] : !cir.ptr>, !cir.ptr tbaa([#tbaa[[TBAA_NO]]]) - // CIR: cir.store %[[C3]], %[[TMP4]] : !cir.float, !cir.ptr tbaa([#tbaa[[TBAA_NO]]]) - if (*a == 1) { - *b = 2.0f; - } else { - *b = 3.0f; - } -}