1 | /* Target-dependent costs for expmed.c. |
---|---|

2 | Copyright (C) 1987-2017 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 | #ifndef EXPMED_H |

21 | #define EXPMED_H 1 |

22 | |

23 | #include "insn-codes.h" |

24 | |

25 | enum alg_code { |

26 | alg_unknown, |

27 | alg_zero, |

28 | alg_m, alg_shift, |

29 | alg_add_t_m2, |

30 | alg_sub_t_m2, |

31 | alg_add_factor, |

32 | alg_sub_factor, |

33 | alg_add_t2_m, |

34 | alg_sub_t2_m, |

35 | alg_impossible |

36 | }; |

37 | |

38 | /* Indicates the type of fixup needed after a constant multiplication. |

39 | BASIC_VARIANT means no fixup is needed, NEGATE_VARIANT means that |

40 | the result should be negated, and ADD_VARIANT means that the |

41 | multiplicand should be added to the result. */ |

42 | enum mult_variant {basic_variant, negate_variant, add_variant}; |

43 | |

44 | bool choose_mult_variant (machine_mode, HOST_WIDE_INT, |

45 | struct algorithm *, enum mult_variant *, int); |

46 | |

47 | /* This structure holds the "cost" of a multiply sequence. The |

48 | "cost" field holds the total rtx_cost of every operator in the |

49 | synthetic multiplication sequence, hence cost(a op b) is defined |

50 | as rtx_cost(op) + cost(a) + cost(b), where cost(leaf) is zero. |

51 | The "latency" field holds the minimum possible latency of the |

52 | synthetic multiply, on a hypothetical infinitely parallel CPU. |

53 | This is the critical path, or the maximum height, of the expression |

54 | tree which is the sum of rtx_costs on the most expensive path from |

55 | any leaf to the root. Hence latency(a op b) is defined as zero for |

56 | leaves and rtx_cost(op) + max(latency(a), latency(b)) otherwise. */ |

57 | |

58 | struct mult_cost { |

59 | short cost; /* Total rtx_cost of the multiplication sequence. */ |

60 | short latency; /* The latency of the multiplication sequence. */ |

61 | }; |

62 | |

63 | /* This macro is used to compare a pointer to a mult_cost against an |

64 | single integer "rtx_cost" value. This is equivalent to the macro |

65 | CHEAPER_MULT_COST(X,Z) where Z = {Y,Y}. */ |

66 | #define MULT_COST_LESS(X,Y) ((X)->cost < (Y) \ |

67 | || ((X)->cost == (Y) && (X)->latency < (Y))) |

68 | |

69 | /* This macro is used to compare two pointers to mult_costs against |

70 | each other. The macro returns true if X is cheaper than Y. |

71 | Currently, the cheaper of two mult_costs is the one with the |

72 | lower "cost". If "cost"s are tied, the lower latency is cheaper. */ |

73 | #define CHEAPER_MULT_COST(X,Y) ((X)->cost < (Y)->cost \ |

74 | || ((X)->cost == (Y)->cost \ |

75 | && (X)->latency < (Y)->latency)) |

76 | |

77 | /* This structure records a sequence of operations. |

78 | `ops' is the number of operations recorded. |

79 | `cost' is their total cost. |

80 | The operations are stored in `op' and the corresponding |

81 | logarithms of the integer coefficients in `log'. |

82 | |

83 | These are the operations: |

84 | alg_zero total := 0; |

85 | alg_m total := multiplicand; |

86 | alg_shift total := total * coeff |

87 | alg_add_t_m2 total := total + multiplicand * coeff; |

88 | alg_sub_t_m2 total := total - multiplicand * coeff; |

89 | alg_add_factor total := total * coeff + total; |

90 | alg_sub_factor total := total * coeff - total; |

91 | alg_add_t2_m total := total * coeff + multiplicand; |

92 | alg_sub_t2_m total := total * coeff - multiplicand; |

93 | |

94 | The first operand must be either alg_zero or alg_m. */ |

