On 10/21/2011 10:15 AM, Paulo J. Matos wrote: > So I have implemented the nadd and addc as: > > (define_insn "negqi2" > [(set (match_operand:QI 0 "register_operand" "=c") > (neg:QI (match_operand:QI 1 "register_operand" "0"))) > (set (reg:CC_C RCC) (eq (match_dup 1) (const_int 0))) > (clobber (reg:CC RCC))] > "" > { > operands[2] = const0_rtx; > return "nadd\\t%0,%2"; > })
There are lots of parts of the compiler that don't optimize well when an insn has more than one output. For the normal insn, just clobber the flags; don't include a second SET. > (define_insn "addc_internal" > [(set (match_operand:QI 0 "nonimmediate_operand" "=c") > (plus:QI > (plus:QI > (ltu:QI (reg:CC RCC) (const_int 0)) > (match_operand:QI 1 "nonimmediate_operand" "%0")) > (match_operand:QI 2 "general_operand" "cwmi"))) > (use (reg:CC_C RCC)) > (clobber (reg:CC RCC))] > "" > "addc\\t%0,%f2") You don't need the USE, because you mention RCC inside the LTU. > (define_insn "*addc_internal_flags" Likewise. > A couple of things to note: > * negqi (which generates the nadd x, y equivalent to -x + y) has a > set RCC in C mode followed by a clobber. The set in C mode doesn't > show up in the _flags variant which is used only for the compare-elim > since it doesn't really matter and it already contains a set RCC > anyway. Surely the NADD insn is simply a normal subtract (with reversed operands). You shouldn't *need* to implement NEG at all, as the middle-end will let NEG expand via MINUS. Just so you know... > * is this enough for GCC to understand that anything that clobbers > RCC or specifically touches the RCC in C mode shouldn't go in between > these two instructions? Yes. > Also, do I need to specify in the RCC > clobber, exactly which flags are clobbered, or should I use a set > instead? No, the compiler will assume the entire register is changed, no matter what CCmode you place there. > * in the case of using sets, it was easy in the case of the negqi of > findind the source of the set RCC, however, it's not so easy for the > general case. Is unspec the answer? Is unspec the way of saying: > "hey, I am setting RCC in Cmode here, you shouldn't bother about the > value that I put there. Just know that RCC is going to be set." You can often just use (compare x y) as well, assuming that the flags are set "appropriately". GCC doesn't assume anything about the contents of the intermediate CCmode object, but does assume that (lt (compare x y) (const_int 0)) produces the same value as (lt x y) But, yes, if there's no obvious comparison, then unspec is ok. r~