373 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			LLVM
		
	
	
	
			
		
		
	
	
			373 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			LLVM
		
	
	
	
| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 | |
| ; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -infer-address-spaces -instsimplify %s | FileCheck %s
 | |
| 
 | |
| target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5"
 | |
| 
 | |
| define i8 @ptrmask_cast_local_to_flat(i8 addrspace(3)* %src.ptr, i64 %mask) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_local_to_flat(
 | |
| ; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8 addrspace(3)* [[SRC_PTR:%.*]] to i8*
 | |
| ; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[CAST]], i64 [[MASK:%.*]])
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8* [[MASKED]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %cast = addrspacecast i8 addrspace(3)* %src.ptr to i8*
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %mask)
 | |
|   %load = load i8, i8* %masked
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| define i8 @ptrmask_cast_private_to_flat(i8 addrspace(5)* %src.ptr, i64 %mask) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_private_to_flat(
 | |
| ; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8 addrspace(5)* [[SRC_PTR:%.*]] to i8*
 | |
| ; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[CAST]], i64 [[MASK:%.*]])
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8* [[MASKED]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %cast = addrspacecast i8 addrspace(5)* %src.ptr to i8*
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %mask)
 | |
|   %load = load i8, i8* %masked
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| define i8 @ptrmask_cast_region_to_flat(i8 addrspace(2)* %src.ptr, i64 %mask) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_region_to_flat(
 | |
| ; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8 addrspace(2)* [[SRC_PTR:%.*]] to i8*
 | |
| ; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[CAST]], i64 [[MASK:%.*]])
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8* [[MASKED]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %cast = addrspacecast i8 addrspace(2)* %src.ptr to i8*
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %mask)
 | |
|   %load = load i8, i8* %masked
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| define i8 @ptrmask_cast_global_to_flat(i8 addrspace(1)* %src.ptr, i64 %mask) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_global_to_flat(
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 addrspace(1)* @llvm.ptrmask.p1i8.i64(i8 addrspace(1)* [[SRC_PTR:%.*]], i64 [[MASK:%.*]])
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(1)* [[TMP1]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %cast = addrspacecast i8 addrspace(1)* %src.ptr to i8*
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %mask)
 | |
|   %load = load i8, i8* %masked
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| define i8 @ptrmask_cast_999_to_flat(i8 addrspace(999)* %src.ptr, i64 %mask) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_999_to_flat(
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 addrspace(999)* @llvm.ptrmask.p999i8.i64(i8 addrspace(999)* [[SRC_PTR:%.*]], i64 [[MASK:%.*]])
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(999)* [[TMP1]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %cast = addrspacecast i8 addrspace(999)* %src.ptr to i8*
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %mask)
 | |
|   %load = load i8, i8* %masked
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| define i8 @ptrmask_cast_flat_to_local(i8* %ptr, i64 %mask) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_flat_to_local(
 | |
| ; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[PTR:%.*]], i64 [[MASK:%.*]])
 | |
| ; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8* [[MASKED]] to i8 addrspace(3)*
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(3)* [[CAST]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %ptr, i64 %mask)
 | |
|   %cast = addrspacecast i8* %masked to i8 addrspace(3)*
 | |
|   %load = load i8, i8 addrspace(3)* %cast
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| define i8 @ptrmask_cast_flat_to_private(i8* %ptr, i64 %mask) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_flat_to_private(
 | |
| ; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[PTR:%.*]], i64 [[MASK:%.*]])
 | |
| ; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8* [[MASKED]] to i8 addrspace(5)*
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(5)* [[CAST]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %ptr, i64 %mask)
 | |
|   %cast = addrspacecast i8* %masked to i8 addrspace(5)*
 | |
|   %load = load i8, i8 addrspace(5)* %cast
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| define i8 @ptrmask_cast_flat_to_global(i8* %ptr, i64 %mask) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_flat_to_global(
 | |
| ; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[PTR:%.*]], i64 [[MASK:%.*]])
 | |
| ; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8* [[MASKED]] to i8 addrspace(1)*
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(1)* [[CAST]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %ptr, i64 %mask)
 | |
|   %cast = addrspacecast i8* %masked to i8 addrspace(1)*
 | |
|   %load = load i8, i8 addrspace(1)* %cast
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| @lds0 = internal addrspace(3) global i8 123, align 4
 | |
| @gv = internal addrspace(1) global i8 123, align 4
 | |
| 
 | |
| define i8 @ptrmask_cast_local_to_flat_global(i64 %mask) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_local_to_flat_global(
 | |
| ; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* addrspacecast (i8 addrspace(3)* @lds0 to i8*), i64 [[MASK:%.*]])
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8* [[MASKED]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* addrspacecast (i8 addrspace(3)* @lds0 to i8*), i64 %mask)
 | |
