re PR rtl-optimization/82628 (wrong code at -Os on x86_64-linux-gnu in the 32-bit...
authorJakub Jelinek <jakub@redhat.com>
Tue, 24 Oct 2017 10:44:56 +0000 (12:44 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 24 Oct 2017 10:44:56 +0000 (12:44 +0200)
PR target/82628
* config/i386/i386.md (addcarry<mode>, subborrow<mode>): Change
patterns to better describe from which operation the CF is computed.
(addcarry<mode>_0, subborrow<mode>_0): New patterns.
* config/i386/i386.c (ix86_expand_builtin) <case handlecarry>: Pass
one LTU with [DT]Imode and another one with [SD]Imode.  If arg0
is 0, use _0 suffixed expanders instead of emitting a comparison
before it.

From-SVN: r254039

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.md

index 82d69edfb0b8ec63a81d960d3d664772ce86e05a..c2c3a523405a918689bf79cc2b71582efcd0af4f 100644 (file)
@@ -1,3 +1,14 @@
+2017-10-24  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/82628
+       * config/i386/i386.md (addcarry<mode>, subborrow<mode>): Change
+       patterns to better describe from which operation the CF is computed.
+       (addcarry<mode>_0, subborrow<mode>_0): New patterns.
+       * config/i386/i386.c (ix86_expand_builtin) <case handlecarry>: Pass
+       one LTU with [DT]Imode and another one with [SD]Imode.  If arg0
+       is 0, use _0 suffixed expanders instead of emitting a comparison
+       before it.
+
 2017-10-06  Sergey Shalnov  <Sergey.Shalnov@intel.com>
 
        * config/i386/i386.md(*movsf_internal, *movdf_internal):
index 72caf62bbf8e7e39bffbf8392dc532c4ea8d500d..d8241fa15cd10be33d530f1fbd49a6ae84335952 100644 (file)
@@ -35080,10 +35080,10 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
                     machine_mode mode, int ignore)
 {
   size_t i;
-  enum insn_code icode;
+  enum insn_code icode, icode2;
   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
   tree arg0, arg1, arg2, arg3, arg4;
-  rtx op0, op1, op2, op3, op4, pat, insn;
+  rtx op0, op1, op2, op3, op4, pat, pat2, insn;
   machine_mode mode0, mode1, mode2, mode3, mode4;
   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
 
@@ -36058,22 +36058,34 @@ rdseed_step:
 
     case IX86_BUILTIN_SBB32:
       icode = CODE_FOR_subborrowsi;
+      icode2 = CODE_FOR_subborrowsi_0;
       mode0 = SImode;
+      mode1 = DImode;
+      mode2 = CCmode;
       goto handlecarry;
 
     case IX86_BUILTIN_SBB64:
       icode = CODE_FOR_subborrowdi;
+      icode2 = CODE_FOR_subborrowdi_0;
       mode0 = DImode;
+      mode1 = TImode;
+      mode2 = CCmode;
       goto handlecarry;
 
     case IX86_BUILTIN_ADDCARRYX32:
       icode = CODE_FOR_addcarrysi;
+      icode2 = CODE_FOR_addcarrysi_0;
       mode0 = SImode;
+      mode1 = DImode;
+      mode2 = CCCmode;
       goto handlecarry;
 
     case IX86_BUILTIN_ADDCARRYX64:
       icode = CODE_FOR_addcarrydi;
+      icode2 = CODE_FOR_addcarrydi_0;
       mode0 = DImode;
+      mode1 = TImode;
+      mode2 = CCCmode;
 
     handlecarry:
       arg0 = CALL_EXPR_ARG (exp, 0); /* unsigned char c_in.  */
@@ -36082,7 +36094,8 @@ rdseed_step:
       arg3 = CALL_EXPR_ARG (exp, 3); /* unsigned int *sum_out.  */
 
       op1 = expand_normal (arg0);
-      op1 = copy_to_mode_reg (QImode, convert_to_mode (QImode, op1, 1));
+      if (!integer_zerop (arg0))
+       op1 = copy_to_mode_reg (QImode, convert_to_mode (QImode, op1, 1));
 
       op2 = expand_normal (arg1);
       if (!register_operand (op2, mode0))
@@ -36099,21 +36112,31 @@ rdseed_step:
          op4 = copy_addr_to_reg (op4);
        }
 
-      /* Generate CF from input operand.  */
-      emit_insn (gen_addqi3_cconly_overflow (op1, constm1_rtx));
-
-      /* Generate instruction that consumes CF.  */
       op0 = gen_reg_rtx (mode0);
+      if (integer_zerop (arg0))
+       {
+         /* If arg0 is 0, optimize right away into add or sub
+            instruction that sets CCCmode flags.  */
+         op1 = gen_rtx_REG (mode2, FLAGS_REG);
+         emit_insn (GEN_FCN (icode2) (op0, op2, op3));
+       }
+      else
+       {
+         /* Generate CF from input operand.  */
+         emit_insn (gen_addqi3_cconly_overflow (op1, constm1_rtx));
 
-      op1 = gen_rtx_REG (CCCmode, FLAGS_REG);
-      pat = gen_rtx_LTU (mode0, op1, const0_rtx);
-      emit_insn (GEN_FCN (icode) (op0, op2, op3, op1, pat));
+         /* Generate instruction that consumes CF.  */
+         op1 = gen_rtx_REG (CCCmode, FLAGS_REG);
+         pat = gen_rtx_LTU (mode1, op1, const0_rtx);
+         pat2 = gen_rtx_LTU (mode0, op1, const0_rtx);
+         emit_insn (GEN_FCN (icode) (op0, op2, op3, op1, pat, pat2));
+       }
 
       /* Return current CF value.  */
       if (target == 0)
         target = gen_reg_rtx (QImode);
 
-      PUT_MODE (pat, QImode);
+      pat = gen_rtx_LTU (QImode, op1, const0_rtx);
       emit_insn (gen_rtx_SET (target, pat));
 
       /* Store the result.  */
index d5792eb22a4161380fb8f5f526968fafcbd6d073..49ad0394fb57dde3c155f39ec7d408229f1350cf 100644 (file)
 (define_insn "addcarry<mode>"
   [(set (reg:CCC FLAGS_REG)
        (compare:CCC
-         (plus:SWI48
+         (zero_extend:<DWI>
            (plus:SWI48
-             (match_operator:SWI48 4 "ix86_carry_flag_operator"
-              [(match_operand 3 "flags_reg_operand") (const_int 0)])
-             (match_operand:SWI48 1 "nonimmediate_operand" "%0"))
-           (match_operand:SWI48 2 "nonimmediate_operand" "rm"))
-         (match_dup 1)))
+             (plus:SWI48
+               (match_operator:SWI48 5 "ix86_carry_flag_operator"
+                 [(match_operand 3 "flags_reg_operand") (const_int 0)])
+               (match_operand:SWI48 1 "nonimmediate_operand" "%0"))
+             (match_operand:SWI48 2 "nonimmediate_operand" "rm")))
+         (plus:<DWI>
+           (zero_extend:<DWI> (match_dup 2))
+           (match_operator:<DWI> 4 "ix86_carry_flag_operator"
+             [(match_dup 3) (const_int 0)]))))
    (set (match_operand:SWI48 0 "register_operand" "=r")
-       (plus:SWI48 (plus:SWI48 (match_op_dup 4
+       (plus:SWI48 (plus:SWI48 (match_op_dup 5
                                 [(match_dup 3) (const_int 0)])
                                (match_dup 1))
                    (match_dup 2)))]
    (set_attr "pent_pair" "pu")
    (set_attr "mode" "<MODE>")])
 
