prat3492

120-2.diff

Sep 6th, 2015
201
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 9.05 KB | None | 0 0
  1. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
  2. index fa4e083..836e6d1 100644
  3. --- a/gcc/config/arm/arm.c
  4. +++ b/gcc/config/arm/arm.c
  5. @@ -73,6 +73,8 @@
  6.  #include "builtins.h"
  7.  #include "tm-constrs.h"
  8.  #include "rtl-iter.h"
  9. +#include "tree-pass.h"
  10. +#include "context.h"
  11.  
  12.  /* This file should be included last.  */
  13.  #include "target-def.h"
  14. @@ -3397,6 +3399,23 @@ arm_option_override (void)
  15.  
  16.    /* Init initial mode for testing.  */
  17.    thumb_flipper = TARGET_THUMB;
  18. +
  19. +
  20. +  /* Registering the pass must be done at start up.  It's
  21. +     convenient to do it here.  */
  22. +
  23. +  rtl_opt_pass *make_pass_rtl_remove_temps (gcc::context *);
  24. +
  25. +  opt_pass *new_pass = make_pass_rtl_remove_temps (g);
  26. +  struct register_pass_info insert_pass_rtl_remove_temps =
  27. +    {
  28. +      new_pass,            /* pass */
  29. +      "combine",       /* reference_pass_name */
  30. +      1,           /* ref_pass_instance_number */
  31. +      PASS_POS_INSERT_BEFORE   /* po_op */
  32. +    };
  33. +  pass_init_dump_file (new_pass);
  34. +  register_pass (&insert_pass_rtl_remove_temps);
  35.  }
  36.  
  37.  static void
  38. @@ -29781,4 +29800,284 @@ arm_sched_fusion_priority (rtx_insn *insn, int max_pri,
  39.    *pri = tmp;
  40.    return;
  41.  }
  42. +
  43. +/*
  44. + * The pass tries to fold arm_cmpsi_insn into andsi3_compare0_scratch or
  45. + * zeroextractsi_compare0_scratch if reg:CC in arm_cmpsi_insn is set from arm_andsi3_insn.
  46. + */
  47. +
  48. +namespace {
  49. +
  50. +const pass_data pass_data_rtl_remove_temps =
  51. +{
  52. +  RTL_PASS,        /* type */
  53. +  "remove-temps",  /* name */
  54. +  OPTGROUP_NONE,   /* optinfo_flags */
  55. +  TV_NONE,
  56. +  PROP_cfglayout,  /* properties_required */
  57. +  0,           /* properties_provided */
  58. +  0,           /* properties_destroyed */
  59. +  0,           /* todo_flags_start */
  60. +  TODO_df_finish,  /* todo_flags_finish */
  61. +};
  62. +
  63. +class pass_rtl_remove_temps : public rtl_opt_pass
  64. +{
  65. +public:
  66. +  pass_rtl_remove_temps (gcc::context *ctxt)
  67. +    : rtl_opt_pass (pass_data_rtl_remove_temps, ctxt)
  68. +  {}
  69. +
  70. +  /* opt_pass methods: */
  71. +  virtual bool gate (function *);
  72. +  virtual unsigned int execute (function *);
  73. +
  74. +private:
  75. +  static rtx_insn *get_def_insn (rtx_insn *, rtx);
  76. +  static bool reg_simode_p (rtx x) { return REG_P (x) && (GET_MODE (x) == SImode); }
  77. +  static rtx fold (rtx, enum rtx_code *);
  78. +  static rtx gen_andsi3_compare0_scratch (rtx, rtx);
  79. +  static rtx gen_zeroextractsi_compare0_scratch (rtx, rtx);
  80. +  static int getlastbitpos(int x);
  81. +  static int getfirstbitpos(int x);
  82. +  static void change_jump_insn (rtx_insn *);
  83. +  static void do_remove_temp (rtx_insn *insn);
  84. +}; // class pass_rtl_remove_temps
  85. +
  86. +
  87. +int
  88. +pass_rtl_remove_temps::getfirstbitpos (int x)
  89. +{
  90. +  if (x == 0)
  91. +    return -1;
  92. +  return floor_log2 (x & (~x + 1));
  93. +}
  94. +
  95. +int
  96. +pass_rtl_remove_temps::getlastbitpos (int x)
  97. +{
  98. +  /* FIXME: Rewrite */
  99. +  if (x == 0)
  100. +    return -1;
  101. +
  102. +  unsigned pos, bitpos=-1;
  103. +  for (pos = 0; x; x >>=1, pos++)
  104. +    if (x & 1)
  105. +      bitpos = pos;
  106. +
  107. +  return bitpos;
  108. +}
  109. +
  110. +rtx_insn *
  111. +pass_rtl_remove_temps::get_def_insn (rtx_insn *insn, rtx reg)
  112. +{
  113. +  df_ref use;
  114. +  struct df_link *ref_chain, *ref_link;
  115. +
  116. +  use = df_find_use (insn, reg);
  117. +  gcc_assert (use != NULL);
  118. +  ref_chain = DF_REF_CHAIN (use);
  119. +
  120. +  // Punt if a use has multiple defs
  121. +  if (ref_chain->next)
  122. +    return NULL;
  123. +
  124. +  if (ref_chain->ref == NULL || DF_REF_INSN_INFO (ref_chain->ref) == NULL)
  125. +    return NULL;
  126. +
  127. +  rtx_insn *def_insn = DF_REF_INSN (ref_chain->ref);
  128. +  
  129. +  /* Check if def_insn has form
  130. +     (set (reg:SI)
  131. +     (and:SI (reg:SI)
  132. +         (const_int or reg:SI)))
  133. +   */
  134. +
  135. +  rtx pattern = PATTERN (def_insn);
  136. +  return ((GET_CODE (pattern) == SET)
  137. +          && reg_simode_p (SET_DEST (pattern))
  138. +          && (GET_CODE (SET_SRC (pattern)) == AND)
  139. +          && reg_simode_p (XEXP (SET_SRC (pattern), 0))
  140. +          && (reg_simode_p (XEXP (SET_SRC (pattern), 1))
  141. +         || (GET_CODE (XEXP (SET_SRC (pattern), 1)) == CONST_INT)))
  142. +   ? def_insn
  143. +   : NULL;
  144. +}
  145. +
  146. +rtx
  147. +pass_rtl_remove_temps::gen_andsi3_compare0_scratch (rtx op0, rtx op1)
  148. +{
  149. +  if (!s_register_operand (op0, SImode) || !arm_not_operand (op1, SImode))
  150. +    return NULL_RTX;
  151. +
  152. +  rtx reg = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
  153. +  rtx o0 = gen_rtx_AND (SImode, op0, op1);
  154. +  rtx o1 = GEN_INT (0);
  155. +  rtx compare_expr = gen_rtx_COMPARE (CC_NOOVmode, o0, o1);
  156. +  rtx x = gen_rtx_SET (reg, compare_expr);
  157. +
  158. +  rtx scratch_expr = gen_rtx_SCRATCH (SImode);
  159. +  rtx clobber_expr = gen_rtx_CLOBBER (VOIDmode, scratch_expr);
  160. +  rtx parallelexpr = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, x, clobber_expr));
  161. +
  162. +  return parallelexpr;
  163. +}
  164. +
  165. +rtx
  166. +pass_rtl_remove_temps::gen_zeroextractsi_compare0_scratch (rtx op0, rtx op1)
  167. +{
  168. +  if (!s_register_operand (op0, SImode))
  169. +    return NULL_RTX;
  170. +
  171. +  int x = INTVAL (op1);
  172. +  unsigned pos = getfirstbitpos (x);
  173. +  unsigned len = (getlastbitpos (x) - pos) + 1;
  174. +  
  175. +  if (!(TARGET_32BIT
  176. +   && pos >= 0 && pos < 32
  177. +   && len > 0
  178. +   && (len + (pos & 1) <= 8)
  179. +   && (len + pos <= 32)))
  180. +    return NULL_RTX;
  181. +
  182. +  if ((((1 << len) - 1) << pos) != x)
  183. +    return NULL_RTX;
  184. +
  185. +  rtx zexpr = gen_rtx_ZERO_EXTRACT (SImode, op0, GEN_INT (len), GEN_INT (pos));
  186. +  rtx compare_expr = gen_rtx_COMPARE (CC_NOOVmode, zexpr, GEN_INT (0));
  187. +  rtx reg = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
  188. +  return gen_rtx_SET (reg, compare_expr);
  189. +}
  190. +
  191. +/* we need to change reg:CC 100 in JUMP_INSN to reg:CC_NOOV 100 in
  192. +   (set (pc)
  193. +   (if_then_else (eq/ne (reg:CC 100)
  194. +                (const_int 0))
  195. +             (label-ref)
  196. +             (pc)))
  197. +*/
  198. +
  199. +void
  200. +pass_rtl_remove_temps::change_jump_insn (rtx_insn *next)
  201. +{
  202. +  gcc_assert (JUMP_P (next));
  203. +            
  204. +  rtx pat = PATTERN (next);
  205. +  rtx op = SET_SRC (pat);
  206. +  if (GET_CODE (op) == IF_THEN_ELSE)
  207. +    {
  208. +      rtx cond = XEXP (op, 0);
  209. +      if (GET_CODE (cond) == EQ || GET_CODE (cond) == NE)
  210. +   {
  211. +     rtx reg = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
  212. +     XEXP (cond, 0) = reg;
  213. +     df_insn_rescan (next);
  214. +   }
  215. +    }
  216. +}
  217. +
  218. +/* Transform compare-against-0 insn to rtx from either zeroextractsi_compare0_scratch
  219. + * or andsi3_compare0_scratch.
  220. + * codep stores ZERO_EXTRACT if we generate from zeroextractsi_compare0_scratch
  221. + * This is required because if we change this rtx to zeroextractsi_compare0_scratch
  222. + * reg:CC 100 in jump_insn needs to be changed to reg:CC_NOOV 100, to match the peephole
  223. + * pattern in thumb2.md:1527
  224. + */
  225. +rtx
  226. +pass_rtl_remove_temps::fold (rtx pat, enum rtx_code *codep)
  227. +{
  228. +  rtx and_expr = SET_SRC (pat);
  229. +  rtx op0 = XEXP (and_expr, 0);
  230. +  rtx op1 = XEXP (and_expr, 1);
  231. +
  232. +  if (GET_CODE (op1) == CONST_INT)
  233. +    {
  234. +      rtx x = gen_zeroextractsi_compare0_scratch (op0, op1);
  235. +      if (x != NULL_RTX)
  236. +        {
  237. +     *codep = ZERO_EXTRACT;
  238. +     return x;
  239. +   }
  240. +    }
  241. +
  242. +  *codep = AND;
  243. +  return gen_andsi3_compare0_scratch (op0, op1);
  244. +}
  245. +
  246. +bool
  247. +pass_rtl_remove_temps::gate (function *)
  248. +{
  249. +  return flag_rtl_remove_temps != 0 && optimize > 0;
  250. +}
  251. +
  252. +} // anon namespace
  253. +
  254. +void
  255. +pass_rtl_remove_temps::do_remove_temp (rtx_insn *insn)
  256. +{
  257. + /* Check for:
  258. +         (set (reg:cc)
  259. +         (compare:cc (reg:SI)
  260. +             (const_int 0)))
  261. +  */
  262. +
  263. +  rtx pattern = PATTERN (insn);
  264. +  if (GET_CODE (pattern) == SET
  265. +      && (REG_P (SET_DEST (pattern))) && GET_MODE (SET_DEST (pattern)) == CCmode
  266. +      && (GET_CODE (SET_SRC (pattern)) == COMPARE))
  267. +    {
  268. +      rtx compare_expr = SET_SRC (pattern);
  269. +      rtx op0 = XEXP (compare_expr, 0);
  270. +      rtx op1 = XEXP (compare_expr, 1);
  271. +
  272. +      if (REG_P (op0) && (GET_MODE (op0) == SImode)
  273. +     && (GET_CODE (op1) == CONST_INT) && (INTVAL (op1) == 0))
  274. +   {
  275. +     rtx_insn *def_insn = pass_rtl_remove_temps::get_def_insn (insn, op0);
  276. +     if (def_insn)
  277. +       {
  278. +         enum rtx_code code = UNKNOWN;
  279. +         rtx x = pass_rtl_remove_temps::fold (PATTERN (def_insn), &code);
  280. +         if (x != NULL_RTX)
  281. +       {
  282. +         rtx_insn *a = emit_insn_before (x, insn);
  283. +         recog_memoized (a);
  284. +         df_insn_rescan (a);
  285. +         if (code == ZERO_EXTRACT)
  286. +           change_jump_insn (NEXT_INSN (insn));
  287. +         delete_insn (insn);
  288. +       }
  289. +       }
  290. +       }
  291. +    }
  292. +}
  293. +
  294. +
  295. +unsigned int
  296. +pass_rtl_remove_temps::execute (function *)
  297. +{
  298. +  df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
  299. +  df_chain_add_problem (DF_UD_CHAIN);
  300. +  df_analyze ();
  301. +  df_set_flags (DF_DEFER_INSN_RESCAN);
  302. +
  303. +  rtx_insn *next;
  304. +
  305. +  for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
  306. +    {
  307. +      if (!INSN_P (insn))
  308. +   continue;
  309. +
  310. +      do_remove_temp (insn);
  311. +    }
  312. +
  313. +  return 0;
  314. +}
  315. +
  316. +rtl_opt_pass *
  317. +make_pass_rtl_remove_temps (gcc::context *ctxt)
  318. +{
  319. +  return new pass_rtl_remove_temps (ctxt);
  320. +}
  321. +
  322.  #include "gt-arm.h"
  323. diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt
  324. index c9095b9..20b1d05 100644
  325. --- a/gcc/config/arm/arm.opt
  326. +++ b/gcc/config/arm/arm.opt
  327. @@ -281,3 +281,7 @@ Assume loading data from flash is slower than fetching instructions.
  328.  masm-syntax-unified
  329.  Target Report Var(inline_asm_unified) Init(0) Save
  330.  Assume unified syntax for Thumb inline assembly code.
  331. +
  332. +fremove-temps
  333. +Target Report Var(flag_rtl_remove_temps) Optimization
  334. +Fold arm_andsi3_insn/arm_cmpsi_insn to zeroextractsi_compare0_scratch or andsi3_compare0_scratch
Advertisement
Add Comment
Please, Sign In to add comment