95 | |

96 | struct algorithm |

97 | { |

98 | struct mult_cost cost; |

99 | short ops; |

100 | /* The size of the OP and LOG fields are not directly related to the |

101 | word size, but the worst-case algorithms will be if we have few |

102 | consecutive ones or zeros, i.e., a multiplicand like 10101010101... |

103 | In that case we will generate shift-by-2, add, shift-by-2, add,..., |

104 | in total wordsize operations. */ |

105 | enum alg_code op[MAX_BITS_PER_WORD]; |

106 | char log[MAX_BITS_PER_WORD]; |

107 | }; |

108 | |

109 | /* The entry for our multiplication cache/hash table. */ |

110 | struct alg_hash_entry { |

111 | /* The number we are multiplying by. */ |

112 | unsigned HOST_WIDE_INT t; |

113 | |

114 | /* The mode in which we are multiplying something by T. */ |

115 | machine_mode mode; |

116 | |

117 | /* The best multiplication algorithm for t. */ |

118 | enum alg_code alg; |

119 | |

120 | /* The cost of multiplication if ALG_CODE is not alg_impossible. |

121 | Otherwise, the cost within which multiplication by T is |

122 | impossible. */ |

123 | struct mult_cost cost; |

124 | |

125 | /* Optimized for speed? */ |

126 | bool speed; |

127 | }; |

128 | |

129 | /* The number of cache/hash entries. */ |

130 | #if HOST_BITS_PER_WIDE_INT == 64 |

131 | #define NUM_ALG_HASH_ENTRIES 1031 |

132 | #else |

133 | #define NUM_ALG_HASH_ENTRIES 307 |

134 | #endif |

135 | |

136 | #define NUM_MODE_INT \ |

137 | (MAX_MODE_INT - MIN_MODE_INT + 1) |

138 | #define NUM_MODE_PARTIAL_INT \ |

139 | (MIN_MODE_PARTIAL_INT == E_VOIDmode ? 0 \ |

140 | : MAX_MODE_PARTIAL_INT - MIN_MODE_PARTIAL_INT + 1) |

141 | #define NUM_MODE_VECTOR_INT \ |

142 | (MIN_MODE_VECTOR_INT == E_VOIDmode ? 0 \ |

143 | : MAX_MODE_VECTOR_INT - MIN_MODE_VECTOR_INT + 1) |

144 | |

145 | #define NUM_MODE_IP_INT (NUM_MODE_INT + NUM_MODE_PARTIAL_INT) |

146 | #define NUM_MODE_IPV_INT (NUM_MODE_IP_INT + NUM_MODE_VECTOR_INT) |

147 | |

148 | struct expmed_op_cheap { |

149 | bool cheap[2][NUM_MODE_IPV_INT]; |

150 | }; |

151 | |

152 | struct expmed_op_costs { |

153 | int cost[2][NUM_MODE_IPV_INT]; |

154 | }; |

155 | |

156 | /* Target-dependent globals. */ |

