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