From 2c39ad967d921ae8b26b2f7a3b16d811ce99a7f6 Mon Sep 17 00:00:00 2001 From: PikachuHy Date: Fri, 7 Mar 2025 14:13:30 +0800 Subject: [PATCH] [CIR][CIRGen][TBAA] Add support for pointer tbaa --- .../clang/CIR/Dialect/IR/CIRTBAAAttrs.td | 18 ++- clang/include/clang/CIR/MissingFeatures.h | 1 - clang/lib/CIR/CodeGen/CIRGenTBAA.cpp | 78 ++++++++++- clang/lib/CIR/CodeGen/CIRGenTBAA.h | 2 +- .../Lowering/DirectToLLVM/LowerTBAAToLLVM.cpp | 6 +- clang/test/CIR/CodeGen/tbaa-enum.c | 15 +-- clang/test/CIR/CodeGen/tbaa-enum.cpp | 15 +-- clang/test/CIR/CodeGen/tbaa-pointer.cpp | 126 ++++++++++++++++++ clang/test/CIR/CodeGen/tbaa-struct.cpp | 17 ++- 9 files changed, 243 insertions(+), 35 deletions(-) create mode 100644 clang/test/CIR/CodeGen/tbaa-pointer.cpp diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTBAAAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRTBAAAttrs.td index 83d3d24c05c8..96c05971345a 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTBAAAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTBAAAttrs.td @@ -22,22 +22,38 @@ def CIR_TBAAOmnipotentChar def CIR_TBAAScalarAttr : CIR_Attr<"TBAAScalar", "tbaa_scalar", [], "TBAAAttr"> { let summary = "Describes a scalar type in TBAA with an identifier."; - let parameters = (ins StringRefParameter<> : $id, CIR_AnyType : $type); + let parameters = (ins StringRefParameter<>:$id, + CIR_AnyType:$type, + OptionalParameter<"cir::TBAAScalarAttr">:$parent); let description = [{ Define a TBAA scalar attribute. + The optional `parent` attribute is used to describe the parent type of the + scalar type. If the `parent` is null or omitted, the parent type is the + `omnipotent char` type. Example: ```mlir // CIR_TBAAScalarAttr #tbaa_scalar = #cir.tbaa_scalar #tbaa_scalar1 = #cir.tbaa_scalar + + #tbaa_scalar2 = #cir.tbaa_scalar> + #tbaa_scalar3 = #cir.tbaa_scalar, + parent = #tbaa_scalar2> ``` See the following link for more details: https://llvm.org/docs/LangRef.html#tbaa-metadata }]; + let builders = [ + AttrBuilder<(ins "llvm::StringRef":$id, + "mlir::Type":$type), [{ + return $_get($_ctxt, id, type, /*parent =*/ nullptr); + }]> + ]; + let assemblyFormat = "`<` struct(params) `>`"; } diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index d29a905fd4a2..124fd2012c41 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -65,7 +65,6 @@ struct MissingFeatures { static bool tbaaMergeTBAAInfo() { return false; } static bool tbaaMayAlias() { return false; } static bool tbaaNewStructPath() { return false; } - static bool tbaaPointer() { return false; } static bool emitNullabilityCheck() { return false; } static bool ptrAuth() { return false; } static bool memberFuncPtrAuthInfo() { return false; } diff --git a/clang/lib/CIR/CodeGen/CIRGenTBAA.cpp b/clang/lib/CIR/CodeGen/CIRGenTBAA.cpp index c1eb9326c04a..ff098d91e13e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTBAA.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenTBAA.cpp @@ -65,7 +65,7 @@ static bool isValidBaseType(clang::QualType qty) { return false; } -cir::TBAAAttr CIRGenTBAA::getScalarTypeInfo(clang::QualType qty) { +cir::TBAAScalarAttr CIRGenTBAA::getScalarTypeInfo(clang::QualType qty) { const clang::Type *ty = astContext.getCanonicalType(qty).getTypePtr(); assert(mlir::isa(ty)); const clang::BuiltinType *bty = mlir::dyn_cast(ty); @@ -159,12 +159,78 @@ cir::TBAAAttr CIRGenTBAA::getTypeInfoHelper(clang::QualType qty) { // they involve a significant representation difference. We don't // currently do so, however. if (ty->isPointerType() || ty->isReferenceType()) { - if (!codeGenOpts.PointerTBAA) { - return cir::TBAAScalarAttr::get(mlirContext, "any pointer", - types.convertType(qty)); + auto anyPtr = cir::TBAAScalarAttr::get(mlirContext, "any pointer", + types.convertType(qty)); + if (!codeGenOpts.PointerTBAA) + return anyPtr; + // C++ [basic.lval]p11 permits objects to accessed through an l-value of + // similar type. Two types are similar under C++ [conv.qual]p2 if the + // decomposition of the types into pointers, member pointers, and arrays has + // the same structure when ignoring cv-qualifiers at each level of the + // decomposition. Meanwhile, C makes T(*)[] and T(*)[N] compatible, which + // would really complicate any attempt to distinguish pointers to arrays by + // their bounds. It's simpler, and much easier to explain to users, to + // simply treat all pointers to arrays as pointers to their element type for + // aliasing purposes. So when creating a TBAA tag for a pointer type, we + // recursively ignore both qualifiers and array types when decomposing the + // pointee type. The only meaningful remaining structure is the number of + // pointer types we encountered along the way, so we just produce the tag + // "p ". If we do find a member pointer type, for now + // we just conservatively bail out with AnyPtr (below) rather than trying to + // create a tag that honors the similar-type rules while still + // distinguishing different kinds of member pointer. + unsigned ptrDepth = 0; + do { + ptrDepth++; + ty = ty->getPointeeType()->getBaseElementTypeUnsafe(); + } while (ty->isPointerType()); + assert(!isa(ty)); + // When the underlying type is a builtin type, we compute the pointee type + // string recursively, which is implicitly more forgiving than the standards + // require. Effectively, we are turning the question "are these types + // compatible/similar" into "are accesses to these types allowed to alias". + // In both C and C++, the latter question has special carve-outs for + // signedness mismatches that only apply at the top level. As a result, we + // are allowing e.g. `int *` l-values to access `unsigned *` objects. + SmallString<256> tyName; + + if (isa(ty)) { + auto scalarAttr = getScalarTypeInfo(ty->getCanonicalTypeInternal()); + tyName = scalarAttr.getId(); + } else { + // Be conservative if the type isn't a RecordType. We are specifically + // required to do this for member pointers until we implement the + // similar-types rule. + const auto *rt = ty->getAs(); + if (!rt) + return anyPtr; + + // For unnamed structs or unions C's compatible types rule applies. Two + // compatible types in different compilation units can have different + // mangled names, meaning the metadata emitted below would incorrectly + // mark them as no-alias. Use AnyPtr for such types in both C and C++, as + // C and C++ types may be visible when doing LTO. + // + // Note that using AnyPtr is overly conservative. We could summarize the + // members of the type, as per the C compatibility rule in the future. + // This also covers anonymous structs and unions, which have a different + // compatibility rule, but it doesn't matter because you can never have a + // pointer to an anonymous struct or union. + if (!rt->getDecl()->getDeclName()) + return anyPtr; + + // For non-builtin types use the mangled name of the canonical type. + llvm::raw_svector_ostream tyOut(tyName); + types.getCXXABI().getMangleContext().mangleCanonicalTypeName( + QualType(ty, 0), tyOut); } - assert(!cir::MissingFeatures::tbaaPointer()); - return tbaa_NYI(mlirContext); + + SmallString<256> outName("p"); + outName += std::to_string(ptrDepth); + outName += " "; + outName += tyName; + return cir::TBAAScalarAttr::get(mlirContext, outName, + types.convertType(qty), anyPtr); } // Accesses to arrays are accesses to objects of their element types. if (codeGenOpts.NewStructPathTBAA && ty->isArrayType()) { diff --git a/clang/lib/CIR/CodeGen/CIRGenTBAA.h b/clang/lib/CIR/CodeGen/CIRGenTBAA.h index 301adf414139..3272c1630916 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTBAA.h +++ b/clang/lib/CIR/CodeGen/CIRGenTBAA.h @@ -112,7 +112,7 @@ class CIRGenTBAA { // An internal helper function to generate metadata used // to describe accesses to objects of the given type. cir::TBAAAttr getTypeInfoHelper(clang::QualType qty); - cir::TBAAAttr getScalarTypeInfo(clang::QualType qty); + cir::TBAAScalarAttr getScalarTypeInfo(clang::QualType qty); cir::TBAAAttr getValidBaseTypeInfo(clang::QualType qty); cir::TBAAAttr getBaseTypeInfoHelper(const clang::Type *ty); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerTBAAToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerTBAAToLLVM.cpp index 09d5c2042bbd..d42a822c2215 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerTBAAToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerTBAAToLLVM.cpp @@ -25,7 +25,11 @@ class CIRToLLVMTBAAAttrLowering { if (auto scalarAttr = mlir::dyn_cast(tbaa)) { mlir::DataLayout layout; auto size = layout.getTypeSize(scalarAttr.getType()); - return createScalarTypeNode(scalarAttr.getId(), getChar(), size); + mlir::LLVM::TBAANodeAttr parent = + scalarAttr.getParent() + ? lowerCIRTBAAAttrToLLVMTBAAAttr(scalarAttr.getParent()) + : getChar(); + return createScalarTypeNode(scalarAttr.getId(), parent, size); } if (auto structAttr = mlir::dyn_cast(tbaa)) { llvm::SmallVector members; diff --git a/clang/test/CIR/CodeGen/tbaa-enum.c b/clang/test/CIR/CodeGen/tbaa-enum.c index 2136ab2303f7..e419b19c4909 100644 --- a/clang/test/CIR/CodeGen/tbaa-enum.c +++ b/clang/test/CIR/CodeGen/tbaa-enum.c @@ -1,16 +1,15 @@ // This is inspired from clang/test/CodeGen/tbaa.c, with both CIR and LLVM checks. -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir -O1 +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir -O1 -no-pointer-tbaa // 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 -disable-llvm-passes +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -O1 -disable-llvm-passes -no-pointer-tbaa // 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 -disable-llvm-passes -relaxed-aliasing +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -O1 -disable-llvm-passes -relaxed-aliasing -no-pointer-tbaa // 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 -disable-llvm-passes +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -O0 -disable-llvm-passes -no-pointer-tbaa // RUN: FileCheck --check-prefix=NO-TBAA --input-file=%t.ll %s // NO-TBAA-NOT: !tbaa -// CIR: #tbaa[[NYI:.*]] = #cir.tbaa // CIR: #tbaa[[CHAR:.*]] = #cir.tbaa_omnipotent_char // CIR: #tbaa[[INT:.*]] = #cir.tbaa_scalar // CIR: #tbaa[[LONG_LONG:.*]] = #cir.tbaa_scalar @@ -136,10 +135,10 @@ uint8_t g3(Enum8 *E, uint8_t *val) { return *val; } -// LLVM: [[TAG_i32]] = !{[[TYPE_i32:!.*]], [[TYPE_i32]], i64 0} -// LLVM: [[TYPE_i32]] = !{!"int", [[TYPE_char:!.*]], -// LLVM: [[TYPE_char]] = !{!"omnipotent char", [[TAG_c_tbaa:!.*]], +// LLVM: [[TYPE_char:!.*]] = !{!"omnipotent char", [[TAG_c_tbaa:!.*]], // LLVM: [[TAG_c_tbaa]] = !{!"Simple C/C++ TBAA"} +// LLVM: [[TAG_i32]] = !{[[TYPE_i32:!.*]], [[TYPE_i32]], i64 0} +// LLVM: [[TYPE_i32]] = !{!"int", [[TYPE_char]], // LLVM: [[TAG_i64]] = !{[[TYPE_i64:!.*]], [[TYPE_i64]], i64 0} // LLVM: [[TYPE_i64]] = !{!"long long", [[TYPE_char]], // LLVM: [[TAG_long]] = !{[[TYPE_long:!.*]], [[TYPE_long]], i64 0} diff --git a/clang/test/CIR/CodeGen/tbaa-enum.cpp b/clang/test/CIR/CodeGen/tbaa-enum.cpp index 6dc469a21e58..bcf42e9ff921 100644 --- a/clang/test/CIR/CodeGen/tbaa-enum.cpp +++ b/clang/test/CIR/CodeGen/tbaa-enum.cpp @@ -1,16 +1,15 @@ // This is inspired from clang/test/CodeGen/tbaa.c, with both CIR and LLVM checks. -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir -O1 +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir -O1 -no-pointer-tbaa // 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 -disable-llvm-passes +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -O1 -disable-llvm-passes -no-pointer-tbaa // 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 -disable-llvm-passes -relaxed-aliasing +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -O1 -disable-llvm-passes -relaxed-aliasing -no-pointer-tbaa // 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 -disable-llvm-passes +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -O0 -disable-llvm-passes -no-pointer-tbaa // RUN: FileCheck --check-prefix=NO-TBAA --input-file=%t.ll %s // NO-TBAA-NOT: !tbaa -// CIR: #tbaa[[NYI:.*]] = #cir.tbaa // CIR: #tbaa[[CHAR:.*]] = #cir.tbaa_omnipotent_char // CIR: #tbaa[[INT:.*]] = #cir.tbaa_scalar // CIR: #tbaa[[EnumAuto32:.*]] = #cir.tbaa_scalar @@ -139,10 +138,10 @@ uint8_t g3(Enum8 *E, uint8_t *val) { return *val; } -// LLVM: [[TAG_i32]] = !{[[TYPE_i32:!.*]], [[TYPE_i32]], i64 0} -// LLVM: [[TYPE_i32]] = !{!"int", [[TYPE_char:!.*]], -// LLVM: [[TYPE_char]] = !{!"omnipotent char", [[TAG_c_tbaa:!.*]], +// LLVM: [[TYPE_char:!.*]] = !{!"omnipotent char", [[TAG_c_tbaa:!.*]], // LLVM: [[TAG_c_tbaa]] = !{!"Simple C++ TBAA"} +// LLVM: [[TAG_i32]] = !{[[TYPE_i32:!.*]], [[TYPE_i32]], i64 0} +// LLVM: [[TYPE_i32]] = !{!"int", [[TYPE_char]], // LLVM: [[TAG_EnumAuto32]] = !{[[TYPE_EnumAuto32:!.*]], [[TYPE_EnumAuto32]], i64 0} // LLVM: [[TYPE_EnumAuto32]] = !{!"_ZTS10EnumAuto32", [[TYPE_char]], // LLVM: [[TAG_i64]] = !{[[TYPE_i64:!.*]], [[TYPE_i64]], i64 0} diff --git a/clang/test/CIR/CodeGen/tbaa-pointer.cpp b/clang/test/CIR/CodeGen/tbaa-pointer.cpp new file mode 100644 index 000000000000..e766aec1533d --- /dev/null +++ b/clang/test/CIR/CodeGen/tbaa-pointer.cpp @@ -0,0 +1,126 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir -O1 -no-pointer-tbaa +// 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 -no-pointer-tbaa +// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir -O1 -pointer-tbaa +// RUN: FileCheck --check-prefix=CIR-POINTER-TBAA --input-file=%t.cir %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -O1 -pointer-tbaa +// RUN: FileCheck --check-prefix=LLVM-POINTER-TBAA --input-file=%t.ll %s + +// CIR: #tbaa[[CHAR:.*]] = #cir.tbaa_omnipotent_char +// CIR: #tbaa[[INT:.*]] = #cir.tbaa_scalar +// CIR: #tbaa[[PTR_TO_A:.*]] = #cir.tbaa_scalar> +// CIR: #tbaa[[STRUCT_A:.*]] = #cir.tbaa_struct, <#tbaa[[INT]], 4>}> +// CIR: #tbaa[[TAG_STRUCT_A_a:.*]] = #cir.tbaa_tag + +// CIR-POINTER-TBAA: #tbaa[[CHAR:.*]] = #cir.tbaa_omnipotent_char +// CIR-POINTER-TBAA: #tbaa[[INT:.*]] = #cir.tbaa_scalar +// CIR-POINTER-TBAA-DAG: #tbaa[[p1_INT:.*]] = #cir.tbaa_scalar +// CIR-POINTER-TBAA-DAG: #tbaa[[p2_INT:.*]] = #cir.tbaa_scalar> +// CIR-POINTER-TBAA-DAG: #tbaa[[p3_INT:.*]] = #cir.tbaa_scalar>> +// CIR-POINTER-TBAA-DAG: #tbaa[[STRUCT_A:.*]] = #cir.tbaa_struct, <#tbaa[[INT]], 4>}> +// CIR-POINTER-TBAA-DAG: #tbaa[[p1_STRUCT_A:.*]] = #cir.tbaa_scalar +// CIR-POINTER-TBAA-DAG: #tbaa[[p2_STRUCT_A:.*]] = #cir.tbaa_scalar> +// CIR-POINTER-TBAA-DAG: #tbaa[[p3_STRUCT_A:.*]] = #cir.tbaa_scalar>> + +int test_scalar_pointer(int*** p3) { + int* p1; + int** p2; + p2 = *p3; + p1 = *p2; + int t = *p1; + + // CIR-POINTER-TBAA-LABEL: _Z19test_scalar_pointerPPPi + // CIR-POINTER-TBAA: %{{.*}} = cir.load deref %{{.*}} : !cir.ptr>>>, !cir.ptr>> tbaa(#tbaa[[p3_INT]]) + // CIR-POINTER-TBAA: %{{.*}} = cir.load deref %{{.*}} : !cir.ptr>>, !cir.ptr> tbaa(#tbaa[[p2_INT]]) + // CIR-POINTER-TBAA: %{{.*}} = cir.load deref %{{.*}} : !cir.ptr>, !cir.ptr tbaa(#tbaa[[p1_INT]]) + + // LLVM-LABEL: _Z19test_scalar_pointerPPPi + // LLVM: %[[p2:.*]] = load ptr, ptr %{{.*}}, align 8, !tbaa ![[TBAA_ANY_PTR:.*]] + // LLVM: %[[p1:.*]] = load ptr, ptr %[[p2]], align 8, !tbaa ![[TBAA_ANY_PTR]] + // LLVM: %[[t:.*]] = load i32, ptr %[[p1]], align 4, !tbaa ![[TBAA_INT:.*]] + + // LLVM-POINTER-TBAA-LABEL: _Z19test_scalar_pointerPPPi + // LLVM-POINTER-TBAA: %[[p2:.*]] = load ptr, ptr %{{.*}}, align 8, !tbaa ![[TBAA_p2_INT:.*]] + // LLVM-POINTER-TBAA: %[[p1:.*]] = load ptr, ptr %[[p2]], align 8, !tbaa ![[TBAA_p1_INT:.*]] + // LLVM-POINTER-TBAA: %[[t:.*]] = load i32, ptr %[[p1]], align 4, !tbaa ![[TBAA_INT:.*]] + return t; +} + +struct A { + int a; + int b; +}; + +int test_struct_pointer(A*** p3, int A::***m3) { + A* p1; + A** p2; + p2 = *p3; + p1 = *p2; + + // CIR-POINTER-TBAA-LABEL: _Z19test_struct_pointerPPP1APPMS_i + // CIR-POINTER-TBAA: %{{.*}} = cir.load deref %{{.*}} : !cir.ptr>>>, !cir.ptr>> tbaa(#tbaa[[p3_STRUCT_A]]) + // CIR-POINTER-TBAA: %{{.*}} = cir.load deref %{{.*}} : !cir.ptr>>, !cir.ptr> tbaa(#tbaa[[p2_STRUCT_A]]) + // CIR-POINTER-TBAA: %{{.*}} = cir.load %{{.*}} : !cir.ptr>, !cir.ptr tbaa(#tbaa[[p1_STRUCT_A]]) + + // LLVM-LABEL: _Z19test_struct_pointerPPP1APPMS_i + // LLVM: %[[p2:.*]] = load ptr, ptr %{{.*}}, align 8, !tbaa ![[TBAA_ANY_PTR]] + // LLVM: %[[p1:.*]] = load ptr, ptr %[[p2]], align 8, !tbaa ![[TBAA_ANY_PTR]] + // LLVM: %[[t:.*]] = load i32, ptr %[[p1]], align 4, !tbaa ![[TBAA_STRUCT_A_a:.*]] + + // LLVM-POINTER-TBAA-LABEL: _Z19test_struct_pointerPPP1APPMS_i + // LLVM-POINTER-TBAA: %[[p2:.*]] = load ptr, ptr %{{.*}}, align 8, !tbaa ![[TBAA_p2_STRUCT_A:.*]] + // LLVM-POINTER-TBAA: %[[p1:.*]] = load ptr, ptr %[[p2]], align 8, !tbaa ![[TBAA_p1_STRUCT_A:.*]] + // LLVM-POINTER-TBAA: %[[t:.*]] = load i32, ptr %[[p1]], align 4, !tbaa ![[TBAA_STRUCT_A_a:.*]] + return p1->a; +} + +void test_member_pointer(A& a, int A::***m3, int val) { + + // CIR-LABEL: _Z19test_member_pointerR1APPMS_ii + // CIR: %{{.*}} = cir.load %{{.*}} : !cir.ptr>, !cir.data_member tbaa(#tbaa[[CHAR]]) + + // CIR-POINTER-TBAA-LABEL: _Z19test_member_pointerR1APPMS_ii + // CIR-POINTER-TBAA: %{{.*}} = cir.load %{{.*}} : !cir.ptr>, !cir.data_member tbaa(#tbaa[[CHAR]]) + + // LLVM-LABEL: _Z19test_member_pointerR1APPMS_ii + // LLVM: %[[m2:.*]] = load ptr, ptr %{{.*}}, align 8, !tbaa ![[TBAA_ANY_PTR:.*]] + // LLVM: %[[m1:.*]] = load i64, ptr %[[m2]], align 8, !tbaa ![[TBAA_member_ptr:.*]] + // LLVM: %[[A_a:.*]] = getelementptr i8, ptr %{{.*}}, i64 %[[m1]] + // LLVM: store i32 %{{.*}}, ptr %[[A_a]], align 4, !tbaa ![[TBAA_INT]] + + // LLVM-POINTER-TBAA-LABEL: _Z19test_member_pointerR1APPMS_ii + // LLVM-POINTER-TBAA: %[[m2:.*]] = load ptr, ptr %{{.*}}, align 8, !tbaa ![[TBAA_ANY_PTR:.*]] + // LLVM-POINTER-TBAA: %[[m1:.*]] = load i64, ptr %[[m2]], align 8, !tbaa ![[TBAA_member_ptr:.*]] + // LLVM-POINTER-TBAA: %[[A_a:.*]] = getelementptr i8, ptr %{{.*}}, i64 %[[m1]] + // LLVM-POINTER-TBAA: store i32 %{{.*}}, ptr %[[A_a]], align 4, !tbaa ![[TBAA_INT]] + a.***m3 = val; +} + +// LLVM: ![[TBAA_ANY_PTR]] = !{![[TBAA_ANY_PTR_PARENT:.*]], ![[TBAA_ANY_PTR_PARENT]], i64 0} +// LLVM: ![[TBAA_ANY_PTR_PARENT]] = !{!"any pointer", ![[CHAR:.*]], i64 0} +// LLVM: ![[CHAR]] = !{!"omnipotent char", ![[ROOT:.*]], i64 0} +// LLVM: ![[ROOT]] = !{!"Simple C++ TBAA"} +// LLVM: ![[TBAA_INT]] = !{![[TBAA_INT_PARENT:.*]], ![[TBAA_INT_PARENT]], i64 0} +// LLVM: ![[TBAA_INT_PARENT]] = !{!"int", ![[CHAR]], i64 0} +// LLVM: ![[TBAA_STRUCT_A_a]] = !{![[TBAA_STRUCT_A:.*]], ![[TBAA_INT_PARENT]], i64 0} +// LLVM: ![[TBAA_STRUCT_A]] = !{!"_ZTS1A", ![[TBAA_INT_PARENT]], i64 0, ![[TBAA_INT_PARENT]], i64 4} +// LLVM: ![[TBAA_member_ptr]] = !{![[CHAR]], ![[CHAR]], i64 0} + +// LLVM-POINTER-TBAA: ![[TBAA_p2_INT]] = !{![[TBAA_p2_INT_PARENT:.*]], ![[TBAA_p2_INT_PARENT]], i64 0} +// LLVM-POINTER-TBAA: ![[TBAA_p2_INT_PARENT]] = !{!"p2 int", ![[TBAA_ANY_PTR_PARENT:.*]], i64 0} +// LLVM-POINTER-TBAA: ![[TBAA_ANY_PTR_PARENT]] = !{!"any pointer", ![[CHAR:.*]], i64 0} +// LLVM-POINTER-TBAA: ![[CHAR]] = !{!"omnipotent char", ![[ROOT:.*]], i64 0} +// LLVM-POINTER-TBAA: ![[ROOT]] = !{!"Simple C++ TBAA"} +// LLVM-POINTER-TBAA: ![[TBAA_p1_INT]] = !{![[TBAA_p1_INT_PARENT:.*]], ![[TBAA_p1_INT_PARENT]], i64 0} +// LLVM-POINTER-TBAA: ![[TBAA_p1_INT_PARENT]] = !{!"p1 int", ![[TBAA_ANY_PTR_PARENT]], i64 0} +// LLVM-POINTER-TBAA: ![[TBAA_INT]] = !{![[TBAA_INT_PARENT:.*]], ![[TBAA_INT_PARENT]], i64 +// LLVM-POINTER-TBAA: ![[TBAA_INT_PARENT]] = !{!"int", ![[CHAR]], i64 0} +// LLVM-POINTER-TBAA: ![[TBAA_p2_STRUCT_A]] = !{![[TBAA_p2_STRUCT_A_PARENT:.*]], ![[TBAA_p2_STRUCT_A_PARENT]], i64 0} +// LLVM-POINTER-TBAA: ![[TBAA_p2_STRUCT_A_PARENT]] = !{!"p2 _ZTS1A", ![[TBAA_ANY_PTR_PARENT]], i64 0} +// LLVM-POINTER-TBAA: ![[TBAA_p1_STRUCT_A]] = !{![[TBAA_p1_STRUCT_A_PARENT:.*]], ![[TBAA_p1_STRUCT_A_PARENT]], i64 0} +// LLVM-POINTER-TBAA: ![[TBAA_p1_STRUCT_A_PARENT]] = !{!"p1 _ZTS1A", ![[TBAA_ANY_PTR_PARENT]], i64 0} +// LLVM-POINTER-TBAA: ![[TBAA_STRUCT_A_a]] = !{![[TBAA_STRUCT_A:.*]], ![[TBAA_INT_PARENT]], i64 0} +// LLVM-POINTER-TBAA: ![[TBAA_STRUCT_A]] = !{!"_ZTS1A", ![[TBAA_INT_PARENT]], i64 0, ![[TBAA_INT_PARENT]], i64 4} +// LLVM-POINTER-TBAA: ![[TBAA_ANY_PTR]] = !{![[TBAA_ANY_PTR_PARENT]], ![[TBAA_ANY_PTR_PARENT]], i64 0} +// LLVM-POINTER-TBAA: ![[TBAA_member_ptr]] = !{![[CHAR]], ![[CHAR]], i64 0} diff --git a/clang/test/CIR/CodeGen/tbaa-struct.cpp b/clang/test/CIR/CodeGen/tbaa-struct.cpp index a071ce3f4ae6..17b05fad9fde 100644 --- a/clang/test/CIR/CodeGen/tbaa-struct.cpp +++ b/clang/test/CIR/CodeGen/tbaa-struct.cpp @@ -2,19 +2,18 @@ // g13 is not supported due to DiscreteBitFieldABI is NYI. // see clang/lib/CIR/CodeGen/CIRRecordLayoutBuilder.cpp CIRRecordLowering::accumulateBitFields -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir -O1 +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir -O1 -no-pointer-tbaa // 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 -disable-llvm-passes -no-struct-path-tbaa +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -O1 -disable-llvm-passes -no-struct-path-tbaa -no-pointer-tbaa // RUN: FileCheck --check-prefix=CHECK --input-file=%t.ll %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -O1 -disable-llvm-passes +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -O1 -disable-llvm-passes -no-pointer-tbaa // RUN: FileCheck --check-prefixes=PATH,OLD-PATH --input-file=%t.ll %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -O1 -disable-llvm-passes -relaxed-aliasing +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -O1 -disable-llvm-passes -relaxed-aliasing -no-pointer-tbaa // 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 -disable-llvm-passes +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -O0 -disable-llvm-passes -no-pointer-tbaa // RUN: FileCheck --check-prefix=NO-TBAA --input-file=%t.ll %s // NO-TBAA-NOT: !tbaa -// CIR: #tbaa[[NYI:.*]] = #cir.tbaa // CIR: #tbaa[[CHAR:.*]] = #cir.tbaa_omnipotent_char // CIR: #tbaa[[INT:.*]] = #cir.tbaa_scalar // CIR: #tbaa[[SHORT:.*]] = #cir.tbaa_scalar @@ -377,10 +376,10 @@ uint32_t g15(StructS *S, StructS3 *S3, uint64_t count) { // LLVM: [[TYPE_i16]] = !{!"short", [[TYPE_char]], // LLVM: [[TAG_char]] = !{[[TYPE_char]], [[TYPE_char]], i64 0} -// OLD-PATH: [[TAG_i32]] = !{[[TYPE_INT:!.*]], [[TYPE_INT]], i64 0} -// OLD-PATH: [[TYPE_INT]] = !{!"int", [[TYPE_CHAR:!.*]], i64 0} -// OLD-PATH: [[TYPE_CHAR]] = !{!"omnipotent char", [[TAG_cxx_tbaa:!.*]], +// OLD-PATH: [[TYPE_CHAR:!.*]] = !{!"omnipotent char", [[TAG_cxx_tbaa:!.*]], // OLD-PATH: [[TAG_cxx_tbaa]] = !{!"Simple C++ TBAA"} +// OLD-PATH: [[TAG_i32]] = !{[[TYPE_INT:!.*]], [[TYPE_INT]], i64 0} +// OLD-PATH: [[TYPE_INT]] = !{!"int", [[TYPE_CHAR]], i64 0} // OLD-PATH: [[TAG_A_f32]] = !{[[TYPE_A:!.*]], [[TYPE_INT]], i64 4} // OLD-PATH: [[TYPE_A]] = !{!"_ZTS7StructA", [[TYPE_SHORT:!.*]], i64 0, [[TYPE_INT]], i64 4, [[TYPE_SHORT]], i64 8, [[TYPE_INT]], i64 12} // OLD-PATH: [[TYPE_SHORT:!.*]] = !{!"short", [[TYPE_CHAR]]