From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1005) id 88B003858D20; Thu, 17 Feb 2022 17:47:11 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 88B003858D20 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Michael Meissner To: gcc-cvs@gcc.gnu.org Subject: [gcc(refs/users/meissner/heads/work078)] Don't do int cmoves for IEEE comparisons. X-Act-Checkin: gcc X-Git-Author: Michael Meissner X-Git-Refname: refs/users/meissner/heads/work078 X-Git-Oldrev: 62fe8284eb5e6c15cb666e7cef2b80fc08185ae7 X-Git-Newrev: 8946d7f6e2239ad5c2c91da3d50bc0250e7e0162 Message-Id: <20220217174711.88B003858D20@sourceware.org> Date: Thu, 17 Feb 2022 17:47:11 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 17 Feb 2022 17:47:11 -0000 https://gcc.gnu.org/g:8946d7f6e2239ad5c2c91da3d50bc0250e7e0162 commit 8946d7f6e2239ad5c2c91da3d50bc0250e7e0162 Author: Michael Meissner Date: Thu Feb 17 12:40:15 2022 -0500 Don't do int cmoves for IEEE comparisons. Protect int cmove from raising an assertion if it is trying to do an int conditional move where the test involves floating point comparisons that can't easily be reversed due to NaNs. The code used to generate the condition, and possibly reverse the condition if ISEL could not handle it by rewriting the OP in the comparison rtx. Unfortunately there are some conditions like UNLE that can't easily be reversed due to NaNs. The patch changes this so that it does the reversal before generating the comparison. If the comparison cannot be reversed, it just returns false, saying that we can't do an int conditional move in this case. 2022-02-17 Michael Meissner gcc/ PR target/104256 * config/rs6000/rs6000.cc (rs6000_emit_int_cmove): Don't do integer conditional moves if the test needs to be reversed and there isn't a direct reverse comparison. gcc/testsuite/ PR target/104256 * gcc.target/powerpc/ppc-fortran/pr104254.f90: New test. Diff: --- gcc/config/rs6000/rs6000.cc | 36 ++++++++++++---------- .../gcc.target/powerpc/ppc-fortran/pr104254.f90 | 25 +++++++++++++++ 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index f56cf66313a..15d324d13aa 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -16174,18 +16174,35 @@ rs6000_emit_int_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) { rtx condition_rtx, cr; machine_mode mode = GET_MODE (dest); - enum rtx_code cond_code; rtx (*isel_func) (rtx, rtx, rtx, rtx, rtx); bool signedp; if (mode != SImode && (!TARGET_POWERPC64 || mode != DImode)) return false; + /* Swap the comparison if isel can't handle it directly. Don't generate int + cmoves if we can't swap the condition code due to NaNs. */ + enum rtx_code op_code = GET_CODE (op); + if (op_code != LT && op_code != GT && op_code != LTU && op_code != GTU + && op_code != EQ) + { + if (!COMPARISON_P (op)) + return false; + + enum rtx_code rev_code = reverse_condition (op_code); + if (rev_code == UNKNOWN) + return false; + + std::swap (false_cond, true_cond); + op = gen_rtx_fmt_ee (rev_code, GET_MODE (op), + XEXP (op, 0), + XEXP (op, 1)); + } + /* We still have to do the compare, because isel doesn't do a compare, it just looks at the CRx bits set by a previous compare instruction. */ condition_rtx = rs6000_generate_compare (op, mode); - cond_code = GET_CODE (condition_rtx); cr = XEXP (condition_rtx, 0); signedp = GET_MODE (cr) == CCmode; @@ -16193,21 +16210,6 @@ rs6000_emit_int_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) ? (signedp ? gen_isel_signed_si : gen_isel_unsigned_si) : (signedp ? gen_isel_signed_di : gen_isel_unsigned_di)); - switch (cond_code) - { - case LT: case GT: case LTU: case GTU: case EQ: - /* isel handles these directly. */ - break; - - default: - /* We need to swap the sense of the comparison. */ - { - std::swap (false_cond, true_cond); - PUT_CODE (condition_rtx, reverse_condition (cond_code)); - } - break; - } - false_cond = force_reg (mode, false_cond); if (true_cond != const0_rtx) true_cond = force_reg (mode, true_cond); diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fortran/pr104254.f90 b/gcc/testsuite/gcc.target/powerpc/ppc-fortran/pr104254.f90 new file mode 100644 index 00000000000..d1bfab23482 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/ppc-fortran/pr104254.f90 @@ -0,0 +1,25 @@ +! { dg-do compile } +! { dg-require-effective-target powerpc_p9vector_ok } +! { dg-options "-mdejagnu-cpu=power9 -O1 -fnon-call-exceptions" } + +! PR target/104254. GCC would raise an assertion error if this program was +! compiled with -O1 and -fnon-call-exceptions on a power9 or higher. The issue +! occurs because at this optimization level, the compiler is trying to make +! a conditional move to store integers using a 32-bit floating point compare. +! It wants to use UNLE, which is not supported for integer modes. + + real :: a(2), nan + real, allocatable :: c(:) + integer :: ia(1) + + nan = 0.0 + nan = 0.0/nan + + a(:) = nan + ia = maxloc (a) + if (ia(1).ne.1) STOP 1 + + allocate (c(1)) + c(:) = nan + deallocate (c) +end