Mercurial > octave-nkf
annotate libinterp/corefcn/jit-typeinfo.cc @ 20654:b65888ec820e draft default tip gccjit
dmalcom gcc jit import
author | Stefan Mahr <dac922@gmx.de> |
---|---|
date | Fri, 27 Feb 2015 16:59:36 +0100 |
parents | d35201e5ce5d |
children |
rev | line source |
---|---|
15016 | 1 /* |
2 | |
19731
4197fc428c7d
maint: Update copyright notices for 2015.
John W. Eaton <jwe@octave.org>
parents:
18840
diff
changeset
|
3 Copyright (C) 2012-2015 Max Brister |
15016 | 4 |
5 This file is part of Octave. | |
6 | |
7 Octave is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by the | |
9 Free Software Foundation; either version 3 of the License, or (at your | |
10 option) any later version. | |
11 | |
12 Octave is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with Octave; see the file COPYING. If not, see | |
19 <http://www.gnu.org/licenses/>. | |
20 | |
21 */ | |
22 | |
16768 | 23 // Author: Max Brister <max@2bass.com> |
24 | |
15016 | 25 // defines required by llvm |
26 #define __STDC_LIMIT_MACROS | |
27 #define __STDC_CONSTANT_MACROS | |
28 | |
29 #ifdef HAVE_CONFIG_H | |
30 #include <config.h> | |
31 #endif | |
32 | |
33 #ifdef HAVE_LLVM | |
34 | |
35 #include "jit-typeinfo.h" | |
36 | |
18840
4a4edf0f2077
fix LLVM 3.4 build (bug #41061)
Stefan Mahr <dac922@gmx.de>
parents:
18446
diff
changeset
|
37 #ifdef HAVE_LLVM_IR_VERIFIER_H |
4a4edf0f2077
fix LLVM 3.4 build (bug #41061)
Stefan Mahr <dac922@gmx.de>
parents:
18446
diff
changeset
|
38 #include <llvm/IR/Verifier.h> |
4a4edf0f2077
fix LLVM 3.4 build (bug #41061)
Stefan Mahr <dac922@gmx.de>
parents:
18446
diff
changeset
|
39 #else |
15016 | 40 #include <llvm/Analysis/Verifier.h> |
18840
4a4edf0f2077
fix LLVM 3.4 build (bug #41061)
Stefan Mahr <dac922@gmx.de>
parents:
18446
diff
changeset
|
41 #endif |
4a4edf0f2077
fix LLVM 3.4 build (bug #41061)
Stefan Mahr <dac922@gmx.de>
parents:
18446
diff
changeset
|
42 |
17164 | 43 #include <llvm/ExecutionEngine/ExecutionEngine.h> |
44 | |
45 #ifdef HAVE_LLVM_IR_FUNCTION_H | |
46 #include <llvm/IR/GlobalVariable.h> | |
47 #include <llvm/IR/LLVMContext.h> | |
48 #include <llvm/IR/Function.h> | |
49 #include <llvm/IR/Instructions.h> | |
50 #include <llvm/IR/Intrinsics.h> | |
51 #else | |
15016 | 52 #include <llvm/GlobalVariable.h> |
53 #include <llvm/LLVMContext.h> | |
54 #include <llvm/Function.h> | |
55 #include <llvm/Instructions.h> | |
56 #include <llvm/Intrinsics.h> | |
17164 | 57 #endif |
58 | |
59 #ifdef HAVE_LLVM_SUPPORT_IRBUILDER_H | |
15016 | 60 #include <llvm/Support/IRBuilder.h> |
17164 | 61 #elif defined(HAVE_LLVM_IR_IRBUILDER_H) |
62 #include <llvm/IR/IRBuilder.h> | |
17031
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
63 #else |
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
64 #include <llvm/IRBuilder.h> |
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
65 #endif |
17164 | 66 |
15016 | 67 #include <llvm/Support/raw_os_ostream.h> |
68 | |
69 #include "jit-ir.h" | |
70 #include "ov.h" | |
71 #include "ov-builtin.h" | |
72 #include "ov-complex.h" | |
73 #include "ov-scalar.h" | |
74 #include "pager.h" | |
75 | |
76 static llvm::LLVMContext& context = llvm::getGlobalContext (); | |
77 | |
78 jit_typeinfo *jit_typeinfo::instance = 0; | |
79 | |
80 std::ostream& jit_print (std::ostream& os, jit_type *atype) | |
81 { | |
82 if (! atype) | |
83 return os << "null"; | |
84 return os << atype->name (); | |
85 } | |
86 | |
87 // function that jit code calls | |
88 extern "C" void | |
89 octave_jit_print_any (const char *name, octave_base_value *obv) | |
90 { | |
91 obv->print_with_name (octave_stdout, name, true); | |
92 } | |
93 | |
94 extern "C" void | |
15019
ae3670d4df29
Update the execution engine's global mapping for external functions
Max Brister <max@2bass.com>
parents:
15016
diff
changeset
|
95 octave_jit_print_scalar (const char *name, double value) |
15016 | 96 { |
97 // FIXME: We should avoid allocating a new octave_scalar each time | |
98 octave_value ov (value); | |
99 ov.print_with_name (octave_stdout, name); | |
100 } | |
101 | |
102 extern "C" octave_base_value* | |
103 octave_jit_binary_any_any (octave_value::binary_op op, octave_base_value *lhs, | |
104 octave_base_value *rhs) | |
105 { | |
106 octave_value olhs (lhs, true); | |
107 octave_value orhs (rhs, true); | |
108 octave_value result = do_binary_op (op, olhs, orhs); | |
109 octave_base_value *rep = result.internal_rep (); | |
110 rep->grab (); | |
111 return rep; | |
112 } | |
113 | |
114 extern "C" octave_idx_type | |
115 octave_jit_compute_nelem (double base, double limit, double inc) | |
116 { | |
117 Range rng = Range (base, limit, inc); | |
20649
d35201e5ce5d
Fix compilation of jit broken by dd6345fd8a97 (bug #46191).
Rik <rik@octave.org>
parents:
20569
diff
changeset
|
118 return rng.numel (); |
15016 | 119 } |
120 | |
121 extern "C" void | |
122 octave_jit_release_any (octave_base_value *obv) | |
123 { | |
124 obv->release (); | |
125 } | |
126 | |
127 extern "C" void | |
128 octave_jit_release_matrix (jit_matrix *m) | |
129 { | |
130 delete m->array; | |
131 } | |
132 | |
133 extern "C" octave_base_value * | |
134 octave_jit_grab_any (octave_base_value *obv) | |
135 { | |
136 obv->grab (); | |
137 return obv; | |
138 } | |
139 | |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
140 extern "C" jit_matrix |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
141 octave_jit_grab_matrix (jit_matrix *m) |
15016 | 142 { |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
143 return *m->array; |
15016 | 144 } |
145 | |
146 extern "C" octave_base_value * | |
147 octave_jit_cast_any_matrix (jit_matrix *m) | |
148 { | |
149 octave_value ret (*m->array); | |
150 octave_base_value *rep = ret.internal_rep (); | |
151 rep->grab (); | |
152 delete m->array; | |
153 | |
154 return rep; | |
155 } | |
156 | |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
157 extern "C" jit_matrix |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
158 octave_jit_cast_matrix_any (octave_base_value *obv) |
15016 | 159 { |
160 NDArray m = obv->array_value (); | |
161 obv->release (); | |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
162 return m; |
15016 | 163 } |
164 | |
15027
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
165 extern "C" octave_base_value * |
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
166 octave_jit_cast_any_range (jit_range *rng) |
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
167 { |
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
168 Range temp (*rng); |
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
169 octave_value ret (temp); |
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
170 octave_base_value *rep = ret.internal_rep (); |
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
171 rep->grab (); |
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
172 |
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
173 return rep; |
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
174 } |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
175 extern "C" jit_range |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
176 octave_jit_cast_range_any (octave_base_value *obv) |
15027
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
177 { |
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
178 |
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
179 jit_range r (obv->range_value ()); |
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
180 obv->release (); |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
181 return r; |
15027
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
182 } |
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
183 |
15016 | 184 extern "C" double |
185 octave_jit_cast_scalar_any (octave_base_value *obv) | |
186 { | |
187 double ret = obv->double_value (); | |
188 obv->release (); | |
189 return ret; | |
190 } | |
191 | |
192 extern "C" octave_base_value * | |
193 octave_jit_cast_any_scalar (double value) | |
194 { | |
195 return new octave_scalar (value); | |
196 } | |
197 | |
198 extern "C" Complex | |
199 octave_jit_cast_complex_any (octave_base_value *obv) | |
200 { | |
201 Complex ret = obv->complex_value (); | |
202 obv->release (); | |
203 return ret; | |
204 } | |
205 | |
206 extern "C" octave_base_value * | |
207 octave_jit_cast_any_complex (Complex c) | |
208 { | |
209 if (c.imag () == 0) | |
210 return new octave_scalar (c.real ()); | |
211 else | |
212 return new octave_complex (c); | |
213 } | |
214 | |
215 extern "C" void | |
216 octave_jit_gripe_nan_to_logical_conversion (void) | |
217 { | |
20569
b70cc4bd8109
begin removal of global error_state variable
John W. Eaton <jwe@octave.org>
parents:
20263
diff
changeset
|
218 gripe_nan_to_logical_conversion (); |
15016 | 219 } |
220 | |
221 extern "C" void | |
222 octave_jit_ginvalid_index (void) | |
223 { | |
20649
d35201e5ce5d
Fix compilation of jit broken by dd6345fd8a97 (bug #46191).
Rik <rik@octave.org>
parents:
20569
diff
changeset
|
224 // FIXME: 0-argument form of gripe_invalid_index removed in cset dd6345fd8a97 |
d35201e5ce5d
Fix compilation of jit broken by dd6345fd8a97 (bug #46191).
Rik <rik@octave.org>
parents:
20569
diff
changeset
|
225 // Report -1 as the bad index for all occurrences. |
d35201e5ce5d
Fix compilation of jit broken by dd6345fd8a97 (bug #46191).
Rik <rik@octave.org>
parents:
20569
diff
changeset
|
226 gripe_invalid_index (-1); |
15016 | 227 } |
228 | |
229 extern "C" void | |
230 octave_jit_gindex_range (int nd, int dim, octave_idx_type iext, | |
231 octave_idx_type ext) | |
232 { | |
20569
b70cc4bd8109
begin removal of global error_state variable
John W. Eaton <jwe@octave.org>
parents:
20263
diff
changeset
|
233 gripe_index_out_of_range (nd, dim, iext, ext); |
15016 | 234 } |
235 | |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
236 extern "C" jit_matrix |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
237 octave_jit_paren_subsasgn_impl (jit_matrix *mat, octave_idx_type index, |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
238 double value) |
15016 | 239 { |
240 NDArray *array = mat->array; | |
20263
00cf2847355d
Deprecate Array::nelem() and Range::nelem() in favour of ::numel().
Carnë Draug <carandraug@octave.org>
parents:
19731
diff
changeset
|
241 if (array->numel () < index) |
15016 | 242 array->resize1 (index); |
243 | |
244 double *data = array->fortran_vec (); | |
245 data[index - 1] = value; | |
246 | |
247 mat->update (); | |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
248 return *mat; |
15016 | 249 } |
250 | |
15068
f57d7578c1a6
Support ND matrix indexing with scalar assignment in JIT.
Max Brister <max@2bass.com>
parents:
15067
diff
changeset
|
251 static void |
f57d7578c1a6
Support ND matrix indexing with scalar assignment in JIT.
Max Brister <max@2bass.com>
parents:
15067
diff
changeset
|
252 make_indices (double *indices, octave_idx_type idx_count, |
f57d7578c1a6
Support ND matrix indexing with scalar assignment in JIT.
Max Brister <max@2bass.com>
parents:
15067
diff
changeset
|
253 Array<idx_vector>& result) |
f57d7578c1a6
Support ND matrix indexing with scalar assignment in JIT.
Max Brister <max@2bass.com>
parents:
15067
diff
changeset
|
254 { |
f57d7578c1a6
Support ND matrix indexing with scalar assignment in JIT.
Max Brister <max@2bass.com>
parents:
15067
diff
changeset
|
255 result.resize (dim_vector (1, idx_count)); |
f57d7578c1a6
Support ND matrix indexing with scalar assignment in JIT.
Max Brister <max@2bass.com>
parents:
15067
diff
changeset
|
256 for (octave_idx_type i = 0; i < idx_count; ++i) |
f57d7578c1a6
Support ND matrix indexing with scalar assignment in JIT.
Max Brister <max@2bass.com>
parents:
15067
diff
changeset
|
257 result(i) = idx_vector (indices[i]); |
f57d7578c1a6
Support ND matrix indexing with scalar assignment in JIT.
Max Brister <max@2bass.com>
parents:
15067
diff
changeset
|
258 } |
f57d7578c1a6
Support ND matrix indexing with scalar assignment in JIT.
Max Brister <max@2bass.com>
parents:
15067
diff
changeset
|
259 |
15067 | 260 extern "C" double |
261 octave_jit_paren_scalar (jit_matrix *mat, double *indicies, | |
262 octave_idx_type idx_count) | |
263 { | |
264 // FIXME: Replace this with a more optimal version | |
20569
b70cc4bd8109
begin removal of global error_state variable
John W. Eaton <jwe@octave.org>
parents:
20263
diff
changeset
|
265 Array<idx_vector> idx; |
b70cc4bd8109
begin removal of global error_state variable
John W. Eaton <jwe@octave.org>
parents:
20263
diff
changeset
|
266 make_indices (indicies, idx_count, idx); |
15067 | 267 |
20569
b70cc4bd8109
begin removal of global error_state variable
John W. Eaton <jwe@octave.org>
parents:
20263
diff
changeset
|
268 Array<double> ret = mat->array->index (idx); |
b70cc4bd8109
begin removal of global error_state variable
John W. Eaton <jwe@octave.org>
parents:
20263
diff
changeset
|
269 |
b70cc4bd8109
begin removal of global error_state variable
John W. Eaton <jwe@octave.org>
parents:
20263
diff
changeset
|
270 return ret.xelem (0); |
15067 | 271 } |
272 | |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
273 extern "C" jit_matrix |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
274 octave_jit_paren_scalar_subsasgn (jit_matrix *mat, double *indices, |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
275 octave_idx_type idx_count, double value) |
15068
f57d7578c1a6
Support ND matrix indexing with scalar assignment in JIT.
Max Brister <max@2bass.com>
parents:
15067
diff
changeset
|
276 { |
f57d7578c1a6
Support ND matrix indexing with scalar assignment in JIT.
Max Brister <max@2bass.com>
parents:
15067
diff
changeset
|
277 // FIXME: Replace this with a more optimal version |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
278 jit_matrix ret; |
20569
b70cc4bd8109
begin removal of global error_state variable
John W. Eaton <jwe@octave.org>
parents:
20263
diff
changeset
|
279 |
b70cc4bd8109
begin removal of global error_state variable
John W. Eaton <jwe@octave.org>
parents:
20263
diff
changeset
|
280 Array<idx_vector> idx; |
b70cc4bd8109
begin removal of global error_state variable
John W. Eaton <jwe@octave.org>
parents:
20263
diff
changeset
|
281 make_indices (indices, idx_count, idx); |
15068
f57d7578c1a6
Support ND matrix indexing with scalar assignment in JIT.
Max Brister <max@2bass.com>
parents:
15067
diff
changeset
|
282 |
20569
b70cc4bd8109
begin removal of global error_state variable
John W. Eaton <jwe@octave.org>
parents:
20263
diff
changeset
|
283 Matrix temp (1, 1); |
b70cc4bd8109
begin removal of global error_state variable
John W. Eaton <jwe@octave.org>
parents:
20263
diff
changeset
|
284 temp.xelem(0) = value; |
b70cc4bd8109
begin removal of global error_state variable
John W. Eaton <jwe@octave.org>
parents:
20263
diff
changeset
|
285 mat->array->assign (idx, temp); |
b70cc4bd8109
begin removal of global error_state variable
John W. Eaton <jwe@octave.org>
parents:
20263
diff
changeset
|
286 ret.update (mat->array); |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
287 |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
288 return ret; |
15068
f57d7578c1a6
Support ND matrix indexing with scalar assignment in JIT.
Max Brister <max@2bass.com>
parents:
15067
diff
changeset
|
289 } |
f57d7578c1a6
Support ND matrix indexing with scalar assignment in JIT.
Max Brister <max@2bass.com>
parents:
15067
diff
changeset
|
290 |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
291 extern "C" jit_matrix |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
292 octave_jit_paren_subsasgn_matrix_range (jit_matrix *mat, jit_range *index, |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
293 double value) |
15016 | 294 { |
295 NDArray *array = mat->array; | |
296 bool done = false; | |
297 | |
298 // optimize for the simple case (no resizing and no errors) | |
299 if (*array->jit_ref_count () == 1 | |
300 && index->all_elements_are_ints ()) | |
301 { | |
302 // this code is similar to idx_vector::fill, but we avoid allocating an | |
303 // idx_vector and its associated rep | |
304 octave_idx_type start = static_cast<octave_idx_type> (index->base) - 1; | |
305 octave_idx_type step = static_cast<octave_idx_type> (index->inc); | |
306 octave_idx_type nelem = index->nelem; | |
307 octave_idx_type final = start + nelem * step; | |
308 if (step < 0) | |
309 { | |
310 step = -step; | |
311 std::swap (final, start); | |
312 } | |
313 | |
314 if (start >= 0 && final < mat->slice_len) | |
315 { | |
316 done = true; | |
317 | |
318 double *data = array->jit_slice_data (); | |
319 if (step == 1) | |
320 std::fill (data + start, data + start + nelem, value); | |
321 else | |
322 { | |
323 for (octave_idx_type i = start; i < final; i += step) | |
324 data[i] = value; | |
325 } | |
326 } | |
327 } | |
328 | |
329 if (! done) | |
330 { | |
331 idx_vector idx (*index); | |
332 NDArray avalue (dim_vector (1, 1)); | |
333 avalue.xelem (0) = value; | |
334 array->assign (idx, avalue); | |
335 } | |
336 | |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
337 jit_matrix ret; |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
338 ret.update (array); |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
339 return ret; |
15016 | 340 } |
341 | |
15102
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
342 extern "C" double |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
343 octave_jit_end_matrix (jit_matrix *mat, octave_idx_type idx, |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
344 octave_idx_type count) |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
345 { |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
346 octave_idx_type ndim = mat->dimensions[-1]; |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
347 if (ndim == count) |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
348 return mat->dimensions[idx]; |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
349 else if (ndim > count) |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
350 { |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
351 if (idx == count - 1) |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
352 { |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
353 double ret = mat->dimensions[idx]; |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
354 for (octave_idx_type i = idx + 1; i < ndim; ++i) |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
355 ret *= mat->dimensions[idx]; |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
356 return ret; |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
357 } |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
358 |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
359 return mat->dimensions[idx]; |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
360 } |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
361 else // ndim < count |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
362 return idx < ndim ? mat->dimensions[idx] : 1; |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
363 } |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
364 |
15337
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
365 extern "C" octave_base_value * |
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
366 octave_jit_create_undef (void) |
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
367 { |
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
368 octave_value undef; |
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
369 octave_base_value *ret = undef.internal_rep (); |
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
370 ret->grab (); |
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
371 |
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
372 return ret; |
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
373 } |
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
374 |
15016 | 375 extern "C" Complex |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
376 octave_jit_complex_mul (Complex lhs, Complex rhs) |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
377 { |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
378 if (lhs.imag () == 0 && rhs.imag() == 0) |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
379 return Complex (lhs.real () * rhs.real (), 0); |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
380 |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
381 return lhs * rhs; |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
382 } |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
383 |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
384 extern "C" Complex |
15016 | 385 octave_jit_complex_div (Complex lhs, Complex rhs) |
386 { | |
387 // see src/OPERATORS/op-cs-cs.cc | |
388 if (rhs == 0.0) | |
389 gripe_divide_by_zero (); | |
390 | |
391 return lhs / rhs; | |
392 } | |
393 | |
394 // FIXME: CP form src/xpow.cc | |
395 static inline int | |
396 xisint (double x) | |
397 { | |
398 return (D_NINT (x) == x | |
15215
9020dddc925a
use std::numeric_limits for integer max and min values
John W. Eaton <jwe@octave.org>
parents:
15195
diff
changeset
|
399 && ((x >= 0 && x < std::numeric_limits<int>::max ()) |
15219
aeba1adfd76b
Correct small typo in jit-typeinfo.cc
Melvin Robinson <melvin.robinson@mavs.uta.edu>
parents:
15215
diff
changeset
|
400 || (x <= 0 && x > std::numeric_limits<int>::min ()))); |
15016 | 401 } |
402 | |
403 extern "C" Complex | |
404 octave_jit_pow_scalar_scalar (double lhs, double rhs) | |
405 { | |
406 // FIXME: almost CP from src/xpow.cc | |
407 if (lhs < 0.0 && ! xisint (rhs)) | |
408 return std::pow (Complex (lhs), rhs); | |
409 return std::pow (lhs, rhs); | |
410 } | |
411 | |
412 extern "C" Complex | |
413 octave_jit_pow_complex_complex (Complex lhs, Complex rhs) | |
414 { | |
415 if (lhs.imag () == 0 && rhs.imag () == 0) | |
416 return octave_jit_pow_scalar_scalar (lhs.real (), rhs.real ()); | |
417 return std::pow (lhs, rhs); | |
418 } | |
419 | |
420 extern "C" Complex | |
421 octave_jit_pow_complex_scalar (Complex lhs, double rhs) | |
422 { | |
423 if (lhs.imag () == 0) | |
424 return octave_jit_pow_scalar_scalar (lhs.real (), rhs); | |
425 return std::pow (lhs, rhs); | |
426 } | |
427 | |
428 extern "C" Complex | |
429 octave_jit_pow_scalar_complex (double lhs, Complex rhs) | |
430 { | |
431 if (rhs.imag () == 0) | |
432 return octave_jit_pow_scalar_scalar (lhs, rhs.real ()); | |
433 return std::pow (lhs, rhs); | |
434 } | |
435 | |
436 extern "C" void | |
437 octave_jit_print_matrix (jit_matrix *m) | |
438 { | |
439 std::cout << *m << std::endl; | |
440 } | |
441 | |
442 static void | |
443 gripe_bad_result (void) | |
444 { | |
445 error ("incorrect type information given to the JIT compiler"); | |
446 } | |
447 | |
448 // FIXME: Add support for multiple outputs | |
449 extern "C" octave_base_value * | |
450 octave_jit_call (octave_builtin::fcn fn, size_t nargin, | |
451 octave_base_value **argin, jit_type *result_type) | |
452 { | |
453 octave_value_list ovl (nargin); | |
454 for (size_t i = 0; i < nargin; ++i) | |
455 ovl.xelem (i) = octave_value (argin[i]); | |
456 | |
457 ovl = fn (ovl, 1); | |
458 | |
15169
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
459 // FIXME: Check result_type somehow |
15016 | 460 if (result_type) |
461 { | |
15169
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
462 if (ovl.length () < 1) |
15016 | 463 { |
464 gripe_bad_result (); | |
465 return 0; | |
466 } | |
467 | |
15169
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
468 octave_value result = ovl.xelem(0); |
15016 | 469 octave_base_value *ret = result.internal_rep (); |
470 ret->grab (); | |
471 return ret; | |
472 } | |
473 | |
474 if (! (ovl.length () == 0 | |
475 || (ovl.length () == 1 && ovl.xelem (0).is_undefined ()))) | |
476 gripe_bad_result (); | |
477 | |
478 return 0; | |
479 } | |
480 | |
481 // -------------------- jit_range -------------------- | |
482 bool | |
483 jit_range::all_elements_are_ints () const | |
484 { | |
485 Range r (*this); | |
486 return r.all_elements_are_ints (); | |
487 } | |
488 | |
489 std::ostream& | |
490 operator<< (std::ostream& os, const jit_range& rng) | |
491 { | |
492 return os << "Range[" << rng.base << ", " << rng.limit << ", " << rng.inc | |
17787
175b392e91fe
Use GNU style coding conventions for code in libinterp/
Rik <rik@octave.org>
parents:
17744
diff
changeset
|
493 << ", " << rng.nelem << "]"; |
15016 | 494 } |
495 | |
496 // -------------------- jit_matrix -------------------- | |
497 | |
498 std::ostream& | |
499 operator<< (std::ostream& os, const jit_matrix& mat) | |
500 { | |
501 return os << "Matrix[" << mat.ref_count << ", " << mat.slice_data << ", " | |
17787
175b392e91fe
Use GNU style coding conventions for code in libinterp/
Rik <rik@octave.org>
parents:
17744
diff
changeset
|
502 << mat.slice_len << ", " << mat.dimensions << ", " |
175b392e91fe
Use GNU style coding conventions for code in libinterp/
Rik <rik@octave.org>
parents:
17744
diff
changeset
|
503 << mat.array << "]"; |
15016 | 504 } |
505 | |
506 // -------------------- jit_type -------------------- | |
20654 | 507 jit_type::jit_type (const std::string& aname, jit_type *aparent |
508 #ifdef HAVE_LLVM | |
509 , llvm::Type *allvm_type | |
510 #endif | |
511 #ifdef HAVE_GCCJIT | |
512 , gccjit::type agcc_type | |
513 #endif | |
514 , bool askip_paren, int aid) : | |
515 mname (aname), mparent (aparent) | |
516 #ifdef HAVE_LLVM | |
517 , llvm_type (allvm_type) | |
518 #endif | |
519 #ifdef HAVE_GCCJIT | |
520 , gccjit_type (agcc_type) | |
521 #endif | |
522 , mid (aid), | |
15124
0464e3ceb85b
Skip functions when resolving end context in JIT
Max Brister <max@2bass.com>
parents:
15102
diff
changeset
|
523 mdepth (aparent ? aparent->mdepth + 1 : 0), mskip_paren (askip_paren) |
15016 | 524 { |
525 std::memset (msret, 0, sizeof (msret)); | |
526 std::memset (mpointer_arg, 0, sizeof (mpointer_arg)); | |
527 std::memset (mpack, 0, sizeof (mpack)); | |
528 std::memset (munpack, 0, sizeof (munpack)); | |
529 | |
530 for (size_t i = 0; i < jit_convention::length; ++i) | |
531 mpacked_type[i] = llvm_type; | |
532 } | |
533 | |
534 llvm::Type * | |
535 jit_type::to_llvm_arg (void) const | |
536 { | |
537 return llvm_type ? llvm_type->getPointerTo () : 0; | |
538 } | |
539 | |
540 // -------------------- jit_function -------------------- | |
20654 | 541 jit_function::jit_function () : module (0), llvm_function (0), |
542 #ifdef HAVE_GCCJIT | |
543 gccjit_function (), | |
544 #endif | |
545 mresult (0), | |
15016 | 546 call_conv (jit_convention::length), |
547 mcan_error (false) | |
548 {} | |
549 | |
550 jit_function::jit_function (llvm::Module *amodule, | |
20654 | 551 #ifdef HAVE_GCCJIT |
552 gccjit::context gccjit_ctxt, | |
553 #endif | |
15016 | 554 jit_convention::type acall_conv, |
20654 | 555 std::string aname, jit_type *aresult, |
15016 | 556 const std::vector<jit_type *>& aargs) |
557 : module (amodule), mresult (aresult), args (aargs), call_conv (acall_conv), | |
558 mcan_error (false) | |
559 { | |
560 llvm::SmallVector<llvm::Type *, 15> llvm_args; | |
561 | |
562 llvm::Type *rtype = llvm::Type::getVoidTy (context); | |
563 if (mresult) | |
564 { | |
565 rtype = mresult->packed_type (call_conv); | |
566 if (sret ()) | |
567 { | |
568 llvm_args.push_back (rtype->getPointerTo ()); | |
569 rtype = llvm::Type::getVoidTy (context); | |
570 } | |
571 } | |
572 | |
573 for (std::vector<jit_type *>::const_iterator iter = args.begin (); | |
574 iter != args.end (); ++iter) | |
575 { | |
576 jit_type *ty = *iter; | |
577 assert (ty); | |
578 llvm::Type *argty = ty->packed_type (call_conv); | |
579 if (ty->pointer_arg (call_conv)) | |
580 argty = argty->getPointerTo (); | |
581 | |
582 llvm_args.push_back (argty); | |
583 } | |
584 | |
585 // we mark all functinos as external linkage because this prevents llvm | |
586 // from getting rid of always inline functions | |
587 llvm::FunctionType *ft = llvm::FunctionType::get (rtype, llvm_args, false); | |
588 llvm_function = llvm::Function::Create (ft, llvm::Function::ExternalLinkage, | |
589 aname, module); | |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
590 |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
591 if (sret ()) |
17031
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
592 { |
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
593 #ifdef FUNCTION_ADDATTRIBUTE_ARG_IS_ATTRIBUTES |
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
594 llvm::AttrBuilder attr_builder; |
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
595 attr_builder.addAttribute (llvm::Attributes::StructRet); |
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
596 llvm::Attributes attrs = llvm::Attributes::get(context, attr_builder); |
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
597 llvm_function->addAttribute (1, attrs); |
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
598 #else |
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
599 llvm_function->addAttribute (1, llvm::Attribute::StructRet); |
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
600 #endif |
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
601 } |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
602 |
15016 | 603 if (call_conv == jit_convention::internal) |
17031
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
604 #ifdef FUNCTION_ADDFNATTR_ARG_IS_ATTRIBUTES |
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
605 llvm_function->addFnAttr (llvm::Attributes::AlwaysInline); |
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
606 #else |
15016 | 607 llvm_function->addFnAttr (llvm::Attribute::AlwaysInline); |
17031
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
608 #endif |
20654 | 609 |
610 #ifdef HAVE_GCCJIT | |
611 if (gccjit_ctxt.get_inner_context ()) | |
612 { | |
613 std::vector<gccjit::param> gccjit_params; | |
614 for (int i = 0; i < args.size (); i++) | |
615 { | |
616 jit_type *ty = args[i]; | |
617 assert (ty); | |
618 | |
619 gccjit::type argty = ty->to_gccjit (); | |
620 if (ty->pointer_arg (call_conv)) | |
621 argty = argty.get_pointer (); | |
622 | |
623 std::stringstream paramname; | |
624 paramname << "arg" << i; | |
625 | |
626 gccjit::param param = gccjit_ctxt.new_param (argty, | |
627 paramname.str ()); | |
628 gccjit_params.push_back (param); | |
629 } | |
630 gccjit::type gccjit_return_type; | |
631 if (aresult) | |
632 gccjit_return_type = aresult->to_gccjit (); | |
633 else | |
634 gccjit_return_type = gccjit_ctxt.get_type (GCC_JIT_TYPE_VOID); | |
635 | |
636 enum gcc_jit_function_kind kind; | |
637 if (acall_conv == jit_convention::external) | |
638 kind = GCC_JIT_FUNCTION_IMPORTED; | |
639 else | |
640 { | |
641 if (0) | |
642 /* Doing this is correct, but makes the dump a little harder | |
643 to read. | |
644 Also, not fully implemented yet in libgccjit. */ | |
645 kind = GCC_JIT_FUNCTION_ALWAYS_INLINE; | |
646 else | |
647 kind = GCC_JIT_FUNCTION_EXPORTED; | |
648 } | |
649 gccjit_function = | |
650 gccjit_ctxt.new_function (kind, | |
651 gccjit_return_type, | |
652 aname, | |
653 gccjit_params, | |
654 0); | |
655 } | |
656 #endif | |
15016 | 657 } |
658 | |
659 jit_function::jit_function (const jit_function& fn, jit_type *aresult, | |
660 const std::vector<jit_type *>& aargs) | |
20654 | 661 : module (fn.module), |
662 llvm_function (fn.llvm_function), | |
663 #ifdef HAVE_GCCJIT | |
664 gccjit_function (fn.gccjit_function), | |
665 #endif | |
666 mresult (aresult), | |
15016 | 667 args (aargs), call_conv (fn.call_conv), mcan_error (fn.mcan_error) |
668 { | |
669 } | |
670 | |
671 jit_function::jit_function (const jit_function& fn) | |
20654 | 672 : module (fn.module), |
673 llvm_function (fn.llvm_function), | |
674 #ifdef HAVE_GCCJIT | |
675 gccjit_function (fn.gccjit_function), | |
676 #endif | |
677 mresult (fn.mresult), | |
15016 | 678 args (fn.args), call_conv (fn.call_conv), mcan_error (fn.mcan_error) |
679 {} | |
680 | |
15385
8ccb187b24e9
Erase partially created functions on JIT compilation failure (bug #37308)
Max Brister <max@2bass.com>
parents:
15370
diff
changeset
|
681 void |
8ccb187b24e9
Erase partially created functions on JIT compilation failure (bug #37308)
Max Brister <max@2bass.com>
parents:
15370
diff
changeset
|
682 jit_function::erase (void) |
8ccb187b24e9
Erase partially created functions on JIT compilation failure (bug #37308)
Max Brister <max@2bass.com>
parents:
15370
diff
changeset
|
683 { |
8ccb187b24e9
Erase partially created functions on JIT compilation failure (bug #37308)
Max Brister <max@2bass.com>
parents:
15370
diff
changeset
|
684 if (! llvm_function) |
8ccb187b24e9
Erase partially created functions on JIT compilation failure (bug #37308)
Max Brister <max@2bass.com>
parents:
15370
diff
changeset
|
685 return; |
8ccb187b24e9
Erase partially created functions on JIT compilation failure (bug #37308)
Max Brister <max@2bass.com>
parents:
15370
diff
changeset
|
686 |
8ccb187b24e9
Erase partially created functions on JIT compilation failure (bug #37308)
Max Brister <max@2bass.com>
parents:
15370
diff
changeset
|
687 llvm_function->eraseFromParent (); |
8ccb187b24e9
Erase partially created functions on JIT compilation failure (bug #37308)
Max Brister <max@2bass.com>
parents:
15370
diff
changeset
|
688 llvm_function = 0; |
8ccb187b24e9
Erase partially created functions on JIT compilation failure (bug #37308)
Max Brister <max@2bass.com>
parents:
15370
diff
changeset
|
689 } |
8ccb187b24e9
Erase partially created functions on JIT compilation failure (bug #37308)
Max Brister <max@2bass.com>
parents:
15370
diff
changeset
|
690 |
15016 | 691 std::string |
692 jit_function::name (void) const | |
693 { | |
694 return llvm_function->getName (); | |
695 } | |
696 | |
697 llvm::BasicBlock * | |
698 jit_function::new_block (const std::string& aname, | |
699 llvm::BasicBlock *insert_before) | |
700 { | |
701 return llvm::BasicBlock::Create (context, aname, llvm_function, | |
702 insert_before); | |
703 } | |
704 | |
705 llvm::Value * | |
706 jit_function::call (llvm::IRBuilderD& builder, | |
707 const std::vector<jit_value *>& in_args) const | |
708 { | |
15056
bc32288f4a42
Support the end keyword for one dimentional indexing in JIT.
Max Brister <max@2bass.com>
parents:
15027
diff
changeset
|
709 if (! valid ()) |
bc32288f4a42
Support the end keyword for one dimentional indexing in JIT.
Max Brister <max@2bass.com>
parents:
15027
diff
changeset
|
710 throw jit_fail_exception ("Call not implemented"); |
bc32288f4a42
Support the end keyword for one dimentional indexing in JIT.
Max Brister <max@2bass.com>
parents:
15027
diff
changeset
|
711 |
15016 | 712 assert (in_args.size () == args.size ()); |
713 std::vector<llvm::Value *> llvm_args (args.size ()); | |
714 for (size_t i = 0; i < in_args.size (); ++i) | |
715 llvm_args[i] = in_args[i]->to_llvm (); | |
716 | |
717 return call (builder, llvm_args); | |
718 } | |
719 | |
720 llvm::Value * | |
721 jit_function::call (llvm::IRBuilderD& builder, | |
722 const std::vector<llvm::Value *>& in_args) const | |
723 { | |
15056
bc32288f4a42
Support the end keyword for one dimentional indexing in JIT.
Max Brister <max@2bass.com>
parents:
15027
diff
changeset
|
724 if (! valid ()) |
bc32288f4a42
Support the end keyword for one dimentional indexing in JIT.
Max Brister <max@2bass.com>
parents:
15027
diff
changeset
|
725 throw jit_fail_exception ("Call not implemented"); |
bc32288f4a42
Support the end keyword for one dimentional indexing in JIT.
Max Brister <max@2bass.com>
parents:
15027
diff
changeset
|
726 |
15016 | 727 assert (in_args.size () == args.size ()); |
728 llvm::SmallVector<llvm::Value *, 10> llvm_args; | |
729 llvm_args.reserve (in_args.size () + sret ()); | |
730 | |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
731 llvm::BasicBlock *insert_block = builder.GetInsertBlock (); |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
732 llvm::Function *parent = insert_block->getParent (); |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
733 assert (parent); |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
734 |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
735 // we insert allocas inside the prelude block to prevent stack overflows |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
736 llvm::BasicBlock& prelude = parent->getEntryBlock (); |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
737 llvm::IRBuilder<> pre_builder (&prelude, prelude.begin ()); |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
738 |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
739 llvm::AllocaInst *sret_mem = 0; |
15016 | 740 if (sret ()) |
741 { | |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
742 sret_mem = pre_builder.CreateAlloca (mresult->packed_type (call_conv)); |
15016 | 743 llvm_args.push_back (sret_mem); |
744 } | |
745 | |
746 for (size_t i = 0; i < in_args.size (); ++i) | |
747 { | |
748 llvm::Value *arg = in_args[i]; | |
749 jit_type::convert_fn convert = args[i]->pack (call_conv); | |
750 if (convert) | |
751 arg = convert (builder, arg); | |
752 | |
753 if (args[i]->pointer_arg (call_conv)) | |
754 { | |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
755 llvm::Type *ty = args[i]->packed_type (call_conv); |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
756 llvm::Value *alloca = pre_builder.CreateAlloca (ty); |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
757 builder.CreateStore (arg, alloca); |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
758 arg = alloca; |
15016 | 759 } |
760 | |
761 llvm_args.push_back (arg); | |
762 } | |
763 | |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
764 llvm::CallInst *callinst = builder.CreateCall (llvm_function, llvm_args); |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
765 llvm::Value *ret = callinst; |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
766 |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
767 if (sret ()) |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
768 { |
17031
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
769 #ifdef CALLINST_ADDATTRIBUTE_ARG_IS_ATTRIBUTES |
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
770 llvm::AttrBuilder attr_builder; |
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
771 attr_builder.addAttribute(llvm::Attributes::StructRet); |
17787
175b392e91fe
Use GNU style coding conventions for code in libinterp/
Rik <rik@octave.org>
parents:
17744
diff
changeset
|
772 llvm::Attributes attrs = llvm::Attributes::get(context, attr_builder); |
17031
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
773 callinst->addAttribute (1, attrs); |
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
774 #else |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
775 callinst->addAttribute (1, llvm::Attribute::StructRet); |
17031
38bcfd413db0
Handle LLVM API incoherence. Octave now works with LLVM 3.0, 3.1, and 3.2
LYH <lyh.kernel@gmail.com>
parents:
16892
diff
changeset
|
776 #endif |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
777 ret = builder.CreateLoad (sret_mem); |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
778 } |
15016 | 779 |
780 if (mresult) | |
781 { | |
782 jit_type::convert_fn unpack = mresult->unpack (call_conv); | |
783 if (unpack) | |
784 ret = unpack (builder, ret); | |
785 } | |
786 | |
787 return ret; | |
788 } | |
789 | |
790 llvm::Value * | |
791 jit_function::argument (llvm::IRBuilderD& builder, size_t idx) const | |
792 { | |
793 assert (idx < args.size ()); | |
794 | |
795 // FIXME: We should be treating arguments like a list, not a vector. Shouldn't | |
796 // matter much for now, as the number of arguments shouldn't be much bigger | |
797 // than 4 | |
798 llvm::Function::arg_iterator iter = llvm_function->arg_begin (); | |
799 if (sret ()) | |
800 ++iter; | |
801 | |
802 for (size_t i = 0; i < idx; ++i, ++iter); | |
803 | |
804 if (args[idx]->pointer_arg (call_conv)) | |
805 return builder.CreateLoad (iter); | |
806 | |
807 return iter; | |
808 } | |
809 | |
810 void | |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
811 jit_function::do_return (llvm::IRBuilderD& builder, llvm::Value *rval, |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
812 bool verify) |
15016 | 813 { |
814 assert (! rval == ! mresult); | |
815 | |
816 if (rval) | |
817 { | |
818 jit_type::convert_fn convert = mresult->pack (call_conv); | |
819 if (convert) | |
820 rval = convert (builder, rval); | |
821 | |
822 if (sret ()) | |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
823 { |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
824 builder.CreateStore (rval, llvm_function->arg_begin ()); |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
825 builder.CreateRetVoid (); |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
826 } |
15016 | 827 else |
828 builder.CreateRet (rval); | |
829 } | |
830 else | |
831 builder.CreateRetVoid (); | |
832 | |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
833 if (verify) |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
834 llvm::verifyFunction (*llvm_function); |
20654 | 835 |
836 if (0) | |
837 { | |
838 std::cout << "-------------------- llvm ir (at do_return) --------------------"; | |
839 std::cout << *llvm_function << std::endl; | |
840 } | |
15016 | 841 } |
842 | |
20654 | 843 #ifdef HAVE_GCCJIT |
844 #if 1 | |
845 gccjit::rvalue | |
846 jit_function::call (gccjit::context ctxt, | |
847 gccjit::block block, | |
848 const std::vector<jit_value *>& in_args) const | |
849 { | |
850 assert (in_args.size () == args.size ()); | |
851 std::vector<gccjit::rvalue> gccjit_args (args.size ()); | |
852 for (size_t i = 0; i < in_args.size (); ++i) | |
853 gccjit_args[i] = in_args[i]->as_rvalue (); | |
854 return call (ctxt, block, gccjit_args); | |
855 } | |
856 | |
857 gccjit::rvalue | |
858 jit_function::call (gccjit::context ctxt, | |
859 gccjit::block block, | |
860 std::vector<gccjit::rvalue>& in_args) const | |
861 { | |
862 assert (in_args.size () == args.size ()); | |
863 | |
864 #if 1 | |
865 std::vector<gccjit::rvalue> packed_args (in_args.size ()); | |
866 | |
867 for (size_t i = 0; i < in_args.size (); ++i) | |
868 { | |
869 gccjit::rvalue arg = in_args[i]; | |
870 #if 0 | |
871 jit_type::convert_fn convert = args[i]->pack (call_conv); | |
872 if (convert) | |
873 arg = convert (builder, arg); | |
874 #endif | |
875 | |
876 if (args[i]->pointer_arg (call_conv)) | |
877 { | |
878 // The LLVM implementation takes a copy using alloca, passing | |
879 // a ptr to the copy to the fn. Emulate this behavior. | |
880 gccjit::lvalue tmp = | |
881 block.get_function ().new_local (arg.get_type (), "tmp"); | |
882 block.add_assignment (tmp, arg); | |
883 arg = tmp.get_address (); | |
884 } | |
885 | |
886 packed_args[i] = arg; | |
887 } | |
888 | |
889 return ctxt.new_call (gccjit_function, | |
890 packed_args); | |
891 #else | |
892 return ctxt.new_call (gccjit_function, | |
893 in_args); | |
894 #endif | |
895 } | |
896 #endif | |
897 | |
898 gccjit::lvalue | |
899 jit_function::argument (size_t idx) const | |
900 { | |
901 return gccjit_function.get_param (idx); | |
902 } | |
903 #endif | |
904 | |
15019
ae3670d4df29
Update the execution engine's global mapping for external functions
Max Brister <max@2bass.com>
parents:
15016
diff
changeset
|
905 void |
ae3670d4df29
Update the execution engine's global mapping for external functions
Max Brister <max@2bass.com>
parents:
15016
diff
changeset
|
906 jit_function::do_add_mapping (llvm::ExecutionEngine *engine, void *fn) |
ae3670d4df29
Update the execution engine's global mapping for external functions
Max Brister <max@2bass.com>
parents:
15016
diff
changeset
|
907 { |
ae3670d4df29
Update the execution engine's global mapping for external functions
Max Brister <max@2bass.com>
parents:
15016
diff
changeset
|
908 assert (valid ()); |
ae3670d4df29
Update the execution engine's global mapping for external functions
Max Brister <max@2bass.com>
parents:
15016
diff
changeset
|
909 engine->addGlobalMapping (llvm_function, fn); |
ae3670d4df29
Update the execution engine's global mapping for external functions
Max Brister <max@2bass.com>
parents:
15016
diff
changeset
|
910 } |
ae3670d4df29
Update the execution engine's global mapping for external functions
Max Brister <max@2bass.com>
parents:
15016
diff
changeset
|
911 |
15016 | 912 std::ostream& |
913 operator<< (std::ostream& os, const jit_function& fn) | |
914 { | |
915 llvm::Function *lfn = fn.to_llvm (); | |
916 os << "jit_function: cc=" << fn.call_conv; | |
917 llvm::raw_os_ostream llvm_out (os); | |
918 lfn->print (llvm_out); | |
919 llvm_out.flush (); | |
920 return os; | |
921 } | |
922 | |
923 // -------------------- jit_operation -------------------- | |
15078
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
924 jit_operation::~jit_operation (void) |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
925 { |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
926 for (generated_map::iterator iter = generated.begin (); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
927 iter != generated.end (); ++iter) |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
928 { |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
929 delete iter->first; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
930 delete iter->second; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
931 } |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
932 } |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
933 |
15016 | 934 void |
935 jit_operation::add_overload (const jit_function& func, | |
17787
175b392e91fe
Use GNU style coding conventions for code in libinterp/
Rik <rik@octave.org>
parents:
17744
diff
changeset
|
936 const std::vector<jit_type*>& args) |
15016 | 937 { |
938 if (args.size () >= overloads.size ()) | |
939 overloads.resize (args.size () + 1); | |
940 | |
941 Array<jit_function>& over = overloads[args.size ()]; | |
942 dim_vector dv (over.dims ()); | |
943 Array<octave_idx_type> idx = to_idx (args); | |
944 bool must_resize = false; | |
945 | |
946 if (dv.length () != idx.numel ()) | |
947 { | |
948 dv.resize (idx.numel ()); | |
949 must_resize = true; | |
950 } | |
951 | |
952 for (octave_idx_type i = 0; i < dv.length (); ++i) | |
953 if (dv(i) <= idx(i)) | |
954 { | |
955 must_resize = true; | |
956 dv(i) = idx(i) + 1; | |
957 } | |
958 | |
959 if (must_resize) | |
960 over.resize (dv); | |
961 | |
962 over(idx) = func; | |
963 } | |
964 | |
965 const jit_function& | |
966 jit_operation::overload (const std::vector<jit_type*>& types) const | |
967 { | |
968 static jit_function null_overload; | |
969 for (size_t i =0; i < types.size (); ++i) | |
970 if (! types[i]) | |
971 return null_overload; | |
972 | |
15078
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
973 if (types.size () >= overloads.size ()) |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
974 return do_generate (types); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
975 |
15016 | 976 const Array<jit_function>& over = overloads[types.size ()]; |
977 dim_vector dv (over.dims ()); | |
978 Array<octave_idx_type> idx = to_idx (types); | |
979 for (octave_idx_type i = 0; i < dv.length (); ++i) | |
980 if (idx(i) >= dv(i)) | |
15078
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
981 return do_generate (types); |
15016 | 982 |
15078
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
983 const jit_function& ret = over(idx); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
984 if (! ret.valid ()) |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
985 return do_generate (types); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
986 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
987 return ret; |
15016 | 988 } |
989 | |
990 Array<octave_idx_type> | |
991 jit_operation::to_idx (const std::vector<jit_type*>& types) const | |
992 { | |
993 octave_idx_type numel = types.size (); | |
18277
cc1c19863ae3
jit-typeinfo.cc: Fix C++ function ambiguity (bug #41145).
Lasse Schuirmann <lasse@schuirmann.net>
parents:
18274
diff
changeset
|
994 numel = std::max (numel, static_cast<octave_idx_type>(2)); |
15016 | 995 |
996 Array<octave_idx_type> idx (dim_vector (1, numel)); | |
997 for (octave_idx_type i = 0; i < static_cast<octave_idx_type> (types.size ()); | |
998 ++i) | |
999 idx(i) = types[i]->type_id (); | |
1000 | |
15337
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
1001 if (types.size () == 0) |
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
1002 idx(0) = idx(1) = 0; |
15016 | 1003 if (types.size () == 1) |
1004 { | |
1005 idx(1) = idx(0); | |
1006 idx(0) = 0; | |
1007 } | |
1008 | |
1009 return idx; | |
1010 } | |
1011 | |
15078
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1012 const jit_function& |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1013 jit_operation::do_generate (const signature_vec& types) const |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1014 { |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1015 static jit_function null_overload; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1016 generated_map::const_iterator find = generated.find (&types); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1017 if (find != generated.end ()) |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1018 { |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1019 if (find->second) |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1020 return *find->second; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1021 else |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1022 return null_overload; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1023 } |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1024 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1025 jit_function *ret = generate (types); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1026 generated[new signature_vec (types)] = ret; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1027 return ret ? *ret : null_overload; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1028 } |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1029 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1030 jit_function * |
15135
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
1031 jit_operation::generate (const signature_vec&) const |
15078
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1032 { |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1033 return 0; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1034 } |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1035 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1036 bool |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1037 jit_operation::signature_cmp |
18222
4d90e104bf35
Allow jit-typeinfo.h to compile with clang on OS X (bug #41114)
Michael C. Grant <mcg@cvxr.com>
parents:
17787
diff
changeset
|
1038 ::operator() (const signature_vec *lhs, const signature_vec *rhs) const |
15078
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1039 { |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1040 const signature_vec& l = *lhs; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1041 const signature_vec& r = *rhs; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1042 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1043 if (l.size () < r.size ()) |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1044 return true; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1045 else if (l.size () > r.size ()) |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1046 return false; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1047 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1048 for (size_t i = 0; i < l.size (); ++i) |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1049 { |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1050 if (l[i]->type_id () < r[i]->type_id ()) |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1051 return true; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1052 else if (l[i]->type_id () > r[i]->type_id ()) |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1053 return false; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1054 } |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1055 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1056 return false; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1057 } |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1058 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1059 // -------------------- jit_index_operation -------------------- |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1060 jit_function * |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1061 jit_index_operation::generate (const signature_vec& types) const |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1062 { |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1063 if (types.size () > 2 && types[0] == jit_typeinfo::get_matrix ()) |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1064 { |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1065 // indexing a matrix with scalars |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1066 jit_type *scalar = jit_typeinfo::get_scalar (); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1067 for (size_t i = 1; i < types.size (); ++i) |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1068 if (types[i] != scalar) |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1069 return 0; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1070 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1071 return generate_matrix (types); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1072 } |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1073 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1074 return 0; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1075 } |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1076 |
20654 | 1077 #ifdef HAVE_LLVM |
15078
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1078 llvm::Value * |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1079 jit_index_operation::create_arg_array (llvm::IRBuilderD& builder, |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1080 const jit_function &fn, size_t start_idx, |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1081 size_t end_idx) const |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1082 { |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1083 size_t n = end_idx - start_idx; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1084 llvm::Type *scalar_t = jit_typeinfo::get_scalar_llvm (); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1085 llvm::ArrayType *array_t = llvm::ArrayType::get (scalar_t, n); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1086 llvm::Value *array = llvm::UndefValue::get (array_t); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1087 for (size_t i = start_idx; i < end_idx; ++i) |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1088 { |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1089 llvm::Value *idx = fn.argument (builder, i); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1090 array = builder.CreateInsertValue (array, idx, i - start_idx); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1091 } |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1092 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1093 llvm::Value *array_mem = builder.CreateAlloca (array_t); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1094 builder.CreateStore (array, array_mem); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1095 return builder.CreateBitCast (array_mem, scalar_t->getPointerTo ()); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1096 } |
20654 | 1097 #endif // #ifdef HAVE_LLVM |
1098 | |
1099 #ifdef HAVE_GCCJIT | |
1100 gccjit::rvalue | |
1101 jit_index_operation::create_arg_array (const jit_function &fn, | |
1102 gccjit::block block, | |
1103 size_t start_idx, | |
1104 size_t end_idx) const | |
1105 { | |
1106 size_t n = end_idx - start_idx; | |
1107 gccjit::type scalar_t = jit_typeinfo::get_scalar_gccjit (); | |
1108 gccjit::type array_t = block.get_context ().new_array_type (scalar_t, n); | |
1109 gccjit::lvalue array = | |
1110 block.get_function ().new_local (array_t, "tmp_array"); | |
1111 for (size_t i = start_idx; i < end_idx; ++i) | |
1112 { | |
1113 gccjit::rvalue idx = fn.argument (i); | |
1114 block.add_assignment (array[i - start_idx], idx); | |
1115 } | |
1116 return array.get_address ().cast_to (scalar_t.get_pointer ()); | |
1117 } | |
1118 #endif // #ifdef HAVE_GCCJIT | |
15078
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1119 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1120 // -------------------- jit_paren_subsref -------------------- |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1121 jit_function * |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1122 jit_paren_subsref::generate_matrix (const signature_vec& types) const |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1123 { |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1124 std::stringstream ss; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1125 ss << "jit_paren_subsref_matrix_scalar" << (types.size () - 1); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1126 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1127 jit_type *scalar = jit_typeinfo::get_scalar (); |
20654 | 1128 jit_function *fn = new jit_function (module, |
1129 #ifdef HAVE_GCCJIT | |
1130 gccjit_ctxt, | |
1131 #endif | |
1132 jit_convention::internal, | |
15078
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1133 ss.str (), scalar, types); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1134 fn->mark_can_error (); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1135 llvm::BasicBlock *body = fn->new_block (); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1136 llvm::IRBuilder<> builder (body); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1137 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1138 llvm::Value *array = create_arg_array (builder, *fn, 1, types.size ()); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1139 jit_type *index = jit_typeinfo::get_index (); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1140 llvm::Value *nelem = llvm::ConstantInt::get (index->to_llvm (), |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1141 types.size () - 1); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1142 llvm::Value *mat = fn->argument (builder, 0); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1143 llvm::Value *ret = paren_scalar.call (builder, mat, array, nelem); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1144 fn->do_return (builder, ret); |
20654 | 1145 |
1146 #ifdef HAVE_GCCJIT | |
1147 // gcc implementation | |
1148 { | |
1149 gccjit::function gf = fn->gccjit_function; | |
1150 gccjit::block body = gf.new_block (); | |
1151 gccjit::rvalue array = create_arg_array (*fn, body, 1, types.size ()); | |
1152 jit_type *index = jit_typeinfo::get_index (); | |
1153 gccjit::rvalue nelem = gccjit_ctxt.new_rvalue (index->to_gccjit (), | |
1154 (int)types.size () - 1); | |
1155 gccjit::rvalue mat = gf.get_param (0); | |
1156 std::vector<gccjit::rvalue> args (3); | |
1157 args[0] = mat; | |
1158 args[1] = array; | |
1159 args[2] = nelem; | |
1160 gccjit::rvalue ret = paren_scalar.call (gccjit_ctxt, body, args); | |
1161 body.end_with_return (ret); | |
1162 } | |
1163 #endif | |
1164 | |
15078
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1165 return fn; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1166 } |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1167 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1168 void |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1169 jit_paren_subsref::do_initialize (void) |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1170 { |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1171 std::vector<jit_type *> types (3); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1172 types[0] = jit_typeinfo::get_matrix (); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1173 types[1] = jit_typeinfo::get_scalar_ptr (); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1174 types[2] = jit_typeinfo::get_index (); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1175 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1176 jit_type *scalar = jit_typeinfo::get_scalar (); |
20654 | 1177 paren_scalar = jit_function (module, |
1178 #ifdef HAVE_GCCJIT | |
1179 gccjit_ctxt, | |
1180 #endif | |
1181 jit_convention::external, | |
15078
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1182 "octave_jit_paren_scalar", scalar, types); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1183 paren_scalar.add_mapping (engine, &octave_jit_paren_scalar); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1184 paren_scalar.mark_can_error (); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1185 } |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1186 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1187 // -------------------- jit_paren_subsasgn -------------------- |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1188 jit_function * |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1189 jit_paren_subsasgn::generate_matrix (const signature_vec& types) const |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1190 { |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1191 std::stringstream ss; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1192 ss << "jit_paren_subsasgn_matrix_scalar" << (types.size () - 2); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1193 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1194 jit_type *matrix = jit_typeinfo::get_matrix (); |
20654 | 1195 jit_function *fn = new jit_function (module, |
1196 #ifdef HAVE_GCCJIT | |
1197 gccjit_ctxt, | |
1198 #endif | |
1199 jit_convention::internal, | |
15078
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1200 ss.str (), matrix, types); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1201 fn->mark_can_error (); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1202 llvm::BasicBlock *body = fn->new_block (); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1203 llvm::IRBuilder<> builder (body); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1204 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1205 llvm::Value *array = create_arg_array (builder, *fn, 1, types.size () - 1); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1206 jit_type *index = jit_typeinfo::get_index (); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1207 llvm::Value *nelem = llvm::ConstantInt::get (index->to_llvm (), |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1208 types.size () - 2); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1209 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1210 llvm::Value *mat = fn->argument (builder, 0); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1211 llvm::Value *value = fn->argument (builder, types.size () - 1); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1212 llvm::Value *ret = paren_scalar.call (builder, mat, array, nelem, value); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1213 fn->do_return (builder, ret); |
20654 | 1214 |
1215 #ifdef HAVE_GCCJIT | |
1216 { | |
1217 // FIXME: TODO | |
1218 gccjit::function gf = fn->gccjit_function; | |
1219 gccjit::block body = gf.new_block (); | |
1220 gccjit::rvalue array = create_arg_array (*fn, body, 1, types.size () - 1); | |
1221 jit_type *index = jit_typeinfo::get_index (); | |
1222 gccjit::rvalue nelem = gccjit_ctxt.new_rvalue (index->to_gccjit (), | |
1223 (int)types.size () - 2); | |
1224 gccjit::rvalue mat = gf.get_param (0); | |
1225 gccjit::rvalue value = gf.get_param (types.size () - 1); | |
1226 std::vector<gccjit::rvalue> args(4); | |
1227 args[0] = mat; | |
1228 args[1] = array; | |
1229 args[2] = nelem; | |
1230 args[3] = value; | |
1231 gccjit::rvalue ret = paren_scalar.call (gccjit_ctxt, body, args); | |
1232 body.end_with_return (ret); | |
1233 } | |
1234 #endif | |
1235 | |
15078
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1236 return fn; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1237 } |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1238 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1239 void |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1240 jit_paren_subsasgn::do_initialize (void) |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1241 { |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1242 if (paren_scalar.valid ()) |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1243 return; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1244 |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1245 jit_type *matrix = jit_typeinfo::get_matrix (); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1246 std::vector<jit_type *> types (4); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1247 types[0] = matrix; |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1248 types[1] = jit_typeinfo::get_scalar_ptr (); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1249 types[2] = jit_typeinfo::get_index (); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1250 types[3] = jit_typeinfo::get_scalar (); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1251 |
20654 | 1252 paren_scalar = jit_function (module, |
1253 #ifdef HAVE_GCCJIT | |
1254 gccjit_ctxt, | |
1255 #endif | |
1256 jit_convention::external, | |
15078
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1257 "octave_jit_paren_scalar", matrix, types); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1258 paren_scalar.add_mapping (engine, &octave_jit_paren_scalar_subsasgn); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1259 paren_scalar.mark_can_error (); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1260 } |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1261 |
15016 | 1262 // -------------------- jit_typeinfo -------------------- |
1263 void | |
1264 jit_typeinfo::initialize (llvm::Module *m, llvm::ExecutionEngine *e) | |
1265 { | |
1266 new jit_typeinfo (m, e); | |
1267 } | |
1268 | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1269 // wrap function names to simplify jit_typeinfo::create_external |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1270 #define JIT_FN(fn) engine, &fn, #fn |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1271 |
15016 | 1272 jit_typeinfo::jit_typeinfo (llvm::Module *m, llvm::ExecutionEngine *e) |
1273 : module (m), engine (e), next_id (0), | |
1274 builder (*new llvm::IRBuilderD (context)) | |
1275 { | |
1276 instance = this; | |
1277 | |
20654 | 1278 #ifdef HAVE_GCCJIT |
1279 gccjit_ctxt = gccjit::context::acquire (); | |
1280 #endif | |
1281 | |
15016 | 1282 // FIXME: We should be registering types like in octave_value_typeinfo |
20654 | 1283 #ifdef HAVE_LLVM |
15016 | 1284 llvm::Type *any_t = llvm::StructType::create (context, "octave_base_value"); |
1285 any_t = any_t->getPointerTo (); | |
1286 | |
1287 llvm::Type *scalar_t = llvm::Type::getDoubleTy (context); | |
1288 llvm::Type *bool_t = llvm::Type::getInt1Ty (context); | |
1289 llvm::Type *string_t = llvm::Type::getInt8Ty (context); | |
1290 string_t = string_t->getPointerTo (); | |
1291 llvm::Type *index_t = llvm::Type::getIntNTy (context, | |
1292 sizeof(octave_idx_type) * 8); | |
20654 | 1293 #endif |
1294 | |
1295 #ifdef HAVE_GCCJIT | |
1296 gccjit::type any_t_gcc = | |
1297 gccjit_ctxt.new_opaque_struct_type ("octave_base_value"); | |
1298 any_t_gcc = any_t_gcc.get_pointer (); | |
1299 gccjit::type scalar_t_gcc = gccjit_ctxt.get_type (GCC_JIT_TYPE_DOUBLE); | |
1300 gccjit::type bool_t_gcc = gccjit_ctxt.get_type (GCC_JIT_TYPE_BOOL); | |
1301 gccjit::type string_t_gcc = | |
1302 gccjit_ctxt.get_type (GCC_JIT_TYPE_CHAR).get_pointer (); | |
1303 gccjit::type index_t_gcc = gccjit_ctxt.get_int_type <octave_idx_type> (); | |
1304 gccjit::type int_t_gcc = gccjit_ctxt.get_type (GCC_JIT_TYPE_INT); | |
1305 #endif | |
1306 | |
1307 #ifdef HAVE_LLVM | |
15016 | 1308 llvm::StructType *range_t = llvm::StructType::create (context, "range"); |
1309 std::vector<llvm::Type *> range_contents (4, scalar_t); | |
1310 range_contents[3] = index_t; | |
1311 range_t->setBody (range_contents); | |
20654 | 1312 #endif |
1313 #ifdef HAVE_GCCJIT | |
1314 field_rng_base = gccjit_ctxt.new_field (scalar_t_gcc, "rng_base"); | |
1315 field_rng_limit = gccjit_ctxt.new_field (scalar_t_gcc, "rng_limit"); | |
1316 field_rng_inc = gccjit_ctxt.new_field (scalar_t_gcc, "rng_inc"); | |
1317 field_rng_nelem = gccjit_ctxt.new_field (index_t_gcc, "rng_nelem"); | |
1318 /* FIXME: what about the "mutable Matrix cache;" */ | |
1319 | |
1320 std::vector<gccjit::field> range_fields (4); | |
1321 range_fields [0] = field_rng_base; | |
1322 range_fields [1] = field_rng_limit; | |
1323 range_fields [2] = field_rng_inc; | |
1324 range_fields [3] = field_rng_nelem; | |
1325 | |
1326 gccjit::type range_t_gcc = | |
1327 gccjit_ctxt.new_struct_type ( | |
1328 "range", | |
1329 range_fields, | |
1330 gccjit_ctxt.new_location ("liboctave/array/Range.h", 33, 0)); | |
1331 #endif | |
1332 | |
1333 #ifdef HAVE_LLVM | |
15016 | 1334 llvm::Type *refcount_t = llvm::Type::getIntNTy (context, sizeof(int) * 8); |
20654 | 1335 #endif |
1336 #ifdef HAVE_GCCJIT | |
1337 gccjit::type refcount_t_gcc = gccjit_ctxt.get_type (GCC_JIT_TYPE_INT); | |
1338 #endif | |
1339 | |
1340 #ifdef HAVE_LLVM | |
15016 | 1341 llvm::StructType *matrix_t = llvm::StructType::create (context, "matrix"); |
1342 llvm::Type *matrix_contents[5]; | |
1343 matrix_contents[0] = refcount_t->getPointerTo (); | |
1344 matrix_contents[1] = scalar_t->getPointerTo (); | |
1345 matrix_contents[2] = index_t; | |
1346 matrix_contents[3] = index_t->getPointerTo (); | |
1347 matrix_contents[4] = string_t; | |
1348 matrix_t->setBody (llvm::makeArrayRef (matrix_contents, 5)); | |
20654 | 1349 #endif |
1350 #ifdef HAVE_GCCJIT | |
1351 /* | |
1352 jit-typeinfo.h has, somewhat ominously: | |
1353 // jit_array is compatable with the llvm array/matrix structures | |
1354 typedef jit_array<NDArray, double> jit_matrix; | |
1355 */ | |
1356 gccjit::type matrix_t_gcc; | |
1357 { | |
1358 /* typedef jit_array<NDArray, double> jit_matrix; */ | |
1359 /* template <typename T, typename U> struct jit_array {...}; */ | |
1360 gccjit::type T = string_t_gcc; /* NDArray */ | |
1361 gccjit::type U = scalar_t_gcc; /* double */ | |
1362 | |
1363 /* int *ref_count; */ | |
1364 field_ref_count = | |
1365 gccjit_ctxt.new_field (refcount_t_gcc.get_pointer (), "ref_count"); | |
1366 | |
1367 /* U *slice_data; */ | |
1368 field_slice_data = | |
1369 gccjit_ctxt.new_field (U.get_pointer (), "slice_data"); | |
1370 | |
1371 /* octave_idx_type slice_len; */ | |
1372 field_slice_len = gccjit_ctxt.new_field (index_t_gcc, "slice_len"); | |
1373 | |
1374 /* octave_idx_type *dimensions; */ | |
1375 field_dimensions = | |
1376 gccjit_ctxt.new_field (index_t_gcc.get_pointer (), "dimensions"); | |
1377 | |
1378 /* T *array; */ | |
1379 field_array = gccjit_ctxt.new_field (T.get_pointer (), "array"); | |
1380 | |
1381 std::vector<gccjit::field> matrix_fields (5); | |
1382 matrix_fields[0] = field_ref_count; | |
1383 matrix_fields[1] = field_slice_data; | |
1384 matrix_fields[2] = field_slice_len; | |
1385 matrix_fields[3] = field_dimensions; | |
1386 matrix_fields[4] = field_array; | |
1387 | |
1388 matrix_t_gcc = gccjit_ctxt.new_struct_type ( | |
1389 "jit_matrix", | |
1390 matrix_fields, | |
1391 gccjit_ctxt.new_location ("jit-typeinfo.h", 106, 0)); | |
1392 } | |
1393 #endif | |
1394 | |
1395 #ifdef HAVE_LLVM | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1396 llvm::Type *complex_t = llvm::ArrayType::get (scalar_t, 2); |
20654 | 1397 #endif |
1398 #ifdef HAVE_GCCJIT | |
1399 gccjit::type complex_t_gcc = gccjit_ctxt.new_array_type (scalar_t_gcc, 2); | |
1400 #endif | |
15016 | 1401 |
1402 // complex_ret is what is passed to C functions in order to get calling | |
1403 // convention right | |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
1404 llvm::Type *cmplx_inner_cont[] = {scalar_t, scalar_t}; |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
1405 llvm::StructType *cmplx_inner = llvm::StructType::create (cmplx_inner_cont); |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
1406 |
15016 | 1407 complex_ret = llvm::StructType::create (context, "complex_ret"); |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
1408 { |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
1409 llvm::Type *contents[] = {cmplx_inner}; |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
1410 complex_ret->setBody (contents); |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
1411 } |
15016 | 1412 |
1413 // create types | |
20654 | 1414 #ifdef HAVE_GCCJIT |
1415 any = new_type ("any", 0, any_t, any_t_gcc); | |
1416 matrix = new_type ("matrix", any, matrix_t, matrix_t_gcc); | |
1417 complex = new_type ("complex", any, complex_t, complex_t_gcc); | |
1418 scalar = new_type ("scalar", complex, scalar_t, scalar_t_gcc); | |
1419 scalar_ptr = new_type ("scalar_ptr", 0, scalar_t->getPointerTo (), | |
1420 scalar_t_gcc.get_pointer ()); | |
1421 any_ptr = new_type ("any_ptr", 0, any_t->getPointerTo (), | |
1422 any_t_gcc.get_pointer()); | |
1423 range = new_type ("range", any, range_t, range_t_gcc); | |
1424 string = new_type ("string", any, string_t, string_t_gcc); | |
1425 boolean = new_type ("bool", any, bool_t, bool_t_gcc); | |
1426 index = new_type ("index", any, index_t, index_t_gcc); | |
1427 #else | |
15016 | 1428 any = new_type ("any", 0, any_t); |
1429 matrix = new_type ("matrix", any, matrix_t); | |
1430 complex = new_type ("complex", any, complex_t); | |
1431 scalar = new_type ("scalar", complex, scalar_t); | |
15078
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1432 scalar_ptr = new_type ("scalar_ptr", 0, scalar_t->getPointerTo ()); |
15135
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
1433 any_ptr = new_type ("any_ptr", 0, any_t->getPointerTo ()); |
15016 | 1434 range = new_type ("range", any, range_t); |
1435 string = new_type ("string", any, string_t); | |
1436 boolean = new_type ("bool", any, bool_t); | |
1437 index = new_type ("index", any, index_t); | |
20654 | 1438 #endif |
15016 | 1439 |
1440 create_int (8); | |
1441 create_int (16); | |
1442 create_int (32); | |
1443 create_int (64); | |
1444 | |
1445 casts.resize (next_id + 1); | |
1446 identities.resize (next_id + 1); | |
1447 | |
1448 // specify calling conventions | |
1449 // FIXME: We should detect architecture and do something sane based on that | |
1450 // here we assume x86 or x86_64 | |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
1451 matrix->mark_sret (jit_convention::external); |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
1452 matrix->mark_pointer_arg (jit_convention::external); |
15016 | 1453 |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
1454 range->mark_sret (jit_convention::external); |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
1455 range->mark_pointer_arg (jit_convention::external); |
15016 | 1456 |
1457 complex->set_pack (jit_convention::external, &jit_typeinfo::pack_complex); | |
1458 complex->set_unpack (jit_convention::external, &jit_typeinfo::unpack_complex); | |
1459 complex->set_packed_type (jit_convention::external, complex_ret); | |
1460 | |
1461 if (sizeof (void *) == 4) | |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
1462 complex->mark_sret (jit_convention::external); |
15016 | 1463 |
20654 | 1464 #ifdef HAVE_GCCJIT |
1465 paren_subsref_fn.initialize (module, engine, gccjit_ctxt); | |
1466 paren_subsasgn_fn.initialize (module, engine, gccjit_ctxt); | |
1467 #else | |
15078
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1468 paren_subsref_fn.initialize (module, engine); |
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1469 paren_subsasgn_fn.initialize (module, engine); |
20654 | 1470 #endif |
15078
fe4752f772e2
Generate ND indexing functions on demand in JIT.
Max Brister <max@2bass.com>
parents:
15068
diff
changeset
|
1471 |
15016 | 1472 // bind global variables |
20654 | 1473 #ifdef HAVE_LLVM |
15016 | 1474 lerror_state = new llvm::GlobalVariable (*module, bool_t, false, |
1475 llvm::GlobalValue::ExternalLinkage, | |
1476 0, "error_state"); | |
1477 engine->addGlobalMapping (lerror_state, | |
1478 reinterpret_cast<void *> (&error_state)); | |
1479 | |
15603 | 1480 // sig_atomic_type is going to be some sort of integer |
1481 sig_atomic_type = llvm::Type::getIntNTy (context, sizeof(sig_atomic_t) * 8); | |
1482 loctave_interrupt_state | |
1483 = new llvm::GlobalVariable (*module, sig_atomic_type, false, | |
1484 llvm::GlobalValue::ExternalLinkage, 0, | |
1485 "octave_interrupt_state"); | |
1486 engine->addGlobalMapping (loctave_interrupt_state, | |
1487 reinterpret_cast<void *> (&octave_interrupt_state)); | |
20654 | 1488 #endif |
1489 | |
1490 #ifdef HAVE_GCCJIT | |
1491 // Access "error_state" (actually declared as an "int"), by | |
1492 // taking its address and dereferencing: | |
1493 error_state_gccjit = | |
1494 *gccjit_ctxt.new_rvalue (int_t_gcc.get_pointer (), | |
1495 &error_state); | |
1496 sig_atomic_type_gccjit = gccjit_ctxt.get_int_type <sig_atomic_t> (); | |
1497 octave_interrupt_state_gccjit = | |
1498 *gccjit_ctxt.new_rvalue ( | |
1499 sig_atomic_type_gccjit.get_volatile ().get_pointer (), | |
1500 &octave_interrupt_state); | |
1501 #endif | |
15603 | 1502 |
15135
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
1503 // generic call function |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
1504 { |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
1505 jit_type *int_t = intN (sizeof (octave_builtin::fcn) * 8); |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1506 any_call = create_external (JIT_FN (octave_jit_call), any, int_t, int_t, |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1507 any_ptr, int_t); |
15135
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
1508 } |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
1509 |
15016 | 1510 // any with anything is an any op |
1511 jit_function fn; | |
1512 jit_type *binary_op_type = intN (sizeof (octave_value::binary_op) * 8); | |
1513 llvm::Type *llvm_bo_type = binary_op_type->to_llvm (); | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1514 jit_function any_binary = create_external (JIT_FN (octave_jit_binary_any_any), |
15016 | 1515 any, binary_op_type, any, any); |
1516 any_binary.mark_can_error (); | |
1517 binary_ops.resize (octave_value::num_binary_ops); | |
1518 for (size_t i = 0; i < octave_value::num_binary_ops; ++i) | |
1519 { | |
1520 octave_value::binary_op op = static_cast<octave_value::binary_op> (i); | |
1521 std::string op_name = octave_value::binary_op_as_string (op); | |
1522 binary_ops[i].stash_name ("binary" + op_name); | |
1523 } | |
1524 | |
15146
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1525 unary_ops.resize (octave_value::num_unary_ops); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1526 for (size_t i = 0; i < octave_value::num_unary_ops; ++i) |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1527 { |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1528 octave_value::unary_op op = static_cast<octave_value::unary_op> (i); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1529 std::string op_name = octave_value::unary_op_as_string (op); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1530 unary_ops[i].stash_name ("unary" + op_name); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1531 } |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1532 |
15016 | 1533 for (int op = 0; op < octave_value::num_binary_ops; ++op) |
1534 { | |
20654 | 1535 std::string fn_name ("octave_jit_binary_any_any_"); |
1536 char buf[64]; | |
1537 snprintf (buf, sizeof(buf), "%i", op); | |
1538 fn_name = fn_name + std::string (buf); | |
15016 | 1539 |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1540 fn = create_internal (fn_name, any, any, any); |
15016 | 1541 fn.mark_can_error (); |
1542 llvm::BasicBlock *block = fn.new_block (); | |
1543 builder.SetInsertPoint (block); | |
1544 llvm::APInt op_int(sizeof (octave_value::binary_op) * 8, op, | |
1545 std::numeric_limits<octave_value::binary_op>::is_signed); | |
1546 llvm::Value *op_as_llvm = llvm::ConstantInt::get (llvm_bo_type, op_int); | |
1547 llvm::Value *ret = any_binary.call (builder, op_as_llvm, | |
1548 fn.argument (builder, 0), | |
1549 fn.argument (builder, 1)); | |
1550 fn.do_return (builder, ret); | |
20654 | 1551 |
1552 #ifdef HAVE_GCCJIT | |
1553 // gccjit implementation of octave_jit_binary_any_any_*: | |
1554 gccjit::function gf = fn.gccjit_function; | |
1555 gccjit::block gccjit_block = gf.new_block (); | |
1556 gccjit_block.end_with_return ( | |
1557 gccjit_block.add_call ( | |
1558 any_binary.gccjit_function, | |
1559 gccjit_ctxt.new_rvalue (binary_op_type->to_gccjit (), | |
1560 op), | |
1561 gf.get_param (0), | |
1562 gf.get_param (1))); | |
1563 #endif | |
1564 | |
15016 | 1565 binary_ops[op].add_overload (fn); |
1566 } | |
1567 | |
1568 // grab matrix | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1569 fn = create_external (JIT_FN (octave_jit_grab_matrix), matrix, matrix); |
15016 | 1570 grab_fn.add_overload (fn); |
1571 | |
15334
8125773322d4
Error on undefined an unused variables in JIT
Max Brister <max@2bass.com>
parents:
15311
diff
changeset
|
1572 grab_fn.add_overload (create_identity (scalar)); |
8125773322d4
Error on undefined an unused variables in JIT
Max Brister <max@2bass.com>
parents:
15311
diff
changeset
|
1573 grab_fn.add_overload (create_identity (scalar_ptr)); |
8125773322d4
Error on undefined an unused variables in JIT
Max Brister <max@2bass.com>
parents:
15311
diff
changeset
|
1574 grab_fn.add_overload (create_identity (any_ptr)); |
8125773322d4
Error on undefined an unused variables in JIT
Max Brister <max@2bass.com>
parents:
15311
diff
changeset
|
1575 grab_fn.add_overload (create_identity (boolean)); |
8125773322d4
Error on undefined an unused variables in JIT
Max Brister <max@2bass.com>
parents:
15311
diff
changeset
|
1576 grab_fn.add_overload (create_identity (complex)); |
8125773322d4
Error on undefined an unused variables in JIT
Max Brister <max@2bass.com>
parents:
15311
diff
changeset
|
1577 grab_fn.add_overload (create_identity (index)); |
8125773322d4
Error on undefined an unused variables in JIT
Max Brister <max@2bass.com>
parents:
15311
diff
changeset
|
1578 |
15016 | 1579 // release any |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1580 fn = create_external (JIT_FN (octave_jit_release_any), 0, any); |
15016 | 1581 release_fn.add_overload (fn); |
1582 release_fn.stash_name ("release"); | |
1583 | |
1584 // release matrix | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1585 fn = create_external (JIT_FN (octave_jit_release_matrix), 0, matrix); |
15016 | 1586 release_fn.add_overload (fn); |
1587 | |
15337
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
1588 // destroy |
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
1589 destroy_fn = release_fn; |
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
1590 destroy_fn.stash_name ("destroy"); |
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
1591 destroy_fn.add_overload (create_identity(scalar)); |
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
1592 destroy_fn.add_overload (create_identity(boolean)); |
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
1593 destroy_fn.add_overload (create_identity(index)); |
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
1594 destroy_fn.add_overload (create_identity(complex)); |
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
1595 |
15016 | 1596 // now for binary scalar operations |
20654 | 1597 #ifdef HAVE_GCCJIT |
1598 add_binary_op (scalar, octave_value::op_add, | |
1599 llvm::Instruction::FAdd, | |
1600 GCC_JIT_BINARY_OP_PLUS); | |
1601 add_binary_op (scalar, octave_value::op_sub, | |
1602 llvm::Instruction::FSub, | |
1603 GCC_JIT_BINARY_OP_MINUS); | |
1604 add_binary_op (scalar, octave_value::op_mul, | |
1605 llvm::Instruction::FMul, | |
1606 GCC_JIT_BINARY_OP_MULT); | |
1607 add_binary_op (scalar, octave_value::op_el_mul, | |
1608 llvm::Instruction::FMul, | |
1609 GCC_JIT_BINARY_OP_MULT); | |
1610 | |
1611 add_binary_fcmp (scalar, octave_value::op_lt, | |
1612 llvm::CmpInst::FCMP_ULT, | |
1613 GCC_JIT_COMPARISON_LT); | |
1614 add_binary_fcmp (scalar, octave_value::op_le, | |
1615 llvm::CmpInst::FCMP_ULE, | |
1616 GCC_JIT_COMPARISON_LE); | |
1617 add_binary_fcmp (scalar, octave_value::op_eq, | |
1618 llvm::CmpInst::FCMP_UEQ, | |
1619 GCC_JIT_COMPARISON_EQ); | |
1620 add_binary_fcmp (scalar, octave_value::op_ge, | |
1621 llvm::CmpInst::FCMP_UGE, | |
1622 GCC_JIT_COMPARISON_GE); | |
1623 add_binary_fcmp (scalar, octave_value::op_gt, | |
1624 llvm::CmpInst::FCMP_UGT, | |
1625 GCC_JIT_COMPARISON_GT); | |
1626 add_binary_fcmp (scalar, octave_value::op_ne, | |
1627 llvm::CmpInst::FCMP_UNE, | |
1628 GCC_JIT_COMPARISON_NE); | |
1629 #else | |
15016 | 1630 add_binary_op (scalar, octave_value::op_add, llvm::Instruction::FAdd); |
1631 add_binary_op (scalar, octave_value::op_sub, llvm::Instruction::FSub); | |
1632 add_binary_op (scalar, octave_value::op_mul, llvm::Instruction::FMul); | |
1633 add_binary_op (scalar, octave_value::op_el_mul, llvm::Instruction::FMul); | |
1634 | |
1635 add_binary_fcmp (scalar, octave_value::op_lt, llvm::CmpInst::FCMP_ULT); | |
1636 add_binary_fcmp (scalar, octave_value::op_le, llvm::CmpInst::FCMP_ULE); | |
1637 add_binary_fcmp (scalar, octave_value::op_eq, llvm::CmpInst::FCMP_UEQ); | |
1638 add_binary_fcmp (scalar, octave_value::op_ge, llvm::CmpInst::FCMP_UGE); | |
1639 add_binary_fcmp (scalar, octave_value::op_gt, llvm::CmpInst::FCMP_UGT); | |
1640 add_binary_fcmp (scalar, octave_value::op_ne, llvm::CmpInst::FCMP_UNE); | |
20654 | 1641 #endif |
15016 | 1642 |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1643 jit_function gripe_div0 = create_external (JIT_FN (gripe_divide_by_zero), 0); |
15016 | 1644 gripe_div0.mark_can_error (); |
1645 | |
1646 // divide is annoying because it might error | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1647 fn = create_internal ("octave_jit_div_scalar_scalar", scalar, scalar, scalar); |
15016 | 1648 fn.mark_can_error (); |
1649 | |
1650 llvm::BasicBlock *body = fn.new_block (); | |
1651 builder.SetInsertPoint (body); | |
1652 { | |
1653 llvm::BasicBlock *warn_block = fn.new_block ("warn"); | |
1654 llvm::BasicBlock *normal_block = fn.new_block ("normal"); | |
1655 | |
1656 llvm::Value *zero = llvm::ConstantFP::get (scalar_t, 0); | |
15095
9df70a18aa27
Correct division by zero check in JIT
Max Brister <max@2bass.com>
parents:
15078
diff
changeset
|
1657 llvm::Value *check = builder.CreateFCmpUEQ (zero, fn.argument (builder, 1)); |
15016 | 1658 builder.CreateCondBr (check, warn_block, normal_block); |
1659 | |
1660 builder.SetInsertPoint (warn_block); | |
1661 gripe_div0.call (builder); | |
1662 builder.CreateBr (normal_block); | |
1663 | |
1664 builder.SetInsertPoint (normal_block); | |
1665 llvm::Value *ret = builder.CreateFDiv (fn.argument (builder, 0), | |
1666 fn.argument (builder, 1)); | |
1667 fn.do_return (builder, ret); | |
1668 } | |
20654 | 1669 |
1670 // gccjit implementation of octave_jit_div_scalar_scalar: | |
1671 #ifdef HAVE_GCCJIT | |
1672 { | |
1673 gccjit::function gf = fn.gccjit_function; | |
1674 gccjit::block initial_block = gf.new_block ("initial"); | |
1675 gccjit::block warn_block = gf.new_block ("warn"); | |
1676 gccjit::block normal_block = gf.new_block ("normal"); | |
1677 initial_block.end_with_conditional ( | |
1678 gf.get_param (1) != scalar_t_gcc.zero (), | |
1679 normal_block, // on_true | |
1680 warn_block); // on_false | |
1681 | |
1682 warn_block.add_call (gripe_div0.gccjit_function); | |
1683 warn_block.end_with_jump (normal_block); | |
1684 | |
1685 normal_block.end_with_return (gf.get_param (0) / gf.get_param (1)); | |
1686 } | |
1687 #endif | |
15016 | 1688 binary_ops[octave_value::op_div].add_overload (fn); |
1689 binary_ops[octave_value::op_el_div].add_overload (fn); | |
1690 | |
1691 // ldiv is the same as div with the operators reversed | |
1692 fn = mirror_binary (fn); | |
1693 binary_ops[octave_value::op_ldiv].add_overload (fn); | |
1694 binary_ops[octave_value::op_el_ldiv].add_overload (fn); | |
1695 | |
1696 // In general, the result of scalar ^ scalar is a complex number. We might be | |
1697 // able to improve on this if we keep track of the range of values varaibles | |
1698 // can take on. | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1699 fn = create_external (JIT_FN (octave_jit_pow_scalar_scalar), complex, scalar, |
15016 | 1700 scalar); |
1701 binary_ops[octave_value::op_pow].add_overload (fn); | |
1702 binary_ops[octave_value::op_el_pow].add_overload (fn); | |
1703 | |
15146
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1704 // now for unary scalar operations |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1705 // FIXME: Impelment not |
20654 | 1706 fn = create_internal ("octave_jit_plusplus", scalar, scalar); |
15146
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1707 body = fn.new_block (); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1708 builder.SetInsertPoint (body); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1709 { |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1710 llvm::Value *one = llvm::ConstantFP::get (scalar_t, 1); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1711 llvm::Value *val = fn.argument (builder, 0); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1712 val = builder.CreateFAdd (val, one); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1713 fn.do_return (builder, val); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1714 } |
20654 | 1715 // gccjit implementation of octave_jit_plusplus: |
1716 #ifdef HAVE_GCCJIT | |
1717 { | |
1718 gccjit::function gf = fn.gccjit_function; | |
1719 gccjit::block b = gf.new_block (); | |
1720 b.end_with_return (gf.get_param (0) + scalar_t_gcc.one ()); | |
1721 } | |
1722 #endif | |
15146
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1723 unary_ops[octave_value::op_incr].add_overload (fn); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1724 |
20654 | 1725 fn = create_internal ("octave_jit_minusminus", scalar, scalar); |
15146
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1726 body = fn.new_block (); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1727 builder.SetInsertPoint (body); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1728 { |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1729 llvm::Value *one = llvm::ConstantFP::get (scalar_t, 1); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1730 llvm::Value *val = fn.argument (builder, 0); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1731 val = builder.CreateFSub (val, one); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1732 fn.do_return (builder, val); |
20654 | 1733 |
1734 // gccjit implementation of octave_jit_minusminus: | |
1735 #ifdef HAVE_GCCJIT | |
1736 gccjit::function gf = fn.gccjit_function; | |
1737 gccjit::block b = gf.new_block (); | |
1738 b.end_with_return (gf.get_param (0) - scalar_t_gcc.one ()); | |
1739 #endif | |
15146
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1740 } |
20654 | 1741 |
15146
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1742 unary_ops[octave_value::op_decr].add_overload (fn); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1743 |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1744 fn = create_internal ("octave_jit_uminus", scalar, scalar); |
15146
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1745 body = fn.new_block (); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1746 builder.SetInsertPoint (body); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1747 { |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1748 llvm::Value *mone = llvm::ConstantFP::get (scalar_t, -1); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1749 llvm::Value *val = fn.argument (builder, 0); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1750 val = builder.CreateFMul (val, mone); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1751 fn.do_return (builder, val); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1752 } |
20654 | 1753 // gccjit implementation of octave_jit_uminus: |
1754 #ifdef HAVE_GCCJIT | |
1755 { | |
1756 gccjit::function gf = fn.gccjit_function; | |
1757 gccjit::block b = gf.new_block (); | |
1758 b.end_with_return (-gf.get_param (0)); | |
1759 } | |
1760 #endif | |
15146
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1761 |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1762 fn = create_identity (scalar); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1763 unary_ops[octave_value::op_uplus].add_overload (fn); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1764 unary_ops[octave_value::op_transpose].add_overload (fn); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1765 unary_ops[octave_value::op_hermitian].add_overload (fn); |
709e8928e68c
Scalar unary operation support in JIT
Max Brister <max@2bass.com>
parents:
15136
diff
changeset
|
1766 |
15016 | 1767 // now for binary complex operations |
20654 | 1768 fn = create_internal ("octave_jit_plus_complex_complex", complex, complex, |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1769 complex); |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1770 body = fn.new_block (); |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1771 builder.SetInsertPoint (body); |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1772 { |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1773 llvm::Value *lhs = fn.argument (builder, 0); |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1774 llvm::Value *rhs = fn.argument (builder, 1); |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1775 llvm::Value *real = builder.CreateFAdd (complex_real (lhs), |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1776 complex_real (rhs)); |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1777 llvm::Value *imag = builder.CreateFAdd (complex_imag (lhs), |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1778 complex_imag (rhs)); |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1779 fn.do_return (builder, complex_new (real, imag)); |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1780 } |
20654 | 1781 // gccjit implementation of octave_jit_plus_complex_complex: |
1782 #ifdef HAVE_GCCJIT | |
1783 { | |
1784 gccjit::function gf = fn.gccjit_function; | |
1785 gccjit::block b = gf.new_block (); | |
1786 gccjit::rvalue lhs = gf.get_param (0); | |
1787 gccjit::rvalue rhs = gf.get_param (1); | |
1788 gccjit::rvalue real = complex_real (lhs) + complex_real (rhs); | |
1789 gccjit::rvalue imag = complex_imag (lhs) + complex_imag (rhs); | |
1790 b.end_with_return (complex_new (b, real, imag)); | |
1791 } | |
1792 #endif | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1793 binary_ops[octave_value::op_add].add_overload (fn); |
15016 | 1794 |
20654 | 1795 fn = create_internal ("octave_jit_minus_complex_complex", complex, complex, |
15016 | 1796 complex); |
1797 body = fn.new_block (); | |
1798 builder.SetInsertPoint (body); | |
1799 { | |
1800 llvm::Value *lhs = fn.argument (builder, 0); | |
1801 llvm::Value *rhs = fn.argument (builder, 1); | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1802 llvm::Value *real = builder.CreateFSub (complex_real (lhs), |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1803 complex_real (rhs)); |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1804 llvm::Value *imag = builder.CreateFSub (complex_imag (lhs), |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1805 complex_imag (rhs)); |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1806 fn.do_return (builder, complex_new (real, imag)); |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1807 } |
20654 | 1808 // gccjit implementation of octave_jit_minus_complex_complex: |
1809 #ifdef HAVE_GCCJIT | |
1810 { | |
1811 gccjit::function gf = fn.gccjit_function; | |
1812 gccjit::block b = gf.new_block (); | |
1813 gccjit::rvalue lhs = gf.get_param (0); | |
1814 gccjit::rvalue rhs = gf.get_param (1); | |
1815 gccjit::rvalue real = complex_real (lhs) - complex_real (rhs); | |
1816 gccjit::rvalue imag = complex_imag (lhs) - complex_imag (rhs); | |
1817 b.end_with_return (complex_new (b, real, imag)); | |
1818 } | |
1819 #endif | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1820 binary_ops[octave_value::op_sub].add_overload (fn); |
15016 | 1821 |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1822 fn = create_external (JIT_FN (octave_jit_complex_mul), |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1823 complex, complex, complex); |
15016 | 1824 binary_ops[octave_value::op_mul].add_overload (fn); |
1825 binary_ops[octave_value::op_el_mul].add_overload (fn); | |
1826 | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1827 jit_function complex_div = create_external (JIT_FN (octave_jit_complex_div), |
15016 | 1828 complex, complex, complex); |
1829 complex_div.mark_can_error (); | |
1830 binary_ops[octave_value::op_div].add_overload (fn); | |
1831 binary_ops[octave_value::op_ldiv].add_overload (fn); | |
1832 | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1833 fn = create_external (JIT_FN (octave_jit_pow_complex_complex), complex, |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1834 complex, complex); |
15016 | 1835 binary_ops[octave_value::op_pow].add_overload (fn); |
1836 binary_ops[octave_value::op_el_pow].add_overload (fn); | |
1837 | |
20654 | 1838 fn = create_internal ("octave_jit_mult_scalar_complex", complex, scalar, |
15016 | 1839 complex); |
1840 jit_function mul_scalar_complex = fn; | |
1841 body = fn.new_block (); | |
1842 builder.SetInsertPoint (body); | |
1843 { | |
15583
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
1844 llvm::BasicBlock *complex_mul = fn.new_block ("complex_mul"); |
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
1845 llvm::BasicBlock *scalar_mul = fn.new_block ("scalar_mul"); |
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
1846 |
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
1847 llvm::Value *fzero = llvm::ConstantFP::get (scalar_t, 0); |
15016 | 1848 llvm::Value *lhs = fn.argument (builder, 0); |
1849 llvm::Value *rhs = fn.argument (builder, 1); | |
15583
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
1850 |
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
1851 llvm::Value *cmp = builder.CreateFCmpUEQ (complex_imag (rhs), fzero); |
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
1852 builder.CreateCondBr (cmp, scalar_mul, complex_mul); |
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
1853 |
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
1854 builder.SetInsertPoint (scalar_mul); |
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
1855 llvm::Value *temp = complex_real (rhs); |
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
1856 temp = builder.CreateFMul (lhs, temp); |
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
1857 fn.do_return (builder, complex_new (temp, fzero), false); |
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
1858 |
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
1859 |
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
1860 builder.SetInsertPoint (complex_mul); |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1861 temp = complex_new (builder.CreateFMul (lhs, complex_real (rhs)), |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1862 builder.CreateFMul (lhs, complex_imag (rhs))); |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1863 fn.do_return (builder, temp); |
15016 | 1864 } |
20654 | 1865 // gccjit implementation of octave_jit_mult_scalar_complex: |
1866 #ifdef HAVE_GCCJIT | |
1867 { | |
1868 gccjit::function gf = fn.gccjit_function; | |
1869 | |
1870 gccjit::rvalue fzero = scalar_t_gcc.zero (); | |
1871 gccjit::rvalue lhs = gf.get_param (0); | |
1872 gccjit::rvalue rhs = gf.get_param (1); | |
1873 | |
1874 gccjit::block initial = gf.new_block ("initial"); | |
1875 gccjit::block complex_mul = gf.new_block ("complex_mul"); | |
1876 gccjit::block scalar_mul = gf.new_block ("scalar_mul"); | |
1877 | |
1878 initial.end_with_conditional (complex_imag (rhs) == fzero, | |
1879 scalar_mul, | |
1880 complex_mul); | |
1881 | |
1882 scalar_mul.end_with_return (complex_new (scalar_mul, | |
1883 lhs * complex_real (rhs), | |
1884 fzero)); | |
1885 complex_mul.end_with_return (complex_new (complex_mul, | |
1886 lhs * complex_real (rhs), | |
1887 lhs * complex_imag (rhs))); | |
1888 } | |
1889 #endif | |
15016 | 1890 binary_ops[octave_value::op_mul].add_overload (fn); |
1891 binary_ops[octave_value::op_el_mul].add_overload (fn); | |
1892 | |
1893 | |
1894 fn = mirror_binary (mul_scalar_complex); | |
1895 binary_ops[octave_value::op_mul].add_overload (fn); | |
1896 binary_ops[octave_value::op_el_mul].add_overload (fn); | |
1897 | |
20654 | 1898 fn = create_internal ("octave_jit_plus_scalar_complex", complex, scalar, |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1899 complex); |
15016 | 1900 body = fn.new_block (); |
1901 builder.SetInsertPoint (body); | |
1902 { | |
1903 llvm::Value *lhs = fn.argument (builder, 0); | |
1904 llvm::Value *rhs = fn.argument (builder, 1); | |
1905 llvm::Value *real = builder.CreateFAdd (lhs, complex_real (rhs)); | |
1906 fn.do_return (builder, complex_real (rhs, real)); | |
1907 } | |
20654 | 1908 // gccjit implementation of octave_jit_plus_scalar_complex: |
1909 #ifdef HAVE_GCCJIT | |
1910 { | |
1911 gccjit::function gf = fn.gccjit_function; | |
1912 gccjit::block b = gf.new_block (); | |
1913 gccjit::rvalue lhs = gf.get_param (0); | |
1914 gccjit::lvalue rhs = gf.get_param (1); | |
1915 gccjit::rvalue real = lhs + complex_real (rhs); | |
1916 b.end_with_return (complex_real (b, rhs, real)); | |
1917 } | |
1918 #endif | |
15016 | 1919 binary_ops[octave_value::op_add].add_overload (fn); |
1920 | |
1921 fn = mirror_binary (fn); | |
1922 binary_ops[octave_value::op_add].add_overload (fn); | |
1923 | |
20654 | 1924 fn = create_internal ("octave_jit_minus_complex_scalar", complex, complex, |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1925 scalar); |
15016 | 1926 body = fn.new_block (); |
1927 builder.SetInsertPoint (body); | |
1928 { | |
1929 llvm::Value *lhs = fn.argument (builder, 0); | |
1930 llvm::Value *rhs = fn.argument (builder, 1); | |
1931 llvm::Value *real = builder.CreateFSub (complex_real (lhs), rhs); | |
1932 fn.do_return (builder, complex_real (lhs, real)); | |
1933 } | |
20654 | 1934 // gccjit implementation of octave_jit_minus_complex_scalar: |
1935 #ifdef HAVE_GCCJIT | |
1936 { | |
1937 gccjit::function gf = fn.gccjit_function; | |
1938 gccjit::block b = gf.new_block (); | |
1939 gccjit::lvalue lhs = gf.get_param (0); | |
1940 gccjit::rvalue rhs = gf.get_param (1); | |
1941 gccjit::rvalue real = complex_real (lhs) - rhs; | |
1942 b.end_with_return (complex_real (b, lhs, real)); | |
1943 } | |
1944 #endif | |
15016 | 1945 binary_ops[octave_value::op_sub].add_overload (fn); |
1946 | |
20654 | 1947 fn = create_internal ("octave_jit_minus_scalar_complex", complex, scalar, |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1948 complex); |
15016 | 1949 body = fn.new_block (); |
1950 builder.SetInsertPoint (body); | |
1951 { | |
1952 llvm::Value *lhs = fn.argument (builder, 0); | |
1953 llvm::Value *rhs = fn.argument (builder, 1); | |
1954 llvm::Value *real = builder.CreateFSub (lhs, complex_real (rhs)); | |
1955 fn.do_return (builder, complex_real (rhs, real)); | |
1956 } | |
20654 | 1957 // gccjit implementation of octave_jit_minus_scalar_complex: |
1958 #ifdef HAVE_GCCJIT | |
1959 { | |
1960 gccjit::function gf = fn.gccjit_function; | |
1961 gccjit::block b = gf.new_block (); | |
1962 gccjit::rvalue lhs = gf.get_param (0); | |
1963 gccjit::lvalue rhs = gf.get_param (1); | |
1964 gccjit::rvalue real = lhs - complex_real (rhs); | |
1965 b.end_with_return (complex_real (b, rhs, real)); | |
1966 } | |
1967 #endif | |
15016 | 1968 binary_ops[octave_value::op_sub].add_overload (fn); |
1969 | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1970 fn = create_external (JIT_FN (octave_jit_pow_scalar_complex), complex, scalar, |
15016 | 1971 complex); |
1972 binary_ops[octave_value::op_pow].add_overload (fn); | |
1973 binary_ops[octave_value::op_el_pow].add_overload (fn); | |
1974 | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1975 fn = create_external (JIT_FN (octave_jit_pow_complex_scalar), complex, |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
1976 complex, scalar); |
15016 | 1977 binary_ops[octave_value::op_pow].add_overload (fn); |
1978 binary_ops[octave_value::op_el_pow].add_overload (fn); | |
1979 | |
1980 // now for binary index operators | |
20654 | 1981 #ifdef HAVE_GCCJIT |
1982 add_binary_op (index, octave_value::op_add, | |
1983 llvm::Instruction::Add, | |
1984 GCC_JIT_BINARY_OP_PLUS); | |
1985 | |
1986 // and binary bool operators | |
1987 add_binary_op (boolean, octave_value::op_el_or, | |
1988 llvm::Instruction::Or, | |
1989 GCC_JIT_BINARY_OP_LOGICAL_OR); | |
1990 add_binary_op (boolean, octave_value::op_el_and, | |
1991 llvm::Instruction::And, | |
1992 GCC_JIT_BINARY_OP_LOGICAL_AND); | |
1993 #else | |
15016 | 1994 add_binary_op (index, octave_value::op_add, llvm::Instruction::Add); |
1995 | |
1996 // and binary bool operators | |
1997 add_binary_op (boolean, octave_value::op_el_or, llvm::Instruction::Or); | |
1998 add_binary_op (boolean, octave_value::op_el_and, llvm::Instruction::And); | |
20654 | 1999 #endif |
15016 | 2000 |
2001 // now for printing functions | |
2002 print_fn.stash_name ("print"); | |
15019
ae3670d4df29
Update the execution engine's global mapping for external functions
Max Brister <max@2bass.com>
parents:
15016
diff
changeset
|
2003 add_print (any, reinterpret_cast<void *> (&octave_jit_print_any)); |
ae3670d4df29
Update the execution engine's global mapping for external functions
Max Brister <max@2bass.com>
parents:
15016
diff
changeset
|
2004 add_print (scalar, reinterpret_cast<void *> (&octave_jit_print_scalar)); |
15016 | 2005 |
2006 // initialize for loop | |
2007 for_init_fn.stash_name ("for_init"); | |
2008 | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2009 fn = create_internal ("octave_jit_for_range_init", index, range); |
15016 | 2010 body = fn.new_block (); |
2011 builder.SetInsertPoint (body); | |
2012 { | |
2013 llvm::Value *zero = llvm::ConstantInt::get (index_t, 0); | |
2014 fn.do_return (builder, zero); | |
2015 } | |
20654 | 2016 #ifdef HAVE_GCCJIT |
2017 { | |
2018 gccjit::function gf = fn.gccjit_function; | |
2019 gccjit::block b = gf.new_block (); | |
2020 b.end_with_return (gccjit_ctxt.zero (index_t_gcc)); | |
2021 } | |
2022 #endif | |
15016 | 2023 for_init_fn.add_overload (fn); |
2024 | |
2025 // bounds check for for loop | |
2026 for_check_fn.stash_name ("for_check"); | |
2027 | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2028 fn = create_internal ("octave_jit_for_range_check", boolean, range, index); |
15016 | 2029 body = fn.new_block (); |
2030 builder.SetInsertPoint (body); | |
2031 { | |
2032 llvm::Value *nelem | |
2033 = builder.CreateExtractValue (fn.argument (builder, 0), 3); | |
2034 llvm::Value *idx = fn.argument (builder, 1); | |
2035 llvm::Value *ret = builder.CreateICmpULT (idx, nelem); | |
2036 fn.do_return (builder, ret); | |
20654 | 2037 |
15016 | 2038 } |
20654 | 2039 #ifdef HAVE_GCCJIT |
2040 { | |
2041 gccjit::function gf = fn.gccjit_function; | |
2042 // FIXME: is "range" a (struct range) or a (struct range *) ? | |
2043 gccjit::rvalue nelem | |
2044 = gf.get_param (0).access_field (field_rng_nelem); | |
2045 gccjit::rvalue idx = gf.get_param (1); | |
2046 gccjit::rvalue ret = idx < nelem; | |
2047 gccjit::block b = gf.new_block (); | |
2048 b.end_with_return (ret); | |
2049 } | |
2050 #endif | |
15016 | 2051 for_check_fn.add_overload (fn); |
2052 | |
2053 // index variabe for for loop | |
2054 for_index_fn.stash_name ("for_index"); | |
2055 | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2056 fn = create_internal ("octave_jit_for_range_idx", scalar, range, index); |
15016 | 2057 body = fn.new_block (); |
2058 builder.SetInsertPoint (body); | |
2059 { | |
2060 llvm::Value *idx = fn.argument (builder, 1); | |
2061 llvm::Value *didx = builder.CreateSIToFP (idx, scalar_t); | |
2062 llvm::Value *rng = fn.argument (builder, 0); | |
2063 llvm::Value *base = builder.CreateExtractValue (rng, 0); | |
2064 llvm::Value *inc = builder.CreateExtractValue (rng, 2); | |
2065 | |
2066 llvm::Value *ret = builder.CreateFMul (didx, inc); | |
2067 ret = builder.CreateFAdd (base, ret); | |
2068 fn.do_return (builder, ret); | |
2069 } | |
20654 | 2070 #ifdef HAVE_GCCJIT |
2071 { | |
2072 gccjit::function gf = fn.gccjit_function; | |
2073 gccjit::block b = gf.new_block (); | |
2074 gccjit::rvalue idx = gf.get_param (1); | |
2075 gccjit::rvalue didx = idx.cast_to (scalar_t_gcc); | |
2076 gccjit::rvalue rng = gf.get_param (0); | |
2077 gccjit::rvalue base = rng.access_field (field_rng_base); | |
2078 gccjit::rvalue inc = rng.access_field (field_rng_inc); | |
2079 gccjit::rvalue ret = didx * inc; | |
2080 ret = base + ret; | |
2081 b.end_with_return (ret); | |
2082 } | |
2083 #endif | |
15016 | 2084 for_index_fn.add_overload (fn); |
2085 | |
2086 // logically true | |
2087 logically_true_fn.stash_name ("logically_true"); | |
2088 | |
2089 jit_function gripe_nantl | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2090 = create_external (JIT_FN (octave_jit_gripe_nan_to_logical_conversion), 0); |
15016 | 2091 gripe_nantl.mark_can_error (); |
2092 | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2093 fn = create_internal ("octave_jit_logically_true_scalar", boolean, scalar); |
15016 | 2094 fn.mark_can_error (); |
2095 | |
2096 body = fn.new_block (); | |
2097 builder.SetInsertPoint (body); | |
2098 { | |
2099 llvm::BasicBlock *error_block = fn.new_block ("error"); | |
2100 llvm::BasicBlock *normal_block = fn.new_block ("normal"); | |
2101 | |
2102 llvm::Value *check = builder.CreateFCmpUNE (fn.argument (builder, 0), | |
2103 fn.argument (builder, 0)); | |
2104 builder.CreateCondBr (check, error_block, normal_block); | |
2105 | |
2106 builder.SetInsertPoint (error_block); | |
2107 gripe_nantl.call (builder); | |
2108 builder.CreateBr (normal_block); | |
2109 builder.SetInsertPoint (normal_block); | |
2110 | |
2111 llvm::Value *zero = llvm::ConstantFP::get (scalar_t, 0); | |
2112 llvm::Value *ret = builder.CreateFCmpONE (fn.argument (builder, 0), zero); | |
2113 fn.do_return (builder, ret); | |
2114 } | |
20654 | 2115 #ifdef HAVE_GCCJIT |
2116 { | |
2117 gccjit::function gf = fn.gccjit_function; | |
2118 gccjit::block initial = gf.new_block ("initial"); | |
2119 gccjit::block error = gf.new_block ("error"); | |
2120 gccjit::block normal = gf.new_block ("normal"); | |
2121 initial.add_comment ("check for NaN"); | |
2122 initial.end_with_conditional (gf.get_param (0) != gf.get_param (0), | |
2123 error, normal); | |
2124 | |
2125 error.add_call (gripe_nantl.gccjit_function); | |
2126 error.end_with_jump (normal); | |
2127 | |
2128 normal.end_with_return ( gf.get_param (0) != scalar_t_gcc.zero ()); | |
2129 } | |
2130 #endif | |
15016 | 2131 logically_true_fn.add_overload (fn); |
2132 | |
2133 // logically_true boolean | |
2134 fn = create_identity (boolean); | |
2135 logically_true_fn.add_overload (fn); | |
2136 | |
2137 // make_range | |
2138 // FIXME: May be benificial to implement all in LLVM | |
2139 make_range_fn.stash_name ("make_range"); | |
2140 jit_function compute_nelem | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2141 = create_external (JIT_FN (octave_jit_compute_nelem), |
15016 | 2142 index, scalar, scalar, scalar); |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2143 |
15016 | 2144 |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2145 fn = create_internal ("octave_jit_make_range", range, scalar, scalar, scalar); |
15016 | 2146 body = fn.new_block (); |
2147 builder.SetInsertPoint (body); | |
2148 { | |
2149 llvm::Value *base = fn.argument (builder, 0); | |
2150 llvm::Value *limit = fn.argument (builder, 1); | |
2151 llvm::Value *inc = fn.argument (builder, 2); | |
2152 llvm::Value *nelem = compute_nelem.call (builder, base, limit, inc); | |
2153 | |
2154 llvm::Value *dzero = llvm::ConstantFP::get (scalar_t, 0); | |
2155 llvm::Value *izero = llvm::ConstantInt::get (index_t, 0); | |
2156 llvm::Value *rng = llvm::ConstantStruct::get (range_t, dzero, dzero, dzero, | |
2157 izero, NULL); | |
2158 rng = builder.CreateInsertValue (rng, base, 0); | |
2159 rng = builder.CreateInsertValue (rng, limit, 1); | |
2160 rng = builder.CreateInsertValue (rng, inc, 2); | |
2161 rng = builder.CreateInsertValue (rng, nelem, 3); | |
2162 fn.do_return (builder, rng); | |
2163 } | |
20654 | 2164 #ifdef HAVE_GCCJIT |
2165 { | |
2166 gccjit::function gf = fn.gccjit_function; | |
2167 gccjit::rvalue base = gf.get_param (0); | |
2168 gccjit::rvalue limit = gf.get_param (1); | |
2169 gccjit::rvalue inc = gf.get_param (2); | |
2170 gccjit::block b = gf.new_block (); | |
2171 gccjit::rvalue nelem = compute_nelem.gccjit_function (base, limit, inc); | |
2172 gccjit::lvalue rng = gf.new_local (range_t_gcc, "rng"); | |
2173 b.add_assignment (rng.access_field (field_rng_base), base); | |
2174 b.add_assignment (rng.access_field (field_rng_limit), limit); | |
2175 b.add_assignment (rng.access_field (field_rng_inc), inc); | |
2176 b.add_assignment (rng.access_field (field_rng_nelem), nelem); | |
2177 b.end_with_return (rng); | |
2178 } | |
2179 #endif | |
15016 | 2180 make_range_fn.add_overload (fn); |
2181 | |
2182 // paren_subsref | |
2183 jit_type *jit_int = intN (sizeof (int) * 8); | |
2184 llvm::Type *int_t = jit_int->to_llvm (); | |
2185 jit_function ginvalid_index | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2186 = create_external (JIT_FN (octave_jit_ginvalid_index), 0); |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2187 jit_function gindex_range = create_external (JIT_FN (octave_jit_gindex_range), |
15016 | 2188 0, jit_int, jit_int, index, |
2189 index); | |
2190 | |
20654 | 2191 fn = create_internal ("subsref", scalar, matrix, scalar); |
15016 | 2192 fn.mark_can_error (); |
2193 | |
2194 body = fn.new_block (); | |
2195 builder.SetInsertPoint (body); | |
2196 { | |
18274
e243b705a726
Fix building JIT with 64-bit indexing (bug #41163).
Lasse Schuirmann <lasse@schuirmann.net>
parents:
17787
diff
changeset
|
2197 llvm::Value *one_idx = llvm::ConstantInt::get (index_t, 1); |
e243b705a726
Fix building JIT with 64-bit indexing (bug #41163).
Lasse Schuirmann <lasse@schuirmann.net>
parents:
17787
diff
changeset
|
2198 llvm::Value *one_int = llvm::ConstantInt::get (int_t, 1); |
15016 | 2199 |
2200 llvm::Value *undef = llvm::UndefValue::get (scalar_t); | |
2201 llvm::Value *mat = fn.argument (builder, 0); | |
2202 llvm::Value *idx = fn.argument (builder, 1); | |
2203 | |
2204 // convert index to scalar to integer, and check index >= 1 | |
2205 llvm::Value *int_idx = builder.CreateFPToSI (idx, index_t); | |
2206 llvm::Value *check_idx = builder.CreateSIToFP (int_idx, scalar_t); | |
2207 llvm::Value *cond0 = builder.CreateFCmpUNE (idx, check_idx); | |
18274
e243b705a726
Fix building JIT with 64-bit indexing (bug #41163).
Lasse Schuirmann <lasse@schuirmann.net>
parents:
17787
diff
changeset
|
2208 llvm::Value *cond1 = builder.CreateICmpSLT (int_idx, one_idx); |
15016 | 2209 llvm::Value *cond = builder.CreateOr (cond0, cond1); |
2210 | |
2211 llvm::BasicBlock *done = fn.new_block ("done"); | |
2212 llvm::BasicBlock *conv_error = fn.new_block ("conv_error", done); | |
2213 llvm::BasicBlock *normal = fn.new_block ("normal", done); | |
2214 builder.CreateCondBr (cond, conv_error, normal); | |
2215 | |
2216 builder.SetInsertPoint (conv_error); | |
2217 ginvalid_index.call (builder); | |
2218 builder.CreateBr (done); | |
2219 | |
2220 builder.SetInsertPoint (normal); | |
17787
175b392e91fe
Use GNU style coding conventions for code in libinterp/
Rik <rik@octave.org>
parents:
17744
diff
changeset
|
2221 llvm::Value *len |
175b392e91fe
Use GNU style coding conventions for code in libinterp/
Rik <rik@octave.org>
parents:
17744
diff
changeset
|
2222 = builder.CreateExtractValue (mat, llvm::ArrayRef<unsigned> (2)); |
15016 | 2223 cond = builder.CreateICmpSGT (int_idx, len); |
2224 | |
2225 | |
2226 llvm::BasicBlock *bounds_error = fn.new_block ("bounds_error", done); | |
2227 llvm::BasicBlock *success = fn.new_block ("success", done); | |
2228 builder.CreateCondBr (cond, bounds_error, success); | |
2229 | |
2230 builder.SetInsertPoint (bounds_error); | |
18274
e243b705a726
Fix building JIT with 64-bit indexing (bug #41163).
Lasse Schuirmann <lasse@schuirmann.net>
parents:
17787
diff
changeset
|
2231 gindex_range.call (builder, one_int, one_int, int_idx, len); |
15016 | 2232 builder.CreateBr (done); |
2233 | |
2234 builder.SetInsertPoint (success); | |
2235 llvm::Value *data = builder.CreateExtractValue (mat, | |
2236 llvm::ArrayRef<unsigned> (1)); | |
2237 llvm::Value *gep = builder.CreateInBoundsGEP (data, int_idx); | |
2238 llvm::Value *ret = builder.CreateLoad (gep); | |
2239 builder.CreateBr (done); | |
2240 | |
2241 builder.SetInsertPoint (done); | |
2242 | |
2243 llvm::PHINode *merge = llvm::PHINode::Create (scalar_t, 3); | |
2244 builder.Insert (merge); | |
2245 merge->addIncoming (undef, conv_error); | |
2246 merge->addIncoming (undef, bounds_error); | |
2247 merge->addIncoming (ret, success); | |
2248 fn.do_return (builder, merge); | |
2249 } | |
20654 | 2250 // gccjit implementation of subsref: |
2251 #ifdef HAVE_GCCJIT | |
2252 { | |
2253 gccjit::function gf = fn.gccjit_function; | |
2254 gccjit::block initial = gf.new_block ("initial"); | |
2255 | |
2256 gccjit::rvalue one_idx = index_t_gcc.one (); | |
2257 gccjit::rvalue one_int = jit_int->to_gccjit ().one (); | |
2258 | |
2259 gccjit::rvalue mat = gf.get_param (0); | |
2260 gccjit::rvalue idx = gf.get_param (1); // scalar | |
2261 | |
2262 // convert index to scalar to integer, and check index >= 1 | |
2263 gccjit::rvalue int_idx = idx.cast_to (index_t_gcc); | |
2264 gccjit::rvalue check_idx = int_idx.cast_to (scalar_t_gcc); | |
2265 gccjit::rvalue cond0 = (idx != check_idx); | |
2266 gccjit::rvalue cond1 = (int_idx < one_idx); | |
2267 | |
2268 gccjit::block conv_error = gf.new_block ("conv_error"); | |
2269 gccjit::block normal = gf.new_block ("normal"); | |
2270 initial.end_with_conditional (cond0 || cond1, conv_error, normal); | |
2271 | |
2272 // "conv_error" block: | |
2273 conv_error.add_call (ginvalid_index.gccjit_function); | |
2274 conv_error.end_with_return (scalar_t_gcc.zero ()); // dummy value | |
2275 | |
2276 // "normal" block: | |
2277 gccjit::rvalue len = mat.access_field (field_slice_len); | |
2278 gccjit::rvalue cond = (int_idx > len); | |
2279 gccjit::block bounds_error = gf.new_block ("bounds_error"); | |
2280 gccjit::block success = gf.new_block ("success"); | |
2281 normal.end_with_conditional (cond, bounds_error, success); | |
2282 | |
2283 // "bounds_error" block: | |
2284 bounds_error.add_call (gindex_range.gccjit_function, | |
2285 one_int, one_int, int_idx, len); | |
2286 bounds_error.end_with_return (scalar_t_gcc.zero ()); // dummy value | |
2287 | |
2288 // "success" block: | |
2289 gccjit::rvalue data = mat.access_field (field_slice_data); | |
2290 gccjit::rvalue gep = data[int_idx]; | |
2291 gccjit::rvalue ret = gep; | |
2292 success.end_with_return (ret); | |
2293 } | |
2294 #endif | |
15016 | 2295 paren_subsref_fn.add_overload (fn); |
2296 | |
2297 // paren subsasgn | |
20654 | 2298 paren_subsasgn_fn.stash_name ("subsasgn"); |
15016 | 2299 |
2300 jit_function resize_paren_subsasgn | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2301 = create_external (JIT_FN (octave_jit_paren_subsasgn_impl), matrix, matrix, |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2302 index, scalar); |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2303 |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2304 fn = create_internal ("octave_jit_paren_subsasgn", matrix, matrix, scalar, |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2305 scalar); |
15016 | 2306 fn.mark_can_error (); |
2307 body = fn.new_block (); | |
2308 builder.SetInsertPoint (body); | |
2309 { | |
18274
e243b705a726
Fix building JIT with 64-bit indexing (bug #41163).
Lasse Schuirmann <lasse@schuirmann.net>
parents:
17787
diff
changeset
|
2310 llvm::Value *one_idx = llvm::ConstantInt::get (index_t, 1); |
e243b705a726
Fix building JIT with 64-bit indexing (bug #41163).
Lasse Schuirmann <lasse@schuirmann.net>
parents:
17787
diff
changeset
|
2311 llvm::Value *one_int = llvm::ConstantInt::get (int_t, 1); |
15016 | 2312 |
2313 llvm::Value *mat = fn.argument (builder, 0); | |
2314 llvm::Value *idx = fn.argument (builder, 1); | |
2315 llvm::Value *value = fn.argument (builder, 2); | |
2316 | |
2317 llvm::Value *int_idx = builder.CreateFPToSI (idx, index_t); | |
2318 llvm::Value *check_idx = builder.CreateSIToFP (int_idx, scalar_t); | |
2319 llvm::Value *cond0 = builder.CreateFCmpUNE (idx, check_idx); | |
18274
e243b705a726
Fix building JIT with 64-bit indexing (bug #41163).
Lasse Schuirmann <lasse@schuirmann.net>
parents:
17787
diff
changeset
|
2320 llvm::Value *cond1 = builder.CreateICmpSLT (int_idx, one_idx); |
15016 | 2321 llvm::Value *cond = builder.CreateOr (cond0, cond1); |
2322 | |
2323 llvm::BasicBlock *done = fn.new_block ("done"); | |
2324 | |
2325 llvm::BasicBlock *conv_error = fn.new_block ("conv_error", done); | |
2326 llvm::BasicBlock *normal = fn.new_block ("normal", done); | |
2327 builder.CreateCondBr (cond, conv_error, normal); | |
2328 builder.SetInsertPoint (conv_error); | |
2329 ginvalid_index.call (builder); | |
2330 builder.CreateBr (done); | |
2331 | |
2332 builder.SetInsertPoint (normal); | |
15056
bc32288f4a42
Support the end keyword for one dimentional indexing in JIT.
Max Brister <max@2bass.com>
parents:
15027
diff
changeset
|
2333 llvm::Value *len = builder.CreateExtractValue (mat, 2); |
15016 | 2334 cond0 = builder.CreateICmpSGT (int_idx, len); |
2335 | |
2336 llvm::Value *rcount = builder.CreateExtractValue (mat, 0); | |
2337 rcount = builder.CreateLoad (rcount); | |
18274
e243b705a726
Fix building JIT with 64-bit indexing (bug #41163).
Lasse Schuirmann <lasse@schuirmann.net>
parents:
17787
diff
changeset
|
2338 cond1 = builder.CreateICmpSGT (rcount, one_int); |
15016 | 2339 cond = builder.CreateOr (cond0, cond1); |
2340 | |
2341 llvm::BasicBlock *bounds_error = fn.new_block ("bounds_error", done); | |
2342 llvm::BasicBlock *success = fn.new_block ("success", done); | |
2343 builder.CreateCondBr (cond, bounds_error, success); | |
2344 | |
2345 // resize on out of bounds access | |
2346 builder.SetInsertPoint (bounds_error); | |
15027
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
2347 llvm::Value *resize_result = resize_paren_subsasgn.call (builder, mat, |
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
2348 int_idx, value); |
15016 | 2349 builder.CreateBr (done); |
2350 | |
2351 builder.SetInsertPoint (success); | |
17787
175b392e91fe
Use GNU style coding conventions for code in libinterp/
Rik <rik@octave.org>
parents:
17744
diff
changeset
|
2352 llvm::Value *data |
175b392e91fe
Use GNU style coding conventions for code in libinterp/
Rik <rik@octave.org>
parents:
17744
diff
changeset
|
2353 = builder.CreateExtractValue (mat, llvm::ArrayRef<unsigned> (1)); |
15016 | 2354 llvm::Value *gep = builder.CreateInBoundsGEP (data, int_idx); |
2355 builder.CreateStore (value, gep); | |
2356 builder.CreateBr (done); | |
2357 | |
2358 builder.SetInsertPoint (done); | |
2359 | |
2360 llvm::PHINode *merge = llvm::PHINode::Create (matrix_t, 3); | |
2361 builder.Insert (merge); | |
2362 merge->addIncoming (mat, conv_error); | |
2363 merge->addIncoming (resize_result, bounds_error); | |
2364 merge->addIncoming (mat, success); | |
2365 fn.do_return (builder, merge); | |
2366 } | |
20654 | 2367 // gccjit implementation of octave_jit_paren_subsasgn: |
2368 #ifdef HAVE_GCCJIT | |
2369 { | |
2370 gccjit::function gf = fn.gccjit_function; | |
2371 gccjit::block initial = gf.new_block ("initial"); | |
2372 gccjit::rvalue one_idx = index_t_gcc.one (); | |
2373 gccjit::rvalue one_int = jit_int->to_gccjit ().one (); | |
2374 | |
2375 gccjit::lvalue mat = gf.get_param (0); | |
2376 gccjit::rvalue idx = gf.get_param (1); | |
2377 gccjit::rvalue value = gf.get_param (2); | |
2378 gccjit::rvalue int_idx = idx.cast_to (index_t_gcc); | |
2379 gccjit::rvalue check_idx = int_idx.cast_to (scalar_t_gcc); | |
2380 gccjit::rvalue cond0 = (idx != check_idx); | |
2381 gccjit::rvalue cond1 = (int_idx < one_idx); | |
2382 gccjit::rvalue cond = (cond0 || cond1); | |
2383 | |
2384 gccjit::block conv_error = gf.new_block ("conv_error"); | |
2385 gccjit::block normal = gf.new_block ("normal"); | |
2386 initial.end_with_conditional (cond, conv_error, normal); | |
2387 | |
2388 // block: conv_error | |
2389 conv_error.add_call (ginvalid_index.gccjit_function); | |
2390 conv_error.end_with_return (mat); | |
2391 | |
2392 // block: normal | |
2393 gccjit::rvalue len = mat.access_field (field_slice_len); | |
2394 cond0 = (int_idx > len); | |
2395 | |
2396 gccjit::rvalue rcount = mat.access_field (field_ref_count); | |
2397 rcount = rcount.dereference (); | |
2398 cond1 = rcount > one_int; | |
2399 cond = (cond0 || cond1); | |
2400 | |
2401 gccjit::block bounds_error = gf.new_block ("bounds_error"); | |
2402 gccjit::block success = gf.new_block ("success"); | |
2403 normal.end_with_conditional (cond, bounds_error, success); | |
2404 | |
2405 // block: bounds_error | |
2406 // resize on out of bounds access | |
2407 std::vector<gccjit::rvalue> args (3); | |
2408 args[0] = mat; | |
2409 args[1] = int_idx; | |
2410 args[2] = value; | |
2411 gccjit::rvalue resize_result = | |
2412 resize_paren_subsasgn.call (gccjit_ctxt, bounds_error, args); | |
2413 bounds_error.end_with_return (resize_result); | |
2414 | |
2415 // block: success | |
2416 gccjit::rvalue data = mat.access_field (field_slice_data); | |
2417 gccjit::lvalue gep = data[int_idx]; | |
2418 success.add_assignment (gep, value); | |
2419 success.end_with_return (mat); | |
2420 } | |
2421 #endif | |
15016 | 2422 paren_subsasgn_fn.add_overload (fn); |
2423 | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2424 fn = create_external (JIT_FN (octave_jit_paren_subsasgn_matrix_range), matrix, |
15016 | 2425 matrix, range, scalar); |
2426 fn.mark_can_error (); | |
2427 paren_subsasgn_fn.add_overload (fn); | |
2428 | |
15102
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
2429 end1_fn.stash_name ("end1"); |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2430 fn = create_internal ("octave_jit_end1_matrix", scalar, matrix, index, index); |
15056
bc32288f4a42
Support the end keyword for one dimentional indexing in JIT.
Max Brister <max@2bass.com>
parents:
15027
diff
changeset
|
2431 body = fn.new_block (); |
bc32288f4a42
Support the end keyword for one dimentional indexing in JIT.
Max Brister <max@2bass.com>
parents:
15027
diff
changeset
|
2432 builder.SetInsertPoint (body); |
bc32288f4a42
Support the end keyword for one dimentional indexing in JIT.
Max Brister <max@2bass.com>
parents:
15027
diff
changeset
|
2433 { |
bc32288f4a42
Support the end keyword for one dimentional indexing in JIT.
Max Brister <max@2bass.com>
parents:
15027
diff
changeset
|
2434 llvm::Value *mat = fn.argument (builder, 0); |
bc32288f4a42
Support the end keyword for one dimentional indexing in JIT.
Max Brister <max@2bass.com>
parents:
15027
diff
changeset
|
2435 llvm::Value *ret = builder.CreateExtractValue (mat, 2); |
bc32288f4a42
Support the end keyword for one dimentional indexing in JIT.
Max Brister <max@2bass.com>
parents:
15027
diff
changeset
|
2436 fn.do_return (builder, builder.CreateSIToFP (ret, scalar_t)); |
bc32288f4a42
Support the end keyword for one dimentional indexing in JIT.
Max Brister <max@2bass.com>
parents:
15027
diff
changeset
|
2437 } |
20654 | 2438 #ifdef HAVE_GCCJIT |
2439 { | |
2440 gccjit::function gf = fn.gccjit_function; | |
2441 gccjit::rvalue mat = gf.get_param (0); | |
2442 // FIXME: is this the right behavior? | |
2443 gccjit::rvalue ret = mat.access_field (field_slice_len); | |
2444 gccjit::block b = gf.new_block (); | |
2445 b.end_with_return (ret.cast_to (scalar_t_gcc)); | |
2446 } | |
2447 #endif | |
15102
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
2448 end1_fn.add_overload (fn); |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
2449 |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
2450 end_fn.stash_name ("end"); |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2451 fn = create_external (JIT_FN (octave_jit_end_matrix),scalar, matrix, index, |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2452 index); |
15056
bc32288f4a42
Support the end keyword for one dimentional indexing in JIT.
Max Brister <max@2bass.com>
parents:
15027
diff
changeset
|
2453 end_fn.add_overload (fn); |
bc32288f4a42
Support the end keyword for one dimentional indexing in JIT.
Max Brister <max@2bass.com>
parents:
15027
diff
changeset
|
2454 |
15337
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
2455 // -------------------- create_undef -------------------- |
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
2456 create_undef_fn.stash_name ("create_undef"); |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2457 fn = create_external (JIT_FN (octave_jit_create_undef), any); |
15337
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
2458 create_undef_fn.add_overload (fn); |
3f43e9d6d86e
JIT compile anonymous functions
Max Brister <max@2bass.com>
parents:
15334
diff
changeset
|
2459 |
15016 | 2460 casts[any->type_id ()].stash_name ("(any)"); |
2461 casts[scalar->type_id ()].stash_name ("(scalar)"); | |
2462 casts[complex->type_id ()].stash_name ("(complex)"); | |
2463 casts[matrix->type_id ()].stash_name ("(matrix)"); | |
15603 | 2464 casts[range->type_id ()].stash_name ("(range)"); |
15016 | 2465 |
2466 // cast any <- matrix | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2467 fn = create_external (JIT_FN (octave_jit_cast_any_matrix), any, matrix); |
15016 | 2468 casts[any->type_id ()].add_overload (fn); |
2469 | |
2470 // cast matrix <- any | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2471 fn = create_external (JIT_FN (octave_jit_cast_matrix_any), matrix, any); |
15016 | 2472 casts[matrix->type_id ()].add_overload (fn); |
2473 | |
15027
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
2474 // cast any <- range |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2475 fn = create_external (JIT_FN (octave_jit_cast_any_range), any, range); |
15027
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
2476 casts[any->type_id ()].add_overload (fn); |
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
2477 |
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
2478 // cast range <- any |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2479 fn = create_external (JIT_FN (octave_jit_cast_range_any), range, any); |
15027
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
2480 casts[range->type_id ()].add_overload (fn); |
741d2dbcc117
Check trip count before compiling for loops.
Max Brister <max@2bass.com>
parents:
15019
diff
changeset
|
2481 |
15016 | 2482 // cast any <- scalar |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2483 fn = create_external (JIT_FN (octave_jit_cast_any_scalar), any, scalar); |
15016 | 2484 casts[any->type_id ()].add_overload (fn); |
2485 | |
2486 // cast scalar <- any | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2487 fn = create_external (JIT_FN (octave_jit_cast_scalar_any), scalar, any); |
15016 | 2488 casts[scalar->type_id ()].add_overload (fn); |
2489 | |
2490 // cast any <- complex | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2491 fn = create_external (JIT_FN (octave_jit_cast_any_complex), any, complex); |
15016 | 2492 casts[any->type_id ()].add_overload (fn); |
2493 | |
2494 // cast complex <- any | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2495 fn = create_external (JIT_FN (octave_jit_cast_complex_any), complex, any); |
15016 | 2496 casts[complex->type_id ()].add_overload (fn); |
2497 | |
2498 // cast complex <- scalar | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2499 fn = create_internal ("octave_jit_cast_complex_scalar", complex, scalar); |
15016 | 2500 body = fn.new_block (); |
2501 builder.SetInsertPoint (body); | |
2502 { | |
2503 llvm::Value *zero = llvm::ConstantFP::get (scalar_t, 0); | |
2504 fn.do_return (builder, complex_new (fn.argument (builder, 0), zero)); | |
2505 } | |
20654 | 2506 // gccjit implementation of octave_jit_cast_complex_scalar: |
2507 #ifdef HAVE_GCCJIT | |
2508 { | |
2509 gccjit::function gf = fn.gccjit_function; | |
2510 gccjit::block b = gf.new_block (); | |
2511 gccjit::rvalue zero = scalar_t_gcc.zero (); | |
2512 b.end_with_return (complex_new (b, gf.get_param (0), zero)); | |
2513 } | |
2514 #endif | |
15016 | 2515 casts[complex->type_id ()].add_overload (fn); |
2516 | |
2517 // cast scalar <- complex | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2518 fn = create_internal ("octave_jit_cast_scalar_complex", scalar, complex); |
15016 | 2519 body = fn.new_block (); |
2520 builder.SetInsertPoint (body); | |
2521 fn.do_return (builder, complex_real (fn.argument (builder, 0))); | |
20654 | 2522 #ifdef HAVE_GCCJIT |
2523 { | |
2524 gccjit::function gf = fn.gccjit_function; | |
2525 gccjit::block b = gf.new_block (); | |
2526 b.end_with_return (complex_real (gf.get_param (0))); | |
2527 } | |
2528 #endif | |
15016 | 2529 casts[scalar->type_id ()].add_overload (fn); |
2530 | |
2531 // cast any <- any | |
2532 fn = create_identity (any); | |
2533 casts[any->type_id ()].add_overload (fn); | |
2534 | |
2535 // cast scalar <- scalar | |
2536 fn = create_identity (scalar); | |
2537 casts[scalar->type_id ()].add_overload (fn); | |
2538 | |
2539 // cast complex <- complex | |
2540 fn = create_identity (complex); | |
2541 casts[complex->type_id ()].add_overload (fn); | |
2542 | |
2543 // -------------------- builtin functions -------------------- | |
2544 add_builtin ("#unknown_function"); | |
2545 unknown_function = builtins["#unknown_function"]; | |
2546 | |
2547 add_builtin ("sin"); | |
2548 register_intrinsic ("sin", llvm::Intrinsic::sin, scalar, scalar); | |
2549 register_generic ("sin", matrix, matrix); | |
2550 | |
2551 add_builtin ("cos"); | |
2552 register_intrinsic ("cos", llvm::Intrinsic::cos, scalar, scalar); | |
2553 register_generic ("cos", matrix, matrix); | |
2554 | |
2555 add_builtin ("exp"); | |
20654 | 2556 // FIXME: looks like a typo: "cos" here should be "exp": |
2557 // filed as http://savannah.gnu.org/bugs/index.php?41560 | |
2558 register_intrinsic ("exp", llvm::Intrinsic::cos, scalar, scalar); | |
15016 | 2559 register_generic ("exp", matrix, matrix); |
2560 | |
15169
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2561 add_builtin ("balance"); |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2562 register_generic ("balance", matrix, matrix); |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2563 |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2564 add_builtin ("cond"); |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2565 register_generic ("cond", scalar, matrix); |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2566 |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2567 add_builtin ("det"); |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2568 register_generic ("det", scalar, matrix); |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2569 |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2570 add_builtin ("norm"); |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2571 register_generic ("norm", scalar, matrix); |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2572 |
20654 | 2573 //FIXME: gccjit can't yet cope with duplicate names |
2574 #if !defined (HAVE_GCCJIT) | |
15169
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2575 add_builtin ("rand"); |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2576 register_generic ("rand", matrix, scalar); |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2577 register_generic ("rand", matrix, std::vector<jit_type *> (2, scalar)); |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2578 |
20654 | 2579 |
15169
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2580 add_builtin ("magic"); |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2581 register_generic ("magic", matrix, scalar); |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2582 register_generic ("magic", matrix, std::vector<jit_type *> (2, scalar)); |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2583 |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2584 add_builtin ("eye"); |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2585 register_generic ("eye", matrix, scalar); |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2586 register_generic ("eye", matrix, std::vector<jit_type *> (2, scalar)); |
20654 | 2587 #endif |
15169
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2588 |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2589 add_builtin ("mod"); |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2590 register_generic ("mod", scalar, std::vector<jit_type *> (2, scalar)); |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2591 |
15016 | 2592 casts.resize (next_id + 1); |
2593 jit_function any_id = create_identity (any); | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2594 jit_function grab_any = create_external (JIT_FN (octave_jit_grab_any), |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2595 any, any); |
15016 | 2596 jit_function release_any = get_release (any); |
2597 std::vector<jit_type *> args; | |
2598 args.resize (1); | |
2599 | |
2600 for (std::map<std::string, jit_type *>::iterator iter = builtins.begin (); | |
2601 iter != builtins.end (); ++iter) | |
2602 { | |
2603 jit_type *btype = iter->second; | |
2604 args[0] = btype; | |
2605 | |
15334
8125773322d4
Error on undefined an unused variables in JIT
Max Brister <max@2bass.com>
parents:
15311
diff
changeset
|
2606 grab_fn.add_overload (jit_function (grab_any, btype, args)); |
15016 | 2607 release_fn.add_overload (jit_function (release_any, 0, args)); |
2608 casts[any->type_id ()].add_overload (jit_function (any_id, any, args)); | |
2609 | |
2610 args[0] = any; | |
2611 casts[btype->type_id ()].add_overload (jit_function (any_id, btype, | |
2612 args)); | |
2613 } | |
20654 | 2614 #ifdef HAVE_GCCJIT |
2615 gccjit_ctxt.dump_to_file ("/tmp/jit-typeinfo-dump.c", true); | |
2616 #endif | |
15016 | 2617 } |
2618 | |
15102
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
2619 const jit_function& |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
2620 jit_typeinfo::do_end (jit_value *value, jit_value *idx, jit_value *count) |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
2621 { |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
2622 jit_const_index *ccount = dynamic_cast<jit_const_index *> (count); |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
2623 if (ccount && ccount->value () == 1) |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
2624 return end1_fn.overload (value->type (), idx->type (), count->type ()); |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
2625 |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
2626 return end_fn.overload (value->type (), idx->type (), count->type ()); |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
2627 } |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
2628 |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
2629 jit_type* |
20654 | 2630 jit_typeinfo::new_type (const std::string& name, jit_type *parent |
2631 #ifdef HAVE_LLVM | |
2632 , llvm::Type *llvm_type | |
2633 #endif | |
2634 #ifdef HAVE_GCCJIT | |
2635 , gccjit::type gccjit_type | |
2636 #endif | |
2637 , bool skip_paren) | |
15102
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
2638 { |
20654 | 2639 jit_type *ret = new jit_type (name, parent |
2640 #ifdef HAVE_LLVM | |
2641 , llvm_type | |
2642 #endif | |
2643 #ifdef HAVE_GCCJIT | |
2644 , gccjit_type | |
2645 #endif | |
2646 , skip_paren, next_id++); | |
15102
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
2647 id_to_type.push_back (ret); |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
2648 return ret; |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
2649 } |
d29f2583cf7b
Support end in multi indexing in JIT
Max Brister <max@2bass.com>
parents:
15096
diff
changeset
|
2650 |
15016 | 2651 void |
15019
ae3670d4df29
Update the execution engine's global mapping for external functions
Max Brister <max@2bass.com>
parents:
15016
diff
changeset
|
2652 jit_typeinfo::add_print (jit_type *ty, void *fptr) |
15016 | 2653 { |
2654 std::stringstream name; | |
2655 name << "octave_jit_print_" << ty->name (); | |
17787
175b392e91fe
Use GNU style coding conventions for code in libinterp/
Rik <rik@octave.org>
parents:
17744
diff
changeset
|
2656 jit_function fn = create_external (engine, fptr, name.str (), |
175b392e91fe
Use GNU style coding conventions for code in libinterp/
Rik <rik@octave.org>
parents:
17744
diff
changeset
|
2657 0, intN (8), ty); |
15016 | 2658 print_fn.add_overload (fn); |
2659 } | |
2660 | |
2661 // FIXME: cp between add_binary_op, add_binary_icmp, and add_binary_fcmp | |
2662 void | |
20654 | 2663 jit_typeinfo::add_binary_op (jit_type *ty, int op |
2664 , int llvm_op | |
2665 #ifdef HAVE_GCCJIT | |
2666 , enum gcc_jit_binary_op gccjit_op | |
2667 #endif | |
2668 ) | |
15016 | 2669 { |
2670 std::stringstream fname; | |
2671 octave_value::binary_op ov_op = static_cast<octave_value::binary_op>(op); | |
20654 | 2672 fname << "octave_jit_" << octave_value::binary_op_fcn_name (ov_op) |
15016 | 2673 << "_" << ty->name (); |
2674 | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2675 jit_function fn = create_internal (fname.str (), ty, ty, ty); |
20654 | 2676 |
2677 // LLVM implementation: | |
15016 | 2678 llvm::BasicBlock *block = fn.new_block (); |
2679 builder.SetInsertPoint (block); | |
2680 llvm::Instruction::BinaryOps temp | |
2681 = static_cast<llvm::Instruction::BinaryOps>(llvm_op); | |
2682 | |
2683 llvm::Value *ret = builder.CreateBinOp (temp, fn.argument (builder, 0), | |
2684 fn.argument (builder, 1)); | |
2685 fn.do_return (builder, ret); | |
20654 | 2686 |
2687 // gccjit implementation: | |
2688 #ifdef HAVE_GCCJIT | |
2689 gccjit::function gf = fn.gccjit_function; | |
2690 gccjit::block b = gf.new_block (); | |
2691 b.end_with_return ( | |
2692 gf.get_context ().new_binary_op ( | |
2693 gccjit_op, | |
2694 ty->to_gccjit (), | |
2695 gf.get_param (0), | |
2696 gf.get_param (1))); | |
2697 #endif | |
15016 | 2698 binary_ops[op].add_overload (fn); |
2699 } | |
2700 | |
2701 void | |
20654 | 2702 jit_typeinfo::add_binary_icmp (jit_type *ty, int op |
2703 , int llvm_op | |
2704 #ifdef HAVE_GCCJIT | |
2705 , enum gcc_jit_comparison gccjit_op | |
2706 #endif | |
2707 ) | |
15016 | 2708 { |
2709 std::stringstream fname; | |
2710 octave_value::binary_op ov_op = static_cast<octave_value::binary_op>(op); | |
20654 | 2711 fname << "octave_jit_" << octave_value::binary_op_fcn_name (ov_op) |
15016 | 2712 << "_" << ty->name (); |
2713 | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2714 jit_function fn = create_internal (fname.str (), boolean, ty, ty); |
20654 | 2715 |
2716 // LLVM implementation: | |
15016 | 2717 llvm::BasicBlock *block = fn.new_block (); |
2718 builder.SetInsertPoint (block); | |
2719 llvm::CmpInst::Predicate temp | |
2720 = static_cast<llvm::CmpInst::Predicate>(llvm_op); | |
2721 llvm::Value *ret = builder.CreateICmp (temp, fn.argument (builder, 0), | |
2722 fn.argument (builder, 1)); | |
2723 fn.do_return (builder, ret); | |
20654 | 2724 |
2725 // gccjit implementation: | |
2726 #ifdef HAVE_GCCJIT | |
2727 gccjit::function gf = fn.gccjit_function; | |
2728 gccjit::block b = gf.new_block (); | |
2729 b.end_with_return ( | |
2730 gf.get_context ().new_comparison ( | |
2731 gccjit_op, | |
2732 gf.get_param (0), | |
2733 gf.get_param (1))); | |
2734 #endif | |
15016 | 2735 binary_ops[op].add_overload (fn); |
2736 } | |
2737 | |
2738 void | |
20654 | 2739 jit_typeinfo::add_binary_fcmp (jit_type *ty, int op |
2740 , int llvm_op | |
2741 #ifdef HAVE_GCCJIT | |
2742 , enum gcc_jit_comparison gccjit_op | |
2743 #endif | |
2744 ) | |
15016 | 2745 { |
2746 std::stringstream fname; | |
2747 octave_value::binary_op ov_op = static_cast<octave_value::binary_op>(op); | |
20654 | 2748 fname << "octave_jit_" << octave_value::binary_op_fcn_name (ov_op) |
15016 | 2749 << "_" << ty->name (); |
2750 | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2751 jit_function fn = create_internal (fname.str (), boolean, ty, ty); |
20654 | 2752 |
2753 // LLVM implementation: | |
15016 | 2754 llvm::BasicBlock *block = fn.new_block (); |
2755 builder.SetInsertPoint (block); | |
2756 llvm::CmpInst::Predicate temp | |
2757 = static_cast<llvm::CmpInst::Predicate>(llvm_op); | |
2758 llvm::Value *ret = builder.CreateFCmp (temp, fn.argument (builder, 0), | |
2759 fn.argument (builder, 1)); | |
2760 fn.do_return (builder, ret); | |
20654 | 2761 |
2762 // gccjit implementation: | |
2763 #ifdef HAVE_GCCJIT | |
2764 gccjit::function gf = fn.gccjit_function; | |
2765 gccjit::block b = gf.new_block (); | |
2766 b.end_with_return ( | |
2767 gf.get_context ().new_comparison ( | |
2768 gccjit_op, | |
2769 gf.get_param (0), | |
2770 gf.get_param (1))); | |
2771 #endif | |
15016 | 2772 binary_ops[op].add_overload (fn); |
2773 } | |
2774 | |
2775 jit_function | |
20654 | 2776 jit_typeinfo::create_function (jit_convention::type cc, std::string name, |
15016 | 2777 jit_type *ret, |
2778 const std::vector<jit_type *>& args) | |
2779 { | |
20654 | 2780 jit_function result (module, |
2781 #ifdef HAVE_GCCJIT | |
2782 gccjit_ctxt, | |
2783 #endif | |
2784 cc, name, ret, args); | |
15016 | 2785 return result; |
2786 } | |
2787 | |
2788 jit_function | |
2789 jit_typeinfo::create_identity (jit_type *type) | |
2790 { | |
2791 size_t id = type->type_id (); | |
2792 if (id >= identities.size ()) | |
2793 identities.resize (id + 1); | |
2794 | |
2795 if (! identities[id].valid ()) | |
2796 { | |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
2797 std::stringstream name; |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
2798 name << "id_" << type->name (); |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
2799 |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2800 jit_function fn = create_internal (name.str (), type, type); |
20654 | 2801 |
2802 // LLVM implementation: | |
15016 | 2803 llvm::BasicBlock *body = fn.new_block (); |
2804 builder.SetInsertPoint (body); | |
2805 fn.do_return (builder, fn.argument (builder, 0)); | |
20654 | 2806 |
2807 // gccjit implementation: | |
2808 #ifdef HAVE_GCCJIT | |
2809 gccjit::function gf = fn.gccjit_function; | |
2810 gccjit::block b = gf.new_block (); | |
2811 b.end_with_return (gf.get_param (0)); | |
2812 #endif | |
2813 | |
15016 | 2814 return identities[id] = fn; |
2815 } | |
2816 | |
2817 return identities[id]; | |
2818 } | |
2819 | |
20654 | 2820 #ifdef HAVE_LLVM |
15016 | 2821 llvm::Value * |
15019
ae3670d4df29
Update the execution engine's global mapping for external functions
Max Brister <max@2bass.com>
parents:
15016
diff
changeset
|
2822 jit_typeinfo::do_insert_error_check (llvm::IRBuilderD& abuilder) |
15016 | 2823 { |
15019
ae3670d4df29
Update the execution engine's global mapping for external functions
Max Brister <max@2bass.com>
parents:
15016
diff
changeset
|
2824 return abuilder.CreateLoad (lerror_state); |
15016 | 2825 } |
2826 | |
15603 | 2827 llvm::Value * |
2828 jit_typeinfo::do_insert_interrupt_check (llvm::IRBuilderD& abuilder) | |
2829 { | |
2830 llvm::LoadInst *val = abuilder.CreateLoad (loctave_interrupt_state); | |
2831 val->setVolatile (true); | |
2832 return abuilder.CreateICmpSGT (val, abuilder.getInt32 (0)); | |
2833 } | |
20654 | 2834 #endif /* #ifdef HAVE_LLVM */ |
2835 | |
2836 #ifdef HAVE_GCCJIT | |
2837 gccjit::rvalue | |
2838 jit_typeinfo::do_insert_error_check (gccjit::function func) | |
2839 { | |
2840 return error_state_gccjit.cast_to (gccjit_ctxt.get_type (GCC_JIT_TYPE_BOOL)); | |
2841 } | |
2842 | |
2843 gccjit::rvalue | |
2844 jit_typeinfo::do_insert_interrupt_check (gccjit::function func) | |
2845 { | |
2846 return octave_interrupt_state_gccjit > sig_atomic_type_gccjit.zero (); | |
2847 } | |
2848 #endif /* #ifdef HAVE_GCCJIT */ | |
2849 | |
15603 | 2850 |
15016 | 2851 void |
2852 jit_typeinfo::add_builtin (const std::string& name) | |
2853 { | |
20654 | 2854 jit_type *btype = new_type (name, any, any->to_llvm (), |
2855 #ifdef HAVE_GCCJIT | |
2856 any->to_gccjit (), | |
2857 #endif | |
2858 true); | |
15016 | 2859 builtins[name] = btype; |
2860 | |
2861 octave_builtin *ov_builtin = find_builtin (name); | |
2862 if (ov_builtin) | |
2863 ov_builtin->stash_jit (*btype); | |
2864 } | |
2865 | |
2866 void | |
2867 jit_typeinfo::register_intrinsic (const std::string& name, size_t iid, | |
2868 jit_type *result, | |
2869 const std::vector<jit_type *>& args) | |
2870 { | |
2871 jit_type *builtin_type = builtins[name]; | |
2872 size_t nargs = args.size (); | |
2873 llvm::SmallVector<llvm::Type *, 5> llvm_args (nargs); | |
2874 for (size_t i = 0; i < nargs; ++i) | |
2875 llvm_args[i] = args[i]->to_llvm (); | |
2876 | |
2877 llvm::Intrinsic::ID id = static_cast<llvm::Intrinsic::ID> (iid); | |
2878 llvm::Function *ifun = llvm::Intrinsic::getDeclaration (module, id, | |
2879 llvm_args); | |
2880 std::stringstream fn_name; | |
2881 fn_name << "octave_jit_" << name; | |
2882 | |
2883 std::vector<jit_type *> args1 (nargs + 1); | |
2884 args1[0] = builtin_type; | |
2885 std::copy (args.begin (), args.end (), args1.begin () + 1); | |
2886 | |
2887 // The first argument will be the Octave function, but we already know that | |
2888 // the function call is the equivalent of the intrinsic, so we ignore it and | |
2889 // call the intrinsic with the remaining arguments. | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2890 jit_function fn = create_internal (fn_name.str (), result, args1); |
15016 | 2891 llvm::BasicBlock *body = fn.new_block (); |
2892 builder.SetInsertPoint (body); | |
2893 | |
2894 llvm::SmallVector<llvm::Value *, 5> fargs (nargs); | |
2895 for (size_t i = 0; i < nargs; ++i) | |
2896 fargs[i] = fn.argument (builder, i + 1); | |
2897 | |
2898 llvm::Value *ret = builder.CreateCall (ifun, fargs); | |
2899 fn.do_return (builder, ret); | |
20654 | 2900 |
2901 // gcc implementation | |
2902 #ifdef HAVE_GCCJIT | |
2903 { | |
2904 gccjit::function gf = fn.gccjit_function; | |
2905 gccjit::function builtin = gccjit_ctxt.get_builtin_function (name); | |
2906 std::vector<gccjit::rvalue> gccjit_args (nargs); | |
2907 for (size_t i = 0; i < nargs; ++i) | |
2908 gccjit_args[i] = gf.get_param (i + 1); | |
2909 gccjit::rvalue ret = gccjit_ctxt.new_call (builtin, gccjit_args); | |
2910 gccjit::block b = gf.new_block (); | |
2911 b.end_with_return (ret); | |
2912 } | |
2913 #endif | |
2914 | |
15016 | 2915 paren_subsref_fn.add_overload (fn); |
2916 } | |
2917 | |
2918 octave_builtin * | |
2919 jit_typeinfo::find_builtin (const std::string& name) | |
2920 { | |
2921 // FIXME: Finalize what we want to store in octave_builtin, then add functions | |
2922 // to access these values in octave_value | |
2923 octave_value ov_builtin = symbol_table::find (name); | |
2924 return dynamic_cast<octave_builtin *> (ov_builtin.internal_rep ()); | |
2925 } | |
2926 | |
2927 void | |
15135
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2928 jit_typeinfo::register_generic (const std::string& name, jit_type *result, |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2929 const std::vector<jit_type *>& args) |
15016 | 2930 { |
15135
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2931 octave_builtin *builtin = find_builtin (name); |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2932 if (! builtin) |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2933 return; |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2934 |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2935 std::vector<jit_type *> fn_args (args.size () + 1); |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2936 fn_args[0] = builtins[name]; |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2937 std::copy (args.begin (), args.end (), fn_args.begin () + 1); |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
2938 jit_function fn = create_internal (name, result, fn_args); |
15136
eeaaac7c86b6
jit-typeinfo.cc (jit_typeinfo::register_generic): Mark can error
Max Brister <max@2bass.com>
parents:
15135
diff
changeset
|
2939 fn.mark_can_error (); |
20654 | 2940 |
2941 // LLVM implementation: | |
15135
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2942 llvm::BasicBlock *block = fn.new_block (); |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2943 builder.SetInsertPoint (block); |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2944 llvm::Type *any_t = any->to_llvm (); |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2945 llvm::ArrayType *array_t = llvm::ArrayType::get (any_t, args.size ()); |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2946 llvm::Value *array = llvm::UndefValue::get (array_t); |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2947 for (size_t i = 0; i < args.size (); ++i) |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2948 { |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2949 llvm::Value *arg = fn.argument (builder, i + 1); |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2950 jit_function agrab = get_grab (args[i]); |
15169
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2951 if (agrab.valid ()) |
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2952 arg = agrab.call (builder, arg); |
15135
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2953 jit_function acast = cast (any, args[i]); |
15169
6242904370bd
Support balance, cond, det, norm, rand, magic, eye, and mod in JIT
Max Brister <max@2bass.com>
parents:
15148
diff
changeset
|
2954 array = builder.CreateInsertValue (array, acast.call (builder, arg), i); |
15135
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2955 } |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2956 |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2957 llvm::Value *array_mem = builder.CreateAlloca (array_t); |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2958 builder.CreateStore (array, array_mem); |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2959 array = builder.CreateBitCast (array_mem, any_t->getPointerTo ()); |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2960 |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2961 jit_type *jintTy = intN (sizeof (octave_builtin::fcn) * 8); |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2962 llvm::Type *intTy = jintTy->to_llvm (); |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2963 size_t fcn_int = reinterpret_cast<size_t> (builtin->function ()); |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2964 llvm::Value *fcn = llvm::ConstantInt::get (intTy, fcn_int); |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2965 llvm::Value *nargin = llvm::ConstantInt::get (intTy, args.size ()); |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2966 size_t result_int = reinterpret_cast<size_t> (result); |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2967 llvm::Value *res_llvm = llvm::ConstantInt::get (intTy, result_int); |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2968 llvm::Value *ret = any_call.call (builder, fcn, nargin, array, res_llvm); |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2969 |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2970 jit_function cast_result = cast (result, any); |
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
2971 fn.do_return (builder, cast_result.call (builder, ret)); |
20654 | 2972 |
2973 // gccjit implementation: | |
2974 #ifdef HAVE_GCCJIT | |
2975 { | |
2976 gccjit::function gf = fn.gccjit_function; | |
2977 gccjit::block b = gf.new_block ("body of register_generic"); | |
2978 b.add_comment ("TODO: register_generic"); | |
2979 | |
2980 gccjit::type array_t = gccjit_ctxt.new_array_type (any->to_gccjit (), | |
2981 args.size ()); | |
2982 #if 1 | |
2983 gccjit::lvalue array = gf.new_local (array_t, "tmp_array"); | |
2984 for (size_t i = 0; i < args.size (); ++i) | |
2985 { | |
2986 gccjit::lvalue arg = gf.get_param (i + 1); | |
2987 jit_function agrab = get_grab (args[i]); | |
2988 if (agrab.valid ()) | |
2989 { | |
2990 std::vector<gccjit::rvalue> grab_args (1, arg); | |
2991 b.add_assignment (arg, agrab.call (gccjit_ctxt, b, grab_args)); | |
2992 } | |
2993 jit_function acast = cast (any, args[i]); | |
2994 std::vector<gccjit::rvalue> cast_args (1, arg); | |
2995 b.add_assignment (array[i], | |
2996 acast.call (gccjit_ctxt, b, cast_args)); | |
2997 } | |
2998 #endif | |
2999 | |
3000 gccjit::type int_t = intN (sizeof (octave_builtin::fcn) * 8)->to_gccjit (); | |
3001 size_t fcn_int = reinterpret_cast<size_t> (builtin->function ()); | |
3002 gccjit::rvalue fcn = gccjit_ctxt.new_rvalue (int_t, (int)fcn_int); | |
3003 gccjit::rvalue nargin = gccjit_ctxt.new_rvalue (int_t, (int)args.size ()); | |
3004 size_t result_int = reinterpret_cast<size_t> (result); | |
3005 gccjit::rvalue res_gcc = gccjit_ctxt.new_rvalue (int_t, (int)result_int); | |
3006 std::vector<gccjit::rvalue> call_args (4); | |
3007 call_args[0] = fcn; | |
3008 call_args[1] = nargin; | |
3009 call_args[2] = array; | |
3010 call_args[3] = res_gcc; | |
3011 gccjit::rvalue ret = any_call.call (gccjit_ctxt, b, call_args); | |
3012 | |
3013 jit_function cast_result = cast (result, any); | |
3014 std::vector<gccjit::rvalue> final_cast_args (1); | |
3015 final_cast_args[0] = ret; | |
3016 gccjit::rvalue final_result = cast_result.call (gccjit_ctxt, b, final_cast_args); | |
3017 b.end_with_return (final_result); | |
3018 } | |
3019 #endif | |
3020 | |
15135
bd6bb87e2bea
Support sin, cos, and exp with matrix arguments in JIT
Max Brister <max@2bass.com>
parents:
15124
diff
changeset
|
3021 paren_subsref_fn.add_overload (fn); |
15016 | 3022 } |
3023 | |
3024 jit_function | |
3025 jit_typeinfo::mirror_binary (const jit_function& fn) | |
3026 { | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
3027 jit_function ret = create_internal (fn.name () + "_reverse", |
15016 | 3028 fn.result (), fn.argument_type (1), |
3029 fn.argument_type (0)); | |
3030 if (fn.can_error ()) | |
3031 ret.mark_can_error (); | |
3032 | |
20654 | 3033 // LLVM implementation: |
15016 | 3034 llvm::BasicBlock *body = ret.new_block (); |
3035 builder.SetInsertPoint (body); | |
3036 llvm::Value *result = fn.call (builder, ret.argument (builder, 1), | |
3037 ret.argument (builder, 0)); | |
3038 if (ret.result ()) | |
3039 ret.do_return (builder, result); | |
3040 else | |
3041 ret.do_return (builder); | |
3042 | |
20654 | 3043 // gccjit implementation: |
3044 #ifdef HAVE_GCCJIT | |
3045 gccjit::function gf = ret.gccjit_function; | |
3046 gccjit::block b = gf.new_block (); | |
3047 b.add_comment ("built by mirror_binary"); | |
3048 //std::vector<gccjit::rvalue> gccjit_args (2); | |
3049 //gccjit_args[0] = gf.get_param (1); | |
3050 //gccjit_args[1] = gf.get_param (0); | |
3051 if (ret.result ()) | |
3052 b.end_with_return ( | |
3053 gccjit_ctxt.new_call (fn.gccjit_function, | |
3054 gf.get_param (1), | |
3055 gf.get_param (0))); | |
3056 else | |
3057 b.end_with_return (); | |
3058 #endif | |
3059 | |
15016 | 3060 return ret; |
3061 } | |
3062 | |
20654 | 3063 #ifdef HAVE_LLVM |
15016 | 3064 llvm::Value * |
3065 jit_typeinfo::pack_complex (llvm::IRBuilderD& bld, llvm::Value *cplx) | |
3066 { | |
3067 llvm::Type *complex_ret = instance->complex_ret; | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
3068 llvm::Value *real = bld.CreateExtractValue (cplx, 0); |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
3069 llvm::Value *imag = bld.CreateExtractValue (cplx, 1); |
15016 | 3070 llvm::Value *ret = llvm::UndefValue::get (complex_ret); |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
3071 |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
3072 unsigned int re_idx[] = {0, 0}; |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
3073 unsigned int im_idx[] = {0, 1}; |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
3074 ret = bld.CreateInsertValue (ret, real, re_idx); |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
3075 return bld.CreateInsertValue (ret, imag, im_idx); |
15016 | 3076 } |
3077 | |
3078 llvm::Value * | |
3079 jit_typeinfo::unpack_complex (llvm::IRBuilderD& bld, llvm::Value *result) | |
3080 { | |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
3081 unsigned int re_idx[] = {0, 0}; |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
3082 unsigned int im_idx[] = {0, 1}; |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
3083 |
15016 | 3084 llvm::Type *complex_t = get_complex ()->to_llvm (); |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
3085 llvm::Value *real = bld.CreateExtractValue (result, re_idx); |
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
3086 llvm::Value *imag = bld.CreateExtractValue (result, im_idx); |
15016 | 3087 llvm::Value *ret = llvm::UndefValue::get (complex_t); |
15370
8355fddce815
Use sret and do not use save/restore stack (bug #37308)
Max Brister <max@2bass.com>
parents:
15337
diff
changeset
|
3088 |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
3089 ret = bld.CreateInsertValue (ret, real, 0); |
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
3090 return bld.CreateInsertValue (ret, imag, 1); |
15016 | 3091 } |
3092 | |
3093 llvm::Value * | |
3094 jit_typeinfo::complex_real (llvm::Value *cx) | |
3095 { | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
3096 return builder.CreateExtractValue (cx, 0); |
15016 | 3097 } |
3098 | |
3099 llvm::Value * | |
3100 jit_typeinfo::complex_real (llvm::Value *cx, llvm::Value *real) | |
3101 { | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
3102 return builder.CreateInsertValue (cx, real, 0); |
15016 | 3103 } |
3104 | |
3105 llvm::Value * | |
3106 jit_typeinfo::complex_imag (llvm::Value *cx) | |
3107 { | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
3108 return builder.CreateExtractValue (cx, 1); |
15016 | 3109 } |
3110 | |
3111 llvm::Value * | |
3112 jit_typeinfo::complex_imag (llvm::Value *cx, llvm::Value *imag) | |
3113 { | |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
3114 return builder.CreateInsertValue (cx, imag, 1); |
15016 | 3115 } |
3116 | |
3117 llvm::Value * | |
3118 jit_typeinfo::complex_new (llvm::Value *real, llvm::Value *imag) | |
3119 { | |
3120 llvm::Value *ret = llvm::UndefValue::get (complex->to_llvm ()); | |
3121 ret = complex_real (ret, real); | |
3122 return complex_imag (ret, imag); | |
3123 } | |
20654 | 3124 #endif // #ifdef HAVE_LLVM |
3125 | |
3126 #ifdef HAVE_GCCJIT | |
3127 gccjit::rvalue | |
3128 jit_typeinfo::complex_real (gccjit::rvalue cx) | |
3129 { | |
3130 return cx[0]; | |
3131 } | |
3132 | |
3133 gccjit::rvalue | |
3134 jit_typeinfo::complex_real (gccjit::block block, | |
3135 gccjit::lvalue cx, | |
3136 gccjit::rvalue real) | |
3137 { | |
3138 block.add_assignment (cx[0], real); | |
3139 return cx; | |
3140 } | |
3141 | |
3142 gccjit::rvalue | |
3143 jit_typeinfo::complex_imag (gccjit::rvalue cx) | |
3144 { | |
3145 return cx[1]; | |
3146 } | |
3147 | |
3148 gccjit::rvalue | |
3149 jit_typeinfo::complex_imag (gccjit::block block, | |
3150 gccjit::lvalue cx, | |
3151 gccjit::rvalue imag) | |
3152 { | |
3153 block.add_assignment (cx[1], imag); | |
3154 return cx; | |
3155 } | |
3156 | |
3157 gccjit::rvalue | |
3158 jit_typeinfo::complex_new (gccjit::block block, | |
3159 gccjit::rvalue real, | |
3160 gccjit::rvalue imag) | |
3161 { | |
3162 gccjit::rvalue tmp = | |
3163 block.get_function ().new_local (complex->to_gccjit (), | |
3164 "complex_new"); | |
3165 block.add_assignment (tmp[0], real); | |
3166 block.add_assignment (tmp[1], imag); | |
3167 return tmp; | |
3168 } | |
3169 #endif // #ifdef HAVE_GCCJIT | |
15016 | 3170 |
3171 void | |
3172 jit_typeinfo::create_int (size_t nbits) | |
3173 { | |
3174 std::stringstream tname; | |
3175 tname << "int" << nbits; | |
20654 | 3176 ints[nbits] = new_type (tname.str (), any |
3177 , llvm::Type::getIntNTy (context, | |
3178 nbits) | |
3179 #ifdef HAVE_GCCJIT | |
3180 , gccjit_ctxt.get_int_type (nbits / 8, 1) | |
3181 #endif | |
3182 ); | |
15016 | 3183 } |
3184 | |
3185 jit_type * | |
3186 jit_typeinfo::intN (size_t nbits) const | |
3187 { | |
3188 std::map<size_t, jit_type *>::const_iterator iter = ints.find (nbits); | |
3189 if (iter != ints.end ()) | |
3190 return iter->second; | |
3191 | |
3192 throw jit_fail_exception ("No such integer type"); | |
3193 } | |
3194 | |
3195 jit_type * | |
3196 jit_typeinfo::do_type_of (const octave_value &ov) const | |
3197 { | |
3198 if (ov.is_function ()) | |
3199 { | |
3200 // FIXME: This is ugly, we need to finalize how we want to to this, then | |
3201 // have octave_value fully support the needed functionality | |
3202 octave_builtin *builtin | |
3203 = dynamic_cast<octave_builtin *> (ov.internal_rep ()); | |
3204 return builtin && builtin->to_jit () ? builtin->to_jit () | |
17787
175b392e91fe
Use GNU style coding conventions for code in libinterp/
Rik <rik@octave.org>
parents:
17744
diff
changeset
|
3205 : unknown_function; |
15016 | 3206 } |
3207 | |
3208 if (ov.is_range ()) | |
3209 return get_range (); | |
3210 | |
15311
de9bfcf637df
Fix error when compiling with complex matrix (bug #37247)
Max Brister <max@2bass.com>
parents:
15219
diff
changeset
|
3211 if (ov.is_double_type () && ! ov.is_complex_type ()) |
15016 | 3212 { |
3213 if (ov.is_real_scalar ()) | |
3214 return get_scalar (); | |
3215 | |
3216 if (ov.is_matrix_type ()) | |
3217 return get_matrix (); | |
3218 } | |
3219 | |
3220 if (ov.is_complex_scalar ()) | |
15583
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
3221 { |
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
3222 Complex cv = ov.complex_value (); |
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
3223 |
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
3224 // We don't really represent complex values, instead we represent |
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
3225 // complex_or_scalar. If the imag value is zero, we assume a scalar. |
15893
1f076c40c133
Do not use vectorized llvm commands for complex numbers
Max Brister <max@2bass.com>
parents:
15603
diff
changeset
|
3226 if (cv.imag () != 0) |
15583
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
3227 return get_complex (); |
0754bdfbc8fe
Correct multiplication complex multiplication with NaN in JIT
Max Brister <max@2bass.com>
parents:
15385
diff
changeset
|
3228 } |
15016 | 3229 |
3230 return get_any (); | |
3231 } | |
3232 | |
3233 #endif |