xref: /netbsd-src/external/gpl3/gcc/dist/gcc/function-tests.cc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /* Unit tests for function-handling.
2    Copyright (C) 2015-2022 Free Software Foundation, Inc.
3 
4 This file is part of GCC.
5 
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10 
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
19 
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "tm.h"
24 #include "opts.h"
25 #include "hash-set.h"
26 #include "fixed-value.h"
27 #include "alias.h"
28 #include "flags.h"
29 #include "symtab.h"
30 #include "tree-core.h"
31 #include "stor-layout.h"
32 #include "tree.h"
33 #include "stringpool.h"
34 #include "stor-layout.h"
35 #include "rtl.h"
36 #include "predict.h"
37 #include "vec.h"
38 #include "hashtab.h"
39 #include "hash-set.h"
40 #include "hard-reg-set.h"
41 #include "input.h"
42 #include "function.h"
43 #include "dominance.h"
44 #include "cfg.h"
45 #include "bitmap.h"
46 #include "cfganal.h"
47 #include "basic-block.h"
48 #include "tree-ssa-alias.h"
49 #include "internal-fn.h"
50 #include "gimple-fold.h"
51 #include "gimple-expr.h"
52 #include "toplev.h"
53 #include "print-tree.h"
54 #include "tree-iterator.h"
55 #include "gimplify.h"
56 #include "tree-cfg.h"
57 #include "basic-block.h"
58 #include "alias.h"
59 #include "symtab.h"
60 #include "inchash.h"
61 #include "tree.h"
62 #include "fold-const.h"
63 #include "stor-layout.h"
64 #include "stmt.h"
65 #include "hash-table.h"
66 #include "tree-ssa-alias.h"
67 #include "internal-fn.h"
68 #include "gimple-expr.h"
69 #include "is-a.h"
70 #include "gimple.h"
71 #include "tree-pass.h"
72 #include "context.h"
73 #include "hash-map.h"
74 #include "plugin-api.h"
75 #include "ipa-ref.h"
76 #include "cgraph.h"
77 #include "selftest.h"
78 #include "print-rtl.h"
79 
80 #if CHECKING_P
81 
82 namespace selftest {
83 
84 /* Helper function for selftests of function-creation.  */
85 
86 tree
make_fndecl(tree return_type,const char * name,vec<tree> & param_types,bool is_variadic)87 make_fndecl (tree return_type,
88 	     const char *name,
89 	     vec <tree> &param_types,
90 	     bool is_variadic)
91 {
92   tree fn_type;
93   if (is_variadic)
94     fn_type = build_varargs_function_type_array (return_type,
95 						 param_types.length (),
96 						 param_types.address ());
97   else
98     fn_type = build_function_type_array (return_type,
99 					 param_types.length (),
100 					 param_types.address ());
101   /* FIXME: this uses input_location: */
102   tree fndecl = build_fn_decl (name, fn_type);
103 
104   return fndecl;
105 }
106 
107 /* Verify creating a function declaration equivalent to the following
108      int test_fndecl_int_void (void);
109    C declaration.  */
110 
111 static void
test_fndecl_int_void()112 test_fndecl_int_void ()
113 {
114   auto_vec <tree> param_types;
115   const char *name = "test_fndecl_int_void";
116   tree fndecl = make_fndecl (integer_type_node,
117 			     name,
118 			     param_types);
119   ASSERT_TRUE (fndecl != NULL);
120 
121   /* Verify name of decl.  */
122   tree declname = DECL_NAME (fndecl);
123   ASSERT_TRUE (declname != NULL);
124   ASSERT_EQ (IDENTIFIER_NODE, TREE_CODE (declname));
125   /* We expect it to use a *copy* of the string we passed in.  */
126   const char *identifier_ptr = IDENTIFIER_POINTER (declname);
127   ASSERT_NE (name, identifier_ptr);
128   ASSERT_EQ (0, strcmp ("test_fndecl_int_void", identifier_ptr));
129 
130   /* Verify type of fndecl.  */
131   ASSERT_EQ (FUNCTION_DECL, TREE_CODE (fndecl));
132   tree fntype = TREE_TYPE (fndecl);
133   ASSERT_EQ (FUNCTION_TYPE, TREE_CODE (fntype));
134 
135   /* Verify return type.  */
136   ASSERT_EQ (integer_type_node, TREE_TYPE (fntype));
137 
138   /* Verify "void" args.  */
139   tree argtypes = TYPE_ARG_TYPES (fntype);
140   ASSERT_EQ (TREE_LIST, TREE_CODE (argtypes));
141   ASSERT_EQ (void_type_node, TREE_VALUE (argtypes));
142   ASSERT_EQ (NULL, TREE_CHAIN (argtypes));
143 }
144 
145 /* Verify creating a function declaration equivalent to the following
146      float test_fndecl_float_intchar (int, char);
147    C declaration.  */
148 
149 static void
test_fndecl_float_intchar()150 test_fndecl_float_intchar ()
151 {
152   auto_vec <tree> param_types;
153   param_types.safe_push (integer_type_node);
154   param_types.safe_push (char_type_node);
155   const char *name = "test_fndecl_float_intchar";
156   tree fndecl = make_fndecl (float_type_node,
157 			     name,
158 			     param_types);
159   ASSERT_TRUE (fndecl != NULL);
160 
161   /* Verify name of decl.  */
162   tree declname = DECL_NAME (fndecl);
163   ASSERT_TRUE (declname != NULL);
164   ASSERT_EQ (IDENTIFIER_NODE, TREE_CODE (declname));
165   /* We expect it to use a *copy* of the string we passed in.  */
166   const char *identifier_ptr = IDENTIFIER_POINTER (declname);
167   ASSERT_NE (name, identifier_ptr);
168   ASSERT_EQ (0, strcmp (name, identifier_ptr));
169 
170   /* Verify type of fndecl.  */
171   ASSERT_EQ (FUNCTION_DECL, TREE_CODE (fndecl));
172   tree fntype = TREE_TYPE (fndecl);
173   ASSERT_EQ (FUNCTION_TYPE, TREE_CODE (fntype));
174 
175   /* Verify return type.  */
176   ASSERT_EQ (float_type_node, TREE_TYPE (fntype));
177 
178   /* Verify "(int, char)" args.  */
179   tree arg0 = TYPE_ARG_TYPES (fntype);
180   ASSERT_EQ (TREE_LIST, TREE_CODE (arg0));
181   ASSERT_EQ (integer_type_node, TREE_VALUE (arg0));
182   tree arg1 = TREE_CHAIN (arg0);
183   ASSERT_TRUE (arg1 != NULL);
184   ASSERT_EQ (TREE_LIST, TREE_CODE (arg1));
185   ASSERT_EQ (char_type_node, TREE_VALUE (arg1));
186   tree argterm = TREE_CHAIN (arg1);
187   ASSERT_TRUE (argterm != NULL);
188   ASSERT_EQ (TREE_LIST, TREE_CODE (argterm));
189   ASSERT_EQ (void_type_node, TREE_VALUE (argterm));
190   ASSERT_EQ (NULL, TREE_CHAIN (argterm));
191 }
192 
193 /* The test cases using these helper functions take a trivial function:
194 
195      int test_fn (void) { return 42; }
196 
197    and test various conversions done to it:
198 
199    - gimplification
200    - construction of the CFG
201    - conversion to SSA form
202    - expansion to RTL form
203 
204    In avoid having one overlong test case, this is broken
205    up into separate test cases for each stage, with helper functions
206    to minimize code duplication.
207 
208    Another approach would be to attempt to directly construct a function
209    in the appropriate representation at each stage, though presumably
210    that would exhibit different kinds of failure compared to this
211    approach.  */
212 
213 /* Construct this function:
214    int test_fn (void) { return 42; }
215    in generic tree form.  Return the fndecl.  */
216 
217 static tree
build_trivial_generic_function()218 build_trivial_generic_function ()
219 {
220   auto_vec <tree> param_types;
221   tree fndecl = make_fndecl (integer_type_node,
222 			     "test_fn",
223 			     param_types);
224   ASSERT_TRUE (fndecl != NULL);
225 
226   /* Populate the function.  */
227   tree retval = build_decl (UNKNOWN_LOCATION, RESULT_DECL,
228 			    NULL_TREE, integer_type_node);
229   DECL_ARTIFICIAL (retval) = 1;
230   DECL_IGNORED_P (retval) = 1;
231   DECL_RESULT (fndecl) = retval;
232 
233   /* Create a BIND_EXPR, and within it, a statement list.  */
234   tree stmt_list = alloc_stmt_list ();
235   tree_stmt_iterator stmt_iter = tsi_start (stmt_list);
236   tree block = make_node (BLOCK);
237   tree bind_expr
238     = build3 (BIND_EXPR, void_type_node, NULL, stmt_list, block);
239 
240   tree modify_retval = build2 (MODIFY_EXPR,
241 			       integer_type_node,
242 			       retval,
243 			       build_int_cst (integer_type_node, 42));
244   tree return_stmt = build1 (RETURN_EXPR,
245 			     integer_type_node,
246 			     modify_retval);
247   tsi_link_after (&stmt_iter, return_stmt, TSI_CONTINUE_LINKING);
248 
249   DECL_INITIAL (fndecl) = block;
250   BLOCK_SUPERCONTEXT (block) = fndecl;
251 
252   /* how to add to function? the following appears to be how to
253      set the body of a fndecl: */
254   DECL_SAVED_TREE(fndecl) = bind_expr;
255 
256   /* Ensure that locals appear in the debuginfo.  */
257   BLOCK_VARS (block) = BIND_EXPR_VARS (bind_expr);
258 
259   return fndecl;
260 }
261 
262 /* Construct this function:
263      int test_fn (void) { return 42; }
264    in "high gimple" form.  Return the fndecl.  */
265 
266 static tree
build_trivial_high_gimple_function()267 build_trivial_high_gimple_function ()
268 {
269   /* Construct a trivial function, and gimplify it: */
270   tree fndecl = build_trivial_generic_function ();
271   gimplify_function_tree (fndecl);
272   return fndecl;
273 }
274 
275 /* Build a CFG for a function in gimple form.  */
276 
277 static void
build_cfg(tree fndecl)278 build_cfg (tree fndecl)
279 {
280   function *fun = DECL_STRUCT_FUNCTION (fndecl);
281   ASSERT_TRUE (fun != NULL);
282   ASSERT_EQ (fndecl, fun->decl);
283 
284   /* We first have to lower control flow; for our trivial test function
285      this gives us:
286 	 test_fn ()
287 	 {
288 	   D.56 = 42;
289 	   goto <D.57>;
290 	   <D.57>:
291 	   return D.56;
292 	 }
293   */
294   gimple_opt_pass *lower_cf_pass = make_pass_lower_cf (g);
295   push_cfun (fun);
296   lower_cf_pass->execute (fun);
297   pop_cfun ();
298   delete lower_cf_pass;
299 
300   /* We can now convert to CFG form; for our trivial test function this
301      gives us:
302 	 test_fn ()
303 	 {
304 	   <bb 2>:
305 	   D.56 = 42;
306 	   return D.56;
307 	 }
308   */
309   gimple_opt_pass *build_cfg_pass = make_pass_build_cfg (g);
310   push_cfun (fun);
311   build_cfg_pass->execute (fun);
312   pop_cfun ();
313   delete build_cfg_pass;
314 }
315 
316 /* Convert a gimple+CFG function to SSA form.  */
317 
318 static void
convert_to_ssa(tree fndecl)319 convert_to_ssa (tree fndecl)
320 {
321   function *fun = DECL_STRUCT_FUNCTION (fndecl);
322   ASSERT_TRUE (fun != NULL);
323   ASSERT_EQ (fndecl, fun->decl);
324 
325   gimple_opt_pass *build_ssa_pass = make_pass_build_ssa (g);
326   push_cfun (fun);
327   build_ssa_pass->execute (fun);
328   pop_cfun ();
329   delete build_ssa_pass;
330 }
331 
332 /* Assuming we have a simple 3-block CFG like this:
333      [ENTRY] -> [block2] -> [EXIT]
334    get the "real" basic block (block 2).  */
335 
336 static basic_block
get_real_block(function * fun)337 get_real_block (function *fun)
338 {
339   ASSERT_TRUE (fun->cfg != NULL);
340   ASSERT_EQ (3, n_basic_blocks_for_fn (fun));
341   basic_block bb2 = (*fun->cfg->x_basic_block_info)[2];
342   ASSERT_TRUE (bb2 != NULL);
343   return bb2;
344 }
345 
346 /* Verify that we have a simple 3-block CFG: the two "fake" ones, and
347    a "real" one:
348      [ENTRY] -> [block2] -> [EXIT].  */
349 
350 static void
verify_three_block_cfg(function * fun)351 verify_three_block_cfg (function *fun)
352 {
353   ASSERT_TRUE (fun->cfg != NULL);
354   ASSERT_EQ (3, n_basic_blocks_for_fn (fun));
355   ASSERT_EQ (2, n_edges_for_fn (fun));
356 
357   /* The "fake" basic blocks.  */
358   basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (fun);
359   ASSERT_TRUE (entry != NULL);
360   ASSERT_EQ (ENTRY_BLOCK, entry->index);
361 
362   basic_block exit = EXIT_BLOCK_PTR_FOR_FN (fun);
363   ASSERT_TRUE (exit != NULL);
364   ASSERT_EQ (EXIT_BLOCK, exit->index);
365 
366   /* The "real" basic block.  */
367   basic_block bb2 = get_real_block (fun);
368   ASSERT_TRUE (bb2 != NULL);
369   ASSERT_EQ (2, bb2->index);
370 
371   /* Verify connectivity.  */
372   ASSERT_EQ (NULL, entry->preds);
373   ASSERT_EQ (1, entry->succs->length ());
374 
375   edge from_entry_to_bb2 = (*entry->succs)[0];
376   ASSERT_EQ (entry, from_entry_to_bb2->src);
377   ASSERT_EQ (bb2, from_entry_to_bb2->dest);
378 
379   ASSERT_EQ (1, bb2->preds->length ());
380   ASSERT_EQ (from_entry_to_bb2, (*bb2->preds)[0]);
381   ASSERT_EQ (1, bb2->succs->length ());
382 
383   edge from_bb2_to_exit = (*bb2->succs)[0];
384   ASSERT_EQ (bb2, from_bb2_to_exit->src);
385   ASSERT_EQ (exit, from_bb2_to_exit->dest);
386 
387   ASSERT_EQ (1, exit->preds->length ());
388   ASSERT_EQ (from_bb2_to_exit, (*exit->preds)[0]);
389   ASSERT_EQ (NULL, exit->succs);
390 }
391 
392 /* As above, but additionally verify the gimple statements are sane.  */
393 
394 static void
verify_three_block_gimple_cfg(function * fun)395 verify_three_block_gimple_cfg (function *fun)
396 {
397   verify_three_block_cfg (fun);
398 
399   /* The "fake" basic blocks should be flagged as gimple, but with have no
400      statements.  */
401   basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (fun);
402   ASSERT_TRUE (entry != NULL);
403   ASSERT_EQ (0, entry->flags & BB_RTL);
404   ASSERT_EQ (NULL, bb_seq (entry));
405 
406   basic_block exit = EXIT_BLOCK_PTR_FOR_FN (fun);
407   ASSERT_TRUE (exit != NULL);
408   ASSERT_EQ (0, entry->flags & BB_RTL);
409   ASSERT_EQ (NULL, bb_seq (exit));
410 
411   /* The "real" basic block should be flagged as gimple, and have one
412      or more statements.  */
413   basic_block bb2 = get_real_block (fun);
414   ASSERT_TRUE (bb2 != NULL);
415   ASSERT_EQ (0, entry->flags & BB_RTL);
416   ASSERT_TRUE (bb_seq (bb2) != NULL);
417 }
418 
419 /* As above, but additionally verify the RTL insns are sane.  */
420 
421 void
verify_three_block_rtl_cfg(function * fun)422 verify_three_block_rtl_cfg (function *fun)
423 {
424   verify_three_block_cfg (fun);
425 
426   /* The "fake" basic blocks should be flagged as RTL, but with no
427      insns.  */
428   basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (fun);
429   ASSERT_TRUE (entry != NULL);
430   ASSERT_EQ (BB_RTL, entry->flags & BB_RTL);
431   ASSERT_EQ (NULL, BB_HEAD (entry));
432 
433   basic_block exit = EXIT_BLOCK_PTR_FOR_FN (fun);
434   ASSERT_TRUE (exit != NULL);
435   ASSERT_EQ (BB_RTL, exit->flags & BB_RTL);
436   ASSERT_EQ (NULL, BB_HEAD (exit));
437 
438   /* The "real" basic block should be flagged as RTL, and have one
439      or more insns.  */
440   basic_block bb2 = get_real_block (fun);
441   ASSERT_TRUE (bb2 != NULL);
442   ASSERT_EQ (BB_RTL, bb2->flags & BB_RTL);
443   ASSERT_TRUE (BB_HEAD (bb2) != NULL);
444 }
445 
446 /* Test converting our trivial function:
447      int test_fn (void) { return 42; }
448    to gimple form.  */
449 
450 static void
test_gimplification()451 test_gimplification ()
452 {
453   tree fndecl = build_trivial_generic_function ();
454 
455   /* Convert to gimple: */
456   gimplify_function_tree (fndecl);
457 
458   /* Verify that we got gimple out of it.  */
459 
460   /* The function is now in GIMPLE form but the CFG has not been
461      built yet.  */
462 
463   /* We should have a struct function for the decl.  */
464   function *fun = DECL_STRUCT_FUNCTION (fndecl);
465   ASSERT_TRUE (fun != NULL);
466   ASSERT_EQ (fndecl, fun->decl);
467 
468   /* We expect a GIMPLE_BIND, with two gimple statements within it:
469        tmp = 42;
470        return tmp;  */
471 
472   gimple_seq seq_fn_body = gimple_body (fndecl);
473   ASSERT_TRUE (seq_fn_body != NULL);
474   gimple *bind_stmt = gimple_seq_first_stmt (seq_fn_body);
475   ASSERT_EQ (GIMPLE_BIND, gimple_code (bind_stmt));
476   ASSERT_EQ (NULL, bind_stmt->next);
477 
478   gimple_seq seq_bind_body = gimple_bind_body (as_a <gbind *> (bind_stmt));
479 
480   /* Verify that we have the 2 statements we expect.  */
481   ASSERT_TRUE (seq_bind_body != NULL);
482   gimple *stmt1 = gimple_seq_first_stmt (seq_bind_body);
483   ASSERT_TRUE (stmt1 != NULL);
484   ASSERT_EQ (GIMPLE_ASSIGN, gimple_code (stmt1));
485   gimple *stmt2 = stmt1->next;
486   ASSERT_TRUE (stmt2 != NULL);
487   ASSERT_EQ (stmt1, stmt2->prev);
488   ASSERT_EQ (GIMPLE_RETURN, gimple_code (stmt2));
489 }
490 
491 /* Test of building a CFG for a function in high gimple form.  */
492 
493 static void
test_building_cfg()494 test_building_cfg ()
495 {
496   /* Construct a trivial function, and gimplify it: */
497   tree fndecl = build_trivial_high_gimple_function ();
498   function *fun = DECL_STRUCT_FUNCTION (fndecl);
499   ASSERT_TRUE (fun != NULL);
500 
501   /* Build a CFG.  */
502   build_cfg (fndecl);
503 
504   /* The CFG-building code constructs a 4-block cfg (with
505      ENTRY and EXIT):
506        test_fn ()
507        {
508          <bb 2>:
509 	 D.65 = 42;
510 
511 	 <bb 3>:
512 	 return D.65;
513        }
514      and then ought to merge blocks 2 and 3 in cleanup_tree_cfg.
515 
516      Hence we should end up with a simple 3-block cfg, the two "fake" ones,
517      and a "real" one:
518        [ENTRY] -> [block2] -> [EXIT]
519      with code like this:
520 	 test_fn ()
521 	 {
522 	   <bb 2>:
523 	   D.56 = 42;
524 	   return D.56;
525 	 }
526   */
527   verify_three_block_gimple_cfg (fun);
528 
529   /* Verify the statements within the "real" block.  */
530   basic_block bb2 = get_real_block (fun);
531   gimple *stmt_a = gimple_seq_first_stmt (bb_seq (bb2));
532   ASSERT_EQ (GIMPLE_ASSIGN, gimple_code (stmt_a));
533   gimple *stmt_b = stmt_a->next;
534   ASSERT_EQ (GIMPLE_RETURN, gimple_code (stmt_b));
535   ASSERT_EQ (NULL, stmt_b->next);
536 }
537 
538 /* Test of conversion of gimple to SSA form.  */
539 
540 static void
test_conversion_to_ssa()541 test_conversion_to_ssa ()
542 {
543   /* As above, construct a trivial function, gimplify it, and build a CFG: */
544   tree fndecl = build_trivial_high_gimple_function ();
545   function *fun = DECL_STRUCT_FUNCTION (fndecl);
546   ASSERT_TRUE (fun != NULL);
547   build_cfg (fndecl);
548 
549   convert_to_ssa (fndecl);
550 
551   verify_three_block_gimple_cfg (fun);
552 
553   /* For out trivial test function we should now have something like
554      this:
555        test_fn ()
556        {
557 	 <bb 2>:
558 	 _1 = 42;
559 	 return _1;
560        }
561   */
562   basic_block bb2 = get_real_block (fun);
563   gimple *stmt_a = gimple_seq_first_stmt (bb_seq (bb2));
564   ASSERT_EQ (GIMPLE_ASSIGN, gimple_code (stmt_a));
565 
566   gimple *stmt_b = stmt_a->next;
567   ASSERT_EQ (GIMPLE_RETURN, gimple_code (stmt_b));
568   ASSERT_EQ (NULL, stmt_b->next);
569 
570   greturn *return_stmt = as_a <greturn *> (stmt_b);
571   ASSERT_EQ (SSA_NAME, TREE_CODE (gimple_return_retval (return_stmt)));
572 }
573 
574 /* Test range folding.  We must start this here because we need cfun
575    set.  */
576 
577 static void
test_ranges()578 test_ranges ()
579 {
580   tree fndecl = build_trivial_high_gimple_function ();
581   function *fun = DECL_STRUCT_FUNCTION (fndecl);
582   push_cfun (fun);
583   range_tests ();
584   range_op_tests ();
585 
586   build_cfg (fndecl);
587   convert_to_ssa (fndecl);
588   gimple_range_tests ();
589 
590   pop_cfun ();
591 }
592 
593 /* Test of expansion from gimple-ssa to RTL.  */
594 
595 static void
test_expansion_to_rtl()596 test_expansion_to_rtl ()
597 {
598   /* As above, construct a trivial function, gimplify it, build a CFG,
599      and convert to SSA: */
600   tree fndecl = build_trivial_high_gimple_function ();
601   function *fun = DECL_STRUCT_FUNCTION (fndecl);
602   ASSERT_TRUE (fun != NULL);
603   build_cfg (fndecl);
604   convert_to_ssa (fndecl);
605 
606   /* We need a cgraph_node for it.  */
607   cgraph_node::get_create (fndecl);
608   /* Normally, cgraph_node::expand () would call
609      init_function_start (and a bunch of other stuff),
610      and invoke the expand pass, but it also runs
611      all of the other passes.  So just do the minimum
612      needed to get from gimple-SSA to RTL.  */
613   rtl_opt_pass *expand_pass = make_pass_expand (g);
614   push_cfun (fun);
615   init_function_start (fndecl);
616   expand_pass->execute (fun);
617   pop_cfun ();
618   delete expand_pass;
619 
620   /* On x86_64, I get this:
621        (note 3 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
622        (note 2 3 5 2 NOTE_INSN_FUNCTION_BEG)
623        (insn 5 2 6 2 (set (reg:SI 87 [ D.59 ])
624 			  (const_int 42 [0x2a])) -1 (nil))
625        (insn 6 5 10 2 (set (reg:SI 88 [ <retval> ])
626 			   (reg:SI 87 [ D.59 ])) -1 (nil))
627        (insn 10 6 11 2 (set (reg/i:SI 0 ax)
628 			    (reg:SI 88 [ <retval> ])) -1 (nil))
629        (insn 11 10 0 2 (use (reg/i:SI 0 ax)) -1 (nil))
630 
631      On cr16-elf I get this:
632        (note 4 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
633        (insn 2 4 3 2 (set (reg:SI 24)
634 	    (reg/f:SI 16 virtual-incoming-args)) -1
635 	  (nil))
636        (note 3 2 6 2 NOTE_INSN_FUNCTION_BEG)
637        (insn 6 3 7 2 (set (reg:HI 22 [ _1 ])
638 	    (const_int 42 [0x2a])) -1
639 	 (nil))
640        (insn 7 6 11 2 (set (reg:HI 23 [ <retval> ])
641 	   (reg:HI 22 [ _1 ])) -1
642 	 (nil))
643        (insn 11 7 12 2 (set (reg/i:HI 0 r0)
644 	   (reg:HI 23 [ <retval> ])) -1
645 	 (nil))
646        (insn 12 11 0 2 (use (reg/i:HI 0 r0)) -1
647 	 (nil)).  */
648   verify_three_block_rtl_cfg (fun);
649 
650   /* Verify as much of the RTL as we can whilst avoiding
651      target-specific behavior.  */
652   basic_block bb2 = get_real_block (fun);
653 
654   /* Expect a NOTE_INSN_BASIC_BLOCK... */
655   rtx_insn *insn = BB_HEAD (bb2);
656   ASSERT_TRUE (insn != NULL);
657   ASSERT_EQ (NOTE, insn->code);
658   ASSERT_EQ (NOTE_INSN_BASIC_BLOCK, NOTE_KIND (insn));
659   ASSERT_EQ (bb2, NOTE_BASIC_BLOCK (insn));
660 
661   /* ...etc; any further checks are likely to over-specify things
662      and run us into target dependencies.  */
663 
664   /* Verify that print_rtl_function is sane.  */
665   named_temp_file tmp_out (".rtl");
666   FILE *outfile = fopen (tmp_out.get_filename (), "w");
667   print_rtx_function (outfile, fun, true);
668   fclose (outfile);
669 
670   char *dump = read_file (SELFTEST_LOCATION, tmp_out.get_filename ());
671   ASSERT_STR_CONTAINS (dump, "(function \"test_fn\"\n");
672   ASSERT_STR_CONTAINS (dump, "  (insn-chain\n");
673   ASSERT_STR_CONTAINS (dump, "    (block 2\n");
674   ASSERT_STR_CONTAINS (dump, "      (edge-from entry (flags \"FALLTHRU\"))\n");
675   ASSERT_STR_CONTAINS (dump, "      (cinsn "); /* ...etc.  */
676   ASSERT_STR_CONTAINS (dump, "      (edge-to exit (flags \"FALLTHRU\"))\n");
677   ASSERT_STR_CONTAINS (dump, "    ) ;; block 2\n");
678   ASSERT_STR_CONTAINS (dump, "  ) ;; insn-chain\n");
679   ASSERT_STR_CONTAINS (dump, "  (crtl\n");
680   ASSERT_STR_CONTAINS (dump, "  ) ;; crtl\n");
681   ASSERT_STR_CONTAINS (dump, ") ;; function \"test_fn\"\n");
682 
683   free (dump);
684   free_after_compilation (fun);
685 }
686 
687 /* Run all of the selftests within this file.  */
688 
689 void
function_tests_cc_tests()690 function_tests_cc_tests ()
691 {
692   test_fndecl_int_void ();
693   test_fndecl_float_intchar ();
694   test_gimplification ();
695   test_building_cfg ();
696   test_conversion_to_ssa ();
697   test_ranges ();
698   test_expansion_to_rtl ();
699 }
700 
701 } // namespace selftest
702 
703 #endif /* #if CHECKING_P */
704