ree.c 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301
  1. /* Redundant Extension Elimination pass for the GNU compiler.
  2. Copyright (C) 2010-2015 Free Software Foundation, Inc.
  3. Contributed by Ilya Enkovich (ilya.enkovich@intel.com)
  4. Based on the Redundant Zero-extension elimination pass contributed by
  5. Sriraman Tallam (tmsriram@google.com) and Silvius Rus (rus@google.com).
  6. This file is part of GCC.
  7. GCC is free software; you can redistribute it and/or modify it under
  8. the terms of the GNU General Public License as published by the Free
  9. Software Foundation; either version 3, or (at your option) any later
  10. version.
  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. You should have received a copy of the GNU General Public License
  16. along with GCC; see the file COPYING3. If not see
  17. <http://www.gnu.org/licenses/>. */
  18. /* Problem Description :
  19. --------------------
  20. This pass is intended to remove redundant extension instructions.
  21. Such instructions appear for different reasons. We expect some of
  22. them due to implicit zero-extension in 64-bit registers after writing
  23. to their lower 32-bit half (e.g. for the x86-64 architecture).
  24. Another possible reason is a type cast which follows a load (for
  25. instance a register restore) and which can be combined into a single
  26. instruction, and for which earlier local passes, e.g. the combiner,
  27. weren't able to optimize.
  28. How does this pass work ?
  29. --------------------------
  30. This pass is run after register allocation. Hence, all registers that
  31. this pass deals with are hard registers. This pass first looks for an
  32. extension instruction that could possibly be redundant. Such extension
  33. instructions show up in RTL with the pattern :
  34. (set (reg:<SWI248> x) (any_extend:<SWI248> (reg:<SWI124> x))),
  35. where x can be any hard register.
  36. Now, this pass tries to eliminate this instruction by merging the
  37. extension with the definitions of register x. For instance, if
  38. one of the definitions of register x was :
  39. (set (reg:SI x) (plus:SI (reg:SI z1) (reg:SI z2))),
  40. followed by extension :
  41. (set (reg:DI x) (zero_extend:DI (reg:SI x)))
  42. then the combination converts this into :
  43. (set (reg:DI x) (zero_extend:DI (plus:SI (reg:SI z1) (reg:SI z2)))).
  44. If all the merged definitions are recognizable assembly instructions,
  45. the extension is effectively eliminated.
  46. For example, for the x86-64 architecture, implicit zero-extensions
  47. are captured with appropriate patterns in the i386.md file. Hence,
  48. these merged definition can be matched to a single assembly instruction.
  49. The original extension instruction is then deleted if all the
  50. definitions can be merged.
  51. However, there are cases where the definition instruction cannot be
  52. merged with an extension. Examples are CALL instructions. In such
  53. cases, the original extension is not redundant and this pass does
  54. not delete it.
  55. Handling conditional moves :
  56. ----------------------------
  57. Architectures like x86-64 support conditional moves whose semantics for
  58. extension differ from the other instructions. For instance, the
  59. instruction *cmov ebx, eax*
  60. zero-extends eax onto rax only when the move from ebx to eax happens.
  61. Otherwise, eax may not be zero-extended. Consider conditional moves as
  62. RTL instructions of the form
  63. (set (reg:SI x) (if_then_else (cond) (reg:SI y) (reg:SI z))).
  64. This pass tries to merge an extension with a conditional move by
  65. actually merging the definitions of y and z with an extension and then
  66. converting the conditional move into :
  67. (set (reg:DI x) (if_then_else (cond) (reg:DI y) (reg:DI z))).
  68. Since registers y and z are extended, register x will also be extended
  69. after the conditional move. Note that this step has to be done
  70. transitively since the definition of a conditional copy can be
  71. another conditional copy.
  72. Motivating Example I :
  73. ---------------------
  74. For this program :
  75. **********************************************
  76. bad_code.c
  77. int mask[1000];
  78. int foo(unsigned x)
  79. {
  80. if (x < 10)
  81. x = x * 45;
  82. else
  83. x = x * 78;
  84. return mask[x];
  85. }
  86. **********************************************
  87. $ gcc -O2 bad_code.c
  88. ........
  89. 400315: b8 4e 00 00 00 mov $0x4e,%eax
  90. 40031a: 0f af f8 imul %eax,%edi
  91. 40031d: 89 ff mov %edi,%edi - useless extension
  92. 40031f: 8b 04 bd 60 19 40 00 mov 0x401960(,%rdi,4),%eax
  93. 400326: c3 retq
  94. ......
  95. 400330: ba 2d 00 00 00 mov $0x2d,%edx
  96. 400335: 0f af fa imul %edx,%edi
  97. 400338: 89 ff mov %edi,%edi - useless extension
  98. 40033a: 8b 04 bd 60 19 40 00 mov 0x401960(,%rdi,4),%eax
  99. 400341: c3 retq
  100. $ gcc -O2 -free bad_code.c
  101. ......
  102. 400315: 6b ff 4e imul $0x4e,%edi,%edi
  103. 400318: 8b 04 bd 40 19 40 00 mov 0x401940(,%rdi,4),%eax
  104. 40031f: c3 retq
  105. 400320: 6b ff 2d imul $0x2d,%edi,%edi
  106. 400323: 8b 04 bd 40 19 40 00 mov 0x401940(,%rdi,4),%eax
  107. 40032a: c3 retq
  108. Motivating Example II :
  109. ---------------------
  110. Here is an example with a conditional move.
  111. For this program :
  112. **********************************************
  113. unsigned long long foo(unsigned x , unsigned y)
  114. {
  115. unsigned z;
  116. if (x > 100)
  117. z = x + y;
  118. else
  119. z = x - y;
  120. return (unsigned long long)(z);
  121. }
  122. $ gcc -O2 bad_code.c
  123. ............
  124. 400360: 8d 14 3e lea (%rsi,%rdi,1),%edx
  125. 400363: 89 f8 mov %edi,%eax
  126. 400365: 29 f0 sub %esi,%eax
  127. 400367: 83 ff 65 cmp $0x65,%edi
  128. 40036a: 0f 43 c2 cmovae %edx,%eax
  129. 40036d: 89 c0 mov %eax,%eax - useless extension
  130. 40036f: c3 retq
  131. $ gcc -O2 -free bad_code.c
  132. .............
  133. 400360: 89 fa mov %edi,%edx
  134. 400362: 8d 04 3e lea (%rsi,%rdi,1),%eax
  135. 400365: 29 f2 sub %esi,%edx
  136. 400367: 83 ff 65 cmp $0x65,%edi
  137. 40036a: 89 d6 mov %edx,%esi
  138. 40036c: 48 0f 42 c6 cmovb %rsi,%rax
  139. 400370: c3 retq
  140. Motivating Example III :
  141. ---------------------
  142. Here is an example with a type cast.
  143. For this program :
  144. **********************************************
  145. void test(int size, unsigned char *in, unsigned char *out)
  146. {
  147. int i;
  148. unsigned char xr, xg, xy=0;
  149. for (i = 0; i < size; i++) {
  150. xr = *in++;
  151. xg = *in++;
  152. xy = (unsigned char) ((19595*xr + 38470*xg) >> 16);
  153. *out++ = xy;
  154. }
  155. }
  156. $ gcc -O2 bad_code.c
  157. ............
  158. 10: 0f b6 0e movzbl (%rsi),%ecx
  159. 13: 0f b6 46 01 movzbl 0x1(%rsi),%eax
  160. 17: 48 83 c6 02 add $0x2,%rsi
  161. 1b: 0f b6 c9 movzbl %cl,%ecx - useless extension
  162. 1e: 0f b6 c0 movzbl %al,%eax - useless extension
  163. 21: 69 c9 8b 4c 00 00 imul $0x4c8b,%ecx,%ecx
  164. 27: 69 c0 46 96 00 00 imul $0x9646,%eax,%eax
  165. $ gcc -O2 -free bad_code.c
  166. .............
  167. 10: 0f b6 0e movzbl (%rsi),%ecx
  168. 13: 0f b6 46 01 movzbl 0x1(%rsi),%eax
  169. 17: 48 83 c6 02 add $0x2,%rsi
  170. 1b: 69 c9 8b 4c 00 00 imul $0x4c8b,%ecx,%ecx
  171. 21: 69 c0 46 96 00 00 imul $0x9646,%eax,%eax
  172. Usefulness :
  173. ----------
  174. The original redundant zero-extension elimination pass reported reduction
  175. of the dynamic instruction count of a compression benchmark by 2.8% and
  176. improvement of its run time by about 1%.
  177. The additional performance gain with the enhanced pass is mostly expected
  178. on in-order architectures where redundancy cannot be compensated by out of
  179. order execution. Measurements showed up to 10% performance gain (reduced
  180. run time) on EEMBC 2.0 benchmarks on Atom processor with geomean performance
  181. gain 1%. */
  182. #include "config.h"
  183. #include "system.h"
  184. #include "coretypes.h"
  185. #include "tm.h"
  186. #include "rtl.h"
  187. #include "hash-set.h"
  188. #include "machmode.h"
  189. #include "vec.h"
  190. #include "double-int.h"
  191. #include "input.h"
  192. #include "alias.h"
  193. #include "symtab.h"
  194. #include "wide-int.h"
  195. #include "inchash.h"
  196. #include "tree.h"
  197. #include "tm_p.h"
  198. #include "flags.h"
  199. #include "regs.h"
  200. #include "hard-reg-set.h"
  201. #include "predict.h"
  202. #include "function.h"
  203. #include "dominance.h"
  204. #include "cfg.h"
  205. #include "cfgrtl.h"
  206. #include "basic-block.h"
  207. #include "insn-config.h"
  208. #include "hashtab.h"
  209. #include "statistics.h"
  210. #include "real.h"
  211. #include "fixed-value.h"
  212. #include "expmed.h"
  213. #include "dojump.h"
  214. #include "explow.h"
  215. #include "calls.h"
  216. #include "emit-rtl.h"
  217. #include "varasm.h"
  218. #include "stmt.h"
  219. #include "expr.h"
  220. #include "insn-attr.h"
  221. #include "recog.h"
  222. #include "diagnostic-core.h"
  223. #include "target.h"
  224. #include "insn-codes.h"
  225. #include "optabs.h"
  226. #include "rtlhooks-def.h"
  227. #include "params.h"
  228. #include "tree-pass.h"
  229. #include "df.h"
  230. #include "hash-map.h"
  231. #include "is-a.h"
  232. #include "plugin-api.h"
  233. #include "ipa-ref.h"
  234. #include "cgraph.h"
  235. /* This structure represents a candidate for elimination. */
  236. typedef struct ext_cand
  237. {
  238. /* The expression. */
  239. const_rtx expr;
  240. /* The kind of extension. */
  241. enum rtx_code code;
  242. /* The destination mode. */
  243. machine_mode mode;
  244. /* The instruction where it lives. */
  245. rtx_insn *insn;
  246. } ext_cand;
  247. static int max_insn_uid;
  248. /* Update or remove REG_EQUAL or REG_EQUIV notes for INSN. */
  249. static bool
  250. update_reg_equal_equiv_notes (rtx_insn *insn, machine_mode new_mode,
  251. machine_mode old_mode, enum rtx_code code)
  252. {
  253. rtx *loc = &REG_NOTES (insn);
  254. while (*loc)
  255. {
  256. enum reg_note kind = REG_NOTE_KIND (*loc);
  257. if (kind == REG_EQUAL || kind == REG_EQUIV)
  258. {
  259. rtx orig_src = XEXP (*loc, 0);
  260. /* Update equivalency constants. Recall that RTL constants are
  261. sign-extended. */
  262. if (GET_CODE (orig_src) == CONST_INT
  263. && HOST_BITS_PER_WIDE_INT >= GET_MODE_BITSIZE (new_mode))
  264. {
  265. if (INTVAL (orig_src) >= 0 || code == SIGN_EXTEND)
  266. /* Nothing needed. */;
  267. else
  268. {
  269. /* Zero-extend the negative constant by masking out the
  270. bits outside the source mode. */
  271. rtx new_const_int
  272. = gen_int_mode (INTVAL (orig_src)
  273. & GET_MODE_MASK (old_mode),
  274. new_mode);
  275. if (!validate_change (insn, &XEXP (*loc, 0),
  276. new_const_int, true))
  277. return false;
  278. }
  279. loc = &XEXP (*loc, 1);
  280. }
  281. /* Drop all other notes, they assume a wrong mode. */
  282. else if (!validate_change (insn, loc, XEXP (*loc, 1), true))
  283. return false;
  284. }
  285. else
  286. loc = &XEXP (*loc, 1);
  287. }
  288. return true;
  289. }
  290. /* Given a insn (CURR_INSN), an extension candidate for removal (CAND)
  291. and a pointer to the SET rtx (ORIG_SET) that needs to be modified,
  292. this code modifies the SET rtx to a new SET rtx that extends the
  293. right hand expression into a register on the left hand side. Note
  294. that multiple assumptions are made about the nature of the set that
  295. needs to be true for this to work and is called from merge_def_and_ext.
  296. Original :
  297. (set (reg a) (expression))
  298. Transform :
  299. (set (reg a) (any_extend (expression)))
  300. Special Cases :
  301. If the expression is a constant or another extension, then directly
  302. assign it to the register. */
  303. static bool
  304. combine_set_extension (ext_cand *cand, rtx_insn *curr_insn, rtx *orig_set)
  305. {
  306. rtx orig_src = SET_SRC (*orig_set);
  307. machine_mode orig_mode = GET_MODE (SET_DEST (*orig_set));
  308. rtx new_set;
  309. rtx cand_pat = PATTERN (cand->insn);
  310. /* If the extension's source/destination registers are not the same
  311. then we need to change the original load to reference the destination
  312. of the extension. Then we need to emit a copy from that destination
  313. to the original destination of the load. */
  314. rtx new_reg;
  315. bool copy_needed
  316. = (REGNO (SET_DEST (cand_pat)) != REGNO (XEXP (SET_SRC (cand_pat), 0)));
  317. if (copy_needed)
  318. new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (cand_pat)));
  319. else
  320. new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (*orig_set)));
  321. #if 0
  322. /* Rethinking test. Temporarily disabled. */
  323. /* We're going to be widening the result of DEF_INSN, ensure that doing so
  324. doesn't change the number of hard registers needed for the result. */
  325. if (HARD_REGNO_NREGS (REGNO (new_reg), cand->mode)
  326. != HARD_REGNO_NREGS (REGNO (SET_DEST (*orig_set)),
  327. GET_MODE (SET_DEST (*orig_set))))
  328. return false;
  329. #endif
  330. /* Merge constants by directly moving the constant into the register under
  331. some conditions. Recall that RTL constants are sign-extended. */
  332. if (GET_CODE (orig_src) == CONST_INT
  333. && HOST_BITS_PER_WIDE_INT >= GET_MODE_BITSIZE (cand->mode))
  334. {
  335. if (INTVAL (orig_src) >= 0 || cand->code == SIGN_EXTEND)
  336. new_set = gen_rtx_SET (VOIDmode, new_reg, orig_src);
  337. else
  338. {
  339. /* Zero-extend the negative constant by masking out the bits outside
  340. the source mode. */
  341. rtx new_const_int
  342. = gen_int_mode (INTVAL (orig_src) & GET_MODE_MASK (orig_mode),
  343. GET_MODE (new_reg));
  344. new_set = gen_rtx_SET (VOIDmode, new_reg, new_const_int);
  345. }
  346. }
  347. else if (GET_MODE (orig_src) == VOIDmode)
  348. {
  349. /* This is mostly due to a call insn that should not be optimized. */
  350. return false;
  351. }
  352. else if (GET_CODE (orig_src) == cand->code)
  353. {
  354. /* Here is a sequence of two extensions. Try to merge them. */
  355. rtx temp_extension
  356. = gen_rtx_fmt_e (cand->code, cand->mode, XEXP (orig_src, 0));
  357. rtx simplified_temp_extension = simplify_rtx (temp_extension);
  358. if (simplified_temp_extension)
  359. temp_extension = simplified_temp_extension;
  360. new_set = gen_rtx_SET (VOIDmode, new_reg, temp_extension);
  361. }
  362. else if (GET_CODE (orig_src) == IF_THEN_ELSE)
  363. {
  364. /* Only IF_THEN_ELSE of phi-type copies are combined. Otherwise,
  365. in general, IF_THEN_ELSE should not be combined. */
  366. return false;
  367. }
  368. else
  369. {
  370. /* This is the normal case. */
  371. rtx temp_extension
  372. = gen_rtx_fmt_e (cand->code, cand->mode, orig_src);
  373. rtx simplified_temp_extension = simplify_rtx (temp_extension);
  374. if (simplified_temp_extension)
  375. temp_extension = simplified_temp_extension;
  376. new_set = gen_rtx_SET (VOIDmode, new_reg, temp_extension);
  377. }
  378. /* This change is a part of a group of changes. Hence,
  379. validate_change will not try to commit the change. */
  380. if (validate_change (curr_insn, orig_set, new_set, true)
  381. && update_reg_equal_equiv_notes (curr_insn, cand->mode, orig_mode,
  382. cand->code))
  383. {
  384. if (dump_file)
  385. {
  386. fprintf (dump_file,
  387. "Tentatively merged extension with definition %s:\n",
  388. (copy_needed) ? "(copy needed)" : "");
  389. print_rtl_single (dump_file, curr_insn);
  390. }
  391. return true;
  392. }
  393. return false;
  394. }
  395. /* Treat if_then_else insns, where the operands of both branches
  396. are registers, as copies. For instance,
  397. Original :
  398. (set (reg:SI a) (if_then_else (cond) (reg:SI b) (reg:SI c)))
  399. Transformed :
  400. (set (reg:DI a) (if_then_else (cond) (reg:DI b) (reg:DI c)))
  401. DEF_INSN is the if_then_else insn. */
  402. static bool
  403. transform_ifelse (ext_cand *cand, rtx_insn *def_insn)
  404. {
  405. rtx set_insn = PATTERN (def_insn);
  406. rtx srcreg, dstreg, srcreg2;
  407. rtx map_srcreg, map_dstreg, map_srcreg2;
  408. rtx ifexpr;
  409. rtx cond;
  410. rtx new_set;
  411. gcc_assert (GET_CODE (set_insn) == SET);
  412. cond = XEXP (SET_SRC (set_insn), 0);
  413. dstreg = SET_DEST (set_insn);
  414. srcreg = XEXP (SET_SRC (set_insn), 1);
  415. srcreg2 = XEXP (SET_SRC (set_insn), 2);
  416. /* If the conditional move already has the right or wider mode,
  417. there is nothing to do. */
  418. if (GET_MODE_SIZE (GET_MODE (dstreg)) >= GET_MODE_SIZE (cand->mode))
  419. return true;
  420. map_srcreg = gen_rtx_REG (cand->mode, REGNO (srcreg));
  421. map_srcreg2 = gen_rtx_REG (cand->mode, REGNO (srcreg2));
  422. map_dstreg = gen_rtx_REG (cand->mode, REGNO (dstreg));
  423. ifexpr = gen_rtx_IF_THEN_ELSE (cand->mode, cond, map_srcreg, map_srcreg2);
  424. new_set = gen_rtx_SET (VOIDmode, map_dstreg, ifexpr);
  425. if (validate_change (def_insn, &PATTERN (def_insn), new_set, true)
  426. && update_reg_equal_equiv_notes (def_insn, cand->mode, GET_MODE (dstreg),
  427. cand->code))
  428. {
  429. if (dump_file)
  430. {
  431. fprintf (dump_file,
  432. "Mode of conditional move instruction extended:\n");
  433. print_rtl_single (dump_file, def_insn);
  434. }
  435. return true;
  436. }
  437. return false;
  438. }
  439. /* Get all the reaching definitions of an instruction. The definitions are
  440. desired for REG used in INSN. Return the definition list or NULL if a
  441. definition is missing. If DEST is non-NULL, additionally push the INSN
  442. of the definitions onto DEST. */
  443. static struct df_link *
  444. get_defs (rtx_insn *insn, rtx reg, vec<rtx_insn *> *dest)
  445. {
  446. df_ref use;
  447. struct df_link *ref_chain, *ref_link;
  448. FOR_EACH_INSN_USE (use, insn)
  449. {
  450. if (GET_CODE (DF_REF_REG (use)) == SUBREG)
  451. return NULL;
  452. if (REGNO (DF_REF_REG (use)) == REGNO (reg))
  453. break;
  454. }
  455. gcc_assert (use != NULL);
  456. ref_chain = DF_REF_CHAIN (use);
  457. for (ref_link = ref_chain; ref_link; ref_link = ref_link->next)
  458. {
  459. /* Problem getting some definition for this instruction. */
  460. if (ref_link->ref == NULL)
  461. return NULL;
  462. if (DF_REF_INSN_INFO (ref_link->ref) == NULL)
  463. return NULL;
  464. }
  465. if (dest)
  466. for (ref_link = ref_chain; ref_link; ref_link = ref_link->next)
  467. dest->safe_push (DF_REF_INSN (ref_link->ref));
  468. return ref_chain;
  469. }
  470. /* Return true if INSN is
  471. (SET (reg REGNO (def_reg)) (if_then_else (cond) (REG x1) (REG x2)))
  472. and store x1 and x2 in REG_1 and REG_2. */
  473. static bool
  474. is_cond_copy_insn (rtx_insn *insn, rtx *reg1, rtx *reg2)
  475. {
  476. rtx expr = single_set (insn);
  477. if (expr != NULL_RTX
  478. && GET_CODE (expr) == SET
  479. && GET_CODE (SET_DEST (expr)) == REG
  480. && GET_CODE (SET_SRC (expr)) == IF_THEN_ELSE
  481. && GET_CODE (XEXP (SET_SRC (expr), 1)) == REG
  482. && GET_CODE (XEXP (SET_SRC (expr), 2)) == REG)
  483. {
  484. *reg1 = XEXP (SET_SRC (expr), 1);
  485. *reg2 = XEXP (SET_SRC (expr), 2);
  486. return true;
  487. }
  488. return false;
  489. }
  490. enum ext_modified_kind
  491. {
  492. /* The insn hasn't been modified by ree pass yet. */
  493. EXT_MODIFIED_NONE,
  494. /* Changed into zero extension. */
  495. EXT_MODIFIED_ZEXT,
  496. /* Changed into sign extension. */
  497. EXT_MODIFIED_SEXT
  498. };
  499. struct ATTRIBUTE_PACKED ext_modified
  500. {
  501. /* Mode from which ree has zero or sign extended the destination. */
  502. ENUM_BITFIELD(machine_mode) mode : 8;
  503. /* Kind of modification of the insn. */
  504. ENUM_BITFIELD(ext_modified_kind) kind : 2;
  505. unsigned int do_not_reextend : 1;
  506. /* True if the insn is scheduled to be deleted. */
  507. unsigned int deleted : 1;
  508. };
  509. /* Vectors used by combine_reaching_defs and its helpers. */
  510. typedef struct ext_state
  511. {
  512. /* In order to avoid constant alloc/free, we keep these
  513. 4 vectors live through the entire find_and_remove_re and just
  514. truncate them each time. */
  515. vec<rtx_insn *> defs_list;
  516. vec<rtx_insn *> copies_list;
  517. vec<rtx_insn *> modified_list;
  518. vec<rtx_insn *> work_list;
  519. /* For instructions that have been successfully modified, this is
  520. the original mode from which the insn is extending and
  521. kind of extension. */
  522. struct ext_modified *modified;
  523. } ext_state;
  524. /* Reaching Definitions of the extended register could be conditional copies
  525. or regular definitions. This function separates the two types into two
  526. lists, STATE->DEFS_LIST and STATE->COPIES_LIST. This is necessary because,
  527. if a reaching definition is a conditional copy, merging the extension with
  528. this definition is wrong. Conditional copies are merged by transitively
  529. merging their definitions. The defs_list is populated with all the reaching
  530. definitions of the extension instruction (EXTEND_INSN) which must be merged
  531. with an extension. The copies_list contains all the conditional moves that
  532. will later be extended into a wider mode conditional move if all the merges
  533. are successful. The function returns false upon failure, true upon
  534. success. */
  535. static bool
  536. make_defs_and_copies_lists (rtx_insn *extend_insn, const_rtx set_pat,
  537. ext_state *state)
  538. {
  539. rtx src_reg = XEXP (SET_SRC (set_pat), 0);
  540. bool *is_insn_visited;
  541. bool ret = true;
  542. state->work_list.truncate (0);
  543. /* Initialize the work list. */
  544. if (!get_defs (extend_insn, src_reg, &state->work_list))
  545. gcc_unreachable ();
  546. is_insn_visited = XCNEWVEC (bool, max_insn_uid);
  547. /* Perform transitive closure for conditional copies. */
  548. while (!state->work_list.is_empty ())
  549. {
  550. rtx_insn *def_insn = state->work_list.pop ();
  551. rtx reg1, reg2;
  552. gcc_assert (INSN_UID (def_insn) < max_insn_uid);
  553. if (is_insn_visited[INSN_UID (def_insn)])
  554. continue;
  555. is_insn_visited[INSN_UID (def_insn)] = true;
  556. if (is_cond_copy_insn (def_insn, &reg1, &reg2))
  557. {
  558. /* Push it onto the copy list first. */
  559. state->copies_list.safe_push (def_insn);
  560. /* Now perform the transitive closure. */
  561. if (!get_defs (def_insn, reg1, &state->work_list)
  562. || !get_defs (def_insn, reg2, &state->work_list))
  563. {
  564. ret = false;
  565. break;
  566. }
  567. }
  568. else
  569. state->defs_list.safe_push (def_insn);
  570. }
  571. XDELETEVEC (is_insn_visited);
  572. return ret;
  573. }
  574. /* If DEF_INSN has single SET expression, possibly buried inside
  575. a PARALLEL, return the address of the SET expression, else
  576. return NULL. This is similar to single_set, except that
  577. single_set allows multiple SETs when all but one is dead. */
  578. static rtx *
  579. get_sub_rtx (rtx_insn *def_insn)
  580. {
  581. enum rtx_code code = GET_CODE (PATTERN (def_insn));
  582. rtx *sub_rtx = NULL;
  583. if (code == PARALLEL)
  584. {
  585. for (int i = 0; i < XVECLEN (PATTERN (def_insn), 0); i++)
  586. {
  587. rtx s_expr = XVECEXP (PATTERN (def_insn), 0, i);
  588. if (GET_CODE (s_expr) != SET)
  589. continue;
  590. if (sub_rtx == NULL)
  591. sub_rtx = &XVECEXP (PATTERN (def_insn), 0, i);
  592. else
  593. {
  594. /* PARALLEL with multiple SETs. */
  595. return NULL;
  596. }
  597. }
  598. }
  599. else if (code == SET)
  600. sub_rtx = &PATTERN (def_insn);
  601. else
  602. {
  603. /* It is not a PARALLEL or a SET, what could it be ? */
  604. return NULL;
  605. }
  606. gcc_assert (sub_rtx != NULL);
  607. return sub_rtx;
  608. }
  609. /* Merge the DEF_INSN with an extension. Calls combine_set_extension
  610. on the SET pattern. */
  611. static bool
  612. merge_def_and_ext (ext_cand *cand, rtx_insn *def_insn, ext_state *state)
  613. {
  614. machine_mode ext_src_mode;
  615. rtx *sub_rtx;
  616. ext_src_mode = GET_MODE (XEXP (SET_SRC (cand->expr), 0));
  617. sub_rtx = get_sub_rtx (def_insn);
  618. if (sub_rtx == NULL)
  619. return false;
  620. if (REG_P (SET_DEST (*sub_rtx))
  621. && (GET_MODE (SET_DEST (*sub_rtx)) == ext_src_mode
  622. || ((state->modified[INSN_UID (def_insn)].kind
  623. == (cand->code == ZERO_EXTEND
  624. ? EXT_MODIFIED_ZEXT : EXT_MODIFIED_SEXT))
  625. && state->modified[INSN_UID (def_insn)].mode
  626. == ext_src_mode)))
  627. {
  628. if (GET_MODE_SIZE (GET_MODE (SET_DEST (*sub_rtx)))
  629. >= GET_MODE_SIZE (cand->mode))
  630. return true;
  631. /* If def_insn is already scheduled to be deleted, don't attempt
  632. to modify it. */
  633. if (state->modified[INSN_UID (def_insn)].deleted)
  634. return false;
  635. if (combine_set_extension (cand, def_insn, sub_rtx))
  636. {
  637. if (state->modified[INSN_UID (def_insn)].kind == EXT_MODIFIED_NONE)
  638. state->modified[INSN_UID (def_insn)].mode = ext_src_mode;
  639. return true;
  640. }
  641. }
  642. return false;
  643. }
  644. /* Given SRC, which should be one or more extensions of a REG, strip
  645. away the extensions and return the REG. */
  646. static inline rtx
  647. get_extended_src_reg (rtx src)
  648. {
  649. while (GET_CODE (src) == SIGN_EXTEND || GET_CODE (src) == ZERO_EXTEND)
  650. src = XEXP (src, 0);
  651. gcc_assert (REG_P (src));
  652. return src;
  653. }
  654. /* This function goes through all reaching defs of the source
  655. of the candidate for elimination (CAND) and tries to combine
  656. the extension with the definition instruction. The changes
  657. are made as a group so that even if one definition cannot be
  658. merged, all reaching definitions end up not being merged.
  659. When a conditional copy is encountered, merging is attempted
  660. transitively on its definitions. It returns true upon success
  661. and false upon failure. */
  662. static bool
  663. combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
  664. {
  665. rtx_insn *def_insn;
  666. bool merge_successful = true;
  667. int i;
  668. int defs_ix;
  669. bool outcome;
  670. state->defs_list.truncate (0);
  671. state->copies_list.truncate (0);
  672. outcome = make_defs_and_copies_lists (cand->insn, set_pat, state);
  673. if (!outcome)
  674. return false;
  675. /* If the destination operand of the extension is a different
  676. register than the source operand, then additional restrictions
  677. are needed. Note we have to handle cases where we have nested
  678. extensions in the source operand. */
  679. bool copy_needed
  680. = (REGNO (SET_DEST (PATTERN (cand->insn)))
  681. != REGNO (get_extended_src_reg (SET_SRC (PATTERN (cand->insn)))));
  682. if (copy_needed)
  683. {
  684. /* Considering transformation of
  685. (set (reg1) (expression))
  686. ...
  687. (set (reg2) (any_extend (reg1)))
  688. into
  689. (set (reg2) (any_extend (expression)))
  690. (set (reg1) (reg2))
  691. ... */
  692. /* In theory we could handle more than one reaching def, it
  693. just makes the code to update the insn stream more complex. */
  694. if (state->defs_list.length () != 1)
  695. return false;
  696. /* We require the candidate not already be modified. It may,
  697. for example have been changed from a (sign_extend (reg))
  698. into (zero_extend (sign_extend (reg))).
  699. Handling that case shouldn't be terribly difficult, but the code
  700. here and the code to emit copies would need auditing. Until
  701. we see a need, this is the safe thing to do. */
  702. if (state->modified[INSN_UID (cand->insn)].kind != EXT_MODIFIED_NONE)
  703. return false;
  704. machine_mode dst_mode = GET_MODE (SET_DEST (PATTERN (cand->insn)));
  705. rtx src_reg = get_extended_src_reg (SET_SRC (PATTERN (cand->insn)));
  706. /* Ensure the number of hard registers of the copy match. */
  707. if (HARD_REGNO_NREGS (REGNO (src_reg), dst_mode)
  708. != HARD_REGNO_NREGS (REGNO (src_reg), GET_MODE (src_reg)))
  709. return false;
  710. /* There's only one reaching def. */
  711. rtx_insn *def_insn = state->defs_list[0];
  712. /* The defining statement must not have been modified either. */
  713. if (state->modified[INSN_UID (def_insn)].kind != EXT_MODIFIED_NONE)
  714. return false;
  715. /* The defining statement and candidate insn must be in the same block.
  716. This is merely to keep the test for safety and updating the insn
  717. stream simple. Also ensure that within the block the candidate
  718. follows the defining insn. */
  719. basic_block bb = BLOCK_FOR_INSN (cand->insn);
  720. if (bb != BLOCK_FOR_INSN (def_insn)
  721. || DF_INSN_LUID (def_insn) > DF_INSN_LUID (cand->insn))
  722. return false;
  723. /* If there is an overlap between the destination of DEF_INSN and
  724. CAND->insn, then this transformation is not safe. Note we have
  725. to test in the widened mode. */
  726. rtx *dest_sub_rtx = get_sub_rtx (def_insn);
  727. if (dest_sub_rtx == NULL
  728. || !REG_P (SET_DEST (*dest_sub_rtx)))
  729. return false;
  730. rtx tmp_reg = gen_rtx_REG (GET_MODE (SET_DEST (PATTERN (cand->insn))),
  731. REGNO (SET_DEST (*dest_sub_rtx)));
  732. if (reg_overlap_mentioned_p (tmp_reg, SET_DEST (PATTERN (cand->insn))))
  733. return false;
  734. /* The destination register of the extension insn must not be
  735. used or set between the def_insn and cand->insn exclusive. */
  736. if (reg_used_between_p (SET_DEST (PATTERN (cand->insn)),
  737. def_insn, cand->insn)
  738. || reg_set_between_p (SET_DEST (PATTERN (cand->insn)),
  739. def_insn, cand->insn))
  740. return false;
  741. /* We must be able to copy between the two registers. Generate,
  742. recognize and verify constraints of the copy. Also fail if this
  743. generated more than one insn.
  744. This generates garbage since we throw away the insn when we're
  745. done, only to recreate it later if this test was successful.
  746. Make sure to get the mode from the extension (cand->insn). This
  747. is different than in the code to emit the copy as we have not
  748. modified the defining insn yet. */
  749. start_sequence ();
  750. rtx pat = PATTERN (cand->insn);
  751. rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (pat)),
  752. REGNO (get_extended_src_reg (SET_SRC (pat))));
  753. rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (pat)),
  754. REGNO (SET_DEST (pat)));
  755. emit_move_insn (new_dst, new_src);
  756. rtx_insn *insn = get_insns();
  757. end_sequence ();
  758. if (NEXT_INSN (insn))
  759. return false;
  760. if (recog_memoized (insn) == -1)
  761. return false;
  762. extract_insn (insn);
  763. if (!constrain_operands (1, get_preferred_alternatives (insn, bb)))
  764. return false;
  765. }
  766. /* If cand->insn has been already modified, update cand->mode to a wider
  767. mode if possible, or punt. */
  768. if (state->modified[INSN_UID (cand->insn)].kind != EXT_MODIFIED_NONE)
  769. {
  770. machine_mode mode;
  771. rtx set;
  772. if (state->modified[INSN_UID (cand->insn)].kind
  773. != (cand->code == ZERO_EXTEND
  774. ? EXT_MODIFIED_ZEXT : EXT_MODIFIED_SEXT)
  775. || state->modified[INSN_UID (cand->insn)].mode != cand->mode
  776. || (set = single_set (cand->insn)) == NULL_RTX)
  777. return false;
  778. mode = GET_MODE (SET_DEST (set));
  779. gcc_assert (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (cand->mode));
  780. cand->mode = mode;
  781. }
  782. merge_successful = true;
  783. /* Go through the defs vector and try to merge all the definitions
  784. in this vector. */
  785. state->modified_list.truncate (0);
  786. FOR_EACH_VEC_ELT (state->defs_list, defs_ix, def_insn)
  787. {
  788. if (merge_def_and_ext (cand, def_insn, state))
  789. state->modified_list.safe_push (def_insn);
  790. else
  791. {
  792. merge_successful = false;
  793. break;
  794. }
  795. }
  796. /* Now go through the conditional copies vector and try to merge all
  797. the copies in this vector. */
  798. if (merge_successful)
  799. {
  800. FOR_EACH_VEC_ELT (state->copies_list, i, def_insn)
  801. {
  802. if (transform_ifelse (cand, def_insn))
  803. state->modified_list.safe_push (def_insn);
  804. else
  805. {
  806. merge_successful = false;
  807. break;
  808. }
  809. }
  810. }
  811. if (merge_successful)
  812. {
  813. /* Commit the changes here if possible
  814. FIXME: It's an all-or-nothing scenario. Even if only one definition
  815. cannot be merged, we entirely give up. In the future, we should allow
  816. extensions to be partially eliminated along those paths where the
  817. definitions could be merged. */
  818. if (apply_change_group ())
  819. {
  820. if (dump_file)
  821. fprintf (dump_file, "All merges were successful.\n");
  822. FOR_EACH_VEC_ELT (state->modified_list, i, def_insn)
  823. {
  824. ext_modified *modified = &state->modified[INSN_UID (def_insn)];
  825. if (modified->kind == EXT_MODIFIED_NONE)
  826. modified->kind = (cand->code == ZERO_EXTEND ? EXT_MODIFIED_ZEXT
  827. : EXT_MODIFIED_SEXT);
  828. if (copy_needed)
  829. modified->do_not_reextend = 1;
  830. }
  831. return true;
  832. }
  833. else
  834. {
  835. /* Changes need not be cancelled explicitly as apply_change_group
  836. does it. Print list of definitions in the dump_file for debug
  837. purposes. This extension cannot be deleted. */
  838. if (dump_file)
  839. {
  840. fprintf (dump_file,
  841. "Merge cancelled, non-mergeable definitions:\n");
  842. FOR_EACH_VEC_ELT (state->modified_list, i, def_insn)
  843. print_rtl_single (dump_file, def_insn);
  844. }
  845. }
  846. }
  847. else
  848. {
  849. /* Cancel any changes that have been made so far. */
  850. cancel_changes (0);
  851. }
  852. return false;
  853. }
  854. /* Add an extension pattern that could be eliminated. */
  855. static void
  856. add_removable_extension (const_rtx expr, rtx_insn *insn,
  857. vec<ext_cand> *insn_list,
  858. unsigned *def_map)
  859. {
  860. enum rtx_code code;
  861. machine_mode mode;
  862. unsigned int idx;
  863. rtx src, dest;
  864. /* We are looking for SET (REG N) (ANY_EXTEND (REG N)). */
  865. if (GET_CODE (expr) != SET)
  866. return;
  867. src = SET_SRC (expr);
  868. code = GET_CODE (src);
  869. dest = SET_DEST (expr);
  870. mode = GET_MODE (dest);
  871. if (REG_P (dest)
  872. && (code == SIGN_EXTEND || code == ZERO_EXTEND)
  873. && REG_P (XEXP (src, 0)))
  874. {
  875. struct df_link *defs, *def;
  876. ext_cand *cand;
  877. /* First, make sure we can get all the reaching definitions. */
  878. defs = get_defs (insn, XEXP (src, 0), NULL);
  879. if (!defs)
  880. {
  881. if (dump_file)
  882. {
  883. fprintf (dump_file, "Cannot eliminate extension:\n");
  884. print_rtl_single (dump_file, insn);
  885. fprintf (dump_file, " because of missing definition(s)\n");
  886. }
  887. return;
  888. }
  889. /* Second, make sure the reaching definitions don't feed another and
  890. different extension. FIXME: this obviously can be improved. */
  891. for (def = defs; def; def = def->next)
  892. if ((idx = def_map[INSN_UID (DF_REF_INSN (def->ref))])
  893. && idx != -1U
  894. && (cand = &(*insn_list)[idx - 1])
  895. && cand->code != code)
  896. {
  897. if (dump_file)
  898. {
  899. fprintf (dump_file, "Cannot eliminate extension:\n");
  900. print_rtl_single (dump_file, insn);
  901. fprintf (dump_file, " because of other extension\n");
  902. }
  903. return;
  904. }
  905. /* For vector mode extensions, ensure that all uses of the
  906. XEXP (src, 0) register are the same extension (both code
  907. and to which mode), as unlike integral extensions lowpart
  908. subreg of the sign/zero extended register are not equal
  909. to the original register, so we have to change all uses or
  910. none. */
  911. else if (VECTOR_MODE_P (GET_MODE (XEXP (src, 0))))
  912. {
  913. if (idx == 0)
  914. {
  915. struct df_link *ref_chain, *ref_link;
  916. ref_chain = DF_REF_CHAIN (def->ref);
  917. for (ref_link = ref_chain; ref_link; ref_link = ref_link->next)
  918. {
  919. if (ref_link->ref == NULL
  920. || DF_REF_INSN_INFO (ref_link->ref) == NULL)
  921. {
  922. idx = -1U;
  923. break;
  924. }
  925. rtx_insn *use_insn = DF_REF_INSN (ref_link->ref);
  926. const_rtx use_set;
  927. if (use_insn == insn || DEBUG_INSN_P (use_insn))
  928. continue;
  929. if (!(use_set = single_set (use_insn))
  930. || !REG_P (SET_DEST (use_set))
  931. || GET_MODE (SET_DEST (use_set)) != GET_MODE (dest)
  932. || GET_CODE (SET_SRC (use_set)) != code
  933. || !rtx_equal_p (XEXP (SET_SRC (use_set), 0),
  934. XEXP (src, 0)))
  935. {
  936. idx = -1U;
  937. break;
  938. }
  939. }
  940. if (idx == -1U)
  941. def_map[INSN_UID (DF_REF_INSN (def->ref))] = idx;
  942. }
  943. if (idx == -1U)
  944. {
  945. if (dump_file)
  946. {
  947. fprintf (dump_file, "Cannot eliminate extension:\n");
  948. print_rtl_single (dump_file, insn);
  949. fprintf (dump_file,
  950. " because some vector uses aren't extension\n");
  951. }
  952. return;
  953. }
  954. }
  955. /* Then add the candidate to the list and insert the reaching definitions
  956. into the definition map. */
  957. ext_cand e = {expr, code, mode, insn};
  958. insn_list->safe_push (e);
  959. idx = insn_list->length ();
  960. for (def = defs; def; def = def->next)
  961. def_map[INSN_UID (DF_REF_INSN (def->ref))] = idx;
  962. }
  963. }
  964. /* Traverse the instruction stream looking for extensions and return the
  965. list of candidates. */
  966. static vec<ext_cand>
  967. find_removable_extensions (void)
  968. {
  969. vec<ext_cand> insn_list = vNULL;
  970. basic_block bb;
  971. rtx_insn *insn;
  972. rtx set;
  973. unsigned *def_map = XCNEWVEC (unsigned, max_insn_uid);
  974. FOR_EACH_BB_FN (bb, cfun)
  975. FOR_BB_INSNS (bb, insn)
  976. {
  977. if (!NONDEBUG_INSN_P (insn))
  978. continue;
  979. set = single_set (insn);
  980. if (set == NULL_RTX)
  981. continue;
  982. add_removable_extension (set, insn, &insn_list, def_map);
  983. }
  984. XDELETEVEC (def_map);
  985. return insn_list;
  986. }
  987. /* This is the main function that checks the insn stream for redundant
  988. extensions and tries to remove them if possible. */
  989. static void
  990. find_and_remove_re (void)
  991. {
  992. ext_cand *curr_cand;
  993. rtx_insn *curr_insn = NULL;
  994. int num_re_opportunities = 0, num_realized = 0, i;
  995. vec<ext_cand> reinsn_list;
  996. auto_vec<rtx_insn *> reinsn_del_list;
  997. auto_vec<rtx_insn *> reinsn_copy_list;
  998. ext_state state;
  999. /* Construct DU chain to get all reaching definitions of each
  1000. extension instruction. */
  1001. df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
  1002. df_chain_add_problem (DF_UD_CHAIN + DF_DU_CHAIN);
  1003. df_analyze ();
  1004. df_set_flags (DF_DEFER_INSN_RESCAN);
  1005. max_insn_uid = get_max_uid ();
  1006. reinsn_list = find_removable_extensions ();
  1007. state.defs_list.create (0);
  1008. state.copies_list.create (0);
  1009. state.modified_list.create (0);
  1010. state.work_list.create (0);
  1011. if (reinsn_list.is_empty ())
  1012. state.modified = NULL;
  1013. else
  1014. state.modified = XCNEWVEC (struct ext_modified, max_insn_uid);
  1015. FOR_EACH_VEC_ELT (reinsn_list, i, curr_cand)
  1016. {
  1017. num_re_opportunities++;
  1018. /* Try to combine the extension with the definition. */
  1019. if (dump_file)
  1020. {
  1021. fprintf (dump_file, "Trying to eliminate extension:\n");
  1022. print_rtl_single (dump_file, curr_cand->insn);
  1023. }
  1024. if (combine_reaching_defs (curr_cand, curr_cand->expr, &state))
  1025. {
  1026. if (dump_file)
  1027. fprintf (dump_file, "Eliminated the extension.\n");
  1028. num_realized++;
  1029. /* If the RHS of the current candidate is not (extend (reg)), then
  1030. we do not allow the optimization of extensions where
  1031. the source and destination registers do not match. Thus
  1032. checking REG_P here is correct. */
  1033. if (REG_P (XEXP (SET_SRC (PATTERN (curr_cand->insn)), 0))
  1034. && (REGNO (SET_DEST (PATTERN (curr_cand->insn)))
  1035. != REGNO (XEXP (SET_SRC (PATTERN (curr_cand->insn)), 0))))
  1036. {
  1037. reinsn_copy_list.safe_push (curr_cand->insn);
  1038. reinsn_copy_list.safe_push (state.defs_list[0]);
  1039. }
  1040. reinsn_del_list.safe_push (curr_cand->insn);
  1041. state.modified[INSN_UID (curr_cand->insn)].deleted = 1;
  1042. }
  1043. }
  1044. /* The copy list contains pairs of insns which describe copies we
  1045. need to insert into the INSN stream.
  1046. The first insn in each pair is the extension insn, from which
  1047. we derive the source and destination of the copy.
  1048. The second insn in each pair is the memory reference where the
  1049. extension will ultimately happen. We emit the new copy
  1050. immediately after this insn.
  1051. It may first appear that the arguments for the copy are reversed.
  1052. Remember that the memory reference will be changed to refer to the
  1053. destination of the extention. So we're actually emitting a copy
  1054. from the new destination to the old destination. */
  1055. for (unsigned int i = 0; i < reinsn_copy_list.length (); i += 2)
  1056. {
  1057. rtx_insn *curr_insn = reinsn_copy_list[i];
  1058. rtx_insn *def_insn = reinsn_copy_list[i + 1];
  1059. /* Use the mode of the destination of the defining insn
  1060. for the mode of the copy. This is necessary if the
  1061. defining insn was used to eliminate a second extension
  1062. that was wider than the first. */
  1063. rtx sub_rtx = *get_sub_rtx (def_insn);
  1064. rtx pat = PATTERN (curr_insn);
  1065. rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
  1066. REGNO (XEXP (SET_SRC (pat), 0)));
  1067. rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
  1068. REGNO (SET_DEST (pat)));
  1069. rtx set = gen_rtx_SET (VOIDmode, new_dst, new_src);
  1070. emit_insn_after (set, def_insn);
  1071. }
  1072. /* Delete all useless extensions here in one sweep. */
  1073. FOR_EACH_VEC_ELT (reinsn_del_list, i, curr_insn)
  1074. delete_insn (curr_insn);
  1075. reinsn_list.release ();
  1076. state.defs_list.release ();
  1077. state.copies_list.release ();
  1078. state.modified_list.release ();
  1079. state.work_list.release ();
  1080. XDELETEVEC (state.modified);
  1081. if (dump_file && num_re_opportunities > 0)
  1082. fprintf (dump_file, "Elimination opportunities = %d realized = %d\n",
  1083. num_re_opportunities, num_realized);
  1084. }
  1085. /* Find and remove redundant extensions. */
  1086. static unsigned int
  1087. rest_of_handle_ree (void)
  1088. {
  1089. timevar_push (TV_REE);
  1090. find_and_remove_re ();
  1091. timevar_pop (TV_REE);
  1092. return 0;
  1093. }
  1094. namespace {
  1095. const pass_data pass_data_ree =
  1096. {
  1097. RTL_PASS, /* type */
  1098. "ree", /* name */
  1099. OPTGROUP_NONE, /* optinfo_flags */
  1100. TV_REE, /* tv_id */
  1101. 0, /* properties_required */
  1102. 0, /* properties_provided */
  1103. 0, /* properties_destroyed */
  1104. 0, /* todo_flags_start */
  1105. TODO_df_finish, /* todo_flags_finish */
  1106. };
  1107. class pass_ree : public rtl_opt_pass
  1108. {
  1109. public:
  1110. pass_ree (gcc::context *ctxt)
  1111. : rtl_opt_pass (pass_data_ree, ctxt)
  1112. {}
  1113. /* opt_pass methods: */
  1114. virtual bool gate (function *) { return (optimize > 0 && flag_ree); }
  1115. virtual unsigned int execute (function *) { return rest_of_handle_ree (); }
  1116. }; // class pass_ree
  1117. } // anon namespace
  1118. rtl_opt_pass *
  1119. make_pass_ree (gcc::context *ctxt)
  1120. {
  1121. return new pass_ree (ctxt);
  1122. }