|   %load = load i8, i8* %masked, align 1
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| define i8 @ptrmask_cast_global_to_flat_global(i64 %mask) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_global_to_flat_global(
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 addrspace(1)* @llvm.ptrmask.p1i8.i64(i8 addrspace(1)* @gv, i64 [[MASK:%.*]])
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(1)* [[TMP1]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* addrspacecast (i8 addrspace(1)* @gv to i8*), i64 %mask)
 | |
|   %load = load i8, i8* %masked, align 1
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| define i8 @multi_ptrmask_cast_global_to_flat(i8 addrspace(1)* %src.ptr, i64 %mask) {
 | |
| ; CHECK-LABEL: @multi_ptrmask_cast_global_to_flat(
 | |
| ; CHECK-NEXT:    [[LOAD0:%.*]] = load i8, i8 addrspace(1)* [[SRC_PTR:%.*]], align 1
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 addrspace(1)* @llvm.ptrmask.p1i8.i64(i8 addrspace(1)* [[SRC_PTR]], i64 [[MASK:%.*]])
 | |
| ; CHECK-NEXT:    [[LOAD1:%.*]] = load i8, i8 addrspace(1)* [[TMP1]], align 1
 | |
| ; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[LOAD0]], [[LOAD1]]
 | |
| ; CHECK-NEXT:    ret i8 [[ADD]]
 | |
| ;
 | |
|   %cast = addrspacecast i8 addrspace(1)* %src.ptr to i8*
 | |
|   %load0 = load i8, i8* %cast
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %mask)
 | |
|   %load1 = load i8, i8* %masked
 | |
|   %add = add i8 %load0, %load1
 | |
|   ret i8 %add
 | |
| }
 | |
| 
 | |
| ; Can't rewrite the ptrmask, but can rewrite other use instructions
 | |
| define i8 @multi_ptrmask_cast_local_to_flat(i8 addrspace(3)* %src.ptr, i64 %mask) {
 | |
| ; CHECK-LABEL: @multi_ptrmask_cast_local_to_flat(
 | |
| ; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8 addrspace(3)* [[SRC_PTR:%.*]] to i8*
 | |
| ; CHECK-NEXT:    [[LOAD0:%.*]] = load i8, i8 addrspace(3)* [[SRC_PTR]], align 1
 | |
| ; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[CAST]], i64 [[MASK:%.*]])
 | |
| ; CHECK-NEXT:    [[LOAD1:%.*]] = load i8, i8* [[MASKED]], align 1
 | |
| ; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[LOAD0]], [[LOAD1]]
 | |
| ; CHECK-NEXT:    ret i8 [[ADD]]
 | |
| ;
 | |
|   %cast = addrspacecast i8 addrspace(3)* %src.ptr to i8*
 | |
|   %load0 = load i8, i8* %cast
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %mask)
 | |
|   %load1 = load i8, i8* %masked
 | |
|   %add = add i8 %load0, %load1
 | |
|   ret i8 %add
 | |
| }
 | |
| 
 | |
| define i8 @multi_ptrmask_cast_region_to_flat(i8 addrspace(2)* %src.ptr, i64 %mask) {
 | |
| ; CHECK-LABEL: @multi_ptrmask_cast_region_to_flat(
 | |
| ; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8 addrspace(2)* [[SRC_PTR:%.*]] to i8*
 | |
| ; CHECK-NEXT:    [[LOAD0:%.*]] = load i8, i8 addrspace(2)* [[SRC_PTR]], align 1
 | |
| ; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[CAST]], i64 [[MASK:%.*]])
 | |
| ; CHECK-NEXT:    [[LOAD1:%.*]] = load i8, i8* [[MASKED]], align 1
 | |
| ; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[LOAD0]], [[LOAD1]]
 | |
| ; CHECK-NEXT:    ret i8 [[ADD]]
 | |
| ;
 | |
|   %cast = addrspacecast i8 addrspace(2)* %src.ptr to i8*
 | |
|   %load0 = load i8, i8* %cast
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %mask)
 | |
|   %load1 = load i8, i8* %masked
 | |
|   %add = add i8 %load0, %load1
 | |
|   ret i8 %add
 | |
| }
 | |
| 
 | |
| ; Do not fold this since it clears a single high bit.
 | |
| define i8 @ptrmask_cast_local_to_flat_const_mask_fffffffeffffffff(i8 addrspace(3)* %src.ptr) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_local_to_flat_const_mask_fffffffeffffffff(
 | |
| ; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8 addrspace(3)* [[SRC_PTR:%.*]] to i8*
 | |
| ; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[CAST]], i64 -4294967297)
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8* [[MASKED]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %cast = addrspacecast i8 addrspace(3)* %src.ptr to i8*
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 -4294967297)
 | |
