arm_instruction_sets.py 5.57 KB
Newer Older
Michael Kuron's avatar
Michael Kuron committed
1
def get_argument_string(function_shortcut, first=''):
Markus Holzer's avatar
Markus Holzer committed
2
3
    args = function_shortcut[function_shortcut.index('[') + 1: -1]
    arg_string = "("
Michael Kuron's avatar
Michael Kuron committed
4
5
    if first:
        arg_string += first + ', '
Markus Holzer's avatar
Markus Holzer committed
6
7
8
9
10
11
12
13
14
15
16
17
    for arg in args.split(","):
        arg = arg.strip()
        if not arg:
            continue
        if arg in ('0', '1', '2', '3', '4', '5'):
            arg_string += "{" + arg + "},"
        else:
            arg_string += arg + ","
    arg_string = arg_string[:-1] + ")"
    return arg_string


Michael Kuron's avatar
Michael Kuron committed
18
def get_vector_instruction_set_arm(data_type='double', instruction_set='neon'):
Michael Kuron's avatar
Michael Kuron committed
19
    if instruction_set != 'neon' and not instruction_set.startswith('sve'):
Michael Kuron's avatar
Michael Kuron committed
20
        raise NotImplementedError(instruction_set)
Michael Kuron's avatar
Michael Kuron committed
21
22
23
24
25
26
27
28
29
    if instruction_set == 'sve':
        raise NotImplementedError("sizeless SVE is not implemented")

    if instruction_set.startswith('sve'):
        cmp = 'cmp'
        bitwidth = int(instruction_set[3:])
    elif instruction_set == 'neon':
        cmp = 'c'
        bitwidth = 128
Michael Kuron's avatar
Michael Kuron committed
30

Markus Holzer's avatar
Markus Holzer committed
31
32
33
34
35
36
37
38
39
40
41
42
43
    base_names = {
        '+': 'add[0, 1]',
        '-': 'sub[0, 1]',
        '*': 'mul[0, 1]',
        '/': 'div[0, 1]',
        'sqrt': 'sqrt[0]',

        'loadU': 'ld1[0]',
        'loadA': 'ld1[0]',
        'storeU': 'st1[0, 1]',
        'storeA': 'st1[0, 1]',

        'abs': 'abs[0]',
Michael Kuron's avatar
Michael Kuron committed
44
45
46
47
48
49
        '==': f'{cmp}eq[0, 1]',
        '!=': f'{cmp}eq[0, 1]',
        '<=': f'{cmp}le[0, 1]',
        '<': f'{cmp}lt[0, 1]',
        '>=': f'{cmp}ge[0, 1]',
        '>': f'{cmp}gt[0, 1]',
Markus Holzer's avatar
Markus Holzer committed
50
51
52
    }

    bits = {'double': 64,
Michael Kuron's avatar
Michael Kuron committed
53
54
            'float': 32,
            'int': 32}
Markus Holzer's avatar
Markus Holzer committed
55

Michael Kuron's avatar
Michael Kuron committed
56
57
58
59
60
61
62
63
    width = bitwidth // bits[data_type]
    intwidth = bitwidth // bits['int']
    if instruction_set.startswith('sve'):
        prefix = 'sv'
        suffix = f'_f{bits[data_type]}' 
    elif instruction_set == 'neon':
        prefix = 'v'
        suffix = f'q_f{bits[data_type]}' 
Markus Holzer's avatar
Markus Holzer committed
64
65

    result = dict()
Michael Kuron's avatar
Michael Kuron committed
66
67
68
69
    result['bytes'] = bitwidth // 8

    predicate = f'{prefix}whilelt_b{bits[data_type]}(0, {width})'
    int_predicate = f'{prefix}whilelt_b{bits["int"]}(0, {intwidth})'
Markus Holzer's avatar
Markus Holzer committed
70
71
72
73
74

    for intrinsic_id, function_shortcut in base_names.items():
        function_shortcut = function_shortcut.strip()
        name = function_shortcut[:function_shortcut.index('[')]

Michael Kuron's avatar
Michael Kuron committed
75
76
77
78
79
        arg_string = get_argument_string(function_shortcut, first=predicate if prefix == 'sv' else '')
        if prefix == 'sv' and not name.startswith('ld') and not name.startswith('st') and not name.startswith(cmp):
            undef = '_x'
        else:
            undef = ''
Markus Holzer's avatar
Markus Holzer committed
80

Michael Kuron's avatar
Michael Kuron committed
81
        result[intrinsic_id] = prefix + name + suffix + undef + arg_string
Markus Holzer's avatar
Markus Holzer committed
82

Michael Kuron's avatar
Michael Kuron committed
83
84
    result['width'] = width
    result['intwidth'] = intwidth
Michael Kuron's avatar
Michael Kuron committed
85

