Hi, This patch fixes the ICE in PR100736. It adds a reverse condition comparison when the condition code can be reversed and finite-math-only is set.
Bootstrapped and tested on powerpc64-linux BE and LE with no regressions. Is this okay for trunk? Any recommendations? Thanks a lot. ChangeLog 2021-12-20 Haochen Gui <guih...@linux.ibm.com> gcc/ * config/rs6000/altivec.md (bcd<bcd_add_sub>_test_<mode>): Named. (bcd<bcd_add_sub>_<code>_<mode>): Reverse compare condition if finite-math-only is set. * config/rs6000/rs6000-protos.c (rs6000_reverse_compare): Defined. * config/rs6000/rs6000.c (rs6000_emit_sCOND): Refactored. Call rs6000_reverse_compare if the condition code can be reversed. (rs6000_reverse_compare): Implemented. gcc/testsuite/ * gcc.target/powerpc/pr100736.h: New. * gcc.target/powerpc/pr100736.finite.c: New. * gcc.target/powerpc/pr100736.infinite.c: New. patch.diff diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md index ef432112333..cc40edc5381 100644 --- a/gcc/config/rs6000/altivec.md +++ b/gcc/config/rs6000/altivec.md @@ -4412,7 +4412,7 @@ (define_insn "bcd<bcd_add_sub>_<mode>" ;; UNORDERED test on an integer type (like V1TImode) is not defined. The type ;; probably should be one that can go in the VMX (Altivec) registers, so we ;; can't use DDmode or DFmode. -(define_insn "*bcd<bcd_add_sub>_test_<mode>" +(define_insn "bcd<bcd_add_sub>_test_<mode>" [(set (reg:CCFP CR6_REGNO) (compare:CCFP (unspec:V2DF [(match_operand:VBCD 1 "register_operand" "v") @@ -4539,6 +4539,18 @@ (define_expand "bcd<bcd_add_sub>_<code>_<mode>" "TARGET_P8_VECTOR" { operands[4] = CONST0_RTX (V2DFmode); + emit_insn (gen_bcd<bcd_add_sub>_test_<mode> (operands[0], operands[1], + operands[2], operands[3], + operands[4])); + rtx cr6 = gen_rtx_REG (CCFPmode, CR6_REGNO); + rtx condition_rtx = gen_rtx_<CODE> (SImode, cr6, const0_rtx); + if (flag_finite_math_only) + { + condition_rtx = rs6000_reverse_compare (condition_rtx); + PUT_MODE (condition_rtx, SImode); + } + emit_insn (gen_rtx_SET (operands[0], condition_rtx)); + DONE; }) (define_insn "*bcdinvalid_<mode>" diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 14f6b313105..9b93e26bec2 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -114,6 +114,7 @@ extern enum rtx_code rs6000_reverse_condition (machine_mode, extern rtx rs6000_emit_eqne (machine_mode, rtx, rtx, rtx); extern rtx rs6000_emit_fp_cror (rtx_code, machine_mode, rtx); extern void rs6000_emit_sCOND (machine_mode, rtx[]); +extern rtx rs6000_reverse_compare (rtx); extern void rs6000_emit_cbranch (machine_mode, rtx[]); extern char * output_cbranch (rtx, const char *, int, rtx_insn *); extern const char * output_probe_stack_range (rtx, rtx, rtx); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 5e129986516..2f3dd311396 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -15653,19 +15653,14 @@ rs6000_emit_fp_cror (rtx_code code, machine_mode mode, rtx x) return cc; } -void -rs6000_emit_sCOND (machine_mode mode, rtx operands[]) +rtx +rs6000_reverse_compare (rtx condition_rtx) { - rtx condition_rtx = rs6000_generate_compare (operands[1], mode); rtx_code cond_code = GET_CODE (condition_rtx); - - if (FLOAT_MODE_P (mode) && HONOR_NANS (mode) - && !(FLOAT128_VECTOR_P (mode) && !TARGET_FLOAT128_HW)) - ; - else if (cond_code == NE - || cond_code == GE || cond_code == LE - || cond_code == GEU || cond_code == LEU - || cond_code == ORDERED || cond_code == UNGE || cond_code == UNLE) + if (cond_code == NE + || cond_code == GE || cond_code == LE + || cond_code == GEU || cond_code == LEU + || cond_code == ORDERED || cond_code == UNGE || cond_code == UNLE) { rtx not_result = gen_reg_rtx (CCEQmode); rtx not_op, rev_cond_rtx; @@ -15679,6 +15674,19 @@ rs6000_emit_sCOND (machine_mode mode, rtx operands[]) emit_insn (gen_rtx_SET (not_result, not_op)); condition_rtx = gen_rtx_EQ (VOIDmode, not_result, const0_rtx); } + return condition_rtx; +} + +void +rs6000_emit_sCOND (machine_mode mode, rtx operands[]) +{ + rtx condition_rtx = rs6000_generate_compare (operands[1], mode); + + if (FLOAT_MODE_P (mode) && HONOR_NANS (mode) + && !(FLOAT128_VECTOR_P (mode) && !TARGET_FLOAT128_HW)) + ; + else + condition_rtx = rs6000_reverse_compare (condition_rtx); machine_mode op_mode = GET_MODE (XEXP (operands[1], 0)); if (op_mode == VOIDmode) diff --git a/gcc/testsuite/gcc.target/powerpc/pr100736.finite.c b/gcc/testsuite/gcc.target/powerpc/pr100736.finite.c new file mode 100644 index 00000000000..43c85d4a2c1 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr100736.finite.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target lp64 } } */ +/* { dg-require-effective-target powerpc_p8vector_ok } */ +/* { dg-options "-mdejagnu-cpu=power8 -O2 -ffinite-math-only" } */ + +/* Source code for the test in pr100736.h */ +#include "pr100736.h" + +/* { dg-final { scan-assembler {\mcrnot\M} } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/pr100736.h b/gcc/testsuite/gcc.target/powerpc/pr100736.h new file mode 100644 index 00000000000..b1b3dc08247 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr100736.h @@ -0,0 +1,12 @@ +/* This test code is included into pr100736.infinite.c and pr100736.finite.c + The two files have the tests for finite-math-only set and not set. + + finite-math-only: bcdsub.;crnot;mfcr;rlwinm. + not set: bcdsub.;cror;mfcr;rlwinm. */ + +typedef __attribute__ ((altivec (vector__))) unsigned char v; + +int foo (v a, v b) +{ + return __builtin_vec_bcdsub_ge (a, b, 0); +} diff --git a/gcc/testsuite/gcc.target/powerpc/pr100736.infinite.c b/gcc/testsuite/gcc.target/powerpc/pr100736.infinite.c new file mode 100644 index 00000000000..881f18794f5 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr100736.infinite.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target lp64 } } */ +/* { dg-require-effective-target powerpc_p8vector_ok } */ +/* { dg-options "-mdejagnu-cpu=power8 -O2" } */ + +/* Source code for the test in pr100736.h */ +#include "pr100736.h" + +/* { dg-final { scan-assembler {\mcror\M} } } */