Say I have the following code:
main.c:
void foo(char *, ...);
void bar(int, ...);
int main(void)
{
foo("foo", 1);
bar(1, 2, 3, "bar");
return 0;
}
foobar.c:
int printf(const char *, ...);
void foo(const char *str, int i)
{
printf("%s: %d\n", str, i);
}
void bar(int i, int j, int k, const char *str)
{
printf("%s sum: %d\n", str, i+j+k);
}
When I compile these separately and run llvm-ld -disable-opt I get this
unfortunate sequence:
define i32 @main() nounwind {
entry:
%retval = alloca i32 ; <i32*> [#uses=2]
%0 = alloca i32 ; <i32*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32>
[#uses=0]
call void (i8*, ...)* bitcast (void (i8*, i32)* @foo to void (i8*, ...)*)
(i8* getelementptr inbounds ([4 x i8]* @.str, i64 0, i64 0), i32 1) nounwind
call void (i32, ...)* bitcast (void (i32, i32, i32, i8*)* @bar to void
(i32, ...)*)(i32 1, i32 2, i32 3, i8* getelementptr inbounds ([4 x i8]*
@.str1, i64 0, i64 0)) nounwind
It's unfortunate because the bitcast gets in the way. For example, looking
at the ValueMap in the linker one would expect a Function to map to a
Function. That's not true here. A Function maps to a bitcast. It also
means the generated code will be suboptimal on targets like x86-64 that
require extra processing for vararg calls.
This happens because RecursiveResolveTypes in LinkModules.cpp doesn't
understand that a "more fully specified" function argument list is
compatible
with a "less fully specified" one and that it should be perfectly fine
to
resolve the type to the more specified one.
Would it break things horribly if I went in and taught RecursiveResolveTypes
how to handle this or would that violate some deep-level assumption?
-Dave
On Oct 5, 2009, at 3:14 PM, David Greene wrote:> When I compile these separately and run llvm-ld -disable-opt I get > this > unfortunate sequence: > > define i32 @main() nounwind { > entry: > %retval = alloca i32 ; <i32*> [#uses=2] > %0 = alloca i32 ; <i32*> [#uses=2] > %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] > call void (i8*, ...)* bitcast (void (i8*, i32)* @foo to void > (i8*, ...)*) > (i8* getelementptr inbounds ([4 x i8]* @.str, i64 0, i64 0), i32 1) > nounwind > call void (i32, ...)* bitcast (void (i32, i32, i32, i8*)* @bar to > void > (i32, ...)*)(i32 1, i32 2, i32 3, i8* getelementptr inbounds ([4 x > i8]* > @.str1, i64 0, i64 0)) nounwind > > It's unfortunate because the bitcast gets in the way. For example, > looking > at the ValueMap in the linker one would expect a Function to map to a > Function. That's not true here. A Function maps to a bitcast. It > also > means the generated code will be suboptimal on targets like x86-64 > that > require extra processing for vararg calls.Yep, it's pretty ugly.> This happens because RecursiveResolveTypes in LinkModules.cpp doesn't > understand that a "more fully specified" function argument list is > compatible > with a "less fully specified" one and that it should be perfectly > fine to > resolve the type to the more specified one. > > Would it break things horribly if I went in and taught > RecursiveResolveTypes > how to handle this or would that violate some deep-level assumption?This is intentional, but instcombine should clean it up. Are you not seeing this? If not, instcombine should be improved. -Chris
On Monday 05 October 2009 17:21, Chris Lattner wrote:> > Would it break things horribly if I went in and taught > > RecursiveResolveTypes > > how to handle this or would that violate some deep-level assumption? > > This is intentional, but instcombine should clean it up. Are you not > seeing this? If not, instcombine should be improved.The problem is I need to examine this before instcombine and do various nefarious things like spitting out IR and/or generating code without any modifications to improve debuggability of our compiler. Why is this intentional? I've coded up the necessary linker changes but the build is waiting on NFS and a tape drive. Grr... -Dave