mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-07 03:16:05 +03:00
Don't emit init symbol for zero-initialized structs (#3131)
And optimize previous usages of it to direct memset-zero.
This commit is contained in:
parent
25195fb36c
commit
3840a03af4
8 changed files with 69 additions and 22 deletions
|
@ -141,12 +141,15 @@ public:
|
|||
// 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);
|
||||
|
||||
// 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()) {
|
||||
|
|
|
@ -1650,10 +1650,16 @@ 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();
|
||||
if (sd->zeroInit) {
|
||||
error(loc, "no init symbol for zero-initialized struct");
|
||||
fatal();
|
||||
}
|
||||
|
||||
LLValue *initsym = getIrAggr(sd)->getInitSymbol();
|
||||
initsym = DtoBitCast(initsym, DtoType(ts->pointerTo()));
|
||||
return new DLValue(type, initsym);
|
||||
}
|
||||
|
|
32
gen/toir.cpp
32
gen/toir.cpp
|
@ -2293,15 +2293,21 @@ public:
|
|||
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");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -2739,6 +2745,26 @@ bool basetypesAreEqualWithoutModifiers(Type *l, Type *r) {
|
|||
}
|
||||
|
||||
bool toInPlaceConstruction(DLValue *lhs, Expression *rhs) {
|
||||
// Is the rhs the init symbol of a zero-initialized struct?
|
||||
// Then aggressively zero-out the lhs, without any type checks, e.g., allowing
|
||||
// to initialize a `S[1]` lhs with a `S` rhs.
|
||||
if (auto ve = rhs->isVarExp()) {
|
||||
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);
|
||||
|
||||
if (sd->zeroInit) {
|
||||
DtoMemSetZero(DtoLVal(lhs));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!basetypesAreEqualWithoutModifiers(lhs->type, rhs->type))
|
||||
return false;
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
||||
|
||||
|
@ -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; }
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
13
tests/codegen/no_init_symbols_for_zeroinit_structs.d
Normal file
13
tests/codegen/no_init_symbols_for_zeroinit_structs.d
Normal file
|
@ -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; }
|
|
@ -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(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue