1 #include "sfn_nir_lower_alu.h"
2 #include "sfn_nir.h"
3 
4 namespace r600 {
5 
6 class Lower2x16 : public NirLowerInstruction {
7 private:
8    bool filter(const nir_instr *instr) const override;
9    nir_ssa_def *lower(nir_instr *instr) override;
10 };
11 
12 
filter(const nir_instr * instr) const13 bool Lower2x16::filter(const nir_instr *instr) const
14 {
15    if (instr->type != nir_instr_type_alu)
16       return false;
17    auto alu = nir_instr_as_alu(instr);
18    switch (alu->op) {
19    case nir_op_unpack_half_2x16:
20    case nir_op_pack_half_2x16:
21       return true;
22    default:
23       return false;
24    }
25 }
26 
lower(nir_instr * instr)27 nir_ssa_def *Lower2x16::lower(nir_instr *instr)
28 {
29    nir_alu_instr *alu = nir_instr_as_alu(instr);
30 
31    switch (alu->op) {
32    case nir_op_unpack_half_2x16: {
33       nir_ssa_def *packed = nir_ssa_for_alu_src(b, alu, 0);
34       return  nir_vec2(b, nir_unpack_half_2x16_split_x(b, packed),
35                        nir_unpack_half_2x16_split_y(b, packed));
36 
37    }
38    case nir_op_pack_half_2x16: {
39       nir_ssa_def *src_vec2 = nir_ssa_for_alu_src(b, alu, 0);
40       return nir_pack_half_2x16_split(b, nir_channel(b, src_vec2, 0),
41                                       nir_channel(b, src_vec2, 1));
42    }
43    default:
44       unreachable("Lower2x16 filter doesn't filter correctly");
45    }
46 }
47 
48 class LowerSinCos : public NirLowerInstruction {
49 private:
50    bool filter(const nir_instr *instr) const override;
51    nir_ssa_def *lower(nir_instr *instr) override;
52 };
53 
filter(const nir_instr * instr) const54 bool LowerSinCos::filter(const nir_instr *instr) const
55 {
56    if (instr->type != nir_instr_type_alu)
57       return false;
58 
59    auto alu = nir_instr_as_alu(instr);
60    switch (alu->op) {
61    case nir_op_fsin:
62    case nir_op_fcos:
63       return true;
64    default:
65       return false;
66    }
67 }
68 
lower(nir_instr * instr)69 nir_ssa_def *LowerSinCos::lower(nir_instr *instr)
70 {
71    auto alu = nir_instr_as_alu(instr);
72 
73    assert(alu->op == nir_op_fsin ||
74           alu->op == nir_op_fcos);
75 
76    auto normalized =
77          nir_fadd(b,
78                   nir_ffract(b,
79                              nir_ffma(b,
80                                       nir_ssa_for_alu_src(b, alu, 0),
81                                       nir_imm_float(b, 0.15915494),
82                                       nir_imm_float(b, 0.5))),
83                               nir_imm_float(b, -0.5));
84 
85    if (alu->op == nir_op_fsin)
86       return nir_fsin_r600(b, normalized);
87    else
88       return nir_fcos_r600(b, normalized);
89 }
90 
91 
92 } // namespace r600
93 
94 
r600_nir_lower_pack_unpack_2x16(nir_shader * shader)95 bool r600_nir_lower_pack_unpack_2x16(nir_shader *shader)
96 {
97    return r600::Lower2x16().run(shader);
98 }
99 
r600_nir_lower_trigen(nir_shader * shader)100 bool r600_nir_lower_trigen(nir_shader *shader)
101 {
102    return r600::LowerSinCos().run(shader);
103 }
104