GCC's bacl-end & assemble emission (13)

6.        Tool of genextract

Genextract outputs insn-extract.c from machine description files. This file tells the way to extract operands from the specified pattern.

 

347  main (int argc, char **argv)                                                                 in genextract.c

348  {

349    rtx desc;

350    int i;

351    struct extraction *p;

352    struct code_ptr *link;

353    const char *name;

354 

355    progname = "genextract";

356 

357    if (argc <= 1)

358      fatal ("no input file name");

359 

360    if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)

361      return (FATAL_EXIT_CODE);

362 

363    /* Assign sequential codes to all entries in the machine description

364      i n parallel with the tables in insn-output.c.  */

365 

366    insn_code_number = 0;

367 

368    printf ("/* Generated automatically by the program `genextract'/n/

369          from the machine description file `md'.  *//n/n");

370 

371    printf ("#include /"config.h/"/n");

372    printf ("#include /"system.h/"/n");

373    printf ("#include /"coretypes.h/"/n");

374    printf ("#include /"tm.h/"/n");

375    printf ("#include /"rtl.h/"/n");

376    printf ("#include /"insn-config.h/"/n");

377    printf ("#include /"recog.h/"/n");

378    printf ("#include /"toplev.h/"/n/n");

379 

380    /* This variable exists only so it can be the "location"

381      of any missing operand whose numbers are skipped by a given pattern.  */

382    printf ("static rtx junk ATTRIBUTE_UNUSED;/n");

383 

384    printf ("void/ninsn_extract (rtx insn)/n");

385    printf ("{/n");

386    printf ("  rtx *ro = recog_data.operand;/n");

387    printf ("  rtx **ro_loc = recog_data.operand_loc;/n");

388    printf ("  rtx pat = PATTERN (insn);/n");

389    printf ("  int i ATTRIBUTE_UNUSED;/n/n");

390  #ifdef ENABLE_CHECKING

391    printf ("  memset (ro, 0xab, sizeof (*ro) * MAX_RECOG_OPERANDS);/n");

392    printf ("  memset (ro_loc, 0xab, sizeof (*ro_loc) * MAX_RECOG_OPERANDS);/n");

393  #endif

394    printf ("  switch (INSN_CODE (insn))/n");

395    printf ("    {/n");

396    printf ("    case -1:/n");

397    printf ("      fatal_insn_not_found (insn);/n/n");

398 

399    /* Read the machine description.  */

400 

401    while (1)

402    {

403      int line_no;

404 

405      desc = read_md_rtx (&line_no, &insn_code_number );

406      if (desc == NULL)

407        break ;

408 

409      if (GET_CODE (desc) == DEFINE_INSN)

410      {

411         record_insn_name (insn_code_number , XSTR (desc, 0));

412         gen_insn (desc);

413      }

414 

415      else if (GET_CODE (desc) == DEFINE_PEEPHOLE)

416      {

417         struct code_ptr *link = xmalloc (sizeof (struct code_ptr));

418 

419         link->insn_code = insn_code_number ;

420         link->next = peepholes ;

421         peepholes = link;

422      }

423    }

 

Again init_md_reader_args reads in the machine description file, creates rtx objects and put them into lists; then function read_md_rtx reads out the rtx objects one by one.

At line 415 above, pattern of define_peephole is not recommended to use now, pattern of define_peephole2 is expected instead. Both patterns define the way to find out the chance of peephole optimization. For define_peephole, as its output template gives out the result, so its hanlding is quite straight.

For pattern of define_insn, at line 411, the name of the pattern is recorded in insn_name_ptr which is indexed by insn_code_number . Here we use following pattern as example again.

 

467  (define_insn "cmpdi_ccno_1_rex64"                                                            in i386.md

468    [(set (reg 17)

469         (compare (match_operand:DI 0 "nonimmediate_operand" "r,?mr")

470                (match_operand:DI 1 "const0_operand" "n,n")))]

471    "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"

472    "@

473     test{q}/t{%0, %0|%0, %0}

474     cmp{q}/t{%1, %0|%0, %1}"

475    [(set_attr "type" "test,icmp")

476     (set_attr "length_immediate" "0,1")

477     (set_attr "mode" "DI")])

 

t34

figure 34  : genextract - example of define_insn

 

103  static void

104  gen_insn (rtx insn)                                                                              in genextract.c

105  {

106    int i;

107    struct extraction *p;

108    struct code_ptr *link;

109 

110    op_count = 0;

111    dup_count = 0;

112 

113    /* No operands seen so far in this pattern.  */

114    memset (oplocs , 0, sizeof oplocs );

115 

116    /* Walk the insn's pattern, remembering at all times the path

117      down to the walking point.  */

118 

119    if (XVECLEN (insn, 1) == 1)

120      walk_rtx (XVECEXP (insn, 1, 0), "");

121    else

122      for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)

123      {

124        char path[2];

125 

126        path[0] = 'a' + i;

127        path[1] = 0;

128 

129        walk_rtx (XVECEXP (insn, 1, i), path);

130      }

 

walk_rtx like those other pattern handling functions we see before, are recursed to handle define_insn pattern.

 

182  static void

183  walk_rtx (rtx x, const char *path)

184  {

185    RTX_CODE code;

186    int i;

187    int len;

188    const char *fmt;

189    int depth = strlen (path);

190    char *newpath;

191 

192    if (x == 0)

193      return ;

194 

195    code = GET_CODE (x);

196 

197    switch (code)

198    {

199      case PC:

200      case CC0:

201      case CONST_INT:

202      case SYMBOL_REF:

203        return ;

204 

205      case MATCH_OPERAND:

206      case MATCH_SCRATCH:

207        oplocs [XINT (x, 0)] = xstrdup (path);

208        op_count = MAX (op_count , XINT (x, 0) + 1);

209        break ;

210 

211       case MATCH_DUP:

212        duplocs [dup_count ] = xstrdup (path);

213        dupnums [dup_count ] = XINT (x, 0);

214        dup_count ++;

215        break ;

216 

217      case MATCH_PAR_DUP:

218      case MATCH_OP_DUP:

219        duplocs [dup_count ] = xstrdup (path);

220        dupnums [dup_count ] = XINT (x, 0);

221        dup_count ++;

222 

223        newpath = xmalloc (depth + 2);

224        strcpy (newpath, path);

225        newpath[depth + 1] = 0;

226 

227        for (i = XVECLEN (x, 1) - 1; i >= 0; i--)

228        {

229           newpath[depth] = (code == MATCH_OP_DUP ? '0' : 'a') + i;

230          walk_rtx (XVECEXP (x, 1, i), newpath);

231        }

232        free (newpath);

233        return ;

234 

235      case MATCH_OPERATOR:

236        oplocs [XINT (x, 0)] = xstrdup (path);

237        op_count = MAX (op_count , XINT (x, 0) + 1);

238 

239        newpath = xmalloc (depth + 2);

240        strcpy (newpath, path);

241        newpath[depth + 1] = 0;

242 

243        for (i = XVECLEN (x, 2) - 1; i >= 0; i--)

244         {

245          newpath[depth] = '0' + i;

246          walk_rtx (XVECEXP (x, 2, i), newpath);

247        }

248        free (newpath);

249        return ;

250 

251      case MATCH_PARALLEL:

252        oplocs [XINT (x, 0)] = xstrdup (path);

253        op_count = MAX (op_count , XINT (x, 0) + 1);

254 

255        newpath = xmalloc (depth + 2);

256        strcpy (newpath, path);

257        newpath[depth + 1] = 0;

258 

259        for (i = XVECLEN (x, 2) - 1; i >= 0; i--)

260        {

261          newpath[depth] = 'a' + i;

262          walk_rtx (XVECEXP (x, 2, i), newpath);

263        }

264        free (newpath);

265        return ;

266 

267      case ADDRESS:

268        walk_rtx (XEXP (x, 0), path);

269        return ;

270 

271      default :

272        break ;

273    }

274 

275    newpath = xmalloc (depth + 2);

276    strcpy (newpath, path);

277    newpath[depth + 1] = 0;

278 

279    fmt = GET_RTX_FORMAT (code);

280    len = GET_RTX_LENGTH (code);

281    for (i = 0; i < len; i++)

282    {

283      if (fmt[i] == 'e' || fmt[i] == 'u')

284      {

285        newpath[depth] = '0' + i;

286        walk_rtx (XEXP (x, i), newpath);

287      }

288      else if (fmt[i] == 'E')

289      {

290        int j;

291        for (j = XVECLEN (x, i) - 1; j >= 0; j--)

292        {

293          newpath[depth] = 'a' + j;

294          walk_rtx (XVECEXP (x, i, j), newpath);

295        }

296      }

297    }

298    free (newpath);

299  }

 

Note that template of rtl code SET has format “ee”, REG has format “i00”, COMPARE has format “ee”. walk_rtx is quite easy for our example. When it returns, oplocs points to ‘0’ and ‘1’, op_count is 2. Back to gen_insn , extraction and code_ptr have following definition:

 

43    struct extraction                                                                                   in genextract.c

44    {

45      int op_count;

46      char *oplocs[MAX_RECOG_OPERANDS];

47      int dup_count;

48      char *duplocs[MAX_DUP_OPERANDS];

49      int dupnums[MAX_DUP_OPERANDS];

50      struct code_ptr *insns;

51      struct extraction *next;

52    };

 

56    struct code_ptr

57    {

58      int insn_code;

59      struct code_ptr *next;

60    };

 

In which at line 45, op_count records the large operand number in this insn. At line 47 dup_count records number the occurrences of MATCH_DUP in each instruction, starting at 0 for the first occurrence. Duplocs and dupnums match every insn, duplocs records the location of any MATCH_DUP operands, dupnums records the operand number of any MATCH_DUPs. Macros MAX_DUP_OPERANDS and MAX_RECOG_OPERANDS is part of configuration generated by tool genconfig.

For patterns having similar form, they will share the same extraction , and the insns field at line 50, will keep the record of their insn code number, all extraction s will be linked together via next field at line 51.

 

gen_insn (continued)

 

132    link = xmalloc (sizeof (struct code_ptr));

133    link->insn_code = insn_code_number ;

134 

135    /* See if we find something that already had this extraction method.  */

136 

137    for (p = extractions ; p; p = p->next)

138    {

139      if (p->op_count != op_count || p->dup_count != dup_count )

140        continue ;

141 

142      for (i = 0; i < op_count ; i++)

143        if (p->oplocs[i] != oplocs [i]

144           && ! (p->oplocs[i] != 0 && oplocs [i] != 0

145                   && ! strcmp (p->oplocs[i], oplocs [i])))

146          break ;

147 

148      if (i != op_count )

149        continue ;

150 

151      for (i = 0; i < dup_count ; i++)

152        if (p->dupnums[i] != dupnums [i]

153           || strcmp (p->duplocs[i], duplocs [i]))

154          break ;

155 

156      if (i != dup_count )

157        continue ;

158 

159      /* This extraction is the same as ours. Just link us in.  */

160      link->next = p->insns;

161      p->insns = link;

162      return ;

163    }

164 

165    /* Otherwise, make a new extraction method.  */

166 

167    p = xmalloc (sizeof (struct extraction));

168    p->op_count = op_count ;

169    p->dup_count = dup_count ;

170    p->next = extractions ;

171    extractions = p;

172    p->insns = link;

173    link->next = 0;

174 

175    for (i = 0; i < op_count ; i++)

176      p->oplocs[i] = oplocs [i];

177 

178    for (i = 0; i < dup_count ; i++)

179      p->dupnums[i] = dupnums [i], p->duplocs[i] = duplocs [i];

180  }

 

In the rest part of gen_insn , it links the result of walk_rtx into extractions list. Back to main , it will handle this data.

 

main (continued)

 

425    /* Write out code to handle peepholes and the insn_codes that it should

426      be called for.  */

427    if (peepholes )

428    {

429      for (link = peepholes ; link; link = link->next)

430        printf ("    case %d:/n", link->insn_code);

431 

432      /* The vector in the insn says how many operands it has.

433         And all it contains are operands. In fact, the vector was

434        created just for the sake of this function. We need to set the

435         location of the operands for sake of simplifications after

436         extraction, like eliminating subregs.  */

437      printf ("      for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)/n");

438      printf ("          ro[i] = *(ro_loc[i] = &XVECEXP (pat, 0, i));/n");

439      printf ("      break;/n/n");

440    }

441 

442    /* Write out all the ways to extract insn operands.  */

443    for (p = extractions ; p; p = p->next)

444    {

445      for (link = p->insns; link; link = link->next)

446      {

447         i = link->insn_code;

448         name = get_insn_name (i);

449         if (name)

450           printf ("    case %d:  /* %s *//n", i, name);

451         else

452           printf ("    case %d:/n", i);

453      }

454 

455      for (i = 0; i < p->op_count; i++)

456      {

457         if (p->oplocs[i] == 0)

458         {

459           printf ("      ro[%d] = const0_rtx;/n", i);

460           printf ("      ro_loc[%d] = &junk;/n", i);

461         }

462         else

463         {

464           printf ("      ro[%d] = *(ro_loc[%d] = &", i, i);

465           print_path (p->oplocs[i]);

466            printf (");/n");

467         }

468      }

469 

470      for (i = 0; i < p->dup_count; i++)

471      {

472         printf ("      recog_data.dup_loc[%d] = &", i);

473         print_path (p->duplocs[i]);

474         printf (";/n");

475         printf ("      recog_data.dup_num[%d] = %d;/n", i, p->dupnums[i]);

476      }

477 

478      printf ("      break;/n/n");

479    }

480 

481    /* This should never be reached. Note that we would also reach this abort

482      if we tried to extract something whose INSN_CODE was a DEFINE_EXPAND or

483       DEFINE_SPLIT, but that is correct.  */

484    printf ("    default:/n      abort ();/n");

485 

486    printf ("    }/n}/n");

487 

488    fflush (stdout);

489    return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);

490  }

 

The rest code is quite simple, but in actual output code, our exampe is present in i386 32 bits system, it is discarded in read_md_rtx due to maybe_eval_c_test at line 1002 says the condition is provably always false. For real output it will be like following:

 

1     /* Generated automatically by the program `genextract'

2     from the machine description file `md'.  */

3    

4     #include "config.h"

5     #include "system.h"

6     #include "coretypes.h"

7     #include "tm.h"

8     #include "rtl.h"

9     #include "insn-config.h"

10    #include "recog.h"

11    #include "toplev.h"

12   

13    static rtx junk ATTRIBUTE_UNUSED;

14    void

15    insn_extract (rtx insn)

16    {

17      rtx *ro = recog_data.operand;

18      rtx **ro_loc = recog_data.operand_loc;

19      rtx pat = PATTERN (insn);

20      int i ATTRIBUTE_UNUSED;

21   

22      memset (ro, 0xab, sizeof (*ro) * MAX_RECOG_OPERANDS);

23      memset (ro_loc, 0xab, sizeof (*ro_loc) * MAX_RECOG_OPERANDS);

24      switch (INSN_CODE (insn))

25      {

26        case -1:

27          fatal_insn_not_found (insn);

28   

29        case 819:  /* monitor */

30          ro[0] = *(ro_loc[0] = &XVECEXP (pat, 0, 0));

31          ro[1] = *(ro_loc[1] = &XVECEXP (pat, 0, 1));

32          ro[2] = *(ro_loc[2] = &XVECEXP (pat, 0, 2));

33          break;

34       

35        default:

36          gcc_unreachable ();

37      }

38    }

7.        Tool of genpreds

Genpreds outputs file tm-preds.h from machine description file. This file declares predicate functions using by define_insn and etc. Notice that the predicate functions are defined in file `arch`.c. For different architecture the tool outputs matching tm-preds.h.

 

1     int

2     main (void)                                                                                               in genpreds.c

3     {

4       puts ("/* Generated automatically by the program `genpreds'.  *//n");

5       puts ("#ifndef GCC_TM_PREDS_H");

6       puts ("#define GCC_TM_PREDS_H/n");

7    

8       output_predicate_decls ();

9    

10      puts ("#endif /* GCC_TM_PREDS_H */");

11   

12      if (ferror (stdout) || fflush (stdout) || fclose (stdout))

13        return FATAL_EXIT_CODE;

14   

15      return SUCCESS_EXIT_CODE;

16    }

 

