[llvm] [mips][micromips] Add mayRaiseFPException to appropriate instructions, mark all instructions that read FCSR (FCR31) rounding bits as doing so (PR #170322)

Erik Enikeev via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 2 08:32:02 PST 2025


https://github.com/Varnike created https://github.com/llvm/llvm-project/pull/170322

None

>From 48e11800ce7a37cd2ab4cb01e6fb66c6c6d1971f Mon Sep 17 00:00:00 2001
From: Erik Enikeev <evonatarius at gmail.com>
Date: Thu, 18 Sep 2025 15:06:09 +0300
Subject: [PATCH] [mips][micromips] Add mayRaiseFPException to appropriate
 instructions, mark all instructions that read FCSR (FCR31) rounding bits as
 doing so

---
 .../lib/Target/Mips/MicroMips32r6InstrInfo.td | 233 +++++++++--------
 llvm/lib/Target/Mips/MicroMipsInstrFPU.td     | 243 ++++++++++--------
 llvm/lib/Target/Mips/Mips32r6InstrInfo.td     | 120 +++++----
 llvm/lib/Target/Mips/MipsInstrFPU.td          | 152 ++++++-----
 llvm/lib/Target/Mips/MipsRegisterInfo.cpp     |   2 +
 .../float_arithmetic_operations.mir           | 184 +++++++------
 .../instruction-select/fpext_and_fptrunc.mir  |  38 +--
 .../GlobalISel/instruction-select/fsqrt.mir   |  38 +--
 .../instruction-select/sitofp_and_uitofp.mir  |  77 +++---
 llvm/test/CodeGen/Mips/fp-strict-fp-ops.ll    | 110 ++++++++
 10 files changed, 706 insertions(+), 491 deletions(-)
 create mode 100644 llvm/test/CodeGen/Mips/fp-strict-fp-ops.ll

diff --git a/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td b/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td
index 197cd8ac5579b..dc47f1d3d9dad 100644
--- a/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td
+++ b/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td
@@ -976,38 +976,41 @@ multiclass CMP_CC_MMR6<bits<6> format, string Typestr,
       !strconcat("cmp.ule.", Typestr), format, FIELD_CMP_COND_ULE>,
       CMP_CONDN_DESC_BASE<"ule", Typestr, FGROpnd, Itin, setule>, HARDFLOAT,
       ISA_MICROMIPS32R6;
-  def CMP_SAF_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
-      !strconcat("cmp.saf.", Typestr), format, FIELD_CMP_COND_SAF>,
-      CMP_CONDN_DESC_BASE<"saf", Typestr, FGROpnd, Itin>, HARDFLOAT,
-      ISA_MICROMIPS32R6;
-  def CMP_SUN_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
-      !strconcat("cmp.sun.", Typestr), format, FIELD_CMP_COND_SUN>,
-      CMP_CONDN_DESC_BASE<"sun", Typestr, FGROpnd, Itin>, HARDFLOAT,
-      ISA_MICROMIPS32R6;
-  def CMP_SEQ_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
-      !strconcat("cmp.seq.", Typestr), format, FIELD_CMP_COND_SEQ>,
-      CMP_CONDN_DESC_BASE<"seq", Typestr, FGROpnd, Itin>, HARDFLOAT,
-      ISA_MICROMIPS32R6;
-  def CMP_SUEQ_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
-      !strconcat("cmp.sueq.", Typestr), format, FIELD_CMP_COND_SUEQ>,
-      CMP_CONDN_DESC_BASE<"sueq", Typestr, FGROpnd, Itin>, HARDFLOAT,
-      ISA_MICROMIPS32R6;
-  def CMP_SLT_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
-      !strconcat("cmp.slt.", Typestr), format, FIELD_CMP_COND_SLT>,
-      CMP_CONDN_DESC_BASE<"slt", Typestr, FGROpnd, Itin>, HARDFLOAT,
-      ISA_MICROMIPS32R6;
-  def CMP_SULT_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
-      !strconcat("cmp.sult.", Typestr), format, FIELD_CMP_COND_SULT>,
-      CMP_CONDN_DESC_BASE<"sult", Typestr, FGROpnd, Itin>, HARDFLOAT,
-      ISA_MICROMIPS32R6;
-  def CMP_SLE_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
-      !strconcat("cmp.sle.", Typestr), format, FIELD_CMP_COND_SLE>,
-      CMP_CONDN_DESC_BASE<"sle", Typestr, FGROpnd, Itin>, HARDFLOAT,
-      ISA_MICROMIPS32R6;
-  def CMP_SULE_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
-      !strconcat("cmp.sule.", Typestr), format, FIELD_CMP_COND_SULE>,
-      CMP_CONDN_DESC_BASE<"sule", Typestr, FGROpnd, Itin>, HARDFLOAT,
-      ISA_MICROMIPS32R6;
+
+  let mayRaiseFPException = 1 in {
+    def CMP_SAF_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
+        !strconcat("cmp.saf.", Typestr), format, FIELD_CMP_COND_SAF>,
+        CMP_CONDN_DESC_BASE<"saf", Typestr, FGROpnd, Itin>, HARDFLOAT,
+        ISA_MICROMIPS32R6;
+    def CMP_SUN_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
+        !strconcat("cmp.sun.", Typestr), format, FIELD_CMP_COND_SUN>,
+        CMP_CONDN_DESC_BASE<"sun", Typestr, FGROpnd, Itin>, HARDFLOAT,
+        ISA_MICROMIPS32R6;
+    def CMP_SEQ_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
+        !strconcat("cmp.seq.", Typestr), format, FIELD_CMP_COND_SEQ>,
+        CMP_CONDN_DESC_BASE<"seq", Typestr, FGROpnd, Itin>, HARDFLOAT,
+        ISA_MICROMIPS32R6;
+    def CMP_SUEQ_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
+        !strconcat("cmp.sueq.", Typestr), format, FIELD_CMP_COND_SUEQ>,
+        CMP_CONDN_DESC_BASE<"sueq", Typestr, FGROpnd, Itin>, HARDFLOAT,
+        ISA_MICROMIPS32R6;
+    def CMP_SLT_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
+        !strconcat("cmp.slt.", Typestr), format, FIELD_CMP_COND_SLT>,
+        CMP_CONDN_DESC_BASE<"slt", Typestr, FGROpnd, Itin>, HARDFLOAT,
+        ISA_MICROMIPS32R6;
+    def CMP_SULT_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
+        !strconcat("cmp.sult.", Typestr), format, FIELD_CMP_COND_SULT>,
+        CMP_CONDN_DESC_BASE<"sult", Typestr, FGROpnd, Itin>, HARDFLOAT,
+        ISA_MICROMIPS32R6;
+    def CMP_SLE_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
+        !strconcat("cmp.sle.", Typestr), format, FIELD_CMP_COND_SLE>,
+        CMP_CONDN_DESC_BASE<"sle", Typestr, FGROpnd, Itin>, HARDFLOAT,
+        ISA_MICROMIPS32R6;
+    def CMP_SULE_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
+        !strconcat("cmp.sule.", Typestr), format, FIELD_CMP_COND_SULE>,
+        CMP_CONDN_DESC_BASE<"sule", Typestr, FGROpnd, Itin>, HARDFLOAT,
+        ISA_MICROMIPS32R6;
+  }
 }
 
 class ABSS_FT_MMR6_DESC_BASE<string instr_asm, RegisterOperand DstRC,
@@ -1453,78 +1456,90 @@ let DecoderMethod = "DecodeMemMMImm16" in {
   def SW_MMR6 : StdMMR6Rel, SW_MMR6_DESC, SW_MMR6_ENC, ISA_MICROMIPS32R6;
 }
 /// Floating Point Instructions
-def FADD_S_MMR6 : StdMMR6Rel, FADD_S_MMR6_ENC, FADD_S_MMR6_DESC,
-                  ISA_MICROMIPS32R6;
-def FSUB_S_MMR6 : StdMMR6Rel, FSUB_S_MMR6_ENC, FSUB_S_MMR6_DESC,
-                  ISA_MICROMIPS32R6;
-def FMUL_S_MMR6 : StdMMR6Rel, FMUL_S_MMR6_ENC, FMUL_S_MMR6_DESC,
-                  ISA_MICROMIPS32R6;
-def FDIV_S_MMR6 : StdMMR6Rel, FDIV_S_MMR6_ENC, FDIV_S_MMR6_DESC,
-                  ISA_MICROMIPS32R6;
-def MADDF_S_MMR6 : R6MMR6Rel, MADDF_S_MMR6_ENC, MADDF_S_MMR6_DESC,
-                   ISA_MICROMIPS32R6;
-def MADDF_D_MMR6 : R6MMR6Rel, MADDF_D_MMR6_ENC, MADDF_D_MMR6_DESC,
-                   ISA_MICROMIPS32R6;
-def MSUBF_S_MMR6 : R6MMR6Rel, MSUBF_S_MMR6_ENC, MSUBF_S_MMR6_DESC,
-                   ISA_MICROMIPS32R6;
-def MSUBF_D_MMR6 : R6MMR6Rel, MSUBF_D_MMR6_ENC, MSUBF_D_MMR6_DESC,
-                   ISA_MICROMIPS32R6;
+let mayRaiseFPException = 1, Uses = [FCR31] in {
+  def FADD_S_MMR6 : StdMMR6Rel, FADD_S_MMR6_ENC, FADD_S_MMR6_DESC,
+                    ISA_MICROMIPS32R6;
+  def FSUB_S_MMR6 : StdMMR6Rel, FSUB_S_MMR6_ENC, FSUB_S_MMR6_DESC,
+                    ISA_MICROMIPS32R6;
+  def FMUL_S_MMR6 : StdMMR6Rel, FMUL_S_MMR6_ENC, FMUL_S_MMR6_DESC,
+                    ISA_MICROMIPS32R6;
+  def FDIV_S_MMR6 : StdMMR6Rel, FDIV_S_MMR6_ENC, FDIV_S_MMR6_DESC,
+                    ISA_MICROMIPS32R6;
+  def MADDF_S_MMR6 : R6MMR6Rel, MADDF_S_MMR6_ENC, MADDF_S_MMR6_DESC,
+                     ISA_MICROMIPS32R6;
+  def MADDF_D_MMR6 : R6MMR6Rel, MADDF_D_MMR6_ENC, MADDF_D_MMR6_DESC,
+                     ISA_MICROMIPS32R6;
+  def MSUBF_S_MMR6 : R6MMR6Rel, MSUBF_S_MMR6_ENC, MSUBF_S_MMR6_DESC,
+                     ISA_MICROMIPS32R6;
+  def MSUBF_D_MMR6 : R6MMR6Rel, MSUBF_D_MMR6_ENC, MSUBF_D_MMR6_DESC,
+                     ISA_MICROMIPS32R6;
+}
+
 def FMOV_S_MMR6 : StdMMR6Rel, FMOV_S_MMR6_ENC, FMOV_S_MMR6_DESC,
                   ISA_MICROMIPS32R6;
 def FMOV_D_MMR6 : StdMMR6Rel, FMOV_D_MMR6_ENC, FMOV_D_MMR6_DESC,
                   ISA_MICROMIPS32R6;
 def FNEG_S_MMR6 : StdMMR6Rel, FNEG_S_MMR6_ENC, FNEG_S_MMR6_DESC,
                   ISA_MICROMIPS32R6;
