现在的位置: 首页 > 综合 > 正文

GCC后端及汇编发布(45)

2013年01月10日 ⁄ 综合 ⁄ 共 13393字 ⁄ 字号 评论关闭

15.   genpeep工具

模式define_peephole的细节参考概览 – 关于define_peephole一节,这个工具不处理define_peephole2模式,这个模式则由genemit,genoutput及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  }

 

直到399行,我们可以看到如下的输出的片段。

 

/* 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 continues to ouput the pattern in the
peephole function.

 

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  }

 

那么如果架构(对于i386系统,没有定义define_peephole)包含define_peephole,直到 93行,在调用match_rtx之前,我们可以得到如下的peephole函数。

 

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);

 

对于我们在概览 – 关于define_peephole中看到的例子,这个rtx对象的第一个孩子是如下的rtx对象,它将是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"))]

 

它是包含两条指令的parallel。

在输出的peephole中,insn是由emit_insn产生的rtx对象,PATTERN将从这个指令获取define_insn的rtx对象。

 

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       /* Make sure that at run time `x' is the RTXwe 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  }

 

对于指令,输出的peephole如下:

 

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

 

有趣的是,在上面,当指令序列匹配时,新的指令对象将被构建并加入序列在。在genoutput工具一节,define_peephole被赋予唯一的指令编号,并且输出用于汇编生成的数据。看到在上面62行, 这个新的指令对象被赋予这个指令编号。这个号码将是找出对应汇编输出模板的索引。

抱歉!评论已关闭.