[Beignet] [PATCH] GBE: optimize phi elimination.
Ruiling Song
ruiling.song at intel.com
Wed Jul 1 00:34:35 PDT 2015
This is special optimization for below situation:
bb1:
...
bb2:
x = phi [x1, bb1], [x2, bb2]
x2 = x+1;
after de-ssa:
bb2:
mov x, x-copy
add x2, x, 1
mov x-copy, x2
obviously x2, x-copy and x2 can be mapped to same virtual register.
Signed-off-by: Ruiling Song <ruiling.song at intel.com>
---
backend/src/llvm/llvm_gen_backend.cpp | 64 +++++++++++++++++++++++++++++++++--
1 file changed, 62 insertions(+), 2 deletions(-)
diff --git a/backend/src/llvm/llvm_gen_backend.cpp b/backend/src/llvm/llvm_gen_backend.cpp
index e1b6931..c5fdbf0 100644
--- a/backend/src/llvm/llvm_gen_backend.cpp
+++ b/backend/src/llvm/llvm_gen_backend.cpp
@@ -2134,6 +2134,9 @@ namespace gbe
// between phi and phiCopy live range. If there is no point that
// phi & phiCopy are both alive, then we can optimize off the move
// from phiCopy to phi, and use phiCopy directly instead of phi.
+ // right now, the algorithm is still very conservative, we need to do
+ // aggressive coaleasing for the moves added during phi elimination.
+
using namespace ir;
ir::FunctionDAG *dag = new ir::FunctionDAG(liveness);
@@ -2145,6 +2148,9 @@ namespace gbe
const ir::UseSet *phiUse = dag->getRegUse(phi);
const DefSet *phiDef = dag->getRegDef(phi);
bool isOpt = true;
+
+ const ir::BasicBlock *phiDefBB = (*phiDef->begin())->getInstruction()->getParent();
+
for (auto &x : *phiCopyDef) {
const ir::Instruction * phiCopyDefInsn = x->getInstruction();
const ir::BasicBlock *bb = phiCopyDefInsn->getParent();
@@ -2155,6 +2161,61 @@ namespace gbe
isOpt = false;
break;
}
+
+ const ir::Register phiCopySrc = phiCopyDefInsn->getSrc(0);
+ const ir::UseSet *phiCopySrcUse = dag->getRegUse(phiCopySrc);
+ const ir::DefSet *phiCopySrcDef = dag->getRegDef(phiCopySrc);
+ // non-ssa value. skip opt on such kind of value
+ if (phiCopySrcDef->size() > 1) break;
+
+ const ir::Instruction *phiCopySrcDefInsn = (*(phiCopySrcDef->begin()))->getInstruction();
+ if(bb == phiDefBB && bb == phiCopySrcDefInsn->getParent()) {
+ // phiCopy, phiCopySrc defined in same basicblock as phi
+ // try to coalease phiCopy and phiCopySrc first.
+ // consider below situation:
+ // bb1:
+ // ...
+ // bb2:
+ // x = phi [x1, bb1], [x2, bb2]
+ // x2 = x+1;
+ // after de-ssa:
+ // bb2:
+ // mov x, x-copy
+ // add x2, x, 1
+ // mov x-copy, x2
+ // obviously x2, x-copy and x2 can be mapped to same virtual register
+
+ ir::BasicBlock::const_iterator iter = ir::BasicBlock::const_iterator(phiCopySrcDefInsn);
+ ir::BasicBlock::const_iterator iterE = bb->end();
+ // check no use of phi in this basicblock between [phiCopySrc def, bb end]
+ bool phiPhiCopySrcInterfere = false;
+ while (iter != iterE) {
+ const ir::Instruction *insn = iter.node();
+ // check phiUse
+ for (unsigned i = 0; i < insn->getSrcNum(); i++) {
+ ir::Register src = insn->getSrc(i);
+ if (src == phi) {
+ phiPhiCopySrcInterfere = true; break;
+ }
+ }
+ ++iter;
+ }
+ if (!phiPhiCopySrcInterfere) {
+ // phiCopy source can be coaleased with phiCopy
+ const_cast<Instruction *>(phiCopyDefInsn)->remove();
+
+ for (auto &s : *phiCopySrcDef) {
+ const Instruction *phiSrcDefInsn = s->getInstruction();
+ replaceDst(const_cast<Instruction *>(phiSrcDefInsn), phiCopySrc, phiCopy);
+ }
+
+ for (auto &s : *phiCopySrcUse) {
+ const Instruction *phiSrcUseInsn = s->getInstruction();
+ replaceSrc(const_cast<Instruction *>(phiSrcUseInsn), phiCopySrc, phiCopy);
+ }
+ }
+ }
+
// If phi is used in the same BB that define the phiCopy,
// we need carefully check the liveness of phi & phiCopy.
// Make sure their live ranges do not interfere.
@@ -2184,8 +2245,7 @@ namespace gbe
}
}
- // [MOV phi, phiCopy;] can be removed. So we remove it
- // and replace phi uses with phiCopy
+ // coalease phi and phiCopy
if (isOpt) {
for (auto &x : *phiDef) {
const_cast<Instruction *>(x->getInstruction())->remove();
--
2.3.6
More information about the Beignet
mailing list