1b8e80941Smrg/*
2b8e80941Smrg * Copyright © 2014 Intel Corporation
3b8e80941Smrg *
4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5b8e80941Smrg * copy of this software and associated documentation files (the "Software"),
6b8e80941Smrg * to deal in the Software without restriction, including without limitation
7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the
9b8e80941Smrg * Software is furnished to do so, subject to the following conditions:
10b8e80941Smrg *
11b8e80941Smrg * The above copyright notice and this permission notice (including the next
12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the
13b8e80941Smrg * Software.
14b8e80941Smrg *
15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21b8e80941Smrg * DEALINGS IN THE SOFTWARE.
22b8e80941Smrg */
23b8e80941Smrg
24b8e80941Smrg/**
25b8e80941Smrg * \file opt_minmax.cpp
26b8e80941Smrg *
27b8e80941Smrg * Drop operands from an expression tree of only min/max operations if they
28b8e80941Smrg * can be proven to not contribute to the final result.
29b8e80941Smrg *
30b8e80941Smrg * The algorithm is similar to alpha-beta pruning on a minmax search.
31b8e80941Smrg */
32b8e80941Smrg
33b8e80941Smrg#include "ir.h"
34b8e80941Smrg#include "ir_visitor.h"
35b8e80941Smrg#include "ir_rvalue_visitor.h"
36b8e80941Smrg#include "ir_optimization.h"
37b8e80941Smrg#include "ir_builder.h"
38b8e80941Smrg#include "program/prog_instruction.h"
39b8e80941Smrg#include "compiler/glsl_types.h"
40b8e80941Smrg#include "main/macros.h"
41b8e80941Smrg
42b8e80941Smrgusing namespace ir_builder;
43b8e80941Smrg
44b8e80941Smrgnamespace {
45b8e80941Smrg
46b8e80941Smrgenum compare_components_result {
47b8e80941Smrg   LESS,
48b8e80941Smrg   LESS_OR_EQUAL,
49b8e80941Smrg   EQUAL,
50b8e80941Smrg   GREATER_OR_EQUAL,
51b8e80941Smrg   GREATER,
52b8e80941Smrg   MIXED
53b8e80941Smrg};
54b8e80941Smrg
55b8e80941Smrgclass minmax_range {
56b8e80941Smrgpublic:
57b8e80941Smrg   minmax_range(ir_constant *low = NULL, ir_constant *high = NULL)
58b8e80941Smrg   {
59b8e80941Smrg      this->low = low;
60b8e80941Smrg      this->high = high;
61b8e80941Smrg   }
62b8e80941Smrg
63b8e80941Smrg   /* low is the lower limit of the range, high is the higher limit. NULL on
64b8e80941Smrg    * low means negative infinity (unlimited) and on high positive infinity
65b8e80941Smrg    * (unlimited). Because of the two interpretations of the value NULL,
66b8e80941Smrg    * arbitrary comparison between ir_constants is impossible.
67b8e80941Smrg    */
68b8e80941Smrg   ir_constant *low;
69b8e80941Smrg   ir_constant *high;
70b8e80941Smrg};
71b8e80941Smrg
72b8e80941Smrgclass ir_minmax_visitor : public ir_rvalue_enter_visitor {
73b8e80941Smrgpublic:
74b8e80941Smrg   ir_minmax_visitor()
75b8e80941Smrg      : progress(false)
76b8e80941Smrg   {
77b8e80941Smrg   }
78b8e80941Smrg
79b8e80941Smrg   ir_rvalue *prune_expression(ir_expression *expr, minmax_range baserange);
80b8e80941Smrg
81b8e80941Smrg   void handle_rvalue(ir_rvalue **rvalue);
82b8e80941Smrg
83b8e80941Smrg   bool progress;
84b8e80941Smrg};
85b8e80941Smrg
86b8e80941Smrg/*
87b8e80941Smrg * Returns LESS if all vector components of `a' are strictly lower than of `b',
88b8e80941Smrg * GREATER if all vector components of `a' are strictly greater than of `b',
89b8e80941Smrg * MIXED if some vector components of `a' are strictly lower than of `b' while
90b8e80941Smrg * others are strictly greater, or EQUAL otherwise.
91b8e80941Smrg */
92b8e80941Smrgstatic enum compare_components_result
93b8e80941Smrgcompare_components(ir_constant *a, ir_constant *b)
94b8e80941Smrg{
95b8e80941Smrg   assert(a != NULL);
96b8e80941Smrg   assert(b != NULL);
97b8e80941Smrg
98b8e80941Smrg   assert(a->type->base_type == b->type->base_type);
99b8e80941Smrg
100b8e80941Smrg   unsigned a_inc = a->type->is_scalar() ? 0 : 1;
101b8e80941Smrg   unsigned b_inc = b->type->is_scalar() ? 0 : 1;
102b8e80941Smrg   unsigned components = MAX2(a->type->components(), b->type->components());
103b8e80941Smrg
104b8e80941Smrg   bool foundless = false;
105b8e80941Smrg   bool foundgreater = false;
106b8e80941Smrg   bool foundequal = false;
107b8e80941Smrg
108b8e80941Smrg   for (unsigned i = 0, c0 = 0, c1 = 0;
109b8e80941Smrg        i < components;
110b8e80941Smrg        c0 += a_inc, c1 += b_inc, ++i) {
111b8e80941Smrg      switch (a->type->base_type) {
112b8e80941Smrg      case GLSL_TYPE_UINT:
113b8e80941Smrg         if (a->value.u[c0] < b->value.u[c1])
114b8e80941Smrg            foundless = true;
115b8e80941Smrg         else if (a->value.u[c0] > b->value.u[c1])
116b8e80941Smrg            foundgreater = true;
117b8e80941Smrg         else
118b8e80941Smrg            foundequal = true;
119b8e80941Smrg         break;
120b8e80941Smrg      case GLSL_TYPE_INT:
121b8e80941Smrg         if (a->value.i[c0] < b->value.i[c1])
122b8e80941Smrg            foundless = true;
123b8e80941Smrg         else if (a->value.i[c0] > b->value.i[c1])
124b8e80941Smrg            foundgreater = true;
125b8e80941Smrg         else
126b8e80941Smrg            foundequal = true;
127b8e80941Smrg         break;
128b8e80941Smrg      case GLSL_TYPE_FLOAT:
129b8e80941Smrg         if (a->value.f[c0] < b->value.f[c1])
130b8e80941Smrg            foundless = true;
131b8e80941Smrg         else if (a->value.f[c0] > b->value.f[c1])
132b8e80941Smrg            foundgreater = true;
133b8e80941Smrg         else
134b8e80941Smrg            foundequal = true;
135b8e80941Smrg         break;
136b8e80941Smrg      case GLSL_TYPE_DOUBLE:
137b8e80941Smrg         if (a->value.d[c0] < b->value.d[c1])
138b8e80941Smrg            foundless = true;
139b8e80941Smrg         else if (a->value.d[c0] > b->value.d[c1])
140b8e80941Smrg            foundgreater = true;
141b8e80941Smrg         else
142b8e80941Smrg            foundequal = true;
143b8e80941Smrg         break;
144b8e80941Smrg      default:
145b8e80941Smrg         unreachable("not reached");
146b8e80941Smrg      }
147b8e80941Smrg   }
148b8e80941Smrg
149b8e80941Smrg   if (foundless && foundgreater) {
150b8e80941Smrg      /* Some components are strictly lower, others are strictly greater */
151b8e80941Smrg      return MIXED;
152b8e80941Smrg   }
153b8e80941Smrg
154b8e80941Smrg   if (foundequal) {
155b8e80941Smrg       /* It is not mixed, but it is not strictly lower or greater */
156b8e80941Smrg      if (foundless)
157b8e80941Smrg         return LESS_OR_EQUAL;
158b8e80941Smrg      if (foundgreater)
159b8e80941Smrg         return GREATER_OR_EQUAL;
160b8e80941Smrg      return EQUAL;
161b8e80941Smrg   }
162b8e80941Smrg
163b8e80941Smrg   /* All components are strictly lower or strictly greater */
164b8e80941Smrg   return foundless ? LESS : GREATER;
165b8e80941Smrg}
166b8e80941Smrg
167b8e80941Smrgstatic ir_constant *
168b8e80941Smrgcombine_constant(bool ismin, ir_constant *a, ir_constant *b)
169b8e80941Smrg{
170b8e80941Smrg   void *mem_ctx = ralloc_parent(a);
171b8e80941Smrg   ir_constant *c = a->clone(mem_ctx, NULL);
172b8e80941Smrg   for (unsigned i = 0; i < c->type->components(); i++) {
173b8e80941Smrg      switch (c->type->base_type) {
174b8e80941Smrg      case GLSL_TYPE_UINT:
175b8e80941Smrg         if ((ismin && b->value.u[i] < c->value.u[i]) ||
176b8e80941Smrg             (!ismin && b->value.u[i] > c->value.u[i]))
177b8e80941Smrg            c->value.u[i] = b->value.u[i];
178b8e80941Smrg         break;
179b8e80941Smrg      case GLSL_TYPE_INT:
180b8e80941Smrg         if ((ismin && b->value.i[i] < c->value.i[i]) ||
181b8e80941Smrg             (!ismin && b->value.i[i] > c->value.i[i]))
182b8e80941Smrg            c->value.i[i] = b->value.i[i];
183b8e80941Smrg         break;
184b8e80941Smrg      case GLSL_TYPE_FLOAT:
185b8e80941Smrg         if ((ismin && b->value.f[i] < c->value.f[i]) ||
186b8e80941Smrg             (!ismin && b->value.f[i] > c->value.f[i]))
187b8e80941Smrg            c->value.f[i] = b->value.f[i];
188b8e80941Smrg         break;
189b8e80941Smrg      case GLSL_TYPE_DOUBLE:
190b8e80941Smrg         if ((ismin && b->value.d[i] < c->value.d[i]) ||
191b8e80941Smrg             (!ismin && b->value.d[i] > c->value.d[i]))
192b8e80941Smrg            c->value.d[i] = b->value.d[i];
193b8e80941Smrg         break;
194b8e80941Smrg      default:
195b8e80941Smrg         assert(!"not reached");
196b8e80941Smrg      }
197b8e80941Smrg   }
198b8e80941Smrg   return c;
199b8e80941Smrg}
200b8e80941Smrg
201b8e80941Smrgstatic ir_constant *
202b8e80941Smrgsmaller_constant(ir_constant *a, ir_constant *b)
203b8e80941Smrg{
204b8e80941Smrg   assert(a != NULL);
205b8e80941Smrg   assert(b != NULL);
206b8e80941Smrg
207b8e80941Smrg   enum compare_components_result ret = compare_components(a, b);
208b8e80941Smrg   if (ret == MIXED)
209b8e80941Smrg      return combine_constant(true, a, b);
210b8e80941Smrg   else if (ret < EQUAL)
211b8e80941Smrg      return a;
212b8e80941Smrg   else
213b8e80941Smrg      return b;
214b8e80941Smrg}
215b8e80941Smrg
216b8e80941Smrgstatic ir_constant *
217b8e80941Smrglarger_constant(ir_constant *a, ir_constant *b)
218b8e80941Smrg{
219b8e80941Smrg   assert(a != NULL);
220b8e80941Smrg   assert(b != NULL);
221b8e80941Smrg
222b8e80941Smrg   enum compare_components_result ret = compare_components(a, b);
223b8e80941Smrg   if (ret == MIXED)
224b8e80941Smrg      return combine_constant(false, a, b);
225b8e80941Smrg   else if (ret < EQUAL)
226b8e80941Smrg      return b;
227b8e80941Smrg   else
228b8e80941Smrg      return a;
229b8e80941Smrg}
230b8e80941Smrg
231b8e80941Smrg/* Combines two ranges by doing an element-wise min() / max() depending on the
232b8e80941Smrg * operation.
233b8e80941Smrg */
234b8e80941Smrgstatic minmax_range
235b8e80941Smrgcombine_range(minmax_range r0, minmax_range r1, bool ismin)
236b8e80941Smrg{
237b8e80941Smrg   minmax_range ret;
238b8e80941Smrg
239b8e80941Smrg   if (!r0.low) {
240b8e80941Smrg      ret.low = ismin ? r0.low : r1.low;
241b8e80941Smrg   } else if (!r1.low) {
242b8e80941Smrg      ret.low = ismin ? r1.low : r0.low;
243b8e80941Smrg   } else {
244b8e80941Smrg      ret.low = ismin ? smaller_constant(r0.low, r1.low) :
245b8e80941Smrg         larger_constant(r0.low, r1.low);
246b8e80941Smrg   }
247b8e80941Smrg
248b8e80941Smrg   if (!r0.high) {
249b8e80941Smrg      ret.high = ismin ? r1.high : r0.high;
250b8e80941Smrg   } else if (!r1.high) {
251b8e80941Smrg      ret.high = ismin ? r0.high : r1.high;
252b8e80941Smrg   } else {
253b8e80941Smrg      ret.high = ismin ? smaller_constant(r0.high, r1.high) :
254b8e80941Smrg         larger_constant(r0.high, r1.high);
255b8e80941Smrg   }
256b8e80941Smrg
257b8e80941Smrg   return ret;
258b8e80941Smrg}
259b8e80941Smrg
260b8e80941Smrg/* Returns a range so that lower limit is the larger of the two lower limits,
261b8e80941Smrg * and higher limit is the smaller of the two higher limits.
262b8e80941Smrg */
263b8e80941Smrgstatic minmax_range
264b8e80941Smrgrange_intersection(minmax_range r0, minmax_range r1)
265b8e80941Smrg{
266b8e80941Smrg   minmax_range ret;
267b8e80941Smrg
268b8e80941Smrg   if (!r0.low)
269b8e80941Smrg      ret.low = r1.low;
270b8e80941Smrg   else if (!r1.low)
271b8e80941Smrg      ret.low = r0.low;
272b8e80941Smrg   else
273b8e80941Smrg      ret.low = larger_constant(r0.low, r1.low);
274b8e80941Smrg
275b8e80941Smrg   if (!r0.high)
276b8e80941Smrg      ret.high = r1.high;
277b8e80941Smrg   else if (!r1.high)
278b8e80941Smrg      ret.high = r0.high;
279b8e80941Smrg   else
280b8e80941Smrg      ret.high = smaller_constant(r0.high, r1.high);
281b8e80941Smrg
282b8e80941Smrg   return ret;
283b8e80941Smrg}
284b8e80941Smrg
285b8e80941Smrgstatic minmax_range
286b8e80941Smrgget_range(ir_rvalue *rval)
287b8e80941Smrg{
288b8e80941Smrg   ir_expression *expr = rval->as_expression();
289b8e80941Smrg   if (expr && (expr->operation == ir_binop_min ||
290b8e80941Smrg                expr->operation == ir_binop_max)) {
291b8e80941Smrg      minmax_range r0 = get_range(expr->operands[0]);
292b8e80941Smrg      minmax_range r1 = get_range(expr->operands[1]);
293b8e80941Smrg      return combine_range(r0, r1, expr->operation == ir_binop_min);
294b8e80941Smrg   }
295b8e80941Smrg
296b8e80941Smrg   ir_constant *c = rval->as_constant();
297b8e80941Smrg   if (c) {
298b8e80941Smrg      return minmax_range(c, c);
299b8e80941Smrg   }
300b8e80941Smrg
301b8e80941Smrg   return minmax_range();
302b8e80941Smrg}
303b8e80941Smrg
304b8e80941Smrg/**
305b8e80941Smrg * Prunes a min/max expression considering the base range of the parent
306b8e80941Smrg * min/max expression.
307b8e80941Smrg *
308b8e80941Smrg * @param baserange the range that the parents of this min/max expression
309b8e80941Smrg * in the min/max tree will clamp its value to.
310b8e80941Smrg */
311b8e80941Smrgir_rvalue *
312b8e80941Smrgir_minmax_visitor::prune_expression(ir_expression *expr, minmax_range baserange)
313b8e80941Smrg{
314b8e80941Smrg   assert(expr->operation == ir_binop_min ||
315b8e80941Smrg          expr->operation == ir_binop_max);
316b8e80941Smrg
317b8e80941Smrg   bool ismin = expr->operation == ir_binop_min;
318b8e80941Smrg   minmax_range limits[2];
319b8e80941Smrg
320b8e80941Smrg   /* Recurse to get the ranges for each of the subtrees of this
321b8e80941Smrg    * expression. We need to do this as a separate step because we need to
322b8e80941Smrg    * know the ranges of each of the subtrees before we prune either one.
323b8e80941Smrg    * Consider something like this:
324b8e80941Smrg    *
325b8e80941Smrg    *        max
326b8e80941Smrg    *     /       \
327b8e80941Smrg    *    max     max
328b8e80941Smrg    *   /   \   /   \
329b8e80941Smrg    *  3    a   b    2
330b8e80941Smrg    *
331b8e80941Smrg    * We would like to prune away the max on the bottom-right, but to do so
332b8e80941Smrg    * we need to know the range of the expression on the left beforehand,
333b8e80941Smrg    * and there's no guarantee that we will visit either subtree in a
334b8e80941Smrg    * particular order.
335b8e80941Smrg    */
336b8e80941Smrg   for (unsigned i = 0; i < 2; ++i)
337b8e80941Smrg      limits[i] = get_range(expr->operands[i]);
338b8e80941Smrg
339b8e80941Smrg   for (unsigned i = 0; i < 2; ++i) {
340b8e80941Smrg      bool is_redundant = false;
341b8e80941Smrg
342b8e80941Smrg      enum compare_components_result cr = LESS;
343b8e80941Smrg      if (ismin) {
344b8e80941Smrg         /* If this operand will always be greater than the other one, it's
345b8e80941Smrg          * redundant.
346b8e80941Smrg          */
347b8e80941Smrg         if (limits[i].low && limits[1 - i].high) {
348b8e80941Smrg               cr = compare_components(limits[i].low, limits[1 - i].high);
349b8e80941Smrg            if (cr >= EQUAL && cr != MIXED)
350b8e80941Smrg               is_redundant = true;
351b8e80941Smrg         }
352b8e80941Smrg         /* If this operand is always greater than baserange, then even if
353b8e80941Smrg          * it's smaller than the other one it'll get clamped, so it's
354b8e80941Smrg          * redundant.
355b8e80941Smrg          */
356b8e80941Smrg         if (!is_redundant && limits[i].low && baserange.high) {
357b8e80941Smrg            cr = compare_components(limits[i].low, baserange.high);
358b8e80941Smrg            if (cr > EQUAL && cr != MIXED)
359b8e80941Smrg               is_redundant = true;
360b8e80941Smrg         }
361b8e80941Smrg      } else {
362b8e80941Smrg         /* If this operand will always be lower than the other one, it's
363b8e80941Smrg          * redundant.
364b8e80941Smrg          */
365b8e80941Smrg         if (limits[i].high && limits[1 - i].low) {
366b8e80941Smrg            cr = compare_components(limits[i].high, limits[1 - i].low);
367b8e80941Smrg            if (cr <= EQUAL)
368b8e80941Smrg               is_redundant = true;
369b8e80941Smrg         }
370b8e80941Smrg         /* If this operand is always lower than baserange, then even if
371b8e80941Smrg          * it's greater than the other one it'll get clamped, so it's
372b8e80941Smrg          * redundant.
373b8e80941Smrg          */
374b8e80941Smrg         if (!is_redundant && limits[i].high && baserange.low) {
375b8e80941Smrg            cr = compare_components(limits[i].high, baserange.low);
376b8e80941Smrg            if (cr < EQUAL)
377b8e80941Smrg               is_redundant = true;
378b8e80941Smrg         }
379b8e80941Smrg      }
380b8e80941Smrg
381b8e80941Smrg      if (is_redundant) {
382b8e80941Smrg         progress = true;
383b8e80941Smrg
384b8e80941Smrg         /* Recurse if necessary. */
385b8e80941Smrg         ir_expression *op_expr = expr->operands[1 - i]->as_expression();
386b8e80941Smrg         if (op_expr && (op_expr->operation == ir_binop_min ||
387b8e80941Smrg                         op_expr->operation == ir_binop_max)) {
388b8e80941Smrg            return prune_expression(op_expr, baserange);
389b8e80941Smrg         }
390b8e80941Smrg
391b8e80941Smrg         return expr->operands[1 - i];
392b8e80941Smrg      } else if (cr == MIXED) {
393b8e80941Smrg         /* If we have mixed vector operands, we can try to resolve the minmax
394b8e80941Smrg          * expression by doing a component-wise minmax:
395b8e80941Smrg          *
396b8e80941Smrg          *             min                          min
397b8e80941Smrg          *           /    \                       /    \
398b8e80941Smrg          *         min     a       ===>        [1,1]    a
399b8e80941Smrg          *       /    \
400b8e80941Smrg          *    [1,3]   [3,1]
401b8e80941Smrg          *
402b8e80941Smrg          */
403b8e80941Smrg         ir_constant *a = expr->operands[0]->as_constant();
404b8e80941Smrg         ir_constant *b = expr->operands[1]->as_constant();
405b8e80941Smrg         if (a && b)
406b8e80941Smrg            return combine_constant(ismin, a, b);
407b8e80941Smrg      }
408b8e80941Smrg   }
409b8e80941Smrg
410b8e80941Smrg   /* Now recurse to operands giving them the proper baserange. The baserange
411b8e80941Smrg    * to pass is the intersection of our baserange and the other operand's
412b8e80941Smrg    * limit with one of the ranges unlimited. If we can't compute a valid
413b8e80941Smrg    * intersection, we use the current baserange.
414b8e80941Smrg    */
415b8e80941Smrg   for (unsigned i = 0; i < 2; ++i) {
416b8e80941Smrg      ir_expression *op_expr = expr->operands[i]->as_expression();
417b8e80941Smrg      if (op_expr && (op_expr->operation == ir_binop_min ||
418b8e80941Smrg                      op_expr->operation == ir_binop_max)) {
419b8e80941Smrg         /* We can only compute a new baserange for this operand if we managed
420b8e80941Smrg          * to compute a valid range for the other operand.
421b8e80941Smrg          */
422b8e80941Smrg         if (ismin)
423b8e80941Smrg            limits[1 - i].low = NULL;
424b8e80941Smrg         else
425b8e80941Smrg            limits[1 - i].high = NULL;
426b8e80941Smrg         minmax_range base = range_intersection(limits[1 - i], baserange);
427b8e80941Smrg         expr->operands[i] = prune_expression(op_expr, base);
428b8e80941Smrg      }
429b8e80941Smrg   }
430b8e80941Smrg
431b8e80941Smrg   /* If we got here we could not discard any of the operands of the minmax
432b8e80941Smrg    * expression, but we can still try to resolve the expression if both
433b8e80941Smrg    * operands are constant. We do this after the loop above, to make sure
434b8e80941Smrg    * that if our operands are minmax expressions we have tried to prune them
435b8e80941Smrg    * first (hopefully reducing them to constants).
436b8e80941Smrg    */
437b8e80941Smrg   ir_constant *a = expr->operands[0]->as_constant();
438b8e80941Smrg   ir_constant *b = expr->operands[1]->as_constant();
439b8e80941Smrg   if (a && b)
440b8e80941Smrg      return combine_constant(ismin, a, b);
441b8e80941Smrg
442b8e80941Smrg   return expr;
443b8e80941Smrg}
444b8e80941Smrg
445b8e80941Smrgstatic ir_rvalue *
446b8e80941Smrgswizzle_if_required(ir_expression *expr, ir_rvalue *rval)
447b8e80941Smrg{
448b8e80941Smrg   if (expr->type->is_vector() && rval->type->is_scalar()) {
449b8e80941Smrg      return swizzle(rval, SWIZZLE_XXXX, expr->type->vector_elements);
450b8e80941Smrg   } else {
451b8e80941Smrg      return rval;
452b8e80941Smrg   }
453b8e80941Smrg}
454b8e80941Smrg
455b8e80941Smrgvoid
456b8e80941Smrgir_minmax_visitor::handle_rvalue(ir_rvalue **rvalue)
457b8e80941Smrg{
458b8e80941Smrg   if (!*rvalue)
459b8e80941Smrg      return;
460b8e80941Smrg
461b8e80941Smrg   ir_expression *expr = (*rvalue)->as_expression();
462b8e80941Smrg   if (!expr || (expr->operation != ir_binop_min &&
463b8e80941Smrg                 expr->operation != ir_binop_max))
464b8e80941Smrg      return;
465b8e80941Smrg
466b8e80941Smrg   ir_rvalue *new_rvalue = prune_expression(expr, minmax_range());
467b8e80941Smrg   if (new_rvalue == *rvalue)
468b8e80941Smrg      return;
469b8e80941Smrg
470b8e80941Smrg   /* If the expression type is a vector and the optimization leaves a scalar
471b8e80941Smrg    * as the result, we need to turn it into a vector.
472b8e80941Smrg    */
473b8e80941Smrg   *rvalue = swizzle_if_required(expr, new_rvalue);
474b8e80941Smrg
475b8e80941Smrg   progress = true;
476b8e80941Smrg}
477b8e80941Smrg
478b8e80941Smrg}
479b8e80941Smrg
480b8e80941Smrgbool
481b8e80941Smrgdo_minmax_prune(exec_list *instructions)
482b8e80941Smrg{
483b8e80941Smrg   ir_minmax_visitor v;
484b8e80941Smrg
485b8e80941Smrg   visit_list_elements(&v, instructions);
486b8e80941Smrg
487b8e80941Smrg   return v.progress;
488b8e80941Smrg}
489