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)