|   %load = load i8, i8* %masked
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| ; Do not fold this since it clears a single high bit.
 | |
| define i8 @ptrmask_cast_local_to_flat_const_mask_7fffffffffffffff(i8 addrspace(3)* %src.ptr) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_local_to_flat_const_mask_7fffffffffffffff(
 | |
| ; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8 addrspace(3)* [[SRC_PTR:%.*]] to i8*
 | |
| ; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i64(i8* [[CAST]], i64 9223372036854775807)
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8* [[MASKED]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %cast = addrspacecast i8 addrspace(3)* %src.ptr to i8*
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 9223372036854775807)
 | |
|   %load = load i8, i8* %masked
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| define i8 @ptrmask_cast_local_to_flat_const_mask_ffffffff00000000(i8 addrspace(3)* %src.ptr) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_local_to_flat_const_mask_ffffffff00000000(
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 addrspace(3)* @llvm.ptrmask.p3i8.i32(i8 addrspace(3)* [[SRC_PTR:%.*]], i32 0)
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(3)* [[TMP1]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %cast = addrspacecast i8 addrspace(3)* %src.ptr to i8*
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 -4294967296)
 | |
|   %load = load i8, i8* %masked
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| define i8 @ptrmask_cast_local_to_flat_const_mask_ffffffff80000000(i8 addrspace(3)* %src.ptr) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_local_to_flat_const_mask_ffffffff80000000(
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 addrspace(3)* @llvm.ptrmask.p3i8.i32(i8 addrspace(3)* [[SRC_PTR:%.*]], i32 -2147483648)
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(3)* [[TMP1]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %cast = addrspacecast i8 addrspace(3)* %src.ptr to i8*
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 -2147483648)
 | |
|   %load = load i8, i8* %masked
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| ; Test some align-down patterns. These only touch the low bits, which are preserved through the cast.
 | |
| define i8 @ptrmask_cast_local_to_flat_const_mask_ffffffffffff0000(i8 addrspace(3)* %src.ptr) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_local_to_flat_const_mask_ffffffffffff0000(
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 addrspace(3)* @llvm.ptrmask.p3i8.i32(i8 addrspace(3)* [[SRC_PTR:%.*]], i32 -65536)
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(3)* [[TMP1]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %cast = addrspacecast i8 addrspace(3)* %src.ptr to i8*
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 -65536)
 | |
|   %load = load i8, i8* %masked
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| define i8 @ptrmask_cast_local_to_flat_const_mask_ffffffffffffff00(i8 addrspace(3)* %src.ptr) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_local_to_flat_const_mask_ffffffffffffff00(
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 addrspace(3)* @llvm.ptrmask.p3i8.i32(i8 addrspace(3)* [[SRC_PTR:%.*]], i32 -256)
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(3)* [[TMP1]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %cast = addrspacecast i8 addrspace(3)* %src.ptr to i8*
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 -256)
 | |
|   %load = load i8, i8* %masked
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| define i8 @ptrmask_cast_local_to_flat_const_mask_ffffffffffffffe0(i8 addrspace(3)* %src.ptr) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_local_to_flat_const_mask_ffffffffffffffe0(
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 addrspace(3)* @llvm.ptrmask.p3i8.i32(i8 addrspace(3)* [[SRC_PTR:%.*]], i32 -32)
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(3)* [[TMP1]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %cast = addrspacecast i8 addrspace(3)* %src.ptr to i8*
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 -32)
 | |
|   %load = load i8, i8* %masked
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| define i8 @ptrmask_cast_local_to_flat_const_mask_fffffffffffffff0(i8 addrspace(3)* %src.ptr) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_local_to_flat_const_mask_fffffffffffffff0(
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 addrspace(3)* @llvm.ptrmask.p3i8.i32(i8 addrspace(3)* [[SRC_PTR:%.*]], i32 -16)
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(3)* [[TMP1]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %cast = addrspacecast i8 addrspace(3)* %src.ptr to i8*
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 -16)
 | |
|   %load = load i8, i8* %masked
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| define i8 @ptrmask_cast_local_to_flat_const_mask_fffffffffffffff8(i8 addrspace(3)* %src.ptr) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_local_to_flat_const_mask_fffffffffffffff8(
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 addrspace(3)* @llvm.ptrmask.p3i8.i32(i8 addrspace(3)* [[SRC_PTR:%.*]], i32 -8)
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(3)* [[TMP1]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %cast = addrspacecast i8 addrspace(3)* %src.ptr to i8*
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 -8)
 | |
|   %load = load i8, i8* %masked
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| define i8 @ptrmask_cast_local_to_flat_const_mask_fffffffffffffffc(i8 addrspace(3)* %src.ptr) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_local_to_flat_const_mask_fffffffffffffffc(
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 addrspace(3)* @llvm.ptrmask.p3i8.i32(i8 addrspace(3)* [[SRC_PTR:%.*]], i32 -4)
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(3)* [[TMP1]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %cast = addrspacecast i8 addrspace(3)* %src.ptr to i8*
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 -4)
 | |
|   %load = load i8, i8* %masked
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| define i8 @ptrmask_cast_local_to_flat_const_mask_fffffffffffffffe(i8 addrspace(3)* %src.ptr) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_local_to_flat_const_mask_fffffffffffffffe(
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 addrspace(3)* @llvm.ptrmask.p3i8.i32(i8 addrspace(3)* [[SRC_PTR:%.*]], i32 -2)
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(3)* [[TMP1]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %cast = addrspacecast i8 addrspace(3)* %src.ptr to i8*
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 -2)
 | |
|   %load = load i8, i8* %masked
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| define i8 @ptrmask_cast_local_to_flat_const_mask_ffffffffffffffff(i8 addrspace(3)* %src.ptr) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_local_to_flat_const_mask_ffffffffffffffff(
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 addrspace(3)* @llvm.ptrmask.p3i8.i32(i8 addrspace(3)* [[SRC_PTR:%.*]], i32 -1)
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(3)* [[TMP1]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %cast = addrspacecast i8 addrspace(3)* %src.ptr to i8*
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 -1)
 | |
|   %load = load i8, i8* %masked
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| ; Make sure non-constant masks can also be handled.
 | |
| define i8 @ptrmask_cast_local_to_flat_load_range_mask(i8 addrspace(3)* %src.ptr, i64 addrspace(1)* %mask.ptr) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_local_to_flat_load_range_mask(
 | |
| ; CHECK-NEXT:    [[LOAD_MASK:%.*]] = load i64, i64 addrspace(1)* [[MASK_PTR:%.*]], align 8, !range !0
 | |
| ; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[LOAD_MASK]] to i32
 | |
| ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 addrspace(3)* @llvm.ptrmask.p3i8.i32(i8 addrspace(3)* [[SRC_PTR:%.*]], i32 [[TMP1]])
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8 addrspace(3)* [[TMP2]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %load.mask = load i64, i64 addrspace(1)* %mask.ptr, align 8, !range !0
 | |
|   %cast = addrspacecast i8 addrspace(3)* %src.ptr to i8*
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i64(i8* %cast, i64 %load.mask)
 | |
|   %load = load i8, i8* %masked
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| ; This should not be folded, as the mask is implicitly zero extended,
 | |
| ; so it would clear the high bits.
 | |
| define i8 @ptrmask_cast_local_to_flat_const_mask_32bit_neg4(i8 addrspace(3)* %src.ptr) {
 | |
| ; CHECK-LABEL: @ptrmask_cast_local_to_flat_const_mask_32bit_neg4(
 | |
| ; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast i8 addrspace(3)* [[SRC_PTR:%.*]] to i8*
 | |
| ; CHECK-NEXT:    [[MASKED:%.*]] = call i8* @llvm.ptrmask.p0i8.i32(i8* [[CAST]], i32 -4)
 | |
| ; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8* [[MASKED]], align 1
 | |
| ; CHECK-NEXT:    ret i8 [[LOAD]]
 | |
| ;
 | |
|   %cast = addrspacecast i8 addrspace(3)* %src.ptr to i8*
 | |
|   %masked = call i8* @llvm.ptrmask.p0i8.i32(i8* %cast, i32 -4)
 | |
|   %load = load i8, i8* %masked
 | |
|   ret i8 %load
 | |
| }
 | |
| 
 | |
| declare i8* @llvm.ptrmask.p0i8.i64(i8*, i64) #0
 | |
| declare i8* @llvm.ptrmask.p0i8.i32(i8*, i32) #0
 | |
| declare i8 addrspace(5)* @llvm.ptrmask.p5i8.i32(i8 addrspace(5)*, i32) #0
 | |
| declare i8 addrspace(3)* @llvm.ptrmask.p3i8.i32(i8 addrspace(3)*, i32) #0
 | |
| declare i8 addrspace(1)* @llvm.ptrmask.p1i8.i64(i8 addrspace(1)*, i64) #0
 | |
| 
 | |
| attributes #0 = { nounwind readnone speculatable willreturn }
 | |
| 
 | |
| !0 = !{i64 -64, i64 -1}
 |