> From: Denis Chertykov <[EMAIL PROTECTED]>
>> Paul Schlie <[EMAIL PROTECTED]> writes:
>>> From: Denis Chertykov <[EMAIL PROTECTED]>
>> - although I agree that there's likely a cleaner more consistent way
>> to accurately describe and track condition-code side-effects of AVR's
>> ISA, it seems that this approach actually inhibits GCC helping to
>> optimize the code, as too much information is being hidden from it?
>
> I don't want to hide useful information. I want to ignore unusable.
>
> For example: even i386 port (probably better port) isn't
> "accurately describe and track condition-code side-effects"
>
> FLAGS_REG just clobbered. It's not a true.
> As I understand '(clobber (reg:CC FLAGS_REG))' needed only for
> scheduling.
> AVR havn't scheduling and I want to omit such clobbers, but I have
> added special insns for optimization.
> For example: ...
- yes but only for QI mode operations, but not otherwise; which prohibits
safe instruction re-ordering/scheduling, which I understand you rely on
not occurring, then use peephole optimization in an effort to identify
opportunities to eliminate otherwise redundant compare operations.
- alternatively, why not accurately expose the instruction's FLAGS_REG
side-effects, and enable GCC to re-order/schedule (maintaining the fully
exposed data-flow-control-graph's sequential dependencies) to attempt
to find more optimal sequences which may reduce the cost of an arbitrary
instruction sequence within a basic block (including the potential
elimination of explicit comparison operations, when an instruction which
generates the necessary FLAGS_REG side-effect may be safely re-ordered
prior to it's requirement with no instructions with interfering
side-effects in between)?
>> ...
>> As it would seem that the initial hiding of this critical information
>> only inhibits GCC from being able to optimally (not to mention safely)
>> schedule basic block instruction sequences in an effort to eliminate
>> the necessity of otherwise relatively expensive multi-byte comparisons
>> to begin with. (Which would seem to be more optimal than relying on
>> no scheduling, and likely only catching some of the potential
>> opportunities to eliminate expensive compares after the fact?)
>
> Ohhh. I'm probably understand you. Are you mean that better way for
> splitting comparisions is cmpHI,
> cbranch -> cmpQI1_and_set_CC, cbranch1, cmpQI2_and_use_CC, cbranch2 ?
> In this case cmpQI1,cbranch1 may be in one basic block
> and cmpQI2, cbranch2 in another. You right it's impossible without
> "accurately describe and track condition-code side-effects".
> If you (or any other) want to support such splitting then clobbers
> must be added to insns.
- basically yes, but it would seem that it's necessary to accurately
describe instructions side effects to do so optimally; as clobbering
FLAGS_REG only prevents unsafe re-reordering, it doesn't enable optimal
reordering (which would seem to be one of the few optimizations that GCC
could do for avr, or other lightly pipelined in-order issue/completion
targets, and would be unfortunate to prohibit)?
> I think that better to support
> cmpHI, cbranch -> cmpQI1_set_CC, cmpQI2_use_CC, cbranch. because
> AVR is a microcontroller and code size more important than code speed.
- I fully agree that code-size tends to be most important, which is why I
believe it's important to enable instruction scheduling/re-ordering
optimizations that are capable of eliminating potentially unnecessary
explicit comparison operations for wider than byte-sized operand results
against 0, if the instructions within a basic block can be safely
rescheduled to eliminate them.
Which would seem to require that both instruction FLAGS_REG side-effects
be fully exposed, and correspondingly that conditional branches expose
their dependency on them (and all are visible during DFCG scheduling).
- possibly something like: ?
(define_insn "*addhi3"
[(set (match_operand:HI 0 ...)
(plus:HI (match_operand:HI 1 ...)
(match_operand:HI 2 ...)))
(set (reg ZCMP_FLAGS)
(compare:HI (plus:HI (match_dup 1) (match_dup 2))) (const_int 0))
(set (reg CARRY_FLAGS)
(compare:HI (plus:HI (match_dup 1) (match_dup 2))) (const_int 0))]
""
"@ add %A0,%A2\;adc %B0,%B2
..."
[(set_attr "length" "2, ...")])
(define_insn "*andhi3"
[(set (match_operand:HI 0 ...)
(and:HI (match_operand:HI 1 ...)
(match_operand:HI 2 ...)))
(set (reg ZCMP_FLAGS)
(compare:HI (and:HI (match_dup 1) (match_dup 2))) (const_int 0))]
""
"@ and %A0,%A2\;and %B0,%B2
..."
[(set_attr "length" "2, ...")])
(define_insn "*comparehi"
[(set (reg ZCMP_FLAGS)
(compare:HI (plus:HI (match_dup 1) (match_dup 2))) (const_int 0))
(set (reg CARRY_FLAGS)
(compare:HI (plus:HI (match_dup 1) (match_dup 2))) (const_int 0))]
""
"@ cp %A1,%A2\;cpc %B1,%B2
..."
[(set_attr "length" "2, ...")])
(define_insn "branch"
[(set (pc)
(if_then_else (condition (reg ZCMP_FLAGS) (match_operand 1 ...))
(label_ref (match_operand 0 ...))
(pc)))]
"* return ret_cond_branch (operands);
..."
[(set_attr "type" "branch")])
Or something like that, such that all side-effects and dependencies
are fully exposed, which in theory should allow GCC to reorder for
example operations which only need CARRY_FLAGS past operations which
only set ZCMP_FLAGS for example, and/or recognize that a literal
compare operation could be eliminated if an operation generating
the same side-effect could be scheduled safely prior to the branch?
(which in theory should also allow a safe way to split multi-byte
operations apart by defining subsequent sequential operations as
being dependant on the previous operations CARRY_FLAGS side-effect
for example it would seem?)