From 323267da3fcfb2a3029b19e17008645055d86590 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Christian=20W=C3=BCrdig?= Date: Fri, 6 Oct 2006 08:45:19 +0000 Subject: [PATCH] added support for separate outflags --- ir/be/ia32/bearch_ia32.c | 34 +++++---------------- ir/be/ia32/ia32_new_nodes.c | 24 +++++++++++++-- ir/be/ia32/ia32_new_nodes.h | 11 +++++++ ir/be/ia32/ia32_nodes_attr.h | 4 ++- ir/be/ia32/ia32_spec.pl | 17 ++++++----- ir/be/scripts/generate_new_opcodes.pl | 44 ++++++++++++++++++++++++--- 6 files changed, 93 insertions(+), 41 deletions(-) diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index ee0e16c0a..5a3dfe128 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -265,37 +265,19 @@ static arch_irn_class_t ia32_classify(const void *self, const ir_node *irn) { } static arch_irn_flags_t ia32_get_flags(const void *self, const ir_node *irn) { + arch_irn_flags_t flags = arch_irn_flags_none; - if(is_Proj(irn)) { - ir_node *pred = get_Proj_pred(irn); - int ia32_op = get_ia32_irn_opcode(pred); - long proj = get_Proj_proj(irn); - if (iro_ia32_Push == ia32_op && proj == pn_ia32_Push_stack) { - /* Push modifies always ESP, this cannot be changed */ - return arch_irn_flags_modify_sp | arch_irn_flags_ignore; - } - if (iro_ia32_Pop == ia32_op && proj == pn_ia32_Pop_stack) { - /* Pop modifies always ESP, this cannot be changed */ - return arch_irn_flags_modify_sp | arch_irn_flags_ignore; - } - if (iro_ia32_AddSP == ia32_op && proj == pn_ia32_AddSP_stack) { - /* AddSP modifies always ESP, this cannot be changed */ - return arch_irn_flags_modify_sp | arch_irn_flags_ignore; - } - if (iro_ia32_SubSP == ia32_op && proj == pn_ia32_SubSP_stack) { - /* SubSP modifies always ESP, this cannot be changed */ - return arch_irn_flags_modify_sp | arch_irn_flags_ignore; - } + if (is_Proj(irn) && is_ia32_irn(get_Proj_pred(irn))) { + flags |= get_ia32_out_flags(irn, get_Proj_proj(irn)); } irn = skip_Proj(irn); if (is_ia32_irn(irn)) - return get_ia32_flags(irn); - else { - if (is_Unknown(irn)) - return arch_irn_flags_ignore; - return 0; - } + flags |= get_ia32_flags(irn); + else if (is_Unknown(irn)) + flags = arch_irn_flags_ignore; + + return flags; } /** diff --git a/ir/be/ia32/ia32_new_nodes.c b/ir/be/ia32/ia32_new_nodes.c index 43e01692f..009ebefc3 100644 --- a/ir/be/ia32/ia32_new_nodes.c +++ b/ir/be/ia32/ia32_new_nodes.c @@ -1075,6 +1075,24 @@ void set_ia32_pncode(ir_node *node, long code) { attr->pn_code = code; } +/** + * Sets the flags for the n'th out. + */ +void set_ia32_out_flags(ir_node *node, arch_irn_flags_t flags, int pos) { + ia32_attr_t *attr = get_ia32_attr(node); + assert(pos < (int) attr->data.n_res && "Invalid OUT position."); + attr->out_flags[pos] = flags; +} + +/** + * Gets the flags for the n'th out. + */ +arch_irn_flags_t get_ia32_out_flags(const ir_node *node, int pos) { + ia32_attr_t *attr = get_ia32_attr(node); + assert(pos < (int) attr->data.n_res && "Invalid OUT position."); + return attr->out_flags[pos]; +} + #ifndef NDEBUG /** @@ -1288,7 +1306,6 @@ int is_ia32_Cnst(const ir_node *node) { const char *get_ia32_out_reg_name(const ir_node *node, int pos) { ia32_attr_t *attr = get_ia32_attr(node); - assert(is_ia32_irn(node) && "Not an ia32 node."); assert(pos < (int) attr->data.n_res && "Invalid OUT position."); assert(attr->slots[pos] && "No register assigned"); @@ -1301,7 +1318,6 @@ const char *get_ia32_out_reg_name(const ir_node *node, int pos) { int get_ia32_out_regnr(const ir_node *node, int pos) { ia32_attr_t *attr = get_ia32_attr(node); - assert(is_ia32_irn(node) && "Not an ia32 node."); assert(pos < (int) attr->data.n_res && "Invalid OUT position."); assert(attr->slots[pos] && "No register assigned"); @@ -1314,7 +1330,6 @@ int get_ia32_out_regnr(const ir_node *node, int pos) { const arch_register_t *get_ia32_out_reg(const ir_node *node, int pos) { ia32_attr_t *attr = get_ia32_attr(node); - assert(is_ia32_irn(node) && "Not an ia32 node."); assert(pos < (int) attr->data.n_res && "Invalid OUT position."); assert(attr->slots[pos] && "No register assigned"); @@ -1333,6 +1348,9 @@ void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags, const ia32_regi set_ia32_out_req_all(node, out_reqs); set_ia32_latency(node, latency); + attr->out_flags = NEW_ARR_D(int, get_irg_obstack(get_irn_irg(node)), n_res); + memset(attr->out_flags, 0, n_res * sizeof(attr->out_flags[0])); + attr->data.n_res = n_res; memset((void *)attr->slots, 0, n_res * sizeof(attr->slots[0])); } diff --git a/ir/be/ia32/ia32_new_nodes.h b/ir/be/ia32/ia32_new_nodes.h index d6f19ba4c..ba51f2121 100644 --- a/ir/be/ia32/ia32_new_nodes.h +++ b/ir/be/ia32/ia32_new_nodes.h @@ -393,6 +393,17 @@ unsigned get_ia32_latency(const ir_node *node); */ void set_ia32_latency(ir_node *node, unsigned latency); + +/** + * Sets the flags for the n'th out. + */ +void set_ia32_out_flags(ir_node *node, arch_irn_flags_t flags, int pos); + +/** + * Gets the flags for the n'th out. + */ +arch_irn_flags_t get_ia32_out_flags(const ir_node *node, int pos); + #ifndef NDEBUG /** diff --git a/ir/be/ia32/ia32_nodes_attr.h b/ir/be/ia32/ia32_nodes_attr.h index f37d617f1..d9e36dce7 100644 --- a/ir/be/ia32/ia32_nodes_attr.h +++ b/ir/be/ia32/ia32_nodes_attr.h @@ -88,7 +88,7 @@ typedef struct _ia32_attr_t { unsigned op_flav:2; /**< flavour of an op (flavour_Div/Mod/DivMod) */ - unsigned flags:4; /**< indicating if spillable and/or rematerializeable */ + unsigned flags:4; /**< indicating if spillable, rematerializeable, stack modifying and/or ignore */ unsigned is_commutative:1; /**< indicates whether op is commutative or not */ @@ -101,6 +101,8 @@ typedef struct _ia32_attr_t { unsigned n_res:6; /**< number of results produced by this node */ } data; + int *out_flags; /**< flags for each produced value */ + int am_offs; /**< offsets for AddrMode */ ident *am_sc; /**< SymConst for AddrMode */ diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index 4390e1f7e..e3309944c 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -73,6 +73,10 @@ $comment_string = "/*"; # # outs: if a node defines more than one output, the names of the projections # nodes having outs having automatically the mode mode_T +# One can also annotate some flags for each out, additional to irn_flags. +# They are separated from name with a colon ':', and concatenated by pipe '|' +# Only I and S are available at the moment (same meaning as in irn_flags). +# example: [ "frame:I", "stack:I|S", "M" ] # # comment: OPTIONAL comment for the node constructor # @@ -716,11 +720,10 @@ else { }, "Push" => { - # We don't set class modify_stack here (but we will do this on proj 0) "comment" => "push on the stack", "reg_req" => { "in" => [ "gp", "gp", "gp", "esp", "none" ], "out" => [ "esp" ] }, "emit" => '. push %ia32_emit_unop /* PUSH(%A1) */', - "outs" => [ "stack", "M" ], + "outs" => [ "stack:I|S", "M" ], "latency" => 3, }, @@ -729,7 +732,7 @@ else { "comment" => "pop a gp register from the stack", "reg_req" => { "in" => [ "gp", "gp", "esp", "none" ], "out" => [ "gp", "esp" ] }, "emit" => '. pop %ia32_emit_unop /* POP(%A1) */', - "outs" => [ "res", "stack", "M" ], + "outs" => [ "res", "stack:I|S", "M" ], "latency" => 4, }, @@ -737,7 +740,7 @@ else { "comment" => "create stack frame", "reg_req" => { "in" => [ "esp" ], "out" => [ "ebp", "esp" ] }, "emit" => '. enter /* Enter */', - "outs" => [ "frame", "stack", "M" ], + "outs" => [ "frame:I", "stack:I|S", "M" ], "latency" => 15, }, @@ -745,7 +748,7 @@ else { "comment" => "destroy stack frame", "reg_req" => { "in" => [ "esp", "ebp" ], "out" => [ "ebp", "esp" ] }, "emit" => '. leave /* Leave */', - "outs" => [ "frame", "stack", "M" ], + "outs" => [ "frame:I", "stack:I|S", "M" ], "latency" => 3, }, @@ -753,14 +756,14 @@ else { "irn_flags" => "I", "comment" => "allocate space on stack", "reg_req" => { "in" => [ "esp", "gp" ], "out" => [ "esp", "none" ] }, - "outs" => [ "stack", "M" ], + "outs" => [ "stack:S", "M" ], }, "SubSP" => { "irn_flags" => "I", "comment" => "free space on stack", "reg_req" => { "in" => [ "esp", "gp" ], "out" => [ "esp", "none" ] }, - "outs" => [ "stack", "M" ], + "outs" => [ "stack:S", "M" ], }, "LdTls" => { diff --git a/ir/be/scripts/generate_new_opcodes.pl b/ir/be/scripts/generate_new_opcodes.pl index 224c592ca..eb5fef677 100755 --- a/ir/be/scripts/generate_new_opcodes.pl +++ b/ir/be/scripts/generate_new_opcodes.pl @@ -61,9 +61,11 @@ push(@obst_header, "void ".$arch."_create_opcodes(void);\n"); push(@obst_enum_op, "typedef enum _$arch\_opcodes {\n"); foreach my $op (keys(%nodes)) { - my %n = %{ $nodes{"$op"} }; - my $tuple = 0; - my $n_res = 0; + my %n = %{ $nodes{"$op"} }; + my $tuple = 0; + my $n_res = 0; + my $num_outs = 0; + my @out_flags; # determine arity from in requirements $arity = exists($n{"arity"}) ? $n{"arity"} : 0; @@ -75,13 +77,24 @@ foreach my $op (keys(%nodes)) { $op = $arch."_".$op; $temp = ""; + # define some proj numbers if (exists($n{"outs"})) { undef my @outs; - @outs = @{ $n{"outs"} }; + + @outs = @{ $n{"outs"} }; + $num_outs = $#outs; + push(@obst_proj, "\nenum pn_$op {\n"); + for (my $idx = 0; $idx <= $#outs; $idx++) { + # check, if we have additional flags annotated to out + if ($outs[$idx] =~ /:(S|I(\|(S|I))*)/) { + push(@out_flags, $1); + $outs[$idx] =~ s/:(S|I(\|(S|I))*)//; + } push(@obst_proj, " pn_$op\_".$outs[$idx]." = $idx,\n"); } + push(@obst_proj, "};\n"); $tuple = 1; } @@ -276,6 +289,29 @@ foreach my $op (keys(%nodes)) { $temp .= "\n /* init node attributes */\n"; $temp .= " init_$arch\_attributes(res, flags, $in_param, $out_param, $latency);\n"; + # set flags for outs + if ($#out_flags >= 0) { + $temp .= "\n /* set flags for outs */\n"; + for (my $idx = 0; $idx <= $#out_flags; $idx++) { + my $flags = ""; + my $prefix = ""; + + foreach my $flag (split(/\|/, $out_flags[$idx])) { + if ($flag eq "I") { + $flags .= $prefix."arch_irn_flags_ignore"; + $prefix = " | "; + } + elsif ($flag eq "S") { + $flags .= $prefix."arch_irn_flags_modify_sp"; + $prefix = " | "; + } + } + + $temp .= " set_$arch\_out_flags(res, $flags, $idx);\n"; + } + } + + if (exists($n{"init_attr"})) { $temp .= " attr = get_$arch\_attr(res);\n"; $temp .= $n{"init_attr"}."\n"; -- 2.20.1