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

15.   Toolof genpeep

The detail of define_peepholepattern refers to Overview – about define_peephole,this tool won’t handle define_peephole2 pattern which is processed by toolsgenemit, genoutput and genrecog.

 

353  int

354  main (int argc, char **argv)                                                                        ingenpeep.c

355  {

356   rtx desc;

357 

358   max_opno= -1;

359 

360   progname= "genpeep";

361 

362   if (argc <= 1)

363     fatal ("no input file name");

364 

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

366     return (FATAL_EXIT_CODE);

367 

368   printf ("/* Generated automatically by the program `genpeep'\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 \"insn-config.h\"\n");

376   printf ("#include \"rtl.h\"\n");

377   printf ("#include \"tm_p.h\"\n");

378   printf ("#include \"regs.h\"\n");

379   printf ("#include \"output.h\"\n");

380   printf ("#include \"real.h\"\n");

381   printf ("#include \"recog.h\"\n");

382   printf ("#include \"except.h\"\n\n");

383   printf ("#include \"function.h\"\n\n");

384 

385   printf ("#ifdef HAVE_peephole\n");

386   printf ("extern rtx peep_operand[];\n\n");

387   printf ("#define operands peep_operand\n\n");

388 

389   printf ("rtx\npeephole (rtx ins1)\n{\n");

390    printf ("  rtx insn ATTRIBUTE_UNUSED, xATTRIBUTE_UNUSED, pat ATTRIBUTE_UNUSED;\n\n");

391 

392   /* Early out: no peepholes for insns followedby barriers.  */

393   printf ("  if (NEXT_INSN(ins1)\n");

394   printf ("      &&GET_CODE (NEXT_INSN (ins1)) == BARRIER)\n");

395   printf ("    return0;\n\n");

396 

397   /* Read the machine description.  */

398 

399   while (1)

400   {

401     int line_no, rtx_number = 0;

402 

403     desc = read_md_rtx (&line_no,&rtx_number);

404     if (desc == NULL)

405       break;

406 

407     if (GET_CODE (desc) == DEFINE_PEEPHOLE)

408     {

409       gen_peephole (desc);

410       insn_code_number++;

411     }

412     if (GET_CODE (desc) == DEFINE_INSN

413        || GET_CODE (desc) == DEFINE_EXPAND

414        || GET_CODE (desc) == DEFINE_SPLIT

415        || GET_CODE (desc) == DEFINE_PEEPHOLE2)

416     {

417       insn_code_number++;

418     }

419   }

420 

421   printf ("  return0;\n}\n\n");

422 

423   if (max_opno== -1)

424     max_opno= 1;

425 

426   printf ("rtx peep_operand[%d];\n", max_opno + 1);

427   printf ("#endif\n");

428 

429   fflush (stdout);

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

431  }

 

Till line 399, we can see following output fragment.

 

/* Generated automatically by theprogram `genpeep'

from the machine description file`md'.  */

 

#include "config.h"

#include "system.h"

#include "coretypes.h"

#include "tm.h"

#include "insn-config.h"

#include "rtl.h"

#include "tm_p.h"

#include "regs.h"

#include "output.h"

#include "real.h"

#include "recog.h"

#include "except.h"

 

#include "function.h"

 

#ifdef HAVE_peephole

extern rtx peep_operand[];

 

#define operands peep_operand

 

rtx

peephole (rtx ins1)

