+/* Allocate values defined by instructions such as TEX, which have to be
+ * assigned to consecutive registers.
+ * Linear scan doesn't really work here since the values can have different
+ * live intervals.
+ */
+static int
+pass_allocate_constrained_values(struct nv_pc_pass *ctx)
+{
+ struct nv_value regvals, *val;
+ struct nv_instruction *i;
+ struct nv_value *defs[4];
+ struct register_set regs[4];
+ int n, vsize, c;
+ uint32_t mask;
+ boolean mem;
+
+ collect_register_values(ctx, ®vals, TRUE);
+
+ for (n = 0; n < ctx->num_insns; ++n) {
+ i = ctx->insns[n];
+ vsize = nvi_vector_size(i);
+ if (!(vsize > 1))
+ continue;
+ assert(vsize <= 4);
+ for (c = 0; c < vsize; ++c)
+ defs[c] = i->def[c]->join;
+
+ if (defs[0]->reg.id >= 0) {
+ for (c = 1; c < vsize; ++c)
+ assert(defs[c]->reg.id >= 0);
+ continue;
+ }
+
+ /* Compute registers available for this "vector" of consecutive registers.
+ * Each value (component) has its own independent live interval.
+ */
+ for (c = 0; c < vsize; ++c) {
+ nv50_ctor_register_set(ctx->pc, ®s[c]);
+
+ foreach(val, ®vals) {
+ if (val->reg.id >= 0 && livei_have_overlap(val, defs[c]))
+ reg_occupy(®s[c], val);
+ }
+ /* Only 32 bit GPRs will be allocated here, but register set
+ * granularity for GPRs is 16 bit.
+ */
+ mask = 0x03030303;
+ if (vsize == 2) /* granularity is 2 and not 4 */
+ mask |= 0x03030303 << 4;
+ mask_register_set(®s[c], 0, mask << (c * 2));
+
+ if (defs[c]->livei)
+ insert_ordered_tail(®vals, defs[c]);
+ }
+ for (c = 1; c < vsize; ++c)
+ intersect_register_sets(®s[0], ®s[0], ®s[c]);
+
+ mem = !reg_assign(®s[0], &defs[0], vsize);
+
+ if (mem) {
+ NOUVEAU_ERR("out of registers\n");
+ abort();
+ }
+ }
+ return 0;
+}
+