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