diff --git a/gcc/config/riscv/riscv-cores.def b/gcc/config/riscv/riscv-cores.def
index a07a79e2cb76809d58e68111d931105278c91a89..0785e8f3fbdeab69e377ca770b0c3dc3214ca521 100644
--- a/gcc/config/riscv/riscv-cores.def
+++ b/gcc/config/riscv/riscv-cores.def
@@ -37,6 +37,7 @@ RISCV_TUNE("rocket", generic, rocket_tune_info)
 RISCV_TUNE("sifive-3-series", generic, rocket_tune_info)
 RISCV_TUNE("sifive-5-series", generic, rocket_tune_info)
 RISCV_TUNE("sifive-7-series", sifive_7, sifive_7_tune_info)
+RISCV_TUNE("sifive-p400-series", sifive_p400, sifive_p400_tune_info)
 RISCV_TUNE("sifive-p600-series", sifive_p600, sifive_p600_tune_info)
 RISCV_TUNE("thead-c906", generic, thead_c906_tune_info)
 RISCV_TUNE("generic-ooo", generic_ooo, generic_ooo_tune_info)
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index 25951665b130a64fcb9334ff8e851dc916092b1c..4edddbadc37bb5db2abc99c6738661580d5a9ef2 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -55,6 +55,7 @@ extern enum riscv_isa_spec_class riscv_isa_spec;
 enum riscv_microarchitecture_type {
   generic,
   sifive_7,
+  sifive_p400,
   sifive_p600,
   generic_ooo
 };
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index d6868a65b3159163ac39743d2b5c506c4284035c..799d7919a4a28c26fd6449c7c1e4ea01600e243a 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -447,6 +447,23 @@ static const struct riscv_tune_param sifive_7_tune_info = {
   NULL,						/* vector cost */
 };
 