A simple main function is indeed.

 

33    static void

34    output_predicate_decls (void)                                                                     in genpreds.c

35    {

36    #ifdef PREDICATE_CODES

37      static const struct {

38        const char *const name;

39        const RTX_CODE codes[NUM_RTX_CODE];

40      } predicate[] = {

41        PREDICATE_CODES

42      };

43      size_t i;

44   

45      puts ("#ifdef RTX_CODE/n");

46      for (i = 0; i < ARRAY_SIZE (predicate); i++)

47        printf ("extern int %s (rtx, enum machine_mode);/n",

48               predicate[i].name);

49      puts ("/n#endif /* RTX_CODE *//n");

50    #endif

51    }

 

PREDICATE_CODES is defined by target system. For i386 system, it is following.

 

2916 #define PREDICATE_CODES                                               /                    in i386.h

2917   {"x86_64_immediate_operand", {CONST_INT, SUBREG, REG,                /

2918                             SYMBOL_REF, LABEL_REF, CONST}},         /

2919   {"x86_64_nonmemory_operand", {CONST_INT, SUBREG, REG,                     /

2920                             SYMBOL_REF, LABEL_REF, CONST}},         /

2921   {"x86_64_movabs_operand", {CONST_INT, SUBREG, REG,                    /

2922                             SYMBOL_REF, LABEL_REF, CONST}},         /

