2007/9/25, Jim Wilson <[EMAIL PROTECTED]>:
> ÎâêØ 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~

Reply via email to