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