From 864268ff0d15693fae42d3e6ae478994bbd6cecb Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 5 Apr 2024 10:16:40 -0700 Subject: [PATCH] intel/brw: Algebraic optimizations for CSEL No shader-db or fossil-db changes on any Intel platform. In this MR, the only benefit of these changes is to convert some "-a > 0" CSEL comparisons to "a < 0" for improved readability. v2: Add integer CSEL support v3: Use fs_inst::resize_sources and brw_type_is_sint. Both suggested by Ken. Reviewed-by: Kenneth Graunke Part-of: --- src/intel/compiler/brw_fs_opt_algebraic.cpp | 81 +++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/src/intel/compiler/brw_fs_opt_algebraic.cpp b/src/intel/compiler/brw_fs_opt_algebraic.cpp index 30f3d5a0b0a..49e31219145 100644 --- a/src/intel/compiler/brw_fs_opt_algebraic.cpp +++ b/src/intel/compiler/brw_fs_opt_algebraic.cpp @@ -290,6 +290,87 @@ brw_fs_opt_algebraic(fs_visitor &s) } } break; + case BRW_OPCODE_CSEL: + if (brw_type_is_float(inst->dst.type)) { + /* This transformation can both clean up spurious modifiers + * (making assembly dumps easier to read) and convert GE with -abs + * to LE with abs. See abs handling below. + */ + if (inst->src[2].negate) { + inst->conditional_mod = brw_swap_cmod(inst->conditional_mod); + inst->src[2].negate = false; + progress = true; + } + + if (inst->src[2].abs) { + switch (inst->conditional_mod) { + case BRW_CONDITIONAL_Z: + case BRW_CONDITIONAL_NZ: + inst->src[2].abs = false; + progress = true; + break; + + case BRW_CONDITIONAL_LE: + /* Converting to Z can help constant propagation into src0 + * and src1. + */ + inst->conditional_mod = BRW_CONDITIONAL_Z; + inst->src[2].abs = false; + progress = true; + break; + + default: + /* GE or L conditions with absolute value could be used to + * implement isnan(x) in CSEL. Transforming G with absolute + * value to NZ is **not** NaN safe. + */ + break; + } + } + } else if (brw_type_is_sint(inst->src[2].type)) { + /* Integer transformations are more challenging than floating + * point transformations due to INT_MIN == -(INT_MIN) == + * abs(INT_MIN). + */ + if (inst->src[2].negate && inst->src[2].abs) { + switch (inst->conditional_mod) { + case BRW_CONDITIONAL_GE: + inst->src[2].negate = false; + inst->src[2].abs = false; + inst->conditional_mod = BRW_CONDITIONAL_Z; + progress = true; + break; + case BRW_CONDITIONAL_L: + inst->src[2].negate = false; + inst->src[2].abs = false; + inst->conditional_mod = BRW_CONDITIONAL_NZ; + progress = true; + break; + case BRW_CONDITIONAL_G: + /* This is a contradtion. -abs(x) cannot be > 0. */ + inst->opcode = BRW_OPCODE_MOV; + inst->src[0] = inst->src[1]; + inst->resize_sources(1); + progress = true; + break; + case BRW_CONDITIONAL_LE: + /* This is a tautology. -abs(x) must be <= 0. */ + inst->opcode = BRW_OPCODE_MOV; + inst->resize_sources(1); + progress = true; + break; + case BRW_CONDITIONAL_Z: + case BRW_CONDITIONAL_NZ: + inst->src[2].negate = false; + inst->src[2].abs = false; + progress = true; + break; + default: + unreachable("Impossible icsel condition."); + } + } + } + break; case BRW_OPCODE_MAD: if (inst->src[0].type != BRW_TYPE_F || inst->src[1].type != BRW_TYPE_F ||