157 | struct target_expmed { |

158 | /* Each entry of ALG_HASH caches alg_code for some integer. This is |

159 | actually a hash table. If we have a collision, that the older |

160 | entry is kicked out. */ |

161 | struct alg_hash_entry x_alg_hash[NUM_ALG_HASH_ENTRIES]; |

162 | |

163 | /* True if x_alg_hash might already have been used. */ |

164 | bool x_alg_hash_used_p; |

165 | |

166 | /* Nonzero means divides or modulus operations are relatively cheap for |

167 | powers of two, so don't use branches; emit the operation instead. |

168 | Usually, this will mean that the MD file will emit non-branch |

169 | sequences. */ |

170 | struct expmed_op_cheap x_sdiv_pow2_cheap; |

171 | struct expmed_op_cheap x_smod_pow2_cheap; |

172 | |

173 | /* Cost of various pieces of RTL. Note that some of these are indexed by |

174 | shift count and some by mode. */ |

175 | int x_zero_cost[2]; |

176 | struct expmed_op_costs x_add_cost; |

177 | struct expmed_op_costs x_neg_cost; |

178 | struct expmed_op_costs x_shift_cost[MAX_BITS_PER_WORD]; |

179 | struct expmed_op_costs x_shiftadd_cost[MAX_BITS_PER_WORD]; |

180 | struct expmed_op_costs x_shiftsub0_cost[MAX_BITS_PER_WORD]; |

181 | struct expmed_op_costs x_shiftsub1_cost[MAX_BITS_PER_WORD]; |

182 | struct expmed_op_costs x_mul_cost; |

183 | struct expmed_op_costs x_sdiv_cost; |

184 | struct expmed_op_costs x_udiv_cost; |

185 | int x_mul_widen_cost[2][NUM_MODE_INT]; |

186 | int x_mul_highpart_cost[2][NUM_MODE_INT]; |

187 | |

188 | /* Conversion costs are only defined between two scalar integer modes |

189 | of different sizes. The first machine mode is the destination mode, |

190 | and the second is the source mode. */ |

191 | int x_convert_cost[2][NUM_MODE_IP_INT][NUM_MODE_IP_INT]; |

192 | }; |

193 | |

194 | extern struct target_expmed default_target_expmed; |

195 | #if SWITCHABLE_TARGET |

196 | extern struct target_expmed *this_target_expmed; |

197 | #else |

198 | #define this_target_expmed (&default_target_expmed) |

199 | #endif |

200 | |

201 | /* Return a pointer to the alg_hash_entry at IDX. */ |

202 | |

203 | static inline struct alg_hash_entry * |

204 | alg_hash_entry_ptr (int idx) |

205 | { |

206 | return &this_target_expmed->x_alg_hash[idx]; |

207 | } |

208 | |

209 | /* Return true if the x_alg_hash field might have been used. */ |

210 | |

211 | static inline bool |

212 | alg_hash_used_p (void) |

213 | { |

214 | return this_target_expmed->x_alg_hash_used_p; |

215 | } |

216 | |

217 | /* Set whether the x_alg_hash field might have been used. */ |

218 | |

219 | static inline void |

220 | set_alg_hash_used_p (bool usedp) |

221 | { |

222 | this_target_expmed->x_alg_hash_used_p = usedp; |

223 | } |

224 | |

225 | /* Compute an index into the cost arrays by mode class. */ |

226 | |

227 | static inline int |

228 | expmed_mode_index (machine_mode mode) |

229 | { |

230 | switch (GET_MODE_CLASS (mode)) |

231 | { |

232 | case MODE_INT: |

233 | return mode - MIN_MODE_INT; |

234 | case MODE_PARTIAL_INT: |

235 | /* If there are no partial integer modes, help the compiler |

236 | to figure out this will never happen. See PR59934. */ |

237 | if (MIN_MODE_PARTIAL_INT != VOIDmode) |

238 | return mode - MIN_MODE_PARTIAL_INT + NUM_MODE_INT; |

239 | break; |

240 | case MODE_VECTOR_INT: |

241 | /* If there are no vector integer modes, help the compiler |

242 | to figure out this will never happen. See PR59934. */ |

243 | if (MIN_MODE_VECTOR_INT != VOIDmode) |

244 | return mode - MIN_MODE_VECTOR_INT + NUM_MODE_IP_INT; |

245 | break; |

246 | default: |

247 | break; |

248 | } |

249 | gcc_unreachable (); |

250 | } |

251 | |

252 | /* Return a pointer to a boolean contained in EOC indicating whether |

253 | a particular operation performed in MODE is cheap when optimizing |

254 | for SPEED. */ |

255 | |

256 | static inline bool * |

257 | expmed_op_cheap_ptr (struct expmed_op_cheap *eoc, bool speed, |

258 | machine_mode mode) |

259 | { |

260 | int idx = expmed_mode_index (mode); |

261 | return &eoc->cheap[speed][idx]; |

262 | } |

263 | |

