extsrc/mesa/src/mesa/drivers/dri/i965/brw_fs.cpp
/**
 * Attempts to move immediate constants into the immediate
 * constant slot of following instructions.
 *
 * Immediate constants are a bit tricky -- they have to be in the last
 * operand slot, you can't do abs/negate on them,
 */
Attempts to move immediate constants into the immediate
constant slot of following instructions.

Immediate constants are a bit tricky -- they have to be in the last
operand slot, you can't do abs/negate on them.
Attempts to move immediate constants into the immediate constant slot of following instructions . Immediate constants are a bit tricky -- they have to be in the last operand slot you can ' t do abs / negate on them .
bool
fs_visitor::propagate_constants()
{
   bool progress = false;
   calculate_live_intervals();
   foreach_list(node, &this->instructions) {
      fs_inst *inst = (fs_inst *)node;
      if (inst->opcode != BRW_OPCODE_MOV ||
	  inst->predicated ||
	  inst->dst.file != GRF || inst->src[0].file != IMM ||
	  inst->dst.type != inst->src[0].type ||
	  (c->dispatch_width == 16 &&
	   (inst->force_uncompressed || inst->force_sechalf)))
	 continue;
      if (inst->saturate)
	 continue;
      for (fs_inst *scan_inst = (fs_inst *)inst->next;
	   !scan_inst->is_tail_sentinel();
	   scan_inst = (fs_inst *)scan_inst->next) {
	 if (scan_inst->opcode == BRW_OPCODE_DO ||
	     scan_inst->opcode == BRW_OPCODE_WHILE ||
	     scan_inst->opcode == BRW_OPCODE_ELSE ||
	     scan_inst->opcode == BRW_OPCODE_ENDIF) {
	    break;
	 }
	 for (int i = 2; i >= 0; i--) {
	    if (scan_inst->src[i].file != GRF ||
		scan_inst->src[i].reg != inst->dst.reg ||
		scan_inst->src[i].reg_offset != inst->dst.reg_offset)
	       continue;
	    if (scan_inst->src[i].negate || scan_inst->src[i].abs)
	       continue;
	    switch (scan_inst->opcode) {
	    case BRW_OPCODE_MOV:
	       scan_inst->src[i] = inst->src[0];
	       progress = true;
	       break;
	    case BRW_OPCODE_MUL:
	    case BRW_OPCODE_ADD:
	       if (i == 1) {
		  scan_inst->src[i] = inst->src[0];
		  progress = true;
	       } else if (i == 0 && scan_inst->src[1].file != IMM) {
		  if (scan_inst->opcode == BRW_OPCODE_MUL &&
		      (scan_inst->src[1].type == BRW_REGISTER_TYPE_D ||
		       scan_inst->src[1].type == BRW_REGISTER_TYPE_UD))
		     break;
		  scan_inst->src[0] = scan_inst->src[1];
		  scan_inst->src[1] = inst->src[0];
		  progress = true;
	       }
	       break;
	    case BRW_OPCODE_CMP:
	    case BRW_OPCODE_IF:
	       if (i == 1) {
		  scan_inst->src[i] = inst->src[0];
		  progress = true;
	       } else if (i == 0 && scan_inst->src[1].file != IMM) {
		  uint32_t new_cmod;
		  new_cmod = brw_swap_cmod(scan_inst->conditional_mod);
		  if (new_cmod != ~0u) {
		     scan_inst->src[0] = scan_inst->src[1];
		     scan_inst->src[1] = inst->src[0];
		     scan_inst->conditional_mod = new_cmod;
		     progress = true;
		  }
	       }
	       break;
	    case BRW_OPCODE_SEL:
	       if (i == 1) {
		  scan_inst->src[i] = inst->src[0];
		  progress = true;
	       } else if (i == 0 && scan_inst->src[1].file != IMM) {
		  scan_inst->src[0] = scan_inst->src[1];
		  scan_inst->src[1] = inst->src[0];
		  if (scan_inst->conditional_mod == BRW_CONDITIONAL_NONE) {
		     scan_inst->predicate_inverse =
			!scan_inst->predicate_inverse;
		  }
		  progress = true;
	       }
	       break;
	    case SHADER_OPCODE_RCP:
	       assert(i == 0);
	       if (inst->src[0].imm.f != 0.0f) {
		  scan_inst->opcode = BRW_OPCODE_MOV;
		  scan_inst->src[0] = inst->src[0];
		  scan_inst->src[0].imm.f = 1.0f / scan_inst->src[0].imm.f;
		  progress = true;
	       }
	       break;
	    default:
	       break;
	    }
	 }
	 if (scan_inst->dst.file == GRF &&
	     scan_inst->dst.reg == inst->dst.reg &&
	     (scan_inst->dst.reg_offset == inst->dst.reg_offset ||
	      scan_inst->is_tex())) {
	    break;
	 }
      }
   }
   if (progress)
       this->live_intervals_valid = false;
   return progress;
}
bool fs_visitor :: propagate_constants ( ) { bool progress = false ; calculate_live_intervals ( ) ; foreach_list ( node , & this -> instructions ) { fs_inst * inst = ( fs_inst * ) node ; if ( inst -> opcode != BRW_OPCODE_MOV || inst -> predicated || inst -> dst . file != GRF || inst -> src [ 0 ] . file != IMM || inst -> dst . type != inst -> src [ 0 ] . type || ( c -> dispatch_width == 16 && ( inst -> force_uncompressed || inst -> force_sechalf ) ) ) continue ; if ( inst -> saturate ) continue ; for ( fs_inst * scan_inst = ( fs_inst * ) inst -> next ; ! scan_inst -> is_tail_sentinel ( ) ; scan_inst = ( fs_inst * ) scan_inst -> next ) { if ( scan_inst -> opcode == BRW_OPCODE_DO || scan_inst -> opcode == BRW_OPCODE_WHILE || scan_inst -> opcode == BRW_OPCODE_ELSE || scan_inst -> opcode == BRW_OPCODE_ENDIF ) { break ; } for ( int i = 2 ; i >= 0 ; i -- ) { if ( scan_inst -> src [ i ] . file != GRF || scan_inst -> src [ i ] . reg != inst -> dst . reg || scan_inst -> src [ i ] . reg_offset != inst -> dst . reg_offset ) continue ; if ( scan_inst -> src [ i ] . negate || scan_inst -> src [ i ] . abs ) continue ; switch ( scan_inst -> opcode ) { case BRW_OPCODE_MOV : scan_inst -> src [ i ] = inst -> src [ 0 ] ; progress = true ; break ; case BRW_OPCODE_MUL : case BRW_OPCODE_ADD : if ( i == 1 ) { scan_inst -> src [ i ] = inst -> src [ 0 ] ; progress = true ; } else if ( i == 0 && scan_inst -> src [ 1 ] . file != IMM ) { if ( scan_inst -> opcode == BRW_OPCODE_MUL && ( scan_inst -> src [ 1 ] . type == BRW_REGISTER_TYPE_D || scan_inst -> src [ 1 ] . type == BRW_REGISTER_TYPE_UD ) ) break ; scan_inst -> src [ 0 ] = scan_inst -> src [ 1 ] ; scan_inst -> src [ 1 ] = inst -> src [ 0 ] ; progress = true ; } break ; case BRW_OPCODE_CMP : case BRW_OPCODE_IF : if ( i == 1 ) { scan_inst -> src [ i ] = inst -> src [ 0 ] ; progress = true ; } else if ( i == 0 && scan_inst -> src [ 1 ] . file != IMM ) { uint32_t new_cmod ; new_cmod = brw_swap_cmod ( scan_inst -> conditional_mod ) ; if ( new_cmod != ~ 0u ) { scan_inst -> src [ 0 ] = scan_inst -> src [ 1 ] ; scan_inst -> src [ 1 ] = inst -> src [ 0 ] ; scan_inst -> conditional_mod = new_cmod ; progress = true ; } } break ; case BRW_OPCODE_SEL : if ( i == 1 ) { scan_inst -> src [ i ] = inst -> src [ 0 ] ; progress = true ; } else if ( i == 0 && scan_inst -> src [ 1 ] . file != IMM ) { scan_inst -> src [ 0 ] = scan_inst -> src [ 1 ] ; scan_inst -> src [ 1 ] = inst -> src [ 0 ] ; if ( scan_inst -> conditional_mod == BRW_CONDITIONAL_NONE ) { scan_inst -> predicate_inverse = ! scan_inst -> predicate_inverse ; } progress = true ; } break ; case SHADER_OPCODE_RCP : assert ( i == 0 ) ; if ( inst -> src [ 0 ] . imm . f != 0.0f ) { scan_inst -> opcode = BRW_OPCODE_MOV ; scan_inst -> src [ 0 ] = inst -> src [ 0 ] ; scan_inst -> src [ 0 ] . imm . f = 1.0f / scan_inst -> src [ 0 ] . imm . f ; progress = true ; } break ; default : break ; } } if ( scan_inst -> dst . file == GRF && scan_inst -> dst . reg == inst -> dst . reg && ( scan_inst -> dst . reg_offset == inst -> dst . reg_offset || scan_inst -> is_tex ( ) ) ) { break ; } } } if ( progress ) this -> live_intervals_valid = false ; return progress ; }
Attempts to move immediate constants into the immediate
 constant slot of following instructions.
Attempts to move immediate constants into the immediate constant slot of following instructions .
/* Don't bother with cases where we should have had the
       * operation on the constant folded in GLSL already.
       */ /* Found a move of a constant to a GRF.  Find anything else using the GRF
       * before it's written, and replace it with the constant if we can.
       */ /* Don't bother with cases where we should have had the
	     * operation on the constant folded in GLSL already.
	     */ /* Fit this constant in by commuting the operands.
		   * Exception: we can't do this for 32-bit integer MUL
		   * because it's asymmetric.
		   */ /* Fit this constant in by swapping the operands and
		      * flipping the test
		      */ /* If this was predicated, flipping operands means
		   * we also need to flip the predicate.
		   */ /* The hardware doesn't do math on immediate values
		* (because why are you doing that, seriously?), but
		* the correct answer is to just constant fold it
		* anyway.
		*/