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~