Added option to prevent creation of misaligned loads/stores during CopyB lowering.
authorManuel Mohr <manuel.mohr@kit.edu>
Tue, 27 Sep 2011 08:05:39 +0000 (10:05 +0200)
committerManuel Mohr <manuel.mohr@kit.edu>
Tue, 27 Sep 2011 08:06:49 +0000 (10:06 +0200)
include/libfirm/lowering.h
ir/be/amd64/bearch_amd64.c
ir/be/arm/bearch_arm.c
ir/be/ia32/bearch_ia32.c
ir/be/sparc/bearch_sparc.c
ir/lower/lower_copyb.c

index d031a2b..a928d08 100644 (file)
  *                            that it is still considered 'small'.
  * @param min_large_size      The minimum number of bytes for a CopyB node so
  *                            that it is regarded as 'large'.
+ * @param allow_misalignments Backend can handle misaligned loads and stores.
  */
 FIRM_API void lower_CopyB(ir_graph *irg, unsigned max_small_size,
-                          unsigned min_large_size);
+                          unsigned min_large_size, int allow_misalignments);
 
 /**
  * Lowers all Switches (Cond nodes with non-boolean mode) depending on spare_size.
index 57ea929..2d0eb18 100644 (file)
@@ -481,7 +481,7 @@ static void amd64_lower_for_target(void)
                 * CopyBs into memcpy calls, because we cannot handle CopyB nodes
                 * during code generation yet.
                 * TODO:  Adapt this once custom CopyB handling is implemented. */
-               lower_CopyB(irg, 64, 65);
+               lower_CopyB(irg, 64, 65, true);
        }
 }
 
index 9e1edbc..585d1b7 100644 (file)
@@ -548,7 +548,7 @@ static void arm_lower_for_target(void)
                /* Turn all small CopyBs into loads/stores and all bigger CopyBs into
                 * memcpy calls.
                 * TODO:  These constants need arm-specific tuning. */
-               lower_CopyB(irg, 31, 32);
+               lower_CopyB(irg, 31, 32, false);
        }
 }
 
index 56fa4f3..6c94d98 100644 (file)
@@ -2070,7 +2070,7 @@ static void ia32_lower_for_target(void)
                /* Turn all small CopyBs into loads/stores, keep medium-sized CopyBs,
                 * so we can generate rep movs later, and turn all big CopyBs into
                 * memcpy calls. */
-               lower_CopyB(irg, 64, 8193);
+               lower_CopyB(irg, 64, 8193, true);
        }
 }
 
index 39da8dc..92c0425 100644 (file)
@@ -444,7 +444,7 @@ static void sparc_lower_for_target(void)
                ir_graph *irg = get_irp_irg(i);
                /* Turn all small CopyBs into loads/stores and all bigger CopyBs into
                 * memcpy calls. */
-               lower_CopyB(irg, 31, 32);
+               lower_CopyB(irg, 31, 32, false);
        }
 }
 
index b4b114c..e5f88ce 100644 (file)
@@ -86,6 +86,8 @@ static unsigned max_small_size; /**< The maximum size of a CopyB node
 static unsigned min_large_size; /**< The minimum size of a CopyB node
                                      so that it is regarded as 'large'. */
 static unsigned native_mode_bytes; /**< The size of the native mode in bytes. */
+static int allow_misalignments; /**< Whether backend can handle misaligned
+                                     loads and stores. */
 
 typedef struct walk_env {
        struct obstack   obst;           /**< the obstack where data is allocated
@@ -112,27 +114,17 @@ static ir_mode *get_ir_mode(unsigned mode_bytes)
 static void lower_small_copyb_node(ir_node *irn)
 {
        ir_graph *irg        = get_irn_irg(irn);
-       unsigned  mode_bytes = native_mode_bytes;
-       unsigned  size;
-       unsigned  offset;
+       ir_node  *block      = get_nodes_block(irn);
+       ir_type  *tp         = get_CopyB_type(irn);
+       ir_node  *addr_src   = get_CopyB_src(irn);
+       ir_node  *addr_dst   = get_CopyB_dst(irn);
+       ir_node  *mem        = get_CopyB_mem(irn);
+       ir_mode  *addr_mode  = get_irn_mode(addr_src);
+       unsigned  mode_bytes = allow_misalignments ? native_mode_bytes : tp->align;
+       unsigned  size       = get_type_size_bytes(tp);
+       unsigned  offset     = 0;
        ir_mode  *mode;
-       ir_mode  *addr_mode;
-       ir_node  *mem;
-       ir_node  *addr_src;
-       ir_node  *addr_dst;
-       ir_node  *block;
-       ir_type  *tp;
-
-       addr_src  = get_CopyB_src(irn);
-       addr_dst  = get_CopyB_dst(irn);
-       mem       = get_CopyB_mem(irn);
-       addr_mode = get_irn_mode(addr_src);
-       block     = get_nodes_block(irn);
-
-       tp   = get_CopyB_type(irn);
-       size = get_type_size_bytes(tp);
-
-       offset     = 0;
+
        while (offset < size) {
                mode = get_ir_mode(mode_bytes);
                for (; offset + mode_bytes <= size; offset += mode_bytes) {
@@ -280,7 +272,8 @@ static void find_copyb_nodes(ir_node *irn, void *ctx)
        list_add_tail(&entry->list, &env->list);
 }
 
-void lower_CopyB(ir_graph *irg, unsigned max_small_sz, unsigned min_large_sz)
+void lower_CopyB(ir_graph *irg, unsigned max_small_sz, unsigned min_large_sz,
+                 int allow_misaligns)
 {
        const backend_params *bparams = be_get_backend_param();
        walk_env_t            env;
@@ -288,9 +281,10 @@ void lower_CopyB(ir_graph *irg, unsigned max_small_sz, unsigned min_large_sz)
 
        assert(max_small_sz < min_large_sz && "CopyB size ranges must not overlap");
 
-       max_small_size    = max_small_sz;
-       min_large_size    = min_large_sz;
-       native_mode_bytes = bparams->machine_size / 8;
+       max_small_size      = max_small_sz;
+       min_large_size      = min_large_sz;
+       native_mode_bytes   = bparams->machine_size / 8;
+       allow_misalignments = allow_misaligns;
 
        obstack_init(&env.obst);
        INIT_LIST_HEAD(&env.list);