mirror of
https://github.com/RRZE-HPC/asmbench.git
synced 2025-07-20 20:21:05 +02:00
Add explicit support for AArch64
Specifies register shape and suffix for floating point and vector registers. The former cannot be benchmarked without and the latter would require adding the required suffixes manually in the instruction operands. Doing both allows using them in the same manner as on x86. Additionally there are two small changes affecting all architectures: Allow the 'w' constraint code, which is used for vector registers on aarch64. Always specify a clobber for the flags register as many instructions one might want to benchmark modify it.
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
import re
|
||||
from itertools import zip_longest
|
||||
|
||||
import llvmlite.binding as llvm
|
||||
|
||||
# TODO use abc to force implementation of interface requirements
|
||||
|
||||
init_value_by_llvm_type = {'i' + bits: '3' for bits in ['1', '8', '16', '32', '64']}
|
||||
@@ -16,6 +18,22 @@ init_value_by_llvm_type.update(
|
||||
for vec in [2, 4, 8, 16, 32, 64]})
|
||||
|
||||
|
||||
aarch64_llvm_type_shape = {
|
||||
'float': 's',
|
||||
'double': 'd'
|
||||
}
|
||||
aarch64_llvm_type_suffix = {
|
||||
'<8 x i8>': '8b',
|
||||
'<16 x i8>': '16b',
|
||||
'<4 x i16>': '4h',
|
||||
'<8 x i16>': '8h',
|
||||
'<4 x i32>': '4s',
|
||||
'<2 x i64>>': '2d',
|
||||
'<4 x float>': '4s',
|
||||
'<2 x double>': '2d'
|
||||
}
|
||||
|
||||
|
||||
class NotSerializableError(Exception):
|
||||
pass
|
||||
|
||||
@@ -26,6 +44,38 @@ class Operand:
|
||||
def get_constraint_char(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def template_string(self, index):
|
||||
"""
|
||||
Generate template string to be used in LLVM IR call asm.
|
||||
|
||||
This is used to disambiguate different usage types of a single register
|
||||
from its constaint code.
|
||||
|
||||
E.g. on aarch64 targets float types will append a shape parameter to
|
||||
differentiate between single and double precision types.
|
||||
|
||||
:param index: Index to use for input or output constraints.
|
||||
"""
|
||||
# Optional ${reg:shape} parameter
|
||||
shape = None
|
||||
# Optional ${reg}.suffix parameter
|
||||
suffix = None
|
||||
|
||||
target_triple = llvm.get_default_triple()
|
||||
if target_triple.startswith('aarch64-'):
|
||||
shape = aarch64_llvm_type_shape.get(self.llvm_type)
|
||||
suffix = aarch64_llvm_type_suffix.get(self.llvm_type)
|
||||
|
||||
if shape == None:
|
||||
shape = ''
|
||||
else:
|
||||
shape = ':' + shape
|
||||
if suffix == None:
|
||||
suffix = ''
|
||||
else:
|
||||
suffix = '.' + suffix
|
||||
return '${{{}{}}}{}'.format(index, shape, suffix)
|
||||
|
||||
def __repr__(self):
|
||||
return '{}({})'.format(
|
||||
self.__class__.__name__,
|
||||
@@ -154,7 +204,7 @@ class Register(Operand):
|
||||
:param s: must have the form: "llvm_type:constraint_char"
|
||||
"""
|
||||
llvm_type, constraint_char = s.split(':', 1)
|
||||
valid_cc = 'rx'
|
||||
valid_cc = 'rxw'
|
||||
if constraint_char not in valid_cc:
|
||||
raise ValueError("Invalid constraint character, must be one of {!r}".format(valid_cc))
|
||||
return cls(llvm_type, constraint_char)
|
||||
@@ -240,7 +290,8 @@ class Instruction(Operation):
|
||||
# Build constraint string from operands
|
||||
constraints = ','.join(
|
||||
['=' + self.destination_operand.get_constraint_char()] +
|
||||
[sop.get_constraint_char() for sop in self.source_operands])
|
||||
[sop.get_constraint_char() for sop in self.source_operands] +
|
||||
['~{cc}'])
|
||||
|
||||
# Build argument string from operands and register names
|
||||
operands = []
|
||||
@@ -305,13 +356,13 @@ class Instruction(Operation):
|
||||
if 'src' in direction and not 'dst' in direction:
|
||||
src_ops.append(operand)
|
||||
# replace with index string
|
||||
instruction = (instruction[:m.start()] + "${}".format(src_index)
|
||||
instruction = (instruction[:m.start()] + operand.template_string(src_index)
|
||||
+ instruction[m.end():])
|
||||
src_index += 1
|
||||
if 'dst' in direction:
|
||||
dst_ops.append(operand)
|
||||
# replace with index string
|
||||
instruction = (instruction[:m.start()] + "${}".format(dst_index)
|
||||
instruction = (instruction[:m.start()] + operand.template_string(dst_index)
|
||||
+ instruction[m.end():])
|
||||
if 'src' in direction:
|
||||
src_ops.append(Register(operand_string.split(':', 1)[0], str(dst_index)))
|
||||
|
Reference in New Issue
Block a user