On 4 July 2016 at 15:17, Richard Biener <richard.guent...@gmail.com> wrote:
> On Sun, Jul 3, 2016 at 9:34 AM, Prasad Ghangal <prasad.ghan...@gmail.com> 
> wrote:
>> In this patch, I am passing labels and vars with internal function and
>> handling them in tree-cfg for parsing PHI.
>> For first label, label_to_block() gives correct basic block and I am
>> getting proper edges but for other labels the function is giving NULL.
>>
>> test-case :
>>
>> void __GIMPLE () foo()
>> {
>>   int a;
>>   int a_2;
>>   int a_3;
>>   int a_1;
>>
>> bb_2:
>>   a_2 = 3;
>>   goto bb_4;
>>
>> bb_3:
>>   a_3 = 6;
>>   goto bb_4;
>>
>> bb_4:
>>   a_1 = __PHI (bb_2: a_2, bb_3: a_3);
>>   a_1 = a_1 + 1;
>>   return;
>> }
>>
>
> The issue is probably you lower PHIs after cleanup_tree_cfg is run which may
> end up removing labels.  Or it is cleanup_dead_labels in build_gimple_cfg.

Yes, that was due to cleanup_dead_label. It is working after calling
lower_phi_internal_fn just after make_edges

So test case like:

void __GIMPLE () foo()
{
  int a;
  int a_2;
  int a_3;
  int a_1;
  int a_0;

bb_2:
  if (a > 4)
    goto bb_3;
  else
    goto bb_4;

bb_3:
  a_2 = 6;
  goto bb_5;

bb_4:
  a_3 = 99;
  goto bb_5;

bb_5:
  a_1 = __PHI (bb_3: a_2, bb_4: a_3);
  a_0 = a_1 + 1;
  return;
}

produces ssa dump as

;; Function foo (foo, funcdef_no=0, decl_uid=1744, cgraph_uid=0, symbol_order=0)

foo ()
{
  int a_0;
  int a_1;
  int a_3;
  int a_2;
  int a;

bb_2:
  if (a_2(D) > 4)
    goto <bb 3> (bb_3);
  else
    goto <bb 4> (bb_4);

bb_3:
  a_2_3 = 6;
  goto <bb 5> (bb_5);

bb_4:
  a_3_5 = 99;

  # a_1_1 = PHI <a_1_4(D)(3), a_1_4(D)(4)>
bb_5:
  a_0_6 = a_1_1 + 1;
  return;

}


and test case like :

void __GIMPLE () foo()
{
  int a;
  int a_2;
  int a_3;
  int a_1;
  int a_0;

bb_3:
  a_2 = 6;
  goto bb_5;

bb_4:
  a_3 = 99;
  goto bb_5;

bb_5:
  a_1 = __PHI (bb_3: a_2, bb_4: a_3);
  a_0 = a_1 + 1;
  return;
}

gets its block with bb_4 label removed as it is unreachable and
produces ssa dump as -

;; Function foo (foo, funcdef_no=0, decl_uid=1744, cgraph_uid=0, symbol_order=0)

foo ()
{
  int a_0;
  int a_1;
  int a_3;
  int a_2;
  int a;

bb_3:
  a_2_2 = 6;

  # a_1_1 = PHI <a_1_3(D)(2)>
bb_5:
  a_0_4 = a_1_1 + 1;
  return;

}

I think which is fine(?).

Now ssa pass is producing ssa names for the vars because it expects
them with tree code SSA_NAME. How can we prevent this? Can we convert
VAR_DECL to SSA_NAME ?

