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(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(MCPV); + XtensaConstantPoolValue *XtensaCPV = + static_cast(MCPV); MCSymbol *MCSym; - if (ACPV->isBlockAddress()) { + if (XtensaCPV->isBlockAddress()) { const BlockAddress *BA = - cast(ACPV)->getBlockAddress(); + cast(XtensaCPV)->getBlockAddress(); MCSym = GetBlockAddressSymbol(BA); - } else if (ACPV->isMachineBasicBlock()) { - const MachineBasicBlock *MBB = cast(ACPV)->getMBB(); + } else if (XtensaCPV->isMachineBasicBlock()) { + const MachineBasicBlock *MBB = + cast(XtensaCPV)->getMBB(); MCSym = MBB->getSymbol(); - } else if (ACPV->isJumpTable()) { - unsigned Idx = cast(ACPV)->getIndex(); + } else if (XtensaCPV->isJumpTable()) { + unsigned Idx = cast(XtensaCPV)->getIndex(); MCSym = this->GetJTISymbol(Idx, false); } else { - assert(ACPV->isExtSymbol() && "unrecognized constant pool value"); - XtensaConstantPoolSymbol *XtensaSym = cast(ACPV); + assert(XtensaCPV->isExtSymbol() && "unrecognized constant pool value"); + XtensaConstantPoolSymbol *XtensaSym = + cast(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(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(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(); + 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(Op); + SDLoc DL(Op); const BlockAddress *BA = Node->getBlockAddress(); EVT PtrVT = Op.getValueType(); + MachineFunction &MF = DAG.getMachineFunction(); + XtensaMachineFunctionInfo *XtensaFI = MF.getInfo(); + 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(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 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 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 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 num, string n, list alt = []> : XtensaReg { + 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 num, string n> : XtensaReg { + 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..720a9e58ef956 --- /dev/null +++ b/llvm/test/CodeGen/Xtensa/float-arith.ll @@ -0,0 +1,608 @@ +; 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 +} + +;define float @copysign_f32(float %a, float %b) { +;entry: +; %c = call float @llvm.copysign.f32(float %a, float %b) +; ret float %c +;} 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