PR rtl-optimization/79386
[official-gcc.git] / gcc / brig / brigfrontend / brig-mem-inst-handler.cc
blob2b245a11dfeefe7ea8f776dbbc0abb68e1aa742c
1 /* brig-mem-inst-handler.cc -- brig memory inst handler
2 Copyright (C) 2016-2017 Free Software Foundation, Inc.
3 Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
4 for General Processor Tech.
6 This file is part of GCC.
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.
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.
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/>. */
22 #include "brig-code-entry-handler.h"
24 #include "errors.h"
25 #include "brig-util.h"
26 #include "gimple-expr.h"
27 #include "print-tree.h"
28 #include "tree-pretty-print.h"
29 #include "convert.h"
30 #include "diagnostic-core.h"
32 tree
33 brig_mem_inst_handler::build_mem_access (const BrigInstBase *brig_inst,
34 tree addr, tree data)
36 bool is_load = brig_inst->opcode == BRIG_OPCODE_LD;
37 bool is_store = brig_inst->opcode == BRIG_OPCODE_ST;
39 if (!is_load && !is_store)
40 gcc_unreachable ();
42 tree instr_type = gccbrig_tree_type_for_hsa_type (brig_inst->type);
44 if (VECTOR_TYPE_P (TREE_TYPE (data)))
45 instr_type = TREE_TYPE (data);
47 tree ptype = build_pointer_type (instr_type);
49 /* The HSAIL mem instructions are unaligned by default.
50 TODO: exploit the align modifier, it should lead to faster code.
52 tree unaligned_type = build_aligned_type (instr_type, 8);
54 /* Create a mem ref from the previous result, without offset. */
55 tree mem_ref
56 = build2 (MEM_REF, unaligned_type, addr, build_int_cst (ptype, 0));
58 if (is_load)
60 /* Add a temporary variable so there won't be multiple
61 reads in case of vector unpack. */
62 mem_ref = add_temp_var ("mem_read", mem_ref);
63 return build_output_assignment (*brig_inst, data, mem_ref);
65 else
67 tree stmt = build2 (MODIFY_EXPR, TREE_TYPE (mem_ref), mem_ref, data);
68 return m_parent.m_cf->append_statement (stmt);
70 return mem_ref;
73 size_t
74 brig_mem_inst_handler::operator () (const BrigBase *base)
76 const BrigInstBase *brig_inst
77 = (const BrigInstBase *) &((const BrigInstBasic *) base)->base;
79 if (brig_inst->opcode == BRIG_OPCODE_ALLOCA)
81 tree_stl_vec operands = build_operands (*brig_inst);
82 size_t alignment = 1;
83 const BrigInstMem *mem_inst = (const BrigInstMem *) brig_inst;
84 if (mem_inst->align != BRIG_ALIGNMENT_NONE)
86 alignment = 1 << (mem_inst->align - 1);
89 tree align_opr = build_int_cstu (size_type_node, alignment);
90 tree_stl_vec inputs;
91 inputs.push_back (operands[1]);
92 inputs.push_back (align_opr);
93 tree builtin_call
94 = expand_or_call_builtin (BRIG_OPCODE_ALLOCA, BRIG_TYPE_U32,
95 uint32_type_node, inputs);
96 build_output_assignment (*brig_inst, operands[0], builtin_call);
97 m_parent.m_cf->m_has_allocas = true;
98 return base->byteCount;
101 tree instr_type = gccbrig_tree_type_for_hsa_type (brig_inst->type);
103 const BrigData *operand_entries
104 = m_parent.get_brig_data_entry (brig_inst->operands);
106 uint32_t data_operand_offset;
107 memcpy (&data_operand_offset, &operand_entries->bytes, 4);
109 const BrigBase *operand
110 = m_parent.get_brig_operand_entry (data_operand_offset);
112 const BrigData *operandData = NULL;
114 bool is_store = brig_inst->opcode == BRIG_OPCODE_ST;
116 bool is_three_element_vector_access
117 = operand->kind == BRIG_KIND_OPERAND_OPERAND_LIST
118 && (operandData = m_parent.get_brig_data_entry
119 (((const BrigOperandOperandList *) operand)->elements))
120 && operandData->byteCount / 4 == 3;
122 if (is_three_element_vector_access)
124 /* We need to scalarize the 3-element vector accesses here
125 because gcc assumes the GENERIC vector datatypes are of two exponent
126 size internally. */
127 size_t bytes = operandData->byteCount;
128 const BrigOperandOffset32_t *operand_ptr
129 = (const BrigOperandOffset32_t *) operandData->bytes;
131 uint32_t addr_operand_offset;
132 memcpy (&addr_operand_offset, &operand_entries->bytes + 4, 4);
134 const BrigOperandAddress *addr_operand
135 = (const BrigOperandAddress *) m_parent.get_brig_operand_entry
136 (addr_operand_offset);
138 tree address_base = build_address_operand (*brig_inst, *addr_operand);
140 uint32_t address_offset = 0;
141 while (bytes > 0)
143 BrigOperandOffset32_t offset = *operand_ptr;
144 const BrigBase *operand_element
145 = m_parent.get_brig_operand_entry (offset);
146 tree data
147 = build_tree_operand (*brig_inst, *operand_element, instr_type);
149 tree ptr_offset = build_int_cst (size_type_node, address_offset);
150 tree address = build2 (POINTER_PLUS_EXPR, TREE_TYPE (address_base),
151 address_base, ptr_offset);
153 if (is_store && TREE_TYPE (data) != instr_type)
155 if (int_size_in_bytes (TREE_TYPE (data))
156 == int_size_in_bytes (instr_type)
157 && !INTEGRAL_TYPE_P (instr_type))
158 data = build1 (VIEW_CONVERT_EXPR, instr_type, data);
159 else
160 data = convert (instr_type, data);
163 build_mem_access (brig_inst, address, data);
165 address_offset += int_size_in_bytes (instr_type);
166 ++operand_ptr;
167 bytes -= 4;
170 else
172 tree_stl_vec operands = build_operands (*brig_inst);
174 tree &data = operands.at (0);
175 tree &addr = operands.at (1);
176 build_mem_access (brig_inst, addr, data);
179 return base->byteCount;