cleanup fragile op handling
authorMatthias Braun <matze@braunis.de>
Wed, 25 May 2011 13:31:54 +0000 (15:31 +0200)
committerMatthias Braun <matze@braunis.de>
Wed, 25 May 2011 13:31:54 +0000 (15:31 +0200)
- The pns of X_regular and X_except are annotated in the opcode now.
- The memory input is annotated in the opcode now
- only nodes with X_regular, X_except are marked fragile

20 files changed:
include/libfirm/firm_types.h
include/libfirm/irnode.h
include/libfirm/irop.h
ir/ana/interval_analysis.c
ir/be/TEMPLATE/TEMPLATE_spec.pl
ir/be/amd64/amd64_spec.pl
ir/be/arm/arm_spec.pl
ir/be/ia32/ia32_spec.pl
ir/be/ia32/ia32_transform.c
ir/be/scripts/generate_new_opcodes.pl
ir/be/sparc/sparc_spec.pl
ir/ir/irnode.c
ir/ir/irop.c
ir/ir/irtypes.h
ir/opt/critical_edges.c
ir/opt/ldstopt.c
ir/opt/opt_ldst.c
scripts/gen_ir.py
scripts/ir_spec.py
scripts/spec_util.py

index 3c3657e..13bab56 100644 (file)
@@ -273,16 +273,6 @@ typedef enum ir_builtin_kind {
        ir_bk_inner_trampoline,       /**< address of a trampoline for GCC inner functions */
 } ir_builtin_kind;
 
-/**
- * Some projection numbers must be always equal to support automatic phi construction
- */
-enum pn_generic {
-       pn_Generic_M         = 0,  /**< The memory result. */
-       pn_Generic_X_regular = 1,  /**< Execution result if no exception occurred. */
-       pn_Generic_X_except  = 2,  /**< The control flow result branching to the exception handler */
-       pn_Generic_other     = 3   /**< First free projection number */
-};
-
 /**
  * Possible return values of value_classify().
  */
index 99cc27d..8713c58 100644 (file)
@@ -478,6 +478,16 @@ FIRM_API void     set_binop_left(ir_node *node, ir_node *left);
 FIRM_API ir_node *get_binop_right(const ir_node *node);
 FIRM_API void     set_binop_right(ir_node *node, ir_node *right);
 
+/**
+ * Test wether a node is the X_except Proj of a fragile operation
+ */
+FIRM_API int      is_x_except_Proj(const ir_node *node);
+
+/**
+ * Test wether a node is the X_regular Proj of a fragile operation
+ */
+FIRM_API int      is_x_regular_Proj(const ir_node *node);
+
 /** returns the name of an ir_relation */
 FIRM_API const char *get_relation_string(ir_relation relation);
 
