Commit b719d82d authored by Matthias Braun's avatar Matthias Braun
Browse files

API change+fix for IncSP alignment

- alignment is set on each single IncSP now instead of a global arch_env
  setting
- fixed ia32 not requesting any alignment anymore (even on darwin where
  we need it)
- fixed amd64 creating IncSP nodes without flag_modifies_flags set
parent 14b3c4c7
......@@ -113,7 +113,6 @@ static TEMPLATE_isa_t TEMPLATE_isa_template = {
.register_classes = TEMPLATE_reg_classes,
.sp = &TEMPLATE_registers[REG_SP],
.bp = &TEMPLATE_registers[REG_BP],
.stack_alignment = 2, /* power of two stack alignment */
.spill_cost = 7,
.reload_cost = 5,
},
......
......@@ -384,12 +384,13 @@ static ir_node *gen_Address(ir_node *node)
}
}
static ir_node *create_IncSP(const arch_register_t *sp_reg, ir_node *block,
ir_node *old_sp, int offset, int align)
ir_node *amd64_new_IncSP(ir_node *block, ir_node *old_sp, int offset,
unsigned align)
{
ir_node *res = be_new_IncSP(sp_reg, block, old_sp, offset, align);
arch_add_irn_flags(res, arch_irn_flag_modify_flags);
return res;
ir_node *incsp = be_new_IncSP(&amd64_registers[REG_RSP], block, old_sp,
offset, align);
arch_add_irn_flags(incsp, arch_irn_flag_modify_flags);
return incsp;
}
typedef ir_node *(*construct_binop_func)(dbg_info *dbgi, ir_node *block,
......@@ -1510,8 +1511,9 @@ static ir_node *gen_Call(ir_node *node)
/* construct an IncSP -> we have to always be sure that the stack is
* aligned even if we don't push arguments on it */
const arch_register_t *sp_reg = &amd64_registers[REG_RSP];
ir_node *incsp = create_IncSP(sp_reg, new_block, new_frame,
cconv->param_stack_size, 1);
ir_node *incsp = amd64_new_IncSP(new_block, new_frame,
cconv->param_stack_size,
AMD64_PO2_STACK_ALIGNMENT);
/* match callee */
amd64_addr_t addr;
......@@ -1701,7 +1703,7 @@ static ir_node *gen_Call(ir_node *node)
set_irn_pinned(call, get_irn_pinned(node));
/* IncSP to destroy the call stackframe */
incsp = create_IncSP(sp_reg, new_block, incsp, -cconv->param_stack_size, 0);
incsp = amd64_new_IncSP(new_block, incsp, -cconv->param_stack_size, 0);
/* if we are the last IncSP producer in a block then we have to keep
* the stack value.
* Note: This here keeps all producers which is more than necessary */
......
......@@ -18,4 +18,7 @@ ir_node *amd64_new_reload(ir_node *value, ir_node *spill, ir_node *before);
void amd64_transform_graph(ir_graph *irg);
ir_node *amd64_new_IncSP(ir_node *block, ir_node *old_sp, int offset,
unsigned align);
#endif
......@@ -547,8 +547,8 @@ static void introduce_epilogue(ir_node *ret)
set_irn_n(ret, n_rbp, curr_bp);
} else {
if (frame_size > 0) {
ir_node *incsp = be_new_IncSP(sp, block, curr_sp,
- (int) frame_size, 0);
ir_node *incsp = amd64_new_IncSP(block, curr_sp,
-(int)frame_size, 0);
sched_add_before(ret, incsp);
curr_sp = incsp;
}
......@@ -594,7 +594,7 @@ static void introduce_prologue_epilogue(ir_graph *irg)
be_set_constr_single_reg_out(curr_sp, 0,
sp, arch_register_req_type_produces_sp);
ir_node *incsp = be_new_IncSP(sp, block, curr_sp, frame_size, 0);
ir_node *incsp = amd64_new_IncSP(block, curr_sp, frame_size, 0);
sched_add_after(curr_sp, incsp);
/* make sure the initial IncSP is really used by someone */
......@@ -607,7 +607,7 @@ static void introduce_prologue_epilogue(ir_graph *irg)
layout->initial_bias = -8;
} else {
if (frame_size > 0) {
ir_node *const incsp = be_new_IncSP(sp, block, initial_sp,
ir_node *const incsp = amd64_new_IncSP(block, initial_sp,
frame_size, 0);
sched_add_after(start, incsp);
}
......@@ -659,7 +659,6 @@ static amd64_isa_t amd64_isa_template = {
.register_classes = amd64_reg_classes,
.sp = &amd64_registers[REG_RSP],
.bp = &amd64_registers[REG_RBP],
.stack_alignment = 4, /* power of two stack alignment for calls */
.spill_cost = 7,
.reload_cost = 5,
},
......
......@@ -20,5 +20,7 @@ struct amd64_isa_t {
};
#define AMD64_REGISTER_SIZE 8
/** power of two stack alignment on calls */
#define AMD64_PO2_STACK_ALIGNMENT 4
#endif
......@@ -38,6 +38,8 @@
#include <limits.h>
#define ARM_PO2_STACK_ALIGNMENT 3
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
typedef struct start_val_t {
......@@ -1967,7 +1969,8 @@ static ir_node *gen_Call(ir_node *node)
* Note that we always need an IncSP to ensure stack alignment */
ir_node *new_frame = get_stack_pointer_for(node);
ir_node *incsp = be_new_IncSP(sp_reg, new_block, new_frame,
cconv->param_stack_size, 1);
cconv->param_stack_size,
ARM_PO2_STACK_ALIGNMENT);
int sp_pos = in_arity++;
in_req[sp_pos] = sp_reg->single_req;
in[sp_pos] = incsp;
......
......@@ -253,7 +253,6 @@ static arm_isa_t arm_isa_template = {
.register_classes = arm_reg_classes,
.sp = &arm_registers[REG_SP],
.bp = &arm_registers[REG_R11],
.stack_alignment = 3, /* power of two alignment */
.spill_cost = 7,
.reload_cost = 5,
},
......
......@@ -484,7 +484,6 @@ struct arch_env_t {
const arch_register_class_t *register_classes;
const arch_register_t *sp; /**< The stack pointer register. */
const arch_register_t *bp; /**< The base pointer register. */
unsigned stack_alignment; /**< power of 2 stack alignment */
unsigned spill_cost; /**< cost for a be_Spill node */
unsigned reload_cost; /**< cost for a be_Reload node */
};
......
......@@ -60,7 +60,7 @@ typedef struct {
be_node_attr_t base;
int offset; /**< The offset by which the stack shall be
expanded/shrinked. */
int align; /**< alignment after the IncSP (0=no alignment) */
unsigned align; /**< alignment after the IncSP (0=no alignment) */
} be_incsp_attr_t;
typedef struct {
......@@ -279,7 +279,7 @@ void be_Keep_add_node(ir_node *keep, const arch_register_class_t *cls, ir_node *
}
ir_node *be_new_IncSP(const arch_register_t *sp, ir_node *bl,
ir_node *old_sp, int offset, int align)
ir_node *old_sp, int offset, unsigned align)
{
ir_graph *irg = get_irn_irg(bl);
ir_node *in[] = { old_sp };
......@@ -474,7 +474,7 @@ int be_get_IncSP_offset(const ir_node *irn)
return a->offset;
}
int be_get_IncSP_align(const ir_node *irn)
unsigned be_get_IncSP_align(const ir_node *irn)
{
assert(be_is_IncSP(irn));
const be_incsp_attr_t *a = (const be_incsp_attr_t*)get_irn_generic_attr_const(irn);
......@@ -655,7 +655,7 @@ static void dump_node(FILE *f, const ir_node *irn, dump_reason_t reason)
switch (get_be_irn_opcode(irn)) {
case beo_IncSP: {
const be_incsp_attr_t *a = (const be_incsp_attr_t*)get_irn_generic_attr_const(irn);
fprintf(f, "align: %d\n", a->align);
fprintf(f, "align: %u\n", a->align);
fprintf(f, "offset: %d\n", a->offset);
break;
}
......
......@@ -113,14 +113,14 @@ void be_Keep_add_node(ir_node *keep, const arch_register_class_t *cls,
* (negative offset). Note that the offset is independent of the
* natural stack direction of the architecture but just specifies
* abstract expanding/shrinking of the stack area.
* @param align force stack alignment to this power of 2. (i.e. specifying 3
* results in a 2^3 = 8byte stack alignment)
* @param align force stack alignment to this power of 2. (i.e. specifying 4
* results in a 2**4 = 16 bytes stack alignment)
* @return A new stack pointer increment/decrement node.
* @note This node sets a register constraint to the @p sp register on
* its output.
*/
ir_node *be_new_IncSP(const arch_register_t *sp, ir_node *block,
ir_node *old_sp, int offset, int align);
ir_node *old_sp, int offset, unsigned align);
/** Returns the previous node that computes the stack pointer. */
ir_node *be_get_IncSP_pred(ir_node *incsp);
......@@ -138,7 +138,9 @@ void be_set_IncSP_offset(ir_node *irn, int offset);
/** Gets the offset from a IncSP node. */
int be_get_IncSP_offset(const ir_node *irn);
int be_get_IncSP_align(const ir_node *irn);
/** Return requested stack alignment (as a logarithm of two, i.e. 4 means
* the stack alignment will be 2**4=16 bytes) */
unsigned be_get_IncSP_align(const ir_node *irn);
enum {
n_be_CopyKeep_op,
......
......@@ -108,11 +108,12 @@ static int process_stack_bias(ir_node *bl, int real_bias)
* record that in the bias. */
if (be_is_IncSP(irn)) {
int ofs = be_get_IncSP_offset(irn);
unsigned align = be_get_IncSP_align(irn);
/* fill in real stack frame size */
if (be_get_IncSP_align(irn)) {
if (align > 0) {
/* patch IncSP to produce an aligned stack pointer */
int const between_size = get_type_size_bytes(layout->between_type);
int const alignment = 1 << arch_env->stack_alignment;
int const alignment = 1 << align;
int const delta = (real_bias + ofs + between_size) & (alignment - 1);
assert(ofs >= 0);
if (delta > 0) {
......
......@@ -1582,7 +1582,6 @@ static ia32_isa_t ia32_isa_template = {
.register_classes = ia32_reg_classes,
.sp = &ia32_registers[REG_ESP],
.bp = &ia32_registers[REG_EBP],
.stack_alignment = 2, /* power of two stack alignment */
.spill_cost = 7,
.reload_cost = 5,
},
......@@ -1715,8 +1714,6 @@ static lc_opt_enum_int_var_t gas_var = {
static const lc_opt_table_entry_t ia32_options[] = {
LC_OPT_ENT_ENUM_INT("gasmode", "set the GAS compatibility mode", &gas_var),
LC_OPT_ENT_INT ("stackalign", "set power of two stack alignment for calls",
(int*)&ia32_isa_template.base.stack_alignment),
LC_OPT_ENT_BOOL("gprof", "create gprof profiling code", &gprof),
LC_OPT_ENT_BOOL("precise_float_spill", "Spill floatingpoint values precisely (the whole 80 bits)", &precise_x87_spills),
LC_OPT_LAST
......
......@@ -151,6 +151,7 @@ static cpu_arch_features opt_arch = 0;
static int fpu_arch = 0;
static bool opt_cc = true;
static bool opt_unsafe_floatconv = false;
static int stack_alignment = 2;
/* instruction set architectures. */
static const lc_opt_enum_int_items_t arch_items[] = {
......@@ -232,6 +233,7 @@ static lc_opt_enum_int_var_t fp_unit_var = {
};
static const lc_opt_table_entry_t ia32_architecture_options[] = {
LC_OPT_ENT_INT ("stackalign", "set power of two stack alignment for calls", &stack_alignment),
LC_OPT_ENT_BOOL ("size", "optimize for size", &opt_size),
LC_OPT_ENT_ENUM_INT("arch", "select the instruction architecture", &arch_var),
LC_OPT_ENT_ENUM_INT("tune", "optimize for instruction architecture", &opt_arch_var),
......@@ -919,6 +921,7 @@ void ia32_setup_cg_config(void)
flags(opt_arch, arch_i386 | arch_i486) || opt_size ? 0 :
opt_arch & arch_all_amd ? 3 :
2;
c->stack_alignment = stack_alignment;
}
void ia32_init_architecture(void)
......
......@@ -89,6 +89,8 @@ typedef struct {
/** if a blocks execfreq is factor higher than its predecessor then align
* the blocks label (0 switches off label alignment) */
double label_alignment_factor;
/** stack alignment required at calls */
unsigned stack_alignment;
} ia32_code_gen_config_t;
extern ia32_code_gen_config_t ia32_cg_config;
......
......@@ -5002,7 +5002,8 @@ static ir_node *gen_Call(ir_node *node)
if (callframe_size == 0) {
callframe = new_frame;
} else {
callframe = ia32_new_IncSP(block, new_frame, callframe_size, 0);
callframe = ia32_new_IncSP(block, new_frame, callframe_size,
ia32_cg_config.stack_alignment);
}
/* special case for PIC trampoline calls */
......@@ -5747,7 +5748,8 @@ static ir_node *gen_Proj_Builtin(ir_node *proj)
panic("Builtin %s not implemented", get_builtin_kind_name(kind));
}
ir_node *ia32_new_IncSP(ir_node *block, ir_node *old_sp, int offset, int align)
ir_node *ia32_new_IncSP(ir_node *block, ir_node *old_sp, int offset,
unsigned align)
{
ir_node *incsp = be_new_IncSP(&ia32_registers[REG_ESP], block, old_sp,
offset, align);
......
......@@ -45,6 +45,7 @@ ir_node *ia32_skip_downconv(ir_node *node);
/** Initialize the ia32 instruction selector. */
void ia32_init_transform(void);
ir_node *ia32_new_IncSP(ir_node *block, ir_node *old_sp, int offset, int align);
ir_node *ia32_new_IncSP(ir_node *block, ir_node *old_sp, int offset,
unsigned align);
#endif
......@@ -66,7 +66,6 @@ static sparc_isa_t sparc_isa_template = {
.register_classes = sparc_reg_classes,
.sp = &sparc_registers[REG_SP],
.bp = &sparc_registers[REG_FRAME_POINTER],
.stack_alignment = 3, /* power of two alignment */
.spill_cost = 7,
.reload_cost = 5,
},
......
......@@ -53,7 +53,8 @@ extern ir_mode *sparc_mode_Q;
#define SPARC_PARAMS_SPILL_OFFSET 68
#define SPARC_SAVE_AREA_SIZE 64
#define SPARC_N_PARAM_REGS 6
#define SPARC_STACK_ALIGNMENT 8
#define SPARC_PO2_STACK_ALIGNMENT 3
#define SPARC_STACK_ALIGNMENT (1<<SPARC_PO2_STACK_ALIGNMENT)
#define SPARC_REGISTER_SIZE 4
static inline bool sparc_is_value_imm_encodeable(int32_t value)
......
......@@ -2081,7 +2081,8 @@ static ir_node *gen_Call(ir_node *node)
/* construct an IncSP -> we have to always be sure that the stack is
* aligned even if we don't push arguments on it */
ir_node *incsp = be_new_IncSP(sp_reg, new_block, new_frame,
cconv->param_stack_size, 1);
cconv->param_stack_size,
SPARC_PO2_STACK_ALIGNMENT);
in_req[in_arity] = sp_reg->single_req;
in[in_arity] = incsp;
++in_arity;
......
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