#define DFP_INTMAX "9223372036854775807"
#define ULL_BIAS "18446744073709551616"
-#define ENT_SFP_SIGN ".LC_ia32_sfp_sign"
-#define ENT_DFP_SIGN ".LC_ia32_dfp_sign"
-#define ENT_SFP_ABS ".LC_ia32_sfp_abs"
-#define ENT_DFP_ABS ".LC_ia32_dfp_abs"
-#define ENT_ULL_BIAS ".LC_ia32_ull_bias"
+#define ENT_SFP_SIGN "C_ia32_sfp_sign"
+#define ENT_DFP_SIGN "C_ia32_dfp_sign"
+#define ENT_SFP_ABS "C_ia32_sfp_abs"
+#define ENT_DFP_ABS "C_ia32_dfp_abs"
+#define ENT_ULL_BIAS "C_ia32_ull_bias"
#define mode_vfp (ia32_reg_classes[CLASS_ia32_vfp].mode)
#define mode_xmm (ia32_reg_classes[CLASS_ia32_xmm].mode)
*/
static ir_node *get_symconst_base(void)
{
- if (env_cg->birg->main_env->options->pic) {
+ if (be_get_irg_options(env_cg->irg)->pic) {
return arch_code_generator_get_pic_base(env_cg);
}
set_entity_ld_ident(ent, get_entity_ident(ent));
add_entity_linkage(ent, IR_LINKAGE_CONSTANT);
- set_entity_visibility(ent, ir_visibility_local);
+ set_entity_visibility(ent, ir_visibility_private);
if (kct == ia32_ULLBIAS) {
ir_initializer_t *initializer = create_initializer_compound(2);
return 0;
/* we only want to skip the conv when we're the only user
- * (not optimal but for now...)
- */
+ * (because this test is used in the context of address-mode selection
+ * and we don't want to use address mode for multiple users) */
if (get_irn_n_edges(node) > 1)
return 0;
get_mode_size_bits(dest_mode) <= get_mode_size_bits(src_mode);
}
-/* Skip all Down-Conv's on a given node and return the resulting node. */
+/** Skip all Down-Conv's on a given node and return the resulting node. */
ir_node *ia32_skip_downconv(ir_node *node)
{
while (is_downconv(node))
return node;
}
+static bool is_sameconv(ir_node *node)
+{
+ ir_mode *src_mode;
+ ir_mode *dest_mode;
+
+ if (!is_Conv(node))
+ return 0;
+
+ /* we only want to skip the conv when we're the only user
+ * (because this test is used in the context of address-mode selection
+ * and we don't want to use address mode for multiple users) */
+ if (get_irn_n_edges(node) > 1)
+ return 0;
+
+ src_mode = get_irn_mode(get_Conv_op(node));
+ dest_mode = get_irn_mode(node);
+ return
+ ia32_mode_needs_gp_reg(src_mode) &&
+ ia32_mode_needs_gp_reg(dest_mode) &&
+ get_mode_size_bits(dest_mode) == get_mode_size_bits(src_mode);
+}
+
+/** Skip all signedness convs */
+static ir_node *ia32_skip_sameconv(ir_node *node)
+{
+ while (is_sameconv(node))
+ node = get_Conv_op(node);
+
+ return node;
+}
+
static ir_node *create_upconv(ir_node *node, ir_node *orig_node)
{
ir_mode *mode = get_irn_mode(node);
if (op1 != NULL) {
op1 = ia32_skip_downconv(op1);
}
+ } else {
+ op2 = ia32_skip_sameconv(op2);
+ if (op1 != NULL) {
+ op1 = ia32_skip_sameconv(op1);
+ }
}
/* match immediates. firm nodes are normalized: constants are always on the
if (initial_fpcw != NULL)
return initial_fpcw;
- fpcw = be_abi_get_ignore_irn(env_cg->birg->abi,
+ fpcw = be_abi_get_ignore_irn(be_get_irg_abi(env_cg->irg),
&ia32_fp_cw_regs[REG_FPCW]);
initial_fpcw = be_transform_node(fpcw);
ir_node *index;
dbg_info *dbgi = get_irn_dbg_info(node);
ir_mode *mode = get_Load_mode(node);
- ir_mode *res_mode;
ir_node *new_node;
ia32_address_t addr;
if (ia32_cg_config.use_sse2) {
new_node = new_bd_ia32_xLoad(dbgi, block, base, index, new_mem,
mode);
- res_mode = mode_xmm;
} else {
new_node = new_bd_ia32_vfld(dbgi, block, base, index, new_mem,
mode);
- res_mode = mode_vfp;
}
} else {
assert(mode != mode_b);
} else {
new_node = new_bd_ia32_Load(dbgi, block, base, index, new_mem);
}
- res_mode = mode_Iu;
}
set_irn_pinned(new_node, get_irn_pinned(node));
ir_node *mux_true = get_Mux_true(node);
ir_node *mux_false = get_Mux_false(node);
ir_node *cond;
- ir_node *new_mem;
dbg_info *dbgi;
ir_node *block;
ir_node *new_block;
dbgi = get_irn_dbg_info(node);
block = get_nodes_block(node);
new_block = be_transform_node(block);
- new_mem = be_transform_node(mem);
new_node = new_bd_ia32_SetccMem(dbgi, new_block, addr.base,
addr.index, addr.mem, flags, pnc);
set_address(new_node, &addr);
tp = ia32_create_float_type(mode, 4);
tp = ia32_create_float_array(tp);
- ent = new_entity(get_glob_type(), ia32_unique_id(".LC%u"), tp);
+ ent = new_entity(get_glob_type(), id_unique("C%u"), tp);
set_entity_ld_ident(ent, get_entity_ident(ent));
- set_entity_visibility(ent, ir_visibility_local);
+ set_entity_visibility(ent, ir_visibility_private);
add_entity_linkage(ent, IR_LINKAGE_CONSTANT);
initializer = create_initializer_compound(2);
setcc_transform_t res;
int step;
- /* check if flags is a cmp node and we are the only user,
- i.e no other user yet */
- int permutate_allowed = 0;
- if (is_ia32_Cmp(flags) && get_irn_n_edges(flags) == 0) {
- /* yes, we can permutate its inputs */
- permutate_allowed = 1;
- }
find_const_transform(pnc, tv_true, tv_false, &res);
new_node = node;
if (res.permutate_cmp_ins) {
return mem;
}
-/**
- * the BAD transformer.
- */
-static ir_node *bad_transform(ir_node *node)
-{
- panic("No transform function for %+F available.", node);
- return NULL;
-}
-
static ir_node *gen_Proj_l_FloattoLL(ir_node *node)
{
ir_node *block = be_transform_node(get_nodes_block(node));
long proj = get_Proj_proj(node);
switch (proj) {
- case pn_CopyB_M_regular:
+ case pn_CopyB_M:
if (is_ia32_CopyB_i(new_pred)) {
return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_CopyB_i_M);
} else if (is_ia32_CopyB(new_pred)) {
/* special case for PIC trampoline calls */
old_no_pic_adjust = no_pic_adjust;
- no_pic_adjust = env_cg->birg->main_env->options->pic;
+ no_pic_adjust = be_get_irg_options(env_cg->irg)->pic;
match_arguments(&am, src_block, NULL, src_ptr, src_mem,
match_am | match_immediate);
*/
static ir_node *gen_Proj_Bound(ir_node *node)
{
- ir_node *new_node, *block;
+ ir_node *new_node;
ir_node *pred = get_Proj_pred(node);
switch (get_Proj_proj(node)) {
return be_transform_node(get_Bound_mem(pred));
case pn_Bound_X_regular:
new_node = be_transform_node(pred);
- block = get_nodes_block(new_node);
return new_r_Proj(new_node, mode_X, pn_ia32_Jcc_true);
case pn_Bound_X_except:
new_node = be_transform_node(pred);
- block = get_nodes_block(new_node);
return new_r_Proj(new_node, mode_X, pn_ia32_Jcc_false);
case pn_Bound_res:
return be_transform_node(get_Bound_index(pred));
static void register_transformers(void)
{
/* first clear the generic function pointer for all ops */
- clear_irp_opcodes_generic_func();
-
-#define GEN(a) { be_transform_func *func = gen_##a; op_##a->ops.generic = (op_func) func; }
-#define BAD(a) op_##a->ops.generic = (op_func)bad_transform
-
- GEN(Add);
- GEN(Sub);
- GEN(Mul);
- GEN(Mulh);
- GEN(And);
- GEN(Or);
- GEN(Eor);
-
- GEN(Shl);
- GEN(Shr);
- GEN(Shrs);
- GEN(Rotl);
-
- GEN(Quot);
-
- GEN(Div);
- GEN(Mod);
- GEN(DivMod);
-
- GEN(Minus);
- GEN(Conv);
- GEN(Abs);
- GEN(Not);
-
- GEN(Load);
- GEN(Store);
- GEN(Cond);
-
- GEN(Cmp);
- GEN(ASM);
- GEN(CopyB);
- GEN(Mux);
- GEN(Proj);
- GEN(Phi);
- GEN(Jmp);
- GEN(IJmp);
- GEN(Bound);
-
- /* transform ops from intrinsic lowering */
- GEN(ia32_l_Add);
- GEN(ia32_l_Adc);
- GEN(ia32_l_Mul);
- GEN(ia32_l_IMul);
- GEN(ia32_l_ShlDep);
- GEN(ia32_l_ShrDep);
- GEN(ia32_l_SarDep);
- GEN(ia32_l_ShlD);
- GEN(ia32_l_ShrD);
- GEN(ia32_l_Sub);
- GEN(ia32_l_Sbb);
- GEN(ia32_l_LLtoFloat);
- GEN(ia32_l_FloattoLL);
-
- GEN(Const);
- GEN(SymConst);
- GEN(Unknown);
-
- /* we should never see these nodes */
- BAD(Raise);
- BAD(Sel);
- BAD(InstOf);
- BAD(Cast);
- BAD(Free);
- BAD(Tuple);
- BAD(Id);
- //BAD(Bad);
- BAD(Confirm);
- BAD(Filter);
- BAD(CallBegin);
- BAD(EndReg);
- BAD(EndExcept);
-
- /* handle builtins */
- GEN(Builtin);
-
- /* handle generic backend nodes */
- GEN(be_FrameAddr);
- GEN(be_Call);
- GEN(be_IncSP);
- GEN(be_Return);
- GEN(be_AddSP);
- GEN(be_SubSP);
- GEN(be_Copy);
-
-#undef GEN
-#undef BAD
+ be_start_transform_setup();
+
+ be_set_transform_function(op_Abs, gen_Abs);
+ be_set_transform_function(op_Add, gen_Add);
+ be_set_transform_function(op_And, gen_And);
+ be_set_transform_function(op_ASM, gen_ASM);
+ be_set_transform_function(op_be_AddSP, gen_be_AddSP);
+ be_set_transform_function(op_be_Call, gen_be_Call);
+ be_set_transform_function(op_be_Copy, gen_be_Copy);
+ be_set_transform_function(op_be_FrameAddr, gen_be_FrameAddr);
+ be_set_transform_function(op_be_IncSP, gen_be_IncSP);
+ be_set_transform_function(op_be_Return, gen_be_Return);
+ be_set_transform_function(op_be_SubSP, gen_be_SubSP);
+ be_set_transform_function(op_Bound, gen_Bound);
+ be_set_transform_function(op_Builtin, gen_Builtin);
+ be_set_transform_function(op_Cmp, gen_Cmp);
+ be_set_transform_function(op_Cond, gen_Cond);
+ be_set_transform_function(op_Const, gen_Const);
+ be_set_transform_function(op_Conv, gen_Conv);
+ be_set_transform_function(op_CopyB, gen_CopyB);
+ be_set_transform_function(op_Div, gen_Div);
+ be_set_transform_function(op_DivMod, gen_DivMod);
+ be_set_transform_function(op_Eor, gen_Eor);
+ be_set_transform_function(op_ia32_l_Adc, gen_ia32_l_Adc);
+ be_set_transform_function(op_ia32_l_Add, gen_ia32_l_Add);
+ be_set_transform_function(op_ia32_Leave, be_duplicate_node);
+ be_set_transform_function(op_ia32_l_FloattoLL, gen_ia32_l_FloattoLL);
+ be_set_transform_function(op_ia32_l_IMul, gen_ia32_l_IMul);
+ be_set_transform_function(op_ia32_l_LLtoFloat, gen_ia32_l_LLtoFloat);
+ be_set_transform_function(op_ia32_l_Mul, gen_ia32_l_Mul);
+ be_set_transform_function(op_ia32_l_SarDep, gen_ia32_l_SarDep);
+ be_set_transform_function(op_ia32_l_Sbb, gen_ia32_l_Sbb);
+ be_set_transform_function(op_ia32_l_ShlDep, gen_ia32_l_ShlDep);
+ be_set_transform_function(op_ia32_l_ShlD, gen_ia32_l_ShlD);
+ be_set_transform_function(op_ia32_l_ShrDep, gen_ia32_l_ShrDep);
+ be_set_transform_function(op_ia32_l_ShrD, gen_ia32_l_ShrD);
+ be_set_transform_function(op_ia32_l_Sub, gen_ia32_l_Sub);
+ be_set_transform_function(op_ia32_Minus64Bit, be_duplicate_node);
+ be_set_transform_function(op_ia32_NoReg_GP, be_duplicate_node);
+ be_set_transform_function(op_ia32_NoReg_VFP, be_duplicate_node);
+ be_set_transform_function(op_ia32_NoReg_XMM, be_duplicate_node);
+ be_set_transform_function(op_ia32_PopEbp, be_duplicate_node);
+ be_set_transform_function(op_ia32_Push, be_duplicate_node);
+ be_set_transform_function(op_IJmp, gen_IJmp);
+ be_set_transform_function(op_Jmp, gen_Jmp);
+ be_set_transform_function(op_Load, gen_Load);
+ be_set_transform_function(op_Minus, gen_Minus);
+ be_set_transform_function(op_Mod, gen_Mod);
+ be_set_transform_function(op_Mul, gen_Mul);
+ be_set_transform_function(op_Mulh, gen_Mulh);
+ be_set_transform_function(op_Mux, gen_Mux);
+ be_set_transform_function(op_Not, gen_Not);
+ be_set_transform_function(op_Or, gen_Or);
+ be_set_transform_function(op_Phi, gen_Phi);
+ be_set_transform_function(op_Proj, gen_Proj);
+ be_set_transform_function(op_Quot, gen_Quot);
+ be_set_transform_function(op_Rotl, gen_Rotl);
+ be_set_transform_function(op_Shl, gen_Shl);
+ be_set_transform_function(op_Shr, gen_Shr);
+ be_set_transform_function(op_Shrs, gen_Shrs);
+ be_set_transform_function(op_Store, gen_Store);
+ be_set_transform_function(op_Sub, gen_Sub);
+ be_set_transform_function(op_SymConst, gen_SymConst);
+ be_set_transform_function(op_Unknown, gen_Unknown);
}
/**
{
ia32_code_gen_t *cg = env_cg;
- cg->unknown_gp = be_pre_transform_node(cg->unknown_gp);
- cg->unknown_vfp = be_pre_transform_node(cg->unknown_vfp);
- cg->unknown_xmm = be_pre_transform_node(cg->unknown_xmm);
cg->noreg_gp = be_pre_transform_node(cg->noreg_gp);
cg->noreg_vfp = be_pre_transform_node(cg->noreg_vfp);
cg->noreg_xmm = be_pre_transform_node(cg->noreg_xmm);
get_fpcw();
}
-/**
- * Walker, checks if all ia32 nodes producing more than one result have their
- * Projs, otherwise creates new Projs and keeps them using a be_Keep node.
- */
-static void add_missing_keep_walker(ir_node *node, void *data)
-{
- int n_outs, i;
- unsigned found_projs = 0;
- const ir_edge_t *edge;
- ir_mode *mode = get_irn_mode(node);
- ir_node *last_keep;
- (void) data;
- if (mode != mode_T)
- return;
- if (!is_ia32_irn(node))
- return;
-
- n_outs = arch_irn_get_n_outs(node);
- if (n_outs <= 0)
- return;
- if (is_ia32_SwitchJmp(node))
- return;
-
- assert(n_outs < (int) sizeof(unsigned) * 8);
- foreach_out_edge(node, edge) {
- ir_node *proj = get_edge_src_irn(edge);
- int pn;
-
- /* The node could be kept */
- if (is_End(proj))
- continue;
-
- if (get_irn_mode(proj) == mode_M)
- continue;
-
- pn = get_Proj_proj(proj);
- assert(pn < n_outs);
- found_projs |= 1 << pn;
- }
-
-
- /* are keeps missing? */
- last_keep = NULL;
- for (i = 0; i < n_outs; ++i) {
- ir_node *block;
- ir_node *in[1];
- const arch_register_req_t *req;
- const arch_register_class_t *cls;
-
- if (found_projs & (1 << i)) {
- continue;
- }
-
- req = arch_get_out_register_req(node, i);
- cls = req->cls;
- if (cls == NULL) {
- continue;
- }
- if (cls == &ia32_reg_classes[CLASS_ia32_flags]) {
- continue;
- }
-
- block = get_nodes_block(node);
- in[0] = new_r_Proj(node, arch_register_class_mode(cls), i);
- if (last_keep != NULL) {
- be_Keep_add_node(last_keep, cls, in[0]);
- } else {
- last_keep = be_new_Keep(block, 1, in);
- if (sched_is_scheduled(node)) {
- sched_add_after(node, last_keep);
- }
- }
- }
-}
-
-/**
- * Adds missing keeps to nodes. Adds missing Proj nodes for unused outputs
- * and keeps them.
- */
-void ia32_add_missing_keeps(ia32_code_gen_t *cg)
-{
- ir_graph *irg = be_get_birg_irg(cg->birg);
- irg_walk_graph(irg, add_missing_keep_walker, NULL, NULL);
-}
-
/**
* Post-process all calls if we are in SSE mode.
* The ABI requires that the results are in st0, copy them
be_timer_push(T_HEIGHTS);
heights = heights_new(cg->irg);
be_timer_pop(T_HEIGHTS);
- ia32_calculate_non_address_mode_nodes(cg->birg);
+ ia32_calculate_non_address_mode_nodes(cg->irg);
/* the transform phase is not safe for CSE (yet) because several nodes get
* attributes set after their creation */
call_list = NEW_ARR_F(ir_node *, 0);
call_types = NEW_ARR_F(ir_type *, 0);
- be_transform_graph(cg->birg, ia32_pretransform_node);
+ be_transform_graph(cg->irg, ia32_pretransform_node);
if (ia32_cg_config.use_sse2)
postprocess_fp_call_results();