On 11/02/2012 02:34 AM, Bin Cheng wrote:

Also I don't understand why the bogus patch can catch more hoist
opportunities and improve code size, so please help if you have any idea
about this.
Well, perturbing the code, particularly in a way which is supposed to change the amount of register pressure is certainly going to affect the allocators and reload.

It shouldn't be that hard to look at results which differ between the two patches and analyze why they're different.


2012-11-02  Bin Cheng<bin.ch...@arm.com>

        * gcse.c: (struct bb_data): Add new fields, old_pressure, live_in
        and backup.
        (calculate_bb_reg_pressure): Initialize live_in and backup.
        (update_bb_reg_pressure): New.
        (should_hoist_expr_to_dom): Add new parameter from.
        Monitor the change of reg pressure and use it to drive hoisting.
        (hoist_code): Update LIVE and reg pressure information.

gcc/testsuite/ChangeLog
2012-11-02  Bin Cheng<bin.ch...@arm.com>

        * gcc.dg/hoist-register-pressure-3.c: New test.


+/* Update register pressure for BB when hoisting an expression from
+   instruction FROM, if live ranges of inputs are shrunk.  Also
+   maintain live_in information if live range of register referred
+   in FROM is shrunk.
+
+   Return 0 if register pressure doesn't change, otherwise return
+   the number by which register pressure is decreased.
+
+   NOTE: Register pressure won't be increased in this function.  */
+
+static int
+update_bb_reg_pressure (basic_block bb, rtx from,
+                       enum reg_class pressure_class, int nregs)
+{
+  rtx dreg, insn;
+  basic_block succ_bb;
+  df_ref *op, op_ref;
+  edge succ;
+  edge_iterator ei;
+  int decreased_pressure = 0;
+
+  for (op = DF_INSN_USES (from); *op; op++)
+    {
+      dreg = DF_REF_REAL_REG (*op);
+      /* The live range of register is shrunk only if it isn't:
+        1. referred on any path from the end of this block to EXIT, or
+        2. referred by insns other than FROM in this block.  */
+      FOR_EACH_EDGE (succ, ei, bb->succs)
+       {
+         succ_bb = succ->dest;
+         if (succ_bb == EXIT_BLOCK_PTR)
+           continue;
+
+         if (bitmap_bit_p (BB_DATA (succ_bb)->live_in, REGNO (dreg)))
+           break;
+       }
+      if (succ != NULL)
+       continue;
+
+      op_ref = DF_REG_USE_CHAIN (REGNO (dreg));
+      for (; op_ref; op_ref = DF_REF_NEXT_REG (op_ref))
+       {
+         if (!DF_REF_INSN_INFO (op_ref))
+           continue;
+
+         insn = DF_REF_INSN (op_ref);
+         if (BLOCK_FOR_INSN (insn) == bb
+             && NONDEBUG_INSN_P (insn) && insn != from)
+           break;
+       }
+
+      /* Decrease register pressure and update live_in information for
+        this block.  */
+      if (!op_ref)
+       {
+         decreased_pressure += nregs;
+         BB_DATA (bb)->max_reg_pressure[pressure_class] -= nregs;
+         bitmap_clear_bit (BB_DATA (bb)->live_in, REGNO (dreg));
+       }
+    }
+  return decreased_pressure;
So we're looking to see if any of the registers used in FROM are used after from. If none are used, then we decrease the register pressure by nregs which appears to be a property of the the registers *set* in FROM. Is seems like there's some inconsistency here. Or have I misunderstood something?

I'm not sure how much it matters in practice, except perhaps for conversions and the like where the source and destination operands are different modes.
jeff

Reply via email to