[PATCH] Make sink pass able to sink instructions in block-loop-block situation.

Tom Stellard tom at stellard.net
Tue Oct 29 09:48:56 PDT 2013


Ping.

On Mon, Oct 21, 2013 at 06:02:50AM -0700, Vincent Lejeune wrote:
> I noticed that I added an uneeded include, this newer patch removes it.
> 
> I tested the changes with lit test for all targets and ran llvm-test-suite on x86 with
> no regression on Fedora 19 x86.
> 
> Can I have a review please ?
> 
> 
> Vincent
> 
> 
> 
> 
> ----- Mail original -----
> > De : Vincent Lejeune <vljn at ovi.com>
> > À : llvm-commits at cs.uiuc.edu
> > Cc : Vincent Lejeune <vljn at ovi.com>
> > Envoyé le : Lundi 14 octobre 2013 20h04
> > Objet : [PATCH] Make sink pass able to sink instructions in block-loop-block situation.
> > 
> >T his patch makes Sink pass able to sink instruction from blocks with single
> > successor and to consider all dominated block as sink candidate.
> > 
> > It allows to reduce register liveness length in case like :
> > %BB1
> >   .. Lot of defs
> >   br label %LOOP
> > %LOOP
> >   ..
> >   br i1 %indvar, label %LOOP, label %BB2
> > %BB2
> >   .. Uses of value from %BB1
> > ---
> > lib/Transforms/Scalar/Sink.cpp             | 38 +++++++++++++++++------------
> > test/Transforms/Sink/aggressive-sinking.ll | 39 ++++++++++++++++++++++++++++++
> > 2 files changed, 62 insertions(+), 15 deletions(-)
> > create mode 100644 test/Transforms/Sink/aggressive-sinking.ll
> > 
> > diff --git a/lib/Transforms/Scalar/Sink.cpp b/lib/Transforms/Scalar/Sink.cpp
> > index d4595bb..ce2af39 100644
> > --- a/lib/Transforms/Scalar/Sink.cpp
> > +++ b/lib/Transforms/Scalar/Sink.cpp
> > @@ -24,6 +24,7 @@
> > #include "llvm/Support/CFG.h"
> > #include "llvm/Support/Debug.h"
> > #include "llvm/Support/raw_ostream.h"
> > +#include "llvm/ADT/DepthFirstIterator.h"
> > using namespace llvm;
> > 
> > STATISTIC(NumSunk, "Number of instructions sunk");
> > @@ -54,6 +55,7 @@ namespace {
> >      }
> >    private:
> >      bool ProcessBlock(BasicBlock &BB);
> > +    BasicBlock *ParseSinkToCandidates(Instruction *Inst, BasicBlock *BB) const;
> >      bool SinkInstruction(Instruction *I, SmallPtrSet<Instruction *, 8> 
> > &Stores);
> >      bool AllUsesDominatedByBlock(Instruction *Inst, BasicBlock *BB) const;
> >      bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo) const;
> > @@ -117,8 +119,7 @@ bool Sinking::runOnFunction(Function &F) {
> > }
> > 
> > bool Sinking::ProcessBlock(BasicBlock &BB) {
> > -  // Can't sink anything out of a block that has less than two successors.
> > -  if (BB.getTerminator()->getNumSuccessors() <= 1 || BB.empty()) return 
> > false;
> > +  if (BB.empty()) return false;
> > 
> >    // Don't bother sinking code out of unreachable blocks. In addition to 
> > being
> >    // unprofitable, it can also lead to infinite looping, because in an
> > @@ -214,6 +215,25 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst,
> >    return AllUsesDominatedByBlock(Inst, SuccToSinkTo);
> > }
> > 
> > +/// ParseSinkToCandidates - Evaluate all block dominated by BB as sink
> > +/// destination.
> > +BasicBlock *Sinking::ParseSinkToCandidates(Instruction *Inst,
> > +                                           BasicBlock *BB) const {
> > +  DomTreeNode *DTN = DT->getNode(BB);
> > +  for (DomTreeNode::iterator I = DTN->begin(), E = DTN->end(); I != E; 
> > ++I) {
> > +    BasicBlock *Candidate = (*I)->getBlock();
> > +    if (IsAcceptableTarget(Inst, Candidate))
> > +      return Candidate;
> > +    // If some uses are not dominated by Candidate, we can prune the dominator
> > +    // tree beneath.
> > +    if (!AllUsesDominatedByBlock(Inst, Candidate))
> > +      continue;
> > +    if (BasicBlock *ChildCandidate = ParseSinkToCandidates(Inst, Candidate))
> > +      return ChildCandidate;
> > +  }
> > +  return NULL;
> > +}
> > +
> > /// SinkInstruction - Determine whether it is safe to sink the specified machine
> > /// instruction out of its current block into a successor.
> > bool Sinking::SinkInstruction(Instruction *Inst,
> > @@ -232,19 +252,7 @@ bool Sinking::SinkInstruction(Instruction *Inst,
> > 
> >    // SuccToSinkTo - This is the successor to sink this instruction to, once we
> >    // decide.
> > -  BasicBlock *SuccToSinkTo = 0;
> > -
> > -  // Instructions can only be sunk if all their uses are in blocks
> > -  // dominated by one of the successors.
> > -  // Look at all the postdominators and see if we can sink it in one.
> > -  DomTreeNode *DTN = DT->getNode(Inst->getParent());
> > -  for (DomTreeNode::iterator I = DTN->begin(), E = DTN->end();
> > -      I != E && SuccToSinkTo == 0; ++I) {
> > -    BasicBlock *Candidate = (*I)->getBlock();
> > -    if ((*I)->getIDom()->getBlock() == Inst->getParent() &&
> > -        IsAcceptableTarget(Inst, Candidate))
> > -      SuccToSinkTo = Candidate;
> > -  }
> > +  BasicBlock *SuccToSinkTo = ParseSinkToCandidates(Inst, Inst->getParent());
> > 
> >    // If no suitable postdominator was found, look at all the successors and
> >    // decide which one we should sink to, if any.
> > diff --git a/test/Transforms/Sink/aggressive-sinking.ll 
> > b/test/Transforms/Sink/aggressive-sinking.ll
> > new file mode 100644
> > index 0000000..08e49d6
> > --- /dev/null
> > +++ b/test/Transforms/Sink/aggressive-sinking.ll
> > @@ -0,0 +1,39 @@
> > +; RUN: opt < %s -basicaa -sink -S | FileCheck %s
> > +
> > +;CHECK-LABEL: @main
> > +;CHECK-LABEL: after_loop
> > +;CHECK: getelementptr
> > + 
> > +define void @main([32 x <16 x i8>] addrspace(2)* byval, [16 x <32 x 
> > i8>] addrspace(2)* byval) {
> > +main_body:
> > +  %2 = getelementptr [32 x <16 x i8>] addrspace(2)* %0, i64 0, i32 0
> > +  %3 = load <16 x i8> addrspace(2)* %2
> > +  %4 = getelementptr [16 x <32 x i8>] addrspace(2)* %1, i64 0, i32 0
> > +  %5 = load <32 x i8> addrspace(2)* %4
> > +  br label %loop
> > + 
> > +loop:                                             ; preds = %loop, %main_body
> > +  %indvar = phi i32 [0, %main_body], [%indvarincr, %loop]
> > +  %temp = phi float [1.0, %main_body], [%tempincr, %loop]
> > +  %indvarincr = add i32 %indvar, 1
> > +  %tempincr = fadd float %temp, 1.0
> > +  %6 = icmp ne i32 %indvar, 100
> > +  br i1 %6, label %after_loop, label %loop
> > + 
> > +after_loop:                                            ; preds = %after_loop
> > +  %7 = phi float [%temp, %loop]
> > +  %8 = bitcast float %7 to i32
> > +  %9 = insertelement <2 x i32> undef, i32 %8, i32 0
> > +  %10 = call <4 x float> @llvm.SI.sample.v2i32(<2 x i32> %9, <32 
> > x i8> %5, <16 x i8> %3, i32 0)
> > +  %11 = extractelement <4 x float> %10, i32 0
> > +  call void @llvm.SI.export(i32 15, i32 1, i32 1, i32 0, i32 1, float %11, 
> > float %11, float %11, float %11)
> > +  ret void
> > + 
> > +}
> > +
> > +; Function Attrs: nounwind readnone
> > +declare <4 x float> @llvm.SI.sample.v2i32(<2 x i32>, <32 x 
> > i8>, <16 x i8>, i32) #1
> > +
> > +declare void @llvm.SI.export(i32, i32, i32, i32, i32, float, float, float, 
> > float)
> > +
> > +attributes #1 = { nounwind readnone }
> > -- 
> > 1.8.3.1
> > 

> From be881a2378ce49c87ada565309f671d061c9b12f Mon Sep 17 00:00:00 2001
> From: Vincent Lejeune <vljn at ovi.com>
> Date: Wed, 9 Oct 2013 19:39:44 +0200
> Subject: [PATCH] Make sink pass able to sink instructions in block-loop-block
>  situation.
> 
> This patch makes Sink pass able to sink instruction from blocks with single
> successor and to consider all dominated block as sink candidate.
> 
> It allows to reduce register liveness length in case like :
> %BB1
>   .. Lot of defs
>   br label %LOOP
> %LOOP
>   ..
>   br i1 %indvar, label %LOOP, label %BB2
> %BB2
>   .. Uses of value from %BB1
> ---
>  lib/Transforms/Scalar/Sink.cpp             | 37 ++++++++++++++++------------
>  test/Transforms/Sink/aggressive-sinking.ll | 39 ++++++++++++++++++++++++++++++
>  2 files changed, 61 insertions(+), 15 deletions(-)
>  create mode 100644 test/Transforms/Sink/aggressive-sinking.ll
> 
> diff --git a/lib/Transforms/Scalar/Sink.cpp b/lib/Transforms/Scalar/Sink.cpp
> index d4595bb..005633d 100644
> --- a/lib/Transforms/Scalar/Sink.cpp
> +++ b/lib/Transforms/Scalar/Sink.cpp
> @@ -54,6 +54,7 @@ namespace {
>      }
>    private:
>      bool ProcessBlock(BasicBlock &BB);
> +    BasicBlock *ParseSinkToCandidates(Instruction *Inst, BasicBlock *BB) const;
>      bool SinkInstruction(Instruction *I, SmallPtrSet<Instruction *, 8> &Stores);
>      bool AllUsesDominatedByBlock(Instruction *Inst, BasicBlock *BB) const;
>      bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo) const;
> @@ -117,8 +118,7 @@ bool Sinking::runOnFunction(Function &F) {
>  }
>  
>  bool Sinking::ProcessBlock(BasicBlock &BB) {
> -  // Can't sink anything out of a block that has less than two successors.
> -  if (BB.getTerminator()->getNumSuccessors() <= 1 || BB.empty()) return false;
> +  if (BB.empty()) return false;
>  
>    // Don't bother sinking code out of unreachable blocks. In addition to being
>    // unprofitable, it can also lead to infinite looping, because in an
> @@ -214,6 +214,25 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst,
>    return AllUsesDominatedByBlock(Inst, SuccToSinkTo);
>  }
>  
> +/// ParseSinkToCandidates - Evaluate all block dominated by BB as sink
> +/// destination.
> +BasicBlock *Sinking::ParseSinkToCandidates(Instruction *Inst,
> +                                           BasicBlock *BB) const {
> +  DomTreeNode *DTN = DT->getNode(BB);
> +  for (DomTreeNode::iterator I = DTN->begin(), E = DTN->end(); I != E; ++I) {
> +    BasicBlock *Candidate = (*I)->getBlock();
> +    if (IsAcceptableTarget(Inst, Candidate))
> +      return Candidate;
> +    // If some uses are not dominated by Candidate, we can prune the dominator
> +    // tree beneath.
> +    if (!AllUsesDominatedByBlock(Inst, Candidate))
> +      continue;
> +    if (BasicBlock *ChildCandidate = ParseSinkToCandidates(Inst, Candidate))
> +      return ChildCandidate;
> +  }
> +  return NULL;
> +}
> +
>  /// SinkInstruction - Determine whether it is safe to sink the specified machine
>  /// instruction out of its current block into a successor.
>  bool Sinking::SinkInstruction(Instruction *Inst,
> @@ -232,19 +251,7 @@ bool Sinking::SinkInstruction(Instruction *Inst,
>  
>    // SuccToSinkTo - This is the successor to sink this instruction to, once we
>    // decide.
> -  BasicBlock *SuccToSinkTo = 0;
> -
> -  // Instructions can only be sunk if all their uses are in blocks
> -  // dominated by one of the successors.
> -  // Look at all the postdominators and see if we can sink it in one.
> -  DomTreeNode *DTN = DT->getNode(Inst->getParent());
> -  for (DomTreeNode::iterator I = DTN->begin(), E = DTN->end();
> -      I != E && SuccToSinkTo == 0; ++I) {
> -    BasicBlock *Candidate = (*I)->getBlock();
> -    if ((*I)->getIDom()->getBlock() == Inst->getParent() &&
> -        IsAcceptableTarget(Inst, Candidate))
> -      SuccToSinkTo = Candidate;
> -  }
> +  BasicBlock *SuccToSinkTo = ParseSinkToCandidates(Inst, Inst->getParent());
>  
>    // If no suitable postdominator was found, look at all the successors and
>    // decide which one we should sink to, if any.
> diff --git a/test/Transforms/Sink/aggressive-sinking.ll b/test/Transforms/Sink/aggressive-sinking.ll
> new file mode 100644
> index 0000000..08e49d6
> --- /dev/null
> +++ b/test/Transforms/Sink/aggressive-sinking.ll
> @@ -0,0 +1,39 @@
> +; RUN: opt < %s -basicaa -sink -S | FileCheck %s
> +
> +;CHECK-LABEL: @main
> +;CHECK-LABEL: after_loop
> +;CHECK: getelementptr
> + 
> +define void @main([32 x <16 x i8>] addrspace(2)* byval, [16 x <32 x i8>] addrspace(2)* byval) {
> +main_body:
> +  %2 = getelementptr [32 x <16 x i8>] addrspace(2)* %0, i64 0, i32 0
> +  %3 = load <16 x i8> addrspace(2)* %2
> +  %4 = getelementptr [16 x <32 x i8>] addrspace(2)* %1, i64 0, i32 0
> +  %5 = load <32 x i8> addrspace(2)* %4
> +  br label %loop
> + 
> +loop:                                             ; preds = %loop, %main_body
> +  %indvar = phi i32 [0, %main_body], [%indvarincr, %loop]
> +  %temp = phi float [1.0, %main_body], [%tempincr, %loop]
> +  %indvarincr = add i32 %indvar, 1
> +  %tempincr = fadd float %temp, 1.0
> +  %6 = icmp ne i32 %indvar, 100
> +  br i1 %6, label %after_loop, label %loop
> + 
> +after_loop:                                            ; preds = %after_loop
> +  %7 = phi float [%temp, %loop]
> +  %8 = bitcast float %7 to i32
> +  %9 = insertelement <2 x i32> undef, i32 %8, i32 0
> +  %10 = call <4 x float> @llvm.SI.sample.v2i32(<2 x i32> %9, <32 x i8> %5, <16 x i8> %3, i32 0)
> +  %11 = extractelement <4 x float> %10, i32 0
> +  call void @llvm.SI.export(i32 15, i32 1, i32 1, i32 0, i32 1, float %11, float %11, float %11, float %11)
> +  ret void
> + 
> +}
> +
> +; Function Attrs: nounwind readnone
> +declare <4 x float> @llvm.SI.sample.v2i32(<2 x i32>, <32 x i8>, <16 x i8>, i32) #1
> +
> +declare void @llvm.SI.export(i32, i32, i32, i32, i32, float, float, float, float)
> +
> +attributes #1 = { nounwind readnone }
> -- 
> 1.8.3.1
> 

> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits





More information about the llvm-commits mailing list