Index: llvm/test/Transforms/GVN/condprop.ll =================================================================== --- llvm/test/Transforms/GVN/condprop.ll +++ llvm/test/Transforms/GVN/condprop.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=gvn -S | FileCheck %s -@a = external global i32 ; [#uses=7] +@a = external global i32 ; [#uses=8] define i32 @test1() nounwind { ; CHECK-LABEL: @test1( @@ -512,9 +512,7 @@ ret i32 %res } -; On the path from entry->if->end we know that ptr1==ptr2, so we can determine -; that gep2 does not alias ptr1 on that path (as it would require that -; ptr2==ptr2+2), so we can perform PRE of the load. +; Check that we dont propagate pointer equalities when illegal. define i32 @test13(ptr %ptr1, ptr %ptr2) { ; CHECK-LABEL: @test13( ; CHECK-NEXT: entry: @@ -556,14 +554,14 @@ ret i32 %ret } -define void @test14(ptr %ptr1, ptr noalias %ptr2) { +define void @test14(ptr %ptr1, ptr noalias %ptr2, i1 %c1, i1 %c2) { ; CHECK-LABEL: @test14( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i32, ptr [[PTR1:%.*]], i32 1 ; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i32, ptr [[PTR1]], i32 2 ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: br i1 undef, label [[LOOP_IF1_CRIT_EDGE:%.*]], label [[THEN:%.*]] +; CHECK-NEXT: br i1 [[C1:%.*]], label [[LOOP_IF1_CRIT_EDGE:%.*]], label [[THEN:%.*]] ; CHECK: loop.if1_crit_edge: ; CHECK-NEXT: [[VAL2_PRE:%.*]] = load i32, ptr [[GEP2]], align 4 ; CHECK-NEXT: br label [[IF1:%.*]] @@ -581,7 +579,7 @@ ; CHECK-NEXT: [[PHI3:%.*]] = phi ptr [ [[PTR2]], [[THEN]] ], [ [[PTR1]], [[IF2]] ] ; CHECK-NEXT: [[VAL3]] = load i32, ptr [[GEP2]], align 4 ; CHECK-NEXT: store i32 [[VAL3]], ptr [[PHI3]], align 4 -; CHECK-NEXT: br i1 undef, label [[LOOP]], label [[IF1]] +; CHECK-NEXT: br i1 [[C2:%.*]], label [[LOOP]], label [[IF1]] ; entry: %gep1 = getelementptr inbounds i32, ptr %ptr1, i32 1 @@ -590,7 +588,7 @@ loop: %phi1 = phi ptr [ %gep3, %loop.end ], [ %gep1, %entry ] - br i1 undef, label %if1, label %then + br i1 %c1, label %if1, label %then if1: @@ -611,5 +609,232 @@ %val3 = load i32, ptr %gep2, align 4 store i32 %val3, ptr %phi3, align 4 %gep3 = getelementptr inbounds i32, ptr %ptr1, i32 1 - br i1 undef, label %loop, label %if1 + br i1 %c2, label %loop, label %if1 } + +define i32 @test15(ptr noalias %p, i64 %i) { +; CHECK-LABEL: @test15( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[I:%.*]] +; CHECK-NEXT: store i32 1, ptr [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], @a +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] +; CHECK: if.then: +; CHECK-NEXT: store i32 2, ptr @a, align 4 +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: ret i32 1 +; +entry: + %arrayidx = getelementptr inbounds i32, ptr %p, i64 %i + store i32 1, ptr %arrayidx, align 4 + %cmp = icmp eq ptr %p, @a + br i1 %cmp, label %if.then, label %if.end + +if.then: + store i32 2, ptr %p, align 4 + br label %if.end + +if.end: + %0 = load i32, ptr %arrayidx, align 4 + ret i32 %0 +} + +define void @single_phi1(ptr %p1) { +; CHECK-LABEL: @single_phi1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr poison, align 8 +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq ptr [[P2]], [[P1:%.*]] +; CHECK-NEXT: br i1 [[CMP1]], label [[BB4:%.*]], label [[BB1:%.*]] +; CHECK: bb1: +; CHECK-NEXT: switch i8 poison, label [[BB2:%.*]] [ +; CHECK-NEXT: i8 0, label [[BB1]] +; CHECK-NEXT: i8 1, label [[BB3:%.*]] +; CHECK-NEXT: ] +; CHECK: bb2: +; CHECK-NEXT: unreachable +; CHECK: bb3: +; CHECK-NEXT: br label [[BB4]] +; CHECK: bb4: +; CHECK-NEXT: call void @use_bool(i1 true) +; CHECK-NEXT: call void @use_ptr(ptr [[P1]]) +; CHECK-NEXT: ret void +; +entry: + %p2 = load ptr, ptr poison, align 8 + %cmp1 = icmp eq ptr %p2, %p1 + br i1 %cmp1, label %bb4, label %bb1 + +bb1: + switch i8 poison, label %bb2 [ + i8 0, label %bb1 + i8 1, label %bb3 + ] + +bb2: + unreachable + +bb3: + br label %bb4 + +bb4: + %phi1 = phi ptr [ %p2, %entry ], [ poison, %bb3 ] + %cmp2 = icmp eq ptr %phi1, %p1 + call void @use_bool(i1 %cmp2) + call void @use_ptr(ptr %phi1) + ret void +} + +define void @single_phi2(ptr %p1) { +; CHECK-LABEL: @single_phi2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr poison, align 8 +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq ptr [[P2]], [[P1:%.*]] +; CHECK-NEXT: br i1 [[CMP1]], label [[BB4:%.*]], label [[BB1:%.*]] +; CHECK: bb1: +; CHECK-NEXT: switch i8 poison, label [[BB2:%.*]] [ +; CHECK-NEXT: i8 0, label [[BB1]] +; CHECK-NEXT: i8 1, label [[BB3:%.*]] +; CHECK-NEXT: ] +; CHECK: bb2: +; CHECK-NEXT: br label [[BB4]] +; CHECK: bb3: +; CHECK-NEXT: br label [[BB4]] +; CHECK: bb4: +; CHECK-NEXT: [[PHI1:%.*]] = phi ptr [ [[P1]], [[ENTRY:%.*]] ], [ [[P2]], [[BB2]] ], [ poison, [[BB3]] ] +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq ptr [[PHI1]], [[P1]] +; CHECK-NEXT: call void @use_bool(i1 [[CMP2]]) +; CHECK-NEXT: call void @use_ptr(ptr [[PHI1]]) +; CHECK-NEXT: ret void +; +entry: + %p2 = load ptr, ptr poison, align 8 + %cmp1 = icmp eq ptr %p2, %p1 + br i1 %cmp1, label %bb4, label %bb1 + +bb1: + switch i8 poison, label %bb2 [ + i8 0, label %bb1 + i8 1, label %bb3 + ] + +bb2: + br label %bb4 + +bb3: + br label %bb4 + +bb4: + %phi1 = phi ptr [ %p2, %entry ], [ %p2, %bb2 ], [ poison, %bb3 ] + %cmp2 = icmp eq ptr %phi1, %p1 + call void @use_bool(i1 %cmp2) + call void @use_ptr(ptr %phi1) + ret void +} + +define void @multiple_phi1(ptr %p1) { +; CHECK-LABEL: @multiple_phi1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr poison, align 8 +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq ptr [[P2]], [[P1:%.*]] +; CHECK-NEXT: br i1 [[CMP1]], label [[BB4:%.*]], label [[BB1:%.*]] +; CHECK: bb1: +; CHECK-NEXT: switch i8 poison, label [[BB2:%.*]] [ +; CHECK-NEXT: i8 0, label [[BB1]] +; CHECK-NEXT: i8 1, label [[BB3:%.*]] +; CHECK-NEXT: ] +; CHECK: bb2: +; CHECK-NEXT: unreachable +; CHECK: bb3: +; CHECK-NEXT: br label [[BB4]] +; CHECK: bb4: +; CHECK-NEXT: call void @use_bool(i1 true) +; CHECK-NEXT: br label [[BB5:%.*]] +; CHECK: bb5: +; CHECK-NEXT: call void @use_ptr(ptr [[P1]]) +; CHECK-NEXT: br label [[BB5]] +; +entry: + %p2 = load ptr, ptr poison, align 8 + %cmp1 = icmp eq ptr %p2, %p1 + br i1 %cmp1, label %bb4, label %bb1 + +bb1: + switch i8 poison, label %bb2 [ + i8 0, label %bb1 + i8 1, label %bb3 + ] + +bb2: + unreachable + +bb3: + br label %bb4 + +bb4: + %phi1 = phi ptr [ %p2, %entry ], [ poison, %bb3 ] + %cmp2 = icmp eq ptr %phi1, %p1 + call void @use_bool(i1 %cmp2) + br label %bb5 + +bb5: + %phi2 = phi ptr [ poison, %bb5 ], [ %phi1, %bb4 ] + call void @use_ptr(ptr %phi2) + br label %bb5 +} + +define void @multiple_phi2(ptr %p1) { +; CHECK-LABEL: @multiple_phi2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr poison, align 8 +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq ptr [[P2]], [[P1:%.*]] +; CHECK-NEXT: br i1 [[CMP1]], label [[BB4:%.*]], label [[BB1:%.*]] +; CHECK: bb1: +; CHECK-NEXT: switch i8 poison, label [[BB2:%.*]] [ +; CHECK-NEXT: i8 0, label [[BB1]] +; CHECK-NEXT: i8 1, label [[BB3:%.*]] +; CHECK-NEXT: ] +; CHECK: bb2: +; CHECK-NEXT: br label [[BB4]] +; CHECK: bb3: +; CHECK-NEXT: br label [[BB4]] +; CHECK: bb4: +; CHECK-NEXT: [[PHI1:%.*]] = phi ptr [ [[P1]], [[ENTRY:%.*]] ], [ [[P2]], [[BB2]] ], [ poison, [[BB3]] ] +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq ptr [[PHI1]], [[P1]] +; CHECK-NEXT: call void @use_bool(i1 [[CMP2]]) +; CHECK-NEXT: br label [[BB5:%.*]] +; CHECK: bb5: +; CHECK-NEXT: call void @use_ptr(ptr [[PHI1]]) +; CHECK-NEXT: br label [[BB5]] +; +entry: + %p2 = load ptr, ptr poison, align 8 + %cmp1 = icmp eq ptr %p2, %p1 + br i1 %cmp1, label %bb4, label %bb1 + +bb1: + switch i8 poison, label %bb2 [ + i8 0, label %bb1 + i8 1, label %bb3 + ] + +bb2: + br label %bb4 + +bb3: + br label %bb4 + +bb4: + %phi1 = phi ptr [ %p2, %entry ], [ %p2, %bb2 ], [ poison, %bb3 ] + %cmp2 = icmp eq ptr %phi1, %p1 + call void @use_bool(i1 %cmp2) + br label %bb5 + +bb5: + %phi2 = phi ptr [ poison, %bb5 ], [ %phi1, %bb4 ] + call void @use_ptr(ptr %phi2) + br label %bb5 +} + +declare void @use_bool(i1) +declare void @use_ptr(ptr)