kosarev created this revision.
kosarev added reviewers: rjmccall, hfinkel.
kosarev added a project: clang.
We only do this for the new format as the old format does not allow to
represent accesses to aggregates. This patch significantly improves TBAA
coverage on -O1 builds.
Repository:
rL LLVM
https://reviews.llvm.org/D41562
Files:
lib/CodeGen/CGCall.cpp
test/CodeGen/tbaa-call.cpp
Index: test/CodeGen/tbaa-call.cpp
===================================================================
--- test/CodeGen/tbaa-call.cpp
+++ test/CodeGen/tbaa-call.cpp
@@ -0,0 +1,110 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -disable-llvm-passes \
+// RUN: -new-struct-path-tbaa %s -emit-llvm -o - | FileCheck %s
+//
+// Check that we generate correct TBAA information for instructions that pass
+// function arguments and returning values.
+
+struct A { int : 0; };
+struct B { double d; };
+struct C { A a; B b; };
+struct D { int i; };
+struct E { double d; int i; };
+struct F { float _Complex c; int x; };
+struct G { E e; };
+
+B get_B();
+C get_C();
+D get_D();
+E get_E();
+F get_F();
+
+void set_E(E);
+
+C f1() {
+// CHECK-LABEL: _Z2f1v
+// CHECK: load double, {{.*}}, !tbaa [[TAG_C:!.*]]
+ return C();
+}
+
+D f2() {
+// CHECK-LABEL: _Z2f2v
+// CHECK: load i32, {{.*}}, !tbaa [[TAG_D:!.*]]
+ return D();
+}
+
+E f3() {
+// CHECK-LABEL: _Z2f3v
+// CHECK: load { double, i32 }, {{.*}}, !tbaa [[TAG_E:!.*]]
+ return E();
+}
+
+E f4() {
+// CHECK-LABEL: _Z2f4v
+// CHECK: call { double, i32 } @_Z5get_Ev()
+// CHECK-DAG: store double {{.*}}, !tbaa [[TAG_E]]
+// CHECK-DAG: store i32 {{.*}}, !tbaa [[TAG_E]]
+// CHECK: load { double, i32 }, {{.*}}, !tbaa [[TAG_E]]
+ return get_E();
+}
+
+B f5() {
+// CHECK-LABEL: _Z2f5v
+// CHECK: call double @_Z5get_Bv()
+// CHECK: store double {{.*}}, !tbaa [[TAG_B:!.*]]
+// CHECK: load double, {{.*}}, !tbaa [[TAG_B]]
+ return get_B();
+}
+
+C f6() {
+// CHECK-LABEL: _Z2f6v
+// CHECK: call double @_Z5get_Cv()
+// CHECK: store double {{.*}}, !tbaa [[TAG_C]]
+// CHECK: load double, {{.*}}, !tbaa [[TAG_C]]
+ return get_C();
+}
+
+D f7() {
+// CHECK-LABEL: _Z2f7v
+// CHECK: call i32 @_Z5get_Dv()
+// CHECK: store i32 {{.*}}, !tbaa [[TAG_D]]
+// CHECK: load i32, {{.*}}, !tbaa [[TAG_D]]
+ return get_D();
+}
+
+F f8() {
+// CHECK-LABEL: _Z2f8v
+// CHECK: call { <2 x float>, i32 } @_Z5get_Fv()
+// CHECK: store { <2 x float>, i32 } {{.*}}, !tbaa [[TAG_F:!.*]]
+// CHECK: load { <2 x float>, i32 }, {{.*}}, !tbaa [[TAG_F]]
+ return get_F();
+}
+
+G f9(G g) {
+// CHECK-LABEL: _Z2f91G
+// CHECK-DAG: store double {{.*}}, !tbaa [[TAG_G:!.*]]
+// CHECK-DAG: store i32 {{.*}}, !tbaa [[TAG_G]]
+// CHECK: load { double, i32 }, {{.*}}, !tbaa [[TAG_G]]
+ return g;
+}
+
+void f10() {
+// CHECK-LABEL: _Z3f10v
+// CHECK-DAG: load double, {{.*}}, !tbaa [[TAG_E]]
+// CHECK-DAG: load i32, {{.*}}, !tbaa [[TAG_E]]
+// CHECK: call void @_Z5set_E1E
+ E e;
+ set_E(e);
+}
+
+// CHECK-DAG: [[TYPE_B:!.*]] = !{{{.*}}, !"_ZTS1B", {{.*}}}
+// CHECK-DAG: [[TAG_B]] = !{[[TYPE_B]], [[TYPE_B]], {{.*}}}
+// CHECK-DAG: [[TYPE_C:!.*]] = !{{{.*}}, !"_ZTS1C", {{.*}}}
+// CHECK-DAG: [[TAG_C]] = !{[[TYPE_C]], [[TYPE_C]], {{.*}}}
+// CHECK-DAG: [[TYPE_D:!.*]] = !{{{.*}}, !"_ZTS1D", {{.*}}}
+// CHECK-DAG: [[TAG_D]] = !{[[TYPE_D]], [[TYPE_D]], {{.*}}}
+// CHECK-DAG: [[TYPE_E:!.*]] = !{{{.*}}, !"_ZTS1E", {{.*}}}
+// CHECK-DAG: [[TAG_E]] = !{[[TYPE_E]], [[TYPE_E]], {{.*}}}
+// CHECK-DAG: [[TYPE_F:!.*]] = !{{{.*}}, !"_ZTS1F", {{.*}}}
+// CHECK-DAG: [[TAG_F]] = !{[[TYPE_F]], [[TYPE_F]], {{.*}}}
+// CHECK-DAG: [[TYPE_G:!.*]] = !{{{.*}}, !"_ZTS1G", {{.*}}}
+// CHECK-DAG: [[TAG_G]] = !{[[TYPE_G]], [[TYPE_G]], {{.*}}}
Index: lib/CodeGen/CGCall.cpp
===================================================================
--- lib/CodeGen/CGCall.cpp
+++ lib/CodeGen/CGCall.cpp
@@ -1195,12 +1195,16 @@
/// destination type; in this situation the values of bits which not
/// present in the src are undefined.
static llvm::Value *CreateCoercedLoad(Address Src, llvm::Type *Ty,
+ TBAAAccessInfo TBAAInfo,
CodeGenFunction &CGF) {
llvm::Type *SrcTy = Src.getElementType();
// If SrcTy and Ty are the same, just do a load.
- if (SrcTy == Ty)
- return CGF.Builder.CreateLoad(Src);
+ if (SrcTy == Ty) {
+ auto *Load = CGF.Builder.CreateLoad(Src);
+ CGF.CGM.DecorateInstructionWithTBAA(Load, TBAAInfo);
+ return Load;
+ }
uint64_t DstSize = CGF.CGM.getDataLayout().getTypeAllocSize(Ty);
@@ -1215,7 +1219,8 @@
// extension or truncation to the desired type.
if ((isa<llvm::IntegerType>(Ty) || isa<llvm::PointerType>(Ty)) &&
(isa<llvm::IntegerType>(SrcTy) || isa<llvm::PointerType>(SrcTy))) {
- llvm::Value *Load = CGF.Builder.CreateLoad(Src);
+ auto *Load = CGF.Builder.CreateLoad(Src);
+ CGF.CGM.DecorateInstructionWithTBAA(Load, TBAAInfo);
return CoerceIntOrPtrToIntOrPtr(Load, Ty, CGF);
}
@@ -1229,7 +1234,9 @@
// to that information.
Src = CGF.Builder.CreateBitCast(Src,
Ty->getPointerTo(Src.getAddressSpace()));
- return CGF.Builder.CreateLoad(Src);
+ auto *Load = CGF.Builder.CreateLoad(Src);
+ CGF.CGM.DecorateInstructionWithTBAA(Load, TBAAInfo);
+ return Load;
}
// Otherwise do coercion through memory. This is stupid, but simple.
@@ -1239,15 +1246,18 @@
CGF.Builder.CreateMemCpy(Casted, SrcCasted,
llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize),
false);
- return CGF.Builder.CreateLoad(Tmp);
+ auto *Load = CGF.Builder.CreateLoad(Tmp);
+ CGF.CGM.DecorateInstructionWithTBAA(Load, TBAAInfo);
+ return Load;
}
// Function to store a first-class aggregate into memory. We prefer to
// store the elements rather than the aggregate to be more friendly to
// fast-isel.
// FIXME: Do we need to recurse here?
static void BuildAggStore(CodeGenFunction &CGF, llvm::Value *Val,
- Address Dest, bool DestIsVolatile) {
+ Address Dest, bool DestIsVolatile,
+ TBAAAccessInfo TBAAInfo) {
// Prefer scalar stores to first-class aggregate stores.
if (llvm::StructType *STy =
dyn_cast<llvm::StructType>(Val->getType())) {
@@ -1258,27 +1268,28 @@
auto EltOffset = CharUnits::fromQuantity(Layout->getElementOffset(i));
Address EltPtr = CGF.Builder.CreateStructGEP(Dest, i, EltOffset);
llvm::Value *Elt = CGF.Builder.CreateExtractValue(Val, i);
- CGF.Builder.CreateStore(Elt, EltPtr, DestIsVolatile);
+ auto *Store = CGF.Builder.CreateStore(Elt, EltPtr, DestIsVolatile);
+ CGF.CGM.DecorateInstructionWithTBAA(Store, TBAAInfo);
}
} else {
- CGF.Builder.CreateStore(Val, Dest, DestIsVolatile);
+ auto *Store = CGF.Builder.CreateStore(Val, Dest, DestIsVolatile);
+ CGF.CGM.DecorateInstructionWithTBAA(Store, TBAAInfo);
}
}
-/// CreateCoercedStore - Create a store to \arg DstPtr from \arg Src,
-/// where the source and destination may have different types. The
-/// destination is known to be aligned to \arg DstAlign bytes.
+/// CreateCoercedStore - Create a store to \arg Dst from \arg Src,
+/// where the source and destination may have different types.
///
/// This safely handles the case when the src type is larger than the
/// destination type; the upper bits of the src will be lost.
-static void CreateCoercedStore(llvm::Value *Src,
- Address Dst,
- bool DstIsVolatile,
+static void CreateCoercedStore(llvm::Value *Src, Address Dst,
+ bool DstIsVolatile, TBAAAccessInfo TBAAInfo,
CodeGenFunction &CGF) {
llvm::Type *SrcTy = Src->getType();
llvm::Type *DstTy = Dst.getType()->getElementType();
if (SrcTy == DstTy) {
- CGF.Builder.CreateStore(Src, Dst, DstIsVolatile);
+ auto *Store = CGF.Builder.CreateStore(Src, Dst, DstIsVolatile);
+ CGF.CGM.DecorateInstructionWithTBAA(Store, TBAAInfo);
return;
}
@@ -1294,16 +1305,17 @@
if ((isa<llvm::IntegerType>(SrcTy) || isa<llvm::PointerType>(SrcTy)) &&
(isa<llvm::IntegerType>(DstTy) || isa<llvm::PointerType>(DstTy))) {
Src = CoerceIntOrPtrToIntOrPtr(Src, DstTy, CGF);
- CGF.Builder.CreateStore(Src, Dst, DstIsVolatile);
+ auto *Store = CGF.Builder.CreateStore(Src, Dst, DstIsVolatile);
+ CGF.CGM.DecorateInstructionWithTBAA(Store, TBAAInfo);
return;
}
uint64_t DstSize = CGF.CGM.getDataLayout().getTypeAllocSize(DstTy);
// If store is legal, just bitcast the src pointer.
if (SrcSize <= DstSize) {
Dst = CGF.Builder.CreateElementBitCast(Dst, SrcTy);
- BuildAggStore(CGF, Src, Dst, DstIsVolatile);
+ BuildAggStore(CGF, Src, Dst, DstIsVolatile, TBAAInfo);
} else {
// Otherwise do coercion through memory. This is stupid, but
// simple.
@@ -1315,7 +1327,8 @@
// FIXME: Assert that we aren't truncating non-padding bits when have access
// to that information.
Address Tmp = CreateTempAllocaForCoercion(CGF, SrcTy, Dst.getAlignment());
- CGF.Builder.CreateStore(Src, Tmp);
+ auto *Store = CGF.Builder.CreateStore(Src, Tmp);
+ CGF.CGM.DecorateInstructionWithTBAA(Store, TBAAInfo);
Address Casted = CGF.Builder.CreateBitCast(Tmp, CGF.AllocaInt8PtrTy);
Address DstCasted = CGF.Builder.CreateBitCast(Dst, CGF.AllocaInt8PtrTy);
CGF.Builder.CreateMemCpy(DstCasted, Casted,
@@ -2258,6 +2271,10 @@
QualType Ty = info_it->type;
const ABIArgInfo &ArgI = info_it->info;
+ TBAAAccessInfo ArgTBAAInfo;
+ if (CGM.getCodeGenOpts().NewStructPathTBAA)
+ ArgTBAAInfo = CGM.getTBAAAccessInfo(Ty);
+
bool isPromoted =
isa<ParmVarDecl>(Arg) && cast<ParmVarDecl>(Arg)->isKNRPromoted();
@@ -2445,7 +2462,8 @@
auto Offset = CharUnits::fromQuantity(SrcLayout->getElementOffset(i));
Address EltPtr =
Builder.CreateStructGEP(AddrToStoreInto, i, Offset);
- Builder.CreateStore(AI, EltPtr);
+ auto *Store = Builder.CreateStore(AI, EltPtr);
+ CGM.DecorateInstructionWithTBAA(Store, ArgTBAAInfo);
}
if (SrcSize > DstSize) {
@@ -2457,7 +2475,8 @@
assert(NumIRArgs == 1);
auto AI = FnArgs[FirstIRArg];
AI->setName(Arg->getName() + ".coerce");
- CreateCoercedStore(AI, Ptr, /*DestIsVolatile=*/false, *this);
+ CreateCoercedStore(AI, Ptr, /*DestIsVolatile=*/false, ArgTBAAInfo,
+ *this);
}
// Match to what EmitParmDecl is expecting for this type.
@@ -2781,6 +2800,10 @@
QualType RetTy = FI.getReturnType();
const ABIArgInfo &RetAI = FI.getReturnInfo();
+ TBAAAccessInfo RetTBAAInfo;
+ if (CGM.getCodeGenOpts().NewStructPathTBAA)
+ RetTBAAInfo = CGM.getTBAAAccessInfo(RetTy);
+
switch (RetAI.getKind()) {
case ABIArgInfo::InAlloca:
// Aggregrates get evaluated directly into the destination. Sometimes we
@@ -2857,7 +2880,7 @@
// If the value is offset in memory, apply the offset now.
Address V = emitAddressAtOffset(*this, ReturnValue, RetAI);
- RV = CreateCoercedLoad(V, RetAI.getCoerceToType(), *this);
+ RV = CreateCoercedLoad(V, RetAI.getCoerceToType(), RetTBAAInfo, *this);
}
// In ARC, end functions that return a retainable type with a call
@@ -3735,6 +3758,10 @@
QualType RetTy = CallInfo.getReturnType();
const ABIArgInfo &RetAI = CallInfo.getReturnInfo();
+ TBAAAccessInfo RetTBAAInfo;
+ if (CGM.getCodeGenOpts().NewStructPathTBAA)
+ RetTBAAInfo = CGM.getTBAAAccessInfo(RetTy);
+
llvm::FunctionType *IRFuncTy = Callee.getFunctionType();
// 1. Set up the arguments.
@@ -3807,6 +3834,9 @@
for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end();
I != E; ++I, ++info_it, ++ArgNo) {
const ABIArgInfo &ArgInfo = info_it->info;
+ TBAAAccessInfo ArgTBAAInfo;
+ if (CGM.getCodeGenOpts().NewStructPathTBAA)
+ ArgTBAAInfo = CGM.getTBAAAccessInfo(info_it->type);
RValue RV = I->RV;
// Insert a padding argument to ensure proper alignment.
@@ -3984,14 +4014,15 @@
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
auto Offset = CharUnits::fromQuantity(SrcLayout->getElementOffset(i));
Address EltPtr = Builder.CreateStructGEP(Src, i, Offset);
- llvm::Value *LI = Builder.CreateLoad(EltPtr);
+ auto *LI = Builder.CreateLoad(EltPtr);
+ CGM.DecorateInstructionWithTBAA(LI, ArgTBAAInfo);
IRCallArgs[FirstIRArg + i] = LI;
}
} else {
// In the simple case, just pass the coerced loaded value.
assert(NumIRArgs == 1);
IRCallArgs[FirstIRArg] =
- CreateCoercedLoad(Src, ArgInfo.getCoerceToType(), *this);
+ CreateCoercedLoad(Src, ArgInfo.getCoerceToType(), ArgTBAAInfo, *this);
}
break;
@@ -4344,7 +4375,7 @@
DestPtr = CreateMemTemp(RetTy, "agg.tmp");
DestIsVolatile = false;
}
- BuildAggStore(*this, CI, DestPtr, DestIsVolatile);
+ BuildAggStore(*this, CI, DestPtr, DestIsVolatile, RetTBAAInfo);
return RValue::getAggregate(DestPtr);
}
case TEK_Scalar: {
@@ -4369,7 +4400,7 @@
// If the value is offset in memory, apply the offset now.
Address StorePtr = emitAddressAtOffset(*this, DestPtr, RetAI);
- CreateCoercedStore(CI, StorePtr, DestIsVolatile, *this);
+ CreateCoercedStore(CI, StorePtr, DestIsVolatile, RetTBAAInfo, *this);
return convertTempToRValue(DestPtr, RetTy, SourceLocation());
}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits