forked from OSchip/llvm-project
[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:
parent
9aa773381b
commit
ca2e7e5999
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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;
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue