~mmach/netext73/mesa-ryzen

« back to all changes in this revision

Viewing changes to src/gallium/drivers/r600/sfn/sfn_instr_alu.cpp

  • Committer: mmach
  • Date: 2023-11-02 21:31:35 UTC
  • Revision ID: netbit73@gmail.com-20231102213135-18d4tzh7tj0uz752
2023-11-02 22:11:57

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
#include "sfn_instr_alugroup.h"
32
32
#include "sfn_instr_tex.h"
33
33
#include "sfn_shader.h"
 
34
#include "sfn_virtualvalues.h"
34
35
 
35
36
#include <algorithm>
36
37
#include <sstream>
71
72
 
72
73
   if (dest && slots > 1) {
73
74
      switch (m_opcode) {
74
 
      case op2_dot_ieee: m_allowed_desk_mask = (1 << (5 - slots)) - 1;
 
75
      case op2_dot_ieee: m_allowed_dest_mask = (1 << (5 - slots)) - 1;
75
76
         break;
76
77
      default:
77
78
         if (has_alu_flag(alu_is_cayman_trans)) {
78
 
            m_allowed_desk_mask = (1 << slots) - 1;
 
79
            m_allowed_dest_mask = (1 << slots) - 1;
79
80
         }
80
81
      }
81
82
   }
82
 
   assert(!dest || (m_allowed_desk_mask & (1 << dest->chan())));
 
83
   assert(!dest || (m_allowed_dest_mask & (1 << dest->chan())));
83
84
}
84
85
 
85
86
AluInstr::AluInstr(EAluOp opcode):
168
169
         u->buf_addr()->as_register()->add_use(this);
169
170
   }
170
171
 
