1#!/usr/bin/env python3 2 3# This script was committed on 20/11/2019 and it would probably make sense to remove 4# it after the next release branches. 5 6# This script is pipe based and converts an arm_neon.td (or arm_fp16.td) file 7# using the old single-char type modifiers to an equivalent new-style form where 8# each modifier is orthogonal and they can be composed. 9# 10# It was used to directly generate the .td files on main, so if you have any 11# local additions I would suggest implementing any modifiers here, and running 12# it over your entire pre-merge .td files rather than trying to resolve any 13# conflicts manually. 14 15import re, sys 16 17MOD_MAP = { 18 "v": "v", 19 "x": "S", 20 "u": "U", 21 "d": ".", 22 "g": "q", 23 "j": "Q", 24 "w": ">Q", 25 "n": ">", 26 "h": "<", 27 "q": "<Q", 28 "e": "<U", 29 "m": "<q", 30 "i": "I", 31 "l": "IU>", 32 "s": "1", 33 "z": "1<", 34 "r": "1>", 35 "b": "1U", 36 "$": "1S", 37 "k": "Q", 38 "2": "2", 39 "3": "3", 40 "4": "4", 41 "B": "2Q", 42 "C": "3Q", 43 "D": "4Q", 44 "p": "*", 45 "c": "c*", 46 "7": "<<q", 47 "8": "<<", 48 "9": "<<Q", 49 "t": "p", 50} 51 52 53def typespec_elt_size(typespec): 54 if "c" in typespec: 55 return 8 56 elif "s" in typespec or "h" in typespec: 57 return 16 58 elif "i" in typespec or "f" in typespec: 59 return 32 60 elif "l" in typespec or "d" in typespec: 61 return 64 62 elif "k" in typespec: 63 return 128 64 65 66def get_resize(cur, desired): 67 res = "" 68 while cur < desired: 69 res += ">" 70 cur *= 2 71 while cur > desired: 72 res += "<" 73 cur /= 2 74 return res 75 76 77def remap_protocol(proto, typespec, name): 78 key_type = 0 79 80 # Conversions like to see the integer type so they know signedness. 81 if ( 82 "vcvt" in name 83 and "_f" in name 84 and name != "vcvt_f32_f64" 85 and name != "vcvt_f64_f32" 86 ): 87 key_type = 1 88 default_width = typespec_elt_size(typespec) 89 inconsistent_width = False 90 for elt in typespec: 91 new_width = typespec_elt_size(elt) 92 if new_width and new_width != default_width: 93 inconsistent_width = True 94 95 res = "" 96 for i, c in enumerate(proto): 97 # void and pointers make for bad discriminators in CGBuiltin.cpp. 98 if c in "vcp": 99 key_type += 1 100 101 if c in MOD_MAP: 102 cur_mod = MOD_MAP[c] 103 elif inconsistent_width: 104 # Otherwise it's a fixed output width modifier. 105 sys.stderr.write( 106 f"warning: {name} uses fixed output size but has inconsistent input widths: {proto} {typespec}\n" 107 ) 108 109 if c == "Y": 110 # y: scalar of half float 111 resize = get_resize(default_width, 16) 112 cur_mod = f"1F{resize}" 113 elif c == "y": 114 # y: scalar of float 115 resize = get_resize(default_width, 32) 116 cur_mod = f"1F{resize}" 117 elif c == "o": 118 # o: scalar of double 119 resize = get_resize(default_width, 64) 120 cur_mod = f"1F{resize}" 121 elif c == "I": 122 # I: scalar of 32-bit signed 123 resize = get_resize(default_width, 32) 124 cur_mod = f"1S{resize}" 125 elif c == "L": 126 # L: scalar of 64-bit signed 127 resize = get_resize(default_width, 64) 128 cur_mod = f"1S{resize}" 129 elif c == "U": 130 # I: scalar of 32-bit unsigned 131 resize = get_resize(default_width, 32) 132 cur_mod = f"1U{resize}" 133 elif c == "O": 134 # O: scalar of 64-bit unsigned 135 resize = get_resize(default_width, 64) 136 cur_mod = f"1U{resize}" 137 elif c == "f": 138 # f: float (int args) 139 resize = get_resize(default_width, 32) 140 cur_mod = f"F{resize}" 141 elif c == "F": 142 # F: double (int args) 143 resize = get_resize(default_width, 64) 144 cur_mod = f"F{resize}" 145 elif c == "H": 146 # H: half (int args) 147 resize = get_resize(default_width, 16) 148 cur_mod = f"F{resize}" 149 elif c == "0": 150 # 0: half (int args), ignore 'Q' size modifier. 151 resize = get_resize(default_width, 16) 152 cur_mod = f"Fq{resize}" 153 elif c == "1": 154 # 1: half (int args), force 'Q' size modifier. 155 resize = get_resize(default_width, 16) 156 cur_mod = f"FQ{resize}" 157 158 if len(cur_mod) == 0: 159 raise Exception(f"WTF: {c} in {name}") 160 161 if key_type != 0 and key_type == i: 162 cur_mod += "!" 163 164 if len(cur_mod) == 1: 165 res += cur_mod 166 else: 167 res += "(" + cur_mod + ")" 168 169 return res 170 171 172def replace_insts(m): 173 start, end = m.span("proto") 174 start -= m.start() 175 end -= m.start() 176 new_proto = remap_protocol(m["proto"], m["kinds"], m["name"]) 177 return m.group()[:start] + new_proto + m.group()[end:] 178 179 180INST = re.compile(r'Inst<"(?P<name>.*?)",\s*"(?P<proto>.*?)",\s*"(?P<kinds>.*?)"') 181 182new_td = INST.sub(replace_insts, sys.stdin.read()) 183sys.stdout.write(new_td) 184