https://gcc.gnu.org/g:a9e84ce68bf3779e5bbc643cfab457803f7b5ad7

commit a9e84ce68bf3779e5bbc643cfab457803f7b5ad7
Author: Christoph Müllner <christoph.muell...@vrull.eu>
Date:   Tue Aug 6 06:48:59 2024 +0200

    RISC-V: rv32/DF: Prevent 2 SImode loads using XTheadMemIdx
    
    When enabling XTheadFmv/Zfa and XThead(F)MemIdx, we might end up
    with the following insn (registers are examples, but of correct class):
    
    (set (reg:DF a4)
         (mem:DF (plus:SI (mult:SI (reg:SI a0)
                                   (const_int 8))
                          (reg:SI a5))))
    
    This is a result of an attempt to load the DF register via two SI
    register loads followed by XTheadFmv/Zfa instructions to move the
    contents of the two SI registers into the DF register.
    
    The two loads are generated in riscv_split_doubleword_move(),
    where the second load adds an offset of 4 to load address.
    While this works fine for RVI loads, this can't be handled
    for XTheadMemIdx addresses.  Coming back to the example above,
    we would end up with the following insn, which can't be simplified
    or matched:
    
    (set (reg:SI a4)
         (mem:SI (plus:SI (plus:SI (mult:SI (reg:SI a0)
                                            (const_int 8))
                                   (reg:SI a5))
                          (const_int 4))))
    
    This triggered an ICE in the past, which was resolved in b79cd204c780,
    which also added the test xtheadfmemidx-medany.c, where the examples
    are from.  The patch postponed the optimization insn_and_split pattern
    for XThead(F)MemIdx, so that the situation could effectively be avoided.
    
    Since we don't want to rely on these optimization pattern in the future,
    we need a different solution.  Therefore, this patch restricts the
    movdf_hardfloat_rv32 insn to not match for split-double-word-moves
    with XThead(F)MemIdx operands.  This ensures we don't need to split
    them up later.
    
    When looking at the code generation of the test file, we can see that
    we have less GP<->FP conversions, but cannot use the indexed loads.
    The new sequence is identical to rv32gc_xtheadfmv (similar to rv32gc_zfa).
    
    Old:
    [...]
            lla     a5,.LANCHOR0
            th.flrd fa5,a5,a0,3
            fmv.x.w a4,fa5
            th.fmv.x.hw     a5,fa5
    .L1:
            fmv.w.x fa0,a4
            th.fmv.hw.x     fa0,a5
            ret
    [...]
    
    New:
    [...]
            lla     a5,.LANCHOR0
            slli    a4,a0,3
            add     a4,a4,a5
            lw      a5,4(a4)
            lw      a4,0(a4)
    .L1:
            fmv.w.x fa0,a4
            th.fmv.hw.x     fa0,a5
            ret
    [...]
    
    This was tested (together with the patch that eliminates the
    XTheadMemIdx optimization patterns) with SPEC CPU 2017 intrate
    on QEMU (RV64/lp64d).
    
    gcc/ChangeLog:
    
            * config/riscv/constraints.md (th_m_noi): New constraint.
            * config/riscv/riscv.md: Adjust movdf_hardfloat_rv32 for
            XTheadMemIdx.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/riscv/xtheadfmemidx-xtheadfmv-medany.c: Adjust.
            * gcc.target/riscv/xtheadfmemidx-zfa-medany.c: Likewise.
    
    Signed-off-by: Christoph Müllner <christoph.muell...@vrull.eu>
    (cherry picked from commit 33aca37ebc0c06e9c9240a8a0c13e31a0bcd4efb)

Diff:
---
 gcc/config/riscv/constraints.md                                 | 9 +++++++++
 gcc/config/riscv/riscv.md                                       | 4 ++--
 gcc/testsuite/gcc.target/riscv/xtheadfmemidx-xtheadfmv-medany.c | 3 ++-
 gcc/testsuite/gcc.target/riscv/xtheadfmemidx-zfa-medany.c       | 3 ++-
 4 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md
index a9ee346af6f..3ab6d542622 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -243,6 +243,15 @@
   (and (match_code "mem")
        (match_test "th_memidx_legitimate_index_p (op, true)")))
 
+(define_memory_constraint "th_m_noi"
+  "@internal
+   A MEM with does not match XTheadMemIdx operands."
+  (and (match_code "mem")
+       (and (match_test "!th_memidx_legitimate_modify_p (op, true)")
+           (and (match_test "!th_memidx_legitimate_modify_p (op, false)")
+                (and (match_test "!th_memidx_legitimate_index_p (op, false)")
+                     (match_test "!th_memidx_legitimate_index_p (op, 
true)"))))))
+
 ;; CORE-V Constraints
 (define_constraint "CV_alu_pow2"
   "@internal
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index d9f6c1765d0..f46851dd471 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -2592,8 +2592,8 @@
 ;; In RV32, we lack fmv.x.d and fmv.d.x.  Go through memory instead.
 ;; (However, we can still use fcvt.d.w to zero a floating-point register.)
 (define_insn "*movdf_hardfloat_rv32"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,   
f,f,f,m,m,*zmvf,*zmvr,  *r,*r,*m")
-       (match_operand:DF 1 "move_operand"         " 
f,zfli,G,m,f,G,*zmvr,*zmvf,*r*G,*m,*r"))]
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,   
f,f,f,m,m,*zmvf,*zmvr,  *r,*r,*th_m_noi")
+       (match_operand:DF 1 "move_operand"         " 
f,zfli,G,m,f,G,*zmvr,*zmvf,*r*G,*th_m_noi,*r"))]
   "!TARGET_64BIT && TARGET_DOUBLE_FLOAT
    && (register_operand (operands[0], DFmode)
        || reg_or_0_operand (operands[1], DFmode))"
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadfmemidx-xtheadfmv-medany.c 
b/gcc/testsuite/gcc.target/riscv/xtheadfmemidx-xtheadfmv-medany.c
index 7c70b775824..6746c314057 100644
--- a/gcc/testsuite/gcc.target/riscv/xtheadfmemidx-xtheadfmv-medany.c
+++ b/gcc/testsuite/gcc.target/riscv/xtheadfmemidx-xtheadfmv-medany.c
@@ -35,5 +35,6 @@ double foo (int i, int j)
   return z;
 }
 
-/* { dg-final { scan-assembler-times {\mth\.flrd\M} 1 } } */
+/* { dg-final { scan-assembler-not {\mth\.flrd\M} } } */
+/* { dg-final { scan-assembler-times {\mlw\M} 2 } } */
 /* { dg-final { scan-assembler-times {\mth\.fmv\.hw\.x\M} 3 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadfmemidx-zfa-medany.c 
b/gcc/testsuite/gcc.target/riscv/xtheadfmemidx-zfa-medany.c
index 4215eab1195..fb1ac2b735c 100644
--- a/gcc/testsuite/gcc.target/riscv/xtheadfmemidx-zfa-medany.c
+++ b/gcc/testsuite/gcc.target/riscv/xtheadfmemidx-zfa-medany.c
@@ -35,5 +35,6 @@ double foo (int i, int j)
   return z;
 }
 
-/* { dg-final { scan-assembler-times {\mth\.flrd\M} 1 } } */
+/* { dg-final { scan-assembler-not {\mth\.flrd\M} } } */
+/* { dg-final { scan-assembler-times {\mlw\M} 2 } } */
 /* { dg-final { scan-assembler-times {\mfmvp\.d\.x\M} 3 } } */

Reply via email to