From 0ed79620c6d2ff008a483d62f51b21e69f5bfac6 Mon Sep 17 00:00:00 2001 From: Max Kazantsev Date: Wed, 13 Jun 2018 02:25:32 +0000 Subject: [PATCH] [SimplifyIndVars] Ignore dead users IndVarSimplify sometimes makes transforms basing on users that are trivially dead. In particular, if DCE wasn't run before it, there may be a dead `sext/zext` in loop that will trigger widening transforms, however it makes no sense to do it. This patch teaches IndVarsSimplify ignore the mist trivial cases of that. Differential Revision: https://reviews.llvm.org/D47974 Reviewed By: sanjoy llvm-svn: 334567 --- llvm/lib/Transforms/Utils/SimplifyIndVar.cpp | 10 ++++++ .../ScalarEvolution/2012-05-29-MulAddRec.ll | 4 +++ llvm/test/Analysis/ScalarEvolution/guards.ll | 3 ++ .../IndVarSimplify/2011-09-10-widen-nsw.ll | 6 ++++ .../Transforms/IndVarSimplify/iv-widen.ll | 35 ++++++++++++++++++- .../Transforms/IndVarSimplify/lftr-reuse.ll | 5 ++- .../loop-invariant-conditions.ll | 3 ++ .../IndVarSimplify/no-iv-rewrite.ll | 5 +++ .../test/Transforms/IndVarSimplify/pr25578.ll | 3 ++ 9 files changed, 72 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp index e72602d016f5..a417b037314c 100644 --- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp @@ -26,6 +26,7 @@ #include "llvm/IR/PatternMatch.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Utils/Local.h" using namespace llvm; @@ -772,6 +773,15 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) { SimpleIVUsers.pop_back_val(); Instruction *UseInst = UseOper.first; + // If a user of the IndVar is trivially dead, we prefer just to mark it dead + // rather than try to do some complex analysis or transformation (such as + // widening) basing on it. + // TODO: Propagate TLI and pass it here to handle more cases. + if (isInstructionTriviallyDead(UseInst, /* TLI */ nullptr)) { + DeadInsts.emplace_back(UseInst); + continue; + } + // Bypass back edges to avoid extra work. if (UseInst == CurrIV) continue; diff --git a/llvm/test/Analysis/ScalarEvolution/2012-05-29-MulAddRec.ll b/llvm/test/Analysis/ScalarEvolution/2012-05-29-MulAddRec.ll index 3f04e2e21c46..5777e968f07e 100644 --- a/llvm/test/Analysis/ScalarEvolution/2012-05-29-MulAddRec.ll +++ b/llvm/test/Analysis/ScalarEvolution/2012-05-29-MulAddRec.ll @@ -8,6 +8,8 @@ ; ; PR12929: cast() argument of incompatible type +declare void @use(i8 %x) + ; CHECK: @func ; CHECK: for.cond: ; CHECK: %inc1 = phi i8 [ 0, %entry ], [ %0, %for.body ] @@ -33,6 +35,7 @@ for.cond: ; preds = %for.cond.loopexit, %indvars.iv = phi i8 [ %indvars.iv.next, %for.cond.loopexit ], [ 10, %entry ] %mul3 = phi i8 [ undef, %entry ], [ %mul.lcssa, %for.cond.loopexit ] %inc1 = phi i8 [ 0, %entry ], [ %0, %for.cond.loopexit ] + call void @use(i8 %inc1) br label %for.body for.body: ; preds = %for.body, %for.cond @@ -40,6 +43,7 @@ for.body: ; preds = %for.body, %for.cond %mul45 = phi i8 [ %mul3, %for.cond ], [ %mul, %for.body ] %inc = add i8 %inc26, 1 %mul = mul i8 %inc26, %mul45 + call void @use(i8 %inc) %exitcond = icmp ne i8 %inc, %indvars.iv br i1 %exitcond, label %for.body, label %for.cond.loopexit } diff --git a/llvm/test/Analysis/ScalarEvolution/guards.ll b/llvm/test/Analysis/ScalarEvolution/guards.ll index d4b1f431ffc6..dd86cc65ddc1 100644 --- a/llvm/test/Analysis/ScalarEvolution/guards.ll +++ b/llvm/test/Analysis/ScalarEvolution/guards.ll @@ -10,6 +10,8 @@ target datalayout = "n8:16:32:64" declare void @llvm.experimental.guard(i1, ...) +declare void @use(i64 %x) + define void @test_1(i1* %cond_buf, i32* %len_buf) { ; CHECK-LABEL: @test_1( entry: @@ -60,6 +62,7 @@ loop: %iv.inc = add i32 %iv, 1 %iv.sext = sext i32 %iv to i64 + call void @use(i64 %iv.sext) %iv.inc.cmp = icmp slt i32 %iv.inc, %len call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ] diff --git a/llvm/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll b/llvm/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll index ad63277db55a..09082c61eecd 100644 --- a/llvm/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll +++ b/llvm/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll @@ -5,6 +5,8 @@ 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" +declare void @use(i64 %x) + define void @test() nounwind { entry: br i1 undef, label %for.body11, label %for.end285 @@ -26,15 +28,19 @@ for.body170: ; preds = %for.body170, %for.b %add = add nsw i32 %i2.19, 1 %add.idxprom = sext i32 %add to i64 + call void @use(i64 %add.idxprom) %sub = sub nsw i32 %i2.19, 2 %sub.idxprom = sext i32 %sub to i64 + call void @use(i64 %sub.idxprom) %sub.neg = sub nsw i32 4, %i2.19 %sub.neg.idxprom = sext i32 %sub.neg to i64 + call void @use(i64 %sub.neg.idxprom) %mul = mul nsw i32 %i2.19, 8 %mul.idxprom = sext i32 %mul to i64 + call void @use(i64 %mul.idxprom) %add249 = add nsw i32 %i2.19, %shl132 br label %for.body170 diff --git a/llvm/test/Transforms/IndVarSimplify/iv-widen.ll b/llvm/test/Transforms/IndVarSimplify/iv-widen.ll index aa69da4b5053..558869aac926 100644 --- a/llvm/test/Transforms/IndVarSimplify/iv-widen.ll +++ b/llvm/test/Transforms/IndVarSimplify/iv-widen.ll @@ -7,10 +7,12 @@ target datalayout = "n8:16:32:64" target triple = "x86_64-apple-darwin" +declare void @use(i64 %x) + ; CHECK-LABEL: @loop_0 ; CHECK-LABEL: B18: ; Only one phi now. -; CHECK: phi +; CHECK: phi i64 ; CHECK-NOT: phi ; One trunc for the gep. ; CHECK: trunc i64 %indvars.iv to i32 @@ -21,6 +23,37 @@ define void @loop_0(i32* %a) { Prologue: br i1 undef, label %B18, label %B6 +B18: ; preds = %B24, %Prologue + %.02 = phi i32 [ 0, %Prologue ], [ %tmp33, %B24 ] + %tmp23 = zext i32 %.02 to i64 + call void @use(i64 %tmp23) + %tmp33 = add i32 %.02, 1 + %o = getelementptr i32, i32* %a, i32 %.02 + %v = load i32, i32* %o + %t = icmp eq i32 %v, 0 + br i1 %t, label %exit24, label %B24 + +B24: ; preds = %B18 + %t2 = icmp eq i32 %tmp33, 20 + br i1 %t2, label %B6, label %B18 + +B6: ; preds = %Prologue + ret void + +exit24: ; preds = %B18 + call void @dummy(i32 %.02) + unreachable +} + +; Make sure that dead zext is removed and no widening happens. +; CHECK-LABEL: @loop_0.dead +; CHECK: phi i32 +; CHECK-NOT: zext +; CHECK-NOT: trunc +define void @loop_0.dead(i32* %a) { +Prologue: + br i1 undef, label %B18, label %B6 + B18: ; preds = %B24, %Prologue %.02 = phi i32 [ 0, %Prologue ], [ %tmp33, %B24 ] %tmp23 = zext i32 %.02 to i64 diff --git a/llvm/test/Transforms/IndVarSimplify/lftr-reuse.ll b/llvm/test/Transforms/IndVarSimplify/lftr-reuse.ll index b4e1fdef4885..dd09f162d793 100644 --- a/llvm/test/Transforms/IndVarSimplify/lftr-reuse.ll +++ b/llvm/test/Transforms/IndVarSimplify/lftr-reuse.ll @@ -6,6 +6,8 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3 ; Perform LFTR using the original pointer-type IV. +declare void @use(double %x) + ; for(char* p = base; p < base + n; ++p) { ; *p = p-base; ; } @@ -102,9 +104,11 @@ loop: %diagidxw = sext i32 %diagidx to i64 %matrixp = getelementptr inbounds [0 x double], [0 x double]* %matrix, i32 0, i64 %diagidxw %v1 = load double, double* %matrixp + call void @use(double %v1) %iw = sext i32 %i to i64 %vectorp = getelementptr inbounds [0 x double], [0 x double]* %vector, i32 0, i64 %iw %v2 = load double, double* %vectorp + call void @use(double %v2) %row.inc = add nsw i32 %rowidx, %ilead %i.inc = add nsw i32 %i, 1 %cmp196 = icmp slt i32 %i.inc, %irow @@ -125,7 +129,6 @@ entry: ; CHECK-NOT: add ; CHECK: loop: ; CHECK: phi i64 -; CHECK: phi i64 ; CHECK-NOT: phi ; CHECK: icmp slt ; CHECK: br i1 diff --git a/llvm/test/Transforms/IndVarSimplify/loop-invariant-conditions.ll b/llvm/test/Transforms/IndVarSimplify/loop-invariant-conditions.ll index 1a63c7955484..320f0b30cb98 100644 --- a/llvm/test/Transforms/IndVarSimplify/loop-invariant-conditions.ll +++ b/llvm/test/Transforms/IndVarSimplify/loop-invariant-conditions.ll @@ -293,6 +293,8 @@ for.end: ; preds = %if.end, %entry ret void } +declare void @use(i1 %x) + ; check that we handle conditions with loop invariant operands which ; *aren't* in the header - this is a very rare and fragile case where ; we have a "loop" which is known to run exactly one iteration but @@ -320,6 +322,7 @@ latch: br i1 true, label %exit, label %loop exit: + call void @use(i1 %cmp) ret void } diff --git a/llvm/test/Transforms/IndVarSimplify/no-iv-rewrite.ll b/llvm/test/Transforms/IndVarSimplify/no-iv-rewrite.ll index ca7b89911662..ff344cb79e45 100644 --- a/llvm/test/Transforms/IndVarSimplify/no-iv-rewrite.ll +++ b/llvm/test/Transforms/IndVarSimplify/no-iv-rewrite.ll @@ -357,6 +357,9 @@ exit: ret void } +declare void @use32(i32 %x) +declare void @use64(i64 %x) + ; Test a widened IV that is used by a phi on different paths within the loop. ; ; CHECK: for.body: @@ -385,10 +388,12 @@ if.else: if.then97: %idxprom100 = sext i32 %iv to i64 + call void @use64(i64 %idxprom100) br label %for.inc for.inc: %kmin.1 = phi i32 [ %iv, %if.then33 ], [ 0, %if.then ], [ %iv, %if.then97 ], [ 0, %if.else ] + call void @use32(i32 %kmin.1) %inc = add nsw i32 %iv, 1 br i1 undef, label %for.body, label %for.end diff --git a/llvm/test/Transforms/IndVarSimplify/pr25578.ll b/llvm/test/Transforms/IndVarSimplify/pr25578.ll index bc648b517bbe..b9d374a4c772 100644 --- a/llvm/test/Transforms/IndVarSimplify/pr25578.ll +++ b/llvm/test/Transforms/IndVarSimplify/pr25578.ll @@ -1,6 +1,8 @@ ; RUN: opt < %s -indvars -S | FileCheck %s target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +declare void @use(i64 %x) + ; CHECK-LABEL: @foo define void @foo() { entry: @@ -15,6 +17,7 @@ L1_header: L2_header: %i = phi i32 [ 0, %L1_header ], [ %i_next, %L2_latch ] %i_prom = sext i32 %i to i64 + call void @use(i64 %i_prom) br label %L3_header L3_header: