129 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S -passes=licm < %s | FileCheck %s3 4; Note: the !invariant.load is there just solely to let us call @use()5; to add a fake use, and still have the aliasing work out. The call6; to @use(0) is just to provide a may-unwind exit out of the loop, so7; that LICM cannot hoist out the load simply because it is guaranteed8; to execute.9 10declare void @use(i32)11 12define void @f_0(ptr align 4 dereferenceable(1024) %ptr) nofree nosync {13; CHECK-LABEL: @f_0(14; CHECK-NEXT: entry:15; CHECK-NEXT: [[PTR_GEP:%.*]] = getelementptr i8, ptr [[PTR:%.*]], i32 3216; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[PTR_GEP]], align 417; CHECK-NEXT: br label [[LOOP:%.*]]18; CHECK: loop:19; CHECK-NEXT: call void @use(i32 0)20; CHECK-NEXT: call void @use(i32 [[VAL]])21; CHECK-NEXT: br label [[LOOP]]22;23 24 25entry:26 %ptr.gep = getelementptr i8, ptr %ptr, i32 3227 br label %loop28 29loop:30 call void @use(i32 0)31 %val = load i32, ptr %ptr.gep, !invariant.load !{}32 call void @use(i32 %val)33 br label %loop34}35 36define void @f_1(ptr align 4 dereferenceable_or_null(1024) %ptr) nofree nosync {37; CHECK-LABEL: @f_1(38; CHECK-NEXT: entry:39; CHECK-NEXT: [[PTR_GEP:%.*]] = getelementptr i8, ptr [[PTR:%.*]], i32 3240; CHECK-NEXT: [[PTR_IS_NULL:%.*]] = icmp eq ptr [[PTR]], null41; CHECK-NEXT: br i1 [[PTR_IS_NULL]], label [[LEAVE:%.*]], label [[LOOP_PREHEADER:%.*]]42; CHECK: loop.preheader:43; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[PTR_GEP]], align 444; CHECK-NEXT: br label [[LOOP:%.*]]45; CHECK: loop:46; CHECK-NEXT: call void @use(i32 0)47; CHECK-NEXT: call void @use(i32 [[VAL]])48; CHECK-NEXT: br label [[LOOP]]49; CHECK: leave:50; CHECK-NEXT: ret void51;52entry:53 %ptr.gep = getelementptr i8, ptr %ptr, i32 3254 %ptr_is_null = icmp eq ptr %ptr, null55 br i1 %ptr_is_null, label %leave, label %loop56 57 58loop:59 call void @use(i32 0)60 %val = load i32, ptr %ptr.gep, !invariant.load !{}61 call void @use(i32 %val)62 br label %loop63 64leave:65 ret void66}67 68define void @f_2(ptr align 4 dereferenceable_or_null(1024) %ptr) {69; CHECK-LABEL: @f_2(70; CHECK-NEXT: entry:71; CHECK-NEXT: [[PTR_GEP:%.*]] = getelementptr i8, ptr [[PTR:%.*]], i32 3072; CHECK-NEXT: [[PTR_IS_NULL:%.*]] = icmp eq ptr [[PTR]], null73; CHECK-NEXT: br i1 [[PTR_IS_NULL]], label [[LEAVE:%.*]], label [[LOOP_PREHEADER:%.*]]74; CHECK: loop.preheader:75; CHECK-NEXT: br label [[LOOP:%.*]]76; CHECK: loop:77; CHECK-NEXT: call void @use(i32 0)78; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[PTR_GEP]], align 4, !invariant.load !079; CHECK-NEXT: call void @use(i32 [[VAL]])80; CHECK-NEXT: br label [[LOOP]]81; CHECK: leave:82; CHECK-NEXT: ret void83;84 85entry:86 ;; Can't hoist, since the alignment does not work out -- (<4 byte87 ;; aligned> + 30) is not necessarily 4 byte aligned.88 89 %ptr.gep = getelementptr i8, ptr %ptr, i32 3090 %ptr_is_null = icmp eq ptr %ptr, null91 br i1 %ptr_is_null, label %leave, label %loop92 93loop:94 call void @use(i32 0)95 %val = load i32, ptr %ptr.gep, !invariant.load !{}96 call void @use(i32 %val)97 br label %loop98 99leave:100 ret void101}102 103define void @checkLaunder(ptr align 4 dereferenceable(1024) %p) nofree nosync {104; CHECK-LABEL: @checkLaunder(105; CHECK-NEXT: entry:106; CHECK-NEXT: [[L:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[P:%.*]])107; CHECK-NEXT: [[VAL:%.*]] = load i8, ptr [[L]], align 1108; CHECK-NEXT: br label [[LOOP:%.*]]109; CHECK: loop:110; CHECK-NEXT: call void @use(i32 0)111; CHECK-NEXT: call void @use8(i8 [[VAL]])112; CHECK-NEXT: br label [[LOOP]]113;114 115entry:116 %l = call ptr @llvm.launder.invariant.group.p0(ptr %p)117 br label %loop118 119loop:120 call void @use(i32 0)121 %val = load i8, ptr %l, !invariant.load !{}122 call void @use8(i8 %val)123 br label %loop124}125 126declare ptr @llvm.launder.invariant.group.p0(ptr)127 128declare void @use8(i8)129