> 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?)