# HG changeset patch # User Christian Kamm # Date 1266138665 -3600 # Node ID 5c0cebff9be8f887af29cf826fd78ad1e14c561c # Parent 8c37dcd7cfdeb097e6bfd46b1746f8a84daf50e1 Improve array append performance. Actually use the appropriate runtime function, instead of just growing the array by one! diff -r 8c37dcd7cfde -r 5c0cebff9be8 gen/arrays.cpp --- a/gen/arrays.cpp Sun Sep 13 22:15:33 2009 +0300 +++ b/gen/arrays.cpp Sun Feb 14 10:11:05 2010 +0100 @@ -474,7 +474,7 @@ // build dims LLValue* dimsArg = DtoArrayAlloca(Type::tsize_t, ndims, ".newdims"); - LLValue* firstDim = NULL; + LLValue* firstDim = NULL; for (size_t i=0; igetRVal(); @@ -532,30 +532,29 @@ } ////////////////////////////////////////////////////////////////////////////////////////// -DSliceValue* DtoCatAssignElement(DValue* array, Expression* exp) +void DtoCatAssignElement(Type* arrayType, DValue* array, Expression* exp) { Logger::println("DtoCatAssignElement"); LOG_SCOPE; assert(array); - LLValue* idx = DtoArrayLen(array); - LLValue* one = DtoConstSize_t(1); - LLValue* len = gIR->ir->CreateAdd(idx,one,"tmp"); - - DValue* newdim = new DImValue(Type::tsize_t, len); - DSliceValue* slice = DtoResizeDynArray(array->getType(), array, newdim); + DValue *expVal = exp->toElem(gIR); + LLValue *valueToAppend; + if (expVal->isLVal()) + valueToAppend = expVal->getLVal(); + else { + valueToAppend = DtoAlloca(expVal->getType(), ".appendingElementOnStack"); + DtoStore(expVal->getRVal(), valueToAppend); + } - LLValue* ptr = slice->ptr; - ptr = llvm::GetElementPtrInst::Create(ptr, idx, "tmp", gIR->scopebb()); - - DValue* dptr = new DVarValue(exp->type, ptr); + LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_arrayappendcT"); + LLSmallVector args; + args.push_back(DtoTypeInfoOf(arrayType)); + args.push_back(DtoBitCast(array->getLVal(), getVoidPtrType())); + args.push_back(DtoBitCast(valueToAppend, getVoidPtrType())); - DValue* e = exp->toElem(gIR); - - DtoAssign(exp->loc, dptr, e); - - return slice; + gIR->CreateCallOrInvoke(fn, args.begin(), args.end(), ".appendedArray"); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -980,7 +979,7 @@ else if (totype->ty == Tsarray) { if (Logger::enabled()) Logger::cout() << "to sarray" << '\n'; - + size_t tosize = ((TypeSArray*)totype)->dim->toInteger(); if (fromtype->ty == Tsarray) { @@ -1004,9 +1003,9 @@ size_t i = (tosize * totype->nextOf()->size() - 1) / fromtype->nextOf()->size(); DConstValue index(Type::tsize_t, DtoConstSize_t(i)); DtoArrayBoundsCheck(loc, u, &index, false); - + rval = DtoArrayPtr(u); - rval = DtoBitCast(rval, getPtrToType(tolltype)); + rval = DtoBitCast(rval, getPtrToType(tolltype)); } } else if (totype->ty == Tbool) { diff -r 8c37dcd7cfde -r 5c0cebff9be8 gen/arrays.h --- a/gen/arrays.h Sun Sep 13 22:15:33 2009 +0300 +++ b/gen/arrays.h Sun Feb 14 10:11:05 2010 +0100 @@ -24,7 +24,7 @@ DSliceValue* DtoNewMulDimDynArray(Loc& loc, Type* arrayType, DValue** dims, size_t ndims, bool defaultInit=true); DSliceValue* DtoResizeDynArray(Type* arrayType, DValue* array, DValue* newdim); -DSliceValue* DtoCatAssignElement(DValue* arr, Expression* exp); +void DtoCatAssignElement(Type* type, DValue* arr, Expression* exp); DSliceValue* DtoCatAssignArray(DValue* arr, Expression* exp); DSliceValue* DtoCatArrays(Type* type, Expression* e1, Expression* e2); DSliceValue* DtoCatArrayElement(Type* type, Expression* exp1, Expression* exp2); diff -r 8c37dcd7cfde -r 5c0cebff9be8 gen/runtime.cpp --- a/gen/runtime.cpp Sun Sep 13 22:15:33 2009 +0300 +++ b/gen/runtime.cpp Sun Feb 14 10:11:05 2010 +0100 @@ -326,6 +326,17 @@ llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M); } + // void* _d_arrayappendcT(TypeInfo ti, void* array, void* element) + { + llvm::StringRef fname("_d_arrayappendcT"); + std::vector types; + types.push_back(typeInfoTy); + types.push_back(voidPtrTy); + types.push_back(voidPtrTy); + const llvm::FunctionType* fty = llvm::FunctionType::get(rt_array(byteTy), types, false); + llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); + } + // Object _d_allocclass(ClassInfo ci) { llvm::StringRef fname("_d_allocclass"); diff -r 8c37dcd7cfde -r 5c0cebff9be8 gen/toir.cpp --- a/gen/toir.cpp Sun Sep 13 22:15:33 2009 +0300 +++ b/gen/toir.cpp Sun Feb 14 10:11:05 2010 +0100 @@ -624,7 +624,7 @@ // valid array ops would have been transformed by optimize if ((t1->ty == Tarray || t1->ty == Tsarray) && (t2->ty == Tarray || t2->ty == Tsarray) - ) + ) { base->error("Array operation %s not recognized", base->toChars()); fatal(); @@ -1013,7 +1013,7 @@ return DtoBitCast(gep, DtoType(type)); } else if ( - e1->op == TOKstructliteral || + e1->op == TOKstructliteral || e1->op == TOKslice) { error("non-constant expression '%s'", toChars()); @@ -1138,7 +1138,7 @@ // decide whether this function needs to be looked up in the vtable // bool vtbllookup = fdecl->isAbstract() || (!fdecl->isFinal() && fdecl->isVirtual()); - + // even virtual functions are looked up directly if super or DotTypeExp // are used, thus we need to walk through the this expression and check Expression* e = e1; @@ -1150,7 +1150,7 @@ else break; } - + // // look up function // @@ -1237,12 +1237,12 @@ arrptr = DtoGEP1(l->getRVal(),r->getRVal()); } else if (e1type->ty == Tsarray) { - if(global.params.useArrayBounds) + if(global.params.useArrayBounds) DtoArrayBoundsCheck(loc, l, r, false); arrptr = DtoGEP(l->getRVal(), zero, r->getRVal()); } else if (e1type->ty == Tarray) { - if(global.params.useArrayBounds) + if(global.params.useArrayBounds) DtoArrayBoundsCheck(loc, l, r, false); arrptr = DtoArrayPtr(l); arrptr = DtoGEP1(arrptr,r->getRVal()); @@ -1769,7 +1769,7 @@ // class invariants if( - global.params.useInvariants && + global.params.useInvariants && condty->ty == Tclass && !((TypeClass*)condty)->sym->isInterfaceDeclaration()) { @@ -1780,7 +1780,7 @@ } // struct invariants else if( - global.params.useInvariants && + global.params.useInvariants && condty->ty == Tpointer && condty->nextOf()->ty == Tstruct && (invdecl = ((TypeStruct*)condty->nextOf())->sym->inv) != NULL) { @@ -2234,8 +2234,7 @@ Type* e2type = e2->type->toBasetype(); if (e2type == elemtype) { - DSliceValue* slice = DtoCatAssignElement(l,e2); - DtoAssign(loc, l, slice); + DtoCatAssignElement(e1type, l, e2); } else if (e1type == e2type) { DSliceValue* slice = DtoCatAssignArray(l,e2); diff -r 8c37dcd7cfde -r 5c0cebff9be8 tango-0.99.9.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tango-0.99.9.patch Sun Feb 14 10:11:05 2010 +0100 @@ -0,0 +1,55 @@ +Index: tango/core/rt/compiler/ldc/rt/lifetime.d +=================================================================== +--- tango/core/rt/compiler/ldc/rt/lifetime.d (revision 5368) ++++ tango/core/rt/compiler/ldc/rt/lifetime.d (working copy) +@@ -786,6 +786,7 @@ + return *cast(long*)px; + } + +++/ + + /** + * +@@ -849,10 +850,11 @@ + + + /** +- * ++ * Appends a single element to an array. + */ +-extern (C) byte[] _d_arrayappendcT(TypeInfo ti, ref byte[] x, ...) ++extern (C) byte[] _d_arrayappendcT(TypeInfo ti, void* array, void* element) + { ++ auto x = cast(byte[]*)array; + auto sizeelem = ti.next.tsize(); // array element size + auto info = gc_query(x.ptr); + auto length = x.length; +@@ -879,16 +881,16 @@ + assert(newcap >= newlength * sizeelem); + newdata = cast(byte *)gc_malloc(newcap + 1, info.attr); + memcpy(newdata, x.ptr, length * sizeelem); +- (cast(void**)(&x))[1] = newdata; ++ (cast(void**)x)[1] = newdata; + } + L1: +- byte *argp = cast(byte *)(&ti + 2); ++ byte *argp = cast(byte *)element; + +- *cast(size_t *)&x = newlength; ++ *cast(size_t *)x = newlength; + x.ptr[length * sizeelem .. newsize] = argp[0 .. sizeelem]; + assert((cast(size_t)x.ptr & 15) == 0); + assert(gc_sizeOf(x.ptr) > x.length * sizeelem); +- return x; ++ return *x; + } + + +@@ -1128,6 +1130,7 @@ + return result; + } + ++/+ + + /** + *