1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes='sroa<preserve-cfg>' -S | FileCheck %s --check-prefixes=CHECK,CHECK-PRESERVE-CFG 3; RUN: opt < %s -passes='sroa<modify-cfg>' -S | FileCheck %s --check-prefixes=CHECK,CHECK-MODIFY-CFG 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.p0.p1.i32(ptr nocapture writeonly, ptr addrspace(1) nocapture readonly, i32, i1 immarg) #0 8declare void @llvm.memcpy.p1.p0.i32(ptr addrspace(1) nocapture writeonly, ptr 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 ptr %A to ptr addrspace(1) 18 store i64 %X, ptr addrspace(1) %A.cast 19 %Z = load i64, ptr addrspace(1) %A.cast 20 ret i64 %Z 21} 22 23define i64 @alloca_bitcast_addrspacecast(i64 %X) { 24; CHECK-LABEL: @alloca_bitcast_addrspacecast( 25; CHECK-NEXT: entry: 26; CHECK-NEXT: ret i64 [[X:%.*]] 27; 28entry: 29 %A = alloca [8 x i8] 30 %B = addrspacecast ptr %A to ptr addrspace(1) 31 store i64 %X, ptr addrspace(1) %B 32 %Z = load i64, ptr addrspace(1) %B 33 ret i64 %Z 34} 35 36define i64 @alloca_addrspacecast_gep(i64 %X) { 37; CHECK-LABEL: @alloca_addrspacecast_gep( 38; CHECK-NEXT: entry: 39; CHECK-NEXT: ret i64 [[X:%.*]] 40; 41entry: 42 %A.as0 = alloca [256 x i8], align 4 43 44 %gepA.as0 = getelementptr [256 x i8], ptr %A.as0, i16 0, i16 32 45 store i64 %X, ptr %gepA.as0, align 4 46 47 %A.as1 = addrspacecast ptr %A.as0 to ptr addrspace(1) 48 %gepA.as1 = getelementptr [256 x i8], ptr addrspace(1) %A.as1, i16 0, i16 32 49 %Z = load i64, ptr addrspace(1) %gepA.as1, align 4 50 51 ret i64 %Z 52} 53 54define i64 @alloca_gep_addrspacecast(i64 %X) { 55; CHECK-LABEL: @alloca_gep_addrspacecast( 56; CHECK-NEXT: entry: 57; CHECK-NEXT: ret i64 [[X:%.*]] 58; 59entry: 60 %A.as0 = alloca [256 x i8], align 4 61 62 %gepA.as0 = getelementptr [256 x i8], ptr %A.as0, i16 0, i16 32 63 store i64 %X, ptr %gepA.as0, align 4 64 65 %gepA.as1.bc = addrspacecast ptr %gepA.as0 to ptr addrspace(1) 66 %Z = load i64, ptr addrspace(1) %gepA.as1.bc, align 4 67 ret i64 %Z 68} 69 70define i64 @alloca_gep_addrspacecast_gep(i64 %X) { 71; CHECK-LABEL: @alloca_gep_addrspacecast_gep( 72; CHECK-NEXT: entry: 73; CHECK-NEXT: ret i64 [[X:%.*]] 74; 75entry: 76 %A.as0 = alloca [256 x i8], align 4 77 78 %gepA.as0 = getelementptr [256 x i8], ptr %A.as0, i16 0, i16 32 79 store i64 %X, ptr %gepA.as0, align 4 80 81 82 %gepB.as0 = getelementptr [256 x i8], ptr %A.as0, i16 0, i16 16 83 %gepB.as1 = addrspacecast ptr %gepB.as0 to ptr addrspace(1) 84 %gepC.as1 = getelementptr i8, ptr addrspace(1) %gepB.as1, i16 16 85 %Z = load i64, ptr addrspace(1) %gepC.as1, align 4 86 87 ret i64 %Z 88} 89 90define i64 @getAdjustedPtr_addrspacecast_gep(ptr %x) { 91; CHECK-LABEL: @getAdjustedPtr_addrspacecast_gep( 92; CHECK-NEXT: entry: 93; CHECK-NEXT: [[CAST1:%.*]] = addrspacecast ptr [[X:%.*]] to ptr addrspace(1) 94; CHECK-NEXT: [[A_SROA_0_0_COPYLOAD:%.*]] = load i64, ptr addrspace(1) [[CAST1]], align 1 95; CHECK-NEXT: [[A_SROA_2_0_CAST1_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[CAST1]], i16 8 96; CHECK-NEXT: [[A_SROA_2_0_COPYLOAD:%.*]] = load i64, ptr addrspace(1) [[A_SROA_2_0_CAST1_SROA_IDX]], align 1 97; CHECK-NEXT: ret i64 [[A_SROA_0_0_COPYLOAD]] 98; 99entry: 100 %a = alloca [32 x i8], align 8 101 %cast1 = addrspacecast ptr %x to ptr addrspace(1) 102 call void @llvm.memcpy.p0.p1.i32(ptr %a, ptr addrspace(1) %cast1, i32 16, i1 false) 103 %val = load i64, ptr %a 104 ret i64 %val 105} 106 107define i64 @getAdjustedPtr_gep_addrspacecast(ptr %x) { 108; CHECK-LABEL: @getAdjustedPtr_gep_addrspacecast( 109; CHECK-NEXT: entry: 110; CHECK-NEXT: [[GEP_X:%.*]] = getelementptr [32 x i8], ptr [[X:%.*]], i32 0, i32 16 111; CHECK-NEXT: [[CAST1:%.*]] = addrspacecast ptr [[GEP_X]] to ptr addrspace(1) 112; CHECK-NEXT: [[A_SROA_0_0_COPYLOAD:%.*]] = load i64, ptr addrspace(1) [[CAST1]], align 1 113; CHECK-NEXT: [[A_SROA_2_0_CAST1_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[CAST1]], i16 8 114; CHECK-NEXT: [[A_SROA_2_0_COPYLOAD:%.*]] = load i64, ptr addrspace(1) [[A_SROA_2_0_CAST1_SROA_IDX]], align 1 115; CHECK-NEXT: ret i64 [[A_SROA_0_0_COPYLOAD]] 116; 117entry: 118 %a = alloca [32 x i8], align 8 119 %gep.x = getelementptr [32 x i8], ptr %x, i32 0, i32 16 120 %cast1 = addrspacecast ptr %gep.x to ptr addrspace(1) 121 122 call void @llvm.memcpy.p0.p1.i32(ptr %a, ptr addrspace(1) %cast1, i32 16, i1 false) 123 %val = load i64, ptr %a 124 ret i64 %val 125} 126 127define i64 @getAdjustedPtr_gep_addrspacecast_gep(ptr %x) { 128; CHECK-LABEL: @getAdjustedPtr_gep_addrspacecast_gep( 129; CHECK-NEXT: entry: 130; CHECK-NEXT: [[GEP0_X:%.*]] = getelementptr [32 x i8], ptr [[X:%.*]], i32 0, i32 8 131; CHECK-NEXT: [[CAST1:%.*]] = addrspacecast ptr [[GEP0_X]] to ptr addrspace(1) 132; CHECK-NEXT: [[GEP1_X:%.*]] = getelementptr i8, ptr addrspace(1) [[CAST1]], i32 8 133; CHECK-NEXT: [[A_SROA_0_0_COPYLOAD:%.*]] = load i64, ptr addrspace(1) [[GEP1_X]], align 1 134; CHECK-NEXT: [[A_SROA_2_0_GEP1_X_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[GEP1_X]], i16 8 135; CHECK-NEXT: [[A_SROA_2_0_COPYLOAD:%.*]] = load i64, ptr addrspace(1) [[A_SROA_2_0_GEP1_X_SROA_IDX]], align 1 136; CHECK-NEXT: ret i64 [[A_SROA_0_0_COPYLOAD]] 137; 138entry: 139 %a = alloca [32 x i8], align 8 140 %gep0.x = getelementptr [32 x i8], ptr %x, i32 0, i32 8 141 %cast1 = addrspacecast ptr %gep0.x to ptr addrspace(1) 142 %gep1.x = getelementptr i8, ptr addrspace(1) %cast1, i32 8 143 144 call void @llvm.memcpy.p0.p1.i32(ptr %a, ptr addrspace(1) %gep1.x, i32 16, i1 false) 145 %val = load i64, ptr %a 146 ret i64 %val 147} 148 149; Don't change the address space of a volatile operation 150define i64 @alloca_addrspacecast_bitcast_volatile_store(i64 %X) { 151; CHECK-LABEL: @alloca_addrspacecast_bitcast_volatile_store( 152; CHECK-NEXT: entry: 153; CHECK-NEXT: [[A_SROA_0:%.*]] = alloca i64, align 8 154; CHECK-NEXT: [[TMP0:%.*]] = addrspacecast ptr [[A_SROA_0]] to ptr addrspace(1) 155; CHECK-NEXT: store volatile i64 [[X:%.*]], ptr addrspace(1) [[TMP0]], align 8 156; CHECK-NEXT: [[A_SROA_0_0_A_SROA_0_0_Z:%.*]] = load i64, ptr [[A_SROA_0]], align 8 157; CHECK-NEXT: ret i64 [[A_SROA_0_0_A_SROA_0_0_Z]] 158; 159entry: 160 %A = alloca [8 x i8] 161 %A.cast = addrspacecast ptr %A to ptr addrspace(1) 162 store volatile i64 %X, ptr addrspace(1) %A.cast 163 %Z = load i64, ptr addrspace(1) %A.cast 164 ret i64 %Z 165} 166 167%struct = type { [256 x i8], i32 } 168 169define i65 @volatile_store_addrspacecast_slice(i65 %X, i16 %idx) { 170; CHECK-LABEL: @volatile_store_addrspacecast_slice( 171; CHECK-NEXT: entry: 172; CHECK-NEXT: [[A_SROA_0:%.*]] = alloca [9 x i8], align 4 173; CHECK-NEXT: [[A_SROA_1:%.*]] = alloca [9 x i8], align 8 174; CHECK-NEXT: [[A_SROA_1_0_GEPB_SROA_CAST:%.*]] = addrspacecast ptr [[A_SROA_1]] to ptr addrspace(1) 175; CHECK-NEXT: store volatile i65 [[X:%.*]], ptr addrspace(1) [[A_SROA_1_0_GEPB_SROA_CAST]], align 8 176; CHECK-NEXT: br label [[L2:%.*]] 177; CHECK: L2: 178; CHECK-NEXT: [[A_SROA_0_0_A_SROA_0_20_Z:%.*]] = load i65, ptr [[A_SROA_0]], align 4 179; CHECK-NEXT: ret i65 [[A_SROA_0_0_A_SROA_0_20_Z]] 180; 181entry: 182 %A = alloca %struct 183 %B = addrspacecast ptr %A to ptr addrspace(1) 184 %gepA = getelementptr %struct, ptr %A, i32 0, i32 0, i16 20 185 %gepB = getelementptr i65, ptr addrspace(1) %B, i16 6 186 store volatile i65 %X, ptr addrspace(1) %gepB, align 1 187 br label %L2 188 189L2: 190 %Z = load i65, ptr %gepA, align 1 191 ret i65 %Z 192} 193 194; Don't change the address space of a volatile operation 195define i64 @alloca_addrspacecast_bitcast_volatile_load(i64 %X) { 196; CHECK-LABEL: @alloca_addrspacecast_bitcast_volatile_load( 197; CHECK-NEXT: entry: 198; CHECK-NEXT: [[A_SROA_0:%.*]] = alloca i64, align 8 199; CHECK-NEXT: store i64 [[X:%.*]], ptr [[A_SROA_0]], align 8 200; CHECK-NEXT: [[TMP0:%.*]] = addrspacecast ptr [[A_SROA_0]] to ptr addrspace(1) 201; CHECK-NEXT: [[A_SROA_0_0_A_SROA_0_0_Z:%.*]] = load volatile i64, ptr addrspace(1) [[TMP0]], align 8 202; CHECK-NEXT: ret i64 [[A_SROA_0_0_A_SROA_0_0_Z]] 203; 204entry: 205 %A = alloca [8 x i8] 206 %A.cast = addrspacecast ptr %A to ptr addrspace(1) 207 store i64 %X, ptr addrspace(1) %A.cast 208 %Z = load volatile i64, ptr addrspace(1) %A.cast 209 ret i64 %Z 210} 211 212declare void @llvm.memset.p1.i32(ptr addrspace(1) nocapture, i8, i32, i1) nounwind 213 214define i65 @volatile_load_addrspacecast_slice(i65 %X, i16 %idx) { 215; CHECK-LABEL: @volatile_load_addrspacecast_slice( 216; CHECK-NEXT: entry: 217; CHECK-NEXT: [[A_SROA_0:%.*]] = alloca [9 x i8], align 4 218; CHECK-NEXT: [[A_SROA_1:%.*]] = alloca [9 x i8], align 8 219; CHECK-NEXT: [[A_SROA_1_0_GEPB_SROA_CAST:%.*]] = addrspacecast ptr [[A_SROA_1]] to ptr addrspace(1) 220; CHECK-NEXT: store i65 [[X:%.*]], ptr addrspace(1) [[A_SROA_1_0_GEPB_SROA_CAST]], align 8 221; CHECK-NEXT: br label [[L2:%.*]] 222; CHECK: L2: 223; CHECK-NEXT: [[A_SROA_0_0_A_SROA_0_20_Z:%.*]] = load volatile i65, ptr [[A_SROA_0]], align 4 224; CHECK-NEXT: ret i65 [[A_SROA_0_0_A_SROA_0_20_Z]] 225; 226entry: 227 %A = alloca %struct 228 %B = addrspacecast ptr %A to ptr addrspace(1) 229 %gepA = getelementptr %struct, ptr %A, i32 0, i32 0, i16 20 230 %gepB = getelementptr i65, ptr addrspace(1) %B, i16 6 231 store i65 %X, ptr addrspace(1) %gepB, align 1 232 br label %L2 233 234L2: 235 %Z = load volatile i65, ptr %gepA, align 1 236 ret i65 %Z 237} 238 239; Don't change the address space of a volatile operation 240define i32 @volatile_memset() { 241; CHECK-LABEL: @volatile_memset( 242; CHECK-NEXT: entry: 243; CHECK-NEXT: [[A_SROA_0:%.*]] = alloca i32, align 4 244; CHECK-NEXT: [[TMP0:%.*]] = addrspacecast ptr [[A_SROA_0]] to ptr addrspace(1) 245; CHECK-NEXT: store volatile i32 707406378, ptr addrspace(1) [[TMP0]], align 4 246; CHECK-NEXT: [[A_SROA_0_0_A_SROA_0_0_VAL:%.*]] = load i32, ptr [[A_SROA_0]], align 4 247; CHECK-NEXT: ret i32 [[A_SROA_0_0_A_SROA_0_0_VAL]] 248; 249entry: 250 %a = alloca [4 x i8] 251 %asc = addrspacecast ptr %a to ptr addrspace(1) 252 call void @llvm.memset.p1.i32(ptr addrspace(1) %asc, i8 42, i32 4, i1 true) 253 %val = load i32, ptr %a 254 ret i32 %val 255} 256 257; Don't change the address space of a volatile operation 258define void @volatile_memcpy(ptr %src, ptr %dst) { 259; CHECK-LABEL: @volatile_memcpy( 260; CHECK-NEXT: entry: 261; CHECK-NEXT: [[A_SROA_0:%.*]] = alloca i32, align 4 262; CHECK-NEXT: [[A_SROA_0_0_COPYLOAD:%.*]] = load volatile i32, ptr [[SRC:%.*]], align 1, !tbaa [[TBAA0:![0-9]+]] 263; CHECK-NEXT: [[TMP0:%.*]] = addrspacecast ptr [[A_SROA_0]] to ptr addrspace(1) 264; CHECK-NEXT: store volatile i32 [[A_SROA_0_0_COPYLOAD]], ptr addrspace(1) [[TMP0]], align 4, !tbaa [[TBAA0]] 265; CHECK-NEXT: [[TMP1:%.*]] = addrspacecast ptr [[A_SROA_0]] to ptr addrspace(1) 266; CHECK-NEXT: [[A_SROA_0_0_A_SROA_0_0_COPYLOAD1:%.*]] = load volatile i32, ptr addrspace(1) [[TMP1]], align 4, !tbaa [[TBAA3:![0-9]+]] 267; CHECK-NEXT: store volatile i32 [[A_SROA_0_0_A_SROA_0_0_COPYLOAD1]], ptr [[DST:%.*]], align 1, !tbaa [[TBAA3]] 268; CHECK-NEXT: ret void 269; 270entry: 271 %a = alloca [4 x i8] 272 %asc = addrspacecast ptr %a to ptr addrspace(1) 273 call void @llvm.memcpy.p1.p0.i32(ptr addrspace(1) %asc, ptr %src, i32 4, i1 true), !tbaa !0 274 call void @llvm.memcpy.p0.p1.i32(ptr %dst, ptr addrspace(1) %asc, i32 4, i1 true), !tbaa !3 275 ret void 276} 277 278define void @select_addrspacecast(i1 %a, i1 %b) { 279; CHECK-LABEL: @select_addrspacecast( 280; CHECK-NEXT: ret void 281; 282 %c = alloca i64, align 8 283 %p.0.c = select i1 %a, ptr %c, ptr %c 284 %asc = addrspacecast ptr %p.0.c to ptr addrspace(1) 285 286 %cond.in = select i1 %b, ptr addrspace(1) %asc, ptr addrspace(1) %asc 287 %cond = load i64, ptr addrspace(1) %cond.in, align 8 288 ret void 289} 290 291define void @select_addrspacecast_const_op(i1 %a, i1 %b) { 292; CHECK-PRESERVE-CFG-LABEL: @select_addrspacecast_const_op( 293; CHECK-PRESERVE-CFG-NEXT: [[C:%.*]] = alloca i64, align 8 294; CHECK-PRESERVE-CFG-NEXT: [[C_0_ASC_SROA_CAST:%.*]] = addrspacecast ptr [[C]] to ptr addrspace(1) 295; CHECK-PRESERVE-CFG-NEXT: [[COND_IN:%.*]] = select i1 [[B:%.*]], ptr addrspace(1) [[C_0_ASC_SROA_CAST]], ptr addrspace(1) null 296; CHECK-PRESERVE-CFG-NEXT: [[COND:%.*]] = load i64, ptr addrspace(1) [[COND_IN]], align 8 297; CHECK-PRESERVE-CFG-NEXT: ret void 298; 299; CHECK-MODIFY-CFG-LABEL: @select_addrspacecast_const_op( 300; CHECK-MODIFY-CFG-NEXT: br i1 [[B:%.*]], label [[DOTCONT:%.*]], label [[DOTELSE:%.*]] 301; CHECK-MODIFY-CFG: .else: 302; CHECK-MODIFY-CFG-NEXT: [[COND_ELSE_VAL:%.*]] = load i64, ptr addrspace(1) null, align 8 303; CHECK-MODIFY-CFG-NEXT: br label [[DOTCONT]] 304; CHECK-MODIFY-CFG: .cont: 305; CHECK-MODIFY-CFG-NEXT: [[COND:%.*]] = phi i64 [ undef, [[TMP0:%.*]] ], [ [[COND_ELSE_VAL]], [[DOTELSE]] ] 306; CHECK-MODIFY-CFG-NEXT: ret void 307; 308 %c = alloca i64, align 8 309 %p.0.c = select i1 %a, ptr %c, ptr %c 310 %asc = addrspacecast ptr %p.0.c to ptr addrspace(1) 311 312 %cond.in = select i1 %b, ptr addrspace(1) %asc, ptr addrspace(1) null 313 %cond = load i64, ptr addrspace(1) %cond.in, align 8 314 ret void 315} 316 317;; If this was external, we wouldn't be able to prove dereferenceability 318;; of the location. 319@gv = addrspace(1) global i64 zeroinitializer 320 321define void @select_addrspacecast_gv(i1 %a, i1 %b) { 322; CHECK-LABEL: @select_addrspacecast_gv( 323; CHECK-NEXT: [[COND_SROA_SPECULATE_LOAD_FALSE:%.*]] = load i64, ptr addrspace(1) @gv, align 8 324; CHECK-NEXT: [[COND_SROA_SPECULATED:%.*]] = select i1 [[B:%.*]], i64 undef, i64 [[COND_SROA_SPECULATE_LOAD_FALSE]] 325; CHECK-NEXT: ret void 326; 327 %c = alloca i64, align 8 328 %p.0.c = select i1 %a, ptr %c, ptr %c 329 %asc = addrspacecast ptr %p.0.c to ptr addrspace(1) 330 331 %cond.in = select i1 %b, ptr addrspace(1) %asc, ptr addrspace(1) @gv 332 %cond = load i64, ptr addrspace(1) %cond.in, align 8 333 ret void 334} 335 336define void @select_addrspacecast_gv_constexpr(i1 %a, i1 %b) { 337; CHECK-LABEL: @select_addrspacecast_gv_constexpr( 338; CHECK-NEXT: [[COND_SROA_SPECULATE_LOAD_FALSE:%.*]] = load i64, ptr addrspace(2) addrspacecast (ptr addrspace(1) @gv to ptr addrspace(2)), align 8 339; CHECK-NEXT: [[COND_SROA_SPECULATED:%.*]] = select i1 [[B:%.*]], i64 undef, i64 [[COND_SROA_SPECULATE_LOAD_FALSE]] 340; CHECK-NEXT: ret void 341; 342 %c = alloca i64, align 8 343 %p.0.c = select i1 %a, ptr %c, ptr %c 344 %asc = addrspacecast ptr %p.0.c to ptr addrspace(2) 345 346 %cond.in = select i1 %b, ptr addrspace(2) %asc, ptr addrspace(2) addrspacecast (ptr addrspace(1) @gv to ptr addrspace(2)) 347 %cond = load i64, ptr addrspace(2) %cond.in, align 8 348 ret void 349} 350 351define i8 @select_addrspacecast_i8(i1 %c) { 352; CHECK-LABEL: @select_addrspacecast_i8( 353; CHECK-NEXT: [[RET_SROA_SPECULATED:%.*]] = select i1 [[C:%.*]], i8 undef, i8 undef 354; CHECK-NEXT: ret i8 [[RET_SROA_SPECULATED]] 355; 356 %a = alloca i8 357 %b = alloca i8 358 359 %a.ptr = addrspacecast ptr %a to ptr addrspace(1) 360 %b.ptr = addrspacecast ptr %b to ptr addrspace(1) 361 362 %ptr = select i1 %c, ptr addrspace(1) %a.ptr, ptr addrspace(1) %b.ptr 363 %ret = load i8, ptr addrspace(1) %ptr 364 ret i8 %ret 365} 366 367!0 = !{!1, !1, i64 0, i64 1} 368!1 = !{!2, i64 1, !"type_0"} 369!2 = !{!"root"} 370!3 = !{!4, !4, i64 0, i64 1} 371!4 = !{!2, i64 1, !"type_3"} 372