Permalink
Browse files

Fix #113 - promotion of small static array arguments to registers.

  • Loading branch information...
1 parent ba9fb72 commit 62bfda0259f9bfc5c9b91c74b0d7aa3acacb50f3 @klickverbot klickverbot committed Jun 6, 2012
Showing with 33 additions and 49 deletions.
  1. +22 −18 gen/abi-generic.h
  2. +6 −20 gen/abi-x86-64.cpp
  3. +5 −11 gen/abi-x86.cpp
View
@@ -55,41 +55,45 @@ struct X87_complex_swap : ABIRewrite
//////////////////////////////////////////////////////////////////////////////
-// FIXME: try into eliminating the alloca or if at least check
-// if it gets optimized away
-
-// convert byval struct
-// when
-struct X86_struct_to_register : ABIRewrite
+/**
+ * Rewrites a composite type parameter to an integer of the same size.
+ *
+ * This is needed in order to be able to use LLVM's inreg attribute to put
+ * struct and static array parameters into registers, because the attribute has
+ * slightly different semantics. For example, LLVM would store a [4 x i8] inreg
+ * in four registers (zero-extended), instead of a single 32bit one.
+ *
+ * The LLVM value in dv is expected to be a pointer to the parameter, as
+ * generated when lowering struct/static array paramters to LLVM byval.
+ */
+struct CompositeToInt : ABIRewrite
{
- // int -> struct
LLValue* get(Type* dty, DValue* dv)
{
- Logger::println("rewriting int -> struct");
- LLValue* mem = DtoAlloca(dty, ".int_to_struct");
+ Logger::println("rewriting integer -> %s", dty->toChars());
+ LLValue* mem = DtoAlloca(dty, ".int_to_composite");
LLValue* v = dv->getRVal();
DtoStore(v, DtoBitCast(mem, getPtrToType(v->getType())));
return DtoLoad(mem);
}
- // int -> struct (with dst lvalue given)
+
void getL(Type* dty, DValue* dv, llvm::Value* lval)
{
- Logger::println("rewriting int -> struct");
+ Logger::println("rewriting integer -> %s", dty->toChars());
LLValue* v = dv->getRVal();
DtoStore(v, DtoBitCast(lval, getPtrToType(v->getType())));
}
- // struct -> int
+
LLValue* put(Type* dty, DValue* dv)
{
- Logger::println("rewriting struct -> int");
- assert(dv->isLVal());
- LLValue* mem = dv->getLVal();
- LLType* t = LLIntegerType::get(gIR->context(), dty->size()*8);
- return DtoLoad(DtoBitCast(mem, getPtrToType(t)));
+ Logger::println("rewriting %s -> integer", dty->toChars());
+ LLType* t = LLIntegerType::get(gIR->context(), dty->size() * 8);
+ return DtoLoad(DtoBitCast(dv->getRVal(), getPtrToType(t)));
}
+
LLType* type(Type* t, LLType*)
{
- size_t sz = t->size()*8;
+ size_t sz = t->size() * 8;
return LLIntegerType::get(gIR->context(), sz);
}
};
View
@@ -348,7 +348,7 @@ struct RegCount {
struct X86_64TargetABI : TargetABI {
X86_64_C_struct_rewrite struct_rewrite;
X87_complex_swap swapComplex;
- X86_struct_to_register structToReg;
+ CompositeToInt compositeToInt;
void newFunctionType(TypeFunction* tf) {
funcTypeStack.push_back(FuncTypeData(tf->linkage));
@@ -587,25 +587,11 @@ void X86_64TargetABI::rewriteFunctionType(TypeFunction* tf) {
else if ((ty->ty == Tstruct || ty->ty == Tsarray) &&
(sz == 1 || sz == 2 || sz == 4 || sz == 8))
{
- if (ty->ty == Tstruct)
- {
- Logger::println("Putting struct in register");
- arg.rewrite = &structToReg;
- arg.ltype = structToReg.type(arg.type, arg.ltype);
- arg.byref = false;
- // erase previous attributes
- arg.attrs = 0;
- }
- else
- {
- Logger::println("Putting static array in register");
- // need to make sure type is not pointer
- arg.ltype = DtoType(arg.type);
- arg.byref = false;
- // erase previous attributes
- arg.attrs = 0;
- }
- arg.attrs |= llvm::Attribute::InReg;
+ Logger::println("Putting struct/sarray in register");
+ arg.rewrite = &compositeToInt;
+ arg.ltype = compositeToInt.type(arg.type, arg.ltype);
+ arg.byref = false;
+ arg.attrs = llvm::Attribute::InReg;
--regcount;
}
}
View
@@ -69,7 +69,7 @@ struct X86TargetABI : TargetABI
{
X87_complex_swap swapComplex;
X86_cfloat_rewrite cfloatToInt;
- X86_struct_to_register structToReg;
+ CompositeToInt compositeToInt;
bool returnInArg(TypeFunction* tf)
{
@@ -150,19 +150,13 @@ struct X86TargetABI : TargetABI
else if (!lastTy->isfloating() && (sz == 1 || sz == 2 || sz == 4)) // right?
{
// rewrite the struct into an integer to make inreg work
- if (lastTy->ty == Tstruct)
+ if (lastTy->ty == Tstruct || lastTy->ty == Tsarray)
{
- last->rewrite = &structToReg;
- last->ltype = structToReg.type(last->type, last->ltype);
+ last->rewrite = &compositeToInt;
+ last->ltype = compositeToInt.type(last->type, last->ltype);
last->byref = false;
// erase previous attributes
- last->attrs = 0;
- }
- else if (lastTy->ty == Tsarray)
- {
- last->ltype = DtoType(last->type);
- last->byref = false;
- last->attrs &= ~llvm::Attribute::ByVal;
+ last->attrs = llvm::Attribute::None;
}
last->attrs |= llvm::Attribute::InReg;
}

0 comments on commit 62bfda0

Please sign in to comment.