Mercurial > hg > CbC > CbC_llvm
diff clang/utils/convert_arm_neon.py @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children | c4bab56944e8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/clang/utils/convert_arm_neon.py Thu Feb 13 15:10:13 2020 +0900 @@ -0,0 +1,172 @@ +#!/usr/bin/env python3 + +# This script was committed on 20/11/2019 and it would probably make sense to remove +# it after the next release branches. + +# This script is pipe based and converts an arm_neon.td (or arm_fp16.td) file +# using the old single-char type modifiers to an equivalent new-style form where +# each modifier is orthogonal and they can be composed. +# +# It was used to directly generate the .td files on master, so if you have any +# local additions I would suggest implementing any modifiers here, and running +# it over your entire pre-merge .td files rather than trying to resolve any +# conflicts manually. + +import re, sys +MOD_MAP = { + 'v': 'v', + 'x': 'S', + 'u': 'U', + 'd': '.', + 'g': 'q', + 'j': 'Q', + 'w': '>Q', + 'n': '>', + 'h': '<', + 'q': '<Q', + 'e': '<U', + 'm': '<q', + 'i': 'I', + 'l': 'IU>', + 's': '1', + 'z': '1<', + 'r': '1>', + 'b': '1U', + '$': '1S', + 'k': 'Q', + '2': '2', + '3': '3', + '4': '4', + 'B': '2Q', + 'C': '3Q', + 'D': '4Q', + 'p': '*', + 'c': 'c*', + '7': '<<q', + '8': '<<', + '9': '<<Q', + 't': 'p' + } + + +def typespec_elt_size(typespec): + if 'c' in typespec: + return 8 + elif 's' in typespec or 'h' in typespec: + return 16 + elif 'i' in typespec or 'f' in typespec: + return 32 + elif 'l' in typespec or 'd' in typespec: + return 64 + elif 'k' in typespec: + return 128 + +def get_resize(cur, desired): + res = '' + while cur < desired: + res += '>' + cur *= 2 + while cur > desired: + res += '<' + cur /= 2 + return res + + +def remap_protocol(proto, typespec, name): + key_type = 0 + + # Conversions like to see the integer type so they know signedness. + if 'vcvt' in name and '_f' in name and name != 'vcvt_f32_f64' and name != 'vcvt_f64_f32': + key_type = 1 + default_width = typespec_elt_size(typespec) + inconsistent_width = False + for elt in typespec: + new_width = typespec_elt_size(elt) + if new_width and new_width != default_width: + inconsistent_width = True + + res = '' + for i, c in enumerate(proto): + # void and pointers make for bad discriminators in CGBuiltin.cpp. + if c in 'vcp': + key_type += 1 + + if c in MOD_MAP: + cur_mod = MOD_MAP[c] + elif inconsistent_width: + # Otherwise it's a fixed output width modifier. + sys.stderr.write(f'warning: {name} uses fixed output size but has inconsistent input widths: {proto} {typespec}\n') + + if c == 'Y': + # y: scalar of half float + resize = get_resize(default_width, 16) + cur_mod = f'1F{resize}' + elif c == 'y': + # y: scalar of float + resize = get_resize(default_width, 32) + cur_mod = f'1F{resize}' + elif c == 'o': + # o: scalar of double + resize = get_resize(default_width, 64) + cur_mod = f'1F{resize}' + elif c == 'I': + # I: scalar of 32-bit signed + resize = get_resize(default_width, 32) + cur_mod = f'1S{resize}' + elif c == 'L': + # L: scalar of 64-bit signed + resize = get_resize(default_width, 64) + cur_mod = f'1S{resize}' + elif c == 'U': + # I: scalar of 32-bit unsigned + resize = get_resize(default_width, 32) + cur_mod = f'1U{resize}' + elif c == 'O': + # O: scalar of 64-bit unsigned + resize = get_resize(default_width, 64) + cur_mod = f'1U{resize}' + elif c == 'f': + # f: float (int args) + resize = get_resize(default_width, 32) + cur_mod = f'F{resize}' + elif c == 'F': + # F: double (int args) + resize = get_resize(default_width, 64) + cur_mod = f'F{resize}' + elif c == 'H': + # H: half (int args) + resize = get_resize(default_width, 16) + cur_mod = f'F{resize}' + elif c == '0': + # 0: half (int args), ignore 'Q' size modifier. + resize = get_resize(default_width, 16) + cur_mod = f'Fq{resize}' + elif c == '1': + # 1: half (int args), force 'Q' size modifier. + resize = get_resize(default_width, 16) + cur_mod = f'FQ{resize}' + + if len(cur_mod) == 0: + raise Exception(f'WTF: {c} in {name}') + + if key_type != 0 and key_type == i: + cur_mod += '!' + + if len(cur_mod) == 1: + res += cur_mod + else: + res += '(' + cur_mod + ')' + + return res + +def replace_insts(m): + start, end = m.span('proto') + start -= m.start() + end -= m.start() + new_proto = remap_protocol(m['proto'], m['kinds'], m['name']) + return m.group()[:start] + new_proto + m.group()[end:] + +INST = re.compile(r'Inst<"(?P<name>.*?)",\s*"(?P<proto>.*?)",\s*"(?P<kinds>.*?)"') + +new_td = INST.sub(replace_insts, sys.stdin.read()) +sys.stdout.write(new_td)