>
> Richard.
>
>>
>>
>>
>> On 1 July 2016 at 17:33, Richard Biener <richard.guent...@gmail.com> wrote:
>>> On Fri, Jul 1, 2016 at 1:57 PM, Prasad Ghangal <prasad.ghan...@gmail.com> 
>>> wrote:
>>>> On 29 June 2016 at 12:42, Richard Biener <richard.guent...@gmail.com> 
>>>> wrote:
>>>>> On Tue, Jun 28, 2016 at 4:16 PM, Prasad Ghangal
>>>>> <prasad.ghan...@gmail.com> wrote:
>>>>>> Hi,
>>>>>>
>>>>>> For handling PHI, it expects cfg to be built before. So I was
>>>>>> wondering how are we going to handle this? Do we need to build cfg
>>>>>> while parsing only?
>>>>>
>>>>> For handling PHIs we need to have a CFG in the sense that the GIMPLE PHI
>>>>> data structures are built in a way to have the PHI argument index 
>>>>> correspond
>>>>> to CFG predecessor edge index.  As we'd like to parse phis with args
>>>>> corresponding
>>>>> to predecessor block labels, like
>>>>>
>>>>> a:
>>>>>   i_1 = 1;
>>>>>   goto p;
>>>>>
>>>>> b:
>>>>>   i_2 = 2;
>>>>>   goto p;
>>>>>
>>>>> p:
>>>>>   i_3 = __PHI (a: i_1, b: i_2);
>>>>>
>>>>> I think that a possibility is to leave those PHIs as internal function
>>>>> with label / arg
>>>>> pairs and have CFG construction lower them to real PHIs.
>>>>>
>>>>> Of course the parser could as well build a CFG on its own but I think
>>>>> we should use
>>>>> the easy way out for now.
>>>>>
>>>>> Thus you'd have to modify CFG construction a bit to lower the internal
>>>>> function calls.
>>>>
>>>> Currently I am just building internal call using
>>>> gimple_build_call_internal_vec (), and detecting (and removing for
>>>> now) it after edge creation in tree-cfg. I was observing
>>>> internal-fn.def, do I need to make entry in internal-fn.def and write
>>>> expand function?
>>>
>>> You should add an entry and a stub expand function (like those
>>> others that simply have gcc_unreachable in them).
>>>
>>> Richard.
>>>
>>>>>
>>>>> Richard.
>>>>>>
>>>>>>
>>>>>>
>>>>>> Thanks,
>>>>>> Prasad
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index f2e62ca..138ca4f 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -512,6 +512,7 @@ const struct c_common_resword c_common_reswords[] =
   { "__volatile",      RID_VOLATILE,   0 },
   { "__volatile__",    RID_VOLATILE,   0 },
   { "__GIMPLE",                RID_GIMPLE,     D_CONLY },
+  { "__PHI",           RID_PHI,        D_CONLY},
   { "alignas",         RID_ALIGNAS,    D_CXXONLY | D_CXX11 | D_CXXWARN },
   { "alignof",         RID_ALIGNOF,    D_CXXONLY | D_CXX11 | D_CXXWARN },
   { "asm",             RID_ASM,        D_ASM },
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 23a401d..ede3549 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -107,6 +107,9 @@ enum rid
   /* "__GIMPLE", for the GIMPLE-parsing extension to the C frontend. */
   RID_GIMPLE,
 
+  /* "__PHI", for parsing PHI function in GIMPLE FE */
+  RID_PHI,
+
   /* C11 */
   RID_ALIGNAS, RID_GENERIC,
 
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index d62b8e8..00e0bc5 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -18345,6 +18345,57 @@ c_parser_gimple_expression (c_parser *parser, 
gimple_seq *seq)
       return;
     }
 
+  if (c_parser_next_token_is_keyword (parser, RID_PHI))
+    {
+      c_parser_consume_token (parser);
+      
+      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+       {
+         return;
+       }
+
+      gcall *call_stmt;
+      /* Gimplify internal functions. */
+      tree arg;
+      vec<tree> vargs = vNULL;
+
+      if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+       c_parser_consume_token (parser);
+      
+      while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+       {
+         if (c_parser_next_token_is (parser, CPP_NAME) &&
+             c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+           {
+             arg = lookup_label_for_goto (c_parser_peek_token 
(parser)->location, 
+                                          c_parser_peek_token (parser)->value);
+             c_parser_consume_token (parser);
+
+             if (c_parser_next_token_is (parser, CPP_COLON))
+               c_parser_consume_token (parser);
+             vargs.safe_push (arg);
+           }
+         else if (c_parser_next_token_is (parser, CPP_COMMA))
+           {
+             c_parser_consume_token (parser);
+           }
+         else
+           {
+             arg = c_parser_gimple_unary_expression (parser).value;
+             vargs.safe_push (arg);
+           }
+       }
+
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                "expected %<)%>");
+
+      call_stmt = gimple_build_call_internal_vec (IFN_PHI, vargs);
+      gimple_call_set_lhs (call_stmt, lhs.value);
+      gimple_set_location (call_stmt, UNKNOWN_LOCATION);
+      gimple_seq_add_stmt (seq, call_stmt);
+      return;
+    }
+
   exp_location = c_parser_peek_token (parser)->location;
   rhs = c_parser_gimple_binary_expression (parser, &subcode);
   rhs = convert_lvalue_to_rvalue (exp_location, rhs, true, true);
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index c867ddc..eefa4e4 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -2361,3 +2361,9 @@ expand_internal_call (gcall *stmt)
 {
   expand_internal_call (gimple_call_internal_fn (stmt), stmt);
 }
