diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h index be9965ae3101f..19521ea4d2ebf 100644 --- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -205,7 +205,8 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { bool isVolatile = false, uint64_t alignment = 0) { mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment); return cir::LoadOp::create(*this, loc, ptr, /*isDeref=*/false, isVolatile, - alignmentAttr, cir::MemOrderAttr{}); + alignmentAttr, cir::MemOrderAttr{}, + /*tbaa=*/mlir::ArrayAttr{}); } mlir::Value createAlignedLoad(mlir::Location loc, mlir::Value ptr, @@ -321,14 +322,16 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { /// Create a copy with inferred length. cir::CopyOp createCopy(mlir::Value dst, mlir::Value src, bool isVolatile = false) { - return cir::CopyOp::create(*this, dst.getLoc(), dst, src, isVolatile); + return cir::CopyOp::create(*this, dst.getLoc(), dst, src, isVolatile, + /*tbaa=*/mlir::ArrayAttr{}); } cir::StoreOp createStore(mlir::Location loc, mlir::Value val, mlir::Value dst, bool isVolatile = false, mlir::IntegerAttr align = {}, cir::MemOrderAttr order = {}) { - return cir::StoreOp::create(*this, loc, val, dst, isVolatile, align, order); + return cir::StoreOp::create(*this, loc, val, dst, isVolatile, align, order, + /*tbaa=*/mlir::ArrayAttr{}); } [[nodiscard]] cir::GlobalOp createGlobal(mlir::ModuleOp mlirModule, @@ -353,7 +356,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { auto addr = createAlloca(loc, getPointerTo(type), type, {}, alignmentAttr); return cir::LoadOp::create(*this, loc, addr, /*isDeref=*/false, /*isVolatile=*/false, alignmentAttr, - /*mem_order=*/{}); + /*mem_order=*/{}, /*tbaa=*/mlir::ArrayAttr{}); } cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base, diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index 12bc9cf7b5b04..5dbfe9334c867 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -447,6 +447,14 @@ def CIR_ConstPtrAttr : CIR_Attr<"ConstPtr", "ptr", [TypedAttrInterface]> { }]; } +//===----------------------------------------------------------------------===// +// TBAAAttr +//===----------------------------------------------------------------------===// + +def CIR_TBAAAttr : CIR_Attr<"TBAA", "tbaa", []> { + let summary = "CIR dialect TBAA base attribute"; +} + //===----------------------------------------------------------------------===// // GlobalViewAttr //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index a19c4f951fff9..40710783c97c0 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -586,7 +586,10 @@ def CIR_LoadOp : CIR_Op<"load", [ UnitAttr:$isDeref, UnitAttr:$is_volatile, OptionalAttr:$alignment, - OptionalAttr:$mem_order); + OptionalAttr:$mem_order, + OptionalAttr:$tbaa + ); + let results = (outs CIR_AnyType:$result); let assemblyFormat = [{ @@ -595,6 +598,7 @@ def CIR_LoadOp : CIR_Op<"load", [ (`align` `(` $alignment^ `)`)? (`atomic` `(` $mem_order^ `)`)? $addr `:` qualified(type($addr)) `,` type($result) attr-dict + (`tbaa` `(` $tbaa^ `)`)? }]; // FIXME: add verifier. @@ -638,13 +642,16 @@ def CIR_StoreOp : CIR_Op<"store", [ [MemWrite]>:$addr, UnitAttr:$is_volatile, OptionalAttr:$alignment, - OptionalAttr:$mem_order); + OptionalAttr:$mem_order, + OptionalAttr:$tbaa + ); let assemblyFormat = [{ (`volatile` $is_volatile^)? (`align` `(` $alignment^ `)`)? (`atomic` `(` $mem_order^ `)`)? $value `,` $addr attr-dict `:` type($value) `,` qualified(type($addr)) + (`tbaa` `(` $tbaa^ `)`)? }]; // FIXME: add verifier. @@ -2979,12 +2986,16 @@ def CIR_CopyOp : CIR_Op<"copy",[ let arguments = (ins Arg:$dst, Arg:$src, - UnitAttr:$is_volatile + UnitAttr:$is_volatile, + OptionalAttr:$tbaa ); - let assemblyFormat = [{$src `to` $dst (`volatile` $is_volatile^)? - attr-dict `:` qualified(type($dst)) + let assemblyFormat = [{ + $src `to` $dst (`volatile` $is_volatile^)? + attr-dict `:` qualified(type($dst)) + (`tbaa` `(` $tbaa^ `)`)? }]; + let hasVerifier = 1; let extraClassDeclaration = [{ @@ -2994,7 +3005,7 @@ def CIR_CopyOp : CIR_Op<"copy",[ /// Returns the number of bytes to be copied. unsigned getLength(const mlir::DataLayout &dt) { return dt.getTypeSize(getType().getPointee()); - } + } }]; } diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index c99fd6f0bfcc4..defcb5dd600d1 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -302,6 +302,7 @@ struct MissingFeatures { static bool openCL() { return false; } static bool openMP() { return false; } static bool opTBAA() { return false; } + static bool opTBAAStruct() { return false; } static bool peepholeProtection() { return false; } static bool pgoUse() { return false; } static bool pointerAuthentication() { return false; } diff --git a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp index 48c082d89de18..aea832051b355 100644 --- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp @@ -1011,7 +1011,7 @@ void CIRGenFunction::emitAtomicStore(RValue rvalue, LValue dest, if (isVolatile) store.setIsVolatile(true); - assert(!cir::MissingFeatures::opLoadStoreTbaa()); + cgm.decorateOperationWithTBAA(store, dest.getTBAAInfo()); return; } diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h index 85b38120169fd..99803dc8aaac3 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h @@ -462,7 +462,8 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { mlir::IntegerAttr align = getAlignmentAttr(addr.getAlignment()); return cir::LoadOp::create(*this, loc, addr.getPointer(), /*isDeref=*/false, isVolatile, /*alignment=*/align, - /*mem_order=*/cir::MemOrderAttr{}); + /*mem_order=*/cir::MemOrderAttr{}, + /*tbaa=*/mlir::ArrayAttr{}); } cir::LoadOp createAlignedLoad(mlir::Location loc, mlir::Type ty, @@ -473,7 +474,8 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { mlir::IntegerAttr alignAttr = getAlignmentAttr(alignment); return cir::LoadOp::create(*this, loc, ptr, /*isDeref=*/false, /*isVolatile=*/false, alignAttr, - /*mem_order=*/cir::MemOrderAttr{}); + /*mem_order=*/cir::MemOrderAttr{}, + /*tbaa=*/mlir::ArrayAttr{}); } cir::LoadOp diff --git a/clang/lib/CIR/CodeGen/CIRGenClass.cpp b/clang/lib/CIR/CodeGen/CIRGenClass.cpp index 0f10347944fae..a619b1b1009cd 100644 --- a/clang/lib/CIR/CodeGen/CIRGenClass.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenClass.cpp @@ -429,7 +429,16 @@ void CIRGenFunction::initializeVTablePointer(mlir::Location loc, builder, loc, builder.getPtrToVPtrType(), classAddr.getPointer()); Address vtableField = Address(vtablePtr, classAddr.getAlignment()); builder.createStore(loc, vtableAddressPoint, vtableField); - assert(!cir::MissingFeatures::opTBAA()); + + cir::StoreOp storeOp = + builder.createStore(loc, vtableAddressPoint, vtableField); + TBAAAccessInfo tbaaInfo = + cgm.getTBAAVTablePtrAccessInfo(vtableAddressPoint.getType()); + cgm.decorateOperationWithTBAA(storeOp, tbaaInfo); + if (cgm.getCodeGenOpts().OptimizationLevel > 0 && + cgm.getCodeGenOpts().StrictVTablePointers) { + } + assert(!cir::MissingFeatures::createInvariantGroup()); } diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 70497258eb64a..5981218758dc4 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -14,6 +14,7 @@ #include "CIRGenConstantEmitter.h" #include "CIRGenFunction.h" #include "CIRGenModule.h" +#include "CIRGenTBAA.h" #include "CIRGenValue.h" #include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/Value.h" @@ -69,7 +70,8 @@ Address CIRGenFunction::emitAddrOfFieldStorage(Address base, /// Given an expression of pointer type, try to /// derive a more accurate bound on the alignment of the pointer. Address CIRGenFunction::emitPointerWithAlignment(const Expr *expr, - LValueBaseInfo *baseInfo) { + LValueBaseInfo *baseInfo, + TBAAAccessInfo *tbaaInfo) { // We allow this with ObjC object pointers because of fragile ABIs. assert(expr->getType()->isPointerType() || expr->getType()->isObjCObjectPointerType()); @@ -98,12 +100,18 @@ Address CIRGenFunction::emitPointerWithAlignment(const Expr *expr, *baseInfo = innerBaseInfo; if (isa(ce)) { - LValueBaseInfo targetTypeBaseInfo; - const QualType pointeeType = expr->getType()->getPointeeType(); + + LValueBaseInfo targetTypeBaseInfo; const CharUnits align = cgm.getNaturalTypeAlignment(pointeeType, &targetTypeBaseInfo); + if (tbaaInfo) { + TBAAAccessInfo targetTypeTbaaInfo = + cgm.getTBAAAccessInfo(pointeeType); + *tbaaInfo = cgm.mergeTBAAInfoForCast(*tbaaInfo, targetTypeTbaaInfo); + } + // If the source l-value is opaque, honor the alignment of the // casted-to type. if (innerBaseInfo.getAlignmentSource() != AlignmentSource::Decl) { @@ -315,7 +323,8 @@ static LValue emitGlobalVarDeclLValue(CIRGenFunction &cgf, const Expr *e, void CIRGenFunction::emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile, QualType ty, - LValueBaseInfo baseInfo, bool isInit, + LValueBaseInfo baseInfo, + TBAAAccessInfo tbaaInfo, bool isInit, bool isNontemporal) { assert(!cir::MissingFeatures::opLoadStoreThreadLocal()); @@ -338,8 +347,7 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, Address addr, value = emitToMemory(value, ty); - assert(!cir::MissingFeatures::opLoadStoreTbaa()); - LValue atomicLValue = LValue::makeAddr(addr, ty, baseInfo); + LValue atomicLValue = LValue::makeAddr(addr, ty, baseInfo, tbaaInfo); if (ty->isAtomicType() || (!isInit && isLValueSuitableForInlineAtomic(atomicLValue))) { emitAtomicStore(RValue::get(value), atomicLValue, isInit); @@ -357,14 +365,14 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, Address addr, } assert(currSrcLoc && "must pass in source location"); - builder.createStore(*currSrcLoc, value, addr, isVolatile); + cir::StoreOp store = + builder.createStore(*currSrcLoc, value, addr, isVolatile); + cgm.decorateOperationWithTBAA(store, tbaaInfo); if (isNontemporal) { cgm.errorNYI(addr.getPointer().getLoc(), "emitStoreOfScalar nontemporal"); return; } - - assert(!cir::MissingFeatures::opTBAA()); } // TODO: Replace this with a proper TargetInfo function call. @@ -426,6 +434,8 @@ Address CIRGenFunction::getAddrOfBitFieldStorage(LValue base, LValue CIRGenFunction::emitLValueForBitField(LValue base, const FieldDecl *field) { LValueBaseInfo baseInfo = base.getBaseInfo(); + TBAAAccessInfo tbaaInfo{}; + const CIRGenRecordLayout &layout = cgm.getTypes().getCIRGenRecordLayout(field->getParent()); const CIRGenBitFieldInfo &info = layout.getBitFieldInfo(field); @@ -444,7 +454,7 @@ LValue CIRGenFunction::emitLValueForBitField(LValue base, // TODO(cir): Support TBAA for bit fields. assert(!cir::MissingFeatures::opTBAA()); LValueBaseInfo fieldBaseInfo(baseInfo.getAlignmentSource()); - return LValue::makeBitfield(addr, info, fieldType, fieldBaseInfo); + return LValue::makeBitfield(addr, info, fieldType, fieldBaseInfo, tbaaInfo); } LValue CIRGenFunction::emitLValueForField(LValue base, const FieldDecl *field) { @@ -457,7 +467,10 @@ LValue CIRGenFunction::emitLValueForField(LValue base, const FieldDecl *field) { const RecordDecl *rec = field->getParent(); AlignmentSource baseAlignSource = baseInfo.getAlignmentSource(); LValueBaseInfo fieldBaseInfo(getFieldAlignmentSource(baseAlignSource)); - assert(!cir::MissingFeatures::opTBAA()); + TBAAAccessInfo fieldTbaaInfo{}; + + // TODO(cir): Initialize tbaa info + assert(!MissingFeatures::opTBAA()); Address addr = base.getAddress(); if (auto *classDecl = dyn_cast(rec)) { @@ -489,11 +502,12 @@ LValue CIRGenFunction::emitLValueForField(LValue base, const FieldDecl *field) { // If this is a reference field, load the reference right now. if (fieldType->isReferenceType()) { assert(!cir::MissingFeatures::opTBAA()); - LValue refLVal = makeAddrLValue(addr, fieldType, fieldBaseInfo); + LValue refLVal = + makeAddrLValue(addr, fieldType, fieldBaseInfo, fieldTbaaInfo); if (recordCVR & Qualifiers::Volatile) refLVal.getQuals().addVolatile(); addr = emitLoadOfReference(refLVal, getLoc(field->getSourceRange()), - &fieldBaseInfo); + &fieldBaseInfo, &fieldTbaaInfo); // Qualifiers on the struct don't apply to the referencee. recordCVR = 0; @@ -561,13 +575,15 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, LValue lvalue, } emitStoreOfScalar(value, lvalue.getAddress(), lvalue.isVolatile(), - lvalue.getType(), lvalue.getBaseInfo(), isInit, + lvalue.getType(), lvalue.getBaseInfo(), + lvalue.getTBAAInfo(), isInit, /*isNontemporal=*/false); } mlir::Value CIRGenFunction::emitLoadOfScalar(Address addr, bool isVolatile, QualType ty, SourceLocation loc, - LValueBaseInfo baseInfo) { + LValueBaseInfo baseInfo, + TBAAAccessInfo tbaaInfo) { assert(!cir::MissingFeatures::opLoadStoreThreadLocal()); mlir::Type eltTy = addr.getElementType(); @@ -586,8 +602,7 @@ mlir::Value CIRGenFunction::emitLoadOfScalar(Address addr, bool isVolatile, "emitLoadOfScalar Vec3 & PreserveVec3Type disabled"); } - assert(!cir::MissingFeatures::opLoadStoreTbaa()); - LValue atomicLValue = LValue::makeAddr(addr, ty, baseInfo); + LValue atomicLValue = LValue::makeAddr(addr, ty, baseInfo, tbaaInfo); if (ty->isAtomicType() || isLValueSuitableForInlineAtomic(atomicLValue)) cgm.errorNYI("emitLoadOfScalar: load atomic"); @@ -596,7 +611,9 @@ mlir::Value CIRGenFunction::emitLoadOfScalar(Address addr, bool isVolatile, assert(!cir::MissingFeatures::opLoadEmitScalarRangeCheck()); - mlir::Value loadOp = builder.createLoad(getLoc(loc), addr, isVolatile); + cir::LoadOp loadOp = builder.createLoad(getLoc(loc), addr, isVolatile); + cgm.decorateOperationWithTBAA(loadOp, tbaaInfo); + if (!ty->isBooleanType() && ty->hasBooleanRepresentation()) cgm.errorNYI("emitLoadOfScalar: boolean type with boolean representation"); @@ -606,9 +623,9 @@ mlir::Value CIRGenFunction::emitLoadOfScalar(Address addr, bool isVolatile, mlir::Value CIRGenFunction::emitLoadOfScalar(LValue lvalue, SourceLocation loc) { assert(!cir::MissingFeatures::opLoadStoreNontemporal()); - assert(!cir::MissingFeatures::opLoadStoreTbaa()); return emitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(), - lvalue.getType(), loc, lvalue.getBaseInfo()); + lvalue.getType(), loc, lvalue.getBaseInfo(), + lvalue.getTBAAInfo()); } /// Given an expression that represents a value lvalue, this @@ -2285,17 +2302,20 @@ RValue CIRGenFunction::emitReferenceBindingToExpr(const Expr *e) { } Address CIRGenFunction::emitLoadOfReference(LValue refLVal, mlir::Location loc, - LValueBaseInfo *pointeeBaseInfo) { + LValueBaseInfo *pointeeBaseInfo, + TBAAAccessInfo *pointeeTbaaInfo) { if (refLVal.isVolatile()) cgm.errorNYI(loc, "load of volatile reference"); + QualType pointeeType = refLVal.getType()->getPointeeType(); cir::LoadOp load = cir::LoadOp::create(builder, loc, refLVal.getAddress().getElementType(), refLVal.getAddress().getPointer()); - assert(!cir::MissingFeatures::opTBAA()); + cgm.decorateOperationWithTBAA(load, refLVal.getTBAAInfo()); + if (pointeeTbaaInfo) + *pointeeTbaaInfo = cgm.getTBAAAccessInfo(pointeeType); - QualType pointeeType = refLVal.getType()->getPointeeType(); CharUnits align = cgm.getNaturalTypeAlignment(pointeeType, pointeeBaseInfo); return Address(load, convertTypeForMem(pointeeType), align); } @@ -2306,10 +2326,11 @@ LValue CIRGenFunction::emitLoadOfReferenceLValue(Address refAddr, AlignmentSource source) { LValue refLVal = makeAddrLValue(refAddr, refTy, LValueBaseInfo(source)); LValueBaseInfo pointeeBaseInfo; - assert(!cir::MissingFeatures::opTBAA()); - Address pointeeAddr = emitLoadOfReference(refLVal, loc, &pointeeBaseInfo); + TBAAAccessInfo tbaaAccessInfo; + Address pointeeAddr = + emitLoadOfReference(refLVal, loc, &pointeeBaseInfo, &tbaaAccessInfo); return makeAddrLValue(pointeeAddr, refLVal.getType()->getPointeeType(), - pointeeBaseInfo); + pointeeBaseInfo, tbaaAccessInfo); } void CIRGenFunction::emitTrap(mlir::Location loc, bool createNewBlock) { diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp index 872fc8d14ad95..b466b68b8f0ae 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp @@ -983,7 +983,13 @@ void CIRGenFunction::emitAggregateCopy(LValue dest, LValue src, QualType ty, [[maybe_unused]] cir::CopyOp copyOp = builder.createCopy(destPtr.getPointer(), srcPtr.getPointer(), isVolatile); - assert(!cir::MissingFeatures::opTBAA()); + assert(!cir::MissingFeatures::opTBAAStruct()); + + if (cgm.getCodeGenOpts().NewStructPathTBAA) { + TBAAAccessInfo tbaaInfo = cgm.mergeTBAAInfoForMemoryTransfer( + dest.getTBAAInfo(), src.getTBAAInfo()); + cgm.decorateOperationWithTBAA(copyOp, tbaaInfo); + } } // TODO(cir): This could be shared with classic codegen. diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp index 33bdfa315a9ea..c38bf6d90c915 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp @@ -14,6 +14,7 @@ #include "CIRGenCXXABI.h" #include "CIRGenCall.h" +#include "CIRGenTBAA.h" #include "CIRGenValue.h" #include "mlir/IR/Location.h" #include "clang/AST/ExprCXX.h" diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index a3a7b4a207a81..e0a57c358c06b 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -16,6 +16,7 @@ #include "CIRGenBuilder.h" #include "CIRGenCall.h" #include "CIRGenModule.h" +#include "CIRGenTBAA.h" #include "CIRGenTypeCache.h" #include "CIRGenValue.h" #include "EHScopeStack.h" @@ -838,11 +839,13 @@ class CIRGenFunction : public CIRGenTypeCache { LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source = AlignmentSource::Type) { - return makeAddrLValue(addr, ty, LValueBaseInfo(source)); + return makeAddrLValue(addr, ty, LValueBaseInfo(source), + cgm.getTBAAAccessInfo(ty)); } - LValue makeAddrLValue(Address addr, QualType ty, LValueBaseInfo baseInfo) { - return LValue::makeAddr(addr, ty, baseInfo); + LValue makeAddrLValue(Address addr, QualType ty, LValueBaseInfo baseInfo, + TBAAAccessInfo tbaaInfo = {}) { + return LValue::makeAddr(addr, ty, baseInfo, tbaaInfo); } void initializeVTablePointers(mlir::Location loc, @@ -1670,7 +1673,8 @@ class CIRGenFunction : public CIRGenTypeCache { RValue emitLoadOfLValue(LValue lv, SourceLocation loc); Address emitLoadOfReference(LValue refLVal, mlir::Location loc, - LValueBaseInfo *pointeeBaseInfo); + LValueBaseInfo *pointeeBaseInfo, + TBAAAccessInfo *pointeeTbaaInfo); LValue emitLoadOfReferenceLValue(Address refAddr, mlir::Location loc, QualType refTy, AlignmentSource source); @@ -1680,7 +1684,8 @@ class CIRGenFunction : public CIRGenTypeCache { /// l-value. mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc); mlir::Value emitLoadOfScalar(Address addr, bool isVolatile, QualType ty, - SourceLocation loc, LValueBaseInfo baseInfo); + SourceLocation loc, LValueBaseInfo baseInfo, + TBAAAccessInfo tbaaInfo); /// Emit code to compute a designator that specifies the location /// of the expression. @@ -1719,7 +1724,8 @@ class CIRGenFunction : public CIRGenTypeCache { /// reasonable to just ignore the returned alignment when it isn't from an /// explicit source. Address emitPointerWithAlignment(const clang::Expr *expr, - LValueBaseInfo *baseInfo = nullptr); + LValueBaseInfo *baseInfo = nullptr, + TBAAAccessInfo *tbaaInfo = nullptr); /// Emits a reference binding to the passed in expression. RValue emitReferenceBindingToExpr(const Expr *e); @@ -1749,7 +1755,8 @@ class CIRGenFunction : public CIRGenTypeCache { void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile, clang::QualType ty, LValueBaseInfo baseInfo, - bool isInit = false, bool isNontemporal = false); + TBAAAccessInfo tbaaInfo, bool isInit = false, + bool isNontemporal = false); void emitStoreOfScalar(mlir::Value value, LValue lvalue, bool isInit); /// Store the specified rvalue into the specified diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index e09d3de5aac9a..0b9834c6bffbc 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -20,12 +20,15 @@ #include "clang/AST/DeclOpenACC.h" #include "clang/AST/GlobalDecl.h" #include "clang/AST/RecordLayout.h" +#include "clang/AST/TypeBase.h" #include "clang/Basic/SourceManager.h" +#include "clang/CIR/Dialect/IR/CIRAttrs.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" #include "clang/CIR/Interfaces/CIROpInterfaces.h" #include "clang/CIR/MissingFeatures.h" #include "CIRGenFunctionInfo.h" +#include "CIRGenTBAA.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/Location.h" #include "mlir/IR/MLIRContext.h" @@ -96,6 +99,12 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext, astContext.getTargetInfo().getPointerAlign(LangAS::Default)) .getQuantity(); + // Enable TBAA unless it's suppressed. TSan and TySan need TBAA even at O0. + if (langOpts.Sanitize.hasOneOf(SanitizerKind::Thread | SanitizerKind::Type) || + (!codeGenOpts.RelaxedAliasing && codeGenOpts.OptimizationLevel > 0)) + tbaa = std::make_unique(&mlirContext, astContext, getTypes(), + theModule, codeGenOpts, getLangOpts()); + const unsigned charSize = astContext.getTargetInfo().getCharWidth(); uCharTy = cir::IntType::get(&getMLIRContext(), charSize, /*isSigned=*/false); @@ -160,7 +169,6 @@ CharUnits CIRGenModule::getClassPointerAlignment(const CXXRecordDecl *rd) { CharUnits CIRGenModule::getNaturalTypeAlignment(QualType t, LValueBaseInfo *baseInfo) { - assert(!cir::MissingFeatures::opTBAA()); // FIXME: This duplicates logic in ASTContext::getTypeAlignIfKnown, but // that doesn't return the information we need to compute baseInfo. @@ -2492,3 +2500,72 @@ DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc, llvm::StringRef feature) { return errorNYI(loc.getBegin(), feature) << loc; } + +cir::TBAAAttr CIRGenModule::getTBAATypeInfo(QualType type) { + if (!tbaa) { + return nullptr; + } + return tbaa->getTypeInfo(type); +} + +TBAAAccessInfo CIRGenModule::getTBAAAccessInfo(QualType accessType) { + if (!tbaa) { + return TBAAAccessInfo{}; + } + if (getLangOpts().CUDAIsDevice) { + llvm_unreachable("TBAA access NYI"); + } + return tbaa->getAccessInfo(accessType); +} + +TBAAAccessInfo +CIRGenModule::getTBAAVTablePtrAccessInfo(mlir::Type vTablePtrType) { + if (!tbaa) + return TBAAAccessInfo{}; + + llvm_unreachable("TBAA vtable pointer access NYI"); + return tbaa->getVTablePtrAccessInfo(vTablePtrType); +} + +mlir::ArrayAttr CIRGenModule::getTBAAStructInfo(QualType type) { + if (!tbaa) + return nullptr; + return tbaa->getTBAAStructInfo(type); +} + +cir::TBAAAttr CIRGenModule::getTBAABaseTypeInfo(QualType type) { + if (!tbaa) { + return nullptr; + } + return tbaa->getBaseTypeInfo(type); +} + +mlir::ArrayAttr CIRGenModule::getTBAAAccessTagInfo(TBAAAccessInfo tbaaInfo) { + if (!tbaa) { + return nullptr; + } + return tbaa->getAccessTagInfo(tbaaInfo); +} + +TBAAAccessInfo CIRGenModule::mergeTBAAInfoForCast(TBAAAccessInfo sourceInfo, + TBAAAccessInfo targetInfo) { + if (!tbaa) + return TBAAAccessInfo(); + return tbaa->mergeTBAAInfoForCast(sourceInfo, targetInfo); +} + +TBAAAccessInfo +CIRGenModule::mergeTBAAInfoForConditionalOperator(TBAAAccessInfo infoA, + TBAAAccessInfo infoB) { + if (!tbaa) + return TBAAAccessInfo(); + return tbaa->mergeTBAAInfoForConditionalOperator(infoA, infoB); +} + +TBAAAccessInfo +CIRGenModule::mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo destInfo, + TBAAAccessInfo srcInfo) { + if (!tbaa) + return TBAAAccessInfo(); + return tbaa->mergeTBAAInfoForConditionalOperator(destInfo, srcInfo); +} diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h index 2c45bb238f95a..d83575226231e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -15,17 +15,21 @@ #include "CIRGenBuilder.h" #include "CIRGenCall.h" +#include "CIRGenTBAA.h" #include "CIRGenTypeCache.h" #include "CIRGenTypes.h" #include "CIRGenVTables.h" #include "CIRGenValue.h" #include "clang/AST/CharUnits.h" +#include "clang/CIR/Dialect/IR/CIRAttrs.h" #include "clang/CIR/Dialect/IR/CIRDataLayout.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" #include "TargetInfo.h" +#include "mlir/Dialect/LLVMIR/LLVMAttrs.h" #include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/MLIRContext.h" #include "clang/AST/Decl.h" @@ -85,6 +89,8 @@ class CIRGenModule : public CIRGenTypeCache { std::unique_ptr abi; + std::unique_ptr tbaa; + CIRGenTypes genTypes; /// Holds information about C++ vtables. @@ -325,6 +331,52 @@ class CIRGenModule : public CIRGenTypeCache { clang::CharUnits getNaturalTypeAlignment(clang::QualType t, LValueBaseInfo *baseInfo); + /// Get attribute used to describe accesses to objects of + /// the given type. + cir::TBAAAttr getTBAATypeInfo(QualType type); + + /// Get TBAA information that describes an access to an object of the given + /// type. + TBAAAccessInfo getTBAAAccessInfo(QualType accessType); + + /// Get the TBAA information that describes an access to a virtual table + /// pointer. + TBAAAccessInfo getTBAAVTablePtrAccessInfo(mlir::Type vTablePtrType); + + mlir::ArrayAttr getTBAAStructInfo(QualType type); + + /// Get metadata that describes the given base access type. Return null if the + /// type is not suitable for use in TBAA access tags. + cir::TBAAAttr getTBAABaseTypeInfo(QualType type); + + mlir::ArrayAttr getTBAAAccessTagInfo(TBAAAccessInfo tbaaInfo); + + /// Get merged TBAA information for the purposes of type casts. + TBAAAccessInfo mergeTBAAInfoForCast(TBAAAccessInfo sourceInfo, + TBAAAccessInfo targetInfo); + + /// Get merged TBAA information for the purposes of conditional operator. + TBAAAccessInfo mergeTBAAInfoForConditionalOperator(TBAAAccessInfo infoA, + TBAAAccessInfo infoB); + + /// Get merged TBAA information for the purposes of memory transfer calls. + TBAAAccessInfo mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo destInfo, + TBAAAccessInfo srcInfo); + + /// Get TBAA information for an access with a given base lvalue. + TBAAAccessInfo getTBAAInfoForSubobject(LValue base, QualType accessType) { + if (base.getTBAAInfo().isMayAlias()) + return TBAAAccessInfo::getMayAliasInfo(); + return getTBAAAccessInfo(accessType); + } + + template + void decorateOperationWithTBAA(Op op, TBAAAccessInfo tbaaInfo) { + if (mlir::ArrayAttr tag = getTBAAAccessTagInfo(tbaaInfo)) { + op.setTbaaAttr(tag); + } + } + /// TODO: Add TBAAAccessInfo CharUnits getDynamicOffsetAlignment(CharUnits actualBaseAlign, const CXXRecordDecl *baseDecl, diff --git a/clang/lib/CIR/CodeGen/CIRGenTBAA.cpp b/clang/lib/CIR/CodeGen/CIRGenTBAA.cpp new file mode 100644 index 0000000000000..9db01e85c5e44 --- /dev/null +++ b/clang/lib/CIR/CodeGen/CIRGenTBAA.cpp @@ -0,0 +1,64 @@ +#include "CIRGenTBAA.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" + +namespace clang::CIRGen { + +static cir::TBAAAttr tbaaNYI(mlir::MLIRContext *ctx) { + return cir::TBAAAttr::get(ctx); +} + +CIRGenTBAA::CIRGenTBAA(mlir::MLIRContext *mlirContext, + clang::ASTContext &astContext, CIRGenTypes &types, + mlir::ModuleOp moduleOp, + const clang::CodeGenOptions &codeGenOpts, + const clang::LangOptions &features) + : mlirContext(mlirContext), astContext(astContext), types(types), + moduleOp(moduleOp), codeGenOpts(codeGenOpts), features(features) {} + +cir::TBAAAttr CIRGenTBAA::getTypeInfo(clang::QualType qty) { + return tbaaNYI(mlirContext); +} + +TBAAAccessInfo CIRGenTBAA::getAccessInfo(clang::QualType accessType) { + return TBAAAccessInfo(); +} + +TBAAAccessInfo CIRGenTBAA::getVTablePtrAccessInfo(mlir::Type vtablePtrType) { + return TBAAAccessInfo(); +} + +mlir::ArrayAttr CIRGenTBAA::getTBAAStructInfo(clang::QualType qty) { + return mlir::ArrayAttr::get(mlirContext, {}); +} + +cir::TBAAAttr CIRGenTBAA::getBaseTypeInfo(clang::QualType qty) { + return tbaaNYI(mlirContext); +} + +mlir::ArrayAttr CIRGenTBAA::getAccessTagInfo(TBAAAccessInfo tbaaInfo) { + return mlir::ArrayAttr::get(mlirContext, {tbaaNYI(mlirContext)}); +} + +TBAAAccessInfo CIRGenTBAA::mergeTBAAInfoForCast(TBAAAccessInfo sourceInfo, + TBAAAccessInfo targetInfo) { + return TBAAAccessInfo(); +} + +TBAAAccessInfo +CIRGenTBAA::mergeTBAAInfoForConditionalOperator(TBAAAccessInfo infoA, + TBAAAccessInfo infoB) { + return TBAAAccessInfo(); +} + +TBAAAccessInfo +CIRGenTBAA::mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo destInfo, + TBAAAccessInfo srcInfo) { + return TBAAAccessInfo(); +} + +} // namespace clang::CIRGen diff --git a/clang/lib/CIR/CodeGen/CIRGenTBAA.h b/clang/lib/CIR/CodeGen/CIRGenTBAA.h new file mode 100644 index 0000000000000..c05e8f4e6f964 --- /dev/null +++ b/clang/lib/CIR/CodeGen/CIRGenTBAA.h @@ -0,0 +1,188 @@ +//===--- CIRGenTBAA.h - TBAA information for LLVM CIRGen --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This is the code that manages TBAA information and defines the TBAA policy +// for the optimizer to use. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENTBAA_H +#define LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENTBAA_H + +#include "mlir/IR/Attributes.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/MLIRContext.h" +#include "clang/AST/Type.h" +#include "clang/Basic/CodeGenOptions.h" +#include "clang/CIR/Dialect/IR/CIRAttrs.h" + +namespace clang::CIRGen { + +class CIRGenTypes; + +enum class TBAAAccessKind : unsigned { + Ordinary, + MayAlias, + Incomplete, +}; + +// Describes a memory access in terms of TBAA. +struct TBAAAccessInfo { + TBAAAccessInfo(TBAAAccessKind kind, cir::TBAAAttr baseType, + cir::TBAAAttr accessType, uint64_t offset, uint64_t size) + : kind(kind), baseType(baseType), accessType(accessType), offset(offset), + size(size) {} + + TBAAAccessInfo(cir::TBAAAttr baseType, cir::TBAAAttr accessType, + uint64_t offset, uint64_t size) + : TBAAAccessInfo(TBAAAccessKind::Ordinary, baseType, accessType, offset, + size) {} + + explicit TBAAAccessInfo(cir::TBAAAttr accessType, uint64_t size) + : TBAAAccessInfo(TBAAAccessKind::Ordinary, /* baseType= */ {}, accessType, + /* offset= */ 0, size) {} + + TBAAAccessInfo() + : TBAAAccessInfo(/* accessType= */ nullptr, /* size= */ 0) {}; + + static TBAAAccessInfo getMayAliasInfo() { + return TBAAAccessInfo(TBAAAccessKind::MayAlias, /* baseType= */ {}, + /* accessType= */ nullptr, + /* offset= */ 0, /* size= */ 0); + } + + static TBAAAccessInfo getIncompleteInfo() { + return TBAAAccessInfo(TBAAAccessKind::Incomplete, /* baseType= */ {}, + /* accessType= */ {}, + /* offset= */ 0, /* size= */ 0); + } + + bool isMayAlias() const { return kind == TBAAAccessKind::MayAlias; } + + bool isIncomplete() const { return kind == TBAAAccessKind::Incomplete; } + + bool operator==(const TBAAAccessInfo &other) const { + return kind == other.kind && baseType == other.baseType && + accessType == other.accessType && offset == other.offset && + size == other.size; + } + + bool operator!=(const TBAAAccessInfo &other) const { + return !(*this == other); + } + + explicit operator bool() const { return *this != TBAAAccessInfo(); } + + /// The kind of the access descriptor. + TBAAAccessKind kind; + + /// The base/leading access type. May be null if this access + /// descriptor represents an access that is not considered to be an access + /// to an aggregate or union member. + cir::TBAAAttr baseType; + + /// The final access type. May be null if there is no TBAA + /// information available about this access. + cir::TBAAAttr accessType; + + /// The byte offset of the final access within the base one. Must be + /// zero if the base access type is not specified. + uint64_t offset; + + /// The size of access, in bytes. + uint64_t size; +}; + +/// This class organizes the cross-module state that is used while lowering AST +/// types to LLVM types. +class CIRGenTBAA { + mlir::MLIRContext *mlirContext; + [[maybe_unused]] clang::ASTContext &astContext; + [[maybe_unused]] CIRGenTypes &types; + mlir::ModuleOp moduleOp; + [[maybe_unused]] const clang::CodeGenOptions &codeGenOpts; + [[maybe_unused]] const clang::LangOptions &features; + +public: + CIRGenTBAA(mlir::MLIRContext *mlirContext, clang::ASTContext &astContext, + CIRGenTypes &types, mlir::ModuleOp moduleOp, + const clang::CodeGenOptions &codeGenOpts, + const clang::LangOptions &features); + + /// Get attribute used to describe accesses to objects of the given type. + cir::TBAAAttr getTypeInfo(clang::QualType qty); + + /// Get TBAA information that describes an access to an object of the given + /// type. + TBAAAccessInfo getAccessInfo(clang::QualType accessType); + + /// Get the TBAA information that describes an access to a virtual table + /// pointer. + TBAAAccessInfo getVTablePtrAccessInfo(mlir::Type vtablePtrType); + + /// Get the TBAAStruct attributes to be used for a memcpy of the given type. + mlir::ArrayAttr getTBAAStructInfo(clang::QualType qty); + + /// Get attribute that describes the given base access type. Return null if + /// the type is not suitable for use in TBAA access tags. + cir::TBAAAttr getBaseTypeInfo(clang::QualType qty); + + /// Get TBAA tag for a given memory access. + mlir::ArrayAttr getAccessTagInfo(TBAAAccessInfo tbaaInfo); + + /// Get merged TBAA information for the purpose of type casts. + TBAAAccessInfo mergeTBAAInfoForCast(TBAAAccessInfo sourceInfo, + TBAAAccessInfo targetInfo); + + /// Get merged TBAA information for the purpose of conditional operator. + TBAAAccessInfo mergeTBAAInfoForConditionalOperator(TBAAAccessInfo infoA, + TBAAAccessInfo infoB); + + /// Get merged TBAA information for the purpose of memory transfer calls. + TBAAAccessInfo mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo destInfo, + TBAAAccessInfo srcInfo); +}; +} // namespace clang::CIRGen + +namespace llvm { +template <> struct DenseMapInfo { + static clang::CIRGen::TBAAAccessInfo getEmptyKey() { + unsigned unsignedKey = DenseMapInfo::getEmptyKey(); + return clang::CIRGen::TBAAAccessInfo( + static_cast(unsignedKey), + DenseMapInfo::getEmptyKey(), + DenseMapInfo::getEmptyKey(), + DenseMapInfo::getEmptyKey(), + DenseMapInfo::getEmptyKey()); + } + static clang::CIRGen::TBAAAccessInfo getTombstoneKey() { + unsigned unsignedKey = DenseMapInfo::getTombstoneKey(); + return clang::CIRGen::TBAAAccessInfo( + static_cast(unsignedKey), + DenseMapInfo::getTombstoneKey(), + DenseMapInfo::getTombstoneKey(), + DenseMapInfo::getTombstoneKey(), + DenseMapInfo::getTombstoneKey()); + } + static unsigned getHashValue(const clang::CIRGen::TBAAAccessInfo &val) { + auto kindValue = static_cast(val.kind); + return DenseMapInfo::getHashValue(kindValue) ^ + DenseMapInfo::getHashValue(val.baseType) ^ + DenseMapInfo::getHashValue(val.accessType) ^ + DenseMapInfo::getHashValue(val.offset) ^ + DenseMapInfo::getHashValue(val.size); + } + static bool isEqual(const clang::CIRGen::TBAAAccessInfo &lhs, + const clang::CIRGen::TBAAAccessInfo &rhs) { + return lhs == rhs; + } +}; +} // namespace llvm + +#endif diff --git a/clang/lib/CIR/CodeGen/CIRGenValue.h b/clang/lib/CIR/CodeGen/CIRGenValue.h index 2002bd7e7c488..6324292ee4770 100644 --- a/clang/lib/CIR/CodeGen/CIRGenValue.h +++ b/clang/lib/CIR/CodeGen/CIRGenValue.h @@ -20,6 +20,7 @@ #include "clang/AST/Type.h" #include "CIRGenRecordLayout.h" +#include "CIRGenTBAA.h" #include "mlir/IR/Value.h" #include "clang/CIR/MissingFeatures.h" @@ -172,9 +173,11 @@ class LValue { mlir::Type elementType; LValueBaseInfo baseInfo; const CIRGenBitFieldInfo *bitFieldInfo{nullptr}; + TBAAAccessInfo tbaaInfo; void initialize(clang::QualType type, clang::Qualifiers quals, - clang::CharUnits alignment, LValueBaseInfo baseInfo) { + clang::CharUnits alignment, LValueBaseInfo baseInfo, + TBAAAccessInfo tbaaInfo) { assert((!alignment.isZero() || type->isIncompleteType()) && "initializing l-value with zero alignment!"); this->type = type; @@ -223,6 +226,9 @@ class LValue { assert(!cir::MissingFeatures::addressIsKnownNonNull()); } + TBAAAccessInfo getTBAAInfo() const { return tbaaInfo; } + void setTBAAInfo(TBAAAccessInfo info) { tbaaInfo = info; } + const clang::Qualifiers &getQuals() const { return quals; } clang::Qualifiers &getQuals() { return quals; } @@ -230,7 +236,8 @@ class LValue { void setBaseInfo(LValueBaseInfo info) { baseInfo = info; } static LValue makeAddr(Address address, clang::QualType t, - LValueBaseInfo baseInfo) { + LValueBaseInfo baseInfo, + TBAAAccessInfo tbaaInfo = {}) { // Classic codegen sets the objc gc qualifier here. That requires an // ASTContext, which is passed in from CIRGenFunction::makeAddrLValue. assert(!cir::MissingFeatures::objCGC()); @@ -239,7 +246,8 @@ class LValue { r.lvType = Simple; r.v = address.getPointer(); r.elementType = address.getElementType(); - r.initialize(t, t.getQualifiers(), address.getAlignment(), baseInfo); + r.initialize(t, t.getQualifiers(), address.getAlignment(), baseInfo, + tbaaInfo); return r; } @@ -274,26 +282,28 @@ class LValue { } static LValue makeVectorElt(Address vecAddress, mlir::Value index, - clang::QualType t, LValueBaseInfo baseInfo) { + clang::QualType t, LValueBaseInfo baseInfo, + TBAAAccessInfo tbaaInfo = {}) { LValue r; r.lvType = VectorElt; r.v = vecAddress.getPointer(); r.elementType = vecAddress.getElementType(); r.vectorIdx = index; - r.initialize(t, t.getQualifiers(), vecAddress.getAlignment(), baseInfo); + r.initialize(t, t.getQualifiers(), vecAddress.getAlignment(), baseInfo, + tbaaInfo); return r; } static LValue makeExtVectorElt(Address vecAddress, mlir::ArrayAttr elts, - clang::QualType type, - LValueBaseInfo baseInfo) { + clang::QualType type, LValueBaseInfo baseInfo, + TBAAAccessInfo tbaaInfo = {}) { LValue r; r.lvType = ExtVectorElt; r.v = vecAddress.getPointer(); r.elementType = vecAddress.getElementType(); r.vectorElts = elts; r.initialize(type, type.getQualifiers(), vecAddress.getAlignment(), - baseInfo); + baseInfo, tbaaInfo); return r; } @@ -319,13 +329,15 @@ class LValue { /// \param Info - The information describing how to perform the bit-field /// access. static LValue makeBitfield(Address addr, const CIRGenBitFieldInfo &info, - clang::QualType type, LValueBaseInfo baseInfo) { + clang::QualType type, LValueBaseInfo baseInfo, + TBAAAccessInfo tbaaInfo) { LValue r; r.lvType = BitField; r.v = addr.getPointer(); r.elementType = addr.getElementType(); r.bitFieldInfo = &info; - r.initialize(type, type.getQualifiers(), addr.getAlignment(), baseInfo); + r.initialize(type, type.getQualifiers(), addr.getAlignment(), baseInfo, + tbaaInfo); return r; } }; diff --git a/clang/lib/CIR/CodeGen/CMakeLists.txt b/clang/lib/CIR/CodeGen/CMakeLists.txt index d3e2290ceea0b..81f844404096f 100644 --- a/clang/lib/CIR/CodeGen/CMakeLists.txt +++ b/clang/lib/CIR/CodeGen/CMakeLists.txt @@ -40,6 +40,7 @@ add_clang_library(clangCIR CIRGenStmt.cpp CIRGenStmtOpenACC.cpp CIRGenStmtOpenACCLoop.cpp + CIRGenTBAA.cpp CIRGenTypes.cpp CIRGenVTables.cpp TargetInfo.cpp diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 6bf543cf794b7..daa8b6cf4b7ea 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -61,7 +61,6 @@ struct CIROpAsmDialectInterface : public OpAsmDialectInterface { os << voidType.getAlias(); return AliasResult::OverridableAlias; } - return AliasResult::NoAlias; } @@ -78,6 +77,11 @@ 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; } }; diff --git a/clang/lib/CIR/Dialect/IR/CIRMemorySlot.cpp b/clang/lib/CIR/Dialect/IR/CIRMemorySlot.cpp index 66469e208d7b0..39c67e3f13163 100644 --- a/clang/lib/CIR/Dialect/IR/CIRMemorySlot.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRMemorySlot.cpp @@ -143,7 +143,8 @@ DeletionKind cir::CopyOp::removeBlockingUses( cir::StoreOp::create(builder, getLoc(), reachingDefinition, getDst(), /*isVolatile=*/false, /*alignment=*/mlir::IntegerAttr{}, - /*mem-order=*/cir::MemOrderAttr()); + /*mem-order=*/cir::MemOrderAttr(), + /*tbaa=*/mlir::ArrayAttr{}); return DeletionKind::Delete; } diff --git a/clang/test/CIR/CodeGen/tbaa.c b/clang/test/CIR/CodeGen/tbaa.c new file mode 100644 index 0000000000000..51729a589d083 --- /dev/null +++ b/clang/test/CIR/CodeGen/tbaa.c @@ -0,0 +1,23 @@ +// 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) { + if (*a == 1) { + *b = 2.0f; + } else { + *b = 3.0f; + } +} + +// 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]]])