added support for separate outflags
authorChristian Würdig <chriswue@ipd.info.uni-karlsruhe.de>
Fri, 6 Oct 2006 08:45:19 +0000 (08:45 +0000)
committerChristian Würdig <chriswue@ipd.info.uni-karlsruhe.de>
Fri, 6 Oct 2006 08:45:19 +0000 (08:45 +0000)
ir/be/ia32/bearch_ia32.c
ir/be/ia32/ia32_new_nodes.c
ir/be/ia32/ia32_new_nodes.h
ir/be/ia32/ia32_nodes_attr.h
ir/be/ia32/ia32_spec.pl
ir/be/scripts/generate_new_opcodes.pl

index ee0e16c..5a3dfe1 100644 (file)
@@ -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;
 }
 
 /**
index 43e0169..009ebef 100644 (file)
@@ -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]));
 }
index d6f19ba..ba51f21 100644 (file)
@@ -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
 
 /**
index f37d617..d9e36dc 100644 (file)
@@ -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 */
 
index 4390e1f..e330994 100644 (file)
@@ -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" => {
index 224c592..eb5fef6 100755 (executable)
@@ -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";