171
 
   if (m_dest && has_alu_flag(alu_write)) {
 
172
   if (m_dest &&
 
173
       (has_alu_flag(alu_write) ||
 
174
        m_opcode == op1_mova_int ||
 
175
        m_opcode == op1_set_cf_idx0 ||
 
176
        m_opcode == op1_set_cf_idx1)) {
172
177
      m_dest->add_parent(this);
173
178
 
174
179
      if (m_dest->pin() == pin_array) {
212
217
   {alu_vec_210, "VEC_210"}
213
218
};
214
219
 
215
 
const AluModifiers AluInstr::src_abs_flags[2] = {alu_src0_abs, alu_src1_abs};
216
 
const AluModifiers AluInstr::src_neg_flags[3] = {
217
 
   alu_src0_neg, alu_src1_neg, alu_src2_neg};
218
220
const AluModifiers AluInstr::src_rel_flags[3] = {
219
221
   alu_src0_rel, alu_src1_rel, alu_src2_rel};
220
222
 
253
255
         os << " CLAMP";
254
256
 
255
257
      if (m_dest) {
256
 
         if (has_alu_flag(alu_write))
 
258
         if (has_alu_flag(alu_write) || m_dest->has_flag(Register::addr_or_idx)) {
257
259
            os << " " << *m_dest;
258
 
         else
 
260
         } else {
259
261
            os << " __"
260
262
               << "." << swzchar[m_dest->chan()];
261
 
         if (!has_alu_flag(alu_write) && m_dest->pin() != pin_none)
262
 
            os << "@" << m_dest->pin();
 
263
            if (m_dest->pin() != pin_none)
 
264
               os << "@" << m_dest->pin();
 
265
         }
263
266
         os << " : ";
264
267
      } else {
265
 
         os << "__." << swzchar[dest_chan()] << " : ";
 
268
         os << " __." << swzchar[dest_chan()] << " : ";
266
269
      }
267
270
   }
268
271
 
269
272
   const int n_source_per_slot =
270
273
      has_alu_flag(alu_is_lds) ? m_src.size() : alu_ops.at(m_opcode).nsrc;
271
274
 
 
275
 
272
276
   for (int s = 0; s < m_alu_slots; ++s) {
273
277
 
274
278
      if (s > 0)
278
282
         int pflags = 0;
279
283
         if (i)
280
284
            os << ' ';
281
 
         if (has_alu_flag(src_neg_flags[k]))
 
285
         if (has_source_mod(i, mod_neg))
282
286
            pflags |= ValuePrintFlags::has_neg;
283
287
         if (has_alu_flag(src_rel_flags[k]))
284
288
            pflags |= ValuePrintFlags::is_rel;
285
 
         if (i < 2)
286
 
            if (has_alu_flag(src_abs_flags[k]))
 
289
         if (n_source_per_slot <= 2)
 
290
            if (has_source_mod(i, mod_abs))
287
291
               pflags |= ValuePrintFlags::has_abs;
288
292
 
289
293
         if (pflags & ValuePrintFlags::has_neg)
345
349
   return m_dest->pin() == pin_none || m_dest->pin() == pin_free;
346
350
}
347
351
 
 
352
class ReplaceIndirectArrayAddr : public RegisterVisitor {
 
353
public:
 
354
   void visit(Register& value) override { (void)value; }
 
355
   void visit(LocalArray& value) override
 
356
   {
 
357
      (void)value;
 
358
      unreachable("An array can't be used as address");
 
359
   }
 
360
   void visit(LocalArrayValue& value) override;
 
361
   void visit(UniformValue& value) override;
 
362
   void visit(LiteralConstant& value) override { (void)value; }
 
363
   void visit(InlineConstant& value) override { (void)value; }
 
364
 
 
365
   PRegister new_addr;
 
366
};
 
367
 
 
368
void ReplaceIndirectArrayAddr::visit(LocalArrayValue& value)
 
369
{
 
370
   if (new_addr->sel() == 0 && value.addr()->as_register())
 
371
      value.set_addr(new_addr);
 
372
}
 
373
 
 
374
void ReplaceIndirectArrayAddr::visit(UniformValue& value)
 
375
{
 
376
   if (value.buf_addr() && value.buf_addr()->as_register() &&
 
377
       (new_addr->sel() == 1 || new_addr->sel() == 2)) {
 
378
      value.set_buf_addr(new_addr);
 
379
   }
 
380
}
 
381
 
 
382
void AluInstr::update_indirect_addr(PRegister reg)
 
383
{
 
384
   ReplaceIndirectArrayAddr visitor;
 
385
   visitor.new_addr = reg;
 
386
   assert(reg->has_flag(Register::addr_or_idx));
 
387
 
 
388
   if (m_dest)
 
389
      m_dest->accept(visitor);
 
390
 
 
391
   for (auto src : m_src)
 
392
      src->accept(visitor);
 
393
 
 
394
   reg->add_use(this);
 
395
}
 
396
 
348
397
bool
349
398
AluInstr::can_propagate_dest() const
350
399
{
366
415
   if (!src_reg->has_flag(Register::ssa))
367
416
      return false;
368
417
 
 
418
   if (!m_dest->has_flag(Register::ssa))
 
419
      return false;
 
420
 
369
421
   if (src_reg->pin() == pin_chan)
370
422
      return m_dest->pin() == pin_none || m_dest->pin() == pin_free ||
371
423
             ((m_dest->pin() == pin_chan || m_dest->pin() == pin_group) &&
380
432
   if (m_opcode != op1_mov)
381
433
      return false;
382
434
 
383
 
   if (has_alu_flag(alu_src0_abs) || has_alu_flag(alu_src0_neg) ||
 
435
   if (has_source_mod(0, mod_abs) || has_source_mod(0, mod_neg) ||
384
436
       has_alu_flag(alu_dst_clamp))
385
437
      return false;
386
438
 
416
468
   return process;
417
469
}
418
470
 
 
471
bool AluInstr::replace_src(int i, PVirtualValue new_src, uint32_t to_set,
 
472
                           SourceMod to_clear)
 
473
{
 
474
   auto old_src = m_src[i]->as_register();
 
475
   assert(old_src);
 
476
 
 
477
   if (!can_replace_source(old_src, new_src))
 
478
      return false;
 
479
 
 
480
   assert(old_src);
 
481
   old_src->del_use(this);
 
482
 
 
483
   m_src[i] = new_src;
 
484
 
 
485
   auto r = new_src->as_register();
 
486
   if (r)
 
487
      r->add_use(this);
 
488
 
 
489
   m_source_modifiers |= to_set << (2 * i);
 
490
   m_source_modifiers &= ~(to_clear  << (2 * i));
 
491
 
 
492
   return true;
 
493
}
 
494
 
 
495
 
419
496
bool AluInstr::can_replace_source(PRegister old_src, PVirtualValue new_src)
420
497
{
421
498
   if (!check_readport_validation(old_src, new_src))
422
499
      return false;
423
500
 
424
 
   /* If the old source is an array element, we assume that there
 
501
   /* If the old or new source is an array element, we assume that there
425
502
    * might have been an (untracked) indirect access, so don't replace
426
503
    * this source */
427
 
   if (old_src->pin() == pin_array)
 
504
   if (old_src->pin() == pin_array || new_src->pin() == pin_array)
428
505
      return false;
429
506
 
430
 
   if (new_src->get_addr()) {
431
 
      for (auto& s : m_src) {
432
 
         auto addr = s->get_addr();
433
 
         /* can't have two differen't indirect addresses in the same instr */
434
 
         if (addr && !addr->equal_to(*new_src->get_addr()))
 
507
   auto [addr, dummy, index] = indirect_addr();
 
508
   auto addr_reg = addr ?  addr->as_register() : nullptr;
 
509
   auto index_reg = index ? index->as_register() : nullptr;
 
510
 
 
511
   if (auto u = new_src->as_uniform()) {
 
512
      if (u && u->buf_addr()) {
 
513
 
 
514
         /* Don't mix indirect buffer and indirect registers, because the
 
515
          * scheduler can't handle it yet. */
 
516
         if (addr_reg)
 
517
            return false;
 
518
 
 
519
         /* Don't allow two different index registers, can't deal with that yet */
 
520
         if (index_reg && !index_reg->equal_to(*u->buf_addr()))
435
521
            return false;
436
522
      }
437
523
   }
438
524
 
439
 
   if (m_dest) {
440
 
      /* We don't allow src and dst with rel and different indirect register
441
 
       * addresses */
442
 
      if (m_dest->pin() == pin_array && new_src->pin() == pin_array) {
443
 
         auto dav = static_cast<const LocalArrayValue *>(m_dest)->addr();
444
 
         auto sav = static_cast<const LocalArrayValue *>(new_src)->addr();
445
 
         if (dav && sav && dav->as_register() && !dav->equal_to(*sav))
 
525
   if (auto new_addr = new_src->get_addr()) {
 
526
      auto new_addr_reg = new_addr->as_register();
 
527
      bool new_addr_lowered = new_addr_reg &&
 
528
                              new_addr_reg->has_flag(Register::addr_or_idx);
 
529
 
 
530
      if (addr_reg) {
 
531
         if (!addr_reg->equal_to(*new_addr) || new_addr_lowered ||
 
532
             addr_reg->has_flag(Register::addr_or_idx))
446
533
            return false;
 
534
      }
 
535
      if (m_dest->has_flag(Register::addr_or_idx)) {
 
536
         if (new_src->pin() == pin_array) {
 
537
            auto s = static_cast<const LocalArrayValue *>(new_src)->addr();
 
538
            if (!s->as_inline_const() || !s->as_literal())
 
539
               return false;
 
540
         }
447
541
      }
448
542
   }
449
543
   return true;
516
610
      return false;
517
611
 
518
612
   /* Currently we bail out when an array write should be moved, because
519
 
    * decalring an array write is currently not well defined. The
520
 
    * Whole "backwards" copy propagation shoul dprobably be replaced by some
 
613
    * declaring an array write is currently not well defined. The
 
614
    * Whole "backwards" copy propagation should dprobably be replaced by some
521
615
    * forward peep holew optimization */
522
616
   /*
523
617
   if (new_dest->pin() == pin_array) {
666
760
   void visit(const InlineConstant& value) { (void)value; }
667
761
 
668
762
   PRegister addr{nullptr};
669
 
   bool is_index{false};
 
763
   PRegister index{nullptr};
 
764
   bool addr_is_for_dest{false};
670
765
};
671
766
 
672
767
void
673
768
ResolveIndirectArrayAddr::visit(const LocalArrayValue& value)
674
769
{
675
770
   auto a = value.addr();
676
 
   if (a)
 
771
   if (a) {
677
772
      addr = a->as_register();
 
773
      assert(!addr_is_for_dest);
 
774
   }
678
775
}
679
776
 
680
777
void
682
779
{
683
780
   auto a = value.buf_addr();
684
781
   if (a) {
685
 
      addr = a->as_register();
686
 
      is_index = true;
 
782
      index = a->as_register();
687
783
   }
688
784
}
689
785
 
690
 
std::tuple<PRegister, bool, bool>
 
786
std::tuple<PRegister, bool, PRegister>
691
787
AluInstr::indirect_addr() const
692
788
{
693
789
   ResolveIndirectArrayAddr visitor;
695
791
   if (m_dest) {
696
792
      m_dest->accept(visitor);
697
793
      if (visitor.addr)
698
 
         return {visitor.addr, false, false};
 
794
          visitor.addr_is_for_dest = true;
699
795
   }
700
796
 
701
797
   for (auto s : m_src) {
702
798
      s->accept(visitor);
703
 
      if (visitor.addr) {
704
 
         return {visitor.addr, !visitor.is_index, visitor.is_index};
705
 
      }
706
799
   }
707
 
   return {nullptr, false, false};
 
800
   return {visitor.addr, visitor.addr_is_for_dest, visitor.index};
708
801
}
709
802
 
710
803
AluGroup *
764
857
      instr->set_blockid(block_id(), index());
765
858
 
766
859
      if (s == 0 || !m_alu_flags.test(alu_64bit_op)) {
767
 
         if (has_alu_flag(alu_src0_neg))
768
 
            instr->set_alu_flag(alu_src0_neg);
769
 
         if (has_alu_flag(alu_src1_neg))
770
 
            instr->set_alu_flag(alu_src1_neg);
771
 
         if (has_alu_flag(alu_src2_neg))
772
 
            instr->set_alu_flag(alu_src2_neg);
773
 
         if (has_alu_flag(alu_src0_abs))
774
 
            instr->set_alu_flag(alu_src0_abs);
775
 
         if (has_alu_flag(alu_src1_abs))
776
 
            instr->set_alu_flag(alu_src1_abs);
 
860
         if (has_source_mod(nsrc * k + 0, mod_neg))
 
861
            instr->set_source_mod(0, mod_neg);
 
862
         if (has_source_mod(nsrc * k + 1, mod_neg))
 
863
            instr->set_source_mod(1, mod_neg);
 
864
         if (has_source_mod(nsrc * k + 2, mod_neg))
 
865
            instr->set_source_mod(2, mod_neg);
 
866
         if (has_source_mod(nsrc * k + 0, mod_abs))
 
867
            instr->set_source_mod(0, mod_abs);
 
868
         if (has_source_mod(nsrc * k + 1, mod_abs))
 
869
            instr->set_source_mod(1, mod_abs);
777
870
      }
778
871
      if (has_alu_flag(alu_dst_clamp))
779
872
         instr->set_alu_flag(alu_dst_clamp);
815
908
 
816
909
      if (m_dest) {
817
910
         if (m_dest->has_flag(Register::ssa) && has_alu_flag(alu_write)) {
818
 
            if (m_dest->pin() != pin_group && m_dest->pin() != pin_chgr)
 
911
            if (m_dest->pin() != pin_group && m_dest->pin() != pin_chgr &&
 
912
                !m_dest->addr())
819
913
               priority--;
820
914
         } else {
821
915
            // Arrays and registers are pre-allocated, hence scheduling
826
920
 
827
921
      for (const auto s : m_src) {
828
922
         auto r = s->as_register();
829
 
         if (r && r->has_flag(Register::ssa)) {
830
 
            int pending = 0;
831
 
            for (auto b : r->uses()) {
832
 
               if (!b->is_scheduled())
833
 
                  ++pending;
 
923
         if (r) {
 
924
            if (r->has_flag(Register::ssa)) {
 
925
               int pending = 0;
 
926
               for (auto b : r->uses()) {
 
927
                  if (!b->is_scheduled())
 
928
                     ++pending;
 
929
               }
 
930
               if (pending == 1)
 
931
                  ++priority;
834
932
            }
835
 
            if (pending == 1)
836
 
               ++priority;
 
933
            if (r->addr() && r->addr()->as_register())
 
934
               priority += 2;
837
935
         }
838
936
         if (s->as_uniform())
839
937
            ++priority;
865
963
 
866
964
   /* We assume that nir does a good job in eliminating all ALU results that
867
965
    * are not needed, and we don't let copy propagation doesn't make the
868
 
    * instruction obsolte, so just keep all */
 
966
    * instruction obsolete, so just keep all */
869
967
   if (has_alu_flag(alu_is_cayman_trans))
870
968
      return false;
871
969
 
1002
1100
 
1003
1101
   int slots = 0;
1004
1102
 
1005
 
 
 
1103
   uint32_t src_mods = 0;
1006
1104
   SrcValues sources;
1007
1105
   do {
1008
1106
      ++t;
1010
1108
         string srcstr = *t++;
1011
1109
 
1012
1110
         if (srcstr[0] == '-') {
1013
 
            if (!slots)
1014
 
               flags.insert(AluInstr::src_neg_flags[i]);
1015
 
            else
1016
 
               assert(flags.find(AluInstr::src_neg_flags[i]) != flags.end());
 
1111
            src_mods |= AluInstr::mod_neg << (2 * sources.size());
1017
1112
            srcstr = srcstr.substr(1);
1018
1113
         }
1019
1114
 
1020
1115
         if (srcstr[0] == '|') {
1021
1116
            assert(srcstr[srcstr.length() - 1] == '|');
1022
 
            if (!slots)
1023
 
               flags.insert(AluInstr::src_abs_flags[i]);
1024
 
            else
1025
 
               assert(flags.find(AluInstr::src_abs_flags[i]) != flags.end());
 
1117
            src_mods |= AluInstr::mod_abs << (2 * sources.size());
1026
1118
            srcstr = srcstr.substr(1, srcstr.length() - 2);
1027
1119
         }
1028
1120
 
1122
1214
   else
1123
1215
      retval = new AluInstr(op_descr.alu_opcode, dest, sources, flags, slots);
1124
1216
 
 
1217
   retval->m_source_modifiers = src_mods;
1125
1218
   retval->set_bank_swizzle(bank_swizzle);
1126
1219
   retval->set_cf_type(cf);
1127
1220
   if (group) {
1206
1299
   instr->predicate()->accept(*this);
1207
1300
}
1208
1301
 
 
1302
bool AluInstr::is_kill() const
 
1303
{
 
1304
   if (has_alu_flag(alu_is_lds))
 
1305
      return false;
 
1306
 
 
1307
   switch (m_opcode) {
 
1308
   case op2_kille:
 
1309
   case op2_kille_int:
 
1310
   case op2_killne:
 
1311
   case op2_killne_int:
 
1312
   case op2_killge:
 
1313
   case op2_killge_int:
 
1314
   case op2_killge_uint:
 
1315
   case op2_killgt:
 
1316
   case op2_killgt_int:
 
1317
   case op2_killgt_uint:
 
1318
      return true;
 
1319
   default:
 
1320
      return false;
 
1321
   }
 
1322
}
 
1323
 
 
1324
enum AluMods {
 
1325
   mod_none,
 
1326
   mod_src0_abs,
 
1327
   mod_src0_neg,
 
1328
   mod_dest_clamp,
 
1329
};
 
1330
 
1209
1331
static bool
1210
1332
emit_alu_b2x(const nir_alu_instr& alu, AluInlineConstants mask, Shader& shader);
1211
1333
 
 
1334
 
 
1335
 
1212
1336
static bool
1213
1337
emit_alu_op1(const nir_alu_instr& alu,
1214
1338
             EAluOp opcode,
1215
1339
             Shader& shader,
1216
 
             const AluOpFlags& flags = 0);
 
1340
             AluMods mod = mod_none);
1217
1341
static bool
1218
1342
emit_alu_op1_64bit(const nir_alu_instr& alu,
1219
1343
                   EAluOp opcode,
1247
1371
emit_alu_f2f32(const nir_alu_instr& alu, Shader& shader);
1248
1372
static bool
1249
1373
emit_alu_abs64(const nir_alu_instr& alu, Shader& shader);
 
1374
static bool
 
1375
emit_alu_fsat64(const nir_alu_instr& alu, Shader& shader);
1250
1376
 
1251
1377
static bool
1252
1378
emit_alu_op2(const nir_alu_instr& alu,
1362
1488
         return emit_alu_mov_64bit(*alu, shader);
1363
1489
      case nir_op_fneg:
1364
1490
         return emit_alu_neg(*alu, shader);
 
1491
      case nir_op_fsat:
 
1492
         return emit_alu_fsat64(*alu, shader);
1365
1493
      case nir_op_ffract:
1366
1494
         return emit_alu_op1_64bit(*alu, op1_fract_64, shader, true);
1367
1495
      case nir_op_feq32:
1561
1689
      return emit_alu_op3(*alu, op3_cnde_int, shader, {0, 2, 1});
1562
1690
 
1563
1691
   case nir_op_fabs:
1564
 
      return emit_alu_op1(*alu, op1_mov, shader, {1 << alu_src0_abs});
 
1692
      return emit_alu_op1(*alu, op1_mov, shader, mod_src0_abs);
1565
1693
   case nir_op_fadd:
1566
1694
      return emit_alu_op2(*alu, op2_add, shader);
1567
1695
   case nir_op_fceil:
1619
1747
      return emit_alu_op2(*alu, op2_mul, shader);
1620
1748
 
1621
1749
   case nir_op_fneg:
1622
 
      return emit_alu_op1(*alu, op1_mov, shader, {1 << alu_src0_neg});
 
1750
      return emit_alu_op1(*alu, op1_mov, shader, mod_src0_neg);
1623
1751
   case nir_op_fneu32:
1624
1752
      return emit_alu_op2(*alu, op2_setne_dx10, shader);
1625
1753
   case nir_op_fneu:
1628
1756
   case nir_op_fround_even:
1629
1757
      return emit_alu_op1(*alu, op1_rndne, shader);
1630
1758
   case nir_op_fsat:
1631
 
      return emit_alu_op1(*alu, op1_mov, shader, {1 << alu_dst_clamp});
 
1759
      return emit_alu_op1(*alu, op1_mov, shader, mod_dest_clamp);
1632
1760
   case nir_op_fsub:
1633
1761
      return emit_alu_op2(*alu, op2_add, shader, op2_opt_neg_src1);
1634
1762
   case nir_op_ftrunc:
1748
1876
      return emit_tex_fdd(*alu, TexInstr::get_gradient_v, false, shader);
1749
1877
   case nir_op_fddy_fine:
1750
1878
      return emit_tex_fdd(*alu, TexInstr::get_gradient_v, true, shader);
1751
 
   case nir_op_cube_r600:
 
1879
   case nir_op_cube_amd:
1752
1880
      return emit_alu_cube(*alu, shader);
1753
1881
   default:
1754
1882
      fprintf(stderr, "Unknown instruction '");
1791
1919
                        value_factory.src64(alu.src[0], i, swz[0]),
1792
1920
                        {alu_write});
1793
1921
      group->add_instruction(ir);
1794
 
      if (alu.src[0].abs)
1795
 
         ir->set_alu_flag(alu_src0_abs);
1796
 
      if (alu.src[0].negate)
1797
 
         ir->set_alu_flag(alu_src0_neg);
1798
1922
 
1799
1923
      ir = new AluInstr(opcode,
1800
1924
                        value_factory.dest(alu.dest, 2 * i + 1, pin_chan),
1823
1947
                           {alu_write});
1824
1948
         shader.emit_instruction(ir);
1825
1949
      }
1826
 
      if (alu.src[0].abs)
1827
 
         ir->set_alu_flag(alu_src0_abs);
1828
 
      if (alu.src[0].negate)
1829
 
         ir->set_alu_flag(alu_src0_neg);
1830
1950
   }
1831
1951
   if (ir)
1832
1952
      ir->set_alu_flag(alu_last_instr);
1838
1958
{
1839
1959
   auto& value_factory = shader.value_factory();
1840
1960
 
1841
 
   auto group = new AluGroup();
1842
 
 
1843
1961
   AluInstr *ir = nullptr;
1844
1962
 
1845
1963
   for (unsigned i = 0; i < nir_dest_num_components(alu.dest.dest); ++i) {
1848
1966
                           value_factory.dest(alu.dest, 2 * i + c, pin_chan),
1849
1967
                           value_factory.src64(alu.src[0], i, c),
1850
1968
                           {alu_write});
1851
 
         group->add_instruction(ir);
 
1969
         shader.emit_instruction(ir);
1852
1970
      }
1853
 
      ir->set_alu_flag(alu_src0_neg);
 
1971
      ir->set_source_mod(0, AluInstr::mod_neg);
1854
1972
   }
1855
1973
   if (ir)
1856
1974
      ir->set_alu_flag(alu_last_instr);
1857
 
   shader.emit_instruction(group);
 
1975
 
1858
1976
   return true;
1859
1977
}
1860
1978
 
1874
1992
                          value_factory.dest(alu.dest, 1, pin_chan),
1875
1993
                          value_factory.src64(alu.src[0], 0, 1),
1876
1994
                          AluInstr::last_write);
1877
 
   ir->set_alu_flag(alu_src0_abs);
 
1995
   ir->set_source_mod(0, AluInstr::mod_abs);
1878
1996
   shader.emit_instruction(ir);
1879
1997
   return true;
1880
1998
}
1881
1999
 
1882
2000
static bool
 
2001
try_propagat_fsat64(const nir_alu_instr& alu, Shader& shader)
 
2002
{
 
2003
   auto& value_factory = shader.value_factory();
 
2004
   auto src0 = value_factory.src64(alu.src[0], 0, 0);
 
2005
   auto reg0 = src0->as_register();
 
2006
   if (!reg0)
 
2007
      return false;
 
2008
 
 
2009
   if (!reg0->has_flag(Register::ssa))
 
2010
      return false;
 
2011
 
 
2012
   if (reg0->parents().size() != 1)
 
2013
      return false;
 
2014
 
 
2015
   if (!reg0->uses().empty())
 
2016
      return false;
 
2017
 
 
2018
   auto parent = (*reg0->parents().begin())->as_alu();
 
2019
   if (!parent)
 
2020
      return false;
 
2021
 
 
2022
   auto opinfo = alu_ops.at(parent->opcode());
 
2023
   if (!opinfo.can_clamp)
 
2024
      return false;
 
2025
 
 
2026
   parent->set_alu_flag(alu_dst_clamp);
 
2027
   return true;
 
2028
}
 
2029
 
 
2030
 
 
2031
static bool
 
2032
emit_alu_fsat64(const nir_alu_instr& alu, Shader& shader)
 
2033
{
 
2034
   auto& value_factory = shader.value_factory();
 
2035
 
 
2036
   assert(nir_dest_num_components(alu.dest.dest) == 1);
 
2037
 
 
2038
   if (try_propagat_fsat64(alu, shader)) {
 
2039
      auto ir = new AluInstr(op1_mov,
 
2040
                             value_factory.dest(alu.dest, 0, pin_chan),
 
2041
                             value_factory.src64(alu.src[0], 0, 0),
 
2042
                             AluInstr::write);
 
2043
      shader.emit_instruction(ir);
 
2044
 
 
2045
      shader.emit_instruction(new AluInstr(op1_mov,
 
2046
                                           value_factory.dest(alu.dest, 1, pin_chan),
 
2047
                                           value_factory.src64(alu.src[0], 0, 1),
 
2048
                              AluInstr::last_write));
 
2049
   } else {
 
2050
 
 
2051
      /* dest clamp doesn't work on plain 64 bit move, so add a zero
 
2052
       * to apply the modifier */
 
2053
 
 
2054
      auto group = new AluGroup();
 
2055
      auto ir = new AluInstr(op2_add_64,
 
2056
                             value_factory.dest(alu.dest, 0, pin_chan),
 
2057
                             value_factory.src64(alu.src[0], 0, 1),
 
2058
                             value_factory.literal(0),
 
2059
                             AluInstr::write);
 
2060
      ir->set_alu_flag(alu_dst_clamp);
 
2061
      group->add_instruction(ir);
 
2062
 
 
2063
      group->add_instruction(new AluInstr(op2_add_64,
 
2064
                                          value_factory.dest(alu.dest, 1, pin_chan),
 
2065
                                          value_factory.src64(alu.src[0], 0, 0),
 
2066
                                          value_factory.literal(0),
 
2067
                                          AluInstr::last_write));
 
2068
      shader.emit_instruction(group);
 
2069
 
 
2070
   }
 
2071
   return true;
 
2072
}
 
2073
 
 
2074
 
 
2075
static bool
1883
2076
emit_alu_op2_64bit(const nir_alu_instr& alu,
1884
2077
                   EAluOp opcode,
1885
2078
                   Shader& shader,
1909
2102
                           value_factory.src64(alu.src[order[0]], k, 1),
1910
2103
                           value_factory.src64(alu.src[order[1]], k, 1),
1911
2104
                           i < 2 ? AluInstr::write : AluInstr::empty);
1912
 
 
1913
 
         if (alu.src[0].abs)
1914
 
            ir->set_alu_flag(switch_src ? alu_src1_abs : alu_src0_abs);
1915
 
         if (alu.src[1].abs)
1916
 
            ir->set_alu_flag(switch_src ? alu_src0_abs : alu_src1_abs);
1917
 
         if (alu.src[0].negate)
1918
 
            ir->set_alu_flag(switch_src ? alu_src1_neg : alu_src0_neg);
1919
 
         if (alu.src[1].negate)
1920
 
            ir->set_alu_flag(switch_src ? alu_src0_neg : alu_src1_neg);
1921
 
         if (alu.dest.saturate && i == 0) {
1922
 
            ir->set_alu_flag(alu_dst_clamp);
1923
 
         }
1924
 
 
1925
2105
         group->add_instruction(ir);
1926
2106
      }
1927
2107
 
1966
2146
      src[3] = value_factory.src64(alu.src[order[1]], k, 0);
1967
2147
 
1968
2148
      ir = new AluInstr(opcode, dest, src, AluInstr::write, 2);
1969
 
 
1970
 
      if (alu.src[0].abs)
1971
 
         ir->set_alu_flag(switch_order ? alu_src1_abs : alu_src0_abs);
1972
 
      if (alu.src[1].abs)
1973
 
         ir->set_alu_flag(switch_order ? alu_src0_abs : alu_src1_abs);
1974
 
      if (alu.src[0].negate)
1975
 
         ir->set_alu_flag(switch_order ? alu_src1_neg : alu_src0_neg);
1976
 
      if (alu.src[1].negate)
1977
 
         ir->set_alu_flag(switch_order ? alu_src0_neg : alu_src1_neg);
1978
2149
      ir->set_alu_flag(alu_64bit_op);
1979
2150
 
1980
2151
      shader.emit_instruction(ir);
1999
2170
                        value_factory.src64(alu.src[0], 0, 0),
2000
2171
                        i < 2 ? AluInstr::write : AluInstr::empty);
2001
2172
 
2002
 
      if (alu.src[0].abs || opcode == op1_sqrt_64)
2003
 
         ir->set_alu_flag(alu_src1_abs);
2004
 
      if (alu.src[0].negate)
2005
 
         ir->set_alu_flag(alu_src1_neg);
2006
 
 
 
2173
      if (opcode == op1_sqrt_64)
 
2174
         ir->set_source_mod(0, AluInstr::mod_abs);
2007
2175
      group->add_instruction(ir);
2008
2176
   }
