diff options
Diffstat (limited to 'contrib/llvm/lib/Target/Sparc')
21 files changed, 1105 insertions, 205 deletions
| diff --git a/contrib/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/contrib/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp index 1c4e486da418..a55274744fd1 100644 --- a/contrib/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ b/contrib/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -14,6 +14,7 @@  #include "llvm/MC/MCInst.h"  #include "llvm/MC/MCObjectFileInfo.h"  #include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/MC/MCRegisterInfo.h"  #include "llvm/MC/MCStreamer.h"  #include "llvm/MC/MCSubtargetInfo.h"  #include "llvm/MC/MCSymbol.h" @@ -34,7 +35,6 @@ namespace {  class SparcOperand;  class SparcAsmParser : public MCTargetAsmParser { -  MCSubtargetInfo &STI;    MCAsmParser &Parser;    /// @name Auto-generated Match Functions @@ -69,6 +69,10 @@ class SparcAsmParser : public MCTargetAsmParser {    OperandMatchResultTy parseBranchModifiers(OperandVector &Operands); +  // Helper function for dealing with %lo / %hi in PIC mode. +  const SparcMCExpr *adjustPICRelocation(SparcMCExpr::VariantKind VK, +                                         const MCExpr *subExpr); +    // returns true if Tok is matched to a register and returns register in RegNo.    bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo,                           unsigned &RegKind); @@ -77,24 +81,24 @@ class SparcAsmParser : public MCTargetAsmParser {    bool parseDirectiveWord(unsigned Size, SMLoc L);    bool is64Bit() const { -    return STI.getTargetTriple().getArch() == Triple::sparcv9; +    return getSTI().getTargetTriple().getArch() == Triple::sparcv9;    }    void expandSET(MCInst &Inst, SMLoc IDLoc,                   SmallVectorImpl<MCInst> &Instructions);  public: -  SparcAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser, +  SparcAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,                  const MCInstrInfo &MII,                  const MCTargetOptions &Options) -      : MCTargetAsmParser(), STI(sti), Parser(parser) { +      : MCTargetAsmParser(Options, sti), Parser(parser) {      // Initialize the set of available features. -    setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); +    setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));    }  }; -  static unsigned IntRegs[32] = { +  static const MCPhysReg IntRegs[32] = {      Sparc::G0, Sparc::G1, Sparc::G2, Sparc::G3,      Sparc::G4, Sparc::G5, Sparc::G6, Sparc::G7,      Sparc::O0, Sparc::O1, Sparc::O2, Sparc::O3, @@ -104,7 +108,7 @@ public:      Sparc::I0, Sparc::I1, Sparc::I2, Sparc::I3,      Sparc::I4, Sparc::I5, Sparc::I6, Sparc::I7 }; -  static unsigned FloatRegs[32] = { +  static const MCPhysReg FloatRegs[32] = {      Sparc::F0,  Sparc::F1,  Sparc::F2,  Sparc::F3,      Sparc::F4,  Sparc::F5,  Sparc::F6,  Sparc::F7,      Sparc::F8,  Sparc::F9,  Sparc::F10, Sparc::F11, @@ -114,7 +118,7 @@ public:      Sparc::F24, Sparc::F25, Sparc::F26, Sparc::F27,      Sparc::F28, Sparc::F29, Sparc::F30, Sparc::F31 }; -  static unsigned DoubleRegs[32] = { +  static const MCPhysReg DoubleRegs[32] = {      Sparc::D0,  Sparc::D1,  Sparc::D2,  Sparc::D3,      Sparc::D4,  Sparc::D5,  Sparc::D6,  Sparc::D7,      Sparc::D8,  Sparc::D7,  Sparc::D8,  Sparc::D9, @@ -124,13 +128,13 @@ public:      Sparc::D24, Sparc::D25, Sparc::D26, Sparc::D27,      Sparc::D28, Sparc::D29, Sparc::D30, Sparc::D31 }; -  static unsigned QuadFPRegs[32] = { +  static const MCPhysReg QuadFPRegs[32] = {      Sparc::Q0,  Sparc::Q1,  Sparc::Q2,  Sparc::Q3,      Sparc::Q4,  Sparc::Q5,  Sparc::Q6,  Sparc::Q7,      Sparc::Q8,  Sparc::Q9,  Sparc::Q10, Sparc::Q11,      Sparc::Q12, Sparc::Q13, Sparc::Q14, Sparc::Q15 }; -  static unsigned ASRRegs[32] = { +  static const MCPhysReg ASRRegs[32] = {      SP::Y,     SP::ASR1,  SP::ASR2,  SP::ASR3,      SP::ASR4,  SP::ASR5,  SP::ASR6, SP::ASR7,      SP::ASR8,  SP::ASR9,  SP::ASR10, SP::ASR11, @@ -140,6 +144,12 @@ public:      SP::ASR24, SP::ASR25, SP::ASR26, SP::ASR27,      SP::ASR28, SP::ASR29, SP::ASR30, SP::ASR31}; +  static const MCPhysReg IntPairRegs[] = { +    Sparc::G0_G1, Sparc::G2_G3, Sparc::G4_G5, Sparc::G6_G7, +    Sparc::O0_O1, Sparc::O2_O3, Sparc::O4_O5, Sparc::O6_O7, +    Sparc::L0_L1, Sparc::L2_L3, Sparc::L4_L5, Sparc::L6_L7, +    Sparc::I0_I1, Sparc::I2_I3, Sparc::I4_I5, Sparc::I6_I7}; +  /// SparcOperand - Instances of this class represent a parsed Sparc machine  /// instruction.  class SparcOperand : public MCParsedAsmOperand { @@ -147,6 +157,7 @@ public:    enum RegisterKind {      rk_None,      rk_IntReg, +    rk_IntPairReg,      rk_FloatReg,      rk_DoubleReg,      rk_QuadReg, @@ -200,6 +211,10 @@ public:    bool isMEMrr() const { return Kind == k_MemoryReg; }    bool isMEMri() const { return Kind == k_MemoryImm; } +  bool isIntReg() const { +    return (Kind == k_Register && Reg.Kind == rk_IntReg); +  } +    bool isFloatReg() const {      return (Kind == k_Register && Reg.Kind == rk_FloatReg);    } @@ -330,6 +345,25 @@ public:      return Op;    } +  static bool MorphToIntPairReg(SparcOperand &Op) { +    unsigned Reg = Op.getReg(); +    assert(Op.Reg.Kind == rk_IntReg); +    unsigned regIdx = 32; +    if (Reg >= Sparc::G0 && Reg <= Sparc::G7) +      regIdx = Reg - Sparc::G0; +    else if (Reg >= Sparc::O0 && Reg <= Sparc::O7) +      regIdx = Reg - Sparc::O0 + 8; +    else if (Reg >= Sparc::L0 && Reg <= Sparc::L7) +      regIdx = Reg - Sparc::L0 + 16; +    else if (Reg >= Sparc::I0 && Reg <= Sparc::I7) +      regIdx = Reg - Sparc::I0 + 24; +    if (regIdx % 2 || regIdx > 31) +      return false; +    Op.Reg.RegNum = IntPairRegs[regIdx / 2]; +    Op.Reg.Kind = rk_IntPairReg; +    return true; +  } +    static bool MorphToDoubleReg(SparcOperand &Op) {      unsigned Reg = Op.getReg();      assert(Op.Reg.Kind == rk_FloatReg); @@ -407,7 +441,22 @@ void SparcAsmParser::expandSET(MCInst &Inst, SMLoc IDLoc,    // the imm operand can be either an expression or an immediate.    bool IsImm = Inst.getOperand(1).isImm(); -  uint64_t ImmValue = IsImm ? MCValOp.getImm() : 0; +  int64_t RawImmValue = IsImm ? MCValOp.getImm() : 0; + +  // Allow either a signed or unsigned 32-bit immediate. +  if (RawImmValue < -2147483648LL || RawImmValue > 4294967295LL) { +    Error(IDLoc, "set: argument must be between -2147483648 and 4294967295"); +    return; +  } + +  // If the value was expressed as a large unsigned number, that's ok. +  // We want to see if it "looks like" a small signed number. +  int32_t ImmValue = RawImmValue; +  // For 'set' you can't use 'or' with a negative operand on V9 because +  // that would splat the sign bit across the upper half of the destination +  // register, whereas 'set' is defined to zero the high 32 bits. +  bool IsEffectivelyImm13 = +      IsImm && ((is64Bit() ? 0 : -4096) <= ImmValue && ImmValue < 4096);    const MCExpr *ValExpr;    if (IsImm)      ValExpr = MCConstantExpr::create(ImmValue, getContext()); @@ -416,10 +465,12 @@ void SparcAsmParser::expandSET(MCInst &Inst, SMLoc IDLoc,    MCOperand PrevReg = MCOperand::createReg(Sparc::G0); -  if (!IsImm || (ImmValue & ~0x1fff)) { +  // If not just a signed imm13 value, then either we use a 'sethi' with a +  // following 'or', or a 'sethi' by itself if there are no more 1 bits. +  // In either case, start with the 'sethi'. +  if (!IsEffectivelyImm13) {      MCInst TmpInst; -    const MCExpr *Expr = -        SparcMCExpr::create(SparcMCExpr::VK_Sparc_HI, ValExpr, getContext()); +    const MCExpr *Expr = adjustPICRelocation(SparcMCExpr::VK_Sparc_HI, ValExpr);      TmpInst.setLoc(IDLoc);      TmpInst.setOpcode(SP::SETHIi);      TmpInst.addOperand(MCRegOp); @@ -428,10 +479,23 @@ void SparcAsmParser::expandSET(MCInst &Inst, SMLoc IDLoc,      PrevReg = MCRegOp;    } -  if (!IsImm || ((ImmValue & 0x1fff) != 0 || ImmValue == 0)) { +  // The low bits require touching in 3 cases: +  // * A non-immediate value will always require both instructions. +  // * An effectively imm13 value needs only an 'or' instruction. +  // * Otherwise, an immediate that is not effectively imm13 requires the +  //   'or' only if bits remain after clearing the 22 bits that 'sethi' set. +  // If the low bits are known zeros, there's nothing to do. +  // In the second case, and only in that case, must we NOT clear +  // bits of the immediate value via the %lo() assembler function. +  // Note also, the 'or' instruction doesn't mind a large value in the case +  // where the operand to 'set' was 0xFFFFFzzz - it does exactly what you mean. +  if (!IsImm || IsEffectivelyImm13 || (ImmValue & 0x3ff)) {      MCInst TmpInst; -    const MCExpr *Expr = -        SparcMCExpr::create(SparcMCExpr::VK_Sparc_LO, ValExpr, getContext()); +    const MCExpr *Expr; +    if (IsEffectivelyImm13) +      Expr = ValExpr; +    else +      Expr = adjustPICRelocation(SparcMCExpr::VK_Sparc_LO, ValExpr);      TmpInst.setLoc(IDLoc);      TmpInst.setOpcode(SP::ORri);      TmpInst.addOperand(MCRegOp); @@ -463,7 +527,7 @@ bool SparcAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,      }      for (const MCInst &I : Instructions) { -      Out.EmitInstruction(I, STI); +      Out.EmitInstruction(I, getSTI());      }      return false;    } @@ -742,6 +806,9 @@ SparcAsmParser::parseSparcAsmOperand(std::unique_ptr<SparcOperand> &Op,        case Sparc::PSR:          Op = SparcOperand::CreateToken("%psr", S);          break; +      case Sparc::FSR: +        Op = SparcOperand::CreateToken("%fsr", S); +        break;        case Sparc::WIM:          Op = SparcOperand::CreateToken("%wim", S);          break; @@ -766,6 +833,7 @@ SparcAsmParser::parseSparcAsmOperand(std::unique_ptr<SparcOperand> &Op,    case AsmToken::Minus:    case AsmToken::Integer:    case AsmToken::LParen: +  case AsmToken::Dot:      if (!getParser().parseExpression(EVal, E))        Op = SparcOperand::CreateImm(EVal, S, E);      break; @@ -848,6 +916,13 @@ bool SparcAsmParser::matchRegisterName(const AsmToken &Tok,        return true;      } +    // %fprs is an alias of %asr6. +    if (name.equals("fprs")) { +      RegNo = ASRRegs[6]; +      RegKind = SparcOperand::rk_Special; +      return true; +    } +      if (name.equals("icc")) {        RegNo = Sparc::ICC;        RegKind = SparcOperand::rk_Special; @@ -860,6 +935,12 @@ bool SparcAsmParser::matchRegisterName(const AsmToken &Tok,        return true;      } +    if (name.equals("fsr")) { +      RegNo = Sparc::FSR; +      RegKind = SparcOperand::rk_Special; +      return true; +    } +      if (name.equals("wim")) {        RegNo = Sparc::WIM;        RegKind = SparcOperand::rk_Special; @@ -943,6 +1024,82 @@ bool SparcAsmParser::matchRegisterName(const AsmToken &Tok,        RegKind = SparcOperand::rk_IntReg;        return true;      } + +    if (name.equals("tpc")) { +      RegNo = Sparc::TPC; +      RegKind = SparcOperand::rk_Special; +      return true; +    } +    if (name.equals("tnpc")) { +      RegNo = Sparc::TNPC; +      RegKind = SparcOperand::rk_Special; +      return true; +    } +    if (name.equals("tstate")) { +      RegNo = Sparc::TSTATE; +      RegKind = SparcOperand::rk_Special; +      return true; +    } +    if (name.equals("tt")) { +      RegNo = Sparc::TT; +      RegKind = SparcOperand::rk_Special; +      return true; +    } +    if (name.equals("tick")) { +      RegNo = Sparc::TICK; +      RegKind = SparcOperand::rk_Special; +      return true; +    } +    if (name.equals("tba")) { +      RegNo = Sparc::TBA; +      RegKind = SparcOperand::rk_Special; +      return true; +    } +    if (name.equals("pstate")) { +      RegNo = Sparc::PSTATE; +      RegKind = SparcOperand::rk_Special; +      return true; +    } +    if (name.equals("tl")) { +      RegNo = Sparc::TL; +      RegKind = SparcOperand::rk_Special; +      return true; +    } +    if (name.equals("pil")) { +      RegNo = Sparc::PIL; +      RegKind = SparcOperand::rk_Special; +      return true; +    } +    if (name.equals("cwp")) { +      RegNo = Sparc::CWP; +      RegKind = SparcOperand::rk_Special; +      return true; +    } +    if (name.equals("cansave")) { +      RegNo = Sparc::CANSAVE; +      RegKind = SparcOperand::rk_Special; +      return true; +    } +    if (name.equals("canrestore")) { +      RegNo = Sparc::CANRESTORE; +      RegKind = SparcOperand::rk_Special; +      return true; +    } +    if (name.equals("cleanwin")) { +      RegNo = Sparc::CLEANWIN; +      RegKind = SparcOperand::rk_Special; +      return true; +    } +    if (name.equals("otherwin")) { +      RegNo = Sparc::OTHERWIN; +      RegKind = SparcOperand::rk_Special; +      return true; +    } +    if (name.equals("wstate")) { +      RegNo = Sparc::WSTATE; +      RegKind = SparcOperand::rk_Special; +      return true; +    }    }    return false;  } @@ -975,6 +1132,32 @@ static bool hasGOTReference(const MCExpr *Expr) {    return false;  } +const SparcMCExpr * +SparcAsmParser::adjustPICRelocation(SparcMCExpr::VariantKind VK, +                                    const MCExpr *subExpr) +{ +  // When in PIC mode, "%lo(...)" and "%hi(...)" behave differently. +  // If the expression refers contains _GLOBAL_OFFSETE_TABLE, it is +  // actually a %pc10 or %pc22 relocation. Otherwise, they are interpreted +  // as %got10 or %got22 relocation. + +  if (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_) { +    switch(VK) { +    default: break; +    case SparcMCExpr::VK_Sparc_LO: +      VK = (hasGOTReference(subExpr) ? SparcMCExpr::VK_Sparc_PC10 +                                     : SparcMCExpr::VK_Sparc_GOT10); +      break; +    case SparcMCExpr::VK_Sparc_HI: +      VK = (hasGOTReference(subExpr) ? SparcMCExpr::VK_Sparc_PC22 +                                     : SparcMCExpr::VK_Sparc_GOT22); +      break; +    } +  } + +  return SparcMCExpr::create(VK, subExpr, getContext()); +} +  bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal,                                              SMLoc &EndLoc)  { @@ -998,30 +1181,7 @@ bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal,    if (Parser.parseParenExpression(subExpr, EndLoc))      return false; -  bool isPIC = getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_; - -  // Ugly: if a sparc assembly expression says "%hi(...)" but the -  // expression within contains _GLOBAL_OFFSET_TABLE_, it REALLY means -  // %pc22. Same with %lo -> %pc10. Worse, if it doesn't contain that, -  // the meaning depends on whether the assembler was invoked with -  // -KPIC or not: if so, it really means %got22/%got10; if not, it -  // actually means what it said! Sigh, historical mistakes... - -  switch(VK) { -  default: break; -  case SparcMCExpr::VK_Sparc_LO: -    VK =  (hasGOTReference(subExpr) -           ? SparcMCExpr::VK_Sparc_PC10 -           : (isPIC ? SparcMCExpr::VK_Sparc_GOT10 : VK)); -    break; -  case SparcMCExpr::VK_Sparc_HI: -    VK =  (hasGOTReference(subExpr) -           ? SparcMCExpr::VK_Sparc_PC22 -           : (isPIC ? SparcMCExpr::VK_Sparc_GOT22 : VK)); -    break; -  } - -  EVal = SparcMCExpr::create(VK, subExpr, getContext()); +  EVal = adjustPICRelocation(VK, subExpr);    return true;  } @@ -1051,5 +1211,9 @@ unsigned SparcAsmParser::validateTargetOperandClass(MCParsedAsmOperand &GOp,        break;      }    } +  if (Op.isIntReg() && Kind == MCK_IntPair) { +    if (SparcOperand::MorphToIntPairReg(Op)) +      return MCTargetAsmParser::Match_Success; +  }    return Match_InvalidOperand;  } diff --git a/contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp b/contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp index 38bff44e7542..c689b7f7201e 100644 --- a/contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp +++ b/contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp @@ -122,6 +122,8 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {        continue;      } +    // TODO: If we ever want to support v7, this needs to be extended +    // to cover all floating point operations.      if (!Subtarget->isV9() &&          (MI->getOpcode() == SP::FCMPS || MI->getOpcode() == SP::FCMPD           || MI->getOpcode() == SP::FCMPQ)) { diff --git a/contrib/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp b/contrib/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp index 3e56b9e9b883..51751ec511c9 100644 --- a/contrib/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp +++ b/contrib/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp @@ -117,6 +117,19 @@ static const unsigned ASRRegDecoderTable[] = {    SP::ASR24, SP::ASR25, SP::ASR26, SP::ASR27,    SP::ASR28, SP::ASR29, SP::ASR30, SP::ASR31}; +static const unsigned PRRegDecoderTable[] = { +  SP::TPC, SP::TNPC, SP::TSTATE, SP::TT, SP::TICK, SP::TBA, SP::PSTATE, +  SP::TL, SP::PIL, SP::CWP, SP::CANSAVE, SP::CANRESTORE, SP::CLEANWIN, +  SP::OTHERWIN, SP::WSTATE +}; + +static const uint16_t IntPairDecoderTable[] = { +  SP::G0_G1, SP::G2_G3, SP::G4_G5, SP::G6_G7, +  SP::O0_O1, SP::O2_O3, SP::O4_O5, SP::O6_O7, +  SP::L0_L1, SP::L2_L3, SP::L4_L5, SP::L6_L7, +  SP::I0_I1, SP::I2_I3, SP::I4_I5, SP::I6_I7, +}; +  static DecodeStatus DecodeIntRegsRegisterClass(MCInst &Inst,                                                 unsigned RegNo,                                                 uint64_t Address, @@ -196,9 +209,34 @@ static DecodeStatus DecodeASRRegsRegisterClass(MCInst &Inst, unsigned RegNo,    return MCDisassembler::Success;  } +static DecodeStatus DecodePRRegsRegisterClass(MCInst &Inst, unsigned RegNo, +                                               uint64_t Address, +                                               const void *Decoder) { +  if (RegNo >= array_lengthof(PRRegDecoderTable)) +    return MCDisassembler::Fail; +  Inst.addOperand(MCOperand::createReg(PRRegDecoderTable[RegNo])); +  return MCDisassembler::Success; +} + +static DecodeStatus DecodeIntPairRegisterClass(MCInst &Inst, unsigned RegNo, +                                   uint64_t Address, const void *Decoder) { +  DecodeStatus S = MCDisassembler::Success; + +  if (RegNo > 31) +    return MCDisassembler::Fail; + +  if ((RegNo & 1)) +    S = MCDisassembler::SoftFail; + +  unsigned RegisterPair = IntPairDecoderTable[RegNo/2]; +  Inst.addOperand(MCOperand::createReg(RegisterPair)); +  return S; +}  static DecodeStatus DecodeLoadInt(MCInst &Inst, unsigned insn, uint64_t Address,                                    const void *Decoder); +static DecodeStatus DecodeLoadIntPair(MCInst &Inst, unsigned insn, uint64_t Address, +                                  const void *Decoder);  static DecodeStatus DecodeLoadFP(MCInst &Inst, unsigned insn, uint64_t Address,                                   const void *Decoder);  static DecodeStatus DecodeLoadDFP(MCInst &Inst, unsigned insn, uint64_t Address, @@ -207,6 +245,8 @@ static DecodeStatus DecodeLoadQFP(MCInst &Inst, unsigned insn, uint64_t Address,                                    const void *Decoder);  static DecodeStatus DecodeStoreInt(MCInst &Inst, unsigned insn,                                     uint64_t Address, const void *Decoder); +static DecodeStatus DecodeStoreIntPair(MCInst &Inst, unsigned insn, +                                   uint64_t Address, const void *Decoder);  static DecodeStatus DecodeStoreFP(MCInst &Inst, unsigned insn,                                    uint64_t Address, const void *Decoder);  static DecodeStatus DecodeStoreDFP(MCInst &Inst, unsigned insn, @@ -326,6 +366,12 @@ static DecodeStatus DecodeLoadInt(MCInst &Inst, unsigned insn, uint64_t Address,                     DecodeIntRegsRegisterClass);  } +static DecodeStatus DecodeLoadIntPair(MCInst &Inst, unsigned insn, uint64_t Address, +                                  const void *Decoder) { +  return DecodeMem(Inst, insn, Address, Decoder, true, +                   DecodeIntPairRegisterClass); +} +  static DecodeStatus DecodeLoadFP(MCInst &Inst, unsigned insn, uint64_t Address,                                   const void *Decoder) {    return DecodeMem(Inst, insn, Address, Decoder, true, @@ -350,6 +396,12 @@ static DecodeStatus DecodeStoreInt(MCInst &Inst, unsigned insn,                     DecodeIntRegsRegisterClass);  } +static DecodeStatus DecodeStoreIntPair(MCInst &Inst, unsigned insn, +                                   uint64_t Address, const void *Decoder) { +  return DecodeMem(Inst, insn, Address, Decoder, false, +                   DecodeIntPairRegisterClass); +} +  static DecodeStatus DecodeStoreFP(MCInst &Inst, unsigned insn, uint64_t Address,                                    const void *Decoder) {    return DecodeMem(Inst, insn, Address, Decoder, false, diff --git a/contrib/llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h b/contrib/llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h index 0b01b88e5250..6f06d1ddae32 100644 --- a/contrib/llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h +++ b/contrib/llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h @@ -15,12 +15,9 @@  #define LLVM_LIB_TARGET_SPARC_INSTPRINTER_SPARCINSTPRINTER_H  #include "llvm/MC/MCInstPrinter.h" -#include "llvm/MC/MCSubtargetInfo.h"  namespace llvm { -class MCOperand; -  class SparcInstPrinter : public MCInstPrinter {  public:    SparcInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h index 12386f14443e..ad441227600e 100644 --- a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h +++ b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h @@ -21,6 +21,7 @@ class Triple;  class SparcELFMCAsmInfo : public MCAsmInfoELF {    void anchor() override; +  public:    explicit SparcELFMCAsmInfo(const Triple &TheTriple);    const MCExpr* diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h index d08ad86dbe04..13f08195c764 100644 --- a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h +++ b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h @@ -90,8 +90,8 @@ public:                                   const MCAsmLayout *Layout,                                   const MCFixup *Fixup) const override;    void visitUsedExpr(MCStreamer &Streamer) const override; -  MCSection *findAssociatedSection() const override { -    return getSubExpr()->findAssociatedSection(); +  MCFragment *findAssociatedFragment() const override { +    return getSubExpr()->findAssociatedFragment();    }    void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override; diff --git a/contrib/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp b/contrib/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp index c5f046bfc5bb..e3b0f5266747 100644 --- a/contrib/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp +++ b/contrib/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp @@ -267,11 +267,11 @@ void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI)      LowerGETPCXAndEmitMCInsts(MI, getSubtargetInfo());      return;    } -  MachineBasicBlock::const_instr_iterator I = MI; +  MachineBasicBlock::const_instr_iterator I = MI->getIterator();    MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();    do {      MCInst TmpInst; -    LowerSparcMachineInstrToMCInst(I, TmpInst, *this); +    LowerSparcMachineInstrToMCInst(&*I, TmpInst, *this);      EmitToStreamer(*OutStreamer, TmpInst);    } while ((++I != E) && I->isInsideBundle()); // Delay slot check.  } @@ -296,7 +296,7 @@ void SparcAsmPrinter::EmitFunctionBodyStart() {  void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum,                                     raw_ostream &O) { -  const DataLayout *DL = TM.getDataLayout(); +  const DataLayout &DL = getDataLayout();    const MachineOperand &MO = MI->getOperand (opNum);    SparcMCExpr::VariantKind TF = (SparcMCExpr::VariantKind) MO.getTargetFlags(); @@ -373,7 +373,7 @@ void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum,      O << MO.getSymbolName();      break;    case MachineOperand::MO_ConstantPoolIndex: -    O << DL->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" +    O << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"        << MO.getIndex();      break;    default: diff --git a/contrib/llvm/lib/Target/Sparc/SparcCallingConv.td b/contrib/llvm/lib/Target/Sparc/SparcCallingConv.td index dfaaabf344a3..0aa29d186dc1 100644 --- a/contrib/llvm/lib/Target/Sparc/SparcCallingConv.td +++ b/contrib/llvm/lib/Target/Sparc/SparcCallingConv.td @@ -21,7 +21,11 @@ def CC_Sparc32 : CallingConv<[    // i32 f32 arguments get passed in integer registers if there is space.    CCIfType<[i32, f32], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>,    // f64 arguments are split and passed through registers or through stack. -  CCIfType<[f64], CCCustom<"CC_Sparc_Assign_f64">>, +  CCIfType<[f64], CCCustom<"CC_Sparc_Assign_Split_64">>, +  // As are v2i32 arguments (this would be the default behavior for +  // v2i32 if it wasn't allocated to the IntPair register-class) +  CCIfType<[v2i32], CCCustom<"CC_Sparc_Assign_Split_64">>, +    // Alternatively, they are assigned to the stack in 4-byte aligned units.    CCAssignToStack<4, 4> @@ -30,7 +34,8 @@ def CC_Sparc32 : CallingConv<[  def RetCC_Sparc32 : CallingConv<[    CCIfType<[i32], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>,    CCIfType<[f32], CCAssignToReg<[F0, F1, F2, F3]>>, -  CCIfType<[f64], CCAssignToReg<[D0, D1]>> +  CCIfType<[f64], CCAssignToReg<[D0, D1]>>, +  CCIfType<[v2i32], CCCustom<"CC_Sparc_Assign_Ret_Split_64">>  ]>; diff --git a/contrib/llvm/lib/Target/Sparc/SparcFrameLowering.cpp b/contrib/llvm/lib/Target/Sparc/SparcFrameLowering.cpp index c0279daa63d9..39b5e809c9be 100644 --- a/contrib/llvm/lib/Target/Sparc/SparcFrameLowering.cpp +++ b/contrib/llvm/lib/Target/Sparc/SparcFrameLowering.cpp @@ -44,7 +44,7 @@ void SparcFrameLowering::emitSPAdjustment(MachineFunction &MF,                                            unsigned ADDrr,                                            unsigned ADDri) const { -  DebugLoc dl = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc(); +  DebugLoc dl;    const SparcInstrInfo &TII =        *static_cast<const SparcInstrInfo *>(MF.getSubtarget().getInstrInfo()); @@ -90,8 +90,23 @@ void SparcFrameLowering::emitPrologue(MachineFunction &MF,    MachineFrameInfo *MFI = MF.getFrameInfo();    const SparcInstrInfo &TII =        *static_cast<const SparcInstrInfo *>(MF.getSubtarget().getInstrInfo()); +  const SparcRegisterInfo &RegInfo = +      *static_cast<const SparcRegisterInfo *>(MF.getSubtarget().getRegisterInfo());    MachineBasicBlock::iterator MBBI = MBB.begin(); -  DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); +  // Debug location must be unknown since the first debug location is used +  // to determine the end of the prologue. +  DebugLoc dl; +  bool NeedsStackRealignment = RegInfo.needsStackRealignment(MF); + +  // FIXME: unfortunately, returning false from canRealignStack +  // actually just causes needsStackRealignment to return false, +  // rather than reporting an error, as would be sensible. This is +  // poor, but fixing that bogosity is going to be a large project. +  // For now, just see if it's lied, and report an error here. +  if (!NeedsStackRealignment && MFI->getMaxAlignment() > getStackAlignment()) +    report_fatal_error("Function \"" + Twine(MF.getName()) + "\" required " +                       "stack re-alignment, but LLVM couldn't handle it " +                       "(probably because it has a dynamic alloca).");    // Get the number of bytes to allocate from the FrameInfo    int NumBytes = (int) MFI->getStackSize(); @@ -104,12 +119,43 @@ void SparcFrameLowering::emitPrologue(MachineFunction &MF,      SAVEri = SP::ADDri;      SAVErr = SP::ADDrr;    } -  NumBytes = -MF.getSubtarget<SparcSubtarget>().getAdjustedFrameSize(NumBytes); -  emitSPAdjustment(MF, MBB, MBBI, NumBytes, SAVErr, SAVEri); + +  // The SPARC ABI is a bit odd in that it requires a reserved 92-byte +  // (128 in v9) area in the user's stack, starting at %sp. Thus, the +  // first part of the stack that can actually be used is located at +  // %sp + 92. +  // +  // We therefore need to add that offset to the total stack size +  // after all the stack objects are placed by +  // PrologEpilogInserter calculateFrameObjectOffsets. However, since the stack needs to be +  // aligned *after* the extra size is added, we need to disable +  // calculateFrameObjectOffsets's built-in stack alignment, by having +  // targetHandlesStackFrameRounding return true. + + +  // Add the extra call frame stack size, if needed. (This is the same +  // code as in PrologEpilogInserter, but also gets disabled by +  // targetHandlesStackFrameRounding) +  if (MFI->adjustsStack() && hasReservedCallFrame(MF)) +    NumBytes += MFI->getMaxCallFrameSize(); + +  // Adds the SPARC subtarget-specific spill area to the stack +  // size. Also ensures target-required alignment. +  NumBytes = MF.getSubtarget<SparcSubtarget>().getAdjustedFrameSize(NumBytes); + +  // Finally, ensure that the size is sufficiently aligned for the +  // data on the stack. +  if (MFI->getMaxAlignment() > 0) { +    NumBytes = RoundUpToAlignment(NumBytes, MFI->getMaxAlignment()); +  } + +  // Update stack size with corrected value. +  MFI->setStackSize(NumBytes); + +  emitSPAdjustment(MF, MBB, MBBI, -NumBytes, SAVErr, SAVEri);    MachineModuleInfo &MMI = MF.getMMI(); -  const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); -  unsigned regFP = MRI->getDwarfRegNum(SP::I6, true); +  unsigned regFP = RegInfo.getDwarfRegNum(SP::I6, true);    // Emit ".cfi_def_cfa_register 30".    unsigned CFIIndex = @@ -122,13 +168,19 @@ void SparcFrameLowering::emitPrologue(MachineFunction &MF,    BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))        .addCFIIndex(CFIIndex); -  unsigned regInRA = MRI->getDwarfRegNum(SP::I7, true); -  unsigned regOutRA = MRI->getDwarfRegNum(SP::O7, true); +  unsigned regInRA = RegInfo.getDwarfRegNum(SP::I7, true); +  unsigned regOutRA = RegInfo.getDwarfRegNum(SP::O7, true);    // Emit ".cfi_register 15, 31".    CFIIndex = MMI.addFrameInst(        MCCFIInstruction::createRegister(nullptr, regOutRA, regInRA));    BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))        .addCFIIndex(CFIIndex); + +  if (NeedsStackRealignment) { +    // andn %o6, MaxAlign-1, %o6 +    int MaxAlign = MFI->getMaxAlignment(); +    BuildMI(MBB, MBBI, dl, TII.get(SP::ANDNri), SP::O6).addReg(SP::O6).addImm(MaxAlign - 1); +  }  }  void SparcFrameLowering:: @@ -167,7 +219,6 @@ void SparcFrameLowering::emitEpilogue(MachineFunction &MF,    if (NumBytes == 0)      return; -  NumBytes = MF.getSubtarget<SparcSubtarget>().getAdjustedFrameSize(NumBytes);    emitSPAdjustment(MF, MBB, MBBI, NumBytes, SP::ADDrr, SP::ADDri);  } @@ -180,21 +231,69 @@ bool SparcFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {  // pointer register.  This is true if the function has variable sized allocas or  // if frame pointer elimination is disabled.  bool SparcFrameLowering::hasFP(const MachineFunction &MF) const { +  const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); +    const MachineFrameInfo *MFI = MF.getFrameInfo();    return MF.getTarget().Options.DisableFramePointerElim(MF) || -    MFI->hasVarSizedObjects() || MFI->isFrameAddressTaken(); +      RegInfo->needsStackRealignment(MF) || +      MFI->hasVarSizedObjects() || +      MFI->isFrameAddressTaken();  } +int SparcFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, +                                               unsigned &FrameReg) const { +  const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>(); +  const MachineFrameInfo *MFI = MF.getFrameInfo(); +  const SparcRegisterInfo *RegInfo = Subtarget.getRegisterInfo(); +  const SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); +  bool isFixed = MFI->isFixedObjectIndex(FI); + +  // Addressable stack objects are accessed using neg. offsets from +  // %fp, or positive offsets from %sp. +  bool UseFP; + +  // Sparc uses FP-based references in general, even when "hasFP" is +  // false. That function is rather a misnomer, because %fp is +  // actually always available, unless isLeafProc. +  if (FuncInfo->isLeafProc()) { +    // If there's a leaf proc, all offsets need to be %sp-based, +    // because we haven't caused %fp to actually point to our frame. +    UseFP = false; +  } else if (isFixed) { +    // Otherwise, argument access should always use %fp. +    UseFP = true; +  } else if (RegInfo->needsStackRealignment(MF)) { +    // If there is dynamic stack realignment, all local object +    // references need to be via %sp, to take account of the +    // re-alignment. +    UseFP = false; +  } else { +    // Finally, default to using %fp. +    UseFP = true; +  } + +  int64_t FrameOffset = MF.getFrameInfo()->getObjectOffset(FI) + +      Subtarget.getStackPointerBias(); + +  if (UseFP) { +    FrameReg = RegInfo->getFrameRegister(MF); +    return FrameOffset; +  } else { +    FrameReg = SP::O6; // %sp +    return FrameOffset + MF.getFrameInfo()->getStackSize(); +  } +} +  static bool LLVM_ATTRIBUTE_UNUSED verifyLeafProcRegUse(MachineRegisterInfo *MRI)  {    for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) -    if (MRI->isPhysRegUsed(reg)) +    if (!MRI->reg_nodbg_empty(reg))        return false;    for (unsigned reg = SP::L0; reg <= SP::L7; ++reg) -    if (MRI->isPhysRegUsed(reg)) +    if (!MRI->reg_nodbg_empty(reg))        return false;    return true; @@ -206,33 +305,42 @@ bool SparcFrameLowering::isLeafProc(MachineFunction &MF) const    MachineRegisterInfo &MRI = MF.getRegInfo();    MachineFrameInfo    *MFI = MF.getFrameInfo(); -  return !(MFI->hasCalls()              // has calls -           || MRI.isPhysRegUsed(SP::L0) // Too many registers needed -           || MRI.isPhysRegUsed(SP::O6) // %SP is used -           || hasFP(MF));               // need %FP +  return !(MFI->hasCalls()                 // has calls +           || !MRI.reg_nodbg_empty(SP::L0) // Too many registers needed +           || !MRI.reg_nodbg_empty(SP::O6) // %SP is used +           || hasFP(MF));                  // need %FP  }  void SparcFrameLowering::remapRegsForLeafProc(MachineFunction &MF) const { -    MachineRegisterInfo &MRI = MF.getRegInfo(); -    // Remap %i[0-7] to %o[0-7].    for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) { -    if (!MRI.isPhysRegUsed(reg)) +    if (MRI.reg_nodbg_empty(reg))        continue; -    unsigned mapped_reg = (reg - SP::I0 + SP::O0); -    assert(!MRI.isPhysRegUsed(mapped_reg)); + +    unsigned mapped_reg = reg - SP::I0 + SP::O0; +    assert(MRI.reg_nodbg_empty(mapped_reg));      // Replace I register with O register.      MRI.replaceRegWith(reg, mapped_reg); -    // Mark the reg unused. -    MRI.setPhysRegUnused(reg); +    // Also replace register pair super-registers. +    if ((reg - SP::I0) % 2 == 0) { +      unsigned preg = (reg - SP::I0) / 2 + SP::I0_I1; +      unsigned mapped_preg = preg - SP::I0_I1 + SP::O0_O1; +      MRI.replaceRegWith(preg, mapped_preg); +    }    }    // Rewrite MBB's Live-ins.    for (MachineFunction::iterator MBB = MF.begin(), E = MF.end();         MBB != E; ++MBB) { +    for (unsigned reg = SP::I0_I1; reg <= SP::I6_I7; ++reg) { +      if (!MBB->isLiveIn(reg)) +        continue; +      MBB->removeLiveIn(reg); +      MBB->addLiveIn(reg - SP::I0_I1 + SP::O0_O1); +    }      for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) {        if (!MBB->isLiveIn(reg))          continue; diff --git a/contrib/llvm/lib/Target/Sparc/SparcFrameLowering.h b/contrib/llvm/lib/Target/Sparc/SparcFrameLowering.h index 29fc7b7ba036..cbb4dc04fc23 100644 --- a/contrib/llvm/lib/Target/Sparc/SparcFrameLowering.h +++ b/contrib/llvm/lib/Target/Sparc/SparcFrameLowering.h @@ -39,6 +39,14 @@ public:    void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,                              RegScavenger *RS = nullptr) const override; +  int getFrameIndexReference(const MachineFunction &MF, int FI, +                             unsigned &FrameReg) const override; + +  /// targetHandlesStackFrameRounding - Returns true if the target is +  /// responsible for rounding up the stack frame (probably at emitPrologue +  /// time). +  bool targetHandlesStackFrameRounding() const override { return true; } +  private:    // Remap input registers to output registers for leaf procedure.    void remapRegsForLeafProc(MachineFunction &MF) const; diff --git a/contrib/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp b/contrib/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp index 340b72e7940f..c4c641659df3 100644 --- a/contrib/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp +++ b/contrib/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp @@ -12,6 +12,7 @@  //===----------------------------------------------------------------------===//  #include "SparcTargetMachine.h" +#include "llvm/CodeGen/MachineRegisterInfo.h"  #include "llvm/CodeGen/SelectionDAGISel.h"  #include "llvm/IR/Intrinsics.h"  #include "llvm/Support/Compiler.h" @@ -62,6 +63,7 @@ public:  private:    SDNode* getGlobalBaseReg(); +  SDNode *SelectInlineAsm(SDNode *N);  };  }  // end anonymous namespace @@ -141,6 +143,181 @@ bool SparcDAGToDAGISel::SelectADDRrr(SDValue Addr, SDValue &R1, SDValue &R2) {    return true;  } + +// Re-assemble i64 arguments split up in SelectionDAGBuilder's +// visitInlineAsm / GetRegistersForValue functions. +// +// Note: This function was copied from, and is essentially identical +// to ARMISelDAGToDAG::SelectInlineAsm. It is very unfortunate that +// such hacking-up is necessary; a rethink of how inline asm operands +// are handled may be in order to make doing this more sane. +// +// TODO: fix inline asm support so I can simply tell it that 'i64' +// inputs to asm need to be allocated to the IntPair register type, +// and have that work. Then, delete this function. +SDNode *SparcDAGToDAGISel::SelectInlineAsm(SDNode *N){ +  std::vector<SDValue> AsmNodeOperands; +  unsigned Flag, Kind; +  bool Changed = false; +  unsigned NumOps = N->getNumOperands(); + +  // Normally, i64 data is bounded to two arbitrary GPRs for "%r" +  // constraint.  However, some instructions (e.g. ldd/std) require +  // (even/even+1) GPRs. + +  // So, here, we check for this case, and mutate the inlineasm to use +  // a single IntPair register instead, which guarantees such even/odd +  // placement. + +  SDLoc dl(N); +  SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1) +                                   : SDValue(nullptr,0); + +  SmallVector<bool, 8> OpChanged; +  // Glue node will be appended late. +  for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) { +    SDValue op = N->getOperand(i); +    AsmNodeOperands.push_back(op); + +    if (i < InlineAsm::Op_FirstOperand) +      continue; + +    if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) { +      Flag = C->getZExtValue(); +      Kind = InlineAsm::getKind(Flag); +    } +    else +      continue; + +    // Immediate operands to inline asm in the SelectionDAG are modeled with +    // two operands. The first is a constant of value InlineAsm::Kind_Imm, and +    // the second is a constant with the value of the immediate. If we get here +    // and we have a Kind_Imm, skip the next operand, and continue. +    if (Kind == InlineAsm::Kind_Imm) { +      SDValue op = N->getOperand(++i); +      AsmNodeOperands.push_back(op); +      continue; +    } + +    unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag); +    if (NumRegs) +      OpChanged.push_back(false); + +    unsigned DefIdx = 0; +    bool IsTiedToChangedOp = false; +    // If it's a use that is tied with a previous def, it has no +    // reg class constraint. +    if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx)) +      IsTiedToChangedOp = OpChanged[DefIdx]; + +    if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef +        && Kind != InlineAsm::Kind_RegDefEarlyClobber) +      continue; + +    unsigned RC; +    bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC); +    if ((!IsTiedToChangedOp && (!HasRC || RC != SP::IntRegsRegClassID)) +        || NumRegs != 2) +      continue; + +    assert((i+2 < NumOps) && "Invalid number of operands in inline asm"); +    SDValue V0 = N->getOperand(i+1); +    SDValue V1 = N->getOperand(i+2); +    unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg(); +    unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg(); +    SDValue PairedReg; +    MachineRegisterInfo &MRI = MF->getRegInfo(); + +    if (Kind == InlineAsm::Kind_RegDef || +        Kind == InlineAsm::Kind_RegDefEarlyClobber) { +      // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to +      // the original GPRs. + +      unsigned GPVR = MRI.createVirtualRegister(&SP::IntPairRegClass); +      PairedReg = CurDAG->getRegister(GPVR, MVT::v2i32); +      SDValue Chain = SDValue(N,0); + +      SDNode *GU = N->getGluedUser(); +      SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::v2i32, +                                               Chain.getValue(1)); + +      // Extract values from a GPRPair reg and copy to the original GPR reg. +      SDValue Sub0 = CurDAG->getTargetExtractSubreg(SP::sub_even, dl, MVT::i32, +                                                    RegCopy); +      SDValue Sub1 = CurDAG->getTargetExtractSubreg(SP::sub_odd, dl, MVT::i32, +                                                    RegCopy); +      SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0, +                                        RegCopy.getValue(1)); +      SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1)); + +      // Update the original glue user. +      std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1); +      Ops.push_back(T1.getValue(1)); +      CurDAG->UpdateNodeOperands(GU, Ops); +    } +    else { +      // For Kind  == InlineAsm::Kind_RegUse, we first copy two GPRs into a +      // GPRPair and then pass the GPRPair to the inline asm. +      SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain]; + +      // As REG_SEQ doesn't take RegisterSDNode, we copy them first. +      SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32, +                                          Chain.getValue(1)); +      SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32, +                                          T0.getValue(1)); +      SDValue Pair = SDValue( +          CurDAG->getMachineNode( +              TargetOpcode::REG_SEQUENCE, dl, MVT::v2i32, +              { +                  CurDAG->getTargetConstant(SP::IntPairRegClassID, dl, +                                            MVT::i32), +                  T0, +                  CurDAG->getTargetConstant(SP::sub_even, dl, MVT::i32), +                  T1, +                  CurDAG->getTargetConstant(SP::sub_odd, dl, MVT::i32), +              }), +          0); + +      // Copy REG_SEQ into a GPRPair-typed VR and replace the original two +      // i32 VRs of inline asm with it. +      unsigned GPVR = MRI.createVirtualRegister(&SP::IntPairRegClass); +      PairedReg = CurDAG->getRegister(GPVR, MVT::v2i32); +      Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1)); + +      AsmNodeOperands[InlineAsm::Op_InputChain] = Chain; +      Glue = Chain.getValue(1); +    } + +    Changed = true; + +    if(PairedReg.getNode()) { +      OpChanged[OpChanged.size() -1 ] = true; +      Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/); +      if (IsTiedToChangedOp) +        Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx); +      else +        Flag = InlineAsm::getFlagWordForRegClass(Flag, SP::IntPairRegClassID); +      // Replace the current flag. +      AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant( +          Flag, dl, MVT::i32); +      // Add the new register node and skip the original two GPRs. +      AsmNodeOperands.push_back(PairedReg); +      // Skip the next two GPRs. +      i += 2; +    } +  } + +  if (Glue.getNode()) +    AsmNodeOperands.push_back(Glue); +  if (!Changed) +    return nullptr; + +  SDValue New = CurDAG->getNode(ISD::INLINEASM, SDLoc(N), +      CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands); +  New->setNodeId(-1); +  return New.getNode(); +} +  SDNode *SparcDAGToDAGISel::Select(SDNode *N) {    SDLoc dl(N);    if (N->isMachineOpcode()) { @@ -150,6 +327,12 @@ SDNode *SparcDAGToDAGISel::Select(SDNode *N) {    switch (N->getOpcode()) {    default: break; +    case ISD::INLINEASM: { +    SDNode *ResNode = SelectInlineAsm(N); +    if (ResNode) +      return ResNode; +    break; +  }    case SPISD::GLOBAL_BASE_REG:      return getGlobalBaseReg(); diff --git a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp index 4879d4ee79e5..5e70ffe2223c 100644 --- a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -49,9 +49,9 @@ static bool CC_Sparc_Assign_SRet(unsigned &ValNo, MVT &ValVT,    return true;  } -static bool CC_Sparc_Assign_f64(unsigned &ValNo, MVT &ValVT, -                                MVT &LocVT, CCValAssign::LocInfo &LocInfo, -                                ISD::ArgFlagsTy &ArgFlags, CCState &State) +static bool CC_Sparc_Assign_Split_64(unsigned &ValNo, MVT &ValVT, +                                     MVT &LocVT, CCValAssign::LocInfo &LocInfo, +                                     ISD::ArgFlagsTy &ArgFlags, CCState &State)  {    static const MCPhysReg RegList[] = {      SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5 @@ -77,6 +77,29 @@ static bool CC_Sparc_Assign_f64(unsigned &ValNo, MVT &ValVT,    return true;  } +static bool CC_Sparc_Assign_Ret_Split_64(unsigned &ValNo, MVT &ValVT, +                                         MVT &LocVT, CCValAssign::LocInfo &LocInfo, +                                         ISD::ArgFlagsTy &ArgFlags, CCState &State) +{ +  static const MCPhysReg RegList[] = { +    SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5 +  }; + +  // Try to get first reg. +  if (unsigned Reg = State.AllocateReg(RegList)) +    State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); +  else +    return false; + +  // Try to get second reg. +  if (unsigned Reg = State.AllocateReg(RegList)) +    State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); +  else +    return false; + +  return true; +} +  // Allocate a full-sized argument for the 64-bit ABI.  static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT,                              MVT &LocVT, CCValAssign::LocInfo &LocInfo, @@ -202,12 +225,34 @@ SparcTargetLowering::LowerReturn_32(SDValue Chain,    RetOps.push_back(SDValue());    // Copy the result values into the output registers. -  for (unsigned i = 0; i != RVLocs.size(); ++i) { +  for (unsigned i = 0, realRVLocIdx = 0; +       i != RVLocs.size(); +       ++i, ++realRVLocIdx) {      CCValAssign &VA = RVLocs[i];      assert(VA.isRegLoc() && "Can only return in registers!"); -    Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), -                             OutVals[i], Flag); +    SDValue Arg = OutVals[realRVLocIdx]; + +    if (VA.needsCustom()) { +      assert(VA.getLocVT() == MVT::v2i32); +      // Legalize ret v2i32 -> ret 2 x i32 (Basically: do what would +      // happen by default if this wasn't a legal type) + +      SDValue Part0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, +                                  Arg, +                                  DAG.getConstant(0, DL, getVectorIdxTy(DAG.getDataLayout()))); +      SDValue Part1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, +                                  Arg, +                                  DAG.getConstant(1, DL, getVectorIdxTy(DAG.getDataLayout()))); + +      Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Part0, Flag); +      Flag = Chain.getValue(1); +      RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); +      VA = RVLocs[++i]; // skip ahead to next loc +      Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Part1, +                               Flag); +    } else +      Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Arg, Flag);      // Guarantee that all emitted copies are stuck together with flags.      Flag = Chain.getValue(1); @@ -355,6 +400,7 @@ LowerFormalArguments_32(SDValue Chain,    CCInfo.AnalyzeFormalArguments(Ins, CC_Sparc32);    const unsigned StackOffset = 92; +  bool IsLittleEndian = DAG.getDataLayout().isLittleEndian();    unsigned InIdx = 0;    for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i, ++InIdx) { @@ -375,7 +421,8 @@ LowerFormalArguments_32(SDValue Chain,      if (VA.isRegLoc()) {        if (VA.needsCustom()) { -        assert(VA.getLocVT() == MVT::f64); +        assert(VA.getLocVT() == MVT::f64 || VA.getLocVT() == MVT::v2i32); +          unsigned VRegHi = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);          MF.getRegInfo().addLiveIn(VA.getLocReg(), VRegHi);          SDValue HiVal = DAG.getCopyFromReg(Chain, dl, VRegHi, MVT::i32); @@ -396,9 +443,13 @@ LowerFormalArguments_32(SDValue Chain,                                          &SP::IntRegsRegClass);            LoVal = DAG.getCopyFromReg(Chain, dl, loReg, MVT::i32);          } + +        if (IsLittleEndian) +          std::swap(LoVal, HiVal); +          SDValue WholeValue =            DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal); -        WholeValue = DAG.getNode(ISD::BITCAST, dl, MVT::f64, WholeValue); +        WholeValue = DAG.getNode(ISD::BITCAST, dl, VA.getLocVT(), WholeValue);          InVals.push_back(WholeValue);          continue;        } @@ -422,7 +473,7 @@ LowerFormalArguments_32(SDValue Chain,      auto PtrVT = getPointerTy(DAG.getDataLayout());      if (VA.needsCustom()) { -      assert(VA.getValVT() == MVT::f64); +      assert(VA.getValVT() == MVT::f64 || MVT::v2i32);        // If it is double-word aligned, just load.        if (Offset % 8 == 0) {          int FI = MF.getFrameInfo()->CreateFixedObject(8, @@ -452,9 +503,12 @@ LowerFormalArguments_32(SDValue Chain,                                    MachinePointerInfo(),                                    false, false, false, 0); +      if (IsLittleEndian) +        std::swap(LoVal, HiVal); +        SDValue WholeValue =          DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal); -      WholeValue = DAG.getNode(ISD::BITCAST, dl, MVT::f64, WholeValue); +      WholeValue = DAG.getNode(ISD::BITCAST, dl, VA.getValVT(), WholeValue);        InVals.push_back(WholeValue);        continue;      } @@ -468,16 +522,12 @@ LowerFormalArguments_32(SDValue Chain,        Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr,                           MachinePointerInfo(),                           false, false, false, 0); +    } else if (VA.getValVT() == MVT::f128) { +      report_fatal_error("SPARCv8 does not handle f128 in calls; " +                         "pass indirectly");      } else { -      ISD::LoadExtType LoadOp = ISD::SEXTLOAD; -      // Sparc is big endian, so add an offset based on the ObjectVT. -      unsigned Offset = 4-std::max(1U, VA.getValVT().getSizeInBits()/8); -      FIPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, FIPtr, -                          DAG.getConstant(Offset, dl, MVT::i32)); -      Load = DAG.getExtLoad(LoadOp, dl, MVT::i32, Chain, FIPtr, -                            MachinePointerInfo(), -                            VA.getValVT(), false, false, false,0); -      Load = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), Load); +      // We shouldn't see any other value types here. +      llvm_unreachable("Unexpected ValVT encountered in frame lowering.");      }      InVals.push_back(Load);    } @@ -612,7 +662,7 @@ LowerFormalArguments_64(SDValue Chain,      InVals.push_back(DAG.getLoad(          VA.getValVT(), DL, Chain,          DAG.getFrameIndex(FI, getPointerTy(MF.getDataLayout())), -        MachinePointerInfo::getFixedStack(FI), false, false, false, 0)); +        MachinePointerInfo::getFixedStack(MF, FI), false, false, false, 0));    }    if (!IsVarArg) @@ -640,9 +690,9 @@ LowerFormalArguments_64(SDValue Chain,      SDValue VArg = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i64);      int FI = MF.getFrameInfo()->CreateFixedObject(8, ArgOffset + ArgArea, true);      auto PtrVT = getPointerTy(MF.getDataLayout()); -    OutChains.push_back( -        DAG.getStore(Chain, DL, VArg, DAG.getFrameIndex(FI, PtrVT), -                     MachinePointerInfo::getFixedStack(FI), false, false, 0)); +    OutChains.push_back(DAG.getStore( +        Chain, DL, VArg, DAG.getFrameIndex(FI, PtrVT), +        MachinePointerInfo::getFixedStack(MF, FI), false, false, 0));    }    if (!OutChains.empty()) @@ -788,7 +838,7 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,      }      if (VA.needsCustom()) { -      assert(VA.getLocVT() == MVT::f64); +      assert(VA.getLocVT() == MVT::f64 || VA.getLocVT() == MVT::v2i32);        if (VA.isMemLoc()) {          unsigned Offset = VA.getLocMemOffset() + StackOffset; @@ -804,49 +854,53 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,          }        } -      SDValue StackPtr = DAG.CreateStackTemporary(MVT::f64, MVT::i32); -      SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, -                                   Arg, StackPtr, MachinePointerInfo(), -                                   false, false, 0); -      // Sparc is big-endian, so the high part comes first. -      SDValue Hi = DAG.getLoad(MVT::i32, dl, Store, StackPtr, -                               MachinePointerInfo(), false, false, false, 0); -      // Increment the pointer to the other half. -      StackPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), StackPtr, -                             DAG.getIntPtrConstant(4, dl)); -      // Load the low part. -      SDValue Lo = DAG.getLoad(MVT::i32, dl, Store, StackPtr, -                               MachinePointerInfo(), false, false, false, 0); +      if (VA.getLocVT() == MVT::f64) { +        // Move from the float value from float registers into the +        // integer registers. + +        // TODO: The f64 -> v2i32 conversion is super-inefficient for +        // constants: it sticks them in the constant pool, then loads +        // to a fp register, then stores to temp memory, then loads to +        // integer registers. +        Arg = DAG.getNode(ISD::BITCAST, dl, MVT::v2i32, Arg); +      } + +      SDValue Part0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i32, +                                  Arg, +                                  DAG.getConstant(0, dl, getVectorIdxTy(DAG.getDataLayout()))); +      SDValue Part1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i32, +                                  Arg, +                                  DAG.getConstant(1, dl, getVectorIdxTy(DAG.getDataLayout())));        if (VA.isRegLoc()) { -        RegsToPass.push_back(std::make_pair(VA.getLocReg(), Hi)); +        RegsToPass.push_back(std::make_pair(VA.getLocReg(), Part0));          assert(i+1 != e);          CCValAssign &NextVA = ArgLocs[++i];          if (NextVA.isRegLoc()) { -          RegsToPass.push_back(std::make_pair(NextVA.getLocReg(), Lo)); +          RegsToPass.push_back(std::make_pair(NextVA.getLocReg(), Part1));          } else { -          // Store the low part in stack. +          // Store the second part in stack.            unsigned Offset = NextVA.getLocMemOffset() + StackOffset;            SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);            SDValue PtrOff = DAG.getIntPtrConstant(Offset, dl);            PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); -          MemOpChains.push_back(DAG.getStore(Chain, dl, Lo, PtrOff, +          MemOpChains.push_back(DAG.getStore(Chain, dl, Part1, PtrOff,                                               MachinePointerInfo(),                                               false, false, 0));          }        } else {          unsigned Offset = VA.getLocMemOffset() + StackOffset; -        // Store the high part. +        // Store the first part.          SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);          SDValue PtrOff = DAG.getIntPtrConstant(Offset, dl);          PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); -        MemOpChains.push_back(DAG.getStore(Chain, dl, Hi, PtrOff, +        MemOpChains.push_back(DAG.getStore(Chain, dl, Part0, PtrOff,                                             MachinePointerInfo(),                                             false, false, 0)); -        // Store the low part. +        // Store the second part.          PtrOff = DAG.getIntPtrConstant(Offset + 4, dl);          PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); -        MemOpChains.push_back(DAG.getStore(Chain, dl, Lo, PtrOff, +        MemOpChains.push_back(DAG.getStore(Chain, dl, Part1, PtrOff,                                             MachinePointerInfo(),                                             false, false, 0));        } @@ -990,8 +1044,8 @@ SparcTargetLowering::getSRetArgSize(SelectionDAG &DAG, SDValue Callee) const    if (!CalleeFn)      return 0; -  assert(CalleeFn->hasStructRetAttr() && -         "Callee does not have the StructRet attribute."); +  // It would be nice to check for the sret attribute on CalleeFn here, +  // but since it is not part of the function type, any check will misfire.    PointerType *Ty = cast<PointerType>(CalleeFn->arg_begin()->getType());    Type *ElementTy = Ty->getElementType(); @@ -1370,15 +1424,60 @@ static SPCC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) {  SparcTargetLowering::SparcTargetLowering(TargetMachine &TM,                                           const SparcSubtarget &STI)      : TargetLowering(TM), Subtarget(&STI) { -  auto &DL = *TM.getDataLayout(); +  MVT PtrVT = MVT::getIntegerVT(8 * TM.getPointerSize()); + +  // Instructions which use registers as conditionals examine all the +  // bits (as does the pseudo SELECT_CC expansion). I don't think it +  // matters much whether it's ZeroOrOneBooleanContent, or +  // ZeroOrNegativeOneBooleanContent, so, arbitrarily choose the +  // former. +  setBooleanContents(ZeroOrOneBooleanContent); +  setBooleanVectorContents(ZeroOrOneBooleanContent);    // Set up the register classes.    addRegisterClass(MVT::i32, &SP::IntRegsRegClass);    addRegisterClass(MVT::f32, &SP::FPRegsRegClass);    addRegisterClass(MVT::f64, &SP::DFPRegsRegClass);    addRegisterClass(MVT::f128, &SP::QFPRegsRegClass); -  if (Subtarget->is64Bit()) +  if (Subtarget->is64Bit()) {      addRegisterClass(MVT::i64, &SP::I64RegsRegClass); +  } else { +    // On 32bit sparc, we define a double-register 32bit register +    // class, as well. This is modeled in LLVM as a 2-vector of i32. +    addRegisterClass(MVT::v2i32, &SP::IntPairRegClass); + +    // ...but almost all operations must be expanded, so set that as +    // the default. +    for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op) { +      setOperationAction(Op, MVT::v2i32, Expand); +    } +    // Truncating/extending stores/loads are also not supported. +    for (MVT VT : MVT::integer_vector_valuetypes()) { +      setLoadExtAction(ISD::SEXTLOAD, VT, MVT::v2i32, Expand); +      setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::v2i32, Expand); +      setLoadExtAction(ISD::EXTLOAD, VT, MVT::v2i32, Expand); + +      setLoadExtAction(ISD::SEXTLOAD, MVT::v2i32, VT, Expand); +      setLoadExtAction(ISD::ZEXTLOAD, MVT::v2i32, VT, Expand); +      setLoadExtAction(ISD::EXTLOAD, MVT::v2i32, VT, Expand); + +      setTruncStoreAction(VT, MVT::v2i32, Expand); +      setTruncStoreAction(MVT::v2i32, VT, Expand); +    } +    // However, load and store *are* legal. +    setOperationAction(ISD::LOAD, MVT::v2i32, Legal); +    setOperationAction(ISD::STORE, MVT::v2i32, Legal); +    setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v2i32, Legal); +    setOperationAction(ISD::BUILD_VECTOR, MVT::v2i32, Legal); + +    // And we need to promote i64 loads/stores into vector load/store +    setOperationAction(ISD::LOAD, MVT::i64, Custom); +    setOperationAction(ISD::STORE, MVT::i64, Custom); + +    // Sadly, this doesn't work: +    //    AddPromotedToType(ISD::LOAD, MVT::i64, MVT::v2i32); +    //    AddPromotedToType(ISD::STORE, MVT::i64, MVT::v2i32); +  }    // Turn FP extload into load/fextend    for (MVT VT : MVT::fp_valuetypes()) { @@ -1396,10 +1495,10 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM,    setTruncStoreAction(MVT::f128, MVT::f64, Expand);    // Custom legalize GlobalAddress nodes into LO/HI parts. -  setOperationAction(ISD::GlobalAddress, getPointerTy(DL), Custom); -  setOperationAction(ISD::GlobalTLSAddress, getPointerTy(DL), Custom); -  setOperationAction(ISD::ConstantPool, getPointerTy(DL), Custom); -  setOperationAction(ISD::BlockAddress, getPointerTy(DL), Custom); +  setOperationAction(ISD::GlobalAddress, PtrVT, Custom); +  setOperationAction(ISD::GlobalTLSAddress, PtrVT, Custom); +  setOperationAction(ISD::ConstantPool, PtrVT, Custom); +  setOperationAction(ISD::BlockAddress, PtrVT, Custom);    // Sparc doesn't have sext_inreg, replace them with shl/sra    setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand); @@ -1579,9 +1678,6 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM,    setOperationAction(ISD::STACKRESTORE      , MVT::Other, Expand);    setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32  , Custom); -  setExceptionPointerRegister(SP::I0); -  setExceptionSelectorRegister(SP::I1); -    setStackPointerRegisterToSaveRestore(SP::O6);    setOperationAction(ISD::CTPOP, MVT::i32, @@ -1744,18 +1840,15 @@ void SparcTargetLowering::computeKnownBitsForTargetNode  // set LHS/RHS and SPCC to the LHS/RHS of the setcc and SPCC to the condition.  static void LookThroughSetCC(SDValue &LHS, SDValue &RHS,                               ISD::CondCode CC, unsigned &SPCC) { -  if (isa<ConstantSDNode>(RHS) && -      cast<ConstantSDNode>(RHS)->isNullValue() && +  if (isNullConstant(RHS) &&        CC == ISD::SETNE &&        (((LHS.getOpcode() == SPISD::SELECT_ICC ||           LHS.getOpcode() == SPISD::SELECT_XCC) &&          LHS.getOperand(3).getOpcode() == SPISD::CMPICC) ||         (LHS.getOpcode() == SPISD::SELECT_FCC &&          LHS.getOperand(3).getOpcode() == SPISD::CMPFCC)) && -      isa<ConstantSDNode>(LHS.getOperand(0)) && -      isa<ConstantSDNode>(LHS.getOperand(1)) && -      cast<ConstantSDNode>(LHS.getOperand(0))->isOne() && -      cast<ConstantSDNode>(LHS.getOperand(1))->isNullValue()) { +      isOneConstant(LHS.getOperand(0)) && +      isNullConstant(LHS.getOperand(1))) {      SDValue CMPCC = LHS.getOperand(3);      SPCC = cast<ConstantSDNode>(LHS.getOperand(2))->getZExtValue();      LHS = CMPCC.getOperand(0); @@ -1821,7 +1914,8 @@ SDValue SparcTargetLowering::makeAddress(SDValue Op, SelectionDAG &DAG) const {      MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();      MFI->setHasCalls(true);      return DAG.getLoad(VT, DL, DAG.getEntryNode(), AbsAddr, -                       MachinePointerInfo::getGOT(), false, false, false, 0); +                       MachinePointerInfo::getGOT(DAG.getMachineFunction()), +                       false, false, false, 0);    }    // This is one of the absolute code models. @@ -1872,6 +1966,9 @@ SDValue SparcTargetLowering::LowerGlobalTLSAddress(SDValue Op,                                                     SelectionDAG &DAG) const {    GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op); +  if (DAG.getTarget().Options.EmulatedTLS) +    return LowerToTLSEmulatedModel(GA, DAG); +    SDLoc DL(GA);    const GlobalValue *GV = GA->getGlobal();    EVT PtrVT = getPointerTy(DAG.getDataLayout()); @@ -2601,6 +2698,17 @@ static SDValue LowerF128Load(SDValue Op, SelectionDAG &DAG)    return DAG.getMergeValues(Ops, dl);  } +static SDValue LowerLOAD(SDValue Op, SelectionDAG &DAG) +{ +  LoadSDNode *LdNode = cast<LoadSDNode>(Op.getNode()); + +  EVT MemVT = LdNode->getMemoryVT(); +  if (MemVT == MVT::f128) +    return LowerF128Load(Op, DAG); + +  return Op; +} +  // Lower a f128 store into two f64 stores.  static SDValue LowerF128Store(SDValue Op, SelectionDAG &DAG) {    SDLoc dl(Op); @@ -2645,6 +2753,29 @@ static SDValue LowerF128Store(SDValue Op, SelectionDAG &DAG) {    return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);  } +static SDValue LowerSTORE(SDValue Op, SelectionDAG &DAG) +{ +  SDLoc dl(Op); +  StoreSDNode *St = cast<StoreSDNode>(Op.getNode()); + +  EVT MemVT = St->getMemoryVT(); +  if (MemVT == MVT::f128) +    return LowerF128Store(Op, DAG); + +  if (MemVT == MVT::i64) { +    // Custom handling for i64 stores: turn it into a bitcast and a +    // v2i32 store. +    SDValue Val = DAG.getNode(ISD::BITCAST, dl, MVT::v2i32, St->getValue()); +    SDValue Chain = DAG.getStore( +        St->getChain(), dl, Val, St->getBasePtr(), St->getPointerInfo(), +        St->isVolatile(), St->isNonTemporal(), St->getAlignment(), +        St->getAAInfo()); +    return Chain; +  } + +  return SDValue(); +} +  static SDValue LowerFNEGorFABS(SDValue Op, SelectionDAG &DAG, bool isV9) {    assert((Op.getOpcode() == ISD::FNEG || Op.getOpcode() == ISD::FABS)           && "invalid opcode"); @@ -2752,7 +2883,7 @@ static SDValue LowerUMULO_SMULO(SDValue Op, SelectionDAG &DAG,    SDValue MulResult = TLI.makeLibCall(DAG,                                        RTLIB::MUL_I128, WideVT, -                                      Args, 4, isSigned, dl).first; +                                      Args, isSigned, dl).first;    SDValue BottomHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT,                                     MulResult, DAG.getIntPtrConstant(0, dl));    SDValue TopHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, @@ -2783,7 +2914,6 @@ static SDValue LowerATOMIC_LOAD_STORE(SDValue Op, SelectionDAG &DAG) {    return SDValue();  } -  SDValue SparcTargetLowering::  LowerOperation(SDValue Op, SelectionDAG &DAG) const { @@ -2818,8 +2948,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const {    case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG,                                                                 Subtarget); -  case ISD::LOAD:               return LowerF128Load(Op, DAG); -  case ISD::STORE:              return LowerF128Store(Op, DAG); +  case ISD::LOAD:               return LowerLOAD(Op, DAG); +  case ISD::STORE:              return LowerSTORE(Op, DAG);    case ISD::FADD:               return LowerF128Op(Op, DAG,                                         getLibcallName(RTLIB::ADD_F128), 2);    case ISD::FSUB:               return LowerF128Op(Op, DAG, @@ -2921,8 +3051,7 @@ SparcTargetLowering::expandSelectCC(MachineInstr *MI,    // to set, the condition code register to branch on, the true/false values to    // select between, and a branch opcode to use.    const BasicBlock *LLVM_BB = BB->getBasicBlock(); -  MachineFunction::iterator It = BB; -  ++It; +  MachineFunction::iterator It = ++BB->getIterator();    //  thisMBB:    //  ... @@ -3007,7 +3136,7 @@ SparcTargetLowering::expandAtomicRMW(MachineInstr *MI,      .addReg(AddrReg).addImm(0);    // Split the basic block MBB before MI and insert the loop block in the hole. -  MachineFunction::iterator MFI = MBB; +  MachineFunction::iterator MFI = MBB->getIterator();    const BasicBlock *LLVM_BB = MBB->getBasicBlock();    MachineFunction *MF = MBB->getParent();    MachineBasicBlock *LoopMBB = MF->CreateMachineBasicBlock(LLVM_BB); @@ -3149,9 +3278,12 @@ SparcTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,    if (Constraint.size() == 1) {      switch (Constraint[0]) {      case 'r': -      return std::make_pair(0U, &SP::IntRegsRegClass); +      if (VT == MVT::v2i32) +        return std::make_pair(0U, &SP::IntPairRegClass); +      else +        return std::make_pair(0U, &SP::IntRegsRegClass);      } -  } else  if (!Constraint.empty() && Constraint.size() <= 5 +  } else if (!Constraint.empty() && Constraint.size() <= 5                && Constraint[0] == '{' && *(Constraint.end()-1) == '}') {      // constraint = '{r<d>}'      // Remove the braces from around the name. @@ -3227,5 +3359,24 @@ void SparcTargetLowering::ReplaceNodeResults(SDNode *N,                                    getLibcallName(libCall),                                    1));      return; +  case ISD::LOAD: { +    LoadSDNode *Ld = cast<LoadSDNode>(N); +    // Custom handling only for i64: turn i64 load into a v2i32 load, +    // and a bitcast. +    if (Ld->getValueType(0) != MVT::i64 || Ld->getMemoryVT() != MVT::i64) +      return; + +    SDLoc dl(N); +    SDValue LoadRes = DAG.getExtLoad( +        Ld->getExtensionType(), dl, MVT::v2i32, +        Ld->getChain(), Ld->getBasePtr(), Ld->getPointerInfo(), +        MVT::v2i32, Ld->isVolatile(), Ld->isNonTemporal(), +        Ld->isInvariant(), Ld->getAlignment(), Ld->getAAInfo()); + +    SDValue Res = DAG.getNode(ISD::BITCAST, dl, MVT::i64, LoadRes); +    Results.push_back(Res); +    Results.push_back(LoadRes.getValue(1)); +    return; +  }    }  } diff --git a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.h b/contrib/llvm/lib/Target/Sparc/SparcISelLowering.h index bbc91a493c9d..4e46709cfc09 100644 --- a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.h +++ b/contrib/llvm/lib/Target/Sparc/SparcISelLowering.h @@ -89,6 +89,20 @@ namespace llvm {        return MVT::i32;      } +    /// If a physical register, this returns the register that receives the +    /// exception address on entry to an EH pad. +    unsigned +    getExceptionPointerRegister(const Constant *PersonalityFn) const override { +      return SP::I0; +    } + +    /// If a physical register, this returns the register that receives the +    /// exception typeid on entry to a landing pad. +    unsigned +    getExceptionSelectorRegister(const Constant *PersonalityFn) const override { +      return SP::I1; +    } +      /// getSetCCResultType - Return the ISD::SETCC ValueType      EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context,                             EVT VT) const override; @@ -167,8 +181,8 @@ namespace llvm {      }      void ReplaceNodeResults(SDNode *N, -                                    SmallVectorImpl<SDValue>& Results, -                                    SelectionDAG &DAG) const override; +                            SmallVectorImpl<SDValue>& Results, +                            SelectionDAG &DAG) const override;      MachineBasicBlock *expandSelectCC(MachineInstr *MI, MachineBasicBlock *BB,                                        unsigned BROpcode) const; diff --git a/contrib/llvm/lib/Target/Sparc/SparcInstrAliases.td b/contrib/llvm/lib/Target/Sparc/SparcInstrAliases.td index 25cc652dbd9e..d51e2ccc8a35 100644 --- a/contrib/llvm/lib/Target/Sparc/SparcInstrAliases.td +++ b/contrib/llvm/lib/Target/Sparc/SparcInstrAliases.td @@ -250,6 +250,7 @@ defm : int_cond_alias<"n",    0b0000>;  defm : int_cond_alias<"ne",   0b1001>;  defm : int_cond_alias<"nz",   0b1001>; // same as ne  defm : int_cond_alias<"e",    0b0001>; +defm : int_cond_alias<"eq",    0b0001>; // same as e  defm : int_cond_alias<"z",    0b0001>; // same as e  defm : int_cond_alias<"g",    0b1010>;  defm : int_cond_alias<"le",   0b0010>; @@ -429,6 +430,9 @@ def : InstAlias<"wr $simm13, %tbr", (WRTBRri G0, i32imm:$simm13), 0>;  def : InstAlias<"flush", (FLUSH), 0>; +def : MnemonicAlias<"lduw", "ld">, Requires<[HasV9]>; +def : MnemonicAlias<"lduwa", "lda">, Requires<[HasV9]>; +  def : MnemonicAlias<"return", "rett">, Requires<[HasV9]>;  def : MnemonicAlias<"addc", "addx">, Requires<[HasV9]>; @@ -450,3 +454,8 @@ def : InstAlias<"fcmpeq $rs1, $rs2", (V9FCMPEQ FCC0, QFPRegs:$rs1,                                                       QFPRegs:$rs2)>,                  Requires<[HasHardQuad]>; +// signx rd -> sra rd, %g0, rd +def : InstAlias<"signx $rd", (SRArr IntRegs:$rd, IntRegs:$rd, G0), 0>, Requires<[HasV9]>; + +// signx reg, rd -> sra reg, %g0, rd +def : InstAlias<"signx $rs1, $rd", (SRArr IntRegs:$rd, IntRegs:$rs1, G0), 0>, Requires<[HasV9]>; diff --git a/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.cpp b/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.cpp index 6167c532db80..733027a5d2be 100644 --- a/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.cpp +++ b/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.cpp @@ -284,7 +284,9 @@ void SparcInstrInfo::copyPhysReg(MachineBasicBlock &MBB,    unsigned numSubRegs = 0;    unsigned movOpc     = 0;    const unsigned *subRegIdx = nullptr; +  bool ExtraG0 = false; +  const unsigned DW_SubRegsIdx[]  = { SP::sub_even, SP::sub_odd };    const unsigned DFP_FP_SubRegsIdx[]  = { SP::sub_even, SP::sub_odd };    const unsigned QFP_DFP_SubRegsIdx[] = { SP::sub_even64, SP::sub_odd64 };    const unsigned QFP_FP_SubRegsIdx[]  = { SP::sub_even, SP::sub_odd, @@ -294,7 +296,12 @@ void SparcInstrInfo::copyPhysReg(MachineBasicBlock &MBB,    if (SP::IntRegsRegClass.contains(DestReg, SrcReg))      BuildMI(MBB, I, DL, get(SP::ORrr), DestReg).addReg(SP::G0)        .addReg(SrcReg, getKillRegState(KillSrc)); -  else if (SP::FPRegsRegClass.contains(DestReg, SrcReg)) +  else if (SP::IntPairRegClass.contains(DestReg, SrcReg)) { +    subRegIdx  = DW_SubRegsIdx; +    numSubRegs = 2; +    movOpc     = SP::ORrr; +    ExtraG0 = true; +  } else if (SP::FPRegsRegClass.contains(DestReg, SrcReg))      BuildMI(MBB, I, DL, get(SP::FMOVS), DestReg)        .addReg(SrcReg, getKillRegState(KillSrc));    else if (SP::DFPRegsRegClass.contains(DestReg, SrcReg)) { @@ -347,7 +354,11 @@ void SparcInstrInfo::copyPhysReg(MachineBasicBlock &MBB,      unsigned Src = TRI->getSubReg(SrcReg,  subRegIdx[i]);      assert(Dst && Src && "Bad sub-register"); -    MovMI = BuildMI(MBB, I, DL, get(movOpc), Dst).addReg(Src); +    MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(movOpc), Dst); +    if (ExtraG0) +      MIB.addReg(SP::G0); +    MIB.addReg(Src); +    MovMI = MIB.getInstr();    }    // Add implicit super-register defs and kills to the last MovMI.    MovMI->addRegisterDefined(DestReg, TRI); @@ -365,19 +376,20 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,    MachineFunction *MF = MBB.getParent();    const MachineFrameInfo &MFI = *MF->getFrameInfo(); -  MachineMemOperand *MMO = -    MF->getMachineMemOperand(MachinePointerInfo::getFixedStack(FI), -                             MachineMemOperand::MOStore, -                             MFI.getObjectSize(FI), -                             MFI.getObjectAlignment(FI)); +  MachineMemOperand *MMO = MF->getMachineMemOperand( +      MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore, +      MFI.getObjectSize(FI), MFI.getObjectAlignment(FI));    // On the order of operands here: think "[FrameIdx + 0] = SrcReg". - if (RC == &SP::I64RegsRegClass) +  if (RC == &SP::I64RegsRegClass)      BuildMI(MBB, I, DL, get(SP::STXri)).addFrameIndex(FI).addImm(0)        .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);    else if (RC == &SP::IntRegsRegClass)      BuildMI(MBB, I, DL, get(SP::STri)).addFrameIndex(FI).addImm(0)        .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO); +  else if (RC == &SP::IntPairRegClass) +    BuildMI(MBB, I, DL, get(SP::STDri)).addFrameIndex(FI).addImm(0) +      .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);    else if (RC == &SP::FPRegsRegClass)      BuildMI(MBB, I, DL, get(SP::STFri)).addFrameIndex(FI).addImm(0)        .addReg(SrcReg,  getKillRegState(isKill)).addMemOperand(MMO); @@ -403,11 +415,9 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,    MachineFunction *MF = MBB.getParent();    const MachineFrameInfo &MFI = *MF->getFrameInfo(); -  MachineMemOperand *MMO = -    MF->getMachineMemOperand(MachinePointerInfo::getFixedStack(FI), -                             MachineMemOperand::MOLoad, -                             MFI.getObjectSize(FI), -                             MFI.getObjectAlignment(FI)); +  MachineMemOperand *MMO = MF->getMachineMemOperand( +      MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad, +      MFI.getObjectSize(FI), MFI.getObjectAlignment(FI));    if (RC == &SP::I64RegsRegClass)      BuildMI(MBB, I, DL, get(SP::LDXri), DestReg).addFrameIndex(FI).addImm(0) @@ -415,6 +425,9 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,    else if (RC == &SP::IntRegsRegClass)      BuildMI(MBB, I, DL, get(SP::LDri), DestReg).addFrameIndex(FI).addImm(0)        .addMemOperand(MMO); +  else if (RC == &SP::IntPairRegClass) +    BuildMI(MBB, I, DL, get(SP::LDDri), DestReg).addFrameIndex(FI).addImm(0) +      .addMemOperand(MMO);    else if (RC == &SP::FPRegsRegClass)      BuildMI(MBB, I, DL, get(SP::LDFri), DestReg).addFrameIndex(FI).addImm(0)        .addMemOperand(MMO); diff --git a/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td b/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td index 3b9e048ea8b3..ec37c22a5b33 100644 --- a/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td +++ b/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td @@ -283,17 +283,32 @@ multiclass Load<string OpcStr, bits<6> Op3Val, SDPatternOperator OpNode,                   [(set Ty:$dst, (OpNode ADDRri:$addr))]>;  } +// TODO: Instructions of the LoadASI class are currently asm only; hooking up +// CodeGen's address spaces to use these is a future task. +class LoadASI<string OpcStr, bits<6> Op3Val, SDPatternOperator OpNode, +              RegisterClass RC, ValueType Ty> : +  F3_1_asi<3, Op3Val, (outs RC:$dst), (ins MEMrr:$addr, i8imm:$asi), +                !strconcat(OpcStr, "a [$addr] $asi, $dst"), +                []>; +  // LoadA multiclass - As above, but also define alternate address space variant  multiclass LoadA<string OpcStr, bits<6> Op3Val, bits<6> LoadAOp3Val,                   SDPatternOperator OpNode, RegisterClass RC, ValueType Ty> :               Load<OpcStr, Op3Val, OpNode, RC, Ty> { -  // TODO: The LD*Arr instructions are currently asm only; hooking up -  // CodeGen's address spaces to use these is a future task. -  def Arr  : F3_1_asi<3, LoadAOp3Val, (outs RC:$dst), (ins MEMrr:$addr, i8imm:$asi), -                !strconcat(OpcStr, "a [$addr] $asi, $dst"), -                []>; +  def Arr  : LoadASI<OpcStr, LoadAOp3Val, OpNode, RC, Ty>;  } +// The LDSTUB instruction is supported for asm only. +// It is unlikely that general-purpose code could make use of it. +// CAS is preferred for sparc v9. +def LDSTUBrr : F3_1<3, 0b001101, (outs IntRegs:$dst), (ins MEMrr:$addr), +                  "ldstub [$addr], $dst", []>; +def LDSTUBri : F3_2<3, 0b001101, (outs IntRegs:$dst), (ins MEMri:$addr), +                  "ldstub [$addr], $dst", []>; +def LDSTUBArr : F3_1_asi<3, 0b011101, (outs IntRegs:$dst), +                         (ins MEMrr:$addr, i8imm:$asi), +                         "ldstuba [$addr] $asi, $dst", []>; +  // Store multiclass - Define both Reg+Reg/Reg+Imm patterns in one shot.  multiclass Store<string OpcStr, bits<6> Op3Val, SDPatternOperator OpNode,             RegisterClass RC, ValueType Ty> { @@ -307,14 +322,18 @@ multiclass Store<string OpcStr, bits<6> Op3Val, SDPatternOperator OpNode,                   [(OpNode Ty:$rd, ADDRri:$addr)]>;  } -multiclass StoreA<string OpcStr, bits<6> Op3Val, bits<6> StoreAOp3Val, +// TODO: Instructions of the StoreASI class are currently asm only; hooking up +// CodeGen's address spaces to use these is a future task. +class StoreASI<string OpcStr, bits<6> Op3Val,                    SDPatternOperator OpNode, RegisterClass RC, ValueType Ty> : -             Store<OpcStr, Op3Val, OpNode, RC, Ty> { -  // TODO: The ST*Arr instructions are currently asm only; hooking up -  // CodeGen's address spaces to use these is a future task. -  def Arr  : F3_1_asi<3, StoreAOp3Val, (outs), (ins MEMrr:$addr, RC:$rd, i8imm:$asi), +  F3_1_asi<3, Op3Val, (outs), (ins MEMrr:$addr, RC:$rd, i8imm:$asi),                    !strconcat(OpcStr, "a $rd, [$addr] $asi"),                    []>; + +multiclass StoreA<string OpcStr, bits<6> Op3Val, bits<6> StoreAOp3Val, +                  SDPatternOperator OpNode, RegisterClass RC, ValueType Ty> : +             Store<OpcStr, Op3Val, OpNode, RC, Ty> { +  def Arr : StoreASI<OpcStr, StoreAOp3Val, OpNode, RC, Ty>;  }  //===----------------------------------------------------------------------===// @@ -408,15 +427,40 @@ let DecoderMethod = "DecodeLoadInt" in {    defm LD   : LoadA<"ld",   0b000000, 0b010000, load,        IntRegs, i32>;  } +let DecoderMethod = "DecodeLoadIntPair" in +  defm LDD : LoadA<"ldd", 0b000011, 0b010011, load, IntPair, v2i32>; +  // Section B.2 - Load Floating-point Instructions, p. 92 -let DecoderMethod = "DecodeLoadFP" in -  defm LDF   : Load<"ld",  0b100000, load, FPRegs,  f32>; -let DecoderMethod = "DecodeLoadDFP" in -  defm LDDF  : Load<"ldd", 0b100011, load, DFPRegs, f64>; +let DecoderMethod = "DecodeLoadFP" in { +  defm LDF   : Load<"ld",  0b100000, load,    FPRegs,  f32>; +  def LDFArr : LoadASI<"ld",  0b110000, load, FPRegs,  f32>, +                Requires<[HasV9]>; +} +let DecoderMethod = "DecodeLoadDFP" in { +  defm LDDF   : Load<"ldd", 0b100011, load,    DFPRegs, f64>; +  def LDDFArr : LoadASI<"ldd", 0b110011, load, DFPRegs, f64>, +                 Requires<[HasV9]>; +}  let DecoderMethod = "DecodeLoadQFP" in -  defm LDQF  : Load<"ldq", 0b100010, load, QFPRegs, f128>, +  defm LDQF  : LoadA<"ldq", 0b100010, 0b110010, load, QFPRegs, f128>,                 Requires<[HasV9, HasHardQuad]>; +let DecoderMethod = "DecodeLoadFP" in +  let Defs = [FSR] in { +    let rd = 0 in { +      def LDFSRrr : F3_1<3, 0b100001, (outs), (ins MEMrr:$addr), +                     "ld [$addr], %fsr", []>; +      def LDFSRri : F3_2<3, 0b100001, (outs), (ins MEMri:$addr), +                     "ld [$addr], %fsr", []>; +    } +    let rd = 1 in { +      def LDXFSRrr : F3_1<3, 0b100001, (outs), (ins MEMrr:$addr), +                     "ldx [$addr], %fsr", []>, Requires<[HasV9]>; +      def LDXFSRri : F3_2<3, 0b100001, (outs), (ins MEMri:$addr), +                     "ldx [$addr], %fsr", []>, Requires<[HasV9]>; +    } +  } +  // Section B.4 - Store Integer Instructions, p. 95  let DecoderMethod = "DecodeStoreInt" in {    defm STB   : StoreA<"stb", 0b000101, 0b010101, truncstorei8,  IntRegs, i32>; @@ -424,15 +468,40 @@ let DecoderMethod = "DecodeStoreInt" in {    defm ST    : StoreA<"st",  0b000100, 0b010100, store,         IntRegs, i32>;  } +let DecoderMethod = "DecodeStoreIntPair" in +  defm STD   : StoreA<"std", 0b000111, 0b010111, store, IntPair, v2i32>; +  // Section B.5 - Store Floating-point Instructions, p. 97 -let DecoderMethod = "DecodeStoreFP" in +let DecoderMethod = "DecodeStoreFP" in {    defm STF   : Store<"st",  0b100100, store,         FPRegs,  f32>; -let DecoderMethod = "DecodeStoreDFP" in -  defm STDF  : Store<"std", 0b100111, store,         DFPRegs, f64>; +  def STFArr : StoreASI<"st",  0b110100, store,      FPRegs,  f32>, +               Requires<[HasV9]>; +} +let DecoderMethod = "DecodeStoreDFP" in { +  defm STDF   : Store<"std", 0b100111, store,         DFPRegs, f64>; +  def STDFArr : StoreASI<"std", 0b110111, store,      DFPRegs, f64>, +                Requires<[HasV9]>; +}  let DecoderMethod = "DecodeStoreQFP" in -  defm STQF  : Store<"stq", 0b100110, store,         QFPRegs, f128>, +  defm STQF  : StoreA<"stq", 0b100110, 0b110110, store, QFPRegs, f128>,                 Requires<[HasV9, HasHardQuad]>; +let DecoderMethod = "DecodeStoreFP" in +  let Defs = [FSR] in { +    let rd = 0 in { +      def STFSRrr : F3_1<3, 0b100101, (outs MEMrr:$addr), (ins), +                     "st %fsr, [$addr]", []>; +      def STFSRri : F3_2<3, 0b100101, (outs MEMri:$addr), (ins), +                     "st %fsr, [$addr]", []>; +    } +    let rd = 1 in { +      def STXFSRrr : F3_1<3, 0b100101, (outs MEMrr:$addr), (ins), +                     "stx %fsr, [$addr]", []>, Requires<[HasV9]>; +      def STXFSRri : F3_2<3, 0b100101, (outs MEMri:$addr), (ins), +                     "stx %fsr, [$addr]", []>, Requires<[HasV9]>; +    } +  } +  // Section B.8 - SWAP Register with Memory Instruction  // (Atomic swap)  let Constraints = "$val = $dst", DecoderMethod = "DecodeSWAP" in { @@ -559,6 +628,10 @@ let Defs = [Y, ICC] in {    defm SMULCC : F3_12np<"smulcc", 0b011011>;  } +let Defs = [Y, ICC], Uses = [Y, ICC] in { +  defm MULSCC : F3_12np<"mulscc", 0b100100>; +} +  // Section B.19 - Divide Instructions, p. 115  let Uses = [Y], Defs = [Y] in {    defm UDIV : F3_12np<"udiv", 0b001110>; @@ -1221,8 +1294,8 @@ let Predicates = [HasV9] in {  // the top 32-bits before using it.  To do this clearing, we use a SRLri X,0.  let rs1 = 0 in    def POPCrr : F3_1<2, 0b101110, -                    (outs IntRegs:$dst), (ins IntRegs:$src), -                    "popc $src, $dst", []>, Requires<[HasV9]>; +                    (outs IntRegs:$rd), (ins IntRegs:$rs2), +                    "popc $rs2, $rd", []>, Requires<[HasV9]>;  def : Pat<(ctpop i32:$src),            (POPCrr (SRLri $src, 0))>; @@ -1254,6 +1327,25 @@ let hasSideEffects = 1 in {  }  } + +// Section A.43 - Read Privileged Register Instructions +let Predicates = [HasV9] in { +let rs2 = 0 in +  def RDPR : F3_1<2, 0b101010, +                 (outs IntRegs:$rd), (ins PRRegs:$rs1), +                 "rdpr $rs1, $rd", []>; +} + +// Section A.62 - Write Privileged Register Instructions +let Predicates = [HasV9] in { +  def WRPRrr : F3_1<2, 0b110010, +                   (outs PRRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2), +                   "wrpr $rs1, $rs2, $rd", []>; +  def WRPRri : F3_2<2, 0b110010, +                   (outs PRRegs:$rd), (ins IntRegs:$rs1, simm13Op:$simm13), +                   "wrpr $rs1, $simm13, $rd", []>; +} +  //===----------------------------------------------------------------------===//  // Non-Instruction Patterns  //===----------------------------------------------------------------------===// @@ -1327,6 +1419,18 @@ def : Pat<(i32 (atomic_load ADDRri:$src)), (LDri ADDRri:$src)>;  def : Pat<(atomic_store ADDRrr:$dst, i32:$val), (STrr ADDRrr:$dst, $val)>;  def : Pat<(atomic_store ADDRri:$dst, i32:$val), (STri ADDRri:$dst, $val)>; +// extract_vector +def : Pat<(extractelt (v2i32 IntPair:$Rn), 0), +          (i32 (EXTRACT_SUBREG IntPair:$Rn, sub_even))>; +def : Pat<(extractelt (v2i32 IntPair:$Rn), 1), +          (i32 (EXTRACT_SUBREG IntPair:$Rn, sub_odd))>; + +// build_vector +def : Pat<(build_vector (i32 IntRegs:$a1), (i32 IntRegs:$a2)), +          (INSERT_SUBREG +	    (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)), (i32 IntRegs:$a1), sub_even), +            (i32 IntRegs:$a2), sub_odd)>; +  include "SparcInstr64Bit.td"  include "SparcInstrVIS.td" diff --git a/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp b/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp index 9667bc059f18..da31783ba248 100644 --- a/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp +++ b/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp @@ -75,6 +75,18 @@ BitVector SparcRegisterInfo::getReservedRegs(const MachineFunction &MF) const {    Reserved.set(SP::G6);    Reserved.set(SP::G7); +  // Also reserve the register pair aliases covering the above +  // registers, with the same conditions. +  Reserved.set(SP::G0_G1); +  if (ReserveAppRegisters) +    Reserved.set(SP::G2_G3); +  if (ReserveAppRegisters || !Subtarget.is64Bit()) +    Reserved.set(SP::G4_G5); + +  Reserved.set(SP::O6_O7); +  Reserved.set(SP::I6_I7); +  Reserved.set(SP::G6_G7); +    // Unaliased double registers are not available in non-V9 targets.    if (!Subtarget.isV9()) {      for (unsigned n = 0; n != 16; ++n) { @@ -158,21 +170,15 @@ SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,    MachineInstr &MI = *II;    DebugLoc dl = MI.getDebugLoc();    int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); - -  // Addressable stack objects are accessed using neg. offsets from %fp    MachineFunction &MF = *MI.getParent()->getParent();    const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>(); -  int64_t Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) + -                   MI.getOperand(FIOperandNum + 1).getImm() + -                   Subtarget.getStackPointerBias(); -  SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); -  unsigned FramePtr = SP::I6; -  if (FuncInfo->isLeafProc()) { -    // Use %sp and adjust offset if needed. -    FramePtr = SP::O6; -    int stackSize = MF.getFrameInfo()->getStackSize(); -    Offset += (stackSize) ? Subtarget.getAdjustedFrameSize(stackSize) : 0 ; -  } +  const SparcFrameLowering *TFI = getFrameLowering(MF); + +  unsigned FrameReg; +  int Offset; +  Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg); + +  Offset += MI.getOperand(FIOperandNum + 1).getImm();    if (!Subtarget.isV9() || !Subtarget.hasHardQuad()) {      if (MI.getOpcode() == SP::STQFri) { @@ -182,8 +188,8 @@ SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,        unsigned SrcOddReg  = getSubReg(SrcReg, SP::sub_odd64);        MachineInstr *StMI =          BuildMI(*MI.getParent(), II, dl, TII.get(SP::STDFri)) -        .addReg(FramePtr).addImm(0).addReg(SrcEvenReg); -      replaceFI(MF, II, *StMI, dl, 0, Offset, FramePtr); +        .addReg(FrameReg).addImm(0).addReg(SrcEvenReg); +      replaceFI(MF, II, *StMI, dl, 0, Offset, FrameReg);        MI.setDesc(TII.get(SP::STDFri));        MI.getOperand(2).setReg(SrcOddReg);        Offset += 8; @@ -194,8 +200,8 @@ SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,        unsigned DestOddReg  = getSubReg(DestReg, SP::sub_odd64);        MachineInstr *StMI =          BuildMI(*MI.getParent(), II, dl, TII.get(SP::LDDFri), DestEvenReg) -        .addReg(FramePtr).addImm(0); -      replaceFI(MF, II, *StMI, dl, 1, Offset, FramePtr); +        .addReg(FrameReg).addImm(0); +      replaceFI(MF, II, *StMI, dl, 1, Offset, FrameReg);        MI.setDesc(TII.get(SP::LDDFri));        MI.getOperand(0).setReg(DestOddReg); @@ -203,7 +209,7 @@ SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,      }    } -  replaceFI(MF, II, MI, dl, FIOperandNum, Offset, FramePtr); +  replaceFI(MF, II, MI, dl, FIOperandNum, Offset, FrameReg);  } @@ -211,3 +217,25 @@ unsigned SparcRegisterInfo::getFrameRegister(const MachineFunction &MF) const {    return SP::I6;  } +// Sparc has no architectural need for stack realignment support, +// except that LLVM unfortunately currently implements overaligned +// stack objects by depending upon stack realignment support. +// If that ever changes, this can probably be deleted. +bool SparcRegisterInfo::canRealignStack(const MachineFunction &MF) const { +  if (!TargetRegisterInfo::canRealignStack(MF)) +    return false; + +  // Sparc always has a fixed frame pointer register, so don't need to +  // worry about needing to reserve it. [even if we don't have a frame +  // pointer for our frame, it still cannot be used for other things, +  // or register window traps will be SADNESS.] + +  // If there's a reserved call frame, we can use SP to access locals. +  if (getFrameLowering(MF)->hasReservedCallFrame(MF)) +    return true; + +  // Otherwise, we'd need a base pointer, but those aren't implemented +  // for SPARC at the moment. + +  return false; +} diff --git a/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.h b/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.h index 764a894fe9a3..32075b1df410 100644 --- a/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.h +++ b/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.h @@ -42,8 +42,10 @@ struct SparcRegisterInfo : public SparcGenRegisterInfo {    void processFunctionBeforeFrameFinalized(MachineFunction &MF,                                         RegScavenger *RS = nullptr) const; -  // Debug information queries.    unsigned getFrameRegister(const MachineFunction &MF) const override; + +  bool canRealignStack(const MachineFunction &MF) const override; +  };  } // end namespace llvm diff --git a/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.td b/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.td index db8a7e86962d..cca9463562a4 100644 --- a/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.td +++ b/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.td @@ -32,6 +32,12 @@ def sub_odd64  : SubRegIndex<64, 64>;  // Ri - 32-bit integer registers  class Ri<bits<16> Enc, string n> : SparcReg<Enc, n>; +// Rdi - pairs of 32-bit integer registers +class Rdi<bits<16> Enc, string n, list<Register> subregs> : SparcReg<Enc, n> { +  let SubRegs = subregs; +  let SubRegIndices = [sub_even, sub_odd]; +  let CoveredBySubRegs = 1; +}  // Rf - 32-bit floating-point registers  class Rf<bits<16> Enc, string n> : SparcReg<Enc, n>; @@ -54,6 +60,8 @@ def ICC : SparcCtrlReg<0, "ICC">; // This represents icc and xcc in 64-bit code.  foreach I = 0-3 in    def FCC#I : SparcCtrlReg<I, "FCC"#I>; +def FSR : SparcCtrlReg<0, "FSR">; // Floating-point state register. +  // Y register  def Y : SparcCtrlReg<0, "Y">, DwarfRegNum<[64]>;  // Ancillary state registers (implementation defined) @@ -94,6 +102,22 @@ def PSR : SparcCtrlReg<0, "PSR">;  def WIM : SparcCtrlReg<0, "WIM">;  def TBR : SparcCtrlReg<0, "TBR">; +def TPC : SparcCtrlReg<0, "TPC">; +def TNPC : SparcCtrlReg<1, "TNPC">; +def TSTATE : SparcCtrlReg<2, "TSTATE">; +def TT : SparcCtrlReg<3, "TT">; +def TICK : SparcCtrlReg<4, "TICK">; +def TBA : SparcCtrlReg<5, "TBA">; +def PSTATE : SparcCtrlReg<6, "PSTATE">; +def TL : SparcCtrlReg<7, "TL">; +def PIL : SparcCtrlReg<8, "PIL">; +def CWP : SparcCtrlReg<9, "CWP">; +def CANSAVE : SparcCtrlReg<10, "CANSAVE">; +def CANRESTORE : SparcCtrlReg<11, "CANRESTORE">; +def CLEANWIN : SparcCtrlReg<12, "CLEANWIN">; +def OTHERWIN : SparcCtrlReg<13, "OTHERWIN">; +def WSTATE : SparcCtrlReg<14, "WSTATE">; +  // Integer registers  def G0 : Ri< 0, "G0">, DwarfRegNum<[0]>;  def G1 : Ri< 1, "G1">, DwarfRegNum<[1]>; @@ -217,6 +241,24 @@ def Q13 : Rq<21, "F52", [D26, D27]>;  def Q14 : Rq<25, "F56", [D28, D29]>;  def Q15 : Rq<29, "F60", [D30, D31]>; +// Aliases of the integer registers used for LDD/STD double-word operations +def G0_G1 : Rdi<0, "G0", [G0, G1]>; +def G2_G3 : Rdi<2, "G2", [G2, G3]>; +def G4_G5 : Rdi<4, "G4", [G4, G5]>; +def G6_G7 : Rdi<6, "G6", [G6, G7]>; +def O0_O1 : Rdi<8, "O0", [O0, O1]>; +def O2_O3 : Rdi<10, "O2", [O2, O3]>; +def O4_O5 : Rdi<12, "O4", [O4, O5]>; +def O6_O7 : Rdi<14, "O6", [O6, O7]>; +def L0_L1 : Rdi<16, "L0", [L0, L1]>; +def L2_L3 : Rdi<18, "L2", [L2, L3]>; +def L4_L5 : Rdi<20, "L4", [L4, L5]>; +def L6_L7 : Rdi<22, "L6", [L6, L7]>; +def I0_I1 : Rdi<24, "I0", [I0, I1]>; +def I2_I3 : Rdi<26, "I2", [I2, I3]>; +def I4_I5 : Rdi<28, "I4", [I4, I5]>; +def I6_I7 : Rdi<30, "I6", [I6, I7]>; +  // Register classes.  //  // FIXME: the register order should be defined in terms of the preferred @@ -231,6 +273,13 @@ def IntRegs : RegisterClass<"SP", [i32, i64], 32,                                   (sequence "L%u", 0, 7),                                   (sequence "O%u", 0, 7))>; +// Should be in the same order as IntRegs. +def IntPair : RegisterClass<"SP", [v2i32], 64, +    (add I0_I1, I2_I3, I4_I5, I6_I7, +         G0_G1, G2_G3, G4_G5, G6_G7, +         L0_L1, L2_L3, L4_L5, L6_L7, +         O0_O1, O2_O3, O4_O5, O6_O7)>; +  // Register class for 64-bit mode, with a 64-bit spill slot size.  // These are the same as the 32-bit registers, so TableGen will consider this  // to be a sub-class of IntRegs. That works out because requiring a 64-bit @@ -252,3 +301,8 @@ def ASRRegs : RegisterClass<"SP", [i32], 32,                              (add Y, (sequence "ASR%u", 1, 31))> {    let isAllocatable = 0;  } + +// Privileged Registers +def PRRegs : RegisterClass<"SP", [i64], 64, +    (add TPC, TNPC, TSTATE, TT, TICK, TBA, PSTATE, TL, PIL, CWP, +         CANSAVE, CANRESTORE, CLEANWIN, OTHERWIN, WSTATE)>; diff --git a/contrib/llvm/lib/Target/Sparc/SparcSubtarget.cpp b/contrib/llvm/lib/Target/Sparc/SparcSubtarget.cpp index d69da409e428..d701594d27af 100644 --- a/contrib/llvm/lib/Target/Sparc/SparcSubtarget.cpp +++ b/contrib/llvm/lib/Target/Sparc/SparcSubtarget.cpp @@ -64,7 +64,7 @@ int SparcSubtarget::getAdjustedFrameSize(int frameSize) const {      frameSize += 128;      // Frames with calls must also reserve space for 6 outgoing arguments      // whether they are used or not. LowerCall_64 takes care of that. -    assert(frameSize % 16 == 0 && "Stack size not 16-byte aligned"); +    frameSize = RoundUpToAlignment(frameSize, 16);    } else {      // Emit the correct save instruction based on the number of bytes in      // the frame. Minimum stack frame size according to V8 ABI is: @@ -81,3 +81,7 @@ int SparcSubtarget::getAdjustedFrameSize(int frameSize) const {    }    return frameSize;  } + +bool SparcSubtarget::enableMachineScheduler() const { +  return true; +} diff --git a/contrib/llvm/lib/Target/Sparc/SparcSubtarget.h b/contrib/llvm/lib/Target/Sparc/SparcSubtarget.h index 9d21911d88f0..e2fd2f04528a 100644 --- a/contrib/llvm/lib/Target/Sparc/SparcSubtarget.h +++ b/contrib/llvm/lib/Target/Sparc/SparcSubtarget.h @@ -60,6 +60,8 @@ public:      return &TSInfo;    } +  bool enableMachineScheduler() const override; +    bool isV9() const { return IsV9; }    bool isVIS() const { return IsVIS; }    bool isVIS2() const { return IsVIS2; } @@ -85,7 +87,6 @@ public:    /// returns adjusted framesize which includes space for register window    /// spills and arguments.    int getAdjustedFrameSize(int stackSize) const; -  };  } // end namespace llvm | 
