Hi Duncan,
> Message: 15
> Date: Thu, 18 Jun 2009 10:58:47 +0200
> From: Duncan Sands <baldrick at free.fr>
> Subject: Re: [LLVMdev] Query on optimizing away function calls.
> To: LLVM Developers Mailing List <llvmdev at cs.uiuc.edu>
> Message-ID: <4A3A01C7.8020707 at free.fr>
> Content-Type: text/plain; charset=ISO-8859-1; format=flowed
>
> Hi,
>
> > Consider the following code:
> >
> > ------------
> > define void @func() {
> > %a = alloca i32
> > store i32 42, i32* %a
> > call void @func2(i32* %a) nounwind
> > ret void
> > }
> >
> > define void @func2(i32* %a) nounwind {
> > store i32 43, i32* %a
> > ret void
> > }
> > ------------
> >
> > It is possible to optimize this to:
> >
> > ------------
> > define void @func() {
> > ret void
> > }
> >
> > define void @func2(i32* %a) nounwind {
> > store i32 43, i32* %a
> > ret void
> > }
> > ------------
> >
> > which is just what I want. However, if @func2 is implemented in an
external C
> > library, is this not possible? Specifically, while optimizing:
> >
> > ------------
> > define void @func() {
> > %a = alloca i32
> > store i32 42, i32* %a
> > call void @func2(i32* %a) nounwind
> > ret void
> > }
> >
> > declare void @func2(i32* %a) nounwind
> > ------------
> >
> > is there some way to specify that @func2 only modifies values
accessible via %a,
> > so that if all those values are ultimately discarded then the call to
@func2
> > itself can be discarded?
>
> no, there is currently no way. There was some discussion of adding
> attributes for this, but I think the conclusion was that there were
> too many hairy details for not enough gain.
>
> > The "readonly" function attribute looks to be too strict for
this.
>
> It is possible to put "readonly" on the call, rather than on
func2
> itself. So if your front-end somehow knows that this use of func2
> has no real effect it could mark the call this way.
Here's where this question comes from, may be this use case inspires
someone :-). I've a "big.int", that should behave like an i32. The
big.int routines are provided by a C runtime. To illustrate:
----------------------
; int func(int a, int b) { int c = a; return b; }
; using a regular int
define i32 @func1(i32 %a, i32 %b) {
%cp = alloca i32
store i32 %a, i32* %cp
ret i32 %b
}
%big.int = type { i32, i32, i32* }
; using this big.int
define %big.int* @func2(%big.int* %a, %big.int* %b) {
%cp = alloca %big.int
call void @big.int.copy.ctor(%big.int* %cp, %big.int* %b) nounwind
call void @big.int.dtor(%big.int* %cp) nounwind
ret %big.int* %b
}
declare void @big.int.copy.ctor(%big.int*, %big.int*) nounwind
declare void @big.int.dtor(%big.int*) nounwind
----------------------
LLVM being able to optimize away the unnecessary temp object would be a
big win here.
The only way for my frontend to know that the temp is unnecessary is to
track values using use-defs, and well, you know, implement that function
attribute :-). The frontend would now need passes, pass managers..
Another, more elegant way would be to somehow be able to plugin a type,
like i32, at runtime, into LLVM, so that the front end can say naughty things
like:
----------------------
; using a big int, and magic!
define %ext.big.int @func1(%ext.big.int %a, %ext.big.int %b) {
%cp = alloca %ext.big.int
store %ext.big.int %a, %ext.big.int* %cp
ret %ext.big.int %b
}
----------------------
And maybe have a final pass take care of expanding those things into
big.int.* calls. Something of that sort.
>From what I've experimented so far, looks like if a language were to use
exclusively a big.int instead of say i32, the effectiveness of LLVM's
optimizations are low (please correct me if I'm wrong). (My real-life big
int is naturally a wrapper over GMP, which means it can't be
"written" in
LLVM. Writing *everything* in LLVM would solve *everything*, of course :-)
My apologies if I haven't done enough homework, any pointers are
appreciated.
Thanks & Regards,
-Mahadevan.
>
> > Or am I missing something obvious?
>
> Nope.
>
> Ciao,
>
> Duncan.
>