264 | /* Return a pointer to a cost contained in COSTS when a particular |

265 | operation is performed in MODE when optimizing for SPEED. */ |

266 | |

267 | static inline int * |

268 | expmed_op_cost_ptr (struct expmed_op_costs *costs, bool speed, |

269 | machine_mode mode) |

270 | { |

271 | int idx = expmed_mode_index (mode); |

272 | return &costs->cost[speed][idx]; |

273 | } |

274 | |

275 | /* Subroutine of {set_,}sdiv_pow2_cheap. Not to be used otherwise. */ |

276 | |

277 | static inline bool * |

278 | sdiv_pow2_cheap_ptr (bool speed, machine_mode mode) |

279 | { |

280 | return expmed_op_cheap_ptr (&this_target_expmed->x_sdiv_pow2_cheap, |

281 | speed, mode); |

282 | } |

283 | |

284 | /* Set whether a signed division by a power of 2 is cheap in MODE |

285 | when optimizing for SPEED. */ |

286 | |

287 | static inline void |

288 | set_sdiv_pow2_cheap (bool speed, machine_mode mode, bool cheap_p) |

289 | { |

290 | *sdiv_pow2_cheap_ptr (speed, mode) = cheap_p; |

291 | } |

292 | |

293 | /* Return whether a signed division by a power of 2 is cheap in MODE |

294 | when optimizing for SPEED. */ |

295 | |

296 | static inline bool |

297 | sdiv_pow2_cheap (bool speed, machine_mode mode) |

298 | { |

299 | return *sdiv_pow2_cheap_ptr (speed, mode); |

300 | } |

301 | |

302 | /* Subroutine of {set_,}smod_pow2_cheap. Not to be used otherwise. */ |

303 | |

304 | static inline bool * |

305 | smod_pow2_cheap_ptr (bool speed, machine_mode mode) |

306 | { |

307 | return expmed_op_cheap_ptr (&this_target_expmed->x_smod_pow2_cheap, |

308 | speed, mode); |

309 | } |

310 | |

311 | /* Set whether a signed modulo by a power of 2 is CHEAP in MODE when |

312 | optimizing for SPEED. */ |

313 | |

314 | static inline void |

315 | set_smod_pow2_cheap (bool speed, machine_mode mode, bool cheap) |

316 | { |

317 | *smod_pow2_cheap_ptr (speed, mode) = cheap; |

318 | } |

319 | |

320 | /* Return whether a signed modulo by a power of 2 is cheap in MODE |

321 | when optimizing for SPEED. */ |

322 | |

323 | static inline bool |

324 | smod_pow2_cheap (bool speed, machine_mode mode) |

325 | { |

326 | return *smod_pow2_cheap_ptr (speed, mode); |

327 | } |

328 | |

329 | /* Subroutine of {set_,}zero_cost. Not to be used otherwise. */ |

330 | |

331 | static inline int * |

332 | zero_cost_ptr (bool speed) |

333 | { |

334 | return &this_target_expmed->x_zero_cost[speed]; |

335 | } |

336 | |

337 | /* Set the COST of loading zero when optimizing for SPEED. */ |

338 | |

339 | static inline void |

340 | set_zero_cost (bool speed, int cost) |

341 | { |

342 | *zero_cost_ptr (speed) = cost; |

343 | } |

344 | |

345 | /* Return the COST of loading zero when optimizing for SPEED. */ |

346 | |

347 | static inline int |

348 | zero_cost (bool speed) |

349 | { |

350 | return *zero_cost_ptr (speed); |

351 | } |

352 | |

353 | /* Subroutine of {set_,}add_cost. Not to be used otherwise. */ |

354 | |

355 | static inline int * |

356 | add_cost_ptr (bool speed, machine_mode mode) |

357 | { |

358 | return expmed_op_cost_ptr (&this_target_expmed->x_add_cost, speed, mode); |

359 | } |

360 | |

361 | /* Set the COST of computing an add in MODE when optimizing for SPEED. */ |

362 | |

363 | static inline void |

