@@ -4712,11 +4712,22 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
*total = COSTS_N_INSNS (SINGLE_SHIFT_COST);
return true;
}
+ if (riscv_fusion_enabled_p (RISCV_FUSE_BFEXT_SRLI)
+ && outer_code == SET
+ && CONST_INT_P (XEXP (x, 1))
+ && CONST_INT_P (XEXP (x, 2)))
+ {
+ *total = COSTS_N_INSNS (SINGLE_SHIFT_COST);
+ return true;
+ }
gcc_fallthrough ();
case SIGN_EXTRACT:
- if (TARGET_XTHEADBB && outer_code == SET
+ if (outer_code == SET
&& CONST_INT_P (XEXP (x, 1))
- && CONST_INT_P (XEXP (x, 2)))
+ && CONST_INT_P (XEXP (x, 2))
+ && ((GET_CODE (x) == SIGN_EXTRACT
+ && riscv_fusion_enabled_p (RISCV_FUSE_BFEXT_SRAI))
+ || TARGET_XTHEADBB))
{
*total = COSTS_N_INSNS (SINGLE_SHIFT_COST);
return true;
@@ -4792,8 +4792,69 @@
(mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand"))
(sign_extend:SI (match_operand:HI 2 "register_operand")))
(match_operand:SI 3 "register_operand")))]
- "TARGET_XTHEADMAC"
-)
+ "TARGET_XTHEADMAC || (riscv_fusion_enabled_p (RISCV_FUSE_MULT_ADD)
+ && (TARGET_ZMMUL || TARGET_MUL))"
+{
+ if (riscv_fusion_enabled_p (RISCV_FUSE_MULT_ADD)
+ && !TARGET_XTHEADMAC)
+ {
+ rtx tmp0 = gen_reg_rtx (SImode), tmp1 = gen_reg_rtx (SImode);
+ emit_insn (gen_extendhisi2 (tmp0, operands[1]));
+ emit_insn (gen_extendhisi2 (tmp1, operands[2]));
+
+ if (TARGET_64BIT)
+ {
+ rtx op0 = gen_reg_rtx (DImode);
+ emit_insn (gen_madd_fused_extended (op0, tmp0, tmp1, operands[3]));
+ op0 = gen_lowpart (SImode, op0);
+ SUBREG_PROMOTED_VAR_P (op0) = 1;
+ SUBREG_PROMOTED_SET (op0, SRP_SIGNED);
+ emit_move_insn (operands[0], op0);
+ }
+ else
+ {
+ emit_insn (gen_madd_fused (operands[0], tmp0, tmp1, operands[3]));
+ }
+
+ DONE;
+ }
+})
+
+(define_expand "umaddhisi4"
+ [(set (match_operand:SI 0 "register_operand")
+ (plus:SI
+ (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand"))
+ (zero_extend:SI (match_operand:HI 2 "register_operand")))
+ (match_operand:SI 3 "register_operand")))]
+ "riscv_fusion_enabled_p (RISCV_FUSE_MULT_ADD)
+ && (TARGET_ZMMUL || TARGET_MUL)"
+{
+ if (TARGET_64BIT)
+ {
+ rtx tmp0 = gen_reg_rtx (DImode), tmp1 = gen_reg_rtx (DImode);
+ emit_insn (gen_zero_extendhidi2 (tmp0, operands[1]));
+ emit_insn (gen_zero_extendhidi2 (tmp1, operands[2]));
+
+ rtx op0 = gen_reg_rtx (DImode);
+ emit_insn (gen_madd_fused_extended (op0,
+ gen_lowpart (SImode, tmp0),
+ gen_lowpart (SImode, tmp1),
+ operands[3]));
+ op0 = gen_lowpart (SImode, op0);
+ SUBREG_PROMOTED_VAR_P (op0) = 1;
+ SUBREG_PROMOTED_SET (op0, SRP_SIGNED);
+ emit_move_insn (operands[0], op0);
+ }
+ else
+ {
+ rtx tmp0 = gen_reg_rtx (SImode), tmp1 = gen_reg_rtx (SImode);
+ emit_insn (gen_zero_extendhisi2 (tmp0, operands[1]));
+ emit_insn (gen_zero_extendhisi2 (tmp1, operands[2]));
+ emit_insn (gen_madd_fused (operands[0], tmp0, tmp1, operands[3]));
+ }
+
+ DONE;
+})
(define_expand "msubhisi4"
[(set (match_operand:SI 0 "register_operand")
@@ -4804,6 +4865,63 @@
"TARGET_XTHEADMAC"
)
+(define_insn_and_split "madd_fused"
+ [(set (match_operand:SI 0 "register_operand" "=&r")
+ (plus:SI
+ (mult:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r"))
+ (match_operand:SI 3 "register_operand" "r")))]
+ "riscv_fusion_enabled_p (RISCV_FUSE_MULT_ADD)
+ && !TARGET_XTHEADMAC
+ && !TARGET_64BIT && (TARGET_ZMMUL || TARGET_MUL)"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+ "{
+ rtx addend = operands[3];
+ if (can_create_pseudo_p ()
+ && reg_overlap_mentioned_p (operands[0], operands[3]))
+ {
+ addend = gen_reg_rtx (SImode);
+ emit_move_insn (addend, operands[3]);
+ }
+
+ emit_insn (gen_mulsi3 (operands[0], operands[1], operands[2]));
+ emit_insn (gen_addsi3 (operands[0], operands[0], addend));
+ DONE;
+ }"
+ [(set_attr "type" "imul")])
+
+(define_insn_and_split "madd_fused_extended"
+ [(set (match_operand:DI 0 "register_operand" "=&r")
+ (sign_extend:DI
+ (plus:SI
+ (mult:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r"))
+ (match_operand:SI 3 "register_operand" "r"))))]
+ "riscv_fusion_enabled_p (RISCV_FUSE_MULT_ADD)
+ && !TARGET_XTHEADMAC
+ && TARGET_64BIT && (TARGET_ZMMUL || TARGET_MUL)"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+ "{
+ rtx addend = operands[3];
+ if (can_create_pseudo_p ()
+ && reg_overlap_mentioned_p (operands[0], operands[3]))
+ {
+ addend = gen_reg_rtx (SImode);
+ emit_move_insn (addend, operands[3]);
+ }
+
+ emit_insn (gen_mulsi3_extended (operands[0], operands[1], operands[2]));
+ emit_insn (gen_addsi3_extended (operands[0],
+ gen_lowpart (SImode, operands[0]),
+ addend));
+ DONE;
+ }"
+ [(set_attr "type" "imul")])
+
;; String compare with length insn.
;; Argument 0 is the target (result)
;; Argument 1 is the source1
new file mode 100644
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target rv32 } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto" "-O0" "-Oz" "-Os" } } */
+/* { dg-options "-mtune=arc-v-rhx-100-series -march=rv32im_zbs -mabi=ilp32" } */
+
+#define bit_extract(x,start,amt) (((x)>>(start)) & (~(0xffffffff << (amt))))
+
+int
+f (int x)
+{
+ return bit_extract(x,10,14) + bit_extract(x,1,1);
+}
+
+/* { dg-final { scan-assembler {\sslli\s([ast][0-9]+),a0,8\n\ssrli\s([ast][0-9]+),\1,18\n\sbexti\sa0,a0,1.*\n\sadd\sa0,\2,a0.*\n} } } */
new file mode 100644
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mtune=arc-v-rhx-100-series" } */
+
+int
+f (int x)
+{
+ begin:
+ if (x <= 3)
+ goto begin;
+}
+
+/* { dg-final { scan-assembler "\\sli\\sa5,3\n\\sble\\sa0,a5,.L\[0-9\]+\n" } } */
new file mode 100644
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto" "-O0" "-O1" "-O3" "-Oz" "-Os" } } */
+/* { dg-options "-mtune=arc-v-rhx-100-series -march=rv32im -mabi=ilp32" { target { rv32 } } } */
+/* { dg-options "-mtune=arc-v-rhx-100-series -march=rv64im -mabi=lp64" { target { rv64 } } } */
+
+int
+f (int x, short y, short z, short v, short w)
+{
+ return x + (int) y * (int) z + (int) v * (int) w;
+}
+
+/* { dg-final { scan-assembler {\smul\s([ast][0-9]+),a1,a2\n\sadd\s\1,\1,a0\n\smul\sa0,a3,a4\n\sadd\sa0,a0,\1\n} { target rv32 } } } */
+/* { dg-final { scan-assembler {\smulw\sa2,a2,a1\n\saddw\sa2,a2,a0\n\smulw\sa0,a4,a3\n\saddw\sa0,a0,a2\n} { target rv64 } } } */