forked from OSchip/llvm-project
CodeGen: specify alignment + inbounds for automatic variable initialization
Summary: Automatic variable initialization was generating default-aligned stores (which are deprecated) instead of using the known alignment from the alloca. Further, they didn't specify inbounds. Subscribers: dexonsmith, cfe-commits Differential Revision: https://reviews.llvm.org/D49209 llvm-svn: 337041
This commit is contained in:
parent
2f7de23bea
commit
9aab85a6a0
|
@ -244,6 +244,21 @@ public:
|
|||
Addr.getAlignment().alignmentAtOffset(Offset));
|
||||
}
|
||||
|
||||
using CGBuilderBaseTy::CreateConstInBoundsGEP2_32;
|
||||
Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0,
|
||||
unsigned Idx1, const llvm::DataLayout &DL,
|
||||
const llvm::Twine &Name = "") {
|
||||
auto *GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32(
|
||||
Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name));
|
||||
llvm::APInt Offset(
|
||||
DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0,
|
||||
/*IsSigned=*/true);
|
||||
if (!GEP->accumulateConstantOffset(DL, Offset))
|
||||
llvm_unreachable("offset of GEP with constants is always computable");
|
||||
return Address(GEP, Addr.getAlignment().alignmentAtOffset(
|
||||
CharUnits::fromQuantity(Offset.getSExtValue())));
|
||||
}
|
||||
|
||||
llvm::Value *CreateConstInBoundsByteGEP(llvm::Value *Ptr, CharUnits Offset,
|
||||
const llvm::Twine &Name = "") {
|
||||
assert(Ptr->getType()->getPointerElementType() == TypeCache.Int8Ty);
|
||||
|
|
|
@ -888,15 +888,17 @@ static bool canEmitInitWithFewStoresAfterMemset(llvm::Constant *Init,
|
|||
/// emitStoresForInitAfterMemset - For inits that
|
||||
/// canEmitInitWithFewStoresAfterMemset returned true for, emit the scalar
|
||||
/// stores that would be required.
|
||||
static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc,
|
||||
bool isVolatile, CGBuilderTy &Builder) {
|
||||
static void emitStoresForInitAfterMemset(CodeGenModule &CGM,
|
||||
llvm::Constant *Init, Address Loc,
|
||||
bool isVolatile,
|
||||
CGBuilderTy &Builder) {
|
||||
assert(!Init->isNullValue() && !isa<llvm::UndefValue>(Init) &&
|
||||
"called emitStoresForInitAfterMemset 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.CreateDefaultAlignedStore(Init, Loc, isVolatile);
|
||||
Builder.CreateStore(Init, Loc, isVolatile);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -908,7 +910,8 @@ static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc,
|
|||
// If necessary, get a pointer to the element and emit it.
|
||||
if (!Elt->isNullValue() && !isa<llvm::UndefValue>(Elt))
|
||||
emitStoresForInitAfterMemset(
|
||||
Elt, Builder.CreateConstGEP2_32(Init->getType(), Loc, 0, i),
|
||||
CGM, Elt,
|
||||
Builder.CreateConstInBoundsGEP2_32(Loc, 0, i, CGM.getDataLayout()),
|
||||
isVolatile, Builder);
|
||||
}
|
||||
return;
|
||||
|
@ -923,7 +926,8 @@ static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc,
|
|||
// If necessary, get a pointer to the element and emit it.
|
||||
if (!Elt->isNullValue() && !isa<llvm::UndefValue>(Elt))
|
||||
emitStoresForInitAfterMemset(
|
||||
Elt, Builder.CreateConstGEP2_32(Init->getType(), Loc, 0, i),
|
||||
CGM, Elt,
|
||||
Builder.CreateConstInBoundsGEP2_32(Loc, 0, i, CGM.getDataLayout()),
|
||||
isVolatile, Builder);
|
||||
}
|
||||
}
|
||||
|
@ -1411,8 +1415,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
|
|||
if (!constant->isNullValue() && !isa<llvm::UndefValue>(constant)) {
|
||||
Loc = Builder.CreateBitCast(Loc,
|
||||
constant->getType()->getPointerTo(Loc.getAddressSpace()));
|
||||
emitStoresForInitAfterMemset(constant, Loc.getPointer(),
|
||||
isVolatile, Builder);
|
||||
emitStoresForInitAfterMemset(CGM, constant, Loc, isVolatile, Builder);
|
||||
}
|
||||
} else {
|
||||
// Otherwise, create a temporary global with the initializer then
|
||||
|
|
|
@ -86,25 +86,25 @@ struct Huge {
|
|||
char test8(int X) {
|
||||
char str[100000] = "abc"; // tail should be memset.
|
||||
return str[X];
|
||||
// CHECK: @test8(
|
||||
// CHECK: call void @llvm.memset
|
||||
// CHECK: store i8 97
|
||||
// CHECK: store i8 98
|
||||
// CHECK: store i8 99
|
||||
// CHECK-NOT: getelementptr
|
||||
// CHECK: load
|
||||
// CHECK-LABEL: @test8(
|
||||
// CHECK: call void @llvm.memset
|
||||
// CHECK: store i8 97, i8* %{{[0-9]*}}, align 1
|
||||
// CHECK: store i8 98, i8* %{{[0-9]*}}, align 1
|
||||
// CHECK: store i8 99, i8* %{{[0-9]*}}, align 1
|
||||
// CHECK-NOT: getelementptr
|
||||
// CHECK: load
|
||||
}
|
||||
|
||||
void bar(void*);
|
||||
|
||||
// PR279
|
||||
int test9(int X) {
|
||||
void test9(int X) {
|
||||
int Arr[100] = { X }; // Should use memset
|
||||
bar(Arr);
|
||||
// CHECK: @test9
|
||||
// CHECK: call void @llvm.memset
|
||||
// CHECK-NOT: store i32 0
|
||||
// CHECK: call void @bar
|
||||
// CHECK-LABEL: @test9(
|
||||
// CHECK: call void @llvm.memset
|
||||
// CHECK-NOT: store i32 0
|
||||
// CHECK: call void @bar
|
||||
}
|
||||
|
||||
struct a {
|
||||
|
@ -115,11 +115,11 @@ struct b {
|
|||
struct a a,b,c,d,e,f,g;
|
||||
};
|
||||
|
||||
int test10(int X) {
|
||||
void test10(int X) {
|
||||
struct b S = { .a.a = X, .d.e = X, .f.e = 0, .f.f = 0, .f.p = 0 };
|
||||
bar(&S);
|
||||
|
||||
// CHECK: @test10
|
||||
// CHECK-LABEL: @test10(
|
||||
// CHECK: call void @llvm.memset
|
||||
// CHECK-NOT: store i32 0
|
||||
// CHECK: call void @bar
|
||||
|
@ -132,11 +132,11 @@ struct test11S {
|
|||
};
|
||||
void test11(struct test11S *P) {
|
||||
*P = (struct test11S) { .A = { [0 ... 3] = 4 } };
|
||||
// CHECK: @test11
|
||||
// CHECK: store i32 4
|
||||
// CHECK: store i32 4
|
||||
// CHECK: store i32 4
|
||||
// CHECK: store i32 4
|
||||
// CHECK-LABEL: @test11(
|
||||
// CHECK: store i32 4, i32* %{{.*}}, align 4
|
||||
// CHECK: store i32 4, i32* %{{.*}}, align 4
|
||||
// CHECK: store i32 4, i32* %{{.*}}, align 4
|
||||
// CHECK: store i32 4, i32* %{{.*}}, align 4
|
||||
// CHECK: ret void
|
||||
}
|
||||
|
||||
|
@ -151,11 +151,11 @@ struct test12 {
|
|||
void test13(int x) {
|
||||
struct X { int a; int b : 10; int c; };
|
||||
struct X y = {.c = x};
|
||||
// CHECK: @test13
|
||||
// CHECK-LABEL: @test13(
|
||||
// CHECK: and i16 {{.*}}, -1024
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @PR20473
|
||||
// CHECK-LABEL: @PR20473(
|
||||
void PR20473() {
|
||||
// CHECK: memcpy{{.*}}getelementptr inbounds ([2 x i8], [2 x i8]* @
|
||||
bar((char[2]) {""});
|
||||
|
@ -168,9 +168,9 @@ void PR20473() {
|
|||
struct S14 { int a[16]; };
|
||||
|
||||
void test14(struct S14 *s14) {
|
||||
// CHECK-LABEL: @test14
|
||||
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 {{.*}}, i8* align 4 {{.*}} [[INIT14]] {{.*}}, i32 64, i1 false)
|
||||
// CHECK-NOT: store
|
||||
// CHECK: ret void
|
||||
// CHECK-LABEL: @test14(
|
||||
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 {{.*}}, i8* align 4 {{.*}} [[INIT14]] {{.*}}, i32 64, i1 false)
|
||||
// CHECK-NOT: store
|
||||
// CHECK: ret void
|
||||
*s14 = (struct S14) { { [5 ... 11] = 17 } };
|
||||
}
|
||||
|
|
|
@ -38,11 +38,11 @@ void f(void) {
|
|||
// CHECK: %[[v0:.*]] = bitcast [6 x [6 x float]]* %A to i8*
|
||||
// CHECK: call void @llvm.memset.p0i8.i32(i8* align 4 %[[v0]], i8 0, i32 144, i1 false)
|
||||
// CHECK: %[[v1:.*]] = bitcast i8* %[[v0]] to [6 x [6 x float]]*
|
||||
// CHECK: %[[v2:.*]] = getelementptr [6 x [6 x float]], [6 x [6 x float]]* %[[v1]], i32 0, i32 0
|
||||
// CHECK: %[[v3:.*]] = getelementptr [6 x float], [6 x float]* %[[v2]], i32 0, i32 0
|
||||
// CHECK: store float 1.000000e+00, float* %[[v3]]
|
||||
// CHECK: %[[v4:.*]] = getelementptr [6 x float], [6 x float]* %[[v2]], i32 0, i32 1
|
||||
// CHECK: store float 2.000000e+00, float* %[[v4]]
|
||||
// CHECK: %[[v2:.*]] = getelementptr inbounds [6 x [6 x float]], [6 x [6 x float]]* %[[v1]], i32 0, i32 0
|
||||
// CHECK: %[[v3:.*]] = getelementptr inbounds [6 x float], [6 x float]* %[[v2]], i32 0, i32 0
|
||||
// CHECK: store float 1.000000e+00, float* %[[v3]], align 4
|
||||
// CHECK: %[[v4:.*]] = getelementptr inbounds [6 x float], [6 x float]* %[[v2]], i32 0, i32 1
|
||||
// CHECK: store float 2.000000e+00, float* %[[v4]], align 4
|
||||
float A[6][6] = {1.0f, 2.0f};
|
||||
|
||||
// CHECK: %[[v5:.*]] = bitcast %struct.StrucTy* %S to i8*
|
||||
|
|
Loading…
Reference in New Issue