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:
Frits van Bommel 2009-04-12 21:56:43 +02:00
parent 751f528969
commit 071bad95dc
4 changed files with 37 additions and 16 deletions

View file

@ -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';

View file

@ -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

View file

@ -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)

View file

@ -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.