1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -sroa -S | FileCheck %s 3; RUN: opt < %s -passes=sroa -S | FileCheck %s 4 5target datalayout = "e-p:64:64:64-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n8:16:32:64" 6 7declare void @llvm.memcpy.p0i8.p1i8.i32(i8* nocapture writeonly, i8 addrspace(1)* nocapture readonly, i32, i1 immarg) #0 8declare void @llvm.memcpy.p1i8.p0i8.i32(i8 addrspace(1)* nocapture writeonly, i8* nocapture readonly, i32, i1 immarg) #0 9 10define i64 @alloca_addrspacecast_bitcast(i64 %X) { 11; CHECK-LABEL: @alloca_addrspacecast_bitcast( 12; CHECK-NEXT: entry: 13; CHECK-NEXT: ret i64 [[X:%.*]] 14; 15entry: 16 %A = alloca [8 x i8] 17 %A.cast = addrspacecast [8 x i8]* %A to [8 x i8] addrspace(1)* 18 %B = bitcast [8 x i8] addrspace(1)* %A.cast to i64 addrspace(1)* 19 store i64 %X, i64 addrspace(1)* %B 20 %Z = load i64, i64 addrspace(1)* %B 21 ret i64 %Z 22} 23 24define i64 @alloca_bitcast_addrspacecast(i64 %X) { 25; CHECK-LABEL: @alloca_bitcast_addrspacecast( 26; CHECK-NEXT: entry: 27; CHECK-NEXT: ret i64 [[X:%.*]] 28; 29entry: 30 %A = alloca [8 x i8] 31 %A.cast = bitcast [8 x i8]* %A to i64* 32 %B = addrspacecast i64* %A.cast to i64 addrspace(1)* 33 store i64 %X, i64 addrspace(1)* %B 34 %Z = load i64, i64 addrspace(1)* %B 35 ret i64 %Z 36} 37 38define i64 @alloca_addrspacecast_gep(i64 %X) { 39; CHECK-LABEL: @alloca_addrspacecast_gep( 40; CHECK-NEXT: entry: 41; CHECK-NEXT: ret i64 [[X:%.*]] 42; 43entry: 44 %A.as0 = alloca [256 x i8], align 4 45 46 %gepA.as0 = getelementptr [256 x i8], [256 x i8]* %A.as0, i16 0, i16 32 47 %gepA.as0.bc = bitcast i8* %gepA.as0 to i64* 48 store i64 %X, i64* %gepA.as0.bc, align 4 49 50 %A.as1 = addrspacecast [256 x i8]* %A.as0 to [256 x i8] addrspace(1)* 51 %gepA.as1 = getelementptr [256 x i8], [256 x i8] addrspace(1)* %A.as1, i16 0, i16 32 52 %gepA.as1.bc = bitcast i8 addrspace(1)* %gepA.as1 to i64 addrspace(1)* 53 %Z = load i64, i64 addrspace(1)* %gepA.as1.bc, align 4 54 55 ret i64 %Z 56} 57 58define i64 @alloca_gep_addrspacecast(i64 %X) { 59; CHECK-LABEL: @alloca_gep_addrspacecast( 60; CHECK-NEXT: entry: 61; CHECK-NEXT: ret i64 [[X:%.*]] 62; 63entry: 64 %A.as0 = alloca [256 x i8], align 4 65 66 %gepA.as0 = getelementptr [256 x i8], [256 x i8]* %A.as0, i16 0, i16 32 67 %gepA.as0.bc = bitcast i8* %gepA.as0 to i64* 68 store i64 %X, i64* %gepA.as0.bc, align 4 69 70 %gepA.as1.bc = addrspacecast i64* %gepA.as0.bc to i64 addrspace(1)* 71 %Z = load i64, i64 addrspace(1)* %gepA.as1.bc, align 4 72 ret i64 %Z 73} 74 75define i64 @alloca_gep_addrspacecast_gep(i64 %X) { 76; CHECK-LABEL: @alloca_gep_addrspacecast_gep( 77; CHECK-NEXT: entry: 78; CHECK-NEXT: ret i64 [[X:%.*]] 79; 80entry: 81 %A.as0 = alloca [256 x i8], align 4 82 83 %gepA.as0 = getelementptr [256 x i8], [256 x i8]* %A.as0, i16 0, i16 32 84 %gepA.as0.bc = bitcast i8* %gepA.as0 to i64* 85 store i64 %X, i64* %gepA.as0.bc, align 4 86 87 88 %gepB.as0 = getelementptr [256 x i8], [256 x i8]* %A.as0, i16 0, i16 16 89 %gepB.as1 = addrspacecast i8* %gepB.as0 to i8 addrspace(1)* 90 %gepC.as1 = getelementptr i8, i8 addrspace(1)* %gepB.as1, i16 16 91 %gepC.as1.bc = bitcast i8 addrspace(1)* %gepC.as1 to i64 addrspace(1)* 92 %Z = load i64, i64 addrspace(1)* %gepC.as1.bc, align 4 93 94 ret i64 %Z 95} 96 97define i64 @getAdjustedPtr_addrspacecast_gep([32 x i8]* %x) { 98; CHECK-LABEL: @getAdjustedPtr_addrspacecast_gep( 99; CHECK-NEXT: entry: 100; CHECK-NEXT: [[CAST1:%.*]] = addrspacecast [32 x i8]* [[X:%.*]] to i8 addrspace(1)* 101; CHECK-NEXT: [[A_SROA_0_0_CAST1_SROA_CAST:%.*]] = bitcast i8 addrspace(1)* [[CAST1]] to i64 addrspace(1)* 102; CHECK-NEXT: [[A_SROA_0_0_COPYLOAD:%.*]] = load i64, i64 addrspace(1)* [[A_SROA_0_0_CAST1_SROA_CAST]], align 1 103; CHECK-NEXT: [[A_SROA_2_0_CAST1_SROA_IDX:%.*]] = getelementptr inbounds i8, i8 addrspace(1)* [[CAST1]], i16 8 104; CHECK-NEXT: [[A_SROA_2_0_CAST1_SROA_CAST:%.*]] = bitcast i8 addrspace(1)* [[A_SROA_2_0_CAST1_SROA_IDX]] to i64 addrspace(1)* 105; CHECK-NEXT: [[A_SROA_2_0_COPYLOAD:%.*]] = load i64, i64 addrspace(1)* [[A_SROA_2_0_CAST1_SROA_CAST]], align 1 106; CHECK-NEXT: ret i64 [[A_SROA_0_0_COPYLOAD]] 107; 108entry: 109 %a = alloca [32 x i8], align 8 110 %cast1 = addrspacecast [32 x i8]* %x to i8 addrspace(1)* 111 %cast2 = bitcast [32 x i8]* %a to i8* 112 call void @llvm.memcpy.p0i8.p1i8.i32(i8* %cast2, i8 addrspace(1)* %cast1, i32 16, i1 false) 113 %gep = getelementptr [32 x i8], [32 x i8]* %a, i32 0 114 %gep.bitcast = bitcast [32 x i8]* %gep to i64* 115 %val = load i64, i64* %gep.bitcast 116 ret i64 %val 117} 118 119define i64 @getAdjustedPtr_gep_addrspacecast([32 x i8]* %x) { 120; CHECK-LABEL: @getAdjustedPtr_gep_addrspacecast( 121; CHECK-NEXT: entry: 122; CHECK-NEXT: [[GEP_X:%.*]] = getelementptr [32 x i8], [32 x i8]* [[X:%.*]], i32 0, i32 16 123; CHECK-NEXT: [[CAST1:%.*]] = addrspacecast i8* [[GEP_X]] to i8 addrspace(1)* 124; CHECK-NEXT: [[A_SROA_0_0_CAST1_SROA_CAST:%.*]] = bitcast i8 addrspace(1)* [[CAST1]] to i64 addrspace(1)* 125; CHECK-NEXT: [[A_SROA_0_0_COPYLOAD:%.*]] = load i64, i64 addrspace(1)* [[A_SROA_0_0_CAST1_SROA_CAST]], align 1 126; CHECK-NEXT: [[A_SROA_2_0_CAST1_SROA_IDX:%.*]] = getelementptr inbounds i8, i8 addrspace(1)* [[CAST1]], i16 8 127; CHECK-NEXT: [[A_SROA_2_0_CAST1_SROA_CAST:%.*]] = bitcast i8 addrspace(1)* [[A_SROA_2_0_CAST1_SROA_IDX]] to i64 addrspace(1)* 128; CHECK-NEXT: [[A_SROA_2_0_COPYLOAD:%.*]] = load i64, i64 addrspace(1)* [[A_SROA_2_0_CAST1_SROA_CAST]], align 1 129; CHECK-NEXT: ret i64 [[A_SROA_0_0_COPYLOAD]] 130; 131entry: 132 %a = alloca [32 x i8], align 8 133 %gep.x = getelementptr [32 x i8], [32 x i8]* %x, i32 0, i32 16 134 %cast1 = addrspacecast i8* %gep.x to i8 addrspace(1)* 135 136 %cast2 = bitcast [32 x i8]* %a to i8* 137 call void @llvm.memcpy.p0i8.p1i8.i32(i8* %cast2, i8 addrspace(1)* %cast1, i32 16, i1 false) 138 %gep = getelementptr [32 x i8], [32 x i8]* %a, i32 0 139 %gep.bitcast = bitcast [32 x i8]* %gep to i64* 140 %val = load i64, i64* %gep.bitcast 141 ret i64 %val 142} 143 144define i64 @getAdjustedPtr_gep_addrspacecast_gep([32 x i8]* %x) { 145; CHECK-LABEL: @getAdjustedPtr_gep_addrspacecast_gep( 146; CHECK-NEXT: entry: 147; CHECK-NEXT: [[GEP0_X:%.*]] = getelementptr [32 x i8], [32 x i8]* [[X:%.*]], i32 0, i32 8 148; CHECK-NEXT: [[CAST1:%.*]] = addrspacecast i8* [[GEP0_X]] to i8 addrspace(1)* 149; CHECK-NEXT: [[A_SROA_0_0_GEP1_X_SROA_IDX:%.*]] = getelementptr inbounds i8, i8 addrspace(1)* [[CAST1]], i16 8 150; CHECK-NEXT: [[A_SROA_0_0_GEP1_X_SROA_CAST:%.*]] = bitcast i8 addrspace(1)* [[A_SROA_0_0_GEP1_X_SROA_IDX]] to i64 addrspace(1)* 151; CHECK-NEXT: [[A_SROA_0_0_COPYLOAD:%.*]] = load i64, i64 addrspace(1)* [[A_SROA_0_0_GEP1_X_SROA_CAST]], align 1 152; CHECK-NEXT: [[A_SROA_2_0_GEP1_X_SROA_IDX:%.*]] = getelementptr inbounds i8, i8 addrspace(1)* [[CAST1]], i16 16 153; CHECK-NEXT: [[A_SROA_2_0_GEP1_X_SROA_CAST:%.*]] = bitcast i8 addrspace(1)* [[A_SROA_2_0_GEP1_X_SROA_IDX]] to i64 addrspace(1)* 154; CHECK-NEXT: [[A_SROA_2_0_COPYLOAD:%.*]] = load i64, i64 addrspace(1)* [[A_SROA_2_0_GEP1_X_SROA_CAST]], align 1 155; CHECK-NEXT: ret i64 [[A_SROA_0_0_COPYLOAD]] 156; 157entry: 158 %a = alloca [32 x i8], align 8 159 %gep0.x = getelementptr [32 x i8], [32 x i8]* %x, i32 0, i32 8 160 %cast1 = addrspacecast i8* %gep0.x to i8 addrspace(1)* 161 %gep1.x = getelementptr i8, i8 addrspace(1)* %cast1, i32 8 162 163 %cast2 = bitcast [32 x i8]* %a to i8* 164 call void @llvm.memcpy.p0i8.p1i8.i32(i8* %cast2, i8 addrspace(1)* %gep1.x, i32 16, i1 false) 165 %gep = getelementptr [32 x i8], [32 x i8]* %a, i32 0 166 %gep.bitcast = bitcast [32 x i8]* %gep to i64* 167 %val = load i64, i64* %gep.bitcast 168 ret i64 %val 169} 170 171; Don't change the address space of a volatile operation 172define i64 @alloca_addrspacecast_bitcast_volatile_store(i64 %X) { 173; CHECK-LABEL: @alloca_addrspacecast_bitcast_volatile_store( 174; CHECK-NEXT: entry: 175; CHECK-NEXT: [[A:%.*]] = alloca [8 x i8] 176; CHECK-NEXT: [[A_CAST:%.*]] = addrspacecast [8 x i8]* [[A]] to [8 x i8] addrspace(1)* 177; CHECK-NEXT: [[B:%.*]] = bitcast [8 x i8] addrspace(1)* [[A_CAST]] to i64 addrspace(1)* 178; CHECK-NEXT: store volatile i64 [[X:%.*]], i64 addrspace(1)* [[B]] 179; CHECK-NEXT: [[Z:%.*]] = load i64, i64 addrspace(1)* [[B]] 180; CHECK-NEXT: ret i64 [[Z]] 181; 182entry: 183 %A = alloca [8 x i8] 184 %A.cast = addrspacecast [8 x i8]* %A to [8 x i8] addrspace(1)* 185 %B = bitcast [8 x i8] addrspace(1)* %A.cast to i64 addrspace(1)* 186 store volatile i64 %X, i64 addrspace(1)* %B 187 %Z = load i64, i64 addrspace(1)* %B 188 ret i64 %Z 189} 190 191; Don't change the address space of a volatile operation 192define i64 @alloca_addrspacecast_bitcast_volatile_load(i64 %X) { 193; CHECK-LABEL: @alloca_addrspacecast_bitcast_volatile_load( 194; CHECK-NEXT: entry: 195; CHECK-NEXT: [[A:%.*]] = alloca [8 x i8] 196; CHECK-NEXT: [[A_CAST:%.*]] = addrspacecast [8 x i8]* [[A]] to [8 x i8] addrspace(1)* 197; CHECK-NEXT: [[B:%.*]] = bitcast [8 x i8] addrspace(1)* [[A_CAST]] to i64 addrspace(1)* 198; CHECK-NEXT: store i64 [[X:%.*]], i64 addrspace(1)* [[B]] 199; CHECK-NEXT: [[Z:%.*]] = load volatile i64, i64 addrspace(1)* [[B]] 200; CHECK-NEXT: ret i64 [[Z]] 201; 202entry: 203 %A = alloca [8 x i8] 204 %A.cast = addrspacecast [8 x i8]* %A to [8 x i8] addrspace(1)* 205 %B = bitcast [8 x i8] addrspace(1)* %A.cast to i64 addrspace(1)* 206 store i64 %X, i64 addrspace(1)* %B 207 %Z = load volatile i64, i64 addrspace(1)* %B 208 ret i64 %Z 209} 210 211declare void @llvm.memset.p1i8.i32(i8 addrspace(1)* nocapture, i8, i32, i1) nounwind 212 213; Don't change the address space of a volatile operation 214define i32 @volatile_memset() { 215; CHECK-LABEL: @volatile_memset( 216; CHECK-NEXT: entry: 217; CHECK-NEXT: [[A:%.*]] = alloca [4 x i8] 218; CHECK-NEXT: [[PTR:%.*]] = getelementptr [4 x i8], [4 x i8]* [[A]], i32 0, i32 0 219; CHECK-NEXT: [[ASC:%.*]] = addrspacecast i8* [[PTR]] to i8 addrspace(1)* 220; CHECK-NEXT: call void @llvm.memset.p1i8.i32(i8 addrspace(1)* [[ASC]], i8 42, i32 4, i1 true) 221; CHECK-NEXT: [[IPTR:%.*]] = bitcast i8* [[PTR]] to i32* 222; CHECK-NEXT: [[VAL:%.*]] = load i32, i32* [[IPTR]] 223; CHECK-NEXT: ret i32 [[VAL]] 224; 225entry: 226 %a = alloca [4 x i8] 227 %ptr = getelementptr [4 x i8], [4 x i8]* %a, i32 0, i32 0 228 %asc = addrspacecast i8* %ptr to i8 addrspace(1)* 229 call void @llvm.memset.p1i8.i32(i8 addrspace(1)* %asc, i8 42, i32 4, i1 true) 230 %iptr = bitcast i8* %ptr to i32* 231 %val = load i32, i32* %iptr 232 ret i32 %val 233} 234 235; Don't change the address space of a volatile operation 236define void @volatile_memcpy(i8* %src, i8* %dst) { 237; CHECK-LABEL: @volatile_memcpy( 238; CHECK-NEXT: entry: 239; CHECK-NEXT: [[A:%.*]] = alloca [4 x i8] 240; CHECK-NEXT: [[PTR:%.*]] = getelementptr [4 x i8], [4 x i8]* [[A]], i32 0, i32 0 241; CHECK-NEXT: [[ASC:%.*]] = addrspacecast i8* [[PTR]] to i8 addrspace(1)* 242; CHECK-NEXT: call void @llvm.memcpy.p1i8.p0i8.i32(i8 addrspace(1)* [[ASC]], i8* [[SRC:%.*]], i32 4, i1 true), !tbaa !0 243; CHECK-NEXT: call void @llvm.memcpy.p0i8.p1i8.i32(i8* [[DST:%.*]], i8 addrspace(1)* [[ASC]], i32 4, i1 true), !tbaa !3 244; CHECK-NEXT: ret void 245; 246entry: 247 %a = alloca [4 x i8] 248 %ptr = getelementptr [4 x i8], [4 x i8]* %a, i32 0, i32 0 249 %asc = addrspacecast i8* %ptr to i8 addrspace(1)* 250 call void @llvm.memcpy.p1i8.p0i8.i32(i8 addrspace(1)* %asc, i8* %src, i32 4, i1 true), !tbaa !0 251 call void @llvm.memcpy.p0i8.p1i8.i32(i8* %dst, i8 addrspace(1)* %asc, i32 4, i1 true), !tbaa !3 252 ret void 253} 254 255define void @select_addrspacecast(i1 %a, i1 %b) { 256; CHECK-LABEL: @select_addrspacecast( 257; CHECK-NEXT: ret void 258; 259 %c = alloca i64, align 8 260 %p.0.c = select i1 undef, i64* %c, i64* %c 261 %asc = addrspacecast i64* %p.0.c to i64 addrspace(1)* 262 263 %cond.in = select i1 undef, i64 addrspace(1)* %asc, i64 addrspace(1)* %asc 264 %cond = load i64, i64 addrspace(1)* %cond.in, align 8 265 ret void 266} 267 268define void @select_addrspacecast_const_op(i1 %a, i1 %b) { 269; CHECK-LABEL: @select_addrspacecast_const_op( 270; CHECK-NEXT: [[C:%.*]] = alloca i64, align 8 271; CHECK-NEXT: [[C_0_ASC_SROA_CAST:%.*]] = addrspacecast i64* [[C]] to i64 addrspace(1)* 272; CHECK-NEXT: [[COND_IN:%.*]] = select i1 undef, i64 addrspace(1)* [[C_0_ASC_SROA_CAST]], i64 addrspace(1)* null 273; CHECK-NEXT: [[COND:%.*]] = load i64, i64 addrspace(1)* [[COND_IN]], align 8 274; CHECK-NEXT: ret void 275; 276 %c = alloca i64, align 8 277 %p.0.c = select i1 undef, i64* %c, i64* %c 278 %asc = addrspacecast i64* %p.0.c to i64 addrspace(1)* 279 280 %cond.in = select i1 undef, i64 addrspace(1)* %asc, i64 addrspace(1)* null 281 %cond = load i64, i64 addrspace(1)* %cond.in, align 8 282 ret void 283} 284 285;; If this was external, we wouldn't be able to prove dereferenceability 286;; of the location. 287@gv = addrspace(1) global i64 zeroinitializer 288 289define void @select_addrspacecast_gv(i1 %a, i1 %b) { 290; CHECK-LABEL: @select_addrspacecast_gv( 291; CHECK-NEXT: [[COND_SROA_SPECULATE_LOAD_FALSE:%.*]] = load i64, i64 addrspace(1)* @gv, align 8 292; CHECK-NEXT: [[COND_SROA_SPECULATED:%.*]] = select i1 undef, i64 undef, i64 [[COND_SROA_SPECULATE_LOAD_FALSE]] 293; CHECK-NEXT: ret void 294; 295 %c = alloca i64, align 8 296 %p.0.c = select i1 undef, i64* %c, i64* %c 297 %asc = addrspacecast i64* %p.0.c to i64 addrspace(1)* 298 299 %cond.in = select i1 undef, i64 addrspace(1)* %asc, i64 addrspace(1)* @gv 300 %cond = load i64, i64 addrspace(1)* %cond.in, align 8 301 ret void 302} 303 304define i8 @select_addrspacecast_i8() { 305; CHECK-LABEL: @select_addrspacecast_i8( 306; CHECK-NEXT: [[RET_SROA_SPECULATED:%.*]] = select i1 undef, i8 undef, i8 undef 307; CHECK-NEXT: ret i8 [[RET_SROA_SPECULATED]] 308; 309 %a = alloca i8 310 %b = alloca i8 311 312 %a.ptr = addrspacecast i8* %a to i8 addrspace(1)* 313 %b.ptr = addrspacecast i8* %b to i8 addrspace(1)* 314 315 %ptr = select i1 undef, i8 addrspace(1)* %a.ptr, i8 addrspace(1)* %b.ptr 316 %ret = load i8, i8 addrspace(1)* %ptr 317 ret i8 %ret 318} 319 320!0 = !{!1, !1, i64 0, i64 1} 321!1 = !{!2, i64 1, !"type_0"} 322!2 = !{!"root"} 323!3 = !{!4, !4, i64 0, i64 1} 324!4 = !{!2, i64 1, !"type_3"} 325