index 521c034..b573867 100644 (file)
@@ -60,8 +60,9 @@ typedef enum {
        irop_flag_labeled      = 1U << 0, /**< If set, output edge labels on in-edges in vcg graph. */
        irop_flag_commutative  = 1U << 1, /**< This operation is commutative. */
        irop_flag_cfopcode     = 1U << 2, /**< This operation is a control flow operation. */
-       irop_flag_fragile      = 1U << 3, /**< Set if the operation can change the control flow because
-                                      of an exception. */
+       irop_flag_fragile      = 1U << 3, /**< Set if the operation can change the
+                                              control flow because of an exception.
+                                          */
        irop_flag_forking      = 1U << 4, /**< Forking control flow at this operation. */
        irop_flag_highlevel    = 1U << 5, /**< This operation is a pure high-level one and can be
                                              skipped in low-level optimizations. */
@@ -280,6 +281,13 @@ FIRM_API ir_op *new_ir_op(unsigned code, const char *name, op_pin_state p,
                           unsigned flags, op_arity opar, int op_index,
                           size_t attr_size, const ir_op_ops *ops);
 
+/**
+ * Set proj-number for X_regular and X_except projs of fragile nodes.
+ * Note: should only be used immediately after new_ir_op
+ */
+FIRM_API void ir_op_set_fragile_indices(ir_op *op, int fragile_mem_index,
+                                        int pn_x_regular, int pn_x_except);
+
 /** Returns the ir_op_ops of an ir_op. */
 FIRM_API const ir_op_ops *get_op_ops(const ir_op *op);
 
index d52a814..79e3440 100644 (file)
@@ -343,7 +343,7 @@ static void construct_interval_block(ir_node *blk, ir_loop *l)
                cfop = get_Block_cfgpred(blk, i);
                if (is_Proj(cfop)) {
                        ir_node *op = skip_Proj(cfop);
-                       if (is_fragile_op(op) && get_Proj_proj(cfop) == pn_Generic_X_except) {
+                       if (is_x_except_Proj(cfop)) {
                                /*
                                 * Skip the Proj for the exception flow only, leave the
                                 * not exception flow Proj's intact.
index 27f3115..678c10c 100644 (file)
@@ -233,7 +233,7 @@ Jmp => {
 # Load / Store
 
 Load => {
-       op_flags  => [ "labeled", "fragile" ],
+       op_flags  => [ "labeled" ],
        irn_flags => [ "rematerializable" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "none" ], out => [ "gp" ] },
@@ -241,7 +241,7 @@ Load => {
 },
 
 Store => {
-       op_flags  => [ "labeled", "fragile" ],
+       op_flags  => [ "labeled" ],
        irn_flags => [ "rematerializable" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none" ] },
@@ -301,7 +301,7 @@ fConst => {
 # Load / Store
 
 fLoad => {
-       op_flags  => [ "labeled", "fragile" ],
+       op_flags  => [ "labeled" ],
        irn_flags => [ "rematerializable" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "none" ], out => [ "fp" ] },
@@ -309,7 +309,7 @@ fLoad => {
 },
 
 fStore => {
-       op_flags  => [ "labeled", "fragile" ],
+       op_flags  => [ "labeled" ],
        irn_flags => [ "rematerializable" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "fp", "none" ] },
index 6413609..8091083 100644 (file)
@@ -272,7 +272,7 @@ Jcc => {
        mode      => "mode_T",
 },
 Load => {
-       op_flags  => [ "labeled", "fragile" ],
+       op_flags  => [ "labeled" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "none" ],
                       out => [ "gp", "none" ] },
@@ -292,7 +292,7 @@ FrameAddr => {
        mode      => $mode_gp,
 },
 Store => {
-       op_flags  => [ "labeled", "fragile" ],
+       op_flags  => [ "labeled" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
        ins       => [ "ptr", "val", "mem" ],
index 471f7d3..a1155c7 100644 (file)
@@ -351,7 +351,6 @@ EmptyReg => {
 },
 
 CopyB => {
-       op_flags  => [ "fragile" ],
        state     => "pinned",
        attr      => "unsigned size",
        attr_type => "arm_CopyB_attr_t",
@@ -425,7 +424,7 @@ SwitchJmp => {
 },
 
 Ldr => {
-       op_flags  => [ "labeled", "fragile" ],
+       op_flags  => [ "labeled" ],
        state     => "exc_pinned",
        ins       => [ "ptr", "mem" ],
        outs      => [ "res", "M" ],
@@ -436,7 +435,7 @@ Ldr => {
 },
 
 Str => {
-       op_flags  => [ "labeled", "fragile" ],
+       op_flags  => [ "labeled" ],
        state     => "exc_pinned",
        ins       => [ "ptr", "val", "mem" ],
        outs      => [ "M" ],
@@ -448,7 +447,7 @@ Str => {
 },
 
 StoreStackM4Inc => {
-       op_flags  => [ "labeled", "fragile" ],
+       op_flags  => [ "labeled" ],
        irn_flags => [ "rematerializable" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "sp", "gp", "gp", "gp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
@@ -457,7 +456,7 @@ StoreStackM4Inc => {
 },
 
 LoadStackM3Epilogue => {
-       op_flags  => [ "labeled", "fragile" ],
+       op_flags  => [ "labeled" ],
        irn_flags => [ "rematerializable" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "sp", "none" ], out => [ "r11:I", "sp:I|S", "pc:I", "none" ] },
@@ -532,7 +531,7 @@ Cmfe => {
 },
 
 Ldf => {
-       op_flags  => [ "labeled", "fragile" ],
+       op_flags  => [ "labeled" ],
        state     => "exc_pinned",
        ins       => [ "ptr", "mem" ],
        outs      => [ "res", "M" ],
@@ -543,7 +542,7 @@ Ldf => {
 },
 
 Stf => {
-       op_flags  => [ "labeled", "fragile" ],
+       op_flags  => [ "labeled" ],
        state     => "exc_pinned",
        ins       => [ "ptr", "val", "mem" ],
        outs      => [ "M" ],
index c309892..199a7d4 100644 (file)
@@ -594,9 +594,9 @@ IDiv => {
        op_flags  => [ "fragile", "labeled" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ],
-                      out => [ "eax", "flags", "none", "edx", "none" ] },
+                      out => [ "eax", "flags", "none", "edx", "none", "none" ] },
        ins       => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
-       outs      => [ "div_res", "flags", "M", "mod_res", "X_exc" ],
+       outs      => [ "div_res", "flags", "M", "mod_res", "X_regular", "X_except" ],
        am        => "source,unary",
        emit      => ". idiv%M %unop3",
        latency   => 25,
@@ -608,9 +608,9 @@ Div => {
        op_flags  => [ "fragile", "labeled" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ],
-                      out => [ "eax", "flags", "none", "edx", "none" ] },
+                      out => [ "eax", "flags", "none", "edx", "none", "none" ] },
        ins       => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
-       outs      => [ "div_res", "flags", "M", "mod_res", "X_exc" ],
+       outs      => [ "div_res", "flags", "M", "mod_res", "X_regular", "X_except" ],
        am        => "source,unary",
        emit      => ". div%M %unop3",
        latency   => 25,
@@ -1152,7 +1152,7 @@ ChangeCW => {
 },
 
 FldCW => {
-       op_flags  => [ "fragile", "labeled" ],
+       op_flags  => [ "labeled" ],
        state     => "pinned",
        reg_req   => { in => [ "gp", "gp", "none" ], out => [ "fpcw:I" ] },
        ins       => [ "base", "index", "mem" ],
@@ -1164,7 +1164,7 @@ FldCW => {
 },
 
 FnstCW => {
-       op_flags  => [ "fragile", "labeled" ],
+       op_flags  => [ "labeled" ],
        state     => "pinned",
        reg_req   => { in => [ "gp", "gp", "none", "fp_cw" ], out => [ "none" ] },
        ins       => [ "base", "index", "mem", "fpcw" ],
@@ -1175,7 +1175,7 @@ FnstCW => {
 },
 
 FnstCWNOP => {
-       op_flags  => [ "fragile", "labeled" ],
+       op_flags  => [ "labeled" ],
        state     => "pinned",
        reg_req   => { in => [ "fp_cw" ], out => [ "none" ] },
        ins       => [ "fpcw" ],
@@ -1203,9 +1203,9 @@ Load => {
        op_flags  => [ "fragile", "labeled" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none" ],
-                      out => [ "gp", "none", "none", "none" ] },
+                      out => [ "gp", "none", "none", "none", "none" ] },
        ins       => [ "base", "index", "mem" ],
-       outs      => [ "res", "unused", "M", "X_exc" ],
+       outs      => [ "res", "unused", "M", "X_regular", "X_except" ],
        latency   => 0,
        emit      => ". mov%EX%.l %AM, %D0",
        units     => [ "GP" ],
@@ -1214,9 +1214,10 @@ Load => {
 Store => {
        op_flags  => [ "fragile", "labeled" ],
        state     => "exc_pinned",
-       reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none", "none" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "gp" ],
+                      out => [ "none", "none", "none" ] },
        ins       => [ "base", "index", "mem", "val" ],
-       outs      => [ "M", "X_exc" ],
+       outs      => [ "M", "X_regular", "X_except" ],
        emit      => '. mov%M %SI3, %AM',
        latency   => 2,
        units     => [ "GP" ],
@@ -1226,9 +1227,10 @@ Store => {
 Store8Bit => {
        op_flags  => [ "fragile", "labeled" ],
        state     => "exc_pinned",
-       reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => ["none", "none" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ],
+                      out => ["none", "none", "none" ] },
        ins       => [ "base", "index", "mem", "val" ],
-       outs      => [ "M", "X_exc" ],
+       outs      => [ "M", "X_regular", "X_except" ],
        emit      => '. mov%M %SB3, %AM',
        latency   => 2,
        units     => [ "GP" ],
@@ -1554,7 +1556,7 @@ Inport => {
 # Intel style prefetching
 #
 Prefetch0 => {
-       op_flags  => [ "fragile", "labeled" ],
+       op_flags  => [ "labeled" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
        ins       => [ "base", "index", "mem" ],
@@ -1565,7 +1567,7 @@ Prefetch0 => {
 },
 
 Prefetch1 => {
-       op_flags  => [ "fragile", "labeled" ],
+       op_flags  => [ "labeled" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
        ins       => [ "base", "index", "mem" ],
@@ -1576,7 +1578,7 @@ Prefetch1 => {
 },
 
 Prefetch2 => {
-       op_flags  => [ "fragile", "labeled" ],
+       op_flags  => [ "labeled" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
        ins       => [ "base", "index", "mem" ],
@@ -1587,7 +1589,7 @@ Prefetch2 => {
 },
 
 PrefetchNTA => {
-       op_flags  => [ "fragile", "labeled" ],
+       op_flags  => [ "labeled" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
        ins       => [ "base", "index", "mem" ],
@@ -1601,7 +1603,7 @@ PrefetchNTA => {
 # 3DNow! prefetch instructions
 #
 Prefetch => {
-       op_flags  => [ "fragile", "labeled" ],
+       op_flags  => [ "labeled" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
        ins       => [ "base", "index", "mem" ],
@@ -1612,7 +1614,7 @@ Prefetch => {
 },
 
 PrefetchW => {
-       op_flags  => [ "fragile", "labeled" ],
+       op_flags  => [ "labeled" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
        ins       => [ "base", "index", "mem" ],
@@ -1860,9 +1862,9 @@ xLoad => {
        op_flags  => [ "fragile", "labeled" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none" ],
-                      out => [ "xmm", "none", "none", "none" ] },
+                      out => [ "xmm", "none", "none", "none", "none" ] },
        ins       => [ "base", "index", "mem" ],
-       outs      => [ "res", "unused", "M", "X_exc" ],
+       outs      => [ "res", "unused", "M", "X_regular", "X_except" ],
        emit      => '. mov%XXM %AM, %D0',
        attr      => "ir_mode *load_mode",
        init_attr => "attr->ls_mode = load_mode;",
@@ -1873,9 +1875,10 @@ xLoad => {
 xStore => {
        op_flags => [ "fragile", "labeled" ],
        state    => "exc_pinned",
-       reg_req  => { in => [ "gp", "gp", "none", "xmm" ], out => [ "none", "none" ] },
+       reg_req  => { in => [ "gp", "gp", "none", "xmm" ],
+                     out => [ "none", "none", "none" ] },
        ins       => [ "base", "index", "mem", "val" ],
-       outs      => [ "M", "X_exc" ],
+       outs      => [ "M", "X_regular", "X_except" ],
        emit     => '. mov%XXM %S3, %AM',
        latency  => 0,
        units    => [ "SSE" ],
@@ -1885,9 +1888,10 @@ xStore => {
 xStoreSimple => {
        op_flags => [ "fragile", "labeled" ],
        state    => "exc_pinned",
-       reg_req  => { in => [ "gp", "gp", "none", "xmm" ], out => [ "none" ] },
+       reg_req  => { in => [ "gp", "gp", "none", "xmm" ],
+                     out => [ "none", "none", "none" ] },
        ins      => [ "base", "index", "mem", "val" ],
-       outs     => [ "M" ],
+       outs     => [ "M", "X_regular", "X_except" ],
        emit     => '. mov%XXM %S3, %AM',
        latency  => 0,
        units    => [ "SSE" ],
@@ -1895,7 +1899,7 @@ xStoreSimple => {
 },
 
 CvtSI2SS => {
-       op_flags => [ "fragile", "labeled" ],
+       op_flags => [ "labeled" ],
        state     => "exc_pinned",
        reg_req  => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
        ins      => [ "base", "index", "mem", "val" ],
@@ -1907,7 +1911,7 @@ CvtSI2SS => {
 },
 
 CvtSI2SD => {
-       op_flags => [ "fragile", "labeled" ],
+       op_flags => [ "labeled" ],
        state     => "exc_pinned",
        reg_req  => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
        ins      => [ "base", "index", "mem", "val" ],
@@ -1920,14 +1924,14 @@ CvtSI2SD => {
 
 
 l_LLtoFloat => {
-       op_flags => [ "fragile", "labeled" ],
+       op_flags => [ "labeled" ],
        cmp_attr => "return 1;",
        ins      => [ "val_high", "val_low" ],
        reg_req  => { in => [ "none", "none" ], out => [ "none" ] }
 },
 
 l_FloattoLL => {
-       op_flags => [ "fragile", "labeled" ],
+       op_flags => [ "labeled" ],
        cmp_attr => "return 1;",
        ins      => [ "val" ],
        outs     => [ "res_high", "res_low" ],
@@ -1937,12 +1941,14 @@ l_FloattoLL => {
 CopyB => {
        op_flags  => [ "fragile" ],
        state     => "pinned",
-       reg_req   => { in => [ "edi", "esi", "ecx", "none" ], out => [ "edi", "esi", "ecx", "none" ] },
-       outs      => [ "DST", "SRC", "CNT", "M" ],
+       reg_req   => { in => [ "edi", "esi", "ecx", "none" ],
+                      out => [ "edi", "esi", "ecx", "none", "none", "none" ] },
+       ins       => [ "dest", "source", "count", "mem" ],
+       outs      => [ "dest", "source", "count", "M", "X_regular", "X_except" ],
        attr_type => "ia32_copyb_attr_t",
        attr      => "unsigned size",
        units     => [ "GP" ],
-       latency  => 3,
+       latency   => 3,
 # we don't care about this flag, so no need to mark this node
 #      modified_flags => [ "DF" ]
 },
@@ -1950,12 +1956,14 @@ CopyB => {
 CopyB_i => {
        op_flags  => [ "fragile" ],
        state     => "pinned",
-       reg_req   => { in => [ "edi", "esi", "none" ], out => [  "edi", "esi", "none" ] },
-       outs      => [ "DST", "SRC", "M" ],
+       reg_req   => { in => [ "edi", "esi", "none" ],
+                      out => [  "edi", "esi", "none", "none", "none" ] },
+       ins       => [ "dest", "source", "mem" ],
+       outs      => [ "dest", "source", "M", "X_regular", "X_except" ],
        attr_type => "ia32_copyb_attr_t",
        attr      => "unsigned size",
        units     => [ "GP" ],
-       latency  => 3,
+       latency   => 3,
 # we don't care about this flag, so no need to mark this node
 #      modified_flags => [ "DF" ]
 },
@@ -2120,9 +2128,9 @@ vfld => {
        op_flags  => [ "fragile", "labeled" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none" ],
-                      out => [ "vfp", "none", "none", "none" ] },
+                      out => [ "vfp", "none", "none", "none", "none" ] },
        ins       => [ "base", "index", "mem" ],
-       outs      => [ "res", "unused", "M", "X_exc" ],
+       outs      => [ "res", "unused", "M", "X_regular", "X_except" ],
        attr      => "ir_mode *load_mode",
        init_attr => "attr->attr.ls_mode = load_mode;",
        latency   => 2,
@@ -2135,9 +2143,9 @@ vfst => {
        op_flags  => [ "fragile", "labeled" ],
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none", "vfp" ],
-                      out => [ "none", "none" ] },
+                      out => [ "none", "none", "none" ] },
        ins       => [ "base", "index", "mem", "val" ],
-       outs      => [ "M", "X_exc" ],
+       outs      => [ "M", "X_regular", "X_except" ],
        attr      => "ir_mode *store_mode",
        init_attr => "attr->attr.ls_mode = store_mode;",
        latency   => 2,
@@ -2441,7 +2449,7 @@ fchs => {
 
 fld => {
        irn_flags => [ "rematerializable" ],
-       op_flags  => [ "fragile", "labeled" ],
+       op_flags  => [ "labeled" ],
        state     => "exc_pinned",
        emit      => '. fld%XM %AM',
        attr_type => "ia32_x87_attr_t",
@@ -2451,7 +2459,7 @@ fld => {
 
 fst => {
        irn_flags => [ "rematerializable" ],
-       op_flags  => [ "fragile", "labeled" ],
+       op_flags  => [ "labeled" ],
        state     => "exc_pinned",
        emit      => '. fst%XM %AM',
        mode      => "mode_M",
@@ -2462,7 +2470,7 @@ fst => {
 
 fstp => {
        irn_flags => [ "rematerializable" ],
-       op_flags  => [ "fragile", "labeled" ],
+       op_flags  => [ "labeled" ],
        state     => "exc_pinned",
        emit      => '. fstp%XM %AM',
        mode      => "mode_M",
@@ -2693,9 +2701,11 @@ FtstFnstsw => {
 xxLoad => {
        op_flags  => [ "fragile", "labeled" ],
        state     => "exc_pinned",
-       reg_req   => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] },
+       reg_req   => { in => [ "gp", "gp", "none" ],
+                      out => [ "xmm", "none", "none", "none" ] },
        emit      => '. movdqu %D0, %AM',
-       outs      => [ "res", "M" ],
+       ins       => [ "base", "index", "mem" ],
+       outs      => [ "res", "M", "X_regular", "X_except" ],
        units     => [ "SSE" ],
        latency   => 1,
 },
@@ -2703,11 +2713,13 @@ xxLoad => {
 xxStore => {
        op_flags => [ "fragile", "labeled" ],
        state    => "exc_pinned",
-       reg_req  => { in => [ "gp", "gp", "none", "xmm" ] },
+       reg_req  => { in => [ "gp", "gp", "none", "xmm" ],
+                     out => [ "none", "none", "none" ] },
        ins      => [ "base", "index", "mem", "val" ],
+       outs     => [ "M", "X_regular", "X_except" ],
        emit     => '. movdqu %binop',
        units    => [ "SSE" ],
-       latency   => 1,
+       latency  => 1,
        mode     => "mode_M",
 },
 
index bfc9b3f..7ece981 100644 (file)
@@ -4522,10 +4522,9 @@ static ir_node *gen_Proj_be_SubSP(ir_node *node)
 static ir_node *gen_Proj_Load(ir_node *node)
 {
        ir_node  *new_pred;
-       ir_node  *block    = be_transform_node(get_nodes_block(node));
-       ir_node  *pred     = get_Proj_pred(node);
-       dbg_info *dbgi     = get_irn_dbg_info(node);
-       long     proj      = get_Proj_proj(node);
+       ir_node  *pred = get_Proj_pred(node);
+       dbg_info *dbgi = get_irn_dbg_info(node);
+       long      proj = get_Proj_proj(node);
 
        /* loads might be part of source address mode matches, so we don't
         * transform the ProjMs yet (with the exception of loads whose result is
@@ -4546,18 +4545,18 @@ static ir_node *gen_Proj_Load(ir_node *node)
        /* renumber the proj */
        new_pred = be_transform_node(pred);
        if (is_ia32_Load(new_pred)) {
-               switch (proj) {
+               switch ((pn_Load)proj) {
                case pn_Load_res:
                        return new_rd_Proj(dbgi, new_pred, mode_Iu, pn_ia32_Load_res);
                case pn_Load_M:
                        return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_Load_M);
-               case pn_Load_X_regular:
-                       return new_rd_Jmp(dbgi, block);
                case pn_Load_X_except:
                        /* This Load might raise an exception. Mark it. */
                        set_ia32_exc_label(new_pred, 1);
-                       return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_Load_X_exc);
-               default:
+                       return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_Load_X_except);
+               case pn_Load_X_regular:
+                       return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_Load_X_regular);
+               case pn_Load_max:
                        break;
                }
        } else if (is_ia32_Conv_I2I(new_pred) ||
@@ -4569,33 +4568,33 @@ static ir_node *gen_Proj_Load(ir_node *node)
                        return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_mem);
                }
        } else if (is_ia32_xLoad(new_pred)) {
-               switch (proj) {
+               switch ((pn_Load)proj) {
                case pn_Load_res:
                        return new_rd_Proj(dbgi, new_pred, mode_xmm, pn_ia32_xLoad_res);
                case pn_Load_M:
                        return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_xLoad_M);
-               case pn_Load_X_regular:
-                       return new_rd_Jmp(dbgi, block);
                case pn_Load_X_except:
                        /* This Load might raise an exception. Mark it. */
                        set_ia32_exc_label(new_pred, 1);
-                       return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_xLoad_X_exc);
-               default:
+                       return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_xLoad_X_except);
+               case pn_Load_X_regular:
+                       return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_xLoad_X_regular);
+               case pn_Load_max:
                        break;
                }
        } else if (is_ia32_vfld(new_pred)) {
-               switch (proj) {
+               switch ((pn_Load)proj) {
                case pn_Load_res:
                        return new_rd_Proj(dbgi, new_pred, mode_vfp, pn_ia32_vfld_res);
                case pn_Load_M:
                        return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_vfld_M);
-               case pn_Load_X_regular:
-                       return new_rd_Jmp(dbgi, block);
                case pn_Load_X_except:
                        /* This Load might raise an exception. Mark it. */
                        set_ia32_exc_label(new_pred, 1);
-                       return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_vfld_X_exc);
-               default:
+                       return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_vfld_X_except);
+               case pn_Load_X_regular:
+                       return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_vfld_X_regular);
+               case pn_Load_max:
                        break;
                }
        } else {
@@ -4619,16 +4618,15 @@ static ir_node *gen_Proj_Load(ir_node *node)
  */
 static ir_node *gen_Proj_Div(ir_node *node)
 {
-       ir_node  *block    = be_transform_node(get_nodes_block(node));
        ir_node  *pred     = get_Proj_pred(node);
        ir_node  *new_pred = be_transform_node(pred);
        dbg_info *dbgi     = get_irn_dbg_info(node);
-       long     proj      = get_Proj_proj(node);
+       long      proj     = get_Proj_proj(node);
 
        assert((long)pn_ia32_Div_M == (long)pn_ia32_IDiv_M);
        assert((long)pn_ia32_Div_div_res == (long)pn_ia32_IDiv_div_res);
 
-       switch (proj) {
+       switch ((pn_Div)proj) {
        case pn_Div_M:
                if (is_ia32_Div(new_pred) || is_ia32_IDiv(new_pred)) {
                        return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_Div_M);
@@ -4649,12 +4647,12 @@ static ir_node *gen_Proj_Div(ir_node *node)
                } else {
                        panic("Div transformed to unexpected thing %+F", new_pred);
                }
-       case pn_Div_X_regular:
-               return new_rd_Jmp(dbgi, block);
        case pn_Div_X_except:
                set_ia32_exc_label(new_pred, 1);
-               return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_Div_X_exc);
-       default:
+               return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_Div_X_except);
+       case pn_Div_X_regular:
+               return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_Div_X_regular);
+       case pn_Div_max:
                break;
        }
 