-def MAX_S_MMR6 : R6MMR6Rel, MAX_S_MMR6_ENC, MAX_S_MMR6_DESC, ISA_MICROMIPS32R6;
-def MAX_D_MMR6 : R6MMR6Rel, MAX_D_MMR6_ENC, MAX_D_MMR6_DESC, ISA_MICROMIPS32R6;
-def MIN_S_MMR6 : R6MMR6Rel, MIN_S_MMR6_ENC, MIN_S_MMR6_DESC, ISA_MICROMIPS32R6;
-def MIN_D_MMR6 : R6MMR6Rel, MIN_D_MMR6_ENC, MIN_D_MMR6_DESC, ISA_MICROMIPS32R6;
-def MAXA_S_MMR6 : R6MMR6Rel, MAXA_S_MMR6_ENC, MAXA_S_MMR6_DESC,
-                  ISA_MICROMIPS32R6;
-def MAXA_D_MMR6 : R6MMR6Rel, MAXA_D_MMR6_ENC, MAXA_D_MMR6_DESC,
-                  ISA_MICROMIPS32R6;
-def MINA_S_MMR6 : R6MMR6Rel, MINA_S_MMR6_ENC, MINA_S_MMR6_DESC,
-                  ISA_MICROMIPS32R6;
-def MINA_D_MMR6 : R6MMR6Rel, MINA_D_MMR6_ENC, MINA_D_MMR6_DESC,
-                  ISA_MICROMIPS32R6;
-def CVT_L_S_MMR6 : StdMMR6Rel, CVT_L_S_MMR6_ENC, CVT_L_S_MMR6_DESC,
-                   ISA_MICROMIPS32R6;
-def CVT_L_D_MMR6 : StdMMR6Rel, CVT_L_D_MMR6_ENC, CVT_L_D_MMR6_DESC,
-                   ISA_MICROMIPS32R6;
-def CVT_W_S_MMR6 : StdMMR6Rel, CVT_W_S_MMR6_ENC, CVT_W_S_MMR6_DESC,
-                   ISA_MICROMIPS32R6;
-def CVT_D_L_MMR6 : StdMMR6Rel, CVT_D_L_MMR6_ENC, CVT_D_L_MMR6_DESC,
-                   ISA_MICROMIPS32R6;
-def CVT_S_W_MMR6 : StdMMR6Rel, CVT_S_W_MMR6_ENC, CVT_S_W_MMR6_DESC,
-                   ISA_MICROMIPS32R6;
-def CVT_S_L_MMR6 : StdMMR6Rel, CVT_S_L_MMR6_ENC, CVT_S_L_MMR6_DESC,
-                   ISA_MICROMIPS32R6;
-defm S_MMR6 : CMP_CC_MMR6<0b000101, "s", FGR32Opnd, II_CMP_CC_S>;
-defm D_MMR6 : CMP_CC_MMR6<0b010101, "d", FGR64Opnd, II_CMP_CC_D>;
-def FLOOR_L_S_MMR6 : StdMMR6Rel, FLOOR_L_S_MMR6_ENC, FLOOR_L_S_MMR6_DESC,
-                     ISA_MICROMIPS32R6;
-def FLOOR_L_D_MMR6 : StdMMR6Rel, FLOOR_L_D_MMR6_ENC, FLOOR_L_D_MMR6_DESC,
-                     ISA_MICROMIPS32R6;
-def FLOOR_W_S_MMR6 : StdMMR6Rel, FLOOR_W_S_MMR6_ENC, FLOOR_W_S_MMR6_DESC,
-                     ISA_MICROMIPS32R6;
-def FLOOR_W_D_MMR6 : StdMMR6Rel, FLOOR_W_D_MMR6_ENC, FLOOR_W_D_MMR6_DESC,
-                     ISA_MICROMIPS32R6;
-def CEIL_L_S_MMR6 : StdMMR6Rel, CEIL_L_S_MMR6_ENC, CEIL_L_S_MMR6_DESC,
+
+let mayRaiseFPException = 1 in {
+  def MAX_S_MMR6 : R6MMR6Rel, MAX_S_MMR6_ENC, MAX_S_MMR6_DESC, ISA_MICROMIPS32R6;
+  def MAX_D_MMR6 : R6MMR6Rel, MAX_D_MMR6_ENC, MAX_D_MMR6_DESC, ISA_MICROMIPS32R6;
+  def MIN_S_MMR6 : R6MMR6Rel, MIN_S_MMR6_ENC, MIN_S_MMR6_DESC, ISA_MICROMIPS32R6;
+  def MIN_D_MMR6 : R6MMR6Rel, MIN_D_MMR6_ENC, MIN_D_MMR6_DESC, ISA_MICROMIPS32R6;
+  def MAXA_S_MMR6 : R6MMR6Rel, MAXA_S_MMR6_ENC, MAXA_S_MMR6_DESC,
                     ISA_MICROMIPS32R6;
-def CEIL_L_D_MMR6 : StdMMR6Rel, CEIL_L_D_MMR6_ENC, CEIL_L_D_MMR6_DESC,
+  def MAXA_D_MMR6 : R6MMR6Rel, MAXA_D_MMR6_ENC, MAXA_D_MMR6_DESC,
                     ISA_MICROMIPS32R6;
-def CEIL_W_S_MMR6 : StdMMR6Rel, CEIL_W_S_MMR6_ENC, CEIL_W_S_MMR6_DESC,
+  def MINA_S_MMR6 : R6MMR6Rel, MINA_S_MMR6_ENC, MINA_S_MMR6_DESC,
                     ISA_MICROMIPS32R6;
-def CEIL_W_D_MMR6 : StdMMR6Rel, CEIL_W_D_MMR6_ENC, CEIL_W_D_MMR6_DESC,
+  def MINA_D_MMR6 : R6MMR6Rel, MINA_D_MMR6_ENC, MINA_D_MMR6_DESC,
                     ISA_MICROMIPS32R6;
-def TRUNC_L_S_MMR6 : StdMMR6Rel, TRUNC_L_S_MMR6_ENC, TRUNC_L_S_MMR6_DESC,
-                     ISA_MICROMIPS32R6;
-def TRUNC_L_D_MMR6 : StdMMR6Rel, TRUNC_L_D_MMR6_ENC, TRUNC_L_D_MMR6_DESC,
-                     ISA_MICROMIPS32R6;
-def TRUNC_W_S_MMR6 : StdMMR6Rel, TRUNC_W_S_MMR6_ENC, TRUNC_W_S_MMR6_DESC,
-                     ISA_MICROMIPS32R6;
-def TRUNC_W_D_MMR6 : StdMMR6Rel, TRUNC_W_D_MMR6_ENC, TRUNC_W_D_MMR6_DESC,
-                     ISA_MICROMIPS32R6;
+
+  let Uses = [FCR31] in {
+    def CVT_L_S_MMR6 : StdMMR6Rel, CVT_L_S_MMR6_ENC, CVT_L_S_MMR6_DESC,
+                       ISA_MICROMIPS32R6;
+    def CVT_L_D_MMR6 : StdMMR6Rel, CVT_L_D_MMR6_ENC, CVT_L_D_MMR6_DESC,
+                       ISA_MICROMIPS32R6;
+    def CVT_W_S_MMR6 : StdMMR6Rel, CVT_W_S_MMR6_ENC, CVT_W_S_MMR6_DESC,
+                       ISA_MICROMIPS32R6;
+    def CVT_D_L_MMR6 : StdMMR6Rel, CVT_D_L_MMR6_ENC, CVT_D_L_MMR6_DESC,
+                       ISA_MICROMIPS32R6;
+    def CVT_S_W_MMR6 : StdMMR6Rel, CVT_S_W_MMR6_ENC, CVT_S_W_MMR6_DESC,
+                       ISA_MICROMIPS32R6;
+    def CVT_S_L_MMR6 : StdMMR6Rel, CVT_S_L_MMR6_ENC, CVT_S_L_MMR6_DESC,
+                       ISA_MICROMIPS32R6;
+  }
+}
+
+defm S_MMR6 : CMP_CC_MMR6<0b000101, "s", FGR32Opnd, II_CMP_CC_S>;
+defm D_MMR6 : CMP_CC_MMR6<0b010101, "d", FGR64Opnd, II_CMP_CC_D>;
+let mayRaiseFPException = 1 in {
+  def FLOOR_L_S_MMR6 : StdMMR6Rel, FLOOR_L_S_MMR6_ENC, FLOOR_L_S_MMR6_DESC,
+                       ISA_MICROMIPS32R6;
+  def FLOOR_L_D_MMR6 : StdMMR6Rel, FLOOR_L_D_MMR6_ENC, FLOOR_L_D_MMR6_DESC,
+                       ISA_MICROMIPS32R6;
+  def FLOOR_W_S_MMR6 : StdMMR6Rel, FLOOR_W_S_MMR6_ENC, FLOOR_W_S_MMR6_DESC,
+                       ISA_MICROMIPS32R6;
+  def FLOOR_W_D_MMR6 : StdMMR6Rel, FLOOR_W_D_MMR6_ENC, FLOOR_W_D_MMR6_DESC,
+                       ISA_MICROMIPS32R6;
+  def CEIL_L_S_MMR6 : StdMMR6Rel, CEIL_L_S_MMR6_ENC, CEIL_L_S_MMR6_DESC,
+                      ISA_MICROMIPS32R6;
+  def CEIL_L_D_MMR6 : StdMMR6Rel, CEIL_L_D_MMR6_ENC, CEIL_L_D_MMR6_DESC,
+                      ISA_MICROMIPS32R6;
+  def CEIL_W_S_MMR6 : StdMMR6Rel, CEIL_W_S_MMR6_ENC, CEIL_W_S_MMR6_DESC,
+                      ISA_MICROMIPS32R6;
+  def CEIL_W_D_MMR6 : StdMMR6Rel, CEIL_W_D_MMR6_ENC, CEIL_W_D_MMR6_DESC,
+                      ISA_MICROMIPS32R6;
+  def TRUNC_L_S_MMR6 : StdMMR6Rel, TRUNC_L_S_MMR6_ENC, TRUNC_L_S_MMR6_DESC,
+                       ISA_MICROMIPS32R6;
+  def TRUNC_L_D_MMR6 : StdMMR6Rel, TRUNC_L_D_MMR6_ENC, TRUNC_L_D_MMR6_DESC,
+                       ISA_MICROMIPS32R6;
+  def TRUNC_W_S_MMR6 : StdMMR6Rel, TRUNC_W_S_MMR6_ENC, TRUNC_W_S_MMR6_DESC,
+                       ISA_MICROMIPS32R6;
+  def TRUNC_W_D_MMR6 : StdMMR6Rel, TRUNC_W_D_MMR6_ENC, TRUNC_W_D_MMR6_DESC,
+                       ISA_MICROMIPS32R6;
+}
 def SB_MMR6 : StdMMR6Rel, SB_MMR6_DESC, SB_MMR6_ENC, ISA_MICROMIPS32R6;
 def SH_MMR6 : StdMMR6Rel, SH_MMR6_DESC, SH_MMR6_ENC, ISA_MICROMIPS32R6;
 def LW_MMR6 : StdMMR6Rel, LW_MMR6_DESC, LW_MMR6_ENC, ISA_MICROMIPS32R6;
@@ -1562,18 +1577,24 @@ def JALRC_HB_MMR6 : R6MMR6Rel, JALRC_HB_MMR6_ENC, JALRC_HB_MMR6_DESC,
 def EXT_MMR6 : StdMMR6Rel, EXT_MMR6_ENC, EXT_MMR6_DESC, ISA_MICROMIPS32R6;
 def INS_MMR6 : StdMMR6Rel, INS_MMR6_ENC, INS_MMR6_DESC, ISA_MICROMIPS32R6;
 def JALRC_MMR6 : R6MMR6Rel, JALRC_MMR6_ENC, JALRC_MMR6_DESC, ISA_MICROMIPS32R6;
-def RINT_S_MMR6 : StdMMR6Rel, RINT_S_MMR6_ENC, RINT_S_MMR6_DESC,
-                  ISA_MICROMIPS32R6;
-def RINT_D_MMR6 : StdMMR6Rel, RINT_D_MMR6_ENC, RINT_D_MMR6_DESC,
-                  ISA_MICROMIPS32R6;
-def ROUND_L_S_MMR6 : StdMMR6Rel, ROUND_L_S_MMR6_ENC, ROUND_L_S_MMR6_DESC,
-                     ISA_MICROMIPS32R6;
-def ROUND_L_D_MMR6 : StdMMR6Rel, ROUND_L_D_MMR6_ENC, ROUND_L_D_MMR6_DESC,
-                     ISA_MICROMIPS32R6;
-def ROUND_W_S_MMR6 : StdMMR6Rel, ROUND_W_S_MMR6_ENC, ROUND_W_S_MMR6_DESC,
-                     ISA_MICROMIPS32R6;
-def ROUND_W_D_MMR6 : StdMMR6Rel, ROUND_W_D_MMR6_ENC, ROUND_W_D_MMR6_DESC,
-                     ISA_MICROMIPS32R6;
+
+let mayRaiseFPException = 1 in {
+  let Uses = [FCR31] in {
+    def RINT_S_MMR6 : StdMMR6Rel, RINT_S_MMR6_ENC, RINT_S_MMR6_DESC,
+                      ISA_MICROMIPS32R6;
+    def RINT_D_MMR6 : StdMMR6Rel, RINT_D_MMR6_ENC, RINT_D_MMR6_DESC,
+                      ISA_MICROMIPS32R6;
+  }
+  def ROUND_L_S_MMR6 : StdMMR6Rel, ROUND_L_S_MMR6_ENC, ROUND_L_S_MMR6_DESC,
+                       ISA_MICROMIPS32R6;
+  def ROUND_L_D_MMR6 : StdMMR6Rel, ROUND_L_D_MMR6_ENC, ROUND_L_D_MMR6_DESC,
+                       ISA_MICROMIPS32R6;
+  def ROUND_W_S_MMR6 : StdMMR6Rel, ROUND_W_S_MMR6_ENC, ROUND_W_S_MMR6_DESC,
+                       ISA_MICROMIPS32R6;
+  def ROUND_W_D_MMR6 : StdMMR6Rel, ROUND_W_D_MMR6_ENC, ROUND_W_D_MMR6_DESC,
+                       ISA_MICROMIPS32R6;
+}
+
 def SEL_S_MMR6 : R6MMR6Rel, SEL_S_MMR6_ENC, SEL_S_MMR6_DESC, ISA_MICROMIPS32R6;
 def SEL_D_MMR6 : R6MMR6Rel, SEL_D_MMR6_ENC, SEL_D_MMR6_DESC, ISA_MICROMIPS32R6;
 def SELEQZ_S_MMR6 : R6MMR6Rel, SELEQZ_S_MMR6_ENC, SELEQZ_S_MMR6_DESC,
diff --git a/llvm/lib/Target/Mips/MicroMipsInstrFPU.td b/llvm/lib/Target/Mips/MicroMipsInstrFPU.td
index d5fc30cef695c..22890dc35baa3 100644
--- a/llvm/lib/Target/Mips/MicroMipsInstrFPU.td
+++ b/llvm/lib/Target/Mips/MicroMipsInstrFPU.td
@@ -22,23 +22,25 @@ multiclass ADDS_MMM<string opstr, InstrItinClass Itin, bit IsComm,
   }
 }
 
