llvm-project
183 строки · 5.0 Кб
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):
54if "c" in typespec:
55return 8
56elif "s" in typespec or "h" in typespec:
57return 16
58elif "i" in typespec or "f" in typespec:
59return 32
60elif "l" in typespec or "d" in typespec:
61return 64
62elif "k" in typespec:
63return 128
64
65
66def get_resize(cur, desired):
67res = ""
68while cur < desired:
69res += ">"
70cur *= 2
71while cur > desired:
72res += "<"
73cur /= 2
74return res
75
76
77def remap_protocol(proto, typespec, name):
78key_type = 0
79
80# Conversions like to see the integer type so they know signedness.
81if (
82"vcvt" in name
83and "_f" in name
84and name != "vcvt_f32_f64"
85and name != "vcvt_f64_f32"
86):
87key_type = 1
88default_width = typespec_elt_size(typespec)
89inconsistent_width = False
90for elt in typespec:
91new_width = typespec_elt_size(elt)
92if new_width and new_width != default_width:
93inconsistent_width = True
94
95res = ""
96for i, c in enumerate(proto):
97# void and pointers make for bad discriminators in CGBuiltin.cpp.
98if c in "vcp":
99key_type += 1
100
101if c in MOD_MAP:
102cur_mod = MOD_MAP[c]
103elif inconsistent_width:
104# Otherwise it's a fixed output width modifier.
105sys.stderr.write(
106f"warning: {name} uses fixed output size but has inconsistent input widths: {proto} {typespec}\n"
107)
108
109if c == "Y":
110# y: scalar of half float
111resize = get_resize(default_width, 16)
112cur_mod = f"1F{resize}"
113elif c == "y":
114# y: scalar of float
115resize = get_resize(default_width, 32)
116cur_mod = f"1F{resize}"
117elif c == "o":
118# o: scalar of double
119resize = get_resize(default_width, 64)
120cur_mod = f"1F{resize}"
121elif c == "I":
122# I: scalar of 32-bit signed
123resize = get_resize(default_width, 32)
124cur_mod = f"1S{resize}"
125elif c == "L":
126# L: scalar of 64-bit signed
127resize = get_resize(default_width, 64)
128cur_mod = f"1S{resize}"
129elif c == "U":
130# I: scalar of 32-bit unsigned
131resize = get_resize(default_width, 32)
132cur_mod = f"1U{resize}"
133elif c == "O":
134# O: scalar of 64-bit unsigned
135resize = get_resize(default_width, 64)
136cur_mod = f"1U{resize}"
137elif c == "f":
138# f: float (int args)
139resize = get_resize(default_width, 32)
140cur_mod = f"F{resize}"
141elif c == "F":
142# F: double (int args)
143resize = get_resize(default_width, 64)
144cur_mod = f"F{resize}"
145elif c == "H":
146# H: half (int args)
147resize = get_resize(default_width, 16)
148cur_mod = f"F{resize}"
149elif c == "0":
150# 0: half (int args), ignore 'Q' size modifier.
151resize = get_resize(default_width, 16)
152cur_mod = f"Fq{resize}"
153elif c == "1":
154# 1: half (int args), force 'Q' size modifier.
155resize = get_resize(default_width, 16)
156cur_mod = f"FQ{resize}"
157
158if len(cur_mod) == 0:
159raise Exception(f"WTF: {c} in {name}")
160
161if key_type != 0 and key_type == i:
162cur_mod += "!"
163
164if len(cur_mod) == 1:
165res += cur_mod
166else:
167res += "(" + cur_mod + ")"
168
169return res
170
171
172def replace_insts(m):
173start, end = m.span("proto")
174start -= m.start()
175end -= m.start()
176new_proto = remap_protocol(m["proto"], m["kinds"], m["name"])
177return 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