diff options
author | Marek Polacek <mpolacek@gcc.gnu.org> | 2013-12-04 22:47:11 +0000 |
---|---|---|
committer | Marek Polacek <mpolacek@gcc.gnu.org> | 2013-12-04 22:47:11 +0000 |
commit | 31e071aeb827f49ce2e891620852198e99d44a0c (patch) | |
tree | 20fca81276f1e6d6224300c11a4e10fa89519d41 /gcc/config | |
parent | 59b6687cceaf95d8c49afee88248cf4fb0a33105 (diff) | |
download | gcc-31e071aeb827f49ce2e891620852198e99d44a0c.zip gcc-31e071aeb827f49ce2e891620852198e99d44a0c.tar.gz gcc-31e071aeb827f49ce2e891620852198e99d44a0c.tar.bz2 |
Implement -fsanitize=signed-integer-overflow.
From-SVN: r205684
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/i386/i386.md | 156 |
1 files changed, 154 insertions, 2 deletions
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 0c732c7..5ff66cc 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -905,8 +905,8 @@ (TI "TARGET_64BIT")]) ;; Double word integer modes as mode attribute. -(define_mode_attr DWI [(SI "DI") (DI "TI")]) -(define_mode_attr dwi [(SI "di") (DI "ti")]) +(define_mode_attr DWI [(QI "HI") (HI "SI") (SI "DI") (DI "TI")]) +(define_mode_attr dwi [(QI "hi") (HI "si") (SI "di") (DI "ti")]) ;; Half mode for double word integer modes. (define_mode_iterator DWIH [(SI "!TARGET_64BIT") @@ -6160,6 +6160,41 @@ [(set_attr "type" "alu") (set_attr "mode" "QI")]) +;; Add with jump on overflow. +(define_expand "addv<mode>4" + [(parallel [(set (reg:CCO FLAGS_REG) + (eq:CCO (plus:<DWI> + (sign_extend:<DWI> + (match_operand:SWI 1 "nonimmediate_operand")) + (sign_extend:<DWI> + (match_operand:SWI 2 "<general_operand>"))) + (sign_extend:<DWI> + (plus:SWI (match_dup 1) (match_dup 2))))) + (set (match_operand:SWI 0 "register_operand") + (plus:SWI (match_dup 1) (match_dup 2)))]) + (set (pc) (if_then_else + (eq (reg:CCO FLAGS_REG) (const_int 0)) + (label_ref (match_operand 3)) + (pc)))] + "" + "ix86_fixup_binary_operands_no_copy (PLUS, <MODE>mode, operands);") + +(define_insn "*addv<mode>4" + [(set (reg:CCO FLAGS_REG) + (eq:CCO (plus:<DWI> + (sign_extend:<DWI> + (match_operand:SWI 1 "nonimmediate_operand" "%0,0")) + (sign_extend:<DWI> + (match_operand:SWI 2 "<general_operand>" "<g>,<r><i>"))) + (sign_extend:<DWI> + (plus:SWI (match_dup 1) (match_dup 2))))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>,<r>m") + (plus:SWI (match_dup 1) (match_dup 2)))] + "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)" + "add{<imodesuffix>}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "mode" "<MODE>")]) + ;; The lea patterns for modes less than 32 bits need to be matched by ;; several insns converted to real lea by splitters. @@ -6397,6 +6432,41 @@ [(set_attr "type" "alu") (set_attr "mode" "SI")]) +;; Subtract with jump on overflow. +(define_expand "subv<mode>4" + [(parallel [(set (reg:CCO FLAGS_REG) + (eq:CCO (minus:<DWI> + (sign_extend:<DWI> + (match_operand:SWI 1 "nonimmediate_operand")) + (sign_extend:<DWI> + (match_operand:SWI 2 "<general_operand>"))) + (sign_extend:<DWI> + (minus:SWI (match_dup 1) (match_dup 2))))) + (set (match_operand:SWI 0 "register_operand") + (minus:SWI (match_dup 1) (match_dup 2)))]) + (set (pc) (if_then_else + (eq (reg:CCO FLAGS_REG) (const_int 0)) + (label_ref (match_operand 3)) + (pc)))] + "" + "ix86_fixup_binary_operands_no_copy (MINUS, <MODE>mode, operands);") + +(define_insn "*subv<mode>4" + [(set (reg:CCO FLAGS_REG) + (eq:CCO (minus:<DWI> + (sign_extend:<DWI> + (match_operand:SWI 1 "nonimmediate_operand" "0,0")) + (sign_extend:<DWI> + (match_operand:SWI 2 "<general_operand>" "<r><i>,<r>m"))) + (sign_extend:<DWI> + (minus:SWI (match_dup 1) (match_dup 2))))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>") + (minus:SWI (match_dup 1) (match_dup 2)))] + "ix86_binary_operator_ok (MINUS, <MODE>mode, operands)" + "sub{<imodesuffix>}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "mode" "<MODE>")]) + (define_insn "*sub<mode>_3" [(set (reg FLAGS_REG) (compare (match_operand:SWI 1 "nonimmediate_operand" "0,0") @@ -6711,6 +6781,58 @@ (set_attr "bdver1_decode" "direct") (set_attr "mode" "QI")]) +;; Multiply with jump on overflow. +(define_expand "mulv<mode>4" + [(parallel [(set (reg:CCO FLAGS_REG) + (eq:CCO (mult:<DWI> + (sign_extend:<DWI> + (match_operand:SWI48 1 "register_operand")) + (sign_extend:<DWI> + (match_operand:SWI48 2 "<general_operand>"))) + (sign_extend:<DWI> + (mult:SWI48 (match_dup 1) (match_dup 2))))) + (set (match_operand:SWI48 0 "register_operand") + (mult:SWI48 (match_dup 1) (match_dup 2)))]) + (set (pc) (if_then_else + (eq (reg:CCO FLAGS_REG) (const_int 0)) + (label_ref (match_operand 3)) + (pc)))]) + +(define_insn "*mulv<mode>4" + [(set (reg:CCO FLAGS_REG) + (eq:CCO (mult:<DWI> + (sign_extend:<DWI> + (match_operand:SWI 1 "nonimmediate_operand" "%rm,rm,0")) + (sign_extend:<DWI> + (match_operand:SWI 2 "<general_operand>" "K,<i>,mr"))) + (sign_extend:<DWI> + (mult:SWI (match_dup 1) (match_dup 2))))) + (set (match_operand:SWI 0 "register_operand" "=r,r,r") + (mult:SWI (match_dup 1) (match_dup 2)))] + "!(MEM_P (operands[1]) && MEM_P (operands[2]))" + "@ + imul{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} + imul{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} + imul{<imodesuffix>}\t{%2, %0|%0, %2}" + [(set_attr "type" "imul") + (set_attr "prefix_0f" "0,0,1") + (set (attr "athlon_decode") + (cond [(eq_attr "cpu" "athlon") + (const_string "vector") + (eq_attr "alternative" "1") + (const_string "vector") + (and (eq_attr "alternative" "2") + (match_operand 1 "memory_operand")) + (const_string "vector")] + (const_string "direct"))) + (set (attr "amdfam10_decode") + (cond [(and (eq_attr "alternative" "0,1") + (match_operand 1 "memory_operand")) + (const_string "vector")] + (const_string "direct"))) + (set_attr "bdver1_decode" "direct") + (set_attr "mode" "<MODE>")]) + (define_expand "<u>mul<mode><dwi>3" [(parallel [(set (match_operand:<DWI> 0 "register_operand") (mult:<DWI> @@ -8624,6 +8746,36 @@ [(set_attr "type" "negnot") (set_attr "mode" "SI")]) +;; Negate with jump on overflow. +(define_expand "negv<mode>3" + [(parallel [(set (reg:CCO FLAGS_REG) + (ne:CCO (match_operand:SWI 1 "register_operand") + (match_dup 3))) + (set (match_operand:SWI 0 "register_operand") + (neg:SWI (match_dup 1)))]) + (set (pc) (if_then_else + (eq (reg:CCO FLAGS_REG) (const_int 0)) + (label_ref (match_operand 2)) + (pc)))] + "" +{ + operands[3] + = gen_int_mode (HOST_WIDE_INT_1U << (GET_MODE_BITSIZE (<MODE>mode) - 1), + <MODE>mode); +}) + +(define_insn "*negv<mode>3" + [(set (reg:CCO FLAGS_REG) + (ne:CCO (match_operand:SWI 1 "nonimmediate_operand" "0") + (match_operand:SWI 2 "const_int_operand"))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m") + (neg:SWI (match_dup 1)))] + "ix86_unary_operator_ok (NEG, <MODE>mode, operands) + && mode_signbit_p (<MODE>mode, operands[2])" + "neg{<imodesuffix>}\t%0" + [(set_attr "type" "negnot") + (set_attr "mode" "<MODE>")]) + ;; Changing of sign for FP values is doable using integer unit too. (define_expand "<code><mode>2" |