{

 rtx insn ATTRIBUTE_UNUSED, x ATTRIBUTE_UNUSED, pat ATTRIBUTE_UNUSED;

 

 if (NEXT_INSN (ins1)

      && GET_CODE (NEXT_INSN (ins1)) ==BARRIER)

   return 0;

 

gen_peephole继续把该模式输出到这个peephole函数中。

 

61    static void

62    gen_peephole (rtx peep)                                                                             ingenpeep.c

63    {

64     int ninsns = XVECLEN (peep, 0);

65     int i;

66   

67     n_operands= 0;

68   

69     printf ("  insn =ins1;\n");

70   

71      for(i = 0; i < ninsns; i++)

72     {

73       if (i > 0)

74       {

75         printf ("  do { insn =NEXT_INSN (insn);\n");

76         printf ("       if (insn ==0) goto L%d; }\n",

77                     insn_code_number);

78         printf ("  while (GET_CODE(insn) == NOTE\n");

79          printf ("\t || (GET_CODE(insn) == INSN\n");

80         printf ("\t     &&(GET_CODE (PATTERN (insn)) == USE\n");

81         printf ("\t\t || GET_CODE (PATTERN (insn)) == CLOBBER)));\n");

82   

83         printf ("  if (GET_CODE(insn) == CODE_LABEL\n\

84                || GET_CODE (insn) ==BARRIER)\n    goto L%d;\n",

85                insn_code_number);

86       }

87   

88       printf ("  pat = PATTERN(insn);\n");

89   

90       /* Walk the insn's pattern, remembering at alltimes the path

91          down to the walking point.  */

92   

93       match_rtx (XVECEXP (peep, 0, i), NULL, insn_code_number);

94     }

95   

96     /* We get this far if the pattern matches.

97        Now test the extra condition.  */

98   

99     if (XSTR (peep, 1) && XSTR (peep, 1)[0])

100     printf ("  if (! (%s)) gotoL%d;\n",

101            XSTR (peep, 1), insn_code_number);

102 

103   /* If that matches, construct new pattern andput it in the first insn.

104      This new pattern will never be matched.

105      It exists only so that insn-extract can getthe operands back.

106      So use a simple regular form: a PARALLELcontaining a vector

107      of all the operands.  */

108 

109   printf ("  PATTERN (ins1) =gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (%d, operands));\n", n_operands);

110 

111   /* Record this define_peephole's insn code inthe insn,

112      as if it had been recognized to matchthis.  */

113    printf ("  INSN_CODE (ins1) = %d;\n",

114         insn_code_number);

115 

116   /* Delete the remaining insns.  */

117   if (ninsns > 1)

118     printf (" delete_for_peephole (NEXT_INSN (ins1), insn);\n");

119 

120   /* See reload1.c for insertion of NOTE whichguarantees that this

121      cannot be zero.  */

122   printf ("  return NEXT_INSN(insn);\n");

123 

124   printf (" L%d:\n\n", insn_code_number);

125  }

 

Then if the architecture (for i386 system, no define_peephole isdefined) contains define_peephole, till line 93, before invoking match_rtx, wecan get peepholefunction as following.

 

rtx

peephole (rtx ins1)

