Skip to content

Commit 8117036

Browse files
committed
Fix for issue ldc-developers#119.
Instead of creating individual stores to the array elements an constant array is created and assigned to the destination memory. This is much less IR than before. With -O it is optimized to a memset.
1 parent e24c76e commit 8117036

File tree

1 file changed

+55
-11
lines changed

1 file changed

+55
-11
lines changed

gen/toir.cpp

+55-11
Original file line numberDiff line numberDiff line change
@@ -2876,20 +2876,64 @@ DValue* ArrayLiteralExp::toElem(IRState* p)
28762876
else
28772877
dstMem = DtoRawAlloca(llStoType, 0, "arrayliteral");
28782878

2879-
// store elements
2880-
for (size_t i=0; i<len; ++i)
2879+
// Check for const'ness
2880+
bool isAllConst = true;
2881+
for (size_t i = 0; i < len && isAllConst; ++i)
28812882
{
2882-
Expression* expr = static_cast<Expression*>(elements->data[i]);
2883-
LLValue* elemAddr;
2884-
if(dyn)
2885-
elemAddr = DtoGEPi1(dstMem, i, "tmp", p->scopebb());
2883+
Expression *expr = static_cast<Expression *>(elements->data[i]);
2884+
isAllConst = expr->isConst() == 1;
2885+
}
2886+
2887+
if (isAllConst)
2888+
{
2889+
// allocate room for initializers
2890+
std::vector<LLConstant *> initvals(len, NULL);
2891+
2892+
// true if array elements differ in type
2893+
bool mismatch = false;
2894+
2895+
// store elements
2896+
for (size_t i = 0; i < len; ++i)
2897+
{
2898+
Expression *expr = static_cast<Expression *>(elements->data[i]);
2899+
llvm::Constant *c = expr->toConstElem(gIR);
2900+
if (llElemType != c->getType())
2901+
mismatch = true;
2902+
initvals[i] = c;
2903+
}
2904+
LLConstant *constarr;
2905+
if (mismatch)
2906+
constarr = LLConstantStruct::getAnon(gIR->context(), initvals); // FIXME should this pack?;
2907+
else
2908+
constarr = LLConstantArray::get(LLArrayType::get(llElemType, len), initvals);
2909+
2910+
// If the type pointed to by dstMem is different from the array type
2911+
// then we must assign the value to a global variable.
2912+
if (constarr->getType() != dstMem->getType()->getPointerElementType())
2913+
{
2914+
LLGlobalVariable *gvar = new LLGlobalVariable(*gIR->module, constarr->getType(), true, LLGlobalValue::InternalLinkage, constarr, ".constarrayliteral_init");
2915+
DtoMemCpy(dstMem, gvar, DtoConstSize_t(getTypePaddedSize(constarr->getType())));
2916+
}
28862917
else
2887-
elemAddr = DtoGEPi(dstMem,0,i,"tmp",p->scopebb());
2918+
DtoStore(constarr, dstMem);
2919+
}
2920+
else
2921+
{
2922+
// store elements
2923+
for (size_t i = 0; i < len; ++i)
2924+
{
2925+
Expression *expr = static_cast<Expression *>(elements->data[i]);
2926+
LLValue *elemAddr;
2927+
if(dyn)
2928+
elemAddr = DtoGEPi1(dstMem, i, "tmp", p->scopebb());
2929+
else
2930+
elemAddr = DtoGEPi(dstMem, 0, i, "tmp", p->scopebb());
28882931

2889-
// emulate assignment
2890-
DVarValue* vv = new DVarValue(expr->type, elemAddr);
2891-
DValue* e = expr->toElem(p);
2892-
DtoAssign(loc, vv, e);
2932+
// emulate assignment
2933+
DVarValue *vv = new DVarValue(expr->type, elemAddr);
2934+
DValue *e = expr->toElem(p);
2935+
DtoAssign(loc, vv, e);
2936+
}
28932937
}
28942938

28952939
// return storage directly ?

0 commit comments

Comments
 (0)