[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / clang / utils / convert_arm_neon.py
blobbb3516b07b577135bf9f467c81176fb5f82b4c1b
1 #!/usr/bin/env python3
3 # This script was committed on 20/11/2019 and it would probably make sense to remove
4 # it after the next release branches.
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.
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.
15 import re, sys
16 MOD_MAP = {
17 'v': 'v',
18 'x': 'S',
19 'u': 'U',
20 'd': '.',
21 'g': 'q',
22 'j': 'Q',
23 'w': '>Q',
24 'n': '>',
25 'h': '<',
26 'q': '<Q',
27 'e': '<U',
28 'm': '<q',
29 'i': 'I',
30 'l': 'IU>',
31 's': '1',
32 'z': '1<',
33 'r': '1>',
34 'b': '1U',
35 '$': '1S',
36 'k': 'Q',
37 '2': '2',
38 '3': '3',
39 '4': '4',
40 'B': '2Q',
41 'C': '3Q',
42 'D': '4Q',
43 'p': '*',
44 'c': 'c*',
45 '7': '<<q',
46 '8': '<<',
47 '9': '<<Q',
48 't': 'p'
52 def typespec_elt_size(typespec):
53 if 'c' in typespec:
54 return 8
55 elif 's' in typespec or 'h' in typespec:
56 return 16
57 elif 'i' in typespec or 'f' in typespec:
58 return 32
59 elif 'l' in typespec or 'd' in typespec:
60 return 64
61 elif 'k' in typespec:
62 return 128
64 def get_resize(cur, desired):
65 res = ''
66 while cur < desired:
67 res += '>'
68 cur *= 2
69 while cur > desired:
70 res += '<'
71 cur /= 2
72 return res
75 def remap_protocol(proto, typespec, name):
76 key_type = 0
78 # Conversions like to see the integer type so they know signedness.
79 if 'vcvt' in name and '_f' in name and name != 'vcvt_f32_f64' and name != 'vcvt_f64_f32':
80 key_type = 1
81 default_width = typespec_elt_size(typespec)
82 inconsistent_width = False
83 for elt in typespec:
84 new_width = typespec_elt_size(elt)
85 if new_width and new_width != default_width:
86 inconsistent_width = True
88 res = ''
89 for i, c in enumerate(proto):
90 # void and pointers make for bad discriminators in CGBuiltin.cpp.
91 if c in 'vcp':
92 key_type += 1
94 if c in MOD_MAP:
95 cur_mod = MOD_MAP[c]
96 elif inconsistent_width:
97 # Otherwise it's a fixed output width modifier.
98 sys.stderr.write(f'warning: {name} uses fixed output size but has inconsistent input widths: {proto} {typespec}\n')
100 if c == 'Y':
101 # y: scalar of half float
102 resize = get_resize(default_width, 16)
103 cur_mod = f'1F{resize}'
104 elif c == 'y':
105 # y: scalar of float
106 resize = get_resize(default_width, 32)
107 cur_mod = f'1F{resize}'
108 elif c == 'o':
109 # o: scalar of double
110 resize = get_resize(default_width, 64)
111 cur_mod = f'1F{resize}'
112 elif c == 'I':
113 # I: scalar of 32-bit signed
114 resize = get_resize(default_width, 32)
115 cur_mod = f'1S{resize}'
116 elif c == 'L':
117 # L: scalar of 64-bit signed
118 resize = get_resize(default_width, 64)
119 cur_mod = f'1S{resize}'
120 elif c == 'U':
121 # I: scalar of 32-bit unsigned
122 resize = get_resize(default_width, 32)
123 cur_mod = f'1U{resize}'
124 elif c == 'O':
125 # O: scalar of 64-bit unsigned
126 resize = get_resize(default_width, 64)
127 cur_mod = f'1U{resize}'
128 elif c == 'f':
129 # f: float (int args)
130 resize = get_resize(default_width, 32)
131 cur_mod = f'F{resize}'
132 elif c == 'F':
133 # F: double (int args)
134 resize = get_resize(default_width, 64)
135 cur_mod = f'F{resize}'
136 elif c == 'H':
137 # H: half (int args)
138 resize = get_resize(default_width, 16)
139 cur_mod = f'F{resize}'
140 elif c == '0':
141 # 0: half (int args), ignore 'Q' size modifier.
142 resize = get_resize(default_width, 16)
143 cur_mod = f'Fq{resize}'
144 elif c == '1':
145 # 1: half (int args), force 'Q' size modifier.
146 resize = get_resize(default_width, 16)
147 cur_mod = f'FQ{resize}'
149 if len(cur_mod) == 0:
150 raise Exception(f'WTF: {c} in {name}')
152 if key_type != 0 and key_type == i:
153 cur_mod += '!'
155 if len(cur_mod) == 1:
156 res += cur_mod
157 else:
158 res += '(' + cur_mod + ')'
160 return res
162 def replace_insts(m):
163 start, end = m.span('proto')
164 start -= m.start()
165 end -= m.start()
166 new_proto = remap_protocol(m['proto'], m['kinds'], m['name'])
167 return m.group()[:start] + new_proto + m.group()[end:]
169 INST = re.compile(r'Inst<"(?P<name>.*?)",\s*"(?P<proto>.*?)",\s*"(?P<kinds>.*?)"')
171 new_td = INST.sub(replace_insts, sys.stdin.read())
172 sys.stdout.write(new_td)