[llvm] 4154ada - [Xtensa] Implement Xtensa Floating Point Option. (#136086)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 22 15:18:08 PDT 2025


Author: Andrei Safronov
Date: 2025-06-23T01:18:04+03:00
New Revision: 4154ada1d485e652a7d0088e25959f101be79723

URL: https://github.com/llvm/llvm-project/commit/4154ada1d485e652a7d0088e25959f101be79723
DIFF: https://github.com/llvm/llvm-project/commit/4154ada1d485e652a7d0088e25959f101be79723.diff

LOG: [Xtensa] Implement Xtensa Floating Point Option. (#136086)

 Implement Xtensa FP Option instructions and lowering 
of the base FP operations with tests. Implement UR registers parsing.
 Fix loading from constant pool callee, basic block, globaladdress and
jumptable addresses. Also fixed potential memory leakage when several
similar XtensaConstantPoolValue objects are created Fix lowering i32 immediate.

Added: 
    llvm/test/CodeGen/Xtensa/add_shifted_imm.ll
    llvm/test/CodeGen/Xtensa/brcc_fp.ll
    llvm/test/CodeGen/Xtensa/float-arith.ll
    llvm/test/MC/Disassembler/Xtensa/fp.txt
    llvm/test/MC/Xtensa/float-err.s
    llvm/test/MC/Xtensa/float.s

Modified: 
    llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
    llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
    llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
    llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
    llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.h
    llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp
    llvm/lib/Target/Xtensa/XtensaCallingConv.td
    llvm/lib/Target/Xtensa/XtensaFeatures.td
    llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
    llvm/lib/Target/Xtensa/XtensaISelLowering.h
    llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
    llvm/lib/Target/Xtensa/XtensaInstrInfo.td
    llvm/lib/Target/Xtensa/XtensaMachineFunctionInfo.h
    llvm/lib/Target/Xtensa/XtensaOperators.td
    llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
    llvm/lib/Target/Xtensa/XtensaSubtarget.h
    llvm/test/CodeGen/Xtensa/aligned_alloc.ll
    llvm/test/CodeGen/Xtensa/bswap.ll
    llvm/test/CodeGen/Xtensa/ctlz-cttz-ctpop.ll
    llvm/test/CodeGen/Xtensa/mul.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
index 6c4e365451af0..4103ff6b877a7 100644
--- a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
+++ b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
@@ -35,7 +35,9 @@ using namespace llvm;
 struct XtensaOperand;
 
 class XtensaAsmParser : public MCTargetAsmParser {
+  const MCRegisterInfo &MRI;
 
+  enum XtensaRegisterType { Xtensa_Generic, Xtensa_SR, Xtensa_UR };
   SMLoc getLoc() const { return getParser().getTok().getLoc(); }
 
   XtensaTargetStreamer &getTargetStreamer() {
@@ -64,11 +66,12 @@ class XtensaAsmParser : public MCTargetAsmParser {
   ParseStatus parseImmediate(OperandVector &Operands);
   ParseStatus
   parseRegister(OperandVector &Operands, bool AllowParens = false,
-                bool SR = false,
+                XtensaRegisterType SR = Xtensa_Generic,
                 Xtensa::RegisterAccessType RAType = Xtensa::REGISTER_EXCHANGE);
   ParseStatus parseOperandWithModifier(OperandVector &Operands);
   bool
-  parseOperand(OperandVector &Operands, StringRef Mnemonic, bool SR = false,
+  parseOperand(OperandVector &Operands, StringRef Mnemonic,
+               XtensaRegisterType SR = Xtensa_Generic,
                Xtensa::RegisterAccessType RAType = Xtensa::REGISTER_EXCHANGE);
   bool ParseInstructionWithSR(ParseInstructionInfo &Info, StringRef Name,
                               SMLoc NameLoc, OperandVector &Operands);
@@ -90,7 +93,8 @@ class XtensaAsmParser : public MCTargetAsmParser {
 
   XtensaAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
                   const MCInstrInfo &MII, const MCTargetOptions &Options)
-      : MCTargetAsmParser(Options, STI, MII) {
+      : MCTargetAsmParser(Options, STI, MII),
+        MRI(*Parser.getContext().getRegisterInfo()) {
     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
   }
 
@@ -583,7 +587,8 @@ bool XtensaAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
 }
 
 ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands,
-                                           bool AllowParens, bool SR,
+                                           bool AllowParens,
+                                           XtensaRegisterType RegType,
                                            Xtensa::RegisterAccessType RAType) {
   SMLoc FirstS = getLoc();
   bool HadParens = false;
@@ -594,25 +599,32 @@ ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands,
   if (AllowParens && getLexer().is(AsmToken::LParen)) {
     size_t ReadCount = getLexer().peekTokens(Buf);
     if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
-      if ((Buf[0].getKind() == AsmToken::Integer) && (!SR))
+      if (Buf[0].getKind() == AsmToken::Integer && RegType == Xtensa_Generic)
         return ParseStatus::NoMatch;
       HadParens = true;
       getParser().Lex(); // Eat '('
     }
   }
 
-  unsigned RegNo = 0;
+  MCRegister RegNo = 0;
 
   switch (getLexer().getKind()) {
   default:
     return ParseStatus::NoMatch;
   case AsmToken::Integer:
-    if (!SR)
+    if (RegType == Xtensa_Generic)
       return ParseStatus::NoMatch;
-    RegName = getLexer().getTok().getString();
-    RegNo = MatchRegisterName(RegName);
-    if (RegNo == 0)
+
+    // Parse case when we expect UR register code as special case,
+    // because SR and UR registers may have the same number
+    // and such situation may lead to confilct
+    if (RegType == Xtensa_UR) {
+      int64_t RegCode = getLexer().getTok().getIntVal();
+      RegNo = Xtensa::getUserRegister(RegCode, MRI);
+    } else {
+      RegName = getLexer().getTok().getString();
       RegNo = MatchRegisterAltName(RegName);
+    }
     break;
   case AsmToken::Identifier:
     RegName = getLexer().getTok().getIdentifier();
@@ -689,7 +701,8 @@ ParseStatus XtensaAsmParser::parseOperandWithModifier(OperandVector &Operands) {
 /// from this information, adding to Operands.
 /// If operand was parsed, returns false, else true.
 bool XtensaAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic,
-                                   bool SR, Xtensa::RegisterAccessType RAType) {
+                                   XtensaRegisterType RegType,
+                                   Xtensa::RegisterAccessType RAType) {
   // Check if the current operand has a custom associated parser, if so, try to
   // custom parse the operand, or fallback to the general approach.
   ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic);
@@ -703,7 +716,7 @@ bool XtensaAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic,
     return true;
 
   // Attempt to parse token as register
-  if (parseRegister(Operands, true, SR, RAType).isSuccess())
+  if (parseRegister(Operands, true, RegType, RAType).isSuccess())
     return false;
 
   // Attempt to parse token as an immediate
@@ -722,11 +735,9 @@ bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info,
                      : (Name[0] == 'r' ? Xtensa::REGISTER_READ
                                        : Xtensa::REGISTER_EXCHANGE);
 
-  if ((Name.starts_with("wsr.") || Name.starts_with("rsr.") ||
-       Name.starts_with("xsr.")) &&
-      (Name.size() > 4)) {
-    // Parse case when instruction name is concatenated with SR register
-    // name, like "wsr.sar a1"
+  if ((Name.size() > 4) && Name[3] == '.') {
+    // Parse case when instruction name is concatenated with SR/UR register
+    // name, like "wsr.sar a1" or "wur.fcr a1"
 
     // First operand is token for instruction
     Operands.push_back(XtensaOperand::createToken(Name.take_front(3), NameLoc));
@@ -762,7 +773,8 @@ bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info,
     }
 
     // Parse second operand
-    if (parseOperand(Operands, Name, true, RAType))
+    if (parseOperand(Operands, Name, Name[1] == 's' ? Xtensa_SR : Xtensa_UR,
+                     RAType))
       return true;
   }
 
@@ -780,7 +792,8 @@ bool XtensaAsmParser::parseInstruction(ParseInstructionInfo &Info,
                                        StringRef Name, SMLoc NameLoc,
                                        OperandVector &Operands) {
   if (Name.starts_with("wsr") || Name.starts_with("rsr") ||
-      Name.starts_with("xsr")) {
+      Name.starts_with("xsr") || Name.starts_with("rur") ||
+      Name.starts_with("wur")) {
     return ParseInstructionWithSR(Info, Name, NameLoc, Operands);
   }
 

diff  --git a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
index 3b37ac88b9b17..2f92f8606fb48 100644
--- a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
+++ b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
@@ -73,42 +73,68 @@ static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo,
   return MCDisassembler::Success;
 }
 
-static const MCPhysReg MRDecoderTable[] = {Xtensa::M0, Xtensa::M1, Xtensa::M2,
-                                           Xtensa::M3};
-
 static DecodeStatus DecodeMRRegisterClass(MCInst &Inst, uint64_t RegNo,
                                           uint64_t Address,
                                           const void *Decoder) {
-  if (RegNo >= std::size(MRDecoderTable))
+  if (RegNo > 3)
     return MCDisassembler::Fail;
 
-  MCPhysReg Reg = MRDecoderTable[RegNo];
+  MCPhysReg Reg = Xtensa::M0 + RegNo;
   Inst.addOperand(MCOperand::createReg(Reg));
   return MCDisassembler::Success;
 }
 
-static const MCPhysReg MR01DecoderTable[] = {Xtensa::M0, Xtensa::M1};
-
 static DecodeStatus DecodeMR01RegisterClass(MCInst &Inst, uint64_t RegNo,
                                             uint64_t Address,
                                             const void *Decoder) {
-  if (RegNo > 2)
+  if (RegNo > 1)
     return MCDisassembler::Fail;
 
-  MCPhysReg Reg = MR01DecoderTable[RegNo];
+  MCPhysReg Reg = Xtensa::M0 + RegNo;
   Inst.addOperand(MCOperand::createReg(Reg));
   return MCDisassembler::Success;
 }
 
-static const MCPhysReg MR23DecoderTable[] = {Xtensa::M2, Xtensa::M3};
-
 static DecodeStatus DecodeMR23RegisterClass(MCInst &Inst, uint64_t RegNo,
                                             uint64_t Address,
                                             const void *Decoder) {
-  if (RegNo != 0 && RegNo != 1)
+  if (RegNo > 1)
+    return MCDisassembler::Fail;
+
+  MCPhysReg Reg = Xtensa::M2 + RegNo;
+  Inst.addOperand(MCOperand::createReg(Reg));
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeFPRRegisterClass(MCInst &Inst, uint64_t RegNo,
+                                           uint64_t Address,
+                                           const void *Decoder) {
+  if (RegNo > 15)
+    return MCDisassembler::Fail;
+
+  MCPhysReg Reg = Xtensa::F0 + RegNo;
+  Inst.addOperand(MCOperand::createReg(Reg));
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeURRegisterClass(MCInst &Inst, uint64_t RegNo,
+                                          uint64_t Address,
+                                          const MCDisassembler *Decoder) {
+  if (RegNo > 255)
+    return MCDisassembler::Fail;
+
+  Xtensa::RegisterAccessType RAType = Inst.getOpcode() == Xtensa::WUR
+                                          ? Xtensa::REGISTER_WRITE
+                                          : Xtensa::REGISTER_READ;
+
+  const XtensaDisassembler *Dis =
+      static_cast<const XtensaDisassembler *>(Decoder);
+  const MCRegisterInfo *MRI = Dis->getContext().getRegisterInfo();
+  MCPhysReg Reg = Xtensa::getUserRegister(RegNo, *MRI);
+  if (!Xtensa::checkRegister(Reg, Decoder->getSubtargetInfo().getFeatureBits(),
+                             RAType))
     return MCDisassembler::Fail;
 
-  MCPhysReg Reg = MR23DecoderTable[RegNo];
   Inst.addOperand(MCOperand::createReg(Reg));
   return MCDisassembler::Success;
 }
@@ -187,18 +213,13 @@ static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo,
   return MCDisassembler::Fail;
 }
 
-const MCPhysReg BRDecoderTable[] = {
-    Xtensa::B0,  Xtensa::B1,  Xtensa::B2,  Xtensa::B3, Xtensa::B4,  Xtensa::B5,
-    Xtensa::B6,  Xtensa::B7,  Xtensa::B8,  Xtensa::B9, Xtensa::B10, Xtensa::B11,
-    Xtensa::B12, Xtensa::B13, Xtensa::B14, Xtensa::B15};
-
 static DecodeStatus DecodeBRRegisterClass(MCInst &Inst, uint64_t RegNo,
                                           uint64_t Address,
                                           const void *Decoder) {
-  if (RegNo >= std::size(BRDecoderTable))
+  if (RegNo > 15)
     return MCDisassembler::Fail;
 
-  MCPhysReg Reg = BRDecoderTable[RegNo];
+  MCPhysReg Reg = Xtensa::B0 + RegNo;
   Inst.addOperand(MCOperand::createReg(Reg));
   return MCDisassembler::Success;
 }

diff  --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
index 8231a8a9a44d4..03b3ed0c121be 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
@@ -307,6 +307,11 @@ XtensaMCCodeEmitter::getMemRegEncoding(const MCInst &MI, unsigned OpNo,
   case Xtensa::L32I:
   case Xtensa::S32I_N:
   case Xtensa::L32I_N:
+  case Xtensa::SSI:
+  case Xtensa::SSIP:
+  case Xtensa::LSI:
+  case Xtensa::LSIP:
+
     if (Res & 0x3) {
       report_fatal_error("Unexpected operand value!");
     }

diff  --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
index f48c6225827b0..9a55635674d72 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
@@ -188,6 +188,9 @@ bool Xtensa::checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits,
     return RAType == Xtensa::REGISTER_READ && FeatureBits[Xtensa::FeaturePRID];
   case Xtensa::VECBASE:
     return FeatureBits[Xtensa::FeatureRelocatableVector];
+  case Xtensa::FCR:
+  case Xtensa::FSR:
+    return FeatureBits[FeatureSingleFloat];
   case Xtensa::WINDOWBASE:
   case Xtensa::WINDOWSTART:
     return FeatureBits[Xtensa::FeatureWindowed];
@@ -198,6 +201,16 @@ bool Xtensa::checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits,
   return true;
 }
 
+// Get Xtensa User Register by encoding value.
+MCRegister Xtensa::getUserRegister(unsigned Code, const MCRegisterInfo &MRI) {
+  if (MRI.getEncodingValue(Xtensa::FCR) == Code) {
+    return Xtensa::FCR;
+  } else if (MRI.getEncodingValue(Xtensa::FSR) == Code) {
+    return Xtensa::FSR;
+  }
+  return Xtensa::NoRegister;
+}
+
 static MCAsmInfo *createXtensaMCAsmInfo(const MCRegisterInfo &MRI,
                                         const Triple &TT,
                                         const MCTargetOptions &Options) {

diff  --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.h b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.h
index ec91f656bdcbd..963f86679fcf8 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.h
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.h
@@ -64,6 +64,9 @@ enum RegisterAccessType {
 // Verify if it's correct to use a special register.
 bool checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits,
                    RegisterAccessType RA);
+
+// Get Xtensa User Register by register encoding value.
+MCRegister getUserRegister(unsigned Code, const MCRegisterInfo &MRI);
 } // namespace Xtensa
 } // end namespace llvm
 

diff  --git a/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp b/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp
index 4e3ed4b9e8ee5..d31a256dd00fc 100644
--- a/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp
@@ -62,22 +62,25 @@ void XtensaAsmPrinter::emitInstruction(const MachineInstr *MI) {
 
 void XtensaAsmPrinter::emitMachineConstantPoolValue(
     MachineConstantPoolValue *MCPV) {
-  XtensaConstantPoolValue *ACPV = static_cast<XtensaConstantPoolValue *>(MCPV);
+  XtensaConstantPoolValue *XtensaCPV =
+      static_cast<XtensaConstantPoolValue *>(MCPV);
   MCSymbol *MCSym;
 
-  if (ACPV->isBlockAddress()) {
+  if (XtensaCPV->isBlockAddress()) {
     const BlockAddress *BA =
-        cast<XtensaConstantPoolConstant>(ACPV)->getBlockAddress();
+        cast<XtensaConstantPoolConstant>(XtensaCPV)->getBlockAddress();
     MCSym = GetBlockAddressSymbol(BA);
-  } else if (ACPV->isMachineBasicBlock()) {
-    const MachineBasicBlock *MBB = cast<XtensaConstantPoolMBB>(ACPV)->getMBB();
+  } else if (XtensaCPV->isMachineBasicBlock()) {
+    const MachineBasicBlock *MBB =
+        cast<XtensaConstantPoolMBB>(XtensaCPV)->getMBB();
     MCSym = MBB->getSymbol();
-  } else if (ACPV->isJumpTable()) {
-    unsigned Idx = cast<XtensaConstantPoolJumpTable>(ACPV)->getIndex();
+  } else if (XtensaCPV->isJumpTable()) {
+    unsigned Idx = cast<XtensaConstantPoolJumpTable>(XtensaCPV)->getIndex();
     MCSym = this->GetJTISymbol(Idx, false);
   } else {
-    assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
-    XtensaConstantPoolSymbol *XtensaSym = cast<XtensaConstantPoolSymbol>(ACPV);
+    assert(XtensaCPV->isExtSymbol() && "unrecognized constant pool value");
+    XtensaConstantPoolSymbol *XtensaSym =
+        cast<XtensaConstantPoolSymbol>(XtensaCPV);
     const char *SymName = XtensaSym->getSymbol();
 
     if (XtensaSym->isPrivateLinkage()) {
@@ -89,14 +92,14 @@ void XtensaAsmPrinter::emitMachineConstantPoolValue(
     }
   }
 
-  MCSymbol *LblSym = GetCPISymbol(ACPV->getLabelId());
+  MCSymbol *LblSym = GetCPISymbol(XtensaCPV->getLabelId());
   auto *TS =
       static_cast<XtensaTargetStreamer *>(OutStreamer->getTargetStreamer());
-  auto Spec = getModifierSpecifier(ACPV->getModifier());
+  auto Spec = getModifierSpecifier(XtensaCPV->getModifier());
 
-  if (ACPV->getModifier() != XtensaCP::no_modifier) {
+  if (XtensaCPV->getModifier() != XtensaCP::no_modifier) {
     std::string SymName(MCSym->getName());
-    StringRef Modifier = ACPV->getModifierText();
+    StringRef Modifier = XtensaCPV->getModifierText();
     SymName += Modifier;
     MCSym = OutContext.getOrCreateSymbol(SymName);
   }
@@ -108,9 +111,9 @@ void XtensaAsmPrinter::emitMachineConstantPoolValue(
 void XtensaAsmPrinter::emitMachineConstantPoolEntry(
     const MachineConstantPoolEntry &CPE, int i) {
   if (CPE.isMachineConstantPoolEntry()) {
-    XtensaConstantPoolValue *ACPV =
+    XtensaConstantPoolValue *XtensaCPV =
         static_cast<XtensaConstantPoolValue *>(CPE.Val.MachineCPVal);
-    ACPV->setLabelId(i);
+    XtensaCPV->setLabelId(i);
     emitMachineConstantPoolValue(CPE.Val.MachineCPVal);
   } else {
     MCSymbol *LblSym = GetCPISymbol(i);

diff  --git a/llvm/lib/Target/Xtensa/XtensaCallingConv.td b/llvm/lib/Target/Xtensa/XtensaCallingConv.td
index 2c48f8f86cafb..96528ed283a30 100644
--- a/llvm/lib/Target/Xtensa/XtensaCallingConv.td
+++ b/llvm/lib/Target/Xtensa/XtensaCallingConv.td
@@ -15,6 +15,7 @@
 def RetCC_Xtensa : CallingConv<[
   // First two return values go in a2, a3, a4, a5
   CCIfType<[i32], CCAssignToReg<[A2, A3, A4, A5]>>,
+  CCIfType<[f32], CCAssignToReg<[A2, A3, A4, A5]>>,
   CCIfType<[i64], CCAssignToRegWithShadow<[A2, A4], [A3, A5]>>
 ]>;
 

diff  --git a/llvm/lib/Target/Xtensa/XtensaFeatures.td b/llvm/lib/Target/Xtensa/XtensaFeatures.td
index 1dd03283e9313..d48f494388a23 100644
--- a/llvm/lib/Target/Xtensa/XtensaFeatures.td
+++ b/llvm/lib/Target/Xtensa/XtensaFeatures.td
@@ -8,6 +8,11 @@ def FeatureDensity : SubtargetFeature<"density", "HasDensity", "true",
 def HasDensity : Predicate<"Subtarget->hasDensity()">,
                  AssemblerPredicate<(all_of FeatureDensity)>;
 
+def FeatureSingleFloat : SubtargetFeature<"fp", "HasSingleFloat", "true",
+                                          "Enable Xtensa Single FP instructions">;
+def HasSingleFloat : Predicate<"Subtarget->hasSingleFloat()">,
+                     AssemblerPredicate<(all_of FeatureSingleFloat)>;
+
 def FeatureWindowed : SubtargetFeature<"windowed", "HasWindowed", "true",
                                        "Enable Xtensa Windowed Register option">;
 def HasWindowed : Predicate<"Subtarget->hasWindowed()">,

diff  --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
index b17840aad9b4d..d51c573282da7 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
@@ -58,6 +58,10 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
   // Set up the register classes.
   addRegisterClass(MVT::i32, &Xtensa::ARRegClass);
 
+  if (Subtarget.hasSingleFloat()) {
+    addRegisterClass(MVT::f32, &Xtensa::FPRRegClass);
+  }
+
   if (Subtarget.hasBoolean()) {
     addRegisterClass(MVT::v1i1, &Xtensa::BRRegClass);
   }
@@ -71,6 +75,8 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
 
   setOperationAction(ISD::Constant, MVT::i32, Custom);
   setOperationAction(ISD::Constant, MVT::i64, Expand);
+  setOperationAction(ISD::ConstantFP, MVT::f32, Expand);
+  setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
 
   setBooleanContents(ZeroOrOneBooleanContent);
 
@@ -107,8 +113,12 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
   setOperationAction(ISD::BR_CC, MVT::f32, Expand);
 
   setOperationAction(ISD::SELECT, MVT::i32, Expand);
+  setOperationAction(ISD::SELECT, MVT::f32, Expand);
   setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
+  setOperationAction(ISD::SELECT_CC, MVT::f32, Expand);
+
   setOperationAction(ISD::SETCC, MVT::i32, Expand);
+  setOperationAction(ISD::SETCC, MVT::f32, Expand);
 
   setCondCodeAction(ISD::SETGT, MVT::i32, Expand);
   setCondCodeAction(ISD::SETLE, MVT::i32, Expand);
@@ -175,6 +185,64 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
   setOperationAction(ISD::VACOPY, MVT::Other, Custom);
   setOperationAction(ISD::VAEND, MVT::Other, Expand);
 
+  // Handle floating-point types.
+  for (unsigned I = MVT::FIRST_FP_VALUETYPE; I <= MVT::LAST_FP_VALUETYPE; ++I) {
+    MVT VT = MVT::SimpleValueType(I);
+    if (isTypeLegal(VT)) {
+      if (VT.getSizeInBits() == 32 && Subtarget.hasSingleFloat()) {
+        setOperationAction(ISD::FABS, VT, Legal);
+        setOperationAction(ISD::FADD, VT, Legal);
+        setOperationAction(ISD::FSUB, VT, Legal);
+        setOperationAction(ISD::FMA, VT, Legal);
+        setOperationAction(ISD::FMUL, VT, Legal);
+        setOperationAction(ISD::FNEG, VT, Legal);
+      } else {
+        setOperationAction(ISD::FABS, VT, Expand);
+        setOperationAction(ISD::FADD, VT, Expand);
+        setOperationAction(ISD::FSUB, VT, Expand);
+        setOperationAction(ISD::FMA, VT, Expand);
+        setOperationAction(ISD::FMUL, VT, Expand);
+        setOperationAction(ISD::FNEG, VT, Expand);
+      }
+
+      // TODO: once implemented in InstrInfo uncomment
+      setOperationAction(ISD::FSQRT, VT, Expand);
+      setOperationAction(ISD::FSIN, VT, Expand);
+      setOperationAction(ISD::FCOS, VT, Expand);
+      setOperationAction(ISD::FREM, VT, Expand);
+      setOperationAction(ISD::FDIV, VT, Expand);
+      setOperationAction(ISD::FPOW, VT, Expand);
+      setOperationAction(ISD::FSQRT, VT, Expand);
+      setOperationAction(ISD::FCOPYSIGN, VT, Expand);
+    }
+  }
+
+  // Handle floating-point types.
+  if (Subtarget.hasSingleFloat()) {
+    setOperationAction(ISD::BITCAST, MVT::i32, Legal);
+    setOperationAction(ISD::BITCAST, MVT::f32, Legal);
+    setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
+    setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
+    setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
+    setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
+
+    setCondCodeAction(ISD::SETOGT, MVT::f32, Expand);
+    setCondCodeAction(ISD::SETOGE, MVT::f32, Expand);
+    setCondCodeAction(ISD::SETONE, MVT::f32, Expand);
+    setCondCodeAction(ISD::SETUGE, MVT::f32, Expand);
+    setCondCodeAction(ISD::SETUGT, MVT::f32, Expand);
+  } else {
+    setOperationAction(ISD::BITCAST, MVT::i32, Expand);
+    setOperationAction(ISD::BITCAST, MVT::f32, Expand);
+    setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand);
+    setOperationAction(ISD::SINT_TO_FP, MVT::i32, Expand);
+    setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand);
+    setOperationAction(ISD::FP_TO_SINT, MVT::i32, Expand);
+  }
+
+  // Floating-point truncation and stores need to be done separately.
+  setTruncStoreAction(MVT::f64, MVT::f32, Expand);
+
   // Compute derived properties from the register classes
   computeRegisterProperties(STI.getRegisterInfo());
 }
@@ -185,6 +253,11 @@ bool XtensaTargetLowering::isOffsetFoldingLegal(
   return false;
 }
 
+bool XtensaTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,
+                                        bool ForCodeSize) const {
+  return false;
+}
+
 //===----------------------------------------------------------------------===//
 // Inline asm support
 //===----------------------------------------------------------------------===//
@@ -335,6 +408,16 @@ static bool CC_Xtensa_Custom(unsigned ValNo, MVT ValVT, MVT LocVT,
   return false;
 }
 
+/// Return the register type for a given MVT
+MVT XtensaTargetLowering::getRegisterTypeForCallingConv(LLVMContext &Context,
+                                                        CallingConv::ID CC,
+                                                        EVT VT) const {
+  if (VT.isFloatingPoint())
+    return MVT::i32;
+
+  return TargetLowering::getRegisterTypeForCallingConv(Context, CC, VT);
+}
+
 CCAssignFn *XtensaTargetLowering::CCAssignFnForCall(CallingConv::ID CC,
                                                     bool IsVarArg) const {
   return CC_Xtensa_Custom;
@@ -604,15 +687,19 @@ XtensaTargetLowering::LowerCall(CallLoweringInfo &CLI,
   if ((!name.empty()) && isLongCall(name.c_str())) {
     // Create a constant pool entry for the callee address
     XtensaCP::XtensaCPModifier Modifier = XtensaCP::no_modifier;
+    XtensaMachineFunctionInfo *XtensaFI =
+        MF.getInfo<XtensaMachineFunctionInfo>();
+    unsigned LabelId = XtensaFI->createCPLabelId();
 
     XtensaConstantPoolValue *CPV = XtensaConstantPoolSymbol::Create(
-        *DAG.getContext(), name.c_str(), 0 /* XtensaCLabelIndex */, false,
-        Modifier);
+        *DAG.getContext(), name.c_str(), LabelId, false, Modifier);
 
     // Get the address of the callee into a register
     SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, Align(4), 0, TF);
     SDValue CPWrap = getAddrPCRel(CPAddr, DAG);
-    Callee = CPWrap;
+    Callee = DAG.getLoad(
+        PtrVT, DL, DAG.getEntryNode(), CPWrap,
+        MachinePointerInfo::getConstantPool(DAG.getMachineFunction()));
   }
 
   // The first call operand is the chain and the second is the target address.
@@ -805,12 +892,14 @@ SDValue XtensaTargetLowering::LowerImmediate(SDValue Op,
     // Check if use node maybe lowered to the ADDMI instruction
     SDNode &OpNode = *Op.getNode();
     if ((OpNode.hasOneUse() && OpNode.user_begin()->getOpcode() == ISD::ADD) &&
-        isShiftedInt<16, 8>(Value))
+        isShiftedInt<8, 8>(Value))
       return Op;
     Type *Ty = Type::getInt32Ty(*DAG.getContext());
     Constant *CV = ConstantInt::get(Ty, Value);
     SDValue CP = DAG.getConstantPool(CV, MVT::i32);
-    return CP;
+    SDValue Res =
+        DAG.getLoad(MVT::i32, DL, DAG.getEntryNode(), CP, MachinePointerInfo());
+    return Res;
   }
   return Op;
 }
@@ -824,22 +913,30 @@ SDValue XtensaTargetLowering::LowerGlobalAddress(SDValue Op,
 
   SDValue CPAddr = DAG.getTargetConstantPool(GV, PtrVT, Align(4));
   SDValue CPWrap = getAddrPCRel(CPAddr, DAG);
-
-  return CPWrap;
+  SDValue Res = DAG.getLoad(
+      PtrVT, DL, DAG.getEntryNode(), CPWrap,
+      MachinePointerInfo::getConstantPool(DAG.getMachineFunction()));
+  return Res;
 }
 
 SDValue XtensaTargetLowering::LowerBlockAddress(SDValue Op,
                                                 SelectionDAG &DAG) const {
   BlockAddressSDNode *Node = cast<BlockAddressSDNode>(Op);
+  SDLoc DL(Op);
   const BlockAddress *BA = Node->getBlockAddress();
   EVT PtrVT = Op.getValueType();
+  MachineFunction &MF = DAG.getMachineFunction();
+  XtensaMachineFunctionInfo *XtensaFI = MF.getInfo<XtensaMachineFunctionInfo>();
+  unsigned LabelId = XtensaFI->createCPLabelId();
 
   XtensaConstantPoolValue *CPV =
-      XtensaConstantPoolConstant::Create(BA, 0, XtensaCP::CPBlockAddress);
+      XtensaConstantPoolConstant::Create(BA, LabelId, XtensaCP::CPBlockAddress);
   SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, Align(4));
   SDValue CPWrap = getAddrPCRel(CPAddr, DAG);
-
-  return CPWrap;
+  SDValue Res = DAG.getLoad(
+      PtrVT, DL, DAG.getEntryNode(), CPWrap,
+      MachinePointerInfo::getConstantPool(DAG.getMachineFunction()));
+  return Res;
 }
 
 SDValue XtensaTargetLowering::LowerBR_JT(SDValue Op, SelectionDAG &DAG) const {
@@ -874,15 +971,19 @@ SDValue XtensaTargetLowering::LowerJumpTable(SDValue Op,
                                              SelectionDAG &DAG) const {
   JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
   EVT PtrVT = Op.getValueType();
+  SDLoc DL(Op);
 
-  // Create a constant pool entry for the callee address
+  // Create a constant pool entry for the jumptable address
   XtensaConstantPoolValue *CPV =
       XtensaConstantPoolJumpTable::Create(*DAG.getContext(), JT->getIndex());
 
-  // Get the address of the callee into a register
+  // Get the address of the jumptable into a register
   SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, Align(4));
 
-  return getAddrPCRel(CPAddr, DAG);
+  SDValue Res = DAG.getLoad(
+      PtrVT, DL, DAG.getEntryNode(), getAddrPCRel(CPAddr, DAG),
+      MachinePointerInfo::getConstantPool(DAG.getMachineFunction()));
+  return Res;
 }
 
 SDValue XtensaTargetLowering::getAddrPCRel(SDValue Op,
@@ -1311,6 +1412,26 @@ const char *XtensaTargetLowering::getTargetNodeName(unsigned Opcode) const {
     return "XtensaISD::SRCL";
   case XtensaISD::SRCR:
     return "XtensaISD::SRCR";
+  case XtensaISD::CMPUO:
+    return "XtensaISD::CMPUO";
+  case XtensaISD::CMPUEQ:
+    return "XtensaISD::CMPUEQ";
+  case XtensaISD::CMPULE:
+    return "XtensaISD::CMPULE";
+  case XtensaISD::CMPULT:
+    return "XtensaISD::CMPULT";
+  case XtensaISD::CMPOEQ:
+    return "XtensaISD::CMPOEQ";
+  case XtensaISD::CMPOLE:
+    return "XtensaISD::CMPOLE";
+  case XtensaISD::CMPOLT:
+    return "XtensaISD::CMPOLT";
+  case XtensaISD::MADD:
+    return "XtensaISD::MADD";
+  case XtensaISD::MSUB:
+    return "XtensaISD::MSUB";
+  case XtensaISD::MOVS:
+    return "XtensaISD::MOVS";
   }
   return nullptr;
 }
@@ -1395,11 +1516,19 @@ MachineBasicBlock *XtensaTargetLowering::EmitInstrWithCustomInserter(
   case Xtensa::S16I:
   case Xtensa::S32I:
   case Xtensa::S32I_N:
+  case Xtensa::SSI:
+  case Xtensa::SSIP:
+  case Xtensa::SSX:
+  case Xtensa::SSXP:
   case Xtensa::L8UI:
   case Xtensa::L16SI:
   case Xtensa::L16UI:
   case Xtensa::L32I:
-  case Xtensa::L32I_N: {
+  case Xtensa::L32I_N:
+  case Xtensa::LSI:
+  case Xtensa::LSIP:
+  case Xtensa::LSX:
+  case Xtensa::LSXP: {
     // Insert memory wait instruction "memw" before volatile load/store as it is
     // implemented in gcc. If memoperands is empty then assume that it aslo
     // maybe volatile load/store and insert "memw".

diff  --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.h b/llvm/lib/Target/Xtensa/XtensaISelLowering.h
index c7d4f41b1f08e..b6f2ebe21c940 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.h
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.h
@@ -56,6 +56,21 @@ enum {
   SRCL,
   // Shift Right Combined
   SRCR,
+
+  // Floating point unordered compare conditions
+  CMPUEQ,
+  CMPULE,
+  CMPULT,
+  CMPUO,
+  // Floating point compare conditions
+  CMPOEQ,
+  CMPOLE,
+  CMPOLT,
+  // FP multipy-add/sub
+  MADD,
+  MSUB,
+  // FP move
+  MOVS,
 };
 }
 
@@ -70,6 +85,9 @@ class XtensaTargetLowering : public TargetLowering {
     return LHSTy.getSizeInBits() <= 32 ? MVT::i32 : MVT::i64;
   }
 
+  MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC,
+                                    EVT VT) const override;
+
   EVT getSetCCResultType(const DataLayout &, LLVMContext &,
                          EVT VT) const override {
     if (!VT.isVector())
@@ -81,6 +99,9 @@ class XtensaTargetLowering : public TargetLowering {
 
   const char *getTargetNodeName(unsigned Opcode) const override;
 
+  bool isFPImmLegal(const APFloat &Imm, EVT VT,
+                    bool ForCodeSize) const override;
+
   std::pair<unsigned, const TargetRegisterClass *>
   getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
                                StringRef Constraint, MVT VT) const override;

diff  --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
index 005532b864c41..896e2f8f1c01c 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
@@ -151,11 +151,15 @@ void XtensaInstrInfo::getLoadStoreOpcodes(const TargetRegisterClass *RC,
                                           unsigned &LoadOpcode,
                                           unsigned &StoreOpcode,
                                           int64_t offset) const {
-  assert((RC == &Xtensa::ARRegClass) &&
-         "Unsupported regclass to load or store");
-
-  LoadOpcode = Xtensa::L32I;
-  StoreOpcode = Xtensa::S32I;
+  if (RC == &Xtensa::ARRegClass) {
+    LoadOpcode = Xtensa::L32I;
+    StoreOpcode = Xtensa::S32I;
+  } else if (RC == &Xtensa::FPRRegClass) {
+    LoadOpcode = Xtensa::LSI;
+    StoreOpcode = Xtensa::SSI;
+  } else {
+    llvm_unreachable("Unsupported regclass to load or store");
+  }
 }
 
 void XtensaInstrInfo::loadImmediate(MachineBasicBlock &MBB,
@@ -520,8 +524,10 @@ void XtensaInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
     JumpToMBB = &RestoreBB;
   }
 
+  unsigned LabelId = XtensaFI->createCPLabelId();
+
   XtensaConstantPoolValue *C = XtensaConstantPoolMBB::Create(
-      MF->getFunction().getContext(), JumpToMBB, 0);
+      MF->getFunction().getContext(), JumpToMBB, LabelId);
   unsigned Idx = ConstantPool->getConstantPoolIndex(C, Align(4));
   L32R.addOperand(MachineOperand::CreateCPI(Idx, 0));
 

diff  --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
index 7e9fcd7058c20..1335c6faff6b7 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
@@ -234,15 +234,13 @@ def S8I  : Store_II8<0x04, "s8i", truncstorei8, addr_ish1, mem8>;
 def S16I : Store_II8<0x05, "s16i", truncstorei16, addr_ish2, mem16>;
 def S32I : Store_II8<0x06, "s32i", store, addr_ish4, mem32>;
 
+let AddedComplexity = 10 in
 def L32R : RI16_Inst<0x01, (outs AR:$t), (ins L32Rtarget:$label),
-                    "l32r\t$t, $label", []> {
+                    "l32r\t$t, $label", [(set AR:$t, (load (Xtensa_pcrel_wrapper tconstpool:$label)))]> {
   bits<16> label;
   let imm16 = label;
 }
 
-// pcrel addr loading using L32R
-def : Pat<(Xtensa_pcrel_wrapper tconstpool : $in), (L32R tconstpool : $in)>;
-
 // FrameIndexes are legalized when they are operands from load/store
 // instructions. The same not happens for stack address copies, so an
 // add op with mem ComplexPattern is used and the stack address copy
@@ -565,6 +563,26 @@ def XSR : RSR_Inst<0x00, 0x01, 0x06, (outs AR:$ard, SR:$srd), (ins AR:$t, SR:$sr
   let Constraints = "$ard = $t, $srd = $sr";
 }
 
+//===----------------------------------------------------------------------===//
+// User Registers read/write instructions
+//===----------------------------------------------------------------------===//
+
+def WUR : RRR_Inst<0x00, 0x03, 0x0F, (outs UR:$ur), (ins AR:$t),
+                  "wur\t$t, $ur", []> {
+  bits<8> ur;
+
+  let r = ur{7-4};
+  let s = ur{3-0};
+}
+
+def RUR : RRR_Inst<0x00, 0x03, 0x0E, (outs AR:$r), (ins UR:$ur),
+                  "rur\t$r, $ur", []> {
+  bits<8> ur;
+
+  let s = ur{7-4};
+  let t = ur{3-0};
+}
+
 //===----------------------------------------------------------------------===//
 // Stack allocation
 //===----------------------------------------------------------------------===//
@@ -998,6 +1016,300 @@ let Predicates = [HasDiv32] in {
   def REMU : ArithLogic_RRR<0x0E, 0x02, "remu", urem>;
 }
 
+//===----------------------------------------------------------------------===//
+// Floating-Point Instructions
+//===----------------------------------------------------------------------===//
+
+class FPArith_RRR<bits<4> oper2, bits<4> oper1, string instrAsm,
+                 SDPatternOperator opNode, bit isComm = 0>
+  : RRR_Inst<0x00, oper1, oper2, (outs FPR:$r), (ins FPR:$s, FPR:$t),
+             instrAsm#"\t$r, $s, $t",
+            [(set FPR:$r, (opNode FPR:$s, FPR:$t))]> {
+  let isCommutable = isComm;
+  let isReMaterializable = 0;
+  let Predicates = [HasSingleFloat];
+}
+
+def ADD_S : FPArith_RRR<0x00, 0x0A, "add.s", fadd, 1>;
+def SUB_S : FPArith_RRR<0x01, 0x0A, "sub.s", fsub>;
+def MUL_S : FPArith_RRR<0x02, 0x0A, "mul.s", fmul, 1>;
+
+// FP load instructions
+let mayLoad = 1, usesCustomInserter = 1, Predicates = [HasSingleFloat] in {
+  def LSI : RRI8_Inst<0x03, (outs FPR:$t), (ins mem32:$addr),
+                     "lsi\t$t, $addr", []> {
+    bits<12> addr;
+
+    let r = 0x00;
+    let imm8{7-0} = addr{11-4};
+    let s{3-0} = addr{3-0};
+  }
+
+  def LSIP : RRI8_Inst<0x03, (outs FPR:$t), (ins mem32:$addr),
+                      "lsip\t$t, $addr", []> {
+    bits<12> addr;
+
+    let r = 0x08;
+    let imm8{7-0} = addr{11-4};
+    let s{3-0} = addr{3-0};
+  }
+
+  def LSX : RRR_Inst<0x00, 0x08, 0x00, (outs), (ins FPR:$r, AR:$s, AR:$t),
+                    "lsx\t$r, $s, $t", []>;
+
+  def LSXP : RRR_Inst<0x00, 0x08, 0x01, (outs), (ins FPR:$r, AR:$s, AR:$t),
+                     "lsxp\t$r, $s, $t", []>;
+}
+
+def : Pat<(f32 (load addr_ish4:$addr)), (f32 (LSI mem32:$addr))>;
+
+// FP store instructions
+let mayStore = 1, usesCustomInserter = 1, Predicates = [HasSingleFloat] in {
+  def SSI : RRI8_Inst<0x03, (outs), (ins FPR:$t, mem32:$addr),
+                     "ssi\t$t, $addr", []> {
+    bits<12> addr;
+
+    let r = 0x04;
+    let imm8{7-0} = addr{11-4};
+    let s{3-0} = addr{3-0};
+  }
+
+  def SSIP : RRI8_Inst<0x03, (outs), (ins FPR:$t, mem32:$addr),
+                      "ssip\t$t, $addr", []> {
+    bits<12> addr;
+
+    let r = 0x0C;
+    let imm8{7-0} = addr{11-4};
+    let s{3-0} = addr{3-0};
+  }
+
+  def SSX: RRR_Inst<0x00, 0x08, 0x04, (outs), (ins FPR:$r, AR:$s, AR:$t),
+                   "ssx\t$r, $s, $t", []>;
+
+  def SSXP: RRR_Inst<0x00, 0x08, 0x05, (outs), (ins FPR:$r, AR:$s, AR:$t),
+                    "ssxp\t$r, $s, $t", []>;
+}
+
+def : Pat<(store FPR:$t, addr_ish4:$addr), (SSI FPR:$t, mem32:$addr)>;
+
+// FP compare instructions
+let isCompare = 1, Predicates = [HasSingleFloat] in {
+  class FCompare <bits<4> oper2, bits<4> oper1, string instrAsm,
+                 SDPatternOperator opNode, bit isComm = 0>
+    : RRR_Inst<0x00, oper1, oper2, (outs BR:$r), (ins FPR:$s, FPR:$t),
+               instrAsm#"\t$r, $s, $t",
+              [(set BR:$r, (opNode FPR:$s, FPR:$t))]> {
+    let isCommutable = isComm;
+    let isReMaterializable = 0;
+    let Predicates = [HasSingleFloat];
+  }
+}
+
+def OEQ_S :  FCompare<0x02, 0x0b, "oeq.s", Xtensa_cmpoeq, 1>;
+def OLT_S :  FCompare<0x04, 0x0b, "olt.s", Xtensa_cmpolt, 0>;
+def OLE_S :  FCompare<0x06, 0x0b, "ole.s", Xtensa_cmpole, 0>;
+
+def UEQ_S :  FCompare<0x03, 0x0b, "ueq.s", Xtensa_cmpueq, 1>;
+def ULT_S :  FCompare<0x05, 0x0b, "ult.s", Xtensa_cmpult, 0>;
+def ULE_S :  FCompare<0x07, 0x0b, "ule.s", Xtensa_cmpule, 0>;
+def UN_S  :  FCompare<0x01, 0x0b, "un.s",  Xtensa_cmpuo, 1>;
+
+def ABS_S : RRR_Inst<0x00, 0x0A, 0x0F, (outs FPR:$r), (ins FPR:$s),
+                    "abs.s\t$r, $s",
+                    [(set FPR:$r, (fabs FPR:$s))]>, Requires<[HasSingleFloat]> {
+  let t = 0x01;
+}
+
+def : Pat<(fabs FPR:$s), (ABS_S $s)>;
+
+def ADDEXP_S : RRR_Inst<0x00, 0x0A, 0x0F, (outs FPR:$r), (ins FPR:$s),
+                       "addexp.s\t$r, $s", []>, Requires<[HasSingleFloat]> {
+  let t = 0x0E;
+}
+
+def ADDEXPM_S : RRR_Inst<0x00, 0x0A, 0x0F, (outs FPR:$r), (ins FPR:$s),
+                        "addexpm.s\t$r, $s", []>, Requires<[HasSingleFloat]> {
+  let t = 0x0F;
+}
+
+def CEIL_S : RRR_Inst<0x00, 0x0A, 0x0B, (outs AR:$r), (ins FPR:$s, uimm4:$imm),
+                     "ceil.s\t$r, $s, $imm", []>, Requires<[HasSingleFloat]> {
+  bits<4> imm;
+
+  let t = imm;
+}
+
+def CONST_S : RRR_Inst<0x00, 0x0a, 0x0f, (outs FPR:$r), (ins uimm4:$imm),
+                      "const.s\t$r, $imm", []>, Requires<[HasSingleFloat]> {
+  bits<4> imm;
+
+  let t = 0x03;
+  let s = imm{3-0};
+}
+
+def DIV0_S : RRR_Inst<0x00, 0x0A, 0x0F, (outs FPR:$r), (ins FPR:$s),
+                     "div0.s\t$r, $s", []>, Requires<[HasSingleFloat]> {
+  let t = 0x7;
+}
+
+def DIVN_S : RRR_Inst<0x00, 0x0A, 0x07, (outs FPR:$r), (ins FPR:$s, FPR:$t),
+                     "divn.s\t$r, $s, $t", []>, Requires<[HasSingleFloat]>;
+
+def FLOAT_S : RRR_Inst<0x00, 0x0A, 0x0c, (outs FPR:$r), (ins AR:$s, uimm4:$imm),
+                      "float.s\t$r, $s, $imm", []>, Requires<[HasSingleFloat]> {
+  bits<4> imm;
+
+  let t = imm;
+}
+
+def : Pat<(f32 (sint_to_fp AR:$s)), (FLOAT_S AR:$s, 0)>;
+
+def FLOOR_S : RRR_Inst<0x00, 0x0A, 0x0A, (outs AR:$r), (ins FPR:$s, uimm4:$imm),
+                      "floor.s\t$r, $s, $imm", []>, Requires<[HasSingleFloat]> {
+  bits<4> imm;
+
+  let t = imm;
+}
+
+def MADDN_S : RRR_Inst<0x00, 0x0A, 0x06, (outs FPR:$r), (ins FPR:$s, FPR:$t),
+                      "maddn.s\t$r, $s, $t", []>, Requires<[HasSingleFloat]> {
+  let isCommutable = 0;
+}
+
+// FP multipy-add
+def MADD_S : RRR_Inst<0x00, 0x0A, 0x04, (outs FPR:$r), (ins FPR:$a, FPR:$s, FPR:$t),
+                     "madd.s\t$r, $s, $t",
+                     [(set FPR:$r, (Xtensa_madd FPR:$a, FPR:$s, FPR:$t))]>,
+                     Requires<[HasSingleFloat]> {
+  let isCommutable = 0;
+  let isReMaterializable = 0;
+  let Constraints = "$r = $a";
+}
+
+// fmadd: r1 * r2 + r3
+def : Pat<(fma FPR:$r1, FPR:$r2, FPR:$r3),
+          (MADD_S $r3, $r1, $r2)>;
+
+def MKDADJ_S : RRR_Inst<0x00, 0x0A, 0x0F, (outs FPR:$r), (ins FPR:$s),
+                       "mkdadj.s\t$r, $s", []>, Requires<[HasSingleFloat]> {
+  let t = 0x0D;
+}
+
+def MKSADJ_S : RRR_Inst<0x00, 0x0A, 0x0F, (outs FPR:$r), (ins FPR:$s),
+                       "mksadj.s\t$r, $s", []>, Requires<[HasSingleFloat]> {
+  let t = 0x0C;
+}
+
+// FP move instructions
+def MOV_S : RRR_Inst<0x00, 0x0A, 0x0f, (outs FPR:$r), (ins FPR:$s),
+                    "mov.s\t$r, $s",
+                    [(set FPR:$r, (Xtensa_movs FPR:$s))]>, Requires<[HasSingleFloat]> {
+  let t = 0x00;
+}
+
+def MOVEQZ_S : RRR_Inst<0x00, 0x0B, 0x08, (outs FPR:$r), (ins FPR:$s, AR:$t),
+                       "moveqz.s\t$r, $s, $t", []>, Requires<[HasSingleFloat]>;
+
+def MOVF_S   : RRR_Inst<0x00, 0x0B, 0x0C, (outs FPR:$r), (ins FPR:$s, BR:$t),
+                       "movf.s\t$r, $s, $t", []>, Requires<[HasBoolean, HasSingleFloat]>;
+
+def MOVGEZ_S : RRR_Inst<0x00, 0x0B, 0x0B, (outs FPR:$r), (ins FPR:$s, AR:$t),
+                       "movgez.s\t$r, $s, $t", []>, Requires<[HasSingleFloat]>;
+
+def MOVLTZ_S : RRR_Inst<0x00, 0x0B, 0x0A, (outs FPR:$r), (ins FPR:$s, AR:$t),
+                       "movltz.s\t$r, $s, $t", []>, Requires<[HasSingleFloat]>;
+
+def MOVNEZ_S : RRR_Inst<0x00, 0x0B, 0x09, (outs FPR:$r), (ins FPR:$s, AR:$t),
+                       "movnez.s\t$r, $s, $t", []>, Requires<[HasSingleFloat]>;
+
+def MOVT_S   : RRR_Inst<0x00, 0x0B, 0x0D, (outs FPR:$r), (ins FPR:$s, BR:$t),
+                       "movt.s\t$r, $s, $t", []>, Requires<[HasBoolean, HasSingleFloat]>;
+
+// FP multipy-sub
+def MSUB_S : RRR_Inst<0x00, 0x0A, 0x05, (outs FPR:$r), (ins FPR:$a, FPR:$s, FPR:$t),
+                     "msub.s\t$r, $s, $t",
+                     [(set FPR:$r, (Xtensa_msub FPR:$a, FPR:$s, FPR:$t))]>, Requires<[HasSingleFloat]> {
+  let isCommutable = 0;
+  let isReMaterializable = 0;
+  let Constraints = "$r = $a";
+}
+
+def NEXP01_S : RRR_Inst<0x00, 0x0A, 0x0F, (outs FPR:$r), (ins FPR:$s),
+                       "nexp01.s\t$r, $s", []>, Requires<[HasSingleFloat]> {
+  let t = 0x0B;
+}
+
+def NEG_S : RRR_Inst<0x00, 0x0A, 0x0F, (outs FPR:$r), (ins FPR:$s),
+                    "neg.s\t$r, $s",
+                    [(set FPR:$r, (fneg FPR:$s))]>, Requires<[HasSingleFloat]> {
+  let t = 0x06;
+}
+
+def RECIP0_S : RRR_Inst<0x00, 0x0A, 0x0F, (outs FPR:$r), (ins FPR:$s),
+                       "recip0.s\t$r, $s", []>, Requires<[HasSingleFloat]> {
+  let t = 0x08;
+}
+
+def RFR : RRR_Inst<0x00, 0x0A, 0x0f, (outs AR:$r), (ins FPR:$s),
+                  "rfr\t$r, $s",
+                  [(set AR:$r, (bitconvert FPR:$s))]>, Requires<[HasSingleFloat]> {
+  let t = 0x04;
+}
+
+def ROUND_S : RRR_Inst<0x00, 0x0A, 0x08, (outs AR:$r), (ins FPR:$s, uimm4:$imm),
+                      "round.s\t$r, $s, $imm", []>, Requires<[HasSingleFloat]> {
+  bits<4> imm;
+
+  let t = imm;
+}
+
+def RSQRT0_S : RRR_Inst<0x00, 0x0A, 0x0F, (outs FPR:$r), (ins FPR:$s),
+                       "rsqrt0.s\t$r, $s", []>, Requires<[HasSingleFloat]> {
+  let t = 0x0A;
+}
+
+def SQRT0_S : RRR_Inst<0x00, 0x0A, 0x0F, (outs FPR:$r), (ins FPR:$s),
+                      "sqrt0.s\t$r, $s", []>, Requires<[HasSingleFloat]> {
+  let t = 0x09;
+}
+
+def TRUNC_S : RRR_Inst<0x00, 0x0A, 0x09, (outs AR:$r), (ins FPR:$s, uimm4:$imm),
+                      "trunc.s\t$r, $s, $imm", []>, Requires<[HasSingleFloat]>  {
+  bits<4> imm;
+
+  let t = imm;
+}
+
+def : Pat<(i32 (fp_to_sint FPR:$s)), (TRUNC_S FPR:$s, 0)>;
+
+def UFLOAT_S : RRR_Inst<0x00, 0x0A, 0x0D, (outs FPR:$r), (ins AR:$s, uimm4:$imm),
+                       "ufloat.s\t$r, $s, $imm", []>, Requires<[HasSingleFloat]>  {
+  bits<4> imm;
+
+  let t = imm;
+}
+
+def : Pat<(f32 (uint_to_fp AR:$s)), (UFLOAT_S AR:$s, 0)>;
+
+def UTRUNC_S : RRR_Inst<0x00, 0x0A, 0x0e, (outs AR:$r), (ins FPR:$s, uimm4:$imm),
+                       "utrunc.s\t$r, $s, $imm", []>, Requires<[HasSingleFloat]>  {
+  bits<4> imm;
+
+  let t = imm;
+}
+
+def : Pat<(i32 (fp_to_uint FPR:$s)), (UTRUNC_S FPR:$s, 0)>;
+
+def WFR : RRR_Inst<0x00, 0x0A, 0x0f, (outs FPR:$r), (ins AR:$s),
+                  "wfr\t$r, $s",
+                  [(set FPR:$r, (bitconvert AR:$s))]>, Requires<[HasSingleFloat]>  {
+  let t = 0x05;
+}
+
+let AddedComplexity = 10 in
+def : Pat<(f32 (load (Xtensa_pcrel_wrapper tconstpool:$in))),
+          (WFR (L32R tconstpool:$in))>;
+
 //===----------------------------------------------------------------------===//
 // Region Protection feature instructions
 //===----------------------------------------------------------------------===//

diff  --git a/llvm/lib/Target/Xtensa/XtensaMachineFunctionInfo.h b/llvm/lib/Target/Xtensa/XtensaMachineFunctionInfo.h
index bc051d9ca14fa..ff3bba0985c27 100644
--- a/llvm/lib/Target/Xtensa/XtensaMachineFunctionInfo.h
+++ b/llvm/lib/Target/Xtensa/XtensaMachineFunctionInfo.h
@@ -28,6 +28,7 @@ class XtensaMachineFunctionInfo : public MachineFunctionInfo {
   int VarArgsOnStackFrameIndex;
   int VarArgsInRegsFrameIndex;
   bool SaveFrameRegister = false;
+  unsigned CPLabelId = 0;
 
 public:
   explicit XtensaMachineFunctionInfo(const Function &F,
@@ -54,6 +55,8 @@ class XtensaMachineFunctionInfo : public MachineFunctionInfo {
 
   bool isSaveFrameRegister() const { return SaveFrameRegister; }
   void setSaveFrameRegister() { SaveFrameRegister = true; }
+
+  unsigned createCPLabelId() { return CPLabelId++; }
 };
 
 } // namespace llvm

diff  --git a/llvm/lib/Target/Xtensa/XtensaOperators.td b/llvm/lib/Target/Xtensa/XtensaOperators.td
index 12b81fccec479..fea13c2298d97 100644
--- a/llvm/lib/Target/Xtensa/XtensaOperators.td
+++ b/llvm/lib/Target/Xtensa/XtensaOperators.td
@@ -25,6 +25,11 @@ def SDT_XtensaSelectCC            : SDTypeProfile<1, 5,
                                                   SDTCisSameAs<2, 3>,
                                                   SDTCisVT<5, i32>]>;
 
+def SDT_XtensaCmp                 : SDTypeProfile<1, 2, [SDTCisVT<0, v1i1>, SDTCisVT<1, f32>, SDTCisVT<2, f32>]>;
+def SDT_XtensaMADD                : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>, SDTCisVT<0, f32>]>;
+def SDT_XtensaMOVS                : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisVT<0, f32>]>;
+def SDT_XtensaSelectCCFP          : SDTypeProfile<1, 5, [SDTCisSameAs<0, 3>, SDTCisSameAs<1, 2>, SDTCisSameAs<3, 4>, SDTCisVT<5, i32>]>;
+
 def SDT_XtensaSRC                 : SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisVT<1, i32>,
                                                          SDTCisVT<2, i32>, SDTCisVT<3, i32>]>;
 
@@ -70,3 +75,15 @@ def Xtensa_extui: SDNode<"XtensaISD::EXTUI", SDT_XtensaEXTUI>;
 
 def Xtensa_movsp: SDNode<"XtensaISD::MOVSP", SDT_XtensaMOVSP,
                         [SDNPHasChain, SDNPSideEffect, SDNPInGlue]>;
+
+def Xtensa_cmpoeq     : SDNode<"XtensaISD::CMPOEQ", SDT_XtensaCmp, [SDNPOutGlue]>;
+def Xtensa_cmpolt     : SDNode<"XtensaISD::CMPOLT", SDT_XtensaCmp, [SDNPOutGlue]>;
+def Xtensa_cmpole     : SDNode<"XtensaISD::CMPOLE", SDT_XtensaCmp, [SDNPOutGlue]>;
+def Xtensa_cmpueq     : SDNode<"XtensaISD::CMPUEQ", SDT_XtensaCmp, [SDNPOutGlue]>;
+def Xtensa_cmpult     : SDNode<"XtensaISD::CMPULT", SDT_XtensaCmp, [SDNPOutGlue]>;
+def Xtensa_cmpule     : SDNode<"XtensaISD::CMPULE", SDT_XtensaCmp, [SDNPOutGlue]>;
+def Xtensa_cmpuo      : SDNode<"XtensaISD::CMPUO", SDT_XtensaCmp, [SDNPOutGlue]>;
+
+def Xtensa_madd: SDNode<"XtensaISD::MADD", SDT_XtensaMADD, [SDNPInGlue]>;
+def Xtensa_msub: SDNode<"XtensaISD::MSUB", SDT_XtensaMADD, [SDNPInGlue]>;
+def Xtensa_movs: SDNode<"XtensaISD::MOVS", SDT_XtensaMOVS, [SDNPInGlue]>;

diff  --git a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
index 7d44029124344..644faee51f513 100644
--- a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
+++ b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
@@ -226,6 +226,50 @@ def SR :  RegisterClass<"Xtensa", [i32], 32, (add
   PS, VECBASE, EXCCAUSE, DEBUGCAUSE, CCOUNT, PRID, ICOUNT, ICOUNTLEVEL, EXCVADDR, CCOMPARE0,
   CCOMPARE1, CCOMPARE2, MISC0, MISC1, MISC2, MISC3)>;
 
+//===----------------------------------------------------------------------===//
+// USER registers
+//===----------------------------------------------------------------------===//
+class URReg<bits<8> num, string n, list<string> alt = []> : XtensaReg<n> {
+  let HWEncoding{7-0} = num;
+  let AltNames = alt;
+}
+
+def FCR : URReg<232, "fcr", ["FCR"]>;
+def FSR : URReg<233, "fsr", ["FSR"]>;
+
+def UR :  RegisterClass<"Xtensa", [i32], 32, (add FCR, FSR)>;
+
+//===----------------------------------------------------------------------===//
+// Floating-Point registers
+//===----------------------------------------------------------------------===//
+
+// Xtensa Floating-Point regs
+class FPReg<bits<4> num, string n> : XtensaReg<n> {
+  let HWEncoding{3-0} = num;
+}
+
+def F0 : FPReg<0, "f0">, DwarfRegNum<[19]>;
+def F1 : FPReg<1, "f1">, DwarfRegNum<[20]>;
+def F2 : FPReg<2, "f2">, DwarfRegNum<[21]>;
+def F3 : FPReg<3, "f3">, DwarfRegNum<[22]>;
+def F4 : FPReg<4, "f4">, DwarfRegNum<[23]>;
+def F5 : FPReg<5, "f5">, DwarfRegNum<[24]>;
+def F6 : FPReg<6, "f6">, DwarfRegNum<[25]>;
+def F7 : FPReg<7, "f7">, DwarfRegNum<[26]>;
+def F8 : FPReg<8, "f8">, DwarfRegNum<[27]>;
+def F9 : FPReg<9, "f9">, DwarfRegNum<[28]>;
+def F10 : FPReg<10, "f10">, DwarfRegNum<[29]>;
+def F11 : FPReg<11, "f11">, DwarfRegNum<[30]>;
+def F12 : FPReg<12, "f12">, DwarfRegNum<[31]>;
+def F13 : FPReg<13, "f13">, DwarfRegNum<[32]>;
+def F14 : FPReg<14, "f14">, DwarfRegNum<[33]>;
+def F15 : FPReg<15, "f15">, DwarfRegNum<[34]>;
+
+// Floating-Point register class with allocation order
+def FPR : RegisterClass<"Xtensa", [f32], 32, (add
+  F8, F9, F10, F11, F12, F13, F14, F15,
+  F7, F6, F5, F4, F3, F2, F1, F0)>;
+
 //===----------------------------------------------------------------------===//
 // Boolean registers
 //===----------------------------------------------------------------------===//

diff  --git a/llvm/lib/Target/Xtensa/XtensaSubtarget.h b/llvm/lib/Target/Xtensa/XtensaSubtarget.h
index da4e14a53eef3..bc32541750ece 100644
--- a/llvm/lib/Target/Xtensa/XtensaSubtarget.h
+++ b/llvm/lib/Target/Xtensa/XtensaSubtarget.h
@@ -77,6 +77,7 @@ class XtensaSubtarget : public XtensaGenSubtargetInfo {
   bool hasMul32() const { return HasMul32; }
   bool hasMul32High() const { return HasMul32High; }
   bool hasDiv32() const { return HasDiv32; }
+  bool hasSingleFloat() const { return HasSingleFloat; }
   bool hasRegionProtection() const { return HasRegionProtection; }
   bool hasRelocatableVector() const { return HasRelocatableVector; }
   bool hasMiscSR() const { return HasMiscSR; }

diff  --git a/llvm/test/CodeGen/Xtensa/add_shifted_imm.ll b/llvm/test/CodeGen/Xtensa/add_shifted_imm.ll
new file mode 100644
index 0000000000000..243076f4619a6
--- /dev/null
+++ b/llvm/test/CodeGen/Xtensa/add_shifted_imm.ll
@@ -0,0 +1,53 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=xtensa -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s
+
+define i64 @test_1(i32 %v) {
+; CHECK-LABEL: test_1:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:    l32r a8, .LCPI0_0
+; CHECK-NEXT:    add a2, a2, a8
+; CHECK-NEXT:    movi a3, 0
+; CHECK-NEXT:    ret
+  %addres = add i32 %v, -65536
+  %res = zext i32 %addres to i64
+  ret i64 %res
+}
+
+define i64 @test_2(i32 %v) {
+; CHECK-LABEL: test_2:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:    l32r a8, .LCPI1_0
+; CHECK-NEXT:    add a2, a2, a8
+; CHECK-NEXT:    movi a3, 0
+; CHECK-NEXT:    ret
+  %addres = add i32 %v, 65536
+  %res = zext i32 %addres to i64
+  ret i64 %res
+}
+
+define i64 @test_3(i32 %v) {
+; CHECK-LABEL: test_3:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:    addmi a2, a2, -32768
+; CHECK-NEXT:    movi a3, 0
+; CHECK-NEXT:    ret
+  %addres = add i32 %v, -32768
+  %res = zext i32 %addres to i64
+  ret i64 %res
+}
+
+define i64 @test_4(i32 %v) {
+; CHECK-LABEL: test_4:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:    addmi a2, a2, 32512
+; CHECK-NEXT:    movi a3, 0
+; CHECK-NEXT:    ret
+  %addres = add i32 %v, 32512
+  %res = zext i32 %addres to i64
+  ret i64 %res
+}

diff  --git a/llvm/test/CodeGen/Xtensa/aligned_alloc.ll b/llvm/test/CodeGen/Xtensa/aligned_alloc.ll
index ebb24d9272ddc..471158fb30b70 100644
--- a/llvm/test/CodeGen/Xtensa/aligned_alloc.ll
+++ b/llvm/test/CodeGen/Xtensa/aligned_alloc.ll
@@ -11,10 +11,10 @@ define i8 @loadi8_128(i8 %a) {
 ; XTENSA-NEXT:    .cfi_def_cfa_offset 128
 ; XTENSA-NEXT:    s32i a0, a1, 124 # 4-byte Folded Spill
 ; XTENSA-NEXT:    .cfi_offset a0, -4
+; XTENSA-NEXT:    l32r a8, .LCPI0_0
 ; XTENSA-NEXT:    addi a2, a1, 0
 ; XTENSA-NEXT:    movi a3, 0
 ; XTENSA-NEXT:    movi a4, 64
-; XTENSA-NEXT:    l32r a8, .LCPI0_0
 ; XTENSA-NEXT:    callx0 a8
 ; XTENSA-NEXT:    l8ui a2, a1, 0
 ; XTENSA-NEXT:    l32i a0, a1, 124 # 4-byte Folded Reload

diff  --git a/llvm/test/CodeGen/Xtensa/brcc_fp.ll b/llvm/test/CodeGen/Xtensa/brcc_fp.ll
new file mode 100644
index 0000000000000..3dd17b9ccb940
--- /dev/null
+++ b/llvm/test/CodeGen/Xtensa/brcc_fp.ll
@@ -0,0 +1,223 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=xtensa -mattr=+fp -disable-block-placement -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s
+
+define i32 @brcc_sgt(i32 %a, i32 %b) nounwind {
+; CHECK-LABEL: brcc_sgt:
+; CHECK:         bge a3, a2, .LBB0_2
+; CHECK-NEXT:  # %bb.1: # %t1
+; CHECK-NEXT:    addi a2, a2, 4
+; CHECK-NEXT:    ret
+; CHECK-NEXT:  .LBB0_2: # %t2
+; CHECK-NEXT:    addi a2, a3, 8
+; CHECK-NEXT:    ret
+  %wb = icmp sgt i32 %a, %b
+  br i1 %wb, label %t1, label %t2
+t1:
+  %t1v = add i32 %a, 4
+  br label %exit
+t2:
+  %t2v = add i32 %b, 8
+  br label %exit
+exit:
+  %v = phi i32 [ %t1v, %t1 ], [ %t2v, %t2 ]
+  ret i32 %v
+}
+
+define i32 @brcc_ugt(i32 %a, i32 %b) nounwind {
+; CHECK-LABEL: brcc_ugt:
+; CHECK:         bgeu a3, a2, .LBB1_2
+; CHECK-NEXT:  # %bb.1: # %t1
+; CHECK-NEXT:    addi a2, a2, 4
+; CHECK-NEXT:    ret
+; CHECK-NEXT:  .LBB1_2: # %t2
+; CHECK-NEXT:    addi a2, a3, 8
+; CHECK-NEXT:    ret
+  %wb = icmp ugt i32 %a, %b
+  br i1 %wb, label %t1, label %t2
+t1:
+  %t1v = add i32 %a, 4
+  br label %exit
+t2:
+  %t2v = add i32 %b, 8
+  br label %exit
+exit:
+  %v = phi i32 [ %t1v, %t1 ], [ %t2v, %t2 ]
+  ret i32 %v
+}
+
+define i32 @brcc_sle(i32 %a, i32 %b) nounwind {
+; CHECK-LABEL: brcc_sle:
+; CHECK:         blt a3, a2, .LBB2_2
+; CHECK-NEXT:  # %bb.1: # %t1
+; CHECK-NEXT:    addi a2, a2, 4
+; CHECK-NEXT:    ret
+; CHECK-NEXT:  .LBB2_2: # %t2
+; CHECK-NEXT:    addi a2, a3, 8
+; CHECK-NEXT:    ret
+  %wb = icmp sle i32 %a, %b
+  br i1 %wb, label %t1, label %t2
+t1:
+  %t1v = add i32 %a, 4
+  br label %exit
+t2:
+  %t2v = add i32 %b, 8
+  br label %exit
+exit:
+  %v = phi i32 [ %t1v, %t1 ], [ %t2v, %t2 ]
+  ret i32 %v
+}
+
+define i32 @brcc_ule(i32 %a, i32 %b) nounwind {
+; CHECK-LABEL: brcc_ule:
+; CHECK:         bltu a3, a2, .LBB3_2
+; CHECK-NEXT:  # %bb.1: # %t1
+; CHECK-NEXT:    addi a2, a2, 4
+; CHECK-NEXT:    ret
+; CHECK-NEXT:  .LBB3_2: # %t2
+; CHECK-NEXT:    addi a2, a3, 8
+; CHECK-NEXT:    ret
+  %wb = icmp ule i32 %a, %b
+  br i1 %wb, label %t1, label %t2
+t1:
+  %t1v = add i32 %a, 4
+  br label %exit
+t2:
+  %t2v = add i32 %b, 8
+  br label %exit
+exit:
+  %v = phi i32 [ %t1v, %t1 ], [ %t2v, %t2 ]
+  ret i32 %v
+}
+
+define i32 @brcc_eq(i32 %a, i32 %b) nounwind {
+; CHECK-LABEL: brcc_eq:
+; CHECK:         bne a2, a3, .LBB4_2
+; CHECK-NEXT:  # %bb.1: # %t1
+; CHECK-NEXT:    addi a2, a2, 4
+; CHECK-NEXT:    ret
+; CHECK-NEXT:  .LBB4_2: # %t2
+; CHECK-NEXT:    addi a2, a3, 8
+; CHECK-NEXT:    ret
+  %wb = icmp eq i32 %a, %b
+  br i1 %wb, label %t1, label %t2
+t1:
+  %t1v = add i32 %a, 4
+  br label %exit
+t2:
+  %t2v = add i32 %b, 8
+  br label %exit
+exit:
+  %v = phi i32 [ %t1v, %t1 ], [ %t2v, %t2 ]
+  ret i32 %v
+}
+
+define i32 @brcc_ne(i32 %a, i32 %b) nounwind {
+; CHECK-LABEL: brcc_ne:
+; CHECK:         beq a2, a3, .LBB5_2
+; CHECK-NEXT:  # %bb.1: # %t1
+; CHECK-NEXT:    addi a2, a2, 4
+; CHECK-NEXT:    ret
+; CHECK-NEXT:  .LBB5_2: # %t2
+; CHECK-NEXT:    addi a2, a3, 8
+; CHECK-NEXT:    ret
+  %wb = icmp ne i32 %a, %b
+  br i1 %wb, label %t1, label %t2
+t1:
+  %t1v = add i32 %a, 4
+  br label %exit
+t2:
+  %t2v = add i32 %b, 8
+  br label %exit
+exit:
+  %v = phi i32 [ %t1v, %t1 ], [ %t2v, %t2 ]
+  ret i32 %v
+}
+
+define i32 @brcc_ge(i32 %a, i32 %b) nounwind {
+; CHECK-LABEL: brcc_ge:
+; CHECK:         blt a2, a3, .LBB6_2
+; CHECK-NEXT:  # %bb.1: # %t1
+; CHECK-NEXT:    addi a2, a2, 4
+; CHECK-NEXT:    ret
+; CHECK-NEXT:  .LBB6_2: # %t2
+; CHECK-NEXT:    addi a2, a3, 8
+; CHECK-NEXT:    ret
+  %wb = icmp sge i32 %a, %b
+  br i1 %wb, label %t1, label %t2
+t1:
+  %t1v = add i32 %a, 4
+  br label %exit
+t2:
+  %t2v = add i32 %b, 8
+  br label %exit
+exit:
+  %v = phi i32 [ %t1v, %t1 ], [ %t2v, %t2 ]
+  ret i32 %v
+}
+
+define i32 @brcc_lt(i32 %a, i32 %b) nounwind {
+; CHECK-LABEL: brcc_lt:
+; CHECK:         bge a2, a3, .LBB7_2
+; CHECK-NEXT:  # %bb.1: # %t1
+; CHECK-NEXT:    addi a2, a2, 4
+; CHECK-NEXT:    ret
+; CHECK-NEXT:  .LBB7_2: # %t2
+; CHECK-NEXT:    addi a2, a3, 8
+; CHECK-NEXT:    ret
+  %wb = icmp slt i32 %a, %b
+  br i1 %wb, label %t1, label %t2
+t1:
+  %t1v = add i32 %a, 4
+  br label %exit
+t2:
+  %t2v = add i32 %b, 8
+  br label %exit
+exit:
+  %v = phi i32 [ %t1v, %t1 ], [ %t2v, %t2 ]
+  ret i32 %v
+}
+
+define i32 @brcc_uge(i32 %a, i32 %b) nounwind {
+; CHECK-LABEL: brcc_uge:
+; CHECK:         bltu a2, a3, .LBB8_2
+; CHECK-NEXT:  # %bb.1: # %t1
+; CHECK-NEXT:    addi a2, a2, 4
+; CHECK-NEXT:    ret
+; CHECK-NEXT:  .LBB8_2: # %t2
+; CHECK-NEXT:    addi a2, a3, 8
+; CHECK-NEXT:    ret
+  %wb = icmp uge i32 %a, %b
+  br i1 %wb, label %t1, label %t2
+t1:
+  %t1v = add i32 %a, 4
+  br label %exit
+t2:
+  %t2v = add i32 %b, 8
+  br label %exit
+exit:
+  %v = phi i32 [ %t1v, %t1 ], [ %t2v, %t2 ]
+  ret i32 %v
+}
+
+define i32 @brcc_ult(i32 %a, i32 %b) nounwind {
+; CHECK-LABEL: brcc_ult:
+; CHECK:         bgeu a2, a3, .LBB9_2
+; CHECK-NEXT:  # %bb.1: # %t1
+; CHECK-NEXT:    addi a2, a2, 4
+; CHECK-NEXT:    ret
+; CHECK-NEXT:  .LBB9_2: # %t2
+; CHECK-NEXT:    addi a2, a3, 8
+; CHECK-NEXT:    ret
+  %wb = icmp ult i32 %a, %b
+  br i1 %wb, label %t1, label %t2
+t1:
+  %t1v = add i32 %a, 4
+  br label %exit
+t2:
+  %t2v = add i32 %b, 8
+  br label %exit
+exit:
+  %v = phi i32 [ %t1v, %t1 ], [ %t2v, %t2 ]
+  ret i32 %v
+}

diff  --git a/llvm/test/CodeGen/Xtensa/bswap.ll b/llvm/test/CodeGen/Xtensa/bswap.ll
index 6a87aa84351cf..a836f4c30e3eb 100644
--- a/llvm/test/CodeGen/Xtensa/bswap.ll
+++ b/llvm/test/CodeGen/Xtensa/bswap.ll
@@ -12,7 +12,8 @@ declare i64 @llvm.bitreverse.i64(i64)
 
 define i16 @test_bswap_i16(i16 %a) nounwind {
 ; XTENSA-LABEL: test_bswap_i16:
-; XTENSA:         l32r a8, .LCPI0_0
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    l32r a8, .LCPI0_0
 ; XTENSA-NEXT:    and a8, a2, a8
 ; XTENSA-NEXT:    srli a8, a8, 8
 ; XTENSA-NEXT:    slli a9, a2, 8
@@ -24,7 +25,8 @@ define i16 @test_bswap_i16(i16 %a) nounwind {
 
 define i32 @test_bswap_i32(i32 %a) nounwind {
 ; XTENSA-LABEL: test_bswap_i32:
-; XTENSA:         srli a8, a2, 8
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    srli a8, a2, 8
 ; XTENSA-NEXT:    l32r a9, .LCPI1_0
 ; XTENSA-NEXT:    and a8, a8, a9
 ; XTENSA-NEXT:    extui a10, a2, 24, 8
@@ -41,7 +43,8 @@ define i32 @test_bswap_i32(i32 %a) nounwind {
 
 define i64 @test_bswap_i64(i64 %a) nounwind {
 ; XTENSA-LABEL: test_bswap_i64:
-; XTENSA:         srli a8, a3, 8
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    srli a8, a3, 8
 ; XTENSA-NEXT:    l32r a9, .LCPI2_0
 ; XTENSA-NEXT:    and a8, a8, a9
 ; XTENSA-NEXT:    extui a10, a3, 24, 8
@@ -68,7 +71,8 @@ define i64 @test_bswap_i64(i64 %a) nounwind {
 
 define i8 @test_bitreverse_i8(i8 %a) nounwind {
 ; XTENSA-LABEL: test_bitreverse_i8:
-; XTENSA:         movi a8, 15
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    movi a8, 15
 ; XTENSA-NEXT:    and a8, a2, a8
 ; XTENSA-NEXT:    slli a8, a8, 4
 ; XTENSA-NEXT:    movi a9, 240
@@ -94,7 +98,8 @@ define i8 @test_bitreverse_i8(i8 %a) nounwind {
 
 define i16 @test_bitreverse_i16(i16 %a) nounwind {
 ; XTENSA-LABEL: test_bitreverse_i16:
-; XTENSA:         l32r a8, .LCPI4_0
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    l32r a8, .LCPI4_0
 ; XTENSA-NEXT:    and a8, a2, a8
 ; XTENSA-NEXT:    srli a8, a8, 8
 ; XTENSA-NEXT:    slli a9, a2, 8
@@ -124,7 +129,8 @@ define i16 @test_bitreverse_i16(i16 %a) nounwind {
 
 define i32 @test_bitreverse_i32(i32 %a) nounwind {
 ; XTENSA-LABEL: test_bitreverse_i32:
-; XTENSA:         srli a8, a2, 8
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    srli a8, a2, 8
 ; XTENSA-NEXT:    l32r a9, .LCPI5_0
 ; XTENSA-NEXT:    and a8, a8, a9
 ; XTENSA-NEXT:    extui a10, a2, 24, 8
@@ -159,7 +165,8 @@ define i32 @test_bitreverse_i32(i32 %a) nounwind {
 
 define i64 @test_bitreverse_i64(i64 %a) nounwind {
 ; XTENSA-LABEL: test_bitreverse_i64:
-; XTENSA:         srli a8, a3, 8
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    srli a8, a3, 8
 ; XTENSA-NEXT:    l32r a9, .LCPI6_0
 ; XTENSA-NEXT:    and a8, a8, a9
 ; XTENSA-NEXT:    extui a10, a3, 24, 8
@@ -219,7 +226,8 @@ define i64 @test_bitreverse_i64(i64 %a) nounwind {
 
 define i16 @test_bswap_bitreverse_i16(i16 %a) nounwind {
 ; XTENSA-LABEL: test_bswap_bitreverse_i16:
-; XTENSA:         srli a8, a2, 4
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    srli a8, a2, 4
 ; XTENSA-NEXT:    l32r a9, .LCPI7_0
 ; XTENSA-NEXT:    and a8, a8, a9
 ; XTENSA-NEXT:    and a9, a2, a9
@@ -245,7 +253,8 @@ define i16 @test_bswap_bitreverse_i16(i16 %a) nounwind {
 
 define i32 @test_bswap_bitreverse_i32(i32 %a) nounwind {
 ; XTENSA-LABEL: test_bswap_bitreverse_i32:
-; XTENSA:         srli a8, a2, 4
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    srli a8, a2, 4
 ; XTENSA-NEXT:    l32r a9, .LCPI8_0
 ; XTENSA-NEXT:    and a8, a8, a9
 ; XTENSA-NEXT:    and a9, a2, a9
@@ -271,7 +280,8 @@ define i32 @test_bswap_bitreverse_i32(i32 %a) nounwind {
 
 define i64 @test_bswap_bitreverse_i64(i64 %a) nounwind {
 ; XTENSA-LABEL: test_bswap_bitreverse_i64:
-; XTENSA:         srli a8, a2, 4
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    srli a8, a2, 4
 ; XTENSA-NEXT:    l32r a9, .LCPI9_0
 ; XTENSA-NEXT:    and a8, a8, a9
 ; XTENSA-NEXT:    and a10, a2, a9
@@ -312,7 +322,8 @@ define i64 @test_bswap_bitreverse_i64(i64 %a) nounwind {
 
 define i16 @test_bitreverse_bswap_i16(i16 %a) nounwind {
 ; XTENSA-LABEL: test_bitreverse_bswap_i16:
-; XTENSA:         srli a8, a2, 4
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    srli a8, a2, 4
 ; XTENSA-NEXT:    l32r a9, .LCPI10_0
 ; XTENSA-NEXT:    and a8, a8, a9
 ; XTENSA-NEXT:    and a9, a2, a9
@@ -338,7 +349,8 @@ define i16 @test_bitreverse_bswap_i16(i16 %a) nounwind {
 
 define i32 @test_bitreverse_bswap_i32(i32 %a) nounwind {
 ; XTENSA-LABEL: test_bitreverse_bswap_i32:
-; XTENSA:         srli a8, a2, 4
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    srli a8, a2, 4
 ; XTENSA-NEXT:    l32r a9, .LCPI11_0
 ; XTENSA-NEXT:    and a8, a8, a9
 ; XTENSA-NEXT:    and a9, a2, a9
@@ -364,7 +376,8 @@ define i32 @test_bitreverse_bswap_i32(i32 %a) nounwind {
 
 define i64 @test_bitreverse_bswap_i64(i64 %a) nounwind {
 ; XTENSA-LABEL: test_bitreverse_bswap_i64:
-; XTENSA:         srli a8, a2, 4
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    srli a8, a2, 4
 ; XTENSA-NEXT:    l32r a9, .LCPI12_0
 ; XTENSA-NEXT:    and a8, a8, a9
 ; XTENSA-NEXT:    and a10, a2, a9

diff  --git a/llvm/test/CodeGen/Xtensa/ctlz-cttz-ctpop.ll b/llvm/test/CodeGen/Xtensa/ctlz-cttz-ctpop.ll
index 6030323538625..2524a333556e2 100644
--- a/llvm/test/CodeGen/Xtensa/ctlz-cttz-ctpop.ll
+++ b/llvm/test/CodeGen/Xtensa/ctlz-cttz-ctpop.ll
@@ -8,7 +8,8 @@ declare i32 @llvm.ctpop.i32(i32)
 
 define i32 @test_cttz_i32(i32 %a) nounwind {
 ; XTENSA-LABEL: test_cttz_i32:
-; XTENSA:         beqz a2, .LBB0_2
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    beqz a2, .LBB0_2
 ; XTENSA-NEXT:  # %bb.1: # %cond.false
 ; XTENSA-NEXT:    movi a8, -1
 ; XTENSA-NEXT:    xor a8, a2, a8
@@ -42,7 +43,8 @@ define i32 @test_cttz_i32(i32 %a) nounwind {
 
 define i32 @test_cttz_i32_zero_undef(i32 %a) nounwind {
 ; XTENSA-LABEL: test_cttz_i32_zero_undef:
-; XTENSA:         movi a8, -1
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    movi a8, -1
 ; XTENSA-NEXT:    xor a8, a2, a8
 ; XTENSA-NEXT:    addi a9, a2, -1
 ; XTENSA-NEXT:    and a8, a8, a9
@@ -71,7 +73,8 @@ define i32 @test_cttz_i32_zero_undef(i32 %a) nounwind {
 
 define i32 @test_ctlz_i32(i32 %a) nounwind {
 ; XTENSA-LABEL: test_ctlz_i32:
-; XTENSA:         beqz a2, .LBB2_2
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    beqz a2, .LBB2_2
 ; XTENSA-NEXT:  # %bb.1: # %cond.false
 ; XTENSA-NEXT:    srli a8, a2, 1
 ; XTENSA-NEXT:    or a8, a2, a8
@@ -113,7 +116,8 @@ define i32 @test_ctlz_i32(i32 %a) nounwind {
 
 define i32 @test_ctlz_i32_zero_undef(i32 %a) nounwind {
 ; XTENSA-LABEL: test_ctlz_i32_zero_undef:
-; XTENSA:         srli a8, a2, 1
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    srli a8, a2, 1
 ; XTENSA-NEXT:    or a8, a2, a8
 ; XTENSA-NEXT:    srli a9, a8, 2
 ; XTENSA-NEXT:    or a8, a8, a9
@@ -150,7 +154,8 @@ define i32 @test_ctlz_i32_zero_undef(i32 %a) nounwind {
 
 define i32 @test_ctpop_i32(i32 %a) nounwind {
 ; XTENSA-LABEL: test_ctpop_i32:
-; XTENSA:         srli a8, a2, 1
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    srli a8, a2, 1
 ; XTENSA-NEXT:    l32r a9, .LCPI4_0
 ; XTENSA-NEXT:    and a8, a8, a9
 ; XTENSA-NEXT:    sub a8, a2, a8

diff  --git a/llvm/test/CodeGen/Xtensa/float-arith.ll b/llvm/test/CodeGen/Xtensa/float-arith.ll
new file mode 100644
index 0000000000000..2b7186c44aebf
--- /dev/null
+++ b/llvm/test/CodeGen/Xtensa/float-arith.ll
@@ -0,0 +1,603 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=xtensa -mattr=+fp -verify-machineinstrs < %s | FileCheck -check-prefix=XTENSA %s
+
+define float @fadd_s(float %a, float %b) nounwind {
+; XTENSA-LABEL: fadd_s:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    wfr f8, a3
+; XTENSA-NEXT:    wfr f9, a2
+; XTENSA-NEXT:    add.s f8, f9, f8
+; XTENSA-NEXT:    rfr a2, f8
+; XTENSA-NEXT:    ret
+  %res = fadd float %a, %b
+  ret float %res
+}
+
+define float @fsub_s(float %a, float %b) nounwind {
+; XTENSA-LABEL: fsub_s:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    wfr f8, a3
+; XTENSA-NEXT:    wfr f9, a2
+; XTENSA-NEXT:    sub.s f8, f9, f8
+; XTENSA-NEXT:    rfr a2, f8
+; XTENSA-NEXT:    ret
+  %res = fsub float %a, %b
+  ret float %res
+}
+
+define float @fmul_s(float %a, float %b) nounwind {
+; XTENSA-LABEL: fmul_s:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    wfr f8, a3
+; XTENSA-NEXT:    wfr f9, a2
+; XTENSA-NEXT:    mul.s f8, f9, f8
+; XTENSA-NEXT:    rfr a2, f8
+; XTENSA-NEXT:    ret
+  %res = fmul float %a, %b
+  ret float %res
+}
+
+define float @fdiv_s(float %a, float %b) nounwind {
+; XTENSA-LABEL: fdiv_s:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    addi a8, a1, -16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    s32i a0, a1, 0 # 4-byte Folded Spill
+; XTENSA-NEXT:    l32r a8, .LCPI3_0
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    l32i a0, a1, 0 # 4-byte Folded Reload
+; XTENSA-NEXT:    addi a8, a1, 16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    ret
+  %res = fdiv float %a, %b
+  ret float %res
+}
+
+declare float @llvm.sqrt.f32(float)
+
+define float @fsqrt_s(float %a) nounwind {
+; XTENSA-LABEL: fsqrt_s:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    addi a8, a1, -16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    s32i a0, a1, 0 # 4-byte Folded Spill
+; XTENSA-NEXT:    l32r a8, .LCPI4_0
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    l32i a0, a1, 0 # 4-byte Folded Reload
+; XTENSA-NEXT:    addi a8, a1, 16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    ret
+  %res = call float @llvm.sqrt.f32(float %a)
+  ret float %res
+}
+
+declare float @llvm.fabs.f32(float)
+
+define float @fabs_s(float %a, float %b) nounwind {
+; XTENSA-LABEL: fabs_s:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    wfr f8, a3
+; XTENSA-NEXT:    wfr f9, a2
+; XTENSA-NEXT:    add.s f8, f9, f8
+; XTENSA-NEXT:    abs.s f9, f8
+; XTENSA-NEXT:    add.s f8, f9, f8
+; XTENSA-NEXT:    rfr a2, f8
+; XTENSA-NEXT:    ret
+  %fa = fadd float %a, %b
+  %call_res = call float @llvm.fabs.f32(float %fa)
+  %res = fadd float %call_res, %fa
+  ret float %res
+}
+
+declare float @llvm.minnum.f32(float, float)
+
+define float @fmin_s(float %a, float %b) nounwind {
+; XTENSA-LABEL: fmin_s:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    addi a8, a1, -16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    s32i a0, a1, 0 # 4-byte Folded Spill
+; XTENSA-NEXT:    l32r a8, .LCPI6_0
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    l32i a0, a1, 0 # 4-byte Folded Reload
+; XTENSA-NEXT:    addi a8, a1, 16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    ret
+  %res = call float @llvm.minnum.f32(float %a, float %b)
+  ret float %res
+}
+
+declare float @llvm.maxnum.f32(float, float)
+
+define float @fmax_s(float %a, float %b) nounwind {
+; XTENSA-LABEL: fmax_s:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    addi a8, a1, -16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    s32i a0, a1, 0 # 4-byte Folded Spill
+; XTENSA-NEXT:    l32r a8, .LCPI7_0
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    l32i a0, a1, 0 # 4-byte Folded Reload
+; XTENSA-NEXT:    addi a8, a1, 16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    ret
+  %res = call float @llvm.maxnum.f32(float %a, float %b)
+  ret float %res
+}
+
+declare float @llvm.fma.f32(float, float, float)
+
+define float @fmadd_s(float %a, float %b, float %c) nounwind {
+; XTENSA-LABEL: fmadd_s:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    wfr f8, a3
+; XTENSA-NEXT:    wfr f9, a2
+; XTENSA-NEXT:    wfr f10, a4
+; XTENSA-NEXT:    madd.s f10, f9, f8
+; XTENSA-NEXT:    rfr a2, f10
+; XTENSA-NEXT:    ret
+  %res = call float @llvm.fma.f32(float %a, float %b, float %c)
+  ret float %res
+}
+
+define float @fmsub_s(float %a, float %b, float %c) nounwind {
+; XTENSA-LABEL: fmsub_s:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    l32r a8, .LCPI9_0
+; XTENSA-NEXT:    wfr f8, a8
+; XTENSA-NEXT:    wfr f9, a4
+; XTENSA-NEXT:    add.s f8, f9, f8
+; XTENSA-NEXT:    neg.s f8, f8
+; XTENSA-NEXT:    wfr f9, a3
+; XTENSA-NEXT:    wfr f10, a2
+; XTENSA-NEXT:    madd.s f8, f10, f9
+; XTENSA-NEXT:    rfr a2, f8
+; XTENSA-NEXT:    ret
+  %c_ = fadd float 0.0, %c ; avoid negation using xor
+  %negc = fsub float -0.0, %c_
+  %res = call float @llvm.fma.f32(float %a, float %b, float %negc)
+  ret float %res
+}
+
+define float @fnmadd_s(float %a, float %b, float %c) nounwind {
+; XTENSA-LABEL: fnmadd_s:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    l32r a8, .LCPI10_0
+; XTENSA-NEXT:    wfr f8, a8
+; XTENSA-NEXT:    wfr f9, a2
+; XTENSA-NEXT:    add.s f9, f9, f8
+; XTENSA-NEXT:    neg.s f9, f9
+; XTENSA-NEXT:    wfr f10, a4
+; XTENSA-NEXT:    add.s f8, f10, f8
+; XTENSA-NEXT:    neg.s f8, f8
+; XTENSA-NEXT:    wfr f10, a3
+; XTENSA-NEXT:    madd.s f8, f9, f10
+; XTENSA-NEXT:    rfr a2, f8
+; XTENSA-NEXT:    ret
+  %a_ = fadd float 0.0, %a
+  %c_ = fadd float 0.0, %c
+  %nega = fsub float -0.0, %a_
+  %negc = fsub float -0.0, %c_
+  %res = call float @llvm.fma.f32(float %nega, float %b, float %negc)
+  ret float %res
+}
+
+define float @fnmadd_s_2(float %a, float %b, float %c) nounwind {
+; XTENSA-LABEL: fnmadd_s_2:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    l32r a8, .LCPI11_0
+; XTENSA-NEXT:    wfr f8, a8
+; XTENSA-NEXT:    wfr f9, a3
+; XTENSA-NEXT:    add.s f9, f9, f8
+; XTENSA-NEXT:    neg.s f9, f9
+; XTENSA-NEXT:    wfr f10, a4
+; XTENSA-NEXT:    add.s f8, f10, f8
+; XTENSA-NEXT:    neg.s f8, f8
+; XTENSA-NEXT:    wfr f10, a2
+; XTENSA-NEXT:    madd.s f8, f10, f9
+; XTENSA-NEXT:    rfr a2, f8
+; XTENSA-NEXT:    ret
+  %b_ = fadd float 0.0, %b
+  %c_ = fadd float 0.0, %c
+  %negb = fsub float -0.0, %b_
+  %negc = fsub float -0.0, %c_
+  %res = call float @llvm.fma.f32(float %a, float %negb, float %negc)
+  ret float %res
+}
+
+define float @fnmadd_s_3(float %a, float %b, float %c) nounwind {
+; XTENSA-LABEL: fnmadd_s_3:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    wfr f8, a3
+; XTENSA-NEXT:    wfr f9, a2
+; XTENSA-NEXT:    wfr f10, a4
+; XTENSA-NEXT:    madd.s f10, f9, f8
+; XTENSA-NEXT:    rfr a8, f10
+; XTENSA-NEXT:    l32r a9, .LCPI12_0
+; XTENSA-NEXT:    xor a2, a8, a9
+; XTENSA-NEXT:    ret
+  %res = call float @llvm.fma.f32(float %a, float %b, float %c)
+  %neg = fneg float %res
+  ret float %neg
+}
+
+define float @fnmadd_nsz(float %a, float %b, float %c) nounwind {
+; XTENSA-LABEL: fnmadd_nsz:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    wfr f8, a3
+; XTENSA-NEXT:    wfr f9, a2
+; XTENSA-NEXT:    wfr f10, a4
+; XTENSA-NEXT:    madd.s f10, f9, f8
+; XTENSA-NEXT:    rfr a8, f10
+; XTENSA-NEXT:    l32r a9, .LCPI13_0
+; XTENSA-NEXT:    xor a2, a8, a9
+; XTENSA-NEXT:    ret
+  %res = call nsz float @llvm.fma.f32(float %a, float %b, float %c)
+  %neg = fneg nsz float %res
+  ret float %neg
+}
+
+define float @fnmsub_s(float %a, float %b, float %c) nounwind {
+; XTENSA-LABEL: fnmsub_s:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    l32r a8, .LCPI14_0
+; XTENSA-NEXT:    wfr f8, a8
+; XTENSA-NEXT:    wfr f9, a2
+; XTENSA-NEXT:    add.s f8, f9, f8
+; XTENSA-NEXT:    neg.s f8, f8
+; XTENSA-NEXT:    wfr f9, a3
+; XTENSA-NEXT:    wfr f10, a4
+; XTENSA-NEXT:    madd.s f10, f8, f9
+; XTENSA-NEXT:    rfr a2, f10
+; XTENSA-NEXT:    ret
+  %a_ = fadd float 0.0, %a
+  %nega = fsub float -0.0, %a_
+  %res = call float @llvm.fma.f32(float %nega, float %b, float %c)
+  ret float %res
+}
+
+define float @fnmsub_s_2(float %a, float %b, float %c) nounwind {
+; XTENSA-LABEL: fnmsub_s_2:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    l32r a8, .LCPI15_0
+; XTENSA-NEXT:    wfr f8, a8
+; XTENSA-NEXT:    wfr f9, a3
+; XTENSA-NEXT:    add.s f8, f9, f8
+; XTENSA-NEXT:    neg.s f8, f8
+; XTENSA-NEXT:    wfr f9, a2
+; XTENSA-NEXT:    wfr f10, a4
+; XTENSA-NEXT:    madd.s f10, f9, f8
+; XTENSA-NEXT:    rfr a2, f10
+; XTENSA-NEXT:    ret
+  %b_ = fadd float 0.0, %b
+  %negb = fsub float -0.0, %b_
+  %res = call float @llvm.fma.f32(float %a, float %negb, float %c)
+  ret float %res
+}
+
+define float @fmadd_s_contract(float %a, float %b, float %c) nounwind {
+; XTENSA-LABEL: fmadd_s_contract:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    wfr f8, a3
+; XTENSA-NEXT:    wfr f9, a2
+; XTENSA-NEXT:    mul.s f8, f9, f8
+; XTENSA-NEXT:    wfr f9, a4
+; XTENSA-NEXT:    add.s f8, f8, f9
+; XTENSA-NEXT:    rfr a2, f8
+; XTENSA-NEXT:    ret
+  %fm = fmul contract float %a, %b
+  %res = fadd contract float %fm, %c
+  ret float %res
+}
+
+define float @fmsub_s_contract(float %a, float %b, float %c) nounwind {
+; XTENSA-LABEL: fmsub_s_contract:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    l32r a8, .LCPI17_0
+; XTENSA-NEXT:    wfr f8, a8
+; XTENSA-NEXT:    wfr f9, a4
+; XTENSA-NEXT:    add.s f8, f9, f8
+; XTENSA-NEXT:    wfr f9, a3
+; XTENSA-NEXT:    wfr f10, a2
+; XTENSA-NEXT:    mul.s f9, f10, f9
+; XTENSA-NEXT:    sub.s f8, f9, f8
+; XTENSA-NEXT:    rfr a2, f8
+; XTENSA-NEXT:    ret
+  %c_ = fadd float 0.0, %c ; avoid negation using xor
+  %fm = fmul contract float %a, %b
+  %res = fsub contract float %fm, %c_
+  ret float %res
+}
+
+define float @fnmadd_s_contract(float %a, float %b, float %c) nounwind {
+; XTENSA-LABEL: fnmadd_s_contract:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    l32r a8, .LCPI18_0
+; XTENSA-NEXT:    wfr f8, a8
+; XTENSA-NEXT:    wfr f9, a3
+; XTENSA-NEXT:    add.s f9, f9, f8
+; XTENSA-NEXT:    wfr f10, a2
+; XTENSA-NEXT:    add.s f10, f10, f8
+; XTENSA-NEXT:    mul.s f9, f10, f9
+; XTENSA-NEXT:    neg.s f9, f9
+; XTENSA-NEXT:    wfr f10, a4
+; XTENSA-NEXT:    add.s f8, f10, f8
+; XTENSA-NEXT:    sub.s f8, f9, f8
+; XTENSA-NEXT:    rfr a2, f8
+; XTENSA-NEXT:    ret
+  %a_ = fadd float 0.0, %a ; avoid negation using xor
+  %b_ = fadd float 0.0, %b ; avoid negation using xor
+  %c_ = fadd float 0.0, %c ; avoid negation using xor
+  %fm = fmul contract float %a_, %b_
+  %fn = fneg float %fm
+  %res = fsub contract float %fn, %c_
+  ret float %res
+}
+
+define float @fnmsub_s_contract(float %a, float %b, float %c) nounwind {
+; XTENSA-LABEL: fnmsub_s_contract:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    l32r a8, .LCPI19_0
+; XTENSA-NEXT:    wfr f8, a8
+; XTENSA-NEXT:    wfr f9, a3
+; XTENSA-NEXT:    add.s f9, f9, f8
+; XTENSA-NEXT:    wfr f10, a2
+; XTENSA-NEXT:    add.s f8, f10, f8
+; XTENSA-NEXT:    mul.s f8, f8, f9
+; XTENSA-NEXT:    wfr f9, a4
+; XTENSA-NEXT:    sub.s f8, f9, f8
+; XTENSA-NEXT:    rfr a2, f8
+; XTENSA-NEXT:    ret
+  %a_ = fadd float 0.0, %a ; avoid negation using xor
+  %b_ = fadd float 0.0, %b ; avoid negation using xor
+  %fm = fmul contract float %a_, %b_
+  %res = fsub contract float %c, %fm
+  ret float %res
+}
+
+declare float @llvm.powi.f32(float, i32)
+
+define float @powi_f32(float %a, i32 %b) nounwind {
+; XTENSA-LABEL: powi_f32:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    addi a8, a1, -16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    s32i a0, a1, 0 # 4-byte Folded Spill
+; XTENSA-NEXT:    l32r a8, .LCPI20_0
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    l32i a0, a1, 0 # 4-byte Folded Reload
+; XTENSA-NEXT:    addi a8, a1, 16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    ret
+
+  %res = call float @llvm.powi.f32(float %a, i32 %b)
+  ret float %res
+}
+
+declare float @llvm.sin.f32(float)
+
+define float @sin_f32(float %a) nounwind {
+; XTENSA-LABEL: sin_f32:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    addi a8, a1, -16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    s32i a0, a1, 0 # 4-byte Folded Spill
+; XTENSA-NEXT:    l32r a8, .LCPI21_0
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    l32i a0, a1, 0 # 4-byte Folded Reload
+; XTENSA-NEXT:    addi a8, a1, 16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    ret
+  %res = call float @llvm.sin.f32(float %a)
+  ret float %res
+}
+
+declare float @llvm.cos.f32(float)
+
+define float @cos_f32(float %a) nounwind {
+; XTENSA-LABEL: cos_f32:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    addi a8, a1, -16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    s32i a0, a1, 0 # 4-byte Folded Spill
+; XTENSA-NEXT:    l32r a8, .LCPI22_0
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    l32i a0, a1, 0 # 4-byte Folded Reload
+; XTENSA-NEXT:    addi a8, a1, 16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    ret
+  %res = call float @llvm.cos.f32(float %a)
+  ret float %res
+}
+declare float @llvm.exp.f32(float)
+
+define float @exp_f32(float %a) nounwind {
+; XTENSA-LABEL: exp_f32:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    addi a8, a1, -16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    s32i a0, a1, 0 # 4-byte Folded Spill
+; XTENSA-NEXT:    l32r a8, .LCPI23_0
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    l32i a0, a1, 0 # 4-byte Folded Reload
+; XTENSA-NEXT:    addi a8, a1, 16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    ret
+  %res = call float @llvm.exp.f32(float %a)
+  ret float %res
+}
+
+define float @log_f32(float %a) nounwind {
+; XTENSA-LABEL: log_f32:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    addi a8, a1, -16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    s32i a0, a1, 0 # 4-byte Folded Spill
+; XTENSA-NEXT:    l32r a8, .LCPI24_0
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    l32i a0, a1, 0 # 4-byte Folded Reload
+; XTENSA-NEXT:    addi a8, a1, 16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    ret
+  %res = call float @llvm.log.f32(float %a)
+  ret float %res
+}
+
+declare float @llvm.log10.f32(float)
+
+define float @log10_f32(float %a) nounwind {
+; XTENSA-LABEL: log10_f32:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    addi a8, a1, -16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    s32i a0, a1, 0 # 4-byte Folded Spill
+; XTENSA-NEXT:    l32r a8, .LCPI25_0
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    l32i a0, a1, 0 # 4-byte Folded Reload
+; XTENSA-NEXT:    addi a8, a1, 16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    ret
+  %res = call float @llvm.log10.f32(float %a)
+  ret float %res
+}
+
+declare float @llvm.log2.f32(float)
+
+define float @log2_f32(float %a) nounwind {
+; XTENSA-LABEL: log2_f32:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    addi a8, a1, -16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    s32i a0, a1, 0 # 4-byte Folded Spill
+; XTENSA-NEXT:    l32r a8, .LCPI26_0
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    l32i a0, a1, 0 # 4-byte Folded Reload
+; XTENSA-NEXT:    addi a8, a1, 16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    ret
+  %res = call float @llvm.log2.f32(float %a)
+  ret float %res
+}
+
+declare float @llvm.floor.f32(float)
+
+define float @floor_f32(float %a) nounwind {
+; XTENSA-LABEL: floor_f32:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    addi a8, a1, -16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    s32i a0, a1, 0 # 4-byte Folded Spill
+; XTENSA-NEXT:    l32r a8, .LCPI27_0
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    l32i a0, a1, 0 # 4-byte Folded Reload
+; XTENSA-NEXT:    addi a8, a1, 16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    ret
+  %res = call float @llvm.floor.f32(float %a)
+  ret float %res
+}
+
+declare float @llvm.ceil.f32(float)
+
+define float @ceil_f32(float %a) nounwind {
+; XTENSA-LABEL: ceil_f32:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    addi a8, a1, -16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    s32i a0, a1, 0 # 4-byte Folded Spill
+; XTENSA-NEXT:    l32r a8, .LCPI28_0
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    l32i a0, a1, 0 # 4-byte Folded Reload
+; XTENSA-NEXT:    addi a8, a1, 16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    ret
+  %res = call float @llvm.ceil.f32(float %a)
+  ret float %res
+}
+declare float @llvm.rint.f32(float)
+
+define float @rint_f32(float %a) nounwind {
+; XTENSA-LABEL: rint_f32:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    addi a8, a1, -16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    s32i a0, a1, 0 # 4-byte Folded Spill
+; XTENSA-NEXT:    l32r a8, .LCPI29_0
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    l32i a0, a1, 0 # 4-byte Folded Reload
+; XTENSA-NEXT:    addi a8, a1, 16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    ret
+  %res = call float @llvm.rint.f32(float %a)
+  ret float %res
+}
+
+declare float @llvm.nearbyint.f32(float)
+
+define float @nearbyint_f32(float %a) nounwind {
+; XTENSA-LABEL: nearbyint_f32:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    addi a8, a1, -16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    s32i a0, a1, 0 # 4-byte Folded Spill
+; XTENSA-NEXT:    l32r a8, .LCPI30_0
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    l32i a0, a1, 0 # 4-byte Folded Reload
+; XTENSA-NEXT:    addi a8, a1, 16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    ret
+  %res = call float @llvm.nearbyint.f32(float %a)
+  ret float %res
+}
+
+declare float @llvm.round.f32(float)
+
+define float @round_f32(float %a) nounwind {
+; XTENSA-LABEL: round_f32:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    addi a8, a1, -16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    s32i a0, a1, 0 # 4-byte Folded Spill
+; XTENSA-NEXT:    l32r a8, .LCPI31_0
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    l32i a0, a1, 0 # 4-byte Folded Reload
+; XTENSA-NEXT:    addi a8, a1, 16
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    ret
+  %res = call float @llvm.round.f32(float %a)
+  ret float %res
+}
+
+
+define float @fneg_s(float %a) nounwind {
+; XTENSA-LABEL: fneg_s:
+; XTENSA:       # %bb.0:
+; XTENSA-NEXT:    l32r a8, .LCPI32_0
+; XTENSA-NEXT:    and a2, a2, a8
+; XTENSA-NEXT:    ret
+  %res = call float @llvm.fabs.f32(float %a)
+  ret float %res
+}
+
+define i32 @fptosi(float %f) {
+; XTENSA-LABEL: fptosi:
+; XTENSA:         .cfi_startproc
+; XTENSA-NEXT:  # %bb.0:
+; XTENSA-NEXT:    wfr f8, a2
+; XTENSA-NEXT:    trunc.s a2, f8, 0
+; XTENSA-NEXT:    ret
+  %conv = fptosi float %f to i32
+  ret i32 %conv
+}
+
+define i32 @fptoui(float %f) {
+; XTENSA-LABEL: fptoui:
+; XTENSA:         .cfi_startproc
+; XTENSA-NEXT:  # %bb.0:
+; XTENSA-NEXT:    wfr f8, a2
+; XTENSA-NEXT:    utrunc.s a2, f8, 0
+; XTENSA-NEXT:    ret
+  %conv = fptoui float %f to i32
+  ret i32 %conv
+}
+

diff  --git a/llvm/test/CodeGen/Xtensa/mul.ll b/llvm/test/CodeGen/Xtensa/mul.ll
index 6901323822280..4dd03e408fcf4 100644
--- a/llvm/test/CodeGen/Xtensa/mul.ll
+++ b/llvm/test/CodeGen/Xtensa/mul.ll
@@ -767,51 +767,52 @@ define i64 @muli64_m3840(i64 %a) nounwind {
 define i128 @muli128_m3840(i128 %a) nounwind {
 ; XTENSA-LABEL: muli128_m3840:
 ; XTENSA:       # %bb.0:
-; XTENSA-NEXT:    addi a8, a1, -80
+; XTENSA-NEXT:    addi a8, a1, -64
 ; XTENSA-NEXT:    or a1, a8, a8
-; XTENSA-NEXT:    s32i a0, a1, 64 # 4-byte Folded Spill
-; XTENSA-NEXT:    s32i a12, a1, 60 # 4-byte Folded Spill
-; XTENSA-NEXT:    s32i a13, a1, 56 # 4-byte Folded Spill
-; XTENSA-NEXT:    s32i a14, a1, 52 # 4-byte Folded Spill
-; XTENSA-NEXT:    s32i a15, a1, 48 # 4-byte Folded Spill
+; XTENSA-NEXT:    s32i a0, a1, 60 # 4-byte Folded Spill
+; XTENSA-NEXT:    s32i a12, a1, 56 # 4-byte Folded Spill
+; XTENSA-NEXT:    s32i a13, a1, 52 # 4-byte Folded Spill
+; XTENSA-NEXT:    s32i a14, a1, 48 # 4-byte Folded Spill
+; XTENSA-NEXT:    s32i a15, a1, 44 # 4-byte Folded Spill
 ; XTENSA-NEXT:    s32i a5, a1, 20 # 4-byte Folded Spill
 ; XTENSA-NEXT:    s32i a4, a1, 16 # 4-byte Folded Spill
-; XTENSA-NEXT:    or a15, a3, a3
-; XTENSA-NEXT:    l32r a14, .LCPI30_0
+; XTENSA-NEXT:    or a13, a3, a3
+; XTENSA-NEXT:    l32r a15, .LCPI30_0
 ; XTENSA-NEXT:    movi a12, 0
-; XTENSA-NEXT:    l32r a13, .LCPI30_1
+; XTENSA-NEXT:    l32r a8, .LCPI30_1
 ; XTENSA-NEXT:    s32i a2, a1, 36 # 4-byte Folded Spill
 ; XTENSA-NEXT:    or a3, a12, a12
-; XTENSA-NEXT:    or a4, a14, a14
+; XTENSA-NEXT:    or a4, a15, a15
 ; XTENSA-NEXT:    or a5, a12, a12
-; XTENSA-NEXT:    callx0 a13
+; XTENSA-NEXT:    callx0 a8
 ; XTENSA-NEXT:    s32i a2, a1, 28 # 4-byte Folded Spill
-; XTENSA-NEXT:    s32i a3, a1, 44 # 4-byte Folded Spill
-; XTENSA-NEXT:    s32i a15, a1, 40 # 4-byte Folded Spill
-; XTENSA-NEXT:    or a2, a15, a15
+; XTENSA-NEXT:    or a14, a3, a3
+; XTENSA-NEXT:    l32r a8, .LCPI30_2
+; XTENSA-NEXT:    s32i a13, a1, 40 # 4-byte Folded Spill
+; XTENSA-NEXT:    or a2, a13, a13
 ; XTENSA-NEXT:    or a3, a12, a12
-; XTENSA-NEXT:    s32i a14, a1, 12 # 4-byte Folded Spill
-; XTENSA-NEXT:    or a4, a14, a14
+; XTENSA-NEXT:    s32i a15, a1, 12 # 4-byte Folded Spill
+; XTENSA-NEXT:    or a4, a15, a15
 ; XTENSA-NEXT:    or a5, a12, a12
-; XTENSA-NEXT:    callx0 a13
-; XTENSA-NEXT:    l32i a8, a1, 44 # 4-byte Folded Reload
-; XTENSA-NEXT:    add a15, a2, a8
-; XTENSA-NEXT:    movi a8, 1
-; XTENSA-NEXT:    s32i a8, a1, 44 # 4-byte Folded Spill
-; XTENSA-NEXT:    bltu a15, a2, .LBB30_2
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    add a13, a2, a14
+; XTENSA-NEXT:    movi a15, 1
+; XTENSA-NEXT:    or a8, a15, a15
+; XTENSA-NEXT:    bltu a13, a2, .LBB30_2
 ; XTENSA-NEXT:  # %bb.1:
 ; XTENSA-NEXT:    or a8, a12, a12
 ; XTENSA-NEXT:  .LBB30_2:
 ; XTENSA-NEXT:    add a8, a3, a8
 ; XTENSA-NEXT:    s32i a8, a1, 32 # 4-byte Folded Spill
 ; XTENSA-NEXT:    movi a14, -1
+; XTENSA-NEXT:    l32r a8, .LCPI30_3
 ; XTENSA-NEXT:    l32i a2, a1, 36 # 4-byte Folded Reload
 ; XTENSA-NEXT:    or a3, a12, a12
 ; XTENSA-NEXT:    or a4, a14, a14
 ; XTENSA-NEXT:    or a5, a12, a12
-; XTENSA-NEXT:    callx0 a13
-; XTENSA-NEXT:    add a9, a2, a15
-; XTENSA-NEXT:    l32i a8, a1, 44 # 4-byte Folded Reload
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    add a9, a2, a13
+; XTENSA-NEXT:    or a8, a15, a15
 ; XTENSA-NEXT:    s32i a9, a1, 24 # 4-byte Folded Spill
 ; XTENSA-NEXT:    bltu a9, a2, .LBB30_4
 ; XTENSA-NEXT:  # %bb.3:
@@ -819,70 +820,72 @@ define i128 @muli128_m3840(i128 %a) nounwind {
 ; XTENSA-NEXT:  .LBB30_4:
 ; XTENSA-NEXT:    add a8, a3, a8
 ; XTENSA-NEXT:    l32i a9, a1, 32 # 4-byte Folded Reload
-; XTENSA-NEXT:    add a15, a9, a8
+; XTENSA-NEXT:    add a13, a9, a8
+; XTENSA-NEXT:    l32r a8, .LCPI30_4
 ; XTENSA-NEXT:    l32i a2, a1, 40 # 4-byte Folded Reload
 ; XTENSA-NEXT:    or a3, a12, a12
 ; XTENSA-NEXT:    or a4, a14, a14
 ; XTENSA-NEXT:    or a5, a12, a12
-; XTENSA-NEXT:    callx0 a13
+; XTENSA-NEXT:    callx0 a8
 ; XTENSA-NEXT:    s32i a3, a1, 4 # 4-byte Folded Spill
-; XTENSA-NEXT:    s32i a15, a1, 8 # 4-byte Folded Spill
+; XTENSA-NEXT:    s32i a13, a1, 8 # 4-byte Folded Spill
 ; XTENSA-NEXT:    s32i a2, a1, 0 # 4-byte Folded Spill
-; XTENSA-NEXT:    add a15, a2, a15
+; XTENSA-NEXT:    add a13, a2, a13
+; XTENSA-NEXT:    l32r a8, .LCPI30_5
 ; XTENSA-NEXT:    l32i a2, a1, 16 # 4-byte Folded Reload
 ; XTENSA-NEXT:    l32i a3, a1, 20 # 4-byte Folded Reload
 ; XTENSA-NEXT:    l32i a4, a1, 12 # 4-byte Folded Reload
 ; XTENSA-NEXT:    or a5, a14, a14
-; XTENSA-NEXT:    callx0 a13
+; XTENSA-NEXT:    callx0 a8
 ; XTENSA-NEXT:    s32i a2, a1, 16 # 4-byte Folded Spill
 ; XTENSA-NEXT:    s32i a3, a1, 20 # 4-byte Folded Spill
+; XTENSA-NEXT:    l32r a8, .LCPI30_6
 ; XTENSA-NEXT:    l32i a2, a1, 36 # 4-byte Folded Reload
 ; XTENSA-NEXT:    l32i a3, a1, 40 # 4-byte Folded Reload
 ; XTENSA-NEXT:    or a4, a14, a14
 ; XTENSA-NEXT:    or a5, a14, a14
-; XTENSA-NEXT:    callx0 a13
+; XTENSA-NEXT:    callx0 a8
 ; XTENSA-NEXT:    l32i a8, a1, 16 # 4-byte Folded Reload
 ; XTENSA-NEXT:    add a9, a2, a8
-; XTENSA-NEXT:    add a4, a15, a9
-; XTENSA-NEXT:    l32i a7, a1, 44 # 4-byte Folded Reload
-; XTENSA-NEXT:    or a8, a7, a7
-; XTENSA-NEXT:    bltu a4, a15, .LBB30_6
+; XTENSA-NEXT:    add a4, a13, a9
+; XTENSA-NEXT:    or a8, a15, a15
+; XTENSA-NEXT:    bltu a4, a13, .LBB30_6
 ; XTENSA-NEXT:  # %bb.5:
 ; XTENSA-NEXT:    or a8, a12, a12
 ; XTENSA-NEXT:  .LBB30_6:
-; XTENSA-NEXT:    or a10, a7, a7
+; XTENSA-NEXT:    or a10, a15, a15
 ; XTENSA-NEXT:    l32i a11, a1, 0 # 4-byte Folded Reload
-; XTENSA-NEXT:    bltu a15, a11, .LBB30_8
+; XTENSA-NEXT:    bltu a13, a11, .LBB30_8
 ; XTENSA-NEXT:  # %bb.7:
 ; XTENSA-NEXT:    or a10, a12, a12
 ; XTENSA-NEXT:  .LBB30_8:
-; XTENSA-NEXT:    or a11, a7, a7
-; XTENSA-NEXT:    l32i a6, a1, 32 # 4-byte Folded Reload
-; XTENSA-NEXT:    l32i a5, a1, 8 # 4-byte Folded Reload
-; XTENSA-NEXT:    bltu a5, a6, .LBB30_10
+; XTENSA-NEXT:    or a11, a15, a15
+; XTENSA-NEXT:    l32i a7, a1, 32 # 4-byte Folded Reload
+; XTENSA-NEXT:    l32i a6, a1, 8 # 4-byte Folded Reload
+; XTENSA-NEXT:    bltu a6, a7, .LBB30_10
 ; XTENSA-NEXT:  # %bb.9:
 ; XTENSA-NEXT:    or a11, a12, a12
 ; XTENSA-NEXT:  .LBB30_10:
-; XTENSA-NEXT:    l32i a6, a1, 4 # 4-byte Folded Reload
-; XTENSA-NEXT:    add a11, a6, a11
+; XTENSA-NEXT:    l32i a7, a1, 4 # 4-byte Folded Reload
+; XTENSA-NEXT:    add a11, a7, a11
 ; XTENSA-NEXT:    add a10, a11, a10
 ; XTENSA-NEXT:    bltu a9, a2, .LBB30_12
 ; XTENSA-NEXT:  # %bb.11:
-; XTENSA-NEXT:    or a7, a12, a12
+; XTENSA-NEXT:    or a15, a12, a12
 ; XTENSA-NEXT:  .LBB30_12:
 ; XTENSA-NEXT:    l32i a9, a1, 20 # 4-byte Folded Reload
 ; XTENSA-NEXT:    add a9, a3, a9
-; XTENSA-NEXT:    add a9, a9, a7
+; XTENSA-NEXT:    add a9, a9, a15
 ; XTENSA-NEXT:    add a9, a10, a9
 ; XTENSA-NEXT:    add a5, a9, a8
 ; XTENSA-NEXT:    l32i a2, a1, 28 # 4-byte Folded Reload
 ; XTENSA-NEXT:    l32i a3, a1, 24 # 4-byte Folded Reload
-; XTENSA-NEXT:    l32i a15, a1, 48 # 4-byte Folded Reload
-; XTENSA-NEXT:    l32i a14, a1, 52 # 4-byte Folded Reload
-; XTENSA-NEXT:    l32i a13, a1, 56 # 4-byte Folded Reload
-; XTENSA-NEXT:    l32i a12, a1, 60 # 4-byte Folded Reload
-; XTENSA-NEXT:    l32i a0, a1, 64 # 4-byte Folded Reload
-; XTENSA-NEXT:    addi a8, a1, 80
+; XTENSA-NEXT:    l32i a15, a1, 44 # 4-byte Folded Reload
+; XTENSA-NEXT:    l32i a14, a1, 48 # 4-byte Folded Reload
+; XTENSA-NEXT:    l32i a13, a1, 52 # 4-byte Folded Reload
+; XTENSA-NEXT:    l32i a12, a1, 56 # 4-byte Folded Reload
+; XTENSA-NEXT:    l32i a0, a1, 60 # 4-byte Folded Reload
+; XTENSA-NEXT:    addi a8, a1, 64
 ; XTENSA-NEXT:    or a1, a8, a8
 ; XTENSA-NEXT:    ret
 ;
@@ -980,51 +983,52 @@ define i128 @muli128_m3840(i128 %a) nounwind {
 define i128 @muli128_m63(i128 %a) nounwind {
 ; XTENSA-LABEL: muli128_m63:
 ; XTENSA:       # %bb.0:
-; XTENSA-NEXT:    addi a8, a1, -80
+; XTENSA-NEXT:    addi a8, a1, -64
 ; XTENSA-NEXT:    or a1, a8, a8
-; XTENSA-NEXT:    s32i a0, a1, 64 # 4-byte Folded Spill
-; XTENSA-NEXT:    s32i a12, a1, 60 # 4-byte Folded Spill
-; XTENSA-NEXT:    s32i a13, a1, 56 # 4-byte Folded Spill
-; XTENSA-NEXT:    s32i a14, a1, 52 # 4-byte Folded Spill
-; XTENSA-NEXT:    s32i a15, a1, 48 # 4-byte Folded Spill
+; XTENSA-NEXT:    s32i a0, a1, 60 # 4-byte Folded Spill
+; XTENSA-NEXT:    s32i a12, a1, 56 # 4-byte Folded Spill
+; XTENSA-NEXT:    s32i a13, a1, 52 # 4-byte Folded Spill
+; XTENSA-NEXT:    s32i a14, a1, 48 # 4-byte Folded Spill
+; XTENSA-NEXT:    s32i a15, a1, 44 # 4-byte Folded Spill
 ; XTENSA-NEXT:    s32i a5, a1, 20 # 4-byte Folded Spill
 ; XTENSA-NEXT:    s32i a4, a1, 16 # 4-byte Folded Spill
-; XTENSA-NEXT:    or a15, a3, a3
-; XTENSA-NEXT:    movi a14, -63
+; XTENSA-NEXT:    or a13, a3, a3
+; XTENSA-NEXT:    movi a15, -63
 ; XTENSA-NEXT:    movi a12, 0
-; XTENSA-NEXT:    l32r a13, .LCPI31_0
+; XTENSA-NEXT:    l32r a8, .LCPI31_0
 ; XTENSA-NEXT:    s32i a2, a1, 36 # 4-byte Folded Spill
 ; XTENSA-NEXT:    or a3, a12, a12
-; XTENSA-NEXT:    or a4, a14, a14
+; XTENSA-NEXT:    or a4, a15, a15
 ; XTENSA-NEXT:    or a5, a12, a12
-; XTENSA-NEXT:    callx0 a13
+; XTENSA-NEXT:    callx0 a8
 ; XTENSA-NEXT:    s32i a2, a1, 28 # 4-byte Folded Spill
-; XTENSA-NEXT:    s32i a3, a1, 44 # 4-byte Folded Spill
-; XTENSA-NEXT:    s32i a15, a1, 40 # 4-byte Folded Spill
-; XTENSA-NEXT:    or a2, a15, a15
+; XTENSA-NEXT:    or a14, a3, a3
+; XTENSA-NEXT:    l32r a8, .LCPI31_1
+; XTENSA-NEXT:    s32i a13, a1, 40 # 4-byte Folded Spill
+; XTENSA-NEXT:    or a2, a13, a13
 ; XTENSA-NEXT:    or a3, a12, a12
-; XTENSA-NEXT:    s32i a14, a1, 12 # 4-byte Folded Spill
-; XTENSA-NEXT:    or a4, a14, a14
+; XTENSA-NEXT:    s32i a15, a1, 12 # 4-byte Folded Spill
+; XTENSA-NEXT:    or a4, a15, a15
 ; XTENSA-NEXT:    or a5, a12, a12
-; XTENSA-NEXT:    callx0 a13
-; XTENSA-NEXT:    l32i a8, a1, 44 # 4-byte Folded Reload
-; XTENSA-NEXT:    add a15, a2, a8
-; XTENSA-NEXT:    movi a8, 1
-; XTENSA-NEXT:    s32i a8, a1, 44 # 4-byte Folded Spill
-; XTENSA-NEXT:    bltu a15, a2, .LBB31_2
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    add a13, a2, a14
+; XTENSA-NEXT:    movi a15, 1
+; XTENSA-NEXT:    or a8, a15, a15
+; XTENSA-NEXT:    bltu a13, a2, .LBB31_2
 ; XTENSA-NEXT:  # %bb.1:
 ; XTENSA-NEXT:    or a8, a12, a12
 ; XTENSA-NEXT:  .LBB31_2:
 ; XTENSA-NEXT:    add a8, a3, a8
 ; XTENSA-NEXT:    s32i a8, a1, 32 # 4-byte Folded Spill
 ; XTENSA-NEXT:    movi a14, -1
+; XTENSA-NEXT:    l32r a8, .LCPI31_2
 ; XTENSA-NEXT:    l32i a2, a1, 36 # 4-byte Folded Reload
 ; XTENSA-NEXT:    or a3, a12, a12
 ; XTENSA-NEXT:    or a4, a14, a14
 ; XTENSA-NEXT:    or a5, a12, a12
-; XTENSA-NEXT:    callx0 a13
-; XTENSA-NEXT:    add a9, a2, a15
-; XTENSA-NEXT:    l32i a8, a1, 44 # 4-byte Folded Reload
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    add a9, a2, a13
+; XTENSA-NEXT:    or a8, a15, a15
 ; XTENSA-NEXT:    s32i a9, a1, 24 # 4-byte Folded Spill
 ; XTENSA-NEXT:    bltu a9, a2, .LBB31_4
 ; XTENSA-NEXT:  # %bb.3:
@@ -1032,70 +1036,72 @@ define i128 @muli128_m63(i128 %a) nounwind {
 ; XTENSA-NEXT:  .LBB31_4:
 ; XTENSA-NEXT:    add a8, a3, a8
 ; XTENSA-NEXT:    l32i a9, a1, 32 # 4-byte Folded Reload
-; XTENSA-NEXT:    add a15, a9, a8
+; XTENSA-NEXT:    add a13, a9, a8
+; XTENSA-NEXT:    l32r a8, .LCPI31_3
 ; XTENSA-NEXT:    l32i a2, a1, 40 # 4-byte Folded Reload
 ; XTENSA-NEXT:    or a3, a12, a12
 ; XTENSA-NEXT:    or a4, a14, a14
 ; XTENSA-NEXT:    or a5, a12, a12
-; XTENSA-NEXT:    callx0 a13
+; XTENSA-NEXT:    callx0 a8
 ; XTENSA-NEXT:    s32i a3, a1, 4 # 4-byte Folded Spill
-; XTENSA-NEXT:    s32i a15, a1, 8 # 4-byte Folded Spill
+; XTENSA-NEXT:    s32i a13, a1, 8 # 4-byte Folded Spill
 ; XTENSA-NEXT:    s32i a2, a1, 0 # 4-byte Folded Spill
-; XTENSA-NEXT:    add a15, a2, a15
+; XTENSA-NEXT:    add a13, a2, a13
+; XTENSA-NEXT:    l32r a8, .LCPI31_4
 ; XTENSA-NEXT:    l32i a2, a1, 16 # 4-byte Folded Reload
 ; XTENSA-NEXT:    l32i a3, a1, 20 # 4-byte Folded Reload
 ; XTENSA-NEXT:    l32i a4, a1, 12 # 4-byte Folded Reload
 ; XTENSA-NEXT:    or a5, a14, a14
-; XTENSA-NEXT:    callx0 a13
+; XTENSA-NEXT:    callx0 a8
 ; XTENSA-NEXT:    s32i a2, a1, 16 # 4-byte Folded Spill
 ; XTENSA-NEXT:    s32i a3, a1, 20 # 4-byte Folded Spill
+; XTENSA-NEXT:    l32r a8, .LCPI31_5
 ; XTENSA-NEXT:    l32i a2, a1, 36 # 4-byte Folded Reload
 ; XTENSA-NEXT:    l32i a3, a1, 40 # 4-byte Folded Reload
 ; XTENSA-NEXT:    or a4, a14, a14
 ; XTENSA-NEXT:    or a5, a14, a14
-; XTENSA-NEXT:    callx0 a13
+; XTENSA-NEXT:    callx0 a8
 ; XTENSA-NEXT:    l32i a8, a1, 16 # 4-byte Folded Reload
 ; XTENSA-NEXT:    add a9, a2, a8
-; XTENSA-NEXT:    add a4, a15, a9
-; XTENSA-NEXT:    l32i a7, a1, 44 # 4-byte Folded Reload
-; XTENSA-NEXT:    or a8, a7, a7
-; XTENSA-NEXT:    bltu a4, a15, .LBB31_6
+; XTENSA-NEXT:    add a4, a13, a9
+; XTENSA-NEXT:    or a8, a15, a15
+; XTENSA-NEXT:    bltu a4, a13, .LBB31_6
 ; XTENSA-NEXT:  # %bb.5:
 ; XTENSA-NEXT:    or a8, a12, a12
 ; XTENSA-NEXT:  .LBB31_6:
-; XTENSA-NEXT:    or a10, a7, a7
+; XTENSA-NEXT:    or a10, a15, a15
 ; XTENSA-NEXT:    l32i a11, a1, 0 # 4-byte Folded Reload
-; XTENSA-NEXT:    bltu a15, a11, .LBB31_8
+; XTENSA-NEXT:    bltu a13, a11, .LBB31_8
 ; XTENSA-NEXT:  # %bb.7:
 ; XTENSA-NEXT:    or a10, a12, a12
 ; XTENSA-NEXT:  .LBB31_8:
-; XTENSA-NEXT:    or a11, a7, a7
-; XTENSA-NEXT:    l32i a6, a1, 32 # 4-byte Folded Reload
-; XTENSA-NEXT:    l32i a5, a1, 8 # 4-byte Folded Reload
-; XTENSA-NEXT:    bltu a5, a6, .LBB31_10
+; XTENSA-NEXT:    or a11, a15, a15
+; XTENSA-NEXT:    l32i a7, a1, 32 # 4-byte Folded Reload
+; XTENSA-NEXT:    l32i a6, a1, 8 # 4-byte Folded Reload
+; XTENSA-NEXT:    bltu a6, a7, .LBB31_10
 ; XTENSA-NEXT:  # %bb.9:
 ; XTENSA-NEXT:    or a11, a12, a12
 ; XTENSA-NEXT:  .LBB31_10:
-; XTENSA-NEXT:    l32i a6, a1, 4 # 4-byte Folded Reload
-; XTENSA-NEXT:    add a11, a6, a11
+; XTENSA-NEXT:    l32i a7, a1, 4 # 4-byte Folded Reload
+; XTENSA-NEXT:    add a11, a7, a11
 ; XTENSA-NEXT:    add a10, a11, a10
 ; XTENSA-NEXT:    bltu a9, a2, .LBB31_12
 ; XTENSA-NEXT:  # %bb.11:
-; XTENSA-NEXT:    or a7, a12, a12
+; XTENSA-NEXT:    or a15, a12, a12
 ; XTENSA-NEXT:  .LBB31_12:
 ; XTENSA-NEXT:    l32i a9, a1, 20 # 4-byte Folded Reload
 ; XTENSA-NEXT:    add a9, a3, a9
-; XTENSA-NEXT:    add a9, a9, a7
+; XTENSA-NEXT:    add a9, a9, a15
 ; XTENSA-NEXT:    add a9, a10, a9
 ; XTENSA-NEXT:    add a5, a9, a8
 ; XTENSA-NEXT:    l32i a2, a1, 28 # 4-byte Folded Reload
 ; XTENSA-NEXT:    l32i a3, a1, 24 # 4-byte Folded Reload
-; XTENSA-NEXT:    l32i a15, a1, 48 # 4-byte Folded Reload
-; XTENSA-NEXT:    l32i a14, a1, 52 # 4-byte Folded Reload
-; XTENSA-NEXT:    l32i a13, a1, 56 # 4-byte Folded Reload
-; XTENSA-NEXT:    l32i a12, a1, 60 # 4-byte Folded Reload
-; XTENSA-NEXT:    l32i a0, a1, 64 # 4-byte Folded Reload
-; XTENSA-NEXT:    addi a8, a1, 80
+; XTENSA-NEXT:    l32i a15, a1, 44 # 4-byte Folded Reload
+; XTENSA-NEXT:    l32i a14, a1, 48 # 4-byte Folded Reload
+; XTENSA-NEXT:    l32i a13, a1, 52 # 4-byte Folded Reload
+; XTENSA-NEXT:    l32i a12, a1, 56 # 4-byte Folded Reload
+; XTENSA-NEXT:    l32i a0, a1, 60 # 4-byte Folded Reload
+; XTENSA-NEXT:    addi a8, a1, 64
 ; XTENSA-NEXT:    or a1, a8, a8
 ; XTENSA-NEXT:    ret
 ;
@@ -1195,30 +1201,30 @@ define i64 @mulhsu_i64(i64 %a, i64 %b) nounwind {
 ; XTENSA:       # %bb.0:
 ; XTENSA-NEXT:    addi a8, a1, -64
 ; XTENSA-NEXT:    or a1, a8, a8
-; XTENSA-NEXT:    s32i a0, a1, 56 # 4-byte Folded Spill
-; XTENSA-NEXT:    s32i a12, a1, 52 # 4-byte Folded Spill
-; XTENSA-NEXT:    s32i a13, a1, 48 # 4-byte Folded Spill
-; XTENSA-NEXT:    s32i a14, a1, 44 # 4-byte Folded Spill
-; XTENSA-NEXT:    s32i a15, a1, 40 # 4-byte Folded Spill
+; XTENSA-NEXT:    s32i a0, a1, 52 # 4-byte Folded Spill
+; XTENSA-NEXT:    s32i a12, a1, 48 # 4-byte Folded Spill
+; XTENSA-NEXT:    s32i a13, a1, 44 # 4-byte Folded Spill
+; XTENSA-NEXT:    s32i a14, a1, 40 # 4-byte Folded Spill
+; XTENSA-NEXT:    s32i a15, a1, 36 # 4-byte Folded Spill
 ; XTENSA-NEXT:    s32i a5, a1, 28 # 4-byte Folded Spill
-; XTENSA-NEXT:    or a14, a4, a4
+; XTENSA-NEXT:    or a13, a4, a4
 ; XTENSA-NEXT:    or a15, a3, a3
 ; XTENSA-NEXT:    movi a12, 0
-; XTENSA-NEXT:    l32r a13, .LCPI32_0
+; XTENSA-NEXT:    l32r a8, .LCPI32_0
 ; XTENSA-NEXT:    s32i a2, a1, 32 # 4-byte Folded Spill
 ; XTENSA-NEXT:    or a3, a12, a12
 ; XTENSA-NEXT:    or a5, a12, a12
-; XTENSA-NEXT:    callx0 a13
-; XTENSA-NEXT:    s32i a3, a1, 24 # 4-byte Folded Spill
-; XTENSA-NEXT:    s32i a15, a1, 36 # 4-byte Folded Spill
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    or a14, a3, a3
+; XTENSA-NEXT:    l32r a8, .LCPI32_1
+; XTENSA-NEXT:    s32i a15, a1, 20 # 4-byte Folded Spill
 ; XTENSA-NEXT:    or a2, a15, a15
 ; XTENSA-NEXT:    or a3, a12, a12
-; XTENSA-NEXT:    s32i a14, a1, 16 # 4-byte Folded Spill
-; XTENSA-NEXT:    or a4, a14, a14
+; XTENSA-NEXT:    s32i a13, a1, 16 # 4-byte Folded Spill
+; XTENSA-NEXT:    or a4, a13, a13
 ; XTENSA-NEXT:    or a5, a12, a12
-; XTENSA-NEXT:    callx0 a13
-; XTENSA-NEXT:    l32i a8, a1, 24 # 4-byte Folded Reload
-; XTENSA-NEXT:    add a14, a2, a8
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    add a14, a2, a14
 ; XTENSA-NEXT:    movi a15, 1
 ; XTENSA-NEXT:    or a8, a15, a15
 ; XTENSA-NEXT:    bltu a14, a2, .LBB32_2
@@ -1227,13 +1233,13 @@ define i64 @mulhsu_i64(i64 %a, i64 %b) nounwind {
 ; XTENSA-NEXT:  .LBB32_2:
 ; XTENSA-NEXT:    add a8, a3, a8
 ; XTENSA-NEXT:    s32i a8, a1, 24 # 4-byte Folded Spill
+; XTENSA-NEXT:    l32r a8, .LCPI32_2
 ; XTENSA-NEXT:    l32i a2, a1, 32 # 4-byte Folded Reload
 ; XTENSA-NEXT:    or a3, a12, a12
 ; XTENSA-NEXT:    l32i a4, a1, 28 # 4-byte Folded Reload
 ; XTENSA-NEXT:    or a5, a12, a12
-; XTENSA-NEXT:    callx0 a13
+; XTENSA-NEXT:    callx0 a8
 ; XTENSA-NEXT:    add a9, a2, a14
-; XTENSA-NEXT:    s32i a15, a1, 20 # 4-byte Folded Spill
 ; XTENSA-NEXT:    or a8, a15, a15
 ; XTENSA-NEXT:    bltu a9, a2, .LBB32_4
 ; XTENSA-NEXT:  # %bb.3:
@@ -1242,68 +1248,70 @@ define i64 @mulhsu_i64(i64 %a, i64 %b) nounwind {
 ; XTENSA-NEXT:    add a8, a3, a8
 ; XTENSA-NEXT:    l32i a9, a1, 24 # 4-byte Folded Reload
 ; XTENSA-NEXT:    add a14, a9, a8
-; XTENSA-NEXT:    l32i a2, a1, 36 # 4-byte Folded Reload
+; XTENSA-NEXT:    l32r a8, .LCPI32_3
+; XTENSA-NEXT:    l32i a2, a1, 20 # 4-byte Folded Reload
 ; XTENSA-NEXT:    or a3, a12, a12
-; XTENSA-NEXT:    l32i a15, a1, 28 # 4-byte Folded Reload
-; XTENSA-NEXT:    or a4, a15, a15
+; XTENSA-NEXT:    l32i a13, a1, 28 # 4-byte Folded Reload
+; XTENSA-NEXT:    or a4, a13, a13
 ; XTENSA-NEXT:    or a5, a12, a12
-; XTENSA-NEXT:    callx0 a13
+; XTENSA-NEXT:    callx0 a8
 ; XTENSA-NEXT:    s32i a3, a1, 8 # 4-byte Folded Spill
 ; XTENSA-NEXT:    s32i a14, a1, 12 # 4-byte Folded Spill
 ; XTENSA-NEXT:    s32i a2, a1, 4 # 4-byte Folded Spill
 ; XTENSA-NEXT:    add a14, a2, a14
+; XTENSA-NEXT:    l32r a8, .LCPI32_4
 ; XTENSA-NEXT:    l32i a2, a1, 16 # 4-byte Folded Reload
-; XTENSA-NEXT:    or a3, a15, a15
+; XTENSA-NEXT:    or a3, a13, a13
 ; XTENSA-NEXT:    or a4, a12, a12
 ; XTENSA-NEXT:    or a5, a12, a12
-; XTENSA-NEXT:    callx0 a13
+; XTENSA-NEXT:    callx0 a8
 ; XTENSA-NEXT:    s32i a2, a1, 0 # 4-byte Folded Spill
 ; XTENSA-NEXT:    s32i a3, a1, 16 # 4-byte Folded Spill
-; XTENSA-NEXT:    srai a2, a15, 31
+; XTENSA-NEXT:    srai a2, a13, 31
+; XTENSA-NEXT:    l32r a8, .LCPI32_5
 ; XTENSA-NEXT:    or a3, a2, a2
 ; XTENSA-NEXT:    l32i a4, a1, 32 # 4-byte Folded Reload
-; XTENSA-NEXT:    l32i a5, a1, 36 # 4-byte Folded Reload
-; XTENSA-NEXT:    callx0 a13
+; XTENSA-NEXT:    l32i a5, a1, 20 # 4-byte Folded Reload
+; XTENSA-NEXT:    callx0 a8
 ; XTENSA-NEXT:    or a8, a2, a2
 ; XTENSA-NEXT:    l32i a9, a1, 0 # 4-byte Folded Reload
 ; XTENSA-NEXT:    add a10, a8, a9
 ; XTENSA-NEXT:    add a2, a14, a10
-; XTENSA-NEXT:    l32i a6, a1, 20 # 4-byte Folded Reload
-; XTENSA-NEXT:    or a9, a6, a6
+; XTENSA-NEXT:    or a9, a15, a15
 ; XTENSA-NEXT:    bltu a2, a14, .LBB32_6
 ; XTENSA-NEXT:  # %bb.5:
 ; XTENSA-NEXT:    or a9, a12, a12
 ; XTENSA-NEXT:  .LBB32_6:
-; XTENSA-NEXT:    or a11, a6, a6
+; XTENSA-NEXT:    or a11, a15, a15
 ; XTENSA-NEXT:    l32i a7, a1, 4 # 4-byte Folded Reload
 ; XTENSA-NEXT:    bltu a14, a7, .LBB32_8
 ; XTENSA-NEXT:  # %bb.7:
 ; XTENSA-NEXT:    or a11, a12, a12
 ; XTENSA-NEXT:  .LBB32_8:
-; XTENSA-NEXT:    or a7, a6, a6
-; XTENSA-NEXT:    l32i a5, a1, 24 # 4-byte Folded Reload
-; XTENSA-NEXT:    l32i a4, a1, 12 # 4-byte Folded Reload
-; XTENSA-NEXT:    bltu a4, a5, .LBB32_10
+; XTENSA-NEXT:    or a7, a15, a15
+; XTENSA-NEXT:    l32i a6, a1, 24 # 4-byte Folded Reload
+; XTENSA-NEXT:    l32i a5, a1, 12 # 4-byte Folded Reload
+; XTENSA-NEXT:    bltu a5, a6, .LBB32_10
 ; XTENSA-NEXT:  # %bb.9:
 ; XTENSA-NEXT:    or a7, a12, a12
 ; XTENSA-NEXT:  .LBB32_10:
-; XTENSA-NEXT:    l32i a5, a1, 8 # 4-byte Folded Reload
-; XTENSA-NEXT:    add a7, a5, a7
+; XTENSA-NEXT:    l32i a6, a1, 8 # 4-byte Folded Reload
+; XTENSA-NEXT:    add a7, a6, a7
 ; XTENSA-NEXT:    add a11, a7, a11
 ; XTENSA-NEXT:    bltu a10, a8, .LBB32_12
 ; XTENSA-NEXT:  # %bb.11:
-; XTENSA-NEXT:    or a6, a12, a12
+; XTENSA-NEXT:    or a15, a12, a12
 ; XTENSA-NEXT:  .LBB32_12:
 ; XTENSA-NEXT:    l32i a8, a1, 16 # 4-byte Folded Reload
 ; XTENSA-NEXT:    add a8, a3, a8
-; XTENSA-NEXT:    add a8, a8, a6
+; XTENSA-NEXT:    add a8, a8, a15
 ; XTENSA-NEXT:    add a8, a11, a8
 ; XTENSA-NEXT:    add a3, a8, a9
-; XTENSA-NEXT:    l32i a15, a1, 40 # 4-byte Folded Reload
-; XTENSA-NEXT:    l32i a14, a1, 44 # 4-byte Folded Reload
-; XTENSA-NEXT:    l32i a13, a1, 48 # 4-byte Folded Reload
-; XTENSA-NEXT:    l32i a12, a1, 52 # 4-byte Folded Reload
-; XTENSA-NEXT:    l32i a0, a1, 56 # 4-byte Folded Reload
+; XTENSA-NEXT:    l32i a15, a1, 36 # 4-byte Folded Reload
+; XTENSA-NEXT:    l32i a14, a1, 40 # 4-byte Folded Reload
+; XTENSA-NEXT:    l32i a13, a1, 44 # 4-byte Folded Reload
+; XTENSA-NEXT:    l32i a12, a1, 48 # 4-byte Folded Reload
+; XTENSA-NEXT:    l32i a0, a1, 52 # 4-byte Folded Reload
 ; XTENSA-NEXT:    addi a8, a1, 64
 ; XTENSA-NEXT:    or a1, a8, a8
 ; XTENSA-NEXT:    ret

diff  --git a/llvm/test/MC/Disassembler/Xtensa/fp.txt b/llvm/test/MC/Disassembler/Xtensa/fp.txt
new file mode 100644
index 0000000000000..993b9987c1bca
--- /dev/null
+++ b/llvm/test/MC/Disassembler/Xtensa/fp.txt
@@ -0,0 +1,215 @@
+# NOTE: Assertions have been autogenerated by utils/update_mc_test_checks.py UTC_ARGS: --version 5
+# RUN: llvm-mc -triple=xtensa -mattr=+fp,+bool -disassemble %s | FileCheck -check-prefixes=CHECK-FLOAT %s
+# RUN: not llvm-mc -triple=xtensa -disassemble %s 2>&1 | FileCheck --implicit-check-not=warning: -check-prefixes=CHECK-CORE %s
+
+## Verify that binary code is correctly disassembled with
+## fp option enabled. Also verify that dissasembling without
+## fp option generates warnings.
+
+[0x10,0x23,0xfa]
+# CHECK-FLOAT: abs.s f2, f3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x40,0x23,0x0a]
+# CHECK-FLOAT: add.s f2, f3, f4
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0xe0,0x23,0xfa]
+# CHECK-FLOAT: addexp.s f2, f3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0xf0,0x23,0xfa]
+# CHECK-FLOAT: addexpm.s f2, f3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x50,0x23,0xba]
+# CHECK-FLOAT: ceil.s a2, f3, 5
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x30,0x35,0xfa]
+# CHECK-FLOAT: const.s f3, 5
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x70,0x23,0xfa]
+# CHECK-FLOAT: div0.s f2, f3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x40,0x23,0x7a]
+# CHECK-FLOAT: divn.s f2, f3, f4
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x50,0x23,0xca]
+# CHECK-FLOAT: float.s f2, a3, 5
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x50,0x23,0xaa]
+# CHECK-FLOAT: floor.s a2, f3, 5
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x23,0x03,0x02]
+# CHECK-FLOAT: lsi f2, a3, 8
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x23,0x83,0x02]
+# CHECK-FLOAT: lsip f2, a3, 8
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x40,0x23,0x08]
+# CHECK-FLOAT: lsx f2, a3, a4
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x40,0x23,0x18]
+# CHECK-FLOAT: lsxp f2, a3, a4
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x40,0x23,0x4a]
+# CHECK-FLOAT: madd.s f2, f3, f4
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x40,0x23,0x6a]
+# CHECK-FLOAT: maddn.s f2, f3, f4
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0xd0,0x23,0xfa]
+# CHECK-FLOAT: mkdadj.s f2, f3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0xc0,0x23,0xfa]
+# CHECK-FLOAT: mksadj.s f2, f3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x00,0x23,0xfa]
+# CHECK-FLOAT: mov.s f2, f3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x40,0x23,0x8b]
+# CHECK-FLOAT: moveqz.s f2, f3, a4
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x00,0x23,0xcb]
+# CHECK-FLOAT: movf.s f2, f3, b0
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x40,0x23,0xbb]
+# CHECK-FLOAT: movgez.s f2, f3, a4
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x40,0x23,0xab]
+# CHECK-FLOAT: movltz.s f2, f3, a4
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x40,0x23,0x9b]
+# CHECK-FLOAT: movnez.s f2, f3, a4
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x00,0x23,0xdb]
+# CHECK-FLOAT: movt.s f2, f3, b0
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x40,0x23,0x5a]
+# CHECK-FLOAT: msub.s f2, f3, f4
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x40,0x23,0x2a]
+# CHECK-FLOAT: mul.s f2, f3, f4
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x60,0x23,0xfa]
+# CHECK-FLOAT: neg.s f2, f3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0xb0,0x23,0xfa]
+# CHECK-FLOAT: nexp01.s f2, f3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x30,0x02,0x2b]
+# CHECK-FLOAT: oeq.s b0, f2, f3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x30,0x02,0x6b]
+# CHECK-FLOAT: ole.s b0, f2, f3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x30,0x02,0x4b]
+# CHECK-FLOAT: olt.s b0, f2, f3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x80,0x23,0xfa]
+# CHECK-FLOAT: recip0.s f2, f3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x40,0x23,0xfa]
+# CHECK-FLOAT: rfr a2, f3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x50,0x23,0x8a]
+# CHECK-FLOAT: round.s a2, f3, 5
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0xa0,0x23,0xfa]
+# CHECK-FLOAT: rsqrt0.s f2, f3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x90,0x23,0xfa]
+# CHECK-FLOAT: sqrt0.s f2, f3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x23,0x43,0x02]
+# CHECK-FLOAT: ssi f2, a3, 8
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x23,0xc3,0x02]
+# CHECK-FLOAT: ssip f2, a3, 8
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x40,0x23,0x48]
+# CHECK-FLOAT: ssx f2, a3, a4
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x40,0x23,0x58]
+# CHECK-FLOAT: ssxp f2, a3, a4
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x40,0x23,0x1a]
+# CHECK-FLOAT: sub.s f2, f3, f4
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x50,0x23,0x9a]
+# CHECK-FLOAT: trunc.s a2, f3, 5
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x30,0x02,0x3b]
+# CHECK-FLOAT: ueq.s b0, f2, f3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x50,0x23,0xda]
+# CHECK-FLOAT: ufloat.s f2, a3, 5
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x30,0x02,0x7b]
+# CHECK-FLOAT: ule.s b0, f2, f3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x30,0x02,0x5b]
+# CHECK-FLOAT: ult.s b0, f2, f3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x30,0x02,0x1b]
+# CHECK-FLOAT: un.s b0, f2, f3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x50,0x23,0xea]
+# CHECK-FLOAT: utrunc.s a2, f3, 5
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x50,0x23,0xfa]
+# CHECK-FLOAT: wfr f2, a3
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x80,0x3e,0xe3]
+# CHECK-FLOAT: rur a3, fcr
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x90,0x3e,0xe3]
+# CHECK-FLOAT: rur a3, fsr
+# CHECK-CORE: [[#@LINE-2]]:2: warning: invalid instruction encoding

diff  --git a/llvm/test/MC/Xtensa/float-err.s b/llvm/test/MC/Xtensa/float-err.s
new file mode 100644
index 0000000000000..34c41fab18081
--- /dev/null
+++ b/llvm/test/MC/Xtensa/float-err.s
@@ -0,0 +1,37 @@
+# RUN: not llvm-mc %s -triple=xtensa -mattr=+fp -filetype=asm 2>&1 | FileCheck --implicit-check-not=error: %s
+
+ceil.s	a2, f3, 17
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: expected immediate in range [0, 15]
+
+const.s	f3, 18
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: expected immediate in range [0, 15]
+
+float.s	f2, a3, 16
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: expected immediate in range [0, 15]
+
+ufloat.s	f2, a3, 25
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: expected immediate in range [0, 15]
+
+floor.s	a2, f3, 17
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: expected immediate in range [0, 15]
+
+lsi f2, a3, 4099
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: expected immediate in range [0, 1020]
+
+lsip f2, a3, 4099
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: expected immediate in range [0, 1020]
+
+round.s	a2, f3, 20
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: expected immediate in range [0, 15]
+
+ssi f2, a3, 5000
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: expected immediate in range [0, 1020]
+
+ssip f2, a3, 5001
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: expected immediate in range [0, 1020]
+
+trunc.s	a2, f3, 21
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: expected immediate in range [0, 15]
+
+utrunc.s	a2, f3, 19
+// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: expected immediate in range [0, 15]

diff  --git a/llvm/test/MC/Xtensa/float.s b/llvm/test/MC/Xtensa/float.s
new file mode 100644
index 0000000000000..08aa2a12878ec
--- /dev/null
+++ b/llvm/test/MC/Xtensa/float.s
@@ -0,0 +1,209 @@
+# RUN: llvm-mc %s -triple=xtensa -mattr=+fp -mattr=+bool -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK,CHECK-INST %s
+
+.align	4
+LBL0:
+
+# CHECK-INST: abs.s	f2, f3
+# CHECK: encoding: [0x10,0x23,0xfa]
+	abs.s	f2, f3
+# CHECK-INST: add.s	f2, f3, f4
+# CHECK: encoding: [0x40,0x23,0x0a]
+	add.s	f2, f3, f4
+# CHECK-INST: addexp.s	f2, f3
+# CHECK: encoding: [0xe0,0x23,0xfa]
+	addexp.s	f2, f3
+# CHECK-INST: addexpm.s	f2, f3
+# CHECK: encoding: [0xf0,0x23,0xfa]
+	addexpm.s	f2, f3
+
+# CHECK-INST: ceil.s a2, f3, 5
+# CHECK: encoding: [0x50,0x23,0xba]
+	ceil.s	a2, f3, 5
+# CHECK-INST: const.s	f3, 5
+# CHECK: encoding: [0x30,0x35,0xfa]
+	const.s	f3, 5
+
+# CHECK-INST: div0.s f2, f3
+# CHECK: encoding: [0x70,0x23,0xfa]
+	div0.s f2, f3
+# CHECK-INST: divn.s f2, f3, f4
+# CHECK: encoding: [0x40,0x23,0x7a]
+	divn.s f2, f3, f4
+
+# CHECK-INST: float.s	f2, a3, 5
+# CHECK: encoding: [0x50,0x23,0xca]
+	float.s	f2, a3, 5
+# CHECK-INST: floor.s a2, f3, 5
+# CHECK: encoding: [0x50,0x23,0xaa]
+	floor.s	a2, f3, 5
+
+# CHECK-INST: lsi f2, a3, 8
+# CHECK: encoding: [0x23,0x03,0x02]
+	lsi f2, a3, 8
+# CHECK-INST: lsip f2, a3, 8
+# CHECK: encoding: [0x23,0x83,0x02]
+	lsip f2, a3, 8
+# CHECK-INST: lsx f2, a3, a4
+# CHECK: encoding: [0x40,0x23,0x08]
+	lsx f2, a3, a4
+# CHECK-INST: lsxp f2, a3, a4
+# CHECK: encoding: [0x40,0x23,0x18]
+	lsxp f2, a3, a4
+
+# CHECK-INST: madd.s f2, f3, f4
+# CHECK: encoding: [0x40,0x23,0x4a]
+	madd.s f2, f3, f4
+# CHECK-INST: maddn.s f2, f3, f4
+# CHECK: encoding: [0x40,0x23,0x6a]
+	maddn.s f2, f3, f4
+# CHECK-INST: mkdadj.s f2, f3
+# CHECK: encoding: [0xd0,0x23,0xfa]
+	mkdadj.s f2, f3
+# CHECK-INST: mksadj.s f2, f3
+# CHECK: encoding: [0xc0,0x23,0xfa]
+	mksadj.s f2, f3
+
+# CHECK-INST: mov.s f2, f3
+# CHECK: encoding: [0x00,0x23,0xfa]
+	mov.s f2, f3
+
+# CHECK-INST: moveqz.s f2, f3, a4
+# CHECK: encoding: [0x40,0x23,0x8b]
+	moveqz.s f2, f3, a4
+# CHECK-INST: movf.s f2, f3, b0
+# CHECK: encoding: [0x00,0x23,0xcb]
+	movf.s f2, f3, b0
+# CHECK-INST: movgez.s f2, f3, a4
+# CHECK: encoding: [0x40,0x23,0xbb]
+	movgez.s f2, f3, a4
+# CHECK-INST: movltz.s f2, f3, a4
+# CHECK: encoding: [0x40,0x23,0xab]
+	movltz.s f2, f3, a4
+# CHECK-INST: movnez.s f2, f3, a4
+# CHECK: encoding: [0x40,0x23,0x9b]
+	movnez.s f2, f3, a4
+# CHECK-INST: movt.s f2, f3, b0
+# CHECK: encoding: [0x00,0x23,0xdb]
+	movt.s f2, f3, b0
+
+# CHECK-INST: msub.s f2, f3, f4
+# CHECK: encoding: [0x40,0x23,0x5a]
+	msub.s f2, f3, f4
+# CHECK-INST: mul.s	f2, f3, f4
+# CHECK: encoding: [0x40,0x23,0x2a]
+	mul.s	f2, f3, f4
+# CHECK-INST: neg.s f2, f3
+# CHECK: encoding: [0x60,0x23,0xfa]
+	neg.s f2, f3
+
+# CHECK-INST: nexp01.s f2, f3
+# CHECK: encoding: [0xb0,0x23,0xfa]
+	nexp01.s f2, f3
+
+# CHECK-INST: oeq.s b0, f2, f3
+# CHECK: encoding: [0x30,0x02,0x2b]
+	oeq.s b0, f2, f3
+# CHECK-INST: ole.s b0, f2, f3
+# CHECK: encoding: [0x30,0x02,0x6b]
+	ole.s b0, f2, f3
+# CHECK-INST: olt.s b0, f2, f3
+# CHECK: encoding: [0x30,0x02,0x4b]
+	olt.s b0, f2, f3
+
+# CHECK-INST: recip0.s f2, f3
+# CHECK: encoding: [0x80,0x23,0xfa]
+	recip0.s f2, f3
+
+# CHECK-INST: rfr a2, f3
+# CHECK: encoding: [0x40,0x23,0xfa]
+	rfr a2, f3
+
+# CHECK-INST: round.s a2, f3, 5
+# CHECK: encoding: [0x50,0x23,0x8a]
+	round.s	a2, f3, 5
+# CHECK-INST: rsqrt0.s f2, f3
+# CHECK: encoding: [0xa0,0x23,0xfa]
+	rsqrt0.s f2, f3
+# CHECK-INST: sqrt0.s f2, f3
+# CHECK: encoding: [0x90,0x23,0xfa]
+	sqrt0.s f2, f3
+
+# CHECK-INST: ssi f2, a3, 8
+# CHECK: encoding: [0x23,0x43,0x02]
+	ssi f2, a3, 8
+# CHECK-INST: ssip f2, a3, 8
+# CHECK: encoding: [0x23,0xc3,0x02]
+	ssip f2, a3, 8
+# CHECK-INST: ssx f2, a3, a4
+# CHECK: encoding: [0x40,0x23,0x48]
+	ssx f2, a3, a4
+# CHECK-INST: ssxp f2, a3, a4
+# CHECK: encoding: [0x40,0x23,0x58]
+	ssxp f2, a3, a4
+
+# CHECK-INST: sub.s	f2, f3, f4
+# CHECK: encoding: [0x40,0x23,0x1a]
+	sub.s	f2, f3, f4
+
+# CHECK-INST: trunc.s a2, f3, 5
+# CHECK: encoding: [0x50,0x23,0x9a]
+	trunc.s	a2, f3, 5
+
+# CHECK-INST: ueq.s b0, f2, f3
+# CHECK: encoding: [0x30,0x02,0x3b]
+	ueq.s b0, f2, f3
+
+# CHECK-INST: ufloat.s	f2, a3, 5
+# CHECK: encoding: [0x50,0x23,0xda]
+	ufloat.s	f2, a3, 5
+
+# CHECK-INST: ule.s b0, f2, f3
+# CHECK: encoding: [0x30,0x02,0x7b]
+	ule.s b0, f2, f3
+# CHECK-INST: ult.s b0, f2, f3
+# CHECK: encoding: [0x30,0x02,0x5b]
+	ult.s b0, f2, f3
+# CHECK-INST: un.s b0, f2, f3
+# CHECK: encoding: [0x30,0x02,0x1b]
+	un.s b0, f2, f3
+
+# CHECK-INST: utrunc.s a2, f3, 5
+# CHECK: encoding: [0x50,0x23,0xea]
+	utrunc.s	a2, f3, 5
+
+# CHECK-INST: wfr f2, a3
+# CHECK: encoding: [0x50,0x23,0xfa]
+	wfr f2, a3
+
+# CHECK-INST: rur a3, fcr
+# CHECK: encoding: [0x80,0x3e,0xe3]
+	rur a3, fcr
+
+# CHECK-INST: rur a3, fcr
+# CHECK: encoding: [0x80,0x3e,0xe3]
+	rur a3, 232
+
+# CHECK-INST: rur a3, fcr
+# CHECK: encoding: [0x80,0x3e,0xe3]
+	rur.fcr a3
+
+# CHECK-INST: wur a3, fcr
+# CHECK: encoding: [0x30,0xe8,0xf3]
+	wur a3, fcr
+
+# CHECK-INST: rur a3, fsr
+# CHECK: encoding: [0x90,0x3e,0xe3]
+	rur a3, fsr
+
+# CHECK-INST: rur a3, fsr
+# CHECK: encoding: [0x90,0x3e,0xe3]
+	rur a3, 233
+
+# CHECK-INST: rur a3, fsr
+# CHECK: encoding: [0x90,0x3e,0xe3]
+	rur.fsr a3
+
+# CHECK-INST: wur a3, fsr
+# CHECK: encoding: [0x30,0xe9,0xf3]
+	wur a3, fsr


        


More information about the llvm-commits mailing list