557 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes='bounds-checking<merge>' -S | FileCheck %s3target datalayout = "e-p:64:64:64-p1:16:16:16-p2:64:64:64:48-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"4 5@.str = private constant [8 x i8] c"abcdefg\00"6 7@.str_as1 = private addrspace(1) constant [8 x i8] c"abcdefg\00"8 9@.str_as2 = private addrspace(2) constant [8 x i8] c"abcdefg\00"10 11 12declare noalias ptr @malloc(i64) nounwind allocsize(0)13declare noalias ptr @calloc(i64, i64) nounwind allocsize(0,1)14declare noalias ptr @realloc(ptr nocapture allocptr, i64) nounwind allocsize(1)15 16define void @f1() nounwind {17; CHECK-LABEL: @f1(18; CHECK-NEXT: [[TMP1:%.*]] = tail call ptr @malloc(i64 32)19; CHECK-NEXT: [[IDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 220; CHECK-NEXT: store i32 3, ptr [[IDX]], align 421; CHECK-NEXT: ret void22;23 %1 = tail call ptr @malloc(i64 32)24 %idx = getelementptr inbounds i32, ptr %1, i64 225 store i32 3, ptr %idx, align 426 ret void27}28 29define void @f2() nounwind {30; CHECK-LABEL: @f2(31; CHECK-NEXT: [[TMP1:%.*]] = tail call ptr @malloc(i64 32)32; CHECK-NEXT: [[IDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 833; CHECK-NEXT: br label [[TRAP:%.*]]34; CHECK: 2:35; CHECK-NEXT: store i32 3, ptr [[IDX]], align 436; CHECK-NEXT: ret void37; CHECK: trap:38; CHECK-NEXT: call void @llvm.trap() #[[ATTR6:[0-9]+]], !nosanitize [[META0:![0-9]+]]39; CHECK-NEXT: unreachable, !nosanitize [[META0]]40;41 %1 = tail call ptr @malloc(i64 32)42 %idx = getelementptr inbounds i32, ptr %1, i64 843 store i32 3, ptr %idx, align 444 ret void45}46 47define void @f3(i64 %x) nounwind {48; CHECK-LABEL: @f3(49; CHECK-NEXT: [[TMP1:%.*]] = mul i64 4, [[X:%.*]]50; CHECK-NEXT: [[TMP2:%.*]] = tail call ptr @calloc(i64 4, i64 [[X]])51; CHECK-NEXT: [[IDX:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 852; CHECK-NEXT: [[TMP3:%.*]] = sub i64 [[TMP1]], 32, !nosanitize [[META0]]53; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP1]], 32, !nosanitize [[META0]]54; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i64 [[TMP3]], 4, !nosanitize [[META0]]55; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP4]], [[TMP5]], !nosanitize [[META0]]56; CHECK-NEXT: [[TMP7:%.*]] = or i1 false, [[TMP6]], !nosanitize [[META0]]57; CHECK-NEXT: br i1 [[TMP7]], label [[TRAP:%.*]], label [[TMP8:%.*]]58; CHECK: 8:59; CHECK-NEXT: store i32 3, ptr [[IDX]], align 460; CHECK-NEXT: ret void61; CHECK: trap:62; CHECK-NEXT: call void @llvm.trap() #[[ATTR6]], !nosanitize [[META0]]63; CHECK-NEXT: unreachable, !nosanitize [[META0]]64;65 %1 = tail call ptr @calloc(i64 4, i64 %x)66 %idx = getelementptr inbounds i32, ptr %1, i64 867 store i32 3, ptr %idx, align 468 ret void69}70 71define void @store_volatile(i64 %x) nounwind {72; CHECK-LABEL: @store_volatile(73; CHECK-NEXT: [[TMP1:%.*]] = tail call ptr @calloc(i64 4, i64 [[X:%.*]])74; CHECK-NEXT: [[IDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 875; CHECK-NEXT: store volatile i32 3, ptr [[IDX]], align 476; CHECK-NEXT: ret void77;78 %1 = tail call ptr @calloc(i64 4, i64 %x)79 %idx = getelementptr inbounds i32, ptr %1, i64 880 store volatile i32 3, ptr %idx, align 481 ret void82}83 84define void @f4(i64 %x) nounwind {85; CHECK-LABEL: @f4(86; CHECK-NEXT: [[TMP1:%.*]] = tail call ptr @realloc(ptr null, i64 [[X:%.*]]) #[[ATTR3:[0-9]+]]87; CHECK-NEXT: [[IDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 888; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[X]], 32, !nosanitize [[META0]]89; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i64 [[X]], 32, !nosanitize [[META0]]90; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP2]], 4, !nosanitize [[META0]]91; CHECK-NEXT: [[TMP5:%.*]] = or i1 [[TMP3]], [[TMP4]], !nosanitize [[META0]]92; CHECK-NEXT: [[TMP6:%.*]] = or i1 false, [[TMP5]], !nosanitize [[META0]]93; CHECK-NEXT: br i1 [[TMP6]], label [[TRAP:%.*]], label [[TMP7:%.*]]94; CHECK: 7:95; CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr [[IDX]], align 496; CHECK-NEXT: ret void97; CHECK: trap:98; CHECK-NEXT: call void @llvm.trap() #[[ATTR6]], !nosanitize [[META0]]99; CHECK-NEXT: unreachable, !nosanitize [[META0]]100;101 %1 = tail call ptr @realloc(ptr null, i64 %x) nounwind102 %idx = getelementptr inbounds i32, ptr %1, i64 8103 %2 = load i32, ptr %idx, align 4104 ret void105}106 107define void @f5(i64 %x) nounwind {108; CHECK-LABEL: @f5(109; CHECK-NEXT: [[TMP1:%.*]] = add i64 0, [[X:%.*]]110; CHECK-NEXT: [[IDX:%.*]] = getelementptr inbounds [8 x i8], ptr @.str, i64 0, i64 [[X]]111; CHECK-NEXT: [[TMP2:%.*]] = sub i64 8, [[TMP1]], !nosanitize [[META0]]112; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i64 8, [[TMP1]], !nosanitize [[META0]]113; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP2]], 1, !nosanitize [[META0]]114; CHECK-NEXT: [[TMP5:%.*]] = or i1 [[TMP3]], [[TMP4]], !nosanitize [[META0]]115; CHECK-NEXT: br i1 [[TMP5]], label [[TRAP:%.*]], label [[TMP6:%.*]]116; CHECK: 6:117; CHECK-NEXT: [[TMP7:%.*]] = load i8, ptr [[IDX]], align 4118; CHECK-NEXT: ret void119; CHECK: trap:120; CHECK-NEXT: call void @llvm.trap() #[[ATTR6]], !nosanitize [[META0]]121; CHECK-NEXT: unreachable, !nosanitize [[META0]]122;123 %idx = getelementptr inbounds [8 x i8], ptr @.str, i64 0, i64 %x124 %1 = load i8, ptr %idx, align 4125 ret void126}127 128define void @f5_as1(i64 %x) nounwind {129; CHECK-LABEL: @f5_as1(130; CHECK-NEXT: [[X_C:%.*]] = trunc i64 [[X:%.*]] to i16131; CHECK-NEXT: [[TMP1:%.*]] = add i16 0, [[X_C]]132; CHECK-NEXT: [[IDX:%.*]] = getelementptr inbounds [8 x i8], ptr addrspace(1) @.str_as1, i64 0, i64 [[X]]133; CHECK-NEXT: [[TMP2:%.*]] = sub i16 8, [[TMP1]], !nosanitize [[META0]]134; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i16 8, [[TMP1]], !nosanitize [[META0]]135; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i16 [[TMP2]], 1, !nosanitize [[META0]]136; CHECK-NEXT: [[TMP5:%.*]] = or i1 [[TMP3]], [[TMP4]], !nosanitize [[META0]]137; CHECK-NEXT: br i1 [[TMP5]], label [[TRAP:%.*]], label [[TMP6:%.*]]138; CHECK: 6:139; CHECK-NEXT: [[TMP7:%.*]] = load i8, ptr addrspace(1) [[IDX]], align 4140; CHECK-NEXT: ret void141; CHECK: trap:142; CHECK-NEXT: call void @llvm.trap() #[[ATTR6]], !nosanitize [[META0]]143; CHECK-NEXT: unreachable, !nosanitize [[META0]]144;145 %idx = getelementptr inbounds [8 x i8], ptr addrspace(1) @.str_as1, i64 0, i64 %x146 %1 = load i8, ptr addrspace(1) %idx, align 4147 ret void148}149 150define void @f5_as2(i32 %x) nounwind {;151; CHECK-LABEL: @f5_as2(152; CHECK-NEXT: [[X_C:%.*]] = sext i32 [[X:%.*]] to i48153; CHECK-NEXT: [[TMP1:%.*]] = add i48 0, [[X_C]]154; CHECK-NEXT: [[IDX:%.*]] = getelementptr inbounds [8 x i8], ptr addrspace(2) @.str_as2, i32 0, i32 [[X]]155; CHECK-NEXT: [[TMP2:%.*]] = sub i48 8, [[TMP1]], !nosanitize [[META0]]156; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i48 8, [[TMP1]], !nosanitize [[META0]]157; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i48 [[TMP2]], 1, !nosanitize [[META0]]158; CHECK-NEXT: [[TMP5:%.*]] = or i1 [[TMP3]], [[TMP4]], !nosanitize [[META0]]159; CHECK-NEXT: br i1 [[TMP5]], label [[TRAP:%.*]], label [[TMP6:%.*]]160; CHECK: 6:161; CHECK-NEXT: [[TMP7:%.*]] = load i8, ptr addrspace(2) [[IDX]], align 4162; CHECK-NEXT: ret void163; CHECK: trap:164; CHECK-NEXT: call void @llvm.trap() #[[ATTR6]], !nosanitize [[META0]]165; CHECK-NEXT: unreachable, !nosanitize [[META0]]166;167 %idx = getelementptr inbounds [8 x i8], ptr addrspace(2) @.str_as2, i32 0, i32 %x168 %1 = load i8, ptr addrspace(2) %idx, align 4169 ret void170}171 172define void @f6(i64 %x) nounwind {173; CHECK-LABEL: @f6(174; CHECK-NEXT: [[TMP1:%.*]] = alloca i128, align 8175; CHECK-NEXT: [[TMP2:%.*]] = load i128, ptr [[TMP1]], align 4176; CHECK-NEXT: ret void177;178 %1 = alloca i128179 %2 = load i128, ptr %1, align 4180 ret void181}182 183define void @f7(i64 %x) nounwind {184; CHECK-LABEL: @f7(185; CHECK-NEXT: [[TMP1:%.*]] = mul i64 16, [[X:%.*]]186; CHECK-NEXT: [[TMP2:%.*]] = alloca i128, i64 [[X]], align 8187; CHECK-NEXT: [[TMP3:%.*]] = sub i64 [[TMP1]], 0, !nosanitize [[META0]]188; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP3]], 16, !nosanitize [[META0]]189; CHECK-NEXT: [[TMP5:%.*]] = or i1 false, [[TMP4]], !nosanitize [[META0]]190; CHECK-NEXT: [[TMP6:%.*]] = or i1 false, [[TMP5]], !nosanitize [[META0]]191; CHECK-NEXT: br i1 [[TMP6]], label [[TRAP:%.*]], label [[TMP7:%.*]]192; CHECK: 7:193; CHECK-NEXT: [[TMP8:%.*]] = load i128, ptr [[TMP2]], align 4194; CHECK-NEXT: ret void195; CHECK: trap:196; CHECK-NEXT: call void @llvm.trap() #[[ATTR6]], !nosanitize [[META0]]197; CHECK-NEXT: unreachable, !nosanitize [[META0]]198;199 %1 = alloca i128, i64 %x200 %2 = load i128, ptr %1, align 4201 ret void202}203 204define void @f8() nounwind {205; CHECK-LABEL: @f8(206; CHECK-NEXT: [[TMP1:%.*]] = alloca i128, align 8207; CHECK-NEXT: [[TMP2:%.*]] = alloca i128, align 8208; CHECK-NEXT: [[TMP3:%.*]] = select i1 undef, ptr [[TMP1]], ptr [[TMP2]]209; CHECK-NEXT: [[TMP4:%.*]] = load i128, ptr [[TMP3]], align 4210; CHECK-NEXT: ret void211;212 %1 = alloca i128213 %2 = alloca i128214 %3 = select i1 undef, ptr %1, ptr %2215 %4 = load i128, ptr %3, align 4216 ret void217}218 219define void @f9(ptr %arg) nounwind {220; CHECK-LABEL: @f9(221; CHECK-NEXT: [[TMP1:%.*]] = alloca i128, align 8222; CHECK-NEXT: [[TMP2:%.*]] = select i1 undef, ptr [[ARG:%.*]], ptr [[TMP1]]223; CHECK-NEXT: [[TMP3:%.*]] = load i128, ptr [[TMP2]], align 4224; CHECK-NEXT: ret void225;226 %1 = alloca i128227 %2 = select i1 undef, ptr %arg, ptr %1228 %3 = load i128, ptr %2, align 4229 ret void230}231 232define void @f10(i64 %x, i64 %y) nounwind {233; CHECK-LABEL: @f10(234; CHECK-NEXT: [[TMP1:%.*]] = mul i64 16, [[X:%.*]]235; CHECK-NEXT: [[TMP2:%.*]] = alloca i128, i64 [[X]], align 8236; CHECK-NEXT: [[TMP3:%.*]] = mul i64 16, [[Y:%.*]]237; CHECK-NEXT: [[TMP4:%.*]] = alloca i128, i64 [[Y]], align 8238; CHECK-NEXT: [[TMP5:%.*]] = select i1 undef, i64 [[TMP1]], i64 [[TMP3]]239; CHECK-NEXT: [[TMP6:%.*]] = select i1 undef, ptr [[TMP2]], ptr [[TMP4]]240; CHECK-NEXT: [[TMP7:%.*]] = sub i64 [[TMP5]], 0, !nosanitize [[META0]]241; CHECK-NEXT: [[TMP8:%.*]] = icmp ult i64 [[TMP7]], 16, !nosanitize [[META0]]242; CHECK-NEXT: [[TMP9:%.*]] = or i1 false, [[TMP8]], !nosanitize [[META0]]243; CHECK-NEXT: [[TMP10:%.*]] = or i1 false, [[TMP9]], !nosanitize [[META0]]244; CHECK-NEXT: br i1 [[TMP10]], label [[TRAP:%.*]], label [[TMP11:%.*]]245; CHECK: 11:246; CHECK-NEXT: [[TMP12:%.*]] = load i128, ptr [[TMP6]], align 4247; CHECK-NEXT: ret void248; CHECK: trap:249; CHECK-NEXT: call void @llvm.trap() #[[ATTR6]], !nosanitize [[META0]]250; CHECK-NEXT: unreachable, !nosanitize [[META0]]251;252 %1 = alloca i128, i64 %x253 %2 = alloca i128, i64 %y254 %3 = select i1 undef, ptr %1, ptr %2255 %4 = load i128, ptr %3, align 4256 ret void257}258 259define void @f11(ptr byval(i128) %x) nounwind {260; CHECK-LABEL: @f11(261; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[X:%.*]], i64 16262; CHECK-NEXT: br label [[TRAP:%.*]]263; CHECK: 2:264; CHECK-NEXT: [[TMP3:%.*]] = load i8, ptr [[TMP1]], align 4265; CHECK-NEXT: ret void266; CHECK: trap:267; CHECK-NEXT: call void @llvm.trap() #[[ATTR6]], !nosanitize [[META0]]268; CHECK-NEXT: unreachable, !nosanitize [[META0]]269;270 %1 = getelementptr inbounds i8, ptr %x, i64 16271 %2 = load i8, ptr %1, align 4272 ret void273}274 275define void @f11_as1(ptr addrspace(1) byval(i128) %x) nounwind {276; CHECK-LABEL: @f11_as1(277; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[X:%.*]], i16 16278; CHECK-NEXT: br label [[TRAP:%.*]]279; CHECK: 2:280; CHECK-NEXT: [[TMP3:%.*]] = load i8, ptr addrspace(1) [[TMP1]], align 4281; CHECK-NEXT: ret void282; CHECK: trap:283; CHECK-NEXT: call void @llvm.trap() #[[ATTR6]], !nosanitize [[META0]]284; CHECK-NEXT: unreachable, !nosanitize [[META0]]285;286 %1 = getelementptr inbounds i8, ptr addrspace(1) %x, i16 16287 %2 = load i8, ptr addrspace(1) %1, align 4288 ret void289}290 291define i64 @f12(i64 %x, i64 %y) nounwind {292; CHECK-LABEL: @f12(293; CHECK-NEXT: [[TMP1:%.*]] = mul i64 1, [[X:%.*]]294; CHECK-NEXT: [[TMP2:%.*]] = tail call ptr @calloc(i64 1, i64 [[X]])295; CHECK-NEXT: [[DOTIDX:%.*]] = mul i64 [[Y:%.*]], 8296; CHECK-NEXT: [[TMP3:%.*]] = add i64 0, [[DOTIDX]]297; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i64, ptr [[TMP2]], i64 [[Y]]298; CHECK-NEXT: [[TMP5:%.*]] = sub i64 [[TMP1]], [[TMP3]], !nosanitize [[META0]]299; CHECK-NEXT: [[TMP6:%.*]] = icmp ult i64 [[TMP1]], [[TMP3]], !nosanitize [[META0]]300; CHECK-NEXT: [[TMP7:%.*]] = icmp ult i64 [[TMP5]], 8, !nosanitize [[META0]]301; CHECK-NEXT: [[TMP8:%.*]] = or i1 [[TMP6]], [[TMP7]], !nosanitize [[META0]]302; CHECK-NEXT: [[TMP9:%.*]] = icmp slt i64 [[TMP3]], 0, !nosanitize [[META0]]303; CHECK-NEXT: [[TMP10:%.*]] = or i1 [[TMP9]], [[TMP8]], !nosanitize [[META0]]304; CHECK-NEXT: br i1 [[TMP10]], label [[TRAP:%.*]], label [[TMP11:%.*]]305; CHECK: 11:306; CHECK-NEXT: [[TMP12:%.*]] = load i64, ptr [[TMP4]], align 8307; CHECK-NEXT: ret i64 [[TMP12]]308; CHECK: trap:309; CHECK-NEXT: call void @llvm.trap() #[[ATTR6]], !nosanitize [[META0]]310; CHECK-NEXT: unreachable, !nosanitize [[META0]]311;312 %1 = tail call ptr @calloc(i64 1, i64 %x)313 %2 = getelementptr inbounds i64, ptr %1, i64 %y314 %3 = load i64, ptr %2, align 8315 ret i64 %3316}317 318define i64 @load_volatile(i64 %x, i64 %y) nounwind {319; CHECK-LABEL: @load_volatile(320; CHECK-NEXT: [[TMP1:%.*]] = tail call ptr @calloc(i64 1, i64 [[X:%.*]])321; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i64, ptr [[TMP1]], i64 [[Y:%.*]]322; CHECK-NEXT: [[TMP3:%.*]] = load volatile i64, ptr [[TMP2]], align 8323; CHECK-NEXT: ret i64 [[TMP3]]324;325 %1 = tail call ptr @calloc(i64 1, i64 %x)326 %2 = getelementptr inbounds i64, ptr %1, i64 %y327 %3 = load volatile i64, ptr %2, align 8328 ret i64 %3329}330 331; PR17402332define void @f13() nounwind {333; CHECK-LABEL: @f13(334; CHECK-NEXT: entry:335; CHECK-NEXT: br label [[ALIVE:%.*]]336; CHECK: dead:337; CHECK-NEXT: [[INCDEC_PTR:%.*]] = getelementptr inbounds i32, ptr [[INCDEC_PTR]], i64 1338; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[INCDEC_PTR]], align 4339; CHECK-NEXT: br label [[ALIVE]]340; CHECK: alive:341; CHECK-NEXT: ret void342;343entry:344 br label %alive345 346dead:347 ; Self-refential GEPs can occur in dead code.348 %incdec.ptr = getelementptr inbounds i32, ptr %incdec.ptr, i64 1349 %l = load i32, ptr %incdec.ptr350 br label %alive351 352alive:353 ret void354}355 356; Check that merging sizes in a phi works.357define i8 @f14(i1 %i) {358; CHECK-LABEL: @f14(359; CHECK-NEXT: entry:360; CHECK-NEXT: br i1 [[I:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]361; CHECK: bb1:362; CHECK-NEXT: [[A:%.*]] = alloca [32 x i8], align 1363; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[A]], i32 32364; CHECK-NEXT: br label [[BB2]]365; CHECK: bb2:366; CHECK-NEXT: [[TMP0:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ 32, [[BB1]] ]367; CHECK-NEXT: [[TMP1:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ 32, [[BB1]] ]368; CHECK-NEXT: [[ALLOC:%.*]] = phi ptr [ null, [[ENTRY]] ], [ [[G]], [[BB1]] ]369; CHECK-NEXT: [[IND:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ -4, [[BB1]] ]370; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], [[IND]]371; CHECK-NEXT: [[P:%.*]] = getelementptr i8, ptr [[ALLOC]], i64 [[IND]]372; CHECK-NEXT: [[TMP3:%.*]] = sub i64 [[TMP0]], [[TMP2]], !nosanitize [[META0]]373; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP0]], [[TMP2]], !nosanitize [[META0]]374; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i64 [[TMP3]], 1, !nosanitize [[META0]]375; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP4]], [[TMP5]], !nosanitize [[META0]]376; CHECK-NEXT: br i1 [[TMP6]], label [[TRAP:%.*]], label [[TMP7:%.*]]377; CHECK: 7:378; CHECK-NEXT: [[RET:%.*]] = load i8, ptr [[P]], align 1379; CHECK-NEXT: ret i8 [[RET]]380; CHECK: trap:381; CHECK-NEXT: call void @llvm.trap() #[[ATTR6]], !nosanitize [[META0]]382; CHECK-NEXT: unreachable, !nosanitize [[META0]]383;384entry:385 br i1 %i, label %bb1, label %bb2386 387bb1:388 %a = alloca [32 x i8]389 %g = getelementptr i8, ptr %a, i32 32390 br label %bb2391 392bb2:393 %alloc = phi ptr [ null, %entry ], [ %g, %bb1 ]394 %ind = phi i64 [ 0, %entry ], [ -4, %bb1 ]395 %p = getelementptr i8, ptr %alloc, i64 %ind396 %ret = load i8, ptr %p397 ret i8 %ret398}399 400; Check that merging offsets in a phi works.401define i8 @f15(i1 %i) {402; CHECK-LABEL: @f15(403; CHECK-NEXT: entry:404; CHECK-NEXT: [[A1:%.*]] = alloca [32 x i8], align 1405; CHECK-NEXT: [[G1:%.*]] = getelementptr i8, ptr [[A1]], i32 100406; CHECK-NEXT: br i1 [[I:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]407; CHECK: bb1:408; CHECK-NEXT: [[A2:%.*]] = alloca [32 x i8], align 1409; CHECK-NEXT: [[G2:%.*]] = getelementptr i8, ptr [[A2]], i32 16410; CHECK-NEXT: br label [[BB2]]411; CHECK: bb2:412; CHECK-NEXT: [[TMP0:%.*]] = phi i64 [ 100, [[ENTRY:%.*]] ], [ 16, [[BB1]] ]413; CHECK-NEXT: [[ALLOC:%.*]] = phi ptr [ [[G1]], [[ENTRY]] ], [ [[G2]], [[BB1]] ]414; CHECK-NEXT: [[TMP1:%.*]] = sub i64 32, [[TMP0]], !nosanitize [[META0]]415; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i64 32, [[TMP0]], !nosanitize [[META0]]416; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP1]], 1, !nosanitize [[META0]]417; CHECK-NEXT: [[TMP4:%.*]] = or i1 [[TMP2]], [[TMP3]], !nosanitize [[META0]]418; CHECK-NEXT: br i1 [[TMP4]], label [[TRAP:%.*]], label [[TMP5:%.*]]419; CHECK: 5:420; CHECK-NEXT: [[RET:%.*]] = load i8, ptr [[ALLOC]], align 1421; CHECK-NEXT: ret i8 [[RET]]422; CHECK: trap:423; CHECK-NEXT: call void @llvm.trap() #[[ATTR6]], !nosanitize [[META0]]424; CHECK-NEXT: unreachable, !nosanitize [[META0]]425;426entry:427 %a1 = alloca [32 x i8]428 %g1 = getelementptr i8, ptr %a1, i32 100429 br i1 %i, label %bb1, label %bb2430 431bb1:432 %a2 = alloca [32 x i8]433 %g2 = getelementptr i8, ptr %a2, i32 16434 br label %bb2435 436bb2:437 %alloc = phi ptr [ %g1, %entry ], [ %g2, %bb1 ]438 %ret = load i8, ptr %alloc439 ret i8 %ret440}441 442define <4 x i32> @load_vector(i64 %y) nounwind {443; CHECK-LABEL: @load_vector(444; CHECK-NEXT: [[TMP1:%.*]] = tail call ptr @calloc(i64 1, i64 256)445; CHECK-NEXT: [[DOTIDX:%.*]] = mul i64 [[Y:%.*]], 8446; CHECK-NEXT: [[TMP2:%.*]] = add i64 0, [[DOTIDX]]447; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i64, ptr [[TMP1]], i64 [[Y]]448; CHECK-NEXT: [[TMP4:%.*]] = sub i64 256, [[TMP2]], !nosanitize [[META0]]449; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i64 256, [[TMP2]], !nosanitize [[META0]]450; CHECK-NEXT: [[TMP6:%.*]] = icmp ult i64 [[TMP4]], 16, !nosanitize [[META0]]451; CHECK-NEXT: [[TMP7:%.*]] = or i1 [[TMP5]], [[TMP6]], !nosanitize [[META0]]452; CHECK-NEXT: br i1 [[TMP7]], label [[TRAP:%.*]], label [[TMP8:%.*]]453; CHECK: 8:454; CHECK-NEXT: [[TMP9:%.*]] = load <4 x i32>, ptr [[TMP3]], align 8455; CHECK-NEXT: ret <4 x i32> [[TMP9]]456; CHECK: trap:457; CHECK-NEXT: call void @llvm.trap() #[[ATTR6]], !nosanitize [[META0]]458; CHECK-NEXT: unreachable, !nosanitize [[META0]]459;460 %1 = tail call ptr @calloc(i64 1, i64 256)461 %2 = getelementptr inbounds i64, ptr %1, i64 %y462 %3 = load <4 x i32>, ptr %2, align 8463 ret <4 x i32> %3464}465 466define <vscale x 1 x i32> @load_scalable_vector(i64 %y) nounwind {467; CHECK-LABEL: @load_scalable_vector(468; CHECK-NEXT: [[TMP1:%.*]] = tail call ptr @calloc(i64 1, i64 256)469; CHECK-NEXT: [[DOTIDX:%.*]] = mul i64 [[Y:%.*]], 8470; CHECK-NEXT: [[TMP2:%.*]] = add i64 0, [[DOTIDX]]471; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i64, ptr [[TMP1]], i64 [[Y]]472; CHECK-NEXT: [[TMP4:%.*]] = call i64 @llvm.vscale.i64(), !nosanitize [[META0]]473; CHECK-NEXT: [[TMP5:%.*]] = mul nuw i64 [[TMP4]], 4, !nosanitize [[META0]]474; CHECK-NEXT: [[TMP6:%.*]] = sub i64 256, [[TMP2]], !nosanitize [[META0]]475; CHECK-NEXT: [[TMP7:%.*]] = icmp ult i64 256, [[TMP2]], !nosanitize [[META0]]476; CHECK-NEXT: [[TMP8:%.*]] = icmp ult i64 [[TMP6]], [[TMP5]], !nosanitize [[META0]]477; CHECK-NEXT: [[TMP9:%.*]] = or i1 [[TMP7]], [[TMP8]], !nosanitize [[META0]]478; CHECK-NEXT: br i1 [[TMP9]], label [[TRAP:%.*]], label [[TMP10:%.*]]479; CHECK: 10:480; CHECK-NEXT: [[TMP11:%.*]] = load <vscale x 1 x i32>, ptr [[TMP3]], align 8481; CHECK-NEXT: ret <vscale x 1 x i32> [[TMP11]]482; CHECK: trap:483; CHECK-NEXT: call void @llvm.trap() #[[ATTR6]], !nosanitize [[META0]]484; CHECK-NEXT: unreachable, !nosanitize [[META0]]485;486 %1 = tail call ptr @calloc(i64 1, i64 256)487 %2 = getelementptr inbounds i64, ptr %1, i64 %y488 %3 = load <vscale x 1 x i32>, ptr %2, align 8489 ret <vscale x 1 x i32> %3490}491 492define void @scalable_alloca(i64 %y) nounwind {493; CHECK-LABEL: @scalable_alloca(494; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()495; CHECK-NEXT: [[TMP2:%.*]] = mul nuw i64 [[TMP1]], 8496; CHECK-NEXT: [[TMP3:%.*]] = mul i64 [[TMP2]], 5497; CHECK-NEXT: [[TMP4:%.*]] = alloca <vscale x 4 x i16>, i32 5, align 8498; CHECK-NEXT: [[TMP5:%.*]] = call i64 @llvm.vscale.i64()499; CHECK-NEXT: [[TMP6:%.*]] = mul nuw i64 [[TMP5]], 8500; CHECK-NEXT: [[DOTIDX:%.*]] = mul i64 [[Y:%.*]], [[TMP6]]501; CHECK-NEXT: [[TMP7:%.*]] = add i64 0, [[DOTIDX]]502; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds <vscale x 4 x i16>, ptr [[TMP4]], i64 [[Y]]503; CHECK-NEXT: [[TMP9:%.*]] = call i64 @llvm.vscale.i64(), !nosanitize [[META0]]504; CHECK-NEXT: [[TMP10:%.*]] = mul nuw i64 [[TMP9]], 8, !nosanitize [[META0]]505; CHECK-NEXT: [[TMP11:%.*]] = sub i64 [[TMP3]], [[TMP7]], !nosanitize [[META0]]506; CHECK-NEXT: [[TMP12:%.*]] = icmp ult i64 [[TMP3]], [[TMP7]], !nosanitize [[META0]]507; CHECK-NEXT: [[TMP13:%.*]] = icmp ult i64 [[TMP11]], [[TMP10]], !nosanitize [[META0]]508; CHECK-NEXT: [[TMP14:%.*]] = or i1 [[TMP12]], [[TMP13]], !nosanitize [[META0]]509; CHECK-NEXT: [[TMP15:%.*]] = icmp slt i64 [[TMP7]], 0, !nosanitize [[META0]]510; CHECK-NEXT: [[TMP16:%.*]] = or i1 [[TMP15]], [[TMP14]], !nosanitize [[META0]]511; CHECK-NEXT: br i1 [[TMP16]], label [[TRAP:%.*]], label [[TMP17:%.*]]512; CHECK: 17:513; CHECK-NEXT: [[TMP18:%.*]] = load <vscale x 4 x i16>, ptr [[TMP8]], align 4514; CHECK-NEXT: ret void515; CHECK: trap:516; CHECK-NEXT: call void @llvm.trap() #[[ATTR6]], !nosanitize [[META0]]517; CHECK-NEXT: unreachable, !nosanitize [[META0]]518;519 %1 = alloca <vscale x 4 x i16>, i32 5520 %2 = getelementptr inbounds <vscale x 4 x i16>, ptr %1, i64 %y521 %3 = load <vscale x 4 x i16>, ptr %2, align 4522 ret void523}524 525define void @scalable_alloca2(i64 %y) nounwind {526; CHECK-LABEL: @scalable_alloca2(527; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()528; CHECK-NEXT: [[TMP2:%.*]] = mul nuw i64 [[TMP1]], 32529; CHECK-NEXT: [[TMP3:%.*]] = mul i64 [[TMP2]], 1530; CHECK-NEXT: [[TMP4:%.*]] = alloca <vscale x 4 x i64>, align 32531; CHECK-NEXT: [[TMP5:%.*]] = call i64 @llvm.vscale.i64()532; CHECK-NEXT: [[TMP6:%.*]] = mul nuw i64 [[TMP5]], 32533; CHECK-NEXT: [[DOTIDX:%.*]] = mul i64 [[Y:%.*]], [[TMP6]]534; CHECK-NEXT: [[TMP7:%.*]] = add i64 0, [[DOTIDX]]535; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds <vscale x 4 x i64>, ptr [[TMP4]], i64 [[Y]]536; CHECK-NEXT: [[TMP9:%.*]] = call i64 @llvm.vscale.i64(), !nosanitize [[META0]]537; CHECK-NEXT: [[TMP10:%.*]] = mul nuw i64 [[TMP9]], 32, !nosanitize [[META0]]538; CHECK-NEXT: [[TMP11:%.*]] = sub i64 [[TMP3]], [[TMP7]], !nosanitize [[META0]]539; CHECK-NEXT: [[TMP12:%.*]] = icmp ult i64 [[TMP3]], [[TMP7]], !nosanitize [[META0]]540; CHECK-NEXT: [[TMP13:%.*]] = icmp ult i64 [[TMP11]], [[TMP10]], !nosanitize [[META0]]541; CHECK-NEXT: [[TMP14:%.*]] = or i1 [[TMP12]], [[TMP13]], !nosanitize [[META0]]542; CHECK-NEXT: [[TMP15:%.*]] = icmp slt i64 [[TMP7]], 0, !nosanitize [[META0]]543; CHECK-NEXT: [[TMP16:%.*]] = or i1 [[TMP15]], [[TMP14]], !nosanitize [[META0]]544; CHECK-NEXT: br i1 [[TMP16]], label [[TRAP:%.*]], label [[TMP17:%.*]]545; CHECK: 17:546; CHECK-NEXT: [[TMP18:%.*]] = load <vscale x 4 x i64>, ptr [[TMP8]], align 4547; CHECK-NEXT: ret void548; CHECK: trap:549; CHECK-NEXT: call void @llvm.trap() #[[ATTR6]], !nosanitize [[META0]]550; CHECK-NEXT: unreachable, !nosanitize [[META0]]551;552 %1 = alloca <vscale x 4 x i64>553 %2 = getelementptr inbounds <vscale x 4 x i64>, ptr %1, i64 %y554 %3 = load <vscale x 4 x i64>, ptr %2, align 4555 ret void556}557