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

8.2. Program Entry

To illustrate, we use following example through this section.

 

278  (define_delay (and (eq_attr "type" "branch")                                                        in mips.md

279                   (eq (symbol_ref "TARGET_MIPS16") (const_int 0)))

280    [(eq_attr "can_delay" "yes")

281     (nil)

282     (and (eq_attr "branch_likely" "yes")

283         (eq_attr "can_delay" "yes"))])

 

After treated by init_md_reader_args , above pattern will be loaded into memory as rtx object as following.

t35

figure 35 : genattr - example of define_delay

 

43    (define_function_unit "k6_alux" 1 0                                                                    in k6.md

44      (and (eq_attr "cpu" "k6")

45           (eq_attr "type" "ishift,ishift1,rotate,rotate1,alu1,negnot,cld"))

46      1 1)

 

After treated by init_md_reader_args , above pattern will be loaded into memory as rtx object as following.

t36

figure 36 : genattr - example of define_function_unit

 

135  (define_insn_reservation "pent_mul" 11                                                               in pentium.md

136    (and (eq_attr "cpu" "pentium")

137         (eq_attr "type" "imul"))

138    "pentium-np*11")

 

After treated by init_md_reader_args , above pattern will be loaded into memory as rtx object as following.

t37

figure 37 : genattr - example of define_insn_reservation

So now, we can begin.

 

175  int

176  main (int argc, char **argv)                                                                        in genattr.c

