re PR target/82692 (Ordered comparisons used for unordered built-ins)
authorUros Bizjak <ubizjak@gmail.com>
Fri, 27 Oct 2017 18:13:14 +0000 (20:13 +0200)
committerUros Bizjak <uros@gcc.gnu.org>
Fri, 27 Oct 2017 18:13:14 +0000 (20:13 +0200)
PR target/82692
* config/i386/i386-modes.def (CCFPU): Remove definition.
* config/i386/i386.c (put_condition_mode): Remove CCFPU mode handling.
(ix86_cc_modes_compatible): Ditto.
(ix86_expand_carry_flag_compare): Ditto.
(ix86_expand_int_movcc): Ditto.
(ix86_expand_int_addcc): Ditto.
(ix86_reverse_condition): Ditto.
(ix86_unordered_fp_compare): Rename from ix86_fp_compare_mode.
Return true/false for unordered/ordered fp comparisons.
(ix86_cc_mode): Always return CCFPmode for float mode comparisons.
(ix86_prepare_fp_compare_args): Update for rename.
(ix86_expand_fp_compare): Update for rename.  Generate unordered
compare RTXes wrapped with UNSPEC_NOTRAP unspec.
(ix86_expand_sse_compare_and_jump): Ditto.
* config/i386/predicates.md (fcmov_comparison_operator):
Remove CCFPU mode handling.
(ix86_comparison_operator): Ditto.
(ix86_carry_flag_operator): Ditto.
* config/i386/i386.md (UNSPEC_NOTRAP): New unspec.
(*cmpu<mode>_i387): Wrap compare RTX with UNSPEC_NOTRAP unspec.
(*cmpu<mode>_cc_i387): Ditto.
(FPCMP): Remove mode iterator.
(unord): Remove mode attribute.
(unord_subst): New define_subst transformation
(unord): New define_subst attribute.
(unordered): Ditto.
(*cmpi<unord><MODEF:mode>): Rewrite using unord_subst transformation.
(*cmpi<unord>xf_i387): Ditto.
* config/i386/sse.md (<sse>_<unord>comi<round_saeonly_name>): Merge
from <sse>_comi<round_saeonly_name> and <sse>_ucomi<round_saeonly_name>
using unord_subst transformation.
* config/i386/subst.md (SUBST_A): Remove CCFP and CCFPU modes.
(round_saeonly): Also handle CCFP mode.
* reg-stack.c (subst_stack_regs_pat): Handle UNSPEC_NOTRAP unspec.
Remove UNSPEC_SAHF unspec handling.

testsuite/ChangeLog:

PR target/82692
* gcc.dg/torture/pr82692.c: New test.

From-SVN: r254167

gcc/ChangeLog
gcc/config/i386/i386-modes.def
gcc/config/i386/i386.c
gcc/config/i386/i386.md
gcc/config/i386/predicates.md
gcc/config/i386/sse.md
gcc/config/i386/subst.md
gcc/reg-stack.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr82692.c [new file with mode: 0644]

