This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH 2/2] Implement -fsanitize=signed-integer-overflow (i?86 parts)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Uros Bizjak <ubizjak at gmail dot com>
- Cc: Marek Polacek <polacek at redhat dot com>, GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 4 Dec 2013 21:01:09 +0100
- Subject: Re: [PATCH 2/2] Implement -fsanitize=signed-integer-overflow (i?86 parts)
- Authentication-results: sourceware.org; auth=none
- References: <20131204134418 dot GD32420 at redhat dot com> <CAFULd4ZrkEH0YtYD7uZZT6XD7TWEw6UTMJ5DKymZ5PHPyyh18g at mail dot gmail dot com> <20131204190745 dot GY892 at tucnak dot redhat dot com> <CAFULd4ZR1toXitD4QgAGe8uZuVkF71KMJQwLojX0-BXFVHh=FQ at mail dot gmail dot com>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
On Wed, Dec 04, 2013 at 08:23:22PM +0100, Uros Bizjak wrote:
> > My memory is fuzzy about that, but I think that was my first version which
> > didn't work, because with match_dup then it requires on the internal-fn.c
> > side to pass 4 arguments instead of just 3. I can try again though.
Weird, now it works, dunno what I have done differently before.
Though, I've discovered a bug in internal-fn.c for the negation case.
So is this everything you wanted?
2013-12-04 Jakub Jelinek <jakub@redhat.com>
Marek Polacek <polacek@redhat.com>
* config/i386/i386.md (DWI, dwi): Add QImode and HImode cases.
(addv<mode>4, subv<mode>4, mulv<mode>4, negv<mode>3): New
expanders.
(*addv<mode>4, *subv<mode>4, *mulv<mode>4, *negv<mode>3): New insns.
* internal-fn.c (ubsan_expand_si_overflow_neg_check): The return
value lives in res rather than target.
--- gcc/config/i386/i386.md.jj 2013-12-04 12:05:46.689185140 +0100
+++ gcc/config/i386/i386.md 2013-12-04 20:40:25.417309596 +0100
@@ -905,8 +905,8 @@ (define_mode_iterator DWI [(DI "!TARGET_
(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 @@ (define_insn "*addqi_ext_2"
[(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 @@ (define_insn "*subsi_2_zext"
[(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 @@ (define_insn "*mulqi3_1"
(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 @@ (define_insn "*negsi2_cmpz_zext"
[(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"
--- gcc/internal-fn.c.jj 2013-12-04 20:09:39.000000000 +0100
+++ gcc/internal-fn.c 2013-12-04 20:54:40.994939539 +0100
@@ -291,7 +291,6 @@ ubsan_expand_si_overflow_neg_check (gimp
&& !find_reg_note (last, REG_BR_PROB, 0))
add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
emit_jump (done_label);
- res = target;
}
else
{
Jakub