On Mon, Oct 19, 2020 at 7:52 PM Gary Oblock <g...@amperecomputing.com> wrote:
>
> Richard,
>
> I guess that will work for me. However, since it
> was decided to remove an identical function,
> why weren't the calls to it adjusted to reflect it?
> If the call wasn't transformed that means it will
> be mapped at some later time. Is that mapping
> available to look at? Because using that would
> also be a potential solution (assuming call
> graph information exists for the deleted function.)

I'm not sure how the transitional cgraph looks like
during WPA analysis (which is what we're talking about?),
but definitely the IL is unmodified in that state.

Maybe Martin has an idea.

Richard.

> Gary
>
>
>
> ________________________________
> From: Richard Biener <richard.guent...@gmail.com>
> Sent: Sunday, October 18, 2020 11:28 PM
> To: Gary Oblock <g...@amperecomputing.com>
> Cc: gcc@gcc.gnu.org <gcc@gcc.gnu.org>
> Subject: Re: Where did my function go?
>
> [EXTERNAL EMAIL NOTICE: This email originated from an external sender. Please 
> be mindful of safe email handling and proprietary information protection 
> practices.]
>
>
> On Fri, Oct 16, 2020 at 9:59 PM Gary Oblock via Gcc <gcc@gcc.gnu.org> wrote:
> >
> > I have a tiny program composed of a few functions
> > and one of those functions (setupB) has gone missing.
> > Since I need to walk its GIMPLE, this is a problem.
> >
> > The program:
> >
> > -- aux.h -----------------------------------------
> > #include "stdlib.h"
> > typedef struct A A_t;
> > typedef struct A B_t;
> > struct A {
> >   int i;
> >   double x;
> > };
> >
> > #define MAX(x,y) ((x)>(y) ? (x) : (y))
> >
> > extern int max1( A_t *, size_t);
> > extern double max2( B_t *, size_t);
> > extern A_t *setupA( size_t);
> > extern B_t *setupB( size_t);
> > -- aux.c ----------------------------------------
> > #include "aux.h"
> > #include "stdlib.h"
> >
> > A_t *
> > setupA( size_t size)
> > {
> >   A_t *data = (A_t *)malloc( size * sizeof(A_t));
> >   size_t i;
> >   for( i = 0; i < size; i++ ) {
> >     data[i].i = rand();
> >     data[i].x = drand48();
> >   }
> >   return data;
> > }
> >
> > B_t *
> > setupB( size_t size)
> > {
> >   B_t *data = (B_t *)malloc( size * sizeof(B_t));
> >   size_t i;
> >   for( i = 0; i < size; i++ ) {
> >     data[i].i = rand();
> >     data[i].x = drand48();
> >   }
> >   return data;
> > }
> >
> > int
> > max1( A_t *array, size_t len)
> > {
> >   size_t i;
> >   int result = array[0].i;
> >   for( i = 1; i < len; i++  ) {
> >     result = MAX( array[i].i, result);
> >   }
> >   return result;
> > }
> >
> > double
> > max2( B_t *array, size_t len)
> > {
> >   size_t i;
> >   double result = array[0].x;
> >   for( i = 1; i < len; i++  ) {
> >     result = MAX( array[i].x, result);
> >   }
> >   return result;
> > }
> > -- main.c -------------------------------------
> > #include "stdio.h"
> >
> > A_t *data1;
> >
> > int
> > main(void)
> > {
> >   B_t *data2 = setupB(200);
> >   data1 = setupA(100);
> >
> >   printf("First %d\n" , max1(data1,100));
> >   printf("Second %e\n", max2(data2,200));
> > }
> > ------------------------------------------------
> >
> > Here is its GIMPLE dump:
> > (for the sole purpose of letting you see
> > with your own eyes that setupB is indeed missing)
> > ------------------------------------------------
> > Program:
> >   static struct A_t * data1;
> > struct A_t * <T623> (size_t)
> >
> > ;; Function setupA (setupA, funcdef_no=4, decl_uid=4398, cgraph_uid=6, 
> > symbol_order=48) (executed once)
> >
> > setupA (size_t size)
> > {
> >   size_t i;
> >   struct A_t * data;
> >
> >   <bb 2> [local count: 118111600]:
> >   _1 = size_8(D) * 16;
> >   data_11 = malloc (_1);
> >   goto <bb 4>; [100.00%]
> >
> >   <bb 3> [local count: 955630225]:
> >   _2 = i_6 * 16;
> >   _3 = data_11 + _2;
> >   _4 = rand ();
> >   _3->i = _4;
> >   _5 = drand48 ();
> >   _3->x = _5;
> >   i_16 = i_6 + 1;
> >
> >   <bb 4> [local count: 1073741824]:
> >   # i_6 = PHI <0(2), i_16(3)>
> >   if (i_6 < size_8(D))
> >     goto <bb 3>; [89.00%]
> >   else
> >     goto <bb 5>; [11.00%]
> >
> >   <bb 5> [local count: 118111600]:
> >   return data_11;
> >
> > }
> >
> >
> > int <T622> (struct A_t *)
> >
> > ;; Function max1.constprop (max1.constprop.0, funcdef_no=1, decl_uid=4397, 
> > cgraph_uid=5, symbol_order=58) (executed once)
> >
> > max1.constprop (struct A_t * array)
> > {
> >   size_t i;
> >   int result;
> >   size_t len;
> >
> >   <bb 6> [local count: 118111600]:
> >
> >   <bb 2> [local count: 118111600]:
> >   result_2 = array_1(D)->i;
> >   goto <bb 4>; [100.00%]
> >
> >   <bb 3> [local count: 955630225]:
> >   _4 = i_3 * 16;
> >   _5 = array_1(D) + _4;
> >   _6 = _5->i;
> >   result_8 = MAX_EXPR <_6, result_7>;
> >   i_9 = i_3 + 1;
> >
> >   <bb 4> [local count: 1073741824]:
> >   # i_3 = PHI <1(2), i_9(3)>
> >   # result_7 = PHI <result_2(2), result_8(3)>
> >   if (i_3 <= 99)
> >     goto <bb 3>; [89.00%]
> >   else
> >     goto <bb 5>; [11.00%]
> >
> >   <bb 5> [local count: 118111600]:
> >   # result_10 = PHI <result_7(4)>
> >   return result_10;
> >
> > }
> >
> >
> > double <T61e> (struct B_t *)
> >
> > ;; Function max2.constprop (max2.constprop.0, funcdef_no=3, decl_uid=4395, 
> > cgraph_uid=3, symbol_order=59) (executed once)
> >
> > max2.constprop (struct B_t * array)
> > {
> >   size_t i;
> >   double result;
> >   size_t len;
> >
> >   <bb 8> [local count: 118111600]:
> >
> >   <bb 2> [local count: 118111600]:
> >   result_2 = array_1(D)->x;
> >   goto <bb 6>; [100.00%]
> >
> >   <bb 3> [local count: 955630225]:
> >   _4 = i_3 * 16;
> >   _5 = array_1(D) + _4;
> >   _6 = _5->x;
> >   if (_6 > result_7)
> >     goto <bb 4>; [50.00%]
> >   else
> >     goto <bb 5>; [50.00%]
> >
> >   <bb 4> [local count: 477815112]:
> >
> >   <bb 5> [local count: 955630225]:
> >   # _10 = PHI <result_7(3), _6(4)>
> >   i_8 = i_3 + 1;
> >
> >   <bb 6> [local count: 1073741824]:
> >   # i_3 = PHI <1(2), i_8(5)>
> >   # result_7 = PHI <result_2(2), _10(5)>
> >   if (i_3 <= 199)
> >     goto <bb 3>; [89.00%]
> >   else
> >     goto <bb 7>; [11.00%]
> >
> >   <bb 7> [local count: 118111600]:
> >   # result_9 = PHI <result_7(6)>
> >   return result_9;
> >
> > }
> >
> >
> > int <T619> (void)
> >
> > ;; Function main (main, funcdef_no=5, decl_uid=4392, cgraph_uid=1, 
> > symbol_order=25) (executed once)
> >
> > main ()
> > {
> >   struct B_t * data2;
> >
> >   <bb 2> [local count: 1073741824]:
> >   data2_6 = setupB (200);
> >   _1 = setupA (100);
> >   data1 = _1;
> >   _2 = max1 (_1, 100);
> >   printf ("First %d\n", _2);
> >   _3 = max2 (data2_6, 200);
> >   printf ("Second %e\n", _3);
> >   return 0;
> >
> > }
> > ------------------------------------------------
> > The pass is invoked at this location in passes.def
> >
> >   /* Simple IPA passes executed after the regular passes.  In WHOPR mode the
> >      passes are executed after partitioning and thus see just parts of the
> >      compiled unit.  */
> >   INSERT_PASSES_AFTER (all_late_ipa_passes)
> >   NEXT_PASS (pass_materialize_all_clones);
> >   NEXT_PASS (pass_ipa_type_escape_analysis);
> >   NEXT_PASS (pass_ipa_structure_reorg); <========== my pass!
> >   NEXT_PASS (pass_ipa_prototype);
> >   NEXT_PASS (pass_ipa_pta);
> >   NEXT_PASS (pass_omp_simd_clone);
> >   TERMINATE_PASS_LIST (all_late_ipa_passes)
> >
> > --------------------------------------------------------------------------
> > The program was compiled with these options:
> >
> > export OPTIONS='-O2 -fdump-passes -flto -flto-partition=one 
> > -fipa-instance-interleave -fdump-ipa-all-details -save-temps -v'
> >
> > By the way, changing -flto-partition=one to -flto-partition=none
> > makes no difference.
> >
> > ---------------------------------------------------------------------------
> > Here is how the dump was done:
> >
> > void
> > print_program ( FILE *file, bool my_format, int leading_space, Info_t *info)
> > {
> >   struct cgraph_node *node;
> >   fprintf ( file, "%*sProgram:\n", leading_space, "");
> >
> >   // Print Global Decls
> >   //
> >   varpool_node *var;
> >   FOR_EACH_VARIABLE ( var)
> >   {
> >     tree decl = var->decl;
> >     fprintf ( file, "%*s", leading_space, "");
> >     flexible_print ( file, decl, 1, (dump_flags_t)0);
> >   }
> >
> >   FOR_EACH_FUNCTION_WITH_GIMPLE_BODY ( node)
> >   {
> >     struct function *func = DECL_STRUCT_FUNCTION ( node->decl);
> >     flexible_print ( file, TREE_TYPE( func->decl), 1, (dump_flags_t)0);
> >     dump_function_header ( file, func->decl, (dump_flags_t)0);
> >     dump_function_to_file ( func->decl, file, (dump_flags_t)0);
> >   }
> > }
> >
> > Note, flexible_print is a wrapper that calls either print_generic_decl
> > or print_generic_expr depending on whether or not it's a decl. The "1"
> > just causes a "\n" to be emmited...
> >
> > I also should mention I spin through the following loop at the
> > start of my pass to make sure the functions are sane:
> >
> >   cgraph_node* node;
> >   FOR_EACH_FUNCTION_WITH_GIMPLE_BODY ( node)
> >     node->get_untransformed_body ();
> >
> > I don't think I left out any pertinent details.
> >
> > Any suggestions (other than don't use lto this way)
> > are welcome.
>
> Try -fno-ipa-icf - it looks like setupA and setupB are
> identical.  You'll see adjusted calls only after IPA
> transform.
>
> Richard.
>
> > Thanks,
> >
> > Gary
> >
> >
> >
> >
> > CONFIDENTIALITY NOTICE: This e-mail message, including any attachments, is 
> > for the sole use of the intended recipient(s) and contains information that 
> > is confidential and proprietary to Ampere Computing or its subsidiaries. It 
> > is to be used solely for the purpose of furthering the parties' business 
> > relationship. Any unauthorized review, copying, or distribution of this 
> > email (or any attachments thereto) is strictly prohibited. If you are not 
> > the intended recipient, please contact the sender immediately and 
> > permanently delete the original and any copies of this email and any 
> > attachments thereto.

Reply via email to