364 | set_add_cost (bool speed, machine_mode mode, int cost) |

365 | { |

366 | *add_cost_ptr (speed, mode) = cost; |

367 | } |

368 | |

369 | /* Return the cost of computing an add in MODE when optimizing for SPEED. */ |

370 | |

371 | static inline int |

372 | add_cost (bool speed, machine_mode mode) |

373 | { |

374 | return *add_cost_ptr (speed, mode); |

375 | } |

376 | |

377 | /* Subroutine of {set_,}neg_cost. Not to be used otherwise. */ |

378 | |

379 | static inline int * |

380 | neg_cost_ptr (bool speed, machine_mode mode) |

381 | { |

382 | return expmed_op_cost_ptr (&this_target_expmed->x_neg_cost, speed, mode); |

383 | } |

384 | |

385 | /* Set the COST of computing a negation in MODE when optimizing for SPEED. */ |

386 | |

387 | static inline void |

388 | set_neg_cost (bool speed, machine_mode mode, int cost) |

389 | { |

390 | *neg_cost_ptr (speed, mode) = cost; |

391 | } |

392 | |

393 | /* Return the cost of computing a negation in MODE when optimizing for |

394 | SPEED. */ |

395 | |

396 | static inline int |

397 | neg_cost (bool speed, machine_mode mode) |

398 | { |

399 | return *neg_cost_ptr (speed, mode); |

400 | } |

401 | |

402 | /* Subroutine of {set_,}shift_cost. Not to be used otherwise. */ |

403 | |

404 | static inline int * |

405 | shift_cost_ptr (bool speed, machine_mode mode, int bits) |

406 | { |

407 | return expmed_op_cost_ptr (&this_target_expmed->x_shift_cost[bits], |

408 | speed, mode); |

409 | } |

410 | |

411 | /* Set the COST of doing a shift in MODE by BITS when optimizing for SPEED. */ |

412 | |

413 | static inline void |

414 | set_shift_cost (bool speed, machine_mode mode, int bits, int cost) |

415 | { |

416 | *shift_cost_ptr (speed, mode, bits) = cost; |

417 | } |

418 | |

419 | /* Return the cost of doing a shift in MODE by BITS when optimizing for |

420 | SPEED. */ |

421 | |

422 | static inline int |

423 | shift_cost (bool speed, machine_mode mode, int bits) |

424 | { |

425 | return *shift_cost_ptr (speed, mode, bits); |

426 | } |

427 | |

428 | /* Subroutine of {set_,}shiftadd_cost. Not to be used otherwise. */ |

429 | |

430 | static inline int * |

431 | shiftadd_cost_ptr (bool speed, machine_mode mode, int bits) |

432 | { |

433 | return expmed_op_cost_ptr (&this_target_expmed->x_shiftadd_cost[bits], |

434 | speed, mode); |

435 | } |

436 | |

437 | /* Set the COST of doing a shift in MODE by BITS followed by an add when |

438 | optimizing for SPEED. */ |

439 | |

440 | static inline void |

441 | set_shiftadd_cost (bool speed, machine_mode mode, int bits, int cost) |

442 | { |

443 | *shiftadd_cost_ptr (speed, mode, bits) = cost; |

444 | } |

445 | |

446 | /* Return the cost of doing a shift in MODE by BITS followed by an add |

447 | when optimizing for SPEED. */ |

448 | |

449 | static inline int |

450 | shiftadd_cost (bool speed, machine_mode mode, int bits) |

451 | { |

452 | return *shiftadd_cost_ptr (speed, mode, bits); |

453 | } |

454 | |

455 | /* Subroutine of {set_,}shiftsub0_cost. Not to be used otherwise. */ |

456 | |

457 | static inline int * |

458 | shiftsub0_cost_ptr (bool speed, machine_mode mode, int bits) |

459 | { |

460 | return expmed_op_cost_ptr (&this_target_expmed->x_shiftsub0_cost[bits], |

461 | speed, mode); |

462 | } |

463 | |