index e8fa8fce70b4a5fa48bfec89c9fdf68eed1cf3c7..7c3f1e5459028ffeaf90c9f3f3aede76db4f4995 100644 (file)
@@ -1,3 +1,42 @@
+2017-10-27  Uros Bizjak  <ubizjak@gmail.com>
+
+       PR target/82692
+       * config/i386/i386-modes.def (CCFPU): Remove definition.
+       * config/i386/i386.c (put_condition_mode): Remove CCFPU mode handling.
+       (ix86_cc_modes_compatible): Ditto.
+       (ix86_expand_carry_flag_compare): Ditto.
+       (ix86_expand_int_movcc): Ditto.
+       (ix86_expand_int_addcc): Ditto.
+       (ix86_reverse_condition): Ditto.
+       (ix86_unordered_fp_compare): Rename from ix86_fp_compare_mode.
+       Return true/false for unordered/ordered fp comparisons.
+       (ix86_cc_mode): Always return CCFPmode for float mode comparisons.
+       (ix86_prepare_fp_compare_args): Update for rename.
+       (ix86_expand_fp_compare): Update for rename.  Generate unordered
+       compare RTXes wrapped with UNSPEC_NOTRAP unspec.
+       (ix86_expand_sse_compare_and_jump): Ditto.
+       * config/i386/predicates.md (fcmov_comparison_operator):
+       Remove CCFPU mode handling.
+       (ix86_comparison_operator): Ditto.
+       (ix86_carry_flag_operator): Ditto.
+       * config/i386/i386.md (UNSPEC_NOTRAP): New unspec.
+       (*cmpu<mode>_i387): Wrap compare RTX with UNSPEC_NOTRAP unspec.
+       (*cmpu<mode>_cc_i387): Ditto.
+       (FPCMP): Remove mode iterator.
+       (unord): Remove mode attribute.
+       (unord_subst): New define_subst transformation
+       (unord): New define_subst attribute.
+       (unordered): Ditto.
+       (*cmpi<unord><MODEF:mode>): Rewrite using unord_subst transformation.
+       (*cmpi<unord>xf_i387): Ditto.
+       * config/i386/sse.md (<sse>_<unord>comi<round_saeonly_name>): Merge
+       from <sse>_comi<round_saeonly_name> and <sse>_ucomi<round_saeonly_name>
+       using unord_subst transformation.
+       * config/i386/subst.md (SUBST_A): Remove CCFP and CCFPU modes.
+       (round_saeonly): Also handle CCFP mode.
+       * reg-stack.c (subst_stack_regs_pat): Handle UNSPEC_NOTRAP unspec.
+       Remove UNSPEC_SAHF unspec handling.
+
 2017-10-27  Jan Hubicka  <hubicka@ucw.cz>
 
        * x86-tune.def (X86_TUNE_INTER_UNIT_MOVES_TO_VEC): Disable for Zen.
index 16bc1d8b71a878968f03a21da15131d58ea5073e..dcf6854b57dbc2a5eded13485663af79162013ae 100644 (file)
@@ -72,8 +72,8 @@ CC_MODE (CCO);
 CC_MODE (CCP);
 CC_MODE (CCS);
 CC_MODE (CCZ);
+
 CC_MODE (CCFP);
-CC_MODE (CCFPU);
 
 /* Vector modes.  Note that VEC_CONCAT patterns require vector
    sizes twice as big as implemented in hardware.  */
