From patchwork Fri Aug 10 20:47:28 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Janne Blomqvist X-Patchwork-Id: 956473 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-483520-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="iDkaHNaq"; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="XZ8xARfI"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41nHJB50lFz9s4Z for ; Sat, 11 Aug 2018 06:47:54 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id; q=dns; s=default; b=e5P/HazsIv4F xuwZ96Zb4Z5rv77njJ7fOg5m3sk2CCZpk2xGcTSkX/EVBv5t02u064BGrlh3GGvV SfGjjSLk5ag3S/9XOsft82MuWmP/hy2ZK7VodEzesYtWuoQHScYlRQAcfZICMgfL OYCUxJ/Y9ULqgsI+AxgxFt3rdpihRRY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id; s=default; bh=LwbjFh3FnoazF1AuKa IcxHPy/N4=; b=iDkaHNaqlTndj+P3UT8g7kAFjzeVki5eFktdZXhnSN3Lqm2vII 0Y8wRxv08t3qKtaFxvxWzi+fWDmFlSm9ddRfJX06lAgVhPFF9Fd7rmjroXcaB0Q7 DQ/RWvY83qIZIl5+YPBZmuNJF2kZJZSPjCGJgtqv7vqqi9VFxsIbDy1Kg= Received: (qmail 110309 invoked by alias); 10 Aug 2018 20:47:47 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 110280 invoked by uid 89); 10 Aug 2018 20:47:46 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=STOP, NULL_TREE, null_tree, Otherwise X-HELO: mail-lj1-f179.google.com Received: from mail-lj1-f179.google.com (HELO mail-lj1-f179.google.com) (209.85.208.179) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 10 Aug 2018 20:47:44 +0000 Received: by mail-lj1-f179.google.com with SMTP id v9-v6so8153224ljk.4; Fri, 10 Aug 2018 13:47:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=qiy23plsbSFPyxTOSdZCUigHga1aF2ZBnBV+/z0TH5Y=; b=XZ8xARfIT9JvZlY+3WG16ilpY7Lj8lXcolOjM2fmNyWGBH35JAFw+ZtbclVGaUHjbw FdCWyEQoTX4rOqODFoGPSalSkTtO/+5W0LmI2K7XjZo/Fv1/eaE0VgvYDVBh/sFKFYoT BkPfIiY2ZKuLBTKHKKc78e0HoaQ+rgQpTk/+lQtstz5X6zYGN96O/xDyTKBMF3sCuYa4 Aq5xEY1ScLa+45vRNVdUUKDLwKeQhc5wS5WAmPc3A4+7qrpmbv5qNG1gPqgADymVZUkY CGr6OqOCDxKE7Vzdrwnivgm5ZgTfV4fogKtK5Q7lIbwSCl5l01l8n9baSX2hKTLN7ys6 JVxw== Received: from dt.lan (88-114-247-254.elisa-laajakaista.fi. [88.114.247.254]) by smtp.gmail.com with ESMTPSA id g23-v6sm2114603lfl.42.2018.08.10.13.47.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 10 Aug 2018 13:47:40 -0700 (PDT) From: Janne Blomqvist To: fortran@gcc.gnu.org, gcc-patches@gcc.gnu.org Cc: Janne Blomqvist Subject: [PATCH] Unconditionally use MAX_EXPR/MIN_EXPR for MAX/MIN intrinsics Date: Fri, 10 Aug 2018 23:47:28 +0300 Message-Id: <20180810204728.20191-1-blomqvist.janne@gmail.com> For floating point types, the question is what MAX(a, NaN) or MIN(a, NaN) should return (where "a" is a normal number). There are valid usecases for returning either one, but the Fortran standard doesn't specify which one should be chosen. Also, there is no consensus among other tested compilers. In short, it's a mess. So lets just do whatever is fastest, which is using MAX_EXPR/MIN_EXPR which are not defined to do anything in particular if one of the operands is a NaN. Regtested on x86_64-pc-linux-gnu, Ok for trunk? gcc/fortran/ChangeLog: 2018-08-10 Janne Blomqvist * trans-intrinsic.c (gfc_conv_intrinsic_minmax): Use MAX_EXPR/MIN_EXPR unconditionally for real arguments. gcc/testsuite/ChangeLog: 2018-08-10 Janne Blomqvist * gfortran.dg/nan_1.f90: Remove tests that test MAX/MIN with NaNs. --- gcc/fortran/trans-intrinsic.c | 55 ++++++----------------------- gcc/testsuite/gfortran.dg/nan_1.f90 | 35 ------------------ 2 files changed, 10 insertions(+), 80 deletions(-) diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index c9b5479740c..190fde66a8d 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -3914,8 +3914,6 @@ gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op) mvar = gfc_create_var (type, "M"); gfc_add_modify (&se->pre, mvar, args[0]); - internal_fn ifn = op == GT_EXPR ? IFN_FMAX : IFN_FMIN; - for (i = 1, argexpr = argexpr->next; i < nargs; i++, argexpr = argexpr->next) { tree cond = NULL_TREE; @@ -3936,49 +3934,16 @@ gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op) val = gfc_evaluate_now (val, &se->pre); tree calc; - /* If we dealing with integral types or we don't care about NaNs - just do a MIN/MAX_EXPR. */ - if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)) - { - - tree_code code = op == GT_EXPR ? MAX_EXPR : MIN_EXPR; - calc = fold_build2_loc (input_location, code, type, - convert (type, val), mvar); - tmp = build2_v (MODIFY_EXPR, mvar, calc); - - } - /* If we care about NaNs and we have internal functions available for - fmin/fmax to perform the comparison, use those. */ - else if (SCALAR_FLOAT_TYPE_P (type) - && direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED)) - { - calc = build_call_expr_internal_loc (input_location, ifn, type, - 2, mvar, convert (type, val)); - tmp = build2_v (MODIFY_EXPR, mvar, calc); - - } - /* Otherwise expand to: - mvar = a1; - if (a2 .op. mvar || isnan (mvar)) - mvar = a2; - if (a3 .op. mvar || isnan (mvar)) - mvar = a3; - ... */ - else - { - tree isnan = build_call_expr_loc (input_location, - builtin_decl_explicit (BUILT_IN_ISNAN), - 1, mvar); - tmp = fold_build2_loc (input_location, op, logical_type_node, - convert (type, val), mvar); - - tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, - logical_type_node, tmp, - fold_convert (logical_type_node, isnan)); - tmp = build3_v (COND_EXPR, tmp, - build2_v (MODIFY_EXPR, mvar, convert (type, val)), - build_empty_stmt (input_location)); - } + /* For floating point types, the question is what MAX(a, NaN) or + MIN(a, NaN) should return (where "a" is a normal number). + There are valid usecase for returning either one, but the + Fortran standard doesn't specify which one should be chosen. + Also, there is no consensus among other tested compilers. In + short, it's a mess. So lets just do whatever is fastest. */ + tree_code code = op == GT_EXPR ? MAX_EXPR : MIN_EXPR; + calc = fold_build2_loc (input_location, code, type, + convert (type, val), mvar); + tmp = build2_v (MODIFY_EXPR, mvar, calc); if (cond != NULL_TREE) tmp = build3_v (COND_EXPR, cond, tmp, diff --git a/gcc/testsuite/gfortran.dg/nan_1.f90 b/gcc/testsuite/gfortran.dg/nan_1.f90 index e64b4ce65e1..1b39cc1f21c 100644 --- a/gcc/testsuite/gfortran.dg/nan_1.f90 +++ b/gcc/testsuite/gfortran.dg/nan_1.f90 @@ -66,35 +66,12 @@ program test if (isinf(-nan) .or. isinf(-large) .or. .not. isinf(-inf)) STOP 4 ! Check that MIN and MAX behave correctly - if (max(2.0, nan) /= 2.0) STOP 5 - if (min(2.0, nan) /= 2.0) STOP 6 - if (max(nan, 2.0) /= 2.0) STOP 7 - if (min(nan, 2.0) /= 2.0) STOP 8 - - if (max(2.d0, nan) /= 2.d0) STOP 9! { dg-warning "Extension: Different type kinds" } - if (min(2.d0, nan) /= 2.d0) STOP 10! { dg-warning "Extension: Different type kinds" } - if (max(nan, 2.d0) /= 2.d0) STOP 11! { dg-warning "Extension: Different type kinds" } - if (min(nan, 2.d0) /= 2.d0) STOP 12! { dg-warning "Extension: Different type kinds" } if (.not. isnan(min(nan,nan))) STOP 13 if (.not. isnan(max(nan,nan))) STOP 14 ! Same thing, with more arguments - if (max(3.0, 2.0, nan) /= 3.0) STOP 15 - if (min(3.0, 2.0, nan) /= 2.0) STOP 16 - if (max(3.0, nan, 2.0) /= 3.0) STOP 17 - if (min(3.0, nan, 2.0) /= 2.0) STOP 18 - if (max(nan, 3.0, 2.0) /= 3.0) STOP 19 - if (min(nan, 3.0, 2.0) /= 2.0) STOP 20 - - if (max(3.d0, 2.d0, nan) /= 3.d0) STOP 21! { dg-warning "Extension: Different type kinds" } - if (min(3.d0, 2.d0, nan) /= 2.d0) STOP 22! { dg-warning "Extension: Different type kinds" } - if (max(3.d0, nan, 2.d0) /= 3.d0) STOP 23! { dg-warning "Extension: Different type kinds" } - if (min(3.d0, nan, 2.d0) /= 2.d0) STOP 24! { dg-warning "Extension: Different type kinds" } - if (max(nan, 3.d0, 2.d0) /= 3.d0) STOP 25! { dg-warning "Extension: Different type kinds" } - if (min(nan, 3.d0, 2.d0) /= 2.d0) STOP 26! { dg-warning "Extension: Different type kinds" } - if (.not. isnan(min(nan,nan,nan))) STOP 27 if (.not. isnan(max(nan,nan,nan))) STOP 28 if (.not. isnan(min(nan,nan,nan,nan))) STOP 29 @@ -105,20 +82,8 @@ program test ! Large values, INF and NaNs if (.not. isinf(max(large, inf))) STOP 33 if (isinf(min(large, inf))) STOP 34 - if (.not. isinf(max(nan, large, inf))) STOP 35 - if (isinf(min(nan, large, inf))) STOP 36 - if (.not. isinf(max(large, nan, inf))) STOP 37 - if (isinf(min(large, nan, inf))) STOP 38 - if (.not. isinf(max(large, inf, nan))) STOP 39 - if (isinf(min(large, inf, nan))) STOP 40 if (.not. isinf(min(-large, -inf))) STOP 41 if (isinf(max(-large, -inf))) STOP 42 - if (.not. isinf(min(nan, -large, -inf))) STOP 43 - if (isinf(max(nan, -large, -inf))) STOP 44 - if (.not. isinf(min(-large, nan, -inf))) STOP 45 - if (isinf(max(-large, nan, -inf))) STOP 46 - if (.not. isinf(min(-large, -inf, nan))) STOP 47 - if (isinf(max(-large, -inf, nan))) STOP 48 end program test