mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-08 11:56:12 +03:00
Add some alignment info where LLVM might otherwise be more pessimistic.
In particular, %.nest_arg is always aligned even though it's bitcast from i8*. Pointers in vtables are also guaranteed to be stored at aligned addresses.
This commit is contained in:
parent
751f528969
commit
071bad95dc
4 changed files with 37 additions and 16 deletions
|
@ -1331,7 +1331,7 @@ LLValue* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl)
|
||||||
// index vtbl
|
// index vtbl
|
||||||
funcval = DtoGEPi(funcval, 0, fdecl->vtblIndex, fdecl->toChars());
|
funcval = DtoGEPi(funcval, 0, fdecl->vtblIndex, fdecl->toChars());
|
||||||
// load funcptr
|
// load funcptr
|
||||||
funcval = DtoLoad(funcval);
|
funcval = DtoAlignedLoad(funcval);
|
||||||
|
|
||||||
if (Logger::enabled())
|
if (Logger::enabled())
|
||||||
Logger::cout() << "funcval: " << *funcval << '\n';
|
Logger::cout() << "funcval: " << *funcval << '\n';
|
||||||
|
|
|
@ -96,7 +96,7 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd)
|
||||||
if (nestedCtx == NCArray) {
|
if (nestedCtx == NCArray) {
|
||||||
LLValue* val = DtoBitCast(ctx, getPtrToType(getVoidPtrType()));
|
LLValue* val = DtoBitCast(ctx, getPtrToType(getVoidPtrType()));
|
||||||
val = DtoGEPi1(val, vd->ir.irLocal->nestedIndex);
|
val = DtoGEPi1(val, vd->ir.irLocal->nestedIndex);
|
||||||
val = DtoLoad(val);
|
val = DtoAlignedLoad(val);
|
||||||
assert(vd->ir.irLocal->value);
|
assert(vd->ir.irLocal->value);
|
||||||
val = DtoBitCast(val, vd->ir.irLocal->value->getType(), vd->toChars());
|
val = DtoBitCast(val, vd->ir.irLocal->value->getType(), vd->toChars());
|
||||||
return new DVarValue(astype, vd, val);
|
return new DVarValue(astype, vd, val);
|
||||||
|
@ -107,10 +107,10 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd)
|
||||||
|
|
||||||
LLValue* val = DtoBitCast(ctx, LLPointerType::getUnqual(parentfunc->ir.irFunc->framesType));
|
LLValue* val = DtoBitCast(ctx, LLPointerType::getUnqual(parentfunc->ir.irFunc->framesType));
|
||||||
val = DtoGEPi(val, 0, vd->ir.irLocal->nestedDepth);
|
val = DtoGEPi(val, 0, vd->ir.irLocal->nestedDepth);
|
||||||
val = DtoLoad(val, (std::string(".frame.") + parentfunc->toChars()).c_str());
|
val = DtoAlignedLoad(val, (std::string(".frame.") + parentfunc->toChars()).c_str());
|
||||||
val = DtoGEPi(val, 0, vd->ir.irLocal->nestedIndex, vd->toChars());
|
val = DtoGEPi(val, 0, vd->ir.irLocal->nestedIndex, vd->toChars());
|
||||||
if (vd->ir.irLocal->byref)
|
if (vd->ir.irLocal->byref)
|
||||||
val = DtoLoad(val);
|
val = DtoAlignedLoad(val);
|
||||||
return new DVarValue(astype, vd, val);
|
return new DVarValue(astype, vd, val);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -137,7 +137,7 @@ void DtoNestedInit(VarDeclaration* vd)
|
||||||
assert(isaPointer(vd->ir.irLocal->value));
|
assert(isaPointer(vd->ir.irLocal->value));
|
||||||
LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType());
|
LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType());
|
||||||
|
|
||||||
DtoStore(val, gep);
|
DtoAlignedStore(val, gep);
|
||||||
}
|
}
|
||||||
else if (nestedCtx == NCHybrid) {
|
else if (nestedCtx == NCHybrid) {
|
||||||
assert(vd->ir.irLocal->value && "Nested variable without storage?");
|
assert(vd->ir.irLocal->value && "Nested variable without storage?");
|
||||||
|
@ -147,10 +147,10 @@ void DtoNestedInit(VarDeclaration* vd)
|
||||||
|
|
||||||
FuncDeclaration *parentfunc = getParentFunc(vd);
|
FuncDeclaration *parentfunc = getParentFunc(vd);
|
||||||
assert(parentfunc && "No parent function for nested variable?");
|
assert(parentfunc && "No parent function for nested variable?");
|
||||||
LLValue* frame = DtoLoad(framep, (std::string(".frame.") + parentfunc->toChars()).c_str());
|
LLValue* frame = DtoAlignedLoad(framep, (std::string(".frame.") + parentfunc->toChars()).c_str());
|
||||||
|
|
||||||
LLValue* slot = DtoGEPi(frame, 0, vd->ir.irLocal->nestedIndex);
|
LLValue* slot = DtoGEPi(frame, 0, vd->ir.irLocal->nestedIndex);
|
||||||
DtoStore(vd->ir.irLocal->value, slot);
|
DtoAlignedStore(vd->ir.irLocal->value, slot);
|
||||||
} else {
|
} else {
|
||||||
// Already initialized in DtoCreateNestedContext
|
// Already initialized in DtoCreateNestedContext
|
||||||
}
|
}
|
||||||
|
@ -248,7 +248,8 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
|
||||||
assert(cd->vthis);
|
assert(cd->vthis);
|
||||||
src = DtoLoad(DtoGEPi(thisval, 0,cd->vthis->ir.irField->index, ".vthis"));
|
src = DtoLoad(DtoGEPi(thisval, 0,cd->vthis->ir.irField->index, ".vthis"));
|
||||||
}
|
}
|
||||||
DtoMemCpy(nestedVars, src, DtoConstSize_t(nparelems*PTRSIZE));
|
DtoMemCpy(nestedVars, src, DtoConstSize_t(nparelems*PTRSIZE),
|
||||||
|
getABITypeAlign(getVoidPtrType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// store in IrFunction
|
// store in IrFunction
|
||||||
|
@ -267,7 +268,7 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
|
||||||
Logger::println("nested param: %s", vd->toChars());
|
Logger::println("nested param: %s", vd->toChars());
|
||||||
LLValue* gep = DtoGEPi(nestedVars, 0, idx);
|
LLValue* gep = DtoGEPi(nestedVars, 0, idx);
|
||||||
LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType());
|
LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType());
|
||||||
DtoStore(val, gep);
|
DtoAlignedStore(val, gep);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -367,13 +368,14 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
|
||||||
}
|
}
|
||||||
src = DtoBitCast(src, getVoidPtrType());
|
src = DtoBitCast(src, getVoidPtrType());
|
||||||
LLValue* dst = DtoBitCast(nestedVars, getVoidPtrType());
|
LLValue* dst = DtoBitCast(nestedVars, getVoidPtrType());
|
||||||
DtoMemCpy(dst, src, DtoConstSize_t(depth * PTRSIZE));
|
DtoMemCpy(dst, src, DtoConstSize_t(depth * PTRSIZE),
|
||||||
|
getABITypeAlign(getVoidPtrType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create frame for current function and append to frames list
|
// Create frame for current function and append to frames list
|
||||||
LLValue* frame = DtoAlloca(frameType, ".frame");
|
LLValue* frame = DtoAlloca(frameType, ".frame");
|
||||||
// store current frame in list
|
// store current frame in list
|
||||||
DtoStore(frame, DtoGEPi(nestedVars, 0, depth));
|
DtoAlignedStore(frame, DtoGEPi(nestedVars, 0, depth));
|
||||||
|
|
||||||
// store context in IrFunction
|
// store context in IrFunction
|
||||||
irfunction->nestedVar = nestedVars;
|
irfunction->nestedVar = nestedVars;
|
||||||
|
@ -386,7 +388,7 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
|
||||||
LLValue* gep = DtoGEPi(frame, 0, vd->ir.irLocal->nestedIndex, vd->toChars());
|
LLValue* gep = DtoGEPi(frame, 0, vd->ir.irLocal->nestedIndex, vd->toChars());
|
||||||
if (vd->isParameter()) {
|
if (vd->isParameter()) {
|
||||||
Logger::println("nested param: %s", vd->toChars());
|
Logger::println("nested param: %s", vd->toChars());
|
||||||
DtoStore(vd->ir.irLocal->value, gep);
|
DtoAlignedStore(vd->ir.irLocal->value, gep);
|
||||||
vd->ir.irLocal->byref = true;
|
vd->ir.irLocal->byref = true;
|
||||||
} else if (vd->isRef() || vd->isOut()) {
|
} else if (vd->isRef() || vd->isOut()) {
|
||||||
// This slot is initialized in DtoNestedInit, to handle things like byref foreach variables
|
// This slot is initialized in DtoNestedInit, to handle things like byref foreach variables
|
||||||
|
|
|
@ -426,7 +426,7 @@ void DtoMemSetZero(LLValue* dst, LLValue* nbytes)
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void DtoMemCpy(LLValue* dst, LLValue* src, LLValue* nbytes)
|
void DtoMemCpy(LLValue* dst, LLValue* src, LLValue* nbytes, unsigned align)
|
||||||
{
|
{
|
||||||
dst = DtoBitCast(dst,getVoidPtrType());
|
dst = DtoBitCast(dst,getVoidPtrType());
|
||||||
src = DtoBitCast(src,getVoidPtrType());
|
src = DtoBitCast(src,getVoidPtrType());
|
||||||
|
@ -435,7 +435,7 @@ void DtoMemCpy(LLValue* dst, LLValue* src, LLValue* nbytes)
|
||||||
llvm::Function* fn = llvm::Intrinsic::getDeclaration(gIR->module,
|
llvm::Function* fn = llvm::Intrinsic::getDeclaration(gIR->module,
|
||||||
llvm::Intrinsic::memcpy, &intTy, 1);
|
llvm::Intrinsic::memcpy, &intTy, 1);
|
||||||
|
|
||||||
gIR->ir->CreateCall4(fn, dst, src, nbytes, DtoConstUint(0), "");
|
gIR->ir->CreateCall4(fn, dst, src, nbytes, DtoConstUint(align), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -573,11 +573,20 @@ LLValue* DtoLoad(LLValue* src, const char* name)
|
||||||
{
|
{
|
||||||
// if (Logger::enabled())
|
// if (Logger::enabled())
|
||||||
// Logger::cout() << "loading " << *src << '\n';
|
// Logger::cout() << "loading " << *src << '\n';
|
||||||
LLValue* ld = gIR->ir->CreateLoad(src, name ? name : "tmp");
|
llvm::LoadInst* ld = gIR->ir->CreateLoad(src, name ? name : "tmp");
|
||||||
//ld->setVolatile(gIR->func()->inVolatile);
|
//ld->setVolatile(gIR->func()->inVolatile);
|
||||||
return ld;
|
return ld;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Like DtoLoad, but the pointer is guaranteed to be aligned appropriately for the type.
|
||||||
|
LLValue* DtoAlignedLoad(LLValue* src, const char* name)
|
||||||
|
{
|
||||||
|
llvm::LoadInst* ld = gIR->ir->CreateLoad(src, name ? name : "tmp");
|
||||||
|
ld->setAlignment(getABITypeAlign(ld->getType()));
|
||||||
|
return ld;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DtoStore(LLValue* src, LLValue* dst)
|
void DtoStore(LLValue* src, LLValue* dst)
|
||||||
{
|
{
|
||||||
// if (Logger::enabled())
|
// if (Logger::enabled())
|
||||||
|
@ -586,6 +595,13 @@ void DtoStore(LLValue* src, LLValue* dst)
|
||||||
//st->setVolatile(gIR->func()->inVolatile);
|
//st->setVolatile(gIR->func()->inVolatile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Like DtoStore, but the pointer is guaranteed to be aligned appropriately for the type.
|
||||||
|
void DtoAlignedStore(LLValue* src, LLValue* dst)
|
||||||
|
{
|
||||||
|
llvm::StoreInst* st = gIR->ir->CreateStore(src,dst);
|
||||||
|
st->setAlignment(getABITypeAlign(src->getType()));
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
LLValue* DtoBitCast(LLValue* v, const LLType* t, const char* name)
|
LLValue* DtoBitCast(LLValue* v, const LLType* t, const char* name)
|
||||||
|
|
|
@ -63,7 +63,9 @@ LLConstant* DtoConstBool(bool);
|
||||||
|
|
||||||
// llvm wrappers
|
// llvm wrappers
|
||||||
LLValue* DtoLoad(LLValue* src, const char* name=0);
|
LLValue* DtoLoad(LLValue* src, const char* name=0);
|
||||||
|
LLValue* DtoAlignedLoad(LLValue* src, const char* name=0);
|
||||||
void DtoStore(LLValue* src, LLValue* dst);
|
void DtoStore(LLValue* src, LLValue* dst);
|
||||||
|
void DtoAlignedStore(LLValue* src, LLValue* dst);
|
||||||
LLValue* DtoBitCast(LLValue* v, const LLType* t, const char* name=0);
|
LLValue* DtoBitCast(LLValue* v, const LLType* t, const char* name=0);
|
||||||
LLConstant* DtoBitCast(LLConstant* v, const LLType* t);
|
LLConstant* DtoBitCast(LLConstant* v, const LLType* t);
|
||||||
|
|
||||||
|
@ -117,8 +119,9 @@ void DtoMemSetZero(LLValue* dst, LLValue* nbytes);
|
||||||
* @param dst Destination memory.
|
* @param dst Destination memory.
|
||||||
* @param src Source memory.
|
* @param src Source memory.
|
||||||
* @param nbytes Number of bytes to copy.
|
* @param nbytes Number of bytes to copy.
|
||||||
|
* @param align The minimum alignment of the source and destination memory.
|
||||||
*/
|
*/
|
||||||
void DtoMemCpy(LLValue* dst, LLValue* src, LLValue* nbytes);
|
void DtoMemCpy(LLValue* dst, LLValue* src, LLValue* nbytes, unsigned align = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a call to C memcmp.
|
* Generates a call to C memcmp.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue