• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (C) 2014-2017 Intel Corporation.   All Rights Reserved.
2#
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:
9#
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
12# Software.
13#
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
20# IN THE SOFTWARE.
21
22from __future__ import print_function
23import os, sys, re
24from gen_common import MakoTemplateWriter, ArgumentParser
25from argparse import FileType
26
27inst_aliases = {
28    'SHUFFLE_VECTOR': 'VSHUFFLE',
29    'INSERT_ELEMENT': 'VINSERT',
30    'EXTRACT_ELEMENT': 'VEXTRACT',
31    'MEM_SET': 'MEMSET',
32    'MEM_CPY': 'MEMCOPY',
33    'MEM_MOVE': 'MEMMOVE',
34    'L_SHR': 'LSHR',
35    'A_SHR': 'ASHR',
36    'BIT_CAST': 'BITCAST',
37    'U_DIV': 'UDIV',
38    'S_DIV': 'SDIV',
39    'U_REM': 'UREM',
40    'S_REM': 'SREM',
41    'BIN_OP': 'BINOP',
42}
43
44intrinsics = [
45        ['VGATHERPD', 'x86_avx2_gather_d_pd_256', ['src', 'pBase', 'indices', 'mask', 'scale']],
46        ['VGATHERPS', 'x86_avx2_gather_d_ps_256', ['src', 'pBase', 'indices', 'mask', 'scale']],
47        ['VGATHERPS_16', 'x86_avx512_gather_dps_512', ['src', 'pBase', 'indices', 'mask', 'scale']],
48        ['VGATHERDD', 'x86_avx2_gather_d_d_256', ['src', 'pBase', 'indices', 'mask', 'scale']],
49        ['VGATHERDD_16', 'x86_avx512_gather_dpi_512', ['src', 'pBase', 'indices', 'mask', 'scale']],
50        ['VSQRTPS', 'x86_avx_sqrt_ps_256', ['a']],
51        ['VRSQRTPS', 'x86_avx_rsqrt_ps_256', ['a']],
52        ['VRCPPS', 'x86_avx_rcp_ps_256', ['a']],
53        ['VMINPS', 'x86_avx_min_ps_256', ['a', 'b']],
54        ['VMAXPS', 'x86_avx_max_ps_256', ['a', 'b']],
55        ['VROUND', 'x86_avx_round_ps_256', ['a', 'rounding']],
56        ['VCMPPS', 'x86_avx_cmp_ps_256', ['a', 'b', 'cmpop']],
57        ['VBLENDVPS', 'x86_avx_blendv_ps_256', ['a', 'b', 'mask']],
58        ['BEXTR_32', 'x86_bmi_bextr_32', ['src', 'control']],
59        ['VMASKLOADD', 'x86_avx2_maskload_d_256', ['src', 'mask']],
60        ['VMASKMOVPS', 'x86_avx_maskload_ps_256', ['src', 'mask']],
61        ['VMASKSTOREPS', 'x86_avx_maskstore_ps_256', ['src', 'mask', 'val']],
62        ['VPSHUFB', 'x86_avx2_pshuf_b', ['a', 'b']],
63        ['VPERMD', 'x86_avx2_permd', ['a', 'idx']],
64        ['VPERMPS', 'x86_avx2_permps', ['idx', 'a']],
65        ['VCVTPD2PS', 'x86_avx_cvt_pd2_ps_256', ['a']],
66        ['VCVTPH2PS', 'x86_vcvtph2ps_256', ['a']],
67        ['VCVTPS2PH', 'x86_vcvtps2ph_256', ['a', 'round']],
68        ['VHSUBPS', 'x86_avx_hsub_ps_256', ['a', 'b']],
69        ['VPTESTC', 'x86_avx_ptestc_256', ['a', 'b']],
70        ['VPTESTZ', 'x86_avx_ptestz_256', ['a', 'b']],
71        ['VFMADDPS', 'x86_fma_vfmadd_ps_256', ['a', 'b', 'c']],
72        ['VMOVMSKPS', 'x86_avx_movmsk_ps_256', ['a']],
73        ['INTERRUPT', 'x86_int', ['a']],
74    ]
75
76this_dir = os.path.dirname(os.path.abspath(__file__))
77template = os.path.join(this_dir, 'templates', 'gen_builder.hpp')
78
79def convert_uppercamel(name):
80    s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
81    return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).upper()
82
83'''
84    Given an input file (e.g. IRBuilder.h) generates function dictionary.
85'''
86def parse_ir_builder(input_file):
87
88    functions = []
89
90    lines = input_file.readlines()
91
92    idx = 0
93    while idx < len(lines) - 1:
94        line = lines[idx].rstrip()
95        idx += 1
96
97        #match = re.search(r'\*Create', line)
98        match = re.search(r'[\*\s]Create(\w*)\(', line)
99        if match is not None:
100            #print('Line: %s' % match.group(1))
101
102            if re.search(r'^\s*Create', line) is not None:
103                func_sig = lines[idx-2].rstrip() + line
104            else:
105                func_sig = line
106
107            end_of_args = False
108            while not end_of_args:
109                end_paren = re.search(r'\)', line)
110                if end_paren is not None:
111                    end_of_args = True
112                else:
113                    line = lines[idx].rstrip()
114                    func_sig += line
115                    idx += 1
116
117            delfunc = re.search(r'LLVM_DELETED_FUNCTION|= delete;', func_sig)
118
119            if not delfunc:
120                func = re.search(r'(.*?)\*[\n\s]*(Create\w*)\((.*?)\)', func_sig)
121                if func is not None:
122
123                    return_type = func.group(1).strip() + '*'
124                    func_name = func.group(2)
125                    arguments = func.group(3)
126
127                    func_args = []
128                    arg_names = []
129                    args = arguments.split(',')
130                    for arg in args:
131                        arg = arg.strip()
132                        if arg:
133                            func_args.append(arg)
134
135                            split_args = arg.split('=')
136                            arg_name = split_args[0].rsplit(None, 1)[-1]
137
138                            reg_arg = re.search(r'[\&\*]*(\w*)', arg_name)
139                            if reg_arg:
140                                arg_names += [reg_arg.group(1)]
141
142                    ignore = False
143
144                    # The following functions need to be ignored in openswr.
145                    # API change in llvm-5.0 breaks baked autogen files
146                    if (
147                        (func_name == 'CreateFence' or
148                         func_name == 'CreateAtomicCmpXchg' or
149                         func_name == 'CreateAtomicRMW')):
150                        ignore = True
151
152                    # The following functions need to be ignored.
153                    if (func_name == 'CreateInsertNUWNSWBinOp' or
154                        func_name == 'CreateMaskedIntrinsic' or
155                        func_name == 'CreateAlignmentAssumptionHelper'):
156                        ignore = True
157
158                    # Convert CamelCase to CAMEL_CASE
159                    func_mod = re.search(r'Create(\w*)', func_name)
160                    if func_mod:
161                        func_mod = func_mod.group(1)
162                        func_mod = convert_uppercamel(func_mod)
163                        if func_mod[0:2] == 'F_' or func_mod[0:2] == 'I_':
164                            func_mod = func_mod[0] + func_mod[2:]
165
166                    # Substitute alias based on CAMEL_CASE name.
167                    func_alias = inst_aliases.get(func_mod)
168                    if not func_alias:
169                        func_alias = func_mod
170
171                        if func_name == 'CreateCall' or func_name == 'CreateGEP':
172                            arglist = re.search(r'ArrayRef', ', '.join(func_args))
173                            if arglist:
174                                func_alias = func_alias + 'A'
175
176                    if not ignore:
177                        functions.append({
178                                'name'      : func_name,
179                                'alias'     : func_alias,
180                                'return'    : return_type,
181                                'args'      : ', '.join(func_args),
182                                'arg_names' : arg_names,
183                            })
184
185    return functions
186
187'''
188    Auto-generates macros for LLVM IR
189'''
190def generate_gen_h(functions, output_dir):
191    filename = 'gen_builder.hpp'
192    output_filename = os.path.join(output_dir, filename)
193
194    templfuncs = []
195    for func in functions:
196        decl = '%s %s(%s)' % (func['return'], func['alias'], func['args'])
197
198        templfuncs.append({
199            'decl'      : decl,
200            'intrin'    : func['name'],
201            'args'      : ', '.join(func['arg_names']),
202        })
203
204    MakoTemplateWriter.to_file(
205        template,
206        output_filename,
207        cmdline=sys.argv,
208        comment='Builder IR Wrappers',
209        filename=filename,
210        functions=templfuncs,
211        isX86=False)
212
213'''
214    Auto-generates macros for LLVM IR
215'''
216def generate_x86_h(output_dir):
217    filename = 'gen_builder_x86.hpp'
218    output_filename = os.path.join(output_dir, filename)
219
220    functions = []
221    for inst in intrinsics:
222        #print('Inst: %s, x86: %s numArgs: %d' % (inst[0], inst[1], len(inst[2])))
223        declargs = 'Value* ' + ', Value* '.join(inst[2])
224
225        functions.append({
226            'decl'      : 'Value* %s(%s, const llvm::Twine& name = "")' % (inst[0], declargs),
227            'args'      : ', '.join(inst[2]),
228            'intrin'    : inst[1],
229        })
230
231    MakoTemplateWriter.to_file(
232        template,
233        output_filename,
234        cmdline=sys.argv,
235        comment='x86 intrinsics',
236        filename=filename,
237        functions=functions,
238        isX86=True)
239
240'''
241    Function which is invoked when this script is started from a command line.
242    Will present and consume a set of arguments which will tell this script how
243    to behave
244'''
245def main():
246
247    # Parse args...
248    parser = ArgumentParser()
249    parser.add_argument('--input', '-i', type=FileType('r'), help='Path to IRBuilder.h', required=False)
250    parser.add_argument('--output-dir', '-o', action='store', dest='output', help='Path to output directory', required=True)
251    parser.add_argument('--gen_h', help='Generate builder_gen.h', action='store_true', default=False)
252    parser.add_argument('--gen_x86_h', help='Generate x86 intrinsics. No input is needed.', action='store_true', default=False)
253    args = parser.parse_args()
254
255    if not os.path.exists(args.output):
256        os.makedirs(args.output)
257
258    if args.input:
259        functions = parse_ir_builder(args.input)
260
261        if args.gen_h:
262            generate_gen_h(functions, args.output)
263
264    elif args.gen_h:
265        print('Need to specify --input for --gen_h!')
266
267    if args.gen_x86_h:
268        generate_x86_h(args.output)
269
270if __name__ == '__main__':
271    main()
272# END OF FILE
273