+(define_expand "addcarry<mode>_0"
+  [(parallel
+     [(set (reg:CCC FLAGS_REG)
+          (compare:CCC
+            (plus:SWI48
+              (match_operand:SWI48 1 "nonimmediate_operand")
+              (match_operand:SWI48 2 "x86_64_general_operand"))
+            (match_dup 1)))
+      (set (match_operand:SWI48 0 "register_operand")
+          (plus:SWI48 (match_dup 1) (match_dup 2)))])]
+  "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)")
+
 (define_insn "sub<mode>3_carry"
   [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
        (minus:SWI
 (define_insn "subborrow<mode>"
   [(set (reg:CCC FLAGS_REG)
        (compare:CCC
-         (match_operand:SWI48 1 "nonimmediate_operand" "0")
-         (plus:SWI48
-           (match_operator:SWI48 4 "ix86_carry_flag_operator"
-            [(match_operand 3 "flags_reg_operand") (const_int 0)])
-           (match_operand:SWI48 2 "nonimmediate_operand" "rm"))))
+         (zero_extend:<DWI>
+           (match_operand:SWI48 1 "nonimmediate_operand" "0"))
+         (plus:<DWI>
+           (match_operator:<DWI> 4 "ix86_carry_flag_operator"
+             [(match_operand 3 "flags_reg_operand") (const_int 0)])
+           (zero_extend:<DWI>
+             (match_operand:SWI48 2 "nonimmediate_operand" "rm")))))
    (set (match_operand:SWI48 0 "register_operand" "=r")
-       (minus:SWI48 (minus:SWI48 (match_dup 1)
-                                 (match_op_dup 4
-                                  [(match_dup 3) (const_int 0)]))
+       (minus:SWI48 (minus:SWI48
+                      (match_dup 1)
+                      (match_operator:SWI48 5 "ix86_carry_flag_operator"
+                        [(match_dup 3) (const_int 0)]))
                     (match_dup 2)))]
   "ix86_binary_operator_ok (MINUS, <MODE>mode, operands)"
   "sbb{<imodesuffix>}\t{%2, %0|%0, %2}"
    (set_attr "use_carry" "1")
    (set_attr "pent_pair" "pu")
    (set_attr "mode" "<MODE>")])
+
+(define_expand "subborrow<mode>_0"
+  [(parallel
+     [(set (reg:CC FLAGS_REG)
+          (compare:CC
+            (match_operand:SWI48 1 "nonimmediate_operand")
+            (match_operand:SWI48 2 "<general_operand>")))
+      (set (match_operand:SWI48 0 "register_operand")
+          (minus:SWI48 (match_dup 1) (match_dup 2)))])]
+  "ix86_binary_operator_ok (MINUS, <MODE>mode, operands)")
 \f
 ;; Overflow setting add instructions