1/* 2 * Copyright © 2016 Red Hat 3 * 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: 10 * 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 13 * Software. 14 * 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 21 * IN THE SOFTWARE. 22 * 23 * Authors: 24 * Rob Clark <robclark@freedesktop.org> 25 */ 26 27#ifndef _NIR_SEARCH_HELPERS_ 28#define _NIR_SEARCH_HELPERS_ 29 30#include "nir.h" 31#include "util/bitscan.h" 32#include "nir_range_analysis.h" 33#include <math.h> 34 35static inline bool 36is_pos_power_of_two(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 37 unsigned src, unsigned num_components, 38 const uint8_t *swizzle) 39{ 40 /* only constant srcs: */ 41 if (!nir_src_is_const(instr->src[src].src)) 42 return false; 43 44 for (unsigned i = 0; i < num_components; i++) { 45 nir_alu_type type = nir_op_infos[instr->op].input_types[src]; 46 switch (nir_alu_type_get_base_type(type)) { 47 case nir_type_int: { 48 int64_t val = nir_src_comp_as_int(instr->src[src].src, swizzle[i]); 49 if (val <= 0 || !util_is_power_of_two_or_zero64(val)) 50 return false; 51 break; 52 } 53 case nir_type_uint: { 54 uint64_t val = nir_src_comp_as_uint(instr->src[src].src, swizzle[i]); 55 if (val == 0 || !util_is_power_of_two_or_zero64(val)) 56 return false; 57 break; 58 } 59 default: 60 return false; 61 } 62 } 63 64 return true; 65} 66 67static inline bool 68is_neg_power_of_two(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 69 unsigned src, unsigned num_components, 70 const uint8_t *swizzle) 71{ 72 /* only constant srcs: */ 73 if (!nir_src_is_const(instr->src[src].src)) 74 return false; 75 76 int64_t int_min = u_intN_min(instr->src[src].src.ssa->bit_size); 77 78 for (unsigned i = 0; i < num_components; i++) { 79 nir_alu_type type = nir_op_infos[instr->op].input_types[src]; 80 switch (nir_alu_type_get_base_type(type)) { 81 case nir_type_int: { 82 int64_t val = nir_src_comp_as_int(instr->src[src].src, swizzle[i]); 83 /* "int_min" is a power-of-two, but negation can cause overflow. */ 84 if (val == int_min || val >= 0 || !util_is_power_of_two_or_zero64(-val)) 85 return false; 86 break; 87 } 88 default: 89 return false; 90 } 91 } 92 93 return true; 94} 95 96#define MULTIPLE(test) \ 97static inline bool \ 98is_unsigned_multiple_of_ ## test(UNUSED struct hash_table *ht, \ 99 const nir_alu_instr *instr, \ 100 unsigned src, unsigned num_components, \ 101 const uint8_t *swizzle) \ 102{ \ 103 /* only constant srcs: */ \ 104 if (!nir_src_is_const(instr->src[src].src)) \ 105 return false; \ 106 \ 107 for (unsigned i = 0; i < num_components; i++) { \ 108 uint64_t val = nir_src_comp_as_uint(instr->src[src].src, swizzle[i]); \ 109 if (val % test != 0) \ 110 return false; \ 111 } \ 112 \ 113 return true; \ 114} 115 116MULTIPLE(2) 117MULTIPLE(4) 118MULTIPLE(8) 119MULTIPLE(16) 120MULTIPLE(32) 121MULTIPLE(64) 122 123static inline bool 124is_zero_to_one(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 125 unsigned src, unsigned num_components, 126 const uint8_t *swizzle) 127{ 128 /* only constant srcs: */ 129 if (!nir_src_is_const(instr->src[src].src)) 130 return false; 131 132 for (unsigned i = 0; i < num_components; i++) { 133 switch (nir_op_infos[instr->op].input_types[src]) { 134 case nir_type_float: { 135 double val = nir_src_comp_as_float(instr->src[src].src, swizzle[i]); 136 if (isnan(val) || val < 0.0f || val > 1.0f) 137 return false; 138 break; 139 } 140 default: 141 return false; 142 } 143 } 144 145 return true; 146} 147 148/** 149 * Exclusive compare with (0, 1). 150 * 151 * This differs from \c is_zero_to_one because that function tests 0 <= src <= 152 * 1 while this function tests 0 < src < 1. 153 */ 154static inline bool 155is_gt_0_and_lt_1(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 156 unsigned src, unsigned num_components, 157 const uint8_t *swizzle) 158{ 159 /* only constant srcs: */ 160 if (!nir_src_is_const(instr->src[src].src)) 161 return false; 162 163 for (unsigned i = 0; i < num_components; i++) { 164 switch (nir_op_infos[instr->op].input_types[src]) { 165 case nir_type_float: { 166 double val = nir_src_comp_as_float(instr->src[src].src, swizzle[i]); 167 if (isnan(val) || val <= 0.0f || val >= 1.0f) 168 return false; 169 break; 170 } 171 default: 172 return false; 173 } 174 } 175 176 return true; 177} 178 179static inline bool 180is_not_const_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 181 unsigned src, unsigned num_components, 182 const uint8_t *swizzle) 183{ 184 if (nir_src_as_const_value(instr->src[src].src) == NULL) 185 return true; 186 187 for (unsigned i = 0; i < num_components; i++) { 188 nir_alu_type type = nir_op_infos[instr->op].input_types[src]; 189 switch (nir_alu_type_get_base_type(type)) { 190 case nir_type_float: 191 if (nir_src_comp_as_float(instr->src[src].src, swizzle[i]) == 0.0) 192 return false; 193 break; 194 case nir_type_bool: 195 case nir_type_int: 196 case nir_type_uint: 197 if (nir_src_comp_as_uint(instr->src[src].src, swizzle[i]) == 0) 198 return false; 199 break; 200 default: 201 return false; 202 } 203 } 204 205 return true; 206} 207 208/** Is value unsigned less than 0xfffc07fc? */ 209static inline bool 210is_ult_0xfffc07fc(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 211 unsigned src, unsigned num_components, 212 const uint8_t *swizzle) 213{ 214 /* only constant srcs: */ 215 if (!nir_src_is_const(instr->src[src].src)) 216 return false; 217 218 for (unsigned i = 0; i < num_components; i++) { 219 const unsigned val = 220 nir_src_comp_as_uint(instr->src[src].src, swizzle[i]); 221 222 if (val >= 0xfffc07fcU) 223 return false; 224 } 225 226 return true; 227} 228 229static inline bool 230is_not_const(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 231 unsigned src, UNUSED unsigned num_components, 232 UNUSED const uint8_t *swizzle) 233{ 234 return !nir_src_is_const(instr->src[src].src); 235} 236 237static inline bool 238is_not_fmul(struct hash_table *ht, const nir_alu_instr *instr, unsigned src, 239 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 240{ 241 nir_alu_instr *src_alu = 242 nir_src_as_alu_instr(instr->src[src].src); 243 244 if (src_alu == NULL) 245 return true; 246 247 if (src_alu->op == nir_op_fneg) 248 return is_not_fmul(ht, src_alu, 0, 0, NULL); 249 250 return src_alu->op != nir_op_fmul; 251} 252 253static inline bool 254is_fmul(struct hash_table *ht, const nir_alu_instr *instr, unsigned src, 255 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 256{ 257 nir_alu_instr *src_alu = 258 nir_src_as_alu_instr(instr->src[src].src); 259 260 if (src_alu == NULL) 261 return false; 262 263 if (src_alu->op == nir_op_fneg) 264 return is_fmul(ht, src_alu, 0, 0, NULL); 265 266 return src_alu->op == nir_op_fmul; 267} 268 269static inline bool 270is_fsign(const nir_alu_instr *instr, unsigned src, 271 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 272{ 273 nir_alu_instr *src_alu = 274 nir_src_as_alu_instr(instr->src[src].src); 275 276 if (src_alu == NULL) 277 return false; 278 279 if (src_alu->op == nir_op_fneg) 280 src_alu = nir_src_as_alu_instr(src_alu->src[0].src); 281 282 return src_alu != NULL && src_alu->op == nir_op_fsign; 283} 284 285static inline bool 286is_not_const_and_not_fsign(struct hash_table *ht, const nir_alu_instr *instr, 287 unsigned src, unsigned num_components, 288 const uint8_t *swizzle) 289{ 290 return is_not_const(ht, instr, src, num_components, swizzle) && 291 !is_fsign(instr, src, num_components, swizzle); 292} 293 294static inline bool 295is_used_once(nir_alu_instr *instr) 296{ 297 bool zero_if_use = list_is_empty(&instr->dest.dest.ssa.if_uses); 298 bool zero_use = list_is_empty(&instr->dest.dest.ssa.uses); 299 300 if (zero_if_use && zero_use) 301 return false; 302 303 if (!zero_if_use && list_is_singular(&instr->dest.dest.ssa.uses)) 304 return false; 305 306 if (!zero_use && list_is_singular(&instr->dest.dest.ssa.if_uses)) 307 return false; 308 309 if (!list_is_singular(&instr->dest.dest.ssa.if_uses) && 310 !list_is_singular(&instr->dest.dest.ssa.uses)) 311 return false; 312 313 return true; 314} 315 316static inline bool 317is_used_by_if(nir_alu_instr *instr) 318{ 319 return !list_is_empty(&instr->dest.dest.ssa.if_uses); 320} 321 322static inline bool 323is_not_used_by_if(nir_alu_instr *instr) 324{ 325 return list_is_empty(&instr->dest.dest.ssa.if_uses); 326} 327 328static inline bool 329is_used_by_non_fsat(nir_alu_instr *instr) 330{ 331 nir_foreach_use(src, &instr->dest.dest.ssa) { 332 const nir_instr *const user_instr = src->parent_instr; 333 334 if (user_instr->type != nir_instr_type_alu) 335 return true; 336 337 const nir_alu_instr *const user_alu = nir_instr_as_alu(user_instr); 338 339 assert(instr != user_alu); 340 if (user_alu->op != nir_op_fsat) 341 return true; 342 } 343 344 return false; 345} 346 347static inline bool 348is_only_used_as_float(nir_alu_instr *instr) 349{ 350 nir_foreach_use(src, &instr->dest.dest.ssa) { 351 const nir_instr *const user_instr = src->parent_instr; 352 if (user_instr->type != nir_instr_type_alu) 353 return false; 354 355 const nir_alu_instr *const user_alu = nir_instr_as_alu(user_instr); 356 assert(instr != user_alu); 357 358 unsigned index = (nir_alu_src*)container_of(src, nir_alu_src, src) - user_alu->src; 359 if (nir_op_infos[user_alu->op].input_types[index] != nir_type_float) 360 return false; 361 } 362 363 return true; 364} 365 366static inline bool 367only_lower_8_bits_used(nir_alu_instr *instr) 368{ 369 return (nir_ssa_def_bits_used(&instr->dest.dest.ssa) & ~0xffull) == 0; 370} 371 372static inline bool 373only_lower_16_bits_used(nir_alu_instr *instr) 374{ 375 return (nir_ssa_def_bits_used(&instr->dest.dest.ssa) & ~0xffffull) == 0; 376} 377 378/** 379 * Returns true if a NIR ALU src represents a constant integer 380 * of either 32 or 64 bits, and the higher word (bit-size / 2) 381 * of all its components is zero. 382 */ 383static inline bool 384is_upper_half_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 385 unsigned src, unsigned num_components, 386 const uint8_t *swizzle) 387{ 388 if (nir_src_as_const_value(instr->src[src].src) == NULL) 389 return false; 390 391 for (unsigned i = 0; i < num_components; i++) { 392 unsigned half_bit_size = nir_src_bit_size(instr->src[src].src) / 2; 393 uint32_t high_bits = ((1 << half_bit_size) - 1) << half_bit_size; 394 if ((nir_src_comp_as_uint(instr->src[src].src, 395 swizzle[i]) & high_bits) != 0) { 396 return false; 397 } 398 } 399 400 return true; 401} 402 403/** 404 * Returns true if a NIR ALU src represents a constant integer 405 * of either 32 or 64 bits, and the lower word (bit-size / 2) 406 * of all its components is zero. 407 */ 408static inline bool 409is_lower_half_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 410 unsigned src, unsigned num_components, 411 const uint8_t *swizzle) 412{ 413 if (nir_src_as_const_value(instr->src[src].src) == NULL) 414 return false; 415 416 for (unsigned i = 0; i < num_components; i++) { 417 uint32_t low_bits = 418 (1 << (nir_src_bit_size(instr->src[src].src) / 2)) - 1; 419 if ((nir_src_comp_as_int(instr->src[src].src, swizzle[i]) & low_bits) != 0) 420 return false; 421 } 422 423 return true; 424} 425 426static inline bool 427no_signed_wrap(nir_alu_instr *instr) 428{ 429 return instr->no_signed_wrap; 430} 431 432static inline bool 433no_unsigned_wrap(nir_alu_instr *instr) 434{ 435 return instr->no_unsigned_wrap; 436} 437 438static inline bool 439is_integral(struct hash_table *ht, const nir_alu_instr *instr, unsigned src, 440 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 441{ 442 const struct ssa_result_range r = nir_analyze_range(ht, instr, src); 443 444 return r.is_integral; 445} 446 447/** 448 * Is the value finite? 449 */ 450static inline bool 451is_finite(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 452 unsigned src, UNUSED unsigned num_components, 453 UNUSED const uint8_t *swizzle) 454{ 455 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 456 457 return v.is_finite; 458} 459 460 461#define RELATION(r) \ 462static inline bool \ 463is_ ## r (struct hash_table *ht, const nir_alu_instr *instr, \ 464 unsigned src, UNUSED unsigned num_components, \ 465 UNUSED const uint8_t *swizzle) \ 466{ \ 467 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); \ 468 return v.range == r; \ 469} \ 470 \ 471static inline bool \ 472is_a_number_ ## r (struct hash_table *ht, const nir_alu_instr *instr, \ 473 unsigned src, UNUSED unsigned num_components, \ 474 UNUSED const uint8_t *swizzle) \ 475{ \ 476 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); \ 477 return v.is_a_number && v.range == r; \ 478} 479 480RELATION(lt_zero) 481RELATION(le_zero) 482RELATION(gt_zero) 483RELATION(ge_zero) 484RELATION(ne_zero) 485 486static inline bool 487is_not_negative(struct hash_table *ht, const nir_alu_instr *instr, unsigned src, 488 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 489{ 490 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 491 return v.range == ge_zero || v.range == gt_zero || v.range == eq_zero; 492} 493 494static inline bool 495is_a_number_not_negative(struct hash_table *ht, const nir_alu_instr *instr, 496 unsigned src, UNUSED unsigned num_components, 497 UNUSED const uint8_t *swizzle) 498{ 499 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 500 return v.is_a_number && 501 (v.range == ge_zero || v.range == gt_zero || v.range == eq_zero); 502} 503 504 505static inline bool 506is_not_positive(struct hash_table *ht, const nir_alu_instr *instr, unsigned src, 507 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 508{ 509 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 510 return v.range == le_zero || v.range == lt_zero || v.range == eq_zero; 511} 512 513static inline bool 514is_a_number_not_positive(struct hash_table *ht, const nir_alu_instr *instr, 515 unsigned src, UNUSED unsigned num_components, 516 UNUSED const uint8_t *swizzle) 517{ 518 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 519 return v.is_a_number && 520 (v.range == le_zero || v.range == lt_zero || v.range == eq_zero); 521} 522 523static inline bool 524is_not_zero(struct hash_table *ht, const nir_alu_instr *instr, unsigned src, 525 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 526{ 527 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 528 return v.range == lt_zero || v.range == gt_zero || v.range == ne_zero; 529} 530 531static inline bool 532is_a_number_not_zero(struct hash_table *ht, const nir_alu_instr *instr, 533 unsigned src, UNUSED unsigned num_components, 534 UNUSED const uint8_t *swizzle) 535{ 536 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 537 return v.is_a_number && 538 (v.range == lt_zero || v.range == gt_zero || v.range == ne_zero); 539} 540 541static inline bool 542is_a_number(struct hash_table *ht, const nir_alu_instr *instr, unsigned src, 543 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 544{ 545 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 546 return v.is_a_number; 547} 548 549#endif /* _NIR_SEARCH_ */ 550