2923   {"x86_64_szext_nonmemory_operand", {CONST_INT, SUBREG, REG,            /

2924                                  SYMBOL_REF, LABEL_REF, CONST}},       /

2925   {"x86_64_general_operand", {CONST_INT, SUBREG, REG, MEM,           /

2926                            SYMBOL_REF, LABEL_REF, CONST}},             /

2927   {"x86_64_szext_general_operand", {CONST_INT, SUBREG, REG, MEM,  /

2928                                SYMBOL_REF, LABEL_REF, CONST}},    /

2929   {"x86_64_zext_immediate_operand", {CONST_INT, CONST_DOUBLE, CONST,     /

2930                                    SYMBOL_REF, LABEL_REF}},          /

2931   {"shiftdi_operand", {SUBREG, REG, MEM}},                           /

2932   {"const_int_1_31_operand", {CONST_INT}},                            /

2933   {"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}},                    /

2934   {"aligned_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,     /

2935                      LABEL_REF, SUBREG, REG, MEM}},                     /

2936   {"pic_symbolic_operand", {CONST}},                               /

2937   {"call_insn_operand", {REG, SUBREG, MEM, SYMBOL_REF}},             /

2938   {"sibcall_insn_operand", {REG, SUBREG, SYMBOL_REF}},                   /