177  {

178    rtx desc;

179    int have_delay = 0;

180    int have_annul_true = 0;

181    int have_annul_false = 0;

182    int num_insn_reservations = 0;

183    int num_units = 0;

184    struct range all_simultaneity, all_multiplicity;

185    struct range all_ready_cost, all_issue_delay, all_blockage;

186    struct function_unit *units = 0, *unit;

187    int i;

188 

189    init_range (&all_multiplicity);

190    init_range (&all_simultaneity);

191    init_range (&all_ready_cost);

192    init_range (&all_issue_delay);

193    init_range (&all_blockage);

194 

195    progname = "genattr";

196 

197    if (argc <= 1)

198      fatal ("no input file name");

199 

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

201      return (FATAL_EXIT_CODE);

202 

203    puts ("/* Generated automatically by the program `genattr'");

204    puts ("   from the machine description file `md'.  *//n");

205    puts ("#ifndef GCC_INSN_ATTR_H");

206    puts ("#define GCC_INSN_ATTR_H/n");

207 

208    /* For compatibility, define the attribute `alternative', which is just

209      a reference to the variable `which_alternative'.  */

210 

211    puts ("#define HAVE_ATTR_alternative");

212    puts ("#define get_attr_alternative(insn) which_alternative");

213 

214    /* Read the machine description.  */

215 

216    while (1)

217    {

218      int line_no, insn_code_number;

219 

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

221      if (desc == NULL)

222        break ;

223 

224      if (GET_CODE (desc) == DEFINE_ATTR)

225        gen_attr (desc);

226 

227      else if (GET_CODE (desc) == DEFINE_DELAY)

228      {

229         if (! have_delay)

230         {

231           printf ("#define DELAY_SLOTS/n");

232           printf ("extern int num_delay_slots (rtx);/n");

233           printf ("extern int eligible_for_delay (rtx, int, rtx, int);/n/n");

234           printf ("extern int const_num_delay_slots (rtx);/n/n");

235           have_delay = 1;

236         }

237 

238         for (i = 0; i < XVECLEN (desc, 1); i += 3)

239         {

240           if (XVECEXP (desc, 1, i + 1) && ! have_annul_true)

241          {

242             printf ("#define ANNUL_IFTRUE_SLOTS/n");

243             printf ("extern int eligible_for_annul_true (rtx, int, rtx, int);/n");

244             have_annul_true = 1;

245          }

246 

247           if (XVECEXP (desc, 1, i + 2) && ! have_annul_false)

248          {

249             printf ("#define ANNUL_IFFALSE_SLOTS/n");

250             printf ("extern int eligible_for_annul_false (rtx, int, rtx, int);/n");

251             have_annul_false = 1;

252          }

253         }

254      }

 

Above, at line 225, define_attr is always treated as enum. It defines constants for the tool. And for define_delay, the declaration of related routines is output. Note that for every time slot, 3 entries will be used. Here in our example, have_annul_true will be zero, and have_annual_false will be 1.

 

main (continued)

 

256      else if (GET_CODE (desc) == DEFINE_FUNCTION_UNIT)

257      {

258         const char *name = XSTR (desc, 0);

259         int multiplicity = XINT (desc, 1);

260         int simultaneity = XINT (desc, 2);

261         int ready_cost = MAX (XINT (desc, 4), 1);

262         int issue_delay = MAX (XINT (desc, 5), 1);

263         int issueexp_p = (XVEC (desc, 6) != 0);

264 

265         for (unit = units; unit; unit = unit->next)

266           if (strcmp (unit->name, name) == 0)

267             break ;

268 

269         if (unit == 0)

270         {

271           unit = xmalloc (sizeof (struct function_unit ));

272           unit->name = xstrdup (name);

273           unit->multiplicity = multiplicity;

274           unit->simultaneity = simultaneity;

275           unit->ready_cost.min = unit->ready_cost.max = ready_cost;

276            unit->issue_delay.min = unit->issue_delay.max = issue_delay;

277           unit->next = units;

278           units = unit;

279           num_units++;

280 

281           extend_range (&all_multiplicity, multiplicity, multiplicity);

282           extend_range (&all_simultaneity, simultaneity, simultaneity);

283         }

284         else if (unit->multiplicity != multiplicity

285              || unit->simultaneity != simultaneity)

286           fatal ("Differing specifications given for `%s' function unit",

287                unit->name);

288 

289         extend_range (&unit->ready_cost, ready_cost, ready_cost);

290         extend_range (&unit->issue_delay,

291             issueexp_p ? 1 : issue_delay, issue_delay);

292         extend_range (&all_ready_cost,

293             unit->ready_cost.min, unit->ready_cost.max);

294         extend_range (&all_issue_delay,

295             unit->issue_delay.min, unit->issue_delay.max);

296      }

297      else if (GET_CODE (desc) == DEFINE_INSN_RESERVATION)

298        num_insn_reservations++;

299    }

300 

301    if (num_units > 0 || num_insn_reservations > 0)

302    {

303      if (num_units > 0)

304        printf ("#define TRADITIONAL_PIPELINE_INTERFACE 1/n");

305 

306      if (num_insn_reservations > 0)

307        printf ("#define DFA_PIPELINE_INTERFACE 1/n");

308 

309      /* Compute the range of blockage cost values. See genattrtab.c

310         for the derivation. BLOCKAGE (E,C) when SIMULTANEITY is zero is

311 

312         MAX (ISSUE-DELAY (E,C),

313             READY-COST (E) - (READY-COST (C) - 1))

314 

315         and otherwise

316 

317        MAX (ISSUE-DELAY (E,C),

318             READY-COST (E) - (READY-COST (C) - 1),

319             READY-COST (E) - FILL-TIME)  */

320 

321      for (unit = units; unit; unit = unit->next)

322      {

323         struct range blockage;

324 

325         blockage = unit->issue_delay;

326          blockage.max = MAX (unit->ready_cost.max

327                   - (unit->ready_cost.min - 1),

328                   blockage.max);

329         blockage.min = MAX (1, blockage.min);

330 

331         if (unit->simultaneity != 0)

332         {

333           int fill_time = ((unit->simultaneity - 1)

334                       * unit->issue_delay.min);

335           blockage.min = MAX (unit->ready_cost.min - fill_time,

336                              blockage.min);

337           blockage.max = MAX (unit->ready_cost.max - fill_time,

338                              blockage.max);

339         }

340         extend_range (&all_blockage, blockage.min, blockage.max);

341      }

 

Sturcture function_unit collects the content of the define_function_uint pattern. And see that define_function_uint pattern must have unique name as indicated by line 268.

 

44    struct function_unit                                                                                           in genattr.c

45    {

46      char *name;                     /* Function unit name.  */

47      struct function_unit *next; /* Next function unit.  */

48      int multiplicity;         /* Number of units of this type.  */

49      int simultaneity;         /* Maximum number of simultaneous insns

50                           on this function unit or 0 if unlimited.  */

51      struct range ready_cost;     /* Range of ready cost values.  */

52      struct range issue_delay;    /* Range of issue delay values.  */

53    };

 

62    static void

63    extend_range (struct range *range, int min, int max)

64    {

65      if (range->min > min) range->min = min;

66      if (range->max < max) range->max = max;

67    }

 

The handle of both define_function_uint and define_insn_reservation are quite simple in genattr.c, just saves the range of all data. Then following code produces the output.

 

main (continued)

 

343      write_units (num_units, &all_multiplicity, &all_simultaneity,

344                 &all_ready_cost, &all_issue_delay, &all_blockage);

345 

346      /* Output interface for pipeline hazards recognition based on

347        DFA (deterministic finite state automata.  */

348      printf ("/n/* DFA based pipeline interface.  */");

349      printf ("/n#ifndef AUTOMATON_ALTS/n");

350      printf ("#define AUTOMATON_ALTS 0/n");

351      printf ("#endif/n/n");

352      printf ("/n#ifndef AUTOMATON_STATE_ALTS/n");

353      printf ("#define AUTOMATON_STATE_ALTS 0/n");

354      printf ("#endif/n/n");

355      printf ("#ifndef CPU_UNITS_QUERY/n");

356      printf ("#define CPU_UNITS_QUERY 0/n");

357      printf ("#endif/n/n");

358       /* Interface itself: */

359      printf ("extern int max_dfa_issue_rate;/n/n");

360       printf ("/* The following macro value is calculated from the/n");

361      printf ("   automaton based pipeline description and is equal to/n");

362      printf ("   maximal number of all insns described in constructions/n");

363      printf ("   `define_insn_reservation' which can be issued on the/n");

364      printf ("   same processor cycle. *//n");

365      printf ("#define MAX_DFA_ISSUE_RATE max_dfa_issue_rate/n/n");

366      printf ("/* Insn latency time defined in define_insn_reservation. *//n");

367       printf ("extern int insn_default_latency (rtx);/n/n");

368      printf ("/* Return nonzero if there is a bypass for given insn/n");

369      printf ("   which is a data producer.  *//n");

370      printf ("extern int bypass_p (rtx);/n/n");

371      printf ("/* Insn latency time on data consumed by the 2nd insn./n");

372      printf ("   Use the function if bypass_p returns nonzero for/n");

373      printf ("   the 1st insn. *//n");

374      printf ("extern int insn_latency (rtx, rtx);/n/n");

375      printf ("/n#if AUTOMATON_ALTS/n");

376      printf ("/* The following function returns number of alternative/n");

377      printf ("   reservations of given insn.  It may be used for better/n");

378      printf ("   insns scheduling heuristics. *//n");

379      printf ("extern int insn_alts (rtx);/n/n");

380      printf ("#endif/n/n");

381      printf ("/* Maximal possible number of insns waiting results being/n");

382      printf ("   produced by insns whose execution is not finished. *//n");

383      printf ("extern int max_insn_queue_index;/n/n");

384      printf ("/* Pointer to data describing current state of DFA.  *//n");

385      printf ("typedef void *state_t;/n/n");

386      printf ("/* Size of the data in bytes.  *//n");

387      printf ("extern int state_size (void);/n/n");

388      printf ("/* Initiate given DFA state, i.e. Set up the state/n");

389      printf ("   as all functional units were not reserved.  *//n");

390      printf ("extern void state_reset (state_t);/n");

391      printf ("/* The following function returns negative value if given/n");

392      printf ("   insn can be issued in processor state described by given/n");

393      printf ("   DFA state.  In this case, the DFA state is changed to/n");

394      printf ("   reflect the current and future reservations by given/n");

395      printf ("   insn.  Otherwise the function returns minimal time/n");

396      printf ("   delay to issue the insn.  This delay may be zero/n");

397      printf ("   for superscalar or VLIW processors.  If the second/n");

398      printf ("   parameter is NULL the function changes given DFA state/n");

399      printf ("   as new processor cycle started.  *//n");

400      printf ("extern int state_transition (state_t, rtx);/n");

401      printf ("/n#if AUTOMATON_STATE_ALTS/n");

402      printf ("/* The following function returns number of possible/n");

403      printf ("   alternative reservations of given insn in given/n");

404      printf ("   DFA state.  It may be used for better insns scheduling/n");

405      printf ("   heuristics.  By default the function is defined if/n");

406      printf ("   macro AUTOMATON_STATE_ALTS is defined because its/n");

407      printf ("   implementation may require much memory.  *//n");

408      printf ("extern int state_alts (state_t, rtx);/n");

409      printf ("#endif/n/n");

410      printf ("extern int min_issue_delay (state_t, rtx);/n");

411      printf ("/* The following function returns nonzero if no one insn/n");

412      printf ("  can be issued in current DFA state. *//n");

413      printf ("extern int state_dead_lock_p (state_t);/n");

414      printf ("/* The function returns minimal delay of issue of the 2nd/n");

415      printf ("   insn after issuing the 1st insn in given DFA state./n");

416      printf ("   The 1st insn should be issued in given state (i.e./n");

417      printf ("   state_transition should return negative value for/n");

418      printf ("   the insn and the state).  Data dependencies between/n");

419      printf ("   the insns are ignored by the function.  *//n");

420      printf

421           ("extern int min_insn_conflict_delay (state_t, rtx, rtx);/n");

422      printf ("/* The following function outputs reservations for given/n");

423      printf ("   insn as they are described in the corresponding/n");

424      printf ("   define_insn_reservation.  *//n");

425      printf ("extern void print_reservation (FILE *, rtx);/n");

426      printf ("/n#if CPU_UNITS_QUERY/n");

427      printf ("/* The following function returns code of functional unit/n");

428      printf ("   with given name (see define_cpu_unit). *//n");

429      printf ("extern int get_cpu_unit_code (const char *);/n");

430      printf ("/* The following function returns nonzero if functional/n");

431      printf ("   unit with given code is currently reserved in given/n");

432      printf ("   DFA state.  *//n");

433      printf ("extern int cpu_unit_reservation_p (state_t, int);/n");

434      printf ("#endif/n/n");

435      printf ("/* Clean insn code cache.  It should be called if there/n");

436      printf ("   is a chance that condition value in a/n");

437      printf ("   define_insn_reservation will be changed after/n");

438      printf ("   last call of dfa_start.  *//n");

439      printf ("extern void dfa_clean_insn_cache (void);/n/n");

440      printf ("/* Initiate and finish work with DFA.  They should be/n");

441      printf ("  called as the first and the last interface/n");

442      printf ("  functions.  *//n");

443      printf ("extern void dfa_start (void);/n");

444      printf ("extern void dfa_finish (void);/n");

445    }

446    else

447    {

448      /* Otherwise we do no scheduling, but we need these typedefs

449         i n order to avoid uglifying other code with more ifdefs.  */

450      printf ("typedef void *state_t;/n/n");

451    }

452 

453    /* Output flag masks for use by reorg.

454 

455      Flags are used to hold branch direction and prediction information

456      for use by eligible_for_...  */

457    printf("/n#define ATTR_FLAG_forward/t0x1/n");

458    printf("#define ATTR_FLAG_backward/t0x2/n");

459    printf("#define ATTR_FLAG_likely/t0x4/n");

460    printf("#define ATTR_FLAG_very_likely/t0x8/n");

461    printf("#define ATTR_FLAG_unlikely/t0x10/n");

462    printf("#define ATTR_FLAG_very_unlikely/t0x20/n");

463 

464    puts("/n#endif /* GCC_INSN_ATTR_H */");

465 

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

467      return FATAL_EXIT_CODE;

468 

469    return SUCCESS_EXIT_CODE;

470  }

 