+
+void 
+expand_PHI (internal_fn, gcall *)
+{
+    gcc_unreachable ();
+}
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index e729d85..c385ab0 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -169,6 +169,7 @@ DEF_INTERNAL_FN (VA_ARG, ECF_NOTHROW | ECF_LEAF, NULL)
    other such optimizations.  The first argument distinguishes
    between uses.  See internal-fn.h for usage.  */
 DEF_INTERNAL_FN (UNIQUE, ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (PHI, 0, NULL)
 
 /* DIM_SIZE and DIM_POS return the size of a particular compute
    dimension and the executing thread's position within that
diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h
index bb31465..9c39dd67 100644
--- a/gcc/internal-fn.h
+++ b/gcc/internal-fn.h
@@ -174,5 +174,6 @@ extern bool set_edom_supported_p (void);
 
 extern void expand_internal_call (gcall *);
 extern void expand_internal_call (internal_fn, gcall *);
+extern void expand_PHI (internal_fn, gcall *);
 
 #endif
diff --git a/gcc/passes.c b/gcc/passes.c
index fd2f5cb..c84b4b1 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -114,7 +114,8 @@ pass_manager::execute_early_local_passes ()
   execute_pass_list (cfun, pass_build_ssa_passes_1->sub);
   if (flag_check_pointer_bounds)
     execute_pass_list (cfun, pass_chkp_instrumentation_passes_1->sub);
-  execute_pass_list (cfun, pass_local_optimization_passes_1->sub);
+  if (flag_gimple && cfun->custom_pass_list)
+    execute_pass_list (cfun, pass_local_optimization_passes_1->sub);
 }
 
 unsigned int
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 7fc24ba..3e34df8 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -169,6 +169,7 @@ static edge find_taken_edge_computed_goto (basic_block, 
tree);
 static edge find_taken_edge_cond_expr (basic_block, tree);
 static edge find_taken_edge_switch_expr (gswitch *, basic_block, tree);
 static tree find_case_label_for_value (gswitch *, tree);
+static void lower_phi_internal_fn ();
 
 void
 init_empty_tree_cfg_for_function (struct function *fn)
@@ -243,6 +244,7 @@ build_gimple_cfg (gimple_seq seq)
   discriminator_per_locus = new hash_table<locus_discrim_hasher> (13);
   make_edges ();
   assign_discriminators ();
+  lower_phi_internal_fn ();
   cleanup_dead_labels ();
   delete discriminator_per_locus;
   discriminator_per_locus = NULL;
@@ -344,6 +346,49 @@ replace_loop_annotate (void)
     }
 }
 
+/* Lower internal PHI function from GIMPLE FE */
+static void 
+lower_phi_internal_fn ()
+{
+  basic_block bb, pred;
+  gimple_stmt_iterator gsi;
+  tree lhs;
+  gphi *phi_node;
+  gimple *stmt;
+  int len, capacity;
+  /* After edge creation, handle __PHI function from GIMPLE FE */
+
+  FOR_EACH_BB_FN (bb, cfun)
+    {
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+       {
+         stmt = gsi_stmt (gsi);
+         if (gimple_code (stmt) != GIMPLE_CALL)
+           continue;
+
+         if (gimple_call_internal_p (stmt) && gimple_call_internal_fn (stmt) 
== IFN_PHI)
+           {
+            gsi_remove (&gsi, true);
+             int i;
+             lhs = gimple_call_lhs (stmt);
+             
+             phi_node = create_phi_node (lhs, bb);
+             
+             for (i = 0; i < gimple_call_num_args (stmt); ++i)
+               {
+                 tree arg = gimple_call_arg (stmt, i);
+                 if (TREE_CODE (arg) == LABEL_DECL)
+                   pred = label_to_block (arg);
+                 else
+                   {
+                     edge e = find_edge (pred, bb);
+                     add_phi_arg (phi_node, arg, e, UNKNOWN_LOCATION);
+                   }
+               }
+           }
+       }
+    }
+}
 
 static unsigned int
 execute_build_cfg (void)
@@ -3339,6 +3384,11 @@ verify_gimple_call (gcall *stmt)
          debug_generic_stmt (fn);
          return true;
        }
+      /* FIXME : for passing label as arg in internal fn PHI from GIMPLE FE*/
+      else if (gimple_call_internal_fn (stmt) == IFN_PHI)      
+       {
+         return false;
+       }
     }
   else
     {

Reply via email to