This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
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~