On Mon, 7 Jan 2013, Steven Bosscher wrote:

> Hello,
> 
> Consider this test case:
> 
> ---------------------- 8< ----------------
> int a;
> __attribute__((__noinline__,__noclone__,__pure__))
> int use (int b)
> {
>   return b * 2 + 4 + a;
> }
> 
> int foo (int b, int c, int d)
> {
>   int res, r = 0;
>   res = use (b);
>   if (c)
>     r = res;
>   return r;
> }
> ---------------------- 8< ----------------
> 
> I would expect the "res = use(b)" statement to be sinkable, but this
> doesn't happen. There are strange VOPs on the return statements, even
> though they return a GIMPLE register, AFAICT:
> 
> use (int b)
> {
>   int a.0;
>   int _2;
>   int _3;
>   int _6;
>   <bb 2>:
>   _2 = b_1(D) + 2;
>   _3 = _2 * 2;
>   # VUSE <.MEM_4(D)>
>   a.0_5 = a;
>   _6 = _3 + a.0_5;
>   # VUSE <.MEM_4(D)>
>   return _6;
> }
> 
> foo (int b, int c, int d)
> {
>   int r;
>   <bb 2>:
>   # VUSE <.MEM_2(D)>
>   r_4 = use (b_3(D));

The issue is the VUSE here - it's a "load" (reads global memory)
and thus we do not consider sinking it.

>   if (c_5(D) != 0)
>     goto <bb 3>;
>   else
>     goto <bb 5>;
>   <bb 5>:
>   goto <bb 4>;
>   <bb 3>:
>   <bb 4>:
>   # r_1 = PHI <0(5), r_4(3)>
>   # VUSE <.MEM_2(D)>
>   return r_1;
> }
> 
> Why are those VUSEs there?

They are there to properly represent the fact that stores to
global memory are kept live by the return stmt.  This enables
more sinking of stores (heh) and facilitates memory analysis
that looks for things used by function exit points (simply
walk the VUSE -> VDEF chain).

Richard.

Reply via email to