2939   {"constant_call_address_operand", {SYMBOL_REF, CONST}},         /

2940   {"const0_operand", {CONST_INT, CONST_DOUBLE}},                   /

2941   {"const1_operand", {CONST_INT}},                                 /

2942   {"const248_operand", {CONST_INT}},                              /

2943   {"const_0_to_3_operand", {CONST_INT}},                        /

2944   {"const_0_to_7_operand", {CONST_INT}},                        /

2945   {"const_0_to_15_operand", {CONST_INT}},                      /

2946   {"const_0_to_255_operand", {CONST_INT}},                           /

2947   {"incdec_operand", {CONST_INT}},                                 /

2948   {"mmx_reg_operand", {REG}},                                         /

2949   {"reg_no_sp_operand", {SUBREG, REG}},                               /

2950   {"general_no_elim_operand", {CONST_INT, CONST_DOUBLE, CONST,         /

2951                      SYMBOL_REF, LABEL_REF, SUBREG, REG, MEM}},  /

2952   {"nonmemory_no_elim_operand", {CONST_INT, REG, SUBREG}},         /

2953   {"index_register_operand", {SUBREG, REG}},                          /

2954   {"flags_reg_operand", {REG}},                                         /

2955   {"q_regs_operand", {SUBREG, REG}},                              /