2009
2177
   if (ir)
2030
2198
                        value_factory.src64(alu.src[1], 0, chan),
2031
2199
                        value_factory.src64(alu.src[2], 0, chan),
2032
2200
                        i < 2 ? AluInstr::write : AluInstr::empty);
2033
 
 
2034
 
      if (i < 3) {
2035
 
         if (alu.src[0].negate)
2036
 
            ir->set_alu_flag(alu_src0_neg);
2037
 
         if (alu.src[1].negate)
2038
 
            ir->set_alu_flag(alu_src1_neg);
2039
 
         if (alu.src[2].negate)
2040
 
            ir->set_alu_flag(alu_src2_neg);
2041
 
      }
2042
 
 
2043
2201
      group->add_instruction(ir);
2044
2202
   }
2045
2203
   if (ir)
2198
2356
                           src,
2199
2357
                           value_factory.inline_const(mask, 0),
2200
2358
                           {alu_write});
2201
 
         if (alu.src[0].negate)
2202
 
            ir->set_alu_flag(alu_src0_neg);
2203
 
         if (alu.src[0].abs)
2204
 
            ir->set_alu_flag(alu_src0_abs);
2205
2359
         shader.emit_instruction(ir);
2206
2360
      }
2207
2361
   }
2214
2368
emit_alu_op1(const nir_alu_instr& alu,
2215
2369
             EAluOp opcode,
2216
2370
             Shader& shader,
2217
 
             const AluOpFlags& flags)
 
