1 ; RUN: opt -S -instcombine %s -o - | FileCheck %s 2 target datalayout = "e-p:32:32:32-p1:64:64:64-p2:8:8:8-p3:16:16:16-p4:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:32" 3 4 @g = addrspace(3) global i32 89 5 6 @const_zero_i8_as1 = addrspace(1) constant i8 0 7 @const_zero_i32_as1 = addrspace(1) constant i32 0 8 9 @const_zero_i8_as2 = addrspace(2) constant i8 0 10 @const_zero_i32_as2 = addrspace(2) constant i32 0 11 12 @const_zero_i8_as3 = addrspace(3) constant i8 0 13 @const_zero_i32_as3 = addrspace(3) constant i32 0 14 15 ; Test constant folding of inttoptr (ptrtoint constantexpr) 16 ; The intermediate integer size is the same as the pointer size 17 define i32 addrspace(3)* @test_constant_fold_inttoptr_as_pointer_same_size() { 18 ; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_same_size( 19 ; CHECK-NEXT: ret i32 addrspace(3)* @const_zero_i32_as3 20 %x = ptrtoint i32 addrspace(3)* @const_zero_i32_as3 to i32 21 %y = inttoptr i32 %x to i32 addrspace(3)* 22 ret i32 addrspace(3)* %y 23 } 24 25 ; The intermediate integer size is larger than the pointer size 26 define i32 addrspace(2)* @test_constant_fold_inttoptr_as_pointer_smaller() { 27 ; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_smaller( 28 ; CHECK-NEXT: ret i32 addrspace(2)* @const_zero_i32_as2 29 %x = ptrtoint i32 addrspace(2)* @const_zero_i32_as2 to i16 30 %y = inttoptr i16 %x to i32 addrspace(2)* 31 ret i32 addrspace(2)* %y 32 } 33 34 ; Different address spaces that are the same size, but they are 35 ; different so nothing should happen 36 define i32 addrspace(4)* @test_constant_fold_inttoptr_as_pointer_smaller_different_as() { 37 ; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_smaller_different_as( 38 ; CHECK-NEXT: ret i32 addrspace(4)* inttoptr (i16 ptrtoint (i32 addrspace(3)* @const_zero_i32_as3 to i16) to i32 addrspace(4)*) 39 %x = ptrtoint i32 addrspace(3)* @const_zero_i32_as3 to i16 40 %y = inttoptr i16 %x to i32 addrspace(4)* 41 ret i32 addrspace(4)* %y 42 } 43 44 ; Make sure we don't introduce a bitcast between different sized 45 ; address spaces when folding this 46 define i32 addrspace(2)* @test_constant_fold_inttoptr_as_pointer_smaller_different_size_as() { 47 ; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_smaller_different_size_as( 48 ; CHECK-NEXT: ret i32 addrspace(2)* inttoptr (i32 ptrtoint (i32 addrspace(3)* @const_zero_i32_as3 to i32) to i32 addrspace(2)*) 49 %x = ptrtoint i32 addrspace(3)* @const_zero_i32_as3 to i32 50 %y = inttoptr i32 %x to i32 addrspace(2)* 51 ret i32 addrspace(2)* %y 52 } 53 54 ; The intermediate integer size is too small, nothing should happen 55 define i32 addrspace(3)* @test_constant_fold_inttoptr_as_pointer_larger() { 56 ; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_larger( 57 ; CHECK-NEXT: ret i32 addrspace(3)* inttoptr (i8 ptrtoint (i32 addrspace(3)* @const_zero_i32_as3 to i8) to i32 addrspace(3)*) 58 %x = ptrtoint i32 addrspace(3)* @const_zero_i32_as3 to i8 59 %y = inttoptr i8 %x to i32 addrspace(3)* 60 ret i32 addrspace(3)* %y 61 } 62 63 define i8 @const_fold_ptrtoint() { 64 ; CHECK-LABEL: @const_fold_ptrtoint( 65 ; CHECK-NEXT: ret i8 4 66 ret i8 ptrtoint (i32 addrspace(2)* inttoptr (i4 4 to i32 addrspace(2)*) to i8) 67 } 68 69 ; Test that mask happens when the destination pointer is smaller than 70 ; the original 71 define i8 @const_fold_ptrtoint_mask() { 72 ; CHECK-LABEL: @const_fold_ptrtoint_mask( 73 ; CHECK-NEXT: ret i8 1 74 ret i8 ptrtoint (i32 addrspace(3)* inttoptr (i32 257 to i32 addrspace(3)*) to i8) 75 } 76 77 ; Address space 0 is too small for the correct mask, should mask with 78 ; 64-bits instead of 32 79 define i64 @const_fold_ptrtoint_mask_small_as0() { 80 ; CHECK-LABEL: @const_fold_ptrtoint_mask_small_as0( 81 ; CHECK: ret i64 -1 82 ret i64 ptrtoint (i32 addrspace(1)* inttoptr (i128 -1 to i32 addrspace(1)*) to i64) 83 } 84 85 define i32 addrspace(3)* @const_inttoptr() { 86 ; CHECK-LABEL: @const_inttoptr( 87 ; CHECK-NEXT: ret i32 addrspace(3)* inttoptr (i16 4 to i32 addrspace(3)*) 88 %p = inttoptr i16 4 to i32 addrspace(3)* 89 ret i32 addrspace(3)* %p 90 } 91 92 define i16 @const_ptrtoint() { 93 ; CHECK-LABEL: @const_ptrtoint( 94 ; CHECK-NEXT: ret i16 ptrtoint (i32 addrspace(3)* @g to i16) 95 %i = ptrtoint i32 addrspace(3)* @g to i16 96 ret i16 %i 97 } 98 99 define i16 @const_inttoptr_ptrtoint() { 100 ; CHECK-LABEL: @const_inttoptr_ptrtoint( 101 ; CHECK-NEXT: ret i16 9 102 ret i16 ptrtoint (i32 addrspace(3)* inttoptr (i16 9 to i32 addrspace(3)*) to i16) 103 } 104 105 define i1 @constant_fold_cmp_constantexpr_inttoptr() { 106 ; CHECK-LABEL: @constant_fold_cmp_constantexpr_inttoptr( 107 ; CHECK-NEXT: ret i1 true 108 %x = icmp eq i32 addrspace(3)* inttoptr (i16 0 to i32 addrspace(3)*), null 109 ret i1 %x 110 } 111 112 define i1 @constant_fold_inttoptr_null(i16 %i) { 113 ; CHECK-LABEL: @constant_fold_inttoptr_null( 114 ; CHECK-NEXT: ret i1 false 115 %x = icmp eq i32 addrspace(3)* inttoptr (i16 99 to i32 addrspace(3)*), inttoptr (i16 0 to i32 addrspace(3)*) 116 ret i1 %x 117 } 118 119 define i1 @constant_fold_ptrtoint_null() { 120 ; CHECK-LABEL: @constant_fold_ptrtoint_null( 121 ; CHECK-NEXT: ret i1 false 122 %x = icmp eq i16 ptrtoint (i32 addrspace(3)* @g to i16), ptrtoint (i32 addrspace(3)* null to i16) 123 ret i1 %x 124 } 125 126 define i1 @constant_fold_ptrtoint_null_2() { 127 ; CHECK-LABEL: @constant_fold_ptrtoint_null_2( 128 ; CHECK-NEXT: ret i1 false 129 %x = icmp eq i16 ptrtoint (i32 addrspace(3)* null to i16), ptrtoint (i32 addrspace(3)* @g to i16) 130 ret i1 %x 131 } 132 133 define i1 @constant_fold_ptrtoint() { 134 ; CHECK-LABEL: @constant_fold_ptrtoint( 135 ; CHECK-NEXT: ret i1 true 136 %x = icmp eq i16 ptrtoint (i32 addrspace(3)* @g to i16), ptrtoint (i32 addrspace(3)* @g to i16) 137 ret i1 %x 138 } 139 140 define i1 @constant_fold_inttoptr() { 141 ; CHECK-LABEL: @constant_fold_inttoptr( 142 ; CHECK-NEXT: ret i1 false 143 %x = icmp eq i32 addrspace(3)* inttoptr (i16 99 to i32 addrspace(3)*), inttoptr (i16 27 to i32 addrspace(3)*) 144 ret i1 %x 145 } 146 147 @g_float_as3 = addrspace(3) global float zeroinitializer 148 @g_v4f_as3 = addrspace(3) global <4 x float> zeroinitializer 149 150 define float @constant_fold_bitcast_ftoi_load() { 151 ; CHECK-LABEL: @constant_fold_bitcast_ftoi_load( 152 ; CHECK: load float, float addrspace(3)* bitcast (i32 addrspace(3)* @g to float addrspace(3)*), align 4 153 %a = load float, float addrspace(3)* bitcast (i32 addrspace(3)* @g to float addrspace(3)*), align 4 154 ret float %a 155 } 156 157 define i32 @constant_fold_bitcast_itof_load() { 158 ; CHECK-LABEL: @constant_fold_bitcast_itof_load( 159 ; CHECK: load i32, i32 addrspace(3)* bitcast (float addrspace(3)* @g_float_as3 to i32 addrspace(3)*), align 4 160 %a = load i32, i32 addrspace(3)* bitcast (float addrspace(3)* @g_float_as3 to i32 addrspace(3)*), align 4 161 ret i32 %a 162 } 163 164 define <4 x float> @constant_fold_bitcast_vector_as() { 165 ; CHECK-LABEL: @constant_fold_bitcast_vector_as( 166 ; CHECK: load <4 x float>, <4 x float> addrspace(3)* @g_v4f_as3, align 16 167 %a = load <4 x float>, <4 x float> addrspace(3)* bitcast (<4 x i32> addrspace(3)* bitcast (<4 x float> addrspace(3)* @g_v4f_as3 to <4 x i32> addrspace(3)*) to <4 x float> addrspace(3)*), align 4 168 ret <4 x float> %a 169 } 170 171 @i32_array_as3 = addrspace(3) global [10 x i32] zeroinitializer 172 173 define i32 @test_cast_gep_small_indices_as() { 174 ; CHECK-LABEL: @test_cast_gep_small_indices_as( 175 ; CHECK: load i32, i32 addrspace(3)* getelementptr inbounds ([10 x i32], [10 x i32] addrspace(3)* @i32_array_as3, i16 0, i16 0), align 16 176 %p = getelementptr [10 x i32], [10 x i32] addrspace(3)* @i32_array_as3, i7 0, i7 0 177 %x = load i32, i32 addrspace(3)* %p, align 4 178 ret i32 %x 179 } 180 181 %struct.foo = type { float, float, [4 x i32], i32 addrspace(3)* } 182 183 @constant_fold_global_ptr = addrspace(3) global %struct.foo { 184 float 0.0, 185 float 0.0, 186 [4 x i32] zeroinitializer, 187 i32 addrspace(3)* getelementptr ([10 x i32], [10 x i32] addrspace(3)* @i32_array_as3, i64 0, i64 0) 188 } 189 190 define i32 @test_cast_gep_large_indices_as() { 191 ; CHECK-LABEL: @test_cast_gep_large_indices_as( 192 ; CHECK: load i32, i32 addrspace(3)* getelementptr inbounds ([10 x i32], [10 x i32] addrspace(3)* @i32_array_as3, i16 0, i16 0), align 16 193 %p = getelementptr [10 x i32], [10 x i32] addrspace(3)* @i32_array_as3, i64 0, i64 0 194 %x = load i32, i32 addrspace(3)* %p, align 4 195 ret i32 %x 196 } 197 198 define i32 @test_constant_cast_gep_struct_indices_as() { 199 ; CHECK-LABEL: @test_constant_cast_gep_struct_indices_as( 200 ; CHECK: load i32, i32 addrspace(3)* getelementptr inbounds (%struct.foo, %struct.foo addrspace(3)* @constant_fold_global_ptr, i16 0, i32 2, i16 2), align 8 201 %x = getelementptr %struct.foo, %struct.foo addrspace(3)* @constant_fold_global_ptr, i18 0, i32 2, i12 2 202 %y = load i32, i32 addrspace(3)* %x, align 4 203 ret i32 %y 204 } 205 206 @constant_data_as3 = addrspace(3) constant [5 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5] 207 208 define i32 @test_read_data_from_global_as3() { 209 ; CHECK-LABEL: @test_read_data_from_global_as3( 210 ; CHECK-NEXT: ret i32 2 211 %x = getelementptr [5 x i32], [5 x i32] addrspace(3)* @constant_data_as3, i32 0, i32 1 212 %y = load i32, i32 addrspace(3)* %x, align 4 213 ret i32 %y 214 } 215 216 @a = addrspace(1) constant i32 9 217 @b = addrspace(1) constant i32 23 218 @c = addrspace(1) constant i32 34 219 @d = addrspace(1) constant i32 99 220 221 @ptr_array = addrspace(2) constant [4 x i32 addrspace(1)*] [ i32 addrspace(1)* @a, i32 addrspace(1)* @b, i32 addrspace(1)* @c, i32 addrspace(1)* @d] 222 @indirect = addrspace(0) constant i32 addrspace(1)* addrspace(2)* getelementptr inbounds ([4 x i32 addrspace(1)*], [4 x i32 addrspace(1)*] addrspace(2)* @ptr_array, i1 0, i32 2) 223 224 define i32 @constant_through_array_as_ptrs() { 225 ; CHECK-LABEL: @constant_through_array_as_ptrs( 226 ; CHECK-NEXT: ret i32 34 227 %p = load i32 addrspace(1)* addrspace(2)*, i32 addrspace(1)* addrspace(2)* addrspace(0)* @indirect, align 4 228 %a = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(2)* %p, align 4 229 %b = load i32, i32 addrspace(1)* %a, align 4 230 ret i32 %b 231 } 232 233 @shared_mem = external addrspace(3) global [0 x i8] 234 235 define float @canonicalize_addrspacecast(i32 %i) { 236 ; CHECK-LABEL: @canonicalize_addrspacecast 237 ; CHECK-NEXT: getelementptr inbounds float, float* addrspacecast (float addrspace(3)* bitcast ([0 x i8] addrspace(3)* @shared_mem to float addrspace(3)*) to float*), i32 %i 238 %p = getelementptr inbounds float, float* addrspacecast ([0 x i8] addrspace(3)* @shared_mem to float*), i32 %i 239 %v = load float, float* %p 240 ret float %v 241 } 242