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