+static ir_node *search_def_end_of_block(be_ssa_construction_env_t *env,
+ ir_node *block);
+
+struct constr_info {
+ bool is_definition : 1;
+ bool is_use : 1;
+ bool already_processed : 1;
+ union {
+ /* Since we only consider scheduled nodes,
+ * this points to the real definition (e.g. a Proj). */
+ ir_node *definition;
+
+ /* Last definition of a block. */
+ ir_node *last_definition;
+ };
+};
+
+typedef struct constr_info constr_info;
+
+/**
+ * @return Whether the block contains a definition.
+ */
+static bool has_definition(const ir_node *block)
+{
+ return irn_visited(block);
+}
+
+static constr_info *get_or_set_info(be_ssa_construction_env_t *env,
+ const ir_node *node)
+{
+ constr_info *info = ir_nodemap_get(&env->infos, node);
+ if (info == NULL) {
+ info = OALLOCZ(&env->obst, constr_info);
+ ir_nodemap_insert(&env->infos, node, info);
+ }
+ return info;
+}
+
+static constr_info *get_info(const be_ssa_construction_env_t *env,
+ const ir_node *node)
+{
+ return (constr_info*)ir_nodemap_get(&env->infos, node);
+}
+
+/**
+ * @return Whether the block contains a use.
+ */
+static inline bool has_use(be_ssa_construction_env_t *env, ir_node *block)
+{
+ constr_info *info = get_or_set_info(env, block);
+ return info->is_use;
+}
+
+/**
+ * @return Whether the node is a definition.
+ */
+static bool is_definition(be_ssa_construction_env_t *env, ir_node *node)
+{
+ constr_info *info = get_info(env, node);
+ return info != NULL && info->is_definition;
+}
+
+/**
+ * @return Whether the node is a use.
+ */
+static bool is_use(const be_ssa_construction_env_t *env, ir_node *node)
+{
+ constr_info *info = get_info(env, node);
+ return info != NULL && info->is_use;
+}
+
+/**
+ * Introduces a definition at the corresponding block.
+ */
+static void introduce_definition(be_ssa_construction_env_t *env, ir_node *def)
+{
+ ir_node *block = get_nodes_block(def);
+ constr_info *def_info = get_or_set_info(env, def);
+ ir_node *skip = skip_Proj(def);
+ constr_info *skip_info = get_or_set_info(env, skip);
+ constr_info *block_info = get_or_set_info(env, block);
+
+ DBG((dbg, LEVEL_2, "\tintroducing definition %+F in %+F\n", def, block));
+
+ def_info->is_definition = true;
+
+ skip_info->is_definition = true;
+ skip_info->definition = def;
+
+ // Set the last definition if we only introduce one definition for the block
+ if (has_definition(block)) {
+ assert(!block_info->already_processed);
+ block_info->last_definition = NULL;
+ } else {
+ mark_irn_visited(block);
+ block_info->last_definition = def;
+ }
+}
+
+static void introduce_use(be_ssa_construction_env_t *env, ir_node *use)
+{
+ ir_node *block = get_nodes_block(use);
+ constr_info *info = get_or_set_info(env, use);
+ constr_info *block_info = get_or_set_info(env, block);
+
+ DBG((dbg, LEVEL_2, "\tintroducing use %+F in %+F\n", use, block));
+
+ info->is_use = true;
+ block_info->is_use = true;
+
+ waitq_put(env->worklist, use);
+}
+