- cleaned up spill/reload transform code a bit
authorMatthias Braun <matze@braunis.de>
Fri, 15 Dec 2006 16:39:30 +0000 (16:39 +0000)
committerMatthias Braun <matze@braunis.de>
Fri, 15 Dec 2006 16:39:30 +0000 (16:39 +0000)
- don't do address mode if spill size is bad (no addressmode for mode_E)
- don't do super exact spilling for now
- fixed bug where node compare didn't respect some node attributes

ir/be/ia32/bearch_ia32.c
ir/be/ia32/ia32_new_nodes.c
ir/be/ia32/ia32_spec.pl

index a8c5240..a9e04cb 100644 (file)
@@ -723,6 +723,43 @@ static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, in
        return inverse;
 }
 
+/**
+ * Get the mode that should be used for spilling value node
+ */
+static ir_mode *get_spill_mode(ia32_code_gen_t *cg, const ir_node *node)
+{
+       ir_mode *mode = get_irn_mode(node);
+       if (mode_is_float(mode)) {
+#if 0
+               // super exact spilling...
+               if (USE_SSE2(cg))
+                       return mode_D;
+               else
+                       return mode_E;
+#else
+               return mode;
+#endif
+       }
+       else
+               return mode_Is;
+
+       assert(0);
+       return mode;
+}
+
+/**
+ * Checks wether an addressmode reload for a node with mode mode is compatible
+ * with a spillslot of mode spill_mode
+ */
+static int ia32_is_spillmode_compatible(const ir_mode *mode, const ir_mode *spillmode)
+{
+       if(mode_is_float(mode)) {
+               return mode == spillmode;
+       } else {
+               return 1;
+       }
+}
+
 /**
  * Check if irn can load it's operand at position i from memory (source addressmode).
  * @param self   Pointer to irn ops itself
@@ -731,10 +768,17 @@ static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, in
  * @return Non-Zero if operand can be loaded
  */
 static int ia32_possible_memory_operand(const void *self, const ir_node *irn, unsigned int i) {
+       const ia32_irn_ops_t *ops = self;
+       ia32_code_gen_t      *cg  = ops->cg;
+       ir_node *op = get_irn_n(irn, i);
+       const ir_mode *mode = get_irn_mode(op);
+       const ir_mode *spillmode = get_spill_mode(cg, op);
+
        if (! is_ia32_irn(irn)                            ||  /* must be an ia32 irn */
                get_irn_arity(irn) != 5                       ||  /* must be a binary operation */
                get_ia32_op_type(irn) != ia32_Normal          ||  /* must not already be a addressmode irn */
                ! (get_ia32_am_support(irn) & ia32_am_Source) ||  /* must be capable of source addressmode */
+               ! ia32_is_spillmode_compatible(mode, spillmode) ||
                (i != 2 && i != 3)                            ||  /* a "real" operand position must be requested */
                (i == 2 && ! is_ia32_commutative(irn))        ||  /* if first operand requested irn must be commutative */
                is_ia32_use_frame(irn))                           /* must not already use frame */
@@ -980,12 +1024,12 @@ static void ia32_before_ra(void *self) {
 
 
 /**
- * Transforms a be node into a Load.
+ * Transforms a be_Reload into a ia32 Load.
  */
 static void transform_to_Load(ia32_transform_env_t *env) {
        ir_node *irn         = env->irn;
        ir_entity *ent       = be_get_frame_entity(irn);
-       ir_mode *mode        = env->mode;
+       ir_mode *mode        = get_spill_mode(env->cg, irn);
        ir_node *noreg       = ia32_new_NoReg_gp(env->cg);
        ir_node *sched_point = NULL;
        ir_node *ptr         = get_irg_frame(env->irg);
@@ -1034,12 +1078,13 @@ static void transform_to_Load(ia32_transform_env_t *env) {
 }
 
 /**
- * Transforms a be node into a Store.
+ * Transforms a be_Spill node into a ia32 Store.
  */
 static void transform_to_Store(ia32_transform_env_t *env) {
        ir_node *irn   = env->irn;
        ir_entity *ent = be_get_frame_entity(irn);
-       ir_mode *mode  = env->mode;
+       const ir_node *spillval = get_irn_n(irn, be_pos_Spill_val);
+       ir_mode *mode  = get_spill_mode(env->cg, spillval);
        ir_node *noreg = ia32_new_NoReg_gp(env->cg);
        ir_node *nomem = new_rd_NoMem(env->irg);
        ir_node *ptr   = get_irg_frame(env->irg);
@@ -1209,22 +1254,6 @@ static void transform_MemPerm(ia32_transform_env_t *env) {
        sched_remove(node);
 }
 
-/**
- * Fix the mode of Spill/Reload
- */
-static ir_mode *fix_spill_mode(ia32_code_gen_t *cg, ir_mode *mode)
-{
-       if (mode_is_float(mode)) {
-               if (USE_SSE2(cg))
-                       mode = mode_D;
-               else
-                       mode = mode_E;
-       }
-       else
-               mode = mode_Is;
-       return mode;
-}
-
 /**
  * Block-Walker: Calls the transform functions Spill and Reload.
  */
@@ -1241,24 +1270,15 @@ static void ia32_after_ra_walker(ir_node *block, void *env) {
        /* beware: the schedule is changed here */
        for (node = sched_last(block); !sched_is_begin(node); node = prev) {
                prev = sched_prev(node);
+               tenv.dbg  = get_irn_dbg_info(node);
+               tenv.irn  = node;
+               tenv.mode = get_irn_mode(node);
+
                if (be_is_Reload(node)) {
-                       /* we always reload the whole register  */
-                       tenv.dbg  = get_irn_dbg_info(node);
-                       tenv.irn  = node;
-                       tenv.mode = fix_spill_mode(cg, get_irn_mode(node));
                        transform_to_Load(&tenv);
-               }
-               else if (be_is_Spill(node)) {
-                       ir_node *spillval = get_irn_n(node, be_pos_Spill_val);
-                       /* we always spill the whole register  */
-                       tenv.dbg  = get_irn_dbg_info(node);
-                       tenv.irn  = node;
-                       tenv.mode = fix_spill_mode(cg, get_irn_mode(spillval));
+               } else if (be_is_Spill(node)) {
                        transform_to_Store(&tenv);
-               }
-               else if(be_is_MemPerm(node)) {
-                       tenv.dbg = get_irn_dbg_info(node);
-                       tenv.irn = node;
+               } else if(be_is_MemPerm(node)) {
                        transform_MemPerm(&tenv);
                }
        }
@@ -1267,9 +1287,6 @@ static void ia32_after_ra_walker(ir_node *block, void *env) {
 /**
  * We transform Spill and Reload here. This needs to be done before
  * stack biasing otherwise we would miss the corrected offset for these nodes.
- *
- * If x87 instruction should be emitted, run the x87 simulator and patch
- * the virtual instructions. This must obviously be done after register allocation.
  */
 static void ia32_after_ra(void *self) {
        ia32_code_gen_t *cg = self;
@@ -1281,7 +1298,9 @@ static void ia32_after_ra(void *self) {
 }
 
 /**
- * Last touchups for the graph before emit
+ * Last touchups for the graph before emit: x87 simulation to replace the
+ * virtual with real x87 instructions, creating a block schedule and peephole
+ * optimisations.
  */
 static void ia32_finish(void *self) {
        ia32_code_gen_t *cg = self;
index 2e099b1..e95456f 100644 (file)
@@ -349,7 +349,7 @@ static int ia32_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
                        fprintf(F, "AM scale = %d\n", get_ia32_am_scale(n));
 
                        /* dump pn code */
-                       fprintf(F, "pn_code = %ld\n", get_ia32_pncode(n));
+                       fprintf(F, "pn_code = %ld (%s)\n", get_ia32_pncode(n), get_pnc_string(get_ia32_pncode(n)));
 
                        /* dump n_res */
                        fprintf(F, "n_res = %d\n", get_ia32_n_res(n));
@@ -1386,13 +1386,28 @@ void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags, const ia32_regi
 int ia32_compare_immop_attr(ia32_attr_t *a, ia32_attr_t *b) {
        int equ = 0;
 
-       if (a->data.tp == b->data.tp) {
-               equ = (a->cnst == b->cnst);
-               equ = equ ? (a->data.use_frame == b->data.use_frame) : 0;
+       if (a->data.tp != b->data.tp)
+               return 1;
 
-               if (equ && a->data.use_frame && b->data.use_frame)
-                       equ = (a->frame_ent == b->frame_ent);
-       }
+       if (a->cnst != b->cnst)
+               return 1;
+
+       if (a->data.use_frame != b->data.use_frame)
+               return 1;
+
+       if (a->data.use_frame && a->frame_ent != b->frame_ent)
+               return 1;
+
+       if (a->data.am_flavour != b->data.am_flavour
+                       || a->data.am_scale != b->data.am_scale
+                       || a->data.offs_sign != b->data.offs_sign
+                       || a->data.am_sc_sign != b->data.am_sc_sign
+                       || a->am_offs != b->am_offs
+                       || a->am_sc != b->am_sc)
+               return 1;
+
+       if(a->pn_code != b->pn_code)
+               return 1;
 
        return !equ;
 }
index 3935c82..7b3c2fa 100644 (file)
@@ -1230,6 +1230,7 @@ else {
   "comment"   => "construct Set: Set(sel) == sel ? 1 : 0",
   "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "eax ebx ecx edx", "none" ] },
   "outs"      => [ "res", "M" ],
+  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "latency"   => 2,
   "units"     => [ "ALU" ],
 },