464 | /* Set the COST of doing a shift in MODE by BITS and then subtracting a |

465 | value when optimizing for SPEED. */ |

466 | |

467 | static inline void |

468 | set_shiftsub0_cost (bool speed, machine_mode mode, int bits, int cost) |

469 | { |

470 | *shiftsub0_cost_ptr (speed, mode, bits) = cost; |

471 | } |

472 | |

473 | /* Return the cost of doing a shift in MODE by BITS and then subtracting |

474 | a value when optimizing for SPEED. */ |

475 | |

476 | static inline int |

477 | shiftsub0_cost (bool speed, machine_mode mode, int bits) |

478 | { |

479 | return *shiftsub0_cost_ptr (speed, mode, bits); |

480 | } |

481 | |

482 | /* Subroutine of {set_,}shiftsub1_cost. Not to be used otherwise. */ |

483 | |

484 | static inline int * |

485 | shiftsub1_cost_ptr (bool speed, machine_mode mode, int bits) |

486 | { |

487 | return expmed_op_cost_ptr (&this_target_expmed->x_shiftsub1_cost[bits], |

488 | speed, mode); |

489 | } |

490 | |

491 | /* Set the COST of subtracting a shift in MODE by BITS from a value when |

492 | optimizing for SPEED. */ |

493 | |

494 | static inline void |

495 | set_shiftsub1_cost (bool speed, machine_mode mode, int bits, int cost) |

496 | { |

497 | *shiftsub1_cost_ptr (speed, mode, bits) = cost; |

498 | } |

499 | |

500 | /* Return the cost of subtracting a shift in MODE by BITS from a value |

501 | when optimizing for SPEED. */ |

502 | |

503 | static inline int |

504 | shiftsub1_cost (bool speed, machine_mode mode, int bits) |

505 | { |

506 | return *shiftsub1_cost_ptr (speed, mode, bits); |

507 | } |

508 | |

509 | /* Subroutine of {set_,}mul_cost. Not to be used otherwise. */ |

510 | |

511 | static inline int * |

512 | mul_cost_ptr (bool speed, machine_mode mode) |

513 | { |

514 | return expmed_op_cost_ptr (&this_target_expmed->x_mul_cost, speed, mode); |

515 | } |

516 | |

517 | /* Set the COST of doing a multiplication in MODE when optimizing for |

518 | SPEED. */ |

519 | |

520 | static inline void |

521 | set_mul_cost (bool speed, machine_mode mode, int cost) |

522 | { |

523 | *mul_cost_ptr (speed, mode) = cost; |

524 | } |

525 | |

526 | /* Return the cost of doing a multiplication in MODE when optimizing |

527 | for SPEED. */ |

528 | |

529 | static inline int |

530 | mul_cost (bool speed, machine_mode mode) |

531 | { |

532 | return *mul_cost_ptr (speed, mode); |

533 | } |

534 | |

535 | /* Subroutine of {set_,}sdiv_cost. Not to be used otherwise. */ |

536 | |

537 | static inline int * |

538 | sdiv_cost_ptr (bool speed, machine_mode mode) |

539 | { |

540 | return expmed_op_cost_ptr (&this_target_expmed->x_sdiv_cost, speed, mode); |

541 | } |

542 | |

543 | /* Set the COST of doing a signed division in MODE when optimizing |

544 | for SPEED. */ |

545 | |

546 | static inline void |

547 | set_sdiv_cost (bool speed, machine_mode mode, int cost) |

548 | { |

549 | *sdiv_cost_ptr (speed, mode) = cost; |

550 | } |

551 | |

552 | /* Return the cost of doing a signed division in MODE when optimizing |

553 | for SPEED. */ |

554 | |

555 | static inline int |

556 | sdiv_cost (bool speed, machine_mode mode) |

557 | { |

558 | return *sdiv_cost_ptr (speed, mode); |

559 | } |

560 | |

561 | /* Subroutine of {set_,}udiv_cost. Not to be used otherwise. */ |

562 | |

