This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: support single predicate set instructions in GCC-4.1.1


2007/9/25, Jim Wilson <wilson@specifix.com>:
> ÎâêØ wrote:
> > (define_insn "*shift_predicate_cmp"
> >   [(set (const_int 0)
> >     (and:BI (and:BI (match_operand:BI 1 "register_operand" "c")
> >           (and:BI (match_operand:DI 2 "gr_reg_or_8bit_adjusted_operand" "rL")
> >                      (match_operand:DI 3 "gr_register_operand" "r")))
> >       (match_operand:BI 0 "register_operand" "c")))]
> >   ""
> >   "(%0) cmp.ne %1, p0 = %2, %3"
> >   [(set_attr "itanium_class" "icmp")])
> > it warns "WAW" and there should be stop ";;" between these two
> > instructions.
>
> It is the assembler that is giving the warning.  The assembler knows
> that the %1 operand is modified by the instruction, but the compiler
> does not, because the %1 operand is not a SET_DEST operand.  Your
> SET_DEST is (const_int 0) which is useless info and incorrect.  You need
> to make sure that the RTL is an accurate description of what the
> instruction does.
>
> Besides the problem with the missing SET_DEST, there is also the problem
> that you are using AND operands for a compare, which won't work.  AND
> and NE are not interchangeable operations.  Consider what happens if you
> compare 0x1 with 0x1.  cmp.ne returns false.  However, AND returns 0x1,
> which when truncated from DImode to BImode is still 0x1, i.e. true.  So
> the RTL does not perform the same operation as the instruction you
> emitted.  This could confuse the optimizer.
>
> GCC internals assume that predicate registers are always allocated in
> pairs, and that the second one is always the inverse of the first one.
> Defining a special pattern that only modifies one predicate register
> probably isn't gaining you much.  If you are doing this before register
> allocation, then you are still using 2 predicate registers, as the
> register allocator will always give you 2 even if you only use one.
> Worst case, if this pattern is exposed to the optimizer, then the
> optimizer may make changes that break your assumptions.  It might
> simplify a following instruction by using the second predicate reg for
> instance, which then fails at run-time because you didn't actually set
> the second predicate reg.  If you are only using this in sequences that
> the optimizer can't rewrite, then you should be OK.
> --
> Jim Wilson, GNU Tools Support, http://www.specifix.com
>

Thanks so much for your helpful hints. I think I need to write more
details about why I need this kind of instruction. But before that,
there is another problem on the liveness calculation (this problem
occurs when I use my new GCC to compile some source with no
optimization flag).

Roughly speaking, my work is to instrument sensitive instructions to
do information flow tracking. I did this work after register
allocation and just before the second scheduling phase (As I need to
intercept all memory access, so I choose to do this work after
register allocation). Instead of reserving certain number of registers
in backend to do instrumentation, I choose to allocate registers for
it. As the register allocation is done, I need compute liveness
information manually for each sensitive insn to get a set of registers
that I can use without any save or restore. To do this, I borrow code
from the function
	propagte_block
which is defined in flow.c, more specifically, the code is:
	    struct propagate_block_info *pbi;
	
	    int changed, flags;
	  rtx insn, prev;
	
	  bitmap insn_live_in, insn_live_out;
	  bitmap bb_live_in, bb_live_out;
	  basic_block cur_bb;
	
	
	     flags = PROP_DEATH_NOTES;
	  flags &= ~(PROP_SCAN_DEAD_CODE | PROP_SCAN_DEAD_STORES
			 | PROP_KILL_DEAD_CODE);
	
	  insn_live_in = BITMAP_ALLOC(NULL);
	  insn_live_out = BITMAP_ALLOC(NULL);
	
	  FOR_EACH_BB (cur_bb)
	    {
	      bb_live_in = cur_bb->il.rtl->global_live_at_start;
	      bb_live_out = cur_bb->il.rtl->global_live_at_end;
	
	      bitmap_copy (insn_live_out, bb_live_out);
	      bitmap_copy (insn_live_in, insn_live_out);
	
	      pbi = init_propagate_block_info (cur_bb, insn_live_in, NULL,
NULL, flags);
	
	      if (flags & PROP_REG_INFO)
	      {
	        unsigned i;
	        reg_set_iterator rsi;
	
	        /* Process the regs live at the end of the block.
	           Mark them as not local to any one basic block.  */
	        EXECUTE_IF_SET_IN_REG_SET (insn_live_in, 0, i, rsi)
	          REG_BASIC_BLOCK (i) = REG_BLOCK_GLOBAL;
	      }
	
	      changed = 0;
	
	      for (insn = BB_END (cur_bb); ; insn = prev)
	      {
	        bitmap_clear (shift_usable);
	
	        /* If this is a call to `setjmp' et al, warn if any
	           non-volatile datum is live.  */
	        if ((flags & PROP_REG_INFO)
	            && CALL_P (insn)
	            && find_reg_note (insn, REG_SETJMP, NULL))
	          IOR_REG_SET (regs_live_at_setjmp, pbi->reg_live);
	
	        prev = propagate_one_insn (pbi, insn);
	
	        /* find regs to instrument INSN */
	                  shift_insn_stats (stat, insn_live_in, insn_live_out);
	
		      /* instrument INSN */
	        if (shift_flag_instrument_func)
	        {
	          shift_instrument_insn (insn);
	        }
	
	        if (insn == BB_HEAD (cur_bb))
	          break;
	
	        bitmap_copy (insn_live_out, insn_live_in);
	      }
	
	      assert (bitmap_equal_p (insn_live_in, bb_live_in));
	
	      free_propagate_block_info (pbi);
	    }
	
	  BITMAP_FREE (insn_live_in);
	  BITMAP_FREE (insn_live_out);

In order to do some checking, I assert the insn_live_in I computed at
the entry of a basic block is the same to the bb_live_in.  However,
the new compiler works fine once I have optimization flag (-O1, -O2,
-O3, etc). The compiler fails this assertion if no optimization flag
exists. For example:
	gcc -c foo.c
throws the error:
	cc1: ../../shift-compiler/gcc/flow.c:5607: rest_of_handle_shift_anal:
Assertion `bitmap_equal_p (insn_live_in, bb_live_in)' failed.
As the code to compute liveness is somehow complex (for example,
propagate_one_insn), I don't understand why GCC fails the computation
of liveness if there is no optimization flag :-(.

Any hints ?

Thanks very much~


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]