{

 rtx insn ATTRIBUTE_UNUSED, x ATTRIBUTE_UNUSED, pat ATTRIBUTE_UNUSED;

 

 if (NEXT_INSN (ins1)

      && GET_CODE (NEXT_INSN (ins1)) ==BARRIER)

   return 0;

 

  insn = ins1;

do { insn = NEXT_INSN (insn);

  if (insn == 0) gotoL’insn-code-num`; }

while (GET_CODE (insn) == NOTE

|| (GET_CODE (insn) == INSN

  && (GET_CODE(PATTERN (insn)) == USE

  || GET_CODE (PATTERN(insn)) == CLOBBER)));

 

if (GET_CODE (insn) == CODE_LABEL

  || GET_CODE (insn)== BARRIER)

  goto L’insn-code-num`;

 

pat = PATTERN (insn);

 

For the example we see in Overview –about define_peephole, the first child of the rtx object is following rtxobject, which will be the first parameter of match_rtx.

 

[(set(reg:SI 15) (plus:SI (reg:SI 15) (const_int 4)))

    (set(match_operand:DF 0 "register_operand" "=f")

       (match_operand:DF 1"register_operand" "ad"))]

 

It is parallel containing two instructions.

In the output peephole, insn is the rtx object generated by emit_insn, PATTERN willretrieve the rtx object of define_insn from the instruction.

 

127  static void

128  match_rtx (rtx x, struct link *path, intfail_label)                                                 in genpeep.c

129  {

130    RTX_CODE code;

131    int i;

132    int len;

133    constchar *fmt;

134   struct link link;

135 

136   if (x == 0)

137     return;

138 

139 

140   code = GET_CODE (x);

141 

142   switch (code)

143   {

144     case MATCH_OPERAND:

145       if (XINT (x, 0) > max_opno)

146         max_opno= XINT (x, 0);

147       if (XINT (x, 0) >= n_operands)

148         n_operands= 1 + XINT (x, 0);

149 

150       printf ("  x = ");

151       print_path (path);

152       printf (";\n");

153 

154       printf ("  operands[%d] =x;\n", XINT (x, 0));

155       if (XSTR (x, 1) && XSTR (x, 1)[0])

156         printf ("  if (! %s (x,%smode)) goto L%d;\n",

157                XSTR(x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);

158       return;

159 

160     case MATCH_DUP:

161     case MATCH_PAR_DUP:

162       printf ("  x = ");

163       print_path (path);

164       printf (";\n");

165 

166       printf ("  if (!rtx_equal_p(operands[%d], x)) goto L%d;\n",

167              XINT (x, 0), fail_label);

168       return;

169 

170     case MATCH_OP_DUP:

171       printf ("  x = ");

172       print_path (path);

173       printf (";\n");

174 

175       printf ("  if (GET_CODE(operands[%d]) != GET_CODE (x)\n", XINT (x, 0));

176       printf ("      || GET_MODE(operands[%d]) != GET_MODE (x)) goto L%d;\n",

177              XINT (x, 0), fail_label);

178       printf ("  operands[%d] =x;\n", XINT (x, 0));

179       link.next = path;

180       link.vecelt = -1;

181        for(i = 0; i < XVECLEN (x, 1); i++)

182       {

183         link.pos = i;

184         match_rtx (XVECEXP (x, 1, i), &link,fail_label);

185       }

186       return;

187 

188     case MATCH_OPERATOR:

189       if (XINT (x, 0) > max_opno)

190         max_opno= XINT (x, 0);

191       if (XINT (x, 0) >= n_operands)

192         n_operands= 1 + XINT (x, 0);

193 

194       printf ("  x = ");

195       print_path (path);

196       printf (";\n");

197 

198       printf ("  operands[%d] =x;\n", XINT (x, 0));

199       if (XSTR (x, 1) && XSTR (x, 1)[0])

200         printf ("  if (! %s (x,%smode)) goto L%d;\n",

201               XSTR (x, 1), GET_MODE_NAME(GET_MODE (x)), fail_label);

202       link.next = path;

203        link.vecelt = -1;

204        for(i = 0; i < XVECLEN (x, 2); i++)

205       {

206         link.pos = i;

207         match_rtx (XVECEXP (x, 2, i), &link,fail_label);

208       }

209       return;

210 

211     case MATCH_PARALLEL:

212       if (XINT (x, 0) > max_opno)

213         max_opno= XINT (x, 0);

214       if (XINT (x, 0) >= n_operands)

215         n_operands= 1 + XINT (x, 0);

216 

217       printf ("  x = ");

218       print_path (path);

219       printf (";\n");

220 

221       printf ("  if (GET_CODE (x)!= PARALLEL) goto L%d;\n", fail_label);

222       printf ("  operands[%d] =x;\n", XINT (x, 0));

223       if (XSTR (x, 1) && XSTR (x, 1)[0])

224         printf ("  if (! %s (x,%smode)) goto L%d;\n",

225                XSTR(x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);

226       link.next = path;

227        link.pos = 0;

228        for(i = 0; i < XVECLEN (x, 2); i++)

229       {

230         link.vecelt = i;

231         match_rtx (XVECEXP (x, 2, i), &link,fail_label);

232       }

233       return;

234 

235     case ADDRESS:

236       match_rtx (XEXP (x, 0),path, fail_label);

237       return;

238 

239     default:

240       break;

241   }

242 

243   printf ("  x = ");

244   print_path (path);

245   printf (";\n");

246 

247   printf ("  if (GET_CODE (x)!= ");

248    print_code (code);

249    printf (") goto L%d;\n",fail_label);

250 

251   if (GET_MODE (x) != VOIDmode)

252   {

253     printf ("  if (GET_MODE (x)!= %smode) goto L%d;\n",

254            GET_MODE_NAME (GET_MODE (x)),fail_label);

255   }

256 

257   link.next = path;

258   link.vecelt = -1;

259   fmt = GET_RTX_FORMAT (code);

260   len = GET_RTX_LENGTH (code);

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

262    {

263      link.pos = i;

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

265       match_rtx (XEXP (x, i),&link, fail_label);

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

267     {

268       int j;

269       printf ("  if (XVECLEN (x,%d) != %d) goto L%d;\n",

270              i, XVECLEN (x, i),fail_label);

271        for(j = 0; j < XVECLEN (x, i); j++)

272        {

273          link.vecelt = j;

274          match_rtx (XVECEXP (x, i, j), &link,fail_label);

275       }

276     }

277     else if (fmt[i] == 'i')

278     {

279       /* Makesure that at run time `x' is the RTX we want to test.  */

280       if (i != 0)

281       {

282         printf ("  x = ");

283         print_path (path);

284         printf (";\n");

285       }

286 

287       printf ("  if (XINT (x, %d)!= %d) goto L%d;\n",

288              i, XINT (x, i), fail_label);

289     }

290     else if (fmt[i] == 'w')

291     {

292       /* Make sure that at run time `x' is the RTXwe want to test.  */

293       if (i != 0)

294       {

295         printf ("  x = ");

296         print_path (path);

297         printf (";\n");

298       }

299 

300       printf ("  if (XWINT (x, %d)!= ", i);

301       printf (HOST_WIDE_INT_PRINT_DEC, XWINT (x, i));

302       printf (") goto L%d;\n", fail_label);

303      }

304      else if (fmt[i] == 's')

305     {

306       /* Make sure that at run time `x' is the RTXwe want to test.  */

307       if (i != 0)

308       {

309         printf ("  x = ");

310         print_path (path);

311         printf (";\n");

312       }

313 

314       printf ("  if (strcmp (XSTR(x, %d), \"%s\")) goto L%d;\n",

315              i, XSTR (x, i),fail_label);

316     }

317   }

318  }

 

324  static void

325  print_path (struct link *path)                                                                       in genpeep.c

326  {

327   if (path == 0)

328     printf ("pat");

329   else if (path->vecelt >= 0)

330   {

331     printf ("XVECEXP (");

332     print_path (path->next);

333     printf (", %d, %d)", path->pos, path->vecelt);

334   }

335   else

336   {

337     printf ("XEXP (");

338     print_path (path->next);

339     printf (", %d)", path->pos);

340   }

341  }

 

For instructions, peephole output as following.

 

1     rtx

2     peephole (rtx ins1)

3     {

4       rtx insnATTRIBUTE_UNUSED, x ATTRIBUTE_UNUSED, pat ATTRIBUTE_UNUSED;

5    

6       if(NEXT_INSN (ins1)

7          && GET_CODE (NEXT_INSN (ins1)) == BARRIER)

8         return0;

9    

10      insn = ins1;

11    do { insn = NEXT_INSN(insn);

12      if (insn == 0) goto L`insn-code-num`; }

13    while (GET_CODE (insn)== NOTE

14    || (GET_CODE (insn) ==INSN

15      && (GET_CODE (PATTERN (insn)) == USE

16      || GET_CODE (PATTERN (insn)) == CLOBBER)));

17   

18    if (GET_CODE (insn) ==CODE_LABEL

19      || GET_CODE (insn) == BARRIER)

20      goto L`insn-code-num`;

21   

22    pat = PATTERN (insn);        // first insn

23    x = pat;

24    if (GET_CODE (x) !=SET) goto L`insn-code-num`;         // set

25    if (GET_CODE (x) != REG)goto L`insn-code-num`; // reg:SI 15

26    if (GET_MODE (x) !=SImode) goto L`insn-code-num`;

27    x = XEXP (pat, 0);

28    if (XINT (x, 0) != 15)goto L`insn-code-num`;

29    if (GET_CODE (x)!= PLUS) goto L`insn-code-num`;       //plus

30    if (GET_MODE (x) !=SImode) goto L`insn-code-num`;

31    if (GET_CODE (x) != REG)goto L`insn-code-num`; // reg:SI 15

32    if (GET_MODE (x) !=SImode) goto L`insn-code-num`;

33    x = XEXP (XEXP(pat,1), 0);

34    if (XINT (x, 0) != 15)goto L`insn-code-num`;

35    if (GET_CODE(x) !=CONST_INT) goto L`insn-code-num`;     //const_int

36    x = XEXP (XEXP(pat,1), 1);

37    if (XWINT (x, 0) != 4)goto L`insn-code-num`;

38   

39    do { insn = NEXT_INSN(insn);           // second insn

40      if (insn == 0) goto L`insn-code-num`; }

41    while (GET_CODE (insn)== NOTE

42    || (GET_CODE (insn) ==INSN

43      && (GET_CODE (PATTERN (insn)) == USE

44      || GET_CODE (PATTERN (insn)) == CLOBBER)));

45   

46    if (GET_CODE (insn) ==CODE_LABEL

47      || GET_CODE (insn) == BARRIER)

48      goto L`insn-code-num`;

49   

50    pat = PATTERN (insn);

51    x = pat;

52    if (GET_CODE (x) !=SET) goto L`insn-code-num`;         // set

53    x = XEXP (pat, 0);

54    operands [0] = x;

55    if (!match_operand (x,DFmode)) goto L`insn-code-num`;  //match_operand 0

56    x = XEXP (pat, 1);

57    operands [1] = x;

58    if (!match_operand (x,DFmode)) goto L`insn-code-num`;  //match_operand 1

59    if (FP_REG_P(operands[0]) && ! FP_REG_P (operands[1])) goto L`insn-code-num`;

60    // out of match_rtx

61    PATTERN (ins1) =gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (2, operands));

62    INSN_CODE (ins1) =`insn-code-num`;

63    delete_for_peephole(NEXT_INSN (ins1), insn);

64    return NEXT_INSN(insn);

65    L`insn-code-num`:

66      return 0;

67    }

68   

69    rtx peep_operand[2];

70    #endif

 

It is interesting to see that, above, when instruction sequence ismatched, the new instruction object will be created and place the sequence. In 5. Tool of genoutput, define_peephole is assignedwith unique insn-code-number and data for assemble generation is output. Seethat at line 62 above, the new instruction object is assigned with that codenumber. This number will be the index to find out the corresponding assembleoutput template.

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