Skip to content

Commit

Permalink
Don't emit init symbol for zero-initialized structs
Browse files Browse the repository at this point in the history
And optimize previous usages of it to direct memset-zero.
  • Loading branch information
kinke committed Aug 11, 2019
1 parent a8dd0b1 commit 98fb979
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 22 deletions.
13 changes: 8 additions & 5 deletions gen/declarations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,15 @@ class CodegenVisitor : public Visitor {
// Skip __initZ and typeinfo for @compute device code.
// TODO: support global variables and thus __initZ
if (!irs->dcomputetarget) {
// Define the __initZ symbol.
IrAggr *ir = getIrAggr(decl);
auto &initZ = ir->getInitSymbol();
auto initGlobal = llvm::cast<LLGlobalVariable>(initZ);
initZ = irs->setGlobalVarInitializer(initGlobal, ir->getDefaultInit());
setLinkageAndVisibility(decl, initGlobal);

// Define the __initZ symbol.
if (!decl->zeroInit) {
auto &initZ = ir->getInitSymbol();
auto initGlobal = llvm::cast<LLGlobalVariable>(initZ);
initZ = irs->setGlobalVarInitializer(initGlobal, ir->getDefaultInit());
setLinkageAndVisibility(decl, initGlobal);
}

// emit typeinfo
if (!ir->suppressTypeInfo()) {
Expand Down
8 changes: 5 additions & 3 deletions gen/llvmhelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1650,10 +1650,12 @@ DValue *DtoSymbolAddress(Loc &loc, Type *type, Declaration *decl) {
IF_LOG Logger::print("Sym: type=%s\n", sdecltype->toChars());
assert(sdecltype->ty == Tstruct);
TypeStruct *ts = static_cast<TypeStruct *>(sdecltype);
assert(ts->sym);
DtoResolveStruct(ts->sym);
StructDeclaration *sd = ts->sym;
assert(sd);
DtoResolveStruct(sd);

LLValue *initsym = getIrAggr(ts->sym)->getInitSymbol();
assert(!sd->zeroInit && "No init symbol for zero-initialized struct");
LLValue *initsym = getIrAggr(sd)->getInitSymbol();
initsym = DtoBitCast(initsym, DtoType(ts->pointerTo()));
return new DLValue(type, initsym);
}
Expand Down
41 changes: 36 additions & 5 deletions gen/toir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2294,15 +2294,21 @@ class ToElemVisitor : public Visitor {
LOG_SCOPE;

if (e->useStaticInit) {
DtoResolveStruct(e->sd);
LLValue *initsym = getIrAggr(e->sd)->getInitSymbol();
initsym = DtoBitCast(initsym, DtoType(e->type->pointerTo()));
StructDeclaration *sd = e->sd;
DtoResolveStruct(sd);

if (!dstMem)
dstMem = DtoAlloca(e->type, ".structliteral");

assert(dstMem->getType() == initsym->getType());
DtoMemCpy(dstMem, initsym);
if (sd->zeroInit) {
DtoMemSetZero(dstMem);
} else {
LLValue *initsym = getIrAggr(sd)->getInitSymbol();
initsym = DtoBitCast(initsym, DtoType(e->type->pointerTo()));
assert(dstMem->getType() == initsym->getType());
DtoMemCpy(dstMem, initsym);
}

return new DLValue(e->type, dstMem);
}

Expand Down Expand Up @@ -2757,6 +2763,31 @@ bool toInPlaceConstruction(DLValue *lhs, Expression *rhs) {
return true;
}

if (rhs->op == TOKvar) {
auto ve = static_cast<VarExp *>(rhs);
if (auto symdecl = ve->var->isSymbolDeclaration()) {
Type *t = symdecl->type->toBasetype();
if (auto ts = t->isTypeStruct()) {
// this is the static initializer for a struct (init symbol)
StructDeclaration *sd = ts->sym;
assert(sd);
DtoResolveStruct(sd);

LLValue *lhsLVal = DtoLVal(lhs);
if (sd->zeroInit) {
DtoMemSetZero(lhsLVal);
} else {
LLValue *initsym = getIrAggr(sd)->getInitSymbol();
initsym = DtoBitCast(initsym, DtoType(ve->type->pointerTo()));
assert(lhsLVal->getType() == initsym->getType());
DtoMemCpy(lhsLVal, initsym);
}

return true;
}
}
}

// static array literals too
Type *lhsBasetype = lhs->type->toBasetype();
if (rhs->op == TOKarrayliteral && lhsBasetype->ty == Tsarray) {
Expand Down
8 changes: 4 additions & 4 deletions tests/codegen/align.d
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
// Fails on Windows_x86, see https://github.com/ldc-developers/ldc/issues/1356
// XFAIL: Windows_x86

align(32) struct Outer { int a; }
struct Inner { align(32) int a; }
align(32) struct Outer { int a = 1; }
// CHECK-DAG: _D5align5Outer6__initZ = constant %align.Outer {{.*}}, align 32
struct Inner { align(32) int a = 1; }
// CHECK-DAG: _D5align5Inner6__initZ = constant %align.Inner {{.*}}, align 32

align(1) ubyte globalByte1;
// CHECK-DAG: _D5align11globalByte1h = {{.*}} align 1
static Outer globalOuter;
// CHECK-DAG: constant %align.Outer zeroinitializer{{(, comdat)?}}, align 32
// CHECK-DAG: _D5align11globalOuterSQu5Outer = {{.*}} align 32
static Inner globalInner;
// CHECK-DAG: constant %align.Inner zeroinitializer{{(, comdat)?}}, align 32
// CHECK-DAG: _D5align11globalInnerSQu5Inner = {{.*}} align 32

Outer passAndReturnOuterByVal(Outer arg) { return arg; }
Expand Down
4 changes: 2 additions & 2 deletions tests/codegen/export_aggregate_symbols.d
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ interface DefaultI { void foo(); }

// DEFAULT: _D24export_aggregate_symbols8DefaultS6__initZ
// HIDDEN-NOT: _D24export_aggregate_symbols8DefaultS6__initZ
struct DefaultS {}
struct DefaultS { int nonZero = 1; }



Expand All @@ -43,7 +43,7 @@ export class ExportedC : ExportedI { void foo() {} }
export interface ExportedI { void foo(); }

// BOTH: _D24export_aggregate_symbols9ExportedS6__initZ
export struct ExportedS {}
export struct ExportedS { int nonZero = 1; }



Expand Down
4 changes: 2 additions & 2 deletions tests/codegen/gh2235.d
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// RUN: %ldc -output-ll -of=%t.ll %s && FileCheck %s < %t.ll
// RUN: %ldc -run %s

// CHECK: %gh2235.Foo = type <{
// CHECK-DAG: %gh2235.Foo = type <{
align(2) struct Foo {
long y;
byte z;
}

// CHECK: %gh2235.Bar = type <{
// CHECK-DAG: %gh2235.Bar = type <{
class Bar {
union {
bool b;
Expand Down
13 changes: 13 additions & 0 deletions tests/codegen/no_init_symbols_for_zeroinit_structs.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// RUN: %ldc -output-ll -of=%t.ll %s
// RUN: FileCheck %s < %t.ll

module mod;

// CHECK-NOT: _D3mod5Empty6__initZ
struct Empty {}

// CHECK-NOT: _D3mod7WithInt6__initZ
struct WithInt { int a; }

// CHECK-NOT: _D3mod13WithZeroFloat6__initZ
struct WithZeroFloat { float a = 0; }
1 change: 0 additions & 1 deletion tests/codegen/simd_alignment.d
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ struct S17237
int4 globalIntFour;
// CHECK-DAG: globalIntFour{{.*}} = {{.*}} align 16
S17237 globalStruct;
// CHECK-DAG: constant %{{.*}}.S17237 zeroinitializer{{(, comdat)?}}, align 32
// CHECK-DAG: @{{.*}}globalStruct{{.*}}S17237{{\"?}} = {{.*}} zeroinitializer{{(, comdat)?}}, align 32

// CHECK-LABEL: define <8 x i32> @foo(
Expand Down

0 comments on commit 98fb979

Please sign in to comment.