2371
             AluMods mod)
2218
2372
{
2219
2373
   auto& value_factory = shader.value_factory();
2220
2374
 
2223
2377
 
2224
2378
   for (unsigned i = 0; i < nir_dest_num_components(alu.dest.dest); ++i) {
2225
2379
      if (alu.dest.write_mask & (1 << i)) {
 
2380
 
2226
2381
         ir = new AluInstr(opcode,
2227
2382
                           value_factory.dest(alu.dest, i, pin),
2228
2383
                           value_factory.src(alu.src[0], i),
2229
2384
                           {alu_write});
2230
 
 
2231
 
         if (flags.test(alu_src0_abs) || alu.src[0].abs)
2232
 
            ir->set_alu_flag(alu_src0_abs);
2233
 
 
2234
 
         if (alu.src[0].negate ^ flags.test(alu_src0_neg))
2235
 
            ir->set_alu_flag(alu_src0_neg);
2236
 
 
2237
 
         if (flags.test(alu_dst_clamp) || alu.dest.saturate)
 
2385
         switch (mod) {
 
2386
         case mod_src0_abs:
 
2387
            ir->set_source_mod(0, AluInstr::mod_abs); break;
 
2388
         case mod_src0_neg:
 
2389
            ir->set_source_mod(0, AluInstr::mod_neg); break;
 
2390
         case mod_dest_clamp:
2238
2391
            ir->set_alu_flag(alu_dst_clamp);
2239
 
 
 
2392
            default:;
 
2393
         }
2240
2394
         shader.emit_instruction(ir);
2241
2395
      }
2242
2396
   }
2262
2416
      std::swap(idx0, idx1);
2263
2417
   }