@@ -4675,15 +4673,17 @@ static ir_node *gen_Proj_Mod(ir_node *node)
        assert((long)pn_ia32_Div_M == (long)pn_ia32_IDiv_M);
        assert((long)pn_ia32_Div_mod_res == (long)pn_ia32_IDiv_mod_res);
 
-       switch (proj) {
+       switch ((pn_Mod)proj) {
        case pn_Mod_M:
                return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_Div_M);
        case pn_Mod_res:
                return new_rd_Proj(dbgi, new_pred, mode_Iu, pn_ia32_Div_mod_res);
        case pn_Mod_X_except:
                set_ia32_exc_label(new_pred, 1);
-               return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_Div_X_exc);
-       default:
+               return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_Div_X_except);
+       case pn_Mod_X_regular:
+               return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_Div_X_regular);
+       case pn_Mod_max:
                break;
        }
        panic("No idea how to transform proj->Mod");
index 3e353e6..cfe3cf5 100755 (executable)
@@ -681,10 +681,14 @@ EOF
                "start_block", "uses_memory", "dump_noblock", "dump_noinput",
                "machine", "machine_op", "cse_neutral"
        );
+       my $is_fragile = 0;
        foreach my $flag (@{$n{"op_flags"}}) {
                if (not defined($known_flags{$flag})) {
                        print STDERR "WARNING: Flag '$flag' in opcode $op is unknown\n";
                }
+               if ($flag eq "fragile") {
+                       $is_fragile = 1;
+               }
        }
        my @mapped = map { "irop_flag_$_" } @{$n{"op_flags"}};
        my $op_flags = join('|', @mapped);
