diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 889c08c09e8..d5de76c342e 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -15440,9 +15440,13 @@ synthesize_add (rtx operands[3]) ival -= saturated; - rtx x = gen_rtx_PLUS (word_mode, operands[1], GEN_INT (saturated)); + /* The first add may be an FP relative address during reload. FP + may be replaced with (sp + C). We don't want that to already + be saturated as (sp + C) would then exceed a simm12 field. So + emit the smaller offset first and the saturated constant last. */ + rtx x = gen_rtx_PLUS (word_mode, operands[1], GEN_INT (ival)); emit_insn (gen_rtx_SET (operands[0], x)); - rtx output = gen_rtx_PLUS (word_mode, operands[0], GEN_INT (ival)); + rtx output = gen_rtx_PLUS (word_mode, operands[0], GEN_INT (saturated)); emit_insn (gen_rtx_SET (operands[0], output)); return true; } @@ -15539,14 +15543,18 @@ synthesize_add_extended (rtx operands[3]) ival -= saturated; + /* The first add may be an FP relative address during reload. FP + may be replaced with (sp + C). We don't want that to already + be saturated as (sp + C) would then exceed a simm12 field. So + emit the smaller offset first and the saturated constant last. */ rtx temp = gen_reg_rtx (DImode); - emit_insn (gen_addsi3_extended (temp, operands[1], GEN_INT (saturated))); + emit_insn (gen_addsi3_extended (temp, operands[1], GEN_INT (ival))); temp = gen_lowpart (SImode, temp); SUBREG_PROMOTED_VAR_P (temp) = 1; SUBREG_PROMOTED_SET (temp, SRP_SIGNED); emit_insn (gen_rtx_SET (operands[0], temp)); rtx t = gen_reg_rtx (DImode); - emit_insn (gen_addsi3_extended (t, operands[0], GEN_INT (ival))); + emit_insn (gen_addsi3_extended (t, operands[0], GEN_INT (saturated))); t = gen_lowpart (SImode, t); SUBREG_PROMOTED_VAR_P (t) = 1; SUBREG_PROMOTED_SET (t, SRP_SIGNED); diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 78a01ef30c7..640ca5f9b0e 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -702,6 +702,22 @@ [(set_attr "type" "fadd") (set_attr "mode" "")]) +(define_expand "addptr3" + [(set (match_operand:X 0 "register_operand") + (plus:X (match_operand:X 1 "register_operand") + (match_operand 2 "const_int_operand")))] + "" +{ + gcc_assert (CONST_INT_P (operands[2])); + bool status = synthesize_add (operands); + + if (!SMALL_OPERAND (INTVAL (operands[2]))) + { + gcc_assert (status); + DONE; + } +}) + (define_insn "*addsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") (plus:SI (match_operand:SI 1 "register_operand" " r,r") @@ -759,46 +775,6 @@ [(set_attr "type" "arith") (set_attr "mode" "DI")]) -;; Special case of adding a reg and constant if latter is sum of two S12 -;; values (in range -2048 to 2047). Avoid materialized the const and fuse -;; into the add (with an additional add for 2nd value). Makes a 3 insn -;; sequence into 2 insn. - -(define_insn_and_split "*add3_const_sum_of_two_s12" - [(set (match_operand:P 0 "register_operand" "=r,r") - (plus:P (match_operand:P 1 "register_operand" " r,r") - (match_operand:P 2 "const_two_s12" " MiG,r")))] - "!riscv_reg_frame_related (operands[0])" -{ - /* operand matching MiG constraint is always meant to be split. */ - if (which_alternative == 0) - return "#"; - else - return "add %0,%1,%2"; -} - "" - [(set (match_dup 0) - (plus:P (match_dup 1) (match_dup 3))) - (set (match_dup 0) - (plus:P (match_dup 0) (match_dup 4)))] -{ - int val = INTVAL (operands[2]); - if (SUM_OF_TWO_S12_P (val)) - { - operands[3] = GEN_INT (2047); - operands[4] = GEN_INT (val - 2047); - } - else if (SUM_OF_TWO_S12_N (val)) - { - operands[3] = GEN_INT (-2048); - operands[4] = GEN_INT (val + 2048); - } - else - gcc_unreachable (); -} - [(set_attr "type" "arith") - (set_attr "mode" "")]) - (define_expand "addv4" [(set (match_operand:GPR 0 "register_operand" "=r,r") (plus:GPR (match_operand:GPR 1 "register_operand" " r,r") diff --git a/gcc/testsuite/gcc.target/riscv/add-synthesis-1.c b/gcc/testsuite/gcc.target/riscv/add-synthesis-1.c index 247096cec00..982b2fa7f2b 100644 --- a/gcc/testsuite/gcc.target/riscv/add-synthesis-1.c +++ b/gcc/testsuite/gcc.target/riscv/add-synthesis-1.c @@ -25,7 +25,7 @@ T (4100) T (8200) TM (2049) -TM (4096) +TM (4094) TM (4100) TM (8200) diff --git a/gcc/testsuite/gcc.target/riscv/pr120811.c b/gcc/testsuite/gcc.target/riscv/pr120811.c index c28e5ec4cc3..b8a7347d3c9 100644 --- a/gcc/testsuite/gcc.target/riscv/pr120811.c +++ b/gcc/testsuite/gcc.target/riscv/pr120811.c @@ -38,5 +38,4 @@ void q() { } /* { dg-final { scan-rtl-dump-not "const_sum_of_two_s12" "reload" } } */ /* { dg-final { scan-rtl-dump-not "const_sum_of_two_s12" "late_combine2" } } */ -/* { dg-final { scan-assembler "addi.*sp,2047\n\tl\[dw\]\t.*,1\(.*\).*" } } */ - +/* { dg-final { scan-assembler "addi.*\[ats\]\[0-9\]*,sp,\[0-9\]*\n\tld\t.*,2047\(.*\).*" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sum-of-two-s12-const-1.c b/gcc/testsuite/gcc.target/riscv/sum-of-two-s12-const-1.c index 4d6d135de5f..ac17ec271be 100644 --- a/gcc/testsuite/gcc.target/riscv/sum-of-two-s12-const-1.c +++ b/gcc/testsuite/gcc.target/riscv/sum-of-two-s12-const-1.c @@ -26,7 +26,7 @@ plus3(unsigned long i) long minus1(unsigned long i) { - return i - 4096; + return i - 4094; } long