[llvm] r302096 - [SCEV] createAddRecFromPHI: Optimize for the most common case.
Michael Zolotukhin via llvm-commits
llvm-commits at lists.llvm.org
Wed May 3 16:53:39 PDT 2017
Author: mzolotukhin
Date: Wed May 3 18:53:38 2017
New Revision: 302096
URL: http://llvm.org/viewvc/llvm-project?rev=302096&view=rev
Log:
[SCEV] createAddRecFromPHI: Optimize for the most common case.
Summary:
The existing implementation creates a symbolic SCEV expression every
time we analyze a phi node and then has to remove it, when the analysis
is finished. This is very expensive, and in most of the cases it's also
unnecessary. According to the data I collected, ~60-70% of analyzed phi
nodes (measured on SPEC) have the following form:
PN = phi(Start, OP(Self, Constant))
Handling such cases separately significantly speeds this up.
Reviewers: sanjoy, pete
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D32663
Added:
llvm/trunk/test/Analysis/ScalarEvolution/ZeroStep.ll
Modified:
llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
llvm/trunk/lib/Analysis/ScalarEvolution.cpp
llvm/trunk/test/CodeGen/X86/2014-08-29-CompactUnwind.ll
Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolution.h?rev=302096&r1=302095&r2=302096&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ScalarEvolution.h (original)
+++ llvm/trunk/include/llvm/Analysis/ScalarEvolution.h Wed May 3 18:53:38 2017
@@ -816,6 +816,10 @@ private:
/// Helper function called from createNodeForPHI.
const SCEV *createAddRecFromPHI(PHINode *PN);
+ /// A helper function for createAddRecFromPHI to handle simple cases.
+ const SCEV *createSimpleAffineAddRec(PHINode *PN, Value *BEValueV,
+ Value *StartValueV);
+
/// Helper function called from createNodeForPHI.
const SCEV *createNodeFromSelectLikePHI(PHINode *PN);
Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=302096&r1=302095&r2=302096&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Wed May 3 18:53:38 2017
@@ -4083,6 +4083,56 @@ static Optional<BinaryOp> MatchBinaryOp(
return None;
}
+/// A helper function for createAddRecFromPHI to handle simple cases.
+///
+/// This function tries to find an AddRec expression for the simplest (yet most
+/// common) cases: PN = PHI(Start, OP(Self, LoopInvariant)).
+/// If it fails, createAddRecFromPHI will use a more general, but slow,
+/// technique for finding the AddRec expression.
+const SCEV *ScalarEvolution::createSimpleAffineAddRec(PHINode *PN,
+ Value *BEValueV,
+ Value *StartValueV) {
+ const Loop *L = LI.getLoopFor(PN->getParent());
+ assert(L && L->getHeader() == PN->getParent());
+ assert(BEValueV && StartValueV);
+
+ auto BO = MatchBinaryOp(BEValueV, DT);
+ if (!BO)
+ return nullptr;
+
+ if (BO->Opcode != Instruction::Add)
+ return nullptr;
+
+ const SCEV *Accum = nullptr;
+ if (BO->LHS == PN && L->isLoopInvariant(BO->RHS))
+ Accum = getSCEV(BO->RHS);
+ else if (BO->RHS == PN && L->isLoopInvariant(BO->LHS))
+ Accum = getSCEV(BO->LHS);
+
+ if (!Accum)
+ return nullptr;
+
+ SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap;
+ if (BO->IsNUW)
+ Flags = setFlags(Flags, SCEV::FlagNUW);
+ if (BO->IsNSW)
+ Flags = setFlags(Flags, SCEV::FlagNSW);
+
+ const SCEV *StartVal = getSCEV(StartValueV);
+ const SCEV *PHISCEV = getAddRecExpr(StartVal, Accum, L, Flags);
+
+ ValueExprMap[SCEVCallbackVH(PN, this)] = PHISCEV;
+
+ // We can add Flags to the post-inc expression only if we
+ // know that it us *undefined behavior* for BEValueV to
+ // overflow.
+ if (auto *BEInst = dyn_cast<Instruction>(BEValueV))
+ if (isLoopInvariant(Accum, L) && isAddRecNeverPoison(BEInst, L))
+ (void)getAddRecExpr(getAddExpr(StartVal, Accum), Accum, L, Flags);
+
+ return PHISCEV;
+}
+
const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
const Loop *L = LI.getLoopFor(PN->getParent());
if (!L || L->getHeader() != PN->getParent())
@@ -4111,10 +4161,16 @@ const SCEV *ScalarEvolution::createAddRe
if (!BEValueV || !StartValueV)
return nullptr;
- // While we are analyzing this PHI node, handle its value symbolically.
- const SCEV *SymbolicName = getUnknown(PN);
assert(ValueExprMap.find_as(PN) == ValueExprMap.end() &&
"PHI node already processed?");
+
+ // First, try to find AddRec expression without creating a fictituos symbolic
+ // value for PN.
+ if (auto *S = createSimpleAffineAddRec(PN, BEValueV, StartValueV))
+ return S;
+
+ // Handle PHI node value symbolically.
+ const SCEV *SymbolicName = getUnknown(PN);
ValueExprMap.insert({SCEVCallbackVH(PN, this), SymbolicName});
// Using this symbolic name for the PHI, analyze the value coming around
Added: llvm/trunk/test/Analysis/ScalarEvolution/ZeroStep.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ScalarEvolution/ZeroStep.ll?rev=302096&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/ScalarEvolution/ZeroStep.ll (added)
+++ llvm/trunk/test/Analysis/ScalarEvolution/ZeroStep.ll Wed May 3 18:53:38 2017
@@ -0,0 +1,18 @@
+; RUN: opt -analyze -scalar-evolution < %s -o - -S | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.9.0"
+
+; Test that SCEV is capable of figuring out value of 'IV' that actually does not change.
+; CHECK: Classifying expressions for: @foo
+; CHECK: %iv.i = phi i64
+; CHECK: -5 U: [-5,-4) S: [-5,-4) Exits: -5 LoopDispositions: { %loop: Invariant }
+define void @foo() {
+entry:
+ br label %loop
+
+loop:
+ %iv.i = phi i64 [ -5, %entry ], [ %iv.next.i, %loop ]
+ %iv.next.i = add nsw i64 %iv.i, 0
+ br label %loop
+}
Modified: llvm/trunk/test/CodeGen/X86/2014-08-29-CompactUnwind.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2014-08-29-CompactUnwind.ll?rev=302096&r1=302095&r2=302096&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/2014-08-29-CompactUnwind.ll (original)
+++ llvm/trunk/test/CodeGen/X86/2014-08-29-CompactUnwind.ll Wed May 3 18:53:38 2017
@@ -24,7 +24,7 @@ target triple = "x86_64-apple-macosx10.9
; CHECK-NOT: {{compact encoding:.*0x0309f800}}
; CHECK: {{compact encoding:.*0x030df800}}
-define void @__asan_report_error() #0 {
+define void @__asan_report_error(i64 %step) #0 {
%str.i = alloca i64, align 8
%stack = alloca [256 x i64], align 8
br label %print_shadow_bytes.exit.i
@@ -37,7 +37,7 @@ print_shadow_bytes.exit.i: ; preds = %pr
%reg17 = shl i64 %iv.i, 1
%reg19 = inttoptr i64 %reg17 to i8*
call void (i64*, i8*, ...) @append(i64* %str.i, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str2, i64 0, i64 0), i8* %reg16, i8* %reg19)
- %iv.next.i = add nsw i64 %iv.i, 0
+ %iv.next.i = add nsw i64 %iv.i, %step
br label %print_shadow_bytes.exit.i
}
More information about the llvm-commits
mailing list