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

Vincent Lejeune vljn at ovi.com
Mon Oct 14 11:04:44 PDT 2013


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             | 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




More information about the llvm-commits mailing list