[IRGen] Add !annotation metadata for auto-init stores.

This patch updates Clang's IRGen to add !annotation nodes with an
"auto-init" annotation to all stores for auto-initialization.

As discussed in 'RFC: Combining Annotation Metadata and Remarks'
(http://lists.llvm.org/pipermail/llvm-dev/2020-November/146393.html)
this allows using optimization remarks to track down where auto-init
code was inserted (and not removed by optimizations).

There are a few cases in the tests where !annotation gets dropped by
optimizations. Those optimizations will be updated in subsequent
patches.

This patch is based on a patch by Francis Visoiu Mistrih.

Reviewed By: thegameg, paquette

Differential Revision: https://reviews.llvm.org/D91417
This commit is contained in:
Florian Hahn 2020-11-16 10:25:49 +00:00
parent 9aa773381b
commit ca2e7e5999
7 changed files with 438 additions and 209 deletions

View File

@ -78,7 +78,8 @@ static void initializeAlloca(CodeGenFunction &CGF, AllocaInst *AI, Value *Size,
}
if (CGF.CGM.stopAutoInit())
return;
CGF.Builder.CreateMemSet(AI, Byte, Size, AlignmentInBytes);
auto *I = CGF.Builder.CreateMemSet(AI, Byte, Size, AlignmentInBytes);
I->addAnnotationMetadata("auto-init");
}
/// getBuiltinLibFunction - Given a builtin id for a function like

View File

