1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2016 Red Hat 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci * Authors: 24bf215546Sopenharmony_ci * Rob Clark <robclark@freedesktop.org> 25bf215546Sopenharmony_ci */ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#ifndef _NIR_SEARCH_HELPERS_ 28bf215546Sopenharmony_ci#define _NIR_SEARCH_HELPERS_ 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "nir.h" 31bf215546Sopenharmony_ci#include "util/bitscan.h" 32bf215546Sopenharmony_ci#include "nir_range_analysis.h" 33bf215546Sopenharmony_ci#include <math.h> 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_cistatic inline bool 36bf215546Sopenharmony_ciis_pos_power_of_two(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 37bf215546Sopenharmony_ci unsigned src, unsigned num_components, 38bf215546Sopenharmony_ci const uint8_t *swizzle) 39bf215546Sopenharmony_ci{ 40bf215546Sopenharmony_ci /* only constant srcs: */ 41bf215546Sopenharmony_ci if (!nir_src_is_const(instr->src[src].src)) 42bf215546Sopenharmony_ci return false; 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci for (unsigned i = 0; i < num_components; i++) { 45bf215546Sopenharmony_ci nir_alu_type type = nir_op_infos[instr->op].input_types[src]; 46bf215546Sopenharmony_ci switch (nir_alu_type_get_base_type(type)) { 47bf215546Sopenharmony_ci case nir_type_int: { 48bf215546Sopenharmony_ci int64_t val = nir_src_comp_as_int(instr->src[src].src, swizzle[i]); 49bf215546Sopenharmony_ci if (val <= 0 || !util_is_power_of_two_or_zero64(val)) 50bf215546Sopenharmony_ci return false; 51bf215546Sopenharmony_ci break; 52bf215546Sopenharmony_ci } 53bf215546Sopenharmony_ci case nir_type_uint: { 54bf215546Sopenharmony_ci uint64_t val = nir_src_comp_as_uint(instr->src[src].src, swizzle[i]); 55bf215546Sopenharmony_ci if (val == 0 || !util_is_power_of_two_or_zero64(val)) 56bf215546Sopenharmony_ci return false; 57bf215546Sopenharmony_ci break; 58bf215546Sopenharmony_ci } 59bf215546Sopenharmony_ci default: 60bf215546Sopenharmony_ci return false; 61bf215546Sopenharmony_ci } 62bf215546Sopenharmony_ci } 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci return true; 65bf215546Sopenharmony_ci} 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_cistatic inline bool 68bf215546Sopenharmony_ciis_neg_power_of_two(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 69bf215546Sopenharmony_ci unsigned src, unsigned num_components, 70bf215546Sopenharmony_ci const uint8_t *swizzle) 71bf215546Sopenharmony_ci{ 72bf215546Sopenharmony_ci /* only constant srcs: */ 73bf215546Sopenharmony_ci if (!nir_src_is_const(instr->src[src].src)) 74bf215546Sopenharmony_ci return false; 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ci int64_t int_min = u_intN_min(instr->src[src].src.ssa->bit_size); 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci for (unsigned i = 0; i < num_components; i++) { 79bf215546Sopenharmony_ci nir_alu_type type = nir_op_infos[instr->op].input_types[src]; 80bf215546Sopenharmony_ci switch (nir_alu_type_get_base_type(type)) { 81bf215546Sopenharmony_ci case nir_type_int: { 82bf215546Sopenharmony_ci int64_t val = nir_src_comp_as_int(instr->src[src].src, swizzle[i]); 83bf215546Sopenharmony_ci /* "int_min" is a power-of-two, but negation can cause overflow. */ 84bf215546Sopenharmony_ci if (val == int_min || val >= 0 || !util_is_power_of_two_or_zero64(-val)) 85bf215546Sopenharmony_ci return false; 86bf215546Sopenharmony_ci break; 87bf215546Sopenharmony_ci } 88bf215546Sopenharmony_ci default: 89bf215546Sopenharmony_ci return false; 90bf215546Sopenharmony_ci } 91bf215546Sopenharmony_ci } 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_ci return true; 94bf215546Sopenharmony_ci} 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_cistatic inline bool 97bf215546Sopenharmony_ciis_bitcount2(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 98bf215546Sopenharmony_ci unsigned src, unsigned num_components, 99bf215546Sopenharmony_ci const uint8_t *swizzle) 100bf215546Sopenharmony_ci{ 101bf215546Sopenharmony_ci /* only constant srcs: */ 102bf215546Sopenharmony_ci if (!nir_src_is_const(instr->src[src].src)) 103bf215546Sopenharmony_ci return false; 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci for (unsigned i = 0; i < num_components; i++) { 106bf215546Sopenharmony_ci uint64_t val = nir_src_comp_as_uint(instr->src[src].src, swizzle[i]); 107bf215546Sopenharmony_ci if (util_bitcount64(val) != 2) 108bf215546Sopenharmony_ci return false; 109bf215546Sopenharmony_ci } 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci return true; 112bf215546Sopenharmony_ci} 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci#define MULTIPLE(test) \ 115bf215546Sopenharmony_cistatic inline bool \ 116bf215546Sopenharmony_ciis_unsigned_multiple_of_ ## test(UNUSED struct hash_table *ht, \ 117bf215546Sopenharmony_ci const nir_alu_instr *instr, \ 118bf215546Sopenharmony_ci unsigned src, unsigned num_components, \ 119bf215546Sopenharmony_ci const uint8_t *swizzle) \ 120bf215546Sopenharmony_ci{ \ 121bf215546Sopenharmony_ci /* only constant srcs: */ \ 122bf215546Sopenharmony_ci if (!nir_src_is_const(instr->src[src].src)) \ 123bf215546Sopenharmony_ci return false; \ 124bf215546Sopenharmony_ci \ 125bf215546Sopenharmony_ci for (unsigned i = 0; i < num_components; i++) { \ 126bf215546Sopenharmony_ci uint64_t val = nir_src_comp_as_uint(instr->src[src].src, swizzle[i]); \ 127bf215546Sopenharmony_ci if (val % test != 0) \ 128bf215546Sopenharmony_ci return false; \ 129bf215546Sopenharmony_ci } \ 130bf215546Sopenharmony_ci \ 131bf215546Sopenharmony_ci return true; \ 132bf215546Sopenharmony_ci} 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ciMULTIPLE(2) 135bf215546Sopenharmony_ciMULTIPLE(4) 136bf215546Sopenharmony_ciMULTIPLE(8) 137bf215546Sopenharmony_ciMULTIPLE(16) 138bf215546Sopenharmony_ciMULTIPLE(32) 139bf215546Sopenharmony_ciMULTIPLE(64) 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_cistatic inline bool 142bf215546Sopenharmony_ciis_zero_to_one(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 143bf215546Sopenharmony_ci unsigned src, unsigned num_components, 144bf215546Sopenharmony_ci const uint8_t *swizzle) 145bf215546Sopenharmony_ci{ 146bf215546Sopenharmony_ci /* only constant srcs: */ 147bf215546Sopenharmony_ci if (!nir_src_is_const(instr->src[src].src)) 148bf215546Sopenharmony_ci return false; 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci for (unsigned i = 0; i < num_components; i++) { 151bf215546Sopenharmony_ci nir_alu_type type = nir_op_infos[instr->op].input_types[src]; 152bf215546Sopenharmony_ci switch (nir_alu_type_get_base_type(type)) { 153bf215546Sopenharmony_ci case nir_type_float: { 154bf215546Sopenharmony_ci double val = nir_src_comp_as_float(instr->src[src].src, swizzle[i]); 155bf215546Sopenharmony_ci if (isnan(val) || val < 0.0f || val > 1.0f) 156bf215546Sopenharmony_ci return false; 157bf215546Sopenharmony_ci break; 158bf215546Sopenharmony_ci } 159bf215546Sopenharmony_ci default: 160bf215546Sopenharmony_ci return false; 161bf215546Sopenharmony_ci } 162bf215546Sopenharmony_ci } 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci return true; 165bf215546Sopenharmony_ci} 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci/** 168bf215546Sopenharmony_ci * Exclusive compare with (0, 1). 169bf215546Sopenharmony_ci * 170bf215546Sopenharmony_ci * This differs from \c is_zero_to_one because that function tests 0 <= src <= 171bf215546Sopenharmony_ci * 1 while this function tests 0 < src < 1. 172bf215546Sopenharmony_ci */ 173bf215546Sopenharmony_cistatic inline bool 174bf215546Sopenharmony_ciis_gt_0_and_lt_1(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 175bf215546Sopenharmony_ci unsigned src, unsigned num_components, 176bf215546Sopenharmony_ci const uint8_t *swizzle) 177bf215546Sopenharmony_ci{ 178bf215546Sopenharmony_ci /* only constant srcs: */ 179bf215546Sopenharmony_ci if (!nir_src_is_const(instr->src[src].src)) 180bf215546Sopenharmony_ci return false; 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci for (unsigned i = 0; i < num_components; i++) { 183bf215546Sopenharmony_ci nir_alu_type type = nir_op_infos[instr->op].input_types[src]; 184bf215546Sopenharmony_ci switch (nir_alu_type_get_base_type(type)) { 185bf215546Sopenharmony_ci case nir_type_float: { 186bf215546Sopenharmony_ci double val = nir_src_comp_as_float(instr->src[src].src, swizzle[i]); 187bf215546Sopenharmony_ci if (isnan(val) || val <= 0.0f || val >= 1.0f) 188bf215546Sopenharmony_ci return false; 189bf215546Sopenharmony_ci break; 190bf215546Sopenharmony_ci } 191bf215546Sopenharmony_ci default: 192bf215546Sopenharmony_ci return false; 193bf215546Sopenharmony_ci } 194bf215546Sopenharmony_ci } 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci return true; 197bf215546Sopenharmony_ci} 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_cistatic inline bool 200bf215546Sopenharmony_ciis_not_const_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 201bf215546Sopenharmony_ci unsigned src, unsigned num_components, 202bf215546Sopenharmony_ci const uint8_t *swizzle) 203bf215546Sopenharmony_ci{ 204bf215546Sopenharmony_ci if (nir_src_as_const_value(instr->src[src].src) == NULL) 205bf215546Sopenharmony_ci return true; 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci for (unsigned i = 0; i < num_components; i++) { 208bf215546Sopenharmony_ci nir_alu_type type = nir_op_infos[instr->op].input_types[src]; 209bf215546Sopenharmony_ci switch (nir_alu_type_get_base_type(type)) { 210bf215546Sopenharmony_ci case nir_type_float: 211bf215546Sopenharmony_ci if (nir_src_comp_as_float(instr->src[src].src, swizzle[i]) == 0.0) 212bf215546Sopenharmony_ci return false; 213bf215546Sopenharmony_ci break; 214bf215546Sopenharmony_ci case nir_type_bool: 215bf215546Sopenharmony_ci case nir_type_int: 216bf215546Sopenharmony_ci case nir_type_uint: 217bf215546Sopenharmony_ci if (nir_src_comp_as_uint(instr->src[src].src, swizzle[i]) == 0) 218bf215546Sopenharmony_ci return false; 219bf215546Sopenharmony_ci break; 220bf215546Sopenharmony_ci default: 221bf215546Sopenharmony_ci return false; 222bf215546Sopenharmony_ci } 223bf215546Sopenharmony_ci } 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci return true; 226bf215546Sopenharmony_ci} 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci/** Is value unsigned less than 0xfffc07fc? */ 229bf215546Sopenharmony_cistatic inline bool 230bf215546Sopenharmony_ciis_ult_0xfffc07fc(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 231bf215546Sopenharmony_ci unsigned src, unsigned num_components, 232bf215546Sopenharmony_ci const uint8_t *swizzle) 233bf215546Sopenharmony_ci{ 234bf215546Sopenharmony_ci /* only constant srcs: */ 235bf215546Sopenharmony_ci if (!nir_src_is_const(instr->src[src].src)) 236bf215546Sopenharmony_ci return false; 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci for (unsigned i = 0; i < num_components; i++) { 239bf215546Sopenharmony_ci const unsigned val = 240bf215546Sopenharmony_ci nir_src_comp_as_uint(instr->src[src].src, swizzle[i]); 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_ci if (val >= 0xfffc07fcU) 243bf215546Sopenharmony_ci return false; 244bf215546Sopenharmony_ci } 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci return true; 247bf215546Sopenharmony_ci} 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci/** Is the first 5 bits of value unsigned greater than or equal 2? */ 250bf215546Sopenharmony_cistatic inline bool 251bf215546Sopenharmony_ciis_first_5_bits_uge_2(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 252bf215546Sopenharmony_ci unsigned src, unsigned num_components, 253bf215546Sopenharmony_ci const uint8_t *swizzle) 254bf215546Sopenharmony_ci{ 255bf215546Sopenharmony_ci /* only constant srcs: */ 256bf215546Sopenharmony_ci if (!nir_src_is_const(instr->src[src].src)) 257bf215546Sopenharmony_ci return false; 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci for (unsigned i = 0; i < num_components; i++) { 260bf215546Sopenharmony_ci const unsigned val = 261bf215546Sopenharmony_ci nir_src_comp_as_uint(instr->src[src].src, swizzle[i]); 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci if ((val & 0x1f) < 2) 264bf215546Sopenharmony_ci return false; 265bf215546Sopenharmony_ci } 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci return true; 268bf215546Sopenharmony_ci} 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_cistatic inline bool 271bf215546Sopenharmony_ciis_not_const(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 272bf215546Sopenharmony_ci unsigned src, UNUSED unsigned num_components, 273bf215546Sopenharmony_ci UNUSED const uint8_t *swizzle) 274bf215546Sopenharmony_ci{ 275bf215546Sopenharmony_ci return !nir_src_is_const(instr->src[src].src); 276bf215546Sopenharmony_ci} 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_cistatic inline bool 279bf215546Sopenharmony_ciis_not_fmul(struct hash_table *ht, const nir_alu_instr *instr, unsigned src, 280bf215546Sopenharmony_ci UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 281bf215546Sopenharmony_ci{ 282bf215546Sopenharmony_ci nir_alu_instr *src_alu = 283bf215546Sopenharmony_ci nir_src_as_alu_instr(instr->src[src].src); 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci if (src_alu == NULL) 286bf215546Sopenharmony_ci return true; 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_ci if (src_alu->op == nir_op_fneg) 289bf215546Sopenharmony_ci return is_not_fmul(ht, src_alu, 0, 0, NULL); 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci return src_alu->op != nir_op_fmul && src_alu->op != nir_op_fmulz; 292bf215546Sopenharmony_ci} 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_cistatic inline bool 295bf215546Sopenharmony_ciis_fmul(struct hash_table *ht, const nir_alu_instr *instr, unsigned src, 296bf215546Sopenharmony_ci UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 297bf215546Sopenharmony_ci{ 298bf215546Sopenharmony_ci nir_alu_instr *src_alu = 299bf215546Sopenharmony_ci nir_src_as_alu_instr(instr->src[src].src); 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci if (src_alu == NULL) 302bf215546Sopenharmony_ci return false; 303bf215546Sopenharmony_ci 304bf215546Sopenharmony_ci if (src_alu->op == nir_op_fneg) 305bf215546Sopenharmony_ci return is_fmul(ht, src_alu, 0, 0, NULL); 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci return src_alu->op == nir_op_fmul || src_alu->op == nir_op_fmulz; 308bf215546Sopenharmony_ci} 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_cistatic inline bool 311bf215546Sopenharmony_ciis_fsign(const nir_alu_instr *instr, unsigned src, 312bf215546Sopenharmony_ci UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 313bf215546Sopenharmony_ci{ 314bf215546Sopenharmony_ci nir_alu_instr *src_alu = 315bf215546Sopenharmony_ci nir_src_as_alu_instr(instr->src[src].src); 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_ci if (src_alu == NULL) 318bf215546Sopenharmony_ci return false; 319bf215546Sopenharmony_ci 320bf215546Sopenharmony_ci if (src_alu->op == nir_op_fneg) 321bf215546Sopenharmony_ci src_alu = nir_src_as_alu_instr(src_alu->src[0].src); 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ci return src_alu != NULL && src_alu->op == nir_op_fsign; 324bf215546Sopenharmony_ci} 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_cistatic inline bool 327bf215546Sopenharmony_ciis_not_const_and_not_fsign(struct hash_table *ht, const nir_alu_instr *instr, 328bf215546Sopenharmony_ci unsigned src, unsigned num_components, 329bf215546Sopenharmony_ci const uint8_t *swizzle) 330bf215546Sopenharmony_ci{ 331bf215546Sopenharmony_ci return is_not_const(ht, instr, src, num_components, swizzle) && 332bf215546Sopenharmony_ci !is_fsign(instr, src, num_components, swizzle); 333bf215546Sopenharmony_ci} 334bf215546Sopenharmony_ci 335bf215546Sopenharmony_cistatic inline bool 336bf215546Sopenharmony_ciis_used_once(const nir_alu_instr *instr) 337bf215546Sopenharmony_ci{ 338bf215546Sopenharmony_ci bool zero_if_use = list_is_empty(&instr->dest.dest.ssa.if_uses); 339bf215546Sopenharmony_ci bool zero_use = list_is_empty(&instr->dest.dest.ssa.uses); 340bf215546Sopenharmony_ci 341bf215546Sopenharmony_ci if (zero_if_use && zero_use) 342bf215546Sopenharmony_ci return false; 343bf215546Sopenharmony_ci 344bf215546Sopenharmony_ci if (!zero_if_use && list_is_singular(&instr->dest.dest.ssa.uses)) 345bf215546Sopenharmony_ci return false; 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_ci if (!zero_use && list_is_singular(&instr->dest.dest.ssa.if_uses)) 348bf215546Sopenharmony_ci return false; 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_ci if (!list_is_singular(&instr->dest.dest.ssa.if_uses) && 351bf215546Sopenharmony_ci !list_is_singular(&instr->dest.dest.ssa.uses)) 352bf215546Sopenharmony_ci return false; 353bf215546Sopenharmony_ci 354bf215546Sopenharmony_ci return true; 355bf215546Sopenharmony_ci} 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_cistatic inline bool 358bf215546Sopenharmony_ciis_used_by_if(const nir_alu_instr *instr) 359bf215546Sopenharmony_ci{ 360bf215546Sopenharmony_ci return !list_is_empty(&instr->dest.dest.ssa.if_uses); 361bf215546Sopenharmony_ci} 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_cistatic inline bool 364bf215546Sopenharmony_ciis_not_used_by_if(const nir_alu_instr *instr) 365bf215546Sopenharmony_ci{ 366bf215546Sopenharmony_ci return list_is_empty(&instr->dest.dest.ssa.if_uses); 367bf215546Sopenharmony_ci} 368bf215546Sopenharmony_ci 369bf215546Sopenharmony_cistatic inline bool 370bf215546Sopenharmony_ciis_used_by_non_fsat(const nir_alu_instr *instr) 371bf215546Sopenharmony_ci{ 372bf215546Sopenharmony_ci nir_foreach_use(src, &instr->dest.dest.ssa) { 373bf215546Sopenharmony_ci const nir_instr *const user_instr = src->parent_instr; 374bf215546Sopenharmony_ci 375bf215546Sopenharmony_ci if (user_instr->type != nir_instr_type_alu) 376bf215546Sopenharmony_ci return true; 377bf215546Sopenharmony_ci 378bf215546Sopenharmony_ci const nir_alu_instr *const user_alu = nir_instr_as_alu(user_instr); 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_ci assert(instr != user_alu); 381bf215546Sopenharmony_ci if (user_alu->op != nir_op_fsat) 382bf215546Sopenharmony_ci return true; 383bf215546Sopenharmony_ci } 384bf215546Sopenharmony_ci 385bf215546Sopenharmony_ci return false; 386bf215546Sopenharmony_ci} 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_cistatic inline bool 389bf215546Sopenharmony_ciis_only_used_as_float(const nir_alu_instr *instr) 390bf215546Sopenharmony_ci{ 391bf215546Sopenharmony_ci nir_foreach_use(src, &instr->dest.dest.ssa) { 392bf215546Sopenharmony_ci const nir_instr *const user_instr = src->parent_instr; 393bf215546Sopenharmony_ci if (user_instr->type != nir_instr_type_alu) 394bf215546Sopenharmony_ci return false; 395bf215546Sopenharmony_ci 396bf215546Sopenharmony_ci const nir_alu_instr *const user_alu = nir_instr_as_alu(user_instr); 397bf215546Sopenharmony_ci assert(instr != user_alu); 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_ci unsigned index = (nir_alu_src*)container_of(src, nir_alu_src, src) - user_alu->src; 400bf215546Sopenharmony_ci nir_alu_type type = nir_op_infos[user_alu->op].input_types[index]; 401bf215546Sopenharmony_ci if (nir_alu_type_get_base_type(type) != nir_type_float) 402bf215546Sopenharmony_ci return false; 403bf215546Sopenharmony_ci } 404bf215546Sopenharmony_ci 405bf215546Sopenharmony_ci return true; 406bf215546Sopenharmony_ci} 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_cistatic inline bool 409bf215546Sopenharmony_cionly_lower_8_bits_used(const nir_alu_instr *instr) 410bf215546Sopenharmony_ci{ 411bf215546Sopenharmony_ci return (nir_ssa_def_bits_used(&instr->dest.dest.ssa) & ~0xffull) == 0; 412bf215546Sopenharmony_ci} 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_cistatic inline bool 415bf215546Sopenharmony_cionly_lower_16_bits_used(const nir_alu_instr *instr) 416bf215546Sopenharmony_ci{ 417bf215546Sopenharmony_ci return (nir_ssa_def_bits_used(&instr->dest.dest.ssa) & ~0xffffull) == 0; 418bf215546Sopenharmony_ci} 419bf215546Sopenharmony_ci 420bf215546Sopenharmony_ci/** 421bf215546Sopenharmony_ci * Returns true if a NIR ALU src represents a constant integer 422bf215546Sopenharmony_ci * of either 32 or 64 bits, and the higher word (bit-size / 2) 423bf215546Sopenharmony_ci * of all its components is zero. 424bf215546Sopenharmony_ci */ 425bf215546Sopenharmony_cistatic inline bool 426bf215546Sopenharmony_ciis_upper_half_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 427bf215546Sopenharmony_ci unsigned src, unsigned num_components, 428bf215546Sopenharmony_ci const uint8_t *swizzle) 429bf215546Sopenharmony_ci{ 430bf215546Sopenharmony_ci if (nir_src_as_const_value(instr->src[src].src) == NULL) 431bf215546Sopenharmony_ci return false; 432bf215546Sopenharmony_ci 433bf215546Sopenharmony_ci for (unsigned i = 0; i < num_components; i++) { 434bf215546Sopenharmony_ci unsigned half_bit_size = nir_src_bit_size(instr->src[src].src) / 2; 435bf215546Sopenharmony_ci uint32_t high_bits = ((1 << half_bit_size) - 1) << half_bit_size; 436bf215546Sopenharmony_ci if ((nir_src_comp_as_uint(instr->src[src].src, 437bf215546Sopenharmony_ci swizzle[i]) & high_bits) != 0) { 438bf215546Sopenharmony_ci return false; 439bf215546Sopenharmony_ci } 440bf215546Sopenharmony_ci } 441bf215546Sopenharmony_ci 442bf215546Sopenharmony_ci return true; 443bf215546Sopenharmony_ci} 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_ci/** 446bf215546Sopenharmony_ci * Returns true if a NIR ALU src represents a constant integer 447bf215546Sopenharmony_ci * of either 32 or 64 bits, and the lower word (bit-size / 2) 448bf215546Sopenharmony_ci * of all its components is zero. 449bf215546Sopenharmony_ci */ 450bf215546Sopenharmony_cistatic inline bool 451bf215546Sopenharmony_ciis_lower_half_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 452bf215546Sopenharmony_ci unsigned src, unsigned num_components, 453bf215546Sopenharmony_ci const uint8_t *swizzle) 454bf215546Sopenharmony_ci{ 455bf215546Sopenharmony_ci if (nir_src_as_const_value(instr->src[src].src) == NULL) 456bf215546Sopenharmony_ci return false; 457bf215546Sopenharmony_ci 458bf215546Sopenharmony_ci for (unsigned i = 0; i < num_components; i++) { 459bf215546Sopenharmony_ci uint32_t low_bits = 460bf215546Sopenharmony_ci (1 << (nir_src_bit_size(instr->src[src].src) / 2)) - 1; 461bf215546Sopenharmony_ci if ((nir_src_comp_as_int(instr->src[src].src, swizzle[i]) & low_bits) != 0) 462bf215546Sopenharmony_ci return false; 463bf215546Sopenharmony_ci } 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci return true; 466bf215546Sopenharmony_ci} 467bf215546Sopenharmony_ci 468bf215546Sopenharmony_cistatic inline bool 469bf215546Sopenharmony_cino_signed_wrap(const nir_alu_instr *instr) 470bf215546Sopenharmony_ci{ 471bf215546Sopenharmony_ci return instr->no_signed_wrap; 472bf215546Sopenharmony_ci} 473bf215546Sopenharmony_ci 474bf215546Sopenharmony_cistatic inline bool 475bf215546Sopenharmony_cino_unsigned_wrap(const nir_alu_instr *instr) 476bf215546Sopenharmony_ci{ 477bf215546Sopenharmony_ci return instr->no_unsigned_wrap; 478bf215546Sopenharmony_ci} 479bf215546Sopenharmony_ci 480bf215546Sopenharmony_cistatic inline bool 481bf215546Sopenharmony_ciis_integral(struct hash_table *ht, const nir_alu_instr *instr, unsigned src, 482bf215546Sopenharmony_ci UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 483bf215546Sopenharmony_ci{ 484bf215546Sopenharmony_ci const struct ssa_result_range r = nir_analyze_range(ht, instr, src); 485bf215546Sopenharmony_ci 486bf215546Sopenharmony_ci return r.is_integral; 487bf215546Sopenharmony_ci} 488bf215546Sopenharmony_ci 489bf215546Sopenharmony_ci/** 490bf215546Sopenharmony_ci * Is the value finite? 491bf215546Sopenharmony_ci */ 492bf215546Sopenharmony_cistatic inline bool 493bf215546Sopenharmony_ciis_finite(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 494bf215546Sopenharmony_ci unsigned src, UNUSED unsigned num_components, 495bf215546Sopenharmony_ci UNUSED const uint8_t *swizzle) 496bf215546Sopenharmony_ci{ 497bf215546Sopenharmony_ci const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 498bf215546Sopenharmony_ci 499bf215546Sopenharmony_ci return v.is_finite; 500bf215546Sopenharmony_ci} 501bf215546Sopenharmony_ci 502bf215546Sopenharmony_cistatic inline bool 503bf215546Sopenharmony_ciis_finite_not_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 504bf215546Sopenharmony_ci unsigned src, UNUSED unsigned num_components, 505bf215546Sopenharmony_ci UNUSED const uint8_t *swizzle) 506bf215546Sopenharmony_ci{ 507bf215546Sopenharmony_ci const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_ci return v.is_finite && 510bf215546Sopenharmony_ci (v.range == lt_zero || v.range == gt_zero || v.range == ne_zero); 511bf215546Sopenharmony_ci} 512bf215546Sopenharmony_ci 513bf215546Sopenharmony_ci 514bf215546Sopenharmony_ci#define RELATION(r) \ 515bf215546Sopenharmony_cistatic inline bool \ 516bf215546Sopenharmony_ciis_ ## r (struct hash_table *ht, const nir_alu_instr *instr, \ 517bf215546Sopenharmony_ci unsigned src, UNUSED unsigned num_components, \ 518bf215546Sopenharmony_ci UNUSED const uint8_t *swizzle) \ 519bf215546Sopenharmony_ci{ \ 520bf215546Sopenharmony_ci const struct ssa_result_range v = nir_analyze_range(ht, instr, src); \ 521bf215546Sopenharmony_ci return v.range == r; \ 522bf215546Sopenharmony_ci} \ 523bf215546Sopenharmony_ci \ 524bf215546Sopenharmony_cistatic inline bool \ 525bf215546Sopenharmony_ciis_a_number_ ## r (struct hash_table *ht, const nir_alu_instr *instr, \ 526bf215546Sopenharmony_ci unsigned src, UNUSED unsigned num_components, \ 527bf215546Sopenharmony_ci UNUSED const uint8_t *swizzle) \ 528bf215546Sopenharmony_ci{ \ 529bf215546Sopenharmony_ci const struct ssa_result_range v = nir_analyze_range(ht, instr, src); \ 530bf215546Sopenharmony_ci return v.is_a_number && v.range == r; \ 531bf215546Sopenharmony_ci} 532bf215546Sopenharmony_ci 533bf215546Sopenharmony_ciRELATION(lt_zero) 534bf215546Sopenharmony_ciRELATION(le_zero) 535bf215546Sopenharmony_ciRELATION(gt_zero) 536bf215546Sopenharmony_ciRELATION(ge_zero) 537bf215546Sopenharmony_ciRELATION(ne_zero) 538bf215546Sopenharmony_ci 539bf215546Sopenharmony_cistatic inline bool 540bf215546Sopenharmony_ciis_not_negative(struct hash_table *ht, const nir_alu_instr *instr, unsigned src, 541bf215546Sopenharmony_ci UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 542bf215546Sopenharmony_ci{ 543bf215546Sopenharmony_ci const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 544bf215546Sopenharmony_ci return v.range == ge_zero || v.range == gt_zero || v.range == eq_zero; 545bf215546Sopenharmony_ci} 546bf215546Sopenharmony_ci 547bf215546Sopenharmony_cistatic inline bool 548bf215546Sopenharmony_ciis_a_number_not_negative(struct hash_table *ht, const nir_alu_instr *instr, 549bf215546Sopenharmony_ci unsigned src, UNUSED unsigned num_components, 550bf215546Sopenharmony_ci UNUSED const uint8_t *swizzle) 551bf215546Sopenharmony_ci{ 552bf215546Sopenharmony_ci const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 553bf215546Sopenharmony_ci return v.is_a_number && 554bf215546Sopenharmony_ci (v.range == ge_zero || v.range == gt_zero || v.range == eq_zero); 555bf215546Sopenharmony_ci} 556bf215546Sopenharmony_ci 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_cistatic inline bool 559bf215546Sopenharmony_ciis_not_positive(struct hash_table *ht, const nir_alu_instr *instr, unsigned src, 560bf215546Sopenharmony_ci UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 561bf215546Sopenharmony_ci{ 562bf215546Sopenharmony_ci const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 563bf215546Sopenharmony_ci return v.range == le_zero || v.range == lt_zero || v.range == eq_zero; 564bf215546Sopenharmony_ci} 565bf215546Sopenharmony_ci 566bf215546Sopenharmony_cistatic inline bool 567bf215546Sopenharmony_ciis_a_number_not_positive(struct hash_table *ht, const nir_alu_instr *instr, 568bf215546Sopenharmony_ci unsigned src, UNUSED unsigned num_components, 569bf215546Sopenharmony_ci UNUSED const uint8_t *swizzle) 570bf215546Sopenharmony_ci{ 571bf215546Sopenharmony_ci const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 572bf215546Sopenharmony_ci return v.is_a_number && 573bf215546Sopenharmony_ci (v.range == le_zero || v.range == lt_zero || v.range == eq_zero); 574bf215546Sopenharmony_ci} 575bf215546Sopenharmony_ci 576bf215546Sopenharmony_cistatic inline bool 577bf215546Sopenharmony_ciis_not_zero(struct hash_table *ht, const nir_alu_instr *instr, unsigned src, 578bf215546Sopenharmony_ci UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 579bf215546Sopenharmony_ci{ 580bf215546Sopenharmony_ci const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 581bf215546Sopenharmony_ci return v.range == lt_zero || v.range == gt_zero || v.range == ne_zero; 582bf215546Sopenharmony_ci} 583bf215546Sopenharmony_ci 584bf215546Sopenharmony_cistatic inline bool 585bf215546Sopenharmony_ciis_a_number_not_zero(struct hash_table *ht, const nir_alu_instr *instr, 586bf215546Sopenharmony_ci unsigned src, UNUSED unsigned num_components, 587bf215546Sopenharmony_ci UNUSED const uint8_t *swizzle) 588bf215546Sopenharmony_ci{ 589bf215546Sopenharmony_ci const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 590bf215546Sopenharmony_ci return v.is_a_number && 591bf215546Sopenharmony_ci (v.range == lt_zero || v.range == gt_zero || v.range == ne_zero); 592bf215546Sopenharmony_ci} 593bf215546Sopenharmony_ci 594bf215546Sopenharmony_cistatic inline bool 595bf215546Sopenharmony_ciis_a_number(struct hash_table *ht, const nir_alu_instr *instr, unsigned src, 596bf215546Sopenharmony_ci UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 597bf215546Sopenharmony_ci{ 598bf215546Sopenharmony_ci const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 599bf215546Sopenharmony_ci return v.is_a_number; 600bf215546Sopenharmony_ci} 601bf215546Sopenharmony_ci 602bf215546Sopenharmony_ci#endif /* _NIR_SEARCH_ */ 603