98 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			98 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
	
| # This test generates all variants of load/store instructions and verifies that
 | |
| # LLVM generates correct PTX for them.
 | |
| 
 | |
| # RUN: python %s > %t.ll
 | |
| # RUN: llc < %t.ll -march=nvptx64 -mcpu=sm_30 | FileCheck -check-prefixes=CHECK,CHECK_P64 %t.ll
 | |
| # RUN: llc < %t.ll -march=nvptx -mcpu=sm_30 | FileCheck -check-prefixes=CHECK,CHECK_P32 %t.ll
 | |
| 
 | |
| from itertools import product
 | |
| from string import Template
 | |
| 
 | |
| llvm_type_to_ptx_type = {
 | |
|     "i8": "u8",
 | |
|     "i16": "u16",
 | |
|     "i32": "u32",
 | |
|     "i64": "u64",
 | |
|     "half": "b16",
 | |
|     "<2 x half>": "b32",
 | |
|     "float": "f32",
 | |
|     "double": "f64"
 | |
| }
 | |
| 
 | |
| llvm_type_to_ptx_reg = {
 | |
|     "i8": "r",
 | |
|     "i16": "r",
 | |
|     "i32": "r",
 | |
|     "i64": "rd",
 | |
|     "half": "h",
 | |
|     "<2 x half>": "hh",
 | |
|     "float": "f",
 | |
|     "double": "fd"
 | |
| }
 | |
| 
 | |
| addrspace_id = {
 | |
|     "": 0,
 | |
|     ".global": 1,
 | |
|     ".shared": 3,
 | |
|     ".const": 4,
 | |
|     ".local": 5,
 | |
|     ".param": 101
 | |
| }
 | |
| 
 | |
| 
 | |
| def gen_load_tests():
 | |
|   load_template = """
 | |
| define ${type} @ld${_volatile}${_space}.${ptx_type}(${type} addrspace(${asid})* %ptr) {
 | |
| ; CHECK_P32: ld${_volatile}${_volatile_as}.${ptx_type} %${ptx_reg}{{[0-9]+}}, [%r{{[0-9]+}}]
 | |
| ; CHECK_P64: ld${_volatile}${_volatile_as}.${ptx_type} %${ptx_reg}{{[0-9]+}}, [%rd{{[0-9]+}}]
 | |
| ; CHECK: ret
 | |
|   %p = ${generic_ptr}
 | |
|   %a = load ${volatile} ${type}, ${type}* %p
 | |
|   ret ${type} %a
 | |
| }
 | |
| """
 | |
|   for op_type, volatile, space in product(
 | |
|       ["i8", "i16", "i32", "i64", "half", "float", "double", "<2 x half>"],
 | |
|       [True, False],  # volatile
 | |
|       ["", ".shared", ".global", ".const", ".local", ".param"]):
 | |
| 
 | |
|     # Volatile is only supported for global, shared and generic.
 | |
|     if volatile and not space in ["", ".global", ".shared"]:
 | |
|       continue
 | |
| 
 | |
|     # Volatile is only supported for global, shared and generic.
 | |
|     # All other volatile accesses are done in generic AS.
 | |
|     if volatile and not space in ["", ".global", ".shared"]:
 | |
|       volatile_as = ""
 | |
|     else:
 | |
|       volatile_as = space
 | |
| 
 | |
|     params = {
 | |
|         "type": op_type,
 | |
|         "volatile": "volatile" if volatile else "",
 | |
|         "_volatile": ".volatile" if volatile else "",
 | |
|         "_volatile_as": volatile_as,
 | |
|         "_space": space,
 | |
|         "ptx_reg": llvm_type_to_ptx_reg[op_type],
 | |
|         "ptx_type": llvm_type_to_ptx_type[op_type],
 | |
|         "asid": addrspace_id[space],
 | |
|     }
 | |
| 
 | |
|     # LLVM does not accept "addrspacecast Type* addrspace(0) to Type*", so we
 | |
|     # need to avoid it for generic pointer tests.
 | |
|     if space:
 | |
|       generic_ptr_template = ("addrspacecast ${type} addrspace(${asid})* %ptr "
 | |
|                               "to ${type}*")
 | |
|     else:
 | |
|       generic_ptr_template = "select i1 true, ${type}* %ptr, ${type}* %ptr"
 | |
|     params["generic_ptr"] = Template(generic_ptr_template).substitute(params)
 | |
| 
 | |
|     print(Template(load_template).substitute(params))
 | |
| 
 | |
| 
 | |
| def main():
 | |
|   gen_load_tests()
 | |
| 
 | |
| 
 | |
| main()
 |