Hello,

I am trying to size-optimise one of our instructions. That's addhi3. HImode is 32 bits and QImode is 16bits, which is what our processor instructions work with.

So generally an addhi3 looks like:
(define_insn "addhi3"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=c")
         (plus:HI (match_operand:HI 1 "general_operand" "%0")
                  (match_operand:HI 2 "general_operand" "cwmi")))]
   ""
   "add  %b0,%b2\;addc %t0,%t2")

Where the format specifiers b and t choose the top and bottom 16 bits of each operand. add is a 16bit addition operand and addc takes carry flag into consideration. Now, there are a lot of simple manipulations that can be made if I release GCC from always outputting these two instructions together. However, the problem is expanding an addhi3 into two QImode add insn (which look the same), one of each outputs addc instead of add.

I thought about using attributes but I am very unsure that it works or even if it is the way to go.

The problem is, if addhi3 expands into two insn:
(define_insn "addqi3"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=c")
         (plus:HI (match_operand:HI 1 "general_operand" "%0")
                  (match_operand:HI 2 "general_operand" "cwmi")))]
   "get_attr_CARRY(insn) == 0"
   "add  %b0,%b2")

(define_insn "addqi3_carry"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=c")
         (plus:HI (match_operand:HI 1 "general_operand" "%0")
                  (match_operand:HI 2 "general_operand" "cwmi")))]
   "get_attr_CARRY(insn) == 1"
   "addc %t0,%t2")

_One_ of the problems with this is that if GCC sees that op2 is 0, it will remove the insn because it will see: R0 = R0 + 0. However, it can't do this in this specific case because the plus is actually also adding the carry flag.

Any suggestions on how to deal with this situation?

Cheers,
--

PMatos

Reply via email to