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


Reply via email to