For once, the documentation seems to be most accurate; more accurate than random comments in the code, of which some contradicts other code:
@item REG_LABEL This insn uses @var{op}, a @code{code_label} or a @code{note} of type @code{NOTE_INSN_DELETED_LABEL}, but is not a @code{jump_insn}, or it is a @code{jump_insn} that required the label to be held in a register. The presence of this note allows jump optimization to be aware that @var{op} is, in fact, being used, and flow optimization to build an accurate flow graph. However, for a cbranchsi4, the pattern can look like this: (define_insn_and_split "cbranch<mode>4" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(match_operand:BWDQ 1 "nonimmediate_operand" "<cmpop0constraints>") (match_operand:BWDQ 2 "general_operand" "<cmpop1constraints>")]) (label_ref (match_operand 3 "" "")) (pc)))] ...) Causing for example in (from gfortran.dg/g77/pr9258.f and with local CRIS-cc0-removal-changes): (jump_insn 54 53 56 6 (set (pc) (if_then_else (eq (reg/v/f:SI 25 [ m.1 ]) (label_ref:SI 0)) (label_ref 33) (pc))) 1 {cbranchsi4} (nil) (expr_list:REG_BR_PROB (const_int 1900 [0x76c]) (nil))) Note *two* labels. One is a jump target, the other is an operand. So, a JUMP_P can have multiple label references *some of which are not jump targets*. This causes ambiguity with the documented (and mostly real) use of REG_LABEL, and of course the code assumes there are no non-jump-target REG_LABELs in JUMP_P:s. I could of course "fix" this by disallowing REG_LABELs in operand 2 in the pattern above, but that'd be like cheating, giving in to a lame restriction in GCC and proving a cbranchM4-representation to be lacking by definition with better expressibility with cc0. Can't do that. I propose (and will try to) solve this by splitting REG_LABELs into two types, REG_LABEL_TARGET and REG_LABEL_OPERAND: Only JUMP_P:s will have REG_LABEL_TARGET notes; those notes marks its jump targets (perhaps can be only one). As a special case, the JUMP_LABEL field in a JUMP_P is a short-cut and will be handled as a first REG_LABEL_TARGET note. It is invalid to have both JUMP_TARGET being NULL and REG_LABEL_TARGET notes in a (JUMP_P) insn. A tablejump/casesi will have its JUMP_LABEL set to the corresponding ADDR_VEC (there can be another label-ref-target there, in case you think there'll only ever be the JUMP_TARGET field and no REG_LABEL_TARGET notes). A JUMP_P using a register for ordinary branches (like on sh64) will have its JUMP_LABEL pointing to the label loaded in that register (if it can be identified; it seems it usually can). To make this work, REG_LABEL_TARGET notes (and the JUMP_LABEL) are sticky; not removed before each jump pass if the JUMP_P no longer refer to the label in its body. Any insn can have REG_LABEL_OPERAND, which marks non-target use, e.g. &&label operands and branch-target register loads in non-jumps and the non-jump cbranchM4 (label-ref:SI 0) operand above. (IIRC the 0 is actually due to the failure I saw.) REG_LABEL_OPERANDs are regenerated for each jump pass. A JUMP_P can have REG_LABEL_OPERANDs only for stuff in a if_then_else condition; everything else is considered a jump-target. Or at least that's the definition I currently think (and hope) will work. Thoughts? brgds, H-P