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 96static inline bool 97is_bitcount2(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 98 unsigned src, unsigned num_components, 99 const uint8_t *swizzle) 100{ 101 /* only constant srcs: */ 102 if (!nir_src_is_const(instr->src[src].src)) 103 return false; 104 105 for (unsigned i = 0; i < num_components; i++) { 106 uint64_t val = nir_src_comp_as_uint(instr->src[src].src, swizzle[i]); 107 if (util_bitcount64(val) != 2) 108 return false; 109 } 110 111 return true; 112} 113 114#define MULTIPLE(test) \ 115static inline bool \ 116is_unsigned_multiple_of_ ## test(UNUSED struct hash_table *ht, \ 117 const nir_alu_instr *instr, \ 118 unsigned src, unsigned num_components, \ 119 const uint8_t *swizzle) \ 120{ \ 121 /* only constant srcs: */ \ 122 if (!nir_src_is_const(instr->src[src].src)) \ 123 return false; \ 124 \ 125 for (unsigned i = 0; i < num_components; i++) { \ 126 uint64_t val = nir_src_comp_as_uint(instr->src[src].src, swizzle[i]); \ 127 if (val % test != 0) \ 128 return false; \ 129 } \ 130 \ 131 return true; \ 132} 133 134MULTIPLE(2) 135MULTIPLE(4) 136MULTIPLE(8) 137MULTIPLE(16) 138MULTIPLE(32) 139MULTIPLE(64) 140 141static inline bool 142is_zero_to_one(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 143 unsigned src, unsigned num_components, 144 const uint8_t *swizzle) 145{ 146 /* only constant srcs: */ 147 if (!nir_src_is_const(instr->src[src].src)) 148 return false; 149 150 for (unsigned i = 0; i < num_components; i++) { 151 nir_alu_type type = nir_op_infos[instr->op].input_types[src]; 152 switch (nir_alu_type_get_base_type(type)) { 153 case nir_type_float: { 154 double val = nir_src_comp_as_float(instr->src[src].src, swizzle[i]); 155 if (isnan(val) || val < 0.0f || val > 1.0f) 156 return false; 157 break; 158 } 159 default: 160 return false; 161 } 162 } 163 164 return true; 165} 166 167/** 168 * Exclusive compare with (0, 1). 169 * 170 * This differs from \c is_zero_to_one because that function tests 0 <= src <= 171 * 1 while this function tests 0 < src < 1. 172 */ 173static inline bool 174is_gt_0_and_lt_1(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 175 unsigned src, unsigned num_components, 176 const uint8_t *swizzle) 177{ 178 /* only constant srcs: */ 179 if (!nir_src_is_const(instr->src[src].src)) 180 return false; 181 182 for (unsigned i = 0; i < num_components; i++) { 183 nir_alu_type type = nir_op_infos[instr->op].input_types[src]; 184 switch (nir_alu_type_get_base_type(type)) { 185 case nir_type_float: { 186 double val = nir_src_comp_as_float(instr->src[src].src, swizzle[i]); 187 if (isnan(val) || val <= 0.0f || val >= 1.0f) 188 return false; 189 break; 190 } 191 default: 192 return false; 193 } 194 } 195 196 return true; 197} 198 199static inline bool 200is_not_const_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 201 unsigned src, unsigned num_components, 202 const uint8_t *swizzle) 203{ 204 if (nir_src_as_const_value(instr->src[src].src) == NULL) 205 return true; 206 207 for (unsigned i = 0; i < num_components; i++) { 208 nir_alu_type type = nir_op_infos[instr->op].input_types[src]; 209 switch (nir_alu_type_get_base_type(type)) { 210 case nir_type_float: 211 if (nir_src_comp_as_float(instr->src[src].src, swizzle[i]) == 0.0) 212 return false; 213 break; 214 case nir_type_bool: 215 case nir_type_int: 216 case nir_type_uint: 217 if (nir_src_comp_as_uint(instr->src[src].src, swizzle[i]) == 0) 218 return false; 219 break; 220 default: 221 return false; 222 } 223 } 224 225 return true; 226} 227 228/** Is value unsigned less than 0xfffc07fc? */ 229static inline bool 230is_ult_0xfffc07fc(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 231 unsigned src, unsigned num_components, 232 const uint8_t *swizzle) 233{ 234 /* only constant srcs: */ 235 if (!nir_src_is_const(instr->src[src].src)) 236 return false; 237 238 for (unsigned i = 0; i < num_components; i++) { 239 const unsigned val = 240 nir_src_comp_as_uint(instr->src[src].src, swizzle[i]); 241 242 if (val >= 0xfffc07fcU) 243 return false; 244 } 245 246 return true; 247} 248 249/** Is the first 5 bits of value unsigned greater than or equal 2? */ 250static inline bool 251is_first_5_bits_uge_2(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 252 unsigned src, unsigned num_components, 253 const uint8_t *swizzle) 254{ 255 /* only constant srcs: */ 256 if (!nir_src_is_const(instr->src[src].src)) 257 return false; 258 259 for (unsigned i = 0; i < num_components; i++) { 260 const unsigned val = 261 nir_src_comp_as_uint(instr->src[src].src, swizzle[i]); 262 263 if ((val & 0x1f) < 2) 264 return false; 265 } 266 267 return true; 268} 269 270static inline bool 271is_not_const(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 272 unsigned src, UNUSED unsigned num_components, 273 UNUSED const uint8_t *swizzle) 274{ 275 return !nir_src_is_const(instr->src[src].src); 276} 277 278static inline bool 279is_not_fmul(struct hash_table *ht, const nir_alu_instr *instr, unsigned src, 280 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 281{ 282 nir_alu_instr *src_alu = 283 nir_src_as_alu_instr(instr->src[src].src); 284 285 if (src_alu == NULL) 286 return true; 287 288 if (src_alu->op == nir_op_fneg) 289 return is_not_fmul(ht, src_alu, 0, 0, NULL); 290 291 return src_alu->op != nir_op_fmul && src_alu->op != nir_op_fmulz; 292} 293 294static inline bool 295is_fmul(struct hash_table *ht, const nir_alu_instr *instr, unsigned src, 296 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 297{ 298 nir_alu_instr *src_alu = 299 nir_src_as_alu_instr(instr->src[src].src); 300 301 if (src_alu == NULL) 302 return false; 303 304 if (src_alu->op == nir_op_fneg) 305 return is_fmul(ht, src_alu, 0, 0, NULL); 306 307 return src_alu->op == nir_op_fmul || src_alu->op == nir_op_fmulz; 308} 309 310static inline bool 311is_fsign(const nir_alu_instr *instr, unsigned src, 312 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 313{ 314 nir_alu_instr *src_alu = 315 nir_src_as_alu_instr(instr->src[src].src); 316 317 if (src_alu == NULL) 318 return false; 319 320 if (src_alu->op == nir_op_fneg) 321 src_alu = nir_src_as_alu_instr(src_alu->src[0].src); 322 323 return src_alu != NULL && src_alu->op == nir_op_fsign; 324} 325 326static inline bool 327is_not_const_and_not_fsign(struct hash_table *ht, const nir_alu_instr *instr, 328 unsigned src, unsigned num_components, 329 const uint8_t *swizzle) 330{ 331 return is_not_const(ht, instr, src, num_components, swizzle) && 332 !is_fsign(instr, src, num_components, swizzle); 333} 334 335static inline bool 336is_used_once(const nir_alu_instr *instr) 337{ 338 bool zero_if_use = list_is_empty(&instr->dest.dest.ssa.if_uses); 339 bool zero_use = list_is_empty(&instr->dest.dest.ssa.uses); 340 341 if (zero_if_use && zero_use) 342 return false; 343 344 if (!zero_if_use && list_is_singular(&instr->dest.dest.ssa.uses)) 345 return false; 346 347 if (!zero_use && list_is_singular(&instr->dest.dest.ssa.if_uses)) 348 return false; 349 350 if (!list_is_singular(&instr->dest.dest.ssa.if_uses) && 351 !list_is_singular(&instr->dest.dest.ssa.uses)) 352 return false; 353 354 return true; 355} 356 357static inline bool 358is_used_by_if(const nir_alu_instr *instr) 359{ 360 return !list_is_empty(&instr->dest.dest.ssa.if_uses); 361} 362 363static inline bool 364is_not_used_by_if(const nir_alu_instr *instr) 365{ 366 return list_is_empty(&instr->dest.dest.ssa.if_uses); 367} 368 369static inline bool 370is_used_by_non_fsat(const nir_alu_instr *instr) 371{ 372 nir_foreach_use(src, &instr->dest.dest.ssa) { 373 const nir_instr *const user_instr = src->parent_instr; 374 375 if (user_instr->type != nir_instr_type_alu) 376 return true; 377 378 const nir_alu_instr *const user_alu = nir_instr_as_alu(user_instr); 379 380 assert(instr != user_alu); 381 if (user_alu->op != nir_op_fsat) 382 return true; 383 } 384 385 return false; 386} 387 388static inline bool 389is_only_used_as_float(const nir_alu_instr *instr) 390{ 391 nir_foreach_use(src, &instr->dest.dest.ssa) { 392 const nir_instr *const user_instr = src->parent_instr; 393 if (user_instr->type != nir_instr_type_alu) 394 return false; 395 396 const nir_alu_instr *const user_alu = nir_instr_as_alu(user_instr); 397 assert(instr != user_alu); 398 399 unsigned index = (nir_alu_src*)container_of(src, nir_alu_src, src) - user_alu->src; 400 nir_alu_type type = nir_op_infos[user_alu->op].input_types[index]; 401 if (nir_alu_type_get_base_type(type) != nir_type_float) 402 return false; 403 } 404 405 return true; 406} 407 408static inline bool 409only_lower_8_bits_used(const nir_alu_instr *instr) 410{ 411 return (nir_ssa_def_bits_used(&instr->dest.dest.ssa) & ~0xffull) == 0; 412} 413 414static inline bool 415only_lower_16_bits_used(const nir_alu_instr *instr) 416{ 417 return (nir_ssa_def_bits_used(&instr->dest.dest.ssa) & ~0xffffull) == 0; 418} 419 420/** 421 * Returns true if a NIR ALU src represents a constant integer 422 * of either 32 or 64 bits, and the higher word (bit-size / 2) 423 * of all its components is zero. 424 */ 425static inline bool 426is_upper_half_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 427 unsigned src, unsigned num_components, 428 const uint8_t *swizzle) 429{ 430 if (nir_src_as_const_value(instr->src[src].src) == NULL) 431 return false; 432 433 for (unsigned i = 0; i < num_components; i++) { 434 unsigned half_bit_size = nir_src_bit_size(instr->src[src].src) / 2; 435 uint32_t high_bits = ((1 << half_bit_size) - 1) << half_bit_size; 436 if ((nir_src_comp_as_uint(instr->src[src].src, 437 swizzle[i]) & high_bits) != 0) { 438 return false; 439 } 440 } 441 442 return true; 443} 444 445/** 446 * Returns true if a NIR ALU src represents a constant integer 447 * of either 32 or 64 bits, and the lower word (bit-size / 2) 448 * of all its components is zero. 449 */ 450static inline bool 451is_lower_half_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 452 unsigned src, unsigned num_components, 453 const uint8_t *swizzle) 454{ 455 if (nir_src_as_const_value(instr->src[src].src) == NULL) 456 return false; 457 458 for (unsigned i = 0; i < num_components; i++) { 459 uint32_t low_bits = 460 (1 << (nir_src_bit_size(instr->src[src].src) / 2)) - 1; 461 if ((nir_src_comp_as_int(instr->src[src].src, swizzle[i]) & low_bits) != 0) 462 return false; 463 } 464 465 return true; 466} 467 468static inline bool 469no_signed_wrap(const nir_alu_instr *instr) 470{ 471 return instr->no_signed_wrap; 472} 473 474static inline bool 475no_unsigned_wrap(const nir_alu_instr *instr) 476{ 477 return instr->no_unsigned_wrap; 478} 479 480static inline bool 481is_integral(struct hash_table *ht, const nir_alu_instr *instr, unsigned src, 482 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 483{ 484 const struct ssa_result_range r = nir_analyze_range(ht, instr, src); 485 486 return r.is_integral; 487} 488 489/** 490 * Is the value finite? 491 */ 492static inline bool 493is_finite(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 494 unsigned src, UNUSED unsigned num_components, 495 UNUSED const uint8_t *swizzle) 496{ 497 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 498 499 return v.is_finite; 500} 501 502static inline bool 503is_finite_not_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr, 504 unsigned src, UNUSED unsigned num_components, 505 UNUSED const uint8_t *swizzle) 506{ 507 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 508 509 return v.is_finite && 510 (v.range == lt_zero || v.range == gt_zero || v.range == ne_zero); 511} 512 513 514#define RELATION(r) \ 515static inline bool \ 516is_ ## r (struct hash_table *ht, const nir_alu_instr *instr, \ 517 unsigned src, UNUSED unsigned num_components, \ 518 UNUSED const uint8_t *swizzle) \ 519{ \ 520 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); \ 521 return v.range == r; \ 522} \ 523 \ 524static inline bool \ 525is_a_number_ ## r (struct hash_table *ht, const nir_alu_instr *instr, \ 526 unsigned src, UNUSED unsigned num_components, \ 527 UNUSED const uint8_t *swizzle) \ 528{ \ 529 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); \ 530 return v.is_a_number && v.range == r; \ 531} 532 533RELATION(lt_zero) 534RELATION(le_zero) 535RELATION(gt_zero) 536RELATION(ge_zero) 537RELATION(ne_zero) 538 539static inline bool 540is_not_negative(struct hash_table *ht, const nir_alu_instr *instr, unsigned src, 541 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 542{ 543 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 544 return v.range == ge_zero || v.range == gt_zero || v.range == eq_zero; 545} 546 547static inline bool 548is_a_number_not_negative(struct hash_table *ht, const nir_alu_instr *instr, 549 unsigned src, UNUSED unsigned num_components, 550 UNUSED const uint8_t *swizzle) 551{ 552 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 553 return v.is_a_number && 554 (v.range == ge_zero || v.range == gt_zero || v.range == eq_zero); 555} 556 557 558static inline bool 559is_not_positive(struct hash_table *ht, const nir_alu_instr *instr, unsigned src, 560 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 561{ 562 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 563 return v.range == le_zero || v.range == lt_zero || v.range == eq_zero; 564} 565 566static inline bool 567is_a_number_not_positive(struct hash_table *ht, const nir_alu_instr *instr, 568 unsigned src, UNUSED unsigned num_components, 569 UNUSED const uint8_t *swizzle) 570{ 571 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 572 return v.is_a_number && 573 (v.range == le_zero || v.range == lt_zero || v.range == eq_zero); 574} 575 576static inline bool 577is_not_zero(struct hash_table *ht, const nir_alu_instr *instr, unsigned src, 578 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 579{ 580 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 581 return v.range == lt_zero || v.range == gt_zero || v.range == ne_zero; 582} 583 584static inline bool 585is_a_number_not_zero(struct hash_table *ht, const nir_alu_instr *instr, 586 unsigned src, UNUSED unsigned num_components, 587 UNUSED const uint8_t *swizzle) 588{ 589 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 590 return v.is_a_number && 591 (v.range == lt_zero || v.range == gt_zero || v.range == ne_zero); 592} 593 594static inline bool 595is_a_number(struct hash_table *ht, const nir_alu_instr *instr, unsigned src, 596 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) 597{ 598 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); 599 return v.is_a_number; 600} 601 602#endif /* _NIR_SEARCH_ */ 603