Add basic support for adding !tbaa.struct metadata on llvm.memcpy calls for

struct assignment.

llvm-svn: 164853
This commit is contained in:
Dan Gohman 2012-09-28 21:58:29 +00:00
parent 3852b3e189
commit 22695fcec3
6 changed files with 102 additions and 1 deletions

View File

@ -1362,11 +1362,17 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,
}
}
}
// Determine the metadata to describe the position of any padding in this
// memcpy, as well as the TBAA tags for the members of the struct, in case
// the optimizer wishes to expand it in to scalar memory operations.
llvm::MDNode *TBAAStructTag = CGM.getTBAAStructInfo(Ty);
Builder.CreateMemCpy(DestPtr, SrcPtr,
llvm::ConstantInt::get(IntPtrTy,
TypeInfo.first.getQuantity()),
alignment.getQuantity(), isVolatile);
alignment.getQuantity(), isVolatile,
/*TBAATag=*/0, TBAAStructTag);
}
void CodeGenFunction::MaybeEmitStdInitializerListCleanup(llvm::Value *loc,

View File

@ -202,6 +202,12 @@ llvm::MDNode *CodeGenModule::getTBAAInfoForVTablePtr() {
return TBAA->getTBAAInfoForVTablePtr();
}
llvm::MDNode *CodeGenModule::getTBAAStructInfo(QualType QTy) {
if (!TBAA)
return 0;
return TBAA->getTBAAStructInfo(QTy);
}
void CodeGenModule::DecorateInstruction(llvm::Instruction *Inst,
llvm::MDNode *TBAAInfo) {
Inst->setMetadata(llvm::LLVMContext::MD_tbaa, TBAAInfo);

View File

@ -461,6 +461,7 @@ public:
llvm::MDNode *getTBAAInfo(QualType QTy);
llvm::MDNode *getTBAAInfoForVTablePtr();
llvm::MDNode *getTBAAStructInfo(QualType QTy);
bool isTypeConstant(QualType QTy, bool ExcludeCtorDtor);

View File

@ -17,6 +17,7 @@
#include "CodeGenTBAA.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/Mangle.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/LLVMContext.h"
@ -167,3 +168,59 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) {
llvm::MDNode *CodeGenTBAA::getTBAAInfoForVTablePtr() {
return MDHelper.createTBAANode("vtable pointer", getRoot());
}
bool
CodeGenTBAA::CollectFields(uint64_t BaseOffset,
QualType QTy,
SmallVectorImpl<llvm::MDBuilder::TBAAStructField> &
Fields,
bool MayAlias) {
/* Things not handled yet include: C++ base classes, bitfields, */
if (const RecordType *TTy = QTy->getAs<RecordType>()) {
const RecordDecl *RD = TTy->getDecl()->getDefinition();
if (RD->hasFlexibleArrayMember())
return false;
// TODO: Handle C++ base classes.
if (const CXXRecordDecl *Decl = dyn_cast<CXXRecordDecl>(RD))
if (Decl->bases_begin() != Decl->bases_end())
return false;
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
unsigned idx = 0;
for (RecordDecl::field_iterator i = RD->field_begin(),
e = RD->field_end(); i != e; ++i, ++idx) {
uint64_t Offset = BaseOffset +
Layout.getFieldOffset(idx) / Context.getCharWidth();
QualType FieldQTy = i->getType();
if (!CollectFields(Offset, FieldQTy, Fields,
MayAlias || TypeHasMayAlias(FieldQTy)))
return false;
}
return true;
}
/* Otherwise, treat whatever it is as a field. */
uint64_t Offset = BaseOffset;
uint64_t Size = Context.getTypeSizeInChars(QTy).getQuantity();
llvm::MDNode *TBAAInfo = MayAlias ? getChar() : getTBAAInfo(QTy);
Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size, TBAAInfo));
return true;
}
llvm::MDNode *
CodeGenTBAA::getTBAAStructInfo(QualType QTy) {
const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
if (llvm::MDNode *N = StructMetadataCache[Ty])
return N;
SmallVector<llvm::MDBuilder::TBAAStructField, 4> Fields;
if (CollectFields(0, QTy, Fields, TypeHasMayAlias(QTy)))
return MDHelper.createTBAAStructNode(Fields);
// For now, handle any other kind of type conservatively.
return StructMetadataCache[Ty] = NULL;
}

View File

@ -49,6 +49,10 @@ class CodeGenTBAA {
/// MetadataCache - This maps clang::Types to llvm::MDNodes describing them.
llvm::DenseMap<const Type *, llvm::MDNode *> MetadataCache;
/// StructMetadataCache - This maps clang::Types to llvm::MDNodes describing
/// them for struct assignments.
llvm::DenseMap<const Type *, llvm::MDNode *> StructMetadataCache;
llvm::MDNode *Root;
llvm::MDNode *Char;
@ -60,6 +64,13 @@ class CodeGenTBAA {
/// considered to be equivalent to it.
llvm::MDNode *getChar();
/// CollectFields - Collect information about the fields of a type for
/// !tbaa.struct metadata formation. Return false for an unsupported type.
bool CollectFields(uint64_t BaseOffset,
QualType Ty,
SmallVectorImpl<llvm::MDBuilder::TBAAStructField> &Fields,
bool MayAlias);
public:
CodeGenTBAA(ASTContext &Ctx, llvm::LLVMContext &VMContext,
const CodeGenOptions &CGO,
@ -74,6 +85,10 @@ public:
/// getTBAAInfoForVTablePtr - Get the TBAA MDNode to be used for a
/// dereference of a vtable pointer.
llvm::MDNode *getTBAAInfoForVTablePtr();
/// getTBAAStructInfo - Get the TBAAStruct MDNode to be used for a memcpy of
/// the given type.
llvm::MDNode *getTBAAStructInfo(QualType QTy);
};
} // end namespace CodeGen

View File

@ -0,0 +1,16 @@
// RUN: %clang_cc1 -emit-llvm -o - -O1 %s | FileCheck %s
//
// Check that we generate !tbaa.struct metadata for struct copies.
struct A {
short s;
int i;
char c;
int j;
};
void copy(struct A *a, struct A *b) {
*a = *b;
}
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.*}}, i8* %{{.*}}, i64 16, i32 4, i1 false), !tbaa.struct [[TS:!.*]]
// CHECK: [[TS]] = metadata !{i64 0, i64 2, metadata !{{.*}}, i64 4, i64 4, metadata !{{.*}}, i64 8, i64 1, metadata !{{.*}}, i64 12, i64 4, metadata !{{.*}}}