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;
}
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);
[(set_attr "type" "fadd")
(set_attr "mode" "<UNITMODE>")])
+(define_expand "addptr<mode>3"
+ [(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")
[(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 "*add<mode>3_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" "<P:MODE>")])
-
(define_expand "addv<mode>4"
[(set (match_operand:GPR 0 "register_operand" "=r,r")
(plus:GPR (match_operand:GPR 1 "register_operand" " r,r")