diff options
author | Ian Romanick <ian.d.romanick@intel.com> | 2024-02-29 09:21:20 -0800 |
---|---|---|
committer | Eric Engestrom <eric@engestrom.ch> | 2024-05-05 15:47:07 +0200 |
commit | e0899ef81a40c73627f2be011a540da77b995e34 (patch) | |
tree | bb4831e70c830de6ce768928539d5c225b9f411a | |
parent | 55ad51ff40ade46ef4281f11e2c3253538b79246 (diff) | |
download | mesa3d-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.json | 2 | ||||
-rw-r--r-- | src/intel/compiler/elk/elk_fs_nir.cpp | 43 |
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, |