1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=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 ptr 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 ptr addrspace(3) @const_zero_i32_as3 21; 22 %x = ptrtoint ptr addrspace(3) @const_zero_i32_as3 to i32 23 %y = inttoptr i32 %x to ptr addrspace(3) 24 ret ptr addrspace(3) %y 25} 26 27; The intermediate integer size is larger than the pointer size 28define ptr addrspace(2) @test_constant_fold_inttoptr_as_pointer_smaller() { 29; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_smaller( 30; CHECK-NEXT: ret ptr addrspace(2) @const_zero_i32_as2 31; 32 %x = ptrtoint ptr addrspace(2) @const_zero_i32_as2 to i16 33 %y = inttoptr i16 %x to ptr addrspace(2) 34 ret ptr addrspace(2) %y 35} 36 37; Different address spaces that are the same size, but they are 38; different so nothing should happen 39define ptr 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 ptr addrspace(4) inttoptr (i16 ptrtoint (ptr addrspace(3) @const_zero_i32_as3 to i16) to ptr addrspace(4)) 42; 43 %x = ptrtoint ptr addrspace(3) @const_zero_i32_as3 to i16 44 %y = inttoptr i16 %x to ptr addrspace(4) 45 ret ptr addrspace(4) %y 46} 47 48; Make sure we don't introduce a bitcast between different sized 49; address spaces when folding this 50define ptr 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 ptr addrspace(2) inttoptr (i32 ptrtoint (ptr addrspace(3) @const_zero_i32_as3 to i32) to ptr addrspace(2)) 53; 54 %x = ptrtoint ptr addrspace(3) @const_zero_i32_as3 to i32 55 %y = inttoptr i32 %x to ptr addrspace(2) 56 ret ptr addrspace(2) %y 57} 58 59; The intermediate integer size is too small, nothing should happen 60define ptr addrspace(3) @test_constant_fold_inttoptr_as_pointer_larger() { 61; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_larger( 62; CHECK-NEXT: ret ptr addrspace(3) inttoptr (i8 ptrtoint (ptr addrspace(3) @const_zero_i32_as3 to i8) to ptr addrspace(3)) 63; 64 %x = ptrtoint ptr addrspace(3) @const_zero_i32_as3 to i8 65 %y = inttoptr i8 %x to ptr addrspace(3) 66 ret ptr 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 (ptr addrspace(2) inttoptr (i4 4 to ptr 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 (ptr addrspace(3) inttoptr (i32 257 to ptr 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 (ptr addrspace(1) inttoptr (i128 -1 to ptr addrspace(1)) to i64) 92} 93 94define ptr addrspace(3) @const_inttoptr() { 95; CHECK-LABEL: @const_inttoptr( 96; CHECK-NEXT: ret ptr addrspace(3) inttoptr (i16 4 to ptr addrspace(3)) 97; 98 %p = inttoptr i16 4 to ptr addrspace(3) 99 ret ptr addrspace(3) %p 100} 101 102define i16 @const_ptrtoint() { 103; CHECK-LABEL: @const_ptrtoint( 104; CHECK-NEXT: ret i16 ptrtoint (ptr addrspace(3) @g to i16) 105; 106 %i = ptrtoint ptr 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 (ptr addrspace(3) inttoptr (i16 9 to ptr 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 ptr addrspace(3) inttoptr (i16 0 to ptr 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 ptr addrspace(3) inttoptr (i16 99 to ptr addrspace(3)), inttoptr (i16 0 to ptr addrspace(3)) 130 ret i1 %x 131} 132 133define i1 @constant_fold_ptrtoint_null() { 134; CHECK-LABEL: @constant_fold_ptrtoint_null( 135; CHECK-NEXT: [[X:%.*]] = icmp eq i16 ptrtoint (ptr addrspace(3) @g to i16), 0 136; CHECK-NEXT: ret i1 [[X]] 137; 138 %x = icmp eq i16 ptrtoint (ptr addrspace(3) @g to i16), ptrtoint (ptr addrspace(3) null to i16) 139 ret i1 %x 140} 141 142define i1 @constant_fold_ptrtoint_null_2() { 143; CHECK-LABEL: @constant_fold_ptrtoint_null_2( 144; CHECK-NEXT: [[X:%.*]] = icmp eq i16 0, ptrtoint (ptr addrspace(3) @g to i16) 145; CHECK-NEXT: ret i1 [[X]] 146; 147 %x = icmp eq i16 ptrtoint (ptr addrspace(3) null to i16), ptrtoint (ptr addrspace(3) @g to i16) 148 ret i1 %x 149} 150 151define i1 @constant_fold_ptrtoint() { 152; CHECK-LABEL: @constant_fold_ptrtoint( 153; CHECK-NEXT: ret i1 true 154; 155 %x = icmp eq i16 ptrtoint (ptr addrspace(3) @g to i16), ptrtoint (ptr addrspace(3) @g to i16) 156 ret i1 %x 157} 158 159define i1 @constant_fold_inttoptr() { 160; CHECK-LABEL: @constant_fold_inttoptr( 161; CHECK-NEXT: ret i1 false 162; 163 %x = icmp eq ptr addrspace(3) inttoptr (i16 99 to ptr addrspace(3)), inttoptr (i16 27 to ptr addrspace(3)) 164 ret i1 %x 165} 166 167@g_float_as3 = addrspace(3) global float zeroinitializer 168@g_v4f_as3 = addrspace(3) global <4 x float> zeroinitializer 169 170define float @constant_fold_bitcast_ftoi_load() { 171; CHECK-LABEL: @constant_fold_bitcast_ftoi_load( 172; CHECK-NEXT: [[A:%.*]] = load float, ptr addrspace(3) @g, align 4 173; CHECK-NEXT: ret float [[A]] 174; 175 %a = load float, ptr addrspace(3) @g, align 4 176 ret float %a 177} 178 179define i32 @constant_fold_bitcast_itof_load() { 180; CHECK-LABEL: @constant_fold_bitcast_itof_load( 181; CHECK-NEXT: [[A:%.*]] = load i32, ptr addrspace(3) @g_float_as3, align 4 182; CHECK-NEXT: ret i32 [[A]] 183; 184 %a = load i32, ptr addrspace(3) @g_float_as3, align 4 185 ret i32 %a 186} 187 188define <4 x float> @constant_fold_bitcast_vector_as() { 189; CHECK-LABEL: @constant_fold_bitcast_vector_as( 190; CHECK-NEXT: [[A:%.*]] = load <4 x float>, ptr addrspace(3) @g_v4f_as3, align 4 191; CHECK-NEXT: ret <4 x float> [[A]] 192; 193 %a = load <4 x float>, ptr addrspace(3) @g_v4f_as3, align 4 194 ret <4 x float> %a 195} 196 197@i32_array_as3 = addrspace(3) global [10 x i32] zeroinitializer 198 199define i32 @test_cast_gep_small_indices_as() { 200; CHECK-LABEL: @test_cast_gep_small_indices_as( 201; CHECK-NEXT: [[X:%.*]] = load i32, ptr addrspace(3) @i32_array_as3, align 4 202; CHECK-NEXT: ret i32 [[X]] 203; 204 %x = load i32, ptr addrspace(3) @i32_array_as3, align 4 205 ret i32 %x 206} 207 208%struct.foo = type { float, float, [4 x i32], ptr addrspace(3) } 209 210@constant_fold_global_ptr = addrspace(3) global %struct.foo { 211 float 0.0, 212 float 0.0, 213 [4 x i32] zeroinitializer, 214 ptr addrspace(3) @i32_array_as3 215} 216 217define i32 @test_cast_gep_large_indices_as() { 218; CHECK-LABEL: @test_cast_gep_large_indices_as( 219; CHECK-NEXT: [[X:%.*]] = load i32, ptr addrspace(3) @i32_array_as3, align 4 220; CHECK-NEXT: ret i32 [[X]] 221; 222 %x = load i32, ptr addrspace(3) @i32_array_as3, 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, ptr addrspace(3) getelementptr inbounds nuw (i8, ptr addrspace(3) @constant_fold_global_ptr, i16 16), align 4 229; CHECK-NEXT: ret i32 [[Y]] 230; 231 %x = getelementptr %struct.foo, ptr addrspace(3) @constant_fold_global_ptr, i18 0, i32 2, i12 2 232 %y = load i32, ptr 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], ptr addrspace(3) @constant_data_as3, i32 0, i32 1 243 %y = load i32, ptr 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 ptr addrspace(1)] [ ptr addrspace(1) @a, ptr addrspace(1) @b, ptr addrspace(1) @c, ptr addrspace(1) @d] 253@indirect = addrspace(0) constant ptr addrspace(2) getelementptr inbounds ([4 x ptr addrspace(1)], ptr 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 ptr addrspace(2), ptr addrspace(0) @indirect, align 4 260 %a = load ptr addrspace(1), ptr addrspace(2) %p, align 4 261 %b = load i32, ptr 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, ptr addrspacecast (ptr addrspace(3) @shared_mem to ptr), i32 [[I:%.*]] 270; CHECK-NEXT: [[V:%.*]] = load float, ptr [[P]], align 4 271; CHECK-NEXT: ret float [[V]] 272; 273 %p = getelementptr inbounds float, ptr addrspacecast (ptr addrspace(3) @shared_mem to ptr), i32 %i 274 %v = load float, ptr %p 275 ret float %v 276} 277