Commit 5fd9fcfb authored by Andreas Fried's avatar Andreas Fried
Browse files

Add a volatility flag to CopyB nodes.

This requires to actually compute volatility in a number of places.
Therefore, this also adds some helper functions to do that.
parent b239a80e
......@@ -1291,3 +1291,129 @@ void mark_private_methods(void)
pmap_destroy(mtp_map);
}
/**
* Find the entity that the given pointer points to.
*
* This function returns the entity into which @c ptr points, ignoring
* any offsets (it assumes that offsets always stay within the
* entity).
*
* This function does *not* always return a top-level entity
* (i.e. local/global variable), but may also return a member of
* another entity.
*
* If no entity can be found (e.g. pointer is itself result of a
* Load), NULL is returned.
*/
static ir_entity *find_entity(ir_node *ptr)
{
switch (get_irn_opcode(ptr)) {
case iro_SymConst:
return get_SymConst_entity(ptr);
case iro_Sel:
return get_Sel_entity(ptr);
case iro_Sub:
case iro_Add: {
ir_node *left = get_binop_left(ptr);
if (mode_is_reference(get_irn_mode(left)))
return find_entity(left);
ir_node *right = get_binop_right(ptr);
if (mode_is_reference(get_irn_mode(right)))
return find_entity(right);
return NULL;
}
default:
return NULL;
}
}
/**
* Returns true, if the entity that the given pointer points to is
* volatile itself, or if it is part of a larger volatile entity.
*
* If no entity can be found (@see find_entity), the functions assumes
* volatility.
*/
static bool is_inside_volatile_entity(ir_node *ptr)
{
ir_entity *ent = find_entity(ptr);
// TODO Probably a pointer, follow the Load(s) to the actual entity
if (!ent) return true;
if (get_entity_volatility(ent) == volatility_is_volatile) {
return true;
}
if (is_Sel(ptr)) {
ir_node *sel_ptr = get_Sel_ptr(ptr);
return is_inside_volatile_entity(sel_ptr);
} else {
return false;
}
}
/**
* Returns true, if the given type is compound and contains at least
* one entity which is volatile.
*/
static bool contains_volatile_entity(ir_type *type)
{
size_t n;
switch (get_type_tpop_code(type)) {
case tpo_class: n = get_class_n_members(type);
break;
case tpo_struct: n = get_struct_n_members(type);
break;
case tpo_union: n = get_union_n_members(type);
break;
default:
return false;
}
for (size_t i = 0; i < n; i++) {
ir_entity *ent;
switch (get_type_tpop_code(type)) {
case tpo_class: ent = get_class_member(type, i);
break;
case tpo_struct: ent = get_struct_member(type, i);
break;
case tpo_union: ent = get_union_member(type, i);
break;
default: abort(); // Should never happen
}
if (get_entity_volatility(ent) == volatility_is_volatile)
return true;
ir_type *ent_type = get_entity_type(ent);
if (contains_volatile_entity(ent_type))
return true;
}
return false;
}
/**
* Returns true, if the entity that the given pointer points to is...
* - volatile itself
* - part of a larger volatile entity
* - of a type which contains volatile entities.
*
* If no entity can be found (@see find_entity), the function assumes
* volatility.
*/
bool is_partly_volatile(ir_node *ptr)
{
ir_entity *ent = find_entity(ptr);
if (!ent) return true;
ir_type *type = get_entity_type(ent);
return contains_volatile_entity(type) ||
is_inside_volatile_entity(ptr);
}
......@@ -17,4 +17,6 @@
*/
void firm_init_memory_disambiguator(void);
bool is_partly_volatile(ir_node *ptr);
#endif
......@@ -26,6 +26,7 @@
#include "raw_bitset.h"
#include "error.h"
#include "pset_new.h"
#include "irmemory_t.h"
#include "be.h"
#include "beabi.h"
......@@ -413,7 +414,11 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
} else {
/* Make a mem copy for compound arguments. */
assert(mode_is_reference(get_irn_mode(param)));
mem = new_rd_CopyB(dbgi, bl, curr_mem, addr, param, param_type);
bool is_volatile = is_partly_volatile(addr) ||
is_partly_volatile(param);
mem = new_rd_CopyB(dbgi, bl, curr_mem, addr, param, param_type, is_volatile ? cons_volatile : cons_none);
}
curr_ofs += param_size;
......
......@@ -315,7 +315,8 @@ typedef struct confirm_attr {
/** CopyB attribute. */
typedef struct copyb_attr {
ir_type *type; /**< Type of the copied entity. */
ir_type *type; /**< Type of the copied entity. */
__extension__ ir_volatility volatility:1; /**< The volatility of this CopyB operation. */
} copyb_attr;
/** Div attribute. */
......
......@@ -10,6 +10,7 @@
*/
#include <stdbool.h>
#include "firm_types.h"
#include "lower_calls.h"
#include "lowering.h"
#include "irprog_t.h"
......@@ -20,6 +21,7 @@
#include "irgmod.h"
#include "irgwalk.h"
#include "irmemory.h"
#include "irmemory_t.h"
#include "irtools.h"
#include "iroptimize.h"
#include "array_t.h"
......@@ -608,14 +610,16 @@ static void fix_compound_params(cl_entry *entry, ir_type *ctp)
ir_node *arg;
ir_node *sel;
ir_entity *arg_entity;
bool is_volatile;
if (!needs_lowering(type))
continue;
arg = get_Call_param(call, i);
arg_entity = create_compound_arg_entity(irg, type);
block = get_nodes_block(call);
sel = new_rd_simpleSel(dbgi, block, nomem, frame, arg_entity);
mem = new_rd_CopyB(dbgi, block, mem, sel, arg, type);
arg = get_Call_param(call, i);
arg_entity = create_compound_arg_entity(irg, type);
block = get_nodes_block(call);
sel = new_rd_simpleSel(dbgi, block, nomem, frame, arg_entity);
is_volatile = is_partly_volatile(arg);
mem = new_rd_CopyB(dbgi, block, mem, sel, arg, type, is_volatile ? cons_volatile : cons_none);
set_Call_param(call, i, sel);
}
set_Call_mem(call, mem);
......@@ -775,7 +779,9 @@ static void transform_irg(compound_call_lowering_flags flags, ir_graph *irg)
} else {
/* copy-return optimization is impossible, do the
* copy. */
mem = new_r_CopyB(bl, mem, arg, pred, tp);
bool is_volatile = is_partly_volatile(pred);
mem = new_r_CopyB(bl, mem, arg, pred, tp, is_volatile ? cons_volatile : cons_none);
}
}
if (flags & LF_RETURN_HIDDEN) {
......
......@@ -10,6 +10,7 @@
*/
#include <string.h>
#include "entity_t.h"
#include "error.h"
#include "iroptimize.h"
#include "irnode_t.h"
......@@ -967,7 +968,6 @@ static unsigned follow_Mem_chain_for_Store(ir_node *store, ir_node *curr, bool h
return res;
}
/** find entity used as base for an address calculation */
static ir_entity *find_entity(ir_node *ptr)
{
switch (get_irn_opcode(ptr)) {
......
......@@ -15,6 +15,7 @@
#include "irnode_t.h"
#include "irgraph_t.h"
#include "irprog_t.h"
#include "entity_t.h"
#include "iroptimize.h"
#include "ircons_t.h"
......@@ -36,6 +37,7 @@
#include "cgana.h"
#include "trouts.h"
#include "error.h"
#include "irmemory_t.h"
#include "analyze_irg_args.h"
#include "iredges_t.h"
......@@ -317,7 +319,10 @@ static void copy_parameter_entities(ir_node *call, ir_graph *called_graph)
ir_node *new_mem;
if (is_compound_type(old_type) || is_Array_type(old_type)) {
/* Copy the compound parameter */
new_mem = new_rd_CopyB(dbgi, block, call_mem, sel, param, old_type);
bool is_volatile = is_partly_volatile(param) || is_partly_volatile(sel);
new_mem = new_rd_CopyB(dbgi, block, call_mem, sel, param, old_type, is_volatile ? cons_volatile : cons_none);
set_Call_param(call, n_param_pos, sel);
if (have_copyb) {
ARR_APP1(ir_node*, sync_mem, new_mem);
......
......@@ -420,9 +420,23 @@ class CopyB:
name = "type",
type = "ir_type*",
comment = "type of copied data",
),
dict(
type = "ir_volatility",
name = "volatility",
comment = "volatile CopyB nodes have a visible side-effect and may not be optimized",
init = "flags & cons_volatile ? volatility_is_volatile : volatility_non_volatile",
to_flags = "%s == volatility_is_volatile ? cons_volatile : cons_none"
)
]
attr_struct = "copyb_attr"
constructor_args = [
dict(
type = "ir_cons_flags",
name = "flags",
comment = "specifies volatility",
),
]
pinned = "no"
@op
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment