mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-04 01:26:41 +00:00
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@302096 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
bcd731ca9c
commit
805e09d964
@ -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);
|
||||
|
||||
|
@ -4083,6 +4083,56 @@ static Optional<BinaryOp> MatchBinaryOp(Value *V, DominatorTree &DT) {
|
||||
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::createAddRecFromPHI(PHINode *PN) {
|
||||
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
|
||||
|
18
test/Analysis/ScalarEvolution/ZeroStep.ll
Normal file
18
test/Analysis/ScalarEvolution/ZeroStep.ll
Normal file
@ -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
|
||||
}
|
@ -24,7 +24,7 @@ target triple = "x86_64-apple-macosx10.9.0"
|
||||
; 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 = %print_shadow_bytes.exit.i, %0
|
||||
%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
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user