egl: Add Haiku code and support
[mesa.git] / src / glsl / opt_algebraic.cpp
1 /*
2 * Copyright © 2010 Intel Corporation
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
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 /**
25 * \file opt_algebraic.cpp
26 *
27 * Takes advantage of association, commutivity, and other algebraic
28 * properties to simplify expressions.
29 */
30
31 #include "ir.h"
32 #include "ir_visitor.h"
33 #include "ir_rvalue_visitor.h"
34 #include "ir_optimization.h"
35 #include "ir_builder.h"
36 #include "glsl_types.h"
37
38 using namespace ir_builder;
39
40 namespace {
41
42 /**
43 * Visitor class for replacing expressions with ir_constant values.
44 */
45
46 class ir_algebraic_visitor : public ir_rvalue_visitor {
47 public:
48 ir_algebraic_visitor(bool native_integers,
49 const struct gl_shader_compiler_options *options)
50 : options(options)
51 {
52 this->progress = false;
53 this->mem_ctx = NULL;
54 this->native_integers = native_integers;
55 }
56
57 virtual ~ir_algebraic_visitor()
58 {
59 }
60
61 ir_rvalue *handle_expression(ir_expression *ir);
62 void handle_rvalue(ir_rvalue **rvalue);
63 bool reassociate_constant(ir_expression *ir1,
64 int const_index,
65 ir_constant *constant,
66 ir_expression *ir2);
67 void reassociate_operands(ir_expression *ir1,
68 int op1,
69 ir_expression *ir2,
70 int op2);
71 ir_rvalue *swizzle_if_required(ir_expression *expr,
72 ir_rvalue *operand);
73
74 const struct gl_shader_compiler_options *options;
75 void *mem_ctx;
76
77 bool native_integers;
78 bool progress;
79 };
80
81 } /* unnamed namespace */
82
83 static inline bool
84 is_vec_zero(ir_constant *ir)
85 {
86 return (ir == NULL) ? false : ir->is_zero();
87 }
88
89 static inline bool
90 is_vec_one(ir_constant *ir)
91 {
92 return (ir == NULL) ? false : ir->is_one();
93 }
94
95 static inline bool
96 is_vec_two(ir_constant *ir)
97 {
98 return (ir == NULL) ? false : ir->is_value(2.0, 2);
99 }
100
101 static inline bool
102 is_vec_negative_one(ir_constant *ir)
103 {
104 return (ir == NULL) ? false : ir->is_negative_one();
105 }
106
107 static inline bool
108 is_valid_vec_const(ir_constant *ir)
109 {
110 if (ir == NULL)
111 return false;
112
113 if (!ir->type->is_scalar() && !ir->type->is_vector())
114 return false;
115
116 return true;
117 }
118
119 static inline bool
120 is_less_than_one(ir_constant *ir)
121 {
122 if (!is_valid_vec_const(ir))
123 return false;
124
125 unsigned component = 0;
126 for (int c = 0; c < ir->type->vector_elements; c++) {
127 if (ir->get_float_component(c) < 1.0f)
128 component++;
129 }
130
131 return (component == ir->type->vector_elements);
132 }
133
134 static inline bool
135 is_greater_than_zero(ir_constant *ir)
136 {
137 if (!is_valid_vec_const(ir))
138 return false;
139
140 unsigned component = 0;
141 for (int c = 0; c < ir->type->vector_elements; c++) {
142 if (ir->get_float_component(c) > 0.0f)
143 component++;
144 }
145
146 return (component == ir->type->vector_elements);
147 }
148
149 static void
150 update_type(ir_expression *ir)
151 {
152 if (ir->operands[0]->type->is_vector())
153 ir->type = ir->operands[0]->type;
154 else
155 ir->type = ir->operands[1]->type;
156 }
157
158 /* Recognize (v.x + v.y) + (v.z + v.w) as dot(v, 1.0) */
159 static ir_expression *
160 try_replace_with_dot(ir_expression *expr0, ir_expression *expr1, void *mem_ctx)
161 {
162 if (expr0 && expr0->operation == ir_binop_add &&
163 expr0->type->is_float() &&
164 expr1 && expr1->operation == ir_binop_add &&
165 expr1->type->is_float()) {
166 ir_swizzle *x = expr0->operands[0]->as_swizzle();
167 ir_swizzle *y = expr0->operands[1]->as_swizzle();
168 ir_swizzle *z = expr1->operands[0]->as_swizzle();
169 ir_swizzle *w = expr1->operands[1]->as_swizzle();
170
171 if (!x || x->mask.num_components != 1 ||
172 !y || y->mask.num_components != 1 ||
173 !z || z->mask.num_components != 1 ||
174 !w || w->mask.num_components != 1) {
175 return NULL;
176 }
177
178 bool swiz_seen[4] = {false, false, false, false};
179 swiz_seen[x->mask.x] = true;
180 swiz_seen[y->mask.x] = true;
181 swiz_seen[z->mask.x] = true;
182 swiz_seen[w->mask.x] = true;
183
184 if (!swiz_seen[0] || !swiz_seen[1] ||
185 !swiz_seen[2] || !swiz_seen[3]) {
186 return NULL;
187 }
188
189 if (x->val->equals(y->val) &&
190 x->val->equals(z->val) &&
191 x->val->equals(w->val)) {
192 return dot(x->val, new(mem_ctx) ir_constant(1.0f, 4));
193 }
194 }
195 return NULL;
196 }
197
198 void
199 ir_algebraic_visitor::reassociate_operands(ir_expression *ir1,
200 int op1,
201 ir_expression *ir2,
202 int op2)
203 {
204 ir_rvalue *temp = ir2->operands[op2];
205 ir2->operands[op2] = ir1->operands[op1];
206 ir1->operands[op1] = temp;
207
208 /* Update the type of ir2. The type of ir1 won't have changed --
209 * base types matched, and at least one of the operands of the 2
210 * binops is still a vector if any of them were.
211 */
212 update_type(ir2);
213
214 this->progress = true;
215 }
216
217 /**
218 * Reassociates a constant down a tree of adds or multiplies.
219 *
220 * Consider (2 * (a * (b * 0.5))). We want to send up with a * b.
221 */
222 bool
223 ir_algebraic_visitor::reassociate_constant(ir_expression *ir1, int const_index,
224 ir_constant *constant,
225 ir_expression *ir2)
226 {
227 if (!ir2 || ir1->operation != ir2->operation)
228 return false;
229
230 /* Don't want to even think about matrices. */
231 if (ir1->operands[0]->type->is_matrix() ||
232 ir1->operands[1]->type->is_matrix() ||
233 ir2->operands[0]->type->is_matrix() ||
234 ir2->operands[1]->type->is_matrix())
235 return false;
236
237 ir_constant *ir2_const[2];
238 ir2_const[0] = ir2->operands[0]->constant_expression_value();
239 ir2_const[1] = ir2->operands[1]->constant_expression_value();
240
241 if (ir2_const[0] && ir2_const[1])
242 return false;
243
244 if (ir2_const[0]) {
245 reassociate_operands(ir1, const_index, ir2, 1);
246 return true;
247 } else if (ir2_const[1]) {
248 reassociate_operands(ir1, const_index, ir2, 0);
249 return true;
250 }
251
252 if (reassociate_constant(ir1, const_index, constant,
253 ir2->operands[0]->as_expression())) {
254 update_type(ir2);
255 return true;
256 }
257
258 if (reassociate_constant(ir1, const_index, constant,
259 ir2->operands[1]->as_expression())) {
260 update_type(ir2);
261 return true;
262 }
263
264 return false;
265 }
266
267 /* When eliminating an expression and just returning one of its operands,
268 * we may need to swizzle that operand out to a vector if the expression was
269 * vector type.
270 */
271 ir_rvalue *
272 ir_algebraic_visitor::swizzle_if_required(ir_expression *expr,
273 ir_rvalue *operand)
274 {
275 if (expr->type->is_vector() && operand->type->is_scalar()) {
276 return new(mem_ctx) ir_swizzle(operand, 0, 0, 0, 0,
277 expr->type->vector_elements);
278 } else
279 return operand;
280 }
281
282 ir_rvalue *
283 ir_algebraic_visitor::handle_expression(ir_expression *ir)
284 {
285 ir_constant *op_const[4] = {NULL, NULL, NULL, NULL};
286 ir_expression *op_expr[4] = {NULL, NULL, NULL, NULL};
287 unsigned int i;
288
289 assert(ir->get_num_operands() <= 4);
290 for (i = 0; i < ir->get_num_operands(); i++) {
291 if (ir->operands[i]->type->is_matrix())
292 return ir;
293
294 op_const[i] = ir->operands[i]->constant_expression_value();
295 op_expr[i] = ir->operands[i]->as_expression();
296 }
297
298 if (this->mem_ctx == NULL)
299 this->mem_ctx = ralloc_parent(ir);
300
301 switch (ir->operation) {
302 case ir_unop_bit_not:
303 if (op_expr[0] && op_expr[0]->operation == ir_unop_bit_not)
304 return op_expr[0]->operands[0];
305 break;
306
307 case ir_unop_abs:
308 if (op_expr[0] == NULL)
309 break;
310
311 switch (op_expr[0]->operation) {
312 case ir_unop_abs:
313 case ir_unop_neg:
314 return abs(op_expr[0]->operands[0]);
315 default:
316 break;
317 }
318 break;
319
320 case ir_unop_neg:
321 if (op_expr[0] == NULL)
322 break;
323
324 if (op_expr[0]->operation == ir_unop_neg) {
325 return op_expr[0]->operands[0];
326 }
327 break;
328
329 case ir_unop_exp:
330 if (op_expr[0] == NULL)
331 break;
332
333 if (op_expr[0]->operation == ir_unop_log) {
334 return op_expr[0]->operands[0];
335 }
336 break;
337
338 case ir_unop_log:
339 if (op_expr[0] == NULL)
340 break;
341
342 if (op_expr[0]->operation == ir_unop_exp) {
343 return op_expr[0]->operands[0];
344 }
345 break;
346
347 case ir_unop_exp2:
348 if (op_expr[0] == NULL)
349 break;
350
351 if (op_expr[0]->operation == ir_unop_log2) {
352 return op_expr[0]->operands[0];
353 }
354
355 if (!options->EmitNoPow && op_expr[0]->operation == ir_binop_mul) {
356 for (int log2_pos = 0; log2_pos < 2; log2_pos++) {
357 ir_expression *log2_expr =
358 op_expr[0]->operands[log2_pos]->as_expression();
359
360 if (log2_expr && log2_expr->operation == ir_unop_log2) {
361 return new(mem_ctx) ir_expression(ir_binop_pow,
362 ir->type,
363 log2_expr->operands[0],
364 op_expr[0]->operands[1 - log2_pos]);
365 }
366 }
367 }
368 break;
369
370 case ir_unop_log2:
371 if (op_expr[0] == NULL)
372 break;
373
374 if (op_expr[0]->operation == ir_unop_exp2) {
375 return op_expr[0]->operands[0];
376 }
377 break;
378
379 case ir_unop_logic_not: {
380 enum ir_expression_operation new_op = ir_unop_logic_not;
381
382 if (op_expr[0] == NULL)
383 break;
384
385 switch (op_expr[0]->operation) {
386 case ir_binop_less: new_op = ir_binop_gequal; break;
387 case ir_binop_greater: new_op = ir_binop_lequal; break;
388 case ir_binop_lequal: new_op = ir_binop_greater; break;
389 case ir_binop_gequal: new_op = ir_binop_less; break;
390 case ir_binop_equal: new_op = ir_binop_nequal; break;
391 case ir_binop_nequal: new_op = ir_binop_equal; break;
392 case ir_binop_all_equal: new_op = ir_binop_any_nequal; break;
393 case ir_binop_any_nequal: new_op = ir_binop_all_equal; break;
394
395 default:
396 /* The default case handler is here to silence a warning from GCC.
397 */
398 break;
399 }
400
401 if (new_op != ir_unop_logic_not) {
402 return new(mem_ctx) ir_expression(new_op,
403 ir->type,
404 op_expr[0]->operands[0],
405 op_expr[0]->operands[1]);
406 }
407
408 break;
409 }
410
411 case ir_binop_add:
412 if (is_vec_zero(op_const[0]))
413 return ir->operands[1];
414 if (is_vec_zero(op_const[1]))
415 return ir->operands[0];
416
417 /* Reassociate addition of constants so that we can do constant
418 * folding.
419 */
420 if (op_const[0] && !op_const[1])
421 reassociate_constant(ir, 0, op_const[0], op_expr[1]);
422 if (op_const[1] && !op_const[0])
423 reassociate_constant(ir, 1, op_const[1], op_expr[0]);
424
425 /* Recognize (v.x + v.y) + (v.z + v.w) as dot(v, 1.0) */
426 if (options->OptimizeForAOS) {
427 ir_expression *expr = try_replace_with_dot(op_expr[0], op_expr[1],
428 mem_ctx);
429 if (expr)
430 return expr;
431 }
432
433 /* Replace (-x + y) * a + x and commutative variations with lrp(x, y, a).
434 *
435 * (-x + y) * a + x
436 * (x * -a) + (y * a) + x
437 * x + (x * -a) + (y * a)
438 * x * (1 - a) + y * a
439 * lrp(x, y, a)
440 */
441 for (int mul_pos = 0; mul_pos < 2; mul_pos++) {
442 ir_expression *mul = op_expr[mul_pos];
443
444 if (!mul || mul->operation != ir_binop_mul)
445 continue;
446
447 /* Multiply found on one of the operands. Now check for an
448 * inner addition operation.
449 */
450 for (int inner_add_pos = 0; inner_add_pos < 2; inner_add_pos++) {
451 ir_expression *inner_add =
452 mul->operands[inner_add_pos]->as_expression();
453
454 if (!inner_add || inner_add->operation != ir_binop_add)
455 continue;
456
457 /* Inner addition found on one of the operands. Now check for
458 * one of the operands of the inner addition to be the negative
459 * of x_operand.
460 */
461 for (int neg_pos = 0; neg_pos < 2; neg_pos++) {
462 ir_expression *neg =
463 inner_add->operands[neg_pos]->as_expression();
464
465 if (!neg || neg->operation != ir_unop_neg)
466 continue;
467
468 ir_rvalue *x_operand = ir->operands[1 - mul_pos];
469
470 if (!neg->operands[0]->equals(x_operand))
471 continue;
472
473 ir_rvalue *y_operand = inner_add->operands[1 - neg_pos];
474 ir_rvalue *a_operand = mul->operands[1 - inner_add_pos];
475
476 if (x_operand->type != y_operand->type ||
477 x_operand->type != a_operand->type)
478 continue;
479
480 return lrp(x_operand, y_operand, a_operand);
481 }
482 }
483 }
484
485 break;
486
487 case ir_binop_sub:
488 if (is_vec_zero(op_const[0]))
489 return neg(ir->operands[1]);
490 if (is_vec_zero(op_const[1]))
491 return ir->operands[0];
492 break;
493
494 case ir_binop_mul:
495 if (is_vec_one(op_const[0]))
496 return ir->operands[1];
497 if (is_vec_one(op_const[1]))
498 return ir->operands[0];
499
500 if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1]))
501 return ir_constant::zero(ir, ir->type);
502
503 if (is_vec_negative_one(op_const[0]))
504 return neg(ir->operands[1]);
505 if (is_vec_negative_one(op_const[1]))
506 return neg(ir->operands[0]);
507
508
509 /* Reassociate multiplication of constants so that we can do
510 * constant folding.
511 */
512 if (op_const[0] && !op_const[1])
513 reassociate_constant(ir, 0, op_const[0], op_expr[1]);
514 if (op_const[1] && !op_const[0])
515 reassociate_constant(ir, 1, op_const[1], op_expr[0]);
516
517 break;
518
519 case ir_binop_div:
520 if (is_vec_one(op_const[0]) && ir->type->base_type == GLSL_TYPE_FLOAT) {
521 return new(mem_ctx) ir_expression(ir_unop_rcp,
522 ir->operands[1]->type,
523 ir->operands[1],
524 NULL);
525 }
526 if (is_vec_one(op_const[1]))
527 return ir->operands[0];
528 break;
529
530 case ir_binop_dot:
531 if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1]))
532 return ir_constant::zero(mem_ctx, ir->type);
533
534 for (int i = 0; i < 2; i++) {
535 if (!op_const[i])
536 continue;
537
538 unsigned components[4] = { 0 }, count = 0;
539
540 for (unsigned c = 0; c < op_const[i]->type->vector_elements; c++) {
541 if (op_const[i]->value.f[c] == 0.0)
542 continue;
543
544 components[count] = c;
545 count++;
546 }
547
548 /* No channels had zero values; bail. */
549 if (count >= op_const[i]->type->vector_elements)
550 break;
551
552 ir_expression_operation op = count == 1 ?
553 ir_binop_mul : ir_binop_dot;
554
555 /* Swizzle both operands to remove the channels that were zero. */
556 return new(mem_ctx)
557 ir_expression(op, glsl_type::float_type,
558 new(mem_ctx) ir_swizzle(ir->operands[0],
559 components, count),
560 new(mem_ctx) ir_swizzle(ir->operands[1],
561 components, count));
562 }
563 break;
564
565 case ir_binop_less:
566 case ir_binop_lequal:
567 case ir_binop_greater:
568 case ir_binop_gequal:
569 case ir_binop_equal:
570 case ir_binop_nequal:
571 for (int add_pos = 0; add_pos < 2; add_pos++) {
572 ir_expression *add = op_expr[add_pos];
573
574 if (!add || add->operation != ir_binop_add)
575 continue;
576
577 ir_constant *zero = op_const[1 - add_pos];
578 if (!is_vec_zero(zero))
579 continue;
580
581 return new(mem_ctx) ir_expression(ir->operation,
582 add->operands[0],
583 neg(add->operands[1]));
584 }
585 break;
586
587 case ir_binop_all_equal:
588 case ir_binop_any_nequal:
589 if (ir->operands[0]->type->is_scalar() &&
590 ir->operands[1]->type->is_scalar())
591 return new(mem_ctx) ir_expression(ir->operation == ir_binop_all_equal
592 ? ir_binop_equal : ir_binop_nequal,
593 ir->operands[0],
594 ir->operands[1]);
595 break;
596
597 case ir_binop_rshift:
598 case ir_binop_lshift:
599 /* 0 >> x == 0 */
600 if (is_vec_zero(op_const[0]))
601 return ir->operands[0];
602 /* x >> 0 == x */
603 if (is_vec_zero(op_const[1]))
604 return ir->operands[0];
605 break;
606
607 case ir_binop_logic_and:
608 if (is_vec_one(op_const[0])) {
609 return ir->operands[1];
610 } else if (is_vec_one(op_const[1])) {
611 return ir->operands[0];
612 } else if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) {
613 return ir_constant::zero(mem_ctx, ir->type);
614 } else if (op_expr[0] && op_expr[0]->operation == ir_unop_logic_not &&
615 op_expr[1] && op_expr[1]->operation == ir_unop_logic_not) {
616 /* De Morgan's Law:
617 * (not A) and (not B) === not (A or B)
618 */
619 return logic_not(logic_or(op_expr[0]->operands[0],
620 op_expr[1]->operands[0]));
621 } else if (ir->operands[0]->equals(ir->operands[1])) {
622 /* (a && a) == a */
623 return ir->operands[0];
624 }
625 break;
626
627 case ir_binop_logic_xor:
628 if (is_vec_zero(op_const[0])) {
629 return ir->operands[1];
630 } else if (is_vec_zero(op_const[1])) {
631 return ir->operands[0];
632 } else if (is_vec_one(op_const[0])) {
633 return logic_not(ir->operands[1]);
634 } else if (is_vec_one(op_const[1])) {
635 return logic_not(ir->operands[0]);
636 } else if (ir->operands[0]->equals(ir->operands[1])) {
637 /* (a ^^ a) == false */
638 return ir_constant::zero(mem_ctx, ir->type);
639 }
640 break;
641
642 case ir_binop_logic_or:
643 if (is_vec_zero(op_const[0])) {
644 return ir->operands[1];
645 } else if (is_vec_zero(op_const[1])) {
646 return ir->operands[0];
647 } else if (is_vec_one(op_const[0]) || is_vec_one(op_const[1])) {
648 ir_constant_data data;
649
650 for (unsigned i = 0; i < 16; i++)
651 data.b[i] = true;
652
653 return new(mem_ctx) ir_constant(ir->type, &data);
654 } else if (op_expr[0] && op_expr[0]->operation == ir_unop_logic_not &&
655 op_expr[1] && op_expr[1]->operation == ir_unop_logic_not) {
656 /* De Morgan's Law:
657 * (not A) or (not B) === not (A and B)
658 */
659 return logic_not(logic_and(op_expr[0]->operands[0],
660 op_expr[1]->operands[0]));
661 } else if (ir->operands[0]->equals(ir->operands[1])) {
662 /* (a || a) == a */
663 return ir->operands[0];
664 }
665 break;
666
667 case ir_binop_pow:
668 /* 1^x == 1 */
669 if (is_vec_one(op_const[0]))
670 return op_const[0];
671
672 /* x^1 == x */
673 if (is_vec_one(op_const[1]))
674 return ir->operands[0];
675
676 /* pow(2,x) == exp2(x) */
677 if (is_vec_two(op_const[0]))
678 return expr(ir_unop_exp2, ir->operands[1]);
679
680 if (is_vec_two(op_const[1])) {
681 ir_variable *x = new(ir) ir_variable(ir->operands[1]->type, "x",
682 ir_var_temporary);
683 base_ir->insert_before(x);
684 base_ir->insert_before(assign(x, ir->operands[0]));
685 return mul(x, x);
686 }
687
688 break;
689
690 case ir_binop_min:
691 case ir_binop_max:
692 if (ir->type->base_type != GLSL_TYPE_FLOAT || options->EmitNoSat)
693 break;
694
695 /* Replace min(max) operations and its commutative combinations with
696 * a saturate operation
697 */
698 for (int op = 0; op < 2; op++) {
699 ir_expression *minmax = op_expr[op];
700 ir_constant *outer_const = op_const[1 - op];
701 ir_expression_operation op_cond = (ir->operation == ir_binop_max) ?
702 ir_binop_min : ir_binop_max;
703
704 if (!minmax || !outer_const || (minmax->operation != op_cond))
705 continue;
706
707 /* Found a min(max) combination. Now try to see if its operands
708 * meet our conditions that we can do just a single saturate operation
709 */
710 for (int minmax_op = 0; minmax_op < 2; minmax_op++) {
711 ir_rvalue *inner_val_a = minmax->operands[minmax_op];
712 ir_rvalue *inner_val_b = minmax->operands[1 - minmax_op];
713
714 if (!inner_val_a || !inner_val_b)
715 continue;
716
717 /* Found a {min|max} ({max|min} (x, 0.0), 1.0) operation and its variations */
718 if ((outer_const->is_one() && inner_val_a->is_zero()) ||
719 (inner_val_a->is_one() && outer_const->is_zero()))
720 return saturate(inner_val_b);
721
722 /* Found a {min|max} ({max|min} (x, 0.0), b) where b < 1.0
723 * and its variations
724 */
725 if (is_less_than_one(outer_const) && inner_val_b->is_zero())
726 return expr(ir_binop_min, saturate(inner_val_a), outer_const);
727
728 if (!inner_val_b->as_constant())
729 continue;
730
731 if (is_less_than_one(inner_val_b->as_constant()) && outer_const->is_zero())
732 return expr(ir_binop_min, saturate(inner_val_a), inner_val_b);
733
734 /* Found a {min|max} ({max|min} (x, b), 1.0), where b > 0.0
735 * and its variations
736 */
737 if (outer_const->is_one() && is_greater_than_zero(inner_val_b->as_constant()))
738 return expr(ir_binop_max, saturate(inner_val_a), inner_val_b);
739 if (inner_val_b->as_constant()->is_one() && is_greater_than_zero(outer_const))
740 return expr(ir_binop_max, saturate(inner_val_a), outer_const);
741 }
742 }
743
744 break;
745
746 case ir_unop_rcp:
747 if (op_expr[0] && op_expr[0]->operation == ir_unop_rcp)
748 return op_expr[0]->operands[0];
749
750 /* While ir_to_mesa.cpp will lower sqrt(x) to rcp(rsq(x)), it does so at
751 * its IR level, so we can always apply this transformation.
752 */
753 if (op_expr[0] && op_expr[0]->operation == ir_unop_rsq)
754 return sqrt(op_expr[0]->operands[0]);
755
756 /* As far as we know, all backends are OK with rsq. */
757 if (op_expr[0] && op_expr[0]->operation == ir_unop_sqrt) {
758 return rsq(op_expr[0]->operands[0]);
759 }
760
761 break;
762
763 case ir_triop_fma:
764 /* Operands are op0 * op1 + op2. */
765 if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) {
766 return ir->operands[2];
767 } else if (is_vec_zero(op_const[2])) {
768 return mul(ir->operands[0], ir->operands[1]);
769 } else if (is_vec_one(op_const[0])) {
770 return add(ir->operands[1], ir->operands[2]);
771 } else if (is_vec_one(op_const[1])) {
772 return add(ir->operands[0], ir->operands[2]);
773 }
774 break;
775
776 case ir_triop_lrp:
777 /* Operands are (x, y, a). */
778 if (is_vec_zero(op_const[2])) {
779 return ir->operands[0];
780 } else if (is_vec_one(op_const[2])) {
781 return ir->operands[1];
782 } else if (ir->operands[0]->equals(ir->operands[1])) {
783 return ir->operands[0];
784 } else if (is_vec_zero(op_const[0])) {
785 return mul(ir->operands[1], ir->operands[2]);
786 } else if (is_vec_zero(op_const[1])) {
787 unsigned op2_components = ir->operands[2]->type->vector_elements;
788 ir_constant *one = new(mem_ctx) ir_constant(1.0f, op2_components);
789 return mul(ir->operands[0], add(one, neg(ir->operands[2])));
790 }
791 break;
792
793 case ir_triop_csel:
794 if (is_vec_one(op_const[0]))
795 return ir->operands[1];
796 if (is_vec_zero(op_const[0]))
797 return ir->operands[2];
798 break;
799
800 default:
801 break;
802 }
803
804 return ir;
805 }
806
807 void
808 ir_algebraic_visitor::handle_rvalue(ir_rvalue **rvalue)
809 {
810 if (!*rvalue)
811 return;
812
813 ir_expression *expr = (*rvalue)->as_expression();
814 if (!expr || expr->operation == ir_quadop_vector)
815 return;
816
817 ir_rvalue *new_rvalue = handle_expression(expr);
818 if (new_rvalue == *rvalue)
819 return;
820
821 /* If the expr used to be some vec OP scalar returning a vector, and the
822 * optimization gave us back a scalar, we still need to turn it into a
823 * vector.
824 */
825 *rvalue = swizzle_if_required(expr, new_rvalue);
826
827 this->progress = true;
828 }
829
830 bool
831 do_algebraic(exec_list *instructions, bool native_integers,
832 const struct gl_shader_compiler_options *options)
833 {
834 ir_algebraic_visitor v(native_integers, options);
835
836 visit_list_elements(&v, instructions);
837
838 return v.progress;
839 }