prat3492

Untitled

Sep 3rd, 2015
169
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 6.86 KB | None | 0 0
  1. diff --git a/gcc/common.opt b/gcc/common.opt
  2. index 94d1d88..3913bc1 100644
  3. --- a/gcc/common.opt
  4. +++ b/gcc/common.opt
  5. @@ -1300,6 +1300,10 @@ ffunction-sections
  6.  Common Report Var(flag_function_sections)
  7.  Place each function into its own section
  8.  
  9. +fremove-temps
  10. +Common Report Var(flag_rtl_remove_temps) Optimization
  11. +Undo CSE of test conditions made by rtl pre.
  12. +
  13.  fgcse
  14.  Common Report Var(flag_gcse) Optimization
  15.  Perform global common subexpression elimination
  16. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
  17. index fa4e083..d36d017 100644
  18. --- a/gcc/config/arm/arm.c
  19. +++ b/gcc/config/arm/arm.c
  20. @@ -73,6 +73,9 @@
  21.  #include "builtins.h"
  22.  #include "tm-constrs.h"
  23.  #include "rtl-iter.h"
  24. +#include "tree-pass.h"
  25. +#include "context.h"
  26. +#include <set>
  27.  
  28.  /* This file should be included last.  */
  29.  #include "target-def.h"
  30. @@ -3397,6 +3400,22 @@ arm_option_override (void)
  31.  
  32.    /* Init initial mode for testing.  */
  33.    thumb_flipper = TARGET_THUMB;
  34. +
  35. +  /* Registering the pass must be done at start up.  It's
  36. +     convenient to do it here.  */
  37. +  
  38. +  rtl_opt_pass *make_pass_rtl_remove_temps (gcc::context *);
  39. +
  40. +  opt_pass *new_pass = make_pass_rtl_remove_temps (g);
  41. +  struct register_pass_info insert_pass_rtl_remove_temps =
  42. +    {
  43. +      new_pass,            /* pass */
  44. +      "combine",       /* reference_pass_name */
  45. +      1,           /* ref_pass_instance_number */
  46. +      PASS_POS_INSERT_BEFORE   /* po_op */
  47. +    };
  48. +  pass_init_dump_file (new_pass);
  49. +  register_pass (&insert_pass_rtl_remove_temps);
  50.  }
  51.  
  52.  static void
  53. @@ -29781,4 +29800,219 @@ arm_sched_fusion_priority (rtx_insn *insn, int max_pri,
  54.    *pri = tmp;
  55.    return;
  56.  }
  57. +
  58. +/* Pass: pass_rtl_remove_temps
  59. +The patch look for rtx containing
  60. +(set (reg:CC )
  61. +       (compare:CC (reg:SI <num>) (const_int 0)))
  62. +
  63. +and then looks for insn that sets reg:SI <num> and creates a copy of
  64. +that rtx insn.
  65. +
  66. +Suppose the definition of reg:SI<num> is follows:
  67. +(set (reg:SI <num>)
  68. +       (and:SI (reg:SI ) (const_int <val>)))
  69. +
  70. +The above insn is replicated:
  71. +(set (reg:SI <num2>)
  72. +       (and:SI (reg:SI ) (const_int <val>))) { *arm_andsi3_insn }
  73. +
  74. +and then it's value used in compare-against-0 insn
  75. +(set (reg:CC)
  76. +        (compare:CC (reg:SI <num2>) (const_int 0)))  { *arm_cmpsi_insn }
  77. +
  78. +The rationale for this change is that combine pass combines adjacent
  79. +arm_andsi3_insn, arm_cmpsi_insn into zeroextractsi_compare0_scratch,
  80. +which results in tst instruction.
  81. +The new insn is introduced only if reg:SI<num> is used in multiple
  82. +compare-against-0 insns (seen_regs is used for this purpose)
  83. +*/
  84. +
  85. +std::set<int> seen_regs;
  86. +
  87. +/* Find insn that defines reg. rtx_insn *insn uses the reg */
  88. +static rtx_insn *
  89. +get_def_insn (rtx_insn *insn, rtx reg)
  90. +{
  91. +  df_ref use;
  92. +  struct df_link *ref_chain, *ref_link;
  93. +
  94. +  use = df_find_use (insn, reg);
  95. +  gcc_assert (use != NULL);
  96. +  ref_chain = DF_REF_CHAIN (use);
  97. +
  98. +  // ??? Punt if a use has multiple defs
  99. +  if (ref_chain->next)
  100. +    return NULL;
  101. +
  102. +  if (ref_chain->ref == NULL || DF_REF_INSN_INFO (ref_chain->ref) == NULL)
  103. +    return NULL;
  104. +
  105. +  return DF_REF_INSN (ref_chain->ref);
  106. +}
  107. +
  108. +/* See if expr is of the form
  109. +  (and:SI (reg:SI <num> ) {(const_int <val>), (reg:SI <num>)}) */
  110. +
  111. +static bool
  112. +def_candidate_p (rtx expr)
  113. +{
  114. +  if (GET_CODE (expr) != AND)
  115. +    return false;
  116. +
  117. +  if (GET_MODE (expr) != SImode)
  118. +    return false;
  119. +
  120. +  rtx op0 = XEXP (expr, 0);
  121. +  rtx op1 = XEXP (expr, 1);
  122. +
  123. +  if (!REG_P (op0) || GET_MODE (op0) != SImode)
  124. +    return false;
  125. +
  126. +  if ((REG_P (op1) && GET_MODE (op1) != SImode)
  127. +      || GET_CODE (op1) != CONST_INT)
  128. +    return false;
  129. +
  130. +  return true;
  131. +}
  132. +
  133. +/* Performs the transform described above */
  134. +
  135. +static void
  136. +do_remove_temp (rtx_insn *insn)
  137. +{
  138. +  rtx exp = PATTERN (insn);
  139. +
  140. +  if (GET_CODE (exp) != SET)
  141. +    return;
  142. +  exp = XEXP (exp, 1);
  143. +  if (GET_CODE (exp) != COMPARE)
  144. +    return;
  145. +  if (GET_MODE (exp) != CCmode)
  146. +    return;
  147. +
  148. +  rtx compare_expr = exp;
  149. +  rtx op0 = XEXP (exp, 0);
  150. +  if (!REG_P (op0))
  151. +    return;
  152. +
  153. +  if (GET_MODE (op0) != SImode)
  154. +    return;
  155. +
  156. +  rtx op1 = XEXP (exp, 1);
  157. +  if (GET_CODE (op1) != CONST_INT || INTVAL (op1) != 0)
  158. +    return;
  159. +
  160. +  rtx_insn *def_insn = get_def_insn (insn, op0);
  161. +  if (def_insn == NULL)
  162. +    return;
  163. +
  164. +  rtx pat = PATTERN (def_insn);
  165. +  if (!def_candidate_p (XEXP (pat, 1)))
  166. +    return;
  167. +
  168. +  rtx result_reg = XEXP (pat, 0);
  169. +  if (!REG_P (result_reg) || GET_MODE (result_reg) != SImode)
  170. +    return;
  171. +
  172. +  gcc_assert (REG_P (result_reg));
  173. +  std::pair< std::set<int>::iterator, bool > ret = seen_regs.insert (REGNO (result_reg));
  174. +  if (ret.second == true)
  175. +    return;
  176. +
  177. +  rtx reg = gen_reg_rtx (SImode);
  178. +  rtx newpat = gen_rtx_SET (reg, copy_rtx (SET_SRC (pat)));
  179. +  rtx_insn *x = emit_insn_before (newpat, insn);
  180. +  XEXP (compare_expr, 0) = reg;
  181. +  df_insn_rescan (insn);
  182. +  recog_memoized (x);
  183. +}
  184. +
  185. +static void
  186. +rtl_remove_temps_init()
  187. +{
  188. +  df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
  189. +  df_chain_add_problem (DF_UD_CHAIN);
  190. +  df_analyze ();
  191. +  df_set_flags (DF_DEFER_INSN_RESCAN);
  192. +}
  193. +
  194. +static unsigned int
  195. +execute_rtl_remove_temps (void)
  196. +{
  197. +  rtx_insn *insn, *last, *first;
  198. +
  199. +  for (insn = first = get_insns (), last = get_last_insn (); insn != last; insn = NEXT_INSN (insn))
  200. +    {
  201. +      if (!INSN_P (insn))
  202. +   continue;
  203. +
  204. +      rtx pat = PATTERN (insn);
  205. +      /* ??? set and use of same register cannot happen in PARALLEL */
  206. +      if (GET_CODE (pat) == PARALLEL)
  207. +   continue;
  208. +      else if (GET_CODE (pat) == SEQUENCE)
  209. +   {
  210. +     push_topmost_sequence ();
  211. +     execute_rtl_remove_temps ();
  212. +     pop_topmost_sequence ();
  213. +   }
  214. +      else
  215. +   do_remove_temp (insn);
  216. +    }
  217. +
  218. +  return 0;
  219. +}
  220. +
  221. +namespace {
  222. +
  223. +const pass_data pass_data_rtl_remove_temps =
  224. +{
  225. +  RTL_PASS,        /* type */
  226. +  "remove-temps",  /* name */
  227. +  OPTGROUP_NONE,   /* optinfo_flags */
  228. +  TV_NONE,
  229. +  PROP_cfglayout,  /* properties_required */
  230. +  0,           /* properties_provided */
  231. +  0,           /* properties_destroyed */
  232. +  0,           /* todo_flags_start */
  233. +  TODO_df_finish,  /* todo_flags_finish */
  234. +};
  235. +
  236. +class pass_rtl_remove_temps : public rtl_opt_pass
  237. +{
  238. +public:
  239. +  pass_rtl_remove_temps (gcc::context *ctxt)
  240. +    : rtl_opt_pass (pass_data_rtl_remove_temps, ctxt)
  241. +  {}
  242. +
  243. +  /* opt_pass methods: */
  244. +  virtual bool gate (function *);
  245. +  virtual unsigned int execute (function *);
  246. +
  247. +}; // class pass_rtl_remove_temps
  248. +
  249. +bool
  250. +pass_rtl_remove_temps::gate (function *)
  251. +{
  252. +  return flag_rtl_remove_temps != 0 && optimize > 0;
  253. +}
  254. +
  255. +} // anon namespace
  256. +
  257. +unsigned int
  258. +pass_rtl_remove_temps::execute (function *)
  259. +{
  260. +  rtl_remove_temps_init ();
  261. +  unsigned ret = execute_rtl_remove_temps ();
  262. +  df_process_deferred_rescans ();
  263. +  return ret;
  264. +}
  265. +
  266. +rtl_opt_pass *
  267. +make_pass_rtl_remove_temps (gcc::context *ctxt)
  268. +{
  269. +  return new pass_rtl_remove_temps (ctxt);
  270. +}
  271. +
  272.  #include "gt-arm.h"
Advertisement
Add Comment
Please, Sign In to add comment