@@ -698,6 +702,9 @@ EOF
        $temp  = "\top_$op = new_ir_op(cur_opcode + iro_$op, \"$op\", op_pin_state_".$n{"state"}.", $op_flags";
        $temp .= "|irop_flag_machine, ".translate_arity($arity).", 0, ${attr_size}, &ops);\n";
        push(@obst_new_irop, $temp);
+       if ($is_fragile) {
+               push(@obst_new_irop, "\tir_op_set_fragile_indices(op_${op}, n_${op}_mem, pn_${op}_X_regular, pn_${op}_X_except);\n");
+       }
        push(@obst_new_irop, "\tset_op_tag(op_$op, $arch\_op_tag);\n");
        if(defined($default_op_attr_type)) {
                push(@obst_new_irop, "\tattr = &attrs[iro_$op];\n");
index a2d4d1b..45aabf2 100644 (file)
@@ -325,7 +325,7 @@ SubX_t => {
 
 # Load / Store
 Ld => {
-       op_flags  => [ "labeled", "fragile" ],
+       op_flags  => [ "labeled" ],
        state     => "exc_pinned",
        constructors => {
                imm => {
@@ -358,7 +358,7 @@ SetHi => {
 },
 
 St => {
-       op_flags  => [ "labeled", "fragile" ],
+       op_flags  => [ "labeled" ],
        mode      => "mode_M",
        state     => "exc_pinned",
        constructors => {
@@ -832,7 +832,7 @@ fftoi => {
 },
 
 Ldf => {
-       op_flags  => [ "labeled", "fragile" ],
+       op_flags  => [ "labeled" ],
        state     => "exc_pinned",
        constructors => {
                s => {
@@ -854,7 +854,7 @@ Ldf => {
 },
 
 Stf => {
-       op_flags  => [ "labeled", "fragile" ],
+       op_flags  => [ "labeled" ],
        state     => "exc_pinned",
        constructors => {
                s => {
index 10df911..53bed2e 100644 (file)
@@ -1306,6 +1306,28 @@ int (is_arg_Proj)(const ir_node *node)
        return _is_arg_Proj(node);
 }
 
+int is_x_except_Proj(const ir_node *node)
+{
+       ir_node *pred;
+       if (!is_Proj(node))
+               return false;
+       pred = get_Proj_pred(node);
+       if (!is_fragile_op(pred))
+               return false;
+       return get_Proj_proj(node) == pred->op->pn_x_except;
+}
+
+int is_x_regular_Proj(const ir_node *node)
+{
+       ir_node *pred;
+       if (!is_Proj(node))
+               return false;
+       pred = get_Proj_pred(node);
+       if (!is_fragile_op(pred))
+               return false;
+       return get_Proj_proj(node) == pred->op->pn_x_except;
+}
+
 ir_node **get_Tuple_preds_arr(ir_node *node)
 {
        assert(is_Tuple(node));
@@ -1521,23 +1543,7 @@ int is_fragile_op(const ir_node *node)
 ir_node *get_fragile_op_mem(ir_node *node)
 {
        assert(node && is_fragile_op(node));
-
-       switch (get_irn_opcode(node)) {
-       case iro_Call  :
-       case iro_Div   :
-       case iro_Mod   :
-       case iro_Load  :
-       case iro_Store :
-       case iro_Alloc :
-       case iro_Bound :
-       case iro_CopyB :
-               return get_irn_n(node, pn_Generic_M);
-       case iro_Bad   :
-       case iro_Unknown:
-               return node;
-       default:
-               panic("should not be reached");
-       }
+       return get_irn_n(node, node->op->fragile_mem_index);
 }
 
 /* Returns true if the operation is a forking control flow operation. */
index 7a59fa1..31adf0c 100644 (file)
@@ -189,6 +189,14 @@ void free_ir_op(ir_op *code)
        free(code);
 }  /* free_ir_op */
 
+void ir_op_set_fragile_indices(ir_op *op, int fragile_mem_index,
+                               int pn_x_regular, int pn_x_except)
+{
+       op->fragile_mem_index = fragile_mem_index;
+       op->pn_x_regular = pn_x_regular;
+       op->pn_x_except = pn_x_except;
+}
+
 /* Returns the string for the opcode. */
 const char *get_op_name (const ir_op *op)
 {
index b17299c..56de92c 100644 (file)
@@ -61,17 +61,25 @@ ENUM_COUNTABLE(ir_phase_id)
 
 /** The type of an ir_op. */
 struct ir_op {
-       unsigned code;          /**< The unique opcode of the op. */
-       ident *name;            /**< The name of the op. */
-       size_t attr_size;       /**< Space needed in memory for private attributes. */
-       op_pin_state pin_state; /**< How to deal with the node in CSE, PRE. */
-       op_arity opar;          /**< The arity of operator. */
-       int op_index;           /**< The index of the first data operand, 0 for most cases, 1 for Div etc. */
-       unsigned flags;         /**< Flags describing the behavior of the ir_op, a bitmasks of irop_flags. */
-       unsigned tag;           /**< Some custom TAG value the op's creator set to. */
-       void *attr;             /**< custom pointer where op's creator can attach attribute stuff to. */
-
-       ir_op_ops ops;          /**< The operations of the this op. */
+       unsigned code;            /**< The unique opcode of the op. */
+       ident *name;              /**< The name of the op. */
+       size_t attr_size;         /**< Space needed in memory for private attributes
+                                      */
+       op_pin_state pin_state;   /**< How to deal with the node in CSE, PRE. */
+       op_arity opar;            /**< The arity of operator. */
+       int op_index;             /**< The index of the first data operand, 0 for
+                                      most cases, 1 for Div etc. */
+       int fragile_mem_index;    /**< index of memory input for fragile nodes */
+       int pn_x_regular;         /**< for fragile ops the position of the
+                                      X_regular output */
+       int pn_x_except;          /**< for fragile ops the position of the
+                                      X_except output */
+       unsigned flags;           /**< Flags describing the behavior of the ir_op,
+                                      a bitmasks of irop_flags. */
+       unsigned tag;             /**< Some custom TAG value the op's creator set */
+       void *attr;               /**< custom pointer where op's creator can attach
+                                      attribute stuff to. */
+       ir_op_ops ops;            /**< The operations of the this op. */
 };
 
 /**
index 0d0a884..765f032 100644 (file)
@@ -69,7 +69,7 @@ static void walk_critical_cf_edges(ir_node *n, void *env)
 
                        cfop = get_irn_op(skip_Proj(pre));
                        if (is_op_fragile(cfop)) {
-                               if (cenv->ignore_exc_edges && get_Proj_proj(pre) == pn_Generic_X_except)
+                               if (cenv->ignore_exc_edges && is_x_except_Proj(pre))
                                        continue;
                                goto insert;
                        }
index 817e111..c8552d6 100644 (file)
@@ -215,7 +215,7 @@ static void collect_nodes(ir_node *node, void *env)
 
                        if (is_Proj(proj)) {
                                pred   = get_Proj_pred(proj);
-                               is_exc = get_Proj_proj(proj) == pn_Generic_X_except;
+                               is_exc = is_x_except_Proj(proj);
                        }
 
                        /* ignore Bad predecessors, they will be removed later */
index 9226a47..6c3d116 100644 (file)
@@ -1205,7 +1205,7 @@ static void update_Call_memop(memop_t *m)
  *
  * @param m  the memop
  */
-static void update_DivOp_memop(memop_t *m)
+static void update_Div_memop(memop_t *m)
 {
        ir_node *div = m->node;
        int     i;
@@ -1218,15 +1218,38 @@ static void update_DivOp_memop(memop_t *m)
                        continue;
 
                switch (get_Proj_proj(proj)) {
-               case pn_Generic_X_except:
+               case pn_Div_X_except:
                        m->flags |= FLAG_EXCEPTION;
                        break;
-               case pn_Generic_M:
+               case pn_Div_M:
                        m->mem = proj;
                        break;
                }
        }
-}  /* update_DivOp_memop */
+}
+
+static void update_Mod_memop(memop_t *m)
+{
+       ir_node *div = m->node;
+       int     i;
+
+       for (i = get_irn_n_outs(div) - 1; i >= 0; --i) {
+               ir_node *proj = get_irn_out(div, i);
+
+               /* beware of keep edges */
+               if (is_End(proj))
+                       continue;
+
+               switch (get_Proj_proj(proj)) {
+               case pn_Mod_X_except:
+                       m->flags |= FLAG_EXCEPTION;
+                       break;
+               case pn_Mod_M:
+                       m->mem = proj;
+                       break;
+               }
+       }
+}
 
 /**
  * Update a memop for a Phi.
@@ -1291,8 +1314,10 @@ static void collect_memops(ir_node *irn, void *ctx)
                        /* we can those to find the memory edge */
                        break;
                case iro_Div:
+                       update_Div_memop(op);
+                       break;
                case iro_Mod:
-                       update_DivOp_memop(op);
+                       update_Mod_memop(op);
                        break;
 
                case iro_Builtin:
index c9e8808..bceca3a 100755 (executable)
@@ -455,6 +455,9 @@ void init_op(void)
                        {{node|attr_size}}
                        NULL
                {% endfilter %});
+       {%- if "fragile" in node.flags: %}
+       ir_op_set_fragile_indices(op_{{node.name}}, n_{{node.name}}_mem, pn_{{node.name}}_X_regular, pn_{{node.name}}_X_except);
+       {%- endif -%}
        {%- endfor %}
 
        be_init_op();
index 5e47b09..b4d5710 100755 (executable)
@@ -38,10 +38,10 @@ class Alloc(Op):
                ("count", "number of objects to allocate" ),
        ]
        outs  = [
-               ("M",         "memory result",                         "pn_Generic_M"),
-               ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
-               ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
-               ("res",       "pointer to newly allocated memory",     "pn_Generic_other"),
+               ("M",         "memory result"),
+               ("X_regular", "control flow when no exception occurs"),
+               ("X_except",  "control flow when exception occured"),
+               ("res",       "pointer to newly allocated memory"),
        ]
        attrs = [
                dict(
@@ -201,10 +201,10 @@ class Bound(Op):
                ("upper",  "upper bound (exclusive)"),
        ]
        outs  = [
-               ("M",         "memory result",                         "pn_Generic_M"),
-               ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
-               ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
-               ("res",       "the checked index",                     "pn_Generic_other"),
+               ("M",         "memory result"),
+               ("X_regular", "control flow when no exception occurs"),
+               ("X_except",  "control flow when exception occured"),
+               ("res",       "the checked index"),
        ]
        flags  = [ "fragile", "highlevel" ]
        pinned = "exception"
@@ -219,8 +219,8 @@ class Builtin(Op):
        ]
        arity    = "variable"
        outs     = [
-               ("M",        "memory result", "pn_Generic_M"),
-               ("1_result", "first result",  "pn_Generic_other"),
+               ("M",        "memory result"),
+               ("1_result", "first result"),
        ]
        flags    = [ "uses_memory" ]
        attrs    = [
@@ -253,10 +253,10 @@ class Call(Op):
        ]
        arity    = "variable"
        outs     = [
-               ("M",                "memory result",                         "pn_Generic_M"),
-               ("X_regular",        "control flow when no exception occurs", "pn_Generic_X_regular"),
-               ("X_except",         "control flow when exception occured",   "pn_Generic_X_except"),
-               ("T_result",         "tuple containing all results",          "pn_Generic_other"),
+               ("M",                "memory result"),
+               ("X_regular",        "control flow when no exception occurs"),
+               ("X_except",         "control flow when exception occured"),
+               ("T_result",         "tuple containing all results"),
        ]
        flags    = [ "fragile", "uses_memory" ]
        attrs    = [
@@ -417,9 +417,9 @@ class CopyB(Op):
                ("src",  "source address"),
        ]
        outs  = [
-               ("M",         "memory result",                         "pn_Generic_M"),
-               ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
-               ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
+               ("M",         "memory result"),
+               ("X_regular", "control flow when no exception occurs"),
+               ("X_except",  "control flow when exception occured"),
        ]
        flags = [ "fragile", "uses_memory" ]
        attrs = [
@@ -442,10 +442,10 @@ class Div(Op):
                ("right", "second operand"),
        ]
        outs  = [
-               ("M",         "memory result",                         "pn_Generic_M"),
-               ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
-               ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
-               ("res",       "result of computation",                 "pn_Generic_other"),
+               ("M",         "memory result"),
+               ("X_regular", "control flow when no exception occurs"),
+               ("X_except",  "control flow when exception occured"),
+               ("res",       "result of computation"),
        ]
        flags = [ "fragile", "uses_memory" ]
        attrs_name = "div"
@@ -542,10 +542,10 @@ class InstOf(Op):
           ("obj",   "pointer to object being queried")
        ]
        outs  = [
-               ("M",         "memory result",                         "pn_Generic_M"),
-               ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
-               ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
-               ("res",       "checked object pointer",                "pn_Generic_other"),
+               ("M",         "memory result"),
+               ("X_regular", "control flow when no exception occurs"),
+               ("X_except",  "control flow when exception occured"),
+               ("res",       "checked object pointer"),
        ]
        flags = [ "highlevel" ]
        attrs = [
@@ -573,10 +573,10 @@ class Load(Op):
                ("ptr",  "address to load from"),
        ]
        outs  = [
-               ("M",         "memory result",                         "pn_Generic_M"),
-               ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
-               ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
-               ("res",       "result of load operation",              "pn_Generic_other"),
+               ("M",         "memory result"),
+               ("X_regular", "control flow when no exception occurs"),
+               ("X_except",  "control flow when exception occured"),
+               ("res",       "result of load operation"),
        ]
        flags    = [ "fragile", "uses_memory" ]
        pinned   = "exception"
@@ -628,10 +628,10 @@ class Mod(Op):
                ("right", "second operand"),
        ]
        outs  = [
-               ("M",         "memory result",                         "pn_Generic_M"),
-               ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
-               ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
-               ("res",       "result of computation",                 "pn_Generic_other"),
+               ("M",         "memory result"),
+               ("X_regular", "control flow when no exception occurs"),
+               ("X_except",  "control flow when exception occured"),
+               ("res",       "result of computation"),
        ]
        flags = [ "fragile", "uses_memory" ]
        attrs_name = "mod"
@@ -743,8 +743,8 @@ class Raise(Op):
                ("exo_ptr", "pointer to exception object to be thrown"),
        ]
        outs  = [
-               ("M", "memory result",                     "pn_Generic_M"),
-               ("X", "control flow to exception handler", "pn_Generic_X_regular"),
+               ("M", "memory result"),
+               ("X", "control flow to exception handler"),
        ]
        flags  = [ "highlevel", "cfopcode" ]
        pinned = "yes"
@@ -825,9 +825,9 @@ class Store(Op):
           ("value", "value to store"),
        ]
        outs  = [
-               ("M",         "memory result",                         "pn_Generic_M"),
-               ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
-               ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
+               ("M",         "memory result"),
+               ("X_regular", "control flow when no exception occurs"),
+               ("X_except",  "control flow when exception occured"),
        ]
        flags    = [ "fragile", "uses_memory" ]
        pinned   = "exception"
index c33d9c3..7fd35a4 100644 (file)
@@ -8,6 +8,12 @@ def isAbstract(nodetype):
 def is_dynamic_pinned(node):
        return node.pinned in ["memory", "exception"]
 
+def inout_contains(l, name):
+       for entry in l:
+               if entry[0] == name:
+                       return True
+       return False
+
 def verify_node(node):
        if not hasattr(node, "pinned"):
                print "%s: NO PINNED SET" % node.__name__
@@ -18,6 +24,15 @@ def verify_node(node):
                print "WARNING: no flags specified for %s\n" % node.__name__
        elif type(node.flags) != list:
                print "ERROR: flags of %s not a list" % node.__name__
+       if hasattr(node, "flags"):
+               flags = node.flags
+               if "fragile" in flags:
+                       if not inout_contains(node.ins, "mem"):
+                               print "ERROR: fragile node %s needs an input named 'mem'" % node.__name__
+                       if not inout_contains(node.outs, "X_regular"):
+                               print "ERROR: fragile node %s needs an output named 'X_regular'" % node.__name__
+                       if not inout_contains(node.outs, "X_except"):
+                               print "ERROR: fragile node %s needs an output named 'X_except'" % node.__name__
 
 def setldefault(node, attr, val):
        # Don't use hasattr, as these things should not be inherited