From 42e6ab74b67a18019e35e2f84f62a3b4747160c9 Mon Sep 17 00:00:00 2001 From: Sandra Loosemore Date: Tue, 14 Jul 2015 18:34:23 -0400 Subject: [PATCH] nios2.h (SMALL_INT12): New macro. 2015-07-14 Sandra Loosemore Cesar Philippidis Chung-Lin Tang gcc/ * config/nios2/nios2.h (SMALL_INT12): New macro. * config/nios2/nios2.c (nios2_valid_addr_offset_p): New function. (nios2_valid_addr_expr_p): Use it. (nios2_symbol_ref_in_small_data_p): Disallow GP-relative addressing with implicit "io" instructions on R2. * config/nios2/constraints.md (w): New constraint. * config/nios2/predicates.md (ldstio_memory_operand): New. * config/nios2/nios2.md (ldio, ldio): Update memory operand predicate and constraint. (ldio_signed, stio>): Likewise. * doc/md.texi (Machine Constraints): Document w constraint. gcc/testsuite/ * gcc.target/nios2/r2-io-range.c: New. * gcc.target/nios2/r2-stio-1.c: New. * gcc.target/nios2/r2-stio-2.c: New. * gcc.target/nios2/nios2-ldxio.c: New. * gcc.target/nios2/nios2-stxio.c: Change to assemble test instead of just compile. Add more tests. Co-Authored-By: Cesar Philippidis Co-Authored-By: Chung-Lin Tang From-SVN: r225792 --- gcc/ChangeLog | 16 +++++++++ gcc/config/nios2/constraints.md | 8 +++++ gcc/config/nios2/nios2.c | 24 ++++++++++++- gcc/config/nios2/nios2.h | 1 + gcc/config/nios2/nios2.md | 8 ++--- gcc/config/nios2/predicates.md | 17 +++++++++ gcc/doc/md.texi | 4 +++ gcc/testsuite/ChangeLog | 11 ++++++ gcc/testsuite/gcc.target/nios2/nios2-ldxio.c | 52 ++++++++++++++++++++++++++++ gcc/testsuite/gcc.target/nios2/nios2-stxio.c | 10 +++++- gcc/testsuite/gcc.target/nios2/r2-io-range.c | 18 ++++++++++ gcc/testsuite/gcc.target/nios2/r2-stio-1.c | 19 ++++++++++ gcc/testsuite/gcc.target/nios2/r2-stio-2.c | 19 ++++++++++ 13 files changed, 201 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.target/nios2/nios2-ldxio.c create mode 100644 gcc/testsuite/gcc.target/nios2/r2-io-range.c create mode 100644 gcc/testsuite/gcc.target/nios2/r2-stio-1.c create mode 100644 gcc/testsuite/gcc.target/nios2/r2-stio-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b6026ba..80b38cd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -2,6 +2,22 @@ Cesar Philippidis Chung-Lin Tang + * config/nios2/nios2.h (SMALL_INT12): New macro. + * config/nios2/nios2.c (nios2_valid_addr_offset_p): New function. + (nios2_valid_addr_expr_p): Use it. + (nios2_symbol_ref_in_small_data_p): Disallow GP-relative addressing + with implicit "io" instructions on R2. + * config/nios2/constraints.md (w): New constraint. + * config/nios2/predicates.md (ldstio_memory_operand): New. + * config/nios2/nios2.md (ldio, ldio): Update memory + operand predicate and constraint. + (ldio_signed, stio>): Likewise. + * doc/md.texi (Machine Constraints): Document w constraint. + +2015-07-14 Sandra Loosemore + Cesar Philippidis + Chung-Lin Tang + * config/nios2/nios2.opt (march, mbmx, mcdx): New options. * config/nios2/nios2-opts.h (enum nios2_arch_type): New enum for Nios II architecture level. diff --git a/gcc/config/nios2/constraints.md b/gcc/config/nios2/constraints.md index b67e87d..7c7afdf 100644 --- a/gcc/config/nios2/constraints.md +++ b/gcc/config/nios2/constraints.md @@ -28,6 +28,10 @@ ;; N: 0 to 255 (for custom instruction numbers) ;; O: 0 to 31 (for control register numbers) ;; +;; We use the following constraint letters for memory constraints +;; +;; w: memory operands for load/store IO and cache instructions +;; ;; We use the following built-in register classes: ;; ;; r: general purpose register (r0..r31) @@ -89,3 +93,7 @@ (define_constraint "T" "A constant unspec offset representing a relocation." (match_test "nios2_unspec_reloc_p (op)")) + +(define_memory_constraint "w" + "A memory operand suitable for load/store IO and cache instructions." + (match_operand 0 "ldstio_memory_operand")) diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c index 7c97a02..93e0a86 100644 --- a/gcc/config/nios2/nios2.c +++ b/gcc/config/nios2/nios2.c @@ -1627,6 +1627,21 @@ nios2_regno_ok_for_base_p (int regno, bool strict_p) || regno == ARG_POINTER_REGNUM); } +/* Return true if OFFSET is permitted in a load/store address expression. + Normally any 16-bit value is permitted, but on R2 if we may be emitting + the IO forms of these instructions we must restrict the offset to fit + in a 12-bit field instead. */ + +static bool +nios2_valid_addr_offset_p (rtx offset) +{ + return (CONST_INT_P (offset) + && ((TARGET_ARCH_R2 && (TARGET_BYPASS_CACHE + || TARGET_BYPASS_CACHE_VOLATILE)) + ? SMALL_INT12 (INTVAL (offset)) + : SMALL_INT (INTVAL (offset)))); +} + /* Return true if the address expression formed by BASE + OFFSET is valid. */ static bool @@ -1637,7 +1652,7 @@ nios2_valid_addr_expr_p (rtx base, rtx offset, bool strict_p) return (REG_P (base) && nios2_regno_ok_for_base_p (REGNO (base), strict_p) && (offset == NULL_RTX - || const_arith_operand (offset, Pmode) + || nios2_valid_addr_offset_p (offset) || nios2_unspec_reloc_p (offset))); } @@ -1739,6 +1754,13 @@ nios2_symbol_ref_in_small_data_p (rtx sym) if (SYMBOL_REF_TLS_MODEL (sym) != 0) return false; + /* On Nios II R2, there is no GP-relative relocation that can be + used with "io" instructions. So, if we are implicitly generating + those instructions, we cannot emit GP-relative accesses. */ + if (TARGET_ARCH_R2 + && (TARGET_BYPASS_CACHE || TARGET_BYPASS_CACHE_VOLATILE)) + return false; + /* If the user has explicitly placed the symbol in a small data section via an attribute, generate gp-relative addressing even if the symbol is external, weak, or larger than we'd automatically put in the diff --git a/gcc/config/nios2/nios2.h b/gcc/config/nios2/nios2.h index c3c958a..58afaec 100644 --- a/gcc/config/nios2/nios2.h +++ b/gcc/config/nios2/nios2.h @@ -216,6 +216,7 @@ enum reg_class /* Tests for various kinds of constants used in the Nios II port. */ #define SMALL_INT(X) ((unsigned HOST_WIDE_INT)(X) + 0x8000 < 0x10000) +#define SMALL_INT12(X) ((unsigned HOST_WIDE_INT)(X) + 0x800 < 0x1000) #define SMALL_INT_UNSIGNED(X) ((X) >= 0 && (X) < 0x10000) #define UPPER16_INT(X) (((X) & 0xffff) == 0) #define SHIFT_INT(X) ((X) >= 0 && (X) <= 31) diff --git a/gcc/config/nios2/nios2.md b/gcc/config/nios2/nios2.md index 7097780..8cf2347 100644 --- a/gcc/config/nios2/nios2.md +++ b/gcc/config/nios2/nios2.md @@ -221,14 +221,14 @@ (define_insn "ldio" [(set (match_operand:BHW 0 "register_operand" "=r") (unspec_volatile:BHW - [(match_operand:BHW 1 "memory_operand" "m")] UNSPECV_LDXIO))] + [(match_operand:BHW 1 "ldstio_memory_operand" "w")] UNSPECV_LDXIO))] "" "ldio\\t%0, %1" [(set_attr "type" "ld")]) (define_expand "ldio" [(set (match_operand:BH 0 "register_operand" "=r") - (match_operand:BH 1 "memory_operand" "m"))] + (match_operand:BH 1 "ldstio_memory_operand" "w"))] "" { rtx tmp = gen_reg_rtx (SImode); @@ -241,13 +241,13 @@ [(set (match_operand:SI 0 "register_operand" "=r") (sign_extend:SI (unspec_volatile:BH - [(match_operand:BH 1 "memory_operand" "m")] UNSPECV_LDXIO)))] + [(match_operand:BH 1 "ldstio_memory_operand" "w")] UNSPECV_LDXIO)))] "" "ldio\\t%0, %1" [(set_attr "type" "ld")]) (define_insn "stio" - [(set (match_operand:BHW 0 "memory_operand" "=m") + [(set (match_operand:BHW 0 "ldstio_memory_operand" "=w") (unspec_volatile:BHW [(match_operand:BHW 1 "reg_or_0_operand" "rM")] UNSPECV_STXIO))] "" diff --git a/gcc/config/nios2/predicates.md b/gcc/config/nios2/predicates.md index 37cecf7..fa57803 100644 --- a/gcc/config/nios2/predicates.md +++ b/gcc/config/nios2/predicates.md @@ -83,3 +83,20 @@ &XEXP (op, 0), &XEXP (op, 1), false)); }) + +(define_predicate "ldstio_memory_operand" + (match_code "mem") +{ + if (TARGET_ARCH_R2) + { + rtx addr = XEXP (op, 0); + if (REG_P (addr)) + return true; + else if (GET_CODE (addr) == PLUS) + return (REG_P (XEXP (addr, 0)) + && CONST_INT_P (XEXP (addr, 1)) + && SMALL_INT12 (INTVAL (XEXP (addr, 1)))); + return false; + } + return memory_operand (op, mode); +}) diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index e991286..84c39a8 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -2996,6 +2996,10 @@ Matches immediates which are addresses in the small data section and therefore can be added to @code{gp} as a 16-bit immediate to re-create their 32-bit value. +@item w +A memory operand suitable for load/store IO and cache +instructions. + @ifset INTERNALS @item T A @code{const} wrapped @code{UNSPEC} expression, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 801e462..6dd4feb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2015-07-14 Sandra Loosemore + Cesar Philippidis + Chung-Lin Tang + + * gcc.target/nios2/r2-io-range.c: New. + * gcc.target/nios2/r2-stio-1.c: New. + * gcc.target/nios2/r2-stio-2.c: New. + * gcc.target/nios2/nios2-ldxio.c: New. + * gcc.target/nios2/nios2-stxio.c: Change to assemble test instead + of just compile. Add more tests. + 2015-07-14 Steven G. Kargl gfortran.dg/pr66864.f90: New test. diff --git a/gcc/testsuite/gcc.target/nios2/nios2-ldxio.c b/gcc/testsuite/gcc.target/nios2/nios2-ldxio.c new file mode 100644 index 0000000..ac661a0 --- /dev/null +++ b/gcc/testsuite/gcc.target/nios2/nios2-ldxio.c @@ -0,0 +1,52 @@ +/* { dg-do assemble } */ +/* { dg-options "-O" } */ + +void test_ldbio (unsigned char* p1, unsigned char* p2) +{ + __builtin_ldbio (p1); + __builtin_ldbio (p2); + __builtin_ldbio (p2 + 1); + __builtin_ldbio (p2 + 2); + __builtin_ldbio (p2 + 2047); + __builtin_ldbio (p2 + 2048); +} + +void test_ldbuio (unsigned char* p1, unsigned char* p2) +{ + __builtin_ldbuio (p1); + __builtin_ldbuio (p2); + __builtin_ldbuio (p2 + 1); + __builtin_ldbuio (p2 + 2); + __builtin_ldbuio (p2 + 2047); + __builtin_ldbuio (p2 + 2048); +} + +void test_ldhio (unsigned short* p1, unsigned short* p2) +{ + __builtin_ldhio (p1); + __builtin_ldhio (p2); + __builtin_ldhio (p2 + 1); + __builtin_ldhio (p2 + 2); + __builtin_ldhio (p2 + 1023); + __builtin_ldhio (p2 + 1024); +} + +void test_ldhuio (unsigned short* p1, unsigned short* p2) +{ + __builtin_ldhuio (p1); + __builtin_ldhuio (p2); + __builtin_ldhuio (p2 + 1); + __builtin_ldhuio (p2 + 2); + __builtin_ldhuio (p2 + 1023); + __builtin_ldhuio (p2 + 1024); +} + +void test_ldwio (unsigned int* p1, unsigned int* p2) +{ + __builtin_ldwio (p1); + __builtin_ldwio (p2); + __builtin_ldwio (p2 + 1); + __builtin_ldwio (p2 + 2); + __builtin_ldwio (p2 + 511); + __builtin_ldwio (p2 + 512); +} diff --git a/gcc/testsuite/gcc.target/nios2/nios2-stxio.c b/gcc/testsuite/gcc.target/nios2/nios2-stxio.c index af079d6..0e675be 100644 --- a/gcc/testsuite/gcc.target/nios2/nios2-stxio.c +++ b/gcc/testsuite/gcc.target/nios2/nios2-stxio.c @@ -1,4 +1,5 @@ -/* { dg-do compile } */ +/* { dg-do assemble } */ +/* { dg-options "-O" } */ void test_stbio (unsigned char* p1, unsigned char* p2) { @@ -6,6 +7,8 @@ void test_stbio (unsigned char* p1, unsigned char* p2) __builtin_stbio (p2, 0); __builtin_stbio (p2 + 1, 0x80); __builtin_stbio (p2 + 2, 0x7f); + __builtin_stbio (p2 + 2047, 0x80); + __builtin_stbio (p2 + 2048, 0x7f); } void test_sthio (unsigned short* p1, unsigned short* p2) @@ -14,6 +17,8 @@ void test_sthio (unsigned short* p1, unsigned short* p2) __builtin_sthio (p2, 0); __builtin_sthio (p2 + 1, 0x8000); __builtin_sthio (p2 + 2, 0x7fff); + __builtin_sthio (p2 + 1023, 0x8000); + __builtin_sthio (p2 + 1024, 0x7fff); } void test_stwio (unsigned int* p1, unsigned int* p2) @@ -22,4 +27,7 @@ void test_stwio (unsigned int* p1, unsigned int* p2) __builtin_stwio (p2, 0); __builtin_stwio (p2 + 1, 0x80000000); __builtin_stwio (p2 + 2, 0x7fffffff); + __builtin_stwio (p2 + 511, 5); + __builtin_stwio (p2 + 512, 5); } + diff --git a/gcc/testsuite/gcc.target/nios2/r2-io-range.c b/gcc/testsuite/gcc.target/nios2/r2-io-range.c new file mode 100644 index 0000000..2064ff6 --- /dev/null +++ b/gcc/testsuite/gcc.target/nios2/r2-io-range.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=r2 -mbypass-cache" } */ + +/* Check that the compiler is aware of the reduced offset range for ldio/stio + instructions in the Nios II R2 encoding. */ + +unsigned int too_big (unsigned int *p) +{ + return *(p + 0x400); +} + +unsigned int small_enough (unsigned int *p) +{ + return *(p + 0x100); +} + +/* { dg-final { scan-assembler-not "\tldwio\t.*, 4096\\(r.*\\)" } } */ +/* { dg-final { scan-assembler "\tldwio\t.*, 1024\\(r.*\\)" } } */ diff --git a/gcc/testsuite/gcc.target/nios2/r2-stio-1.c b/gcc/testsuite/gcc.target/nios2/r2-stio-1.c new file mode 100644 index 0000000..5aadd20 --- /dev/null +++ b/gcc/testsuite/gcc.target/nios2/r2-stio-1.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O -mgpopt -march=r2" } */ + +/* The ldio/stio builtins must not use GP-relative addresses for + small data objects in R2. This is because the address offset field + has been reduced to 12 bits in R2, and %gprel is a 16-bit relocation. */ + +extern volatile unsigned int frob; + +volatile unsigned int frob = 0; + +void foo (unsigned int val) +{ + __builtin_stwio (&frob, val); +} + +/* { dg-final { scan-assembler "stwio\\t" } } */ +/* { dg-final { scan-assembler-not "stwio\\t.*%gprel(frob)" } } */ + diff --git a/gcc/testsuite/gcc.target/nios2/r2-stio-2.c b/gcc/testsuite/gcc.target/nios2/r2-stio-2.c new file mode 100644 index 0000000..0a6de90 --- /dev/null +++ b/gcc/testsuite/gcc.target/nios2/r2-stio-2.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O -mgpopt -march=r2 -mbypass-cache" } */ + +/* Implicit ldio/stio operations must not use GP-relative addresses for + small data objects in R2. This is because the address offset field + has been reduced to 12 bits in R2, and %gprel is a 16-bit relocation. */ + +extern volatile unsigned int frob; + +volatile unsigned int frob = 0; + +void foo (unsigned int val) +{ + frob = val; +} + +/* { dg-final { scan-assembler "stwio\\t" } } */ +/* { dg-final { scan-assembler-not "stwio\\t.*%gprel(frob)" } } */ + -- 2.7.4