write_uints is also a simple function.

 

128  static void

129  write_units (int num_units, struct range *multiplicity, struct range *simultaneity,

130              struct range *ready_cost, struct range *issue_delay,

131              struct range *blockage)

132  {

133    int i, q_size;

134 

135    printf ("#define INSN_SCHEDULING/n/n");

136    printf ("extern int result_ready_cost (rtx);/n");

137    printf ("extern int function_units_used (rtx);/n/n");

138    printf ("extern const struct function_unit_desc/n");

139    printf ("{/n");

140    printf ("  const char *const name;/n");

141    printf ("  const int bitmask;/n");

142    printf ("  const int multiplicity;/n");

143    printf ("  const int simultaneity;/n");

144    printf ("  const int default_cost;/n");

145    printf ("  const int max_issue_delay;/n");

146    printf ("  int (*const ready_cost_function) (rtx);/n");

147    printf ("  int (*const conflict_cost_function) (rtx, rtx);/n");

148    printf ("  const int max_blockage;/n");

149    printf ("  unsigned int (*const blockage_range_function) (rtx);/n");

150    printf ("  int (*const blockage_function) (rtx, rtx);/n");

151    printf ("} function_units[];/n/n");

152    printf ("#define FUNCTION_UNITS_SIZE %d/n", num_units);

153    printf ("#define MIN_MULTIPLICITY %d/n", multiplicity->min);

154    printf ("#define MAX_MULTIPLICITY %d/n", multiplicity->max);

155    printf ("#define MIN_SIMULTANEITY %d/n", simultaneity->min);

156    printf ("#define MAX_SIMULTANEITY %d/n", simultaneity->max);

157    printf ("#define MIN_READY_COST %d/n", ready_cost->min);

158    printf ("#define MAX_READY_COST %d/n", ready_cost->max);

159    printf ("#define MIN_ISSUE_DELAY %d/n", issue_delay->min);

160    printf ("#define MAX_ISSUE_DELAY %d/n", issue_delay->max);

161    printf ("#define MIN_BLOCKAGE %d/n", blockage->min);

162    printf ("#define MAX_BLOCKAGE %d/n", blockage->max);

163    for (i = 0; (1 << i) < blockage->max; i++)

164      ;

165    printf ("#define BLOCKAGE_BITS %d/n", i + 1);

166 

167    /* INSN_QUEUE_SIZE is a power of two larger than MAX_BLOCKAGE and

168      MAX_READY_COST. This is the longest time an insn may be queued.  */

169    i = MAX (blockage->max, ready_cost->max);

170    for (q_size = 1; q_size <= i; q_size <<= 1)

171      ;

172    printf ("#define INSN_QUEUE_SIZE %d/n", q_size);

173  }

 

Insn-attr.h actually works as the header file of insn-attrtab.c generated below.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值