2956   {"non_q_regs_operand", {SUBREG, REG}},                       /

2957   {"fcmov_comparison_operator", {EQ, NE, LTU, GTU, LEU, GEU, UNORDERED, /

2958                             ORDERED, LT, UNLT, GT, UNGT, LE, UNLE,       /

2959                             GE, UNGE, LTGT, UNEQ}},            /

2960   {"sse_comparison_operator", {EQ, LT, LE, UNORDERED, NE, UNGE, UNGT,       /

2961                             ORDERED, UNEQ, UNLT, UNLE, LTGT, GE, GT      /

2962                             }},                                /

2963   {"ix86_comparison_operator", {EQ, NE, LE, LT, GE, GT, LEU, LTU, GEU,     /

2964                             GTU, UNORDERED, ORDERED, UNLE, UNLT,       /

2965                             UNGE, UNGT, LTGT, UNEQ }},          /

2966   {"ix86_carry_flag_operator", {LTU, LT, UNLT, GT, UNGT, LE, UNLE,     /

2967                             GE, UNGE, LTGT, UNEQ}},            /

2968   {"cmp_fp_expander_operand", {CONST_DOUBLE, SUBREG, REG, MEM}},   /

2969   {"ext_register_operand", {SUBREG, REG}},                      /

2970   {"binary_fp_operator", {PLUS, MINUS, MULT, DIV}},                    /