index 6ee6abea258d8cb380392a3227c537244f71f4c8..8a2e2dac6b703aa6e002a0e57792e02c20bfbe9b 100644 (file)
@@ -16930,7 +16930,7 @@ put_condition_code (enum rtx_code code, machine_mode mode, bool reverse,
 {
   const char *suffix;
 
-  if (mode == CCFPmode || mode == CCFPUmode)
+  if (mode == CCFPmode)
     {
       code = ix86_fp_compare_code_to_integer (code);
       mode = CCmode;
@@ -21695,14 +21695,13 @@ ix86_expand_int_compare (enum rtx_code code, rtx op0, rtx op1)
   return gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx);
 }
 
-/* Figure out whether to use ordered or unordered fp comparisons.
-   Return the appropriate mode to use.  */
+/* Figure out whether to use unordered fp comparisons.  */
 
-machine_mode
-ix86_fp_compare_mode (enum rtx_code code)
+static bool
+ix86_unordered_fp_compare (enum rtx_code code)
 {
   if (!TARGET_IEEE_FP)
-    return CCFPmode;
+    return false;
 
   switch (code)
     {
@@ -21710,7 +21709,7 @@ ix86_fp_compare_mode (enum rtx_code code)
     case GE:
     case LT:
     case LE:
-      return CCFPmode;
+      return false;
 
     case EQ:
     case NE:
@@ -21723,7 +21722,7 @@ ix86_fp_compare_mode (enum rtx_code code)
     case UNGT:
     case UNGE:
     case UNEQ:
-      return CCFPUmode;
+      return true;
 
     default:
       gcc_unreachable ();
@@ -21738,7 +21737,7 @@ ix86_cc_mode (enum rtx_code code, rtx op0, rtx op1)
   if (SCALAR_FLOAT_MODE_P (mode))
     {
       gcc_assert (!DECIMAL_FLOAT_MODE_P (mode));
-      return ix86_fp_compare_mode (code);
+      return CCFPmode;
     }
 
   switch (code)
@@ -21860,7 +21859,6 @@ ix86_cc_modes_compatible (machine_mode m1, machine_mode m2)
        }
 
     case E_CCFPmode:
-    case E_CCFPUmode:
       /* These are only compatible with themselves, which we already
         checked above.  */
       return VOIDmode;
@@ -21964,7 +21962,7 @@ ix86_fp_comparison_strategy (enum rtx_code)
 static enum rtx_code
 ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1)
 {
-  machine_mode fpcmp_mode = ix86_fp_compare_mode (code);
+  bool unordered_compare = ix86_unordered_fp_compare (code);
   rtx op0 = *pop0, op1 = *pop1;
   machine_mode op_mode = GET_MODE (op0);
   bool is_sse = TARGET_SSE_MATH && SSE_FLOAT_MODE_P (op_mode);
@@ -21976,7 +21974,7 @@ ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1)
      floating point.  */
 
   if (!is_sse
-      && (fpcmp_mode == CCFPUmode
+      && (unordered_compare
          || (op_mode == XFmode
              && ! (standard_80387_constant_p (op0) == 1
                    || standard_80387_constant_p (op1) == 1)
@@ -22073,27 +22071,29 @@ ix86_fp_compare_code_to_integer (enum rtx_code code)
 static rtx
 ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch)
 {
-  machine_mode fpcmp_mode, intcmp_mode;
+  bool unordered_compare = ix86_unordered_fp_compare (code);
+  machine_mode intcmp_mode;
   rtx tmp, tmp2;
 
-  fpcmp_mode = ix86_fp_compare_mode (code);
   code = ix86_prepare_fp_compare_args (code, &op0, &op1);
 
   /* Do fcomi/sahf based test when profitable.  */
   switch (ix86_fp_comparison_strategy (code))
     {
     case IX86_FPCMP_COMI:
-      intcmp_mode = fpcmp_mode;
-      tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1);
-      tmp = gen_rtx_SET (gen_rtx_REG (fpcmp_mode, FLAGS_REG), tmp);
-      emit_insn (tmp);
+      intcmp_mode = CCFPmode;
+      tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
+      if (unordered_compare)
+       tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
+      emit_insn (gen_rtx_SET (gen_rtx_REG (CCFPmode, FLAGS_REG), tmp));
       break;
 
     case IX86_FPCMP_SAHF:
-      intcmp_mode = fpcmp_mode;
-      tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1);
-      tmp = gen_rtx_SET (gen_rtx_REG (fpcmp_mode, FLAGS_REG), tmp);
-
+      intcmp_mode = CCFPmode;
+      tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
+      if (unordered_compare)
+       tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
+      tmp = gen_rtx_SET (gen_rtx_REG (CCFPmode, FLAGS_REG), tmp);
       if (!scratch)
        scratch = gen_reg_rtx (HImode);
       tmp2 = gen_rtx_CLOBBER (VOIDmode, scratch);
@@ -22102,11 +22102,13 @@ ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch)
 
     case IX86_FPCMP_ARITH:
       /* Sadness wrt reg-stack pops killing fpsr -- gotta get fnstsw first.  */
-      tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1);
-      tmp2 = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW);
+      tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
+      if (unordered_compare)
+       tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
+      tmp = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW);
       if (!scratch)
        scratch = gen_reg_rtx (HImode);