@ -911,14 +911,17 @@ static bool canEmitInitWithFewStoresAfterBZero(llvm::Constant *Init,
/// the scalar stores that would be required.
static void emitStoresForInitAfterBZero(CodeGenModule &CGM,
llvm::Constant *Init, Address Loc,
bool isVolatile, CGBuilderTy &Builder) {
bool isVolatile, CGBuilderTy &Builder,
bool IsAutoInit) {
assert(!Init->isNullValue() && !isa<llvm::UndefValue>(Init) &&
"called emitStoresForInitAfterBZero for zero or undef value.");
if (isa<llvm::ConstantInt>(Init) || isa<llvm::ConstantFP>(Init) ||
isa<llvm::ConstantVector>(Init) || isa<llvm::BlockAddress>(Init) ||
isa<llvm::ConstantExpr>(Init)) {
Builder.CreateStore(Init, Loc, isVolatile);
auto *I = Builder.CreateStore(Init, Loc, isVolatile);
if (IsAutoInit)
I->addAnnotationMetadata("auto-init");
return;
}
@ -931,7 +934,7 @@ static void emitStoresForInitAfterBZero(CodeGenModule &CGM,
if (!Elt->isNullValue() && !isa<llvm::UndefValue>(Elt))
emitStoresForInitAfterBZero(
CGM, Elt, Builder.CreateConstInBoundsGEP2_32(Loc, 0, i), isVolatile,
Builder);
Builder, IsAutoInit);
}
return;
}
@ -946,7 +949,7 @@ static void emitStoresForInitAfterBZero(CodeGenModule &CGM,
if (!Elt->isNullValue() && !isa<llvm::UndefValue>(Elt))
emitStoresForInitAfterBZero(CGM, Elt,
Builder.CreateConstInBoundsGEP2_32(Loc, 0, i),
isVolatile, Builder);
isVolatile, Builder, IsAutoInit);
}
}
@ -1154,7 +1157,7 @@ static Address createUnnamedGlobalForMemcpyFrom(CodeGenModule &CGM,
static void emitStoresForConstant(CodeGenModule &CGM, const VarDecl &D,
Address Loc, bool isVolatile,
CGBuilderTy &Builder,
llvm::Constant *constant) {
llvm::Constant *constant, bool IsAutoInit) {
auto *Ty = constant->getType();
uint64_t ConstantSize = CGM.getDataLayout().getTypeAllocSize(Ty);
if (!ConstantSize)
@ -1163,7 +1166,9 @@ static void emitStoresForConstant(CodeGenModule &CGM, const VarDecl &D,
bool canDoSingleStore = Ty->isIntOrIntVectorTy() ||
Ty->isPtrOrPtrVectorTy() || Ty->isFPOrFPVectorTy();
if (canDoSingleStore) {
Builder.CreateStore(constant, Loc, isVolatile);
auto *I = Builder.CreateStore(constant, Loc, isVolatile);
if (IsAutoInit)
I->addAnnotationMetadata("auto-init");
return;
}
@ -1172,14 +1177,17 @@ static void emitStoresForConstant(CodeGenModule &CGM, const VarDecl &D,
// If the initializer is all or mostly the same, codegen with bzero / memset
// then do a few stores afterward.
if (shouldUseBZeroPlusStoresToInitialize(constant, ConstantSize)) {
Builder.CreateMemSet(Loc, llvm::ConstantInt::get(CGM.Int8Ty, 0), SizeVal,
isVolatile);
auto *I = Builder.CreateMemSet(Loc, llvm::ConstantInt::get(CGM.Int8Ty, 0),
SizeVal, isVolatile);
if (IsAutoInit)
I->addAnnotationMetadata("auto-init");
bool valueAlreadyCorrect =
constant->isNullValue() || isa<llvm::UndefValue>(constant);
if (!valueAlreadyCorrect) {
Loc = Builder.CreateBitCast(Loc, Ty->getPointerTo(Loc.getAddressSpace()));
emitStoresForInitAfterBZero(CGM, constant, Loc, isVolatile, Builder);
emitStoresForInitAfterBZero(CGM, constant, Loc, isVolatile, Builder,
IsAutoInit);
}
return;
}
@ -1194,8 +1202,10 @@ static void emitStoresForConstant(CodeGenModule &CGM, const VarDecl &D,
assert(AP.getBitWidth() <= 8);
Value = AP.getLimitedValue();
}
Builder.CreateMemSet(Loc, llvm::ConstantInt::get(CGM.Int8Ty, Value), SizeVal,
isVolatile);
auto *I = Builder.CreateMemSet(
Loc, llvm::ConstantInt::get(CGM.Int8Ty, Value), SizeVal, isVolatile);
if (IsAutoInit)
I->addAnnotationMetadata("auto-init");
return;
}
@ -1208,7 +1218,8 @@ static void emitStoresForConstant(CodeGenModule &CGM, const VarDecl &D,
Address EltPtr = Builder.CreateStructGEP(Loc, i);
emitStoresForConstant(
CGM, D, EltPtr, isVolatile, Builder,
cast<llvm::Constant>(Builder.CreateExtractValue(constant, i)));
cast<llvm::Constant>(Builder.CreateExtractValue(constant, i)),
IsAutoInit);
}
return;
}
@ -1219,7 +1230,8 @@ static void emitStoresForConstant(CodeGenModule &CGM, const VarDecl &D,
Address EltPtr = Builder.CreateConstArrayGEP(Loc, i);
emitStoresForConstant(
CGM, D, EltPtr, isVolatile, Builder,
cast<llvm::Constant>(Builder.CreateExtractValue(constant, i)));
cast<llvm::Constant>(Builder.CreateExtractValue(constant, i)),
IsAutoInit);
}
return;
}
@ -1227,10 +1239,13 @@ static void emitStoresForConstant(CodeGenModule &CGM, const VarDecl &D,
}
// Copy from a global.
Builder.CreateMemCpy(Loc,
createUnnamedGlobalForMemcpyFrom(
CGM, D, Builder, constant, Loc.getAlignment()),
SizeVal, isVolatile);
auto *I =
Builder.CreateMemCpy(Loc,
createUnnamedGlobalForMemcpyFrom(
CGM, D, Builder, constant, Loc.getAlignment()),
SizeVal, isVolatile);
if (IsAutoInit)
I->addAnnotationMetadata("auto-init");
}
static void emitStoresForZeroInit(CodeGenModule &CGM, const VarDecl &D,
@ -1239,7 +1254,8 @@ static void emitStoresForZeroInit(CodeGenModule &CGM, const VarDecl &D,
llvm::Type *ElTy = Loc.getElementType();
llvm::Constant *constant =
constWithPadding(CGM, IsPattern::No, llvm::Constant::getNullValue(ElTy));
emitStoresForConstant(CGM, D, Loc, isVolatile, Builder, constant);
emitStoresForConstant(CGM, D, Loc, isVolatile, Builder, constant,
/*IsAutoInit=*/true);
}
static void emitStoresForPatternInit(CodeGenModule &CGM, const VarDecl &D,
@ -1249,7 +1265,8 @@ static void emitStoresForPatternInit(CodeGenModule &CGM, const VarDecl &D,
llvm::Constant *constant = constWithPadding(
CGM, IsPattern::Yes, initializationPatternFor(CGM, ElTy));
assert(!isa<llvm::UndefValue>(constant));
emitStoresForConstant(CGM, D, Loc, isVolatile, Builder, constant);
emitStoresForConstant(CGM, D, Loc, isVolatile, Builder, constant,
/*IsAutoInit=*/true);
}
static bool containsUndef(llvm::Constant *constant) {
@ -1718,14 +1735,16 @@ void CodeGenFunction::emitZeroOrPatternForAutoVarInit(QualType type,
case LangOptions::TrivialAutoVarInitKind::Uninitialized:
llvm_unreachable("Uninitialized handled by caller");
case LangOptions::TrivialAutoVarInitKind::Zero:
case LangOptions::TrivialAutoVarInitKind::Zero: {
if (CGM.stopAutoInit())
return;
if (!EltSize.isOne())
SizeVal = Builder.CreateNUWMul(SizeVal, CGM.getSize(EltSize));
Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0), SizeVal,
isVolatile);
auto *I = Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0),
SizeVal, isVolatile);
I->addAnnotationMetadata("auto-init");
break;
}
case LangOptions::TrivialAutoVarInitKind::Pattern: {
if (CGM.stopAutoInit())
@ -1754,10 +1773,12 @@ void CodeGenFunction::emitZeroOrPatternForAutoVarInit(QualType type,
llvm::PHINode *Cur = Builder.CreatePHI(Begin.getType(), 2, "vla.cur");
Cur->addIncoming(Begin.getPointer(), OriginBB);
CharUnits CurAlign = Loc.getAlignment().alignmentOfArrayElement(EltSize);
Builder.CreateMemCpy(Address(Cur, CurAlign),
createUnnamedGlobalForMemcpyFrom(
CGM, D, Builder, Constant, ConstantAlign),
BaseSizeInChars, isVolatile);
auto *I =
Builder.CreateMemCpy(Address(Cur, CurAlign),
createUnnamedGlobalForMemcpyFrom(
CGM, D, Builder, Constant, ConstantAlign),
BaseSizeInChars, isVolatile);
I->addAnnotationMetadata("auto-init");
llvm::Value *Next =
Builder.CreateInBoundsGEP(Int8Ty, Cur, BaseSizeInChars, "vla.next");
llvm::Value *Done = Builder.CreateICmpEQ(Next, End, "vla-init.isdone");
@ -1878,7 +1899,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
llvm::Type *BP = CGM.Int8Ty->getPointerTo(Loc.getAddressSpace());
emitStoresForConstant(
CGM, D, (Loc.getType() == BP) ? Loc : Builder.CreateBitCast(Loc, BP),
type.isVolatileQualified(), Builder, constant);
type.isVolatileQualified(), Builder, constant, /*IsAutoInit=*/false);
}
/// Emit an expression as an initializer for an object (variable, field, etc.)

