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