2264
2418
 
2265
 
   bool src1_negate = (opts & AluInstr::op2_opt_neg_src1) ^ src1->negate;
 
2419
   bool src1_negate = (opts & AluInstr::op2_opt_neg_src1);
2266
2420
 
2267
2421
   auto pin = pin_for_components(alu);
2268
2422
   AluInstr *ir = nullptr;
2273
2427
                           value_factory.src(*src0, i),
2274
2428
                           value_factory.src(*src1, i),
2275
2429
                           {alu_write});
2276
 
 
2277
 
         if (src0->negate)
2278
 
            ir->set_alu_flag(alu_src0_neg);
2279
 
         if (src0->abs)
2280
 
            ir->set_alu_flag(alu_src0_abs);
2281
2430
         if (src1_negate)
2282
 
            ir->set_alu_flag(alu_src1_neg);
2283
 
         if (src1->abs)
2284
 
            ir->set_alu_flag(alu_src1_abs);
2285
 
         if (alu.dest.saturate)
2286
 
            ir->set_alu_flag(alu_dst_clamp);
 
2431
            ir->set_source_mod(1, AluInstr::mod_neg);
2287
2432
         shader.emit_instruction(ir);
2288
2433
      }
2289
2434
   }
2298
2443
                 Shader& shader,
