1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (c) 2017 Lima Project
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sub license,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
12bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
13bf215546Sopenharmony_ci * of the Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE.
22bf215546Sopenharmony_ci *
23bf215546Sopenharmony_ci */
24bf215546Sopenharmony_ci
25bf215546Sopenharmony_ci#include "util/ralloc.h"
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "gpir.h"
28bf215546Sopenharmony_ci#include "lima_context.h"
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_cistatic bool gpir_lower_const(gpir_compiler *comp)
31bf215546Sopenharmony_ci{
32bf215546Sopenharmony_ci   int num_constant = 0;
33bf215546Sopenharmony_ci   list_for_each_entry(gpir_block, block, &comp->block_list, list) {
34bf215546Sopenharmony_ci      list_for_each_entry_safe(gpir_node, node, &block->node_list, list) {
35bf215546Sopenharmony_ci         if (node->op == gpir_op_const) {
36bf215546Sopenharmony_ci            if (gpir_node_is_root(node))
37bf215546Sopenharmony_ci               gpir_node_delete(node);
38bf215546Sopenharmony_ci            else
39bf215546Sopenharmony_ci               num_constant++;
40bf215546Sopenharmony_ci         }
41bf215546Sopenharmony_ci      }
42bf215546Sopenharmony_ci   }
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_ci   if (num_constant) {
45bf215546Sopenharmony_ci      union fi *constant = ralloc_array(comp->prog, union fi, num_constant);
46bf215546Sopenharmony_ci      if (!constant)
47bf215546Sopenharmony_ci         return false;
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci      comp->prog->constant = constant;
50bf215546Sopenharmony_ci      comp->prog->state.constant_size = num_constant * sizeof(union fi);
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci      int index = 0;
53bf215546Sopenharmony_ci      list_for_each_entry(gpir_block, block, &comp->block_list, list) {
54bf215546Sopenharmony_ci         list_for_each_entry_safe(gpir_node, node, &block->node_list, list) {
55bf215546Sopenharmony_ci            if (node->op == gpir_op_const) {
56bf215546Sopenharmony_ci               gpir_const_node *c = gpir_node_to_const(node);
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_ci               if (!gpir_node_is_root(node)) {
59bf215546Sopenharmony_ci                  gpir_load_node *load = gpir_node_create(block, gpir_op_load_uniform);
60bf215546Sopenharmony_ci                  if (unlikely(!load))
61bf215546Sopenharmony_ci                     return false;
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ci                  load->index = comp->constant_base + (index >> 2);
64bf215546Sopenharmony_ci                  load->component = index % 4;
65bf215546Sopenharmony_ci                  constant[index++] = c->value;
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci                  gpir_node_replace_succ(&load->node, node);
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_ci                  list_addtail(&load->node.list, &node->list);
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_ci                  gpir_debug("lower const create uniform %d for const %d\n",
72bf215546Sopenharmony_ci                             load->node.index, node->index);
73bf215546Sopenharmony_ci               }
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci               gpir_node_delete(node);
76bf215546Sopenharmony_ci            }
77bf215546Sopenharmony_ci         }
78bf215546Sopenharmony_ci      }
79bf215546Sopenharmony_ci   }
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_ci   return true;
82bf215546Sopenharmony_ci}
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci/* duplicate load to all its successors */
85bf215546Sopenharmony_cistatic bool gpir_lower_load(gpir_compiler *comp)
86bf215546Sopenharmony_ci{
87bf215546Sopenharmony_ci   list_for_each_entry(gpir_block, block, &comp->block_list, list) {
88bf215546Sopenharmony_ci      list_for_each_entry_safe(gpir_node, node, &block->node_list, list) {
89bf215546Sopenharmony_ci         if (node->type == gpir_node_type_load) {
90bf215546Sopenharmony_ci            gpir_load_node *load = gpir_node_to_load(node);
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci            bool first = true;
93bf215546Sopenharmony_ci            gpir_node_foreach_succ_safe(node, dep) {
94bf215546Sopenharmony_ci               gpir_node *succ = dep->succ;
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci               if (first) {
97bf215546Sopenharmony_ci                  first = false;
98bf215546Sopenharmony_ci                  continue;
99bf215546Sopenharmony_ci               }
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci               gpir_node *new = gpir_node_create(succ->block, node->op);
102bf215546Sopenharmony_ci               if (unlikely(!new))
103bf215546Sopenharmony_ci                  return false;
104bf215546Sopenharmony_ci               list_addtail(&new->list, &succ->list);
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci               gpir_debug("lower load create %d from %d for succ %d\n",
107bf215546Sopenharmony_ci                          new->index, node->index, succ->index);
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci               gpir_load_node *nload = gpir_node_to_load(new);
110bf215546Sopenharmony_ci               nload->index = load->index;
111bf215546Sopenharmony_ci               nload->component = load->component;
112bf215546Sopenharmony_ci               nload->reg = load->reg;
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci               gpir_node_replace_pred(dep, new);
115bf215546Sopenharmony_ci               gpir_node_replace_child(succ, node, new);
116bf215546Sopenharmony_ci            }
117bf215546Sopenharmony_ci         }
118bf215546Sopenharmony_ci      }
119bf215546Sopenharmony_ci   }
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci   return true;
122bf215546Sopenharmony_ci}
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_cistatic bool gpir_lower_neg(gpir_block *block, gpir_node *node)
125bf215546Sopenharmony_ci{
126bf215546Sopenharmony_ci   gpir_alu_node *neg = gpir_node_to_alu(node);
127bf215546Sopenharmony_ci   gpir_node *child = neg->children[0];
128bf215546Sopenharmony_ci
129bf215546Sopenharmony_ci   /* check if child can dest negate */
130bf215546Sopenharmony_ci   if (child->type == gpir_node_type_alu) {
131bf215546Sopenharmony_ci      /* negate must be its only successor */
132bf215546Sopenharmony_ci      if (list_is_singular(&child->succ_list) &&
133bf215546Sopenharmony_ci          gpir_op_infos[child->op].dest_neg) {
134bf215546Sopenharmony_ci         gpir_alu_node *alu = gpir_node_to_alu(child);
135bf215546Sopenharmony_ci         alu->dest_negate = !alu->dest_negate;
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci         gpir_node_replace_succ(child, node);
138bf215546Sopenharmony_ci         gpir_node_delete(node);
139bf215546Sopenharmony_ci         return true;
140bf215546Sopenharmony_ci      }
141bf215546Sopenharmony_ci   }
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ci   /* check if child can src negate */
144bf215546Sopenharmony_ci   gpir_node_foreach_succ_safe(node, dep) {
145bf215546Sopenharmony_ci      gpir_node *succ = dep->succ;
146bf215546Sopenharmony_ci      if (succ->type != gpir_node_type_alu)
147bf215546Sopenharmony_ci         continue;
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci      bool success = true;
150bf215546Sopenharmony_ci      gpir_alu_node *alu = gpir_node_to_alu(dep->succ);
151bf215546Sopenharmony_ci      for (int i = 0; i < alu->num_child; i++) {
152bf215546Sopenharmony_ci         if (alu->children[i] == node) {
153bf215546Sopenharmony_ci            if (gpir_op_infos[succ->op].src_neg[i]) {
154bf215546Sopenharmony_ci               alu->children_negate[i] = !alu->children_negate[i];
155bf215546Sopenharmony_ci               alu->children[i] = child;
156bf215546Sopenharmony_ci            }
157bf215546Sopenharmony_ci            else
158bf215546Sopenharmony_ci               success = false;
159bf215546Sopenharmony_ci         }
160bf215546Sopenharmony_ci      }
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci      if (success)
163bf215546Sopenharmony_ci         gpir_node_replace_pred(dep, child);
164bf215546Sopenharmony_ci   }
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_ci   if (gpir_node_is_root(node))
167bf215546Sopenharmony_ci      gpir_node_delete(node);
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci   return true;
170bf215546Sopenharmony_ci}
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_cistatic bool gpir_lower_complex(gpir_block *block, gpir_node *node)
173bf215546Sopenharmony_ci{
174bf215546Sopenharmony_ci   gpir_alu_node *alu = gpir_node_to_alu(node);
175bf215546Sopenharmony_ci   gpir_node *child = alu->children[0];
176bf215546Sopenharmony_ci
177bf215546Sopenharmony_ci   if (node->op == gpir_op_exp2) {
178bf215546Sopenharmony_ci      gpir_alu_node *preexp2 = gpir_node_create(block, gpir_op_preexp2);
179bf215546Sopenharmony_ci      if (unlikely(!preexp2))
180bf215546Sopenharmony_ci         return false;
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_ci      preexp2->children[0] = child;
183bf215546Sopenharmony_ci      preexp2->num_child = 1;
184bf215546Sopenharmony_ci      gpir_node_add_dep(&preexp2->node, child, GPIR_DEP_INPUT);
185bf215546Sopenharmony_ci      list_addtail(&preexp2->node.list, &node->list);
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_ci      child = &preexp2->node;
188bf215546Sopenharmony_ci   }
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_ci   gpir_alu_node *complex2 = gpir_node_create(block, gpir_op_complex2);
191bf215546Sopenharmony_ci   if (unlikely(!complex2))
192bf215546Sopenharmony_ci      return false;
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci   complex2->children[0] = child;
195bf215546Sopenharmony_ci   complex2->num_child = 1;
196bf215546Sopenharmony_ci   gpir_node_add_dep(&complex2->node, child, GPIR_DEP_INPUT);
197bf215546Sopenharmony_ci   list_addtail(&complex2->node.list, &node->list);
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci   int impl_op = 0;
200bf215546Sopenharmony_ci   switch (node->op) {
201bf215546Sopenharmony_ci   case gpir_op_rcp:
202bf215546Sopenharmony_ci      impl_op = gpir_op_rcp_impl;
203bf215546Sopenharmony_ci      break;
204bf215546Sopenharmony_ci   case gpir_op_rsqrt:
205bf215546Sopenharmony_ci      impl_op = gpir_op_rsqrt_impl;
206bf215546Sopenharmony_ci      break;
207bf215546Sopenharmony_ci   case gpir_op_exp2:
208bf215546Sopenharmony_ci      impl_op = gpir_op_exp2_impl;
209bf215546Sopenharmony_ci      break;
210bf215546Sopenharmony_ci   case gpir_op_log2:
211bf215546Sopenharmony_ci      impl_op = gpir_op_log2_impl;
212bf215546Sopenharmony_ci      break;
213bf215546Sopenharmony_ci   default:
214bf215546Sopenharmony_ci      assert(0);
215bf215546Sopenharmony_ci   }
216bf215546Sopenharmony_ci
217bf215546Sopenharmony_ci   gpir_alu_node *impl = gpir_node_create(block, impl_op);
218bf215546Sopenharmony_ci   if (unlikely(!impl))
219bf215546Sopenharmony_ci      return false;
220bf215546Sopenharmony_ci
221bf215546Sopenharmony_ci   impl->children[0] = child;
222bf215546Sopenharmony_ci   impl->num_child = 1;
223bf215546Sopenharmony_ci   gpir_node_add_dep(&impl->node, child, GPIR_DEP_INPUT);
224bf215546Sopenharmony_ci   list_addtail(&impl->node.list, &node->list);
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_ci   gpir_alu_node *complex1 = gpir_node_create(block, gpir_op_complex1);
227bf215546Sopenharmony_ci   complex1->children[0] = &impl->node;
228bf215546Sopenharmony_ci   complex1->children[1] = &complex2->node;
229bf215546Sopenharmony_ci   complex1->children[2] = child;
230bf215546Sopenharmony_ci   complex1->num_child = 3;
231bf215546Sopenharmony_ci   gpir_node_add_dep(&complex1->node, child, GPIR_DEP_INPUT);
232bf215546Sopenharmony_ci   gpir_node_add_dep(&complex1->node, &impl->node, GPIR_DEP_INPUT);
233bf215546Sopenharmony_ci   gpir_node_add_dep(&complex1->node, &complex2->node, GPIR_DEP_INPUT);
234bf215546Sopenharmony_ci   list_addtail(&complex1->node.list, &node->list);
235bf215546Sopenharmony_ci
236bf215546Sopenharmony_ci   gpir_node *result = &complex1->node;
237bf215546Sopenharmony_ci
238bf215546Sopenharmony_ci   if (node->op == gpir_op_log2) {
239bf215546Sopenharmony_ci      gpir_alu_node *postlog2 = gpir_node_create(block, gpir_op_postlog2);
240bf215546Sopenharmony_ci      if (unlikely(!postlog2))
241bf215546Sopenharmony_ci         return false;
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci      postlog2->children[0] = result;
244bf215546Sopenharmony_ci      postlog2->num_child = 1;
245bf215546Sopenharmony_ci      gpir_node_add_dep(&postlog2->node, result, GPIR_DEP_INPUT);
246bf215546Sopenharmony_ci      list_addtail(&postlog2->node.list, &node->list);
247bf215546Sopenharmony_ci
248bf215546Sopenharmony_ci      result = &postlog2->node;
249bf215546Sopenharmony_ci   }
250bf215546Sopenharmony_ci
251bf215546Sopenharmony_ci   gpir_node_replace_succ(result, node);
252bf215546Sopenharmony_ci   gpir_node_delete(node);
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci   return true;
255bf215546Sopenharmony_ci}
256bf215546Sopenharmony_ci
257bf215546Sopenharmony_cistatic bool gpir_lower_node_may_consume_two_slots(gpir_compiler *comp)
258bf215546Sopenharmony_ci{
259bf215546Sopenharmony_ci   list_for_each_entry(gpir_block, block, &comp->block_list, list) {
260bf215546Sopenharmony_ci      list_for_each_entry_safe(gpir_node, node, &block->node_list, list) {
261bf215546Sopenharmony_ci         if (gpir_op_infos[node->op].may_consume_two_slots) {
262bf215546Sopenharmony_ci            /* dummy_f/m are auxiliary nodes for value reg alloc:
263bf215546Sopenharmony_ci             * 1. before reg alloc, create fake nodes dummy_f, dummy_m,
264bf215546Sopenharmony_ci             *    so the tree become: (dummy_m (node dummy_f))
265bf215546Sopenharmony_ci             *    dummy_m can be spilled, but other nodes in the tree can't
266bf215546Sopenharmony_ci             *    be spilled.
267bf215546Sopenharmony_ci             * 2. After reg allocation and fake dep add, merge all deps of
268bf215546Sopenharmony_ci             *    dummy_m and dummy_f to node and remove dummy_m & dummy_f
269bf215546Sopenharmony_ci             *
270bf215546Sopenharmony_ci             * We may also not use dummy_f/m, but alloc two value reg for
271bf215546Sopenharmony_ci             * node. But that means we need to make sure there're 2 free
272bf215546Sopenharmony_ci             * slot after the node successors, but we just need one slot
273bf215546Sopenharmony_ci             * after to be able to schedule it because we can use one move for
274bf215546Sopenharmony_ci             * the two slot node. It's also not easy to handle the spill case
275bf215546Sopenharmony_ci             * for the alloc 2 value method.
276bf215546Sopenharmony_ci             *
277bf215546Sopenharmony_ci             * With the dummy_f/m method, there's no such requirement, the
278bf215546Sopenharmony_ci             * node can be scheduled only when there's two slots for it,
279bf215546Sopenharmony_ci             * otherwise a move. And the node can be spilled with one reg.
280bf215546Sopenharmony_ci             */
281bf215546Sopenharmony_ci            gpir_node *dummy_m = gpir_node_create(block, gpir_op_dummy_m);
282bf215546Sopenharmony_ci            if (unlikely(!dummy_m))
283bf215546Sopenharmony_ci               return false;
284bf215546Sopenharmony_ci            list_add(&dummy_m->list, &node->list);
285bf215546Sopenharmony_ci
286bf215546Sopenharmony_ci            gpir_node *dummy_f = gpir_node_create(block, gpir_op_dummy_f);
287bf215546Sopenharmony_ci            if (unlikely(!dummy_f))
288bf215546Sopenharmony_ci               return false;
289bf215546Sopenharmony_ci            list_add(&dummy_f->list, &node->list);
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_ci            gpir_alu_node *alu = gpir_node_to_alu(dummy_m);
292bf215546Sopenharmony_ci            alu->children[0] = node;
293bf215546Sopenharmony_ci            alu->children[1] = dummy_f;
294bf215546Sopenharmony_ci            alu->num_child = 2;
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_ci            gpir_node_replace_succ(dummy_m, node);
297bf215546Sopenharmony_ci            gpir_node_add_dep(dummy_m, node, GPIR_DEP_INPUT);
298bf215546Sopenharmony_ci            gpir_node_add_dep(dummy_m, dummy_f, GPIR_DEP_INPUT);
299bf215546Sopenharmony_ci
300bf215546Sopenharmony_ci         }
301bf215546Sopenharmony_ci      }
302bf215546Sopenharmony_ci   }
303bf215546Sopenharmony_ci
304bf215546Sopenharmony_ci   return true;
305bf215546Sopenharmony_ci}
306bf215546Sopenharmony_ci
307bf215546Sopenharmony_ci/*
308bf215546Sopenharmony_ci * There are no 'equal' or 'not-equal' opcodes.
309bf215546Sopenharmony_ci * eq (a == b) is lowered to and(a >= b, b >= a)
310bf215546Sopenharmony_ci * ne (a != b) is lowered to or(a < b, b < a)
311bf215546Sopenharmony_ci */
312bf215546Sopenharmony_cistatic bool gpir_lower_eq_ne(gpir_block *block, gpir_node *node)
313bf215546Sopenharmony_ci{
314bf215546Sopenharmony_ci   gpir_op cmp_node_op;
315bf215546Sopenharmony_ci   gpir_op node_new_op;
316bf215546Sopenharmony_ci   switch (node->op) {
317bf215546Sopenharmony_ci      case gpir_op_eq:
318bf215546Sopenharmony_ci         cmp_node_op = gpir_op_ge;
319bf215546Sopenharmony_ci         node_new_op = gpir_op_min; /* and */
320bf215546Sopenharmony_ci         break;
321bf215546Sopenharmony_ci      case gpir_op_ne:
322bf215546Sopenharmony_ci         cmp_node_op = gpir_op_lt;
323bf215546Sopenharmony_ci         node_new_op = gpir_op_max; /* or */
324bf215546Sopenharmony_ci         break;
325bf215546Sopenharmony_ci      default:
326bf215546Sopenharmony_ci         unreachable("bad node op");
327bf215546Sopenharmony_ci   }
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_ci   gpir_alu_node *e = gpir_node_to_alu(node);
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_ci   gpir_alu_node *cmp1 = gpir_node_create(block, cmp_node_op);
332bf215546Sopenharmony_ci   list_addtail(&cmp1->node.list, &node->list);
333bf215546Sopenharmony_ci   gpir_alu_node *cmp2 = gpir_node_create(block, cmp_node_op);
334bf215546Sopenharmony_ci   list_addtail(&cmp2->node.list, &node->list);
335bf215546Sopenharmony_ci
336bf215546Sopenharmony_ci   cmp1->children[0] = e->children[0];
337bf215546Sopenharmony_ci   cmp1->children[1] = e->children[1];
338bf215546Sopenharmony_ci   cmp1->num_child = 2;
339bf215546Sopenharmony_ci
340bf215546Sopenharmony_ci   cmp2->children[0] = e->children[1];
341bf215546Sopenharmony_ci   cmp2->children[1] = e->children[0];
342bf215546Sopenharmony_ci   cmp2->num_child = 2;
343bf215546Sopenharmony_ci
344bf215546Sopenharmony_ci   gpir_node_add_dep(&cmp1->node, e->children[0], GPIR_DEP_INPUT);
345bf215546Sopenharmony_ci   gpir_node_add_dep(&cmp1->node, e->children[1], GPIR_DEP_INPUT);
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_ci   gpir_node_add_dep(&cmp2->node, e->children[0], GPIR_DEP_INPUT);
348bf215546Sopenharmony_ci   gpir_node_add_dep(&cmp2->node, e->children[1], GPIR_DEP_INPUT);
349bf215546Sopenharmony_ci
350bf215546Sopenharmony_ci   gpir_node_foreach_pred_safe(node, dep) {
351bf215546Sopenharmony_ci      gpir_node_remove_dep(node, dep->pred);
352bf215546Sopenharmony_ci   }
353bf215546Sopenharmony_ci
354bf215546Sopenharmony_ci   gpir_node_add_dep(node, &cmp1->node, GPIR_DEP_INPUT);
355bf215546Sopenharmony_ci   gpir_node_add_dep(node, &cmp2->node, GPIR_DEP_INPUT);
356bf215546Sopenharmony_ci
357bf215546Sopenharmony_ci   node->op = node_new_op;
358bf215546Sopenharmony_ci   e->children[0] = &cmp1->node;
359bf215546Sopenharmony_ci   e->children[1] = &cmp2->node;
360bf215546Sopenharmony_ci   e->num_child = 2;
361bf215546Sopenharmony_ci
362bf215546Sopenharmony_ci   return true;
363bf215546Sopenharmony_ci}
364bf215546Sopenharmony_ci
365bf215546Sopenharmony_ci/*
366bf215546Sopenharmony_ci * There is no 'abs' opcode.
367bf215546Sopenharmony_ci * abs(a) is lowered to max(a, -a)
368bf215546Sopenharmony_ci */
369bf215546Sopenharmony_cistatic bool gpir_lower_abs(gpir_block *block, gpir_node *node)
370bf215546Sopenharmony_ci{
371bf215546Sopenharmony_ci   gpir_alu_node *alu = gpir_node_to_alu(node);
372bf215546Sopenharmony_ci
373bf215546Sopenharmony_ci   assert(node->op == gpir_op_abs);
374bf215546Sopenharmony_ci
375bf215546Sopenharmony_ci   node->op = gpir_op_max;
376bf215546Sopenharmony_ci
377bf215546Sopenharmony_ci   alu->children[1] = alu->children[0];
378bf215546Sopenharmony_ci   alu->children_negate[1] = true;
379bf215546Sopenharmony_ci   alu->num_child = 2;
380bf215546Sopenharmony_ci
381bf215546Sopenharmony_ci   return true;
382bf215546Sopenharmony_ci}
383bf215546Sopenharmony_ci
384bf215546Sopenharmony_ci/*
385bf215546Sopenharmony_ci * There is no 'not' opcode.
386bf215546Sopenharmony_ci * not(a) is lowered to add(1, -a)
387bf215546Sopenharmony_ci */
388bf215546Sopenharmony_cistatic bool gpir_lower_not(gpir_block *block, gpir_node *node)
389bf215546Sopenharmony_ci{
390bf215546Sopenharmony_ci   gpir_alu_node *alu = gpir_node_to_alu(node);
391bf215546Sopenharmony_ci
392bf215546Sopenharmony_ci   assert(alu->node.op == gpir_op_not);
393bf215546Sopenharmony_ci
394bf215546Sopenharmony_ci   node->op = gpir_op_add;
395bf215546Sopenharmony_ci
396bf215546Sopenharmony_ci   gpir_node *node_const = gpir_node_create(block, gpir_op_const);
397bf215546Sopenharmony_ci   gpir_const_node *c = gpir_node_to_const(node_const);
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_ci   assert(c->node.op == gpir_op_const);
400bf215546Sopenharmony_ci
401bf215546Sopenharmony_ci   list_addtail(&c->node.list, &node->list);
402bf215546Sopenharmony_ci   c->value.f = 1.0f;
403bf215546Sopenharmony_ci   gpir_node_add_dep(&alu->node, &c->node, GPIR_DEP_INPUT);
404bf215546Sopenharmony_ci
405bf215546Sopenharmony_ci   alu->children_negate[1] = !alu->children_negate[0];
406bf215546Sopenharmony_ci   alu->children[1] = alu->children[0];
407bf215546Sopenharmony_ci   alu->children[0] = &c->node;
408bf215546Sopenharmony_ci   alu->num_child = 2;
409bf215546Sopenharmony_ci
410bf215546Sopenharmony_ci   return true;
411bf215546Sopenharmony_ci}
412bf215546Sopenharmony_ci
413bf215546Sopenharmony_ci/* There is no unconditional branch instruction, so we have to lower it to a
414bf215546Sopenharmony_ci * conditional branch with a condition of 1.0.
415bf215546Sopenharmony_ci */
416bf215546Sopenharmony_ci
417bf215546Sopenharmony_cistatic bool gpir_lower_branch_uncond(gpir_block *block, gpir_node *node)
418bf215546Sopenharmony_ci{
419bf215546Sopenharmony_ci   gpir_branch_node *branch = gpir_node_to_branch(node);
420bf215546Sopenharmony_ci
421bf215546Sopenharmony_ci   gpir_node *node_const = gpir_node_create(block, gpir_op_const);
422bf215546Sopenharmony_ci   gpir_const_node *c = gpir_node_to_const(node_const);
423bf215546Sopenharmony_ci
424bf215546Sopenharmony_ci   list_addtail(&c->node.list, &node->list);
425bf215546Sopenharmony_ci   c->value.f = 1.0f;
426bf215546Sopenharmony_ci   gpir_node_add_dep(&branch->node, &c->node, GPIR_DEP_INPUT);
427bf215546Sopenharmony_ci
428bf215546Sopenharmony_ci   branch->node.op = gpir_op_branch_cond;
429bf215546Sopenharmony_ci   branch->cond = node_const;
430bf215546Sopenharmony_ci
431bf215546Sopenharmony_ci   return true;
432bf215546Sopenharmony_ci}
433bf215546Sopenharmony_ci
434bf215546Sopenharmony_cistatic bool (*gpir_pre_rsched_lower_funcs[gpir_op_num])(gpir_block *, gpir_node *) = {
435bf215546Sopenharmony_ci   [gpir_op_not] = gpir_lower_not,
436bf215546Sopenharmony_ci   [gpir_op_neg] = gpir_lower_neg,
437bf215546Sopenharmony_ci   [gpir_op_rcp] = gpir_lower_complex,
438bf215546Sopenharmony_ci   [gpir_op_rsqrt] = gpir_lower_complex,
439bf215546Sopenharmony_ci   [gpir_op_exp2] = gpir_lower_complex,
440bf215546Sopenharmony_ci   [gpir_op_log2] = gpir_lower_complex,
441bf215546Sopenharmony_ci   [gpir_op_eq] = gpir_lower_eq_ne,
442bf215546Sopenharmony_ci   [gpir_op_ne] = gpir_lower_eq_ne,
443bf215546Sopenharmony_ci   [gpir_op_abs] = gpir_lower_abs,
444bf215546Sopenharmony_ci   [gpir_op_branch_uncond] = gpir_lower_branch_uncond,
445bf215546Sopenharmony_ci};
446bf215546Sopenharmony_ci
447bf215546Sopenharmony_cibool gpir_pre_rsched_lower_prog(gpir_compiler *comp)
448bf215546Sopenharmony_ci{
449bf215546Sopenharmony_ci   list_for_each_entry(gpir_block, block, &comp->block_list, list) {
450bf215546Sopenharmony_ci      list_for_each_entry_safe(gpir_node, node, &block->node_list, list) {
451bf215546Sopenharmony_ci         if (gpir_pre_rsched_lower_funcs[node->op] &&
452bf215546Sopenharmony_ci             !gpir_pre_rsched_lower_funcs[node->op](block, node))
453bf215546Sopenharmony_ci            return false;
454bf215546Sopenharmony_ci      }
455bf215546Sopenharmony_ci   }
456bf215546Sopenharmony_ci
457bf215546Sopenharmony_ci   if (!gpir_lower_const(comp))
458bf215546Sopenharmony_ci      return false;
459bf215546Sopenharmony_ci
460bf215546Sopenharmony_ci   if (!gpir_lower_load(comp))
461bf215546Sopenharmony_ci      return false;
462bf215546Sopenharmony_ci
463bf215546Sopenharmony_ci   if (!gpir_lower_node_may_consume_two_slots(comp))
464bf215546Sopenharmony_ci      return false;
465bf215546Sopenharmony_ci
466bf215546Sopenharmony_ci   gpir_debug("pre rsched lower prog\n");
467bf215546Sopenharmony_ci   gpir_node_print_prog_seq(comp);
468bf215546Sopenharmony_ci   return true;
469bf215546Sopenharmony_ci}
470bf215546Sopenharmony_ci
471