From 4ddf51db6af36736d5d42c1043eeea86e47459ce Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Mon, 7 Apr 2014 12:31:14 +0800 Subject: [PATCH] i965/vec4: fix record clearing in copy propagation Given mov vgrf7, vgrf9.xyxz add vgrf9.xyz, vgrf4.xyzw, vgrf5.xyzw add vgrf10.x, vgrf6.xyzw, vgrf7.wwww the last instruction would be wrongly changed to add vgrf10.x, vgrf6.xyzw, vgrf9.zzzz during copy propagation. The issue is that when deciding if a record should be cleared, the old code checked for inst->dst.writemask & (1 << ch) instead of inst->dst.writemask & (1 << BRW_GET_SWZ(src->swizzle, ch)) Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=76749 Signed-off-by: Chia-I Wu Cc: Jordan Justen Cc: Matt Turner Reviewed-by: Ian Romainck Reviewed-by: Eric Anholt Cc: "10.1" --- .../dri/i965/brw_vec4_copy_propagation.cpp | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp b/src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp index 3d68f0ed5d4..83cf19114be 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp @@ -57,6 +57,21 @@ is_dominated_by_previous_instruction(vec4_instruction *inst) inst->opcode != BRW_OPCODE_ENDIF); } +static bool +is_channel_updated(vec4_instruction *inst, src_reg *values[4], int ch) +{ + const src_reg *src = values[ch]; + + /* consider GRF only */ + assert(inst->dst.file == GRF); + if (!src || src->file != GRF) + return false; + + return (src->reg == inst->dst.reg && + src->reg_offset == inst->dst.reg_offset && + inst->dst.writemask & (1 << BRW_GET_SWZ(src->swizzle, ch))); +} + static bool try_constant_propagation(vec4_instruction *inst, int arg, src_reg *values[4]) { @@ -357,11 +372,7 @@ vec4_visitor::opt_copy_propagation() else { for (int i = 0; i < virtual_grf_reg_count; i++) { for (int j = 0; j < 4; j++) { - if (inst->dst.writemask & (1 << j) && - cur_value[i][j] && - cur_value[i][j]->file == GRF && - cur_value[i][j]->reg == inst->dst.reg && - cur_value[i][j]->reg_offset == inst->dst.reg_offset) { + if (is_channel_updated(inst, cur_value[i], j)){ cur_value[i][j] = NULL; } } -- 2.30.2