Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize ABIRewrite system for lvalues #1528

Merged
merged 5 commits into from
May 29, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions gen/abi-aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ struct AArch64TargetABI : TargetABI {
// non-HFA and messes up register selection
if (isHFA((TypeStruct *)retTy, &fty.ret->ltype)) {
fty.ret->rewrite = &hfaToArray;
fty.ret->ltype = hfaToArray.type(fty.ret->type, fty.ret->ltype);
fty.ret->ltype = hfaToArray.type(fty.ret->type);
}
else {
fty.ret->rewrite = &integerRewrite;
fty.ret->ltype = integerRewrite.type(fty.ret->type, fty.ret->ltype);
fty.ret->ltype = integerRewrite.type(fty.ret->type);
}
}

Expand All @@ -75,11 +75,11 @@ struct AArch64TargetABI : TargetABI {
// non-HFA and messes up register selection
if (ty->ty == Tstruct && isHFA((TypeStruct *)ty, &arg.ltype)) {
arg.rewrite = &hfaToArray;
arg.ltype = hfaToArray.type(arg.type, arg.ltype);
arg.ltype = hfaToArray.type(arg.type);
}
else {
arg.rewrite = &compositeToArray64;
arg.ltype = compositeToArray64.type(arg.type, arg.ltype);
arg.ltype = compositeToArray64.type(arg.type);
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions gen/abi-arm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ struct ArmTargetABI : TargetABI {
fty.ret->rewrite = &hfaToArray;
} else {
fty.ret->rewrite = &integerRewrite;
fty.ret->ltype = integerRewrite.type(fty.ret->type, fty.ret->ltype);
fty.ret->ltype = integerRewrite.type(fty.ret->type);
}
}

Expand Down Expand Up @@ -111,10 +111,10 @@ struct ArmTargetABI : TargetABI {
arg.rewrite = &hfaToArray;
} else if (DtoAlignment(ty) <= 4) {
arg.rewrite = &compositeToArray32;
arg.ltype = compositeToArray32.type(arg.type, arg.ltype);
arg.ltype = compositeToArray32.type(arg.type);
} else {
arg.rewrite = &compositeToArray64;
arg.ltype = compositeToArray64.type(arg.type, arg.ltype);
arg.ltype = compositeToArray64.type(arg.type);
}
}
}
Expand Down
133 changes: 51 additions & 82 deletions gen/abi-generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,30 +84,21 @@ struct LLTypeMemoryLayout {

/// Removes padding fields for (non-union-containing!) structs
struct RemoveStructPadding : ABIRewrite {
/// get a rewritten value back to its original form
LLValue *get(Type *dty, LLValue *v) override {
LLValue *lval = DtoAlloca(dty, ".rewritetmp");
getL(dty, v, lval);
return lval;
LLValue *put(DValue *v) override {
return DtoUnpaddedStruct(v->getType()->toBasetype(), v->getRVal());
}

/// get a rewritten value back to its original form and store result in
/// provided lvalue
void getL(Type *dty, LLValue *v, LLValue *lval) override {
LLValue *getLVal(Type *dty, LLValue *v) override {
LLValue *lval = DtoAlloca(dty, ".RemoveStructPadding_dump");
// Make sure the padding is zero, so struct comparisons work.
// TODO: Only do this if there's padding, and/or only initialize padding.
DtoMemSetZero(lval, DtoConstSize_t(getTypeAllocSize(DtoType(dty))));
DtoPaddedStruct(dty->toBasetype(), v, lval);
return lval;
}

/// put out rewritten value
LLValue *put(DValue *v) override {
return DtoUnpaddedStruct(v->getType()->toBasetype(), v->getRVal());
}

/// return the transformed type for this rewrite
LLType *type(Type *dty, LLType *t) override {
return DtoUnpaddedStructType(dty->toBasetype());
LLType *type(Type *t) override {
return DtoUnpaddedStructType(t->toBasetype());
}
};

Expand Down Expand Up @@ -164,23 +155,17 @@ struct IntegerRewrite : ABIRewrite {
return LLTypeMemoryLayout::typesAreEquivalent(llType, integerType);
}

LLValue *get(Type *dty, LLValue *v) override {
LLValue *integerDump = DtoAllocaDump(v, dty, ".IntegerRewrite_dump");
LLType *type = DtoType(dty);
return loadFromMemory(integerDump, type, ".IntegerRewrite_getResult");
}

void getL(Type *dty, LLValue *v, LLValue *lval) override {
storeToMemory(v, lval);
}

LLValue *put(DValue *dv) override {
LLValue *address = getAddressOf(dv);
LLType *integerType = getIntegerType(dv->getType()->size());
return loadFromMemory(address, integerType, ".IntegerRewrite_putResult");
return loadFromMemory(address, integerType);
}

LLValue *getLVal(Type *dty, LLValue *v) override {
return DtoAllocaDump(v, dty, ".IntegerRewrite_dump");
}

LLType *type(Type *t, LLType *) override { return getIntegerType(t->size()); }
LLType *type(Type *t) override { return getIntegerType(t->size()); }
};

//////////////////////////////////////////////////////////////////////////////
Expand All @@ -204,32 +189,28 @@ struct ExplicitByvalRewrite : ABIRewrite {
explicit ExplicitByvalRewrite(unsigned minAlignment = 16)
: minAlignment(minAlignment) {}

LLValue *get(Type *dty, LLValue *v) override {
return DtoLoad(v, ".ExplicitByvalRewrite_getResult");
}

void getL(Type *dty, LLValue *v, LLValue *lval) override {
DtoMemCpy(lval, v);
}

LLValue *put(DValue *v) override {
Type *dty = v->getType();
const unsigned align = alignment(dty);

if (DtoIsInMemoryOnly(dty)) {
LLValue *originalPointer = v->getRVal();
LLType *type = originalPointer->getType()->getPointerElementType();
LLValue *copyForCallee =
DtoRawAlloca(type, align, ".ExplicitByvalRewrite_putResult");
DtoMemCpy(copyForCallee, originalPointer);
return copyForCallee;
if (!DtoIsInMemoryOnly(dty)) {
return DtoAllocaDump(v->getRVal(), align,
".ExplicitByvalRewrite_dump");
}

return DtoAllocaDump(v->getRVal(), align,
".ExplicitByvalRewrite_putResult");
LLValue *originalPointer = v->getRVal();
LLType *type = originalPointer->getType()->getPointerElementType();
LLValue *copyForCallee =
DtoRawAlloca(type, align, ".ExplicitByvalRewrite_dump");
DtoMemCpy(copyForCallee, originalPointer);
return copyForCallee;
}

LLType *type(Type *dty, LLType *t) override { return DtoPtrToType(dty); }
LLValue *getLVal(Type *dty, LLValue *v) override {
return DtoBitCast(v, DtoPtrToType(dty));
}

LLType *type(Type *t) override { return DtoPtrToType(t); }

unsigned alignment(Type *dty) const {
return std::max(minAlignment, DtoAlignment(dty));
Expand All @@ -245,52 +226,44 @@ struct HFAToArray : ABIRewrite {

HFAToArray(const int max = 4) : maxFloats(max) {}

LLValue *get(Type *dty, LLValue *v) override {
Logger::println("rewriting array -> as HFA %s", dty->toChars());
LLValue *lval = DtoRawAlloca(v->getType(), 0);
DtoStore(v, lval);

LLType *pTy = getPtrToType(DtoType(dty));
return DtoLoad(DtoBitCast(lval, pTy), "get-result");
}

LLValue *put(DValue *dv) override {
Type *dty = dv->getType();
Logger::println("rewriting HFA %s -> as array", dty->toChars());
LLType *t = type(dty, nullptr);
LLType *t = type(dty);
return DtoLoad(DtoBitCast(dv->getRVal(), getPtrToType(t)));
}

LLType *type(Type *dty, LLType *) override {
assert(dty->ty == Tstruct);
LLValue *getLVal(Type *dty, LLValue *v) override {
Logger::println("rewriting array -> as HFA %s", dty->toChars());
return DtoAllocaDump(v, dty, ".HFAToArray_dump");
}

LLType *type(Type *t) override {
assert(t->ty == Tstruct);
LLType *floatArrayType = nullptr;
if (TargetABI::isHFA((TypeStruct *)dty, &floatArrayType, maxFloats))
if (TargetABI::isHFA((TypeStruct *)t, &floatArrayType, maxFloats))
return floatArrayType;
llvm_unreachable("Type dty should be an HFA");
llvm_unreachable("Type t should be an HFA");
}
};

/**
* Rewrite a composite as array of i64.
*/
struct CompositeToArray64 : ABIRewrite {
LLValue *get(Type *dty, LLValue *v) override {
Logger::println("rewriting i64 array -> as %s", dty->toChars());
LLValue *lval = DtoRawAlloca(v->getType(), 0);
DtoStore(v, lval);

LLType *pTy = getPtrToType(DtoType(dty));
return DtoLoad(DtoBitCast(lval, pTy), "get-result");
}

LLValue *put(DValue *dv) override {
Type *dty = dv->getType();
Logger::println("rewriting %s -> as i64 array", dty->toChars());
LLType *t = type(dty, nullptr);
LLType *t = type(dty);
return DtoLoad(DtoBitCast(dv->getRVal(), getPtrToType(t)));
}

LLType *type(Type *t, LLType *) override {
LLValue *getLVal(Type *dty, LLValue *v) override {
Logger::println("rewriting i64 array -> as %s", dty->toChars());
return DtoAllocaDump(v, dty, ".CompositeToArray64_dump");
}

LLType *type(Type *t) override {
// An i64 array that will hold Type 't'
size_t sz = (t->size() + 7) / 8;
return LLArrayType::get(LLIntegerType::get(gIR->context(), 64), sz);
Expand All @@ -301,23 +274,19 @@ struct CompositeToArray64 : ABIRewrite {
* Rewrite a composite as array of i32.
*/
struct CompositeToArray32 : ABIRewrite {
LLValue *get(Type *dty, LLValue *v) override {
Logger::println("rewriting i32 array -> as %s", dty->toChars());
LLValue *lval = DtoRawAlloca(v->getType(), 0);
DtoStore(v, lval);

LLType *pTy = getPtrToType(DtoType(dty));
return DtoLoad(DtoBitCast(lval, pTy), "get-result");
}

LLValue *put(DValue *dv) override {
Type *dty = dv->getType();
Logger::println("rewriting %s -> as i32 array", dty->toChars());
LLType *t = type(dty, nullptr);
LLType *t = type(dty);
return DtoLoad(DtoBitCast(dv->getRVal(), getPtrToType(t)));
}

LLType *type(Type *t, LLType *) override {
LLValue *getLVal(Type *dty, LLValue *v) override {
Logger::println("rewriting i32 array -> as %s", dty->toChars());
return DtoAllocaDump(v, dty, ".CompositeToArray32_dump");
}

LLType *type(Type *t) override {
// An i32 array that will hold Type 't'
size_t sz = (t->size() + 3) / 4;
return LLArrayType::get(LLIntegerType::get(gIR->context(), 32), sz);
Expand Down
4 changes: 2 additions & 2 deletions gen/abi-ppc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,13 @@ struct PPCTargetABI : TargetABI {
if (canRewriteAsInt(ty, Is64Bit)) {
if (!IntegerRewrite::isObsoleteFor(arg.ltype)) {
arg.rewrite = &integerRewrite;
arg.ltype = integerRewrite.type(arg.type, arg.ltype);
arg.ltype = integerRewrite.type(arg.type);
}
} else {
// these types are passed byval:
// the caller allocates a copy and then passes a pointer to the copy
arg.rewrite = &byvalRewrite;
arg.ltype = byvalRewrite.type(arg.type, arg.ltype);
arg.ltype = byvalRewrite.type(arg.type);

// the copy is treated as a local variable of the callee
// hence add the NoAlias and NoCapture attributes
Expand Down
12 changes: 6 additions & 6 deletions gen/abi-ppc64le.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,14 @@ struct PPC64LETargetABI : TargetABI {
if (retTy->ty == Tstruct &&
isHFA((TypeStruct *)retTy, &fty.ret->ltype, 8)) {
fty.ret->rewrite = &hfaToArray;
fty.ret->ltype = hfaToArray.type(fty.ret->type, fty.ret->ltype);
fty.ret->ltype = hfaToArray.type(fty.ret->type);
} else if (canRewriteAsInt(retTy, true)) {
fty.ret->rewrite = &integerRewrite;
fty.ret->ltype = integerRewrite.type(fty.ret->type, fty.ret->ltype);
fty.ret->ltype = integerRewrite.type(fty.ret->type);
} else {
fty.ret->rewrite = &compositeToArray64;
fty.ret->ltype =
compositeToArray64.type(fty.ret->type, fty.ret->ltype);
compositeToArray64.type(fty.ret->type);
}
} else if (retTy->isintegral())
fty.ret->attrs.add(retTy->isunsigned() ? LLAttribute::ZExt
Expand All @@ -90,13 +90,13 @@ struct PPC64LETargetABI : TargetABI {
if (ty->ty == Tstruct || ty->ty == Tsarray) {
if (ty->ty == Tstruct && isHFA((TypeStruct *)ty, &arg.ltype, 8)) {
arg.rewrite = &hfaToArray;
arg.ltype = hfaToArray.type(arg.type, arg.ltype);
arg.ltype = hfaToArray.type(arg.type);
} else if (canRewriteAsInt(ty, true)) {
arg.rewrite = &integerRewrite;
arg.ltype = integerRewrite.type(arg.type, arg.ltype);
arg.ltype = integerRewrite.type(arg.type);
} else {
arg.rewrite = &compositeToArray64;
arg.ltype = compositeToArray64.type(arg.type, arg.ltype);
arg.ltype = compositeToArray64.type(arg.type);
}
} else if (ty->isintegral())
arg.attrs.add(ty->isunsigned() ? LLAttribute::ZExt : LLAttribute::SExt);
Expand Down
2 changes: 1 addition & 1 deletion gen/abi-win64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ struct Win64TargetABI : TargetABI {

if (arg.rewrite) {
LLType *originalLType = arg.ltype;
arg.ltype = arg.rewrite->type(arg.type, arg.ltype);
arg.ltype = arg.rewrite->type(arg.type);

IF_LOG {
Logger::println("Rewriting argument type %s", t->toChars());
Expand Down
28 changes: 8 additions & 20 deletions gen/abi-x86-64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,16 +169,6 @@ struct RegCount {
* memory so that it's then readable as the other type (i.e., bit-casting).
*/
struct X86_64_C_struct_rewrite : ABIRewrite {
LLValue *get(Type *dty, LLValue *v) override {
LLValue *address = DtoAllocaDump(v, dty, ".X86_64_C_struct_rewrite_dump");
LLType *type = DtoType(dty);
return loadFromMemory(address, type, ".X86_64_C_struct_rewrite_getResult");
}

void getL(Type *dty, LLValue *v, LLValue *lval) override {
storeToMemory(v, lval);
}

LLValue *put(DValue *v) override {
LLValue *address = getAddressOf(v);

Expand All @@ -188,7 +178,11 @@ struct X86_64_C_struct_rewrite : ABIRewrite {
return loadFromMemory(address, abiTy, ".X86_64_C_struct_rewrite_putResult");
}

LLType *type(Type *dty, LLType *t) override { return getAbiType(dty); }
LLValue *getLVal(Type *dty, LLValue *v) override {
return DtoAllocaDump(v, dty, ".X86_64_C_struct_rewrite_dump");
}

LLType *type(Type *t) override { return getAbiType(t); }
};

/**
Expand All @@ -200,17 +194,11 @@ struct X86_64_C_struct_rewrite : ABIRewrite {
* the ByVal LLVM attribute.
*/
struct ImplicitByvalRewrite : ABIRewrite {
LLValue *get(Type *dty, LLValue *v) override {
return DtoLoad(v, ".ImplicitByvalRewrite_getResult");
}

void getL(Type *dty, LLValue *v, LLValue *lval) override {
DtoMemCpy(lval, v);
}

LLValue *put(DValue *v) override { return getAddressOf(v); }

LLType *type(Type *dty, LLType *t) override { return DtoPtrToType(dty); }
LLValue *getLVal(Type *dty, LLValue *v) override { return v; }

LLType *type(Type *t) override { return DtoPtrToType(t); }
};

struct X86_64TargetABI : TargetABI {
Expand Down
4 changes: 2 additions & 2 deletions gen/abi-x86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ struct X86TargetABI : TargetABI {
!(externD && rt->ty == Tcomplex32) &&
!integerRewrite.isObsoleteFor(fty.ret->ltype)) {
fty.ret->rewrite = &integerRewrite;
fty.ret->ltype = integerRewrite.type(fty.ret->type, fty.ret->ltype);
fty.ret->ltype = integerRewrite.type(fty.ret->type);
}
}

Expand Down Expand Up @@ -166,7 +166,7 @@ struct X86TargetABI : TargetABI {
// rewrite aggregates as integers to make inreg work
if (lastTy->ty == Tstruct || lastTy->ty == Tsarray) {
last->rewrite = &integerRewrite;
last->ltype = integerRewrite.type(last->type, last->ltype);
last->ltype = integerRewrite.type(last->type);
// undo byval semantics applied via passByVal() returning true
last->byref = false;
last->attrs.clear();
Expand Down
Loading