Skip to content

Commit d5934a4

Browse files
[clang] Avoid memcopy for small structure with padding under -ftrivial-auto-var-init
1 parent 3f9d385 commit d5934a4

File tree

2 files changed

+30
-30
lines changed

2 files changed

+30
-30
lines changed

clang/lib/CodeGen/CGDecl.cpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,17 +1244,18 @@ static void emitStoresForConstant(CodeGenModule &CGM, const VarDecl &D,
12441244
// If the initializer is small, use a handful of stores.
12451245
if (shouldSplitConstantStore(CGM, ConstantSize)) {
12461246
if (auto *STy = dyn_cast<llvm::StructType>(Ty)) {
1247-
// FIXME: handle the case when STy != Loc.getElementType().
1248-
if (STy == Loc.getElementType()) {
1249-
for (unsigned i = 0; i != constant->getNumOperands(); i++) {
1250-
Address EltPtr = Builder.CreateStructGEP(Loc, i);
1251-
emitStoresForConstant(
1252-
CGM, D, EltPtr, isVolatile, Builder,
1253-
cast<llvm::Constant>(Builder.CreateExtractValue(constant, i)),
1254-
IsAutoInit);
1255-
}
1256-
return;
1247+
const llvm::StructLayout *Layout = CGM.getDataLayout().getStructLayout(
1248+
cast<llvm::StructType>(constant->getType()));
1249+
for (unsigned i = 0; i != constant->getNumOperands(); i++) {
1250+
CharUnits CurOff = CharUnits::fromQuantity(Layout->getElementOffset(i));
1251+
Address EltPtr = Builder.CreateConstInBoundsByteGEP(
1252+
Loc.withElementType(CGM.Int8Ty), CurOff);
1253+
emitStoresForConstant(
1254+
CGM, D, EltPtr, isVolatile, Builder,
1255+
cast<llvm::Constant>(Builder.CreateExtractValue(constant, i)),
1256+
IsAutoInit);
12571257
}
1258+
return;
12581259
} else if (auto *ATy = dyn_cast<llvm::ArrayType>(Ty)) {
12591260
// FIXME: handle the case when ATy != Loc.getElementType().
12601261
if (ATy == Loc.getElementType()) {

clang/test/CodeGenCXX/auto-var-init.cpp

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -89,22 +89,14 @@ struct padded { char c; int i; };
8989
// PATTERN-O1-NOT: @__const.test_paddednullinit_custom.custom
9090
struct paddednullinit { char c = 0; int i = 0; };
9191
// PATTERN-O0: @__const.test_paddedpacked_uninit.uninit = private unnamed_addr constant %struct.paddedpacked <{ i8 [[I8]], i32 [[I32]] }>, align 1
92-
// PATTERN: @__const.test_paddedpacked_custom.custom = private unnamed_addr constant %struct.paddedpacked <{ i8 42, i32 13371337 }>, align 1
93-
// ZERO: @__const.test_paddedpacked_custom.custom = private unnamed_addr constant %struct.paddedpacked <{ i8 42, i32 13371337 }>, align 1
9492
struct paddedpacked { char c; int i; } __attribute__((packed));
9593
// PATTERN-O0: @__const.test_paddedpackedarray_uninit.uninit = private unnamed_addr constant %struct.paddedpackedarray { [2 x %struct.paddedpacked] [%struct.paddedpacked <{ i8 [[I8]], i32 [[I32]] }>, %struct.paddedpacked <{ i8 [[I8]], i32 [[I32]] }>] }, align 1
96-
// PATTERN: @__const.test_paddedpackedarray_custom.custom = private unnamed_addr constant %struct.paddedpackedarray { [2 x %struct.paddedpacked] [%struct.paddedpacked <{ i8 42, i32 13371337 }>, %struct.paddedpacked <{ i8 43, i32 13371338 }>] }, align 1
97-
// ZERO: @__const.test_paddedpackedarray_custom.custom = private unnamed_addr constant %struct.paddedpackedarray { [2 x %struct.paddedpacked] [%struct.paddedpacked <{ i8 42, i32 13371337 }>, %struct.paddedpacked <{ i8 43, i32 13371338 }>] }, align 1
9894
struct paddedpackedarray { struct paddedpacked p[2]; };
9995
// PATTERN-O0: @__const.test_unpackedinpacked_uninit.uninit = private unnamed_addr constant <{ { i8, [3 x i8], i32 }, i8 }> <{ { i8, [3 x i8], i32 } { i8 [[I8]], [3 x i8] c"\[[IC]]\[[IC]]\[[IC]]", i32 [[I32]] }, i8 [[I8]] }>, align 1
10096
struct unpackedinpacked { padded a; char b; } __attribute__((packed));
10197
// PATTERN-O0: @__const.test_paddednested_uninit.uninit = private unnamed_addr constant { { i8, [3 x i8], i32 }, { i8, [3 x i8], i32 } } { { i8, [3 x i8], i32 } { i8 [[I8]], [3 x i8] c"\[[IC]]\[[IC]]\[[IC]]", i32 [[I32]] }, { i8, [3 x i8], i32 } { i8 [[I8]], [3 x i8] c"\[[IC]]\[[IC]]\[[IC]]", i32 [[I32]] } }, align 4
102-
// PATTERN: @__const.test_paddednested_custom.custom = private unnamed_addr constant { { i8, [3 x i8], i32 }, { i8, [3 x i8], i32 } } { { i8, [3 x i8], i32 } { i8 42, [3 x i8] zeroinitializer, i32 13371337 }, { i8, [3 x i8], i32 } { i8 43, [3 x i8] zeroinitializer, i32 13371338 } }, align 4
103-
// ZERO: @__const.test_paddednested_custom.custom = private unnamed_addr constant { { i8, [3 x i8], i32 }, { i8, [3 x i8], i32 } } { { i8, [3 x i8], i32 } { i8 42, [3 x i8] zeroinitializer, i32 13371337 }, { i8, [3 x i8], i32 } { i8 43, [3 x i8] zeroinitializer, i32 13371338 } }, align 4
10498
struct paddednested { struct padded p1, p2; };
10599
// PATTERN-O0: @__const.test_paddedpackednested_uninit.uninit = private unnamed_addr constant %struct.paddedpackednested { %struct.paddedpacked <{ i8 [[I8]], i32 [[I32]] }>, %struct.paddedpacked <{ i8 [[I8]], i32 [[I32]] }> }, align 1
106-
// PATTERN: @__const.test_paddedpackednested_custom.custom = private unnamed_addr constant %struct.paddedpackednested { %struct.paddedpacked <{ i8 42, i32 13371337 }>, %struct.paddedpacked <{ i8 43, i32 13371338 }> }, align 1
107-
// ZERO: @__const.test_paddedpackednested_custom.custom = private unnamed_addr constant %struct.paddedpackednested { %struct.paddedpacked <{ i8 42, i32 13371337 }>, %struct.paddedpacked <{ i8 43, i32 13371338 }> }, align 1
108100
struct paddedpackednested { struct paddedpacked p1, p2; };
109101
// PATTERN-O0: @__const.test_bitfield_uninit.uninit = private unnamed_addr constant %struct.bitfield { i8 [[I8]], [3 x i8] c"\[[IC]]\[[IC]]\[[IC]]" }, align 4
110102
// PATTERN-O0: @__const.test_bitfield_custom.custom = private unnamed_addr constant %struct.bitfield { i8 20, [3 x i8] c"\[[IC]]\[[IC]]\[[IC]]" }, align 4
@@ -714,7 +706,8 @@ TEST_UNINIT(padded, padded);
714706
// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
715707
// PATTERN-LABEL: @test_padded_uninit()
716708
// PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_padded_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]]
717-
// PATTERN-O1: store i64 [[I64]], ptr %uninit, align 8, !annotation [[AUTO_INIT]]
709+
// PATTERN-O1: store i64 [[I64]], ptr %uninit, align 8
710+
// PATTERN-O1-NOT: !annotation
718711
// ZERO-LABEL: @test_padded_uninit()
719712
// ZERO-O0: call void @llvm.memset{{.*}}, i8 0,{{.+}}), !annotation [[AUTO_INIT]]
720713
// ZERO-O1: store i64 0, ptr %uninit, align 8, !annotation [[AUTO_INIT]]
@@ -740,7 +733,8 @@ TEST_UNINIT(paddednullinit, paddednullinit);
740733
// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
741734
// PATTERN-LABEL: @test_paddednullinit_uninit()
742735
// PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_paddednullinit_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]]
743-
// PATTERN-O1: store i64 [[I64]], ptr %uninit, align 8, !annotation [[AUTO_INIT]]
736+
// PATTERN-O1: store i64 [[I64]], ptr %uninit, align 8
737+
// PATTERN-O1-NOT: !annotation
744738
// ZERO-LABEL: @test_paddednullinit_uninit()
745739
// ZERO-O0: call void @llvm.memset{{.*}}, i8 0, {{.*}}, !annotation [[AUTO_INIT]]
746740
// ZERO-O1: store i64 0, ptr %uninit, align 8
@@ -778,9 +772,8 @@ TEST_UNINIT(paddedpacked, paddedpacked);
778772
// PATTERN-LABEL: @test_paddedpacked_uninit()
779773
// PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_paddedpacked_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]]
780774
// PATTERN-O1: store i8 [[I8]], ptr %uninit, align {{.+}}, !annotation [[AUTO_INIT]]
781-
// PATTERN-O1: %[[I:[^ ]*]] = getelementptr inbounds {{.*}}%uninit, i64 0, i32 1
775+
// PATTERN-O1: %[[I:[^ ]*]] = getelementptr inbounds {{.*}}%uninit, i64 1
782776
// PATTERN-O1: store i32 [[I32]], ptr %[[I]], align {{.+}}, !annotation [[AUTO_INIT]]
783-
784777
// ZERO-LABEL: @test_paddedpacked_uninit()
785778
// ZERO: call void @llvm.memset{{.*}}, i8 0,{{.+}}), !annotation [[AUTO_INIT]]
786779

@@ -1192,7 +1185,8 @@ TEST_UNINIT(atomicpadded, _Atomic(padded));
11921185
// CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit)
11931186
// PATTERN-LABEL: @test_atomicpadded_uninit()
11941187
// PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_atomicpadded_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]]
1195-
// PATTERN-O1: store i64 [[IPTR]], ptr %uninit, align 8, !annotation [[AUTO_INIT]]
1188+
// PATTERN-O1: store i64 [[IPTR]], ptr %uninit, align 8
1189+
// PATTERN-O1-NOT: !annotation
11961190
// ZERO-LABEL: @test_atomicpadded_uninit()
11971191
// ZERO-O0: call void @llvm.memset{{.*}}, i8 0, {{.+}}), !annotation [[AUTO_INIT]]
11981192
// ZERO-O1: store i64 0, ptr %uninit, align 8, !annotation [[AUTO_INIT]]
@@ -1214,8 +1208,7 @@ TEST_UNINIT(complexfloat, _Complex float);
12141208
// PATTERN-LABEL: @test_complexfloat_uninit()
12151209
// PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_complexfloat_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]]
12161210
// PATTERN-O1: store float 0xFFFFFFFFE0000000, ptr %uninit, align {{.+}}, !annotation [[AUTO_INIT]]
1217-
1218-
// PATTERN-O1: %[[F2:[^ ]*]] = getelementptr inbounds {{.*}}%uninit, i64 0, i32 1
1211+
// PATTERN-O1: %[[F2:[^ ]*]] = getelementptr inbounds {{.*}}%uninit, i64 4
12191212
// PATTERN-O1: store float 0xFFFFFFFFE0000000, ptr %[[F2]], align {{.+}}, !annotation [[AUTO_INIT]]
12201213

12211214
// ZERO-LABEL: @test_complexfloat_uninit()
@@ -1314,7 +1307,9 @@ TEST_CUSTOM(semivolatile, semivolatile, { 0x44444444, 0x44444444 });
13141307
// CHECK-O0: call void @llvm.memcpy
13151308
// CHECK-NOT: !annotation
13161309
// CHECK-O0: call void @{{.*}}used{{.*}}%custom)
1317-
// CHECK-O1: store i64 4919131752989213764, ptr %custom, align 8
1310+
// CHECK-O1: store i32 1145324612, ptr %custom, align 4
1311+
// CHECK-O1-NEXT: %[[I:[^ ]*]] = getelementptr inbounds i8, ptr %custom, i64 4
1312+
// CHECK-O1-NEXT: store i32 1145324612, ptr %[[I]], align 4
13181313
// CHECK-NOT: !annotation
13191314

13201315
TEST_UNINIT(semivolatileinit, semivolatileinit);
@@ -1427,7 +1422,7 @@ TEST_CUSTOM(matching, matching, { .f = 0xf00f });
14271422
// CHECK-O0: call void @llvm.memcpy
14281423
// CHECK-NOT: !annotation
14291424
// CHECK-O0: call void @{{.*}}used{{.*}}%custom)
1430-
// CHECK-O1: store i32 1198526208, ptr {{.*}}, align 4
1425+
// CHECK-O1: store float 6.145500e+04, ptr {{.*}}, align 4
14311426
// CHECK-NOT: !annotation
14321427

14331428
TEST_UNINIT(matchingreverse, matchingreverse);
@@ -1506,8 +1501,12 @@ TEST_CUSTOM(unmatchedreverse, unmatchedreverse, { .c = 42 });
15061501
// CHECK-O0: call void @llvm.memcpy
15071502
// CHECK-NOT: !annotation
15081503
// CHECK-O0: call void @{{.*}}used{{.*}}%custom)
1509-
// PATTERN-O1: store i32 -1431655894, ptr {{.*}}, align 4
1510-
// ZERO-O1: store i32 42, ptr {{.*}}, align 4
1504+
// PATTERN-O1: store i8 42, ptr {{.*}}, align 4
1505+
// PATTERN-O1-NEXT: %[[I:[^ ]*]] = getelementptr inbounds i8, ptr %custom, i64 1
1506+
// PATTERN-O1-NEXT: call void @llvm.memset.{{.*}}({{.*}}, i8 -86, i64 3, {{.*}})
1507+
// ZERO-O1: store i8 42, ptr {{.*}}, align 4
1508+
// ZERO-O1-NEXT: %[[I:[^ ]*]] = getelementptr inbounds i8, ptr %custom, i64 1
1509+
// ZERO-O1-NEXT: call void @llvm.memset.{{.*}}({{.*}}, i8 0, i64 3, {{.*}})
15111510

15121511
TEST_UNINIT(unmatchedfp, unmatchedfp);
15131512
// CHECK-LABEL: @test_unmatchedfp_uninit()
@@ -1532,7 +1531,7 @@ TEST_CUSTOM(unmatchedfp, unmatchedfp, { .d = 3.1415926535897932384626433 });
15321531
// CHECK-O0: call void @llvm.memcpy
15331532
// CHECK-NOT: !annotation
15341533
// CHECK-O0: call void @{{.*}}used{{.*}}%custom)
1535-
// CHECK-O1: store i64 4614256656552045848, ptr %custom, align 8
1534+
// CHECK-O1: store double 0x400921FB54442D18, ptr %custom, align 8
15361535
// CHECK-NOT: !annotation
15371536

15381537
TEST_UNINIT(emptyenum, emptyenum);

0 commit comments

Comments
 (0)