summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJohannes Bucher <johannes.bucher2@student.kit.edu>2021-04-01 15:31:59 +0200
committerJohannes Bucher <johannes.bucher2@student.kit.edu>2021-04-01 15:31:59 +0200
commit8897db7caa601b79d5b003af2dea8e65257a2597 (patch)
treeeed97562a24c05d6e05257314da3e2c3ca376e18
parenta1a52aa28f446f8d0ec2147dda1d2abb5ca7f12b (diff)
WIP handle copybs in scalar replacementtmp-amd64-improvements
-rw-r--r--ir/opt/scalar_replace.c123
1 files changed, 119 insertions, 4 deletions
diff --git a/ir/opt/scalar_replace.c b/ir/opt/scalar_replace.c
index 4173d5a..614c24f 100644
--- a/ir/opt/scalar_replace.c
+++ b/ir/opt/scalar_replace.c
@@ -151,6 +151,10 @@ typedef struct {
ir_node **copybs;
} copyb_walk_env_t;
+static pset *copybs;
+/* TODO: Ask the backend for the maximum size */
+static unsigned copyb_max_members = 8;
+
static void lower_copyb_node(ir_node *copyb)
{
ir_node *block = get_nodes_block(copyb);
@@ -184,6 +188,55 @@ static void lower_copyb_node(ir_node *copyb)
exchange(copyb, mem);
}
+static void lower_copyb_node_new(ir_node *copyb, bool sr_src, bool sr_dst)
+{
+ ir_node *block = get_nodes_block(copyb);
+ ir_node *src = get_CopyB_src(copyb);
+ ir_node *dst = get_CopyB_dst(copyb);
+ ir_node *mem = get_CopyB_mem(copyb);
+ dbg_info *dbgi = get_irn_dbg_info(copyb);
+ ir_type *ty = get_CopyB_type(copyb);
+ bool is_volatile = get_CopyB_volatility(copyb) == volatility_is_volatile;
+ ir_cons_flags flags = is_volatile ? cons_volatile : cons_none;
+
+ ir_node *src_link = get_entity_link(get_Member_entity(src));
+ ir_node *dst_link = get_entity_link(get_Member_entity(dst));
+
+ size_t n_members = get_compound_n_members(ty);
+
+ for (size_t m = 0; m < n_members; m++) {
+ ir_entity *member = get_compound_member(ty, m);
+ ir_type *member_type = get_entity_type(member);
+ ir_mode *member_mode = get_type_mode(member_type);
+ if (member_mode == NULL) {
+ member_mode = mode_P;
+ }
+
+ ir_node *src_member = new_rd_Member(dbgi, block, src, member);
+ ir_node *dst_member = new_rd_Member(dbgi, block, dst, member);
+ if (sr_src) {
+ set_irn_link(src_member, src_link);
+ src_link = src_member;
+ }
+ if (sr_dst) {
+ set_irn_link(dst_member, dst_link);
+ dst_link = dst_member;
+ }
+ ir_node *load = new_rd_Load(dbgi, block, mem, src_member, member_mode, member_type, flags);
+ mem = new_rd_Proj(dbgi, load, mode_M, pn_Load_M);
+ ir_node *res = new_rd_Proj(dbgi, load, member_mode, pn_Load_res);
+ ir_node *store = new_rd_Store(dbgi, block, mem, dst_member, res, member_type, flags);
+ mem = new_rd_Proj(dbgi, store, mode_M, pn_Store_M);
+ }
+
+ if (sr_src)
+ set_entity_link(get_Member_entity(src), src_link);
+ if (sr_dst)
+ set_entity_link(get_Member_entity(dst), dst_link);
+
+ exchange(copyb, mem);
+}
+
/**
* Post-Walker: find CopyB nodes.
*/
@@ -223,6 +276,36 @@ static void find_copyb_nodes(ir_node *irn, void *ctx)
ARR_APP1(ir_node*, env->copybs, irn);
}
+static bool copyb_suitable(ir_node *copyb)
+{
+ ir_node *irg_frame = get_irg_frame(get_irn_irg(copyb));
+ ir_node *src = get_CopyB_src(copyb);
+ ir_node *dst = get_CopyB_dst(copyb);
+
+ if (!is_Member(src) || get_Member_ptr(src) != irg_frame ||
+ !is_Member(dst) || get_Member_ptr(dst) != irg_frame)
+ return false;
+
+ ir_type *tp = get_CopyB_type(copyb);
+
+ if (!is_compound_type(tp))
+ return false;
+
+ size_t members = get_compound_n_members(tp);
+
+ if (members > copyb_max_members)
+ return false;
+
+ for (size_t m = 0; m < members; m++) {
+ ir_entity *member = get_compound_member(tp, m);
+ ir_type *mtp = get_entity_type(member);
+
+ if (!is_atomic_type(mtp))
+ return false;
+ }
+ return true;
+}
+
/**
* Lowers CopyB nodes to sequences of load and stores. Unlike the
* function in lower/lower_copyb.c, this one here uses Member nodes
@@ -303,6 +386,12 @@ bool is_address_taken(ir_node *node)
return true;
break;
}
+ case iro_CopyB: {
+ bool res = copyb_suitable(succ);
+ if (!res)
+ return true;
+ break;
+ }
default:
/* another op, the address is taken */
@@ -320,6 +409,7 @@ typedef enum leaf_state_t {
POSSIBLE_LEAF = 0,
HAS_CHILD_LOAD_STORE = (1u << 0),
HAS_CHILD_SELS = (1u << 1),
+ HAS_CHILD_COPYB = (1u << 2),
} leaf_state_t;
/**
@@ -333,8 +423,12 @@ static leaf_state_t link_all_leaf_members(ir_entity *ent, ir_node *sel)
/** A leaf Sel is a Sel that is used directly by a Load or Store. */
leaf_state_t state = POSSIBLE_LEAF;
foreach_irn_out_r(sel, i, succ) {
- if (is_Load(succ) || is_Store(succ)) {
+ if (is_Load(succ) || is_Store(succ) || is_CopyB(succ)) {
state |= HAS_CHILD_LOAD_STORE;
+ if (is_CopyB(succ)) {
+ state |= HAS_CHILD_COPYB;
+ pset_insert_ptr(copybs, succ); //TODO move to end?
+ }
continue;
}
if (is_Member(succ)) {
@@ -366,6 +460,12 @@ static leaf_state_t link_all_leaf_members(ir_entity *ent, ir_node *sel)
/* we know we are at a leaf, because this function is only called if
* the address is NOT taken, so sel's successor(s) must be Loads or
* Stores */
+ if (state & HAS_CHILD_COPYB) {
+ /* skip sels/members with CopyB successors, as those are replaced with new member nodes
+ * when lowering the CopyB node
+ * TODO: breaks for chains with only such member nodes (entity will have link NULL) */
+ return state;
+ }
set_irn_link(sel, link);
set_entity_link(ent, sel);
return state;
@@ -425,7 +525,7 @@ static bool find_possible_replacements(ir_graph *irg)
if (get_entity_link(ent) == NULL)
++res;
link_all_leaf_members(ent, succ);
- DB((dbg, LEVEL_3, "Mabye\n"));
+ DB((dbg, LEVEL_3, "Maybe\n"));
}
} else {
DB((dbg, LEVEL_3, "No, unsupported type\n"));
@@ -674,8 +774,8 @@ static void do_scalar_replacements(ir_graph *irg, pset *members, unsigned nvals,
void scalar_replacement_opt(ir_graph *irg)
{
/* TODO: Ask the backend for the maximum size */
- lower_CopyB_to_Member(irg, 8);
- be_after_transform(irg, "hl-lower-copyb");
+ //lower_CopyB_to_Member(irg, 8);
+ //be_after_transform(irg, "hl-lower-copyb");
assure_irg_properties(irg, IR_GRAPH_PROPERTY_NO_UNREACHABLE_CODE
| IR_GRAPH_PROPERTY_CONSISTENT_OUTS
@@ -685,6 +785,9 @@ void scalar_replacement_opt(ir_graph *irg)
ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK);
irp_reserve_resources(irp, IRP_RESOURCE_ENTITY_LINK);
+
+ copybs = pset_new_ptr(8);
+
/* Find possible scalar replacements */
bool changed = false;
if (find_possible_replacements(irg)) {
@@ -698,6 +801,17 @@ void scalar_replacement_opt(ir_graph *irg)
pset *sels = pset_new_ptr(8);
ir_type *frame_tp = get_irg_frame_type(irg);
+ /* replace CopyBs with pairs of load and store nodes */
+ foreach_pset(copybs, ir_node, copyb) {
+ ir_node *src_link = get_entity_link(get_Member_entity(get_CopyB_src(copyb)));
+ ir_node *dst_link = get_entity_link(get_Member_entity(get_CopyB_dst(copyb)));
+ bool scalar_replace_src = src_link != NULL && src_link != ADDRESS_TAKEN;
+ bool scalar_replace_dst = dst_link != NULL && dst_link != ADDRESS_TAKEN;
+ if (scalar_replace_src || scalar_replace_dst) {
+ lower_copyb_node_new(copyb, scalar_replace_src, scalar_replace_dst);
+ }
+ }
+
foreach_irn_out_r(irg_frame, i, succ) {
if (!is_Member(succ))
continue;
@@ -746,6 +860,7 @@ void scalar_replacement_opt(ir_graph *irg)
changed = true;
}
del_pset(sels);
+ del_pset(copybs);
del_set(set_ent);
DEL_ARR_F(modes);
}