+ progress |= nir_convert_from_ssa_impl(function->impl, phi_webs_only);
+ }
+
+ return progress;
+}
+
+
+static void
+place_phi_read(nir_shader *shader, nir_register *reg,
+ nir_ssa_def *def, nir_block *block)
+{
+ if (block != def->parent_instr->block) {
+ /* Try to go up the single-successor tree */
+ bool all_single_successors = true;
+ struct set_entry *entry;
+ set_foreach(block->predecessors, entry) {
+ nir_block *pred = (nir_block *)entry->key;
+ if (pred->successors[0] && pred->successors[1]) {
+ all_single_successors = false;
+ break;
+ }
+ }
+
+ if (all_single_successors) {
+ /* All predecessors of this block have exactly one successor and it
+ * is this block so they must eventually lead here without
+ * intersecting each other. Place the reads in the predecessors
+ * instead of this block.
+ */
+ set_foreach(block->predecessors, entry)
+ place_phi_read(shader, reg, def, (nir_block *)entry->key);
+ return;
+ }
+ }
+
+ nir_alu_instr *mov = nir_alu_instr_create(shader, nir_op_imov);
+ mov->src[0].src = nir_src_for_ssa(def);
+ mov->dest.dest = nir_dest_for_reg(reg);
+ mov->dest.write_mask = (1 << reg->num_components) - 1;
+ nir_instr_insert(nir_after_block_before_jump(block), &mov->instr);
+}
+
+/** Lower all of the phi nodes in a block to imovs to and from a register
+ *
+ * This provides a very quick-and-dirty out-of-SSA pass that you can run on a
+ * single block to convert all of its phis to a register and some imovs.
+ * The code that is generated, while not optimal for actual codegen in a
+ * back-end, is easy to generate, correct, and will turn into the same set of
+ * phis after you call regs_to_ssa and do some copy propagation.
+ *
+ * The one intelligent thing this pass does is that it places the moves from
+ * the phi sources as high up the predecessor tree as possible instead of in
+ * the exact predecessor. This means that, in particular, it will crawl into
+ * the deepest nesting of any if-ladders. In order to ensure that doing so is
+ * safe, it stops as soon as one of the predecessors has multiple successors.
+ */
+bool
+nir_lower_phis_to_regs_block(nir_block *block)
+{
+ nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node);
+ nir_shader *shader = impl->function->shader;
+
+ bool progress = false;
+ nir_foreach_instr_safe(instr, block) {
+ if (instr->type != nir_instr_type_phi)
+ break;
+
+ nir_phi_instr *phi = nir_instr_as_phi(instr);
+ assert(phi->dest.is_ssa);
+
+ nir_register *reg = create_reg_for_ssa_def(&phi->dest.ssa, impl);
+
+ nir_alu_instr *mov = nir_alu_instr_create(shader, nir_op_imov);
+ mov->src[0].src = nir_src_for_reg(reg);
+ mov->dest.write_mask = (1 << phi->dest.ssa.num_components) - 1;
+ nir_ssa_dest_init(&mov->instr, &mov->dest.dest,
+ phi->dest.ssa.num_components, phi->dest.ssa.bit_size,
+ phi->dest.ssa.name);
+ nir_instr_insert(nir_after_instr(&phi->instr), &mov->instr);
+
+ nir_ssa_def_rewrite_uses(&phi->dest.ssa,
+ nir_src_for_ssa(&mov->dest.dest.ssa));
+
+ nir_foreach_phi_src(src, phi) {
+ assert(src->src.is_ssa);
+ place_phi_read(shader, reg, src->src.ssa, src->pred);
+ }
+
+ nir_instr_remove(&phi->instr);
+
+ progress = true;