aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2024-02-29 09:21:20 -0800
committerEric Engestrom <eric@engestrom.ch>2024-05-05 15:47:07 +0200
commite0899ef81a40c73627f2be011a540da77b995e34 (patch)
treebb4831e70c830de6ce768928539d5c225b9f411a
parent55ad51ff40ade46ef4281f11e2c3253538b79246 (diff)
downloadmesa3d-e0899ef81a40c73627f2be011a540da77b995e34.tar.gz
intel/elk: Fix optimize_extract_to_float for i2f of unsigned extract
Fixes fs-uint-to-float-of-extract-int8.shader_test and fs-uint-to-float-of-extract-int16.shader_test added by piglit!883. v2: Expand the comment explaining the potential problem. Suggested by Caio. Fixes: e6022281f27 ("intel/elk: Rename files to use elk prefix") Reviewed-by: Caio Oliveira <caio.oliveira@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27891> (cherry picked from commit 0fa17962d6b26fe29996a5767fbdd44dc2dbd082)
-rw-r--r--.pick_status.json2
-rw-r--r--src/intel/compiler/elk/elk_fs_nir.cpp43
2 files changed, 39 insertions, 6 deletions
diff --git a/.pick_status.json b/.pick_status.json
index f753a2e315c..aa5632ea223 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -64,7 +64,7 @@
"description": "intel/elk: Fix optimize_extract_to_float for i2f of unsigned extract",
"nominated": true,
"nomination_type": 1,
- "resolution": 0,
+ "resolution": 1,
"main_sha": null,
"because_sha": "e6022281f273287499e9012f9a7c3dd87a733e5b",
"notes": null
diff --git a/src/intel/compiler/elk/elk_fs_nir.cpp b/src/intel/compiler/elk/elk_fs_nir.cpp
index 75f0e6e610f..799e59a3e4a 100644
--- a/src/intel/compiler/elk/elk_fs_nir.cpp
+++ b/src/intel/compiler/elk/elk_fs_nir.cpp
@@ -479,6 +479,9 @@ optimize_extract_to_float(nir_to_elk_state &ntb, nir_alu_instr *instr,
const intel_device_info *devinfo = ntb.devinfo;
const fs_builder &bld = ntb.bld;
+ /* No fast path for f16 or f64. */
+ assert(instr->op == nir_op_i2f32 || instr->op == nir_op_u2f32);
+
if (!instr->src[0].src.ssa->parent_instr)
return false;
@@ -488,16 +491,46 @@ optimize_extract_to_float(nir_to_elk_state &ntb, nir_alu_instr *instr,
nir_alu_instr *src0 =
nir_instr_as_alu(instr->src[0].src.ssa->parent_instr);
- if (src0->op != nir_op_extract_u8 && src0->op != nir_op_extract_u16 &&
- src0->op != nir_op_extract_i8 && src0->op != nir_op_extract_i16)
+ unsigned bytes;
+ bool is_signed;
+
+ switch (src0->op) {
+ case nir_op_extract_u8:
+ case nir_op_extract_u16:
+ bytes = src0->op == nir_op_extract_u8 ? 1 : 2;
+
+ /* i2f(extract_u8(a, b)) and u2f(extract_u8(a, b)) produce the same
+ * result. Ditto for extract_u16.
+ */
+ is_signed = false;
+ break;
+
+ case nir_op_extract_i8:
+ case nir_op_extract_i16:
+ bytes = src0->op == nir_op_extract_i8 ? 1 : 2;
+
+ /* The fast path can't handle u2f(extract_i8(a, b)) because the implicit
+ * sign extension of the extract_i8 is lost. For example,
+ * u2f(extract_i8(0x0000ff00, 1)) should produce 4294967295.0, but a
+ * fast path could either give 255.0 (by implementing the fast path as
+ * u2f(extract_u8(x))) or -1.0 (by implementing the fast path as
+ * i2f(extract_i8(x))). At one point in time, we incorrectly implemented
+ * the former.
+ */
+ if (instr->op != nir_op_i2f32)
+ return false;
+
+ is_signed = true;
+ break;
+
+ default:
return false;
+ }
unsigned element = nir_src_as_uint(src0->src[1].src);
/* Element type to extract.*/
- const elk_reg_type type = elk_int_type(
- src0->op == nir_op_extract_u16 || src0->op == nir_op_extract_i16 ? 2 : 1,
- src0->op == nir_op_extract_i16 || src0->op == nir_op_extract_i8);
+ const elk_reg_type type = elk_int_type(bytes, is_signed);
elk_fs_reg op0 = get_nir_src(ntb, src0->src[0].src);
op0.type = elk_type_for_nir_type(devinfo,