# HG changeset patch # User Frits van Bommel # Date 1239566203 -7200 # Node ID 3d4581761b4c92d936cabae1658afb5487118e7d # Parent 8699c450a1a0eb292a41cf0fb618f104c6bbcbf5 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. diff -r 8699c450a1a0 -r 3d4581761b4c gen/classes.cpp --- a/gen/classes.cpp Sun Apr 12 20:23:00 2009 +0200 +++ b/gen/classes.cpp Sun Apr 12 21:56:43 2009 +0200 @@ -1331,7 +1331,7 @@ // index vtbl funcval = DtoGEPi(funcval, 0, fdecl->vtblIndex, fdecl->toChars()); // load funcptr - funcval = DtoLoad(funcval); + funcval = DtoAlignedLoad(funcval); if (Logger::enabled()) Logger::cout() << "funcval: " << *funcval << '\n'; diff -r 8699c450a1a0 -r 3d4581761b4c gen/nested.cpp --- a/gen/nested.cpp Sun Apr 12 20:23:00 2009 +0200 +++ b/gen/nested.cpp Sun Apr 12 21:56:43 2009 +0200 @@ -96,7 +96,7 @@ if (nestedCtx == NCArray) { LLValue* val = DtoBitCast(ctx, getPtrToType(getVoidPtrType())); val = DtoGEPi1(val, vd->ir.irLocal->nestedIndex); - val = DtoLoad(val); + val = DtoAlignedLoad(val); assert(vd->ir.irLocal->value); val = DtoBitCast(val, vd->ir.irLocal->value->getType(), vd->toChars()); return new DVarValue(astype, vd, val); @@ -107,10 +107,10 @@ LLValue* val = DtoBitCast(ctx, LLPointerType::getUnqual(parentfunc->ir.irFunc->framesType)); 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()); if (vd->ir.irLocal->byref) - val = DtoLoad(val); + val = DtoAlignedLoad(val); return new DVarValue(astype, vd, val); } else { @@ -137,7 +137,7 @@ assert(isaPointer(vd->ir.irLocal->value)); LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType()); - DtoStore(val, gep); + DtoAlignedStore(val, gep); } else if (nestedCtx == NCHybrid) { assert(vd->ir.irLocal->value && "Nested variable without storage?"); @@ -147,10 +147,10 @@ FuncDeclaration *parentfunc = getParentFunc(vd); 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); - DtoStore(vd->ir.irLocal->value, slot); + DtoAlignedStore(vd->ir.irLocal->value, slot); } else { // Already initialized in DtoCreateNestedContext } @@ -248,7 +248,8 @@ assert(cd->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 @@ -267,7 +268,7 @@ Logger::println("nested param: %s", vd->toChars()); LLValue* gep = DtoGEPi(nestedVars, 0, idx); LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType()); - DtoStore(val, gep); + DtoAlignedStore(val, gep); } else { @@ -367,13 +368,14 @@ } src = DtoBitCast(src, 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 LLValue* frame = DtoAlloca(frameType, ".frame"); // store current frame in list - DtoStore(frame, DtoGEPi(nestedVars, 0, depth)); + DtoAlignedStore(frame, DtoGEPi(nestedVars, 0, depth)); // store context in IrFunction irfunction->nestedVar = nestedVars; @@ -386,7 +388,7 @@ LLValue* gep = DtoGEPi(frame, 0, vd->ir.irLocal->nestedIndex, vd->toChars()); if (vd->isParameter()) { Logger::println("nested param: %s", vd->toChars()); - DtoStore(vd->ir.irLocal->value, gep); + DtoAlignedStore(vd->ir.irLocal->value, gep); vd->ir.irLocal->byref = true; } else if (vd->isRef() || vd->isOut()) { // This slot is initialized in DtoNestedInit, to handle things like byref foreach variables diff -r 8699c450a1a0 -r 3d4581761b4c gen/tollvm.cpp --- a/gen/tollvm.cpp Sun Apr 12 20:23:00 2009 +0200 +++ b/gen/tollvm.cpp Sun Apr 12 21:56:43 2009 +0200 @@ -426,7 +426,7 @@ ////////////////////////////////////////////////////////////////////////////////////////// -void DtoMemCpy(LLValue* dst, LLValue* src, LLValue* nbytes) +void DtoMemCpy(LLValue* dst, LLValue* src, LLValue* nbytes, unsigned align) { dst = DtoBitCast(dst,getVoidPtrType()); src = DtoBitCast(src,getVoidPtrType()); @@ -435,7 +435,7 @@ llvm::Function* fn = llvm::Intrinsic::getDeclaration(gIR->module, 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 @@ { // if (Logger::enabled()) // 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); 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) { // if (Logger::enabled()) @@ -586,6 +595,13 @@ //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) diff -r 8699c450a1a0 -r 3d4581761b4c gen/tollvm.h --- a/gen/tollvm.h Sun Apr 12 20:23:00 2009 +0200 +++ b/gen/tollvm.h Sun Apr 12 21:56:43 2009 +0200 @@ -63,7 +63,9 @@ // llvm wrappers LLValue* DtoLoad(LLValue* src, const char* name=0); +LLValue* DtoAlignedLoad(LLValue* src, const char* name=0); void DtoStore(LLValue* src, LLValue* dst); +void DtoAlignedStore(LLValue* src, LLValue* dst); LLValue* DtoBitCast(LLValue* v, const LLType* t, const char* name=0); LLConstant* DtoBitCast(LLConstant* v, const LLType* t); @@ -117,8 +119,9 @@ * @param dst Destination memory. * @param src Source memory. * @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.