------- Comment #4 from rask at sygehus dot dk  2007-06-06 10:33 -------
   I see no reason to mark this enhancement request as invalid.

   As to generating reasonable x86 code for overflow checks written in C, it
isn't completely hopeless. I did an experiment with my 16-bit x86 port. First,
I wrote the overflow check differently (and of course changed the data size to
16-bits):

#include <limits.h>

void abort (void);

unsigned short int foo (unsigned short int a, unsigned short int b)
{
  unsigned short int sum;

  sum = a + b;
  if ((unsigned long int) a + (unsigned long int) b > USHRT_MAX)
    abort ();
  return sum;
}

   Second, I added new instructions, of which combine was asking for the first
one:

(define_insn_and_split "*addsi3_cconly_highpart_ccz_nc"
  [(set (reg:CCZ_NC CC_REG)
        (compare:CCZ_NC
            (subreg:HI (plus:SI (match_operand:SI 1 "general_operand" "0")
                                (match_operand:SI 2 "general_operand" "g")) 2)
            (const_int 0)))
   (clobber (match_scratch:HI 0 "=r"))]
  "ia16_arith_operands_p (PLUS, operands)"
  "#"
  ""
  [(parallel
  [(set (match_dup 0) (plus:HI (match_dup 3) (match_dup 4)))
   (set (reg:CCZ_NC CC_REG)
        (compare:CCZ_NC (subreg:HI (plus:SI (zero_extend:SI (match_dup 3))
                                            (zero_extend:SI (match_dup 4))) 2)
                        (const_int 0)))]
  )]
{
  operands[3] = simplify_gen_subreg (HImode, operands[1], SImode, 0);
  operands[4] = simplify_gen_subreg (HImode, operands[2], SImode, 0);
})

(define_insn "*addhi3_cc_carry_ccz_nc"
  [(set (match_operand:HI 0 "nonimmediate_operand" "=qm,r,m")
        (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,0")
                 (match_operand:HI 2 "general_operand" "Uo,g,ri")))
   (set (reg:CCZ_NC CC_REG)
        (compare:CCZ_NC
            (subreg:HI (plus:SI (zero_extend:SI (match_dup 1))
                                (zero_extend:SI (match_dup 2))) 2)
            (const_int 0)))]
  "ia16_arith_operands_p (PLUS, operands)"
  "@
   addb\t%H2,\t%H0
   addw\t%2,\t%0
   addw\t%2,\t%0"
)

(define_insn "*addhi3_cconly_carry_ccz_nc"
  [(set (match_scratch:HI 0 "=qm,r,m")
        (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,0")
                 (match_operand:HI 2 "general_operand" "Uo,g,ri")))
   (set (reg:CCZ_NC CC_REG)
        (compare:CCZ_NC
            (subreg:HI (plus:SI (zero_extend:SI (match_dup 1))
                                (zero_extend:SI (match_dup 2))) 2)
            (const_int 0)))]
  "ia16_arith_operands_p (PLUS, operands)"
  "@
   addb\t%H2,\t%H0
   addw\t%2,\t%0
   addw\t%2,\t%0"
)

(define_insn "*beq_ccz_nc"
        [(set (pc)
              (if_then_else (eq (reg:CCZ_NC CC_REG)
                                (const_int 0))
                            (label_ref (match_operand 0))
                            (pc)))]
        ""
        "jnc\t%l0"
)

   Third, I created CCZ_NCmode and modified my SELECT_CC_MODE callback to use
it for the comparison in "*addsi3_cconly_highpart_ccz_nc". Result:

foo:
        pushw   %cx             ;# 69   *pushhi1_nonimm
        pushw   %si             ;# 70   *pushhi1_nonimm
        pushw   %di             ;# 71   *pushhi1_nonimm
        pushw   %bp             ;# 72   *pushhi1_nonimm
        movw    %sp,    %bp     ;# 67   *movhi/1
        movw    10(%bp),%di     ;# 2    *movhi/1
        movw    %sp,    %si     ;# 68   *movhi/1
        movw    12(%si),%bp     ;# 3    *movhi/1
        movw    %bp,    %ax     ;# 7    *movhi/1
        addw    %di,    %ax     ;# 63   *addhi3_cc_carry_ccz_nc/2
        jnc     .L7             ;# 15   *beq_ccz_nc
        call    abort           ;# 25   *call
.L7:
        popw    %bp             ;# 75   *pophi1
        popw    %di             ;# 76   *pophi1
        popw    %si             ;# 77   *pophi1
        popw    %cx             ;# 78   *pophi1
        ret                     ;# 79   *return

   I see no reason the i386 back end can't be improved in a similiar fashion.

   The original example is a lot more difficult because it uses two
comparisons. The middle end would have to recognize that the two comparisons
test the same thing.


-- 

rask at sygehus dot dk changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |rask at sygehus dot dk


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30315

Reply via email to