LoongArch: Fixed the problem of incorrect judgment of the immediate field of the [x]vld/[x]vst instruction.
The [x]vld/[x]vst directive is defined as follows: [x]vld/[x]vst {x/v}d, rj, si12 When not modified, the immediate field of [x]vld/[x]vst is between 10 and 14 bits depending on the type. However, in loongarch_valid_offset_p, the immediate field is restricted first, so there is no error. However, in some cases redundant instructions will be generated, see test cases. Now modify it according to the description in the instruction manual. gcc/ChangeLog: * config/loongarch/lasx.md (lasx_mxld_<lasxfmt_f>): Modify the method of determining the memory offset of [x]vld/[x]vst. (lasx_mxst_<lasxfmt_f>): Likewise. * config/loongarch/loongarch.cc (loongarch_valid_offset_p): Delete. (loongarch_address_insns): Likewise. * config/loongarch/lsx.md (lsx_ld_<lsxfmt_f>): Likewise. (lsx_st_<lsxfmt_f>): Likewise. * config/loongarch/predicates.md (aq10b_operand): Likewise. (aq10h_operand): Likewise. (aq10w_operand): Likewise. (aq10d_operand): Likewise. gcc/testsuite/ChangeLog: * gcc.target/loongarch/vect-ld-st-imm12.c: New test.
This commit is contained in:
parent
f8e4412b04
commit
03c7df97e7
5 changed files with 19 additions and 83 deletions
|
@ -846,32 +846,6 @@
|
|||
DONE;
|
||||
})
|
||||
|
||||
;; Offset load
|
||||
(define_expand "lasx_mxld_<lasxfmt_f>"
|
||||
[(match_operand:LASX 0 "register_operand")
|
||||
(match_operand 1 "pmode_register_operand")
|
||||
(match_operand 2 "aq10<lasxfmt>_operand")]
|
||||
"ISA_HAS_LASX"
|
||||
{
|
||||
rtx addr = plus_constant (GET_MODE (operands[1]), operands[1],
|
||||
INTVAL (operands[2]));
|
||||
loongarch_emit_move (operands[0], gen_rtx_MEM (<MODE>mode, addr));
|
||||
DONE;
|
||||
})
|
||||
|
||||
;; Offset store
|
||||
(define_expand "lasx_mxst_<lasxfmt_f>"
|
||||
[(match_operand:LASX 0 "register_operand")
|
||||
(match_operand 1 "pmode_register_operand")
|
||||
(match_operand 2 "aq10<lasxfmt>_operand")]
|
||||
"ISA_HAS_LASX"
|
||||
{
|
||||
rtx addr = plus_constant (GET_MODE (operands[1]), operands[1],
|
||||
INTVAL (operands[2]));
|
||||
loongarch_emit_move (gen_rtx_MEM (<MODE>mode, addr), operands[0]);
|
||||
DONE;
|
||||
})
|
||||
|
||||
;; LASX
|
||||
(define_insn "add<mode>3"
|
||||
[(set (match_operand:ILASX 0 "register_operand" "=f,f,f")
|
||||
|
|
|
@ -2126,21 +2126,11 @@ loongarch_valid_offset_p (rtx x, machine_mode mode)
|
|||
|
||||
/* We may need to split multiword moves, so make sure that every word
|
||||
is accessible. */
|
||||
if (GET_MODE_SIZE (mode) > UNITS_PER_WORD
|
||||
if (!(LSX_SUPPORTED_MODE_P (mode) || LASX_SUPPORTED_MODE_P (mode))
|
||||
&& GET_MODE_SIZE (mode) > UNITS_PER_WORD
|
||||
&& !IMM12_OPERAND (INTVAL (x) + GET_MODE_SIZE (mode) - UNITS_PER_WORD))
|
||||
return false;
|
||||
|
||||
/* LSX LD.* and ST.* supports 10-bit signed offsets. */
|
||||
if (LSX_SUPPORTED_MODE_P (mode)
|
||||
&& !loongarch_signed_immediate_p (INTVAL (x), 10,
|
||||
loongarch_ldst_scaled_shift (mode)))
|
||||
return false;
|
||||
|
||||
/* LASX XVLD.B and XVST.B supports 10-bit signed offsets without shift. */
|
||||
if (LASX_SUPPORTED_MODE_P (mode)
|
||||
&& !loongarch_signed_immediate_p (INTVAL (x), 10, 0))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2376,9 +2366,8 @@ loongarch_address_insns (rtx x, machine_mode mode, bool might_split_p)
|
|||
case ADDRESS_REG:
|
||||
if (lsx_p)
|
||||
{
|
||||
/* LSX LD.* and ST.* supports 10-bit signed offsets. */
|
||||
if (loongarch_signed_immediate_p (INTVAL (addr.offset), 10,
|
||||
loongarch_ldst_scaled_shift (mode)))
|
||||
/* LSX LD.* and ST.* supports 12-bit signed offsets. */
|
||||
if (IMM12_OPERAND (INTVAL (addr.offset)))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
|
|
|
@ -812,32 +812,6 @@
|
|||
DONE;
|
||||
})
|
||||
|
||||
;; Offset load
|
||||
(define_expand "lsx_ld_<lsxfmt_f>"
|
||||
[(match_operand:LSX 0 "register_operand")
|
||||
(match_operand 1 "pmode_register_operand")
|
||||
(match_operand 2 "aq10<lsxfmt>_operand")]
|
||||
"ISA_HAS_LSX"
|
||||
{
|
||||
rtx addr = plus_constant (GET_MODE (operands[1]), operands[1],
|
||||
INTVAL (operands[2]));
|
||||
loongarch_emit_move (operands[0], gen_rtx_MEM (<MODE>mode, addr));
|
||||
DONE;
|
||||
})
|
||||
|
||||
;; Offset store
|
||||
(define_expand "lsx_st_<lsxfmt_f>"
|
||||
[(match_operand:LSX 0 "register_operand")
|
||||
(match_operand 1 "pmode_register_operand")
|
||||
(match_operand 2 "aq10<lsxfmt>_operand")]
|
||||
"ISA_HAS_LSX"
|
||||
{
|
||||
rtx addr = plus_constant (GET_MODE (operands[1]), operands[1],
|
||||
INTVAL (operands[2]));
|
||||
loongarch_emit_move (gen_rtx_MEM (<MODE>mode, addr), operands[0]);
|
||||
DONE;
|
||||
})
|
||||
|
||||
;; Integer operations
|
||||
(define_insn "add<mode>3"
|
||||
[(set (match_operand:ILSX 0 "register_operand" "=f,f,f")
|
||||
|
|
|
@ -167,22 +167,6 @@
|
|||
(and (match_code "const_int")
|
||||
(match_test "loongarch_signed_immediate_p (INTVAL (op), 8, 3)")))
|
||||
|
||||
(define_predicate "aq10b_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "loongarch_signed_immediate_p (INTVAL (op), 10, 0)")))
|
||||
|
||||
(define_predicate "aq10h_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "loongarch_signed_immediate_p (INTVAL (op), 10, 1)")))
|
||||
|
||||
(define_predicate "aq10w_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "loongarch_signed_immediate_p (INTVAL (op), 10, 2)")))
|
||||
|
||||
(define_predicate "aq10d_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "loongarch_signed_immediate_p (INTVAL (op), 10, 3)")))
|
||||
|
||||
(define_predicate "aq12b_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "loongarch_signed_immediate_p (INTVAL (op), 12, 0)")))
|
||||
|
|
15
gcc/testsuite/gcc.target/loongarch/vect-ld-st-imm12.c
Normal file
15
gcc/testsuite/gcc.target/loongarch/vect-ld-st-imm12.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-march=loongarch64 -mabi=lp64d -mlasx -O2" } */
|
||||
/* { dg-final { scan-assembler-not "addi.d" } } */
|
||||
|
||||
extern short a[1000];
|
||||
extern short b[1000];
|
||||
extern short c[1000];
|
||||
|
||||
void
|
||||
test (void)
|
||||
{
|
||||
for (int i = 501; i < 517; i++)
|
||||
((int *)(c + 1))[i] = ((int *)(a + 1))[i] + ((int *)(b + 1))[i];
|
||||
}
|
||||
|
Loading…
Add table
Reference in a new issue