Re: fix -fmax-errors & notes

2016-10-15 Thread Andreas Schwab
On Okt 13 2016, Nathan Sidwell  wrote:

> 2016-10-13  Nathan Sidwell  
>
>   * diagnostic.c (diagnostic_action_after_output): Remove max error
>   handling here 
>   (diagnostic_report_diagnostic): ... do it here instead.

All tests that use -fmax-errors now cause the compiler to crash.

*** glibc detected *** 
/usr/local/gcc/gcc-20161015/Build/gcc/testsuite/gfortran/../../f951: free(): 
invalid pointer: 0x600524b0 ***^M

Andreas.

-- 
Andreas Schwab, sch...@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."


[patch] Do not let validize_mem modify its argument

2016-10-15 Thread Eric Botcazou
Hi,

gcc.dg/atomic/c11-atomic-exec-1.c has been failing at -O2 -mcpu=v8 on SPARC 
since the fix for PR middle-end/61268 was installed, i.e. with all 5.x, 6.x 
and 7.0 compilers.  The failure mode is as follows:

emit_cstore is called on:

(mem/c:DF (plus:SI (plus:SI (reg/f:SI 104 virtual-stack-vars)
(reg:SI 1753))
(const_int 8 [0x8])) [2 D.1567+8 S8 A64])

and does:

last = get_last_insn ();

then it calls prepare_operand, which calls copy_to_mode_reg, which calls 
emit_move_insn, which calls validize_mem, which modifies the MEM in-place:

(mem/c:DF (plus:SI (reg/f:SI 1757)
(const_int 8 [0x8])) [2 D.1567+8 S8 A64])

after emitting an addition:

(set (reg/f:SI 1757)
 (plus:SI (reg/f:SI 104 virtual-stack-vars) (reg:SI 1753)))

But the call to maybe_expand_insn from emit_cstore fails so:

 delete_insns_since (last);

is invoked and the addition is lost, i.e. (reg/f:SI 1757) will be emitted
uninitialized in the RTL stream, leading to a SIGSEGV at run time.

IMO this shows that the explow.c hunk of the fix for PR middle-end/61268 was 
ill-advised and should not have been accepted.  Having copy_to_mode_reg or 
emit_move_insn silently modify their argument is IMO a recipe for problems.

So the attached patch backs it out and I suggest installing on all branches.

Tested on x86_64-suse-linux.


2016-10-15  Eric Botcazou  

* explow.c (validize_mem): Do not modify the argument in-place.

-- 
Eric BotcazouIndex: explow.c
===
--- explow.c	(revision 241147)
+++ explow.c	(working copy)
@@ -496,9 +496,8 @@ memory_address_addr_space (machine_mode
   return x;
 }
 
-/* If REF is a MEM with an invalid address, change it into a valid address.
-   Pass through anything else unchanged.  REF must be an unshared rtx and
-   the function may modify it in-place.  */
+/* Convert a mem ref into one with a valid memory address.
+   Pass through anything else unchanged.  */
 
 rtx
 validize_mem (rtx ref)
@@ -510,7 +509,8 @@ validize_mem (rtx ref)
    MEM_ADDR_SPACE (ref)))
 return ref;
 
-  return replace_equiv_address (ref, XEXP (ref, 0), true);
+  /* Don't alter REF itself, since that is probably a stack slot.  */
+  return replace_equiv_address (ref, XEXP (ref, 0));
 }
 
 /* If X is a memory reference to a member of an object block, try rewriting


Re: fix -fmax-errors & notes

2016-10-15 Thread Nathan Sidwell

On 10/15/16 05:31, Andreas Schwab wrote:

On Okt 13 2016, Nathan Sidwell  wrote:


2016-10-13  Nathan Sidwell  

* diagnostic.c (diagnostic_action_after_output): Remove max error
handling here 
(diagnostic_report_diagnostic): ... do it here instead.


All tests that use -fmax-errors now cause the compiler to crash.

*** glibc detected *** 
/usr/local/gcc/gcc-20161015/Build/gcc/testsuite/gfortran/../../f951: free(): 
invalid pointer: 0x600524b0 ***^M


Patch reverted



Re: [PATCH] rs6000: Fix shrink-wrap-separate for AIX

2016-10-15 Thread David Edelsohn
On Fri, Oct 14, 2016 at 11:00 PM, Segher Boessenkool
 wrote:
> All out-of-line register save routines need LR, so we cannot wrap the
> LR component if there are out-of-line saves.  This didn't show up for
> testing on Linux because none of the tests there use out-of-line FPR
> saves without also using out-of-line GPR saves, which we did handle.
>
> This patch fixes it, and also cleans up code a little.
>
> Is this okay for trunk?
>
>
> Segher
>
>
> 2016-10-15  Segher Boessenkool  
>
> * config/rs6000/rs6000.c (rs6000_get_separate_components): Do not
> make LR a separately shrink-wrapped component if savres_strategy
> contains any of {SAVE,REST}_INLINE_{GPRS,FPRS,VRS}.  Do not wrap
> GPRs if {SAVE,REST}_INLINE_GPRS.  Do not disallow all wrapping
> when {SAVE,REST}_INLINE_GPRS.

This is okay.

Maybe rs6000 always should prefer inline save-restore when SWS is
enabled, except for optimize_size?

Thanks, David


Re: [PATCH] rs6000: Fix shrink-wrap-separate for AIX

2016-10-15 Thread Segher Boessenkool
On Sat, Oct 15, 2016 at 07:55:47AM -0400, David Edelsohn wrote:
> Maybe rs6000 always should prefer inline save-restore when SWS is
> enabled, except for optimize_size?

Yes, that would be a good optimization probably.

try_shrink_wrapping_separate already does nothing unless you have
optimize_function_for_speed_p (cfun), so that will do what you want
already.


Segher


Fix mode mismatch in expand_parity

2016-10-15 Thread Eric Botcazou
expand_parity attempts to generate popcount operations in wider modes and do a 
logical AND afterward, but it overlooks the mode of "target" and just do:

  if (temp != 0)
temp = expand_binop (wider_mode, and_optab, temp, const1_rtx,
 target, true, OPTAB_DIRECT);

and this ICEs if the mode of "target" is not wider_mode, as for the attached 
testcase compiled for Niagara-2 at -Os.

Tested on x86_64-suse-linux and SPARC/Solaris, applied on mainline as obvious.


2016-10-15  Eric Botcazou  

* optabs.c (expand_parity): Fix mode mismatch, add final conversion
and keep looping on failure.


2016-10-15  Eric Botcazou  

* gcc.target/sparc/popc-2.c: New test.

-- 
Eric BotcazouIndex: optabs.c
===
--- optabs.c	(revision 241147)
+++ optabs.c	(working copy)
@@ -2382,18 +2382,26 @@ expand_parity (machine_mode mode, rtx op
 
 	  last = get_last_insn ();
 
-	  if (target == 0)
-		target = gen_reg_rtx (mode);
+	  if (target == 0 || GET_MODE (target) != wider_mode)
+		target = gen_reg_rtx (wider_mode);
+
 	  xop0 = widen_operand (op0, wider_mode, mode, true, false);
 	  temp = expand_unop (wider_mode, popcount_optab, xop0, NULL_RTX,
   true);
 	  if (temp != 0)
 		temp = expand_binop (wider_mode, and_optab, temp, const1_rtx,
  target, true, OPTAB_DIRECT);
-	  if (temp == 0)
-		delete_insns_since (last);
 
-	  return temp;
+	  if (temp)
+		{
+		  if (mclass != MODE_INT
+		  || !TRULY_NOOP_TRUNCATION_MODES_P (mode, wider_mode))
+		return convert_to_mode (mode, temp, 0);
+		  else
+		return gen_lowpart (mode, temp);
+		}
+	  else
+		delete_insns_since (last);
 	}
 	}
 }
/* { dg-do compile } */
/* { dg-options "-mcpu=niagara2 -Os" } */

