re PR target/30315 (optimize unsigned-add overflow test on x86 to use cpu flags from addl)
PR target/30315 * config/i386/i386.h (CANONICALIZE_COMPARISON): New. * config/i386/i386.md (plusminus)(addsub)(SWI): New. (*<addsub><mode>3_cc_overflow): New. (*add<mode>3_cconly_overflow): New. (*sub<mode>3_cconly_overflow): New. (*<addsub>si3_zext_cc_overflow): New. * config/i386/predicates.md (fcmov_comparison_operator): Accept CCCmode for LTU, GTU, LEU and GEU. (ix86_comparison_operator): Likewise. (ix86_carry_flag_operator): Carry flag is set if LTU or GTU in CCCmode. * gcc/config/i386/i386.c (put_condition_code): Support CCCmode. (ix86_cc_mode): Use CCCmode when testing for overflow of PLUS or MINUS expressions. testsuite/ PR target/30315 * gcc.target/i386/pr30315.c: New. From-SVN: r127481
This commit is contained in:
parent
9a251aa118
commit
d39d658dbe
7 changed files with 244 additions and 11 deletions
|
@ -1,3 +1,20 @@
|
|||
2007-08-14 Rask Ingemann Lambertsen <rask@sygehus.dk>
|
||||
|
||||
PR target/30315
|
||||
* config/i386/i386.h (CANONICALIZE_COMPARISON): New.
|
||||
* config/i386/i386.md (plusminus)(addsub)(SWI): New.
|
||||
(*<addsub><mode>3_cc_overflow): New.
|
||||
(*add<mode>3_cconly_overflow): New.
|
||||
(*sub<mode>3_cconly_overflow): New.
|
||||
(*<addsub>si3_zext_cc_overflow): New.
|
||||
* config/i386/predicates.md (fcmov_comparison_operator): Accept
|
||||
CCCmode for LTU, GTU, LEU and GEU.
|
||||
(ix86_comparison_operator): Likewise.
|
||||
(ix86_carry_flag_operator): Carry flag is set if LTU or GTU in CCCmode.
|
||||
* gcc/config/i386/i386.c (put_condition_code): Support CCCmode.
|
||||
(ix86_cc_mode): Use CCCmode when testing for overflow of PLUS
|
||||
or MINUS expressions.
|
||||
|
||||
2007-08-14 Andrew Pinski <pinskia@gmail.com>
|
||||
|
||||
PR c/30428
|
||||
|
|
|
@ -8261,8 +8261,12 @@ put_condition_code (enum rtx_code code, enum machine_mode mode, int reverse,
|
|||
case GTU:
|
||||
/* ??? Use "nbe" instead of "a" for fcmov lossage on some assemblers.
|
||||
Those same assemblers have the same but opposite lossage on cmov. */
|
||||
gcc_assert (mode == CCmode);
|
||||
suffix = fp ? "nbe" : "a";
|
||||
if (mode == CCmode)
|
||||
suffix = fp ? "nbe" : "a";
|
||||
else if (mode == CCCmode)
|
||||
suffix = "b";
|
||||
else
|
||||
gcc_unreachable ();
|
||||
break;
|
||||
case LT:
|
||||
switch (mode)
|
||||
|
@ -8282,7 +8286,7 @@ put_condition_code (enum rtx_code code, enum machine_mode mode, int reverse,
|
|||
}
|
||||
break;
|
||||
case LTU:
|
||||
gcc_assert (mode == CCmode);
|
||||
gcc_assert (mode == CCmode || mode == CCCmode);
|
||||
suffix = "b";
|
||||
break;
|
||||
case GE:
|
||||
|
@ -8304,7 +8308,7 @@ put_condition_code (enum rtx_code code, enum machine_mode mode, int reverse,
|
|||
break;
|
||||
case GEU:
|
||||
/* ??? As above. */
|
||||
gcc_assert (mode == CCmode);
|
||||
gcc_assert (mode == CCmode || mode == CCCmode);
|
||||
suffix = fp ? "nb" : "ae";
|
||||
break;
|
||||
case LE:
|
||||
|
@ -8312,8 +8316,13 @@ put_condition_code (enum rtx_code code, enum machine_mode mode, int reverse,
|
|||
suffix = "le";
|
||||
break;
|
||||
case LEU:
|
||||
gcc_assert (mode == CCmode);
|
||||
suffix = "be";
|
||||
/* ??? As above. */
|
||||
if (mode == CCmode)
|
||||
suffix = "be";
|
||||
else if (mode == CCCmode)
|
||||
suffix = fp ? "nb" : "ae";
|
||||
else
|
||||
gcc_unreachable ();
|
||||
break;
|
||||
case UNORDERED:
|
||||
suffix = fp ? "u" : "p";
|
||||
|
@ -11040,10 +11049,21 @@ ix86_cc_mode (enum rtx_code code, rtx op0, rtx op1)
|
|||
return CCZmode;
|
||||
/* Codes needing carry flag. */
|
||||
case GEU: /* CF=0 */
|
||||
case GTU: /* CF=0 & ZF=0 */
|
||||
case LTU: /* CF=1 */
|
||||
/* Detect overflow checks. They need just the carry flag. */
|
||||
if (GET_CODE (op0) == PLUS
|
||||
&& rtx_equal_p (op1, XEXP (op0, 0)))
|
||||
return CCCmode;
|
||||
else
|
||||
return CCmode;
|
||||
case GTU: /* CF=0 & ZF=0 */
|
||||
case LEU: /* CF=1 | ZF=1 */
|
||||
return CCmode;
|
||||
/* Detect overflow checks. They need just the carry flag. */
|
||||
if (GET_CODE (op0) == MINUS
|
||||
&& rtx_equal_p (op1, XEXP (op0, 0)))
|
||||
return CCCmode;
|
||||
else
|
||||
return CCmode;
|
||||
/* Codes possibly doable only with sign flag when
|
||||
comparing against zero. */
|
||||
case GE: /* SF=OF or SF=0 */
|
||||
|
|
|
@ -2065,6 +2065,16 @@ do { \
|
|||
|
||||
#define SELECT_CC_MODE(OP, X, Y) ix86_cc_mode ((OP), (X), (Y))
|
||||
|
||||
/* Canonicalize overflow checks to save on the insn patterns. We change
|
||||
"a + b < b" into "a + b < a" and "a + b >= b" into "a + b >= a". */
|
||||
#define CANONICALIZE_COMPARISON(code, op0, op1) \
|
||||
{ \
|
||||
if ((code == LTU || code == GEU) \
|
||||
&& GET_CODE (op0) == PLUS \
|
||||
&& rtx_equal_p (op1, XEXP (op0, 1))) \
|
||||
op1 = XEXP (op0, 0); \
|
||||
}
|
||||
|
||||
/* Return nonzero if MODE implies a floating point inequality can be
|
||||
reversed. */
|
||||
|
||||
|
|
|
@ -488,6 +488,33 @@
|
|||
[(set_attr "length" "128")
|
||||
(set_attr "type" "multi")])
|
||||
|
||||
(define_code_macro plusminus [plus minus])
|
||||
|
||||
;; Base name for define_insn and insn mnemonic.
|
||||
(define_code_attr addsub [(plus "add") (minus "sub")])
|
||||
|
||||
;; Mark commutative operators as such in constraints.
|
||||
(define_code_attr comm [(plus "%") (minus "")])
|
||||
|
||||
;; All single word integer modes.
|
||||
(define_mode_macro SWI [QI HI SI (DI "TARGET_64BIT")])
|
||||
|
||||
;; Instruction suffix for integer modes.
|
||||
(define_mode_attr imodesuffix [(QI "b") (HI "w") (SI "l") (DI "q")])
|
||||
|
||||
;; Register class for integer modes.
|
||||
(define_mode_attr r [(QI "q") (HI "r") (SI "r") (DI "r")])
|
||||
|
||||
;; Immediate operand constraint for integer modes.
|
||||
(define_mode_attr i [(QI "i") (HI "i") (SI "i") (DI "e")])
|
||||
|
||||
;; General operand predicate for integer modes.
|
||||
(define_mode_attr general_operand
|
||||
[(QI "general_operand")
|
||||
(HI "general_operand")
|
||||
(SI "general_operand")
|
||||
(DI "x86_64_general_operand")])
|
||||
|
||||
;; All x87 floating point modes
|
||||
(define_mode_macro X87MODEF [SF DF XF])
|
||||
|
||||
|
@ -4855,6 +4882,56 @@
|
|||
[(set_attr "type" "alu")
|
||||
(set_attr "mode" "DI")])
|
||||
|
||||
(define_insn "*<addsub><mode>3_cc_overflow"
|
||||
[(set (reg:CCC FLAGS_REG)
|
||||
(compare:CCC
|
||||
(plusminus:SWI
|
||||
(match_operand:SWI 1 "nonimmediate_operand" "<comm>0,0")
|
||||
(match_operand:SWI 2 "<general_operand>" "<r><i>,<r>m"))
|
||||
(match_dup 1)))
|
||||
(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
|
||||
(plusminus:SWI (match_dup 1) (match_dup 2)))]
|
||||
"ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
|
||||
"<addsub>{<imodesuffix>}\t{%2, %0|%0, %2}"
|
||||
[(set_attr "type" "alu")
|
||||
(set_attr "mode" "<MODE>")])
|
||||
|
||||
(define_insn "*add<mode>3_cconly_overflow"
|
||||
[(set (reg:CCC FLAGS_REG)
|
||||
(compare:CCC
|
||||
(plus:SWI (match_operand:SWI 1 "nonimmediate_operand" "%0")
|
||||
(match_operand:SWI 2 "<general_operand>" "<r><i>m"))
|
||||
(match_dup 1)))
|
||||
(clobber (match_scratch:SWI 0 "=<r>"))]
|
||||
"ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
|
||||
"add{<imodesuffix>}\t{%2, %0|%0, %2}"
|
||||
[(set_attr "type" "alu")
|
||||
(set_attr "mode" "<MODE>")])
|
||||
|
||||
(define_insn "*sub<mode>3_cconly_overflow"
|
||||
[(set (reg:CCC FLAGS_REG)
|
||||
(compare:CCC
|
||||
(minus:SWI (match_operand:SWI 0 "nonimmediate_operand" "<r>m,<r>")
|
||||
(match_operand:SWI 1 "<general_operand>" "<r><i>,<r>m"))
|
||||
(match_dup 0)))]
|
||||
""
|
||||
"cmp{<imodesuffix>}\t{%1, %0|%0, %1}"
|
||||
[(set_attr "type" "icmp")
|
||||
(set_attr "mode" "<MODE>")])
|
||||
|
||||
(define_insn "*<addsub>si3_zext_cc_overflow"
|
||||
[(set (reg:CCC FLAGS_REG)
|
||||
(compare:CCC
|
||||
(plusminus:SI (match_operand:SI 1 "nonimmediate_operand" "<comm>0")
|
||||
(match_operand:SI 2 "general_operand" "g"))
|
||||
(match_dup 1)))
|
||||
(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(zero_extend:DI (plusminus:SI (match_dup 1) (match_dup 2))))]
|
||||
"TARGET_64BIT && ix86_binary_operator_ok (<CODE>, SImode, operands)"
|
||||
"<addsub>{l}\t{%2, %k0|%k0, %2}"
|
||||
[(set_attr "type" "alu")
|
||||
(set_attr "mode" "SI")])
|
||||
|
||||
(define_insn "addqi3_carry"
|
||||
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
|
||||
(plus:QI (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "")
|
||||
|
|
|
@ -879,7 +879,8 @@
|
|||
switch (code)
|
||||
{
|
||||
case LTU: case GTU: case LEU: case GEU:
|
||||
if (inmode == CCmode || inmode == CCFPmode || inmode == CCFPUmode)
|
||||
if (inmode == CCmode || inmode == CCFPmode || inmode == CCFPUmode
|
||||
|| inmode == CCCmode)
|
||||
return 1;
|
||||
return 0;
|
||||
case ORDERED: case UNORDERED:
|
||||
|
@ -924,7 +925,11 @@
|
|||
|| inmode == CCGOCmode || inmode == CCNOmode)
|
||||
return 1;
|
||||
return 0;
|
||||
case LTU: case GTU: case LEU: case ORDERED: case UNORDERED: case GEU:
|
||||
case LTU: case GTU: case LEU: case GEU:
|
||||
if (inmode == CCmode || inmode == CCCmode)
|
||||
return 1;
|
||||
return 0;
|
||||
case ORDERED: case UNORDERED:
|
||||
if (inmode == CCmode)
|
||||
return 1;
|
||||
return 0;
|
||||
|
@ -939,7 +944,7 @@
|
|||
|
||||
;; Return 1 if OP is a valid comparison operator testing carry flag to be set.
|
||||
(define_predicate "ix86_carry_flag_operator"
|
||||
(match_code "ltu,lt,unlt,gt,ungt,le,unle,ge,unge,ltgt,uneq")
|
||||
(match_code "ltu,lt,unlt,gtu,gt,ungt,le,unle,ge,unge,ltgt,uneq")
|
||||
{
|
||||
enum machine_mode inmode = GET_MODE (XEXP (op, 0));
|
||||
enum rtx_code code = GET_CODE (op);
|
||||
|
@ -957,6 +962,8 @@
|
|||
return 0;
|
||||
code = ix86_fp_compare_code_to_integer (code);
|
||||
}
|
||||
else if (inmode == CCCmode)
|
||||
return code == LTU || code == GTU;
|
||||
else if (inmode != CCmode)
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2007-08-14 Rask Ingemann Lambertsen <rask@sygehus.dk>
|
||||
|
||||
PR target/30315
|
||||
* gcc.target/i386/pr30315.c: New.
|
||||
|
||||
2007-08-14 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
|
||||
|
||||
PR fortran/32594
|
||||
|
|
97
gcc/testsuite/gcc.target/i386/pr30315.c
Normal file
97
gcc/testsuite/gcc.target/i386/pr30315.c
Normal file
|
@ -0,0 +1,97 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-final { scan-assembler-times "cmp" 4 } } */
|
||||
|
||||
extern void abort (void);
|
||||
int c;
|
||||
|
||||
#define PLUSCC1(T, t, C) \
|
||||
T pluscc##t##C (T a, T b) \
|
||||
{ \
|
||||
T sum = a + b; \
|
||||
if (sum < C) \
|
||||
abort (); \
|
||||
return sum; \
|
||||
}
|
||||
#define PLUSCC(T, t) PLUSCC1(T, t, a) PLUSCC1(T, t, b)
|
||||
|
||||
#define INCCC1(T, t, C) \
|
||||
T inccc##t##C (T a, T b) \
|
||||
{ \
|
||||
T sum = a + b; \
|
||||
if (sum < C) \
|
||||
c ++; \
|
||||
return sum; \
|
||||
}
|
||||
#define INCCC(T, t) INCCC1(T, t, a) INCCC1(T, t, b)
|
||||
|
||||
#define PLUSCCONLY1(T, t, C) \
|
||||
void pluscconly##t##C (T a, T b) \
|
||||
{ \
|
||||
T sum = a + b; \
|
||||
if (sum < C) \
|
||||
abort (); \
|
||||
}
|
||||
#define PLUSCCONLY(T, t) PLUSCCONLY1(T, t, a) PLUSCCONLY1(T, t, b)
|
||||
|
||||
#define MINUSCC(T, t) \
|
||||
T minuscc##t (T a, T b) \
|
||||
{ \
|
||||
T difference = a - b; \
|
||||
if (difference > a) \
|
||||
abort (); \
|
||||
return difference; \
|
||||
}
|
||||
|
||||
#define DECCC(T, t) \
|
||||
T deccc##t (T a, T b) \
|
||||
{ \
|
||||
T difference = a - b; \
|
||||
if (difference > a) \
|
||||
c --; \
|
||||
return difference; \
|
||||
}
|
||||
|
||||
#define MINUSCCONLY(T, t) \
|
||||
void minuscconly##t (T a, T b) \
|
||||
{ \
|
||||
T difference = a - b; \
|
||||
if (difference > a) \
|
||||
abort (); \
|
||||
}
|
||||
|
||||
#define TEST(T, t) \
|
||||
PLUSCC(T, t) \
|
||||
PLUSCCONLY(T, t) \
|
||||
INCCC(T, t) \
|
||||
MINUSCC(T, t) \
|
||||
MINUSCCONLY(T, t) \
|
||||
DECCC(T, t)
|
||||
|
||||
TEST (unsigned long, l)
|
||||
TEST (unsigned int, i)
|
||||
TEST (unsigned short, s)
|
||||
TEST (unsigned char, c)
|
||||
|
||||
#define PLUSCCZEXT(C) \
|
||||
unsigned long pluscczext##C (unsigned int a, unsigned int b) \
|
||||
{ \
|
||||
unsigned int sum = a + b; \
|
||||
if (sum < C) \
|
||||
abort (); \
|
||||
return sum; \
|
||||
}
|
||||
|
||||
PLUSCCZEXT(a)
|
||||
PLUSCCZEXT(b)
|
||||
|
||||
#define MINUSCCZEXT \
|
||||
unsigned long minuscczext (unsigned int a, unsigned int b) \
|
||||
{ \
|
||||
unsigned int difference = a - b; \
|
||||
if (difference > a) \
|
||||
abort (); \
|
||||
return difference; \
|
||||
}
|
||||
|
||||
MINUSCCZEXT
|
Loading…
Add table
Reference in a new issue