2 * Copyright © 2018 Intel Corporation
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:
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
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
26 #include "nir_range_analysis.h"
27 #include "util/hash_table.h"
30 * Analyzes a sequence of operations to determine some aspects of the range of
35 pack_data(const struct ssa_result_range r
)
37 return (void *)(uintptr_t)(r
.range
| r
.is_integral
<< 8);
40 static struct ssa_result_range
41 unpack_data(const void *p
)
43 const uintptr_t v
= (uintptr_t) p
;
45 return (struct ssa_result_range
){v
& 0xff, (v
& 0x0ff00) != 0};
48 static struct ssa_result_range
49 analyze_constant(const struct nir_alu_instr
*instr
, unsigned src
)
51 uint8_t swizzle
[4] = { 0, 1, 2, 3 };
53 /* If the source is an explicitly sized source, then we need to reset
54 * both the number of components and the swizzle.
56 const unsigned num_components
= nir_ssa_alu_instr_src_components(instr
, src
);
58 for (unsigned i
= 0; i
< num_components
; ++i
)
59 swizzle
[i
] = instr
->src
[src
].swizzle
[i
];
61 const nir_load_const_instr
*const load
=
62 nir_instr_as_load_const(instr
->src
[src
].src
.ssa
->parent_instr
);
64 struct ssa_result_range r
= { unknown
, false };
66 switch (nir_op_infos
[instr
->op
].input_types
[src
]) {
67 case nir_type_float
: {
68 double min_value
= DBL_MAX
;
69 double max_value
= -DBL_MAX
;
70 bool any_zero
= false;
75 for (unsigned i
= 0; i
< num_components
; ++i
) {
76 const double v
= nir_const_value_as_float(load
->value
[swizzle
[i
]],
80 r
.is_integral
= false;
82 any_zero
= any_zero
|| (v
== 0.0);
83 all_zero
= all_zero
&& (v
== 0.0);
84 min_value
= MIN2(min_value
, v
);
85 max_value
= MAX2(max_value
, v
);
88 assert(any_zero
>= all_zero
);
89 assert(isnan(max_value
) || max_value
>= min_value
);
93 else if (min_value
> 0.0)
95 else if (min_value
== 0.0)
97 else if (max_value
< 0.0)
99 else if (max_value
== 0.0)
110 case nir_type_bool
: {
111 int64_t min_value
= INT_MAX
;
112 int64_t max_value
= INT_MIN
;
113 bool any_zero
= false;
114 bool all_zero
= true;
116 for (unsigned i
= 0; i
< num_components
; ++i
) {
117 const int64_t v
= nir_const_value_as_int(load
->value
[swizzle
[i
]],
120 any_zero
= any_zero
|| (v
== 0);
121 all_zero
= all_zero
&& (v
== 0);
122 min_value
= MIN2(min_value
, v
);
123 max_value
= MAX2(max_value
, v
);
126 assert(any_zero
>= all_zero
);
127 assert(max_value
>= min_value
);
131 else if (min_value
> 0)
133 else if (min_value
== 0)
135 else if (max_value
< 0)
137 else if (max_value
== 0)
147 case nir_type_uint
: {
148 bool any_zero
= false;
149 bool all_zero
= true;
151 for (unsigned i
= 0; i
< num_components
; ++i
) {
152 const uint64_t v
= nir_const_value_as_uint(load
->value
[swizzle
[i
]],
155 any_zero
= any_zero
|| (v
== 0);
156 all_zero
= all_zero
&& (v
== 0);
159 assert(any_zero
>= all_zero
);
172 unreachable("Invalid alu source type");
177 #define ASSERT_TABLE_IS_COMMUTATIVE(t) \
179 for (unsigned r = 0; r < ARRAY_SIZE(t); r++) { \
180 for (unsigned c = 0; c < ARRAY_SIZE(t[0]); c++) \
181 assert(t[r][c] == t[c][r]); \
185 #define ASSERT_TABLE_IS_DIAGONAL(t) \
187 for (unsigned r = 0; r < ARRAY_SIZE(t); r++) \
188 assert(t[r][r] == r); \
191 #define ASSERT_TABLE_IS_COMMUTATIVE(t)
192 #define ASSERT_TABLE_IS_DIAGONAL(t)
196 * Short-hand name for use in the tables in analyze_expression. If this name
197 * becomes a problem on some compiler, we can change it to _.
199 #define _______ unknown
202 * Analyze an expression to determine the range of its result
204 * The end result of this analysis is a token that communicates something
205 * about the range of values. There's an implicit grammar that produces
206 * tokens from sequences of literal values, other tokens, and operations.
207 * This function implements this grammar as a recursive-descent parser. Some
208 * (but not all) of the grammar is listed in-line in the function.
210 static struct ssa_result_range
211 analyze_expression(const nir_alu_instr
*instr
, unsigned src
,
212 struct hash_table
*ht
)
214 if (!instr
->src
[src
].src
.is_ssa
)
215 return (struct ssa_result_range
){unknown
, false};
217 if (nir_src_is_const(instr
->src
[src
].src
))
218 return analyze_constant(instr
, src
);
220 if (instr
->src
[src
].src
.ssa
->parent_instr
->type
!= nir_instr_type_alu
)
221 return (struct ssa_result_range
){unknown
, false};
223 const struct nir_alu_instr
*const alu
=
224 nir_instr_as_alu(instr
->src
[src
].src
.ssa
->parent_instr
);
226 struct hash_entry
*he
= _mesa_hash_table_search(ht
, alu
);
228 return unpack_data(he
->data
);
230 struct ssa_result_range r
= {unknown
, false};
232 /* ge_zero: ge_zero + ge_zero
234 * gt_zero: gt_zero + eq_zero
235 * | gt_zero + ge_zero
236 * | eq_zero + gt_zero # Addition is commutative
237 * | ge_zero + gt_zero # Addition is commutative
238 * | gt_zero + gt_zero
241 * le_zero: le_zero + le_zero
243 * lt_zero: lt_zero + eq_zero
244 * | lt_zero + le_zero
245 * | eq_zero + lt_zero # Addition is commutative
246 * | le_zero + lt_zero # Addition is commutative
247 * | lt_zero + lt_zero
250 * ne_zero: eq_zero + ne_zero
251 * | ne_zero + eq_zero # Addition is commutative
254 * eq_zero: eq_zero + eq_zero
257 * All other cases are 'unknown'. The seeming odd entry is (ne_zero,
258 * ne_zero), but that could be (-5, +5) which is not ne_zero.
260 static const enum ssa_ranges fadd_table
[last_range
+ 1][last_range
+ 1] = {
261 /* left\right unknown lt_zero le_zero gt_zero ge_zero ne_zero eq_zero */
262 /* unknown */ { _______
, _______
, _______
, _______
, _______
, _______
, _______
},
263 /* lt_zero */ { _______
, lt_zero
, lt_zero
, _______
, _______
, _______
, lt_zero
},
264 /* le_zero */ { _______
, lt_zero
, le_zero
, _______
, _______
, _______
, le_zero
},
265 /* gt_zero */ { _______
, _______
, _______
, gt_zero
, gt_zero
, _______
, gt_zero
},
266 /* ge_zero */ { _______
, _______
, _______
, gt_zero
, ge_zero
, _______
, ge_zero
},
267 /* ne_zero */ { _______
, _______
, _______
, _______
, _______
, _______
, ne_zero
},
268 /* eq_zero */ { _______
, lt_zero
, le_zero
, gt_zero
, ge_zero
, ne_zero
, eq_zero
},
271 ASSERT_TABLE_IS_COMMUTATIVE(fadd_table
);
273 /* Due to flush-to-zero semanatics of floating-point numbers with very
274 * small mangnitudes, we can never really be sure a result will be
277 * ge_zero: ge_zero * ge_zero
278 * | ge_zero * gt_zero
279 * | ge_zero * eq_zero
280 * | le_zero * lt_zero
281 * | lt_zero * le_zero # Multiplication is commutative
282 * | le_zero * le_zero
283 * | gt_zero * ge_zero # Multiplication is commutative
284 * | eq_zero * ge_zero # Multiplication is commutative
285 * | a * a # Left source == right source
286 * | gt_zero * gt_zero
287 * | lt_zero * lt_zero
290 * le_zero: ge_zero * le_zero
291 * | ge_zero * lt_zero
292 * | lt_zero * ge_zero # Multiplication is commutative
293 * | le_zero * ge_zero # Multiplication is commutative
294 * | le_zero * gt_zero
295 * | lt_zero * gt_zero
296 * | gt_zero * lt_zero # Multiplication is commutative
299 * eq_zero: eq_zero * <any>
300 * <any> * eq_zero # Multiplication is commutative
302 * All other cases are 'unknown'.
304 static const enum ssa_ranges fmul_table
[last_range
+ 1][last_range
+ 1] = {
305 /* left\right unknown lt_zero le_zero gt_zero ge_zero ne_zero eq_zero */
306 /* unknown */ { _______
, _______
, _______
, _______
, _______
, _______
, eq_zero
},
307 /* lt_zero */ { _______
, ge_zero
, ge_zero
, le_zero
, le_zero
, _______
, eq_zero
},
308 /* le_zero */ { _______
, ge_zero
, ge_zero
, le_zero
, le_zero
, _______
, eq_zero
},
309 /* gt_zero */ { _______
, le_zero
, le_zero
, ge_zero
, ge_zero
, _______
, eq_zero
},
310 /* ge_zero */ { _______
, le_zero
, le_zero
, ge_zero
, ge_zero
, _______
, eq_zero
},
311 /* ne_zero */ { _______
, _______
, _______
, _______
, _______
, _______
, eq_zero
},
312 /* eq_zero */ { eq_zero
, eq_zero
, eq_zero
, eq_zero
, eq_zero
, eq_zero
, eq_zero
}
315 ASSERT_TABLE_IS_COMMUTATIVE(fmul_table
);
317 static const enum ssa_ranges fneg_table
[last_range
+ 1] = {
318 /* unknown lt_zero le_zero gt_zero ge_zero ne_zero eq_zero */
319 _______
, gt_zero
, ge_zero
, lt_zero
, le_zero
, ne_zero
, eq_zero
326 r
= (struct ssa_result_range
){ge_zero
, alu
->op
== nir_op_b2f32
};
330 const struct ssa_result_range left
= analyze_expression(alu
, 1, ht
);
331 const struct ssa_result_range right
= analyze_expression(alu
, 2, ht
);
333 /* If either source is a constant load that is not zero, punt. The type
334 * will always be uint regardless of the actual type. We can't even
335 * decide if the value is non-zero because -0.0 is 0x80000000, and that
336 * will (possibly incorrectly) be considered non-zero.
338 /* FINISHME: We could do better, but it would require having the expected
339 * FINISHME: type passed in.
341 if ((nir_src_is_const(alu
->src
[1].src
) && left
.range
!= eq_zero
) ||
342 (nir_src_is_const(alu
->src
[2].src
) && right
.range
!= eq_zero
)) {
343 return (struct ssa_result_range
){unknown
, false};
346 r
.is_integral
= left
.is_integral
&& right
.is_integral
;
348 /* le_zero: bcsel(<any>, le_zero, lt_zero)
349 * | bcsel(<any>, eq_zero, lt_zero)
350 * | bcsel(<any>, le_zero, eq_zero)
351 * | bcsel(<any>, lt_zero, le_zero)
352 * | bcsel(<any>, lt_zero, eq_zero)
353 * | bcsel(<any>, eq_zero, le_zero)
354 * | bcsel(<any>, le_zero, le_zero)
357 * lt_zero: bcsel(<any>, lt_zero, lt_zero)
360 * ge_zero: bcsel(<any>, ge_zero, ge_zero)
361 * | bcsel(<any>, ge_zero, gt_zero)
362 * | bcsel(<any>, ge_zero, eq_zero)
363 * | bcsel(<any>, gt_zero, ge_zero)
364 * | bcsel(<any>, eq_zero, ge_zero)
367 * gt_zero: bcsel(<any>, gt_zero, gt_zero)
370 * ne_zero: bcsel(<any>, ne_zero, gt_zero)
371 * | bcsel(<any>, ne_zero, lt_zero)
372 * | bcsel(<any>, gt_zero, lt_zero)
373 * | bcsel(<any>, gt_zero, ne_zero)
374 * | bcsel(<any>, lt_zero, ne_zero)
375 * | bcsel(<any>, lt_zero, gt_zero)
376 * | bcsel(<any>, ne_zero, ne_zero)
379 * eq_zero: bcsel(<any>, eq_zero, eq_zero)
382 * All other cases are 'unknown'.
384 * The ranges could be tightened if the range of the first source is
385 * known. However, opt_algebraic will (eventually) elminiate the bcsel
386 * if the condition is known.
388 static const enum ssa_ranges table
[last_range
+ 1][last_range
+ 1] = {
389 /* left\right unknown lt_zero le_zero gt_zero ge_zero ne_zero eq_zero */
390 /* unknown */ { _______
, _______
, _______
, _______
, _______
, _______
, _______
},
391 /* lt_zero */ { _______
, lt_zero
, le_zero
, ne_zero
, _______
, ne_zero
, le_zero
},
392 /* le_zero */ { _______
, le_zero
, le_zero
, _______
, _______
, _______
, le_zero
},
393 /* gt_zero */ { _______
, ne_zero
, _______
, gt_zero
, ge_zero
, ne_zero
, ge_zero
},
394 /* ge_zero */ { _______
, _______
, _______
, ge_zero
, ge_zero
, _______
, ge_zero
},
395 /* ne_zero */ { _______
, ne_zero
, _______
, ne_zero
, _______
, ne_zero
, _______
},
396 /* eq_zero */ { _______
, le_zero
, le_zero
, ge_zero
, ge_zero
, _______
, eq_zero
},
399 ASSERT_TABLE_IS_COMMUTATIVE(table
);
400 ASSERT_TABLE_IS_DIAGONAL(table
);
402 r
.range
= table
[left
.range
][right
.range
];
408 r
= analyze_expression(alu
, 0, ht
);
410 r
.is_integral
= true;
412 if (r
.range
== unknown
&& alu
->op
== nir_op_u2f32
)
418 r
= analyze_expression(alu
, 0, ht
);
440 const struct ssa_result_range left
= analyze_expression(alu
, 0, ht
);
441 const struct ssa_result_range right
= analyze_expression(alu
, 1, ht
);
443 r
.is_integral
= left
.is_integral
&& right
.is_integral
;
444 r
.range
= fadd_table
[left
.range
][right
.range
];
449 /* If the parameter might be less than zero, the mathematically result
450 * will be on (0, 1). For sufficiently large magnitude negative
451 * parameters, the result will flush to zero.
453 static const enum ssa_ranges table
[last_range
+ 1] = {
454 /* unknown lt_zero le_zero gt_zero ge_zero ne_zero eq_zero */
455 ge_zero
, ge_zero
, ge_zero
, gt_zero
, gt_zero
, ge_zero
, gt_zero
458 r
= analyze_expression(alu
, 0, ht
);
460 r
.range
= table
[r
.range
];
465 const struct ssa_result_range left
= analyze_expression(alu
, 0, ht
);
466 const struct ssa_result_range right
= analyze_expression(alu
, 1, ht
);
468 r
.is_integral
= left
.is_integral
&& right
.is_integral
;
470 /* gt_zero: fmax(gt_zero, *)
471 * | fmax(*, gt_zero) # Treat fmax as commutative
474 * ge_zero: fmax(ge_zero, ne_zero)
475 * | fmax(ge_zero, lt_zero)
476 * | fmax(ge_zero, le_zero)
477 * | fmax(ge_zero, eq_zero)
478 * | fmax(ne_zero, ge_zero) # Treat fmax as commutative
479 * | fmax(lt_zero, ge_zero) # Treat fmax as commutative
480 * | fmax(le_zero, ge_zero) # Treat fmax as commutative
481 * | fmax(eq_zero, ge_zero) # Treat fmax as commutative
482 * | fmax(ge_zero, ge_zero)
485 * le_zero: fmax(le_zero, lt_zero)
486 * | fmax(lt_zero, le_zero) # Treat fmax as commutative
487 * | fmax(le_zero, le_zero)
490 * lt_zero: fmax(lt_zero, lt_zero)
493 * ne_zero: fmax(ne_zero, lt_zero)
494 * | fmax(lt_zero, ne_zero) # Treat fmax as commutative
495 * | fmax(ne_zero, ne_zero)
498 * eq_zero: fmax(eq_zero, le_zero)
499 * | fmax(eq_zero, lt_zero)
500 * | fmax(le_zero, eq_zero) # Treat fmax as commutative
501 * | fmax(lt_zero, eq_zero) # Treat fmax as commutative
502 * | fmax(eq_zero, eq_zero)
505 * All other cases are 'unknown'.
507 static const enum ssa_ranges table
[last_range
+ 1][last_range
+ 1] = {
508 /* left\right unknown lt_zero le_zero gt_zero ge_zero ne_zero eq_zero */
509 /* unknown */ { _______
, _______
, _______
, gt_zero
, ge_zero
, _______
, _______
},
510 /* lt_zero */ { _______
, lt_zero
, le_zero
, gt_zero
, ge_zero
, ne_zero
, eq_zero
},
511 /* le_zero */ { _______
, le_zero
, le_zero
, gt_zero
, ge_zero
, _______
, eq_zero
},
512 /* gt_zero */ { gt_zero
, gt_zero
, gt_zero
, gt_zero
, gt_zero
, gt_zero
, gt_zero
},
513 /* ge_zero */ { ge_zero
, ge_zero
, ge_zero
, gt_zero
, ge_zero
, ge_zero
, ge_zero
},
514 /* ne_zero */ { _______
, ne_zero
, _______
, gt_zero
, ge_zero
, ne_zero
, _______
},
515 /* eq_zero */ { _______
, eq_zero
, eq_zero
, gt_zero
, ge_zero
, _______
, eq_zero
}
518 /* Treat fmax as commutative. */
519 ASSERT_TABLE_IS_COMMUTATIVE(table
);
520 ASSERT_TABLE_IS_DIAGONAL(table
);
522 r
.range
= table
[left
.range
][right
.range
];
527 const struct ssa_result_range left
= analyze_expression(alu
, 0, ht
);
528 const struct ssa_result_range right
= analyze_expression(alu
, 1, ht
);
530 r
.is_integral
= left
.is_integral
&& right
.is_integral
;
532 /* lt_zero: fmin(lt_zero, *)
533 * | fmin(*, lt_zero) # Treat fmin as commutative
536 * le_zero: fmin(le_zero, ne_zero)
537 * | fmin(le_zero, gt_zero)
538 * | fmin(le_zero, ge_zero)
539 * | fmin(le_zero, eq_zero)
540 * | fmin(ne_zero, le_zero) # Treat fmin as commutative
541 * | fmin(gt_zero, le_zero) # Treat fmin as commutative
542 * | fmin(ge_zero, le_zero) # Treat fmin as commutative
543 * | fmin(eq_zero, le_zero) # Treat fmin as commutative
544 * | fmin(le_zero, le_zero)
547 * ge_zero: fmin(ge_zero, gt_zero)
548 * | fmin(gt_zero, ge_zero) # Treat fmin as commutative
549 * | fmin(ge_zero, ge_zero)
552 * gt_zero: fmin(gt_zero, gt_zero)
555 * ne_zero: fmin(ne_zero, gt_zero)
556 * | fmin(gt_zero, ne_zero) # Treat fmin as commutative
557 * | fmin(ne_zero, ne_zero)
560 * eq_zero: fmin(eq_zero, ge_zero)
561 * | fmin(eq_zero, gt_zero)
562 * | fmin(ge_zero, eq_zero) # Treat fmin as commutative
563 * | fmin(gt_zero, eq_zero) # Treat fmin as commutative
564 * | fmin(eq_zero, eq_zero)
567 * All other cases are 'unknown'.
569 static const enum ssa_ranges table
[last_range
+ 1][last_range
+ 1] = {
570 /* left\right unknown lt_zero le_zero gt_zero ge_zero ne_zero eq_zero */
571 /* unknown */ { _______
, lt_zero
, le_zero
, _______
, _______
, _______
, _______
},
572 /* lt_zero */ { lt_zero
, lt_zero
, lt_zero
, lt_zero
, lt_zero
, lt_zero
, lt_zero
},
573 /* le_zero */ { le_zero
, lt_zero
, le_zero
, le_zero
, le_zero
, le_zero
, le_zero
},
574 /* gt_zero */ { _______
, lt_zero
, le_zero
, gt_zero
, ge_zero
, ne_zero
, eq_zero
},
575 /* ge_zero */ { _______
, lt_zero
, le_zero
, ge_zero
, ge_zero
, _______
, eq_zero
},
576 /* ne_zero */ { _______
, lt_zero
, le_zero
, ne_zero
, _______
, ne_zero
, _______
},
577 /* eq_zero */ { _______
, lt_zero
, le_zero
, eq_zero
, eq_zero
, _______
, eq_zero
}
580 /* Treat fmin as commutative. */
581 ASSERT_TABLE_IS_COMMUTATIVE(table
);
582 ASSERT_TABLE_IS_DIAGONAL(table
);
584 r
.range
= table
[left
.range
][right
.range
];
589 const struct ssa_result_range left
= analyze_expression(alu
, 0, ht
);
590 const struct ssa_result_range right
= analyze_expression(alu
, 1, ht
);
592 r
.is_integral
= left
.is_integral
&& right
.is_integral
;
594 /* x * x => ge_zero */
595 if (left
.range
!= eq_zero
&& nir_alu_srcs_equal(alu
, alu
, 0, 1)) {
596 /* Even if x > 0, the result of x*x can be zero when x is, for
597 * example, a subnormal number.
600 } else if (left
.range
!= eq_zero
&& nir_alu_srcs_negative_equal(alu
, alu
, 0, 1)) {
601 /* -x * x => le_zero. */
604 r
.range
= fmul_table
[left
.range
][right
.range
];
610 r
= (struct ssa_result_range
){analyze_expression(alu
, 0, ht
).range
, false};
614 r
= analyze_expression(alu
, 0, ht
);
618 r
= analyze_expression(alu
, 0, ht
);
620 r
.range
= fneg_table
[r
.range
];
624 r
= analyze_expression(alu
, 0, ht
);
630 r
.is_integral
= true;
634 assert(r
.is_integral
);
637 /* The fsat doesn't add any information in these cases. */
642 /* Since the result must be in [0, 1], the value must be >= 0. */
649 r
= (struct ssa_result_range
){analyze_expression(alu
, 0, ht
).range
, true};
654 r
= (struct ssa_result_range
){ge_zero
, false};
657 case nir_op_ffloor
: {
658 const struct ssa_result_range left
= analyze_expression(alu
, 0, ht
);
660 r
.is_integral
= true;
662 if (left
.is_integral
|| left
.range
== le_zero
|| left
.range
== lt_zero
)
663 r
.range
= left
.range
;
664 else if (left
.range
== ge_zero
|| left
.range
== gt_zero
)
666 else if (left
.range
== ne_zero
)
673 const struct ssa_result_range left
= analyze_expression(alu
, 0, ht
);
675 r
.is_integral
= true;
677 if (left
.is_integral
|| left
.range
== ge_zero
|| left
.range
== gt_zero
)
678 r
.range
= left
.range
;
679 else if (left
.range
== le_zero
|| left
.range
== lt_zero
)
681 else if (left
.range
== ne_zero
)
687 case nir_op_ftrunc
: {
688 const struct ssa_result_range left
= analyze_expression(alu
, 0, ht
);
690 r
.is_integral
= true;
692 if (left
.is_integral
)
693 r
.range
= left
.range
;
694 else if (left
.range
== ge_zero
|| left
.range
== gt_zero
)
696 else if (left
.range
== le_zero
|| left
.range
== lt_zero
)
698 else if (left
.range
== ne_zero
)
714 /* Boolean results are 0 or -1. */
715 r
= (struct ssa_result_range
){le_zero
, false};
719 const struct ssa_result_range first
= analyze_expression(alu
, 0, ht
);
720 const struct ssa_result_range second
= analyze_expression(alu
, 1, ht
);
721 const struct ssa_result_range third
= analyze_expression(alu
, 2, ht
);
723 r
.is_integral
= first
.is_integral
&& second
.is_integral
&&
726 enum ssa_ranges fmul_range
;
728 if (first
.range
!= eq_zero
&& nir_alu_srcs_equal(alu
, alu
, 0, 1)) {
729 /* See handling of nir_op_fmul for explanation of why ge_zero is the
732 fmul_range
= ge_zero
;
733 } else if (first
.range
!= eq_zero
&& nir_alu_srcs_negative_equal(alu
, alu
, 0, 1)) {
734 /* -x * x => le_zero */
735 fmul_range
= le_zero
;
737 fmul_range
= fmul_table
[first
.range
][second
.range
];
739 r
.range
= fadd_table
[fmul_range
][third
.range
];
744 const struct ssa_result_range first
= analyze_expression(alu
, 0, ht
);
745 const struct ssa_result_range second
= analyze_expression(alu
, 1, ht
);
746 const struct ssa_result_range third
= analyze_expression(alu
, 2, ht
);
748 r
.is_integral
= first
.is_integral
&& second
.is_integral
&&
751 /* Decompose the flrp to first + third * (second + -first) */
752 const enum ssa_ranges inner_fadd_range
=
753 fadd_table
[second
.range
][fneg_table
[first
.range
]];
755 const enum ssa_ranges fmul_range
=
756 fmul_table
[third
.range
][inner_fadd_range
];
758 r
.range
= fadd_table
[first
.range
][fmul_range
];
763 r
= (struct ssa_result_range
){unknown
, false};
767 if (r
.range
== eq_zero
)
768 r
.is_integral
= true;
770 _mesa_hash_table_insert(ht
, alu
, pack_data(r
));
776 struct ssa_result_range
777 nir_analyze_range(const nir_alu_instr
*instr
, unsigned src
)
779 struct hash_table
*ht
= _mesa_pointer_hash_table_create(NULL
);
781 const struct ssa_result_range r
= analyze_expression(instr
, src
, ht
);
783 _mesa_hash_table_destroy(ht
, NULL
);