diff options
Diffstat (limited to 'llvm/test/Transforms/GVN')
55 files changed, 1809 insertions, 665 deletions
diff --git a/llvm/test/Transforms/GVN/2011-07-07-MatchIntrinsicExtract.ll b/llvm/test/Transforms/GVN/2011-07-07-MatchIntrinsicExtract.ll index b139e07..acd0317 100644 --- a/llvm/test/Transforms/GVN/2011-07-07-MatchIntrinsicExtract.ll +++ b/llvm/test/Transforms/GVN/2011-07-07-MatchIntrinsicExtract.ll @@ -1,9 +1,19 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt < %s -passes=gvn -S | FileCheck %s -; %0 = type { i64, i1 } define i64 @test1(i64 %a, i64 %b) nounwind ssp { +; CHECK-LABEL: define i64 @test1( +; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP0:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[A]], i64 [[B]]) +; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i64, i1 } [[TMP0]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [[TMP0]] poison, i64 [[TMP1]], 0 +; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1 +; CHECK-NEXT: [[TMP4:%.*]] = insertvalue [[TMP0]] [[TMP2]], i1 [[TMP3]], 1 +; CHECK-NEXT: ret i64 [[TMP1]] +; entry: %uadd = tail call %0 @llvm.uadd.with.overflow.i64(i64 %a, i64 %b) %uadd.0 = extractvalue %0 %uadd, 0 @@ -11,11 +21,17 @@ entry: ret i64 %add1 } -; CHECK-LABEL: @test1( -; CHECK-NOT: add1 -; CHECK: ret - define i64 @test2(i64 %a, i64 %b) nounwind ssp { +; CHECK-LABEL: define i64 @test2( +; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP0:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[A]], i64 [[B]]) +; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i64, i1 } [[TMP0]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [[TMP0]] poison, i64 [[TMP1]], 0 +; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1 +; CHECK-NEXT: [[TMP4:%.*]] = insertvalue [[TMP0]] [[TMP2]], i1 [[TMP3]], 1 +; CHECK-NEXT: ret i64 [[TMP1]] +; entry: %usub = tail call %0 @llvm.usub.with.overflow.i64(i64 %a, i64 %b) %usub.0 = extractvalue %0 %usub, 0 @@ -23,11 +39,17 @@ entry: ret i64 %sub1 } -; CHECK-LABEL: @test2( -; CHECK-NOT: sub1 -; CHECK: ret - define i64 @test3(i64 %a, i64 %b) nounwind ssp { +; CHECK-LABEL: define i64 @test3( +; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP0:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[A]], i64 [[B]]) +; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i64, i1 } [[TMP0]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [[TMP0]] poison, i64 [[TMP1]], 0 +; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1 +; CHECK-NEXT: [[TMP4:%.*]] = insertvalue [[TMP0]] [[TMP2]], i1 [[TMP3]], 1 +; CHECK-NEXT: ret i64 [[TMP1]] +; entry: %umul = tail call %0 @llvm.umul.with.overflow.i64(i64 %a, i64 %b) %umul.0 = extractvalue %0 %umul, 0 @@ -35,11 +57,17 @@ entry: ret i64 %mul1 } -; CHECK-LABEL: @test3( -; CHECK-NOT: mul1 -; CHECK: ret - define i64 @test4(i64 %a, i64 %b) nounwind ssp { +; CHECK-LABEL: define i64 @test4( +; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP0:%.*]] = call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 [[A]], i64 [[B]]) +; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i64, i1 } [[TMP0]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [[TMP0]] poison, i64 [[TMP1]], 0 +; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1 +; CHECK-NEXT: [[TMP4:%.*]] = insertvalue [[TMP0]] [[TMP2]], i1 [[TMP3]], 1 +; CHECK-NEXT: ret i64 [[TMP1]] +; entry: %sadd = tail call %0 @llvm.sadd.with.overflow.i64(i64 %a, i64 %b) %sadd.0 = extractvalue %0 %sadd, 0 @@ -47,11 +75,17 @@ entry: ret i64 %add1 } -; CHECK-LABEL: @test4( -; CHECK-NOT: add1 -; CHECK: ret - define i64 @test5(i64 %a, i64 %b) nounwind ssp { +; CHECK-LABEL: define i64 @test5( +; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP0:%.*]] = call { i64, i1 } @llvm.ssub.with.overflow.i64(i64 [[A]], i64 [[B]]) +; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i64, i1 } [[TMP0]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [[TMP0]] poison, i64 [[TMP1]], 0 +; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1 +; CHECK-NEXT: [[TMP4:%.*]] = insertvalue [[TMP0]] [[TMP2]], i1 [[TMP3]], 1 +; CHECK-NEXT: ret i64 [[TMP1]] +; entry: %ssub = tail call %0 @llvm.ssub.with.overflow.i64(i64 %a, i64 %b) %ssub.0 = extractvalue %0 %ssub, 0 @@ -59,11 +93,17 @@ entry: ret i64 %sub1 } -; CHECK-LABEL: @test5( -; CHECK-NOT: sub1 -; CHECK: ret - define i64 @test6(i64 %a, i64 %b) nounwind ssp { +; CHECK-LABEL: define i64 @test6( +; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP0:%.*]] = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 [[A]], i64 [[B]]) +; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i64, i1 } [[TMP0]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [[TMP0]] poison, i64 [[TMP1]], 0 +; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1 +; CHECK-NEXT: [[TMP4:%.*]] = insertvalue [[TMP0]] [[TMP2]], i1 [[TMP3]], 1 +; CHECK-NEXT: ret i64 [[TMP1]] +; entry: %smul = tail call %0 @llvm.smul.with.overflow.i64(i64 %a, i64 %b) %smul.0 = extractvalue %0 %smul, 0 @@ -71,10 +111,6 @@ entry: ret i64 %mul1 } -; CHECK-LABEL: @test6( -; CHECK-NOT: mul1 -; CHECK: ret - declare void @exit(i32) noreturn declare %0 @llvm.uadd.with.overflow.i64(i64, i64) nounwind readnone declare %0 @llvm.usub.with.overflow.i64(i64, i64) nounwind readnone @@ -82,4 +118,3 @@ declare %0 @llvm.umul.with.overflow.i64(i64, i64) nounwind readnone declare %0 @llvm.sadd.with.overflow.i64(i64, i64) nounwind readnone declare %0 @llvm.ssub.with.overflow.i64(i64, i64) nounwind readnone declare %0 @llvm.smul.with.overflow.i64(i64, i64) nounwind readnone - diff --git a/llvm/test/Transforms/GVN/2011-09-07-TypeIdFor.ll b/llvm/test/Transforms/GVN/2011-09-07-TypeIdFor.ll index 01cc3164..52e6a8e 100644 --- a/llvm/test/Transforms/GVN/2011-09-07-TypeIdFor.ll +++ b/llvm/test/Transforms/GVN/2011-09-07-TypeIdFor.ll @@ -1,4 +1,6 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt < %s -passes=gvn -S | FileCheck %s + %struct.__fundamental_type_info_pseudo = type { %struct.__type_info_pseudo } %struct.__type_info_pseudo = type { ptr, ptr } @@ -18,26 +20,70 @@ declare void @__cxa_end_catch() declare i32 @__gxx_personality_v0(i32, i64, ptr, ptr) define void @_Z3foov() uwtable personality ptr @__gxx_personality_v0 { +; CHECK-LABEL: define void @_Z3foov( +; CHECK-SAME: ) #[[ATTR1:[0-9]+]] personality ptr @__gxx_personality_v0 { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: invoke void @_Z4barv() +; CHECK-NEXT: to label %[[RETURN:.*]] unwind label %[[LPAD:.*]] +; CHECK: [[LPAD]]: +; CHECK-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 } +; CHECK-NEXT: catch ptr @_ZTIi +; CHECK-NEXT: catch ptr @_ZTIb +; CHECK-NEXT: catch ptr @_ZTIi +; CHECK-NEXT: catch ptr @_ZTIb +; CHECK-NEXT: [[EXC_PTR2_I:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0 +; CHECK-NEXT: [[FILTER3_I:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1 +; CHECK-NEXT: [[TYPEID_I:%.*]] = tail call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[FILTER3_I]], [[TYPEID_I]] +; CHECK-NEXT: br i1 [[TMP1]], label %[[PPAD:.*]], label %[[NEXT:.*]] +; CHECK: [[NEXT]]: +; CHECK-NEXT: [[TYPEID1_I:%.*]] = tail call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIb) +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[FILTER3_I]], [[TYPEID1_I]] +; CHECK-NEXT: br i1 [[TMP2]], label %[[PPAD2:.*]], label %[[NEXT2:.*]] +; CHECK: [[PPAD]]: +; CHECK-NEXT: [[TMP3:%.*]] = tail call ptr @__cxa_begin_catch(ptr [[EXC_PTR2_I]]) #[[ATTR0:[0-9]+]] +; CHECK-NEXT: tail call void @__cxa_end_catch() #[[ATTR0]] +; CHECK-NEXT: br label %[[RETURN]] +; CHECK: [[PPAD2]]: +; CHECK-NEXT: [[D_2073_5_I:%.*]] = tail call ptr @__cxa_begin_catch(ptr [[EXC_PTR2_I]]) #[[ATTR0]] +; CHECK-NEXT: tail call void @__cxa_end_catch() #[[ATTR0]] +; CHECK-NEXT: br label %[[RETURN]] +; CHECK: [[NEXT2]]: +; CHECK-NEXT: call void @_Z7cleanupv() +; CHECK-NEXT: br i1 false, label %[[PPAD3:.*]], label %[[NEXT3:.*]] +; CHECK: [[NEXT3]]: +; CHECK-NEXT: br i1 false, label %[[PPAD4:.*]], label %[[UNWIND:.*]] +; CHECK: [[UNWIND]]: +; CHECK-NEXT: resume { ptr, i32 } [[TMP0]] +; CHECK: [[PPAD3]]: +; CHECK-NEXT: [[TMP4:%.*]] = tail call ptr @__cxa_begin_catch(ptr [[EXC_PTR2_I]]) #[[ATTR0]] +; CHECK-NEXT: tail call void @__cxa_end_catch() #[[ATTR0]] +; CHECK-NEXT: br label %[[RETURN]] +; CHECK: [[PPAD4]]: +; CHECK-NEXT: [[D_2080_5:%.*]] = tail call ptr @__cxa_begin_catch(ptr [[EXC_PTR2_I]]) #[[ATTR0]] +; CHECK-NEXT: tail call void @__cxa_end_catch() #[[ATTR0]] +; CHECK-NEXT: br label %[[RETURN]] +; CHECK: [[RETURN]]: +; CHECK-NEXT: ret void +; entry: invoke void @_Z4barv() - to label %return unwind label %lpad + to label %return unwind label %lpad lpad: ; preds = %entry %0 = landingpad { ptr, i32 } - catch ptr @_ZTIi - catch ptr @_ZTIb - catch ptr @_ZTIi - catch ptr @_ZTIb + catch ptr @_ZTIi + catch ptr @_ZTIb + catch ptr @_ZTIi + catch ptr @_ZTIb %exc_ptr2.i = extractvalue { ptr, i32 } %0, 0 %filter3.i = extractvalue { ptr, i32 } %0, 1 %typeid.i = tail call i32 @llvm.eh.typeid.for(ptr @_ZTIi) -; CHECK: call i32 @llvm.eh.typeid.for %1 = icmp eq i32 %filter3.i, %typeid.i br i1 %1, label %ppad, label %next next: ; preds = %lpad %typeid1.i = tail call i32 @llvm.eh.typeid.for(ptr @_ZTIb) -; CHECK: call i32 @llvm.eh.typeid.for %2 = icmp eq i32 %filter3.i, %typeid1.i br i1 %2, label %ppad2, label %next2 @@ -54,7 +100,6 @@ ppad2: ; preds = %next next2: ; preds = %next call void @_Z7cleanupv() %typeid = tail call i32 @llvm.eh.typeid.for(ptr @_ZTIi) -; CHECK-NOT: call i32 @llvm.eh.typeid.for %4 = icmp eq i32 %filter3.i, %typeid br i1 %4, label %ppad3, label %next3 diff --git a/llvm/test/Transforms/GVN/2012-05-22-PreCrash.ll b/llvm/test/Transforms/GVN/2012-05-22-PreCrash.ll index 28b7178..205dff7 100644 --- a/llvm/test/Transforms/GVN/2012-05-22-PreCrash.ll +++ b/llvm/test/Transforms/GVN/2012-05-22-PreCrash.ll @@ -1,7 +1,35 @@ -; RUN: opt < %s -passes=gvn +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 +; RUN: opt < %s -passes=gvn -S | FileCheck %s + ; PR12858 define void @fn5(i16 signext %p1, i8 signext %p2, i1 %arg) nounwind uwtable { +; CHECK-LABEL: define void @fn5( +; CHECK-SAME: i16 signext [[P1:%.*]], i8 signext [[P2:%.*]], i1 [[ARG:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: br i1 [[ARG]], label %[[IF_ELSE:.*]], label %[[IF_THEN:.*]] +; CHECK: [[IF_THEN]]: +; CHECK-NEXT: [[DOTPRE:%.*]] = sext i16 [[P1]] to i32 +; CHECK-NEXT: br label %[[IF_END:.*]] +; CHECK: [[IF_ELSE]]: +; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[P1]] to i32 +; CHECK-NEXT: br label %[[IF_END]] +; CHECK: [[IF_END]]: +; CHECK-NEXT: [[CONV1_PRE_PHI:%.*]] = phi i32 [ [[CONV]], %[[IF_ELSE]] ], [ [[DOTPRE]], %[[IF_THEN]] ] +; CHECK-NEXT: br i1 [[ARG]], label %[[IF_THEN3:.*]], label %[[IF_ELSE4:.*]] +; CHECK: [[IF_THEN3]]: +; CHECK-NEXT: [[DOTPRE1:%.*]] = sext i8 [[P2]] to i32 +; CHECK-NEXT: br label %[[IF_END12:.*]] +; CHECK: [[IF_ELSE4]]: +; CHECK-NEXT: [[CONV7:%.*]] = sext i8 [[P2]] to i32 +; CHECK-NEXT: [[CMP8:%.*]] = icmp eq i32 [[CONV1_PRE_PHI]], [[CONV7]] +; CHECK-NEXT: br i1 [[CMP8]], label %[[IF_THEN10:.*]], label %[[IF_END12]] +; CHECK: [[IF_THEN10]]: +; CHECK-NEXT: br label %[[IF_END12]] +; CHECK: [[IF_END12]]: +; CHECK-NEXT: [[CONV13_PRE_PHI:%.*]] = phi i32 [ [[CONV7]], %[[IF_THEN10]] ], [ [[CONV7]], %[[IF_ELSE4]] ], [ [[DOTPRE1]], %[[IF_THEN3]] ] +; CHECK-NEXT: ret void +; entry: br i1 %arg, label %if.else, label %if.then diff --git a/llvm/test/Transforms/GVN/2016-08-30-MaskedScatterGather-inseltpoison.ll b/llvm/test/Transforms/GVN/2016-08-30-MaskedScatterGather-inseltpoison.ll index c2b123b..aeb3de9 100644 --- a/llvm/test/Transforms/GVN/2016-08-30-MaskedScatterGather-inseltpoison.ll +++ b/llvm/test/Transforms/GVN/2016-08-30-MaskedScatterGather-inseltpoison.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt < %s -passes=gvn -S | FileCheck %s declare void @llvm.masked.scatter.v2i32.v2p0(<2 x i32> , <2 x ptr> , i32 , <2 x i1> ) @@ -5,14 +6,29 @@ declare <2 x i32> @llvm.masked.gather.v2i32.v2p0(<2 x ptr>, i32, <2 x i1>, <2 x ; This test ensures that masked scatter and gather operations, which take vectors of pointers, ; do not have pointer aliasing ignored when being processed. -; No scatter/gather calls should end up eliminated -; CHECK: llvm.masked.gather -; CHECK: llvm.masked.gather -; CHECK: llvm.masked.scatter -; CHECK: llvm.masked.gather -; CHECK: llvm.masked.scatter -; CHECK: llvm.masked.gather +; No scatter/gather calls should end up eliminated. + define spir_kernel void @test(<2 x ptr> %in1, <2 x ptr> %in2, ptr %out) { +; CHECK-LABEL: define spir_kernel void @test( +; CHECK-SAME: <2 x ptr> [[IN1:%.*]], <2 x ptr> [[IN2:%.*]], ptr [[OUT:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP_0:%.*]] = alloca i32, align 4 +; CHECK-NEXT: [[TMP_1:%.*]] = alloca i32, align 4 +; CHECK-NEXT: [[TMP_I:%.*]] = insertelement <2 x ptr> poison, ptr [[TMP_0]], i32 0 +; CHECK-NEXT: [[TMP:%.*]] = insertelement <2 x ptr> [[TMP_I]], ptr [[TMP_1]], i32 1 +; CHECK-NEXT: [[IN1_V:%.*]] = call <2 x i32> @llvm.masked.gather.v2i32.v2p0(<2 x ptr> [[IN1]], i32 1, <2 x i1> splat (i1 true), <2 x i32> undef) +; CHECK-NEXT: [[IN2_V:%.*]] = call <2 x i32> @llvm.masked.gather.v2i32.v2p0(<2 x ptr> [[IN2]], i32 1, <2 x i1> splat (i1 true), <2 x i32> undef) +; CHECK-NEXT: call void @llvm.masked.scatter.v2i32.v2p0(<2 x i32> [[IN1_V]], <2 x ptr> [[TMP]], i32 1, <2 x i1> splat (i1 true)) +; CHECK-NEXT: [[TMP_V_0:%.*]] = call <2 x i32> @llvm.masked.gather.v2i32.v2p0(<2 x ptr> [[TMP]], i32 1, <2 x i1> splat (i1 true), <2 x i32> undef) +; CHECK-NEXT: call void @llvm.masked.scatter.v2i32.v2p0(<2 x i32> [[IN2_V]], <2 x ptr> [[TMP]], i32 1, <2 x i1> splat (i1 true)) +; CHECK-NEXT: [[TMP_V_1:%.*]] = call <2 x i32> @llvm.masked.gather.v2i32.v2p0(<2 x ptr> [[TMP]], i32 1, <2 x i1> splat (i1 true), <2 x i32> undef) +; CHECK-NEXT: [[TMP_V_1_0:%.*]] = extractelement <2 x i32> [[TMP_V_1]], i32 0 +; CHECK-NEXT: [[TMP_V_1_1:%.*]] = extractelement <2 x i32> [[TMP_V_1]], i32 1 +; CHECK-NEXT: store i32 [[TMP_V_1_0]], ptr [[OUT]], align 4 +; CHECK-NEXT: [[OUT_1:%.*]] = getelementptr i32, ptr [[OUT]], i32 1 +; CHECK-NEXT: store i32 [[TMP_V_1_1]], ptr [[OUT_1]], align 4 +; CHECK-NEXT: ret void +; entry: ; Just some temporary storage %tmp.0 = alloca i32 diff --git a/llvm/test/Transforms/GVN/2016-08-30-MaskedScatterGather.ll b/llvm/test/Transforms/GVN/2016-08-30-MaskedScatterGather.ll index e18f388..4c00060 100644 --- a/llvm/test/Transforms/GVN/2016-08-30-MaskedScatterGather.ll +++ b/llvm/test/Transforms/GVN/2016-08-30-MaskedScatterGather.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt < %s -passes=gvn -S | FileCheck %s declare void @llvm.masked.scatter.v2i32.v2p0(<2 x i32> , <2 x ptr> , i32 , <2 x i1> ) @@ -5,14 +6,29 @@ declare <2 x i32> @llvm.masked.gather.v2i32.v2p0(<2 x ptr>, i32, <2 x i1>, <2 x ; This test ensures that masked scatter and gather operations, which take vectors of pointers, ; do not have pointer aliasing ignored when being processed. -; No scatter/gather calls should end up eliminated -; CHECK: llvm.masked.gather -; CHECK: llvm.masked.gather -; CHECK: llvm.masked.scatter -; CHECK: llvm.masked.gather -; CHECK: llvm.masked.scatter -; CHECK: llvm.masked.gather +; No scatter/gather calls should end up eliminated. + define spir_kernel void @test(<2 x ptr> %in1, <2 x ptr> %in2, ptr %out) { +; CHECK-LABEL: define spir_kernel void @test( +; CHECK-SAME: <2 x ptr> [[IN1:%.*]], <2 x ptr> [[IN2:%.*]], ptr [[OUT:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP_0:%.*]] = alloca i32, align 4 +; CHECK-NEXT: [[TMP_1:%.*]] = alloca i32, align 4 +; CHECK-NEXT: [[TMP_I:%.*]] = insertelement <2 x ptr> undef, ptr [[TMP_0]], i32 0 +; CHECK-NEXT: [[TMP:%.*]] = insertelement <2 x ptr> [[TMP_I]], ptr [[TMP_1]], i32 1 +; CHECK-NEXT: [[IN1_V:%.*]] = call <2 x i32> @llvm.masked.gather.v2i32.v2p0(<2 x ptr> [[IN1]], i32 1, <2 x i1> splat (i1 true), <2 x i32> undef) +; CHECK-NEXT: [[IN2_V:%.*]] = call <2 x i32> @llvm.masked.gather.v2i32.v2p0(<2 x ptr> [[IN2]], i32 1, <2 x i1> splat (i1 true), <2 x i32> undef) +; CHECK-NEXT: call void @llvm.masked.scatter.v2i32.v2p0(<2 x i32> [[IN1_V]], <2 x ptr> [[TMP]], i32 1, <2 x i1> splat (i1 true)) +; CHECK-NEXT: [[TMP_V_0:%.*]] = call <2 x i32> @llvm.masked.gather.v2i32.v2p0(<2 x ptr> [[TMP]], i32 1, <2 x i1> splat (i1 true), <2 x i32> undef) +; CHECK-NEXT: call void @llvm.masked.scatter.v2i32.v2p0(<2 x i32> [[IN2_V]], <2 x ptr> [[TMP]], i32 1, <2 x i1> splat (i1 true)) +; CHECK-NEXT: [[TMP_V_1:%.*]] = call <2 x i32> @llvm.masked.gather.v2i32.v2p0(<2 x ptr> [[TMP]], i32 1, <2 x i1> splat (i1 true), <2 x i32> undef) +; CHECK-NEXT: [[TMP_V_1_0:%.*]] = extractelement <2 x i32> [[TMP_V_1]], i32 0 +; CHECK-NEXT: [[TMP_V_1_1:%.*]] = extractelement <2 x i32> [[TMP_V_1]], i32 1 +; CHECK-NEXT: store i32 [[TMP_V_1_0]], ptr [[OUT]], align 4 +; CHECK-NEXT: [[OUT_1:%.*]] = getelementptr i32, ptr [[OUT]], i32 1 +; CHECK-NEXT: store i32 [[TMP_V_1_1]], ptr [[OUT_1]], align 4 +; CHECK-NEXT: ret void +; entry: ; Just some temporary storage %tmp.0 = alloca i32 diff --git a/llvm/test/Transforms/GVN/MemdepMiscompile.ll b/llvm/test/Transforms/GVN/MemdepMiscompile.ll index cb9b011..7c8accb 100644 --- a/llvm/test/Transforms/GVN/MemdepMiscompile.ll +++ b/llvm/test/Transforms/GVN/MemdepMiscompile.ll @@ -1,4 +1,6 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt < %s -passes=gvn -S | FileCheck %s + target datalayout = "e-p:64:64:64-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" target triple = "x86_64-apple-macosx10.7.0" @@ -7,14 +9,38 @@ target triple = "x86_64-apple-macosx10.7.0" ; Make sure we do not replace load %shouldExit in while.cond.backedge ; with a phi node where the value from while.body is 0. define i32 @test() nounwind ssp { +; CHECK-LABEL: define i32 @test( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[SHOULDEXIT:%.*]] = alloca i32, align 4 +; CHECK-NEXT: [[TASKSIDLE:%.*]] = alloca i32, align 4 +; CHECK-NEXT: store i32 0, ptr [[SHOULDEXIT]], align 4 +; CHECK-NEXT: store i32 0, ptr [[TASKSIDLE]], align 4 +; CHECK-NEXT: call void @CTestInitialize(ptr [[TASKSIDLE]]) #[[ATTR1:[0-9]+]] +; CHECK-NEXT: br i1 true, label %[[WHILE_BODY_LR_PH:.*]], label %[[ENTRY_WHILE_END_CRIT_EDGE:.*]] +; CHECK: [[ENTRY_WHILE_END_CRIT_EDGE]]: +; CHECK-NEXT: br label %[[WHILE_END:.*]] +; CHECK: [[WHILE_BODY_LR_PH]]: +; CHECK-NEXT: br label %[[WHILE_BODY:.*]] +; CHECK: [[WHILE_BODY]]: +; CHECK-NEXT: call void @RunInMode(i32 100) #[[ATTR1]] +; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[TASKSIDLE]], align 4 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[TMP0]], 0 +; CHECK-NEXT: br i1 [[TOBOOL]], label %[[WHILE_COND_BACKEDGE:.*]], label %[[IF_THEN:.*]] +; CHECK: [[IF_THEN]]: +; CHECK-NEXT: store i32 0, ptr [[TASKSIDLE]], align 4 +; CHECK-NEXT: call void @TimerCreate(ptr [[SHOULDEXIT]]) #[[ATTR1]] +; CHECK-NEXT: br label %[[WHILE_COND_BACKEDGE]] +; CHECK: [[WHILE_COND_BACKEDGE]]: +; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[SHOULDEXIT]], align 4 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 0 +; CHECK-NEXT: br i1 [[CMP]], label %[[WHILE_BODY]], label %[[WHILE_COND_WHILE_END_CRIT_EDGE:.*]] +; CHECK: [[WHILE_COND_WHILE_END_CRIT_EDGE]]: +; CHECK-NEXT: br label %[[WHILE_END]] +; CHECK: [[WHILE_END]]: +; CHECK-NEXT: ret i32 0 +; entry: -; CHECK: test() -; CHECK: while.body: -; CHECK: call void @RunInMode -; CHECK: br i1 %tobool, label %while.cond.backedge, label %if.then -; CHECK: while.cond.backedge: -; CHECK: load i32, ptr %shouldExit -; CHECK: br i1 %cmp, label %while.body %shouldExit = alloca i32, align 4 %tasksIdle = alloca i32, align 4 store i32 0, ptr %shouldExit, align 4 diff --git a/llvm/test/Transforms/GVN/basic-undef-test.ll b/llvm/test/Transforms/GVN/basic-undef-test.ll index d12c3db..459ef25 100644 --- a/llvm/test/Transforms/GVN/basic-undef-test.ll +++ b/llvm/test/Transforms/GVN/basic-undef-test.ll @@ -1,15 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=gvn -S < %s | FileCheck %s -; ModuleID = 'test3.ll' + target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +; RLE over the second load. define i32 @main(ptr %foo) { +; CHECK-LABEL: define i32 @main( +; CHECK-SAME: ptr [[FOO:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[FOO]], align 4 +; CHECK-NEXT: store i32 5, ptr undef, align 4 +; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], [[TMP0]] +; CHECK-NEXT: ret i32 [[TMP1]] +; entry: -; CHECK: load i32, ptr %foo, align 4 %0 = load i32, ptr %foo, align 4 store i32 5, ptr undef, align 4 -; CHECK-NOT: load i32, ptr %foo, align 4 %1 = load i32, ptr %foo, align 4 -; CHECK: add i32 %0, %0 %2 = add i32 %0, %1 ret i32 %2 } diff --git a/llvm/test/Transforms/GVN/bitcast-of-call.ll b/llvm/test/Transforms/GVN/bitcast-of-call.ll index 6c4e8d2..3f40085 100644 --- a/llvm/test/Transforms/GVN/bitcast-of-call.ll +++ b/llvm/test/Transforms/GVN/bitcast-of-call.ll @@ -1,13 +1,20 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt < %s -passes=gvn -S | FileCheck %s + ; PR2213 define ptr @f(ptr %x) { +; CHECK-LABEL: define ptr @f( +; CHECK-SAME: ptr [[X:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP:%.*]] = call ptr @m(i32 12) +; CHECK-NEXT: ret ptr [[TMP]] +; entry: - %tmp = call ptr @m( i32 12 ) ; <ptr> [#uses=2] - %tmp1 = bitcast ptr %tmp to ptr ; <ptr> [#uses=0] - %tmp2 = bitcast ptr %tmp to ptr ; <ptr> [#uses=0] -; CHECK-NOT: %tmp2 - ret ptr %tmp2 + %tmp = call ptr @m(i32 12) ; <ptr> [#uses=2] + %tmp1 = bitcast ptr %tmp to ptr ; <ptr> [#uses=0] + %tmp2 = bitcast ptr %tmp to ptr ; <ptr> [#uses=0] + ret ptr %tmp2 } declare ptr @m(i32) diff --git a/llvm/test/Transforms/GVN/br-identical.ll b/llvm/test/Transforms/GVN/br-identical.ll index 9997e01..5266889 100644 --- a/llvm/test/Transforms/GVN/br-identical.ll +++ b/llvm/test/Transforms/GVN/br-identical.ll @@ -1,8 +1,32 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=gvn -S -o - %s | FileCheck %s ; If a branch has two identical successors, we cannot declare either dead. - define void @widget(i1 %p) { +; CHECK-LABEL: define void @widget( +; CHECK-SAME: i1 [[P:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: br label %[[BB2:.*]] +; CHECK: [[BB2]]: +; CHECK-NEXT: [[T1:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[T2:%.*]], %[[BB7:.*]] ] +; CHECK-NEXT: [[T2]] = add i64 [[T1]], 1 +; CHECK-NEXT: [[T3:%.*]] = icmp ult i64 0, [[T2]] +; CHECK-NEXT: br i1 [[T3]], label %[[BB3:.*]], label %[[BB4:.*]] +; CHECK: [[BB3]]: +; CHECK-NEXT: [[T4:%.*]] = call i64 @f() +; CHECK-NEXT: br label %[[BB4]] +; CHECK: [[BB4]]: +; CHECK-NEXT: [[FOO:%.*]] = phi i64 [ [[T4]], %[[BB3]] ], [ 0, %[[BB2]] ] +; CHECK-NEXT: br i1 [[P]], label %[[BB5:.*]], label %[[BB6:.*]] +; CHECK: [[BB5]]: +; CHECK-NEXT: br i1 true, label %[[BB7]], label %[[BB7]] +; CHECK: [[BB6]]: +; CHECK-NEXT: br i1 true, label %[[BB7]], label %[[BB7]] +; CHECK: [[BB7]]: +; CHECK-NEXT: br i1 [[P]], label %[[BB2]], label %[[BB8:.*]] +; CHECK: [[BB8]]: +; CHECK-NEXT: ret void +; entry: br label %bb2 @@ -17,7 +41,6 @@ bb3: br label %bb4 bb4: - ; CHECK-NOT: phi {{.*}} undef %foo = phi i64 [ %t4, %bb3 ], [ 0, %bb2 ] br i1 %p, label %bb5, label %bb6 diff --git a/llvm/test/Transforms/GVN/calls-nonlocal.ll b/llvm/test/Transforms/GVN/calls-nonlocal.ll index e891545..4340d57 100644 --- a/llvm/test/Transforms/GVN/calls-nonlocal.ll +++ b/llvm/test/Transforms/GVN/calls-nonlocal.ll @@ -1,75 +1,78 @@ -; Two occurrences of strlen should be zapped. +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt < %s -passes=gvn -S | FileCheck %s + +; Two occurrences of strlen should be zapped. target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" target triple = "i386-apple-darwin9" define i32 @test(i32 %g, ptr %P) nounwind { +; CHECK-LABEL: define i32 @test( +; CHECK-SAME: i32 [[G:%.*]], ptr [[P:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP2:%.*]] = call i32 @strlen(ptr [[P]]) #[[ATTR1:[0-9]+]] +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 100 +; CHECK-NEXT: [[TMP34:%.*]] = zext i1 [[TMP3]] to i8 +; CHECK-NEXT: br i1 [[TMP3]], label %[[BB:.*]], label %[[BB6:.*]] +; CHECK: [[BB]]: +; CHECK-NEXT: br label %[[BB27:.*]] +; CHECK: [[BB6]]: +; CHECK-NEXT: [[TMP8:%.*]] = add i32 [[G]], 42 +; CHECK-NEXT: br i1 false, label %[[BB14:.*]], label %[[BB16:.*]] +; CHECK: [[BB14]]: +; CHECK-NEXT: br label %[[BB27]] +; CHECK: [[BB16]]: +; CHECK-NEXT: [[TMP18:%.*]] = mul i32 [[TMP8]], 2 +; CHECK-NEXT: br i1 false, label %[[BB24:.*]], label %[[BB26:.*]] +; CHECK: [[BB24]]: +; CHECK-NEXT: br label %[[BB27]] +; CHECK: [[BB26]]: +; CHECK-NEXT: br label %[[BB27]] +; CHECK: [[BB27]]: +; CHECK-NEXT: [[TMP_0:%.*]] = phi i32 [ 11, %[[BB26]] ], [ poison, %[[BB24]] ], [ poison, %[[BB14]] ], [ [[G]], %[[BB]] ] +; CHECK-NEXT: ret i32 [[TMP_0]] +; entry: - %tmp2 = call i32 @strlen( ptr %P ) nounwind readonly ; <i32> [#uses=1] - %tmp3 = icmp eq i32 %tmp2, 100 ; <i1> [#uses=1] - %tmp34 = zext i1 %tmp3 to i8 ; <i8> [#uses=1] - %toBool = icmp ne i8 %tmp34, 0 ; <i1> [#uses=1] - br i1 %toBool, label %bb, label %bb6 + %tmp2 = call i32 @strlen( ptr %P ) nounwind readonly ; <i32> [#uses=1] + %tmp3 = icmp eq i32 %tmp2, 100 ; <i1> [#uses=1] + %tmp34 = zext i1 %tmp3 to i8 ; <i8> [#uses=1] + %toBool = icmp ne i8 %tmp34, 0 ; <i1> [#uses=1] + br i1 %toBool, label %bb, label %bb6 bb: ; preds = %entry - br label %bb27 + br label %bb27 bb6: ; preds = %entry - %tmp8 = add i32 %g, 42 ; <i32> [#uses=2] - %tmp10 = call i32 @strlen( ptr %P ) nounwind readonly ; <i32> [#uses=1] - %tmp11 = icmp eq i32 %tmp10, 100 ; <i1> [#uses=1] - %tmp1112 = zext i1 %tmp11 to i8 ; <i8> [#uses=1] - %toBool13 = icmp ne i8 %tmp1112, 0 ; <i1> [#uses=1] - br i1 %toBool13, label %bb14, label %bb16 + %tmp8 = add i32 %g, 42 ; <i32> [#uses=2] + %tmp10 = call i32 @strlen( ptr %P ) nounwind readonly ; <i32> [#uses=1] + %tmp11 = icmp eq i32 %tmp10, 100 ; <i1> [#uses=1] + %tmp1112 = zext i1 %tmp11 to i8 ; <i8> [#uses=1] + %toBool13 = icmp ne i8 %tmp1112, 0 ; <i1> [#uses=1] + br i1 %toBool13, label %bb14, label %bb16 bb14: ; preds = %bb6 - br label %bb27 + br label %bb27 bb16: ; preds = %bb6 - %tmp18 = mul i32 %tmp8, 2 ; <i32> [#uses=1] - %tmp20 = call i32 @strlen( ptr %P ) nounwind readonly ; <i32> [#uses=1] - %tmp21 = icmp eq i32 %tmp20, 100 ; <i1> [#uses=1] - %tmp2122 = zext i1 %tmp21 to i8 ; <i8> [#uses=1] - %toBool23 = icmp ne i8 %tmp2122, 0 ; <i1> [#uses=1] - br i1 %toBool23, label %bb24, label %bb26 + %tmp18 = mul i32 %tmp8, 2 ; <i32> [#uses=1] + %tmp20 = call i32 @strlen( ptr %P ) nounwind readonly ; <i32> [#uses=1] + %tmp21 = icmp eq i32 %tmp20, 100 ; <i1> [#uses=1] + %tmp2122 = zext i1 %tmp21 to i8 ; <i8> [#uses=1] + %toBool23 = icmp ne i8 %tmp2122, 0 ; <i1> [#uses=1] + br i1 %toBool23, label %bb24, label %bb26 bb24: ; preds = %bb16 - br label %bb27 + br label %bb27 bb26: ; preds = %bb16 - br label %bb27 + br label %bb27 bb27: ; preds = %bb26, %bb24, %bb14, %bb - %tmp.0 = phi i32 [ 11, %bb26 ], [ %tmp18, %bb24 ], [ %tmp8, %bb14 ], [ %g, %bb ] ; <i32> [#uses=1] - br label %return + %tmp.0 = phi i32 [ 11, %bb26 ], [ %tmp18, %bb24 ], [ %tmp8, %bb14 ], [ %g, %bb ] ; <i32> [#uses=1] + br label %return return: ; preds = %bb27 - ret i32 %tmp.0 + ret i32 %tmp.0 } -; CHECK: define i32 @test(i32 %g, ptr %P) #0 { -; CHECK: entry: -; CHECK: %tmp2 = call i32 @strlen(ptr %P) #1 -; CHECK: %tmp3 = icmp eq i32 %tmp2, 100 -; CHECK: %tmp34 = zext i1 %tmp3 to i8 -; CHECK: br i1 %tmp3, label %bb, label %bb6 -; CHECK: bb: -; CHECK: br label %bb27 -; CHECK: bb6: -; CHECK: %tmp8 = add i32 %g, 42 -; CHECK: br i1 false, label %bb14, label %bb16 -; CHECK: bb14: -; CHECK: br label %bb27 -; CHECK: bb16: -; CHECK: %tmp18 = mul i32 %tmp8, 2 -; CHECK: br i1 false, label %bb24, label %bb26 -; CHECK: bb24: -; CHECK: br label %bb27 -; CHECK: bb26: -; CHECK: br label %bb27 -; CHECK: bb27: -; CHECK: %tmp.0 = phi i32 [ 11, %bb26 ], [ poison, %bb24 ], [ poison, %bb14 ], [ %g, %bb ] -; CHECK: ret i32 %tmp.0 -; CHECK: } -declare i32 @strlen(ptr) nounwind readonly +declare i32 @strlen(ptr) nounwind readonly diff --git a/llvm/test/Transforms/GVN/calls-readonly.ll b/llvm/test/Transforms/GVN/calls-readonly.ll index b4855e4..2fb5621 100644 --- a/llvm/test/Transforms/GVN/calls-readonly.ll +++ b/llvm/test/Transforms/GVN/calls-readonly.ll @@ -1,10 +1,28 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt < %s -passes=gvn -S | FileCheck %s + ; Should delete the second call to strlen even though the intervening strchr call exists. target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" target triple = "i386-apple-darwin7" define ptr @test(ptr %P, ptr %Q, i32 %x, i32 %y) nounwind readonly { +; CHECK-LABEL: define ptr @test( +; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @strlen(ptr [[P]]), !prof [[PROF0:![0-9]+]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 0 +; CHECK-NEXT: br i1 [[TMP1]], label %[[BB:.*]], label %[[BB1:.*]] +; CHECK: [[BB]]: +; CHECK-NEXT: [[TMP2:%.*]] = sdiv i32 [[X]], [[Y]] +; CHECK-NEXT: br label %[[BB1]] +; CHECK: [[BB1]]: +; CHECK-NEXT: [[X_ADDR_0:%.*]] = phi i32 [ [[TMP2]], %[[BB]] ], [ [[X]], %[[ENTRY]] ] +; CHECK-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr [[Q]], i32 97) +; CHECK-NEXT: [[TMP4:%.*]] = add i32 [[X_ADDR_0]], [[TMP0]] +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP3]], i32 [[X_ADDR_0]] +; CHECK-NEXT: ret ptr [[TMP5]] +; entry: %0 = tail call i32 @strlen(ptr %P), !prof !0 ; <i32> [#uses=2] %1 = icmp eq i32 %0, 0 ; <i1> [#uses=1] @@ -24,21 +42,6 @@ bb1: ; preds = %bb, %entry ret ptr %6 } -; CHECK: define ptr @test(ptr %P, ptr %Q, i32 %x, i32 %y) #0 { -; CHECK: entry: -; CHECK-NEXT: %0 = tail call i32 @strlen(ptr %P), !prof !0 -; CHECK-NEXT: %1 = icmp eq i32 %0, 0 -; CHECK-NEXT: br i1 %1, label %bb, label %bb1 -; CHECK: bb: -; CHECK-NEXT: %2 = sdiv i32 %x, %y -; CHECK-NEXT: br label %bb1 -; CHECK: bb1: -; CHECK-NEXT: %x_addr.0 = phi i32 [ %2, %bb ], [ %x, %entry ] -; CHECK-NEXT: %3 = tail call ptr @strchr(ptr %Q, i32 97) -; CHECK-NEXT: %4 = add i32 %x_addr.0, %0 -; CHECK-NEXT: %5 = getelementptr i8, ptr %3, i32 %x_addr.0 -; CHECK-NEXT: ret ptr %5 -; CHECK: } declare i32 @strlen(ptr) nounwind readonly @@ -46,3 +49,6 @@ declare ptr @strchr(ptr, i32) nounwind readonly !0 = !{!"branch_weights", i32 95} !1 = !{!"branch_weights", i32 95} +;. +; CHECK: [[PROF0]] = !{!"branch_weights", i64 190} +;. diff --git a/llvm/test/Transforms/GVN/cond_br.ll b/llvm/test/Transforms/GVN/cond_br.ll index fb84b62..10ee3a0 100644 --- a/llvm/test/Transforms/GVN/cond_br.ll +++ b/llvm/test/Transforms/GVN/cond_br.ll @@ -1,12 +1,25 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=gvn -S < %s | FileCheck %s + @y = external global i32 @z = external global i32 ; Function Attrs: nounwind ssp uwtable define void @foo(i32 %x) { -; CHECK: @foo(i32 %x) -; CHECK: %.pre = load i32, ptr @y -; CHECK: call void @bar(i32 %.pre) +; CHECK-LABEL: define void @foo( +; CHECK-SAME: i32 [[X:%.*]]) { +; CHECK-NEXT: [[DOTPRE:%.*]] = load i32, ptr @y, align 4 +; CHECK-NEXT: br i1 false, label %[[IF_THEN:.*]], label %[[ENTRY_IF_END_CRIT_EDGE:.*]] +; CHECK: [[ENTRY_IF_END_CRIT_EDGE]]: +; CHECK-NEXT: br label %[[IF_END:.*]] +; CHECK: [[IF_THEN]]: +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 3 +; CHECK-NEXT: store i32 [[ADD]], ptr @y, align 4 +; CHECK-NEXT: br label %[[IF_END]] +; CHECK: [[IF_END]]: +; CHECK-NEXT: tail call void @bar(i32 [[DOTPRE]]) +; CHECK-NEXT: ret void +; %t = sub i32 %x, %x %.pre = load i32, ptr @y, align 4 @@ -28,9 +41,22 @@ if.end: ; preds = %entry.if.end_crit_e } define void @foo2(i32 %x) { -; CHECK: @foo2(i32 %x) -; CHECK: %.pre = load i32, ptr @y -; CHECK: tail call void @bar(i32 %.pre) +; CHECK-LABEL: define void @foo2( +; CHECK-SAME: i32 [[X:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[DOTPRE:%.*]] = load i32, ptr @y, align 4 +; CHECK-NEXT: br i1 false, label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]] +; CHECK: [[IF_THEN]]: +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X]], 3 +; CHECK-NEXT: store i32 [[ADD]], ptr @y, align 4 +; CHECK-NEXT: br label %[[IF_END:.*]] +; CHECK: [[IF_ELSE]]: +; CHECK-NEXT: store i32 1, ptr @z, align 4 +; CHECK-NEXT: br label %[[IF_END]] +; CHECK: [[IF_END]]: +; CHECK-NEXT: tail call void @bar(i32 [[DOTPRE]]) +; CHECK-NEXT: ret void +; entry: %t = sub i32 %x, %x %.pre = load i32, ptr @y, align 4 diff --git a/llvm/test/Transforms/GVN/cond_br2.ll b/llvm/test/Transforms/GVN/cond_br2.ll index ff80328..6ceec95 100644 --- a/llvm/test/Transforms/GVN/cond_br2.ll +++ b/llvm/test/Transforms/GVN/cond_br2.ll @@ -1,4 +1,6 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=gvn -S < %s | FileCheck %s + target datalayout = "e-p:64:64:64-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" %"class.llvm::SmallVector" = type { %"class.llvm::SmallVectorImpl", [1 x %"union.llvm::SmallVectorBase::U"] } @@ -10,10 +12,77 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3 ; Function Attrs: ssp uwtable define void @_Z4testv() #0 personality ptr @__gxx_personality_v0 { -; CHECK: @_Z4testv() -; CHECK: invoke.cont: -; CHECK: br i1 true, label %new.notnull.i11, label %if.end.i14 -; CHECK: Retry.i10: +; CHECK-LABEL: define void @_Z4testv( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] personality ptr @__gxx_personality_v0 { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[SV:%.*]] = alloca %"class.llvm::SmallVector", align 16 +; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[SV]]) #[[ATTR4:[0-9]+]] +; CHECK-NEXT: [[FIRSTEL_I_I_I_I_I_I:%.*]] = getelementptr inbounds %"class.llvm::SmallVector", ptr [[SV]], i64 0, i32 0, i32 0, i32 0, i32 0, i32 3 +; CHECK-NEXT: store ptr [[FIRSTEL_I_I_I_I_I_I]], ptr [[SV]], align 16, !tbaa [[ANYPTR_TBAA0:![0-9]+]] +; CHECK-NEXT: [[ENDX_I_I_I_I_I_I:%.*]] = getelementptr inbounds %"class.llvm::SmallVector", ptr [[SV]], i64 0, i32 0, i32 0, i32 0, i32 0, i32 1 +; CHECK-NEXT: store ptr [[FIRSTEL_I_I_I_I_I_I]], ptr [[ENDX_I_I_I_I_I_I]], align 8, !tbaa [[ANYPTR_TBAA0]] +; CHECK-NEXT: [[CAPACITYX_I_I_I_I_I_I:%.*]] = getelementptr inbounds %"class.llvm::SmallVector", ptr [[SV]], i64 0, i32 0, i32 0, i32 0, i32 0, i32 2 +; CHECK-NEXT: [[ADD_PTR_I_I_I_I2_I_I:%.*]] = getelementptr inbounds %"union.llvm::SmallVectorBase::U", ptr [[FIRSTEL_I_I_I_I_I_I]], i64 2 +; CHECK-NEXT: store ptr [[ADD_PTR_I_I_I_I2_I_I]], ptr [[CAPACITYX_I_I_I_I_I_I]], align 16, !tbaa [[ANYPTR_TBAA0]] +; CHECK-NEXT: br i1 true, label %[[RETRY_I:.*]], label %[[IF_END_I:.*]] +; CHECK: [[RETRY_I]]: +; CHECK-NEXT: br i1 false, label %[[RETRY_I_INVOKE_CONT_CRIT_EDGE:.*]], label %[[NEW_NOTNULL_I:.*]] +; CHECK: [[RETRY_I_INVOKE_CONT_CRIT_EDGE]]: +; CHECK-NEXT: br label %[[INVOKE_CONT:.*]] +; CHECK: [[NEW_NOTNULL_I]]: +; CHECK-NEXT: store i32 1, ptr [[FIRSTEL_I_I_I_I_I_I]], align 4, !tbaa [[INT_TBAA4:![0-9]+]] +; CHECK-NEXT: br label %[[INVOKE_CONT]] +; CHECK: [[IF_END_I]]: +; CHECK-NEXT: invoke void @_ZN4llvm15SmallVectorBase8grow_podEmm(ptr [[SV]], i64 0, i64 4) +; CHECK-NEXT: to [[DOTNOEXC:label %.*]] unwind label %[[LPAD:.*]] +; CHECK: [[_NOEXC:.*:]] +; CHECK-NEXT: [[DOTPRE_I:%.*]] = load ptr, ptr [[ENDX_I_I_I_I_I_I]], align 8, !tbaa [[ANYPTR_TBAA0]] +; CHECK-NEXT: br label %[[RETRY_I]] +; CHECK: [[INVOKE_CONT]]: +; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[FIRSTEL_I_I_I_I_I_I]], i64 4 +; CHECK-NEXT: store ptr [[ADD_PTR_I]], ptr [[ENDX_I_I_I_I_I_I]], align 8, !tbaa [[ANYPTR_TBAA0]] +; CHECK-NEXT: br i1 true, label %[[NEW_NOTNULL_I11:.*]], label %[[IF_END_I14:.*]] +; CHECK: [[RETRY_I10:.*]]: +; CHECK-NEXT: [[DOTPRE_I13:%.*]] = load ptr, ptr [[ENDX_I_I_I_I_I_I]], align 8, !tbaa [[ANYPTR_TBAA0]] +; CHECK-NEXT: [[NEW_ISNULL_I9:%.*]] = icmp eq ptr [[DOTPRE_I13]], null +; CHECK-NEXT: br i1 [[NEW_ISNULL_I9]], label %[[RETRY_I10_INVOKE_CONT2_CRIT_EDGE:.*]], label %[[RETRY_I10_NEW_NOTNULL_I11_CRIT_EDGE:.*]] +; CHECK: [[RETRY_I10_NEW_NOTNULL_I11_CRIT_EDGE]]: +; CHECK-NEXT: br label %[[NEW_NOTNULL_I11]] +; CHECK: [[RETRY_I10_INVOKE_CONT2_CRIT_EDGE]]: +; CHECK-NEXT: br label %[[INVOKE_CONT2:.*]] +; CHECK: [[NEW_NOTNULL_I11]]: +; CHECK-NEXT: store i32 2, ptr [[ADD_PTR_I]], align 4, !tbaa [[INT_TBAA4]] +; CHECK-NEXT: br label %[[INVOKE_CONT2]] +; CHECK: [[IF_END_I14]]: +; CHECK-NEXT: invoke void @_ZN4llvm15SmallVectorBase8grow_podEmm(ptr [[SV]], i64 0, i64 4) +; CHECK-NEXT: to label %[[RETRY_I10]] unwind label %[[LPAD]] +; CHECK: [[INVOKE_CONT2]]: +; CHECK-NEXT: [[ADD_PTR_I12:%.*]] = getelementptr inbounds i8, ptr [[ADD_PTR_I]], i64 4 +; CHECK-NEXT: store ptr [[ADD_PTR_I12]], ptr [[ENDX_I_I_I_I_I_I]], align 8, !tbaa [[ANYPTR_TBAA0]] +; CHECK-NEXT: invoke void @_Z1gRN4llvm11SmallVectorIiLj8EEE(ptr [[SV]]) +; CHECK-NEXT: to label %[[INVOKE_CONT3:.*]] unwind label %[[LPAD]] +; CHECK: [[INVOKE_CONT3]]: +; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[SV]], align 16, !tbaa [[ANYPTR_TBAA0]] +; CHECK-NEXT: [[CMP_I_I_I_I19:%.*]] = icmp eq ptr [[TMP0]], [[FIRSTEL_I_I_I_I_I_I]] +; CHECK-NEXT: br i1 [[CMP_I_I_I_I19]], label %[[_ZN4LLVM11SMALLVECTORIILJ8EED1EV_EXIT21:.*]], label %[[IF_THEN_I_I_I20:.*]] +; CHECK: [[IF_THEN_I_I_I20]]: +; CHECK-NEXT: call void @free(ptr [[TMP0]]) #[[ATTR4]] +; CHECK-NEXT: br label %[[_ZN4LLVM11SMALLVECTORIILJ8EED1EV_EXIT21]] +; CHECK: [[_ZN4LLVM11SMALLVECTORIILJ8EED1EV_EXIT21]]: +; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[SV]]) #[[ATTR4]] +; CHECK-NEXT: ret void +; CHECK: [[LPAD]]: +; CHECK-NEXT: [[TMP1:%.*]] = landingpad { ptr, i32 } +; CHECK-NEXT: cleanup +; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[SV]], align 16, !tbaa [[ANYPTR_TBAA0]] +; CHECK-NEXT: [[CMP_I_I_I_I:%.*]] = icmp eq ptr [[TMP2]], [[FIRSTEL_I_I_I_I_I_I]] +; CHECK-NEXT: br i1 [[CMP_I_I_I_I]], label %[[EH_RESUME:.*]], label %[[IF_THEN_I_I_I:.*]] +; CHECK: [[IF_THEN_I_I_I]]: +; CHECK-NEXT: call void @free(ptr [[TMP2]]) #[[ATTR4]] +; CHECK-NEXT: br label %[[EH_RESUME]] +; CHECK: [[EH_RESUME]]: +; CHECK-NEXT: resume { ptr, i32 } [[TMP1]] +; entry: %sv = alloca %"class.llvm::SmallVector", align 16 @@ -42,7 +111,7 @@ new.notnull.i: ; preds = %Retry.i if.end.i: ; preds = %entry invoke void @_ZN4llvm15SmallVectorBase8grow_podEmm(ptr %sv, i64 0, i64 4) - to label %.noexc unwind label %lpad + to label %.noexc unwind label %lpad .noexc: ; preds = %if.end.i %.pre.i = load ptr, ptr %EndX.i, align 8, !tbaa !4 @@ -67,14 +136,14 @@ new.notnull.i11: ; preds = %invoke.cont, %Retry if.end.i14: ; preds = %invoke.cont invoke void @_ZN4llvm15SmallVectorBase8grow_podEmm(ptr %sv, i64 0, i64 4) - to label %Retry.i10 unwind label %lpad + to label %Retry.i10 unwind label %lpad invoke.cont2: ; preds = %new.notnull.i11, %Retry.i10 %4 = phi ptr [ null, %Retry.i10 ], [ %3, %new.notnull.i11 ] %add.ptr.i12 = getelementptr inbounds i8, ptr %4, i64 4 store ptr %add.ptr.i12, ptr %EndX.i, align 8, !tbaa !4 invoke void @_Z1gRN4llvm11SmallVectorIiLj8EEE(ptr %sv) - to label %invoke.cont3 unwind label %lpad + to label %invoke.cont3 unwind label %lpad invoke.cont3: ; preds = %invoke.cont2 %5 = load ptr, ptr %sv, align 16, !tbaa !4 @@ -91,7 +160,7 @@ _ZN4llvm11SmallVectorIiLj8EED1Ev.exit21: ; preds = %invoke.cont3, %if.t lpad: ; preds = %if.end.i14, %if.end.i, %invoke.cont2 %6 = landingpad { ptr, i32 } - cleanup + cleanup %7 = load ptr, ptr %sv, align 16, !tbaa !4 %cmp.i.i.i.i = icmp eq ptr %7, %FirstEl.i.i.i.i.i.i br i1 %cmp.i.i.i.i, label %eh.resume, label %if.then.i.i.i @@ -130,3 +199,11 @@ attributes #3 = { nounwind "less-precise-fpmad"="false" "frame-pointer"="all" "n !3 = !{!"int", !1} !4 = !{!0, !0, i64 0} !5 = !{!3, !3, i64 0} +;. +; CHECK: [[ANYPTR_TBAA0]] = !{[[META1:![0-9]+]], [[META1]], i64 0} +; CHECK: [[META1]] = !{!"any pointer", [[META2:![0-9]+]]} +; CHECK: [[META2]] = !{!"omnipotent char", [[META3:![0-9]+]]} +; CHECK: [[META3]] = !{!"Simple C/C++ TBAA"} +; CHECK: [[INT_TBAA4]] = !{[[META5:![0-9]+]], [[META5]], i64 0} +; CHECK: [[META5]] = !{!"int", [[META2]]} +;. diff --git a/llvm/test/Transforms/GVN/crash-no-aa.ll b/llvm/test/Transforms/GVN/crash-no-aa.ll index 10e6374..f396c10 100644 --- a/llvm/test/Transforms/GVN/crash-no-aa.ll +++ b/llvm/test/Transforms/GVN/crash-no-aa.ll @@ -1,10 +1,19 @@ -; RUN: opt -disable-basic-aa -passes=gvn -S < %s +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 +; RUN: opt -disable-basic-aa -passes=gvn -S -o - < %s | FileCheck %s + +; PR5744 target datalayout = "e-p:64:64:64-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" target triple = "x86_64-unknown-freebsd8.0" -; PR5744 define i32 @test1(ptr %P) { +; CHECK-LABEL: define i32 @test1( +; CHECK-SAME: ptr [[P:%.*]]) { +; CHECK-NEXT: store i16 42, ptr [[P]], align 2 +; CHECK-NEXT: [[P3:%.*]] = getelementptr { i16, i32 }, ptr [[P]], i32 0, i32 1 +; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[P3]], align 4 +; CHECK-NEXT: ret i32 [[V]] +; %P2 = getelementptr {i16, i32}, ptr %P, i32 0, i32 0 store i16 42, ptr %P2 diff --git a/llvm/test/Transforms/GVN/critical-edge-split-failure.ll b/llvm/test/Transforms/GVN/critical-edge-split-failure.ll index 8eac5fe..40ebe14 100644 --- a/llvm/test/Transforms/GVN/critical-edge-split-failure.ll +++ b/llvm/test/Transforms/GVN/critical-edge-split-failure.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=gvn -S -o - %s | FileCheck %s %struct.sk_buff = type opaque @@ -10,6 +11,31 @@ declare void @llvm.assume(i1 noundef) define dso_local void @l2tp_recv_dequeue() local_unnamed_addr { +; CHECK-LABEL: define dso_local void @l2tp_recv_dequeue() local_unnamed_addr { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @l2tp_recv_dequeue_session, align 4 +; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64 +; CHECK-NEXT: [[TMP1:%.*]] = inttoptr i64 [[CONV]] to ptr +; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr @l2tp_recv_dequeue_session_2, align 4 +; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[TMP2]], 0 +; CHECK-NEXT: br label %[[FOR_COND:.*]] +; CHECK: [[FOR_COND]]: +; CHECK-NEXT: [[STOREMERGE:%.*]] = phi ptr [ [[TMP1]], %[[ENTRY]] ], [ null, %[[IF_END:.*]] ] +; CHECK-NEXT: store ptr [[STOREMERGE]], ptr @l2tp_recv_dequeue_skb, align 8 +; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label %[[IF_END]], label %[[IF_THEN:.*]] +; CHECK: [[IF_THEN]]: +; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[STOREMERGE]], align 4 +; CHECK-NEXT: store i32 [[TMP3]], ptr @l2tp_recv_dequeue_session_0, align 4 +; CHECK-NEXT: callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"() +; CHECK-NEXT: to label %[[ASM_FALLTHROUGH_I:.*]] [label %if.end] +; CHECK: [[ASM_FALLTHROUGH_I]]: +; CHECK-NEXT: br label %[[IF_END]] +; CHECK: [[IF_END]]: +; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[STOREMERGE]], align 4 +; CHECK-NEXT: [[TOBOOL2_NOT:%.*]] = icmp eq i32 [[TMP4]], 0 +; CHECK-NEXT: tail call void @llvm.assume(i1 [[TOBOOL2_NOT]]) +; CHECK-NEXT: br label %[[FOR_COND]] +; entry: %0 = load i32, ptr @l2tp_recv_dequeue_session, align 4 %conv = sext i32 %0 to i64 @@ -29,10 +55,8 @@ if.then: ; preds = %for.cond ; Splitting the critical edge from if.then to if.end will fail, but should not ; cause an infinite loop in GVN. If we can one day split edges of callbr ; indirect targets, great! -; CHECK: callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"() -; CHECK-NEXT: to label %asm.fallthrough.i [label %if.end] callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"() - to label %asm.fallthrough.i [label %if.end] + to label %asm.fallthrough.i [label %if.end] asm.fallthrough.i: ; preds = %if.then br label %if.end @@ -43,4 +67,3 @@ if.end: ; preds = %asm.fallthrough.i, tail call void @llvm.assume(i1 %tobool2.not) br label %for.cond } - diff --git a/llvm/test/Transforms/GVN/dbg-redundant-load.ll b/llvm/test/Transforms/GVN/dbg-redundant-load.ll index 1ba4e8b..094467e 100644 --- a/llvm/test/Transforms/GVN/dbg-redundant-load.ll +++ b/llvm/test/Transforms/GVN/dbg-redundant-load.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=gvn -S < %s | FileCheck %s ; Check that the redundant load from %if.then is removed. @@ -6,15 +7,21 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" -; CHECK: @test_redundant_load( -; CHECK-LABEL: entry: -; CHECK-NEXT: load i32, ptr %Y, align 4, !dbg ![[LOC:[0-9]+]] -; CHECK-LABEL: if.then: -; CHECK-NOT: load -; CHECK-LABEL: if.end: -; CHECK: ![[LOC]] = !DILocation(line: 3, scope: !{{.*}}) - define i32 @test_redundant_load(i32 %X, ptr %Y) !dbg !6 { +; CHECK-LABEL: define i32 @test_redundant_load( +; CHECK-SAME: i32 [[X:%.*]], ptr [[Y:%.*]]) !dbg [[DBG6:![0-9]+]] { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[Y]], align 4, !dbg [[DBG8:![0-9]+]] +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X]], -1, !dbg [[DBG9:![0-9]+]] +; CHECK-NEXT: br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_END:.*]], !dbg [[DBG9]] +; CHECK: [[IF_THEN]]: +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP0]], !dbg [[DBG10:![0-9]+]] +; CHECK-NEXT: call void @foo(), !dbg [[DBG11:![0-9]+]] +; CHECK-NEXT: br label %[[IF_END]], !dbg [[DBG12:![0-9]+]] +; CHECK: [[IF_END]]: +; CHECK-NEXT: [[RESULT_0:%.*]] = phi i32 [ [[ADD]], %[[IF_THEN]] ], [ [[TMP0]], %[[ENTRY]] ] +; CHECK-NEXT: ret i32 [[RESULT_0]], !dbg [[DBG13:![0-9]+]] +; entry: %0 = load i32, ptr %Y, align 4, !dbg !8 %cmp = icmp sgt i32 %X, -1, !dbg !9 @@ -50,3 +57,16 @@ declare void @foo() !11 = !DILocation(line: 7, scope: !6) !12 = !DILocation(line: 8, scope: !6) !13 = !DILocation(line: 10, scope: !6) +;. +; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: [[META1:![0-9]+]], isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: [[META2:![0-9]+]]) +; CHECK: [[META1]] = !DIFile(filename: "test.cpp", directory: "") +; CHECK: [[META2]] = !{} +; CHECK: [[DBG6]] = distinct !DISubprogram(name: "test_redundant_load", scope: [[META1]], file: [[META1]], line: 2, type: [[META7:![0-9]+]], scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META2]]) +; CHECK: [[META7]] = !DISubroutineType(types: [[META2]]) +; CHECK: [[DBG8]] = !DILocation(line: 3, scope: [[DBG6]]) +; CHECK: [[DBG9]] = !DILocation(line: 5, scope: [[DBG6]]) +; CHECK: [[DBG10]] = !DILocation(line: 6, scope: [[DBG6]]) +; CHECK: [[DBG11]] = !DILocation(line: 7, scope: [[DBG6]]) +; CHECK: [[DBG12]] = !DILocation(line: 8, scope: [[DBG6]]) +; CHECK: [[DBG13]] = !DILocation(line: 10, scope: [[DBG6]]) +;. diff --git a/llvm/test/Transforms/GVN/fake-use-constprop.ll b/llvm/test/Transforms/GVN/fake-use-constprop.ll index 0e7ca10..85b7dc3 100644 --- a/llvm/test/Transforms/GVN/fake-use-constprop.ll +++ b/llvm/test/Transforms/GVN/fake-use-constprop.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=gvn -S < %s | FileCheck %s ; ; The Global Value Numbering pass (GVN) propagates boolean values @@ -33,11 +34,20 @@ ;; GVN should propagate a constant value through to a regular call, but not to ;; a fake use, which should continue to track the original value. -; CHECK: %[[CONV_VAR:[a-zA-Z0-9]+]] = fptosi -; CHECK: call {{.+}} @bees(i8 0) -; CHECK: call {{.+}} @llvm.fake.use(i8 %[[CONV_VAR]]) define i32 @foo(float %f) optdebug { +; CHECK-LABEL: define i32 @foo( +; CHECK-SAME: float [[F:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[CONV:%.*]] = fptosi float [[F]] to i8 +; CHECK-NEXT: [[TOBOOL3:%.*]] = icmp eq i8 [[CONV]], 0 +; CHECK-NEXT: br i1 [[TOBOOL3]], label %[[IF_END:.*]], label %[[LAB:.*]] +; CHECK: [[IF_END]]: +; CHECK-NEXT: tail call void (...) @bees(i8 0) +; CHECK-NEXT: tail call void (...) @llvm.fake.use(i8 [[CONV]]) +; CHECK-NEXT: br label %[[LAB]] +; CHECK: [[LAB]]: +; CHECK-NEXT: ret i32 1 +; %conv = fptosi float %f to i8 %tobool3 = icmp eq i8 %conv, 0 br i1 %tobool3, label %if.end, label %lab diff --git a/llvm/test/Transforms/GVN/flags.ll b/llvm/test/Transforms/GVN/flags.ll index 2e5aeed..3777e14 100644 --- a/llvm/test/Transforms/GVN/flags.ll +++ b/llvm/test/Transforms/GVN/flags.ll @@ -1,8 +1,17 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=gvn -S < %s | FileCheck %s declare void @use(i1) define void @test1(float %x, float %y) { +; CHECK-LABEL: define void @test1( +; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[CMP1:%.*]] = fcmp oeq float [[Y]], [[X]] +; CHECK-NEXT: call void @use(i1 [[CMP1]]) +; CHECK-NEXT: call void @use(i1 [[CMP1]]) +; CHECK-NEXT: ret void +; entry: %cmp1 = fcmp nnan oeq float %y, %x %cmp2 = fcmp oeq float %x, %y @@ -10,9 +19,3 @@ entry: call void @use(i1 %cmp2) ret void } - -; CHECK-LABEL: define void @test1( -; CHECK: %[[cmp:.*]] = fcmp oeq float %y, %x -; CHECK-NEXT: call void @use(i1 %[[cmp]]) -; CHECK-NEXT: call void @use(i1 %[[cmp]]) -; CHECK-NEXT: ret void diff --git a/llvm/test/Transforms/GVN/fold-const-expr.ll b/llvm/test/Transforms/GVN/fold-const-expr.ll index 9e1129e..edbfcda 100644 --- a/llvm/test/Transforms/GVN/fold-const-expr.ll +++ b/llvm/test/Transforms/GVN/fold-const-expr.ll @@ -1,12 +1,24 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 +; RUN: opt -passes=gvn -S < %s | FileCheck %s + ; GVN failed to do constant expression folding and expanded ; them unfolded in many places, producing exponentially large const ; expressions. As a result, the compilation never fisished. ; This test checks that we are folding constant expression ; PR 28418 -; RUN: opt -passes=gvn -S < %s | FileCheck %s %2 = type { i32, i32, i32, i32, i32 } define i32 @_Z16vector3util_mainv(i32 %x, i32 %y) { +; CHECK-LABEL: define i32 @_Z16vector3util_mainv( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = alloca [[TMP0:%.*]], align 4 +; CHECK-NEXT: [[TMP114:%.*]] = getelementptr inbounds [[TMP0]], ptr [[TMP1]], i64 0, i32 1 +; CHECK-NEXT: store <4 x i32> <i32 234567891, i32 345678912, i32 456789123, i32 0>, ptr [[TMP114]], align 4 +; CHECK-NEXT: store i32 310393545, ptr [[TMP114]], align 4 +; CHECK-NEXT: store i32 -383584258, ptr [[TMP114]], align 4 +; CHECK-NEXT: store i32 -57163022, ptr [[TMP114]], align 4 +; CHECK-NEXT: ret i32 0 +; %tmp1 = alloca %2, align 4 %tmp114 = getelementptr inbounds %2, ptr %tmp1, i64 0, i32 1 store <4 x i32> <i32 234567891, i32 345678912, i32 456789123, i32 0>, ptr %tmp114, align 4 @@ -37,7 +49,6 @@ define i32 @_Z16vector3util_mainv(i32 %x, i32 %y) { %tmp1739 = shl i32 %tmp1738, 22 %tmp1740 = xor i32 %tmp1739, %tmp1738 store i32 %tmp1740, ptr %tmp1683, align 4 -; CHECK: store i32 310393545, ptr %tmp114, align 4 %tmp1756 = getelementptr inbounds %2, ptr %tmp1, i64 0, i32 1 %tmp1761 = load i32, ptr %tmp1756, align 4 %tmp1766 = shl i32 %tmp1761, 5 @@ -65,7 +76,6 @@ define i32 @_Z16vector3util_mainv(i32 %x, i32 %y) { %tmp1812 = shl i32 %tmp1811, 22 %tmp1813 = xor i32 %tmp1812, %tmp1811 store i32 %tmp1813, ptr %tmp1756, align 4 -; CHECK: store i32 -383584258, ptr %tmp114, align 4 %tmp2645 = getelementptr inbounds %2, ptr %tmp1, i64 0, i32 1 %tmp2650 = load i32, ptr %tmp2645, align 4 %tmp2655 = shl i32 %tmp2650, 5 @@ -93,6 +103,5 @@ define i32 @_Z16vector3util_mainv(i32 %x, i32 %y) { %tmp2701 = shl i32 %tmp2700, 22 %tmp2702 = xor i32 %tmp2701, %tmp2700 store i32 %tmp2702, ptr %tmp2645, align 4 -; CHECK: store i32 -57163022, ptr %tmp114, align 4 ret i32 0 } diff --git a/llvm/test/Transforms/GVN/fpmath.ll b/llvm/test/Transforms/GVN/fpmath.ll index 970dd89..2069faa 100644 --- a/llvm/test/Transforms/GVN/fpmath.ll +++ b/llvm/test/Transforms/GVN/fpmath.ll @@ -1,10 +1,13 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=gvn -S < %s | FileCheck %s define double @test1(double %x, double %y) { -; CHECK: @test1(double %x, double %y) -; CHECK: %add1 = fadd double %x, %y -; CHECK-NOT: fpmath -; CHECK: %foo = fadd double %add1, %add1 +; CHECK-LABEL: define double @test1( +; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { +; CHECK-NEXT: [[ADD1:%.*]] = fadd double [[X]], [[Y]] +; CHECK-NEXT: [[FOO:%.*]] = fadd double [[ADD1]], [[ADD1]] +; CHECK-NEXT: ret double [[FOO]] +; %add1 = fadd double %x, %y, !fpmath !0 %add2 = fadd double %x, %y %foo = fadd double %add1, %add2 @@ -12,9 +15,12 @@ define double @test1(double %x, double %y) { } define double @test2(double %x, double %y) { -; CHECK: @test2(double %x, double %y) -; CHECK: %add1 = fadd double %x, %y, !fpmath !0 -; CHECK: %foo = fadd double %add1, %add1 +; CHECK-LABEL: define double @test2( +; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { +; CHECK-NEXT: [[ADD1:%.*]] = fadd double [[X]], [[Y]], !fpmath [[META0:![0-9]+]] +; CHECK-NEXT: [[FOO:%.*]] = fadd double [[ADD1]], [[ADD1]] +; CHECK-NEXT: ret double [[FOO]] +; %add1 = fadd double %x, %y, !fpmath !0 %add2 = fadd double %x, %y, !fpmath !0 %foo = fadd double %add1, %add2 @@ -22,9 +28,12 @@ define double @test2(double %x, double %y) { } define double @test3(double %x, double %y) { -; CHECK: @test3(double %x, double %y) -; CHECK: %add1 = fadd double %x, %y, !fpmath !1 -; CHECK: %foo = fadd double %add1, %add1 +; CHECK-LABEL: define double @test3( +; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { +; CHECK-NEXT: [[ADD1:%.*]] = fadd double [[X]], [[Y]], !fpmath [[META1:![0-9]+]] +; CHECK-NEXT: [[FOO:%.*]] = fadd double [[ADD1]], [[ADD1]] +; CHECK-NEXT: ret double [[FOO]] +; %add1 = fadd double %x, %y, !fpmath !1 %add2 = fadd double %x, %y, !fpmath !0 %foo = fadd double %add1, %add2 @@ -32,9 +41,12 @@ define double @test3(double %x, double %y) { } define double @test4(double %x, double %y) { -; CHECK: @test4(double %x, double %y) -; CHECK: %add1 = fadd double %x, %y, !fpmath !1 -; CHECK: %foo = fadd double %add1, %add1 +; CHECK-LABEL: define double @test4( +; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { +; CHECK-NEXT: [[ADD1:%.*]] = fadd double [[X]], [[Y]], !fpmath [[META1]] +; CHECK-NEXT: [[FOO:%.*]] = fadd double [[ADD1]], [[ADD1]] +; CHECK-NEXT: ret double [[FOO]] +; %add1 = fadd double %x, %y, !fpmath !0 %add2 = fadd double %x, %y, !fpmath !1 %foo = fadd double %add1, %add2 @@ -42,9 +54,12 @@ define double @test4(double %x, double %y) { } define double @test5(double %x, double %y) { -; CHECK: @test5(double %x, double %y) -; CHECK: %neg1 = fneg double %x, !fpmath !1 -; CHECK: %foo = fadd double %neg1, %neg1 +; CHECK-LABEL: define double @test5( +; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { +; CHECK-NEXT: [[NEG1:%.*]] = fneg double [[X]], !fpmath [[META1]] +; CHECK-NEXT: [[FOO:%.*]] = fadd double [[NEG1]], [[NEG1]] +; CHECK-NEXT: ret double [[FOO]] +; %neg1 = fneg double %x, !fpmath !0 %neg2 = fneg double %x, !fpmath !1 %foo = fadd double %neg1, %neg2 @@ -53,3 +68,7 @@ define double @test5(double %x, double %y) { !0 = !{ float 5.0 } !1 = !{ float 2.5 } +;. +; CHECK: [[META0]] = !{float 5.000000e+00} +; CHECK: [[META1]] = !{float 2.500000e+00} +;. diff --git a/llvm/test/Transforms/GVN/funclet.ll b/llvm/test/Transforms/GVN/funclet.ll index 8ef4c96..34ed78f 100644 --- a/llvm/test/Transforms/GVN/funclet.ll +++ b/llvm/test/Transforms/GVN/funclet.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=gvn -S < %s | FileCheck %s target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" target triple = "i686-pc-windows-msvc" @@ -8,13 +9,35 @@ target triple = "i686-pc-windows-msvc" @"_TI1?AUA@@" = external constant %eh.ThrowInfo define i8 @f() personality ptr @__CxxFrameHandler3 { +; CHECK-LABEL: define i8 @f() personality ptr @__CxxFrameHandler3 { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[B:%.*]] = alloca i8, align 1 +; CHECK-NEXT: [[C:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[B]], align 1 +; CHECK-NEXT: store i8 13, ptr [[C]], align 1 +; CHECK-NEXT: invoke void @_CxxThrowException(ptr [[B]], ptr nonnull @"_TI1?AUA@@") +; CHECK-NEXT: to label %[[UNREACHABLE:.*]] unwind label %[[CATCH_DISPATCH:.*]] +; CHECK: [[CATCH_DISPATCH]]: +; CHECK-NEXT: [[CS1:%.*]] = catchswitch within none [label %catch] unwind to caller +; CHECK: [[CATCH:.*:]] +; CHECK-NEXT: [[CATCHPAD:%.*]] = catchpad within [[CS1]] [ptr null, i32 64, ptr null] +; CHECK-NEXT: store i8 5, ptr [[B]], align 1 +; CHECK-NEXT: catchret from [[CATCHPAD]] to label %[[TRY_CONT:.*]] +; CHECK: [[TRY_CONT]]: +; CHECK-NEXT: [[LOAD_B:%.*]] = load i8, ptr [[B]], align 1 +; CHECK-NEXT: [[LOAD_C:%.*]] = load i8, ptr [[C]], align 1 +; CHECK-NEXT: [[ADD:%.*]] = add i8 [[LOAD_B]], [[LOAD_C]] +; CHECK-NEXT: ret i8 [[ADD]] +; CHECK: [[UNREACHABLE]]: +; CHECK-NEXT: unreachable +; entry: %b = alloca i8 %c = alloca i8 store i8 42, ptr %b store i8 13, ptr %c invoke void @_CxxThrowException(ptr %b, ptr nonnull @"_TI1?AUA@@") - to label %unreachable unwind label %catch.dispatch + to label %unreachable unwind label %catch.dispatch catch.dispatch: ; preds = %entry %cs1 = catchswitch within none [label %catch] unwind to caller @@ -33,11 +56,6 @@ try.cont: ; preds = %catch unreachable: ; preds = %entry unreachable } -; CHECK-LABEL: define i8 @f( -; CHECK: %[[load_b:.*]] = load i8, ptr %b -; CHECK-NEXT: %[[load_c:.*]] = load i8, ptr %c -; CHECK-NEXT: %[[add:.*]] = add i8 %[[load_b]], %[[load_c]] -; CHECK-NEXT: ret i8 %[[add]] declare i32 @__CxxFrameHandler3(...) diff --git a/llvm/test/Transforms/GVN/int_sideeffect.ll b/llvm/test/Transforms/GVN/int_sideeffect.ll index 513533a..8754cc0 100644 --- a/llvm/test/Transforms/GVN/int_sideeffect.ll +++ b/llvm/test/Transforms/GVN/int_sideeffect.ll @@ -1,38 +1,56 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -S < %s -passes=gvn | FileCheck %s declare void @llvm.sideeffect() ; Store-to-load forwarding across a @llvm.sideeffect. - -; CHECK-LABEL: s2l -; CHECK-NOT: load define float @s2l(ptr %p) { - store float 0.0, ptr %p - call void @llvm.sideeffect() - %t = load float, ptr %p - ret float %t +; CHECK-LABEL: define float @s2l( +; CHECK-SAME: ptr [[P:%.*]]) { +; CHECK-NEXT: store float 0.000000e+00, ptr [[P]], align 4 +; CHECK-NEXT: call void @llvm.sideeffect() +; CHECK-NEXT: ret float 0.000000e+00 +; + store float 0.0, ptr %p + call void @llvm.sideeffect() + %t = load float, ptr %p + ret float %t } ; Redundant load elimination across a @llvm.sideeffect. - -; CHECK-LABEL: rle -; CHECK: load -; CHECK-NOT: load define float @rle(ptr %p) { - %r = load float, ptr %p - call void @llvm.sideeffect() - %s = load float, ptr %p - %t = fadd float %r, %s - ret float %t +; CHECK-LABEL: define float @rle( +; CHECK-SAME: ptr [[P:%.*]]) { +; CHECK-NEXT: [[R:%.*]] = load float, ptr [[P]], align 4 +; CHECK-NEXT: call void @llvm.sideeffect() +; CHECK-NEXT: [[T:%.*]] = fadd float [[R]], [[R]] +; CHECK-NEXT: ret float [[T]] +; + %r = load float, ptr %p + call void @llvm.sideeffect() + %s = load float, ptr %p + %t = fadd float %r, %s + ret float %t } ; LICM across a @llvm.sideeffect. - -; CHECK-LABEL: licm -; CHECK: load -; CHECK: loop: -; CHECK-NOT: load define float @licm(i64 %n, ptr nocapture readonly %p) #0 { +; CHECK-LABEL: define float @licm( +; CHECK-SAME: i64 [[N:%.*]], ptr readonly captures(none) [[P:%.*]]) { +; CHECK-NEXT: [[BB0:.*]]: +; CHECK-NEXT: [[T3_PRE:%.*]] = load float, ptr [[P]], align 4 +; CHECK-NEXT: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK-NEXT: [[I:%.*]] = phi i64 [ 0, %[[BB0]] ], [ [[T5:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[SUM:%.*]] = phi float [ 0.000000e+00, %[[BB0]] ], [ [[T4:%.*]], %[[LOOP]] ] +; CHECK-NEXT: call void @llvm.sideeffect() +; CHECK-NEXT: [[T4]] = fadd float [[SUM]], [[T3_PRE]] +; CHECK-NEXT: [[T5]] = add i64 [[I]], 1 +; CHECK-NEXT: [[T6:%.*]] = icmp ult i64 [[T5]], [[N]] +; CHECK-NEXT: br i1 [[T6]], label %[[LOOP]], label %[[BB2:.*]] +; CHECK: [[BB2]]: +; CHECK-NEXT: ret float [[T4]] +; bb0: br label %loop diff --git a/llvm/test/Transforms/GVN/invariant.group.ll b/llvm/test/Transforms/GVN/invariant.group.ll index 9c673ba..aba20ee 100644 --- a/llvm/test/Transforms/GVN/invariant.group.ll +++ b/llvm/test/Transforms/GVN/invariant.group.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt < %s -passes=gvn -S | FileCheck %s %struct.A = type { ptr } @@ -6,130 +7,175 @@ @unknownPtr = external global i8 -; CHECK-LABEL: define i8 @simple() { define i8 @simple() { +; CHECK-LABEL: define i8 @simple() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0:![0-9]+]] +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: ret i8 42 +; entry: - %ptr = alloca i8 - store i8 42, ptr %ptr, !invariant.group !0 - call void @foo(ptr %ptr) - - %a = load i8, ptr %ptr, !invariant.group !0 - %b = load i8, ptr %ptr, !invariant.group !0 - %c = load i8, ptr %ptr, !invariant.group !0 -; CHECK: ret i8 42 - ret i8 %a + %ptr = alloca i8 + store i8 42, ptr %ptr, !invariant.group !0 + call void @foo(ptr %ptr) + + %a = load i8, ptr %ptr, !invariant.group !0 + %b = load i8, ptr %ptr, !invariant.group !0 + %c = load i8, ptr %ptr, !invariant.group !0 + ret i8 %a } -; CHECK-LABEL: define i8 @optimizable1() { define i8 @optimizable1() { +; CHECK-LABEL: define i8 @optimizable1() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: [[PTR2:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[PTR]]) +; CHECK-NEXT: call void @foo(ptr [[PTR2]]) +; CHECK-NEXT: ret i8 42 +; entry: - %ptr = alloca i8 - store i8 42, ptr %ptr, !invariant.group !0 - %ptr2 = call ptr @llvm.launder.invariant.group.p0(ptr %ptr) - %a = load i8, ptr %ptr, !invariant.group !0 - - call void @foo(ptr %ptr2); call to use %ptr2 -; CHECK: ret i8 42 - ret i8 %a + %ptr = alloca i8 + store i8 42, ptr %ptr, !invariant.group !0 + %ptr2 = call ptr @llvm.launder.invariant.group.p0(ptr %ptr) + %a = load i8, ptr %ptr, !invariant.group !0 + + call void @foo(ptr %ptr2); call to use %ptr2 + ret i8 %a } -; CHECK-LABEL: define i8 @optimizable2() { define i8 @optimizable2() { +; CHECK-LABEL: define i8 @optimizable2() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: store i8 13, ptr [[PTR]], align 1 +; CHECK-NEXT: call void @bar(i8 13) +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: ret i8 42 +; entry: - %ptr = alloca i8 - store i8 42, ptr %ptr, !invariant.group !0 - call void @foo(ptr %ptr) - - store i8 13, ptr %ptr ; can't use this store with invariant.group - %a = load i8, ptr %ptr - call void @bar(i8 %a) ; call to use %a - - call void @foo(ptr %ptr) - %b = load i8, ptr %ptr, !invariant.group !0 - -; CHECK: ret i8 42 - ret i8 %b + %ptr = alloca i8 + store i8 42, ptr %ptr, !invariant.group !0 + call void @foo(ptr %ptr) + + store i8 13, ptr %ptr ; can't use this store with invariant.group + %a = load i8, ptr %ptr + call void @bar(i8 %a) ; call to use %a + + call void @foo(ptr %ptr) + %b = load i8, ptr %ptr, !invariant.group !0 + + ret i8 %b } -; CHECK-LABEL: define i1 @proveEqualityForStrip( -define i1 @proveEqualityForStrip(ptr %a) { ; FIXME: The first call could be also removed by GVN. Right now ; DCE removes it. The second call is CSE'd with the first one. -; CHECK: %b1 = call ptr @llvm.strip.invariant.group.p0(ptr %a) +define i1 @proveEqualityForStrip(ptr %a) { +; CHECK-LABEL: define i1 @proveEqualityForStrip( +; CHECK-SAME: ptr [[A:%.*]]) { +; CHECK-NEXT: [[B1:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr [[A]]) +; CHECK-NEXT: ret i1 true +; %b1 = call ptr @llvm.strip.invariant.group.p0(ptr %a) -; CHECK-NOT: llvm.strip.invariant.group %b2 = call ptr @llvm.strip.invariant.group.p0(ptr %a) %r = icmp eq ptr %b1, %b2 -; CHECK: ret i1 true ret i1 %r } -; CHECK-LABEL: define i8 @unoptimizable1() { + define i8 @unoptimizable1() { +; CHECK-LABEL: define i8 @unoptimizable1() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1 +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: [[A:%.*]] = load i8, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: ret i8 [[A]] +; entry: - %ptr = alloca i8 - store i8 42, ptr %ptr - call void @foo(ptr %ptr) - %a = load i8, ptr %ptr, !invariant.group !0 -; CHECK: ret i8 %a - ret i8 %a + %ptr = alloca i8 + store i8 42, ptr %ptr + call void @foo(ptr %ptr) + %a = load i8, ptr %ptr, !invariant.group !0 + ret i8 %a } -; CHECK-LABEL: define void @indirectLoads() { define void @indirectLoads() { +; CHECK-LABEL: define void @indirectLoads() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[A:%.*]] = alloca ptr, align 8 +; CHECK-NEXT: [[CALL:%.*]] = call ptr @getPointer(ptr null) +; CHECK-NEXT: call void @_ZN1AC1Ev(ptr [[CALL]]) +; CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[CALL]], align 8, !invariant.group [[META0]] +; CHECK-NEXT: [[CMP_VTABLES:%.*]] = icmp eq ptr [[VTABLE]], getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2) +; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_VTABLES]]) +; CHECK-NEXT: store ptr [[CALL]], ptr [[A]], align 8 +; CHECK-NEXT: call void @_ZN1A3fooEv(ptr [[CALL]]) +; CHECK-NEXT: call void @_ZN1A3fooEv(ptr [[CALL]]) +; CHECK-NEXT: call void @_ZN1A3fooEv(ptr [[CALL]]) +; CHECK-NEXT: call void @_ZN1A3fooEv(ptr [[CALL]]) +; CHECK-NEXT: ret void +; entry: %a = alloca ptr, align 8 - - %call = call ptr @getPointer(ptr null) + + %call = call ptr @getPointer(ptr null) call void @_ZN1AC1Ev(ptr %call) - -; CHECK: %vtable = load {{.*}} !invariant.group + %vtable = load ptr, ptr %call, align 8, !invariant.group !0 %cmp.vtables = icmp eq ptr %vtable, getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2) call void @llvm.assume(i1 %cmp.vtables) - + store ptr %call, ptr %a, align 8 %0 = load ptr, ptr %a, align 8 -; CHECK: call void @_ZN1A3fooEv( %vtable1 = load ptr, ptr %0, align 8, !invariant.group !0 %1 = load ptr, ptr %vtable1, align 8 call void %1(ptr %0) %2 = load ptr, ptr %a, align 8 -; CHECK: call void @_ZN1A3fooEv( %vtable2 = load ptr, ptr %2, align 8, !invariant.group !0 %3 = load ptr, ptr %vtable2, align 8 - + call void %3(ptr %2) %4 = load ptr, ptr %a, align 8 - + %vtable4 = load ptr, ptr %4, align 8, !invariant.group !0 %5 = load ptr, ptr %vtable4, align 8 -; CHECK: call void @_ZN1A3fooEv( call void %5(ptr %4) - + %vtable5 = load ptr, ptr %call, align 8, !invariant.group !0 %6 = load ptr, ptr %vtable5, align 8 -; CHECK: call void @_ZN1A3fooEv( call void %6(ptr %4) - + ret void } -; CHECK-LABEL: define void @combiningBitCastWithLoad() { define void @combiningBitCastWithLoad() { +; CHECK-LABEL: define void @combiningBitCastWithLoad() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[A:%.*]] = alloca ptr, align 8 +; CHECK-NEXT: [[CALL:%.*]] = call ptr @getPointer(ptr null) +; CHECK-NEXT: call void @_ZN1AC1Ev(ptr [[CALL]]) +; CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[CALL]], align 8, !invariant.group [[META0]] +; CHECK-NEXT: [[CMP_VTABLES:%.*]] = icmp eq ptr [[VTABLE]], getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2) +; CHECK-NEXT: store ptr [[CALL]], ptr [[A]], align 8 +; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VTABLE]], align 8 +; CHECK-NEXT: call void [[TMP0]](ptr [[CALL]]) +; CHECK-NEXT: ret void +; entry: %a = alloca ptr, align 8 - - %call = call ptr @getPointer(ptr null) + + %call = call ptr @getPointer(ptr null) call void @_ZN1AC1Ev(ptr %call) - -; CHECK: %vtable = load {{.*}} !invariant.group + %vtable = load ptr, ptr %call, align 8, !invariant.group !0 %cmp.vtables = icmp eq ptr %vtable, getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2) - + store ptr %call, ptr %a, align 8 -; CHECK-NOT: !invariant.group %0 = load ptr, ptr %a, align 8 %vtable1 = load ptr, ptr %0, align 8, !invariant.group !0 @@ -139,185 +185,255 @@ entry: ret void } -; CHECK-LABEL:define void @loadCombine() { define void @loadCombine() { +; CHECK-LABEL: define void @loadCombine() { +; CHECK-NEXT: [[ENTER:.*:]] +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1 +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: [[A:%.*]] = load i8, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @bar(i8 [[A]]) +; CHECK-NEXT: call void @bar(i8 [[A]]) +; CHECK-NEXT: ret void +; enter: %ptr = alloca i8 store i8 42, ptr %ptr call void @foo(ptr %ptr) -; CHECK: %[[A:.*]] = load i8, ptr %ptr, align 1, !invariant.group %a = load i8, ptr %ptr, !invariant.group !0 -; CHECK-NOT: load %b = load i8, ptr %ptr, !invariant.group !0 -; CHECK: call void @bar(i8 %[[A]]) call void @bar(i8 %a) -; CHECK: call void @bar(i8 %[[A]]) call void @bar(i8 %b) ret void } -; CHECK-LABEL: define void @loadCombine1() { define void @loadCombine1() { +; CHECK-LABEL: define void @loadCombine1() { +; CHECK-NEXT: [[ENTER:.*:]] +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1 +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: [[C:%.*]] = load i8, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @bar(i8 [[C]]) +; CHECK-NEXT: call void @bar(i8 [[C]]) +; CHECK-NEXT: ret void +; enter: %ptr = alloca i8 store i8 42, ptr %ptr call void @foo(ptr %ptr) -; CHECK: %[[D:.*]] = load i8, ptr %ptr, align 1, !invariant.group %c = load i8, ptr %ptr -; CHECK-NOT: load %d = load i8, ptr %ptr, !invariant.group !0 -; CHECK: call void @bar(i8 %[[D]]) call void @bar(i8 %c) -; CHECK: call void @bar(i8 %[[D]]) call void @bar(i8 %d) ret void } -; CHECK-LABEL: define void @loadCombine2() { define void @loadCombine2() { +; CHECK-LABEL: define void @loadCombine2() { +; CHECK-NEXT: [[ENTER:.*:]] +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1 +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: [[E:%.*]] = load i8, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @bar(i8 [[E]]) +; CHECK-NEXT: call void @bar(i8 [[E]]) +; CHECK-NEXT: ret void +; enter: %ptr = alloca i8 store i8 42, ptr %ptr call void @foo(ptr %ptr) -; CHECK: %[[E:.*]] = load i8, ptr %ptr, align 1, !invariant.group %e = load i8, ptr %ptr, !invariant.group !0 -; CHECK-NOT: load %f = load i8, ptr %ptr -; CHECK: call void @bar(i8 %[[E]]) call void @bar(i8 %e) -; CHECK: call void @bar(i8 %[[E]]) call void @bar(i8 %f) ret void } -; CHECK-LABEL: define void @loadCombine3() { define void @loadCombine3() { +; CHECK-LABEL: define void @loadCombine3() { +; CHECK-NEXT: [[ENTER:.*:]] +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1 +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: [[E:%.*]] = load i8, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @bar(i8 [[E]]) +; CHECK-NEXT: call void @bar(i8 [[E]]) +; CHECK-NEXT: ret void +; enter: %ptr = alloca i8 store i8 42, ptr %ptr call void @foo(ptr %ptr) -; CHECK: %[[E:.*]] = load i8, ptr %ptr, align 1, !invariant.group %e = load i8, ptr %ptr, !invariant.group !0 -; CHECK-NOT: load %f = load i8, ptr %ptr, !invariant.group !0 -; CHECK: call void @bar(i8 %[[E]]) call void @bar(i8 %e) -; CHECK: call void @bar(i8 %[[E]]) call void @bar(i8 %f) ret void } -; CHECK-LABEL: define i8 @unoptimizable2() { define i8 @unoptimizable2() { +; CHECK-LABEL: define i8 @unoptimizable2() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1 +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: [[A:%.*]] = load i8, ptr [[PTR]], align 1 +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: ret i8 [[A]] +; entry: - %ptr = alloca i8 - store i8 42, ptr %ptr - call void @foo(ptr %ptr) - %a = load i8, ptr %ptr - call void @foo(ptr %ptr) - %b = load i8, ptr %ptr, !invariant.group !0 - -; CHECK: ret i8 %a - ret i8 %a + %ptr = alloca i8 + store i8 42, ptr %ptr + call void @foo(ptr %ptr) + %a = load i8, ptr %ptr + call void @foo(ptr %ptr) + %b = load i8, ptr %ptr, !invariant.group !0 + + ret i8 %a } -; CHECK-LABEL: define i8 @unoptimizable3() { define i8 @unoptimizable3() { +; CHECK-LABEL: define i8 @unoptimizable3() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: [[PTR2:%.*]] = call ptr @getPointer(ptr [[PTR]]) +; CHECK-NEXT: [[A:%.*]] = load i8, ptr [[PTR2]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: ret i8 [[A]] +; entry: - %ptr = alloca i8 - store i8 42, ptr %ptr, !invariant.group !0 - %ptr2 = call ptr @getPointer(ptr %ptr) - %a = load i8, ptr %ptr2, !invariant.group !0 - -; CHECK: ret i8 %a - ret i8 %a + %ptr = alloca i8 + store i8 42, ptr %ptr, !invariant.group !0 + %ptr2 = call ptr @getPointer(ptr %ptr) + %a = load i8, ptr %ptr2, !invariant.group !0 + + ret i8 %a } -; CHECK-LABEL: define i8 @optimizable4() { define i8 @optimizable4() { +; CHECK-LABEL: define i8 @optimizable4() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: [[PTR2:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[PTR]]) +; CHECK-NEXT: ret i8 42 +; entry: - %ptr = alloca i8 - store i8 42, ptr %ptr, !invariant.group !0 - %ptr2 = call ptr @llvm.launder.invariant.group.p0(ptr %ptr) -; CHECK-NOT: load - %a = load i8, ptr %ptr2, !invariant.group !0 - -; CHECK: ret i8 42 - ret i8 %a + %ptr = alloca i8 + store i8 42, ptr %ptr, !invariant.group !0 + %ptr2 = call ptr @llvm.launder.invariant.group.p0(ptr %ptr) + %a = load i8, ptr %ptr2, !invariant.group !0 + + ret i8 %a } -; CHECK-LABEL: define i8 @volatile1() { define i8 @volatile1() { +; CHECK-LABEL: define i8 @volatile1() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: [[B:%.*]] = load volatile i8, ptr [[PTR]], align 1 +; CHECK-NEXT: call void @bar(i8 [[B]]) +; CHECK-NEXT: [[C:%.*]] = load volatile i8, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @bar(i8 [[C]]) +; CHECK-NEXT: ret i8 42 +; entry: - %ptr = alloca i8 - store i8 42, ptr %ptr, !invariant.group !0 - call void @foo(ptr %ptr) - %a = load i8, ptr %ptr, !invariant.group !0 - %b = load volatile i8, ptr %ptr -; CHECK: call void @bar(i8 %b) - call void @bar(i8 %b) - - %c = load volatile i8, ptr %ptr, !invariant.group !0 + %ptr = alloca i8 + store i8 42, ptr %ptr, !invariant.group !0 + call void @foo(ptr %ptr) + %a = load i8, ptr %ptr, !invariant.group !0 + %b = load volatile i8, ptr %ptr + call void @bar(i8 %b) + + %c = load volatile i8, ptr %ptr, !invariant.group !0 ; FIXME: we could change %c to 42, preserving volatile load -; CHECK: call void @bar(i8 %c) - call void @bar(i8 %c) -; CHECK: ret i8 42 - ret i8 %a + call void @bar(i8 %c) + ret i8 %a } -; CHECK-LABEL: define i8 @volatile2() { define i8 @volatile2() { +; CHECK-LABEL: define i8 @volatile2() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: [[B:%.*]] = load volatile i8, ptr [[PTR]], align 1 +; CHECK-NEXT: call void @bar(i8 [[B]]) +; CHECK-NEXT: [[C:%.*]] = load volatile i8, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @bar(i8 [[C]]) +; CHECK-NEXT: ret i8 42 +; entry: - %ptr = alloca i8 - store i8 42, ptr %ptr, !invariant.group !0 - call void @foo(ptr %ptr) - %a = load i8, ptr %ptr, !invariant.group !0 - %b = load volatile i8, ptr %ptr -; CHECK: call void @bar(i8 %b) - call void @bar(i8 %b) - - %c = load volatile i8, ptr %ptr, !invariant.group !0 + %ptr = alloca i8 + store i8 42, ptr %ptr, !invariant.group !0 + call void @foo(ptr %ptr) + %a = load i8, ptr %ptr, !invariant.group !0 + %b = load volatile i8, ptr %ptr + call void @bar(i8 %b) + + %c = load volatile i8, ptr %ptr, !invariant.group !0 ; FIXME: we could change %c to 42, preserving volatile load -; CHECK: call void @bar(i8 %c) - call void @bar(i8 %c) -; CHECK: ret i8 42 - ret i8 %a + call void @bar(i8 %c) + ret i8 %a } -; CHECK-LABEL: define i8 @fun() { define i8 @fun() { +; CHECK-LABEL: define i8 @fun() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: call void @bar(i8 42) +; CHECK-NEXT: [[NEWPTR:%.*]] = call ptr @getPointer(ptr [[PTR]]) +; CHECK-NEXT: [[C:%.*]] = load i8, ptr [[NEWPTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @bar(i8 [[C]]) +; CHECK-NEXT: [[UNKNOWNVALUE:%.*]] = load i8, ptr @unknownPtr, align 1 +; CHECK-NEXT: store i8 [[UNKNOWNVALUE]], ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: [[NEWPTR2:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[PTR]]) +; CHECK-NEXT: ret i8 [[UNKNOWNVALUE]] +; entry: - %ptr = alloca i8 - store i8 42, ptr %ptr, !invariant.group !0 - call void @foo(ptr %ptr) - - %a = load i8, ptr %ptr, !invariant.group !0 ; Can assume that value under %ptr didn't change -; CHECK: call void @bar(i8 42) - call void @bar(i8 %a) - - %newPtr = call ptr @getPointer(ptr %ptr) - %c = load i8, ptr %newPtr, !invariant.group !0 ; Can't assume anything, because we only have information about %ptr -; CHECK: call void @bar(i8 %c) - call void @bar(i8 %c) - - %unknownValue = load i8, ptr @unknownPtr + %ptr = alloca i8 + store i8 42, ptr %ptr, !invariant.group !0 + call void @foo(ptr %ptr) + + %a = load i8, ptr %ptr, !invariant.group !0 ; Can assume that value under %ptr didn't change + call void @bar(i8 %a) + + %newPtr = call ptr @getPointer(ptr %ptr) + %c = load i8, ptr %newPtr, !invariant.group !0 ; Can't assume anything, because we only have information about %ptr + call void @bar(i8 %c) + + %unknownValue = load i8, ptr @unknownPtr ; FIXME: Can assume that %unknownValue == 42 -; CHECK: store i8 %unknownValue, ptr %ptr, align 1, !invariant.group !0 - store i8 %unknownValue, ptr %ptr, !invariant.group !0 - - %newPtr2 = call ptr @llvm.launder.invariant.group.p0(ptr %ptr) -; CHECK-NOT: load - %d = load i8, ptr %newPtr2, !invariant.group !0 -; CHECK: ret i8 %unknownValue - ret i8 %d + store i8 %unknownValue, ptr %ptr, !invariant.group !0 + + %newPtr2 = call ptr @llvm.launder.invariant.group.p0(ptr %ptr) + %d = load i8, ptr %newPtr2, !invariant.group !0 + ret i8 %d } ; This test checks if invariant.group understands gep with zeros -; CHECK-LABEL: define void @testGEP0() { define void @testGEP0() { +; CHECK-LABEL: define void @testGEP0() { +; CHECK-NEXT: [[A:%.*]] = alloca [[STRUCT_A:%.*]], align 8 +; CHECK-NEXT: store ptr getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2), ptr [[A]], align 8, !invariant.group [[META0]] +; CHECK-NEXT: call void @_ZN1A3fooEv(ptr nonnull dereferenceable(8) [[A]]) +; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr @unknownPtr, align 4 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 0 +; CHECK-NEXT: br i1 [[TMP2]], label %[[_Z1GR1A_EXIT:.*]], label %[[BB3:.*]] +; CHECK: [[BB3]]: +; CHECK-NEXT: call void @_ZN1A3fooEv(ptr nonnull [[A]]) +; CHECK-NEXT: br label %[[_Z1GR1A_EXIT]] +; CHECK: [[_Z1GR1A_EXIT]]: +; CHECK-NEXT: ret void +; %a = alloca %struct.A, align 8 store ptr getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2), ptr %a, align 8, !invariant.group !0 -; CHECK: call void @_ZN1A3fooEv(ptr nonnull dereferenceable(8) %a) call void @_ZN1A3fooEv(ptr nonnull dereferenceable(8) %a) ; This call may change vptr %1 = load i8, ptr @unknownPtr, align 4 %2 = icmp eq i8 %1, 0 @@ -326,7 +442,6 @@ define void @testGEP0() { ; This should be devirtualized by invariant.group %4 = load ptr, ptr %a, align 8, !invariant.group !0 %5 = load ptr, ptr %4, align 8 -; CHECK: call void @_ZN1A3fooEv(ptr nonnull %a) call void %5(ptr nonnull %a) br label %_Z1gR1A.exit @@ -337,51 +452,86 @@ _Z1gR1A.exit: ; preds = %0, %3 ; Check if no optimizations are performed with global pointers. ; FIXME: we could do the optimizations if we would check if dependency comes ; from the same function. -; CHECK-LABEL: define void @testGlobal() { define void @testGlobal() { -; CHECK: %a = load i8, ptr @unknownPtr, align 1, !invariant.group !0 - %a = load i8, ptr @unknownPtr, !invariant.group !0 - call void @foo2(ptr @unknownPtr, i8 %a) -; CHECK: %1 = load i8, ptr @unknownPtr, align 1, !invariant.group !0 - %1 = load i8, ptr @unknownPtr, !invariant.group !0 - call void @bar(i8 %1) - - call void @fooBit(ptr @unknownPtr, i1 1) +; CHECK-LABEL: define void @testGlobal() { +; CHECK-NEXT: [[A:%.*]] = load i8, ptr @unknownPtr, align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @foo2(ptr @unknownPtr, i8 [[A]]) +; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr @unknownPtr, align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @bar(i8 [[TMP1]]) +; CHECK-NEXT: call void @fooBit(ptr @unknownPtr, i1 true) +; CHECK-NEXT: [[TMP2:%.*]] = load i1, ptr @unknownPtr, align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @fooBit(ptr @unknownPtr, i1 [[TMP2]]) +; CHECK-NEXT: [[TMP3:%.*]] = load i1, ptr @unknownPtr, align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @fooBit(ptr @unknownPtr, i1 [[TMP3]]) +; CHECK-NEXT: ret void +; + %a = load i8, ptr @unknownPtr, !invariant.group !0 + call void @foo2(ptr @unknownPtr, i8 %a) + %1 = load i8, ptr @unknownPtr, !invariant.group !0 + call void @bar(i8 %1) + + call void @fooBit(ptr @unknownPtr, i1 1) ; Adding regex because of canonicalization of bitcasts -; CHECK: %2 = load i1, ptr {{.*}}, !invariant.group !0 - %2 = load i1, ptr @unknownPtr, !invariant.group !0 - call void @fooBit(ptr @unknownPtr, i1 %2) -; CHECK: %3 = load i1, ptr {{.*}}, !invariant.group !0 - %3 = load i1, ptr @unknownPtr, !invariant.group !0 - call void @fooBit(ptr @unknownPtr, i1 %3) - ret void + %2 = load i1, ptr @unknownPtr, !invariant.group !0 + call void @fooBit(ptr @unknownPtr, i1 %2) + %3 = load i1, ptr @unknownPtr, !invariant.group !0 + call void @fooBit(ptr @unknownPtr, i1 %3) + ret void } ; And in the case it is not global -; CHECK-LABEL: define void @testNotGlobal() { define void @testNotGlobal() { - %a = alloca i8 - call void @foo(ptr %a) -; CHECK: %b = load i8, ptr %a, align 1, !invariant.group !0 - %b = load i8, ptr %a, !invariant.group !0 - call void @foo2(ptr %a, i8 %b) - - %1 = load i8, ptr %a, !invariant.group !0 -; CHECK: call void @bar(i8 %b) - call void @bar(i8 %1) - - call void @fooBit(ptr %a, i1 1) -; CHECK: %1 = trunc i8 %b to i1 - %2 = load i1, ptr %a, !invariant.group !0 -; CHECK-NEXT: call void @fooBit(ptr %a, i1 %1) - call void @fooBit(ptr %a, i1 %2) - %3 = load i1, ptr %a, !invariant.group !0 -; CHECK-NEXT: call void @fooBit(ptr %a, i1 %1) - call void @fooBit(ptr %a, i1 %3) - ret void +; CHECK-LABEL: define void @testNotGlobal() { +; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1 +; CHECK-NEXT: call void @foo(ptr [[A]]) +; CHECK-NEXT: [[B:%.*]] = load i8, ptr [[A]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @foo2(ptr [[A]], i8 [[B]]) +; CHECK-NEXT: call void @bar(i8 [[B]]) +; CHECK-NEXT: call void @fooBit(ptr [[A]], i1 true) +; CHECK-NEXT: [[TMP1:%.*]] = trunc i8 [[B]] to i1 +; CHECK-NEXT: call void @fooBit(ptr [[A]], i1 [[TMP1]]) +; CHECK-NEXT: call void @fooBit(ptr [[A]], i1 [[TMP1]]) +; CHECK-NEXT: ret void +; + %a = alloca i8 + call void @foo(ptr %a) + %b = load i8, ptr %a, !invariant.group !0 + call void @foo2(ptr %a, i8 %b) + + %1 = load i8, ptr %a, !invariant.group !0 + call void @bar(i8 %1) + + call void @fooBit(ptr %a, i1 1) + %2 = load i1, ptr %a, !invariant.group !0 + call void @fooBit(ptr %a, i1 %2) + %3 = load i1, ptr %a, !invariant.group !0 + call void @fooBit(ptr %a, i1 %3) + ret void } -; CHECK-LABEL: define void @handling_loops() define void @handling_loops() { +; CHECK-LABEL: define void @handling_loops() { +; CHECK-NEXT: [[A:%.*]] = alloca [[STRUCT_A:%.*]], align 8 +; CHECK-NEXT: store ptr getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2), ptr [[A]], align 8, !invariant.group [[META0]] +; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr @unknownPtr, align 4 +; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i8 [[TMP1]], 0 +; CHECK-NEXT: br i1 [[TMP2]], [[DOTLR_PH_I:label %.*]], label %[[_Z2G2R1A_EXIT:.*]] +; CHECK: [[_LR_PH_I:.*:]] +; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i8 [[TMP1]], 1 +; CHECK-NEXT: br i1 [[TMP3]], label %[[DOT_CRIT_EDGE_PREHEADER:.*]], label %[[_Z2G2R1A_EXIT]] +; CHECK: [[__CRIT_EDGE_PREHEADER:.*:]] +; CHECK-NEXT: br label %[[DOT_CRIT_EDGE:.*]] +; CHECK: [[__CRIT_EDGE:.*:]] +; CHECK-NEXT: [[TMP4:%.*]] = phi i8 [ [[TMP5:%.*]], %[[DOT_CRIT_EDGE]] ], [ 1, %[[DOT_CRIT_EDGE_PREHEADER]] ] +; CHECK-NEXT: call void @_ZN1A3fooEv(ptr nonnull [[A]]) +; CHECK-NEXT: [[TMP5]] = add nuw nsw i8 [[TMP4]], 1 +; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr @unknownPtr, align 4 +; CHECK-NEXT: [[TMP7:%.*]] = icmp slt i8 [[TMP5]], [[TMP6]] +; CHECK-NEXT: br i1 [[TMP7]], label %[[DOT_CRIT_EDGE]], label %[[_Z2G2R1A_EXIT_LOOPEXIT:.*]] +; CHECK: [[_Z2G2R1A_EXIT_LOOPEXIT]]: +; CHECK-NEXT: br label %[[_Z2G2R1A_EXIT]] +; CHECK: [[_Z2G2R1A_EXIT]]: +; CHECK-NEXT: ret void +; %a = alloca %struct.A, align 8 store ptr getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2), ptr %a, align 8, !invariant.group !0 %1 = load i8, ptr @unknownPtr, align 4 @@ -400,9 +550,7 @@ define void @handling_loops() { %5 = phi i8 [ %7, %._crit_edge ], [ 1, %._crit_edge.preheader ] %.pre = load ptr, ptr %a, align 8, !invariant.group !0 %6 = load ptr, ptr %.pre, align 8 - ; CHECK: call void @_ZN1A3fooEv(ptr nonnull %a) call void %6(ptr nonnull %a) #3 - ; CHECK-NOT: call void % %7 = add nuw nsw i8 %5, 1 %8 = load i8, ptr @unknownPtr, align 4 %9 = icmp slt i8 %7, %8 @@ -432,3 +580,6 @@ declare void @llvm.assume(i1 %cmp.vtables) !0 = !{} +;. +; CHECK: [[META0]] = !{} +;. diff --git a/llvm/test/Transforms/GVN/invariant.start.ll b/llvm/test/Transforms/GVN/invariant.start.ll index f2d7dd0..6f38197 100644 --- a/llvm/test/Transforms/GVN/invariant.start.ll +++ b/llvm/test/Transforms/GVN/invariant.start.ll @@ -1,16 +1,19 @@ -; Test to make sure llvm.invariant.start calls are not treated as clobbers. +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt < %s -passes=gvn -S | FileCheck %s +; Test to make sure llvm.invariant.start calls are not treated as clobbers. declare ptr @llvm.invariant.start.p0(i64, ptr nocapture) nounwind readonly declare void @llvm.invariant.end.p0(ptr, i64, ptr nocapture) nounwind ; We forward store to the load across the invariant.start intrinsic define i8 @forward_store() { -; CHECK-LABEL: @forward_store -; CHECK: call ptr @llvm.invariant.start.p0(i64 1, ptr %a) -; CHECK-NOT: load -; CHECK: ret i8 0 +; CHECK-LABEL: define i8 @forward_store() { +; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 0, ptr [[A]], align 1 +; CHECK-NEXT: [[I:%.*]] = call ptr @llvm.invariant.start.p0(i64 1, ptr [[A]]) +; CHECK-NEXT: ret i8 0 +; %a = alloca i8 store i8 0, ptr %a %i = call ptr @llvm.invariant.start.p0(i64 1, ptr %a) @@ -23,10 +26,18 @@ declare i8 @dummy(ptr nocapture) nounwind readonly ; We forward store to the load in the non-local analysis case, ; i.e. invariant.start is in another basic block. define i8 @forward_store_nonlocal(i1 %cond) { -; CHECK-LABEL: forward_store_nonlocal -; CHECK: call ptr @llvm.invariant.start.p0(i64 1, ptr %a) -; CHECK: ret i8 0 -; CHECK: ret i8 %val +; CHECK-LABEL: define i8 @forward_store_nonlocal( +; CHECK-SAME: i1 [[COND:%.*]]) { +; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 0, ptr [[A]], align 1 +; CHECK-NEXT: [[I:%.*]] = call ptr @llvm.invariant.start.p0(i64 1, ptr [[A]]) +; CHECK-NEXT: br i1 [[COND]], label %[[LOADBLOCK:.*]], label %[[EXIT:.*]] +; CHECK: [[LOADBLOCK]]: +; CHECK-NEXT: ret i8 0 +; CHECK: [[EXIT]]: +; CHECK-NEXT: [[VAL:%.*]] = call i8 @dummy(ptr [[A]]) +; CHECK-NEXT: ret i8 [[VAL]] +; %a = alloca i8 store i8 0, ptr %a %i = call ptr @llvm.invariant.start.p0(i64 1, ptr %a) @@ -43,12 +54,14 @@ exit: ; We should not value forward %foo to the invariant.end corresponding to %bar. define i8 @forward_store1() { -; CHECK-LABEL: forward_store1 -; CHECK: %foo = call ptr @llvm.invariant.start.p0 -; CHECK-NOT: load -; CHECK: %bar = call ptr @llvm.invariant.start.p0 -; CHECK: call void @llvm.invariant.end.p0(ptr %bar, i64 1, ptr %a) -; CHECK: ret i8 0 +; CHECK-LABEL: define i8 @forward_store1() { +; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 0, ptr [[A]], align 1 +; CHECK-NEXT: [[FOO:%.*]] = call ptr @llvm.invariant.start.p0(i64 1, ptr [[A]]) +; CHECK-NEXT: [[BAR:%.*]] = call ptr @llvm.invariant.start.p0(i64 1, ptr [[A]]) +; CHECK-NEXT: call void @llvm.invariant.end.p0(ptr [[BAR]], i64 1, ptr [[A]]) +; CHECK-NEXT: ret i8 0 +; %a = alloca i8 store i8 0, ptr %a %foo = call ptr @llvm.invariant.start.p0(i64 1, ptr %a) diff --git a/llvm/test/Transforms/GVN/load-constant-mem.ll b/llvm/test/Transforms/GVN/load-constant-mem.ll index d5858d6..f5b0d7c 100644 --- a/llvm/test/Transforms/GVN/load-constant-mem.ll +++ b/llvm/test/Transforms/GVN/load-constant-mem.ll @@ -1,19 +1,21 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt < %s -passes=gvn,instcombine -S | FileCheck %s + ; PR4189 @G = external constant [4 x i32] define i32 @test(ptr %p, i32 %i) nounwind { +; CHECK-LABEL: define i32 @test( +; CHECK-SAME: ptr [[P:%.*]], i32 [[I:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: store i8 4, ptr [[P]], align 1 +; CHECK-NEXT: ret i32 0 +; entry: - %P = getelementptr [4 x i32], ptr @G, i32 0, i32 %i - %A = load i32, ptr %P - store i8 4, ptr %p - %B = load i32, ptr %P - %C = sub i32 %A, %B - ret i32 %C + %P = getelementptr [4 x i32], ptr @G, i32 0, i32 %i + %A = load i32, ptr %P + store i8 4, ptr %p + %B = load i32, ptr %P + %C = sub i32 %A, %B + ret i32 %C } - -; CHECK: define i32 @test(ptr %p, i32 %i) #0 { -; CHECK-NEXT: entry: -; CHECK-NEXT: store i8 4, ptr %p, align 1 -; CHECK-NEXT: ret i32 0 -; CHECK-NEXT: } diff --git a/llvm/test/Transforms/GVN/load-from-unreachable-predecessor.ll b/llvm/test/Transforms/GVN/load-from-unreachable-predecessor.ll index 6ad0f59..c0b20d3 100644 --- a/llvm/test/Transforms/GVN/load-from-unreachable-predecessor.ll +++ b/llvm/test/Transforms/GVN/load-from-unreachable-predecessor.ll @@ -1,12 +1,21 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=gvn -S < %s | FileCheck %s ; Check that an unreachable predecessor to a PHI node doesn't cause a crash. -; PR21625. - +; PR21625. The first load should be removed, since it's ignored. define i32 @f(ptr %f) { -; CHECK: bb0: -; Load should be removed, since it's ignored. -; CHECK-NEXT: br label +; CHECK-LABEL: define i32 @f( +; CHECK-SAME: ptr [[F:%.*]]) { +; CHECK-NEXT: [[BB0:.*]]: +; CHECK-NEXT: br label %[[BB2:.*]] +; CHECK: [[BB1:.*]]: +; CHECK-NEXT: [[ZED:%.*]] = load ptr, ptr [[F]], align 8 +; CHECK-NEXT: br i1 false, label %[[BB1]], label %[[BB2]] +; CHECK: [[BB2]]: +; CHECK-NEXT: [[FOO:%.*]] = phi ptr [ null, %[[BB0]] ], [ [[ZED]], %[[BB1]] ] +; CHECK-NEXT: [[STOREMERGE:%.*]] = load i32, ptr [[FOO]], align 4 +; CHECK-NEXT: ret i32 [[STOREMERGE]] +; bb0: %bar = load ptr, ptr %f br label %bb2 diff --git a/llvm/test/Transforms/GVN/malloc-load-removal.ll b/llvm/test/Transforms/GVN/malloc-load-removal.ll index 0aa4beb..c86990f 100644 --- a/llvm/test/Transforms/GVN/malloc-load-removal.ll +++ b/llvm/test/Transforms/GVN/malloc-load-removal.ll @@ -1,4 +1,6 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -S -passes=gvn < %s | FileCheck %s + ; PR13694 target datalayout = "e-p:64:64:64-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" @@ -6,6 +8,17 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3 declare noalias ptr @malloc(i64) nounwind allockind("alloc,uninitialized") allocsize(0) define noalias ptr @test1() nounwind uwtable ssp { +; CHECK-LABEL: define noalias ptr @test1( +; CHECK-SAME: ) #[[ATTR1:[0-9]+]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @malloc(i64 100) #[[ATTR2:[0-9]+]] +; CHECK-NEXT: br i1 undef, label %[[IF_END:.*]], label %[[IF_THEN:.*]] +; CHECK: [[IF_THEN]]: +; CHECK-NEXT: store i8 0, ptr [[CALL]], align 1 +; CHECK-NEXT: br label %[[IF_END]] +; CHECK: [[IF_END]]: +; CHECK-NEXT: ret ptr [[CALL]] +; entry: %call = tail call ptr @malloc(i64 100) nounwind %0 = load i8, ptr %call, align 1 @@ -18,19 +31,22 @@ if.then: ; preds = %entry if.end: ; preds = %if.then, %entry ret ptr %call - -; CHECK-LABEL: @test1( -; CHECK-NOT: load -; CHECK-NOT: icmp - -; CHECK_NO_LIBCALLS-LABEL: @test1( -; CHECK_NO_LIBCALLS: load -; CHECK_NO_LIBCALLS: icmp } declare noalias ptr @_Znwm(i64) nounwind define noalias ptr @test2() nounwind uwtable ssp { +; CHECK-LABEL: define noalias ptr @test2( +; CHECK-SAME: ) #[[ATTR1]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @_Znwm(i64 100) #[[ATTR2]] +; CHECK-NEXT: br i1 undef, label %[[IF_END:.*]], label %[[IF_THEN:.*]] +; CHECK: [[IF_THEN]]: +; CHECK-NEXT: store i8 0, ptr [[CALL]], align 1 +; CHECK-NEXT: br label %[[IF_END]] +; CHECK: [[IF_END]]: +; CHECK-NEXT: ret ptr [[CALL]] +; entry: %call = tail call ptr @_Znwm(i64 100) nounwind %0 = load i8, ptr %call, align 1 @@ -43,19 +59,22 @@ if.then: ; preds = %entry if.end: ; preds = %if.then, %entry ret ptr %call - -; CHECK-LABEL: @test2( -; CHECK-NOT: load -; CHECK-NOT: icmp - -; CHECK_NO_LIBCALLS-LABEL: @test2( -; CHECK_NO_LIBCALLS: load -; CHECK_NO_LIBCALLS: icmp } declare noalias ptr @aligned_alloc(i64 allocalign, i64) nounwind allockind("alloc,uninitialized,aligned") allocsize(1) define noalias ptr @test3() nounwind uwtable ssp { +; CHECK-LABEL: define noalias ptr @test3( +; CHECK-SAME: ) #[[ATTR1]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @aligned_alloc(i64 256, i64 32) #[[ATTR2]] +; CHECK-NEXT: br i1 undef, label %[[IF_END:.*]], label %[[IF_THEN:.*]] +; CHECK: [[IF_THEN]]: +; CHECK-NEXT: store i8 0, ptr [[CALL]], align 1 +; CHECK-NEXT: br label %[[IF_END]] +; CHECK: [[IF_END]]: +; CHECK-NEXT: ret ptr [[CALL]] +; entry: %call = tail call ptr @aligned_alloc(i64 256, i64 32) nounwind %0 = load i8, ptr %call, align 32 @@ -68,12 +87,4 @@ if.then: ; preds = %entry if.end: ; preds = %if.then, %entry ret ptr %call - -; CHECK-LABEL: @test3( -; CHECK-NOT: load -; CHECK-NOT: icmp - -; CHECK_NO_LIBCALLS-LABEL: @test3( -; CHECK_NO_LIBCALLS: load -; CHECK_NO_LIBCALLS: icmp } diff --git a/llvm/test/Transforms/GVN/mssa-update-dead-def.ll b/llvm/test/Transforms/GVN/mssa-update-dead-def.ll index ad71a04..1a5b704 100644 --- a/llvm/test/Transforms/GVN/mssa-update-dead-def.ll +++ b/llvm/test/Transforms/GVN/mssa-update-dead-def.ll @@ -1,12 +1,28 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes='require<memoryssa>,gvn' -verify-memoryssa -S %s | FileCheck %s ; This is a regression test for a bug in MemorySSA updater. ; Make sure that we don't crash and end up with a valid MemorySSA. -; CHECK: @test() define void @test() personality ptr null { +; CHECK-LABEL: define void @test() personality ptr null { +; CHECK-NEXT: invoke void @bar() +; CHECK-NEXT: to label %[[BAR_NORMAL:.*]] unwind label %[[EXCEPTIONAL:.*]] +; CHECK: [[BAR_NORMAL]]: +; CHECK-NEXT: ret void +; CHECK: [[DEAD_BLOCK:.*:]] +; CHECK-NEXT: invoke void @baz() +; CHECK-NEXT: to label %[[BAZ_NORMAL:.*]] unwind label %[[EXCEPTIONAL]] +; CHECK: [[BAZ_NORMAL]]: +; CHECK-NEXT: ret void +; CHECK: [[EXCEPTIONAL]]: +; CHECK-NEXT: [[TMP9:%.*]] = landingpad { ptr, i32 } +; CHECK-NEXT: cleanup +; CHECK-NEXT: call void @foo() +; CHECK-NEXT: ret void +; invoke void @bar() - to label %bar.normal unwind label %exceptional + to label %bar.normal unwind label %exceptional bar.normal: ret void @@ -16,14 +32,14 @@ dead.block: baz.invoke: invoke void @baz() - to label %baz.normal unwind label %exceptional + to label %baz.normal unwind label %exceptional baz.normal: ret void exceptional: %tmp9 = landingpad { ptr, i32 } - cleanup + cleanup call void @foo() ret void } diff --git a/llvm/test/Transforms/GVN/no-mem-dep-info.ll b/llvm/test/Transforms/GVN/no-mem-dep-info.ll index 0380b7e..5f67902 100644 --- a/llvm/test/Transforms/GVN/no-mem-dep-info.ll +++ b/llvm/test/Transforms/GVN/no-mem-dep-info.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt %s -passes=gvn -S -enable-gvn-memdep=false | FileCheck %s ; RUN: opt %s -passes=gvn -S -enable-gvn-memdep=true | FileCheck %s @@ -11,6 +12,17 @@ declare <8 x float> @llvm.x86.avx2.gather.d.ps.256(<8 x float>, ptr, <8 x i32>, ; Function Attrs: nounwind define <8 x float> @foo1(ptr noalias readonly %arr.ptr, ptr noalias readonly %vix.ptr, ptr noalias %t2.ptr) #1 { +; CHECK-LABEL: define <8 x float> @foo1( +; CHECK-SAME: ptr noalias readonly [[ARR_PTR:%.*]], ptr noalias readonly [[VIX_PTR:%.*]], ptr noalias [[T2_PTR:%.*]]) { +; CHECK-NEXT: [[ALLOCAS:.*:]] +; CHECK-NEXT: [[VIX:%.*]] = load <8 x i32>, ptr [[VIX_PTR]], align 4 +; CHECK-NEXT: [[T1_PTR:%.*]] = getelementptr i8, ptr [[ARR_PTR]], i8 4 +; CHECK-NEXT: [[V1:%.*]] = tail call <8 x float> @llvm.x86.avx2.gather.d.ps.256(<8 x float> undef, ptr [[ARR_PTR]], <8 x i32> [[VIX]], <8 x float> splat (float 0xFFFFFFFFE0000000), i8 1) +; CHECK-NEXT: store i8 1, ptr [[T1_PTR]], align 4 +; CHECK-NEXT: [[V2:%.*]] = tail call <8 x float> @llvm.x86.avx2.gather.d.ps.256(<8 x float> undef, ptr [[ARR_PTR]], <8 x i32> [[VIX]], <8 x float> splat (float 0xFFFFFFFFE0000000), i8 1) +; CHECK-NEXT: [[RES:%.*]] = fadd <8 x float> [[V1]], [[V2]] +; CHECK-NEXT: ret <8 x float> [[RES]] +; allocas: %vix = load <8 x i32>, ptr %vix.ptr, align 4 %t1.ptr = getelementptr i8, ptr %arr.ptr, i8 4 @@ -23,7 +35,3 @@ allocas: ret <8 x float> %res } -; CHECK: foo1 -; CHECK: llvm.x86.avx2.gather.d.ps.256 -; CHECK: store -; CHECK: llvm.x86.avx2.gather.d.ps.256 diff --git a/llvm/test/Transforms/GVN/noalias.ll b/llvm/test/Transforms/GVN/noalias.ll index 98cc930..f28023d 100644 --- a/llvm/test/Transforms/GVN/noalias.ll +++ b/llvm/test/Transforms/GVN/noalias.ll @@ -1,9 +1,13 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=gvn -S < %s | FileCheck %s define i32 @test1(ptr %p, ptr %q) { -; CHECK-LABEL: @test1(ptr %p, ptr %q) -; CHECK: load i32, ptr %p, align 4, !noalias ![[SCOPE1:[0-9]+]] -; CHECK: %c = add i32 %a, %a +; CHECK-LABEL: define i32 @test1( +; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { +; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 4, !noalias [[META0:![0-9]+]] +; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] +; CHECK-NEXT: ret i32 [[C]] +; %a = load i32, ptr %p, !noalias !3 %b = load i32, ptr %p %c = add i32 %a, %b @@ -11,9 +15,12 @@ define i32 @test1(ptr %p, ptr %q) { } define i32 @test2(ptr %p, ptr %q) { -; CHECK-LABEL: @test2(ptr %p, ptr %q) -; CHECK: load i32, ptr %p, align 4, !alias.scope ![[SCOPE1]] -; CHECK: %c = add i32 %a, %a +; CHECK-LABEL: define i32 @test2( +; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { +; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 4, !alias.scope [[META0]] +; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] +; CHECK-NEXT: ret i32 [[C]] +; %a = load i32, ptr %p, !alias.scope !3 %b = load i32, ptr %p, !alias.scope !3 %c = add i32 %a, %b @@ -21,17 +28,18 @@ define i32 @test2(ptr %p, ptr %q) { } define i32 @test3(ptr %p, ptr %q) { -; CHECK-LABEL: @test3(ptr %p, ptr %q) -; CHECK: load i32, ptr %p, align 4, !alias.scope ![[SCOPE2:[0-9]+]] -; CHECK: %c = add i32 %a, %a +; CHECK-LABEL: define i32 @test3( +; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { +; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 4, !alias.scope [[META3:![0-9]+]] +; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] +; CHECK-NEXT: ret i32 [[C]] +; %a = load i32, ptr %p, !alias.scope !4 %b = load i32, ptr %p, !alias.scope !5 %c = add i32 %a, %b ret i32 %c } -; CHECK: ![[SCOPE1]] = !{!{{[0-9]+}}} -; CHECK: ![[SCOPE2]] = !{!{{[0-9]+}}} declare i32 @foo(ptr) readonly !0 = distinct !{!0, !2, !"callee0: %a"} @@ -41,3 +49,10 @@ declare i32 @foo(ptr) readonly !3 = !{!0} !4 = !{!1} !5 = !{!0, !1} +;. +; CHECK: [[META0]] = !{[[META1:![0-9]+]]} +; CHECK: [[META1]] = distinct !{[[META1]], [[META2:![0-9]+]], !"callee0: %a"} +; CHECK: [[META2]] = distinct !{[[META2]], !"callee0"} +; CHECK: [[META3]] = !{[[META4:![0-9]+]]} +; CHECK: [[META4]] = distinct !{[[META4]], [[META2]], !"callee0: %b"} +;. diff --git a/llvm/test/Transforms/GVN/non-local-offset.ll b/llvm/test/Transforms/GVN/non-local-offset.ll index 0467657..19b571e 100644 --- a/llvm/test/Transforms/GVN/non-local-offset.ll +++ b/llvm/test/Transforms/GVN/non-local-offset.ll @@ -1,16 +1,24 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=gvn -S < %s | FileCheck %s target datalayout = "e-p:64:64:64" ; GVN should ignore the store to p[1] to see that the load from p[0] is ; fully redundant. - -; CHECK-LABEL: @yes( -; CHECK: if.then: -; CHECK-NEXT: store i32 0, ptr %q -; CHECK-NEXT: ret void - define void @yes(i1 %c, ptr %p, ptr %q) nounwind { +; CHECK-LABEL: define void @yes( +; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]], ptr [[Q:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: store i32 0, ptr [[P]], align 4 +; CHECK-NEXT: [[P1:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 1 +; CHECK-NEXT: store i32 1, ptr [[P1]], align 4 +; CHECK-NEXT: br i1 [[C]], label %[[IF_ELSE:.*]], label %[[IF_THEN:.*]] +; CHECK: [[IF_THEN]]: +; CHECK-NEXT: store i32 0, ptr [[Q]], align 4 +; CHECK-NEXT: ret void +; CHECK: [[IF_ELSE]]: +; CHECK-NEXT: ret void +; entry: store i32 0, ptr %p %p1 = getelementptr inbounds i32, ptr %p, i64 1 @@ -29,16 +37,22 @@ if.else: ; GVN should ignore the store to p[1] to see that the first load from p[0] is ; fully redundant. However, the second load is larger, so it's not a simple ; redundancy. - -; CHECK-LABEL: @watch_out_for_size_change( -; CHECK: if.then: -; CHECK-NEXT: store i32 0, ptr %q -; CHECK-NEXT: ret void -; CHECK: if.else: -; CHECK: load i64, ptr %p -; CHECK: store i64 - define void @watch_out_for_size_change(i1 %c, ptr %p, ptr %q) nounwind { +; CHECK-LABEL: define void @watch_out_for_size_change( +; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]], ptr [[Q:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: store i32 0, ptr [[P]], align 4 +; CHECK-NEXT: [[P1:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 1 +; CHECK-NEXT: store i32 1, ptr [[P1]], align 4 +; CHECK-NEXT: br i1 [[C]], label %[[IF_ELSE:.*]], label %[[IF_THEN:.*]] +; CHECK: [[IF_THEN]]: +; CHECK-NEXT: store i32 0, ptr [[Q]], align 4 +; CHECK-NEXT: ret void +; CHECK: [[IF_ELSE]]: +; CHECK-NEXT: [[T64:%.*]] = load i64, ptr [[P]], align 4 +; CHECK-NEXT: store i64 [[T64]], ptr [[Q]], align 4 +; CHECK-NEXT: ret void +; entry: store i32 0, ptr %p %p1 = getelementptr inbounds i32, ptr %p, i64 1 diff --git a/llvm/test/Transforms/GVN/nonescaping-malloc.ll b/llvm/test/Transforms/GVN/nonescaping-malloc.ll index 76d8cda..f67c958 100644 --- a/llvm/test/Transforms/GVN/nonescaping-malloc.ll +++ b/llvm/test/Transforms/GVN/nonescaping-malloc.ll @@ -1,5 +1,7 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; REQUIRES: asserts ; RUN: opt < %s -passes=gvn -stats -disable-output 2>&1 | FileCheck %s + ; rdar://7363102 ; CHECK: Number of loads deleted @@ -102,3 +104,5 @@ _ZN4llvm9StringMapIPvNS_15MallocAllocatorEE16GetOrCreateValueIS1_EERNS_14StringM } declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) nounwind +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; CHECK: {{.*}} diff --git a/llvm/test/Transforms/GVN/null-aliases-nothing.ll b/llvm/test/Transforms/GVN/null-aliases-nothing.ll index dc4ff406..81d44ce 100644 --- a/llvm/test/Transforms/GVN/null-aliases-nothing.ll +++ b/llvm/test/Transforms/GVN/null-aliases-nothing.ll @@ -1,19 +1,24 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt < %s -passes=gvn -S | FileCheck %s %t = type { i32 } declare void @test1f(ptr) -define void @test1(ptr noalias %stuff ) { - %before = load i32, ptr %stuff - - call void @test1f(ptr null) - - %after = load i32, ptr %stuff ; <--- This should be a dead load - %sum = add i32 %before, %after - - store i32 %sum, ptr %stuff - ret void -; CHECK: load -; CHECK-NOT: load -; CHECK: ret void +; `%stuff` is noalias, `test1f` receives only null, cannot clobber `%stuff`, +; thus the second load is dead. +define void @test1(ptr noalias %stuff) { +; CHECK-LABEL: define void @test1( +; CHECK-SAME: ptr noalias [[STUFF:%.*]]) { +; CHECK-NEXT: [[BEFORE:%.*]] = load i32, ptr [[STUFF]], align 4 +; CHECK-NEXT: call void @test1f(ptr null) +; CHECK-NEXT: [[SUM:%.*]] = add i32 [[BEFORE]], [[BEFORE]] +; CHECK-NEXT: store i32 [[SUM]], ptr [[STUFF]], align 4 +; CHECK-NEXT: ret void +; + %before = load i32, ptr %stuff + call void @test1f(ptr null) + %after = load i32, ptr %stuff + %sum = add i32 %before, %after + store i32 %sum, ptr %stuff + ret void } diff --git a/llvm/test/Transforms/GVN/phi-translate-partial-alias.ll b/llvm/test/Transforms/GVN/phi-translate-partial-alias.ll index a102976..358816f 100644 --- a/llvm/test/Transforms/GVN/phi-translate-partial-alias.ll +++ b/llvm/test/Transforms/GVN/phi-translate-partial-alias.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=gvn -S < %s | FileCheck %s target datalayout = "e-p:64:64:64-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-f128:128:128-n8:16:32:64" @@ -6,12 +7,19 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3 ; not actually redundant around the loop backedge, despite appearances ; if phi-translation is ignored. -; CHECK: define void @test0(ptr %begin) -; CHECK: loop: -; CHECK: %l0 = load i8, ptr %phi -; CHECK: call void @bar(i8 %l0) -; CHECK: %l1 = load i8, ptr %phi define void @test0(ptr %begin) { +; CHECK-LABEL: define void @test0( +; CHECK-SAME: ptr [[BEGIN:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[BEGIN]], %[[ENTRY]] ], [ [[NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[L0:%.*]] = load i8, ptr [[PHI]], align 1 +; CHECK-NEXT: call void @bar(i8 [[L0]]) +; CHECK-NEXT: [[L1:%.*]] = load i8, ptr [[PHI]], align 1 +; CHECK-NEXT: [[NEXT]] = getelementptr inbounds i8, ptr [[PHI]], i8 [[L1]] +; CHECK-NEXT: br label %[[LOOP]] +; entry: br label %loop diff --git a/llvm/test/Transforms/GVN/pr10820.ll b/llvm/test/Transforms/GVN/pr10820.ll index 48b13a4..4b7be9c 100644 --- a/llvm/test/Transforms/GVN/pr10820.ll +++ b/llvm/test/Transforms/GVN/pr10820.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt < %s -passes=gvn -S | FileCheck %s target datalayout = @@ -7,12 +8,16 @@ target triple = "x86_64-unknown-linux-gnu" @g = external global i31 define void @main() nounwind uwtable { +; CHECK-LABEL: define void @main( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: store i32 402662078, ptr @g, align 8 +; CHECK-NEXT: store i31 402662078, ptr undef, align 1 +; CHECK-NEXT: unreachable +; entry: -; CHECK: store i32 store i32 402662078, ptr @g, align 8 -; CHECK-NOT: load i31 %0 = load i31, ptr @g, align 8 -; CHECK: store i31 store i31 %0, ptr undef, align 1 unreachable } diff --git a/llvm/test/Transforms/GVN/pr12979.ll b/llvm/test/Transforms/GVN/pr12979.ll index 2f7a463..5ff3aa2 100644 --- a/llvm/test/Transforms/GVN/pr12979.ll +++ b/llvm/test/Transforms/GVN/pr12979.ll @@ -1,10 +1,13 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=gvn -S < %s | FileCheck %s define i32 @test1(i32 %x, i32 %y) { -; CHECK: @test1(i32 %x, i32 %y) -; CHECK: %add1 = add i32 %x, %y -; CHECK: %foo = add i32 %add1, %add1 - +; CHECK-LABEL: define i32 @test1( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[X]], [[Y]] +; CHECK-NEXT: [[FOO:%.*]] = add i32 [[ADD1]], [[ADD1]] +; CHECK-NEXT: ret i32 [[FOO]] +; %add1 = add nsw i32 %x, %y %add2 = add i32 %x, %y %foo = add i32 %add1, %add2 @@ -12,10 +15,12 @@ define i32 @test1(i32 %x, i32 %y) { } define i32 @test2(i32 %x, i32 %y) { -; CHECK: @test2(i32 %x, i32 %y) -; CHECK: %add1 = add i32 %x, %y -; CHECK: %foo = add i32 %add1, %add1 - +; CHECK-LABEL: define i32 @test2( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[X]], [[Y]] +; CHECK-NEXT: [[FOO:%.*]] = add i32 [[ADD1]], [[ADD1]] +; CHECK-NEXT: ret i32 [[FOO]] +; %add1 = add nuw i32 %x, %y %add2 = add i32 %x, %y %foo = add i32 %add1, %add2 @@ -23,10 +28,12 @@ define i32 @test2(i32 %x, i32 %y) { } define i32 @test3(i32 %x, i32 %y) { -; CHECK: @test3(i32 %x, i32 %y) -; CHECK: %add1 = add i32 %x, %y -; CHECK: %foo = add i32 %add1, %add1 - +; CHECK-LABEL: define i32 @test3( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[X]], [[Y]] +; CHECK-NEXT: [[FOO:%.*]] = add i32 [[ADD1]], [[ADD1]] +; CHECK-NEXT: ret i32 [[FOO]] +; %add1 = add nuw nsw i32 %x, %y %add2 = add i32 %x, %y %foo = add i32 %add1, %add2 @@ -34,10 +41,12 @@ define i32 @test3(i32 %x, i32 %y) { } define i32 @test4(i32 %x, i32 %y) { -; CHECK: @test4(i32 %x, i32 %y) -; CHECK: %add1 = add nsw i32 %x, %y -; CHECK: %foo = add i32 %add1, %add1 - +; CHECK-LABEL: define i32 @test4( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[X]], [[Y]] +; CHECK-NEXT: [[FOO:%.*]] = add i32 [[ADD1]], [[ADD1]] +; CHECK-NEXT: ret i32 [[FOO]] +; %add1 = add nsw i32 %x, %y %add2 = add nsw i32 %x, %y %foo = add i32 %add1, %add2 @@ -45,10 +54,12 @@ define i32 @test4(i32 %x, i32 %y) { } define i32 @test5(i32 %x, i32 %y) { -; CHECK: @test5(i32 %x, i32 %y) -; CHECK: %add1 = add i32 %x, %y -; CHECK: %foo = add i32 %add1, %add1 - +; CHECK-LABEL: define i32 @test5( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[X]], [[Y]] +; CHECK-NEXT: [[FOO:%.*]] = add i32 [[ADD1]], [[ADD1]] +; CHECK-NEXT: ret i32 [[FOO]] +; %add1 = add nuw i32 %x, %y %add2 = add nsw i32 %x, %y %foo = add i32 %add1, %add2 @@ -56,10 +67,12 @@ define i32 @test5(i32 %x, i32 %y) { } define i32 @test6(i32 %x, i32 %y) { -; CHECK: @test6(i32 %x, i32 %y) -; CHECK: %add1 = add nsw i32 %x, %y -; CHECK: %foo = add i32 %add1, %add1 - +; CHECK-LABEL: define i32 @test6( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[X]], [[Y]] +; CHECK-NEXT: [[FOO:%.*]] = add i32 [[ADD1]], [[ADD1]] +; CHECK-NEXT: ret i32 [[FOO]] +; %add1 = add nuw nsw i32 %x, %y %add2 = add nsw i32 %x, %y %foo = add i32 %add1, %add2 @@ -67,11 +80,12 @@ define i32 @test6(i32 %x, i32 %y) { } define i32 @test7(i32 %x, i32 %y) { -; CHECK: @test7(i32 %x, i32 %y) -; CHECK: %add1 = add i32 %x, %y -; CHECK-NOT: what_is_this -; CHECK: %foo = add i32 %add1, %add1 - +; CHECK-LABEL: define i32 @test7( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[X]], [[Y]] +; CHECK-NEXT: [[FOO:%.*]] = add i32 [[ADD1]], [[ADD1]] +; CHECK-NEXT: ret i32 [[FOO]] +; %add1 = add i32 %x, %y, !what_is_this !{} %add2 = add i32 %x, %y %foo = add i32 %add1, %add2 @@ -81,11 +95,12 @@ define i32 @test7(i32 %x, i32 %y) { declare void @mumble(i2, i2) define void @test8(i2 %x) { -; CHECK-LABEL: @test8( -; CHECK: %[[ashr:.*]] = ashr i2 %x, 1 -; CHECK-NEXT: call void @mumble(i2 %[[ashr]], i2 %[[ashr]]) -; CHECK-NEXT: ret void - +; CHECK-LABEL: define void @test8( +; CHECK-SAME: i2 [[X:%.*]]) { +; CHECK-NEXT: [[ASHR0:%.*]] = ashr i2 [[X]], 1 +; CHECK-NEXT: call void @mumble(i2 [[ASHR0]], i2 [[ASHR0]]) +; CHECK-NEXT: ret void +; %ashr0 = ashr exact i2 %x, 1 %ashr1 = ashr i2 %x, 1 call void @mumble(i2 %ashr0, i2 %ashr1) diff --git a/llvm/test/Transforms/GVN/pr17732.ll b/llvm/test/Transforms/GVN/pr17732.ll index c6ebd7a..29c7931c 100644 --- a/llvm/test/Transforms/GVN/pr17732.ll +++ b/llvm/test/Transforms/GVN/pr17732.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=gvn -S -o - < %s | FileCheck %s target datalayout = "e-p:64:64:64-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" @@ -13,6 +14,12 @@ target triple = "x86_64-unknown-linux-gnu" @vector_with_zeroinit = common global %struct.with_vector zeroinitializer, align 4 define i32 @main() { +; CHECK-LABEL: define i32 @main() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr align 4 @array_with_zeroinit, ptr align 4 @main.obj_with_array, i64 12, i1 false) +; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr align 4 @vector_with_zeroinit, ptr align 4 @main.obj_with_vector, i64 12, i1 false) +; CHECK-NEXT: ret i32 1 +; entry: tail call void @llvm.memcpy.p0.p0.i64(ptr align 4 @array_with_zeroinit, ptr align 4 @main.obj_with_array, i64 12, i1 false) %0 = load i8, ptr getelementptr inbounds (%struct.with_array, ptr @array_with_zeroinit, i64 0, i32 2), align 4 @@ -23,8 +30,6 @@ entry: %conv1 = sext i8 %1 to i32 %and = and i32 %conv0, %conv1 ret i32 %and -; CHECK-LABEL: define i32 @main( -; CHECK: ret i32 1 } declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture readonly, i64, i1) diff --git a/llvm/test/Transforms/GVN/pr17852.ll b/llvm/test/Transforms/GVN/pr17852.ll index 731cbc6..c464cf2 100644 --- a/llvm/test/Transforms/GVN/pr17852.ll +++ b/llvm/test/Transforms/GVN/pr17852.ll @@ -1,7 +1,69 @@ -; RUN: opt < %s -passes=gvn +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 +; RUN: opt -passes=gvn -S -o - < %s | FileCheck %s + target datalayout = "e-p:64:64:64-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" %struct.S0 = type { [2 x i8], [2 x i8], [4 x i8], [2 x i8], i32, i32, i32, i32 } + define void @fn1(ptr byval(%struct.S0) align 8 %p1) { +; CHECK-LABEL: define void @fn1( +; CHECK-SAME: ptr byval([[STRUCT_S0:%.*]]) align 8 [[P1:%.*]]) { +; CHECK-NEXT: br label %[[FOR_COND:.*]] +; CHECK: [[FOR_COND]]: +; CHECK-NEXT: br i1 true, label %[[IF_ELSE:.*]], label %[[IF_THEN:.*]] +; CHECK: [[BB1:.*:]] +; CHECK-NEXT: [[F2:%.*]] = getelementptr inbounds [[STRUCT_S0]], ptr [[P1]], i64 0, i32 2 +; CHECK-NEXT: [[F9:%.*]] = getelementptr inbounds [[STRUCT_S0]], ptr [[P1]], i64 0, i32 7 +; CHECK-NEXT: br label %[[FOR_COND]] +; CHECK: [[IF_THEN]]: +; CHECK-NEXT: [[F22:%.*]] = getelementptr inbounds [[STRUCT_S0]], ptr [[P1]], i64 0, i32 2 +; CHECK-NEXT: [[F7:%.*]] = getelementptr inbounds [[STRUCT_S0]], ptr [[P1]], i64 0, i32 5 +; CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[F7]], align 8 +; CHECK-NEXT: br label %[[IF_END40:.*]] +; CHECK: [[IF_ELSE]]: +; CHECK-NEXT: br i1 false, label %[[FOR_COND18:.*]], label %[[IF_THEN6:.*]] +; CHECK: [[IF_THEN6]]: +; CHECK-NEXT: [[F3:%.*]] = getelementptr inbounds [[STRUCT_S0]], ptr [[P1]], i64 0, i32 2 +; CHECK-NEXT: [[F5:%.*]] = getelementptr inbounds [[STRUCT_S0]], ptr [[P1]], i64 0, i32 3 +; CHECK-NEXT: br label %[[IF_END36:.*]] +; CHECK: [[FOR_COND18]]: +; CHECK-NEXT: call void @fn4() +; CHECK-NEXT: br i1 true, label %[[IF_END:.*]], label %[[FOR_COND18_IF_END36_CRIT_EDGE:.*]] +; CHECK: [[FOR_COND18_IF_END36_CRIT_EDGE]]: +; CHECK-NEXT: br label %[[IF_END36]] +; CHECK: [[IF_END]]: +; CHECK-NEXT: [[F321:%.*]] = getelementptr inbounds [[STRUCT_S0]], ptr [[P1]], i64 0, i32 2 +; CHECK-NEXT: [[F925:%.*]] = getelementptr inbounds [[STRUCT_S0]], ptr [[P1]], i64 0, i32 7 +; CHECK-NEXT: [[F526:%.*]] = getelementptr inbounds [[STRUCT_S0]], ptr [[P1]], i64 0, i32 3 +; CHECK-NEXT: [[BF_LOAD27:%.*]] = load i16, ptr [[F526]], align 8 +; CHECK-NEXT: br label %[[IF_END36]] +; CHECK: [[IF_END36]]: +; CHECK-NEXT: [[F537:%.*]] = getelementptr inbounds [[STRUCT_S0]], ptr [[P1]], i64 0, i32 3 +; CHECK-NEXT: [[BF_LOAD38:%.*]] = load i16, ptr [[F537]], align 8 +; CHECK-NEXT: [[BF_CLEAR39:%.*]] = and i16 [[BF_LOAD38]], -16384 +; CHECK-NEXT: br label %[[IF_END40]] +; CHECK: [[IF_END40]]: +; CHECK-NEXT: [[BF_LOAD522:%.*]] = phi i16 [ [[BF_LOAD38]], %[[IF_END36]] ], [ poison, %[[IF_THEN]] ] +; CHECK-NEXT: [[F6:%.*]] = getelementptr inbounds [[STRUCT_S0]], ptr [[P1]], i64 0, i32 4 +; CHECK-NEXT: [[TMP18:%.*]] = load i32, ptr [[F6]], align 4 +; CHECK-NEXT: call void @fn2(i32 [[TMP18]]) +; CHECK-NEXT: [[F8:%.*]] = getelementptr inbounds [[STRUCT_S0]], ptr [[P1]], i64 0, i32 6 +; CHECK-NEXT: [[TMP19:%.*]] = load i32, ptr [[F8]], align 4 +; CHECK-NEXT: [[TOBOOL41:%.*]] = icmp eq i32 [[TMP19]], 0 +; CHECK-NEXT: br i1 true, label %[[IF_END40_IF_END50_CRIT_EDGE:.*]], label %[[IF_THEN42:.*]] +; CHECK: [[IF_END40_IF_END50_CRIT_EDGE]]: +; CHECK-NEXT: [[F551_PHI_TRANS_INSERT:%.*]] = getelementptr inbounds [[STRUCT_S0]], ptr [[P1]], i64 0, i32 3 +; CHECK-NEXT: [[BF_LOAD52_PRE:%.*]] = load i16, ptr [[F551_PHI_TRANS_INSERT]], align 8 +; CHECK-NEXT: br label %[[IF_END50:.*]] +; CHECK: [[IF_THEN42]]: +; CHECK-NEXT: [[F547:%.*]] = getelementptr inbounds [[STRUCT_S0]], ptr [[P1]], i64 0, i32 3 +; CHECK-NEXT: [[BF_LOAD48:%.*]] = load i16, ptr [[F547]], align 8 +; CHECK-NEXT: br label %[[IF_END50]] +; CHECK: [[IF_END50]]: +; CHECK-NEXT: [[BF_LOAD52:%.*]] = phi i16 [ [[BF_LOAD52_PRE]], %[[IF_END40_IF_END50_CRIT_EDGE]] ], [ [[BF_LOAD522]], %[[IF_THEN42]] ] +; CHECK-NEXT: [[F551:%.*]] = getelementptr inbounds [[STRUCT_S0]], ptr [[P1]], i64 0, i32 3 +; CHECK-NEXT: [[BF_CLEAR53:%.*]] = and i16 [[BF_LOAD52]], -16384 +; CHECK-NEXT: ret void +; br label %for.cond for.cond: ; preds = %1, %0 br label %for.end diff --git a/llvm/test/Transforms/GVN/pr24397.ll b/llvm/test/Transforms/GVN/pr24397.ll index 8ef9360..a663350 100644 --- a/llvm/test/Transforms/GVN/pr24397.ll +++ b/llvm/test/Transforms/GVN/pr24397.ll @@ -1,8 +1,21 @@ -; RUN: opt -passes=gvn -disable-output < %s +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 +; RUN: opt -passes=gvn -S -o - < %s | FileCheck %s target triple = "x86_64-unknown-linux-gnu" define i64 @foo(ptr %arrayidx) { +; CHECK-LABEL: define i64 @foo( +; CHECK-SAME: ptr [[ARRAYIDX:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[P:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8 +; CHECK-NEXT: [[CMPNULL:%.*]] = icmp eq ptr [[P]], null +; CHECK-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[P]] to i64 +; CHECK-NEXT: br label %[[BB2:.*]] +; CHECK: [[ENTRY2:.*:]] +; CHECK-NEXT: br label %[[BB2]] +; CHECK: [[BB2]]: +; CHECK-NEXT: ret i64 [[TMP0]] +; entry: %p = load ptr, ptr %arrayidx, align 8 %cmpnull = icmp eq ptr %p, null diff --git a/llvm/test/Transforms/GVN/pr24426.ll b/llvm/test/Transforms/GVN/pr24426.ll index 2a08857..d296e15a0 100644 --- a/llvm/test/Transforms/GVN/pr24426.ll +++ b/llvm/test/Transforms/GVN/pr24426.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt < %s -passes=memcpyopt,mldst-motion,gvn -S | FileCheck %s declare void @check(i8) @@ -5,13 +6,17 @@ declare void @check(i8) declare void @write(ptr %res) define void @test1() { +; CHECK-LABEL: define void @test1() { +; CHECK-NEXT: [[TMP1:%.*]] = alloca [10 x i8], align 1 +; CHECK-NEXT: call void @write(ptr [[TMP1]]) +; CHECK-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1 +; CHECK-NEXT: call void @check(i8 [[TMP2]]) +; CHECK-NEXT: ret void +; %1 = alloca [10 x i8] call void @write(ptr %1) %2 = load i8, ptr %1 - -; CHECK-NOT: undef call void @check(i8 %2) - ret void } diff --git a/llvm/test/Transforms/GVN/pr25440.ll b/llvm/test/Transforms/GVN/pr25440.ll index 507111ef..046775e 100644 --- a/llvm/test/Transforms/GVN/pr25440.ll +++ b/llvm/test/Transforms/GVN/pr25440.ll @@ -1,4 +1,5 @@ -;RUN: opt -passes=gvn -S < %s | FileCheck %s +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 +; RUN: opt -passes=gvn -S < %s | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n8:16:32-S64" target triple = "thumbv7--linux-gnueabi" @@ -10,19 +11,53 @@ target triple = "thumbv7--linux-gnueabi" ; Function Attrs: nounwind define fastcc void @foo(ptr nocapture readonly %x) { -;CHECK-LABEL: foo +; CHECK-LABEL: define fastcc void @foo( +; CHECK-SAME: ptr readonly captures(none) [[X:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: br label %[[BB0:.*]] +; CHECK: [[BB0]]: +; CHECK-NEXT: [[X_TR:%.*]] = phi ptr [ [[X]], %[[ENTRY]] ], [ null, %[[LAND_LHS_TRUE:.*]] ] +; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[X_TR]], align 4 +; CHECK-NEXT: [[CONV:%.*]] = zext i16 [[TMP0]] to i32 +; CHECK-NEXT: switch i32 [[CONV]], label %[[IF_END_50:.*]] [ +; CHECK-NEXT: i32 43, label %[[CLEANUP:.*]] +; CHECK-NEXT: i32 52, label %[[IF_THEN_5:.*]] +; CHECK-NEXT: ] +; CHECK: [[IF_THEN_5]]: +; CHECK-NEXT: br i1 undef, label %[[LAND_LHS_TRUE]], label %[[IF_THEN_26:.*]] +; CHECK: [[LAND_LHS_TRUE]]: +; CHECK-NEXT: br i1 undef, label %[[CLEANUP]], label %[[BB0]] +; CHECK: [[IF_THEN_26]]: +; CHECK-NEXT: br i1 undef, label %[[COND_END:.*]], label %[[COND_FALSE:.*]] +; CHECK: [[COND_FALSE]]: +; CHECK-NEXT: [[MODE:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[X_TR]], i32 0, i32 1 +; CHECK-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[MODE]], align 2 +; CHECK-NEXT: [[BF_SHL:%.*]] = shl i16 [[BF_LOAD]], 8 +; CHECK-NEXT: br label %[[COND_END]] +; CHECK: [[COND_END]]: +; CHECK-NEXT: br i1 undef, label %[[IF_THEN_44:.*]], label %[[CLEANUP]] +; CHECK: [[IF_THEN_44]]: +; CHECK-NEXT: unreachable +; CHECK: [[IF_END_50]]: +; CHECK-NEXT: [[ARRAYIDX52:%.*]] = getelementptr inbounds [0 x i32], ptr @length, i32 0, i32 [[CONV]] +; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX52]], align 4 +; CHECK-NEXT: br i1 undef, label %[[FOR_BODY_57:.*]], label %[[CLEANUP]] +; CHECK: [[FOR_BODY_57]]: +; CHECK-NEXT: [[I_2157:%.*]] = add nsw i32 [[TMP1]], -1 +; CHECK-NEXT: unreachable +; CHECK: [[CLEANUP]]: +; CHECK-NEXT: ret void +; entry: br label %bb0 bb0: ; preds = %land.lhs.true, %entry -;CHECK: bb0: %x.tr = phi ptr [ %x, %entry ], [ null, %land.lhs.true ] %0 = load i16, ptr %x.tr, align 4 -; CHECK: load i16, ptr %conv = zext i16 %0 to i32 switch i32 %conv, label %if.end.50 [ - i32 43, label %cleanup - i32 52, label %if.then.5 + i32 43, label %cleanup + i32 52, label %if.then.5 ] if.then.5: ; preds = %bb0 @@ -36,8 +71,6 @@ if.then.26: ; preds = %if.then.5 br i1 undef, label %cond.end, label %cond.false cond.false: ; preds = %if.then.26 -; CHECK: cond.false: -; CHECK: load i16 %mode = getelementptr inbounds %struct.a, ptr %x.tr.lcssa163, i32 0, i32 1 %bf.load = load i16, ptr %mode, align 2 %bf.shl = shl i16 %bf.load, 8 @@ -50,7 +83,6 @@ if.then.44: ; preds = %cond.end unreachable if.end.50: ; preds = %bb0 -;%CHECK: if.end.50: %conv.lcssa = phi i32 [ %conv, %bb0 ] %arrayidx52 = getelementptr inbounds [0 x i32], ptr @length, i32 0, i32 %conv.lcssa %1 = load i32, ptr %arrayidx52, align 4 @@ -68,7 +100,38 @@ cleanup: ; preds = %if.end.50, %cond.en @dfg_text = external global ptr, align 4 define void @dfg_lex() { -;CHECK-LABEL: dfg_lex +; CHECK-LABEL: define void @dfg_lex() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: br label %[[WHILE_BODYTHREAD_PRE_SPLIT:.*]] +; CHECK: [[WHILE_BODYTHREAD_PRE_SPLIT]]: +; CHECK-NEXT: br i1 undef, label %[[WHILE_BODYTHREAD_PRE_SPLIT_IF_THEN_14_CRIT_EDGE:.*]], label %[[IF_END_15:.*]] +; CHECK: [[WHILE_BODYTHREAD_PRE_SPLIT_IF_THEN_14_CRIT_EDGE]]: +; CHECK-NEXT: [[V1_PRE:%.*]] = load i32, ptr @dfg_text, align 4 +; CHECK-NEXT: br label %[[IF_THEN_14:.*]] +; CHECK: [[IF_THEN_14]]: +; CHECK-NEXT: [[V1:%.*]] = phi i32 [ [[V1_PRE]], %[[WHILE_BODYTHREAD_PRE_SPLIT_IF_THEN_14_CRIT_EDGE]] ], [ [[SUB_PTR_RHS_CAST25:%.*]], %[[WHILE_END:.*]] ] +; CHECK-NEXT: br label %[[IF_END_15]] +; CHECK: [[IF_END_15]]: +; CHECK-NEXT: [[V2:%.*]] = load ptr, ptr @yy_c_buf_p, align 4 +; CHECK-NEXT: br label %[[WHILE_COND_16:.*]] +; CHECK: [[WHILE_COND_16]]: +; CHECK-NEXT: br i1 undef, label %[[WHILE_COND_16]], label %[[WHILE_END]] +; CHECK: [[WHILE_END]]: +; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[V2]], i32 undef +; CHECK-NEXT: store ptr [[ADD_PTR]], ptr @dfg_text, align 4 +; CHECK-NEXT: [[SUB_PTR_RHS_CAST25]] = ptrtoint ptr [[ADD_PTR]] to i32 +; CHECK-NEXT: [[SUB_PTR_SUB26:%.*]] = sub i32 0, [[SUB_PTR_RHS_CAST25]] +; CHECK-NEXT: switch i32 undef, label %[[SW_DEFAULT:.*]] [ +; CHECK-NEXT: i32 65, label %[[WHILE_BODYTHREAD_PRE_SPLIT]] +; CHECK-NEXT: i32 3, label %[[RETURN:.*]] +; CHECK-NEXT: i32 57, label %[[WHILE_BODYTHREAD_PRE_SPLIT]] +; CHECK-NEXT: i32 60, label %[[IF_THEN_14]] +; CHECK-NEXT: ] +; CHECK: [[SW_DEFAULT]]: +; CHECK-NEXT: unreachable +; CHECK: [[RETURN]]: +; CHECK-NEXT: ret void +; entry: br label %while.bodythread-pre-split @@ -93,10 +156,10 @@ while.end: ; preds = %while.cond.16 %sub.ptr.rhs.cast25 = ptrtoint ptr %add.ptr to i32 %sub.ptr.sub26 = sub i32 0, %sub.ptr.rhs.cast25 switch i32 undef, label %sw.default [ - i32 65, label %while.bodythread-pre-split - i32 3, label %return - i32 57, label %while.bodythread-pre-split - i32 60, label %if.then.14 + i32 65, label %while.bodythread-pre-split + i32 3, label %return + i32 57, label %while.bodythread-pre-split + i32 60, label %if.then.14 ] sw.default: ; preds = %while.end diff --git a/llvm/test/Transforms/GVN/pr28562.ll b/llvm/test/Transforms/GVN/pr28562.ll index 338200a..02301dc 100644 --- a/llvm/test/Transforms/GVN/pr28562.ll +++ b/llvm/test/Transforms/GVN/pr28562.ll @@ -1,9 +1,13 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -S -passes=gvn < %s | FileCheck %s + define ptr @test1(ptr %a) { +; CHECK-LABEL: define ptr @test1( +; CHECK-SAME: ptr [[A:%.*]]) { +; CHECK-NEXT: [[X1:%.*]] = getelementptr i32, ptr [[A]], i32 10 +; CHECK-NEXT: ret ptr [[X1]] +; %x1 = getelementptr inbounds i32, ptr %a, i32 10 %x2 = getelementptr i32, ptr %a, i32 10 ret ptr %x2 -; CHECK-LABEL: @test1( -; CHECK: %[[x:.*]] = getelementptr i32, ptr %a, i32 10 -; CHECK: ret ptr %[[x]] } diff --git a/llvm/test/Transforms/GVN/pr28879.ll b/llvm/test/Transforms/GVN/pr28879.ll index 0c9231d..b961a55 100644 --- a/llvm/test/Transforms/GVN/pr28879.ll +++ b/llvm/test/Transforms/GVN/pr28879.ll @@ -1,12 +1,22 @@ -; RUN: opt -passes=gvn <%s -S -o - | FileCheck %s +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 +; RUN: opt -passes=gvn < %s -S -o - | FileCheck %s define void @f() { +; CHECK-LABEL: define void @f() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[A:%.*]] = alloca <7 x i1>, align 2 +; CHECK-NEXT: store <7 x i1> undef, ptr [[A]], align 2 +; CHECK-NEXT: [[VAL:%.*]] = load i1, ptr [[A]], align 2 +; CHECK-NEXT: br i1 [[VAL]], label %[[COND_TRUE:.*]], label %[[COND_FALSE:.*]] +; CHECK: [[COND_TRUE]]: +; CHECK-NEXT: ret void +; CHECK: [[COND_FALSE]]: +; CHECK-NEXT: ret void +; entry: %a = alloca <7 x i1>, align 2 store <7 x i1> undef, ptr %a, align 2 -; CHECK: store <7 x i1> undef, ptr %val = load i1, ptr %a, align 2 -; CHECK: load i1, ptr br i1 %val, label %cond.true, label %cond.false cond.true: @@ -17,11 +27,20 @@ cond.false: } define <7 x i1> @g(ptr %a) { +; CHECK-LABEL: define <7 x i1> @g( +; CHECK-SAME: ptr [[A:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[VEC:%.*]] = load <7 x i1>, ptr [[A]], align 1 +; CHECK-NEXT: [[VAL:%.*]] = load i1, ptr [[A]], align 2 +; CHECK-NEXT: br i1 [[VAL]], label %[[COND_TRUE:.*]], label %[[COND_FALSE:.*]] +; CHECK: [[COND_TRUE]]: +; CHECK-NEXT: ret <7 x i1> [[VEC]] +; CHECK: [[COND_FALSE]]: +; CHECK-NEXT: ret <7 x i1> zeroinitializer +; entry: %vec = load <7 x i1>, ptr %a -; CHECK: load <7 x i1>, ptr %val = load i1, ptr %a, align 2 -; CHECK: load i1, ptr br i1 %val, label %cond.true, label %cond.false cond.true: diff --git a/llvm/test/Transforms/GVN/pr36063.ll b/llvm/test/Transforms/GVN/pr36063.ll index 5ac4c3d..8aaeff6 100644 --- a/llvm/test/Transforms/GVN/pr36063.ll +++ b/llvm/test/Transforms/GVN/pr36063.ll @@ -1,6 +1,20 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt < %s -passes=memcpyopt,mldst-motion,gvn -S | FileCheck %s define void @foo(ptr %ret, i1 %x) { +; CHECK-LABEL: define void @foo( +; CHECK-SAME: ptr [[RET:%.*]], i1 [[X:%.*]]) { +; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1 +; CHECK-NEXT: br i1 [[X]], label %[[YES:.*]], label %[[NO:.*]] +; CHECK: [[YES]]: +; CHECK-NEXT: br label %[[OUT:.*]] +; CHECK: [[NO]]: +; CHECK-NEXT: br label %[[OUT]] +; CHECK: [[OUT]]: +; CHECK-NEXT: store i8 5, ptr [[A]], align 1 +; CHECK-NEXT: store i8 5, ptr [[RET]], align 1 +; CHECK-NEXT: ret void +; %a = alloca i8 br i1 %x, label %yes, label %no @@ -14,7 +28,6 @@ no: ; preds = %0 out: ; preds = %no, %yes %tmp = load i8, ptr %a -; CHECK-NOT: undef store i8 %tmp, ptr %ret ret void } diff --git a/llvm/test/Transforms/GVN/pr42605.ll b/llvm/test/Transforms/GVN/pr42605.ll index f0ff6d9..3e6241c 100644 --- a/llvm/test/Transforms/GVN/pr42605.ll +++ b/llvm/test/Transforms/GVN/pr42605.ll @@ -1,6 +1,9 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=gvn %s -S | FileCheck %s + ; PR42605. Check phi-translate won't translate the value number of a call ; to the value of another call with clobber in between. + target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @@ -12,6 +15,13 @@ declare dso_local i32 @printf(ptr nocapture readonly, ...) local_unnamed_addr ; Function Attrs: noinline norecurse nounwind readonly uwtable define dso_local i32 @_Z3gooi(i32 %i) local_unnamed_addr #0 { +; CHECK-LABEL: define dso_local i32 @_Z3gooi( +; CHECK-SAME: i32 [[I:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[T0:%.*]] = load i32, ptr @global, align 4, !tbaa [[INT_TBAA2:![0-9]+]] +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[T0]], [[I]] +; CHECK-NEXT: ret i32 [[ADD]] +; entry: %t0 = load i32, ptr @global, align 4, !tbaa !2 %add = add nsw i32 %t0, %i @@ -20,6 +30,24 @@ entry: ; Function Attrs: nofree nounwind uwtable define dso_local void @noclobber() local_unnamed_addr { +; CHECK-LABEL: define dso_local void @noclobber() local_unnamed_addr { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @_Z3gooi(i32 2) +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL]], 5 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[ADD]], 2 +; CHECK-NEXT: br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_END:.*]] +; CHECK: [[IF_THEN]]: +; CHECK-NEXT: [[CALL1:%.*]] = tail call i32 @_Z3gooi(i32 3) +; CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[CALL1]], 5 +; CHECK-NEXT: br label %[[IF_END]] +; CHECK: [[IF_END]]: +; CHECK-NEXT: [[ADD4_PRE_PHI:%.*]] = phi i32 [ [[ADD2]], %[[IF_THEN]] ], [ [[ADD]], %[[ENTRY]] ] +; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 3, %[[IF_THEN]] ], [ 2, %[[ENTRY]] ] +; CHECK-NEXT: [[GLOBAL2_0:%.*]] = phi i32 [ [[ADD2]], %[[IF_THEN]] ], [ [[ADD]], %[[ENTRY]] ] +; CHECK-NEXT: [[CALL3:%.*]] = tail call i32 @_Z3gooi(i32 [[I_0]]) +; CHECK-NEXT: [[CALL5:%.*]] = tail call i32 (ptr, ...) @printf(ptr @.str, i32 [[GLOBAL2_0]], i32 [[ADD4_PRE_PHI]]) +; CHECK-NEXT: ret void +; entry: %call = tail call i32 @_Z3gooi(i32 2) %add = add nsw i32 %call, 5 @@ -32,9 +60,6 @@ if.then: ; preds = %entry br label %if.end ; Check pre happens after phitranslate. -; CHECK-LABEL: @noclobber -; CHECK: %add4.pre-phi = phi i32 [ %add2, %if.then ], [ %add, %entry ] -; CHECK: printf(ptr @.str, i32 %global2.0, i32 %add4.pre-phi) if.end: ; preds = %if.then, %entry %i.0 = phi i32 [ 3, %if.then ], [ 2, %entry ] @@ -47,6 +72,25 @@ if.end: ; preds = %if.then, %entry ; Function Attrs: nofree nounwind uwtable define dso_local void @hasclobber() local_unnamed_addr { +; CHECK-LABEL: define dso_local void @hasclobber() local_unnamed_addr { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @_Z3gooi(i32 2) +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL]], 5 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[ADD]], 2 +; CHECK-NEXT: br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_END:.*]] +; CHECK: [[IF_THEN]]: +; CHECK-NEXT: [[CALL1:%.*]] = tail call i32 @_Z3gooi(i32 3) +; CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[CALL1]], 5 +; CHECK-NEXT: br label %[[IF_END]] +; CHECK: [[IF_END]]: +; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 3, %[[IF_THEN]] ], [ 2, %[[ENTRY]] ] +; CHECK-NEXT: [[GLOBAL2_0:%.*]] = phi i32 [ [[ADD2]], %[[IF_THEN]] ], [ [[ADD]], %[[ENTRY]] ] +; CHECK-NEXT: store i32 5, ptr @global, align 4, !tbaa [[INT_TBAA2]] +; CHECK-NEXT: [[CALL3:%.*]] = tail call i32 @_Z3gooi(i32 [[I_0]]) +; CHECK-NEXT: [[ADD4:%.*]] = add nsw i32 [[CALL3]], 5 +; CHECK-NEXT: [[CALL5:%.*]] = tail call i32 (ptr, ...) @printf(ptr @.str, i32 [[GLOBAL2_0]], i32 [[ADD4]]) +; CHECK-NEXT: ret void +; entry: %call = tail call i32 @_Z3gooi(i32 2) %add = add nsw i32 %call, 5 @@ -59,10 +103,6 @@ if.then: ; preds = %entry br label %if.end ; Check no pre happens. -; CHECK-LABEL: @hasclobber -; CHECK: %call3 = tail call i32 @_Z3gooi(i32 %i.0) -; CHECK-NEXT: %add4 = add nsw i32 %call3, 5 -; CHECK-NEXT: printf(ptr @.str, i32 %global2.0, i32 %add4) if.end: ; preds = %if.then, %entry %i.0 = phi i32 [ 3, %if.then ], [ 2, %entry ] @@ -85,3 +125,9 @@ attributes #0 = { noinline norecurse nounwind readonly uwtable "correctly-rounde !3 = !{!"int", !4, i64 0} !4 = !{!"omnipotent char", !5, i64 0} !5 = !{!"Simple C++ TBAA"} +;. +; CHECK: [[INT_TBAA2]] = !{[[META3:![0-9]+]], [[META3]], i64 0} +; CHECK: [[META3]] = !{!"int", [[META4:![0-9]+]], i64 0} +; CHECK: [[META4]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0} +; CHECK: [[META5]] = !{!"Simple C++ TBAA"} +;. diff --git a/llvm/test/Transforms/GVN/pr49193.ll b/llvm/test/Transforms/GVN/pr49193.ll index 9ee9f26..52703ee 100644 --- a/llvm/test/Transforms/GVN/pr49193.ll +++ b/llvm/test/Transforms/GVN/pr49193.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=gvn -S < %s | FileCheck %s @a = external local_unnamed_addr global i32, align 4 @@ -6,9 +7,37 @@ ; Function Attrs: nounwind readnone declare ptr @j() local_unnamed_addr #0 -; CHECK: define {{.*}}@k() - define i64 @k() local_unnamed_addr { +; CHECK-LABEL: define i64 @k() local_unnamed_addr { +; CHECK-NEXT: [[BB:.*:]] +; CHECK-NEXT: br i1 undef, label %[[BB10_PREHEADER:.*]], label %[[BB3:.*]] +; CHECK: [[BB10_PREHEADER]]: +; CHECK-NEXT: br label %[[BB13:.*]] +; CHECK: [[BB3]]: +; CHECK-NEXT: [[I4:%.*]] = load i32, ptr @a, align 4 +; CHECK-NEXT: [[I5_NOT:%.*]] = icmp eq i32 [[I4]], 0 +; CHECK-NEXT: [[I8:%.*]] = tail call ptr @j() +; CHECK-NEXT: br label %[[BB37:.*]] +; CHECK: [[BB13]]: +; CHECK-NEXT: br i1 undef, label %[[BB30THREAD_PRE_SPLIT:.*]], label %[[BB16:.*]] +; CHECK: [[BB16]]: +; CHECK-NEXT: [[I17:%.*]] = tail call ptr @j() +; CHECK-NEXT: br i1 undef, label %[[BB22THREAD_PRE_SPLIT:.*]], label %[[BB37_LOOPEXIT:.*]] +; CHECK: [[BB22THREAD_PRE_SPLIT]]: +; CHECK-NEXT: br i1 undef, label %[[BB30THREAD_PRE_SPLIT]], label %[[BB37_LOOPEXIT]] +; CHECK: [[BB30THREAD_PRE_SPLIT]]: +; CHECK-NEXT: [[I31_PR:%.*]] = load i32, ptr @a, align 4 +; CHECK-NEXT: [[I32_NOT2:%.*]] = icmp eq i32 [[I31_PR]], 0 +; CHECK-NEXT: br i1 undef, label %[[BB37_LOOPEXIT]], label %[[BB13]] +; CHECK: [[BB37_LOOPEXIT]]: +; CHECK-NEXT: [[I38_PRE:%.*]] = load i32, ptr @a, align 4 +; CHECK-NEXT: br label %[[BB37]] +; CHECK: [[BB37]]: +; CHECK-NEXT: [[I38:%.*]] = phi i32 [ [[I38_PRE]], %[[BB37_LOOPEXIT]] ], [ [[I4]], %[[BB3]] ] +; CHECK-NEXT: store i32 [[I38]], ptr @b, align 4 +; CHECK-NEXT: [[I39:%.*]] = tail call ptr @j() +; CHECK-NEXT: unreachable +; bb: br i1 undef, label %bb10.preheader, label %bb3 diff --git a/llvm/test/Transforms/GVN/pre-new-inst.ll b/llvm/test/Transforms/GVN/pre-new-inst.ll index 8e8cea0..0af8ad2 100644 --- a/llvm/test/Transforms/GVN/pre-new-inst.ll +++ b/llvm/test/Transforms/GVN/pre-new-inst.ll @@ -1,7 +1,23 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=gvn -S %s | FileCheck %s %MyStruct = type { i32, i32 } + define i8 @foo(i64 %in, ptr %arr, i1 %arg) { +; CHECK-LABEL: define i8 @foo( +; CHECK-SAME: i64 [[IN:%.*]], ptr [[ARR:%.*]], i1 [[ARG:%.*]]) { +; CHECK-NEXT: [[ADDR:%.*]] = alloca [[MYSTRUCT:%.*]], align 8 +; CHECK-NEXT: [[DEAD:%.*]] = trunc i64 [[IN]] to i32 +; CHECK-NEXT: br i1 [[ARG]], label %[[NEXT:.*]], label %[[TMP:.*]] +; CHECK: [[TMP]]: +; CHECK-NEXT: call void @bar() +; CHECK-NEXT: br label %[[NEXT]] +; CHECK: [[NEXT]]: +; CHECK-NEXT: store i64 [[IN]], ptr [[ADDR]], align 4 +; CHECK-NEXT: [[RESPTR:%.*]] = getelementptr i8, ptr [[ARR]], i32 [[DEAD]] +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[RESPTR]], align 1 +; CHECK-NEXT: ret i8 [[RES]] +; %addr = alloca %MyStruct %dead = trunc i64 %in to i32 br i1 %arg, label %next, label %tmp @@ -16,11 +32,8 @@ next: final: %idx32 = load i32, ptr %addr - -; CHECK: %resptr = getelementptr i8, ptr %arr, i32 %dead %resptr = getelementptr i8, ptr %arr, i32 %idx32 %res = load i8, ptr %resptr - ret i8 %res } diff --git a/llvm/test/Transforms/GVN/propagate-ir-flags.ll b/llvm/test/Transforms/GVN/propagate-ir-flags.ll index 6f4e662..6b11ff5 100644 --- a/llvm/test/Transforms/GVN/propagate-ir-flags.ll +++ b/llvm/test/Transforms/GVN/propagate-ir-flags.ll @@ -1,11 +1,15 @@ - +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt < %s -passes=gvn -S | FileCheck %s -; CHECK-LABEL: func_fast -; CHECK: fadd fast double -; CHECK-NEXT: store -; CHECK-NEXT: ret define double @func_fast(double %a, double %b) { +; CHECK-LABEL: define double @func_fast( +; CHECK-SAME: double [[A:%.*]], double [[B:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[A_ADDR:%.*]] = alloca double, align 8 +; CHECK-NEXT: [[ADD:%.*]] = fadd fast double [[B]], 3.000000e+00 +; CHECK-NEXT: store double [[ADD]], ptr [[A_ADDR]], align 8 +; CHECK-NEXT: ret double [[ADD]] +; entry: %a.addr = alloca double, align 8 %add = fadd fast double %b, 3.000000e+00 @@ -14,11 +18,15 @@ entry: ret double %load_add } -; CHECK-LABEL: func_no_fast -; CHECK: fadd double -; CHECK-NEXT: store -; CHECK-NEXT: ret define double @func_no_fast(double %a, double %b) { +; CHECK-LABEL: define double @func_no_fast( +; CHECK-SAME: double [[A:%.*]], double [[B:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[A_ADDR:%.*]] = alloca double, align 8 +; CHECK-NEXT: [[ADD:%.*]] = fadd double [[B]], 3.000000e+00 +; CHECK-NEXT: store double [[ADD]], ptr [[A_ADDR]], align 8 +; CHECK-NEXT: ret double [[ADD]] +; entry: %a.addr = alloca double, align 8 %add = fadd fast double %b, 3.000000e+00 @@ -26,4 +34,3 @@ entry: %duplicated_add = fadd double %b, 3.000000e+00 ret double %duplicated_add } - diff --git a/llvm/test/Transforms/GVN/rle-no-phi-translate.ll b/llvm/test/Transforms/GVN/rle-no-phi-translate.ll index 8876665..5b8b4db 100644 --- a/llvm/test/Transforms/GVN/rle-no-phi-translate.ll +++ b/llvm/test/Transforms/GVN/rle-no-phi-translate.ll @@ -1,5 +1,7 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt < %s -passes=gvn -S | FileCheck %s ; XFAIL: * + ; FIXME: This should be promotable, but memdep/gvn don't track values ; path/edge sensitively enough. @@ -7,22 +9,30 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3 target triple = "i386-apple-darwin7" define i32 @g(ptr %b, ptr %c) nounwind { +; CHECK-LABEL: define i32 @g( +; CHECK-SAME: ptr [[B:%.*]], ptr [[C:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: store i32 1, ptr [[B]], align 4 +; CHECK-NEXT: store i32 2, ptr [[C]], align 4 +; CHECK-NEXT: br i1 false, label %[[BB:.*]], label %[[BB2:.*]] +; CHECK: [[BB]]: +; CHECK-NEXT: br label %[[BB2]] +; CHECK: [[BB2]]: +; CHECK-NEXT: ret i32 [[CV]] +; entry: - store i32 1, ptr %b - store i32 2, ptr %c - - %t1 = icmp eq ptr %b, null ; <i1> [#uses=1] - br i1 %t1, label %bb, label %bb2 + store i32 1, ptr %b + store i32 2, ptr %c + + %t1 = icmp eq ptr %b, null ; <i1> [#uses=1] + br i1 %t1, label %bb, label %bb2 bb: ; preds = %entry - br label %bb2 + br label %bb2 bb2: ; preds = %bb1, %bb - %c_addr.0 = phi ptr [ %b, %entry ], [ %c, %bb ] ; <ptr> [#uses=1] - %cv = load i32, ptr %c_addr.0, align 4 ; <i32> [#uses=1] - ret i32 %cv -; CHECK: bb2: -; CHECK-NOT: load i32 -; CHECK: ret i32 + %c_addr.0 = phi ptr [ %b, %entry ], [ %c, %bb ] ; <ptr> [#uses=1] + %cv = load i32, ptr %c_addr.0, align 4 ; <i32> [#uses=1] + ret i32 %cv } diff --git a/llvm/test/Transforms/GVN/rle-nonlocal.ll b/llvm/test/Transforms/GVN/rle-nonlocal.ll index 06aa188..4cadc40 100644 --- a/llvm/test/Transforms/GVN/rle-nonlocal.ll +++ b/llvm/test/Transforms/GVN/rle-nonlocal.ll @@ -1,22 +1,38 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt < %s -passes=gvn -S | FileCheck %s define i32 @main(ptr %p, i32 %x, i32 %y) { +; CHECK-LABEL: define i32 @main( +; CHECK-SAME: ptr [[P:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[BLOCK1:.*:]] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X]], [[Y]] +; CHECK-NEXT: br i1 [[CMP]], label %[[BLOCK2:.*]], label %[[BLOCK3:.*]] +; CHECK: [[BLOCK2]]: +; CHECK-NEXT: [[A:%.*]] = load ptr, ptr [[P]], align 8 +; CHECK-NEXT: br label %[[BLOCK4:.*]] +; CHECK: [[BLOCK3]]: +; CHECK-NEXT: [[B:%.*]] = load ptr, ptr [[P]], align 8 +; CHECK-NEXT: br label %[[BLOCK4]] +; CHECK: [[BLOCK4]]: +; CHECK-NEXT: [[DEAD:%.*]] = phi ptr [ [[A]], %[[BLOCK2]] ], [ [[B]], %[[BLOCK3]] ] +; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[DEAD]], align 4 +; CHECK-NEXT: [[E:%.*]] = add i32 [[C]], [[C]] +; CHECK-NEXT: ret i32 [[E]] +; block1: - %cmp = icmp eq i32 %x, %y - br i1 %cmp , label %block2, label %block3 + %cmp = icmp eq i32 %x, %y + br i1 %cmp , label %block2, label %block3 block2: - %a = load ptr, ptr %p - br label %block4 + %a = load ptr, ptr %p + br label %block4 block3: %b = load ptr, ptr %p br label %block4 block4: -; CHECK-NOT: %existingPHI = phi -; CHECK: %DEAD = phi - %existingPHI = phi ptr [ %a, %block2 ], [ %b, %block3 ] + %existingPHI = phi ptr [ %a, %block2 ], [ %b, %block3 ] %DEAD = load ptr, ptr %p %c = load i32, ptr %DEAD %d = load i32, ptr %existingPHI diff --git a/llvm/test/Transforms/GVN/simplify-icf-cache-invalidation.ll b/llvm/test/Transforms/GVN/simplify-icf-cache-invalidation.ll index 8332a98..f4a4155 100644 --- a/llvm/test/Transforms/GVN/simplify-icf-cache-invalidation.ll +++ b/llvm/test/Transforms/GVN/simplify-icf-cache-invalidation.ll @@ -1,7 +1,6 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=gvn -S < %s | FileCheck %s -; CHECK: define {{.*}}@eggs - %struct.zot = type { ptr } %struct.wombat = type { ptr } %struct.baz = type { i8, ptr } @@ -11,6 +10,28 @@ declare ptr @f() define hidden void @eggs(ptr %arg, i1 %arg2, ptr %arg3, i32 %arg4, ptr %arg5) unnamed_addr align 2 { +; CHECK-LABEL: define hidden void @eggs( +; CHECK-SAME: ptr [[ARG:%.*]], i1 [[ARG2:%.*]], ptr [[ARG3:%.*]], i32 [[ARG4:%.*]], ptr [[ARG5:%.*]]) unnamed_addr align 2 { +; CHECK-NEXT: [[BB:.*:]] +; CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_WOMBAT:%.*]], align 8 +; CHECK-NEXT: store ptr @global, ptr [[ARG]], align 8, !invariant.group [[META0:![0-9]+]] +; CHECK-NEXT: br i1 [[ARG2]], label %[[BB4:.*]], label %[[BB2:.*]] +; CHECK: [[BB2]]: +; CHECK-NEXT: [[TMP3:%.*]] = atomicrmw sub ptr [[ARG3]], i32 [[ARG4]] acq_rel, align 4 +; CHECK-NEXT: br label %[[BB4]] +; CHECK: [[BB4]]: +; CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[ARG5]], align 8 +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_BAZ:%.*]], ptr [[TMP5]], i64 0, i32 1 +; CHECK-NEXT: br i1 [[ARG2]], label %[[BB9:.*]], label %[[BB7:.*]] +; CHECK: [[BB7]]: +; CHECK-NEXT: [[TMP8:%.*]] = tail call ptr @f() +; CHECK-NEXT: br label %[[BB9]] +; CHECK: [[BB9]]: +; CHECK-NEXT: tail call void @quux(ptr [[ARG]], i1 [[ARG2]]) +; CHECK-NEXT: [[TMP17:%.*]] = load ptr, ptr [[TMP]], align 8 +; CHECK-NEXT: [[TMP18:%.*]] = icmp eq ptr [[TMP17]], null +; CHECK-NEXT: ret void +; bb: %tmp = alloca %struct.wombat, align 8 store ptr @global, ptr %arg, align 8, !invariant.group !0 @@ -45,3 +66,6 @@ declare hidden void @quux(ptr, i1) unnamed_addr #0 align 2 attributes #0 = { nounwind willreturn } !0 = !{} +;. +; CHECK: [[META0]] = !{} +;. diff --git a/llvm/test/Transforms/GVN/stale-loop-info.ll b/llvm/test/Transforms/GVN/stale-loop-info.ll index 3d6ec67..e253aea 100644 --- a/llvm/test/Transforms/GVN/stale-loop-info.ll +++ b/llvm/test/Transforms/GVN/stale-loop-info.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes='require<loops>,gvn' -S < %s | FileCheck %s ; This used to fail with ASAN enabled and if for some reason LoopInfo remained @@ -14,6 +15,27 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" declare void @snork.1(ptr) local_unnamed_addr #0 define hidden zeroext i1 @eggs(ptr %arg, i1 %arg2, i1 %arg3) unnamed_addr align 2 { +; CHECK-LABEL: define hidden zeroext i1 @eggs( +; CHECK-SAME: ptr [[ARG:%.*]], i1 [[ARG2:%.*]], i1 [[ARG3:%.*]]) unnamed_addr align 2 { +; CHECK-NEXT: [[BB:.*:]] +; CHECK-NEXT: br i1 [[ARG2]], label %[[BB14:.*]], label %[[BB3:.*]] +; CHECK: [[BB3]]: +; CHECK-NEXT: [[TMP:%.*]] = getelementptr inbounds [[STRUCT_WIBBLE_1028:%.*]], ptr [[ARG]], i64 0, i32 2, i32 0, i32 0, i64 0 +; CHECK-NEXT: br label %[[BB6:.*]] +; CHECK: [[BB6]]: +; CHECK-NEXT: br i1 [[ARG3]], label %[[BB11:.*]], label %[[BB8:.*]] +; CHECK: [[BB8]]: +; CHECK-NEXT: [[TMP9:%.*]] = load ptr, ptr [[TMP]], align 8 +; CHECK-NEXT: br label %[[BB12:.*]] +; CHECK: [[BB11]]: +; CHECK-NEXT: br label %[[BB12]] +; CHECK: [[BB12]]: +; CHECK-NEXT: [[TMP13:%.*]] = phi ptr [ [[TMP]], %[[BB11]] ], [ [[TMP9]], %[[BB8]] ] +; CHECK-NEXT: call void @snork.1(ptr [[TMP13]]) #[[ATTR1:[0-9]+]] +; CHECK-NEXT: br label %[[BB6]] +; CHECK: [[BB14]]: +; CHECK-NEXT: ret i1 false +; bb: br i1 %arg2, label %bb14, label %bb3 @@ -29,7 +51,6 @@ bb7: ; preds = %bb6 bb8: ; preds = %bb7 %tmp9 = load ptr, ptr %tmp, align 8 -; CHECK: %tmp9 = load ptr, ptr %tmp, align 8 br label %bb12 bb11: ; preds = %bb7 diff --git a/llvm/test/Transforms/GVN/unreachable-predecessor.ll b/llvm/test/Transforms/GVN/unreachable-predecessor.ll index 532d554..a584189 100644 --- a/llvm/test/Transforms/GVN/unreachable-predecessor.ll +++ b/llvm/test/Transforms/GVN/unreachable-predecessor.ll @@ -1,13 +1,31 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt < %s -passes=gvn -S | FileCheck %s ; loop.then is not reachable from loop, so we should be able to deduce that the ; store through %phi2 cannot alias %ptr1. - -; CHECK-LABEL: @test1 define void @test1(ptr %ptr1, ptr %ptr2) { -; CHECK-LABEL: entry: -; CHECK: %[[GEP:.*]] = getelementptr inbounds i32, ptr %ptr1, i64 1 -; CHECK: %[[VAL1:.*]] = load i32, ptr %[[GEP]] +; CHECK-LABEL: define void @test1( +; CHECK-SAME: ptr [[PTR1:%.*]], ptr [[PTR2:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i32, ptr [[PTR1]], i64 1 +; CHECK-NEXT: [[VAL1_PRE:%.*]] = load i32, ptr [[GEP1]], align 4 +; CHECK-NEXT: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK-NEXT: [[PHI1:%.*]] = phi ptr [ [[GEP1]], %[[ENTRY]] ], [ [[PHI2:%.*]], %[[LOOP_THEN:.*]] ] +; CHECK-NEXT: br i1 false, label %[[LOOP_LOOP_THEN_CRIT_EDGE:.*]], label %[[LOOP_IF:.*]] +; CHECK: [[LOOP_LOOP_THEN_CRIT_EDGE]]: +; CHECK-NEXT: br label %[[LOOP_THEN]] +; CHECK: [[LOOP_IF]]: +; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i32, ptr [[GEP1]], i64 1 +; CHECK-NEXT: [[VAL2:%.*]] = load i32, ptr [[GEP2]], align 4 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[VAL1_PRE]], [[VAL2]] +; CHECK-NEXT: br label %[[LOOP_THEN]] +; CHECK: [[LOOP_THEN]]: +; CHECK-NEXT: [[PHI2]] = phi ptr [ poison, %[[LOOP_LOOP_THEN_CRIT_EDGE]] ], [ [[GEP2]], %[[LOOP_IF]] ] +; CHECK-NEXT: store i32 [[VAL1_PRE]], ptr [[PHI2]], align 4 +; CHECK-NEXT: store i32 0, ptr [[PTR1]], align 4 +; CHECK-NEXT: br label %[[LOOP]] +; entry: br label %loop.preheader @@ -15,8 +33,6 @@ loop.preheader: %gep1 = getelementptr inbounds i32, ptr %ptr1, i64 1 br label %loop -; CHECK-LABEL: loop: -; CHECK-NOT: load loop: %phi1 = phi ptr [ %gep1, %loop.preheader ], [ %phi2, %loop.then ] %val1 = load i32, ptr %phi1 @@ -28,8 +44,6 @@ loop.if: %cmp = icmp slt i32 %val1, %val2 br label %loop.then -; CHECK-LABEL: loop.then -; CHECK: store i32 %[[VAL1]], ptr %phi2 loop.then: %phi2 = phi ptr [ %ptr2, %loop ], [ %gep2, %loop.if ] store i32 %val1, ptr %phi2 diff --git a/llvm/test/Transforms/GVN/unreachable_block_infinite_loop.ll b/llvm/test/Transforms/GVN/unreachable_block_infinite_loop.ll index 5de5e03..2743fd0 100644 --- a/llvm/test/Transforms/GVN/unreachable_block_infinite_loop.ll +++ b/llvm/test/Transforms/GVN/unreachable_block_infinite_loop.ll @@ -1,18 +1,40 @@ -; RUN: opt -passes=gvn -disable-output < %s +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 +; RUN: opt -passes=gvn -S < %s | FileCheck %s target datalayout = "e-p:64:64:64-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" target triple = "x86_64-apple-darwin10.0" define i32 @test2() nounwind ssp { +; CHECK-LABEL: define i32 @test2( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: ret i32 0 +; CHECK: [[UNREACHABLE_BLOCK:.*:]] +; CHECK-NEXT: [[A:%.*]] = add i32 [[A]], 1 +; CHECK-NEXT: ret i32 [[A]] +; entry: - ret i32 0 + ret i32 0 unreachable_block: - %a = add i32 %a, 1 - ret i32 %a + %a = add i32 %a, 1 + ret i32 %a } define i32 @pr23096_test0(i1 %arg, ptr %arg2) { +; CHECK-LABEL: define i32 @pr23096_test0( +; CHECK-SAME: i1 [[ARG:%.*]], ptr [[ARG2:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: br label %[[BB0:.*]] +; CHECK: [[BB1:.*]]: +; CHECK-NEXT: [[PTR1:%.*]] = ptrtoint ptr [[PTR2:%.*]] to i64 +; CHECK-NEXT: [[PTR2]] = inttoptr i64 [[PTR1]] to ptr +; CHECK-NEXT: br i1 [[ARG]], label %[[BB0]], label %[[BB1]] +; CHECK: [[BB0]]: +; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[ARG2]], %[[ENTRY]] ], [ [[PTR2]], %[[BB1]] ] +; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[PHI]], align 4 +; CHECK-NEXT: ret i32 [[LOAD]] +; entry: br label %bb0 @@ -28,6 +50,19 @@ bb0: } define i32 @pr23096_test1(i1 %arg, ptr %arg2) { +; CHECK-LABEL: define i32 @pr23096_test1( +; CHECK-SAME: i1 [[ARG:%.*]], ptr [[ARG2:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: br label %[[BB0:.*]] +; CHECK: [[BB1:.*]]: +; CHECK-NEXT: [[PTR1:%.*]] = getelementptr i32, ptr [[PTR2:%.*]], i32 0 +; CHECK-NEXT: [[PTR2]] = getelementptr i32, ptr [[PTR1]], i32 0 +; CHECK-NEXT: br i1 [[ARG]], label %[[BB0]], label %[[BB1]] +; CHECK: [[BB0]]: +; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[ARG2]], %[[ENTRY]] ], [ [[PTR2]], %[[BB1]] ] +; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[PHI]], align 4 +; CHECK-NEXT: ret i32 [[LOAD]] +; entry: br label %bb0 diff --git a/llvm/test/Transforms/GVN/volatile-nonvolatile.ll b/llvm/test/Transforms/GVN/volatile-nonvolatile.ll index 72c6a30..d34c891 100644 --- a/llvm/test/Transforms/GVN/volatile-nonvolatile.ll +++ b/llvm/test/Transforms/GVN/volatile-nonvolatile.ll @@ -1,13 +1,19 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=gvn -S < %s | FileCheck %s %struct.t = type { ptr } ; The loaded address and the location of the address itself are not aliased, ; so the second reload is not necessary. Check that it can be eliminated. -; CHECK-LABEL: test1 -; CHECK: load -; CHECK-NOT: load define void @test1(ptr nocapture readonly %p, i32 %v) #0 { +; CHECK-LABEL: define void @test1( +; CHECK-SAME: ptr readonly captures(none) [[P:%.*]], i32 [[V:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 4, !tbaa [[ANYPTR_TBAA0:![0-9]+]] +; CHECK-NEXT: store volatile i32 [[V]], ptr [[TMP0]], align 4, !tbaa [[INT_TBAA5:![0-9]+]] +; CHECK-NEXT: store volatile i32 [[V]], ptr [[TMP0]], align 4, !tbaa [[INT_TBAA5]] +; CHECK-NEXT: ret void +; entry: %0 = load ptr, ptr %p, align 4, !tbaa !1 store volatile i32 %v, ptr %0, align 4, !tbaa !6 @@ -18,11 +24,16 @@ entry: ; The store via the loaded address may overwrite the address itself. ; Make sure that both loads remain. -; CHECK-LABEL: test2 -; CHECK: load -; CHECK: store -; CHECK: load define void @test2(ptr nocapture readonly %p, i32 %v) #0 { +; CHECK-LABEL: define void @test2( +; CHECK-SAME: ptr readonly captures(none) [[P:%.*]], i32 [[V:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 4, !tbaa [[ANYPTR_TBAA0]] +; CHECK-NEXT: store volatile i32 [[V]], ptr [[TMP0]], align 4, !tbaa [[ANYPTR_TBAA0]] +; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[P]], align 4, !tbaa [[ANYPTR_TBAA0]] +; CHECK-NEXT: store volatile i32 [[V]], ptr [[TMP1]], align 4, !tbaa [[ANYPTR_TBAA0]] +; CHECK-NEXT: ret void +; entry: %0 = load ptr, ptr %p, align 4, !tbaa !1 store volatile i32 %v, ptr %0, align 4, !tbaa !1 @@ -33,11 +44,16 @@ entry: ; The loads are ordered and non-monotonic. Although they are not aliased to ; the stores, make sure both are preserved. -; CHECK-LABEL: test3 -; CHECK: load -; CHECK: store -; CHECK: load define void @test3(ptr nocapture readonly %p, i32 %v) #0 { +; CHECK-LABEL: define void @test3( +; CHECK-SAME: ptr readonly captures(none) [[P:%.*]], i32 [[V:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TMP0:%.*]] = load atomic ptr, ptr [[P]] acquire, align 4, !tbaa [[ANYPTR_TBAA0]] +; CHECK-NEXT: store volatile i32 [[V]], ptr [[TMP0]], align 4, !tbaa [[INT_TBAA5]] +; CHECK-NEXT: [[TMP1:%.*]] = load atomic ptr, ptr [[P]] acquire, align 4, !tbaa [[ANYPTR_TBAA0]] +; CHECK-NEXT: store volatile i32 [[V]], ptr [[TMP1]], align 4, !tbaa [[INT_TBAA5]] +; CHECK-NEXT: ret void +; entry: %0 = load atomic ptr, ptr %p acquire, align 4, !tbaa !1 store volatile i32 %v, ptr %0, align 4, !tbaa !6 @@ -56,3 +72,12 @@ attributes #0 = { norecurse nounwind } !6 = !{!7, !7, i64 0} !7 = !{!"int", !4, i64 0} +;. +; CHECK: [[ANYPTR_TBAA0]] = !{[[META1:![0-9]+]], [[META2:![0-9]+]], i64 0} +; CHECK: [[META1]] = !{!"", [[META2]], i64 0} +; CHECK: [[META2]] = !{!"any pointer", [[META3:![0-9]+]], i64 0} +; CHECK: [[META3]] = !{!"omnipotent char", [[META4:![0-9]+]], i64 0} +; CHECK: [[META4]] = !{!"Simple C/C++ TBAA"} +; CHECK: [[INT_TBAA5]] = !{[[META6:![0-9]+]], [[META6]], i64 0} +; CHECK: [[META6]] = !{!"int", [[META3]], i64 0} +;. |