1 # Copyright (C) 2014-2018 Intel Corporation. All Rights Reserved.
3 # Permission is hereby granted, free of charge, to any person obtaining a
4 # copy of this software and associated documentation files (the "Software"),
5 # to deal in the Software without restriction, including without limitation
6 # the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 # and/or sell copies of the Software, and to permit persons to whom the
8 # Software is furnished to do so, subject to the following conditions:
10 # The above copyright notice and this permission notice (including the next
11 # paragraph) shall be included in all copies or substantial portions of the
14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 from __future__
import print_function
24 from gen_common
import *
25 from argparse
import FileType
28 'SHUFFLE_VECTOR': 'VSHUFFLE',
29 'INSERT_ELEMENT': 'VINSERT',
30 'EXTRACT_ELEMENT': 'VEXTRACT',
33 'MEM_MOVE': 'MEMMOVE',
36 'BIT_CAST': 'BITCAST',
45 ['VGATHERPD', ['src', 'pBase', 'indices', 'mask', 'scale'], 'src'],
46 ['VGATHERPS', ['src', 'pBase', 'indices', 'mask', 'scale'], 'src'],
47 ['VGATHERDD', ['src', 'pBase', 'indices', 'mask', 'scale'], 'src'],
48 ['VRCPPS', ['a'], 'a'],
49 ['VROUND', ['a', 'rounding'], 'a'],
50 ['BEXTR_32', ['src', 'control'], 'src'],
51 ['VPSHUFB', ['a', 'b'], 'a'],
52 ['VPERMD', ['a', 'idx'], 'a'],
53 ['VPERMPS', ['idx', 'a'], 'a'],
54 ['VCVTPD2PS', ['a'], 'VectorType::get(mFP32Ty, a->getType()->getVectorNumElements())'],
55 ['VCVTPH2PS', ['a'], 'VectorType::get(mFP32Ty, a->getType()->getVectorNumElements())'],
56 ['VCVTPS2PH', ['a', 'round'], 'mSimdInt16Ty'],
57 ['VHSUBPS', ['a', 'b'], 'a'],
58 ['VPTESTC', ['a', 'b'], 'mInt32Ty'],
59 ['VPTESTZ', ['a', 'b'], 'mInt32Ty'],
60 ['VPHADDD', ['a', 'b'], 'a'],
61 ['PDEP32', ['a', 'b'], 'a'],
62 ['RDTSC', [], 'mInt64Ty'],
66 ['CTTZ', 'cttz', ['a', 'flag'], ['a']],
67 ['CTLZ', 'ctlz', ['a', 'flag'], ['a']],
68 ['VSQRTPS', 'sqrt', ['a'], ['a']],
69 ['STACKSAVE', 'stacksave', [], []],
70 ['STACKRESTORE', 'stackrestore', ['a'], []],
71 ['VMINPS', 'minnum', ['a', 'b'], ['a']],
72 ['VMAXPS', 'maxnum', ['a', 'b'], ['a']],
73 ['VFMADDPS', 'fmuladd', ['a', 'b', 'c'], ['a']],
74 ['DEBUGTRAP', 'debugtrap', [], []],
75 ['POPCNT', 'ctpop', ['a'], ['a']],
76 ['LOG2', 'log2', ['a'], ['a']],
77 ['FABS', 'fabs', ['a'], ['a']],
78 ['EXP2', 'exp2', ['a'], ['a']],
79 ['POW', 'pow', ['a', 'b'], ['a']]
82 this_dir
= os
.path
.dirname(os
.path
.abspath(__file__
))
83 template
= os
.path
.join(this_dir
, 'templates', 'gen_builder.hpp')
85 def convert_uppercamel(name
):
86 s1
= re
.sub('(.)([A-Z][a-z]+)', r
'\1_\2', name
)
87 return re
.sub('([a-z0-9])([A-Z])', r
'\1_\2', s1
).upper()
90 Given an input file (e.g. IRBuilder.h) generates function dictionary.
92 def parse_ir_builder(input_file
):
96 lines
= input_file
.readlines()
99 while idx
< len(lines
) - 1:
100 line
= lines
[idx
].rstrip()
103 #match = re.search(r'\*Create', line)
104 match
= re
.search(r
'[\*\s]Create(\w*)\(', line
)
105 if match
is not None:
106 #print('Line: %s' % match.group(1))
108 if re
.search(r
'^\s*Create', line
) is not None:
109 func_sig
= lines
[idx
-2].rstrip() + line
114 while not end_of_args
:
115 end_paren
= re
.search(r
'\)', line
)
116 if end_paren
is not None:
119 line
= lines
[idx
].rstrip()
123 delfunc
= re
.search(r
'LLVM_DELETED_FUNCTION|= delete;', func_sig
)
126 func
= re
.search(r
'(.*?)\*[\n\s]*(Create\w*)\((.*?)\)', func_sig
)
129 return_type
= func
.group(1).strip() + '*'
130 func_name
= func
.group(2)
131 arguments
= func
.group(3)
135 args
= arguments
.split(',')
139 func_args
.append(arg
)
141 split_args
= arg
.split('=')
142 arg_name
= split_args
[0].rsplit(None, 1)[-1]
144 reg_arg
= re
.search(r
'[\&\*]*(\w*)', arg_name
)
146 arg_names
+= [reg_arg
.group(1)]
150 # The following functions need to be ignored in openswr.
151 # API change in llvm-5.0 breaks baked autogen files
153 (func_name
== 'CreateFence' or
154 func_name
== 'CreateAtomicCmpXchg' or
155 func_name
== 'CreateAtomicRMW')):
158 # The following functions need to be ignored.
159 if (func_name
== 'CreateInsertNUWNSWBinOp' or
160 func_name
== 'CreateMaskedIntrinsic' or
161 func_name
== 'CreateAlignmentAssumptionHelper' or
162 func_name
== 'CreateGEP' or
163 func_name
== 'CreateLoad' or
164 func_name
== 'CreateMaskedLoad' or
165 func_name
== 'CreateElementUnorderedAtomicMemCpy'):
168 # Convert CamelCase to CAMEL_CASE
169 func_mod
= re
.search(r
'Create(\w*)', func_name
)
171 func_mod
= func_mod
.group(1)
172 func_mod
= convert_uppercamel(func_mod
)
173 if func_mod
[0:2] == 'F_' or func_mod
[0:2] == 'I_':
174 func_mod
= func_mod
[0] + func_mod
[2:]
176 # Substitute alias based on CAMEL_CASE name.
177 func_alias
= inst_aliases
.get(func_mod
)
179 func_alias
= func_mod
181 if func_name
== 'CreateCall' or func_name
== 'CreateGEP':
182 arglist
= re
.search(r
'ArrayRef', ', '.join(func_args
))
184 func_alias
= func_alias
+ 'A'
189 'alias' : func_alias
,
190 'return' : return_type
,
191 'args' : ', '.join(func_args
),
192 'arg_names' : arg_names
,
198 Auto-generates macros for LLVM IR
200 def generate_gen_h(functions
, output_dir
):
201 filename
= 'gen_builder.hpp'
202 output_filename
= os
.path
.join(output_dir
, filename
)
205 for func
in functions
:
206 decl
= '%s %s(%s)' % (func
['return'], func
['alias'], func
['args'])
210 'intrin' : func
['name'],
211 'args' : func
['arg_names'],
214 MakoTemplateWriter
.to_file(
218 comment
='Builder IR Wrappers',
220 functions
=templfuncs
,
221 isX86
=False, isIntrin
=False)
224 Auto-generates macros for LLVM IR
226 def generate_meta_h(output_dir
):
227 filename
= 'gen_builder_meta.hpp'
228 output_filename
= os
.path
.join(output_dir
, filename
)
231 for inst
in intrinsics
:
236 #print('Inst: %s, x86: %s numArgs: %d' % (inst[0], inst[1], len(inst[2])))
238 declargs
= 'Value* ' + ', Value* '.join(args
)
239 decl
= 'Value* %s(%s, const llvm::Twine& name = "")' % (name
, declargs
)
241 decl
= 'Value* %s(const llvm::Twine& name = "")' % (name
)
243 # determine the return type of the intrinsic. It can either be:
244 # - type of one of the input arguments
245 # - snippet of code to set the return type
248 returnTy
= ret
+ '->getType()'
256 'returnType': returnTy
259 MakoTemplateWriter
.to_file(
263 comment
='meta intrinsics',
266 isX86
=True, isIntrin
=False)
268 def generate_intrin_h(output_dir
):
269 filename
= 'gen_builder_intrin.hpp'
270 output_filename
= os
.path
.join(output_dir
, filename
)
273 for inst
in llvm_intrinsics
:
274 #print('Inst: %s, x86: %s numArgs: %d' % (inst[0], inst[1], len(inst[2])))
275 if len(inst
[2]) != 0:
276 declargs
= 'Value* ' + ', Value* '.join(inst
[2])
277 decl
= 'Value* %s(%s, const llvm::Twine& name = "")' % (inst
[0], declargs
)
279 decl
= 'Value* %s(const llvm::Twine& name = "")' % (inst
[0])
288 MakoTemplateWriter
.to_file(
292 comment
='llvm intrinsics',
295 isX86
=False, isIntrin
=True)
297 Function which is invoked when this script is started from a command line.
298 Will present and consume a set of arguments which will tell this script how
304 parser
= ArgumentParser()
305 parser
.add_argument('--input', '-i', type=FileType('r'), help='Path to IRBuilder.h', required
=False)
306 parser
.add_argument('--output-dir', '-o', action
='store', dest
='output', help='Path to output directory', required
=True)
307 parser
.add_argument('--gen_h', help='Generate builder_gen.h', action
='store_true', default
=False)
308 parser
.add_argument('--gen_meta_h', help='Generate meta intrinsics. No input is needed.', action
='store_true', default
=False)
309 parser
.add_argument('--gen_intrin_h', help='Generate llvm intrinsics. No input is needed.', action
='store_true', default
=False)
310 args
= parser
.parse_args()
312 if not os
.path
.exists(args
.output
):
313 os
.makedirs(args
.output
)
315 final_output_dir
= args
.output
316 args
.output
= MakeTmpDir('_codegen')
321 functions
= parse_ir_builder(args
.input)
324 generate_gen_h(functions
, args
.output
)
327 print('Need to specify --input for --gen_h!')
330 generate_meta_h(args
.output
)
332 if args
.gen_intrin_h
:
333 generate_intrin_h(args
.output
)
335 rval
= CopyDirFilesIfDifferent(args
.output
, final_output_dir
)
338 print('ERROR: Could not generate llvm_ir_macros', file=sys
.stderr
)
342 DeleteDirTree(args
.output
)
346 if __name__
== '__main__':