Michael Kuron's avatar
Michael Kuron committed
86
87
88
89
    if instruction_set.startswith('sve'):
        result['makeVecConst'] = f'svdup_f{bits[data_type]}' + '({0})'
        result['makeVecConstInt'] = f'svdup_s{bits["int"]}' + '({0})'
        result['makeVecIndex'] = f'svindex_s{bits["int"]}' + '({0}, {1})'
Markus Holzer's avatar
Markus Holzer committed
90

Michael Kuron's avatar
Michael Kuron committed
91
92
93
94
95
96
        vindex = f'svindex_u{bits[data_type]}(0, {{0}})'
        result['scatter'] = f'svst1_scatter_u{bits[data_type]}index_f{bits[data_type]}({predicate}, {{0}}, ' + \
                            vindex.format("{2}") + ', {1})'
        result['gather'] = f'svld1_gather_u{bits[data_type]}index_f{bits[data_type]}({predicate}, {{0}}, ' + \
                           vindex.format("{1}") + ')'

Michael Kuron's avatar
Michael Kuron committed
97
        result['+int'] = f"svadd_s{bits['int']}_x({int_predicate}, " + "{0}, {1})"
Markus Holzer's avatar
Markus Holzer committed
98

Michael Kuron's avatar
Michael Kuron committed
99
100
        result['float'] = 'svfloat32_st'
        result['double'] = 'svfloat64_st'
Michael Kuron's avatar
Michael Kuron committed
101
102
103
104
105
106
107
108
109
110
111
        result['int'] = f'svint{bits["int"]}_st'
        result['bool'] = 'svbool_st'

        result['headers'] = ['<arm_sve.h>', '"arm_neon_helpers.h"']

        result['&'] = f'svand_b_z({predicate},' + ' {0}, {1})'
        result['|'] = f'svorr_b_z({predicate},' + ' {0}, {1})'
        result['blendv'] = f'svsel_f{bits[data_type]}' + '({2}, {1}, {0})'
        result['any'] = f'svptest_any({predicate}, {{0}})'
        result['all'] = f'svcntp_b{bits[data_type]}({predicate}, {{0}}) == {width}'

Michael Kuron's avatar
Michael Kuron committed
112
113
114
115
        result['maskStoreU'] = result['storeU'].replace(predicate, '{2}')
        result['maskStoreA'] = result['storeA'].replace(predicate, '{2}')
        result['maskScatter'] = result['scatter'].replace(predicate, '{3}')

Michael Kuron's avatar
Michael Kuron committed
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
        result['compile_flags'] = [f'-msve-vector-bits={bitwidth}']
    else:
        result['makeVecConst'] = f'vdupq_n_f{bits[data_type]}' + '({0})'
        result['makeVec'] = f'makeVec_f{bits[data_type]}' + '(' + ", ".join(['{' + str(i) + '}' for i in
                                                                             range(width)]) + ')'
        result['makeVecConstInt'] = f'vdupq_n_s{bits["int"]}' + '({0})'
        result['makeVecInt'] = f'makeVec_s{bits["int"]}' + '({0}, {1}, {2}, {3})'

        result['+int'] = f"vaddq_s{bits['int']}" + "({0}, {1})"

        result[data_type] = f'float{bits[data_type]}x{width}_t'
        result['int'] = f'int{bits["int"]}x{intwidth}_t'
        result['bool'] = f'uint{bits[data_type]}x{width}_t'

        result['headers'] = ['<arm_neon.h>', '"arm_neon_helpers.h"']
Markus Holzer's avatar
Markus Holzer committed
131

Michael Kuron's avatar
Michael Kuron committed
132
        result['!='] = f'vmvnq_u{bits[data_type]}({result["=="]})'
Michael Kuron's avatar
Michael Kuron committed
133

Michael Kuron's avatar
Michael Kuron committed
134
135
136
137
138
        result['&'] = f'vandq_u{bits[data_type]}' + '({0}, {1})'
        result['|'] = f'vorrq_u{bits[data_type]}' + '({0}, {1})'
        result['blendv'] = f'vbslq_f{bits[data_type]}' + '({2}, {1}, {0})'
        result['any'] = f'vaddlvq_u8(vreinterpretq_u8_u{bits[data_type]}({{0}})) > 0'
        result['all'] = f'vaddlvq_u8(vreinterpretq_u8_u{bits[data_type]}({{0}})) == 16*0xff'
Markus Holzer's avatar
Markus Holzer committed
139

Michael Kuron's avatar
Michael Kuron committed
140
141
142
143
    if bitwidth & (bitwidth - 1) == 0:
        # only power-of-2 vector sizes will evenly divide a cacheline
        result['cachelineSize'] = 'cachelineSize()'
        result['cachelineZero'] = 'cachelineZero((void*) {0})'
144

Markus Holzer's avatar
Markus Holzer committed
145
    return result