1 /* brig-mem-inst-handler.cc -- brig memory inst handler
2 Copyright (C) 2016-2018 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
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
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"
25 #include "brig-util.h"
26 #include "gimple-expr.h"
27 #include "print-tree.h"
28 #include "tree-pretty-print.h"
30 #include "diagnostic-core.h"
33 brig_mem_inst_handler::build_mem_access (const BrigInstBase
*brig_inst
,
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
)
42 tree instr_type
= gccbrig_tree_type_for_hsa_type (brig_inst
->type
);
44 /* In case of {ld,st}_v{2,4}. Note: since 'register' variables may
45 be any type, even a vector type, we distinguish the registers
46 from operand lists by checking for constructor nodes (which
47 operand lists are represented as). */
48 if (VECTOR_TYPE_P (TREE_TYPE (data
)) && TREE_CODE (data
) == CONSTRUCTOR
)
49 instr_type
= TREE_TYPE (data
);
51 tree ptype
= build_pointer_type (instr_type
);
53 /* The HSAIL mem instructions are unaligned by default.
54 TODO: exploit the align modifier, it should lead to faster code.
56 tree unaligned_type
= build_aligned_type (instr_type
, 8);
58 /* Create a mem ref from the previous result, without offset. */
60 = build2 (MEM_REF
, unaligned_type
, addr
, build_int_cst (ptype
, 0));
64 /* Add a temporary variable so there won't be multiple
65 reads in case of vector unpack. */
66 mem_ref
= m_parent
.m_cf
->add_temp_var ("mem_read", mem_ref
);
67 return build_output_assignment (*brig_inst
, data
, mem_ref
);
71 tree stmt
= build2 (MODIFY_EXPR
, TREE_TYPE (mem_ref
), mem_ref
, data
);
72 return m_parent
.m_cf
->append_statement (stmt
);
78 brig_mem_inst_handler::operator () (const BrigBase
*base
)
80 const BrigInstBase
*brig_inst
81 = (const BrigInstBase
*) &((const BrigInstBasic
*) base
)->base
;
83 if (brig_inst
->opcode
== BRIG_OPCODE_ALLOCA
)
85 tree_stl_vec operands
= build_operands (*brig_inst
);
87 const BrigInstMem
*mem_inst
= (const BrigInstMem
*) brig_inst
;
88 if (mem_inst
->align
!= BRIG_ALIGNMENT_NONE
)
90 alignment
= 1 << (mem_inst
->align
- 1);
93 tree align_opr
= build_int_cstu (size_type_node
, alignment
);
95 inputs
.push_back (operands
[1]);
96 inputs
.push_back (align_opr
);
98 = m_parent
.m_cf
->expand_or_call_builtin (BRIG_OPCODE_ALLOCA
,
100 uint32_type_node
, inputs
);
101 build_output_assignment (*brig_inst
, operands
[0], builtin_call
);
102 m_parent
.m_cf
->m_has_allocas
= true;
103 return base
->byteCount
;
106 tree instr_type
= gccbrig_tree_type_for_hsa_type (brig_inst
->type
);
108 const BrigData
*operand_entries
109 = m_parent
.get_brig_data_entry (brig_inst
->operands
);
111 uint32_t data_operand_offset
;
112 memcpy (&data_operand_offset
, &operand_entries
->bytes
, 4);
114 const BrigBase
*operand
115 = m_parent
.get_brig_operand_entry (data_operand_offset
);
117 const BrigData
*operandData
= NULL
;
119 bool is_store
= brig_inst
->opcode
== BRIG_OPCODE_ST
;
121 bool is_three_element_vector_access
122 = operand
->kind
== BRIG_KIND_OPERAND_OPERAND_LIST
123 && (operandData
= m_parent
.get_brig_data_entry
124 (((const BrigOperandOperandList
*) operand
)->elements
))
125 && operandData
->byteCount
/ 4 == 3;
127 if (is_three_element_vector_access
)
129 /* We need to scalarize the 3-element vector accesses here
130 because gcc assumes the GENERIC vector datatypes are of two exponent
132 size_t bytes
= operandData
->byteCount
;
133 const BrigOperandOffset32_t
*operand_ptr
134 = (const BrigOperandOffset32_t
*) operandData
->bytes
;
136 uint32_t addr_operand_offset
;
137 memcpy (&addr_operand_offset
, &operand_entries
->bytes
+ 4, 4);
139 const BrigOperandAddress
*addr_operand
140 = (const BrigOperandAddress
*) m_parent
.get_brig_operand_entry
141 (addr_operand_offset
);
143 tree address_base
= build_address_operand (*brig_inst
, *addr_operand
);
145 uint32_t address_offset
= 0;
148 BrigOperandOffset32_t offset
= *operand_ptr
;
149 const BrigBase
*operand_element
150 = m_parent
.get_brig_operand_entry (offset
);
152 = build_tree_operand (*brig_inst
, *operand_element
, instr_type
);
154 tree ptr_offset
= build_int_cst (size_type_node
, address_offset
);
155 tree address
= build2 (POINTER_PLUS_EXPR
, TREE_TYPE (address_base
),
156 address_base
, ptr_offset
);
158 if (is_store
&& TREE_TYPE (data
) != instr_type
)
159 data
= build_resize_convert_view (instr_type
, data
);
161 build_mem_access (brig_inst
, address
, data
);
163 address_offset
+= int_size_in_bytes (instr_type
);
170 tree_stl_vec operands
= build_operands (*brig_inst
);
172 tree
&data
= operands
.at (0);
173 tree
&addr
= operands
.at (1);
174 build_mem_access (brig_inst
, addr
, data
);
177 return base
->byteCount
;