From aa1d47f97d35a758f620a5c22554ff18c905cdbe Mon Sep 17 00:00:00 2001 From: turjan Date: Tue, 16 Jun 2026 15:43:03 +0000 Subject: [PATCH] arc: fix for extvsi split patterns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Description change to the pattern define_insn_and_split "*extvsi_n_0" If using && reload_completed the compiler is forced to wait until after the RA/Reload pass is entirely finished. Physical registers are already permanently locked down. If using && 1 the split is allowed to occur early such as during the combine pass when registers are still flexible pseudos. Splitting earlier (using && 1) is generally better than waiting until after reload—provided as it provides significant optimization advantages. Description change to pattern define_insn_and_split "*extvsi_1_0" keeping "0" with && 1 is not in accordance with the GCC instruction pattern rules: 1. According to RTL instruction definition by writing "0" we are telling the dataflow analysis that operand 0 and operand 1 must share the exact same physical register. By writing && 1 we are telling the compiler to split this instruction into pieces during the very early optimization passes (like combine) which is before physical registers are even handed out the "0" constraint. 2. When you split an instruction early using && 1 the purpose is to allow subsequent optimization passes (like Scheduling for register pressure, cse, dce etc) to optimize the broken instructions. If you combine an early split with a restrictive "0" the df-scan gets confused about the exact life ranges of the pseudo registers. Because it thinks the destination and source are linked it may assume a register becomes dead earlier than it actually does. This prevents subsequent passes from safely reordering instructions or eliminating redundant operations resulting in less optimized code. --- gcc/config/arc/arc.md | 4 +- .../gcc.target/arc/extvsi-sign-extract.c | 67 +++++++++++++++++++ 2 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arc/extvsi-sign-extract.c diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md index 54b65fefe6ac..9fe323c5f37b 100644 --- a/gcc/config/arc/arc.md +++ b/gcc/config/arc/arc.md @@ -6268,7 +6268,7 @@ archs4x, archs4xd" ;; Split sign-extension of single least significant bit as and x,$1;neg x (define_insn_and_split "*extvsi_1_0" [(set (match_operand:SI 0 "register_operand" "=r") - (sign_extract:SI (match_operand:SI 1 "register_operand" "0") + (sign_extract:SI (match_operand:SI 1 "register_operand" "r") (const_int 1) (const_int 0)))] "!TARGET_BARREL_SHIFTER" @@ -6288,7 +6288,7 @@ archs4x, archs4xd" && IN_RANGE (INTVAL (operands[2]), 2, (optimize_insn_for_size_p () ? 28 : 30))" "#" - "&& reload_completed" + "&& 1" [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 3))) (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 4))) (set (match_dup 0) (minus:SI (match_dup 0) (match_dup 4)))] diff --git a/gcc/testsuite/gcc.target/arc/extvsi-sign-extract.c b/gcc/testsuite/gcc.target/arc/extvsi-sign-extract.c new file mode 100644 index 000000000000..d7f4d0d65184 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/extvsi-sign-extract.c @@ -0,0 +1,67 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -mcpu=em -save-temps" } */ + +#include +#include + +/* Test multi-bit Extraction Pattern (*extvsi_n_0). */ +struct bitstruct { + unsigned a : 21; + unsigned b : 8; + unsigned c : 2; + int d : 17; +} __attribute__((packed)); + +static volatile struct bitstruct bits = { + .a = 0x100, + .b = 0x2f, + .c = 0, + .d = 0 +}; + +volatile int global_d; + +/* Test snigle-bit Extraction Pattern (*extvsi_1_0). */ +struct source_struct { + int target_bit : 1; + unsigned int padding : 31; +} __attribute__((packed)); + +static volatile struct source_struct data = { + .target_bit = 1, + .padding = 0xabcdef +}; + +volatile int destination; + +int +main (void) +{ + /* 1. Execute Multi-bit Sign-Extract Test */ + global_d = bits.d; + if (global_d != 0) + { + printf ("FAIL: Multi-bit extract (*extvsi_n_0) failed. Expected 0, got %d\n", global_d); + abort (); + } + + /* 2. Execute Single-bit Sign-Extract Test */ + destination = data.target_bit; + if (destination != -1) + { + printf ("FAIL: Single-bit extract (*extvsi_1_0) failed. Expected -1, got %d\n", destination); + abort (); + } + + printf ("PASS: Both sign-extract patterns executed successfully.\n"); + return 0; +} + +/* Check that the extvsi_n_0 split got triggered. */ +/* { dg-final { scan-assembler "bmsk.*,16" } } */ +/* { dg-final { scan-assembler "bxor.*,16" } } */ +/* { dg-final { scan-assembler "sub.*,65536" } } */ + +/* Check that the extvsi_1_0 split got triggered. */ +/* { dg-final { scan-assembler "bmsk.*,0" } } */ +/* { dg-final { scan-assembler "neg" } } */