* [COMMITTED 0/9] Small cleanups and improvements for PRU backend
@ 2024-05-07 7:22 Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 1/9] pru: Implement TARGET_ADDRESS_COST Dimitar Dimitrov
` (8 more replies)
0 siblings, 9 replies; 10+ messages in thread
From: Dimitar Dimitrov @ 2024-05-07 7:22 UTC (permalink / raw)
To: gcc-patches; +Cc: Dimitar Dimitrov
This patch set includes small cleanups and code generation improvements
I implemented during stages 3 and 4.
All patches have been regression-tested individually for pru-unknown-elf
while being developed. And the entire set was tested again on GCC 15
mainline.
Dimitar Dimitrov (9):
pru: Implement TARGET_ADDRESS_COST
pru: Implement zero fill for 64-bit registers
pru: Optimize the extzv and insv patterns
pru: Add pattern variants for zero extending destination
pru: Skip register save if function will not return
pru: Drop usage of ATTRIBUTE_UNUSED
pru: Use HOST_WIDE_INT_1U macro
pru: Refactor to use passes definition file
pru: New validation pass for minrt
gcc/config/pru/alu-zext.md | 38 +++++-
gcc/config/pru/pru-passes.cc | 96 ++++++++++---
gcc/config/pru/pru-passes.def | 29 ++++
gcc/config/pru/pru-pragma.cc | 2 +-
gcc/config/pru/pru-protos.h | 3 +-
gcc/config/pru/pru.cc | 58 +++++---
gcc/config/pru/pru.md | 128 +++++++++++++++---
gcc/config/pru/t-pru | 2 +
gcc/testsuite/g++.target/pru/minrt-1.cc | 10 ++
gcc/testsuite/g++.target/pru/minrt-2.cc | 10 ++
gcc/testsuite/g++.target/pru/minrt-3.cc | 9 ++
gcc/testsuite/g++.target/pru/pru.exp | 34 +++++
gcc/testsuite/gcc.target/pru/ashiftrt.c | 2 +-
gcc/testsuite/gcc.target/pru/extzv-1.c | 14 ++
gcc/testsuite/gcc.target/pru/extzv-2.c | 15 ++
gcc/testsuite/gcc.target/pru/extzv-3.c | 13 ++
gcc/testsuite/gcc.target/pru/insv-1.c | 14 ++
gcc/testsuite/gcc.target/pru/insv-2.c | 14 ++
gcc/testsuite/gcc.target/pru/insv-3.c | 14 ++
gcc/testsuite/gcc.target/pru/insv-4.c | 14 ++
gcc/testsuite/gcc.target/pru/minrt-1.c | 10 ++
gcc/testsuite/gcc.target/pru/minrt-2.c | 10 ++
gcc/testsuite/gcc.target/pru/minrt-3.c | 9 ++
gcc/testsuite/gcc.target/pru/mov-0.c | 19 +++
.../gcc.target/pru/noreturn-prologue-1.c | 10 ++
.../gcc.target/pru/noreturn-prologue-2.c | 11 ++
.../gcc.target/pru/zero_extend-op0.c | 28 ++++
27 files changed, 549 insertions(+), 67 deletions(-)
create mode 100644 gcc/config/pru/pru-passes.def
create mode 100644 gcc/testsuite/g++.target/pru/minrt-1.cc
create mode 100644 gcc/testsuite/g++.target/pru/minrt-2.cc
create mode 100644 gcc/testsuite/g++.target/pru/minrt-3.cc
create mode 100644 gcc/testsuite/g++.target/pru/pru.exp
create mode 100644 gcc/testsuite/gcc.target/pru/extzv-1.c
create mode 100644 gcc/testsuite/gcc.target/pru/extzv-2.c
create mode 100644 gcc/testsuite/gcc.target/pru/extzv-3.c
create mode 100644 gcc/testsuite/gcc.target/pru/insv-1.c
create mode 100644 gcc/testsuite/gcc.target/pru/insv-2.c
create mode 100644 gcc/testsuite/gcc.target/pru/insv-3.c
create mode 100644 gcc/testsuite/gcc.target/pru/insv-4.c
create mode 100644 gcc/testsuite/gcc.target/pru/minrt-1.c
create mode 100644 gcc/testsuite/gcc.target/pru/minrt-2.c
create mode 100644 gcc/testsuite/gcc.target/pru/minrt-3.c
create mode 100644 gcc/testsuite/gcc.target/pru/mov-0.c
create mode 100644 gcc/testsuite/gcc.target/pru/noreturn-prologue-1.c
create mode 100644 gcc/testsuite/gcc.target/pru/noreturn-prologue-2.c
create mode 100644 gcc/testsuite/gcc.target/pru/zero_extend-op0.c
--
2.45.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [COMMITTED 1/9] pru: Implement TARGET_ADDRESS_COST
2024-05-07 7:22 [COMMITTED 0/9] Small cleanups and improvements for PRU backend Dimitar Dimitrov
@ 2024-05-07 7:22 ` Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 2/9] pru: Implement zero fill for 64-bit registers Dimitar Dimitrov
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Dimitar Dimitrov @ 2024-05-07 7:22 UTC (permalink / raw)
To: gcc-patches; +Cc: Dimitar Dimitrov
Stop relying on the default fallback to TARGET_RTX_COST for PRU's
addressing costs. Implement TARGET_ADDRESS_COST, in order to allow RTX
cost refactoring in the future without affecting the addressing costs.
No code generation changes are expected by this patch. No changes were
detected when running embench-iot and building a few real-world firmware
examples.
gcc/ChangeLog:
* config/pru/pru.cc (pru_address_cost): Implement address cost
calculation.
(TARGET_ADDRESS_COST): Define for PRU.
Signed-off-by: Dimitar Dimitrov <dimitar@dinux.eu>
---
gcc/config/pru/pru.cc | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/gcc/config/pru/pru.cc b/gcc/config/pru/pru.cc
index 270c536d4c7..a76451f4223 100644
--- a/gcc/config/pru/pru.cc
+++ b/gcc/config/pru/pru.cc
@@ -784,6 +784,28 @@ pru_rtx_costs (rtx x, machine_mode mode,
}
}
+/* Calculate the cost of an addressing mode that contains ADDR.
+ ADDR must be a valid address. */
+
+static int
+pru_address_cost (rtx addr, machine_mode, addr_space_t as, bool)
+{
+ if (as != ADDR_SPACE_GENERIC)
+ /* All currently implemented special address spaces for PRU
+ are much more efficient than generic memory I/O. */
+ return 0;
+ else if (ctable_addr_operand (addr, VOIDmode)
+ || (GET_CODE (addr) == PLUS
+ && ctable_base_operand (XEXP (addr, 1), VOIDmode)))
+ /* Using CTABLE instructions reduces register pressure,
+ so give it precedence. */
+ return 1;
+ else
+ /* Same two instructions (LBBO/SBBO) are used for any valid
+ addressing mode. */
+ return 2;
+}
+
/* Insn costs on PRU are straightforward because:
- Insns emit 0, 1 or more instructions.
- All instructions are 32-bit length.
@@ -3208,6 +3230,9 @@ pru_unwind_word_mode (void)
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS pru_rtx_costs
+#undef TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST pru_address_cost
+
#undef TARGET_INSN_COST
#define TARGET_INSN_COST pru_insn_cost
--
2.45.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [COMMITTED 2/9] pru: Implement zero fill for 64-bit registers
2024-05-07 7:22 [COMMITTED 0/9] Small cleanups and improvements for PRU backend Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 1/9] pru: Implement TARGET_ADDRESS_COST Dimitar Dimitrov
@ 2024-05-07 7:22 ` Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 3/9] pru: Optimize the extzv and insv patterns Dimitar Dimitrov
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Dimitar Dimitrov @ 2024-05-07 7:22 UTC (permalink / raw)
To: gcc-patches; +Cc: Dimitar Dimitrov
Loading a constant zero in a 64-bit register now takes one instead of
two instructions.
gcc/ChangeLog:
* config/pru/pru.md: New pattern alternative for zero-filling
64-bit registers.
gcc/testsuite/ChangeLog:
* gcc.target/pru/mov-0.c: New test.
Signed-off-by: Dimitar Dimitrov <dimitar@dinux.eu>
---
gcc/config/pru/pru.md | 18 ++++++++++--------
gcc/testsuite/gcc.target/pru/mov-0.c | 19 +++++++++++++++++++
2 files changed, 29 insertions(+), 8 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/pru/mov-0.c
diff --git a/gcc/config/pru/pru.md b/gcc/config/pru/pru.md
index 8393d8f9607..0123952aa9e 100644
--- a/gcc/config/pru/pru.md
+++ b/gcc/config/pru/pru.md
@@ -248,8 +248,8 @@ (define_insn "prumov<mode>"
; Forcing DI reg alignment (akin to microblaze's HARD_REGNO_MODE_OK)
; does not seem efficient, and will violate TI ABI.
(define_insn "mov<mode>"
- [(set (match_operand:MOV64 0 "nonimmediate_operand" "=m,r,r,r,r,r,r")
- (match_operand:MOV64 1 "general_operand" "r,m,Um,r,T,J,nF"))]
+ [(set (match_operand:MOV64 0 "nonimmediate_operand" "=m,r,r,r,r,r,r,r")
+ (match_operand:MOV64 1 "general_operand" "r,m,Z,Um,r,T,J,nF"))]
""
{
switch (which_alternative)
@@ -259,8 +259,10 @@ (define_insn "mov<mode>"
case 1:
return "lb%B1o\\t%b0, %1, %S1";
case 2:
- return "fill\\t%F0, 8";
+ return "zero\\t%F0, 8";
case 3:
+ return "fill\\t%F0, 8";
+ case 4:
/* careful with overlapping source and destination regs. */
gcc_assert (GP_REG_P (REGNO (operands[0])));
gcc_assert (GP_REG_P (REGNO (operands[1])));
@@ -268,18 +270,18 @@ (define_insn "mov<mode>"
return "mov\\t%N0, %N1\;mov\\t%F0, %F1";
else
return "mov\\t%F0, %F1\;mov\\t%N0, %N1";
- case 4:
- return "ldi\\t%F0, %%pmem(%1)\;ldi\\t%N0, 0";
case 5:
- return "ldi\\t%F0, %1\;ldi\\t%N0, 0";
+ return "ldi\\t%F0, %%pmem(%1)\;ldi\\t%N0, 0";
case 6:
+ return "ldi\\t%F0, %1\;ldi\\t%N0, 0";
+ case 7:
return "ldi32\\t%F0, %w1\;ldi32\\t%N0, %W1";
default:
gcc_unreachable ();
}
}
- [(set_attr "type" "st,ld,alu,alu,alu,alu,alu")
- (set_attr "length" "4,4,4,8,8,8,16")])
+ [(set_attr "type" "st,ld,alu,alu,alu,alu,alu,alu")
+ (set_attr "length" "4,4,4,4,8,8,8,16")])
;
; load_multiple pattern(s).
diff --git a/gcc/testsuite/gcc.target/pru/mov-0.c b/gcc/testsuite/gcc.target/pru/mov-0.c
new file mode 100644
index 00000000000..0190be36fa4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/mov-0.c
@@ -0,0 +1,19 @@
+/* Loading a register with constant 0 integer value. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+int
+test_set_0_si (void)
+{
+ /* Since zero-extension is free, "zero" fill is not implemented for SI. */
+ /* { dg-final { scan-assembler "ldi\\tr14(.b0)?, 0" } } */
+ return 0;
+}
+
+long long
+test_set_0_di (void)
+{
+ /* { dg-final { scan-assembler "zero\\tr14(.b0)?, 8" } } */
+ return 0;
+}
--
2.45.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [COMMITTED 3/9] pru: Optimize the extzv and insv patterns
2024-05-07 7:22 [COMMITTED 0/9] Small cleanups and improvements for PRU backend Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 1/9] pru: Implement TARGET_ADDRESS_COST Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 2/9] pru: Implement zero fill for 64-bit registers Dimitar Dimitrov
@ 2024-05-07 7:22 ` Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 4/9] pru: Add pattern variants for zero extending destination Dimitar Dimitrov
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Dimitar Dimitrov @ 2024-05-07 7:22 UTC (permalink / raw)
To: gcc-patches; +Cc: Dimitar Dimitrov
Optimize the generated code for the bit-field extract and insert
patterns:
- Use bit-set and bit-clear instructions for 1-bit fields.
- Expand to SImode operations instead of relying on the default
expansion to word (QI) mode.
gcc/ChangeLog:
* config/pru/pru.md (extzv<mode>): Make it an expand pattern,
handle efficiently zero-positioned bit-fields.
(insv<mode>): New expand pattern.
gcc/testsuite/ChangeLog:
* gcc.target/pru/ashiftrt.c: Minor update due to new (but
equivalent) generated code sequence.
* gcc.target/pru/extzv-1.c: New test.
* gcc.target/pru/extzv-2.c: New test.
* gcc.target/pru/extzv-3.c: New test.
* gcc.target/pru/insv-1.c: New test.
* gcc.target/pru/insv-2.c: New test.
* gcc.target/pru/insv-3.c: New test.
* gcc.target/pru/insv-4.c: New test.
Signed-off-by: Dimitar Dimitrov <dimitar@dinux.eu>
---
gcc/config/pru/pru.md | 104 ++++++++++++++++++++++--
gcc/testsuite/gcc.target/pru/ashiftrt.c | 2 +-
gcc/testsuite/gcc.target/pru/extzv-1.c | 14 ++++
gcc/testsuite/gcc.target/pru/extzv-2.c | 15 ++++
gcc/testsuite/gcc.target/pru/extzv-3.c | 13 +++
gcc/testsuite/gcc.target/pru/insv-1.c | 14 ++++
gcc/testsuite/gcc.target/pru/insv-2.c | 14 ++++
gcc/testsuite/gcc.target/pru/insv-3.c | 14 ++++
gcc/testsuite/gcc.target/pru/insv-4.c | 14 ++++
9 files changed, 194 insertions(+), 10 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/pru/extzv-1.c
create mode 100644 gcc/testsuite/gcc.target/pru/extzv-2.c
create mode 100644 gcc/testsuite/gcc.target/pru/extzv-3.c
create mode 100644 gcc/testsuite/gcc.target/pru/insv-1.c
create mode 100644 gcc/testsuite/gcc.target/pru/insv-2.c
create mode 100644 gcc/testsuite/gcc.target/pru/insv-3.c
create mode 100644 gcc/testsuite/gcc.target/pru/insv-4.c
diff --git a/gcc/config/pru/pru.md b/gcc/config/pru/pru.md
index 0123952aa9e..2ceea2e7b1c 100644
--- a/gcc/config/pru/pru.md
+++ b/gcc/config/pru/pru.md
@@ -486,22 +486,108 @@ (define_expand "extend<EQS0:mode><EQDHIDI:mode>2"
})
\f
;; Bit extraction
-;; We define it solely to allow combine to choose SImode
+;; One reason to define it is to allow combine to choose SImode
;; for word mode when trying to match our cbranch_qbbx_* insn.
;;
;; Check how combine.cc:make_extraction() uses
;; get_best_reg_extraction_insn() to select the op size.
-(define_insn "extzv<mode>"
- [(set (match_operand:QISI 0 "register_operand" "=r")
+(define_expand "extzv<mode>"
+ [(set (match_operand:QISI 0 "register_operand")
(zero_extract:QISI
- (match_operand:QISI 1 "register_operand" "r")
- (match_operand:QISI 2 "const_int_operand" "i")
- (match_operand:QISI 3 "const_int_operand" "i")))]
+ (match_operand:QISI 1 "register_operand")
+ (match_operand:QISI 2 "const_int_operand")
+ (match_operand:QISI 3 "const_int_operand")))]
""
- "lsl\\t%0, %1, (%S0 * 8 - %2 - %3)\;lsr\\t%0, %0, (%S0 * 8 - %2)"
- [(set_attr "type" "complex")
- (set_attr "length" "8")])
+{
+ const int nbits = INTVAL (operands[2]);
+ const int bitpos = INTVAL (operands[3]);
+ const int trailing_bits = GET_MODE_BITSIZE (<MODE>mode) - nbits - bitpos;
+
+ if (bitpos == 0 && nbits <= 7)
+ {
+ emit_insn (gen_and<mode>3 (operands[0],
+ operands[1],
+ gen_int_mode ((HOST_WIDE_INT_1U << nbits) - 1,
+ <MODE>mode)));
+ DONE;
+ }
+
+ rtx src = operands[1];
+ if (trailing_bits != 0)
+ {
+ emit_insn (gen_ashl<mode>3 (operands[0],
+ operands[1],
+ GEN_INT (trailing_bits)));
+ src = operands[0];
+ }
+ emit_insn (gen_lshr<mode>3 (operands[0],
+ src,
+ GEN_INT (trailing_bits + bitpos)));
+ DONE;
+})
+
+;; Bit-field insert.
+(define_expand "insv<mode>"
+ [(set (zero_extract:QISI
+ (match_operand:QISI 0 "register_operand")
+ (match_operand:QISI 1 "const_int_operand")
+ (match_operand:QISI 2 "const_int_operand"))
+ (match_operand:QISI 3 "reg_or_ubyte_operand"))]
+ ""
+{
+ const int nbits = INTVAL (operands[1]);
+ const int bitpos = INTVAL (operands[2]);
+ if (nbits == 1)
+ {
+ rtx j;
+ rtx src = gen_reg_rtx (<MODE>mode);
+ rtx dst = operands[0];
+
+ emit_move_insn (src, operands[3]);
+
+ emit_insn (gen_and<mode>3 (dst,
+ dst,
+ gen_int_mode (~(HOST_WIDE_INT_1U << bitpos),
+ <MODE>mode)));
+
+ rtx_code_label *skip_set_label = gen_label_rtx ();
+ j = emit_jump_insn (gen_cbranch_qbbx_eq<mode><mode><mode>4 (
+ src,
+ GEN_INT (0),
+ skip_set_label));
+ JUMP_LABEL (j) = skip_set_label;
+ LABEL_NUSES (skip_set_label)++;
+
+ emit_insn (gen_ior<mode>3 (dst,
+ dst,
+ gen_int_mode (HOST_WIDE_INT_1U << bitpos,
+ <MODE>mode)));
+ emit_label (skip_set_label);
+
+ DONE;
+ }
+
+ /* Explicitly expand in order to avoid using word_mode for PRU, and instead
+ use SI and HI modes as applicable. */
+ rtx dst = operands[0];
+ rtx src = gen_reg_rtx (<MODE>mode);
+ emit_insn (gen_and<mode>3 (src,
+ force_reg (<MODE>mode, operands[3]),
+ gen_int_mode ((HOST_WIDE_INT_1U << nbits) - 1,
+ <MODE>mode)));
+ if (bitpos > 0)
+ emit_insn (gen_ashl<mode>3 (src, src, gen_int_mode (bitpos, <MODE>mode)));
+
+ HOST_WIDE_INT vmask = ~(((HOST_WIDE_INT_1U << nbits) - 1) << bitpos);
+ emit_insn (gen_and<mode>3 (dst,
+ dst,
+ gen_int_mode (vmask, <MODE>mode)));
+
+ emit_insn (gen_ior<mode>3 (dst, dst, src));
+
+ DONE;
+})
\f
;; Arithmetic Operations
diff --git a/gcc/testsuite/gcc.target/pru/ashiftrt.c b/gcc/testsuite/gcc.target/pru/ashiftrt.c
index ee8d55d60e6..fb8e4759a0e 100644
--- a/gcc/testsuite/gcc.target/pru/ashiftrt.c
+++ b/gcc/testsuite/gcc.target/pru/ashiftrt.c
@@ -8,6 +8,6 @@ extern void func2(unsigned char);
void test(unsigned char v)
{
- /* { dg-final { scan-assembler "lsl\tr14.b0, r14.b0, .\+\n\tlsr\tr14.b0, r14.b0" } } */
+ /* { dg-final { scan-assembler "lsr\tr14(.b0)?, r14.b0, .\+\n\tand\tr14.b0, r14.b0" } } */
func2((v & 2) ? 1 : 0);
}
diff --git a/gcc/testsuite/gcc.target/pru/extzv-1.c b/gcc/testsuite/gcc.target/pru/extzv-1.c
new file mode 100644
index 00000000000..573ded99830
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/extzv-1.c
@@ -0,0 +1,14 @@
+/* { dg-do assemble } */
+/* { dg-options "-Os" } */
+/* { dg-final { object-size text <= 12 } } */
+
+struct S {
+ unsigned int a : 5;
+ unsigned int b : 1;
+ unsigned int c : 1;
+};
+
+unsigned int test(struct S s)
+{
+ return s.a;
+}
diff --git a/gcc/testsuite/gcc.target/pru/extzv-2.c b/gcc/testsuite/gcc.target/pru/extzv-2.c
new file mode 100644
index 00000000000..e34ba138f16
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/extzv-2.c
@@ -0,0 +1,15 @@
+/* { dg-do assemble } */
+/* { dg-options "-Os" } */
+/* { dg-final { object-size text <= 12 } } */
+
+struct S {
+ unsigned int a : 5;
+ unsigned int b : 1;
+ unsigned int c : 24;
+ unsigned int d : 2;
+};
+
+unsigned int test(struct S s)
+{
+ return s.d;
+}
diff --git a/gcc/testsuite/gcc.target/pru/extzv-3.c b/gcc/testsuite/gcc.target/pru/extzv-3.c
new file mode 100644
index 00000000000..66f4f376885
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/extzv-3.c
@@ -0,0 +1,13 @@
+/* { dg-do assemble } */
+/* { dg-options "-Os" } */
+/* { dg-final { object-size text <= 16 } } */
+
+struct S {
+ unsigned int a : 9;
+ unsigned int b : 4;
+};
+
+unsigned int test(struct S s)
+{
+ return s.b;
+}
diff --git a/gcc/testsuite/gcc.target/pru/insv-1.c b/gcc/testsuite/gcc.target/pru/insv-1.c
new file mode 100644
index 00000000000..50e29a1b818
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/insv-1.c
@@ -0,0 +1,14 @@
+/* { dg-do assemble } */
+/* { dg-options "-Os" } */
+/* { dg-final { object-size text <= 16 } } */
+
+struct S {
+ unsigned int a : 5;
+ unsigned int b : 1;
+ unsigned int c : 1;
+};
+
+void test(struct S *s)
+{
+ s->b = 1;
+}
diff --git a/gcc/testsuite/gcc.target/pru/insv-2.c b/gcc/testsuite/gcc.target/pru/insv-2.c
new file mode 100644
index 00000000000..50272b713e7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/insv-2.c
@@ -0,0 +1,14 @@
+/* { dg-do assemble } */
+/* { dg-options "-Os" } */
+/* { dg-final { object-size text <= 16 } } */
+
+struct S {
+ unsigned int a : 5;
+ unsigned int b : 1;
+ unsigned int c : 1;
+};
+
+void test(struct S *s)
+{
+ s->b = 0;
+}
diff --git a/gcc/testsuite/gcc.target/pru/insv-3.c b/gcc/testsuite/gcc.target/pru/insv-3.c
new file mode 100644
index 00000000000..5ff0feb2ca1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/insv-3.c
@@ -0,0 +1,14 @@
+/* { dg-do assemble } */
+/* { dg-options "-Os" } */
+/* { dg-final { object-size text <= 24 } } */
+
+struct S {
+ unsigned int a : 5;
+ unsigned int b : 1;
+ unsigned int c : 1;
+};
+
+void test(struct S *s, unsigned int val)
+{
+ s->b = val;
+}
diff --git a/gcc/testsuite/gcc.target/pru/insv-4.c b/gcc/testsuite/gcc.target/pru/insv-4.c
new file mode 100644
index 00000000000..4eaa733c560
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/insv-4.c
@@ -0,0 +1,14 @@
+/* { dg-do assemble } */
+/* { dg-options "-Os" } */
+/* { dg-final { object-size text <= 28 } } */
+
+struct S {
+ unsigned int a : 3;
+ unsigned int b : 3;
+ unsigned int c : 3;
+};
+
+void test(struct S *s, unsigned int val)
+{
+ s->b = val;
+}
--
2.45.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [COMMITTED 4/9] pru: Add pattern variants for zero extending destination
2024-05-07 7:22 [COMMITTED 0/9] Small cleanups and improvements for PRU backend Dimitar Dimitrov
` (2 preceding siblings ...)
2024-05-07 7:22 ` [COMMITTED 3/9] pru: Optimize the extzv and insv patterns Dimitar Dimitrov
@ 2024-05-07 7:22 ` Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 5/9] pru: Skip register save if function will not return Dimitar Dimitrov
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Dimitar Dimitrov @ 2024-05-07 7:22 UTC (permalink / raw)
To: gcc-patches; +Cc: Dimitar Dimitrov
The higher bits in the result of some ALU operations are inherently
always zero when all input operands are smaller than 32-bits.
Add pattern variants to match when the resulting value is zero
extended, so that all operations can be effectively executed in a
single instruction. For PRU it simply means to use a wider register for
destination.
ALU operations which cannot be presented as zero-extending their
destination are addition, subtraction and logical shift left. The PRU
ALU performs all operations in 32-bit mode, so the carry-out and
shifted-out bits would violate the assumption that ALU operation was
performed in 16-bit or 8-bit mode, and result was zero-extended.
gcc/ChangeLog:
* config/pru/alu-zext.md (_noz0): New subst attribute.
(<code>_impl): Allow zero-extending the destination.
(<shift_op>): Remove unified pattern
(ashl_impl): New distinct pattern.
(lshr_impl): Ditto.
(alu3_zext_op0_subst): New subst iterator to zero-extend the
destination register.
gcc/testsuite/ChangeLog:
* gcc.target/pru/extzv-1.c: Update to mark the new more
efficient generated code sequence.
* gcc.target/pru/extzv-2.c: Ditto.
* gcc.target/pru/extzv-3.c: Ditto.
* gcc.target/pru/zero_extend-op0.c: New test.
Signed-off-by: Dimitar Dimitrov <dimitar@dinux.eu>
---
gcc/config/pru/alu-zext.md | 38 ++++++++++++++++---
gcc/testsuite/gcc.target/pru/extzv-1.c | 2 +-
gcc/testsuite/gcc.target/pru/extzv-2.c | 2 +-
gcc/testsuite/gcc.target/pru/extzv-3.c | 2 +-
.../gcc.target/pru/zero_extend-op0.c | 28 ++++++++++++++
5 files changed, 63 insertions(+), 9 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/pru/zero_extend-op0.c
diff --git a/gcc/config/pru/alu-zext.md b/gcc/config/pru/alu-zext.md
index 04378db4774..c88eaf0ab44 100644
--- a/gcc/config/pru/alu-zext.md
+++ b/gcc/config/pru/alu-zext.md
@@ -33,6 +33,7 @@
(define_subst_attr "alu2_zext" "alu2_zext_subst" "_z" "_noz")
+(define_subst_attr "alu3_zext_op0" "alu3_zext_op0_subst" "_z0" "_noz0")
(define_subst_attr "alu3_zext_op1" "alu3_zext_op1_subst" "_z1" "_noz1")
(define_subst_attr "alu3_zext_op2" "alu3_zext_op2_subst" "_z2" "_noz2")
(define_subst_attr "alu3_zext" "alu3_zext_subst" "_z" "_noz")
@@ -44,6 +45,7 @@ (define_subst_attr "lmbd_zext" "lmbd_zext_subst" "_z" "_noz")
(define_subst_attr "bitalu_zext" "bitalu_zext_subst" "_z" "_noz")
(define_code_iterator ALUOP3 [plus minus and ior xor umin umax ashift lshiftrt])
+(define_code_iterator ALUOP3_ZEXT0 [and ior xor umin umax lshiftrt])
(define_code_iterator ALUOP2 [neg not])
;; Arithmetic Operations
@@ -130,8 +132,9 @@ (define_insn "setbit_<EQD:mode><EQS0:mode>_<bitalu_zext>"
"set\\t%0, %1, %T2"
[(set_attr "type" "alu")])
-; Regular ALU ops
-(define_insn "<code>_impl<EQD:mode><EQS0:mode><EQS1:mode>_<alu3_zext><alu3_zext_op1><alu3_zext_op2>"
+; Regular ALU ops. For all of them it is safe to present the result as
+; zero-extended, because there is no carry or shifted-out bits.
+(define_insn "<code>_impl<EQD:mode><EQS0:mode><EQS1:mode>_<alu3_zext><alu3_zext_op0><alu3_zext_op1><alu3_zext_op2>"
[(set (match_operand:EQD 0 "register_operand" "=r")
(LOGICAL:EQD
(zero_extend:EQD
@@ -142,14 +145,25 @@ (define_insn "<code>_impl<EQD:mode><EQS0:mode><EQS1:mode>_<alu3_zext><alu3_zext_
"<logical_asm>\\t%0, %1, %u2"
[(set_attr "type" "alu")])
-; Shift ALU ops
-(define_insn "<shift_op>_impl<EQD:mode><EQS0:mode><EQS1:mode>_<alu3_zext><alu3_zext_op1><alu3_zext_op2>"
+; Shift left ALU op. Cannot present the result as zero-extended because
+; of the shifted-out bits.
+(define_insn "ashl_impl<EQD:mode><EQS0:mode><EQS1:mode>_<alu3_zext><alu3_zext_op1><alu3_zext_op2>"
[(set (match_operand:EQD 0 "register_operand" "=r")
- (SHIFT:EQD
+ (ashift:EQD
(zero_extend:EQD (match_operand:EQS0 1 "register_operand" "r"))
(zero_extend:EQD (match_operand:EQS1 2 "shift_operand" "rL"))))]
""
- "<shift_asm>\\t%0, %1, %2"
+ "lsl\\t%0, %1, %2"
+ [(set_attr "type" "alu")])
+
+; Shift right ALU op. The result can be presented as zero-extended.
+(define_insn "lshr_impl<EQD:mode><EQS0:mode><EQS1:mode>_<alu3_zext><alu3_zext_op0><alu3_zext_op1><alu3_zext_op2>"
+ [(set (match_operand:EQD 0 "register_operand" "=r")
+ (lshiftrt:EQD
+ (zero_extend:EQD (match_operand:EQS0 1 "register_operand" "r"))
+ (zero_extend:EQD (match_operand:EQS1 2 "shift_operand" "rL"))))]
+ ""
+ "lsr\\t%0, %1, %2"
[(set_attr "type" "alu")])
;; Substitutions
@@ -197,6 +211,18 @@ (define_subst "alu3_zext_op2_subst"
(ALUOP3:EQD (zero_extend:EQD (match_dup 1))
(match_dup 2)))])
+;; Some ALU operations with zero-extended inputs are
+;; equivalent to doing the same ALU operation in the
+;; smaller mode, and then zero-extending the output.
+(define_subst "alu3_zext_op0_subst"
+ [(set (match_operand:EQD 0)
+ (ALUOP3_ZEXT0:EQD (zero_extend:EQD (match_operand:EQS0 1))
+ (zero_extend:EQD (match_operand:EQS0 2))))]
+ "GET_MODE_SIZE (<EQS0:MODE>mode) < GET_MODE_SIZE (<EQD:MODE>mode)"
+ [(set (match_dup 0)
+ (zero_extend:EQD
+ (ALUOP3_ZEXT0:EQS0 (match_dup 1)
+ (match_dup 2))))])
(define_subst "lmbd_zext_subst"
[(set (match_operand:EQD 0)
diff --git a/gcc/testsuite/gcc.target/pru/extzv-1.c b/gcc/testsuite/gcc.target/pru/extzv-1.c
index 573ded99830..165e1d71081 100644
--- a/gcc/testsuite/gcc.target/pru/extzv-1.c
+++ b/gcc/testsuite/gcc.target/pru/extzv-1.c
@@ -1,6 +1,6 @@
/* { dg-do assemble } */
/* { dg-options "-Os" } */
-/* { dg-final { object-size text <= 12 } } */
+/* { dg-final { object-size text <= 8 } } */
struct S {
unsigned int a : 5;
diff --git a/gcc/testsuite/gcc.target/pru/extzv-2.c b/gcc/testsuite/gcc.target/pru/extzv-2.c
index e34ba138f16..6ecf9170c94 100644
--- a/gcc/testsuite/gcc.target/pru/extzv-2.c
+++ b/gcc/testsuite/gcc.target/pru/extzv-2.c
@@ -1,6 +1,6 @@
/* { dg-do assemble } */
/* { dg-options "-Os" } */
-/* { dg-final { object-size text <= 12 } } */
+/* { dg-final { object-size text <= 8 } } */
struct S {
unsigned int a : 5;
diff --git a/gcc/testsuite/gcc.target/pru/extzv-3.c b/gcc/testsuite/gcc.target/pru/extzv-3.c
index 66f4f376885..7799b8505af 100644
--- a/gcc/testsuite/gcc.target/pru/extzv-3.c
+++ b/gcc/testsuite/gcc.target/pru/extzv-3.c
@@ -1,6 +1,6 @@
/* { dg-do assemble } */
/* { dg-options "-Os" } */
-/* { dg-final { object-size text <= 16 } } */
+/* { dg-final { object-size text <= 12 } } */
struct S {
unsigned int a : 9;
diff --git a/gcc/testsuite/gcc.target/pru/zero_extend-op0.c b/gcc/testsuite/gcc.target/pru/zero_extend-op0.c
new file mode 100644
index 00000000000..e9e86f744ae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/zero_extend-op0.c
@@ -0,0 +1,28 @@
+/* ALU operations with zero extended destination. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+/* -O1 in the options is significant. Without it the zero extension might not
+ be coalesced into the ALU instruction. */
+
+unsigned int
+test_zext_xor_hi (unsigned short val1, unsigned short val2)
+{
+ /* { dg-final { scan-assembler "xor\\tr14, r14.w0, r14.w2" } } */
+ return (unsigned short)(val1 ^ val2);
+}
+
+unsigned int
+test_zext_or_hi (unsigned short val1, unsigned short val2)
+{
+ /* { dg-final { scan-assembler "or\\tr14, r14.w0, r14.w2" } } */
+ return (unsigned short)(val1 | val2);
+}
+
+unsigned int
+test_zext_ashr_hi_const (unsigned short val1)
+{
+ /* { dg-final { scan-assembler "lsr\\tr14, r14.w0, 3" } } */
+ return (unsigned short)(val1 >> 3);
+}
--
2.45.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [COMMITTED 5/9] pru: Skip register save if function will not return
2024-05-07 7:22 [COMMITTED 0/9] Small cleanups and improvements for PRU backend Dimitar Dimitrov
` (3 preceding siblings ...)
2024-05-07 7:22 ` [COMMITTED 4/9] pru: Add pattern variants for zero extending destination Dimitar Dimitrov
@ 2024-05-07 7:22 ` Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 6/9] pru: Drop usage of ATTRIBUTE_UNUSED Dimitar Dimitrov
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Dimitar Dimitrov @ 2024-05-07 7:22 UTC (permalink / raw)
To: gcc-patches; +Cc: Dimitar Dimitrov
There is no need to store callee-saved registers in prologue if the
function would never return. Size optimization is paramount for the
microcontroller-class PRU.
Some backends save some registers for noreturn functions. But for PRU
debuggability is a less concern because GDB has not been ported yet
for PRU.
gcc/ChangeLog:
* config/pru/pru.cc (prologue_saved_reg_p): Skip saving
if function will not return.
gcc/testsuite/ChangeLog:
* gcc.target/pru/noreturn-prologue-1.c: New test.
* gcc.target/pru/noreturn-prologue-2.c: New test.
Signed-off-by: Dimitar Dimitrov <dimitar@dinux.eu>
---
gcc/config/pru/pru.cc | 4 ++++
gcc/testsuite/gcc.target/pru/noreturn-prologue-1.c | 10 ++++++++++
gcc/testsuite/gcc.target/pru/noreturn-prologue-2.c | 11 +++++++++++
3 files changed, 25 insertions(+)
create mode 100644 gcc/testsuite/gcc.target/pru/noreturn-prologue-1.c
create mode 100644 gcc/testsuite/gcc.target/pru/noreturn-prologue-2.c
diff --git a/gcc/config/pru/pru.cc b/gcc/config/pru/pru.cc
index a76451f4223..e5ec398d2db 100644
--- a/gcc/config/pru/pru.cc
+++ b/gcc/config/pru/pru.cc
@@ -443,6 +443,10 @@ prologue_saved_reg_p (int regno)
{
gcc_assert (GP_REG_P (regno));
+ /* Do not save the register if function will not return. */
+ if (TREE_THIS_VOLATILE (current_function_decl))
+ return false;
+
if (df_regs_ever_live_p (regno) && !call_used_or_fixed_reg_p (regno))
return true;
diff --git a/gcc/testsuite/gcc.target/pru/noreturn-prologue-1.c b/gcc/testsuite/gcc.target/pru/noreturn-prologue-1.c
new file mode 100644
index 00000000000..af69e52d925
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/noreturn-prologue-1.c
@@ -0,0 +1,10 @@
+/* Ensure prologues are not generated for noreturn functions. */
+/* { dg-do assemble } */
+/* { dg-options "-Os" } */
+/* { dg-final { object-size text == 0 } } */
+
+void test(void)
+{
+ asm volatile ("# \n\t" : : : "r5", "r10");
+ __builtin_unreachable ();
+}
diff --git a/gcc/testsuite/gcc.target/pru/noreturn-prologue-2.c b/gcc/testsuite/gcc.target/pru/noreturn-prologue-2.c
new file mode 100644
index 00000000000..8d12a9c462b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/noreturn-prologue-2.c
@@ -0,0 +1,11 @@
+/* Ensure prologues are not generated for noreturn functions. */
+/* { dg-do assemble } */
+/* { dg-options "-Os" } */
+/* { dg-final { object-size text == 4 } } */
+
+void test(void)
+{
+ asm volatile ("# \n\t" : : : "r0", "r9");
+ for (;;)
+ ;
+}
--
2.45.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [COMMITTED 6/9] pru: Drop usage of ATTRIBUTE_UNUSED
2024-05-07 7:22 [COMMITTED 0/9] Small cleanups and improvements for PRU backend Dimitar Dimitrov
` (4 preceding siblings ...)
2024-05-07 7:22 ` [COMMITTED 5/9] pru: Skip register save if function will not return Dimitar Dimitrov
@ 2024-05-07 7:22 ` Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 7/9] pru: Use HOST_WIDE_INT_1U macro Dimitar Dimitrov
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Dimitar Dimitrov @ 2024-05-07 7:22 UTC (permalink / raw)
To: gcc-patches; +Cc: Dimitar Dimitrov
Remove usage of ATTRIBUTE_UNUSED. Instead remove the argument's name,
which in C++ means that the argument would not be used.
gcc/ChangeLog:
* config/pru/pru-passes.cc: Drop ATTRIBUTE_UNUSED and remove
argument's name.
* config/pru/pru-pragma.cc (pru_pragma_ctable_entry): Ditto.
* config/pru/pru.cc (pru_function_profiler): Ditto.
(pru_can_eliminate): Ditto.
(pru_rtx_costs): Ditto.
(pru_insert_attributes): Ditto.
(pru_function_value): Ditto.
(pru_libcall_value): Ditto.
(pru_return_in_memory): Ditto.
(pru_builtin_decl): Ditto.
(pru_expand_builtin): Ditto.
Signed-off-by: Dimitar Dimitrov <dimitar@dinux.eu>
---
gcc/config/pru/pru-passes.cc | 2 +-
gcc/config/pru/pru-pragma.cc | 2 +-
gcc/config/pru/pru.cc | 24 +++++++++---------------
3 files changed, 11 insertions(+), 17 deletions(-)
diff --git a/gcc/config/pru/pru-passes.cc b/gcc/config/pru/pru-passes.cc
index fdef068f6a3..a76be8fd528 100644
--- a/gcc/config/pru/pru-passes.cc
+++ b/gcc/config/pru/pru-passes.cc
@@ -68,7 +68,7 @@ public:
/* opt_pass methods: */
virtual unsigned int execute (function *);
- virtual bool gate (function *fun ATTRIBUTE_UNUSED)
+ virtual bool gate (function *)
{
return pru_current_abi == PRU_ABI_TI;
}
diff --git a/gcc/config/pru/pru-pragma.cc b/gcc/config/pru/pru-pragma.cc
index f948411aef7..73bb4b60e51 100644
--- a/gcc/config/pru/pru-pragma.cc
+++ b/gcc/config/pru/pru-pragma.cc
@@ -40,7 +40,7 @@
WARNING: Only immediate constant addresses are currently supported. */
static void
-pru_pragma_ctable_entry (cpp_reader * reader ATTRIBUTE_UNUSED)
+pru_pragma_ctable_entry (cpp_reader *)
{
tree ctable_index, base_addr;
enum cpp_ttype type;
diff --git a/gcc/config/pru/pru.cc b/gcc/config/pru/pru.cc
index e5ec398d2db..49d35c60d12 100644
--- a/gcc/config/pru/pru.cc
+++ b/gcc/config/pru/pru.cc
@@ -405,7 +405,7 @@ pru_get_return_address (int count)
/* Implement FUNCTION_PROFILER macro. */
void
-pru_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
+pru_function_profiler (FILE *file, int)
{
fprintf (file, "\tmov\tr1, ra\n");
fprintf (file, "\tcall\t_mcount\n");
@@ -467,7 +467,7 @@ prologue_saved_reg_p (int regno)
/* Implement TARGET_CAN_ELIMINATE. */
static bool
-pru_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+pru_can_eliminate (const int, const int to)
{
if (to == STACK_POINTER_REGNUM)
return !frame_pointer_needed;
@@ -637,9 +637,7 @@ pru_option_override (void)
cost has been computed, and false if subexpressions should be
scanned. In either case, *TOTAL contains the cost result. */
static bool
-pru_rtx_costs (rtx x, machine_mode mode,
- int outer_code, int opno ATTRIBUTE_UNUSED,
- int *total, bool speed ATTRIBUTE_UNUSED)
+pru_rtx_costs (rtx x, machine_mode mode, int outer_code, int, int *total, bool)
{
const int code = GET_CODE (x);
@@ -2174,7 +2172,7 @@ pru_nongeneric_pointer_addrspace (tree typ)
during the "mov<mode>" pattern expansion. */
static void
-pru_insert_attributes (tree node, tree *attributes ATTRIBUTE_UNUSED)
+pru_insert_attributes (tree node, tree *)
{
/* Validate __regio_symbol variable declarations. */
@@ -2399,15 +2397,14 @@ pru_function_arg_advance (cumulative_args_t cum_v,
/* Implement TARGET_FUNCTION_VALUE. */
static rtx
-pru_function_value (const_tree ret_type, const_tree fn ATTRIBUTE_UNUSED,
- bool outgoing ATTRIBUTE_UNUSED)
+pru_function_value (const_tree ret_type, const_tree, bool)
{
return gen_rtx_REG (TYPE_MODE (ret_type), FIRST_RETVAL_REGNUM);
}
/* Implement TARGET_LIBCALL_VALUE. */
static rtx
-pru_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
+pru_libcall_value (machine_mode mode, const_rtx)
{
return gen_rtx_REG (mode, FIRST_RETVAL_REGNUM);
}
@@ -2421,7 +2418,7 @@ pru_function_value_regno_p (const unsigned int regno)
/* Implement TARGET_RETURN_IN_MEMORY. */
bool
-pru_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
+pru_return_in_memory (const_tree type, const_tree)
{
bool in_memory = (!pru_arg_in_reg_bysize (int_size_in_bytes (type))
|| int_size_in_bytes (type) == -1);
@@ -2989,7 +2986,7 @@ pru_init_builtins (void)
/* Implement TARGET_BUILTIN_DECL. */
static tree
-pru_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
+pru_builtin_decl (unsigned code, bool)
{
switch (code)
{
@@ -3068,10 +3065,7 @@ pru_expand_delay_cycles (rtx arg)
IGNORE is nonzero if the value is to be ignored. */
static rtx
-pru_expand_builtin (tree exp, rtx target,
- rtx subtarget ATTRIBUTE_UNUSED,
- machine_mode mode,
- int ignore ATTRIBUTE_UNUSED)
+pru_expand_builtin (tree exp, rtx target, rtx, machine_mode mode, int)
{
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
--
2.45.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [COMMITTED 7/9] pru: Use HOST_WIDE_INT_1U macro
2024-05-07 7:22 [COMMITTED 0/9] Small cleanups and improvements for PRU backend Dimitar Dimitrov
` (5 preceding siblings ...)
2024-05-07 7:22 ` [COMMITTED 6/9] pru: Drop usage of ATTRIBUTE_UNUSED Dimitar Dimitrov
@ 2024-05-07 7:22 ` Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 8/9] pru: Refactor to use passes definition file Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 9/9] pru: New validation pass for minrt Dimitar Dimitrov
8 siblings, 0 replies; 10+ messages in thread
From: Dimitar Dimitrov @ 2024-05-07 7:22 UTC (permalink / raw)
To: gcc-patches; +Cc: Dimitar Dimitrov
Use the HOST_WIDE_INT_1U macro instead of literal 1 when constructing
constants for RTL.
gcc/ChangeLog:
* config/pru/pru.md (lshrdi3): Use HOST_WIDE_INT_1U macro.
(ashldi3): Ditto.
Signed-off-by: Dimitar Dimitrov <dimitar@dinux.eu>
---
gcc/config/pru/pru.md | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/gcc/config/pru/pru.md b/gcc/config/pru/pru.md
index 2ceea2e7b1c..db7a5af6875 100644
--- a/gcc/config/pru/pru.md
+++ b/gcc/config/pru/pru.md
@@ -870,7 +870,8 @@ (define_expand "lshrdi3"
JUMP_LABEL (j) = skip_hiset_label;
LABEL_NUSES (skip_hiset_label)++;
- emit_insn (gen_iorsi3 (dst_lo, dst_lo, GEN_INT (1 << 31)));
+ const HOST_WIDE_INT bit31_mask = HOST_WIDE_INT_1U << 31;
+ emit_insn (gen_iorsi3 (dst_lo, dst_lo, GEN_INT (bit31_mask)));
emit_label (skip_hiset_label);
emit_insn (gen_rtx_SET (dst_hi,
gen_rtx_LSHIFTRT (SImode, src_hi, const1_rtx)));
@@ -959,7 +960,8 @@ (define_expand "ashldi3"
JUMP_LABEL (j) = skip_hiset_label;
LABEL_NUSES (skip_hiset_label)++;
- emit_insn (gen_iorsi3 (dst_hi, dst_hi, GEN_INT (1 << 0)));
+ const HOST_WIDE_INT bit0_mask = HOST_WIDE_INT_1U << 0;
+ emit_insn (gen_iorsi3 (dst_hi, dst_hi, GEN_INT (bit0_mask)));
emit_label (skip_hiset_label);
emit_insn (gen_rtx_SET (dst_lo,
gen_rtx_ASHIFT (SImode, src_lo, const1_rtx)));
--
2.45.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [COMMITTED 8/9] pru: Refactor to use passes definition file
2024-05-07 7:22 [COMMITTED 0/9] Small cleanups and improvements for PRU backend Dimitar Dimitrov
` (6 preceding siblings ...)
2024-05-07 7:22 ` [COMMITTED 7/9] pru: Use HOST_WIDE_INT_1U macro Dimitar Dimitrov
@ 2024-05-07 7:22 ` Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 9/9] pru: New validation pass for minrt Dimitar Dimitrov
8 siblings, 0 replies; 10+ messages in thread
From: Dimitar Dimitrov @ 2024-05-07 7:22 UTC (permalink / raw)
To: gcc-patches; +Cc: Dimitar Dimitrov
Switch to using a passes definition file instead of explicitly
registering the PRU-specific passes in pru.cc. This would make it
cleaner to add new PRU-specific passes.
There are no functional changes.
gcc/ChangeLog:
* config/pru/pru-passes.cc (class pass_tiabi_check): Rename to
add "pru_" prefix.
(class pass_pru_tiabi_check): Ditto.
(pass_tiabi_check::execute): Ditto.
(pass_pru_tiabi_check::execute): Ditto.
(make_pru_tiabi_check): Ditto.
(pru_register_abicheck_pass): Remove.
* config/pru/pru-protos.h (pru_register_abicheck_pass): Remove.
(make_pru_tiabi_check): Add declaration.
* config/pru/pru.cc (pru_option_override): Remove explicit pass
registration.
* config/pru/t-pru: Register PRU passes definition file.
* config/pru/pru-passes.def: New file.
Signed-off-by: Dimitar Dimitrov <dimitar@dinux.eu>
---
gcc/config/pru/pru-passes.cc | 30 +++++++++---------------------
gcc/config/pru/pru-passes.def | 24 ++++++++++++++++++++++++
gcc/config/pru/pru-protos.h | 2 +-
gcc/config/pru/pru.cc | 5 -----
gcc/config/pru/t-pru | 2 ++
5 files changed, 36 insertions(+), 27 deletions(-)
create mode 100644 gcc/config/pru/pru-passes.def
diff --git a/gcc/config/pru/pru-passes.cc b/gcc/config/pru/pru-passes.cc
index a76be8fd528..d2c6ae8737d 100644
--- a/gcc/config/pru/pru-passes.cc
+++ b/gcc/config/pru/pru-passes.cc
@@ -44,10 +44,10 @@ namespace {
/* Scan the tree to ensure that the compiled code by GCC
conforms to the TI ABI specification. If GCC cannot
output a conforming code, raise an error. */
-const pass_data pass_data_tiabi_check =
+const pass_data pass_data_pru_tiabi_check =
{
GIMPLE_PASS, /* type */
- "*tiabi_check", /* name */
+ "*pru_tiabi_check", /* name */
OPTGROUP_NONE, /* optinfo_flags */
TV_NONE, /* tv_id */
PROP_gimple_any, /* properties_required */
@@ -58,11 +58,11 @@ const pass_data pass_data_tiabi_check =
};
/* Implementation class for the TI ABI compliance-check pass. */
-class pass_tiabi_check : public gimple_opt_pass
+class pass_pru_tiabi_check : public gimple_opt_pass
{
public:
- pass_tiabi_check (gcc::context *ctxt)
- : gimple_opt_pass (pass_data_tiabi_check, ctxt)
+ pass_pru_tiabi_check (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_pru_tiabi_check, ctxt)
{}
/* opt_pass methods: */
@@ -73,7 +73,7 @@ public:
return pru_current_abi == PRU_ABI_TI;
}
-}; // class pass_tiabi_check
+}; // class pass_pru_tiabi_check
\f
/* Return 1 if type TYPE is a pointer to function type or a
structure having a pointer to function type as one of its fields.
@@ -187,7 +187,7 @@ check_op_callback (tree *tp, int *walk_subtrees, void *data)
/* Pass implementation. */
unsigned
-pass_tiabi_check::execute (function *fun)
+pass_pru_tiabi_check::execute (function *fun)
{
struct walk_stmt_info wi;
const_tree fntype = TREE_TYPE (fun->decl);
@@ -210,19 +210,7 @@ pass_tiabi_check::execute (function *fun)
} // anon namespace
gimple_opt_pass *
-make_pass_tiabi_check (gcc::context *ctxt)
+make_pru_tiabi_check (gcc::context *ctxt)
{
- return new pass_tiabi_check (ctxt);
-}
-
-/* Register as early as possible. */
-void
-pru_register_abicheck_pass (void)
-{
- opt_pass *tiabi_check = make_pass_tiabi_check (g);
- struct register_pass_info tiabi_check_info
- = { tiabi_check, "*warn_unused_result",
- 1, PASS_POS_INSERT_AFTER
- };
- register_pass (&tiabi_check_info);
+ return new pass_pru_tiabi_check (ctxt);
}
diff --git a/gcc/config/pru/pru-passes.def b/gcc/config/pru/pru-passes.def
new file mode 100644
index 00000000000..cdef089bd82
--- /dev/null
+++ b/gcc/config/pru/pru-passes.def
@@ -0,0 +1,24 @@
+/* Description of target passes for PRU.
+ Copyright (C) 2024 Free Software Foundation, Inc. */
+
+/* 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
+ <http://www.gnu.org/licenses/>. */
+
+/* If strict TI ABI conformance is requested, then this pass would validate
+ that the compiled code by GCC conforms to the TI ABI specification.
+ If GCC cannot output a conforming code, then an error is raised. */
+
+INSERT_PASS_AFTER (pass_warn_unused_result, 1, pru_tiabi_check);
diff --git a/gcc/config/pru/pru-protos.h b/gcc/config/pru/pru-protos.h
index e8670ad4326..74426bb86ea 100644
--- a/gcc/config/pru/pru-protos.h
+++ b/gcc/config/pru/pru-protos.h
@@ -72,7 +72,7 @@ extern int pru_get_ctable_base_offset (unsigned HOST_WIDE_INT caddr);
extern int pru_symref2ioregno (rtx op);
-extern void pru_register_abicheck_pass (void);
+extern rtl_opt_pass *make_pru_tiabi_check (gcc::context *);
#endif /* RTX_CODE */
diff --git a/gcc/config/pru/pru.cc b/gcc/config/pru/pru.cc
index 49d35c60d12..41d7195d2b5 100644
--- a/gcc/config/pru/pru.cc
+++ b/gcc/config/pru/pru.cc
@@ -626,11 +626,6 @@ pru_option_override (void)
options. */
target_option_default_node = target_option_current_node
= build_target_option_node (&global_options, &global_options_set);
-
- /* Due to difficulties in implementing the TI ABI with GCC,
- at least check and error-out if GCC cannot compile a
- compliant output. */
- pru_register_abicheck_pass ();
}
\f
/* Compute a (partial) cost for rtx X. Return true if the complete
diff --git a/gcc/config/pru/t-pru b/gcc/config/pru/t-pru
index 389ef2d8c98..1e67fdf11c1 100644
--- a/gcc/config/pru/t-pru
+++ b/gcc/config/pru/t-pru
@@ -19,6 +19,8 @@
# License along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
+PASSES_EXTRA += $(srcdir)/config/pru/pru-passes.def
+
# Unfortunately mabi=ti is not feature-complete enough to build newlib.
# Hence we cannot present mabi=gnu/ti as a multilib option.
--
2.45.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [COMMITTED 9/9] pru: New validation pass for minrt
2024-05-07 7:22 [COMMITTED 0/9] Small cleanups and improvements for PRU backend Dimitar Dimitrov
` (7 preceding siblings ...)
2024-05-07 7:22 ` [COMMITTED 8/9] pru: Refactor to use passes definition file Dimitar Dimitrov
@ 2024-05-07 7:22 ` Dimitar Dimitrov
8 siblings, 0 replies; 10+ messages in thread
From: Dimitar Dimitrov @ 2024-05-07 7:22 UTC (permalink / raw)
To: gcc-patches; +Cc: Dimitar Dimitrov
Add a new pru-specific pass to validate that the assumptions for the
minimal C runtime are not violated by the user program.
gcc/ChangeLog:
* config/pru/pru-passes.cc (class pass_pru_minrt_check): New
pass.
(pass_pru_minrt_check::execute): New method.
(make_pru_minrt_check): New function.
* config/pru/pru-passes.def (INSERT_PASS_AFTER): Register the
minrt check pass.
* config/pru/pru-protos.h (make_pru_minrt_check): Add
declaration.
gcc/testsuite/ChangeLog:
* g++.target/pru/minrt-1.cc: New test.
* g++.target/pru/minrt-2.cc: New test.
* g++.target/pru/minrt-3.cc: New test.
* g++.target/pru/pru.exp: New test.
* gcc.target/pru/minrt-1.c: New test.
* gcc.target/pru/minrt-2.c: New test.
* gcc.target/pru/minrt-3.c: New test.
Signed-off-by: Dimitar Dimitrov <dimitar@dinux.eu>
---
gcc/config/pru/pru-passes.cc | 70 +++++++++++++++++++++++++
gcc/config/pru/pru-passes.def | 5 ++
gcc/config/pru/pru-protos.h | 1 +
gcc/testsuite/g++.target/pru/minrt-1.cc | 10 ++++
gcc/testsuite/g++.target/pru/minrt-2.cc | 10 ++++
gcc/testsuite/g++.target/pru/minrt-3.cc | 9 ++++
gcc/testsuite/g++.target/pru/pru.exp | 34 ++++++++++++
gcc/testsuite/gcc.target/pru/minrt-1.c | 10 ++++
gcc/testsuite/gcc.target/pru/minrt-2.c | 10 ++++
gcc/testsuite/gcc.target/pru/minrt-3.c | 9 ++++
10 files changed, 168 insertions(+)
create mode 100644 gcc/testsuite/g++.target/pru/minrt-1.cc
create mode 100644 gcc/testsuite/g++.target/pru/minrt-2.cc
create mode 100644 gcc/testsuite/g++.target/pru/minrt-3.cc
create mode 100644 gcc/testsuite/g++.target/pru/pru.exp
create mode 100644 gcc/testsuite/gcc.target/pru/minrt-1.c
create mode 100644 gcc/testsuite/gcc.target/pru/minrt-2.c
create mode 100644 gcc/testsuite/gcc.target/pru/minrt-3.c
diff --git a/gcc/config/pru/pru-passes.cc b/gcc/config/pru/pru-passes.cc
index d2c6ae8737d..5e7e22df65d 100644
--- a/gcc/config/pru/pru-passes.cc
+++ b/gcc/config/pru/pru-passes.cc
@@ -214,3 +214,73 @@ make_pru_tiabi_check (gcc::context *ctxt)
{
return new pass_pru_tiabi_check (ctxt);
}
+\f
+namespace {
+
+/* Scan the tree to ensure that the compiled code by GCC
+ conforms to the non-standard minimal runtime. */
+const pass_data pass_data_pru_minrt_check =
+{
+ GIMPLE_PASS, /* type */
+ "*pru_minrt_check", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_NONE, /* tv_id */
+ PROP_gimple_any, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+/* Implementation class for the minrt compliance-check pass. */
+class pass_pru_minrt_check : public gimple_opt_pass
+{
+public:
+ pass_pru_minrt_check (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_pru_minrt_check, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual unsigned int execute (function *);
+
+ virtual bool gate (function *)
+ {
+ return TARGET_MINRT;
+ }
+
+}; // class pass_pru_minrt_check
+\f
+/* Pass implementation. */
+unsigned
+pass_pru_minrt_check::execute (function *fun)
+{
+ const_tree fntype = TREE_TYPE (fun->decl);
+
+ if (id_equal (DECL_NAME (fun->decl), "main"))
+ {
+ /* Argument list always ends with VOID_TYPE, so subtract one
+ to get the number of function arguments. */
+ const unsigned num_args = list_length (TYPE_ARG_TYPES (fntype)) - 1;
+
+ if (num_args != 0)
+ error_at (DECL_SOURCE_LOCATION (fun->decl), "function %<main%> "
+ "must have no arguments when using the "
+ "%<-minrt%> option");
+
+ /* The required CFG analysis to detect when a functions would never
+ return is available only with -O1 and higher. */
+ if (optimize >= 1 && !TREE_THIS_VOLATILE (fun->decl))
+ error_at (DECL_SOURCE_LOCATION (fun->decl), "function %<main%> "
+ "must never return when using the "
+ "%<-minrt%> option");
+ }
+ return 0;
+}
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pru_minrt_check (gcc::context *ctxt)
+{
+ return new pass_pru_minrt_check (ctxt);
+}
diff --git a/gcc/config/pru/pru-passes.def b/gcc/config/pru/pru-passes.def
index cdef089bd82..3eee313ac67 100644
--- a/gcc/config/pru/pru-passes.def
+++ b/gcc/config/pru/pru-passes.def
@@ -22,3 +22,8 @@
If GCC cannot output a conforming code, then an error is raised. */
INSERT_PASS_AFTER (pass_warn_unused_result, 1, pru_tiabi_check);
+
+/* If -minrt option is used, then this pass would validate
+ that the compiled code by GCC is compatible with the minimal
+ C runtime. */
+INSERT_PASS_AFTER (pass_warn_function_noreturn, 1, pru_minrt_check);
diff --git a/gcc/config/pru/pru-protos.h b/gcc/config/pru/pru-protos.h
index 74426bb86ea..3baf605d915 100644
--- a/gcc/config/pru/pru-protos.h
+++ b/gcc/config/pru/pru-protos.h
@@ -73,6 +73,7 @@ extern int pru_get_ctable_base_offset (unsigned HOST_WIDE_INT caddr);
extern int pru_symref2ioregno (rtx op);
extern rtl_opt_pass *make_pru_tiabi_check (gcc::context *);
+extern rtl_opt_pass *make_pru_minrt_check (gcc::context *);
#endif /* RTX_CODE */
diff --git a/gcc/testsuite/g++.target/pru/minrt-1.cc b/gcc/testsuite/g++.target/pru/minrt-1.cc
new file mode 100644
index 00000000000..c30ad2cbe1e
--- /dev/null
+++ b/gcc/testsuite/g++.target/pru/minrt-1.cc
@@ -0,0 +1,10 @@
+/* Test minrt checks */
+
+/* { dg-options "-O1 -minrt" } */
+
+
+int main(void)
+{
+ for (;;)
+ ;
+}
diff --git a/gcc/testsuite/g++.target/pru/minrt-2.cc b/gcc/testsuite/g++.target/pru/minrt-2.cc
new file mode 100644
index 00000000000..258385dbdba
--- /dev/null
+++ b/gcc/testsuite/g++.target/pru/minrt-2.cc
@@ -0,0 +1,10 @@
+/* Test minrt checks */
+
+/* { dg-options "-O1 -minrt" } */
+
+int main(int argc, char *argv[])
+/* { dg-error "function 'main' must have no arguments when using the '-minrt' option" "" { target pru-*-* } .-1 } */
+{
+ for (;;)
+ ;
+}
diff --git a/gcc/testsuite/g++.target/pru/minrt-3.cc b/gcc/testsuite/g++.target/pru/minrt-3.cc
new file mode 100644
index 00000000000..07b4e5e430a
--- /dev/null
+++ b/gcc/testsuite/g++.target/pru/minrt-3.cc
@@ -0,0 +1,9 @@
+/* Test minrt checks */
+
+/* { dg-options "-O1 -minrt" } */
+
+int main(void)
+/* { dg-error "function 'main' must never return when using the '-minrt' option" "" { target pru-*-* } .-1 } */
+{
+ return 0;
+}
diff --git a/gcc/testsuite/g++.target/pru/pru.exp b/gcc/testsuite/g++.target/pru/pru.exp
new file mode 100644
index 00000000000..c9a3ab2b076
--- /dev/null
+++ b/gcc/testsuite/g++.target/pru/pru.exp
@@ -0,0 +1,34 @@
+# Copyright (C) 2024 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# <http://www.gnu.org/licenses/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't a pru target.
+if ![istarget pru*-*-*] then {
+ return
+}
+
+# Load support procs.
+load_lib g++-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.cc]] "" ""
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gcc.target/pru/minrt-1.c b/gcc/testsuite/gcc.target/pru/minrt-1.c
new file mode 100644
index 00000000000..c30ad2cbe1e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/minrt-1.c
@@ -0,0 +1,10 @@
+/* Test minrt checks */
+
+/* { dg-options "-O1 -minrt" } */
+
+
+int main(void)
+{
+ for (;;)
+ ;
+}
diff --git a/gcc/testsuite/gcc.target/pru/minrt-2.c b/gcc/testsuite/gcc.target/pru/minrt-2.c
new file mode 100644
index 00000000000..258385dbdba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/minrt-2.c
@@ -0,0 +1,10 @@
+/* Test minrt checks */
+
+/* { dg-options "-O1 -minrt" } */
+
+int main(int argc, char *argv[])
+/* { dg-error "function 'main' must have no arguments when using the '-minrt' option" "" { target pru-*-* } .-1 } */
+{
+ for (;;)
+ ;
+}
diff --git a/gcc/testsuite/gcc.target/pru/minrt-3.c b/gcc/testsuite/gcc.target/pru/minrt-3.c
new file mode 100644
index 00000000000..07b4e5e430a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/minrt-3.c
@@ -0,0 +1,9 @@
+/* Test minrt checks */
+
+/* { dg-options "-O1 -minrt" } */
+
+int main(void)
+/* { dg-error "function 'main' must never return when using the '-minrt' option" "" { target pru-*-* } .-1 } */
+{
+ return 0;
+}
--
2.45.0
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2024-05-07 7:23 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-05-07 7:22 [COMMITTED 0/9] Small cleanups and improvements for PRU backend Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 1/9] pru: Implement TARGET_ADDRESS_COST Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 2/9] pru: Implement zero fill for 64-bit registers Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 3/9] pru: Optimize the extzv and insv patterns Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 4/9] pru: Add pattern variants for zero extending destination Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 5/9] pru: Skip register save if function will not return Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 6/9] pru: Drop usage of ATTRIBUTE_UNUSED Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 7/9] pru: Use HOST_WIDE_INT_1U macro Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 8/9] pru: Refactor to use passes definition file Dimitar Dimitrov
2024-05-07 7:22 ` [COMMITTED 9/9] pru: New validation pass for minrt Dimitar Dimitrov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).