From 31e071aeb827f49ce2e891620852198e99d44a0c Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Wed, 4 Dec 2013 22:47:11 +0000 Subject: Implement -fsanitize=signed-integer-overflow. From-SVN: r205684 --- gcc/config/i386/i386.md | 156 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 154 insertions(+), 2 deletions(-) (limited to 'gcc/config') 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 "addv4" + [(parallel [(set (reg:CCO FLAGS_REG) + (eq:CCO (plus: + (sign_extend: + (match_operand:SWI 1 "nonimmediate_operand")) + (sign_extend: + (match_operand:SWI 2 ""))) + (sign_extend: + (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, operands);") + +(define_insn "*addv4" + [(set (reg:CCO FLAGS_REG) + (eq:CCO (plus: + (sign_extend: + (match_operand:SWI 1 "nonimmediate_operand" "%0,0")) + (sign_extend: + (match_operand:SWI 2 "" ","))) + (sign_extend: + (plus:SWI (match_dup 1) (match_dup 2))))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=,m") + (plus:SWI (match_dup 1) (match_dup 2)))] + "ix86_binary_operator_ok (PLUS, mode, operands)" + "add{}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "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 "subv4" + [(parallel [(set (reg:CCO FLAGS_REG) + (eq:CCO (minus: + (sign_extend: + (match_operand:SWI 1 "nonimmediate_operand")) + (sign_extend: + (match_operand:SWI 2 ""))) + (sign_extend: + (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, operands);") + +(define_insn "*subv4" + [(set (reg:CCO FLAGS_REG) + (eq:CCO (minus: + (sign_extend: + (match_operand:SWI 1 "nonimmediate_operand" "0,0")) + (sign_extend: + (match_operand:SWI 2 "" ",m"))) + (sign_extend: + (minus:SWI (match_dup 1) (match_dup 2))))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=m,") + (minus:SWI (match_dup 1) (match_dup 2)))] + "ix86_binary_operator_ok (MINUS, mode, operands)" + "sub{}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "mode" "")]) + (define_insn "*sub_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 "mulv4" + [(parallel [(set (reg:CCO FLAGS_REG) + (eq:CCO (mult: + (sign_extend: + (match_operand:SWI48 1 "register_operand")) + (sign_extend: + (match_operand:SWI48 2 ""))) + (sign_extend: + (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 "*mulv4" + [(set (reg:CCO FLAGS_REG) + (eq:CCO (mult: + (sign_extend: + (match_operand:SWI 1 "nonimmediate_operand" "%rm,rm,0")) + (sign_extend: + (match_operand:SWI 2 "" "K,,mr"))) + (sign_extend: + (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{}\t{%2, %1, %0|%0, %1, %2} + imul{}\t{%2, %1, %0|%0, %1, %2} + imul{}\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" "")]) + (define_expand "mul3" [(parallel [(set (match_operand: 0 "register_operand") (mult: @@ -8624,6 +8746,36 @@ [(set_attr "type" "negnot") (set_attr "mode" "SI")]) +;; Negate with jump on overflow. +(define_expand "negv3" + [(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) - 1), + mode); +}) + +(define_insn "*negv3" + [(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" "=m") + (neg:SWI (match_dup 1)))] + "ix86_unary_operator_ok (NEG, mode, operands) + && mode_signbit_p (mode, operands[2])" + "neg{}\t%0" + [(set_attr "type" "negnot") + (set_attr "mode" "")]) + ;; Changing of sign for FP values is doable using integer unit too. (define_expand "2" -- cgit v1.1