From c214bc2b8da91f38c4d2c060831229a17b6af816 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sat, 15 Dec 2018 00:32:38 +0000 Subject: [PATCH] [NewGVN] Update use counts for SSA copies when replacing them by their operands. The current code relies on LeaderUseCount to determine if we can remove an SSA copy, but in that the LeaderUseCount does not refer to the SSA copy. If a SSA copy is a dominating leader, we use the operand as dominating leader instead. This means we removed a user of a ssa copy and we should decrement its use count, so we can remove the ssa copy once it becomes dead. Fixes PR38804. Reviewers: efriedma, davide Reviewed By: davide Differential Revision: https://reviews.llvm.org/D51595 llvm-svn: 349217 --- llvm/lib/Transforms/Scalar/NewGVN.cpp | 11 ++-- llvm/test/Transforms/NewGVN/eliminate-ssacopy.ll | 81 ++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 llvm/test/Transforms/NewGVN/eliminate-ssacopy.ll diff --git a/llvm/lib/Transforms/Scalar/NewGVN.cpp b/llvm/lib/Transforms/Scalar/NewGVN.cpp index 6e9ab44..7cbb0fe 100644 --- a/llvm/lib/Transforms/Scalar/NewGVN.cpp +++ b/llvm/lib/Transforms/Scalar/NewGVN.cpp @@ -4093,10 +4093,13 @@ bool NewGVN::eliminateInstructions(Function &F) { // It's about to be alive again. if (LeaderUseCount == 0 && isa(DominatingLeader)) ProbablyDead.erase(cast(DominatingLeader)); - // Copy instructions, however, are still dead because we use their - // operand as the leader. - if (LeaderUseCount == 0 && isSSACopy) - ProbablyDead.insert(II); + // For copy instructions, we use their operand as a leader, + // which means we remove a user of the copy and it may become dead. + if (isSSACopy) { + unsigned &IIUseCount = UseCounts[II]; + if (--IIUseCount == 0) + ProbablyDead.insert(II); + } ++LeaderUseCount; AnythingReplaced = true; } diff --git a/llvm/test/Transforms/NewGVN/eliminate-ssacopy.ll b/llvm/test/Transforms/NewGVN/eliminate-ssacopy.ll new file mode 100644 index 0000000..57bed02 --- /dev/null +++ b/llvm/test/Transforms/NewGVN/eliminate-ssacopy.ll @@ -0,0 +1,81 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -newgvn -S < %s | FileCheck %s + +; Make sure the created ssa copies are cleaned up. See PR38804. + +; CHECK-NOT: ssa_copy + +@b = external dso_local local_unnamed_addr global i32, align 4 +@a = external dso_local local_unnamed_addr global i8, align 1 +@f = external dso_local local_unnamed_addr global i16, align 2 + +define void @g() { +; CHECK-LABEL: @g( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 undef, label [[FOR_COND1THREAD_PRE_SPLIT:%.*]], label [[FOR_COND_PREHEADER:%.*]] +; CHECK: for.cond.preheader: +; CHECK-NEXT: unreachable +; CHECK: for.cond1thread-pre-split: +; CHECK-NEXT: br label [[FOR_END4_SPLIT:%.*]] +; CHECK: for.end4.split: +; CHECK-NEXT: br i1 true, label [[FOR_COND6_PREHEADER:%.*]], label [[IF_END11:%.*]] +; CHECK: for.cond6.preheader: +; CHECK-NEXT: br i1 undef, label [[FOR_COND6_PREHEADER3:%.*]], label [[IF_END11_LOOPEXIT:%.*]] +; CHECK: for.cond6.preheader3: +; CHECK-NEXT: br label [[IF_END11_LOOPEXIT]] +; CHECK: if.end11.loopexit: +; CHECK-NEXT: [[STOREMERGE_LCSSA:%.*]] = phi i32 [ 0, [[FOR_COND6_PREHEADER]] ], [ 1, [[FOR_COND6_PREHEADER3]] ] +; CHECK-NEXT: store i32 [[STOREMERGE_LCSSA]], i32* @b, align 4 +; CHECK-NEXT: br label [[IF_END11]] +; CHECK: if.end11: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @b, align 4 +; CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* @a, align 1 +; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[TMP1]] to i32 +; CHECK-NEXT: [[CMP12:%.*]] = icmp eq i32 [[TMP0]], [[CONV]] +; CHECK-NEXT: br i1 [[CMP12]], label [[IF_THEN14:%.*]], label [[IF_END16:%.*]] +; CHECK: if.then14: +; CHECK-NEXT: [[CONV15:%.*]] = trunc i32 [[TMP0]] to i16 +; CHECK-NEXT: store i16 [[CONV15]], i16* @f, align 2 +; CHECK-NEXT: unreachable +; CHECK: if.end16: +; CHECK-NEXT: ret void +; +entry: + %tobool = icmp eq i32 undef, 0 + br i1 %tobool, label %for.cond1thread-pre-split, label %for.cond.preheader + +for.cond.preheader: ; preds = %entry + unreachable + +for.cond1thread-pre-split: ; preds = %entry + br label %for.end4.split + +for.end4.split: ; preds = %for.cond1thread-pre-split + br i1 %tobool, label %for.cond6.preheader, label %if.end11 + +for.cond6.preheader: ; preds = %for.end4.split + br i1 undef, label %for.cond6.preheader3, label %if.end11.loopexit + +for.cond6.preheader3: ; preds = %for.cond6.preheader + br label %if.end11.loopexit + +if.end11.loopexit: ; preds = %for.cond6.preheader3, %for.cond6.preheader + %storemerge.lcssa = phi i32 [ 0, %for.cond6.preheader ], [ 1, %for.cond6.preheader3 ] + store i32 %storemerge.lcssa, i32* @b, align 4 + br label %if.end11 + +if.end11: ; preds = %if.end11.loopexit, %for.end4.split + %0 = load i32, i32* @b, align 4 + %1 = load i8, i8* @a, align 1 + %conv = sext i8 %1 to i32 + %cmp12 = icmp eq i32 %0, %conv + br i1 %cmp12, label %if.then14, label %if.end16 + +if.then14: ; preds = %if.end11 + %conv15 = trunc i32 %0 to i16 + store i16 %conv15, i16* @f, align 2 + unreachable + +if.end16: ; preds = %if.end11 + ret void +} -- 2.7.4