diff options
Diffstat (limited to 'gcc/config/rs6000/rs6000.c')
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 202 |
1 files changed, 186 insertions, 16 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 40106ba9d7b..409a810189c 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -366,7 +366,9 @@ static const struct { "tar", PPC_FEATURE2_HAS_TAR, 1 }, { "vcrypto", PPC_FEATURE2_HAS_VEC_CRYPTO, 1 }, { "arch_3_00", PPC_FEATURE2_ARCH_3_00, 1 }, - { "ieee128", PPC_FEATURE2_HAS_IEEE128, 1 } + { "ieee128", PPC_FEATURE2_HAS_IEEE128, 1 }, + { "darn", PPC_FEATURE2_DARN, 1 }, + { "scv", PPC_FEATURE2_SCV, 1 } }; /* Newer LIBCs explicitly export this symbol to declare that they provide @@ -495,6 +497,91 @@ mode_supports_pre_modify_p (machine_mode mode) != 0); } +/* Given that there exists at least one variable that is set (produced) + by OUT_INSN and read (consumed) by IN_INSN, return true iff + IN_INSN represents one or more memory store operations and none of + the variables set by OUT_INSN is used by IN_INSN as the address of a + store operation. If either IN_INSN or OUT_INSN does not represent + a "single" RTL SET expression (as loosely defined by the + implementation of the single_set function) or a PARALLEL with only + SETs, CLOBBERs, and USEs inside, this function returns false. + + This rs6000-specific version of store_data_bypass_p checks for + certain conditions that result in assertion failures (and internal + compiler errors) in the generic store_data_bypass_p function and + returns false rather than calling store_data_bypass_p if one of the + problematic conditions is detected. */ + +int +rs6000_store_data_bypass_p (rtx_insn *out_insn, rtx_insn *in_insn) +{ + rtx out_set, in_set; + rtx out_pat, in_pat; + rtx out_exp, in_exp; + int i, j; + + in_set = single_set (in_insn); + if (in_set) + { + if (MEM_P (SET_DEST (in_set))) + { + out_set = single_set (out_insn); + if (!out_set) + { + out_pat = PATTERN (out_insn); + if (GET_CODE (out_pat) == PARALLEL) + { + for (i = 0; i < XVECLEN (out_pat, 0); i++) + { + out_exp = XVECEXP (out_pat, 0, i); + if ((GET_CODE (out_exp) == CLOBBER) + || (GET_CODE (out_exp) == USE)) + continue; + else if (GET_CODE (out_exp) != SET) + return false; + } + } + } + } + } + else + { + in_pat = PATTERN (in_insn); + if (GET_CODE (in_pat) != PARALLEL) + return false; + + for (i = 0; i < XVECLEN (in_pat, 0); i++) + { + in_exp = XVECEXP (in_pat, 0, i); + if ((GET_CODE (in_exp) == CLOBBER) || (GET_CODE (in_exp) == USE)) + continue; + else if (GET_CODE (in_exp) != SET) + return false; + + if (MEM_P (SET_DEST (in_exp))) + { + out_set = single_set (out_insn); + if (!out_set) + { + out_pat = PATTERN (out_insn); + if (GET_CODE (out_pat) != PARALLEL) + return false; + for (j = 0; j < XVECLEN (out_pat, 0); j++) + { + out_exp = XVECEXP (out_pat, 0, j); + if ((GET_CODE (out_exp) == CLOBBER) + || (GET_CODE (out_exp) == USE)) + continue; + else if (GET_CODE (out_exp) != SET) + return false; + } + } + } + } + } + return store_data_bypass_p (out_insn, in_insn); +} + /* Return true if we have D-form addressing in altivec registers. */ static inline bool mode_supports_vmx_dform (machine_mode mode) @@ -4076,9 +4163,22 @@ rs6000_option_override_internal (bool global_init_p) if (TARGET_P8_VECTOR && !TARGET_VSX) { - if (rs6000_isa_flags_explicit & OPTION_MASK_P8_VECTOR) + if ((rs6000_isa_flags_explicit & OPTION_MASK_P8_VECTOR) + && (rs6000_isa_flags_explicit & OPTION_MASK_VSX)) error ("-mpower8-vector requires -mvsx"); - rs6000_isa_flags &= ~OPTION_MASK_P8_VECTOR; + else if ((rs6000_isa_flags_explicit & OPTION_MASK_P8_VECTOR) == 0) + { + rs6000_isa_flags &= ~OPTION_MASK_P8_VECTOR; + if (rs6000_isa_flags_explicit & OPTION_MASK_VSX) + rs6000_isa_flags_explicit |= OPTION_MASK_P8_VECTOR; + } + else + { + /* OPTION_MASK_P8_VECTOR is explicit, and OPTION_MASK_VSX is + not explicit. */ + rs6000_isa_flags |= OPTION_MASK_VSX; + rs6000_isa_flags_explicit |= OPTION_MASK_VSX; + } } if (TARGET_VSX_TIMODE && !TARGET_VSX) @@ -4259,9 +4359,22 @@ rs6000_option_override_internal (bool global_init_p) error messages. However, if users have managed to select power9-vector without selecting power8-vector, they already know about undocumented flags. */ - if (rs6000_isa_flags_explicit & OPTION_MASK_P8_VECTOR) + if ((rs6000_isa_flags_explicit & OPTION_MASK_P9_VECTOR) && + (rs6000_isa_flags_explicit & OPTION_MASK_P8_VECTOR)) error ("-mpower9-vector requires -mpower8-vector"); - rs6000_isa_flags &= ~OPTION_MASK_P9_VECTOR; + else if ((rs6000_isa_flags_explicit & OPTION_MASK_P9_VECTOR) == 0) + { + rs6000_isa_flags &= ~OPTION_MASK_P9_VECTOR; + if (rs6000_isa_flags_explicit & OPTION_MASK_P8_VECTOR) + rs6000_isa_flags_explicit |= OPTION_MASK_P9_VECTOR; + } + else + { + /* OPTION_MASK_P9_VECTOR is explicit and + OPTION_MASK_P8_VECTOR is not explicit. */ + rs6000_isa_flags |= OPTION_MASK_P8_VECTOR; + rs6000_isa_flags_explicit |= OPTION_MASK_P8_VECTOR; + } } /* -mpower9-dform turns on both -mpower9-dform-scalar and @@ -4290,10 +4403,52 @@ rs6000_option_override_internal (bool global_init_p) error messages. However, if users have managed to select power9-dform without selecting power9-vector, they already know about undocumented flags. */ - if (rs6000_isa_flags_explicit & OPTION_MASK_P9_VECTOR) + if ((rs6000_isa_flags_explicit & OPTION_MASK_P9_VECTOR) + && (rs6000_isa_flags_explicit & (OPTION_MASK_P9_DFORM_SCALAR + | OPTION_MASK_P9_DFORM_VECTOR))) error ("-mpower9-dform requires -mpower9-vector"); - rs6000_isa_flags &= ~(OPTION_MASK_P9_DFORM_SCALAR - | OPTION_MASK_P9_DFORM_VECTOR); + else if (rs6000_isa_flags_explicit & OPTION_MASK_P9_VECTOR) + { + rs6000_isa_flags &= + ~(OPTION_MASK_P9_DFORM_SCALAR | OPTION_MASK_P9_DFORM_VECTOR); + rs6000_isa_flags_explicit |= + (OPTION_MASK_P9_DFORM_SCALAR | OPTION_MASK_P9_DFORM_VECTOR); + } + else + { + /* We know that OPTION_MASK_P9_VECTOR is not explicit and + OPTION_MASK_P9_DFORM_SCALAR or OPTION_MASK_P9_DORM_VECTOR + may be explicit. */ + rs6000_isa_flags |= OPTION_MASK_P9_VECTOR; + rs6000_isa_flags_explicit |= OPTION_MASK_P9_VECTOR; + } + } + + if ((TARGET_P9_DFORM_SCALAR || TARGET_P9_DFORM_VECTOR) + && !TARGET_DIRECT_MOVE) + { + /* We prefer to not mention undocumented options in + error messages. However, if users have managed to select + power9-dform without selecting power9-vector, they + already know about undocumented flags. */ + if ((rs6000_isa_flags_explicit & OPTION_MASK_DIRECT_MOVE) + && ((rs6000_isa_flags_explicit & OPTION_MASK_P9_DFORM_VECTOR) || + (rs6000_isa_flags_explicit & OPTION_MASK_P9_DFORM_SCALAR) || + (TARGET_P9_DFORM_BOTH == 1))) + error ("-mpower9-dform, -mpower9-dform-vector, -mpower9-dform-scalar" + " require -mdirect-move"); + else if ((rs6000_isa_flags_explicit & OPTION_MASK_DIRECT_MOVE) == 0) + { + rs6000_isa_flags |= OPTION_MASK_DIRECT_MOVE; + rs6000_isa_flags_explicit |= OPTION_MASK_DIRECT_MOVE; + } + else + { + rs6000_isa_flags &= + ~(OPTION_MASK_P9_DFORM_SCALAR | OPTION_MASK_P9_DFORM_VECTOR); + rs6000_isa_flags_explicit |= + (OPTION_MASK_P9_DFORM_SCALAR | OPTION_MASK_P9_DFORM_VECTOR); + } } if (TARGET_P9_DFORM_SCALAR && !TARGET_UPPER_REGS_DF) @@ -14163,6 +14318,8 @@ cpu_expand_builtin (enum rs6000_builtins fcode, tree exp ATTRIBUTE_UNUSED, emit_insn (gen_eqsi3 (scratch2, scratch1, const0_rtx)); emit_insn (gen_rtx_SET (target, gen_rtx_XOR (SImode, scratch2, const1_rtx))); } + else + gcc_unreachable (); /* Record that we have expanded a CPU builtin, so that we can later emit a reference to the special symbol exported by LIBC to ensure we @@ -14170,6 +14327,9 @@ cpu_expand_builtin (enum rs6000_builtins fcode, tree exp ATTRIBUTE_UNUSED, cpu_builtin_p = true; #else + warning (0, "%s needs GLIBC (2.23 and newer) that exports hardware " + "capability bits", rs6000_builtin_info[(size_t) fcode].name); + /* For old LIBCs, always return FALSE. */ emit_move_insn (target, GEN_INT (0)); #endif /* TARGET_LIBC_PROVIDES_HWCAP_IN_TCB */ @@ -30188,14 +30348,14 @@ rs6000_adjust_cost (rtx_insn *insn, rtx link, rtx_insn *dep_insn, int cost) case TYPE_LOAD: case TYPE_CNTLZ: { - if (! store_data_bypass_p (dep_insn, insn)) + if (! rs6000_store_data_bypass_p (dep_insn, insn)) return get_attr_sign_extend (dep_insn) == SIGN_EXTEND_YES ? 6 : 4; break; } case TYPE_SHIFT: { - if (! store_data_bypass_p (dep_insn, insn)) + if (! rs6000_store_data_bypass_p (dep_insn, insn)) return get_attr_var_shift (dep_insn) == VAR_SHIFT_YES ? 6 : 3; break; @@ -30206,7 +30366,7 @@ rs6000_adjust_cost (rtx_insn *insn, rtx link, rtx_insn *dep_insn, int cost) case TYPE_EXTS: case TYPE_INSERT: { - if (! store_data_bypass_p (dep_insn, insn)) + if (! rs6000_store_data_bypass_p (dep_insn, insn)) return 3; break; } @@ -30215,19 +30375,19 @@ rs6000_adjust_cost (rtx_insn *insn, rtx link, rtx_insn *dep_insn, int cost) case TYPE_FPSTORE: { if (get_attr_update (dep_insn) == UPDATE_YES - && ! store_data_bypass_p (dep_insn, insn)) + && ! rs6000_store_data_bypass_p (dep_insn, insn)) return 3; break; } case TYPE_MUL: { - if (! store_data_bypass_p (dep_insn, insn)) + if (! rs6000_store_data_bypass_p (dep_insn, insn)) return 17; break; } case TYPE_DIV: { - if (! store_data_bypass_p (dep_insn, insn)) + if (! rs6000_store_data_bypass_p (dep_insn, insn)) return get_attr_size (dep_insn) == SIZE_32 ? 45 : 57; break; } @@ -32542,8 +32702,8 @@ rs6000_elf_output_toc_section_asm_op (const void *data ATTRIBUTE_UNUSED) { if (!toc_initialized) { - toc_initialized = 1; fprintf (asm_out_file, "%s\n", TOC_SECTION_ASM_OP); + ASM_OUTPUT_ALIGN (asm_out_file, TARGET_64BIT ? 3 : 2); (*targetm.asm_out.internal_label) (asm_out_file, "LCTOC", 0); fprintf (asm_out_file, "\t.tc "); ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1[TC],"); @@ -32551,20 +32711,30 @@ rs6000_elf_output_toc_section_asm_op (const void *data ATTRIBUTE_UNUSED) fprintf (asm_out_file, "\n"); fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP); + ASM_OUTPUT_ALIGN (asm_out_file, TARGET_64BIT ? 3 : 2); ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1"); fprintf (asm_out_file, " = .+32768\n"); + toc_initialized = 1; } else fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP); } else if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) && !TARGET_RELOCATABLE) - fprintf (asm_out_file, "%s\n", TOC_SECTION_ASM_OP); + { + fprintf (asm_out_file, "%s\n", TOC_SECTION_ASM_OP); + if (!toc_initialized) + { + ASM_OUTPUT_ALIGN (asm_out_file, TARGET_64BIT ? 3 : 2); + toc_initialized = 1; + } + } else { fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP); if (!toc_initialized) { + ASM_OUTPUT_ALIGN (asm_out_file, TARGET_64BIT ? 3 : 2); ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1"); fprintf (asm_out_file, " = .+32768\n"); toc_initialized = 1; |