2299
2444
                 AluInstr::Op2Options opts)
2300
2445
{
2301
 
   assert(!alu.src[0].abs);
2302
 
   assert(!alu.src[0].negate);
2303
 
   assert(!alu.src[1].abs);
2304
 
   assert(!alu.src[1].negate);
2305
 
 
2306
2446
   return emit_alu_op2(alu, opcode, shader, opts);
2307
2447
}
2308
2448
 
2328
2468
                           value_factory.src(*src[1], i),
2329
2469
                           value_factory.src(*src[2], i),
2330
2470
                           {alu_write});
2331
 
 
2332
 
         if (src[0]->negate)
2333
 
            ir->set_alu_flag(alu_src0_neg);
2334
 
         if (src[1]->negate)
2335
 
            ir->set_alu_flag(alu_src1_neg);
2336
 
         if (src[2]->negate)
2337
 
            ir->set_alu_flag(alu_src2_neg);
2338
 
 
2339
 
         assert(!src[0]->abs);
2340
 
         assert(!src[1]->abs);
2341
 
         assert(!src[2]->abs);
2342
 
 
2343
 
         if (alu.dest.saturate)
2344
 
            ir->set_alu_flag(alu_dst_clamp);
2345
2471
         ir->set_alu_flag(alu_write);
2346
2472
         shader.emit_instruction(ir);