+/* Costs to use when optimizing for Sifive p400 Series.  */
+static const struct riscv_tune_param sifive_p400_tune_info = {
+  {COSTS_N_INSNS (4), COSTS_N_INSNS (4)},	/* fp_add */
+  {COSTS_N_INSNS (4), COSTS_N_INSNS (4)},	/* fp_mul */
+  {COSTS_N_INSNS (20), COSTS_N_INSNS (20)},	/* fp_div */
+  {COSTS_N_INSNS (4), COSTS_N_INSNS (4)},	/* int_mul */
+  {COSTS_N_INSNS (6), COSTS_N_INSNS (6)},	/* int_div */
+  3,						/* issue_rate */
+  4,						/* branch_cost */
+  3,						/* memory_cost */
+  4,						/* fmv_cost */
+  true,						/* slow_unaligned_access */
+  false,					/* use_divmod_expansion */
+  RISCV_FUSE_LUI_ADDI | RISCV_FUSE_AUIPC_ADDI,  /* fusible_ops */
+  &generic_vector_cost,				/* vector cost */
+};
+
 /* Costs to use when optimizing for Sifive p600 Series.  */
 static const struct riscv_tune_param sifive_p600_tune_info = {
   {COSTS_N_INSNS (4), COSTS_N_INSNS (4)},	/* fp_add */
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index e0cb3ba08d4263b0355e42dc7b92f0959382ff88..669308cc96dd2b3ddaa89763498362f82c3e1ac0 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -898,6 +898,7 @@ extern enum riscv_cc get_riscv_cc (const rtx use);
 
 #define TARGET_SFB_ALU \
  ((riscv_microarchitecture == sifive_7) \
+  || (riscv_microarchitecture == sifive_p400) \
   || (riscv_microarchitecture == sifive_p600))
 
 #define LOGICAL_OP_NON_SHORT_CIRCUIT 0
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 2a164a03dbd5ef07d3692e03a2169d22e8691a5a..39b29795cd6cf35a0d313467fec175c96b8cae82 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -687,7 +687,7 @@
 ;; Microarchitectures we know how to tune for.
 ;; Keep this in sync with enum riscv_microarchitecture.
 (define_attr "tune"
-  "generic,sifive_7,sifive_p600,generic_ooo"
+  "generic,sifive_7,sifive_p400,sifive_p600,generic_ooo"
   (const (symbol_ref "((enum attr_tune) riscv_microarchitecture)")))
 
 ;; Describe a user's asm statement.
@@ -3850,6 +3850,7 @@
 (include "pic.md")
 (include "generic.md")
 (include "sifive-7.md")
+(include "sifive-p400.md")
 (include "sifive-p600.md")
 (include "thead.md")
 (include "generic-ooo.md")
diff --git a/gcc/config/riscv/sifive-p400.md b/gcc/config/riscv/sifive-p400.md
new file mode 100644
index 0000000000000000000000000000000000000000..cc244d3c3e68b87dbe57760b6d8c48b4d69dca07
--- /dev/null
+++ b/gcc/config/riscv/sifive-p400.md
@@ -0,0 +1,174 @@
+;; Scheduling description for Sifive p400.
+
+;; Sifive p400 series is a triple-issue, superscalar, out-of-order processor.
+
+;; CPU execution units:
+;; ialu            Integer Units: all arithmetic and logic.
+;;
+;; bru             Branch Resolution Unit: all branches.
+;;
+;; st              Memory Write Unit: all writes to memory.
+;;
+;; ld              Memory Read Unit: all reads from memory.
+;;
+;; imul            Integer Multiply Unit
+;;
+;; idiv            Integer Divide Unit
+;;
+;; system          System Unit: all coprocessor accesses.
+;;
+;; fpu             Floating Point Unit
+;;
+;; fmul            Floating Point Multiply Unit
+;;
+;; fdiv            Floating Point Divide Unit
+
+;; Four automata are defined to reduce number of states
+;; which a single large automaton will have.
+(define_automaton "sifive_p400_iex,sifive_p400_fex,sifive_p400_mem,sifive_p400_div")
+
+;; The Sifive p400 has six pipelines:
+;; A-pipe       Load, Store
+;; B-pipe       ALU, Branch
+;; M-pipe       ALU, MUL, DIV and I2F(integer to float instruction)
+;; C-pipe       ALU, Conditional move and system for coprocessor accesses
+;; F-pipe       FPU, MUL, F2I(float to integer instruction)
+;; FM-pipe      FPU, MUL, DIV
+
+(define_cpu_unit "sifive_p400_A" "sifive_p400_mem")
+(define_cpu_unit "sifive_p400_B" "sifive_p400_iex")
+(define_cpu_unit "sifive_p400_M" "sifive_p400_iex")
+(define_cpu_unit "sifive_p400_C" "sifive_p400_iex")
+(define_cpu_unit "sifive_p400_F" "sifive_p400_fex")
+(define_cpu_unit "sifive_p400_FM" "sifive_p400_fex")
+
+;; Load and store unit.
+(define_cpu_unit "sifive_p400_ld" "sifive_p400_mem")
+(define_cpu_unit "sifive_p400_st" "sifive_p400_mem")
+
+;; Branch unit.
+(define_cpu_unit "sifive_p400_bru" "sifive_p400_iex")
+
+;; Integer and multiply unit.
+(define_cpu_unit "sifive_p400_ialu" "sifive_p400_iex")
+(define_cpu_unit "sifive_p400_imul" "sifive_p400_iex")
+(define_cpu_unit "sifive_p400_system" "sifive_p400_iex")
+
+;; Divide unit.
+(define_cpu_unit "sifive_p400_idiv" "sifive_p400_div")
+(define_cpu_unit "sifive_p400_fdiv" "sifive_p400_div")
+
+;; Float and multiply unit.
+(define_cpu_unit "sifive_p400_fmul" "sifive_p400_fex")
+(define_cpu_unit "sifive_p400_fpu" "sifive_p400_fex")
+
+;; ALU instruction can use pipeline C, B and M.
+(define_reservation "p400_int_pipe" "(sifive_p400_C|sifive_p400_B|sifive_p400_M)")
+;; FPU instruction can use pipeline F and FM.
+(define_reservation "p400_float_pipe" "(sifive_p400_F|sifive_p400_FM)")
+
+(define_insn_reservation "sifive_p400_load" 3
+  (and (eq_attr "tune" "sifive_p400")
+       (eq_attr "type" "load"))
+  "sifive_p400_A,sifive_p400_ld*2")
+
+(define_insn_reservation "sifive_p400_fpload" 4
+  (and (eq_attr "tune" "sifive_p400")
+       (eq_attr "type" "fpload"))
+  "sifive_p400_A,sifive_p400_ld*3")
+
+(define_insn_reservation "sifive_p400_store" 1
+  (and (eq_attr "tune" "sifive_p400")
+       (eq_attr "type" "store"))
+  "sifive_p400_A+sifive_p400_st")
+
+(define_insn_reservation "sifive_p400_fpstore" 1
+  (and (eq_attr "tune" "sifive_p400")
+       (eq_attr "type" "fpstore"))
+  "sifive_p400_A+sifive_p400_st")
+
+(define_insn_reservation "sifive_p400_branch" 1
+  (and (eq_attr "tune" "sifive_p400")
+       (eq_attr "type" "branch,jump,call"))
+  "sifive_p400_B+sifive_p400_bru")
+
+(define_insn_reservation "sifive_p400_sfb_alu" 1
+  (and (eq_attr "tune" "sifive_p400")
+       (eq_attr "type" "sfb_alu"))
+  "sifive_p400_C+sifive_p400_bru+sifive_p400_ialu")
+
+(define_insn_reservation "sifive_p400_atomic" 3
+  (and (eq_attr "tune" "sifive_p400")
+       (eq_attr "type" "atomic"))
+  "sifive_p400_C,sifive_p400_system*2")
+
+(define_insn_reservation "sifive_p400_mul" 3
+  (and (eq_attr "tune" "sifive_p400")
+       (eq_attr "type" "imul"))
+  "sifive_p400_M,sifive_p400_imul*2")
+
+(define_insn_reservation "sifive_p400_div" 31
+  (and (eq_attr "tune" "sifive_p400")
+       (eq_attr "type" "idiv"))
+  "sifive_p400_M, sifive_p400_idiv*5")
+
+(define_insn_reservation "sifive_p400_alu" 1
+  (and (eq_attr "tune" "sifive_p400")
+       (eq_attr "type" "unknown,arith,logical,shift,slt,multi,bitmanip,clz,ctz,rotate"))
+  "p400_int_pipe+sifive_p400_ialu")
+
+(define_insn_reservation "sifive_p400_cpop" 3
+  (and (eq_attr "tune" "sifive_p400")
+       (eq_attr "type" "cpop"))
+  "p400_int_pipe,sifive_p400_ialu*2")
+
+(define_insn_reservation "sifive_p400_load_immediate" 1
+  (and (eq_attr "tune" "sifive_p400")
+       (eq_attr "type" "nop,const,auipc,move"))
+  "p400_int_pipe")
+
+(define_insn_reservation "sifive_p400_fma" 4
+  (and (eq_attr "tune" "sifive_p400")
+       (eq_attr "type" "fadd,fmul,fmadd"))
+  "p400_float_pipe,sifive_p400_fmul*3")
+
+(define_insn_reservation "sifive_p400_i2f" 2
+  (and (eq_attr "tune" "sifive_p400")
+       (eq_attr "type" "mtc,fcvt_i2f"))
+  "sifive_p400_M,sifive_p400_ialu")
+
+(define_insn_reservation "sifive_p400_f2i" 2
+  (and (eq_attr "tune" "sifive_p400")
+       (eq_attr "type" "mfc,fcmp,fcvt_f2i"))
+  "sifive_p400_F,sifive_p400_fpu")
+
+(define_insn_reservation "sifive_p400_fmove" 2
+  (and (eq_attr "tune" "sifive_p400")
+       (eq_attr "type" "fmove,fcvt"))
+  "p400_float_pipe,sifive_p400_fpu")
+
+(define_insn_reservation "sifive_p400_fdiv_s" 18
+  (and (eq_attr "tune" "sifive_p400")
+       (eq_attr "type" "fdiv,fsqrt")
+       (eq_attr "mode" "SF"))
+  "sifive_p400_FM, sifive_p400_fdiv*5")
+
+(define_insn_reservation "sifive_p400_fdiv_d" 31
+  (and (eq_attr "tune" "sifive_p400")
+       (eq_attr "type" "fdiv,fsqrt")
+       (eq_attr "mode" "DF"))
+  "sifive_p400_FM, sifive_p400_fdiv*5")
+
+(define_bypass 1 "sifive_p400_load,sifive_p400_alu,sifive_p400_mul,sifive_p400_sfb_alu"
+  "sifive_p400_alu,sifive_p400_branch")
+
+(define_bypass 1 "sifive_p400_load,sifive_p400_alu,sifive_p400_mul,
+                  sifive_p400_f2i,sifive_p400_fmove,sifive_p400_sfb_alu"
+  "sifive_p400_store" "riscv_store_data_bypass_p")
+
+(define_bypass 1 "sifive_p400_i2f"
+  "sifive_p400_fma,sifive_p400_f2i,sifive_p400_fmove,sifive_p400_fdiv_s,sifive_p400_fdiv_d")
+
+(define_bypass 1 "sifive_p400_f2i"
+  "sifive_p400_branch,sifive_p400_sfb_alu,sifive_p400_mul,
+   sifive_p400_div,sifive_p400_alu,sifive_p400_cpop")
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index e9c691d63da899fadd885b5ec89b7a98303882b0..f8645822ca4aa0e798516ae70ef7777cf2f861fa 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -30714,8 +30714,8 @@ Permissible values for this option are: @samp{sifive-e20}, @samp{sifive-e21},
 Optimize the output for the given processor, specified by microarchitecture or
 particular CPU name.  Permissible values for this option are: @samp{rocket},
 @samp{sifive-3-series}, @samp{sifive-5-series}, @samp{sifive-7-series},
-@samp{thead-c906}, @samp{size}, @samp{sifive-p600-series},
-and all valid options for @option{-mcpu=}.
+@samp{thead-c906}, @samp{size}, @samp{sifive-p400-series},
+@samp{sifive-p600-series}, and all valid options for @option{-mcpu=}.
 
 When @option{-mtune=} is not specified, use the setting from @option{-mcpu},
 the default is @samp{rocket} if both are not specified.