[Beignet] [PATCH] GBE: try to avoid bank conflict in register allocator.
Ruiling Song
ruiling.song at intel.com
Wed Apr 27 05:50:48 UTC 2016
Signed-off-by: Ruiling Song <ruiling.song at intel.com>
---
backend/src/backend/gen_reg_allocation.cpp | 31 ++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/backend/src/backend/gen_reg_allocation.cpp b/backend/src/backend/gen_reg_allocation.cpp
index 89c53d4..ccb76a1 100644
--- a/backend/src/backend/gen_reg_allocation.cpp
+++ b/backend/src/backend/gen_reg_allocation.cpp
@@ -35,6 +35,7 @@
#include <iomanip>
+#define HALF_REGISTER_FILE_OFFSET (32*64)
namespace gbe
{
/////////////////////////////////////////////////////////////////////////////
@@ -48,8 +49,9 @@ namespace gbe
*/
struct GenRegInterval {
INLINE GenRegInterval(ir::Register reg) :
- reg(reg), minID(INT_MAX), maxID(-INT_MAX) {}
+ reg(reg), minID(INT_MAX), maxID(-INT_MAX), conflictReg(0) {}
ir::Register reg; //!< (virtual) register of the interval
+ ir::Register conflictReg;
int32_t minID, maxID; //!< Starting and ending points
};
@@ -1052,7 +1054,17 @@ namespace gbe
// and the source is a scalar Dword. If that is the case, the byte register
// must get 4byte alignment register offset.
alignment = (alignment + 3) & ~3;
- while ((grfOffset = ctx.allocate(size, alignment)) == 0) {
+
+ bool direction = true;
+ if (interval.conflictReg != 0) {
+ // try to allocate conflict registers in top/bottom half.
+ if (RA.contains(interval.conflictReg)) {
+ if (RA.find(interval.conflictReg)->second < HALF_REGISTER_FILE_OFFSE) {
+ direction = false;
+ }
+ }
+ }
+ while ((grfOffset = ctx.allocate(size, alignment, direction)) == 0) {
const bool success = this->expireGRF(interval);
if (success == false) {
if (spillAtInterval(interval, size, alignment) == false)
@@ -1104,6 +1116,7 @@ namespace gbe
for (auto &insn : block.insnList) {
const uint32_t srcNum = insn.srcNum, dstNum = insn.dstNum;
insn.ID = insnID;
+ bool is3SrcOp = insn.opcode == SELECTION_OP_MAD;
for (uint32_t srcID = 0; srcID < srcNum; ++srcID) {
const GenRegister &selReg = insn.src(srcID);
const ir::Register reg = selReg.reg();
@@ -1113,6 +1126,20 @@ namespace gbe
reg == ir::ocl::groupid1 ||
reg == ir::ocl::groupid2)
continue;
+ ir::Register conflictReg = ir::Register(0);
+ if (is3SrcOp) {
+ if (srcID == 1)
+ conflictReg = insn.src(2).reg();
+ else if (srcID == 2)
+ conflictReg = insn.src(1).reg();
+ }
+ // we only let it conflict with one register, and with smaller reg number,
+ // as smaller virtual register usually comes first,
+ // and linear scan allocator allocate from smaller to larger register
+ // so, conflict with larger register number will not make any effect.
+ if (this->intervals[reg].conflictReg == 0 ||
+ this->intervals[reg].conflictReg > conflictReg)
+ this->intervals[reg].conflictReg = conflictReg;
this->intervals[reg].minID = std::min(this->intervals[reg].minID, insnID);
this->intervals[reg].maxID = std::max(this->intervals[reg].maxID, insnID);
}
--
2.4.1
More information about the Beignet
mailing list