2347
2473
      }
2367
2493
                        value_factory.src(alu.src[0], i),
2368
2494
                        value_factory.src(alu.src[1], i),
2369
2495
                        {alu_write});
2370
 
      if (alu.src[0].abs)
2371
 
         ir->set_alu_flag(alu_src0_abs);
2372
 
      if (alu.src[0].negate)
2373
 
         ir->set_alu_flag(alu_src0_neg);
2374
 
 
2375
 
      if (alu.src[1].abs)
2376
 
         ir->set_alu_flag(alu_src1_abs);
2377
 
      if (alu.src[1].negate)
2378
 
         ir->set_alu_flag(alu_src1_neg);
2379
 
 
2380
2496
      shader.emit_instruction(ir);
2381
2497
   }
2382
2498
   ir->set_alu_flag(alu_last_instr);
2414
2530
                        value_factory.src(alu.src[0], i),
2415
2531
                        value_factory.src(alu.src[1], i),
2416
2532
                        {alu_write});
2417
 
 
2418
 
      if (alu.src[0].abs)
2419
 
         ir->set_alu_flag(alu_src0_abs);
2420
 
      if (alu.src[0].negate)
2421
 
         ir->set_alu_flag(alu_src0_neg);
2422
 
 
2423
 
      if (alu.src[1].abs)
2424
 
         ir->set_alu_flag(alu_src1_abs);
2425
 
      if (alu.src[1].negate)
2426
 
         ir->set_alu_flag(alu_src1_neg);
2427
 
 
2428
2533
      shader.emit_instruction(ir);
2429
2534
   }
2430
2535
   if (ir)
2434
2539
 
2435
2540
   ir = new AluInstr(op1_max4, max_val, s, AluInstr::last_write, 4);
2436
2541
 
2437
 
   if (all)
2438
 
      ir->set_alu_flag(alu_src0_neg);
 
2542
   if (all) {
 
2543
      ir->set_source_mod(0, AluInstr::mod_neg);
 
2544
      ir->set_source_mod(1, AluInstr::mod_neg);
 
2545
      ir->set_source_mod(2, AluInstr::mod_neg);
 
2546
      ir->set_source_mod(3, AluInstr::mod_neg);
 
2547
   }
2439
2548
 
2440
2549
   shader.emit_instruction(ir);
2441
2550
 
2450
2559
                     value_factory.inline_const(ALU_SRC_1, 0),
2451
2560
                     AluInstr::last_write);
2452
2561
   if (all)
2453
 
      ir->set_alu_flag(alu_src1_neg);
 
2562
      ir->set_source_mod(1, AluInstr::mod_neg);
2454
2563
   shader.emit_instruction(ir);
2455
2564
 
2456
2565
   return true;
2533
2642
 
2534
2643
   AluInstr *ir = new AluInstr(op2_dot_ieee, dest, srcs, AluInstr::last_write, n);
2535
2644
 
2536
 
   if (src0.negate)
2537
 
      ir->set_alu_flag(alu_src0_neg);
2538
 
   if (src0.abs)
2539
 
      ir->set_alu_flag(alu_src0_abs);
2540
 
   if (src1.negate)
2541
 
      ir->set_alu_flag(alu_src1_neg);
2542
 
   if (src1.abs)
2543
 
      ir->set_alu_flag(alu_src1_abs);
2544
 
 
2545
 
   if (alu.dest.saturate)
2546
 
      ir->set_alu_flag(alu_dst_clamp);
2547
 
 
2548
2645
   shader.emit_instruction(ir);
 
2646
   shader.set_flag(Shader::sh_disble_sb);
 
2647
 
2549
2648
   return true;
2550
2649
}
2551
2650
 
2572
2671
 
2573
2672
   AluInstr *ir = new AluInstr(op2_dot4_ieee, dest, srcs, AluInstr::last_write, 4);
2574
2673
 
2575
 
   if (src0.negate)
2576
 
      ir->set_alu_flag(alu_src0_neg);
2577
 
   if (src0.abs)
2578
 
      ir->set_alu_flag(alu_src0_abs);
2579
 
   if (src1.negate)
2580
 
      ir->set_alu_flag(alu_src1_neg);
2581
 
   if (src1.abs)
2582
 
      ir->set_alu_flag(alu_src1_abs);
2583
 
 
2584
 
   if (alu.dest.saturate)
