https://gcc.gnu.org/g:89a0027e79e90ac5cf8909c28d05cae569646ede
commit 89a0027e79e90ac5cf8909c28d05cae569646ede Author: Michael Meissner <[email protected]> Date: Mon Dec 8 21:29:50 2025 -0500 Revert changes Diff: --- gcc/config/rs6000/linux64.h | 5 +- gcc/config/rs6000/predicates.md | 11 + gcc/config/rs6000/rs6000.cc | 121 ++++++++-- gcc/config/rs6000/rs6000.md | 305 ++++++++++++++++--------- gcc/config/rs6000/vsx.md | 18 -- gcc/testsuite/gcc.target/powerpc/builtins-1.c | 2 +- gcc/testsuite/gcc.target/powerpc/p9-minmax-2.c | 175 +++++++++++++- gcc/testsuite/gcc.target/powerpc/pr108958.c | 47 ---- gcc/testsuite/gcc.target/powerpc/pr120528.c | 91 -------- gcc/testsuite/gcc.target/powerpc/pr120681.c | 34 --- gcc/testsuite/gcc.target/powerpc/pr99293.c | 22 -- 11 files changed, 485 insertions(+), 346 deletions(-) diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h index 5a6c3e199ba8..dd4d3f1f2095 100644 --- a/gcc/config/rs6000/linux64.h +++ b/gcc/config/rs6000/linux64.h @@ -564,8 +564,7 @@ extern int dot_symbols; /* Enable using prefixed PC-relative addressing on POWER10 if the ABI supports it. The ELF v2 ABI only supports PC-relative relocations for - the medium/large code models. */ + the medium code model. */ #define PCREL_SUPPORTED_BY_OS (TARGET_POWER10 && TARGET_PREFIXED \ && ELFv2_ABI_CHECK \ - && (TARGET_CMODEL == CMODEL_MEDIUM \ - || TARGET_CMODEL == CMODEL_LARGE)) + && TARGET_CMODEL == CMODEL_MEDIUM) diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index 065cdb10e10f..647e89afb6a7 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -1458,6 +1458,17 @@ (and (match_operand 0 "branch_comparison_operator") (match_code "ne,le,ge,leu,geu,ordered"))) +;; Return 1 if OP is a comparison operator suitable for floating point +;; vector/scalar comparisons that generate a -1/0 mask. +(define_predicate "fpmask_comparison_operator" + (match_code "eq,gt,ge")) + +;; Return 1 if OP is a comparison operator suitable for vector/scalar +;; comparisons that generate a 0/-1 mask (i.e. the inverse of +;; fpmask_comparison_operator). +(define_predicate "invert_fpmask_comparison_operator" + (match_code "ne,unlt,unle")) + ;; Return 1 if OP is a comparison operation suitable for integer vector/scalar ;; comparisons that generate a -1/0 mask. (define_predicate "vecint_comparison_operator" diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index 3b365b9fc30a..cb087640ebcf 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -4358,15 +4358,12 @@ rs6000_option_override_internal (bool global_init_p) && (rs6000_isa_flags_explicit & OPTION_MASK_PCREL) == 0) rs6000_isa_flags |= OPTION_MASK_PCREL; - /* -mpcrel requires medium or large code models, but we can't check - TARGET_CMODEL until after the subtarget override options are done. */ - else if (TARGET_PCREL - && TARGET_CMODEL != CMODEL_MEDIUM - && TARGET_CMODEL != CMODEL_LARGE) + /* -mpcrel requires -mcmodel=medium, but we can't check TARGET_CMODEL until + after the subtarget override options are done. */ + else if (TARGET_PCREL && TARGET_CMODEL != CMODEL_MEDIUM) { if ((rs6000_isa_flags_explicit & OPTION_MASK_PCREL) != 0) - error ("%qs requires %qs or %qs", "-mpcrel", "-mcmodel=medium", - "-mcmodel=large"); + error ("%qs requires %qs", "-mpcrel", "-mcmodel=medium"); rs6000_isa_flags &= ~OPTION_MASK_PCREL; } @@ -16338,11 +16335,98 @@ rs6000_maybe_emit_maxc_minc (rtx dest, rtx op, rtx true_cond, rtx false_cond) return true; } -/* Helper function to return true if the target supports the "C" minimum and - maximum instructions. */ +/* Possibly emit a floating point conditional move by generating a compare that + sets a mask instruction and a XXSEL select instruction. + + Move TRUE_COND to DEST if OP of the operands of the last comparison is + nonzero/true, FALSE_COND if it is zero/false. + + Return false if the operation cannot be generated, and true if we could + generate the instruction. */ + +static bool +rs6000_maybe_emit_fp_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) +{ + enum rtx_code code = GET_CODE (op); + rtx op0 = XEXP (op, 0); + rtx op1 = XEXP (op, 1); + machine_mode compare_mode = GET_MODE (op0); + machine_mode result_mode = GET_MODE (dest); + rtx compare_rtx; + rtx cmove_rtx; + rtx clobber_rtx; + + if (!can_create_pseudo_p ()) + return 0; + + /* We allow the comparison to be either SFmode/DFmode and the true/false + condition to be either SFmode/DFmode. I.e. we allow: + + float a, b; + double c, d, r; + + r = (a == b) ? c : d; + + and: + + double a, b; + float c, d, r; + + r = (a == b) ? c : d; + + but we don't allow intermixing the IEEE 128-bit floating point types with + the 32/64-bit scalar types. */ + + if (!(compare_mode == result_mode + || (compare_mode == SFmode && result_mode == DFmode) + || (compare_mode == DFmode && result_mode == SFmode))) + return false; + + switch (code) + { + case EQ: + case GE: + case GT: + break; + + case NE: + case LT: + case LE: + code = swap_condition (code); + std::swap (op0, op1); + break; + + default: + return false; + } + + /* Generate: [(parallel [(set (dest) + (if_then_else (op (cmp1) (cmp2)) + (true) + (false))) + (clobber (scratch))])]. */ + + compare_rtx = gen_rtx_fmt_ee (code, CCFPmode, op0, op1); + cmove_rtx = gen_rtx_SET (dest, + gen_rtx_IF_THEN_ELSE (result_mode, + compare_rtx, + true_cond, + false_cond)); + + clobber_rtx = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (V2DImode)); + emit_insn (gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (2, cmove_rtx, clobber_rtx))); + + return true; +} + +/* Helper function to return true if the target has instructions to do a + compare and set mask instruction that can be used with XXSEL to implement a + conditional move. It is also assumed that such a target also supports the + "C" minimum and maximum instructions. */ static bool -have_fp_minc_maxc (machine_mode mode) +have_compare_and_set_mask (machine_mode mode) { switch (mode) { @@ -16387,10 +16471,17 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) if (GET_MODE (false_cond) != result_mode) return false; - /* See if we can use the "C" minimum, "C" maximum instructions. */ - if (have_fp_minc_maxc (compare_mode) && compare_mode == result_mode - && rs6000_maybe_emit_maxc_minc (dest, op, true_cond, false_cond)) - return true; + /* See if we can use the "C" minimum, "C" maximum, and compare and set mask + instructions. */ + if (have_compare_and_set_mask (compare_mode) + && have_compare_and_set_mask (result_mode)) + { + if (rs6000_maybe_emit_maxc_minc (dest, op, true_cond, false_cond)) + return true; + + if (rs6000_maybe_emit_fp_cmove (dest, op, true_cond, false_cond)) + return true; + } /* Don't allow using floating point comparisons for integer results for now. */ @@ -21268,7 +21359,7 @@ rs6000_elf_declare_function_name (FILE *file, const char *name, tree decl) ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function"); ASM_DECLARE_RESULT (file, DECL_RESULT (decl)); - if (TARGET_CMODEL == CMODEL_LARGE && !TARGET_PCREL + if (TARGET_CMODEL == CMODEL_LARGE && rs6000_global_entry_point_prologue_needed_p ()) { char buf[256]; diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 87e42cd548fa..ff085bf9bb10 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -173,7 +173,6 @@ UNSPEC_XXSPLTIW_CONST UNSPEC_FMAX UNSPEC_FMIN - UNSPEC_ZERO_EXTEND ]) ;; @@ -970,100 +969,6 @@ (set_attr "dot" "yes") (set_attr "length" "4,8")]) -;; Optimize zero_extendsiti2 from a GPR to a GPR and then moving the GPR to a -;; VSX register -(define_peephole2 - [(set (match_operand:DI 0 "int_reg_operand") - (match_operand:DI 1 "int_reg_operand")) - (set (match_operand:DI 2 "int_reg_operand") - (const_int 0)) - (set (match_operand:TI 3 "vsx_register_operand") - (match_operand:TI 4 "int_reg_operand"))] - "TARGET_DIRECT_MOVE_64BIT - && (reg_or_subregno (operands[0]) - == reg_or_subregno (operands[4]) + !!WORDS_BIG_ENDIAN) - && (reg_or_subregno (operands[2]) - == reg_or_subregno (operands[4]) + !WORDS_BIG_ENDIAN) - && peep2_reg_dead_p (3, operands[4])" - [(set (match_dup 3) - (unspec:TI [(match_dup 1)] UNSPEC_ZERO_EXTEND))]) - -(define_insn "*zero_extendsiti2_vsx" - [(set (match_operand:TI 0 "vsx_register_operand" "=wa") - (unspec:TI [(match_operand:DI 1 "int_reg_operand" "r")] - UNSPEC_ZERO_EXTEND))] - "TARGET_DIRECT_MOVE_64BIT" - "mtvsrdd %x0,0,%1" - [(set_attr "type" "mtvsr")]) - -;; On power10, optimize zero extending a QI/HI/SI/DImode value from memory that -;; is going to a vector register target by generating a LXVR{B,H,W,D}X -;; instruction without creating the TImode value in a GPR and using MTVSRDD to -;; move it to the vector register. -(define_peephole2 - [(set (match_operand:DI 0 "int_reg_operand") - (match_operand:DI 1 "memory_operand")) - (set (match_operand:DI 2 "base_reg_operand") - (const_int 0)) - (set (match_operand:TI 3 "vsx_register_operand") - (match_operand:TI 4 "int_reg_operand"))] - "TARGET_POWER10 && TARGET_POWERPC64 - && (reg_or_subregno (operands[0]) - == reg_or_subregno (operands[4]) + !!WORDS_BIG_ENDIAN) - && (reg_or_subregno (operands[2]) - == reg_or_subregno (operands[4]) + !WORDS_BIG_ENDIAN) - && peep2_reg_dead_p (3, operands[4]) - && (REG_P (XEXP (operands[1], 0)) - || SUBREG_P (XEXP (operands[1], 0)) - || GET_CODE (XEXP (operands[1], 0)) == PLUS)" - [(set (match_dup 3) - (zero_extend:TI (match_dup 5)))] -{ - rtx mem = operands[1]; - rtx addr = XEXP (mem, 0); - - if (indexed_or_indirect_address (addr, DImode)) - operands[5] = mem; - else - { - rtx op2 = operands[2]; - emit_insn (gen_rtx_SET (op2, addr)); - operands[5] = change_address (mem, DImode, op2); - } -}) - -(define_peephole2 - [(set (match_operand:DI 0 "int_reg_operand") - (zero_extend:DI - (match_operand:QHSI 1 "memory_operand"))) - (set (match_operand:DI 2 "base_reg_operand") - (const_int 0)) - (set (match_operand:TI 3 "vsx_register_operand") - (match_operand:TI 4 "int_reg_operand"))] - "TARGET_POWER10 && TARGET_POWERPC64 - && (reg_or_subregno (operands[0]) - == reg_or_subregno (operands[4]) + !!WORDS_BIG_ENDIAN) - && (reg_or_subregno (operands[2]) - == reg_or_subregno (operands[4]) + !WORDS_BIG_ENDIAN) - && peep2_reg_dead_p (3, operands[4]) - && (REG_P (XEXP (operands[1], 0)) - || SUBREG_P (XEXP (operands[1], 0)) - || GET_CODE (XEXP (operands[1], 0)) == PLUS)" - [(set (match_dup 3) - (zero_extend:TI (match_dup 5)))] -{ - rtx mem = operands[1]; - rtx addr = XEXP (mem, 0); - - if (indexed_or_indirect_address (addr, DImode)) - operands[5] = mem; - else - { - rtx op2 = operands[2]; - emit_insn (gen_rtx_SET (op2, addr)); - operands[5] = change_address (mem, DImode, op2); - } -}) (define_insn "zero_extendsi<mode>2" [(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r,r,d,wa,wa,r,wa") @@ -5645,19 +5550,6 @@ FAIL; }) -(define_expand "mov<mode>cc" - [(set (match_operand:IEEE128 0 "gpc_reg_operand") - (if_then_else:IEEE128 (match_operand 1 "comparison_operator") - (match_operand:IEEE128 2 "gpc_reg_operand") - (match_operand:IEEE128 3 "gpc_reg_operand")))] - "TARGET_POWER10 && TARGET_FLOAT128_HW" -{ - if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3])) - DONE; - else - FAIL; -}) - ;; We use the BASE_REGS for the isel input operands because, if rA is ;; 0, the value of 0 is placed in rD upon truth. Similarly for rB ;; because we may switch the operands and rB may end up being rA. @@ -5760,6 +5652,203 @@ "TARGET_HARD_FLOAT && TARGET_PPC_GFXOPT" "fsel %0,%1,%2,%3" [(set_attr "type" "fp")]) + +(define_insn_and_split "*mov<SFDF:mode><SFDF2:mode>cc_p9" + [(set (match_operand:SFDF 0 "vsx_register_operand" "=&wa,wa") + (if_then_else:SFDF + (match_operator:CCFP 1 "fpmask_comparison_operator" + [(match_operand:SFDF2 2 "vsx_register_operand" "wa,wa") + (match_operand:SFDF2 3 "vsx_register_operand" "wa,wa")]) + (match_operand:SFDF 4 "vsx_register_operand" "wa,wa") + (match_operand:SFDF 5 "vsx_register_operand" "wa,wa"))) + (clobber (match_scratch:V2DI 6 "=0,&wa"))] + "TARGET_P9_MINMAX" + "#" + "&& 1" + [(set (match_dup 6) + (if_then_else:V2DI (match_dup 1) + (match_dup 7) + (match_dup 8))) + (set (match_dup 0) + (if_then_else:SFDF (ne (match_dup 6) + (match_dup 8)) + (match_dup 4) + (match_dup 5)))] +{ + if (GET_CODE (operands[6]) == SCRATCH) + operands[6] = gen_reg_rtx (V2DImode); + + operands[7] = CONSTM1_RTX (V2DImode); + operands[8] = CONST0_RTX (V2DImode); +} + [(set_attr "length" "8") + (set_attr "type" "vecperm")]) + +;; Handle inverting the fpmask comparisons. +(define_insn_and_split "*mov<SFDF:mode><SFDF2:mode>cc_invert_p9" + [(set (match_operand:SFDF 0 "vsx_register_operand" "=&wa,wa") + (if_then_else:SFDF + (match_operator:CCFP 1 "invert_fpmask_comparison_operator" + [(match_operand:SFDF2 2 "vsx_register_operand" "wa,wa") + (match_operand:SFDF2 3 "vsx_register_operand" "wa,wa")]) + (match_operand:SFDF 4 "vsx_register_operand" "wa,wa") + (match_operand:SFDF 5 "vsx_register_operand" "wa,wa"))) + (clobber (match_scratch:V2DI 6 "=0,&wa"))] + "TARGET_P9_MINMAX" + "#" + "&& 1" + [(set (match_dup 6) + (if_then_else:V2DI (match_dup 9) + (match_dup 7) + (match_dup 8))) + (set (match_dup 0) + (if_then_else:SFDF (ne (match_dup 6) + (match_dup 8)) + (match_dup 5) + (match_dup 4)))] +{ + rtx op1 = operands[1]; + enum rtx_code cond = reverse_condition_maybe_unordered (GET_CODE (op1)); + + if (GET_CODE (operands[6]) == SCRATCH) + operands[6] = gen_reg_rtx (V2DImode); + + operands[7] = CONSTM1_RTX (V2DImode); + operands[8] = CONST0_RTX (V2DImode); + + operands[9] = gen_rtx_fmt_ee (cond, CCFPmode, operands[2], operands[3]); +} + [(set_attr "length" "8") + (set_attr "type" "vecperm")]) + +(define_insn "*fpmask<mode>" + [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa") + (if_then_else:V2DI + (match_operator:CCFP 1 "fpmask_comparison_operator" + [(match_operand:SFDF 2 "vsx_register_operand" "wa") + (match_operand:SFDF 3 "vsx_register_operand" "wa")]) + (match_operand:V2DI 4 "all_ones_constant" "") + (match_operand:V2DI 5 "zero_constant" "")))] + "TARGET_P9_MINMAX" + "xscmp%V1dp %x0,%x2,%x3" + [(set_attr "type" "fpcompare")]) + +(define_insn "*xxsel<mode>" + [(set (match_operand:SFDF 0 "vsx_register_operand" "=wa") + (if_then_else:SFDF (ne (match_operand:V2DI 1 "vsx_register_operand" "wa") + (match_operand:V2DI 2 "zero_constant" "")) + (match_operand:SFDF 3 "vsx_register_operand" "wa") + (match_operand:SFDF 4 "vsx_register_operand" "wa")))] + "TARGET_P9_MINMAX" + "xxsel %x0,%x4,%x3,%x1" + [(set_attr "type" "vecmove")]) + +;; Support for ISA 3.1 IEEE 128-bit conditional move. The mode used in the +;; comparison must be the same as used in the move. +(define_expand "mov<mode>cc" + [(set (match_operand:IEEE128 0 "gpc_reg_operand") + (if_then_else:IEEE128 (match_operand 1 "comparison_operator") + (match_operand:IEEE128 2 "gpc_reg_operand") + (match_operand:IEEE128 3 "gpc_reg_operand")))] + "TARGET_POWER10 && TARGET_FLOAT128_HW" +{ + if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3])) + DONE; + else + FAIL; +}) + +(define_insn_and_split "*mov<mode>cc_p10" + [(set (match_operand:IEEE128 0 "altivec_register_operand" "=&v,v") + (if_then_else:IEEE128 + (match_operator:CCFP 1 "fpmask_comparison_operator" + [(match_operand:IEEE128 2 "altivec_register_operand" "v,v") + (match_operand:IEEE128 3 "altivec_register_operand" "v,v")]) + (match_operand:IEEE128 4 "altivec_register_operand" "v,v") + (match_operand:IEEE128 5 "altivec_register_operand" "v,v"))) + (clobber (match_scratch:V2DI 6 "=0,&v"))] + "TARGET_POWER10 && TARGET_FLOAT128_HW" + "#" + "&& 1" + [(set (match_dup 6) + (if_then_else:V2DI (match_dup 1) + (match_dup 7) + (match_dup 8))) + (set (match_dup 0) + (if_then_else:IEEE128 (ne (match_dup 6) + (match_dup 8)) + (match_dup 4) + (match_dup 5)))] +{ + if (GET_CODE (operands[6]) == SCRATCH) + operands[6] = gen_reg_rtx (V2DImode); + + operands[7] = CONSTM1_RTX (V2DImode); + operands[8] = CONST0_RTX (V2DImode); +} + [(set_attr "length" "8") + (set_attr "type" "vecperm")]) + +;; Handle inverting the fpmask comparisons. +(define_insn_and_split "*mov<mode>cc_invert_p10" + [(set (match_operand:IEEE128 0 "altivec_register_operand" "=&v,v") + (if_then_else:IEEE128 + (match_operator:CCFP 1 "invert_fpmask_comparison_operator" + [(match_operand:IEEE128 2 "altivec_register_operand" "v,v") + (match_operand:IEEE128 3 "altivec_register_operand" "v,v")]) + (match_operand:IEEE128 4 "altivec_register_operand" "v,v") + (match_operand:IEEE128 5 "altivec_register_operand" "v,v"))) + (clobber (match_scratch:V2DI 6 "=0,&v"))] + "TARGET_POWER10 && TARGET_FLOAT128_HW" + "#" + "&& 1" + [(set (match_dup 6) + (if_then_else:V2DI (match_dup 9) + (match_dup 7) + (match_dup 8))) + (set (match_dup 0) + (if_then_else:IEEE128 (ne (match_dup 6) + (match_dup 8)) + (match_dup 5) + (match_dup 4)))] +{ + rtx op1 = operands[1]; + enum rtx_code cond = reverse_condition_maybe_unordered (GET_CODE (op1)); + + if (GET_CODE (operands[6]) == SCRATCH) + operands[6] = gen_reg_rtx (V2DImode); + + operands[7] = CONSTM1_RTX (V2DImode); + operands[8] = CONST0_RTX (V2DImode); + + operands[9] = gen_rtx_fmt_ee (cond, CCFPmode, operands[2], operands[3]); +} + [(set_attr "length" "8") + (set_attr "type" "vecperm")]) + +(define_insn "*fpmask<mode>" + [(set (match_operand:V2DI 0 "altivec_register_operand" "=v") + (if_then_else:V2DI + (match_operator:CCFP 1 "fpmask_comparison_operator" + [(match_operand:IEEE128 2 "altivec_register_operand" "v") + (match_operand:IEEE128 3 "altivec_register_operand" "v")]) + (match_operand:V2DI 4 "all_ones_constant" "") + (match_operand:V2DI 5 "zero_constant" "")))] + "TARGET_POWER10 && TARGET_FLOAT128_HW" + "xscmp%V1qp %0,%2,%3" + [(set_attr "type" "fpcompare")]) + +(define_insn "*xxsel<mode>" + [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v") + (if_then_else:IEEE128 + (ne (match_operand:V2DI 1 "altivec_register_operand" "v") + (match_operand:V2DI 2 "zero_constant" "")) + (match_operand:IEEE128 3 "altivec_register_operand" "v") + (match_operand:IEEE128 4 "altivec_register_operand" "v")))] + "TARGET_POWER10 && TARGET_FLOAT128_HW" + "xxsel %x0,%x4,%x3,%x1" + [(set_attr "type" "vecmove")]) + ;; Conversions to and from floating-point. diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index f47c4e2f7766..0082a36831a5 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -4798,24 +4798,6 @@ "lxvdsx %x0,%y1" [(set_attr "type" "vecload")]) -;; Optimize SPLAT of an extract from a V2DF/V2DI vector with a constant element -(define_insn "*vsx_splat_extract_<mode>" - [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa") - (vec_duplicate:VSX_D - (vec_select:<VEC_base> - (match_operand:VSX_D 1 "vsx_register_operand" "wa") - (parallel [(match_operand 2 "const_0_to_1_operand" "n")]))))] - "VECTOR_MEM_VSX_P (<MODE>mode)" -{ - int which_word = INTVAL (operands[2]); - if (!BYTES_BIG_ENDIAN) - which_word = 1 - which_word; - - operands[3] = GEN_INT (which_word ? 3 : 0); - return "xxpermdi %x0,%x1,%x1,%3"; -} - [(set_attr "type" "vecperm")]) - ;; V4SI splat support (define_insn "vsx_splat_v4si" [(set (match_operand:V4SI 0 "vsx_register_operand" "=wa,wa") diff --git a/gcc/testsuite/gcc.target/powerpc/builtins-1.c b/gcc/testsuite/gcc.target/powerpc/builtins-1.c index 8410a5fd4319..4e7e5384675f 100644 --- a/gcc/testsuite/gcc.target/powerpc/builtins-1.c +++ b/gcc/testsuite/gcc.target/powerpc/builtins-1.c @@ -1035,4 +1035,4 @@ foo156 (vector unsigned short usa) /* { dg-final { scan-assembler-times {\mvmrglb\M} 3 } } */ /* { dg-final { scan-assembler-times {\mvmrgew\M} 4 } } */ /* { dg-final { scan-assembler-times {\mvsplth|xxsplth\M} 4 } } */ -/* { dg-final { scan-assembler-times {\mxxpermdi\M} 44 } } */ +/* { dg-final { scan-assembler-times {\mxxpermdi\M} 42 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/p9-minmax-2.c b/gcc/testsuite/gcc.target/powerpc/p9-minmax-2.c index b93056f78aea..0684eb501c56 100644 --- a/gcc/testsuite/gcc.target/powerpc/p9-minmax-2.c +++ b/gcc/testsuite/gcc.target/powerpc/p9-minmax-2.c @@ -1,29 +1,190 @@ /* { dg-do compile } */ -/* { dg-options "-mdejagnu-cpu=power9 -mvsx -O2" } */ +/* { dg-options "-mdejagnu-cpu=power9 -mvsx -O2 -mpower9-minmax" } */ /* { dg-require-effective-target powerpc_vsx } */ -/* { dg-final { scan-assembler "xsmaxcdp" } } */ -/* { dg-final { scan-assembler "xsmincdp" } } */ +/* { dg-final { scan-assembler-not "fsel" } } */ +/* { dg-final { scan-assembler "xscmpeqdp" } } */ +/* { dg-final { scan-assembler "xscmpgtdp" } } */ +/* { dg-final { scan-assembler-not "xscmpodp" } } */ +/* { dg-final { scan-assembler-not "xscmpudp" } } */ +/* { dg-final { scan-assembler "xsmaxcdp" } } */ +/* { dg-final { scan-assembler-not "xsmaxdp" } } */ +/* { dg-final { scan-assembler "xsmincdp" } } */ +/* { dg-final { scan-assembler-not "xsmindp" } } */ +/* { dg-final { scan-assembler "xxsel" } } */ + +/* Due to NaN support, <= and >= are not handled presently unless -ffast-math + is used. At some point this will be fixed and the xscmpgedp instruction can + be generated normally. The <= and >= tests are bracketed with + #ifdef DO_GE_LE. */ + +#ifdef DO_GE_LE +double +dbl_max1 (double a, double b) +{ + return (a >= b) ? a : b; +} +#endif double -dbl_max (double a, double b) +dbl_max2 (double a, double b) { return (a > b) ? a : b; } double -dbl_min (double a, double b) +dbl_min1 (double a, double b) { return (a < b) ? a : b; } +#ifdef DO_GE_LE +double +dbl_min2 (double a, double b) +{ + return (a <= b) ? a : b; +} +#endif + +double +dbl_cmp_eq (double a, double b, double c, double d) +{ + return (a == b) ? c : d; +} + +double +dbl_cmp_ne (double a, double b, double c, double d) +{ + return (a != b) ? c : d; +} + +double +dbl_cmp_gt (double a, double b, double c, double d) +{ + return (a > b) ? c : d; +} + +#ifdef DO_GE_LE +double +dbl_cmp_ge (double a, double b, double c, double d) +{ + return (a >= b) ? c : d; +} +#endif + +double +dbl_cmp_lt (double a, double b, double c, double d) +{ + return (a < b) ? c : d; +} + +#ifdef DO_GE_LE +double +dbl_cmp_le (double a, double b, double c, double d) +{ + return (a <= b) ? c : d; +} +#endif + +#ifdef DO_GE_LE +float +flt_max1 (float a, float b) +{ + return (a >= b) ? a : b; +} +#endif + float -flt_max (float a, float b) +flt_max2 (float a, float b) { return (a > b) ? a : b; } float -flt_min (float a, float b) +flt_min1 (float a, float b) +{ + return (a < b) ? a : b; +} + +#ifdef DO_GE_LE +float +flt_min2 (float a, float b) +{ + return (a <= b) ? a : b; +} +#endif + +float +flt_cmp_eq (float a, float b, float c, float d) +{ + return (a == b) ? c : d; +} + +float +flt_cmp_ne (float a, float b, float c, float d) +{ + return (a != b) ? c : d; +} + +float +flt_cmp_gt (float a, float b, float c, float d) +{ + return (a > b) ? c : d; +} + +#ifdef DO_GE_LE +float +flt_cmp_ge (float a, float b, float c, float d) +{ + return (a >= b) ? c : d; +} +#endif + +float +flt_cmp_lt (float a, float b, float c, float d) +{ + return (a < b) ? c : d; +} + +#ifdef DO_GE_LE +float +flt_cmp_le (float a, float b, float c, float d) +{ + return (a <= b) ? c : d; +} +#endif + +double +dbl_flt_max1 (float a, float b) +{ + return (a > b) ? a : b; +} + +double +dbl_flt_max2 (double a, float b) +{ + return (a > b) ? a : b; +} + +double +dbl_flt_max3 (float a, double b) +{ + return (a > b) ? a : b; +} + +double +dbl_flt_min1 (float a, float b) +{ + return (a < b) ? a : b; +} + +double +dbl_flt_min2 (double a, float b) +{ + return (a < b) ? a : b; +} + +double +dbl_flt_min3 (float a, double b) { return (a < b) ? a : b; } diff --git a/gcc/testsuite/gcc.target/powerpc/pr108958.c b/gcc/testsuite/gcc.target/powerpc/pr108958.c deleted file mode 100644 index 21b3f2766918..000000000000 --- a/gcc/testsuite/gcc.target/powerpc/pr108958.c +++ /dev/null @@ -1,47 +0,0 @@ -/* { dg-do compile } */ -/* { dg-require-effective-target int128 } */ -/* { dg-require-effective-target lp64 } */ -/* { dg-options "-mdejagnu-cpu=power9 -O2" } */ - -#ifndef TYPE -#define TYPE unsigned long long -#endif - -/* PR target/108958, when zero extending a DImode to a TImode, and the TImode variable is in a VSX register, generate: - - mtvsrdd vreg,0,gpr - - instead of: - - mr tmp,gpr - li tmp+1,0 - mtvsrdd vreg,tmp+1,tmp. */ - -void -gpr_to_vsx (TYPE x, __uint128_t *p) -{ - /* mtvsrdd 0,0,3 - stvx 0,0(4) */ - - __uint128_t y = x; - __asm__ (" # %x0" : "+wa" (y)); - *p = y; -} - -void -gpr_to_gpr (TYPE x, __uint128_t *p) -{ - /* mr 2,3 - li 3,0 - std 2,0(4) - std 3,8(4) */ - - __uint128_t y = x; - __asm__ (" # %0" : "+r" (y)); - *p = y; -} - -/* { dg-final { scan-assembler-times {\mli\M} 1 } } */ -/* { dg-final { scan-assembler-times {\mmtvsrdd .*,0,.*\M} 1 } } */ -/* { dg-final { scan-assembler-times {\mstd\M} 2 } } */ -/* { dg-final { scan-assembler-times {\mstxv\M} 1 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/pr120528.c b/gcc/testsuite/gcc.target/powerpc/pr120528.c deleted file mode 100644 index 476725eaa4fb..000000000000 --- a/gcc/testsuite/gcc.target/powerpc/pr120528.c +++ /dev/null @@ -1,91 +0,0 @@ -/* { dg-do compile } */ -/* { dg-require-effective-target int128 } */ -/* { dg-require-effective-target lp64 } */ -/* { dg-require-effective-target power10_ok } */ -/* { dg-options "-mdejagnu-cpu=power10 -O2" } */ - -#include <stddef.h> - -#ifndef TYPE -#define TYPE unsigned long long -#endif - -void -mem_to_vsx (TYPE *p, __uint128_t *q) -{ - /* lxvrdx 0,0,3 - stxv 0,0(4) */ - - __uint128_t x = *p; - __asm__ (" # %x0" : "+wa" (x)); - *q = x; -} - -void -memx_to_vsx (TYPE *p, size_t n, __uint128_t *q) -{ - /* sldi 4,4,3 - lxvrdx 0,3,4 - stxv 0,0(4) */ - - __uint128_t x = p[n]; - __asm__ (" # %x0" : "+wa" (x)); - *q = x; -} - -void -mem3_to_vsx (TYPE *p, __uint128_t *q) -{ - /* addi 2,3,24 - lxvrdx 0,0,2 - stxv 0,0(4) */ - - __uint128_t x = p[3]; - __asm__ (" # %x0" : "+wa" (x)); - *q = x; -} - -void -mem_to_gpr (TYPE *p, __uint128_t *q) -{ - /* ld 2,0(3) - li 3,0 - std 2,0(4) - std 3,8(8) */ - - __uint128_t x = *p; - __asm__ (" # %0" : "+r" (x)); - *q = x; -} - -void -memx_to_gpr (TYPE *p, size_t n, __uint128_t *q) -{ - /* sldi 4,4,3 - ldx 2,3,4 - li 3,0 - std 2,0(4) - std 3,8(8) */ - - __uint128_t x = p[n]; - __asm__ (" # %0" : "+r" (x)); - *q = x; -} - -void -mem3_to_gpr (TYPE *p, __uint128_t *q) -{ - /* ld 2,24(3) - li 3,0 - std 2,0(4) - std 3,8(8) */ - - __uint128_t x = p[3]; - __asm__ (" # %0" : "+r" (x)); - *q = x; -} - -/* { dg-final { scan-assembler-times {\maddi\M} 1 } } */ -/* { dg-final { scan-assembler-times {\mli\M} 3 } } */ -/* { dg-final { scan-assembler-times {\mlxvrdx\M} 3 } } */ -/* { dg-final { scan-assembler-times {\mstxv\M} 3 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/pr120681.c b/gcc/testsuite/gcc.target/powerpc/pr120681.c deleted file mode 100644 index d883d1c8a951..000000000000 --- a/gcc/testsuite/gcc.target/powerpc/pr120681.c +++ /dev/null @@ -1,34 +0,0 @@ -/* { dg-do compile } */ -/* { dg-require-effective-target powerpc_elfv2 } */ -/* { dg-require-effective-target powerpc_pcrel } */ -/* { dg-options "-mdejagnu-cpu=power10 -O2 -mcmodel=large" } */ - -/* PR target/120681 -- verify that -mcpu=power10 -mcmodel=large uses PC - relative addressing instead of using TOC addressing. */ - -#ifndef TYPE -#define TYPE unsigned long -#endif - -extern TYPE global_var; - -void -set_global (TYPE value) -{ - /* - * Generate: - * pld 9,global_var@got@pcrel - * std 3,0(9) - * - * Not: - * addis 9,2,.LC0@toc@ha - * ld 9,.LC0@toc@l(9) - * std 3,0(9) - */ - - global_var = value; -} - -/* { dg-final { scan-assembler {@got@pcrel} } } */ -/* { dg-final { scan-assembler-not {@toc@ha} } } */ -/* { dg-final { scan-assembler-not {@toc@l} } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/pr99293.c b/gcc/testsuite/gcc.target/powerpc/pr99293.c deleted file mode 100644 index 20adc1f27f65..000000000000 --- a/gcc/testsuite/gcc.target/powerpc/pr99293.c +++ /dev/null @@ -1,22 +0,0 @@ -/* { dg-do compile { target powerpc*-*-* } } */ -/* { dg-require-effective-target powerpc_vsx_ok } */ -/* { dg-options "-O2 -mvsx" } */ - -/* Test for PR 99263, which wants to do: - __builtin_vec_splats (__builtin_vec_extract (v, n)) - - where v is a V2DF or V2DI vector and n is either 0 or 1. Previously the - compiler would do a direct move to the GPR registers to select the item and a - direct move from the GPR registers to do the splat. */ - -vector long long splat_dup_l_0 (vector long long v) -{ - return __builtin_vec_splats (__builtin_vec_extract (v, 0)); -} - -vector long long splat_dup_l_1 (vector long long v) -{ - return __builtin_vec_splats (__builtin_vec_extract (v, 1)); -} - -/* { dg-final { scan-assembler-times "xxpermdi" 2 } } */
