mirror of
https://github.com/RRZE-HPC/asmbench.git
synced 2026-01-08 21:40:12 +01:00
added support of correct dstsrc register constraints to tablegen
This commit is contained in:
28
bench.py
28
bench.py
@@ -213,20 +213,24 @@ init_value_by_llvm_type.update(
|
||||
|
||||
def bench_instruction(instruction):
|
||||
# Latency Benchmark
|
||||
lat = float('inf')
|
||||
for serial_factor in range(1, 16):
|
||||
s = op.Serialized([instruction] * serial_factor)
|
||||
init_values = [init_value_by_llvm_type[reg.llvm_type] for reg in s.get_source_registers()]
|
||||
b = IntegerLoopBenchmark(s, init_values)
|
||||
print(serial_factor)
|
||||
print(b.build_ir())
|
||||
print(b.get_assembly())
|
||||
result = b.build_and_execute(repeat=4, min_elapsed=0.1, max_elapsed=0.3)
|
||||
lat = min(lat, *[(t/serial_factor)*result['frequency']/result['iterations']
|
||||
for t in result['runtimes']])
|
||||
serial_factor = 8
|
||||
s = op.Serialized([instruction] * serial_factor)
|
||||
init_values = [init_value_by_llvm_type[reg.llvm_type] for reg in s.get_source_registers()]
|
||||
b = IntegerLoopBenchmark(s, init_values)
|
||||
result = b.build_and_execute(repeat=4, min_elapsed=0.1, max_elapsed=0.3)
|
||||
lat = min(*[(t/serial_factor)*result['frequency']/result['iterations']
|
||||
for t in result['runtimes']])
|
||||
|
||||
# Throughput Benchmark
|
||||
tp = 0
|
||||
parallel_factor = 7
|
||||
serial_factor = 4
|
||||
p = op.Parallelized([op.Serialized([instruction] * serial_factor)] * parallel_factor)
|
||||
init_values = [init_value_by_llvm_type[reg.llvm_type] for reg in
|
||||
p.get_source_registers()]
|
||||
b = IntegerLoopBenchmark(p, init_values)
|
||||
result = b.build_and_execute(repeat=4, min_elapsed=0.1, max_elapsed=0.3)
|
||||
tp = min([(t/serial_factor/parallel_factor)*result['frequency']/result['iterations']
|
||||
for t in result['runtimes']])
|
||||
|
||||
# Ports
|
||||
ports = 0
|
||||
|
||||
2
op.py
2
op.py
@@ -160,7 +160,7 @@ class Instruction(Operation):
|
||||
args = ', '.join(operands)
|
||||
|
||||
# Build instruction from instruction and operands
|
||||
return ('{dst_reg} = call {dst_type} asm sideeffect'
|
||||
return ('{dst_reg} = call {dst_type} asm '
|
||||
' "{instruction}", "{constraints}" ({args})').format(
|
||||
dst_reg=dst_reg_names[0],
|
||||
dst_type=self.destination_operand.llvm_type,
|
||||
|
||||
51
tablegen.py
51
tablegen.py
@@ -223,6 +223,8 @@ def convert_operands(operands, data):
|
||||
|
||||
|
||||
def build_operand(op_constraint, op_type):
|
||||
if re.match(r'[0-9]+', op_constraint):
|
||||
return op.Register(op_type, op_constraint)
|
||||
if op_constraint in ['r', 'x']:
|
||||
return op.Register(op_type, op_constraint)
|
||||
elif op_constraint == 'i':
|
||||
@@ -347,7 +349,7 @@ def main():
|
||||
for vt in reg_data[('list<ValueType>', 'RegTypes')].split(', '):
|
||||
llvm_types.append(evt_to_llvm_type(vt))
|
||||
|
||||
# Get opernad information and filter all unsupported operand types (e.g., memory references)
|
||||
# Get operand information and filter all unsupported operand types (e.g., memory references)
|
||||
try:
|
||||
instr_info['source operands'] = convert_operands(instr[('dag', 'InOperandList')], data)
|
||||
instr_info['destination operands'] = convert_operands(instr[('dag', 'OutOperandList')], data)
|
||||
@@ -374,14 +376,8 @@ def main():
|
||||
# Build op.Instruction
|
||||
# Build registers for source (in) and destination (out) operands
|
||||
source_operands = []
|
||||
destination_operand = None
|
||||
try:
|
||||
for so_name, so_type in instr_info['source operands'].items():
|
||||
if len(so_type) != 1:
|
||||
# FIXME which one to select?
|
||||
pass
|
||||
source_operands.append(build_operand(so_type[0][0], so_type[0][1]))
|
||||
|
||||
destination_operand = None
|
||||
if len(instr_info['destination operands']) < 1:
|
||||
# FIXME use "uses" and "defines"
|
||||
continue
|
||||
@@ -397,6 +393,22 @@ def main():
|
||||
destination_operand = op.Register(do_type[0][1], do_type[0][0])
|
||||
else:
|
||||
raise ValueError('Destination operand is not a register')
|
||||
|
||||
for so_name, so_type in instr_info['source operands'].items():
|
||||
if len(so_type) != 1:
|
||||
# FIXME which one to select?
|
||||
pass
|
||||
if so_name in instr_info['destination operands']:
|
||||
# If this operand is both source AND destination, the source constraint string
|
||||
# needs to reference the destination
|
||||
if len(instr_info['destination operands']) > 1:
|
||||
raise ValueError("Multiple destination operands are not supported")
|
||||
# FIXME if multiple destinations are supported, the intere needs to match dst
|
||||
# order
|
||||
constraint = '0'
|
||||
else:
|
||||
constraint = so_type[0][0]
|
||||
source_operands.append(build_operand(constraint, so_type[0][1]))
|
||||
except ValueError as e:
|
||||
print("skipped", instr_name, str(e), file=sys.stderr)
|
||||
continue
|
||||
@@ -422,27 +434,30 @@ def main():
|
||||
for so in instr_op.source_operands]):
|
||||
# TODO take also "uses" and "defs" into account
|
||||
continue
|
||||
|
||||
|
||||
tp, lat, ports = bench.bench_instruction(instr_op)
|
||||
print("{:>12} {:>5.2f} {:>5.2f}".format(instr_name, tp, lat))
|
||||
|
||||
continue
|
||||
s = op.Serialized([instr_op])
|
||||
s.build_ir()
|
||||
|
||||
print('{:>12} '.format(instr_name), end='')
|
||||
sys.stdout.flush()
|
||||
|
||||
# Choose init_value according to llvm_type
|
||||
init_values = {r.get_ir_repr(): init_value_by_llvm_type[r.llvm_type]
|
||||
for r in s.get_source_registers()}
|
||||
init_values = [init_value_by_llvm_type[r.llvm_type]
|
||||
for r in s.get_source_registers()]
|
||||
b = bench.IntegerLoopBenchmark(s, init_values)
|
||||
print()
|
||||
#print(instr_name)
|
||||
#pprint(instr_data[instr_name])
|
||||
pprint(instr_data[instr_name])
|
||||
#print(i)
|
||||
#print(s.build_ir())
|
||||
#print(b.build_ir())
|
||||
#print(b.get_assembly())
|
||||
print(b.build_ir())
|
||||
print(b.get_assembly())
|
||||
r = b.build_and_execute(repeat=1)
|
||||
print('{:>5.2f} cy/It'.format(min(r['runtimes'])*r['frequency']/r['iterations']))
|
||||
|
||||
op.Register.reset()
|
||||
|
||||
break
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user