changeset 1210:3d4581761b4c

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.
author Frits van Bommel <fvbommel wxs.nl>
date Sun, 12 Apr 2009 21:56:43 +0200
parents 8699c450a1a0
children 50dc0db06238
files gen/classes.cpp gen/nested.cpp gen/tollvm.cpp gen/tollvm.h
diffstat 4 files changed, 37 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- 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';
--- 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
--- 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)
--- 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.