Home | History | Annotate | Line # | Download | only in compiler
      1 /*
      2  * Copyright  2018 Valve Corporation
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     21  * IN THE SOFTWARE.
     22  *
     23  */
     24 
     25 #include "aco_builder.h"
     26 #include "aco_ir.h"
     27 
     28 #include "util/half_float.h"
     29 #include "util/memstream.h"
     30 
     31 #include <algorithm>
     32 #include <array>
     33 #include <vector>
     34 
     35 namespace aco {
     36 
     37 #ifndef NDEBUG
     38 void
     39 perfwarn(Program* program, bool cond, const char* msg, Instruction* instr)
     40 {
     41    if (cond) {
     42       char* out;
     43       size_t outsize;
     44       struct u_memstream mem;
     45       u_memstream_open(&mem, &out, &outsize);
     46       FILE* const memf = u_memstream_get(&mem);
     47 
     48       fprintf(memf, "%s: ", msg);
     49       aco_print_instr(instr, memf);
     50       u_memstream_close(&mem);
     51 
     52       aco_perfwarn(program, out);
     53       free(out);
     54 
     55       if (debug_flags & DEBUG_PERFWARN)
     56          exit(1);
     57    }
     58 }
     59 #endif
     60 
     61 /**
     62  * The optimizer works in 4 phases:
     63  * (1) The first pass collects information for each ssa-def,
     64  *     propagates reg->reg operands of the same type, inline constants
     65  *     and neg/abs input modifiers.
     66  * (2) The second pass combines instructions like mad, omod, clamp and
     67  *     propagates sgpr's on VALU instructions.
     68  *     This pass depends on information collected in the first pass.
     69  * (3) The third pass goes backwards, and selects instructions,
     70  *     i.e. decides if a mad instruction is profitable and eliminates dead code.
     71  * (4) The fourth pass cleans up the sequence: literals get applied and dead
     72  *     instructions are removed from the sequence.
     73  */
     74 
     75 struct mad_info {
     76    aco_ptr<Instruction> add_instr;
     77    uint32_t mul_temp_id;
     78    uint16_t literal_idx;
     79    bool check_literal;
     80 
     81    mad_info(aco_ptr<Instruction> instr, uint32_t id)
     82        : add_instr(std::move(instr)), mul_temp_id(id), literal_idx(0), check_literal(false)
     83    {}
     84 };
     85 
     86 enum Label {
     87    label_vec = 1 << 0,
     88    label_constant_32bit = 1 << 1,
     89    /* label_{abs,neg,mul,omod2,omod4,omod5,clamp} are used for both 16 and
     90     * 32-bit operations but this shouldn't cause any issues because we don't
     91     * look through any conversions */
     92    label_abs = 1 << 2,
     93    label_neg = 1 << 3,
     94    label_mul = 1 << 4,
     95    label_temp = 1 << 5,
     96    label_literal = 1 << 6,
     97    label_mad = 1 << 7,
     98    label_omod2 = 1 << 8,
     99    label_omod4 = 1 << 9,
    100    label_omod5 = 1 << 10,
    101    label_clamp = 1 << 12,
    102    label_undefined = 1 << 14,
    103    label_vcc = 1 << 15,
    104    label_b2f = 1 << 16,
    105    label_add_sub = 1 << 17,
    106    label_bitwise = 1 << 18,
    107    label_minmax = 1 << 19,
    108    label_vopc = 1 << 20,
    109    label_uniform_bool = 1 << 21,
    110    label_constant_64bit = 1 << 22,
    111    label_uniform_bitwise = 1 << 23,
    112    label_scc_invert = 1 << 24,
    113    label_vcc_hint = 1 << 25,
    114    label_scc_needed = 1 << 26,
    115    label_b2i = 1 << 27,
    116    label_fcanonicalize = 1 << 28,
    117    label_constant_16bit = 1 << 29,
    118    label_usedef = 1 << 30,   /* generic label */
    119    label_vop3p = 1ull << 31, /* 1ull to prevent sign extension */
    120    label_canonicalized = 1ull << 32,
    121    label_extract = 1ull << 33,
    122    label_insert = 1ull << 34,
    123    label_dpp = 1ull << 35,
    124 };
    125 
    126 static constexpr uint64_t instr_usedef_labels =
    127    label_vec | label_mul | label_mad | label_add_sub | label_vop3p | label_bitwise |
    128    label_uniform_bitwise | label_minmax | label_vopc | label_usedef | label_extract | label_dpp;
    129 static constexpr uint64_t instr_mod_labels =
    130    label_omod2 | label_omod4 | label_omod5 | label_clamp | label_insert;
    131 
    132 static constexpr uint64_t instr_labels = instr_usedef_labels | instr_mod_labels;
    133 static constexpr uint64_t temp_labels = label_abs | label_neg | label_temp | label_vcc | label_b2f |
    134                                         label_uniform_bool | label_scc_invert | label_b2i |
    135                                         label_fcanonicalize;
    136 static constexpr uint32_t val_labels =
    137    label_constant_32bit | label_constant_64bit | label_constant_16bit | label_literal;
    138 
    139 static_assert((instr_labels & temp_labels) == 0, "labels cannot intersect");
    140 static_assert((instr_labels & val_labels) == 0, "labels cannot intersect");
    141 static_assert((temp_labels & val_labels) == 0, "labels cannot intersect");
    142 
    143 struct ssa_info {
    144    uint64_t label;
    145    union {
    146       uint32_t val;
    147       Temp temp;
    148       Instruction* instr;
    149    };
    150 
    151    ssa_info() : label(0) {}
    152 
    153    void add_label(Label new_label)
    154    {
    155       /* Since all the instr_usedef_labels use instr for the same thing
    156        * (indicating the defining instruction), there is usually no need to
    157        * clear any other instr labels. */
    158       if (new_label & instr_usedef_labels)
    159          label &= ~(instr_mod_labels | temp_labels | val_labels); /* instr, temp and val alias */
    160 
    161       if (new_label & instr_mod_labels) {
    162          label &= ~instr_labels;
    163          label &= ~(temp_labels | val_labels); /* instr, temp and val alias */
    164       }
    165 
    166       if (new_label & temp_labels) {
    167          label &= ~temp_labels;
    168          label &= ~(instr_labels | val_labels); /* instr, temp and val alias */
    169       }
    170 
    171       uint32_t const_labels =
    172          label_literal | label_constant_32bit | label_constant_64bit | label_constant_16bit;
    173       if (new_label & const_labels) {
    174          label &= ~val_labels | const_labels;
    175          label &= ~(instr_labels | temp_labels); /* instr, temp and val alias */
    176       } else if (new_label & val_labels) {
    177          label &= ~val_labels;
    178          label &= ~(instr_labels | temp_labels); /* instr, temp and val alias */
    179       }
    180 
    181       label |= new_label;
    182    }
    183 
    184    void set_vec(Instruction* vec)
    185    {
    186       add_label(label_vec);
    187       instr = vec;
    188    }
    189 
    190    bool is_vec() { return label & label_vec; }
    191 
    192    void set_constant(chip_class chip, uint64_t constant)
    193    {
    194       Operand op16 = Operand::c16(constant);
    195       Operand op32 = Operand::get_const(chip, constant, 4);
    196       add_label(label_literal);
    197       val = constant;
    198 
    199       /* check that no upper bits are lost in case of packed 16bit constants */
    200       if (chip >= GFX8 && !op16.isLiteral() && op16.constantValue64() == constant)
    201          add_label(label_constant_16bit);
    202 
    203       if (!op32.isLiteral())
    204          add_label(label_constant_32bit);
    205 
    206       if (Operand::is_constant_representable(constant, 8))
    207          add_label(label_constant_64bit);
    208 
    209       if (label & label_constant_64bit) {
    210          val = Operand::c64(constant).constantValue();
    211          if (val != constant)
    212             label &= ~(label_literal | label_constant_16bit | label_constant_32bit);
    213       }
    214    }
    215 
    216    bool is_constant(unsigned bits)
    217    {
    218       switch (bits) {
    219       case 8: return label & label_literal;
    220       case 16: return label & label_constant_16bit;
    221       case 32: return label & label_constant_32bit;
    222       case 64: return label & label_constant_64bit;
    223       }
    224       return false;
    225    }
    226 
    227    bool is_literal(unsigned bits)
    228    {
    229       bool is_lit = label & label_literal;
    230       switch (bits) {
    231       case 8: return false;
    232       case 16: return is_lit && ~(label & label_constant_16bit);
    233       case 32: return is_lit && ~(label & label_constant_32bit);
    234       case 64: return false;
    235       }
    236       return false;
    237    }
    238 
    239    bool is_constant_or_literal(unsigned bits)
    240    {
    241       if (bits == 64)
    242          return label & label_constant_64bit;
    243       else
    244          return label & label_literal;
    245    }
    246 
    247    void set_abs(Temp abs_temp)
    248    {
    249       add_label(label_abs);
    250       temp = abs_temp;
    251    }
    252 
    253    bool is_abs() { return label & label_abs; }
    254 
    255    void set_neg(Temp neg_temp)
    256    {
    257       add_label(label_neg);
    258       temp = neg_temp;
    259    }
    260 
    261    bool is_neg() { return label & label_neg; }
    262 
    263    void set_neg_abs(Temp neg_abs_temp)
    264    {
    265       add_label((Label)((uint32_t)label_abs | (uint32_t)label_neg));
    266       temp = neg_abs_temp;
    267    }
    268 
    269    void set_mul(Instruction* mul)
    270    {
    271       add_label(label_mul);
    272       instr = mul;
    273    }
    274 
    275    bool is_mul() { return label & label_mul; }
    276 
    277    void set_temp(Temp tmp)
    278    {
    279       add_label(label_temp);
    280       temp = tmp;
    281    }
    282 
    283    bool is_temp() { return label & label_temp; }
    284 
    285    void set_mad(Instruction* mad, uint32_t mad_info_idx)
    286    {
    287       add_label(label_mad);
    288       mad->pass_flags = mad_info_idx;
    289       instr = mad;
    290    }
    291 
    292    bool is_mad() { return label & label_mad; }
    293 
    294    void set_omod2(Instruction* mul)
    295    {
    296       add_label(label_omod2);
    297       instr = mul;
    298    }
    299 
    300    bool is_omod2() { return label & label_omod2; }
    301 
    302    void set_omod4(Instruction* mul)
    303    {
    304       add_label(label_omod4);
    305       instr = mul;
    306    }
    307 
    308    bool is_omod4() { return label & label_omod4; }
    309 
    310    void set_omod5(Instruction* mul)
    311    {
    312       add_label(label_omod5);
    313       instr = mul;
    314    }
    315 
    316    bool is_omod5() { return label & label_omod5; }
    317 
    318    void set_clamp(Instruction* med3)
    319    {
    320       add_label(label_clamp);
    321       instr = med3;
    322    }
    323 
    324    bool is_clamp() { return label & label_clamp; }
    325 
    326    void set_undefined() { add_label(label_undefined); }
    327 
    328    bool is_undefined() { return label & label_undefined; }
    329 
    330    void set_vcc(Temp vcc_val)
    331    {
    332       add_label(label_vcc);
    333       temp = vcc_val;
    334    }
    335 
    336    bool is_vcc() { return label & label_vcc; }
    337 
    338    void set_b2f(Temp b2f_val)
    339    {
    340       add_label(label_b2f);
    341       temp = b2f_val;
    342    }
    343 
    344    bool is_b2f() { return label & label_b2f; }
    345 
    346    void set_add_sub(Instruction* add_sub_instr)
    347    {
    348       add_label(label_add_sub);
    349       instr = add_sub_instr;
    350    }
    351 
    352    bool is_add_sub() { return label & label_add_sub; }
    353 
    354    void set_bitwise(Instruction* bitwise_instr)
    355    {
    356       add_label(label_bitwise);
    357       instr = bitwise_instr;
    358    }
    359 
    360    bool is_bitwise() { return label & label_bitwise; }
    361 
    362    void set_uniform_bitwise() { add_label(label_uniform_bitwise); }
    363 
    364    bool is_uniform_bitwise() { return label & label_uniform_bitwise; }
    365 
    366    void set_minmax(Instruction* minmax_instr)
    367    {
    368       add_label(label_minmax);
    369       instr = minmax_instr;
    370    }
    371 
    372    bool is_minmax() { return label & label_minmax; }
    373 
    374    void set_vopc(Instruction* vopc_instr)
    375    {
    376       add_label(label_vopc);
    377       instr = vopc_instr;
    378    }
    379 
    380    bool is_vopc() { return label & label_vopc; }
    381 
    382    void set_scc_needed() { add_label(label_scc_needed); }
    383 
    384    bool is_scc_needed() { return label & label_scc_needed; }
    385 
    386    void set_scc_invert(Temp scc_inv)
    387    {
    388       add_label(label_scc_invert);
    389       temp = scc_inv;
    390    }
    391 
    392    bool is_scc_invert() { return label & label_scc_invert; }
    393 
    394    void set_uniform_bool(Temp uniform_bool)
    395    {
    396       add_label(label_uniform_bool);
    397       temp = uniform_bool;
    398    }
    399 
    400    bool is_uniform_bool() { return label & label_uniform_bool; }
    401 
    402    void set_vcc_hint() { add_label(label_vcc_hint); }
    403 
    404    bool is_vcc_hint() { return label & label_vcc_hint; }
    405 
    406    void set_b2i(Temp b2i_val)
    407    {
    408       add_label(label_b2i);
    409       temp = b2i_val;
    410    }
    411 
    412    bool is_b2i() { return label & label_b2i; }
    413 
    414    void set_usedef(Instruction* label_instr)
    415    {
    416       add_label(label_usedef);
    417       instr = label_instr;
    418    }
    419 
    420    bool is_usedef() { return label & label_usedef; }
    421 
    422    void set_vop3p(Instruction* vop3p_instr)
    423    {
    424       add_label(label_vop3p);
    425       instr = vop3p_instr;
    426    }
    427 
    428    bool is_vop3p() { return label & label_vop3p; }
    429 
    430    void set_fcanonicalize(Temp tmp)
    431    {
    432       add_label(label_fcanonicalize);
    433       temp = tmp;
    434    }
    435 
    436    bool is_fcanonicalize() { return label & label_fcanonicalize; }
    437 
    438    void set_canonicalized() { add_label(label_canonicalized); }
    439 
    440    bool is_canonicalized() { return label & label_canonicalized; }
    441 
    442    void set_extract(Instruction* extract)
    443    {
    444       add_label(label_extract);
    445       instr = extract;
    446    }
    447 
    448    bool is_extract() { return label & label_extract; }
    449 
    450    void set_insert(Instruction* insert)
    451    {
    452       add_label(label_insert);
    453       instr = insert;
    454    }
    455 
    456    bool is_insert() { return label & label_insert; }
    457 
    458    void set_dpp(Instruction* mov)
    459    {
    460       add_label(label_dpp);
    461       instr = mov;
    462    }
    463 
    464    bool is_dpp() { return label & label_dpp; }
    465 };
    466 
    467 struct opt_ctx {
    468    Program* program;
    469    float_mode fp_mode;
    470    std::vector<aco_ptr<Instruction>> instructions;
    471    ssa_info* info;
    472    std::pair<uint32_t, Temp> last_literal;
    473    std::vector<mad_info> mad_infos;
    474    std::vector<uint16_t> uses;
    475 };
    476 
    477 bool
    478 can_use_VOP3(opt_ctx& ctx, const aco_ptr<Instruction>& instr)
    479 {
    480    if (instr->isVOP3())
    481       return true;
    482 
    483    if (instr->isVOP3P())
    484       return false;
    485 
    486    if (instr->operands.size() && instr->operands[0].isLiteral() && ctx.program->chip_class < GFX10)
    487       return false;
    488 
    489    if (instr->isDPP() || instr->isSDWA())
    490       return false;
    491 
    492    return instr->opcode != aco_opcode::v_madmk_f32 && instr->opcode != aco_opcode::v_madak_f32 &&
    493           instr->opcode != aco_opcode::v_madmk_f16 && instr->opcode != aco_opcode::v_madak_f16 &&
    494           instr->opcode != aco_opcode::v_fmamk_f32 && instr->opcode != aco_opcode::v_fmaak_f32 &&
    495           instr->opcode != aco_opcode::v_fmamk_f16 && instr->opcode != aco_opcode::v_fmaak_f16 &&
    496           instr->opcode != aco_opcode::v_readlane_b32 &&
    497           instr->opcode != aco_opcode::v_writelane_b32 &&
    498           instr->opcode != aco_opcode::v_readfirstlane_b32;
    499 }
    500 
    501 bool
    502 pseudo_propagate_temp(opt_ctx& ctx, aco_ptr<Instruction>& instr, Temp temp, unsigned index)
    503 {
    504    if (instr->definitions.empty())
    505       return false;
    506 
    507    const bool vgpr =
    508       instr->opcode == aco_opcode::p_as_uniform ||
    509       std::all_of(instr->definitions.begin(), instr->definitions.end(),
    510                   [](const Definition& def) { return def.regClass().type() == RegType::vgpr; });
    511 
    512    /* don't propagate VGPRs into SGPR instructions */
    513    if (temp.type() == RegType::vgpr && !vgpr)
    514       return false;
    515 
    516    bool can_accept_sgpr =
    517       ctx.program->chip_class >= GFX9 ||
    518       std::none_of(instr->definitions.begin(), instr->definitions.end(),
    519                    [](const Definition& def) { return def.regClass().is_subdword(); });
    520 
    521    switch (instr->opcode) {
    522    case aco_opcode::p_phi:
    523    case aco_opcode::p_linear_phi:
    524    case aco_opcode::p_parallelcopy:
    525    case aco_opcode::p_create_vector:
    526       if (temp.bytes() != instr->operands[index].bytes())
    527          return false;
    528       break;
    529    case aco_opcode::p_extract_vector:
    530       if (temp.type() == RegType::sgpr && !can_accept_sgpr)
    531          return false;
    532       break;
    533    case aco_opcode::p_split_vector: {
    534       if (temp.type() == RegType::sgpr && !can_accept_sgpr)
    535          return false;
    536       /* don't increase the vector size */
    537       if (temp.bytes() > instr->operands[index].bytes())
    538          return false;
    539       /* We can decrease the vector size as smaller temporaries are only
    540        * propagated by p_as_uniform instructions.
    541        * If this propagation leads to invalid IR or hits the assertion below,
    542        * it means that some undefined bytes within a dword are begin accessed
    543        * and a bug in instruction_selection is likely. */
    544       int decrease = instr->operands[index].bytes() - temp.bytes();
    545       while (decrease > 0) {
    546          decrease -= instr->definitions.back().bytes();
    547          instr->definitions.pop_back();
    548       }
    549       assert(decrease == 0);
    550       break;
    551    }
    552    case aco_opcode::p_as_uniform:
    553       if (temp.regClass() == instr->definitions[0].regClass())
    554          instr->opcode = aco_opcode::p_parallelcopy;
    555       break;
    556    default: return false;
    557    }
    558 
    559    instr->operands[index].setTemp(temp);
    560    return true;
    561 }
    562 
    563 /* This expects the DPP modifier to be removed. */
    564 bool
    565 can_apply_sgprs(opt_ctx& ctx, aco_ptr<Instruction>& instr)
    566 {
    567    if (instr->isSDWA() && ctx.program->chip_class < GFX9)
    568       return false;
    569    return instr->opcode != aco_opcode::v_readfirstlane_b32 &&
    570           instr->opcode != aco_opcode::v_readlane_b32 &&
    571           instr->opcode != aco_opcode::v_readlane_b32_e64 &&
    572           instr->opcode != aco_opcode::v_writelane_b32 &&
    573           instr->opcode != aco_opcode::v_writelane_b32_e64 &&
    574           instr->opcode != aco_opcode::v_permlane16_b32 &&
    575           instr->opcode != aco_opcode::v_permlanex16_b32;
    576 }
    577 
    578 void
    579 to_VOP3(opt_ctx& ctx, aco_ptr<Instruction>& instr)
    580 {
    581    if (instr->isVOP3())
    582       return;
    583 
    584    aco_ptr<Instruction> tmp = std::move(instr);
    585    Format format = asVOP3(tmp->format);
    586    instr.reset(create_instruction<VOP3_instruction>(tmp->opcode, format, tmp->operands.size(),
    587                                                     tmp->definitions.size()));
    588    std::copy(tmp->operands.cbegin(), tmp->operands.cend(), instr->operands.begin());
    589    for (unsigned i = 0; i < instr->definitions.size(); i++) {
    590       instr->definitions[i] = tmp->definitions[i];
    591       if (instr->definitions[i].isTemp()) {
    592          ssa_info& info = ctx.info[instr->definitions[i].tempId()];
    593          if (info.label & instr_usedef_labels && info.instr == tmp.get())
    594             info.instr = instr.get();
    595       }
    596    }
    597    /* we don't need to update any instr_mod_labels because they either haven't
    598     * been applied yet or this instruction isn't dead and so they've been ignored */
    599 }
    600 
    601 bool
    602 is_operand_vgpr(Operand op)
    603 {
    604    return op.isTemp() && op.getTemp().type() == RegType::vgpr;
    605 }
    606 
    607 void
    608 to_SDWA(opt_ctx& ctx, aco_ptr<Instruction>& instr)
    609 {
    610    aco_ptr<Instruction> tmp = convert_to_SDWA(ctx.program->chip_class, instr);
    611    if (!tmp)
    612       return;
    613 
    614    for (unsigned i = 0; i < instr->definitions.size(); i++) {
    615       ssa_info& info = ctx.info[instr->definitions[i].tempId()];
    616       if (info.label & instr_labels && info.instr == tmp.get())
    617          info.instr = instr.get();
    618    }
    619 }
    620 
    621 /* only covers special cases */
    622 bool
    623 alu_can_accept_constant(aco_opcode opcode, unsigned operand)
    624 {
    625    switch (opcode) {
    626    case aco_opcode::v_interp_p2_f32:
    627    case aco_opcode::v_mac_f32:
    628    case aco_opcode::v_writelane_b32:
    629    case aco_opcode::v_writelane_b32_e64:
    630    case aco_opcode::v_cndmask_b32: return operand != 2;
    631    case aco_opcode::s_addk_i32:
    632    case aco_opcode::s_mulk_i32:
    633    case aco_opcode::p_wqm:
    634    case aco_opcode::p_extract_vector:
    635    case aco_opcode::p_split_vector:
    636    case aco_opcode::v_readlane_b32:
    637    case aco_opcode::v_readlane_b32_e64:
    638    case aco_opcode::v_readfirstlane_b32:
    639    case aco_opcode::p_extract:
    640    case aco_opcode::p_insert: return operand != 0;
    641    default: return true;
    642    }
    643 }
    644 
    645 bool
    646 valu_can_accept_vgpr(aco_ptr<Instruction>& instr, unsigned operand)
    647 {
    648    if (instr->opcode == aco_opcode::v_readlane_b32 ||
    649        instr->opcode == aco_opcode::v_readlane_b32_e64 ||
    650        instr->opcode == aco_opcode::v_writelane_b32 ||
    651        instr->opcode == aco_opcode::v_writelane_b32_e64)
    652       return operand != 1;
    653    if (instr->opcode == aco_opcode::v_permlane16_b32 ||
    654        instr->opcode == aco_opcode::v_permlanex16_b32)
    655       return operand == 0;
    656    return true;
    657 }
    658 
    659 /* check constant bus and literal limitations */
    660 bool
    661 check_vop3_operands(opt_ctx& ctx, unsigned num_operands, Operand* operands)
    662 {
    663    int limit = ctx.program->chip_class >= GFX10 ? 2 : 1;
    664    Operand literal32(s1);
    665    Operand literal64(s2);
    666    unsigned num_sgprs = 0;
    667    unsigned sgpr[] = {0, 0};
    668 
    669    for (unsigned i = 0; i < num_operands; i++) {
    670       Operand op = operands[i];
    671 
    672       if (op.hasRegClass() && op.regClass().type() == RegType::sgpr) {
    673          /* two reads of the same SGPR count as 1 to the limit */
    674          if (op.tempId() != sgpr[0] && op.tempId() != sgpr[1]) {
    675             if (num_sgprs < 2)
    676                sgpr[num_sgprs++] = op.tempId();
    677             limit--;
    678             if (limit < 0)
    679                return false;
    680          }
    681       } else if (op.isLiteral()) {
    682          if (ctx.program->chip_class < GFX10)
    683             return false;
    684 
    685          if (!literal32.isUndefined() && literal32.constantValue() != op.constantValue())
    686             return false;
    687          if (!literal64.isUndefined() && literal64.constantValue() != op.constantValue())
    688             return false;
    689 
    690          /* Any number of 32-bit literals counts as only 1 to the limit. Same
    691           * (but separately) for 64-bit literals. */
    692          if (op.size() == 1 && literal32.isUndefined()) {
    693             limit--;
    694             literal32 = op;
    695          } else if (op.size() == 2 && literal64.isUndefined()) {
    696             limit--;
    697             literal64 = op;
    698          }
    699 
    700          if (limit < 0)
    701             return false;
    702       }
    703    }
    704 
    705    return true;
    706 }
    707 
    708 bool
    709 parse_base_offset(opt_ctx& ctx, Instruction* instr, unsigned op_index, Temp* base, uint32_t* offset,
    710                   bool prevent_overflow)
    711 {
    712    Operand op = instr->operands[op_index];
    713 
    714    if (!op.isTemp())
    715       return false;
    716    Temp tmp = op.getTemp();
    717    if (!ctx.info[tmp.id()].is_add_sub())
    718       return false;
    719 
    720    Instruction* add_instr = ctx.info[tmp.id()].instr;
    721 
    722    switch (add_instr->opcode) {
    723    case aco_opcode::v_add_u32:
    724    case aco_opcode::v_add_co_u32:
    725    case aco_opcode::v_add_co_u32_e64:
    726    case aco_opcode::s_add_i32:
    727    case aco_opcode::s_add_u32: break;
    728    default: return false;
    729    }
    730    if (prevent_overflow && !add_instr->definitions[0].isNUW())
    731       return false;
    732 
    733    if (add_instr->usesModifiers())
    734       return false;
    735 
    736    for (unsigned i = 0; i < 2; i++) {
    737       if (add_instr->operands[i].isConstant()) {
    738          *offset = add_instr->operands[i].constantValue();
    739       } else if (add_instr->operands[i].isTemp() &&
    740                  ctx.info[add_instr->operands[i].tempId()].is_constant_or_literal(32)) {
    741          *offset = ctx.info[add_instr->operands[i].tempId()].val;
    742       } else {
    743          continue;
    744       }
    745       if (!add_instr->operands[!i].isTemp())
    746          continue;
    747 
    748       uint32_t offset2 = 0;
    749       if (parse_base_offset(ctx, add_instr, !i, base, &offset2, prevent_overflow)) {
    750          *offset += offset2;
    751       } else {
    752          *base = add_instr->operands[!i].getTemp();
    753       }
    754       return true;
    755    }
    756 
    757    return false;
    758 }
    759 
    760 unsigned
    761 get_operand_size(aco_ptr<Instruction>& instr, unsigned index)
    762 {
    763    if (instr->isPseudo())
    764       return instr->operands[index].bytes() * 8u;
    765    else if (instr->opcode == aco_opcode::v_mad_u64_u32 ||
    766             instr->opcode == aco_opcode::v_mad_i64_i32)
    767       return index == 2 ? 64 : 32;
    768    else if (instr->isVALU() || instr->isSALU())
    769       return instr_info.operand_size[(int)instr->opcode];
    770    else
    771       return 0;
    772 }
    773 
    774 Operand
    775 get_constant_op(opt_ctx& ctx, ssa_info info, uint32_t bits)
    776 {
    777    if (bits == 64)
    778       return Operand::c32_or_c64(info.val, true);
    779    return Operand::get_const(ctx.program->chip_class, info.val, bits / 8u);
    780 }
    781 
    782 bool
    783 fixed_to_exec(Operand op)
    784 {
    785    return op.isFixed() && op.physReg() == exec;
    786 }
    787 
    788 SubdwordSel
    789 parse_extract(Instruction* instr)
    790 {
    791    if (instr->opcode == aco_opcode::p_extract) {
    792       unsigned size = instr->operands[2].constantValue() / 8;
    793       unsigned offset = instr->operands[1].constantValue() * size;
    794       bool sext = instr->operands[3].constantEquals(1);
    795       return SubdwordSel(size, offset, sext);
    796    } else if (instr->opcode == aco_opcode::p_insert && instr->operands[1].constantEquals(0)) {
    797       return instr->operands[2].constantEquals(8) ? SubdwordSel::ubyte : SubdwordSel::uword;
    798    } else {
    799       return SubdwordSel();
    800    }
    801 }
    802 
    803 SubdwordSel
    804 parse_insert(Instruction* instr)
    805 {
    806    if (instr->opcode == aco_opcode::p_extract && instr->operands[3].constantEquals(0) &&
    807        instr->operands[1].constantEquals(0)) {
    808       return instr->operands[2].constantEquals(8) ? SubdwordSel::ubyte : SubdwordSel::uword;
    809    } else if (instr->opcode == aco_opcode::p_insert) {
    810       unsigned size = instr->operands[2].constantValue() / 8;
    811       unsigned offset = instr->operands[1].constantValue() * size;
    812       return SubdwordSel(size, offset, false);
    813    } else {
    814       return SubdwordSel();
    815    }
    816 }
    817 
    818 bool
    819 can_apply_extract(opt_ctx& ctx, aco_ptr<Instruction>& instr, unsigned idx, ssa_info& info)
    820 {
    821    if (idx >= 2)
    822       return false;
    823 
    824    Temp tmp = info.instr->operands[0].getTemp();
    825    SubdwordSel sel = parse_extract(info.instr);
    826 
    827    if (!sel) {
    828       return false;
    829    } else if (sel.size() == 4) {
    830       return true;
    831    } else if (instr->opcode == aco_opcode::v_cvt_f32_u32 && sel.size() == 1 && !sel.sign_extend()) {
    832       return true;
    833    } else if (can_use_SDWA(ctx.program->chip_class, instr, true) &&
    834               (tmp.type() == RegType::vgpr || ctx.program->chip_class >= GFX9)) {
    835       if (instr->isSDWA() && instr->sdwa().sel[idx] != SubdwordSel::dword)
    836          return false;
    837       return true;
    838    } else if (instr->isVOP3() && sel.size() == 2 &&
    839               can_use_opsel(ctx.program->chip_class, instr->opcode, idx, sel.offset()) &&
    840               !(instr->vop3().opsel & (1 << idx))) {
    841       return true;
    842    } else {
    843       return false;
    844    }
    845 }
    846 
    847 /* Combine an p_extract (or p_insert, in some cases) instruction with instr.
    848  * instr(p_extract(...)) -> instr()
    849  */
    850 void
    851 apply_extract(opt_ctx& ctx, aco_ptr<Instruction>& instr, unsigned idx, ssa_info& info)
    852 {
    853    Temp tmp = info.instr->operands[0].getTemp();
    854    SubdwordSel sel = parse_extract(info.instr);
    855    assert(sel);
    856 
    857    instr->operands[idx].set16bit(false);
    858    instr->operands[idx].set24bit(false);
    859 
    860    ctx.info[tmp.id()].label &= ~label_insert;
    861 
    862    if (sel.size() == 4) {
    863       /* full dword selection */
    864    } else if (instr->opcode == aco_opcode::v_cvt_f32_u32 && sel.size() == 1 && !sel.sign_extend()) {
    865       switch (sel.offset()) {
    866       case 0: instr->opcode = aco_opcode::v_cvt_f32_ubyte0; break;
    867       case 1: instr->opcode = aco_opcode::v_cvt_f32_ubyte1; break;
    868       case 2: instr->opcode = aco_opcode::v_cvt_f32_ubyte2; break;
    869       case 3: instr->opcode = aco_opcode::v_cvt_f32_ubyte3; break;
    870       }
    871    } else if (instr->opcode == aco_opcode::v_lshlrev_b32 && instr->operands[0].isConstant() &&
    872               sel.offset() == 0 &&
    873               ((sel.size() == 2 && instr->operands[0].constantValue() >= 16u) ||
    874                (sel.size() == 1 && instr->operands[0].constantValue() >= 24u))) {
    875       /* The undesireable upper bits are already shifted out. */
    876       return;
    877    } else if (can_use_SDWA(ctx.program->chip_class, instr, true) &&
    878               (tmp.type() == RegType::vgpr || ctx.program->chip_class >= GFX9)) {
    879       to_SDWA(ctx, instr);
    880       static_cast<SDWA_instruction*>(instr.get())->sel[idx] = sel;
    881    } else if (instr->isVOP3()) {
    882       if (sel.offset())
    883          instr->vop3().opsel |= 1 << idx;
    884    }
    885 
    886    /* label_vopc seems to be the only one worth keeping at the moment */
    887    for (Definition& def : instr->definitions)
    888       ctx.info[def.tempId()].label &= label_vopc;
    889 }
    890 
    891 void
    892 check_sdwa_extract(opt_ctx& ctx, aco_ptr<Instruction>& instr)
    893 {
    894    for (unsigned i = 0; i < instr->operands.size(); i++) {
    895       Operand op = instr->operands[i];
    896       if (!op.isTemp())
    897          continue;
    898       ssa_info& info = ctx.info[op.tempId()];
    899       if (info.is_extract() && (info.instr->operands[0].getTemp().type() == RegType::vgpr ||
    900                                 op.getTemp().type() == RegType::sgpr)) {
    901          if (!can_apply_extract(ctx, instr, i, info))
    902             info.label &= ~label_extract;
    903       }
    904    }
    905 }
    906 
    907 bool
    908 does_fp_op_flush_denorms(opt_ctx& ctx, aco_opcode op)
    909 {
    910    if (ctx.program->chip_class <= GFX8) {
    911       switch (op) {
    912       case aco_opcode::v_min_f32:
    913       case aco_opcode::v_max_f32:
    914       case aco_opcode::v_med3_f32:
    915       case aco_opcode::v_min3_f32:
    916       case aco_opcode::v_max3_f32:
    917       case aco_opcode::v_min_f16:
    918       case aco_opcode::v_max_f16: return false;
    919       default: break;
    920       }
    921    }
    922    return op != aco_opcode::v_cndmask_b32;
    923 }
    924 
    925 bool
    926 can_eliminate_fcanonicalize(opt_ctx& ctx, aco_ptr<Instruction>& instr, Temp tmp)
    927 {
    928    float_mode* fp = &ctx.fp_mode;
    929    if (ctx.info[tmp.id()].is_canonicalized() ||
    930        (tmp.bytes() == 4 ? fp->denorm32 : fp->denorm16_64) == fp_denorm_keep)
    931       return true;
    932 
    933    aco_opcode op = instr->opcode;
    934    return instr_info.can_use_input_modifiers[(int)op] && does_fp_op_flush_denorms(ctx, op);
    935 }
    936 
    937 bool
    938 is_copy_label(opt_ctx& ctx, aco_ptr<Instruction>& instr, ssa_info& info)
    939 {
    940    return info.is_temp() ||
    941           (info.is_fcanonicalize() && can_eliminate_fcanonicalize(ctx, instr, info.temp));
    942 }
    943 
    944 bool
    945 is_op_canonicalized(opt_ctx& ctx, Operand op)
    946 {
    947    float_mode* fp = &ctx.fp_mode;
    948    if ((op.isTemp() && ctx.info[op.tempId()].is_canonicalized()) ||
    949        (op.bytes() == 4 ? fp->denorm32 : fp->denorm16_64) == fp_denorm_keep)
    950       return true;
    951 
    952    if (op.isConstant() || (op.isTemp() && ctx.info[op.tempId()].is_constant_or_literal(32))) {
    953       uint32_t val = op.isTemp() ? ctx.info[op.tempId()].val : op.constantValue();
    954       if (op.bytes() == 2)
    955          return (val & 0x7fff) == 0 || (val & 0x7fff) > 0x3ff;
    956       else if (op.bytes() == 4)
    957          return (val & 0x7fffffff) == 0 || (val & 0x7fffffff) > 0x7fffff;
    958    }
    959    return false;
    960 }
    961 
    962 void
    963 label_instruction(opt_ctx& ctx, aco_ptr<Instruction>& instr)
    964 {
    965    if (instr->isSALU() || instr->isVALU() || instr->isPseudo()) {
    966       ASSERTED bool all_const = false;
    967       for (Operand& op : instr->operands)
    968          all_const =
    969             all_const && (!op.isTemp() || ctx.info[op.tempId()].is_constant_or_literal(32));
    970       perfwarn(ctx.program, all_const, "All instruction operands are constant", instr.get());
    971 
    972       ASSERTED bool is_copy = instr->opcode == aco_opcode::s_mov_b32 ||
    973                               instr->opcode == aco_opcode::s_mov_b64 ||
    974                               instr->opcode == aco_opcode::v_mov_b32;
    975       perfwarn(ctx.program, is_copy && !instr->usesModifiers(), "Use p_parallelcopy instead",
    976                instr.get());
    977    }
    978 
    979    for (unsigned i = 0; i < instr->operands.size(); i++) {
    980       if (!instr->operands[i].isTemp())
    981          continue;
    982 
    983       ssa_info info = ctx.info[instr->operands[i].tempId()];
    984       /* propagate undef */
    985       if (info.is_undefined() && is_phi(instr))
    986          instr->operands[i] = Operand(instr->operands[i].regClass());
    987       /* propagate reg->reg of same type */
    988       while (info.is_temp() && info.temp.regClass() == instr->operands[i].getTemp().regClass()) {
    989          instr->operands[i].setTemp(ctx.info[instr->operands[i].tempId()].temp);
    990          info = ctx.info[info.temp.id()];
    991       }
    992 
    993       /* PSEUDO: propagate temporaries */
    994       if (instr->isPseudo()) {
    995          while (info.is_temp()) {
    996             pseudo_propagate_temp(ctx, instr, info.temp, i);
    997             info = ctx.info[info.temp.id()];
    998          }
    999       }
   1000 
   1001       /* SALU / PSEUDO: propagate inline constants */
   1002       if (instr->isSALU() || instr->isPseudo()) {
   1003          unsigned bits = get_operand_size(instr, i);
   1004          if ((info.is_constant(bits) || (info.is_literal(bits) && instr->isPseudo())) &&
   1005              !instr->operands[i].isFixed() && alu_can_accept_constant(instr->opcode, i)) {
   1006             instr->operands[i] = get_constant_op(ctx, info, bits);
   1007             continue;
   1008          }
   1009       }
   1010 
   1011       /* VALU: propagate neg, abs & inline constants */
   1012       else if (instr->isVALU()) {
   1013          if (is_copy_label(ctx, instr, info) && info.temp.type() == RegType::vgpr &&
   1014              valu_can_accept_vgpr(instr, i)) {
   1015             instr->operands[i].setTemp(info.temp);
   1016             info = ctx.info[info.temp.id()];
   1017          }
   1018          /* applying SGPRs to VOP1 doesn't increase code size and DCE is helped by doing it earlier */
   1019          if (info.is_temp() && info.temp.type() == RegType::sgpr && can_apply_sgprs(ctx, instr) &&
   1020              instr->operands.size() == 1) {
   1021             instr->format = withoutDPP(instr->format);
   1022             instr->operands[i].setTemp(info.temp);
   1023             info = ctx.info[info.temp.id()];
   1024          }
   1025 
   1026          /* for instructions other than v_cndmask_b32, the size of the instruction should match the
   1027           * operand size */
   1028          unsigned can_use_mod =
   1029             instr->opcode != aco_opcode::v_cndmask_b32 || instr->operands[i].getTemp().bytes() == 4;
   1030          can_use_mod = can_use_mod && instr_info.can_use_input_modifiers[(int)instr->opcode];
   1031 
   1032          if (instr->isSDWA())
   1033             can_use_mod = can_use_mod && instr->sdwa().sel[i].size() == 4;
   1034          else
   1035             can_use_mod = can_use_mod && (instr->isDPP() || can_use_VOP3(ctx, instr));
   1036 
   1037          if (info.is_neg() && instr->opcode == aco_opcode::v_add_f32) {
   1038             instr->opcode = i ? aco_opcode::v_sub_f32 : aco_opcode::v_subrev_f32;
   1039             instr->operands[i].setTemp(info.temp);
   1040          } else if (info.is_neg() && instr->opcode == aco_opcode::v_add_f16) {
   1041             instr->opcode = i ? aco_opcode::v_sub_f16 : aco_opcode::v_subrev_f16;
   1042             instr->operands[i].setTemp(info.temp);
   1043          } else if (info.is_neg() && can_use_mod &&
   1044                     can_eliminate_fcanonicalize(ctx, instr, info.temp)) {
   1045             if (!instr->isDPP() && !instr->isSDWA())
   1046                to_VOP3(ctx, instr);
   1047             instr->operands[i].setTemp(info.temp);
   1048             if (instr->isDPP() && !instr->dpp().abs[i])
   1049                instr->dpp().neg[i] = true;
   1050             else if (instr->isSDWA() && !instr->sdwa().abs[i])
   1051                instr->sdwa().neg[i] = true;
   1052             else if (instr->isVOP3() && !instr->vop3().abs[i])
   1053                instr->vop3().neg[i] = true;
   1054          }
   1055          if (info.is_abs() && can_use_mod && can_eliminate_fcanonicalize(ctx, instr, info.temp)) {
   1056             if (!instr->isDPP() && !instr->isSDWA())
   1057                to_VOP3(ctx, instr);
   1058             instr->operands[i] = Operand(info.temp);
   1059             if (instr->isDPP())
   1060                instr->dpp().abs[i] = true;
   1061             else if (instr->isSDWA())
   1062                instr->sdwa().abs[i] = true;
   1063             else
   1064                instr->vop3().abs[i] = true;
   1065             continue;
   1066          }
   1067 
   1068          unsigned bits = get_operand_size(instr, i);
   1069          if (info.is_constant(bits) && alu_can_accept_constant(instr->opcode, i) &&
   1070              (!instr->isSDWA() || ctx.program->chip_class >= GFX9)) {
   1071             Operand op = get_constant_op(ctx, info, bits);
   1072             perfwarn(ctx.program, instr->opcode == aco_opcode::v_cndmask_b32 && i == 2,
   1073                      "v_cndmask_b32 with a constant selector", instr.get());
   1074             if (i == 0 || instr->isSDWA() || instr->isVOP3P() ||
   1075                 instr->opcode == aco_opcode::v_readlane_b32 ||
   1076                 instr->opcode == aco_opcode::v_writelane_b32) {
   1077                instr->format = withoutDPP(instr->format);
   1078                instr->operands[i] = op;
   1079                continue;
   1080             } else if (!instr->isVOP3() && can_swap_operands(instr, &instr->opcode)) {
   1081                instr->operands[i] = instr->operands[0];
   1082                instr->operands[0] = op;
   1083                continue;
   1084             } else if (can_use_VOP3(ctx, instr)) {
   1085                to_VOP3(ctx, instr);
   1086                instr->operands[i] = op;
   1087                continue;
   1088             }
   1089          }
   1090       }
   1091 
   1092       /* MUBUF: propagate constants and combine additions */
   1093       else if (instr->isMUBUF()) {
   1094          MUBUF_instruction& mubuf = instr->mubuf();
   1095          Temp base;
   1096          uint32_t offset;
   1097          while (info.is_temp())
   1098             info = ctx.info[info.temp.id()];
   1099 
   1100          /* According to AMDGPUDAGToDAGISel::SelectMUBUFScratchOffen(), vaddr
   1101           * overflow for scratch accesses works only on GFX9+ and saddr overflow
   1102           * never works. Since swizzling is the only thing that separates
   1103           * scratch accesses and other accesses and swizzling changing how
   1104           * addressing works significantly, this probably applies to swizzled
   1105           * MUBUF accesses. */
   1106          bool vaddr_prevent_overflow = mubuf.swizzled && ctx.program->chip_class < GFX9;
   1107          bool saddr_prevent_overflow = mubuf.swizzled;
   1108 
   1109          if (mubuf.offen && i == 1 && info.is_constant_or_literal(32) &&
   1110              mubuf.offset + info.val < 4096) {
   1111             assert(!mubuf.idxen);
   1112             instr->operands[1] = Operand(v1);
   1113             mubuf.offset += info.val;
   1114             mubuf.offen = false;
   1115             continue;
   1116          } else if (i == 2 && info.is_constant_or_literal(32) && mubuf.offset + info.val < 4096) {
   1117             instr->operands[2] = Operand::c32(0);
   1118             mubuf.offset += info.val;
   1119             continue;
   1120          } else if (mubuf.offen && i == 1 &&
   1121                     parse_base_offset(ctx, instr.get(), i, &base, &offset,
   1122                                       vaddr_prevent_overflow) &&
   1123                     base.regClass() == v1 && mubuf.offset + offset < 4096) {
   1124             assert(!mubuf.idxen);
   1125             instr->operands[1].setTemp(base);
   1126             mubuf.offset += offset;
   1127             continue;
   1128          } else if (i == 2 &&
   1129                     parse_base_offset(ctx, instr.get(), i, &base, &offset,
   1130                                       saddr_prevent_overflow) &&
   1131                     base.regClass() == s1 && mubuf.offset + offset < 4096) {
   1132             instr->operands[i].setTemp(base);
   1133             mubuf.offset += offset;
   1134             continue;
   1135          }
   1136       }
   1137 
   1138       /* DS: combine additions */
   1139       else if (instr->isDS()) {
   1140 
   1141          DS_instruction& ds = instr->ds();
   1142          Temp base;
   1143          uint32_t offset;
   1144          bool has_usable_ds_offset = ctx.program->chip_class >= GFX7;
   1145          if (has_usable_ds_offset && i == 0 &&
   1146              parse_base_offset(ctx, instr.get(), i, &base, &offset, false) &&
   1147              base.regClass() == instr->operands[i].regClass() &&
   1148              instr->opcode != aco_opcode::ds_swizzle_b32) {
   1149             if (instr->opcode == aco_opcode::ds_write2_b32 ||
   1150                 instr->opcode == aco_opcode::ds_read2_b32 ||
   1151                 instr->opcode == aco_opcode::ds_write2_b64 ||
   1152                 instr->opcode == aco_opcode::ds_read2_b64) {
   1153                unsigned mask = (instr->opcode == aco_opcode::ds_write2_b64 ||
   1154                                 instr->opcode == aco_opcode::ds_read2_b64)
   1155                                   ? 0x7
   1156                                   : 0x3;
   1157                unsigned shifts = (instr->opcode == aco_opcode::ds_write2_b64 ||
   1158                                   instr->opcode == aco_opcode::ds_read2_b64)
   1159                                     ? 3
   1160                                     : 2;
   1161 
   1162                if ((offset & mask) == 0 && ds.offset0 + (offset >> shifts) <= 255 &&
   1163                    ds.offset1 + (offset >> shifts) <= 255) {
   1164                   instr->operands[i].setTemp(base);
   1165                   ds.offset0 += offset >> shifts;
   1166                   ds.offset1 += offset >> shifts;
   1167                }
   1168             } else {
   1169                if (ds.offset0 + offset <= 65535) {
   1170                   instr->operands[i].setTemp(base);
   1171                   ds.offset0 += offset;
   1172                }
   1173             }
   1174          }
   1175       }
   1176 
   1177       /* SMEM: propagate constants and combine additions */
   1178       else if (instr->isSMEM()) {
   1179 
   1180          SMEM_instruction& smem = instr->smem();
   1181          Temp base;
   1182          uint32_t offset;
   1183          bool prevent_overflow = smem.operands[0].size() > 2 || smem.prevent_overflow;
   1184          if (i == 1 && info.is_constant_or_literal(32) &&
   1185              ((ctx.program->chip_class == GFX6 && info.val <= 0x3FF) ||
   1186               (ctx.program->chip_class == GFX7 && info.val <= 0xFFFFFFFF) ||
   1187               (ctx.program->chip_class >= GFX8 && info.val <= 0xFFFFF))) {
   1188             instr->operands[i] = Operand::c32(info.val);
   1189             continue;
   1190          } else if (i == 1 &&
   1191                     parse_base_offset(ctx, instr.get(), i, &base, &offset, prevent_overflow) &&
   1192                     base.regClass() == s1 && offset <= 0xFFFFF && ctx.program->chip_class >= GFX9) {
   1193             bool soe = smem.operands.size() >= (!smem.definitions.empty() ? 3 : 4);
   1194             if (soe && (!ctx.info[smem.operands.back().tempId()].is_constant_or_literal(32) ||
   1195                         ctx.info[smem.operands.back().tempId()].val != 0)) {
   1196                continue;
   1197             }
   1198             if (soe) {
   1199                smem.operands[1] = Operand::c32(offset);
   1200                smem.operands.back() = Operand(base);
   1201             } else {
   1202                SMEM_instruction* new_instr = create_instruction<SMEM_instruction>(
   1203                   smem.opcode, Format::SMEM, smem.operands.size() + 1, smem.definitions.size());
   1204                new_instr->operands[0] = smem.operands[0];
   1205                new_instr->operands[1] = Operand::c32(offset);
   1206                if (smem.definitions.empty())
   1207                   new_instr->operands[2] = smem.operands[2];
   1208                new_instr->operands.back() = Operand(base);
   1209                if (!smem.definitions.empty())
   1210                   new_instr->definitions[0] = smem.definitions[0];
   1211                new_instr->sync = smem.sync;
   1212                new_instr->glc = smem.glc;
   1213                new_instr->dlc = smem.dlc;
   1214                new_instr->nv = smem.nv;
   1215                new_instr->disable_wqm = smem.disable_wqm;
   1216                instr.reset(new_instr);
   1217             }
   1218             continue;
   1219          }
   1220       }
   1221 
   1222       else if (instr->isBranch()) {
   1223          if (ctx.info[instr->operands[0].tempId()].is_scc_invert()) {
   1224             /* Flip the branch instruction to get rid of the scc_invert instruction */
   1225             instr->opcode = instr->opcode == aco_opcode::p_cbranch_z ? aco_opcode::p_cbranch_nz
   1226                                                                      : aco_opcode::p_cbranch_z;
   1227             instr->operands[0].setTemp(ctx.info[instr->operands[0].tempId()].temp);
   1228          }
   1229       }
   1230    }
   1231 
   1232    /* if this instruction doesn't define anything, return */
   1233    if (instr->definitions.empty()) {
   1234       check_sdwa_extract(ctx, instr);
   1235       return;
   1236    }
   1237 
   1238    if (instr->isVALU() || instr->isVINTRP()) {
   1239       if (instr_info.can_use_output_modifiers[(int)instr->opcode] || instr->isVINTRP() ||
   1240           instr->opcode == aco_opcode::v_cndmask_b32) {
   1241          bool canonicalized = true;
   1242          if (!does_fp_op_flush_denorms(ctx, instr->opcode)) {
   1243             unsigned ops = instr->opcode == aco_opcode::v_cndmask_b32 ? 2 : instr->operands.size();
   1244             for (unsigned i = 0; canonicalized && (i < ops); i++)
   1245                canonicalized = is_op_canonicalized(ctx, instr->operands[i]);
   1246          }
   1247          if (canonicalized)
   1248             ctx.info[instr->definitions[0].tempId()].set_canonicalized();
   1249       }
   1250 
   1251       if (instr->isVOPC()) {
   1252          ctx.info[instr->definitions[0].tempId()].set_vopc(instr.get());
   1253          check_sdwa_extract(ctx, instr);
   1254          return;
   1255       }
   1256       if (instr->isVOP3P()) {
   1257          ctx.info[instr->definitions[0].tempId()].set_vop3p(instr.get());
   1258          return;
   1259       }
   1260    }
   1261 
   1262    switch (instr->opcode) {
   1263    case aco_opcode::p_create_vector: {
   1264       bool copy_prop = instr->operands.size() == 1 && instr->operands[0].isTemp() &&
   1265                        instr->operands[0].regClass() == instr->definitions[0].regClass();
   1266       if (copy_prop) {
   1267          ctx.info[instr->definitions[0].tempId()].set_temp(instr->operands[0].getTemp());
   1268          break;
   1269       }
   1270 
   1271       /* expand vector operands */
   1272       std::vector<Operand> ops;
   1273       unsigned offset = 0;
   1274       for (const Operand& op : instr->operands) {
   1275          /* ensure that any expanded operands are properly aligned */
   1276          bool aligned = offset % 4 == 0 || op.bytes() < 4;
   1277          offset += op.bytes();
   1278          if (aligned && op.isTemp() && ctx.info[op.tempId()].is_vec()) {
   1279             Instruction* vec = ctx.info[op.tempId()].instr;
   1280             for (const Operand& vec_op : vec->operands)
   1281                ops.emplace_back(vec_op);
   1282          } else {
   1283             ops.emplace_back(op);
   1284          }
   1285       }
   1286 
   1287       /* combine expanded operands to new vector */
   1288       if (ops.size() != instr->operands.size()) {
   1289          assert(ops.size() > instr->operands.size());
   1290          Definition def = instr->definitions[0];
   1291          instr.reset(create_instruction<Pseudo_instruction>(aco_opcode::p_create_vector,
   1292                                                             Format::PSEUDO, ops.size(), 1));
   1293          for (unsigned i = 0; i < ops.size(); i++) {
   1294             if (ops[i].isTemp() && ctx.info[ops[i].tempId()].is_temp() &&
   1295                 ops[i].regClass() == ctx.info[ops[i].tempId()].temp.regClass())
   1296                ops[i].setTemp(ctx.info[ops[i].tempId()].temp);
   1297             instr->operands[i] = ops[i];
   1298          }
   1299          instr->definitions[0] = def;
   1300       } else {
   1301          for (unsigned i = 0; i < ops.size(); i++) {
   1302             assert(instr->operands[i] == ops[i]);
   1303          }
   1304       }
   1305       ctx.info[instr->definitions[0].tempId()].set_vec(instr.get());
   1306       break;
   1307    }
   1308    case aco_opcode::p_split_vector: {
   1309       ssa_info& info = ctx.info[instr->operands[0].tempId()];
   1310 
   1311       if (info.is_constant_or_literal(32)) {
   1312          uint32_t val = info.val;
   1313          for (Definition def : instr->definitions) {
   1314             uint32_t mask = u_bit_consecutive(0, def.bytes() * 8u);
   1315             ctx.info[def.tempId()].set_constant(ctx.program->chip_class, val & mask);
   1316             val >>= def.bytes() * 8u;
   1317          }
   1318          break;
   1319       } else if (!info.is_vec()) {
   1320          break;
   1321       }
   1322 
   1323       Instruction* vec = ctx.info[instr->operands[0].tempId()].instr;
   1324       unsigned split_offset = 0;
   1325       unsigned vec_offset = 0;
   1326       unsigned vec_index = 0;
   1327       for (unsigned i = 0; i < instr->definitions.size();
   1328            split_offset += instr->definitions[i++].bytes()) {
   1329          while (vec_offset < split_offset && vec_index < vec->operands.size())
   1330             vec_offset += vec->operands[vec_index++].bytes();
   1331 
   1332          if (vec_offset != split_offset ||
   1333              vec->operands[vec_index].bytes() != instr->definitions[i].bytes())
   1334             continue;
   1335 
   1336          Operand vec_op = vec->operands[vec_index];
   1337          if (vec_op.isConstant()) {
   1338             ctx.info[instr->definitions[i].tempId()].set_constant(ctx.program->chip_class,
   1339                                                                   vec_op.constantValue64());
   1340          } else if (vec_op.isUndefined()) {
   1341             ctx.info[instr->definitions[i].tempId()].set_undefined();
   1342          } else {
   1343             assert(vec_op.isTemp());
   1344             ctx.info[instr->definitions[i].tempId()].set_temp(vec_op.getTemp());
   1345          }
   1346       }
   1347       break;
   1348    }
   1349    case aco_opcode::p_extract_vector: { /* mov */
   1350       ssa_info& info = ctx.info[instr->operands[0].tempId()];
   1351       const unsigned index = instr->operands[1].constantValue();
   1352       const unsigned dst_offset = index * instr->definitions[0].bytes();
   1353 
   1354       if (info.is_vec()) {
   1355          /* check if we index directly into a vector element */
   1356          Instruction* vec = info.instr;
   1357          unsigned offset = 0;
   1358 
   1359          for (const Operand& op : vec->operands) {
   1360             if (offset < dst_offset) {
   1361                offset += op.bytes();
   1362                continue;
   1363             } else if (offset != dst_offset || op.bytes() != instr->definitions[0].bytes()) {
   1364                break;
   1365             }
   1366             instr->operands[0] = op;
   1367             break;
   1368          }
   1369       } else if (info.is_constant_or_literal(32)) {
   1370          /* propagate constants */
   1371          uint32_t mask = u_bit_consecutive(0, instr->definitions[0].bytes() * 8u);
   1372          uint32_t val = (info.val >> (dst_offset * 8u)) & mask;
   1373          instr->operands[0] =
   1374             Operand::get_const(ctx.program->chip_class, val, instr->definitions[0].bytes());
   1375          ;
   1376       } else if (index == 0 && instr->operands[0].size() == instr->definitions[0].size()) {
   1377          ctx.info[instr->definitions[0].tempId()].set_temp(instr->operands[0].getTemp());
   1378       }
   1379 
   1380       if (instr->operands[0].bytes() != instr->definitions[0].bytes())
   1381          break;
   1382 
   1383       /* convert this extract into a copy instruction */
   1384       instr->opcode = aco_opcode::p_parallelcopy;
   1385       instr->operands.pop_back();
   1386       FALLTHROUGH;
   1387    }
   1388    case aco_opcode::p_parallelcopy: /* propagate */
   1389       if (instr->operands[0].isTemp() && ctx.info[instr->operands[0].tempId()].is_vec() &&
   1390           instr->operands[0].regClass() != instr->definitions[0].regClass()) {
   1391          /* We might not be able to copy-propagate if it's a SGPR->VGPR copy, so
   1392           * duplicate the vector instead.
   1393           */
   1394          Instruction* vec = ctx.info[instr->operands[0].tempId()].instr;
   1395          aco_ptr<Instruction> old_copy = std::move(instr);
   1396 
   1397          instr.reset(create_instruction<Pseudo_instruction>(
   1398             aco_opcode::p_create_vector, Format::PSEUDO, vec->operands.size(), 1));
   1399          instr->definitions[0] = old_copy->definitions[0];
   1400          std::copy(vec->operands.begin(), vec->operands.end(), instr->operands.begin());
   1401          for (unsigned i = 0; i < vec->operands.size(); i++) {
   1402             Operand& op = instr->operands[i];
   1403             if (op.isTemp() && ctx.info[op.tempId()].is_temp() &&
   1404                 ctx.info[op.tempId()].temp.type() == instr->definitions[0].regClass().type())
   1405                op.setTemp(ctx.info[op.tempId()].temp);
   1406          }
   1407          ctx.info[instr->definitions[0].tempId()].set_vec(instr.get());
   1408          break;
   1409       }
   1410       FALLTHROUGH;
   1411    case aco_opcode::p_as_uniform:
   1412       if (instr->definitions[0].isFixed()) {
   1413          /* don't copy-propagate copies into fixed registers */
   1414       } else if (instr->usesModifiers()) {
   1415          // TODO
   1416       } else if (instr->operands[0].isConstant()) {
   1417          ctx.info[instr->definitions[0].tempId()].set_constant(
   1418             ctx.program->chip_class, instr->operands[0].constantValue64());
   1419       } else if (instr->operands[0].isTemp()) {
   1420          ctx.info[instr->definitions[0].tempId()].set_temp(instr->operands[0].getTemp());
   1421          if (ctx.info[instr->operands[0].tempId()].is_canonicalized())
   1422             ctx.info[instr->definitions[0].tempId()].set_canonicalized();
   1423       } else {
   1424          assert(instr->operands[0].isFixed());
   1425       }
   1426       break;
   1427    case aco_opcode::v_mov_b32:
   1428       if (instr->isDPP()) {
   1429          /* anything else doesn't make sense in SSA */
   1430          assert(instr->dpp().row_mask == 0xf && instr->dpp().bank_mask == 0xf);
   1431          ctx.info[instr->definitions[0].tempId()].set_dpp(instr.get());
   1432       }
   1433       break;
   1434    case aco_opcode::p_is_helper:
   1435       if (!ctx.program->needs_wqm)
   1436          ctx.info[instr->definitions[0].tempId()].set_constant(ctx.program->chip_class, 0u);
   1437       break;
   1438    case aco_opcode::v_mul_f64: ctx.info[instr->definitions[0].tempId()].set_mul(instr.get()); break;
   1439    case aco_opcode::v_mul_f16:
   1440    case aco_opcode::v_mul_f32: { /* omod */
   1441       ctx.info[instr->definitions[0].tempId()].set_mul(instr.get());
   1442 
   1443       /* TODO: try to move the negate/abs modifier to the consumer instead */
   1444       bool uses_mods = instr->usesModifiers();
   1445       bool fp16 = instr->opcode == aco_opcode::v_mul_f16;
   1446 
   1447       for (unsigned i = 0; i < 2; i++) {
   1448          if (instr->operands[!i].isConstant() && instr->operands[i].isTemp()) {
   1449             if (!instr->isDPP() && !instr->isSDWA() &&
   1450                 (instr->operands[!i].constantEquals(fp16 ? 0x3c00 : 0x3f800000) ||   /* 1.0 */
   1451                  instr->operands[!i].constantEquals(fp16 ? 0xbc00 : 0xbf800000u))) { /* -1.0 */
   1452                bool neg1 = instr->operands[!i].constantEquals(fp16 ? 0xbc00 : 0xbf800000u);
   1453 
   1454                VOP3_instruction* vop3 = instr->isVOP3() ? &instr->vop3() : NULL;
   1455                if (vop3 && (vop3->abs[!i] || vop3->neg[!i] || vop3->clamp || vop3->omod))
   1456                   continue;
   1457 
   1458                bool abs = vop3 && vop3->abs[i];
   1459                bool neg = neg1 ^ (vop3 && vop3->neg[i]);
   1460 
   1461                Temp other = instr->operands[i].getTemp();
   1462                if (abs && neg && other.type() == RegType::vgpr)
   1463                   ctx.info[instr->definitions[0].tempId()].set_neg_abs(other);
   1464                else if (abs && !neg && other.type() == RegType::vgpr)
   1465                   ctx.info[instr->definitions[0].tempId()].set_abs(other);
   1466                else if (!abs && neg && other.type() == RegType::vgpr)
   1467                   ctx.info[instr->definitions[0].tempId()].set_neg(other);
   1468                else if (!abs && !neg)
   1469                   ctx.info[instr->definitions[0].tempId()].set_fcanonicalize(other);
   1470             } else if (uses_mods) {
   1471                continue;
   1472             } else if (instr->operands[!i].constantValue() ==
   1473                        (fp16 ? 0x4000 : 0x40000000)) { /* 2.0 */
   1474                ctx.info[instr->operands[i].tempId()].set_omod2(instr.get());
   1475             } else if (instr->operands[!i].constantValue() ==
   1476                        (fp16 ? 0x4400 : 0x40800000)) { /* 4.0 */
   1477                ctx.info[instr->operands[i].tempId()].set_omod4(instr.get());
   1478             } else if (instr->operands[!i].constantValue() ==
   1479                        (fp16 ? 0x3800 : 0x3f000000)) { /* 0.5 */
   1480                ctx.info[instr->operands[i].tempId()].set_omod5(instr.get());
   1481             } else if (instr->operands[!i].constantValue() == 0u &&
   1482                        !(fp16 ? ctx.fp_mode.preserve_signed_zero_inf_nan16_64
   1483                               : ctx.fp_mode.preserve_signed_zero_inf_nan32)) { /* 0.0 */
   1484                ctx.info[instr->definitions[0].tempId()].set_constant(ctx.program->chip_class, 0u);
   1485             } else {
   1486                continue;
   1487             }
   1488             break;
   1489          }
   1490       }
   1491       break;
   1492    }
   1493    case aco_opcode::v_mul_lo_u16:
   1494    case aco_opcode::v_mul_lo_u16_e64:
   1495    case aco_opcode::v_mul_u32_u24:
   1496       ctx.info[instr->definitions[0].tempId()].set_usedef(instr.get());
   1497       break;
   1498    case aco_opcode::v_med3_f16:
   1499    case aco_opcode::v_med3_f32: { /* clamp */
   1500       VOP3_instruction& vop3 = instr->vop3();
   1501       if (vop3.abs[0] || vop3.abs[1] || vop3.abs[2] || vop3.neg[0] || vop3.neg[1] || vop3.neg[2] ||
   1502           vop3.omod != 0 || vop3.opsel != 0)
   1503          break;
   1504 
   1505       unsigned idx = 0;
   1506       bool found_zero = false, found_one = false;
   1507       bool is_fp16 = instr->opcode == aco_opcode::v_med3_f16;
   1508       for (unsigned i = 0; i < 3; i++) {
   1509          if (instr->operands[i].constantEquals(0))
   1510             found_zero = true;
   1511          else if (instr->operands[i].constantEquals(is_fp16 ? 0x3c00 : 0x3f800000)) /* 1.0 */
   1512             found_one = true;
   1513          else
   1514             idx = i;
   1515       }
   1516       if (found_zero && found_one && instr->operands[idx].isTemp())
   1517          ctx.info[instr->operands[idx].tempId()].set_clamp(instr.get());
   1518       break;
   1519    }
   1520    case aco_opcode::v_cndmask_b32:
   1521       if (instr->operands[0].constantEquals(0) && instr->operands[1].constantEquals(0xFFFFFFFF))
   1522          ctx.info[instr->definitions[0].tempId()].set_vcc(instr->operands[2].getTemp());
   1523       else if (instr->operands[0].constantEquals(0) &&
   1524                instr->operands[1].constantEquals(0x3f800000u))
   1525          ctx.info[instr->definitions[0].tempId()].set_b2f(instr->operands[2].getTemp());
   1526       else if (instr->operands[0].constantEquals(0) && instr->operands[1].constantEquals(1))
   1527          ctx.info[instr->definitions[0].tempId()].set_b2i(instr->operands[2].getTemp());
   1528 
   1529       ctx.info[instr->operands[2].tempId()].set_vcc_hint();
   1530       break;
   1531    case aco_opcode::v_cmp_lg_u32:
   1532       if (instr->format == Format::VOPC && /* don't optimize VOP3 / SDWA / DPP */
   1533           instr->operands[0].constantEquals(0) && instr->operands[1].isTemp() &&
   1534           ctx.info[instr->operands[1].tempId()].is_vcc())
   1535          ctx.info[instr->definitions[0].tempId()].set_temp(
   1536             ctx.info[instr->operands[1].tempId()].temp);
   1537       break;
   1538    case aco_opcode::p_linear_phi: {
   1539       /* lower_bool_phis() can create phis like this */
   1540       bool all_same_temp = instr->operands[0].isTemp();
   1541       /* this check is needed when moving uniform loop counters out of a divergent loop */
   1542       if (all_same_temp)
   1543          all_same_temp = instr->definitions[0].regClass() == instr->operands[0].regClass();
   1544       for (unsigned i = 1; all_same_temp && (i < instr->operands.size()); i++) {
   1545          if (!instr->operands[i].isTemp() ||
   1546              instr->operands[i].tempId() != instr->operands[0].tempId())
   1547             all_same_temp = false;
   1548       }
   1549       if (all_same_temp) {
   1550          ctx.info[instr->definitions[0].tempId()].set_temp(instr->operands[0].getTemp());
   1551       } else {
   1552          bool all_undef = instr->operands[0].isUndefined();
   1553          for (unsigned i = 1; all_undef && (i < instr->operands.size()); i++) {
   1554             if (!instr->operands[i].isUndefined())
   1555                all_undef = false;
   1556          }
   1557          if (all_undef)
   1558             ctx.info[instr->definitions[0].tempId()].set_undefined();
   1559       }
   1560       break;
   1561    }
   1562    case aco_opcode::v_add_u32:
   1563    case aco_opcode::v_add_co_u32:
   1564    case aco_opcode::v_add_co_u32_e64:
   1565    case aco_opcode::s_add_i32:
   1566    case aco_opcode::s_add_u32:
   1567    case aco_opcode::v_subbrev_co_u32:
   1568       ctx.info[instr->definitions[0].tempId()].set_add_sub(instr.get());
   1569       break;
   1570    case aco_opcode::s_not_b32:
   1571    case aco_opcode::s_not_b64:
   1572       if (ctx.info[instr->operands[0].tempId()].is_uniform_bool()) {
   1573          ctx.info[instr->definitions[0].tempId()].set_uniform_bitwise();
   1574          ctx.info[instr->definitions[1].tempId()].set_scc_invert(
   1575             ctx.info[instr->operands[0].tempId()].temp);
   1576       } else if (ctx.info[instr->operands[0].tempId()].is_uniform_bitwise()) {
   1577          ctx.info[instr->definitions[0].tempId()].set_uniform_bitwise();
   1578          ctx.info[instr->definitions[1].tempId()].set_scc_invert(
   1579             ctx.info[instr->operands[0].tempId()].instr->definitions[1].getTemp());
   1580       }
   1581       ctx.info[instr->definitions[0].tempId()].set_bitwise(instr.get());
   1582       break;
   1583    case aco_opcode::s_and_b32:
   1584    case aco_opcode::s_and_b64:
   1585       if (fixed_to_exec(instr->operands[1]) && instr->operands[0].isTemp()) {
   1586          if (ctx.info[instr->operands[0].tempId()].is_uniform_bool()) {
   1587             /* Try to get rid of the superfluous s_cselect + s_and_b64 that comes from turning a
   1588              * uniform bool into divergent */
   1589             ctx.info[instr->definitions[1].tempId()].set_temp(
   1590                ctx.info[instr->operands[0].tempId()].temp);
   1591             ctx.info[instr->definitions[0].tempId()].set_uniform_bool(
   1592                ctx.info[instr->operands[0].tempId()].temp);
   1593             break;
   1594          } else if (ctx.info[instr->operands[0].tempId()].is_uniform_bitwise()) {
   1595             /* Try to get rid of the superfluous s_and_b64, since the uniform bitwise instruction
   1596              * already produces the same SCC */
   1597             ctx.info[instr->definitions[1].tempId()].set_temp(
   1598                ctx.info[instr->operands[0].tempId()].instr->definitions[1].getTemp());
   1599             ctx.info[instr->definitions[0].tempId()].set_uniform_bool(
   1600                ctx.info[instr->operands[0].tempId()].instr->definitions[1].getTemp());
   1601             break;
   1602          } else if ((ctx.program->stage.num_sw_stages() > 1 ||
   1603                      ctx.program->stage.hw == HWStage::NGG) &&
   1604                     instr->pass_flags == 1) {
   1605             /* In case of merged shaders, pass_flags=1 means that all lanes are active (exec=-1), so
   1606              * s_and is unnecessary. */
   1607             ctx.info[instr->definitions[0].tempId()].set_temp(instr->operands[0].getTemp());
   1608             break;
   1609          } else if (ctx.info[instr->operands[0].tempId()].is_vopc()) {
   1610             Instruction* vopc_instr = ctx.info[instr->operands[0].tempId()].instr;
   1611             /* Remove superfluous s_and when the VOPC instruction uses the same exec and thus
   1612              * already produces the same result */
   1613             if (vopc_instr->pass_flags == instr->pass_flags) {
   1614                assert(instr->pass_flags > 0);
   1615                ctx.info[instr->definitions[0].tempId()].set_temp(
   1616                   vopc_instr->definitions[0].getTemp());
   1617                break;
   1618             }
   1619          }
   1620       }
   1621       FALLTHROUGH;
   1622    case aco_opcode::s_or_b32:
   1623    case aco_opcode::s_or_b64:
   1624    case aco_opcode::s_xor_b32:
   1625    case aco_opcode::s_xor_b64:
   1626       if (std::all_of(instr->operands.begin(), instr->operands.end(),
   1627                       [&ctx](const Operand& op)
   1628                       {
   1629                          return op.isTemp() && (ctx.info[op.tempId()].is_uniform_bool() ||
   1630                                                 ctx.info[op.tempId()].is_uniform_bitwise());
   1631                       })) {
   1632          ctx.info[instr->definitions[0].tempId()].set_uniform_bitwise();
   1633       }
   1634       FALLTHROUGH;
   1635    case aco_opcode::s_lshl_b32:
   1636    case aco_opcode::v_or_b32:
   1637    case aco_opcode::v_lshlrev_b32:
   1638    case aco_opcode::v_bcnt_u32_b32:
   1639    case aco_opcode::v_and_b32:
   1640    case aco_opcode::v_xor_b32:
   1641       ctx.info[instr->definitions[0].tempId()].set_bitwise(instr.get());
   1642       break;
   1643    case aco_opcode::v_min_f32:
   1644    case aco_opcode::v_min_f16:
   1645    case aco_opcode::v_min_u32:
   1646    case aco_opcode::v_min_i32:
   1647    case aco_opcode::v_min_u16:
   1648    case aco_opcode::v_min_i16:
   1649    case aco_opcode::v_max_f32:
   1650    case aco_opcode::v_max_f16:
   1651    case aco_opcode::v_max_u32:
   1652    case aco_opcode::v_max_i32:
   1653    case aco_opcode::v_max_u16:
   1654    case aco_opcode::v_max_i16:
   1655       ctx.info[instr->definitions[0].tempId()].set_minmax(instr.get());
   1656       break;
   1657    case aco_opcode::s_cselect_b64:
   1658    case aco_opcode::s_cselect_b32:
   1659       if (instr->operands[0].constantEquals((unsigned)-1) && instr->operands[1].constantEquals(0)) {
   1660          /* Found a cselect that operates on a uniform bool that comes from eg. s_cmp */
   1661          ctx.info[instr->definitions[0].tempId()].set_uniform_bool(instr->operands[2].getTemp());
   1662       }
   1663       if (instr->operands[2].isTemp() && ctx.info[instr->operands[2].tempId()].is_scc_invert()) {
   1664          /* Flip the operands to get rid of the scc_invert instruction */
   1665          std::swap(instr->operands[0], instr->operands[1]);
   1666          instr->operands[2].setTemp(ctx.info[instr->operands[2].tempId()].temp);
   1667       }
   1668       break;
   1669    case aco_opcode::p_wqm:
   1670       if (instr->operands[0].isTemp() && ctx.info[instr->operands[0].tempId()].is_scc_invert()) {
   1671          ctx.info[instr->definitions[0].tempId()].set_temp(instr->operands[0].getTemp());
   1672       }
   1673       break;
   1674    case aco_opcode::s_mul_i32:
   1675       /* Testing every uint32_t shows that 0x3f800000*n is never a denormal.
   1676        * This pattern is created from a uniform nir_op_b2f. */
   1677       if (instr->operands[0].constantEquals(0x3f800000u))
   1678          ctx.info[instr->definitions[0].tempId()].set_canonicalized();
   1679       break;
   1680    case aco_opcode::p_extract: {
   1681       if (instr->definitions[0].bytes() == 4) {
   1682          ctx.info[instr->definitions[0].tempId()].set_extract(instr.get());
   1683          if (instr->operands[0].regClass() == v1 && parse_insert(instr.get()))
   1684             ctx.info[instr->operands[0].tempId()].set_insert(instr.get());
   1685       }
   1686       break;
   1687    }
   1688    case aco_opcode::p_insert: {
   1689       if (instr->operands[0].bytes() == 4) {
   1690          if (instr->operands[0].regClass() == v1)
   1691             ctx.info[instr->operands[0].tempId()].set_insert(instr.get());
   1692          if (parse_extract(instr.get()))
   1693             ctx.info[instr->definitions[0].tempId()].set_extract(instr.get());
   1694          ctx.info[instr->definitions[0].tempId()].set_bitwise(instr.get());
   1695       }
   1696       break;
   1697    }
   1698    case aco_opcode::ds_read_u8:
   1699    case aco_opcode::ds_read_u8_d16:
   1700    case aco_opcode::ds_read_u16:
   1701    case aco_opcode::ds_read_u16_d16: {
   1702       ctx.info[instr->definitions[0].tempId()].set_usedef(instr.get());
   1703       break;
   1704    }
   1705    default: break;
   1706    }
   1707 
   1708    /* Don't remove label_extract if we can't apply the extract to
   1709     * neg/abs instructions because we'll likely combine it into another valu. */
   1710    if (!(ctx.info[instr->definitions[0].tempId()].label & (label_neg | label_abs)))
   1711       check_sdwa_extract(ctx, instr);
   1712 }
   1713 
   1714 unsigned
   1715 original_temp_id(opt_ctx& ctx, Temp tmp)
   1716 {
   1717    if (ctx.info[tmp.id()].is_temp())
   1718       return ctx.info[tmp.id()].temp.id();
   1719    else
   1720       return tmp.id();
   1721 }
   1722 
   1723 void
   1724 decrease_uses(opt_ctx& ctx, Instruction* instr)
   1725 {
   1726    if (!--ctx.uses[instr->definitions[0].tempId()]) {
   1727       for (const Operand& op : instr->operands) {
   1728          if (op.isTemp())
   1729             ctx.uses[op.tempId()]--;
   1730       }
   1731    }
   1732 }
   1733 
   1734 Instruction*
   1735 follow_operand(opt_ctx& ctx, Operand op, bool ignore_uses = false)
   1736 {
   1737    if (!op.isTemp() || !(ctx.info[op.tempId()].label & instr_usedef_labels))
   1738       return nullptr;
   1739    if (!ignore_uses && ctx.uses[op.tempId()] > 1)
   1740       return nullptr;
   1741 
   1742    Instruction* instr = ctx.info[op.tempId()].instr;
   1743 
   1744    if (instr->definitions.size() == 2) {
   1745       assert(instr->definitions[0].isTemp() && instr->definitions[0].tempId() == op.tempId());
   1746       if (instr->definitions[1].isTemp() && ctx.uses[instr->definitions[1].tempId()])
   1747          return nullptr;
   1748    }
   1749 
   1750    return instr;
   1751 }
   1752 
   1753 /* s_or_b64(neq(a, a), neq(b, b)) -> v_cmp_u_f32(a, b)
   1754  * s_and_b64(eq(a, a), eq(b, b)) -> v_cmp_o_f32(a, b) */
   1755 bool
   1756 combine_ordering_test(opt_ctx& ctx, aco_ptr<Instruction>& instr)
   1757 {
   1758    if (instr->definitions[0].regClass() != ctx.program->lane_mask)
   1759       return false;
   1760    if (instr->definitions[1].isTemp() && ctx.uses[instr->definitions[1].tempId()])
   1761       return false;
   1762 
   1763    bool is_or = instr->opcode == aco_opcode::s_or_b64 || instr->opcode == aco_opcode::s_or_b32;
   1764 
   1765    bool neg[2] = {false, false};
   1766    bool abs[2] = {false, false};
   1767    uint8_t opsel = 0;
   1768    Instruction* op_instr[2];
   1769    Temp op[2];
   1770 
   1771    unsigned bitsize = 0;
   1772    for (unsigned i = 0; i < 2; i++) {
   1773       op_instr[i] = follow_operand(ctx, instr->operands[i], true);
   1774       if (!op_instr[i])
   1775          return false;
   1776 
   1777       aco_opcode expected_cmp = is_or ? aco_opcode::v_cmp_neq_f32 : aco_opcode::v_cmp_eq_f32;
   1778       unsigned op_bitsize = get_cmp_bitsize(op_instr[i]->opcode);
   1779 
   1780       if (get_f32_cmp(op_instr[i]->opcode) != expected_cmp)
   1781          return false;
   1782       if (bitsize && op_bitsize != bitsize)
   1783          return false;
   1784       if (!op_instr[i]->operands[0].isTemp() || !op_instr[i]->operands[1].isTemp())
   1785          return false;
   1786 
   1787       if (op_instr[i]->isVOP3()) {
   1788          VOP3_instruction& vop3 = op_instr[i]->vop3();
   1789          if (vop3.neg[0] != vop3.neg[1] || vop3.abs[0] != vop3.abs[1] || vop3.opsel == 1 ||
   1790              vop3.opsel == 2)
   1791             return false;
   1792          neg[i] = vop3.neg[0];
   1793          abs[i] = vop3.abs[0];
   1794          opsel |= (vop3.opsel & 1) << i;
   1795       } else if (op_instr[i]->isSDWA()) {
   1796          return false;
   1797       }
   1798 
   1799       Temp op0 = op_instr[i]->operands[0].getTemp();
   1800       Temp op1 = op_instr[i]->operands[1].getTemp();
   1801       if (original_temp_id(ctx, op0) != original_temp_id(ctx, op1))
   1802          return false;
   1803 
   1804       op[i] = op1;
   1805       bitsize = op_bitsize;
   1806    }
   1807 
   1808    if (op[1].type() == RegType::sgpr)
   1809       std::swap(op[0], op[1]);
   1810    unsigned num_sgprs = (op[0].type() == RegType::sgpr) + (op[1].type() == RegType::sgpr);
   1811    if (num_sgprs > (ctx.program->chip_class >= GFX10 ? 2 : 1))
   1812       return false;
   1813 
   1814    ctx.uses[op[0].id()]++;
   1815    ctx.uses[op[1].id()]++;
   1816    decrease_uses(ctx, op_instr[0]);
   1817    decrease_uses(ctx, op_instr[1]);
   1818 
   1819    aco_opcode new_op = aco_opcode::num_opcodes;
   1820    switch (bitsize) {
   1821    case 16: new_op = is_or ? aco_opcode::v_cmp_u_f16 : aco_opcode::v_cmp_o_f16; break;
   1822    case 32: new_op = is_or ? aco_opcode::v_cmp_u_f32 : aco_opcode::v_cmp_o_f32; break;
   1823    case 64: new_op = is_or ? aco_opcode::v_cmp_u_f64 : aco_opcode::v_cmp_o_f64; break;
   1824    }
   1825    Instruction* new_instr;
   1826    if (neg[0] || neg[1] || abs[0] || abs[1] || opsel || num_sgprs > 1) {
   1827       VOP3_instruction* vop3 =
   1828          create_instruction<VOP3_instruction>(new_op, asVOP3(Format::VOPC), 2, 1);
   1829       for (unsigned i = 0; i < 2; i++) {
   1830          vop3->neg[i] = neg[i];
   1831          vop3->abs[i] = abs[i];
   1832       }
   1833       vop3->opsel = opsel;
   1834       new_instr = static_cast<Instruction*>(vop3);
   1835    } else {
   1836       new_instr = create_instruction<VOPC_instruction>(new_op, Format::VOPC, 2, 1);
   1837       instr->definitions[0].setHint(vcc);
   1838    }
   1839    new_instr->operands[0] = Operand(op[0]);
   1840    new_instr->operands[1] = Operand(op[1]);
   1841    new_instr->definitions[0] = instr->definitions[0];
   1842 
   1843    ctx.info[instr->definitions[0].tempId()].label = 0;
   1844    ctx.info[instr->definitions[0].tempId()].set_vopc(new_instr);
   1845 
   1846    instr.reset(new_instr);
   1847 
   1848    return true;
   1849 }
   1850 
   1851 /* s_or_b64(v_cmp_u_f32(a, b), cmp(a, b)) -> get_unordered(cmp)(a, b)
   1852  * s_and_b64(v_cmp_o_f32(a, b), cmp(a, b)) -> get_ordered(cmp)(a, b) */
   1853 bool
   1854 combine_comparison_ordering(opt_ctx& ctx, aco_ptr<Instruction>& instr)
   1855 {
   1856    if (instr->definitions[0].regClass() != ctx.program->lane_mask)
   1857       return false;
   1858    if (instr->definitions[1].isTemp() && ctx.uses[instr->definitions[1].tempId()])
   1859       return false;
   1860 
   1861    bool is_or = instr->opcode == aco_opcode::s_or_b64 || instr->opcode == aco_opcode::s_or_b32;
   1862    aco_opcode expected_nan_test = is_or ? aco_opcode::v_cmp_u_f32 : aco_opcode::v_cmp_o_f32;
   1863 
   1864    Instruction* nan_test = follow_operand(ctx, instr->operands[0], true);
   1865    Instruction* cmp = follow_operand(ctx, instr->operands[1], true);
   1866    if (!nan_test || !cmp)
   1867       return false;
   1868    if (nan_test->isSDWA() || cmp->isSDWA())
   1869       return false;
   1870 
   1871    if (get_f32_cmp(cmp->opcode) == expected_nan_test)
   1872       std::swap(nan_test, cmp);
   1873    else if (get_f32_cmp(nan_test->opcode) != expected_nan_test)
   1874       return false;
   1875 
   1876    if (!is_cmp(cmp->opcode) || get_cmp_bitsize(cmp->opcode) != get_cmp_bitsize(nan_test->opcode))
   1877       return false;
   1878 
   1879    if (!nan_test->operands[0].isTemp() || !nan_test->operands[1].isTemp())
   1880       return false;
   1881    if (!cmp->operands[0].isTemp() || !cmp->operands[1].isTemp())
   1882       return false;
   1883 
   1884    unsigned prop_cmp0 = original_temp_id(ctx, cmp->operands[0].getTemp());
   1885    unsigned prop_cmp1 = original_temp_id(ctx, cmp->operands[1].getTemp());
   1886    unsigned prop_nan0 = original_temp_id(ctx, nan_test->operands[0].getTemp());
   1887    unsigned prop_nan1 = original_temp_id(ctx, nan_test->operands[1].getTemp());
   1888    if (prop_cmp0 != prop_nan0 && prop_cmp0 != prop_nan1)
   1889       return false;
   1890    if (prop_cmp1 != prop_nan0 && prop_cmp1 != prop_nan1)
   1891       return false;
   1892 
   1893    ctx.uses[cmp->operands[0].tempId()]++;
   1894    ctx.uses[cmp->operands[1].tempId()]++;
   1895    decrease_uses(ctx, nan_test);
   1896    decrease_uses(ctx, cmp);
   1897 
   1898    aco_opcode new_op = is_or ? get_unordered(cmp->opcode) : get_ordered(cmp->opcode);
   1899    Instruction* new_instr;
   1900    if (cmp->isVOP3()) {
   1901       VOP3_instruction* new_vop3 =
   1902          create_instruction<VOP3_instruction>(new_op, asVOP3(Format::VOPC), 2, 1);
   1903       VOP3_instruction& cmp_vop3 = cmp->vop3();
   1904       memcpy(new_vop3->abs, cmp_vop3.abs, sizeof(new_vop3->abs));
   1905       memcpy(new_vop3->neg, cmp_vop3.neg, sizeof(new_vop3->neg));
   1906       new_vop3->clamp = cmp_vop3.clamp;
   1907       new_vop3->omod = cmp_vop3.omod;
   1908       new_vop3->opsel = cmp_vop3.opsel;
   1909       new_instr = new_vop3;
   1910    } else {
   1911       new_instr = create_instruction<VOPC_instruction>(new_op, Format::VOPC, 2, 1);
   1912       instr->definitions[0].setHint(vcc);
   1913    }
   1914    new_instr->operands[0] = cmp->operands[0];
   1915    new_instr->operands[1] = cmp->operands[1];
   1916    new_instr->definitions[0] = instr->definitions[0];
   1917 
   1918    ctx.info[instr->definitions[0].tempId()].label = 0;
   1919    ctx.info[instr->definitions[0].tempId()].set_vopc(new_instr);
   1920 
   1921    instr.reset(new_instr);
   1922 
   1923    return true;
   1924 }
   1925 
   1926 bool
   1927 is_operand_constant(opt_ctx& ctx, Operand op, unsigned bit_size, uint64_t* value)
   1928 {
   1929    if (op.isConstant()) {
   1930       *value = op.constantValue64();
   1931       return true;
   1932    } else if (op.isTemp()) {
   1933       unsigned id = original_temp_id(ctx, op.getTemp());
   1934       if (!ctx.info[id].is_constant_or_literal(bit_size))
   1935          return false;
   1936       *value = get_constant_op(ctx, ctx.info[id], bit_size).constantValue64();
   1937       return true;
   1938    }
   1939    return false;
   1940 }
   1941 
   1942 bool
   1943 is_constant_nan(uint64_t value, unsigned bit_size)
   1944 {
   1945    if (bit_size == 16)
   1946       return ((value >> 10) & 0x1f) == 0x1f && (value & 0x3ff);
   1947    else if (bit_size == 32)
   1948       return ((value >> 23) & 0xff) == 0xff && (value & 0x7fffff);
   1949    else
   1950       return ((value >> 52) & 0x7ff) == 0x7ff && (value & 0xfffffffffffff);
   1951 }
   1952 
   1953 /* s_or_b64(v_cmp_neq_f32(a, a), cmp(a, #b)) and b is not NaN -> get_unordered(cmp)(a, b)
   1954  * s_and_b64(v_cmp_eq_f32(a, a), cmp(a, #b)) and b is not NaN -> get_ordered(cmp)(a, b) */
   1955 bool
   1956 combine_constant_comparison_ordering(opt_ctx& ctx, aco_ptr<Instruction>& instr)
   1957 {
   1958    if (instr->definitions[0].regClass() != ctx.program->lane_mask)
   1959       return false;
   1960    if (instr->definitions[1].isTemp() && ctx.uses[instr->definitions[1].tempId()])
   1961       return false;
   1962 
   1963    bool is_or = instr->opcode == aco_opcode::s_or_b64 || instr->opcode == aco_opcode::s_or_b32;
   1964 
   1965    Instruction* nan_test = follow_operand(ctx, instr->operands[0], true);
   1966    Instruction* cmp = follow_operand(ctx, instr->operands[1], true);
   1967 
   1968    if (!nan_test || !cmp || nan_test->isSDWA() || cmp->isSDWA())
   1969       return false;
   1970    if (nan_test->isSDWA() || cmp->isSDWA())
   1971       return false;
   1972 
   1973    aco_opcode expected_nan_test = is_or ? aco_opcode::v_cmp_neq_f32 : aco_opcode::v_cmp_eq_f32;
   1974    if (get_f32_cmp(cmp->opcode) == expected_nan_test)
   1975       std::swap(nan_test, cmp);
   1976    else if (get_f32_cmp(nan_test->opcode) != expected_nan_test)
   1977       return false;
   1978 
   1979    unsigned bit_size = get_cmp_bitsize(cmp->opcode);
   1980    if (!is_cmp(cmp->opcode) || get_cmp_bitsize(nan_test->opcode) != bit_size)
   1981       return false;
   1982 
   1983    if (!nan_test->operands[0].isTemp() || !nan_test->operands[1].isTemp())
   1984       return false;
   1985    if (!cmp->operands[0].isTemp() && !cmp->operands[1].isTemp())
   1986       return false;
   1987 
   1988    unsigned prop_nan0 = original_temp_id(ctx, nan_test->operands[0].getTemp());
   1989    unsigned prop_nan1 = original_temp_id(ctx, nan_test->operands[1].getTemp());
   1990    if (prop_nan0 != prop_nan1)
   1991       return false;
   1992 
   1993    if (nan_test->isVOP3()) {
   1994       VOP3_instruction& vop3 = nan_test->vop3();
   1995       if (vop3.neg[0] != vop3.neg[1] || vop3.abs[0] != vop3.abs[1] || vop3.opsel == 1 ||
   1996           vop3.opsel == 2)
   1997          return false;
   1998    }
   1999 
   2000    int constant_operand = -1;
   2001    for (unsigned i = 0; i < 2; i++) {
   2002       if (cmp->operands[i].isTemp() &&
   2003           original_temp_id(ctx, cmp->operands[i].getTemp()) == prop_nan0) {
   2004          constant_operand = !i;
   2005          break;
   2006       }
   2007    }
   2008    if (constant_operand == -1)
   2009       return false;
   2010 
   2011    uint64_t constant_value;
   2012    if (!is_operand_constant(ctx, cmp->operands[constant_operand], bit_size, &constant_value))
   2013       return false;
   2014    if (is_constant_nan(constant_value, bit_size))
   2015       return false;
   2016 
   2017    if (cmp->operands[0].isTemp())
   2018       ctx.uses[cmp->operands[0].tempId()]++;
   2019    if (cmp->operands[1].isTemp())
   2020       ctx.uses[cmp->operands[1].tempId()]++;
   2021    decrease_uses(ctx, nan_test);
   2022    decrease_uses(ctx, cmp);
   2023 
   2024    aco_opcode new_op = is_or ? get_unordered(cmp->opcode) : get_ordered(cmp->opcode);
   2025    Instruction* new_instr;
   2026    if (cmp->isVOP3()) {
   2027       VOP3_instruction* new_vop3 =
   2028          create_instruction<VOP3_instruction>(new_op, asVOP3(Format::VOPC), 2, 1);
   2029       VOP3_instruction& cmp_vop3 = cmp->vop3();
   2030       memcpy(new_vop3->abs, cmp_vop3.abs, sizeof(new_vop3->abs));
   2031       memcpy(new_vop3->neg, cmp_vop3.neg, sizeof(new_vop3->neg));
   2032       new_vop3->clamp = cmp_vop3.clamp;
   2033       new_vop3->omod = cmp_vop3.omod;
   2034       new_vop3->opsel = cmp_vop3.opsel;
   2035       new_instr = new_vop3;
   2036    } else {
   2037       new_instr = create_instruction<VOPC_instruction>(new_op, Format::VOPC, 2, 1);
   2038       instr->definitions[0].setHint(vcc);
   2039    }
   2040    new_instr->operands[0] = cmp->operands[0];
   2041    new_instr->operands[1] = cmp->operands[1];
   2042    new_instr->definitions[0] = instr->definitions[0];
   2043 
   2044    ctx.info[instr->definitions[0].tempId()].label = 0;
   2045    ctx.info[instr->definitions[0].tempId()].set_vopc(new_instr);
   2046 
   2047    instr.reset(new_instr);
   2048 
   2049    return true;
   2050 }
   2051 
   2052 /* s_andn2(exec, cmp(a, b)) -> get_inverse(cmp)(a, b) */
   2053 bool
   2054 combine_inverse_comparison(opt_ctx& ctx, aco_ptr<Instruction>& instr)
   2055 {
   2056    if (!instr->operands[0].isFixed() || instr->operands[0].physReg() != exec)
   2057       return false;
   2058    if (ctx.uses[instr->definitions[1].tempId()])
   2059       return false;
   2060 
   2061    Instruction* cmp = follow_operand(ctx, instr->operands[1]);
   2062    if (!cmp)
   2063       return false;
   2064 
   2065    aco_opcode new_opcode = get_inverse(cmp->opcode);
   2066    if (new_opcode == aco_opcode::num_opcodes)
   2067       return false;
   2068 
   2069    if (cmp->operands[0].isTemp())
   2070       ctx.uses[cmp->operands[0].tempId()]++;
   2071    if (cmp->operands[1].isTemp())
   2072       ctx.uses[cmp->operands[1].tempId()]++;
   2073    decrease_uses(ctx, cmp);
   2074 
   2075    /* This creates a new instruction instead of modifying the existing
   2076     * comparison so that the comparison is done with the correct exec mask. */
   2077    Instruction* new_instr;
   2078    if (cmp->isVOP3()) {
   2079       VOP3_instruction* new_vop3 =
   2080          create_instruction<VOP3_instruction>(new_opcode, asVOP3(Format::VOPC), 2, 1);
   2081       VOP3_instruction& cmp_vop3 = cmp->vop3();
   2082       memcpy(new_vop3->abs, cmp_vop3.abs, sizeof(new_vop3->abs));
   2083       memcpy(new_vop3->neg, cmp_vop3.neg, sizeof(new_vop3->neg));
   2084       new_vop3->clamp = cmp_vop3.clamp;
   2085       new_vop3->omod = cmp_vop3.omod;
   2086       new_vop3->opsel = cmp_vop3.opsel;
   2087       new_instr = new_vop3;
   2088    } else if (cmp->isSDWA()) {
   2089       SDWA_instruction* new_sdwa = create_instruction<SDWA_instruction>(
   2090          new_opcode, (Format)((uint16_t)Format::SDWA | (uint16_t)Format::VOPC), 2, 1);
   2091       SDWA_instruction& cmp_sdwa = cmp->sdwa();
   2092       memcpy(new_sdwa->abs, cmp_sdwa.abs, sizeof(new_sdwa->abs));
   2093       memcpy(new_sdwa->sel, cmp_sdwa.sel, sizeof(new_sdwa->sel));
   2094       memcpy(new_sdwa->neg, cmp_sdwa.neg, sizeof(new_sdwa->neg));
   2095       new_sdwa->dst_sel = cmp_sdwa.dst_sel;
   2096       new_sdwa->clamp = cmp_sdwa.clamp;
   2097       new_sdwa->omod = cmp_sdwa.omod;
   2098       new_instr = new_sdwa;
   2099    } else if (cmp->isDPP()) {
   2100       DPP_instruction* new_dpp = create_instruction<DPP_instruction>(
   2101          new_opcode, (Format)((uint16_t)Format::DPP | (uint16_t)Format::VOPC), 2, 1);
   2102       DPP_instruction& cmp_dpp = cmp->dpp();
   2103       memcpy(new_dpp->abs, cmp_dpp.abs, sizeof(new_dpp->abs));
   2104       memcpy(new_dpp->neg, cmp_dpp.neg, sizeof(new_dpp->neg));
   2105       new_dpp->dpp_ctrl = cmp_dpp.dpp_ctrl;
   2106       new_dpp->row_mask = cmp_dpp.row_mask;
   2107       new_dpp->bank_mask = cmp_dpp.bank_mask;
   2108       new_dpp->bound_ctrl = cmp_dpp.bound_ctrl;
   2109       new_instr = new_dpp;
   2110    } else {
   2111       new_instr = create_instruction<VOPC_instruction>(new_opcode, Format::VOPC, 2, 1);
   2112       instr->definitions[0].setHint(vcc);
   2113    }
   2114    new_instr->operands[0] = cmp->operands[0];
   2115    new_instr->operands[1] = cmp->operands[1];
   2116    new_instr->definitions[0] = instr->definitions[0];
   2117 
   2118    ctx.info[instr->definitions[0].tempId()].label = 0;
   2119    ctx.info[instr->definitions[0].tempId()].set_vopc(new_instr);
   2120 
   2121    instr.reset(new_instr);
   2122 
   2123    return true;
   2124 }
   2125 
   2126 /* op1(op2(1, 2), 0) if swap = false
   2127  * op1(0, op2(1, 2)) if swap = true */
   2128 bool
   2129 match_op3_for_vop3(opt_ctx& ctx, aco_opcode op1, aco_opcode op2, Instruction* op1_instr, bool swap,
   2130                    const char* shuffle_str, Operand operands[3], bool neg[3], bool abs[3],
   2131                    uint8_t* opsel, bool* op1_clamp, uint8_t* op1_omod, bool* inbetween_neg,
   2132                    bool* inbetween_abs, bool* inbetween_opsel, bool* precise)
   2133 {
   2134    /* checks */
   2135    if (op1_instr->opcode != op1)
   2136       return false;
   2137 
   2138    Instruction* op2_instr = follow_operand(ctx, op1_instr->operands[swap]);
   2139    if (!op2_instr || op2_instr->opcode != op2)
   2140       return false;
   2141    if (fixed_to_exec(op2_instr->operands[0]) || fixed_to_exec(op2_instr->operands[1]))
   2142       return false;
   2143 
   2144    VOP3_instruction* op1_vop3 = op1_instr->isVOP3() ? &op1_instr->vop3() : NULL;
   2145    VOP3_instruction* op2_vop3 = op2_instr->isVOP3() ? &op2_instr->vop3() : NULL;
   2146 
   2147    if (op1_instr->isSDWA() || op2_instr->isSDWA())
   2148       return false;
   2149    if (op1_instr->isDPP() || op2_instr->isDPP())
   2150       return false;
   2151 
   2152    /* don't support inbetween clamp/omod */
   2153    if (op2_vop3 && (op2_vop3->clamp || op2_vop3->omod))
   2154       return false;
   2155 
   2156    /* get operands and modifiers and check inbetween modifiers */
   2157    *op1_clamp = op1_vop3 ? op1_vop3->clamp : false;
   2158    *op1_omod = op1_vop3 ? op1_vop3->omod : 0u;
   2159 
   2160    if (inbetween_neg)
   2161       *inbetween_neg = op1_vop3 ? op1_vop3->neg[swap] : false;
   2162    else if (op1_vop3 && op1_vop3->neg[swap])
   2163       return false;
   2164 
   2165    if (inbetween_abs)
   2166       *inbetween_abs = op1_vop3 ? op1_vop3->abs[swap] : false;
   2167    else if (op1_vop3 && op1_vop3->abs[swap])
   2168       return false;
   2169 
   2170    if (inbetween_opsel)
   2171       *inbetween_opsel = op1_vop3 ? op1_vop3->opsel & (1 << (unsigned)swap) : false;
   2172    else if (op1_vop3 && op1_vop3->opsel & (1 << (unsigned)swap))
   2173       return false;
   2174 
   2175    *precise = op1_instr->definitions[0].isPrecise() || op2_instr->definitions[0].isPrecise();
   2176 
   2177    int shuffle[3];
   2178    shuffle[shuffle_str[0] - '0'] = 0;
   2179    shuffle[shuffle_str[1] - '0'] = 1;
   2180    shuffle[shuffle_str[2] - '0'] = 2;
   2181 
   2182    operands[shuffle[0]] = op1_instr->operands[!swap];
   2183    neg[shuffle[0]] = op1_vop3 ? op1_vop3->neg[!swap] : false;
   2184    abs[shuffle[0]] = op1_vop3 ? op1_vop3->abs[!swap] : false;
   2185    if (op1_vop3 && (op1_vop3->opsel & (1 << (unsigned)!swap)))
   2186       *opsel |= 1 << shuffle[0];
   2187 
   2188    for (unsigned i = 0; i < 2; i++) {
   2189       operands[shuffle[i + 1]] = op2_instr->operands[i];
   2190       neg[shuffle[i + 1]] = op2_vop3 ? op2_vop3->neg[i] : false;
   2191       abs[shuffle[i + 1]] = op2_vop3 ? op2_vop3->abs[i] : false;
   2192       if (op2_vop3 && op2_vop3->opsel & (1 << i))
   2193          *opsel |= 1 << shuffle[i + 1];
   2194    }
   2195 
   2196    /* check operands */
   2197    if (!check_vop3_operands(ctx, 3, operands))
   2198       return false;
   2199 
   2200    return true;
   2201 }
   2202 
   2203 void
   2204 create_vop3_for_op3(opt_ctx& ctx, aco_opcode opcode, aco_ptr<Instruction>& instr,
   2205                     Operand operands[3], bool neg[3], bool abs[3], uint8_t opsel, bool clamp,
   2206                     unsigned omod)
   2207 {
   2208    VOP3_instruction* new_instr = create_instruction<VOP3_instruction>(opcode, Format::VOP3, 3, 1);
   2209    memcpy(new_instr->abs, abs, sizeof(bool[3]));
   2210    memcpy(new_instr->neg, neg, sizeof(bool[3]));
   2211    new_instr->clamp = clamp;
   2212    new_instr->omod = omod;
   2213    new_instr->opsel = opsel;
   2214    new_instr->operands[0] = operands[0];
   2215    new_instr->operands[1] = operands[1];
   2216    new_instr->operands[2] = operands[2];
   2217    new_instr->definitions[0] = instr->definitions[0];
   2218    ctx.info[instr->definitions[0].tempId()].label = 0;
   2219 
   2220    instr.reset(new_instr);
   2221 }
   2222 
   2223 bool
   2224 combine_three_valu_op(opt_ctx& ctx, aco_ptr<Instruction>& instr, aco_opcode op2, aco_opcode new_op,
   2225                       const char* shuffle, uint8_t ops)
   2226 {
   2227    for (unsigned swap = 0; swap < 2; swap++) {
   2228       if (!((1 << swap) & ops))
   2229          continue;
   2230 
   2231       Operand operands[3];
   2232       bool neg[3], abs[3], clamp, precise;
   2233       uint8_t opsel = 0, omod = 0;
   2234       if (match_op3_for_vop3(ctx, instr->opcode, op2, instr.get(), swap, shuffle, operands, neg,
   2235                              abs, &opsel, &clamp, &omod, NULL, NULL, NULL, &precise)) {
   2236          ctx.uses[instr->operands[swap].tempId()]--;
   2237          create_vop3_for_op3(ctx, new_op, instr, operands, neg, abs, opsel, clamp, omod);
   2238          return true;
   2239       }
   2240    }
   2241    return false;
   2242 }
   2243 
   2244 /* creates v_lshl_add_u32, v_lshl_or_b32 or v_and_or_b32 */
   2245 bool
   2246 combine_add_or_then_and_lshl(opt_ctx& ctx, aco_ptr<Instruction>& instr)
   2247 {
   2248    bool is_or = instr->opcode == aco_opcode::v_or_b32;
   2249    aco_opcode new_op_lshl = is_or ? aco_opcode::v_lshl_or_b32 : aco_opcode::v_lshl_add_u32;
   2250 
   2251    if (is_or && combine_three_valu_op(ctx, instr, aco_opcode::s_and_b32, aco_opcode::v_and_or_b32,
   2252                                       "120", 1 | 2))
   2253       return true;
   2254    if (is_or && combine_three_valu_op(ctx, instr, aco_opcode::v_and_b32, aco_opcode::v_and_or_b32,
   2255                                       "120", 1 | 2))
   2256       return true;
   2257    if (combine_three_valu_op(ctx, instr, aco_opcode::s_lshl_b32, new_op_lshl, "120", 1 | 2))
   2258       return true;
   2259    if (combine_three_valu_op(ctx, instr, aco_opcode::v_lshlrev_b32, new_op_lshl, "210", 1 | 2))
   2260       return true;
   2261 
   2262    if (instr->isSDWA() || instr->isDPP())
   2263       return false;
   2264 
   2265    /* v_or_b32(p_extract(a, 0, 8/16, 0), b) -> v_and_or_b32(a, 0xff/0xffff, b)
   2266     * v_or_b32(p_insert(a, 0, 8/16), b) -> v_and_or_b32(a, 0xff/0xffff, b)
   2267     * v_or_b32(p_insert(a, 24/16, 8/16), b) -> v_lshl_or_b32(a, 24/16, b)
   2268     * v_add_u32(p_insert(a, 24/16, 8/16), b) -> v_lshl_add_b32(a, 24/16, b)
   2269     */
   2270    for (unsigned i = 0; i < 2; i++) {
   2271       Instruction* extins = follow_operand(ctx, instr->operands[i]);
   2272       if (!extins)
   2273          continue;
   2274 
   2275       aco_opcode op;
   2276       Operand operands[3];
   2277 
   2278       if (extins->opcode == aco_opcode::p_insert &&
   2279           (extins->operands[1].constantValue() + 1) * extins->operands[2].constantValue() == 32) {
   2280          op = new_op_lshl;
   2281          operands[1] =
   2282             Operand::c32(extins->operands[1].constantValue() * extins->operands[2].constantValue());
   2283       } else if (is_or &&
   2284                  (extins->opcode == aco_opcode::p_insert ||
   2285                   (extins->opcode == aco_opcode::p_extract &&
   2286                    extins->operands[3].constantEquals(0))) &&
   2287                  extins->operands[1].constantEquals(0)) {
   2288          op = aco_opcode::v_and_or_b32;
   2289          operands[1] = Operand::c32(extins->operands[2].constantEquals(8) ? 0xffu : 0xffffu);
   2290       } else {
   2291          continue;
   2292       }
   2293 
   2294       operands[0] = extins->operands[0];
   2295       operands[2] = instr->operands[!i];
   2296 
   2297       if (!check_vop3_operands(ctx, 3, operands))
   2298          continue;
   2299 
   2300       bool neg[3] = {}, abs[3] = {};
   2301       uint8_t opsel = 0, omod = 0;
   2302       bool clamp = false;
   2303       if (instr->isVOP3())
   2304          clamp = instr->vop3().clamp;
   2305 
   2306       ctx.uses[instr->operands[i].tempId()]--;
   2307       create_vop3_for_op3(ctx, op, instr, operands, neg, abs, opsel, clamp, omod);
   2308       return true;
   2309    }
   2310 
   2311    return false;
   2312 }
   2313 
   2314 bool
   2315 combine_minmax(opt_ctx& ctx, aco_ptr<Instruction>& instr, aco_opcode opposite, aco_opcode minmax3)
   2316 {
   2317    /* TODO: this can handle SDWA min/max instructions by using opsel */
   2318    if (combine_three_valu_op(ctx, instr, instr->opcode, minmax3, "012", 1 | 2))
   2319       return true;
   2320 
   2321    /* min(-max(a, b), c) -> min3(c, -a, -b) *
   2322     * max(-min(a, b), c) -> max3(c, -a, -b) */
   2323    for (unsigned swap = 0; swap < 2; swap++) {
   2324       Operand operands[3];
   2325       bool neg[3], abs[3], clamp, precise;
   2326       uint8_t opsel = 0, omod = 0;
   2327       bool inbetween_neg;
   2328       if (match_op3_for_vop3(ctx, instr->opcode, opposite, instr.get(), swap, "012", operands, neg,
   2329                              abs, &opsel, &clamp, &omod, &inbetween_neg, NULL, NULL, &precise) &&
   2330           inbetween_neg) {
   2331          ctx.uses[instr->operands[swap].tempId()]--;
   2332          neg[1] = !neg[1];
   2333          neg[2] = !neg[2];
   2334          create_vop3_for_op3(ctx, minmax3, instr, operands, neg, abs, opsel, clamp, omod);
   2335          return true;
   2336       }
   2337    }
   2338    return false;
   2339 }
   2340 
   2341 /* s_not_b32(s_and_b32(a, b)) -> s_nand_b32(a, b)
   2342  * s_not_b32(s_or_b32(a, b)) -> s_nor_b32(a, b)
   2343  * s_not_b32(s_xor_b32(a, b)) -> s_xnor_b32(a, b)
   2344  * s_not_b64(s_and_b64(a, b)) -> s_nand_b64(a, b)
   2345  * s_not_b64(s_or_b64(a, b)) -> s_nor_b64(a, b)
   2346  * s_not_b64(s_xor_b64(a, b)) -> s_xnor_b64(a, b) */
   2347 bool
   2348 combine_salu_not_bitwise(opt_ctx& ctx, aco_ptr<Instruction>& instr)
   2349 {
   2350    /* checks */
   2351    if (!instr->operands[0].isTemp())
   2352       return false;
   2353    if (instr->definitions[1].isTemp() && ctx.uses[instr->definitions[1].tempId()])
   2354       return false;
   2355 
   2356    Instruction* op2_instr = follow_operand(ctx, instr->operands[0]);
   2357    if (!op2_instr)
   2358       return false;
   2359    switch (op2_instr->opcode) {
   2360    case aco_opcode::s_and_b32:
   2361    case aco_opcode::s_or_b32:
   2362    case aco_opcode::s_xor_b32:
   2363    case aco_opcode::s_and_b64:
   2364    case aco_opcode::s_or_b64:
   2365    case aco_opcode::s_xor_b64: break;
   2366    default: return false;
   2367    }
   2368 
   2369    /* create instruction */
   2370    std::swap(instr->definitions[0], op2_instr->definitions[0]);
   2371    std::swap(instr->definitions[1], op2_instr->definitions[1]);
   2372    ctx.uses[instr->operands[0].tempId()]--;
   2373    ctx.info[op2_instr->definitions[0].tempId()].label = 0;
   2374 
   2375    switch (op2_instr->opcode) {
   2376    case aco_opcode::s_and_b32: op2_instr->opcode = aco_opcode::s_nand_b32; break;
   2377    case aco_opcode::s_or_b32: op2_instr->opcode = aco_opcode::s_nor_b32; break;
   2378    case aco_opcode::s_xor_b32: op2_instr->opcode = aco_opcode::s_xnor_b32; break;
   2379    case aco_opcode::s_and_b64: op2_instr->opcode = aco_opcode::s_nand_b64; break;
   2380    case aco_opcode::s_or_b64: op2_instr->opcode = aco_opcode::s_nor_b64; break;
   2381    case aco_opcode::s_xor_b64: op2_instr->opcode = aco_opcode::s_xnor_b64; break;
   2382    default: break;
   2383    }
   2384 
   2385    return true;
   2386 }
   2387 
   2388 /* s_and_b32(a, s_not_b32(b)) -> s_andn2_b32(a, b)
   2389  * s_or_b32(a, s_not_b32(b)) -> s_orn2_b32(a, b)
   2390  * s_and_b64(a, s_not_b64(b)) -> s_andn2_b64(a, b)
   2391  * s_or_b64(a, s_not_b64(b)) -> s_orn2_b64(a, b) */
   2392 bool
   2393 combine_salu_n2(opt_ctx& ctx, aco_ptr<Instruction>& instr)
   2394 {
   2395    if (instr->definitions[0].isTemp() && ctx.info[instr->definitions[0].tempId()].is_uniform_bool())
   2396       return false;
   2397 
   2398    for (unsigned i = 0; i < 2; i++) {
   2399       Instruction* op2_instr = follow_operand(ctx, instr->operands[i]);
   2400       if (!op2_instr || (op2_instr->opcode != aco_opcode::s_not_b32 &&
   2401                          op2_instr->opcode != aco_opcode::s_not_b64))
   2402          continue;
   2403       if (ctx.uses[op2_instr->definitions[1].tempId()] || fixed_to_exec(op2_instr->operands[0]))
   2404          continue;
   2405 
   2406       if (instr->operands[!i].isLiteral() && op2_instr->operands[0].isLiteral() &&
   2407           instr->operands[!i].constantValue() != op2_instr->operands[0].constantValue())
   2408          continue;
   2409 
   2410       ctx.uses[instr->operands[i].tempId()]--;
   2411       instr->operands[0] = instr->operands[!i];
   2412       instr->operands[1] = op2_instr->operands[0];
   2413       ctx.info[instr->definitions[0].tempId()].label = 0;
   2414 
   2415       switch (instr->opcode) {
   2416       case aco_opcode::s_and_b32: instr->opcode = aco_opcode::s_andn2_b32; break;
   2417       case aco_opcode::s_or_b32: instr->opcode = aco_opcode::s_orn2_b32; break;
   2418       case aco_opcode::s_and_b64: instr->opcode = aco_opcode::s_andn2_b64; break;
   2419       case aco_opcode::s_or_b64: instr->opcode = aco_opcode::s_orn2_b64; break;
   2420       default: break;
   2421       }
   2422 
   2423       return true;
   2424    }
   2425    return false;
   2426 }
   2427 
   2428 /* s_add_{i32,u32}(a, s_lshl_b32(b, <n>)) -> s_lshl<n>_add_u32(a, b) */
   2429 bool
   2430 combine_salu_lshl_add(opt_ctx& ctx, aco_ptr<Instruction>& instr)
   2431 {
   2432    if (instr->opcode == aco_opcode::s_add_i32 && ctx.uses[instr->definitions[1].tempId()])
   2433       return false;
   2434 
   2435    for (unsigned i = 0; i < 2; i++) {
   2436       Instruction* op2_instr = follow_operand(ctx, instr->operands[i], true);
   2437       if (!op2_instr || op2_instr->opcode != aco_opcode::s_lshl_b32 ||
   2438           ctx.uses[op2_instr->definitions[1].tempId()])
   2439          continue;
   2440       if (!op2_instr->operands[1].isConstant() || fixed_to_exec(op2_instr->operands[0]))
   2441          continue;
   2442 
   2443       uint32_t shift = op2_instr->operands[1].constantValue();
   2444       if (shift < 1 || shift > 4)
   2445          continue;
   2446 
   2447       if (instr->operands[!i].isLiteral() && op2_instr->operands[0].isLiteral() &&
   2448           instr->operands[!i].constantValue() != op2_instr->operands[0].constantValue())
   2449          continue;
   2450 
   2451       ctx.uses[instr->operands[i].tempId()]--;
   2452       instr->operands[1] = instr->operands[!i];
   2453       instr->operands[0] = op2_instr->operands[0];
   2454       ctx.info[instr->definitions[0].tempId()].label = 0;
   2455 
   2456       instr->opcode = std::array<aco_opcode, 4>{
   2457          aco_opcode::s_lshl1_add_u32, aco_opcode::s_lshl2_add_u32, aco_opcode::s_lshl3_add_u32,
   2458          aco_opcode::s_lshl4_add_u32}[shift - 1];
   2459 
   2460       return true;
   2461    }
   2462    return false;
   2463 }
   2464 
   2465 bool
   2466 combine_add_sub_b2i(opt_ctx& ctx, aco_ptr<Instruction>& instr, aco_opcode new_op, uint8_t ops)
   2467 {
   2468    if (instr->usesModifiers())
   2469       return false;
   2470 
   2471    for (unsigned i = 0; i < 2; i++) {
   2472       if (!((1 << i) & ops))
   2473          continue;
   2474       if (instr->operands[i].isTemp() && ctx.info[instr->operands[i].tempId()].is_b2i() &&
   2475           ctx.uses[instr->operands[i].tempId()] == 1) {
   2476 
   2477          aco_ptr<Instruction> new_instr;
   2478          if (instr->operands[!i].isTemp() &&
   2479              instr->operands[!i].getTemp().type() == RegType::vgpr) {
   2480             new_instr.reset(create_instruction<VOP2_instruction>(new_op, Format::VOP2, 3, 2));
   2481          } else if (ctx.program->chip_class >= GFX10 ||
   2482                     (instr->operands[!i].isConstant() && !instr->operands[!i].isLiteral())) {
   2483             new_instr.reset(
   2484                create_instruction<VOP3_instruction>(new_op, asVOP3(Format::VOP2), 3, 2));
   2485          } else {
   2486             return false;
   2487          }
   2488          ctx.uses[instr->operands[i].tempId()]--;
   2489          new_instr->definitions[0] = instr->definitions[0];
   2490          if (instr->definitions.size() == 2) {
   2491             new_instr->definitions[1] = instr->definitions[1];
   2492          } else {
   2493             new_instr->definitions[1] =
   2494                Definition(ctx.program->allocateTmp(ctx.program->lane_mask));
   2495             /* Make sure the uses vector is large enough and the number of
   2496              * uses properly initialized to 0.
   2497              */
   2498             ctx.uses.push_back(0);
   2499          }
   2500          new_instr->definitions[1].setHint(vcc);
   2501          new_instr->operands[0] = Operand::zero();
   2502          new_instr->operands[1] = instr->operands[!i];
   2503          new_instr->operands[2] = Operand(ctx.info[instr->operands[i].tempId()].temp);
   2504          instr = std::move(new_instr);
   2505          ctx.info[instr->definitions[0].tempId()].set_add_sub(instr.get());
   2506          return true;
   2507       }
   2508    }
   2509 
   2510    return false;
   2511 }
   2512 
   2513 bool
   2514 combine_add_bcnt(opt_ctx& ctx, aco_ptr<Instruction>& instr)
   2515 {
   2516    if (instr->usesModifiers())
   2517       return false;
   2518 
   2519    for (unsigned i = 0; i < 2; i++) {
   2520       Instruction* op_instr = follow_operand(ctx, instr->operands[i]);
   2521       if (op_instr && op_instr->opcode == aco_opcode::v_bcnt_u32_b32 &&
   2522           !op_instr->usesModifiers() && op_instr->operands[0].isTemp() &&
   2523           op_instr->operands[0].getTemp().type() == RegType::vgpr &&
   2524           op_instr->operands[1].constantEquals(0)) {
   2525          aco_ptr<Instruction> new_instr{
   2526             create_instruction<VOP3_instruction>(aco_opcode::v_bcnt_u32_b32, Format::VOP3, 2, 1)};
   2527          ctx.uses[instr->operands[i].tempId()]--;
   2528          new_instr->operands[0] = op_instr->operands[0];
   2529          new_instr->operands[1] = instr->operands[!i];
   2530          new_instr->definitions[0] = instr->definitions[0];
   2531          instr = std::move(new_instr);
   2532          ctx.info[instr->definitions[0].tempId()].label = 0;
   2533 
   2534          return true;
   2535       }
   2536    }
   2537 
   2538    return false;
   2539 }
   2540 
   2541 bool
   2542 get_minmax_info(aco_opcode op, aco_opcode* min, aco_opcode* max, aco_opcode* min3, aco_opcode* max3,
   2543                 aco_opcode* med3, bool* some_gfx9_only)
   2544 {
   2545    switch (op) {
   2546 #define MINMAX(type, gfx9)                                                                         \
   2547    case aco_opcode::v_min_##type:                                                                  \
   2548    case aco_opcode::v_max_##type:                                                                  \
   2549    case aco_opcode::v_med3_##type:                                                                 \
   2550       *min = aco_opcode::v_min_##type;                                                             \
   2551       *max = aco_opcode::v_max_##type;                                                             \
   2552       *med3 = aco_opcode::v_med3_##type;                                                           \
   2553       *min3 = aco_opcode::v_min3_##type;                                                           \
   2554       *max3 = aco_opcode::v_max3_##type;                                                           \
   2555       *some_gfx9_only = gfx9;                                                                      \
   2556       return true;
   2557       MINMAX(f32, false)
   2558       MINMAX(u32, false)
   2559       MINMAX(i32, false)
   2560       MINMAX(f16, true)
   2561       MINMAX(u16, true)
   2562       MINMAX(i16, true)
   2563 #undef MINMAX
   2564    default: return false;
   2565    }
   2566 }
   2567 
   2568 /* when ub > lb:
   2569  * v_min_{f,u,i}{16,32}(v_max_{f,u,i}{16,32}(a, lb), ub) -> v_med3_{f,u,i}{16,32}(a, lb, ub)
   2570  * v_max_{f,u,i}{16,32}(v_min_{f,u,i}{16,32}(a, ub), lb) -> v_med3_{f,u,i}{16,32}(a, lb, ub)
   2571  */
   2572 bool
   2573 combine_clamp(opt_ctx& ctx, aco_ptr<Instruction>& instr, aco_opcode min, aco_opcode max,
   2574               aco_opcode med)
   2575 {
   2576    /* TODO: GLSL's clamp(x, minVal, maxVal) and SPIR-V's
   2577     * FClamp(x, minVal, maxVal)/NClamp(x, minVal, maxVal) are undefined if
   2578     * minVal > maxVal, which means we can always select it to a v_med3_f32 */
   2579    aco_opcode other_op;
   2580    if (instr->opcode == min)
   2581       other_op = max;
   2582    else if (instr->opcode == max)
   2583       other_op = min;
   2584    else
   2585       return false;
   2586 
   2587    for (unsigned swap = 0; swap < 2; swap++) {
   2588       Operand operands[3];
   2589       bool neg[3], abs[3], clamp, precise;
   2590       uint8_t opsel = 0, omod = 0;
   2591       if (match_op3_for_vop3(ctx, instr->opcode, other_op, instr.get(), swap, "012", operands, neg,
   2592                              abs, &opsel, &clamp, &omod, NULL, NULL, NULL, &precise)) {
   2593          /* max(min(src, upper), lower) returns upper if src is NaN, but
   2594           * med3(src, lower, upper) returns lower.
   2595           */
   2596          if (precise && instr->opcode != min)
   2597             continue;
   2598 
   2599          int const0_idx = -1, const1_idx = -1;
   2600          uint32_t const0 = 0, const1 = 0;
   2601          for (int i = 0; i < 3; i++) {
   2602             uint32_t val;
   2603             if (operands[i].isConstant()) {
   2604                val = operands[i].constantValue();
   2605             } else if (operands[i].isTemp() &&
   2606                        ctx.info[operands[i].tempId()].is_constant_or_literal(32)) {
   2607                val = ctx.info[operands[i].tempId()].val;
   2608             } else {
   2609                continue;
   2610             }
   2611             if (const0_idx >= 0) {
   2612                const1_idx = i;
   2613                const1 = val;
   2614             } else {
   2615                const0_idx = i;
   2616                const0 = val;
   2617             }
   2618          }
   2619          if (const0_idx < 0 || const1_idx < 0)
   2620             continue;
   2621 
   2622          if (opsel & (1 << const0_idx))
   2623             const0 >>= 16;
   2624          if (opsel & (1 << const1_idx))
   2625             const1 >>= 16;
   2626 
   2627          int lower_idx = const0_idx;
   2628          switch (min) {
   2629          case aco_opcode::v_min_f32:
   2630          case aco_opcode::v_min_f16: {
   2631             float const0_f, const1_f;
   2632             if (min == aco_opcode::v_min_f32) {
   2633                memcpy(&const0_f, &const0, 4);
   2634                memcpy(&const1_f, &const1, 4);
   2635             } else {
   2636                const0_f = _mesa_half_to_float(const0);
   2637                const1_f = _mesa_half_to_float(const1);
   2638             }
   2639             if (abs[const0_idx])
   2640                const0_f = fabsf(const0_f);
   2641             if (abs[const1_idx])
   2642                const1_f = fabsf(const1_f);
   2643             if (neg[const0_idx])
   2644                const0_f = -const0_f;
   2645             if (neg[const1_idx])
   2646                const1_f = -const1_f;
   2647             lower_idx = const0_f < const1_f ? const0_idx : const1_idx;
   2648             break;
   2649          }
   2650          case aco_opcode::v_min_u32: {
   2651             lower_idx = const0 < const1 ? const0_idx : const1_idx;
   2652             break;
   2653          }
   2654          case aco_opcode::v_min_u16: {
   2655             lower_idx = (uint16_t)const0 < (uint16_t)const1 ? const0_idx : const1_idx;
   2656             break;
   2657          }
   2658          case aco_opcode::v_min_i32: {
   2659             int32_t const0_i =
   2660                const0 & 0x80000000u ? -2147483648 + (int32_t)(const0 & 0x7fffffffu) : const0;
   2661             int32_t const1_i =
   2662                const1 & 0x80000000u ? -2147483648 + (int32_t)(const1 & 0x7fffffffu) : const1;
   2663             lower_idx = const0_i < const1_i ? const0_idx : const1_idx;
   2664             break;
   2665          }
   2666          case aco_opcode::v_min_i16: {
   2667             int16_t const0_i = const0 & 0x8000u ? -32768 + (int16_t)(const0 & 0x7fffu) : const0;
   2668             int16_t const1_i = const1 & 0x8000u ? -32768 + (int16_t)(const1 & 0x7fffu) : const1;
   2669             lower_idx = const0_i < const1_i ? const0_idx : const1_idx;
   2670             break;
   2671          }
   2672          default: break;
   2673          }
   2674          int upper_idx = lower_idx == const0_idx ? const1_idx : const0_idx;
   2675 
   2676          if (instr->opcode == min) {
   2677             if (upper_idx != 0 || lower_idx == 0)
   2678                return false;
   2679          } else {
   2680             if (upper_idx == 0 || lower_idx != 0)
   2681                return false;
   2682          }
   2683 
   2684          ctx.uses[instr->operands[swap].tempId()]--;
   2685          create_vop3_for_op3(ctx, med, instr, operands, neg, abs, opsel, clamp, omod);
   2686 
   2687          return true;
   2688       }
   2689    }
   2690 
   2691    return false;
   2692 }
   2693 
   2694 void
   2695 apply_sgprs(opt_ctx& ctx, aco_ptr<Instruction>& instr)
   2696 {
   2697    bool is_shift64 = instr->opcode == aco_opcode::v_lshlrev_b64 ||
   2698                      instr->opcode == aco_opcode::v_lshrrev_b64 ||
   2699                      instr->opcode == aco_opcode::v_ashrrev_i64;
   2700 
   2701    /* find candidates and create the set of sgprs already read */
   2702    unsigned sgpr_ids[2] = {0, 0};
   2703    uint32_t operand_mask = 0;
   2704    bool has_literal = false;
   2705    for (unsigned i = 0; i < instr->operands.size(); i++) {
   2706       if (instr->operands[i].isLiteral())
   2707          has_literal = true;
   2708       if (!instr->operands[i].isTemp())
   2709          continue;
   2710       if (instr->operands[i].getTemp().type() == RegType::sgpr) {
   2711          if (instr->operands[i].tempId() != sgpr_ids[0])
   2712             sgpr_ids[!!sgpr_ids[0]] = instr->operands[i].tempId();
   2713       }
   2714       ssa_info& info = ctx.info[instr->operands[i].tempId()];
   2715       if (is_copy_label(ctx, instr, info) && info.temp.type() == RegType::sgpr)
   2716          operand_mask |= 1u << i;
   2717       if (info.is_extract() && info.instr->operands[0].getTemp().type() == RegType::sgpr)
   2718          operand_mask |= 1u << i;
   2719    }
   2720    unsigned max_sgprs = 1;
   2721    if (ctx.program->chip_class >= GFX10 && !is_shift64)
   2722       max_sgprs = 2;
   2723    if (has_literal)
   2724       max_sgprs--;
   2725 
   2726    unsigned num_sgprs = !!sgpr_ids[0] + !!sgpr_ids[1];
   2727 
   2728    /* keep on applying sgprs until there is nothing left to be done */
   2729    while (operand_mask) {
   2730       uint32_t sgpr_idx = 0;
   2731       uint32_t sgpr_info_id = 0;
   2732       uint32_t mask = operand_mask;
   2733       /* choose a sgpr */
   2734       while (mask) {
   2735          unsigned i = u_bit_scan(&mask);
   2736          uint16_t uses = ctx.uses[instr->operands[i].tempId()];
   2737          if (sgpr_info_id == 0 || uses < ctx.uses[sgpr_info_id]) {
   2738             sgpr_idx = i;
   2739             sgpr_info_id = instr->operands[i].tempId();
   2740          }
   2741       }
   2742       operand_mask &= ~(1u << sgpr_idx);
   2743 
   2744       ssa_info& info = ctx.info[sgpr_info_id];
   2745 
   2746       /* Applying two sgprs require making it VOP3, so don't do it unless it's
   2747        * definitively beneficial.
   2748        * TODO: this is too conservative because later the use count could be reduced to 1 */
   2749       if (!info.is_extract() && num_sgprs && ctx.uses[sgpr_info_id] > 1 && !instr->isVOP3() &&
   2750           !instr->isSDWA() && instr->format != Format::VOP3P)
   2751          break;
   2752 
   2753       Temp sgpr = info.is_extract() ? info.instr->operands[0].getTemp() : info.temp;
   2754       bool new_sgpr = sgpr.id() != sgpr_ids[0] && sgpr.id() != sgpr_ids[1];
   2755       if (new_sgpr && num_sgprs >= max_sgprs)
   2756          continue;
   2757 
   2758       if (sgpr_idx == 0)
   2759          instr->format = withoutDPP(instr->format);
   2760 
   2761       if (sgpr_idx == 0 || instr->isVOP3() || instr->isSDWA() || instr->isVOP3P() ||
   2762           info.is_extract()) {
   2763          /* can_apply_extract() checks SGPR encoding restrictions */
   2764          if (info.is_extract() && can_apply_extract(ctx, instr, sgpr_idx, info))
   2765             apply_extract(ctx, instr, sgpr_idx, info);
   2766          else if (info.is_extract())
   2767             continue;
   2768          instr->operands[sgpr_idx] = Operand(sgpr);
   2769       } else if (can_swap_operands(instr, &instr->opcode)) {
   2770          instr->operands[sgpr_idx] = instr->operands[0];
   2771          instr->operands[0] = Operand(sgpr);
   2772          /* swap bits using a 4-entry LUT */
   2773          uint32_t swapped = (0x3120 >> (operand_mask & 0x3)) & 0xf;
   2774          operand_mask = (operand_mask & ~0x3) | swapped;
   2775       } else if (can_use_VOP3(ctx, instr) && !info.is_extract()) {
   2776          to_VOP3(ctx, instr);
   2777          instr->operands[sgpr_idx] = Operand(sgpr);
   2778       } else {
   2779          continue;
   2780       }
   2781 
   2782       if (new_sgpr)
   2783          sgpr_ids[num_sgprs++] = sgpr.id();
   2784       ctx.uses[sgpr_info_id]--;
   2785       ctx.uses[sgpr.id()]++;
   2786 
   2787       /* TODO: handle when it's a VGPR */
   2788       if ((ctx.info[sgpr.id()].label & (label_extract | label_temp)) &&
   2789           ctx.info[sgpr.id()].temp.type() == RegType::sgpr)
   2790          operand_mask |= 1u << sgpr_idx;
   2791    }
   2792 }
   2793 
   2794 template <typename T>
   2795 bool
   2796 apply_omod_clamp_helper(opt_ctx& ctx, T* instr, ssa_info& def_info)
   2797 {
   2798    if (!def_info.is_clamp() && (instr->clamp || instr->omod))
   2799       return false;
   2800 
   2801    if (def_info.is_omod2())
   2802       instr->omod = 1;
   2803    else if (def_info.is_omod4())
   2804       instr->omod = 2;
   2805    else if (def_info.is_omod5())
   2806       instr->omod = 3;
   2807    else if (def_info.is_clamp())
   2808       instr->clamp = true;
   2809 
   2810    return true;
   2811 }
   2812 
   2813 /* apply omod / clamp modifiers if the def is used only once and the instruction can have modifiers */
   2814 bool
   2815 apply_omod_clamp(opt_ctx& ctx, aco_ptr<Instruction>& instr)
   2816 {
   2817    if (instr->definitions.empty() || ctx.uses[instr->definitions[0].tempId()] != 1 ||
   2818        !instr_info.can_use_output_modifiers[(int)instr->opcode])
   2819       return false;
   2820 
   2821    bool can_vop3 = can_use_VOP3(ctx, instr);
   2822    if (!instr->isSDWA() && !can_vop3)
   2823       return false;
   2824 
   2825    /* omod flushes -0 to +0 and has no effect if denormals are enabled */
   2826    bool can_use_omod = (can_vop3 || ctx.program->chip_class >= GFX9); /* SDWA omod is GFX9+ */
   2827    if (instr->definitions[0].bytes() == 4)
   2828       can_use_omod =
   2829          can_use_omod && ctx.fp_mode.denorm32 == 0 && !ctx.fp_mode.preserve_signed_zero_inf_nan32;
   2830    else
   2831       can_use_omod = can_use_omod && ctx.fp_mode.denorm16_64 == 0 &&
   2832                      !ctx.fp_mode.preserve_signed_zero_inf_nan16_64;
   2833 
   2834    ssa_info& def_info = ctx.info[instr->definitions[0].tempId()];
   2835 
   2836    uint64_t omod_labels = label_omod2 | label_omod4 | label_omod5;
   2837    if (!def_info.is_clamp() && !(can_use_omod && (def_info.label & omod_labels)))
   2838       return false;
   2839    /* if the omod/clamp instruction is dead, then the single user of this
   2840     * instruction is a different instruction */
   2841    if (!ctx.uses[def_info.instr->definitions[0].tempId()])
   2842       return false;
   2843 
   2844    /* MADs/FMAs are created later, so we don't have to update the original add */
   2845    assert(!ctx.info[instr->definitions[0].tempId()].is_mad());
   2846 
   2847    if (instr->isSDWA()) {
   2848       if (!apply_omod_clamp_helper(ctx, &instr->sdwa(), def_info))
   2849          return false;
   2850    } else {
   2851       to_VOP3(ctx, instr);
   2852       if (!apply_omod_clamp_helper(ctx, &instr->vop3(), def_info))
   2853          return false;
   2854    }
   2855 
   2856    instr->definitions[0].swapTemp(def_info.instr->definitions[0]);
   2857    ctx.info[instr->definitions[0].tempId()].label &= label_clamp | label_insert;
   2858    ctx.uses[def_info.instr->definitions[0].tempId()]--;
   2859 
   2860    return true;
   2861 }
   2862 
   2863 /* Combine an p_insert (or p_extract, in some cases) instruction with instr.
   2864  * p_insert(instr(...)) -> instr_insert().
   2865  */
   2866 bool
   2867 apply_insert(opt_ctx& ctx, aco_ptr<Instruction>& instr)
   2868 {
   2869    if (instr->definitions.empty() || ctx.uses[instr->definitions[0].tempId()] != 1)
   2870       return false;
   2871 
   2872    ssa_info& def_info = ctx.info[instr->definitions[0].tempId()];
   2873    if (!def_info.is_insert())
   2874       return false;
   2875    /* if the insert instruction is dead, then the single user of this
   2876     * instruction is a different instruction */
   2877    if (!ctx.uses[def_info.instr->definitions[0].tempId()])
   2878       return false;
   2879 
   2880    /* MADs/FMAs are created later, so we don't have to update the original add */
   2881    assert(!ctx.info[instr->definitions[0].tempId()].is_mad());
   2882 
   2883    SubdwordSel sel = parse_insert(def_info.instr);
   2884    assert(sel);
   2885 
   2886    if (instr->isVOP3() && sel.size() == 2 && !sel.sign_extend() &&
   2887        can_use_opsel(ctx.program->chip_class, instr->opcode, 3, sel.offset())) {
   2888       if (instr->vop3().opsel & (1 << 3))
   2889          return false;
   2890       if (sel.offset())
   2891          instr->vop3().opsel |= 1 << 3;
   2892    } else {
   2893       if (!can_use_SDWA(ctx.program->chip_class, instr, true))
   2894          return false;
   2895 
   2896       to_SDWA(ctx, instr);
   2897       if (instr->sdwa().dst_sel.size() != 4)
   2898          return false;
   2899       static_cast<SDWA_instruction*>(instr.get())->dst_sel = sel;
   2900    }
   2901 
   2902    instr->definitions[0].swapTemp(def_info.instr->definitions[0]);
   2903    ctx.info[instr->definitions[0].tempId()].label = 0;
   2904    ctx.uses[def_info.instr->definitions[0].tempId()]--;
   2905 
   2906    return true;
   2907 }
   2908 
   2909 /* Remove superfluous extract after ds_read like so:
   2910  * p_extract(ds_read_uN(), 0, N, 0) -> ds_read_uN()
   2911  */
   2912 bool
   2913 apply_ds_extract(opt_ctx& ctx, aco_ptr<Instruction>& extract)
   2914 {
   2915    /* Check if p_extract has a usedef operand and is the only user. */
   2916    if (!ctx.info[extract->operands[0].tempId()].is_usedef() ||
   2917        ctx.uses[extract->operands[0].tempId()] > 1)
   2918       return false;
   2919 
   2920    /* Check if the usedef is a DS instruction. */
   2921    Instruction* ds = ctx.info[extract->operands[0].tempId()].instr;
   2922    if (ds->format != Format::DS)
   2923       return false;
   2924 
   2925    unsigned extract_idx = extract->operands[1].constantValue();
   2926    unsigned bits_extracted = extract->operands[2].constantValue();
   2927    unsigned sign_ext = extract->operands[3].constantValue();
   2928    unsigned dst_bitsize = extract->definitions[0].bytes() * 8u;
   2929 
   2930    /* TODO: These are doable, but probably don't occour too often. */
   2931    if (extract_idx || sign_ext || dst_bitsize != 32)
   2932       return false;
   2933 
   2934    unsigned bits_loaded = 0;
   2935    if (ds->opcode == aco_opcode::ds_read_u8 || ds->opcode == aco_opcode::ds_read_u8_d16)
   2936       bits_loaded = 8;
   2937    else if (ds->opcode == aco_opcode::ds_read_u16 || ds->opcode == aco_opcode::ds_read_u16_d16)
   2938       bits_loaded = 16;
   2939    else
   2940       return false;
   2941 
   2942    /* Shrink the DS load if the extracted bit size is smaller. */
   2943    bits_loaded = MIN2(bits_loaded, bits_extracted);
   2944 
   2945    /* Change the DS opcode so it writes the full register. */
   2946    if (bits_loaded == 8)
   2947       ds->opcode = aco_opcode::ds_read_u8;
   2948    else if (bits_loaded == 16)
   2949       ds->opcode = aco_opcode::ds_read_u16;
   2950    else
   2951       unreachable("Forgot to add DS opcode above.");
   2952 
   2953    /* The DS now produces the exact same thing as the extract, remove the extract. */
   2954    std::swap(ds->definitions[0], extract->definitions[0]);
   2955    ctx.uses[extract->definitions[0].tempId()] = 0;
   2956    ctx.info[ds->definitions[0].tempId()].label = 0;
   2957    return true;
   2958 }
   2959 
   2960 /* v_and(a, v_subbrev_co(0, 0, vcc)) -> v_cndmask(0, a, vcc) */
   2961 bool
   2962 combine_and_subbrev(opt_ctx& ctx, aco_ptr<Instruction>& instr)
   2963 {
   2964    if (instr->usesModifiers())
   2965       return false;
   2966 
   2967    for (unsigned i = 0; i < 2; i++) {
   2968       Instruction* op_instr = follow_operand(ctx, instr->operands[i], true);
   2969       if (op_instr && op_instr->opcode == aco_opcode::v_subbrev_co_u32 &&
   2970           op_instr->operands[0].constantEquals(0) && op_instr->operands[1].constantEquals(0) &&
   2971           !op_instr->usesModifiers()) {
   2972 
   2973          aco_ptr<Instruction> new_instr;
   2974          if (instr->operands[!i].isTemp() &&
   2975              instr->operands[!i].getTemp().type() == RegType::vgpr) {
   2976             new_instr.reset(
   2977                create_instruction<VOP2_instruction>(aco_opcode::v_cndmask_b32, Format::VOP2, 3, 1));
   2978          } else if (ctx.program->chip_class >= GFX10 ||
   2979                     (instr->operands[!i].isConstant() && !instr->operands[!i].isLiteral())) {
   2980             new_instr.reset(create_instruction<VOP3_instruction>(aco_opcode::v_cndmask_b32,
   2981                                                                  asVOP3(Format::VOP2), 3, 1));
   2982          } else {
   2983             return false;
   2984          }
   2985 
   2986          ctx.uses[instr->operands[i].tempId()]--;
   2987          if (ctx.uses[instr->operands[i].tempId()])
   2988             ctx.uses[op_instr->operands[2].tempId()]++;
   2989 
   2990          new_instr->operands[0] = Operand::zero();
   2991          new_instr->operands[1] = instr->operands[!i];
   2992          new_instr->operands[2] = Operand(op_instr->operands[2]);
   2993          new_instr->definitions[0] = instr->definitions[0];
   2994          instr = std::move(new_instr);
   2995          ctx.info[instr->definitions[0].tempId()].label = 0;
   2996          return true;
   2997       }
   2998    }
   2999 
   3000    return false;
   3001 }
   3002 
   3003 /* v_add_co(c, s_lshl(a, b)) -> v_mad_u32_u24(a, 1<<b, c)
   3004  * v_add_co(c, v_lshlrev(a, b)) -> v_mad_u32_u24(b, 1<<a, c)
   3005  * v_sub(c, s_lshl(a, b)) -> v_mad_i32_i24(a, -(1<<b), c)
   3006  * v_sub(c, v_lshlrev(a, b)) -> v_mad_i32_i24(b, -(1<<a), c)
   3007  */
   3008 bool
   3009 combine_add_lshl(opt_ctx& ctx, aco_ptr<Instruction>& instr, bool is_sub)
   3010 {
   3011    if (instr->usesModifiers())
   3012       return false;
   3013 
   3014    /* Substractions: start at operand 1 to avoid mixup such as
   3015     * turning v_sub(v_lshlrev(a, b), c) into v_mad_i32_i24(b, -(1<<a), c)
   3016     */
   3017    unsigned start_op_idx = is_sub ? 1 : 0;
   3018 
   3019    /* Don't allow 24-bit operands on subtraction because
   3020     * v_mad_i32_i24 applies a sign extension.
   3021     */
   3022    bool allow_24bit = !is_sub;
   3023 
   3024    for (unsigned i = start_op_idx; i < 2; i++) {
   3025       Instruction* op_instr = follow_operand(ctx, instr->operands[i]);
   3026       if (!op_instr)
   3027          continue;
   3028 
   3029       if (op_instr->opcode != aco_opcode::s_lshl_b32 &&
   3030           op_instr->opcode != aco_opcode::v_lshlrev_b32)
   3031          continue;
   3032 
   3033       int shift_op_idx = op_instr->opcode == aco_opcode::s_lshl_b32 ? 1 : 0;
   3034 
   3035       if (op_instr->operands[shift_op_idx].isConstant() &&
   3036           ((allow_24bit && op_instr->operands[!shift_op_idx].is24bit()) ||
   3037            op_instr->operands[!shift_op_idx].is16bit())) {
   3038          uint32_t multiplier = 1 << (op_instr->operands[shift_op_idx].constantValue() % 32u);
   3039          if (is_sub)
   3040             multiplier = -multiplier;
   3041          if (is_sub ? (multiplier < 0xff800000) : (multiplier > 0xffffff))
   3042             continue;
   3043 
   3044          Operand ops[3] = {
   3045             op_instr->operands[!shift_op_idx],
   3046             Operand::c32(multiplier),
   3047             instr->operands[!i],
   3048          };
   3049          if (!check_vop3_operands(ctx, 3, ops))
   3050             return false;
   3051 
   3052          ctx.uses[instr->operands[i].tempId()]--;
   3053 
   3054          aco_opcode mad_op = is_sub ? aco_opcode::v_mad_i32_i24 : aco_opcode::v_mad_u32_u24;
   3055          aco_ptr<VOP3_instruction> new_instr{
   3056             create_instruction<VOP3_instruction>(mad_op, Format::VOP3, 3, 1)};
   3057          for (unsigned op_idx = 0; op_idx < 3; ++op_idx)
   3058             new_instr->operands[op_idx] = ops[op_idx];
   3059          new_instr->definitions[0] = instr->definitions[0];
   3060          instr = std::move(new_instr);
   3061          ctx.info[instr->definitions[0].tempId()].label = 0;
   3062          return true;
   3063       }
   3064    }
   3065 
   3066    return false;
   3067 }
   3068 
   3069 void
   3070 propagate_swizzles(VOP3P_instruction* instr, uint8_t opsel_lo, uint8_t opsel_hi)
   3071 {
   3072    /* propagate swizzles which apply to a result down to the instruction's operands:
   3073     * result = a.xy + b.xx -> result.yx = a.yx + b.xx */
   3074    assert((opsel_lo & 1) == opsel_lo);
   3075    assert((opsel_hi & 1) == opsel_hi);
   3076    uint8_t tmp_lo = instr->opsel_lo;
   3077    uint8_t tmp_hi = instr->opsel_hi;
   3078    bool neg_lo[3] = {instr->neg_lo[0], instr->neg_lo[1], instr->neg_lo[2]};
   3079    bool neg_hi[3] = {instr->neg_hi[0], instr->neg_hi[1], instr->neg_hi[2]};
   3080    if (opsel_lo == 1) {
   3081       instr->opsel_lo = tmp_hi;
   3082       for (unsigned i = 0; i < 3; i++)
   3083          instr->neg_lo[i] = neg_hi[i];
   3084    }
   3085    if (opsel_hi == 0) {
   3086       instr->opsel_hi = tmp_lo;
   3087       for (unsigned i = 0; i < 3; i++)
   3088          instr->neg_hi[i] = neg_lo[i];
   3089    }
   3090 }
   3091 
   3092 void
   3093 combine_vop3p(opt_ctx& ctx, aco_ptr<Instruction>& instr)
   3094 {
   3095    VOP3P_instruction* vop3p = &instr->vop3p();
   3096 
   3097    /* apply clamp */
   3098    if (instr->opcode == aco_opcode::v_pk_mul_f16 && instr->operands[1].constantEquals(0x3C00) &&
   3099        vop3p->clamp && instr->operands[0].isTemp() && ctx.uses[instr->operands[0].tempId()] == 1) {
   3100 
   3101       ssa_info& info = ctx.info[instr->operands[0].tempId()];
   3102       if (info.is_vop3p() && instr_info.can_use_output_modifiers[(int)info.instr->opcode]) {
   3103          VOP3P_instruction* candidate = &ctx.info[instr->operands[0].tempId()].instr->vop3p();
   3104          candidate->clamp = true;
   3105          propagate_swizzles(candidate, vop3p->opsel_lo, vop3p->opsel_hi);
   3106          instr->definitions[0].swapTemp(candidate->definitions[0]);
   3107          ctx.info[candidate->definitions[0].tempId()].instr = candidate;
   3108          ctx.uses[instr->definitions[0].tempId()]--;
   3109          return;
   3110       }
   3111    }
   3112 
   3113    /* check for fneg modifiers */
   3114    if (instr_info.can_use_input_modifiers[(int)instr->opcode]) {
   3115       /* at this point, we only have 2-operand instructions */
   3116       assert(instr->operands.size() == 2);
   3117       for (unsigned i = 0; i < 2; i++) {
   3118          Operand& op = instr->operands[i];
   3119          if (!op.isTemp())
   3120             continue;
   3121 
   3122          ssa_info& info = ctx.info[op.tempId()];
   3123          if (info.is_vop3p() && info.instr->opcode == aco_opcode::v_pk_mul_f16 &&
   3124              info.instr->operands[1].constantEquals(0xBC00)) {
   3125             Operand ops[2] = {instr->operands[!i], info.instr->operands[0]};
   3126             if (!check_vop3_operands(ctx, 2, ops))
   3127                continue;
   3128 
   3129             VOP3P_instruction* fneg = &info.instr->vop3p();
   3130             if (fneg->clamp)
   3131                continue;
   3132             instr->operands[i] = fneg->operands[0];
   3133 
   3134             /* opsel_lo/hi is either 0 or 1:
   3135              * if 0 - pick selection from fneg->lo
   3136              * if 1 - pick selection from fneg->hi
   3137              */
   3138             bool opsel_lo = (vop3p->opsel_lo >> i) & 1;
   3139             bool opsel_hi = (vop3p->opsel_hi >> i) & 1;
   3140             bool neg_lo = true ^ fneg->neg_lo[0] ^ fneg->neg_lo[1];
   3141             bool neg_hi = true ^ fneg->neg_hi[0] ^ fneg->neg_hi[1];
   3142             vop3p->neg_lo[i] ^= opsel_lo ? neg_hi : neg_lo;
   3143             vop3p->neg_hi[i] ^= opsel_hi ? neg_hi : neg_lo;
   3144             vop3p->opsel_lo ^= ((opsel_lo ? ~fneg->opsel_hi : fneg->opsel_lo) & 1) << i;
   3145             vop3p->opsel_hi ^= ((opsel_hi ? ~fneg->opsel_hi : fneg->opsel_lo) & 1) << i;
   3146 
   3147             if (--ctx.uses[fneg->definitions[0].tempId()])
   3148                ctx.uses[fneg->operands[0].tempId()]++;
   3149          }
   3150       }
   3151    }
   3152 
   3153    if (instr->opcode == aco_opcode::v_pk_add_f16 || instr->opcode == aco_opcode::v_pk_add_u16) {
   3154       bool fadd = instr->opcode == aco_opcode::v_pk_add_f16;
   3155       if (fadd && instr->definitions[0].isPrecise())
   3156          return;
   3157 
   3158       Instruction* mul_instr = nullptr;
   3159       unsigned add_op_idx = 0;
   3160       uint8_t opsel_lo = 0, opsel_hi = 0;
   3161       uint32_t uses = UINT32_MAX;
   3162 
   3163       /* find the 'best' mul instruction to combine with the add */
   3164       for (unsigned i = 0; i < 2; i++) {
   3165          if (!instr->operands[i].isTemp() || !ctx.info[instr->operands[i].tempId()].is_vop3p())
   3166             continue;
   3167          ssa_info& info = ctx.info[instr->operands[i].tempId()];
   3168          if (fadd) {
   3169             if (info.instr->opcode != aco_opcode::v_pk_mul_f16 ||
   3170                 info.instr->definitions[0].isPrecise())
   3171                continue;
   3172          } else {
   3173             if (info.instr->opcode != aco_opcode::v_pk_mul_lo_u16)
   3174                continue;
   3175          }
   3176 
   3177          Operand op[3] = {info.instr->operands[0], info.instr->operands[1], instr->operands[1 - i]};
   3178          if (ctx.uses[instr->operands[i].tempId()] >= uses || !check_vop3_operands(ctx, 3, op))
   3179             continue;
   3180 
   3181          /* no clamp allowed between mul and add */
   3182          if (info.instr->vop3p().clamp)
   3183             continue;
   3184 
   3185          mul_instr = info.instr;
   3186          add_op_idx = 1 - i;
   3187          opsel_lo = (vop3p->opsel_lo >> i) & 1;
   3188          opsel_hi = (vop3p->opsel_hi >> i) & 1;
   3189          uses = ctx.uses[instr->operands[i].tempId()];
   3190       }
   3191 
   3192       if (!mul_instr)
   3193          return;
   3194 
   3195       /* convert to mad */
   3196       Operand op[3] = {mul_instr->operands[0], mul_instr->operands[1], instr->operands[add_op_idx]};
   3197       ctx.uses[mul_instr->definitions[0].tempId()]--;
   3198       if (ctx.uses[mul_instr->definitions[0].tempId()]) {
   3199          if (op[0].isTemp())
   3200             ctx.uses[op[0].tempId()]++;
   3201          if (op[1].isTemp())
   3202             ctx.uses[op[1].tempId()]++;
   3203       }
   3204 
   3205       /* turn packed mul+add into v_pk_fma_f16 */
   3206       assert(mul_instr->isVOP3P());
   3207       aco_opcode mad = fadd ? aco_opcode::v_pk_fma_f16 : aco_opcode::v_pk_mad_u16;
   3208       aco_ptr<VOP3P_instruction> fma{
   3209          create_instruction<VOP3P_instruction>(mad, Format::VOP3P, 3, 1)};
   3210       VOP3P_instruction* mul = &mul_instr->vop3p();
   3211       for (unsigned i = 0; i < 2; i++) {
   3212          fma->operands[i] = op[i];
   3213          fma->neg_lo[i] = mul->neg_lo[i];
   3214          fma->neg_hi[i] = mul->neg_hi[i];
   3215       }
   3216       fma->operands[2] = op[2];
   3217       fma->clamp = vop3p->clamp;
   3218       fma->opsel_lo = mul->opsel_lo;
   3219       fma->opsel_hi = mul->opsel_hi;
   3220       propagate_swizzles(fma.get(), opsel_lo, opsel_hi);
   3221       fma->opsel_lo |= (vop3p->opsel_lo << (2 - add_op_idx)) & 0x4;
   3222       fma->opsel_hi |= (vop3p->opsel_hi << (2 - add_op_idx)) & 0x4;
   3223       fma->neg_lo[2] = vop3p->neg_lo[add_op_idx];
   3224       fma->neg_hi[2] = vop3p->neg_hi[add_op_idx];
   3225       fma->neg_lo[1] = fma->neg_lo[1] ^ vop3p->neg_lo[1 - add_op_idx];
   3226       fma->neg_hi[1] = fma->neg_hi[1] ^ vop3p->neg_hi[1 - add_op_idx];
   3227       fma->definitions[0] = instr->definitions[0];
   3228       instr = std::move(fma);
   3229       ctx.info[instr->definitions[0].tempId()].set_vop3p(instr.get());
   3230       return;
   3231    }
   3232 }
   3233 
   3234 // TODO: we could possibly move the whole label_instruction pass to combine_instruction:
   3235 // this would mean that we'd have to fix the instruction uses while value propagation
   3236 
   3237 void
   3238 combine_instruction(opt_ctx& ctx, aco_ptr<Instruction>& instr)
   3239 {
   3240    if (instr->definitions.empty() || is_dead(ctx.uses, instr.get()))
   3241       return;
   3242 
   3243    if (instr->isVALU()) {
   3244       /* Apply SDWA. Do this after label_instruction() so it can remove
   3245        * label_extract if not all instructions can take SDWA. */
   3246       for (unsigned i = 0; i < instr->operands.size(); i++) {
   3247          Operand& op = instr->operands[i];
   3248          if (!op.isTemp())
   3249             continue;
   3250          ssa_info& info = ctx.info[op.tempId()];
   3251          if (!info.is_extract())
   3252             continue;
   3253          /* if there are that many uses, there are likely better combinations */
   3254          // TODO: delay applying extract to a point where we know better
   3255          if (ctx.uses[op.tempId()] > 4) {
   3256             info.label &= ~label_extract;
   3257             continue;
   3258          }
   3259          if (info.is_extract() &&
   3260              (info.instr->operands[0].getTemp().type() == RegType::vgpr ||
   3261               instr->operands[i].getTemp().type() == RegType::sgpr) &&
   3262              can_apply_extract(ctx, instr, i, info)) {
   3263             apply_extract(ctx, instr, i, info);
   3264             ctx.uses[instr->operands[i].tempId()]--;
   3265             instr->operands[i].setTemp(info.instr->operands[0].getTemp());
   3266          }
   3267       }
   3268 
   3269       if (can_apply_sgprs(ctx, instr))
   3270          apply_sgprs(ctx, instr);
   3271       while (apply_omod_clamp(ctx, instr))
   3272          ;
   3273       apply_insert(ctx, instr);
   3274    }
   3275 
   3276    if (instr->isVOP3P())
   3277       return combine_vop3p(ctx, instr);
   3278 
   3279    if (ctx.info[instr->definitions[0].tempId()].is_vcc_hint()) {
   3280       instr->definitions[0].setHint(vcc);
   3281    }
   3282 
   3283    if (instr->isSDWA() || instr->isDPP())
   3284       return;
   3285 
   3286    if (instr->opcode == aco_opcode::p_extract)
   3287       apply_ds_extract(ctx, instr);
   3288 
   3289    /* TODO: There are still some peephole optimizations that could be done:
   3290     * - abs(a - b) -> s_absdiff_i32
   3291     * - various patterns for s_bitcmp{0,1}_b32 and s_bitset{0,1}_b32
   3292     * - patterns for v_alignbit_b32 and v_alignbyte_b32
   3293     * These aren't probably too interesting though.
   3294     * There are also patterns for v_cmp_class_f{16,32,64}. This is difficult but
   3295     * probably more useful than the previously mentioned optimizations.
   3296     * The various comparison optimizations also currently only work with 32-bit
   3297     * floats. */
   3298 
   3299    /* neg(mul(a, b)) -> mul(neg(a), b) */
   3300    if (ctx.info[instr->definitions[0].tempId()].is_neg() &&
   3301        ctx.uses[instr->operands[1].tempId()] == 1) {
   3302       Temp val = ctx.info[instr->definitions[0].tempId()].temp;
   3303 
   3304       if (!ctx.info[val.id()].is_mul())
   3305          return;
   3306 
   3307       Instruction* mul_instr = ctx.info[val.id()].instr;
   3308 
   3309       if (mul_instr->operands[0].isLiteral())
   3310          return;
   3311       if (mul_instr->isVOP3() && mul_instr->vop3().clamp)
   3312          return;
   3313       if (mul_instr->isSDWA() || mul_instr->isDPP())
   3314          return;
   3315 
   3316       /* convert to mul(neg(a), b) */
   3317       ctx.uses[mul_instr->definitions[0].tempId()]--;
   3318       Definition def = instr->definitions[0];
   3319       /* neg(abs(mul(a, b))) -> mul(neg(abs(a)), abs(b)) */
   3320       bool is_abs = ctx.info[instr->definitions[0].tempId()].is_abs();
   3321       instr.reset(
   3322          create_instruction<VOP3_instruction>(mul_instr->opcode, asVOP3(Format::VOP2), 2, 1));
   3323       instr->operands[0] = mul_instr->operands[0];
   3324       instr->operands[1] = mul_instr->operands[1];
   3325       instr->definitions[0] = def;
   3326       VOP3_instruction& new_mul = instr->vop3();
   3327       if (mul_instr->isVOP3()) {
   3328          VOP3_instruction& mul = mul_instr->vop3();
   3329          new_mul.neg[0] = mul.neg[0];
   3330          new_mul.neg[1] = mul.neg[1];
   3331          new_mul.abs[0] = mul.abs[0];
   3332          new_mul.abs[1] = mul.abs[1];
   3333          new_mul.omod = mul.omod;
   3334       }
   3335       if (is_abs) {
   3336          new_mul.neg[0] = new_mul.neg[1] = false;
   3337          new_mul.abs[0] = new_mul.abs[1] = true;
   3338       }
   3339       new_mul.neg[0] ^= true;
   3340       new_mul.clamp = false;
   3341 
   3342       ctx.info[instr->definitions[0].tempId()].set_mul(instr.get());
   3343       return;
   3344    }
   3345 
   3346    /* combine mul+add -> mad */
   3347    bool mad32 = instr->opcode == aco_opcode::v_add_f32 || instr->opcode == aco_opcode::v_sub_f32 ||
   3348                 instr->opcode == aco_opcode::v_subrev_f32;
   3349    bool mad16 = instr->opcode == aco_opcode::v_add_f16 || instr->opcode == aco_opcode::v_sub_f16 ||
   3350                 instr->opcode == aco_opcode::v_subrev_f16;
   3351    bool mad64 = instr->opcode == aco_opcode::v_add_f64;
   3352    if (mad16 || mad32 || mad64) {
   3353       bool need_fma =
   3354          mad32 ? (ctx.fp_mode.denorm32 != 0 || ctx.program->chip_class >= GFX10_3)
   3355                : (ctx.fp_mode.denorm16_64 != 0 || ctx.program->chip_class >= GFX10 || mad64);
   3356       if (need_fma && instr->definitions[0].isPrecise())
   3357          return;
   3358       if (need_fma && mad32 && !ctx.program->dev.has_fast_fma32)
   3359          return;
   3360 
   3361       Instruction* mul_instr = nullptr;
   3362       unsigned add_op_idx = 0;
   3363       uint32_t uses = UINT32_MAX;
   3364       /* find the 'best' mul instruction to combine with the add */
   3365       for (unsigned i = 0; i < 2; i++) {
   3366          if (!instr->operands[i].isTemp() || !ctx.info[instr->operands[i].tempId()].is_mul())
   3367             continue;
   3368          /* check precision requirements */
   3369          ssa_info& info = ctx.info[instr->operands[i].tempId()];
   3370          if (need_fma && info.instr->definitions[0].isPrecise())
   3371             continue;
   3372 
   3373          /* no clamp/omod allowed between mul and add */
   3374          if (info.instr->isVOP3() && (info.instr->vop3().clamp || info.instr->vop3().omod))
   3375             continue;
   3376 
   3377          Operand op[3] = {info.instr->operands[0], info.instr->operands[1], instr->operands[1 - i]};
   3378          if (info.instr->isSDWA() || info.instr->isDPP() || !check_vop3_operands(ctx, 3, op) ||
   3379              ctx.uses[instr->operands[i].tempId()] >= uses)
   3380             continue;
   3381 
   3382          mul_instr = info.instr;
   3383          add_op_idx = 1 - i;
   3384          uses = ctx.uses[instr->operands[i].tempId()];
   3385       }
   3386 
   3387       if (mul_instr) {
   3388          /* turn mul+add into v_mad/v_fma */
   3389          Operand op[3] = {mul_instr->operands[0], mul_instr->operands[1],
   3390                           instr->operands[add_op_idx]};
   3391          ctx.uses[mul_instr->definitions[0].tempId()]--;
   3392          if (ctx.uses[mul_instr->definitions[0].tempId()]) {
   3393             if (op[0].isTemp())
   3394                ctx.uses[op[0].tempId()]++;
   3395             if (op[1].isTemp())
   3396                ctx.uses[op[1].tempId()]++;
   3397          }
   3398 
   3399          bool neg[3] = {false, false, false};
   3400          bool abs[3] = {false, false, false};
   3401          unsigned omod = 0;
   3402          bool clamp = false;
   3403 
   3404          if (mul_instr->isVOP3()) {
   3405             VOP3_instruction& vop3 = mul_instr->vop3();
   3406             neg[0] = vop3.neg[0];
   3407             neg[1] = vop3.neg[1];
   3408             abs[0] = vop3.abs[0];
   3409             abs[1] = vop3.abs[1];
   3410          }
   3411 
   3412          if (instr->isVOP3()) {
   3413             VOP3_instruction& vop3 = instr->vop3();
   3414             neg[2] = vop3.neg[add_op_idx];
   3415             abs[2] = vop3.abs[add_op_idx];
   3416             omod = vop3.omod;
   3417             clamp = vop3.clamp;
   3418             /* abs of the multiplication result */
   3419             if (vop3.abs[1 - add_op_idx]) {
   3420                neg[0] = false;
   3421                neg[1] = false;
   3422                abs[0] = true;
   3423                abs[1] = true;
   3424             }
   3425             /* neg of the multiplication result */
   3426             neg[1] = neg[1] ^ vop3.neg[1 - add_op_idx];
   3427          }
   3428          if (instr->opcode == aco_opcode::v_sub_f32 || instr->opcode == aco_opcode::v_sub_f16)
   3429             neg[1 + add_op_idx] = neg[1 + add_op_idx] ^ true;
   3430          else if (instr->opcode == aco_opcode::v_subrev_f32 ||
   3431                   instr->opcode == aco_opcode::v_subrev_f16)
   3432             neg[2 - add_op_idx] = neg[2 - add_op_idx] ^ true;
   3433 
   3434          aco_opcode mad_op = need_fma ? aco_opcode::v_fma_f32 : aco_opcode::v_mad_f32;
   3435          if (mad16)
   3436             mad_op = need_fma ? (ctx.program->chip_class == GFX8 ? aco_opcode::v_fma_legacy_f16
   3437                                                                  : aco_opcode::v_fma_f16)
   3438                               : (ctx.program->chip_class == GFX8 ? aco_opcode::v_mad_legacy_f16
   3439                                                                  : aco_opcode::v_mad_f16);
   3440          if (mad64)
   3441             mad_op = aco_opcode::v_fma_f64;
   3442 
   3443          aco_ptr<VOP3_instruction> mad{
   3444             create_instruction<VOP3_instruction>(mad_op, Format::VOP3, 3, 1)};
   3445          for (unsigned i = 0; i < 3; i++) {
   3446             mad->operands[i] = op[i];
   3447             mad->neg[i] = neg[i];
   3448             mad->abs[i] = abs[i];
   3449          }
   3450          mad->omod = omod;
   3451          mad->clamp = clamp;
   3452          mad->definitions[0] = instr->definitions[0];
   3453 
   3454          /* mark this ssa_def to be re-checked for profitability and literals */
   3455          ctx.mad_infos.emplace_back(std::move(instr), mul_instr->definitions[0].tempId());
   3456          ctx.info[mad->definitions[0].tempId()].set_mad(mad.get(), ctx.mad_infos.size() - 1);
   3457          instr = std::move(mad);
   3458          return;
   3459       }
   3460    }
   3461    /* v_mul_f32(v_cndmask_b32(0, 1.0, cond), a) -> v_cndmask_b32(0, a, cond) */
   3462    else if (instr->opcode == aco_opcode::v_mul_f32 && !instr->isVOP3()) {
   3463       for (unsigned i = 0; i < 2; i++) {
   3464          if (instr->operands[i].isTemp() && ctx.info[instr->operands[i].tempId()].is_b2f() &&
   3465              ctx.uses[instr->operands[i].tempId()] == 1 && instr->operands[!i].isTemp() &&
   3466              instr->operands[!i].getTemp().type() == RegType::vgpr) {
   3467             ctx.uses[instr->operands[i].tempId()]--;
   3468             ctx.uses[ctx.info[instr->operands[i].tempId()].temp.id()]++;
   3469 
   3470             aco_ptr<VOP2_instruction> new_instr{
   3471                create_instruction<VOP2_instruction>(aco_opcode::v_cndmask_b32, Format::VOP2, 3, 1)};
   3472             new_instr->operands[0] = Operand::zero();
   3473             new_instr->operands[1] = instr->operands[!i];
   3474             new_instr->operands[2] = Operand(ctx.info[instr->operands[i].tempId()].temp);
   3475             new_instr->definitions[0] = instr->definitions[0];
   3476             instr = std::move(new_instr);
   3477             ctx.info[instr->definitions[0].tempId()].label = 0;
   3478             return;
   3479          }
   3480       }
   3481    } else if (instr->opcode == aco_opcode::v_or_b32 && ctx.program->chip_class >= GFX9) {
   3482       if (combine_three_valu_op(ctx, instr, aco_opcode::s_or_b32, aco_opcode::v_or3_b32, "012",
   3483                                 1 | 2)) {
   3484       } else if (combine_three_valu_op(ctx, instr, aco_opcode::v_or_b32, aco_opcode::v_or3_b32,
   3485                                        "012", 1 | 2)) {
   3486       } else if (combine_add_or_then_and_lshl(ctx, instr)) {
   3487       }
   3488    } else if (instr->opcode == aco_opcode::v_xor_b32 && ctx.program->chip_class >= GFX10) {
   3489       if (combine_three_valu_op(ctx, instr, aco_opcode::v_xor_b32, aco_opcode::v_xor3_b32, "012",
   3490                                 1 | 2)) {
   3491       } else if (combine_three_valu_op(ctx, instr, aco_opcode::s_xor_b32, aco_opcode::v_xor3_b32,
   3492                                        "012", 1 | 2)) {
   3493       }
   3494    } else if (instr->opcode == aco_opcode::v_add_u16) {
   3495       combine_three_valu_op(
   3496          ctx, instr, aco_opcode::v_mul_lo_u16,
   3497          ctx.program->chip_class == GFX8 ? aco_opcode::v_mad_legacy_u16 : aco_opcode::v_mad_u16,
   3498          "120", 1 | 2);
   3499    } else if (instr->opcode == aco_opcode::v_add_u16_e64) {
   3500       combine_three_valu_op(ctx, instr, aco_opcode::v_mul_lo_u16_e64, aco_opcode::v_mad_u16, "120",
   3501                             1 | 2);
   3502    } else if (instr->opcode == aco_opcode::v_add_u32) {
   3503       if (combine_add_sub_b2i(ctx, instr, aco_opcode::v_addc_co_u32, 1 | 2)) {
   3504       } else if (combine_add_bcnt(ctx, instr)) {
   3505       } else if (combine_three_valu_op(ctx, instr, aco_opcode::v_mul_u32_u24,
   3506                                        aco_opcode::v_mad_u32_u24, "120", 1 | 2)) {
   3507       } else if (ctx.program->chip_class >= GFX9 && !instr->usesModifiers()) {
   3508          if (combine_three_valu_op(ctx, instr, aco_opcode::s_xor_b32, aco_opcode::v_xad_u32, "120",
   3509                                    1 | 2)) {
   3510          } else if (combine_three_valu_op(ctx, instr, aco_opcode::v_xor_b32, aco_opcode::v_xad_u32,
   3511                                           "120", 1 | 2)) {
   3512          } else if (combine_three_valu_op(ctx, instr, aco_opcode::s_add_i32, aco_opcode::v_add3_u32,
   3513                                           "012", 1 | 2)) {
   3514          } else if (combine_three_valu_op(ctx, instr, aco_opcode::s_add_u32, aco_opcode::v_add3_u32,
   3515                                           "012", 1 | 2)) {
   3516          } else if (combine_three_valu_op(ctx, instr, aco_opcode::v_add_u32, aco_opcode::v_add3_u32,
   3517                                           "012", 1 | 2)) {
   3518          } else if (combine_add_or_then_and_lshl(ctx, instr)) {
   3519          }
   3520       }
   3521    } else if (instr->opcode == aco_opcode::v_add_co_u32 ||
   3522               instr->opcode == aco_opcode::v_add_co_u32_e64) {
   3523       bool carry_out = ctx.uses[instr->definitions[1].tempId()] > 0;
   3524       if (combine_add_sub_b2i(ctx, instr, aco_opcode::v_addc_co_u32, 1 | 2)) {
   3525       } else if (!carry_out && combine_add_bcnt(ctx, instr)) {
   3526       } else if (!carry_out && combine_three_valu_op(ctx, instr, aco_opcode::v_mul_u32_u24,
   3527                                                      aco_opcode::v_mad_u32_u24, "120", 1 | 2)) {
   3528       } else if (!carry_out && combine_add_lshl(ctx, instr, false)) {
   3529       }
   3530    } else if (instr->opcode == aco_opcode::v_sub_u32 || instr->opcode == aco_opcode::v_sub_co_u32 ||
   3531               instr->opcode == aco_opcode::v_sub_co_u32_e64) {
   3532       bool carry_out =
   3533          instr->opcode != aco_opcode::v_sub_u32 && ctx.uses[instr->definitions[1].tempId()] > 0;
   3534       if (combine_add_sub_b2i(ctx, instr, aco_opcode::v_subbrev_co_u32, 2)) {
   3535       } else if (!carry_out && combine_add_lshl(ctx, instr, true)) {
   3536       }
   3537    } else if (instr->opcode == aco_opcode::v_subrev_u32 ||
   3538               instr->opcode == aco_opcode::v_subrev_co_u32 ||
   3539               instr->opcode == aco_opcode::v_subrev_co_u32_e64) {
   3540       combine_add_sub_b2i(ctx, instr, aco_opcode::v_subbrev_co_u32, 1);
   3541    } else if (instr->opcode == aco_opcode::v_lshlrev_b32 && ctx.program->chip_class >= GFX9) {
   3542       combine_three_valu_op(ctx, instr, aco_opcode::v_add_u32, aco_opcode::v_add_lshl_u32, "120",
   3543                             2);
   3544    } else if ((instr->opcode == aco_opcode::s_add_u32 || instr->opcode == aco_opcode::s_add_i32) &&
   3545               ctx.program->chip_class >= GFX9) {
   3546       combine_salu_lshl_add(ctx, instr);
   3547    } else if (instr->opcode == aco_opcode::s_not_b32 || instr->opcode == aco_opcode::s_not_b64) {
   3548       combine_salu_not_bitwise(ctx, instr);
   3549    } else if (instr->opcode == aco_opcode::s_and_b32 || instr->opcode == aco_opcode::s_or_b32 ||
   3550               instr->opcode == aco_opcode::s_and_b64 || instr->opcode == aco_opcode::s_or_b64) {
   3551       if (combine_ordering_test(ctx, instr)) {
   3552       } else if (combine_comparison_ordering(ctx, instr)) {
   3553       } else if (combine_constant_comparison_ordering(ctx, instr)) {
   3554       } else if (combine_salu_n2(ctx, instr)) {
   3555       }
   3556    } else if (instr->opcode == aco_opcode::v_and_b32) {
   3557       combine_and_subbrev(ctx, instr);
   3558    } else {
   3559       aco_opcode min, max, min3, max3, med3;
   3560       bool some_gfx9_only;
   3561       if (get_minmax_info(instr->opcode, &min, &max, &min3, &max3, &med3, &some_gfx9_only) &&
   3562           (!some_gfx9_only || ctx.program->chip_class >= GFX9)) {
   3563          if (combine_minmax(ctx, instr, instr->opcode == min ? max : min,
   3564                             instr->opcode == min ? min3 : max3)) {
   3565          } else {
   3566             combine_clamp(ctx, instr, min, max, med3);
   3567          }
   3568       }
   3569    }
   3570 
   3571    /* do this after combine_salu_n2() */
   3572    if (instr->opcode == aco_opcode::s_andn2_b32 || instr->opcode == aco_opcode::s_andn2_b64)
   3573       combine_inverse_comparison(ctx, instr);
   3574 }
   3575 
   3576 bool
   3577 to_uniform_bool_instr(opt_ctx& ctx, aco_ptr<Instruction>& instr)
   3578 {
   3579    /* Check every operand to make sure they are suitable. */
   3580    for (Operand& op : instr->operands) {
   3581       if (!op.isTemp())
   3582          return false;
   3583       if (!ctx.info[op.tempId()].is_uniform_bool() && !ctx.info[op.tempId()].is_uniform_bitwise())
   3584          return false;
   3585    }
   3586 
   3587    switch (instr->opcode) {
   3588    case aco_opcode::s_and_b32:
   3589    case aco_opcode::s_and_b64: instr->opcode = aco_opcode::s_and_b32; break;
   3590    case aco_opcode::s_or_b32:
   3591    case aco_opcode::s_or_b64: instr->opcode = aco_opcode::s_or_b32; break;
   3592    case aco_opcode::s_xor_b32:
   3593    case aco_opcode::s_xor_b64: instr->opcode = aco_opcode::s_absdiff_i32; break;
   3594    default:
   3595       /* Don't transform other instructions. They are very unlikely to appear here. */
   3596       return false;
   3597    }
   3598 
   3599    for (Operand& op : instr->operands) {
   3600       ctx.uses[op.tempId()]--;
   3601 
   3602       if (ctx.info[op.tempId()].is_uniform_bool()) {
   3603          /* Just use the uniform boolean temp. */
   3604          op.setTemp(ctx.info[op.tempId()].temp);
   3605       } else if (ctx.info[op.tempId()].is_uniform_bitwise()) {
   3606          /* Use the SCC definition of the predecessor instruction.
   3607           * This allows the predecessor to get picked up by the same optimization (if it has no
   3608           * divergent users), and it also makes sure that the current instruction will keep working
   3609           * even if the predecessor won't be transformed.
   3610           */
   3611          Instruction* pred_instr = ctx.info[op.tempId()].instr;
   3612          assert(pred_instr->definitions.size() >= 2);
   3613          assert(pred_instr->definitions[1].isFixed() &&
   3614                 pred_instr->definitions[1].physReg() == scc);
   3615          op.setTemp(pred_instr->definitions[1].getTemp());
   3616       } else {
   3617          unreachable("Invalid operand on uniform bitwise instruction.");
   3618       }
   3619 
   3620       ctx.uses[op.tempId()]++;
   3621    }
   3622 
   3623    instr->definitions[0].setTemp(Temp(instr->definitions[0].tempId(), s1));
   3624    assert(instr->operands[0].regClass() == s1);
   3625    assert(instr->operands[1].regClass() == s1);
   3626    return true;
   3627 }
   3628 
   3629 void
   3630 select_instruction(opt_ctx& ctx, aco_ptr<Instruction>& instr)
   3631 {
   3632    const uint32_t threshold = 4;
   3633 
   3634    if (is_dead(ctx.uses, instr.get())) {
   3635       instr.reset();
   3636       return;
   3637    }
   3638 
   3639    /* convert split_vector into a copy or extract_vector if only one definition is ever used */
   3640    if (instr->opcode == aco_opcode::p_split_vector) {
   3641       unsigned num_used = 0;
   3642       unsigned idx = 0;
   3643       unsigned split_offset = 0;
   3644       for (unsigned i = 0, offset = 0; i < instr->definitions.size();
   3645            offset += instr->definitions[i++].bytes()) {
   3646          if (ctx.uses[instr->definitions[i].tempId()]) {
   3647             num_used++;
   3648             idx = i;
   3649             split_offset = offset;
   3650          }
   3651       }
   3652       bool done = false;
   3653       if (num_used == 1 && ctx.info[instr->operands[0].tempId()].is_vec() &&
   3654           ctx.uses[instr->operands[0].tempId()] == 1) {
   3655          Instruction* vec = ctx.info[instr->operands[0].tempId()].instr;
   3656 
   3657          unsigned off = 0;
   3658          Operand op;
   3659          for (Operand& vec_op : vec->operands) {
   3660             if (off == split_offset) {
   3661                op = vec_op;
   3662                break;
   3663             }
   3664             off += vec_op.bytes();
   3665          }
   3666          if (off != instr->operands[0].bytes() && op.bytes() == instr->definitions[idx].bytes()) {
   3667             ctx.uses[instr->operands[0].tempId()]--;
   3668             for (Operand& vec_op : vec->operands) {
   3669                if (vec_op.isTemp())
   3670                   ctx.uses[vec_op.tempId()]--;
   3671             }
   3672             if (op.isTemp())
   3673                ctx.uses[op.tempId()]++;
   3674 
   3675             aco_ptr<Pseudo_instruction> extract{create_instruction<Pseudo_instruction>(
   3676                aco_opcode::p_create_vector, Format::PSEUDO, 1, 1)};
   3677             extract->operands[0] = op;
   3678             extract->definitions[0] = instr->definitions[idx];
   3679             instr = std::move(extract);
   3680 
   3681             done = true;
   3682          }
   3683       }
   3684 
   3685       if (!done && num_used == 1 &&
   3686           instr->operands[0].bytes() % instr->definitions[idx].bytes() == 0 &&
   3687           split_offset % instr->definitions[idx].bytes() == 0) {
   3688          aco_ptr<Pseudo_instruction> extract{create_instruction<Pseudo_instruction>(
   3689             aco_opcode::p_extract_vector, Format::PSEUDO, 2, 1)};
   3690          extract->operands[0] = instr->operands[0];
   3691          extract->operands[1] =
   3692             Operand::c32((uint32_t)split_offset / instr->definitions[idx].bytes());
   3693          extract->definitions[0] = instr->definitions[idx];
   3694          instr = std::move(extract);
   3695       }
   3696    }
   3697 
   3698    mad_info* mad_info = NULL;
   3699    if (!instr->definitions.empty() && ctx.info[instr->definitions[0].tempId()].is_mad()) {
   3700       mad_info = &ctx.mad_infos[ctx.info[instr->definitions[0].tempId()].instr->pass_flags];
   3701       /* re-check mad instructions */
   3702       if (ctx.uses[mad_info->mul_temp_id] && mad_info->add_instr) {
   3703          ctx.uses[mad_info->mul_temp_id]++;
   3704          if (instr->operands[0].isTemp())
   3705             ctx.uses[instr->operands[0].tempId()]--;
   3706          if (instr->operands[1].isTemp())
   3707             ctx.uses[instr->operands[1].tempId()]--;
   3708          instr.swap(mad_info->add_instr);
   3709          mad_info = NULL;
   3710       }
   3711       /* check literals */
   3712       else if (!instr->usesModifiers() && instr->opcode != aco_opcode::v_fma_f64) {
   3713          /* FMA can only take literals on GFX10+ */
   3714          if ((instr->opcode == aco_opcode::v_fma_f32 || instr->opcode == aco_opcode::v_fma_f16) &&
   3715              ctx.program->chip_class < GFX10)
   3716             return;
   3717          /* There are no v_fmaak_legacy_f16/v_fmamk_legacy_f16 and on chips where VOP3 can take
   3718           * literals (GFX10+), these instructions don't exist.
   3719           */
   3720          if (instr->opcode == aco_opcode::v_fma_legacy_f16)
   3721             return;
   3722 
   3723          bool sgpr_used = false;
   3724          uint32_t literal_idx = 0;
   3725          uint32_t literal_uses = UINT32_MAX;
   3726          for (unsigned i = 0; i < instr->operands.size(); i++) {
   3727             if (instr->operands[i].isConstant() && i > 0) {
   3728                literal_uses = UINT32_MAX;
   3729                break;
   3730             }
   3731             if (!instr->operands[i].isTemp())
   3732                continue;
   3733             unsigned bits = get_operand_size(instr, i);
   3734             /* if one of the operands is sgpr, we cannot add a literal somewhere else on pre-GFX10
   3735              * or operands other than the 1st */
   3736             if (instr->operands[i].getTemp().type() == RegType::sgpr &&
   3737                 (i > 0 || ctx.program->chip_class < GFX10)) {
   3738                if (!sgpr_used && ctx.info[instr->operands[i].tempId()].is_literal(bits)) {
   3739                   literal_uses = ctx.uses[instr->operands[i].tempId()];
   3740                   literal_idx = i;
   3741                } else {
   3742                   literal_uses = UINT32_MAX;
   3743                }
   3744                sgpr_used = true;
   3745                /* don't break because we still need to check constants */
   3746             } else if (!sgpr_used && ctx.info[instr->operands[i].tempId()].is_literal(bits) &&
   3747                        ctx.uses[instr->operands[i].tempId()] < literal_uses) {
   3748                literal_uses = ctx.uses[instr->operands[i].tempId()];
   3749                literal_idx = i;
   3750             }
   3751          }
   3752 
   3753          /* Limit the number of literals to apply to not increase the code
   3754           * size too much, but always apply literals for v_mad->v_madak
   3755           * because both instructions are 64-bit and this doesn't increase
   3756           * code size.
   3757           * TODO: try to apply the literals earlier to lower the number of
   3758           * uses below threshold
   3759           */
   3760          if (literal_uses < threshold || literal_idx == 2) {
   3761             ctx.uses[instr->operands[literal_idx].tempId()]--;
   3762             mad_info->check_literal = true;
   3763             mad_info->literal_idx = literal_idx;
   3764             return;
   3765          }
   3766       }
   3767    }
   3768 
   3769    /* Mark SCC needed, so the uniform boolean transformation won't swap the definitions
   3770     * when it isn't beneficial */
   3771    if (instr->isBranch() && instr->operands.size() && instr->operands[0].isTemp() &&
   3772        instr->operands[0].isFixed() && instr->operands[0].physReg() == scc) {
   3773       ctx.info[instr->operands[0].tempId()].set_scc_needed();
   3774       return;
   3775    } else if ((instr->opcode == aco_opcode::s_cselect_b64 ||
   3776                instr->opcode == aco_opcode::s_cselect_b32) &&
   3777               instr->operands[2].isTemp()) {
   3778       ctx.info[instr->operands[2].tempId()].set_scc_needed();
   3779    } else if (instr->opcode == aco_opcode::p_wqm && instr->operands[0].isTemp() &&
   3780               ctx.info[instr->definitions[0].tempId()].is_scc_needed()) {
   3781       /* Propagate label so it is correctly detected by the uniform bool transform */
   3782       ctx.info[instr->operands[0].tempId()].set_scc_needed();
   3783 
   3784       /* Fix definition to SCC, this will prevent RA from adding superfluous moves */
   3785       instr->definitions[0].setFixed(scc);
   3786    }
   3787 
   3788    /* check for literals */
   3789    if (!instr->isSALU() && !instr->isVALU())
   3790       return;
   3791 
   3792    /* Transform uniform bitwise boolean operations to 32-bit when there are no divergent uses. */
   3793    if (instr->definitions.size() && ctx.uses[instr->definitions[0].tempId()] == 0 &&
   3794        ctx.info[instr->definitions[0].tempId()].is_uniform_bitwise()) {
   3795       bool transform_done = to_uniform_bool_instr(ctx, instr);
   3796 
   3797       if (transform_done && !ctx.info[instr->definitions[1].tempId()].is_scc_needed()) {
   3798          /* Swap the two definition IDs in order to avoid overusing the SCC.
   3799           * This reduces extra moves generated by RA. */
   3800          uint32_t def0_id = instr->definitions[0].getTemp().id();
   3801          uint32_t def1_id = instr->definitions[1].getTemp().id();
   3802          instr->definitions[0].setTemp(Temp(def1_id, s1));
   3803          instr->definitions[1].setTemp(Temp(def0_id, s1));
   3804       }
   3805 
   3806       return;
   3807    }
   3808 
   3809    /* Combine DPP copies into VALU. This should be done after creating MAD/FMA. */
   3810    if (instr->isVALU()) {
   3811       for (unsigned i = 0; i < instr->operands.size(); i++) {
   3812          if (!instr->operands[i].isTemp())
   3813             continue;
   3814          ssa_info info = ctx.info[instr->operands[i].tempId()];
   3815 
   3816          aco_opcode swapped_op;
   3817          if (info.is_dpp() && info.instr->pass_flags == instr->pass_flags &&
   3818              (i == 0 || can_swap_operands(instr, &swapped_op)) && can_use_DPP(instr, true) &&
   3819              !instr->isDPP()) {
   3820             convert_to_DPP(instr);
   3821             DPP_instruction* dpp = static_cast<DPP_instruction*>(instr.get());
   3822             if (i) {
   3823                instr->opcode = swapped_op;
   3824                std::swap(instr->operands[0], instr->operands[1]);
   3825                std::swap(dpp->neg[0], dpp->neg[1]);
   3826                std::swap(dpp->abs[0], dpp->abs[1]);
   3827             }
   3828             if (--ctx.uses[info.instr->definitions[0].tempId()])
   3829                ctx.uses[info.instr->operands[0].tempId()]++;
   3830             instr->operands[0].setTemp(info.instr->operands[0].getTemp());
   3831             dpp->dpp_ctrl = info.instr->dpp().dpp_ctrl;
   3832             dpp->bound_ctrl = info.instr->dpp().bound_ctrl;
   3833             dpp->neg[0] ^= info.instr->dpp().neg[0] && !dpp->abs[0];
   3834             dpp->abs[0] |= info.instr->dpp().abs[0];
   3835             break;
   3836          }
   3837       }
   3838    }
   3839 
   3840    if (instr->isSDWA() || (instr->isVOP3() && ctx.program->chip_class < GFX10) ||
   3841        (instr->isVOP3P() && ctx.program->chip_class < GFX10))
   3842       return; /* some encodings can't ever take literals */
   3843 
   3844    /* we do not apply the literals yet as we don't know if it is profitable */
   3845    Operand current_literal(s1);
   3846 
   3847    unsigned literal_id = 0;
   3848    unsigned literal_uses = UINT32_MAX;
   3849    Operand literal(s1);
   3850    unsigned num_operands = 1;
   3851    if (instr->isSALU() ||
   3852        (ctx.program->chip_class >= GFX10 && (can_use_VOP3(ctx, instr) || instr->isVOP3P())))
   3853       num_operands = instr->operands.size();
   3854    /* catch VOP2 with a 3rd SGPR operand (e.g. v_cndmask_b32, v_addc_co_u32) */
   3855    else if (instr->isVALU() && instr->operands.size() >= 3)
   3856       return;
   3857 
   3858    unsigned sgpr_ids[2] = {0, 0};
   3859    bool is_literal_sgpr = false;
   3860    uint32_t mask = 0;
   3861 
   3862    /* choose a literal to apply */
   3863    for (unsigned i = 0; i < num_operands; i++) {
   3864       Operand op = instr->operands[i];
   3865       unsigned bits = get_operand_size(instr, i);
   3866 
   3867       if (instr->isVALU() && op.isTemp() && op.getTemp().type() == RegType::sgpr &&
   3868           op.tempId() != sgpr_ids[0])
   3869          sgpr_ids[!!sgpr_ids[0]] = op.tempId();
   3870 
   3871       if (op.isLiteral()) {
   3872          current_literal = op;
   3873          continue;
   3874       } else if (!op.isTemp() || !ctx.info[op.tempId()].is_literal(bits)) {
   3875          continue;
   3876       }
   3877 
   3878       if (!alu_can_accept_constant(instr->opcode, i))
   3879          continue;
   3880 
   3881       if (ctx.uses[op.tempId()] < literal_uses) {
   3882          is_literal_sgpr = op.getTemp().type() == RegType::sgpr;
   3883          mask = 0;
   3884          literal = Operand::c32(ctx.info[op.tempId()].val);
   3885          literal_uses = ctx.uses[op.tempId()];
   3886          literal_id = op.tempId();
   3887       }
   3888 
   3889       mask |= (op.tempId() == literal_id) << i;
   3890    }
   3891 
   3892    /* don't go over the constant bus limit */
   3893    bool is_shift64 = instr->opcode == aco_opcode::v_lshlrev_b64 ||
   3894                      instr->opcode == aco_opcode::v_lshrrev_b64 ||
   3895                      instr->opcode == aco_opcode::v_ashrrev_i64;
   3896    unsigned const_bus_limit = instr->isVALU() ? 1 : UINT32_MAX;
   3897    if (ctx.program->chip_class >= GFX10 && !is_shift64)
   3898       const_bus_limit = 2;
   3899 
   3900    unsigned num_sgprs = !!sgpr_ids[0] + !!sgpr_ids[1];
   3901    if (num_sgprs == const_bus_limit && !is_literal_sgpr)
   3902       return;
   3903 
   3904    if (literal_id && literal_uses < threshold &&
   3905        (current_literal.isUndefined() ||
   3906         (current_literal.size() == literal.size() &&
   3907          current_literal.constantValue() == literal.constantValue()))) {
   3908       /* mark the literal to be applied */
   3909       while (mask) {
   3910          unsigned i = u_bit_scan(&mask);
   3911          if (instr->operands[i].isTemp() && instr->operands[i].tempId() == literal_id)
   3912             ctx.uses[instr->operands[i].tempId()]--;
   3913       }
   3914    }
   3915 }
   3916 
   3917 void
   3918 apply_literals(opt_ctx& ctx, aco_ptr<Instruction>& instr)
   3919 {
   3920    /* Cleanup Dead Instructions */
   3921    if (!instr)
   3922       return;
   3923 
   3924    /* apply literals on MAD */
   3925    if (!instr->definitions.empty() && ctx.info[instr->definitions[0].tempId()].is_mad()) {
   3926       mad_info* info = &ctx.mad_infos[ctx.info[instr->definitions[0].tempId()].instr->pass_flags];
   3927       if (info->check_literal &&
   3928           (ctx.uses[instr->operands[info->literal_idx].tempId()] == 0 || info->literal_idx == 2)) {
   3929          aco_ptr<Instruction> new_mad;
   3930 
   3931          aco_opcode new_op =
   3932             info->literal_idx == 2 ? aco_opcode::v_madak_f32 : aco_opcode::v_madmk_f32;
   3933          if (instr->opcode == aco_opcode::v_fma_f32)
   3934             new_op = info->literal_idx == 2 ? aco_opcode::v_fmaak_f32 : aco_opcode::v_fmamk_f32;
   3935          else if (instr->opcode == aco_opcode::v_mad_f16 ||
   3936                   instr->opcode == aco_opcode::v_mad_legacy_f16)
   3937             new_op = info->literal_idx == 2 ? aco_opcode::v_madak_f16 : aco_opcode::v_madmk_f16;
   3938          else if (instr->opcode == aco_opcode::v_fma_f16)
   3939             new_op = info->literal_idx == 2 ? aco_opcode::v_fmaak_f16 : aco_opcode::v_fmamk_f16;
   3940 
   3941          new_mad.reset(create_instruction<VOP2_instruction>(new_op, Format::VOP2, 3, 1));
   3942          if (info->literal_idx == 2) { /* add literal -> madak */
   3943             new_mad->operands[0] = instr->operands[0];
   3944             new_mad->operands[1] = instr->operands[1];
   3945          } else { /* mul literal -> madmk */
   3946             new_mad->operands[0] = instr->operands[1 - info->literal_idx];
   3947             new_mad->operands[1] = instr->operands[2];
   3948          }
   3949          new_mad->operands[2] =
   3950             Operand::c32(ctx.info[instr->operands[info->literal_idx].tempId()].val);
   3951          new_mad->definitions[0] = instr->definitions[0];
   3952          ctx.instructions.emplace_back(std::move(new_mad));
   3953          return;
   3954       }
   3955    }
   3956 
   3957    /* apply literals on other SALU/VALU */
   3958    if (instr->isSALU() || instr->isVALU()) {
   3959       for (unsigned i = 0; i < instr->operands.size(); i++) {
   3960          Operand op = instr->operands[i];
   3961          unsigned bits = get_operand_size(instr, i);
   3962          if (op.isTemp() && ctx.info[op.tempId()].is_literal(bits) && ctx.uses[op.tempId()] == 0) {
   3963             Operand literal = Operand::c32(ctx.info[op.tempId()].val);
   3964             instr->format = withoutDPP(instr->format);
   3965             if (instr->isVALU() && i > 0 && instr->format != Format::VOP3P)
   3966                to_VOP3(ctx, instr);
   3967             instr->operands[i] = literal;
   3968          }
   3969       }
   3970    }
   3971 
   3972    ctx.instructions.emplace_back(std::move(instr));
   3973 }
   3974 
   3975 void
   3976 optimize(Program* program)
   3977 {
   3978    opt_ctx ctx;
   3979    ctx.program = program;
   3980    std::vector<ssa_info> info(program->peekAllocationId());
   3981    ctx.info = info.data();
   3982 
   3983    /* 1. Bottom-Up DAG pass (forward) to label all ssa-defs */
   3984    for (Block& block : program->blocks) {
   3985       ctx.fp_mode = block.fp_mode;
   3986       for (aco_ptr<Instruction>& instr : block.instructions)
   3987          label_instruction(ctx, instr);
   3988    }
   3989 
   3990    ctx.uses = dead_code_analysis(program);
   3991 
   3992    /* 2. Combine v_mad, omod, clamp and propagate sgpr on VALU instructions */
   3993    for (Block& block : program->blocks) {
   3994       ctx.fp_mode = block.fp_mode;
   3995       for (aco_ptr<Instruction>& instr : block.instructions)
   3996          combine_instruction(ctx, instr);
   3997    }
   3998 
   3999    /* 3. Top-Down DAG pass (backward) to select instructions (includes DCE) */
   4000    for (auto block_rit = program->blocks.rbegin(); block_rit != program->blocks.rend();
   4001         ++block_rit) {
   4002       Block* block = &(*block_rit);
   4003       ctx.fp_mode = block->fp_mode;
   4004       for (auto instr_rit = block->instructions.rbegin(); instr_rit != block->instructions.rend();
   4005            ++instr_rit)
   4006          select_instruction(ctx, *instr_rit);
   4007    }
   4008 
   4009    /* 4. Add literals to instructions */
   4010    for (Block& block : program->blocks) {
   4011       ctx.instructions.clear();
   4012       ctx.fp_mode = block.fp_mode;
   4013       for (aco_ptr<Instruction>& instr : block.instructions)
   4014          apply_literals(ctx, instr);
   4015       block.instructions.swap(ctx.instructions);
   4016    }
   4017 }
   4018 
   4019 } // namespace aco
   4020