-      emit_insn (gen_rtx_SET (scratch, tmp2));
+      emit_insn (gen_rtx_SET (scratch, tmp));
 
       /* In the unordered case, we have to check C2 for NaN's, which
         doesn't happen to work out to anything nice combination-wise.
@@ -22548,8 +22550,7 @@ ix86_expand_carry_flag_compare (enum rtx_code code, rtx op0, rtx op1, rtx *pop)
       compare_seq = get_insns ();
       end_sequence ();
 
-      if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode
-         || GET_MODE (XEXP (compare_op, 0)) == CCFPUmode)
+      if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode)
         code = ix86_fp_compare_code_to_integer (GET_CODE (compare_op));
       else
        code = GET_CODE (compare_op);
@@ -22689,8 +22690,7 @@ ix86_expand_int_movcc (rtx operands[])
 
              flags = XEXP (compare_op, 0);
 
-             if (GET_MODE (flags) == CCFPmode
-                 || GET_MODE (flags) == CCFPUmode)
+             if (GET_MODE (flags) == CCFPmode)
                {
                  fpcmp = true;
                  compare_code
@@ -24730,8 +24730,7 @@ ix86_expand_int_addcc (rtx operands[])
 
   flags = XEXP (compare_op, 0);
 
-  if (GET_MODE (flags) == CCFPmode
-      || GET_MODE (flags) == CCFPUmode)
+  if (GET_MODE (flags) == CCFPmode)
     {
       fpcmp = true;
       code = ix86_fp_compare_code_to_integer (code);
@@ -43190,7 +43189,7 @@ ix86_encode_section_info (tree decl, rtx rtl, int first)
 enum rtx_code
 ix86_reverse_condition (enum rtx_code code, machine_mode mode)
 {
-  return (mode != CCFPmode && mode != CCFPUmode
+  return (mode != CCFPmode
          ? reverse_condition (code)
          : reverse_condition_maybe_unordered (code));
 }
@@ -43805,17 +43804,20 @@ static rtx_code_label *
 ix86_expand_sse_compare_and_jump (enum rtx_code code, rtx op0, rtx op1,
                                   bool swap_operands)
 {
-  machine_mode fpcmp_mode = ix86_fp_compare_mode (code);
+  bool unordered_compare = ix86_unordered_fp_compare (code);
   rtx_code_label *label;
-  rtx tmp;
+  rtx tmp, reg;
 
   if (swap_operands)
     std::swap (op0, op1);
 
   label = gen_label_rtx ();
-  tmp = gen_rtx_REG (fpcmp_mode, FLAGS_REG);
-  emit_insn (gen_rtx_SET (tmp, gen_rtx_COMPARE (fpcmp_mode, op0, op1)));
-  tmp = gen_rtx_fmt_ee (code, VOIDmode, tmp, const0_rtx);
+  tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
+  if (unordered_compare)
+    tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
+  reg = gen_rtx_REG (CCFPmode, FLAGS_REG);
+  emit_insn (gen_rtx_SET (reg, tmp));
+  tmp = gen_rtx_fmt_ee (code, VOIDmode, reg, const0_rtx);
   tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
                              gen_rtx_LABEL_REF (VOIDmode, label), pc_rtx);
   tmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
index 49ad0394fb57dde3c155f39ec7d408229f1350cf..d48decbb7d99768567be64b5537fe468a0511947 100644 (file)
@@ -99,6 +99,7 @@
   UNSPEC_SCAS
   UNSPEC_FNSTSW
   UNSPEC_SAHF
+  UNSPEC_NOTRAP
   UNSPEC_PARITY
   UNSPEC_FSTCW
   UNSPEC_FLDCW
 
 ;; FP compares, step 1:
 ;; Set the FP condition codes.
-;;
-;; CCFPmode    compare with exceptions
-;; CCFPUmode   compare with no exceptions
 
 ;; We may not use "#" to split and emit these, since the REG_DEAD notes
 ;; used to manage the reg stack popping would not be preserved.
 (define_insn "*cmpu<mode>_i387"
   [(set (match_operand:HI 0 "register_operand" "=a")
        (unspec:HI
-         [(compare:CCFPU
-            (match_operand:X87MODEF 1 "register_operand" "f")
-            (match_operand:X87MODEF 2 "register_operand" "f"))]
+         [(unspec:CCFP
+            [(compare:CCFP
+               (match_operand:X87MODEF 1 "register_operand" "f")
+               (match_operand:X87MODEF 2 "register_operand" "f"))]
+            UNSPEC_NOTRAP)]
          UNSPEC_FNSTSW))]
   "TARGET_80387"
   "* return output_fp_compare (insn, operands, false, true);"
    (set_attr "mode" "<MODE>")])
 
 (define_insn_and_split "*cmpu<mode>_cc_i387"
-  [(set (reg:CCFPU FLAGS_REG)
-       (compare:CCFPU
-         (match_operand:X87MODEF 1 "register_operand" "f")
-         (match_operand:X87MODEF 2 "register_operand" "f")))
+  [(set (reg:CCFP FLAGS_REG)
+       (unspec:CCFP
+         [(compare:CCFP
+            (match_operand:X87MODEF 1 "register_operand" "f")
+            (match_operand:X87MODEF 2 "register_operand" "f"))]
+         UNSPEC_NOTRAP))
    (clobber (match_operand:HI 0 "register_operand" "=a"))]
   "TARGET_80387 && TARGET_SAHF && !TARGET_CMOVE"
   "#"
   "&& reload_completed"
   [(set (match_dup 0)
        (unspec:HI
-         [(compare:CCFPU (match_dup 1)(match_dup 2))]
-       UNSPEC_FNSTSW))
+         [(unspec:CCFP
+            [(compare:CCFP (match_dup 1)(match_dup 2))]
+            UNSPEC_NOTRAP)]
+         UNSPEC_FNSTSW))
    (set (reg:CC FLAGS_REG)
        (unspec:CC [(match_dup 0)] UNSPEC_SAHF))]
   ""
 ;; Pentium Pro can do steps 1 through 3 in one go.
 ;; (these instructions set flags directly)
 
-(define_mode_iterator FPCMP [CCFP CCFPU])
-(define_mode_attr unord [(CCFP "") (CCFPU "u")])
+(define_subst_attr "unord" "unord_subst" "" "u")
+(define_subst_attr "unordered" "unord_subst" "false" "true")
+
+(define_subst "unord_subst"
+  [(set (match_operand:CCFP 0)
+        (match_operand:CCFP 1))]
+  ""
+  [(set (match_dup 0)
+        (unspec:CCFP
+         [(match_dup 1)]
+         UNSPEC_NOTRAP))])
 
-(define_insn "*cmpi<FPCMP:unord><MODEF:mode>"
-  [(set (reg:FPCMP FLAGS_REG)
-       (compare:FPCMP
+(define_insn "*cmpi<unord><MODEF:mode>"
+  [(set (reg:CCFP FLAGS_REG)
+       (compare:CCFP
          (match_operand:MODEF 0 "register_operand" "f,v")
          (match_operand:MODEF 1 "register_ssemem_operand" "f,vm")))]
   "(SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH)
    || (TARGET_80387 && TARGET_CMOVE)"
   "@
-   * return output_fp_compare (insn, operands, true, \
-                              <FPCMP:MODE>mode == CCFPUmode);
-   %v<FPCMP:unord>comi<MODEF:ssemodesuffix>\t{%1, %0|%0, %1}"
+   * return output_fp_compare (insn, operands, true, <unordered>);
+   %v<unord>comi<MODEF:ssemodesuffix>\t{%1, %0|%0, %1}"
   [(set_attr "type" "fcmp,ssecomi")
    (set_attr "prefix" "orig,maybe_vex")
    (set_attr "mode" "<MODEF:MODE>")
         (symbol_ref "false"))))])
 
 (define_insn "*cmpi<unord>xf_i387"
-  [(set (reg:FPCMP FLAGS_REG)
-       (compare:FPCMP
+  [(set (reg:CCFP FLAGS_REG)
+       (compare:CCFP
          (match_operand:XF 0 "register_operand" "f")
          (match_operand:XF 1 "register_operand" "f")))]
   "TARGET_80387 && TARGET_CMOVE"
-  "* return output_fp_compare (insn, operands, true,
-                              <MODE>mode == CCFPUmode);"
+  "* return output_fp_compare (insn, operands, true, <unordered>);"
   [(set_attr "type" "fcmp")
    (set_attr "mode" "XF")
    (set_attr "athlon_decode" "vector")
index 89df15ac55cc2b9fec5ea54cc06bae114b5738d3..be9be85a3f24b49d04a29765de45bb1451c716fc 100644 (file)
   machine_mode inmode = GET_MODE (XEXP (op, 0));
   enum rtx_code code = GET_CODE (op);
 
-  if (inmode == CCFPmode || inmode == CCFPUmode)
+  if (inmode == CCFPmode)
     {
       if (!ix86_trivial_fp_comparison_operator (op, mode))
        return false;
   switch (code)
     {
     case LTU: case GTU: case LEU: case GEU:
-      if (inmode == CCmode || inmode == CCFPmode || inmode == CCFPUmode
+      if (inmode == CCmode || inmode == CCFPmode
          || inmode == CCCmode)
        return true;
       return false;
   machine_mode inmode = GET_MODE (XEXP (op, 0));
   enum rtx_code code = GET_CODE (op);
 
-  if (inmode == CCFPmode || inmode == CCFPUmode)
+  if (inmode == CCFPmode)
     return ix86_trivial_fp_comparison_operator (op, mode);
 
   switch (code)
   machine_mode inmode = GET_MODE (XEXP (op, 0));
   enum rtx_code code = GET_CODE (op);
 
-  if (inmode == CCFPmode || inmode == CCFPUmode)
+  if (inmode == CCFPmode)
     {
       if (!ix86_trivial_fp_comparison_operator (op, mode))
        return false;
index fe3cb1791ad0c28711d94bf1a84b9c86b0d4d365..562751555446cbe6f67a80bd48ba917e275ec6ce 100644 (file)
    (set_attr "prefix" "evex")
    (set_attr "mode" "<sseinsnmode>")])
 
-(define_insn "<sse>_comi<round_saeonly_name>"
+(define_insn "<sse>_<unord>comi<round_saeonly_name>"
   [(set (reg:CCFP FLAGS_REG)
        (compare:CCFP
          (vec_select:MODEF
            (match_operand:<ssevecmode> 1 "<round_saeonly_nimm_scalar_predicate>" "<round_saeonly_constraint>")
            (parallel [(const_int 0)]))))]
   "SSE_FLOAT_MODE_P (<MODE>mode)"
-  "%vcomi<ssemodesuffix>\t{<round_saeonly_op2>%1, %0|%0, %<iptr>1<round_saeonly_op2>}"
-  [(set_attr "type" "ssecomi")
-   (set_attr "prefix" "maybe_vex")
-   (set_attr "prefix_rep" "0")
-   (set (attr "prefix_data16")
-       (if_then_else (eq_attr "mode" "DF")
-                     (const_string "1")
-                     (const_string "0")))
-   (set_attr "mode" "<MODE>")])
-
-(define_insn "<sse>_ucomi<round_saeonly_name>"
-  [(set (reg:CCFPU FLAGS_REG)
-       (compare:CCFPU
-         (vec_select:MODEF
-           (match_operand:<ssevecmode> 0 "register_operand" "v")
-           (parallel [(const_int 0)]))
-         (vec_select:MODEF
-           (match_operand:<ssevecmode> 1 "<round_saeonly_nimm_scalar_predicate>" "<round_saeonly_constraint>")
-           (parallel [(const_int 0)]))))]
-  "SSE_FLOAT_MODE_P (<MODE>mode)"
-  "%vucomi<ssemodesuffix>\t{<round_saeonly_op2>%1, %0|%0, %<iptr>1<round_saeonly_op2>}"
+  "%v<unord>comi<ssemodesuffix>\t{<round_saeonly_op2>%1, %0|%0, %<iptr>1<round_saeonly_op2>}"
   [(set_attr "type" "ssecomi")
    (set_attr "prefix" "maybe_vex")
    (set_attr "prefix_rep" "0")
index c93a526343555015e5a1e64bdd2587c82008f63c..d9100c8d6b0e9575427cafa1646663edfc518dbb 100644 (file)
@@ -37,8 +37,7 @@
    V8DI  V4DI  V2DI
    V16SF V8SF  V4SF
    V8DF  V4DF  V2DF
-   QI HI SI DI SF DF
-   CCFP CCFPU])
+   QI HI SI DI SF DF])
 
 (define_subst_attr "mask_name" "mask" "" "_mask")
 (define_subst_attr "mask_applied" "mask" "false" "true")
          UNSPEC_EMBEDDED_ROUNDING))
 ])
 
+(define_subst "round_saeonly"
+  [(set (match_operand:CCFP 0)
+        (match_operand:CCFP 1))]
+  "TARGET_AVX512F"
+  [(set (match_dup 0)
+       (unspec:CCFP [(match_dup 1)
+         (match_operand:SI 2 "const48_operand")]
+         UNSPEC_EMBEDDED_ROUNDING))
+])
+
 (define_subst_attr "round_expand_name" "round_expand" "" "_round")
 (define_subst_attr "round_expand_nimm_predicate" "round_expand" "nonimmediate_operand" "register_operand")
 (define_subst_attr "round_expand_operand" "round_expand" "" ", operands[5]")
index 62f7d7b965373daafdb90b16a68a092779d23009..83fc47626710055d6540d027f07b06f37e9f8440 100644 (file)
@@ -1560,12 +1560,6 @@ subst_stack_regs_pat (rtx_insn *insn, stack_ptr regstack, rtx pat)
 
        switch (GET_CODE (pat_src))
          {
-         case COMPARE:
-           /* `fcomi' insn can't pop two regs.  */
-           compare_for_stack_reg (insn, regstack, pat_src,
-                                  REGNO (*dest) != FLAGS_REG);
-           break;
-
          case CALL:
            {
              int count;
@@ -1966,31 +1960,35 @@ subst_stack_regs_pat (rtx_insn *insn, stack_ptr regstack, rtx pat)
                replace_reg (src2, FIRST_STACK_REG + 1);
                break;
 
-             case UNSPEC_SAHF:
-               /* (unspec [(unspec [(compare)] UNSPEC_FNSTSW)] UNSPEC_SAHF)
-                  The combination matches the PPRO fcomi instruction.  */
-
-               pat_src = XVECEXP (pat_src, 0, 0);
-               gcc_assert (GET_CODE (pat_src) == UNSPEC);
-               gcc_assert (XINT (pat_src, 1) == UNSPEC_FNSTSW);
-               /* Fall through.  */
-
              case UNSPEC_FNSTSW:
                /* Combined fcomp+fnstsw generated for doing well with
                   CSE.  When optimizing this would have been broken
                   up before now.  */
 
                pat_src = XVECEXP (pat_src, 0, 0);
-               gcc_assert (GET_CODE (pat_src) == COMPARE);
+               if (GET_CODE (pat_src) == COMPARE)
+                 goto do_compare;
 
-               compare_for_stack_reg (insn, regstack, pat_src, true);
-               break;
+               /* Fall through.  */
+
+             case UNSPEC_NOTRAP:
+
+               pat_src = XVECEXP (pat_src, 0, 0);
+               gcc_assert (GET_CODE (pat_src) == COMPARE);
+               goto do_compare;
 
              default:
                gcc_unreachable ();
              }
            break;
 