-def FADD_S_MM : MMRel, ADDS_FT<"add.s", FGR32Opnd, II_ADD_S, 1, fadd>,
-                ADDS_FM_MM<0, 0x30>, ISA_MICROMIPS;
-def FDIV_S_MM : MMRel, ADDS_FT<"div.s", FGR32Opnd, II_DIV_S, 0, fdiv>,
-                ADDS_FM_MM<0, 0xf0>, ISA_MICROMIPS;
-def FMUL_S_MM : MMRel, ADDS_FT<"mul.s", FGR32Opnd, II_MUL_S, 1, fmul>,
-                ADDS_FM_MM<0, 0xb0>, ISA_MICROMIPS;
-def FSUB_S_MM : MMRel, ADDS_FT<"sub.s", FGR32Opnd, II_SUB_S, 0, fsub>,
-                ADDS_FM_MM<0, 0x70>, ISA_MICROMIPS;
-
-defm FADD : ADDS_MMM<"add.d", II_ADD_D, 1, fadd>,
-            ADDS_FM_MM<1, 0x30>, ISA_MICROMIPS;
-defm FDIV : ADDS_MMM<"div.d", II_DIV_D, 0, fdiv>,
-            ADDS_FM_MM<1, 0xf0>, ISA_MICROMIPS;
-defm FMUL : ADDS_MMM<"mul.d", II_MUL_D, 1, fmul>,
-            ADDS_FM_MM<1, 0xb0>, ISA_MICROMIPS;
-defm FSUB : ADDS_MMM<"sub.d", II_SUB_D, 0, fsub>,
-            ADDS_FM_MM<1, 0x70>, ISA_MICROMIPS;
+let mayRaiseFPException = 1, Uses = [FCR31] in {
+  def FADD_S_MM : MMRel, ADDS_FT<"add.s", FGR32Opnd, II_ADD_S, 1, fadd>,
+                  ADDS_FM_MM<0, 0x30>, ISA_MICROMIPS;
+  def FDIV_S_MM : MMRel, ADDS_FT<"div.s", FGR32Opnd, II_DIV_S, 0, fdiv>,
+                  ADDS_FM_MM<0, 0xf0>, ISA_MICROMIPS;
+  def FMUL_S_MM : MMRel, ADDS_FT<"mul.s", FGR32Opnd, II_MUL_S, 1, fmul>,
+                  ADDS_FM_MM<0, 0xb0>, ISA_MICROMIPS;
+  def FSUB_S_MM : MMRel, ADDS_FT<"sub.s", FGR32Opnd, II_SUB_S, 0, fsub>,
+                  ADDS_FM_MM<0, 0x70>, ISA_MICROMIPS;
+
+  defm FADD : ADDS_MMM<"add.d", II_ADD_D, 1, fadd>,
+              ADDS_FM_MM<1, 0x30>, ISA_MICROMIPS;
+  defm FDIV : ADDS_MMM<"div.d", II_DIV_D, 0, fdiv>,
+              ADDS_FM_MM<1, 0xf0>, ISA_MICROMIPS;
+  defm FMUL : ADDS_MMM<"mul.d", II_MUL_D, 1, fmul>,
+              ADDS_FM_MM<1, 0xb0>, ISA_MICROMIPS;
+  defm FSUB : ADDS_MMM<"sub.d", II_SUB_D, 0, fsub>,
+              ADDS_FM_MM<1, 0x70>, ISA_MICROMIPS;
+}
 
 let DecoderNamespace = "MicroMips" in {
   def LWXC1_MM : MMRel, LWXC1_FT<"lwxc1", FGR32Opnd, II_LWXC1, load>,
@@ -75,11 +77,13 @@ let DecoderNamespace = "MicroMips" in {
                 BC1F_FM_MM<0x1c>, ISA_MICROMIPS32_NOT_MIPS32R6;
   def BC1T_MM : MMRel, BC1F_FT<"bc1t", brtarget_mm, II_BC1T, MIPS_BRANCH_T>,
                 BC1F_FM_MM<0x1d>, ISA_MICROMIPS32_NOT_MIPS32R6;
+
+  let mayRaiseFPException = 1, Uses = [FCR31] in
   def CVT_W_S_MM   : MMRel, ABSS_FT<"cvt.w.s", FGR32Opnd, FGR32Opnd, II_CVT>,
                      ROUND_W_FM_MM<0, 0x24>, ISA_MICROMIPS;
 }
 
-let DecoderNamespace = "MicroMips" in {
+let DecoderNamespace = "MicroMips", mayRaiseFPException = 1 in {
   def ROUND_W_S_MM : MMRel, StdMMR6Rel, ABSS_FT<"round.w.s", FGR32Opnd,
                                                 FGR32Opnd, II_ROUND>,
                      ROUND_W_FM_MM<0, 0xec>, ISA_MICROMIPS;
@@ -94,15 +98,17 @@ let DecoderNamespace = "MicroMips" in {
   def TRUNC_W_MM : MMRel, ABSS_FT<"trunc.w.d", FGR32Opnd, AFGR64Opnd, II_TRUNC>,
                    ROUND_W_FM_MM<1, 0xac>, ISA_MICROMIPS, FGR_32;
 
-  def CVT_L_S_MM   : MMRel, ABSS_FT<"cvt.l.s", FGR64Opnd, FGR32Opnd, II_CVT>,
-                     ROUND_W_FM_MM<0, 0x4>, ISA_MICROMIPS, FGR_64;
-  def CVT_L_D64_MM : MMRel, ABSS_FT<"cvt.l.d", FGR64Opnd, FGR64Opnd, II_CVT>,
-                     ROUND_W_FM_MM<1, 0x4>, ISA_MICROMIPS, FGR_64;
+  let Uses = [FCR31] in {
+    def CVT_L_S_MM   : MMRel, ABSS_FT<"cvt.l.s", FGR64Opnd, FGR32Opnd, II_CVT>,
+                       ROUND_W_FM_MM<0, 0x4>, ISA_MICROMIPS, FGR_64;
+    def CVT_L_D64_MM : MMRel, ABSS_FT<"cvt.l.d", FGR64Opnd, FGR64Opnd, II_CVT>,
+                       ROUND_W_FM_MM<1, 0x4>, ISA_MICROMIPS, FGR_64;
 
-  def CVT_W_D32_MM : MMRel, ABSS_FT<"cvt.w.d", FGR32Opnd, AFGR64Opnd, II_CVT>,
-                     ROUND_W_FM_MM<1, 0x24>, ISA_MICROMIPS, FGR_32;
+    def CVT_W_D32_MM : MMRel, ABSS_FT<"cvt.w.d", FGR32Opnd, AFGR64Opnd, II_CVT>,
+                       ROUND_W_FM_MM<1, 0x24>, ISA_MICROMIPS, FGR_32;
+  }
 }
-let DecoderNamespace = "MicroMipsFP64" in {
+let DecoderNamespace = "MicroMipsFP64", mayRaiseFPException = 1, Uses = [FCR31] in {
   def CVT_W_D64_MM : ABSS_FT<"cvt.w.d", FGR32Opnd, FGR64Opnd, II_CVT>,
                      ROUND_W_FM_MM<1, 0x24>, ISA_MICROMIPS, FGR_64;
 }
@@ -119,6 +125,7 @@ multiclass ABSS_MMM<string opstr, InstrItinClass Itin,
   }
 }
 
+let mayRaiseFPException = 1, Uses = [FCR31] in
 defm FSQRT : ABSS_MMM<"sqrt.d", II_SQRT_D, fsqrt>, ROUND_W_FM_MM<1, 0x28>;
 defm FABS : ABSS_MMM<"abs.d", II_SQRT_D, fabs>, ABS_FM_MM<1, 0xd>;
 
@@ -134,14 +141,14 @@ def FMOV_S_MM : MMRel, ABSS_FT<"mov.s", FGR32Opnd, FGR32Opnd, II_MOV_S>,
 def FNEG_S_MM : MMRel, ABSS_FT<"neg.s", FGR32Opnd, FGR32Opnd, II_NEG, fneg>,
                 ABS_FM_MM<0, 0x2d>, ISA_MICROMIPS;
 
-let DecoderNamespace = "MicroMips" in {
+let DecoderNamespace = "MicroMips", mayRaiseFPException = 1, Uses = [FCR31] in {
   def CVT_D32_S_MM : MMRel, ABSS_FT<"cvt.d.s", AFGR64Opnd, FGR32Opnd, II_CVT>,
                      ABS_FM_MM<0, 0x4d>, ISA_MICROMIPS, FGR_32;
   def CVT_D32_W_MM : MMRel, ABSS_FT<"cvt.d.w", AFGR64Opnd, FGR32Opnd, II_CVT>,
                      ABS_FM_MM<1, 0x4d>, ISA_MICROMIPS, FGR_32;
 }
 
-let DecoderNamespace = "MicroMipsFP64" in {
+let DecoderNamespace = "MicroMipsFP64", mayRaiseFPException = 1, Uses = [FCR31] in {
   def CVT_D64_S_MM : ABSS_FT<"cvt.d.s", FGR64Opnd, FGR32Opnd, II_CVT>,
                      ABS_FM_MM<0, 0x4d>, ISA_MICROMIPS, FGR_64;
   def CVT_D64_W_MM : ABSS_FT<"cvt.d.w", FGR64Opnd, FGR32Opnd, II_CVT>,
@@ -150,7 +157,7 @@ let DecoderNamespace = "MicroMipsFP64" in {
                      ABS_FM_MM<0, 0x6d>, ISA_MICROMIPS, FGR_64;
 }
 
-let DecoderNamespace = "MicroMips" in {
+let DecoderNamespace = "MicroMips", mayRaiseFPException = 1, Uses = [FCR31] in {
   def CVT_S_D32_MM : MMRel, ABSS_FT<"cvt.s.d", FGR32Opnd, AFGR64Opnd, II_CVT>,
                      ABS_FM_MM<0, 0x6d>, ISA_MICROMIPS, FGR_32;
   def CVT_S_W_MM : MMRel, ABSS_FT<"cvt.s.w", FGR32Opnd, FGR32Opnd, II_CVT>,
@@ -194,41 +201,44 @@ let DecoderNamespace = "MicroMips" in {
   def MTC1_MM : MMRel, MTC1_FT<"mtc1", FGR32Opnd, GPR32Opnd,
                                II_MTC1, bitconvert>, MFC1_FM_MM<0xa0>,
                 ISA_MICROMIPS;
-
-  def MADD_S_MM : MMRel, MADDS_FT<"madd.s", FGR32Opnd, II_MADD_S>,
-                  MADDS_FM_MM<0x1>, ISA_MICROMIPS32_NOT_MIPS32R6, MADD4;
-  def MSUB_S_MM : MMRel, MADDS_FT<"msub.s", FGR32Opnd, II_MSUB_S>,
-                  MADDS_FM_MM<0x21>, ISA_MICROMIPS32_NOT_MIPS32R6, MADD4;
-  let AdditionalPredicates = [NoNaNsFPMath, HasMadd4] in {
-    def NMADD_S_MM : MMRel, NMADDS_FT<"nmadd.s", FGR32Opnd, II_NMADD_S>,
-                     MADDS_FM_MM<0x2>, ISA_MICROMIPS32_NOT_MIPS32R6;
-    def NMSUB_S_MM : MMRel, NMADDS_FT<"nmsub.s", FGR32Opnd, II_NMSUB_S>,
-                     MADDS_FM_MM<0x22>, ISA_MICROMIPS32_NOT_MIPS32R6;
-  }
-  def MADD_D32_MM  : MMRel, MADDS_FT<"madd.d", AFGR64Opnd, II_MADD_D>,
-                     MADDS_FM_MM<0x9>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32,
-                     MADD4;
-  def MSUB_D32_MM  : MMRel, MADDS_FT<"msub.d", AFGR64Opnd, II_MSUB_D>,
-                     MADDS_FM_MM<0x29>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32,
-                     MADD4;
-  let AdditionalPredicates = [NoNaNsFPMath, HasMadd4] in {
-    def NMADD_D32_MM : MMRel, NMADDS_FT<"nmadd.d", AFGR64Opnd, II_NMADD_D>,
-                       MADDS_FM_MM<0xa>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32;
-    def NMSUB_D32_MM : MMRel, NMADDS_FT<"nmsub.d", AFGR64Opnd, II_NMSUB_D>,
-                       MADDS_FM_MM<0x2a>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32;
+  let mayRaiseFPException = 1, Uses = [FCR31] in {
+    def MADD_S_MM : MMRel, MADDS_FT<"madd.s", FGR32Opnd, II_MADD_S>,
+                    MADDS_FM_MM<0x1>, ISA_MICROMIPS32_NOT_MIPS32R6, MADD4;
+    def MSUB_S_MM : MMRel, MADDS_FT<"msub.s", FGR32Opnd, II_MSUB_S>,
+                    MADDS_FM_MM<0x21>, ISA_MICROMIPS32_NOT_MIPS32R6, MADD4;
+    def MADD_D32_MM  : MMRel, MADDS_FT<"madd.d", AFGR64Opnd, II_MADD_D>,
+                       MADDS_FM_MM<0x9>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32,
+                       MADD4;
+    def MSUB_D32_MM  : MMRel, MADDS_FT<"msub.d", AFGR64Opnd, II_MSUB_D>,
+                       MADDS_FM_MM<0x29>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32,
+                       MADD4;
+
+    let AdditionalPredicates = [NoNaNsFPMath, HasMadd4] in {
+      def NMADD_S_MM : MMRel, NMADDS_FT<"nmadd.s", FGR32Opnd, II_NMADD_S>,
+                       MADDS_FM_MM<0x2>, ISA_MICROMIPS32_NOT_MIPS32R6;
+      def NMSUB_S_MM : MMRel, NMADDS_FT<"nmsub.s", FGR32Opnd, II_NMSUB_S>,
+                       MADDS_FM_MM<0x22>, ISA_MICROMIPS32_NOT_MIPS32R6;
+      def NMADD_D32_MM : MMRel, NMADDS_FT<"nmadd.d", AFGR64Opnd, II_NMADD_D>,
+                         MADDS_FM_MM<0xa>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32;
+      def NMSUB_D32_MM : MMRel, NMADDS_FT<"nmsub.d", AFGR64Opnd, II_NMSUB_D>,
+                         MADDS_FM_MM<0x2a>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32;
+    }
   }
 
-  def FLOOR_W_S_MM : MMRel, ABSS_FT<"floor.w.s", FGR32Opnd, FGR32Opnd,
-                                    II_FLOOR>, ROUND_W_FM_MM<0, 0x2c>,
-                     ISA_MICROMIPS;
-  def TRUNC_W_S_MM : MMRel, StdMMR6Rel, ABSS_FT<"trunc.w.s", FGR32Opnd,
-                                                FGR32Opnd, II_TRUNC>,
-                     ROUND_W_FM_MM<0, 0xac>, ISA_MICROMIPS;
-  def CEIL_W_S_MM  : MMRel, ABSS_FT<"ceil.w.s", FGR32Opnd, FGR32Opnd, II_CEIL>,
-                     ROUND_W_FM_MM<0, 0x6c>, ISA_MICROMIPS;
+  let mayRaiseFPException = 1 in {
+    def FLOOR_W_S_MM : MMRel, ABSS_FT<"floor.w.s", FGR32Opnd, FGR32Opnd,
+                                      II_FLOOR>, ROUND_W_FM_MM<0, 0x2c>,
+                       ISA_MICROMIPS;
+    def TRUNC_W_S_MM : MMRel, StdMMR6Rel, ABSS_FT<"trunc.w.s", FGR32Opnd,
+                                                  FGR32Opnd, II_TRUNC>,
+                       ROUND_W_FM_MM<0, 0xac>, ISA_MICROMIPS;
+    def CEIL_W_S_MM  : MMRel, ABSS_FT<"ceil.w.s", FGR32Opnd, FGR32Opnd, II_CEIL>,
+                       ROUND_W_FM_MM<0, 0x6c>, ISA_MICROMIPS;
+    let Uses = [FCR31] in
+    def FSQRT_S_MM : MMRel, ABSS_FT<"sqrt.s", FGR32Opnd, FGR32Opnd, II_SQRT_S,
+                                   fsqrt>, ROUND_W_FM_MM<0, 0x28>, ISA_MICROMIPS;
+  }
 
-  def FSQRT_S_MM : MMRel, ABSS_FT<"sqrt.s", FGR32Opnd, FGR32Opnd, II_SQRT_S,
-                                  fsqrt>, ROUND_W_FM_MM<0, 0x28>, ISA_MICROMIPS;
 
   def MTHC1_D32_MM : MMRel,
                      MTC1_64_FT<"mthc1", AFGR64Opnd, GPR32Opnd, II_MTHC1>,
@@ -251,30 +261,33 @@ let DecoderNamespace = "MicroMips" in {
                 MFC1_FM_MM<0x40>, ISA_MICROMIPS;
   def CTC1_MM : MMRel, MTC1_FT<"ctc1", CCROpnd, GPR32Opnd, II_CTC1>,
                 MFC1_FM_MM<0x60>, ISA_MICROMIPS;
-  def RECIP_S_MM : MMRel, ABSS_FT<"recip.s", FGR32Opnd, FGR32Opnd,
+
+  let mayRaiseFPException = 1, Uses = [FCR31] in {
+    def RECIP_S_MM : MMRel, ABSS_FT<"recip.s", FGR32Opnd, FGR32Opnd,
+                                      II_RECIP_S>,
+                       ROUND_W_FM_MM<0b0, 0b01001000>, ISA_MICROMIPS;
+    def RECIP_D32_MM : MMRel, ABSS_FT<"recip.d", AFGR64Opnd, AFGR64Opnd,
+                                      II_RECIP_D>,
+                       ROUND_W_FM_MM<0b1, 0b01001000>, ISA_MICROMIPS, FGR_32 {
+      let BaseOpcode = "RECIP_D32";
+    }
+    let DecoderNamespace = "MicroMipsFP64" in
+      def RECIP_D64_MM : MMRel, ABSS_FT<"recip.d", FGR64Opnd, FGR64Opnd,
+                                        II_RECIP_D>,
+                       ROUND_W_FM_MM<0b1, 0b01001000>, ISA_MICROMIPS, FGR_64;
+    def RSQRT_S_MM : MMRel, ABSS_FT<"rsqrt.s", FGR32Opnd, FGR32Opnd,
                                     II_RECIP_S>,
-                     ROUND_W_FM_MM<0b0, 0b01001000>, ISA_MICROMIPS;
-  def RECIP_D32_MM : MMRel, ABSS_FT<"recip.d", AFGR64Opnd, AFGR64Opnd,
+                     ROUND_W_FM_MM<0b0, 0b00001000>, ISA_MICROMIPS;
+    def RSQRT_D32_MM : MMRel, ABSS_FT<"rsqrt.d", AFGR64Opnd, AFGR64Opnd,
                                     II_RECIP_D>,
-                     ROUND_W_FM_MM<0b1, 0b01001000>, ISA_MICROMIPS, FGR_32 {
-    let BaseOpcode = "RECIP_D32";
+                     ROUND_W_FM_MM<0b1, 0b00001000>, ISA_MICROMIPS, FGR_32 {
+      let BaseOpcode = "RSQRT_D32";
+    }
+    let DecoderNamespace = "MicroMipsFP64" in
+      def RSQRT_D64_MM : MMRel, ABSS_FT<"rsqrt.d", FGR64Opnd, FGR64Opnd,
+                                        II_RECIP_D>,
+                         ROUND_W_FM_MM<0b1, 0b00001000>, ISA_MICROMIPS, FGR_64;
   }
-  let DecoderNamespace = "MicroMipsFP64" in
-    def RECIP_D64_MM : MMRel, ABSS_FT<"recip.d", FGR64Opnd, FGR64Opnd,
-                                      II_RECIP_D>,
-                     ROUND_W_FM_MM<0b1, 0b01001000>, ISA_MICROMIPS, FGR_64;
-  def RSQRT_S_MM : MMRel, ABSS_FT<"rsqrt.s", FGR32Opnd, FGR32Opnd,
-                                  II_RECIP_S>,
-                   ROUND_W_FM_MM<0b0, 0b00001000>, ISA_MICROMIPS;
-  def RSQRT_D32_MM : MMRel, ABSS_FT<"rsqrt.d", AFGR64Opnd, AFGR64Opnd,
-                                  II_RECIP_D>,
-                   ROUND_W_FM_MM<0b1, 0b00001000>, ISA_MICROMIPS, FGR_32 {
-    let BaseOpcode = "RSQRT_D32";
-  }
-  let DecoderNamespace = "MicroMipsFP64" in
-    def RSQRT_D64_MM : MMRel, ABSS_FT<"rsqrt.d", FGR64Opnd, FGR64Opnd,
-                                      II_RECIP_D>,
-                       ROUND_W_FM_MM<0b1, 0b00001000>, ISA_MICROMIPS, FGR_64;
 }
 
 let DecoderNamespace = "MicroMips",  DecoderMethod = "DecodeFMemMMR2" in {
@@ -342,39 +355,41 @@ multiclass C_COND_MM<string TypeStr, RegisterOperand RC, bits<2> fmt,
                         C_COND_FM_MM<fmt, 7> {
     let BaseOpcode = "c.ule."#NAME;
   }
-  def C_SF_#NAME#_MM : MMRel, C_COND_FT<"sf", TypeStr, RC, itin>,
-                       C_COND_FM_MM<fmt, 8> {
-    let BaseOpcode = "c.sf."#NAME;
-    let isCommutable = 1;
-  }
-  def C_NGLE_#NAME#_MM : MMRel, C_COND_FT<"ngle", TypeStr, RC, itin>,
-                         C_COND_FM_MM<fmt, 9> {
-    let BaseOpcode = "c.ngle."#NAME;
-  }
-  def C_SEQ_#NAME#_MM : MMRel, C_COND_FT<"seq", TypeStr, RC, itin>,
-                        C_COND_FM_MM<fmt, 10> {
-    let BaseOpcode = "c.seq."#NAME;
-    let isCommutable = 1;
-  }
-  def C_NGL_#NAME#_MM : MMRel, C_COND_FT<"ngl", TypeStr, RC, itin>,
-                        C_COND_FM_MM<fmt, 11> {
-    let BaseOpcode = "c.ngl."#NAME;
-  }
-  def C_LT_#NAME#_MM : MMRel, C_COND_FT<"lt", TypeStr, RC, itin>,
-                       C_COND_FM_MM<fmt, 12> {
-    let BaseOpcode = "c.lt."#NAME;
-  }
-  def C_NGE_#NAME#_MM : MMRel, C_COND_FT<"nge", TypeStr, RC, itin>,
-                        C_COND_FM_MM<fmt, 13> {
-    let BaseOpcode = "c.nge."#NAME;
-  }
-  def C_LE_#NAME#_MM : MMRel, C_COND_FT<"le", TypeStr, RC, itin>,
-                       C_COND_FM_MM<fmt, 14> {
-    let BaseOpcode = "c.le."#NAME;
-  }
-  def C_NGT_#NAME#_MM : MMRel, C_COND_FT<"ngt", TypeStr, RC, itin>,
-                        C_COND_FM_MM<fmt, 15> {
-    let BaseOpcode = "c.ngt."#NAME;
+  let mayRaiseFPException = 1 in {
+    def C_SF_#NAME#_MM : MMRel, C_COND_FT<"sf", TypeStr, RC, itin>,
+                         C_COND_FM_MM<fmt, 8> {
+      let BaseOpcode = "c.sf."#NAME;
+      let isCommutable = 1;
+    }
+    def C_NGLE_#NAME#_MM : MMRel, C_COND_FT<"ngle", TypeStr, RC, itin>,
+                           C_COND_FM_MM<fmt, 9> {
+      let BaseOpcode = "c.ngle."#NAME;
+    }
+    def C_SEQ_#NAME#_MM : MMRel, C_COND_FT<"seq", TypeStr, RC, itin>,
+                          C_COND_FM_MM<fmt, 10> {
+      let BaseOpcode = "c.seq."#NAME;
+      let isCommutable = 1;
+    }
+    def C_NGL_#NAME#_MM : MMRel, C_COND_FT<"ngl", TypeStr, RC, itin>,
+                          C_COND_FM_MM<fmt, 11> {
+      let BaseOpcode = "c.ngl."#NAME;
+    }
+    def C_LT_#NAME#_MM : MMRel, C_COND_FT<"lt", TypeStr, RC, itin>,
+                         C_COND_FM_MM<fmt, 12> {
+      let BaseOpcode = "c.lt."#NAME;
+    }
+    def C_NGE_#NAME#_MM : MMRel, C_COND_FT<"nge", TypeStr, RC, itin>,
+                          C_COND_FM_MM<fmt, 13> {
+      let BaseOpcode = "c.nge."#NAME;
+    }
+    def C_LE_#NAME#_MM : MMRel, C_COND_FT<"le", TypeStr, RC, itin>,
+                         C_COND_FM_MM<fmt, 14> {
+      let BaseOpcode = "c.le."#NAME;
+    }
+    def C_NGT_#NAME#_MM : MMRel, C_COND_FT<"ngt", TypeStr, RC, itin>,
+                          C_COND_FM_MM<fmt, 15> {
+      let BaseOpcode = "c.ngt."#NAME;
+    }
   }
 }
 let DecoderNamespace = "MicroMips" in {
diff --git a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td
index fead376b8c338..853da4c23db2b 100644
--- a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td
+++ b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td
@@ -265,46 +265,48 @@ multiclass CMP_CC_M <FIELD_CMP_FORMAT Format, string Typestr,
                                             setule>,
                         MipsR6Arch<!strconcat("cmp.ule.", Typestr)>,
                         ISA_MIPS32R6, HARDFLOAT;
-    def CMP_SAF_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
-                                                     FIELD_CMP_COND_SAF>,
-                        CMP_CONDN_DESC_BASE<"saf", Typestr, FGROpnd, Itin>,
-                        MipsR6Arch<!strconcat("cmp.saf.", Typestr)>,
-                        ISA_MIPS32R6, HARDFLOAT;
-    def CMP_SUN_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
-                                                     FIELD_CMP_COND_SUN>,
-                        CMP_CONDN_DESC_BASE<"sun", Typestr, FGROpnd, Itin>,
-                        MipsR6Arch<!strconcat("cmp.sun.", Typestr)>,
-                        ISA_MIPS32R6, HARDFLOAT;
-    def CMP_SEQ_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
-                                                     FIELD_CMP_COND_SEQ>,
-                        CMP_CONDN_DESC_BASE<"seq", Typestr, FGROpnd, Itin>,
-                        MipsR6Arch<!strconcat("cmp.seq.", Typestr)>,
-                        ISA_MIPS32R6, HARDFLOAT;
-    def CMP_SUEQ_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
-                                                      FIELD_CMP_COND_SUEQ>,
-                         CMP_CONDN_DESC_BASE<"sueq", Typestr, FGROpnd, Itin>,
-                         MipsR6Arch<!strconcat("cmp.sueq.", Typestr)>,
-                         ISA_MIPS32R6, HARDFLOAT;
-    def CMP_SLT_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
-                                                     FIELD_CMP_COND_SLT>,
-                        CMP_CONDN_DESC_BASE<"slt", Typestr, FGROpnd, Itin>,
-                        MipsR6Arch<!strconcat("cmp.slt.", Typestr)>,
-                        ISA_MIPS32R6, HARDFLOAT;
-    def CMP_SULT_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
-                                                      FIELD_CMP_COND_SULT>,
-                         CMP_CONDN_DESC_BASE<"sult", Typestr, FGROpnd, Itin>,
-                         MipsR6Arch<!strconcat("cmp.sult.", Typestr)>,
-                         ISA_MIPS32R6, HARDFLOAT;
-    def CMP_SLE_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
-                                                     FIELD_CMP_COND_SLE>,
-                        CMP_CONDN_DESC_BASE<"sle", Typestr, FGROpnd, Itin>,
-                        MipsR6Arch<!strconcat("cmp.sle.", Typestr)>,
-                        ISA_MIPS32R6, HARDFLOAT;
-    def CMP_SULE_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
-                                                      FIELD_CMP_COND_SULE>,
-                         CMP_CONDN_DESC_BASE<"sule", Typestr, FGROpnd, Itin>,
-                         MipsR6Arch<!strconcat("cmp.sule.", Typestr)>,
-                         ISA_MIPS32R6, HARDFLOAT;
+    let mayRaiseFPException = 1 in { 
+      def CMP_SAF_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
+                                                       FIELD_CMP_COND_SAF>,
+                          CMP_CONDN_DESC_BASE<"saf", Typestr, FGROpnd, Itin>,
+                          MipsR6Arch<!strconcat("cmp.saf.", Typestr)>,
+                          ISA_MIPS32R6, HARDFLOAT;
+      def CMP_SUN_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
+                                                       FIELD_CMP_COND_SUN>,
+                          CMP_CONDN_DESC_BASE<"sun", Typestr, FGROpnd, Itin>,
+                          MipsR6Arch<!strconcat("cmp.sun.", Typestr)>,
+                          ISA_MIPS32R6, HARDFLOAT;
+      def CMP_SEQ_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
+                                                       FIELD_CMP_COND_SEQ>,
+                          CMP_CONDN_DESC_BASE<"seq", Typestr, FGROpnd, Itin>,
+                          MipsR6Arch<!strconcat("cmp.seq.", Typestr)>,
+                          ISA_MIPS32R6, HARDFLOAT;
+      def CMP_SUEQ_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
+                                                        FIELD_CMP_COND_SUEQ>,
+                           CMP_CONDN_DESC_BASE<"sueq", Typestr, FGROpnd, Itin>,
+                           MipsR6Arch<!strconcat("cmp.sueq.", Typestr)>,
+                           ISA_MIPS32R6, HARDFLOAT;
+      def CMP_SLT_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
+                                                       FIELD_CMP_COND_SLT>,
+                          CMP_CONDN_DESC_BASE<"slt", Typestr, FGROpnd, Itin>,
+                          MipsR6Arch<!strconcat("cmp.slt.", Typestr)>,
+                          ISA_MIPS32R6, HARDFLOAT;
+      def CMP_SULT_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
+                                                        FIELD_CMP_COND_SULT>,
+                           CMP_CONDN_DESC_BASE<"sult", Typestr, FGROpnd, Itin>,
+                           MipsR6Arch<!strconcat("cmp.sult.", Typestr)>,
+                           ISA_MIPS32R6, HARDFLOAT;
+      def CMP_SLE_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
+                                                       FIELD_CMP_COND_SLE>,
+                          CMP_CONDN_DESC_BASE<"sle", Typestr, FGROpnd, Itin>,
+                          MipsR6Arch<!strconcat("cmp.sle.", Typestr)>,
+                          ISA_MIPS32R6, HARDFLOAT;
+      def CMP_SULE_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
+                                                        FIELD_CMP_COND_SULE>,
+                           CMP_CONDN_DESC_BASE<"sule", Typestr, FGROpnd, Itin>,
+                           MipsR6Arch<!strconcat("cmp.sule.", Typestr)>,
+                           ISA_MIPS32R6, HARDFLOAT;
+    }
   }
 }
 
@@ -941,32 +943,38 @@ let AdditionalPredicates = [NotInMicroMips] in {
 }
 def LWPC : R6MMR6Rel, LWPC_ENC, LWPC_DESC, ISA_MIPS32R6;
 let AdditionalPredicates = [NotInMicroMips] in {
-  def MADDF_S : MADDF_S_ENC, MADDF_S_DESC, ISA_MIPS32R6, HARDFLOAT;
-  def MADDF_D : MADDF_D_ENC, MADDF_D_DESC, ISA_MIPS32R6, HARDFLOAT;
-  def MAXA_D : MAXA_D_ENC, MAXA_D_DESC, ISA_MIPS32R6, HARDFLOAT;
-  def MAXA_S : MAXA_S_ENC, MAXA_S_DESC, ISA_MIPS32R6, HARDFLOAT;
-  def MAX_D : MAX_D_ENC, MAX_D_DESC, ISA_MIPS32R6, HARDFLOAT;
-  def MAX_S : MAX_S_ENC, MAX_S_DESC, ISA_MIPS32R6, HARDFLOAT;
-  def MINA_D : MINA_D_ENC, MINA_D_DESC, ISA_MIPS32R6, HARDFLOAT;
-  def MINA_S : MINA_S_ENC, MINA_S_DESC, ISA_MIPS32R6, HARDFLOAT;
-  def MIN_D : MIN_D_ENC, MIN_D_DESC, ISA_MIPS32R6, HARDFLOAT;
-  def MIN_S : MIN_S_ENC, MIN_S_DESC, ISA_MIPS32R6, HARDFLOAT;
+  let mayRaiseFPException = 1 in {
+    let Uses = [FCR31] in {
+      def MADDF_S : MADDF_S_ENC, MADDF_S_DESC, ISA_MIPS32R6, HARDFLOAT;
+      def MADDF_D : MADDF_D_ENC, MADDF_D_DESC, ISA_MIPS32R6, HARDFLOAT;
+      def MSUBF_S : MSUBF_S_ENC, MSUBF_S_DESC, ISA_MIPS32R6, HARDFLOAT;
+      def MSUBF_D : MSUBF_D_ENC, MSUBF_D_DESC, ISA_MIPS32R6, HARDFLOAT;
+    }
+
+    def MAXA_D : MAXA_D_ENC, MAXA_D_DESC, ISA_MIPS32R6, HARDFLOAT;
+    def MAXA_S : MAXA_S_ENC, MAXA_S_DESC, ISA_MIPS32R6, HARDFLOAT;
+    def MAX_D : MAX_D_ENC, MAX_D_DESC, ISA_MIPS32R6, HARDFLOAT;
+    def MAX_S : MAX_S_ENC, MAX_S_DESC, ISA_MIPS32R6, HARDFLOAT;
+    def MINA_D : MINA_D_ENC, MINA_D_DESC, ISA_MIPS32R6, HARDFLOAT;
+    def MINA_S : MINA_S_ENC, MINA_S_DESC, ISA_MIPS32R6, HARDFLOAT;
+    def MIN_D : MIN_D_ENC, MIN_D_DESC, ISA_MIPS32R6, HARDFLOAT;
+    def MIN_S : MIN_S_ENC, MIN_S_DESC, ISA_MIPS32R6, HARDFLOAT;
+  }
 
   def MOD : R6MMR6Rel, MOD_ENC, MOD_DESC, ISA_MIPS32R6;
   def MODU : R6MMR6Rel, MODU_ENC, MODU_DESC, ISA_MIPS32R6;
-
-  def MSUBF_S : MSUBF_S_ENC, MSUBF_S_DESC, ISA_MIPS32R6, HARDFLOAT;
-  def MSUBF_D : MSUBF_D_ENC, MSUBF_D_DESC, ISA_MIPS32R6, HARDFLOAT;
-
   def MUH    : R6MMR6Rel, MUH_ENC, MUH_DESC, ISA_MIPS32R6;
   def MUHU   : R6MMR6Rel, MUHU_ENC, MUHU_DESC, ISA_MIPS32R6;
   def MUL_R6 : R6MMR6Rel, MUL_R6_ENC, MUL_R6_DESC, ISA_MIPS32R6;
   def MULU   : R6MMR6Rel, MULU_ENC, MULU_DESC, ISA_MIPS32R6;
 }
 let AdditionalPredicates = [NotInMicroMips] in {
+  let mayRaiseFPException = 1, Uses = [FCR31] in {
+    def RINT_D : RINT_D_ENC, RINT_D_DESC, ISA_MIPS32R6, HARDFLOAT;
+    def RINT_S : RINT_S_ENC, RINT_S_DESC, ISA_MIPS32R6, HARDFLOAT;
+  }
+
   def PREF_R6 : R6MMR6Rel, PREF_ENC, PREF_DESC, ISA_MIPS32R6;
-  def RINT_D : RINT_D_ENC, RINT_D_DESC, ISA_MIPS32R6, HARDFLOAT;
-  def RINT_S : RINT_S_ENC, RINT_S_DESC, ISA_MIPS32R6, HARDFLOAT;
   def SC_R6 : SC_R6_ENC, SC_R6_DESC, PTR_32, ISA_MIPS32R6;
   def SDBBP_R6 : SDBBP_R6_ENC, SDBBP_R6_DESC, ISA_MIPS32R6;
   def SELEQZ : R6MMR6Rel, SELEQZ_ENC, SELEQZ_DESC, ISA_MIPS32R6, GPR_32;
diff --git a/llvm/lib/Target/Mips/MipsInstrFPU.td b/llvm/lib/Target/Mips/MipsInstrFPU.td
index c065ba6c9632e..a9d8af1418be9 100644
--- a/llvm/lib/Target/Mips/MipsInstrFPU.td
+++ b/llvm/lib/Target/Mips/MipsInstrFPU.td
@@ -142,6 +142,7 @@ class CVT_PS_S_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC,
   let isCommutable = IsComm;
 }
 
+let mayRaiseFPException = 1, Uses = [FCR31] in
 multiclass ABSS_M<string opstr, InstrItinClass Itin,
                   SDPatternOperator OpNode= null_frag> {
   def _D32 : MMRel, ABSS_FT<opstr, AFGR64Opnd, AFGR64Opnd, Itin, OpNode>,
@@ -318,39 +319,49 @@ multiclass C_COND_M<string TypeStr, RegisterOperand RC, bits<5> fmt,
                      C_COND_FM<fmt, 7> {
     let BaseOpcode = "c.ule."#NAME;
   }
-  def C_SF_#NAME : MMRel, C_COND_FT<"sf", TypeStr, RC, itin>,
-                   C_COND_FM<fmt, 8> {
-    let BaseOpcode = "c.sf."#NAME;
-    let isCommutable = 1;
-  }
-  def C_NGLE_#NAME : MMRel, C_COND_FT<"ngle", TypeStr, RC, itin>,
-                     C_COND_FM<fmt, 9> {
-    let BaseOpcode = "c.ngle."#NAME;
-  }
-  def C_SEQ_#NAME : MMRel, C_COND_FT<"seq", TypeStr, RC, itin>,
-                    C_COND_FM<fmt, 10> {
-    let BaseOpcode = "c.seq."#NAME;
-    let isCommutable = 1;
-  }
-  def C_NGL_#NAME : MMRel, C_COND_FT<"ngl", TypeStr, RC, itin>,
-                    C_COND_FM<fmt, 11> {
-    let BaseOpcode = "c.ngl."#NAME;
-  }
-  def C_LT_#NAME : MMRel, C_COND_FT<"lt", TypeStr, RC, itin>,
-                   C_COND_FM<fmt, 12> {
-    let BaseOpcode = "c.lt."#NAME;
-  }
-  def C_NGE_#NAME : MMRel, C_COND_FT<"nge", TypeStr, RC, itin>,
-                    C_COND_FM<fmt, 13> {
-    let BaseOpcode = "c.nge."#NAME;
-  }
-  def C_LE_#NAME : MMRel, C_COND_FT<"le", TypeStr, RC, itin>,
-                   C_COND_FM<fmt, 14> {
-    let BaseOpcode = "c.le."#NAME;
-  }
-  def C_NGT_#NAME : MMRel, C_COND_FT<"ngt", TypeStr, RC, itin>,
-                    C_COND_FM<fmt, 15> {
-    let BaseOpcode = "c.ngt."#NAME;
+  let mayRaiseFPException = 1 in {
+    def C_SF_#NAME : MMRel, C_COND_FT<"sf", TypeStr, RC, itin>,
+                     C_COND_FM<fmt, 8> {
+      let BaseOpcode = "c.sf."#NAME;
+      let isCommutable = 1;
+      let mayRaiseFPException = 1;
+    }
+    def C_NGLE_#NAME : MMRel, C_COND_FT<"ngle", TypeStr, RC, itin>,
+                       C_COND_FM<fmt, 9> {
+      let BaseOpcode = "c.ngle."#NAME;
+      let mayRaiseFPException = 1;
+    }
+    def C_SEQ_#NAME : MMRel, C_COND_FT<"seq", TypeStr, RC, itin>,
+                      C_COND_FM<fmt, 10> {
+      let BaseOpcode = "c.seq."#NAME;
+      let isCommutable = 1;
+      let mayRaiseFPException = 1;
+    }
+    def C_NGL_#NAME : MMRel, C_COND_FT<"ngl", TypeStr, RC, itin>,
+                      C_COND_FM<fmt, 11> {
+      let BaseOpcode = "c.ngl."#NAME;
+      let mayRaiseFPException = 1;
+    }
+    def C_LT_#NAME : MMRel, C_COND_FT<"lt", TypeStr, RC, itin>,
+                     C_COND_FM<fmt, 12> {
+      let BaseOpcode = "c.lt."#NAME;
+      let mayRaiseFPException = 1;
+    }
+    def C_NGE_#NAME : MMRel, C_COND_FT<"nge", TypeStr, RC, itin>,
+                      C_COND_FM<fmt, 13> {
+      let BaseOpcode = "c.nge."#NAME;
+      let mayRaiseFPException = 1;
+    }
+    def C_LE_#NAME : MMRel, C_COND_FT<"le", TypeStr, RC, itin>,
+                     C_COND_FM<fmt, 14> {
+      let BaseOpcode = "c.le."#NAME;
+      let mayRaiseFPException = 1;
+    }
+    def C_NGT_#NAME : MMRel, C_COND_FT<"ngt", TypeStr, RC, itin>,
+                      C_COND_FM<fmt, 15> {
+      let BaseOpcode = "c.ngt."#NAME;
+      let mayRaiseFPException = 1;
+    }
   }
 }
 
@@ -365,7 +376,7 @@ defm D64 : C_COND_M<"d", FGR64Opnd, 17, II_C_CC_D>, ISA_MIPS1_NOT_32R6_64R6,
 //===----------------------------------------------------------------------===//
 // Floating Point Instructions
 //===----------------------------------------------------------------------===//
-let AdditionalPredicates = [NotInMicroMips] in {
+let AdditionalPredicates = [NotInMicroMips], mayRaiseFPException = 1 in {
   def ROUND_W_S : MMRel, StdMMR6Rel,
                   ABSS_FT<"round.w.s", FGR32Opnd, FGR32Opnd, II_ROUND>,
                   ABSS_FM<0xc, 16>, ISA_MIPS2;
@@ -379,16 +390,19 @@ let AdditionalPredicates = [NotInMicroMips] in {
   def FLOOR_W_S : MMRel, StdMMR6Rel,
                   ABSS_FT<"floor.w.s", FGR32Opnd, FGR32Opnd, II_FLOOR>,
                   ABSS_FM<0xf, 16>, ISA_MIPS2;
-  def CVT_W_S   : MMRel, ABSS_FT<"cvt.w.s", FGR32Opnd, FGR32Opnd, II_CVT>,
-                  ABSS_FM<0x24, 16>, ISA_MIPS1;
 
   defm TRUNC_W : ROUND_M<"trunc.w.d", II_TRUNC>, ABSS_FM<0xd, 17>, ISA_MIPS2;
   defm CEIL_W  : ROUND_M<"ceil.w.d", II_CEIL>, ABSS_FM<0xe, 17>, ISA_MIPS2;
   defm FLOOR_W : ROUND_M<"floor.w.d", II_FLOOR>, ABSS_FM<0xf, 17>, ISA_MIPS2;
-  defm CVT_W   : ROUND_M<"cvt.w.d", II_CVT>, ABSS_FM<0x24, 17>, ISA_MIPS1;
+
+  let Uses = [FCR31] in {
+    def CVT_W_S   : MMRel, ABSS_FT<"cvt.w.s", FGR32Opnd, FGR32Opnd, II_CVT>, // fp
+                    ABSS_FM<0x24, 16>, ISA_MIPS1;
+    defm CVT_W   : ROUND_M<"cvt.w.d", II_CVT>, ABSS_FM<0x24, 17>, ISA_MIPS1;
+  }
 }
 
-let AdditionalPredicates = [NotInMicroMips] in {
+let AdditionalPredicates = [NotInMicroMips], mayRaiseFPException = 1, Uses = [FCR31] in {
   def RECIP_S : MMRel, ABSS_FT<"recip.s", FGR32Opnd, FGR32Opnd, II_RECIP_S>,
                 ABSS_FM<0b010101, 0x10>, INSN_MIPS4_32R2;
   def RECIP_D32 : MMRel, ABSS_FT<"recip.d", AFGR64Opnd, AFGR64Opnd, II_RECIP_D>,
@@ -410,7 +424,8 @@ let AdditionalPredicates = [NotInMicroMips] in {
                                    II_RSQRT_D>, ABSS_FM<0b010110, 0x11>,
                     INSN_MIPS4_32R2, FGR_64;
 }
-let DecoderNamespace = "MipsFP64" in {
+
+let DecoderNamespace = "MipsFP64", mayRaiseFPException = 1 in {
   let AdditionalPredicates = [NotInMicroMips] in {
   def ROUND_L_S : ABSS_FT<"round.l.s", FGR64Opnd, FGR32Opnd, II_ROUND>,
                   ABSS_FM<0x8, 16>, ISA_MIPS2, FGR_64;
@@ -431,7 +446,7 @@ let DecoderNamespace = "MipsFP64" in {
   }
 }
 
-let AdditionalPredicates = [NotInMicroMips] in{
+let AdditionalPredicates = [NotInMicroMips], mayRaiseFPException = 1, Uses = [FCR31] in{
   def CVT_S_W : MMRel, ABSS_FT<"cvt.s.w", FGR32Opnd, FGR32Opnd, II_CVT>,
                 ABSS_FM<0x20, 20>, ISA_MIPS1;
   def CVT_L_S : MMRel, ABSS_FT<"cvt.l.s", FGR64Opnd, FGR32Opnd, II_CVT>,
@@ -440,7 +455,7 @@ let AdditionalPredicates = [NotInMicroMips] in{
                  ABSS_FM<0x25, 17>, INSN_MIPS3_32R2;
 }
 
-let AdditionalPredicates = [NotInMicroMips] in {
+let AdditionalPredicates = [NotInMicroMips], mayRaiseFPException = 1, Uses = [FCR31] in {
   def CVT_S_D32 : MMRel, ABSS_FT<"cvt.s.d", FGR32Opnd, AFGR64Opnd, II_CVT>,
                   ABSS_FM<0x20, 17>, ISA_MIPS1, FGR_32;
   def CVT_D32_S : MMRel, ABSS_FT<"cvt.d.s", AFGR64Opnd, FGR32Opnd, II_CVT>,
@@ -449,44 +464,43 @@ let AdditionalPredicates = [NotInMicroMips] in {
                   ABSS_FM<0x21, 20>, ISA_MIPS1, FGR_32;
 }
 
-let DecoderNamespace = "MipsFP64" in {
-  let AdditionalPredicates = [NotInMicroMips] in {
+let DecoderNamespace = "MipsFP64", AdditionalPredicates = [NotInMicroMips] in {
+  let mayRaiseFPException = 1, Uses = [FCR31] in {
     def FADD_PS64   : ADDS_FT<"add.ps", FGR64Opnd, II_ADD_PS, 0>,
                       ADDS_FM<0x0, 22>,
                       ISA_MIPS32R2_NOT_32R6_64R6, FGR_64;
     def FMUL_PS64   : ADDS_FT<"mul.ps", FGR64Opnd, II_MUL_PS, 0>,
                       ADDS_FM<0x2, 22>,
                       ISA_MIPS32R2_NOT_32R6_64R6, FGR_64;
-    def PLL_PS64    : ADDS_FT<"pll.ps", FGR64Opnd, II_CVT, 0>,
-                      ADDS_FM<0x2C, 22>,
-                      ISA_MIPS32R2_NOT_32R6_64R6, FGR_64;
-    def PLU_PS64    : ADDS_FT<"plu.ps", FGR64Opnd, II_CVT, 0>,
-                      ADDS_FM<0x2D, 22>,
-                      ISA_MIPS32R2_NOT_32R6_64R6, FGR_64;
-    def PUL_PS64    : ADDS_FT<"pul.ps", FGR64Opnd, II_CVT, 0>,
-                      ADDS_FM<0x2E, 22>,
-                      ISA_MIPS32R2_NOT_32R6_64R6, FGR_64;
-    def PUU_PS64    : ADDS_FT<"puu.ps", FGR64Opnd, II_CVT, 0>,
-                      ADDS_FM<0x2F, 22>,
-                      ISA_MIPS32R2_NOT_32R6_64R6, FGR_64;
     def FSUB_PS64   : ADDS_FT<"sub.ps", FGR64Opnd, II_SUB_PS, 0>,
                       ADDS_FM<0x1, 22>,
                       ISA_MIPS32R2_NOT_32R6_64R6, FGR_64;
-
-    def CVT_S_PU64  : ABSS_FT<"cvt.s.pu", FGR32Opnd, FGR64Opnd, II_CVT>,
-                      ABSS_FM<0x20, 22>,
-                      ISA_MIPS32R2_NOT_32R6_64R6, FGR_64;
-    def CVT_S_PL64  : ABSS_FT<"cvt.s.pl", FGR32Opnd, FGR64Opnd, II_CVT>,
-                      ABSS_FM<0x28, 22>,
-                      ISA_MIPS32R2_NOT_32R6_64R6, FGR_64;
-
     def CVT_PS_S64  : CVT_PS_S_FT<"cvt.ps.s", FGR64Opnd, FGR32Opnd, II_CVT, 0>,
                       ADDS_FM<0x26, 16>,
                       ISA_MIPS32R2_NOT_32R6_64R6, FGR_64;
   }
+
+  def PLL_PS64    : ADDS_FT<"pll.ps", FGR64Opnd, II_CVT, 0>,
+                    ADDS_FM<0x2C, 22>,
+                    ISA_MIPS32R2_NOT_32R6_64R6, FGR_64;
+  def PLU_PS64    : ADDS_FT<"plu.ps", FGR64Opnd, II_CVT, 0>,
+                    ADDS_FM<0x2D, 22>,
+                    ISA_MIPS32R2_NOT_32R6_64R6, FGR_64;
+  def PUL_PS64    : ADDS_FT<"pul.ps", FGR64Opnd, II_CVT, 0>,
+                    ADDS_FM<0x2E, 22>,
+                    ISA_MIPS32R2_NOT_32R6_64R6, FGR_64;
+  def PUU_PS64    : ADDS_FT<"puu.ps", FGR64Opnd, II_CVT, 0>,
+                    ADDS_FM<0x2F, 22>,
+                    ISA_MIPS32R2_NOT_32R6_64R6, FGR_64;
+  def CVT_S_PU64  : ABSS_FT<"cvt.s.pu", FGR32Opnd, FGR64Opnd, II_CVT>,
+                    ABSS_FM<0x20, 22>,
+                    ISA_MIPS32R2_NOT_32R6_64R6, FGR_64;
+  def CVT_S_PL64  : ABSS_FT<"cvt.s.pl", FGR32Opnd, FGR64Opnd, II_CVT>,
+                    ABSS_FM<0x28, 22>,
+                    ISA_MIPS32R2_NOT_32R6_64R6, FGR_64;
 }
 
-let DecoderNamespace = "MipsFP64" in {
+let DecoderNamespace = "MipsFP64", mayRaiseFPException = 1, Uses = [FCR31] in {
   let AdditionalPredicates = [HasMips3D] in {
     def ADDR_PS64   : ADDS_FT<"addr.ps", FGR64Opnd, II_ADDR_PS, 0>,
                       ADDS_FM<0x18, 22>, ISA_MIPS32R2_NOT_32R6_64R6, FGR_64;
@@ -501,7 +515,7 @@ let DecoderNamespace = "MipsFP64" in {
   }
 }
 
-let DecoderNamespace = "MipsFP64" in {
+let DecoderNamespace = "MipsFP64", mayRaiseFPException = 1, Uses = [FCR31] in {
   let AdditionalPredicates = [NotInMicroMips] in {
     def CVT_S_L   : ABSS_FT<"cvt.s.l", FGR32Opnd, FGR64Opnd, II_CVT>,
                     ABSS_FM<0x20, 21>, INSN_MIPS3_32R2, FGR_64;
@@ -536,7 +550,7 @@ let AdditionalPredicates = [NotInMicroMips] in {
   defm FNEG : ABSS_M<"neg.d", II_NEG, fneg>, ABSS_FM<0x7, 17>, ISA_MIPS1;
 }
 
-let AdditionalPredicates = [NotInMicroMips] in {
+let AdditionalPredicates = [NotInMicroMips], mayRaiseFPException = 1, Uses = [FCR31] in {
   def FSQRT_S : MMRel, StdMMR6Rel, ABSS_FT<"sqrt.s", FGR32Opnd, FGR32Opnd,
                 II_SQRT_S, any_fsqrt>, ABSS_FM<0x4, 16>, ISA_MIPS2;
   defm FSQRT : ABSS_M<"sqrt.d", II_SQRT_D, any_fsqrt>, ABSS_FM<0x4, 17>, ISA_MIPS2;
@@ -659,7 +673,7 @@ let AdditionalPredicates = [NotInMicroMips],
 }
 
 /// Floating-point Arithmetic
-let AdditionalPredicates = [NotInMicroMips] in {
+let AdditionalPredicates = [NotInMicroMips], mayRaiseFPException = 1, Uses = [FCR31] in {
   def FADD_S : MMRel, ADDS_FT<"add.s", FGR32Opnd, II_ADD_S, 1, any_fadd>,
                ADDS_FM<0x00, 16>, ISA_MIPS1;
   defm FADD :  ADDS_M<"add.d", II_ADD_D, 1, any_fadd>, ADDS_FM<0x00, 17>,
@@ -678,7 +692,7 @@ let AdditionalPredicates = [NotInMicroMips] in {
                ISA_MIPS1;
 }
 
-let AdditionalPredicates = [NotInMicroMips, HasMadd4] in {
+let AdditionalPredicates = [NotInMicroMips, HasMadd4], mayRaiseFPException = 1, Uses = [FCR31] in {
   def MADD_S : MMRel, MADDS_FT<"madd.s", FGR32Opnd, II_MADD_S, any_fadd>,
                MADDS_FM<4, 0>, INSN_MIPS4_32R2_NOT_32R6_64R6;
   def MSUB_S : MMRel, MADDS_FT<"msub.s", FGR32Opnd, II_MSUB_S, any_fsub>,
@@ -697,7 +711,7 @@ let AdditionalPredicates = [NotInMicroMips, HasMadd4] in {
   }
 }
 
-let AdditionalPredicates = [NoNaNsFPMath, HasMadd4, NotInMicroMips] in {
+let AdditionalPredicates = [NoNaNsFPMath, HasMadd4, NotInMicroMips], mayRaiseFPException = 1, Uses = [FCR31] in {
   def NMADD_S : MMRel, NMADDS_FT<"nmadd.s", FGR32Opnd, II_NMADD_S, any_fadd>,
                 MADDS_FM<6, 0>, INSN_MIPS4_32R2_NOT_32R6_64R6;
   def NMSUB_S : MMRel, NMADDS_FT<"nmsub.s", FGR32Opnd, II_NMSUB_S, any_fsub>,
diff --git a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
index 6ca587b1ba4d5..948d4db8585db 100644
--- a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
+++ b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
@@ -206,6 +206,8 @@ getReservedRegs(const MachineFunction &MF) const {
       }
     }
   }
+  // Reserve fp control and status register
+  Reserved.set(Mips::FCR31);
 
   // Reserve hardware registers.
   Reserved.set(Mips::HWR29);
diff --git a/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/float_arithmetic_operations.mir b/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/float_arithmetic_operations.mir
index 2654952dc28fc..77af724c76783 100644
--- a/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/float_arithmetic_operations.mir
+++ b/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/float_arithmetic_operations.mir
@@ -25,18 +25,21 @@ body:             |
 
     ; FP32-LABEL: name: float_add
     ; FP32: liveins: $f12, $f14
-    ; FP32: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
-    ; FP32: [[COPY1:%[0-9]+]]:fgr32 = COPY $f14
-    ; FP32: [[FADD_S:%[0-9]+]]:fgr32 = FADD_S [[COPY]], [[COPY1]]
-    ; FP32: $f0 = COPY [[FADD_S]]
-    ; FP32: RetRA implicit $f0
+    ; FP32-NEXT: {{  $}}
+    ; FP32-NEXT: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
+    ; FP32-NEXT: [[COPY1:%[0-9]+]]:fgr32 = COPY $f14
+    ; FP32-NEXT: [[FADD_S:%[0-9]+]]:fgr32 = nofpexcept FADD_S [[COPY]], [[COPY1]], implicit $fcr31
+    ; FP32-NEXT: $f0 = COPY [[FADD_S]]
+    ; FP32-NEXT: RetRA implicit $f0
+    ;
     ; FP64-LABEL: name: float_add
     ; FP64: liveins: $f12, $f14
-    ; FP64: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
-    ; FP64: [[COPY1:%[0-9]+]]:fgr32 = COPY $f14
-    ; FP64: [[FADD_S:%[0-9]+]]:fgr32 = FADD_S [[COPY]], [[COPY1]]
-    ; FP64: $f0 = COPY [[FADD_S]]
-    ; FP64: RetRA implicit $f0
+    ; FP64-NEXT: {{  $}}
+    ; FP64-NEXT: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
+    ; FP64-NEXT: [[COPY1:%[0-9]+]]:fgr32 = COPY $f14
+    ; FP64-NEXT: [[FADD_S:%[0-9]+]]:fgr32 = nofpexcept FADD_S [[COPY]], [[COPY1]], implicit $fcr31
+    ; FP64-NEXT: $f0 = COPY [[FADD_S]]
+    ; FP64-NEXT: RetRA implicit $f0
     %0:fprb(s32) = COPY $f12
     %1:fprb(s32) = COPY $f14
     %2:fprb(s32) = G_FADD %0, %1
@@ -56,18 +59,21 @@ body:             |
 
     ; FP32-LABEL: name: float_sub
     ; FP32: liveins: $f12, $f14
-    ; FP32: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
-    ; FP32: [[COPY1:%[0-9]+]]:fgr32 = COPY $f14
-    ; FP32: [[FSUB_S:%[0-9]+]]:fgr32 = FSUB_S [[COPY]], [[COPY1]]
-    ; FP32: $f0 = COPY [[FSUB_S]]
-    ; FP32: RetRA implicit $f0
+    ; FP32-NEXT: {{  $}}
+    ; FP32-NEXT: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
+    ; FP32-NEXT: [[COPY1:%[0-9]+]]:fgr32 = COPY $f14
+    ; FP32-NEXT: [[FSUB_S:%[0-9]+]]:fgr32 = nofpexcept FSUB_S [[COPY]], [[COPY1]], implicit $fcr31
+    ; FP32-NEXT: $f0 = COPY [[FSUB_S]]
+    ; FP32-NEXT: RetRA implicit $f0
+    ;
     ; FP64-LABEL: name: float_sub
     ; FP64: liveins: $f12, $f14
-    ; FP64: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
-    ; FP64: [[COPY1:%[0-9]+]]:fgr32 = COPY $f14
-    ; FP64: [[FSUB_S:%[0-9]+]]:fgr32 = FSUB_S [[COPY]], [[COPY1]]
-    ; FP64: $f0 = COPY [[FSUB_S]]
-    ; FP64: RetRA implicit $f0
+    ; FP64-NEXT: {{  $}}
+    ; FP64-NEXT: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
+    ; FP64-NEXT: [[COPY1:%[0-9]+]]:fgr32 = COPY $f14
+    ; FP64-NEXT: [[FSUB_S:%[0-9]+]]:fgr32 = nofpexcept FSUB_S [[COPY]], [[COPY1]], implicit $fcr31
+    ; FP64-NEXT: $f0 = COPY [[FSUB_S]]
+    ; FP64-NEXT: RetRA implicit $f0
     %0:fprb(s32) = COPY $f12
     %1:fprb(s32) = COPY $f14
     %2:fprb(s32) = G_FSUB %0, %1
@@ -87,18 +93,21 @@ body:             |
 
     ; FP32-LABEL: name: float_mul
     ; FP32: liveins: $f12, $f14
-    ; FP32: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
-    ; FP32: [[COPY1:%[0-9]+]]:fgr32 = COPY $f14
-    ; FP32: [[FMUL_S:%[0-9]+]]:fgr32 = FMUL_S [[COPY]], [[COPY1]]
-    ; FP32: $f0 = COPY [[FMUL_S]]
-    ; FP32: RetRA implicit $f0
+    ; FP32-NEXT: {{  $}}
+    ; FP32-NEXT: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
+    ; FP32-NEXT: [[COPY1:%[0-9]+]]:fgr32 = COPY $f14
+    ; FP32-NEXT: [[FMUL_S:%[0-9]+]]:fgr32 = nofpexcept FMUL_S [[COPY]], [[COPY1]], implicit $fcr31
+    ; FP32-NEXT: $f0 = COPY [[FMUL_S]]
+    ; FP32-NEXT: RetRA implicit $f0
+    ;
     ; FP64-LABEL: name: float_mul
     ; FP64: liveins: $f12, $f14
-    ; FP64: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
-    ; FP64: [[COPY1:%[0-9]+]]:fgr32 = COPY $f14
-    ; FP64: [[FMUL_S:%[0-9]+]]:fgr32 = FMUL_S [[COPY]], [[COPY1]]
-    ; FP64: $f0 = COPY [[FMUL_S]]
-    ; FP64: RetRA implicit $f0
+    ; FP64-NEXT: {{  $}}
+    ; FP64-NEXT: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
+    ; FP64-NEXT: [[COPY1:%[0-9]+]]:fgr32 = COPY $f14
+    ; FP64-NEXT: [[FMUL_S:%[0-9]+]]:fgr32 = nofpexcept FMUL_S [[COPY]], [[COPY1]], implicit $fcr31
+    ; FP64-NEXT: $f0 = COPY [[FMUL_S]]
+    ; FP64-NEXT: RetRA implicit $f0
     %0:fprb(s32) = COPY $f12
     %1:fprb(s32) = COPY $f14
     %2:fprb(s32) = G_FMUL %0, %1
@@ -118,18 +127,21 @@ body:             |
 
     ; FP32-LABEL: name: float_div
     ; FP32: liveins: $f12, $f14
-    ; FP32: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
-    ; FP32: [[COPY1:%[0-9]+]]:fgr32 = COPY $f14
-    ; FP32: [[FDIV_S:%[0-9]+]]:fgr32 = FDIV_S [[COPY]], [[COPY1]]
-    ; FP32: $f0 = COPY [[FDIV_S]]
-    ; FP32: RetRA implicit $f0
+    ; FP32-NEXT: {{  $}}
+    ; FP32-NEXT: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
+    ; FP32-NEXT: [[COPY1:%[0-9]+]]:fgr32 = COPY $f14
+    ; FP32-NEXT: [[FDIV_S:%[0-9]+]]:fgr32 = nofpexcept FDIV_S [[COPY]], [[COPY1]], implicit $fcr31
+    ; FP32-NEXT: $f0 = COPY [[FDIV_S]]
+    ; FP32-NEXT: RetRA implicit $f0
+    ;
     ; FP64-LABEL: name: float_div
     ; FP64: liveins: $f12, $f14
-    ; FP64: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
-    ; FP64: [[COPY1:%[0-9]+]]:fgr32 = COPY $f14
-    ; FP64: [[FDIV_S:%[0-9]+]]:fgr32 = FDIV_S [[COPY]], [[COPY1]]
-    ; FP64: $f0 = COPY [[FDIV_S]]
-    ; FP64: RetRA implicit $f0
+    ; FP64-NEXT: {{  $}}
+    ; FP64-NEXT: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
+    ; FP64-NEXT: [[COPY1:%[0-9]+]]:fgr32 = COPY $f14
+    ; FP64-NEXT: [[FDIV_S:%[0-9]+]]:fgr32 = nofpexcept FDIV_S [[COPY]], [[COPY1]], implicit $fcr31
+    ; FP64-NEXT: $f0 = COPY [[FDIV_S]]
+    ; FP64-NEXT: RetRA implicit $f0
     %0:fprb(s32) = COPY $f12
     %1:fprb(s32) = COPY $f14
     %2:fprb(s32) = G_FDIV %0, %1
@@ -149,18 +161,21 @@ body:             |
 
     ; FP32-LABEL: name: double_add
     ; FP32: liveins: $d6, $d7
-    ; FP32: [[COPY:%[0-9]+]]:afgr64 = COPY $d6
-    ; FP32: [[COPY1:%[0-9]+]]:afgr64 = COPY $d7
-    ; FP32: [[FADD_D32_:%[0-9]+]]:afgr64 = FADD_D32 [[COPY]], [[COPY1]]
-    ; FP32: $d0 = COPY [[FADD_D32_]]
-    ; FP32: RetRA implicit $d0
+    ; FP32-NEXT: {{  $}}
+    ; FP32-NEXT: [[COPY:%[0-9]+]]:afgr64 = COPY $d6
+    ; FP32-NEXT: [[COPY1:%[0-9]+]]:afgr64 = COPY $d7
+    ; FP32-NEXT: [[FADD_D32_:%[0-9]+]]:afgr64 = nofpexcept FADD_D32 [[COPY]], [[COPY1]], implicit $fcr31
+    ; FP32-NEXT: $d0 = COPY [[FADD_D32_]]
+    ; FP32-NEXT: RetRA implicit $d0
+    ;
     ; FP64-LABEL: name: double_add
     ; FP64: liveins: $d6, $d7
-    ; FP64: [[COPY:%[0-9]+]]:fgr64 = COPY $d6
-    ; FP64: [[COPY1:%[0-9]+]]:fgr64 = COPY $d7
-    ; FP64: [[FADD_D64_:%[0-9]+]]:fgr64 = FADD_D64 [[COPY]], [[COPY1]]
-    ; FP64: $d0 = COPY [[FADD_D64_]]
-    ; FP64: RetRA implicit $d0
+    ; FP64-NEXT: {{  $}}
+    ; FP64-NEXT: [[COPY:%[0-9]+]]:fgr64 = COPY $d6
+    ; FP64-NEXT: [[COPY1:%[0-9]+]]:fgr64 = COPY $d7
+    ; FP64-NEXT: [[FADD_D64_:%[0-9]+]]:fgr64 = nofpexcept FADD_D64 [[COPY]], [[COPY1]], implicit $fcr31
+    ; FP64-NEXT: $d0 = COPY [[FADD_D64_]]
+    ; FP64-NEXT: RetRA implicit $d0
     %0:fprb(s64) = COPY $d6
     %1:fprb(s64) = COPY $d7
     %2:fprb(s64) = G_FADD %0, %1
@@ -180,18 +195,21 @@ body:             |
 
     ; FP32-LABEL: name: double_sub
     ; FP32: liveins: $d6, $d7
-    ; FP32: [[COPY:%[0-9]+]]:afgr64 = COPY $d6
-    ; FP32: [[COPY1:%[0-9]+]]:afgr64 = COPY $d7
-    ; FP32: [[FSUB_D32_:%[0-9]+]]:afgr64 = FSUB_D32 [[COPY]], [[COPY1]]
-    ; FP32: $d0 = COPY [[FSUB_D32_]]
-    ; FP32: RetRA implicit $d0
+    ; FP32-NEXT: {{  $}}
+    ; FP32-NEXT: [[COPY:%[0-9]+]]:afgr64 = COPY $d6
+    ; FP32-NEXT: [[COPY1:%[0-9]+]]:afgr64 = COPY $d7
+    ; FP32-NEXT: [[FSUB_D32_:%[0-9]+]]:afgr64 = nofpexcept FSUB_D32 [[COPY]], [[COPY1]], implicit $fcr31
+    ; FP32-NEXT: $d0 = COPY [[FSUB_D32_]]
+    ; FP32-NEXT: RetRA implicit $d0
+    ;
     ; FP64-LABEL: name: double_sub
     ; FP64: liveins: $d6, $d7
-    ; FP64: [[COPY:%[0-9]+]]:fgr64 = COPY $d6
-    ; FP64: [[COPY1:%[0-9]+]]:fgr64 = COPY $d7
-    ; FP64: [[FSUB_D64_:%[0-9]+]]:fgr64 = FSUB_D64 [[COPY]], [[COPY1]]
-    ; FP64: $d0 = COPY [[FSUB_D64_]]
-    ; FP64: RetRA implicit $d0
+    ; FP64-NEXT: {{  $}}
+    ; FP64-NEXT: [[COPY:%[0-9]+]]:fgr64 = COPY $d6
+    ; FP64-NEXT: [[COPY1:%[0-9]+]]:fgr64 = COPY $d7
+    ; FP64-NEXT: [[FSUB_D64_:%[0-9]+]]:fgr64 = nofpexcept FSUB_D64 [[COPY]], [[COPY1]], implicit $fcr31
+    ; FP64-NEXT: $d0 = COPY [[FSUB_D64_]]
+    ; FP64-NEXT: RetRA implicit $d0
     %0:fprb(s64) = COPY $d6
     %1:fprb(s64) = COPY $d7
     %2:fprb(s64) = G_FSUB %0, %1
@@ -211,18 +229,21 @@ body:             |
 
     ; FP32-LABEL: name: double_mul
     ; FP32: liveins: $d6, $d7
-    ; FP32: [[COPY:%[0-9]+]]:afgr64 = COPY $d6
-    ; FP32: [[COPY1:%[0-9]+]]:afgr64 = COPY $d7
-    ; FP32: [[FMUL_D32_:%[0-9]+]]:afgr64 = FMUL_D32 [[COPY]], [[COPY1]]
-    ; FP32: $d0 = COPY [[FMUL_D32_]]
-    ; FP32: RetRA implicit $d0
+    ; FP32-NEXT: {{  $}}
+    ; FP32-NEXT: [[COPY:%[0-9]+]]:afgr64 = COPY $d6
+    ; FP32-NEXT: [[COPY1:%[0-9]+]]:afgr64 = COPY $d7
+    ; FP32-NEXT: [[FMUL_D32_:%[0-9]+]]:afgr64 = nofpexcept FMUL_D32 [[COPY]], [[COPY1]], implicit $fcr31
+    ; FP32-NEXT: $d0 = COPY [[FMUL_D32_]]
+    ; FP32-NEXT: RetRA implicit $d0
+    ;
     ; FP64-LABEL: name: double_mul
     ; FP64: liveins: $d6, $d7
-    ; FP64: [[COPY:%[0-9]+]]:fgr64 = COPY $d6
-    ; FP64: [[COPY1:%[0-9]+]]:fgr64 = COPY $d7
-    ; FP64: [[FMUL_D64_:%[0-9]+]]:fgr64 = FMUL_D64 [[COPY]], [[COPY1]]
-    ; FP64: $d0 = COPY [[FMUL_D64_]]
-    ; FP64: RetRA implicit $d0
+    ; FP64-NEXT: {{  $}}
+    ; FP64-NEXT: [[COPY:%[0-9]+]]:fgr64 = COPY $d6
+    ; FP64-NEXT: [[COPY1:%[0-9]+]]:fgr64 = COPY $d7
+    ; FP64-NEXT: [[FMUL_D64_:%[0-9]+]]:fgr64 = nofpexcept FMUL_D64 [[COPY]], [[COPY1]], implicit $fcr31
+    ; FP64-NEXT: $d0 = COPY [[FMUL_D64_]]
+    ; FP64-NEXT: RetRA implicit $d0
     %0:fprb(s64) = COPY $d6
     %1:fprb(s64) = COPY $d7
     %2:fprb(s64) = G_FMUL %0, %1
@@ -242,18 +263,21 @@ body:             |
 
     ; FP32-LABEL: name: double_div
     ; FP32: liveins: $d6, $d7
-    ; FP32: [[COPY:%[0-9]+]]:afgr64 = COPY $d6
-    ; FP32: [[COPY1:%[0-9]+]]:afgr64 = COPY $d7
-    ; FP32: [[FDIV_D32_:%[0-9]+]]:afgr64 = FDIV_D32 [[COPY]], [[COPY1]]
-    ; FP32: $d0 = COPY [[FDIV_D32_]]
-    ; FP32: RetRA implicit $d0
+    ; FP32-NEXT: {{  $}}
+    ; FP32-NEXT: [[COPY:%[0-9]+]]:afgr64 = COPY $d6
+    ; FP32-NEXT: [[COPY1:%[0-9]+]]:afgr64 = COPY $d7
+    ; FP32-NEXT: [[FDIV_D32_:%[0-9]+]]:afgr64 = nofpexcept FDIV_D32 [[COPY]], [[COPY1]], implicit $fcr31
+    ; FP32-NEXT: $d0 = COPY [[FDIV_D32_]]
+    ; FP32-NEXT: RetRA implicit $d0
+    ;
     ; FP64-LABEL: name: double_div
     ; FP64: liveins: $d6, $d7
-    ; FP64: [[COPY:%[0-9]+]]:fgr64 = COPY $d6
-    ; FP64: [[COPY1:%[0-9]+]]:fgr64 = COPY $d7
-    ; FP64: [[FDIV_D64_:%[0-9]+]]:fgr64 = FDIV_D64 [[COPY]], [[COPY1]]
-    ; FP64: $d0 = COPY [[FDIV_D64_]]
-    ; FP64: RetRA implicit $d0
+    ; FP64-NEXT: {{  $}}
+    ; FP64-NEXT: [[COPY:%[0-9]+]]:fgr64 = COPY $d6
+    ; FP64-NEXT: [[COPY1:%[0-9]+]]:fgr64 = COPY $d7
+    ; FP64-NEXT: [[FDIV_D64_:%[0-9]+]]:fgr64 = nofpexcept FDIV_D64 [[COPY]], [[COPY1]], implicit $fcr31
+    ; FP64-NEXT: $d0 = COPY [[FDIV_D64_]]
+    ; FP64-NEXT: RetRA implicit $d0
     %0:fprb(s64) = COPY $d6
     %1:fprb(s64) = COPY $d7
     %2:fprb(s64) = G_FDIV %0, %1
diff --git a/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/fpext_and_fptrunc.mir b/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/fpext_and_fptrunc.mir
index 053da198abe36..983362aea209a 100644
--- a/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/fpext_and_fptrunc.mir
+++ b/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/fpext_and_fptrunc.mir
@@ -19,16 +19,19 @@ body:             |
 
     ; FP32-LABEL: name: fpext
     ; FP32: liveins: $f12
-    ; FP32: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
-    ; FP32: [[CVT_D32_S:%[0-9]+]]:afgr64 = CVT_D32_S [[COPY]]
-    ; FP32: $d0 = COPY [[CVT_D32_S]]
-    ; FP32: RetRA implicit $d0
+    ; FP32-NEXT: {{  $}}
+    ; FP32-NEXT: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
+    ; FP32-NEXT: [[CVT_D32_S:%[0-9]+]]:afgr64 = nofpexcept CVT_D32_S [[COPY]], implicit $fcr31
+    ; FP32-NEXT: $d0 = COPY [[CVT_D32_S]]
+    ; FP32-NEXT: RetRA implicit $d0
+    ;
     ; FP64-LABEL: name: fpext
     ; FP64: liveins: $f12
-    ; FP64: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
-    ; FP64: [[CVT_D64_S:%[0-9]+]]:fgr64 = CVT_D64_S [[COPY]]
-    ; FP64: $d0 = COPY [[CVT_D64_S]]
-    ; FP64: RetRA implicit $d0
+    ; FP64-NEXT: {{  $}}
+    ; FP64-NEXT: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
+    ; FP64-NEXT: [[CVT_D64_S:%[0-9]+]]:fgr64 = nofpexcept CVT_D64_S [[COPY]], implicit $fcr31
+    ; FP64-NEXT: $d0 = COPY [[CVT_D64_S]]
+    ; FP64-NEXT: RetRA implicit $d0
     %0:fprb(s32) = COPY $f12
     %1:fprb(s64) = G_FPEXT %0(s32)
     $d0 = COPY %1(s64)
@@ -47,16 +50,19 @@ body:             |
 
     ; FP32-LABEL: name: fptrunc
     ; FP32: liveins: $d6
-    ; FP32: [[COPY:%[0-9]+]]:afgr64 = COPY $d6
-    ; FP32: [[CVT_S_D32_:%[0-9]+]]:fgr32 = CVT_S_D32 [[COPY]]
-    ; FP32: $f0 = COPY [[CVT_S_D32_]]
-    ; FP32: RetRA implicit $f0
+    ; FP32-NEXT: {{  $}}
+    ; FP32-NEXT: [[COPY:%[0-9]+]]:afgr64 = COPY $d6
+    ; FP32-NEXT: [[CVT_S_D32_:%[0-9]+]]:fgr32 = nofpexcept CVT_S_D32 [[COPY]], implicit $fcr31
+    ; FP32-NEXT: $f0 = COPY [[CVT_S_D32_]]
+    ; FP32-NEXT: RetRA implicit $f0
+    ;
     ; FP64-LABEL: name: fptrunc
     ; FP64: liveins: $d6
-    ; FP64: [[COPY:%[0-9]+]]:fgr64 = COPY $d6
-    ; FP64: [[CVT_S_D64_:%[0-9]+]]:fgr32 = CVT_S_D64 [[COPY]]
-    ; FP64: $f0 = COPY [[CVT_S_D64_]]
-    ; FP64: RetRA implicit $f0
+    ; FP64-NEXT: {{  $}}
+    ; FP64-NEXT: [[COPY:%[0-9]+]]:fgr64 = COPY $d6
+    ; FP64-NEXT: [[CVT_S_D64_:%[0-9]+]]:fgr32 = nofpexcept CVT_S_D64 [[COPY]], implicit $fcr31
+    ; FP64-NEXT: $f0 = COPY [[CVT_S_D64_]]
+    ; FP64-NEXT: RetRA implicit $f0
     %0:fprb(s64) = COPY $d6
     %1:fprb(s32) = G_FPTRUNC %0(s64)
     $f0 = COPY %1(s32)
diff --git a/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/fsqrt.mir b/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/fsqrt.mir
index 0759fc1ab5c2f..b4f6f9edc054a 100644
--- a/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/fsqrt.mir
+++ b/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/fsqrt.mir
@@ -19,16 +19,19 @@ body:             |
 
     ; FP32-LABEL: name: sqrt_f32
     ; FP32: liveins: $f12
-    ; FP32: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
-    ; FP32: [[FSQRT_S:%[0-9]+]]:fgr32 = FSQRT_S [[COPY]]
-    ; FP32: $f0 = COPY [[FSQRT_S]]
-    ; FP32: RetRA implicit $f0
+    ; FP32-NEXT: {{  $}}
+    ; FP32-NEXT: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
+    ; FP32-NEXT: [[FSQRT_S:%[0-9]+]]:fgr32 = nofpexcept FSQRT_S [[COPY]], implicit $fcr31
+    ; FP32-NEXT: $f0 = COPY [[FSQRT_S]]
+    ; FP32-NEXT: RetRA implicit $f0
+    ;
     ; FP64-LABEL: name: sqrt_f32
     ; FP64: liveins: $f12
-    ; FP64: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
-    ; FP64: [[FSQRT_S:%[0-9]+]]:fgr32 = FSQRT_S [[COPY]]
-    ; FP64: $f0 = COPY [[FSQRT_S]]
-    ; FP64: RetRA implicit $f0
+    ; FP64-NEXT: {{  $}}
+    ; FP64-NEXT: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
+    ; FP64-NEXT: [[FSQRT_S:%[0-9]+]]:fgr32 = nofpexcept FSQRT_S [[COPY]], implicit $fcr31
+    ; FP64-NEXT: $f0 = COPY [[FSQRT_S]]
+    ; FP64-NEXT: RetRA implicit $f0
     %0:fprb(s32) = COPY $f12
     %1:fprb(s32) = G_FSQRT %0
     $f0 = COPY %1(s32)
@@ -47,16 +50,19 @@ body:             |
 
     ; FP32-LABEL: name: sqrt_f64
     ; FP32: liveins: $d6
-    ; FP32: [[COPY:%[0-9]+]]:afgr64 = COPY $d6
-    ; FP32: [[FSQRT_D32_:%[0-9]+]]:afgr64 = FSQRT_D32 [[COPY]]
-    ; FP32: $d0 = COPY [[FSQRT_D32_]]
-    ; FP32: RetRA implicit $d0
+    ; FP32-NEXT: {{  $}}
+    ; FP32-NEXT: [[COPY:%[0-9]+]]:afgr64 = COPY $d6
+    ; FP32-NEXT: [[FSQRT_D32_:%[0-9]+]]:afgr64 = nofpexcept FSQRT_D32 [[COPY]], implicit $fcr31
+    ; FP32-NEXT: $d0 = COPY [[FSQRT_D32_]]
+    ; FP32-NEXT: RetRA implicit $d0
+    ;
     ; FP64-LABEL: name: sqrt_f64
     ; FP64: liveins: $d6
-    ; FP64: [[COPY:%[0-9]+]]:fgr64 = COPY $d6
-    ; FP64: [[FSQRT_D64_:%[0-9]+]]:fgr64 = FSQRT_D64 [[COPY]]
-    ; FP64: $d0 = COPY [[FSQRT_D64_]]
-    ; FP64: RetRA implicit $d0
+    ; FP64-NEXT: {{  $}}
+    ; FP64-NEXT: [[COPY:%[0-9]+]]:fgr64 = COPY $d6
+    ; FP64-NEXT: [[FSQRT_D64_:%[0-9]+]]:fgr64 = nofpexcept FSQRT_D64 [[COPY]], implicit $fcr31
+    ; FP64-NEXT: $d0 = COPY [[FSQRT_D64_]]
+    ; FP64-NEXT: RetRA implicit $d0
     %0:fprb(s64) = COPY $d6
     %1:fprb(s64) = G_FSQRT %0
     $d0 = COPY %1(s64)
diff --git a/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/sitofp_and_uitofp.mir b/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/sitofp_and_uitofp.mir
index 1569e00f30959..a9d4a6d93402f 100644
--- a/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/sitofp_and_uitofp.mir
+++ b/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/sitofp_and_uitofp.mir
@@ -20,16 +20,19 @@ body:             |
 
     ; FP32-LABEL: name: i32tof32
     ; FP32: liveins: $a0
-    ; FP32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
-    ; FP32: [[PseudoCVT_S_W:%[0-9]+]]:fgr32 = PseudoCVT_S_W [[COPY]]
-    ; FP32: $f0 = COPY [[PseudoCVT_S_W]]
-    ; FP32: RetRA implicit $f0
+    ; FP32-NEXT: {{  $}}
+    ; FP32-NEXT: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+    ; FP32-NEXT: [[PseudoCVT_S_W:%[0-9]+]]:fgr32 = PseudoCVT_S_W [[COPY]]
+    ; FP32-NEXT: $f0 = COPY [[PseudoCVT_S_W]]
+    ; FP32-NEXT: RetRA implicit $f0
+    ;
     ; FP64-LABEL: name: i32tof32
     ; FP64: liveins: $a0
-    ; FP64: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
-    ; FP64: [[PseudoCVT_S_W:%[0-9]+]]:fgr32 = PseudoCVT_S_W [[COPY]]
-    ; FP64: $f0 = COPY [[PseudoCVT_S_W]]
-    ; FP64: RetRA implicit $f0
+    ; FP64-NEXT: {{  $}}
+    ; FP64-NEXT: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+    ; FP64-NEXT: [[PseudoCVT_S_W:%[0-9]+]]:fgr32 = PseudoCVT_S_W [[COPY]]
+    ; FP64-NEXT: $f0 = COPY [[PseudoCVT_S_W]]
+    ; FP64-NEXT: RetRA implicit $f0
     %0:gprb(s32) = COPY $a0
     %1:fprb(s32) = G_SITOFP %0(s32)
     $f0 = COPY %1(s32)
@@ -48,16 +51,19 @@ body:             |
 
     ; FP32-LABEL: name: i32tof64
     ; FP32: liveins: $a0
-    ; FP32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
-    ; FP32: [[PseudoCVT_D32_W:%[0-9]+]]:afgr64 = PseudoCVT_D32_W [[COPY]]
-    ; FP32: $d0 = COPY [[PseudoCVT_D32_W]]
-    ; FP32: RetRA implicit $d0
+    ; FP32-NEXT: {{  $}}
+    ; FP32-NEXT: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+    ; FP32-NEXT: [[PseudoCVT_D32_W:%[0-9]+]]:afgr64 = PseudoCVT_D32_W [[COPY]]
+    ; FP32-NEXT: $d0 = COPY [[PseudoCVT_D32_W]]
+    ; FP32-NEXT: RetRA implicit $d0
+    ;
     ; FP64-LABEL: name: i32tof64
     ; FP64: liveins: $a0
-    ; FP64: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
-    ; FP64: [[PseudoCVT_D64_W:%[0-9]+]]:fgr64 = PseudoCVT_D64_W [[COPY]]
-    ; FP64: $d0 = COPY [[PseudoCVT_D64_W]]
-    ; FP64: RetRA implicit $d0
+    ; FP64-NEXT: {{  $}}
+    ; FP64-NEXT: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+    ; FP64-NEXT: [[PseudoCVT_D64_W:%[0-9]+]]:fgr64 = PseudoCVT_D64_W [[COPY]]
+    ; FP64-NEXT: $d0 = COPY [[PseudoCVT_D64_W]]
+    ; FP64-NEXT: RetRA implicit $d0
     %0:gprb(s32) = COPY $a0
     %1:fprb(s64) = G_SITOFP %0(s32)
     $d0 = COPY %1(s64)
@@ -76,26 +82,29 @@ body:             |
 
     ; FP32-LABEL: name: u32tof64
     ; FP32: liveins: $a0
-    ; FP32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
-    ; FP32: [[LUi:%[0-9]+]]:gpr32 = LUi 17200
-    ; FP32: [[BuildPairF64_:%[0-9]+]]:afgr64 = BuildPairF64 [[COPY]], [[LUi]]
-    ; FP32: [[LUi1:%[0-9]+]]:gpr32 = LUi 17200
-    ; FP32: [[ORi:%[0-9]+]]:gpr32 = ORi $zero, 0
-    ; FP32: [[BuildPairF64_1:%[0-9]+]]:afgr64 = BuildPairF64 [[ORi]], [[LUi1]]
-    ; FP32: [[FSUB_D32_:%[0-9]+]]:afgr64 = FSUB_D32 [[BuildPairF64_]], [[BuildPairF64_1]]
-    ; FP32: $d0 = COPY [[FSUB_D32_]]
-    ; FP32: RetRA implicit $d0
+    ; FP32-NEXT: {{  $}}
+    ; FP32-NEXT: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+    ; FP32-NEXT: [[LUi:%[0-9]+]]:gpr32 = LUi 17200
+    ; FP32-NEXT: [[BuildPairF64_:%[0-9]+]]:afgr64 = BuildPairF64 [[COPY]], [[LUi]]
+    ; FP32-NEXT: [[LUi1:%[0-9]+]]:gpr32 = LUi 17200
+    ; FP32-NEXT: [[ORi:%[0-9]+]]:gpr32 = ORi $zero, 0
+    ; FP32-NEXT: [[BuildPairF64_1:%[0-9]+]]:afgr64 = BuildPairF64 [[ORi]], [[LUi1]]
+    ; FP32-NEXT: [[FSUB_D32_:%[0-9]+]]:afgr64 = nofpexcept FSUB_D32 [[BuildPairF64_]], [[BuildPairF64_1]], implicit $fcr31
+    ; FP32-NEXT: $d0 = COPY [[FSUB_D32_]]
+    ; FP32-NEXT: RetRA implicit $d0
+    ;
     ; FP64-LABEL: name: u32tof64
     ; FP64: liveins: $a0
-    ; FP64: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
-    ; FP64: [[LUi:%[0-9]+]]:gpr32 = LUi 17200
-    ; FP64: [[BuildPairF64_64_:%[0-9]+]]:fgr64 = BuildPairF64_64 [[COPY]], [[LUi]]
-    ; FP64: [[LUi1:%[0-9]+]]:gpr32 = LUi 17200
-    ; FP64: [[ORi:%[0-9]+]]:gpr32 = ORi $zero, 0
-    ; FP64: [[BuildPairF64_64_1:%[0-9]+]]:fgr64 = BuildPairF64_64 [[ORi]], [[LUi1]]
-    ; FP64: [[FSUB_D64_:%[0-9]+]]:fgr64 = FSUB_D64 [[BuildPairF64_64_]], [[BuildPairF64_64_1]]
-    ; FP64: $d0 = COPY [[FSUB_D64_]]
-    ; FP64: RetRA implicit $d0
+    ; FP64-NEXT: {{  $}}
+    ; FP64-NEXT: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+    ; FP64-NEXT: [[LUi:%[0-9]+]]:gpr32 = LUi 17200
+    ; FP64-NEXT: [[BuildPairF64_64_:%[0-9]+]]:fgr64 = BuildPairF64_64 [[COPY]], [[LUi]]
+    ; FP64-NEXT: [[LUi1:%[0-9]+]]:gpr32 = LUi 17200
+    ; FP64-NEXT: [[ORi:%[0-9]+]]:gpr32 = ORi $zero, 0
+    ; FP64-NEXT: [[BuildPairF64_64_1:%[0-9]+]]:fgr64 = BuildPairF64_64 [[ORi]], [[LUi1]]
+    ; FP64-NEXT: [[FSUB_D64_:%[0-9]+]]:fgr64 = nofpexcept FSUB_D64 [[BuildPairF64_64_]], [[BuildPairF64_64_1]], implicit $fcr31
+    ; FP64-NEXT: $d0 = COPY [[FSUB_D64_]]
+    ; FP64-NEXT: RetRA implicit $d0
     %0:gprb(s32) = COPY $a0
     %2:gprb(s32) = G_CONSTANT i32 1127219200
     %3:fprb(s64) = G_MERGE_VALUES %0(s32), %2(s32)
diff --git a/llvm/test/CodeGen/Mips/fp-strict-fp-ops.ll b/llvm/test/CodeGen/Mips/fp-strict-fp-ops.ll
new file mode 100644
index 0000000000000..abb3e5b06cb1b
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/fp-strict-fp-ops.ll
@@ -0,0 +1,110 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=mips -mcpu=mips32r2 < %s | FileCheck %s
+
+define void @unused_div(float %x, float %y) {
+; CHECK-LABEL: unused_div:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    nop
+entry:
+  %add = fdiv float %x, %y
+  ret void
+}
+
+define void @unused_div_fpexcept_strict(float %x, float %y) #0 {
+; CHECK-LABEL: unused_div_fpexcept_strict:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    div.s $f0, $f12, $f14
+entry:
+  %add = call float @llvm.experimental.constrained.fdiv.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
+  ret void
+}
+
+define void @unused_div_round_dynamic(float %x, float %y) #0 {
+; CHECK-LABEL: unused_div_round_dynamic:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    nop
+entry:
+  %add = call float @llvm.experimental.constrained.fdiv.f32(float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
+  ret void
+}
+
+define float @add_twice(float %x, float %y, i32 %n) {
+; CHECK-LABEL: add_twice:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    beqz $6, $BB3_2
+; CHECK-NEXT:    add.s $f0, $f12, $f14
+; CHECK-NEXT:  # %bb.1: # %if.then
+; CHECK-NEXT:    mul.s $f0, $f0, $f0
+; CHECK-NEXT:  $BB3_2: # %if.end
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    nop
+entry:
+  %add = fadd float %x, %y
+  %tobool.not = icmp eq i32 %n, 0
+  br i1 %tobool.not, label %if.end, label %if.then
+
+if.then:
+  %add1 = fadd float %x, %y
+  %mul = fmul float %add, %add1
+  br label %if.end
+
+if.end:
+  %a.0 = phi float [ %mul, %if.then ], [ %add, %entry ]
+  ret float %a.0
+}
+
+define float @add_twice_fpexcept_strict(float %x, float %y, i32 %n) #0 {
+; CHECK-LABEL: add_twice_fpexcept_strict:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    beqz $6, $BB4_2
+; CHECK-NEXT:    add.s $f0, $f12, $f14
+; CHECK-NEXT:  # %bb.1: # %if.then
+; CHECK-NEXT:    add.s $f1, $f12, $f14
+; CHECK-NEXT:    mul.s $f0, $f0, $f1
+; CHECK-NEXT:  $BB4_2: # %if.end
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    nop
+entry:
+  %add = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
+  %tobool.not = icmp eq i32 %n, 0
+  br i1 %tobool.not, label %if.end, label %if.then
+
+if.then:
+  %add1 = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
+  %mul = call float @llvm.experimental.constrained.fmul.f32(float %add, float %add1, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
+  br label %if.end
+
+if.end:
+  %a.0 = phi float [ %mul, %if.then ], [ %add, %entry ]
+  ret float %a.0
+}
+
+define float @add_twice_round_dynamic(float %x, float %y, i32 %n) #0 {
+; CHECK-LABEL: add_twice_round_dynamic:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    beqz $6, $BB5_2
+; CHECK-NEXT:    add.s $f0, $f12, $f14
+; CHECK-NEXT:  # %bb.1: # %if.then
+; CHECK-NEXT:    mul.s $f0, $f0, $f0
+; CHECK-NEXT:  $BB5_2: # %if.end
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    nop
+entry:
+  %add = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
+  %tobool.not = icmp eq i32 %n, 0
+  br i1 %tobool.not, label %if.end, label %if.then
+
+if.then:
+  %add1 = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
+  %mul = call float @llvm.experimental.constrained.fmul.f32(float %add, float %add1, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
+  br label %if.end
+
+if.end:
+  %a.0 = phi float [ %mul, %if.then ], [ %add, %entry ]
+  ret float %a.0
+}
+
+attributes #0 = { strictfp }



More information about the llvm-commits mailing list