Message ID | 6466472.8JuR9QNRED@polaris |
---|---|
State | New |
Headers | show |
On Wed, May 29, 2013 at 10:33 AM, Eric Botcazou <ebotcazou@adacore.com> wrote: > Hi, > > on most platforms the Ada compiler doesn't enable trap-on-FP-exceptions, so > it's appropriate to set -fno-trapping-math there, which has been done in > http://gcc.gnu.org/ml/gcc-patches/2013-05/msg01461.html > > However doing so can have an adverse effect if the architecture doesn't have a > sufficiently rich set of FP comparison instructions because -fno-trapping-math > allows the middle-end and the optimizers to turn the negation of signaling FP > comparison operators into quiet FP unordered operators, e.g. not(<) into !>= > and the quiet unordered operators aren't supported universally. The effect is > that you need 2 comparisons instead of just 1 to achieve the desired result. > > The first (surprising) example is the IA-64, which has ORDERED and UNORDERED > but not UNLT/UNLE/UNGT/UNGE because the unordered comparison instructions are > signaling (since they are the negation of the signaling ordered comparisons). > Therefore the fix is to make it possible to use these unordered comparison > instructions, which are signaling, for the quiet unordered operators when the > flag -fno-trapping-math is in effect. As a matter of fact, the support was > already there (e.g. in ia64_print_operand) but it was rightfully disabled. > > Tested on IA-64/Linux and IA-64/HP-UX, OK for the mainline? Did you check that this doesn't cause traps on SPEC CPU 2000 / 2006 when compiled with -ffast-math (something we generally want to support, even if it is on the border of validity)? Thanks, Richard. > 2013-05-29 Eric Botcazou <ebotcazou@adacore.com> > > * config/ia64/predicates.md (ia64_cbranch_operator): Accept unordered > comparison operators when -fno-trapping-math is in effect. > * config/ia64/ia64.c (ia64_expand_compare): Add support for unordered > comparison operators in TFmode and assert that unsupported operators > cannot reach here. > (ia64_print_operand): Likewise. > > > -- > Eric Botcazou
> Did you check that this doesn't cause traps on SPEC CPU 2000 / 2006 > when compiled with -ffast-math (something we generally want to support, > even if it is on the border of validity)? Do you mean SPECfp because some benchmarks might enable trap-on-FP-exceptions and you nevertheless compile them with -ffast-math?
On Wed, May 29, 2013 at 11:19 AM, Eric Botcazou <ebotcazou@adacore.com> wrote: >> Did you check that this doesn't cause traps on SPEC CPU 2000 / 2006 >> when compiled with -ffast-math (something we generally want to support, >> even if it is on the border of validity)? > > Do you mean SPECfp because some benchmarks might enable trap-on-FP-exceptions > and you nevertheless compile them with -ffast-math? Yes, SPECfp. And no, I don't think they enable trap-on-FP-exceptions but they may cause exceptional behavior even if -fno-trapping-math is specified (not sure if IA64 masks exceptions on the comparisons?) Richard. > -- > Eric Botcazou
> Yes, SPECfp. And no, I don't think they enable trap-on-FP-exceptions but > they may cause exceptional behavior even if -fno-trapping-math is specified > (not sure if IA64 masks exceptions on the comparisons?) The manual says that QNaNs signal Invalid for the signaling FP comparison operators and that you need to enable the Invalid Operation trap to get a fault from Invalid. The IEEE standard also says that comparisons by way of unordered signaling predicates raise the "invalid operation exception", just like the regular operations. That being said, I can double-check.
Index: config/ia64/predicates.md =================================================================== --- config/ia64/predicates.md (revision 199343) +++ config/ia64/predicates.md (working copy) @@ -568,9 +568,15 @@ (define_predicate "fr_reg_or_0_operand" (match_test "op == CONST0_RTX (GET_MODE (op))")))) ;; Return 1 if OP is a valid comparison operator for "cbranch" instructions. +;; If we're assuming that FP operations cannot generate user-visible traps, +;; then we can use the FP unordered-signaling instructions to implement the +;; FP unordered-quiet comparison predicates. (define_predicate "ia64_cbranch_operator" - (ior (match_operand 0 "ordered_comparison_operator") - (match_code "ordered,unordered"))) + (if_then_else (match_test "flag_trapping_math") + (ior (match_operand 0 "ordered_comparison_operator") + (match_code "ordered,unordered")) + (and (match_operand 0 "comparison_operator") + (not (match_code "uneq,ltgt"))))) ;; True if this is a comparison operator, which accepts a normal 8-bit ;; signed immediate operand. Index: config/ia64/ia64.c =================================================================== --- config/ia64/ia64.c (revision 199343) +++ config/ia64/ia64.c (working copy) @@ -1756,7 +1756,7 @@ ia64_expand_compare (rtx *expr, rtx *op0 else if (TARGET_HPUX && GET_MODE (*op0) == TFmode) { enum qfcmp_magic { - QCMP_INV = 1, /* Raise FP_INVALID on SNaN as a side effect. */ + QCMP_INV = 1, /* Raise FP_INVALID on NaNs as a side effect. */ QCMP_UNORD = 2, QCMP_EQ = 4, QCMP_LT = 8, @@ -1770,21 +1770,27 @@ ia64_expand_compare (rtx *expr, rtx *op0 switch (code) { /* 1 = equal, 0 = not equal. Equality operators do - not raise FP_INVALID when given an SNaN operand. */ + not raise FP_INVALID when given a NaN operand. */ case EQ: magic = QCMP_EQ; ncode = NE; break; case NE: magic = QCMP_EQ; ncode = EQ; break; /* isunordered() from C99. */ case UNORDERED: magic = QCMP_UNORD; ncode = NE; break; case ORDERED: magic = QCMP_UNORD; ncode = EQ; break; /* Relational operators raise FP_INVALID when given - an SNaN operand. */ + a NaN operand. */ case LT: magic = QCMP_LT |QCMP_INV; ncode = NE; break; case LE: magic = QCMP_LT|QCMP_EQ|QCMP_INV; ncode = NE; break; case GT: magic = QCMP_GT |QCMP_INV; ncode = NE; break; case GE: magic = QCMP_GT|QCMP_EQ|QCMP_INV; ncode = NE; break; - /* FUTURE: Implement UNEQ, UNLT, UNLE, UNGT, UNGE, LTGT. - Expanders for buneq etc. weuld have to be added to ia64.md - for this to be useful. */ + /* Unordered relational operators do not raise FP_INVALID + when given a NaN operand. */ + case UNLT: magic = QCMP_LT |QCMP_UNORD; ncode = NE; break; + case UNLE: magic = QCMP_LT|QCMP_EQ|QCMP_UNORD; ncode = NE; break; + case UNGT: magic = QCMP_GT |QCMP_UNORD; ncode = NE; break; + case UNGE: magic = QCMP_GT|QCMP_EQ|QCMP_UNORD; ncode = NE; break; + /* Not supported. */ + case UNEQ: + case LTGT: default: gcc_unreachable (); } @@ -5279,6 +5285,9 @@ ia64_print_operand (FILE * file, rtx x, case UNGE: str = "nlt"; break; + case UNEQ: + case LTGT: + gcc_unreachable (); default: str = GET_RTX_NAME (GET_CODE (x)); break;