563 | static inline int * |

564 | udiv_cost_ptr (bool speed, machine_mode mode) |

565 | { |

566 | return expmed_op_cost_ptr (&this_target_expmed->x_udiv_cost, speed, mode); |

567 | } |

568 | |

569 | /* Set the COST of doing an unsigned division in MODE when optimizing |

570 | for SPEED. */ |

571 | |

572 | static inline void |

573 | set_udiv_cost (bool speed, machine_mode mode, int cost) |

574 | { |

575 | *udiv_cost_ptr (speed, mode) = cost; |

576 | } |

577 | |

578 | /* Return the cost of doing an unsigned division in MODE when |

579 | optimizing for SPEED. */ |

580 | |

581 | static inline int |

582 | udiv_cost (bool speed, machine_mode mode) |

583 | { |

584 | return *udiv_cost_ptr (speed, mode); |

585 | } |

586 | |

587 | /* Subroutine of {set_,}mul_widen_cost. Not to be used otherwise. */ |

588 | |

589 | static inline int * |

590 | mul_widen_cost_ptr (bool speed, machine_mode mode) |

591 | { |

592 | gcc_assert (GET_MODE_CLASS (mode) == MODE_INT); |

593 | |

594 | return &this_target_expmed->x_mul_widen_cost[speed][mode - MIN_MODE_INT]; |

595 | } |

596 | |

597 | /* Set the COST for computing a widening multiplication in MODE when |

598 | optimizing for SPEED. */ |

599 | |

600 | static inline void |

601 | set_mul_widen_cost (bool speed, machine_mode mode, int cost) |

602 | { |

603 | *mul_widen_cost_ptr (speed, mode) = cost; |

604 | } |

605 | |

606 | /* Return the cost for computing a widening multiplication in MODE when |

607 | optimizing for SPEED. */ |

608 | |

609 | static inline int |

610 | mul_widen_cost (bool speed, machine_mode mode) |

611 | { |

612 | return *mul_widen_cost_ptr (speed, mode); |

613 | } |

614 | |

615 | /* Subroutine of {set_,}mul_highpart_cost. Not to be used otherwise. */ |

616 | |

617 | static inline int * |

618 | mul_highpart_cost_ptr (bool speed, machine_mode mode) |

619 | { |

620 | gcc_assert (GET_MODE_CLASS (mode) == MODE_INT); |

621 | int m = mode - MIN_MODE_INT; |

622 | gcc_assert (m < NUM_MODE_INT); |

623 | |

624 | return &this_target_expmed->x_mul_highpart_cost[speed][m]; |

625 | } |

626 | |

627 | /* Set the COST for computing the high part of a multiplication in MODE |

628 | when optimizing for SPEED. */ |

629 | |

630 | static inline void |

631 | set_mul_highpart_cost (bool speed, machine_mode mode, int cost) |

632 | { |

633 | *mul_highpart_cost_ptr (speed, mode) = cost; |

634 | } |

635 | |

636 | /* Return the cost for computing the high part of a multiplication in MODE |

637 | when optimizing for SPEED. */ |

638 | |

639 | static inline int |

640 | mul_highpart_cost (bool speed, machine_mode mode) |

641 | { |

642 | return *mul_highpart_cost_ptr (speed, mode); |

643 | } |

644 | |

645 | /* Subroutine of {set_,}convert_cost. Not to be used otherwise. */ |

646 | |

647 | static inline int * |

648 | convert_cost_ptr (machine_mode to_mode, machine_mode from_mode, |

649 | bool speed) |

650 | { |

651 | int to_idx = expmed_mode_index (to_mode); |

652 | int from_idx = expmed_mode_index (from_mode); |

653 | |

654 | gcc_assert (IN_RANGE (to_idx, 0, NUM_MODE_IP_INT - 1)); |

655 | gcc_assert (IN_RANGE (from_idx, 0, NUM_MODE_IP_INT - 1)); |

656 | |

657 | return &this_target_expmed->x_convert_cost[speed][to_idx][from_idx]; |

658 | } |