+         case COMPARE:
+         do_compare:
+           /* `fcomi' insn can't pop two regs.  */
+           compare_for_stack_reg (insn, regstack, pat_src,
+                                  REGNO (*dest) != FLAGS_REG);
+           break;
+
          case IF_THEN_ELSE:
            /* This insn requires the top of stack to be the destination.  */
 
index b8dac7e625a95eb187702aacffe124bc8a617f6a..f227e7ec36f332c8ce4c3a572d152cee7643dfe4 100644 (file)
@@ -1,3 +1,8 @@
+2017-10-27  Uros Bizjak  <ubizjak@gmail.com>
+
+       PR target/82692
+       * gcc.dg/torture/pr82692.c: New test.
+
 2017-10-27  Will Schmidt  <will_schmidt@vnet.ibm.com>
 
        * gcc.target/powerpc/fold-vec-neg-char.c: New.
diff --git a/gcc/testsuite/gcc.target/i386/pr82692.c b/gcc/testsuite/gcc.target/i386/pr82692.c
new file mode 100644 (file)
index 0000000..7f16804
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#include <fenv.h>
+
+extern void abort (void);
+extern void exit (int);
+
+double __attribute__ ((noinline, noclone))
+foo (double x)
+{
+  if (__builtin_islessequal (x, 0.0) || __builtin_isgreater (x, 1.0))
+    return x + x;
+  return x * x;
+}
+
+int
+main (void)
+{
+  volatile double x = foo (__builtin_nan (""));
+  if (fetestexcept (FE_INVALID))
+    abort ();
+  exit (0);
+}