121 lines · python
1# This test generates all variants of load/store instructions and verifies that2# LLVM generates correct PTX for them.3 4# RUN: %python %s > %t.ll5# RUN: llc < %t.ll -mtriple=nvptx -mcpu=sm_30 | FileCheck -check-prefixes=CHECK,CHECK_P32 %t.ll6# RUN: llc < %t.ll -mtriple=nvptx64 -mcpu=sm_30 | FileCheck -check-prefixes=CHECK,CHECK_P64 %t.ll7# RUN: %if ptxas-ptr32 %{ llc < %t.ll -mtriple=nvptx -mcpu=sm_30 | %ptxas-verify %}8# RUN: %if ptxas %{ llc < %t.ll -mtriple=nvptx64 -mcpu=sm_30 | %ptxas-verify %}9 10from __future__ import print_function11 12from itertools import product13from string import Template14 15 16llvm_type_to_ptx_load_type = {17 "i8": "b8",18 "i16": "b16",19 "i32": "b32",20 "i64": "b64",21 "half": "b16",22 "<2 x half>": "b32",23 "float": "b32",24 "double": "b64",25}26 27llvm_type_to_ptx_type = {28 "i8": "u8",29 "i16": "u16",30 "i32": "u32",31 "i64": "u64",32 "half": "b16",33 "<2 x half>": "b32",34 "float": "f32",35 "double": "f64",36}37 38llvm_type_to_ptx_reg = {39 "i8": "r",40 "i16": "r",41 "i32": "r",42 "i64": "rd",43 "half": "rs",44 "<2 x half>": "r",45 "float": "r",46 "double": "rd",47}48 49addrspace_id = {50 "": 0,51 ".global": 1,52 ".shared": 3,53 ".const": 4,54 ".local": 5,55 ".param": 101,56}57 58 59def gen_load_tests():60 load_template = """61define ${type} @${testname}(${type} addrspace(${asid})* %ptr) {62; CHECK: ${testname}63; CHECK_P32: ld${_volatile}${_volatile_as}.${ptx_load_type} %${ptx_reg}{{[0-9]+}}, [%r{{[0-9]+}}]64; CHECK_P64: ld${_volatile}${_volatile_as}.${ptx_load_type} %${ptx_reg}{{[0-9]+}}, [%rd{{[0-9]+}}]65; CHECK: ret66 %p = ${generic_ptr}67 %a = load ${volatile} ${type}, ${type}* %p68 ret ${type} %a69}70"""71 for op_type, volatile, space in product(72 ["i8", "i16", "i32", "i64", "half", "float", "double", "<2 x half>"],73 [True, False], # volatile74 ["", ".shared", ".global", ".const", ".local", ".param"],75 ):76 77 # Volatile is only supported for global, shared and generic.78 if volatile and not space in ["", ".global", ".shared"]:79 continue80 81 # Volatile is only supported for global, shared and generic.82 # All other volatile accesses are done in generic AS.83 if volatile and not space in ["", ".global", ".shared"]:84 volatile_as = ""85 else:86 volatile_as = space87 88 params = {89 "type": op_type,90 "volatile": "volatile" if volatile else "",91 "_volatile": ".volatile" if volatile else "",92 "_volatile_as": volatile_as,93 "_space": space,94 "ptx_reg": llvm_type_to_ptx_reg[op_type],95 "ptx_type": llvm_type_to_ptx_type[op_type],96 "ptx_load_type": llvm_type_to_ptx_load_type[op_type],97 "asid": addrspace_id[space],98 }99 100 testname = Template("ld_${_volatile}${_space}.${ptx_type}").substitute(params)101 params["testname"] = testname.replace(".", "_")102 103 # LLVM does not accept "addrspacecast Type* addrspace(0) to Type*", so we104 # need to avoid it for generic pointer tests.105 if space:106 generic_ptr_template = (107 "addrspacecast ${type} addrspace(${asid})* %ptr " "to ${type}*"108 )109 else:110 generic_ptr_template = "select i1 true, ${type}* %ptr, ${type}* %ptr"111 params["generic_ptr"] = Template(generic_ptr_template).substitute(params)112 113 print(Template(load_template).substitute(params))114 115 116def main():117 gen_load_tests()118 119 120main()121