]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/brig/brigfrontend/brig-branch-inst-handler.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / brig / brigfrontend / brig-branch-inst-handler.cc
CommitLineData
5fd1486c 1/* brig-branch-inst-handler.cc -- brig branch instruction handling
8d9254fc 2 Copyright (C) 2016-2020 Free Software Foundation, Inc.
5fd1486c
PJ
3 Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
4 for General Processor Tech.
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
21
22#include "brig-code-entry-handler.h"
23
24#include "errors.h"
25#include "brig-util.h"
26#include "tree-pretty-print.h"
27#include "print-tree.h"
28#include "vec.h"
29#include "fold-const.h"
30
31size_t
32brig_branch_inst_handler::operator () (const BrigBase *base)
33{
34 const BrigInstBase *brig_inst
35 = (const BrigInstBase *) &((const BrigInstBasic *) base)->base;
36
37 if (brig_inst->opcode == BRIG_OPCODE_CALL)
38 {
39 const BrigData *operand_entries
40 = m_parent.get_brig_data_entry (brig_inst->operands);
41 tree func_ref = NULL_TREE;
42 vec<tree, va_gc> *out_args;
43 vec_alloc (out_args, 1);
44 vec<tree, va_gc> *in_args;
e1e299f3
HL
45 /* Ten elem initially, more reserved if needed. */
46 vec_alloc (in_args, 10);
5fd1486c
PJ
47
48 size_t operand_count = operand_entries->byteCount / 4;
49 gcc_assert (operand_count < 4);
50
51 for (size_t i = 0; i < operand_count; ++i)
52 {
53 uint32_t operand_offset
54 = ((const uint32_t *) &operand_entries->bytes)[i];
55 const BrigBase *operand_data
56 = m_parent.get_brig_operand_entry (operand_offset);
57 if (i == 1)
58 {
59 gcc_assert (operand_data->kind == BRIG_KIND_OPERAND_CODE_REF);
60 func_ref = build_tree_operand (*brig_inst, *operand_data);
61 continue;
62 }
63 gcc_assert (operand_data->kind == BRIG_KIND_OPERAND_CODE_LIST);
64 const BrigOperandCodeList *codelist
65 = (const BrigOperandCodeList *) operand_data;
66 const BrigData *data
67 = m_parent.get_brig_data_entry (codelist->elements);
68
69 size_t bytes = data->byteCount;
70 const BrigOperandOffset32_t *operand_ptr
71 = (const BrigOperandOffset32_t *) data->bytes;
72
14108eda 73 bool out_args_p = i == 0;
5fd1486c
PJ
74
75 while (bytes > 0)
76 {
77 BrigOperandOffset32_t offset = *operand_ptr;
78 const BrigBase *code_element
79 = m_parent.get_brig_code_entry (offset);
80 gcc_assert (code_element->kind == BRIG_KIND_DIRECTIVE_VARIABLE);
81 const BrigDirectiveVariable *brig_var
82 = (const BrigDirectiveVariable *) code_element;
83 tree var = m_parent.m_cf->arg_variable (brig_var);
84
85 if (brig_var->type & BRIG_TYPE_ARRAY)
86 {
87 /* Array return values are passed as the first argument. */
14108eda 88 out_args_p = false;
5fd1486c
PJ
89 /* Pass pointer to the element zero and use its element zero
90 as the base address. */
91 tree etype = TREE_TYPE (TREE_TYPE (var));
92 tree ptype = build_pointer_type (etype);
93 tree element_zero
94 = build4 (ARRAY_REF, etype, var, integer_zero_node,
95 NULL_TREE, NULL_TREE);
96 var = build1 (ADDR_EXPR, ptype, element_zero);
97 }
98
99 gcc_assert (var != NULL_TREE);
14108eda 100 vec_safe_push (out_args_p ? out_args : in_args, var);
5fd1486c
PJ
101 ++operand_ptr;
102 bytes -= 4;
103 }
104 }
105
106 gcc_assert (func_ref != NULL_TREE);
107 gcc_assert (out_args->length () == 0 || out_args->length () == 1);
108
109 tree ret_val_type = void_type_node;
110 tree ret_val = NULL_TREE;
111 if (out_args->length () == 1)
112 {
113 ret_val = (*out_args)[0];
114 ret_val_type = TREE_TYPE (ret_val);
115 }
116
117 /* Pass the hidden kernel arguments along to the called functions as
118 they might call builtins that need them or access group/private
119 memory. */
120
d4b7f2ee 121 tree group_local_offset
080dc243
PJ
122 = m_parent.m_cf->add_temp_var ("group_local_offset",
123 build_int_cst
124 (uint32_type_node,
125 m_parent.m_cf->
126 m_local_group_variables.size()));
d4b7f2ee
PJ
127
128 /* TODO: ensure the callee's frame is aligned! */
129
e1e299f3 130 vec_safe_reserve (in_args, 4);
5fd1486c
PJ
131 vec_safe_push (in_args, m_parent.m_cf->m_context_arg);
132 vec_safe_push (in_args, m_parent.m_cf->m_group_base_arg);
d4b7f2ee 133 vec_safe_push (in_args, group_local_offset);
5fd1486c
PJ
134 vec_safe_push (in_args, m_parent.m_cf->m_private_base_arg);
135
136 tree call = build_call_vec (ret_val_type, build_fold_addr_expr (func_ref),
137 in_args);
138 TREE_NOTHROW (func_ref) = 1;
139 TREE_NOTHROW (call) = 1;
140
141 if (ret_val != NULL_TREE)
142 {
143 TREE_ADDRESSABLE (ret_val) = 1;
144 tree result_assign
145 = build2 (MODIFY_EXPR, TREE_TYPE (ret_val), ret_val, call);
146 m_parent.m_cf->append_statement (result_assign);
147 }
148 else
149 {
150 m_parent.m_cf->append_statement (call);
151 }
152
5fd1486c 153 m_parent.m_cf->m_called_functions.push_back (func_ref);
637f3cde
PJ
154 if (DECL_EXTERNAL (func_ref))
155 m_parent.add_decl_call (call);
080dc243 156 m_parent.m_cf->start_new_bb ();
5fd1486c
PJ
157
158 return base->byteCount;
159 }
160
161 tree instr_type = gccbrig_tree_type_for_hsa_type (brig_inst->type);
162 tree_stl_vec operands = build_operands (*brig_inst);
163
164 if (brig_inst->opcode == BRIG_OPCODE_BR)
165 {
166 tree goto_stmt = build1 (GOTO_EXPR, instr_type, operands[0]);
167 m_parent.m_cf->append_statement (goto_stmt);
168 }
169 else if (brig_inst->opcode == BRIG_OPCODE_SBR)
170 {
171 tree select = operands[0];
172 tree cases = operands[1];
173
9e851845
JJ
174 tree switch_expr = build2 (SWITCH_EXPR, TREE_TYPE (select), select,
175 NULL_TREE);
5fd1486c
PJ
176
177 tree default_case
178 = build_case_label (NULL_TREE, NULL_TREE,
179 create_artificial_label (UNKNOWN_LOCATION));
180 append_to_statement_list (default_case, &SWITCH_BODY (switch_expr));
181
182 tree default_jump
183 = build1 (GOTO_EXPR, void_type_node, TREE_VEC_ELT (cases, 0));
184 append_to_statement_list (default_jump, &SWITCH_BODY (switch_expr));
185
186 for (int c = 0; c < TREE_VEC_LENGTH (cases); ++c)
187 {
188 tree case_label
189 = build_case_label (build_int_cst (integer_type_node, c), NULL_TREE,
190 create_artificial_label (UNKNOWN_LOCATION));
191
192 append_to_statement_list (case_label, &SWITCH_BODY (switch_expr));
193
194 tree jump
195 = build1 (GOTO_EXPR, void_type_node, TREE_VEC_ELT (cases, c));
196 append_to_statement_list (jump, &SWITCH_BODY (switch_expr));
197 }
198 m_parent.m_cf->append_statement (switch_expr);
199 }
200 else if (brig_inst->opcode == BRIG_OPCODE_CBR)
201 {
202 tree condition = operands[0];
203 tree target_goto = build1 (GOTO_EXPR, void_type_node, operands[1]);
204 /* Represents the if..else as (condition)?(goto foo):(goto bar). */
205 tree if_stmt
206 = build3 (COND_EXPR, void_type_node, condition, target_goto, NULL_TREE);
207 m_parent.m_cf->append_statement (if_stmt);
208 }
209 else if (brig_inst->opcode == BRIG_OPCODE_WAVEBARRIER)
210 {
211 /* WAVEBARRIER is a NOP when WAVESIZE = 1. */
212 }
213 else if (brig_inst->opcode == BRIG_OPCODE_BARRIER)
214 {
215 m_parent.m_cf->m_has_barriers = true;
216 tree_stl_vec call_operands;
217 /* FIXME. We should add attributes (are there suitable ones in gcc?) that
218 ensure the barrier won't be duplicated or moved out of loops etc.
219 Like the 'noduplicate' of LLVM. Same goes for fbarriers. */
220 m_parent.m_cf->append_statement
080dc243
PJ
221 (m_parent.m_cf->expand_or_call_builtin (brig_inst->opcode,
222 BRIG_TYPE_NONE, NULL_TREE,
223 call_operands));
5fd1486c
PJ
224 }
225 else if (brig_inst->opcode >= BRIG_OPCODE_ARRIVEFBAR
226 && brig_inst->opcode <= BRIG_OPCODE_WAITFBAR)
227 {
228 m_parent.m_cf->m_has_barriers = true;
229 m_parent.m_cf->append_statement
080dc243
PJ
230 (m_parent.m_cf->expand_or_call_builtin (brig_inst->opcode,
231 BRIG_TYPE_NONE,
232 uint32_type_node, operands));
5fd1486c
PJ
233 }
234 else
235 gcc_unreachable ();
080dc243 236 m_parent.m_cf->start_new_bb ();
5fd1486c
PJ
237 return base->byteCount;
238}