[PATCH 1/6] RISC-V Port: gcc/config/riscv/riscv.c

2017-02-05 Thread Palmer Dabbelt
---
 gcc/config/riscv/riscv.c | 4138 ++
 1 file changed, 4138 insertions(+)
 create mode 100644 gcc/config/riscv/riscv.c

diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
new file mode 100644
index 000..834651f
--- /dev/null
+++ b/gcc/config/riscv/riscv.c
@@ -0,0 +1,4138 @@
+/* Subroutines used for code generation for RISC-V.
+   Copyright (C) 2011-2017 Free Software Foundation, Inc.
+   Contributed by Andrew Waterman (and...@sifive.com).
+   Based on MIPS target for GNU compiler.
+
+This file is part of GCC.
+
+GCC 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.
+
+GCC 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 GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "insn-attr.h"
+#include "recog.h"
+#include "output.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "vec.h"
+#include "double-int.h"
+#include "input.h"
+#include "alias.h"
+#include "symtab.h"
+#include "wide-int.h"
+#include "inchash.h"
+#include "tree.h"
+#include "fold-const.h"
+#include "varasm.h"
+#include "stringpool.h"
+#include "stor-layout.h"
+#include "calls.h"
+#include "function.h"
+#include "hashtab.h"
+#include "flags.h"
+#include "statistics.h"
+#include "real.h"
+#include "fixed-value.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "memmodel.h"
+#include "emit-rtl.h"
+#include "stmt.h"
+#include "expr.h"
+#include "insn-codes.h"
+#include "optabs.h"
+#include "libfuncs.h"
+#include "reload.h"
+#include "tm_p.h"
+#include "ggc.h"
+#include "gstab.h"
+#include "hash-table.h"
+#include "debug.h"
+#include "target.h"
+#include "target-def.h"
+#include "common/common-target.h"
+#include "langhooks.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "cfgrtl.h"
+#include "cfganal.h"
+#include "lcm.h"
+#include "cfgbuild.h"
+#include "cfgcleanup.h"
+#include "predict.h"
+#include "basic-block.h"
+#include "bitmap.h"
+#include "regset.h"
+#include "df.h"
+#include "sched-int.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-fold.h"
+#include "tree-eh.h"
+#include "gimple-expr.h"
+#include "is-a.h"
+#include "gimple.h"
+#include "gimplify.h"
+#include "diagnostic.h"
+#include "target-globals.h"
+#include "opts.h"
+#include "tree-pass.h"
+#include "context.h"
+#include "hash-map.h"
+#include "plugin-api.h"
+#include "ipa-ref.h"
+#include "cgraph.h"
+#include "builtins.h"
+#include "rtl-iter.h"
+
+/* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF.  */
+#define UNSPEC_ADDRESS_P(X)\
+  (GET_CODE (X) == UNSPEC  \
+   && XINT (X, 1) >= UNSPEC_ADDRESS_FIRST  \
+   && XINT (X, 1) < UNSPEC_ADDRESS_FIRST + NUM_SYMBOL_TYPES)
+
+/* Extract the symbol or label from UNSPEC wrapper X.  */
+#define UNSPEC_ADDRESS(X) \
+  XVECEXP (X, 0, 0)
+
+/* Extract the symbol type from UNSPEC wrapper X.  */
+#define UNSPEC_ADDRESS_TYPE(X) \
+  ((enum riscv_symbol_type) (XINT (X, 1) - UNSPEC_ADDRESS_FIRST))
+
+/* True if bit BIT is set in VALUE.  */
+#define BITSET_P(VALUE, BIT) (((VALUE) & (1ULL << (BIT))) != 0)
+
+/* Classifies an address.
+
+   ADDRESS_REG
+   A natural register + offset address.  The register satisfies
+   riscv_valid_base_register_p and the offset is a const_arith_operand.
+
+   ADDRESS_LO_SUM
+   A LO_SUM rtx.  The first operand is a valid base register and
+   the second operand is a symbolic address.
+
+   ADDRESS_CONST_INT
+   A signed 16-bit constant address.
+
+   ADDRESS_SYMBOLIC:
+   A constant symbolic address.  */
+enum riscv_address_type {
+  ADDRESS_REG,
+  ADDRESS_LO_SUM,
+  ADDRESS_CONST_INT,
+  ADDRESS_SYMBOLIC
+};
+
+/* Information about a function's frame layout.  */
+struct GTY(())  riscv_frame_info {
+  /* The size of the frame in bytes.  */
+  HOST_WIDE_INT total_size;
+
+  /* Bit X is set if the function saves or restores GPR X.  */
+  unsigned int mask;
+
+  /* Likewise FPR X.  */
+  unsigned int fmask;
+
+  /* How much the GPR save/restore routines adjust sp (or 0 if unused).  */
+  unsigned save_libcall_adjustment;
+
+  /* Offsets of fixed-point and floating-point save areas from frame bottom */
+  HOST_WIDE_INT gp_sp_offset;
+  HOST_WIDE_INT fp_sp_offset;
+
+  /* Offset of virtual frame pointer from stack 

[PATCH 1/6] RISC-V Port: gcc/config/riscv/riscv.c

2017-02-02 Thread Palmer Dabbelt
---
 gcc/config/riscv/riscv.c | 4138 ++
 1 file changed, 4138 insertions(+)
 create mode 100644 gcc/config/riscv/riscv.c

diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
new file mode 100644
index 000..834651f
--- /dev/null
+++ b/gcc/config/riscv/riscv.c
@@ -0,0 +1,4138 @@
+/* Subroutines used for code generation for RISC-V.
+   Copyright (C) 2011-2017 Free Software Foundation, Inc.
+   Contributed by Andrew Waterman (and...@sifive.com).
+   Based on MIPS target for GNU compiler.
+
+This file is part of GCC.
+
+GCC 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.
+
+GCC 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 GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "insn-attr.h"
+#include "recog.h"
+#include "output.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "vec.h"
+#include "double-int.h"
+#include "input.h"
+#include "alias.h"
+#include "symtab.h"
+#include "wide-int.h"
+#include "inchash.h"
+#include "tree.h"
+#include "fold-const.h"
+#include "varasm.h"
+#include "stringpool.h"
+#include "stor-layout.h"
+#include "calls.h"
+#include "function.h"
+#include "hashtab.h"
+#include "flags.h"
+#include "statistics.h"
+#include "real.h"
+#include "fixed-value.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "memmodel.h"
+#include "emit-rtl.h"
+#include "stmt.h"
+#include "expr.h"
+#include "insn-codes.h"
+#include "optabs.h"
+#include "libfuncs.h"
+#include "reload.h"
+#include "tm_p.h"
+#include "ggc.h"
+#include "gstab.h"
+#include "hash-table.h"
+#include "debug.h"
+#include "target.h"
+#include "target-def.h"
+#include "common/common-target.h"
+#include "langhooks.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "cfgrtl.h"
+#include "cfganal.h"
+#include "lcm.h"
+#include "cfgbuild.h"
+#include "cfgcleanup.h"
+#include "predict.h"
+#include "basic-block.h"
+#include "bitmap.h"
+#include "regset.h"
+#include "df.h"
+#include "sched-int.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-fold.h"
+#include "tree-eh.h"
+#include "gimple-expr.h"
+#include "is-a.h"
+#include "gimple.h"
+#include "gimplify.h"
+#include "diagnostic.h"
+#include "target-globals.h"
+#include "opts.h"
+#include "tree-pass.h"
+#include "context.h"
+#include "hash-map.h"
+#include "plugin-api.h"
+#include "ipa-ref.h"
+#include "cgraph.h"
+#include "builtins.h"
+#include "rtl-iter.h"
+
+/* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF.  */
+#define UNSPEC_ADDRESS_P(X)\
+  (GET_CODE (X) == UNSPEC  \
+   && XINT (X, 1) >= UNSPEC_ADDRESS_FIRST  \
+   && XINT (X, 1) < UNSPEC_ADDRESS_FIRST + NUM_SYMBOL_TYPES)
+
+/* Extract the symbol or label from UNSPEC wrapper X.  */
+#define UNSPEC_ADDRESS(X) \
+  XVECEXP (X, 0, 0)
+
+/* Extract the symbol type from UNSPEC wrapper X.  */
+#define UNSPEC_ADDRESS_TYPE(X) \
+  ((enum riscv_symbol_type) (XINT (X, 1) - UNSPEC_ADDRESS_FIRST))
+
+/* True if bit BIT is set in VALUE.  */
+#define BITSET_P(VALUE, BIT) (((VALUE) & (1ULL << (BIT))) != 0)
+
+/* Classifies an address.
+
+   ADDRESS_REG
+   A natural register + offset address.  The register satisfies
+   riscv_valid_base_register_p and the offset is a const_arith_operand.
+
+   ADDRESS_LO_SUM
+   A LO_SUM rtx.  The first operand is a valid base register and
+   the second operand is a symbolic address.
+
+   ADDRESS_CONST_INT
+   A signed 16-bit constant address.
+
+   ADDRESS_SYMBOLIC:
+   A constant symbolic address.  */
+enum riscv_address_type {
+  ADDRESS_REG,
+  ADDRESS_LO_SUM,
+  ADDRESS_CONST_INT,
+  ADDRESS_SYMBOLIC
+};
+
+/* Information about a function's frame layout.  */
+struct GTY(())  riscv_frame_info {
+  /* The size of the frame in bytes.  */
+  HOST_WIDE_INT total_size;
+
+  /* Bit X is set if the function saves or restores GPR X.  */
+  unsigned int mask;
+
+  /* Likewise FPR X.  */
+  unsigned int fmask;
+
+  /* How much the GPR save/restore routines adjust sp (or 0 if unused).  */
+  unsigned save_libcall_adjustment;
+
+  /* Offsets of fixed-point and floating-point save areas from frame bottom */
+  HOST_WIDE_INT gp_sp_offset;
+  HOST_WIDE_INT fp_sp_offset;
+
+  /* Offset of virtual frame pointer from stack 

Re: [PATCH 1/6] RISC-V Port: gcc/config/riscv/riscv.c

2017-01-31 Thread Andrew Waterman
On Tue, Jan 31, 2017 at 10:01 AM, Richard Henderson  wrote:
> On 01/30/2017 04:53 PM, Andrew Waterman wrote:
>> The ISA spec references an out-of-date calling convention, and will be
>> removed in the next revision to orthogonalize the ABI from the ISA.
>> We are in the process of drafting a RISC-V ELF psABI spec, which the
>> GCC port targets.
>> https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md
>> In this calling convention, the GPRs and FPRs are allocated
>> separately, which is more performant, especially when XLEN and FLEN
>> are not equal.
>
> Good to know.
>
> Re the new spec, you don't require arguments stored in two fp registers to be
> aligned, but you do require arguments stored in two int registers to be
> aligned?  Why?
>
> I see that as a waste when it comes to argument lists (for xlen=32) like
>
>   void foo(class *x, int64_t y, int a, int b, int c, int d)
>
> It's not as if the ISA has a store-multiple-register instruction that requires
> even register numbers...

We will reconsider only aligning arguments in the varargs case.

>
>
> r~


Re: [PATCH 1/6] RISC-V Port: gcc/config/riscv/riscv.c

2017-01-31 Thread Richard Henderson
On 01/30/2017 04:53 PM, Andrew Waterman wrote:
> The ISA spec references an out-of-date calling convention, and will be
> removed in the next revision to orthogonalize the ABI from the ISA.
> We are in the process of drafting a RISC-V ELF psABI spec, which the
> GCC port targets.
> https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md
> In this calling convention, the GPRs and FPRs are allocated
> separately, which is more performant, especially when XLEN and FLEN
> are not equal.

Good to know.

Re the new spec, you don't require arguments stored in two fp registers to be
aligned, but you do require arguments stored in two int registers to be
aligned?  Why?

I see that as a waste when it comes to argument lists (for xlen=32) like

  void foo(class *x, int64_t y, int a, int b, int c, int d)

It's not as if the ISA has a store-multiple-register instruction that requires
even register numbers...


r~


Re: [PATCH 1/6] RISC-V Port: gcc/config/riscv/riscv.c

2017-01-30 Thread Andrew Waterman
Thanks for the feedback, Richard.  We've addressed the bulk of it, and
added some explanatory comments in the few cases where the current
implementation makes sense, but for less than obvious reasons.  We
will submit a v2 patch set reflecting these changes in the next couple
of days.

A few responses are in-line below.

On Fri, Jan 20, 2017 at 6:32 PM, Richard Henderson  wrote:
>
> On 01/11/2017 06:30 PM, Palmer Dabbelt wrote:
>>
>> +/* The largest number of operations needed to load an integer constant.
>> +   The worst case is LUI, ADDI, SLLI, ADDI, SLLI, ADDI, SLLI, ADDI,
>> +   but we may attempt and reject even worse sequences.  */
>> +#define RISCV_MAX_INTEGER_OPS 32
>
>
> Why would you?  Surely after you exhaust 8 you'd just abandon that search as 
> unprofitable.
>
>> +  if (cost > 2 && (value & 1) == 0)
>> +{
>> +  int shift = 0;
>> +  while ((value & 1) == 0)
>> +   shift++, value >>= 1;
>
>
>   shift = ctz_hwi (value);
>
> You also may want to test for
>
>   value | (HOST_WIDE_INT_M1U << (HOST_BITS_PER_WIDE_INT - shift))
>
> i.e. shifting out leading 1's.  As well as checking with shift - 12.  The 
> latter is interesting for shifting a 20-bit value up into the high word.
>
> I once proposed a generic framework for this that cached results for 
> computation of sequences and costs.  Unfortunately it never gained traction. 
> Perhaps it's time to try again.
>
>> +  /* Try filling trailing bits with 1s.  */
>> +  while ((value << shift) >= 0)
>> +   shift++;
>
>
> clz_hwi.
>
>> +  return GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x) != 0;
>
>
> SYMBOL_REF_P.
>
>> +riscv_symbol_binds_local_p (const_rtx x)
>> +{
>> +  return (SYMBOL_REF_DECL (x)
>> + ? targetm.binds_local_p (SYMBOL_REF_DECL (x))
>> + : SYMBOL_REF_LOCAL_P (x));
>
>
> Missing SYMOL_REF_P?
>
> Surely encode_section_info will already have set SYMBOL_FLAG_LOCAL, and thus 
> you need not invoke targetm.binds_local_p again.
>
>> +case LABEL_REF:
>> +  if (LABEL_REF_NONLOCAL_P (x))
>> +   return SYMBOL_GOT_DISP;
>> +  break;
>
>
> Non-local labels are not local to the current function, but they are still 
> local to the translation unit (they'll be local to one of the outer functions 
> of a nested function).
>
>> +  switch (*symbol_type)
>> +{
>> +case SYMBOL_ABSOLUTE:
>> +case SYMBOL_PCREL:
>> +case SYMBOL_TLS_LE:
>> +  return (int32_t) INTVAL (offset) == INTVAL (offset);
>
>
> Why?
>
>
>> +case MINUS:
>> +  if (float_mode_p
>> + && !HONOR_NANS (mode)
>> + && !HONOR_SIGNED_ZEROS (mode))
>> +   {
>> + /* See if we can use NMADD or NMSUB.  See riscv.md for the
>> +associated patterns.  */
>> + rtx op0 = XEXP (x, 0);
>> + rtx op1 = XEXP (x, 1);
>> + if (GET_CODE (op0) == MULT && GET_CODE (XEXP (op0, 0)) == NEG)
>> +   {
>> + *total = (tune_info->fp_mul[mode == DFmode]
>> +   + set_src_cost (XEXP (XEXP (op0, 0), 0), mode, speed)
>> +   + set_src_cost (XEXP (op0, 1), mode, speed)
>> +   + set_src_cost (op1, mode, speed));
>> + return true;
>> +   }
>> + if (GET_CODE (op1) == MULT)
>> +   {
>> + *total = (tune_info->fp_mul[mode == DFmode]
>> +   + set_src_cost (op0, mode, speed)
>> +   + set_src_cost (XEXP (op1, 0), mode, speed)
>> +   + set_src_cost (XEXP (op1, 1), mode, speed));
>> + return true;
>> +   }
>> +   }
>
>
> Do we not fold these to FMA + NEG?  If not, that's surprising and maybe 
> should be fixed.  Also, you appear to be missing costs for FMA in 
> riscv_rtx_costs.
>
>> +   case UNORDERED:
>> + *code = EQ;
>> + /* Fall through.  */
>> +
>> +   case ORDERED:
>> + /* a == a && b == b */
>> + tmp0 = gen_reg_rtx (SImode);
>> + riscv_emit_binary (EQ, tmp0, cmp_op0, cmp_op0);
>> + tmp1 = gen_reg_rtx (SImode);
>> + riscv_emit_binary (EQ, tmp1, cmp_op1, cmp_op1);
>> + *op0 = gen_reg_rtx (SImode);
>> + riscv_emit_binary (AND, *op0, tmp0, tmp1);
>> + break;
>
>
> Better with FCLASS + AND?  At least for a branch?

The code path is slightly shorter using FEQ instead.  If FEQ were two
or more cycles slower than FCLASS, then FCLASS would be a win for
latency, but that is not the case for any known implementation.

>
>> +static int
>> +riscv_flatten_aggregate_field (const_tree type,
>> +  riscv_aggregate_field fields[2],
>> +  int n, HOST_WIDE_INT offset)
>
>
> I don't see any code within to bound N to 2, so as not to overflow FIELDS.  
> Am I missing something?
>
> Are you missing code for COMPLEX_TYPE?  In the default case I only see 
> SCALAR_FLOAT_TYPE_P.
>
>> +  memset (info, 0, sizeof (*info));
>> +  

Re: [PATCH 1/6] RISC-V Port: gcc/config/riscv/riscv.c

2017-01-20 Thread Richard Henderson

On 01/11/2017 06:30 PM, Palmer Dabbelt wrote:

+/* The largest number of operations needed to load an integer constant.
+   The worst case is LUI, ADDI, SLLI, ADDI, SLLI, ADDI, SLLI, ADDI,
+   but we may attempt and reject even worse sequences.  */
+#define RISCV_MAX_INTEGER_OPS 32


Why would you?  Surely after you exhaust 8 you'd just abandon that search as 
unprofitable.



+  if (cost > 2 && (value & 1) == 0)
+{
+  int shift = 0;
+  while ((value & 1) == 0)
+   shift++, value >>= 1;


  shift = ctz_hwi (value);

You also may want to test for

  value | (HOST_WIDE_INT_M1U << (HOST_BITS_PER_WIDE_INT - shift))

i.e. shifting out leading 1's.  As well as checking with shift - 12.  The 
latter is interesting for shifting a 20-bit value up into the high word.


I once proposed a generic framework for this that cached results for 
computation of sequences and costs.  Unfortunately it never gained traction. 
Perhaps it's time to try again.



+  /* Try filling trailing bits with 1s.  */
+  while ((value << shift) >= 0)
+   shift++;


clz_hwi.


+  return GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x) != 0;


SYMBOL_REF_P.


+riscv_symbol_binds_local_p (const_rtx x)
+{
+  return (SYMBOL_REF_DECL (x)
+ ? targetm.binds_local_p (SYMBOL_REF_DECL (x))
+ : SYMBOL_REF_LOCAL_P (x));


Missing SYMOL_REF_P?

Surely encode_section_info will already have set SYMBOL_FLAG_LOCAL, and thus 
you need not invoke targetm.binds_local_p again.



+case LABEL_REF:
+  if (LABEL_REF_NONLOCAL_P (x))
+   return SYMBOL_GOT_DISP;
+  break;


Non-local labels are not local to the current function, but they are still 
local to the translation unit (they'll be local to one of the outer functions 
of a nested function).



+  switch (*symbol_type)
+{
+case SYMBOL_ABSOLUTE:
+case SYMBOL_PCREL:
+case SYMBOL_TLS_LE:
+  return (int32_t) INTVAL (offset) == INTVAL (offset);


Why?


+case MINUS:
+  if (float_mode_p
+ && !HONOR_NANS (mode)
+ && !HONOR_SIGNED_ZEROS (mode))
+   {
+ /* See if we can use NMADD or NMSUB.  See riscv.md for the
+associated patterns.  */
+ rtx op0 = XEXP (x, 0);
+ rtx op1 = XEXP (x, 1);
+ if (GET_CODE (op0) == MULT && GET_CODE (XEXP (op0, 0)) == NEG)
+   {
+ *total = (tune_info->fp_mul[mode == DFmode]
+   + set_src_cost (XEXP (XEXP (op0, 0), 0), mode, speed)
+   + set_src_cost (XEXP (op0, 1), mode, speed)
+   + set_src_cost (op1, mode, speed));
+ return true;
+   }
+ if (GET_CODE (op1) == MULT)
+   {
+ *total = (tune_info->fp_mul[mode == DFmode]
+   + set_src_cost (op0, mode, speed)
+   + set_src_cost (XEXP (op1, 0), mode, speed)
+   + set_src_cost (XEXP (op1, 1), mode, speed));
+ return true;
+   }
+   }


Do we not fold these to FMA + NEG?  If not, that's surprising and maybe should 
be fixed.  Also, you appear to be missing costs for FMA in riscv_rtx_costs.



+   case UNORDERED:
+ *code = EQ;
+ /* Fall through.  */
+
+   case ORDERED:
+ /* a == a && b == b */
+ tmp0 = gen_reg_rtx (SImode);
+ riscv_emit_binary (EQ, tmp0, cmp_op0, cmp_op0);
+ tmp1 = gen_reg_rtx (SImode);
+ riscv_emit_binary (EQ, tmp1, cmp_op1, cmp_op1);
+ *op0 = gen_reg_rtx (SImode);
+ riscv_emit_binary (AND, *op0, tmp0, tmp1);
+ break;


Better with FCLASS + AND?  At least for a branch?


+static int
+riscv_flatten_aggregate_field (const_tree type,
+  riscv_aggregate_field fields[2],
+  int n, HOST_WIDE_INT offset)


I don't see any code within to bound N to 2, so as not to overflow FIELDS.  Am 
I missing something?


Are you missing code for COMPLEX_TYPE?  In the default case I only see 
SCALAR_FLOAT_TYPE_P.



+  memset (info, 0, sizeof (*info));
+  info->gpr_offset = cum->num_gprs;
+  info->fpr_offset = cum->num_fprs;


Since GPRs and FPRs are allocated sequentially, and indicies that are used for 
GPRs are unused in FPRs and vice versa, why store both gpr_offset and gpr_offset?



+/* Emit straight-line code to move LENGTH bytes from SRC to DEST.
+   Assume that the areas do not overlap.  */
+
+static void
+riscv_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length)
+{
+  HOST_WIDE_INT offset, delta;
+  unsigned HOST_WIDE_INT bits;
+  int i;
+  enum machine_mode mode;
+  rtx *regs;
+
+  bits = MAX (BITS_PER_UNIT,
+ MIN (BITS_PER_WORD, MIN (MEM_ALIGN (src), MEM_ALIGN (dest;
+
+  mode = mode_for_size (bits, MODE_INT, 0);
+  delta = bits / BITS_PER_UNIT;
+
+  /* Allocate a buffer for the temporary registers.  */
+  regs = XALLOCAVEC (rtx, length / delta);
+
+  /* Load as many BITS-sized chunks as possible.  Use a normal 

Re: [PATCH 1/6] RISC-V Port: gcc/config/riscv/riscv.c

2017-01-16 Thread Andrew Waterman
On Thu, Jan 12, 2017 at 1:38 PM, Joseph Myers  wrote:
> On Wed, 11 Jan 2017, Palmer Dabbelt wrote:
>
>> +#include 
>
> This is included in system.h, so don't include it here.

OK.

>
>> +  error ("unknown cpu `%s' for -mtune", cpu_string);
>
> This is using very-old-style `' quotes.  Diagnostics should use e.g. %qs
> for quoting the output of a single % directive, or %< and %> for quoting
> anything more complicated, so that Unicode quotes can be used when the
> locale permits.
>
> Likewise elsewhere in this patch and in patch 2.

Will do, throughout.

>
>> +#undef TARGET_LRA_P
>> +#define TARGET_LRA_P hook_bool_void_true
>
> Using LRA is the default; you shouldn't need this definition.

Ah, glad to see LRA is now the default.

>
> I don't see a definition of TARGET_ATOMIC_ASSIGN_EXPAND_FENV.  Since you
> have floating-point exceptions, I'd expect lack this to result in
> c11-atomic-exec-5.c failing.

Indeed, and after implementing the hook, those failures disappeared.  Thanks.

>
> --
> Joseph S. Myers
> jos...@codesourcery.com


Re: [PATCH 1/6] RISC-V Port: gcc/config/riscv/riscv.c

2017-01-12 Thread Joseph Myers
On Wed, 11 Jan 2017, Palmer Dabbelt wrote:

> +#include 

This is included in system.h, so don't include it here.

> +  error ("unknown cpu `%s' for -mtune", cpu_string);

This is using very-old-style `' quotes.  Diagnostics should use e.g. %qs 
for quoting the output of a single % directive, or %< and %> for quoting 
anything more complicated, so that Unicode quotes can be used when the 
locale permits.

Likewise elsewhere in this patch and in patch 2.

> +#undef TARGET_LRA_P
> +#define TARGET_LRA_P hook_bool_void_true

Using LRA is the default; you shouldn't need this definition.

I don't see a definition of TARGET_ATOMIC_ASSIGN_EXPAND_FENV.  Since you 
have floating-point exceptions, I'd expect lack this to result in 
c11-atomic-exec-5.c failing.

-- 
Joseph S. Myers
jos...@codesourcery.com


[PATCH 1/6] RISC-V Port: gcc/config/riscv/riscv.c

2017-01-11 Thread Palmer Dabbelt
This is split from the rest of the gcc submission so I can fit this
patch on the mailing list's 200KiB limit.
---
 gcc/config/riscv/riscv.c | 4157 ++
 1 file changed, 4157 insertions(+)
 create mode 100644 gcc/config/riscv/riscv.c

diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
new file mode 100644
index 000..f4911d3
--- /dev/null
+++ b/gcc/config/riscv/riscv.c
@@ -0,0 +1,4157 @@
+/* Subroutines used for code generation for RISC-V.
+   Copyright (C) 2011-2017 Free Software Foundation, Inc.
+   Contributed by Andrew Waterman (and...@sifive.com).
+   Based on MIPS target for GNU compiler.
+
+This file is part of GCC.
+
+GCC 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.
+
+GCC 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 GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "insn-attr.h"
+#include "recog.h"
+#include "output.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "vec.h"
+#include "double-int.h"
+#include "input.h"
+#include "alias.h"
+#include "symtab.h"
+#include "wide-int.h"
+#include "inchash.h"
+#include "tree.h"
+#include "fold-const.h"
+#include "varasm.h"
+#include "stringpool.h"
+#include "stor-layout.h"
+#include "calls.h"
+#include "function.h"
+#include "hashtab.h"
+#include "flags.h"
+#include "statistics.h"
+#include "real.h"
+#include "fixed-value.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "memmodel.h"
+#include "emit-rtl.h"
+#include "stmt.h"
+#include "expr.h"
+#include "insn-codes.h"
+#include "optabs.h"
+#include "libfuncs.h"
+#include "reload.h"
+#include "tm_p.h"
+#include "ggc.h"
+#include "gstab.h"
+#include "hash-table.h"
+#include "debug.h"
+#include "target.h"
+#include "target-def.h"
+#include "common/common-target.h"
+#include "langhooks.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "cfgrtl.h"
+#include "cfganal.h"
+#include "lcm.h"
+#include "cfgbuild.h"
+#include "cfgcleanup.h"
+#include "predict.h"
+#include "basic-block.h"
+#include "bitmap.h"
+#include "regset.h"
+#include "df.h"
+#include "sched-int.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-fold.h"
+#include "tree-eh.h"
+#include "gimple-expr.h"
+#include "is-a.h"
+#include "gimple.h"
+#include "gimplify.h"
+#include "diagnostic.h"
+#include "target-globals.h"
+#include "opts.h"
+#include "tree-pass.h"
+#include "context.h"
+#include "hash-map.h"
+#include "plugin-api.h"
+#include "ipa-ref.h"
+#include "cgraph.h"
+#include "builtins.h"
+#include "rtl-iter.h"
+#include 
+
+/* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF.  */
+#define UNSPEC_ADDRESS_P(X)\
+  (GET_CODE (X) == UNSPEC  \
+   && XINT (X, 1) >= UNSPEC_ADDRESS_FIRST  \
+   && XINT (X, 1) < UNSPEC_ADDRESS_FIRST + NUM_SYMBOL_TYPES)
+
+/* Extract the symbol or label from UNSPEC wrapper X.  */
+#define UNSPEC_ADDRESS(X) \
+  XVECEXP (X, 0, 0)
+
+/* Extract the symbol type from UNSPEC wrapper X.  */
+#define UNSPEC_ADDRESS_TYPE(X) \
+  ((enum riscv_symbol_type) (XINT (X, 1) - UNSPEC_ADDRESS_FIRST))
+
+/* True if bit BIT is set in VALUE.  */
+#define BITSET_P(VALUE, BIT) (((VALUE) & (1ULL << (BIT))) != 0)
+
+/* Classifies an address.
+
+   ADDRESS_REG
+   A natural register + offset address.  The register satisfies
+   riscv_valid_base_register_p and the offset is a const_arith_operand.
+
+   ADDRESS_LO_SUM
+   A LO_SUM rtx.  The first operand is a valid base register and
+   the second operand is a symbolic address.
+
+   ADDRESS_CONST_INT
+   A signed 16-bit constant address.
+
+   ADDRESS_SYMBOLIC:
+   A constant symbolic address.  */
+enum riscv_address_type {
+  ADDRESS_REG,
+  ADDRESS_LO_SUM,
+  ADDRESS_CONST_INT,
+  ADDRESS_SYMBOLIC
+};
+
+/* Information about a function's frame layout.  */
+struct GTY(())  riscv_frame_info {
+  /* The size of the frame in bytes.  */
+  HOST_WIDE_INT total_size;
+
+  /* Bit X is set if the function saves or restores GPR X.  */
+  unsigned int mask;
+
+  /* Likewise FPR X.  */
+  unsigned int fmask;
+
+  /* How much the GPR save/restore routines adjust sp (or 0 if unused).  */
+  unsigned save_libcall_adjustment;
+
+  /* Offsets of fixed-point and floating-point save areas from frame bottom