Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
  2.  
  3. /*
  4.  * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice (including the next
  14.  * paragraph) shall be included in all copies or substantial portions of the
  15.  * Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23.  * SOFTWARE.
  24.  *
  25.  * Authors:
  26.  *    Rob Clark <robclark@freedesktop.org>
  27.  */
  28.  
  29. #include "pipe/p_shader_tokens.h"
  30. #include "util/u_math.h"
  31.  
  32. #include "ir3.h"
  33.  
  34. /*
  35.  * Register Assignment:
  36.  *
  37.  * NOTE: currently only works on a single basic block.. need to think
  38.  * about how multiple basic blocks are going to get scheduled.  But
  39.  * I think I want to re-arrange how blocks work, ie. get rid of the
  40.  * block nesting thing..
  41.  *
  42.  * NOTE: we could do register coalescing (eliminate moves) as part of
  43.  * the RA step.. OTOH I think we need to do scheduling before register
  44.  * assignment.  And if we remove a mov that effects scheduling (unless
  45.  * we leave a placeholder nop, which seems lame), so I'm not really
  46.  * sure how practical this is to do both in a single stage.  But OTOH
  47.  * I'm not really sure a sane way for the CP stage to realize when it
  48.  * cannot remove a mov due to multi-register constraints..
  49.  *
  50.  * NOTE: http://scopesconf.org/scopes-01/paper/session1_2.ps.gz has
  51.  * some ideas to handle array allocation with a more conventional
  52.  * graph coloring algorithm for register assignment, which might be
  53.  * a good alternative to the current algo.  However afaict it cannot
  54.  * handle overlapping arrays, which is a scenario that we have to
  55.  * deal with
  56.  */
  57.  
  58. struct ir3_ra_ctx {
  59.         struct ir3_block *block;
  60.         enum shader_t type;
  61.         bool frag_coord;
  62.         bool frag_face;
  63.         int cnt;
  64.         bool error;
  65.         struct {
  66.                 unsigned base;
  67.                 unsigned size;
  68.         } arrays[MAX_ARRAYS];
  69. };
  70.  
  71. #ifdef DEBUG
  72. #  include "freedreno_util.h"
  73. #  define ra_debug (fd_mesa_debug & FD_DBG_OPTMSGS)
  74. #else
  75. #  define ra_debug 0
  76. #endif
  77.  
  78. #define ra_dump_list(msg, n) do { \
  79.                 if (ra_debug) { \
  80.                         debug_printf("-- " msg); \
  81.                         ir3_dump_instr_list(n); \
  82.                 } \
  83.         } while (0)
  84.  
  85. #define ra_dump_instr(msg, n) do { \
  86.                 if (ra_debug) { \
  87.                         debug_printf(">> " msg); \
  88.                         ir3_dump_instr_single(n); \
  89.                 } \
  90.         } while (0)
  91.  
  92. #define ra_assert(ctx, x) do { \
  93.                 debug_assert(x); \
  94.                 if (!(x)) { \
  95.                         debug_printf("RA: failed assert: %s\n", #x); \
  96.                         (ctx)->error = true; \
  97.                 }; \
  98.         } while (0)
  99.  
  100.  
  101. /* sorta ugly way to retrofit half-precision support.. rather than
  102.  * passing extra param around, just OR in a high bit.  All the low
  103.  * value arithmetic (ie. +/- offset within a contiguous vec4, etc)
  104.  * will continue to work as long as you don't underflow (and that
  105.  * would go badly anyways).
  106.  */
  107. #define REG_HALF  0x8000
  108.  
  109. #define REG(n, wm, f) (struct ir3_register){ \
  110.                 .flags  = (f), \
  111.                 .num    = (n), \
  112.                 .wrmask = TGSI_WRITEMASK_ ## wm, \
  113.         }
  114.  
  115. /* check that the register exists, is a GPR and is not special (a0/p0) */
  116. static struct ir3_register * reg_check(struct ir3_instruction *instr, unsigned n)
  117. {
  118.         if ((n < instr->regs_count) && reg_gpr(instr->regs[n]) &&
  119.                         !(instr->regs[n]->flags & IR3_REG_SSA))
  120.                 return instr->regs[n];
  121.         return NULL;
  122. }
  123.  
  124. /* figure out if an unassigned src register points back to the instr we
  125.  * are assigning:
  126.  */
  127. static bool instr_used_by(struct ir3_instruction *instr,
  128.                 struct ir3_register *src)
  129. {
  130.         struct ir3_instruction *src_instr = ssa(src);
  131.         unsigned i;
  132.         if (instr == src_instr)
  133.                 return true;
  134.         if (src_instr && is_meta(src_instr))
  135.                 for (i = 1; i < src_instr->regs_count; i++)
  136.                         if (instr_used_by(instr, src_instr->regs[i]))
  137.                                 return true;
  138.  
  139.         return false;
  140. }
  141.  
  142. static bool instr_is_output(struct ir3_instruction *instr)
  143. {
  144.         struct ir3_block *block = instr->block;
  145.         unsigned i;
  146.  
  147.         for (i = 0; i < block->noutputs; i++)
  148.                 if (instr == block->outputs[i])
  149.                         return true;
  150.  
  151.         return false;
  152. }
  153.  
  154. static void mark_sources(struct ir3_instruction *instr,
  155.                 struct ir3_instruction *n, regmask_t *liveregs, regmask_t *written)
  156. {
  157.         unsigned i;
  158.  
  159.         for (i = 1; i < n->regs_count; i++) {
  160.                 struct ir3_register *r = reg_check(n, i);
  161.                 if (r)
  162.                         regmask_set_if_not(liveregs, r, written);
  163.  
  164.                 /* if any src points back to the instruction(s) in
  165.                  * the block of neighbors that we are assigning then
  166.                  * mark any written (clobbered) registers as live:
  167.                  */
  168.                 if (instr_used_by(instr, n->regs[i]))
  169.                         regmask_or(liveregs, liveregs, written);
  170.         }
  171.  
  172. }
  173.  
  174. /* live means read before written */
  175. static void compute_liveregs(struct ir3_ra_ctx *ctx,
  176.                 struct ir3_instruction *instr, regmask_t *liveregs)
  177. {
  178.         struct ir3_block *block = instr->block;
  179.         struct ir3_instruction *n;
  180.         regmask_t written;
  181.         unsigned i;
  182.  
  183.         regmask_init(&written);
  184.  
  185.         for (n = instr->next; n; n = n->next) {
  186.                 struct ir3_register *r;
  187.  
  188.                 if (is_meta(n))
  189.                         continue;
  190.  
  191.                 /* check first src's read: */
  192.                 mark_sources(instr, n, liveregs, &written);
  193.  
  194.                 /* for instructions that write to an array, we need to
  195.                  * capture the dependency on the array elements:
  196.                  */
  197.                 if (n->fanin)
  198.                         mark_sources(instr, n->fanin, liveregs, &written);
  199.  
  200.                 /* meta-instructions don't actually get scheduled,
  201.                  * so don't let it's write confuse us.. what we
  202.                  * really care about is when the src to the meta
  203.                  * instr was written:
  204.                  */
  205.                 if (is_meta(n))
  206.                         continue;
  207.  
  208.                 /* then dst written (if assigned already): */
  209.                 r = reg_check(n, 0);
  210.                 if (r) {
  211.                         /* if an instruction *is* an output, then it is live */
  212.                         if (!instr_is_output(n))
  213.                                 regmask_set(&written, r);
  214.                 }
  215.  
  216.         }
  217.  
  218.         /* be sure to account for output registers too: */
  219.         for (i = 0; i < block->noutputs; i++) {
  220.                 struct ir3_register *r;
  221.                 if (!block->outputs[i])
  222.                         continue;
  223.                 r = reg_check(block->outputs[i], 0);
  224.                 if (r)
  225.                         regmask_set_if_not(liveregs, r, &written);
  226.         }
  227.  
  228.         /* if instruction is output, we need a reg that isn't written
  229.          * before the end.. equiv to the instr_used_by() check above
  230.          * in the loop body
  231.          * TODO maybe should follow fanin/fanout?
  232.          */
  233.         if (instr_is_output(instr))
  234.                 regmask_or(liveregs, liveregs, &written);
  235. }
  236.  
  237. static int find_available(regmask_t *liveregs, int size, bool half)
  238. {
  239.         unsigned i;
  240.         unsigned f = half ? IR3_REG_HALF : 0;
  241.         for (i = 0; i < MAX_REG - size; i++) {
  242.                 if (!regmask_get(liveregs, &REG(i, X, f))) {
  243.                         unsigned start = i++;
  244.                         for (; (i < MAX_REG) && ((i - start) < size); i++)
  245.                                 if (regmask_get(liveregs, &REG(i, X, f)))
  246.                                         break;
  247.                         if ((i - start) >= size)
  248.                                 return start;
  249.                 }
  250.         }
  251.         assert(0);
  252.         return -1;
  253. }
  254.  
  255. static int alloc_block(struct ir3_ra_ctx *ctx,
  256.                 struct ir3_instruction *instr, int size)
  257. {
  258.         struct ir3_register *dst = instr->regs[0];
  259.         struct ir3_instruction *n;
  260.         regmask_t liveregs;
  261.         unsigned name;
  262.  
  263.         /* should only ever be called w/ head of neighbor list: */
  264.         debug_assert(!instr->cp.left);
  265.  
  266.         regmask_init(&liveregs);
  267.  
  268.         for (n = instr; n; n = n->cp.right)
  269.                 compute_liveregs(ctx, n, &liveregs);
  270.  
  271.         /* because we do assignment on fanout nodes for wrmask!=0x1, we
  272.          * need to handle this special case, where the fanout nodes all
  273.          * appear after one or more of the consumers of the src node:
  274.          *
  275.          *   0098:009: sam _, r2.x
  276.          *   0028:010: mul.f r3.z, r4.x, c13.x
  277.          *   ; we start assigning here for '0098:009: sam'.. but
  278.          *   ; would miss the usage at '0028:010: mul.f'
  279.          *   0101:009: _meta:fo _, _[0098:009: sam], off=2
  280.          */
  281.         if (is_meta(instr) && (instr->opc == OPC_META_FO))
  282.                 compute_liveregs(ctx, instr->regs[1]->instr, &liveregs);
  283.  
  284.         name = find_available(&liveregs, size,
  285.                         !!(dst->flags & IR3_REG_HALF));
  286.  
  287.         if (dst->flags & IR3_REG_HALF)
  288.                 name |= REG_HALF;
  289.  
  290.         return name;
  291. }
  292.  
  293. static type_t half_type(type_t type)
  294. {
  295.         switch (type) {
  296.         case TYPE_F32: return TYPE_F16;
  297.         case TYPE_U32: return TYPE_U16;
  298.         case TYPE_S32: return TYPE_S16;
  299.         /* instructions may already be fixed up: */
  300.         case TYPE_F16:
  301.         case TYPE_U16:
  302.         case TYPE_S16:
  303.                 return type;
  304.         default:
  305.                 assert(0);
  306.                 return ~0;
  307.         }
  308. }
  309.  
  310. /* some instructions need fix-up if dst register is half precision: */
  311. static void fixup_half_instr_dst(struct ir3_instruction *instr)
  312. {
  313.         switch (instr->category) {
  314.         case 1: /* move instructions */
  315.                 instr->cat1.dst_type = half_type(instr->cat1.dst_type);
  316.                 break;
  317.         case 3:
  318.                 switch (instr->opc) {
  319.                 case OPC_MAD_F32:
  320.                         instr->opc = OPC_MAD_F16;
  321.                         break;
  322.                 case OPC_SEL_B32:
  323.                         instr->opc = OPC_SEL_B16;
  324.                         break;
  325.                 case OPC_SEL_S32:
  326.                         instr->opc = OPC_SEL_S16;
  327.                         break;
  328.                 case OPC_SEL_F32:
  329.                         instr->opc = OPC_SEL_F16;
  330.                         break;
  331.                 case OPC_SAD_S32:
  332.                         instr->opc = OPC_SAD_S16;
  333.                         break;
  334.                 /* instructions may already be fixed up: */
  335.                 case OPC_MAD_F16:
  336.                 case OPC_SEL_B16:
  337.                 case OPC_SEL_S16:
  338.                 case OPC_SEL_F16:
  339.                 case OPC_SAD_S16:
  340.                         break;
  341.                 default:
  342.                         assert(0);
  343.                         break;
  344.                 }
  345.                 break;
  346.         case 5:
  347.                 instr->cat5.type = half_type(instr->cat5.type);
  348.                 break;
  349.         }
  350. }
  351. /* some instructions need fix-up if src register is half precision: */
  352. static void fixup_half_instr_src(struct ir3_instruction *instr)
  353. {
  354.         switch (instr->category) {
  355.         case 1: /* move instructions */
  356.                 instr->cat1.src_type = half_type(instr->cat1.src_type);
  357.                 break;
  358.         }
  359. }
  360.  
  361. static void reg_assign(struct ir3_instruction *instr,
  362.                 unsigned r, unsigned name)
  363. {
  364.         struct ir3_register *reg = instr->regs[r];
  365.  
  366.         reg->flags &= ~IR3_REG_SSA;
  367.         reg->num = name & ~REG_HALF;
  368.  
  369.         if (name & REG_HALF) {
  370.                 reg->flags |= IR3_REG_HALF;
  371.                 /* if dst reg being assigned, patch up the instr: */
  372.                 if (reg == instr->regs[0])
  373.                         fixup_half_instr_dst(instr);
  374.                 else
  375.                         fixup_half_instr_src(instr);
  376.         }
  377. }
  378.  
  379. static void instr_assign(struct ir3_ra_ctx *ctx,
  380.                 struct ir3_instruction *instr, unsigned name);
  381.  
  382. static void instr_assign_src(struct ir3_ra_ctx *ctx,
  383.                 struct ir3_instruction *instr, unsigned r, unsigned name)
  384. {
  385.         struct ir3_register *reg = instr->regs[r];
  386.  
  387.         if (reg->flags & IR3_REG_RELATIV)
  388.                 name += reg->offset;
  389.  
  390.         reg_assign(instr, r, name);
  391.  
  392.         if (is_meta(instr)) {
  393.                 switch (instr->opc) {
  394.                 case OPC_META_INPUT:
  395.                         /* shader-input does not have a src, only block input: */
  396.                         debug_assert(instr->regs_count == 2);
  397.                         instr_assign(ctx, instr, name);
  398.                         return;
  399.                 case OPC_META_FO:
  400.                         instr_assign(ctx, instr, name + instr->fo.off);
  401.                         return;
  402.                 case OPC_META_FI:
  403.                         instr_assign(ctx, instr, name - (r - 1));
  404.                         return;
  405.                 default:
  406.                         break;
  407.                 }
  408.         }
  409. }
  410.  
  411. static void instr_assign_srcs(struct ir3_ra_ctx *ctx,
  412.                 struct ir3_instruction *instr, unsigned name)
  413. {
  414.         struct ir3_instruction *n, *src;
  415.  
  416.         for (n = instr->next; n && !ctx->error; n = n->next) {
  417.                 foreach_ssa_src_n(src, i, n) {
  418.                         unsigned r = i + 1;
  419.  
  420.                         /* skip address / etc (non real sources): */
  421.                         if (r >= n->regs_count)
  422.                                 continue;
  423.  
  424.                         if (src == instr)
  425.                                 instr_assign_src(ctx, n, r, name);
  426.                 }
  427.         }
  428. }
  429.  
  430. static void instr_assign(struct ir3_ra_ctx *ctx,
  431.                 struct ir3_instruction *instr, unsigned name)
  432. {
  433.         struct ir3_register *reg = instr->regs[0];
  434.  
  435.         if (reg->flags & IR3_REG_RELATIV)
  436.                 return;
  437.  
  438.         /* check if already assigned: */
  439.         if (!(reg->flags & IR3_REG_SSA)) {
  440.                 /* ... and if so, sanity check: */
  441.                 ra_assert(ctx, reg->num == (name & ~REG_HALF));
  442.                 return;
  443.         }
  444.  
  445.         /* rename this instructions dst register: */
  446.         reg_assign(instr, 0, name);
  447.  
  448.         /* and rename any subsequent use of result of this instr: */
  449.         instr_assign_srcs(ctx, instr, name);
  450.  
  451.         /* To simplify the neighbor logic, and to "avoid" dealing with
  452.          * instructions which write more than one output, we actually
  453.          * do register assignment for instructions that produce multiple
  454.          * outputs on the fanout nodes and propagate up the assignment
  455.          * to the actual instruction:
  456.          */
  457.         if (is_meta(instr) && (instr->opc == OPC_META_FO)) {
  458.                 struct ir3_instruction *src;
  459.  
  460.                 debug_assert(name >= instr->fo.off);
  461.  
  462.                 foreach_ssa_src(src, instr)
  463.                         instr_assign(ctx, src, name - instr->fo.off);
  464.         }
  465. }
  466.  
  467. /* check neighbor list to see if it is already partially (or completely)
  468.  * assigned, in which case register block is already allocated and we
  469.  * just need to complete the assignment:
  470.  */
  471. static int check_partial_assignment(struct ir3_ra_ctx *ctx,
  472.                 struct ir3_instruction *instr)
  473. {
  474.         struct ir3_instruction *n;
  475.         int off = 0;
  476.  
  477.         debug_assert(!instr->cp.left);
  478.  
  479.         for (n = instr; n; n = n->cp.right) {
  480.                 struct ir3_register *dst = n->regs[0];
  481.                 if ((n->depth != DEPTH_UNUSED) &&
  482.                                 !(dst->flags & IR3_REG_SSA)) {
  483.                         int name = dst->num - off;
  484.                         debug_assert(name >= 0);
  485.                         return name;
  486.                 }
  487.                 off++;
  488.         }
  489.  
  490.         return -1;
  491. }
  492.  
  493. /* allocate register name(s) for a list of neighboring instructions;
  494.  * instr should point to leftmost neighbor (head of list)
  495.  */
  496. static void instr_alloc_and_assign(struct ir3_ra_ctx *ctx,
  497.                 struct ir3_instruction *instr)
  498. {
  499.         struct ir3_instruction *n;
  500.         struct ir3_register *dst;
  501.         int name;
  502.  
  503.         debug_assert(!instr->cp.left);
  504.  
  505.         if (instr->regs_count == 0)
  506.                 return;
  507.  
  508.         dst = instr->regs[0];
  509.  
  510.         /* For indirect dst, take the register assignment from the
  511.          * fanin and propagate it forward.
  512.          */
  513.         if (dst->flags & IR3_REG_RELATIV) {
  514.                 /* NOTE can be grouped, if for example outputs:
  515.                  * for now disable cp if indirect writes
  516.                  */
  517.                 instr_alloc_and_assign(ctx, instr->fanin);
  518.  
  519.                 dst->num += instr->fanin->regs[0]->num;
  520.                 dst->flags &= ~IR3_REG_SSA;
  521.  
  522.                 instr_assign_srcs(ctx, instr, instr->fanin->regs[0]->num);
  523.  
  524.                 return;
  525.         }
  526.  
  527.         /* for instructions w/ fanouts, do the actual register assignment
  528.          * on the group of fanout neighbor nodes and propagate the reg
  529.          * name back up to the texture instruction.
  530.          */
  531.         if (dst->wrmask != 0x1)
  532.                 return;
  533.  
  534.         name = check_partial_assignment(ctx, instr);
  535.  
  536.         /* allocate register(s): */
  537.         if (name >= 0) {
  538.                 /* already partially assigned, just finish the job */
  539.         } else if (reg_gpr(dst)) {
  540.                 int size;
  541.                 /* number of consecutive registers to assign: */
  542.                 size = ir3_neighbor_count(instr);
  543.                 if (dst->wrmask != 0x1)
  544.                         size = MAX2(size, ffs(~dst->wrmask) - 1);
  545.                 name = alloc_block(ctx, instr, size);
  546.         } else if (dst->flags & IR3_REG_ADDR) {
  547.                 debug_assert(!instr->cp.right);
  548.                 dst->flags &= ~IR3_REG_ADDR;
  549.                 name = regid(REG_A0, 0) | REG_HALF;
  550.         } else {
  551.                 debug_assert(!instr->cp.right);
  552.                 /* predicate register (p0).. etc */
  553.                 name = regid(REG_P0, 0);
  554.                 debug_assert(dst->num == name);
  555.         }
  556.  
  557.         ra_assert(ctx, name >= 0);
  558.  
  559.         for (n = instr; n && !ctx->error; n = n->cp.right) {
  560.                 instr_assign(ctx, n, name);
  561.                 name++;
  562.         }
  563. }
  564.  
  565. static void instr_assign_array(struct ir3_ra_ctx *ctx,
  566.                 struct ir3_instruction *instr)
  567. {
  568.         struct ir3_instruction *src;
  569.         int name, aid = instr->fi.aid;
  570.  
  571.         if (ctx->arrays[aid].base == ~0) {
  572.                 int size = instr->regs_count - 1;
  573.                 ctx->arrays[aid].base = alloc_block(ctx, instr, size);
  574.                 ctx->arrays[aid].size = size;
  575.         }
  576.  
  577.         name = ctx->arrays[aid].base;
  578.  
  579.         foreach_ssa_src_n(src, i, instr) {
  580.                 unsigned r = i + 1;
  581.  
  582.                 /* skip address / etc (non real sources): */
  583.                 if (r >= instr->regs_count)
  584.                         break;
  585.  
  586.                 instr_assign(ctx, src, name);
  587.                 name++;
  588.         }
  589.  
  590. }
  591.  
  592. static int block_ra(struct ir3_ra_ctx *ctx, struct ir3_block *block)
  593. {
  594.         struct ir3_instruction *n;
  595.  
  596.         /* frag shader inputs get pre-assigned, since we have some
  597.          * constraints/unknowns about setup for some of these regs:
  598.          */
  599.         if ((ctx->type == SHADER_FRAGMENT) && !block->parent) {
  600.                 unsigned i = 0, j;
  601.                 if (ctx->frag_face && (i < block->ninputs) && block->inputs[i]) {
  602.                         /* if we have frag_face, it gets hr0.x */
  603.                         instr_assign(ctx, block->inputs[i], REG_HALF | 0);
  604.                         i += 4;
  605.                 }
  606.                 for (j = 0; i < block->ninputs; i++, j++)
  607.                         if (block->inputs[i])
  608.                                 instr_assign(ctx, block->inputs[i], j);
  609.         }
  610.  
  611.         ra_dump_list("-------\n", block->head);
  612.  
  613.         /* first pass, assign arrays: */
  614.         for (n = block->head; n && !ctx->error; n = n->next) {
  615.                 if (is_meta(n) && (n->opc == OPC_META_FI) && n->fi.aid) {
  616.                         debug_assert(!n->cp.left);  /* don't think this should happen */
  617.                         ra_dump_instr("ASSIGN ARRAY: ", n);
  618.                         instr_assign_array(ctx, n);
  619.                         ra_dump_list("-------\n", block->head);
  620.                 }
  621.         }
  622.  
  623.         for (n = block->head; n && !ctx->error; n = n->next) {
  624.                 ra_dump_instr("ASSIGN: ", n);
  625.                 instr_alloc_and_assign(ctx, ir3_neighbor_first(n));
  626.                 ra_dump_list("-------\n", block->head);
  627.         }
  628.  
  629.         return ctx->error ? -1 : 0;
  630. }
  631.  
  632. int ir3_block_ra(struct ir3_block *block, enum shader_t type,
  633.                 bool frag_coord, bool frag_face)
  634. {
  635.         struct ir3_instruction *n;
  636.         struct ir3_ra_ctx ctx = {
  637.                         .block = block,
  638.                         .type = type,
  639.                         .frag_coord = frag_coord,
  640.                         .frag_face = frag_face,
  641.         };
  642.         int ret;
  643.  
  644.         memset(&ctx.arrays, ~0, sizeof(ctx.arrays));
  645.  
  646.         /* mark dst registers w/ SSA flag so we can see which
  647.          * have been assigned so far:
  648.          * NOTE: we really should set SSA flag consistently on
  649.          * every dst register in the frontend.
  650.          */
  651.         for (n = block->head; n; n = n->next)
  652.                 if (n->regs_count > 0)
  653.                         n->regs[0]->flags |= IR3_REG_SSA;
  654.  
  655.         ir3_clear_mark(block->shader);
  656.         ret = block_ra(&ctx, block);
  657.  
  658.         return ret;
  659. }
  660.