Alexandre Oliva <[EMAIL PROTECTED]> writes: > On Mar 23, 2005, Ian Lance Taylor <ian@airs.com> wrote: > > > Of course, correctly modeling the effect on the condition codes > > really means putting the information in the RTL so that it is > > exposed to the RTL optimizers. > > True, but we want to avoid that because of the loss of optimization > opportunities. Besides, there's really no way in GCC (AFAIK) to have > a pattern such that, if reload selects one alternative, you get a > register set in one way; if you select another, you get it set > differently, or even not set at all, and this is what we'd need to be > able to model the correct effect of instructions as common as mov.
There is no way to write such a pattern before reload, but that's OK because there is nothing that the optimizers could do with it anyhow. The pattern would mean something like "if unpredictable option 1 happens, the condition codes are set this way; if unpredictable option 2 happens, they are set this way." You can correctly represent the condition code setting after reload easily enough, by splitting the instruction to show the real effect on the condition code. > >> > 2b) Convert conditional branch instructions from separate > >> > cmpMODE/bCOND instructions to a single conditional branch > >> > instruction, either by saving condition codes in cmpMODE or > >> > tstMODE or by using cbranch. > > >> The problem here IIRC is a combinatorial explosion on the number of > >> alternatives for the now-merged compare&branch instructions. Have a > >> look, for example, at the cc0-setting patterns on h8300.md, including > >> the zero-extend and zero-extract ones. There are many of them, with > >> operands that aren't easy to get into a single cbranch instruction. > > > I'm not proposing any sort of combinatorial explosion. > > Yes, you are. Converting cmpMODE/bCOND to cbranch will involve some > combinatorial explosion in cbranch. We can use computers to handle > this explosion for us, instead of forcing port maintainers to deal > with all the complexity. We are clearly somehow talking past each other. There is a pattern named cmpMODE. There is a pattern named bCOND. Currently gcc emits one and then the other. I am suggesting that they be combined into a single pattern named cbranch. The fact that there are many patterns in h8300.md which set cc0 is not relevant. The only cc0 setter which matters is cmpMODE. What you are talking about is something different. You are talking about combining every cc0 setter with every cc0 user into a single insn. I agree that that is impractical. The question is how much optimization we lose if we don't do the full combinatorial explosion. I'm assuming that we will get most back in the NOTICE_UPDATE_CC pass. But perhaps I am being to optimistic. I'll note that h8300.md has 17 insn patterns which set cc0, and that number could be cut down by several by using mode macros and more flexible predicates. And in this scheme the tstMODE operations would disappear--only the cmpMODE ones are useful. And there are 4 conditional branch insn patterns, which could be reduced to 3 by using code macros. So while doing the full crossbar would be a combinatorial explosion, it would not be an impossible one. > The idea is to get the programs that process .md files such that, when > it reads something like: > > ;; cc0-setter > (define_insn "cmpsi" > [(set (cc0) > (compare (match_operand:SI 0 "register_operand" "!*d*a*x,dax") > (match_operand:SI 1 "nonmemory_operand" "*0,daxi")))] > "<cond1>" > "@ > btst 0,d0 > cmp %1,%0" > [(set_attr "cc" "compare,compare")]) > > ;; cc0-user > (define_insn "condbranch" > [(set (pc) > (if_then_else (match_operator 1 "comparison_operator" > [(cc0) (const_int 0)]) > (label_ref (match_operand 0 "" "")) > (pc)))] > "<cond2>" > "* > { > if (cc_status.mdep.fpCC) > return \"fb%b1 %0\"; > if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 > && (GET_CODE (operands[1]) == GT > || GET_CODE (operands[1]) == GE > || GET_CODE (operands[1]) == LE > || GET_CODE (operands[1]) == LT)) > return 0; > return \"b%b1 %0\"; > }" > [(set_attr "cc" "none")]) > > > it interprets it as something like: > > (define_insn "cmpsi" > [(set (cc0) > (compare (match_operand:SI 0 "register_operand" "!*d*a*x,dax") > (match_operand:SI 1 "nonmemory_operand" "*0,daxi")))] > "(! before_cc0_collapsing || reload_completed) && <cond1>" > "@ > btst 0,d0 > cmp %1,%0" > [(set_attr "cc" "compare,compare")]) > > (define_insn "condbranch" > [(set (pc) > (if_then_else (match_operator 1 "comparison_operator" > [(cc0) (const_int 0)]) > (label_ref (match_operand 0 "" "")) > (pc)))] > "(before_cc0_collapsing || reload_completed) && <cond2>" > "* > { > if (cc_status.mdep.fpCC) > return \"fb%b1 %0\"; > if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 > && (GET_CODE (operands[1]) == GT > || GET_CODE (operands[1]) == GE > || GET_CODE (operands[1]) == LE > || GET_CODE (operands[1]) == LT)) > return 0; > return \"b%b1 %0\"; > }" > [(set_attr "cc" "none")]) > > (define_insn_and_split "cc0_condbranch_cmpsi" > [(sequence [ > (set (cc0) > (compare (match_operand:SI 0 "register_operand" "!*d*a*x,dax") > (match_operand:SI 1 "nonmemory_operand" "*0,daxi"))) > (set (pc) > (if_then_else (match_operator 3 "comparison_operator" > [(cc0) (const_int 0)]) > (label_ref (match_operand 2 "" "")) > (pc)))] > )] > "<cond1>(operands) && <cond2>(operands+2)" > "#" > "reload_completed" > [(set (cc0) > (compare (match_dup 0) > (match_dup 1) > (set (pc) > (if_then_else (match_op_dup 3 "comparison_operator" > [(cc0) (const_int 0)]) > (label_ref (match_dup 2)) > (pc)))]) > > > The code implementing cond1 and cond2 would have to be defined in > functions, such that they could take shifted operands as arguments. > We'd create such a combined pattern for every pair of cc0-setter and > cc0-user. OK, I see what you are getting at. Basically you are suggesting that the .md generators do the combinatorial explosion themselves. > We'd add a pass right after rtl generation to go through the > instruction stream looking for cc0 setters and users, and merging them > into a single combined pattern, perhaps reusing the peephole > mechanisms, generating peepholes that reverse the combined > insn_and_split above. > > I don't think any ports would require sequences of more than two > instructions to be combined into a single pattern (e.g., have > instructions that meaningfully both use and set cc0). Supporting this > would be more of a pain, and would require an alternate, more complex > approach than pre-generating the combined patterns. > > I realize the sequence construct is already taken for delayed > branches, but that's only in the outermost insn pattern. We could > overload the meaning, or just enclose the (sequence) in some other > construct (a dummy parallel?), give it a different mode (a CC mode?) > or something else to indicate that this is a combined pattern. Or > create a different rtl code for cc0 sequences of instructions. The > syntax is not all that important at this point. I don't understand why you are suggesting a sequence at all. Why not this: (define_insn_and_split "cc0_condbranch_cmpsi" [(set (pc) (if_then_else (match_operator 3 "comparison_operator" (match_operand:SI 0 "register_operand" "!*d*a*x,dax") (match_operand:SI 1 "nonmemory_operand" "*0,daxi")))) (label_ref (match_operand 2 "" "")) (pc)))] )] > As for the cc attribute, we'd start from: > > (define_insn "*movsi_impl" > [(set (match_operand:SI 0 "nonimmediate_operand" > > "=dx,ax,dx,a,dxm,dxm,axm,axm,dx,dx,ax,ax,axR,!*y,*f,*f,dxaQ") > (match_operand:SI 1 "general_operand" > > "0,0,I,I,dx,ax,dx,ax,dixm,aixm,dixm,aixm,!*y,axR,0,dxaQi*f,*f"))] > "register_operand (operands[0], SImode) > || register_operand (operands[1], SImode)" > "* > { > switch (which_alternative) > { > [...] > } > }" > [(set_attr "cc" > "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none,none_0hit,none_0hit")]) > > and generate patterns such as: > > (define_insn_and_split "*movsi_impl" > [(set (match_operand:SI 0 "nonimmediate_operand" "...") > (match_operand:SI 1 "general_operand" "..."))] > "! cc0_expanding_completed > && (register_operand (operands[0], SImode) > || register_operand (operands[1], SImode))" > "#" > "cc0_expanding_in_progress" > [(set (match_dup 0) (match_dup 1)) > (match_dup 2)] > " > { > operands[2] = gen_cc0_set_for (insn); > }" > [(set_attr "cc" > "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none,none_0hit,none_0hit")]) > > > (define_insn "*movsi_impl_cc0_set" > [(set (match_operand:SI 0 "nonimmediate_operand" "...") > (match_operand:SI 1 "general_operand" "...")) > (match_operand 2 "cc0_set_operand" "")] > "(cc0_expanding_in_progress || cc0_expanding_completed)" > "* > { > [...] > }" > [(set_attr "cc" > "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none,none_0hit,none_0hit")]) What is the advantage of doing this over the simpler clobbercc attribute which I suggested? How does it help to correctly represent the setting of cc0 in RTL after reload? We aren't going to run the combine pass then anyhow. Does this give any advantage over my suggestion of a special pass which uses NOTICE_UPDATE_CC? > >> Why not use the relatively-common-in-cc0-ports > >> cc attribute for this purpose? > > > That would be fine. It would be trivial to define clobbercc in terms > > of cc for ports which have it. > > See the problem of alternatives above. Would it not be a problem in > your proposal? Before reload, you have to assume that all alternatives clobber the CC--there is no other coherent position that you can take. After reload, you split into those alternatives which clobber CC and those that don't. Looking at your suggestion makes me realize that my suggestion is too complicated. It's not necessary to generate the combinatorial explosion at all. We can always keep cc0 setters and cc0 users in separate instructions. The key is to keep them from getting disconnected, and the key to that is to indicate which instructions clobber the condition codes (i.e., most of them). I'll send a new description in a separate message. Ian