2 * Copyright © 2018 Intel Corporation
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:
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
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
25 #include "compiler/nir/nir_builder.h"
28 get_conversion_op(nir_alu_type src_type
,
29 unsigned src_bit_size
,
30 nir_alu_type dst_type
,
31 unsigned dst_bit_size
,
32 nir_rounding_mode rounding_mode
)
34 nir_alu_type src_full_type
= (nir_alu_type
) (src_type
| src_bit_size
);
35 nir_alu_type dst_full_type
= (nir_alu_type
) (dst_type
| dst_bit_size
);
37 return nir_type_conversion_op(src_full_type
, dst_full_type
, rounding_mode
);
40 static nir_rounding_mode
41 get_opcode_rounding_mode(nir_op op
)
44 case nir_op_f2f16_rtz
:
45 return nir_rounding_mode_rtz
;
46 case nir_op_f2f16_rtne
:
47 return nir_rounding_mode_rtne
;
49 return nir_rounding_mode_undef
;
54 split_conversion(nir_builder
*b
, nir_alu_instr
*alu
, nir_op op1
, nir_op op2
)
56 b
->cursor
= nir_before_instr(&alu
->instr
);
57 assert(alu
->dest
.write_mask
== 1);
58 nir_ssa_def
*src
= nir_ssa_for_alu_src(b
, alu
, 0);
59 nir_ssa_def
*tmp
= nir_build_alu(b
, op1
, src
, NULL
, NULL
, NULL
);
60 nir_ssa_def
*res
= nir_build_alu(b
, op2
, tmp
, NULL
, NULL
, NULL
);
61 nir_ssa_def_rewrite_uses(&alu
->dest
.dest
.ssa
, nir_src_for_ssa(res
));
62 nir_instr_remove(&alu
->instr
);
66 lower_instr(nir_builder
*b
, nir_alu_instr
*alu
)
68 unsigned src_bit_size
= nir_src_bit_size(alu
->src
[0].src
);
69 nir_alu_type src_type
= nir_op_infos
[alu
->op
].input_types
[0];
70 nir_alu_type src_full_type
= (nir_alu_type
) (src_type
| src_bit_size
);
72 unsigned dst_bit_size
= nir_dest_bit_size(alu
->dest
.dest
);
73 nir_alu_type dst_full_type
= nir_op_infos
[alu
->op
].output_type
;
74 nir_alu_type dst_type
= nir_alu_type_get_base_type(dst_full_type
);
76 /* BDW PRM, vol02, Command Reference Instructions, mov - MOVE:
78 * "There is no direct conversion from HF to DF or DF to HF.
79 * Use two instructions and F (Float) as an intermediate type.
81 * There is no direct conversion from HF to Q/UQ or Q/UQ to HF.
82 * Use two instructions and F (Float) or a word integer type
83 * or a DWord integer type as an intermediate type."
85 * It is important that the intermediate conversion happens through a
86 * 32-bit float type so we don't lose range when we convert from
89 if ((src_full_type
== nir_type_float16
&& dst_bit_size
== 64) ||
90 (src_bit_size
== 64 && dst_full_type
== nir_type_float16
)) {
91 nir_op op1
= get_conversion_op(src_type
, src_bit_size
,
93 nir_rounding_mode_undef
);
94 nir_op op2
= get_conversion_op(nir_type_float
, 32,
95 dst_type
, dst_bit_size
,
96 get_opcode_rounding_mode(alu
->op
));
97 split_conversion(b
, alu
, op1
, op2
);
101 /* SKL PRM, vol 02a, Command Reference: Instructions, Move:
103 * "There is no direct conversion from B/UB to DF or DF to B/UB. Use
104 * two instructions and a word or DWord intermediate type."
106 * "There is no direct conversion from B/UB to Q/UQ or Q/UQ to B/UB.
107 * Use two instructions and a word or DWord intermediate integer
110 * It is important that we use a 32-bit integer matching the sign of the
111 * destination as the intermediate type so we avoid any chance of rtne
112 * rounding happening before the conversion to integer (which is expected
113 * to round towards zero) in double to byte conversions.
115 if ((src_bit_size
== 8 && dst_bit_size
== 64) ||
116 (src_bit_size
== 64 && dst_bit_size
== 8)) {
117 nir_op op1
= get_conversion_op(src_type
, src_bit_size
, dst_type
, 32,
118 nir_rounding_mode_undef
);
119 nir_op op2
= get_conversion_op(dst_type
, 32, dst_type
, dst_bit_size
,
120 nir_rounding_mode_undef
);
121 split_conversion(b
, alu
, op1
, op2
);
129 lower_impl(nir_function_impl
*impl
)
132 nir_builder_init(&b
, impl
);
133 bool progress
= false;
135 nir_foreach_block(block
, impl
) {
136 nir_foreach_instr_safe(instr
, block
) {
137 if (instr
->type
!= nir_instr_type_alu
)
140 nir_alu_instr
*alu
= nir_instr_as_alu(instr
);
141 assert(alu
->dest
.dest
.is_ssa
);
143 if (!nir_op_infos
[alu
->op
].is_conversion
)
146 progress
= lower_instr(&b
, alu
) || progress
;
151 nir_metadata_preserve(impl
, nir_metadata_block_index
|
152 nir_metadata_dominance
);
159 brw_nir_lower_conversions(nir_shader
*shader
)
161 bool progress
= false;
163 nir_foreach_function(function
, shader
) {
165 progress
|= lower_impl(function
->impl
);