File diff suppressed because it is too large Load Diff

View File

@ -11,9 +11,11 @@ extern "C" {
// UNINIT-NEXT: call void
// ZERO-LABEL: test_attribute_uninitialized(
// ZERO: alloca
// ZERO-NOT: !annotation
// ZERO-NEXT: call void
// PATTERN-LABEL: test_attribute_uninitialized(
// PATTERN: alloca
// PATTERN-NOT: !annotation
// PATTERN-NEXT: call void
void test_attribute_uninitialized() {
[[clang::uninitialized]] int i;

View File

@ -12,9 +12,9 @@ extern "C" {
// UNINIT-LABEL: test_selfinit(
// ZERO-LABEL: test_selfinit(
// ZERO: store i32 0, i32* %self, align 4
// ZERO: store i32 0, i32* %self, align 4, !annotation [[AUTO_INIT:!.+]]
// PATTERN-LABEL: test_selfinit(
// PATTERN: store i32 -1431655766, i32* %self, align 4
// PATTERN: store i32 -1431655766, i32* %self, align 4, !annotation [[AUTO_INIT:!.+]]
void test_selfinit() {
int self = self + 1;
used(self);
@ -22,9 +22,9 @@ void test_selfinit() {
// UNINIT-LABEL: test_block(
// ZERO-LABEL: test_block(
// ZERO: store i32 0, i32* %block
// ZERO: store i32 0, i32* %block, align 4, !annotation [[AUTO_INIT:!.+]]
// PATTERN-LABEL: test_block(
// PATTERN: store i32 -1431655766, i32* %block
// PATTERN: store i32 -1431655766, i32* %block, align 4, !annotation [[AUTO_INIT:!.+]]
void test_block() {
__block int block;
used(block);
@ -38,12 +38,12 @@ void test_block() {
// ZERO-LABEL: test_block_self_init(
// ZERO: %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8
// ZERO: %captured1 = getelementptr inbounds %struct.__block_byref_captured, %struct.__block_byref_captured* %captured, i32 0, i32 4
// ZERO-NEXT: store %struct.XYZ* null, %struct.XYZ** %captured1, align 8
// ZERO-NEXT: store %struct.XYZ* null, %struct.XYZ** %captured1, align 8, !annotation [[AUTO_INIT:!.+]]
// ZERO: %call = call %struct.XYZ* @create(
// PATTERN-LABEL: test_block_self_init(
// PATTERN: %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8
// PATTERN: %captured1 = getelementptr inbounds %struct.__block_byref_captured, %struct.__block_byref_captured* %captured, i32 0, i32 4
// PATTERN-NEXT: store %struct.XYZ* inttoptr (i64 -6148914691236517206 to %struct.XYZ*), %struct.XYZ** %captured1, align 8
// PATTERN-NEXT: store %struct.XYZ* inttoptr (i64 -6148914691236517206 to %struct.XYZ*), %struct.XYZ** %captured1, align 8, !annotation [[AUTO_INIT:!.+]]
// PATTERN: %call = call %struct.XYZ* @create(
using Block = void (^)();
typedef struct XYZ {
@ -62,12 +62,12 @@ void test_block_self_init() {
// ZERO-LABEL: test_block_captures_self_after_init(
// ZERO: %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8
// ZERO: %captured1 = getelementptr inbounds %struct.__block_byref_captured.1, %struct.__block_byref_captured.1* %captured, i32 0, i32 4
// ZERO-NEXT: store %struct.XYZ* null, %struct.XYZ** %captured1, align 8
// ZERO-NEXT: store %struct.XYZ* null, %struct.XYZ** %captured1, align 8, !annotation [[AUTO_INIT:!.+]]
// ZERO: %call = call %struct.XYZ* @create(
// PATTERN-LABEL: test_block_captures_self_after_init(
// PATTERN: %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8
// PATTERN: %captured1 = getelementptr inbounds %struct.__block_byref_captured.1, %struct.__block_byref_captured.1* %captured, i32 0, i32 4
// PATTERN-NEXT: store %struct.XYZ* inttoptr (i64 -6148914691236517206 to %struct.XYZ*), %struct.XYZ** %captured1, align 8
// PATTERN-NEXT: store %struct.XYZ* inttoptr (i64 -6148914691236517206 to %struct.XYZ*), %struct.XYZ** %captured1, align 8, !annotation [[AUTO_INIT:!.+]]
// PATTERN: %call = call %struct.XYZ* @create(
void test_block_captures_self_after_init() {
extern xyz_t create(Block block);
@ -97,13 +97,13 @@ void test_goto_unreachable_value() {
// ZERO-LABEL: test_goto(
// ZERO: if.then:
// ZERO: br label %jump
// ZERO: store i32 0, i32* %oops, align 4
// ZERO: store i32 0, i32* %oops, align 4, !annotation [[AUTO_INIT:!.+]]
// ZERO: br label %jump
// ZERO: jump:
// PATTERN-LABEL: test_goto(
// PATTERN: if.then:
// PATTERN: br label %jump
// PATTERN: store i32 -1431655766, i32* %oops, align 4
// PATTERN: store i32 -1431655766, i32* %oops, align 4, !annotation [[AUTO_INIT:!.+]]
// PATTERN: br label %jump
// PATTERN: jump:
void test_goto(int i) {
@ -119,12 +119,12 @@ void test_goto(int i) {
// UNINIT-LABEL: test_switch(
// ZERO-LABEL: test_switch(
// ZERO: sw.bb:
// ZERO-NEXT: store i32 0, i32* %oops, align 4
// ZERO-NEXT: store i32 0, i32* %oops, align 4, !annotation [[AUTO_INIT:!.+]]
// ZERO: sw.bb1:
// ZERO-NEXT: call void @{{.*}}used
// PATTERN-LABEL: test_switch(
// PATTERN: sw.bb:
// PATTERN-NEXT: store i32 -1431655766, i32* %oops, align 4
// PATTERN-NEXT: store i32 -1431655766, i32* %oops, align 4, !annotation [[AUTO_INIT:!.+]]
// PATTERN: sw.bb1:
// PATTERN-NEXT: call void @{{.*}}used
void test_switch(int i) {
@ -140,7 +140,7 @@ void test_switch(int i) {
// UNINIT-LABEL: test_vla(
// ZERO-LABEL: test_vla(
// ZERO: %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 4
// ZERO: call void @llvm.memset{{.*}}(i8* align 16 %{{.*}}, i8 0, i64 %[[SIZE]], i1 false)
// ZERO: call void @llvm.memset{{.*}}(i8* align 16 %{{.*}}, i8 0, i64 %[[SIZE]], i1 false), !annotation [[AUTO_INIT:!.+]]
// PATTERN-LABEL: test_vla(
// PATTERN: %vla.iszerosized = icmp eq i64 %{{.*}}, 0
// PATTERN: br i1 %vla.iszerosized, label %vla-init.cont, label %vla-setup.loop
@ -151,7 +151,7 @@ void test_switch(int i) {
// PATTERN: br label %vla-init.loop
// PATTERN: vla-init.loop:
// PATTERN: %vla.cur = phi i8* [ %vla.begin, %vla-setup.loop ], [ %vla.next, %vla-init.loop ]
// PATTERN: call void @llvm.memcpy{{.*}} %vla.cur, {{.*}}@__const.test_vla.vla
// PATTERN: call void @llvm.memcpy{{.*}} %vla.cur, {{.*}}@__const.test_vla.vla {{.*}}), !annotation [[AUTO_INIT:!.+]]
// PATTERN: %vla.next = getelementptr inbounds i8, i8* %vla.cur, i64 4
// PATTERN: %vla-init.isdone = icmp eq i8* %vla.next, %vla.end
// PATTERN: br i1 %vla-init.isdone, label %vla-init.cont, label %vla-init.loop
@ -177,11 +177,11 @@ void test_vla(int size) {
// ZERO-LABEL: test_alloca(
// ZERO: %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64
// ZERO-NEXT: %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align [[ALIGN:[0-9]+]]
// ZERO-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %[[ALLOCA]], i8 0, i64 %[[SIZE]], i1 false)
// ZERO-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %[[ALLOCA]], i8 0, i64 %[[SIZE]], i1 false), !annotation [[AUTO_INIT:!.+]]
// PATTERN-LABEL: test_alloca(
// PATTERN: %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64
// PATTERN-NEXT: %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align [[ALIGN:[0-9]+]]
// PATTERN-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %[[ALLOCA]], i8 -86, i64 %[[SIZE]], i1 false)
// PATTERN-NEXT: call void @llvm.memset{{.*}}(i8* align [[ALIGN]] %[[ALLOCA]], i8 -86, i64 %[[SIZE]], i1 false), !annotation [[AUTO_INIT:!.+]]
void test_alloca(int size) {
void *ptr = __builtin_alloca(size);
used(ptr);
@ -191,11 +191,11 @@ void test_alloca(int size) {
// ZERO-LABEL: test_alloca_with_align(
// ZERO: %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64
// ZERO-NEXT: %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align 128
// ZERO-NEXT: call void @llvm.memset{{.*}}(i8* align 128 %[[ALLOCA]], i8 0, i64 %[[SIZE]], i1 false)
// ZERO-NEXT: call void @llvm.memset{{.*}}(i8* align 128 %[[ALLOCA]], i8 0, i64 %[[SIZE]], i1 false), !annotation [[AUTO_INIT:!.+]]
// PATTERN-LABEL: test_alloca_with_align(
// PATTERN: %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64
// PATTERN-NEXT: %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align 128
// PATTERN-NEXT: call void @llvm.memset{{.*}}(i8* align 128 %[[ALLOCA]], i8 -86, i64 %[[SIZE]], i1 false)
// PATTERN-NEXT: call void @llvm.memset{{.*}}(i8* align 128 %[[ALLOCA]], i8 -86, i64 %[[SIZE]], i1 false), !annotation [[AUTO_INIT:!.+]]
void test_alloca_with_align(int size) {
void *ptr = __builtin_alloca_with_align(size, 1024);
used(ptr);
@ -204,7 +204,7 @@ void test_alloca_with_align(int size) {
// UNINIT-LABEL: test_struct_vla(
// ZERO-LABEL: test_struct_vla(
// ZERO: %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 16
// ZERO: call void @llvm.memset{{.*}}(i8* align 16 %{{.*}}, i8 0, i64 %[[SIZE]], i1 false)
// ZERO: call void @llvm.memset{{.*}}(i8* align 16 %{{.*}}, i8 0, i64 %[[SIZE]], i1 false), !annotation [[AUTO_INIT:!.+]]
// PATTERN-LABEL: test_struct_vla(
// PATTERN: %vla.iszerosized = icmp eq i64 %{{.*}}, 0
// PATTERN: br i1 %vla.iszerosized, label %vla-init.cont, label %vla-setup.loop
@ -215,7 +215,7 @@ void test_alloca_with_align(int size) {
// PATTERN: br label %vla-init.loop
// PATTERN: vla-init.loop:
// PATTERN: %vla.cur = phi i8* [ %vla.begin, %vla-setup.loop ], [ %vla.next, %vla-init.loop ]
// PATTERN: call void @llvm.memcpy{{.*}} %vla.cur, {{.*}}@__const.test_struct_vla.vla
// PATTERN: call void @llvm.memcpy{{.*}} %vla.cur, {{.*}}@__const.test_struct_vla.vla {{.*}}), !annotation [[AUTO_INIT:!.+]]
// PATTERN: %vla.next = getelementptr inbounds i8, i8* %vla.cur, i64 16
// PATTERN: %vla-init.isdone = icmp eq i8* %vla.next, %vla.end
// PATTERN: br i1 %vla-init.isdone, label %vla-init.cont, label %vla-init.loop
@ -247,12 +247,12 @@ void test_zsa(int size) {
int zsa[0];
used(zsa);
}
// UNINIT-LABEL: test_huge_uninit(
// ZERO-LABEL: test_huge_uninit(
// ZERO: call void @llvm.memset{{.*}}, i8 0, i64 65536,
// ZERO: call void @llvm.memset{{.*}}, i8 0, i64 65536, {{.*}}), !annotation [[AUTO_INIT:!.+]]
// PATTERN-LABEL: test_huge_uninit(
// PATTERN: call void @llvm.memset{{.*}}, i8 -86, i64 65536,
// PATTERN: call void @llvm.memset{{.*}}, i8 -86, i64 65536, {{.*}}), !annotation [[AUTO_INIT:!.+]]
void test_huge_uninit() {
// We can't emit this as an inline constant to a store instruction because
// SDNode hits an internal size limit.
@ -263,12 +263,14 @@ void test_huge_uninit() {
// UNINIT-LABEL: test_huge_small_init(
// ZERO-LABEL: test_huge_small_init(
// ZERO: call void @llvm.memset{{.*}}, i8 0, i64 65536,
// ZERO-NOT: !annotation
// ZERO: store i8 97,
// ZERO: store i8 98,
// ZERO: store i8 99,
// ZERO: store i8 100,
// PATTERN-LABEL: test_huge_small_init(
// PATTERN: call void @llvm.memset{{.*}}, i8 0, i64 65536,
// PATTERN-NOT: !annotation
// PATTERN: store i8 97,
// PATTERN: store i8 98,
// PATTERN: store i8 99,
@ -281,11 +283,15 @@ void test_huge_small_init() {
// UNINIT-LABEL: test_huge_larger_init(
// ZERO-LABEL: test_huge_larger_init(
// ZERO: call void @llvm.memcpy{{.*}} @__const.test_huge_larger_init.big, {{.*}}, i64 65536,
// ZERO-NOT: !annotation
// PATTERN-LABEL: test_huge_larger_init(
// PATTERN: call void @llvm.memcpy{{.*}} @__const.test_huge_larger_init.big, {{.*}}, i64 65536,
// PATTERN-NOT: !annotation
void test_huge_larger_init() {
char big[65536] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
used(big);
}
} // extern "C"
// CHECK: [[AUTO_INIT]] = !{ !"auto-init" }

View File

@ -340,6 +340,11 @@ public:
}
/// @}
/// Adds an !annotation metadata node with \p Annotation to this instruction.
/// If this instruction already has !annotation metadata, append \p Annotation
/// to the existing node.
void addAnnotationMetadata(StringRef Annotation);
/// Sets the metadata on this instruction from the AAMDNodes structure.
void setAAMetadata(const AAMDNodes &N);

View File

@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/Metadata.h"
#include "LLVMContextImpl.h"
#include "MetadataImpl.h"
#include "SymbolTableListTraitsImpl.h"
@ -38,7 +39,7 @@
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/TrackingMDRef.h"
#include "llvm/IR/Type.h"
@ -1305,6 +1306,27 @@ void Instruction::setMetadata(unsigned KindID, MDNode *Node) {
Value::setMetadata(KindID, Node);
}
void Instruction::addAnnotationMetadata(StringRef Name) {
MDBuilder MDB(getContext());
auto *Existing = getMetadata(LLVMContext::MD_annotation);
SmallVector<Metadata *, 4> Names;
bool AppendName = true;
if (Existing) {
auto *Tuple = cast<MDTuple>(Existing);
for (auto &N : Tuple->operands()) {
if (cast<MDString>(N.get())->getString() == Name)
AppendName = false;
Names.push_back(N.get());
}
}
if (AppendName)
Names.push_back(MDB.createString(Name));
MDNode *MD = MDTuple::get(getContext(), Names);
setMetadata(LLVMContext::MD_annotation, MD);
}
void Instruction::setAAMetadata(const AAMDNodes &N) {
setMetadata(LLVMContext::MD_tbaa, N.TBAA);
setMetadata(LLVMContext::MD_tbaa_struct, N.TBAAStruct);