2585
 
      ir->set_alu_flag(alu_dst_clamp);
2586
 
 
2587
2674
   shader.emit_instruction(ir);
2588
2675
   return true;
2589
2676
}
2608
2695
   srcs[7] = value_factory.src(src1, 3);
2609
2696
 
2610
2697
   AluInstr *ir = new AluInstr(op2_dot4_ieee, dest, srcs, AluInstr::last_write, 4);
2611
 
 
2612
 
   if (src0.negate)
2613
 
      ir->set_alu_flag(alu_src0_neg);
2614
 
   if (src0.abs)
2615
 
      ir->set_alu_flag(alu_src0_abs);
2616
 
   if (src1.negate)
2617
 
      ir->set_alu_flag(alu_src1_neg);
2618
 
   if (src1.abs)
2619
 
      ir->set_alu_flag(alu_src1_abs);
2620
 
 
2621
 
   if (alu.dest.saturate)
2622
 
      ir->set_alu_flag(alu_dst_clamp);
2623
 
 
2624
2698
   shader.emit_instruction(ir);
2625
2699
   return true;
2626
2700
}
2635
2709
      if (instr.dest.write_mask & (1 << i)) {
2636
2710
         auto src = value_factory.src(instr.src[i].src, instr.src[i].swizzle[0]);
2637
2711
         auto dst = value_factory.dest(instr.dest.dest, i, pin_none);
2638
 
         ir = new AluInstr(op1_mov, dst, src, {alu_write});
2639
 
 
2640
 
         if (instr.dest.saturate)
2641
 
            ir->set_alu_flag(alu_dst_clamp);
2642
 
         if (instr.src[i].negate)
2643
 
            ir->set_alu_flag(alu_src0_neg);
2644
 
         if (instr.src[i].abs)
2645
 
            ir->set_alu_flag(alu_src0_abs);
2646
 
 
2647
 
         shader.emit_instruction(ir);
 
2712
         shader.emit_instruction(new AluInstr(op1_mov, dst, src, {alu_write}));
2648
2713
      }
2649
2714
   }
2650
2715
 
2826
2891
                           value_factory.dest(alu.dest.dest, i, pin),
2827
2892
                           value_factory.src(src0, i),
2828
2893
                           AluInstr::last_write);
2829
 
         if (src0.negate)
2830
 
            ir->set_alu_flag(alu_src0_neg);
2831
 
         if (src0.abs)
2832
 
            ir->set_alu_flag(alu_src0_abs);
2833
 
         if (alu.dest.saturate)
2834
 
            ir->set_alu_flag(alu_dst_clamp);
2835
2894
         ir->set_alu_flag(alu_is_trans);
2836
2895
         shader.emit_instruction(ir);
2837
2896
      }
2856
2915
                        reg[i],
2857
2916
                        value_factory.src(alu.src[0], i),
2858
2917
                        AluInstr::last_write);
2859
 
      if (alu.src[0].abs)
2860
 
         ir->set_alu_flag(alu_src0_abs);
2861
 
      if (alu.src[0].negate)
2862
 
         ir->set_alu_flag(alu_src0_neg);
2863
2918
      shader.emit_instruction(ir);
2864
2919
   }
2865
2920
 
2900
2955
            srcs[i] = value_factory.src(src0, j);
2901
2956
 
2902
2957
         auto ir = new AluInstr(opcode, dest, srcs, flags, ncomp);
2903
 
 
2904
 
         if (alu.src[0].abs)
2905
 
            ir->set_alu_flag(alu_src0_abs);
2906
 
         if (alu.src[0].negate)
2907
 
            ir->set_alu_flag(alu_src0_neg);
2908
 
         if (alu.dest.saturate)
2909
 
            ir->set_alu_flag(alu_dst_clamp);
2910
 
 
2911
2958
         shader.emit_instruction(ir);
2912
2959
      }
2913
2960
   }
2932
2979
                           value_factory.src(src0, i),
2933
2980
                           value_factory.src(src1, i),
2934
2981
                           AluInstr::last_write);
2935
 
         if (src0.negate)
2936
 
            ir->set_alu_flag(alu_src0_neg);
2937
 
         if (src0.abs)
2938
 
            ir->set_alu_flag(alu_src0_abs);
2939
 
         if (src1.negate)
2940
 
            ir->set_alu_flag(alu_src1_neg);
2941
 
         if (src1.abs)
2942
 
            ir->set_alu_flag(alu_src1_abs);
2943
 
         if (alu.dest.saturate)
2944
 
            ir->set_alu_flag(alu_dst_clamp);
2945
2982
         ir->set_alu_flag(alu_is_trans);
2946
2983
         shader.emit_instruction(ir);
2947
2984
      }
2972
3009
         }
2973
3010
 
2974
3011
         auto ir = new AluInstr(opcode, dest, srcs, flags, last_slot);
2975
 
 
2976
 
         if (src0.negate)
2977
 
            ir->set_alu_flag(alu_src0_neg);
2978
 
         if (src0.abs)
2979
 
            ir->set_alu_flag(alu_src0_abs);
2980
 
         if (src1.negate)
2981
 
            ir->set_alu_flag(alu_src1_neg);
2982
 
         if (src1.abs)
2983
 
            ir->set_alu_flag(alu_src1_abs);
2984
 
         if (alu.dest.saturate)
2985
 
            ir->set_alu_flag(alu_dst_clamp);
2986
3012
         ir->set_alu_flag(alu_is_cayman_trans);
2987
3013
         shader.emit_instruction(ir);
2988
3014
      }
3009
3035
   AluInstr *mv = nullptr;
3010
3036
   for (int i = 0; i < ncomp; ++i) {
3011
3037
      mv = new AluInstr(op1_mov, tmp[i], src[i], AluInstr::write);
3012
 
      if (alu.src[0].abs)
3013
 
         mv->set_alu_flag(alu_src0_abs);
3014
 
      if (alu.src[0].negate)
3015
 
         mv->set_alu_flag(alu_src0_neg);
3016
3038
      shader.emit_instruction(mv);
3017
3039
   }
3018
3040
   if (mv)