diff options
Diffstat (limited to 'gcc')
22 files changed, 471 insertions, 40 deletions
diff --git a/gcc/ada/sem_ch7.adb b/gcc/ada/sem_ch7.adb index 42abc89..1d838e2 100644 --- a/gcc/ada/sem_ch7.adb +++ b/gcc/ada/sem_ch7.adb @@ -2521,11 +2521,13 @@ package body Sem_Ch7 is and then Scope (Full_View (Id)) = Scope (Id) and then Ekind (Full_View (Id)) /= E_Incomplete_Type then + Full := Full_View (Id); + -- If there is a use-type clause on the private type, set the full -- view accordingly. - Set_In_Use (Full_View (Id), In_Use (Id)); - Full := Full_View (Id); + Set_In_Use (Full, In_Use (Id)); + Set_Current_Use_Clause (Full, Current_Use_Clause (Id)); if Is_Private_Base_Type (Full) and then Has_Private_Declaration (Full) @@ -2893,7 +2895,12 @@ package body Sem_Ch7 is -- When compiling a child unit this needs to be done recursively. function Type_In_Use (T : Entity_Id) return Boolean; - -- Check whether type or base type appear in an active use_type clause + -- Check whether type T is declared in P and appears in an active + -- use_type clause. + + function Type_Of_Primitive_In_Use_All (Id : Entity_Id) return Boolean; + -- Check whether the profile of primitive subprogram Id mentions a type + -- declared in P that appears in an active use-all-type clause. ------------------------------ -- Preserve_Full_Attributes -- @@ -3058,11 +3065,86 @@ package body Sem_Ch7 is ----------------- function Type_In_Use (T : Entity_Id) return Boolean is + BT : constant Entity_Id := Base_Type (T); begin - return Scope (Base_Type (T)) = P - and then (In_Use (T) or else In_Use (Base_Type (T))); + return Scope (BT) = P and then (In_Use (T) or else In_Use (BT)); end Type_In_Use; + ---------------------------------- + -- Type_Of_Primitive_In_Use_All -- + ---------------------------------- + + function Type_Of_Primitive_In_Use_All (Id : Entity_Id) return Boolean is + function Type_In_Use_All (T : Entity_Id) return Boolean; + -- Check whether type T is declared in P and appears in an active + -- use-all-type clause. + + --------------------- + -- Type_In_Use_All -- + --------------------- + + function Type_In_Use_All (T : Entity_Id) return Boolean is + begin + return Type_In_Use (T) + and then Nkind (Current_Use_Clause (T)) = N_Use_Type_Clause + and then All_Present (Current_Use_Clause (T)); + end Type_In_Use_All; + + -- Local variables + + F : Node_Id; + + -- Start of processing for Type_Of_Primitive_In_Use_All + + begin + -- The use-all-type clauses were introduced in Ada 2005 + + if Ada_Version <= Ada_95 then + return False; + end if; + + -- For enumeration literals, check type + + if Ekind (Id) = E_Enumeration_Literal then + return Type_In_Use_All (Etype (Id)); + end if; + + -- For functions, check return type + + if Ekind (Id) = E_Function then + declare + Typ : constant Entity_Id := + (if Ekind (Etype (Id)) = E_Anonymous_Access_Type + then Designated_Type (Etype (Id)) + else Etype (Id)); + begin + if Type_In_Use_All (Typ) then + return True; + end if; + end; + end if; + + -- For all subprograms, check formals + + F := First_Formal (Id); + while Present (F) loop + declare + Typ : constant Entity_Id := + (if Ekind (Etype (F)) = E_Anonymous_Access_Type + then Designated_Type (Etype (F)) + else Etype (F)); + begin + if Type_In_Use_All (Typ) then + return True; + end if; + end; + + Next_Formal (F); + end loop; + + return False; + end Type_Of_Primitive_In_Use_All; + -- Start of processing for Uninstall_Declarations begin @@ -3120,13 +3202,13 @@ package body Sem_Ch7 is elsif No (Etype (Id)) and then Serious_Errors_Detected /= 0 then null; - -- We need to avoid incorrectly marking enumeration literals as - -- non-visible when a visible use-all-type clause is in effect. + -- RM 8.4(8.1/3): Each primitive subprogram of T, including each + -- enumeration literal (if any), is potentially use-visible if T + -- is named in an active use-all-type clause. - elsif Type_In_Use (Etype (Id)) - and then Nkind (Current_Use_Clause (Etype (Id))) = - N_Use_Type_Clause - and then All_Present (Current_Use_Clause (Etype (Id))) + elsif (Ekind (Id) = E_Enumeration_Literal + or else (Is_Subprogram (Id) and then Is_Primitive (Id))) + and then Type_Of_Primitive_In_Use_All (Id) then null; diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md index 056f9e2..f811a4e 100644 --- a/gcc/config/riscv/predicates.md +++ b/gcc/config/riscv/predicates.md @@ -334,6 +334,13 @@ && riscv_split_symbol_type (symbol_type) && symbol_type != SYMBOL_PCREL; + /* Be tight about the SUBREGs we accept. In particular, + (subreg (mem)) has been discouraged for decades. Just + allow (subreg (reg)) until such time as we see a strong + need to be more permissive. */ + case SUBREG: + return REG_P (SUBREG_REG (op)); + default: return true; } diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index e4473f4..346d7a8 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -832,6 +832,7 @@ extern bool th_print_operand_address (FILE *, machine_mode, rtx); #endif extern bool strided_load_broadcast_p (void); +extern bool riscv_prefer_agnostic_p (void); extern bool riscv_use_divmod_expander (void); void riscv_init_cumulative_args (CUMULATIVE_ARGS *, const_tree, rtx, tree, int); extern bool diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc index 8021bc1..1d7d8a6 100644 --- a/gcc/config/riscv/riscv-v.cc +++ b/gcc/config/riscv/riscv-v.cc @@ -2140,10 +2140,8 @@ get_ma (rtx ma) enum tail_policy get_prefer_tail_policy () { - /* TODO: By default, we choose to use TAIL_ANY which allows - compiler pick up either agnostic or undisturbed. Maybe we - will have a compile option like -mprefer=agnostic to set - this value???. */ + if (riscv_prefer_agnostic_p ()) + return TAIL_AGNOSTIC; return TAIL_ANY; } @@ -2151,10 +2149,8 @@ get_prefer_tail_policy () enum mask_policy get_prefer_mask_policy () { - /* TODO: By default, we choose to use MASK_ANY which allows - compiler pick up either agnostic or undisturbed. Maybe we - will have a compile option like -mprefer=agnostic to set - this value???. */ + if (riscv_prefer_agnostic_p ()) + return MASK_AGNOSTIC; return MASK_ANY; } diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc index 4fe0ae6..3586d0c 100644 --- a/gcc/config/riscv/riscv-vsetvl.cc +++ b/gcc/config/riscv/riscv-vsetvl.cc @@ -1144,9 +1144,10 @@ public: dflags |= demand_flags::DEMAND_LMUL_P; } - if (!m_ta) + /* Demand policy for agnostic if the uarch has a preference. */ + if (!m_ta || riscv_prefer_agnostic_p ()) dflags |= demand_flags::DEMAND_TAIL_POLICY_P; - if (!m_ma) + if (!m_ma || riscv_prefer_agnostic_p ()) dflags |= demand_flags::DEMAND_MASK_POLICY_P; } diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 41ee401..c81a2e4 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -317,6 +317,7 @@ struct riscv_tune_param const char *function_align; const char *jump_align; const char *loop_align; + bool prefer_agnostic; }; @@ -481,6 +482,7 @@ static const struct riscv_tune_param generic_tune_info = { NULL, /* function_align */ NULL, /* jump_align */ NULL, /* loop_align */ + false, /* prefer-agnostic. */ }; /* Costs to use when optimizing for rocket. */ @@ -505,6 +507,7 @@ static const struct riscv_tune_param rocket_tune_info = { NULL, /* function_align */ NULL, /* jump_align */ NULL, /* loop_align */ + false, /* prefer-agnostic. */ }; /* Costs to use when optimizing for Sifive 7 Series. */ @@ -529,6 +532,7 @@ static const struct riscv_tune_param sifive_7_tune_info = { NULL, /* function_align */ NULL, /* jump_align */ NULL, /* loop_align */ + false, /* prefer-agnostic. */ }; /* Costs to use when optimizing for Sifive p400 Series. */ @@ -553,6 +557,7 @@ static const struct riscv_tune_param sifive_p400_tune_info = { NULL, /* function_align */ NULL, /* jump_align */ NULL, /* loop_align */ + true, /* prefer-agnostic. */ }; /* Costs to use when optimizing for Sifive p600 Series. */ @@ -577,6 +582,7 @@ static const struct riscv_tune_param sifive_p600_tune_info = { NULL, /* function_align */ NULL, /* jump_align */ NULL, /* loop_align */ + true, /* prefer-agnostic. */ }; /* Costs to use when optimizing for T-HEAD c906. */ @@ -601,6 +607,7 @@ static const struct riscv_tune_param thead_c906_tune_info = { NULL, /* function_align */ NULL, /* jump_align */ NULL, /* loop_align */ + false, /* prefer-agnostic. */ }; /* Costs to use when optimizing for xiangshan nanhu. */ @@ -625,6 +632,7 @@ static const struct riscv_tune_param xiangshan_nanhu_tune_info = { NULL, /* function_align */ NULL, /* jump_align */ NULL, /* loop_align */ + true, /* prefer-agnostic. */ }; /* Costs to use when optimizing for a generic ooo profile. */ @@ -649,6 +657,7 @@ static const struct riscv_tune_param generic_ooo_tune_info = { NULL, /* function_align */ NULL, /* jump_align */ NULL, /* loop_align */ + true, /* prefer-agnostic. */ }; /* Costs to use when optimizing for Tenstorrent Ascalon 8 wide. */ @@ -673,6 +682,7 @@ static const struct riscv_tune_param tt_ascalon_d8_tune_info = { NULL, /* function_align */ NULL, /* jump_align */ NULL, /* loop_align */ + true, /* prefer-agnostic. */ }; /* Costs to use when optimizing for size. */ @@ -697,6 +707,7 @@ static const struct riscv_tune_param optimize_size_tune_info = { NULL, /* function_align */ NULL, /* jump_align */ NULL, /* loop_align */ + false, /* prefer-agnostic. */ }; /* Costs to use when optimizing for MIPS P8700 */ @@ -720,7 +731,8 @@ static const struct riscv_tune_param mips_p8700_tune_info = { NULL, /* vector cost */ NULL, /* function_align */ NULL, /* jump_align */ - NULL, /* loop_align */ + NULL, /* loop_align. */ + true, /* prefer-agnostic. */ }; static bool riscv_avoid_shrink_wrapping_separate (); @@ -9027,8 +9039,7 @@ riscv_allocate_and_probe_stack_space (rtx temp1, HOST_WIDE_INT size) from the top of the frame, as it might be lowered before. To consider the correct SP addresses for the CFA notes, it is needed to correct them with the initial offset value. */ - HOST_WIDE_INT initial_cfa_offset - = cfun->machine->frame.total_size.to_constant () - size; + poly_int64 initial_cfa_offset = cfun->machine->frame.total_size - size; if (!frame_pointer_needed) { @@ -12842,6 +12853,15 @@ strided_load_broadcast_p () return tune_param->use_zero_stride_load; } +/* Return TRUE if we should use the tail agnostic and mask agnostic policies for + vector code, false otherwise. */ + +bool +riscv_prefer_agnostic_p () +{ + return tune_param->prefer_agnostic; +} + /* Return TRUE if we should use the divmod expander, FALSE otherwise. This allows the behavior to be tuned for specific implementations as well as when optimizing for size. */ diff --git a/gcc/fortran/trans-io.cc b/gcc/fortran/trans-io.cc index df2fef7..9360bdd 100644 --- a/gcc/fortran/trans-io.cc +++ b/gcc/fortran/trans-io.cc @@ -2646,7 +2646,9 @@ gfc_trans_transfer (gfc_code * code) && ((expr->symtree->n.sym->ts.type == BT_DERIVED && expr->ts.deferred) || (expr->symtree->n.sym->assoc && expr->symtree->n.sym->assoc->variable) - || gfc_expr_attr (expr).pointer)) + || gfc_expr_attr (expr).pointer + || (expr->symtree->n.sym->attr.pointer + && gfc_expr_attr (expr).target))) goto scalarize; /* With array-bounds checking enabled, force scalarization in some diff --git a/gcc/match.pd b/gcc/match.pd index b3fd26e..6f896aa 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -6808,6 +6808,34 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) @2)) ) +#if GIMPLE +/* Given two integers a and b: + (a != b) & ((a|b) != 0) -> (a != b) + (a != b) | ((a|b) != 0) -> ((a|b) != 0) + (a == b) & ((a|b) == 0) -> ((a|b) == 0) + (a == b) | ((a|b) == 0) -> (a == b) + (a != b) & ((a|b) == 0) -> false + (a == b) | ((a|b) != 0) -> true */ +(simplify + (bit_and:c (ne:c @0 @1) (ne (bit_ior @0 @1) integer_zerop)) + (ne @0 @1)) +(simplify + (bit_ior:c (ne:c @0 @1) (ne (bit_ior @0 @1) integer_zerop)) + (ne (bit_ior @0 @1) { integer_zero_node; })) +(simplify + (bit_and:c (eq:c @0 @1) (eq (bit_ior @0 @1) integer_zerop)) + (eq (bit_ior @0 @1) { integer_zero_node; })) +(simplify + (bit_ior:c (eq:c @0 @1) (eq (bit_ior @0 @1) integer_zerop)) + (eq @0 @1)) +(simplify + (bit_and:c (ne:c @0 @1) (eq (bit_ior @0 @1) integer_zerop)) + { build_zero_cst (type); }) +(simplify + (bit_ior:c (eq:c @0 @1) (ne (bit_ior @0 @1) integer_zerop)) + { build_one_cst (type); }) +#endif + /* These was part of minmax phiopt. */ /* Optimize (a CMP b) ? minmax<a, c> : minmax<b, c> to minmax<min/max<a, b>, c> */ diff --git a/gcc/testsuite/gcc.dg/int-bwise-opt-1.c b/gcc/testsuite/gcc.dg/int-bwise-opt-1.c new file mode 100644 index 0000000..11ea9ac --- /dev/null +++ b/gcc/testsuite/gcc.dg/int-bwise-opt-1.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int f1(int a, int b) +{ + return (a != b) & ((a | b) != 0); +} + +int f2(int a, int b) +{ + return (a == b) | ((a | b) == 0); +} + +int f3(int a, int b) +{ + return (a != b) & ((a | b) == 0); +} + +int f4(int a, int b) +{ + return (a == b) | ((a | b) != 0); +} + +/* { dg-final { scan-tree-dump-times "\\\|" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "\&" 0 "optimized" } } */ + +/* f3 should fold to `1` (true). */ +/* { dg-final { scan-tree-dump-times "return 1;" 1 "optimized" } } */ + +/* f4 should fold to `0` (false). */ +/* { dg-final { scan-tree-dump-times "return 0;" 1 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/int-bwise-opt-2.c b/gcc/testsuite/gcc.dg/int-bwise-opt-2.c new file mode 100644 index 0000000..cc1a48b --- /dev/null +++ b/gcc/testsuite/gcc.dg/int-bwise-opt-2.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int f1(int a, int b) +{ + return (a != b) | ((a | b) != 0); +} + +int f2(int a, int b) +{ + return (a == b) & ((a | b) == 0); +} + + /* { dg-final { scan-tree-dump-times "a == b" 0 "optimized" } } */ + /* { dg-final { scan-tree-dump-times "a != b" 0 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr122153-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr122153-1.c new file mode 100644 index 0000000..d6e7527 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr122153-1.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-phiopt1" } */ +/* PR tree-optimization/122153 */ +struct s1 +{ + int t; +}; +void g(struct s1*); +struct s1 f(int *a, int c, int d) +{ + struct s1 r; + int t1; + if (c < d) + { + r = (struct s1){}; + t1 = c; + } + else + { + r = (struct s1){}; + t1 = d; + } + g(&r); + r.t = t1; + return r; +} +/* the `r = {};` store should be commonialized out of the conditional + and produce a MIN_EXPR in phiopt1. */ + +/* { dg-final { scan-tree-dump "MIN_EXPR" "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr122104.c b/gcc/testsuite/gcc.target/i386/pr122104.c new file mode 100644 index 0000000..be88933 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr122104.c @@ -0,0 +1,12 @@ +/* PR tree-optimization/122104 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-widening_mul-alias" } */ +/* { dg-final { scan-tree-dump "\\.MUL_OVERFLOW" "widening_mul" } } */ +/* { dg-final { scan-tree-dump-not "# RANGE \\\[irange\\\] unsigned int \\\[1, " "widening_mul" } } */ + +int +foo (int x) +{ + int r = (unsigned) x * 35; + return x && ((unsigned) r / x) != 35U; +} diff --git a/gcc/testsuite/gcc.target/riscv/pr122114.c b/gcc/testsuite/gcc.target/riscv/pr122114.c new file mode 100644 index 0000000..ccb2ec9 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr122114.c @@ -0,0 +1,22 @@ +/* { dg-do compile { target { rv64 } } } */ +/* { dg-options "-O2 -fstack-clash-protection -march=rv64gcv_zvl256b -mabi=lp64d" } */ + +int pk_gen_i, pk_gen_j; +long pk_gen_buf[4]; +long pk_gen_t; + +void vec_mul(long *, long *, long *); +void uint64_is_zero_declassify(long); + +void pk_gen() { + long consts[128][13], prod[128][13]; + + vec_mul(prod[pk_gen_j], prod[pk_gen_j], consts[pk_gen_j]); + + for (; pk_gen_i;) { + for (; pk_gen_j; pk_gen_j++) + pk_gen_t |= pk_gen_buf[pk_gen_j]; + + uint64_is_zero_declassify(pk_gen_t); + } +} diff --git a/gcc/testsuite/gcc.target/riscv/pr122147.c b/gcc/testsuite/gcc.target/riscv/pr122147.c new file mode 100644 index 0000000..14da321 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr122147.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-w -march=rv64gcv -mabi=lp64d" { target rv64 } } */ +/* { dg-additional-options "-w -march=rv32gcv -mabi=ilp32" { target rv32 } } */ + +typedef __attribute__((__vector_size__ (4))) _Float16 F; +_Complex char cc; +F f; + +void +foo () +{ + __builtin_memmove (&f, &cc, 2); + f *= f; +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr118945-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr118945-1.c new file mode 100644 index 0000000..fc37bef --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr118945-1.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-mtune=generic-ooo -O3 -march=rv64gcv_zvl256b_zba -mabi=lp64d -mrvv-max-lmul=m2 -mrvv-vector-bits=scalable" } */ + +int test(int* in, int n) +{ + int accum = 0; + for (int i = 0; i < n; i++) + accum += in[i]; + + return accum; +} + +/* { dg-final { scan-assembler-times {vsetvli\s+[a-z0-9]+,\s*[a-z0-9]+,\s*e[0-9]+,\s*m[f0-9]+,\s*ta,\s*ma} 3 } } */ +/* { dg-final { scan-assembler-times {vsetvli\s+[a-z0-9]+,\s*[a-z0-9]+,\s*e[0-9]+,\s*m[f0-9]+,\s*tu,\s*ma} 1 } } */ + diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr118945-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr118945-2.c new file mode 100644 index 0000000..9565740 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr118945-2.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rva23u64 -mtune=generic-ooo -Ofast -S" } */ + +void vmult( + double* dst, + const double* src, + const unsigned int* rowstart, + const unsigned int* colnums, + const double* val, + const unsigned int n_rows +) { + const double* val_ptr = &val[rowstart[0]]; + const unsigned int* colnum_ptr = &colnums[rowstart[0]]; + double* dst_ptr = dst; + + for (unsigned int row = 0; row < n_rows; ++row) { + double s = 0.; + const double* const val_end_of_row = &val[rowstart[row + 1]]; + while (val_ptr != val_end_of_row) { + s += *val_ptr++ * src[*colnum_ptr++]; + } + *dst_ptr++ = s; + } +} + +/* { dg-final { scan-assembler-times {vsetvli\s+[a-z0-9]+,\s*[a-z0-9]+,\s*e[0-9]+,\s*m[f0-9]+,\s*ta,\s*ma} 4 } } */ +/* { dg-final { scan-assembler-times {vsetvli\s+[a-z0-9]+,\s*[a-z0-9]+,\s*e[0-9]+,\s*m[f0-9]+,\s*tu,\s*ma} 1 } } */ + diff --git a/gcc/testsuite/gfortran.dg/implied_do_io_9.f90 b/gcc/testsuite/gfortran.dg/implied_do_io_9.f90 new file mode 100644 index 0000000..5180b8a --- /dev/null +++ b/gcc/testsuite/gfortran.dg/implied_do_io_9.f90 @@ -0,0 +1,72 @@ +! { dg-do run } +! { dg-additional-options "-O2" } +! +! PR fortran/107968 +! +! Verify that array I/O optimization is not used for a section +! of an array pointer as the pointee can be non-contiguous +! +! Contributed by Nils Dreier + +PROGRAM foo + implicit none + + TYPE t_geographical_coordinates + REAL :: lon + REAL :: lat + END TYPE t_geographical_coordinates + + TYPE t_vertices + REAL, POINTER :: vlon(:) => null() + REAL, POINTER :: vlat(:) => null() + END TYPE t_vertices + + TYPE(t_geographical_coordinates), TARGET :: vertex(2) + TYPE(t_vertices), POINTER :: vertices_pointer + TYPE(t_vertices), TARGET :: vertices_target + + character(24) :: s0, s1, s2 + character(*), parameter :: fmt = '(2f8.3)' + + ! initialization + vertex%lon = [1,3] + vertex%lat = [2,4] + + ! obtain pointer to (non-contiguous) field + vertices_target%vlon => vertex%lon + + ! reference output of write + write (s0,fmt) vertex%lon + + ! set pointer vertices_pointer in a subroutine + CALL set_vertices_pointer(vertices_target) + + write (s1,fmt) vertices_pointer%vlon + write (s2,fmt) vertices_pointer%vlon(1:) + if (s1 /= s0 .or. s2 /= s0) then + print *, s0, s1, s2 + stop 3 + end if + +CONTAINS + + SUBROUTINE set_vertices_pointer(vertices) + TYPE(t_vertices), POINTER, INTENT(IN) :: vertices + + vertices_pointer => vertices + + write (s1,fmt) vertices %vlon + write (s2,fmt) vertices %vlon(1:) + if (s1 /= s0 .or. s2 /= s0) then + print *, s0, s1, s2 + stop 1 + end if + + write (s1,fmt) vertices_pointer%vlon + write (s2,fmt) vertices_pointer%vlon(1:) + if (s1 /= s0 .or. s2 /= s0) then + print *, s0, s1, s2 + stop 2 + end if + END SUBROUTINE set_vertices_pointer +END PROGRAM foo diff --git a/gcc/testsuite/gnat.dg/use_type1.adb b/gcc/testsuite/gnat.dg/use_type1.adb new file mode 100644 index 0000000..a324610 --- /dev/null +++ b/gcc/testsuite/gnat.dg/use_type1.adb @@ -0,0 +1,16 @@ +-- { dg-do compile } + +procedure Use_Type1 is + + package Nested is + type T is (X, Y, Z); + procedure Proc (Obj : T) is null; + end Nested; + + use all type Nested.T; + + Obj : Nested.T := X; + +begin + Proc (Obj); +end; diff --git a/gcc/testsuite/gnat.dg/use_type2.adb b/gcc/testsuite/gnat.dg/use_type2.adb new file mode 100644 index 0000000..8299636 --- /dev/null +++ b/gcc/testsuite/gnat.dg/use_type2.adb @@ -0,0 +1,15 @@ +-- { dg-do compile } + +with Ada.Containers.Vectors; + +procedure Use_Type2 is + + package Vectors is new Ada.Containers.Vectors (Positive, Character); + + use all type Vectors.Vector; + + X : Vectors.Vector := To_Vector (0); + +begin + Append (X, 'A'); +end; diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc index 2c6e1ea..ad09f73 100644 --- a/gcc/tree-ssa-forwprop.cc +++ b/gcc/tree-ssa-forwprop.cc @@ -5451,7 +5451,8 @@ pass_forwprop::execute (function *fun) do { gimple *orig_stmt = stmt = gsi_stmt (gsi); - bool was_noreturn = (is_gimple_call (stmt) + bool was_call = is_gimple_call (stmt); + bool was_noreturn = (was_call && gimple_call_noreturn_p (stmt)); changed = false; @@ -5465,8 +5466,10 @@ pass_forwprop::execute (function *fun) changed = true; /* There is no updating of the address taken after the last forwprop so update - the addresses when a folding happened. */ - if (last_p) + the addresses when a folding happened to a call. + The va_* builtins can remove taking of the address so + can the sincos->cexpi transformation. See PR 39643 and PR 20983. */ + if (was_call && last_p) todoflags |= TODO_update_address_taken; stmt = gsi_stmt (gsi); /* Cleanup the CFG if we simplified a condition to diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc index a9903b6..0db39f3 100644 --- a/gcc/tree-ssa-math-opts.cc +++ b/gcc/tree-ssa-math-opts.cc @@ -3834,6 +3834,7 @@ maybe_optimize_guarding_check (vec<gimple *> &mul_stmts, gimple *cond_stmt, else gimple_cond_make_false (zero_cond); update_stmt (zero_cond); + reset_flow_sensitive_info_in_bb (bb); *cfg_changed = true; } diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc index e1c9e12..bdd1f73 100644 --- a/gcc/tree-ssa-phiopt.cc +++ b/gcc/tree-ssa-phiopt.cc @@ -3645,6 +3645,7 @@ cond_if_else_store_replacement_1 (basic_block then_bb, basic_block else_bb, gimple_stmt_iterator gsi; gphi *newphi; gassign *new_stmt; + bool empty_constructor = false; if (then_assign == NULL || !gimple_assign_single_p (then_assign) @@ -3659,8 +3660,7 @@ cond_if_else_store_replacement_1 (basic_block then_bb, basic_block else_bb, return false; lhs = gimple_assign_lhs (then_assign); - if (!is_gimple_reg_type (TREE_TYPE (lhs)) - || !operand_equal_p (lhs, gimple_assign_lhs (else_assign), 0)) + if (!operand_equal_p (lhs, gimple_assign_lhs (else_assign), 0)) return false; lhs_base = get_base_address (lhs); @@ -3673,6 +3673,16 @@ cond_if_else_store_replacement_1 (basic_block then_bb, basic_block else_bb, then_locus = gimple_location (then_assign); else_locus = gimple_location (else_assign); + if (!is_gimple_reg_type (TREE_TYPE (lhs))) + { + if (!operand_equal_p (then_rhs, else_rhs)) + return false; + /* Currently only handle commoning of `= {}`. */ + if (TREE_CODE (then_rhs) != CONSTRUCTOR) + return false; + empty_constructor = true; + } + if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf(dump_file, "factoring out stores:\n\tthen:\n"); @@ -3699,12 +3709,17 @@ cond_if_else_store_replacement_1 (basic_block then_bb, basic_block else_bb, /* 2) Create a PHI node at the join block, with one argument holding the old RHS, and the other holding the temporary where we stored the old memory contents. */ - name = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "cstore"); - newphi = create_phi_node (name, join_bb); - add_phi_arg (newphi, then_rhs, EDGE_SUCC (then_bb, 0), then_locus); - add_phi_arg (newphi, else_rhs, EDGE_SUCC (else_bb, 0), else_locus); + if (empty_constructor) + name = unshare_expr (then_rhs); + else + { + name = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "cstore"); + newphi = create_phi_node (name, join_bb); + add_phi_arg (newphi, then_rhs, EDGE_SUCC (then_bb, 0), then_locus); + add_phi_arg (newphi, else_rhs, EDGE_SUCC (else_bb, 0), else_locus); + } - new_stmt = gimple_build_assign (lhs, gimple_phi_result (newphi)); + new_stmt = gimple_build_assign (lhs, name); /* Update the vdef for the new store statement. */ tree newvphilhs = make_ssa_name (gimple_vop (cfun)); tree vdef = gimple_phi_result (vphi); @@ -3715,16 +3730,21 @@ cond_if_else_store_replacement_1 (basic_block then_bb, basic_block else_bb, update_stmt (vphi); if (dump_file && (dump_flags & TDF_DETAILS)) { - fprintf(dump_file, "to use phi:\n"); - print_gimple_stmt (dump_file, newphi, 0, - TDF_VOPS|TDF_MEMSYMS); - fprintf(dump_file, "\n"); + if (!empty_constructor) + { + fprintf(dump_file, "to use phi:\n"); + print_gimple_stmt (dump_file, newphi, 0, + TDF_VOPS|TDF_MEMSYMS); + fprintf(dump_file, "\n"); + } + else + fprintf(dump_file, "to:\n"); print_gimple_stmt (dump_file, new_stmt, 0, TDF_VOPS|TDF_MEMSYMS); fprintf(dump_file, "\n\n"); } - /* 3) Insert that PHI node. */ + /* 3) Insert that new store. */ gsi = gsi_after_labels (join_bb); if (gsi_end_p (gsi)) { |