int foo (unsigned long long l)
{
  return __builtin_parityll (l);
}


[Patch, fortran] Implement inquire(iolength= ) for DTIO

2016-10-15 Thread Jerry DeLisle

This very simple patch implements the subject feature.

Fortran Standard draft F2016 states in 9.10.3.2:

The output list in an INQUIRE statement shall not contain any derived-type list 
items that require a defined input/output procedure as described in subclause 
9.6.3. If a derived-type list item appears in the output list, the value 
returned for the IOLENGTH= specifier assumes that no defined input/output 
procedure will be invoked.


The language seems a little obscure. I think the first sentence means don't 
expect inquire to use a UDDTIO procedure and the second sentence says when you 
use a derived type that has UDDTIO procedures in the output list, treat them as 
if they don't and use the default derived type lengths.


Regression tested on x86-64-linux. New test case attached.

I will give this a day or two for comment.

OK for trunk.

Jerry

2016-10-15  Jerry DeLisle  

* trans-io.c (transfer_expr): Ignore dtio procedures for inquire
with iolength.

2016-10-15  Jerry DeLisle  

* gfortran.dg/dtio_16.f90: New test.


diff --git a/gcc/fortran/trans-io.c b/gcc/fortran/trans-io.c
index 3cdbf1fd..216317ad 100644
--- a/gcc/fortran/trans-io.c
+++ b/gcc/fortran/trans-io.c
@@ -2325,7 +2325,7 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree 
addr_expr,
  if (derived->attr.has_dtio_procs)
arg2 = get_dtio_proc (ts, code, &dtio_sub);

