summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhigang Gong <zhigang.gong@intel.com>2015-09-14 15:50:00 +0800
committerYang Rong <rong.r.yang@intel.com>2015-10-09 11:08:41 +0800
commit208ffc2153568bf3f1bbce744b10d8f97fb87da6 (patch)
tree39168c2d31f0a7663a58b792b58768410395be65
parent40b52ca9583b9c85022b21a961170f30dd3aaaab (diff)
downloadbeignet-208ffc2153568bf3f1bbce744b10d8f97fb87da6.tar.gz
GBE: fix a zero/one's liveness bug.
This is a long standing bug, and is exposed by my latest register allocation refinement patchset. ir::ocl::zero and ir::ocl::one are global registers, we have to compute its liveness information carefully, not just get a local interval ID. Signed-off-by: Zhigang Gong <zhigang.gong@intel.com> Reviewed-by: "Yang, Rong R" <rong.r.yang@intel.com>
-rw-r--r--backend/src/backend/gen_reg_allocation.cpp29
1 files changed, 29 insertions, 0 deletions
diff --git a/backend/src/backend/gen_reg_allocation.cpp b/backend/src/backend/gen_reg_allocation.cpp
index 747c2015..a9338c58 100644
--- a/backend/src/backend/gen_reg_allocation.cpp
+++ b/backend/src/backend/gen_reg_allocation.cpp
@@ -179,6 +179,8 @@ namespace gbe
SpilledRegs spilledRegs;
/*! register which could be spilled.*/
SpillCandidateSet spillCandidate;
+ /*! BBs last instruction ID map */
+ map<const ir::BasicBlock *, int32_t> bbLastInsnIDMap;
/* reserved registers for register spill/reload */
uint32_t reservedReg;
/*! Current vector to expire */
@@ -503,6 +505,7 @@ namespace gbe
// policy is to spill the allocate flag which live to the last time end point.
// we have three flags we use for booleans f0.0 , f1.0 and f1.1
+ set<const ir::BasicBlock *> liveInSet01;
for (auto &block : *selection.blockList) {
// Store the registers allocated in the map
map<ir::Register, uint32_t> allocatedFlags;
@@ -672,6 +675,7 @@ namespace gbe
sel0->src(0) = GenRegister::uw1grf(ir::ocl::one);
sel0->src(1) = GenRegister::uw1grf(ir::ocl::zero);
sel0->dst(0) = GET_FLAG_REG(insn);
+ liveInSet01.insert(insn.parent->bb);
insn.append(*sel0);
// We use the zero one after the liveness analysis, we have to update
// the liveness data manually here.
@@ -690,6 +694,30 @@ namespace gbe
}
}
}
+
+ // As we introduce two global variables zero and one, we have to
+ // recompute its liveness information here!
+ if (liveInSet01.size()) {
+ set<const ir::BasicBlock *> liveOutSet01;
+ set<const ir::BasicBlock *> workSet(liveInSet01.begin(), liveInSet01.end());
+ while(workSet.size()) {
+ for(auto bb : workSet) {
+ for(auto predBB : bb->getPredecessorSet()) {
+ liveOutSet01.insert(predBB);
+ if (liveInSet01.contains(predBB))
+ continue;
+ liveInSet01.insert(predBB);
+ workSet.insert(predBB);
+ }
+ workSet.erase(bb);
+ }
+ }
+ int32_t maxID = 0;
+ for(auto bb : liveOutSet01)
+ maxID = std::max(maxID, bbLastInsnIDMap.find(bb)->second);
+ intervals[ir::ocl::zero].maxID = std::max(intervals[ir::ocl::zero].maxID, maxID);
+ intervals[ir::ocl::one].maxID = std::max(intervals[ir::ocl::one].maxID, maxID);
+ }
}
IVAR(OCL_SIMD16_SPILL_THRESHOLD, 0, 16, 256);
@@ -1125,6 +1153,7 @@ namespace gbe
// All registers alive at the begining of the block must update their intervals.
const ir::BasicBlock *bb = block.bb;
+ bbLastInsnIDMap.insert(std::make_pair(bb, lastID));
for (auto reg : ctx.getLiveIn(bb))
this->intervals[reg].minID = std::min(this->intervals[reg].minID, firstID);