Pushed r14-19. On Tue, 2023-04-04 at 17:09 +0800, Lulu Cheng wrote: > > 在 2023/4/4 下午4:38, Xi Ruoyao 写道: > > 1. Use addu16i.d for TARGET_64BIT and suitable immediates. > > 2. Split one addition with immediate into two addu16i.d or > > addi.{d/w} > > instructions if possible. This can avoid using a temp register > > w/o > > increase the count of instructions. > > > > Inspired by https://reviews.llvm.org/D143710 and > > https://reviews.llvm.org/D147222. > > > > Stack check CFA tests are updated because this change somehow hides > > PR109035, causing a smaller stack frame. > > > > Bootstrapped and regtested on loongarch64-linux-gnu. Ok for GCC 14? > > I think there is no problem can be integrated into gcc14. > > Thanks! > > > gcc/ChangeLog: > > > > * config/loongarch/loongarch-protos.h > > (loongarch_addu16i_imm12_operand_p): New function prototype. > > (loongarch_split_plus_constant): Likewise. > > * config/loongarch/loongarch.cc > > (loongarch_addu16i_imm12_operand_p): New function. > > (loongarch_split_plus_constant): Likewise. > > * config/loongarch/loongarch.h (ADDU16I_OPERAND): New macro. > > (DUAL_IMM12_OPERAND): Likewise. > > (DUAL_ADDU16I_OPERAND): Likewise. > > * config/loongarch/constraints.md (La, Lb, Lc, Ld, Le): New > > constraint. > > * config/loongarch/predicates.md (const_dual_imm12_operand): > > New > > predicate. > > (const_addu16i_operand): Likewise. > > (const_addu16i_imm12_di_operand): Likewise. > > (const_addu16i_imm12_si_operand): Likewise. > > (plus_di_operand): Likewise. > > (plus_si_operand): Likewise. > > (plus_si_extend_operand): Likewise. > > * config/loongarch/loongarch.md (add<mode>3): Convert to > > define_insn_and_split. Use plus_<mode>_operand predicate > > instead of arith_operand. Add alternatives for La, Lb, Lc, > > Ld, > > and Le constraints. > > (*addsi3_extended): Convert to define_insn_and_split. Use > > plus_si_extend_operand instead of arith_operand. Add > > alternatives for La and Le alternatives. > > > > gcc/testsuite/ChangeLog: > > > > * gcc.target/loongarch/add-const.c: New test. > > * gcc.target/loongarch/stack-check-cfa-1.c: Adjust for stack > > frame size change. > > * gcc.target/loongarch/stack-check-cfa-2.c: Likewise. > > --- > > gcc/config/loongarch/constraints.md | 46 ++++++++++++- > > gcc/config/loongarch/loongarch-protos.h | 2 + > > gcc/config/loongarch/loongarch.cc | 44 +++++++++++++ > > gcc/config/loongarch/loongarch.h | 19 ++++++ > > gcc/config/loongarch/loongarch.md | 66 > > +++++++++++++++---- > > gcc/config/loongarch/predicates.md | 36 ++++++++++ > > .../gcc.target/loongarch/add-const.c | 45 +++++++++++++ > > .../gcc.target/loongarch/stack-check-cfa-1.c | 2 +- > > .../gcc.target/loongarch/stack-check-cfa-2.c | 2 +- > > 9 files changed, 246 insertions(+), 16 deletions(-) > > create mode 100644 gcc/testsuite/gcc.target/loongarch/add-const.c > > > > diff --git a/gcc/config/loongarch/constraints.md > > b/gcc/config/loongarch/constraints.md > > index cb7fa688ceb..7a38cd07ae9 100644 > > --- a/gcc/config/loongarch/constraints.md > > +++ b/gcc/config/loongarch/constraints.md > > @@ -60,7 +60,22 @@ > > ;; "I" "A signed 12-bit constant (for arithmetic instructions)." > > ;; "J" "Integer zero." > > ;; "K" "An unsigned 12-bit constant (for logic instructions)." > > -;; "L" <-----unused > > +;; "L" - > > +;; "La" > > +;; "A signed constant in [-4096, 2048) or (2047, 4094]." > > +;; "Lb" > > +;; "A signed 32-bit constant and low 16-bit is zero, which can > > be > > +;; added onto a register with addu16i.d. It matches nothing > > if > > +;; the addu16i.d instruction is not available." > > +;; "Lc" > > +;; "A signed 64-bit constant can be expressed as Lb + I, but > > not a > > +;; single Lb or I." > > +;; "Ld" > > +;; "A signed 64-bit constant can be expressed as Lb + Lb, but > > not a > > +;; single Lb." > > +;; "Le" > > +;; "A signed 32-bit constant can be expressed as Lb + I, but > > not a > > +;; single Lb or I." > > ;; "M" <-----unused > > ;; "N" <-----unused > > ;; "O" <-----unused > > @@ -170,6 +185,35 @@ (define_constraint "K" > > (and (match_code "const_int") > > (match_test "IMM12_OPERAND_UNSIGNED (ival)"))) > > > > +(define_constraint "La" > > + "A signed constant in [-4096, 2048) or (2047, 4094]." > > + (and (match_code "const_int") > > + (match_test "DUAL_IMM12_OPERAND (ival)"))) > > + > > +(define_constraint "Lb" > > + "A signed 32-bit constant and low 16-bit is zero, which can be > > added > > + onto a register with addu16i.d." > > + (and (match_code "const_int") > > + (match_test "ADDU16I_OPERAND (ival)"))) > > + > > +(define_constraint "Lc" > > + "A signed 64-bit constant can be expressed as Lb + I, but not a > > single Lb > > + or I." > > + (and (match_code "const_int") > > + (match_test "loongarch_addu16i_imm12_operand_p (ival, > > DImode)"))) > > + > > +(define_constraint "Ld" > > + "A signed 64-bit constant can be expressed as Lb + Lb, but not a > > single > > + Lb." > > + (and (match_code "const_int") > > + (match_test "DUAL_ADDU16I_OPERAND (ival)"))) > > + > > +(define_constraint "Le" > > + "A signed 32-bit constant can be expressed as Lb + I, but not a > > single Lb > > + or I." > > + (and (match_code "const_int") > > + (match_test "loongarch_addu16i_imm12_operand_p (ival, > > SImode)"))) > > + > > (define_constraint "Yd" > > "@internal > > A constant @code{move_operand} that can be safely loaded using > > diff --git a/gcc/config/loongarch/loongarch-protos.h > > b/gcc/config/loongarch/loongarch-protos.h > > index 35cc77c7367..83df489c7a5 100644 > > --- a/gcc/config/loongarch/loongarch-protos.h > > +++ b/gcc/config/loongarch/loongarch-protos.h > > @@ -83,6 +83,8 @@ extern rtx loongarch_legitimize_call_address > > (rtx); > > extern rtx loongarch_subword (rtx, bool); > > extern bool loongarch_split_move_p (rtx, rtx); > > extern void loongarch_split_move (rtx, rtx, rtx); > > +extern bool loongarch_addu16i_imm12_operand_p (HOST_WIDE_INT, > > machine_mode); > > +extern void loongarch_split_plus_constant (rtx *, machine_mode); > > extern const char *loongarch_output_move (rtx, rtx); > > extern bool loongarch_cfun_has_cprestore_slot_p (void); > > #ifdef RTX_CODE > > diff --git a/gcc/config/loongarch/loongarch.cc > > b/gcc/config/loongarch/loongarch.cc > > index 0ecb91ca997..dfb731fca9d 100644 > > --- a/gcc/config/loongarch/loongarch.cc > > +++ b/gcc/config/loongarch/loongarch.cc > > @@ -3756,6 +3756,50 @@ loongarch_split_move (rtx dest, rtx src, rtx > > insn_) > > } > > } > > > > +/* Check if adding an integer constant value for a specific mode > > can be > > + performed with an addu16i.d instruction and an addi.{w/d} > > + instruction. */ > > + > > +bool > > +loongarch_addu16i_imm12_operand_p (HOST_WIDE_INT value, > > machine_mode mode) > > +{ > > + /* Not necessary, but avoid unnecessary calculation if > > !TARGET_64BIT. */ > > + if (!TARGET_64BIT) > > + return false; > > + > > + if ((value & 0xffff) == 0) > > + return false; > > + > > + if (IMM12_OPERAND (value)) > > + return false; > > + > > + value = (value & ~HWIT_UC_0xFFF) + ((value & 0x800) << 1); > > + return ADDU16I_OPERAND (trunc_int_for_mode (value, mode)); > > +} > > + > > +/* Split one integer constant op[0] into two (op[1] and op[2]) for > > constant > > + plus operation in a specific mode. The splitted constants can > > be added > > + onto a register with a single instruction (addi.{d/w} or > > addu16i.d). */ > > + > > +void > > +loongarch_split_plus_constant (rtx *op, machine_mode mode) > > +{ > > + HOST_WIDE_INT v = INTVAL (op[0]), a; > > + > > + if (DUAL_IMM12_OPERAND (v)) > > + a = (v > 0 ? 2047 : -2048); > > + else if (loongarch_addu16i_imm12_operand_p (v, mode)) > > + a = (v & ~HWIT_UC_0xFFF) + ((v & 0x800) << 1); > > + else if (mode == DImode && DUAL_ADDU16I_OPERAND (v)) > > + a = (v > 0 ? 0x7fff : -0x8000) << 16; > > + else > > + gcc_unreachable (); > > + > > + op[1] = gen_int_mode (a, mode); > > + v = v - (unsigned HOST_WIDE_INT) a; > > + op[2] = gen_int_mode (v, mode); > > +} > > + > > /* Return true if a move from SRC to DEST in INSN should be > > split. */ > > > > static bool > > diff --git a/gcc/config/loongarch/loongarch.h > > b/gcc/config/loongarch/loongarch.h > > index f8167875646..7151d5cabb3 100644 > > --- a/gcc/config/loongarch/loongarch.h > > +++ b/gcc/config/loongarch/loongarch.h > > @@ -612,6 +612,25 @@ enum reg_class > > > > #define CONST_LOW_PART(VALUE) ((VALUE) - CONST_HIGH_PART (VALUE)) > > > > +/* True if VALUE can be added onto a register with one addu16i.d > > + instruction. */ > > + > > +#define ADDU16I_OPERAND(VALUE) \ > > + (TARGET_64BIT && (((VALUE) & 0xffff) == 0 \ > > + && IMM16_OPERAND ((HOST_WIDE_INT) (VALUE) / 65536))) > > + > > +/* True if VALUE can be added onto a register with two addi.{d/w} > > + instructions, but not one addi.{d/w} instruction. */ > > +#define DUAL_IMM12_OPERAND(VALUE) \ > > + (IN_RANGE ((VALUE), -4096, 4094) && !IMM12_OPERAND (VALUE)) > > + > > +/* True if VALUE can be added onto a register with two addu16i.d > > + instruction, but not one addu16i.d instruction. */ > > +#define DUAL_ADDU16I_OPERAND(VALUE) \ > > + (TARGET_64BIT && (((VALUE) & 0xffff) == 0 \ > > + && !ADDU16I_OPERAND (VALUE) \ > > + && IN_RANGE ((VALUE) / 65536, -0x10000, 0xfffe))) > > + > > #define IMM12_INT(X) IMM12_OPERAND (INTVAL (X)) > > #define IMM12_INT_UNSIGNED(X) IMM12_OPERAND_UNSIGNED (INTVAL (X)) > > #define LU12I_INT(X) LU12I_OPERAND (INTVAL (X)) > > diff --git a/gcc/config/loongarch/loongarch.md > > b/gcc/config/loongarch/loongarch.md > > index 3509c3c21c1..628ecc78088 100644 > > --- a/gcc/config/loongarch/loongarch.md > > +++ b/gcc/config/loongarch/loongarch.md > > @@ -598,24 +598,64 @@ (define_insn "add<mode>3" > > [(set_attr "type" "fadd") > > (set_attr "mode" "<UNITMODE>")]) > > > > -(define_insn "add<mode>3" > > - [(set (match_operand:GPR 0 "register_operand" "=r,r") > > - (plus:GPR (match_operand:GPR 1 "register_operand" "r,r") > > - (match_operand:GPR 2 "arith_operand" "r,I")))] > > +(define_insn_and_split "add<mode>3" > > + [(set (match_operand:GPR 0 "register_operand" "=r,r,r,r,r,r,r") > > + (plus:GPR (match_operand:GPR 1 "register_operand" > > "r,r,r,r,r,r,r") > > + (match_operand:GPR 2 "plus_<mode>_operand" > > + "r,I,La,Lb,Lc,Ld,Le")))] > > "" > > - "add%i2.<d>\t%0,%1,%2"; > > + "@ > > + add.<d>\t%0,%1,%2 > > + addi.<d>\t%0,%1,%2 > > + # > > + * operands[2] = GEN_INT (INTVAL (operands[2]) / 65536); \ > > + return \"addu16i.d\t%0,%1,%2\"; > > + # > > + # > > + #" > > + "CONST_INT_P (operands[2]) && !IMM12_INT (operands[2]) \ > > + && !ADDU16I_OPERAND (INTVAL (operands[2]))" > > + [(set (match_dup 0) (plus:GPR (match_dup 1) (match_dup 3))) > > + (set (match_dup 0) (plus:GPR (match_dup 0) (match_dup 4)))] > > + { > > + loongarch_split_plus_constant (&operands[2], <MODE>mode); > > + } > > [(set_attr "alu_type" "add") > > - (set_attr "mode" "<MODE>")]) > > - > > -(define_insn "*addsi3_extended" > > - [(set (match_operand:DI 0 "register_operand" "=r,r") > > + (set_attr "mode" "<MODE>") > > + (set_attr "insn_count" "1,1,2,1,2,2,2") > > + (set (attr "enabled") > > + (cond > > + [(match_test "<MODE>mode != DImode && which_alternative == > > 4") > > + (const_string "no") > > + (match_test "<MODE>mode != DImode && which_alternative == > > 5") > > + (const_string "no") > > + (match_test "<MODE>mode != SImode && which_alternative == > > 6") > > + (const_string "no")] > > + (const_string "yes")))]) > > + > > +(define_insn_and_split "*addsi3_extended" > > + [(set (match_operand:DI 0 "register_operand" "=r,r,r,r") > > (sign_extend:DI > > - (plus:SI (match_operand:SI 1 "register_operand" "r,r") > > - (match_operand:SI 2 "arith_operand" "r,I"))))] > > + (plus:SI (match_operand:SI 1 "register_operand" > > "r,r,r,r") > > + (match_operand:SI 2 "plus_si_extend_operand" > > + "r,I,La,Le"))))] > > "TARGET_64BIT" > > - "add%i2.w\t%0,%1,%2" > > + "@ > > + add.w\t%0,%1,%2 > > + addi.w\t%0,%1,%2 > > + # > > + #" > > + "CONST_INT_P (operands[2]) && !IMM12_INT (operands[2])" > > + [(set (subreg:SI (match_dup 0) 0) (plus:SI (match_dup 1) > > (match_dup 3))) > > + (set (match_dup 0) > > + (sign_extend:DI (plus:SI (subreg:SI (match_dup 0) 0) > > + (match_dup 4))))] > > + { > > + loongarch_split_plus_constant (&operands[2], SImode); > > + } > > [(set_attr "alu_type" "add") > > - (set_attr "mode" "SI")]) > > + (set_attr "mode" "SI") > > + (set_attr "insn_count" "1,1,2,2")]) > > > > > > ;; > > diff --git a/gcc/config/loongarch/predicates.md > > b/gcc/config/loongarch/predicates.md > > index 95140280f1e..510973aa339 100644 > > --- a/gcc/config/loongarch/predicates.md > > +++ b/gcc/config/loongarch/predicates.md > > @@ -39,14 +39,50 @@ (define_predicate "const_arith_operand" > > (and (match_code "const_int") > > (match_test "IMM12_OPERAND (INTVAL (op))"))) > > > > +(define_predicate "const_dual_imm12_operand" > > + (and (match_code "const_int") > > + (match_test "DUAL_IMM12_OPERAND (INTVAL (op))"))) > > + > > (define_predicate "const_imm16_operand" > > (and (match_code "const_int") > > (match_test "IMM16_OPERAND (INTVAL (op))"))) > > > > +(define_predicate "const_addu16i_operand" > > + (and (match_code "const_int") > > + (match_test "ADDU16I_OPERAND (INTVAL (op))"))) > > + > > +(define_predicate "const_addu16i_imm12_di_operand" > > + (and (match_code "const_int") > > + (match_test "loongarch_addu16i_imm12_operand_p (INTVAL (op), > > DImode)"))) > > + > > +(define_predicate "const_addu16i_imm12_si_operand" > > + (and (match_code "const_int") > > + (match_test "loongarch_addu16i_imm12_operand_p (INTVAL (op), > > SImode)"))) > > + > > +(define_predicate "const_dual_addu16i_operand" > > + (and (match_code "const_int") > > + (match_test "DUAL_ADDU16I_OPERAND (INTVAL (op))"))) > > + > > (define_predicate "arith_operand" > > (ior (match_operand 0 "const_arith_operand") > > (match_operand 0 "register_operand"))) > > > > +(define_predicate "plus_di_operand" > > + (ior (match_operand 0 "arith_operand") > > + (match_operand 0 "const_dual_imm12_operand") > > + (match_operand 0 "const_addu16i_operand") > > + (match_operand 0 "const_addu16i_imm12_di_operand") > > + (match_operand 0 "const_dual_addu16i_operand"))) > > + > > +(define_predicate "plus_si_extend_operand" > > + (ior (match_operand 0 "arith_operand") > > + (match_operand 0 "const_dual_imm12_operand") > > + (match_operand 0 "const_addu16i_imm12_si_operand"))) > > + > > +(define_predicate "plus_si_operand" > > + (ior (match_operand 0 "plus_si_extend_operand") > > + (match_operand 0 "const_addu16i_operand"))) > > + > > (define_predicate "const_immalsl_operand" > > (and (match_code "const_int") > > (match_test "IN_RANGE (INTVAL (op), 1, 4)"))) > > diff --git a/gcc/testsuite/gcc.target/loongarch/add-const.c > > b/gcc/testsuite/gcc.target/loongarch/add-const.c > > new file mode 100644 > > index 00000000000..7b6a7cb92aa > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/loongarch/add-const.c > > @@ -0,0 +1,45 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O -mabi=lp64d" } */ > > + > > +/* None of these functions should load the const operand into a > > temp > > + register. */ > > + > > +/* { dg-final { scan-assembler-not "add\\.[dw]" } } */ > > + > > +unsigned long f01 (unsigned long x) { return x + 1; } > > +unsigned long f02 (unsigned long x) { return x - 1; } > > +unsigned long f03 (unsigned long x) { return x + 2047; } > > +unsigned long f04 (unsigned long x) { return x + 4094; } > > +unsigned long f05 (unsigned long x) { return x - 2048; } > > +unsigned long f06 (unsigned long x) { return x - 4096; } > > +unsigned long f07 (unsigned long x) { return x + 0x7fff0000; } > > +unsigned long f08 (unsigned long x) { return x - 0x80000000l; } > > +unsigned long f09 (unsigned long x) { return x + 0x7fff0000l * 2; } > > +unsigned long f10 (unsigned long x) { return x - 0x80000000l * 2; } > > +unsigned long f11 (unsigned long x) { return x + 0x7fff0000 + 0x1; > > } > > +unsigned long f12 (unsigned long x) { return x + 0x7fff0000 - 0x1; > > } > > +unsigned long f13 (unsigned long x) { return x + 0x7fff0000 + > > 0x7ff; } > > +unsigned long f14 (unsigned long x) { return x + 0x7fff0000 - > > 0x800; } > > +unsigned long f15 (unsigned long x) { return x - 0x80000000l - 1; } > > +unsigned long f16 (unsigned long x) { return x - 0x80000000l + 1; } > > +unsigned long f17 (unsigned long x) { return x - 0x80000000l - > > 0x800; } > > +unsigned long f18 (unsigned long x) { return x - 0x80000000l + > > 0x7ff; } > > + > > +unsigned int g01 (unsigned int x) { return x + 1; } > > +unsigned int g02 (unsigned int x) { return x - 1; } > > +unsigned int g03 (unsigned int x) { return x + 2047; } > > +unsigned int g04 (unsigned int x) { return x + 4094; } > > +unsigned int g05 (unsigned int x) { return x - 2048; } > > +unsigned int g06 (unsigned int x) { return x - 4096; } > > +unsigned int g07 (unsigned int x) { return x + 0x7fff0000; } > > +unsigned int g08 (unsigned int x) { return x - 0x80000000l; } > > +unsigned int g09 (unsigned int x) { return x + 0x7fff0000l * 2; } > > +unsigned int g10 (unsigned int x) { return x - 0x80000000l * 2; } > > +unsigned int g11 (unsigned int x) { return x + 0x7fff0000 + 0x1; } > > +unsigned int g12 (unsigned int x) { return x + 0x7fff0000 - 0x1; } > > +unsigned int g13 (unsigned int x) { return x + 0x7fff0000 + 0x7ff; > > } > > +unsigned int g14 (unsigned int x) { return x + 0x7fff0000 - 0x800; > > } > > +unsigned int g15 (unsigned int x) { return x - 0x80000000l - 1; } > > +unsigned int g16 (unsigned int x) { return x - 0x80000000l + 1; } > > +unsigned int g17 (unsigned int x) { return x - 0x80000000l - 0x800; > > } > > +unsigned int g18 (unsigned int x) { return x - 0x80000000l + 0x7ff; > > } > > diff --git a/gcc/testsuite/gcc.target/loongarch/stack-check-cfa-1.c > > b/gcc/testsuite/gcc.target/loongarch/stack-check-cfa-1.c > > index 3533fe7b685..cd72154f46c 100644 > > --- a/gcc/testsuite/gcc.target/loongarch/stack-check-cfa-1.c > > +++ b/gcc/testsuite/gcc.target/loongarch/stack-check-cfa-1.c > > @@ -6,7 +6,7 @@ > > #define SIZE 128*1024 > > #include "stack-check-prologue.h" > > > > -/* { dg-final { scan-assembler-times {\.cfi_def_cfa_offset 131088} > > 1 } } */ > > +/* { dg-final { scan-assembler-times {\.cfi_def_cfa_offset 131072} > > 1 } } */ > > /* { dg-final { scan-assembler-times {\.cfi_def_cfa_offset 0} 1 } > > } */ > > > > /* Checks that the CFA notes are correct for every sp adjustment. > > */ > > diff --git a/gcc/testsuite/gcc.target/loongarch/stack-check-cfa-2.c > > b/gcc/testsuite/gcc.target/loongarch/stack-check-cfa-2.c > > index e5e711105ac..3e5ca05b2da 100644 > > --- a/gcc/testsuite/gcc.target/loongarch/stack-check-cfa-2.c > > +++ b/gcc/testsuite/gcc.target/loongarch/stack-check-cfa-2.c > > @@ -6,7 +6,7 @@ > > #define SIZE 1280*1024 + 512 > > #include "stack-check-prologue.h" > > > > -/* { dg-final { scan-assembler-times {\.cfi_def_cfa_offset 1311248} > > 1 } } */ > > +/* { dg-final { scan-assembler-times {\.cfi_def_cfa_offset 1311232} > > 1 } } */ > > /* { dg-final { scan-assembler-times {\.cfi_def_cfa_offset 0} 1 } > > } */ > > > > /* Checks that the CFA notes are correct for every sp adjustment. > > */ >
-- Xi Ruoyao <xry...@xry111.site> School of Aerospace Science and Technology, Xidian University