- if (dtio_sub != NULL)
+ if ((dtio_sub != NULL) && (last_dt != IOLENGTH))
{
  tree decl;
  decl = build_fold_indirect_ref_loc (input_location,
! { dg-do run }
! Tests that inquire(iolength=) treats derived types as if they do not
! have User Defined procedures. Fortran Draft F2016 Standard, 9.10.3
MODULE p
  TYPE :: person
CHARACTER (LEN=20) :: name
INTEGER(4) :: age
  END TYPE person
  INTERFACE WRITE(FORMATTED)
 MODULE procedure pwf
  END INTERFACE
  INTERFACE WRITE(UNFORMATTED)
 MODULE procedure pwuf
  END INTERFACE
  INTERFACE read(FORMATTED)
 MODULE procedure prf
  END INTERFACE
  INTERFACE read(UNFORMATTED)
 MODULE procedure pruf
  END INTERFACE
CONTAINS
  SUBROUTINE pwf (dtv,unit,iotype,vlist,iostat,iomsg)
CLASS(person), INTENT(IN) :: dtv
INTEGER, INTENT(IN) :: unit
CHARACTER (LEN=*), INTENT(IN) :: iotype
INTEGER, INTENT(IN) :: vlist(:)
INTEGER, INTENT(OUT) :: iostat
CHARACTER (LEN=*), INTENT(INOUT) :: iomsg
WRITE(unit, FMT = *, IOSTAT=iostat) dtv%name, dtv%age
  END SUBROUTINE pwf

  SUBROUTINE prf (dtv,unit,iotype,vlist,iostat,iomsg)
CLASS(person), INTENT(INOUT) :: dtv
INTEGER, INTENT(IN) :: unit
CHARACTER (LEN=*), INTENT(IN) :: iotype
INTEGER, INTENT(IN) :: vlist(:)
INTEGER, INTENT(OUT) :: iostat
CHARACTER (LEN=*), INTENT(INOUT) :: iomsg
READ (UNIT = UNIT, FMT = *) dtv%name, dtv%age
  END SUBROUTINE prf

  SUBROUTINE pwuf (dtv,unit,iostat,iomsg)
CLASS(person), INTENT(IN) :: dtv
INTEGER, INTENT(IN) :: unit
INTEGER, INTENT(OUT) :: iostat
CHARACTER (LEN=*), INTENT(INOUT) :: iomsg
print *, "in pwuf"
WRITE (UNIT=UNIT, FMT = *) DTV%name, DTV%age
  END SUBROUTINE pwuf

  SUBROUTINE pruf (dtv,unit,iostat,iomsg)
CLASS(person), INTENT(INOUT) :: dtv
INTEGER, INTENT(IN) :: unit
INTEGER, INTENT(OUT) :: iostat
CHARACTER (LEN=*), INTENT(INOUT) :: iomsg
print *, "in pruf"
READ (UNIT = UNIT, FMT = *) dtv%name, dtv%age
  END SUBROUTINE pruf

END MODULE p

PROGRAM test
  USE p
  TYPE (person) :: chairman
  integer(4) :: rl, tl, kl

  chairman%name="Charlie"
  chairman%age=62

  inquire(iolength=rl) rl, kl, chairman, rl, chairman, t;
  if (rl.ne.64) call abort
END PROGRAM test


[genmatch] Introduce reverse keyword

2016-10-15 Thread Prathamesh Kulkarni
Hi Richard,
This patch makes a minor change to genmatch to add reverse keyword for iterating
over user-defined operators in reverse in for-stmt and in define_operator_list.
eg:
(for op (bit_and bit_ior)
  rop (reverse (op))
  ...)

Verified gimple-match.c and generic-match.c remain unchanged with patch.
Bootstrap+test in progress on x86_64-unknown-linux-gnu.
OK to commit if passes ?

Thanks,
Prathamesh
2016-10-16  Prathamesh Kulkarni  

* genmatch.c (parser::parse_for): Adjust for parsing reverse.
(parser::parse_operator_list): Likewise.
* match.pd: Use reverse in few patterns.
* doc/match-and-simplify.texi: Add documentation for reverse.

diff --git a/gcc/doc/match-and-simplify.texi b/gcc/doc/match-and-simplify.texi
index aaa367b..9530224 100644
--- a/gcc/doc/match-and-simplify.texi
+++ b/gcc/doc/match-and-simplify.texi
@@ -420,3 +420,13 @@ You can use the above predicate like
 Which will match a bitwise and of an operand with its logical
 inverted value.
 
+@code{reverse} can be used in for and define_operator_list for iterating
+in reverse.
+
+@smallexample
+(for opo (bit_and bit_xor)
+ opi (reverse(opo))
+ (simplify
+  (opo:c (opi:c @@0 @@1) @@1)
+  (bit_and (bit_not @@0) @@1)))
+@end smallexample
diff --git a/gcc/genmatch.c b/gcc/genmatch.c
index fc4f598..0a96784 100644
--- a/gcc/genmatch.c
+++ b/gcc/genmatch.c
@@ -4506,7 +4506,15 @@ parser::parse_for (source_location)
   int arity = -1;
   while ((token = peek_ident ()) != 0)
{
+ bool reverse = false;
  const char *oper = get_ident ();
+ if (!strcmp (oper, "reverse"))
+   {
+ reverse = true;
+ eat_token (CPP_OPEN_PAREN);
+ oper = get_ident ();
+ eat_token (CPP_CLOSE_PAREN);
+   }
  id_base *idb = get_operator (oper, true);
  if (idb == NULL)
fatal_at (token, "no such operator '%s'", oper);
@@ -4527,10 +4535,29 @@ parser::parse_for (source_location)
  if (p)
{
  if (p->is_oper_list)
-   op->substitutes.safe_splice (p->substitutes);
+   {
+ if (reverse)
+   {
+ auto_vec substitutes;
+ for (unsigned i = p->substitutes.length (); i > 0; --i)
+   substitutes.safe_push (p->substitutes[i - 1]);
+ op->substitutes.safe_splice (substitutes);
+   }
+ else
+   op->substitutes.safe_splice (p->substitutes);
+   }
+ else if (reverse)
+   {
+ auto_vec substitutes;
+ for (unsigned i = p->substitutes.length (); i > 0; --i)
+   substitutes.safe_push (p->substitutes[i - 1]);
+ op->substitutes.safe_splice (substitutes);
+   }
  else
fatal_at (token, "iterator cannot be used as operator-list");
}
+ else if (reverse)
+   fatal_at (token, "reverse can only be used on user-defined 
operators");
  else 
op->substitutes.safe_push (idb);
}
@@ -4607,6 +4634,16 @@ parser::parse_operator_list (source_location)
 {
   token = peek (); 
   const char *oper = get_ident ();
+
+  bool reverse = false;
+  if (!strcmp (oper, "reverse"))
+   {
+ reverse = true;
+ eat_token (CPP_OPEN_PAREN);
+ oper = get_ident ();
+ eat_token (CPP_CLOSE_PAREN);
+   }
+
   id_base *idb = get_operator (oper, true);
   
   if (idb == 0)
@@ -4622,7 +4659,19 @@ parser::parse_operator_list (source_location)
 
   /* We allow composition of multiple operator lists.  */
   if (user_id *p = dyn_cast (idb))
-   op->substitutes.safe_splice (p->substitutes);
+   {
+ if (reverse)
+   {
+ auto_vec substitutes;
+ for (unsigned i = p->substitutes.length (); i > 0; --i)
+   substitutes.safe_push (p->substitutes[i - 1]);
+ op->substitutes.safe_splice (substitutes);
+   }
+ else
+   op->substitutes.safe_splice (p->substitutes);
+   }
+  else if (reverse)
+   fatal_at (token, "reverse can only be applied on user-defined 
operators");
   else
op->substitutes.safe_push (idb);
 }
diff --git a/gcc/match.pd b/gcc/match.pd
index e4ff0e7..ac0ebc8 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -689,7 +689,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 /* ~x & ~y -> ~(x | y)
~x | ~y -> ~(x & y) */
 (for op (bit_and bit_ior)
- rop (bit_ior bit_and)
+ rop (reverse(op))
  (simplify
   (op (convert1? (bit_not @0)) (convert2? (bit_not @1)))
   (if (element_precision (type) <= element_precision (TREE_TYPE (@0))
@@ -730,7 +730,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 
 /* Fold (X & Y) ^ Y and (X ^ Y) & Y as ~X & Y.  */
 (for opo (bit_and bit_xor)
- opi (bi

[v3 PATCH] Make sure the return value of malloc_allocator::allocate is zero-initialized so that checking it for non-zero works later.

2016-10-15 Thread Ville Voutilainen
2016-10-15  Ville Voutilainen  

Make sure the return value of malloc_allocator::allocate
is zero-initialized so that checking it for non-zero works
later.
* include/ext/malloc_allocator.h (malloc_allocator::allocate):
Initialize the return value.
diff --git a/libstdc++-v3/include/ext/malloc_allocator.h 
b/libstdc++-v3/include/ext/malloc_allocator.h
index acb60a2..113c1dc 100644
--- a/libstdc++-v3/include/ext/malloc_allocator.h
+++ b/libstdc++-v3/include/ext/malloc_allocator.h
@@ -101,7 +101,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__n > this->max_size())
  std::__throw_bad_alloc();
 
-   pointer __ret;
+   pointer __ret = 0;
 #if __cpp_aligned_new
 #if __cplusplus > 201402L && _GLIBCXX_HAVE_ALIGNED_ALLOC
if (alignof(_Tp) > alignof(std::max_align_t))


Re: [v3 PATCH] Make sure the return value of malloc_allocator::allocate is zero-initialized so that checking it for non-zero works later.

2016-10-15 Thread Ville Voutilainen
On 15 October 2016 at 22:44, Ville Voutilainen
 wrote:
> 2016-10-15  Ville Voutilainen  
>
> Make sure the return value of malloc_allocator::allocate
> is zero-initialized so that checking it for non-zero works
> later.
> * include/ext/malloc_allocator.h (malloc_allocator::allocate):
> Initialize the return value.

A new patch, with small sanity tests added.

2016-10-15  Ville Voutilainen  

Make sure the return value of malloc_allocator::allocate
is zero-initialized so that checking it for non-zero works
later.
* include/ext/malloc_allocator.h (malloc_allocator::allocate):
Initialize the return value.
* testsuite/ext/malloc_allocator/sanity.cc: New.
diff --git a/libstdc++-v3/include/ext/malloc_allocator.h 
b/libstdc++-v3/include/ext/malloc_allocator.h
index acb60a2..113c1dc 100644
--- a/libstdc++-v3/include/ext/malloc_allocator.h
+++ b/libstdc++-v3/include/ext/malloc_allocator.h
@@ -101,7 +101,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__n > this->max_size())
  std::__throw_bad_alloc();
 
-   pointer __ret;
+   pointer __ret = 0;
 #if __cpp_aligned_new
 #if __cplusplus > 201402L && _GLIBCXX_HAVE_ALIGNED_ALLOC
if (alignof(_Tp) > alignof(std::max_align_t))
diff --git a/libstdc++-v3/testsuite/ext/malloc_allocator/sanity.cc 
b/libstdc++-v3/testsuite/ext/malloc_allocator/sanity.cc
new file mode 100644
index 000..b59e709
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/malloc_allocator/sanity.cc
@@ -0,0 +1,31 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// .
+
+// { dg-do run { target c++11 } }
+
+#include 
+#include 
+#include 
+
+int main()
+{
+  std::map,
+  __gnu_cxx::malloc_allocator > > allocs;
+  allocs[9] = 3;
+  std::vector> vec(10);
+  vec[5] = 42;
+}


C++ PATCH for c++/77945 (constexpr copy and tail padding)

2016-10-15 Thread Jason Merrill
For classes with trivial copy constructors that might have other data
packed into their tail padding, we represent the copy with an
assignment between arrays of unsigned char.  This is valid in normal
code, but constant expressions don't allow that sort of type punning,
so we need to look through it.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 9a90dc96b1aec8133f94feb12d53347a0d640fa5
Author: Jason Merrill 
Date:   Sat Oct 15 15:32:05 2016 -0400

PR c++/77945 - constexpr and trivial copy

* constexpr.c (maybe_simplify_trivial_copy): New.
(cxx_eval_store_expression): Call it.
* call.c (build_over_call): Use unsigned char for trivial copy.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 4bee487..4c19d2f 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7909,7 +7909,7 @@ build_over_call (struct z_candidate *cand, int flags, 
tsubst_flags_t complain)
  arg2 = TYPE_SIZE_UNIT (as_base);
  arg0 = cp_build_addr_expr (to, complain);
 
- array_type = build_array_type (char_type_node,
+ array_type = build_array_type (unsigned_char_type_node,
 build_index_type
   (size_binop (MINUS_EXPR,
arg2, size_int (1;
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index f5235fc..3c4fcfa 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -3206,6 +3206,26 @@ var_in_maybe_constexpr_fn (tree t)
   return var_in_constexpr_fn (t);
 }
 
+/* We're assigning INIT to TARGET.  In do_build_copy_constructor and
+   build_over_call we implement trivial copy of a class with tail padding using
+   assignment of character arrays, which is valid in normal code, but not in
+   constexpr evaluation.  We don't need to worry about clobbering tail padding
+   in constexpr evaluation, so strip the type punning.  */
+
+static void
+maybe_simplify_trivial_copy (tree &target, tree &init)
+{
+  if (TREE_CODE (target) == MEM_REF
+  && TREE_CODE (init) == MEM_REF
+  && TREE_TYPE (target) == TREE_TYPE (init)
+  && TREE_CODE (TREE_TYPE (target)) == ARRAY_TYPE
+  && TREE_TYPE (TREE_TYPE (target)) == unsigned_char_type_node)
+{
+  target = build_fold_indirect_ref (TREE_OPERAND (target, 0));
+  init = build_fold_indirect_ref (TREE_OPERAND (init, 0));
+}
+}
+
 /* Evaluate an INIT_EXPR or MODIFY_EXPR.  */
 
 static tree
@@ -3222,6 +3242,9 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree 
t,
 
   /* First we figure out where we're storing to.  */
   tree target = TREE_OPERAND (t, 0);
+
+  maybe_simplify_trivial_copy (target, init);
+
   tree type = TREE_TYPE (target);
   target = cxx_eval_constant_expression (ctx, target,
 true,
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-trivial2.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-trivial2.C
new file mode 100644
index 000..d241114
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-trivial2.C
@@ -0,0 +1,14 @@
+// PR c++/77945
+// { dg-do compile { target c++11 } }
+
+struct T 
+{ 
+int x = 0; 
+bool y = 0; 
+constexpr T() {}
+};
+
+int main()
+{
+constexpr T t = (T{} = T{});
+}


Re: [PATCH] Fix PR77826

2016-10-15 Thread Marc Glisse

On Thu, 13 Oct 2016, Richard Biener wrote:


The patch introduces '@@' captures which do two things - first they
change the comparison used for matching back to operand_equal_p
only (thus perform "value-matching"), second the @@ capture denotes
the specific operand that should be refered to in the result
section (ifs and result expressions).

When we face (plus @0 @1) (convert? @@0) for example this is lowered
to (plus @__2 @1) (convert? @__2@0) marking the @__2 match for
value handling.


Funny, I had the opposite convention in mind ;-)

On a completely artificial example:
(minus (plus (plus @0 @@0) @@0) @0)

would correspond to:
(minus (plus (plus @1  @2)  @3) @4)

where either @1 or @4 is captured as @0, say @1 for example, @4 is 
compared strictly to @1, while @2 and @3 are value-compared to @1 (lax).


This way, when we talk about @0 later in the transformation, we are indeed 
talking about the thing that was called @0 in the input pattern, while @@0 
is not-quite-@0.


But your version should be fine.


I modified the patterns you identified and the ones I did and
removed the operand_equal_p uses where possible.


Thanks. (some can be further generalized, as you explained in an earlier 
message, but we can do that later as the need arises)


--
Marc Glisse


[SPARC] Fix optimization issue with bmask

2016-10-15 Thread Eric Botcazou
The problem is that %g0 is used as destination register of the instruction and 
the CSE passes happily substitute it for the value it's supposed to contain...

Tested on SPARC/Solaris, applied on all active branches.


2016-10-15  Eric Botcazou  

* config/sparc/sparc.c (sparc_expand_vec_perm_bmask): Use a scratch
register as destination of bmask.
(vector_init_bshuffle): Likewise.
* config/sparc/sparc.md (vec_perm_constv8qi): Likewise.
(bmaskdi_vis): Enable only in 64-bit mode.


2016-10-15  Eric Botcazou  

* gcc.target/sparc/bmaskbshuf-2.c: New test.

-- 
Eric Botcazou/* { dg-do run } */
/* { dg-require-effective-target ultrasparc_vis2_hw } */
/* { dg-options "-mcpu=ultrasparc3 -O" } */

typedef unsigned int Vect __attribute__((vector_size(8)));

extern void abort (void);

Vect a, b, c, d;

__attribute__((noinline, noclone)) void test (void)
{
  Vect mask = { 2, 2 };
  int i;

  c = __builtin_shuffle (a, mask);
  d = __builtin_shuffle (a, b, mask);

  __asm__ ("" : : "r" (&c), "r" (&d) : "memory");

  for (i = 0; i < 2; ++i)
if (c[i] != a[mask[i] & 1])
  abort ();
else if (mask[i] & 2)
  {
	if (d[i] != b[mask[i] & 1])
	  abort ();
  }
}

int main (void)
{
  int i;
  for (i = 0; i < 2; ++i)
{
  a[i] = i + 2;
  b[i] = 2 + i + 2;
}

  test ();
  return 0;
}
Index: config/sparc/sparc.c
===
--- config/sparc/sparc.c	(revision 241180)
+++ config/sparc/sparc.c	(working copy)
@@ -12044,7 +12044,7 @@ sparc_expand_vec_perm_bmask (machine_mod
 }
 
   /* Always perform the final addition/merge within the bmask insn.  */
-  emit_insn (gen_bmasksi_vis (gen_rtx_REG (SImode, 0), sel, t_1));
+  emit_insn (gen_bmasksi_vis (gen_reg_rtx (SImode), sel, t_1));
 }
 
 /* Implement TARGET_FRAME_POINTER_REQUIRED.  */
@@ -12310,7 +12310,7 @@ vector_init_bshuffle (rtx target, rtx el
 }
 
   sel = force_reg (SImode, GEN_INT (bmask));
-  emit_insn (gen_bmasksi_vis (gen_rtx_REG (SImode, 0), sel, const0_rtx));
+  emit_insn (gen_bmasksi_vis (gen_reg_rtx (SImode), sel, const0_rtx));
   emit_insn (final_insn);
 }
 
Index: config/sparc/sparc.md
===
--- config/sparc/sparc.md	(revision 241147)
+++ config/sparc/sparc.md	(working copy)
@@ -8548,7 +8548,7 @@ (define_insn "bmaskdi_vis"
  (match_operand:DI 2 "register_or_zero_operand" "rJ")))
(set (zero_extract:DI (reg:DI GSR_REG) (const_int 32) (const_int 32))
 (plus:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_VIS2"
+  "TARGET_VIS2 && TARGET_ARCH64"
   "bmask\t%r1, %r2, %0"
   [(set_attr "type" "array")
(set_attr "v3pipe" "true")])
@@ -8593,7 +8593,7 @@ (define_expand "vec_perm_constv8qi"
 mask |= (INTVAL (XVECEXP (sel, 0, i)) & 0xf) << (28 - i*4);
   sel = force_reg (SImode, gen_int_mode (mask, SImode));
 
-  emit_insn (gen_bmasksi_vis (gen_rtx_REG (SImode, 0), sel, const0_rtx));
+  emit_insn (gen_bmasksi_vis (gen_reg_rtx (SImode), sel, const0_rtx));
   emit_insn (gen_bshufflev8qi_vis (operands[0], operands[1], operands[2]));
   DONE;
 })


Re: [PATCH 2/5] [AARCH64] Change IMP and PART over to integers from strings.

2016-10-15 Thread Andrew Pinski
On Wed, Nov 25, 2015 at 11:59 AM, Andrew Pinski  wrote:
> On Wed, Nov 25, 2015 at 2:31 AM, James Greenhalgh
>  wrote:
>> On Tue, Nov 17, 2015 at 02:10:35PM -0800, Andrew Pinski wrote:
>>>
>>> Because the imp and parts are really integer rather than strings, this patch
>>> moves the comparisons to be integer.  Also allows saving around integers are
>>> easier than doing string comparisons.  This allows for the next change.
>>>
>>> The way I store BIG.little is (big<<12)|little as each part num is only 
>>> 12bits
>>> long.  So it would be nice if someone could test -mpu=native on a big.little
>>> system to make sure it works still.
>>>
>>> OK?  Bootstrapped and tested on aarch64-linux-gnu with no regressions.
>>>
>>> Thanks,
>>> Andrew Pinski
>>>
>>>
>>>
>>> * config/aarch64/aarch64-cores.def: Rewrite so IMP and PART are integer 
>>> constants.
>>> * config/aarch64/driver-aarch64.c (struct aarch64_core_data): Change 
>>> implementer_id to unsigned char.
>>> Change part_no to unsigned int.
>>> (AARCH64_BIG_LITTLE): New define.
>>> (INVALID_IMP): New define.
>>> (INVALID_CORE): New define.
>>> (cpu_data): Change the last element's implementer_id and part_no to 
>>> integers.
>>> (valid_bL_string_p): Rewrite to ..
>>> (valid_bL_core_p): this for integers instead of strings.
>>> (parse_field): New function.
>>> (contains_string_p): Rewrite to ...
>>> (contains_core_p): this for integers and only for the part_no.
>>> (host_detect_local_cpu): Rewrite handling of implementation and part num to 
>>> be integers;
>>> simplifying the code.
>>> ---
>>>  gcc/config/aarch64/aarch64-cores.def | 25 +-
>>>  gcc/config/aarch64/driver-aarch64.c  | 90 
>>> 
>>>  2 files changed, 62 insertions(+), 53 deletions(-)
>>>
>>> diff --git a/gcc/config/aarch64/aarch64-cores.def 
>>> b/gcc/config/aarch64/aarch64-cores.def
>>> index 0b456f7..798f3e3 100644
>>> --- a/gcc/config/aarch64/aarch64-cores.def
>>> +++ b/gcc/config/aarch64/aarch64-cores.def
>>> @@ -33,25 +33,26 @@
>>> This need not include flags implied by the architecture.
>>> COSTS is the name of the rtx_costs routine to use.
>>> IMP is the implementer ID of the CPU vendor.  On a GNU/Linux system it 
>>> can
>>> -   be found in /proc/cpuinfo.
>>> +   be found in /proc/cpuinfo.  There is a list in the ARM ARM.
>>
>> Let's be precise with this comment.
>>
>>   "A partial list of implementer IDs is given in the ARM Architecture
>>Reference Manual ARMv8, for ARMv8-A architecture profile"
>>
>>> PART is the part number of the CPU.  On a GNU/Linux system it can be 
>>> found
>>> -   in /proc/cpuinfo.  For big.LITTLE systems this should have the form at 
>>> of
>>> -   ".".  */
>>> +   in /proc/cpuinfo.  For big.LITTLE systems this should use the macro 
>>> AARCH64_BIG_LITTLE
>>> +   where the big part number comes as the first arugment to the macro and 
>>> little is the
>>
>> s/arugment/argument/.
>>
>>> +   second.  */
>>>
>>>  /* V8 Architecture Processors.  */
>>>
>>> -AARCH64_CORE("cortex-a53",  cortexa53, cortexa53, 8A,  
>>> AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC, cortexa53, "0x41", "0xd03")
>>> -AARCH64_CORE("cortex-a57",  cortexa57, cortexa57, 8A,  
>>> AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC, cortexa57, "0x41", "0xd07")
>>> -AARCH64_CORE("cortex-a72",  cortexa72, cortexa57, 8A,  
>>> AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC, cortexa72, "0x41", "0xd08")
>>> -AARCH64_CORE("exynos-m1",   exynosm1,  cortexa57, 8A,  
>>> AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, cortexa72, 
>>> "0x53", "0x001")
>>> -AARCH64_CORE("qdf24xx", qdf24xx,   cortexa57, 8A,  
>>> AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, cortexa57, 
>>> "0x51", "0x800")
>>> -AARCH64_CORE("thunderx",thunderx,  thunderx,  8A,  
>>> AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  
>>> "0x43", "0x0a1")
>>> -AARCH64_CORE("xgene1",  xgene1,xgene1,8A,  
>>> AARCH64_FL_FOR_ARCH8, xgene1, "0x50", "0x000")
>>> +AARCH64_CORE("cortex-a53",  cortexa53, cortexa53, 8A,  
>>> AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC, cortexa53, 0x41, 0xd03)
>>> +AARCH64_CORE("cortex-a57",  cortexa57, cortexa57, 8A,  
>>> AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC, cortexa57, 0x41, 0xd07)
>>> +AARCH64_CORE("cortex-a72",  cortexa72, cortexa57, 8A,  
>>> AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC, cortexa72, 0x41, 0xd08)
>>> +AARCH64_CORE("exynos-m1",   exynosm1,  cortexa57, 8A,  
>>> AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, cortexa72, 0x53, 
>>> 0x001)
>>> +AARCH64_CORE("qdf24xx", qdf24xx,   cortexa57, 8A,  
>>> AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, cortexa57, 0x51, 
>>> 0x800)
>>> +AARCH64_CORE("thunderx",thunderx,  thunderx,  8A,  
>>> AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 
>>> 0x0a1)
>>> +AARCH64_CORE("xgene1",  xgene1,xgene1,8A,  
>>> AARCH64_FL_FOR_ARCH8, xgene1, 0x50, 0x000)
>>>
>>>  /* V8 big.LITTLE implementations.  */
>>>
>>> -AARC

RFC [1/3] divmod transform v2

2016-10-15 Thread Prathamesh Kulkarni
Hi,
After approval from Bernd Schmidt, I committed the patch to remove
optab functions for
sdivmod_optab and udivmod_optab in optabs.def, which removes the block
for divmod patch.

This patch is mostly the same as previous one, except it drops
targeting __udivmoddi4() because
it gave undefined reference link error for calling __udivmoddi4() on
aarch64-linux-gnu.
It appears aarch64 has hardware insn for DImode div, so __udivmoddi4()
isn't needed for the target
(it was a bug in my patch that called __udivmoddi4() even though
aarch64 supported hardware div).

However this makes me wonder if it's guaranteed that __udivmoddi4()
will be available for a target if it doesn't have hardware div and
divmod insn and doesn't have target-specific libfunc for
DImode divmod ? To be conservative, the attached patch doesn't
generate call to __udivmoddi4.

Passes bootstrap+test on x86_64-unknown-linux.
Cross-tested on arm*-*-*, aarch64*-*-*.
Verified that there are no regressions with SPEC2006 on
x86_64-unknown-linux-gnu.
OK to commit ?

Thanks,
Prathamesh
2016-10-15  Prathamesh Kulkarni  
Kugan Vivekanandarajah  
Jim Wilson  

* target.def: New hook expand_divmod_libfunc.
* doc/tm.texi.in: Add hook for TARGET_EXPAND_DIVMOD_LIBFUNC
* doc/tm.texi: Regenerate.
* internal-fn.def: Add new entry for DIVMOD ifn.
* internal-fn.c (expand_DIVMOD): New.
* tree-ssa-math-opts.c: Include optabs-libfuncs.h, tree-eh.h,
targhooks.h.
(widen_mul_stats): Add new field divmod_calls_inserted.
(target_supports_divmod_p): New.
(divmod_candidate_p): Likewise.
(convert_to_divmod): Likewise.
(pass_optimize_widening_mul::execute): Call
calculate_dominance_info(), renumber_gimple_stmt_uids() at
beginning of function. Call convert_to_divmod()
and record stats for divmod.

diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index a4a8e49..866c368 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -7078,6 +7078,11 @@ This is firstly introduced on ARM/AArch64 targets, 
please refer to
 the hook implementation for how different fusion types are supported.
 @end deftypefn
 
+@deftypefn {Target Hook} void TARGET_EXPAND_DIVMOD_LIBFUNC (rtx @var{libfunc}, 
machine_mode @var{mode}, rtx @var{op0}, rtx @var{op1}, rtx *@var{quot}, rtx 
*@var{rem})
+Define this hook for enabling divmod transform if the port does not have
+hardware divmod insn but defines target-specific divmod libfuncs.
+@end deftypefn
+
 @node Sections
 @section Dividing the Output into Sections (Texts, Data, @dots{})
 @c the above section title is WAY too long.  maybe cut the part between
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 265f1be..c4c387b 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -4890,6 +4890,8 @@ them: try the first ones in this list first.
 
 @hook TARGET_SCHED_FUSION_PRIORITY
 
+@hook TARGET_EXPAND_DIVMOD_LIBFUNC
+
 @node Sections
 @section Dividing the Output into Sections (Texts, Data, @dots{})
 @c the above section title is WAY too long.  maybe cut the part between
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 0b32d5f..42c6973 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -2207,6 +2207,53 @@ expand_ATOMIC_COMPARE_EXCHANGE (internal_fn, gcall *call)
   expand_ifn_atomic_compare_exchange (call);
 }
 
+/* Expand DIVMOD() using:
+ a) optab handler for udivmod/sdivmod if it is available.
+ b) If optab_handler doesn't exist, generate call to
+target-specific divmod libfunc.  */
+
+static void
+expand_DIVMOD (internal_fn, gcall *call_stmt)
+{
+  tree lhs = gimple_call_lhs (call_stmt);
+  tree arg0 = gimple_call_arg (call_stmt, 0);
+  tree arg1 = gimple_call_arg (call_stmt, 1);
+
+  gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
+  tree type = TREE_TYPE (TREE_TYPE (lhs));
+  machine_mode mode = TYPE_MODE (type);
+  bool unsignedp = TYPE_UNSIGNED (type);
+  optab tab = (unsignedp) ? udivmod_optab : sdivmod_optab;
+
+  rtx op0 = expand_normal (arg0);
+  rtx op1 = expand_normal (arg1);
+  rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
+
+  rtx quotient, remainder, libfunc;
+
+  /* Check if optab_handler exists for divmod_optab for given mode.  */
+  if (optab_handler (tab, mode) != CODE_FOR_nothing)
+{
+  quotient = gen_reg_rtx (mode);
+  remainder = gen_reg_rtx (mode);
+  expand_twoval_binop (tab, op0, op1, quotient, remainder, unsignedp);
+}
+
+  /* Generate call to divmod libfunc if it exists.  */
+  else if ((libfunc = optab_libfunc (tab, mode)) != NULL_RTX)
+targetm.expand_divmod_libfunc (libfunc, mode, op0, op1,
+  "ient, &remainder);  

+
+  else
+gcc_unreachable ();
+
+  /* Wrap the return value (quotient, remainder) within COMPLEX_EXPR.  */
+  expand_expr (build2 (COMPLEX_EXPR, TREE_TYPE (lhs),
+  

RFC [3/3] divmod transform v2 - add test cases

2016-10-15 Thread Prathamesh Kulkarni
Hi,
This patch adds test-cases for divmod transform.
OK to commit ?

Thanks,
Prathamesh
2016-10-15  Prathamesh Kulkarni  
Kugan Vivekanandarajah  
Jim Wilson  

testsuite/
* gcc.dg/divmod-1-simode.c: New test.
* gcc.dg/divmod-1.c: Likewise.
* gcc.dg/divmod-2-simode.c: Likewise.
* gcc.dg/divmod-2.c: Likewise.
* gcc.dg/divmod-3-simode.c: Likewise.
* gcc.dg/divmod-3.c: Likewise.
* gcc.dg/divmod-4-simode.c: Likewise.
* gcc.dg/divmod-4.c: Likewise.
* gcc.dg/divmod-5.c: Likewise.
* gcc.dg/divmod-6-simode.c: Likewise.
* gcc.dg/divmod-6.c: Likewise.
* gcc.dg/divmod-7.c: Likewise.

diff --git a/gcc/testsuite/gcc.dg/divmod-1-simode.c 
b/gcc/testsuite/gcc.dg/divmod-1-simode.c
new file mode 100644
index 000..9e47799
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/divmod-1-simode.c
@@ -0,0 +1,25 @@
+/* { dg-require-effective-target divmod_simode } */
+/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */
+/* div dominates mod.  */
+
+typedef int SImode __attribute__((mode(SI)));
+typedef unsigned USImode __attribute__((mode(SI)));
+
+extern int cond;
+void foo(void);
+
+#define FOO(smalltype, bigtype, no)  \
+bigtype f_##no(smalltype x, bigtype y) \
+{   \
+  bigtype q = x / y; \
+  if (cond)  \
+foo ();  \
+  bigtype r = x % y; \
+  return q + r;  \
+}
+
+FOO(SImode, SImode, 1)
+FOO(SImode, USImode, 2)
+FOO(USImode, USImode, 3)
+
+/* { dg-final { scan-tree-dump-times "DIVMOD" 3 "widening_mul" } } */
diff --git a/gcc/testsuite/gcc.dg/divmod-1.c b/gcc/testsuite/gcc.dg/divmod-1.c
new file mode 100644
index 000..edcc2a1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/divmod-1.c
@@ -0,0 +1,32 @@
+/* { dg-require-effective-target divmod } */
+/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */
+/* div dominates mod.  */
+
+typedef int SImode __attribute__((mode(SI)));
+typedef unsigned USImode __attribute__((mode(SI)));
+
+typedef int DImode __attribute__((mode(DI)));
+typedef unsigned UDImode __attribute__((mode(DI)));
+
+extern int cond;
+void foo(void);
+
+#define FOO(smalltype, bigtype, no) \
+bigtype f_##no(smalltype x, bigtype y)   \
+{   \
+  bigtype q = x / y; \
+  if (cond)  \
+foo ();  \
+  bigtype r = x % y; \
+  return q + r;  \
+}
+
+FOO(SImode, DImode, 1)
+FOO(SImode, UDImode, 2)
+FOO(USImode, DImode, 3)
+FOO(USImode, UDImode, 4)
+FOO(DImode, DImode, 5)
+FOO(DImode, UDImode, 6)
+FOO(UDImode, UDImode, 7)
+
+/* { dg-final { scan-tree-dump-times "DIVMOD" 7 "widening_mul" } } */
diff --git a/gcc/testsuite/gcc.dg/divmod-2-simode.c 
b/gcc/testsuite/gcc.dg/divmod-2-simode.c
new file mode 100644
index 000..fa28beb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/divmod-2-simode.c
@@ -0,0 +1,25 @@
+/* { dg-require-effective-target divmod_simode } */
+/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */
+/* mod dominates div.  */
+
+typedef int SImode __attribute__((mode(SI)));
+typedef unsigned USImode __attribute__((mode(SI)));
+
+extern int cond;
+void foo(void);
+
+#define FOO(smalltype, bigtype, no)  \
+bigtype f_##no(smalltype x, bigtype y) \
+{   \
+  bigtype r = x % y; \
+  if (cond)  \
+foo ();  \
+  bigtype q = x / y; \
+  return q + r;  \
+}
+
+FOO(SImode, SImode, 1)
+FOO(SImode, USImode, 2)
+FOO(USImode, USImode, 3)
+
+/* { dg-final { scan-tree-dump-times "DIVMOD" 3 "widening_mul" } } */
diff --git a/gcc/testsuite/gcc.dg/divmod-2.c b/gcc/testsuite/gcc.dg/divmod-2.c
new file mode 100644
index 000..ded732e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/divmod-2.c
@@ -0,0 +1,32 @@
+/* { dg-require-effective-target divmod } */
+/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */
+/* mod dominates div.  */
+
+typedef int SImode __attribute__((mode(SI)));
+typedef unsigned USImode __attribute__((mode(SI)));
+
+typedef int DImode __attribute__((mode(DI)));
+typedef unsigned UDImode __attribute__((mode(DI)));
+
+extern int cond;
+void foo(void);
+
+#define FOO(smalltype, bigtype, no) \
+bigtype f_##no(smalltype x, bigtype y)   \
+{   \
+  bigtype r = x % y; \
+  if (cond)  \
+foo ();  \
+  bigtype q = x / y; \
+  return q + r;  \
+}
+
+FOO(SImode, DImode, 1)
+FOO(SImode, UDImode, 2)
+FOO(USImode, DImode, 3)
+FOO(USImode, UDImode, 4)
+FOO(DImode, DImode, 5)
+FOO(DImode, UDImode, 6)
+FOO(UDImode, UDImode, 7)
+
+/* { dg-final { scan-tree-dump-times 

RFC [2/3] divmod transform v2 - override expand_divmod_libfunc for ARM port

2016-10-15 Thread Prathamesh Kulkarni
Hi,
This patch overrides expand_divmod_libfunc hook for ARM port.
I separated the SImode tests into separate file from DImode tests
because certain arm configs (cortex-15) have hardware div insn for
SImode but not for DImode, and for that config we want SImode tests to
be disabled but not DImode tests. The patch therefore has two
target-effective checks: divmod and divmod_simode.
Cross-tested on arm*-*-*.
OK to commit ?

Thanks,
Prathamesh
2016-10-15  Prathamesh Kulkarni  
Kugan Vivekanandarajah  
Jim Wilson  

* config/arm/arm.c (arm_expand_divmod_libfunc): Override hook
TARGET_EXPAND_DIVMOD_LIBFUNC.
* doc/sourcebuild.texi: Add items for arm_divmod_simode, divmod,
divmod_simode.

testsuite/
* lib/target-supports.exp (check_effective_target_divmod): New.
(check_effective_target_divmod_simode): Likewise. 
(check_effective_target_arm_divmod_simode): Likewise.

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 39e3aa8..b1a6aeb 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -62,6 +62,7 @@
 #include "builtins.h"
 #include "tm-constrs.h"
 #include "rtl-iter.h"
+#include "optabs-libfuncs.h"
 
 /* This file should be included last.  */
 #include "target-def.h"
@@ -304,6 +305,7 @@ static section *arm_function_section (tree, enum 
node_frequency, bool, bool);
 static bool arm_asm_elf_flags_numeric (unsigned int flags, unsigned int *num);
 static unsigned int arm_elf_section_type_flags (tree decl, const char *name,
int reloc);
+static void arm_expand_divmod_libfunc (rtx, machine_mode, rtx, rtx, rtx *, rtx 
*);
 
 /* Table of machine attributes.  */
 static const struct attribute_spec arm_attribute_table[] =
@@ -739,6 +741,9 @@ static const struct attribute_spec arm_attribute_table[] =
 #undef TARGET_SECTION_TYPE_FLAGS
 #define TARGET_SECTION_TYPE_FLAGS arm_elf_section_type_flags
 
+#undef TARGET_EXPAND_DIVMOD_LIBFUNC
+#define TARGET_EXPAND_DIVMOD_LIBFUNC arm_expand_divmod_libfunc
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Obstack for minipool constant handling.  */
@@ -30776,4 +30781,33 @@ arm_elf_section_type_flags (tree decl, const char 
*name, int reloc)
   return flags;
 }
 
+/* Generate call to __aeabi_[mode]divmod (op0, op1).  */
+
+static void
+arm_expand_divmod_libfunc (rtx libfunc, machine_mode mode,
+  rtx op0, rtx op1,
+  rtx *quot_p, rtx *rem_p)
+{
+  if (mode == SImode)
+gcc_assert (!TARGET_IDIV);
+
+  machine_mode libval_mode = smallest_mode_for_size (2 * GET_MODE_BITSIZE 
(mode),
+MODE_INT);
+
+  rtx libval = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
+   libval_mode, 2,
+   op0, GET_MODE (op0),
+   op1, GET_MODE (op1));
+
+  rtx quotient = simplify_gen_subreg (mode, libval, libval_mode, 0);
+  rtx remainder = simplify_gen_subreg (mode, libval, libval_mode,
+  GET_MODE_SIZE (mode));
+
+  gcc_assert (quotient);
+  gcc_assert (remainder);
+
+  *quot_p = quotient;
+  *rem_p = remainder;
+}
+
 #include "gt-arm.h"
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 07c75e2..39de0ff 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -1675,6 +1675,10 @@ and @code{MOVT} instructions available.
 ARM target generates Thumb-1 code for @code{-mthumb} with
 @code{CBZ} and @code{CBNZ} instructions available.
 
+@item arm_divmod_simode
+ARM target for which divmod transform is disabled, if it supports hardware
+div instruction.
+
 @end table
 
 @subsubsection AArch64-specific attributes
@@ -1848,6 +1852,13 @@ Target requires a command line argument to enable a SIMD 
instruction set.
 
 @item pie_copyreloc
 The x86-64 target linker supports PIE with copy reloc.
+
+@item divmod
+Target supporting hardware divmod insn or divmod libcall.
+
+@item divmod_simode
+Target supporting hardware divmod insn or divmod libcall for SImode.
+
 @end table
 
 @subsubsection Environment attributes
diff --git a/gcc/testsuite/lib/target-supports.exp 
b/gcc/testsuite/lib/target-supports.exp
index 201ed4b..fc5e37f 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -8070,3 +8070,41 @@ proc check_effective_target_profile_update_atomic {} {
int main (void) { return 0; }
 } "-fprofile-update=atomic -fprofile-generate"]
 }
+
+#For versions of ARM architectures that have hardware div insn,
+#disable the divmod transform
+
+proc check_effective_target_arm_divmod_simode { } {
+return [check_no_compiler_messages arm_divmod assembly {
+   #ifdef __ARM_ARCH_EXT_IDIV__
+   #error has div insn
+   #endif
+   int i;
+}]
+}
+
+# Return 1 if target supports divmod hardware insn or divmod libcall.
+
+proc chec

[PATCH, libfortran] PR 48587 Newunit allocator, cleanup

2016-10-15 Thread Janne Blomqvist
Improve error message, and remove a redundant check, as the same check is
done a bit earlier due to the PR 48587 patch.

2016-10-16  Janne Blomqvist  

PR libfortran/48587
* io/transfer.c (data_transfer_init): Improve error message,
remove redundant check.

Regtested on x86_64-pc-linux-gnu. Committed as obvious.
---
 libgfortran/io/transfer.c | 11 ++-
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c
index 7696cca..2232417 100644
--- a/libgfortran/io/transfer.c
+++ b/libgfortran/io/transfer.c
@@ -2606,7 +2606,8 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag)
   /* This means we tried to access an external unit < 0 without
 having opened it first with NEWUNIT=.  */
   generate_error (&dtp->common, LIBERROR_BAD_OPTION,
- "Invalid unit number in statement");
+ "Unit number is negative and unit was not already "
+ "opened with OPEN(NEWUNIT=...)");
   return;
 }
   else if (dtp->u.p.current_unit->s == NULL)
@@ -2614,14 +2615,6 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag)
st_parameter_open opp;
unit_convert conv;
 
-  if (dtp->common.unit < 0 && !is_internal_unit (dtp))
-   {
- close_unit (dtp->u.p.current_unit);
- dtp->u.p.current_unit = NULL;
- generate_error (&dtp->common, LIBERROR_BAD_OPTION,
- "Bad unit number in statement");
- return;
-   }
   memset (&u_flags, '\0', sizeof (u_flags));
   u_flags.access = ACCESS_SEQUENTIAL;
   u_flags.action = ACTION_READWRITE;
-- 
2.7.4