2971   {"mult_operator", {MULT}},                                      /

2972   {"div_operator", {DIV}},                                    /

2973   {"arith_or_logical_operator", {PLUS, MULT, AND, IOR, XOR, SMIN, SMAX, /

2974                             UMIN, UMAX, COMPARE, MINUS, DIV, MOD,   /

2975                             UDIV, UMOD, ASHIFT, ROTATE, ASHIFTRT,       /

2976                             LSHIFTRT, ROTATERT}},                /

2977   {"promotable_binary_operator", {PLUS, MULT, AND, IOR, XOR, ASHIFT}},  /

2978   {"memory_displacement_operand", {MEM}},                            /

2979   {"cmpsi_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,       /

2980                    LABEL_REF, SUBREG, REG, MEM, AND}},         /

2981   {"long_memory_operand", {MEM}},                                 /

2982   {"tls_symbolic_operand", {SYMBOL_REF}},                            /

2983   {"global_dynamic_symbolic_operand", {SYMBOL_REF}},                /

2984   {"local_dynamic_symbolic_operand", {SYMBOL_REF}},                  /

2985   {"initial_exec_symbolic_operand", {SYMBOL_REF}},               /

2986   {"local_exec_symbolic_operand", {SYMBOL_REF}},                /

2987   {"any_fp_register_operand", {REG}},                                /

2988   {"register_and_not_any_fp_reg_operand", {REG}},                    /

2989   {"fp_register_operand", {REG}},                                /

2990   {"register_and_not_fp_reg_operand", {REG}},                           /

2991   {"zero_extended_scalar_load_operand", {MEM}},                      /

2992   {"vector_move_operand", {CONST_VECTOR, SUBREG, REG, MEM}},          /

2993   {"no_seg_address_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, /

2994                            LABEL_REF, SUBREG, REG, MEM, PLUS, MULT}}, /

2995   {"compare_operator", {COMPARE}},

 

Above function declaration will be output. After release 4.3, the definition will also be produced from machine description automatically from new machine description files – predicate.md.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值