659 | |

660 | /* Set the COST for converting from FROM_MODE to TO_MODE when optimizing |

661 | for SPEED. */ |

662 | |

663 | static inline void |

664 | set_convert_cost (machine_mode to_mode, machine_mode from_mode, |

665 | bool speed, int cost) |

666 | { |

667 | *convert_cost_ptr (to_mode, from_mode, speed) = cost; |

668 | } |

669 | |

670 | /* Return the cost for converting from FROM_MODE to TO_MODE when optimizing |

671 | for SPEED. */ |

672 | |

673 | static inline int |

674 | convert_cost (machine_mode to_mode, machine_mode from_mode, |

675 | bool speed) |

676 | { |

677 | return *convert_cost_ptr (to_mode, from_mode, speed); |

678 | } |

679 | |

680 | extern int mult_by_coeff_cost (HOST_WIDE_INT, machine_mode, bool); |

681 | extern rtx emit_cstore (rtx target, enum insn_code icode, enum rtx_code code, |

682 | machine_mode mode, machine_mode compare_mode, |

683 | int unsignedp, rtx x, rtx y, int normalizep, |

684 | machine_mode target_mode); |

685 | |

686 | /* Arguments MODE, RTX: return an rtx for the negation of that value. |

687 | May emit insns. */ |

688 | extern rtx negate_rtx (machine_mode, rtx); |

689 | |

690 | /* Arguments MODE, RTX: return an rtx for the flipping of that value. |

691 | May emit insns. */ |

692 | extern rtx flip_storage_order (machine_mode, rtx); |

693 | |

694 | /* Expand a logical AND operation. */ |

695 | extern rtx expand_and (machine_mode, rtx, rtx, rtx); |

696 | |

697 | /* Emit a store-flag operation. */ |

698 | extern rtx emit_store_flag (rtx, enum rtx_code, rtx, rtx, machine_mode, |

699 | int, int); |

700 | |

701 | /* Like emit_store_flag, but always succeeds. */ |

702 | extern rtx emit_store_flag_force (rtx, enum rtx_code, rtx, rtx, |

703 | machine_mode, int, int); |

704 | |

705 | /* Choose a minimal N + 1 bit approximation to 1/D that can be used to |

706 | replace division by D, and put the least significant N bits of the result |

707 | in *MULTIPLIER_PTR and return the most significant bit. */ |

708 | extern unsigned HOST_WIDE_INT choose_multiplier (unsigned HOST_WIDE_INT, int, |

709 | int, unsigned HOST_WIDE_INT *, |

710 | int *, int *); |

711 | |

712 | #ifdef TREE_CODE |

713 | extern rtx expand_variable_shift (enum tree_code, machine_mode, |

714 | rtx, tree, rtx, int); |

715 | extern rtx expand_shift (enum tree_code, machine_mode, rtx, int, rtx, |

716 | int); |

717 | extern rtx expand_divmod (int, enum tree_code, machine_mode, rtx, rtx, |

718 | rtx, int); |

719 | #endif |

720 | |

721 | extern void store_bit_field (rtx, unsigned HOST_WIDE_INT, |

722 | unsigned HOST_WIDE_INT, |

723 | unsigned HOST_WIDE_INT, |

724 | unsigned HOST_WIDE_INT, |

725 | machine_mode, rtx, bool); |

726 | extern rtx extract_bit_field (rtx, unsigned HOST_WIDE_INT, |

727 | unsigned HOST_WIDE_INT, int, rtx, |

728 | machine_mode, machine_mode, bool, rtx *); |

729 | extern rtx extract_low_bits (machine_mode, machine_mode, rtx); |

730 | extern rtx expand_mult (machine_mode, rtx, rtx, rtx, int, bool = false); |

731 | extern rtx expand_mult_highpart_adjust (scalar_int_mode, rtx, rtx, rtx, |

732 | rtx, int); |

733 | |

734 | #endif // EXPMED_H |

735 |