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