1 /* Unit tests for RTL-handling. 2 Copyright (C) 2015-2017 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 "signop.h" 26 #include "hash-set.h" 27 #include "fixed-value.h" 28 #include "alias.h" 29 #include "flags.h" 30 #include "symtab.h" 31 #include "tree-core.h" 32 #include "stor-layout.h" 33 #include "tree.h" 34 #include "stringpool.h" 35 #include "stor-layout.h" 36 #include "rtl.h" 37 #include "pretty-print.h" 38 #include "cfgbuild.h" 39 #include "print-rtl.h" 40 #include "selftest.h" 41 #include "selftest-rtl.h" 42 #include "function.h" 43 #include "memmodel.h" 44 #include "emit-rtl.h" 45 46 #if CHECKING_P 47 48 namespace selftest { 49 50 /* Verify that PAT is printed as EXPECTED. Helper function for 51 selftests. */ 52 53 static void 54 verify_print_pattern (const char *expected, rtx pat) 55 { 56 pretty_printer pp; 57 print_pattern (&pp, pat, 1); 58 ASSERT_STREQ (expected, pp_formatted_text (&pp)); 59 } 60 61 /* Verify that X is dumped as EXPECTED_DUMP, using compact mode. 62 Use LOC as the effective location when reporting errors. */ 63 64 void 65 assert_rtl_dump_eq (const location &loc, const char *expected_dump, rtx x, 66 rtx_reuse_manager *reuse_manager) 67 { 68 named_temp_file tmp_out (".rtl"); 69 FILE *outfile = fopen (tmp_out.get_filename (), "w"); 70 rtx_writer w (outfile, 0, false, true, reuse_manager); 71 w.print_rtl (x); 72 fclose (outfile); 73 74 char *dump = read_file (SELFTEST_LOCATION, tmp_out.get_filename ()); 75 ASSERT_STREQ_AT (loc, expected_dump, dump); 76 free (dump); 77 } 78 79 /* Verify that regs are dumped as expected (in compact mode). */ 80 81 static void 82 test_dumping_regs () 83 { 84 /* Dumps of hard regs contain a target-specific name, so we don't test 85 it here; this can be tested in target-specific selftests. */ 86 87 /* Test dumping of virtual regs. The various virtual regs are inited as 88 Pmode, so this is target-specific. The tests below assume DImode, so 89 only run the tests for targets where Pmode is DImode. */ 90 if (Pmode == DImode) 91 { 92 ASSERT_RTL_DUMP_EQ ("(reg:DI virtual-incoming-args)", 93 virtual_incoming_args_rtx); 94 ASSERT_RTL_DUMP_EQ ("(reg:DI virtual-stack-vars)", 95 virtual_stack_vars_rtx); 96 ASSERT_RTL_DUMP_EQ ("(reg:DI virtual-stack-dynamic)", 97 virtual_stack_dynamic_rtx); 98 ASSERT_RTL_DUMP_EQ ("(reg:DI virtual-outgoing-args)", 99 virtual_outgoing_args_rtx); 100 ASSERT_RTL_DUMP_EQ ("(reg:DI virtual-cfa)", 101 virtual_cfa_rtx); 102 ASSERT_RTL_DUMP_EQ ("(reg:DI virtual-preferred-stack-boundary)", 103 virtual_preferred_stack_boundary_rtx); 104 } 105 106 /* Test dumping of non-virtual pseudos. */ 107 ASSERT_RTL_DUMP_EQ ("(reg:SI <0>)", 108 gen_raw_REG (SImode, LAST_VIRTUAL_REGISTER + 1)); 109 ASSERT_RTL_DUMP_EQ ("(reg:SI <1>)", 110 gen_raw_REG (SImode, LAST_VIRTUAL_REGISTER + 2)); 111 } 112 113 /* Verify that insns are dumped as expected (in compact mode). */ 114 115 static void 116 test_dumping_insns () 117 { 118 /* Barriers. */ 119 rtx_barrier *barrier = as_a <rtx_barrier *> (rtx_alloc (BARRIER)); 120 SET_NEXT_INSN (barrier) = NULL; 121 ASSERT_RTL_DUMP_EQ ("(cbarrier 0)\n", barrier); 122 123 /* Labels. */ 124 rtx_insn *label = gen_label_rtx (); 125 CODE_LABEL_NUMBER (label) = 42; 126 ASSERT_RTL_DUMP_EQ ("(clabel 0 42)\n", label); 127 128 LABEL_NAME (label)= "some_label"; 129 ASSERT_RTL_DUMP_EQ ("(clabel 0 42 (\"some_label\"))\n", label); 130 } 131 132 /* Manually exercise the rtx_reuse_manager code. */ 133 134 static void 135 test_dumping_rtx_reuse () 136 { 137 rtx_reuse_manager r; 138 139 rtx x = rtx_alloc (SCRATCH); 140 rtx y = rtx_alloc (SCRATCH); 141 rtx z = rtx_alloc (SCRATCH); 142 143 /* x and y will be seen more than once. */ 144 r.preprocess (x); 145 r.preprocess (x); 146 r.preprocess (y); 147 r.preprocess (y); 148 149 /* z will be only seen once. */ 150 r.preprocess (z); 151 152 /* Verify that x and y have been assigned reuse IDs. */ 153 int reuse_id_for_x; 154 ASSERT_TRUE (r.has_reuse_id (x, &reuse_id_for_x)); 155 ASSERT_EQ (0, reuse_id_for_x); 156 157 int reuse_id_for_y; 158 ASSERT_TRUE (r.has_reuse_id (y, &reuse_id_for_y)); 159 ASSERT_EQ (1, reuse_id_for_y); 160 161 /* z is only seen once and thus shouldn't get a reuse ID. */ 162 ASSERT_FALSE (r.has_reuse_id (z, NULL)); 163 164 /* The first dumps of x and y should be prefixed by reuse ID; 165 all subsequent dumps of them should show up as "reuse_rtx". */ 166 ASSERT_RTL_DUMP_EQ_WITH_REUSE ("(0|scratch)", x, &r); 167 ASSERT_RTL_DUMP_EQ_WITH_REUSE ("(reuse_rtx 0)", x, &r); 168 ASSERT_RTL_DUMP_EQ_WITH_REUSE ("(reuse_rtx 0)", x, &r); 169 170 ASSERT_RTL_DUMP_EQ_WITH_REUSE ("(1|scratch)", y, &r); 171 ASSERT_RTL_DUMP_EQ_WITH_REUSE ("(reuse_rtx 1)", y, &r); 172 ASSERT_RTL_DUMP_EQ_WITH_REUSE ("(reuse_rtx 1)", y, &r); 173 174 /* z only appears once and thus shouldn't be prefixed with a 175 reuse ID. */ 176 ASSERT_RTL_DUMP_EQ_WITH_REUSE ("(scratch)", z, &r); 177 } 178 179 /* Unit testing of "single_set". */ 180 181 static void 182 test_single_set () 183 { 184 /* A label is not a SET. */ 185 ASSERT_EQ (NULL_RTX, single_set (gen_label_rtx ())); 186 187 /* An unconditional jump insn is a single SET. */ 188 rtx set_pc = gen_rtx_SET (pc_rtx, 189 gen_rtx_LABEL_REF (VOIDmode, 190 gen_label_rtx ())); 191 rtx_insn *jump_insn = emit_jump_insn (set_pc); 192 ASSERT_EQ (set_pc, single_set (jump_insn)); 193 194 /* etc */ 195 } 196 197 /* Construct an unconditional jump to a label, and verify that 198 various properties of it are sane. */ 199 200 static void 201 test_uncond_jump () 202 { 203 set_new_first_and_last_insn (NULL, NULL); 204 rtx_insn *label = gen_label_rtx (); 205 rtx jump_pat = gen_rtx_SET (pc_rtx, 206 gen_rtx_LABEL_REF (VOIDmode, 207 label)); 208 ASSERT_EQ (SET, jump_pat->code); 209 ASSERT_EQ (LABEL_REF, SET_SRC (jump_pat)->code); 210 ASSERT_EQ (label, label_ref_label (SET_SRC (jump_pat))); 211 ASSERT_EQ (PC, SET_DEST (jump_pat)->code); 212 213 verify_print_pattern ("pc=L0", jump_pat); 214 215 ASSERT_RTL_DUMP_EQ ("(set (pc)\n" 216 " (label_ref 0))", 217 jump_pat); 218 219 rtx_insn *jump_insn = emit_jump_insn (jump_pat); 220 ASSERT_FALSE (any_condjump_p (jump_insn)); 221 ASSERT_TRUE (any_uncondjump_p (jump_insn)); 222 ASSERT_TRUE (pc_set (jump_insn)); 223 ASSERT_TRUE (simplejump_p (jump_insn)); 224 ASSERT_TRUE (onlyjump_p (jump_insn)); 225 ASSERT_TRUE (control_flow_insn_p (jump_insn)); 226 227 ASSERT_RTL_DUMP_EQ ("(cjump_insn 1 (set (pc)\n" 228 " (label_ref 0)))\n", 229 jump_insn); 230 } 231 232 /* Run all of the selftests within this file. */ 233 234 void 235 rtl_tests_c_tests () 236 { 237 test_dumping_regs (); 238 test_dumping_insns (); 239 test_dumping_rtx_reuse (); 240 test_single_set (); 241 test_uncond_jump (); 242 243 /* Purge state. */ 244 set_first_insn (NULL); 245 set_last_insn (NULL); 246 } 247 248 } // namespace selftest 249 #endif /* #if CHECKING_P */ 250