diff options
Diffstat (limited to 'lib/Target')
391 files changed, 11039 insertions, 7315 deletions
diff --git a/lib/Target/ARM/ARM.h b/lib/Target/ARM/ARM.h index 4679f7443bfc..08dc340f8541 100644 --- a/lib/Target/ARM/ARM.h +++ b/lib/Target/ARM/ARM.h @@ -16,24 +16,29 @@ #define TARGET_ARM_H #include "ARMBaseInfo.h" +#include "MCTargetDesc/ARMMCTargetDesc.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Target/TargetMachine.h" #include <cassert> namespace llvm { +class ARMAsmPrinter; class ARMBaseTargetMachine; class FunctionPass; class JITCodeEmitter; -class formatted_raw_ostream; -class MCCodeEmitter; -class TargetAsmBackend; class MachineInstr; -class ARMAsmPrinter; +class MCCodeEmitter; class MCInst; +class MCInstrInfo; +class MCObjectWriter; +class MCSubtargetInfo; +class TargetAsmBackend; +class formatted_raw_ostream; -MCCodeEmitter *createARMMCCodeEmitter(const Target &, - TargetMachine &TM, +MCCodeEmitter *createARMMCCodeEmitter(const MCInstrInfo &MCII, + const MCSubtargetInfo &STI, MCContext &Ctx); TargetAsmBackend *createARMAsmBackend(const Target &, const std::string &); @@ -53,11 +58,15 @@ FunctionPass *createMLxExpansionPass(); FunctionPass *createThumb2ITBlockPass(); FunctionPass *createThumb2SizeReductionPass(); -extern Target TheARMTarget, TheThumbTarget; - void LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, ARMAsmPrinter &AP); +/// createARMMachObjectWriter - Construct an ARM Mach-O object writer. +MCObjectWriter *createARMMachObjectWriter(raw_ostream &OS, + bool Is64Bit, + uint32_t CPUType, + uint32_t CPUSubtype); + } // end namespace llvm; #endif diff --git a/lib/Target/ARM/ARM.td b/lib/Target/ARM/ARM.td index 6af5f85e8a85..cf333ccd49ba 100644 --- a/lib/Target/ARM/ARM.td +++ b/lib/Target/ARM/ARM.td @@ -16,18 +16,26 @@ include "llvm/Target/Target.td" +//===----------------------------------------------------------------------===// +// ARM Subtarget state. +// + +def ModeThumb : SubtargetFeature<"thumb-mode", "InThumbMode", "true", + "Thumb mode">; //===----------------------------------------------------------------------===// // ARM Subtarget features. // -def FeatureVFP2 : SubtargetFeature<"vfp2", "ARMFPUType", "VFPv2", +def FeatureVFP2 : SubtargetFeature<"vfp2", "HasVFPv2", "true", "Enable VFP2 instructions">; -def FeatureVFP3 : SubtargetFeature<"vfp3", "ARMFPUType", "VFPv3", - "Enable VFP3 instructions">; -def FeatureNEON : SubtargetFeature<"neon", "ARMFPUType", "NEON", - "Enable NEON instructions">; -def FeatureThumb2 : SubtargetFeature<"thumb2", "ThumbMode", "Thumb2", +def FeatureVFP3 : SubtargetFeature<"vfp3", "HasVFPv3", "true", + "Enable VFP3 instructions", + [FeatureVFP2]>; +def FeatureNEON : SubtargetFeature<"neon", "HasNEON", "true", + "Enable NEON instructions", + [FeatureVFP3]>; +def FeatureThumb2 : SubtargetFeature<"thumb2", "HasThumb2", "true", "Enable Thumb2 instructions">; def FeatureNoARM : SubtargetFeature<"noarm", "NoARM", "true", "Does not support ARM mode execution">; @@ -75,32 +83,32 @@ def FeatureAvoidPartialCPSR : SubtargetFeature<"avoid-partial-cpsr", "AvoidCPSRPartialUpdate", "true", "Avoid CPSR partial update for OOO execution">; +/// Some M architectures don't have the DSP extension (v7E-M vs. v7M) +def FeatureDSPThumb2 : SubtargetFeature<"t2dsp", "Thumb2DSP", "true", + "Supports v7 DSP instructions in Thumb2.">; + // Multiprocessing extension. def FeatureMP : SubtargetFeature<"mp", "HasMPExtension", "true", "Supports Multiprocessing extension">; -// ARM architectures. -def ArchV4T : SubtargetFeature<"v4t", "ARMArchVersion", "V4T", - "ARM v4T">; -def ArchV5T : SubtargetFeature<"v5t", "ARMArchVersion", "V5T", - "ARM v5T">; -def ArchV5TE : SubtargetFeature<"v5te", "ARMArchVersion", "V5TE", - "ARM v5TE, v5TEj, v5TExp">; -def ArchV6 : SubtargetFeature<"v6", "ARMArchVersion", "V6", - "ARM v6">; -def ArchV6M : SubtargetFeature<"v6m", "ARMArchVersion", "V6M", - "ARM v6m", - [FeatureNoARM, FeatureDB]>; -def ArchV6T2 : SubtargetFeature<"v6t2", "ARMArchVersion", "V6T2", - "ARM v6t2", - [FeatureThumb2]>; -def ArchV7A : SubtargetFeature<"v7a", "ARMArchVersion", "V7A", - "ARM v7A", - [FeatureThumb2, FeatureNEON, FeatureDB]>; -def ArchV7M : SubtargetFeature<"v7m", "ARMArchVersion", "V7M", - "ARM v7M", - [FeatureThumb2, FeatureNoARM, FeatureDB, - FeatureHWDiv]>; +// ARM ISAs. +def HasV4TOps : SubtargetFeature<"v4t", "HasV4TOps", "true", + "Support ARM v4T instructions">; +def HasV5TOps : SubtargetFeature<"v5t", "HasV5TOps", "true", + "Support ARM v5T instructions", + [HasV4TOps]>; +def HasV5TEOps : SubtargetFeature<"v5te", "HasV5TEOps", "true", + "Support ARM v5TE, v5TEj, and v5TExp instructions", + [HasV5TOps]>; +def HasV6Ops : SubtargetFeature<"v6", "HasV6Ops", "true", + "Support ARM v6 instructions", + [HasV5TEOps]>; +def HasV6T2Ops : SubtargetFeature<"v6t2", "HasV6T2Ops", "true", + "Support ARM v6t2 instructions", + [HasV6Ops, FeatureThumb2, FeatureDSPThumb2]>; +def HasV7Ops : SubtargetFeature<"v7", "HasV7Ops", "true", + "Support ARM v7 instructions", + [HasV6T2Ops]>; //===----------------------------------------------------------------------===// // ARM Processors supported. @@ -109,8 +117,6 @@ def ArchV7M : SubtargetFeature<"v7m", "ARMArchVersion", "V7M", include "ARMSchedule.td" // ARM processor families. -def ProcOthers : SubtargetFeature<"others", "ARMProcFamily", "Others", - "One of the other ARM processor families">; def ProcA8 : SubtargetFeature<"a8", "ARMProcFamily", "CortexA8", "Cortex-A8 ARM processors", [FeatureSlowFPBrcc, FeatureNEONForFP, @@ -135,64 +141,76 @@ def : ProcNoItin<"strongarm1100", []>; def : ProcNoItin<"strongarm1110", []>; // V4T Processors. -def : ProcNoItin<"arm7tdmi", [ArchV4T]>; -def : ProcNoItin<"arm7tdmi-s", [ArchV4T]>; -def : ProcNoItin<"arm710t", [ArchV4T]>; -def : ProcNoItin<"arm720t", [ArchV4T]>; -def : ProcNoItin<"arm9", [ArchV4T]>; -def : ProcNoItin<"arm9tdmi", [ArchV4T]>; -def : ProcNoItin<"arm920", [ArchV4T]>; -def : ProcNoItin<"arm920t", [ArchV4T]>; -def : ProcNoItin<"arm922t", [ArchV4T]>; -def : ProcNoItin<"arm940t", [ArchV4T]>; -def : ProcNoItin<"ep9312", [ArchV4T]>; +def : ProcNoItin<"arm7tdmi", [HasV4TOps]>; +def : ProcNoItin<"arm7tdmi-s", [HasV4TOps]>; +def : ProcNoItin<"arm710t", [HasV4TOps]>; +def : ProcNoItin<"arm720t", [HasV4TOps]>; +def : ProcNoItin<"arm9", [HasV4TOps]>; +def : ProcNoItin<"arm9tdmi", [HasV4TOps]>; +def : ProcNoItin<"arm920", [HasV4TOps]>; +def : ProcNoItin<"arm920t", [HasV4TOps]>; +def : ProcNoItin<"arm922t", [HasV4TOps]>; +def : ProcNoItin<"arm940t", [HasV4TOps]>; +def : ProcNoItin<"ep9312", [HasV4TOps]>; // V5T Processors. -def : ProcNoItin<"arm10tdmi", [ArchV5T]>; -def : ProcNoItin<"arm1020t", [ArchV5T]>; +def : ProcNoItin<"arm10tdmi", [HasV5TOps]>; +def : ProcNoItin<"arm1020t", [HasV5TOps]>; // V5TE Processors. -def : ProcNoItin<"arm9e", [ArchV5TE]>; -def : ProcNoItin<"arm926ej-s", [ArchV5TE]>; -def : ProcNoItin<"arm946e-s", [ArchV5TE]>; -def : ProcNoItin<"arm966e-s", [ArchV5TE]>; -def : ProcNoItin<"arm968e-s", [ArchV5TE]>; -def : ProcNoItin<"arm10e", [ArchV5TE]>; -def : ProcNoItin<"arm1020e", [ArchV5TE]>; -def : ProcNoItin<"arm1022e", [ArchV5TE]>; -def : ProcNoItin<"xscale", [ArchV5TE]>; -def : ProcNoItin<"iwmmxt", [ArchV5TE]>; +def : ProcNoItin<"arm9e", [HasV5TEOps]>; +def : ProcNoItin<"arm926ej-s", [HasV5TEOps]>; +def : ProcNoItin<"arm946e-s", [HasV5TEOps]>; +def : ProcNoItin<"arm966e-s", [HasV5TEOps]>; +def : ProcNoItin<"arm968e-s", [HasV5TEOps]>; +def : ProcNoItin<"arm10e", [HasV5TEOps]>; +def : ProcNoItin<"arm1020e", [HasV5TEOps]>; +def : ProcNoItin<"arm1022e", [HasV5TEOps]>; +def : ProcNoItin<"xscale", [HasV5TEOps]>; +def : ProcNoItin<"iwmmxt", [HasV5TEOps]>; // V6 Processors. -def : Processor<"arm1136j-s", ARMV6Itineraries, [ArchV6]>; -def : Processor<"arm1136jf-s", ARMV6Itineraries, [ArchV6, FeatureVFP2, +def : Processor<"arm1136j-s", ARMV6Itineraries, [HasV6Ops]>; +def : Processor<"arm1136jf-s", ARMV6Itineraries, [HasV6Ops, FeatureVFP2, FeatureHasSlowFPVMLx]>; -def : Processor<"arm1176jz-s", ARMV6Itineraries, [ArchV6]>; -def : Processor<"arm1176jzf-s", ARMV6Itineraries, [ArchV6, FeatureVFP2, +def : Processor<"arm1176jz-s", ARMV6Itineraries, [HasV6Ops]>; +def : Processor<"arm1176jzf-s", ARMV6Itineraries, [HasV6Ops, FeatureVFP2, FeatureHasSlowFPVMLx]>; -def : Processor<"mpcorenovfp", ARMV6Itineraries, [ArchV6]>; -def : Processor<"mpcore", ARMV6Itineraries, [ArchV6, FeatureVFP2, +def : Processor<"mpcorenovfp", ARMV6Itineraries, [HasV6Ops]>; +def : Processor<"mpcore", ARMV6Itineraries, [HasV6Ops, FeatureVFP2, FeatureHasSlowFPVMLx]>; // V6M Processors. -def : Processor<"cortex-m0", ARMV6Itineraries, [ArchV6M]>; +def : Processor<"cortex-m0", ARMV6Itineraries, [HasV6Ops, FeatureNoARM, + FeatureDB]>; // V6T2 Processors. -def : Processor<"arm1156t2-s", ARMV6Itineraries, [ArchV6T2]>; -def : Processor<"arm1156t2f-s", ARMV6Itineraries, [ArchV6T2, FeatureVFP2, +def : Processor<"arm1156t2-s", ARMV6Itineraries, [HasV6T2Ops]>; +def : Processor<"arm1156t2f-s", ARMV6Itineraries, [HasV6T2Ops, FeatureVFP2, FeatureHasSlowFPVMLx]>; -// V7 Processors. +// V7a Processors. def : Processor<"cortex-a8", CortexA8Itineraries, - [ArchV7A, ProcA8]>; + [ProcA8, HasV7Ops, FeatureNEON, FeatureDB, + FeatureDSPThumb2]>; def : Processor<"cortex-a9", CortexA9Itineraries, - [ArchV7A, ProcA9]>; + [ProcA9, HasV7Ops, FeatureNEON, FeatureDB, + FeatureDSPThumb2]>; def : Processor<"cortex-a9-mp", CortexA9Itineraries, - [ArchV7A, ProcA9, FeatureMP]>; + [ProcA9, HasV7Ops, FeatureNEON, FeatureDB, + FeatureDSPThumb2, FeatureMP]>; // V7M Processors. -def : ProcNoItin<"cortex-m3", [ArchV7M]>; -def : ProcNoItin<"cortex-m4", [ArchV7M, FeatureVFP2, FeatureVFPOnlySP]>; +def : ProcNoItin<"cortex-m3", [HasV7Ops, + FeatureThumb2, FeatureNoARM, FeatureDB, + FeatureHWDiv]>; + +// V7EM Processors. +def : ProcNoItin<"cortex-m4", [HasV7Ops, + FeatureThumb2, FeatureNoARM, FeatureDB, + FeatureHWDiv, FeatureDSPThumb2, + FeatureT2XtPk, FeatureVFP2, + FeatureVFPOnlySP]>; //===----------------------------------------------------------------------===// // Register File Description diff --git a/lib/Target/ARM/ARMAsmBackend.cpp b/lib/Target/ARM/ARMAsmBackend.cpp index 618a2b5f3eac..5e438a976732 100644 --- a/lib/Target/ARM/ARMAsmBackend.cpp +++ b/lib/Target/ARM/ARMAsmBackend.cpp @@ -28,14 +28,6 @@ using namespace llvm; namespace { -class ARMMachObjectWriter : public MCMachObjectTargetWriter { -public: - ARMMachObjectWriter(bool Is64Bit, uint32_t CPUType, - uint32_t CPUSubtype) - : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype, - /*UseAggressiveSymbolFolding=*/true) {} -}; - class ARMELFObjectWriter : public MCELFObjectTargetWriter { public: ARMELFObjectWriter(Triple::OSType OSType) @@ -182,7 +174,8 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { Value >>= 16; // Fallthrough case ARM::fixup_t2_movw_lo16: - case ARM::fixup_t2_movt_hi16_pcrel: + case ARM::fixup_t2_movt_hi16_pcrel: //FIXME: Shouldn't this be shifted like + // the other hi16 fixup? case ARM::fixup_t2_movw_lo16_pcrel: { unsigned Hi4 = (Value & 0xF000) >> 12; unsigned i = (Value & 0x800) >> 11; @@ -192,8 +185,10 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { // inst{26} = i; // inst{14-12} = Mid3; // inst{7-0} = Lo8; - assert ((((int64_t)Value) >= -0x8000) && (((int64_t)Value) <= 0x7fff) && - "Out of range pc-relative fixup value!"); + // The value comes in as the whole thing, not just the portion required + // for this fixup, so we need to mask off the bits not handled by this + // portion (lo vs. hi). + Value &= 0xffff; Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8); uint64_t swapped = (Value & 0xFFFF0000) >> 16; swapped |= (Value & 0x0000FFFF) << 16; @@ -423,12 +418,9 @@ public: : ARMAsmBackend(T), Subtype(st) { } MCObjectWriter *createObjectWriter(raw_ostream &OS) const { - return createMachObjectWriter(new ARMMachObjectWriter( - /*Is64Bit=*/false, - object::mach::CTM_ARM, - Subtype), - OS, - /*IsLittleEndian=*/true); + return createARMMachObjectWriter(OS, /*Is64Bit=*/false, + object::mach::CTM_ARM, + Subtype); } void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, @@ -505,7 +497,13 @@ TargetAsmBackend *llvm::createARMAsmBackend(const Target &T, Triple TheTriple(TT); if (TheTriple.isOSDarwin()) { - if (TheTriple.getArchName() == "armv6" || + if (TheTriple.getArchName() == "armv4t" || + TheTriple.getArchName() == "thumbv4t") + return new DarwinARMAsmBackend(T, object::mach::CSARM_V4T); + else if (TheTriple.getArchName() == "armv5e" || + TheTriple.getArchName() == "thumbv5e") + return new DarwinARMAsmBackend(T, object::mach::CSARM_V5TEJ); + else if (TheTriple.getArchName() == "armv6" || TheTriple.getArchName() == "thumbv6") return new DarwinARMAsmBackend(T, object::mach::CSARM_V6); return new DarwinARMAsmBackend(T, object::mach::CSARM_V7); diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index eb7390236df3..dbc3ee41f3da 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -654,7 +654,7 @@ void ARMAsmPrinter::emitAttributes() { } /* TODO: ARMBuildAttrs::Allowed is not completely accurate, - * since NEON can have 1 (allowed) or 2 (fused MAC operations) */ + * since NEON can have 1 (allowed) or 2 (MAC operations) */ if (Subtarget->hasNEON()) { AttrEmitter->EmitAttribute(ARMBuildAttrs::Advanced_SIMD_arch, ARMBuildAttrs::Allowed); @@ -1010,19 +1010,16 @@ void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) { MI->dump(); assert(0 && "Unsupported opcode for unwinding information"); case ARM::MOVr: - case ARM::tMOVgpr2gpr: - case ARM::tMOVgpr2tgpr: Offset = 0; break; case ARM::ADDri: Offset = -MI->getOperand(2).getImm(); break; case ARM::SUBri: - case ARM::t2SUBrSPi: - Offset = MI->getOperand(2).getImm(); + Offset = MI->getOperand(2).getImm(); break; case ARM::tSUBspi: - Offset = MI->getOperand(2).getImm()*4; + Offset = MI->getOperand(2).getImm()*4; break; case ARM::tADDspi: case ARM::tADDrSPi: @@ -1072,39 +1069,18 @@ void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) { extern cl::opt<bool> EnableARMEHABI; +// Simple pseudo-instructions have their lowering (with expansion to real +// instructions) auto-generated. +#include "ARMGenMCPseudoLowering.inc" + void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { - unsigned Opc = MI->getOpcode(); - switch (Opc) { - default: break; - case ARM::B: { - // B is just a Bcc with an 'always' predicate. - MCInst TmpInst; - LowerARMMachineInstrToMCInst(MI, TmpInst, *this); - TmpInst.setOpcode(ARM::Bcc); - // Add predicate operands. - TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); - TmpInst.addOperand(MCOperand::CreateReg(0)); - OutStreamer.EmitInstruction(TmpInst); - return; - } - case ARM::LDMIA_RET: { - // LDMIA_RET is just a normal LDMIA_UPD instruction that targets PC and as - // such has additional code-gen properties and scheduling information. - // To emit it, we just construct as normal and set the opcode to LDMIA_UPD. - MCInst TmpInst; - LowerARMMachineInstrToMCInst(MI, TmpInst, *this); - TmpInst.setOpcode(ARM::LDMIA_UPD); - OutStreamer.EmitInstruction(TmpInst); + // Do any auto-generated pseudo lowerings. + if (emitPseudoExpansionLowering(OutStreamer, MI)) return; - } - case ARM::t2ADDrSPi: - case ARM::t2ADDrSPi12: - case ARM::t2SUBrSPi: - case ARM::t2SUBrSPi12: - assert ((MI->getOperand(1).getReg() == ARM::SP) && - "Unexpected source register!"); - break; + // Check for manual lowerings. + unsigned Opc = MI->getOpcode(); + switch (Opc) { case ARM::t2MOVi32imm: assert(0 && "Should be lowered by thumb2it pass"); case ARM::DBG_VALUE: { if (isVerbose() && OutStreamer.hasRawTextSupport()) { @@ -1115,14 +1091,6 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { } return; } - case ARM::tBfar: { - MCInst TmpInst; - TmpInst.setOpcode(ARM::tBL); - TmpInst.addOperand(MCOperand::CreateExpr(MCSymbolRefExpr::Create( - MI->getOperand(0).getMBB()->getSymbol(), OutContext))); - OutStreamer.EmitInstruction(TmpInst); - return; - } case ARM::LEApcrel: case ARM::tLEApcrel: case ARM::t2LEApcrel: { @@ -1153,39 +1121,8 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { OutStreamer.EmitInstruction(TmpInst); return; } - case ARM::MOVPCRX: { - MCInst TmpInst; - TmpInst.setOpcode(ARM::MOVr); - TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); - TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); - // Add predicate operands. - TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); - TmpInst.addOperand(MCOperand::CreateReg(0)); - // Add 's' bit operand (always reg0 for this) - TmpInst.addOperand(MCOperand::CreateReg(0)); - OutStreamer.EmitInstruction(TmpInst); - return; - } // Darwin call instructions are just normal call instructions with different // clobber semantics (they clobber R9). - case ARM::BLr9: - case ARM::BLr9_pred: - case ARM::BLXr9: - case ARM::BLXr9_pred: { - unsigned newOpc; - switch (Opc) { - default: assert(0); - case ARM::BLr9: newOpc = ARM::BL; break; - case ARM::BLr9_pred: newOpc = ARM::BL_pred; break; - case ARM::BLXr9: newOpc = ARM::BLX; break; - case ARM::BLXr9_pred: newOpc = ARM::BLX_pred; break; - } - MCInst TmpInst; - LowerARMMachineInstrToMCInst(MI, TmpInst, *this); - TmpInst.setOpcode(newOpc); - OutStreamer.EmitInstruction(TmpInst); - return; - } case ARM::BXr9_CALL: case ARM::BX_CALL: { { @@ -1215,6 +1152,9 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { TmpInst.setOpcode(ARM::tMOVr); TmpInst.addOperand(MCOperand::CreateReg(ARM::LR)); TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); + // Add predicate operands. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); OutStreamer.EmitInstruction(TmpInst); } { @@ -1445,7 +1385,7 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { case ARM::t2BR_JT: { // Lower and emit the instruction itself, then the jump table following it. MCInst TmpInst; - TmpInst.setOpcode(ARM::tMOVgpr2gpr); + TmpInst.setOpcode(ARM::tMOVr); TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); // Add predicate operands. @@ -1494,7 +1434,7 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { // mov pc, target MCInst TmpInst; unsigned Opc = MI->getOpcode() == ARM::BR_JTr ? - ARM::MOVr : ARM::tMOVgpr2gpr; + ARM::MOVr : ARM::tMOVr; TmpInst.setOpcode(Opc); TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); @@ -1507,7 +1447,7 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { OutStreamer.EmitInstruction(TmpInst); // Make sure the Thumb jump table is 4-byte aligned. - if (Opc == ARM::tMOVgpr2gpr) + if (Opc == ARM::tMOVr) EmitAlignment(2); // Output the data for the jump table itself @@ -1599,11 +1539,12 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { MCSymbol *Label = GetARMSJLJEHLabel(); { MCInst TmpInst; - TmpInst.setOpcode(ARM::tMOVgpr2tgpr); + TmpInst.setOpcode(ARM::tMOVr); TmpInst.addOperand(MCOperand::CreateReg(ValReg)); TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); - // 's' bit operand - TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR)); + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); OutStreamer.AddComment("eh_setjmp begin"); OutStreamer.EmitInstruction(TmpInst); } @@ -1817,7 +1758,7 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { } { MCInst TmpInst; - TmpInst.setOpcode(ARM::tMOVtgpr2gpr); + TmpInst.setOpcode(ARM::tMOVr); TmpInst.addOperand(MCOperand::CreateReg(ARM::SP)); TmpInst.addOperand(MCOperand::CreateReg(ScratchReg)); // Predicate. @@ -1858,75 +1799,6 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { } return; } - // Tail jump branches are really just branch instructions with additional - // code-gen attributes. Convert them to the canonical form here. - case ARM::TAILJMPd: - case ARM::TAILJMPdND: { - MCInst TmpInst, TmpInst2; - // Lower the instruction as-is to get the operands properly converted. - LowerARMMachineInstrToMCInst(MI, TmpInst2, *this); - TmpInst.setOpcode(ARM::Bcc); - TmpInst.addOperand(TmpInst2.getOperand(0)); - // Add predicate operands. - TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); - TmpInst.addOperand(MCOperand::CreateReg(0)); - OutStreamer.AddComment("TAILCALL"); - OutStreamer.EmitInstruction(TmpInst); - return; - } - case ARM::tTAILJMPd: - case ARM::tTAILJMPdND: { - MCInst TmpInst, TmpInst2; - LowerARMMachineInstrToMCInst(MI, TmpInst2, *this); - // The Darwin toolchain doesn't support tail call relocations of 16-bit - // branches. - TmpInst.setOpcode(Opc == ARM::tTAILJMPd ? ARM::t2B : ARM::tB); - TmpInst.addOperand(TmpInst2.getOperand(0)); - OutStreamer.AddComment("TAILCALL"); - OutStreamer.EmitInstruction(TmpInst); - return; - } - case ARM::TAILJMPrND: - case ARM::tTAILJMPrND: - case ARM::TAILJMPr: - case ARM::tTAILJMPr: { - unsigned newOpc = (Opc == ARM::TAILJMPr || Opc == ARM::TAILJMPrND) - ? ARM::BX : ARM::tBX; - MCInst TmpInst; - TmpInst.setOpcode(newOpc); - TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); - // Predicate. - TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); - TmpInst.addOperand(MCOperand::CreateReg(0)); - OutStreamer.AddComment("TAILCALL"); - OutStreamer.EmitInstruction(TmpInst); - return; - } - - // These are the pseudos created to comply with stricter operand restrictions - // on ARMv5. Lower them now to "normal" instructions, since all the - // restrictions are already satisfied. - case ARM::MULv5: - EmitPatchedInstruction(MI, ARM::MUL); - return; - case ARM::MLAv5: - EmitPatchedInstruction(MI, ARM::MLA); - return; - case ARM::SMULLv5: - EmitPatchedInstruction(MI, ARM::SMULL); - return; - case ARM::UMULLv5: - EmitPatchedInstruction(MI, ARM::UMULL); - return; - case ARM::SMLALv5: - EmitPatchedInstruction(MI, ARM::SMLAL); - return; - case ARM::UMLALv5: - EmitPatchedInstruction(MI, ARM::UMLAL); - return; - case ARM::UMAALv5: - EmitPatchedInstruction(MI, ARM::UMAAL); - return; } MCInst TmpInst; @@ -1944,11 +1816,10 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { //===----------------------------------------------------------------------===// static MCInstPrinter *createARMMCInstPrinter(const Target &T, - TargetMachine &TM, unsigned SyntaxVariant, const MCAsmInfo &MAI) { if (SyntaxVariant == 0) - return new ARMInstPrinter(TM, MAI); + return new ARMInstPrinter(MAI); return 0; } diff --git a/lib/Target/ARM/ARMAsmPrinter.h b/lib/Target/ARM/ARMAsmPrinter.h index 5f9169ef7f77..7741fc4b34e8 100644 --- a/lib/Target/ARM/ARMAsmPrinter.h +++ b/lib/Target/ARM/ARMAsmPrinter.h @@ -21,6 +21,8 @@ namespace llvm { +class MCOperand; + namespace ARM { enum DW_ISA { DW_ISA_ARM_thumb = 1, @@ -72,6 +74,9 @@ public: void EmitStartOfAsmFile(Module &M); void EmitEndOfAsmFile(Module &M); + // lowerOperand - Convert a MachineOperand into the equivalent MCOperand. + bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp); + private: // Helpers for EmitStartOfAsmFile() and EmitEndOfAsmFile() void emitAttributes(); @@ -84,6 +89,10 @@ private: void EmitUnwindingInstruction(const MachineInstr *MI); + // emitPseudoExpansionLowering - tblgen'erated. + bool emitPseudoExpansionLowering(MCStreamer &OutStreamer, + const MachineInstr *MI); + public: void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); @@ -100,6 +109,7 @@ public: llvm::ARM::DW_ISA_ARM_thumb : llvm::ARM::DW_ISA_ARM_arm; } + MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol); MCSymbol *GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2, const MachineBasicBlock *MBB) const; MCSymbol *GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const; @@ -107,7 +117,7 @@ public: MCSymbol *GetARMSJLJEHLabel(void) const; MCSymbol *GetARMGVSymbol(const GlobalValue *GV); - + /// EmitMachineConstantPoolValue - Print a machine constantpool value to /// the .s file. virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV); diff --git a/lib/Target/ARM/ARMBaseInfo.h b/lib/Target/ARM/ARMBaseInfo.h index 36edbad7a601..458f7dd1f784 100644 --- a/lib/Target/ARM/ARMBaseInfo.h +++ b/lib/Target/ARM/ARMBaseInfo.h @@ -17,20 +17,12 @@ #ifndef ARMBASEINFO_H #define ARMBASEINFO_H +#include "MCTargetDesc/ARMMCTargetDesc.h" #include "llvm/Support/ErrorHandling.h" // Note that the following auto-generated files only defined enum types, and // so are safe to include here. -// Defines symbolic names for ARM registers. This defines a mapping from -// register name to register number. -// -#include "ARMGenRegisterNames.inc" - -// Defines symbolic names for the ARM instructions. -// -#include "ARMGenInstrNames.inc" - namespace llvm { // Enums corresponding to ARM condition codes diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index 44a397611526..649bd7d5ce3f 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -18,7 +18,6 @@ #include "ARMHazardRecognizer.h" #include "ARMMachineFunctionInfo.h" #include "ARMRegisterInfo.h" -#include "ARMGenInstrInfo.inc" #include "llvm/Constants.h" #include "llvm/Function.h" #include "llvm/GlobalValue.h" @@ -31,10 +30,15 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/Support/BranchProbability.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/ADT/STLExtras.h" + +#define GET_INSTRINFO_CTOR +#include "ARMGenInstrInfo.inc" + using namespace llvm; static cl::opt<bool> @@ -74,7 +78,7 @@ static const ARM_MLxEntry ARM_MLxTable[] = { }; ARMBaseInstrInfo::ARMBaseInstrInfo(const ARMSubtarget& STI) - : TargetInstrInfoImpl(ARMInsts, array_lengthof(ARMInsts)), + : ARMGenInstrInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP), Subtarget(STI) { for (unsigned i = 0, e = array_lengthof(ARM_MLxTable); i != e; ++i) { if (!MLxEntryMap.insert(std::make_pair(ARM_MLxTable[i].MLxOpc, i)).second) @@ -136,9 +140,9 @@ ARMBaseInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, MachineInstr *UpdateMI = NULL; MachineInstr *MemMI = NULL; unsigned AddrMode = (TSFlags & ARMII::AddrModeMask); - const TargetInstrDesc &TID = MI->getDesc(); - unsigned NumOps = TID.getNumOperands(); - bool isLoad = !TID.mayStore(); + const MCInstrDesc &MCID = MI->getDesc(); + unsigned NumOps = MCID.getNumOperands(); + bool isLoad = !MCID.mayStore(); const MachineOperand &WB = isLoad ? MI->getOperand(1) : MI->getOperand(0); const MachineOperand &Base = MI->getOperand(2); const MachineOperand &Offset = MI->getOperand(NumOps-3); @@ -475,8 +479,8 @@ SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1, bool ARMBaseInstrInfo::DefinesPredicate(MachineInstr *MI, std::vector<MachineOperand> &Pred) const { // FIXME: This confuses implicit_def with optional CPSR def. - const TargetInstrDesc &TID = MI->getDesc(); - if (!TID.getImplicitDefs() && !TID.hasOptionalDef()) + const MCInstrDesc &MCID = MI->getDesc(); + if (!MCID.getImplicitDefs() && !MCID.hasOptionalDef()) return false; bool Found = false; @@ -495,11 +499,11 @@ bool ARMBaseInstrInfo::DefinesPredicate(MachineInstr *MI, /// By default, this returns true for every instruction with a /// PredicateOperand. bool ARMBaseInstrInfo::isPredicable(MachineInstr *MI) const { - const TargetInstrDesc &TID = MI->getDesc(); - if (!TID.isPredicable()) + const MCInstrDesc &MCID = MI->getDesc(); + if (!MCID.isPredicable()) return false; - if ((TID.TSFlags & ARMII::DomainMask) == ARMII::DomainNEON) { + if ((MCID.TSFlags & ARMII::DomainMask) == ARMII::DomainNEON) { ARMFunctionInfo *AFI = MI->getParent()->getParent()->getInfo<ARMFunctionInfo>(); return AFI->isThumb2Function(); @@ -524,35 +528,23 @@ unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { const MachineFunction *MF = MBB.getParent(); const MCAsmInfo *MAI = MF->getTarget().getMCAsmInfo(); - // Basic size info comes from the TSFlags field. - const TargetInstrDesc &TID = MI->getDesc(); - uint64_t TSFlags = TID.TSFlags; + const MCInstrDesc &MCID = MI->getDesc(); + if (MCID.getSize()) + return MCID.getSize(); - unsigned Opc = MI->getOpcode(); - switch ((TSFlags & ARMII::SizeMask) >> ARMII::SizeShift) { - default: { // If this machine instr is an inline asm, measure it. if (MI->getOpcode() == ARM::INLINEASM) return getInlineAsmLength(MI->getOperand(0).getSymbolName(), *MAI); if (MI->isLabel()) return 0; + unsigned Opc = MI->getOpcode(); switch (Opc) { - default: - llvm_unreachable("Unknown or unset size field for instr!"); case TargetOpcode::IMPLICIT_DEF: case TargetOpcode::KILL: case TargetOpcode::PROLOG_LABEL: case TargetOpcode::EH_LABEL: case TargetOpcode::DBG_VALUE: return 0; - } - break; - } - case ARMII::Size8Bytes: return 8; // ARM instruction x 2. - case ARMII::Size4Bytes: return 4; // ARM / Thumb2 instruction. - case ARMII::Size2Bytes: return 2; // Thumb1 instruction. - case ARMII::SizeSpecial: { - switch (Opc) { case ARM::MOVi16_ga_pcrel: case ARM::MOVTi16_ga_pcrel: case ARM::t2MOVi16_ga_pcrel: @@ -588,9 +580,9 @@ unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { // entry is one byte; TBH two byte each. unsigned EntrySize = (Opc == ARM::t2TBB_JT) ? 1 : ((Opc == ARM::t2TBH_JT) ? 2 : 4); - unsigned NumOps = TID.getNumOperands(); + unsigned NumOps = MCID.getNumOperands(); MachineOperand JTOP = - MI->getOperand(NumOps - (TID.isPredicable() ? 3 : 2)); + MI->getOperand(NumOps - (MCID.isPredicable() ? 3 : 2)); unsigned JTI = JTOP.getIndex(); const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); assert(MJTI != 0); @@ -616,8 +608,6 @@ unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { // Otherwise, pseudo-instruction sizes are zero. return 0; } - } - } return 0; // Not reached } @@ -647,7 +637,7 @@ void ARMBaseInstrInfo::copyPhysReg(MachineBasicBlock &MBB, else if (ARM::DPRRegClass.contains(DestReg, SrcReg)) Opc = ARM::VMOVD; else if (ARM::QPRRegClass.contains(DestReg, SrcReg)) - Opc = ARM::VMOVQ; + Opc = ARM::VORRq; else if (ARM::QQPRRegClass.contains(DestReg, SrcReg)) Opc = ARM::VMOVQQ; else if (ARM::QQQQPRRegClass.contains(DestReg, SrcReg)) @@ -657,6 +647,8 @@ void ARMBaseInstrInfo::copyPhysReg(MachineBasicBlock &MBB, MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opc), DestReg); MIB.addReg(SrcReg, getKillRegState(KillSrc)); + if (Opc == ARM::VORRq) + MIB.addReg(SrcReg, getKillRegState(KillSrc)); if (Opc != ARM::VMOVQQ && Opc != ARM::VMOVQQQQ) AddDefaultPred(MIB); } @@ -788,7 +780,7 @@ ARMBaseInstrInfo::isStoreToStackSlot(const MachineInstr *MI, break; case ARM::STRi12: case ARM::t2STRi12: - case ARM::tSpill: + case ARM::tSTRspi: case ARM::VSTRD: case ARM::VSTRS: if (MI->getOperand(1).isFI() && @@ -923,7 +915,7 @@ ARMBaseInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, break; case ARM::LDRi12: case ARM::t2LDRi12: - case ARM::tRestore: + case ARM::tLDRspi: case ARM::VLDRD: case ARM::VLDRS: if (MI->getOperand(1).isFI() && @@ -1269,20 +1261,20 @@ bool ARMBaseInstrInfo::isSchedulingBoundary(const MachineInstr *MI, return false; } -bool ARMBaseInstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB, - unsigned NumCycles, - unsigned ExtraPredCycles, - float Probability, - float Confidence) const { +bool ARMBaseInstrInfo:: +isProfitableToIfCvt(MachineBasicBlock &MBB, + unsigned NumCycles, unsigned ExtraPredCycles, + const BranchProbability &Probability) const { if (!NumCycles) return false; // Attempt to estimate the relative costs of predication versus branching. - float UnpredCost = Probability * NumCycles; - UnpredCost += 1.0; // The branch itself - UnpredCost += (1.0 - Confidence) * Subtarget.getMispredictionPenalty(); + unsigned UnpredCost = Probability.getNumerator() * NumCycles; + UnpredCost /= Probability.getDenominator(); + UnpredCost += 1; // The branch itself + UnpredCost += Subtarget.getMispredictionPenalty() / 10; - return (float)(NumCycles + ExtraPredCycles) < UnpredCost; + return (NumCycles + ExtraPredCycles) <= UnpredCost; } bool ARMBaseInstrInfo:: @@ -1290,16 +1282,23 @@ isProfitableToIfCvt(MachineBasicBlock &TMBB, unsigned TCycles, unsigned TExtra, MachineBasicBlock &FMBB, unsigned FCycles, unsigned FExtra, - float Probability, float Confidence) const { + const BranchProbability &Probability) const { if (!TCycles || !FCycles) return false; // Attempt to estimate the relative costs of predication versus branching. - float UnpredCost = Probability * TCycles + (1.0 - Probability) * FCycles; - UnpredCost += 1.0; // The branch itself - UnpredCost += (1.0 - Confidence) * Subtarget.getMispredictionPenalty(); - - return (float)(TCycles + FCycles + TExtra + FExtra) < UnpredCost; + unsigned TUnpredCost = Probability.getNumerator() * TCycles; + TUnpredCost /= Probability.getDenominator(); + + uint32_t Comp = Probability.getDenominator() - Probability.getNumerator(); + unsigned FUnpredCost = Comp * FCycles; + FUnpredCost /= Probability.getDenominator(); + + unsigned UnpredCost = TUnpredCost + FUnpredCost; + UnpredCost += 1; // The branch itself + UnpredCost += Subtarget.getMispredictionPenalty() / 10; + + return (TCycles + FCycles + TExtra + FExtra) <= UnpredCost; } /// getInstrPredicate - If instruction is predicated, returns its predicate @@ -1363,7 +1362,7 @@ bool llvm::rewriteARMFrameIndex(MachineInstr &MI, unsigned FrameRegIdx, unsigned FrameReg, int &Offset, const ARMBaseInstrInfo &TII) { unsigned Opcode = MI.getOpcode(); - const TargetInstrDesc &Desc = MI.getDesc(); + const MCInstrDesc &Desc = MI.getDesc(); unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); bool isSub = false; @@ -1803,7 +1802,7 @@ ARMBaseInstrInfo::getNumMicroOps(const InstrItineraryData *ItinData, if (!ItinData || ItinData->isEmpty()) return 1; - const TargetInstrDesc &Desc = MI->getDesc(); + const MCInstrDesc &Desc = MI->getDesc(); unsigned Class = Desc.getSchedClass(); unsigned UOps = ItinData->Itineraries[Class].NumMicroOps; if (UOps) @@ -1906,10 +1905,10 @@ ARMBaseInstrInfo::getNumMicroOps(const InstrItineraryData *ItinData, int ARMBaseInstrInfo::getVLDMDefCycle(const InstrItineraryData *ItinData, - const TargetInstrDesc &DefTID, + const MCInstrDesc &DefMCID, unsigned DefClass, unsigned DefIdx, unsigned DefAlign) const { - int RegNo = (int)(DefIdx+1) - DefTID.getNumOperands() + 1; + int RegNo = (int)(DefIdx+1) - DefMCID.getNumOperands() + 1; if (RegNo <= 0) // Def is the address writeback. return ItinData->getOperandCycle(DefClass, DefIdx); @@ -1924,7 +1923,7 @@ ARMBaseInstrInfo::getVLDMDefCycle(const InstrItineraryData *ItinData, DefCycle = RegNo; bool isSLoad = false; - switch (DefTID.getOpcode()) { + switch (DefMCID.getOpcode()) { default: break; case ARM::VLDMSIA: case ARM::VLDMSIA_UPD: @@ -1947,10 +1946,10 @@ ARMBaseInstrInfo::getVLDMDefCycle(const InstrItineraryData *ItinData, int ARMBaseInstrInfo::getLDMDefCycle(const InstrItineraryData *ItinData, - const TargetInstrDesc &DefTID, + const MCInstrDesc &DefMCID, unsigned DefClass, unsigned DefIdx, unsigned DefAlign) const { - int RegNo = (int)(DefIdx+1) - DefTID.getNumOperands() + 1; + int RegNo = (int)(DefIdx+1) - DefMCID.getNumOperands() + 1; if (RegNo <= 0) // Def is the address writeback. return ItinData->getOperandCycle(DefClass, DefIdx); @@ -1982,10 +1981,10 @@ ARMBaseInstrInfo::getLDMDefCycle(const InstrItineraryData *ItinData, int ARMBaseInstrInfo::getVSTMUseCycle(const InstrItineraryData *ItinData, - const TargetInstrDesc &UseTID, + const MCInstrDesc &UseMCID, unsigned UseClass, unsigned UseIdx, unsigned UseAlign) const { - int RegNo = (int)(UseIdx+1) - UseTID.getNumOperands() + 1; + int RegNo = (int)(UseIdx+1) - UseMCID.getNumOperands() + 1; if (RegNo <= 0) return ItinData->getOperandCycle(UseClass, UseIdx); @@ -1999,7 +1998,7 @@ ARMBaseInstrInfo::getVSTMUseCycle(const InstrItineraryData *ItinData, UseCycle = RegNo; bool isSStore = false; - switch (UseTID.getOpcode()) { + switch (UseMCID.getOpcode()) { default: break; case ARM::VSTMSIA: case ARM::VSTMSIA_UPD: @@ -2022,10 +2021,10 @@ ARMBaseInstrInfo::getVSTMUseCycle(const InstrItineraryData *ItinData, int ARMBaseInstrInfo::getSTMUseCycle(const InstrItineraryData *ItinData, - const TargetInstrDesc &UseTID, + const MCInstrDesc &UseMCID, unsigned UseClass, unsigned UseIdx, unsigned UseAlign) const { - int RegNo = (int)(UseIdx+1) - UseTID.getNumOperands() + 1; + int RegNo = (int)(UseIdx+1) - UseMCID.getNumOperands() + 1; if (RegNo <= 0) return ItinData->getOperandCycle(UseClass, UseIdx); @@ -2051,14 +2050,14 @@ ARMBaseInstrInfo::getSTMUseCycle(const InstrItineraryData *ItinData, int ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, - const TargetInstrDesc &DefTID, + const MCInstrDesc &DefMCID, unsigned DefIdx, unsigned DefAlign, - const TargetInstrDesc &UseTID, + const MCInstrDesc &UseMCID, unsigned UseIdx, unsigned UseAlign) const { - unsigned DefClass = DefTID.getSchedClass(); - unsigned UseClass = UseTID.getSchedClass(); + unsigned DefClass = DefMCID.getSchedClass(); + unsigned UseClass = UseMCID.getSchedClass(); - if (DefIdx < DefTID.getNumDefs() && UseIdx < UseTID.getNumOperands()) + if (DefIdx < DefMCID.getNumDefs() && UseIdx < UseMCID.getNumOperands()) return ItinData->getOperandLatency(DefClass, DefIdx, UseClass, UseIdx); // This may be a def / use of a variable_ops instruction, the operand @@ -2066,7 +2065,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, // figure it out. int DefCycle = -1; bool LdmBypass = false; - switch (DefTID.getOpcode()) { + switch (DefMCID.getOpcode()) { default: DefCycle = ItinData->getOperandCycle(DefClass, DefIdx); break; @@ -2077,7 +2076,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, case ARM::VLDMSIA: case ARM::VLDMSIA_UPD: case ARM::VLDMSDB_UPD: - DefCycle = getVLDMDefCycle(ItinData, DefTID, DefClass, DefIdx, DefAlign); + DefCycle = getVLDMDefCycle(ItinData, DefMCID, DefClass, DefIdx, DefAlign); break; case ARM::LDMIA_RET: @@ -2098,7 +2097,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, case ARM::t2LDMIA_UPD: case ARM::t2LDMDB_UPD: LdmBypass = 1; - DefCycle = getLDMDefCycle(ItinData, DefTID, DefClass, DefIdx, DefAlign); + DefCycle = getLDMDefCycle(ItinData, DefMCID, DefClass, DefIdx, DefAlign); break; } @@ -2107,7 +2106,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, DefCycle = 2; int UseCycle = -1; - switch (UseTID.getOpcode()) { + switch (UseMCID.getOpcode()) { default: UseCycle = ItinData->getOperandCycle(UseClass, UseIdx); break; @@ -2118,7 +2117,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, case ARM::VSTMSIA: case ARM::VSTMSIA_UPD: case ARM::VSTMSDB_UPD: - UseCycle = getVSTMUseCycle(ItinData, UseTID, UseClass, UseIdx, UseAlign); + UseCycle = getVSTMUseCycle(ItinData, UseMCID, UseClass, UseIdx, UseAlign); break; case ARM::STMIA: @@ -2137,7 +2136,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, case ARM::t2STMDB: case ARM::t2STMIA_UPD: case ARM::t2STMDB_UPD: - UseCycle = getSTMUseCycle(ItinData, UseTID, UseClass, UseIdx, UseAlign); + UseCycle = getSTMUseCycle(ItinData, UseMCID, UseClass, UseIdx, UseAlign); break; } @@ -2150,7 +2149,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, if (LdmBypass) { // It's a variable_ops instruction so we can't use DefIdx here. Just use // first def operand. - if (ItinData->hasPipelineForwarding(DefClass, DefTID.getNumOperands()-1, + if (ItinData->hasPipelineForwarding(DefClass, DefMCID.getNumOperands()-1, UseClass, UseIdx)) --UseCycle; } else if (ItinData->hasPipelineForwarding(DefClass, DefIdx, @@ -2170,11 +2169,11 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, DefMI->isRegSequence() || DefMI->isImplicitDef()) return 1; - const TargetInstrDesc &DefTID = DefMI->getDesc(); + const MCInstrDesc &DefMCID = DefMI->getDesc(); if (!ItinData || ItinData->isEmpty()) - return DefTID.mayLoad() ? 3 : 1; + return DefMCID.mayLoad() ? 3 : 1; - const TargetInstrDesc &UseTID = UseMI->getDesc(); + const MCInstrDesc &UseMCID = UseMI->getDesc(); const MachineOperand &DefMO = DefMI->getOperand(DefIdx); if (DefMO.getReg() == ARM::CPSR) { if (DefMI->getOpcode() == ARM::FMSTAT) { @@ -2183,7 +2182,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, } // CPSR set and branch can be paired in the same cycle. - if (UseTID.isBranch()) + if (UseMCID.isBranch()) return 0; } @@ -2191,14 +2190,14 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, ? (*DefMI->memoperands_begin())->getAlignment() : 0; unsigned UseAlign = UseMI->hasOneMemOperand() ? (*UseMI->memoperands_begin())->getAlignment() : 0; - int Latency = getOperandLatency(ItinData, DefTID, DefIdx, DefAlign, - UseTID, UseIdx, UseAlign); + int Latency = getOperandLatency(ItinData, DefMCID, DefIdx, DefAlign, + UseMCID, UseIdx, UseAlign); if (Latency > 1 && (Subtarget.isCortexA8() || Subtarget.isCortexA9())) { // FIXME: Shifter op hack: no shift (i.e. [r +/- r]) or [r + r << 2] // variants are one cycle cheaper. - switch (DefTID.getOpcode()) { + switch (DefMCID.getOpcode()) { default: break; case ARM::LDRrs: case ARM::LDRBrs: { @@ -2223,7 +2222,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, } if (DefAlign < 8 && Subtarget.isCortexA9()) - switch (DefTID.getOpcode()) { + switch (DefMCID.getOpcode()) { default: break; case ARM::VLD1q8: case ARM::VLD1q16: @@ -2327,37 +2326,37 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, if (!DefNode->isMachineOpcode()) return 1; - const TargetInstrDesc &DefTID = get(DefNode->getMachineOpcode()); + const MCInstrDesc &DefMCID = get(DefNode->getMachineOpcode()); - if (isZeroCost(DefTID.Opcode)) + if (isZeroCost(DefMCID.Opcode)) return 0; if (!ItinData || ItinData->isEmpty()) - return DefTID.mayLoad() ? 3 : 1; + return DefMCID.mayLoad() ? 3 : 1; if (!UseNode->isMachineOpcode()) { - int Latency = ItinData->getOperandCycle(DefTID.getSchedClass(), DefIdx); + int Latency = ItinData->getOperandCycle(DefMCID.getSchedClass(), DefIdx); if (Subtarget.isCortexA9()) return Latency <= 2 ? 1 : Latency - 1; else return Latency <= 3 ? 1 : Latency - 2; } - const TargetInstrDesc &UseTID = get(UseNode->getMachineOpcode()); + const MCInstrDesc &UseMCID = get(UseNode->getMachineOpcode()); const MachineSDNode *DefMN = dyn_cast<MachineSDNode>(DefNode); unsigned DefAlign = !DefMN->memoperands_empty() ? (*DefMN->memoperands_begin())->getAlignment() : 0; const MachineSDNode *UseMN = dyn_cast<MachineSDNode>(UseNode); unsigned UseAlign = !UseMN->memoperands_empty() ? (*UseMN->memoperands_begin())->getAlignment() : 0; - int Latency = getOperandLatency(ItinData, DefTID, DefIdx, DefAlign, - UseTID, UseIdx, UseAlign); + int Latency = getOperandLatency(ItinData, DefMCID, DefIdx, DefAlign, + UseMCID, UseIdx, UseAlign); if (Latency > 1 && (Subtarget.isCortexA8() || Subtarget.isCortexA9())) { // FIXME: Shifter op hack: no shift (i.e. [r +/- r]) or [r + r << 2] // variants are one cycle cheaper. - switch (DefTID.getOpcode()) { + switch (DefMCID.getOpcode()) { default: break; case ARM::LDRrs: case ARM::LDRBrs: { @@ -2384,7 +2383,7 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, } if (DefAlign < 8 && Subtarget.isCortexA9()) - switch (DefTID.getOpcode()) { + switch (DefMCID.getOpcode()) { default: break; case ARM::VLD1q8Pseudo: case ARM::VLD1q16Pseudo: @@ -2503,10 +2502,10 @@ int ARMBaseInstrInfo::getInstrLatency(const InstrItineraryData *ItinData, if (!ItinData || ItinData->isEmpty()) return 1; - const TargetInstrDesc &TID = MI->getDesc(); - unsigned Class = TID.getSchedClass(); + const MCInstrDesc &MCID = MI->getDesc(); + unsigned Class = MCID.getSchedClass(); unsigned UOps = ItinData->Itineraries[Class].NumMicroOps; - if (PredCost && TID.hasImplicitDefOfPhysReg(ARM::CPSR)) + if (PredCost && MCID.hasImplicitDefOfPhysReg(ARM::CPSR)) // When predicated, CPSR is an additional source operand for CPSR updating // instructions, this apparently increases their latencies. *PredCost = 1; diff --git a/lib/Target/ARM/ARMBaseInstrInfo.h b/lib/Target/ARM/ARMBaseInstrInfo.h index 9a2faf8f9aae..507e8974bf7b 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/lib/Target/ARM/ARMBaseInstrInfo.h @@ -20,6 +20,9 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallSet.h" +#define GET_INSTRINFO_HEADER +#include "ARMGenInstrInfo.inc" + namespace llvm { class ARMSubtarget; class ARMBaseRegisterInfo; @@ -36,24 +39,16 @@ namespace ARMII { // This four-bit field describes the addressing mode used. AddrModeMask = 0x1f, // The AddrMode enums are declared in ARMBaseInfo.h - // Size* - Flags to keep track of the size of an instruction. - SizeShift = 5, - SizeMask = 7 << SizeShift, - SizeSpecial = 1, // 0 byte pseudo or special case. - Size8Bytes = 2, - Size4Bytes = 3, - Size2Bytes = 4, - // IndexMode - Unindex, pre-indexed, or post-indexed are valid for load // and store ops only. Generic "updating" flag is used for ld/st multiple. // The index mode enums are declared in ARMBaseInfo.h - IndexModeShift = 8, + IndexModeShift = 5, IndexModeMask = 3 << IndexModeShift, //===------------------------------------------------------------------===// // Instruction encoding formats. // - FormShift = 10, + FormShift = 7, FormMask = 0x3f << FormShift, // Pseudo instructions @@ -126,15 +121,15 @@ namespace ARMII { // UnaryDP - Indicates this is a unary data processing instruction, i.e. // it doesn't have a Rn operand. - UnaryDP = 1 << 16, + UnaryDP = 1 << 13, // Xform16Bit - Indicates this Thumb2 instruction may be transformed into // a 16-bit Thumb instruction if certain conditions are met. - Xform16Bit = 1 << 17, + Xform16Bit = 1 << 14, //===------------------------------------------------------------------===// // Code domain. - DomainShift = 18, + DomainShift = 15, DomainMask = 7 << DomainShift, DomainGeneral = 0 << DomainShift, DomainVFP = 1 << DomainShift, @@ -172,7 +167,7 @@ namespace ARMII { }; } -class ARMBaseInstrInfo : public TargetInstrInfoImpl { +class ARMBaseInstrInfo : public ARMGenInstrInfo { const ARMSubtarget &Subtarget; protected: @@ -291,8 +286,8 @@ public: int64_t &Offset1, int64_t &Offset2)const; /// shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to - /// determine (in conjunction with areLoadsFromSameBasePtr) if two loads should - /// be scheduled togther. On some targets if two loads are loading from + /// determine (in conjunction with areLoadsFromSameBasePtr) if two loads + /// should be scheduled togther. On some targets if two loads are loading from /// addresses in the same cache line, it's better if they are scheduled /// together. This function takes two integers that represent the load offsets /// from the common base address. It returns true if it decides it's desirable @@ -308,18 +303,18 @@ public: virtual bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, unsigned ExtraPredCycles, - float Prob, float Confidence) const; + const BranchProbability &Probability) const; virtual bool isProfitableToIfCvt(MachineBasicBlock &TMBB, unsigned NumT, unsigned ExtraT, MachineBasicBlock &FMBB, unsigned NumF, unsigned ExtraF, - float Probability, float Confidence) const; + const BranchProbability &Probability) const; virtual bool isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, - float Probability, - float Confidence) const { + const BranchProbability + &Probability) const { return NumCycles == 1; } @@ -353,25 +348,25 @@ public: SDNode *UseNode, unsigned UseIdx) const; private: int getVLDMDefCycle(const InstrItineraryData *ItinData, - const TargetInstrDesc &DefTID, + const MCInstrDesc &DefMCID, unsigned DefClass, unsigned DefIdx, unsigned DefAlign) const; int getLDMDefCycle(const InstrItineraryData *ItinData, - const TargetInstrDesc &DefTID, + const MCInstrDesc &DefMCID, unsigned DefClass, unsigned DefIdx, unsigned DefAlign) const; int getVSTMUseCycle(const InstrItineraryData *ItinData, - const TargetInstrDesc &UseTID, + const MCInstrDesc &UseMCID, unsigned UseClass, unsigned UseIdx, unsigned UseAlign) const; int getSTMUseCycle(const InstrItineraryData *ItinData, - const TargetInstrDesc &UseTID, + const MCInstrDesc &UseMCID, unsigned UseClass, unsigned UseIdx, unsigned UseAlign) const; int getOperandLatency(const InstrItineraryData *ItinData, - const TargetInstrDesc &DefTID, + const MCInstrDesc &DefMCID, unsigned DefIdx, unsigned DefAlign, - const TargetInstrDesc &UseTID, + const MCInstrDesc &UseMCID, unsigned UseIdx, unsigned UseAlign) const; int getInstrLatency(const InstrItineraryData *ItinData, diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index 4ab37f6cc759..ba422952ac1a 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -40,6 +40,9 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Support/CommandLine.h" +#define GET_REGINFO_TARGET_DESC +#include "ARMGenRegisterInfo.inc" + using namespace llvm; static cl::opt<bool> @@ -54,8 +57,7 @@ EnableBasePointer("arm-use-base-pointer", cl::Hidden, cl::init(true), ARMBaseRegisterInfo::ARMBaseRegisterInfo(const ARMBaseInstrInfo &tii, const ARMSubtarget &sti) - : ARMGenRegisterInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP), - TII(tii), STI(sti), + : ARMGenRegisterInfo(), TII(tii), STI(sti), FramePtr((STI.isTargetDarwin() || STI.isThumb()) ? ARM::R7 : ARM::R11), BasePtr(ARM::R6) { } @@ -100,6 +102,12 @@ getReservedRegs(const MachineFunction &MF) const { // Some targets reserve R9. if (STI.isR9Reserved()) Reserved.set(ARM::R9); + // Reserve D16-D31 if the subtarget doesn't support them. + if (!STI.hasVFP3() || STI.hasD16()) { + assert(ARM::D31 == ARM::D16 + 15); + for (unsigned i = 0; i != 16; ++i) + Reserved.set(ARM::D16 + i); + } return Reserved; } @@ -387,12 +395,12 @@ ARMBaseRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC, } } -/// getAllocationOrder - Returns the register allocation order for a specified -/// register class in the form of a pair of TargetRegisterClass iterators. -std::pair<TargetRegisterClass::iterator,TargetRegisterClass::iterator> -ARMBaseRegisterInfo::getAllocationOrder(const TargetRegisterClass *RC, - unsigned HintType, unsigned HintReg, - const MachineFunction &MF) const { +/// getRawAllocationOrder - Returns the register allocation order for a +/// specified register class with a target-dependent hint. +ArrayRef<unsigned> +ARMBaseRegisterInfo::getRawAllocationOrder(const TargetRegisterClass *RC, + unsigned HintType, unsigned HintReg, + const MachineFunction &MF) const { const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); // Alternative register allocation orders when favoring even / odd registers // of register pairs. @@ -469,70 +477,54 @@ ARMBaseRegisterInfo::getAllocationOrder(const TargetRegisterClass *RC, // We only support even/odd hints for GPR and rGPR. if (RC != ARM::GPRRegisterClass && RC != ARM::rGPRRegisterClass) - return std::make_pair(RC->allocation_order_begin(MF), - RC->allocation_order_end(MF)); + return RC->getRawAllocationOrder(MF); if (HintType == ARMRI::RegPairEven) { if (isPhysicalRegister(HintReg) && getRegisterPairEven(HintReg, MF) == 0) // It's no longer possible to fulfill this hint. Return the default // allocation order. - return std::make_pair(RC->allocation_order_begin(MF), - RC->allocation_order_end(MF)); + return RC->getRawAllocationOrder(MF); if (!TFI->hasFP(MF)) { if (!STI.isR9Reserved()) - return std::make_pair(GPREven1, - GPREven1 + (sizeof(GPREven1)/sizeof(unsigned))); + return ArrayRef<unsigned>(GPREven1); else - return std::make_pair(GPREven4, - GPREven4 + (sizeof(GPREven4)/sizeof(unsigned))); + return ArrayRef<unsigned>(GPREven4); } else if (FramePtr == ARM::R7) { if (!STI.isR9Reserved()) - return std::make_pair(GPREven2, - GPREven2 + (sizeof(GPREven2)/sizeof(unsigned))); + return ArrayRef<unsigned>(GPREven2); else - return std::make_pair(GPREven5, - GPREven5 + (sizeof(GPREven5)/sizeof(unsigned))); + return ArrayRef<unsigned>(GPREven5); } else { // FramePtr == ARM::R11 if (!STI.isR9Reserved()) - return std::make_pair(GPREven3, - GPREven3 + (sizeof(GPREven3)/sizeof(unsigned))); + return ArrayRef<unsigned>(GPREven3); else - return std::make_pair(GPREven6, - GPREven6 + (sizeof(GPREven6)/sizeof(unsigned))); + return ArrayRef<unsigned>(GPREven6); } } else if (HintType == ARMRI::RegPairOdd) { if (isPhysicalRegister(HintReg) && getRegisterPairOdd(HintReg, MF) == 0) // It's no longer possible to fulfill this hint. Return the default // allocation order. - return std::make_pair(RC->allocation_order_begin(MF), - RC->allocation_order_end(MF)); + return RC->getRawAllocationOrder(MF); if (!TFI->hasFP(MF)) { if (!STI.isR9Reserved()) - return std::make_pair(GPROdd1, - GPROdd1 + (sizeof(GPROdd1)/sizeof(unsigned))); + return ArrayRef<unsigned>(GPROdd1); else - return std::make_pair(GPROdd4, - GPROdd4 + (sizeof(GPROdd4)/sizeof(unsigned))); + return ArrayRef<unsigned>(GPROdd4); } else if (FramePtr == ARM::R7) { if (!STI.isR9Reserved()) - return std::make_pair(GPROdd2, - GPROdd2 + (sizeof(GPROdd2)/sizeof(unsigned))); + return ArrayRef<unsigned>(GPROdd2); else - return std::make_pair(GPROdd5, - GPROdd5 + (sizeof(GPROdd5)/sizeof(unsigned))); + return ArrayRef<unsigned>(GPROdd5); } else { // FramePtr == ARM::R11 if (!STI.isR9Reserved()) - return std::make_pair(GPROdd3, - GPROdd3 + (sizeof(GPROdd3)/sizeof(unsigned))); + return ArrayRef<unsigned>(GPROdd3); else - return std::make_pair(GPROdd6, - GPROdd6 + (sizeof(GPROdd6)/sizeof(unsigned))); + return ArrayRef<unsigned>(GPROdd6); } } - return std::make_pair(RC->allocation_order_begin(MF), - RC->allocation_order_end(MF)); + return RC->getRawAllocationOrder(MF); } /// ResolveRegAllocHint - Resolves the specified register allocation hint @@ -965,7 +957,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, int64_t ARMBaseRegisterInfo:: getFrameIndexInstrOffset(const MachineInstr *MI, int Idx) const { - const TargetInstrDesc &Desc = MI->getDesc(); + const MCInstrDesc &Desc = MI->getDesc(); unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); int64_t InstrOffs = 0;; int Scale = 1; @@ -1115,11 +1107,11 @@ materializeFrameBaseRegister(MachineBasicBlock *MBB, if (Ins != MBB->end()) DL = Ins->getDebugLoc(); - const TargetInstrDesc &TID = TII.get(ADDriOpc); + const MCInstrDesc &MCID = TII.get(ADDriOpc); MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo(); - MRI.constrainRegClass(BaseReg, TID.OpInfo[0].getRegClass(this)); + MRI.constrainRegClass(BaseReg, TII.getRegClass(MCID, 0, this)); - MachineInstrBuilder MIB = BuildMI(*MBB, Ins, DL, TID, BaseReg) + MachineInstrBuilder MIB = BuildMI(*MBB, Ins, DL, MCID, BaseReg) .addFrameIndex(FrameIdx).addImm(Offset); if (!AFI->isThumb1OnlyFunction()) @@ -1155,7 +1147,7 @@ ARMBaseRegisterInfo::resolveFrameIndex(MachineBasicBlock::iterator I, bool ARMBaseRegisterInfo::isFrameOffsetLegal(const MachineInstr *MI, int64_t Offset) const { - const TargetInstrDesc &Desc = MI->getDesc(); + const MCInstrDesc &Desc = MI->getDesc(); unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); unsigned i = 0; @@ -1291,11 +1283,5 @@ ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, } // Update the original instruction to use the scratch register. MI.getOperand(i).ChangeToRegister(ScratchReg, false, false, true); - if (MI.getOpcode() == ARM::t2ADDrSPi) - MI.setDesc(TII.get(ARM::t2ADDri)); - else if (MI.getOpcode() == ARM::t2SUBrSPi) - MI.setDesc(TII.get(ARM::t2SUBri)); } } - -#include "ARMGenRegisterInfo.inc" diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.h b/lib/Target/ARM/ARMBaseRegisterInfo.h index c60d75a6893d..b4b4059e7361 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.h +++ b/lib/Target/ARM/ARMBaseRegisterInfo.h @@ -16,7 +16,9 @@ #include "ARM.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "ARMGenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "ARMGenRegisterInfo.inc" namespace llvm { class ARMSubtarget; @@ -134,10 +136,9 @@ public: unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const; - std::pair<TargetRegisterClass::iterator,TargetRegisterClass::iterator> - getAllocationOrder(const TargetRegisterClass *RC, - unsigned HintType, unsigned HintReg, - const MachineFunction &MF) const; + ArrayRef<unsigned> getRawAllocationOrder(const TargetRegisterClass *RC, + unsigned HintType, unsigned HintReg, + const MachineFunction &MF) const; unsigned ResolveRegAllocHint(unsigned Type, unsigned Reg, const MachineFunction &MF) const; diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 16d4ca599a06..d6fca6277501 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -96,13 +96,13 @@ namespace { void addPCLabel(unsigned LabelID); void emitPseudoInstruction(const MachineInstr &MI); unsigned getMachineSoRegOpValue(const MachineInstr &MI, - const TargetInstrDesc &TID, + const MCInstrDesc &MCID, const MachineOperand &MO, unsigned OpIdx); unsigned getMachineSoImmOpValue(unsigned SoImm); unsigned getAddrModeSBit(const MachineInstr &MI, - const TargetInstrDesc &TID) const; + const MCInstrDesc &MCID) const; void emitDataProcessingInstruction(const MachineInstr &MI, unsigned ImplicitRd = 0, @@ -443,9 +443,9 @@ unsigned ARMCodeEmitter::getMachineOpValue(const MachineInstr &MI, else if (MO.isSymbol()) emitExternalSymbolAddress(MO.getSymbolName(), ARM::reloc_arm_branch); else if (MO.isCPI()) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); // For VFP load, the immediate offset is multiplied by 4. - unsigned Reloc = ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPLdStFrm) + unsigned Reloc = ((MCID.TSFlags & ARMII::FormMask) == ARMII::VFPLdStFrm) ? ARM::reloc_arm_vfp_cp_entry : ARM::reloc_arm_cp_entry; emitConstPoolAddress(MO.getIndex(), Reloc); } else if (MO.isJTI()) @@ -757,7 +757,7 @@ void ARMCodeEmitter::emitMOVi2piecesInstruction(const MachineInstr &MI) { void ARMCodeEmitter::emitLEApcrelJTInstruction(const MachineInstr &MI) { // It's basically add r, pc, (LJTI - $+8) - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); // Emit the 'add' instruction. unsigned Binary = 0x4 << 21; // add: Insts{24-21} = 0b0100 @@ -766,7 +766,7 @@ void ARMCodeEmitter::emitLEApcrelJTInstruction(const MachineInstr &MI) { Binary |= II->getPredicate(&MI) << ARMII::CondShift; // Encode S bit if MI modifies CPSR. - Binary |= getAddrModeSBit(MI, TID); + Binary |= getAddrModeSBit(MI, MCID); // Encode Rd. Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift; @@ -912,7 +912,7 @@ void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) { } unsigned ARMCodeEmitter::getMachineSoRegOpValue(const MachineInstr &MI, - const TargetInstrDesc &TID, + const MCInstrDesc &MCID, const MachineOperand &MO, unsigned OpIdx) { unsigned Binary = getMachineOpValue(MI, MO); @@ -982,8 +982,8 @@ unsigned ARMCodeEmitter::getMachineSoImmOpValue(unsigned SoImm) { } unsigned ARMCodeEmitter::getAddrModeSBit(const MachineInstr &MI, - const TargetInstrDesc &TID) const { - for (unsigned i = MI.getNumOperands(), e = TID.getNumOperands(); i >= e; --i){ + const MCInstrDesc &MCID) const { + for (unsigned i = MI.getNumOperands(), e = MCID.getNumOperands(); i >= e; --i){ const MachineOperand &MO = MI.getOperand(i-1); if (MO.isReg() && MO.isDef() && MO.getReg() == ARM::CPSR) return 1 << ARMII::S_BitShift; @@ -994,7 +994,7 @@ unsigned ARMCodeEmitter::getAddrModeSBit(const MachineInstr &MI, void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI, unsigned ImplicitRd, unsigned ImplicitRn) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1003,10 +1003,10 @@ void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI, Binary |= II->getPredicate(&MI) << ARMII::CondShift; // Encode S bit if MI modifies CPSR. - Binary |= getAddrModeSBit(MI, TID); + Binary |= getAddrModeSBit(MI, MCID); // Encode register def if there is one. - unsigned NumDefs = TID.getNumDefs(); + unsigned NumDefs = MCID.getNumDefs(); unsigned OpIdx = 0; if (NumDefs) Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; @@ -1014,7 +1014,7 @@ void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI, // Special handling for implicit use (e.g. PC). Binary |= (getARMRegisterNumbering(ImplicitRd) << ARMII::RegRdShift); - if (TID.Opcode == ARM::MOVi16) { + if (MCID.Opcode == ARM::MOVi16) { // Get immediate from MI. unsigned Lo16 = getMovi32Value(MI, MI.getOperand(OpIdx), ARM::reloc_arm_movw); @@ -1023,14 +1023,14 @@ void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI, Binary |= ((Lo16 >> 12) & 0xF) << 16; emitWordLE(Binary); return; - } else if(TID.Opcode == ARM::MOVTi16) { + } else if(MCID.Opcode == ARM::MOVTi16) { unsigned Hi16 = (getMovi32Value(MI, MI.getOperand(OpIdx), ARM::reloc_arm_movt) >> 16); Binary |= Hi16 & 0xFFF; Binary |= ((Hi16 >> 12) & 0xF) << 16; emitWordLE(Binary); return; - } else if ((TID.Opcode == ARM::BFC) || (TID.Opcode == ARM::BFI)) { + } else if ((MCID.Opcode == ARM::BFC) || (MCID.Opcode == ARM::BFI)) { uint32_t v = ~MI.getOperand(2).getImm(); int32_t lsb = CountTrailingZeros_32(v); int32_t msb = (32 - CountLeadingZeros_32(v)) - 1; @@ -1039,7 +1039,7 @@ void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI, Binary |= (lsb & 0x1F) << 7; emitWordLE(Binary); return; - } else if ((TID.Opcode == ARM::UBFX) || (TID.Opcode == ARM::SBFX)) { + } else if ((MCID.Opcode == ARM::UBFX) || (MCID.Opcode == ARM::SBFX)) { // Encode Rn in Instr{0-3} Binary |= getMachineOpValue(MI, OpIdx++); @@ -1054,11 +1054,11 @@ void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI, } // If this is a two-address operand, skip it. e.g. MOVCCr operand 1. - if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) ++OpIdx; // Encode first non-shifter register operand if there is one. - bool isUnary = TID.TSFlags & ARMII::UnaryDP; + bool isUnary = MCID.TSFlags & ARMII::UnaryDP; if (!isUnary) { if (ImplicitRn) // Special handling for implicit use (e.g. PC). @@ -1071,9 +1071,9 @@ void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI, // Encode shifter operand. const MachineOperand &MO = MI.getOperand(OpIdx); - if ((TID.TSFlags & ARMII::FormMask) == ARMII::DPSoRegFrm) { + if ((MCID.TSFlags & ARMII::FormMask) == ARMII::DPSoRegFrm) { // Encode SoReg. - emitWordLE(Binary | getMachineSoRegOpValue(MI, TID, MO, OpIdx)); + emitWordLE(Binary | getMachineSoRegOpValue(MI, MCID, MO, OpIdx)); return; } @@ -1092,9 +1092,9 @@ void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI, void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI, unsigned ImplicitRd, unsigned ImplicitRn) { - const TargetInstrDesc &TID = MI.getDesc(); - unsigned Form = TID.TSFlags & ARMII::FormMask; - bool IsPrePost = (TID.TSFlags & ARMII::IndexModeMask) != 0; + const MCInstrDesc &MCID = MI.getDesc(); + unsigned Form = MCID.TSFlags & ARMII::FormMask; + bool IsPrePost = (MCID.TSFlags & ARMII::IndexModeMask) != 0; // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1134,7 +1134,7 @@ void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI, Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift; // If this is a two-address operand, skip it. e.g. LDR_PRE. - if (!Skipped && TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + if (!Skipped && MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) ++OpIdx; const MachineOperand &MO2 = MI.getOperand(OpIdx); @@ -1170,9 +1170,9 @@ void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI, void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI, unsigned ImplicitRn) { - const TargetInstrDesc &TID = MI.getDesc(); - unsigned Form = TID.TSFlags & ARMII::FormMask; - bool IsPrePost = (TID.TSFlags & ARMII::IndexModeMask) != 0; + const MCInstrDesc &MCID = MI.getDesc(); + unsigned Form = MCID.TSFlags & ARMII::FormMask; + bool IsPrePost = (MCID.TSFlags & ARMII::IndexModeMask) != 0; // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1194,7 +1194,7 @@ void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI, Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; // Skip LDRD and STRD's second operand. - if (TID.Opcode == ARM::LDRD || TID.Opcode == ARM::STRD) + if (MCID.Opcode == ARM::LDRD || MCID.Opcode == ARM::STRD) ++OpIdx; // Set second operand @@ -1205,7 +1205,7 @@ void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI, Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift; // If this is a two-address operand, skip it. e.g. LDRH_POST. - if (!Skipped && TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + if (!Skipped && MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) ++OpIdx; const MachineOperand &MO2 = MI.getOperand(OpIdx); @@ -1255,8 +1255,8 @@ static unsigned getAddrModeUPBits(unsigned Mode) { } void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); - bool IsUpdating = (TID.TSFlags & ARMII::IndexModeMask) != 0; + const MCInstrDesc &MCID = MI.getDesc(); + bool IsUpdating = (MCID.TSFlags & ARMII::IndexModeMask) != 0; // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1295,7 +1295,7 @@ void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) { } void ARMCodeEmitter::emitMulFrmInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1304,12 +1304,12 @@ void ARMCodeEmitter::emitMulFrmInstruction(const MachineInstr &MI) { Binary |= II->getPredicate(&MI) << ARMII::CondShift; // Encode S bit if MI modifies CPSR. - Binary |= getAddrModeSBit(MI, TID); + Binary |= getAddrModeSBit(MI, MCID); // 32x32->64bit operations have two destination registers. The number // of register definitions will tell us if that's what we're dealing with. unsigned OpIdx = 0; - if (TID.getNumDefs() == 2) + if (MCID.getNumDefs() == 2) Binary |= getMachineOpValue (MI, OpIdx++) << ARMII::RegRdLoShift; // Encode Rd @@ -1323,16 +1323,16 @@ void ARMCodeEmitter::emitMulFrmInstruction(const MachineInstr &MI) { // Many multiple instructions (e.g. MLA) have three src operands. Encode // it as Rn (for multiply, that's in the same offset as RdLo. - if (TID.getNumOperands() > OpIdx && - !TID.OpInfo[OpIdx].isPredicate() && - !TID.OpInfo[OpIdx].isOptionalDef()) + if (MCID.getNumOperands() > OpIdx && + !MCID.OpInfo[OpIdx].isPredicate() && + !MCID.OpInfo[OpIdx].isOptionalDef()) Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRdLoShift; emitWordLE(Binary); } void ARMCodeEmitter::emitExtendInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1361,15 +1361,15 @@ void ARMCodeEmitter::emitExtendInstruction(const MachineInstr &MI) { // Encode rot imm (0, 8, 16, or 24) if it has a rotate immediate operand. if (MI.getOperand(OpIdx).isImm() && - !TID.OpInfo[OpIdx].isPredicate() && - !TID.OpInfo[OpIdx].isOptionalDef()) + !MCID.OpInfo[OpIdx].isPredicate() && + !MCID.OpInfo[OpIdx].isOptionalDef()) Binary |= (getMachineOpValue(MI, OpIdx) / 8) << ARMII::ExtRotImmShift; emitWordLE(Binary); } void ARMCodeEmitter::emitMiscArithInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1378,7 +1378,7 @@ void ARMCodeEmitter::emitMiscArithInstruction(const MachineInstr &MI) { Binary |= II->getPredicate(&MI) << ARMII::CondShift; // PKH instructions are finished at this point - if (TID.Opcode == ARM::PKHBT || TID.Opcode == ARM::PKHTB) { + if (MCID.Opcode == ARM::PKHBT || MCID.Opcode == ARM::PKHTB) { emitWordLE(Binary); return; } @@ -1389,9 +1389,9 @@ void ARMCodeEmitter::emitMiscArithInstruction(const MachineInstr &MI) { Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; const MachineOperand &MO = MI.getOperand(OpIdx++); - if (OpIdx == TID.getNumOperands() || - TID.OpInfo[OpIdx].isPredicate() || - TID.OpInfo[OpIdx].isOptionalDef()) { + if (OpIdx == MCID.getNumOperands() || + MCID.OpInfo[OpIdx].isPredicate() || + MCID.OpInfo[OpIdx].isOptionalDef()) { // Encode Rm and it's done. Binary |= getMachineOpValue(MI, MO); emitWordLE(Binary); @@ -1406,7 +1406,7 @@ void ARMCodeEmitter::emitMiscArithInstruction(const MachineInstr &MI) { // Encode shift_imm. unsigned ShiftAmt = MI.getOperand(OpIdx).getImm(); - if (TID.Opcode == ARM::PKHTB) { + if (MCID.Opcode == ARM::PKHTB) { assert(ShiftAmt != 0 && "PKHTB shift_imm is 0!"); if (ShiftAmt == 32) ShiftAmt = 0; @@ -1418,7 +1418,7 @@ void ARMCodeEmitter::emitMiscArithInstruction(const MachineInstr &MI) { } void ARMCodeEmitter::emitSaturateInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); // Part of binary is determined by TableGen. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1431,11 +1431,11 @@ void ARMCodeEmitter::emitSaturateInstruction(const MachineInstr &MI) { // Encode saturate bit position. unsigned Pos = MI.getOperand(1).getImm(); - if (TID.Opcode == ARM::SSAT || TID.Opcode == ARM::SSAT16) + if (MCID.Opcode == ARM::SSAT || MCID.Opcode == ARM::SSAT16) Pos -= 1; assert((Pos < 16 || (Pos < 32 && - TID.Opcode != ARM::SSAT16 && - TID.Opcode != ARM::USAT16)) && + MCID.Opcode != ARM::SSAT16 && + MCID.Opcode != ARM::USAT16)) && "saturate bit position out of range"); Binary |= Pos << 16; @@ -1443,7 +1443,7 @@ void ARMCodeEmitter::emitSaturateInstruction(const MachineInstr &MI) { Binary |= getMachineOpValue(MI, 2); // Encode shift_imm. - if (TID.getNumOperands() == 4) { + if (MCID.getNumOperands() == 4) { unsigned ShiftOp = MI.getOperand(3).getImm(); ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp); if (Opc == ARM_AM::asr) @@ -1459,9 +1459,9 @@ void ARMCodeEmitter::emitSaturateInstruction(const MachineInstr &MI) { } void ARMCodeEmitter::emitBranchInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); - if (TID.Opcode == ARM::TPsoft) { + if (MCID.Opcode == ARM::TPsoft) { llvm_unreachable("ARM::TPsoft FIXME"); // FIXME } @@ -1498,20 +1498,20 @@ void ARMCodeEmitter::emitInlineJumpTable(unsigned JTIndex) { } void ARMCodeEmitter::emitMiscBranchInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); // Handle jump tables. - if (TID.Opcode == ARM::BR_JTr || TID.Opcode == ARM::BR_JTadd) { + if (MCID.Opcode == ARM::BR_JTr || MCID.Opcode == ARM::BR_JTadd) { // First emit a ldr pc, [] instruction. emitDataProcessingInstruction(MI, ARM::PC); // Then emit the inline jump table. unsigned JTIndex = - (TID.Opcode == ARM::BR_JTr) + (MCID.Opcode == ARM::BR_JTr) ? MI.getOperand(1).getIndex() : MI.getOperand(2).getIndex(); emitInlineJumpTable(JTIndex); return; - } else if (TID.Opcode == ARM::BR_JTm) { + } else if (MCID.Opcode == ARM::BR_JTm) { // First emit a ldr pc, [] instruction. emitLoadStoreInstruction(MI, ARM::PC); @@ -1526,7 +1526,7 @@ void ARMCodeEmitter::emitMiscBranchInstruction(const MachineInstr &MI) { // Set the conditional execution predicate Binary |= II->getPredicate(&MI) << ARMII::CondShift; - if (TID.Opcode == ARM::BX_RET || TID.Opcode == ARM::MOVPCLR) + if (MCID.Opcode == ARM::BX_RET || MCID.Opcode == ARM::MOVPCLR) // The return register is LR. Binary |= getARMRegisterNumbering(ARM::LR); else @@ -1579,7 +1579,7 @@ static unsigned encodeVFPRm(const MachineInstr &MI, unsigned OpIdx) { } void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1596,16 +1596,16 @@ void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) { Binary |= encodeVFPRd(MI, OpIdx++); // If this is a two-address operand, skip it, e.g. FMACD. - if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) ++OpIdx; // Encode Dn / Sn. - if ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPBinaryFrm) + if ((MCID.TSFlags & ARMII::FormMask) == ARMII::VFPBinaryFrm) Binary |= encodeVFPRn(MI, OpIdx++); - if (OpIdx == TID.getNumOperands() || - TID.OpInfo[OpIdx].isPredicate() || - TID.OpInfo[OpIdx].isOptionalDef()) { + if (OpIdx == MCID.getNumOperands() || + MCID.OpInfo[OpIdx].isPredicate() || + MCID.OpInfo[OpIdx].isOptionalDef()) { // FCMPEZD etc. has only one operand. emitWordLE(Binary); return; @@ -1618,8 +1618,8 @@ void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) { } void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); - unsigned Form = TID.TSFlags & ARMII::FormMask; + const MCInstrDesc &MCID = MI.getDesc(); + unsigned Form = MCID.TSFlags & ARMII::FormMask; // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1709,8 +1709,8 @@ void ARMCodeEmitter::emitVFPLoadStoreInstruction(const MachineInstr &MI) { void ARMCodeEmitter::emitVFPLoadStoreMultipleInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); - bool IsUpdating = (TID.TSFlags & ARMII::IndexModeMask) != 0; + const MCInstrDesc &MCID = MI.getDesc(); + bool IsUpdating = (MCID.TSFlags & ARMII::IndexModeMask) != 0; // Part of binary is determined by TableGn. unsigned Binary = getBinaryCodeForInstr(MI); @@ -1795,8 +1795,8 @@ void ARMCodeEmitter::emitNEONLaneInstruction(const MachineInstr &MI) { unsigned Binary = getBinaryCodeForInstr(MI); unsigned RegTOpIdx, RegNOpIdx, LnOpIdx; - const TargetInstrDesc &TID = MI.getDesc(); - if ((TID.TSFlags & ARMII::FormMask) == ARMII::NGetLnFrm) { + const MCInstrDesc &MCID = MI.getDesc(); + if ((MCID.TSFlags & ARMII::FormMask) == ARMII::NGetLnFrm) { RegTOpIdx = 0; RegNOpIdx = 1; LnOpIdx = 2; @@ -1863,12 +1863,12 @@ void ARMCodeEmitter::emitNEON1RegModImmInstruction(const MachineInstr &MI) { } void ARMCodeEmitter::emitNEON2RegInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); unsigned Binary = getBinaryCodeForInstr(MI); // Destination register is encoded in Dd; source register in Dm. unsigned OpIdx = 0; Binary |= encodeNEONRd(MI, OpIdx++); - if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) ++OpIdx; Binary |= encodeNEONRm(MI, OpIdx); if (IsThumb) @@ -1878,15 +1878,15 @@ void ARMCodeEmitter::emitNEON2RegInstruction(const MachineInstr &MI) { } void ARMCodeEmitter::emitNEON3RegInstruction(const MachineInstr &MI) { - const TargetInstrDesc &TID = MI.getDesc(); + const MCInstrDesc &MCID = MI.getDesc(); unsigned Binary = getBinaryCodeForInstr(MI); // Destination register is encoded in Dd; source registers in Dn and Dm. unsigned OpIdx = 0; Binary |= encodeNEONRd(MI, OpIdx++); - if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) ++OpIdx; Binary |= encodeNEONRn(MI, OpIdx++); - if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) ++OpIdx; Binary |= encodeNEONRm(MI, OpIdx); if (IsThumb) diff --git a/lib/Target/ARM/ARMConstantIslandPass.cpp b/lib/Target/ARM/ARMConstantIslandPass.cpp index baf95a33dd4b..f45ebdc53500 100644 --- a/lib/Target/ARM/ARMConstantIslandPass.cpp +++ b/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -1538,7 +1538,10 @@ bool ARMConstantIslands::UndoLRSpillRestore() { if (MI->getOpcode() == ARM::tPOP_RET && MI->getOperand(2).getReg() == ARM::PC && MI->getNumExplicitOperands() == 3) { - BuildMI(MI->getParent(), MI->getDebugLoc(), TII->get(ARM::tBX_RET)); + // Create the new insn and copy the predicate from the old. + BuildMI(MI->getParent(), MI->getDebugLoc(), TII->get(ARM::tBX_RET)) + .addOperand(MI->getOperand(0)) + .addOperand(MI->getOperand(1)); MI->eraseFromParent(); MadeChange = true; } @@ -1692,9 +1695,9 @@ bool ARMConstantIslands::OptimizeThumb2JumpTables(MachineFunction &MF) { const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); for (unsigned i = 0, e = T2JumpTables.size(); i != e; ++i) { MachineInstr *MI = T2JumpTables[i]; - const TargetInstrDesc &TID = MI->getDesc(); - unsigned NumOps = TID.getNumOperands(); - unsigned JTOpIdx = NumOps - (TID.isPredicable() ? 3 : 2); + const MCInstrDesc &MCID = MI->getDesc(); + unsigned NumOps = MCID.getNumOperands(); + unsigned JTOpIdx = NumOps - (MCID.isPredicable() ? 3 : 2); MachineOperand JTOP = MI->getOperand(JTOpIdx); unsigned JTI = JTOP.getIndex(); assert(JTI < JT.size()); @@ -1815,9 +1818,9 @@ bool ARMConstantIslands::ReorderThumb2JumpTables(MachineFunction &MF) { const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); for (unsigned i = 0, e = T2JumpTables.size(); i != e; ++i) { MachineInstr *MI = T2JumpTables[i]; - const TargetInstrDesc &TID = MI->getDesc(); - unsigned NumOps = TID.getNumOperands(); - unsigned JTOpIdx = NumOps - (TID.isPredicable() ? 3 : 2); + const MCInstrDesc &MCID = MI->getDesc(); + unsigned NumOps = MCID.getNumOperands(); + unsigned JTOpIdx = NumOps - (MCID.isPredicable() ? 3 : 2); MachineOperand JTOP = MI->getOperand(JTOpIdx); unsigned JTI = JTOP.getIndex(); assert(JTI < JT.size()); diff --git a/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/lib/Target/ARM/ARMExpandPseudoInsts.cpp index b6b3c75943b5..94b72fdb9a7e 100644 --- a/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -68,7 +68,7 @@ namespace { void ARMExpandPseudo::TransferImpOps(MachineInstr &OldMI, MachineInstrBuilder &UseMI, MachineInstrBuilder &DefMI) { - const TargetInstrDesc &Desc = OldMI.getDesc(); + const MCInstrDesc &Desc = OldMI.getDesc(); for (unsigned i = Desc.getNumOperands(), e = OldMI.getNumOperands(); i != e; ++i) { const MachineOperand &MO = OldMI.getOperand(i); @@ -727,8 +727,10 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, MI.eraseFromParent(); return true; } + case ARM::t2MOVCCr: case ARM::MOVCCr: { - BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVr), + unsigned Opc = AFI->isThumbFunction() ? ARM::t2MOVr : ARM::MOVr; + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc), MI.getOperand(1).getReg()) .addReg(MI.getOperand(2).getReg(), getKillRegState(MI.getOperand(2).isKill())) @@ -764,8 +766,10 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, MI.eraseFromParent(); return true; } + case ARM::t2MOVCCi: case ARM::MOVCCi: { - BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVi), + unsigned Opc = AFI->isThumbFunction() ? ARM::t2MOVi : ARM::MOVi; + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc), MI.getOperand(1).getReg()) .addImm(MI.getOperand(2).getImm()) .addImm(MI.getOperand(3).getImm()) // 'pred' @@ -837,8 +841,9 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, MI.getOperand(0).getReg()) .addOperand(MI.getOperand(1)) .addReg(0) - .addImm(ARM_AM::getSORegOpc((Opcode == ARM::MOVsrl_flag ? ARM_AM::lsr - : ARM_AM::asr), 1))) + .addImm(ARM_AM::getSORegOpc((Opcode == ARM::MOVsrl_flag ? + ARM_AM::lsr : ARM_AM::asr), + 1))) .addReg(ARM::CPSR, RegState::Define); MI.eraseFromParent(); return true; @@ -856,10 +861,11 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, MI.eraseFromParent(); return true; } + case ARM::tTPsoft: case ARM::TPsoft: { MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), - TII->get(ARM::BL)) + TII->get(Opcode == ARM::tTPsoft ? ARM::tBL : ARM::BL)) .addExternalSymbol("__aeabi_read_tp", 0); MIB->setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); @@ -900,10 +906,10 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, const MachineOperand &MO1 = MI.getOperand(1); const GlobalValue *GV = MO1.getGlobal(); unsigned TF = MO1.getTargetFlags(); - bool isARM = (Opcode != ARM::t2MOV_ga_pcrel && Opcode != ARM::t2MOV_ga_dyn); + bool isARM = (Opcode != ARM::t2MOV_ga_pcrel && Opcode!=ARM::t2MOV_ga_dyn); bool isPIC = (Opcode != ARM::MOV_ga_dyn && Opcode != ARM::t2MOV_ga_dyn); unsigned LO16Opc = isARM ? ARM::MOVi16_ga_pcrel : ARM::t2MOVi16_ga_pcrel; - unsigned HI16Opc = isARM ? ARM::MOVTi16_ga_pcrel : ARM::t2MOVTi16_ga_pcrel; + unsigned HI16Opc = isARM ? ARM::MOVTi16_ga_pcrel :ARM::t2MOVTi16_ga_pcrel; unsigned LO16TF = isPIC ? ARMII::MO_LO16_NONLAZY_PIC : ARMII::MO_LO16_NONLAZY; unsigned HI16TF = isPIC @@ -958,15 +964,17 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, unsigned OddSrc = TRI->getSubReg(SrcReg, ARM::qsub_1); MachineInstrBuilder Even = AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), - TII->get(ARM::VMOVQ)) + TII->get(ARM::VORRq)) .addReg(EvenDst, RegState::Define | getDeadRegState(DstIsDead)) + .addReg(EvenSrc, getKillRegState(SrcIsKill)) .addReg(EvenSrc, getKillRegState(SrcIsKill))); MachineInstrBuilder Odd = AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), - TII->get(ARM::VMOVQ)) + TII->get(ARM::VORRq)) .addReg(OddDst, RegState::Define | getDeadRegState(DstIsDead)) + .addReg(OddSrc, getKillRegState(SrcIsKill)) .addReg(OddSrc, getKillRegState(SrcIsKill))); TransferImpOps(MI, Even, Odd); MI.eraseFromParent(); diff --git a/lib/Target/ARM/ARMFastISel.cpp b/lib/Target/ARM/ARMFastISel.cpp index 5cf73c479a33..f469d7efe11a 100644 --- a/lib/Target/ARM/ARMFastISel.cpp +++ b/lib/Target/ARM/ARMFastISel.cpp @@ -219,8 +219,8 @@ class ARMFastISel : public FastISel { // we don't care about implicit defs here, just places we'll need to add a // default CCReg argument. Sets CPSR if we're setting CPSR instead of CCR. bool ARMFastISel::DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR) { - const TargetInstrDesc &TID = MI->getDesc(); - if (!TID.hasOptionalDef()) + const MCInstrDesc &MCID = MI->getDesc(); + if (!MCID.hasOptionalDef()) return false; // Look to see if our OptionalDef is defining CPSR or CCR. @@ -234,15 +234,15 @@ bool ARMFastISel::DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR) { } bool ARMFastISel::isARMNEONPred(const MachineInstr *MI) { - const TargetInstrDesc &TID = MI->getDesc(); + const MCInstrDesc &MCID = MI->getDesc(); // If we're a thumb2 or not NEON function we were handled via isPredicable. - if ((TID.TSFlags & ARMII::DomainMask) != ARMII::DomainNEON || + if ((MCID.TSFlags & ARMII::DomainMask) != ARMII::DomainNEON || AFI->isThumb2Function()) return false; - for (unsigned i = 0, e = TID.getNumOperands(); i != e; ++i) - if (TID.OpInfo[i].isPredicate()) + for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i) + if (MCID.OpInfo[i].isPredicate()) return true; return false; @@ -278,7 +278,7 @@ ARMFastISel::AddOptionalDefs(const MachineInstrBuilder &MIB) { unsigned ARMFastISel::FastEmitInst_(unsigned MachineInstOpcode, const TargetRegisterClass* RC) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)); return ResultReg; @@ -288,7 +288,7 @@ unsigned ARMFastISel::FastEmitInst_r(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -308,7 +308,7 @@ unsigned ARMFastISel::FastEmitInst_rr(unsigned MachineInstOpcode, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -331,7 +331,7 @@ unsigned ARMFastISel::FastEmitInst_rrr(unsigned MachineInstOpcode, unsigned Op1, bool Op1IsKill, unsigned Op2, bool Op2IsKill) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -355,7 +355,7 @@ unsigned ARMFastISel::FastEmitInst_ri(unsigned MachineInstOpcode, unsigned Op0, bool Op0IsKill, uint64_t Imm) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -377,7 +377,7 @@ unsigned ARMFastISel::FastEmitInst_rf(unsigned MachineInstOpcode, unsigned Op0, bool Op0IsKill, const ConstantFP *FPImm) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -400,7 +400,7 @@ unsigned ARMFastISel::FastEmitInst_rri(unsigned MachineInstOpcode, unsigned Op1, bool Op1IsKill, uint64_t Imm) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -423,7 +423,7 @@ unsigned ARMFastISel::FastEmitInst_i(unsigned MachineInstOpcode, const TargetRegisterClass *RC, uint64_t Imm) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -442,7 +442,7 @@ unsigned ARMFastISel::FastEmitInst_ii(unsigned MachineInstOpcode, const TargetRegisterClass *RC, uint64_t Imm1, uint64_t Imm2) { unsigned ResultReg = createResultReg(RC); - const TargetInstrDesc &II = TII.get(MachineInstOpcode); + const MCInstrDesc &II = TII.get(MachineInstOpcode); if (II.getNumDefs() >= 1) AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) @@ -1549,7 +1549,7 @@ bool ARMFastISel::ProcessCallArgs(SmallVectorImpl<Value*> &Args, NumBytes = CCInfo.getNextStackOffset(); // Issue CALLSEQ_START - unsigned AdjStackDown = TM.getRegisterInfo()->getCallFrameSetupOpcode(); + unsigned AdjStackDown = TII.getCallFrameSetupOpcode(); AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(AdjStackDown)) .addImm(NumBytes)); @@ -1647,7 +1647,7 @@ bool ARMFastISel::FinishCall(MVT RetVT, SmallVectorImpl<unsigned> &UsedRegs, const Instruction *I, CallingConv::ID CC, unsigned &NumBytes) { // Issue CALLSEQ_END - unsigned AdjStackUp = TM.getRegisterInfo()->getCallFrameDestroyOpcode(); + unsigned AdjStackUp = TII.getCallFrameDestroyOpcode(); AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(AdjStackUp)) .addImm(NumBytes).addImm(0)); diff --git a/lib/Target/ARM/ARMFrameLowering.cpp b/lib/Target/ARM/ARMFrameLowering.cpp index e2e95d47b37b..381b404519e2 100644 --- a/lib/Target/ARM/ARMFrameLowering.cpp +++ b/lib/Target/ARM/ARMFrameLowering.cpp @@ -268,14 +268,14 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const { // bic r4, r4, MaxAlign // mov sp, r4 // FIXME: It will be better just to find spare register here. - BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2tgpr), ARM::R4) - .addReg(ARM::SP, RegState::Kill); + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::R4) + .addReg(ARM::SP, RegState::Kill)); AddDefaultCC(AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::t2BICri), ARM::R4) .addReg(ARM::R4, RegState::Kill) .addImm(MaxAlign-1))); - BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP) - .addReg(ARM::R4, RegState::Kill); + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP) + .addReg(ARM::R4, RegState::Kill)); } AFI->setShouldRestoreSPFromFP(true); @@ -293,9 +293,9 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const { .addReg(ARM::SP) .addImm((unsigned)ARMCC::AL).addReg(0).addReg(0); else - BuildMI(MBB, MBBI, dl, - TII.get(ARM::tMOVgpr2gpr), RegInfo->getBaseRegister()) - .addReg(ARM::SP); + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), + RegInfo->getBaseRegister()) + .addReg(ARM::SP)); } // If the frame has variable sized objects then the epilogue must restore @@ -364,8 +364,9 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF, "No scratch register to restore SP from FP!"); emitT2RegPlusImmediate(MBB, MBBI, dl, ARM::R4, FramePtr, -NumBytes, ARMCC::AL, 0, TII); - BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), ARM::SP) - .addReg(ARM::R4); + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), + ARM::SP) + .addReg(ARM::R4)); } } else { // Thumb2 or ARM. @@ -373,8 +374,9 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF, BuildMI(MBB, MBBI, dl, TII.get(ARM::MOVr), ARM::SP) .addReg(FramePtr).addImm((unsigned)ARMCC::AL).addReg(0).addReg(0); else - BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), ARM::SP) - .addReg(FramePtr); + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), + ARM::SP) + .addReg(FramePtr)); } } else if (NumBytes) emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes); @@ -427,6 +429,7 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF, // Delete the pseudo instruction TCRETURN. MBB.erase(MBBI); + MBBI = NewMI; } if (VARegSaveSize) @@ -736,20 +739,52 @@ static unsigned GetFunctionSizeInBytes(const MachineFunction &MF, /// estimateStackSize - Estimate and return the size of the frame. /// FIXME: Make generic? static unsigned estimateStackSize(MachineFunction &MF) { - const MachineFrameInfo *FFI = MF.getFrameInfo(); + const MachineFrameInfo *MFI = MF.getFrameInfo(); + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo(); + unsigned MaxAlign = MFI->getMaxAlignment(); int Offset = 0; - for (int i = FFI->getObjectIndexBegin(); i != 0; ++i) { - int FixedOff = -FFI->getObjectOffset(i); + + // This code is very, very similar to PEI::calculateFrameObjectOffsets(). + // It really should be refactored to share code. Until then, changes + // should keep in mind that there's tight coupling between the two. + + for (int i = MFI->getObjectIndexBegin(); i != 0; ++i) { + int FixedOff = -MFI->getObjectOffset(i); if (FixedOff > Offset) Offset = FixedOff; } - for (unsigned i = 0, e = FFI->getObjectIndexEnd(); i != e; ++i) { - if (FFI->isDeadObjectIndex(i)) + for (unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) { + if (MFI->isDeadObjectIndex(i)) continue; - Offset += FFI->getObjectSize(i); - unsigned Align = FFI->getObjectAlignment(i); + Offset += MFI->getObjectSize(i); + unsigned Align = MFI->getObjectAlignment(i); // Adjust to alignment boundary Offset = (Offset+Align-1)/Align*Align; + + MaxAlign = std::max(Align, MaxAlign); } + + if (MFI->adjustsStack() && TFI->hasReservedCallFrame(MF)) + Offset += MFI->getMaxCallFrameSize(); + + // Round up the size to a multiple of the alignment. If the function has + // any calls or alloca's, align to the target's StackAlignment value to + // ensure that the callee's frame or the alloca data is suitably aligned; + // otherwise, for leaf functions, align to the TransientStackAlignment + // value. + unsigned StackAlign; + if (MFI->adjustsStack() || MFI->hasVarSizedObjects() || + (RegInfo->needsStackRealignment(MF) && MFI->getObjectIndexEnd() != 0)) + StackAlign = TFI->getStackAlignment(); + else + StackAlign = TFI->getTransientStackAlignment(); + + // If the frame pointer is eliminated, all frame offsets will be relative to + // SP not FP. Align to MaxAlign so this works. + StackAlign = std::max(StackAlign, MaxAlign); + unsigned AlignMask = StackAlign - 1; + Offset = (Offset + AlignMask) & ~uint64_t(AlignMask); + return (unsigned)Offset; } @@ -841,9 +876,14 @@ ARMFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, if (AFI->getVarArgsRegSaveSize() > 0) MF.getRegInfo().setPhysRegUsed(ARM::LR); - // Spill R4 if Thumb1 epilogue has to restore SP from FP since + // Spill R4 if Thumb1 epilogue has to restore SP from FP. We don't know + // for sure what the stack size will be, but for this, an estimate is good + // enough. If there anything changes it, it'll be a spill, which implies + // we've used all the registers and so R4 is already used, so not marking + // it here will be OK. // FIXME: It will be better just to find spare register here. - if (MFI->hasVarSizedObjects()) + unsigned StackSize = estimateStackSize(MF); + if (MFI->hasVarSizedObjects() || StackSize > 508) MF.getRegInfo().setPhysRegUsed(ARM::R4); } diff --git a/lib/Target/ARM/ARMGlobalMerge.cpp b/lib/Target/ARM/ARMGlobalMerge.cpp index 3f0238387a2b..8d77b2d8383e 100644 --- a/lib/Target/ARM/ARMGlobalMerge.cpp +++ b/lib/Target/ARM/ARMGlobalMerge.cpp @@ -128,10 +128,10 @@ bool ARMGlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &Globals, for (size_t i = 0, e = Globals.size(); i != e; ) { size_t j = 0; uint64_t MergedSize = 0; - std::vector<const Type*> Tys; + std::vector<Type*> Tys; std::vector<Constant*> Inits; for (j = i; j != e; ++j) { - const Type *Ty = Globals[j]->getType()->getElementType(); + Type *Ty = Globals[j]->getType()->getElementType(); MergedSize += TD->getTypeAllocSize(Ty); if (MergedSize > MaxOffset) { break; @@ -175,7 +175,9 @@ bool ARMGlobalMerge::doInitialization(Module &M) { continue; // Ignore fancy-aligned globals for now. - if (I->getAlignment() != 0) + unsigned Alignment = I->getAlignment(); + const Type *Ty = I->getType()->getElementType(); + if (Alignment > TD->getABITypeAlignment(Ty)) continue; // Ignore all 'special' globals. @@ -183,7 +185,7 @@ bool ARMGlobalMerge::doInitialization(Module &M) { I->getName().startswith(".llvm.")) continue; - if (TD->getTypeAllocSize(I->getType()->getElementType()) < MaxOffset) { + if (TD->getTypeAllocSize(Ty) < MaxOffset) { const TargetLoweringObjectFile &TLOF = TLI->getObjFileLowering(); if (TLOF.getKindForGlobal(I, TLI->getTargetMachine()).isBSSLocal()) BSSGlobals.push_back(I); diff --git a/lib/Target/ARM/ARMHazardRecognizer.cpp b/lib/Target/ARM/ARMHazardRecognizer.cpp index 517bba8cee8e..787f6a279187 100644 --- a/lib/Target/ARM/ARMHazardRecognizer.cpp +++ b/lib/Target/ARM/ARMHazardRecognizer.cpp @@ -19,11 +19,11 @@ using namespace llvm; static bool hasRAWHazard(MachineInstr *DefMI, MachineInstr *MI, const TargetRegisterInfo &TRI) { // FIXME: Detect integer instructions properly. - const TargetInstrDesc &TID = MI->getDesc(); - unsigned Domain = TID.TSFlags & ARMII::DomainMask; - if (TID.mayStore()) + const MCInstrDesc &MCID = MI->getDesc(); + unsigned Domain = MCID.TSFlags & ARMII::DomainMask; + if (MCID.mayStore()) return false; - unsigned Opcode = TID.getOpcode(); + unsigned Opcode = MCID.getOpcode(); if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD) return false; if ((Domain & ARMII::DomainVFP) || (Domain & ARMII::DomainNEON)) @@ -43,15 +43,15 @@ ARMHazardRecognizer::getHazardType(SUnit *SU, int Stalls) { // Look for special VMLA / VMLS hazards. A VMUL / VADD / VSUB following // a VMLA / VMLS will cause 4 cycle stall. - const TargetInstrDesc &TID = MI->getDesc(); - if (LastMI && (TID.TSFlags & ARMII::DomainMask) != ARMII::DomainGeneral) { + const MCInstrDesc &MCID = MI->getDesc(); + if (LastMI && (MCID.TSFlags & ARMII::DomainMask) != ARMII::DomainGeneral) { MachineInstr *DefMI = LastMI; - const TargetInstrDesc &LastTID = LastMI->getDesc(); + const MCInstrDesc &LastMCID = LastMI->getDesc(); // Skip over one non-VFP / NEON instruction. - if (!LastTID.isBarrier() && + if (!LastMCID.isBarrier() && // On A9, AGU and NEON/FPU are muxed. - !(STI.isCortexA9() && (LastTID.mayLoad() || LastTID.mayStore())) && - (LastTID.TSFlags & ARMII::DomainMask) == ARMII::DomainGeneral) { + !(STI.isCortexA9() && (LastMCID.mayLoad() || LastMCID.mayStore())) && + (LastMCID.TSFlags & ARMII::DomainMask) == ARMII::DomainGeneral) { MachineBasicBlock::iterator I = LastMI; if (I != LastMI->getParent()->begin()) { I = llvm::prior(I); diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index 9ad516dafb91..2c9481b86c55 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -329,10 +329,10 @@ bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const { if (Use->getOpcode() == ISD::CopyToReg) return true; if (Use->isMachineOpcode()) { - const TargetInstrDesc &TID = TII->get(Use->getMachineOpcode()); - if (TID.mayStore()) + const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode()); + if (MCID.mayStore()) return true; - unsigned Opcode = TID.getOpcode(); + unsigned Opcode = MCID.getOpcode(); if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD) return true; // vmlx feeding into another vmlx. We actually want to unfold @@ -1354,30 +1354,34 @@ SDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) { /// SDNode *ARMDAGToDAGISel::PairSRegs(EVT VT, SDValue V0, SDValue V1) { DebugLoc dl = V0.getNode()->getDebugLoc(); + SDValue RegClass = + CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, MVT::i32); SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32); SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32); - const SDValue Ops[] = { V0, SubReg0, V1, SubReg1 }; - return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 4); + const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 }; + return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 5); } /// PairDRegs - Form a quad register from a pair of D registers. /// SDNode *ARMDAGToDAGISel::PairDRegs(EVT VT, SDValue V0, SDValue V1) { DebugLoc dl = V0.getNode()->getDebugLoc(); + SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, MVT::i32); SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32); SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32); - const SDValue Ops[] = { V0, SubReg0, V1, SubReg1 }; - return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 4); + const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 }; + return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 5); } /// PairQRegs - Form 4 consecutive D registers from a pair of Q registers. /// SDNode *ARMDAGToDAGISel::PairQRegs(EVT VT, SDValue V0, SDValue V1) { DebugLoc dl = V0.getNode()->getDebugLoc(); + SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, MVT::i32); SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32); SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32); - const SDValue Ops[] = { V0, SubReg0, V1, SubReg1 }; - return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 4); + const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 }; + return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 5); } /// QuadSRegs - Form 4 consecutive S registers. @@ -1385,12 +1389,15 @@ SDNode *ARMDAGToDAGISel::PairQRegs(EVT VT, SDValue V0, SDValue V1) { SDNode *ARMDAGToDAGISel::QuadSRegs(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3) { DebugLoc dl = V0.getNode()->getDebugLoc(); + SDValue RegClass = + CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, MVT::i32); SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32); SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32); SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, MVT::i32); SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, MVT::i32); - const SDValue Ops[] = { V0, SubReg0, V1, SubReg1, V2, SubReg2, V3, SubReg3 }; - return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 8); + const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1, + V2, SubReg2, V3, SubReg3 }; + return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 9); } /// QuadDRegs - Form 4 consecutive D registers. @@ -1398,12 +1405,14 @@ SDNode *ARMDAGToDAGISel::QuadSRegs(EVT VT, SDValue V0, SDValue V1, SDNode *ARMDAGToDAGISel::QuadDRegs(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3) { DebugLoc dl = V0.getNode()->getDebugLoc(); + SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, MVT::i32); SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32); SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32); SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, MVT::i32); SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, MVT::i32); - const SDValue Ops[] = { V0, SubReg0, V1, SubReg1, V2, SubReg2, V3, SubReg3 }; - return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 8); + const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1, + V2, SubReg2, V3, SubReg3 }; + return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 9); } /// QuadQRegs - Form 4 consecutive Q registers. @@ -1411,12 +1420,14 @@ SDNode *ARMDAGToDAGISel::QuadDRegs(EVT VT, SDValue V0, SDValue V1, SDNode *ARMDAGToDAGISel::QuadQRegs(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3) { DebugLoc dl = V0.getNode()->getDebugLoc(); + SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, MVT::i32); SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32); SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32); SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, MVT::i32); SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, MVT::i32); - const SDValue Ops[] = { V0, SubReg0, V1, SubReg1, V2, SubReg2, V3, SubReg3 }; - return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 8); + const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1, + V2, SubReg2, V3, SubReg3 }; + return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 9); } /// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 339c85886aea..cf8c5baa8e7d 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -506,6 +506,9 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) setTargetDAGCombine(ISD::VECTOR_SHUFFLE); setTargetDAGCombine(ISD::INSERT_VECTOR_ELT); setTargetDAGCombine(ISD::STORE); + setTargetDAGCombine(ISD::FP_TO_SINT); + setTargetDAGCombine(ISD::FP_TO_UINT); + setTargetDAGCombine(ISD::FDIV); } computeRegisterProperties(); @@ -538,7 +541,8 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); } - if (Subtarget->isThumb1Only() || !Subtarget->hasV6Ops()) + if (Subtarget->isThumb1Only() || !Subtarget->hasV6Ops() + || (Subtarget->isThumb2() && !Subtarget->hasThumb2DSP())) setOperationAction(ISD::MULHS, MVT::i32, Expand); setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom); @@ -704,6 +708,9 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) setOperationAction(ISD::FPOW, MVT::f64, Expand); setOperationAction(ISD::FPOW, MVT::f32, Expand); + setOperationAction(ISD::FMA, MVT::f64, Expand); + setOperationAction(ISD::FMA, MVT::f32, Expand); + // Various VFP goodness if (!UseSoftFloat && !Subtarget->isThumb1Only()) { // int <-> fp are custom expanded into bit_convert + ARMISD ops. @@ -974,12 +981,12 @@ Sched::Preference ARMTargetLowering::getSchedulingPreference(SDNode *N) const { // Load are scheduled for latency even if there instruction itinerary // is not available. const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); - const TargetInstrDesc &TID = TII->get(N->getMachineOpcode()); + const MCInstrDesc &MCID = TII->get(N->getMachineOpcode()); - if (TID.getNumDefs() == 0) + if (MCID.getNumDefs() == 0) return Sched::RegPressure; if (!Itins->isEmpty() && - Itins->getOperandCycle(TID.getSchedClass(), 0) > 2) + Itins->getOperandCycle(MCID.getSchedClass(), 0) > 2) return Sched::Latency; return Sched::RegPressure; @@ -1633,7 +1640,11 @@ ARMTargetLowering::IsEligibleForTailCallOptimization(SDValue Callee, return false; // FIXME: Completely disable sibcall for Thumb1 since Thumb1RegisterInfo:: - // emitEpilogue is not ready for them. + // emitEpilogue is not ready for them. Thumb tail calls also use t2B, as + // the Thumb1 16-bit unconditional branch doesn't have sufficient relocation + // support in the assembler and linker to be used. This would need to be + // fixed to fully support tail calls in Thumb1. + // // Doing this is tricky, since the LDM/POP instruction on Thumb doesn't take // LR. This means if we need to reload LR, it takes an extra instructions, // which outweighs the value of the tail call; but here we don't know yet @@ -2281,12 +2292,13 @@ static SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG, // ARMv7 with MP extension has PLDW. return Op.getOperand(0); - if (Subtarget->isThumb()) + unsigned isData = cast<ConstantSDNode>(Op.getOperand(4))->getZExtValue(); + if (Subtarget->isThumb()) { // Invert the bits. isRead = ~isRead & 1; - unsigned isData = Subtarget->isThumb() ? 0 : 1; + isData = ~isData & 1; + } - // Currently there is no intrinsic that matches pli. return DAG.getNode(ARMISD::PRELOAD, dl, MVT::Other, Op.getOperand(0), Op.getOperand(1), DAG.getConstant(isRead, MVT::i32), DAG.getConstant(isData, MVT::i32)); @@ -2742,7 +2754,7 @@ SDValue ARMTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const { SDValue ARMcc; SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32); SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMcc, DAG, dl); - return DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, CCR,Cmp); + return DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, CCR, Cmp); } ARMCC::CondCodes CondCode, CondCode2; @@ -5522,12 +5534,108 @@ SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, return SDValue(); } +// AddCombineToVPADDL- For pair-wise add on neon, use the vpaddl instruction +// (only after legalization). +static SDValue AddCombineToVPADDL(SDNode *N, SDValue N0, SDValue N1, + TargetLowering::DAGCombinerInfo &DCI, + const ARMSubtarget *Subtarget) { + + // Only perform optimization if after legalize, and if NEON is available. We + // also expected both operands to be BUILD_VECTORs. + if (DCI.isBeforeLegalize() || !Subtarget->hasNEON() + || N0.getOpcode() != ISD::BUILD_VECTOR + || N1.getOpcode() != ISD::BUILD_VECTOR) + return SDValue(); + + // Check output type since VPADDL operand elements can only be 8, 16, or 32. + EVT VT = N->getValueType(0); + if (!VT.isInteger() || VT.getVectorElementType() == MVT::i64) + return SDValue(); + + // Check that the vector operands are of the right form. + // N0 and N1 are BUILD_VECTOR nodes with N number of EXTRACT_VECTOR + // operands, where N is the size of the formed vector. + // Each EXTRACT_VECTOR should have the same input vector and odd or even + // index such that we have a pair wise add pattern. + + // Grab the vector that all EXTRACT_VECTOR nodes should be referencing. + if (N0->getOperand(0)->getOpcode() != ISD::EXTRACT_VECTOR_ELT) + return SDValue(); + SDValue Vec = N0->getOperand(0)->getOperand(0); + SDNode *V = Vec.getNode(); + unsigned nextIndex = 0; + + // For each operands to the ADD which are BUILD_VECTORs, + // check to see if each of their operands are an EXTRACT_VECTOR with + // the same vector and appropriate index. + for (unsigned i = 0, e = N0->getNumOperands(); i != e; ++i) { + if (N0->getOperand(i)->getOpcode() == ISD::EXTRACT_VECTOR_ELT + && N1->getOperand(i)->getOpcode() == ISD::EXTRACT_VECTOR_ELT) { + + SDValue ExtVec0 = N0->getOperand(i); + SDValue ExtVec1 = N1->getOperand(i); + + // First operand is the vector, verify its the same. + if (V != ExtVec0->getOperand(0).getNode() || + V != ExtVec1->getOperand(0).getNode()) + return SDValue(); + + // Second is the constant, verify its correct. + ConstantSDNode *C0 = dyn_cast<ConstantSDNode>(ExtVec0->getOperand(1)); + ConstantSDNode *C1 = dyn_cast<ConstantSDNode>(ExtVec1->getOperand(1)); + + // For the constant, we want to see all the even or all the odd. + if (!C0 || !C1 || C0->getZExtValue() != nextIndex + || C1->getZExtValue() != nextIndex+1) + return SDValue(); + + // Increment index. + nextIndex+=2; + } else + return SDValue(); + } + + // Create VPADDL node. + SelectionDAG &DAG = DCI.DAG; + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + + // Build operand list. + SmallVector<SDValue, 8> Ops; + Ops.push_back(DAG.getConstant(Intrinsic::arm_neon_vpaddls, + TLI.getPointerTy())); + + // Input is the vector. + Ops.push_back(Vec); + + // Get widened type and narrowed type. + MVT widenType; + unsigned numElem = VT.getVectorNumElements(); + switch (VT.getVectorElementType().getSimpleVT().SimpleTy) { + case MVT::i8: widenType = MVT::getVectorVT(MVT::i16, numElem); break; + case MVT::i16: widenType = MVT::getVectorVT(MVT::i32, numElem); break; + case MVT::i32: widenType = MVT::getVectorVT(MVT::i64, numElem); break; + default: + assert(0 && "Invalid vector element type for padd optimization."); + } + + SDValue tmp = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, N->getDebugLoc(), + widenType, &Ops[0], Ops.size()); + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, tmp); +} + /// PerformADDCombineWithOperands - Try DAG combinations for an ADD with /// operands N0 and N1. This is a helper for PerformADDCombine that is /// called with the default operands, and if that fails, with commuted /// operands. static SDValue PerformADDCombineWithOperands(SDNode *N, SDValue N0, SDValue N1, - TargetLowering::DAGCombinerInfo &DCI) { + TargetLowering::DAGCombinerInfo &DCI, + const ARMSubtarget *Subtarget){ + + // Attempt to create vpaddl for this add. + SDValue Result = AddCombineToVPADDL(N, N0, N1, DCI, Subtarget); + if (Result.getNode()) + return Result; + // fold (add (select cc, 0, c), x) -> (select cc, x, (add, x, c)) if (N0.getOpcode() == ISD::SELECT && N0.getNode()->hasOneUse()) { SDValue Result = combineSelectAndUse(N, N0, N1, DCI); @@ -5539,17 +5647,18 @@ static SDValue PerformADDCombineWithOperands(SDNode *N, SDValue N0, SDValue N1, /// PerformADDCombine - Target-specific dag combine xforms for ISD::ADD. /// static SDValue PerformADDCombine(SDNode *N, - TargetLowering::DAGCombinerInfo &DCI) { + TargetLowering::DAGCombinerInfo &DCI, + const ARMSubtarget *Subtarget) { SDValue N0 = N->getOperand(0); SDValue N1 = N->getOperand(1); // First try with the default operand order. - SDValue Result = PerformADDCombineWithOperands(N, N0, N1, DCI); + SDValue Result = PerformADDCombineWithOperands(N, N0, N1, DCI, Subtarget); if (Result.getNode()) return Result; // If that didn't work, try again with the operands commuted. - return PerformADDCombineWithOperands(N, N1, N0, DCI); + return PerformADDCombineWithOperands(N, N1, N0, DCI, Subtarget); } /// PerformSUBCombine - Target-specific dag combine xforms for ISD::SUB. @@ -5588,7 +5697,7 @@ static SDValue PerformVMULCombine(SDNode *N, unsigned Opcode = N0.getOpcode(); if (Opcode != ISD::ADD && Opcode != ISD::SUB && Opcode != ISD::FADD && Opcode != ISD::FSUB) { - Opcode = N0.getOpcode(); + Opcode = N1.getOpcode(); if (Opcode != ISD::ADD && Opcode != ISD::SUB && Opcode != ISD::FADD && Opcode != ISD::FSUB) return SDValue(); @@ -5874,8 +5983,8 @@ static SDValue PerformORCombine(SDNode *N, return SDValue(); } -/// PerformBFICombine - (bfi A, (and B, C1), C2) -> (bfi A, B, C2) iff -/// C1 & C2 == C1. +/// PerformBFICombine - (bfi A, (and B, Mask1), Mask2) -> (bfi A, B, Mask2) iff +/// the bits being cleared by the AND are not demanded by the BFI. static SDValue PerformBFICombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI) { SDValue N1 = N->getOperand(1); @@ -5883,9 +5992,12 @@ static SDValue PerformBFICombine(SDNode *N, ConstantSDNode *N11C = dyn_cast<ConstantSDNode>(N1.getOperand(1)); if (!N11C) return SDValue(); - unsigned Mask = cast<ConstantSDNode>(N->getOperand(2))->getZExtValue(); + unsigned InvMask = cast<ConstantSDNode>(N->getOperand(2))->getZExtValue(); + unsigned LSB = CountTrailingZeros_32(~InvMask); + unsigned Width = (32 - CountLeadingZeros_32(~InvMask)) - LSB; + unsigned Mask = (1 << Width)-1; unsigned Mask2 = N11C->getZExtValue(); - if ((Mask & Mask2) == Mask2) + if ((Mask & (~Mask2)) == 0) return DCI.DAG.getNode(ARMISD::BFI, N->getDebugLoc(), N->getValueType(0), N->getOperand(0), N1.getOperand(0), N->getOperand(2)); @@ -6378,7 +6490,105 @@ static SDValue PerformVDUPLANECombine(SDNode *N, return DCI.DAG.getNode(ISD::BITCAST, N->getDebugLoc(), VT, Op); } -/// getVShiftImm - Check if this is a valid build_vector for the immediate +// isConstVecPow2 - Return true if each vector element is a power of 2, all +// elements are the same constant, C, and Log2(C) ranges from 1 to 32. +static bool isConstVecPow2(SDValue ConstVec, bool isSigned, uint64_t &C) +{ + integerPart cN; + integerPart c0 = 0; + for (unsigned I = 0, E = ConstVec.getValueType().getVectorNumElements(); + I != E; I++) { + ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(ConstVec.getOperand(I)); + if (!C) + return false; + + bool isExact; + APFloat APF = C->getValueAPF(); + if (APF.convertToInteger(&cN, 64, isSigned, APFloat::rmTowardZero, &isExact) + != APFloat::opOK || !isExact) + return false; + + c0 = (I == 0) ? cN : c0; + if (!isPowerOf2_64(cN) || c0 != cN || Log2_64(c0) < 1 || Log2_64(c0) > 32) + return false; + } + C = c0; + return true; +} + +/// PerformVCVTCombine - VCVT (floating-point to fixed-point, Advanced SIMD) +/// can replace combinations of VMUL and VCVT (floating-point to integer) +/// when the VMUL has a constant operand that is a power of 2. +/// +/// Example (assume d17 = <float 8.000000e+00, float 8.000000e+00>): +/// vmul.f32 d16, d17, d16 +/// vcvt.s32.f32 d16, d16 +/// becomes: +/// vcvt.s32.f32 d16, d16, #3 +static SDValue PerformVCVTCombine(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI, + const ARMSubtarget *Subtarget) { + SelectionDAG &DAG = DCI.DAG; + SDValue Op = N->getOperand(0); + + if (!Subtarget->hasNEON() || !Op.getValueType().isVector() || + Op.getOpcode() != ISD::FMUL) + return SDValue(); + + uint64_t C; + SDValue N0 = Op->getOperand(0); + SDValue ConstVec = Op->getOperand(1); + bool isSigned = N->getOpcode() == ISD::FP_TO_SINT; + + if (ConstVec.getOpcode() != ISD::BUILD_VECTOR || + !isConstVecPow2(ConstVec, isSigned, C)) + return SDValue(); + + unsigned IntrinsicOpcode = isSigned ? Intrinsic::arm_neon_vcvtfp2fxs : + Intrinsic::arm_neon_vcvtfp2fxu; + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, N->getDebugLoc(), + N->getValueType(0), + DAG.getConstant(IntrinsicOpcode, MVT::i32), N0, + DAG.getConstant(Log2_64(C), MVT::i32)); +} + +/// PerformVDIVCombine - VCVT (fixed-point to floating-point, Advanced SIMD) +/// can replace combinations of VCVT (integer to floating-point) and VDIV +/// when the VDIV has a constant operand that is a power of 2. +/// +/// Example (assume d17 = <float 8.000000e+00, float 8.000000e+00>): +/// vcvt.f32.s32 d16, d16 +/// vdiv.f32 d16, d17, d16 +/// becomes: +/// vcvt.f32.s32 d16, d16, #3 +static SDValue PerformVDIVCombine(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI, + const ARMSubtarget *Subtarget) { + SelectionDAG &DAG = DCI.DAG; + SDValue Op = N->getOperand(0); + unsigned OpOpcode = Op.getNode()->getOpcode(); + + if (!Subtarget->hasNEON() || !N->getValueType(0).isVector() || + (OpOpcode != ISD::SINT_TO_FP && OpOpcode != ISD::UINT_TO_FP)) + return SDValue(); + + uint64_t C; + SDValue ConstVec = N->getOperand(1); + bool isSigned = OpOpcode == ISD::SINT_TO_FP; + + if (ConstVec.getOpcode() != ISD::BUILD_VECTOR || + !isConstVecPow2(ConstVec, isSigned, C)) + return SDValue(); + + unsigned IntrinsicOpcode = isSigned ? Intrinsic::arm_neon_vcvtfxs2fp : + Intrinsic::arm_neon_vcvtfxu2fp; + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, N->getDebugLoc(), + Op.getValueType(), + DAG.getConstant(IntrinsicOpcode, MVT::i32), + Op.getOperand(0), DAG.getConstant(Log2_64(C), MVT::i32)); +} + +/// Getvshiftimm - Check if this is a valid build_vector for the immediate /// operand of a vector shift operation, where all the elements of the /// build_vector must have the same constant integer value. static bool getVShiftImm(SDValue Op, unsigned ElementBits, int64_t &Cnt) { @@ -6750,11 +6960,75 @@ static SDValue PerformSELECT_CCCombine(SDNode *N, SelectionDAG &DAG, return DAG.getNode(Opcode, N->getDebugLoc(), N->getValueType(0), LHS, RHS); } +/// PerformCMOVCombine - Target-specific DAG combining for ARMISD::CMOV. +SDValue +ARMTargetLowering::PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const { + SDValue Cmp = N->getOperand(4); + if (Cmp.getOpcode() != ARMISD::CMPZ) + // Only looking at EQ and NE cases. + return SDValue(); + + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + SDValue LHS = Cmp.getOperand(0); + SDValue RHS = Cmp.getOperand(1); + SDValue FalseVal = N->getOperand(0); + SDValue TrueVal = N->getOperand(1); + SDValue ARMcc = N->getOperand(2); + ARMCC::CondCodes CC = (ARMCC::CondCodes)cast<ConstantSDNode>(ARMcc)->getZExtValue(); + + // Simplify + // mov r1, r0 + // cmp r1, x + // mov r0, y + // moveq r0, x + // to + // cmp r0, x + // movne r0, y + // + // mov r1, r0 + // cmp r1, x + // mov r0, x + // movne r0, y + // to + // cmp r0, x + // movne r0, y + /// FIXME: Turn this into a target neutral optimization? + SDValue Res; + if (CC == ARMCC::NE && FalseVal == RHS) { + Res = DAG.getNode(ARMISD::CMOV, dl, VT, LHS, TrueVal, ARMcc, + N->getOperand(3), Cmp); + } else if (CC == ARMCC::EQ && TrueVal == RHS) { + SDValue ARMcc; + SDValue NewCmp = getARMCmp(LHS, RHS, ISD::SETNE, ARMcc, DAG, dl); + Res = DAG.getNode(ARMISD::CMOV, dl, VT, LHS, FalseVal, ARMcc, + N->getOperand(3), NewCmp); + } + + if (Res.getNode()) { + APInt KnownZero, KnownOne; + APInt Mask = APInt::getAllOnesValue(VT.getScalarType().getSizeInBits()); + DAG.ComputeMaskedBits(SDValue(N,0), Mask, KnownZero, KnownOne); + // Capture demanded bits information that would be otherwise lost. + if (KnownZero == 0xfffffffe) + Res = DAG.getNode(ISD::AssertZext, dl, MVT::i32, Res, + DAG.getValueType(MVT::i1)); + else if (KnownZero == 0xffffff00) + Res = DAG.getNode(ISD::AssertZext, dl, MVT::i32, Res, + DAG.getValueType(MVT::i8)); + else if (KnownZero == 0xffff0000) + Res = DAG.getNode(ISD::AssertZext, dl, MVT::i32, Res, + DAG.getValueType(MVT::i16)); + } + + return Res; +} + SDValue ARMTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { switch (N->getOpcode()) { default: break; - case ISD::ADD: return PerformADDCombine(N, DCI); + case ISD::ADD: return PerformADDCombine(N, DCI, Subtarget); case ISD::SUB: return PerformSUBCombine(N, DCI); case ISD::MUL: return PerformMULCombine(N, DCI, Subtarget); case ISD::OR: return PerformORCombine(N, DCI, Subtarget); @@ -6767,6 +7041,9 @@ SDValue ARMTargetLowering::PerformDAGCombine(SDNode *N, case ISD::INSERT_VECTOR_ELT: return PerformInsertEltCombine(N, DCI); case ISD::VECTOR_SHUFFLE: return PerformVECTOR_SHUFFLECombine(N, DCI.DAG); case ARMISD::VDUPLANE: return PerformVDUPLANECombine(N, DCI); + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: return PerformVCVTCombine(N, DCI, Subtarget); + case ISD::FDIV: return PerformVDIVCombine(N, DCI, Subtarget); case ISD::INTRINSIC_WO_CHAIN: return PerformIntrinsicCombine(N, DCI.DAG); case ISD::SHL: case ISD::SRA: @@ -6775,6 +7052,7 @@ SDValue ARMTargetLowering::PerformDAGCombine(SDNode *N, case ISD::ZERO_EXTEND: case ISD::ANY_EXTEND: return PerformExtendCombine(N, DCI.DAG, Subtarget); case ISD::SELECT_CC: return PerformSELECT_CCCombine(N, DCI.DAG, Subtarget); + case ARMISD::CMOV: return PerformCMOVCombine(N, DCI.DAG); case ARMISD::VLD2DUP: case ARMISD::VLD3DUP: case ARMISD::VLD4DUP: @@ -7277,10 +7555,17 @@ ARMTargetLowering::getConstraintType(const std::string &Constraint) const { default: break; case 'l': return C_RegisterClass; case 'w': return C_RegisterClass; + case 'h': return C_RegisterClass; + case 'x': return C_RegisterClass; + case 't': return C_RegisterClass; + case 'j': return C_Other; // Constant for movw. + } + } else if (Constraint.size() == 2) { + switch (Constraint[0]) { + default: break; + // All 'U+' constraints are addresses. + case 'U': return C_Memory; } - } else { - if (Constraint == "Uv") - return C_Memory; } return TargetLowering::getConstraintType(Constraint); } @@ -7319,26 +7604,43 @@ ARMTargetLowering::getSingleConstraintMatchWeight( return weight; } -std::pair<unsigned, const TargetRegisterClass*> +typedef std::pair<unsigned, const TargetRegisterClass*> RCPair; +RCPair ARMTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { if (Constraint.size() == 1) { // GCC ARM Constraint Letters switch (Constraint[0]) { - case 'l': + case 'l': // Low regs or general regs. if (Subtarget->isThumb()) - return std::make_pair(0U, ARM::tGPRRegisterClass); + return RCPair(0U, ARM::tGPRRegisterClass); else - return std::make_pair(0U, ARM::GPRRegisterClass); + return RCPair(0U, ARM::GPRRegisterClass); + case 'h': // High regs or no regs. + if (Subtarget->isThumb()) + return RCPair(0U, ARM::hGPRRegisterClass); + break; case 'r': - return std::make_pair(0U, ARM::GPRRegisterClass); + return RCPair(0U, ARM::GPRRegisterClass); case 'w': if (VT == MVT::f32) - return std::make_pair(0U, ARM::SPRRegisterClass); + return RCPair(0U, ARM::SPRRegisterClass); if (VT.getSizeInBits() == 64) - return std::make_pair(0U, ARM::DPRRegisterClass); + return RCPair(0U, ARM::DPRRegisterClass); if (VT.getSizeInBits() == 128) - return std::make_pair(0U, ARM::QPRRegisterClass); + return RCPair(0U, ARM::QPRRegisterClass); + break; + case 'x': + if (VT == MVT::f32) + return RCPair(0U, ARM::SPR_8RegisterClass); + if (VT.getSizeInBits() == 64) + return RCPair(0U, ARM::DPR_8RegisterClass); + if (VT.getSizeInBits() == 128) + return RCPair(0U, ARM::QPR_8RegisterClass); + break; + case 't': + if (VT == MVT::f32) + return RCPair(0U, ARM::SPRRegisterClass); break; } } @@ -7348,47 +7650,6 @@ ARMTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); } -std::vector<unsigned> ARMTargetLowering:: -getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const { - if (Constraint.size() != 1) - return std::vector<unsigned>(); - - switch (Constraint[0]) { // GCC ARM Constraint Letters - default: break; - case 'l': - return make_vector<unsigned>(ARM::R0, ARM::R1, ARM::R2, ARM::R3, - ARM::R4, ARM::R5, ARM::R6, ARM::R7, - 0); - case 'r': - return make_vector<unsigned>(ARM::R0, ARM::R1, ARM::R2, ARM::R3, - ARM::R4, ARM::R5, ARM::R6, ARM::R7, - ARM::R8, ARM::R9, ARM::R10, ARM::R11, - ARM::R12, ARM::LR, 0); - case 'w': - if (VT == MVT::f32) - return make_vector<unsigned>(ARM::S0, ARM::S1, ARM::S2, ARM::S3, - ARM::S4, ARM::S5, ARM::S6, ARM::S7, - ARM::S8, ARM::S9, ARM::S10, ARM::S11, - ARM::S12,ARM::S13,ARM::S14,ARM::S15, - ARM::S16,ARM::S17,ARM::S18,ARM::S19, - ARM::S20,ARM::S21,ARM::S22,ARM::S23, - ARM::S24,ARM::S25,ARM::S26,ARM::S27, - ARM::S28,ARM::S29,ARM::S30,ARM::S31, 0); - if (VT.getSizeInBits() == 64) - return make_vector<unsigned>(ARM::D0, ARM::D1, ARM::D2, ARM::D3, - ARM::D4, ARM::D5, ARM::D6, ARM::D7, - ARM::D8, ARM::D9, ARM::D10,ARM::D11, - ARM::D12,ARM::D13,ARM::D14,ARM::D15, 0); - if (VT.getSizeInBits() == 128) - return make_vector<unsigned>(ARM::Q0, ARM::Q1, ARM::Q2, ARM::Q3, - ARM::Q4, ARM::Q5, ARM::Q6, ARM::Q7, 0); - break; - } - - return std::vector<unsigned>(); -} - /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops /// vector. If it is invalid, don't add anything to Ops. void ARMTargetLowering::LowerAsmOperandForConstraint(SDValue Op, @@ -7403,6 +7664,7 @@ void ARMTargetLowering::LowerAsmOperandForConstraint(SDValue Op, char ConstraintLetter = Constraint[0]; switch (ConstraintLetter) { default: break; + case 'j': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op); @@ -7417,6 +7679,13 @@ void ARMTargetLowering::LowerAsmOperandForConstraint(SDValue Op, return; switch (ConstraintLetter) { + case 'j': + // Constant suitable for movw, must be between 0 and + // 65535. + if (Subtarget->hasV6T2Ops()) + if (CVal >= 0 && CVal <= 65535) + break; + return; case 'I': if (Subtarget->isThumb1Only()) { // This must be a constant between 0 and 255, for ADD @@ -7685,7 +7954,7 @@ bool ARMTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info, Info.ptrVal = I.getArgOperand(2); Info.offset = 0; Info.align = 8; - Info.vol = false; + Info.vol = true; Info.readMem = false; Info.writeMem = true; return true; @@ -7696,7 +7965,7 @@ bool ARMTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info, Info.ptrVal = I.getArgOperand(0); Info.offset = 0; Info.align = 8; - Info.vol = false; + Info.vol = true; Info.readMem = true; Info.writeMem = false; return true; diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h index 21a9a3aa746d..980fb404887e 100644 --- a/lib/Target/ARM/ARMISelLowering.h +++ b/lib/Target/ARM/ARMISelLowering.h @@ -244,6 +244,7 @@ namespace llvm { EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const; + SDValue PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const; virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; bool isDesirableToTransformToIntegerOp(unsigned Opc, EVT VT) const; @@ -306,9 +307,6 @@ namespace llvm { std::pair<unsigned, const TargetRegisterClass*> getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; - std::vector<unsigned> - getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const; /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops /// vector. If it is invalid, don't add anything to Ops. If hasMemory is diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index 897d8a5d79e3..3ccf22f80b7d 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -107,16 +107,6 @@ def AddrModeT2_pc : AddrMode<14>; def AddrModeT2_i8s4 : AddrMode<15>; def AddrMode_i12 : AddrMode<16>; -// Instruction size. -class SizeFlagVal<bits<3> val> { - bits<3> Value = val; -} -def SizeInvalid : SizeFlagVal<0>; // Unset. -def SizeSpecial : SizeFlagVal<1>; // Pseudo or special. -def Size8Bytes : SizeFlagVal<2>; -def Size4Bytes : SizeFlagVal<3>; -def Size2Bytes : SizeFlagVal<4>; - // Load / store index mode. class IndexMode<bits<2> val> { bits<2> Value = val; @@ -236,13 +226,13 @@ def shr_imm64 : Operand<i32> { // ARM Instruction templates. // -class InstTemplate<AddrMode am, SizeFlagVal sz, IndexMode im, +class InstTemplate<AddrMode am, int sz, IndexMode im, Format f, Domain d, string cstr, InstrItinClass itin> : Instruction { let Namespace = "ARM"; AddrMode AM = am; - SizeFlagVal SZ = sz; + int Size = sz; IndexMode IM = im; bits<2> IndexModeBits = IM.Value; Format F = f; @@ -256,12 +246,11 @@ class InstTemplate<AddrMode am, SizeFlagVal sz, IndexMode im, // The layout of TSFlags should be kept in sync with ARMBaseInstrInfo.h. let TSFlags{4-0} = AM.Value; - let TSFlags{7-5} = SZ.Value; - let TSFlags{9-8} = IndexModeBits; - let TSFlags{15-10} = Form; - let TSFlags{16} = isUnaryDataProc; - let TSFlags{17} = canXformTo16Bit; - let TSFlags{20-18} = D.Value; + let TSFlags{6-5} = IndexModeBits; + let TSFlags{12-7} = Form; + let TSFlags{13} = isUnaryDataProc; + let TSFlags{14} = canXformTo16Bit; + let TSFlags{17-15} = D.Value; let Constraints = cstr; let Itinerary = itin; @@ -271,53 +260,70 @@ class Encoding { field bits<32> Inst; } -class InstARM<AddrMode am, SizeFlagVal sz, IndexMode im, +class InstARM<AddrMode am, int sz, IndexMode im, Format f, Domain d, string cstr, InstrItinClass itin> : InstTemplate<am, sz, im, f, d, cstr, itin>, Encoding; // This Encoding-less class is used by Thumb1 to specify the encoding bits later // on by adding flavors to specific instructions. -class InstThumb<AddrMode am, SizeFlagVal sz, IndexMode im, +class InstThumb<AddrMode am, int sz, IndexMode im, Format f, Domain d, string cstr, InstrItinClass itin> : InstTemplate<am, sz, im, f, d, cstr, itin>; class PseudoInst<dag oops, dag iops, InstrItinClass itin, list<dag> pattern> - // FIXME: This really should derive from InstTemplate instead, as pseudos - // don't need encoding information. TableGen doesn't like that - // currently. Need to figure out why and fix it. - : InstARM<AddrModeNone, SizeSpecial, IndexModeNone, Pseudo, GenericDomain, - "", itin> { + : InstTemplate<AddrModeNone, 0, IndexModeNone, Pseudo, + GenericDomain, "", itin> { let OutOperandList = oops; let InOperandList = iops; let Pattern = pattern; let isCodeGenOnly = 1; + let isPseudo = 1; } // PseudoInst that's ARM-mode only. -class ARMPseudoInst<dag oops, dag iops, SizeFlagVal sz, InstrItinClass itin, +class ARMPseudoInst<dag oops, dag iops, int sz, InstrItinClass itin, list<dag> pattern> : PseudoInst<oops, iops, itin, pattern> { - let SZ = sz; + let Size = sz; list<Predicate> Predicates = [IsARM]; } // PseudoInst that's Thumb-mode only. -class tPseudoInst<dag oops, dag iops, SizeFlagVal sz, InstrItinClass itin, +class tPseudoInst<dag oops, dag iops, int sz, InstrItinClass itin, list<dag> pattern> : PseudoInst<oops, iops, itin, pattern> { - let SZ = sz; + let Size = sz; list<Predicate> Predicates = [IsThumb]; } // PseudoInst that's Thumb2-mode only. -class t2PseudoInst<dag oops, dag iops, SizeFlagVal sz, InstrItinClass itin, +class t2PseudoInst<dag oops, dag iops, int sz, InstrItinClass itin, list<dag> pattern> : PseudoInst<oops, iops, itin, pattern> { - let SZ = sz; + let Size = sz; list<Predicate> Predicates = [IsThumb2]; } + +class ARMPseudoExpand<dag oops, dag iops, int sz, + InstrItinClass itin, list<dag> pattern, + dag Result> + : ARMPseudoInst<oops, iops, sz, itin, pattern>, + PseudoInstExpansion<Result>; + +class tPseudoExpand<dag oops, dag iops, int sz, + InstrItinClass itin, list<dag> pattern, + dag Result> + : tPseudoInst<oops, iops, sz, itin, pattern>, + PseudoInstExpansion<Result>; + +class t2PseudoExpand<dag oops, dag iops, int sz, + InstrItinClass itin, list<dag> pattern, + dag Result> + : t2PseudoInst<oops, iops, sz, itin, pattern>, + PseudoInstExpansion<Result>; + // Almost all ARM instructions are predicable. -class I<dag oops, dag iops, AddrMode am, SizeFlagVal sz, +class I<dag oops, dag iops, AddrMode am, int sz, IndexMode im, Format f, InstrItinClass itin, string opc, string asm, string cstr, list<dag> pattern> @@ -332,7 +338,7 @@ class I<dag oops, dag iops, AddrMode am, SizeFlagVal sz, } // A few are not predicable -class InoP<dag oops, dag iops, AddrMode am, SizeFlagVal sz, +class InoP<dag oops, dag iops, AddrMode am, int sz, IndexMode im, Format f, InstrItinClass itin, string opc, string asm, string cstr, list<dag> pattern> @@ -348,7 +354,7 @@ class InoP<dag oops, dag iops, AddrMode am, SizeFlagVal sz, // Same as I except it can optionally modify CPSR. Note it's modeled as an input // operand since by default it's a zero register. It will become an implicit def // once it's "flipped". -class sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz, +class sI<dag oops, dag iops, AddrMode am, int sz, IndexMode im, Format f, InstrItinClass itin, string opc, string asm, string cstr, list<dag> pattern> @@ -366,7 +372,7 @@ class sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz, } // Special cases -class XI<dag oops, dag iops, AddrMode am, SizeFlagVal sz, +class XI<dag oops, dag iops, AddrMode am, int sz, IndexMode im, Format f, InstrItinClass itin, string asm, string cstr, list<dag> pattern> : InstARM<am, sz, im, f, GenericDomain, cstr, itin> { @@ -379,31 +385,31 @@ class XI<dag oops, dag iops, AddrMode am, SizeFlagVal sz, class AI<dag oops, dag iops, Format f, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, f, itin, + : I<oops, iops, AddrModeNone, 4, IndexModeNone, f, itin, opc, asm, "", pattern>; class AsI<dag oops, dag iops, Format f, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : sI<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, f, itin, + : sI<oops, iops, AddrModeNone, 4, IndexModeNone, f, itin, opc, asm, "", pattern>; class AXI<dag oops, dag iops, Format f, InstrItinClass itin, string asm, list<dag> pattern> - : XI<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, f, itin, + : XI<oops, iops, AddrModeNone, 4, IndexModeNone, f, itin, asm, "", pattern>; class AInoP<dag oops, dag iops, Format f, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : InoP<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, f, itin, + : InoP<oops, iops, AddrModeNone, 4, IndexModeNone, f, itin, opc, asm, "", pattern>; // Ctrl flow instructions class ABI<bits<4> opcod, dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, BrFrm, itin, + : I<oops, iops, AddrModeNone, 4, IndexModeNone, BrFrm, itin, opc, asm, "", pattern> { let Inst{27-24} = opcod; } class ABXI<bits<4> opcod, dag oops, dag iops, InstrItinClass itin, string asm, list<dag> pattern> - : XI<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, BrFrm, itin, + : XI<oops, iops, AddrModeNone, 4, IndexModeNone, BrFrm, itin, asm, "", pattern> { let Inst{27-24} = opcod; } @@ -411,13 +417,13 @@ class ABXI<bits<4> opcod, dag oops, dag iops, InstrItinClass itin, // BR_JT instructions class JTI<dag oops, dag iops, InstrItinClass itin, string asm, list<dag> pattern> - : XI<oops, iops, AddrModeNone, SizeSpecial, IndexModeNone, BrMiscFrm, itin, + : XI<oops, iops, AddrModeNone, 0, IndexModeNone, BrMiscFrm, itin, asm, "", pattern>; // Atomic load/store instructions class AIldrex<bits<2> opcod, dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, LdStExFrm, itin, + : I<oops, iops, AddrModeNone, 4, IndexModeNone, LdStExFrm, itin, opc, asm, "", pattern> { bits<4> Rt; bits<4> Rn; @@ -430,7 +436,7 @@ class AIldrex<bits<2> opcod, dag oops, dag iops, InstrItinClass itin, } class AIstrex<bits<2> opcod, dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, LdStExFrm, itin, + : I<oops, iops, AddrModeNone, 4, IndexModeNone, LdStExFrm, itin, opc, asm, "", pattern> { bits<4> Rd; bits<4> Rt; @@ -460,21 +466,21 @@ class AIswp<bit b, dag oops, dag iops, string opc, list<dag> pattern> // addrmode1 instructions class AI1<bits<4> opcod, dag oops, dag iops, Format f, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : I<oops, iops, AddrMode1, Size4Bytes, IndexModeNone, f, itin, + : I<oops, iops, AddrMode1, 4, IndexModeNone, f, itin, opc, asm, "", pattern> { let Inst{24-21} = opcod; let Inst{27-26} = 0b00; } class AsI1<bits<4> opcod, dag oops, dag iops, Format f, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : sI<oops, iops, AddrMode1, Size4Bytes, IndexModeNone, f, itin, + : sI<oops, iops, AddrMode1, 4, IndexModeNone, f, itin, opc, asm, "", pattern> { let Inst{24-21} = opcod; let Inst{27-26} = 0b00; } class AXI1<bits<4> opcod, dag oops, dag iops, Format f, InstrItinClass itin, string asm, list<dag> pattern> - : XI<oops, iops, AddrMode1, Size4Bytes, IndexModeNone, f, itin, + : XI<oops, iops, AddrMode1, 4, IndexModeNone, f, itin, asm, "", pattern> { let Inst{24-21} = opcod; let Inst{27-26} = 0b00; @@ -486,7 +492,7 @@ class AXI1<bits<4> opcod, dag oops, dag iops, Format f, InstrItinClass itin, class AI2ldst<bits<3> op, bit isLd, bit isByte, dag oops, dag iops, AddrMode am, Format f, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : I<oops, iops, am, Size4Bytes, IndexModeNone, f, itin, opc, asm, + : I<oops, iops, am, 4, IndexModeNone, f, itin, opc, asm, "", pattern> { let Inst{27-25} = op; let Inst{24} = 1; // 24 == P @@ -499,7 +505,7 @@ class AI2ldst<bits<3> op, bit isLd, bit isByte, dag oops, dag iops, AddrMode am, class AI2ldstidx<bit isLd, bit isByte, bit isPre, dag oops, dag iops, IndexMode im, Format f, InstrItinClass itin, string opc, string asm, string cstr, list<dag> pattern> - : I<oops, iops, AddrMode2, Size4Bytes, im, f, itin, + : I<oops, iops, AddrMode2, 4, im, f, itin, opc, asm, cstr, pattern> { bits<4> Rt; let Inst{27-26} = 0b01; @@ -547,7 +553,7 @@ class AI2stridxT<bit isByte, bit isPre, dag oops, dag iops, // addrmode3 instructions class AI3ld<bits<4> op, bit op20, dag oops, dag iops, Format f, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : I<oops, iops, AddrMode3, Size4Bytes, IndexModeNone, f, itin, + : I<oops, iops, AddrMode3, 4, IndexModeNone, f, itin, opc, asm, "", pattern> { bits<14> addr; bits<4> Rt; @@ -567,7 +573,7 @@ class AI3ld<bits<4> op, bit op20, dag oops, dag iops, Format f, class AI3ldstidx<bits<4> op, bit op20, bit isLd, bit isPre, dag oops, dag iops, IndexMode im, Format f, InstrItinClass itin, string opc, string asm, string cstr, list<dag> pattern> - : I<oops, iops, AddrMode3, Size4Bytes, im, f, itin, + : I<oops, iops, AddrMode3, 4, im, f, itin, opc, asm, cstr, pattern> { bits<4> Rt; let Inst{27-25} = 0b000; @@ -583,7 +589,7 @@ class AI3ldstidx<bits<4> op, bit op20, bit isLd, bit isPre, dag oops, dag iops, class AI3ldstidxT<bits<4> op, bit op20, bit isLd, bit isPre, dag oops, dag iops, IndexMode im, Format f, InstrItinClass itin, string opc, string asm, string cstr, list<dag> pattern> - : I<oops, iops, AddrMode3, Size4Bytes, im, f, itin, + : I<oops, iops, AddrMode3, 4, im, f, itin, opc, asm, cstr, pattern> { // {13} 1 == imm8, 0 == Rm // {12-9} Rn @@ -627,7 +633,7 @@ class AI3stridx<bits<4> op, bit isByte, bit isPre, dag oops, dag iops, // stores class AI3str<bits<4> op, dag oops, dag iops, Format f, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : I<oops, iops, AddrMode3, Size4Bytes, IndexModeNone, f, itin, + : I<oops, iops, AddrMode3, 4, IndexModeNone, f, itin, opc, asm, "", pattern> { bits<14> addr; bits<4> Rt; @@ -647,7 +653,7 @@ class AI3str<bits<4> op, dag oops, dag iops, Format f, InstrItinClass itin, // Pre-indexed stores class AI3sthpr<dag oops, dag iops, Format f, InstrItinClass itin, string opc, string asm, string cstr, list<dag> pattern> - : I<oops, iops, AddrMode3, Size4Bytes, IndexModePre, f, itin, + : I<oops, iops, AddrMode3, 4, IndexModePre, f, itin, opc, asm, cstr, pattern> { let Inst{4} = 1; let Inst{5} = 1; // H bit @@ -660,7 +666,7 @@ class AI3sthpr<dag oops, dag iops, Format f, InstrItinClass itin, } class AI3stdpr<dag oops, dag iops, Format f, InstrItinClass itin, string opc, string asm, string cstr, list<dag> pattern> - : I<oops, iops, AddrMode3, Size4Bytes, IndexModePre, f, itin, + : I<oops, iops, AddrMode3, 4, IndexModePre, f, itin, opc, asm, cstr, pattern> { let Inst{4} = 1; let Inst{5} = 1; // H bit @@ -675,7 +681,7 @@ class AI3stdpr<dag oops, dag iops, Format f, InstrItinClass itin, // Post-indexed stores class AI3sthpo<dag oops, dag iops, Format f, InstrItinClass itin, string opc, string asm, string cstr, list<dag> pattern> - : I<oops, iops, AddrMode3, Size4Bytes, IndexModePost, f, itin, + : I<oops, iops, AddrMode3, 4, IndexModePost, f, itin, opc, asm, cstr,pattern> { // {13} 1 == imm8, 0 == Rm // {12-9} Rn @@ -701,7 +707,7 @@ class AI3sthpo<dag oops, dag iops, Format f, InstrItinClass itin, } class AI3stdpo<dag oops, dag iops, Format f, InstrItinClass itin, string opc, string asm, string cstr, list<dag> pattern> - : I<oops, iops, AddrMode3, Size4Bytes, IndexModePost, f, itin, + : I<oops, iops, AddrMode3, 4, IndexModePost, f, itin, opc, asm, cstr, pattern> { let Inst{4} = 1; let Inst{5} = 1; // H bit @@ -716,7 +722,7 @@ class AI3stdpo<dag oops, dag iops, Format f, InstrItinClass itin, // addrmode4 instructions class AXI4<dag oops, dag iops, IndexMode im, Format f, InstrItinClass itin, string asm, string cstr, list<dag> pattern> - : XI<oops, iops, AddrMode4, Size4Bytes, im, f, itin, asm, cstr, pattern> { + : XI<oops, iops, AddrMode4, 4, im, f, itin, asm, cstr, pattern> { bits<4> p; bits<16> regs; bits<4> Rn; @@ -730,7 +736,7 @@ class AXI4<dag oops, dag iops, IndexMode im, Format f, InstrItinClass itin, // Unsigned multiply, multiply-accumulate instructions. class AMul1I<bits<7> opcod, dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, MulFrm, itin, + : I<oops, iops, AddrModeNone, 4, IndexModeNone, MulFrm, itin, opc, asm, "", pattern> { let Inst{7-4} = 0b1001; let Inst{20} = 0; // S bit @@ -738,7 +744,7 @@ class AMul1I<bits<7> opcod, dag oops, dag iops, InstrItinClass itin, } class AsMul1I<bits<7> opcod, dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : sI<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, MulFrm, itin, + : sI<oops, iops, AddrModeNone, 4, IndexModeNone, MulFrm, itin, opc, asm, "", pattern> { let Inst{7-4} = 0b1001; let Inst{27-21} = opcod; @@ -747,7 +753,7 @@ class AsMul1I<bits<7> opcod, dag oops, dag iops, InstrItinClass itin, // Most significant word multiply class AMul2I<bits<7> opcod, bits<4> opc7_4, dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, MulFrm, itin, + : I<oops, iops, AddrModeNone, 4, IndexModeNone, MulFrm, itin, opc, asm, "", pattern> { bits<4> Rd; bits<4> Rn; @@ -770,7 +776,7 @@ class AMul2Ia<bits<7> opcod, bits<4> opc7_4, dag oops, dag iops, // SMUL<x><y> / SMULW<y> / SMLA<x><y> / SMLAW<x><y> class AMulxyIbase<bits<7> opcod, bits<2> bit6_5, dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, MulFrm, itin, + : I<oops, iops, AddrModeNone, 4, IndexModeNone, MulFrm, itin, opc, asm, "", pattern> { bits<4> Rn; bits<4> Rm; @@ -809,7 +815,7 @@ class AMulxyI64<bits<7> opcod, bits<2> bit6_5, dag oops, dag iops, // Extend instructions. class AExtI<bits<8> opcod, dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, ExtFrm, itin, + : I<oops, iops, AddrModeNone, 4, IndexModeNone, ExtFrm, itin, opc, asm, "", pattern> { // All AExtI instructions have Rd and Rm register operands. bits<4> Rd; @@ -824,7 +830,7 @@ class AExtI<bits<8> opcod, dag oops, dag iops, InstrItinClass itin, // Misc Arithmetic instructions. class AMiscA1I<bits<8> opcod, bits<4> opc7_4, dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, ArithMiscFrm, itin, + : I<oops, iops, AddrModeNone, 4, IndexModeNone, ArithMiscFrm, itin, opc, asm, "", pattern> { bits<4> Rd; bits<4> Rm; @@ -839,7 +845,7 @@ class AMiscA1I<bits<8> opcod, bits<4> opc7_4, dag oops, dag iops, // PKH instructions class APKHI<bits<8> opcod, bit tb, dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, ArithMiscFrm, itin, + : I<oops, iops, AddrModeNone, 4, IndexModeNone, ArithMiscFrm, itin, opc, asm, "", pattern> { bits<4> Rd; bits<4> Rn; @@ -874,7 +880,7 @@ class ARMV6Pat<dag pattern, dag result> : Pat<pattern, result> { // Thumb Instruction Format Definitions. // -class ThumbI<dag oops, dag iops, AddrMode am, SizeFlagVal sz, +class ThumbI<dag oops, dag iops, AddrMode am, int sz, InstrItinClass itin, string asm, string cstr, list<dag> pattern> : InstThumb<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> { let OutOperandList = oops; @@ -886,39 +892,32 @@ class ThumbI<dag oops, dag iops, AddrMode am, SizeFlagVal sz, // TI - Thumb instruction. class TI<dag oops, dag iops, InstrItinClass itin, string asm, list<dag> pattern> - : ThumbI<oops, iops, AddrModeNone, Size2Bytes, itin, asm, "", pattern>; + : ThumbI<oops, iops, AddrModeNone, 2, itin, asm, "", pattern>; // Two-address instructions class TIt<dag oops, dag iops, InstrItinClass itin, string asm, list<dag> pattern> - : ThumbI<oops, iops, AddrModeNone, Size2Bytes, itin, asm, "$lhs = $dst", + : ThumbI<oops, iops, AddrModeNone, 2, itin, asm, "$lhs = $dst", pattern>; // tBL, tBX 32-bit instructions class TIx2<bits<5> opcod1, bits<2> opcod2, bit opcod3, dag oops, dag iops, InstrItinClass itin, string asm, list<dag> pattern> - : ThumbI<oops, iops, AddrModeNone, Size4Bytes, itin, asm, "", pattern>, + : ThumbI<oops, iops, AddrModeNone, 4, itin, asm, "", pattern>, Encoding { let Inst{31-27} = opcod1; let Inst{15-14} = opcod2; let Inst{12} = opcod3; } -// Move to/from coprocessor instructions -class T1Cop<dag oops, dag iops, string asm, list<dag> pattern> - : ThumbI<oops, iops, AddrModeNone, Size4Bytes, NoItinerary, asm, "", pattern>, - Encoding, Requires<[IsThumb, HasV6]> { - let Inst{31-28} = 0b1110; -} - // BR_JT instructions class TJTI<dag oops, dag iops, InstrItinClass itin, string asm, list<dag> pattern> - : ThumbI<oops, iops, AddrModeNone, SizeSpecial, itin, asm, "", pattern>; + : ThumbI<oops, iops, AddrModeNone, 0, itin, asm, "", pattern>; // Thumb1 only -class Thumb1I<dag oops, dag iops, AddrMode am, SizeFlagVal sz, +class Thumb1I<dag oops, dag iops, AddrMode am, int sz, InstrItinClass itin, string asm, string cstr, list<dag> pattern> : InstThumb<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> { let OutOperandList = oops; @@ -930,19 +929,19 @@ class Thumb1I<dag oops, dag iops, AddrMode am, SizeFlagVal sz, class T1I<dag oops, dag iops, InstrItinClass itin, string asm, list<dag> pattern> - : Thumb1I<oops, iops, AddrModeNone, Size2Bytes, itin, asm, "", pattern>; + : Thumb1I<oops, iops, AddrModeNone, 2, itin, asm, "", pattern>; class T1Ix2<dag oops, dag iops, InstrItinClass itin, string asm, list<dag> pattern> - : Thumb1I<oops, iops, AddrModeNone, Size4Bytes, itin, asm, "", pattern>; + : Thumb1I<oops, iops, AddrModeNone, 4, itin, asm, "", pattern>; // Two-address instructions class T1It<dag oops, dag iops, InstrItinClass itin, string asm, string cstr, list<dag> pattern> - : Thumb1I<oops, iops, AddrModeNone, Size2Bytes, itin, + : Thumb1I<oops, iops, AddrModeNone, 2, itin, asm, cstr, pattern>; // Thumb1 instruction that can either be predicated or set CPSR. -class Thumb1sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz, +class Thumb1sI<dag oops, dag iops, AddrMode am, int sz, InstrItinClass itin, string opc, string asm, string cstr, list<dag> pattern> : InstThumb<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> { @@ -955,16 +954,16 @@ class Thumb1sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz, class T1sI<dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : Thumb1sI<oops, iops, AddrModeNone, Size2Bytes, itin, opc, asm, "", pattern>; + : Thumb1sI<oops, iops, AddrModeNone, 2, itin, opc, asm, "", pattern>; // Two-address instructions class T1sIt<dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : Thumb1sI<oops, iops, AddrModeNone, Size2Bytes, itin, opc, asm, + : Thumb1sI<oops, iops, AddrModeNone, 2, itin, opc, asm, "$Rn = $Rdn", pattern>; // Thumb1 instruction that can be predicated. -class Thumb1pI<dag oops, dag iops, AddrMode am, SizeFlagVal sz, +class Thumb1pI<dag oops, dag iops, AddrMode am, int sz, InstrItinClass itin, string opc, string asm, string cstr, list<dag> pattern> : InstThumb<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> { @@ -977,17 +976,17 @@ class Thumb1pI<dag oops, dag iops, AddrMode am, SizeFlagVal sz, class T1pI<dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : Thumb1pI<oops, iops, AddrModeNone, Size2Bytes, itin, opc, asm, "", pattern>; + : Thumb1pI<oops, iops, AddrModeNone, 2, itin, opc, asm, "", pattern>; // Two-address instructions class T1pIt<dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : Thumb1pI<oops, iops, AddrModeNone, Size2Bytes, itin, opc, asm, + : Thumb1pI<oops, iops, AddrModeNone, 2, itin, opc, asm, "$Rn = $Rdn", pattern>; class T1pIs<dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : Thumb1pI<oops, iops, AddrModeT1_s, Size2Bytes, itin, opc, asm, "", pattern>; + : Thumb1pI<oops, iops, AddrModeT1_s, 2, itin, opc, asm, "", pattern>; class Encoding16 : Encoding { let Inst{31-16} = 0x0000; @@ -1036,7 +1035,7 @@ class T1BranchCond<bits<4> opcode> : Encoding16 { class T1pILdStEncode<bits<3> opcode, dag oops, dag iops, AddrMode am, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : Thumb1pI<oops, iops, am, Size2Bytes, itin, opc, asm, "", pattern>, + : Thumb1pI<oops, iops, am, 2, itin, opc, asm, "", pattern>, T1LoadStore<0b0101, opcode> { bits<3> Rt; bits<8> addr; @@ -1047,7 +1046,7 @@ class T1pILdStEncode<bits<3> opcode, dag oops, dag iops, AddrMode am, class T1pILdStEncodeImm<bits<4> opA, bit opB, dag oops, dag iops, AddrMode am, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : Thumb1pI<oops, iops, am, Size2Bytes, itin, opc, asm, "", pattern>, + : Thumb1pI<oops, iops, am, 2, itin, opc, asm, "", pattern>, T1LoadStore<opA, {opB,?,?}> { bits<3> Rt; bits<8> addr; @@ -1063,7 +1062,7 @@ class T1Misc<bits<7> opcode> : Encoding16 { } // Thumb2I - Thumb2 instruction. Almost all Thumb2 instructions are predicable. -class Thumb2I<dag oops, dag iops, AddrMode am, SizeFlagVal sz, +class Thumb2I<dag oops, dag iops, AddrMode am, int sz, InstrItinClass itin, string opc, string asm, string cstr, list<dag> pattern> : InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> { @@ -1080,7 +1079,7 @@ class Thumb2I<dag oops, dag iops, AddrMode am, SizeFlagVal sz, // // FIXME: This uses unified syntax so {s} comes before {p}. We should make it // more consistent. -class Thumb2sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz, +class Thumb2sI<dag oops, dag iops, AddrMode am, int sz, InstrItinClass itin, string opc, string asm, string cstr, list<dag> pattern> : InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> { @@ -1095,7 +1094,7 @@ class Thumb2sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz, } // Special cases -class Thumb2XI<dag oops, dag iops, AddrMode am, SizeFlagVal sz, +class Thumb2XI<dag oops, dag iops, AddrMode am, int sz, InstrItinClass itin, string asm, string cstr, list<dag> pattern> : InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> { @@ -1106,7 +1105,7 @@ class Thumb2XI<dag oops, dag iops, AddrMode am, SizeFlagVal sz, list<Predicate> Predicates = [IsThumb2]; } -class ThumbXI<dag oops, dag iops, AddrMode am, SizeFlagVal sz, +class ThumbXI<dag oops, dag iops, AddrMode am, int sz, InstrItinClass itin, string asm, string cstr, list<dag> pattern> : InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> { @@ -1119,22 +1118,22 @@ class ThumbXI<dag oops, dag iops, AddrMode am, SizeFlagVal sz, class T2I<dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : Thumb2I<oops, iops, AddrModeNone, Size4Bytes, itin, opc, asm, "", pattern>; + : Thumb2I<oops, iops, AddrModeNone, 4, itin, opc, asm, "", pattern>; class T2Ii12<dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : Thumb2I<oops, iops, AddrModeT2_i12, Size4Bytes, itin, opc, asm, "",pattern>; + : Thumb2I<oops, iops, AddrModeT2_i12, 4, itin, opc, asm, "",pattern>; class T2Ii8<dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : Thumb2I<oops, iops, AddrModeT2_i8, Size4Bytes, itin, opc, asm, "", pattern>; + : Thumb2I<oops, iops, AddrModeT2_i8, 4, itin, opc, asm, "", pattern>; class T2Iso<dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : Thumb2I<oops, iops, AddrModeT2_so, Size4Bytes, itin, opc, asm, "", pattern>; + : Thumb2I<oops, iops, AddrModeT2_so, 4, itin, opc, asm, "", pattern>; class T2Ipc<dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : Thumb2I<oops, iops, AddrModeT2_pc, Size4Bytes, itin, opc, asm, "", pattern>; + : Thumb2I<oops, iops, AddrModeT2_pc, 4, itin, opc, asm, "", pattern>; class T2Ii8s4<bit P, bit W, bit isLoad, dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : Thumb2I<oops, iops, AddrModeT2_i8s4, Size4Bytes, itin, opc, asm, "", + : Thumb2I<oops, iops, AddrModeT2_i8s4, 4, itin, opc, asm, "", pattern> { bits<4> Rt; bits<4> Rt2; @@ -1153,32 +1152,32 @@ class T2Ii8s4<bit P, bit W, bit isLoad, dag oops, dag iops, InstrItinClass itin, class T2sI<dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : Thumb2sI<oops, iops, AddrModeNone, Size4Bytes, itin, opc, asm, "", pattern>; + : Thumb2sI<oops, iops, AddrModeNone, 4, itin, opc, asm, "", pattern>; class T2XI<dag oops, dag iops, InstrItinClass itin, string asm, list<dag> pattern> - : Thumb2XI<oops, iops, AddrModeNone, Size4Bytes, itin, asm, "", pattern>; + : Thumb2XI<oops, iops, AddrModeNone, 4, itin, asm, "", pattern>; class T2JTI<dag oops, dag iops, InstrItinClass itin, string asm, list<dag> pattern> - : Thumb2XI<oops, iops, AddrModeNone, SizeSpecial, itin, asm, "", pattern>; + : Thumb2XI<oops, iops, AddrModeNone, 0, itin, asm, "", pattern>; // Move to/from coprocessor instructions -class T2Cop<dag oops, dag iops, string asm, list<dag> pattern> - : T2XI<oops, iops, NoItinerary, asm, pattern>, Requires<[IsThumb2, HasV6]> { - let Inst{31-28} = 0b1111; +class T2Cop<bits<4> opc, dag oops, dag iops, string asm, list<dag> pattern> + : T2XI <oops, iops, NoItinerary, asm, pattern>, Requires<[IsThumb2]> { + let Inst{31-28} = opc; } // Two-address instructions class T2XIt<dag oops, dag iops, InstrItinClass itin, string asm, string cstr, list<dag> pattern> - : Thumb2XI<oops, iops, AddrModeNone, Size4Bytes, itin, asm, cstr, pattern>; + : Thumb2XI<oops, iops, AddrModeNone, 4, itin, asm, cstr, pattern>; // T2Iidxldst - Thumb2 indexed load / store instructions. class T2Iidxldst<bit signed, bits<2> opcod, bit load, bit pre, dag oops, dag iops, AddrMode am, IndexMode im, InstrItinClass itin, string opc, string asm, string cstr, list<dag> pattern> - : InstARM<am, Size4Bytes, im, ThumbFrm, GenericDomain, cstr, itin> { + : InstARM<am, 4, im, ThumbFrm, GenericDomain, cstr, itin> { let OutOperandList = oops; let InOperandList = !con(iops, (ins pred:$p)); let AsmString = !strconcat(opc, "${p}", asm); @@ -1232,7 +1231,7 @@ class T2Pat<dag pattern, dag result> : Pat<pattern, result> { // // Almost all VFP instructions are predicable. -class VFPI<dag oops, dag iops, AddrMode am, SizeFlagVal sz, +class VFPI<dag oops, dag iops, AddrMode am, int sz, IndexMode im, Format f, InstrItinClass itin, string opc, string asm, string cstr, list<dag> pattern> : InstARM<am, sz, im, f, VFPDomain, cstr, itin> { @@ -1247,7 +1246,7 @@ class VFPI<dag oops, dag iops, AddrMode am, SizeFlagVal sz, } // Special cases -class VFPXI<dag oops, dag iops, AddrMode am, SizeFlagVal sz, +class VFPXI<dag oops, dag iops, AddrMode am, int sz, IndexMode im, Format f, InstrItinClass itin, string asm, string cstr, list<dag> pattern> : InstARM<am, sz, im, f, VFPDomain, cstr, itin> { @@ -1263,7 +1262,7 @@ class VFPXI<dag oops, dag iops, AddrMode am, SizeFlagVal sz, class VFPAI<dag oops, dag iops, Format f, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : VFPI<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, f, itin, + : VFPI<oops, iops, AddrModeNone, 4, IndexModeNone, f, itin, opc, asm, "", pattern> { let PostEncoderMethod = "VFPThumb2PostEncoder"; } @@ -1272,7 +1271,7 @@ class VFPAI<dag oops, dag iops, Format f, InstrItinClass itin, class ADI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : VFPI<oops, iops, AddrMode5, Size4Bytes, IndexModeNone, + : VFPI<oops, iops, AddrMode5, 4, IndexModeNone, VFPLdStFrm, itin, opc, asm, "", pattern> { // Instruction operands. bits<5> Dd; @@ -1298,7 +1297,7 @@ class ADI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops, class ASI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> - : VFPI<oops, iops, AddrMode5, Size4Bytes, IndexModeNone, + : VFPI<oops, iops, AddrMode5, 4, IndexModeNone, VFPLdStFrm, itin, opc, asm, "", pattern> { // Instruction operands. bits<5> Sd; @@ -1324,7 +1323,7 @@ class ASI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops, // VFP Load / store multiple pseudo instructions. class PseudoVFPLdStM<dag oops, dag iops, InstrItinClass itin, string cstr, list<dag> pattern> - : InstARM<AddrMode4, Size4Bytes, IndexModeNone, Pseudo, VFPNeonDomain, + : InstARM<AddrMode4, 4, IndexModeNone, Pseudo, VFPNeonDomain, cstr, itin> { let OutOperandList = oops; let InOperandList = !con(iops, (ins pred:$p)); @@ -1335,7 +1334,7 @@ class PseudoVFPLdStM<dag oops, dag iops, InstrItinClass itin, string cstr, // Load / store multiple class AXDI4<dag oops, dag iops, IndexMode im, InstrItinClass itin, string asm, string cstr, list<dag> pattern> - : VFPXI<oops, iops, AddrMode4, Size4Bytes, im, + : VFPXI<oops, iops, AddrMode4, 4, im, VFPLdStMulFrm, itin, asm, cstr, pattern> { // Instruction operands. bits<4> Rn; @@ -1355,7 +1354,7 @@ class AXDI4<dag oops, dag iops, IndexMode im, InstrItinClass itin, class AXSI4<dag oops, dag iops, IndexMode im, InstrItinClass itin, string asm, string cstr, list<dag> pattern> - : VFPXI<oops, iops, AddrMode4, Size4Bytes, im, + : VFPXI<oops, iops, AddrMode4, 4, im, VFPLdStMulFrm, itin, asm, cstr, pattern> { // Instruction operands. bits<4> Rn; @@ -1569,7 +1568,7 @@ class AVConv5I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, class NeonI<dag oops, dag iops, AddrMode am, IndexMode im, Format f, InstrItinClass itin, string opc, string dt, string asm, string cstr, list<dag> pattern> - : InstARM<am, Size4Bytes, im, f, NeonDomain, cstr, itin> { + : InstARM<am, 4, im, f, NeonDomain, cstr, itin> { let OutOperandList = oops; let InOperandList = !con(iops, (ins pred:$p)); let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm); @@ -1581,7 +1580,7 @@ class NeonI<dag oops, dag iops, AddrMode am, IndexMode im, Format f, class NeonXI<dag oops, dag iops, AddrMode am, IndexMode im, Format f, InstrItinClass itin, string opc, string asm, string cstr, list<dag> pattern> - : InstARM<am, Size4Bytes, im, f, NeonDomain, cstr, itin> { + : InstARM<am, 4, im, f, NeonDomain, cstr, itin> { let OutOperandList = oops; let InOperandList = !con(iops, (ins pred:$p)); let AsmString = !strconcat(opc, "${p}", "\t", asm); @@ -1621,7 +1620,7 @@ class NLdStLn<bit op23, bits<2> op21_20, bits<4> op11_8, bits<4> op7_4, } class PseudoNLdSt<dag oops, dag iops, InstrItinClass itin, string cstr> - : InstARM<AddrMode6, Size4Bytes, IndexModeNone, Pseudo, NeonDomain, cstr, + : InstARM<AddrMode6, 4, IndexModeNone, Pseudo, NeonDomain, cstr, itin> { let OutOperandList = oops; let InOperandList = !con(iops, (ins pred:$p)); @@ -1630,7 +1629,7 @@ class PseudoNLdSt<dag oops, dag iops, InstrItinClass itin, string cstr> class PseudoNeonI<dag oops, dag iops, InstrItinClass itin, string cstr, list<dag> pattern> - : InstARM<AddrModeNone, Size4Bytes, IndexModeNone, Pseudo, NeonDomain, cstr, + : InstARM<AddrModeNone, 4, IndexModeNone, Pseudo, NeonDomain, cstr, itin> { let OutOperandList = oops; let InOperandList = !con(iops, (ins pred:$p)); @@ -1859,7 +1858,7 @@ class N3VX<bit op24, bit op23, bits<2> op21_20, bits<4> op11_8, bit op6, class NVLaneOp<bits<8> opcod1, bits<4> opcod2, bits<2> opcod3, dag oops, dag iops, Format f, InstrItinClass itin, string opc, string dt, string asm, list<dag> pattern> - : InstARM<AddrModeNone, Size4Bytes, IndexModeNone, f, NeonDomain, + : InstARM<AddrModeNone, 4, IndexModeNone, f, NeonDomain, "", itin> { let Inst{27-20} = opcod1; let Inst{11-8} = opcod2; diff --git a/lib/Target/ARM/ARMInstrInfo.cpp b/lib/Target/ARM/ARMInstrInfo.cpp index 6f48d967f919..adcbf1806fe3 100644 --- a/lib/Target/ARM/ARMInstrInfo.cpp +++ b/lib/Target/ARM/ARMInstrInfo.cpp @@ -14,7 +14,6 @@ #include "ARMInstrInfo.h" #include "ARM.h" #include "ARMAddressingModes.h" -#include "ARMGenInstrInfo.inc" #include "ARMMachineFunctionInfo.h" #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/LiveVariables.h" diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 9af76df7c37d..a42dd1a54ec7 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -62,6 +62,9 @@ def SDT_ARMEH_SJLJ_DispatchSetup: SDTypeProfile<0, 1, [SDTCisInt<0>]>; def SDT_ARMMEMBARRIER : SDTypeProfile<0, 1, [SDTCisInt<0>]>; +def SDT_ARMPREFETCH : SDTypeProfile<0, 3, [SDTCisPtrTy<0>, SDTCisSameAs<1, 2>, + SDTCisInt<1>]>; + def SDT_ARMTCRET : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; def SDT_ARMBFI : SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisVT<1, i32>, @@ -130,7 +133,7 @@ def ARMMemBarrier : SDNode<"ARMISD::MEMBARRIER", SDT_ARMMEMBARRIER, [SDNPHasChain]>; def ARMMemBarrierMCR : SDNode<"ARMISD::MEMBARRIER_MCR", SDT_ARMMEMBARRIER, [SDNPHasChain]>; -def ARMPreload : SDNode<"ARMISD::PRELOAD", SDTPrefetch, +def ARMPreload : SDNode<"ARMISD::PRELOAD", SDT_ARMPREFETCH, [SDNPHasChain, SDNPMayLoad, SDNPMayStore]>; def ARMrbit : SDNode<"ARMISD::RBIT", SDTIntUnaryOp>; @@ -144,33 +147,48 @@ def ARMbfi : SDNode<"ARMISD::BFI", SDT_ARMBFI>; //===----------------------------------------------------------------------===// // ARM Instruction Predicate Definitions. // -def HasV4T : Predicate<"Subtarget->hasV4TOps()">, AssemblerPredicate; +def HasV4T : Predicate<"Subtarget->hasV4TOps()">, + AssemblerPredicate<"HasV4TOps">; def NoV4T : Predicate<"!Subtarget->hasV4TOps()">; def HasV5T : Predicate<"Subtarget->hasV5TOps()">; -def HasV5TE : Predicate<"Subtarget->hasV5TEOps()">, AssemblerPredicate; -def HasV6 : Predicate<"Subtarget->hasV6Ops()">, AssemblerPredicate; +def HasV5TE : Predicate<"Subtarget->hasV5TEOps()">, + AssemblerPredicate<"HasV5TEOps">; +def HasV6 : Predicate<"Subtarget->hasV6Ops()">, + AssemblerPredicate<"HasV6Ops">; def NoV6 : Predicate<"!Subtarget->hasV6Ops()">; -def HasV6T2 : Predicate<"Subtarget->hasV6T2Ops()">, AssemblerPredicate; +def HasV6T2 : Predicate<"Subtarget->hasV6T2Ops()">, + AssemblerPredicate<"HasV6T2Ops">; def NoV6T2 : Predicate<"!Subtarget->hasV6T2Ops()">; -def HasV7 : Predicate<"Subtarget->hasV7Ops()">, AssemblerPredicate; +def HasV7 : Predicate<"Subtarget->hasV7Ops()">, + AssemblerPredicate<"HasV7Ops">; def NoVFP : Predicate<"!Subtarget->hasVFP2()">; -def HasVFP2 : Predicate<"Subtarget->hasVFP2()">, AssemblerPredicate; -def HasVFP3 : Predicate<"Subtarget->hasVFP3()">, AssemblerPredicate; -def HasNEON : Predicate<"Subtarget->hasNEON()">, AssemblerPredicate; -def HasFP16 : Predicate<"Subtarget->hasFP16()">, AssemblerPredicate; -def HasDivide : Predicate<"Subtarget->hasDivide()">, AssemblerPredicate; +def HasVFP2 : Predicate<"Subtarget->hasVFP2()">, + AssemblerPredicate<"FeatureVFP2">; +def HasVFP3 : Predicate<"Subtarget->hasVFP3()">, + AssemblerPredicate<"FeatureVFP3">; +def HasNEON : Predicate<"Subtarget->hasNEON()">, + AssemblerPredicate<"FeatureNEON">; +def HasFP16 : Predicate<"Subtarget->hasFP16()">, + AssemblerPredicate<"FeatureFP16">; +def HasDivide : Predicate<"Subtarget->hasDivide()">, + AssemblerPredicate<"FeatureHWDiv">; def HasT2ExtractPack : Predicate<"Subtarget->hasT2ExtractPack()">, - AssemblerPredicate; + AssemblerPredicate<"FeatureT2XtPk">; +def HasThumb2DSP : Predicate<"Subtarget->hasThumb2DSP()">, + AssemblerPredicate<"FeatureDSPThumb2">; def HasDB : Predicate<"Subtarget->hasDataBarrier()">, - AssemblerPredicate; + AssemblerPredicate<"FeatureDB">; def HasMP : Predicate<"Subtarget->hasMPExtension()">, - AssemblerPredicate; + AssemblerPredicate<"FeatureMP">; def UseNEONForFP : Predicate<"Subtarget->useNEONForSinglePrecisionFP()">; def DontUseNEONForFP : Predicate<"!Subtarget->useNEONForSinglePrecisionFP()">; -def IsThumb : Predicate<"Subtarget->isThumb()">, AssemblerPredicate; +def IsThumb : Predicate<"Subtarget->isThumb()">, + AssemblerPredicate<"ModeThumb">; def IsThumb1Only : Predicate<"Subtarget->isThumb1Only()">; -def IsThumb2 : Predicate<"Subtarget->isThumb2()">, AssemblerPredicate; -def IsARM : Predicate<"!Subtarget->isThumb()">, AssemblerPredicate; +def IsThumb2 : Predicate<"Subtarget->isThumb2()">, + AssemblerPredicate<"ModeThumb,FeatureThumb2">; +def IsARM : Predicate<"!Subtarget->isThumb()">, + AssemblerPredicate<"!ModeThumb">; def IsDarwin : Predicate<"Subtarget->isTargetDarwin()">; def IsNotDarwin : Predicate<"!Subtarget->isTargetDarwin()">; @@ -237,11 +255,13 @@ def lo16AllZero : PatLeaf<(i32 imm), [{ return (((uint32_t)N->getZExtValue()) & 0xFFFFUL) == 0; }], hi16>; -/// imm0_65535 predicate - True if the 32-bit immediate is in the range -/// [0.65535]. -def imm0_65535 : ImmLeaf<i32, [{ +/// imm0_65535 - An immediate is in the range [0.65535]. +def Imm0_65535AsmOperand: AsmOperandClass { let Name = "Imm0_65535"; } +def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 65536; -}]>; +}]> { + let ParserMatchClass = Imm0_65535AsmOperand; +} class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>; class UnOpFrag <dag res> : PatFrag<(ops node:$Src), res>; @@ -294,16 +314,19 @@ def fsub_mlx : PatFrag<(ops node:$lhs, node:$rhs),(fsub node:$lhs, node:$rhs),[{ // FIXME: rename brtarget to t2_brtarget def brtarget : Operand<OtherVT> { let EncoderMethod = "getBranchTargetOpValue"; + let OperandType = "OPERAND_PCREL"; } // FIXME: get rid of this one? def uncondbrtarget : Operand<OtherVT> { let EncoderMethod = "getUnconditionalBranchTargetOpValue"; + let OperandType = "OPERAND_PCREL"; } // Branch target for ARM. Handles conditional/unconditional def br_target : Operand<OtherVT> { let EncoderMethod = "getARMBranchTargetOpValue"; + let OperandType = "OPERAND_PCREL"; } // Call target. @@ -311,6 +334,7 @@ def br_target : Operand<OtherVT> { def bltarget : Operand<i32> { // Encoded the same as branch targets. let EncoderMethod = "getBranchTargetOpValue"; + let OperandType = "OPERAND_PCREL"; } // Call target for ARM. Handles conditional/unconditional @@ -318,6 +342,7 @@ def bltarget : Operand<i32> { def bl_target : Operand<i32> { // Encoded the same as branch targets. let EncoderMethod = "getARMBranchTargetOpValue"; + let OperandType = "OPERAND_PCREL"; } @@ -394,14 +419,20 @@ def shift_imm : Operand<i32> { let ParserMatchClass = ShifterAsmOperand; } +def ShiftedRegAsmOperand : AsmOperandClass { + let Name = "ShiftedReg"; +} + // shifter_operand operands: so_reg and so_imm. def so_reg : Operand<i32>, // reg reg imm ComplexPattern<i32, 3, "SelectShifterOperandReg", [shl,srl,sra,rotr]> { let EncoderMethod = "getSORegOpValue"; let PrintMethod = "printSORegOperand"; + let ParserMatchClass = ShiftedRegAsmOperand; let MIOperandInfo = (ops GPR, GPR, shift_imm); } +// FIXME: Does this need to be distinct from so_reg? def shift_so_reg : Operand<i32>, // reg reg imm ComplexPattern<i32, 3, "SelectShiftShifterOperandReg", [shl,srl,sra,rotr]> { @@ -416,7 +447,6 @@ def so_imm : Operand<i32>, ImmLeaf<i32, [{ return ARM_AM::getSOImmVal(Imm) != -1; }]> { let EncoderMethod = "getSOImmOpValue"; - let PrintMethod = "printSOImmOperand"; } // Break so_imm's up into two pieces. This handles immediates with up to 16 @@ -434,6 +464,22 @@ def arm_i32imm : PatLeaf<(imm), [{ return ARM_AM::isSOImmTwoPartVal((unsigned)N->getZExtValue()); }]>; +/// imm0_7 predicate - Immediate in the range [0,31]. +def Imm0_7AsmOperand: AsmOperandClass { let Name = "Imm0_7"; } +def imm0_7 : Operand<i32>, ImmLeaf<i32, [{ + return Imm >= 0 && Imm < 8; +}]> { + let ParserMatchClass = Imm0_7AsmOperand; +} + +/// imm0_15 predicate - Immediate in the range [0,31]. +def Imm0_15AsmOperand: AsmOperandClass { let Name = "Imm0_15"; } +def imm0_15 : Operand<i32>, ImmLeaf<i32, [{ + return Imm >= 0 && Imm < 16; +}]> { + let ParserMatchClass = Imm0_15AsmOperand; +} + /// imm0_31 predicate - True if the 32-bit immediate is in the range [0,31]. def imm0_31 : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 32; @@ -673,7 +719,7 @@ include "ARMInstrFormats.td" /// binop that produces a value. multiclass AsI1_bin_irs<bits<4> opcod, string opc, InstrItinClass iii, InstrItinClass iir, InstrItinClass iis, - PatFrag opnode, bit Commutable = 0> { + PatFrag opnode, string baseOpc, bit Commutable = 0> { // The register-immediate version is re-materializable. This is useful // in particular for taking the address of a local. let isReMaterializable = 1 in { @@ -713,6 +759,24 @@ multiclass AsI1_bin_irs<bits<4> opcod, string opc, let Inst{15-12} = Rd; let Inst{11-0} = shift; } + + // Assembly aliases for optional destination operand when it's the same + // as the source operand. + def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $imm"), + (!cast<Instruction>(!strconcat(baseOpc, "ri")) GPR:$Rdn, GPR:$Rdn, + so_imm:$imm, pred:$p, + cc_out:$s)>, + Requires<[IsARM]>; + def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $Rm"), + (!cast<Instruction>(!strconcat(baseOpc, "rr")) GPR:$Rdn, GPR:$Rdn, + GPR:$Rm, pred:$p, + cc_out:$s)>, + Requires<[IsARM]>; + def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $shift"), + (!cast<Instruction>(!strconcat(baseOpc, "rs")) GPR:$Rdn, GPR:$Rdn, + so_reg:$shift, pred:$p, + cc_out:$s)>, + Requires<[IsARM]>; } /// AI1_bin_s_irs - Similar to AsI1_bin_irs except it sets the 's' bit so the @@ -909,9 +973,9 @@ multiclass AI_exta_rrot_np<bits<8> opcod, string opc> { } /// AI1_adde_sube_irs - Define instructions and patterns for adde and sube. -let Uses = [CPSR] in { multiclass AI1_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode, - bit Commutable = 0> { + string baseOpc, bit Commutable = 0> { + let Uses = [CPSR] in { def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm, IIC_iALUi, opc, "\t$Rd, $Rn, $imm", [(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]>, @@ -950,7 +1014,24 @@ multiclass AI1_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode, let Inst{15-12} = Rd; let Inst{19-16} = Rn; } -} + } + // Assembly aliases for optional destination operand when it's the same + // as the source operand. + def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $imm"), + (!cast<Instruction>(!strconcat(baseOpc, "ri")) GPR:$Rdn, GPR:$Rdn, + so_imm:$imm, pred:$p, + cc_out:$s)>, + Requires<[IsARM]>; + def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $Rm"), + (!cast<Instruction>(!strconcat(baseOpc, "rr")) GPR:$Rdn, GPR:$Rdn, + GPR:$Rm, pred:$p, + cc_out:$s)>, + Requires<[IsARM]>; + def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $shift"), + (!cast<Instruction>(!strconcat(baseOpc, "rs")) GPR:$Rdn, GPR:$Rdn, + so_reg:$shift, pred:$p, + cc_out:$s)>, + Requires<[IsARM]>; } // Carry setting variants @@ -958,15 +1039,15 @@ multiclass AI1_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode, let usesCustomInserter = 1 in { multiclass AI1_adde_sube_s_irs<PatFrag opnode, bit Commutable = 0> { def ri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), - Size4Bytes, IIC_iALUi, + 4, IIC_iALUi, [(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]>; def rr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), - Size4Bytes, IIC_iALUr, + 4, IIC_iALUr, [(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]> { let isCommutable = Commutable; } def rs : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), - Size4Bytes, IIC_iALUsr, + 4, IIC_iALUsr, [(set GPR:$Rd, (opnode GPR:$Rn, so_reg:$shift))]>; } } @@ -1116,9 +1197,8 @@ def SEV : AI<(outs), (ins), MiscFrm, NoItinerary, "sev", "", // The i32imm operand $val can be used by a debugger to store more information // about the breakpoint. -def BKPT : AI<(outs), (ins i32imm:$val), MiscFrm, NoItinerary, "bkpt", "\t$val", - [/* For disassembly only; pattern left blank */]>, - Requires<[IsARM]> { +def BKPT : AI<(outs), (ins imm0_65535:$val), MiscFrm, NoItinerary, + "bkpt", "\t$val", []>, Requires<[IsARM]> { bits<16> val; let Inst{3-0} = val{3-0}; let Inst{19-8} = val{15-4}; @@ -1208,9 +1288,8 @@ def SETEND : AXI<(outs),(ins setend_op:$end), MiscFrm, NoItinerary, let Inst{8-0} = 0; } -def DBG : AI<(outs), (ins i32imm:$opt), MiscFrm, NoItinerary, "dbg", "\t$opt", - [/* For disassembly only; pattern left blank */]>, - Requires<[IsARM, HasV7]> { +def DBG : AI<(outs), (ins imm0_15:$opt), MiscFrm, NoItinerary, "dbg", "\t$opt", + []>, Requires<[IsARM, HasV7]> { bits<4> opt; let Inst{27-4} = 0b001100100000111100001111; let Inst{3-0} = opt; @@ -1227,40 +1306,40 @@ def TRAP : AXI<(outs), (ins), MiscFrm, NoItinerary, // Address computation and loads and stores in PIC mode. let isNotDuplicable = 1 in { def PICADD : ARMPseudoInst<(outs GPR:$dst), (ins GPR:$a, pclabel:$cp, pred:$p), - Size4Bytes, IIC_iALUr, + 4, IIC_iALUr, [(set GPR:$dst, (ARMpic_add GPR:$a, imm:$cp))]>; let AddedComplexity = 10 in { def PICLDR : ARMPseudoInst<(outs GPR:$dst), (ins addrmodepc:$addr, pred:$p), - Size4Bytes, IIC_iLoad_r, + 4, IIC_iLoad_r, [(set GPR:$dst, (load addrmodepc:$addr))]>; def PICLDRH : ARMPseudoInst<(outs GPR:$Rt), (ins addrmodepc:$addr, pred:$p), - Size4Bytes, IIC_iLoad_bh_r, + 4, IIC_iLoad_bh_r, [(set GPR:$Rt, (zextloadi16 addrmodepc:$addr))]>; def PICLDRB : ARMPseudoInst<(outs GPR:$Rt), (ins addrmodepc:$addr, pred:$p), - Size4Bytes, IIC_iLoad_bh_r, + 4, IIC_iLoad_bh_r, [(set GPR:$Rt, (zextloadi8 addrmodepc:$addr))]>; def PICLDRSH : ARMPseudoInst<(outs GPR:$Rt), (ins addrmodepc:$addr, pred:$p), - Size4Bytes, IIC_iLoad_bh_r, + 4, IIC_iLoad_bh_r, [(set GPR:$Rt, (sextloadi16 addrmodepc:$addr))]>; def PICLDRSB : ARMPseudoInst<(outs GPR:$Rt), (ins addrmodepc:$addr, pred:$p), - Size4Bytes, IIC_iLoad_bh_r, + 4, IIC_iLoad_bh_r, [(set GPR:$Rt, (sextloadi8 addrmodepc:$addr))]>; } let AddedComplexity = 10 in { def PICSTR : ARMPseudoInst<(outs), (ins GPR:$src, addrmodepc:$addr, pred:$p), - Size4Bytes, IIC_iStore_r, [(store GPR:$src, addrmodepc:$addr)]>; + 4, IIC_iStore_r, [(store GPR:$src, addrmodepc:$addr)]>; def PICSTRH : ARMPseudoInst<(outs), (ins GPR:$src, addrmodepc:$addr, pred:$p), - Size4Bytes, IIC_iStore_bh_r, [(truncstorei16 GPR:$src, + 4, IIC_iStore_bh_r, [(truncstorei16 GPR:$src, addrmodepc:$addr)]>; def PICSTRB : ARMPseudoInst<(outs), (ins GPR:$src, addrmodepc:$addr, pred:$p), - Size4Bytes, IIC_iStore_bh_r, [(truncstorei8 GPR:$src, addrmodepc:$addr)]>; + 4, IIC_iStore_bh_r, [(truncstorei8 GPR:$src, addrmodepc:$addr)]>; } } // isNotDuplicable = 1 @@ -1282,11 +1361,11 @@ def ADR : AI1<{0,?,?,0}, (outs GPR:$Rd), (ins adrlabel:$label), let Inst{11-0} = label; } def LEApcrel : ARMPseudoInst<(outs GPR:$Rd), (ins i32imm:$label, pred:$p), - Size4Bytes, IIC_iALUi, []>; + 4, IIC_iALUi, []>; def LEApcrelJT : ARMPseudoInst<(outs GPR:$Rd), (ins i32imm:$label, nohash_imm:$id, pred:$p), - Size4Bytes, IIC_iALUi, []>; + 4, IIC_iALUi, []>; //===----------------------------------------------------------------------===// // Control Flow Instructions. @@ -1319,22 +1398,13 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { let Inst{3-0} = dst; } - // For disassembly only. - def BX_pred : AXI<(outs), (ins GPR:$dst, pred:$p), BrMiscFrm, IIC_Br, - "bx$p\t$dst", [/* pattern left blank */]>, + def BX_pred : AI<(outs), (ins GPR:$dst), BrMiscFrm, IIC_Br, + "bx", "\t$dst", [/* pattern left blank */]>, Requires<[IsARM, HasV4T]> { bits<4> dst; let Inst{27-4} = 0b000100101111111111110001; let Inst{3-0} = dst; } - - // ARMV4 only - // FIXME: We would really like to define this as a vanilla ARMPat like: - // ARMPat<(brind GPR:$dst), (MOVr PC, GPR:$dst)> - // With that, however, we can't set isBranch, isTerminator, etc.. - def MOVPCRX : ARMPseudoInst<(outs), (ins GPR:$dst), - Size4Bytes, IIC_Br, [(brind GPR:$dst)]>, - Requires<[IsARM, NoV4T]>; } // All calls clobber the non-callee saved registers. SP is marked as @@ -1386,12 +1456,12 @@ let isCall = 1, // ARMv4T // Note: Restrict $func to the tGPR regclass to prevent it being in LR. def BX_CALL : ARMPseudoInst<(outs), (ins tGPR:$func, variable_ops), - Size8Bytes, IIC_Br, [(ARMcall_nolink tGPR:$func)]>, + 8, IIC_Br, [(ARMcall_nolink tGPR:$func)]>, Requires<[IsARM, HasV4T, IsNotDarwin]>; // ARMv4 def BMOVPCRX_CALL : ARMPseudoInst<(outs), (ins tGPR:$func, variable_ops), - Size8Bytes, IIC_Br, [(ARMcall_nolink tGPR:$func)]>, + 8, IIC_Br, [(ARMcall_nolink tGPR:$func)]>, Requires<[IsARM, NoV4T, IsNotDarwin]>; } @@ -1401,131 +1471,82 @@ let isCall = 1, // moved above / below calls. Defs = [R0, R1, R2, R3, R9, R12, LR, QQQQ0, QQQQ2, QQQQ3, CPSR, FPSCR], Uses = [R7, SP] in { - def BLr9 : ARMPseudoInst<(outs), (ins bltarget:$func, variable_ops), - Size4Bytes, IIC_Br, - [(ARMcall tglobaladdr:$func)]>, Requires<[IsARM, IsDarwin]>; - - def BLr9_pred : ARMPseudoInst<(outs), - (ins bltarget:$func, pred:$p, variable_ops), - Size4Bytes, IIC_Br, - [(ARMcall_pred tglobaladdr:$func)]>, + def BLr9 : ARMPseudoExpand<(outs), (ins bl_target:$func, variable_ops), + 4, IIC_Br, + [(ARMcall tglobaladdr:$func)], (BL bl_target:$func)>, + Requires<[IsARM, IsDarwin]>; + + def BLr9_pred : ARMPseudoExpand<(outs), + (ins bl_target:$func, pred:$p, variable_ops), + 4, IIC_Br, + [(ARMcall_pred tglobaladdr:$func)], + (BL_pred bl_target:$func, pred:$p)>, Requires<[IsARM, IsDarwin]>; // ARMv5T and above - def BLXr9 : ARMPseudoInst<(outs), (ins GPR:$func, variable_ops), - Size4Bytes, IIC_Br, - [(ARMcall GPR:$func)]>, Requires<[IsARM, HasV5T, IsDarwin]>; - - def BLXr9_pred: ARMPseudoInst<(outs), (ins GPR:$func, pred:$p, variable_ops), - Size4Bytes, IIC_Br, - [(ARMcall_pred GPR:$func)]>, + def BLXr9 : ARMPseudoExpand<(outs), (ins GPR:$func, variable_ops), + 4, IIC_Br, + [(ARMcall GPR:$func)], + (BLX GPR:$func)>, + Requires<[IsARM, HasV5T, IsDarwin]>; + + def BLXr9_pred: ARMPseudoExpand<(outs), (ins GPR:$func, pred:$p,variable_ops), + 4, IIC_Br, + [(ARMcall_pred GPR:$func)], + (BLX_pred GPR:$func, pred:$p)>, Requires<[IsARM, HasV5T, IsDarwin]>; // ARMv4T // Note: Restrict $func to the tGPR regclass to prevent it being in LR. def BXr9_CALL : ARMPseudoInst<(outs), (ins tGPR:$func, variable_ops), - Size8Bytes, IIC_Br, [(ARMcall_nolink tGPR:$func)]>, + 8, IIC_Br, [(ARMcall_nolink tGPR:$func)]>, Requires<[IsARM, HasV4T, IsDarwin]>; // ARMv4 def BMOVPCRXr9_CALL : ARMPseudoInst<(outs), (ins tGPR:$func, variable_ops), - Size8Bytes, IIC_Br, [(ARMcall_nolink tGPR:$func)]>, + 8, IIC_Br, [(ARMcall_nolink tGPR:$func)]>, Requires<[IsARM, NoV4T, IsDarwin]>; } -// Tail calls. - -// FIXME: The Thumb versions of these should live in ARMInstrThumb.td -let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in { - // Darwin versions. - let Defs = [R0, R1, R2, R3, R9, R12, QQQQ0, QQQQ2, QQQQ3, PC], - Uses = [SP] in { - def TCRETURNdi : PseudoInst<(outs), (ins i32imm:$dst, variable_ops), - IIC_Br, []>, Requires<[IsDarwin]>; - - def TCRETURNri : PseudoInst<(outs), (ins tcGPR:$dst, variable_ops), - IIC_Br, []>, Requires<[IsDarwin]>; - - def TAILJMPd : ARMPseudoInst<(outs), (ins brtarget:$dst, variable_ops), - Size4Bytes, IIC_Br, - []>, Requires<[IsARM, IsDarwin]>; - - def tTAILJMPd: tPseudoInst<(outs), (ins brtarget:$dst, variable_ops), - Size4Bytes, IIC_Br, - []>, Requires<[IsThumb, IsDarwin]>; - - def TAILJMPr : ARMPseudoInst<(outs), (ins tcGPR:$dst, variable_ops), - Size4Bytes, IIC_Br, - []>, Requires<[IsARM, IsDarwin]>; - - def tTAILJMPr : tPseudoInst<(outs), (ins tcGPR:$dst, variable_ops), - Size4Bytes, IIC_Br, - []>, Requires<[IsThumb, IsDarwin]>; - } - - // Non-Darwin versions (the difference is R9). - let Defs = [R0, R1, R2, R3, R12, QQQQ0, QQQQ2, QQQQ3, PC], - Uses = [SP] in { - def TCRETURNdiND : PseudoInst<(outs), (ins i32imm:$dst, variable_ops), - IIC_Br, []>, Requires<[IsNotDarwin]>; - - def TCRETURNriND : PseudoInst<(outs), (ins tcGPR:$dst, variable_ops), - IIC_Br, []>, Requires<[IsNotDarwin]>; - - def TAILJMPdND : ARMPseudoInst<(outs), (ins brtarget:$dst, variable_ops), - Size4Bytes, IIC_Br, - []>, Requires<[IsARM, IsNotDarwin]>; - - def tTAILJMPdND : tPseudoInst<(outs), (ins brtarget:$dst, variable_ops), - Size4Bytes, IIC_Br, - []>, Requires<[IsThumb, IsNotDarwin]>; - - def TAILJMPrND : ARMPseudoInst<(outs), (ins tcGPR:$dst, variable_ops), - Size4Bytes, IIC_Br, - []>, Requires<[IsARM, IsNotDarwin]>; - def tTAILJMPrND : tPseudoInst<(outs), (ins tcGPR:$dst, variable_ops), - Size4Bytes, IIC_Br, - []>, Requires<[IsThumb, IsNotDarwin]>; +let isBranch = 1, isTerminator = 1 in { + // FIXME: should be able to write a pattern for ARMBrcond, but can't use + // a two-value operand where a dag node expects two operands. :( + def Bcc : ABI<0b1010, (outs), (ins br_target:$target), + IIC_Br, "b", "\t$target", + [/*(ARMbrcond bb:$target, imm:$cc, CCR:$ccr)*/]> { + bits<24> target; + let Inst{23-0} = target; } -} -let isBranch = 1, isTerminator = 1 in { - // B is "predicable" since it's just a Bcc with an 'always' condition. let isBarrier = 1 in { + // B is "predicable" since it's just a Bcc with an 'always' condition. let isPredicable = 1 in // FIXME: We shouldn't need this pseudo at all. Just using Bcc directly // should be sufficient. - def B : ARMPseudoInst<(outs), (ins brtarget:$target), Size4Bytes, IIC_Br, - [(br bb:$target)]>; + // FIXME: Is B really a Barrier? That doesn't seem right. + def B : ARMPseudoExpand<(outs), (ins br_target:$target), 4, IIC_Br, + [(br bb:$target)], (Bcc br_target:$target, (ops 14, zero_reg))>; let isNotDuplicable = 1, isIndirectBranch = 1 in { def BR_JTr : ARMPseudoInst<(outs), (ins GPR:$target, i32imm:$jt, i32imm:$id), - SizeSpecial, IIC_Br, + 0, IIC_Br, [(ARMbrjt GPR:$target, tjumptable:$jt, imm:$id)]>; // FIXME: This shouldn't use the generic "addrmode2," but rather be split // into i12 and rs suffixed versions. def BR_JTm : ARMPseudoInst<(outs), (ins addrmode2:$target, i32imm:$jt, i32imm:$id), - SizeSpecial, IIC_Br, + 0, IIC_Br, [(ARMbrjt (i32 (load addrmode2:$target)), tjumptable:$jt, imm:$id)]>; def BR_JTadd : ARMPseudoInst<(outs), (ins GPR:$target, GPR:$idx, i32imm:$jt, i32imm:$id), - SizeSpecial, IIC_Br, + 0, IIC_Br, [(ARMbrjt (add GPR:$target, GPR:$idx), tjumptable:$jt, imm:$id)]>; } // isNotDuplicable = 1, isIndirectBranch = 1 } // isBarrier = 1 - // FIXME: should be able to write a pattern for ARMBrcond, but can't use - // a two-value operand where a dag node expects two operands. :( - def Bcc : ABI<0b1010, (outs), (ins br_target:$target), - IIC_Br, "b", "\t$target", - [/*(ARMbrcond bb:$target, imm:$cc, CCR:$ccr)*/]> { - bits<24> target; - let Inst{23-0} = target; - } } // BLX (immediate) -- for disassembly only @@ -1538,14 +1559,65 @@ def BLXi : AXI<(outs), (ins br_target:$target), BrMiscFrm, NoItinerary, let Inst{24} = target{0}; } -// Branch and Exchange Jazelle -- for disassembly only +// Branch and Exchange Jazelle def BXJ : ABI<0b0001, (outs), (ins GPR:$func), NoItinerary, "bxj", "\t$func", - [/* For disassembly only; pattern left blank */]> { + [/* pattern left blank */]> { + bits<4> func; let Inst{23-20} = 0b0010; - //let Inst{19-8} = 0xfff; + let Inst{19-8} = 0xfff; let Inst{7-4} = 0b0010; + let Inst{3-0} = func; +} + +// Tail calls. + +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in { + // Darwin versions. + let Defs = [R0, R1, R2, R3, R9, R12, QQQQ0, QQQQ2, QQQQ3, PC], + Uses = [SP] in { + def TCRETURNdi : PseudoInst<(outs), (ins i32imm:$dst, variable_ops), + IIC_Br, []>, Requires<[IsDarwin]>; + + def TCRETURNri : PseudoInst<(outs), (ins tcGPR:$dst, variable_ops), + IIC_Br, []>, Requires<[IsDarwin]>; + + def TAILJMPd : ARMPseudoExpand<(outs), (ins br_target:$dst, variable_ops), + 4, IIC_Br, [], + (Bcc br_target:$dst, (ops 14, zero_reg))>, + Requires<[IsARM, IsDarwin]>; + + def TAILJMPr : ARMPseudoExpand<(outs), (ins tcGPR:$dst, variable_ops), + 4, IIC_Br, [], + (BX GPR:$dst)>, + Requires<[IsARM, IsDarwin]>; + + } + + // Non-Darwin versions (the difference is R9). + let Defs = [R0, R1, R2, R3, R12, QQQQ0, QQQQ2, QQQQ3, PC], + Uses = [SP] in { + def TCRETURNdiND : PseudoInst<(outs), (ins i32imm:$dst, variable_ops), + IIC_Br, []>, Requires<[IsNotDarwin]>; + + def TCRETURNriND : PseudoInst<(outs), (ins tcGPR:$dst, variable_ops), + IIC_Br, []>, Requires<[IsNotDarwin]>; + + def TAILJMPdND : ARMPseudoExpand<(outs), (ins brtarget:$dst, variable_ops), + 4, IIC_Br, [], + (Bcc br_target:$dst, (ops 14, zero_reg))>, + Requires<[IsARM, IsNotDarwin]>; + + def TAILJMPrND : ARMPseudoExpand<(outs), (ins tcGPR:$dst, variable_ops), + 4, IIC_Br, [], + (BX GPR:$dst)>, + Requires<[IsARM, IsNotDarwin]>; + } } + + + + // Secure Monitor Call is a system instruction -- for disassembly only def SMC : ABI<0b0001, (outs), (ins i32imm:$opt), NoItinerary, "smc", "\t$opt", [/* For disassembly only; pattern left blank */]> { @@ -1562,7 +1634,6 @@ def SVC : ABI<0b1111, (outs), (ins i32imm:$svc), IIC_Br, "svc", "\t$svc", let Inst{23-0} = svc; } } -def : MnemonicAlias<"swi", "svc">; // Store Return State is a system instruction -- for disassembly only let isCodeGenOnly = 1 in { // FIXME: This should not use submode! @@ -1908,10 +1979,12 @@ def STRHT: AI3sthpo<(outs GPR:$base_wb), (ins GPR:$Rt, addrmode3:$addr), multiclass arm_ldst_mult<string asm, bit L_bit, Format f, InstrItinClass itin, InstrItinClass itin_upd> { + // IA is the default, so no need for an explicit suffix on the + // mnemonic here. Without it is the cannonical spelling. def IA : AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), IndexModeNone, f, itin, - !strconcat(asm, "ia${p}\t$Rn, $regs"), "", []> { + !strconcat(asm, "${p}\t$Rn, $regs"), "", []> { let Inst{24-23} = 0b01; // Increment After let Inst{21} = 0; // No writeback let Inst{20} = L_bit; @@ -1919,7 +1992,7 @@ multiclass arm_ldst_mult<string asm, bit L_bit, Format f, def IA_UPD : AXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), IndexModeUpd, f, itin_upd, - !strconcat(asm, "ia${p}\t$Rn!, $regs"), "$Rn = $wb", []> { + !strconcat(asm, "${p}\t$Rn!, $regs"), "$Rn = $wb", []> { let Inst{24-23} = 0b01; // Increment After let Inst{21} = 1; // Writeback let Inst{20} = L_bit; @@ -1984,17 +2057,14 @@ defm STM : arm_ldst_mult<"stm", 0, LdStMulFrm, IIC_iStore_m, IIC_iStore_mu>; } // neverHasSideEffects -// Load / Store Multiple Mnemonic Aliases -def : MnemonicAlias<"ldm", "ldmia">; -def : MnemonicAlias<"stm", "stmia">; - // FIXME: remove when we have a way to marking a MI with these properties. // FIXME: Should pc be an implicit operand like PICADD, etc? let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, hasExtraDefRegAllocReq = 1, isCodeGenOnly = 1 in -def LDMIA_RET : ARMPseudoInst<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, - reglist:$regs, variable_ops), - Size4Bytes, IIC_iLoad_mBr, []>, +def LDMIA_RET : ARMPseudoExpand<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, + reglist:$regs, variable_ops), + 4, IIC_iLoad_mBr, [], + (LDMIA_UPD GPR:$wb, GPR:$Rn, pred:$p, reglist:$regs)>, RegConstraint<"$Rn = $wb">; //===----------------------------------------------------------------------===// @@ -2164,7 +2234,7 @@ defm UXTAB16 : AI_exta_rrot_np<0b01101100, "uxtab16">; def SBFX : I<(outs GPR:$Rd), (ins GPR:$Rn, imm0_31:$lsb, imm0_31_m1:$width), - AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi, + AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi, "sbfx", "\t$Rd, $Rn, $lsb, $width", "", []>, Requires<[IsARM, HasV6T2]> { bits<4> Rd; @@ -2181,7 +2251,7 @@ def SBFX : I<(outs GPR:$Rd), def UBFX : I<(outs GPR:$Rd), (ins GPR:$Rn, imm0_31:$lsb, imm0_31_m1:$width), - AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi, + AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi, "ubfx", "\t$Rd, $Rn, $lsb, $width", "", []>, Requires<[IsARM, HasV6T2]> { bits<4> Rd; @@ -2202,10 +2272,10 @@ def UBFX : I<(outs GPR:$Rd), defm ADD : AsI1_bin_irs<0b0100, "add", IIC_iALUi, IIC_iALUr, IIC_iALUsr, - BinOpFrag<(add node:$LHS, node:$RHS)>, 1>; + BinOpFrag<(add node:$LHS, node:$RHS)>, "ADD", 1>; defm SUB : AsI1_bin_irs<0b0010, "sub", IIC_iALUi, IIC_iALUr, IIC_iALUsr, - BinOpFrag<(sub node:$LHS, node:$RHS)>>; + BinOpFrag<(sub node:$LHS, node:$RHS)>, "SUB">; // ADD and SUB with 's' bit set. defm ADDS : AI1_bin_s_irs<0b0100, "adds", @@ -2216,9 +2286,11 @@ defm SUBS : AI1_bin_s_irs<0b0010, "subs", BinOpFrag<(subc node:$LHS, node:$RHS)>>; defm ADC : AI1_adde_sube_irs<0b0101, "adc", - BinOpFrag<(adde_dead_carry node:$LHS, node:$RHS)>, 1>; + BinOpFrag<(adde_dead_carry node:$LHS, node:$RHS)>, + "ADC", 1>; defm SBC : AI1_adde_sube_irs<0b0110, "sbc", - BinOpFrag<(sube_dead_carry node:$LHS, node:$RHS)>>; + BinOpFrag<(sube_dead_carry node:$LHS, node:$RHS)>, + "SBC">; // ADC and SUBC with 's' bit set. let usesCustomInserter = 1 in { @@ -2271,13 +2343,13 @@ def RSBrs : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), // NOTE: CPSR def omitted because it will be handled by the custom inserter. let usesCustomInserter = 1 in { def RSBSri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), - Size4Bytes, IIC_iALUi, + 4, IIC_iALUi, [(set GPR:$Rd, (subc so_imm:$imm, GPR:$Rn))]>; def RSBSrr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), - Size4Bytes, IIC_iALUr, + 4, IIC_iALUr, [/* For disassembly only; pattern left blank */]>; def RSBSrs : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), - Size4Bytes, IIC_iALUsr, + 4, IIC_iALUsr, [(set GPR:$Rd, (subc so_reg:$shift, GPR:$Rn))]>; } @@ -2325,10 +2397,10 @@ def RSCrs : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), // NOTE: CPSR def omitted because it will be handled by the custom inserter. let usesCustomInserter = 1, Uses = [CPSR] in { def RSCSri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), - Size4Bytes, IIC_iALUi, + 4, IIC_iALUi, [(set GPR:$Rd, (sube_dead_carry so_imm:$imm, GPR:$Rn))]>; def RSCSrs : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), - Size4Bytes, IIC_iALUsr, + 4, IIC_iALUsr, [(set GPR:$Rd, (sube_dead_carry so_reg:$shift, GPR:$Rn))]>; } @@ -2528,19 +2600,19 @@ def : ARMV6Pat<(int_arm_usat GPR:$a, imm:$pos), (USAT imm:$pos, GPR:$a, 0)>; defm AND : AsI1_bin_irs<0b0000, "and", IIC_iBITi, IIC_iBITr, IIC_iBITsr, - BinOpFrag<(and node:$LHS, node:$RHS)>, 1>; + BinOpFrag<(and node:$LHS, node:$RHS)>, "AND", 1>; defm ORR : AsI1_bin_irs<0b1100, "orr", IIC_iBITi, IIC_iBITr, IIC_iBITsr, - BinOpFrag<(or node:$LHS, node:$RHS)>, 1>; + BinOpFrag<(or node:$LHS, node:$RHS)>, "ORR", 1>; defm EOR : AsI1_bin_irs<0b0001, "eor", IIC_iBITi, IIC_iBITr, IIC_iBITsr, - BinOpFrag<(xor node:$LHS, node:$RHS)>, 1>; + BinOpFrag<(xor node:$LHS, node:$RHS)>, "EOR", 1>; defm BIC : AsI1_bin_irs<0b1110, "bic", IIC_iBITi, IIC_iBITr, IIC_iBITsr, - BinOpFrag<(and node:$LHS, (not node:$RHS))>>; + BinOpFrag<(and node:$LHS, (not node:$RHS))>, "BIC">; def BFC : I<(outs GPR:$Rd), (ins GPR:$src, bf_inv_mask_imm:$imm), - AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi, + AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi, "bfc", "\t$Rd, $imm", "$src = $Rd", [(set GPR:$Rd, (and GPR:$src, bf_inv_mask_imm:$imm))]>, Requires<[IsARM, HasV6T2]> { @@ -2555,7 +2627,7 @@ def BFC : I<(outs GPR:$Rd), (ins GPR:$src, bf_inv_mask_imm:$imm), // A8.6.18 BFI - Bitfield insert (Encoding A1) def BFI : I<(outs GPR:$Rd), (ins GPR:$src, GPR:$Rn, bf_inv_mask_imm:$imm), - AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi, + AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi, "bfi", "\t$Rd, $Rn, $imm", "$src = $Rd", [(set GPR:$Rd, (ARMbfi GPR:$src, GPR:$Rn, bf_inv_mask_imm:$imm))]>, @@ -2575,7 +2647,7 @@ def BFI : I<(outs GPR:$Rd), (ins GPR:$src, GPR:$Rn, bf_inv_mask_imm:$imm), let isAsmParserOnly = 1 in def BFI4p : I<(outs GPR:$Rd), (ins GPR:$src, GPR:$Rn, lsb_pos_imm:$lsb, width_imm:$width), - AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi, + AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi, "bfi", "\t$Rd, $Rn, $lsb, $width", "$src = $Rd", []>, Requires<[IsARM, HasV6T2]> { bits<4> Rd; @@ -2652,31 +2724,26 @@ class AsMul1I64<bits<7> opcod, dag oops, dag iops, InstrItinClass itin, let Inst{3-0} = Rn; } +// FIXME: The v5 pseudos are only necessary for the additional Constraint +// property. Remove them when it's possible to add those properties +// on an individual MachineInstr, not just an instuction description. let isCommutable = 1 in { -let Constraints = "@earlyclobber $Rd" in -def MULv5: ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, - pred:$p, cc_out:$s), - Size4Bytes, IIC_iMUL32, - [(set GPR:$Rd, (mul GPR:$Rn, GPR:$Rm))]>, - Requires<[IsARM, NoV6]>; - def MUL : AsMul1I32<0b0000000, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), IIC_iMUL32, "mul", "\t$Rd, $Rn, $Rm", [(set GPR:$Rd, (mul GPR:$Rn, GPR:$Rm))]>, Requires<[IsARM, HasV6]> { let Inst{15-12} = 0b0000; } -} let Constraints = "@earlyclobber $Rd" in -def MLAv5: ARMPseudoInst<(outs GPR:$Rd), - (ins GPR:$Rn, GPR:$Rm, GPR:$Ra, pred:$p, cc_out:$s), - Size4Bytes, IIC_iMAC32, - [(set GPR:$Rd, (add (mul GPR:$Rn, GPR:$Rm), GPR:$Ra))]>, - Requires<[IsARM, NoV6]> { - bits<4> Ra; - let Inst{15-12} = Ra; +def MULv5: ARMPseudoExpand<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, + pred:$p, cc_out:$s), + 4, IIC_iMUL32, + [(set GPR:$Rd, (mul GPR:$Rn, GPR:$Rm))], + (MUL GPR:$Rd, GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s)>, + Requires<[IsARM, NoV6]>; } + def MLA : AsMul1I32<0b0000001, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), IIC_iMAC32, "mla", "\t$Rd, $Rn, $Rm, $Ra", [(set GPR:$Rd, (add (mul GPR:$Rn, GPR:$Rm), GPR:$Ra))]>, @@ -2685,6 +2752,14 @@ def MLA : AsMul1I32<0b0000001, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), let Inst{15-12} = Ra; } +let Constraints = "@earlyclobber $Rd" in +def MLAv5: ARMPseudoExpand<(outs GPR:$Rd), + (ins GPR:$Rn, GPR:$Rm, GPR:$Ra, pred:$p, cc_out:$s), + 4, IIC_iMAC32, + [(set GPR:$Rd, (add (mul GPR:$Rn, GPR:$Rm), GPR:$Ra))], + (MLA GPR:$Rd, GPR:$Rn, GPR:$Rm, GPR:$Ra, pred:$p, cc_out:$s)>, + Requires<[IsARM, NoV6]>; + def MLS : AMul1I<0b0000011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), IIC_iMAC32, "mls", "\t$Rd, $Rn, $Rm, $Ra", [(set GPR:$Rd, (sub GPR:$Ra, (mul GPR:$Rn, GPR:$Rm)))]>, @@ -2700,49 +2775,34 @@ def MLS : AMul1I<0b0000011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), } // Extra precision multiplies with low / high results - let neverHasSideEffects = 1 in { let isCommutable = 1 in { -let Constraints = "@earlyclobber $RdLo,@earlyclobber $RdHi" in { -def SMULLv5 : ARMPseudoInst<(outs GPR:$RdLo, GPR:$RdHi), - (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s), - Size4Bytes, IIC_iMUL64, []>, - Requires<[IsARM, NoV6]>; - -def UMULLv5 : ARMPseudoInst<(outs GPR:$RdLo, GPR:$RdHi), - (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s), - Size4Bytes, IIC_iMUL64, []>, - Requires<[IsARM, NoV6]>; -} - def SMULL : AsMul1I64<0b0000110, (outs GPR:$RdLo, GPR:$RdHi), - (ins GPR:$Rn, GPR:$Rm), IIC_iMUL64, + (ins GPR:$Rn, GPR:$Rm), IIC_iMUL64, "smull", "\t$RdLo, $RdHi, $Rn, $Rm", []>, Requires<[IsARM, HasV6]>; def UMULL : AsMul1I64<0b0000100, (outs GPR:$RdLo, GPR:$RdHi), - (ins GPR:$Rn, GPR:$Rm), IIC_iMUL64, + (ins GPR:$Rn, GPR:$Rm), IIC_iMUL64, "umull", "\t$RdLo, $RdHi, $Rn, $Rm", []>, Requires<[IsARM, HasV6]>; -} -// Multiply + accumulate let Constraints = "@earlyclobber $RdLo,@earlyclobber $RdHi" in { -def SMLALv5 : ARMPseudoInst<(outs GPR:$RdLo, GPR:$RdHi), - (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s), - Size4Bytes, IIC_iMAC64, []>, - Requires<[IsARM, NoV6]>; -def UMLALv5 : ARMPseudoInst<(outs GPR:$RdLo, GPR:$RdHi), +def SMULLv5 : ARMPseudoExpand<(outs GPR:$RdLo, GPR:$RdHi), (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s), - Size4Bytes, IIC_iMAC64, []>, + 4, IIC_iMUL64, [], + (SMULL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s)>, Requires<[IsARM, NoV6]>; -def UMAALv5 : ARMPseudoInst<(outs GPR:$RdLo, GPR:$RdHi), + +def UMULLv5 : ARMPseudoExpand<(outs GPR:$RdLo, GPR:$RdHi), (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s), - Size4Bytes, IIC_iMAC64, []>, + 4, IIC_iMUL64, [], + (UMULL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s)>, Requires<[IsARM, NoV6]>; - +} } +// Multiply + accumulate def SMLAL : AsMul1I64<0b0000111, (outs GPR:$RdLo, GPR:$RdHi), (ins GPR:$Rn, GPR:$Rm), IIC_iMAC64, "smlal", "\t$RdLo, $RdHi, $Rn, $Rm", []>, @@ -2765,6 +2825,25 @@ def UMAAL : AMul1I <0b0000010, (outs GPR:$RdLo, GPR:$RdHi), let Inst{11-8} = Rm; let Inst{3-0} = Rn; } + +let Constraints = "@earlyclobber $RdLo,@earlyclobber $RdHi" in { +def SMLALv5 : ARMPseudoExpand<(outs GPR:$RdLo, GPR:$RdHi), + (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s), + 4, IIC_iMAC64, [], + (SMLAL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s)>, + Requires<[IsARM, NoV6]>; +def UMLALv5 : ARMPseudoExpand<(outs GPR:$RdLo, GPR:$RdHi), + (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s), + 4, IIC_iMAC64, [], + (UMLAL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s)>, + Requires<[IsARM, NoV6]>; +def UMAALv5 : ARMPseudoExpand<(outs GPR:$RdLo, GPR:$RdHi), + (ins GPR:$Rn, GPR:$Rm, pred:$p), + 4, IIC_iMAC64, [], + (UMAAL GPR:$RdLo, GPR:$RdHi, GPR:$Rn, GPR:$Rm, pred:$p)>, + Requires<[IsARM, NoV6]>; +} + } // neverHasSideEffects // Most significant word multiply @@ -3005,31 +3084,22 @@ def REV : AMiscA1I<0b01101011, 0b0011, (outs GPR:$Rd), (ins GPR:$Rm), IIC_iUNAr, "rev", "\t$Rd, $Rm", [(set GPR:$Rd, (bswap GPR:$Rm))]>, Requires<[IsARM, HasV6]>; +let AddedComplexity = 5 in def REV16 : AMiscA1I<0b01101011, 0b1011, (outs GPR:$Rd), (ins GPR:$Rm), IIC_iUNAr, "rev16", "\t$Rd, $Rm", - [(set GPR:$Rd, - (or (and (srl GPR:$Rm, (i32 8)), 0xFF), - (or (and (shl GPR:$Rm, (i32 8)), 0xFF00), - (or (and (srl GPR:$Rm, (i32 8)), 0xFF0000), - (and (shl GPR:$Rm, (i32 8)), 0xFF000000)))))]>, + [(set GPR:$Rd, (rotr (bswap GPR:$Rm), (i32 16)))]>, Requires<[IsARM, HasV6]>; +let AddedComplexity = 5 in def REVSH : AMiscA1I<0b01101111, 0b1011, (outs GPR:$Rd), (ins GPR:$Rm), IIC_iUNAr, "revsh", "\t$Rd, $Rm", - [(set GPR:$Rd, - (sext_inreg - (or (srl GPR:$Rm, (i32 8)), - (shl GPR:$Rm, (i32 8))), i16))]>, + [(set GPR:$Rd, (sra (bswap GPR:$Rm), (i32 16)))]>, Requires<[IsARM, HasV6]>; -def : ARMV6Pat<(sext_inreg (or (srl (and GPR:$Rm, 0xFF00), (i32 8)), - (shl GPR:$Rm, (i32 8))), i16), +def : ARMV6Pat<(or (sra (shl GPR:$Rm, (i32 24)), (i32 16)), + (and (srl GPR:$Rm, (i32 8)), 0xFF)), (REVSH GPR:$Rm)>; -// Need the AddedComplexity or else MOVs + REV would be chosen. -let AddedComplexity = 5 in -def : ARMV6Pat<(sra (bswap GPR:$Rm), (i32 16)), (REVSH GPR:$Rm)>; - def lsl_shift_imm : SDNodeXForm<imm, [{ unsigned Sh = ARM_AM::getSORegOpc(ARM_AM::lsl, N->getZExtValue()); return CurDAG->getTargetConstant(Sh, MVT::i32); @@ -3177,26 +3247,26 @@ def BCCZi64 : PseudoInst<(outs), // a two-value operand where a dag node expects two operands. :( let neverHasSideEffects = 1 in { def MOVCCr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$false, GPR:$Rm, pred:$p), - Size4Bytes, IIC_iCMOVr, + 4, IIC_iCMOVr, [/*(set GPR:$Rd, (ARMcmov GPR:$false, GPR:$Rm, imm:$cc, CCR:$ccr))*/]>, RegConstraint<"$false = $Rd">; def MOVCCs : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$false, so_reg:$shift, pred:$p), - Size4Bytes, IIC_iCMOVsr, + 4, IIC_iCMOVsr, [/*(set GPR:$Rd, (ARMcmov GPR:$false, so_reg:$shift, imm:$cc, CCR:$ccr))*/]>, RegConstraint<"$false = $Rd">; let isMoveImm = 1 in def MOVCCi16 : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$false, i32imm_hilo16:$imm, pred:$p), - Size4Bytes, IIC_iMOVi, + 4, IIC_iMOVi, []>, RegConstraint<"$false = $Rd">, Requires<[IsARM, HasV6T2]>; let isMoveImm = 1 in def MOVCCi : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$false, so_imm:$imm, pred:$p), - Size4Bytes, IIC_iCMOVi, + 4, IIC_iCMOVi, [/*(set GPR:$Rd, (ARMcmov GPR:$false, so_imm:$imm, imm:$cc, CCR:$ccr))*/]>, RegConstraint<"$false = $Rd">; @@ -3204,12 +3274,12 @@ def MOVCCi : ARMPseudoInst<(outs GPR:$Rd), let isMoveImm = 1 in def MOVCCi32imm : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$false, i32imm:$src, pred:$p), - Size8Bytes, IIC_iCMOVix2, []>, RegConstraint<"$false = $Rd">; + 8, IIC_iCMOVix2, []>, RegConstraint<"$false = $Rd">; let isMoveImm = 1 in def MVNCCi : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$false, so_imm:$imm, pred:$p), - Size4Bytes, IIC_iCMOVi, + 4, IIC_iCMOVi, [/*(set GPR:$Rd, (ARMcmov GPR:$false, so_imm_not:$imm, imm:$cc, CCR:$ccr))*/]>, RegConstraint<"$false = $Rd">; } // neverHasSideEffects @@ -3235,19 +3305,20 @@ def DMB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary, } def DSB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary, - "dsb", "\t$opt", - [/* For disassembly only; pattern left blank */]>, + "dsb", "\t$opt", []>, Requires<[IsARM, HasDB]> { bits<4> opt; let Inst{31-4} = 0xf57ff04; let Inst{3-0} = opt; } -// ISB has only full system option -- for disassembly only -def ISB : AInoP<(outs), (ins), MiscFrm, NoItinerary, "isb", "", []>, +// ISB has only full system option +def ISB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary, + "isb", "\t$opt", []>, Requires<[IsARM, HasDB]> { + bits<4> opt; let Inst{31-4} = 0xf57ff06; - let Inst{3-0} = 0b1111; + let Inst{3-0} = opt; } let usesCustomInserter = 1 in { @@ -3410,8 +3481,8 @@ def SWPB : AIswp<1, (outs GPR:$Rt), (ins GPR:$Rt2, GPR:$Rn), "swpb", // Coprocessor Instructions. // -def CDP : ABI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, - c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), +def CDP : ABI<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1, + c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, imm0_7:$opc2), NoItinerary, "cdp", "\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2", [(int_arm_cdp imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn, imm:$CRm, imm:$opc2)]> { @@ -3431,8 +3502,8 @@ def CDP : ABI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, let Inst{23-20} = opc1; } -def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, - c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), +def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1, + c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, imm0_7:$opc2), NoItinerary, "cdp2\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2", [(int_arm_cdp2 imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn, imm:$CRm, imm:$opc2)]> { @@ -3455,7 +3526,7 @@ def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, class ACI<dag oops, dag iops, string opc, string asm, IndexMode im = IndexModeNone> - : InoP<oops, iops, AddrModeNone, Size4Bytes, im, BrFrm, NoItinerary, + : InoP<oops, iops, AddrModeNone, 4, im, BrFrm, NoItinerary, opc, asm, "", [/* For disassembly only; pattern left blank */]> { let Inst{27-25} = 0b110; } @@ -3583,8 +3654,8 @@ class MovRCopro<string opc, bit direction, dag oops, dag iops, def MCR : MovRCopro<"mcr", 0 /* from ARM core register to coprocessor */, (outs), - (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, c_imm:$CRn, - c_imm:$CRm, i32imm:$opc2), + (ins p_imm:$cop, imm0_7:$opc1, GPR:$Rt, c_imm:$CRn, + c_imm:$CRm, imm0_7:$opc2), [(int_arm_mcr imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn, imm:$CRm, imm:$opc2)]>; def MRC : MovRCopro<"mrc", 1 /* from coprocessor to ARM core register */, @@ -3620,8 +3691,8 @@ class MovRCopro2<string opc, bit direction, dag oops, dag iops, def MCR2 : MovRCopro2<"mcr2", 0 /* from ARM core register to coprocessor */, (outs), - (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, c_imm:$CRn, - c_imm:$CRm, i32imm:$opc2), + (ins p_imm:$cop, imm0_7:$opc1, GPR:$Rt, c_imm:$CRn, + c_imm:$CRm, imm0_7:$opc2), [(int_arm_mcr2 imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn, imm:$CRm, imm:$opc2)]>; def MRC2 : MovRCopro2<"mrc2", 1 /* from coprocessor to ARM core register */, @@ -3635,7 +3706,7 @@ def : ARMV5TPat<(int_arm_mrc2 imm:$cop, imm:$opc1, imm:$CRn, class MovRRCopro<string opc, bit direction, list<dag> pattern = [/* For disassembly only */]> - : ABI<0b1100, (outs), (ins p_imm:$cop, i32imm:$opc1, + : ABI<0b1100, (outs), (ins p_imm:$cop, imm0_15:$opc1, GPR:$Rt, GPR:$Rt2, c_imm:$CRm), NoItinerary, opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm", pattern> { let Inst{23-21} = 0b010; @@ -3661,7 +3732,7 @@ def MRRC : MovRRCopro<"mrrc", 1 /* from coprocessor to ARM core register */>; class MovRRCopro2<string opc, bit direction, list<dag> pattern = [/* For disassembly only */]> - : ABXI<0b1100, (outs), (ins p_imm:$cop, i32imm:$opc1, + : ABXI<0b1100, (outs), (ins p_imm:$cop, imm0_15:$opc1, GPR:$Rt, GPR:$Rt2, c_imm:$CRm), NoItinerary, !strconcat(opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm"), pattern> { let Inst{31-28} = 0b1111; @@ -3812,6 +3883,13 @@ def Int_eh_sjlj_dispatchsetup : // Non-Instruction Patterns // +// ARMv4 indirect branch using (MOVr PC, dst) +let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in + def MOVPCRX : ARMPseudoExpand<(outs), (ins GPR:$dst), + 4, IIC_Br, [(brind GPR:$dst)], + (MOVr PC, GPR:$dst, (ops 14, zero_reg), zero_reg)>, + Requires<[IsARM, NoV4T]>; + // Large immediate handling. // 32-bit immediate using two piece so_imms or movw + movt. @@ -3977,3 +4055,22 @@ include "ARMInstrVFP.td" include "ARMInstrNEON.td" +//===----------------------------------------------------------------------===// +// Assembler aliases +// + +// Memory barriers +def : InstAlias<"dmb", (DMB 0xf)>, Requires<[IsARM, HasDB]>; +def : InstAlias<"dsb", (DSB 0xf)>, Requires<[IsARM, HasDB]>; +def : InstAlias<"isb", (ISB 0xf)>, Requires<[IsARM, HasDB]>; + +// System instructions +def : MnemonicAlias<"swi", "svc">; + +// Load / Store Multiple +def : MnemonicAlias<"ldmfd", "ldm">; +def : MnemonicAlias<"ldmia", "ldm">; +def : MnemonicAlias<"stmfd", "stmdb">; +def : MnemonicAlias<"stmia", "stm">; +def : MnemonicAlias<"stmea", "stm">; + diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td index 79d95d9b2683..0df62f456343 100644 --- a/lib/Target/ARM/ARMInstrNEON.td +++ b/lib/Target/ARM/ARMInstrNEON.td @@ -175,7 +175,7 @@ class VLDQQWBPseudo<InstrItinClass itin> (ins addrmode6:$addr, am6offset:$offset), itin, "$addr.addr = $wb">; class VLDQQQQPseudo<InstrItinClass itin> - : PseudoNLdSt<(outs QQQQPR:$dst), (ins addrmode6:$addr, QQQQPR:$src), itin,"">; + : PseudoNLdSt<(outs QQQQPR:$dst), (ins addrmode6:$addr, QQQQPR:$src),itin,"">; class VLDQQQQWBPseudo<InstrItinClass itin> : PseudoNLdSt<(outs QQQQPR:$dst, GPR:$wb), (ins addrmode6:$addr, am6offset:$offset, QQQQPR:$src), itin, @@ -1387,7 +1387,7 @@ class VST1LN32<bits<4> op11_8, bits<4> op7_4, string Dt, ValueType Ty, : NLdStLn<1, 0b00, op11_8, op7_4, (outs), (ins addrmode6oneL32:$Rn, DPR:$Vd, nohash_imm:$lane), IIC_VST1ln, "vst1", Dt, "\\{$Vd[$lane]\\}, $Rn", "", - [(StoreOp (ExtractOp (Ty DPR:$Vd), imm:$lane), addrmode6oneL32:$Rn)]> { + [(StoreOp (ExtractOp (Ty DPR:$Vd), imm:$lane), addrmode6oneL32:$Rn)]>{ let Rm = 0b1111; } class VST1QLNPseudo<ValueType Ty, PatFrag StoreOp, SDNode ExtractOp> @@ -3793,7 +3793,8 @@ def VBSLd : N3VX<1, 0, 0b01, 0b0001, 0, 1, (outs DPR:$Vd), (ins DPR:$src1, DPR:$Vn, DPR:$Vm), N3RegFrm, IIC_VCNTiD, "vbsl", "$Vd, $Vn, $Vm", "$src1 = $Vd", - [(set DPR:$Vd, (v2i32 (NEONvbsl DPR:$src1, DPR:$Vn, DPR:$Vm)))]>; + [(set DPR:$Vd, + (v2i32 (NEONvbsl DPR:$src1, DPR:$Vn, DPR:$Vm)))]>; def : Pat<(v2i32 (or (and DPR:$Vn, DPR:$Vd), (and DPR:$Vm, (vnotd DPR:$Vd)))), @@ -3803,7 +3804,8 @@ def VBSLq : N3VX<1, 0, 0b01, 0b0001, 1, 1, (outs QPR:$Vd), (ins QPR:$src1, QPR:$Vn, QPR:$Vm), N3RegFrm, IIC_VCNTiQ, "vbsl", "$Vd, $Vn, $Vm", "$src1 = $Vd", - [(set QPR:$Vd, (v4i32 (NEONvbsl QPR:$src1, QPR:$Vn, QPR:$Vm)))]>; + [(set QPR:$Vd, + (v4i32 (NEONvbsl QPR:$src1, QPR:$Vn, QPR:$Vm)))]>; def : Pat<(v4i32 (or (and QPR:$Vn, QPR:$Vd), (and QPR:$Vm, (vnotq QPR:$Vd)))), @@ -4212,17 +4214,12 @@ def VSWPq : N2VX<0b11, 0b11, 0b00, 0b10, 0b00000, 1, 0, // Vector Move Operations. // VMOV : Vector Move (Register) +def : InstAlias<"vmov${p} $Vd, $Vm", + (VORRd DPR:$Vd, DPR:$Vm, DPR:$Vm, pred:$p)>; +def : InstAlias<"vmov${p} $Vd, $Vm", + (VORRq QPR:$Vd, QPR:$Vm, QPR:$Vm, pred:$p)>; let neverHasSideEffects = 1 in { -def VMOVDneon: N3VX<0, 0, 0b10, 0b0001, 0, 1, (outs DPR:$Vd), (ins DPR:$Vm), - N3RegFrm, IIC_VMOV, "vmov", "$Vd, $Vm", "", []> { - let Vn{4-0} = Vm{4-0}; -} -def VMOVQ : N3VX<0, 0, 0b10, 0b0001, 1, 1, (outs QPR:$Vd), (ins QPR:$Vm), - N3RegFrm, IIC_VMOV, "vmov", "$Vd, $Vm", "", []> { - let Vn{4-0} = Vm{4-0}; -} - // Pseudo vector move instructions for QQ and QQQQ registers. This should // be expanded after register allocation is completed. def VMOVQQ : PseudoInst<(outs QQPR:$dst), (ins QQPR:$src), @@ -4702,11 +4699,10 @@ def VEXTd32 : VEXTd<"vext", "32", v2i32> { let Inst{11-10} = index{1-0}; let Inst{9-8} = 0b00; } -def VEXTdf : VEXTd<"vext", "32", v2f32> { - let Inst{11-10} = index{1-0}; - let Inst{9-8} = 0b00; - -} +def : Pat<(v2f32 (NEONvext (v2f32 DPR:$Vn), + (v2f32 DPR:$Vm), + (i32 imm:$index))), + (VEXTd32 DPR:$Vn, DPR:$Vm, imm:$index)>; def VEXTq8 : VEXTq<"vext", "8", v16i8> { let Inst{11-8} = index{3-0}; @@ -4719,10 +4715,10 @@ def VEXTq32 : VEXTq<"vext", "32", v4i32> { let Inst{11-10} = index{1-0}; let Inst{9-8} = 0b00; } -def VEXTqf : VEXTq<"vext", "32", v4f32> { - let Inst{11-10} = index{1-0}; - let Inst{9-8} = 0b00; -} +def : Pat<(v4f32 (NEONvext (v4f32 QPR:$Vn), + (v4f32 QPR:$Vm), + (i32 imm:$index))), + (VEXTq32 QPR:$Vn, QPR:$Vm, imm:$index)>; // VTRN : Vector Transpose diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 4777189934c0..bfe83eceb13f 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -26,17 +26,14 @@ def imm_comp_XFORM : SDNodeXForm<imm, [{ return CurDAG->getTargetConstant(~((uint32_t)N->getZExtValue()), MVT::i32); }]>; -/// imm0_7 predicate - True if the 32-bit immediate is in the range [0,7]. -def imm0_7 : ImmLeaf<i32, [{ - return Imm >= 0 && Imm < 8; -}]>; def imm0_7_neg : PatLeaf<(i32 imm), [{ return (uint32_t)-N->getZExtValue() < 8; }], imm_neg_XFORM>; -def imm0_255 : ImmLeaf<i32, [{ - return Imm >= 0 && Imm < 256; -}]>; +def imm0_255_asmoperand : AsmOperandClass { let Name = "Imm0_255"; } +def imm0_255 : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 256; }]> { + let ParserMatchClass = imm0_255_asmoperand; +} def imm0_255_comp : PatLeaf<(i32 imm), [{ return ~((uint32_t)N->getZExtValue()) < 256; }]>; @@ -74,10 +71,12 @@ def t_adrlabel : Operand<i32> { // Scaled 4 immediate. def t_imm_s4 : Operand<i32> { let PrintMethod = "printThumbS4ImmOperand"; + let OperandType = "OPERAND_IMMEDIATE"; } // Define Thumb specific addressing modes. +let OperandType = "OPERAND_PCREL" in { def t_brtarget : Operand<OtherVT> { let EncoderMethod = "getThumbBRTargetOpValue"; } @@ -97,6 +96,7 @@ def t_bltarget : Operand<i32> { def t_blxtarget : Operand<i32> { let EncoderMethod = "getThumbBLXTargetOpValue"; } +} def MemModeRegThumbAsmOperand : AsmOperandClass { let Name = "MemModeRegThumb"; @@ -360,27 +360,6 @@ def tADDspr : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, // Control Flow Instructions. // -let isReturn = 1, isTerminator = 1, isBarrier = 1 in { - def tBX_RET : TI<(outs), (ins), IIC_Br, "bx\tlr", - [(ARMretflag)]>, - T1Special<{1,1,0,?}> { - // A6.2.3 & A8.6.25 - let Inst{6-3} = 0b1110; // Rm = lr - let Inst{2-0} = 0b000; - } - - // Alternative return instruction used by vararg functions. - def tBX_RET_vararg : TI<(outs), (ins tGPR:$Rm), - IIC_Br, "bx\t$Rm", - []>, - T1Special<{1,1,0,?}> { - // A6.2.3 & A8.6.25 - bits<4> Rm; - let Inst{6-3} = Rm; - let Inst{2-0} = 0b000; - } -} - // Indirect branches let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { def tBX : TI<(outs), (ins GPR:$Rm, pred:$p), IIC_Br, "bx${p}\t$Rm", []>, @@ -390,31 +369,16 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { let Inst{6-3} = Rm; let Inst{2-0} = 0b000; } - - def tBRIND : TI<(outs), (ins GPR:$Rm), - IIC_Br, - "mov\tpc, $Rm", - [(brind GPR:$Rm)]>, - T1Special<{1,0,?,?}> { - // A8.6.97 - bits<4> Rm; - let Inst{7} = 1; // <Rd> = Inst{7:2-0} = pc - let Inst{6-3} = Rm; - let Inst{2-0} = 0b111; - } } -// FIXME: remove when we have a way to marking a MI with these properties. -let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, - hasExtraDefRegAllocReq = 1 in -def tPOP_RET : T1I<(outs), (ins pred:$p, reglist:$regs, variable_ops), - IIC_iPop_Br, - "pop${p}\t$regs", []>, - T1Misc<{1,1,0,?,?,?,?}> { - // A8.6.121 - bits<16> regs; - let Inst{8} = regs{15}; // registers = P:'0000000':register_list - let Inst{7-0} = regs{7-0}; +let isReturn = 1, isTerminator = 1, isBarrier = 1 in { + def tBX_RET : tPseudoExpand<(outs), (ins pred:$p), 2, IIC_Br, + [(ARMretflag)], (tBX LR, pred:$p)>; + + // Alternative return instruction used by vararg functions. + def tBX_RET_vararg : tPseudoExpand<(outs), (ins tGPR:$Rm, pred:$p), + 2, IIC_Br, [], + (tBX GPR:$Rm, pred:$p)>; } // All calls clobber the non-callee saved registers. SP is marked as a use to @@ -464,7 +428,7 @@ let isCall = 1, // ARMv4T def tBX_CALL : tPseudoInst<(outs), (ins tGPR:$func, variable_ops), - Size4Bytes, IIC_Br, + 4, IIC_Br, [(ARMcall_nolink tGPR:$func)]>, Requires<[IsThumb, IsThumb1Only, IsNotDarwin]>; } @@ -516,7 +480,7 @@ let isCall = 1, // ARMv4T def tBXr9_CALL : tPseudoInst<(outs), (ins tGPR:$func, variable_ops), - Size4Bytes, IIC_Br, + 4, IIC_Br, [(ARMcall_nolink tGPR:$func)]>, Requires<[IsThumb, IsThumb1Only, IsDarwin]>; } @@ -534,12 +498,12 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1 in { // Just a pseudo for a tBL instruction. Needed to let regalloc know about // the clobber of LR. let Defs = [LR] in - def tBfar : tPseudoInst<(outs), (ins t_bltarget:$target), - Size4Bytes, IIC_Br, []>; + def tBfar : tPseudoExpand<(outs), (ins t_bltarget:$target), + 4, IIC_Br, [], (tBL t_bltarget:$target)>; def tBR_JTr : tPseudoInst<(outs), (ins tGPR:$target, i32imm:$jt, i32imm:$id), - SizeSpecial, IIC_Br, + 0, IIC_Br, [(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]> { list<Predicate> Predicates = [IsThumb, IsThumb1Only]; } @@ -583,6 +547,33 @@ let isBranch = 1, isTerminator = 1 in { } } +// Tail calls +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in { + // Darwin versions. + let Defs = [R0, R1, R2, R3, R9, R12, QQQQ0, QQQQ2, QQQQ3, PC], + Uses = [SP] in { + // tTAILJMPd: Darwin version uses a Thumb2 branch (no Thumb1 tail calls + // on Darwin), so it's in ARMInstrThumb2.td. + def tTAILJMPr : tPseudoExpand<(outs), (ins tcGPR:$dst, variable_ops), + 4, IIC_Br, [], + (tBX GPR:$dst, (ops 14, zero_reg))>, + Requires<[IsThumb, IsDarwin]>; + } + // Non-Darwin versions (the difference is R9). + let Defs = [R0, R1, R2, R3, R12, QQQQ0, QQQQ2, QQQQ3, PC], + Uses = [SP] in { + def tTAILJMPdND : tPseudoExpand<(outs), (ins t_brtarget:$dst, variable_ops), + 4, IIC_Br, [], + (tB t_brtarget:$dst)>, + Requires<[IsThumb, IsNotDarwin]>; + def tTAILJMPrND : tPseudoExpand<(outs), (ins tcGPR:$dst, variable_ops), + 4, IIC_Br, [], + (tBX GPR:$dst, (ops 14, zero_reg))>, + Requires<[IsThumb, IsNotDarwin]>; + } +} + + // A8.6.218 Supervisor Call (Software Interrupt) -- for disassembly only // A8.6.16 B: Encoding T1 // If Inst{11-8} == 0b1111 then SEE SVC @@ -685,19 +676,6 @@ def tLDRspi : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_sp:$addr), IIC_iLoad_i, let Inst{7-0} = addr; } -// Special instruction for restore. It cannot clobber condition register -// when it's expanded by eliminateCallFramePseudoInstr(). -let canFoldAsLoad = 1, mayLoad = 1, neverHasSideEffects = 1 in -// FIXME: Pseudo for tLDRspi -def tRestore : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoad_i, - "ldr", "\t$dst, $addr", []>, - T1LdStSP<{1,?,?}> { - bits<3> Rt; - bits<8> addr; - let Inst{10-8} = Rt; - let Inst{7-0} = addr; -} - // Load tconstpool // FIXME: Use ldr.n to work around a Darwin assembler bug. let canFoldAsLoad = 1, isReMaterializable = 1 in @@ -739,9 +717,9 @@ defm tSTRB : thumb_st_rr_ri_enc<0b010, 0b0111, t_addrmode_rrs1, // A8.6.207 & A8.6.205 defm tSTRH : thumb_st_rr_ri_enc<0b001, 0b1000, t_addrmode_rrs2, - t_addrmode_is2, AddrModeT1_2, - IIC_iStore_bh_r, IIC_iStore_bh_i, "strh", - BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>; + t_addrmode_is2, AddrModeT1_2, + IIC_iStore_bh_r, IIC_iStore_bh_i, "strh", + BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>; def tSTRspi : T1pIs<(outs), (ins tGPR:$Rt, t_addrmode_sp:$addr), IIC_iStore_i, @@ -754,19 +732,6 @@ def tSTRspi : T1pIs<(outs), (ins tGPR:$Rt, t_addrmode_sp:$addr), IIC_iStore_i, let Inst{7-0} = addr; } -let mayStore = 1, neverHasSideEffects = 1 in -// Special instruction for spill. It cannot clobber condition register when it's -// expanded by eliminateCallFramePseudoInstr(). -// FIXME: Pseudo for tSTRspi -def tSpill : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStore_i, - "str", "\t$src, $addr", []>, - T1LdStSP<{0,?,?}> { - bits<3> Rt; - bits<8> addr; - let Inst{10-8} = Rt; - let Inst{7-0} = addr; -} - //===----------------------------------------------------------------------===// // Load / store multiple Instructions. // @@ -911,7 +876,8 @@ def tADC : // A8.6.2 // Add immediate def tADDi3 : // A8.6.4 T1 - T1sIGenEncodeImm<0b01110, (outs tGPR:$Rd), (ins tGPR:$Rm, i32imm:$imm3), IIC_iALUi, + T1sIGenEncodeImm<0b01110, (outs tGPR:$Rd), (ins tGPR:$Rm, i32imm:$imm3), + IIC_iALUi, "add", "\t$Rd, $Rm, $imm3", [(set tGPR:$Rd, (add tGPR:$Rm, imm0_7:$imm3))]> { bits<3> imm3; @@ -1071,7 +1037,7 @@ def tLSRrr : // A8.6.91 // Move register let isMoveImm = 1 in -def tMOVi8 : T1sI<(outs tGPR:$Rd), (ins i32imm:$imm8), IIC_iMOVi, +def tMOVi8 : T1sI<(outs tGPR:$Rd), (ins imm0_255:$imm8), IIC_iMOVi, "mov", "\t$Rd, $imm8", [(set tGPR:$Rd, imm0_255:$imm8)]>, T1General<{1,0,0,?,?}> { @@ -1082,18 +1048,18 @@ def tMOVi8 : T1sI<(outs tGPR:$Rd), (ins i32imm:$imm8), IIC_iMOVi, let Inst{7-0} = imm8; } -// TODO: A7-73: MOV(2) - mov setting flag. +// A7-73: MOV(2) - mov setting flag. let neverHasSideEffects = 1 in { -// FIXME: Make this predicable. -def tMOVr : T1I<(outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iMOVr, - "mov\t$Rd, $Rm", []>, - T1Special<0b1000> { +def tMOVr : Thumb1pI<(outs GPR:$Rd), (ins GPR:$Rm), AddrModeNone, + 2, IIC_iMOVr, + "mov", "\t$Rd, $Rm", "", []>, + T1Special<{1,0,?,?}> { // A8.6.97 bits<4> Rd; bits<4> Rm; - // Bits {7-6} are encoded by the T1Special value. - let Inst{5-3} = Rm{2-0}; + let Inst{7} = Rd{3}; + let Inst{6-3} = Rm; let Inst{2-0} = Rd{2-0}; } let Defs = [CPSR] in @@ -1106,39 +1072,6 @@ def tMOVSr : T1I<(outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iMOVr, let Inst{5-3} = Rm; let Inst{2-0} = Rd; } - -// FIXME: Make these predicable. -def tMOVgpr2tgpr : T1I<(outs tGPR:$Rd), (ins GPR:$Rm), IIC_iMOVr, - "mov\t$Rd, $Rm", []>, - T1Special<{1,0,0,?}> { - // A8.6.97 - bits<4> Rd; - bits<4> Rm; - // Bit {7} is encoded by the T1Special value. - let Inst{6-3} = Rm; - let Inst{2-0} = Rd{2-0}; -} -def tMOVtgpr2gpr : T1I<(outs GPR:$Rd), (ins tGPR:$Rm), IIC_iMOVr, - "mov\t$Rd, $Rm", []>, - T1Special<{1,0,?,0}> { - // A8.6.97 - bits<4> Rd; - bits<4> Rm; - // Bit {6} is encoded by the T1Special value. - let Inst{7} = Rd{3}; - let Inst{5-3} = Rm{2-0}; - let Inst{2-0} = Rd{2-0}; -} -def tMOVgpr2gpr : T1I<(outs GPR:$Rd), (ins GPR:$Rm), IIC_iMOVr, - "mov\t$Rd, $Rm", []>, - T1Special<{1,0,?,?}> { - // A8.6.97 - bits<4> Rd; - bits<4> Rm; - let Inst{7} = Rd{3}; - let Inst{6-3} = Rm; - let Inst{2-0} = Rd{2-0}; -} } // neverHasSideEffects // Multiply register @@ -1175,31 +1108,16 @@ def tREV16 : // A8.6.135 T1pIMiscEncode<{1,0,1,0,0,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iUNAr, "rev16", "\t$Rd, $Rm", - [(set tGPR:$Rd, - (or (and (srl tGPR:$Rm, (i32 8)), 0xFF), - (or (and (shl tGPR:$Rm, (i32 8)), 0xFF00), - (or (and (srl tGPR:$Rm, (i32 8)), 0xFF0000), - (and (shl tGPR:$Rm, (i32 8)), 0xFF000000)))))]>, + [(set tGPR:$Rd, (rotr (bswap tGPR:$Rm), (i32 16)))]>, Requires<[IsThumb, IsThumb1Only, HasV6]>; def tREVSH : // A8.6.136 T1pIMiscEncode<{1,0,1,0,1,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iUNAr, "revsh", "\t$Rd, $Rm", - [(set tGPR:$Rd, - (sext_inreg - (or (srl tGPR:$Rm, (i32 8)), - (shl tGPR:$Rm, (i32 8))), i16))]>, + [(set tGPR:$Rd, (sra (bswap tGPR:$Rm), (i32 16)))]>, Requires<[IsThumb, IsThumb1Only, HasV6]>; -def : T1Pat<(sext_inreg (or (srl (and tGPR:$Rm, 0xFF00), (i32 8)), - (shl tGPR:$Rm, (i32 8))), i16), - (tREVSH tGPR:$Rm)>, - Requires<[IsThumb, IsThumb1Only, HasV6]>; - -def : T1Pat<(sra (bswap tGPR:$Rm), (i32 16)), (tREVSH tGPR:$Rm)>, - Requires<[IsThumb, IsThumb1Only, HasV6]>; - // Rotate right register def tROR : // A8.6.139 T1sItDPEncode<0b0111, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), @@ -1294,31 +1212,6 @@ let usesCustomInserter = 1 in // Expanded after instruction selection. NoItinerary, [/*(set tGPR:$dst, (ARMcmov tGPR:$false, tGPR:$true, imm:$cc))*/]>; - -// 16-bit movcc in IT blocks for Thumb2. -let neverHasSideEffects = 1 in { -def tMOVCCr : T1pIt<(outs GPR:$Rdn), (ins GPR:$Rn, GPR:$Rm), IIC_iCMOVr, - "mov", "\t$Rdn, $Rm", []>, - T1Special<{1,0,?,?}> { - bits<4> Rdn; - bits<4> Rm; - let Inst{7} = Rdn{3}; - let Inst{6-3} = Rm; - let Inst{2-0} = Rdn{2-0}; -} - -let isMoveImm = 1 in -def tMOVCCi : T1pIt<(outs tGPR:$Rdn), (ins tGPR:$Rn, i32imm:$Rm), IIC_iCMOVi, - "mov", "\t$Rdn, $Rm", []>, - T1General<{1,0,0,?,?}> { - bits<3> Rdn; - bits<8> Rm; - let Inst{10-8} = Rdn; - let Inst{7-0} = Rm; -} - -} // neverHasSideEffects - // tLEApcrel - Load a pc-relative address into a register without offending the // assembler. @@ -1333,118 +1226,22 @@ def tADR : T1I<(outs tGPR:$Rd), (ins t_adrlabel:$addr, pred:$p), let neverHasSideEffects = 1, isReMaterializable = 1 in def tLEApcrel : tPseudoInst<(outs tGPR:$Rd), (ins i32imm:$label, pred:$p), - Size2Bytes, IIC_iALUi, []>; + 2, IIC_iALUi, []>; def tLEApcrelJT : tPseudoInst<(outs tGPR:$Rd), (ins i32imm:$label, nohash_imm:$id, pred:$p), - Size2Bytes, IIC_iALUi, []>; - -//===----------------------------------------------------------------------===// -// Move between coprocessor and ARM core register -- for disassembly only -// - -class tMovRCopro<string opc, bit direction, dag oops, dag iops, - list<dag> pattern> - : T1Cop<oops, iops, !strconcat(opc, "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2"), - pattern> { - let Inst{27-24} = 0b1110; - let Inst{20} = direction; - let Inst{4} = 1; - - bits<4> Rt; - bits<4> cop; - bits<3> opc1; - bits<3> opc2; - bits<4> CRm; - bits<4> CRn; - - let Inst{15-12} = Rt; - let Inst{11-8} = cop; - let Inst{23-21} = opc1; - let Inst{7-5} = opc2; - let Inst{3-0} = CRm; - let Inst{19-16} = CRn; -} - -def tMCR : tMovRCopro<"mcr", 0 /* from ARM core register to coprocessor */, - (outs), - (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, c_imm:$CRn, - c_imm:$CRm, i32imm:$opc2), - [(int_arm_mcr imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn, - imm:$CRm, imm:$opc2)]>; -def tMRC : tMovRCopro<"mrc", 1 /* from coprocessor to ARM core register */, - (outs GPR:$Rt), - (ins p_imm:$cop, i32imm:$opc1, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), - []>; - -def : Pat<(int_arm_mrc imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2), - (tMRC imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2)>, - Requires<[IsThumb, HasV6T2]>; - -class tMovRRCopro<string opc, bit direction, - list<dag> pattern = [/* For disassembly only */]> - : T1Cop<(outs), (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, GPR:$Rt2, c_imm:$CRm), - !strconcat(opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm"), pattern> { - let Inst{27-24} = 0b1100; - let Inst{23-21} = 0b010; - let Inst{20} = direction; - - bits<4> Rt; - bits<4> Rt2; - bits<4> cop; - bits<4> opc1; - bits<4> CRm; - - let Inst{15-12} = Rt; - let Inst{19-16} = Rt2; - let Inst{11-8} = cop; - let Inst{7-4} = opc1; - let Inst{3-0} = CRm; -} - -def tMCRR : tMovRRCopro<"mcrr", 0 /* from ARM core register to coprocessor */, - [(int_arm_mcrr imm:$cop, imm:$opc1, GPR:$Rt, GPR:$Rt2, - imm:$CRm)]>; -def tMRRC : tMovRRCopro<"mrrc", 1 /* from coprocessor to ARM core register */>; - -//===----------------------------------------------------------------------===// -// Other Coprocessor Instructions. For disassembly only. -// -def tCDP : T1Cop<(outs), (ins p_imm:$cop, i32imm:$opc1, - c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), - "cdp\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2", - [(int_arm_cdp imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn, - imm:$CRm, imm:$opc2)]> { - let Inst{27-24} = 0b1110; - - bits<4> opc1; - bits<4> CRn; - bits<4> CRd; - bits<4> cop; - bits<3> opc2; - bits<4> CRm; - - let Inst{3-0} = CRm; - let Inst{4} = 0; - let Inst{7-5} = opc2; - let Inst{11-8} = cop; - let Inst{15-12} = CRd; - let Inst{19-16} = CRn; - let Inst{23-20} = opc1; -} + 2, IIC_iALUi, []>; //===----------------------------------------------------------------------===// // TLS Instructions // // __aeabi_read_tp preserves the registers r1-r3. -let isCall = 1, Defs = [R0, LR], Uses = [SP] in -def tTPsoft : TIx2<0b11110, 0b11, 1, (outs), (ins), IIC_Br, - "bl\t__aeabi_read_tp", - [(set R0, ARMthread_pointer)]> { - // Encoding is 0xf7fffffe. - let Inst = 0xf7fffffe; -} +// This is a pseudo inst so that we can get the encoding right, +// complete with fixup for the aeabi_read_tp function. +let isCall = 1, Defs = [R0, R12, LR, CPSR], Uses = [SP] in +def tTPsoft : tPseudoInst<(outs), (ins), 4, IIC_Br, + [(set R0, ARMthread_pointer)]>; //===----------------------------------------------------------------------===// // SJLJ Exception handling intrinsics @@ -1463,14 +1260,14 @@ def tTPsoft : TIx2<0b11110, 0b11, 1, (outs), (ins), IIC_Br, let Defs = [ R0, R1, R2, R3, R4, R5, R6, R7, R12, CPSR ], hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1 in def tInt_eh_sjlj_setjmp : ThumbXI<(outs),(ins tGPR:$src, tGPR:$val), - AddrModeNone, SizeSpecial, NoItinerary, "","", + AddrModeNone, 0, NoItinerary, "","", [(set R0, (ARMeh_sjlj_setjmp tGPR:$src, tGPR:$val))]>; // FIXME: Non-Darwin version(s) let isBarrier = 1, hasSideEffects = 1, isTerminator = 1, isCodeGenOnly = 1, Defs = [ R7, LR, SP ] in def tInt_eh_sjlj_longjmp : XI<(outs), (ins GPR:$src, GPR:$scratch), - AddrModeNone, SizeSpecial, IndexModeNone, + AddrModeNone, 0, IndexModeNone, Pseudo, NoItinerary, "", "", [(ARMeh_sjlj_longjmp GPR:$src, GPR:$scratch)]>, Requires<[IsThumb, IsDarwin]>; @@ -1583,3 +1380,18 @@ def tLDRpci_pic : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr, pclabel:$cp), [(set GPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)), imm:$cp))]>, Requires<[IsThumb, IsThumb1Only]>; + +// Pseudo-instruction for merged POP and return. +// FIXME: remove when we have a way to marking a MI with these properties. +let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, + hasExtraDefRegAllocReq = 1 in +def tPOP_RET : tPseudoExpand<(outs), (ins pred:$p, reglist:$regs, variable_ops), + 2, IIC_iPop_Br, [], + (tPOP pred:$p, reglist:$regs)>; + +// Indirect branch using "mov pc, $Rm" +let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { + def tBRIND : tPseudoExpand<(outs), (ins GPR:$Rm, pred:$p), + 2, IIC_Br, [(brind GPR:$Rm)], + (tMOVr PC, GPR:$Rm, pred:$p)>; +} diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 598660c69fbe..c2c6cbcac0f5 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -44,9 +44,11 @@ def t2_so_imm_neg_XFORM : SDNodeXForm<imm, [{ // t2_so_imm - Match a 32-bit immediate operand, which is an // 8-bit immediate rotated by an arbitrary number of bits, or an 8-bit // immediate splatted into multiple bytes of the word. +def t2_so_imm_asmoperand : AsmOperandClass { let Name = "T2SOImm"; } def t2_so_imm : Operand<i32>, ImmLeaf<i32, [{ return ARM_AM::getT2SOImmVal(Imm) != -1; }]> { + let ParserMatchClass = t2_so_imm_asmoperand; let EncoderMethod = "getT2SOImmOpValue"; } @@ -463,7 +465,8 @@ multiclass T2I_un_irs<bits<4> opcod, string opc, /// changed to modify CPSR. multiclass T2I_bin_irs<bits<4> opcod, string opc, InstrItinClass iii, InstrItinClass iir, InstrItinClass iis, - PatFrag opnode, bit Commutable = 0, string wide = ""> { + PatFrag opnode, string baseOpc, bit Commutable = 0, + string wide = ""> { // shifted imm def ri : T2sTwoRegImm< (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm), iii, @@ -495,14 +498,31 @@ multiclass T2I_bin_irs<bits<4> opcod, string opc, let Inst{26-25} = 0b01; let Inst{24-21} = opcod; } + // Assembly aliases for optional destination operand when it's the same + // as the source operand. + def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $imm"), + (!cast<Instruction>(!strconcat(baseOpc, "ri")) rGPR:$Rdn, rGPR:$Rdn, + t2_so_imm:$imm, pred:$p, + cc_out:$s)>, + Requires<[IsThumb2]>; + def : InstAlias<!strconcat(opc, "${s}${p}", wide, " $Rdn, $Rm"), + (!cast<Instruction>(!strconcat(baseOpc, "rr")) rGPR:$Rdn, rGPR:$Rdn, + rGPR:$Rm, pred:$p, + cc_out:$s)>, + Requires<[IsThumb2]>; + def : InstAlias<!strconcat(opc, "${s}${p}", wide, " $Rdn, $shift"), + (!cast<Instruction>(!strconcat(baseOpc, "rs")) rGPR:$Rdn, rGPR:$Rdn, + t2_so_reg:$shift, pred:$p, + cc_out:$s)>, + Requires<[IsThumb2]>; } /// T2I_bin_w_irs - Same as T2I_bin_irs except these operations need -// the ".w" prefix to indicate that they are wide. +// the ".w" suffix to indicate that they are wide. multiclass T2I_bin_w_irs<bits<4> opcod, string opc, InstrItinClass iii, InstrItinClass iir, InstrItinClass iis, - PatFrag opnode, bit Commutable = 0> : - T2I_bin_irs<opcod, opc, iii, iir, iis, opnode, Commutable, ".w">; + PatFrag opnode, string baseOpc, bit Commutable = 0> : + T2I_bin_irs<opcod, opc, iii, iir, iis, opnode, baseOpc, Commutable, ".w">; /// T2I_rbin_is - Same as T2I_bin_irs except the order of operands are /// reversed. The 'rr' form is only defined for the disassembler; for codegen @@ -696,18 +716,18 @@ let usesCustomInserter = 1 in { multiclass T2I_adde_sube_s_irs<PatFrag opnode, bit Commutable = 0> { // shifted imm def ri : t2PseudoInst<(outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm), - Size4Bytes, IIC_iALUi, + 4, IIC_iALUi, [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_imm:$imm))]>; // register def rr : t2PseudoInst<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), - Size4Bytes, IIC_iALUr, + 4, IIC_iALUr, [(set rGPR:$Rd, (opnode rGPR:$Rn, rGPR:$Rm))]> { let isCommutable = Commutable; } // shifted register def rs : t2PseudoInst< (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm), - Size4Bytes, IIC_iALUsi, + 4, IIC_iALUsi, [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_reg:$ShiftedRm))]>; } } @@ -1018,7 +1038,8 @@ multiclass T2I_ext_rrot_uxtb16<bits<3> opcod, string opc, PatFrag opnode> { // supported yet. multiclass T2I_ext_rrot_sxtb16<bits<3> opcod, string opc> { def r : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iEXTr, - opc, "\t$Rd, $Rm", []> { + opc, "\t$Rd, $Rm", []>, + Requires<[IsThumb2, HasT2ExtractPack]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0100; let Inst{22-20} = opcod; @@ -1028,7 +1049,8 @@ multiclass T2I_ext_rrot_sxtb16<bits<3> opcod, string opc> { let Inst{5-4} = 0b00; // rotate } def r_rot : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm, i32imm:$rot), IIC_iEXTr, - opc, "\t$Rd, $Rm, ror $rot", []> { + opc, "\t$Rd, $Rm, ror $rot", []>, + Requires<[IsThumb2, HasT2ExtractPack]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0100; let Inst{22-20} = opcod; @@ -1084,7 +1106,7 @@ multiclass T2I_exta_rrot_DO<bits<3> opcod, string opc> { let Inst{7} = 1; let Inst{5-4} = 0b00; // rotate } - def rr_rot : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, i32imm:$rot), + def rr_rot :T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, i32imm:$rot), IIC_iEXTAsr, opc, "\t$Rd, $Rn, $Rm, ror $rot", []> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0100; @@ -1142,93 +1164,13 @@ def t2ADR : T2PCOneRegImm<(outs rGPR:$Rd), let neverHasSideEffects = 1, isReMaterializable = 1 in def t2LEApcrel : t2PseudoInst<(outs rGPR:$Rd), (ins i32imm:$label, pred:$p), - Size4Bytes, IIC_iALUi, []>; + 4, IIC_iALUi, []>; def t2LEApcrelJT : t2PseudoInst<(outs rGPR:$Rd), (ins i32imm:$label, nohash_imm:$id, pred:$p), - Size4Bytes, IIC_iALUi, + 4, IIC_iALUi, []>; -// FIXME: None of these add/sub SP special instructions should be necessary -// at all for thumb2 since they use the same encodings as the generic -// add/sub instructions. In thumb1 we need them since they have dedicated -// encodings. At the least, they should be pseudo instructions. -// ADD r, sp, {so_imm|i12} -let isCodeGenOnly = 1 in { -def t2ADDrSPi : T2sTwoRegImm<(outs GPR:$Rd), (ins GPR:$Rn, t2_so_imm:$imm), - IIC_iALUi, "add", ".w\t$Rd, $Rn, $imm", []> { - let Inst{31-27} = 0b11110; - let Inst{25} = 0; - let Inst{24-21} = 0b1000; - let Inst{15} = 0; -} -def t2ADDrSPi12 : T2TwoRegImm<(outs GPR:$Rd), (ins GPR:$Rn, imm0_4095:$imm), - IIC_iALUi, "addw", "\t$Rd, $Rn, $imm", []> { - let Inst{31-27} = 0b11110; - let Inst{25-20} = 0b100000; - let Inst{15} = 0; -} - -// ADD r, sp, so_reg -def t2ADDrSPs : T2sTwoRegShiftedReg< - (outs GPR:$Rd), (ins GPR:$Rn, t2_so_reg:$ShiftedRm), - IIC_iALUsi, "add", ".w\t$Rd, $Rn, $ShiftedRm", []> { - let Inst{31-27} = 0b11101; - let Inst{26-25} = 0b01; - let Inst{24-21} = 0b1000; - let Inst{15} = 0; -} - -// SUB r, sp, {so_imm|i12} -def t2SUBrSPi : T2sTwoRegImm<(outs GPR:$Rd), (ins GPR:$Rn, t2_so_imm:$imm), - IIC_iALUi, "sub", ".w\t$Rd, $Rn, $imm", []> { - let Inst{31-27} = 0b11110; - let Inst{25} = 0; - let Inst{24-21} = 0b1101; - let Inst{15} = 0; -} -def t2SUBrSPi12 : T2TwoRegImm<(outs GPR:$Rd), (ins GPR:$Rn, imm0_4095:$imm), - IIC_iALUi, "subw", "\t$Rd, $Rn, $imm", []> { - let Inst{31-27} = 0b11110; - let Inst{25-20} = 0b101010; - let Inst{15} = 0; -} - -// SUB r, sp, so_reg -def t2SUBrSPs : T2sTwoRegImm<(outs GPR:$Rd), (ins GPR:$Rn, t2_so_reg:$imm), - IIC_iALUsi, - "sub", "\t$Rd, $Rn, $imm", []> { - let Inst{31-27} = 0b11101; - let Inst{26-25} = 0b01; - let Inst{24-21} = 0b1101; - let Inst{19-16} = 0b1101; // Rn = sp - let Inst{15} = 0; -} -} // end isCodeGenOnly = 1 - -// Signed and unsigned division on v7-M -def t2SDIV : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iALUi, - "sdiv", "\t$Rd, $Rn, $Rm", - [(set rGPR:$Rd, (sdiv rGPR:$Rn, rGPR:$Rm))]>, - Requires<[HasDivide, IsThumb2]> { - let Inst{31-27} = 0b11111; - let Inst{26-21} = 0b011100; - let Inst{20} = 0b1; - let Inst{15-12} = 0b1111; - let Inst{7-4} = 0b1111; -} - -def t2UDIV : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iALUi, - "udiv", "\t$Rd, $Rn, $Rm", - [(set rGPR:$Rd, (udiv rGPR:$Rn, rGPR:$Rm))]>, - Requires<[HasDivide, IsThumb2]> { - let Inst{31-27} = 0b11111; - let Inst{26-21} = 0b011101; - let Inst{20} = 0b1; - let Inst{15-12} = 0b1111; - let Inst{7-4} = 0b1111; -} - //===----------------------------------------------------------------------===// // Load / store Instructions. // @@ -1668,6 +1610,10 @@ def t2MOVi : T2sOneRegImm<(outs rGPR:$Rd), (ins t2_so_imm:$imm), IIC_iMOVi, let Inst{15} = 0; } +def : InstAlias<"mov${s}${p} $Rd, $imm", (t2MOVi rGPR:$Rd, t2_so_imm:$imm, + pred:$p, cc_out:$s)>, + Requires<[IsThumb2]>; + let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in def t2MOVi16 : T2I<(outs rGPR:$Rd), (ins i32imm_hilo16:$imm), IIC_iMOVi, "movw", "\t$Rd, $imm", @@ -1788,8 +1734,10 @@ defm t2ADC : T2I_adde_sube_irs<0b1010, "adc", BinOpFrag<(adde_dead_carry node:$LHS, node:$RHS)>, 1>; defm t2SBC : T2I_adde_sube_irs<0b1011, "sbc", BinOpFrag<(sube_dead_carry node:$LHS, node:$RHS)>>; -defm t2ADCS : T2I_adde_sube_s_irs<BinOpFrag<(adde_live_carry node:$LHS, node:$RHS)>, 1>; -defm t2SBCS : T2I_adde_sube_s_irs<BinOpFrag<(sube_live_carry node:$LHS, node:$RHS)>>; +defm t2ADCS : T2I_adde_sube_s_irs<BinOpFrag<(adde_live_carry node:$LHS, + node:$RHS)>, 1>; +defm t2SBCS : T2I_adde_sube_s_irs<BinOpFrag<(sube_live_carry node:$LHS, + node:$RHS)>>; // RSB defm t2RSB : T2I_rbin_irs <0b1110, "rsb", @@ -1833,7 +1781,8 @@ def : T2Pat<(adde_live_carry rGPR:$src, t2_so_imm_not:$imm), // Select Bytes -- for disassembly only def t2SEL : T2ThreeReg<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), - NoItinerary, "sel", "\t$Rd, $Rn, $Rm", []> { + NoItinerary, "sel", "\t$Rd, $Rn, $Rm", []>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11111; let Inst{26-24} = 0b010; let Inst{23} = 0b1; @@ -1849,7 +1798,8 @@ class T2I_pam<bits<3> op22_20, bits<4> op7_4, string opc, list<dag> pat = [/* For disassembly only; pattern left blank */], dag iops = (ins rGPR:$Rn, rGPR:$Rm), string asm = "\t$Rd, $Rn, $Rm"> - : T2I<(outs rGPR:$Rd), iops, NoItinerary, opc, asm, pat> { + : T2I<(outs rGPR:$Rd), iops, NoItinerary, opc, asm, pat>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0101; let Inst{22-20} = op22_20; @@ -1947,12 +1897,14 @@ class T2FourReg_mac<bit long, bits<3> op22_20, bits<4> op7_4, dag oops, def t2USAD8 : T2ThreeReg_mac<0, 0b111, 0b0000, (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), - NoItinerary, "usad8", "\t$Rd, $Rn, $Rm", []> { + NoItinerary, "usad8", "\t$Rd, $Rn, $Rm", []>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{15-12} = 0b1111; } def t2USADA8 : T2FourReg_mac<0, 0b111, 0b0000, (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), NoItinerary, - "usada8", "\t$Rd, $Rn, $Rm, $Ra", []>; + "usada8", "\t$Rd, $Rn, $Rm, $Ra", []>, + Requires<[IsThumb2, HasThumb2DSP]>; // Signed/Unsigned saturate -- for disassembly only @@ -1985,7 +1937,8 @@ def t2SSAT: T2SatI< def t2SSAT16: T2SatI< (outs rGPR:$Rd), (ins ssat_imm:$sat_imm, rGPR:$Rn), NoItinerary, "ssat16", "\t$Rd, $sat_imm, $Rn", - [/* For disassembly only; pattern left blank */]> { + [/* For disassembly only; pattern left blank */]>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11110; let Inst{25-22} = 0b1100; let Inst{20} = 0; @@ -2005,10 +1958,11 @@ def t2USAT: T2SatI< let Inst{15} = 0; } -def t2USAT16: T2SatI< - (outs rGPR:$dst), (ins i32imm:$sat_imm, rGPR:$Rn), NoItinerary, - "usat16", "\t$dst, $sat_imm, $Rn", - [/* For disassembly only; pattern left blank */]> { +def t2USAT16: T2SatI<(outs rGPR:$dst), (ins i32imm:$sat_imm, rGPR:$Rn), + NoItinerary, + "usat16", "\t$dst, $sat_imm, $Rn", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11110; let Inst{25-22} = 0b1110; let Inst{20} = 0; @@ -2084,17 +2038,18 @@ def t2MOVsra_flag : T2TwoRegShiftImm< defm t2AND : T2I_bin_w_irs<0b0000, "and", IIC_iBITi, IIC_iBITr, IIC_iBITsi, - BinOpFrag<(and node:$LHS, node:$RHS)>, 1>; + BinOpFrag<(and node:$LHS, node:$RHS)>, "t2AND", 1>; defm t2ORR : T2I_bin_w_irs<0b0010, "orr", IIC_iBITi, IIC_iBITr, IIC_iBITsi, - BinOpFrag<(or node:$LHS, node:$RHS)>, 1>; + BinOpFrag<(or node:$LHS, node:$RHS)>, "t2ORR", 1>; defm t2EOR : T2I_bin_w_irs<0b0100, "eor", IIC_iBITi, IIC_iBITr, IIC_iBITsi, - BinOpFrag<(xor node:$LHS, node:$RHS)>, 1>; + BinOpFrag<(xor node:$LHS, node:$RHS)>, "t2EOR", 1>; defm t2BIC : T2I_bin_w_irs<0b0001, "bic", IIC_iBITi, IIC_iBITr, IIC_iBITsi, - BinOpFrag<(and node:$LHS, (not node:$RHS))>>; + BinOpFrag<(and node:$LHS, (not node:$RHS))>, + "t2BIC">; class T2BitFI<dag oops, dag iops, InstrItinClass itin, string opc, string asm, list<dag> pattern> @@ -2194,7 +2149,8 @@ let Constraints = "$src = $Rd" in { defm t2ORN : T2I_bin_irs<0b0011, "orn", IIC_iBITi, IIC_iBITr, IIC_iBITsi, - BinOpFrag<(or node:$LHS, (not node:$RHS))>, 0, "">; + BinOpFrag<(or node:$LHS, (not node:$RHS))>, + "t2ORN", 0, "">; // Prefer over of t2EORri ra, rb, -1 because mvn has 16-bit version let AddedComplexity = 1 in @@ -2277,7 +2233,8 @@ def t2UMLAL : T2MulLong<0b110, 0b0000, def t2UMAAL : T2MulLong<0b110, 0b0110, (outs rGPR:$RdLo, rGPR:$RdHi), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMAC64, - "umaal", "\t$RdLo, $RdHi, $Rn, $Rm", []>; + "umaal", "\t$RdLo, $RdHi, $Rn, $Rm", []>, + Requires<[IsThumb2, HasThumb2DSP]>; } // neverHasSideEffects // Rounding variants of the below included for disassembly only @@ -2285,7 +2242,8 @@ def t2UMAAL : T2MulLong<0b110, 0b0110, // Most significant word multiply def t2SMMUL : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL32, "smmul", "\t$Rd, $Rn, $Rm", - [(set rGPR:$Rd, (mulhs rGPR:$Rn, rGPR:$Rm))]> { + [(set rGPR:$Rd, (mulhs rGPR:$Rn, rGPR:$Rm))]>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b101; @@ -2294,7 +2252,8 @@ def t2SMMUL : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL32, } def t2SMMULR : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL32, - "smmulr", "\t$Rd, $Rn, $Rm", []> { + "smmulr", "\t$Rd, $Rn, $Rm", []>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b101; @@ -2305,7 +2264,8 @@ def t2SMMULR : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL32, def t2SMMLA : T2FourReg< (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32, "smmla", "\t$Rd, $Rn, $Rm, $Ra", - [(set rGPR:$Rd, (add (mulhs rGPR:$Rm, rGPR:$Rn), rGPR:$Ra))]> { + [(set rGPR:$Rd, (add (mulhs rGPR:$Rm, rGPR:$Rn), rGPR:$Ra))]>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b101; @@ -2314,7 +2274,8 @@ def t2SMMLA : T2FourReg< def t2SMMLAR: T2FourReg< (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32, - "smmlar", "\t$Rd, $Rn, $Rm, $Ra", []> { + "smmlar", "\t$Rd, $Rn, $Rm, $Ra", []>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b101; @@ -2324,7 +2285,8 @@ def t2SMMLAR: T2FourReg< def t2SMMLS: T2FourReg< (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32, "smmls", "\t$Rd, $Rn, $Rm, $Ra", - [(set rGPR:$Rd, (sub rGPR:$Ra, (mulhs rGPR:$Rn, rGPR:$Rm)))]> { + [(set rGPR:$Rd, (sub rGPR:$Ra, (mulhs rGPR:$Rn, rGPR:$Rm)))]>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b110; @@ -2333,7 +2295,8 @@ def t2SMMLS: T2FourReg< def t2SMMLSR:T2FourReg< (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32, - "smmlsr", "\t$Rd, $Rn, $Rm, $Ra", []> { + "smmlsr", "\t$Rd, $Rn, $Rm, $Ra", []>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b110; @@ -2344,7 +2307,8 @@ multiclass T2I_smul<string opc, PatFrag opnode> { def BB : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL16, !strconcat(opc, "bb"), "\t$Rd, $Rn, $Rm", [(set rGPR:$Rd, (opnode (sext_inreg rGPR:$Rn, i16), - (sext_inreg rGPR:$Rm, i16)))]> { + (sext_inreg rGPR:$Rm, i16)))]>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b001; @@ -2356,7 +2320,8 @@ multiclass T2I_smul<string opc, PatFrag opnode> { def BT : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL16, !strconcat(opc, "bt"), "\t$Rd, $Rn, $Rm", [(set rGPR:$Rd, (opnode (sext_inreg rGPR:$Rn, i16), - (sra rGPR:$Rm, (i32 16))))]> { + (sra rGPR:$Rm, (i32 16))))]>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b001; @@ -2368,7 +2333,8 @@ multiclass T2I_smul<string opc, PatFrag opnode> { def TB : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL16, !strconcat(opc, "tb"), "\t$Rd, $Rn, $Rm", [(set rGPR:$Rd, (opnode (sra rGPR:$Rn, (i32 16)), - (sext_inreg rGPR:$Rm, i16)))]> { + (sext_inreg rGPR:$Rm, i16)))]>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b001; @@ -2380,7 +2346,8 @@ multiclass T2I_smul<string opc, PatFrag opnode> { def TT : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL16, !strconcat(opc, "tt"), "\t$Rd, $Rn, $Rm", [(set rGPR:$Rd, (opnode (sra rGPR:$Rn, (i32 16)), - (sra rGPR:$Rm, (i32 16))))]> { + (sra rGPR:$Rm, (i32 16))))]>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b001; @@ -2392,7 +2359,8 @@ multiclass T2I_smul<string opc, PatFrag opnode> { def WB : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL16, !strconcat(opc, "wb"), "\t$Rd, $Rn, $Rm", [(set rGPR:$Rd, (sra (opnode rGPR:$Rn, - (sext_inreg rGPR:$Rm, i16)), (i32 16)))]> { + (sext_inreg rGPR:$Rm, i16)), (i32 16)))]>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b011; @@ -2404,7 +2372,8 @@ multiclass T2I_smul<string opc, PatFrag opnode> { def WT : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL16, !strconcat(opc, "wt"), "\t$Rd, $Rn, $Rm", [(set rGPR:$Rd, (sra (opnode rGPR:$Rn, - (sra rGPR:$Rm, (i32 16))), (i32 16)))]> { + (sra rGPR:$Rm, (i32 16))), (i32 16)))]>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b011; @@ -2421,7 +2390,8 @@ multiclass T2I_smla<string opc, PatFrag opnode> { !strconcat(opc, "bb"), "\t$Rd, $Rn, $Rm, $Ra", [(set rGPR:$Rd, (add rGPR:$Ra, (opnode (sext_inreg rGPR:$Rn, i16), - (sext_inreg rGPR:$Rm, i16))))]> { + (sext_inreg rGPR:$Rm, i16))))]>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b001; @@ -2433,7 +2403,8 @@ multiclass T2I_smla<string opc, PatFrag opnode> { (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC16, !strconcat(opc, "bt"), "\t$Rd, $Rn, $Rm, $Ra", [(set rGPR:$Rd, (add rGPR:$Ra, (opnode (sext_inreg rGPR:$Rn, i16), - (sra rGPR:$Rm, (i32 16)))))]> { + (sra rGPR:$Rm, (i32 16)))))]>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b001; @@ -2445,7 +2416,8 @@ multiclass T2I_smla<string opc, PatFrag opnode> { (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC16, !strconcat(opc, "tb"), "\t$Rd, $Rn, $Rm, $Ra", [(set rGPR:$Rd, (add rGPR:$Ra, (opnode (sra rGPR:$Rn, (i32 16)), - (sext_inreg rGPR:$Rm, i16))))]> { + (sext_inreg rGPR:$Rm, i16))))]>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b001; @@ -2457,7 +2429,8 @@ multiclass T2I_smla<string opc, PatFrag opnode> { (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC16, !strconcat(opc, "tt"), "\t$Rd, $Rn, $Rm, $Ra", [(set rGPR:$Rd, (add rGPR:$Ra, (opnode (sra rGPR:$Rn, (i32 16)), - (sra rGPR:$Rm, (i32 16)))))]> { + (sra rGPR:$Rm, (i32 16)))))]>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b001; @@ -2469,7 +2442,8 @@ multiclass T2I_smla<string opc, PatFrag opnode> { (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC16, !strconcat(opc, "wb"), "\t$Rd, $Rn, $Rm, $Ra", [(set rGPR:$Rd, (add rGPR:$Ra, (sra (opnode rGPR:$Rn, - (sext_inreg rGPR:$Rm, i16)), (i32 16))))]> { + (sext_inreg rGPR:$Rm, i16)), (i32 16))))]>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b011; @@ -2481,7 +2455,8 @@ multiclass T2I_smla<string opc, PatFrag opnode> { (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC16, !strconcat(opc, "wt"), "\t$Rd, $Rn, $Rm, $Ra", [(set rGPR:$Rd, (add rGPR:$Ra, (sra (opnode rGPR:$Rn, - (sra rGPR:$Rm, (i32 16))), (i32 16))))]> { + (sra rGPR:$Rm, (i32 16))), (i32 16))))]>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b011; @@ -2496,66 +2471,108 @@ defm t2SMLA : T2I_smla<"smla", BinOpFrag<(mul node:$LHS, node:$RHS)>>; // Halfword multiple accumulate long: SMLAL<x><y> -- for disassembly only def t2SMLALBB : T2FourReg_mac<1, 0b100, 0b1000, (outs rGPR:$Ra,rGPR:$Rd), (ins rGPR:$Rn,rGPR:$Rm), IIC_iMAC64, "smlalbb", "\t$Ra, $Rd, $Rn, $Rm", - [/* For disassembly only; pattern left blank */]>; + [/* For disassembly only; pattern left blank */]>, + Requires<[IsThumb2, HasThumb2DSP]>; def t2SMLALBT : T2FourReg_mac<1, 0b100, 0b1001, (outs rGPR:$Ra,rGPR:$Rd), (ins rGPR:$Rn,rGPR:$Rm), IIC_iMAC64, "smlalbt", "\t$Ra, $Rd, $Rn, $Rm", - [/* For disassembly only; pattern left blank */]>; + [/* For disassembly only; pattern left blank */]>, + Requires<[IsThumb2, HasThumb2DSP]>; def t2SMLALTB : T2FourReg_mac<1, 0b100, 0b1010, (outs rGPR:$Ra,rGPR:$Rd), (ins rGPR:$Rn,rGPR:$Rm), IIC_iMAC64, "smlaltb", "\t$Ra, $Rd, $Rn, $Rm", - [/* For disassembly only; pattern left blank */]>; + [/* For disassembly only; pattern left blank */]>, + Requires<[IsThumb2, HasThumb2DSP]>; def t2SMLALTT : T2FourReg_mac<1, 0b100, 0b1011, (outs rGPR:$Ra,rGPR:$Rd), (ins rGPR:$Rn,rGPR:$Rm), IIC_iMAC64, "smlaltt", "\t$Ra, $Rd, $Rn, $Rm", - [/* For disassembly only; pattern left blank */]>; + [/* For disassembly only; pattern left blank */]>, + Requires<[IsThumb2, HasThumb2DSP]>; // Dual halfword multiple: SMUAD, SMUSD, SMLAD, SMLSD, SMLALD, SMLSLD // These are for disassembly only. def t2SMUAD: T2ThreeReg_mac< 0, 0b010, 0b0000, (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), - IIC_iMAC32, "smuad", "\t$Rd, $Rn, $Rm", []> { + IIC_iMAC32, "smuad", "\t$Rd, $Rn, $Rm", []>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{15-12} = 0b1111; } def t2SMUADX:T2ThreeReg_mac< 0, 0b010, 0b0001, (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), - IIC_iMAC32, "smuadx", "\t$Rd, $Rn, $Rm", []> { + IIC_iMAC32, "smuadx", "\t$Rd, $Rn, $Rm", []>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{15-12} = 0b1111; } def t2SMUSD: T2ThreeReg_mac< 0, 0b100, 0b0000, (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), - IIC_iMAC32, "smusd", "\t$Rd, $Rn, $Rm", []> { + IIC_iMAC32, "smusd", "\t$Rd, $Rn, $Rm", []>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{15-12} = 0b1111; } def t2SMUSDX:T2ThreeReg_mac< 0, 0b100, 0b0001, (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), - IIC_iMAC32, "smusdx", "\t$Rd, $Rn, $Rm", []> { + IIC_iMAC32, "smusdx", "\t$Rd, $Rn, $Rm", []>, + Requires<[IsThumb2, HasThumb2DSP]> { let Inst{15-12} = 0b1111; } def t2SMLAD : T2ThreeReg_mac< 0, 0b010, 0b0000, (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32, "smlad", - "\t$Rd, $Rn, $Rm, $Ra", []>; + "\t$Rd, $Rn, $Rm, $Ra", []>, + Requires<[IsThumb2, HasThumb2DSP]>; def t2SMLADX : T2FourReg_mac< 0, 0b010, 0b0001, (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32, "smladx", - "\t$Rd, $Rn, $Rm, $Ra", []>; + "\t$Rd, $Rn, $Rm, $Ra", []>, + Requires<[IsThumb2, HasThumb2DSP]>; def t2SMLSD : T2FourReg_mac<0, 0b100, 0b0000, (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32, "smlsd", - "\t$Rd, $Rn, $Rm, $Ra", []>; + "\t$Rd, $Rn, $Rm, $Ra", []>, + Requires<[IsThumb2, HasThumb2DSP]>; def t2SMLSDX : T2FourReg_mac<0, 0b100, 0b0001, (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32, "smlsdx", - "\t$Rd, $Rn, $Rm, $Ra", []>; + "\t$Rd, $Rn, $Rm, $Ra", []>, + Requires<[IsThumb2, HasThumb2DSP]>; def t2SMLALD : T2FourReg_mac<1, 0b100, 0b1100, (outs rGPR:$Ra,rGPR:$Rd), (ins rGPR:$Rm, rGPR:$Rn), IIC_iMAC64, "smlald", - "\t$Ra, $Rd, $Rm, $Rn", []>; + "\t$Ra, $Rd, $Rm, $Rn", []>, + Requires<[IsThumb2, HasThumb2DSP]>; def t2SMLALDX : T2FourReg_mac<1, 0b100, 0b1101, (outs rGPR:$Ra,rGPR:$Rd), (ins rGPR:$Rm,rGPR:$Rn), IIC_iMAC64, "smlaldx", - "\t$Ra, $Rd, $Rm, $Rn", []>; + "\t$Ra, $Rd, $Rm, $Rn", []>, + Requires<[IsThumb2, HasThumb2DSP]>; def t2SMLSLD : T2FourReg_mac<1, 0b101, 0b1100, (outs rGPR:$Ra,rGPR:$Rd), (ins rGPR:$Rm,rGPR:$Rn), IIC_iMAC64, "smlsld", - "\t$Ra, $Rd, $Rm, $Rn", []>; + "\t$Ra, $Rd, $Rm, $Rn", []>, + Requires<[IsThumb2, HasThumb2DSP]>; def t2SMLSLDX : T2FourReg_mac<1, 0b101, 0b1101, (outs rGPR:$Ra,rGPR:$Rd), (ins rGPR:$Rm,rGPR:$Rn), IIC_iMAC64, "smlsldx", - "\t$Ra, $Rd, $Rm, $Rn", []>; + "\t$Ra, $Rd, $Rm, $Rn", []>, + Requires<[IsThumb2, HasThumb2DSP]>; + +//===----------------------------------------------------------------------===// +// Division Instructions. +// Signed and unsigned division on v7-M +// +def t2SDIV : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iALUi, + "sdiv", "\t$Rd, $Rn, $Rm", + [(set rGPR:$Rd, (sdiv rGPR:$Rn, rGPR:$Rm))]>, + Requires<[HasDivide, IsThumb2]> { + let Inst{31-27} = 0b11111; + let Inst{26-21} = 0b011100; + let Inst{20} = 0b1; + let Inst{15-12} = 0b1111; + let Inst{7-4} = 0b1111; +} + +def t2UDIV : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iALUi, + "udiv", "\t$Rd, $Rn, $Rm", + [(set rGPR:$Rd, (udiv rGPR:$Rn, rGPR:$Rm))]>, + Requires<[HasDivide, IsThumb2]> { + let Inst{31-27} = 0b11111; + let Inst{26-21} = 0b011101; + let Inst{20} = 0b1; + let Inst{15-12} = 0b1111; + let Inst{7-4} = 0b1111; +} //===----------------------------------------------------------------------===// // Misc. Arithmetic Instructions. @@ -2585,25 +2602,16 @@ def t2REV : T2I_misc<0b01, 0b00, (outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iUNAr, def t2REV16 : T2I_misc<0b01, 0b01, (outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iUNAr, "rev16", ".w\t$Rd, $Rm", - [(set rGPR:$Rd, - (or (and (srl rGPR:$Rm, (i32 8)), 0xFF), - (or (and (shl rGPR:$Rm, (i32 8)), 0xFF00), - (or (and (srl rGPR:$Rm, (i32 8)), 0xFF0000), - (and (shl rGPR:$Rm, (i32 8)), 0xFF000000)))))]>; + [(set rGPR:$Rd, (rotr (bswap rGPR:$Rm), (i32 16)))]>; def t2REVSH : T2I_misc<0b01, 0b11, (outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iUNAr, "revsh", ".w\t$Rd, $Rm", - [(set rGPR:$Rd, - (sext_inreg - (or (srl rGPR:$Rm, (i32 8)), - (shl rGPR:$Rm, (i32 8))), i16))]>; + [(set rGPR:$Rd, (sra (bswap rGPR:$Rm), (i32 16)))]>; -def : T2Pat<(sext_inreg (or (srl (and rGPR:$Rm, 0xFF00), (i32 8)), - (shl rGPR:$Rm, (i32 8))), i16), +def : T2Pat<(or (sra (shl rGPR:$Rm, (i32 24)), (i32 16)), + (and (srl rGPR:$Rm, (i32 8)), 0xFF)), (t2REVSH rGPR:$Rm)>; -def : T2Pat<(sra (bswap rGPR:$Rm), (i32 16)), (t2REVSH rGPR:$Rm)>; - def t2PKHBT : T2ThreeReg< (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, shift_imm:$sh), IIC_iBITsi, "pkhbt", "\t$Rd, $Rn, $Rm$sh", @@ -2699,33 +2707,21 @@ defm t2TEQ : T2I_cmp_irs<0b0100, "teq", // FIXME: should be able to write a pattern for ARMcmov, but can't use // a two-value operand where a dag node expects two operands. :( let neverHasSideEffects = 1 in { -def t2MOVCCr : T2TwoReg< - (outs rGPR:$Rd), (ins rGPR:$false, rGPR:$Rm), IIC_iCMOVr, - "mov", ".w\t$Rd, $Rm", +def t2MOVCCr : t2PseudoInst<(outs rGPR:$Rd), + (ins rGPR:$false, rGPR:$Rm, pred:$p), + 4, IIC_iCMOVr, [/*(set rGPR:$Rd, (ARMcmov rGPR:$false, rGPR:$Rm, imm:$cc, CCR:$ccr))*/]>, - RegConstraint<"$false = $Rd"> { - let Inst{31-27} = 0b11101; - let Inst{26-25} = 0b01; - let Inst{24-21} = 0b0010; - let Inst{20} = 0; // The S bit. - let Inst{19-16} = 0b1111; // Rn - let Inst{14-12} = 0b000; - let Inst{7-4} = 0b0000; -} + RegConstraint<"$false = $Rd">; let isMoveImm = 1 in -def t2MOVCCi : T2OneRegImm<(outs rGPR:$Rd), (ins rGPR:$false, t2_so_imm:$imm), - IIC_iCMOVi, "mov", ".w\t$Rd, $imm", +def t2MOVCCi : t2PseudoInst<(outs rGPR:$Rd), + (ins rGPR:$false, t2_so_imm:$imm, pred:$p), + 4, IIC_iCMOVi, [/*(set rGPR:$Rd,(ARMcmov rGPR:$false,t2_so_imm:$imm, imm:$cc, CCR:$ccr))*/]>, - RegConstraint<"$false = $Rd"> { - let Inst{31-27} = 0b11110; - let Inst{25} = 0; - let Inst{24-21} = 0b0010; - let Inst{20} = 0; // The S bit. - let Inst{19-16} = 0b1111; // Rn - let Inst{15} = 0; -} + RegConstraint<"$false = $Rd">; +// FIXME: Pseudo-ize these. For now, just mark codegen only. +let isCodeGenOnly = 1 in { let isMoveImm = 1 in def t2MOVCCi16 : T2I<(outs rGPR:$Rd), (ins rGPR:$false, i32imm_hilo16:$imm), IIC_iCMOVi, @@ -2792,6 +2788,7 @@ def t2MOVCCror : T2I_movcc_sh<0b11, (outs rGPR:$Rd), (ins rGPR:$false, rGPR:$Rm, i32imm:$imm), IIC_iCMOVsi, "ror", ".w\t$Rd, $Rm, $imm", []>, RegConstraint<"$false = $Rd">; +} // isCodeGenOnly = 1 } // neverHasSideEffects //===----------------------------------------------------------------------===// @@ -2826,7 +2823,7 @@ def t2ISB : AInoP<(outs), (ins), ThumbFrm, NoItinerary, "isb", "", let Inst{3-0} = 0b1111; } -class T2I_ldrex<bits<2> opcod, dag oops, dag iops, AddrMode am, SizeFlagVal sz, +class T2I_ldrex<bits<2> opcod, dag oops, dag iops, AddrMode am, int sz, InstrItinClass itin, string opc, string asm, string cstr, list<dag> pattern, bits<4> rt2 = 0b1111> : Thumb2I<oops, iops, am, sz, itin, opc, asm, cstr, pattern> { @@ -2842,7 +2839,7 @@ class T2I_ldrex<bits<2> opcod, dag oops, dag iops, AddrMode am, SizeFlagVal sz, let Inst{19-16} = addr; let Inst{15-12} = Rt; } -class T2I_strex<bits<2> opcod, dag oops, dag iops, AddrMode am, SizeFlagVal sz, +class T2I_strex<bits<2> opcod, dag oops, dag iops, AddrMode am, int sz, InstrItinClass itin, string opc, string asm, string cstr, list<dag> pattern, bits<4> rt2 = 0b1111> : Thumb2I<oops, iops, am, sz, itin, opc, asm, cstr, pattern> { @@ -2861,16 +2858,15 @@ class T2I_strex<bits<2> opcod, dag oops, dag iops, AddrMode am, SizeFlagVal sz, } let mayLoad = 1 in { -def t2LDREXB : T2I_ldrex<0b00, (outs rGPR:$Rt), (ins t2addrmode_reg:$addr), AddrModeNone, - Size4Bytes, NoItinerary, "ldrexb", "\t$Rt, $addr", - "", []>; -def t2LDREXH : T2I_ldrex<0b01, (outs rGPR:$Rt), (ins t2addrmode_reg:$addr), AddrModeNone, - Size4Bytes, NoItinerary, "ldrexh", "\t$Rt, $addr", - "", []>; -def t2LDREX : Thumb2I<(outs rGPR:$Rt), (ins t2addrmode_reg:$addr), AddrModeNone, - Size4Bytes, NoItinerary, - "ldrex", "\t$Rt, $addr", "", - []> { +def t2LDREXB : T2I_ldrex<0b00, (outs rGPR:$Rt), (ins t2addrmode_reg:$addr), + AddrModeNone, 4, NoItinerary, + "ldrexb", "\t$Rt, $addr", "", []>; +def t2LDREXH : T2I_ldrex<0b01, (outs rGPR:$Rt), (ins t2addrmode_reg:$addr), + AddrModeNone, 4, NoItinerary, + "ldrexh", "\t$Rt, $addr", "", []>; +def t2LDREX : Thumb2I<(outs rGPR:$Rt), (ins t2addrmode_reg:$addr), + AddrModeNone, 4, NoItinerary, + "ldrex", "\t$Rt, $addr", "", []> { let Inst{31-27} = 0b11101; let Inst{26-20} = 0b0000101; let Inst{11-8} = 0b1111; @@ -2884,7 +2880,7 @@ def t2LDREX : Thumb2I<(outs rGPR:$Rt), (ins t2addrmode_reg:$addr), AddrModeNone let hasExtraDefRegAllocReq = 1 in def t2LDREXD : T2I_ldrex<0b11, (outs rGPR:$Rt, rGPR:$Rt2), (ins t2addrmode_reg:$addr), - AddrModeNone, Size4Bytes, NoItinerary, + AddrModeNone, 4, NoItinerary, "ldrexd", "\t$Rt, $Rt2, $addr", "", [], {?, ?, ?, ?}> { bits<4> Rt2; @@ -2893,14 +2889,16 @@ def t2LDREXD : T2I_ldrex<0b11, (outs rGPR:$Rt, rGPR:$Rt2), } let mayStore = 1, Constraints = "@earlyclobber $Rd" in { -def t2STREXB : T2I_strex<0b00, (outs rGPR:$Rd), (ins rGPR:$Rt, t2addrmode_reg:$addr), - AddrModeNone, Size4Bytes, NoItinerary, - "strexb", "\t$Rd, $Rt, $addr", "", []>; -def t2STREXH : T2I_strex<0b01, (outs rGPR:$Rd), (ins rGPR:$Rt, t2addrmode_reg:$addr), - AddrModeNone, Size4Bytes, NoItinerary, - "strexh", "\t$Rd, $Rt, $addr", "", []>; +def t2STREXB : T2I_strex<0b00, (outs rGPR:$Rd), + (ins rGPR:$Rt, t2addrmode_reg:$addr), + AddrModeNone, 4, NoItinerary, + "strexb", "\t$Rd, $Rt, $addr", "", []>; +def t2STREXH : T2I_strex<0b01, (outs rGPR:$Rd), + (ins rGPR:$Rt, t2addrmode_reg:$addr), + AddrModeNone, 4, NoItinerary, + "strexh", "\t$Rd, $Rt, $addr", "", []>; def t2STREX : Thumb2I<(outs rGPR:$Rd), (ins rGPR:$Rt, t2addrmode_reg:$addr), - AddrModeNone, Size4Bytes, NoItinerary, + AddrModeNone, 4, NoItinerary, "strex", "\t$Rd, $Rt, $addr", "", []> { let Inst{31-27} = 0b11101; @@ -2919,7 +2917,7 @@ def t2STREX : Thumb2I<(outs rGPR:$Rd), (ins rGPR:$Rt, t2addrmode_reg:$addr), let hasExtraSrcRegAllocReq = 1, Constraints = "@earlyclobber $Rd" in def t2STREXD : T2I_strex<0b11, (outs rGPR:$Rd), (ins rGPR:$Rt, rGPR:$Rt2, t2addrmode_reg:$addr), - AddrModeNone, Size4Bytes, NoItinerary, + AddrModeNone, 4, NoItinerary, "strexd", "\t$Rd, $Rt, $Rt2, $addr", "", [], {?, ?, ?, ?}> { bits<4> Rt2; @@ -2940,22 +2938,6 @@ def t2CLREX : T2XI<(outs), (ins), NoItinerary, "clrex", } //===----------------------------------------------------------------------===// -// TLS Instructions -// - -// __aeabi_read_tp preserves the registers r1-r3. -let isCall = 1, - Defs = [R0, R12, LR, CPSR], Uses = [SP] in { - def t2TPsoft : T2XI<(outs), (ins), IIC_Br, - "bl\t__aeabi_read_tp", - [(set R0, ARMthread_pointer)]> { - let Inst{31-27} = 0b11110; - let Inst{15-14} = 0b11; - let Inst{12} = 1; - } -} - -//===----------------------------------------------------------------------===// // SJLJ Exception handling intrinsics // eh_sjlj_setjmp() is an instruction sequence to store the return // address and save #0 in R0 for the non-longjmp case. @@ -2973,7 +2955,7 @@ let Defs = QQQQ0, QQQQ1, QQQQ2, QQQQ3 ], hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1 in { def t2Int_eh_sjlj_setjmp : Thumb2XI<(outs), (ins tGPR:$src, tGPR:$val), - AddrModeNone, SizeSpecial, NoItinerary, "", "", + AddrModeNone, 0, NoItinerary, "", "", [(set R0, (ARMeh_sjlj_setjmp tGPR:$src, tGPR:$val))]>, Requires<[IsThumb2, HasVFP2]>; } @@ -2982,7 +2964,7 @@ let Defs = [ R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR, CPSR ], hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1 in { def t2Int_eh_sjlj_setjmp_nofp : Thumb2XI<(outs), (ins tGPR:$src, tGPR:$val), - AddrModeNone, SizeSpecial, NoItinerary, "", "", + AddrModeNone, 0, NoItinerary, "", "", [(set R0, (ARMeh_sjlj_setjmp tGPR:$src, tGPR:$val))]>, Requires<[IsThumb2, NoVFP]>; } @@ -2993,28 +2975,14 @@ let Defs = // // FIXME: remove when we have a way to marking a MI with these properties. -// FIXME: $dst1 should be a def. But the extra ops must be in the end of the -// operand list. // FIXME: Should pc be an implicit operand like PICADD, etc? let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, hasExtraDefRegAllocReq = 1, isCodeGenOnly = 1 in -def t2LDMIA_RET: T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, - reglist:$regs, variable_ops), - IIC_iLoad_mBr, - "ldmia${p}.w\t$Rn!, $regs", - "$Rn = $wb", []> { - bits<4> Rn; - bits<16> regs; - - let Inst{31-27} = 0b11101; - let Inst{26-25} = 0b00; - let Inst{24-23} = 0b01; // Increment After - let Inst{22} = 0; - let Inst{21} = 1; // Writeback - let Inst{20} = 1; - let Inst{19-16} = Rn; - let Inst{15-0} = regs; -} +def t2LDMIA_RET: t2PseudoExpand<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, + reglist:$regs, variable_ops), + 4, IIC_iLoad_mBr, [], + (t2LDMIA_UPD GPR:$wb, GPR:$Rn, pred:$p, reglist:$regs)>, + RegConstraint<"$Rn = $wb">; let isBranch = 1, isTerminator = 1, isBarrier = 1 in { let isPredicable = 1 in @@ -3036,17 +3004,17 @@ def t2B : T2XI<(outs), (ins uncondbrtarget:$target), IIC_Br, let isNotDuplicable = 1, isIndirectBranch = 1 in { def t2BR_JT : t2PseudoInst<(outs), (ins GPR:$target, GPR:$index, i32imm:$jt, i32imm:$id), - SizeSpecial, IIC_Br, + 0, IIC_Br, [(ARMbr2jt GPR:$target, GPR:$index, tjumptable:$jt, imm:$id)]>; // FIXME: Add a non-pc based case that can be predicated. def t2TBB_JT : t2PseudoInst<(outs), (ins GPR:$index, i32imm:$jt, i32imm:$id), - SizeSpecial, IIC_Br, []>; + 0, IIC_Br, []>; def t2TBH_JT : t2PseudoInst<(outs), (ins GPR:$index, i32imm:$jt, i32imm:$id), - SizeSpecial, IIC_Br, []>; + 0, IIC_Br, []>; def t2TBB : T2I<(outs), (ins GPR:$Rn, GPR:$Rm), IIC_Br, "tbb", "\t[$Rn, $Rm]", []> { @@ -3094,11 +3062,22 @@ def t2Bcc : T2I<(outs), (ins brtarget:$target), IIC_Br, let Inst{10-0} = target{11-1}; } +// Tail calls. The Darwin version of thumb tail calls uses a t2 branch, so +// it goes here. +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in { + // Darwin version. + let Defs = [R0, R1, R2, R3, R9, R12, QQQQ0, QQQQ2, QQQQ3, PC], + Uses = [SP] in + def tTAILJMPd: tPseudoExpand<(outs), (ins uncondbrtarget:$dst, variable_ops), + 4, IIC_Br, [], + (t2B uncondbrtarget:$dst)>, + Requires<[IsThumb2, IsDarwin]>; +} // IT block let Defs = [ITSTATE] in def t2IT : Thumb2XI<(outs), (ins it_pred:$cc, it_mask:$mask), - AddrModeNone, Size2Bytes, IIC_iALUx, + AddrModeNone, 2, IIC_iALUx, "it$mask\t$cc", "", []> { // 16-bit instruction. let Inst{31-16} = 0x0000; @@ -3178,8 +3157,7 @@ def t2WFE : T2I_hint<0b00000010, "wfe", ".w">; def t2WFI : T2I_hint<0b00000011, "wfi", ".w">; def t2SEV : T2I_hint<0b00000100, "sev", ".w">; -def t2DBG : T2I<(outs),(ins i32imm:$opt), NoItinerary, "dbg", "\t$opt", - [/* For disassembly only; pattern left blank */]> { +def t2DBG : T2I<(outs), (ins imm0_15:$opt), NoItinerary, "dbg", "\t$opt", []> { let Inst{31-20} = 0xf3a; let Inst{15-14} = 0b10; let Inst{12} = 0; @@ -3347,12 +3325,13 @@ def t2MSR : T2SpecialReg<0b111100111000 /* op31-20 */, 0b10 /* op15-14 */, } //===----------------------------------------------------------------------===// -// Move between coprocessor and ARM core register -- for disassembly only +// Move between coprocessor and ARM core register // -class t2MovRCopro<string opc, bit direction, dag oops, dag iops, +class t2MovRCopro<bits<4> Op, string opc, bit direction, dag oops, dag iops, list<dag> pattern> - : T2Cop<oops, iops, !strconcat(opc, "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2"), + : T2Cop<Op, oops, iops, + !strconcat(opc, "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2"), pattern> { let Inst{27-24} = 0b1110; let Inst{20} = direction; @@ -3373,22 +3352,10 @@ class t2MovRCopro<string opc, bit direction, dag oops, dag iops, let Inst{19-16} = CRn; } -def t2MCR2 : t2MovRCopro<"mcr2", 0 /* from ARM core register to coprocessor */, - (outs), (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, c_imm:$CRn, - c_imm:$CRm, i32imm:$opc2), - [(int_arm_mcr2 imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn, - imm:$CRm, imm:$opc2)]>; -def t2MRC2 : t2MovRCopro<"mrc2", 1 /* from coprocessor to ARM core register */, - (outs GPR:$Rt), (ins p_imm:$cop, i32imm:$opc1, c_imm:$CRn, - c_imm:$CRm, i32imm:$opc2), []>; - -def : T2v6Pat<(int_arm_mrc2 imm:$cop, imm:$opc1, imm:$CRn, - imm:$CRm, imm:$opc2), - (t2MRC2 imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2)>; - -class t2MovRRCopro<string opc, bit direction, - list<dag> pattern = [/* For disassembly only */]> - : T2Cop<(outs), (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, GPR:$Rt2, c_imm:$CRm), +class t2MovRRCopro<bits<4> Op, string opc, bit direction, + list<dag> pattern = []> + : T2Cop<Op, (outs), + (ins p_imm:$cop, imm0_15:$opc1, GPR:$Rt, GPR:$Rt2, c_imm:$CRm), !strconcat(opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm"), pattern> { let Inst{27-24} = 0b1100; let Inst{23-21} = 0b010; @@ -3407,19 +3374,77 @@ class t2MovRRCopro<string opc, bit direction, let Inst{3-0} = CRm; } -def t2MCRR2 : t2MovRRCopro<"mcrr2", - 0 /* from ARM core register to coprocessor */, +/* from ARM core register to coprocessor */ +def t2MCR : t2MovRCopro<0b1110, "mcr", 0, + (outs), + (ins p_imm:$cop, imm0_7:$opc1, GPR:$Rt, c_imm:$CRn, + c_imm:$CRm, imm0_7:$opc2), + [(int_arm_mcr imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn, + imm:$CRm, imm:$opc2)]>; +def t2MCR2 : t2MovRCopro<0b1111, "mcr2", 0, + (outs), (ins p_imm:$cop, imm0_7:$opc1, GPR:$Rt, c_imm:$CRn, + c_imm:$CRm, imm0_7:$opc2), + [(int_arm_mcr2 imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn, + imm:$CRm, imm:$opc2)]>; + +/* from coprocessor to ARM core register */ +def t2MRC : t2MovRCopro<0b1110, "mrc", 1, + (outs GPR:$Rt), + (ins p_imm:$cop, i32imm:$opc1, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), + []>; + +def t2MRC2 : t2MovRCopro<0b1111, "mrc2", 1, + (outs GPR:$Rt), (ins p_imm:$cop, i32imm:$opc1, c_imm:$CRn, + c_imm:$CRm, i32imm:$opc2), []>; + +def : T2v6Pat<(int_arm_mrc imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2), + (t2MRC imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2)>; + +def : T2v6Pat<(int_arm_mrc2 imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2), + (t2MRC2 imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2)>; + + +/* from ARM core register to coprocessor */ +def t2MCRR : t2MovRRCopro<0b1110, "mcrr", 0, + [(int_arm_mcrr imm:$cop, imm:$opc1, GPR:$Rt, GPR:$Rt2, + imm:$CRm)]>; +def t2MCRR2 : t2MovRRCopro<0b1111, "mcrr2", 0, [(int_arm_mcrr2 imm:$cop, imm:$opc1, GPR:$Rt, GPR:$Rt2, imm:$CRm)]>; -def t2MRRC2 : t2MovRRCopro<"mrrc2", - 1 /* from coprocessor to ARM core register */>; +/* from coprocessor to ARM core register */ +def t2MRRC : t2MovRRCopro<0b1110, "mrrc", 1>; + +def t2MRRC2 : t2MovRRCopro<0b1111, "mrrc2", 1>; //===----------------------------------------------------------------------===// -// Other Coprocessor Instructions. For disassembly only. +// Other Coprocessor Instructions. // -def t2CDP2 : T2Cop<(outs), (ins p_imm:$cop, i32imm:$opc1, - c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), +def tCDP : T2Cop<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1, + c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, imm0_7:$opc2), + "cdp\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2", + [(int_arm_cdp imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn, + imm:$CRm, imm:$opc2)]> { + let Inst{27-24} = 0b1110; + + bits<4> opc1; + bits<4> CRn; + bits<4> CRd; + bits<4> cop; + bits<3> opc2; + bits<4> CRm; + + let Inst{3-0} = CRm; + let Inst{4} = 0; + let Inst{7-5} = opc2; + let Inst{11-8} = cop; + let Inst{15-12} = CRd; + let Inst{19-16} = CRn; + let Inst{23-20} = opc1; +} + +def t2CDP2 : T2Cop<0b1111, (outs), (ins p_imm:$cop, imm0_15:$opc1, + c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, imm0_7:$opc2), "cdp2\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2", [(int_arm_cdp2 imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn, imm:$CRm, imm:$opc2)]> { diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td index 376bd9607e4b..f1f3cb9c2ecd 100644 --- a/lib/Target/ARM/ARMInstrVFP.td +++ b/lib/Target/ARM/ARMInstrVFP.td @@ -94,7 +94,8 @@ multiclass vfp_ldst_mult<string asm, bit L_bit, let Inst{20} = L_bit; } def DIA_UPD : - AXDI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, dpr_reglist:$regs, variable_ops), + AXDI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, dpr_reglist:$regs, + variable_ops), IndexModeUpd, itin_upd, !strconcat(asm, "ia${p}\t$Rn!, $regs"), "$Rn = $wb", []> { let Inst{24-23} = 0b01; // Increment After @@ -102,7 +103,8 @@ multiclass vfp_ldst_mult<string asm, bit L_bit, let Inst{20} = L_bit; } def DDB_UPD : - AXDI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, dpr_reglist:$regs, variable_ops), + AXDI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, dpr_reglist:$regs, + variable_ops), IndexModeUpd, itin_upd, !strconcat(asm, "db${p}\t$Rn!, $regs"), "$Rn = $wb", []> { let Inst{24-23} = 0b10; // Decrement Before @@ -124,7 +126,8 @@ multiclass vfp_ldst_mult<string asm, bit L_bit, let D = VFPNeonDomain; } def SIA_UPD : - AXSI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, spr_reglist:$regs, variable_ops), + AXSI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, spr_reglist:$regs, + variable_ops), IndexModeUpd, itin_upd, !strconcat(asm, "ia${p}\t$Rn!, $regs"), "$Rn = $wb", []> { let Inst{24-23} = 0b01; // Increment After @@ -136,7 +139,8 @@ multiclass vfp_ldst_mult<string asm, bit L_bit, let D = VFPNeonDomain; } def SDB_UPD : - AXSI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, spr_reglist:$regs, variable_ops), + AXSI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, spr_reglist:$regs, + variable_ops), IndexModeUpd, itin_upd, !strconcat(asm, "db${p}\t$Rn!, $regs"), "$Rn = $wb", []> { let Inst{24-23} = 0b10; // Decrement Before @@ -162,6 +166,15 @@ defm VSTM : vfp_ldst_mult<"vstm", 0, IIC_fpLoad_m, IIC_fpLoad_mu>; def : MnemonicAlias<"vldm", "vldmia">; def : MnemonicAlias<"vstm", "vstmia">; +def : InstAlias<"vpush${p} $r", (VSTMDDB_UPD SP, pred:$p, dpr_reglist:$r)>, + Requires<[HasVFP2]>; +def : InstAlias<"vpush${p} $r", (VSTMSDB_UPD SP, pred:$p, spr_reglist:$r)>, + Requires<[HasVFP2]>; +def : InstAlias<"vpop${p} $r", (VLDMDIA_UPD SP, pred:$p, dpr_reglist:$r)>, + Requires<[HasVFP2]>; +def : InstAlias<"vpop${p} $r", (VLDMSIA_UPD SP, pred:$p, spr_reglist:$r)>, + Requires<[HasVFP2]>; + // FLDMX, FSTMX - mixing S/D registers for pre-armv6 cores //===----------------------------------------------------------------------===// @@ -860,7 +873,7 @@ def VULTOD : AVConv1XI<0b11101, 0b11, 0b1011, 0b1011, 1, } // End of 'let Constraints = "$a = $dst", isCodeGenOnly = 1 in' //===----------------------------------------------------------------------===// -// FP FMA Operations. +// FP Multiply-Accumulate Operations. // def VMLAD : ADbI<0b11100, 0b00, 0, 0, @@ -977,12 +990,12 @@ def : Pat<(fsub_mlx (fmul_su SPR:$a, SPR:$b), SPR:$dstin), let neverHasSideEffects = 1 in { def VMOVDcc : ARMPseudoInst<(outs DPR:$Dd), (ins DPR:$Dn, DPR:$Dm, pred:$p), - Size4Bytes, IIC_fpUNA64, + 4, IIC_fpUNA64, [/*(set DPR:$Dd, (ARMcmov DPR:$Dn, DPR:$Dm, imm:$cc))*/]>, RegConstraint<"$Dn = $Dd">; def VMOVScc : ARMPseudoInst<(outs SPR:$Sd), (ins SPR:$Sn, SPR:$Sm, pred:$p), - Size4Bytes, IIC_fpUNA32, + 4, IIC_fpUNA32, [/*(set SPR:$Sd, (ARMcmov SPR:$Sn, SPR:$Sm, imm:$cc))*/]>, RegConstraint<"$Sn = $Sd">; } // neverHasSideEffects diff --git a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp index f4645f15a66f..c6efea1d7806 100644 --- a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp +++ b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp @@ -329,13 +329,9 @@ ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB, if (NewBase == 0) return false; } - int BaseOpc = !isThumb2 - ? ARM::ADDri - : ((Base == ARM::SP) ? ARM::t2ADDrSPi : ARM::t2ADDri); + int BaseOpc = !isThumb2 ? ARM::ADDri : ARM::t2ADDri; if (Offset < 0) { - BaseOpc = !isThumb2 - ? ARM::SUBri - : ((Base == ARM::SP) ? ARM::t2SUBrSPi : ARM::t2SUBri); + BaseOpc = !isThumb2 ? ARM::SUBri : ARM::t2SUBri; Offset = - Offset; } int ImmedOffset = isThumb2 @@ -516,8 +512,6 @@ static inline bool isMatchingDecrement(MachineInstr *MI, unsigned Base, if (!MI) return false; if (MI->getOpcode() != ARM::t2SUBri && - MI->getOpcode() != ARM::t2SUBrSPi && - MI->getOpcode() != ARM::t2SUBrSPi12 && MI->getOpcode() != ARM::tSUBspi && MI->getOpcode() != ARM::SUBri) return false; @@ -541,8 +535,6 @@ static inline bool isMatchingIncrement(MachineInstr *MI, unsigned Base, if (!MI) return false; if (MI->getOpcode() != ARM::t2ADDri && - MI->getOpcode() != ARM::t2ADDrSPi && - MI->getOpcode() != ARM::t2ADDrSPi12 && MI->getOpcode() != ARM::tADDspi && MI->getOpcode() != ARM::ADDri) return false; @@ -1461,19 +1453,19 @@ static bool IsSafeAndProfitableToMove(bool isLd, unsigned Base, while (++I != E) { if (I->isDebugValue() || MemOps.count(&*I)) continue; - const TargetInstrDesc &TID = I->getDesc(); - if (TID.isCall() || TID.isTerminator() || I->hasUnmodeledSideEffects()) + const MCInstrDesc &MCID = I->getDesc(); + if (MCID.isCall() || MCID.isTerminator() || I->hasUnmodeledSideEffects()) return false; - if (isLd && TID.mayStore()) + if (isLd && MCID.mayStore()) return false; if (!isLd) { - if (TID.mayLoad()) + if (MCID.mayLoad()) return false; // It's not safe to move the first 'str' down. // str r1, [r0] // strh r5, [r0] // str r4, [r0, #+4] - if (TID.mayStore()) + if (MCID.mayStore()) return false; } for (unsigned j = 0, NumOps = I->getNumOperands(); j != NumOps; ++j) { @@ -1672,14 +1664,14 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB, Ops.pop_back(); Ops.pop_back(); - const TargetInstrDesc &TID = TII->get(NewOpc); - const TargetRegisterClass *TRC = TID.OpInfo[0].getRegClass(TRI); + const MCInstrDesc &MCID = TII->get(NewOpc); + const TargetRegisterClass *TRC = TII->getRegClass(MCID, 0, TRI); MRI->constrainRegClass(EvenReg, TRC); MRI->constrainRegClass(OddReg, TRC); // Form the pair instruction. if (isLd) { - MachineInstrBuilder MIB = BuildMI(*MBB, InsertPos, dl, TID) + MachineInstrBuilder MIB = BuildMI(*MBB, InsertPos, dl, MCID) .addReg(EvenReg, RegState::Define) .addReg(OddReg, RegState::Define) .addReg(BaseReg); @@ -1691,7 +1683,7 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB, MIB.addImm(Offset).addImm(Pred).addReg(PredReg); ++NumLDRDFormed; } else { - MachineInstrBuilder MIB = BuildMI(*MBB, InsertPos, dl, TID) + MachineInstrBuilder MIB = BuildMI(*MBB, InsertPos, dl, MCID) .addReg(EvenReg) .addReg(OddReg) .addReg(BaseReg); @@ -1742,8 +1734,8 @@ ARMPreAllocLoadStoreOpt::RescheduleLoadStoreInstrs(MachineBasicBlock *MBB) { while (MBBI != E) { for (; MBBI != E; ++MBBI) { MachineInstr *MI = MBBI; - const TargetInstrDesc &TID = MI->getDesc(); - if (TID.isCall() || TID.isTerminator()) { + const MCInstrDesc &MCID = MI->getDesc(); + if (MCID.isCall() || MCID.isTerminator()) { // Stop at barriers. ++MBBI; break; diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp index c5f727d60642..39be3f0e39f8 100644 --- a/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -21,8 +21,11 @@ #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/raw_ostream.h" + using namespace llvm; STATISTIC(MCNumEmitted, "Number of MC instructions emitted."); @@ -32,19 +35,30 @@ namespace { class ARMMCCodeEmitter : public MCCodeEmitter { ARMMCCodeEmitter(const ARMMCCodeEmitter &); // DO NOT IMPLEMENT void operator=(const ARMMCCodeEmitter &); // DO NOT IMPLEMENT - const TargetMachine &TM; - const TargetInstrInfo &TII; - const ARMSubtarget *Subtarget; - MCContext &Ctx; + const MCInstrInfo &MCII; + const MCSubtargetInfo &STI; public: - ARMMCCodeEmitter(TargetMachine &tm, MCContext &ctx) - : TM(tm), TII(*TM.getInstrInfo()), - Subtarget(&TM.getSubtarget<ARMSubtarget>()), Ctx(ctx) { + ARMMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti, + MCContext &ctx) + : MCII(mcii), STI(sti) { } ~ARMMCCodeEmitter() {} + bool isThumb() const { + // FIXME: Can tablegen auto-generate this? + return (STI.getFeatureBits() & ARM::ModeThumb) != 0; + } + bool isThumb2() const { + return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) != 0; + } + bool isTargetDarwin() const { + Triple TT(STI.getTargetTriple()); + Triple::OSType OS = TT.getOS(); + return OS == Triple::Darwin || OS == Triple::MacOSX || OS == Triple::IOS; + } + unsigned getMachineSoImmOpValue(unsigned SoImm) const; // getBinaryCodeForInstr - TableGen'erated function for getting the @@ -320,9 +334,10 @@ public: } // end anonymous namespace -MCCodeEmitter *llvm::createARMMCCodeEmitter(const Target &, TargetMachine &TM, +MCCodeEmitter *llvm::createARMMCCodeEmitter(const MCInstrInfo &MCII, + const MCSubtargetInfo &STI, MCContext &Ctx) { - return new ARMMCCodeEmitter(TM, Ctx); + return new ARMMCCodeEmitter(MCII, STI, Ctx); } /// NEONThumb2DataIPostEncoder - Post-process encoded NEON data-processing @@ -330,7 +345,7 @@ MCCodeEmitter *llvm::createARMMCCodeEmitter(const Target &, TargetMachine &TM, /// Thumb2 mode. unsigned ARMMCCodeEmitter::NEONThumb2DataIPostEncoder(const MCInst &MI, unsigned EncodedValue) const { - if (Subtarget->isThumb2()) { + if (isThumb2()) { // NEON Thumb2 data-processsing encodings are very simple: bit 24 is moved // to bit 12 of the high half-word (i.e. bit 28), and bits 27-24 are // set to 1111. @@ -349,7 +364,7 @@ unsigned ARMMCCodeEmitter::NEONThumb2DataIPostEncoder(const MCInst &MI, /// Thumb2 mode. unsigned ARMMCCodeEmitter::NEONThumb2LoadStorePostEncoder(const MCInst &MI, unsigned EncodedValue) const { - if (Subtarget->isThumb2()) { + if (isThumb2()) { EncodedValue &= 0xF0FFFFFF; EncodedValue |= 0x09000000; } @@ -362,7 +377,7 @@ unsigned ARMMCCodeEmitter::NEONThumb2LoadStorePostEncoder(const MCInst &MI, /// Thumb2 mode. unsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI, unsigned EncodedValue) const { - if (Subtarget->isThumb2()) { + if (isThumb2()) { EncodedValue &= 0x00FFFFFF; EncodedValue |= 0xEE000000; } @@ -374,7 +389,7 @@ unsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI, /// them to their Thumb2 form if we are currently in Thumb2 mode. unsigned ARMMCCodeEmitter:: VFPThumb2PostEncoder(const MCInst &MI, unsigned EncodedValue) const { - if (Subtarget->isThumb2()) { + if (isThumb2()) { EncodedValue &= 0x0FFFFFFF; EncodedValue |= 0xE0000000; } @@ -515,7 +530,7 @@ getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups) const { // FIXME: This really, really shouldn't use TargetMachine. We don't want // coupling between MC and TM anywhere we can help it. - if (Subtarget->isThumb2()) + if (isThumb2()) return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_condbranch, Fixups); return getARMBranchTargetOpValue(MI, OpIdx, Fixups); @@ -624,7 +639,7 @@ getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx, const MCExpr *Expr = MO.getExpr(); MCFixupKind Kind; - if (Subtarget->isThumb2()) + if (isThumb2()) Kind = MCFixupKind(ARM::fixup_t2_ldst_pcrel_12); else Kind = MCFixupKind(ARM::fixup_arm_ldst_pcrel_12); @@ -709,22 +724,22 @@ ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx, switch (ARM16Expr->getKind()) { default: assert(0 && "Unsupported ARMFixup"); case ARMMCExpr::VK_ARM_HI16: - if (!Subtarget->isTargetDarwin() && EvaluateAsPCRel(E)) - Kind = MCFixupKind(Subtarget->isThumb2() + if (!isTargetDarwin() && EvaluateAsPCRel(E)) + Kind = MCFixupKind(isThumb2() ? ARM::fixup_t2_movt_hi16_pcrel : ARM::fixup_arm_movt_hi16_pcrel); else - Kind = MCFixupKind(Subtarget->isThumb2() + Kind = MCFixupKind(isThumb2() ? ARM::fixup_t2_movt_hi16 : ARM::fixup_arm_movt_hi16); break; case ARMMCExpr::VK_ARM_LO16: - if (!Subtarget->isTargetDarwin() && EvaluateAsPCRel(E)) - Kind = MCFixupKind(Subtarget->isThumb2() + if (!isTargetDarwin() && EvaluateAsPCRel(E)) + Kind = MCFixupKind(isThumb2() ? ARM::fixup_t2_movw_lo16_pcrel : ARM::fixup_arm_movw_lo16_pcrel); else - Kind = MCFixupKind(Subtarget->isThumb2() + Kind = MCFixupKind(isThumb2() ? ARM::fixup_t2_movw_lo16 : ARM::fixup_arm_movw_lo16); break; @@ -898,7 +913,7 @@ getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx, assert(MO.isExpr() && "Unexpected machine operand type!"); const MCExpr *Expr = MO.getExpr(); MCFixupKind Kind; - if (Subtarget->isThumb2()) + if (isThumb2()) Kind = MCFixupKind(ARM::fixup_t2_pcrel_10); else Kind = MCFixupKind(ARM::fixup_arm_pcrel_10); @@ -1274,21 +1289,21 @@ void ARMMCCodeEmitter:: EncodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups) const { // Pseudo instructions don't get encoded. - const TargetInstrDesc &Desc = TII.get(MI.getOpcode()); + const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); uint64_t TSFlags = Desc.TSFlags; if ((TSFlags & ARMII::FormMask) == ARMII::Pseudo) return; + int Size; - // Basic size info comes from the TSFlags field. - switch ((TSFlags & ARMII::SizeMask) >> ARMII::SizeShift) { - default: llvm_unreachable("Unexpected instruction size!"); - case ARMII::Size2Bytes: Size = 2; break; - case ARMII::Size4Bytes: Size = 4; break; - } + if (Desc.getSize() == 2 || Desc.getSize() == 4) + Size = Desc.getSize(); + else + llvm_unreachable("Unexpected instruction size!"); + uint32_t Binary = getBinaryCodeForInstr(MI, Fixups); // Thumb 32-bit wide instructions need to emit the high order halfword // first. - if (Subtarget->isThumb() && Size == 4) { + if (isThumb() && Size == 4) { EmitConstant(Binary >> 16, 2, OS); EmitConstant(Binary & 0xffff, 2, OS); } else diff --git a/lib/Target/ARM/ARMMCInstLower.cpp b/lib/Target/ARM/ARMMCInstLower.cpp index 59d60506fc0f..7411b599f0fa 100644 --- a/lib/Target/ARM/ARMMCInstLower.cpp +++ b/lib/Target/ARM/ARMMCInstLower.cpp @@ -23,43 +23,94 @@ using namespace llvm; -static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, - ARMAsmPrinter &Printer) { - MCContext &Ctx = Printer.OutContext; +MCOperand ARMAsmPrinter::GetSymbolRef(const MachineOperand &MO, + const MCSymbol *Symbol) { const MCExpr *Expr; switch (MO.getTargetFlags()) { default: { - Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, Ctx); + Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, + OutContext); switch (MO.getTargetFlags()) { default: assert(0 && "Unknown target flag on symbol operand"); case 0: break; case ARMII::MO_LO16: - Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, Ctx); - Expr = ARMMCExpr::CreateLower16(Expr, Ctx); + Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, + OutContext); + Expr = ARMMCExpr::CreateLower16(Expr, OutContext); break; case ARMII::MO_HI16: - Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, Ctx); - Expr = ARMMCExpr::CreateUpper16(Expr, Ctx); + Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, + OutContext); + Expr = ARMMCExpr::CreateUpper16(Expr, OutContext); break; } break; } case ARMII::MO_PLT: - Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_PLT, Ctx); + Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_PLT, + OutContext); break; } if (!MO.isJTI() && MO.getOffset()) Expr = MCBinaryExpr::CreateAdd(Expr, - MCConstantExpr::Create(MO.getOffset(), Ctx), - Ctx); + MCConstantExpr::Create(MO.getOffset(), + OutContext), + OutContext); return MCOperand::CreateExpr(Expr); } +bool ARMAsmPrinter::lowerOperand(const MachineOperand &MO, + MCOperand &MCOp) { + switch (MO.getType()) { + default: + assert(0 && "unknown operand type"); + return false; + case MachineOperand::MO_Register: + // Ignore all non-CPSR implicit register operands. + if (MO.isImplicit() && MO.getReg() != ARM::CPSR) + return false; + assert(!MO.getSubReg() && "Subregs should be eliminated!"); + MCOp = MCOperand::CreateReg(MO.getReg()); + break; + case MachineOperand::MO_Immediate: + MCOp = MCOperand::CreateImm(MO.getImm()); + break; + case MachineOperand::MO_MachineBasicBlock: + MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create( + MO.getMBB()->getSymbol(), OutContext)); + break; + case MachineOperand::MO_GlobalAddress: + MCOp = GetSymbolRef(MO, Mang->getSymbol(MO.getGlobal())); + break; + case MachineOperand::MO_ExternalSymbol: + MCOp = GetSymbolRef(MO, + GetExternalSymbolSymbol(MO.getSymbolName())); + break; + case MachineOperand::MO_JumpTableIndex: + MCOp = GetSymbolRef(MO, GetJTISymbol(MO.getIndex())); + break; + case MachineOperand::MO_ConstantPoolIndex: + MCOp = GetSymbolRef(MO, GetCPISymbol(MO.getIndex())); + break; + case MachineOperand::MO_BlockAddress: + MCOp = GetSymbolRef(MO, GetBlockAddressSymbol(MO.getBlockAddress())); + break; + case MachineOperand::MO_FPImmediate: { + APFloat Val = MO.getFPImm()->getValueAPF(); + bool ignored; + Val.convert(APFloat::IEEEdouble, APFloat::rmTowardZero, &ignored); + MCOp = MCOperand::CreateFPImm(Val.convertToDouble()); + break; + } + } + return true; +} + void llvm::LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, ARMAsmPrinter &AP) { OutMI.setOpcode(MI->getOpcode()); @@ -68,48 +119,7 @@ void llvm::LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, const MachineOperand &MO = MI->getOperand(i); MCOperand MCOp; - switch (MO.getType()) { - default: - MI->dump(); - assert(0 && "unknown operand type"); - case MachineOperand::MO_Register: - // Ignore all non-CPSR implicit register operands. - if (MO.isImplicit() && MO.getReg() != ARM::CPSR) continue; - assert(!MO.getSubReg() && "Subregs should be eliminated!"); - MCOp = MCOperand::CreateReg(MO.getReg()); - break; - case MachineOperand::MO_Immediate: - MCOp = MCOperand::CreateImm(MO.getImm()); - break; - case MachineOperand::MO_MachineBasicBlock: - MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create( - MO.getMBB()->getSymbol(), AP.OutContext)); - break; - case MachineOperand::MO_GlobalAddress: - MCOp = GetSymbolRef(MO, AP.Mang->getSymbol(MO.getGlobal()), AP); - break; - case MachineOperand::MO_ExternalSymbol: - MCOp = GetSymbolRef(MO, - AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP); - break; - case MachineOperand::MO_JumpTableIndex: - MCOp = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP); - break; - case MachineOperand::MO_ConstantPoolIndex: - MCOp = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP); - break; - case MachineOperand::MO_BlockAddress: - MCOp = GetSymbolRef(MO,AP.GetBlockAddressSymbol(MO.getBlockAddress()),AP); - break; - case MachineOperand::MO_FPImmediate: { - APFloat Val = MO.getFPImm()->getValueAPF(); - bool ignored; - Val.convert(APFloat::IEEEdouble, APFloat::rmTowardZero, &ignored); - MCOp = MCOperand::CreateFPImm(Val.convertToDouble()); - break; - } - } - - OutMI.addOperand(MCOp); + if (AP.lowerOperand(MO, MCOp)) + OutMI.addOperand(MCOp); } } diff --git a/lib/Target/ARM/ARMMachObjectWriter.cpp b/lib/Target/ARM/ARMMachObjectWriter.cpp new file mode 100644 index 000000000000..a36e47da06d4 --- /dev/null +++ b/lib/Target/ARM/ARMMachObjectWriter.cpp @@ -0,0 +1,389 @@ +//===-- ARMMachObjectWriter.cpp - ARM Mach Object Writer ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ARM.h" +#include "ARMFixupKinds.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCMachObjectWriter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCFixupKindInfo.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Object/MachOFormat.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetAsmBackend.h" +using namespace llvm; +using namespace llvm::object; + +namespace { +class ARMMachObjectWriter : public MCMachObjectTargetWriter { + void RecordARMScatteredRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + unsigned Log2Size, + uint64_t &FixedValue); + void RecordARMMovwMovtRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + uint64_t &FixedValue); + +public: + ARMMachObjectWriter(bool Is64Bit, uint32_t CPUType, + uint32_t CPUSubtype) + : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype, + /*UseAggressiveSymbolFolding=*/true) {} + + void RecordRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, uint64_t &FixedValue); +}; +} + +static bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType, + unsigned &Log2Size) { + RelocType = unsigned(macho::RIT_Vanilla); + Log2Size = ~0U; + + switch (Kind) { + default: + return false; + + case FK_Data_1: + Log2Size = llvm::Log2_32(1); + return true; + case FK_Data_2: + Log2Size = llvm::Log2_32(2); + return true; + case FK_Data_4: + Log2Size = llvm::Log2_32(4); + return true; + case FK_Data_8: + Log2Size = llvm::Log2_32(8); + return true; + + // Handle 24-bit branch kinds. + case ARM::fixup_arm_ldst_pcrel_12: + case ARM::fixup_arm_pcrel_10: + case ARM::fixup_arm_adr_pcrel_12: + case ARM::fixup_arm_condbranch: + case ARM::fixup_arm_uncondbranch: + RelocType = unsigned(macho::RIT_ARM_Branch24Bit); + // Report as 'long', even though that is not quite accurate. + Log2Size = llvm::Log2_32(4); + return true; + + // Handle Thumb branches. + case ARM::fixup_arm_thumb_br: + RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit); + Log2Size = llvm::Log2_32(2); + return true; + + case ARM::fixup_t2_uncondbranch: + case ARM::fixup_arm_thumb_bl: + case ARM::fixup_arm_thumb_blx: + RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit); + Log2Size = llvm::Log2_32(4); + return true; + + case ARM::fixup_arm_movt_hi16: + case ARM::fixup_arm_movt_hi16_pcrel: + case ARM::fixup_t2_movt_hi16: + case ARM::fixup_t2_movt_hi16_pcrel: + RelocType = unsigned(macho::RIT_ARM_HalfDifference); + // Report as 'long', even though that is not quite accurate. + Log2Size = llvm::Log2_32(4); + return true; + + case ARM::fixup_arm_movw_lo16: + case ARM::fixup_arm_movw_lo16_pcrel: + case ARM::fixup_t2_movw_lo16: + case ARM::fixup_t2_movw_lo16_pcrel: + RelocType = unsigned(macho::RIT_ARM_Half); + // Report as 'long', even though that is not quite accurate. + Log2Size = llvm::Log2_32(4); + return true; + } +} + +void ARMMachObjectWriter:: +RecordARMMovwMovtRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue) { + uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); + unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned Type = macho::RIT_ARM_Half; + + // See <reloc.h>. + const MCSymbol *A = &Target.getSymA()->getSymbol(); + MCSymbolData *A_SD = &Asm.getSymbolData(*A); + + if (!A_SD->getFragment()) + report_fatal_error("symbol '" + A->getName() + + "' can not be undefined in a subtraction expression"); + + uint32_t Value = Writer->getSymbolAddress(A_SD, Layout); + uint32_t Value2 = 0; + uint64_t SecAddr = + Writer->getSectionAddress(A_SD->getFragment()->getParent()); + FixedValue += SecAddr; + + if (const MCSymbolRefExpr *B = Target.getSymB()) { + MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); + + if (!B_SD->getFragment()) + report_fatal_error("symbol '" + B->getSymbol().getName() + + "' can not be undefined in a subtraction expression"); + + // Select the appropriate difference relocation type. + Type = macho::RIT_ARM_HalfDifference; + Value2 = Writer->getSymbolAddress(B_SD, Layout); + FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent()); + } + + // Relocations are written out in reverse order, so the PAIR comes first. + // ARM_RELOC_HALF and ARM_RELOC_HALF_SECTDIFF abuse the r_length field: + // + // For these two r_type relocations they always have a pair following them and + // the r_length bits are used differently. The encoding of the r_length is as + // follows: + // low bit of r_length: + // 0 - :lower16: for movw instructions + // 1 - :upper16: for movt instructions + // high bit of r_length: + // 0 - arm instructions + // 1 - thumb instructions + // the other half of the relocated expression is in the following pair + // relocation entry in the the low 16 bits of r_address field. + unsigned ThumbBit = 0; + unsigned MovtBit = 0; + switch ((unsigned)Fixup.getKind()) { + default: break; + case ARM::fixup_arm_movt_hi16: + case ARM::fixup_arm_movt_hi16_pcrel: + MovtBit = 1; + break; + case ARM::fixup_t2_movt_hi16: + case ARM::fixup_t2_movt_hi16_pcrel: + MovtBit = 1; + // Fallthrough + case ARM::fixup_t2_movw_lo16: + case ARM::fixup_t2_movw_lo16_pcrel: + ThumbBit = 1; + break; + } + + + if (Type == macho::RIT_ARM_HalfDifference) { + uint32_t OtherHalf = MovtBit + ? (FixedValue & 0xffff) : ((FixedValue & 0xffff0000) >> 16); + + macho::RelocationEntry MRE; + MRE.Word0 = ((OtherHalf << 0) | + (macho::RIT_Pair << 24) | + (MovtBit << 28) | + (ThumbBit << 29) | + (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value2; + Writer->addRelocation(Fragment->getParent(), MRE); + } + + macho::RelocationEntry MRE; + MRE.Word0 = ((FixupOffset << 0) | + (Type << 24) | + (MovtBit << 28) | + (ThumbBit << 29) | + (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value; + Writer->addRelocation(Fragment->getParent(), MRE); +} + +void ARMMachObjectWriter::RecordARMScatteredRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + unsigned Log2Size, + uint64_t &FixedValue) { + uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); + unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned Type = macho::RIT_Vanilla; + + // See <reloc.h>. + const MCSymbol *A = &Target.getSymA()->getSymbol(); + MCSymbolData *A_SD = &Asm.getSymbolData(*A); + + if (!A_SD->getFragment()) + report_fatal_error("symbol '" + A->getName() + + "' can not be undefined in a subtraction expression"); + + uint32_t Value = Writer->getSymbolAddress(A_SD, Layout); + uint64_t SecAddr = Writer->getSectionAddress(A_SD->getFragment()->getParent()); + FixedValue += SecAddr; + uint32_t Value2 = 0; + + if (const MCSymbolRefExpr *B = Target.getSymB()) { + MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); + + if (!B_SD->getFragment()) + report_fatal_error("symbol '" + B->getSymbol().getName() + + "' can not be undefined in a subtraction expression"); + + // Select the appropriate difference relocation type. + Type = macho::RIT_Difference; + Value2 = Writer->getSymbolAddress(B_SD, Layout); + FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent()); + } + + // Relocations are written out in reverse order, so the PAIR comes first. + if (Type == macho::RIT_Difference || + Type == macho::RIT_Generic_LocalDifference) { + macho::RelocationEntry MRE; + MRE.Word0 = ((0 << 0) | + (macho::RIT_Pair << 24) | + (Log2Size << 28) | + (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value2; + Writer->addRelocation(Fragment->getParent(), MRE); + } + + macho::RelocationEntry MRE; + MRE.Word0 = ((FixupOffset << 0) | + (Type << 24) | + (Log2Size << 28) | + (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value; + Writer->addRelocation(Fragment->getParent(), MRE); +} + +void ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue) { + unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned Log2Size; + unsigned RelocType = macho::RIT_Vanilla; + if (!getARMFixupKindMachOInfo(Fixup.getKind(), RelocType, Log2Size)) { + report_fatal_error("unknown ARM fixup kind!"); + return; + } + + // If this is a difference or a defined symbol plus an offset, then we need a + // scattered relocation entry. Differences always require scattered + // relocations. + if (Target.getSymB()) { + if (RelocType == macho::RIT_ARM_Half || + RelocType == macho::RIT_ARM_HalfDifference) + return RecordARMMovwMovtRelocation(Writer, Asm, Layout, Fragment, Fixup, + Target, FixedValue); + return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, + Target, Log2Size, FixedValue); + } + + // Get the symbol data, if any. + MCSymbolData *SD = 0; + if (Target.getSymA()) + SD = &Asm.getSymbolData(Target.getSymA()->getSymbol()); + + // FIXME: For other platforms, we need to use scattered relocations for + // internal relocations with offsets. If this is an internal relocation with + // an offset, it also needs a scattered relocation entry. + // + // Is this right for ARM? + uint32_t Offset = Target.getConstant(); + if (IsPCRel && RelocType == macho::RIT_Vanilla) + Offset += 1 << Log2Size; + if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD)) + return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, + Target, Log2Size, FixedValue); + + // See <reloc.h>. + uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); + unsigned Index = 0; + unsigned IsExtern = 0; + unsigned Type = 0; + + if (Target.isAbsolute()) { // constant + // FIXME! + report_fatal_error("FIXME: relocations to absolute targets " + "not yet implemented"); + } else { + // Resolve constant variables. + if (SD->getSymbol().isVariable()) { + int64_t Res; + if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute( + Res, Layout, Writer->getSectionAddressMap())) { + FixedValue = Res; + return; + } + } + + // Check whether we need an external or internal relocation. + if (Writer->doesSymbolRequireExternRelocation(SD)) { + IsExtern = 1; + Index = SD->getIndex(); + + // For external relocations, make sure to offset the fixup value to + // compensate for the addend of the symbol address, if it was + // undefined. This occurs with weak definitions, for example. + if (!SD->Symbol->isUndefined()) + FixedValue -= Layout.getSymbolOffset(SD); + } else { + // The index is the section ordinal (1-based). + const MCSectionData &SymSD = Asm.getSectionData( + SD->getSymbol().getSection()); + Index = SymSD.getOrdinal() + 1; + FixedValue += Writer->getSectionAddress(&SymSD); + } + if (IsPCRel) + FixedValue -= Writer->getSectionAddress(Fragment->getParent()); + + // The type is determined by the fixup kind. + Type = RelocType; + } + + // struct relocation_info (8 bytes) + macho::RelocationEntry MRE; + MRE.Word0 = FixupOffset; + MRE.Word1 = ((Index << 0) | + (IsPCRel << 24) | + (Log2Size << 25) | + (IsExtern << 27) | + (Type << 28)); + Writer->addRelocation(Fragment->getParent(), MRE); +} + +MCObjectWriter *llvm::createARMMachObjectWriter(raw_ostream &OS, + bool Is64Bit, + uint32_t CPUType, + uint32_t CPUSubtype) { + return createMachObjectWriter(new ARMMachObjectWriter(Is64Bit, + CPUType, + CPUSubtype), + OS, /*IsLittleEndian=*/true); +} diff --git a/lib/Target/ARM/ARMRegisterInfo.td b/lib/Target/ARM/ARMRegisterInfo.td index 99418733c376..76eb496bde42 100644 --- a/lib/Target/ARM/ARMRegisterInfo.td +++ b/lib/Target/ARM/ARMRegisterInfo.td @@ -200,45 +200,16 @@ def FPEXC : ARMReg<8, "fpexc">; // r11 == Frame Pointer (arm-style backtraces) // r10 == Stack Limit // -def GPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6, - R7, R8, R9, R10, R11, R12, - SP, LR, PC]> { - let MethodProtos = [{ - iterator allocation_order_begin(const MachineFunction &MF) const; - iterator allocation_order_end(const MachineFunction &MF) const; - }]; - let MethodBodies = [{ - static const unsigned ARM_GPR_AO[] = { - ARM::R0, ARM::R1, ARM::R2, ARM::R3, - ARM::R12,ARM::LR, - ARM::R4, ARM::R5, ARM::R6, ARM::R7, - ARM::R8, ARM::R9, ARM::R10, ARM::R11 }; - - // For Thumb1 mode, we don't want to allocate hi regs at all, as we - // don't know how to spill them. If we make our prologue/epilogue code - // smarter at some point, we can go back to using the above allocation - // orders for the Thumb1 instructions that know how to use hi regs. - static const unsigned THUMB_GPR_AO[] = { - ARM::R0, ARM::R1, ARM::R2, ARM::R3, - ARM::R4, ARM::R5, ARM::R6, ARM::R7 }; - - GPRClass::iterator - GPRClass::allocation_order_begin(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>(); - if (Subtarget.isThumb1Only()) - return THUMB_GPR_AO; - return ARM_GPR_AO; - } - - GPRClass::iterator - GPRClass::allocation_order_end(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>(); - if (Subtarget.isThumb1Only()) - return THUMB_GPR_AO + (sizeof(THUMB_GPR_AO)/sizeof(unsigned)); - return ARM_GPR_AO + (sizeof(ARM_GPR_AO)/sizeof(unsigned)); - } +def GPR : RegisterClass<"ARM", [i32], 32, (add (sequence "R%u", 0, 12), + SP, LR, PC)> { + // Allocate LR as the first CSR since it is always saved anyway. + // For Thumb1 mode, we don't want to allocate hi regs at all, as we don't + // know how to spill them. If we make our prologue/epilogue code smarter at + // some point, we can go back to using the above allocation orders for the + // Thumb1 instructions that know how to use hi regs. + let AltOrders = [(add LR, GPR), (trunc GPR, 8)]; + let AltOrderSelect = [{ + return 1 + MF.getTarget().getSubtarget<ARMSubtarget>().isThumb1Only(); }]; } @@ -246,263 +217,98 @@ def GPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6, // register range for operands, but have undefined behaviours when PC // or SP (R13 or R15) are used. The ARM ISA refers to these operands // via the BadReg() pseudo-code description. -def rGPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6, - R7, R8, R9, R10, R11, R12, LR]> { - let MethodProtos = [{ - iterator allocation_order_begin(const MachineFunction &MF) const; - iterator allocation_order_end(const MachineFunction &MF) const; - }]; - let MethodBodies = [{ - static const unsigned ARM_rGPR_AO[] = { - ARM::R0, ARM::R1, ARM::R2, ARM::R3, - ARM::R12,ARM::LR, - ARM::R4, ARM::R5, ARM::R6, ARM::R7, - ARM::R8, ARM::R9, ARM::R10, - ARM::R11 }; - - // For Thumb1 mode, we don't want to allocate hi regs at all, as we - // don't know how to spill them. If we make our prologue/epilogue code - // smarter at some point, we can go back to using the above allocation - // orders for the Thumb1 instructions that know how to use hi regs. - static const unsigned THUMB_rGPR_AO[] = { - ARM::R0, ARM::R1, ARM::R2, ARM::R3, - ARM::R4, ARM::R5, ARM::R6, ARM::R7 }; - - rGPRClass::iterator - rGPRClass::allocation_order_begin(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>(); - if (Subtarget.isThumb1Only()) - return THUMB_rGPR_AO; - return ARM_rGPR_AO; - } - - rGPRClass::iterator - rGPRClass::allocation_order_end(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>(); - - if (Subtarget.isThumb1Only()) - return THUMB_rGPR_AO + (sizeof(THUMB_rGPR_AO)/sizeof(unsigned)); - return ARM_rGPR_AO + (sizeof(ARM_rGPR_AO)/sizeof(unsigned)); - } +def rGPR : RegisterClass<"ARM", [i32], 32, (sub GPR, SP, PC)> { + let AltOrders = [(add LR, rGPR), (trunc rGPR, 8)]; + let AltOrderSelect = [{ + return 1 + MF.getTarget().getSubtarget<ARMSubtarget>().isThumb1Only(); }]; } // Thumb registers are R0-R7 normally. Some instructions can still use // the general GPR register class above (MOV, e.g.) -def tGPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6, R7]> {} +def tGPR : RegisterClass<"ARM", [i32], 32, (trunc GPR, 8)>; + +// The high registers in thumb mode, R8-R15. +def hGPR : RegisterClass<"ARM", [i32], 32, (sub GPR, tGPR)>; // For tail calls, we can't use callee-saved registers, as they are restored // to the saved value before the tail call, which would clobber a call address. // Note, getMinimalPhysRegClass(R0) returns tGPR because of the names of // this class and the preceding one(!) This is what we want. -def tcGPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R9, R12]> { - let MethodProtos = [{ - iterator allocation_order_begin(const MachineFunction &MF) const; - iterator allocation_order_end(const MachineFunction &MF) const; - }]; - let MethodBodies = [{ - // R9 is available. - static const unsigned ARM_GPR_R9_TC[] = { - ARM::R0, ARM::R1, ARM::R2, ARM::R3, - ARM::R9, ARM::R12 }; - // R9 is not available. - static const unsigned ARM_GPR_NOR9_TC[] = { - ARM::R0, ARM::R1, ARM::R2, ARM::R3, - ARM::R12 }; - - // For Thumb1 mode, we don't want to allocate hi regs at all, as we - // don't know how to spill them. If we make our prologue/epilogue code - // smarter at some point, we can go back to using the above allocation - // orders for the Thumb1 instructions that know how to use hi regs. - static const unsigned THUMB_GPR_AO_TC[] = { - ARM::R0, ARM::R1, ARM::R2, ARM::R3 }; - - tcGPRClass::iterator - tcGPRClass::allocation_order_begin(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>(); - if (Subtarget.isThumb1Only()) - return THUMB_GPR_AO_TC; - return Subtarget.isTargetDarwin() ? ARM_GPR_R9_TC : ARM_GPR_NOR9_TC; - } - - tcGPRClass::iterator - tcGPRClass::allocation_order_end(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>(); - - if (Subtarget.isThumb1Only()) - return THUMB_GPR_AO_TC + (sizeof(THUMB_GPR_AO_TC)/sizeof(unsigned)); - - return Subtarget.isTargetDarwin() ? - ARM_GPR_R9_TC + (sizeof(ARM_GPR_R9_TC)/sizeof(unsigned)) : - ARM_GPR_NOR9_TC + (sizeof(ARM_GPR_NOR9_TC)/sizeof(unsigned)); - } +def tcGPR : RegisterClass<"ARM", [i32], 32, (add R0, R1, R2, R3, R9, R12)> { + let AltOrders = [(and tcGPR, tGPR)]; + let AltOrderSelect = [{ + return MF.getTarget().getSubtarget<ARMSubtarget>().isThumb1Only(); }]; } - // Scalar single precision floating point register class.. -def SPR : RegisterClass<"ARM", [f32], 32, [S0, S1, S2, S3, S4, S5, S6, S7, S8, - S9, S10, S11, S12, S13, S14, S15, S16, S17, S18, S19, S20, S21, S22, - S23, S24, S25, S26, S27, S28, S29, S30, S31]>; +def SPR : RegisterClass<"ARM", [f32], 32, (sequence "S%u", 0, 31)>; // Subset of SPR which can be used as a source of NEON scalars for 16-bit // operations -def SPR_8 : RegisterClass<"ARM", [f32], 32, - [S0, S1, S2, S3, S4, S5, S6, S7, - S8, S9, S10, S11, S12, S13, S14, S15]>; +def SPR_8 : RegisterClass<"ARM", [f32], 32, (trunc SPR, 16)>; // Scalar double precision floating point / generic 64-bit vector register // class. // ARM requires only word alignment for double. It's more performant if it // is double-word alignment though. def DPR : RegisterClass<"ARM", [f64, v8i8, v4i16, v2i32, v1i64, v2f32], 64, - [D0, D1, D2, D3, D4, D5, D6, D7, - D8, D9, D10, D11, D12, D13, D14, D15, - D16, D17, D18, D19, D20, D21, D22, D23, - D24, D25, D26, D27, D28, D29, D30, D31]> { - let MethodProtos = [{ - iterator allocation_order_begin(const MachineFunction &MF) const; - iterator allocation_order_end(const MachineFunction &MF) const; - }]; - let MethodBodies = [{ - // VFP2 / VFPv3-D16 - static const unsigned ARM_DPR_VFP2[] = { - ARM::D0, ARM::D1, ARM::D2, ARM::D3, - ARM::D4, ARM::D5, ARM::D6, ARM::D7, - ARM::D8, ARM::D9, ARM::D10, ARM::D11, - ARM::D12, ARM::D13, ARM::D14, ARM::D15 }; - // VFP3: D8-D15 are callee saved and should be allocated last. - // Save other low registers for use as DPR_VFP2 and DPR_8 classes. - static const unsigned ARM_DPR_VFP3[] = { - ARM::D16, ARM::D17, ARM::D18, ARM::D19, - ARM::D20, ARM::D21, ARM::D22, ARM::D23, - ARM::D24, ARM::D25, ARM::D26, ARM::D27, - ARM::D28, ARM::D29, ARM::D30, ARM::D31, - ARM::D0, ARM::D1, ARM::D2, ARM::D3, - ARM::D4, ARM::D5, ARM::D6, ARM::D7, - ARM::D8, ARM::D9, ARM::D10, ARM::D11, - ARM::D12, ARM::D13, ARM::D14, ARM::D15 }; - - DPRClass::iterator - DPRClass::allocation_order_begin(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>(); - if (Subtarget.hasVFP3() && !Subtarget.hasD16()) - return ARM_DPR_VFP3; - return ARM_DPR_VFP2; - } - - DPRClass::iterator - DPRClass::allocation_order_end(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>(); - if (Subtarget.hasVFP3() && !Subtarget.hasD16()) - return ARM_DPR_VFP3 + (sizeof(ARM_DPR_VFP3)/sizeof(unsigned)); - else - return ARM_DPR_VFP2 + (sizeof(ARM_DPR_VFP2)/sizeof(unsigned)); - } - }]; + (sequence "D%u", 0, 31)> { + // Allocate non-VFP2 registers D16-D31 first. + let AltOrders = [(rotl DPR, 16)]; + let AltOrderSelect = [{ return 1; }]; } // Subset of DPR that are accessible with VFP2 (and so that also have // 32-bit SPR subregs). def DPR_VFP2 : RegisterClass<"ARM", [f64, v8i8, v4i16, v2i32, v1i64, v2f32], 64, - [D0, D1, D2, D3, D4, D5, D6, D7, - D8, D9, D10, D11, D12, D13, D14, D15]> { + (trunc DPR, 16)> { let SubRegClasses = [(SPR ssub_0, ssub_1)]; } // Subset of DPR which can be used as a source of NEON scalars for 16-bit // operations def DPR_8 : RegisterClass<"ARM", [f64, v8i8, v4i16, v2i32, v1i64, v2f32], 64, - [D0, D1, D2, D3, D4, D5, D6, D7]> { + (trunc DPR, 8)> { let SubRegClasses = [(SPR_8 ssub_0, ssub_1)]; } // Generic 128-bit vector register class. def QPR : RegisterClass<"ARM", [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], 128, - [Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, - Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15]> { + (sequence "Q%u", 0, 15)> { let SubRegClasses = [(DPR dsub_0, dsub_1)]; - let MethodProtos = [{ - iterator allocation_order_begin(const MachineFunction &MF) const; - iterator allocation_order_end(const MachineFunction &MF) const; - }]; - let MethodBodies = [{ - // Q4-Q7 are callee saved and should be allocated last. - // Save other low registers for use as QPR_VFP2 and QPR_8 classes. - static const unsigned ARM_QPR[] = { - ARM::Q8, ARM::Q9, ARM::Q10, ARM::Q11, - ARM::Q12, ARM::Q13, ARM::Q14, ARM::Q15, - ARM::Q0, ARM::Q1, ARM::Q2, ARM::Q3, - ARM::Q4, ARM::Q5, ARM::Q6, ARM::Q7 }; - - QPRClass::iterator - QPRClass::allocation_order_begin(const MachineFunction &MF) const { - return ARM_QPR; - } - - QPRClass::iterator - QPRClass::allocation_order_end(const MachineFunction &MF) const { - return ARM_QPR + (sizeof(ARM_QPR)/sizeof(unsigned)); - } - }]; + // Allocate non-VFP2 aliases Q8-Q15 first. + let AltOrders = [(rotl QPR, 8)]; + let AltOrderSelect = [{ return 1; }]; } // Subset of QPR that have 32-bit SPR subregs. def QPR_VFP2 : RegisterClass<"ARM", [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], - 128, - [Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7]> { + 128, (trunc QPR, 8)> { let SubRegClasses = [(SPR ssub_0, ssub_1, ssub_2, ssub_3), (DPR_VFP2 dsub_0, dsub_1)]; } // Subset of QPR that have DPR_8 and SPR_8 subregs. def QPR_8 : RegisterClass<"ARM", [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], - 128, - [Q0, Q1, Q2, Q3]> { + 128, (trunc QPR, 4)> { let SubRegClasses = [(SPR_8 ssub_0, ssub_1, ssub_2, ssub_3), (DPR_8 dsub_0, dsub_1)]; } // Pseudo 256-bit vector register class to model pairs of Q registers // (4 consecutive D registers). -def QQPR : RegisterClass<"ARM", [v4i64], - 256, - [QQ0, QQ1, QQ2, QQ3, QQ4, QQ5, QQ6, QQ7]> { +def QQPR : RegisterClass<"ARM", [v4i64], 256, (sequence "QQ%u", 0, 7)> { let SubRegClasses = [(DPR dsub_0, dsub_1, dsub_2, dsub_3), (QPR qsub_0, qsub_1)]; - let MethodProtos = [{ - iterator allocation_order_begin(const MachineFunction &MF) const; - iterator allocation_order_end(const MachineFunction &MF) const; - }]; - let MethodBodies = [{ - // QQ2-QQ3 are callee saved and should be allocated last. - // Save other low registers for use as QPR_VFP2 and QPR_8 classes. - static const unsigned ARM_QQPR[] = { - ARM::QQ4, ARM::QQ5, ARM::QQ6, ARM::QQ7, - ARM::QQ0, ARM::QQ1, ARM::QQ2, ARM::QQ3 }; - - QQPRClass::iterator - QQPRClass::allocation_order_begin(const MachineFunction &MF) const { - return ARM_QQPR; - } - - QQPRClass::iterator - QQPRClass::allocation_order_end(const MachineFunction &MF) const { - return ARM_QQPR + (sizeof(ARM_QQPR)/sizeof(unsigned)); - } - }]; + // Allocate non-VFP2 aliases first. + let AltOrders = [(rotl QQPR, 4)]; + let AltOrderSelect = [{ return 1; }]; } // Subset of QQPR that have 32-bit SPR subregs. -def QQPR_VFP2 : RegisterClass<"ARM", [v4i64], - 256, - [QQ0, QQ1, QQ2, QQ3]> { +def QQPR_VFP2 : RegisterClass<"ARM", [v4i64], 256, (trunc QQPR, 4)> { let SubRegClasses = [(SPR ssub_0, ssub_1, ssub_2, ssub_3), (DPR_VFP2 dsub_0, dsub_1, dsub_2, dsub_3), (QPR_VFP2 qsub_0, qsub_1)]; @@ -511,35 +317,16 @@ def QQPR_VFP2 : RegisterClass<"ARM", [v4i64], // Pseudo 512-bit vector register class to model 4 consecutive Q registers // (8 consecutive D registers). -def QQQQPR : RegisterClass<"ARM", [v8i64], - 256, - [QQQQ0, QQQQ1, QQQQ2, QQQQ3]> { +def QQQQPR : RegisterClass<"ARM", [v8i64], 256, (sequence "QQQQ%u", 0, 3)> { let SubRegClasses = [(DPR dsub_0, dsub_1, dsub_2, dsub_3, dsub_4, dsub_5, dsub_6, dsub_7), (QPR qsub_0, qsub_1, qsub_2, qsub_3)]; - let MethodProtos = [{ - iterator allocation_order_begin(const MachineFunction &MF) const; - iterator allocation_order_end(const MachineFunction &MF) const; - }]; - let MethodBodies = [{ - // QQQQ1 is callee saved and should be allocated last. - // Save QQQQ0 for use as QPR_VFP2 and QPR_8 classes. - static const unsigned ARM_QQQQPR[] = { - ARM::QQQQ2, ARM::QQQQ3, ARM::QQQQ0, ARM::QQQQ1 }; - - QQQQPRClass::iterator - QQQQPRClass::allocation_order_begin(const MachineFunction &MF) const { - return ARM_QQQQPR; - } - - QQQQPRClass::iterator - QQQQPRClass::allocation_order_end(const MachineFunction &MF) const { - return ARM_QQQQPR + (sizeof(ARM_QQQQPR)/sizeof(unsigned)); - } - }]; + // Allocate non-VFP2 aliases first. + let AltOrders = [(rotl QQQQPR, 2)]; + let AltOrderSelect = [{ return 1; }]; } // Condition code registers. -def CCR : RegisterClass<"ARM", [i32], 32, [CPSR]> { +def CCR : RegisterClass<"ARM", [i32], 32, (add CPSR)> { let isAllocatable = 0; } diff --git a/lib/Target/ARM/ARMSubtarget.cpp b/lib/Target/ARM/ARMSubtarget.cpp index c6f266b07531..1cab9e44ce75 100644 --- a/lib/Target/ARM/ARMSubtarget.cpp +++ b/lib/Target/ARM/ARMSubtarget.cpp @@ -7,17 +7,21 @@ // //===----------------------------------------------------------------------===// // -// This file implements the ARM specific subclass of TargetSubtarget. +// This file implements the ARM specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #include "ARMSubtarget.h" -#include "ARMGenSubtarget.inc" #include "ARMBaseRegisterInfo.h" #include "llvm/GlobalValue.h" -#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetSubtargetInfo.h" #include "llvm/Support/CommandLine.h" #include "llvm/ADT/SmallVector.h" + +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "ARMGenSubtargetInfo.inc" + using namespace llvm; static cl::opt<bool> @@ -31,17 +35,25 @@ static cl::opt<bool> StrictAlign("arm-strict-align", cl::Hidden, cl::desc("Disallow all unaligned memory accesses")); -ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS, - bool isT) - : ARMArchVersion(V4) +ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS) + : ARMGenSubtargetInfo(TT, CPU, FS) , ARMProcFamily(Others) - , ARMFPUType(None) + , HasV4TOps(false) + , HasV5TOps(false) + , HasV5TEOps(false) + , HasV6Ops(false) + , HasV6T2Ops(false) + , HasV7Ops(false) + , HasVFPv2(false) + , HasVFPv3(false) + , HasNEON(false) , UseNEONForSinglePrecisionFP(false) , SlowFPVMLx(false) , HasVMLxForwarding(false) , SlowFPBrcc(false) - , IsThumb(isT) - , ThumbMode(Thumb1) + , InThumbMode(false) + , HasThumb2(false) , NoARM(false) , PostRAScheduler(false) , IsR9Reserved(ReserveR9) @@ -56,94 +68,40 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS, , HasMPExtension(false) , FPOnlySP(false) , AllowsUnalignedMem(false) + , Thumb2DSP(false) , stackAlignment(4) - , CPUString("generic") + , CPUString(CPU) , TargetTriple(TT) , TargetABI(ARM_ABI_APCS) { - // Default to soft float ABI - if (FloatABIType == FloatABI::Default) - FloatABIType = FloatABI::Soft; - // Determine default and user specified characteristics - - // When no arch is specified either by CPU or by attributes, make the default - // ARMv4T. - const char *ARMArchFeature = ""; - if (CPUString == "generic" && (FS.empty() || FS == "generic")) { - ARMArchVersion = V4T; - ARMArchFeature = ",+v4t"; + if (CPUString.empty()) + CPUString = "generic"; + + // Insert the architecture feature derived from the target triple into the + // feature string. This is important for setting features that are implied + // based on the architecture version. + std::string ArchFS = ARM_MC::ParseARMTriple(TT); + if (!FS.empty()) { + if (!ArchFS.empty()) + ArchFS = ArchFS + "," + FS; + else + ArchFS = FS; } + ParseSubtargetFeatures(CPUString, ArchFS); - // Set the boolean corresponding to the current target triple, or the default - // if one cannot be determined, to true. - unsigned Len = TT.length(); - unsigned Idx = 0; + // Thumb2 implies at least V6T2. FIXME: Fix tests to explicitly specify a + // ARM version or CPU and then remove this. + if (!HasV6T2Ops && hasThumb2()) + HasV4TOps = HasV5TOps = HasV5TEOps = HasV6Ops = HasV6T2Ops = true; - if (Len >= 5 && TT.substr(0, 4) == "armv") - Idx = 4; - else if (Len >= 6 && TT.substr(0, 5) == "thumb") { - IsThumb = true; - if (Len >= 7 && TT[5] == 'v') - Idx = 6; - } - if (Idx) { - unsigned SubVer = TT[Idx]; - if (SubVer >= '7' && SubVer <= '9') { - ARMArchVersion = V7A; - ARMArchFeature = ",+v7a"; - if (Len >= Idx+2 && TT[Idx+1] == 'm') { - ARMArchVersion = V7M; - ARMArchFeature = ",+v7m"; - } - } else if (SubVer == '6') { - ARMArchVersion = V6; - ARMArchFeature = ",+v6"; - if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2') { - ARMArchVersion = V6T2; - ARMArchFeature = ",+v6t2"; - } - } else if (SubVer == '5') { - ARMArchVersion = V5T; - ARMArchFeature = ",+v5t"; - if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e') { - ARMArchVersion = V5TE; - ARMArchFeature = ",+v5te"; - } - } else if (SubVer == '4') { - if (Len >= Idx+2 && TT[Idx+1] == 't') { - ARMArchVersion = V4T; - ARMArchFeature = ",+v4t"; - } else { - ARMArchVersion = V4; - ARMArchFeature = ""; - } - } - } - - if (TT.find("eabi") != std::string::npos) - TargetABI = ARM_ABI_AAPCS; - - // Parse features string. If the first entry in FS (the CPU) is missing, - // insert the architecture feature derived from the target triple. This is - // important for setting features that are implied based on the architecture - // version. - std::string FSWithArch; - if (FS.empty()) - FSWithArch = std::string(ARMArchFeature); - else if (FS.find(',') == 0) - FSWithArch = std::string(ARMArchFeature) + FS; - else - FSWithArch = FS; - CPUString = ParseSubtargetFeatures(FSWithArch, CPUString); + // Initialize scheduling itinerary for the specified CPU. + InstrItins = getInstrItineraryForCPU(CPUString); // After parsing Itineraries, set ItinData.IssueWidth. computeIssueWidth(); - // Thumb2 implies at least V6T2. - if (ARMArchVersion >= V6T2) - ThumbMode = Thumb2; - else if (ThumbMode >= Thumb2) - ARMArchVersion = V6T2; + if (TT.find("eabi") != std::string::npos) + TargetABI = ARM_ABI_AAPCS; if (isAAPCS_ABI()) stackAlignment = 8; @@ -151,7 +109,7 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS, if (!isTargetDarwin()) UseMovt = hasV6T2Ops(); else { - IsR9Reserved = ReserveR9 | (ARMArchVersion < V6); + IsR9Reserved = ReserveR9 | !HasV6Ops; UseMovt = DarwinUseMOVT && hasV6T2Ops(); } @@ -247,9 +205,9 @@ void ARMSubtarget::computeIssueWidth() { bool ARMSubtarget::enablePostRAScheduler( CodeGenOpt::Level OptLevel, - TargetSubtarget::AntiDepBreakMode& Mode, + TargetSubtargetInfo::AntiDepBreakMode& Mode, RegClassVector& CriticalPathRCs) const { - Mode = TargetSubtarget::ANTIDEP_CRITICAL; + Mode = TargetSubtargetInfo::ANTIDEP_CRITICAL; CriticalPathRCs.clear(); CriticalPathRCs.push_back(&ARM::GPRRegClass); return PostRAScheduler && OptLevel >= CodeGenOpt::Default; diff --git a/lib/Target/ARM/ARMSubtarget.h b/lib/Target/ARM/ARMSubtarget.h index 0271c873f191..c6508723a576 100644 --- a/lib/Target/ARM/ARMSubtarget.h +++ b/lib/Target/ARM/ARMSubtarget.h @@ -7,50 +7,49 @@ // //===----------------------------------------------------------------------===// // -// This file declares the ARM specific subclass of TargetSubtarget. +// This file declares the ARM specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #ifndef ARMSUBTARGET_H #define ARMSUBTARGET_H -#include "llvm/Target/TargetInstrItineraries.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetSubtarget.h" +#include "MCTargetDesc/ARMMCTargetDesc.h" +#include "llvm/Target/TargetSubtargetInfo.h" +#include "llvm/MC/MCInstrItineraries.h" #include "llvm/ADT/Triple.h" #include <string> +#define GET_SUBTARGETINFO_HEADER +#include "ARMGenSubtargetInfo.inc" + namespace llvm { class GlobalValue; +class StringRef; -class ARMSubtarget : public TargetSubtarget { +class ARMSubtarget : public ARMGenSubtargetInfo { protected: - enum ARMArchEnum { - V4, V4T, V5T, V5TE, V6, V6M, V6T2, V7A, V7M - }; - enum ARMProcFamilyEnum { Others, CortexA8, CortexA9 }; - enum ARMFPEnum { - None, VFPv2, VFPv3, NEON - }; - - enum ThumbTypeEnum { - Thumb1, - Thumb2 - }; - - /// ARMArchVersion - ARM architecture version: V4, V4T (base), V5T, V5TE, - /// V6, V6T2, V7A, V7M. - ARMArchEnum ARMArchVersion; - /// ARMProcFamily - ARM processor family: Cortex-A8, Cortex-A9, and others. ARMProcFamilyEnum ARMProcFamily; - /// ARMFPUType - Floating Point Unit type. - ARMFPEnum ARMFPUType; + /// HasV4TOps, HasV5TOps, HasV5TEOps, HasV6Ops, HasV6T2Ops, HasV7Ops - + /// Specify whether target support specific ARM ISA variants. + bool HasV4TOps; + bool HasV5TOps; + bool HasV5TEOps; + bool HasV6Ops; + bool HasV6T2Ops; + bool HasV7Ops; + + /// HasVFPv2, HasVFPv3, HasNEON - Specify what floating point ISAs are + /// supported. + bool HasVFPv2; + bool HasVFPv3; + bool HasNEON; /// UseNEONForSinglePrecisionFP - if the NEONFP attribute has been /// specified. Use the method useNEONForSinglePrecisionFP() to @@ -68,11 +67,11 @@ protected: /// SlowFPBrcc - True if floating point compare + branch is slow. bool SlowFPBrcc; - /// IsThumb - True if we are in thumb mode, false if in ARM mode. - bool IsThumb; + /// InThumbMode - True if compiling for Thumb, false for ARM. + bool InThumbMode; - /// ThumbMode - Indicates supported Thumb version. - ThumbTypeEnum ThumbMode; + /// HasThumb2 - True if Thumb2 instructions are supported. + bool HasThumb2; /// NoARM - True if subtarget does not support ARM mode execution. bool NoARM; @@ -128,6 +127,10 @@ protected: /// ARMTargetLowering::allowsUnalignedMemoryAccesses(). bool AllowsUnalignedMem; + /// Thumb2DSP - If true, the subtarget supports the v7 DSP (saturating arith + /// and such) instructions in Thumb2 code. + bool Thumb2DSP; + /// stackAlignment - The minimum alignment known to hold of the stack frame on /// entry to the function and which must be maintained by every function. unsigned stackAlignment; @@ -154,7 +157,8 @@ protected: /// This constructor initializes the data members to match that /// of the specified triple. /// - ARMSubtarget(const std::string &TT, const std::string &FS, bool isThumb); + ARMSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS); /// getMaxInlineSizeThreshold - Returns the maximum memset / memcpy size /// that still makes it profitable to inline the call. @@ -165,28 +169,28 @@ protected: } /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(StringRef CPU, StringRef FS); void computeIssueWidth(); - bool hasV4TOps() const { return ARMArchVersion >= V4T; } - bool hasV5TOps() const { return ARMArchVersion >= V5T; } - bool hasV5TEOps() const { return ARMArchVersion >= V5TE; } - bool hasV6Ops() const { return ARMArchVersion >= V6; } - bool hasV6T2Ops() const { return ARMArchVersion >= V6T2; } - bool hasV7Ops() const { return ARMArchVersion >= V7A; } + bool hasV4TOps() const { return HasV4TOps; } + bool hasV5TOps() const { return HasV5TOps; } + bool hasV5TEOps() const { return HasV5TEOps; } + bool hasV6Ops() const { return HasV6Ops; } + bool hasV6T2Ops() const { return HasV6T2Ops; } + bool hasV7Ops() const { return HasV7Ops; } bool isCortexA8() const { return ARMProcFamily == CortexA8; } bool isCortexA9() const { return ARMProcFamily == CortexA9; } bool hasARMOps() const { return !NoARM; } - bool hasVFP2() const { return ARMFPUType >= VFPv2; } - bool hasVFP3() const { return ARMFPUType >= VFPv3; } - bool hasNEON() const { return ARMFPUType >= NEON; } + bool hasVFP2() const { return HasVFPv2; } + bool hasVFP3() const { return HasVFPv3; } + bool hasNEON() const { return HasNEON; } bool useNEONForSinglePrecisionFP() const { return hasNEON() && UseNEONForSinglePrecisionFP; } + bool hasDivide() const { return HasHardwareDivide; } bool hasT2ExtractPack() const { return HasT2ExtractPack; } bool hasDataBarrier() const { return HasDataBarrier; } @@ -197,6 +201,7 @@ protected: bool prefers32BitThumb() const { return Pref32BitThumb; } bool avoidCPSRPartialUpdate() const { return AvoidCPSRPartialUpdate; } bool hasMPExtension() const { return HasMPExtension; } + bool hasThumb2DSP() const { return Thumb2DSP; } bool hasFP16() const { return HasFP16; } bool hasD16() const { return HasD16; } @@ -209,10 +214,10 @@ protected: bool isAPCS_ABI() const { return TargetABI == ARM_ABI_APCS; } bool isAAPCS_ABI() const { return TargetABI == ARM_ABI_AAPCS; } - bool isThumb() const { return IsThumb; } - bool isThumb1Only() const { return IsThumb && (ThumbMode == Thumb1); } - bool isThumb2() const { return IsThumb && (ThumbMode == Thumb2); } - bool hasThumb2() const { return ThumbMode >= Thumb2; } + bool isThumb() const { return InThumbMode; } + bool isThumb1Only() const { return InThumbMode && !HasThumb2; } + bool isThumb2() const { return InThumbMode && HasThumb2; } + bool hasThumb2() const { return HasThumb2; } bool isR9Reserved() const { return IsR9Reserved; } @@ -226,7 +231,7 @@ protected: /// enablePostRAScheduler - True at 'More' optimization. bool enablePostRAScheduler(CodeGenOpt::Level OptLevel, - TargetSubtarget::AntiDepBreakMode& Mode, + TargetSubtargetInfo::AntiDepBreakMode& Mode, RegClassVector& CriticalPathRCs) const; /// getInstrItins - Return the instruction itineraies based on subtarget diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp index 29aa4f7ad2ce..f0b176ad6981 100644 --- a/lib/Target/ARM/ARMTargetMachine.cpp +++ b/lib/Target/ARM/ARMTargetMachine.cpp @@ -11,7 +11,6 @@ //===----------------------------------------------------------------------===// #include "ARMTargetMachine.h" -#include "ARMMCAsmInfo.h" #include "ARMFrameLowering.h" #include "ARM.h" #include "llvm/PassManager.h" @@ -22,15 +21,6 @@ #include "llvm/Target/TargetRegistry.h" using namespace llvm; -static MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) { - Triple TheTriple(TT); - - if (TheTriple.isOSDarwin()) - return new ARMMCAsmInfoDarwin(); - - return new ARMELFMCAsmInfo(); -} - // This is duplicated code. Refactor this. static MCStreamer *createMCStreamer(const Target &T, const std::string &TT, MCContext &Ctx, TargetAsmBackend &TAB, @@ -56,10 +46,6 @@ extern "C" void LLVMInitializeARMTarget() { RegisterTargetMachine<ARMTargetMachine> X(TheARMTarget); RegisterTargetMachine<ThumbTargetMachine> Y(TheThumbTarget); - // Register the target asm info. - RegisterAsmInfoFn A(TheARMTarget, createMCAsmInfo); - RegisterAsmInfoFn B(TheThumbTarget, createMCAsmInfo); - // Register the MC Code Emitter TargetRegistry::RegisterCodeEmitter(TheARMTarget, createARMMCCodeEmitter); TargetRegistry::RegisterCodeEmitter(TheThumbTarget, createARMMCCodeEmitter); @@ -78,18 +64,23 @@ extern "C" void LLVMInitializeARMTarget() { /// ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, const std::string &TT, - const std::string &FS, - bool isThumb) - : LLVMTargetMachine(T, TT), - Subtarget(TT, FS, isThumb), + const std::string &CPU, + const std::string &FS) + : LLVMTargetMachine(T, TT, CPU, FS), + Subtarget(TT, CPU, FS), JITInfo(), InstrItins(Subtarget.getInstrItineraryData()) { DefRelocModel = getRelocationModel(); + + // Default to soft float ABI + if (FloatABIType == FloatABI::Default) + FloatABIType = FloatABI::Soft; } ARMTargetMachine::ARMTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) - : ARMBaseTargetMachine(T, TT, FS, false), InstrInfo(Subtarget), + : ARMBaseTargetMachine(T, TT, CPU, FS), InstrInfo(Subtarget), DataLayout(Subtarget.isAPCS_ABI() ? std::string("e-p:32:32-f64:32:64-i64:32:64-" "v128:32:128-v64:32:64-n32") : @@ -105,8 +96,9 @@ ARMTargetMachine::ARMTargetMachine(const Target &T, const std::string &TT, } ThumbTargetMachine::ThumbTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) - : ARMBaseTargetMachine(T, TT, FS, true), + : ARMBaseTargetMachine(T, TT, CPU, FS), InstrInfo(Subtarget.hasThumb2() ? ((ARMBaseInstrInfo*)new Thumb2InstrInfo(Subtarget)) : ((ARMBaseInstrInfo*)new Thumb1InstrInfo(Subtarget))), diff --git a/lib/Target/ARM/ARMTargetMachine.h b/lib/Target/ARM/ARMTargetMachine.h index e0aa149c4cc2..bc3d46a50ea5 100644 --- a/lib/Target/ARM/ARMTargetMachine.h +++ b/lib/Target/ARM/ARMTargetMachine.h @@ -41,7 +41,7 @@ private: public: ARMBaseTargetMachine(const Target &T, const std::string &TT, - const std::string &FS, bool isThumb); + const std::string &CPU, const std::string &FS); virtual ARMJITInfo *getJITInfo() { return &JITInfo; } virtual const ARMSubtarget *getSubtargetImpl() const { return &Subtarget; } @@ -70,7 +70,7 @@ class ARMTargetMachine : public ARMBaseTargetMachine { ARMFrameLowering FrameLowering; public: ARMTargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); virtual const ARMRegisterInfo *getRegisterInfo() const { return &InstrInfo.getRegisterInfo(); @@ -109,7 +109,7 @@ class ThumbTargetMachine : public ARMBaseTargetMachine { OwningPtr<ARMFrameLowering> FrameLowering; public: ThumbTargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); /// returns either Thumb1RegisterInfo or Thumb2RegisterInfo virtual const ARMBaseRegisterInfo *getRegisterInfo() const { diff --git a/lib/Target/ARM/AsmParser/ARMAsmLexer.cpp b/lib/Target/ARM/AsmParser/ARMAsmLexer.cpp index 2428ce16d3d5..d9a5fa223b4b 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmLexer.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmLexer.cpp @@ -87,8 +87,9 @@ public: : ARMBaseAsmLexer(T, MAI) { std::string tripleString("arm-unknown-unknown"); std::string featureString; + std::string CPU; OwningPtr<const TargetMachine> - targetMachine(T.createTargetMachine(tripleString, featureString)); + targetMachine(T.createTargetMachine(tripleString, CPU, featureString)); InitRegisterMap(targetMachine->getRegisterInfo()); } }; @@ -99,8 +100,9 @@ public: : ARMBaseAsmLexer(T, MAI) { std::string tripleString("thumb-unknown-unknown"); std::string featureString; + std::string CPU; OwningPtr<const TargetMachine> - targetMachine(T.createTargetMachine(tripleString, featureString)); + targetMachine(T.createTargetMachine(tripleString, CPU, featureString)); InitRegisterMap(targetMachine->getRegisterInfo()); } }; diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 4bc12c9c2b49..a4741270c7a5 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -20,14 +20,17 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Target/TargetAsmParser.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" + using namespace llvm; namespace { @@ -35,8 +38,8 @@ namespace { class ARMOperand; class ARMAsmParser : public TargetAsmParser { + MCSubtargetInfo &STI; MCAsmParser &Parser; - TargetMachine &TM; MCAsmParser &getParser() const { return Parser; } MCAsmLexer &getLexer() const { return Parser.getLexer(); } @@ -47,7 +50,7 @@ class ARMAsmParser : public TargetAsmParser { int TryParseRegister(); virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); bool TryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &); - bool TryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &); + int TryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &); bool ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &); bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &, ARMII::AddrMode AddrMode); @@ -79,6 +82,18 @@ class ARMAsmParser : public TargetAsmParser { void GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, bool &CanAcceptPredicationCode); + bool isThumb() const { + // FIXME: Can tablegen auto-generate this? + return (STI.getFeatureBits() & ARM::ModeThumb) != 0; + } + bool isThumbOne() const { + return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0; + } + void SwitchMode() { + unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb)); + setAvailableFeatures(FB); + } + /// @name Auto-generated Match Functions /// { @@ -113,13 +128,13 @@ class ARMAsmParser : public TargetAsmParser { const SmallVectorImpl<MCParsedAsmOperand*> &); public: - ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM) - : TargetAsmParser(T), Parser(_Parser), TM(_TM) { - MCAsmParserExtension::Initialize(_Parser); - // Initialize the set of available features. - setAvailableFeatures(ComputeAvailableFeatures( - &TM.getSubtarget<ARMSubtarget>())); - } + ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser) + : TargetAsmParser(), STI(_STI), Parser(_Parser) { + MCAsmParserExtension::Initialize(_Parser); + + // Initialize the set of available features. + setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); + } virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc, SmallVectorImpl<MCParsedAsmOperand*> &Operands); @@ -146,6 +161,7 @@ class ARMOperand : public MCParsedAsmOperand { RegisterList, DPRRegisterList, SPRRegisterList, + ShiftedRegister, Shifter, Token } Kind; @@ -207,8 +223,14 @@ class ARMOperand : public MCParsedAsmOperand { struct { ARM_AM::ShiftOpc ShiftTy; - unsigned RegNum; + unsigned Imm; } Shift; + struct { + ARM_AM::ShiftOpc ShiftTy; + unsigned SrcReg; + unsigned ShiftReg; + unsigned ShiftImm; + } ShiftedReg; }; ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} @@ -255,6 +277,9 @@ public: case Shifter: Shift = o.Shift; break; + case ShiftedRegister: + ShiftedReg = o.ShiftedReg; + break; } } @@ -350,6 +375,46 @@ public: bool isCondCode() const { return Kind == CondCode; } bool isCCOut() const { return Kind == CCOut; } bool isImm() const { return Kind == Immediate; } + bool isImm0_255() const { + if (Kind != Immediate) + return false; + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); + if (!CE) return false; + int64_t Value = CE->getValue(); + return Value >= 0 && Value < 256; + } + bool isImm0_7() const { + if (Kind != Immediate) + return false; + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); + if (!CE) return false; + int64_t Value = CE->getValue(); + return Value >= 0 && Value < 8; + } + bool isImm0_15() const { + if (Kind != Immediate) + return false; + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); + if (!CE) return false; + int64_t Value = CE->getValue(); + return Value >= 0 && Value < 16; + } + bool isImm0_65535() const { + if (Kind != Immediate) + return false; + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); + if (!CE) return false; + int64_t Value = CE->getValue(); + return Value >= 0 && Value < 65536; + } + bool isT2SOImm() const { + if (Kind != Immediate) + return false; + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); + if (!CE) return false; + int64_t Value = CE->getValue(); + return ARM_AM::getT2SOImmVal(Value) != -1; + } bool isReg() const { return Kind == Register; } bool isRegList() const { return Kind == RegisterList; } bool isDPRRegList() const { return Kind == DPRRegisterList; } @@ -358,6 +423,7 @@ public: bool isMemBarrierOpt() const { return Kind == MemBarrierOpt; } bool isMemory() const { return Kind == Memory; } bool isShifter() const { return Kind == Shifter; } + bool isShiftedReg() const { return Kind == ShiftedRegister; } bool isMemMode2() const { if (getMemAddrMode() != ARMII::AddrMode2) return false; @@ -488,6 +554,18 @@ public: Inst.addOperand(MCOperand::CreateReg(getReg())); } + void addShiftedRegOperands(MCInst &Inst, unsigned N) const { + assert(N == 3 && "Invalid number of operands!"); + assert(isShiftedReg() && "addShiftedRegOperands() on non ShiftedReg!"); + assert((ShiftedReg.ShiftReg == 0 || + ARM_AM::getSORegOffset(ShiftedReg.ShiftImm) == 0) && + "Invalid shifted register operand!"); + Inst.addOperand(MCOperand::CreateReg(ShiftedReg.SrcReg)); + Inst.addOperand(MCOperand::CreateReg(ShiftedReg.ShiftReg)); + Inst.addOperand(MCOperand::CreateImm( + ARM_AM::getSORegOpc(ShiftedReg.ShiftTy, ShiftedReg.ShiftImm))); + } + void addShifterOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateImm( @@ -515,6 +593,31 @@ public: addExpr(Inst, getImm()); } + void addImm0_255Operands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + addExpr(Inst, getImm()); + } + + void addImm0_7Operands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + addExpr(Inst, getImm()); + } + + void addImm0_15Operands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + addExpr(Inst, getImm()); + } + + void addImm0_65535Operands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + addExpr(Inst, getImm()); + } + + void addT2SOImmOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + addExpr(Inst, getImm()); + } + void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt()))); @@ -648,7 +751,7 @@ public: Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags()))); } - virtual void dump(raw_ostream &OS) const; + virtual void print(raw_ostream &OS) const; static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) { ARMOperand *Op = new ARMOperand(CondCode); @@ -699,6 +802,21 @@ public: return Op; } + static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy, + unsigned SrcReg, + unsigned ShiftReg, + unsigned ShiftImm, + SMLoc S, SMLoc E) { + ARMOperand *Op = new ARMOperand(ShiftedRegister); + Op->ShiftedReg.ShiftTy = ShTy; + Op->ShiftedReg.SrcReg = SrcReg; + Op->ShiftedReg.ShiftReg = ShiftReg; + Op->ShiftedReg.ShiftImm = ShiftImm; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + static ARMOperand *CreateShifter(ARM_AM::ShiftOpc ShTy, SMLoc S, SMLoc E) { ARMOperand *Op = new ARMOperand(Shifter); @@ -802,7 +920,7 @@ public: } // end anonymous namespace. -void ARMOperand::dump(raw_ostream &OS) const { +void ARMOperand::print(raw_ostream &OS) const { switch (Kind) { case CondCode: OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">"; @@ -863,7 +981,15 @@ void ARMOperand::dump(raw_ostream &OS) const { OS << "<register " << getReg() << ">"; break; case Shifter: - OS << "<shifter " << getShiftOpcStr(Shift.ShiftTy) << ">"; + OS << "<shifter " << ARM_AM::getShiftOpcStr(Shift.ShiftTy) << ">"; + break; + case ShiftedRegister: + OS << "<so_reg" + << ShiftedReg.SrcReg + << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(ShiftedReg.ShiftImm)) + << ", " << ShiftedReg.ShiftReg << ", " + << ARM_AM::getSORegOffset(ShiftedReg.ShiftImm) + << ">"; break; case RegisterList: case DPRRegisterList: @@ -927,11 +1053,12 @@ int ARMAsmParser::TryParseRegister() { return RegNum; } -/// Try to parse a register name. The token must be an Identifier when called, -/// and if it is a register name the token is eaten and the register number is -/// returned. Otherwise return -1. -/// -bool ARMAsmParser::TryParseShiftRegister( +// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0. +// If a recoverable error occurs, return 1. If an irrecoverable error +// occurs, return -1. An irrecoverable error is one where tokens have been +// consumed in the process of trying to parse the shifter (i.e., when it is +// indeed a shifter operand, but malformed). +int ARMAsmParser::TryParseShiftRegister( SmallVectorImpl<MCParsedAsmOperand*> &Operands) { SMLoc S = Parser.getTok().getLoc(); const AsmToken &Tok = Parser.getTok(); @@ -948,18 +1075,69 @@ bool ARMAsmParser::TryParseShiftRegister( .Default(ARM_AM::no_shift); if (ShiftTy == ARM_AM::no_shift) - return true; - - Parser.Lex(); // Eat shift-type operand; - int RegNum = TryParseRegister(); - if (RegNum == -1) - return Error(Parser.getTok().getLoc(), "register expected"); + return 1; + + Parser.Lex(); // Eat the operator. + + // The source register for the shift has already been added to the + // operand list, so we need to pop it off and combine it into the shifted + // register operand instead. + OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val()); + if (!PrevOp->isReg()) + return Error(PrevOp->getStartLoc(), "shift must be of a register"); + int SrcReg = PrevOp->getReg(); + int64_t Imm = 0; + int ShiftReg = 0; + if (ShiftTy == ARM_AM::rrx) { + // RRX Doesn't have an explicit shift amount. The encoder expects + // the shift register to be the same as the source register. Seems odd, + // but OK. + ShiftReg = SrcReg; + } else { + // Figure out if this is shifted by a constant or a register (for non-RRX). + if (Parser.getTok().is(AsmToken::Hash)) { + Parser.Lex(); // Eat hash. + SMLoc ImmLoc = Parser.getTok().getLoc(); + const MCExpr *ShiftExpr = 0; + if (getParser().ParseExpression(ShiftExpr)) { + Error(ImmLoc, "invalid immediate shift value"); + return -1; + } + // The expression must be evaluatable as an immediate. + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr); + if (!CE) { + Error(ImmLoc, "invalid immediate shift value"); + return -1; + } + // Range check the immediate. + // lsl, ror: 0 <= imm <= 31 + // lsr, asr: 0 <= imm <= 32 + Imm = CE->getValue(); + if (Imm < 0 || + ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) || + ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) { + Error(ImmLoc, "immediate shift value out of range"); + return -1; + } + } else if (Parser.getTok().is(AsmToken::Identifier)) { + ShiftReg = TryParseRegister(); + SMLoc L = Parser.getTok().getLoc(); + if (ShiftReg == -1) { + Error (L, "expected immediate or register in shift operand"); + return -1; + } + } else { + Error (Parser.getTok().getLoc(), + "expected immediate or register in shift operand"); + return -1; + } + } - Operands.push_back(ARMOperand::CreateReg(RegNum,S, Parser.getTok().getLoc())); - Operands.push_back(ARMOperand::CreateShifter(ShiftTy, + Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg, + ShiftReg, Imm, S, Parser.getTok().getLoc())); - return false; + return 0; } @@ -1162,10 +1340,14 @@ tryParseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size())) .Case("sy", ARM_MB::SY) .Case("st", ARM_MB::ST) + .Case("sh", ARM_MB::ISH) .Case("ish", ARM_MB::ISH) + .Case("shst", ARM_MB::ISHST) .Case("ishst", ARM_MB::ISHST) .Case("nsh", ARM_MB::NSH) + .Case("un", ARM_MB::NSH) .Case("nshst", ARM_MB::NSHST) + .Case("unst", ARM_MB::NSHST) .Case("osh", ARM_MB::OSH) .Case("oshst", ARM_MB::OSHST) .Default(~0U); @@ -1604,15 +1786,18 @@ bool ARMAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands, default: Error(Parser.getTok().getLoc(), "unexpected token in operand"); return true; - case AsmToken::Identifier: + case AsmToken::Identifier: { if (!TryParseRegisterWithWriteBack(Operands)) return false; - if (!TryParseShiftRegister(Operands)) + int Res = TryParseShiftRegister(Operands); + if (Res == 0) // success return false; - + else if (Res == -1) // irrecoverable error + return true; // Fall though for the Identifier case that is not a register or a // special name. + } case AsmToken::Integer: // things like 1f and 2b as a branch targets case AsmToken::Dot: { // . as a branch target // This was not a register so parse other operands that start with an @@ -1761,30 +1946,35 @@ static StringRef SplitMnemonic(StringRef Mnemonic, Mnemonic == "vcle" || (Mnemonic == "smlal" || Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" || Mnemonic == "vmlal" || Mnemonic == "vpadal" || - Mnemonic == "vqdmlal")) + Mnemonic == "vqdmlal" || Mnemonic == "bics")) return Mnemonic; - // First, split out any predication code. - unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2)) - .Case("eq", ARMCC::EQ) - .Case("ne", ARMCC::NE) - .Case("hs", ARMCC::HS) - .Case("lo", ARMCC::LO) - .Case("mi", ARMCC::MI) - .Case("pl", ARMCC::PL) - .Case("vs", ARMCC::VS) - .Case("vc", ARMCC::VC) - .Case("hi", ARMCC::HI) - .Case("ls", ARMCC::LS) - .Case("ge", ARMCC::GE) - .Case("lt", ARMCC::LT) - .Case("gt", ARMCC::GT) - .Case("le", ARMCC::LE) - .Case("al", ARMCC::AL) - .Default(~0U); - if (CC != ~0U) { - Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2); - PredicationCode = CC; + // First, split out any predication code. Ignore mnemonics we know aren't + // predicated but do have a carry-set and so weren't caught above. + if (Mnemonic != "adcs") { + unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2)) + .Case("eq", ARMCC::EQ) + .Case("ne", ARMCC::NE) + .Case("hs", ARMCC::HS) + .Case("cs", ARMCC::HS) + .Case("lo", ARMCC::LO) + .Case("cc", ARMCC::LO) + .Case("mi", ARMCC::MI) + .Case("pl", ARMCC::PL) + .Case("vs", ARMCC::VS) + .Case("vc", ARMCC::VC) + .Case("hi", ARMCC::HI) + .Case("ls", ARMCC::LS) + .Case("ge", ARMCC::GE) + .Case("lt", ARMCC::LT) + .Case("gt", ARMCC::GT) + .Case("le", ARMCC::LE) + .Case("al", ARMCC::AL) + .Default(~0U); + if (CC != ~0U) { + Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2); + PredicationCode = CC; + } } // Next, determine if we have a carry setting bit. We explicitly ignore all @@ -1824,8 +2014,6 @@ static StringRef SplitMnemonic(StringRef Mnemonic, void ARMAsmParser:: GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, bool &CanAcceptPredicationCode) { - bool isThumb = TM.getSubtarget<ARMSubtarget>().isThumb(); - if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" || Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" || Mnemonic == "smull" || Mnemonic == "add" || Mnemonic == "adc" || @@ -1834,7 +2022,7 @@ GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" || Mnemonic == "sbc" || Mnemonic == "mla" || Mnemonic == "umull" || Mnemonic == "eor" || Mnemonic == "smlal" || - (Mnemonic == "mov" && !isThumb)) { + (Mnemonic == "mov" && !isThumbOne())) { CanAcceptCarrySet = true; } else { CanAcceptCarrySet = false; @@ -1851,10 +2039,9 @@ GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, CanAcceptPredicationCode = true; } - if (isThumb) + if (isThumb()) if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" || - Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp" || - Mnemonic == "mov") + Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp") CanAcceptPredicationCode = false; } @@ -1884,20 +2071,22 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc, bool CanAcceptCarrySet, CanAcceptPredicationCode; GetMnemonicAcceptInfo(Head, CanAcceptCarrySet, CanAcceptPredicationCode); + // If we had a carry-set on an instruction that can't do that, issue an + // error. + if (!CanAcceptCarrySet && CarrySetting) { + Parser.EatToEndOfStatement(); + return Error(NameLoc, "instruction '" + Head + + "' can not set flags, but 's' suffix specified"); + } + // Add the carry setting operand, if necessary. // // FIXME: It would be awesome if we could somehow invent a location such that // match errors on this operand would print a nice diagnostic about how the // 's' character in the mnemonic resulted in a CCOut operand. - if (CanAcceptCarrySet) { + if (CanAcceptCarrySet) Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0, NameLoc)); - } else { - // This mnemonic can't ever accept a carry set, but the user wrote one (or - // misspelled another mnemonic). - - // FIXME: Issue a nice error. - } // Add the predication code operand, if necessary. if (CanAcceptPredicationCode) { @@ -1988,7 +2177,7 @@ MatchAndEmitInstruction(SMLoc IDLoc, // that updates the condition codes if it ends in 's'. So see if the // mnemonic ends in 's' and if so try removing the 's' and adding a CCOut // operand with a value of CPSR. - else if(MatchResult == Match_MnemonicFail) { + else if (MatchResult == Match_MnemonicFail) { // Get the instruction mnemonic, which is the first token. StringRef Mnemonic = ((ARMOperand*)Operands[0])->getToken(); if (Mnemonic.substr(Mnemonic.size()-1) == "s") { @@ -2174,20 +2363,15 @@ bool ARMAsmParser::ParseDirectiveCode(SMLoc L) { return Error(Parser.getTok().getLoc(), "unexpected token in directive"); Parser.Lex(); - // FIXME: We need to be able switch subtargets at this point so that - // MatchInstructionImpl() will work when it gets the AvailableFeatures which - // includes Feature_IsThumb or not to match the right instructions. This is - // blocked on the FIXME in llvm-mc.cpp when creating the TargetMachine. - if (Val == 16){ - assert(TM.getSubtarget<ARMSubtarget>().isThumb() && - "switching between arm/thumb not yet suppported via .code 16)"); + if (Val == 16) { + if (!isThumb()) + SwitchMode(); getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16); - } - else{ - assert(!TM.getSubtarget<ARMSubtarget>().isThumb() && - "switching between thumb/arm not yet suppported via .code 32)"); + } else { + if (isThumb()) + SwitchMode(); getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32); - } + } return false; } diff --git a/lib/Target/ARM/CMakeLists.txt b/lib/Target/ARM/CMakeLists.txt index d3b8b54e76b8..21608d0b62fd 100644 --- a/lib/Target/ARM/CMakeLists.txt +++ b/lib/Target/ARM/CMakeLists.txt @@ -1,18 +1,16 @@ set(LLVM_TARGET_DEFINITIONS ARM.td) -tablegen(ARMGenRegisterInfo.h.inc -gen-register-desc-header) -tablegen(ARMGenRegisterNames.inc -gen-register-enums) -tablegen(ARMGenRegisterInfo.inc -gen-register-desc) -tablegen(ARMGenInstrNames.inc -gen-instr-enums) -tablegen(ARMGenInstrInfo.inc -gen-instr-desc) +tablegen(ARMGenRegisterInfo.inc -gen-register-info) +tablegen(ARMGenInstrInfo.inc -gen-instr-info) tablegen(ARMGenCodeEmitter.inc -gen-emitter) tablegen(ARMGenMCCodeEmitter.inc -gen-emitter -mc-emitter) +tablegen(ARMGenMCPseudoLowering.inc -gen-pseudo-lowering) tablegen(ARMGenAsmWriter.inc -gen-asm-writer) tablegen(ARMGenAsmMatcher.inc -gen-asm-matcher) tablegen(ARMGenDAGISel.inc -gen-dag-isel) tablegen(ARMGenFastISel.inc -gen-fast-isel) tablegen(ARMGenCallingConv.inc -gen-callingconv) -tablegen(ARMGenSubtarget.inc -gen-subtarget) +tablegen(ARMGenSubtargetInfo.inc -gen-subtarget) tablegen(ARMGenEDInfo.inc -gen-enhanced-disassembly-info) tablegen(ARMGenDecoderTables.inc -gen-arm-decoder) @@ -34,10 +32,10 @@ add_llvm_target(ARMCodeGen ARMISelLowering.cpp ARMInstrInfo.cpp ARMJITInfo.cpp + ARMMachObjectWriter.cpp ARMMCCodeEmitter.cpp ARMMCExpr.cpp ARMLoadStoreOptimizer.cpp - ARMMCAsmInfo.cpp ARMMCInstLower.cpp ARMRegisterInfo.cpp ARMSelectionDAGInfo.cpp @@ -67,3 +65,4 @@ add_subdirectory(TargetInfo) add_subdirectory(AsmParser) add_subdirectory(Disassembler) add_subdirectory(InstPrinter) +add_subdirectory(MCTargetDesc) diff --git a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp index 271ca8c72f08..d89c80a9d457 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp @@ -24,8 +24,8 @@ //#define DEBUG(X) do { X; } while (0) /// ARMGenInstrInfo.inc - ARMGenInstrInfo.inc contains the static const -/// TargetInstrDesc ARMInsts[] definition and the TargetOperandInfo[]'s -/// describing the operand info for each ARMInsts[i]. +/// MCInstrDesc ARMInsts[] definition and the MCOperandInfo[]'s describing the +/// operand info for each ARMInsts[i]. /// /// Together with an instruction's encoding format, we can take advantage of the /// NumOperands and the OpInfo fields of the target instruction description in @@ -46,10 +46,10 @@ /// dag DefaultOps = (ops (i32 14), (i32 zero_reg)); /// } /// -/// which is manifested by the TargetOperandInfo[] of: +/// which is manifested by the MCOperandInfo[] of: /// -/// { 0, 0|(1<<TOI::Predicate), 0 }, -/// { ARM::CCRRegClassID, 0|(1<<TOI::Predicate), 0 } +/// { 0, 0|(1<<MCOI::Predicate), 0 }, +/// { ARM::CCRRegClassID, 0|(1<<MCOI::Predicate), 0 } /// /// So the first predicate MCOperand corresponds to the immediate part of the /// ARM condition field (Inst{31-28}), and the second predicate MCOperand @@ -66,12 +66,14 @@ /// dag DefaultOps = (ops (i32 zero_reg)); /// } /// -/// which is manifested by the one TargetOperandInfo of: +/// which is manifested by the one MCOperandInfo of: /// -/// { ARM::CCRRegClassID, 0|(1<<TOI::OptionalDef), 0 } +/// { ARM::CCRRegClassID, 0|(1<<MCOI::OptionalDef), 0 } /// -/// And this maps to one MCOperand with the regsiter kind of ARM::CPSR. -#include "ARMGenInstrInfo.inc" + +namespace llvm { +extern MCInstrDesc ARMInsts[]; +} using namespace llvm; @@ -588,9 +590,9 @@ static bool BadRegsMulFrm(unsigned Opcode, uint32_t insn) { static bool DisassembleMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - unsigned short NumDefs = TID.getNumDefs(); - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + unsigned short NumDefs = MCID.getNumDefs(); + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -739,9 +741,9 @@ static bool DisassembleCoprocessor(MCInst &MI, unsigned Opcode, uint32_t insn, if (PW) { MI.addOperand(MCOperand::CreateReg(0)); ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub; - const TargetInstrDesc &TID = ARMInsts[Opcode]; + const MCInstrDesc &MCID = ARMInsts[Opcode]; unsigned IndexMode = - (TID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift; + (MCID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift; unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, slice(insn, 7, 0) << 2, ARM_AM::no_shift, IndexMode); MI.addOperand(MCOperand::CreateImm(Offset)); @@ -802,7 +804,7 @@ static bool DisassembleBrFrm(MCInst &MI, unsigned Opcode, uint32_t insn, if (CoprocessorOpcode(Opcode)) return DisassembleCoprocessor(MI, Opcode, insn, NumOps, NumOpsAdded, B); - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; // MRS and MRSsys take one GPR reg Rd. @@ -901,7 +903,7 @@ static bool DisassembleBrFrm(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleBrMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; unsigned &OpIdx = NumOpsAdded; @@ -976,10 +978,10 @@ static bool BadRegsDPFrm(unsigned Opcode, uint32_t insn) { static bool DisassembleDPFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - unsigned short NumDefs = TID.getNumDefs(); - bool isUnary = isUnaryDP(TID.TSFlags); - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + unsigned short NumDefs = MCID.getNumDefs(); + bool isUnary = isUnaryDP(MCID.TSFlags); + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -1041,7 +1043,7 @@ static bool DisassembleDPFrm(MCInst &MI, unsigned Opcode, uint32_t insn, } // If this is a two-address operand, skip it, e.g., MOVCCr operand 1. - if (isUnary && (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)) { + if (isUnary && (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) { MI.addOperand(MCOperand::CreateReg(0)); ++OpIdx; } @@ -1089,10 +1091,10 @@ static bool DisassembleDPFrm(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleDPSoRegFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - unsigned short NumDefs = TID.getNumDefs(); - bool isUnary = isUnaryDP(TID.TSFlags); - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + unsigned short NumDefs = MCID.getNumDefs(); + bool isUnary = isUnaryDP(MCID.TSFlags); + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -1118,7 +1120,7 @@ static bool DisassembleDPSoRegFrm(MCInst &MI, unsigned Opcode, uint32_t insn, } // If this is a two-address operand, skip it, e.g., MOVCCs operand 1. - if (isUnary && (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)) { + if (isUnary && (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) { MI.addOperand(MCOperand::CreateReg(0)); ++OpIdx; } @@ -1244,17 +1246,17 @@ static bool BadRegsLdStFrm(unsigned Opcode, uint32_t insn, bool Store, bool WBac static bool DisassembleLdStFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, bool isStore, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - bool isPrePost = isPrePostLdSt(TID.TSFlags); - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + bool isPrePost = isPrePostLdSt(MCID.TSFlags); + const MCOperandInfo *OpInfo = MCID.OpInfo; if (!OpInfo) return false; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; - assert(((!isStore && TID.getNumDefs() > 0) || - (isStore && (TID.getNumDefs() == 0 || isPrePost))) + assert(((!isStore && MCID.getNumDefs() > 0) || + (isStore && (MCID.getNumDefs() == 0 || isPrePost))) && "Invalid arguments"); // Operand 0 of a pre- and post-indexed store is the address base writeback. @@ -1291,7 +1293,7 @@ static bool DisassembleLdStFrm(MCInst &MI, unsigned Opcode, uint32_t insn, assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && "Reg operand expected"); - assert((!isPrePost || (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)) + assert((!isPrePost || (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) && "Index mode or tied_to operand expected"); MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn)))); @@ -1308,7 +1310,7 @@ static bool DisassembleLdStFrm(MCInst &MI, unsigned Opcode, uint32_t insn, ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub; unsigned IndexMode = - (TID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift; + (MCID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift; if (getIBit(insn) == 0) { // For pre- and post-indexed case, add a reg0 operand (Addressing Mode #2). // Otherwise, skip the reg operand since for addrmode_imm12, Rn has already @@ -1379,17 +1381,17 @@ static bool HasDualReg(unsigned Opcode) { static bool DisassembleLdStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, bool isStore, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - bool isPrePost = isPrePostLdSt(TID.TSFlags); - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + bool isPrePost = isPrePostLdSt(MCID.TSFlags); + const MCOperandInfo *OpInfo = MCID.OpInfo; if (!OpInfo) return false; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; - assert(((!isStore && TID.getNumDefs() > 0) || - (isStore && (TID.getNumDefs() == 0 || isPrePost))) + assert(((!isStore && MCID.getNumDefs() > 0) || + (isStore && (MCID.getNumDefs() == 0 || isPrePost))) && "Invalid arguments"); // Operand 0 of a pre- and post-indexed store is the address base writeback. @@ -1433,7 +1435,7 @@ static bool DisassembleLdStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && "Reg operand expected"); - assert((!isPrePost || (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)) + assert((!isPrePost || (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) && "Offset mode or tied_to operand expected"); MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn)))); @@ -1451,7 +1453,7 @@ static bool DisassembleLdStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub; unsigned IndexMode = - (TID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift; + (MCID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift; if (getAM3IBit(insn) == 1) { MI.addOperand(MCOperand::CreateReg(0)); @@ -1539,7 +1541,7 @@ static bool DisassembleLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleLdStExFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; unsigned &OpIdx = NumOpsAdded; @@ -1591,7 +1593,7 @@ static bool DisassembleLdStExFrm(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleArithMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -1653,8 +1655,8 @@ static bool DisassembleSatFrm(MCInst &MI, unsigned Opcode, uint32_t insn, if (decodeRd(insn) == 15 || decodeRm(insn) == 15) return false; - const TargetInstrDesc &TID = ARMInsts[Opcode]; - NumOpsAdded = TID.getNumOperands() - 2; // ignore predicate operands + const MCInstrDesc &MCID = ARMInsts[Opcode]; + NumOpsAdded = MCID.getNumOperands() - 2; // ignore predicate operands // Disassemble register def. MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, @@ -1696,7 +1698,7 @@ static bool DisassembleExtFrm(MCInst &MI, unsigned Opcode, uint32_t insn, if (decodeRd(insn) == 15 || decodeRm(insn) == 15) return false; - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -1802,7 +1804,7 @@ static bool DisassembleVFPUnaryFrm(MCInst &MI, unsigned Opcode, uint32_t insn, assert(NumOps >= 1 && "VFPUnaryFrm expects NumOps >= 1"); - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -1842,8 +1844,8 @@ static bool DisassembleVFPBinaryFrm(MCInst &MI, unsigned Opcode, uint32_t insn, assert(NumOps >= 3 && "VFPBinaryFrm expects NumOps >= 3"); - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -1858,7 +1860,7 @@ static bool DisassembleVFPBinaryFrm(MCInst &MI, unsigned Opcode, uint32_t insn, ++OpIdx; // Skip tied_to operand constraint. - if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) { + if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) { assert(NumOps >= 4 && "Expect >=4 operands"); MI.addOperand(MCOperand::CreateReg(0)); ++OpIdx; @@ -1886,8 +1888,8 @@ static bool DisassembleVFPConv1Frm(MCInst &MI, unsigned Opcode, uint32_t insn, assert(NumOps >= 2 && "VFPConv1Frm expects NumOps >= 2"); - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; if (!OpInfo) return false; bool SP = slice(insn, 8, 8) == 0; // A8.6.295 & A8.6.297 @@ -1903,7 +1905,7 @@ static bool DisassembleVFPConv1Frm(MCInst &MI, unsigned Opcode, uint32_t insn, getRegisterEnum(B, RegClassID, decodeVFPRd(insn, SP)))); - assert(TID.getOperandConstraint(1, TOI::TIED_TO) != -1 && + assert(MCID.getOperandConstraint(1, MCOI::TIED_TO) != -1 && "Tied to operand expected"); MI.addOperand(MI.getOperand(0)); @@ -1961,7 +1963,7 @@ static bool DisassembleVFPConv3Frm(MCInst &MI, unsigned Opcode, uint32_t insn, assert(NumOps >= 3 && "VFPConv3Frm expects NumOps >= 3"); - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; unsigned &OpIdx = NumOpsAdded; MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, @@ -2011,7 +2013,7 @@ static bool DisassembleVFPConv5Frm(MCInst &MI, unsigned Opcode, uint32_t insn, assert(NumOps >= 3 && "VFPConv5Frm expects NumOps >= 3"); - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -2136,7 +2138,7 @@ static bool DisassembleVFPLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleVFPMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -2402,8 +2404,8 @@ static bool DisassembleNLdSt0(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, bool Store, bool DblSpaced, unsigned alignment, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; // At least one DPR register plus addressing mode #6. assert(NumOps >= 3 && "Expect >= 3 operands"); @@ -2507,7 +2509,7 @@ static bool DisassembleNLdSt0(MCInst &MI, unsigned Opcode, uint32_t insn, } while (OpIdx < NumOps && (unsigned)OpInfo[OpIdx].RegClass == RegClass) { - assert(TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1 && + assert(MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1 && "Tied to operand expected"); MI.addOperand(MCOperand::CreateReg(0)); ++OpIdx; @@ -2757,8 +2759,8 @@ static bool DisassembleNLdSt(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleN1RegModImmFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; assert(NumOps >= 2 && (OpInfo[0].RegClass == ARM::DPRRegClassID || @@ -2848,8 +2850,8 @@ enum N2VFlag { static bool DisassembleNVdVmOptImm(MCInst &MI, unsigned Opc, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, N2VFlag Flag, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opc]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opc]; + const MCOperandInfo *OpInfo = MCID.OpInfo; assert(NumOps >= 2 && (OpInfo[0].RegClass == ARM::DPRRegClassID || @@ -2878,7 +2880,7 @@ static bool DisassembleNVdVmOptImm(MCInst &MI, unsigned Opc, uint32_t insn, ++OpIdx; // VPADAL... - if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) { + if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) { // TIED_TO operand. MI.addOperand(MCOperand::CreateReg(0)); ++OpIdx; @@ -2892,7 +2894,7 @@ static bool DisassembleNVdVmOptImm(MCInst &MI, unsigned Opc, uint32_t insn, // VZIP and others have two TIED_TO reg operands. int Idx; while (OpIdx < NumOps && - (Idx = TID.getOperandConstraint(OpIdx, TOI::TIED_TO)) != -1) { + (Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) { // Add TIED_TO operand. MI.addOperand(MI.getOperand(Idx)); ++OpIdx; @@ -2945,8 +2947,8 @@ static bool DisassembleNVecDupLnFrm(MCInst &MI, unsigned Opc, uint32_t insn, static bool DisassembleNVectorShift(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, bool LeftShift, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; assert(NumOps >= 3 && (OpInfo[0].RegClass == ARM::DPRRegClassID || @@ -2964,7 +2966,7 @@ static bool DisassembleNVectorShift(MCInst &MI, unsigned Opcode, uint32_t insn, decodeNEONRd(insn)))); ++OpIdx; - if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) { + if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) { // TIED_TO operand. MI.addOperand(MCOperand::CreateReg(0)); ++OpIdx; @@ -3044,8 +3046,8 @@ enum N3VFlag { static bool DisassembleNVdVnVmOptImm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, N3VFlag Flag, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; // No checking for OpInfo[2] because of MOVDneon/MOVQ with only two regs. assert(NumOps >= 3 && @@ -3076,7 +3078,7 @@ static bool DisassembleNVdVnVmOptImm(MCInst &MI, unsigned Opcode, uint32_t insn, ++OpIdx; // VABA, VABAL, VBSLd, VBSLq, ... - if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) { + if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) { // TIED_TO operand. MI.addOperand(MCOperand::CreateReg(0)); ++OpIdx; @@ -3091,11 +3093,6 @@ static bool DisassembleNVdVnVmOptImm(MCInst &MI, unsigned Opcode, uint32_t insn, : decodeNEONRm(insn)))); ++OpIdx; - // Special case handling for VMOVDneon and VMOVQ because they are marked as - // N3RegFrm. - if (Opcode == ARM::VMOVDneon || Opcode == ARM::VMOVQ) - return true; - // Dm = Inst{5:3-0} => NEON Rm // or // Dm is restricted to D0-D7 if size is 16, D0-D15 otherwise @@ -3163,8 +3160,8 @@ static bool DisassembleNVecMulScalarFrm(MCInst &MI, unsigned Opcode, static bool DisassembleNVTBLFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; if (!OpInfo) return false; assert(NumOps >= 3 && @@ -3192,7 +3189,7 @@ static bool DisassembleNVTBLFrm(MCInst &MI, unsigned Opcode, uint32_t insn, // Process tied_to operand constraint. int Idx; - if ((Idx = TID.getOperandConstraint(OpIdx, TOI::TIED_TO)) != -1) { + if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) { MI.addOperand(MI.getOperand(Idx)); ++OpIdx; } @@ -3221,11 +3218,11 @@ static bool DisassembleNVTBLFrm(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleNGetLnFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; if (!OpInfo) return false; - assert(TID.getNumDefs() == 1 && NumOps >= 3 && + assert(MCID.getNumDefs() == 1 && NumOps >= 3 && OpInfo[0].RegClass == ARM::GPRRegClassID && OpInfo[1].RegClass == ARM::DPRRegClassID && OpInfo[2].RegClass < 0 && @@ -3255,14 +3252,14 @@ static bool DisassembleNGetLnFrm(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleNSetLnFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; if (!OpInfo) return false; - assert(TID.getNumDefs() == 1 && NumOps >= 3 && + assert(MCID.getNumDefs() == 1 && NumOps >= 3 && OpInfo[0].RegClass == ARM::DPRRegClassID && OpInfo[1].RegClass == ARM::DPRRegClassID && - TID.getOperandConstraint(1, TOI::TIED_TO) != -1 && + MCID.getOperandConstraint(1, MCOI::TIED_TO) != -1 && OpInfo[2].RegClass == ARM::GPRRegClassID && OpInfo[3].RegClass < 0 && "Expect >= 3 operands with one dst operand"); @@ -3294,7 +3291,7 @@ static bool DisassembleNSetLnFrm(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleNDupFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; assert(NumOps >= 2 && (OpInfo[0].RegClass == ARM::DPRRegClassID || @@ -3379,7 +3376,7 @@ static bool DisassemblePreLoadFrm(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - if (Opcode == ARM::DMB || Opcode == ARM::DSB) { + if (Opcode == ARM::DMB || Opcode == ARM::DSB || Opcode == ARM::ISB) { // Inst{3-0} encodes the memory barrier option for the variants. unsigned opt = slice(insn, 3, 0); switch (opt) { @@ -3604,11 +3601,11 @@ bool ARMBasicMCBuilder::DoPredicateOperands(MCInst& MI, unsigned Opcode, assert(NumOpsRemaining > 0 && "Invalid argument"); - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; unsigned Idx = MI.getNumOperands(); // First, we check whether this instr specifies the PredicateOperand through - // a pair of TargetOperandInfos with isPredicate() property. + // a pair of MCOperandInfos with isPredicate() property. if (NumOpsRemaining >= 2 && OpInfo[Idx].isPredicate() && OpInfo[Idx+1].isPredicate() && OpInfo[Idx].RegClass < 0 && @@ -3636,13 +3633,13 @@ bool ARMBasicMCBuilder::TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode, assert(NumOpsRemaining > 0 && "Invalid argument"); - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; const std::string &Name = ARMInsts[Opcode].Name; unsigned Idx = MI.getNumOperands(); uint64_t TSFlags = ARMInsts[Opcode].TSFlags; // First, we check whether this instr specifies the PredicateOperand through - // a pair of TargetOperandInfos with isPredicate() property. + // a pair of MCOperandInfos with isPredicate() property. if (NumOpsRemaining >= 2 && OpInfo[Idx].isPredicate() && OpInfo[Idx+1].isPredicate() && OpInfo[Idx].RegClass < 0 && diff --git a/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h b/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h index 9639c8a4b1bd..834c6f65295d 100644 --- a/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h +++ b/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h @@ -350,7 +350,7 @@ static inline unsigned decodeRotate(uint32_t insn) { static bool DisassembleThumb1General(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -425,8 +425,8 @@ static bool DisassembleThumb1General(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleThumb1DP(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -454,7 +454,7 @@ static bool DisassembleThumb1DP(MCInst &MI, unsigned Opcode, uint32_t insn, assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID && "Thumb reg operand expected"); int Idx; - if ((Idx = TID.getOperandConstraint(OpIdx, TOI::TIED_TO)) != -1) { + if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) { // The reg operand is tied to the first reg operand. MI.addOperand(MI.getOperand(Idx)); ++OpIdx; @@ -511,8 +511,8 @@ static bool DisassembleThumb1Special(MCInst &MI, unsigned Opcode, uint32_t insn, return true; } - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -530,7 +530,7 @@ static bool DisassembleThumb1Special(MCInst &MI, unsigned Opcode, uint32_t insn, assert(OpIdx < NumOps && "More operands expected"); int Idx; - if ((Idx = TID.getOperandConstraint(OpIdx, TOI::TIED_TO)) != -1) { + if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) { // The reg operand is tied to the first reg operand. MI.addOperand(MI.getOperand(Idx)); ++OpIdx; @@ -554,7 +554,7 @@ static bool DisassembleThumb1Special(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleThumb1LdPC(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID && @@ -602,7 +602,7 @@ static bool DisassembleThumb1LdPC(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleThumb2Ldpci(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; assert(NumOps >= 2 && @@ -630,8 +630,8 @@ static bool DisassembleThumb2Ldpci(MCInst &MI, unsigned Opcode, static bool DisassembleThumb1LdSt(unsigned opA, MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; assert(NumOps >= 2 @@ -680,7 +680,7 @@ static bool DisassembleThumb1LdStSP(MCInst &MI, unsigned Opcode, uint32_t insn, assert((Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) && "Unexpected opcode"); - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; assert(NumOps >= 3 && @@ -708,7 +708,7 @@ static bool DisassembleThumb1AddPCi(MCInst &MI, unsigned Opcode, uint32_t insn, assert(Opcode == ARM::tADDrPCi && "Unexpected opcode"); - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID && @@ -733,7 +733,7 @@ static bool DisassembleThumb1AddSPi(MCInst &MI, unsigned Opcode, uint32_t insn, assert(Opcode == ARM::tADDrSPi && "Unexpected opcode"); - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; assert(NumOps >= 3 && @@ -810,7 +810,7 @@ static bool DisassembleThumb1Misc(MCInst &MI, unsigned Opcode, uint32_t insn, if (Opcode == ARM::tPUSH || Opcode == ARM::tPOP) return DisassembleThumb1PushPop(MI, Opcode, insn, NumOps, NumOpsAdded, B); - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; // Predicate operands are handled elsewhere. if (NumOps == 2 && @@ -958,7 +958,7 @@ static bool DisassembleThumb1CondBr(MCInst &MI, unsigned Opcode, uint32_t insn, if (Opcode == ARM::tTRAP) return true; - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; assert(NumOps == 3 && OpInfo[0].RegClass < 0 && @@ -989,7 +989,7 @@ static bool DisassembleThumb1CondBr(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleThumb1Br(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; assert(NumOps == 1 && OpInfo[0].RegClass < 0 && "1 imm operand expected"); @@ -1226,7 +1226,7 @@ static bool DisassembleThumb2LdStMul(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleThumb2LdStEx(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; unsigned &OpIdx = NumOpsAdded; @@ -1316,7 +1316,7 @@ static bool DisassembleThumb2LdStEx(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleThumb2LdStDual(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; if (!OpInfo) return false; assert(NumOps >= 4 @@ -1423,8 +1423,8 @@ static inline bool Thumb2ShiftOpcode(unsigned Opcode) { static bool DisassembleThumb2DPSoReg(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; // Special case handling. @@ -1467,7 +1467,7 @@ static bool DisassembleThumb2DPSoReg(MCInst &MI, unsigned Opcode, uint32_t insn, if (ThreeReg) { int Idx; - if ((Idx = TID.getOperandConstraint(OpIdx, TOI::TIED_TO)) != -1) { + if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) { // Process tied_to operand constraint. MI.addOperand(MI.getOperand(Idx)); ++OpIdx; @@ -1521,8 +1521,8 @@ static bool DisassembleThumb2DPSoReg(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleThumb2DPModImm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -1550,7 +1550,7 @@ static bool DisassembleThumb2DPModImm(MCInst &MI, unsigned Opcode, return false; } int Idx; - if ((Idx = TID.getOperandConstraint(OpIdx, TOI::TIED_TO)) != -1) { + if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) { // The reg operand is tied to the first reg operand. MI.addOperand(MI.getOperand(Idx)); } else { @@ -1590,8 +1590,8 @@ static inline bool Thumb2SaturateOpcode(unsigned Opcode) { /// o t2SSAT16, t2USAT16: Rs sat_pos Rn static bool DisassembleThumb2Sat(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - NumOpsAdded = TID.getNumOperands() - 2; // ignore predicate operands + const MCInstrDesc &MCID = ARMInsts[Opcode]; + NumOpsAdded = MCID.getNumOperands() - 2; // ignore predicate operands // Disassemble the register def. MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID, @@ -1635,8 +1635,8 @@ static bool DisassembleThumb2Sat(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleThumb2DPBinImm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -1659,7 +1659,7 @@ static bool DisassembleThumb2DPBinImm(MCInst &MI, unsigned Opcode, if (TwoReg) { assert(NumOps >= 3 && "Expect >= 3 operands"); int Idx; - if ((Idx = TID.getOperandConstraint(OpIdx, TOI::TIED_TO)) != -1) { + if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) { // Process tied_to operand constraint. MI.addOperand(MI.getOperand(Idx)); } else { @@ -1907,8 +1907,8 @@ static bool DisassembleThumb2PreLoad(MCInst &MI, unsigned Opcode, uint32_t insn, // t2PLDs: Rn Rm imm2=Inst{5-4} // Same pattern applies for t2PLDW* and t2PLI*. - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -2073,8 +2073,8 @@ static bool DisassembleThumb2LdSt(bool Load, MCInst &MI, unsigned Opcode, // See, for example, A6.3.7 Load word: Table A6-18 Load word. if (Load && Rn == 15) return DisassembleThumb2Ldpci(MI, Opcode, insn, NumOps, NumOpsAdded, B); - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -2085,7 +2085,7 @@ static bool DisassembleThumb2LdSt(bool Load, MCInst &MI, unsigned Opcode, "Expect >= 3 operands and first two as reg operands"); bool ThreeReg = (OpInfo[2].RegClass > 0); - bool TIED_TO = ThreeReg && TID.getOperandConstraint(2, TOI::TIED_TO) != -1; + bool TIED_TO = ThreeReg && MCID.getOperandConstraint(2, MCOI::TIED_TO) != -1; bool Imm12 = !ThreeReg && slice(insn, 23, 23) == 1; // ARMInstrThumb2.td // Build the register operands, followed by the immediate. @@ -2160,8 +2160,8 @@ static bool DisassembleThumb2LdSt(bool Load, MCInst &MI, unsigned Opcode, static bool DisassembleThumb2DPReg(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetInstrDesc &TID = ARMInsts[Opcode]; - const TargetOperandInfo *OpInfo = TID.OpInfo; + const MCInstrDesc &MCID = ARMInsts[Opcode]; + const MCOperandInfo *OpInfo = MCID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -2214,7 +2214,7 @@ static bool DisassembleThumb2DPReg(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleThumb2Mul(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; assert(NumOps >= 3 && OpInfo[0].RegClass == ARM::rGPRRegClassID && @@ -2259,7 +2259,7 @@ static bool DisassembleThumb2Mul(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleThumb2LongMul(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; assert(NumOps >= 3 && OpInfo[0].RegClass == ARM::rGPRRegClassID && diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp index 8ae87f81cc1e..78d3e477975c 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp @@ -126,38 +126,6 @@ void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, } } -static void printSOImm(raw_ostream &O, int64_t V, raw_ostream *CommentStream, - const MCAsmInfo *MAI) { - // Break it up into two parts that make up a shifter immediate. - V = ARM_AM::getSOImmVal(V); - assert(V != -1 && "Not a valid so_imm value!"); - - unsigned Imm = ARM_AM::getSOImmValImm(V); - unsigned Rot = ARM_AM::getSOImmValRot(V); - - // Print low-level immediate formation info, per - // A5.2.3: Data-processing (immediate), and - // A5.2.4: Modified immediate constants in ARM instructions - if (Rot) { - O << "#" << Imm << ", #" << Rot; - // Pretty printed version. - if (CommentStream) - *CommentStream << (int)ARM_AM::rotr32(Imm, Rot) << "\n"; - } else { - O << "#" << Imm; - } -} - - -/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit -/// immediate in bits 0-7. -void ARMInstPrinter::printSOImmOperand(const MCInst *MI, unsigned OpNum, - raw_ostream &O) { - const MCOperand &MO = MI->getOperand(OpNum); - assert(MO.isImm() && "Not a valid so_imm value!"); - printSOImm(O, MO.getImm(), CommentStream, &MAI); -} - // so_reg is a 4-operand unit corresponding to register forms of the A5.1 // "Addressing Mode 1 - Data-processing operands" forms. This includes: // REG 0 0 - e.g. R5 @@ -174,6 +142,8 @@ void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum, // Print the shift opc. ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm()); O << ", " << ARM_AM::getShiftOpcStr(ShOpc); + if (ShOpc == ARM_AM::rrx) + return; if (MO2.getReg()) { O << ' ' << getRegisterName(MO2.getReg()); assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0); diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h index bde0eb9199a9..d5f238bb8a61 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h @@ -19,11 +19,10 @@ namespace llvm { class MCOperand; -class TargetMachine; class ARMInstPrinter : public MCInstPrinter { public: - ARMInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI) + ARMInstPrinter(const MCAsmInfo &MAI) : MCInstPrinter(MAI) {} virtual void printInst(const MCInst *MI, raw_ostream &O); @@ -39,8 +38,6 @@ public: void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); - void printSOImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); - void printSORegOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printAddrMode2Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O); diff --git a/lib/Target/ARM/ARMMCAsmInfo.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp index 53b4c95d3801..53b4c95d3801 100644 --- a/lib/Target/ARM/ARMMCAsmInfo.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp diff --git a/lib/Target/ARM/ARMMCAsmInfo.h b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.h index 90f7822ea580..90f7822ea580 100644 --- a/lib/Target/ARM/ARMMCAsmInfo.h +++ b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.h diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp new file mode 100644 index 000000000000..f8fcf2b8aff1 --- /dev/null +++ b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp @@ -0,0 +1,144 @@ +//===-- ARMMCTargetDesc.cpp - ARM Target Descriptions -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides ARM specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#include "ARMMCTargetDesc.h" +#include "ARMMCAsmInfo.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Target/TargetRegistry.h" + +#define GET_REGINFO_MC_DESC +#include "ARMGenRegisterInfo.inc" + +#define GET_INSTRINFO_MC_DESC +#include "ARMGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_MC_DESC +#include "ARMGenSubtargetInfo.inc" + +using namespace llvm; + +std::string ARM_MC::ParseARMTriple(StringRef TT) { + // Set the boolean corresponding to the current target triple, or the default + // if one cannot be determined, to true. + unsigned Len = TT.size(); + unsigned Idx = 0; + + // FIXME: Enahnce Triple helper class to extract ARM version. + bool isThumb = false; + if (Len >= 5 && TT.substr(0, 4) == "armv") + Idx = 4; + else if (Len >= 6 && TT.substr(0, 5) == "thumb") { + isThumb = true; + if (Len >= 7 && TT[5] == 'v') + Idx = 6; + } + + std::string ARMArchFeature; + if (Idx) { + unsigned SubVer = TT[Idx]; + if (SubVer >= '7' && SubVer <= '9') { + if (Len >= Idx+2 && TT[Idx+1] == 'm') { + // v7m: FeatureNoARM, FeatureDB, FeatureHWDiv + ARMArchFeature = "+v7,+noarm,+db,+hwdiv"; + } else if (Len >= Idx+3 && TT[Idx+1] == 'e'&& TT[Idx+2] == 'm') { + // v7em: FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureDSPThumb2, + // FeatureT2XtPk + ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+t2dsp,t2xtpk"; + } else + // v7a: FeatureNEON, FeatureDB, FeatureDSPThumb2 + ARMArchFeature = "+v7,+neon,+db,+t2dsp"; + } else if (SubVer == '6') { + if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2') + ARMArchFeature = "+v6t2"; + else + ARMArchFeature = "+v6"; + } else if (SubVer == '5') { + if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e') + ARMArchFeature = "+v5te"; + else + ARMArchFeature = "+v5t"; + } else if (SubVer == '4' && Len >= Idx+2 && TT[Idx+1] == 't') + ARMArchFeature = "+v4t"; + } + + if (isThumb) { + if (ARMArchFeature.empty()) + ARMArchFeature = "+thumb-mode"; + else + ARMArchFeature += ",+thumb-mode"; + } + + return ARMArchFeature; +} + +MCSubtargetInfo *ARM_MC::createARMMCSubtargetInfo(StringRef TT, StringRef CPU, + StringRef FS) { + std::string ArchFS = ARM_MC::ParseARMTriple(TT); + if (!FS.empty()) { + if (!ArchFS.empty()) + ArchFS = ArchFS + "," + FS.str(); + else + ArchFS = FS; + } + + MCSubtargetInfo *X = new MCSubtargetInfo(); + InitARMMCSubtargetInfo(X, TT, CPU, ArchFS); + return X; +} + +// Force static initialization. +extern "C" void LLVMInitializeARMMCSubtargetInfo() { + TargetRegistry::RegisterMCSubtargetInfo(TheARMTarget, + ARM_MC::createARMMCSubtargetInfo); + TargetRegistry::RegisterMCSubtargetInfo(TheThumbTarget, + ARM_MC::createARMMCSubtargetInfo); +} + +static MCInstrInfo *createARMMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitARMMCInstrInfo(X); + return X; +} + +extern "C" void LLVMInitializeARMMCInstrInfo() { + TargetRegistry::RegisterMCInstrInfo(TheARMTarget, createARMMCInstrInfo); + TargetRegistry::RegisterMCInstrInfo(TheThumbTarget, createARMMCInstrInfo); +} + +static MCRegisterInfo *createARMMCRegisterInfo() { + MCRegisterInfo *X = new MCRegisterInfo(); + InitARMMCRegisterInfo(X); + return X; +} + +extern "C" void LLVMInitializeARMMCRegInfo() { + TargetRegistry::RegisterMCRegInfo(TheARMTarget, createARMMCRegisterInfo); + TargetRegistry::RegisterMCRegInfo(TheThumbTarget, createARMMCRegisterInfo); +} + +static MCAsmInfo *createARMMCAsmInfo(const Target &T, StringRef TT) { + Triple TheTriple(TT); + + if (TheTriple.isOSDarwin()) + return new ARMMCAsmInfoDarwin(); + + return new ARMELFMCAsmInfo(); +} + +extern "C" void LLVMInitializeARMMCAsmInfo() { + // Register the target asm info. + RegisterMCAsmInfoFn A(TheARMTarget, createARMMCAsmInfo); + RegisterMCAsmInfoFn B(TheThumbTarget, createARMMCAsmInfo); +} diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h new file mode 100644 index 000000000000..74701e3516dc --- /dev/null +++ b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h @@ -0,0 +1,52 @@ +//===-- ARMMCTargetDesc.h - ARM Target Descriptions -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides ARM specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMMCTARGETDESC_H +#define ARMMCTARGETDESC_H + +#include <string> + +namespace llvm { +class MCSubtargetInfo; +class Target; +class StringRef; + +extern Target TheARMTarget, TheThumbTarget; + +namespace ARM_MC { + std::string ParseARMTriple(StringRef TT); + + /// createARMMCSubtargetInfo - Create a ARM MCSubtargetInfo instance. + /// This is exposed so Asm parser, etc. do not need to go through + /// TargetRegistry. + MCSubtargetInfo *createARMMCSubtargetInfo(StringRef TT, StringRef CPU, + StringRef FS); +} + +} // End llvm namespace + +// Defines symbolic names for ARM registers. This defines a mapping from +// register name to register number. +// +#define GET_REGINFO_ENUM +#include "ARMGenRegisterInfo.inc" + +// Defines symbolic names for the ARM instructions. +// +#define GET_INSTRINFO_ENUM +#include "ARMGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "ARMGenSubtargetInfo.inc" + +#endif diff --git a/lib/Target/ARM/MCTargetDesc/CMakeLists.txt b/lib/Target/ARM/MCTargetDesc/CMakeLists.txt new file mode 100644 index 000000000000..68daf42c9191 --- /dev/null +++ b/lib/Target/ARM/MCTargetDesc/CMakeLists.txt @@ -0,0 +1,7 @@ +add_llvm_library(LLVMARMDesc + ARMMCTargetDesc.cpp + ARMMCAsmInfo.cpp + ) + +# Hack: we need to include 'main' target directory to grab private headers +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BINARY_DIR}/..) diff --git a/lib/Target/ARM/MCTargetDesc/Makefile b/lib/Target/ARM/MCTargetDesc/Makefile new file mode 100644 index 000000000000..448ed9df2bff --- /dev/null +++ b/lib/Target/ARM/MCTargetDesc/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/ARM/TargetDesc/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +LIBRARYNAME = LLVMARMDesc + +# Hack: we need to include 'main' target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/ARM/MLxExpansionPass.cpp b/lib/Target/ARM/MLxExpansionPass.cpp index f6d024232eae..2df00538b39f 100644 --- a/lib/Target/ARM/MLxExpansionPass.cpp +++ b/lib/Target/ARM/MLxExpansionPass.cpp @@ -137,11 +137,11 @@ unsigned MLxExpansion::getDefReg(MachineInstr *MI) const { bool MLxExpansion::hasRAWHazard(unsigned Reg, MachineInstr *MI) const { // FIXME: Detect integer instructions properly. - const TargetInstrDesc &TID = MI->getDesc(); - unsigned Domain = TID.TSFlags & ARMII::DomainMask; - if (TID.mayStore()) + const MCInstrDesc &MCID = MI->getDesc(); + unsigned Domain = MCID.TSFlags & ARMII::DomainMask; + if (MCID.mayStore()) return false; - unsigned Opcode = TID.getOpcode(); + unsigned Opcode = MCID.getOpcode(); if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD) return false; if ((Domain & ARMII::DomainVFP) || (Domain & ARMII::DomainNEON)) @@ -218,18 +218,18 @@ MLxExpansion::ExpandFPMLxInstruction(MachineBasicBlock &MBB, MachineInstr *MI, ARMCC::CondCodes Pred = (ARMCC::CondCodes)MI->getOperand(NextOp).getImm(); unsigned PredReg = MI->getOperand(++NextOp).getReg(); - const TargetInstrDesc &TID1 = TII->get(MulOpc); - const TargetInstrDesc &TID2 = TII->get(AddSubOpc); - unsigned TmpReg = MRI->createVirtualRegister(TID1.getRegClass(0, TRI)); + const MCInstrDesc &MCID1 = TII->get(MulOpc); + const MCInstrDesc &MCID2 = TII->get(AddSubOpc); + unsigned TmpReg = MRI->createVirtualRegister(TII->getRegClass(MCID1, 0, TRI)); - MachineInstrBuilder MIB = BuildMI(MBB, *MI, MI->getDebugLoc(), TID1, TmpReg) + MachineInstrBuilder MIB = BuildMI(MBB, *MI, MI->getDebugLoc(), MCID1, TmpReg) .addReg(Src1Reg, getKillRegState(Src1Kill)) .addReg(Src2Reg, getKillRegState(Src2Kill)); if (HasLane) MIB.addImm(LaneImm); MIB.addImm(Pred).addReg(PredReg); - MIB = BuildMI(MBB, *MI, MI->getDebugLoc(), TID2) + MIB = BuildMI(MBB, *MI, MI->getDebugLoc(), MCID2) .addReg(DstReg, getDefRegState(true) | getDeadRegState(DstDead)); if (NegAcc) { @@ -273,15 +273,15 @@ bool MLxExpansion::ExpandFPMLxInstructions(MachineBasicBlock &MBB) { continue; } - const TargetInstrDesc &TID = MI->getDesc(); - if (TID.isBarrier()) { + const MCInstrDesc &MCID = MI->getDesc(); + if (MCID.isBarrier()) { clearStack(); Skip = 0; ++MII; continue; } - unsigned Domain = TID.TSFlags & ARMII::DomainMask; + unsigned Domain = MCID.TSFlags & ARMII::DomainMask; if (Domain == ARMII::DomainGeneral) { if (++Skip == 2) // Assume dual issues of non-VFP / NEON instructions. @@ -291,7 +291,7 @@ bool MLxExpansion::ExpandFPMLxInstructions(MachineBasicBlock &MBB) { unsigned MulOpc, AddSubOpc; bool NegAcc, HasLane; - if (!TII->isFpMLxInstruction(TID.getOpcode(), + if (!TII->isFpMLxInstruction(MCID.getOpcode(), MulOpc, AddSubOpc, NegAcc, HasLane) || !FindMLxHazard(MI)) pushStack(MI); diff --git a/lib/Target/ARM/Makefile b/lib/Target/ARM/Makefile index 65a6494986fe..eb8c60354476 100644 --- a/lib/Target/ARM/Makefile +++ b/lib/Target/ARM/Makefile @@ -12,14 +12,14 @@ LIBRARYNAME = LLVMARMCodeGen TARGET = ARM # Make sure that tblgen is run, first thing. -BUILT_SOURCES = ARMGenRegisterInfo.h.inc ARMGenRegisterNames.inc \ - ARMGenRegisterInfo.inc ARMGenInstrNames.inc \ - ARMGenInstrInfo.inc ARMGenAsmWriter.inc ARMGenAsmMatcher.inc \ - ARMGenDAGISel.inc ARMGenSubtarget.inc \ +BUILT_SOURCES = ARMGenRegisterInfo.inc ARMGenInstrInfo.inc \ + ARMGenAsmWriter.inc ARMGenAsmMatcher.inc \ + ARMGenDAGISel.inc ARMGenSubtargetInfo.inc \ ARMGenCodeEmitter.inc ARMGenCallingConv.inc \ ARMGenDecoderTables.inc ARMGenEDInfo.inc \ - ARMGenFastISel.inc ARMGenMCCodeEmitter.inc + ARMGenFastISel.inc ARMGenMCCodeEmitter.inc \ + ARMGenMCPseudoLowering.inc -DIRS = InstPrinter AsmParser Disassembler TargetInfo +DIRS = InstPrinter AsmParser Disassembler TargetInfo MCTargetDesc include $(LEVEL)/Makefile.common diff --git a/lib/Target/ARM/NEONMoveFix.cpp b/lib/Target/ARM/NEONMoveFix.cpp index 965665c2821a..c85d1e99705a 100644 --- a/lib/Target/ARM/NEONMoveFix.cpp +++ b/lib/Target/ARM/NEONMoveFix.cpp @@ -77,7 +77,7 @@ bool NEONMoveFixPass::InsertMoves(MachineBasicBlock &MBB) { } if (inNEONDomain(Domain, isA8)) { - // Convert VMOVD to VMOVDneon + // Convert VMOVD to VORRd unsigned DestReg = MI->getOperand(0).getReg(); DEBUG({errs() << "vmov convert: "; MI->dump();}); @@ -88,7 +88,8 @@ bool NEONMoveFixPass::InsertMoves(MachineBasicBlock &MBB) { // - The imp-defs / imp-uses are superregs only, we don't care about // them. AddDefaultPred(BuildMI(MBB, *MI, MI->getDebugLoc(), - TII->get(ARM::VMOVDneon), DestReg).addReg(SrcReg)); + TII->get(ARM::VORRd), DestReg) + .addReg(SrcReg).addReg(SrcReg)); MBB.erase(MI); MachineBasicBlock::iterator I = prior(NextMII); MI = &*I; diff --git a/lib/Target/ARM/README.txt b/lib/Target/ARM/README.txt index 8ba9a27e95c8..2f6842e8cb60 100644 --- a/lib/Target/ARM/README.txt +++ b/lib/Target/ARM/README.txt @@ -681,3 +681,21 @@ is compiled and optimized to: str r1, [r0] //===---------------------------------------------------------------------===// + +Improve codegen for select's: +if (x != 0) x = 1 +if (x == 1) x = 1 + +ARM codegen used to look like this: + mov r1, r0 + cmp r1, #1 + mov r0, #0 + moveq r0, #1 + +The naive lowering select between two different values. It should recognize the +test is equality test so it's more a conditional move rather than a select: + cmp r0, #1 + movne r0, #0 + +Currently this is a ARM specific dag combine. We probably should make it into a +target-neutral one. diff --git a/lib/Target/ARM/Thumb1FrameLowering.cpp b/lib/Target/ARM/Thumb1FrameLowering.cpp index dee3d278203f..c258870e48a5 100644 --- a/lib/Target/ARM/Thumb1FrameLowering.cpp +++ b/lib/Target/ARM/Thumb1FrameLowering.cpp @@ -136,8 +136,8 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF) const { BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), FramePtr) .addFrameIndex(FramePtrSpillFI).addImm(0) .setMIFlags(MachineInstr::FrameSetup); - if (NumBytes > 7) - // If offset is > 7 then sp cannot be adjusted in a single instruction, + if (NumBytes > 508) + // If offset is > 508 then sp cannot be adjusted in a single instruction, // try restoring from fp instead. AFI->setShouldRestoreSPFromFP(true); } @@ -160,7 +160,8 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF) const { // will be allocated after this, so we can still use the base pointer // to reference locals. if (RegInfo->hasBasePointer(MF)) - BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), BasePtr).addReg(ARM::SP); + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), BasePtr) + .addReg(ARM::SP)); // If the frame has variable sized objects then the epilogue must restore // the sp from fp. We can assume there's an FP here since hasFP already @@ -177,7 +178,7 @@ static bool isCalleeSavedRegister(unsigned Reg, const unsigned *CSRegs) { } static bool isCSRestore(MachineInstr *MI, const unsigned *CSRegs) { - if (MI->getOpcode() == ARM::tRestore && + if (MI->getOpcode() == ARM::tLDRspi && MI->getOperand(1).isFI() && isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs)) return true; @@ -239,11 +240,13 @@ void Thumb1FrameLowering::emitEpilogue(MachineFunction &MF, "No scratch register to restore SP from FP!"); emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::R4, FramePtr, -NumBytes, TII, *RegInfo); - BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP) - .addReg(ARM::R4); + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), + ARM::SP) + .addReg(ARM::R4)); } else - BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP) - .addReg(FramePtr); + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), + ARM::SP) + .addReg(FramePtr)); } else { if (MBBI->getOpcode() == ARM::tBX_RET && &MBB.front() != MBBI && @@ -270,8 +273,8 @@ void Thumb1FrameLowering::emitEpilogue(MachineFunction &MF, emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, VARegSaveSize); - BuildMI(MBB, MBBI, dl, TII.get(ARM::tBX_RET_vararg)) - .addReg(ARM::R3, RegState::Kill); + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tBX_RET_vararg)) + .addReg(ARM::R3, RegState::Kill)); // erase the old tBX_RET instruction MBB.erase(MBBI); } diff --git a/lib/Target/ARM/Thumb1InstrInfo.cpp b/lib/Target/ARM/Thumb1InstrInfo.cpp index 3fbb43340c3f..218311d78d30 100644 --- a/lib/Target/ARM/Thumb1InstrInfo.cpp +++ b/lib/Target/ARM/Thumb1InstrInfo.cpp @@ -13,7 +13,6 @@ #include "Thumb1InstrInfo.h" #include "ARM.h" -#include "ARMGenInstrInfo.inc" #include "ARMMachineFunctionInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -37,18 +36,8 @@ void Thumb1InstrInfo::copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const { - bool tDest = ARM::tGPRRegClass.contains(DestReg); - bool tSrc = ARM::tGPRRegClass.contains(SrcReg); - unsigned Opc = ARM::tMOVgpr2gpr; - if (tDest && tSrc) - Opc = ARM::tMOVr; - else if (tSrc) - Opc = ARM::tMOVtgpr2gpr; - else if (tDest) - Opc = ARM::tMOVgpr2tgpr; - - BuildMI(MBB, I, DL, get(Opc), DestReg) - .addReg(SrcReg, getKillRegState(KillSrc)); + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc))); assert(ARM::GPRRegClass.contains(DestReg, SrcReg) && "Thumb1 can only copy GPR registers"); } @@ -76,7 +65,7 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MachineMemOperand::MOStore, MFI.getObjectSize(FI), MFI.getObjectAlignment(FI)); - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tSpill)) + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tSTRspi)) .addReg(SrcReg, getKillRegState(isKill)) .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); } @@ -105,7 +94,7 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MachineMemOperand::MOLoad, MFI.getObjectSize(FI), MFI.getObjectAlignment(FI)); - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tRestore), DestReg) + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tLDRspi), DestReg) .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); } } diff --git a/lib/Target/ARM/Thumb1RegisterInfo.cpp b/lib/Target/ARM/Thumb1RegisterInfo.cpp index 6bf565068e4a..4eb0b6c93e1d 100644 --- a/lib/Target/ARM/Thumb1RegisterInfo.cpp +++ b/lib/Target/ARM/Thumb1RegisterInfo.cpp @@ -239,13 +239,13 @@ void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB, unsigned Chunk = (1 << 3) - 1; unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; Bytes -= ThisVal; - const TargetInstrDesc &TID = TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3); + const MCInstrDesc &MCID = TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3); const MachineInstrBuilder MIB = - AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg).setMIFlags(MIFlags)); + AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg).setMIFlags(MIFlags)); AddDefaultPred(MIB.addReg(BaseReg, RegState::Kill).addImm(ThisVal)); } else { - BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg) - .addReg(BaseReg, RegState::Kill) + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg) + .addReg(BaseReg, RegState::Kill)) .setMIFlags(MIFlags); } BaseReg = DestReg; @@ -291,8 +291,8 @@ void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB, } if (ExtraOpc) { - const TargetInstrDesc &TID = TII.get(ExtraOpc); - AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg)) + const MCInstrDesc &MCID = TII.get(ExtraOpc); + AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg)) .addReg(DestReg, RegState::Kill) .addImm(((unsigned)NumBytes) & 3) .setMIFlags(MIFlags)); @@ -360,8 +360,8 @@ static void emitThumbConstant(MachineBasicBlock &MBB, if (Imm > 0) emitThumbRegPlusImmediate(MBB, MBBI, dl, DestReg, DestReg, Imm, TII, MRI); if (isSub) { - const TargetInstrDesc &TID = TII.get(ARM::tRSB); - AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg)) + const MCInstrDesc &MCID = TII.get(ARM::tRSB); + AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg)) .addReg(DestReg, RegState::Kill)); } } @@ -377,11 +377,9 @@ static void removeOperands(MachineInstr &MI, unsigned i) { static unsigned convertToNonSPOpcode(unsigned Opcode) { switch (Opcode) { case ARM::tLDRspi: - case ARM::tRestore: // FIXME: Should this opcode be here? return ARM::tLDRi; case ARM::tSTRspi: - case ARM::tSpill: // FIXME: Should this opcode be here? return ARM::tSTRi; } @@ -396,7 +394,7 @@ rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx, MachineBasicBlock &MBB = *MI.getParent(); DebugLoc dl = MI.getDebugLoc(); unsigned Opcode = MI.getOpcode(); - const TargetInstrDesc &Desc = MI.getDesc(); + const MCInstrDesc &Desc = MI.getDesc(); unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); if (Opcode == ARM::tADDrSPi) { @@ -419,13 +417,12 @@ rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx, unsigned PredReg; if (Offset == 0 && getInstrPredicate(&MI, PredReg) == ARMCC::AL) { // Turn it into a move. - MI.setDesc(TII.get(ARM::tMOVgpr2tgpr)); + MI.setDesc(TII.get(ARM::tMOVr)); MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); - // Remove offset and remaining explicit predicate operands. - do MI.RemoveOperand(FrameRegIdx+1); - while (MI.getNumOperands() > FrameRegIdx+1 && - (!MI.getOperand(FrameRegIdx+1).isReg() || - !MI.getOperand(FrameRegIdx+1).isImm())); + // Remove offset and add predicate operands. + MI.RemoveOperand(FrameRegIdx+1); + MachineInstrBuilder MIB(&MI); + AddDefaultPred(MIB); return true; } @@ -524,7 +521,7 @@ rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx, // If this is a thumb spill / restore, we will be using a constpool load to // materialize the offset. - if (Opcode == ARM::tRestore || Opcode == ARM::tSpill) { + if (Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) { ImmOp.ChangeToImmediate(0); } else { // Otherwise, it didn't fit. Pull in what we can to simplify the immed. @@ -567,8 +564,9 @@ Thumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB, // the function, the offset will be negative. Use R12 instead since that's // a call clobbered register that we know won't be used in Thumb1 mode. DebugLoc DL; - BuildMI(MBB, I, DL, TII.get(ARM::tMOVtgpr2gpr)). - addReg(ARM::R12, RegState::Define).addReg(Reg, RegState::Kill); + AddDefaultPred(BuildMI(MBB, I, DL, TII.get(ARM::tMOVr)) + .addReg(ARM::R12, RegState::Define) + .addReg(Reg, RegState::Kill)); // The UseMI is where we would like to restore the register. If there's // interference with R12 before then, however, we'll need to restore it @@ -591,8 +589,8 @@ Thumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB, } } // Restore the register from R12 - BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVgpr2tgpr)). - addReg(Reg, RegState::Define).addReg(ARM::R12, RegState::Kill); + AddDefaultPred(BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVr)). + addReg(Reg, RegState::Define).addReg(ARM::R12, RegState::Kill)); return true; } @@ -653,7 +651,7 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, assert(Offset && "This code isn't needed if offset already handled!"); unsigned Opcode = MI.getOpcode(); - const TargetInstrDesc &Desc = MI.getDesc(); + const MCInstrDesc &Desc = MI.getDesc(); // Remove predicate first. int PIdx = MI.findFirstPredOperandIdx(); @@ -664,7 +662,7 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, // Use the destination register to materialize sp + offset. unsigned TmpReg = MI.getOperand(0).getReg(); bool UseRR = false; - if (Opcode == ARM::tRestore) { + if (Opcode == ARM::tLDRspi) { if (FrameReg == ARM::SP) emitThumbRegPlusImmInReg(MBB, II, dl, TmpReg, FrameReg, Offset, false, TII, *this); @@ -687,7 +685,7 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, VReg = MF.getRegInfo().createVirtualRegister(ARM::tGPRRegisterClass); bool UseRR = false; - if (Opcode == ARM::tSpill) { + if (Opcode == ARM::tSTRspi) { if (FrameReg == ARM::SP) emitThumbRegPlusImmInReg(MBB, II, dl, VReg, FrameReg, Offset, false, TII, *this); diff --git a/lib/Target/ARM/Thumb2ITBlockPass.cpp b/lib/Target/ARM/Thumb2ITBlockPass.cpp index 45e693744b80..360ec009e201 100644 --- a/lib/Target/ARM/Thumb2ITBlockPass.cpp +++ b/lib/Target/ARM/Thumb2ITBlockPass.cpp @@ -98,9 +98,6 @@ static bool isCopy(MachineInstr *MI) { case ARM::MOVr: case ARM::MOVr_TC: case ARM::tMOVr: - case ARM::tMOVgpr2tgpr: - case ARM::tMOVtgpr2gpr: - case ARM::tMOVgpr2gpr: case ARM::t2MOVr: return true; } diff --git a/lib/Target/ARM/Thumb2InstrInfo.cpp b/lib/Target/ARM/Thumb2InstrInfo.cpp index d169dbb7f197..51b56aaeb008 100644 --- a/lib/Target/ARM/Thumb2InstrInfo.cpp +++ b/lib/Target/ARM/Thumb2InstrInfo.cpp @@ -15,7 +15,6 @@ #include "ARM.h" #include "ARMConstantPoolValue.h" #include "ARMAddressingModes.h" -#include "ARMGenInstrInfo.inc" #include "ARMMachineFunctionInfo.h" #include "Thumb2InstrInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -113,18 +112,8 @@ void Thumb2InstrInfo::copyPhysReg(MachineBasicBlock &MBB, if (!ARM::GPRRegClass.contains(DestReg, SrcReg)) return ARMBaseInstrInfo::copyPhysReg(MBB, I, DL, DestReg, SrcReg, KillSrc); - bool tDest = ARM::tGPRRegClass.contains(DestReg); - bool tSrc = ARM::tGPRRegClass.contains(SrcReg); - unsigned Opc = ARM::tMOVgpr2gpr; - if (tDest && tSrc) - Opc = ARM::tMOVr; - else if (tSrc) - Opc = ARM::tMOVtgpr2gpr; - else if (tDest) - Opc = ARM::tMOVgpr2tgpr; - - BuildMI(MBB, I, DL, get(Opc), DestReg) - .addReg(SrcReg, getKillRegState(KillSrc)); + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc))); } void Thumb2InstrInfo:: @@ -232,8 +221,8 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB, unsigned Opc = 0; if (DestReg == ARM::SP && BaseReg != ARM::SP) { // mov sp, rn. Note t2MOVr cannot be used. - BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr),DestReg) - .addReg(BaseReg).setMIFlags(MIFlags); + AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr),DestReg) + .addReg(BaseReg).setMIFlags(MIFlags)); BaseReg = ARM::SP; continue; } @@ -252,7 +241,7 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB, } // sub rd, sp, so_imm - Opc = isSub ? ARM::t2SUBrSPi : ARM::t2ADDrSPi; + Opc = isSub ? ARM::t2SUBri : ARM::t2ADDri; if (ARM_AM::getT2SOImmVal(NumBytes) != -1) { NumBytes = 0; } else { @@ -396,7 +385,7 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, unsigned FrameReg, int &Offset, const ARMBaseInstrInfo &TII) { unsigned Opcode = MI.getOpcode(); - const TargetInstrDesc &Desc = MI.getDesc(); + const MCInstrDesc &Desc = MI.getDesc(); unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); bool isSub = false; @@ -410,25 +399,24 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, unsigned PredReg; if (Offset == 0 && getInstrPredicate(&MI, PredReg) == ARMCC::AL) { // Turn it into a move. - MI.setDesc(TII.get(ARM::tMOVgpr2gpr)); + MI.setDesc(TII.get(ARM::tMOVr)); MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); // Remove offset and remaining explicit predicate operands. do MI.RemoveOperand(FrameRegIdx+1); - while (MI.getNumOperands() > FrameRegIdx+1 && - (!MI.getOperand(FrameRegIdx+1).isReg() || - !MI.getOperand(FrameRegIdx+1).isImm())); + while (MI.getNumOperands() > FrameRegIdx+1); + MachineInstrBuilder MIB(&MI); + AddDefaultPred(MIB); return true; } - bool isSP = FrameReg == ARM::SP; bool HasCCOut = Opcode != ARM::t2ADDri12; if (Offset < 0) { Offset = -Offset; isSub = true; - MI.setDesc(TII.get(isSP ? ARM::t2SUBrSPi : ARM::t2SUBri)); + MI.setDesc(TII.get(ARM::t2SUBri)); } else { - MI.setDesc(TII.get(isSP ? ARM::t2ADDrSPi : ARM::t2ADDri)); + MI.setDesc(TII.get(ARM::t2ADDri)); } // Common case: small offset, fits into instruction. @@ -444,9 +432,7 @@ bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, // Another common case: imm12. if (Offset < 4096 && (!HasCCOut || MI.getOperand(MI.getNumOperands()-1).getReg() == 0)) { - unsigned NewOpc = isSP - ? (isSub ? ARM::t2SUBrSPi12 : ARM::t2ADDrSPi12) - : (isSub ? ARM::t2SUBri12 : ARM::t2ADDri12); + unsigned NewOpc = isSub ? ARM::t2SUBri12 : ARM::t2ADDri12; MI.setDesc(TII.get(NewOpc)); MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset); @@ -579,8 +565,7 @@ void Thumb2InstrInfo::scheduleTwoAddrSource(MachineInstr *SrcMI, MachineInstr *UseMI, const TargetRegisterInfo &TRI) const { - if (SrcMI->getOpcode() != ARM::tMOVgpr2gpr || - SrcMI->getOperand(1).isKill()) + if (SrcMI->getOpcode() != ARM::tMOVr || SrcMI->getOperand(1).isKill()) return; unsigned PredReg = 0; diff --git a/lib/Target/ARM/Thumb2SizeReduction.cpp b/lib/Target/ARM/Thumb2SizeReduction.cpp index ce2e9663fb74..c741a6e8a5b7 100644 --- a/lib/Target/ARM/Thumb2SizeReduction.cpp +++ b/lib/Target/ARM/Thumb2SizeReduction.cpp @@ -57,10 +57,8 @@ namespace { static const ReduceEntry ReduceTable[] = { // Wide, Narrow1, Narrow2, imm1,imm2, lo1, lo2, P/C, PF, S { ARM::t2ADCrr, 0, ARM::tADC, 0, 0, 0, 1, 0,0, 0,0 }, - { ARM::t2ADDri, ARM::tADDi3, ARM::tADDi8, 3, 8, 1, 1, 0,0, 0,0 }, + { ARM::t2ADDri, ARM::tADDi3, ARM::tADDi8, 3, 8, 1, 1, 0,0, 0,1 }, { ARM::t2ADDrr, ARM::tADDrr, ARM::tADDhirr, 0, 0, 1, 0, 0,1, 0,0 }, - // Note: immediate scale is 4. - { ARM::t2ADDrSPi,ARM::tADDrSPi,0, 8, 0, 1, 0, 1,0, 0,1 }, { ARM::t2ADDSri,ARM::tADDi3, ARM::tADDi8, 3, 8, 1, 1, 2,2, 0,1 }, { ARM::t2ADDSrr,ARM::tADDrr, 0, 0, 0, 1, 0, 2,0, 0,1 }, { ARM::t2ANDrr, 0, ARM::tAND, 0, 0, 0, 1, 0,0, 1,0 }, @@ -84,9 +82,7 @@ namespace { { ARM::t2MOVi, ARM::tMOVi8, 0, 8, 0, 1, 0, 0,0, 0,0 }, { ARM::t2MOVi16,ARM::tMOVi8, 0, 8, 0, 1, 0, 0,0, 0,1 }, // FIXME: Do we need the 16-bit 'S' variant? - { ARM::t2MOVr,ARM::tMOVgpr2gpr,0, 0, 0, 0, 0, 1,0, 0,0 }, - { ARM::t2MOVCCr,0, ARM::tMOVCCr, 0, 0, 0, 0, 0,1, 0,0 }, - { ARM::t2MOVCCi,0, ARM::tMOVCCi, 0, 8, 0, 1, 0,1, 0,0 }, + { ARM::t2MOVr,ARM::tMOVr, 0, 0, 0, 0, 0, 1,0, 0,0 }, { ARM::t2MUL, 0, ARM::tMUL, 0, 0, 0, 1, 0,0, 1,0 }, { ARM::t2MVNr, ARM::tMVN, 0, 0, 0, 1, 0, 0,0, 0,0 }, { ARM::t2ORRrr, 0, ARM::tORR, 0, 0, 0, 1, 0,0, 1,0 }, @@ -189,8 +185,8 @@ Thumb2SizeReduce::Thumb2SizeReduce() : MachineFunctionPass(ID) { } } -static bool HasImplicitCPSRDef(const TargetInstrDesc &TID) { - for (const unsigned *Regs = TID.ImplicitDefs; *Regs; ++Regs) +static bool HasImplicitCPSRDef(const MCInstrDesc &MCID) { + for (const unsigned *Regs = MCID.ImplicitDefs; *Regs; ++Regs) if (*Regs == ARM::CPSR) return true; return false; @@ -291,7 +287,7 @@ static bool VerifyLowRegs(MachineInstr *MI) { Opc == ARM::t2LDMDB || Opc == ARM::t2LDMIA_UPD || Opc == ARM::t2LDMDB_UPD); bool isLROk = (Opc == ARM::t2STMIA_UPD || Opc == ARM::t2STMDB_UPD); - bool isSPOk = isPCOk || isLROk || (Opc == ARM::t2ADDrSPi); + bool isSPOk = isPCOk || isLROk; for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); if (!MO.isReg() || MO.isImplicit()) @@ -481,14 +477,54 @@ bool Thumb2SizeReduce::ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI, const ReduceEntry &Entry, bool LiveCPSR, MachineInstr *CPSRDef) { + unsigned Opc = MI->getOpcode(); + if (Opc == ARM::t2ADDri) { + // If the source register is SP, try to reduce to tADDrSPi, otherwise + // it's a normal reduce. + if (MI->getOperand(1).getReg() != ARM::SP) { + if (ReduceTo2Addr(MBB, MI, Entry, LiveCPSR, CPSRDef)) + return true; + return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, CPSRDef); + } + // Try to reduce to tADDrSPi. + unsigned Imm = MI->getOperand(2).getImm(); + // The immediate must be in range, the destination register must be a low + // reg, the predicate must be "always" and the condition flags must not + // be being set. + if (Imm & 3 || Imm > 1020) + return false; + if (!isARMLowRegister(MI->getOperand(0).getReg())) + return false; + if (MI->getOperand(3).getImm() != ARMCC::AL) + return false; + const MCInstrDesc &MCID = MI->getDesc(); + if (MCID.hasOptionalDef() && + MI->getOperand(MCID.getNumOperands()-1).getReg() == ARM::CPSR) + return false; + + MachineInstrBuilder MIB = BuildMI(MBB, *MI, MI->getDebugLoc(), + TII->get(ARM::tADDrSPi)) + .addOperand(MI->getOperand(0)) + .addOperand(MI->getOperand(1)) + .addImm(Imm / 4); // The tADDrSPi has an implied scale by four. + + // Transfer MI flags. + MIB.setMIFlags(MI->getFlags()); + + DEBUG(errs() << "Converted 32-bit: " << *MI << " to 16-bit: " <<*MIB); + + MBB.erase(MI); + ++NumNarrows; + return true; + } + if (Entry.LowRegs1 && !VerifyLowRegs(MI)) return false; - const TargetInstrDesc &TID = MI->getDesc(); - if (TID.mayLoad() || TID.mayStore()) + const MCInstrDesc &MCID = MI->getDesc(); + if (MCID.mayLoad() || MCID.mayStore()) return ReduceLoadStore(MBB, MI, Entry); - unsigned Opc = MI->getOpcode(); switch (Opc) { default: break; case ARM::t2ADDSri: @@ -531,13 +567,6 @@ Thumb2SizeReduce::ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI, return true; return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, CPSRDef); } - case ARM::t2ADDrSPi: { - static const ReduceEntry NarrowEntry = - { ARM::t2ADDrSPi,ARM::tADDspi, 0, 7, 0, 1, 0, 1, 0, 0,1 }; - if (MI->getOperand(0).getReg() == ARM::SP) - return ReduceToNarrow(MBB, MI, NarrowEntry, LiveCPSR, CPSRDef); - return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, CPSRDef); - } } return false; } @@ -576,23 +605,23 @@ Thumb2SizeReduce::ReduceTo2Addr(MachineBasicBlock &MBB, MachineInstr *MI, } // Check if it's possible / necessary to transfer the predicate. - const TargetInstrDesc &NewTID = TII->get(Entry.NarrowOpc2); + const MCInstrDesc &NewMCID = TII->get(Entry.NarrowOpc2); unsigned PredReg = 0; ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg); bool SkipPred = false; if (Pred != ARMCC::AL) { - if (!NewTID.isPredicable()) + if (!NewMCID.isPredicable()) // Can't transfer predicate, fail. return false; } else { - SkipPred = !NewTID.isPredicable(); + SkipPred = !NewMCID.isPredicable(); } bool HasCC = false; bool CCDead = false; - const TargetInstrDesc &TID = MI->getDesc(); - if (TID.hasOptionalDef()) { - unsigned NumOps = TID.getNumOperands(); + const MCInstrDesc &MCID = MI->getDesc(); + if (MCID.hasOptionalDef()) { + unsigned NumOps = MCID.getNumOperands(); HasCC = (MI->getOperand(NumOps-1).getReg() == ARM::CPSR); if (HasCC && MI->getOperand(NumOps-1).isDead()) CCDead = true; @@ -602,15 +631,15 @@ Thumb2SizeReduce::ReduceTo2Addr(MachineBasicBlock &MBB, MachineInstr *MI, // Avoid adding a false dependency on partial flag update by some 16-bit // instructions which has the 's' bit set. - if (Entry.PartFlag && NewTID.hasOptionalDef() && HasCC && + if (Entry.PartFlag && NewMCID.hasOptionalDef() && HasCC && canAddPseudoFlagDep(CPSRDef, MI)) return false; // Add the 16-bit instruction. DebugLoc dl = MI->getDebugLoc(); - MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, NewTID); + MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, NewMCID); MIB.addOperand(MI->getOperand(0)); - if (NewTID.hasOptionalDef()) { + if (NewMCID.hasOptionalDef()) { if (HasCC) AddDefaultT1CC(MIB, CCDead); else @@ -618,11 +647,11 @@ Thumb2SizeReduce::ReduceTo2Addr(MachineBasicBlock &MBB, MachineInstr *MI, } // Transfer the rest of operands. - unsigned NumOps = TID.getNumOperands(); + unsigned NumOps = MCID.getNumOperands(); for (unsigned i = 1, e = MI->getNumOperands(); i != e; ++i) { - if (i < NumOps && TID.OpInfo[i].isOptionalDef()) + if (i < NumOps && MCID.OpInfo[i].isOptionalDef()) continue; - if (SkipPred && TID.OpInfo[i].isPredicate()) + if (SkipPred && MCID.OpInfo[i].isPredicate()) continue; MIB.addOperand(MI->getOperand(i)); } @@ -645,47 +674,44 @@ Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI, return false; unsigned Limit = ~0U; - unsigned Scale = (Entry.WideOpc == ARM::t2ADDrSPi) ? 4 : 1; if (Entry.Imm1Limit) - Limit = ((1 << Entry.Imm1Limit) - 1) * Scale; + Limit = (1 << Entry.Imm1Limit) - 1; - const TargetInstrDesc &TID = MI->getDesc(); - for (unsigned i = 0, e = TID.getNumOperands(); i != e; ++i) { - if (TID.OpInfo[i].isPredicate()) + const MCInstrDesc &MCID = MI->getDesc(); + for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i) { + if (MCID.OpInfo[i].isPredicate()) continue; const MachineOperand &MO = MI->getOperand(i); if (MO.isReg()) { unsigned Reg = MO.getReg(); if (!Reg || Reg == ARM::CPSR) continue; - if (Entry.WideOpc == ARM::t2ADDrSPi && Reg == ARM::SP) - continue; if (Entry.LowRegs1 && !isARMLowRegister(Reg)) return false; } else if (MO.isImm() && - !TID.OpInfo[i].isPredicate()) { - if (((unsigned)MO.getImm()) > Limit || (MO.getImm() & (Scale-1)) != 0) + !MCID.OpInfo[i].isPredicate()) { + if (((unsigned)MO.getImm()) > Limit) return false; } } // Check if it's possible / necessary to transfer the predicate. - const TargetInstrDesc &NewTID = TII->get(Entry.NarrowOpc1); + const MCInstrDesc &NewMCID = TII->get(Entry.NarrowOpc1); unsigned PredReg = 0; ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg); bool SkipPred = false; if (Pred != ARMCC::AL) { - if (!NewTID.isPredicable()) + if (!NewMCID.isPredicable()) // Can't transfer predicate, fail. return false; } else { - SkipPred = !NewTID.isPredicable(); + SkipPred = !NewMCID.isPredicable(); } bool HasCC = false; bool CCDead = false; - if (TID.hasOptionalDef()) { - unsigned NumOps = TID.getNumOperands(); + if (MCID.hasOptionalDef()) { + unsigned NumOps = MCID.getNumOperands(); HasCC = (MI->getOperand(NumOps-1).getReg() == ARM::CPSR); if (HasCC && MI->getOperand(NumOps-1).isDead()) CCDead = true; @@ -695,15 +721,15 @@ Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI, // Avoid adding a false dependency on partial flag update by some 16-bit // instructions which has the 's' bit set. - if (Entry.PartFlag && NewTID.hasOptionalDef() && HasCC && + if (Entry.PartFlag && NewMCID.hasOptionalDef() && HasCC && canAddPseudoFlagDep(CPSRDef, MI)) return false; // Add the 16-bit instruction. DebugLoc dl = MI->getDebugLoc(); - MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, NewTID); + MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, NewMCID); MIB.addOperand(MI->getOperand(0)); - if (NewTID.hasOptionalDef()) { + if (NewMCID.hasOptionalDef()) { if (HasCC) AddDefaultT1CC(MIB, CCDead); else @@ -711,29 +737,25 @@ Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI, } // Transfer the rest of operands. - unsigned NumOps = TID.getNumOperands(); + unsigned NumOps = MCID.getNumOperands(); for (unsigned i = 1, e = MI->getNumOperands(); i != e; ++i) { - if (i < NumOps && TID.OpInfo[i].isOptionalDef()) + if (i < NumOps && MCID.OpInfo[i].isOptionalDef()) continue; - if ((TID.getOpcode() == ARM::t2RSBSri || - TID.getOpcode() == ARM::t2RSBri) && i == 2) + if ((MCID.getOpcode() == ARM::t2RSBSri || + MCID.getOpcode() == ARM::t2RSBri) && i == 2) // Skip the zero immediate operand, it's now implicit. continue; - bool isPred = (i < NumOps && TID.OpInfo[i].isPredicate()); + bool isPred = (i < NumOps && MCID.OpInfo[i].isPredicate()); if (SkipPred && isPred) continue; const MachineOperand &MO = MI->getOperand(i); - if (Scale > 1 && !isPred && MO.isImm()) - MIB.addImm(MO.getImm() / Scale); - else { - if (MO.isReg() && MO.isImplicit() && MO.getReg() == ARM::CPSR) - // Skip implicit def of CPSR. Either it's modeled as an optional - // def now or it's already an implicit def on the new instruction. - continue; - MIB.addOperand(MO); - } + if (MO.isReg() && MO.isImplicit() && MO.getReg() == ARM::CPSR) + // Skip implicit def of CPSR. Either it's modeled as an optional + // def now or it's already an implicit def on the new instruction. + continue; + MIB.addOperand(MO); } - if (!TID.isPredicable() && NewTID.isPredicable()) + if (!MCID.isPredicable() && NewMCID.isPredicable()) AddDefaultPred(MIB); // Transfer MI flags. diff --git a/lib/Target/Alpha/Alpha.h b/lib/Target/Alpha/Alpha.h index 2c359dade29b..6ffaf45f4ed1 100644 --- a/lib/Target/Alpha/Alpha.h +++ b/lib/Target/Alpha/Alpha.h @@ -15,6 +15,7 @@ #ifndef TARGET_ALPHA_H #define TARGET_ALPHA_H +#include "MCTargetDesc/AlphaMCTargetDesc.h" #include "llvm/Target/TargetMachine.h" namespace llvm { @@ -37,17 +38,6 @@ namespace llvm { FunctionPass *createAlphaLLRPPass(AlphaTargetMachine &tm); FunctionPass *createAlphaBranchSelectionPass(); - extern Target TheAlphaTarget; - } // end namespace llvm; -// Defines symbolic names for Alpha registers. This defines a mapping from -// register name to register number. -// -#include "AlphaGenRegisterNames.inc" - -// Defines symbolic names for the Alpha instructions. -// -#include "AlphaGenInstrNames.inc" - #endif diff --git a/lib/Target/Alpha/AlphaISelLowering.cpp b/lib/Target/Alpha/AlphaISelLowering.cpp index 0875cfd1c3c5..de003fb4c65e 100644 --- a/lib/Target/Alpha/AlphaISelLowering.cpp +++ b/lib/Target/Alpha/AlphaISelLowering.cpp @@ -122,6 +122,9 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) setOperationAction(ISD::FPOW , MVT::f32, Expand); setOperationAction(ISD::FPOW , MVT::f64, Expand); + setOperationAction(ISD::FMA, MVT::f64, Expand); + setOperationAction(ISD::FMA, MVT::f32, Expand); + setOperationAction(ISD::SETCC, MVT::f32, Promote); setOperationAction(ISD::BITCAST, MVT::f32, Promote); @@ -824,41 +827,24 @@ AlphaTargetLowering::getSingleConstraintMatchWeight( return weight; } -std::vector<unsigned> AlphaTargetLowering:: -getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const { +/// Given a register class constraint, like 'r', if this corresponds directly +/// to an LLVM register class, return a register of 0 and the register class +/// pointer. +std::pair<unsigned, const TargetRegisterClass*> AlphaTargetLowering:: +getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const +{ if (Constraint.size() == 1) { switch (Constraint[0]) { - default: break; // Unknown constriant letter - case 'f': - return make_vector<unsigned>(Alpha::F0 , Alpha::F1 , Alpha::F2 , - Alpha::F3 , Alpha::F4 , Alpha::F5 , - Alpha::F6 , Alpha::F7 , Alpha::F8 , - Alpha::F9 , Alpha::F10, Alpha::F11, - Alpha::F12, Alpha::F13, Alpha::F14, - Alpha::F15, Alpha::F16, Alpha::F17, - Alpha::F18, Alpha::F19, Alpha::F20, - Alpha::F21, Alpha::F22, Alpha::F23, - Alpha::F24, Alpha::F25, Alpha::F26, - Alpha::F27, Alpha::F28, Alpha::F29, - Alpha::F30, Alpha::F31, 0); case 'r': - return make_vector<unsigned>(Alpha::R0 , Alpha::R1 , Alpha::R2 , - Alpha::R3 , Alpha::R4 , Alpha::R5 , - Alpha::R6 , Alpha::R7 , Alpha::R8 , - Alpha::R9 , Alpha::R10, Alpha::R11, - Alpha::R12, Alpha::R13, Alpha::R14, - Alpha::R15, Alpha::R16, Alpha::R17, - Alpha::R18, Alpha::R19, Alpha::R20, - Alpha::R21, Alpha::R22, Alpha::R23, - Alpha::R24, Alpha::R25, Alpha::R26, - Alpha::R27, Alpha::R28, Alpha::R29, - Alpha::R30, Alpha::R31, 0); + return std::make_pair(0U, Alpha::GPRCRegisterClass); + case 'f': + return VT == MVT::f64 ? std::make_pair(0U, Alpha::F8RCRegisterClass) : + std::make_pair(0U, Alpha::F4RCRegisterClass); } } - - return std::vector<unsigned>(); + return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); } + //===----------------------------------------------------------------------===// // Other Lowering Code //===----------------------------------------------------------------------===// diff --git a/lib/Target/Alpha/AlphaISelLowering.h b/lib/Target/Alpha/AlphaISelLowering.h index d38c3145b19f..13383f4430f9 100644 --- a/lib/Target/Alpha/AlphaISelLowering.h +++ b/lib/Target/Alpha/AlphaISelLowering.h @@ -94,9 +94,9 @@ namespace llvm { ConstraintWeight getSingleConstraintMatchWeight( AsmOperandInfo &info, const char *constraint) const; - std::vector<unsigned> - getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const; + std::pair<unsigned, const TargetRegisterClass*> + getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const; MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr *MI, diff --git a/lib/Target/Alpha/AlphaInstrInfo.cpp b/lib/Target/Alpha/AlphaInstrInfo.cpp index 5a2f5610fdb4..4dcec8f31750 100644 --- a/lib/Target/Alpha/AlphaInstrInfo.cpp +++ b/lib/Target/Alpha/AlphaInstrInfo.cpp @@ -14,17 +14,21 @@ #include "Alpha.h" #include "AlphaInstrInfo.h" #include "AlphaMachineFunctionInfo.h" -#include "AlphaGenInstrInfo.inc" +#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetRegistry.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/Support/ErrorHandling.h" + +#define GET_INSTRINFO_CTOR +#include "AlphaGenInstrInfo.inc" using namespace llvm; AlphaInstrInfo::AlphaInstrInfo() - : TargetInstrInfoImpl(AlphaInsts, array_lengthof(AlphaInsts)), - RI(*this) { } + : AlphaGenInstrInfo(Alpha::ADJUSTSTACKDOWN, Alpha::ADJUSTSTACKUP), + RI(*this) { +} unsigned diff --git a/lib/Target/Alpha/AlphaInstrInfo.h b/lib/Target/Alpha/AlphaInstrInfo.h index ee6077a4a01a..337a85cdf22d 100644 --- a/lib/Target/Alpha/AlphaInstrInfo.h +++ b/lib/Target/Alpha/AlphaInstrInfo.h @@ -17,9 +17,12 @@ #include "llvm/Target/TargetInstrInfo.h" #include "AlphaRegisterInfo.h" +#define GET_INSTRINFO_HEADER +#include "AlphaGenInstrInfo.inc" + namespace llvm { -class AlphaInstrInfo : public TargetInstrInfoImpl { +class AlphaInstrInfo : public AlphaGenInstrInfo { const AlphaRegisterInfo RI; public: AlphaInstrInfo(); diff --git a/lib/Target/Alpha/AlphaRegisterInfo.cpp b/lib/Target/Alpha/AlphaRegisterInfo.cpp index d6c3809960aa..df8f157266e1 100644 --- a/lib/Target/Alpha/AlphaRegisterInfo.cpp +++ b/lib/Target/Alpha/AlphaRegisterInfo.cpp @@ -33,10 +33,14 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include <cstdlib> + +#define GET_REGINFO_TARGET_DESC +#include "AlphaGenRegisterInfo.inc" + using namespace llvm; AlphaRegisterInfo::AlphaRegisterInfo(const TargetInstrInfo &tii) - : AlphaGenRegisterInfo(Alpha::ADJUSTSTACKDOWN, Alpha::ADJUSTSTACKUP), + : AlphaGenRegisterInfo(), TII(tii) { } @@ -204,10 +208,8 @@ int AlphaRegisterInfo::getLLVMRegNum(unsigned DwarfRegNum, bool isEH) const { return -1; } -#include "AlphaGenRegisterInfo.inc" - std::string AlphaRegisterInfo::getPrettyName(unsigned reg) { - std::string s(RegisterDescriptors[reg].Name); + std::string s(AlphaRegDesc[reg].Name); return s; } diff --git a/lib/Target/Alpha/AlphaRegisterInfo.h b/lib/Target/Alpha/AlphaRegisterInfo.h index ffe6cf19e210..1072bf73f199 100644 --- a/lib/Target/Alpha/AlphaRegisterInfo.h +++ b/lib/Target/Alpha/AlphaRegisterInfo.h @@ -15,7 +15,9 @@ #define ALPHAREGISTERINFO_H #include "llvm/Target/TargetRegisterInfo.h" -#include "AlphaGenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "AlphaGenRegisterInfo.inc" namespace llvm { diff --git a/lib/Target/Alpha/AlphaRegisterInfo.td b/lib/Target/Alpha/AlphaRegisterInfo.td index d644f05f91ae..32120d750413 100644 --- a/lib/Target/Alpha/AlphaRegisterInfo.td +++ b/lib/Target/Alpha/AlphaRegisterInfo.td @@ -110,10 +110,10 @@ def F31 : FPR<31, "$f31">, DwarfRegNum<[64]>; // $28 is undefined after any and all calls /// Register classes -def GPRC : RegisterClass<"Alpha", [i64], 64, +def GPRC : RegisterClass<"Alpha", [i64], 64, (add // Volatile - [R0, R1, R2, R3, R4, R5, R6, R7, R8, R16, R17, R18, R19, R20, R21, R22, - R23, R24, R25, R28, + R0, R1, R2, R3, R4, R5, R6, R7, R8, R16, R17, R18, R19, R20, R21, R22, + R23, R24, R25, R28, //Special meaning, but volatile R27, //procedure address R26, //return address @@ -121,18 +121,13 @@ def GPRC : RegisterClass<"Alpha", [i64], 64, // Non-volatile R9, R10, R11, R12, R13, R14, // Don't allocate 15, 30, 31 - R15, R30, R31 ]>; //zero + R15, R30, R31)>; //zero -def F4RC : RegisterClass<"Alpha", [f32], 64, [F0, F1, +def F4RC : RegisterClass<"Alpha", [f32], 64, (add F0, F1, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, // Saved: F2, F3, F4, F5, F6, F7, F8, F9, - F31 ]>; //zero + F31)>; //zero -def F8RC : RegisterClass<"Alpha", [f64], 64, [F0, F1, - F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, - F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, - // Saved: - F2, F3, F4, F5, F6, F7, F8, F9, - F31 ]>; //zero +def F8RC : RegisterClass<"Alpha", [f64], 64, (add F4RC)>; diff --git a/lib/Target/Alpha/AlphaSubtarget.cpp b/lib/Target/Alpha/AlphaSubtarget.cpp index bda7104ab926..624a5e2ebd09 100644 --- a/lib/Target/Alpha/AlphaSubtarget.cpp +++ b/lib/Target/Alpha/AlphaSubtarget.cpp @@ -7,19 +7,30 @@ // //===----------------------------------------------------------------------===// // -// This file implements the Alpha specific subclass of TargetSubtarget. +// This file implements the Alpha specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #include "AlphaSubtarget.h" #include "Alpha.h" -#include "AlphaGenSubtarget.inc" +#include "llvm/Target/TargetRegistry.h" + +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "AlphaGenSubtargetInfo.inc" + using namespace llvm; -AlphaSubtarget::AlphaSubtarget(const std::string &TT, const std::string &FS) - : HasCT(false) { - std::string CPU = "generic"; +AlphaSubtarget::AlphaSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS) + : AlphaGenSubtargetInfo(TT, CPU, FS), HasCT(false) { + std::string CPUName = CPU; + if (CPUName.empty()) + CPUName = "generic"; // Parse features string. - ParseSubtargetFeatures(FS, CPU); + ParseSubtargetFeatures(CPUName, FS); + + // Initialize scheduling itinerary for the specified CPU. + InstrItins = getInstrItineraryForCPU(CPUName); } diff --git a/lib/Target/Alpha/AlphaSubtarget.h b/lib/Target/Alpha/AlphaSubtarget.h index f0eb93c6cba2..70b311683f8b 100644 --- a/lib/Target/Alpha/AlphaSubtarget.h +++ b/lib/Target/Alpha/AlphaSubtarget.h @@ -7,21 +7,24 @@ // //===----------------------------------------------------------------------===// // -// This file declares the Alpha specific subclass of TargetSubtarget. +// This file declares the Alpha specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #ifndef ALPHASUBTARGET_H #define ALPHASUBTARGET_H -#include "llvm/Target/TargetInstrItineraries.h" -#include "llvm/Target/TargetSubtarget.h" - +#include "llvm/Target/TargetSubtargetInfo.h" +#include "llvm/MC/MCInstrItineraries.h" #include <string> +#define GET_SUBTARGETINFO_HEADER +#include "AlphaGenSubtargetInfo.inc" + namespace llvm { +class StringRe; -class AlphaSubtarget : public TargetSubtarget { +class AlphaSubtarget : public AlphaGenSubtargetInfo { protected: bool HasCT; @@ -32,12 +35,12 @@ public: /// This constructor initializes the data members to match that /// of the specified triple. /// - AlphaSubtarget(const std::string &TT, const std::string &FS); + AlphaSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(StringRef CPU, StringRef FS); bool hasCT() const { return HasCT; } }; diff --git a/lib/Target/Alpha/AlphaTargetMachine.cpp b/lib/Target/Alpha/AlphaTargetMachine.cpp index b53533b8ebcb..3b65d41be892 100644 --- a/lib/Target/Alpha/AlphaTargetMachine.cpp +++ b/lib/Target/Alpha/AlphaTargetMachine.cpp @@ -11,7 +11,6 @@ //===----------------------------------------------------------------------===// #include "Alpha.h" -#include "AlphaMCAsmInfo.h" #include "AlphaTargetMachine.h" #include "llvm/PassManager.h" #include "llvm/Support/FormattedStream.h" @@ -21,15 +20,15 @@ using namespace llvm; extern "C" void LLVMInitializeAlphaTarget() { // Register the target. RegisterTargetMachine<AlphaTargetMachine> X(TheAlphaTarget); - RegisterAsmInfo<AlphaMCAsmInfo> Y(TheAlphaTarget); } AlphaTargetMachine::AlphaTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) - : LLVMTargetMachine(T, TT), + : LLVMTargetMachine(T, TT, CPU, FS), DataLayout("e-f128:128:128-n64"), FrameLowering(Subtarget), - Subtarget(TT, FS), + Subtarget(TT, CPU, FS), TLInfo(*this), TSInfo(*this) { setRelocationModel(Reloc::PIC_); diff --git a/lib/Target/Alpha/AlphaTargetMachine.h b/lib/Target/Alpha/AlphaTargetMachine.h index 26238fbbc431..cf00e5875d34 100644 --- a/lib/Target/Alpha/AlphaTargetMachine.h +++ b/lib/Target/Alpha/AlphaTargetMachine.h @@ -37,7 +37,7 @@ class AlphaTargetMachine : public LLVMTargetMachine { public: AlphaTargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); virtual const AlphaInstrInfo *getInstrInfo() const { return &InstrInfo; } virtual const TargetFrameLowering *getFrameLowering() const { diff --git a/lib/Target/Alpha/CMakeLists.txt b/lib/Target/Alpha/CMakeLists.txt index 454262ad631d..a6027bbf0b2a 100644 --- a/lib/Target/Alpha/CMakeLists.txt +++ b/lib/Target/Alpha/CMakeLists.txt @@ -1,14 +1,11 @@ set(LLVM_TARGET_DEFINITIONS Alpha.td) -tablegen(AlphaGenRegisterInfo.h.inc -gen-register-desc-header) -tablegen(AlphaGenRegisterNames.inc -gen-register-enums) -tablegen(AlphaGenRegisterInfo.inc -gen-register-desc) -tablegen(AlphaGenInstrNames.inc -gen-instr-enums) -tablegen(AlphaGenInstrInfo.inc -gen-instr-desc) +tablegen(AlphaGenRegisterInfo.inc -gen-register-info) +tablegen(AlphaGenInstrInfo.inc -gen-instr-info) tablegen(AlphaGenAsmWriter.inc -gen-asm-writer) tablegen(AlphaGenDAGISel.inc -gen-dag-isel) tablegen(AlphaGenCallingConv.inc -gen-callingconv) -tablegen(AlphaGenSubtarget.inc -gen-subtarget) +tablegen(AlphaGenSubtargetInfo.inc -gen-subtarget) add_llvm_target(AlphaCodeGen AlphaAsmPrinter.cpp @@ -18,7 +15,6 @@ add_llvm_target(AlphaCodeGen AlphaISelLowering.cpp AlphaFrameLowering.cpp AlphaLLRP.cpp - AlphaMCAsmInfo.cpp AlphaRegisterInfo.cpp AlphaSubtarget.cpp AlphaTargetMachine.cpp @@ -26,3 +22,4 @@ add_llvm_target(AlphaCodeGen ) add_subdirectory(TargetInfo) +add_subdirectory(MCTargetDesc) diff --git a/lib/Target/Alpha/AlphaMCAsmInfo.cpp b/lib/Target/Alpha/MCTargetDesc/AlphaMCAsmInfo.cpp index a35e8846e072..a35e8846e072 100644 --- a/lib/Target/Alpha/AlphaMCAsmInfo.cpp +++ b/lib/Target/Alpha/MCTargetDesc/AlphaMCAsmInfo.cpp diff --git a/lib/Target/Alpha/AlphaMCAsmInfo.h b/lib/Target/Alpha/MCTargetDesc/AlphaMCAsmInfo.h index 837844bd29a9..837844bd29a9 100644 --- a/lib/Target/Alpha/AlphaMCAsmInfo.h +++ b/lib/Target/Alpha/MCTargetDesc/AlphaMCAsmInfo.h diff --git a/lib/Target/Alpha/MCTargetDesc/AlphaMCTargetDesc.cpp b/lib/Target/Alpha/MCTargetDesc/AlphaMCTargetDesc.cpp new file mode 100644 index 000000000000..562052b6df67 --- /dev/null +++ b/lib/Target/Alpha/MCTargetDesc/AlphaMCTargetDesc.cpp @@ -0,0 +1,57 @@ +//===-- AlphaMCTargetDesc.cpp - Alpha Target Descriptions -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Alpha specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#include "AlphaMCTargetDesc.h" +#include "AlphaMCAsmInfo.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Target/TargetRegistry.h" + +#define GET_INSTRINFO_MC_DESC +#include "AlphaGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_MC_DESC +#include "AlphaGenSubtargetInfo.inc" + +#define GET_REGINFO_MC_DESC +#include "AlphaGenRegisterInfo.inc" + +using namespace llvm; + + +static MCInstrInfo *createAlphaMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitAlphaMCInstrInfo(X); + return X; +} + +extern "C" void LLVMInitializeAlphaMCInstrInfo() { + TargetRegistry::RegisterMCInstrInfo(TheAlphaTarget, createAlphaMCInstrInfo); +} + +static MCSubtargetInfo *createAlphaMCSubtargetInfo(StringRef TT, StringRef CPU, + StringRef FS) { + MCSubtargetInfo *X = new MCSubtargetInfo(); + InitAlphaMCSubtargetInfo(X, TT, CPU, FS); + return X; +} + +extern "C" void LLVMInitializeAlphaMCSubtargetInfo() { + TargetRegistry::RegisterMCSubtargetInfo(TheAlphaTarget, + createAlphaMCSubtargetInfo); +} + +extern "C" void LLVMInitializeAlphaMCAsmInfo() { + RegisterMCAsmInfo<AlphaMCAsmInfo> X(TheAlphaTarget); +} diff --git a/lib/Target/Alpha/MCTargetDesc/AlphaMCTargetDesc.h b/lib/Target/Alpha/MCTargetDesc/AlphaMCTargetDesc.h new file mode 100644 index 000000000000..b0619e6cb011 --- /dev/null +++ b/lib/Target/Alpha/MCTargetDesc/AlphaMCTargetDesc.h @@ -0,0 +1,40 @@ +//===-- AlphaMCTargetDesc.h - Alpha Target Descriptions ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Alpha specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#ifndef ALPHAMCTARGETDESC_H +#define ALPHAMCTARGETDESC_H + +namespace llvm { +class MCSubtargetInfo; +class Target; +class StringRef; + +extern Target TheAlphaTarget; + +} // End llvm namespace + +// Defines symbolic names for Alpha registers. This defines a mapping from +// register name to register number. +// +#define GET_REGINFO_ENUM +#include "AlphaGenRegisterInfo.inc" + +// Defines symbolic names for the Alpha instructions. +// +#define GET_INSTRINFO_ENUM +#include "AlphaGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "AlphaGenSubtargetInfo.inc" + +#endif diff --git a/lib/Target/Alpha/MCTargetDesc/CMakeLists.txt b/lib/Target/Alpha/MCTargetDesc/CMakeLists.txt new file mode 100644 index 000000000000..ad0dd26aafb1 --- /dev/null +++ b/lib/Target/Alpha/MCTargetDesc/CMakeLists.txt @@ -0,0 +1,4 @@ +add_llvm_library(LLVMAlphaDesc + AlphaMCTargetDesc.cpp + AlphaMCAsmInfo.cpp + ) diff --git a/lib/Target/Alpha/MCTargetDesc/Makefile b/lib/Target/Alpha/MCTargetDesc/Makefile new file mode 100644 index 000000000000..d55175fa69dc --- /dev/null +++ b/lib/Target/Alpha/MCTargetDesc/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/Alpha/TargetDesc/Makefile ----------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +LIBRARYNAME = LLVMAlphaDesc + +# Hack: we need to include 'main' target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/Alpha/Makefile b/lib/Target/Alpha/Makefile index 9564be680e51..f48847a0627d 100644 --- a/lib/Target/Alpha/Makefile +++ b/lib/Target/Alpha/Makefile @@ -12,12 +12,10 @@ LIBRARYNAME = LLVMAlphaCodeGen TARGET = Alpha # Make sure that tblgen is run, first thing. -BUILT_SOURCES = AlphaGenRegisterInfo.h.inc AlphaGenRegisterNames.inc \ - AlphaGenRegisterInfo.inc AlphaGenInstrNames.inc \ - AlphaGenInstrInfo.inc \ +BUILT_SOURCES = AlphaGenRegisterInfo.inc AlphaGenInstrInfo.inc \ AlphaGenAsmWriter.inc AlphaGenDAGISel.inc \ - AlphaGenCallingConv.inc AlphaGenSubtarget.inc + AlphaGenCallingConv.inc AlphaGenSubtargetInfo.inc -DIRS = TargetInfo +DIRS = TargetInfo MCTargetDesc include $(LEVEL)/Makefile.common diff --git a/lib/Target/Blackfin/Blackfin.h b/lib/Target/Blackfin/Blackfin.h index ec1fa8689ded..a00ff4cc3275 100644 --- a/lib/Target/Blackfin/Blackfin.h +++ b/lib/Target/Blackfin/Blackfin.h @@ -15,6 +15,7 @@ #ifndef TARGET_BLACKFIN_H #define TARGET_BLACKFIN_H +#include "MCTargetDesc/BlackfinMCTargetDesc.h" #include "llvm/Target/TargetMachine.h" namespace llvm { @@ -24,15 +25,7 @@ namespace llvm { FunctionPass *createBlackfinISelDag(BlackfinTargetMachine &TM, CodeGenOpt::Level OptLevel); - extern Target TheBlackfinTarget; } // end namespace llvm -// Defines symbolic names for Blackfin registers. This defines a mapping from -// register name to register number. -#include "BlackfinGenRegisterNames.inc" - -// Defines symbolic names for the Blackfin instructions. -#include "BlackfinGenInstrNames.inc" - #endif diff --git a/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp b/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp index 42659aed5d71..215ca43ea338 100644 --- a/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp +++ b/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp @@ -146,21 +146,21 @@ void BlackfinDAGToDAGISel::FixRegisterClasses(SelectionDAG &DAG) { NI != DAG.allnodes_end(); ++NI) { if (NI->use_empty() || !NI->isMachineOpcode()) continue; - const TargetInstrDesc &DefTID = TII.get(NI->getMachineOpcode()); + const MCInstrDesc &DefMCID = TII.get(NI->getMachineOpcode()); for (SDNode::use_iterator UI = NI->use_begin(); !UI.atEnd(); ++UI) { if (!UI->isMachineOpcode()) continue; - if (UI.getUse().getResNo() >= DefTID.getNumDefs()) + if (UI.getUse().getResNo() >= DefMCID.getNumDefs()) continue; const TargetRegisterClass *DefRC = - DefTID.OpInfo[UI.getUse().getResNo()].getRegClass(TRI); + TII.getRegClass(DefMCID, UI.getUse().getResNo(), TRI); - const TargetInstrDesc &UseTID = TII.get(UI->getMachineOpcode()); - if (UseTID.getNumDefs()+UI.getOperandNo() >= UseTID.getNumOperands()) + const MCInstrDesc &UseMCID = TII.get(UI->getMachineOpcode()); + if (UseMCID.getNumDefs()+UI.getOperandNo() >= UseMCID.getNumOperands()) continue; const TargetRegisterClass *UseRC = - UseTID.OpInfo[UseTID.getNumDefs()+UI.getOperandNo()].getRegClass(TRI); + TII.getRegClass(UseMCID, UseMCID.getNumDefs()+UI.getOperandNo(), TRI); if (!DefRC || !UseRC) continue; // We cannot copy CC <-> !(CC/D) diff --git a/lib/Target/Blackfin/BlackfinISelLowering.cpp b/lib/Target/Blackfin/BlackfinISelLowering.cpp index 588d9bded87d..d5728324de87 100644 --- a/lib/Target/Blackfin/BlackfinISelLowering.cpp +++ b/lib/Target/Blackfin/BlackfinISelLowering.cpp @@ -621,39 +621,21 @@ getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { case 'w': return Pair(0U, ALLRegisterClass); case 'Z': return Pair(P3, PRegisterClass); case 'Y': return Pair(P1, PRegisterClass); + case 'z': return Pair(0U, zConsRegisterClass); + case 'D': return Pair(0U, DConsRegisterClass); + case 'W': return Pair(0U, WConsRegisterClass); + case 'c': return Pair(0U, cConsRegisterClass); + case 't': return Pair(0U, tConsRegisterClass); + case 'u': return Pair(0U, uConsRegisterClass); + case 'k': return Pair(0U, kConsRegisterClass); + case 'y': return Pair(0U, yConsRegisterClass); } // Not implemented: q0-q7, qA. Use {R2} etc instead. - // Constraints z, D, W, c, t, u, k, and y use non-existing classes, defer to - // getRegClassForInlineAsmConstraint() return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); } -std::vector<unsigned> BlackfinTargetLowering:: -getRegClassForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { - using namespace BF; - - if (Constraint.size() != 1) - return std::vector<unsigned>(); - - switch (Constraint[0]) { - case 'z': return make_vector<unsigned>(P0, P1, P2, 0); - case 'D': return make_vector<unsigned>(R0, R2, R4, R6, 0); - case 'W': return make_vector<unsigned>(R1, R3, R5, R7, 0); - case 'c': return make_vector<unsigned>(I0, I1, I2, I3, - B0, B1, B2, B3, - L0, L1, L2, L3, 0); - case 't': return make_vector<unsigned>(LT0, LT1, 0); - case 'u': return make_vector<unsigned>(LB0, LB1, 0); - case 'k': return make_vector<unsigned>(LC0, LC1, 0); - case 'y': return make_vector<unsigned>(RETS, RETN, RETI, RETX, RETE, - ASTAT, SEQSTAT, USP, 0); - } - - return std::vector<unsigned>(); -} - bool BlackfinTargetLowering:: isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { // The Blackfin target isn't yet aware of offsets. diff --git a/lib/Target/Blackfin/BlackfinISelLowering.h b/lib/Target/Blackfin/BlackfinISelLowering.h index 9a54557ad526..b65775b9285d 100644 --- a/lib/Target/Blackfin/BlackfinISelLowering.h +++ b/lib/Target/Blackfin/BlackfinISelLowering.h @@ -48,9 +48,6 @@ namespace llvm { std::pair<unsigned, const TargetRegisterClass*> getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; - std::vector<unsigned> - getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const; virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; const char *getTargetNodeName(unsigned Opcode) const; diff --git a/lib/Target/Blackfin/BlackfinInstrInfo.cpp b/lib/Target/Blackfin/BlackfinInstrInfo.cpp index 598cf2a68c6b..d190ae7984b2 100644 --- a/lib/Target/Blackfin/BlackfinInstrInfo.cpp +++ b/lib/Target/Blackfin/BlackfinInstrInfo.cpp @@ -14,17 +14,20 @@ #include "BlackfinInstrInfo.h" #include "BlackfinSubtarget.h" #include "Blackfin.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/ErrorHandling.h" + +#define GET_INSTRINFO_CTOR #include "BlackfinGenInstrInfo.inc" using namespace llvm; BlackfinInstrInfo::BlackfinInstrInfo(BlackfinSubtarget &ST) - : TargetInstrInfoImpl(BlackfinInsts, array_lengthof(BlackfinInsts)), + : BlackfinGenInstrInfo(BF::ADJCALLSTACKDOWN, BF::ADJCALLSTACKUP), RI(ST, *this), Subtarget(ST) {} diff --git a/lib/Target/Blackfin/BlackfinInstrInfo.h b/lib/Target/Blackfin/BlackfinInstrInfo.h index fdc1029da588..d22ddf0d7313 100644 --- a/lib/Target/Blackfin/BlackfinInstrInfo.h +++ b/lib/Target/Blackfin/BlackfinInstrInfo.h @@ -17,9 +17,12 @@ #include "llvm/Target/TargetInstrInfo.h" #include "BlackfinRegisterInfo.h" +#define GET_INSTRINFO_HEADER +#include "BlackfinGenInstrInfo.inc" + namespace llvm { - class BlackfinInstrInfo : public TargetInstrInfoImpl { + class BlackfinInstrInfo : public BlackfinGenInstrInfo { const BlackfinRegisterInfo RI; const BlackfinSubtarget& Subtarget; public: diff --git a/lib/Target/Blackfin/BlackfinIntrinsicInfo.cpp b/lib/Target/Blackfin/BlackfinIntrinsicInfo.cpp index 34a8d3809ea2..ae8ee9e2a1a2 100644 --- a/lib/Target/Blackfin/BlackfinIntrinsicInfo.cpp +++ b/lib/Target/Blackfin/BlackfinIntrinsicInfo.cpp @@ -83,7 +83,7 @@ bool BlackfinIntrinsicInfo::isOverloaded(unsigned IntrID) const { static const FunctionType *getType(LLVMContext &Context, unsigned id) { const Type *ResultTy = NULL; - std::vector<const Type*> ArgTys; + std::vector<Type*> ArgTys; bool IsVarArg = false; #define GET_INTRINSIC_GENERATOR diff --git a/lib/Target/Blackfin/BlackfinRegisterInfo.cpp b/lib/Target/Blackfin/BlackfinRegisterInfo.cpp index 6ca460ef803e..3a7c104ee055 100644 --- a/lib/Target/Blackfin/BlackfinRegisterInfo.cpp +++ b/lib/Target/Blackfin/BlackfinRegisterInfo.cpp @@ -29,13 +29,15 @@ #include "llvm/Type.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" + +#define GET_REGINFO_TARGET_DESC +#include "BlackfinGenRegisterInfo.inc" + using namespace llvm; BlackfinRegisterInfo::BlackfinRegisterInfo(BlackfinSubtarget &st, const TargetInstrInfo &tii) - : BlackfinGenRegisterInfo(BF::ADJCALLSTACKDOWN, BF::ADJCALLSTACKUP), - Subtarget(st), - TII(tii) {} + : BlackfinGenRegisterInfo(), Subtarget(st), TII(tii) {} const unsigned* BlackfinRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { @@ -356,6 +358,3 @@ int BlackfinRegisterInfo::getLLVMRegNum(unsigned DwarfRegNum, llvm_unreachable("What is the dwarf register number"); return -1; } - -#include "BlackfinGenRegisterInfo.inc" - diff --git a/lib/Target/Blackfin/BlackfinRegisterInfo.h b/lib/Target/Blackfin/BlackfinRegisterInfo.h index 375d277216c2..86f45c17c625 100644 --- a/lib/Target/Blackfin/BlackfinRegisterInfo.h +++ b/lib/Target/Blackfin/BlackfinRegisterInfo.h @@ -16,7 +16,9 @@ #define BLACKFINREGISTERINFO_H #include "llvm/Target/TargetRegisterInfo.h" -#include "BlackfinGenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "BlackfinGenRegisterInfo.inc" namespace llvm { diff --git a/lib/Target/Blackfin/BlackfinRegisterInfo.td b/lib/Target/Blackfin/BlackfinRegisterInfo.td index d8fd302b513e..1c42205eb780 100644 --- a/lib/Target/Blackfin/BlackfinRegisterInfo.td +++ b/lib/Target/Blackfin/BlackfinRegisterInfo.td @@ -195,108 +195,83 @@ def LB0 : Ri<6, 2, "lb0">, DwarfRegNum<[48]>; def LB1 : Ri<6, 5, "lb1">, DwarfRegNum<[49]>; // Register classes. -def D16 : RegisterClass<"BF", [i16], 16, - [R0H, R0L, R1H, R1L, R2H, R2L, R3H, R3L, - R4H, R4L, R5H, R5L, R6H, R6L, R7H, R7L]>; +def D16L : RegisterClass<"BF", [i16], 16, (sequence "R%uL", 0, 7)>; -def D16L : RegisterClass<"BF", [i16], 16, - [R0L, R1L, R2L, R3L, R4L, R5L, R6L, R7L]>; +def D16H : RegisterClass<"BF", [i16], 16, (sequence "R%uH", 0, 7)>; -def D16H : RegisterClass<"BF", [i16], 16, - [R0H, R1H, R2H, R3H, R4H, R5H, R6H, R7H]>; - -def P16 : RegisterClass<"BF", [i16], 16, - [P0H, P0L, P1H, P1L, P2H, P2L, P3H, P3L, - P4H, P4L, P5H, P5L, SPH, SPL, FPH, FPL]>; +def D16 : RegisterClass<"BF", [i16], 16, (add D16L, D16H)>; def P16L : RegisterClass<"BF", [i16], 16, - [P0L, P1L, P2L, P3L, P4L, P5L, SPL, FPL]>; + (add (sequence "P%uL", 0, 5), SPL, FPL)>; def P16H : RegisterClass<"BF", [i16], 16, - [P0H, P1H, P2H, P3H, P4H, P5H, SPH, FPH]>; + (add (sequence "P%uH", 0, 5), SPH, FPH)>; + +def P16 : RegisterClass<"BF", [i16], 16, (add P16L, P16H)>; -def DP16 : RegisterClass<"BF", [i16], 16, - [R0H, R0L, R1H, R1L, R2H, R2L, R3H, R3L, - R4H, R4L, R5H, R5L, R6H, R6L, R7H, R7L, - P0H, P0L, P1H, P1L, P2H, P2L, P3H, P3L, - P4H, P4L, P5H, P5L, SPH, SPL, FPH, FPL]>; +def DP16 : RegisterClass<"BF", [i16], 16, (add D16, P16)>; -def DP16L : RegisterClass<"BF", [i16], 16, - [R0L, R1L, R2L, R3L, R4L, R5L, R6L, R7L, - P0L, P1L, P2L, P3L, P4L, P5L, SPL, FPL]>; +def DP16L : RegisterClass<"BF", [i16], 16, (add D16L, P16L)>; -def DP16H : RegisterClass<"BF", [i16], 16, - [R0H, R1H, R2H, R3H, R4H, R5H, R6H, R7H, - P0H, P1H, P2H, P3H, P4H, P5H, SPH, FPH]>; +def DP16H : RegisterClass<"BF", [i16], 16, (add D16H, P16H)>; def GR16 : RegisterClass<"BF", [i16], 16, - [R0H, R0L, R1H, R1L, R2H, R2L, R3H, R3L, - R4H, R4L, R5H, R5L, R6H, R6L, R7H, R7L, - P0H, P0L, P1H, P1L, P2H, P2L, P3H, P3L, - P4H, P4L, P5H, P5L, SPH, SPL, FPH, FPL, + (add DP16, I0H, I0L, I1H, I1L, I2H, I2L, I3H, I3L, M0H, M0L, M1H, M1L, M2H, M2L, M3H, M3L, B0H, B0L, B1H, B1L, B2H, B2L, B3H, B3L, - L0H, L0L, L1H, L1L, L2H, L2L, L3H, L3L]>; + L0H, L0L, L1H, L1L, L2H, L2L, L3H, L3L)>; -def D : RegisterClass<"BF", [i32], 32, [R0, R1, R2, R3, R4, R5, R6, R7]> { +def D : RegisterClass<"BF", [i32], 32, (sequence "R%u", 0, 7)> { let SubRegClasses = [(D16L lo16), (D16H hi16)]; } -def P : RegisterClass<"BF", [i32], 32, [P0, P1, P2, P3, P4, P5, FP, SP]> { +def P : RegisterClass<"BF", [i32], 32, (add (sequence "P%u", 0, 5), FP, SP)> { let SubRegClasses = [(P16L lo16), (P16H hi16)]; } -def I : RegisterClass<"BF", [i32], 32, [I0, I1, I2, I3]>; -def M : RegisterClass<"BF", [i32], 32, [M0, M1, M2, M3]>; -def B : RegisterClass<"BF", [i32], 32, [B0, B1, B2, B3]>; -def L : RegisterClass<"BF", [i32], 32, [L0, L1, L2, L3]>; - -def DP : RegisterClass<"BF", [i32], 32, - [R0, R1, R2, R3, R4, R5, R6, R7, - P0, P1, P2, P3, P4, P5, FP, SP]> { +def DP : RegisterClass<"BF", [i32], 32, (add D, P)> { let SubRegClasses = [(DP16L lo16), (DP16H hi16)]; } -def GR : RegisterClass<"BF", [i32], 32, - [R0, R1, R2, R3, R4, R5, R6, R7, - P0, P1, P2, P3, P4, P5, - I0, I1, I2, I3, M0, M1, M2, M3, - B0, B1, B2, B3, L0, L1, L2, L3, - FP, SP]>; +def I : RegisterClass<"BF", [i32], 32, (add I0, I1, I2, I3)>; +def M : RegisterClass<"BF", [i32], 32, (add M0, M1, M2, M3)>; +def B : RegisterClass<"BF", [i32], 32, (add B0, B1, B2, B3)>; +def L : RegisterClass<"BF", [i32], 32, (add L0, L1, L2, L3)>; + +def GR : RegisterClass<"BF", [i32], 32, (add DP, I, M, B, L)>; def ALL : RegisterClass<"BF", [i32], 32, - [R0, R1, R2, R3, R4, R5, R6, R7, - P0, P1, P2, P3, P4, P5, - I0, I1, I2, I3, M0, M1, M2, M3, - B0, B1, B2, B3, L0, L1, L2, L3, - FP, SP, + (add GR, A0X, A0W, A1X, A1W, ASTAT, RETS, LC0, LT0, LB0, LC1, LT1, LB1, CYCLES, CYCLES2, - USP, SEQSTAT, SYSCFG, RETI, RETX, RETN, RETE, EMUDAT]>; + USP, SEQSTAT, SYSCFG, RETI, RETX, RETN, RETE, EMUDAT)>; -def PI : RegisterClass<"BF", [i32], 32, - [P0, P1, P2, P3, P4, P5, I0, I1, I2, I3, FP, SP]>; +def PI : RegisterClass<"BF", [i32], 32, (add P, I)>; // We are going to pretend that CC and !CC are 32-bit registers, even though // they only can hold 1 bit. let CopyCost = -1, Size = 8 in { -def JustCC : RegisterClass<"BF", [i32], 8, [CC]>; -def NotCC : RegisterClass<"BF", [i32], 8, [NCC]>; -def AnyCC : RegisterClass<"BF", [i32], 8, [CC, NCC]> { - let MethodProtos = [{ - iterator allocation_order_end(const MachineFunction &MF) const; - }]; - let MethodBodies = [{ - AnyCCClass::iterator - AnyCCClass::allocation_order_end(const MachineFunction &MF) const { - return allocation_order_begin(MF)+1; - } - }]; -} +def JustCC : RegisterClass<"BF", [i32], 8, (add CC)>; +def NotCC : RegisterClass<"BF", [i32], 8, (add NCC)>; +def AnyCC : RegisterClass<"BF", [i32], 8, (add CC, NCC)>; def StatBit : RegisterClass<"BF", [i1], 8, - [AZ, AN, CC, AQ, AC0, AC1, AV0, AV0S, AV1, AV1S, V, VS]>; + (add AZ, AN, CC, AQ, AC0, AC1, AV0, AV0S, AV1, AV1S, V, VS)>; } // Should be i40, but that isn't defined. It is not a legal type yet anyway. -def Accu : RegisterClass<"BF", [i64], 64, [A0, A1]>; +def Accu : RegisterClass<"BF", [i64], 64, (add A0, A1)>; + +// Register classes to match inline asm constraints. +def zCons : RegisterClass<"BF", [i32], 32, (add P0, P1, P2)>; +def DCons : RegisterClass<"BF", [i32], 32, (add R0, R2, R4, R6)>; +def WCons : RegisterClass<"BF", [i32], 32, (add R1, R3, R5, R7)>; +def cCons : RegisterClass<"BF", [i32], 32, (add I0, I1, I2, I3, + B0, B1, B2, B3, + L0, L1, L2, L3)>; +def tCons : RegisterClass<"BF", [i32], 32, (add LT0, LT1)>; +def uCons : RegisterClass<"BF", [i32], 32, (add LB0, LB1)>; +def kCons : RegisterClass<"BF", [i32], 32, (add LC0, LC1)>; +def yCons : RegisterClass<"BF", [i32], 32, (add RETS, RETN, RETI, RETX, + RETE, ASTAT, SEQSTAT, + USP)>; diff --git a/lib/Target/Blackfin/BlackfinSubtarget.cpp b/lib/Target/Blackfin/BlackfinSubtarget.cpp index e104c5245a9e..ec919cdf0b90 100644 --- a/lib/Target/Blackfin/BlackfinSubtarget.cpp +++ b/lib/Target/Blackfin/BlackfinSubtarget.cpp @@ -7,18 +7,24 @@ // //===----------------------------------------------------------------------===// // -// This file implements the blackfin specific subclass of TargetSubtarget. +// This file implements the blackfin specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #include "BlackfinSubtarget.h" -#include "BlackfinGenSubtarget.inc" +#include "Blackfin.h" +#include "llvm/Target/TargetRegistry.h" + +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "BlackfinGenSubtargetInfo.inc" using namespace llvm; BlackfinSubtarget::BlackfinSubtarget(const std::string &TT, + const std::string &CPU, const std::string &FS) - : sdram(false), + : BlackfinGenSubtargetInfo(TT, CPU, FS), sdram(false), icplb(false), wa_mi_shift(false), wa_csync(false), @@ -30,7 +36,9 @@ BlackfinSubtarget::BlackfinSubtarget(const std::string &TT, wa_killed_mmr(false), wa_rets(false) { - std::string CPU = "generic"; + std::string CPUName = CPU; + if (CPUName.empty()) + CPUName = "generic"; // Parse features string. - ParseSubtargetFeatures(FS, CPU); + ParseSubtargetFeatures(CPUName, FS); } diff --git a/lib/Target/Blackfin/BlackfinSubtarget.h b/lib/Target/Blackfin/BlackfinSubtarget.h index d667fe26519b..1a01a81116d6 100644 --- a/lib/Target/Blackfin/BlackfinSubtarget.h +++ b/lib/Target/Blackfin/BlackfinSubtarget.h @@ -7,19 +7,23 @@ // //===----------------------------------------------------------------------===// // -// This file declares the BLACKFIN specific subclass of TargetSubtarget. +// This file declares the BLACKFIN specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #ifndef BLACKFIN_SUBTARGET_H #define BLACKFIN_SUBTARGET_H -#include "llvm/Target/TargetSubtarget.h" +#include "llvm/Target/TargetSubtargetInfo.h" #include <string> +#define GET_SUBTARGETINFO_HEADER +#include "BlackfinGenSubtargetInfo.inc" + namespace llvm { +class StringRef; - class BlackfinSubtarget : public TargetSubtarget { + class BlackfinSubtarget : public BlackfinGenSubtargetInfo { bool sdram; bool icplb; bool wa_mi_shift; @@ -32,12 +36,12 @@ namespace llvm { bool wa_killed_mmr; bool wa_rets; public: - BlackfinSubtarget(const std::string &TT, const std::string &FS); + BlackfinSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(StringRef CPU, StringRef FS); }; } // end namespace llvm diff --git a/lib/Target/Blackfin/BlackfinTargetMachine.cpp b/lib/Target/Blackfin/BlackfinTargetMachine.cpp index e11920f568a2..a1c9f1c05e0d 100644 --- a/lib/Target/Blackfin/BlackfinTargetMachine.cpp +++ b/lib/Target/Blackfin/BlackfinTargetMachine.cpp @@ -12,7 +12,6 @@ #include "BlackfinTargetMachine.h" #include "Blackfin.h" -#include "BlackfinMCAsmInfo.h" #include "llvm/PassManager.h" #include "llvm/Target/TargetRegistry.h" @@ -20,16 +19,15 @@ using namespace llvm; extern "C" void LLVMInitializeBlackfinTarget() { RegisterTargetMachine<BlackfinTargetMachine> X(TheBlackfinTarget); - RegisterAsmInfo<BlackfinMCAsmInfo> Y(TheBlackfinTarget); - } BlackfinTargetMachine::BlackfinTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) - : LLVMTargetMachine(T, TT), + : LLVMTargetMachine(T, TT, CPU, FS), DataLayout("e-p:32:32-i64:32-f64:32-n32"), - Subtarget(TT, FS), + Subtarget(TT, CPU, FS), TLInfo(*this), TSInfo(*this), InstrInfo(Subtarget), diff --git a/lib/Target/Blackfin/BlackfinTargetMachine.h b/lib/Target/Blackfin/BlackfinTargetMachine.h index 29b2b177fc3c..bd7dc84f04ae 100644 --- a/lib/Target/Blackfin/BlackfinTargetMachine.h +++ b/lib/Target/Blackfin/BlackfinTargetMachine.h @@ -36,7 +36,7 @@ namespace llvm { BlackfinIntrinsicInfo IntrinsicInfo; public: BlackfinTargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); virtual const BlackfinInstrInfo *getInstrInfo() const { return &InstrInfo; } virtual const TargetFrameLowering *getFrameLowering() const { diff --git a/lib/Target/Blackfin/CMakeLists.txt b/lib/Target/Blackfin/CMakeLists.txt index a47299ff1611..d3f33a987e69 100644 --- a/lib/Target/Blackfin/CMakeLists.txt +++ b/lib/Target/Blackfin/CMakeLists.txt @@ -1,13 +1,10 @@ set(LLVM_TARGET_DEFINITIONS Blackfin.td) -tablegen(BlackfinGenRegisterInfo.h.inc -gen-register-desc-header) -tablegen(BlackfinGenRegisterNames.inc -gen-register-enums) -tablegen(BlackfinGenRegisterInfo.inc -gen-register-desc) -tablegen(BlackfinGenInstrNames.inc -gen-instr-enums) -tablegen(BlackfinGenInstrInfo.inc -gen-instr-desc) +tablegen(BlackfinGenRegisterInfo.inc -gen-register-info) +tablegen(BlackfinGenInstrInfo.inc -gen-instr-info) tablegen(BlackfinGenAsmWriter.inc -gen-asm-writer) tablegen(BlackfinGenDAGISel.inc -gen-dag-isel) -tablegen(BlackfinGenSubtarget.inc -gen-subtarget) +tablegen(BlackfinGenSubtargetInfo.inc -gen-subtarget) tablegen(BlackfinGenCallingConv.inc -gen-callingconv) tablegen(BlackfinGenIntrinsics.inc -gen-tgt-intrinsic) @@ -18,7 +15,6 @@ add_llvm_target(BlackfinCodeGen BlackfinISelDAGToDAG.cpp BlackfinISelLowering.cpp BlackfinFrameLowering.cpp - BlackfinMCAsmInfo.cpp BlackfinRegisterInfo.cpp BlackfinSubtarget.cpp BlackfinTargetMachine.cpp @@ -26,3 +22,4 @@ add_llvm_target(BlackfinCodeGen ) add_subdirectory(TargetInfo) +add_subdirectory(MCTargetDesc) diff --git a/lib/Target/Blackfin/BlackfinMCAsmInfo.cpp b/lib/Target/Blackfin/MCTargetDesc/BlackfinMCAsmInfo.cpp index 5b9d4a29794e..5b9d4a29794e 100644 --- a/lib/Target/Blackfin/BlackfinMCAsmInfo.cpp +++ b/lib/Target/Blackfin/MCTargetDesc/BlackfinMCAsmInfo.cpp diff --git a/lib/Target/Blackfin/BlackfinMCAsmInfo.h b/lib/Target/Blackfin/MCTargetDesc/BlackfinMCAsmInfo.h index c372aa247e04..c372aa247e04 100644 --- a/lib/Target/Blackfin/BlackfinMCAsmInfo.h +++ b/lib/Target/Blackfin/MCTargetDesc/BlackfinMCAsmInfo.h diff --git a/lib/Target/Blackfin/MCTargetDesc/BlackfinMCTargetDesc.cpp b/lib/Target/Blackfin/MCTargetDesc/BlackfinMCTargetDesc.cpp new file mode 100644 index 000000000000..0fa1471ae3e7 --- /dev/null +++ b/lib/Target/Blackfin/MCTargetDesc/BlackfinMCTargetDesc.cpp @@ -0,0 +1,60 @@ +//===-- BlackfinMCTargetDesc.cpp - Blackfin Target Descriptions -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Blackfin specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#include "BlackfinMCTargetDesc.h" +#include "BlackfinMCAsmInfo.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Target/TargetRegistry.h" + +#define GET_INSTRINFO_MC_DESC +#include "BlackfinGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_MC_DESC +#include "BlackfinGenSubtargetInfo.inc" + +#define GET_REGINFO_MC_DESC +#include "BlackfinGenRegisterInfo.inc" + +using namespace llvm; + + +static MCInstrInfo *createBlackfinMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitBlackfinMCInstrInfo(X); + return X; +} + +extern "C" void LLVMInitializeBlackfinMCInstrInfo() { + TargetRegistry::RegisterMCInstrInfo(TheBlackfinTarget, + createBlackfinMCInstrInfo); +} + + +static MCSubtargetInfo *createBlackfinMCSubtargetInfo(StringRef TT, + StringRef CPU, + StringRef FS) { + MCSubtargetInfo *X = new MCSubtargetInfo(); + InitBlackfinMCSubtargetInfo(X, TT, CPU, FS); + return X; +} + +extern "C" void LLVMInitializeBlackfinMCSubtargetInfo() { + TargetRegistry::RegisterMCSubtargetInfo(TheBlackfinTarget, + createBlackfinMCSubtargetInfo); +} + +extern "C" void LLVMInitializeBlackfinMCAsmInfo() { + RegisterMCAsmInfo<BlackfinMCAsmInfo> X(TheBlackfinTarget); +} diff --git a/lib/Target/Blackfin/MCTargetDesc/BlackfinMCTargetDesc.h b/lib/Target/Blackfin/MCTargetDesc/BlackfinMCTargetDesc.h new file mode 100644 index 000000000000..5bffe94fc582 --- /dev/null +++ b/lib/Target/Blackfin/MCTargetDesc/BlackfinMCTargetDesc.h @@ -0,0 +1,38 @@ +//===-- BlackfinMCTargetDesc.h - Blackfin Target Descriptions ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Blackfin specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#ifndef BLACKFINMCTARGETDESC_H +#define BLACKFINMCTARGETDESC_H + +namespace llvm { +class MCSubtargetInfo; +class Target; +class StringRef; + +extern Target TheBlackfinTarget; + +} // End llvm namespace + +// Defines symbolic names for Blackfin registers. This defines a mapping from +// register name to register number. +#define GET_REGINFO_ENUM +#include "BlackfinGenRegisterInfo.inc" + +// Defines symbolic names for the Blackfin instructions. +#define GET_INSTRINFO_ENUM +#include "BlackfinGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "BlackfinGenSubtargetInfo.inc" + +#endif diff --git a/lib/Target/Blackfin/MCTargetDesc/CMakeLists.txt b/lib/Target/Blackfin/MCTargetDesc/CMakeLists.txt new file mode 100644 index 000000000000..8cd924f9236f --- /dev/null +++ b/lib/Target/Blackfin/MCTargetDesc/CMakeLists.txt @@ -0,0 +1,4 @@ +add_llvm_library(LLVMBlackfinDesc + BlackfinMCTargetDesc.cpp + BlackfinMCAsmInfo.cpp + ) diff --git a/lib/Target/Blackfin/MCTargetDesc/Makefile b/lib/Target/Blackfin/MCTargetDesc/Makefile new file mode 100644 index 000000000000..6b26101f4473 --- /dev/null +++ b/lib/Target/Blackfin/MCTargetDesc/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/Blackfin/TargetDesc/Makefile -------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +LIBRARYNAME = LLVMBlackfinDesc + +# Hack: we need to include 'main' target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/Blackfin/Makefile b/lib/Target/Blackfin/Makefile index 5eb8e9a992b9..756ac6bcd8a0 100644 --- a/lib/Target/Blackfin/Makefile +++ b/lib/Target/Blackfin/Makefile @@ -12,13 +12,12 @@ LIBRARYNAME = LLVMBlackfinCodeGen TARGET = Blackfin # Make sure that tblgen is run, first thing. -BUILT_SOURCES = BlackfinGenRegisterInfo.h.inc BlackfinGenRegisterNames.inc \ - BlackfinGenRegisterInfo.inc BlackfinGenInstrNames.inc \ - BlackfinGenInstrInfo.inc BlackfinGenAsmWriter.inc \ - BlackfinGenDAGISel.inc BlackfinGenSubtarget.inc \ +BUILT_SOURCES = BlackfinGenRegisterInfo.inc BlackfinGenInstrInfo.inc \ + BlackfinGenAsmWriter.inc \ + BlackfinGenDAGISel.inc BlackfinGenSubtargetInfo.inc \ BlackfinGenCallingConv.inc BlackfinGenIntrinsics.inc -DIRS = TargetInfo +DIRS = TargetInfo MCTargetDesc include $(LEVEL)/Makefile.common diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index fde2e29e80c6..415beb1dd1cd 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -20,7 +20,6 @@ #include "llvm/Instructions.h" #include "llvm/Pass.h" #include "llvm/PassManager.h" -#include "llvm/TypeSymbolTable.h" #include "llvm/Intrinsics.h" #include "llvm/IntrinsicInst.h" #include "llvm/InlineAsm.h" @@ -37,6 +36,8 @@ #include "llvm/Transforms/Scalar.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetRegistry.h" @@ -61,6 +62,12 @@ extern "C" void LLVMInitializeCBackendTarget() { RegisterTargetMachine<CTargetMachine> X(TheCBackendTarget); } +extern "C" void LLVMInitializeCBackendMCAsmInfo() {} + +extern "C" void LLVMInitializeCBackendMCInstrInfo() {} + +extern "C" void LLVMInitializeCBackendMCSubtargetInfo() {} + namespace { class CBEMCAsmInfo : public MCAsmInfo { public: @@ -69,29 +76,6 @@ namespace { PrivateGlobalPrefix = ""; } }; - /// CBackendNameAllUsedStructsAndMergeFunctions - This pass inserts names for - /// any unnamed structure types that are used by the program, and merges - /// external functions with the same name. - /// - class CBackendNameAllUsedStructsAndMergeFunctions : public ModulePass { - public: - static char ID; - CBackendNameAllUsedStructsAndMergeFunctions() - : ModulePass(ID) { - initializeFindUsedTypesPass(*PassRegistry::getPassRegistry()); - } - void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired<FindUsedTypes>(); - } - - virtual const char *getPassName() const { - return "C backend type canonicalizer"; - } - - virtual bool runOnModule(Module &M); - }; - - char CBackendNameAllUsedStructsAndMergeFunctions::ID = 0; /// CWriter - This class is the main chunk of code that converts an LLVM /// module to a C translation unit. @@ -104,7 +88,7 @@ namespace { const MCAsmInfo* TAsm; MCContext *TCtx; const TargetData* TD; - std::map<const Type *, std::string> TypeNames; + std::map<const ConstantFP *, unsigned> FPConstantMap; std::set<Function*> intrinsicPrototypesAlreadyGenerated; std::set<const Argument*> ByValParams; @@ -113,6 +97,10 @@ namespace { DenseMap<const Value*, unsigned> AnonValueNumbers; unsigned NextAnonValueNumber; + /// UnnamedStructIDs - This contains a unique ID for each struct that is + /// either anonymous or has no name. + DenseMap<const StructType*, unsigned> UnnamedStructIDs; + public: static char ID; explicit CWriter(formatted_raw_ostream &o) @@ -158,9 +146,9 @@ namespace { delete TCtx; delete TAsm; FPConstantMap.clear(); - TypeNames.clear(); ByValParams.clear(); intrinsicPrototypesAlreadyGenerated.clear(); + UnnamedStructIDs.clear(); return false; } @@ -177,6 +165,8 @@ namespace { const AttrListPtr &PAL, const PointerType *Ty); + std::string getStructName(const StructType *ST); + /// writeOperandDeref - Print the result of dereferencing the specified /// operand with '*'. This is equivalent to printing '*' then using /// writeOperand, but avoids excess syntax in some cases. @@ -205,9 +195,12 @@ namespace { std::string InterpretASMConstraint(InlineAsm::ConstraintInfo& c); void lowerIntrinsics(Function &F); + /// Prints the definition of the intrinsic function F. Supports the + /// intrinsics which need to be explicitly defined in the CBackend. + void printIntrinsicDefinition(const Function &F, raw_ostream &Out); - void printModuleTypes(const TypeSymbolTable &ST); - void printContainedStructs(const Type *Ty, std::set<const Type *> &); + void printModuleTypes(); + void printContainedStructs(const Type *Ty, SmallPtrSet<const Type *, 16> &); void printFloatingPointConstants(Function &F); void printFloatingPointConstants(const Constant *C); void printFunctionSignature(const Function *F, bool Prototype); @@ -278,7 +271,7 @@ namespace { return AI; } - // isInlineAsm - Check if the instruction is a call to an inline asm chunk + // isInlineAsm - Check if the instruction is a call to an inline asm chunk. static bool isInlineAsm(const Instruction& I) { if (const CallInst *CI = dyn_cast<CallInst>(&I)) return isa<InlineAsm>(CI->getCalledValue()); @@ -351,6 +344,7 @@ namespace { char CWriter::ID = 0; + static std::string CBEMangle(const std::string &S) { std::string Result; @@ -366,90 +360,14 @@ static std::string CBEMangle(const std::string &S) { return Result; } - -/// This method inserts names for any unnamed structure types that are used by -/// the program, and removes names from structure types that are not used by the -/// program. -/// -bool CBackendNameAllUsedStructsAndMergeFunctions::runOnModule(Module &M) { - // Get a set of types that are used by the program... - SetVector<const Type *> UT = getAnalysis<FindUsedTypes>().getTypes(); - - // Loop over the module symbol table, removing types from UT that are - // already named, and removing names for types that are not used. - // - TypeSymbolTable &TST = M.getTypeSymbolTable(); - for (TypeSymbolTable::iterator TI = TST.begin(), TE = TST.end(); - TI != TE; ) { - TypeSymbolTable::iterator I = TI++; - - // If this isn't a struct or array type, remove it from our set of types - // to name. This simplifies emission later. - if (!I->second->isStructTy() && !I->second->isOpaqueTy() && - !I->second->isArrayTy()) { - TST.remove(I); - } else { - // If this is not used, remove it from the symbol table. - if (!UT.count(I->second)) - TST.remove(I); - else - UT.remove(I->second); // Only keep one name for this type. - } - } - - // UT now contains types that are not named. Loop over it, naming - // structure types. - // - bool Changed = false; - unsigned RenameCounter = 0; - for (SetVector<const Type *>::const_iterator I = UT.begin(), E = UT.end(); - I != E; ++I) - if ((*I)->isStructTy() || (*I)->isArrayTy()) { - while (M.addTypeName("unnamed"+utostr(RenameCounter), *I)) - ++RenameCounter; - Changed = true; - } - - - // Loop over all external functions and globals. If we have two with - // identical names, merge them. - // FIXME: This code should disappear when we don't allow values with the same - // names when they have different types! - std::map<std::string, GlobalValue*> ExtSymbols; - for (Module::iterator I = M.begin(), E = M.end(); I != E;) { - Function *GV = I++; - if (GV->isDeclaration() && GV->hasName()) { - std::pair<std::map<std::string, GlobalValue*>::iterator, bool> X - = ExtSymbols.insert(std::make_pair(GV->getName(), GV)); - if (!X.second) { - // Found a conflict, replace this global with the previous one. - GlobalValue *OldGV = X.first->second; - GV->replaceAllUsesWith(ConstantExpr::getBitCast(OldGV, GV->getType())); - GV->eraseFromParent(); - Changed = true; - } - } - } - // Do the same for globals. - for (Module::global_iterator I = M.global_begin(), E = M.global_end(); - I != E;) { - GlobalVariable *GV = I++; - if (GV->isDeclaration() && GV->hasName()) { - std::pair<std::map<std::string, GlobalValue*>::iterator, bool> X - = ExtSymbols.insert(std::make_pair(GV->getName(), GV)); - if (!X.second) { - // Found a conflict, replace this global with the previous one. - GlobalValue *OldGV = X.first->second; - GV->replaceAllUsesWith(ConstantExpr::getBitCast(OldGV, GV->getType())); - GV->eraseFromParent(); - Changed = true; - } - } - } - - return Changed; +std::string CWriter::getStructName(const StructType *ST) { + if (!ST->isAnonymous() && !ST->getName().empty()) + return CBEMangle("l_"+ST->getName().str()); + + return "l_unnamed_" + utostr(UnnamedStructIDs[ST]); } + /// printStructReturnPointerFunctionType - This is like printType for a struct /// return type, except, instead of printing the type as void (*)(Struct*, ...) /// print it as "Struct (*)(...)", for struct return functions. @@ -463,7 +381,7 @@ void CWriter::printStructReturnPointerFunctionType(raw_ostream &Out, bool PrintedType = false; FunctionType::param_iterator I = FTy->param_begin(), E = FTy->param_end(); - const Type *RetTy = cast<PointerType>(I->get())->getElementType(); + const Type *RetTy = cast<PointerType>(*I)->getElementType(); unsigned Idx = 1; for (++I, ++Idx; I != E; ++I, ++Idx) { if (PrintedType) @@ -551,12 +469,6 @@ raw_ostream &CWriter::printType(raw_ostream &Out, const Type *Ty, return Out; } - // Check to see if the type is named. - if (!IgnoreName || Ty->isOpaqueTy()) { - std::map<const Type *, std::string>::iterator I = TypeNames.find(Ty); - if (I != TypeNames.end()) return Out << I->second << ' ' << NameSoFar; - } - switch (Ty->getTypeID()) { case Type::FunctionTyID: { const FunctionType *FTy = cast<FunctionType>(Ty); @@ -591,6 +503,11 @@ raw_ostream &CWriter::printType(raw_ostream &Out, const Type *Ty, } case Type::StructTyID: { const StructType *STy = cast<StructType>(Ty); + + // Check to see if the type is named. + if (!IgnoreName) + return Out << getStructName(STy) << ' ' << NameSoFar; + Out << NameSoFar + " {\n"; unsigned Idx = 0; for (StructType::element_iterator I = STy->element_begin(), @@ -631,12 +548,6 @@ raw_ostream &CWriter::printType(raw_ostream &Out, const Type *Ty, return Out << "; }"; } - case Type::OpaqueTyID: { - std::string TyName = "struct opaque_" + itostr(OpaqueCounter++); - assert(TypeNames.find(Ty) == TypeNames.end()); - TypeNames[Ty] = TyName; - return Out << TyName << ' ' << NameSoFar; - } default: llvm_unreachable("Unhandled case in getTypeProps!"); } @@ -660,7 +571,7 @@ void CWriter::printConstantArray(ConstantArray *CPA, bool Static) { if (isString) { Out << '\"'; - // Keep track of whether the last number was a hexadecimal escape + // Keep track of whether the last number was a hexadecimal escape. bool LastWasHex = false; // Do not include the last character, which we know is null @@ -1751,7 +1662,7 @@ bool CWriter::doInitialization(Module &M) { std::string E; if (const Target *Match = TargetRegistry::lookupTarget(Triple, E)) - TAsm = Match->createAsmInfo(Triple); + TAsm = Match->createMCAsmInfo(Triple); #endif TAsm = new CBEMCAsmInfo(); TCtx = new MCContext(*TAsm, NULL); @@ -1777,6 +1688,7 @@ bool CWriter::doInitialization(Module &M) { Out << "/* Provide Declarations */\n"; Out << "#include <stdarg.h>\n"; // Varargs support Out << "#include <setjmp.h>\n"; // Unwind support + Out << "#include <limits.h>\n"; // With overflow intrinsics support. generateCompilerSpecificCode(Out, TD); // Provide a definition for `bool' if not compiling with a C++ compiler. @@ -1820,8 +1732,8 @@ bool CWriter::doInitialization(Module &M) { << "/* End Module asm statements */\n"; } - // Loop over the symbol table, emitting all named constants... - printModuleTypes(M.getTypeSymbolTable()); + // Loop over the symbol table, emitting all named constants. + printModuleTypes(); // Global variable declarations... if (!M.global_empty()) { @@ -1855,29 +1767,46 @@ bool CWriter::doInitialization(Module &M) { Out << "float fmodf(float, float);\n"; Out << "long double fmodl(long double, long double);\n"; + // Store the intrinsics which will be declared/defined below. + SmallVector<const Function*, 8> intrinsicsToDefine; + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { // Don't print declarations for intrinsic functions. - if (!I->isIntrinsic() && I->getName() != "setjmp" && - I->getName() != "longjmp" && I->getName() != "_setjmp") { - if (I->hasExternalWeakLinkage()) - Out << "extern "; - printFunctionSignature(I, true); - if (I->hasWeakLinkage() || I->hasLinkOnceLinkage()) - Out << " __ATTRIBUTE_WEAK__"; - if (I->hasExternalWeakLinkage()) - Out << " __EXTERNAL_WEAK__"; - if (StaticCtors.count(I)) - Out << " __ATTRIBUTE_CTOR__"; - if (StaticDtors.count(I)) - Out << " __ATTRIBUTE_DTOR__"; - if (I->hasHiddenVisibility()) - Out << " __HIDDEN__"; - - if (I->hasName() && I->getName()[0] == 1) - Out << " LLVM_ASM(\"" << I->getName().substr(1) << "\")"; + // Store the used intrinsics, which need to be explicitly defined. + if (I->isIntrinsic()) { + switch (I->getIntrinsicID()) { + default: + break; + case Intrinsic::uadd_with_overflow: + case Intrinsic::sadd_with_overflow: + intrinsicsToDefine.push_back(I); + break; + } + continue; + } + + if (I->getName() == "setjmp" || + I->getName() == "longjmp" || I->getName() == "_setjmp") + continue; + + if (I->hasExternalWeakLinkage()) + Out << "extern "; + printFunctionSignature(I, true); + if (I->hasWeakLinkage() || I->hasLinkOnceLinkage()) + Out << " __ATTRIBUTE_WEAK__"; + if (I->hasExternalWeakLinkage()) + Out << " __EXTERNAL_WEAK__"; + if (StaticCtors.count(I)) + Out << " __ATTRIBUTE_CTOR__"; + if (StaticDtors.count(I)) + Out << " __ATTRIBUTE_DTOR__"; + if (I->hasHiddenVisibility()) + Out << " __HIDDEN__"; + + if (I->hasName() && I->getName()[0] == 1) + Out << " LLVM_ASM(\"" << I->getName().substr(1) << "\")"; - Out << ";\n"; - } + Out << ";\n"; } // Output the global variable declarations @@ -2012,6 +1941,14 @@ bool CWriter::doInitialization(Module &M) { Out << "return X <= Y ; }\n"; Out << "static inline int llvm_fcmp_oge(double X, double Y) { "; Out << "return X >= Y ; }\n"; + + // Emit definitions of the intrinsics. + for (SmallVector<const Function*, 8>::const_iterator + I = intrinsicsToDefine.begin(), + E = intrinsicsToDefine.end(); I != E; ++I) { + printIntrinsicDefinition(**I, Out); + } + return false; } @@ -2085,11 +2022,10 @@ void CWriter::printFloatingPointConstants(const Constant *C) { } - /// printSymbolTable - Run through symbol table looking for type names. If a /// type name is found, emit its declaration... /// -void CWriter::printModuleTypes(const TypeSymbolTable &TST) { +void CWriter::printModuleTypes() { Out << "/* Helper union for bitcasts */\n"; Out << "typedef union {\n"; Out << " unsigned int Int32;\n"; @@ -2098,46 +2034,42 @@ void CWriter::printModuleTypes(const TypeSymbolTable &TST) { Out << " double Double;\n"; Out << "} llvmBitCastUnion;\n"; - // We are only interested in the type plane of the symbol table. - TypeSymbolTable::const_iterator I = TST.begin(); - TypeSymbolTable::const_iterator End = TST.end(); + // Get all of the struct types used in the module. + std::vector<StructType*> StructTypes; + TheModule->findUsedStructTypes(StructTypes); - // If there are no type names, exit early. - if (I == End) return; + if (StructTypes.empty()) return; - // Print out forward declarations for structure types before anything else! Out << "/* Structure forward decls */\n"; - for (; I != End; ++I) { - std::string Name = "struct " + CBEMangle("l_"+I->first); - Out << Name << ";\n"; - TypeNames.insert(std::make_pair(I->second, Name)); - } - Out << '\n'; + unsigned NextTypeID = 0; + + // If any of them are missing names, add a unique ID to UnnamedStructIDs. + // Print out forward declarations for structure types. + for (unsigned i = 0, e = StructTypes.size(); i != e; ++i) { + StructType *ST = StructTypes[i]; - // Now we can print out typedefs. Above, we guaranteed that this can only be - // for struct or opaque types. - Out << "/* Typedefs */\n"; - for (I = TST.begin(); I != End; ++I) { - std::string Name = CBEMangle("l_"+I->first); - Out << "typedef "; - printType(Out, I->second, false, Name); - Out << ";\n"; + if (ST->isAnonymous() || ST->getName().empty()) + UnnamedStructIDs[ST] = NextTypeID++; + + std::string Name = getStructName(ST); + + Out << "typedef struct " << Name << ' ' << Name << ";\n"; } Out << '\n'; - // Keep track of which structures have been printed so far... - std::set<const Type *> StructPrinted; + // Keep track of which structures have been printed so far. + SmallPtrSet<const Type *, 16> StructPrinted; // Loop over all structures then push them into the stack so they are // printed in the correct order. // Out << "/* Structure contents */\n"; - for (I = TST.begin(); I != End; ++I) - if (I->second->isStructTy() || I->second->isArrayTy()) + for (unsigned i = 0, e = StructTypes.size(); i != e; ++i) + if (StructTypes[i]->isStructTy()) // Only print out used types! - printContainedStructs(I->second, StructPrinted); + printContainedStructs(StructTypes[i], StructPrinted); } // Push the struct onto the stack and recursively push all structs @@ -2146,7 +2078,7 @@ void CWriter::printModuleTypes(const TypeSymbolTable &TST) { // TODO: Make this work properly with vector types // void CWriter::printContainedStructs(const Type *Ty, - std::set<const Type*> &StructPrinted) { + SmallPtrSet<const Type *, 16> &StructPrinted) { // Don't walk through pointers. if (Ty->isPointerTy() || Ty->isPrimitiveType() || Ty->isIntegerTy()) return; @@ -2156,14 +2088,13 @@ void CWriter::printContainedStructs(const Type *Ty, E = Ty->subtype_end(); I != E; ++I) printContainedStructs(*I, StructPrinted); - if (Ty->isStructTy() || Ty->isArrayTy()) { + if (const StructType *ST = dyn_cast<StructType>(Ty)) { // Check to see if we have already printed this struct. - if (StructPrinted.insert(Ty).second) { - // Print structure type out. - std::string Name = TypeNames[Ty]; - printType(Out, Ty, false, Name, true); - Out << ";\n\n"; - } + if (!StructPrinted.insert(Ty)) return; + + // Print structure type out. + printType(Out, ST, false, getStructName(ST), true); + Out << ";\n\n"; } } @@ -2786,6 +2717,103 @@ void CWriter::visitSelectInst(SelectInst &I) { Out << "))"; } +// Returns the macro name or value of the max or min of an integer type +// (as defined in limits.h). +static void printLimitValue(const IntegerType &Ty, bool isSigned, bool isMax, + raw_ostream &Out) { + const char* type; + const char* sprefix = ""; + + unsigned NumBits = Ty.getBitWidth(); + if (NumBits <= 8) { + type = "CHAR"; + sprefix = "S"; + } else if (NumBits <= 16) { + type = "SHRT"; + } else if (NumBits <= 32) { + type = "INT"; + } else if (NumBits <= 64) { + type = "LLONG"; + } else { + llvm_unreachable("Bit widths > 64 not implemented yet"); + } + + if (isSigned) + Out << sprefix << type << (isMax ? "_MAX" : "_MIN"); + else + Out << "U" << type << (isMax ? "_MAX" : "0"); +} + +#ifndef NDEBUG +static bool isSupportedIntegerSize(const IntegerType &T) { + return T.getBitWidth() == 8 || T.getBitWidth() == 16 || + T.getBitWidth() == 32 || T.getBitWidth() == 64; +} +#endif + +void CWriter::printIntrinsicDefinition(const Function &F, raw_ostream &Out) { + const FunctionType *funT = F.getFunctionType(); + const Type *retT = F.getReturnType(); + const IntegerType *elemT = cast<IntegerType>(funT->getParamType(1)); + + assert(isSupportedIntegerSize(*elemT) && + "CBackend does not support arbitrary size integers."); + assert(cast<StructType>(retT)->getElementType(0) == elemT && + elemT == funT->getParamType(0) && funT->getNumParams() == 2); + + switch (F.getIntrinsicID()) { + default: + llvm_unreachable("Unsupported Intrinsic."); + case Intrinsic::uadd_with_overflow: + // static inline Rty uadd_ixx(unsigned ixx a, unsigned ixx b) { + // Rty r; + // r.field0 = a + b; + // r.field1 = (r.field0 < a); + // return r; + // } + Out << "static inline "; + printType(Out, retT); + Out << GetValueName(&F); + Out << "("; + printSimpleType(Out, elemT, false); + Out << "a,"; + printSimpleType(Out, elemT, false); + Out << "b) {\n "; + printType(Out, retT); + Out << "r;\n"; + Out << " r.field0 = a + b;\n"; + Out << " r.field1 = (r.field0 < a);\n"; + Out << " return r;\n}\n"; + break; + + case Intrinsic::sadd_with_overflow: + // static inline Rty sadd_ixx(ixx a, ixx b) { + // Rty r; + // r.field1 = (b > 0 && a > XX_MAX - b) || + // (b < 0 && a < XX_MIN - b); + // r.field0 = r.field1 ? 0 : a + b; + // return r; + // } + Out << "static "; + printType(Out, retT); + Out << GetValueName(&F); + Out << "("; + printSimpleType(Out, elemT, true); + Out << "a,"; + printSimpleType(Out, elemT, true); + Out << "b) {\n "; + printType(Out, retT); + Out << "r;\n"; + Out << " r.field1 = (b > 0 && a > "; + printLimitValue(*elemT, true, true, Out); + Out << " - b) || (b < 0 && a < "; + printLimitValue(*elemT, true, false, Out); + Out << " - b);\n"; + Out << " r.field0 = r.field1 ? 0 : a + b;\n"; + Out << " return r;\n}\n"; + break; + } +} void CWriter::lowerIntrinsics(Function &F) { // This is used to keep track of intrinsics that get generated to a lowered @@ -2816,6 +2844,8 @@ void CWriter::lowerIntrinsics(Function &F) { case Intrinsic::x86_sse2_cmp_sd: case Intrinsic::x86_sse2_cmp_pd: case Intrinsic::ppc_altivec_lvsl: + case Intrinsic::uadd_with_overflow: + case Intrinsic::sadd_with_overflow: // We directly implement these intrinsics break; default: @@ -3109,6 +3139,14 @@ bool CWriter::visitBuiltinCall(CallInst &I, Intrinsic::ID ID, writeOperand(I.getArgOperand(0)); Out << ")"; return true; + case Intrinsic::uadd_with_overflow: + case Intrinsic::sadd_with_overflow: + Out << GetValueName(I.getCalledFunction()) << "("; + writeOperand(I.getArgOperand(0)); + Out << ", "; + writeOperand(I.getArgOperand(1)); + Out << ")"; + return true; } } @@ -3127,7 +3165,7 @@ std::string CWriter::InterpretASMConstraint(InlineAsm::ConstraintInfo& c) { std::string E; if (const Target *Match = TargetRegistry::lookupTarget(Triple, E)) - TargetAsm = Match->createAsmInfo(Triple); + TargetAsm = Match->createMCAsmInfo(Triple); else return c.Codes[0]; @@ -3520,7 +3558,8 @@ void CWriter::visitInsertValueInst(InsertValueInst &IVI) { for (const unsigned *b = IVI.idx_begin(), *i = b, *e = IVI.idx_end(); i != e; ++i) { const Type *IndexedTy = - ExtractValueInst::getIndexedType(IVI.getOperand(0)->getType(), b, i+1); + ExtractValueInst::getIndexedType(IVI.getOperand(0)->getType(), + ArrayRef<unsigned>(b, i+1)); if (IndexedTy->isArrayTy()) Out << ".array[" << *i << "]"; else @@ -3541,7 +3580,8 @@ void CWriter::visitExtractValueInst(ExtractValueInst &EVI) { for (const unsigned *b = EVI.idx_begin(), *i = b, *e = EVI.idx_end(); i != e; ++i) { const Type *IndexedTy = - ExtractValueInst::getIndexedType(EVI.getOperand(0)->getType(), b, i+1); + ExtractValueInst::getIndexedType(EVI.getOperand(0)->getType(), + ArrayRef<unsigned>(b, i+1)); if (IndexedTy->isArrayTy()) Out << ".array[" << *i << "]"; else @@ -3565,7 +3605,6 @@ bool CTargetMachine::addPassesToEmitFile(PassManagerBase &PM, PM.add(createGCLoweringPass()); PM.add(createLowerInvokePass()); PM.add(createCFGSimplificationPass()); // clean up after lower invoke. - PM.add(new CBackendNameAllUsedStructsAndMergeFunctions()); PM.add(new CWriter(o)); PM.add(createGCInfoDeleter()); return false; diff --git a/lib/Target/CBackend/CTargetMachine.h b/lib/Target/CBackend/CTargetMachine.h index 6fed1959ff63..e64216be0bdc 100644 --- a/lib/Target/CBackend/CTargetMachine.h +++ b/lib/Target/CBackend/CTargetMachine.h @@ -20,8 +20,9 @@ namespace llvm { struct CTargetMachine : public TargetMachine { - CTargetMachine(const Target &T, const std::string &TT, const std::string &FS) - : TargetMachine(T) {} + CTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) + : TargetMachine(T, TT, CPU, FS) {} virtual bool addPassesToEmitFile(PassManagerBase &PM, formatted_raw_ostream &Out, diff --git a/lib/Target/CMakeLists.txt b/lib/Target/CMakeLists.txt index 09b48ce632f2..f982316fc087 100644 --- a/lib/Target/CMakeLists.txt +++ b/lib/Target/CMakeLists.txt @@ -1,6 +1,5 @@ add_llvm_library(LLVMTarget Mangler.cpp - SubtargetFeature.cpp Target.cpp TargetAsmInfo.cpp TargetAsmLexer.cpp @@ -13,7 +12,7 @@ add_llvm_library(LLVMTarget TargetLoweringObjectFile.cpp TargetMachine.cpp TargetRegisterInfo.cpp - TargetSubtarget.cpp + TargetSubtargetInfo.cpp ) set(LLVM_ENUM_ASM_PRINTERS "") diff --git a/lib/Target/CellSPU/CMakeLists.txt b/lib/Target/CellSPU/CMakeLists.txt index a2a2ef1aa9af..0b94e0cf1193 100644 --- a/lib/Target/CellSPU/CMakeLists.txt +++ b/lib/Target/CellSPU/CMakeLists.txt @@ -1,14 +1,11 @@ set(LLVM_TARGET_DEFINITIONS SPU.td) -tablegen(SPUGenInstrNames.inc -gen-instr-enums) -tablegen(SPUGenRegisterNames.inc -gen-register-enums) tablegen(SPUGenAsmWriter.inc -gen-asm-writer) tablegen(SPUGenCodeEmitter.inc -gen-emitter) -tablegen(SPUGenRegisterInfo.h.inc -gen-register-desc-header) -tablegen(SPUGenRegisterInfo.inc -gen-register-desc) -tablegen(SPUGenInstrInfo.inc -gen-instr-desc) +tablegen(SPUGenRegisterInfo.inc -gen-register-info) +tablegen(SPUGenInstrInfo.inc -gen-instr-info) tablegen(SPUGenDAGISel.inc -gen-dag-isel) -tablegen(SPUGenSubtarget.inc -gen-subtarget) +tablegen(SPUGenSubtargetInfo.inc -gen-subtarget) tablegen(SPUGenCallingConv.inc -gen-callingconv) add_llvm_target(CellSPUCodeGen @@ -18,7 +15,6 @@ add_llvm_target(CellSPUCodeGen SPUISelDAGToDAG.cpp SPUISelLowering.cpp SPUFrameLowering.cpp - SPUMCAsmInfo.cpp SPURegisterInfo.cpp SPUSubtarget.cpp SPUTargetMachine.cpp @@ -27,3 +23,4 @@ add_llvm_target(CellSPUCodeGen ) add_subdirectory(TargetInfo) +add_subdirectory(MCTargetDesc) diff --git a/lib/Target/CellSPU/MCTargetDesc/CMakeLists.txt b/lib/Target/CellSPU/MCTargetDesc/CMakeLists.txt new file mode 100644 index 000000000000..85fb258eac2c --- /dev/null +++ b/lib/Target/CellSPU/MCTargetDesc/CMakeLists.txt @@ -0,0 +1,4 @@ +add_llvm_library(LLVMCellSPUDesc + SPUMCTargetDesc.cpp + SPUMCAsmInfo.cpp + ) diff --git a/lib/Target/CellSPU/MCTargetDesc/Makefile b/lib/Target/CellSPU/MCTargetDesc/Makefile new file mode 100644 index 000000000000..10d9a42239ad --- /dev/null +++ b/lib/Target/CellSPU/MCTargetDesc/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/CellSPU/TargetDesc/Makefile --------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +LIBRARYNAME = LLVMCellSPUDesc + +# Hack: we need to include 'main' target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/CellSPU/SPUMCAsmInfo.cpp b/lib/Target/CellSPU/MCTargetDesc/SPUMCAsmInfo.cpp index 99aaeb006a0b..8c1176a9d028 100644 --- a/lib/Target/CellSPU/SPUMCAsmInfo.cpp +++ b/lib/Target/CellSPU/MCTargetDesc/SPUMCAsmInfo.cpp @@ -15,6 +15,8 @@ using namespace llvm; SPULinuxMCAsmInfo::SPULinuxMCAsmInfo(const Target &T, StringRef TT) { + IsLittleEndian = false; + ZeroDirective = "\t.space\t"; Data64bitsDirective = "\t.quad\t"; AlignmentIsInBytes = false; diff --git a/lib/Target/CellSPU/SPUMCAsmInfo.h b/lib/Target/CellSPU/MCTargetDesc/SPUMCAsmInfo.h index 7f850d347f56..7f850d347f56 100644 --- a/lib/Target/CellSPU/SPUMCAsmInfo.h +++ b/lib/Target/CellSPU/MCTargetDesc/SPUMCAsmInfo.h diff --git a/lib/Target/CellSPU/MCTargetDesc/SPUMCTargetDesc.cpp b/lib/Target/CellSPU/MCTargetDesc/SPUMCTargetDesc.cpp new file mode 100644 index 000000000000..26c5a4bc7b33 --- /dev/null +++ b/lib/Target/CellSPU/MCTargetDesc/SPUMCTargetDesc.cpp @@ -0,0 +1,56 @@ +//===-- SPUMCTargetDesc.cpp - Cell SPU Target Descriptions -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Cell SPU specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#include "SPUMCTargetDesc.h" +#include "SPUMCAsmInfo.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Target/TargetRegistry.h" + +#define GET_INSTRINFO_MC_DESC +#include "SPUGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_MC_DESC +#include "SPUGenSubtargetInfo.inc" + +#define GET_REGINFO_MC_DESC +#include "SPUGenRegisterInfo.inc" + +using namespace llvm; + +static MCInstrInfo *createSPUMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitSPUMCInstrInfo(X); + return X; +} + +extern "C" void LLVMInitializeCellSPUMCInstrInfo() { + TargetRegistry::RegisterMCInstrInfo(TheCellSPUTarget, createSPUMCInstrInfo); +} + +static MCSubtargetInfo *createSPUMCSubtargetInfo(StringRef TT, StringRef CPU, + StringRef FS) { + MCSubtargetInfo *X = new MCSubtargetInfo(); + InitSPUMCSubtargetInfo(X, TT, CPU, FS); + return X; +} + +extern "C" void LLVMInitializeCellSPUMCSubtargetInfo() { + TargetRegistry::RegisterMCSubtargetInfo(TheCellSPUTarget, + createSPUMCSubtargetInfo); +} + +extern "C" void LLVMInitializeCellSPUMCAsmInfo() { + RegisterMCAsmInfo<SPULinuxMCAsmInfo> X(TheCellSPUTarget); +} diff --git a/lib/Target/CellSPU/MCTargetDesc/SPUMCTargetDesc.h b/lib/Target/CellSPU/MCTargetDesc/SPUMCTargetDesc.h new file mode 100644 index 000000000000..c5c037d4de44 --- /dev/null +++ b/lib/Target/CellSPU/MCTargetDesc/SPUMCTargetDesc.h @@ -0,0 +1,40 @@ +//===-- SPUMCTargetDesc.h - Alpha Target Descriptions ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Alpha specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#ifndef SPUMCTARGETDESC_H +#define SPUMCTARGETDESC_H + +namespace llvm { +class MCSubtargetInfo; +class Target; +class StringRef; + +extern Target TheCellSPUTarget; + +} // End llvm namespace + +// Define symbolic names for Cell registers. This defines a mapping from +// register name to register number. +// +#define GET_REGINFO_ENUM +#include "SPUGenRegisterInfo.inc" + +// Defines symbolic names for the SPU instructions. +// +#define GET_INSTRINFO_ENUM +#include "SPUGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "SPUGenSubtargetInfo.inc" + +#endif diff --git a/lib/Target/CellSPU/Makefile b/lib/Target/CellSPU/Makefile index 77c66be9e857..d7a8247f5702 100644 --- a/lib/Target/CellSPU/Makefile +++ b/lib/Target/CellSPU/Makefile @@ -10,12 +10,11 @@ LEVEL = ../../.. LIBRARYNAME = LLVMCellSPUCodeGen TARGET = SPU -BUILT_SOURCES = SPUGenInstrNames.inc SPUGenRegisterNames.inc \ +BUILT_SOURCES = SPUGenInstrInfo.inc SPUGenRegisterInfo.inc \ SPUGenAsmWriter.inc SPUGenCodeEmitter.inc \ - SPUGenRegisterInfo.h.inc SPUGenRegisterInfo.inc \ - SPUGenInstrInfo.inc SPUGenDAGISel.inc \ - SPUGenSubtarget.inc SPUGenCallingConv.inc + SPUGenDAGISel.inc \ + SPUGenSubtargetInfo.inc SPUGenCallingConv.inc -DIRS = TargetInfo +DIRS = TargetInfo MCTargetDesc include $(LEVEL)/Makefile.common diff --git a/lib/Target/CellSPU/SPU.h b/lib/Target/CellSPU/SPU.h index 72f84300b2c3..b51fbc7a5197 100644 --- a/lib/Target/CellSPU/SPU.h +++ b/lib/Target/CellSPU/SPU.h @@ -15,6 +15,7 @@ #ifndef LLVM_TARGET_IBMCELLSPU_H #define LLVM_TARGET_IBMCELLSPU_H +#include "MCTargetDesc/SPUMCTargetDesc.h" #include "llvm/Target/TargetMachine.h" namespace llvm { @@ -25,11 +26,6 @@ namespace llvm { FunctionPass *createSPUISelDag(SPUTargetMachine &TM); FunctionPass *createSPUNopFillerPass(SPUTargetMachine &tm); - extern Target TheCellSPUTarget; } -// Defines symbolic names for the SPU instructions. -// -#include "SPUGenInstrNames.inc" - #endif /* LLVM_TARGET_IBMCELLSPU_H */ diff --git a/lib/Target/CellSPU/SPUFrameLowering.cpp b/lib/Target/CellSPU/SPUFrameLowering.cpp index 432f4a1b59e2..a3e7e73ae30a 100644 --- a/lib/Target/CellSPU/SPUFrameLowering.cpp +++ b/lib/Target/CellSPU/SPUFrameLowering.cpp @@ -13,7 +13,6 @@ #include "SPU.h" #include "SPUFrameLowering.h" -#include "SPURegisterNames.h" #include "SPUInstrBuilder.h" #include "SPUInstrInfo.h" #include "llvm/Function.h" diff --git a/lib/Target/CellSPU/SPUISelDAGToDAG.cpp b/lib/Target/CellSPU/SPUISelDAGToDAG.cpp index 9351ffdc0b7f..a297d036f03e 100644 --- a/lib/Target/CellSPU/SPUISelDAGToDAG.cpp +++ b/lib/Target/CellSPU/SPUISelDAGToDAG.cpp @@ -16,7 +16,6 @@ #include "SPUTargetMachine.h" #include "SPUHazardRecognizers.h" #include "SPUFrameLowering.h" -#include "SPURegisterNames.h" #include "SPUTargetMachine.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineInstrBuilder.h" diff --git a/lib/Target/CellSPU/SPUISelLowering.cpp b/lib/Target/CellSPU/SPUISelLowering.cpp index f9b50419e7bd..f0ceee214149 100644 --- a/lib/Target/CellSPU/SPUISelLowering.cpp +++ b/lib/Target/CellSPU/SPUISelLowering.cpp @@ -10,7 +10,6 @@ // //===----------------------------------------------------------------------===// -#include "SPURegisterNames.h" #include "SPUISelLowering.h" #include "SPUTargetMachine.h" #include "SPUFrameLowering.h" @@ -221,6 +220,9 @@ SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM) setOperationAction(ISD::FSQRT, MVT::f64, Expand); setOperationAction(ISD::FSQRT, MVT::f32, Expand); + setOperationAction(ISD::FMA, MVT::f64, Expand); + setOperationAction(ISD::FMA, MVT::f32, Expand); + setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand); diff --git a/lib/Target/CellSPU/SPUInstrInfo.cpp b/lib/Target/CellSPU/SPUInstrInfo.cpp index 080434d66789..e67b10c7984d 100644 --- a/lib/Target/CellSPU/SPUInstrInfo.cpp +++ b/lib/Target/CellSPU/SPUInstrInfo.cpp @@ -11,17 +11,19 @@ // //===----------------------------------------------------------------------===// -#include "SPURegisterNames.h" #include "SPUInstrInfo.h" #include "SPUInstrBuilder.h" #include "SPUTargetMachine.h" -#include "SPUGenInstrInfo.inc" #include "SPUHazardRecognizers.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Target/TargetRegistry.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/MC/MCContext.h" + +#define GET_INSTRINFO_CTOR +#include "SPUGenInstrInfo.inc" using namespace llvm; @@ -51,7 +53,7 @@ namespace { } SPUInstrInfo::SPUInstrInfo(SPUTargetMachine &tm) - : TargetInstrInfoImpl(SPUInsts, sizeof(SPUInsts)/sizeof(SPUInsts[0])), + : SPUGenInstrInfo(SPU::ADJCALLSTACKDOWN, SPU::ADJCALLSTACKUP), TM(tm), RI(*TM.getSubtargetImpl(), *this) { /* NOP */ } diff --git a/lib/Target/CellSPU/SPUInstrInfo.h b/lib/Target/CellSPU/SPUInstrInfo.h index e5e91481419a..bc1ba71f7a45 100644 --- a/lib/Target/CellSPU/SPUInstrInfo.h +++ b/lib/Target/CellSPU/SPUInstrInfo.h @@ -18,9 +18,12 @@ #include "llvm/Target/TargetInstrInfo.h" #include "SPURegisterInfo.h" +#define GET_INSTRINFO_HEADER +#include "SPUGenInstrInfo.inc" + namespace llvm { //! Cell SPU instruction information class - class SPUInstrInfo : public TargetInstrInfoImpl { + class SPUInstrInfo : public SPUGenInstrInfo { SPUTargetMachine &TM; const SPURegisterInfo RI; public: diff --git a/lib/Target/CellSPU/SPURegisterInfo.cpp b/lib/Target/CellSPU/SPURegisterInfo.cpp index 623ae76326bb..19896c0b4be9 100644 --- a/lib/Target/CellSPU/SPURegisterInfo.cpp +++ b/lib/Target/CellSPU/SPURegisterInfo.cpp @@ -14,7 +14,6 @@ #define DEBUG_TYPE "reginfo" #include "SPU.h" #include "SPURegisterInfo.h" -#include "SPURegisterNames.h" #include "SPUInstrBuilder.h" #include "SPUSubtarget.h" #include "SPUMachineFunction.h" @@ -43,6 +42,9 @@ #include "llvm/ADT/STLExtras.h" #include <cstdlib> +#define GET_REGINFO_TARGET_DESC +#include "SPUGenRegisterInfo.inc" + using namespace llvm; /// getRegisterNumbering - Given the enum value for some register, e.g. @@ -185,9 +187,7 @@ unsigned SPURegisterInfo::getRegisterNumbering(unsigned RegEnum) { SPURegisterInfo::SPURegisterInfo(const SPUSubtarget &subtarget, const TargetInstrInfo &tii) : - SPUGenRegisterInfo(SPU::ADJCALLSTACKDOWN, SPU::ADJCALLSTACKUP), - Subtarget(subtarget), - TII(tii) + SPUGenRegisterInfo(), Subtarget(subtarget), TII(tii) { } @@ -371,5 +371,3 @@ SPURegisterInfo::findScratchRegister(MachineBasicBlock::iterator II, assert( Reg && "Register scavenger failed"); return Reg; } - -#include "SPUGenRegisterInfo.inc" diff --git a/lib/Target/CellSPU/SPURegisterInfo.h b/lib/Target/CellSPU/SPURegisterInfo.h index 6ecf0f28dd9f..5e014f8adbfc 100644 --- a/lib/Target/CellSPU/SPURegisterInfo.h +++ b/lib/Target/CellSPU/SPURegisterInfo.h @@ -16,7 +16,9 @@ #define SPU_REGISTERINFO_H #include "SPU.h" -#include "SPUGenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "SPUGenRegisterInfo.inc" namespace llvm { class SPUSubtarget; diff --git a/lib/Target/CellSPU/SPURegisterInfo.td b/lib/Target/CellSPU/SPURegisterInfo.td index cce0c823c935..e16f51ff0e02 100644 --- a/lib/Target/CellSPU/SPURegisterInfo.td +++ b/lib/Target/CellSPU/SPURegisterInfo.td @@ -155,147 +155,29 @@ def R127 : SPUVecReg<127, "$127">, DwarfRegNum<[127]>; // The SPU's registers as 128-bit wide entities, and can function as general // purpose registers, where the operands are in the "preferred slot": +// The non-volatile registers are allocated in reverse order, like PPC does it. def GPRC : RegisterClass<"SPU", [i128], 128, - [ - /* volatile register */ - R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, - R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, - R32, R33, R34, R35, R36, R37, R38, R39, R40, R41, R42, R43, R44, R45, R46, - R47, R48, R49, R50, R51, R52, R53, R54, R55, R56, R57, R58, R59, R60, R61, - R62, R63, R64, R65, R66, R67, R68, R69, R70, R71, R72, R73, R74, R75, R76, - R77, R78, R79, - /* non-volatile register: take hint from PPC and allocate in reverse order */ - R127, R126, R125, R124, R123, R122, R121, R120, R119, R118, R117, R116, R115, - R114, R113, R112, R111, R110, R109, R108, R107, R106, R105, R104, R103, R102, - R101, R100, R99, R98, R97, R96, R95, R94, R93, R92, R91, R90, R89, R88, R87, - R86, R85, R84, R83, R82, R81, R80, - /* environment ptr, SP, LR */ - R2, R1, R0 ]>; + (add (sequence "R%u", 0, 79), + (sequence "R%u", 127, 80))>; // The SPU's registers as 64-bit wide (double word integer) "preferred slot": -def R64C : RegisterClass<"SPU", [i64], 128, - [ - /* volatile register */ - R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, - R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, - R32, R33, R34, R35, R36, R37, R38, R39, R40, R41, R42, R43, R44, R45, R46, - R47, R48, R49, R50, R51, R52, R53, R54, R55, R56, R57, R58, R59, R60, R61, - R62, R63, R64, R65, R66, R67, R68, R69, R70, R71, R72, R73, R74, R75, R76, - R77, R78, R79, - /* non-volatile register: take hint from PPC and allocate in reverse order */ - R127, R126, R125, R124, R123, R122, R121, R120, R119, R118, R117, R116, R115, - R114, R113, R112, R111, R110, R109, R108, R107, R106, R105, R104, R103, R102, - R101, R100, R99, R98, R97, R96, R95, R94, R93, R92, R91, R90, R89, R88, R87, - R86, R85, R84, R83, R82, R81, R80, - /* environment ptr, SP, LR */ - R2, R1, R0 ]>; +def R64C : RegisterClass<"SPU", [i64], 128, (add GPRC)>; // The SPU's registers as 64-bit wide (double word) FP "preferred slot": -def R64FP : RegisterClass<"SPU", [f64], 128, - [ - /* volatile register */ - R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, - R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, - R32, R33, R34, R35, R36, R37, R38, R39, R40, R41, R42, R43, R44, R45, R46, - R47, R48, R49, R50, R51, R52, R53, R54, R55, R56, R57, R58, R59, R60, R61, - R62, R63, R64, R65, R66, R67, R68, R69, R70, R71, R72, R73, R74, R75, R76, - R77, R78, R79, - /* non-volatile register: take hint from PPC and allocate in reverse order */ - R127, R126, R125, R124, R123, R122, R121, R120, R119, R118, R117, R116, R115, - R114, R113, R112, R111, R110, R109, R108, R107, R106, R105, R104, R103, R102, - R101, R100, R99, R98, R97, R96, R95, R94, R93, R92, R91, R90, R89, R88, R87, - R86, R85, R84, R83, R82, R81, R80, - /* environment ptr, SP, LR */ - R2, R1, R0 ]>; +def R64FP : RegisterClass<"SPU", [f64], 128, (add GPRC)>; // The SPU's registers as 32-bit wide (word) "preferred slot": -def R32C : RegisterClass<"SPU", [i32], 128, - [ - /* volatile register */ - R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, - R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, - R32, R33, R34, R35, R36, R37, R38, R39, R40, R41, R42, R43, R44, R45, R46, - R47, R48, R49, R50, R51, R52, R53, R54, R55, R56, R57, R58, R59, R60, R61, - R62, R63, R64, R65, R66, R67, R68, R69, R70, R71, R72, R73, R74, R75, R76, - R77, R78, R79, - /* non-volatile register: take hint from PPC and allocate in reverse order */ - R127, R126, R125, R124, R123, R122, R121, R120, R119, R118, R117, R116, R115, - R114, R113, R112, R111, R110, R109, R108, R107, R106, R105, R104, R103, R102, - R101, R100, R99, R98, R97, R96, R95, R94, R93, R92, R91, R90, R89, R88, R87, - R86, R85, R84, R83, R82, R81, R80, - /* environment ptr, SP, LR */ - R2, R1, R0 ]>; +def R32C : RegisterClass<"SPU", [i32], 128, (add GPRC)>; // The SPU's registers as single precision floating point "preferred slot": -def R32FP : RegisterClass<"SPU", [f32], 128, - [ - /* volatile register */ - R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, - R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, - R32, R33, R34, R35, R36, R37, R38, R39, R40, R41, R42, R43, R44, R45, R46, - R47, R48, R49, R50, R51, R52, R53, R54, R55, R56, R57, R58, R59, R60, R61, - R62, R63, R64, R65, R66, R67, R68, R69, R70, R71, R72, R73, R74, R75, R76, - R77, R78, R79, - /* non-volatile register: take hint from PPC and allocate in reverse order */ - R127, R126, R125, R124, R123, R122, R121, R120, R119, R118, R117, R116, R115, - R114, R113, R112, R111, R110, R109, R108, R107, R106, R105, R104, R103, R102, - R101, R100, R99, R98, R97, R96, R95, R94, R93, R92, R91, R90, R89, R88, R87, - R86, R85, R84, R83, R82, R81, R80, - /* environment ptr, SP, LR */ - R2, R1, R0 ]>; +def R32FP : RegisterClass<"SPU", [f32], 128, (add GPRC)>; // The SPU's registers as 16-bit wide (halfword) "preferred slot": -def R16C : RegisterClass<"SPU", [i16], 128, - [ - /* volatile register */ - R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, - R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, - R32, R33, R34, R35, R36, R37, R38, R39, R40, R41, R42, R43, R44, R45, R46, - R47, R48, R49, R50, R51, R52, R53, R54, R55, R56, R57, R58, R59, R60, R61, - R62, R63, R64, R65, R66, R67, R68, R69, R70, R71, R72, R73, R74, R75, R76, - R77, R78, R79, - /* non-volatile register: take hint from PPC and allocate in reverse order */ - R127, R126, R125, R124, R123, R122, R121, R120, R119, R118, R117, R116, R115, - R114, R113, R112, R111, R110, R109, R108, R107, R106, R105, R104, R103, R102, - R101, R100, R99, R98, R97, R96, R95, R94, R93, R92, R91, R90, R89, R88, R87, - R86, R85, R84, R83, R82, R81, R80, - /* environment ptr, SP, LR */ - R2, R1, R0 ]>; +def R16C : RegisterClass<"SPU", [i16], 128, (add GPRC)>; // The SPU's registers as 8-bit wide (byte) "preferred slot": -def R8C : RegisterClass<"SPU", [i8], 128, - [ - /* volatile register */ - R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, - R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, - R32, R33, R34, R35, R36, R37, R38, R39, R40, R41, R42, R43, R44, R45, R46, - R47, R48, R49, R50, R51, R52, R53, R54, R55, R56, R57, R58, R59, R60, R61, - R62, R63, R64, R65, R66, R67, R68, R69, R70, R71, R72, R73, R74, R75, R76, - R77, R78, R79, - /* non-volatile register: take hint from PPC and allocate in reverse order */ - R127, R126, R125, R124, R123, R122, R121, R120, R119, R118, R117, R116, R115, - R114, R113, R112, R111, R110, R109, R108, R107, R106, R105, R104, R103, R102, - R101, R100, R99, R98, R97, R96, R95, R94, R93, R92, R91, R90, R89, R88, R87, - R86, R85, R84, R83, R82, R81, R80, - /* environment ptr, SP, LR */ - R2, R1, R0 ]>; +def R8C : RegisterClass<"SPU", [i8], 128, (add GPRC)>; // The SPU's registers as vector registers: -def VECREG : RegisterClass<"SPU", - [v16i8,v8i16,v4i32,v4f32,v2i64,v2f64], - 128, - [ - /* volatile register */ - R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, - R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, - R32, R33, R34, R35, R36, R37, R38, R39, R40, R41, R42, R43, R44, R45, R46, - R47, R48, R49, R50, R51, R52, R53, R54, R55, R56, R57, R58, R59, R60, R61, - R62, R63, R64, R65, R66, R67, R68, R69, R70, R71, R72, R73, R74, R75, R76, - R77, R78, R79, - /* non-volatile register: take hint from PPC and allocate in reverse order */ - R127, R126, R125, R124, R123, R122, R121, R120, R119, R118, R117, R116, R115, - R114, R113, R112, R111, R110, R109, R108, R107, R106, R105, R104, R103, R102, - R101, R100, R99, R98, R97, R96, R95, R94, R93, R92, R91, R90, R89, R88, R87, - R86, R85, R84, R83, R82, R81, R80, - /* environment ptr, SP, LR */ - R2, R1, R0 ]>; +def VECREG : RegisterClass<"SPU", [v16i8,v8i16,v4i32,v4f32,v2i64,v2f64], 128, + (add GPRC)>; diff --git a/lib/Target/CellSPU/SPURegisterNames.h b/lib/Target/CellSPU/SPURegisterNames.h index 6c3afdf41fdc..e557ed340a28 100644 --- a/lib/Target/CellSPU/SPURegisterNames.h +++ b/lib/Target/CellSPU/SPURegisterNames.h @@ -13,6 +13,7 @@ // Define symbolic names for Cell registers. This defines a mapping from // register name to register number. // -#include "SPUGenRegisterNames.inc" +#define GET_REGINFO_ENUM +#include "SPUGenRegisterInfo.inc" #endif diff --git a/lib/Target/CellSPU/SPUSubtarget.cpp b/lib/Target/CellSPU/SPUSubtarget.cpp index 07c8352fba9f..856dc82f786b 100644 --- a/lib/Target/CellSPU/SPUSubtarget.cpp +++ b/lib/Target/CellSPU/SPUSubtarget.cpp @@ -7,19 +7,25 @@ // //===----------------------------------------------------------------------===// // -// This file implements the CellSPU-specific subclass of TargetSubtarget. +// This file implements the CellSPU-specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #include "SPUSubtarget.h" #include "SPU.h" -#include "SPUGenSubtarget.inc" -#include "llvm/ADT/SmallVector.h" #include "SPURegisterInfo.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/SmallVector.h" + +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "SPUGenSubtargetInfo.inc" using namespace llvm; -SPUSubtarget::SPUSubtarget(const std::string &TT, const std::string &FS) : +SPUSubtarget::SPUSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS) : + SPUGenSubtargetInfo(TT, CPU, FS), StackAlignment(16), ProcDirective(SPU::DEFAULT_PROC), UseLargeMem(false) @@ -29,7 +35,10 @@ SPUSubtarget::SPUSubtarget(const std::string &TT, const std::string &FS) : std::string default_cpu("v0"); // Parse features string. - ParseSubtargetFeatures(FS, default_cpu); + ParseSubtargetFeatures(default_cpu, FS); + + // Initialize scheduling itinerary for the specified CPU. + InstrItins = getInstrItineraryForCPU(default_cpu); } /// SetJITMode - This is called to inform the subtarget info that we are @@ -40,9 +49,9 @@ void SPUSubtarget::SetJITMode() { /// Enable PostRA scheduling for optimization levels -O2 and -O3. bool SPUSubtarget::enablePostRAScheduler( CodeGenOpt::Level OptLevel, - TargetSubtarget::AntiDepBreakMode& Mode, + TargetSubtargetInfo::AntiDepBreakMode& Mode, RegClassVector& CriticalPathRCs) const { - Mode = TargetSubtarget::ANTIDEP_CRITICAL; + Mode = TargetSubtargetInfo::ANTIDEP_CRITICAL; // CriticalPathsRCs seems to be the set of // RegisterClasses that antidep breakings are performed for. // Do it for all register classes diff --git a/lib/Target/CellSPU/SPUSubtarget.h b/lib/Target/CellSPU/SPUSubtarget.h index d7929302f080..7c4aa1430217 100644 --- a/lib/Target/CellSPU/SPUSubtarget.h +++ b/lib/Target/CellSPU/SPUSubtarget.h @@ -7,20 +7,23 @@ // //===----------------------------------------------------------------------===// // -// This file declares the Cell SPU-specific subclass of TargetSubtarget. +// This file declares the Cell SPU-specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #ifndef CELLSUBTARGET_H #define CELLSUBTARGET_H -#include "llvm/Target/TargetInstrItineraries.h" -#include "llvm/Target/TargetSubtarget.h" - +#include "llvm/Target/TargetSubtargetInfo.h" +#include "llvm/MC/MCInstrItineraries.h" #include <string> +#define GET_SUBTARGETINFO_HEADER +#include "SPUGenSubtargetInfo.inc" + namespace llvm { class GlobalValue; + class StringRef; namespace SPU { enum { @@ -29,7 +32,7 @@ namespace llvm { }; } - class SPUSubtarget : public TargetSubtarget { + class SPUSubtarget : public SPUGenSubtargetInfo { protected: /// stackAlignment - The minimum alignment known to hold of the stack frame /// on entry to the function and which must be maintained by every function. @@ -50,12 +53,12 @@ namespace llvm { /// This constructor initializes the data members to match that /// of the specified triple. /// - SPUSubtarget(const std::string &TT, const std::string &FS); + SPUSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(StringRef CPU, StringRef FS); /// SetJITMode - This is called to inform the subtarget info that we are /// producing code for the JIT. @@ -86,7 +89,7 @@ namespace llvm { } bool enablePostRAScheduler(CodeGenOpt::Level OptLevel, - TargetSubtarget::AntiDepBreakMode& Mode, + TargetSubtargetInfo::AntiDepBreakMode& Mode, RegClassVector& CriticalPathRCs) const; }; } // End llvm namespace diff --git a/lib/Target/CellSPU/SPUTargetMachine.cpp b/lib/Target/CellSPU/SPUTargetMachine.cpp index 3ed73613a31d..3542a2b87e43 100644 --- a/lib/Target/CellSPU/SPUTargetMachine.cpp +++ b/lib/Target/CellSPU/SPUTargetMachine.cpp @@ -12,8 +12,6 @@ //===----------------------------------------------------------------------===// #include "SPU.h" -#include "SPURegisterNames.h" -#include "SPUMCAsmInfo.h" #include "SPUTargetMachine.h" #include "llvm/PassManager.h" #include "llvm/CodeGen/RegAllocRegistry.h" @@ -25,7 +23,6 @@ using namespace llvm; extern "C" void LLVMInitializeCellSPUTarget() { // Register the target. RegisterTargetMachine<SPUTargetMachine> X(TheCellSPUTarget); - RegisterAsmInfo<SPULinuxMCAsmInfo> Y(TheCellSPUTarget); } const std::pair<unsigned, int> * @@ -35,9 +32,9 @@ SPUFrameLowering::getCalleeSaveSpillSlots(unsigned &NumEntries) const { } SPUTargetMachine::SPUTargetMachine(const Target &T, const std::string &TT, - const std::string &FS) - : LLVMTargetMachine(T, TT), - Subtarget(TT, FS), + const std::string &CPU,const std::string &FS) + : LLVMTargetMachine(T, TT, CPU, FS), + Subtarget(TT, CPU, FS), DataLayout(Subtarget.getTargetDataString()), InstrInfo(*this), FrameLowering(Subtarget), diff --git a/lib/Target/CellSPU/SPUTargetMachine.h b/lib/Target/CellSPU/SPUTargetMachine.h index 75abd5eb3fca..d96f86dcaeb0 100644 --- a/lib/Target/CellSPU/SPUTargetMachine.h +++ b/lib/Target/CellSPU/SPUTargetMachine.h @@ -39,7 +39,7 @@ class SPUTargetMachine : public LLVMTargetMachine { InstrItineraryData InstrItins; public: SPUTargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); /// Return the subtarget implementation object virtual const SPUSubtarget *getSubtargetImpl() const { diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp index 797cfd597e60..10d18f61c7e2 100644 --- a/lib/Target/CppBackend/CPPBackend.cpp +++ b/lib/Target/CppBackend/CPPBackend.cpp @@ -22,7 +22,9 @@ #include "llvm/Module.h" #include "llvm/Pass.h" #include "llvm/PassManager.h" -#include "llvm/TypeSymbolTable.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" @@ -32,7 +34,7 @@ #include "llvm/Config/config.h" #include <algorithm> #include <set> - +#include <map> using namespace llvm; static cl::opt<std::string> @@ -75,6 +77,16 @@ extern "C" void LLVMInitializeCppBackendTarget() { RegisterTargetMachine<CPPTargetMachine> X(TheCppBackendTarget); } +extern "C" void LLVMInitializeCppBackendMCAsmInfo() {} + +extern "C" void LLVMInitializeCppBackendMCInstrInfo() { + RegisterMCInstrInfo<MCInstrInfo> X(TheCppBackendTarget); +} + +extern "C" void LLVMInitializeCppBackendMCSubtargetInfo() { + RegisterMCSubtargetInfo<MCSubtargetInfo> X(TheCppBackendTarget); +} + namespace { typedef std::vector<const Type*> TypeList; typedef std::map<const Type*,std::string> TypeMap; @@ -92,8 +104,6 @@ namespace { uint64_t uniqueNum; TypeMap TypeNames; ValueMap ValueNames; - TypeMap UnresolvedTypes; - TypeList TypeStack; NameSet UsedNames; TypeSet DefinedTypes; ValueSet DefinedValues; @@ -140,8 +150,7 @@ namespace { inline void printCppName(const Value* val); void printAttributes(const AttrListPtr &PAL, const std::string &name); - bool printTypeInternal(const Type* Ty); - inline void printType(const Type* Ty); + void printType(const Type* Ty); void printTypes(const Module* M); void printConstant(const Constant *CPV); @@ -188,26 +197,11 @@ static std::string getTypePrefix(const Type *Ty) { case Type::ArrayTyID: return "array_"; case Type::PointerTyID: return "ptr_"; case Type::VectorTyID: return "packed_"; - case Type::OpaqueTyID: return "opaque_"; default: return "other_"; } return "unknown_"; } -// Looks up the type in the symbol table and returns a pointer to its name or -// a null pointer if it wasn't found. Note that this isn't the same as the -// Mode::getTypeName function which will return an empty string, not a null -// pointer if the name is not found. -static const std::string * -findTypeName(const TypeSymbolTable& ST, const Type* Ty) { - TypeSymbolTable::const_iterator TI = ST.begin(); - TypeSymbolTable::const_iterator TE = ST.end(); - for (;TI != TE; ++TI) - if (TI->second == Ty) - return &(TI->first); - return 0; -} - void CppWriter::error(const std::string& msg) { report_fatal_error(msg); } @@ -379,18 +373,20 @@ std::string CppWriter::getCppName(const Type* Ty) { case Type::StructTyID: prefix = "StructTy_"; break; case Type::ArrayTyID: prefix = "ArrayTy_"; break; case Type::PointerTyID: prefix = "PointerTy_"; break; - case Type::OpaqueTyID: prefix = "OpaqueTy_"; break; case Type::VectorTyID: prefix = "VectorTy_"; break; default: prefix = "OtherTy_"; break; // prevent breakage } // See if the type has a name in the symboltable and build accordingly - const std::string* tName = findTypeName(TheModule->getTypeSymbolTable(), Ty); std::string name; - if (tName) - name = std::string(prefix) + *tName; - else - name = std::string(prefix) + utostr(uniqueNum++); + if (const StructType *STy = dyn_cast<StructType>(Ty)) + if (STy->hasName()) + name = STy->getName(); + + if (name.empty()) + name = utostr(uniqueNum++); + + name = std::string(prefix) + name; sanitize(name); // Save the name @@ -503,65 +499,38 @@ void CppWriter::printAttributes(const AttrListPtr &PAL, } } -bool CppWriter::printTypeInternal(const Type* Ty) { +void CppWriter::printType(const Type* Ty) { // We don't print definitions for primitive types if (Ty->isPrimitiveType() || Ty->isIntegerTy()) - return false; + return; // If we already defined this type, we don't need to define it again. if (DefinedTypes.find(Ty) != DefinedTypes.end()) - return false; + return; // Everything below needs the name for the type so get it now. std::string typeName(getCppName(Ty)); - // Search the type stack for recursion. If we find it, then generate this - // as an OpaqueType, but make sure not to do this multiple times because - // the type could appear in multiple places on the stack. Once the opaque - // definition is issued, it must not be re-issued. Consequently we have to - // check the UnresolvedTypes list as well. - TypeList::const_iterator TI = std::find(TypeStack.begin(), TypeStack.end(), - Ty); - if (TI != TypeStack.end()) { - TypeMap::const_iterator I = UnresolvedTypes.find(Ty); - if (I == UnresolvedTypes.end()) { - Out << "PATypeHolder " << typeName; - Out << "_fwd = OpaqueType::get(mod->getContext());"; - nl(Out); - UnresolvedTypes[Ty] = typeName; - } - return true; - } - - // We're going to print a derived type which, by definition, contains other - // types. So, push this one we're printing onto the type stack to assist with - // recursive definitions. - TypeStack.push_back(Ty); - // Print the type definition switch (Ty->getTypeID()) { case Type::FunctionTyID: { const FunctionType* FT = cast<FunctionType>(Ty); - Out << "std::vector<const Type*>" << typeName << "_args;"; + Out << "std::vector<Type*>" << typeName << "_args;"; nl(Out); FunctionType::param_iterator PI = FT->param_begin(); FunctionType::param_iterator PE = FT->param_end(); for (; PI != PE; ++PI) { const Type* argTy = static_cast<const Type*>(*PI); - bool isForward = printTypeInternal(argTy); + printType(argTy); std::string argName(getCppName(argTy)); Out << typeName << "_args.push_back(" << argName; - if (isForward) - Out << "_fwd"; Out << ");"; nl(Out); } - bool isForward = printTypeInternal(FT->getReturnType()); + printType(FT->getReturnType()); std::string retTypeName(getCppName(FT->getReturnType())); Out << "FunctionType* " << typeName << " = FunctionType::get("; in(); nl(Out) << "/*Result=*/" << retTypeName; - if (isForward) - Out << "_fwd"; Out << ","; nl(Out) << "/*Params=*/" << typeName << "_args,"; nl(Out) << "/*isVarArg=*/" << (FT->isVarArg() ? "true" : "false") << ");"; @@ -571,23 +540,37 @@ bool CppWriter::printTypeInternal(const Type* Ty) { } case Type::StructTyID: { const StructType* ST = cast<StructType>(Ty); - Out << "std::vector<const Type*>" << typeName << "_fields;"; + if (!ST->isAnonymous()) { + Out << "StructType *" << typeName << " = "; + Out << "StructType::createNamed(mod->getContext(), \""; + printEscapedString(ST->getName()); + Out << "\");"; + nl(Out); + // Indicate that this type is now defined. + DefinedTypes.insert(Ty); + } + + Out << "std::vector<Type*>" << typeName << "_fields;"; nl(Out); StructType::element_iterator EI = ST->element_begin(); StructType::element_iterator EE = ST->element_end(); for (; EI != EE; ++EI) { const Type* fieldTy = static_cast<const Type*>(*EI); - bool isForward = printTypeInternal(fieldTy); + printType(fieldTy); std::string fieldName(getCppName(fieldTy)); Out << typeName << "_fields.push_back(" << fieldName; - if (isForward) - Out << "_fwd"; Out << ");"; nl(Out); } - Out << "StructType* " << typeName << " = StructType::get(" - << "mod->getContext(), " - << typeName << "_fields, /*isPacked=*/" + + if (ST->isAnonymous()) { + Out << "StructType *" << typeName << " = "; + Out << "StructType::get(" << "mod->getContext(), "; + } else { + Out << typeName << "->setBody("; + } + + Out << typeName << "_fields, /*isPacked=*/" << (ST->isPacked() ? "true" : "false") << ");"; nl(Out); break; @@ -595,122 +578,55 @@ bool CppWriter::printTypeInternal(const Type* Ty) { case Type::ArrayTyID: { const ArrayType* AT = cast<ArrayType>(Ty); const Type* ET = AT->getElementType(); - bool isForward = printTypeInternal(ET); - std::string elemName(getCppName(ET)); - Out << "ArrayType* " << typeName << " = ArrayType::get(" - << elemName << (isForward ? "_fwd" : "") - << ", " << utostr(AT->getNumElements()) << ");"; - nl(Out); + printType(ET); + if (DefinedTypes.find(Ty) == DefinedTypes.end()) { + std::string elemName(getCppName(ET)); + Out << "ArrayType* " << typeName << " = ArrayType::get(" + << elemName + << ", " << utostr(AT->getNumElements()) << ");"; + nl(Out); + } break; } case Type::PointerTyID: { const PointerType* PT = cast<PointerType>(Ty); const Type* ET = PT->getElementType(); - bool isForward = printTypeInternal(ET); - std::string elemName(getCppName(ET)); - Out << "PointerType* " << typeName << " = PointerType::get(" - << elemName << (isForward ? "_fwd" : "") - << ", " << utostr(PT->getAddressSpace()) << ");"; - nl(Out); + printType(ET); + if (DefinedTypes.find(Ty) == DefinedTypes.end()) { + std::string elemName(getCppName(ET)); + Out << "PointerType* " << typeName << " = PointerType::get(" + << elemName + << ", " << utostr(PT->getAddressSpace()) << ");"; + nl(Out); + } break; } case Type::VectorTyID: { const VectorType* PT = cast<VectorType>(Ty); const Type* ET = PT->getElementType(); - bool isForward = printTypeInternal(ET); - std::string elemName(getCppName(ET)); - Out << "VectorType* " << typeName << " = VectorType::get(" - << elemName << (isForward ? "_fwd" : "") - << ", " << utostr(PT->getNumElements()) << ");"; - nl(Out); - break; - } - case Type::OpaqueTyID: { - Out << "OpaqueType* " << typeName; - Out << " = OpaqueType::get(mod->getContext());"; - nl(Out); + printType(ET); + if (DefinedTypes.find(Ty) == DefinedTypes.end()) { + std::string elemName(getCppName(ET)); + Out << "VectorType* " << typeName << " = VectorType::get(" + << elemName + << ", " << utostr(PT->getNumElements()) << ");"; + nl(Out); + } break; } default: error("Invalid TypeID"); } - // If the type had a name, make sure we recreate it. - const std::string* progTypeName = - findTypeName(TheModule->getTypeSymbolTable(),Ty); - if (progTypeName) { - Out << "mod->addTypeName(\"" << *progTypeName << "\", " - << typeName << ");"; - nl(Out); - } - - // Pop us off the type stack - TypeStack.pop_back(); - // Indicate that this type is now defined. DefinedTypes.insert(Ty); - // Early resolve as many unresolved types as possible. Search the unresolved - // types map for the type we just printed. Now that its definition is complete - // we can resolve any previous references to it. This prevents a cascade of - // unresolved types. - TypeMap::iterator I = UnresolvedTypes.find(Ty); - if (I != UnresolvedTypes.end()) { - Out << "cast<OpaqueType>(" << I->second - << "_fwd.get())->refineAbstractTypeTo(" << I->second << ");"; - nl(Out); - Out << I->second << " = cast<"; - switch (Ty->getTypeID()) { - case Type::FunctionTyID: Out << "FunctionType"; break; - case Type::ArrayTyID: Out << "ArrayType"; break; - case Type::StructTyID: Out << "StructType"; break; - case Type::VectorTyID: Out << "VectorType"; break; - case Type::PointerTyID: Out << "PointerType"; break; - case Type::OpaqueTyID: Out << "OpaqueType"; break; - default: Out << "NoSuchDerivedType"; break; - } - Out << ">(" << I->second << "_fwd.get());"; - nl(Out); nl(Out); - UnresolvedTypes.erase(I); - } - // Finally, separate the type definition from other with a newline. nl(Out); - - // We weren't a recursive type - return false; -} - -// Prints a type definition. Returns true if it could not resolve all the -// types in the definition but had to use a forward reference. -void CppWriter::printType(const Type* Ty) { - assert(TypeStack.empty()); - TypeStack.clear(); - printTypeInternal(Ty); - assert(TypeStack.empty()); } void CppWriter::printTypes(const Module* M) { - // Walk the symbol table and print out all its types - const TypeSymbolTable& symtab = M->getTypeSymbolTable(); - for (TypeSymbolTable::const_iterator TI = symtab.begin(), TE = symtab.end(); - TI != TE; ++TI) { - - // For primitive types and types already defined, just add a name - TypeMap::const_iterator TNI = TypeNames.find(TI->second); - if (TI->second->isIntegerTy() || TI->second->isPrimitiveType() || - TNI != TypeNames.end()) { - Out << "mod->addTypeName(\""; - printEscapedString(TI->first); - Out << "\", " << getCppName(TI->second) << ");"; - nl(Out); - // For everything else, define the type - } else { - printType(TI->second); - } - } - - // Add all of the global variables to the value table... + // Add all of the global variables to the value table. for (Module::const_global_iterator I = TheModule->global_begin(), E = TheModule->global_end(); I != E; ++I) { if (I->hasInitializer()) @@ -989,12 +905,12 @@ void CppWriter::printVariableUses(const GlobalVariable *GV) { nl(Out); printType(GV->getType()); if (GV->hasInitializer()) { - Constant *Init = GV->getInitializer(); + const Constant *Init = GV->getInitializer(); printType(Init->getType()); - if (Function *F = dyn_cast<Function>(Init)) { + if (const Function *F = dyn_cast<Function>(Init)) { nl(Out)<< "/ Function Declarations"; nl(Out); printFunctionHead(F); - } else if (GlobalVariable* gv = dyn_cast<GlobalVariable>(Init)) { + } else if (const GlobalVariable* gv = dyn_cast<GlobalVariable>(Init)) { nl(Out) << "// Global Variable Declarations"; nl(Out); printVariableHead(gv); @@ -1353,9 +1269,10 @@ void CppWriter::printInstruction(const Instruction *I, printEscapedString(phi->getName()); Out << "\", " << bbname << ");"; nl(Out); - for (unsigned i = 0; i < phi->getNumOperands(); i+=2) { + for (unsigned i = 0; i < phi->getNumIncomingValues(); ++i) { Out << iName << "->addIncoming(" - << opNames[i] << ", " << opNames[i+1] << ");"; + << opNames[PHINode::getOperandNumForIncomingValue(i)] << ", " + << getOpName(phi->getIncomingBlock(i)) << ");"; nl(Out); } break; @@ -1954,8 +1871,8 @@ void CppWriter::printVariable(const std::string& fname, Out << "}\n"; } -void CppWriter::printType(const std::string& fname, - const std::string& typeName) { +void CppWriter::printType(const std::string &fname, + const std::string &typeName) { const Type* Ty = TheModule->getTypeByName(typeName); if (!Ty) { error(std::string("Type '") + typeName + "' not found in input module"); diff --git a/lib/Target/CppBackend/CPPTargetMachine.h b/lib/Target/CppBackend/CPPTargetMachine.h index e42166e05584..7322e3e34f00 100644 --- a/lib/Target/CppBackend/CPPTargetMachine.h +++ b/lib/Target/CppBackend/CPPTargetMachine.h @@ -23,8 +23,8 @@ class formatted_raw_ostream; struct CPPTargetMachine : public TargetMachine { CPPTargetMachine(const Target &T, const std::string &TT, - const std::string &FS) - : TargetMachine(T) {} + const std::string &CPU, const std::string &FS) + : TargetMachine(T, TT, CPU, FS) {} virtual bool addPassesToEmitFile(PassManagerBase &PM, formatted_raw_ostream &Out, diff --git a/lib/Target/MBlaze/AsmParser/MBlazeAsmLexer.cpp b/lib/Target/MBlaze/AsmParser/MBlazeAsmLexer.cpp index 190379657f42..15965964452a 100644 --- a/lib/Target/MBlaze/AsmParser/MBlazeAsmLexer.cpp +++ b/lib/Target/MBlaze/AsmParser/MBlazeAsmLexer.cpp @@ -86,8 +86,9 @@ namespace { : MBlazeBaseAsmLexer(T, MAI) { std::string tripleString("mblaze-unknown-unknown"); std::string featureString; + std::string CPU; OwningPtr<const TargetMachine> - targetMachine(T.createTargetMachine(tripleString, featureString)); + targetMachine(T.createTargetMachine(tripleString, CPU, featureString)); InitRegisterMap(targetMachine->getRegisterInfo()); } }; diff --git a/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp b/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp index 524f33d19335..eebd9d878943 100644 --- a/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp +++ b/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp @@ -32,7 +32,6 @@ struct MBlazeOperand; class MBlazeAsmParser : public TargetAsmParser { MCAsmParser &Parser; - TargetMachine &TM; MCAsmParser &getParser() const { return Parser; } MCAsmLexer &getLexer() const { return Parser.getLexer(); } @@ -64,8 +63,8 @@ class MBlazeAsmParser : public TargetAsmParser { public: - MBlazeAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM) - : TargetAsmParser(T), Parser(_Parser), TM(_TM) {} + MBlazeAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser) + : TargetAsmParser(), Parser(_Parser) {} virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc, SmallVectorImpl<MCParsedAsmOperand*> &Operands); @@ -220,7 +219,7 @@ public: return StringRef(Tok.Data, Tok.Length); } - virtual void dump(raw_ostream &OS) const; + virtual void print(raw_ostream &OS) const; static MBlazeOperand *CreateToken(StringRef Str, SMLoc S) { MBlazeOperand *Op = new MBlazeOperand(Token); @@ -280,7 +279,7 @@ public: } // end anonymous namespace. -void MBlazeOperand::dump(raw_ostream &OS) const { +void MBlazeOperand::print(raw_ostream &OS) const { switch (Kind) { case Immediate: getImm()->print(OS); diff --git a/lib/Target/MBlaze/CMakeLists.txt b/lib/Target/MBlaze/CMakeLists.txt index 004057ad4ae3..0bc5b7820378 100644 --- a/lib/Target/MBlaze/CMakeLists.txt +++ b/lib/Target/MBlaze/CMakeLists.txt @@ -1,16 +1,13 @@ set(LLVM_TARGET_DEFINITIONS MBlaze.td) -tablegen(MBlazeGenRegisterInfo.h.inc -gen-register-desc-header) -tablegen(MBlazeGenRegisterNames.inc -gen-register-enums) -tablegen(MBlazeGenRegisterInfo.inc -gen-register-desc) -tablegen(MBlazeGenInstrNames.inc -gen-instr-enums) -tablegen(MBlazeGenInstrInfo.inc -gen-instr-desc) +tablegen(MBlazeGenRegisterInfo.inc -gen-register-info) +tablegen(MBlazeGenInstrInfo.inc -gen-instr-info) tablegen(MBlazeGenCodeEmitter.inc -gen-emitter) tablegen(MBlazeGenAsmWriter.inc -gen-asm-writer) tablegen(MBlazeGenAsmMatcher.inc -gen-asm-matcher) tablegen(MBlazeGenDAGISel.inc -gen-dag-isel) tablegen(MBlazeGenCallingConv.inc -gen-callingconv) -tablegen(MBlazeGenSubtarget.inc -gen-subtarget) +tablegen(MBlazeGenSubtargetInfo.inc -gen-subtarget) tablegen(MBlazeGenIntrinsics.inc -gen-tgt-intrinsic) tablegen(MBlazeGenEDInfo.inc -gen-enhanced-disassembly-info) @@ -20,7 +17,6 @@ add_llvm_target(MBlazeCodeGen MBlazeISelDAGToDAG.cpp MBlazeISelLowering.cpp MBlazeFrameLowering.cpp - MBlazeMCAsmInfo.cpp MBlazeRegisterInfo.cpp MBlazeSubtarget.cpp MBlazeTargetMachine.cpp @@ -38,3 +34,4 @@ add_subdirectory(AsmParser) add_subdirectory(Disassembler) add_subdirectory(InstPrinter) add_subdirectory(TargetInfo) +add_subdirectory(MCTargetDesc) diff --git a/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp b/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp index 060a87b7c616..88d80a12eb3a 100644 --- a/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp +++ b/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp @@ -27,9 +27,12 @@ // #include "MBlazeGenDecoderTables.inc" // #include "MBlazeGenRegisterNames.inc" -#include "MBlazeGenInstrInfo.inc" #include "MBlazeGenEDInfo.inc" +namespace llvm { +extern MCInstrDesc MBlazeInsts[]; +} + using namespace llvm; const unsigned UNSUPPORTED = -1; diff --git a/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h b/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h index 13c4b49f981c..eacca410b986 100644 --- a/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h +++ b/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h @@ -18,11 +18,10 @@ namespace llvm { class MCOperand; - class TargetMachine; class MBlazeInstPrinter : public MCInstPrinter { public: - MBlazeInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI) + MBlazeInstPrinter(const MCAsmInfo &MAI) : MCInstPrinter(MAI) {} virtual void printInst(const MCInst *MI, raw_ostream &O); diff --git a/lib/Target/MBlaze/MBlaze.h b/lib/Target/MBlaze/MBlaze.h index 00c73f06fe10..3390794c9375 100644 --- a/lib/Target/MBlaze/MBlaze.h +++ b/lib/Target/MBlaze/MBlaze.h @@ -15,6 +15,7 @@ #ifndef TARGET_MBLAZE_H #define TARGET_MBLAZE_H +#include "MCTargetDesc/MBlazeMCTargetDesc.h" #include "llvm/Target/TargetMachine.h" namespace llvm { @@ -22,26 +23,20 @@ namespace llvm { class FunctionPass; class MachineCodeEmitter; class MCCodeEmitter; + class MCInstrInfo; + class MCSubtargetInfo; class TargetAsmBackend; class formatted_raw_ostream; - MCCodeEmitter *createMBlazeMCCodeEmitter(const Target &, - TargetMachine &TM, + MCCodeEmitter *createMBlazeMCCodeEmitter(const MCInstrInfo &MCII, + const MCSubtargetInfo &STI, MCContext &Ctx); - + TargetAsmBackend *createMBlazeAsmBackend(const Target &, const std::string &); FunctionPass *createMBlazeISelDag(MBlazeTargetMachine &TM); FunctionPass *createMBlazeDelaySlotFillerPass(MBlazeTargetMachine &TM); - extern Target TheMBlazeTarget; } // end namespace llvm; -// Defines symbolic names for MBlaze registers. This defines a mapping from -// register name to register number. -#include "MBlazeGenRegisterNames.inc" - -// Defines symbolic names for the MBlaze instructions. -#include "MBlazeGenInstrNames.inc" - #endif diff --git a/lib/Target/MBlaze/MBlazeAsmPrinter.cpp b/lib/Target/MBlaze/MBlazeAsmPrinter.cpp index 0f0f60e69f08..0016df569b93 100644 --- a/lib/Target/MBlaze/MBlazeAsmPrinter.cpp +++ b/lib/Target/MBlaze/MBlazeAsmPrinter.cpp @@ -319,11 +319,10 @@ isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { } static MCInstPrinter *createMBlazeMCInstPrinter(const Target &T, - TargetMachine &TM, unsigned SyntaxVariant, const MCAsmInfo &MAI) { if (SyntaxVariant == 0) - return new MBlazeInstPrinter(TM, MAI); + return new MBlazeInstPrinter(MAI); return 0; } diff --git a/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp b/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp index 973e96844e81..c07570a487b9 100644 --- a/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp +++ b/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp @@ -109,7 +109,7 @@ static bool delayHasHazard(MachineBasicBlock::iterator &candidate, // Hazard check MachineBasicBlock::iterator a = candidate; MachineBasicBlock::iterator b = slot; - TargetInstrDesc desc = candidate->getDesc(); + MCInstrDesc desc = candidate->getDesc(); // MBB layout:- // candidate := a0 = operation(a1, a2) @@ -183,7 +183,7 @@ static bool isDelayFiller(MachineBasicBlock &MBB, if (candidate == MBB.begin()) return false; - TargetInstrDesc brdesc = (--candidate)->getDesc(); + MCInstrDesc brdesc = (--candidate)->getDesc(); return (brdesc.hasDelaySlot()); } @@ -211,7 +211,7 @@ findDelayInstr(MachineBasicBlock &MBB,MachineBasicBlock::iterator slot) { break; --I; - TargetInstrDesc desc = I->getDesc(); + MCInstrDesc desc = I->getDesc(); if (desc.hasDelaySlot() || desc.isBranch() || isDelayFiller(MBB,I) || desc.isCall() || desc.isReturn() || desc.isBarrier() || hasUnknownSideEffects(I)) diff --git a/lib/Target/MBlaze/MBlazeISelLowering.cpp b/lib/Target/MBlaze/MBlazeISelLowering.cpp index c5e0a8960ed8..62dfdcc2fd10 100644 --- a/lib/Target/MBlaze/MBlazeISelLowering.cpp +++ b/lib/Target/MBlaze/MBlazeISelLowering.cpp @@ -69,6 +69,7 @@ MBlazeTargetLowering::MBlazeTargetLowering(MBlazeTargetMachine &TM) // Floating point operations which are not supported setOperationAction(ISD::FREM, MVT::f32, Expand); + setOperationAction(ISD::FMA, MVT::f32, Expand); setOperationAction(ISD::UINT_TO_FP, MVT::i8, Expand); setOperationAction(ISD::UINT_TO_FP, MVT::i16, Expand); setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); @@ -1114,15 +1115,19 @@ MBlazeTargetLowering::getSingleConstraintMatchWeight( return weight; } -/// getRegClassForInlineAsmConstraint - Given a constraint letter (e.g. "r"), -/// return a list of registers that can be used to satisfy the constraint. -/// This should only be used for C_RegisterClass constraints. +/// Given a register class constraint, like 'r', if this corresponds directly +/// to an LLVM register class, return a register of 0 and the register class +/// pointer. std::pair<unsigned, const TargetRegisterClass*> MBlazeTargetLowering:: getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { if (Constraint.size() == 1) { switch (Constraint[0]) { case 'r': return std::make_pair(0U, MBlaze::GPRRegisterClass); + // TODO: These can't possibly be right, but match what was in + // getRegClassForInlineAsmConstraint. + case 'd': + case 'y': case 'f': if (VT == MVT::f32) return std::make_pair(0U, MBlaze::GPRRegisterClass); @@ -1131,32 +1136,6 @@ getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); } -/// Given a register class constraint, like 'r', if this corresponds directly -/// to an LLVM register class, return a register of 0 and the register class -/// pointer. -std::vector<unsigned> MBlazeTargetLowering:: -getRegClassForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { - if (Constraint.size() != 1) - return std::vector<unsigned>(); - - switch (Constraint[0]) { - default : break; - case 'r': - // GCC MBlaze Constraint Letters - case 'd': - case 'y': - case 'f': - return make_vector<unsigned>( - MBlaze::R3, MBlaze::R4, MBlaze::R5, MBlaze::R6, - MBlaze::R7, MBlaze::R9, MBlaze::R10, MBlaze::R11, - MBlaze::R12, MBlaze::R19, MBlaze::R20, MBlaze::R21, - MBlaze::R22, MBlaze::R23, MBlaze::R24, MBlaze::R25, - MBlaze::R26, MBlaze::R27, MBlaze::R28, MBlaze::R29, - MBlaze::R30, MBlaze::R31, 0); - } - return std::vector<unsigned>(); -} - bool MBlazeTargetLowering:: isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { // The MBlaze target isn't yet aware of offsets. diff --git a/lib/Target/MBlaze/MBlazeISelLowering.h b/lib/Target/MBlaze/MBlazeISelLowering.h index 265c1a709bc8..bb128da3c7c0 100644 --- a/lib/Target/MBlaze/MBlazeISelLowering.h +++ b/lib/Target/MBlaze/MBlazeISelLowering.h @@ -173,10 +173,6 @@ namespace llvm { getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; - std::vector<unsigned> - getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const; - virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; /// isFPImmLegal - Returns true if the target can instruction select the diff --git a/lib/Target/MBlaze/MBlazeInstrInfo.cpp b/lib/Target/MBlaze/MBlazeInstrInfo.cpp index 794ebedf1e6a..188f10a3972e 100644 --- a/lib/Target/MBlaze/MBlazeInstrInfo.cpp +++ b/lib/Target/MBlaze/MBlazeInstrInfo.cpp @@ -14,18 +14,21 @@ #include "MBlazeInstrInfo.h" #include "MBlazeTargetMachine.h" #include "MBlazeMachineFunction.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/ScoreboardHazardRecognizer.h" +#include "llvm/Target/TargetRegistry.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/STLExtras.h" + +#define GET_INSTRINFO_CTOR #include "MBlazeGenInstrInfo.inc" using namespace llvm; MBlazeInstrInfo::MBlazeInstrInfo(MBlazeTargetMachine &tm) - : TargetInstrInfoImpl(MBlazeInsts, array_lengthof(MBlazeInsts)), + : MBlazeGenInstrInfo(MBlaze::ADJCALLSTACKDOWN, MBlaze::ADJCALLSTACKUP), TM(tm), RI(*TM.getSubtargetImpl(), *this) {} static bool isZeroImm(const MachineOperand &op) { diff --git a/lib/Target/MBlaze/MBlazeInstrInfo.h b/lib/Target/MBlaze/MBlazeInstrInfo.h index b717da8e2bec..79f962b349bf 100644 --- a/lib/Target/MBlaze/MBlazeInstrInfo.h +++ b/lib/Target/MBlaze/MBlazeInstrInfo.h @@ -19,6 +19,9 @@ #include "llvm/Target/TargetInstrInfo.h" #include "MBlazeRegisterInfo.h" +#define GET_INSTRINFO_HEADER +#include "MBlazeGenInstrInfo.inc" + namespace llvm { namespace MBlaze { @@ -219,7 +222,7 @@ namespace MBlazeII { }; } -class MBlazeInstrInfo : public TargetInstrInfoImpl { +class MBlazeInstrInfo : public MBlazeGenInstrInfo { MBlazeTargetMachine &TM; const MBlazeRegisterInfo RI; public: diff --git a/lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp b/lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp index 7e4a2f5c945e..32d67b264a20 100644 --- a/lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp +++ b/lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp @@ -92,7 +92,7 @@ bool MBlazeIntrinsicInfo::isOverloaded(unsigned IntrID) const { static const FunctionType *getType(LLVMContext &Context, unsigned id) { const Type *ResultTy = NULL; - std::vector<const Type*> ArgTys; + std::vector<Type*> ArgTys; bool IsVarArg = false; #define GET_INTRINSIC_GENERATOR diff --git a/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp b/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp index 3ece1a8a340d..ddc636d0ce64 100644 --- a/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp +++ b/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp @@ -29,13 +29,12 @@ namespace { class MBlazeMCCodeEmitter : public MCCodeEmitter { MBlazeMCCodeEmitter(const MBlazeMCCodeEmitter &); // DO NOT IMPLEMENT void operator=(const MBlazeMCCodeEmitter &); // DO NOT IMPLEMENT - const TargetMachine &TM; - const TargetInstrInfo &TII; - MCContext &Ctx; + const MCInstrInfo &MCII; public: - MBlazeMCCodeEmitter(TargetMachine &tm, MCContext &ctx) - : TM(tm), TII(*TM.getInstrInfo()), Ctx(ctx) { + MBlazeMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti, + MCContext &ctx) + : MCII(mcii) { } ~MBlazeMCCodeEmitter() {} @@ -96,10 +95,10 @@ public: } // end anonymous namespace -MCCodeEmitter *llvm::createMBlazeMCCodeEmitter(const Target &, - TargetMachine &TM, +MCCodeEmitter *llvm::createMBlazeMCCodeEmitter(const MCInstrInfo &MCII, + const MCSubtargetInfo &STI, MCContext &Ctx) { - return new MBlazeMCCodeEmitter(TM, Ctx); + return new MBlazeMCCodeEmitter(MCII, STI, Ctx); } /// getMachineOpValue - Return binary encoding of operand. If the machine @@ -179,7 +178,7 @@ void MBlazeMCCodeEmitter:: EncodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups) const { unsigned Opcode = MI.getOpcode(); - const TargetInstrDesc &Desc = TII.get(Opcode); + const MCInstrDesc &Desc = MCII.get(Opcode); uint64_t TSFlags = Desc.TSFlags; // Keep track of the current byte being emitted. unsigned CurByte = 0; diff --git a/lib/Target/MBlaze/MBlazeRegisterInfo.cpp b/lib/Target/MBlaze/MBlazeRegisterInfo.cpp index 517279fda51e..f0b201a66170 100644 --- a/lib/Target/MBlaze/MBlazeRegisterInfo.cpp +++ b/lib/Target/MBlaze/MBlazeRegisterInfo.cpp @@ -37,12 +37,14 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" +#define GET_REGINFO_TARGET_DESC +#include "MBlazeGenRegisterInfo.inc" + using namespace llvm; MBlazeRegisterInfo:: MBlazeRegisterInfo(const MBlazeSubtarget &ST, const TargetInstrInfo &tii) - : MBlazeGenRegisterInfo(MBlaze::ADJCALLSTACKDOWN, MBlaze::ADJCALLSTACKUP), - Subtarget(ST), TII(tii) {} + : MBlazeGenRegisterInfo(), Subtarget(ST), TII(tii) {} /// getRegisterNumbering - Given the enum value for some register, e.g. /// MBlaze::R0, return the number that it corresponds to (e.g. 0). @@ -359,6 +361,3 @@ int MBlazeRegisterInfo::getDwarfRegNum(unsigned RegNo, bool isEH) const { int MBlazeRegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const { return MBlazeGenRegisterInfo::getLLVMRegNumFull(DwarfRegNo,0); } - -#include "MBlazeGenRegisterInfo.inc" - diff --git a/lib/Target/MBlaze/MBlazeRegisterInfo.h b/lib/Target/MBlaze/MBlazeRegisterInfo.h index 380783991ce1..7ebce21d3a80 100644 --- a/lib/Target/MBlaze/MBlazeRegisterInfo.h +++ b/lib/Target/MBlaze/MBlazeRegisterInfo.h @@ -17,7 +17,9 @@ #include "MBlaze.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "MBlazeGenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "MBlazeGenRegisterInfo.inc" namespace llvm { class MBlazeSubtarget; diff --git a/lib/Target/MBlaze/MBlazeRegisterInfo.td b/lib/Target/MBlaze/MBlazeRegisterInfo.td index bd396ed47b36..13c46ba1ecba 100644 --- a/lib/Target/MBlaze/MBlazeRegisterInfo.td +++ b/lib/Target/MBlaze/MBlazeRegisterInfo.td @@ -109,32 +109,9 @@ let Namespace = "MBlaze" in { // Register Classes //===----------------------------------------------------------------------===// -def GPR : RegisterClass<"MBlaze", [i32,f32], 32, - [ - // Return Values and Arguments - R3, R4, R5, R6, R7, R8, R9, R10, +def GPR : RegisterClass<"MBlaze", [i32,f32], 32, (sequence "R%u", 0, 31)>; - // Not preserved across procedure calls - R11, R12, - - // Callee save - R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, - - // Reserved - R0, // Always zero - R1, // The stack pointer - R2, // Read-only small data area anchor - R13, // Read-write small data area anchor - R14, // Return address for interrupts - R15, // Return address for sub-routines - R16, // Return address for trap - R17, // Return address for exceptions - R18, // Reserved for assembler - R19 // The frame-pointer - ]>; - -def SPR : RegisterClass<"MBlaze", [i32], 32, - [ +def SPR : RegisterClass<"MBlaze", [i32], 32, (add // Reserved RPC, RMSR, @@ -160,12 +137,12 @@ def SPR : RegisterClass<"MBlaze", [i32], 32, RPVR9, RPVR10, RPVR11 - ]> + )> { // None of the special purpose registers are allocatable. let isAllocatable = 0; } -def CRC : RegisterClass<"MBlaze", [i32], 32, [CARRY]> { +def CRC : RegisterClass<"MBlaze", [i32], 32, (add CARRY)> { let CopyCost = -1; } diff --git a/lib/Target/MBlaze/MBlazeSubtarget.cpp b/lib/Target/MBlaze/MBlazeSubtarget.cpp index a80744a4769a..eda141daf2b3 100644 --- a/lib/Target/MBlaze/MBlazeSubtarget.cpp +++ b/lib/Target/MBlaze/MBlazeSubtarget.cpp @@ -7,29 +7,42 @@ // //===----------------------------------------------------------------------===// // -// This file implements the MBlaze specific subclass of TargetSubtarget. +// This file implements the MBlaze specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #include "MBlazeSubtarget.h" #include "MBlaze.h" #include "MBlazeRegisterInfo.h" -#include "MBlazeGenSubtarget.inc" #include "llvm/Support/CommandLine.h" +#include "llvm/Target/TargetRegistry.h" + +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "MBlazeGenSubtargetInfo.inc" + using namespace llvm; -MBlazeSubtarget::MBlazeSubtarget(const std::string &TT, const std::string &FS): +MBlazeSubtarget::MBlazeSubtarget(const std::string &TT, + const std::string &CPU, + const std::string &FS): + MBlazeGenSubtargetInfo(TT, CPU, FS), HasBarrel(false), HasDiv(false), HasMul(false), HasPatCmp(false), HasFPU(false), HasMul64(false), HasSqrt(false) { // Parse features string. - std::string CPU = "mblaze"; - CPU = ParseSubtargetFeatures(FS, CPU); + std::string CPUName = CPU; + if (CPUName.empty()) + CPUName = "mblaze"; + ParseSubtargetFeatures(CPUName, FS); // Only use instruction scheduling if the selected CPU has an instruction // itinerary (the default CPU is the only one that doesn't). - HasItin = CPU != "mblaze"; - DEBUG(dbgs() << "CPU " << CPU << "(" << HasItin << ")\n"); + HasItin = CPUName != "mblaze"; + DEBUG(dbgs() << "CPU " << CPUName << "(" << HasItin << ")\n"); + + // Initialize scheduling itinerary for the specified CPU. + InstrItins = getInstrItineraryForCPU(CPUName); // Compute the issue width of the MBlaze itineraries computeIssueWidth(); @@ -41,11 +54,10 @@ void MBlazeSubtarget::computeIssueWidth() { bool MBlazeSubtarget:: enablePostRAScheduler(CodeGenOpt::Level OptLevel, - TargetSubtarget::AntiDepBreakMode& Mode, + TargetSubtargetInfo::AntiDepBreakMode& Mode, RegClassVector& CriticalPathRCs) const { - Mode = TargetSubtarget::ANTIDEP_CRITICAL; + Mode = TargetSubtargetInfo::ANTIDEP_CRITICAL; CriticalPathRCs.clear(); CriticalPathRCs.push_back(&MBlaze::GPRRegClass); return HasItin && OptLevel >= CodeGenOpt::Default; } - diff --git a/lib/Target/MBlaze/MBlazeSubtarget.h b/lib/Target/MBlaze/MBlazeSubtarget.h index 2255b2809be2..43b0197ad5aa 100644 --- a/lib/Target/MBlaze/MBlazeSubtarget.h +++ b/lib/Target/MBlaze/MBlazeSubtarget.h @@ -7,21 +7,24 @@ // //===----------------------------------------------------------------------===// // -// This file declares the MBlaze specific subclass of TargetSubtarget. +// This file declares the MBlaze specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #ifndef MBLAZESUBTARGET_H #define MBLAZESUBTARGET_H -#include "llvm/Target/TargetSubtarget.h" -#include "llvm/Target/TargetMachine.h" - +#include "llvm/Target/TargetSubtargetInfo.h" +#include "llvm/MC/MCInstrItineraries.h" #include <string> +#define GET_SUBTARGETINFO_HEADER +#include "MBlazeGenSubtargetInfo.inc" + namespace llvm { +class StringRef; -class MBlazeSubtarget : public TargetSubtarget { +class MBlazeSubtarget : public MBlazeGenSubtargetInfo { protected: bool HasBarrel; @@ -39,12 +42,12 @@ public: /// This constructor initializes the data members to match that /// of the specified triple. - MBlazeSubtarget(const std::string &TT, const std::string &FS); + MBlazeSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(StringRef CPU, StringRef FS); /// Compute the number of maximum number of issues per cycle for the /// MBlaze scheduling itineraries. @@ -52,7 +55,7 @@ public: /// enablePostRAScheduler - True at 'More' optimization. bool enablePostRAScheduler(CodeGenOpt::Level OptLevel, - TargetSubtarget::AntiDepBreakMode& Mode, + TargetSubtargetInfo::AntiDepBreakMode& Mode, RegClassVector& CriticalPathRCs) const; /// getInstrItins - Return the instruction itineraies based on subtarget. diff --git a/lib/Target/MBlaze/MBlazeTargetMachine.cpp b/lib/Target/MBlaze/MBlazeTargetMachine.cpp index df34a83e33a8..7208874aef1d 100644 --- a/lib/Target/MBlaze/MBlazeTargetMachine.cpp +++ b/lib/Target/MBlaze/MBlazeTargetMachine.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "MBlaze.h" -#include "MBlazeMCAsmInfo.h" #include "MBlazeTargetMachine.h" #include "llvm/PassManager.h" #include "llvm/CodeGen/Passes.h" @@ -21,14 +20,6 @@ #include "llvm/Target/TargetRegistry.h" using namespace llvm; -static MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) { - Triple TheTriple(TT); - switch (TheTriple.getOS()) { - default: - return new MBlazeMCAsmInfo(); - } -} - static MCStreamer *createMCStreamer(const Target &T, const std::string &TT, MCContext &Ctx, TargetAsmBackend &TAB, raw_ostream &_OS, @@ -55,9 +46,6 @@ extern "C" void LLVMInitializeMBlazeTarget() { // Register the target. RegisterTargetMachine<MBlazeTargetMachine> X(TheMBlazeTarget); - // Register the target asm info. - RegisterAsmInfoFn A(TheMBlazeTarget, createMCAsmInfo); - // Register the MC code emitter TargetRegistry::RegisterCodeEmitter(TheMBlazeTarget, llvm::createMBlazeMCCodeEmitter); @@ -80,9 +68,9 @@ extern "C" void LLVMInitializeMBlazeTarget() { // an easier handling. MBlazeTargetMachine:: MBlazeTargetMachine(const Target &T, const std::string &TT, - const std::string &FS): - LLVMTargetMachine(T, TT), - Subtarget(TT, FS), + const std::string &CPU, const std::string &FS): + LLVMTargetMachine(T, TT, CPU, FS), + Subtarget(TT, CPU, FS), DataLayout("E-p:32:32:32-i8:8:8-i16:16:16"), InstrInfo(*this), FrameLowering(Subtarget), diff --git a/lib/Target/MBlaze/MBlazeTargetMachine.h b/lib/Target/MBlaze/MBlazeTargetMachine.h index 48ce37a482fc..cd6caafbf309 100644 --- a/lib/Target/MBlaze/MBlazeTargetMachine.h +++ b/lib/Target/MBlaze/MBlazeTargetMachine.h @@ -42,7 +42,7 @@ namespace llvm { public: MBlazeTargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); virtual const MBlazeInstrInfo *getInstrInfo() const { return &InstrInfo; } diff --git a/lib/Target/MBlaze/MCTargetDesc/CMakeLists.txt b/lib/Target/MBlaze/MCTargetDesc/CMakeLists.txt new file mode 100644 index 000000000000..3d15708c35b8 --- /dev/null +++ b/lib/Target/MBlaze/MCTargetDesc/CMakeLists.txt @@ -0,0 +1,4 @@ +add_llvm_library(LLVMMBlazeDesc + MBlazeMCTargetDesc.cpp + MBlazeMCAsmInfo.cpp + ) diff --git a/lib/Target/MBlaze/MBlazeMCAsmInfo.cpp b/lib/Target/MBlaze/MCTargetDesc/MBlazeMCAsmInfo.cpp index 1467141d34ae..0d88466bb300 100644 --- a/lib/Target/MBlaze/MBlazeMCAsmInfo.cpp +++ b/lib/Target/MBlaze/MCTargetDesc/MBlazeMCAsmInfo.cpp @@ -15,6 +15,8 @@ using namespace llvm; MBlazeMCAsmInfo::MBlazeMCAsmInfo() { + IsLittleEndian = false; + StackGrowsUp = false; SupportsDebugInformation = true; AlignmentIsInBytes = false; PrivateGlobalPrefix = "$"; diff --git a/lib/Target/MBlaze/MBlazeMCAsmInfo.h b/lib/Target/MBlaze/MCTargetDesc/MBlazeMCAsmInfo.h index e68dd58b016b..e68dd58b016b 100644 --- a/lib/Target/MBlaze/MBlazeMCAsmInfo.h +++ b/lib/Target/MBlaze/MCTargetDesc/MBlazeMCAsmInfo.h diff --git a/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.cpp b/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.cpp new file mode 100644 index 000000000000..20d6c0bd2156 --- /dev/null +++ b/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.cpp @@ -0,0 +1,65 @@ +//===-- MBlazeMCTargetDesc.cpp - MBlaze Target Descriptions -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides MBlaze specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#include "MBlazeMCTargetDesc.h" +#include "MBlazeMCAsmInfo.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Target/TargetRegistry.h" + +#define GET_INSTRINFO_MC_DESC +#include "MBlazeGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_MC_DESC +#include "MBlazeGenSubtargetInfo.inc" + +#define GET_REGINFO_MC_DESC +#include "MBlazeGenRegisterInfo.inc" + +using namespace llvm; + + +static MCInstrInfo *createMBlazeMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitMBlazeMCInstrInfo(X); + return X; +} + +extern "C" void LLVMInitializeMBlazeMCInstrInfo() { + TargetRegistry::RegisterMCInstrInfo(TheMBlazeTarget, createMBlazeMCInstrInfo); +} + +static MCSubtargetInfo *createMBlazeMCSubtargetInfo(StringRef TT, StringRef CPU, + StringRef FS) { + MCSubtargetInfo *X = new MCSubtargetInfo(); + InitMBlazeMCSubtargetInfo(X, TT, CPU, FS); + return X; +} + +extern "C" void LLVMInitializeMBlazeMCSubtargetInfo() { + TargetRegistry::RegisterMCSubtargetInfo(TheMBlazeTarget, + createMBlazeMCSubtargetInfo); +} + +static MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) { + Triple TheTriple(TT); + switch (TheTriple.getOS()) { + default: + return new MBlazeMCAsmInfo(); + } +} + +extern "C" void LLVMInitializeMBlazeMCAsmInfo() { + RegisterMCAsmInfoFn X(TheMBlazeTarget, createMCAsmInfo); +} diff --git a/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.h b/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.h new file mode 100644 index 000000000000..b14772ef060b --- /dev/null +++ b/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.h @@ -0,0 +1,38 @@ +//===-- MBlazeMCTargetDesc.h - MBlaze Target Descriptions -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides MBlaze specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#ifndef MBLAZEMCTARGETDESC_H +#define MBLAZEMCTARGETDESC_H + +namespace llvm { +class MCSubtargetInfo; +class Target; +class StringRef; + +extern Target TheMBlazeTarget; + +} // End llvm namespace + +// Defines symbolic names for MBlaze registers. This defines a mapping from +// register name to register number. +#define GET_REGINFO_ENUM +#include "MBlazeGenRegisterInfo.inc" + +// Defines symbolic names for the MBlaze instructions. +#define GET_INSTRINFO_ENUM +#include "MBlazeGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "MBlazeGenSubtargetInfo.inc" + +#endif diff --git a/lib/Target/MBlaze/MCTargetDesc/Makefile b/lib/Target/MBlaze/MCTargetDesc/Makefile new file mode 100644 index 000000000000..71075ffbf47c --- /dev/null +++ b/lib/Target/MBlaze/MCTargetDesc/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/MBlaze/TargetDesc/Makefile ---------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +LIBRARYNAME = LLVMMBlazeDesc + +# Hack: we need to include 'main' target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/MBlaze/Makefile b/lib/Target/MBlaze/Makefile index e01c60bb8c65..83c2a7d34da1 100644 --- a/lib/Target/MBlaze/Makefile +++ b/lib/Target/MBlaze/Makefile @@ -11,15 +11,14 @@ LIBRARYNAME = LLVMMBlazeCodeGen TARGET = MBlaze # Make sure that tblgen is run, first thing. -BUILT_SOURCES = MBlazeGenRegisterInfo.h.inc MBlazeGenRegisterNames.inc \ - MBlazeGenRegisterInfo.inc MBlazeGenInstrNames.inc \ - MBlazeGenInstrInfo.inc MBlazeGenAsmWriter.inc \ - MBlazeGenDAGISel.inc MBlazeGenAsmMatcher.inc \ - MBlazeGenCodeEmitter.inc MBlazeGenCallingConv.inc \ - MBlazeGenSubtarget.inc MBlazeGenIntrinsics.inc \ - MBlazeGenEDInfo.inc +BUILT_SOURCES = MBlazeGenRegisterInfo.inc MBlazeGenInstrInfo.inc \ + MBlazeGenAsmWriter.inc \ + MBlazeGenDAGISel.inc MBlazeGenAsmMatcher.inc \ + MBlazeGenCodeEmitter.inc MBlazeGenCallingConv.inc \ + MBlazeGenSubtargetInfo.inc MBlazeGenIntrinsics.inc \ + MBlazeGenEDInfo.inc -DIRS = InstPrinter AsmParser Disassembler TargetInfo +DIRS = InstPrinter AsmParser Disassembler TargetInfo MCTargetDesc include $(LEVEL)/Makefile.common diff --git a/lib/Target/MSP430/CMakeLists.txt b/lib/Target/MSP430/CMakeLists.txt index 2c7cbb64418f..33f3d449ed99 100644 --- a/lib/Target/MSP430/CMakeLists.txt +++ b/lib/Target/MSP430/CMakeLists.txt @@ -1,14 +1,11 @@ set(LLVM_TARGET_DEFINITIONS MSP430.td) -tablegen(MSP430GenRegisterInfo.h.inc -gen-register-desc-header) -tablegen(MSP430GenRegisterNames.inc -gen-register-enums) -tablegen(MSP430GenRegisterInfo.inc -gen-register-desc) -tablegen(MSP430GenInstrNames.inc -gen-instr-enums) -tablegen(MSP430GenInstrInfo.inc -gen-instr-desc) +tablegen(MSP430GenRegisterInfo.inc -gen-register-info) +tablegen(MSP430GenInstrInfo.inc -gen-instr-info) tablegen(MSP430GenAsmWriter.inc -gen-asm-writer) tablegen(MSP430GenDAGISel.inc -gen-dag-isel) tablegen(MSP430GenCallingConv.inc -gen-callingconv) -tablegen(MSP430GenSubtarget.inc -gen-subtarget) +tablegen(MSP430GenSubtargetInfo.inc -gen-subtarget) add_llvm_target(MSP430CodeGen MSP430BranchSelector.cpp @@ -16,7 +13,6 @@ add_llvm_target(MSP430CodeGen MSP430ISelLowering.cpp MSP430InstrInfo.cpp MSP430FrameLowering.cpp - MSP430MCAsmInfo.cpp MSP430RegisterInfo.cpp MSP430Subtarget.cpp MSP430TargetMachine.cpp @@ -27,3 +23,4 @@ add_llvm_target(MSP430CodeGen add_subdirectory(InstPrinter) add_subdirectory(TargetInfo) +add_subdirectory(MCTargetDesc) diff --git a/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h b/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h index 63860dcc7e3a..50d98b7c41fd 100644 --- a/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h +++ b/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h @@ -18,11 +18,10 @@ namespace llvm { class MCOperand; - class TargetMachine; class MSP430InstPrinter : public MCInstPrinter { public: - MSP430InstPrinter(TargetMachine &TM, const MCAsmInfo &MAI) + MSP430InstPrinter(const MCAsmInfo &MAI) : MCInstPrinter(MAI) {} virtual void printInst(const MCInst *MI, raw_ostream &O); diff --git a/lib/Target/MSP430/MCTargetDesc/CMakeLists.txt b/lib/Target/MSP430/MCTargetDesc/CMakeLists.txt new file mode 100644 index 000000000000..0f3ebd303924 --- /dev/null +++ b/lib/Target/MSP430/MCTargetDesc/CMakeLists.txt @@ -0,0 +1,4 @@ +add_llvm_library(LLVMMSP430Desc + MSP430MCTargetDesc.cpp + MSP430MCAsmInfo.cpp + ) diff --git a/lib/Target/MSP430/MSP430MCAsmInfo.cpp b/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp index 3f4494460554..ad7d380b5631 100644 --- a/lib/Target/MSP430/MSP430MCAsmInfo.cpp +++ b/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp @@ -15,6 +15,8 @@ using namespace llvm; MSP430MCAsmInfo::MSP430MCAsmInfo(const Target &T, StringRef TT) { + PointerSize = 2; + PrivateGlobalPrefix = ".L"; WeakRefDirective ="\t.weak\t"; PCSymbol="."; diff --git a/lib/Target/MSP430/MSP430MCAsmInfo.h b/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.h index f3138a22022d..f3138a22022d 100644 --- a/lib/Target/MSP430/MSP430MCAsmInfo.h +++ b/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.h diff --git a/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp b/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp new file mode 100644 index 000000000000..43a704d7a7df --- /dev/null +++ b/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp @@ -0,0 +1,58 @@ +//===-- MSP430MCTargetDesc.cpp - MSP430 Target Descriptions -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides MSP430 specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#include "MSP430MCTargetDesc.h" +#include "MSP430MCAsmInfo.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Target/TargetRegistry.h" + +#define GET_INSTRINFO_MC_DESC +#include "MSP430GenInstrInfo.inc" + +#define GET_SUBTARGETINFO_MC_DESC +#include "MSP430GenSubtargetInfo.inc" + +#define GET_REGINFO_MC_DESC +#include "MSP430GenRegisterInfo.inc" + +using namespace llvm; + + +static MCInstrInfo *createMSP430MCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitMSP430MCInstrInfo(X); + return X; +} + +extern "C" void LLVMInitializeMSP430MCInstrInfo() { + TargetRegistry::RegisterMCInstrInfo(TheMSP430Target, createMSP430MCInstrInfo); +} + + +static MCSubtargetInfo *createMSP430MCSubtargetInfo(StringRef TT, StringRef CPU, + StringRef FS) { + MCSubtargetInfo *X = new MCSubtargetInfo(); + InitMSP430MCSubtargetInfo(X, TT, CPU, FS); + return X; +} + +extern "C" void LLVMInitializeMSP430MCSubtargetInfo() { + TargetRegistry::RegisterMCSubtargetInfo(TheMSP430Target, + createMSP430MCSubtargetInfo); +} + +extern "C" void LLVMInitializeMSP430MCAsmInfo() { + RegisterMCAsmInfo<MSP430MCAsmInfo> X(TheMSP430Target); +} diff --git a/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.h b/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.h new file mode 100644 index 000000000000..0d8a6bdb44f9 --- /dev/null +++ b/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.h @@ -0,0 +1,38 @@ +//===-- MSP430MCTargetDesc.h - MSP430 Target Descriptions -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides MSP430 specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#ifndef ALPHAMCTARGETDESC_H +#define ALPHAMCTARGETDESC_H + +namespace llvm { +class MCSubtargetInfo; +class Target; +class StringRef; + +extern Target TheMSP430Target; + +} // End llvm namespace + +// Defines symbolic names for MSP430 registers. +// This defines a mapping from register name to register number. +#define GET_REGINFO_ENUM +#include "MSP430GenRegisterInfo.inc" + +// Defines symbolic names for the MSP430 instructions. +#define GET_INSTRINFO_ENUM +#include "MSP430GenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "MSP430GenSubtargetInfo.inc" + +#endif diff --git a/lib/Target/MSP430/MCTargetDesc/Makefile b/lib/Target/MSP430/MCTargetDesc/Makefile new file mode 100644 index 000000000000..bb857998eef9 --- /dev/null +++ b/lib/Target/MSP430/MCTargetDesc/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/MSP430/TargetDesc/Makefile ---------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +LIBRARYNAME = LLVMMSP430Desc + +# Hack: we need to include 'main' target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/MSP430/MSP430.h b/lib/Target/MSP430/MSP430.h index e74211807c0d..4574ce5f98b7 100644 --- a/lib/Target/MSP430/MSP430.h +++ b/lib/Target/MSP430/MSP430.h @@ -15,6 +15,7 @@ #ifndef LLVM_TARGET_MSP430_H #define LLVM_TARGET_MSP430_H +#include "MCTargetDesc/MSP430MCTargetDesc.h" #include "llvm/Target/TargetMachine.h" namespace MSP430CC { @@ -41,15 +42,6 @@ namespace llvm { FunctionPass *createMSP430BranchSelectionPass(); - extern Target TheMSP430Target; - } // end namespace llvm; -// Defines symbolic names for MSP430 registers. -// This defines a mapping from register name to register number. -#include "MSP430GenRegisterNames.inc" - -// Defines symbolic names for the MSP430 instructions. -#include "MSP430GenInstrNames.inc" - #endif diff --git a/lib/Target/MSP430/MSP430AsmPrinter.cpp b/lib/Target/MSP430/MSP430AsmPrinter.cpp index 5264d680d8b3..2042056617ac 100644 --- a/lib/Target/MSP430/MSP430AsmPrinter.cpp +++ b/lib/Target/MSP430/MSP430AsmPrinter.cpp @@ -15,7 +15,6 @@ #define DEBUG_TYPE "asm-printer" #include "MSP430.h" #include "MSP430InstrInfo.h" -#include "MSP430MCAsmInfo.h" #include "MSP430MCInstLower.h" #include "MSP430TargetMachine.h" #include "InstPrinter/MSP430InstPrinter.h" @@ -28,6 +27,7 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" @@ -164,11 +164,10 @@ void MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) { } static MCInstPrinter *createMSP430MCInstPrinter(const Target &T, - TargetMachine &TM, unsigned SyntaxVariant, const MCAsmInfo &MAI) { if (SyntaxVariant == 0) - return new MSP430InstPrinter(TM, MAI); + return new MSP430InstPrinter(MAI); return 0; } diff --git a/lib/Target/MSP430/MSP430InstrInfo.cpp b/lib/Target/MSP430/MSP430InstrInfo.cpp index 424df136cc16..846d09361b33 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.cpp +++ b/lib/Target/MSP430/MSP430InstrInfo.cpp @@ -15,18 +15,21 @@ #include "MSP430InstrInfo.h" #include "MSP430MachineFunctionInfo.h" #include "MSP430TargetMachine.h" -#include "MSP430GenInstrInfo.inc" #include "llvm/Function.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Target/TargetRegistry.h" #include "llvm/Support/ErrorHandling.h" +#define GET_INSTRINFO_CTOR +#include "MSP430GenInstrInfo.inc" + using namespace llvm; MSP430InstrInfo::MSP430InstrInfo(MSP430TargetMachine &tm) - : TargetInstrInfoImpl(MSP430Insts, array_lengthof(MSP430Insts)), + : MSP430GenInstrInfo(MSP430::ADJCALLSTACKDOWN, MSP430::ADJCALLSTACKUP), RI(tm, *this), TM(tm) {} void MSP430InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, @@ -158,13 +161,13 @@ ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const { } bool MSP430InstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const { - const TargetInstrDesc &TID = MI->getDesc(); - if (!TID.isTerminator()) return false; + const MCInstrDesc &MCID = MI->getDesc(); + if (!MCID.isTerminator()) return false; // Conditional branch is a special case. - if (TID.isBranch() && !TID.isBarrier()) + if (MCID.isBranch() && !MCID.isBarrier()) return true; - if (!TID.isPredicable()) + if (!MCID.isPredicable()) return true; return !isPredicated(MI); } @@ -293,7 +296,7 @@ MSP430InstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, /// instruction may be. This returns the maximum number of bytes. /// unsigned MSP430InstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { - const TargetInstrDesc &Desc = MI->getDesc(); + const MCInstrDesc &Desc = MI->getDesc(); switch (Desc.TSFlags & MSP430II::SizeMask) { default: diff --git a/lib/Target/MSP430/MSP430InstrInfo.h b/lib/Target/MSP430/MSP430InstrInfo.h index e885cd36a041..90013f5c2e70 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.h +++ b/lib/Target/MSP430/MSP430InstrInfo.h @@ -17,6 +17,9 @@ #include "llvm/Target/TargetInstrInfo.h" #include "MSP430RegisterInfo.h" +#define GET_INSTRINFO_HEADER +#include "MSP430GenInstrInfo.inc" + namespace llvm { class MSP430TargetMachine; @@ -37,7 +40,7 @@ namespace MSP430II { }; } -class MSP430InstrInfo : public TargetInstrInfoImpl { +class MSP430InstrInfo : public MSP430GenInstrInfo { const MSP430RegisterInfo RI; MSP430TargetMachine &TM; public: diff --git a/lib/Target/MSP430/MSP430RegisterInfo.cpp b/lib/Target/MSP430/MSP430RegisterInfo.cpp index 53f4c2e4a887..1cc60bba3a55 100644 --- a/lib/Target/MSP430/MSP430RegisterInfo.cpp +++ b/lib/Target/MSP430/MSP430RegisterInfo.cpp @@ -26,13 +26,15 @@ #include "llvm/ADT/BitVector.h" #include "llvm/Support/ErrorHandling.h" +#define GET_REGINFO_TARGET_DESC +#include "MSP430GenRegisterInfo.inc" + using namespace llvm; // FIXME: Provide proper call frame setup / destroy opcodes. MSP430RegisterInfo::MSP430RegisterInfo(MSP430TargetMachine &tm, const TargetInstrInfo &tii) - : MSP430GenRegisterInfo(MSP430::ADJCALLSTACKDOWN, MSP430::ADJCALLSTACKUP), - TM(tm), TII(tii) { + : MSP430GenRegisterInfo(), TM(tm), TII(tii) { StackAlign = TM.getFrameLowering()->getStackAlignment(); } @@ -117,12 +119,12 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, Amount = (Amount+StackAlign-1)/StackAlign*StackAlign; MachineInstr *New = 0; - if (Old->getOpcode() == getCallFrameSetupOpcode()) { + if (Old->getOpcode() == TII.getCallFrameSetupOpcode()) { New = BuildMI(MF, Old->getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SPW) .addReg(MSP430::SPW).addImm(Amount); } else { - assert(Old->getOpcode() == getCallFrameDestroyOpcode()); + assert(Old->getOpcode() == TII.getCallFrameDestroyOpcode()); // factor out the amount the callee already popped. uint64_t CalleeAmt = Old->getOperand(1).getImm(); Amount -= CalleeAmt; @@ -140,7 +142,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MBB.insert(I, New); } } - } else if (I->getOpcode() == getCallFrameDestroyOpcode()) { + } else if (I->getOpcode() == TII.getCallFrameDestroyOpcode()) { // If we are performing frame pointer elimination and if the callee pops // something off the stack pointer, add it back. if (uint64_t CalleeAmt = I->getOperand(1).getImm()) { @@ -250,5 +252,3 @@ int MSP430RegisterInfo::getLLVMRegNum(unsigned RegNum, bool isEH) const { llvm_unreachable("Not implemented yet!"); return 0; } - -#include "MSP430GenRegisterInfo.inc" diff --git a/lib/Target/MSP430/MSP430RegisterInfo.h b/lib/Target/MSP430/MSP430RegisterInfo.h index e82055876f25..fb70594ab37c 100644 --- a/lib/Target/MSP430/MSP430RegisterInfo.h +++ b/lib/Target/MSP430/MSP430RegisterInfo.h @@ -15,7 +15,9 @@ #define LLVM_TARGET_MSP430REGISTERINFO_H #include "llvm/Target/TargetRegisterInfo.h" -#include "MSP430GenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "MSP430GenRegisterInfo.inc" namespace llvm { diff --git a/lib/Target/MSP430/MSP430RegisterInfo.td b/lib/Target/MSP430/MSP430RegisterInfo.td index 3ef6ab219def..d1c2e3f7915c 100644 --- a/lib/Target/MSP430/MSP430RegisterInfo.td +++ b/lib/Target/MSP430/MSP430RegisterInfo.td @@ -66,19 +66,19 @@ def R15W : MSP430RegWithSubregs<15, "r15", [R15B]>; def GR8 : RegisterClass<"MSP430", [i8], 8, // Volatile registers - [R12B, R13B, R14B, R15B, R11B, R10B, R9B, R8B, R7B, R6B, R5B, + (add R12B, R13B, R14B, R15B, R11B, R10B, R9B, R8B, R7B, R6B, R5B, // Frame pointer, sometimes allocable FPB, // Volatile, but not allocable - PCB, SPB, SRB, CGB]>; + PCB, SPB, SRB, CGB)>; def GR16 : RegisterClass<"MSP430", [i16], 16, // Volatile registers - [R12W, R13W, R14W, R15W, R11W, R10W, R9W, R8W, R7W, R6W, R5W, + (add R12W, R13W, R14W, R15W, R11W, R10W, R9W, R8W, R7W, R6W, R5W, // Frame pointer, sometimes allocable FPW, // Volatile, but not allocable - PCW, SPW, SRW, CGW]> + PCW, SPW, SRW, CGW)> { let SubRegClasses = [(GR8 subreg_8bit)]; } diff --git a/lib/Target/MSP430/MSP430Subtarget.cpp b/lib/Target/MSP430/MSP430Subtarget.cpp index 1346cb9a04dc..b58c50afb982 100644 --- a/lib/Target/MSP430/MSP430Subtarget.cpp +++ b/lib/Target/MSP430/MSP430Subtarget.cpp @@ -7,19 +7,26 @@ // //===----------------------------------------------------------------------===// // -// This file implements the MSP430 specific subclass of TargetSubtarget. +// This file implements the MSP430 specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #include "MSP430Subtarget.h" #include "MSP430.h" -#include "MSP430GenSubtarget.inc" +#include "llvm/Target/TargetRegistry.h" + +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "MSP430GenSubtargetInfo.inc" using namespace llvm; -MSP430Subtarget::MSP430Subtarget(const std::string &TT, const std::string &FS) { - std::string CPU = "generic"; +MSP430Subtarget::MSP430Subtarget(const std::string &TT, + const std::string &CPU, + const std::string &FS) : + MSP430GenSubtargetInfo(TT, CPU, FS) { + std::string CPUName = "generic"; // Parse features string. - ParseSubtargetFeatures(FS, CPU); + ParseSubtargetFeatures(CPUName, FS); } diff --git a/lib/Target/MSP430/MSP430Subtarget.h b/lib/Target/MSP430/MSP430Subtarget.h index 1070544f0773..1ce5f11fe1bb 100644 --- a/lib/Target/MSP430/MSP430Subtarget.h +++ b/lib/Target/MSP430/MSP430Subtarget.h @@ -7,31 +7,35 @@ // //===----------------------------------------------------------------------===// // -// This file declares the MSP430 specific subclass of TargetSubtarget. +// This file declares the MSP430 specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #ifndef LLVM_TARGET_MSP430_SUBTARGET_H #define LLVM_TARGET_MSP430_SUBTARGET_H -#include "llvm/Target/TargetSubtarget.h" +#include "llvm/Target/TargetSubtargetInfo.h" + +#define GET_SUBTARGETINFO_HEADER +#include "MSP430GenSubtargetInfo.inc" #include <string> namespace llvm { +class StringRef; -class MSP430Subtarget : public TargetSubtarget { +class MSP430Subtarget : public MSP430GenSubtargetInfo { bool ExtendedInsts; public: /// This constructor initializes the data members to match that /// of the specified triple. /// - MSP430Subtarget(const std::string &TT, const std::string &FS); + MSP430Subtarget(const std::string &TT, const std::string &CPU, + const std::string &FS); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(StringRef CPU, StringRef FS); }; } // End llvm namespace diff --git a/lib/Target/MSP430/MSP430TargetMachine.cpp b/lib/Target/MSP430/MSP430TargetMachine.cpp index fba95365a6a4..971f512141e8 100644 --- a/lib/Target/MSP430/MSP430TargetMachine.cpp +++ b/lib/Target/MSP430/MSP430TargetMachine.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "MSP430.h" -#include "MSP430MCAsmInfo.h" #include "MSP430TargetMachine.h" #include "llvm/PassManager.h" #include "llvm/CodeGen/Passes.h" @@ -23,14 +22,14 @@ using namespace llvm; extern "C" void LLVMInitializeMSP430Target() { // Register the target. RegisterTargetMachine<MSP430TargetMachine> X(TheMSP430Target); - RegisterAsmInfo<MSP430MCAsmInfo> Z(TheMSP430Target); } MSP430TargetMachine::MSP430TargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) - : LLVMTargetMachine(T, TT), - Subtarget(TT, FS), + : LLVMTargetMachine(T, TT, CPU, FS), + Subtarget(TT, CPU, FS), // FIXME: Check TargetData string. DataLayout("e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16"), InstrInfo(*this), TLInfo(*this), TSInfo(*this), diff --git a/lib/Target/MSP430/MSP430TargetMachine.h b/lib/Target/MSP430/MSP430TargetMachine.h index cee3b0480596..2a9eea0bcd82 100644 --- a/lib/Target/MSP430/MSP430TargetMachine.h +++ b/lib/Target/MSP430/MSP430TargetMachine.h @@ -39,7 +39,7 @@ class MSP430TargetMachine : public LLVMTargetMachine { public: MSP430TargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); virtual const TargetFrameLowering *getFrameLowering() const { return &FrameLowering; diff --git a/lib/Target/MSP430/Makefile b/lib/Target/MSP430/Makefile index fa4e80b0ff37..82216edd81e4 100644 --- a/lib/Target/MSP430/Makefile +++ b/lib/Target/MSP430/Makefile @@ -12,13 +12,12 @@ LIBRARYNAME = LLVMMSP430CodeGen TARGET = MSP430 # Make sure that tblgen is run, first thing. -BUILT_SOURCES = MSP430GenRegisterInfo.h.inc MSP430GenRegisterNames.inc \ - MSP430GenRegisterInfo.inc MSP430GenInstrNames.inc \ - MSP430GenInstrInfo.inc MSP430GenAsmWriter.inc \ +BUILT_SOURCES = MSP430GenRegisterInfo.inc MSP430GenInstrInfo.inc \ + MSP430GenAsmWriter.inc \ MSP430GenDAGISel.inc MSP430GenCallingConv.inc \ - MSP430GenSubtarget.inc + MSP430GenSubtargetInfo.inc -DIRS = InstPrinter TargetInfo +DIRS = InstPrinter TargetInfo MCTargetDesc include $(LEVEL)/Makefile.common diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt index fd16516f3851..36ab1a97e4f8 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -1,14 +1,11 @@ set(LLVM_TARGET_DEFINITIONS Mips.td) -tablegen(MipsGenRegisterInfo.h.inc -gen-register-desc-header) -tablegen(MipsGenRegisterNames.inc -gen-register-enums) -tablegen(MipsGenRegisterInfo.inc -gen-register-desc) -tablegen(MipsGenInstrNames.inc -gen-instr-enums) -tablegen(MipsGenInstrInfo.inc -gen-instr-desc) +tablegen(MipsGenRegisterInfo.inc -gen-register-info) +tablegen(MipsGenInstrInfo.inc -gen-instr-info) tablegen(MipsGenAsmWriter.inc -gen-asm-writer) tablegen(MipsGenDAGISel.inc -gen-dag-isel) tablegen(MipsGenCallingConv.inc -gen-callingconv) -tablegen(MipsGenSubtarget.inc -gen-subtarget) +tablegen(MipsGenSubtargetInfo.inc -gen-subtarget) add_llvm_target(MipsCodeGen MipsAsmPrinter.cpp @@ -19,7 +16,8 @@ add_llvm_target(MipsCodeGen MipsISelDAGToDAG.cpp MipsISelLowering.cpp MipsFrameLowering.cpp - MipsMCAsmInfo.cpp + MipsMCInstLower.cpp + MipsMCSymbolRefExpr.cpp MipsRegisterInfo.cpp MipsSubtarget.cpp MipsTargetMachine.cpp @@ -27,4 +25,6 @@ add_llvm_target(MipsCodeGen MipsSelectionDAGInfo.cpp ) +add_subdirectory(InstPrinter) add_subdirectory(TargetInfo) +add_subdirectory(MCTargetDesc) diff --git a/lib/Target/Mips/InstPrinter/CMakeLists.txt b/lib/Target/Mips/InstPrinter/CMakeLists.txt new file mode 100644 index 000000000000..8852fd4126e6 --- /dev/null +++ b/lib/Target/Mips/InstPrinter/CMakeLists.txt @@ -0,0 +1,6 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMMipsAsmPrinter + MipsInstPrinter.cpp + ) +add_dependencies(LLVMMipsAsmPrinter MipsCodeGenTable_gen) diff --git a/lib/Target/Mips/InstPrinter/Makefile b/lib/Target/Mips/InstPrinter/Makefile new file mode 100644 index 000000000000..63e38ef3e6aa --- /dev/null +++ b/lib/Target/Mips/InstPrinter/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/Mips/AsmPrinter/Makefile --------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +LIBRARYNAME = LLVMMipsAsmPrinter + +# Hack: we need to include 'main' arm target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp new file mode 100644 index 000000000000..41c1dd3919b4 --- /dev/null +++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp @@ -0,0 +1,127 @@ +//===-- MipsInstPrinter.cpp - Convert Mips MCInst to assembly syntax --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class prints an Mips MCInst to a .s file. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "MipsInstPrinter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/StringExtras.h" +using namespace llvm; + +#define GET_INSTRUCTION_NAME +#include "MipsGenAsmWriter.inc" + +const char* Mips::MipsFCCToString(Mips::CondCode CC) { + switch (CC) { + case FCOND_F: + case FCOND_T: return "f"; + case FCOND_UN: + case FCOND_OR: return "un"; + case FCOND_OEQ: + case FCOND_UNE: return "eq"; + case FCOND_UEQ: + case FCOND_ONE: return "ueq"; + case FCOND_OLT: + case FCOND_UGE: return "olt"; + case FCOND_ULT: + case FCOND_OGE: return "ult"; + case FCOND_OLE: + case FCOND_UGT: return "ole"; + case FCOND_ULE: + case FCOND_OGT: return "ule"; + case FCOND_SF: + case FCOND_ST: return "sf"; + case FCOND_NGLE: + case FCOND_GLE: return "ngle"; + case FCOND_SEQ: + case FCOND_SNE: return "seq"; + case FCOND_NGL: + case FCOND_GL: return "ngl"; + case FCOND_LT: + case FCOND_NLT: return "lt"; + case FCOND_NGE: + case FCOND_GE: return "nge"; + case FCOND_LE: + case FCOND_NLE: return "le"; + case FCOND_NGT: + case FCOND_GT: return "ngt"; + } + llvm_unreachable("Impossible condition code!"); +} + +StringRef MipsInstPrinter::getOpcodeName(unsigned Opcode) const { + return getInstructionName(Opcode); +} + +void MipsInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { + OS << '$' << LowercaseString(getRegisterName(RegNo)); +} + +void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O) { + printInstruction(MI, O); +} + +void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O) { + const MCOperand &Op = MI->getOperand(OpNo); + if (Op.isReg()) { + printRegName(O, Op.getReg()); + return; + } + + if (Op.isImm()) { + O << Op.getImm(); + return; + } + + assert(Op.isExpr() && "unknown operand kind in printOperand"); + O << *Op.getExpr(); +} + +void MipsInstPrinter::printUnsignedImm(const MCInst *MI, int opNum, + raw_ostream &O) { + const MCOperand &MO = MI->getOperand(opNum); + if (MO.isImm()) + O << (unsigned short int)MO.getImm(); + else + printOperand(MI, opNum, O); +} + +void MipsInstPrinter:: +printMemOperand(const MCInst *MI, int opNum, raw_ostream &O) { + // Load/Store memory operands -- imm($reg) + // If PIC target the target is loaded as the + // pattern lw $25,%call16($28) + printOperand(MI, opNum+1, O); + O << "("; + printOperand(MI, opNum, O); + O << ")"; +} + +void MipsInstPrinter:: +printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O) { + // when using stack locations for not load/store instructions + // print the same way as all normal 3 operand instructions. + printOperand(MI, opNum, O); + O << ", "; + printOperand(MI, opNum+1, O); + return; +} + +void MipsInstPrinter:: +printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O) { + const MCOperand& MO = MI->getOperand(opNum); + O << MipsFCCToString((Mips::CondCode)MO.getImm()); +} diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h new file mode 100644 index 000000000000..680208eb819b --- /dev/null +++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h @@ -0,0 +1,100 @@ +//===-- MipsInstPrinter.h - Convert Mips MCInst to assembly syntax ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class prints a Mips MCInst to a .s file. +// +//===----------------------------------------------------------------------===// + +#ifndef MIPSINSTPRINTER_H +#define MIPSINSTPRINTER_H +#include "llvm/MC/MCInstPrinter.h" + +namespace llvm { +// These enumeration declarations were orignally in MipsInstrInfo.h but +// had to be moved here to avoid circular dependencies between +// LLVMMipsCodeGen and LLVMMipsAsmPrinter. +namespace Mips { +// Mips Branch Codes +enum FPBranchCode { + BRANCH_F, + BRANCH_T, + BRANCH_FL, + BRANCH_TL, + BRANCH_INVALID +}; + +// Mips Condition Codes +enum CondCode { + // To be used with float branch True + FCOND_F, + FCOND_UN, + FCOND_OEQ, + FCOND_UEQ, + FCOND_OLT, + FCOND_ULT, + FCOND_OLE, + FCOND_ULE, + FCOND_SF, + FCOND_NGLE, + FCOND_SEQ, + FCOND_NGL, + FCOND_LT, + FCOND_NGE, + FCOND_LE, + FCOND_NGT, + + // To be used with float branch False + // This conditions have the same mnemonic as the + // above ones, but are used with a branch False; + FCOND_T, + FCOND_OR, + FCOND_UNE, + FCOND_ONE, + FCOND_UGE, + FCOND_OGE, + FCOND_UGT, + FCOND_OGT, + FCOND_ST, + FCOND_GLE, + FCOND_SNE, + FCOND_GL, + FCOND_NLT, + FCOND_GE, + FCOND_NLE, + FCOND_GT +}; + +const char *MipsFCCToString(Mips::CondCode CC); +} // end namespace Mips + +class TargetMachine; + +class MipsInstPrinter : public MCInstPrinter { +public: + MipsInstPrinter(const MCAsmInfo &MAI) : MCInstPrinter(MAI) {} + + // Autogenerated by tblgen. + void printInstruction(const MCInst *MI, raw_ostream &O); + static const char *getInstructionName(unsigned Opcode); + static const char *getRegisterName(unsigned RegNo); + + virtual StringRef getOpcodeName(unsigned Opcode) const; + virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; + virtual void printInst(const MCInst *MI, raw_ostream &O); + +private: + void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); + void printUnsignedImm(const MCInst *MI, int opNum, raw_ostream &O); + void printMemOperand(const MCInst *MI, int opNum, raw_ostream &O); + void printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O); + void printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O); +}; +} // end namespace llvm + +#endif diff --git a/lib/Target/Mips/MCTargetDesc/CMakeLists.txt b/lib/Target/Mips/MCTargetDesc/CMakeLists.txt new file mode 100644 index 000000000000..97de75db5347 --- /dev/null +++ b/lib/Target/Mips/MCTargetDesc/CMakeLists.txt @@ -0,0 +1,4 @@ +add_llvm_library(LLVMMipsDesc + MipsMCTargetDesc.cpp + MipsMCAsmInfo.cpp + ) diff --git a/lib/Target/Mips/MCTargetDesc/Makefile b/lib/Target/Mips/MCTargetDesc/Makefile new file mode 100644 index 000000000000..7fe2086a6e00 --- /dev/null +++ b/lib/Target/Mips/MCTargetDesc/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/Mips/TargetDesc/Makefile -----------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +LIBRARYNAME = LLVMMipsDesc + +# Hack: we need to include 'main' target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/Mips/MipsMCAsmInfo.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp index c86bf405b8e9..5d9242500f6d 100644 --- a/lib/Target/Mips/MipsMCAsmInfo.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp @@ -12,11 +12,17 @@ //===----------------------------------------------------------------------===// #include "MipsMCAsmInfo.h" +#include "llvm/ADT/Triple.h" + using namespace llvm; MipsMCAsmInfo::MipsMCAsmInfo(const Target &T, StringRef TT) { + Triple TheTriple(TT); + if (TheTriple.getArch() == Triple::mips) + IsLittleEndian = false; + AlignmentIsInBytes = false; - Data16bitsDirective = "\t.half\t"; + Data16bitsDirective = "\t.2byte\t"; Data32bitsDirective = "\t.4byte\t"; Data64bitsDirective = 0; PrivateGlobalPrefix = "$"; @@ -28,4 +34,5 @@ MipsMCAsmInfo::MipsMCAsmInfo(const Target &T, StringRef TT) { SupportsDebugInformation = true; ExceptionsType = ExceptionHandling::DwarfCFI; HasLEB128 = true; + DwarfRegNumForCFI = true; } diff --git a/lib/Target/Mips/MipsMCAsmInfo.h b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h index 41b719207b7b..41b719207b7b 100644 --- a/lib/Target/Mips/MipsMCAsmInfo.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp new file mode 100644 index 000000000000..06f0d0bfb6b9 --- /dev/null +++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp @@ -0,0 +1,58 @@ +//===-- MipsMCTargetDesc.cpp - Mips Target Descriptions ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Mips specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#include "MipsMCTargetDesc.h" +#include "MipsMCAsmInfo.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Target/TargetRegistry.h" + +#define GET_INSTRINFO_MC_DESC +#include "MipsGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_MC_DESC +#include "MipsGenSubtargetInfo.inc" + +#define GET_REGINFO_MC_DESC +#include "MipsGenRegisterInfo.inc" + +using namespace llvm; + +static MCInstrInfo *createMipsMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitMipsMCInstrInfo(X); + return X; +} + +extern "C" void LLVMInitializeMipsMCInstrInfo() { + TargetRegistry::RegisterMCInstrInfo(TheMipsTarget, createMipsMCInstrInfo); +} + + +static MCSubtargetInfo *createMipsMCSubtargetInfo(StringRef TT, StringRef CPU, + StringRef FS) { + MCSubtargetInfo *X = new MCSubtargetInfo(); + InitMipsMCSubtargetInfo(X, TT, CPU, FS); + return X; +} + +extern "C" void LLVMInitializeMipsMCSubtargetInfo() { + TargetRegistry::RegisterMCSubtargetInfo(TheMipsTarget, + createMipsMCSubtargetInfo); +} + +extern "C" void LLVMInitializeMipsMCAsmInfo() { + RegisterMCAsmInfo<MipsMCAsmInfo> X(TheMipsTarget); + RegisterMCAsmInfo<MipsMCAsmInfo> Y(TheMipselTarget); +} diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h new file mode 100644 index 000000000000..3d18f114c8bd --- /dev/null +++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h @@ -0,0 +1,39 @@ +//===-- AlphaMCTargetDesc.h - Alpha Target Descriptions ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Alpha specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#ifndef ALPHAMCTARGETDESC_H +#define ALPHAMCTARGETDESC_H + +namespace llvm { +class MCSubtargetInfo; +class Target; +class StringRef; + +extern Target TheMipsTarget; +extern Target TheMipselTarget; + +} // End llvm namespace + +// Defines symbolic names for Mips registers. This defines a mapping from +// register name to register number. +#define GET_REGINFO_ENUM +#include "MipsGenRegisterInfo.inc" + +// Defines symbolic names for the Mips instructions. +#define GET_INSTRINFO_ENUM +#include "MipsGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "MipsGenSubtargetInfo.inc" + +#endif diff --git a/lib/Target/Mips/Makefile b/lib/Target/Mips/Makefile index d16b066a624e..cc4a8aef224a 100644 --- a/lib/Target/Mips/Makefile +++ b/lib/Target/Mips/Makefile @@ -12,13 +12,12 @@ LIBRARYNAME = LLVMMipsCodeGen TARGET = Mips # Make sure that tblgen is run, first thing. -BUILT_SOURCES = MipsGenRegisterInfo.h.inc MipsGenRegisterNames.inc \ - MipsGenRegisterInfo.inc MipsGenInstrNames.inc \ - MipsGenInstrInfo.inc MipsGenAsmWriter.inc \ +BUILT_SOURCES = MipsGenRegisterInfo.inc MipsGenInstrInfo.inc \ + MipsGenAsmWriter.inc \ MipsGenDAGISel.inc MipsGenCallingConv.inc \ - MipsGenSubtarget.inc + MipsGenSubtargetInfo.inc -DIRS = TargetInfo +DIRS = InstPrinter TargetInfo MCTargetDesc include $(LEVEL)/Makefile.common diff --git a/lib/Target/Mips/Mips.h b/lib/Target/Mips/Mips.h index 76a26a9ba581..984b5adfc5f3 100644 --- a/lib/Target/Mips/Mips.h +++ b/lib/Target/Mips/Mips.h @@ -15,6 +15,7 @@ #ifndef TARGET_MIPS_H #define TARGET_MIPS_H +#include "MCTargetDesc/MipsMCTargetDesc.h" #include "llvm/Target/TargetMachine.h" namespace llvm { @@ -28,16 +29,6 @@ namespace llvm { FunctionPass *createMipsExpandPseudoPass(MipsTargetMachine &TM); FunctionPass *createMipsEmitGPRestorePass(MipsTargetMachine &TM); - extern Target TheMipsTarget; - extern Target TheMipselTarget; - } // end namespace llvm; -// Defines symbolic names for Mips registers. This defines a mapping from -// register name to register number. -#include "MipsGenRegisterNames.inc" - -// Defines symbolic names for the Mips instructions. -#include "MipsGenInstrNames.inc" - #endif diff --git a/lib/Target/Mips/Mips.td b/lib/Target/Mips/Mips.td index b79016d788f0..433cd57f34e0 100644 --- a/lib/Target/Mips/Mips.td +++ b/lib/Target/Mips/Mips.td @@ -88,6 +88,14 @@ def : Proc<"allegrex", [FeatureMips2, FeatureSingleFloat, FeatureEABI, FeatureVFPU, FeatureSEInReg, FeatureCondMov, FeatureMulDivAdd, FeatureMinMax, FeatureSwap, FeatureBitCount]>; +def MipsAsmWriter : AsmWriter { + string AsmWriterClassName = "InstPrinter"; + bit isMCAsmWriter = 1; +} + def Mips : Target { let InstructionSet = MipsInstrInfo; + + let AssemblyWriters = [MipsAsmWriter]; } + diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 8caa7cd2f754..69e03bd29724 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -13,80 +13,49 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "mips-asm-printer" +#include "MipsAsmPrinter.h" #include "Mips.h" -#include "MipsSubtarget.h" #include "MipsInstrInfo.h" -#include "MipsTargetMachine.h" #include "MipsMachineFunction.h" +#include "MipsMCInstLower.h" +#include "InstPrinter/MipsInstPrinter.h" #include "llvm/BasicBlock.h" #include "llvm/Instructions.h" -#include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCInst.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetLoweringObjectFile.h" -#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/raw_ostream.h" -using namespace llvm; - -namespace { - class MipsAsmPrinter : public AsmPrinter { - const MipsSubtarget *Subtarget; - public: - explicit MipsAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) - : AsmPrinter(TM, Streamer) { - Subtarget = &TM.getSubtarget<MipsSubtarget>(); - } +#include "llvm/Analysis/DebugInfo.h" - virtual const char *getPassName() const { - return "Mips Assembly Printer"; - } +using namespace llvm; - bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode, - raw_ostream &O); - void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); - void printUnsignedImm(const MachineInstr *MI, int opNum, raw_ostream &O); - void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, - const char *Modifier = 0); - void printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, - const char *Modifier = 0); - void printSavedRegsBitmask(raw_ostream &O); - void printHex32(unsigned int Value, raw_ostream &O); - - const char *getCurrentABIString() const; - void emitFrameDirective(); - - void printInstruction(const MachineInstr *MI, raw_ostream &O); // autogen'd. - void EmitInstruction(const MachineInstr *MI) { - SmallString<128> Str; - raw_svector_ostream OS(Str); - printInstruction(MI, OS); - OutStreamer.EmitRawText(OS.str()); - } - virtual void EmitFunctionBodyStart(); - virtual void EmitFunctionBodyEnd(); - virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock* - MBB) const; - static const char *getRegisterName(unsigned RegNo); +void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { + SmallString<128> Str; + raw_svector_ostream OS(Str); - virtual void EmitFunctionEntryLabel(); - void EmitStartOfAsmFile(Module &M); - }; -} // end of anonymous namespace + if (MI->isDebugValue()) { + PrintDebugValueComment(MI, OS); + return; + } -#include "MipsGenAsmWriter.inc" + MipsMCInstLower MCInstLowering(Mang, *MF, *this); + MCInst TmpInst0; + MCInstLowering.Lower(MI, TmpInst0); + OutStreamer.EmitInstruction(TmpInst0); +} //===----------------------------------------------------------------------===// // @@ -202,9 +171,9 @@ void MipsAsmPrinter::emitFrameDirective() { unsigned stackSize = MF->getFrameInfo()->getStackSize(); OutStreamer.EmitRawText("\t.frame\t$" + - Twine(LowercaseString(getRegisterName(stackReg))) + - "," + Twine(stackSize) + ",$" + - Twine(LowercaseString(getRegisterName(returnReg)))); + Twine(LowercaseString(MipsInstPrinter::getRegisterName(stackReg))) + + "," + Twine(stackSize) + ",$" + + Twine(LowercaseString(MipsInstPrinter::getRegisterName(returnReg)))); } /// Emit Set directives. @@ -304,6 +273,19 @@ bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, return false; } +bool MipsAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, + unsigned OpNum, unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &O) { + if (ExtraCode && ExtraCode[0]) + return true; // Unknown modifier. + + const MachineOperand &MO = MI->getOperand(OpNum); + assert(MO.isReg() && "unexpected inline asm memory operand"); + O << "0($" << MipsInstPrinter::getRegisterName(MO.getReg()) << ")"; + return false; +} + void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, raw_ostream &O) { const MachineOperand &MO = MI->getOperand(opNum); @@ -326,7 +308,8 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, switch (MO.getType()) { case MachineOperand::MO_Register: - O << '$' << LowercaseString(getRegisterName(MO.getReg())); + O << '$' + << LowercaseString(MipsInstPrinter::getRegisterName(MO.getReg())); break; case MachineOperand::MO_Immediate: @@ -380,27 +363,27 @@ void MipsAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum, } void MipsAsmPrinter:: -printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, - const char *Modifier) { - // when using stack locations for not load/store instructions - // print the same way as all normal 3 operand instructions. - if (Modifier && !strcmp(Modifier, "stackloc")) { - printOperand(MI, opNum+1, O); - O << ", "; - printOperand(MI, opNum, O); - return; - } - +printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O) { // Load/Store memory operands -- imm($reg) // If PIC target the target is loaded as the // pattern lw $25,%call16($28) - printOperand(MI, opNum, O); - O << "("; printOperand(MI, opNum+1, O); + O << "("; + printOperand(MI, opNum, O); O << ")"; } void MipsAsmPrinter:: +printMemOperandEA(const MachineInstr *MI, int opNum, raw_ostream &O) { + // when using stack locations for not load/store instructions + // print the same way as all normal 3 operand instructions. + printOperand(MI, opNum, O); + O << ", "; + printOperand(MI, opNum+1, O); + return; +} + +void MipsAsmPrinter:: printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, const char *Modifier) { const MachineOperand& MO = MI->getOperand(opNum); @@ -425,8 +408,33 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { OutStreamer.EmitRawText(StringRef("\t.previous")); } +MachineLocation +MipsAsmPrinter::getDebugValueLocation(const MachineInstr *MI) const { + // Handles frame addresses emitted in MipsInstrInfo::emitFrameIndexDebugValue. + assert(MI->getNumOperands() == 4 && "Invalid no. of machine operands!"); + assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm() && + "Unexpected MachineOperand types"); + return MachineLocation(MI->getOperand(0).getReg(), + MI->getOperand(1).getImm()); +} + +void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, + raw_ostream &OS) { + // TODO: implement +} + // Force static initialization. +static MCInstPrinter *createMipsMCInstPrinter(const Target &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI) { + return new MipsInstPrinter(MAI); +} + extern "C" void LLVMInitializeMipsAsmPrinter() { RegisterAsmPrinter<MipsAsmPrinter> X(TheMipsTarget); RegisterAsmPrinter<MipsAsmPrinter> Y(TheMipselTarget); + + TargetRegistry::RegisterMCInstPrinter(TheMipsTarget, createMipsMCInstPrinter); + TargetRegistry::RegisterMCInstPrinter(TheMipselTarget, + createMipsMCInstPrinter); } diff --git a/lib/Target/Mips/MipsAsmPrinter.h b/lib/Target/Mips/MipsAsmPrinter.h new file mode 100644 index 000000000000..16461ff1fbb0 --- /dev/null +++ b/lib/Target/Mips/MipsAsmPrinter.h @@ -0,0 +1,71 @@ +//===-- MipsAsmPrinter.h - Mips LLVM assembly writer ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Mips Assembly printer class. +// +//===----------------------------------------------------------------------===// + +#ifndef MIPSASMPRINTER_H +#define MIPSASMPRINTER_H + +#include "MipsSubtarget.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { +class MCStreamer; +class MachineInstr; +class raw_ostream; +class MachineBasicBlock; +class Module; + +class LLVM_LIBRARY_VISIBILITY MipsAsmPrinter : public AsmPrinter { + const MipsSubtarget *Subtarget; + +public: + explicit MipsAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer) { + Subtarget = &TM.getSubtarget<MipsSubtarget>(); + } + + virtual const char *getPassName() const { + return "Mips Assembly Printer"; + } + + void EmitInstruction(const MachineInstr *MI); + void printSavedRegsBitmask(raw_ostream &O); + void printHex32(unsigned int Value, raw_ostream &O); + void emitFrameDirective(); + const char *getCurrentABIString() const; + virtual void EmitFunctionEntryLabel(); + virtual void EmitFunctionBodyStart(); + virtual void EmitFunctionBodyEnd(); + virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock* + MBB) const; + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); + bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); + void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + void printUnsignedImm(const MachineInstr *MI, int opNum, raw_ostream &O); + void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + void printMemOperandEA(const MachineInstr *MI, int opNum, raw_ostream &O); + void printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, + const char *Modifier = 0); + void EmitStartOfAsmFile(Module &M); + virtual MachineLocation getDebugValueLocation(const MachineInstr *MI) const; + void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); +}; +} + +#endif + diff --git a/lib/Target/Mips/MipsCallingConv.td b/lib/Target/Mips/MipsCallingConv.td index 57aeb1d2793c..876f0fcc83ea 100644 --- a/lib/Target/Mips/MipsCallingConv.td +++ b/lib/Target/Mips/MipsCallingConv.td @@ -20,8 +20,8 @@ class CCIfSubtarget<string F, CCAction A>: // Only the return rules are defined here for O32. The rules for argument // passing are defined in MipsISelLowering.cpp. def RetCC_MipsO32 : CallingConv<[ - // i32 are returned in registers V0, V1 - CCIfType<[i32], CCAssignToReg<[V0, V1]>>, + // i32 are returned in registers V0, V1, A0, A1 + CCIfType<[i32], CCAssignToReg<[V0, V1, A0, A1]>>, // f32 are returned in registers F0, F2 CCIfType<[f32], CCAssignToReg<[F0, F2]>>, diff --git a/lib/Target/Mips/MipsDelaySlotFiller.cpp b/lib/Target/Mips/MipsDelaySlotFiller.cpp index b44a0af2d436..c3a6211399cd 100644 --- a/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -59,10 +59,10 @@ runOnMachineBasicBlock(MachineBasicBlock &MBB) { bool Changed = false; for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) { - const TargetInstrDesc& Tid = I->getDesc(); - if (Tid.hasDelaySlot() && + const MCInstrDesc& MCid = I->getDesc(); + if (MCid.hasDelaySlot() && (TM.getSubtarget<MipsSubtarget>().isMips1() || - Tid.isCall() || Tid.isBranch() || Tid.isReturn())) { + MCid.isCall() || MCid.isBranch() || MCid.isReturn())) { MachineBasicBlock::iterator J = I; ++J; BuildMI(MBB, J, I->getDebugLoc(), TII->get(Mips::NOP)); diff --git a/lib/Target/Mips/MipsEmitGPRestore.cpp b/lib/Target/Mips/MipsEmitGPRestore.cpp index f49d490565ff..03d922fe7cd6 100644 --- a/lib/Target/Mips/MipsEmitGPRestore.cpp +++ b/lib/Target/Mips/MipsEmitGPRestore.cpp @@ -64,8 +64,8 @@ bool Inserter::runOnMachineFunction(MachineFunction &F) { // Insert lw. ++I; DebugLoc dl = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); - BuildMI(MBB, I, dl, TII->get(Mips::LW), Mips::GP).addImm(0) - .addFrameIndex(FI); + BuildMI(MBB, I, dl, TII->get(Mips::LW), Mips::GP).addFrameIndex(FI) + .addImm(0); Changed = true; } @@ -77,8 +77,8 @@ bool Inserter::runOnMachineFunction(MachineFunction &F) { DebugLoc dl = I->getDebugLoc(); // emit lw $gp, ($gp save slot on stack) after jalr - BuildMI(MBB, ++I, dl, TII->get(Mips::LW), Mips::GP).addImm(0) - .addFrameIndex(FI); + BuildMI(MBB, ++I, dl, TII->get(Mips::LW), Mips::GP).addFrameIndex(FI) + .addImm(0); Changed = true; } } diff --git a/lib/Target/Mips/MipsExpandPseudo.cpp b/lib/Target/Mips/MipsExpandPseudo.cpp index 4423f5147980..a622258a4dcb 100644 --- a/lib/Target/Mips/MipsExpandPseudo.cpp +++ b/lib/Target/Mips/MipsExpandPseudo.cpp @@ -61,9 +61,9 @@ bool MipsExpandPseudo::runOnMachineBasicBlock(MachineBasicBlock& MBB) { bool Changed = false; for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end();) { - const TargetInstrDesc& Tid = I->getDesc(); + const MCInstrDesc& MCid = I->getDesc(); - switch(Tid.getOpcode()) { + switch(MCid.getOpcode()) { default: ++I; continue; @@ -87,7 +87,7 @@ void MipsExpandPseudo::ExpandBuildPairF64(MachineBasicBlock& MBB, MachineBasicBlock::iterator I) { unsigned DstReg = I->getOperand(0).getReg(); unsigned LoReg = I->getOperand(1).getReg(), HiReg = I->getOperand(2).getReg(); - const TargetInstrDesc& Mtc1Tdd = TII->get(Mips::MTC1); + const MCInstrDesc& Mtc1Tdd = TII->get(Mips::MTC1); DebugLoc dl = I->getDebugLoc(); const unsigned* SubReg = TM.getRegisterInfo()->getSubRegisters(DstReg); @@ -103,7 +103,7 @@ void MipsExpandPseudo::ExpandExtractElementF64(MachineBasicBlock& MBB, unsigned DstReg = I->getOperand(0).getReg(); unsigned SrcReg = I->getOperand(1).getReg(); unsigned N = I->getOperand(2).getImm(); - const TargetInstrDesc& Mfc1Tdd = TII->get(Mips::MFC1); + const MCInstrDesc& Mfc1Tdd = TII->get(Mips::MFC1); DebugLoc dl = I->getDebugLoc(); const unsigned* SubReg = TM.getRegisterInfo()->getSubRegisters(SrcReg); diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index d8a84ce52991..90aaeb60d06f 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -94,6 +94,10 @@ private: inline SDValue getI32Imm(unsigned Imm) { return CurDAG->getTargetConstant(Imm, MVT::i32); } + + virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, + char ConstraintCode, + std::vector<SDValue> &OutOps); }; } @@ -109,7 +113,7 @@ SDNode *MipsDAGToDAGISel::getGlobalBaseReg() { /// ComplexPattern used on MipsInstrInfo /// Used on Mips Load/Store instructions bool MipsDAGToDAGISel:: -SelectAddr(SDValue Addr, SDValue &Offset, SDValue &Base) { +SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { // if Address is FI, get the TargetFrameIndex. if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); @@ -166,7 +170,8 @@ SelectAddr(SDValue Addr, SDValue &Offset, SDValue &Base) { Addr.getOperand(0).getOpcode() == ISD::LOAD) && Addr.getOperand(1).getOpcode() == MipsISD::Lo) { SDValue LoVal = Addr.getOperand(1); - if (dyn_cast<ConstantPoolSDNode>(LoVal.getOperand(0))) { + if (isa<ConstantPoolSDNode>(LoVal.getOperand(0)) || + isa<GlobalAddressSDNode>(LoVal.getOperand(0))) { Base = Addr.getOperand(0); Offset = LoVal.getOperand(0); return true; @@ -195,7 +200,7 @@ SDNode *MipsDAGToDAGISel::SelectLoadFp64(SDNode *N) { SDValue N1 = N->getOperand(1); SDValue Offset0, Offset1, Base; - if (!SelectAddr(N1, Offset0, Base) || + if (!SelectAddr(N1, Base, Offset0) || N1.getValueType() != MVT::i32) return NULL; @@ -225,14 +230,14 @@ SDNode *MipsDAGToDAGISel::SelectLoadFp64(SDNode *N) { // lwc $f0, X($3) // lwc $f1, X+4($3) SDNode *LD0 = CurDAG->getMachineNode(Mips::LWC1, dl, MVT::f32, - MVT::Other, Offset0, Base, Chain); + MVT::Other, Base, Offset0, Chain); SDValue Undef = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, NVT), 0); SDValue I0 = CurDAG->getTargetInsertSubreg(Mips::sub_fpeven, dl, MVT::f64, Undef, SDValue(LD0, 0)); SDNode *LD1 = CurDAG->getMachineNode(Mips::LWC1, dl, MVT::f32, - MVT::Other, Offset1, Base, SDValue(LD0, 1)); + MVT::Other, Base, Offset1, SDValue(LD0, 1)); SDValue I1 = CurDAG->getTargetInsertSubreg(Mips::sub_fpodd, dl, MVT::f64, I0, SDValue(LD1, 0)); @@ -259,7 +264,7 @@ SDNode *MipsDAGToDAGISel::SelectStoreFp64(SDNode *N) { SDValue N2 = N->getOperand(2); SDValue Offset0, Offset1, Base; - if (!SelectAddr(N2, Offset0, Base) || + if (!SelectAddr(N2, Base, Offset0) || N1.getValueType() != MVT::f64 || N2.getValueType() != MVT::i32) return NULL; @@ -289,12 +294,12 @@ SDNode *MipsDAGToDAGISel::SelectStoreFp64(SDNode *N) { // Generate: // swc $f0, X($3) // swc $f1, X+4($3) - SDValue Ops0[] = { FPEven, Offset0, Base, Chain }; + SDValue Ops0[] = { FPEven, Base, Offset0, Chain }; Chain = SDValue(CurDAG->getMachineNode(Mips::SWC1, dl, MVT::Other, Ops0, 4), 0); cast<MachineSDNode>(Chain.getNode())->setMemRefs(MemRefs0, MemRefs0 + 1); - SDValue Ops1[] = { FPOdd, Offset1, Base, Chain }; + SDValue Ops1[] = { FPOdd, Base, Offset1, Chain }; Chain = SDValue(CurDAG->getMachineNode(Mips::SWC1, dl, MVT::Other, Ops1, 4), 0); cast<MachineSDNode>(Chain.getNode())->setMemRefs(MemRefs0, MemRefs0 + 1); @@ -462,6 +467,14 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { return ResNode; } +bool MipsDAGToDAGISel:: +SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, + std::vector<SDValue> &OutOps) { + assert(ConstraintCode == 'm' && "unexpected asm memory constraint"); + OutOps.push_back(Op); + return false; +} + /// createMipsISelDag - This pass converts a legalized DAG into a /// MIPS-specific DAG, ready for instruction scheduling. FunctionPass *llvm::createMipsISelDag(MipsTargetMachine &TM) { diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index fd90731f50d2..b4f4b1b4bf04 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -23,6 +23,7 @@ #include "llvm/GlobalVariable.h" #include "llvm/Intrinsics.h" #include "llvm/CallingConv.h" +#include "InstPrinter/MipsInstPrinter.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" @@ -59,6 +60,7 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::BuildPairF64: return "MipsISD::BuildPairF64"; case MipsISD::ExtractElementF64: return "MipsISD::ExtractElementF64"; case MipsISD::WrapperPIC: return "MipsISD::WrapperPIC"; + case MipsISD::DynAlloc: return "MipsISD::DynAlloc"; default: return NULL; } } @@ -144,6 +146,8 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::FLOG2, MVT::f32, Expand); setOperationAction(ISD::FLOG10, MVT::f32, Expand); setOperationAction(ISD::FEXP, MVT::f32, Expand); + setOperationAction(ISD::FMA, MVT::f32, Expand); + setOperationAction(ISD::FMA, MVT::f64, Expand); setOperationAction(ISD::EXCEPTIONADDR, MVT::i32, Expand); setOperationAction(ISD::EHSELECTION, MVT::i32, Expand); @@ -773,7 +777,7 @@ MipsTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, } BuildMI(BB, dl, TII->get(Mips::SW)) - .addReg(Incr).addImm(0).addFrameIndex(fi); + .addReg(Incr).addFrameIndex(fi).addImm(0); } BB->addSuccessor(loopMBB); @@ -784,7 +788,7 @@ MipsTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, // sc tmp1, 0(ptr) // beq tmp1, $0, loopMBB BB = loopMBB; - BuildMI(BB, dl, TII->get(Mips::LL), Oldval).addImm(0).addReg(Ptr); + BuildMI(BB, dl, TII->get(Mips::LL), Oldval).addReg(Ptr).addImm(0); BuildMI(BB, dl, TII->get(Mips::OR), Dest).addReg(Mips::ZERO).addReg(Oldval); if (Nand) { // and tmp2, oldval, incr @@ -797,10 +801,10 @@ MipsTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, } else { // lw tmp2, fi(sp) // load incr from stack // or tmp1, $zero, tmp2 - BuildMI(BB, dl, TII->get(Mips::LW), Tmp2).addImm(0).addFrameIndex(fi);; + BuildMI(BB, dl, TII->get(Mips::LW), Tmp2).addFrameIndex(fi).addImm(0); BuildMI(BB, dl, TII->get(Mips::OR), Tmp1).addReg(Mips::ZERO).addReg(Tmp2); } - BuildMI(BB, dl, TII->get(Mips::SC), Tmp1).addReg(Tmp1).addImm(0).addReg(Ptr); + BuildMI(BB, dl, TII->get(Mips::SC), Tmp1).addReg(Tmp1).addReg(Ptr).addImm(0); BuildMI(BB, dl, TII->get(Mips::BEQ)) .addReg(Tmp1).addReg(Mips::ZERO).addMBB(loopMBB); BB->addSuccessor(loopMBB); @@ -909,7 +913,7 @@ MipsTargetLowering::EmitAtomicBinaryPartword(MachineInstr *MI, } BuildMI(BB, dl, TII->get(Mips::SW)) - .addReg(Incr2).addImm(0).addFrameIndex(fi); + .addReg(Incr2).addFrameIndex(fi).addImm(0); } BB->addSuccessor(loopMBB); @@ -922,7 +926,7 @@ MipsTargetLowering::EmitAtomicBinaryPartword(MachineInstr *MI, // sc tmp9,0(addr) // beq tmp9,$0,loopMBB BB = loopMBB; - BuildMI(BB, dl, TII->get(Mips::LL), Oldval).addImm(0).addReg(Addr); + BuildMI(BB, dl, TII->get(Mips::LL), Oldval).addReg(Addr).addImm(0); if (Nand) { // and tmp6, oldval, incr2 // nor tmp7, $0, tmp6 @@ -937,13 +941,13 @@ MipsTargetLowering::EmitAtomicBinaryPartword(MachineInstr *MI, } else { // lw tmp6, fi(sp) // load incr2 from stack // or tmp7, $zero, tmp6 - BuildMI(BB, dl, TII->get(Mips::LW), Tmp6).addImm(0).addFrameIndex(fi);; + BuildMI(BB, dl, TII->get(Mips::LW), Tmp6).addFrameIndex(fi).addImm(0); BuildMI(BB, dl, TII->get(Mips::OR), Tmp7).addReg(Mips::ZERO).addReg(Tmp6); } BuildMI(BB, dl, TII->get(Mips::AND), Newval).addReg(Tmp7).addReg(Mask); BuildMI(BB, dl, TII->get(Mips::AND), Tmp8).addReg(Oldval).addReg(Mask2); BuildMI(BB, dl, TII->get(Mips::OR), Tmp9).addReg(Tmp8).addReg(Newval); - BuildMI(BB, dl, TII->get(Mips::SC), Tmp9).addReg(Tmp9).addImm(0).addReg(Addr); + BuildMI(BB, dl, TII->get(Mips::SC), Tmp9).addReg(Tmp9).addReg(Addr).addImm(0); BuildMI(BB, dl, TII->get(Mips::BEQ)) .addReg(Tmp9).addReg(Mips::ZERO).addMBB(loopMBB); BB->addSuccessor(loopMBB); @@ -1026,14 +1030,14 @@ MipsTargetLowering::EmitAtomicCmpSwap(MachineInstr *MI, // hoist "or" instruction out of the block loop2MBB. BuildMI(BB, dl, TII->get(Mips::SW)) - .addReg(Newval).addImm(0).addFrameIndex(fi); + .addReg(Newval).addFrameIndex(fi).addImm(0); BB->addSuccessor(loop1MBB); // loop1MBB: // ll dest, 0(ptr) // bne dest, oldval, exitMBB BB = loop1MBB; - BuildMI(BB, dl, TII->get(Mips::LL), Dest).addImm(0).addReg(Ptr); + BuildMI(BB, dl, TII->get(Mips::LL), Dest).addReg(Ptr).addImm(0); BuildMI(BB, dl, TII->get(Mips::BNE)) .addReg(Dest).addReg(Oldval).addMBB(exitMBB); BB->addSuccessor(exitMBB); @@ -1045,9 +1049,9 @@ MipsTargetLowering::EmitAtomicCmpSwap(MachineInstr *MI, // sc tmp1, 0(ptr) // beq tmp1, $0, loop1MBB BB = loop2MBB; - BuildMI(BB, dl, TII->get(Mips::LW), Tmp2).addImm(0).addFrameIndex(fi);; + BuildMI(BB, dl, TII->get(Mips::LW), Tmp2).addFrameIndex(fi).addImm(0); BuildMI(BB, dl, TII->get(Mips::OR), Tmp1).addReg(Mips::ZERO).addReg(Tmp2); - BuildMI(BB, dl, TII->get(Mips::SC), Tmp1).addReg(Tmp1).addImm(0).addReg(Ptr); + BuildMI(BB, dl, TII->get(Mips::SC), Tmp1).addReg(Tmp1).addReg(Ptr).addImm(0); BuildMI(BB, dl, TII->get(Mips::BEQ)) .addReg(Tmp1).addReg(Mips::ZERO).addMBB(loop1MBB); BB->addSuccessor(loop1MBB); @@ -1142,7 +1146,7 @@ MipsTargetLowering::EmitAtomicCmpSwapPartword(MachineInstr *MI, // and oldval4,oldval3,mask // bne oldval4,oldval2,exitMBB BB = loop1MBB; - BuildMI(BB, dl, TII->get(Mips::LL), Oldval3).addImm(0).addReg(Addr); + BuildMI(BB, dl, TII->get(Mips::LL), Oldval3).addReg(Addr).addImm(0); BuildMI(BB, dl, TII->get(Mips::AND), Oldval4).addReg(Oldval3).addReg(Mask); BuildMI(BB, dl, TII->get(Mips::BNE)) .addReg(Oldval4).addReg(Oldval2).addMBB(exitMBB); @@ -1158,7 +1162,7 @@ MipsTargetLowering::EmitAtomicCmpSwapPartword(MachineInstr *MI, BuildMI(BB, dl, TII->get(Mips::AND), Tmp6).addReg(Oldval3).addReg(Mask2); BuildMI(BB, dl, TII->get(Mips::OR), Tmp7).addReg(Tmp6).addReg(Newval2); BuildMI(BB, dl, TII->get(Mips::SC), Tmp7) - .addReg(Tmp7).addImm(0).addReg(Addr); + .addReg(Tmp7).addReg(Addr).addImm(0); BuildMI(BB, dl, TII->get(Mips::BEQ)) .addReg(Tmp7).addReg(Mips::ZERO).addMBB(loop1MBB); BB->addSuccessor(loop1MBB); @@ -1189,9 +1193,10 @@ MipsTargetLowering::EmitAtomicCmpSwapPartword(MachineInstr *MI, SDValue MipsTargetLowering:: LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const { - unsigned StackAlignment = - getTargetMachine().getFrameLowering()->getStackAlignment(); - assert(StackAlignment >= + MachineFunction &MF = DAG.getMachineFunction(); + MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); + + assert(getTargetMachine().getFrameLowering()->getStackAlignment() >= cast<ConstantSDNode>(Op.getOperand(2).getNode())->getZExtValue() && "Cannot lower if the alignment of the allocated space is larger than \ that of the stack."); @@ -1211,24 +1216,14 @@ LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const // must be placed in the stack pointer register. Chain = DAG.getCopyToReg(StackPointer.getValue(1), dl, Mips::SP, Sub, SDValue()); - // Retrieve updated $sp. There is a glue input to prevent instructions that - // clobber $sp from being inserted between copytoreg and copyfromreg. - SDValue NewSP = DAG.getCopyFromReg(Chain, dl, Mips::SP, MVT::i32, - Chain.getValue(1)); - - // The stack space reserved by alloca is located right above the argument - // area. It is aligned on a boundary that is a multiple of StackAlignment. - MachineFunction &MF = DAG.getMachineFunction(); - MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - unsigned SPOffset = (MipsFI->getMaxCallFrameSize() + StackAlignment - 1) / - StackAlignment * StackAlignment; - SDValue AllocPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, NewSP, - DAG.getConstant(SPOffset, MVT::i32)); // This node always has two return values: a new stack pointer // value and a chain - SDValue Ops[2] = { AllocPtr, NewSP.getValue(1) }; - return DAG.getMergeValues(Ops, 2, dl); + SDVTList VTLs = DAG.getVTList(MVT::i32, MVT::Other); + SDValue Ptr = DAG.getFrameIndex(MipsFI->getDynAllocFI(), getPointerTy()); + SDValue Ops[] = { Chain, Ptr, Chain.getValue(1) }; + + return DAG.getNode(MipsISD::DynAlloc, dl, VTLs, Ops, 3); } SDValue MipsTargetLowering:: @@ -1358,7 +1353,7 @@ LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const if (getTargetMachine().getRelocationModel() == Reloc::PIC_) { // General Dynamic TLS Model SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, - 0, MipsII::MO_TLSGD); + 0, MipsII::MO_TLSGD); SDValue Tlsgd = DAG.getNode(MipsISD::TlsGd, dl, MVT::i32, TGA); SDValue GP = DAG.getRegister(Mips::GP, MVT::i32); SDValue Argument = DAG.getNode(ISD::ADD, dl, MVT::i32, GP, Tlsgd); @@ -1370,36 +1365,36 @@ LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const Args.push_back(Entry); std::pair<SDValue, SDValue> CallResult = LowerCallTo(DAG.getEntryNode(), - (const Type *) Type::getInt32Ty(*DAG.getContext()), - false, false, false, false, - 0, CallingConv::C, false, true, - DAG.getExternalSymbol("__tls_get_addr", PtrVT), Args, DAG, dl); + (const Type *) Type::getInt32Ty(*DAG.getContext()), + false, false, false, false, 0, CallingConv::C, false, true, + DAG.getExternalSymbol("__tls_get_addr", PtrVT), Args, DAG, + dl); return CallResult.first; - } else { - SDValue Offset; - if (GV->isDeclaration()) { - // Initial Exec TLS Model - SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, - MipsII::MO_GOTTPREL); - Offset = DAG.getLoad(MVT::i32, dl, - DAG.getEntryNode(), TGA, MachinePointerInfo(), - false, false, 0); - } else { - // Local Exec TLS Model - SDVTList VTs = DAG.getVTList(MVT::i32); - SDValue TGAHi = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, - MipsII::MO_TPREL_HI); - SDValue TGALo = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, - MipsII::MO_TPREL_LO); - SDValue Hi = DAG.getNode(MipsISD::TprelHi, dl, VTs, &TGAHi, 1); - SDValue Lo = DAG.getNode(MipsISD::TprelLo, dl, MVT::i32, TGALo); - Offset = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, Lo); - } + } - SDValue ThreadPointer = DAG.getNode(MipsISD::ThreadPointer, dl, PtrVT); - return DAG.getNode(ISD::ADD, dl, PtrVT, ThreadPointer, Offset); + SDValue Offset; + if (GV->isDeclaration()) { + // Initial Exec TLS Model + SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, + MipsII::MO_GOTTPREL); + Offset = DAG.getLoad(MVT::i32, dl, + DAG.getEntryNode(), TGA, MachinePointerInfo(), + false, false, 0); + } else { + // Local Exec TLS Model + SDVTList VTs = DAG.getVTList(MVT::i32); + SDValue TGAHi = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, + MipsII::MO_TPREL_HI); + SDValue TGALo = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, + MipsII::MO_TPREL_LO); + SDValue Hi = DAG.getNode(MipsISD::TprelHi, dl, VTs, &TGAHi, 1); + SDValue Lo = DAG.getNode(MipsISD::TprelLo, dl, MVT::i32, TGALo); + Offset = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, Lo); } + + SDValue ThreadPointer = DAG.getNode(MipsISD::ThreadPointer, dl, PtrVT); + return DAG.getNode(ISD::ADD, dl, PtrVT, ThreadPointer, Offset); } SDValue MipsTargetLowering:: @@ -1550,8 +1545,8 @@ SDValue MipsTargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) SDValue MipsTargetLowering:: LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { - unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); - assert((Depth == 0) && + // check the depth + assert((cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() == 0) && "Frame address can only be determined for current frame."); MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); @@ -1770,6 +1765,10 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, if (IsPIC && !MipsFI->getGPFI()) MipsFI->setGPFI(MFI->CreateFixedObject(4, 0, true)); + // Get the frame index of the stack frame object that points to the location + // of dynamically allocated area on the stack. + int DynAllocFI = MipsFI->getDynAllocFI(); + // Update size of the maximum argument space. // For O32, a minimum of four words (16 bytes) of argument space is // allocated. @@ -1781,14 +1780,17 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, if (MaxCallFrameSize < NextStackOffset) { MipsFI->setMaxCallFrameSize(NextStackOffset); - if (IsPIC) { - // $gp restore slot must be aligned. - unsigned StackAlignment = TFL->getStackAlignment(); - NextStackOffset = (NextStackOffset + StackAlignment - 1) / - StackAlignment * StackAlignment; - int GPFI = MipsFI->getGPFI(); - MFI->setObjectOffset(GPFI, NextStackOffset); - } + // Set the offsets relative to $sp of the $gp restore slot and dynamically + // allocated stack space. These offsets must be aligned to a boundary + // determined by the stack alignment of the ABI. + unsigned StackAlignment = TFL->getStackAlignment(); + NextStackOffset = (NextStackOffset + StackAlignment - 1) / + StackAlignment * StackAlignment; + + if (IsPIC) + MFI->setObjectOffset(MipsFI->getGPFI(), NextStackOffset); + + MFI->setObjectOffset(DynAllocFI, NextStackOffset); } // With EABI is it possible to have 16 args on registers. @@ -1912,7 +1914,7 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, if (LoadSymAddr) { // Load callee address Callee = DAG.getNode(MipsISD::WrapperPIC, dl, MVT::i32, Callee); - SDValue LoadValue = DAG.getLoad(MVT::i32, dl, Chain, Callee, + SDValue LoadValue = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), Callee, MachinePointerInfo::getGOT(), false, false, 0); @@ -1922,9 +1924,6 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, Callee = DAG.getNode(ISD::ADD, dl, MVT::i32, LoadValue, Lo); } else Callee = LoadValue; - - // Use chain output from LoadValue - Chain = LoadValue.getValue(1); } // copy to T9 @@ -1965,7 +1964,8 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, InFlag = Chain.getValue(1); // Create the CALLSEQ_END node. - Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NextStackOffset, true), + Chain = DAG.getCALLSEQ_END(Chain, + DAG.getIntPtrConstant(NextStackOffset, true), DAG.getIntPtrConstant(0, true), InFlag); InFlag = Chain.getValue(1); @@ -2332,14 +2332,16 @@ MipsTargetLowering::getSingleConstraintMatchWeight( return weight; } -/// getRegClassForInlineAsmConstraint - Given a constraint letter (e.g. "r"), -/// return a list of registers that can be used to satisfy the constraint. -/// This should only be used for C_RegisterClass constraints. +/// Given a register class constraint, like 'r', if this corresponds directly +/// to an LLVM register class, return a register of 0 and the register class +/// pointer. std::pair<unsigned, const TargetRegisterClass*> MipsTargetLowering:: getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { if (Constraint.size() == 1) { switch (Constraint[0]) { + case 'd': // Address register. Same as 'r' unless generating MIPS16 code. + case 'y': // Same as 'r'. Exists for compatibility. case 'r': return std::make_pair(0U, Mips::CPURegsRegisterClass); case 'f': @@ -2348,55 +2350,12 @@ getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const if (VT == MVT::f64) if ((!Subtarget->isSingleFloat()) && (!Subtarget->isFP64bit())) return std::make_pair(0U, Mips::AFGR64RegisterClass); + break; } } return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); } -/// Given a register class constraint, like 'r', if this corresponds directly -/// to an LLVM register class, return a register of 0 and the register class -/// pointer. -std::vector<unsigned> MipsTargetLowering:: -getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const -{ - if (Constraint.size() != 1) - return std::vector<unsigned>(); - - switch (Constraint[0]) { - default : break; - case 'r': - // GCC Mips Constraint Letters - case 'd': - case 'y': - return make_vector<unsigned>(Mips::T0, Mips::T1, Mips::T2, Mips::T3, - Mips::T4, Mips::T5, Mips::T6, Mips::T7, Mips::S0, Mips::S1, - Mips::S2, Mips::S3, Mips::S4, Mips::S5, Mips::S6, Mips::S7, - Mips::T8, 0); - - case 'f': - if (VT == MVT::f32) { - if (Subtarget->isSingleFloat()) - return make_vector<unsigned>(Mips::F2, Mips::F3, Mips::F4, Mips::F5, - Mips::F6, Mips::F7, Mips::F8, Mips::F9, Mips::F10, Mips::F11, - Mips::F20, Mips::F21, Mips::F22, Mips::F23, Mips::F24, - Mips::F25, Mips::F26, Mips::F27, Mips::F28, Mips::F29, - Mips::F30, Mips::F31, 0); - else - return make_vector<unsigned>(Mips::F2, Mips::F4, Mips::F6, Mips::F8, - Mips::F10, Mips::F20, Mips::F22, Mips::F24, Mips::F26, - Mips::F28, Mips::F30, 0); - } - - if (VT == MVT::f64) - if ((!Subtarget->isSingleFloat()) && (!Subtarget->isFP64bit())) - return make_vector<unsigned>(Mips::D1, Mips::D2, Mips::D3, Mips::D4, - Mips::D5, Mips::D10, Mips::D11, Mips::D12, Mips::D13, - Mips::D14, Mips::D15, 0); - } - return std::vector<unsigned>(); -} - bool MipsTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { // The Mips target isn't yet aware of offsets. diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index fbcedfddf99a..bda26a229e72 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -79,7 +79,9 @@ namespace llvm { BuildPairF64, ExtractElementF64, - WrapperPIC + WrapperPIC, + + DynAlloc }; } @@ -167,10 +169,6 @@ namespace llvm { getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; - std::vector<unsigned> - getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const; - virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; /// isFPImmLegal - Returns true if the target can instruction select the diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index be044fa1f3b3..0a7a7f2dfe4e 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -14,18 +14,27 @@ #include "MipsInstrInfo.h" #include "MipsTargetMachine.h" #include "MipsMachineFunction.h" -#include "llvm/ADT/STLExtras.h" +#include "InstPrinter/MipsInstPrinter.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetRegistry.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/STLExtras.h" + +#define GET_INSTRINFO_CTOR #include "MipsGenInstrInfo.inc" using namespace llvm; MipsInstrInfo::MipsInstrInfo(MipsTargetMachine &tm) - : TargetInstrInfoImpl(MipsInsts, array_lengthof(MipsInsts)), + : MipsGenInstrInfo(Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP), TM(tm), RI(*TM.getSubtargetImpl(), *this) {} + +const MipsRegisterInfo &MipsInstrInfo::getRegisterInfo() const { + return RI; +} + static bool isZeroImm(const MachineOperand &op) { return op.isImm() && op.getImm() == 0; } @@ -40,10 +49,10 @@ isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const { if ((MI->getOpcode() == Mips::LW) || (MI->getOpcode() == Mips::LWC1) || (MI->getOpcode() == Mips::LDC1)) { - if ((MI->getOperand(2).isFI()) && // is a stack slot - (MI->getOperand(1).isImm()) && // the imm is zero - (isZeroImm(MI->getOperand(1)))) { - FrameIndex = MI->getOperand(2).getIndex(); + if ((MI->getOperand(1).isFI()) && // is a stack slot + (MI->getOperand(2).isImm()) && // the imm is zero + (isZeroImm(MI->getOperand(2)))) { + FrameIndex = MI->getOperand(1).getIndex(); return MI->getOperand(0).getReg(); } } @@ -61,10 +70,10 @@ isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const { if ((MI->getOpcode() == Mips::SW) || (MI->getOpcode() == Mips::SWC1) || (MI->getOpcode() == Mips::SDC1)) { - if ((MI->getOperand(2).isFI()) && // is a stack slot - (MI->getOperand(1).isImm()) && // the imm is zero - (isZeroImm(MI->getOperand(1)))) { - FrameIndex = MI->getOperand(2).getIndex(); + if ((MI->getOperand(1).isFI()) && // is a stack slot + (MI->getOperand(2).isImm()) && // the imm is zero + (isZeroImm(MI->getOperand(2)))) { + FrameIndex = MI->getOperand(1).getIndex(); return MI->getOperand(0).getReg(); } } @@ -161,25 +170,25 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, if (RC == Mips::CPURegsRegisterClass) BuildMI(MBB, I, DL, get(Mips::SW)).addReg(SrcReg, getKillRegState(isKill)) - .addImm(0).addFrameIndex(FI); + .addFrameIndex(FI).addImm(0); else if (RC == Mips::FGR32RegisterClass) BuildMI(MBB, I, DL, get(Mips::SWC1)).addReg(SrcReg, getKillRegState(isKill)) - .addImm(0).addFrameIndex(FI); + .addFrameIndex(FI).addImm(0); else if (RC == Mips::AFGR64RegisterClass) { if (!TM.getSubtarget<MipsSubtarget>().isMips1()) { BuildMI(MBB, I, DL, get(Mips::SDC1)) .addReg(SrcReg, getKillRegState(isKill)) - .addImm(0).addFrameIndex(FI); + .addFrameIndex(FI).addImm(0); } else { const TargetRegisterInfo *TRI = MBB.getParent()->getTarget().getRegisterInfo(); const unsigned *SubSet = TRI->getSubRegisters(SrcReg); BuildMI(MBB, I, DL, get(Mips::SWC1)) .addReg(SubSet[0], getKillRegState(isKill)) - .addImm(0).addFrameIndex(FI); + .addFrameIndex(FI).addImm(0); BuildMI(MBB, I, DL, get(Mips::SWC1)) .addReg(SubSet[1], getKillRegState(isKill)) - .addImm(4).addFrameIndex(FI); + .addFrameIndex(FI).addImm(4); } } else llvm_unreachable("Register class not handled!"); @@ -195,25 +204,34 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, if (I != MBB.end()) DL = I->getDebugLoc(); if (RC == Mips::CPURegsRegisterClass) - BuildMI(MBB, I, DL, get(Mips::LW), DestReg).addImm(0).addFrameIndex(FI); + BuildMI(MBB, I, DL, get(Mips::LW), DestReg).addFrameIndex(FI).addImm(0); else if (RC == Mips::FGR32RegisterClass) - BuildMI(MBB, I, DL, get(Mips::LWC1), DestReg).addImm(0).addFrameIndex(FI); + BuildMI(MBB, I, DL, get(Mips::LWC1), DestReg).addFrameIndex(FI).addImm(0); else if (RC == Mips::AFGR64RegisterClass) { if (!TM.getSubtarget<MipsSubtarget>().isMips1()) { - BuildMI(MBB, I, DL, get(Mips::LDC1), DestReg).addImm(0).addFrameIndex(FI); + BuildMI(MBB, I, DL, get(Mips::LDC1), DestReg).addFrameIndex(FI).addImm(0); } else { const TargetRegisterInfo *TRI = MBB.getParent()->getTarget().getRegisterInfo(); const unsigned *SubSet = TRI->getSubRegisters(DestReg); BuildMI(MBB, I, DL, get(Mips::LWC1), SubSet[0]) - .addImm(0).addFrameIndex(FI); + .addFrameIndex(FI).addImm(0); BuildMI(MBB, I, DL, get(Mips::LWC1), SubSet[1]) - .addImm(4).addFrameIndex(FI); + .addFrameIndex(FI).addImm(4); } } else llvm_unreachable("Register class not handled!"); } +MachineInstr* +MipsInstrInfo::emitFrameIndexDebugValue(MachineFunction &MF, int FrameIx, + uint64_t Offset, const MDNode *MDPtr, + DebugLoc DL) const { + MachineInstrBuilder MIB = BuildMI(MF, DL, get(Mips::DBG_VALUE)) + .addFrameIndex(FrameIx).addImm(0).addImm(Offset).addMetadata(MDPtr); + return &*MIB; +} + //===----------------------------------------------------------------------===// // Branch Analysis //===----------------------------------------------------------------------===// @@ -341,8 +359,8 @@ void MipsInstrInfo::BuildCondBr(MachineBasicBlock &MBB, const SmallVectorImpl<MachineOperand>& Cond) const { unsigned Opc = Cond[0].getImm(); - const TargetInstrDesc &TID = get(Opc); - MachineInstrBuilder MIB = BuildMI(&MBB, DL, TID); + const MCInstrDesc &MCID = get(Opc); + MachineInstrBuilder MIB = BuildMI(&MBB, DL, MCID); for (unsigned i = 1; i < Cond.size(); ++i) MIB.addReg(Cond[i].getReg()); diff --git a/lib/Target/Mips/MipsInstrInfo.h b/lib/Target/Mips/MipsInstrInfo.h index abf67733f083..4421c4862fa0 100644 --- a/lib/Target/Mips/MipsInstrInfo.h +++ b/lib/Target/Mips/MipsInstrInfo.h @@ -19,103 +19,15 @@ #include "llvm/Target/TargetInstrInfo.h" #include "MipsRegisterInfo.h" +#define GET_INSTRINFO_HEADER +#include "MipsGenInstrInfo.inc" + namespace llvm { namespace Mips { - - // Mips Branch Codes - enum FPBranchCode { - BRANCH_F, - BRANCH_T, - BRANCH_FL, - BRANCH_TL, - BRANCH_INVALID - }; - - // Mips Condition Codes - enum CondCode { - // To be used with float branch True - FCOND_F, - FCOND_UN, - FCOND_OEQ, - FCOND_UEQ, - FCOND_OLT, - FCOND_ULT, - FCOND_OLE, - FCOND_ULE, - FCOND_SF, - FCOND_NGLE, - FCOND_SEQ, - FCOND_NGL, - FCOND_LT, - FCOND_NGE, - FCOND_LE, - FCOND_NGT, - - // To be used with float branch False - // This conditions have the same mnemonic as the - // above ones, but are used with a branch False; - FCOND_T, - FCOND_OR, - FCOND_UNE, - FCOND_ONE, - FCOND_UGE, - FCOND_OGE, - FCOND_UGT, - FCOND_OGT, - FCOND_ST, - FCOND_GLE, - FCOND_SNE, - FCOND_GL, - FCOND_NLT, - FCOND_GE, - FCOND_NLE, - FCOND_GT - }; - /// GetOppositeBranchOpc - Return the inverse of the specified /// opcode, e.g. turning BEQ to BNE. unsigned GetOppositeBranchOpc(unsigned Opc); - - /// MipsCCToString - Map each FP condition code to its string - inline static const char *MipsFCCToString(Mips::CondCode CC) - { - switch (CC) { - default: llvm_unreachable("Unknown condition code"); - case FCOND_F: - case FCOND_T: return "f"; - case FCOND_UN: - case FCOND_OR: return "un"; - case FCOND_OEQ: - case FCOND_UNE: return "eq"; - case FCOND_UEQ: - case FCOND_ONE: return "ueq"; - case FCOND_OLT: - case FCOND_UGE: return "olt"; - case FCOND_ULT: - case FCOND_OGE: return "ult"; - case FCOND_OLE: - case FCOND_UGT: return "ole"; - case FCOND_ULE: - case FCOND_OGT: return "ule"; - case FCOND_SF: - case FCOND_ST: return "sf"; - case FCOND_NGLE: - case FCOND_GLE: return "ngle"; - case FCOND_SEQ: - case FCOND_SNE: return "seq"; - case FCOND_NGL: - case FCOND_GL: return "ngl"; - case FCOND_LT: - case FCOND_NLT: return "lt"; - case FCOND_NGE: - case FCOND_GE: return "nge"; - case FCOND_LE: - case FCOND_NLE: return "le"; - case FCOND_NGT: - case FCOND_GT: return "ngt"; - } - } } /// MipsII - This namespace holds all of the target specific flags that @@ -164,7 +76,7 @@ namespace MipsII { }; } -class MipsInstrInfo : public TargetInstrInfoImpl { +class MipsInstrInfo : public MipsGenInstrInfo { MipsTargetMachine &TM; const MipsRegisterInfo RI; public: @@ -174,7 +86,7 @@ public: /// such, whenever a client has an instance of instruction info, it should /// always be able to get register info as well (through this method). /// - virtual const MipsRegisterInfo &getRegisterInfo() const { return RI; } + virtual const MipsRegisterInfo &getRegisterInfo() const; /// isLoadFromStackSlot - If the specified machine instruction is a direct /// load from a stack slot, return the virtual or physical register number of @@ -224,6 +136,11 @@ public: const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const; + virtual MachineInstr* emitFrameIndexDebugValue(MachineFunction &MF, + int FrameIx, uint64_t Offset, + const MDNode *MDPtr, + DebugLoc DL) const; + virtual bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const; diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index 329a002667a0..d1a058712459 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -39,6 +39,9 @@ def SDT_MipsDivRem : SDTypeProfile<0, 2, def SDT_MipsThreadPointer : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>; +def SDT_MipsDynAlloc : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, + SDTCisVT<1, iPTR>]>; + // Call def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, @@ -99,6 +102,10 @@ def MipsDivRemU : SDNode<"MipsISD::DivRemU", SDT_MipsDivRem, def MipsWrapperPIC : SDNode<"MipsISD::WrapperPIC", SDTIntUnaryOp>; +// Pointer to dynamically allocated stack area. +def MipsDynAlloc : SDNode<"MipsISD::DynAlloc", SDT_MipsDynAlloc, + [SDNPHasChain, SDNPInGlue]>; + //===----------------------------------------------------------------------===// // Mips Instruction Predicate Definitions. //===----------------------------------------------------------------------===// @@ -127,7 +134,12 @@ def uimm16 : Operand<i32> { // Address operand def mem : Operand<i32> { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops simm16, CPURegs); + let MIOperandInfo = (ops CPURegs, simm16); +} + +def mem_ea : Operand<i32> { + let PrintMethod = "printMemOperandEA"; + let MIOperandInfo = (ops CPURegs, simm16); } // Transformation Function - get the lower 16 bits. @@ -344,7 +356,7 @@ class MoveToLOHI<bits<6> func, string instr_asm>: !strconcat(instr_asm, "\t$src"), [], IIHiLo>; class EffectiveAddress<string instr_asm> : - FI<0x09, (outs CPURegs:$dst), (ins mem:$addr), + FI<0x09, (outs CPURegs:$dst), (ins mem_ea:$addr), instr_asm, [(set CPURegs:$dst, addr:$addr)], IIAlu>; // Count Leading Ones/Zeros in Word @@ -412,7 +424,7 @@ def ATMACRO : MipsPseudo<(outs), (ins), ".set\tat", []>; // are used, we have the same behavior, but get also a bunch of warnings // from the assembler. def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$picreg), ".cpload\t$picreg", []>; -def CPRESTORE : MipsPseudo<(outs), (ins i32imm:$loc), ".cprestore\t$loc\n", []>; +def CPRESTORE : MipsPseudo<(outs), (ins i32imm:$loc), ".cprestore\t$loc", []>; let usesCustomInserter = 1 in { def ATOMIC_LOAD_ADD_I8 : MipsPseudo< @@ -673,7 +685,13 @@ let addr=0 in // instructions. The same not happens for stack address copies, so an // add op with mem ComplexPattern is used and the stack address copy // can be matched. It's similar to Sparc LEA_ADDRi -def LEA_ADDiu : EffectiveAddress<"addiu\t$dst, ${addr:stackloc}">; +def LEA_ADDiu : EffectiveAddress<"addiu\t$dst, $addr">; + +// DynAlloc node points to dynamically allocated stack space. +// $sp is added to the list of implicitly used registers to prevent dead code +// elimination from removing instructions that modify $sp. +let Uses = [SP] in +def DynAlloc : EffectiveAddress<"addiu\t$dst, $addr">; // MADD*/MSUB* def MADD : MArithR<0, "madd", MipsMAdd, 1>; @@ -852,6 +870,9 @@ def : Pat<(setge CPURegs:$lhs, immSExt16:$rhs), def : Pat<(setuge CPURegs:$lhs, immSExt16:$rhs), (XORi (SLTiu CPURegs:$lhs, immSExt16:$rhs), 1)>; +// select MipsDynAlloc +def : Pat<(MipsDynAlloc addr:$f), (DynAlloc addr:$f)>; + //===----------------------------------------------------------------------===// // Floating Point Support //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp new file mode 100644 index 000000000000..f5cc3aa25f1b --- /dev/null +++ b/lib/Target/Mips/MipsMCInstLower.cpp @@ -0,0 +1,118 @@ +//===-- MipsMCInstLower.cpp - Convert Mips MachineInstr to MCInst ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains code to lower Mips MachineInstrs to their corresponding +// MCInst records. +// +//===----------------------------------------------------------------------===// + +#include "MipsMCInstLower.h" +#include "MipsAsmPrinter.h" +#include "MipsInstrInfo.h" +#include "MipsMCSymbolRefExpr.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Target/Mangler.h" +using namespace llvm; + +MipsMCInstLower::MipsMCInstLower(Mangler *mang, const MachineFunction &mf, + MipsAsmPrinter &asmprinter) + : Ctx(mf.getContext()), Mang(mang), AsmPrinter(asmprinter) {} + +MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, + MachineOperandType MOTy) const { + MipsMCSymbolRefExpr::VariantKind Kind; + const MCSymbol *Symbol; + int Offset = 0; + + switch(MO.getTargetFlags()) { + default: assert(0 && "Invalid target flag!"); + case MipsII::MO_NO_FLAG: Kind = MipsMCSymbolRefExpr::VK_Mips_None; break; + case MipsII::MO_GPREL: Kind = MipsMCSymbolRefExpr::VK_Mips_GPREL; break; + case MipsII::MO_GOT_CALL: Kind = MipsMCSymbolRefExpr::VK_Mips_GOT_CALL; break; + case MipsII::MO_GOT: Kind = MipsMCSymbolRefExpr::VK_Mips_GOT; break; + case MipsII::MO_ABS_HI: Kind = MipsMCSymbolRefExpr::VK_Mips_ABS_HI; break; + case MipsII::MO_ABS_LO: Kind = MipsMCSymbolRefExpr::VK_Mips_ABS_LO; break; + case MipsII::MO_TLSGD: Kind = MipsMCSymbolRefExpr::VK_Mips_TLSGD; break; + case MipsII::MO_GOTTPREL: Kind = MipsMCSymbolRefExpr::VK_Mips_GOTTPREL; break; + case MipsII::MO_TPREL_HI: Kind = MipsMCSymbolRefExpr::VK_Mips_TPREL_HI; break; + case MipsII::MO_TPREL_LO: Kind = MipsMCSymbolRefExpr::VK_Mips_TPREL_LO; break; + } + + switch (MOTy) { + case MachineOperand::MO_MachineBasicBlock: + Symbol = MO.getMBB()->getSymbol(); + break; + + case MachineOperand::MO_GlobalAddress: + Symbol = Mang->getSymbol(MO.getGlobal()); + break; + + case MachineOperand::MO_BlockAddress: + Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress()); + break; + + case MachineOperand::MO_ExternalSymbol: + Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName()); + break; + + case MachineOperand::MO_JumpTableIndex: + Symbol = AsmPrinter.GetJTISymbol(MO.getIndex()); + break; + + case MachineOperand::MO_ConstantPoolIndex: + Symbol = AsmPrinter.GetCPISymbol(MO.getIndex()); + if (MO.getOffset()) + Offset = MO.getOffset(); + break; + + default: + llvm_unreachable("<unknown operand type>"); + } + + return MCOperand::CreateExpr(MipsMCSymbolRefExpr::Create(Kind, Symbol, Offset, + Ctx)); +} + +void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { + OutMI.setOpcode(MI->getOpcode()); + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + MCOperand MCOp; + MachineOperandType MOTy = MO.getType(); + + switch (MOTy) { + default: + MI->dump(); + llvm_unreachable("unknown operand type"); + case MachineOperand::MO_Register: + // Ignore all implicit register operands. + if (MO.isImplicit()) continue; + MCOp = MCOperand::CreateReg(MO.getReg()); + break; + case MachineOperand::MO_Immediate: + MCOp = MCOperand::CreateImm(MO.getImm()); + break; + case MachineOperand::MO_MachineBasicBlock: + case MachineOperand::MO_GlobalAddress: + case MachineOperand::MO_ExternalSymbol: + case MachineOperand::MO_JumpTableIndex: + case MachineOperand::MO_ConstantPoolIndex: + case MachineOperand::MO_BlockAddress: + MCOp = LowerSymbolOperand(MO, MOTy); + break; + } + + OutMI.addOperand(MCOp); + } +} diff --git a/lib/Target/Mips/MipsMCInstLower.h b/lib/Target/Mips/MipsMCInstLower.h new file mode 100644 index 000000000000..ec5201be7f6d --- /dev/null +++ b/lib/Target/Mips/MipsMCInstLower.h @@ -0,0 +1,43 @@ +//===-- MipsMCInstLower.h - Lower MachineInstr to MCInst -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef MIPSMCINSTLOWER_H +#define MIPSMCINSTLOWER_H +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + class MCAsmInfo; + class MCContext; + class MCInst; + class MCOperand; + class MCSymbol; + class MachineInstr; + class MachineFunction; + class Mangler; + class MipsAsmPrinter; + +/// MipsMCInstLower - This class is used to lower an MachineInstr into an +// MCInst. +class LLVM_LIBRARY_VISIBILITY MipsMCInstLower { + typedef MachineOperand::MachineOperandType MachineOperandType; + MCContext &Ctx; + Mangler *Mang; + MipsAsmPrinter &AsmPrinter; +public: + MipsMCInstLower(Mangler *mang, const MachineFunction &MF, + MipsAsmPrinter &asmprinter); + void Lower(const MachineInstr *MI, MCInst &OutMI) const; +private: + MCOperand LowerSymbolOperand(const MachineOperand &MO, + MachineOperandType MOTy) const; +}; +} + +#endif diff --git a/lib/Target/Mips/MipsMCSymbolRefExpr.cpp b/lib/Target/Mips/MipsMCSymbolRefExpr.cpp new file mode 100644 index 000000000000..9a2bdae0e339 --- /dev/null +++ b/lib/Target/Mips/MipsMCSymbolRefExpr.cpp @@ -0,0 +1,63 @@ +//===-- MipsMCSymbolRefExpr.cpp - Mips specific MC expression classes -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mipsmcsymbolrefexpr" +#include "MipsMCSymbolRefExpr.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSymbol.h" +using namespace llvm; + +const MipsMCSymbolRefExpr* +MipsMCSymbolRefExpr::Create(VariantKind Kind, const MCSymbol *Symbol, + int Offset, MCContext &Ctx) { + return new (Ctx) MipsMCSymbolRefExpr(Kind, Symbol, Offset); +} + +void MipsMCSymbolRefExpr::PrintImpl(raw_ostream &OS) const { + switch (Kind) { + default: assert(0 && "Invalid kind!"); + case VK_Mips_None: break; + case VK_Mips_GPREL: OS << "%gp_rel("; break; + case VK_Mips_GOT_CALL: OS << "%call16("; break; + case VK_Mips_GOT: OS << "%got("; break; + case VK_Mips_ABS_HI: OS << "%hi("; break; + case VK_Mips_ABS_LO: OS << "%lo("; break; + case VK_Mips_TLSGD: OS << "%tlsgd("; break; + case VK_Mips_GOTTPREL: OS << "%gottprel("; break; + case VK_Mips_TPREL_HI: OS << "%tprel_hi("; break; + case VK_Mips_TPREL_LO: OS << "%tprel_lo("; break; + } + + OS << *Symbol; + + if (Offset) { + if (Offset > 0) + OS << '+'; + OS << Offset; + } + + if (Kind != VK_Mips_None) + OS << ')'; +} + +bool +MipsMCSymbolRefExpr::EvaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout) const { + return false; +} + +void MipsMCSymbolRefExpr::AddValueSymbols(MCAssembler *Asm) const { + Asm->getOrCreateSymbolData(*Symbol); +} + +const MCSection *MipsMCSymbolRefExpr::FindAssociatedSection() const { + return Symbol->isDefined() ? &Symbol->getSection() : NULL; +} + diff --git a/lib/Target/Mips/MipsMCSymbolRefExpr.h b/lib/Target/Mips/MipsMCSymbolRefExpr.h new file mode 100644 index 000000000000..3e695963709e --- /dev/null +++ b/lib/Target/Mips/MipsMCSymbolRefExpr.h @@ -0,0 +1,62 @@ +//===-- MipsMCSymbolRefExpr.h - Mips specific MCSymbolRefExpr class -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef MIPSMCSYMBOLREFEXPR_H +#define MIPSMCSYMBOLREFEXPR_H +#include "llvm/MC/MCExpr.h" + +namespace llvm { + +class MipsMCSymbolRefExpr : public MCTargetExpr { +public: + enum VariantKind { + VK_Mips_None, + VK_Mips_GPREL, + VK_Mips_GOT_CALL, + VK_Mips_GOT, + VK_Mips_ABS_HI, + VK_Mips_ABS_LO, + VK_Mips_TLSGD, + VK_Mips_GOTTPREL, + VK_Mips_TPREL_HI, + VK_Mips_TPREL_LO + }; + +private: + const VariantKind Kind; + const MCSymbol *Symbol; + int Offset; + + explicit MipsMCSymbolRefExpr(VariantKind _Kind, const MCSymbol *_Symbol, + int _Offset) + : Kind(_Kind), Symbol(_Symbol), Offset(_Offset) {} + +public: + static const MipsMCSymbolRefExpr *Create(VariantKind Kind, + const MCSymbol *Symbol, int Offset, + MCContext &Ctx); + + void PrintImpl(raw_ostream &OS) const; + bool EvaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout) const; + void AddValueSymbols(MCAssembler *) const; + const MCSection *FindAssociatedSection() const; + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Target; + } + + static bool classof(const MipsMCSymbolRefExpr *) { return true; } + + int getOffset() const { return Offset; } + void setOffset(int O) { Offset = O; } +}; +} // end namespace llvm + +#endif diff --git a/lib/Target/Mips/MipsMachineFunction.h b/lib/Target/Mips/MipsMachineFunction.h index df40e6c748a6..dbb7a6744224 100644 --- a/lib/Target/Mips/MipsMachineFunction.h +++ b/lib/Target/Mips/MipsMachineFunction.h @@ -27,6 +27,7 @@ namespace llvm { class MipsFunctionInfo : public MachineFunctionInfo { private: + MachineFunction& MF; /// SRetReturnReg - Some subtargets require that sret lowering includes /// returning the value of the returned struct in a register. This field /// holds the virtual register into which the sret argument is passed. @@ -47,6 +48,7 @@ private: // LowerCall except for the frame object for restoring $gp. std::pair<int, int> InArgFIRange, OutArgFIRange; int GPFI; // Index of the frame object for restoring $gp + mutable int DynAllocFI; // Frame index of dynamically allocated stack area. unsigned MaxCallFrameSize; /// AtomicFrameIndex - To implement atomic.swap and atomic.cmp.swap @@ -55,10 +57,10 @@ private: int AtomicFrameIndex; public: MipsFunctionInfo(MachineFunction& MF) - : SRetReturnReg(0), GlobalBaseReg(0), + : MF(MF), SRetReturnReg(0), GlobalBaseReg(0), VarArgsFrameIndex(0), InArgFIRange(std::make_pair(-1, 0)), - OutArgFIRange(std::make_pair(-1, 0)), GPFI(0), MaxCallFrameSize(0), - AtomicFrameIndex(-1) + OutArgFIRange(std::make_pair(-1, 0)), GPFI(0), DynAllocFI(0), + MaxCallFrameSize(0), AtomicFrameIndex(-1) {} bool isInArgFI(int FI) const { @@ -81,6 +83,16 @@ public: bool needGPSaveRestore() const { return getGPFI(); } bool isGPFI(int FI) const { return GPFI && GPFI == FI; } + // The first call to this function creates a frame object for dynamically + // allocated stack area. + int getDynAllocFI() const { + if (!DynAllocFI) + DynAllocFI = MF.getFrameInfo()->CreateFixedObject(4, 0, true); + + return DynAllocFI; + } + bool isDynAllocFI(int FI) const { return DynAllocFI && DynAllocFI == FI; } + unsigned getSRetReturnReg() const { return SRetReturnReg; } void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index b0984afbebed..24390daff75c 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -35,13 +35,16 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Analysis/DebugInfo.h" + +#define GET_REGINFO_TARGET_DESC +#include "MipsGenRegisterInfo.inc" using namespace llvm; MipsRegisterInfo::MipsRegisterInfo(const MipsSubtarget &ST, const TargetInstrInfo &tii) - : MipsGenRegisterInfo(Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP), - Subtarget(ST), TII(tii) {} + : MipsGenRegisterInfo(), Subtarget(ST), TII(tii) {} /// getRegisterNumbering - Given the enum value for some register, e.g. /// Mips::RA, return the number that it corresponds to (e.g. 31). @@ -176,28 +179,6 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, << "spOffset : " << spOffset << "\n" << "stackSize : " << stackSize << "\n"); - int Offset; - - // Calculate final offset. - // - There is no need to change the offset if the frame object is an outgoing - // argument or a $gp restore location, - // - If the frame object is any of the following, its offset must be adjusted - // by adding the size of the stack: - // incoming argument, callee-saved register location or local variable. - if (MipsFI->isOutArgFI(FrameIndex) || MipsFI->isGPFI(FrameIndex)) - Offset = spOffset; - else - Offset = spOffset + stackSize; - - Offset += MI.getOperand(i-1).getImm(); - - DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n"); - - unsigned NewReg = 0; - int NewImm = 0; - MachineBasicBlock &MBB = *MI.getParent(); - bool ATUsed; - unsigned FrameReg; const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); int MinCSFI = 0; int MaxCSFI = -1; @@ -213,42 +194,54 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, // 3. Locations for callee-saved registers. // Everything else is referenced relative to whatever register // getFrameRegister() returns. - if (MipsFI->isOutArgFI(FrameIndex) || + unsigned FrameReg; + + if (MipsFI->isOutArgFI(FrameIndex) || MipsFI->isDynAllocFI(FrameIndex) || (FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI)) FrameReg = Mips::SP; else FrameReg = getFrameRegister(MF); - // Offset fits in the 16-bit field - if (Offset < 0x8000 && Offset >= -0x8000) { - NewReg = FrameReg; - NewImm = Offset; - ATUsed = false; - } - else { - const TargetInstrInfo *TII = MF.getTarget().getInstrInfo(); + // Calculate final offset. + // - There is no need to change the offset if the frame object is one of the + // following: an outgoing argument, pointer to a dynamically allocated + // stack space or a $gp restore location, + // - If the frame object is any of the following, its offset must be adjusted + // by adding the size of the stack: + // incoming argument, callee-saved register location or local variable. + int Offset; + + if (MipsFI->isOutArgFI(FrameIndex) || MipsFI->isGPFI(FrameIndex) || + MipsFI->isDynAllocFI(FrameIndex)) + Offset = spOffset; + else + Offset = spOffset + stackSize; + + Offset += MI.getOperand(i+1).getImm(); + + DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n"); + + // If MI is not a debug value, make sure Offset fits in the 16-bit immediate + // field. + if (!MI.isDebugValue() && (Offset >= 0x8000 || Offset < -0x8000)) { + MachineBasicBlock &MBB = *MI.getParent(); DebugLoc DL = II->getDebugLoc(); - int ImmLo = (short)(Offset & 0xffff); int ImmHi = (((unsigned)Offset & 0xffff0000) >> 16) + ((Offset & 0x8000) != 0); // FIXME: change this when mips goes MC". - BuildMI(MBB, II, DL, TII->get(Mips::NOAT)); - BuildMI(MBB, II, DL, TII->get(Mips::LUi), Mips::AT).addImm(ImmHi); - BuildMI(MBB, II, DL, TII->get(Mips::ADDu), Mips::AT).addReg(FrameReg) - .addReg(Mips::AT); - NewReg = Mips::AT; - NewImm = ImmLo; - - ATUsed = true; - } + BuildMI(MBB, II, DL, TII.get(Mips::NOAT)); + BuildMI(MBB, II, DL, TII.get(Mips::LUi), Mips::AT).addImm(ImmHi); + BuildMI(MBB, II, DL, TII.get(Mips::ADDu), Mips::AT).addReg(FrameReg) + .addReg(Mips::AT); + FrameReg = Mips::AT; + Offset = (short)(Offset & 0xffff); - // FIXME: change this when mips goes MC". - if (ATUsed) BuildMI(MBB, ++II, MI.getDebugLoc(), TII.get(Mips::ATMACRO)); + } - MI.getOperand(i).ChangeToRegister(NewReg, false); - MI.getOperand(i-1).ChangeToImmediate(NewImm); + MI.getOperand(i).ChangeToRegister(FrameReg, false); + MI.getOperand(i+1).ChangeToImmediate(Offset); } unsigned MipsRegisterInfo:: @@ -283,5 +276,3 @@ getDwarfRegNum(unsigned RegNum, bool isEH) const { int MipsRegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const { return MipsGenRegisterInfo::getLLVMRegNumFull(DwarfRegNo,0); } - -#include "MipsGenRegisterInfo.inc" diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h index 76b0035f1696..646369b5966f 100644 --- a/lib/Target/Mips/MipsRegisterInfo.h +++ b/lib/Target/Mips/MipsRegisterInfo.h @@ -16,7 +16,9 @@ #include "Mips.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "MipsGenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "MipsGenRegisterInfo.inc" namespace llvm { class MipsSubtarget; diff --git a/lib/Target/Mips/MipsRegisterInfo.td b/lib/Target/Mips/MipsRegisterInfo.td index e97d4505eb43..f0db518b754b 100644 --- a/lib/Target/Mips/MipsRegisterInfo.td +++ b/lib/Target/Mips/MipsRegisterInfo.td @@ -157,15 +157,15 @@ let Namespace = "Mips" in { // Register Classes //===----------------------------------------------------------------------===// -def CPURegs : RegisterClass<"Mips", [i32], 32, +def CPURegs : RegisterClass<"Mips", [i32], 32, (add // Return Values and Arguments - [V0, V1, A0, A1, A2, A3, + V0, V1, A0, A1, A2, A3, // Not preserved across procedure calls T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, // Callee save S0, S1, S2, S3, S4, S5, S6, S7, // Reserved - ZERO, AT, K0, K1, GP, SP, FP, RA]>; + ZERO, AT, K0, K1, GP, SP, FP, RA)>; // 64bit fp: // * FGR64 - 32 64-bit registers @@ -174,33 +174,25 @@ def CPURegs : RegisterClass<"Mips", [i32], 32, // 32bit fp: // * FGR32 - 16 32-bit even registers // * FGR32 - 32 32-bit registers (single float only mode) -def FGR32 : RegisterClass<"Mips", [f32], 32, - // Return Values and Arguments - [F0, F1, F2, F3, F12, F13, F14, F15, - // Not preserved across procedure calls - F4, F5, F6, F7, F8, F9, F10, F11, F16, F17, F18, F19, - // Callee save - F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, - // Reserved - F31]>; +def FGR32 : RegisterClass<"Mips", [f32], 32, (sequence "F%u", 0, 31)>; -def AFGR64 : RegisterClass<"Mips", [f64], 64, +def AFGR64 : RegisterClass<"Mips", [f64], 64, (add // Return Values and Arguments - [D0, D1, D6, D7, + D0, D1, D6, D7, // Not preserved across procedure calls D2, D3, D4, D5, D8, D9, // Callee save D10, D11, D12, D13, D14, // Reserved - D15]> { + D15)> { let SubRegClasses = [(FGR32 sub_fpeven, sub_fpodd)]; } // Condition Register for floating point operations -def CCR : RegisterClass<"Mips", [i32], 32, [FCR31]>; +def CCR : RegisterClass<"Mips", [i32], 32, (add FCR31)>; // Hi/Lo Registers -def HILO : RegisterClass<"Mips", [i32], 32, [HI, LO]>; +def HILO : RegisterClass<"Mips", [i32], 32, (add HI, LO)>; // Hardware registers -def HWRegs : RegisterClass<"Mips", [i32], 32, [HWR29]>; +def HWRegs : RegisterClass<"Mips", [i32], 32, (add HWR29)>; diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp index 70747f5da137..6eee3333d584 100644 --- a/lib/Target/Mips/MipsSubtarget.cpp +++ b/lib/Target/Mips/MipsSubtarget.cpp @@ -7,27 +7,38 @@ // //===----------------------------------------------------------------------===// // -// This file implements the Mips specific subclass of TargetSubtarget. +// This file implements the Mips specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #include "MipsSubtarget.h" #include "Mips.h" -#include "MipsGenSubtarget.inc" +#include "llvm/Target/TargetRegistry.h" + +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "MipsGenSubtargetInfo.inc" + using namespace llvm; -MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &FS, - bool little) : +MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, bool little) : + MipsGenSubtargetInfo(TT, CPU, FS), MipsArchVersion(Mips1), MipsABI(O32), IsLittle(little), IsSingleFloat(false), IsFP64bit(false), IsGP64bit(false), HasVFPU(false), IsLinux(true), HasSEInReg(false), HasCondMov(false), HasMulDivAdd(false), HasMinMax(false), HasSwap(false), HasBitCount(false) { - std::string CPU = "mips1"; + std::string CPUName = CPU; + if (CPUName.empty()) + CPUName = "mips1"; MipsArchVersion = Mips1; // Parse features string. - ParseSubtargetFeatures(FS, CPU); + ParseSubtargetFeatures(CPUName, FS); + + // Initialize scheduling itinerary for the specified CPU. + InstrItins = getInstrItineraryForCPU(CPUName); // Is the target system Linux ? if (TT.find("linux") == std::string::npos) diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index 096bbed7b047..533d4afe073e 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -7,21 +7,24 @@ // //===----------------------------------------------------------------------===// // -// This file declares the Mips specific subclass of TargetSubtarget. +// This file declares the Mips specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #ifndef MIPSSUBTARGET_H #define MIPSSUBTARGET_H -#include "llvm/Target/TargetSubtarget.h" -#include "llvm/Target/TargetMachine.h" - +#include "llvm/Target/TargetSubtargetInfo.h" +#include "llvm/MC/MCInstrItineraries.h" #include <string> +#define GET_SUBTARGETINFO_HEADER +#include "MipsGenSubtargetInfo.inc" + namespace llvm { +class StringRef; -class MipsSubtarget : public TargetSubtarget { +class MipsSubtarget : public MipsGenSubtargetInfo { public: enum MipsABIEnum { @@ -92,12 +95,12 @@ public: /// This constructor initializes the data members to match that /// of the specified triple. - MipsSubtarget(const std::string &TT, const std::string &FS, bool little); + MipsSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, bool little); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(StringRef CPU, StringRef FS); bool isMips1() const { return MipsArchVersion == Mips1; } bool isMips32() const { return MipsArchVersion >= Mips32; } diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp index cfbb92c9ac16..20b9f4ea3853 100644 --- a/lib/Target/Mips/MipsTargetMachine.cpp +++ b/lib/Target/Mips/MipsTargetMachine.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "Mips.h" -#include "MipsMCAsmInfo.h" #include "MipsTargetMachine.h" #include "llvm/PassManager.h" #include "llvm/Target/TargetRegistry.h" @@ -22,8 +21,6 @@ extern "C" void LLVMInitializeMipsTarget() { // Register the target. RegisterTargetMachine<MipsTargetMachine> X(TheMipsTarget); RegisterTargetMachine<MipselTargetMachine> Y(TheMipselTarget); - RegisterAsmInfo<MipsMCAsmInfo> A(TheMipsTarget); - RegisterAsmInfo<MipsMCAsmInfo> B(TheMipselTarget); } // DataLayout --> Big-endian, 32-bit pointer/ABI/alignment @@ -34,10 +31,11 @@ extern "C" void LLVMInitializeMipsTarget() { // an easier handling. // Using CodeModel::Large enables different CALL behavior. MipsTargetMachine:: -MipsTargetMachine(const Target &T, const std::string &TT, const std::string &FS, +MipsTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS, bool isLittle=false): - LLVMTargetMachine(T, TT), - Subtarget(TT, FS, isLittle), + LLVMTargetMachine(T, TT, CPU, FS), + Subtarget(TT, CPU, FS, isLittle), DataLayout(isLittle ? std::string("e-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32") : std::string("E-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32")), @@ -55,8 +53,8 @@ MipsTargetMachine(const Target &T, const std::string &TT, const std::string &FS, MipselTargetMachine:: MipselTargetMachine(const Target &T, const std::string &TT, - const std::string &FS) : - MipsTargetMachine(T, TT, FS, true) {} + const std::string &CPU, const std::string &FS) : + MipsTargetMachine(T, TT, CPU, FS, true) {} // Install an instruction selector pass using // the ISelDag to gen Mips code. diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h index 102dd8566dde..a021af2ff16d 100644 --- a/lib/Target/Mips/MipsTargetMachine.h +++ b/lib/Target/Mips/MipsTargetMachine.h @@ -35,7 +35,8 @@ namespace llvm { MipsSelectionDAGInfo TSInfo; public: MipsTargetMachine(const Target &T, const std::string &TT, - const std::string &FS, bool isLittle); + const std::string &CPU, const std::string &FS, + bool isLittle); virtual const MipsInstrInfo *getInstrInfo() const { return &InstrInfo; } @@ -73,7 +74,7 @@ namespace llvm { class MipselTargetMachine : public MipsTargetMachine { public: MipselTargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); }; } // End llvm namespace diff --git a/lib/Target/PTX/CMakeLists.txt b/lib/Target/PTX/CMakeLists.txt index 331266da30b3..ce08916aaac1 100644 --- a/lib/Target/PTX/CMakeLists.txt +++ b/lib/Target/PTX/CMakeLists.txt @@ -1,13 +1,11 @@ set(LLVM_TARGET_DEFINITIONS PTX.td) tablegen(PTXGenAsmWriter.inc -gen-asm-writer) +tablegen(PTXGenCallingConv.inc -gen-callingconv) tablegen(PTXGenDAGISel.inc -gen-dag-isel) -tablegen(PTXGenInstrInfo.inc -gen-instr-desc) -tablegen(PTXGenInstrNames.inc -gen-instr-enums) -tablegen(PTXGenRegisterInfo.inc -gen-register-desc) -tablegen(PTXGenRegisterInfo.h.inc -gen-register-desc-header) -tablegen(PTXGenRegisterNames.inc -gen-register-enums) -tablegen(PTXGenSubtarget.inc -gen-subtarget) +tablegen(PTXGenInstrInfo.inc -gen-instr-info) +tablegen(PTXGenRegisterInfo.inc -gen-register-info) +tablegen(PTXGenSubtargetInfo.inc -gen-subtarget) add_llvm_target(PTXCodeGen PTXAsmPrinter.cpp @@ -15,7 +13,6 @@ add_llvm_target(PTXCodeGen PTXISelLowering.cpp PTXInstrInfo.cpp PTXFrameLowering.cpp - PTXMCAsmInfo.cpp PTXMCAsmStreamer.cpp PTXMFInfoExtract.cpp PTXRegisterInfo.cpp @@ -24,3 +21,4 @@ add_llvm_target(PTXCodeGen ) add_subdirectory(TargetInfo) +add_subdirectory(MCTargetDesc) diff --git a/lib/Target/PTX/MCTargetDesc/CMakeLists.txt b/lib/Target/PTX/MCTargetDesc/CMakeLists.txt new file mode 100644 index 000000000000..df0f63fdba60 --- /dev/null +++ b/lib/Target/PTX/MCTargetDesc/CMakeLists.txt @@ -0,0 +1,4 @@ +add_llvm_library(LLVMPTXDesc + PTXMCTargetDesc.cpp + PTXMCAsmInfo.cpp + ) diff --git a/lib/Target/PTX/MCTargetDesc/Makefile b/lib/Target/PTX/MCTargetDesc/Makefile new file mode 100644 index 000000000000..35f5a7b2e6ad --- /dev/null +++ b/lib/Target/PTX/MCTargetDesc/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/PTX/TargetDesc/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +LIBRARYNAME = LLVMPTXDesc + +# Hack: we need to include 'main' target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/PTX/PTXMCAsmInfo.cpp b/lib/Target/PTX/MCTargetDesc/PTXMCAsmInfo.cpp index b670abdbe095..efefead5341d 100644 --- a/lib/Target/PTX/PTXMCAsmInfo.cpp +++ b/lib/Target/PTX/MCTargetDesc/PTXMCAsmInfo.cpp @@ -12,10 +12,15 @@ //===----------------------------------------------------------------------===// #include "PTXMCAsmInfo.h" +#include "llvm/ADT/Triple.h" using namespace llvm; PTXMCAsmInfo::PTXMCAsmInfo(const Target &T, const StringRef &TT) { + Triple TheTriple(TT); + if (TheTriple.getArch() == Triple::ptx64) + PointerSize = 8; + CommentString = "//"; PrivateGlobalPrefix = "$L__"; diff --git a/lib/Target/PTX/PTXMCAsmInfo.h b/lib/Target/PTX/MCTargetDesc/PTXMCAsmInfo.h index 03f5d66b3d60..03f5d66b3d60 100644 --- a/lib/Target/PTX/PTXMCAsmInfo.h +++ b/lib/Target/PTX/MCTargetDesc/PTXMCAsmInfo.h diff --git a/lib/Target/PTX/MCTargetDesc/PTXMCTargetDesc.cpp b/lib/Target/PTX/MCTargetDesc/PTXMCTargetDesc.cpp new file mode 100644 index 000000000000..23f70bd13787 --- /dev/null +++ b/lib/Target/PTX/MCTargetDesc/PTXMCTargetDesc.cpp @@ -0,0 +1,60 @@ +//===-- PTXMCTargetDesc.cpp - PTX Target Descriptions -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides PTX specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#include "PTXMCTargetDesc.h" +#include "PTXMCAsmInfo.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Target/TargetRegistry.h" + +#define GET_INSTRINFO_MC_DESC +#include "PTXGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_MC_DESC +#include "PTXGenSubtargetInfo.inc" + +#define GET_REGINFO_MC_DESC +#include "PTXGenRegisterInfo.inc" + +using namespace llvm; + +static MCInstrInfo *createPTXMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitPTXMCInstrInfo(X); + return X; +} + +extern "C" void LLVMInitializePTXMCInstrInfo() { + TargetRegistry::RegisterMCInstrInfo(ThePTX32Target, createPTXMCInstrInfo); + TargetRegistry::RegisterMCInstrInfo(ThePTX64Target, createPTXMCInstrInfo); +} + +static MCSubtargetInfo *createPTXMCSubtargetInfo(StringRef TT, StringRef CPU, + StringRef FS) { + MCSubtargetInfo *X = new MCSubtargetInfo(); + InitPTXMCSubtargetInfo(X, TT, CPU, FS); + return X; +} + +extern "C" void LLVMInitializePTXMCSubtargetInfo() { + TargetRegistry::RegisterMCSubtargetInfo(ThePTX32Target, + createPTXMCSubtargetInfo); + TargetRegistry::RegisterMCSubtargetInfo(ThePTX64Target, + createPTXMCSubtargetInfo); +} + +extern "C" void LLVMInitializePTXMCAsmInfo() { + RegisterMCAsmInfo<PTXMCAsmInfo> X(ThePTX32Target); + RegisterMCAsmInfo<PTXMCAsmInfo> Y(ThePTX64Target); +} diff --git a/lib/Target/PTX/MCTargetDesc/PTXMCTargetDesc.h b/lib/Target/PTX/MCTargetDesc/PTXMCTargetDesc.h new file mode 100644 index 000000000000..1003b0b5ece9 --- /dev/null +++ b/lib/Target/PTX/MCTargetDesc/PTXMCTargetDesc.h @@ -0,0 +1,38 @@ +//===-- PTXMCTargetDesc.h - PTX Target Descriptions ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides PTX specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#ifndef PTXMCTARGETDESC_H +#define PTXMCTARGETDESC_H + +namespace llvm { +class MCSubtargetInfo; +class Target; +class StringRef; + +extern Target ThePTX32Target; +extern Target ThePTX64Target; + +} // End llvm namespace + +// Defines symbolic names for PTX registers. +#define GET_REGINFO_ENUM +#include "PTXGenRegisterInfo.inc" + +// Defines symbolic names for the PTX instructions. +#define GET_INSTRINFO_ENUM +#include "PTXGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "PTXGenSubtargetInfo.inc" + +#endif diff --git a/lib/Target/PTX/Makefile b/lib/Target/PTX/Makefile index 2c40d6994094..93dd38aca7ec 100644 --- a/lib/Target/PTX/Makefile +++ b/lib/Target/PTX/Makefile @@ -13,14 +13,12 @@ TARGET = PTX # Make sure that tblgen is run, first thing. BUILT_SOURCES = PTXGenAsmWriter.inc \ + PTXGenCallingConv.inc \ PTXGenDAGISel.inc \ PTXGenInstrInfo.inc \ - PTXGenInstrNames.inc \ PTXGenRegisterInfo.inc \ - PTXGenRegisterInfo.h.inc \ - PTXGenRegisterNames.inc \ - PTXGenSubtarget.inc + PTXGenSubtargetInfo.inc -DIRS = TargetInfo +DIRS = TargetInfo MCTargetDesc include $(LEVEL)/Makefile.common diff --git a/lib/Target/PTX/PTX.h b/lib/Target/PTX/PTX.h index ec2be9291a04..28cab2429c81 100644 --- a/lib/Target/PTX/PTX.h +++ b/lib/Target/PTX/PTX.h @@ -15,6 +15,7 @@ #ifndef PTX_H #define PTX_H +#include "MCTargetDesc/PTXMCTargetDesc.h" #include "llvm/Target/TargetMachine.h" namespace llvm { @@ -42,14 +43,6 @@ namespace llvm { FunctionPass *createPTXMFInfoExtract(PTXTargetMachine &TM, CodeGenOpt::Level OptLevel); - extern Target ThePTX32Target; - extern Target ThePTX64Target; } // namespace llvm; -// Defines symbolic names for PTX registers. -#include "PTXGenRegisterNames.inc" - -// Defines symbolic names for the PTX instructions. -#include "PTXGenInstrNames.inc" - #endif // PTX_H diff --git a/lib/Target/PTX/PTX.td b/lib/Target/PTX/PTX.td index 231866a08953..f6fbe9fffc6f 100644 --- a/lib/Target/PTX/PTX.td +++ b/lib/Target/PTX/PTX.td @@ -16,7 +16,7 @@ include "llvm/Target/Target.td" //===----------------------------------------------------------------------===// -// Subtarget Features. +// Subtarget Features //===----------------------------------------------------------------------===// //===- Architectural Features ---------------------------------------------===// @@ -30,34 +30,54 @@ def FeatureNoFMA : SubtargetFeature<"no-fma","SupportsFMA", "false", //===- PTX Version --------------------------------------------------------===// def FeaturePTX20 : SubtargetFeature<"ptx20", "PTXVersion", "PTX_VERSION_2_0", - "Use PTX Language Version 2.0", - []>; + "Use PTX Language Version 2.0">; def FeaturePTX21 : SubtargetFeature<"ptx21", "PTXVersion", "PTX_VERSION_2_1", - "Use PTX Language Version 2.1", - [FeaturePTX20]>; + "Use PTX Language Version 2.1">; def FeaturePTX22 : SubtargetFeature<"ptx22", "PTXVersion", "PTX_VERSION_2_2", - "Use PTX Language Version 2.2", - [FeaturePTX21]>; + "Use PTX Language Version 2.2">; def FeaturePTX23 : SubtargetFeature<"ptx23", "PTXVersion", "PTX_VERSION_2_3", - "Use PTX Language Version 2.3", - [FeaturePTX22]>; - -//===- PTX Shader Model ---------------------------------------------------===// - -def FeatureSM10 : SubtargetFeature<"sm10", "PTXShaderModel", "PTX_SM_1_0", - "Enable Shader Model 1.0 compliance">; -def FeatureSM13 : SubtargetFeature<"sm13", "PTXShaderModel", "PTX_SM_1_3", - "Enable Shader Model 1.3 compliance", - [FeatureSM10, FeatureDouble]>; -def FeatureSM20 : SubtargetFeature<"sm20", "PTXShaderModel", "PTX_SM_2_0", - "Enable Shader Model 2.0 compliance", - [FeatureSM13]>; + "Use PTX Language Version 2.3">; + +//===- PTX Target ---------------------------------------------------------===// + +def FeatureSM10 : SubtargetFeature<"sm10", "PTXTarget", "PTX_SM_1_0", + "Use Shader Model 1.0">; +def FeatureSM11 : SubtargetFeature<"sm11", "PTXTarget", "PTX_SM_1_1", + "Use Shader Model 1.1">; +def FeatureSM12 : SubtargetFeature<"sm12", "PTXTarget", "PTX_SM_1_2", + "Use Shader Model 1.2">; +def FeatureSM13 : SubtargetFeature<"sm13", "PTXTarget", "PTX_SM_1_3", + "Use Shader Model 1.3">; +def FeatureSM20 : SubtargetFeature<"sm20", "PTXTarget", "PTX_SM_2_0", + "Use Shader Model 2.0">; +def FeatureSM21 : SubtargetFeature<"sm21", "PTXTarget", "PTX_SM_2_1", + "Use Shader Model 2.1">; +def FeatureSM22 : SubtargetFeature<"sm22", "PTXTarget", "PTX_SM_2_2", + "Use Shader Model 2.2">; +def FeatureSM23 : SubtargetFeature<"sm23", "PTXTarget", "PTX_SM_2_3", + "Use Shader Model 2.3">; + +def FeatureCOMPUTE10 : SubtargetFeature<"compute10", "PTXTarget", + "PTX_COMPUTE_1_0", + "Use Compute Compatibility 1.0">; +def FeatureCOMPUTE11 : SubtargetFeature<"compute11", "PTXTarget", + "PTX_COMPUTE_1_1", + "Use Compute Compatibility 1.1">; +def FeatureCOMPUTE12 : SubtargetFeature<"compute12", "PTXTarget", + "PTX_COMPUTE_1_2", + "Use Compute Compatibility 1.2">; +def FeatureCOMPUTE13 : SubtargetFeature<"compute13", "PTXTarget", + "PTX_COMPUTE_1_3", + "Use Compute Compatibility 1.3">; +def FeatureCOMPUTE20 : SubtargetFeature<"compute20", "PTXTarget", + "PTX_COMPUTE_2_0", + "Use Compute Compatibility 2.0">; //===----------------------------------------------------------------------===// -// PTX supported processors. +// PTX supported processors //===----------------------------------------------------------------------===// class Proc<string Name, list<SubtargetFeature> Features> @@ -65,6 +85,27 @@ class Proc<string Name, list<SubtargetFeature> Features> def : Proc<"generic", []>; +// Processor definitions for compute/shader models +def : Proc<"compute_10", [FeatureCOMPUTE10]>; +def : Proc<"compute_11", [FeatureCOMPUTE11]>; +def : Proc<"compute_12", [FeatureCOMPUTE12]>; +def : Proc<"compute_13", [FeatureCOMPUTE13]>; +def : Proc<"compute_20", [FeatureCOMPUTE20]>; +def : Proc<"sm_10", [FeatureSM10]>; +def : Proc<"sm_11", [FeatureSM11]>; +def : Proc<"sm_12", [FeatureSM12]>; +def : Proc<"sm_13", [FeatureSM13]>; +def : Proc<"sm_20", [FeatureSM20]>; +def : Proc<"sm_21", [FeatureSM21]>; +def : Proc<"sm_22", [FeatureSM22]>; +def : Proc<"sm_23", [FeatureSM23]>; + +// Processor definitions for common GPU architectures +def : Proc<"g80", [FeatureSM10]>; +def : Proc<"gt200", [FeatureSM13]>; +def : Proc<"gf100", [FeatureSM20, FeatureDouble]>; +def : Proc<"fermi", [FeatureSM20, FeatureDouble]>; + //===----------------------------------------------------------------------===// // Register File Description //===----------------------------------------------------------------------===// @@ -72,6 +113,12 @@ def : Proc<"generic", []>; include "PTXRegisterInfo.td" //===----------------------------------------------------------------------===// +// Calling Conventions +//===----------------------------------------------------------------------===// + +include "PTXCallingConv.td" + +//===----------------------------------------------------------------------===// // Instruction Descriptions //===----------------------------------------------------------------------===// diff --git a/lib/Target/PTX/PTXAsmPrinter.cpp b/lib/Target/PTX/PTXAsmPrinter.cpp index 29c4781de654..2848d5460eee 100644 --- a/lib/Target/PTX/PTXAsmPrinter.cpp +++ b/lib/Target/PTX/PTXAsmPrinter.cpp @@ -22,9 +22,12 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" +#include "llvm/Analysis/DebugInfo.h" #include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Target/Mangler.h" @@ -34,6 +37,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -62,8 +66,13 @@ public: const char *Modifier = 0); void printParamOperand(const MachineInstr *MI, int opNum, raw_ostream &OS, const char *Modifier = 0); + void printReturnOperand(const MachineInstr *MI, int opNum, raw_ostream &OS, + const char *Modifier = 0); void printPredicateOperand(const MachineInstr *MI, raw_ostream &O); + unsigned GetOrCreateSourceID(StringRef FileName, + StringRef DirName); + // autogen'd. void printInstruction(const MachineInstr *MI, raw_ostream &OS); static const char *getRegisterName(unsigned RegNo); @@ -71,20 +80,23 @@ public: private: void EmitVariableDeclaration(const GlobalVariable *gv); void EmitFunctionDeclaration(); + + StringMap<unsigned> SourceIdMap; }; // class PTXAsmPrinter } // namespace static const char PARAM_PREFIX[] = "__param_"; +static const char RETURN_PREFIX[] = "__ret_"; static const char *getRegisterTypeName(unsigned RegNo) { #define TEST_REGCLS(cls, clsstr) \ if (PTX::cls ## RegisterClass->contains(RegNo)) return # clsstr; - TEST_REGCLS(Preds, pred); - TEST_REGCLS(RRegu16, u16); - TEST_REGCLS(RRegu32, u32); - TEST_REGCLS(RRegu64, u64); - TEST_REGCLS(RRegf32, f32); - TEST_REGCLS(RRegf64, f64); + TEST_REGCLS(RegPred, pred); + TEST_REGCLS(RegI16, b16); + TEST_REGCLS(RegI32, b32); + TEST_REGCLS(RegI64, b64); + TEST_REGCLS(RegF32, b32); + TEST_REGCLS(RegF64, b64); #undef TEST_REGCLS llvm_unreachable("Not in any register class!"); @@ -162,6 +174,27 @@ void PTXAsmPrinter::EmitStartOfAsmFile(Module &M) OutStreamer.EmitRawText(Twine("\t.target " + ST.getTargetString() + (ST.supportsDouble() ? "" : ", map_f64_to_f32"))); + // .address_size directive is optional, but it must immediately follow + // the .target directive if present within a module + if (ST.supportsPTX23()) { + std::string addrSize = ST.is64Bit() ? "64" : "32"; + OutStreamer.EmitRawText(Twine("\t.address_size " + addrSize)); + } + + OutStreamer.AddBlankLine(); + + // Define any .file directives + DebugInfoFinder DbgFinder; + DbgFinder.processModule(M); + + for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(), + E = DbgFinder.compile_unit_end(); I != E; ++I) { + DICompileUnit DIUnit(*I); + StringRef FN = DIUnit.getFilename(); + StringRef Dir = DIUnit.getDirectory(); + GetOrCreateSourceID(FN, Dir); + } + OutStreamer.AddBlankLine(); // declare global variables @@ -194,6 +227,21 @@ void PTXAsmPrinter::EmitFunctionBodyStart() { def += ';'; OutStreamer.EmitRawText(Twine(def)); } + + const MachineFrameInfo* FrameInfo = MF->getFrameInfo(); + DEBUG(dbgs() << "Have " << FrameInfo->getNumObjects() + << " frame object(s)\n"); + for (unsigned i = 0, e = FrameInfo->getNumObjects(); i != e; ++i) { + DEBUG(dbgs() << "Size of object: " << FrameInfo->getObjectSize(i) << "\n"); + if (FrameInfo->getObjectSize(i) > 0) { + std::string def = "\t.reg .b"; + def += utostr(FrameInfo->getObjectSize(i)*8); // Convert to bits + def += " s"; + def += utostr(i); + def += ";"; + OutStreamer.EmitRawText(Twine(def)); + } + } } void PTXAsmPrinter::EmitInstruction(const MachineInstr *MI) { @@ -202,6 +250,54 @@ void PTXAsmPrinter::EmitInstruction(const MachineInstr *MI) { raw_string_ostream OS(str); + DebugLoc DL = MI->getDebugLoc(); + if (!DL.isUnknown()) { + + const MDNode *S = DL.getScope(MF->getFunction()->getContext()); + + // This is taken from DwarfDebug.cpp, which is conveniently not a public + // LLVM class. + StringRef Fn; + StringRef Dir; + unsigned Src = 1; + if (S) { + DIDescriptor Scope(S); + if (Scope.isCompileUnit()) { + DICompileUnit CU(S); + Fn = CU.getFilename(); + Dir = CU.getDirectory(); + } else if (Scope.isFile()) { + DIFile F(S); + Fn = F.getFilename(); + Dir = F.getDirectory(); + } else if (Scope.isSubprogram()) { + DISubprogram SP(S); + Fn = SP.getFilename(); + Dir = SP.getDirectory(); + } else if (Scope.isLexicalBlock()) { + DILexicalBlock DB(S); + Fn = DB.getFilename(); + Dir = DB.getDirectory(); + } else + assert(0 && "Unexpected scope info"); + + Src = GetOrCreateSourceID(Fn, Dir); + } + OutStreamer.EmitDwarfLocDirective(Src, DL.getLine(), DL.getCol(), + 0, 0, 0, Fn); + + const MCDwarfLoc& MDL = OutContext.getCurrentDwarfLoc(); + + OS << "\t.loc "; + OS << utostr(MDL.getFileNum()); + OS << " "; + OS << utostr(MDL.getLine()); + OS << " "; + OS << utostr(MDL.getColumn()); + OS << "\n"; + } + + // Emit predicate printPredicateOperand(MI, OS); @@ -275,6 +371,11 @@ void PTXAsmPrinter::printParamOperand(const MachineInstr *MI, int opNum, OS << PARAM_PREFIX << (int) MI->getOperand(opNum).getImm() + 1; } +void PTXAsmPrinter::printReturnOperand(const MachineInstr *MI, int opNum, + raw_ostream &OS, const char *Modifier) { + OS << RETURN_PREFIX << (int) MI->getOperand(opNum).getImm() + 1; +} + void PTXAsmPrinter::EmitVariableDeclaration(const GlobalVariable *gv) { // Check to see if this is a special global used by LLVM, if so, emit it. if (EmitSpecialLLVMGlobal(gv)) @@ -311,7 +412,7 @@ void PTXAsmPrinter::EmitVariableDeclaration(const GlobalVariable *gv) { decl += ".b8 "; decl += gvsym->getName(); decl += "["; - + if (elementTy->isArrayTy()) { assert(elementTy->isArrayTy() && "Only pointers to arrays are supported"); @@ -320,7 +421,7 @@ void PTXAsmPrinter::EmitVariableDeclaration(const GlobalVariable *gv) { elementTy = arrayTy->getElementType(); unsigned numElements = arrayTy->getNumElements(); - + while (elementTy->isArrayTy()) { arrayTy = dyn_cast<const ArrayType>(elementTy); @@ -336,17 +437,17 @@ void PTXAsmPrinter::EmitVariableDeclaration(const GlobalVariable *gv) { // Compute the size of the array, in bytes. uint64_t arraySize = (elementTy->getPrimitiveSizeInBits() >> 3) * numElements; - + decl += utostr(arraySize); } - + decl += "]"; - + // handle string constants (assume ConstantArray means string) - + if (gv->hasInitializer()) { - Constant *C = gv->getInitializer(); + const Constant *C = gv->getInitializer(); if (const ConstantArray *CA = dyn_cast<ConstantArray>(C)) { decl += " = {"; @@ -354,10 +455,11 @@ void PTXAsmPrinter::EmitVariableDeclaration(const GlobalVariable *gv) { for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) { if (i > 0) decl += ","; - - decl += "0x" + utohexstr(cast<ConstantInt>(CA->getOperand(i))->getZExtValue()); + + decl += "0x" + + utohexstr(cast<ConstantInt>(CA->getOperand(i))->getZExtValue()); } - + decl += "}"; } } @@ -393,17 +495,25 @@ void PTXAsmPrinter::EmitFunctionDeclaration() { const PTXMachineFunctionInfo *MFI = MF->getInfo<PTXMachineFunctionInfo>(); const bool isKernel = MFI->isKernel(); - unsigned reg; + const PTXSubtarget& ST = TM.getSubtarget<PTXSubtarget>(); std::string decl = isKernel ? ".entry" : ".func"; - // Print return register - reg = MFI->retReg(); - if (!isKernel && reg != PTX::NoRegister) { - decl += " (.reg ."; // FIXME: could it return in .param space? - decl += getRegisterTypeName(reg); - decl += " "; - decl += getRegisterName(reg); + unsigned cnt = 0; + + if (!isKernel) { + decl += " ("; + for (PTXMachineFunctionInfo::ret_iterator + i = MFI->retRegBegin(), e = MFI->retRegEnd(), b = i; + i != e; ++i) { + if (i != b) { + decl += ", "; + } + decl += ".reg ."; + decl += getRegisterTypeName(*i); + decl += " "; + decl += getRegisterName(*i); + } decl += ")"; } @@ -411,40 +521,31 @@ void PTXAsmPrinter::EmitFunctionDeclaration() { decl += " "; decl += CurrentFnSym->getName().str(); - // Print parameter list - if (!MFI->argRegEmpty()) { - decl += " ("; - if (isKernel) { - unsigned cnt = 0; - for(PTXMachineFunctionInfo::reg_iterator - i = MFI->argRegBegin(), e = MFI->argRegEnd(), b = i; - i != e; ++i) { - reg = *i; - assert(reg != PTX::NoRegister && "Not a valid register!"); - if (i != b) - decl += ", "; - decl += ".param ."; - decl += getRegisterTypeName(reg); - decl += " "; - decl += PARAM_PREFIX; - decl += utostr(++cnt); - } + decl += " ("; + + cnt = 0; + + // Print parameters + for (PTXMachineFunctionInfo::reg_iterator + i = MFI->argRegBegin(), e = MFI->argRegEnd(), b = i; + i != e; ++i) { + if (i != b) { + decl += ", "; + } + if (isKernel || ST.useParamSpaceForDeviceArgs()) { + decl += ".param .b"; + decl += utostr(*i); + decl += " "; + decl += PARAM_PREFIX; + decl += utostr(++cnt); } else { - for (PTXMachineFunctionInfo::reg_iterator - i = MFI->argRegBegin(), e = MFI->argRegEnd(), b = i; - i != e; ++i) { - reg = *i; - assert(reg != PTX::NoRegister && "Not a valid register!"); - if (i != b) - decl += ", "; - decl += ".reg ."; - decl += getRegisterTypeName(reg); - decl += " "; - decl += getRegisterName(reg); - } + decl += ".reg ."; + decl += getRegisterTypeName(*i); + decl += " "; + decl += getRegisterName(*i); } - decl += ")"; } + decl += ")"; OutStreamer.EmitRawText(Twine(decl)); } @@ -468,6 +569,33 @@ printPredicateOperand(const MachineInstr *MI, raw_ostream &O) { } } +unsigned PTXAsmPrinter::GetOrCreateSourceID(StringRef FileName, + StringRef DirName) { + // If FE did not provide a file name, then assume stdin. + if (FileName.empty()) + return GetOrCreateSourceID("<stdin>", StringRef()); + + // MCStream expects full path name as filename. + if (!DirName.empty() && !sys::path::is_absolute(FileName)) { + SmallString<128> FullPathName = DirName; + sys::path::append(FullPathName, FileName); + // Here FullPathName will be copied into StringMap by GetOrCreateSourceID. + return GetOrCreateSourceID(StringRef(FullPathName), StringRef()); + } + + StringMapEntry<unsigned> &Entry = SourceIdMap.GetOrCreateValue(FileName); + if (Entry.getValue()) + return Entry.getValue(); + + unsigned SrcId = SourceIdMap.size(); + Entry.setValue(SrcId); + + // Print out a .file directive to specify files for .loc directives. + OutStreamer.EmitDwarfFileDirective(SrcId, Entry.getKey()); + + return SrcId; +} + #include "PTXGenAsmWriter.inc" // Force static initialization. diff --git a/lib/Target/PTX/PTXCallingConv.td b/lib/Target/PTX/PTXCallingConv.td new file mode 100644 index 000000000000..3e3ff4896621 --- /dev/null +++ b/lib/Target/PTX/PTXCallingConv.td @@ -0,0 +1,29 @@ + +//===--- PTXCallingConv.td - Calling Conventions -----------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This describes the calling conventions for the PTX architecture. +// +//===----------------------------------------------------------------------===// + +// PTX Formal Parameter Calling Convention +def CC_PTX : CallingConv<[ + CCIfType<[i1], CCAssignToReg<[P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124, P125, P126, P127]>>, + CCIfType<[i16], CCAssignToReg<[RH12, RH13, RH14, RH15, RH16, RH17, RH18, RH19, RH20, RH21, RH22, RH23, RH24, RH25, RH26, RH27, RH28, RH29, RH30, RH31, RH32, RH33, RH34, RH35, RH36, RH37, RH38, RH39, RH40, RH41, RH42, RH43, RH44, RH45, RH46, RH47, RH48, RH49, RH50, RH51, RH52, RH53, RH54, RH55, RH56, RH57, RH58, RH59, RH60, RH61, RH62, RH63, RH64, RH65, RH66, RH67, RH68, RH69, RH70, RH71, RH72, RH73, RH74, RH75, RH76, RH77, RH78, RH79, RH80, RH81, RH82, RH83, RH84, RH85, RH86, RH87, RH88, RH89, RH90, RH91, RH92, RH93, RH94, RH95, RH96, RH97, RH98, RH99, RH100, RH101, RH102, RH103, RH104, RH105, RH106, RH107, RH108, RH109, RH110, RH111, RH112, RH113, RH114, RH115, RH116, RH117, RH118, RH119, RH120, RH121, RH122, RH123, RH124, RH125, RH126, RH127]>>, + CCIfType<[i32,f32], CCAssignToReg<[R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, R32, R33, R34, R35, R36, R37, R38, R39, R40, R41, R42, R43, R44, R45, R46, R47, R48, R49, R50, R51, R52, R53, R54, R55, R56, R57, R58, R59, R60, R61, R62, R63, R64, R65, R66, R67, R68, R69, R70, R71, R72, R73, R74, R75, R76, R77, R78, R79, R80, R81, R82, R83, R84, R85, R86, R87, R88, R89, R90, R91, R92, R93, R94, R95, R96, R97, R98, R99, R100, R101, R102, R103, R104, R105, R106, R107, R108, R109, R110, R111, R112, R113, R114, R115, R116, R117, R118, R119, R120, R121, R122, R123, R124, R125, R126, R127]>>, + CCIfType<[i64,f64], CCAssignToReg<[RD12, RD13, RD14, RD15, RD16, RD17, RD18, RD19, RD20, RD21, RD22, RD23, RD24, RD25, RD26, RD27, RD28, RD29, RD30, RD31, RD32, RD33, RD34, RD35, RD36, RD37, RD38, RD39, RD40, RD41, RD42, RD43, RD44, RD45, RD46, RD47, RD48, RD49, RD50, RD51, RD52, RD53, RD54, RD55, RD56, RD57, RD58, RD59, RD60, RD61, RD62, RD63, RD64, RD65, RD66, RD67, RD68, RD69, RD70, RD71, RD72, RD73, RD74, RD75, RD76, RD77, RD78, RD79, RD80, RD81, RD82, RD83, RD84, RD85, RD86, RD87, RD88, RD89, RD90, RD91, RD92, RD93, RD94, RD95, RD96, RD97, RD98, RD99, RD100, RD101, RD102, RD103, RD104, RD105, RD106, RD107, RD108, RD109, RD110, RD111, RD112, RD113, RD114, RD115, RD116, RD117, RD118, RD119, RD120, RD121, RD122, RD123, RD124, RD125, RD126, RD127]>> +]>; + +// PTX Return Value Calling Convention +def RetCC_PTX : CallingConv<[ + CCIfType<[i1], CCAssignToReg<[P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11]>>, + CCIfType<[i16], CCAssignToReg<[RH0, RH1, RH2, RH3, RH4, RH5, RH6, RH7, RH8, RH9, RH10, RH11]>>, + CCIfType<[i32,f32], CCAssignToReg<[R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11]>>, + CCIfType<[i64,f64], CCAssignToReg<[RD0, RD1, RD2, RD3, RD4, RD5, RD6, RD7, RD8, RD9, RD10, RD11]>> +]>; diff --git a/lib/Target/PTX/PTXISelDAGToDAG.cpp b/lib/Target/PTX/PTXISelDAGToDAG.cpp index b3c85da7b446..9adfa624b29e 100644 --- a/lib/Target/PTX/PTXISelDAGToDAG.cpp +++ b/lib/Target/PTX/PTXISelDAGToDAG.cpp @@ -15,6 +15,7 @@ #include "PTXTargetMachine.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/DerivedTypes.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -41,8 +42,6 @@ class PTXDAGToDAGISel : public SelectionDAGISel { #include "PTXGenDAGISel.inc" private: - SDNode *SelectREAD_PARAM(SDNode *Node); - // We need this only because we can't match intruction BRAdp // pattern (PTXbrcond bb:$d, ...) in PTXInstrInfo.td SDNode *SelectBRCOND(SDNode *Node); @@ -67,8 +66,6 @@ PTXDAGToDAGISel::PTXDAGToDAGISel(PTXTargetMachine &TM, SDNode *PTXDAGToDAGISel::Select(SDNode *Node) { switch (Node->getOpcode()) { - case PTXISD::READ_PARAM: - return SelectREAD_PARAM(Node); case ISD::BRCOND: return SelectBRCOND(Node); default: @@ -76,37 +73,6 @@ SDNode *PTXDAGToDAGISel::Select(SDNode *Node) { } } -SDNode *PTXDAGToDAGISel::SelectREAD_PARAM(SDNode *Node) { - SDValue index = Node->getOperand(1); - DebugLoc dl = Node->getDebugLoc(); - unsigned opcode; - - if (index.getOpcode() != ISD::TargetConstant) - llvm_unreachable("READ_PARAM: index is not ISD::TargetConstant"); - - if (Node->getValueType(0) == MVT::i16) { - opcode = PTX::LDpiU16; - } - else if (Node->getValueType(0) == MVT::i32) { - opcode = PTX::LDpiU32; - } - else if (Node->getValueType(0) == MVT::i64) { - opcode = PTX::LDpiU64; - } - else if (Node->getValueType(0) == MVT::f32) { - opcode = PTX::LDpiF32; - } - else if (Node->getValueType(0) == MVT::f64) { - opcode = PTX::LDpiF64; - } - else { - llvm_unreachable("Unknown parameter type for ld.param"); - } - - return PTXInstrInfo:: - GetPTXMachineNode(CurDAG, opcode, dl, Node->getValueType(0), index); -} - SDNode *PTXDAGToDAGISel::SelectBRCOND(SDNode *Node) { assert(Node->getNumOperands() >= 3); diff --git a/lib/Target/PTX/PTXISelLowering.cpp b/lib/Target/PTX/PTXISelLowering.cpp index e9b1d8c3bbef..6fcf710e3f1f 100644 --- a/lib/Target/PTX/PTXISelLowering.cpp +++ b/lib/Target/PTX/PTXISelLowering.cpp @@ -15,7 +15,9 @@ #include "PTXISelLowering.h" #include "PTXMachineFunctionInfo.h" #include "PTXRegisterInfo.h" +#include "PTXSubtarget.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAG.h" @@ -24,49 +26,80 @@ using namespace llvm; +//===----------------------------------------------------------------------===// +// Calling Convention Implementation +//===----------------------------------------------------------------------===// + +#include "PTXGenCallingConv.inc" + +//===----------------------------------------------------------------------===// +// TargetLowering Implementation +//===----------------------------------------------------------------------===// + PTXTargetLowering::PTXTargetLowering(TargetMachine &TM) : TargetLowering(TM, new TargetLoweringObjectFileELF()) { // Set up the register classes. - addRegisterClass(MVT::i1, PTX::PredsRegisterClass); - addRegisterClass(MVT::i16, PTX::RRegu16RegisterClass); - addRegisterClass(MVT::i32, PTX::RRegu32RegisterClass); - addRegisterClass(MVT::i64, PTX::RRegu64RegisterClass); - addRegisterClass(MVT::f32, PTX::RRegf32RegisterClass); - addRegisterClass(MVT::f64, PTX::RRegf64RegisterClass); + addRegisterClass(MVT::i1, PTX::RegPredRegisterClass); + addRegisterClass(MVT::i16, PTX::RegI16RegisterClass); + addRegisterClass(MVT::i32, PTX::RegI32RegisterClass); + addRegisterClass(MVT::i64, PTX::RegI64RegisterClass); + addRegisterClass(MVT::f32, PTX::RegF32RegisterClass); + addRegisterClass(MVT::f64, PTX::RegF64RegisterClass); setBooleanContents(ZeroOrOneBooleanContent); + setMinFunctionAlignment(2); - setOperationAction(ISD::EXCEPTIONADDR, MVT::i32, Expand); - - setOperationAction(ISD::ConstantFP, MVT::f32, Legal); - setOperationAction(ISD::ConstantFP, MVT::f64, Legal); + //////////////////////////////////// + /////////// Expansion ////////////// + //////////////////////////////////// + + // (any/zero/sign) extload => load + (any/zero/sign) extend - // Turn i16 (z)extload into load + (z)extend setLoadExtAction(ISD::EXTLOAD, MVT::i16, Expand); setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Expand); - - // Turn f32 extload into load + fextend - setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); + setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Expand); - // Turn f64 truncstore into trunc + store. - setTruncStoreAction(MVT::f64, MVT::f32, Expand); + // f32 extload => load + fextend + + setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); + + // f64 truncstore => trunc + store + + setTruncStoreAction(MVT::f64, MVT::f32, Expand); + + // sign_extend_inreg => sign_extend + + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); + + // br_cc => brcond - // Customize translation of memory addresses - setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); - setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); - - // Expand BR_CC into BRCOND setOperationAction(ISD::BR_CC, MVT::Other, Expand); - // Expand SELECT_CC into SETCC + // select_cc => setcc + setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); setOperationAction(ISD::SELECT_CC, MVT::f32, Expand); setOperationAction(ISD::SELECT_CC, MVT::f64, Expand); - // need to lower SETCC of Preds into bitwise logic + //////////////////////////////////// + //////////// Legal ///////////////// + //////////////////////////////////// + + setOperationAction(ISD::ConstantFP, MVT::f32, Legal); + setOperationAction(ISD::ConstantFP, MVT::f64, Legal); + + //////////////////////////////////// + //////////// Custom //////////////// + //////////////////////////////////// + + // customise setcc to use bitwise logic if possible + setOperationAction(ISD::SETCC, MVT::i1, Custom); - setMinFunctionAlignment(2); + // customize translation of memory addresses + + setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); + setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); // Compute derived properties from the register classes computeRegisterProperties(); @@ -93,8 +126,10 @@ const char *PTXTargetLowering::getTargetNodeName(unsigned Opcode) const { llvm_unreachable("Unknown opcode"); case PTXISD::COPY_ADDRESS: return "PTXISD::COPY_ADDRESS"; - case PTXISD::READ_PARAM: - return "PTXISD::READ_PARAM"; + case PTXISD::LOAD_PARAM: + return "PTXISD::LOAD_PARAM"; + case PTXISD::STORE_PARAM: + return "PTXISD::STORE_PARAM"; case PTXISD::EXIT: return "PTXISD::EXIT"; case PTXISD::RET: @@ -113,18 +148,18 @@ SDValue PTXTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const { SDValue Op2 = Op.getOperand(2); DebugLoc dl = Op.getDebugLoc(); ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); - + // Look for X == 0, X == 1, X != 0, or X != 1 // We can simplify these to bitwise logic - + if (Op1.getOpcode() == ISD::Constant && (cast<ConstantSDNode>(Op1)->getZExtValue() == 1 || cast<ConstantSDNode>(Op1)->isNullValue()) && (CC == ISD::SETEQ || CC == ISD::SETNE)) { - return DAG.getNode(ISD::AND, dl, MVT::i1, Op0, Op1); + return DAG.getNode(ISD::AND, dl, MVT::i1, Op0, Op1); } - + return DAG.getNode(ISD::SETCC, dl, MVT::i1, Op0, Op1, Op2); } @@ -149,27 +184,6 @@ LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const { // Calling Convention Implementation //===----------------------------------------------------------------------===// -namespace { -struct argmap_entry { - MVT::SimpleValueType VT; - TargetRegisterClass *RC; - TargetRegisterClass::iterator loc; - - argmap_entry(MVT::SimpleValueType _VT, TargetRegisterClass *_RC) - : VT(_VT), RC(_RC), loc(_RC->begin()) {} - - void reset() { loc = RC->begin(); } - bool operator==(MVT::SimpleValueType _VT) const { return VT == _VT; } -} argmap[] = { - argmap_entry(MVT::i1, PTX::PredsRegisterClass), - argmap_entry(MVT::i16, PTX::RRegu16RegisterClass), - argmap_entry(MVT::i32, PTX::RRegu32RegisterClass), - argmap_entry(MVT::i64, PTX::RRegu64RegisterClass), - argmap_entry(MVT::f32, PTX::RRegf32RegisterClass), - argmap_entry(MVT::f64, PTX::RRegf64RegisterClass) -}; -} // end anonymous namespace - SDValue PTXTargetLowering:: LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, @@ -181,6 +195,7 @@ SDValue PTXTargetLowering:: if (isVarArg) llvm_unreachable("PTX does not support varargs"); MachineFunction &MF = DAG.getMachineFunction(); + const PTXSubtarget& ST = getTargetMachine().getSubtarget<PTXSubtarget>(); PTXMachineFunctionInfo *MFI = MF.getInfo<PTXMachineFunctionInfo>(); switch (CallConv) { @@ -195,44 +210,76 @@ SDValue PTXTargetLowering:: break; } - // Make sure we don't add argument registers twice - if (MFI->isDoneAddArg()) - llvm_unreachable("cannot add argument registers twice"); - - // Reset argmap before allocation - for (struct argmap_entry *i = argmap, *e = argmap + array_lengthof(argmap); - i != e; ++ i) - i->reset(); - - for (int i = 0, e = Ins.size(); i != e; ++ i) { - MVT::SimpleValueType VT = Ins[i].VT.SimpleTy; - - struct argmap_entry *entry = std::find(argmap, - argmap + array_lengthof(argmap), VT); - if (entry == argmap + array_lengthof(argmap)) - llvm_unreachable("Type of argument is not supported"); - - if (MFI->isKernel() && entry->RC == PTX::PredsRegisterClass) - llvm_unreachable("cannot pass preds to kernel"); - - MachineRegisterInfo &RegInfo = DAG.getMachineFunction().getRegInfo(); - - unsigned preg = *++(entry->loc); // allocate start from register 1 - unsigned vreg = RegInfo.createVirtualRegister(entry->RC); - RegInfo.addLiveIn(preg, vreg); - - MFI->addArgReg(preg); - - SDValue inval; - if (MFI->isKernel()) - inval = DAG.getNode(PTXISD::READ_PARAM, dl, VT, Chain, - DAG.getTargetConstant(i, MVT::i32)); - else - inval = DAG.getCopyFromReg(Chain, dl, vreg, VT); - InVals.push_back(inval); + // We do one of two things here: + // IsKernel || SM >= 2.0 -> Use param space for arguments + // SM < 2.0 -> Use registers for arguments + if (MFI->isKernel() || ST.useParamSpaceForDeviceArgs()) { + // We just need to emit the proper LOAD_PARAM ISDs + for (unsigned i = 0, e = Ins.size(); i != e; ++i) { + + assert((!MFI->isKernel() || Ins[i].VT != MVT::i1) && + "Kernels cannot take pred operands"); + + SDValue ArgValue = DAG.getNode(PTXISD::LOAD_PARAM, dl, Ins[i].VT, Chain, + DAG.getTargetConstant(i, MVT::i32)); + InVals.push_back(ArgValue); + + // Instead of storing a physical register in our argument list, we just + // store the total size of the parameter, in bits. The ASM printer + // knows how to process this. + MFI->addArgReg(Ins[i].VT.getStoreSizeInBits()); + } + } + else { + // For device functions, we use the PTX calling convention to do register + // assignments then create CopyFromReg ISDs for the allocated registers + + SmallVector<CCValAssign, 16> ArgLocs; + CCState CCInfo(CallConv, isVarArg, MF, getTargetMachine(), ArgLocs, + *DAG.getContext()); + + CCInfo.AnalyzeFormalArguments(Ins, CC_PTX); + + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + + CCValAssign& VA = ArgLocs[i]; + EVT RegVT = VA.getLocVT(); + TargetRegisterClass* TRC = 0; + + assert(VA.isRegLoc() && "CCValAssign must be RegLoc"); + + // Determine which register class we need + if (RegVT == MVT::i1) { + TRC = PTX::RegPredRegisterClass; + } + else if (RegVT == MVT::i16) { + TRC = PTX::RegI16RegisterClass; + } + else if (RegVT == MVT::i32) { + TRC = PTX::RegI32RegisterClass; + } + else if (RegVT == MVT::i64) { + TRC = PTX::RegI64RegisterClass; + } + else if (RegVT == MVT::f32) { + TRC = PTX::RegF32RegisterClass; + } + else if (RegVT == MVT::f64) { + TRC = PTX::RegF64RegisterClass; + } + else { + llvm_unreachable("Unknown parameter type"); + } + + unsigned Reg = MF.getRegInfo().createVirtualRegister(TRC); + MF.getRegInfo().addLiveIn(VA.getLocReg(), Reg); + + SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT); + InVals.push_back(ArgValue); + + MFI->addArgReg(VA.getLocReg()); + } } - - MFI->doneAddArg(); return Chain; } @@ -254,51 +301,47 @@ SDValue PTXTargetLowering:: assert(Outs.size() == 0 && "Kernel must return void."); return DAG.getNode(PTXISD::EXIT, dl, MVT::Other, Chain); case CallingConv::PTX_Device: - assert(Outs.size() <= 1 && "Can at most return one value."); + //assert(Outs.size() <= 1 && "Can at most return one value."); break; } - // PTX_Device - - // return void - if (Outs.size() == 0) - return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain); + MachineFunction& MF = DAG.getMachineFunction(); + PTXMachineFunctionInfo *MFI = MF.getInfo<PTXMachineFunctionInfo>(); SDValue Flag; - unsigned reg; - if (Outs[0].VT == MVT::i16) { - reg = PTX::RH0; - } - else if (Outs[0].VT == MVT::i32) { - reg = PTX::R0; - } - else if (Outs[0].VT == MVT::i64) { - reg = PTX::RD0; - } - else if (Outs[0].VT == MVT::f32) { - reg = PTX::F0; - } - else { - assert(Outs[0].VT == MVT::f64 && "Can return only basic types"); - reg = PTX::FD0; - } + // Even though we could use the .param space for return arguments for + // device functions if SM >= 2.0 and the number of return arguments is + // only 1, we just always use registers since this makes the codegen + // easier. + SmallVector<CCValAssign, 16> RVLocs; + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), + getTargetMachine(), RVLocs, *DAG.getContext()); - MachineFunction &MF = DAG.getMachineFunction(); - PTXMachineFunctionInfo *MFI = MF.getInfo<PTXMachineFunctionInfo>(); - MFI->setRetReg(reg); + CCInfo.AnalyzeReturn(Outs, RetCC_PTX); + + for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { + CCValAssign& VA = RVLocs[i]; - // If this is the first return lowered for this function, add the regs to the - // liveout set for the function - if (DAG.getMachineFunction().getRegInfo().liveout_empty()) - DAG.getMachineFunction().getRegInfo().addLiveOut(reg); + assert(VA.isRegLoc() && "CCValAssign must be RegLoc"); - // Copy the result values into the output registers - Chain = DAG.getCopyToReg(Chain, dl, reg, OutVals[0], Flag); + unsigned Reg = VA.getLocReg(); - // Guarantee that all emitted copies are stuck together, - // avoiding something bad - Flag = Chain.getValue(1); + DAG.getMachineFunction().getRegInfo().addLiveOut(Reg); - return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain, Flag); + Chain = DAG.getCopyToReg(Chain, dl, Reg, OutVals[i], Flag); + + // Guarantee that all emitted copies are stuck together, + // avoiding something bad + Flag = Chain.getValue(1); + + MFI->addRetReg(Reg); + } + + if (Flag.getNode() == 0) { + return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain); + } + else { + return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain, Flag); + } } diff --git a/lib/Target/PTX/PTXISelLowering.h b/lib/Target/PTX/PTXISelLowering.h index 225c0004a913..43185416e1fc 100644 --- a/lib/Target/PTX/PTXISelLowering.h +++ b/lib/Target/PTX/PTXISelLowering.h @@ -24,12 +24,13 @@ class PTXTargetMachine; namespace PTXISD { enum NodeType { FIRST_NUMBER = ISD::BUILTIN_OP_END, - READ_PARAM, + LOAD_PARAM, + STORE_PARAM, EXIT, RET, COPY_ADDRESS }; -} // namespace PTXISD +} // namespace PTXISD class PTXTargetLowering : public TargetLowering { public: @@ -40,7 +41,7 @@ class PTXTargetLowering : public TargetLowering { virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; virtual SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const; - + virtual SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, @@ -58,9 +59,9 @@ class PTXTargetLowering : public TargetLowering { const SmallVectorImpl<SDValue> &OutVals, DebugLoc dl, SelectionDAG &DAG) const; - + virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const; - + private: SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; }; // class PTXTargetLowering diff --git a/lib/Target/PTX/PTXInstrFormats.td b/lib/Target/PTX/PTXInstrFormats.td index e4e099987e8d..8cee351ee0df 100644 --- a/lib/Target/PTX/PTXInstrFormats.td +++ b/lib/Target/PTX/PTXInstrFormats.td @@ -9,7 +9,7 @@ // PTX Predicate operand, default to (0, 0) = (zero-reg, always). // Leave PrintMethod empty; predicate printing is defined elsewhere. -def pred : PredicateOperand<OtherVT, (ops Preds, i32imm), +def pred : PredicateOperand<OtherVT, (ops RegPred, i32imm), (ops (i1 zero_reg), (i32 0))>; let Namespace = "PTX" in { diff --git a/lib/Target/PTX/PTXInstrInfo.cpp b/lib/Target/PTX/PTXInstrInfo.cpp index a12a6d01afa7..425265a2fdb7 100644 --- a/lib/Target/PTX/PTXInstrInfo.cpp +++ b/lib/Target/PTX/PTXInstrInfo.cpp @@ -18,27 +18,29 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/Target/TargetRegistry.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -using namespace llvm; - +#define GET_INSTRINFO_CTOR #include "PTXGenInstrInfo.inc" +using namespace llvm; + PTXInstrInfo::PTXInstrInfo(PTXTargetMachine &_TM) - : TargetInstrInfoImpl(PTXInsts, array_lengthof(PTXInsts)), + : PTXGenInstrInfo(), RI(_TM, *this), TM(_TM) {} static const struct map_entry { const TargetRegisterClass *cls; const int opcode; } map[] = { - { &PTX::RRegu16RegClass, PTX::MOVU16rr }, - { &PTX::RRegu32RegClass, PTX::MOVU32rr }, - { &PTX::RRegu64RegClass, PTX::MOVU64rr }, - { &PTX::RRegf32RegClass, PTX::MOVF32rr }, - { &PTX::RRegf64RegClass, PTX::MOVF64rr }, - { &PTX::PredsRegClass, PTX::MOVPREDrr } + { &PTX::RegI16RegClass, PTX::MOVU16rr }, + { &PTX::RegI32RegClass, PTX::MOVU32rr }, + { &PTX::RegI64RegClass, PTX::MOVU64rr }, + { &PTX::RegF32RegClass, PTX::MOVF32rr }, + { &PTX::RegF64RegClass, PTX::MOVF64rr }, + { &PTX::RegPredRegClass, PTX::MOVPREDrr } }; void PTXInstrInfo::copyPhysReg(MachineBasicBlock &MBB, @@ -47,8 +49,8 @@ void PTXInstrInfo::copyPhysReg(MachineBasicBlock &MBB, bool KillSrc) const { for (int i = 0, e = sizeof(map)/sizeof(map[0]); i != e; ++ i) { if (map[i].cls->contains(DstReg, SrcReg)) { - const TargetInstrDesc &TID = get(map[i].opcode); - MachineInstr *MI = BuildMI(MBB, I, DL, TID, DstReg). + const MCInstrDesc &MCID = get(map[i].opcode); + MachineInstr *MI = BuildMI(MBB, I, DL, MCID, DstReg). addReg(SrcReg, getKillRegState(KillSrc)); AddDefaultPredicate(MI); return; @@ -69,8 +71,8 @@ bool PTXInstrInfo::copyRegToReg(MachineBasicBlock &MBB, for (int i = 0, e = sizeof(map)/sizeof(map[0]); i != e; ++ i) if (DstRC == map[i].cls) { - const TargetInstrDesc &TID = get(map[i].opcode); - MachineInstr *MI = BuildMI(MBB, I, DL, TID, DstReg).addReg(SrcReg); + const MCInstrDesc &MCID = get(map[i].opcode); + MachineInstr *MI = BuildMI(MBB, I, DL, MCID, DstReg).addReg(SrcReg); AddDefaultPredicate(MI); return true; } @@ -155,7 +157,7 @@ DefinesPredicate(MachineInstr *MI, const MachineOperand &MO = MI->getOperand(0); - if (!MO.isReg() || RI.getRegClass(MO.getReg()) != &PTX::PredsRegClass) + if (!MO.isReg() || RI.getRegClass(MO.getReg()) != &PTX::RegPredRegClass) return false; Pred.push_back(MO); @@ -178,13 +180,13 @@ AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock::const_iterator iter = MBB.end(); const MachineInstr& instLast1 = *--iter; - const TargetInstrDesc &desc1 = instLast1.getDesc(); + const MCInstrDesc &desc1 = instLast1.getDesc(); // for special case that MBB has only 1 instruction const bool IsSizeOne = MBB.size() == 1; // if IsSizeOne is true, *--iter and instLast2 are invalid // we put a dummy value in instLast2 and desc2 since they are used const MachineInstr& instLast2 = IsSizeOne ? instLast1 : *--iter; - const TargetInstrDesc &desc2 = IsSizeOne ? desc1 : instLast2.getDesc(); + const MCInstrDesc &desc2 = IsSizeOne ? desc1 : instLast2.getDesc(); DEBUG(dbgs() << "\n"); DEBUG(dbgs() << "AnalyzeBranch: opcode: " << instLast1.getOpcode() << "\n"); @@ -288,6 +290,77 @@ InsertBranch(MachineBasicBlock &MBB, } } +// Memory operand folding for spills +void PTXInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MII, + unsigned SrcReg, bool isKill, int FrameIdx, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { + MachineInstr& MI = *MII; + DebugLoc DL = MI.getDebugLoc(); + + DEBUG(dbgs() << "storeRegToStackSlot: " << MI); + + int OpCode; + + // Select the appropriate opcode based on the register class + if (RC == PTX::RegI16RegisterClass) { + OpCode = PTX::STACKSTOREI16; + } else if (RC == PTX::RegI32RegisterClass) { + OpCode = PTX::STACKSTOREI32; + } else if (RC == PTX::RegI64RegisterClass) { + OpCode = PTX::STACKSTOREI32; + } else if (RC == PTX::RegF32RegisterClass) { + OpCode = PTX::STACKSTOREF32; + } else if (RC == PTX::RegF64RegisterClass) { + OpCode = PTX::STACKSTOREF64; + } else { + llvm_unreachable("Unknown PTX register class!"); + } + + // Build the store instruction (really a mov) + MachineInstrBuilder MIB = BuildMI(MBB, MII, DL, get(OpCode)); + MIB.addFrameIndex(FrameIdx); + MIB.addReg(SrcReg); + + AddDefaultPredicate(MIB); +} + +void PTXInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MII, + unsigned DestReg, int FrameIdx, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { + MachineInstr& MI = *MII; + DebugLoc DL = MI.getDebugLoc(); + + DEBUG(dbgs() << "loadRegToStackSlot: " << MI); + + int OpCode; + + // Select the appropriate opcode based on the register class + if (RC == PTX::RegI16RegisterClass) { + OpCode = PTX::STACKLOADI16; + } else if (RC == PTX::RegI32RegisterClass) { + OpCode = PTX::STACKLOADI32; + } else if (RC == PTX::RegI64RegisterClass) { + OpCode = PTX::STACKLOADI32; + } else if (RC == PTX::RegF32RegisterClass) { + OpCode = PTX::STACKLOADF32; + } else if (RC == PTX::RegF64RegisterClass) { + OpCode = PTX::STACKLOADF64; + } else { + llvm_unreachable("Unknown PTX register class!"); + } + + // Build the load instruction (really a mov) + MachineInstrBuilder MIB = BuildMI(MBB, MII, DL, get(OpCode)); + MIB.addReg(DestReg); + MIB.addFrameIndex(FrameIdx); + + AddDefaultPredicate(MIB); +} + // static helper routines MachineSDNode *PTXInstrInfo:: @@ -316,7 +389,7 @@ void PTXInstrInfo::AddDefaultPredicate(MachineInstr *MI) { } bool PTXInstrInfo::IsAnyKindOfBranch(const MachineInstr& inst) { - const TargetInstrDesc &desc = inst.getDesc(); + const MCInstrDesc &desc = inst.getDesc(); return desc.isTerminator() || desc.isBranch() || desc.isIndirectBranch(); } diff --git a/lib/Target/PTX/PTXInstrInfo.h b/lib/Target/PTX/PTXInstrInfo.h index a04be7728f88..871f1ac8d376 100644 --- a/lib/Target/PTX/PTXInstrInfo.h +++ b/lib/Target/PTX/PTXInstrInfo.h @@ -17,6 +17,9 @@ #include "PTXRegisterInfo.h" #include "llvm/Target/TargetInstrInfo.h" +#define GET_INSTRINFO_HEADER +#include "PTXGenInstrInfo.inc" + namespace llvm { class PTXTargetMachine; @@ -24,7 +27,7 @@ class MachineSDNode; class SDValue; class SelectionDAG; -class PTXInstrInfo : public TargetInstrInfoImpl { +class PTXInstrInfo : public PTXGenInstrInfo { private: const PTXRegisterInfo RI; PTXTargetMachine &TM; @@ -84,6 +87,29 @@ public: const SmallVectorImpl<MachineOperand> &Cond, DebugLoc DL) const; + // Memory operand folding for spills + // TODO: Implement this eventually and get rid of storeRegToStackSlot and + // loadRegFromStackSlot. Doing so will get rid of the "stack" registers + // we currently use to spill, though I doubt the overall effect on ptxas + // output will be large. I have yet to see a case where ptxas is unable + // to see through the "stack" register usage and hence generates + // efficient code anyway. + // virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, + // MachineInstr* MI, + // const SmallVectorImpl<unsigned> &Ops, + // int FrameIndex) const; + + virtual void storeRegToStackSlot(MachineBasicBlock& MBB, + MachineBasicBlock::iterator MII, + unsigned SrcReg, bool isKill, int FrameIndex, + const TargetRegisterClass* RC, + const TargetRegisterInfo* TRI) const; + virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MII, + unsigned DestReg, int FrameIdx, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const; + // static helper routines static MachineSDNode *GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode, diff --git a/lib/Target/PTX/PTXInstrInfo.td b/lib/Target/PTX/PTXInstrInfo.td index d5d08bed2247..6bfe906d40ab 100644 --- a/lib/Target/PTX/PTXInstrInfo.td +++ b/lib/Target/PTX/PTXInstrInfo.td @@ -26,10 +26,10 @@ def Use32BitAddresses : Predicate<"!getSubtarget().is64Bit()">; def Use64BitAddresses : Predicate<"getSubtarget().is64Bit()">; // Shader Model Support -def SupportsSM13 : Predicate<"getSubtarget().supportsSM13()">; -def DoesNotSupportSM13 : Predicate<"!getSubtarget().supportsSM13()">; -def SupportsSM20 : Predicate<"getSubtarget().supportsSM20()">; -def DoesNotSupportSM20 : Predicate<"!getSubtarget().supportsSM20()">; +def FDivNeedsRoundingMode : Predicate<"getSubtarget().fdivNeedsRoundingMode()">; +def FDivNoRoundingMode : Predicate<"!getSubtarget().fdivNeedsRoundingMode()">; +def FMadNeedsRoundingMode : Predicate<"getSubtarget().fmadNeedsRoundingMode()">; +def FMadNoRoundingMode : Predicate<"!getSubtarget().fmadNeedsRoundingMode()">; // PTX Version Support def SupportsPTX21 : Predicate<"getSubtarget().supportsPTX21()">; @@ -143,11 +143,11 @@ def ADDRii64 : ComplexPattern<i64, 2, "SelectADDRii", [], []>; // Address operands def MEMri32 : Operand<i32> { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops RRegu32, i32imm); + let MIOperandInfo = (ops RegI32, i32imm); } def MEMri64 : Operand<i64> { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops RRegu64, i64imm); + let MIOperandInfo = (ops RegI64, i64imm); } def MEMii32 : Operand<i32> { let PrintMethod = "printMemOperand"; @@ -163,6 +163,10 @@ def MEMpi : Operand<i32> { let PrintMethod = "printParamOperand"; let MIOperandInfo = (ops i32imm); } +def MEMret : Operand<i32> { + let PrintMethod = "printReturnOperand"; + let MIOperandInfo = (ops i32imm); +} // Branch & call targets have OtherVT type. def brtarget : Operand<OtherVT>; @@ -180,181 +184,190 @@ def PTXsra : SDNode<"ISD::SRA", SDTIntBinOp>; def PTXexit : SDNode<"PTXISD::EXIT", SDTNone, [SDNPHasChain]>; def PTXret - : SDNode<"PTXISD::RET", SDTNone, [SDNPHasChain]>; + : SDNode<"PTXISD::RET", SDTNone, + [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; def PTXcopyaddress : SDNode<"PTXISD::COPY_ADDRESS", SDTypeProfile<1, 1, []>, []>; +// Load/store .param space +def PTXloadparam + : SDNode<"PTXISD::LOAD_PARAM", SDTypeProfile<1, 1, [SDTCisVT<1, i32>]>, + [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue]>; +def PTXstoreparam + : SDNode<"PTXISD::STORE_PARAM", SDTypeProfile<0, 2, [SDTCisVT<0, i32>]>, + [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue]>; + //===----------------------------------------------------------------------===// // Instruction Class Templates //===----------------------------------------------------------------------===// //===- Floating-Point Instructions - 2 Operand Form -----------------------===// multiclass PTX_FLOAT_2OP<string opcstr, SDNode opnode> { - def rr32 : InstPTX<(outs RRegf32:$d), - (ins RRegf32:$a), + def rr32 : InstPTX<(outs RegF32:$d), + (ins RegF32:$a), !strconcat(opcstr, ".f32\t$d, $a"), - [(set RRegf32:$d, (opnode RRegf32:$a))]>; - def ri32 : InstPTX<(outs RRegf32:$d), + [(set RegF32:$d, (opnode RegF32:$a))]>; + def ri32 : InstPTX<(outs RegF32:$d), (ins f32imm:$a), !strconcat(opcstr, ".f32\t$d, $a"), - [(set RRegf32:$d, (opnode fpimm:$a))]>; - def rr64 : InstPTX<(outs RRegf64:$d), - (ins RRegf64:$a), + [(set RegF32:$d, (opnode fpimm:$a))]>; + def rr64 : InstPTX<(outs RegF64:$d), + (ins RegF64:$a), !strconcat(opcstr, ".f64\t$d, $a"), - [(set RRegf64:$d, (opnode RRegf64:$a))]>; - def ri64 : InstPTX<(outs RRegf64:$d), + [(set RegF64:$d, (opnode RegF64:$a))]>; + def ri64 : InstPTX<(outs RegF64:$d), (ins f64imm:$a), !strconcat(opcstr, ".f64\t$d, $a"), - [(set RRegf64:$d, (opnode fpimm:$a))]>; + [(set RegF64:$d, (opnode fpimm:$a))]>; } //===- Floating-Point Instructions - 3 Operand Form -----------------------===// multiclass PTX_FLOAT_3OP<string opcstr, SDNode opnode> { - def rr32 : InstPTX<(outs RRegf32:$d), - (ins RRegf32:$a, RRegf32:$b), + def rr32 : InstPTX<(outs RegF32:$d), + (ins RegF32:$a, RegF32:$b), !strconcat(opcstr, ".f32\t$d, $a, $b"), - [(set RRegf32:$d, (opnode RRegf32:$a, RRegf32:$b))]>; - def ri32 : InstPTX<(outs RRegf32:$d), - (ins RRegf32:$a, f32imm:$b), + [(set RegF32:$d, (opnode RegF32:$a, RegF32:$b))]>; + def ri32 : InstPTX<(outs RegF32:$d), + (ins RegF32:$a, f32imm:$b), !strconcat(opcstr, ".f32\t$d, $a, $b"), - [(set RRegf32:$d, (opnode RRegf32:$a, fpimm:$b))]>; - def rr64 : InstPTX<(outs RRegf64:$d), - (ins RRegf64:$a, RRegf64:$b), + [(set RegF32:$d, (opnode RegF32:$a, fpimm:$b))]>; + def rr64 : InstPTX<(outs RegF64:$d), + (ins RegF64:$a, RegF64:$b), !strconcat(opcstr, ".f64\t$d, $a, $b"), - [(set RRegf64:$d, (opnode RRegf64:$a, RRegf64:$b))]>; - def ri64 : InstPTX<(outs RRegf64:$d), - (ins RRegf64:$a, f64imm:$b), + [(set RegF64:$d, (opnode RegF64:$a, RegF64:$b))]>; + def ri64 : InstPTX<(outs RegF64:$d), + (ins RegF64:$a, f64imm:$b), !strconcat(opcstr, ".f64\t$d, $a, $b"), - [(set RRegf64:$d, (opnode RRegf64:$a, fpimm:$b))]>; + [(set RegF64:$d, (opnode RegF64:$a, fpimm:$b))]>; } //===- Floating-Point Instructions - 4 Operand Form -----------------------===// multiclass PTX_FLOAT_4OP<string opcstr, SDNode opnode1, SDNode opnode2> { - def rrr32 : InstPTX<(outs RRegf32:$d), - (ins RRegf32:$a, RRegf32:$b, RRegf32:$c), + def rrr32 : InstPTX<(outs RegF32:$d), + (ins RegF32:$a, RegF32:$b, RegF32:$c), !strconcat(opcstr, ".f32\t$d, $a, $b, $c"), - [(set RRegf32:$d, (opnode2 (opnode1 RRegf32:$a, - RRegf32:$b), - RRegf32:$c))]>; - def rri32 : InstPTX<(outs RRegf32:$d), - (ins RRegf32:$a, RRegf32:$b, f32imm:$c), + [(set RegF32:$d, (opnode2 (opnode1 RegF32:$a, + RegF32:$b), + RegF32:$c))]>; + def rri32 : InstPTX<(outs RegF32:$d), + (ins RegF32:$a, RegF32:$b, f32imm:$c), !strconcat(opcstr, ".f32\t$d, $a, $b, $c"), - [(set RRegf32:$d, (opnode2 (opnode1 RRegf32:$a, - RRegf32:$b), + [(set RegF32:$d, (opnode2 (opnode1 RegF32:$a, + RegF32:$b), fpimm:$c))]>; - def rrr64 : InstPTX<(outs RRegf64:$d), - (ins RRegf64:$a, RRegf64:$b, RRegf64:$c), + def rrr64 : InstPTX<(outs RegF64:$d), + (ins RegF64:$a, RegF64:$b, RegF64:$c), !strconcat(opcstr, ".f64\t$d, $a, $b, $c"), - [(set RRegf64:$d, (opnode2 (opnode1 RRegf64:$a, - RRegf64:$b), - RRegf64:$c))]>; - def rri64 : InstPTX<(outs RRegf64:$d), - (ins RRegf64:$a, RRegf64:$b, f64imm:$c), + [(set RegF64:$d, (opnode2 (opnode1 RegF64:$a, + RegF64:$b), + RegF64:$c))]>; + def rri64 : InstPTX<(outs RegF64:$d), + (ins RegF64:$a, RegF64:$b, f64imm:$c), !strconcat(opcstr, ".f64\t$d, $a, $b, $c"), - [(set RRegf64:$d, (opnode2 (opnode1 RRegf64:$a, - RRegf64:$b), + [(set RegF64:$d, (opnode2 (opnode1 RegF64:$a, + RegF64:$b), fpimm:$c))]>; } multiclass INT3<string opcstr, SDNode opnode> { - def rr16 : InstPTX<(outs RRegu16:$d), - (ins RRegu16:$a, RRegu16:$b), + def rr16 : InstPTX<(outs RegI16:$d), + (ins RegI16:$a, RegI16:$b), !strconcat(opcstr, ".u16\t$d, $a, $b"), - [(set RRegu16:$d, (opnode RRegu16:$a, RRegu16:$b))]>; - def ri16 : InstPTX<(outs RRegu16:$d), - (ins RRegu16:$a, i16imm:$b), + [(set RegI16:$d, (opnode RegI16:$a, RegI16:$b))]>; + def ri16 : InstPTX<(outs RegI16:$d), + (ins RegI16:$a, i16imm:$b), !strconcat(opcstr, ".u16\t$d, $a, $b"), - [(set RRegu16:$d, (opnode RRegu16:$a, imm:$b))]>; - def rr32 : InstPTX<(outs RRegu32:$d), - (ins RRegu32:$a, RRegu32:$b), + [(set RegI16:$d, (opnode RegI16:$a, imm:$b))]>; + def rr32 : InstPTX<(outs RegI32:$d), + (ins RegI32:$a, RegI32:$b), !strconcat(opcstr, ".u32\t$d, $a, $b"), - [(set RRegu32:$d, (opnode RRegu32:$a, RRegu32:$b))]>; - def ri32 : InstPTX<(outs RRegu32:$d), - (ins RRegu32:$a, i32imm:$b), + [(set RegI32:$d, (opnode RegI32:$a, RegI32:$b))]>; + def ri32 : InstPTX<(outs RegI32:$d), + (ins RegI32:$a, i32imm:$b), !strconcat(opcstr, ".u32\t$d, $a, $b"), - [(set RRegu32:$d, (opnode RRegu32:$a, imm:$b))]>; - def rr64 : InstPTX<(outs RRegu64:$d), - (ins RRegu64:$a, RRegu64:$b), + [(set RegI32:$d, (opnode RegI32:$a, imm:$b))]>; + def rr64 : InstPTX<(outs RegI64:$d), + (ins RegI64:$a, RegI64:$b), !strconcat(opcstr, ".u64\t$d, $a, $b"), - [(set RRegu64:$d, (opnode RRegu64:$a, RRegu64:$b))]>; - def ri64 : InstPTX<(outs RRegu64:$d), - (ins RRegu64:$a, i64imm:$b), + [(set RegI64:$d, (opnode RegI64:$a, RegI64:$b))]>; + def ri64 : InstPTX<(outs RegI64:$d), + (ins RegI64:$a, i64imm:$b), !strconcat(opcstr, ".u64\t$d, $a, $b"), - [(set RRegu64:$d, (opnode RRegu64:$a, imm:$b))]>; + [(set RegI64:$d, (opnode RegI64:$a, imm:$b))]>; } multiclass PTX_LOGIC<string opcstr, SDNode opnode> { - def ripreds : InstPTX<(outs Preds:$d), - (ins Preds:$a, i1imm:$b), + def ripreds : InstPTX<(outs RegPred:$d), + (ins RegPred:$a, i1imm:$b), !strconcat(opcstr, ".pred\t$d, $a, $b"), - [(set Preds:$d, (opnode Preds:$a, imm:$b))]>; - def rrpreds : InstPTX<(outs Preds:$d), - (ins Preds:$a, Preds:$b), + [(set RegPred:$d, (opnode RegPred:$a, imm:$b))]>; + def rrpreds : InstPTX<(outs RegPred:$d), + (ins RegPred:$a, RegPred:$b), !strconcat(opcstr, ".pred\t$d, $a, $b"), - [(set Preds:$d, (opnode Preds:$a, Preds:$b))]>; - def rr16 : InstPTX<(outs RRegu16:$d), - (ins RRegu16:$a, RRegu16:$b), + [(set RegPred:$d, (opnode RegPred:$a, RegPred:$b))]>; + def rr16 : InstPTX<(outs RegI16:$d), + (ins RegI16:$a, RegI16:$b), !strconcat(opcstr, ".b16\t$d, $a, $b"), - [(set RRegu16:$d, (opnode RRegu16:$a, RRegu16:$b))]>; - def ri16 : InstPTX<(outs RRegu16:$d), - (ins RRegu16:$a, i16imm:$b), + [(set RegI16:$d, (opnode RegI16:$a, RegI16:$b))]>; + def ri16 : InstPTX<(outs RegI16:$d), + (ins RegI16:$a, i16imm:$b), !strconcat(opcstr, ".b16\t$d, $a, $b"), - [(set RRegu16:$d, (opnode RRegu16:$a, imm:$b))]>; - def rr32 : InstPTX<(outs RRegu32:$d), - (ins RRegu32:$a, RRegu32:$b), + [(set RegI16:$d, (opnode RegI16:$a, imm:$b))]>; + def rr32 : InstPTX<(outs RegI32:$d), + (ins RegI32:$a, RegI32:$b), !strconcat(opcstr, ".b32\t$d, $a, $b"), - [(set RRegu32:$d, (opnode RRegu32:$a, RRegu32:$b))]>; - def ri32 : InstPTX<(outs RRegu32:$d), - (ins RRegu32:$a, i32imm:$b), + [(set RegI32:$d, (opnode RegI32:$a, RegI32:$b))]>; + def ri32 : InstPTX<(outs RegI32:$d), + (ins RegI32:$a, i32imm:$b), !strconcat(opcstr, ".b32\t$d, $a, $b"), - [(set RRegu32:$d, (opnode RRegu32:$a, imm:$b))]>; - def rr64 : InstPTX<(outs RRegu64:$d), - (ins RRegu64:$a, RRegu64:$b), + [(set RegI32:$d, (opnode RegI32:$a, imm:$b))]>; + def rr64 : InstPTX<(outs RegI64:$d), + (ins RegI64:$a, RegI64:$b), !strconcat(opcstr, ".b64\t$d, $a, $b"), - [(set RRegu64:$d, (opnode RRegu64:$a, RRegu64:$b))]>; - def ri64 : InstPTX<(outs RRegu64:$d), - (ins RRegu64:$a, i64imm:$b), + [(set RegI64:$d, (opnode RegI64:$a, RegI64:$b))]>; + def ri64 : InstPTX<(outs RegI64:$d), + (ins RegI64:$a, i64imm:$b), !strconcat(opcstr, ".b64\t$d, $a, $b"), - [(set RRegu64:$d, (opnode RRegu64:$a, imm:$b))]>; + [(set RegI64:$d, (opnode RegI64:$a, imm:$b))]>; } multiclass INT3ntnc<string opcstr, SDNode opnode> { - def rr16 : InstPTX<(outs RRegu16:$d), - (ins RRegu16:$a, RRegu16:$b), + def rr16 : InstPTX<(outs RegI16:$d), + (ins RegI16:$a, RegI16:$b), !strconcat(opcstr, "16\t$d, $a, $b"), - [(set RRegu16:$d, (opnode RRegu16:$a, RRegu16:$b))]>; - def rr32 : InstPTX<(outs RRegu32:$d), - (ins RRegu32:$a, RRegu32:$b), + [(set RegI16:$d, (opnode RegI16:$a, RegI16:$b))]>; + def rr32 : InstPTX<(outs RegI32:$d), + (ins RegI32:$a, RegI32:$b), !strconcat(opcstr, "32\t$d, $a, $b"), - [(set RRegu32:$d, (opnode RRegu32:$a, RRegu32:$b))]>; - def rr64 : InstPTX<(outs RRegu64:$d), - (ins RRegu64:$a, RRegu64:$b), + [(set RegI32:$d, (opnode RegI32:$a, RegI32:$b))]>; + def rr64 : InstPTX<(outs RegI64:$d), + (ins RegI64:$a, RegI64:$b), !strconcat(opcstr, "64\t$d, $a, $b"), - [(set RRegu64:$d, (opnode RRegu64:$a, RRegu64:$b))]>; - def ri16 : InstPTX<(outs RRegu16:$d), - (ins RRegu16:$a, i16imm:$b), + [(set RegI64:$d, (opnode RegI64:$a, RegI64:$b))]>; + def ri16 : InstPTX<(outs RegI16:$d), + (ins RegI16:$a, i16imm:$b), !strconcat(opcstr, "16\t$d, $a, $b"), - [(set RRegu16:$d, (opnode RRegu16:$a, imm:$b))]>; - def ri32 : InstPTX<(outs RRegu32:$d), - (ins RRegu32:$a, i32imm:$b), + [(set RegI16:$d, (opnode RegI16:$a, imm:$b))]>; + def ri32 : InstPTX<(outs RegI32:$d), + (ins RegI32:$a, i32imm:$b), !strconcat(opcstr, "32\t$d, $a, $b"), - [(set RRegu32:$d, (opnode RRegu32:$a, imm:$b))]>; - def ri64 : InstPTX<(outs RRegu64:$d), - (ins RRegu64:$a, i64imm:$b), + [(set RegI32:$d, (opnode RegI32:$a, imm:$b))]>; + def ri64 : InstPTX<(outs RegI64:$d), + (ins RegI64:$a, i64imm:$b), !strconcat(opcstr, "64\t$d, $a, $b"), - [(set RRegu64:$d, (opnode RRegu64:$a, imm:$b))]>; - def ir16 : InstPTX<(outs RRegu16:$d), - (ins i16imm:$a, RRegu16:$b), + [(set RegI64:$d, (opnode RegI64:$a, imm:$b))]>; + def ir16 : InstPTX<(outs RegI16:$d), + (ins i16imm:$a, RegI16:$b), !strconcat(opcstr, "16\t$d, $a, $b"), - [(set RRegu16:$d, (opnode imm:$a, RRegu16:$b))]>; - def ir32 : InstPTX<(outs RRegu32:$d), - (ins i32imm:$a, RRegu32:$b), + [(set RegI16:$d, (opnode imm:$a, RegI16:$b))]>; + def ir32 : InstPTX<(outs RegI32:$d), + (ins i32imm:$a, RegI32:$b), !strconcat(opcstr, "32\t$d, $a, $b"), - [(set RRegu32:$d, (opnode imm:$a, RRegu32:$b))]>; - def ir64 : InstPTX<(outs RRegu64:$d), - (ins i64imm:$a, RRegu64:$b), + [(set RegI32:$d, (opnode imm:$a, RegI32:$b))]>; + def ir64 : InstPTX<(outs RegI64:$d), + (ins i64imm:$a, RegI64:$b), !strconcat(opcstr, "64\t$d, $a, $b"), - [(set RRegu64:$d, (opnode imm:$a, RRegu64:$b))]>; + [(set RegI64:$d, (opnode imm:$a, RegI64:$b))]>; } multiclass PTX_SETP_I<RegisterClass RC, string regclsname, Operand immcls, @@ -362,63 +375,63 @@ multiclass PTX_SETP_I<RegisterClass RC, string regclsname, Operand immcls, // TODO support 5-operand format: p|q, a, b, c def rr - : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b), + : InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b), !strconcat("setp.", cmpstr, ".", regclsname, "\t$p, $a, $b"), - [(set Preds:$p, (setcc RC:$a, RC:$b, cmp))]>; + [(set RegPred:$p, (setcc RC:$a, RC:$b, cmp))]>; def ri - : InstPTX<(outs Preds:$p), (ins RC:$a, immcls:$b), + : InstPTX<(outs RegPred:$p), (ins RC:$a, immcls:$b), !strconcat("setp.", cmpstr, ".", regclsname, "\t$p, $a, $b"), - [(set Preds:$p, (setcc RC:$a, imm:$b, cmp))]>; + [(set RegPred:$p, (setcc RC:$a, imm:$b, cmp))]>; def rr_and_r - : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c), !strconcat("setp.", cmpstr, ".and.", regclsname, "\t$p, $a, $b, $c"), - [(set Preds:$p, (and (setcc RC:$a, RC:$b, cmp), Preds:$c))]>; + [(set RegPred:$p, (and (setcc RC:$a, RC:$b, cmp), RegPred:$c))]>; def ri_and_r - : InstPTX<(outs Preds:$p), (ins RC:$a, immcls:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, immcls:$b, RegPred:$c), !strconcat("setp.", cmpstr, ".and.", regclsname, "\t$p, $a, $b, $c"), - [(set Preds:$p, (and (setcc RC:$a, imm:$b, cmp), Preds:$c))]>; + [(set RegPred:$p, (and (setcc RC:$a, imm:$b, cmp), RegPred:$c))]>; def rr_or_r - : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c), !strconcat("setp.", cmpstr, ".or.", regclsname, "\t$p, $a, $b, $c"), - [(set Preds:$p, (or (setcc RC:$a, RC:$b, cmp), Preds:$c))]>; + [(set RegPred:$p, (or (setcc RC:$a, RC:$b, cmp), RegPred:$c))]>; def ri_or_r - : InstPTX<(outs Preds:$p), (ins RC:$a, immcls:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, immcls:$b, RegPred:$c), !strconcat("setp.", cmpstr, ".or.", regclsname, "\t$p, $a, $b, $c"), - [(set Preds:$p, (or (setcc RC:$a, imm:$b, cmp), Preds:$c))]>; + [(set RegPred:$p, (or (setcc RC:$a, imm:$b, cmp), RegPred:$c))]>; def rr_xor_r - : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c), !strconcat("setp.", cmpstr, ".xor.", regclsname, "\t$p, $a, $b, $c"), - [(set Preds:$p, (xor (setcc RC:$a, RC:$b, cmp), Preds:$c))]>; + [(set RegPred:$p, (xor (setcc RC:$a, RC:$b, cmp), RegPred:$c))]>; def ri_xor_r - : InstPTX<(outs Preds:$p), (ins RC:$a, immcls:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, immcls:$b, RegPred:$c), !strconcat("setp.", cmpstr, ".xor.", regclsname, "\t$p, $a, $b, $c"), - [(set Preds:$p, (xor (setcc RC:$a, imm:$b, cmp), Preds:$c))]>; + [(set RegPred:$p, (xor (setcc RC:$a, imm:$b, cmp), RegPred:$c))]>; def rr_and_not_r - : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c), !strconcat("setp.", cmpstr, ".and.", regclsname, "\t$p, $a, $b, !$c"), - [(set Preds:$p, (and (setcc RC:$a, RC:$b, cmp), (not Preds:$c)))]>; + [(set RegPred:$p, (and (setcc RC:$a, RC:$b, cmp), (not RegPred:$c)))]>; def ri_and_not_r - : InstPTX<(outs Preds:$p), (ins RC:$a, immcls:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, immcls:$b, RegPred:$c), !strconcat("setp.", cmpstr, ".and.", regclsname, "\t$p, $a, $b, !$c"), - [(set Preds:$p, (and (setcc RC:$a, imm:$b, cmp), (not Preds:$c)))]>; + [(set RegPred:$p, (and (setcc RC:$a, imm:$b, cmp), (not RegPred:$c)))]>; def rr_or_not_r - : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c), !strconcat("setp.", cmpstr, ".or.", regclsname, "\t$p, $a, $b, !$c"), - [(set Preds:$p, (or (setcc RC:$a, RC:$b, cmp), (not Preds:$c)))]>; + [(set RegPred:$p, (or (setcc RC:$a, RC:$b, cmp), (not RegPred:$c)))]>; def ri_or_not_r - : InstPTX<(outs Preds:$p), (ins RC:$a, immcls:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, immcls:$b, RegPred:$c), !strconcat("setp.", cmpstr, ".or.", regclsname, "\t$p, $a, $b, !$c"), - [(set Preds:$p, (or (setcc RC:$a, imm:$b, cmp), (not Preds:$c)))]>; + [(set RegPred:$p, (or (setcc RC:$a, imm:$b, cmp), (not RegPred:$c)))]>; def rr_xor_not_r - : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c), !strconcat("setp.", cmpstr, ".xor.", regclsname, "\t$p, $a, $b, !$c"), - [(set Preds:$p, (xor (setcc RC:$a, RC:$b, cmp), (not Preds:$c)))]>; + [(set RegPred:$p, (xor (setcc RC:$a, RC:$b, cmp), (not RegPred:$c)))]>; def ri_xor_not_r - : InstPTX<(outs Preds:$p), (ins RC:$a, immcls:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, immcls:$b, RegPred:$c), !strconcat("setp.", cmpstr, ".xor.", regclsname, "\t$p, $a, $b, !$c"), - [(set Preds:$p, (xor (setcc RC:$a, imm:$b, cmp), (not Preds:$c)))]>; + [(set RegPred:$p, (xor (setcc RC:$a, imm:$b, cmp), (not RegPred:$c)))]>; } multiclass PTX_SETP_FP<RegisterClass RC, string regclsname, @@ -426,74 +439,74 @@ multiclass PTX_SETP_FP<RegisterClass RC, string regclsname, // TODO support 5-operand format: p|q, a, b, c def rr_u - : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b), + : InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b), !strconcat("setp.", cmpstr, "u.", regclsname, "\t$p, $a, $b"), - [(set Preds:$p, (setcc RC:$a, RC:$b, ucmp))]>; + [(set RegPred:$p, (setcc RC:$a, RC:$b, ucmp))]>; def rr_o - : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b), + : InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b), !strconcat("setp.", cmpstr, ".", regclsname, "\t$p, $a, $b"), - [(set Preds:$p, (setcc RC:$a, RC:$b, ocmp))]>; + [(set RegPred:$p, (setcc RC:$a, RC:$b, ocmp))]>; def rr_and_r_u - : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c), !strconcat("setp.", cmpstr, "u.and.", regclsname, "\t$p, $a, $b, $c"), - [(set Preds:$p, (and (setcc RC:$a, RC:$b, ucmp), Preds:$c))]>; + [(set RegPred:$p, (and (setcc RC:$a, RC:$b, ucmp), RegPred:$c))]>; def rr_and_r_o - : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c), !strconcat("setp.", cmpstr, ".and.", regclsname, "\t$p, $a, $b, $c"), - [(set Preds:$p, (and (setcc RC:$a, RC:$b, ocmp), Preds:$c))]>; + [(set RegPred:$p, (and (setcc RC:$a, RC:$b, ocmp), RegPred:$c))]>; def rr_or_r_u - : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c), !strconcat("setp.", cmpstr, "u.or.", regclsname, "\t$p, $a, $b, $c"), - [(set Preds:$p, (or (setcc RC:$a, RC:$b, ucmp), Preds:$c))]>; + [(set RegPred:$p, (or (setcc RC:$a, RC:$b, ucmp), RegPred:$c))]>; def rr_or_r_o - : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c), !strconcat("setp.", cmpstr, ".or.", regclsname, "\t$p, $a, $b, $c"), - [(set Preds:$p, (or (setcc RC:$a, RC:$b, ocmp), Preds:$c))]>; + [(set RegPred:$p, (or (setcc RC:$a, RC:$b, ocmp), RegPred:$c))]>; def rr_xor_r_u - : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c), !strconcat("setp.", cmpstr, "u.xor.", regclsname, "\t$p, $a, $b, $c"), - [(set Preds:$p, (xor (setcc RC:$a, RC:$b, ucmp), Preds:$c))]>; + [(set RegPred:$p, (xor (setcc RC:$a, RC:$b, ucmp), RegPred:$c))]>; def rr_xor_r_o - : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c), !strconcat("setp.", cmpstr, ".xor.", regclsname, "\t$p, $a, $b, $c"), - [(set Preds:$p, (xor (setcc RC:$a, RC:$b, ocmp), Preds:$c))]>; + [(set RegPred:$p, (xor (setcc RC:$a, RC:$b, ocmp), RegPred:$c))]>; def rr_and_not_r_u - : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c), !strconcat("setp.", cmpstr, "u.and.", regclsname, "\t$p, $a, $b, !$c"), - [(set Preds:$p, (and (setcc RC:$a, RC:$b, ucmp), (not Preds:$c)))]>; + [(set RegPred:$p, (and (setcc RC:$a, RC:$b, ucmp), (not RegPred:$c)))]>; def rr_and_not_r_o - : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c), !strconcat("setp.", cmpstr, ".and.", regclsname, "\t$p, $a, $b, !$c"), - [(set Preds:$p, (and (setcc RC:$a, RC:$b, ocmp), (not Preds:$c)))]>; + [(set RegPred:$p, (and (setcc RC:$a, RC:$b, ocmp), (not RegPred:$c)))]>; def rr_or_not_r_u - : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c), !strconcat("setp.", cmpstr, "u.or.", regclsname, "\t$p, $a, $b, !$c"), - [(set Preds:$p, (or (setcc RC:$a, RC:$b, ucmp), (not Preds:$c)))]>; + [(set RegPred:$p, (or (setcc RC:$a, RC:$b, ucmp), (not RegPred:$c)))]>; def rr_or_not_r_o - : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c), !strconcat("setp.", cmpstr, ".or.", regclsname, "\t$p, $a, $b, !$c"), - [(set Preds:$p, (or (setcc RC:$a, RC:$b, ocmp), (not Preds:$c)))]>; + [(set RegPred:$p, (or (setcc RC:$a, RC:$b, ocmp), (not RegPred:$c)))]>; def rr_xor_not_r_u - : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c), !strconcat("setp.", cmpstr, "u.xor.", regclsname, "\t$p, $a, $b, !$c"), - [(set Preds:$p, (xor (setcc RC:$a, RC:$b, ucmp), (not Preds:$c)))]>; + [(set RegPred:$p, (xor (setcc RC:$a, RC:$b, ucmp), (not RegPred:$c)))]>; def rr_xor_not_r_o - : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + : InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c), !strconcat("setp.", cmpstr, ".xor.", regclsname, "\t$p, $a, $b, !$c"), - [(set Preds:$p, (xor (setcc RC:$a, RC:$b, ocmp), (not Preds:$c)))]>; + [(set RegPred:$p, (xor (setcc RC:$a, RC:$b, ocmp), (not RegPred:$c)))]>; } multiclass PTX_SELP<RegisterClass RC, string regclsname> { def rr - : InstPTX<(outs RC:$r), (ins Preds:$a, RC:$b, RC:$c), + : InstPTX<(outs RC:$r), (ins RegPred:$a, RC:$b, RC:$c), !strconcat("selp.", regclsname, "\t$r, $b, $c, $a"), - [(set RC:$r, (select Preds:$a, RC:$b, RC:$c))]>; + [(set RC:$r, (select RegPred:$a, RC:$b, RC:$c))]>; } multiclass PTX_LD<string opstr, string typestr, RegisterClass RC, PatFrag pat_load> { @@ -524,11 +537,11 @@ multiclass PTX_LD<string opstr, string typestr, RegisterClass RC, PatFrag pat_lo } multiclass PTX_LD_ALL<string opstr, PatFrag pat_load> { - defm u16 : PTX_LD<opstr, ".u16", RRegu16, pat_load>; - defm u32 : PTX_LD<opstr, ".u32", RRegu32, pat_load>; - defm u64 : PTX_LD<opstr, ".u64", RRegu64, pat_load>; - defm f32 : PTX_LD<opstr, ".f32", RRegf32, pat_load>; - defm f64 : PTX_LD<opstr, ".f64", RRegf64, pat_load>; + defm u16 : PTX_LD<opstr, ".u16", RegI16, pat_load>; + defm u32 : PTX_LD<opstr, ".u32", RegI32, pat_load>; + defm u64 : PTX_LD<opstr, ".u64", RegI64, pat_load>; + defm f32 : PTX_LD<opstr, ".f32", RegF32, pat_load>; + defm f64 : PTX_LD<opstr, ".f64", RegF64, pat_load>; } multiclass PTX_ST<string opstr, string typestr, RegisterClass RC, PatFrag pat_store> { @@ -559,11 +572,11 @@ multiclass PTX_ST<string opstr, string typestr, RegisterClass RC, PatFrag pat_st } multiclass PTX_ST_ALL<string opstr, PatFrag pat_store> { - defm u16 : PTX_ST<opstr, ".u16", RRegu16, pat_store>; - defm u32 : PTX_ST<opstr, ".u32", RRegu32, pat_store>; - defm u64 : PTX_ST<opstr, ".u64", RRegu64, pat_store>; - defm f32 : PTX_ST<opstr, ".f32", RRegf32, pat_store>; - defm f64 : PTX_ST<opstr, ".f64", RRegf64, pat_store>; + defm u16 : PTX_ST<opstr, ".u16", RegI16, pat_store>; + defm u32 : PTX_ST<opstr, ".u32", RegI32, pat_store>; + defm u64 : PTX_ST<opstr, ".u64", RegI64, pat_store>; + defm f32 : PTX_ST<opstr, ".f32", RegF32, pat_store>; + defm f64 : PTX_ST<opstr, ".f64", RegF64, pat_store>; } //===----------------------------------------------------------------------===// @@ -584,44 +597,59 @@ defm REM : INT3<"rem", urem>; defm FNEG : PTX_FLOAT_2OP<"neg", fneg>; // Standard Binary Operations -defm FADD : PTX_FLOAT_3OP<"add", fadd>; -defm FSUB : PTX_FLOAT_3OP<"sub", fsub>; -defm FMUL : PTX_FLOAT_3OP<"mul", fmul>; - -// TODO: Allow user selection of rounding modes for fdiv. -// For division, we need to have f32 and f64 differently. -// For f32, we just always use .approx since it is supported on all hardware -// for PTX 1.4+, which is our minimum target. -def FDIVrr32 : InstPTX<(outs RRegf32:$d), - (ins RRegf32:$a, RRegf32:$b), - "div.approx.f32\t$d, $a, $b", - [(set RRegf32:$d, (fdiv RRegf32:$a, RRegf32:$b))]>; -def FDIVri32 : InstPTX<(outs RRegf32:$d), - (ins RRegf32:$a, f32imm:$b), - "div.approx.f32\t$d, $a, $b", - [(set RRegf32:$d, (fdiv RRegf32:$a, fpimm:$b))]>; - -// For f64, we must specify a rounding for sm 1.3+ but *not* for sm 1.0. -def FDIVrr64SM13 : InstPTX<(outs RRegf64:$d), - (ins RRegf64:$a, RRegf64:$b), +defm FADD : PTX_FLOAT_3OP<"add.rn", fadd>; +defm FSUB : PTX_FLOAT_3OP<"sub.rn", fsub>; +defm FMUL : PTX_FLOAT_3OP<"mul.rn", fmul>; + +// For floating-point division: +// SM_13+ defaults to .rn for f32 and f64, +// SM10 must *not* provide a rounding + +// TODO: +// - Allow user selection of rounding modes for fdiv +// - Add support for -prec-div=false (.approx) + +def FDIVrr32SM13 : InstPTX<(outs RegF32:$d), + (ins RegF32:$a, RegF32:$b), + "div.rn.f32\t$d, $a, $b", + [(set RegF32:$d, (fdiv RegF32:$a, RegF32:$b))]>, + Requires<[FDivNeedsRoundingMode]>; +def FDIVri32SM13 : InstPTX<(outs RegF32:$d), + (ins RegF32:$a, f32imm:$b), + "div.rn.f32\t$d, $a, $b", + [(set RegF32:$d, (fdiv RegF32:$a, fpimm:$b))]>, + Requires<[FDivNeedsRoundingMode]>; +def FDIVrr32SM10 : InstPTX<(outs RegF32:$d), + (ins RegF32:$a, RegF32:$b), + "div.f32\t$d, $a, $b", + [(set RegF32:$d, (fdiv RegF32:$a, RegF32:$b))]>, + Requires<[FDivNoRoundingMode]>; +def FDIVri32SM10 : InstPTX<(outs RegF32:$d), + (ins RegF32:$a, f32imm:$b), + "div.f32\t$d, $a, $b", + [(set RegF32:$d, (fdiv RegF32:$a, fpimm:$b))]>, + Requires<[FDivNoRoundingMode]>; + +def FDIVrr64SM13 : InstPTX<(outs RegF64:$d), + (ins RegF64:$a, RegF64:$b), "div.rn.f64\t$d, $a, $b", - [(set RRegf64:$d, (fdiv RRegf64:$a, RRegf64:$b))]>, - Requires<[SupportsSM13]>; -def FDIVri64SM13 : InstPTX<(outs RRegf64:$d), - (ins RRegf64:$a, f64imm:$b), + [(set RegF64:$d, (fdiv RegF64:$a, RegF64:$b))]>, + Requires<[FDivNeedsRoundingMode]>; +def FDIVri64SM13 : InstPTX<(outs RegF64:$d), + (ins RegF64:$a, f64imm:$b), "div.rn.f64\t$d, $a, $b", - [(set RRegf64:$d, (fdiv RRegf64:$a, fpimm:$b))]>, - Requires<[SupportsSM13]>; -def FDIVrr64SM10 : InstPTX<(outs RRegf64:$d), - (ins RRegf64:$a, RRegf64:$b), + [(set RegF64:$d, (fdiv RegF64:$a, fpimm:$b))]>, + Requires<[FDivNeedsRoundingMode]>; +def FDIVrr64SM10 : InstPTX<(outs RegF64:$d), + (ins RegF64:$a, RegF64:$b), "div.f64\t$d, $a, $b", - [(set RRegf64:$d, (fdiv RRegf64:$a, RRegf64:$b))]>, - Requires<[DoesNotSupportSM13]>; -def FDIVri64SM10 : InstPTX<(outs RRegf64:$d), - (ins RRegf64:$a, f64imm:$b), + [(set RegF64:$d, (fdiv RegF64:$a, RegF64:$b))]>, + Requires<[FDivNoRoundingMode]>; +def FDIVri64SM10 : InstPTX<(outs RegF64:$d), + (ins RegF64:$a, f64imm:$b), "div.f64\t$d, $a, $b", - [(set RRegf64:$d, (fdiv RRegf64:$a, fpimm:$b))]>, - Requires<[DoesNotSupportSM13]>; + [(set RegF64:$d, (fdiv RegF64:$a, fpimm:$b))]>, + Requires<[FDivNoRoundingMode]>; @@ -633,40 +661,42 @@ def FDIVri64SM10 : InstPTX<(outs RRegf64:$d), // In the short term, mad is supported on all PTX versions and we use a // default rounding mode no matter what shader model or PTX version. // TODO: Allow the rounding mode to be selectable through llc. -defm FMADSM13 : PTX_FLOAT_4OP<"mad.rn", fmul, fadd>, Requires<[SupportsSM13, SupportsFMA]>; -defm FMAD : PTX_FLOAT_4OP<"mad", fmul, fadd>, Requires<[DoesNotSupportSM13, SupportsFMA]>; +defm FMADSM13 : PTX_FLOAT_4OP<"mad.rn", fmul, fadd>, + Requires<[FMadNeedsRoundingMode, SupportsFMA]>; +defm FMAD : PTX_FLOAT_4OP<"mad", fmul, fadd>, + Requires<[FMadNoRoundingMode, SupportsFMA]>; ///===- Floating-Point Intrinsic Instructions -----------------------------===// -def FSQRT32 : InstPTX<(outs RRegf32:$d), - (ins RRegf32:$a), +def FSQRT32 : InstPTX<(outs RegF32:$d), + (ins RegF32:$a), "sqrt.rn.f32\t$d, $a", - [(set RRegf32:$d, (fsqrt RRegf32:$a))]>; + [(set RegF32:$d, (fsqrt RegF32:$a))]>; -def FSQRT64 : InstPTX<(outs RRegf64:$d), - (ins RRegf64:$a), +def FSQRT64 : InstPTX<(outs RegF64:$d), + (ins RegF64:$a), "sqrt.rn.f64\t$d, $a", - [(set RRegf64:$d, (fsqrt RRegf64:$a))]>; + [(set RegF64:$d, (fsqrt RegF64:$a))]>; -def FSIN32 : InstPTX<(outs RRegf32:$d), - (ins RRegf32:$a), +def FSIN32 : InstPTX<(outs RegF32:$d), + (ins RegF32:$a), "sin.approx.f32\t$d, $a", - [(set RRegf32:$d, (fsin RRegf32:$a))]>; + [(set RegF32:$d, (fsin RegF32:$a))]>; -def FSIN64 : InstPTX<(outs RRegf64:$d), - (ins RRegf64:$a), +def FSIN64 : InstPTX<(outs RegF64:$d), + (ins RegF64:$a), "sin.approx.f64\t$d, $a", - [(set RRegf64:$d, (fsin RRegf64:$a))]>; + [(set RegF64:$d, (fsin RegF64:$a))]>; -def FCOS32 : InstPTX<(outs RRegf32:$d), - (ins RRegf32:$a), +def FCOS32 : InstPTX<(outs RegF32:$d), + (ins RegF32:$a), "cos.approx.f32\t$d, $a", - [(set RRegf32:$d, (fcos RRegf32:$a))]>; + [(set RegF32:$d, (fcos RegF32:$a))]>; -def FCOS64 : InstPTX<(outs RRegf64:$d), - (ins RRegf64:$a), +def FCOS64 : InstPTX<(outs RegF64:$d), + (ins RegF64:$a), "cos.approx.f64\t$d, $a", - [(set RRegf64:$d, (fcos RRegf64:$a))]>; + [(set RegF64:$d, (fcos RegF64:$a))]>; ///===- Comparison and Selection Instructions -----------------------------===// @@ -675,56 +705,68 @@ def FCOS64 : InstPTX<(outs RRegf64:$d), // Compare u16 -defm SETPEQu16 : PTX_SETP_I<RRegu16, "u16", i16imm, SETEQ, "eq">; -defm SETPNEu16 : PTX_SETP_I<RRegu16, "u16", i16imm, SETNE, "ne">; -defm SETPLTu16 : PTX_SETP_I<RRegu16, "u16", i16imm, SETULT, "lt">; -defm SETPLEu16 : PTX_SETP_I<RRegu16, "u16", i16imm, SETULE, "le">; -defm SETPGTu16 : PTX_SETP_I<RRegu16, "u16", i16imm, SETUGT, "gt">; -defm SETPGEu16 : PTX_SETP_I<RRegu16, "u16", i16imm, SETUGE, "ge">; +defm SETPEQu16 : PTX_SETP_I<RegI16, "u16", i16imm, SETEQ, "eq">; +defm SETPNEu16 : PTX_SETP_I<RegI16, "u16", i16imm, SETNE, "ne">; +defm SETPLTu16 : PTX_SETP_I<RegI16, "u16", i16imm, SETULT, "lt">; +defm SETPLEu16 : PTX_SETP_I<RegI16, "u16", i16imm, SETULE, "le">; +defm SETPGTu16 : PTX_SETP_I<RegI16, "u16", i16imm, SETUGT, "gt">; +defm SETPGEu16 : PTX_SETP_I<RegI16, "u16", i16imm, SETUGE, "ge">; +defm SETPLTs16 : PTX_SETP_I<RegI16, "s16", i16imm, SETLT, "lt">; +defm SETPLEs16 : PTX_SETP_I<RegI16, "s16", i16imm, SETLE, "le">; +defm SETPGTs16 : PTX_SETP_I<RegI16, "s16", i16imm, SETGT, "gt">; +defm SETPGEs16 : PTX_SETP_I<RegI16, "s16", i16imm, SETGE, "ge">; // Compare u32 -defm SETPEQu32 : PTX_SETP_I<RRegu32, "u32", i32imm, SETEQ, "eq">; -defm SETPNEu32 : PTX_SETP_I<RRegu32, "u32", i32imm, SETNE, "ne">; -defm SETPLTu32 : PTX_SETP_I<RRegu32, "u32", i32imm, SETULT, "lt">; -defm SETPLEu32 : PTX_SETP_I<RRegu32, "u32", i32imm, SETULE, "le">; -defm SETPGTu32 : PTX_SETP_I<RRegu32, "u32", i32imm, SETUGT, "gt">; -defm SETPGEu32 : PTX_SETP_I<RRegu32, "u32", i32imm, SETUGE, "ge">; +defm SETPEQu32 : PTX_SETP_I<RegI32, "u32", i32imm, SETEQ, "eq">; +defm SETPNEu32 : PTX_SETP_I<RegI32, "u32", i32imm, SETNE, "ne">; +defm SETPLTu32 : PTX_SETP_I<RegI32, "u32", i32imm, SETULT, "lt">; +defm SETPLEu32 : PTX_SETP_I<RegI32, "u32", i32imm, SETULE, "le">; +defm SETPGTu32 : PTX_SETP_I<RegI32, "u32", i32imm, SETUGT, "gt">; +defm SETPGEu32 : PTX_SETP_I<RegI32, "u32", i32imm, SETUGE, "ge">; +defm SETPLTs32 : PTX_SETP_I<RegI32, "s32", i32imm, SETLT, "lt">; +defm SETPLEs32 : PTX_SETP_I<RegI32, "s32", i32imm, SETLE, "le">; +defm SETPGTs32 : PTX_SETP_I<RegI32, "s32", i32imm, SETGT, "gt">; +defm SETPGEs32 : PTX_SETP_I<RegI32, "s32", i32imm, SETGE, "ge">; // Compare u64 -defm SETPEQu64 : PTX_SETP_I<RRegu64, "u64", i64imm, SETEQ, "eq">; -defm SETPNEu64 : PTX_SETP_I<RRegu64, "u64", i64imm, SETNE, "ne">; -defm SETPLTu64 : PTX_SETP_I<RRegu64, "u64", i64imm, SETULT, "lt">; -defm SETPLEu64 : PTX_SETP_I<RRegu64, "u64", i64imm, SETULE, "le">; -defm SETPGTu64 : PTX_SETP_I<RRegu64, "u64", i64imm, SETUGT, "gt">; -defm SETPGEu64 : PTX_SETP_I<RRegu64, "u64", i64imm, SETUGE, "ge">; +defm SETPEQu64 : PTX_SETP_I<RegI64, "u64", i64imm, SETEQ, "eq">; +defm SETPNEu64 : PTX_SETP_I<RegI64, "u64", i64imm, SETNE, "ne">; +defm SETPLTu64 : PTX_SETP_I<RegI64, "u64", i64imm, SETULT, "lt">; +defm SETPLEu64 : PTX_SETP_I<RegI64, "u64", i64imm, SETULE, "le">; +defm SETPGTu64 : PTX_SETP_I<RegI64, "u64", i64imm, SETUGT, "gt">; +defm SETPGEu64 : PTX_SETP_I<RegI64, "u64", i64imm, SETUGE, "ge">; +defm SETPLTs64 : PTX_SETP_I<RegI64, "s64", i64imm, SETLT, "lt">; +defm SETPLEs64 : PTX_SETP_I<RegI64, "s64", i64imm, SETLE, "le">; +defm SETPGTs64 : PTX_SETP_I<RegI64, "s64", i64imm, SETGT, "gt">; +defm SETPGEs64 : PTX_SETP_I<RegI64, "s64", i64imm, SETGE, "ge">; // Compare f32 -defm SETPEQf32 : PTX_SETP_FP<RRegf32, "f32", SETUEQ, SETOEQ, "eq">; -defm SETPNEf32 : PTX_SETP_FP<RRegf32, "f32", SETUNE, SETONE, "ne">; -defm SETPLTf32 : PTX_SETP_FP<RRegf32, "f32", SETULT, SETOLT, "lt">; -defm SETPLEf32 : PTX_SETP_FP<RRegf32, "f32", SETULE, SETOLE, "le">; -defm SETPGTf32 : PTX_SETP_FP<RRegf32, "f32", SETUGT, SETOGT, "gt">; -defm SETPGEf32 : PTX_SETP_FP<RRegf32, "f32", SETUGE, SETOGE, "ge">; +defm SETPEQf32 : PTX_SETP_FP<RegF32, "f32", SETUEQ, SETOEQ, "eq">; +defm SETPNEf32 : PTX_SETP_FP<RegF32, "f32", SETUNE, SETONE, "ne">; +defm SETPLTf32 : PTX_SETP_FP<RegF32, "f32", SETULT, SETOLT, "lt">; +defm SETPLEf32 : PTX_SETP_FP<RegF32, "f32", SETULE, SETOLE, "le">; +defm SETPGTf32 : PTX_SETP_FP<RegF32, "f32", SETUGT, SETOGT, "gt">; +defm SETPGEf32 : PTX_SETP_FP<RegF32, "f32", SETUGE, SETOGE, "ge">; // Compare f64 -defm SETPEQf64 : PTX_SETP_FP<RRegf64, "f64", SETUEQ, SETOEQ, "eq">; -defm SETPNEf64 : PTX_SETP_FP<RRegf64, "f64", SETUNE, SETONE, "ne">; -defm SETPLTf64 : PTX_SETP_FP<RRegf64, "f64", SETULT, SETOLT, "lt">; -defm SETPLEf64 : PTX_SETP_FP<RRegf64, "f64", SETULE, SETOLE, "le">; -defm SETPGTf64 : PTX_SETP_FP<RRegf64, "f64", SETUGT, SETOGT, "gt">; -defm SETPGEf64 : PTX_SETP_FP<RRegf64, "f64", SETUGE, SETOGE, "ge">; +defm SETPEQf64 : PTX_SETP_FP<RegF64, "f64", SETUEQ, SETOEQ, "eq">; +defm SETPNEf64 : PTX_SETP_FP<RegF64, "f64", SETUNE, SETONE, "ne">; +defm SETPLTf64 : PTX_SETP_FP<RegF64, "f64", SETULT, SETOLT, "lt">; +defm SETPLEf64 : PTX_SETP_FP<RegF64, "f64", SETULE, SETOLE, "le">; +defm SETPGTf64 : PTX_SETP_FP<RegF64, "f64", SETUGT, SETOGT, "gt">; +defm SETPGEf64 : PTX_SETP_FP<RegF64, "f64", SETUGE, SETOGE, "ge">; // .selp -defm PTX_SELPu16 : PTX_SELP<RRegu16, "u16">; -defm PTX_SELPu32 : PTX_SELP<RRegu32, "u32">; -defm PTX_SELPu64 : PTX_SELP<RRegu64, "u64">; -defm PTX_SELPf32 : PTX_SELP<RRegf32, "f32">; -defm PTX_SELPf64 : PTX_SELP<RRegf64, "f64">; +defm PTX_SELPu16 : PTX_SELP<RegI16, "u16">; +defm PTX_SELPu32 : PTX_SELP<RegI32, "u32">; +defm PTX_SELPu64 : PTX_SELP<RegI64, "u64">; +defm PTX_SELPf32 : PTX_SELP<RegF32, "f32">; +defm PTX_SELPf64 : PTX_SELP<RegF64, "f64">; ///===- Logic and Shift Instructions --------------------------------------===// @@ -740,47 +782,47 @@ defm XOR : PTX_LOGIC<"xor", xor>; let neverHasSideEffects = 1 in { def MOVPREDrr - : InstPTX<(outs Preds:$d), (ins Preds:$a), "mov.pred\t$d, $a", []>; + : InstPTX<(outs RegPred:$d), (ins RegPred:$a), "mov.pred\t$d, $a", []>; def MOVU16rr - : InstPTX<(outs RRegu16:$d), (ins RRegu16:$a), "mov.u16\t$d, $a", []>; + : InstPTX<(outs RegI16:$d), (ins RegI16:$a), "mov.u16\t$d, $a", []>; def MOVU32rr - : InstPTX<(outs RRegu32:$d), (ins RRegu32:$a), "mov.u32\t$d, $a", []>; + : InstPTX<(outs RegI32:$d), (ins RegI32:$a), "mov.u32\t$d, $a", []>; def MOVU64rr - : InstPTX<(outs RRegu64:$d), (ins RRegu64:$a), "mov.u64\t$d, $a", []>; + : InstPTX<(outs RegI64:$d), (ins RegI64:$a), "mov.u64\t$d, $a", []>; def MOVF32rr - : InstPTX<(outs RRegf32:$d), (ins RRegf32:$a), "mov.f32\t$d, $a", []>; + : InstPTX<(outs RegF32:$d), (ins RegF32:$a), "mov.f32\t$d, $a", []>; def MOVF64rr - : InstPTX<(outs RRegf64:$d), (ins RRegf64:$a), "mov.f64\t$d, $a", []>; + : InstPTX<(outs RegF64:$d), (ins RegF64:$a), "mov.f64\t$d, $a", []>; } let isReMaterializable = 1, isAsCheapAsAMove = 1 in { def MOVPREDri - : InstPTX<(outs Preds:$d), (ins i1imm:$a), "mov.pred\t$d, $a", - [(set Preds:$d, imm:$a)]>; + : InstPTX<(outs RegPred:$d), (ins i1imm:$a), "mov.pred\t$d, $a", + [(set RegPred:$d, imm:$a)]>; def MOVU16ri - : InstPTX<(outs RRegu16:$d), (ins i16imm:$a), "mov.u16\t$d, $a", - [(set RRegu16:$d, imm:$a)]>; + : InstPTX<(outs RegI16:$d), (ins i16imm:$a), "mov.u16\t$d, $a", + [(set RegI16:$d, imm:$a)]>; def MOVU32ri - : InstPTX<(outs RRegu32:$d), (ins i32imm:$a), "mov.u32\t$d, $a", - [(set RRegu32:$d, imm:$a)]>; + : InstPTX<(outs RegI32:$d), (ins i32imm:$a), "mov.u32\t$d, $a", + [(set RegI32:$d, imm:$a)]>; def MOVU64ri - : InstPTX<(outs RRegu64:$d), (ins i64imm:$a), "mov.u64\t$d, $a", - [(set RRegu64:$d, imm:$a)]>; + : InstPTX<(outs RegI64:$d), (ins i64imm:$a), "mov.u64\t$d, $a", + [(set RegI64:$d, imm:$a)]>; def MOVF32ri - : InstPTX<(outs RRegf32:$d), (ins f32imm:$a), "mov.f32\t$d, $a", - [(set RRegf32:$d, fpimm:$a)]>; + : InstPTX<(outs RegF32:$d), (ins f32imm:$a), "mov.f32\t$d, $a", + [(set RegF32:$d, fpimm:$a)]>; def MOVF64ri - : InstPTX<(outs RRegf64:$d), (ins f64imm:$a), "mov.f64\t$d, $a", - [(set RRegf64:$d, fpimm:$a)]>; + : InstPTX<(outs RegF64:$d), (ins f64imm:$a), "mov.f64\t$d, $a", + [(set RegF64:$d, fpimm:$a)]>; } let isReMaterializable = 1, isAsCheapAsAMove = 1 in { def MOVaddr32 - : InstPTX<(outs RRegu32:$d), (ins i32imm:$a), "mov.u32\t$d, $a", - [(set RRegu32:$d, (PTXcopyaddress tglobaladdr:$a))]>; + : InstPTX<(outs RegI32:$d), (ins i32imm:$a), "mov.u32\t$d, $a", + [(set RegI32:$d, (PTXcopyaddress tglobaladdr:$a))]>; def MOVaddr64 - : InstPTX<(outs RRegu64:$d), (ins i64imm:$a), "mov.u64\t$d, $a", - [(set RRegu64:$d, (PTXcopyaddress tglobaladdr:$a))]>; + : InstPTX<(outs RegI64:$d), (ins i64imm:$a), "mov.u64\t$d, $a", + [(set RegI64:$d, (PTXcopyaddress tglobaladdr:$a))]>; } // Loads @@ -789,17 +831,48 @@ defm LDc : PTX_LD_ALL<"ld.const", load_constant>; defm LDl : PTX_LD_ALL<"ld.local", load_local>; defm LDs : PTX_LD_ALL<"ld.shared", load_shared>; -// This is a special instruction that is manually inserted for kernel parameters -def LDpiU16 : InstPTX<(outs RRegu16:$d), (ins MEMpi:$a), - "ld.param.u16\t$d, [$a]", []>; -def LDpiU32 : InstPTX<(outs RRegu32:$d), (ins MEMpi:$a), - "ld.param.u32\t$d, [$a]", []>; -def LDpiU64 : InstPTX<(outs RRegu64:$d), (ins MEMpi:$a), - "ld.param.u64\t$d, [$a]", []>; -def LDpiF32 : InstPTX<(outs RRegf32:$d), (ins MEMpi:$a), - "ld.param.f32\t$d, [$a]", []>; -def LDpiF64 : InstPTX<(outs RRegf64:$d), (ins MEMpi:$a), - "ld.param.f64\t$d, [$a]", []>; +// These instructions are used to load/store from the .param space for +// device and kernel parameters + +let hasSideEffects = 1 in { + def LDpiPred : InstPTX<(outs RegPred:$d), (ins MEMpi:$a), + "ld.param.pred\t$d, [$a]", + [(set RegPred:$d, (PTXloadparam timm:$a))]>; + def LDpiU16 : InstPTX<(outs RegI16:$d), (ins MEMpi:$a), + "ld.param.u16\t$d, [$a]", + [(set RegI16:$d, (PTXloadparam timm:$a))]>; + def LDpiU32 : InstPTX<(outs RegI32:$d), (ins MEMpi:$a), + "ld.param.u32\t$d, [$a]", + [(set RegI32:$d, (PTXloadparam timm:$a))]>; + def LDpiU64 : InstPTX<(outs RegI64:$d), (ins MEMpi:$a), + "ld.param.u64\t$d, [$a]", + [(set RegI64:$d, (PTXloadparam timm:$a))]>; + def LDpiF32 : InstPTX<(outs RegF32:$d), (ins MEMpi:$a), + "ld.param.f32\t$d, [$a]", + [(set RegF32:$d, (PTXloadparam timm:$a))]>; + def LDpiF64 : InstPTX<(outs RegF64:$d), (ins MEMpi:$a), + "ld.param.f64\t$d, [$a]", + [(set RegF64:$d, (PTXloadparam timm:$a))]>; + + def STpiPred : InstPTX<(outs), (ins MEMret:$d, RegPred:$a), + "st.param.pred\t[$d], $a", + [(PTXstoreparam timm:$d, RegPred:$a)]>; + def STpiU16 : InstPTX<(outs), (ins MEMret:$d, RegI16:$a), + "st.param.u16\t[$d], $a", + [(PTXstoreparam timm:$d, RegI16:$a)]>; + def STpiU32 : InstPTX<(outs), (ins MEMret:$d, RegI32:$a), + "st.param.u32\t[$d], $a", + [(PTXstoreparam timm:$d, RegI32:$a)]>; + def STpiU64 : InstPTX<(outs), (ins MEMret:$d, RegI64:$a), + "st.param.u64\t[$d], $a", + [(PTXstoreparam timm:$d, RegI64:$a)]>; + def STpiF32 : InstPTX<(outs), (ins MEMret:$d, RegF32:$a), + "st.param.f32\t[$d], $a", + [(PTXstoreparam timm:$d, RegF32:$a)]>; + def STpiF64 : InstPTX<(outs), (ins MEMret:$d, RegF64:$a), + "st.param.f64\t[$d], $a", + [(PTXstoreparam timm:$d, RegF64:$a)]>; +} // Stores defm STg : PTX_ST_ALL<"st.global", store_global>; @@ -811,136 +884,174 @@ defm STs : PTX_ST_ALL<"st.shared", store_shared>; // TODO: Do something with st.param if/when it is needed. // Conversion to pred - +// PTX does not directly support converting to a predicate type, so we fake it +// by performing a greater-than test between the value and zero. This follows +// the C convention that any non-zero value is equivalent to 'true'. def CVT_pred_u16 - : InstPTX<(outs Preds:$d), (ins RRegu16:$a), "cvt.pred.u16\t$d, $a", - [(set Preds:$d, (trunc RRegu16:$a))]>; + : InstPTX<(outs RegPred:$d), (ins RegI16:$a), "setp.gt.u16\t$d, $a, 0", + [(set RegPred:$d, (trunc RegI16:$a))]>; def CVT_pred_u32 - : InstPTX<(outs Preds:$d), (ins RRegu32:$a), "cvt.pred.u32\t$d, $a", - [(set Preds:$d, (trunc RRegu32:$a))]>; + : InstPTX<(outs RegPred:$d), (ins RegI32:$a), "setp.gt.u32\t$d, $a, 0", + [(set RegPred:$d, (trunc RegI32:$a))]>; def CVT_pred_u64 - : InstPTX<(outs Preds:$d), (ins RRegu64:$a), "cvt.pred.u64\t$d, $a", - [(set Preds:$d, (trunc RRegu64:$a))]>; + : InstPTX<(outs RegPred:$d), (ins RegI64:$a), "setp.gt.u64\t$d, $a, 0", + [(set RegPred:$d, (trunc RegI64:$a))]>; def CVT_pred_f32 - : InstPTX<(outs Preds:$d), (ins RRegf32:$a), "cvt.rni.pred.f32\t$d, $a", - [(set Preds:$d, (fp_to_uint RRegf32:$a))]>; + : InstPTX<(outs RegPred:$d), (ins RegF32:$a), "setp.gt.f32\t$d, $a, 0", + [(set RegPred:$d, (fp_to_uint RegF32:$a))]>; def CVT_pred_f64 - : InstPTX<(outs Preds:$d), (ins RRegf64:$a), "cvt.rni.pred.f64\t$d, $a", - [(set Preds:$d, (fp_to_uint RRegf64:$a))]>; + : InstPTX<(outs RegPred:$d), (ins RegF64:$a), "setp.gt.f64\t$d, $a, 0", + [(set RegPred:$d, (fp_to_uint RegF64:$a))]>; // Conversion to u16 +// PTX does not directly support converting a predicate to a value, so we +// use a select instruction to select either 0 or 1 (integer or fp) based +// on the truth value of the predicate. +def CVT_u16_preda + : InstPTX<(outs RegI16:$d), (ins RegPred:$a), "selp.u16\t$d, 1, 0, $a", + [(set RegI16:$d, (anyext RegPred:$a))]>; def CVT_u16_pred - : InstPTX<(outs RRegu16:$d), (ins Preds:$a), "cvt.u16.pred\t$d, $a", - [(set RRegu16:$d, (zext Preds:$a))]>; + : InstPTX<(outs RegI16:$d), (ins RegPred:$a), "selp.u16\t$d, 1, 0, $a", + [(set RegI16:$d, (zext RegPred:$a))]>; + +def CVT_u16_preds + : InstPTX<(outs RegI16:$d), (ins RegPred:$a), "selp.u16\t$d, 1, 0, $a", + [(set RegI16:$d, (sext RegPred:$a))]>; def CVT_u16_u32 - : InstPTX<(outs RRegu16:$d), (ins RRegu32:$a), "cvt.u16.u32\t$d, $a", - [(set RRegu16:$d, (trunc RRegu32:$a))]>; + : InstPTX<(outs RegI16:$d), (ins RegI32:$a), "cvt.u16.u32\t$d, $a", + [(set RegI16:$d, (trunc RegI32:$a))]>; def CVT_u16_u64 - : InstPTX<(outs RRegu16:$d), (ins RRegu64:$a), "cvt.u16.u64\t$d, $a", - [(set RRegu16:$d, (trunc RRegu64:$a))]>; + : InstPTX<(outs RegI16:$d), (ins RegI64:$a), "cvt.u16.u64\t$d, $a", + [(set RegI16:$d, (trunc RegI64:$a))]>; def CVT_u16_f32 - : InstPTX<(outs RRegu16:$d), (ins RRegf32:$a), "cvt.rni.u16.f32\t$d, $a", - [(set RRegu16:$d, (fp_to_uint RRegf32:$a))]>; + : InstPTX<(outs RegI16:$d), (ins RegF32:$a), "cvt.rzi.u16.f32\t$d, $a", + [(set RegI16:$d, (fp_to_uint RegF32:$a))]>; def CVT_u16_f64 - : InstPTX<(outs RRegu16:$d), (ins RRegf64:$a), "cvt.rni.u16.f64\t$d, $a", - [(set RRegu16:$d, (fp_to_uint RRegf64:$a))]>; + : InstPTX<(outs RegI16:$d), (ins RegF64:$a), "cvt.rzi.u16.f64\t$d, $a", + [(set RegI16:$d, (fp_to_uint RegF64:$a))]>; // Conversion to u32 def CVT_u32_pred - : InstPTX<(outs RRegu32:$d), (ins Preds:$a), "cvt.u32.pred\t$d, $a", - [(set RRegu32:$d, (zext Preds:$a))]>; + : InstPTX<(outs RegI32:$d), (ins RegPred:$a), "selp.u32\t$d, 1, 0, $a", + [(set RegI32:$d, (zext RegPred:$a))]>; + +def CVT_u32_b16 + : InstPTX<(outs RegI32:$d), (ins RegI16:$a), "cvt.u32.u16\t$d, $a", + [(set RegI32:$d, (anyext RegI16:$a))]>; def CVT_u32_u16 - : InstPTX<(outs RRegu32:$d), (ins RRegu16:$a), "cvt.u32.u16\t$d, $a", - [(set RRegu32:$d, (zext RRegu16:$a))]>; + : InstPTX<(outs RegI32:$d), (ins RegI16:$a), "cvt.u32.u16\t$d, $a", + [(set RegI32:$d, (zext RegI16:$a))]>; + +def CVT_u32_preds + : InstPTX<(outs RegI32:$d), (ins RegPred:$a), "selp.u32\t$d, 1, 0, $a", + [(set RegI32:$d, (sext RegPred:$a))]>; + +def CVT_u32_s16 + : InstPTX<(outs RegI32:$d), (ins RegI16:$a), "cvt.u32.s16\t$d, $a", + [(set RegI32:$d, (sext RegI16:$a))]>; def CVT_u32_u64 - : InstPTX<(outs RRegu32:$d), (ins RRegu64:$a), "cvt.u32.u64\t$d, $a", - [(set RRegu32:$d, (trunc RRegu64:$a))]>; + : InstPTX<(outs RegI32:$d), (ins RegI64:$a), "cvt.u32.u64\t$d, $a", + [(set RegI32:$d, (trunc RegI64:$a))]>; def CVT_u32_f32 - : InstPTX<(outs RRegu32:$d), (ins RRegf32:$a), "cvt.rni.u32.f32\t$d, $a", - [(set RRegu32:$d, (fp_to_uint RRegf32:$a))]>; + : InstPTX<(outs RegI32:$d), (ins RegF32:$a), "cvt.rzi.u32.f32\t$d, $a", + [(set RegI32:$d, (fp_to_uint RegF32:$a))]>; def CVT_u32_f64 - : InstPTX<(outs RRegu32:$d), (ins RRegf64:$a), "cvt.rni.u32.f64\t$d, $a", - [(set RRegu32:$d, (fp_to_uint RRegf64:$a))]>; + : InstPTX<(outs RegI32:$d), (ins RegF64:$a), "cvt.rzi.u32.f64\t$d, $a", + [(set RegI32:$d, (fp_to_uint RegF64:$a))]>; // Conversion to u64 def CVT_u64_pred - : InstPTX<(outs RRegu64:$d), (ins Preds:$a), "cvt.u64.pred\t$d, $a", - [(set RRegu64:$d, (zext Preds:$a))]>; + : InstPTX<(outs RegI64:$d), (ins RegPred:$a), "selp.u64\t$d, 1, 0, $a", + [(set RegI64:$d, (zext RegPred:$a))]>; + +def CVT_u64_preds + : InstPTX<(outs RegI64:$d), (ins RegPred:$a), "selp.u64\t$d, 1, 0, $a", + [(set RegI64:$d, (sext RegPred:$a))]>; def CVT_u64_u16 - : InstPTX<(outs RRegu64:$d), (ins RRegu16:$a), "cvt.u64.u16\t$d, $a", - [(set RRegu64:$d, (zext RRegu16:$a))]>; + : InstPTX<(outs RegI64:$d), (ins RegI16:$a), "cvt.u64.u16\t$d, $a", + [(set RegI64:$d, (zext RegI16:$a))]>; + +def CVT_u64_s16 + : InstPTX<(outs RegI64:$d), (ins RegI16:$a), "cvt.u64.s16\t$d, $a", + [(set RegI64:$d, (sext RegI16:$a))]>; def CVT_u64_u32 - : InstPTX<(outs RRegu64:$d), (ins RRegu32:$a), "cvt.u64.u32\t$d, $a", - [(set RRegu64:$d, (zext RRegu32:$a))]>; + : InstPTX<(outs RegI64:$d), (ins RegI32:$a), "cvt.u64.u32\t$d, $a", + [(set RegI64:$d, (zext RegI32:$a))]>; + +def CVT_u64_s32 + : InstPTX<(outs RegI64:$d), (ins RegI32:$a), "cvt.u64.s32\t$d, $a", + [(set RegI64:$d, (sext RegI32:$a))]>; def CVT_u64_f32 - : InstPTX<(outs RRegu64:$d), (ins RRegf32:$a), "cvt.rni.u64.f32\t$d, $a", - [(set RRegu64:$d, (fp_to_uint RRegf32:$a))]>; + : InstPTX<(outs RegI64:$d), (ins RegF32:$a), "cvt.rzi.u64.f32\t$d, $a", + [(set RegI64:$d, (fp_to_uint RegF32:$a))]>; def CVT_u64_f64 - : InstPTX<(outs RRegu64:$d), (ins RRegf64:$a), "cvt.rni.u64.f64\t$d, $a", - [(set RRegu64:$d, (fp_to_uint RRegf64:$a))]>; + : InstPTX<(outs RegI64:$d), (ins RegF64:$a), "cvt.rzi.u64.f64\t$d, $a", + [(set RegI64:$d, (fp_to_uint RegF64:$a))]>; // Conversion to f32 def CVT_f32_pred - : InstPTX<(outs RRegf32:$d), (ins Preds:$a), "cvt.rn.f32.pred\t$d, $a", - [(set RRegf32:$d, (uint_to_fp Preds:$a))]>; + : InstPTX<(outs RegF32:$d), (ins RegPred:$a), + "selp.f32\t$d, 0F3F800000, 0F00000000, $a", // 1.0 + [(set RegF32:$d, (uint_to_fp RegPred:$a))]>; def CVT_f32_u16 - : InstPTX<(outs RRegf32:$d), (ins RRegu16:$a), "cvt.rn.f32.u16\t$d, $a", - [(set RRegf32:$d, (uint_to_fp RRegu16:$a))]>; + : InstPTX<(outs RegF32:$d), (ins RegI16:$a), "cvt.rn.f32.u16\t$d, $a", + [(set RegF32:$d, (uint_to_fp RegI16:$a))]>; def CVT_f32_u32 - : InstPTX<(outs RRegf32:$d), (ins RRegu32:$a), "cvt.rn.f32.u32\t$d, $a", - [(set RRegf32:$d, (uint_to_fp RRegu32:$a))]>; + : InstPTX<(outs RegF32:$d), (ins RegI32:$a), "cvt.rn.f32.u32\t$d, $a", + [(set RegF32:$d, (uint_to_fp RegI32:$a))]>; def CVT_f32_u64 - : InstPTX<(outs RRegf32:$d), (ins RRegu64:$a), "cvt.rn.f32.u64\t$d, $a", - [(set RRegf32:$d, (uint_to_fp RRegu64:$a))]>; + : InstPTX<(outs RegF32:$d), (ins RegI64:$a), "cvt.rn.f32.u64\t$d, $a", + [(set RegF32:$d, (uint_to_fp RegI64:$a))]>; def CVT_f32_f64 - : InstPTX<(outs RRegf32:$d), (ins RRegf64:$a), "cvt.rn.f32.f64\t$d, $a", - [(set RRegf32:$d, (fround RRegf64:$a))]>; + : InstPTX<(outs RegF32:$d), (ins RegF64:$a), "cvt.rn.f32.f64\t$d, $a", + [(set RegF32:$d, (fround RegF64:$a))]>; // Conversion to f64 def CVT_f64_pred - : InstPTX<(outs RRegf64:$d), (ins Preds:$a), "cvt.rn.f64.pred\t$d, $a", - [(set RRegf64:$d, (uint_to_fp Preds:$a))]>; + : InstPTX<(outs RegF64:$d), (ins RegPred:$a), + "selp.f64\t$d, 0D3F80000000000000, 0D0000000000000000, $a", // 1.0 + [(set RegF64:$d, (uint_to_fp RegPred:$a))]>; def CVT_f64_u16 - : InstPTX<(outs RRegf64:$d), (ins RRegu16:$a), "cvt.rn.f64.u16\t$d, $a", - [(set RRegf64:$d, (uint_to_fp RRegu16:$a))]>; + : InstPTX<(outs RegF64:$d), (ins RegI16:$a), "cvt.rn.f64.u16\t$d, $a", + [(set RegF64:$d, (uint_to_fp RegI16:$a))]>; def CVT_f64_u32 - : InstPTX<(outs RRegf64:$d), (ins RRegu32:$a), "cvt.rn.f64.u32\t$d, $a", - [(set RRegf64:$d, (uint_to_fp RRegu32:$a))]>; + : InstPTX<(outs RegF64:$d), (ins RegI32:$a), "cvt.rn.f64.u32\t$d, $a", + [(set RegF64:$d, (uint_to_fp RegI32:$a))]>; def CVT_f64_u64 - : InstPTX<(outs RRegf64:$d), (ins RRegu64:$a), "cvt.rn.f64.u64\t$d, $a", - [(set RRegf64:$d, (uint_to_fp RRegu64:$a))]>; + : InstPTX<(outs RegF64:$d), (ins RegI64:$a), "cvt.rn.f64.u64\t$d, $a", + [(set RegF64:$d, (uint_to_fp RegI64:$a))]>; def CVT_f64_f32 - : InstPTX<(outs RRegf64:$d), (ins RRegf32:$a), "cvt.f64.f32\t$d, $a", - [(set RRegf64:$d, (fextend RRegf32:$a))]>; + : InstPTX<(outs RegF64:$d), (ins RegF32:$a), "cvt.f64.f32\t$d, $a", + [(set RegF64:$d, (fextend RegF32:$a))]>; ///===- Control Flow Instructions -----------------------------------------===// @@ -951,7 +1062,7 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1 in { let isBranch = 1, isTerminator = 1 in { // FIXME: The pattern part is blank because I cannot (or do not yet know - // how to) use the first operand of PredicateOperand (a Preds register) here + // how to) use the first operand of PredicateOperand (a RegPred register) here def BRAdp : InstPTX<(outs), (ins brtarget:$d), "bra\t$d", [/*(brcond pred:$_p, bb:$d)*/]>; @@ -962,6 +1073,30 @@ let isReturn = 1, isTerminator = 1, isBarrier = 1 in { def RET : InstPTX<(outs), (ins), "ret", [(PTXret)]>; } +///===- Spill Instructions ------------------------------------------------===// +// Special instructions used for stack spilling +def STACKSTOREI16 : InstPTX<(outs), (ins i32imm:$d, RegI16:$a), + "mov.u16\ts$d, $a", []>; +def STACKSTOREI32 : InstPTX<(outs), (ins i32imm:$d, RegI32:$a), + "mov.u32\ts$d, $a", []>; +def STACKSTOREI64 : InstPTX<(outs), (ins i32imm:$d, RegI64:$a), + "mov.u64\ts$d, $a", []>; +def STACKSTOREF32 : InstPTX<(outs), (ins i32imm:$d, RegF32:$a), + "mov.f32\ts$d, $a", []>; +def STACKSTOREF64 : InstPTX<(outs), (ins i32imm:$d, RegF64:$a), + "mov.f64\ts$d, $a", []>; + +def STACKLOADI16 : InstPTX<(outs), (ins RegI16:$d, i32imm:$a), + "mov.u16\t$d, s$a", []>; +def STACKLOADI32 : InstPTX<(outs), (ins RegI32:$d, i32imm:$a), + "mov.u32\t$d, s$a", []>; +def STACKLOADI64 : InstPTX<(outs), (ins RegI64:$d, i32imm:$a), + "mov.u64\t$d, s$a", []>; +def STACKLOADF32 : InstPTX<(outs), (ins RegF32:$d, i32imm:$a), + "mov.f32\t$d, s$a", []>; +def STACKLOADF64 : InstPTX<(outs), (ins RegF64:$d, i32imm:$a), + "mov.f64\t$d, s$a", []>; + ///===- Intrinsic Instructions --------------------------------------------===// include "PTXIntrinsicInstrInfo.td" diff --git a/lib/Target/PTX/PTXIntrinsicInstrInfo.td b/lib/Target/PTX/PTXIntrinsicInstrInfo.td index 320934a2228c..8d97909d339a 100644 --- a/lib/Target/PTX/PTXIntrinsicInstrInfo.td +++ b/lib/Target/PTX/PTXIntrinsicInstrInfo.td @@ -14,14 +14,14 @@ // PTX Special Purpose Register Accessor Intrinsics class PTX_READ_SPECIAL_REGISTER_R64<string regname, Intrinsic intop> - : InstPTX<(outs RRegu64:$d), (ins), + : InstPTX<(outs RegI64:$d), (ins), !strconcat("mov.u64\t$d, %", regname), - [(set RRegu64:$d, (intop))]>; + [(set RegI64:$d, (intop))]>; class PTX_READ_SPECIAL_REGISTER_R32<string regname, Intrinsic intop> - : InstPTX<(outs RRegu32:$d), (ins), + : InstPTX<(outs RegI32:$d), (ins), !strconcat("mov.u32\t$d, %", regname), - [(set RRegu32:$d, (intop))]>; + [(set RegI32:$d, (intop))]>; // TODO Add read vector-version of special registers diff --git a/lib/Target/PTX/PTXMCAsmStreamer.cpp b/lib/Target/PTX/PTXMCAsmStreamer.cpp index 1574670b6e9b..b13a3dace130 100644 --- a/lib/Target/PTX/PTXMCAsmStreamer.cpp +++ b/lib/Target/PTX/PTXMCAsmStreamer.cpp @@ -23,7 +23,6 @@ #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetAsmInfo.h" using namespace llvm; @@ -115,7 +114,8 @@ public: virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, - const MCSymbol *Label); + const MCSymbol *Label, + unsigned PointerSize); virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); @@ -260,7 +260,8 @@ void PTXMCAsmStreamer::EmitWeakReference(MCSymbol *Alias, void PTXMCAsmStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, - const MCSymbol *Label) { + const MCSymbol *Label, + unsigned PointerSize) { report_fatal_error("Unimplemented."); } @@ -367,7 +368,7 @@ void PTXMCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, int64_t IntValue; if (!Value->EvaluateAsAbsolute(IntValue)) report_fatal_error("Don't know how to emit this value."); - if (getContext().getTargetAsmInfo().isLittleEndian()) { + if (getContext().getAsmInfo().isLittleEndian()) { EmitIntValue((uint32_t)(IntValue >> 0 ), 4, AddrSpace); EmitIntValue((uint32_t)(IntValue >> 32), 4, AddrSpace); } else { diff --git a/lib/Target/PTX/PTXMFInfoExtract.cpp b/lib/Target/PTX/PTXMFInfoExtract.cpp index c5e191007239..6fe9e6c3f657 100644 --- a/lib/Target/PTX/PTXMFInfoExtract.cpp +++ b/lib/Target/PTX/PTXMFInfoExtract.cpp @@ -54,8 +54,6 @@ bool PTXMFInfoExtract::runOnMachineFunction(MachineFunction &MF) { DEBUG(dbgs() << "******** PTX FUNCTION LOCAL VAR REG DEF ********\n"); - unsigned retreg = MFI->retReg(); - DEBUG(dbgs() << "PTX::NoRegister == " << PTX::NoRegister << "\n" << "PTX::NUM_TARGET_REGS == " << PTX::NUM_TARGET_REGS << "\n"); @@ -68,15 +66,13 @@ bool PTXMFInfoExtract::runOnMachineFunction(MachineFunction &MF) { // FIXME: This is a slow linear scanning for (unsigned reg = PTX::NoRegister + 1; reg < PTX::NUM_TARGET_REGS; ++reg) if (MRI.isPhysRegUsed(reg) && - reg != retreg && + !MFI->isRetReg(reg) && (MFI->isKernel() || !MFI->isArgReg(reg))) MFI->addLocalVarReg(reg); // Notify MachineFunctionInfo that I've done adding local var reg MFI->doneAddLocalVar(); - DEBUG(dbgs() << "Return Reg: " << retreg << "\n"); - DEBUG(for (PTXMachineFunctionInfo::reg_iterator i = MFI->argRegBegin(), e = MFI->argRegEnd(); i != e; ++i) diff --git a/lib/Target/PTX/PTXMachineFunctionInfo.h b/lib/Target/PTX/PTXMachineFunctionInfo.h index 81df1c236cb2..9d65f5bd1ade 100644 --- a/lib/Target/PTX/PTXMachineFunctionInfo.h +++ b/lib/Target/PTX/PTXMachineFunctionInfo.h @@ -15,6 +15,7 @@ #define PTX_MACHINE_FUNCTION_INFO_H #include "PTX.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/CodeGen/MachineFunction.h" namespace llvm { @@ -25,7 +26,7 @@ class PTXMachineFunctionInfo : public MachineFunctionInfo { private: bool is_kernel; std::vector<unsigned> reg_arg, reg_local_var; - unsigned reg_ret; + std::vector<unsigned> reg_ret; bool _isDoneAddArg; public: @@ -39,19 +40,22 @@ public: void addArgReg(unsigned reg) { reg_arg.push_back(reg); } void addLocalVarReg(unsigned reg) { reg_local_var.push_back(reg); } - void setRetReg(unsigned reg) { reg_ret = reg; } + void addRetReg(unsigned reg) { + if (!isRetReg(reg)) { + reg_ret.push_back(reg); + } + } void doneAddArg(void) { _isDoneAddArg = true; } void doneAddLocalVar(void) {} - bool isDoneAddArg(void) { return _isDoneAddArg; } - bool isKernel() const { return is_kernel; } typedef std::vector<unsigned>::const_iterator reg_iterator; typedef std::vector<unsigned>::const_reverse_iterator reg_reverse_iterator; + typedef std::vector<unsigned>::const_iterator ret_iterator; bool argRegEmpty() const { return reg_arg.empty(); } int getNumArg() const { return reg_arg.size(); } @@ -64,12 +68,19 @@ public: reg_iterator localVarRegBegin() const { return reg_local_var.begin(); } reg_iterator localVarRegEnd() const { return reg_local_var.end(); } - unsigned retReg() const { return reg_ret; } + bool retRegEmpty() const { return reg_ret.empty(); } + int getNumRet() const { return reg_ret.size(); } + ret_iterator retRegBegin() const { return reg_ret.begin(); } + ret_iterator retRegEnd() const { return reg_ret.end(); } bool isArgReg(unsigned reg) const { return std::find(reg_arg.begin(), reg_arg.end(), reg) != reg_arg.end(); } + bool isRetReg(unsigned reg) const { + return std::find(reg_ret.begin(), reg_ret.end(), reg) != reg_ret.end(); + } + bool isLocalVarReg(unsigned reg) const { return std::find(reg_local_var.begin(), reg_local_var.end(), reg) != reg_local_var.end(); diff --git a/lib/Target/PTX/PTXRegisterInfo.cpp b/lib/Target/PTX/PTXRegisterInfo.cpp index 0f3e7bc2c3a7..cb56ea98a2b8 100644 --- a/lib/Target/PTX/PTXRegisterInfo.cpp +++ b/lib/Target/PTX/PTXRegisterInfo.cpp @@ -13,7 +13,39 @@ #include "PTX.h" #include "PTXRegisterInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +#define GET_REGINFO_TARGET_DESC +#include "PTXGenRegisterInfo.inc" using namespace llvm; -#include "PTXGenRegisterInfo.inc" +PTXRegisterInfo::PTXRegisterInfo(PTXTargetMachine &TM, + const TargetInstrInfo &TII) + : PTXGenRegisterInfo() { +} + +void PTXRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, + RegScavenger *RS) const { + unsigned Index; + MachineInstr& MI = *II; + + Index = 0; + while (!MI.getOperand(Index).isFI()) { + ++Index; + assert(Index < MI.getNumOperands() && + "Instr does not have a FrameIndex operand!"); + } + + int FrameIndex = MI.getOperand(Index).getIndex(); + + DEBUG(dbgs() << "eliminateFrameIndex: " << MI); + DEBUG(dbgs() << "- SPAdj: " << SPAdj << "\n"); + DEBUG(dbgs() << "- FrameIndex: " << FrameIndex << "\n"); + + // This frame index is post stack slot re-use assignments + MI.getOperand(Index).ChangeToImmediate(FrameIndex); +} diff --git a/lib/Target/PTX/PTXRegisterInfo.h b/lib/Target/PTX/PTXRegisterInfo.h index dc5635238106..0b63cb6d458e 100644 --- a/lib/Target/PTX/PTXRegisterInfo.h +++ b/lib/Target/PTX/PTXRegisterInfo.h @@ -17,7 +17,8 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/ADT/BitVector.h" -#include "PTXGenRegisterInfo.h.inc" +#define GET_REGINFO_HEADER +#include "PTXGenRegisterInfo.inc" namespace llvm { class PTXTargetMachine; @@ -25,7 +26,7 @@ class MachineFunction; struct PTXRegisterInfo : public PTXGenRegisterInfo { PTXRegisterInfo(PTXTargetMachine &TM, - const TargetInstrInfo &TII) {} + const TargetInstrInfo &TII); virtual const unsigned *getCalleeSavedRegs(const MachineFunction *MF = 0) const { @@ -38,11 +39,9 @@ struct PTXRegisterInfo : public PTXGenRegisterInfo { return Reserved; // reserve no regs } - virtual void eliminateFrameIndex(MachineBasicBlock::iterator MI, + virtual void eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, - RegScavenger *RS = NULL) const { - llvm_unreachable("PTX does not support general function call"); - } + RegScavenger *RS = NULL) const; virtual unsigned getFrameRegister(const MachineFunction &MF) const { llvm_unreachable("PTX does not have a frame register"); diff --git a/lib/Target/PTX/PTXRegisterInfo.td b/lib/Target/PTX/PTXRegisterInfo.td index f6161419fec1..1313d248325e 100644 --- a/lib/Target/PTX/PTXRegisterInfo.td +++ b/lib/Target/PTX/PTXRegisterInfo.td @@ -1,3 +1,4 @@ + //===- PTXRegisterInfo.td - PTX Register defs ----------------*- tblgen -*-===// // // The LLVM Compiler Infrastructure @@ -21,16 +22,16 @@ class PTXReg<string n> : Register<n> { ///===- Predicate Registers -----------------------------------------------===// -def P0 : PTXReg<"p0">; -def P1 : PTXReg<"p1">; -def P2 : PTXReg<"p2">; -def P3 : PTXReg<"p3">; -def P4 : PTXReg<"p4">; -def P5 : PTXReg<"p5">; -def P6 : PTXReg<"p6">; -def P7 : PTXReg<"p7">; -def P8 : PTXReg<"p8">; -def P9 : PTXReg<"p9">; +def P0 : PTXReg<"p0">; +def P1 : PTXReg<"p1">; +def P2 : PTXReg<"p2">; +def P3 : PTXReg<"p3">; +def P4 : PTXReg<"p4">; +def P5 : PTXReg<"p5">; +def P6 : PTXReg<"p6">; +def P7 : PTXReg<"p7">; +def P8 : PTXReg<"p8">; +def P9 : PTXReg<"p9">; def P10 : PTXReg<"p10">; def P11 : PTXReg<"p11">; def P12 : PTXReg<"p12">; @@ -85,19 +86,83 @@ def P60 : PTXReg<"p60">; def P61 : PTXReg<"p61">; def P62 : PTXReg<"p62">; def P63 : PTXReg<"p63">; +def P64 : PTXReg<"p64">; +def P65 : PTXReg<"p65">; +def P66 : PTXReg<"p66">; +def P67 : PTXReg<"p67">; +def P68 : PTXReg<"p68">; +def P69 : PTXReg<"p69">; +def P70 : PTXReg<"p70">; +def P71 : PTXReg<"p71">; +def P72 : PTXReg<"p72">; +def P73 : PTXReg<"p73">; +def P74 : PTXReg<"p74">; +def P75 : PTXReg<"p75">; +def P76 : PTXReg<"p76">; +def P77 : PTXReg<"p77">; +def P78 : PTXReg<"p78">; +def P79 : PTXReg<"p79">; +def P80 : PTXReg<"p80">; +def P81 : PTXReg<"p81">; +def P82 : PTXReg<"p82">; +def P83 : PTXReg<"p83">; +def P84 : PTXReg<"p84">; +def P85 : PTXReg<"p85">; +def P86 : PTXReg<"p86">; +def P87 : PTXReg<"p87">; +def P88 : PTXReg<"p88">; +def P89 : PTXReg<"p89">; +def P90 : PTXReg<"p90">; +def P91 : PTXReg<"p91">; +def P92 : PTXReg<"p92">; +def P93 : PTXReg<"p93">; +def P94 : PTXReg<"p94">; +def P95 : PTXReg<"p95">; +def P96 : PTXReg<"p96">; +def P97 : PTXReg<"p97">; +def P98 : PTXReg<"p98">; +def P99 : PTXReg<"p99">; +def P100 : PTXReg<"p100">; +def P101 : PTXReg<"p101">; +def P102 : PTXReg<"p102">; +def P103 : PTXReg<"p103">; +def P104 : PTXReg<"p104">; +def P105 : PTXReg<"p105">; +def P106 : PTXReg<"p106">; +def P107 : PTXReg<"p107">; +def P108 : PTXReg<"p108">; +def P109 : PTXReg<"p109">; +def P110 : PTXReg<"p110">; +def P111 : PTXReg<"p111">; +def P112 : PTXReg<"p112">; +def P113 : PTXReg<"p113">; +def P114 : PTXReg<"p114">; +def P115 : PTXReg<"p115">; +def P116 : PTXReg<"p116">; +def P117 : PTXReg<"p117">; +def P118 : PTXReg<"p118">; +def P119 : PTXReg<"p119">; +def P120 : PTXReg<"p120">; +def P121 : PTXReg<"p121">; +def P122 : PTXReg<"p122">; +def P123 : PTXReg<"p123">; +def P124 : PTXReg<"p124">; +def P125 : PTXReg<"p125">; +def P126 : PTXReg<"p126">; +def P127 : PTXReg<"p127">; -///===- 16-bit Integer Registers ------------------------------------------===// +///===- 16-Bit Registers --------------------------------------------------===// -def RH0 : PTXReg<"rh0">; -def RH1 : PTXReg<"rh1">; -def RH2 : PTXReg<"rh2">; -def RH3 : PTXReg<"rh3">; -def RH4 : PTXReg<"rh4">; -def RH5 : PTXReg<"rh5">; -def RH6 : PTXReg<"rh6">; -def RH7 : PTXReg<"rh7">; -def RH8 : PTXReg<"rh8">; -def RH9 : PTXReg<"rh9">; +def RH0 : PTXReg<"rh0">; +def RH1 : PTXReg<"rh1">; +def RH2 : PTXReg<"rh2">; +def RH3 : PTXReg<"rh3">; +def RH4 : PTXReg<"rh4">; +def RH5 : PTXReg<"rh5">; +def RH6 : PTXReg<"rh6">; +def RH7 : PTXReg<"rh7">; +def RH8 : PTXReg<"rh8">; +def RH9 : PTXReg<"rh9">; def RH10 : PTXReg<"rh10">; def RH11 : PTXReg<"rh11">; def RH12 : PTXReg<"rh12">; @@ -152,20 +217,83 @@ def RH60 : PTXReg<"rh60">; def RH61 : PTXReg<"rh61">; def RH62 : PTXReg<"rh62">; def RH63 : PTXReg<"rh63">; +def RH64 : PTXReg<"rh64">; +def RH65 : PTXReg<"rh65">; +def RH66 : PTXReg<"rh66">; +def RH67 : PTXReg<"rh67">; +def RH68 : PTXReg<"rh68">; +def RH69 : PTXReg<"rh69">; +def RH70 : PTXReg<"rh70">; +def RH71 : PTXReg<"rh71">; +def RH72 : PTXReg<"rh72">; +def RH73 : PTXReg<"rh73">; +def RH74 : PTXReg<"rh74">; +def RH75 : PTXReg<"rh75">; +def RH76 : PTXReg<"rh76">; +def RH77 : PTXReg<"rh77">; +def RH78 : PTXReg<"rh78">; +def RH79 : PTXReg<"rh79">; +def RH80 : PTXReg<"rh80">; +def RH81 : PTXReg<"rh81">; +def RH82 : PTXReg<"rh82">; +def RH83 : PTXReg<"rh83">; +def RH84 : PTXReg<"rh84">; +def RH85 : PTXReg<"rh85">; +def RH86 : PTXReg<"rh86">; +def RH87 : PTXReg<"rh87">; +def RH88 : PTXReg<"rh88">; +def RH89 : PTXReg<"rh89">; +def RH90 : PTXReg<"rh90">; +def RH91 : PTXReg<"rh91">; +def RH92 : PTXReg<"rh92">; +def RH93 : PTXReg<"rh93">; +def RH94 : PTXReg<"rh94">; +def RH95 : PTXReg<"rh95">; +def RH96 : PTXReg<"rh96">; +def RH97 : PTXReg<"rh97">; +def RH98 : PTXReg<"rh98">; +def RH99 : PTXReg<"rh99">; +def RH100 : PTXReg<"rh100">; +def RH101 : PTXReg<"rh101">; +def RH102 : PTXReg<"rh102">; +def RH103 : PTXReg<"rh103">; +def RH104 : PTXReg<"rh104">; +def RH105 : PTXReg<"rh105">; +def RH106 : PTXReg<"rh106">; +def RH107 : PTXReg<"rh107">; +def RH108 : PTXReg<"rh108">; +def RH109 : PTXReg<"rh109">; +def RH110 : PTXReg<"rh110">; +def RH111 : PTXReg<"rh111">; +def RH112 : PTXReg<"rh112">; +def RH113 : PTXReg<"rh113">; +def RH114 : PTXReg<"rh114">; +def RH115 : PTXReg<"rh115">; +def RH116 : PTXReg<"rh116">; +def RH117 : PTXReg<"rh117">; +def RH118 : PTXReg<"rh118">; +def RH119 : PTXReg<"rh119">; +def RH120 : PTXReg<"rh120">; +def RH121 : PTXReg<"rh121">; +def RH122 : PTXReg<"rh122">; +def RH123 : PTXReg<"rh123">; +def RH124 : PTXReg<"rh124">; +def RH125 : PTXReg<"rh125">; +def RH126 : PTXReg<"rh126">; +def RH127 : PTXReg<"rh127">; +///===- 32-Bit Registers --------------------------------------------------===// -///===- 32-bit Integer Registers ------------------------------------------===// - -def R0 : PTXReg<"r0">; -def R1 : PTXReg<"r1">; -def R2 : PTXReg<"r2">; -def R3 : PTXReg<"r3">; -def R4 : PTXReg<"r4">; -def R5 : PTXReg<"r5">; -def R6 : PTXReg<"r6">; -def R7 : PTXReg<"r7">; -def R8 : PTXReg<"r8">; -def R9 : PTXReg<"r9">; +def R0 : PTXReg<"r0">; +def R1 : PTXReg<"r1">; +def R2 : PTXReg<"r2">; +def R3 : PTXReg<"r3">; +def R4 : PTXReg<"r4">; +def R5 : PTXReg<"r5">; +def R6 : PTXReg<"r6">; +def R7 : PTXReg<"r7">; +def R8 : PTXReg<"r8">; +def R9 : PTXReg<"r9">; def R10 : PTXReg<"r10">; def R11 : PTXReg<"r11">; def R12 : PTXReg<"r12">; @@ -220,20 +348,83 @@ def R60 : PTXReg<"r60">; def R61 : PTXReg<"r61">; def R62 : PTXReg<"r62">; def R63 : PTXReg<"r63">; +def R64 : PTXReg<"r64">; +def R65 : PTXReg<"r65">; +def R66 : PTXReg<"r66">; +def R67 : PTXReg<"r67">; +def R68 : PTXReg<"r68">; +def R69 : PTXReg<"r69">; +def R70 : PTXReg<"r70">; +def R71 : PTXReg<"r71">; +def R72 : PTXReg<"r72">; +def R73 : PTXReg<"r73">; +def R74 : PTXReg<"r74">; +def R75 : PTXReg<"r75">; +def R76 : PTXReg<"r76">; +def R77 : PTXReg<"r77">; +def R78 : PTXReg<"r78">; +def R79 : PTXReg<"r79">; +def R80 : PTXReg<"r80">; +def R81 : PTXReg<"r81">; +def R82 : PTXReg<"r82">; +def R83 : PTXReg<"r83">; +def R84 : PTXReg<"r84">; +def R85 : PTXReg<"r85">; +def R86 : PTXReg<"r86">; +def R87 : PTXReg<"r87">; +def R88 : PTXReg<"r88">; +def R89 : PTXReg<"r89">; +def R90 : PTXReg<"r90">; +def R91 : PTXReg<"r91">; +def R92 : PTXReg<"r92">; +def R93 : PTXReg<"r93">; +def R94 : PTXReg<"r94">; +def R95 : PTXReg<"r95">; +def R96 : PTXReg<"r96">; +def R97 : PTXReg<"r97">; +def R98 : PTXReg<"r98">; +def R99 : PTXReg<"r99">; +def R100 : PTXReg<"r100">; +def R101 : PTXReg<"r101">; +def R102 : PTXReg<"r102">; +def R103 : PTXReg<"r103">; +def R104 : PTXReg<"r104">; +def R105 : PTXReg<"r105">; +def R106 : PTXReg<"r106">; +def R107 : PTXReg<"r107">; +def R108 : PTXReg<"r108">; +def R109 : PTXReg<"r109">; +def R110 : PTXReg<"r110">; +def R111 : PTXReg<"r111">; +def R112 : PTXReg<"r112">; +def R113 : PTXReg<"r113">; +def R114 : PTXReg<"r114">; +def R115 : PTXReg<"r115">; +def R116 : PTXReg<"r116">; +def R117 : PTXReg<"r117">; +def R118 : PTXReg<"r118">; +def R119 : PTXReg<"r119">; +def R120 : PTXReg<"r120">; +def R121 : PTXReg<"r121">; +def R122 : PTXReg<"r122">; +def R123 : PTXReg<"r123">; +def R124 : PTXReg<"r124">; +def R125 : PTXReg<"r125">; +def R126 : PTXReg<"r126">; +def R127 : PTXReg<"r127">; +///===- 64-Bit Registers --------------------------------------------------===// -///===- 64-bit Integer Registers ------------------------------------------===// - -def RD0 : PTXReg<"rd0">; -def RD1 : PTXReg<"rd1">; -def RD2 : PTXReg<"rd2">; -def RD3 : PTXReg<"rd3">; -def RD4 : PTXReg<"rd4">; -def RD5 : PTXReg<"rd5">; -def RD6 : PTXReg<"rd6">; -def RD7 : PTXReg<"rd7">; -def RD8 : PTXReg<"rd8">; -def RD9 : PTXReg<"rd9">; +def RD0 : PTXReg<"rd0">; +def RD1 : PTXReg<"rd1">; +def RD2 : PTXReg<"rd2">; +def RD3 : PTXReg<"rd3">; +def RD4 : PTXReg<"rd4">; +def RD5 : PTXReg<"rd5">; +def RD6 : PTXReg<"rd6">; +def RD7 : PTXReg<"rd7">; +def RD8 : PTXReg<"rd8">; +def RD9 : PTXReg<"rd9">; def RD10 : PTXReg<"rd10">; def RD11 : PTXReg<"rd11">; def RD12 : PTXReg<"rd12">; @@ -288,204 +479,77 @@ def RD60 : PTXReg<"rd60">; def RD61 : PTXReg<"rd61">; def RD62 : PTXReg<"rd62">; def RD63 : PTXReg<"rd63">; - - -///===- 32-bit Floating-Point Registers -----------------------------------===// - -def F0 : PTXReg<"f0">; -def F1 : PTXReg<"f1">; -def F2 : PTXReg<"f2">; -def F3 : PTXReg<"f3">; -def F4 : PTXReg<"f4">; -def F5 : PTXReg<"f5">; -def F6 : PTXReg<"f6">; -def F7 : PTXReg<"f7">; -def F8 : PTXReg<"f8">; -def F9 : PTXReg<"f9">; -def F10 : PTXReg<"f10">; -def F11 : PTXReg<"f11">; -def F12 : PTXReg<"f12">; -def F13 : PTXReg<"f13">; -def F14 : PTXReg<"f14">; -def F15 : PTXReg<"f15">; -def F16 : PTXReg<"f16">; -def F17 : PTXReg<"f17">; -def F18 : PTXReg<"f18">; -def F19 : PTXReg<"f19">; -def F20 : PTXReg<"f20">; -def F21 : PTXReg<"f21">; -def F22 : PTXReg<"f22">; -def F23 : PTXReg<"f23">; -def F24 : PTXReg<"f24">; -def F25 : PTXReg<"f25">; -def F26 : PTXReg<"f26">; -def F27 : PTXReg<"f27">; -def F28 : PTXReg<"f28">; -def F29 : PTXReg<"f29">; -def F30 : PTXReg<"f30">; -def F31 : PTXReg<"f31">; -def F32 : PTXReg<"f32">; -def F33 : PTXReg<"f33">; -def F34 : PTXReg<"f34">; -def F35 : PTXReg<"f35">; -def F36 : PTXReg<"f36">; -def F37 : PTXReg<"f37">; -def F38 : PTXReg<"f38">; -def F39 : PTXReg<"f39">; -def F40 : PTXReg<"f40">; -def F41 : PTXReg<"f41">; -def F42 : PTXReg<"f42">; -def F43 : PTXReg<"f43">; -def F44 : PTXReg<"f44">; -def F45 : PTXReg<"f45">; -def F46 : PTXReg<"f46">; -def F47 : PTXReg<"f47">; -def F48 : PTXReg<"f48">; -def F49 : PTXReg<"f49">; -def F50 : PTXReg<"f50">; -def F51 : PTXReg<"f51">; -def F52 : PTXReg<"f52">; -def F53 : PTXReg<"f53">; -def F54 : PTXReg<"f54">; -def F55 : PTXReg<"f55">; -def F56 : PTXReg<"f56">; -def F57 : PTXReg<"f57">; -def F58 : PTXReg<"f58">; -def F59 : PTXReg<"f59">; -def F60 : PTXReg<"f60">; -def F61 : PTXReg<"f61">; -def F62 : PTXReg<"f62">; -def F63 : PTXReg<"f63">; - - -///===- 64-bit Floating-Point Registers -----------------------------------===// - -def FD0 : PTXReg<"fd0">; -def FD1 : PTXReg<"fd1">; -def FD2 : PTXReg<"fd2">; -def FD3 : PTXReg<"fd3">; -def FD4 : PTXReg<"fd4">; -def FD5 : PTXReg<"fd5">; -def FD6 : PTXReg<"fd6">; -def FD7 : PTXReg<"fd7">; -def FD8 : PTXReg<"fd8">; -def FD9 : PTXReg<"fd9">; -def FD10 : PTXReg<"fd10">; -def FD11 : PTXReg<"fd11">; -def FD12 : PTXReg<"fd12">; -def FD13 : PTXReg<"fd13">; -def FD14 : PTXReg<"fd14">; -def FD15 : PTXReg<"fd15">; -def FD16 : PTXReg<"fd16">; -def FD17 : PTXReg<"fd17">; -def FD18 : PTXReg<"fd18">; -def FD19 : PTXReg<"fd19">; -def FD20 : PTXReg<"fd20">; -def FD21 : PTXReg<"fd21">; -def FD22 : PTXReg<"fd22">; -def FD23 : PTXReg<"fd23">; -def FD24 : PTXReg<"fd24">; -def FD25 : PTXReg<"fd25">; -def FD26 : PTXReg<"fd26">; -def FD27 : PTXReg<"fd27">; -def FD28 : PTXReg<"fd28">; -def FD29 : PTXReg<"fd29">; -def FD30 : PTXReg<"fd30">; -def FD31 : PTXReg<"fd31">; -def FD32 : PTXReg<"fd32">; -def FD33 : PTXReg<"fd33">; -def FD34 : PTXReg<"fd34">; -def FD35 : PTXReg<"fd35">; -def FD36 : PTXReg<"fd36">; -def FD37 : PTXReg<"fd37">; -def FD38 : PTXReg<"fd38">; -def FD39 : PTXReg<"fd39">; -def FD40 : PTXReg<"fd40">; -def FD41 : PTXReg<"fd41">; -def FD42 : PTXReg<"fd42">; -def FD43 : PTXReg<"fd43">; -def FD44 : PTXReg<"fd44">; -def FD45 : PTXReg<"fd45">; -def FD46 : PTXReg<"f4d6">; -def FD47 : PTXReg<"fd47">; -def FD48 : PTXReg<"fd48">; -def FD49 : PTXReg<"fd49">; -def FD50 : PTXReg<"fd50">; -def FD51 : PTXReg<"fd51">; -def FD52 : PTXReg<"fd52">; -def FD53 : PTXReg<"fd53">; -def FD54 : PTXReg<"fd54">; -def FD55 : PTXReg<"fd55">; -def FD56 : PTXReg<"fd56">; -def FD57 : PTXReg<"fd57">; -def FD58 : PTXReg<"fd58">; -def FD59 : PTXReg<"fd59">; -def FD60 : PTXReg<"fd60">; -def FD61 : PTXReg<"fd61">; -def FD62 : PTXReg<"fd62">; -def FD63 : PTXReg<"fd63">; - +def RD64 : PTXReg<"rd64">; +def RD65 : PTXReg<"rd65">; +def RD66 : PTXReg<"rd66">; +def RD67 : PTXReg<"rd67">; +def RD68 : PTXReg<"rd68">; +def RD69 : PTXReg<"rd69">; +def RD70 : PTXReg<"rd70">; +def RD71 : PTXReg<"rd71">; +def RD72 : PTXReg<"rd72">; +def RD73 : PTXReg<"rd73">; +def RD74 : PTXReg<"rd74">; +def RD75 : PTXReg<"rd75">; +def RD76 : PTXReg<"rd76">; +def RD77 : PTXReg<"rd77">; +def RD78 : PTXReg<"rd78">; +def RD79 : PTXReg<"rd79">; +def RD80 : PTXReg<"rd80">; +def RD81 : PTXReg<"rd81">; +def RD82 : PTXReg<"rd82">; +def RD83 : PTXReg<"rd83">; +def RD84 : PTXReg<"rd84">; +def RD85 : PTXReg<"rd85">; +def RD86 : PTXReg<"rd86">; +def RD87 : PTXReg<"rd87">; +def RD88 : PTXReg<"rd88">; +def RD89 : PTXReg<"rd89">; +def RD90 : PTXReg<"rd90">; +def RD91 : PTXReg<"rd91">; +def RD92 : PTXReg<"rd92">; +def RD93 : PTXReg<"rd93">; +def RD94 : PTXReg<"rd94">; +def RD95 : PTXReg<"rd95">; +def RD96 : PTXReg<"rd96">; +def RD97 : PTXReg<"rd97">; +def RD98 : PTXReg<"rd98">; +def RD99 : PTXReg<"rd99">; +def RD100 : PTXReg<"rd100">; +def RD101 : PTXReg<"rd101">; +def RD102 : PTXReg<"rd102">; +def RD103 : PTXReg<"rd103">; +def RD104 : PTXReg<"rd104">; +def RD105 : PTXReg<"rd105">; +def RD106 : PTXReg<"rd106">; +def RD107 : PTXReg<"rd107">; +def RD108 : PTXReg<"rd108">; +def RD109 : PTXReg<"rd109">; +def RD110 : PTXReg<"rd110">; +def RD111 : PTXReg<"rd111">; +def RD112 : PTXReg<"rd112">; +def RD113 : PTXReg<"rd113">; +def RD114 : PTXReg<"rd114">; +def RD115 : PTXReg<"rd115">; +def RD116 : PTXReg<"rd116">; +def RD117 : PTXReg<"rd117">; +def RD118 : PTXReg<"rd118">; +def RD119 : PTXReg<"rd119">; +def RD120 : PTXReg<"rd120">; +def RD121 : PTXReg<"rd121">; +def RD122 : PTXReg<"rd122">; +def RD123 : PTXReg<"rd123">; +def RD124 : PTXReg<"rd124">; +def RD125 : PTXReg<"rd125">; +def RD126 : PTXReg<"rd126">; +def RD127 : PTXReg<"rd127">; //===----------------------------------------------------------------------===// // Register classes //===----------------------------------------------------------------------===// - -def Preds : RegisterClass<"PTX", [i1], 8, - [P0, P1, P2, P3, P4, P5, P6, P7, - P8, P9, P10, P11, P12, P13, P14, P15, - P16, P17, P18, P19, P20, P21, P22, P23, - P24, P25, P26, P27, P28, P29, P30, P31, - P32, P33, P34, P35, P36, P37, P38, P39, - P40, P41, P42, P43, P44, P45, P46, P47, - P48, P49, P50, P51, P52, P53, P54, P55, - P56, P57, P58, P59, P60, P61, P62, P63]>; - -def RRegu16 : RegisterClass<"PTX", [i16], 16, - [RH0, RH1, RH2, RH3, RH4, RH5, RH6, RH7, - RH8, RH9, RH10, RH11, RH12, RH13, RH14, RH15, - RH16, RH17, RH18, RH19, RH20, RH21, RH22, RH23, - RH24, RH25, RH26, RH27, RH28, RH29, RH30, RH31, - RH32, RH33, RH34, RH35, RH36, RH37, RH38, RH39, - RH40, RH41, RH42, RH43, RH44, RH45, RH46, RH47, - RH48, RH49, RH50, RH51, RH52, RH53, RH54, RH55, - RH56, RH57, RH58, RH59, RH60, RH61, RH62, RH63]>; - -def RRegu32 : RegisterClass<"PTX", [i32], 32, - [R0, R1, R2, R3, R4, R5, R6, R7, - R8, R9, R10, R11, R12, R13, R14, R15, - R16, R17, R18, R19, R20, R21, R22, R23, - R24, R25, R26, R27, R28, R29, R30, R31, - R32, R33, R34, R35, R36, R37, R38, R39, - R40, R41, R42, R43, R44, R45, R46, R47, - R48, R49, R50, R51, R52, R53, R54, R55, - R56, R57, R58, R59, R60, R61, R62, R63]>; - -def RRegu64 : RegisterClass<"PTX", [i64], 64, - [RD0, RD1, RD2, RD3, RD4, RD5, RD6, RD7, - RD8, RD9, RD10, RD11, RD12, RD13, RD14, RD15, - RD16, RD17, RD18, RD19, RD20, RD21, RD22, RD23, - RD24, RD25, RD26, RD27, RD28, RD29, RD30, RD31, - RD32, RD33, RD34, RD35, RD36, RD37, RD38, RD39, - RD40, RD41, RD42, RD43, RD44, RD45, RD46, RD47, - RD48, RD49, RD50, RD51, RD52, RD53, RD54, RD55, - RD56, RD57, RD58, RD59, RD60, RD61, RD62, RD63]>; - -def RRegf32 : RegisterClass<"PTX", [f32], 32, - [F0, F1, F2, F3, F4, F5, F6, F7, - F8, F9, F10, F11, F12, F13, F14, F15, - F16, F17, F18, F19, F20, F21, F22, F23, - F24, F25, F26, F27, F28, F29, F30, F31, - F32, F33, F34, F35, F36, F37, F38, F39, - F40, F41, F42, F43, F44, F45, F46, F47, - F48, F49, F50, F51, F52, F53, F54, F55, - F56, F57, F58, F59, F60, F61, F62, F63]>; - -def RRegf64 : RegisterClass<"PTX", [f64], 64, - [FD0, FD1, FD2, FD3, FD4, FD5, FD6, FD7, - FD8, FD9, FD10, FD11, FD12, FD13, FD14, FD15, - FD16, FD17, FD18, FD19, FD20, FD21, FD22, FD23, - FD24, FD25, FD26, FD27, FD28, FD29, FD30, FD31, - FD32, FD33, FD34, FD35, FD36, FD37, FD38, FD39, - FD40, FD41, FD42, FD43, FD44, FD45, FD46, FD47, - FD48, FD49, FD50, FD51, FD52, FD53, FD54, FD55, - FD56, FD57, FD58, FD59, FD60, FD61, FD62, FD63]>; +def RegPred : RegisterClass<"PTX", [i1], 8, (sequence "P%u", 0, 127)>; +def RegI16 : RegisterClass<"PTX", [i16], 16, (sequence "RH%u", 0, 127)>; +def RegI32 : RegisterClass<"PTX", [i32], 32, (sequence "R%u", 0, 127)>; +def RegI64 : RegisterClass<"PTX", [i64], 64, (sequence "RD%u", 0, 127)>; +def RegF32 : RegisterClass<"PTX", [f32], 32, (sequence "R%u", 0, 127)>; +def RegF64 : RegisterClass<"PTX", [f64], 64, (sequence "RD%u", 0, 127)>; diff --git a/lib/Target/PTX/PTXSubtarget.cpp b/lib/Target/PTX/PTXSubtarget.cpp index e8a1dfecd00c..8ec646e46f68 100644 --- a/lib/Target/PTX/PTXSubtarget.cpp +++ b/lib/Target/PTX/PTXSubtarget.cpp @@ -7,32 +7,51 @@ // //===----------------------------------------------------------------------===// // -// This file implements the PTX specific subclass of TargetSubtarget. +// This file implements the PTX specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #include "PTXSubtarget.h" +#include "PTX.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetRegistry.h" + +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "PTXGenSubtargetInfo.inc" using namespace llvm; -PTXSubtarget::PTXSubtarget(const std::string &TT, const std::string &FS, - bool is64Bit) - : PTXShaderModel(PTX_SM_1_0), +PTXSubtarget::PTXSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, bool is64Bit) + : PTXGenSubtargetInfo(TT, CPU, FS), + PTXTarget(PTX_COMPUTE_1_0), PTXVersion(PTX_VERSION_2_0), SupportsDouble(false), SupportsFMA(true), - Is64Bit(is64Bit) { - std::string TARGET = "generic"; - ParseSubtargetFeatures(FS, TARGET); + Is64Bit(is64Bit) { + std::string TARGET = CPU; + if (TARGET.empty()) + TARGET = "generic"; + ParseSubtargetFeatures(TARGET, FS); } std::string PTXSubtarget::getTargetString() const { - switch(PTXShaderModel) { - default: llvm_unreachable("Unknown shader model"); + switch(PTXTarget) { + default: llvm_unreachable("Unknown PTX target"); case PTX_SM_1_0: return "sm_10"; + case PTX_SM_1_1: return "sm_11"; + case PTX_SM_1_2: return "sm_12"; case PTX_SM_1_3: return "sm_13"; case PTX_SM_2_0: return "sm_20"; + case PTX_SM_2_1: return "sm_21"; + case PTX_SM_2_2: return "sm_22"; + case PTX_SM_2_3: return "sm_23"; + case PTX_COMPUTE_1_0: return "compute_10"; + case PTX_COMPUTE_1_1: return "compute_11"; + case PTX_COMPUTE_1_2: return "compute_12"; + case PTX_COMPUTE_1_3: return "compute_13"; + case PTX_COMPUTE_2_0: return "compute_20"; } } @@ -45,5 +64,3 @@ std::string PTXSubtarget::getPTXVersionString() const { case PTX_VERSION_2_3: return "2.3"; } } - -#include "PTXGenSubtarget.inc" diff --git a/lib/Target/PTX/PTXSubtarget.h b/lib/Target/PTX/PTXSubtarget.h index 59fa6965bbac..0921f1f22c49 100644 --- a/lib/Target/PTX/PTXSubtarget.h +++ b/lib/Target/PTX/PTXSubtarget.h @@ -7,26 +7,44 @@ // //===----------------------------------------------------------------------===// // -// This file declares the PTX specific subclass of TargetSubtarget. +// This file declares the PTX specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #ifndef PTX_SUBTARGET_H #define PTX_SUBTARGET_H -#include "llvm/Target/TargetSubtarget.h" +#include "llvm/Target/TargetSubtargetInfo.h" + +#define GET_SUBTARGETINFO_HEADER +#include "PTXGenSubtargetInfo.inc" namespace llvm { - class PTXSubtarget : public TargetSubtarget { - private: +class StringRef; + + class PTXSubtarget : public PTXGenSubtargetInfo { + public: /** * Enumeration of Shader Models supported by the back-end. */ - enum PTXShaderModelEnum { + enum PTXTargetEnum { + PTX_COMPUTE_1_0, /*< Compute Compatibility 1.0 */ + PTX_COMPUTE_1_1, /*< Compute Compatibility 1.1 */ + PTX_COMPUTE_1_2, /*< Compute Compatibility 1.2 */ + PTX_COMPUTE_1_3, /*< Compute Compatibility 1.3 */ + PTX_COMPUTE_2_0, /*< Compute Compatibility 2.0 */ + PTX_LAST_COMPUTE, + PTX_SM_1_0, /*< Shader Model 1.0 */ + PTX_SM_1_1, /*< Shader Model 1.1 */ + PTX_SM_1_2, /*< Shader Model 1.2 */ PTX_SM_1_3, /*< Shader Model 1.3 */ - PTX_SM_2_0 /*< Shader Model 2.0 */ + PTX_SM_2_0, /*< Shader Model 2.0 */ + PTX_SM_2_1, /*< Shader Model 2.1 */ + PTX_SM_2_2, /*< Shader Model 2.2 */ + PTX_SM_2_3, /*< Shader Model 2.3 */ + PTX_LAST_SM }; /** @@ -41,24 +59,30 @@ namespace llvm { PTX_VERSION_2_3 /*< PTX Version 2.3 */ }; + private: + /// Shader Model supported on the target GPU. - PTXShaderModelEnum PTXShaderModel; + PTXTargetEnum PTXTarget; /// PTX Language Version. PTXVersionEnum PTXVersion; // The native .f64 type is supported on the hardware. bool SupportsDouble; - - // Support the fused-multiply add (FMA) and multiply-add (MAD) instructions + + // Support the fused-multiply add (FMA) and multiply-add (MAD) + // instructions bool SupportsFMA; - + // Use .u64 instead of .u32 for addresses. bool Is64Bit; public: - PTXSubtarget(const std::string &TT, const std::string &FS, bool is64Bit); + PTXSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, bool is64Bit); + + // Target architecture accessors std::string getTargetString() const; std::string getPTXVersionString() const; @@ -68,10 +92,6 @@ namespace llvm { bool is64Bit() const { return Is64Bit; } bool supportsFMA() const { return SupportsFMA; } - - bool supportsSM13() const { return PTXShaderModel >= PTX_SM_1_3; } - - bool supportsSM20() const { return PTXShaderModel >= PTX_SM_2_0; } bool supportsPTX21() const { return PTXVersion >= PTX_VERSION_2_1; } @@ -79,8 +99,22 @@ namespace llvm { bool supportsPTX23() const { return PTXVersion >= PTX_VERSION_2_3; } - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + bool fdivNeedsRoundingMode() const { + return (PTXTarget >= PTX_SM_1_3 && PTXTarget < PTX_LAST_SM) || + (PTXTarget >= PTX_COMPUTE_1_3 && PTXTarget < PTX_LAST_COMPUTE); + } + + bool fmadNeedsRoundingMode() const { + return (PTXTarget >= PTX_SM_1_3 && PTXTarget < PTX_LAST_SM) || + (PTXTarget >= PTX_COMPUTE_1_3 && PTXTarget < PTX_LAST_COMPUTE); + } + + bool useParamSpaceForDeviceArgs() const { + return (PTXTarget >= PTX_SM_2_0 && PTXTarget < PTX_LAST_SM) || + (PTXTarget >= PTX_COMPUTE_2_0 && PTXTarget < PTX_LAST_COMPUTE); + } + + void ParseSubtargetFeatures(StringRef CPU, StringRef FS); }; // class PTXSubtarget } // namespace llvm diff --git a/lib/Target/PTX/PTXTargetMachine.cpp b/lib/Target/PTX/PTXTargetMachine.cpp index 1b737c9d8634..ab926e02d66f 100644 --- a/lib/Target/PTX/PTXTargetMachine.cpp +++ b/lib/Target/PTX/PTXTargetMachine.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "PTX.h" -#include "PTXMCAsmInfo.h" #include "PTXTargetMachine.h" #include "llvm/PassManager.h" #include "llvm/Target/TargetRegistry.h" @@ -35,9 +34,6 @@ extern "C" void LLVMInitializePTXTarget() { RegisterTargetMachine<PTX32TargetMachine> X(ThePTX32Target); RegisterTargetMachine<PTX64TargetMachine> Y(ThePTX64Target); - RegisterAsmInfo<PTXMCAsmInfo> Z(ThePTX32Target); - RegisterAsmInfo<PTXMCAsmInfo> W(ThePTX64Target); - TargetRegistry::RegisterAsmStreamer(ThePTX32Target, createPTXAsmStreamer); TargetRegistry::RegisterAsmStreamer(ThePTX64Target, createPTXAsmStreamer); } @@ -52,11 +48,12 @@ namespace { // DataLayout and FrameLowering are filled with dummy data PTXTargetMachine::PTXTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS, bool is64Bit) - : LLVMTargetMachine(T, TT), + : LLVMTargetMachine(T, TT, CPU, FS), DataLayout(is64Bit ? DataLayout64 : DataLayout32), - Subtarget(TT, FS, is64Bit), + Subtarget(TT, CPU, FS, is64Bit), FrameLowering(Subtarget), InstrInfo(*this), TLInfo(*this) { @@ -64,14 +61,16 @@ PTXTargetMachine::PTXTargetMachine(const Target &T, PTX32TargetMachine::PTX32TargetMachine(const Target &T, const std::string& TT, + const std::string& CPU, const std::string& FS) - : PTXTargetMachine(T, TT, FS, false) { + : PTXTargetMachine(T, TT, CPU, FS, false) { } PTX64TargetMachine::PTX64TargetMachine(const Target &T, const std::string& TT, + const std::string& CPU, const std::string& FS) - : PTXTargetMachine(T, TT, FS, true) { + : PTXTargetMachine(T, TT, CPU, FS, true) { } bool PTXTargetMachine::addInstSelector(PassManagerBase &PM, diff --git a/lib/Target/PTX/PTXTargetMachine.h b/lib/Target/PTX/PTXTargetMachine.h index 149be8e3b7e9..ae4215325211 100644 --- a/lib/Target/PTX/PTXTargetMachine.h +++ b/lib/Target/PTX/PTXTargetMachine.h @@ -33,7 +33,8 @@ class PTXTargetMachine : public LLVMTargetMachine { public: PTXTargetMachine(const Target &T, const std::string &TT, - const std::string &FS, bool is64Bit); + const std::string &CPU, const std::string &FS, + bool is64Bit); virtual const TargetData *getTargetData() const { return &DataLayout; } @@ -61,14 +62,14 @@ class PTX32TargetMachine : public PTXTargetMachine { public: PTX32TargetMachine(const Target &T, const std::string &TT, - const std::string& FS); + const std::string& CPU, const std::string& FS); }; // class PTX32TargetMachine class PTX64TargetMachine : public PTXTargetMachine { public: PTX64TargetMachine(const Target &T, const std::string &TT, - const std::string& FS); + const std::string& CPU, const std::string& FS); }; // class PTX32TargetMachine } // namespace llvm diff --git a/lib/Target/PTX/generate-register-td.py b/lib/Target/PTX/generate-register-td.py new file mode 100755 index 000000000000..15286908961d --- /dev/null +++ b/lib/Target/PTX/generate-register-td.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python +##===- generate-register-td.py --------------------------------*-python-*--===## +## +## The LLVM Compiler Infrastructure +## +## This file is distributed under the University of Illinois Open Source +## License. See LICENSE.TXT for details. +## +##===----------------------------------------------------------------------===## +## +## This file describes the PTX register file generator. +## +##===----------------------------------------------------------------------===## + +from sys import argv, exit, stdout + + +if len(argv) != 5: + print('Usage: generate-register-td.py <num_preds> <num_16> <num_32> <num_64>') + exit(1) + +try: + num_pred = int(argv[1]) + num_16bit = int(argv[2]) + num_32bit = int(argv[3]) + num_64bit = int(argv[4]) +except: + print('ERROR: Invalid integer parameter') + exit(1) + +## Print the register definition file +td_file = open('PTXRegisterInfo.td', 'w') + +td_file.write(''' +//===- PTXRegisterInfo.td - PTX Register defs ----------------*- tblgen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Declarations that describe the PTX register file +//===----------------------------------------------------------------------===// + +class PTXReg<string n> : Register<n> { + let Namespace = "PTX"; +} + +//===----------------------------------------------------------------------===// +// Registers +//===----------------------------------------------------------------------===// +''') + + +# Print predicate registers +td_file.write('\n///===- Predicate Registers -----------------------------------------------===//\n\n') +for r in range(0, num_pred): + td_file.write('def P%d : PTXReg<"p%d">;\n' % (r, r)) + +# Print 16-bit registers +td_file.write('\n///===- 16-Bit Registers --------------------------------------------------===//\n\n') +for r in range(0, num_16bit): + td_file.write('def RH%d : PTXReg<"rh%d">;\n' % (r, r)) + +# Print 32-bit registers +td_file.write('\n///===- 32-Bit Registers --------------------------------------------------===//\n\n') +for r in range(0, num_32bit): + td_file.write('def R%d : PTXReg<"r%d">;\n' % (r, r)) + +# Print 64-bit registers +td_file.write('\n///===- 64-Bit Registers --------------------------------------------------===//\n\n') +for r in range(0, num_64bit): + td_file.write('def RD%d : PTXReg<"rd%d">;\n' % (r, r)) + + +td_file.write(''' +//===----------------------------------------------------------------------===// +// Register classes +//===----------------------------------------------------------------------===// +''') + + +# Print register classes + +td_file.write('def RegPred : RegisterClass<"PTX", [i1], 8, (sequence "P%%u", 0, %d)>;\n' % (num_pred-1)) +td_file.write('def RegI16 : RegisterClass<"PTX", [i16], 16, (sequence "RH%%u", 0, %d)>;\n' % (num_16bit-1)) +td_file.write('def RegI32 : RegisterClass<"PTX", [i32], 32, (sequence "R%%u", 0, %d)>;\n' % (num_32bit-1)) +td_file.write('def RegI64 : RegisterClass<"PTX", [i64], 64, (sequence "RD%%u", 0, %d)>;\n' % (num_64bit-1)) +td_file.write('def RegF32 : RegisterClass<"PTX", [f32], 32, (sequence "R%%u", 0, %d)>;\n' % (num_32bit-1)) +td_file.write('def RegF64 : RegisterClass<"PTX", [f64], 64, (sequence "RD%%u", 0, %d)>;\n' % (num_64bit-1)) + + +td_file.close() + +## Now write the PTXCallingConv.td file +td_file = open('PTXCallingConv.td', 'w') + +# Reserve 10% of the available registers for return values, and the other 90% +# for parameters +num_ret_pred = int(0.1 * num_pred) +num_ret_16bit = int(0.1 * num_16bit) +num_ret_32bit = int(0.1 * num_32bit) +num_ret_64bit = int(0.1 * num_64bit) +num_param_pred = num_pred - num_ret_pred +num_param_16bit = num_16bit - num_ret_16bit +num_param_32bit = num_32bit - num_ret_32bit +num_param_64bit = num_64bit - num_ret_64bit + +param_regs_pred = [('P%d' % (i+num_ret_pred)) for i in range(0, num_param_pred)] +ret_regs_pred = ['P%d' % i for i in range(0, num_ret_pred)] +param_regs_16bit = [('RH%d' % (i+num_ret_16bit)) for i in range(0, num_param_16bit)] +ret_regs_16bit = ['RH%d' % i for i in range(0, num_ret_16bit)] +param_regs_32bit = [('R%d' % (i+num_ret_32bit)) for i in range(0, num_param_32bit)] +ret_regs_32bit = ['R%d' % i for i in range(0, num_ret_32bit)] +param_regs_64bit = [('RD%d' % (i+num_ret_64bit)) for i in range(0, num_param_64bit)] +ret_regs_64bit = ['RD%d' % i for i in range(0, num_ret_64bit)] + +param_list_pred = reduce(lambda x, y: '%s, %s' % (x, y), param_regs_pred) +ret_list_pred = reduce(lambda x, y: '%s, %s' % (x, y), ret_regs_pred) +param_list_16bit = reduce(lambda x, y: '%s, %s' % (x, y), param_regs_16bit) +ret_list_16bit = reduce(lambda x, y: '%s, %s' % (x, y), ret_regs_16bit) +param_list_32bit = reduce(lambda x, y: '%s, %s' % (x, y), param_regs_32bit) +ret_list_32bit = reduce(lambda x, y: '%s, %s' % (x, y), ret_regs_32bit) +param_list_64bit = reduce(lambda x, y: '%s, %s' % (x, y), param_regs_64bit) +ret_list_64bit = reduce(lambda x, y: '%s, %s' % (x, y), ret_regs_64bit) + +td_file.write(''' +//===--- PTXCallingConv.td - Calling Conventions -----------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This describes the calling conventions for the PTX architecture. +// +//===----------------------------------------------------------------------===// + +// PTX Formal Parameter Calling Convention +def CC_PTX : CallingConv<[ + CCIfType<[i1], CCAssignToReg<[%s]>>, + CCIfType<[i16], CCAssignToReg<[%s]>>, + CCIfType<[i32,f32], CCAssignToReg<[%s]>>, + CCIfType<[i64,f64], CCAssignToReg<[%s]>> +]>; + +// PTX Return Value Calling Convention +def RetCC_PTX : CallingConv<[ + CCIfType<[i1], CCAssignToReg<[%s]>>, + CCIfType<[i16], CCAssignToReg<[%s]>>, + CCIfType<[i32,f32], CCAssignToReg<[%s]>>, + CCIfType<[i64,f64], CCAssignToReg<[%s]>> +]>; +''' % (param_list_pred, param_list_16bit, param_list_32bit, param_list_64bit, + ret_list_pred, ret_list_16bit, ret_list_32bit, ret_list_64bit)) + + +td_file.close() diff --git a/lib/Target/PowerPC/CMakeLists.txt b/lib/Target/PowerPC/CMakeLists.txt index f28257999d1b..d1dda3716c4a 100644 --- a/lib/Target/PowerPC/CMakeLists.txt +++ b/lib/Target/PowerPC/CMakeLists.txt @@ -1,16 +1,13 @@ set(LLVM_TARGET_DEFINITIONS PPC.td) -tablegen(PPCGenInstrNames.inc -gen-instr-enums) -tablegen(PPCGenRegisterNames.inc -gen-register-enums) tablegen(PPCGenAsmWriter.inc -gen-asm-writer) tablegen(PPCGenCodeEmitter.inc -gen-emitter) tablegen(PPCGenMCCodeEmitter.inc -gen-emitter -mc-emitter) -tablegen(PPCGenRegisterInfo.h.inc -gen-register-desc-header) -tablegen(PPCGenRegisterInfo.inc -gen-register-desc) -tablegen(PPCGenInstrInfo.inc -gen-instr-desc) +tablegen(PPCGenRegisterInfo.inc -gen-register-info) +tablegen(PPCGenInstrInfo.inc -gen-instr-info) tablegen(PPCGenDAGISel.inc -gen-dag-isel) tablegen(PPCGenCallingConv.inc -gen-callingconv) -tablegen(PPCGenSubtarget.inc -gen-subtarget) +tablegen(PPCGenSubtargetInfo.inc -gen-subtarget) add_llvm_target(PowerPCCodeGen PPCAsmBackend.cpp @@ -23,7 +20,6 @@ add_llvm_target(PowerPCCodeGen PPCISelLowering.cpp PPCFrameLowering.cpp PPCJITInfo.cpp - PPCMCAsmInfo.cpp PPCMCCodeEmitter.cpp PPCMCInstLower.cpp PPCPredicates.cpp @@ -35,3 +31,4 @@ add_llvm_target(PowerPCCodeGen add_subdirectory(InstPrinter) add_subdirectory(TargetInfo) +add_subdirectory(MCTargetDesc) diff --git a/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h b/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h index adfa0aa6306b..d022a4496e84 100644 --- a/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h +++ b/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h @@ -19,14 +19,12 @@ namespace llvm { class MCOperand; -class TargetMachine; class PPCInstPrinter : public MCInstPrinter { // 0 -> AIX, 1 -> Darwin. unsigned SyntaxVariant; public: - PPCInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI, - unsigned syntaxVariant) + PPCInstPrinter(const MCAsmInfo &MAI, unsigned syntaxVariant) : MCInstPrinter(MAI), SyntaxVariant(syntaxVariant) {} bool isDarwinSyntax() const { diff --git a/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt b/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt new file mode 100644 index 000000000000..a1b81662115a --- /dev/null +++ b/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt @@ -0,0 +1,4 @@ +add_llvm_library(LLVMPowerPCDesc + PPCMCTargetDesc.cpp + PPCMCAsmInfo.cpp + ) diff --git a/lib/Target/PowerPC/MCTargetDesc/Makefile b/lib/Target/PowerPC/MCTargetDesc/Makefile new file mode 100644 index 000000000000..9db66622cced --- /dev/null +++ b/lib/Target/PowerPC/MCTargetDesc/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/PowerPC/TargetDesc/Makefile --------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +LIBRARYNAME = LLVMPowerPCDesc + +# Hack: we need to include 'main' target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/PowerPC/PPCMCAsmInfo.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp index 2d5c8809ba9f..b6dca835b18d 100644 --- a/lib/Target/PowerPC/PPCMCAsmInfo.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp @@ -15,6 +15,10 @@ using namespace llvm; PPCMCAsmInfoDarwin::PPCMCAsmInfoDarwin(bool is64Bit) { + if (is64Bit) + PointerSize = 8; + IsLittleEndian = false; + PCSymbol = "."; CommentString = ";"; ExceptionsType = ExceptionHandling::DwarfCFI; diff --git a/lib/Target/PowerPC/PPCMCAsmInfo.h b/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.h index 96ae6fbba0e4..96ae6fbba0e4 100644 --- a/lib/Target/PowerPC/PPCMCAsmInfo.h +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.h diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp new file mode 100644 index 000000000000..02b887f4d5dc --- /dev/null +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp @@ -0,0 +1,70 @@ +//===-- PPCMCTargetDesc.cpp - PowerPC Target Descriptions -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides PowerPC specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#include "PPCMCTargetDesc.h" +#include "PPCMCAsmInfo.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Target/TargetRegistry.h" + +#define GET_INSTRINFO_MC_DESC +#include "PPCGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_MC_DESC +#include "PPCGenSubtargetInfo.inc" + +#define GET_REGINFO_MC_DESC +#include "PPCGenRegisterInfo.inc" + +using namespace llvm; + +static MCInstrInfo *createPPCMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitPPCMCInstrInfo(X); + return X; +} + +extern "C" void LLVMInitializePowerPCMCInstrInfo() { + TargetRegistry::RegisterMCInstrInfo(ThePPC32Target, createPPCMCInstrInfo); + TargetRegistry::RegisterMCInstrInfo(ThePPC64Target, createPPCMCInstrInfo); +} + + +static MCSubtargetInfo *createPPCMCSubtargetInfo(StringRef TT, StringRef CPU, + StringRef FS) { + MCSubtargetInfo *X = new MCSubtargetInfo(); + InitPPCMCSubtargetInfo(X, TT, CPU, FS); + return X; +} + +extern "C" void LLVMInitializePowerPCMCSubtargetInfo() { + TargetRegistry::RegisterMCSubtargetInfo(ThePPC32Target, + createPPCMCSubtargetInfo); + TargetRegistry::RegisterMCSubtargetInfo(ThePPC64Target, + createPPCMCSubtargetInfo); +} + +static MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) { + Triple TheTriple(TT); + bool isPPC64 = TheTriple.getArch() == Triple::ppc64; + if (TheTriple.isOSDarwin()) + return new PPCMCAsmInfoDarwin(isPPC64); + return new PPCLinuxMCAsmInfo(isPPC64); + +} + +extern "C" void LLVMInitializePowerPCMCAsmInfo() { + RegisterMCAsmInfoFn C(ThePPC32Target, createMCAsmInfo); + RegisterMCAsmInfoFn D(ThePPC64Target, createMCAsmInfo); +} diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h new file mode 100644 index 000000000000..cee235097a0a --- /dev/null +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h @@ -0,0 +1,41 @@ +//===-- PPCMCTargetDesc.h - PowerPC Target Descriptions ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides PowerPC specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#ifndef PPCMCTARGETDESC_H +#define PPCMCTARGETDESC_H + +namespace llvm { +class MCSubtargetInfo; +class Target; +class StringRef; + +extern Target ThePPC32Target; +extern Target ThePPC64Target; + +} // End llvm namespace + +// Defines symbolic names for PowerPC registers. This defines a mapping from +// register name to register number. +// +#define GET_REGINFO_ENUM +#include "PPCGenRegisterInfo.inc" + +// Defines symbolic names for the PowerPC instructions. +// +#define GET_INSTRINFO_ENUM +#include "PPCGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "PPCGenSubtargetInfo.inc" + +#endif diff --git a/lib/Target/PowerPC/Makefile b/lib/Target/PowerPC/Makefile index 030defe212c0..1617b26ca4a5 100644 --- a/lib/Target/PowerPC/Makefile +++ b/lib/Target/PowerPC/Makefile @@ -12,13 +12,12 @@ LIBRARYNAME = LLVMPowerPCCodeGen TARGET = PPC # Make sure that tblgen is run, first thing. -BUILT_SOURCES = PPCGenInstrNames.inc PPCGenRegisterNames.inc \ +BUILT_SOURCES = PPCGenRegisterInfo.inc \ PPCGenAsmWriter.inc PPCGenCodeEmitter.inc \ - PPCGenRegisterInfo.h.inc PPCGenRegisterInfo.inc \ PPCGenInstrInfo.inc PPCGenDAGISel.inc \ - PPCGenSubtarget.inc PPCGenCallingConv.inc \ + PPCGenSubtargetInfo.inc PPCGenCallingConv.inc \ PPCGenMCCodeEmitter.inc -DIRS = InstPrinter TargetInfo +DIRS = InstPrinter TargetInfo MCTargetDesc include $(LEVEL)/Makefile.common diff --git a/lib/Target/PowerPC/PPC.h b/lib/Target/PowerPC/PPC.h index 92672b5b172b..7191dd105f3c 100644 --- a/lib/Target/PowerPC/PPC.h +++ b/lib/Target/PowerPC/PPC.h @@ -15,6 +15,7 @@ #ifndef LLVM_TARGET_POWERPC_H #define LLVM_TARGET_POWERPC_H +#include "MCTargetDesc/PPCMCTargetDesc.h" #include <string> // GCC #defines PPC on Linux but we use it as our namespace name @@ -31,6 +32,8 @@ namespace llvm { class MCInst; class MCCodeEmitter; class MCContext; + class MCInstrInfo; + class MCSubtargetInfo; class TargetMachine; class TargetAsmBackend; @@ -38,16 +41,14 @@ namespace llvm { FunctionPass *createPPCISelDag(PPCTargetMachine &TM); FunctionPass *createPPCJITCodeEmitterPass(PPCTargetMachine &TM, JITCodeEmitter &MCE); - MCCodeEmitter *createPPCMCCodeEmitter(const Target &, TargetMachine &TM, + MCCodeEmitter *createPPCMCCodeEmitter(const MCInstrInfo &MCII, + const MCSubtargetInfo &STI, MCContext &Ctx); TargetAsmBackend *createPPCAsmBackend(const Target &, const std::string &); void LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, AsmPrinter &AP, bool isDarwin); - extern Target ThePPC32Target; - extern Target ThePPC64Target; - namespace PPCII { /// Target Operand Flag enum. @@ -81,13 +82,4 @@ namespace llvm { } // end namespace llvm; -// Defines symbolic names for PowerPC registers. This defines a mapping from -// register name to register number. -// -#include "PPCGenRegisterNames.inc" - -// Defines symbolic names for the PowerPC instructions. -// -#include "PPCGenInstrNames.inc" - #endif diff --git a/lib/Target/PowerPC/PPCAsmBackend.cpp b/lib/Target/PowerPC/PPCAsmBackend.cpp index f562a3f4f9e8..4b8cbb711833 100644 --- a/lib/Target/PowerPC/PPCAsmBackend.cpp +++ b/lib/Target/PowerPC/PPCAsmBackend.cpp @@ -13,6 +13,7 @@ #include "llvm/MC/MCMachObjectWriter.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCValue.h" #include "llvm/Object/MachOFormat.h" #include "llvm/Target/TargetRegistry.h" using namespace llvm; @@ -23,6 +24,11 @@ public: PPCMachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype) : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype) {} + + void RecordRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, uint64_t &FixedValue) {} }; class PPCAsmBackend : public TargetAsmBackend { diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp index b795db9594ff..9de2200296e8 100644 --- a/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -680,10 +680,9 @@ static AsmPrinter *createPPCAsmPrinterPass(TargetMachine &tm, } static MCInstPrinter *createPPCMCInstPrinter(const Target &T, - TargetMachine &TM, unsigned SyntaxVariant, const MCAsmInfo &MAI) { - return new PPCInstPrinter(TM, MAI, SyntaxVariant); + return new PPCInstPrinter(MAI, SyntaxVariant); } diff --git a/lib/Target/PowerPC/PPCHazardRecognizers.cpp b/lib/Target/PowerPC/PPCHazardRecognizers.cpp index 74ecff5af620..cddc9d858adf 100644 --- a/lib/Target/PowerPC/PPCHazardRecognizers.cpp +++ b/lib/Target/PowerPC/PPCHazardRecognizers.cpp @@ -73,12 +73,12 @@ PPCHazardRecognizer970::GetInstrType(unsigned Opcode, } Opcode = ~Opcode; - const TargetInstrDesc &TID = TII.get(Opcode); + const MCInstrDesc &MCID = TII.get(Opcode); - isLoad = TID.mayLoad(); - isStore = TID.mayStore(); + isLoad = MCID.mayLoad(); + isStore = MCID.mayStore(); - uint64_t TSFlags = TID.TSFlags; + uint64_t TSFlags = MCID.TSFlags; isFirst = TSFlags & PPCII::PPC970_First; isSingle = TSFlags & PPCII::PPC970_Single; diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 511bb223cada..2176c02c8503 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -610,6 +610,9 @@ SDNode *PPCDAGToDAGISel::SelectSETCC(SDNode *N) { DebugLoc dl = N->getDebugLoc(); unsigned Imm; ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get(); + EVT PtrVT = CurDAG->getTargetLoweringInfo().getPointerTy(); + bool isPPC64 = (PtrVT == MVT::i64); + if (isInt32Immediate(N->getOperand(1), Imm)) { // We can codegen setcc op, imm very efficiently compared to a brcond. // Check for those cases here. @@ -624,6 +627,7 @@ SDNode *PPCDAGToDAGISel::SelectSETCC(SDNode *N) { return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); } case ISD::SETNE: { + if (isPPC64) break; SDValue AD = SDValue(CurDAG->getMachineNode(PPC::ADDIC, dl, MVT::i32, MVT::Glue, Op, getI32Imm(~0U)), 0); @@ -647,6 +651,7 @@ SDNode *PPCDAGToDAGISel::SelectSETCC(SDNode *N) { switch (CC) { default: break; case ISD::SETEQ: + if (isPPC64) break; Op = SDValue(CurDAG->getMachineNode(PPC::ADDIC, dl, MVT::i32, MVT::Glue, Op, getI32Imm(1)), 0); return CurDAG->SelectNodeTo(N, PPC::ADDZE, MVT::i32, @@ -655,6 +660,7 @@ SDNode *PPCDAGToDAGISel::SelectSETCC(SDNode *N) { getI32Imm(0)), 0), Op.getValue(1)); case ISD::SETNE: { + if (isPPC64) break; Op = SDValue(CurDAG->getMachineNode(PPC::NOR, dl, MVT::i32, Op, Op), 0); SDNode *AD = CurDAG->getMachineNode(PPC::ADDIC, dl, MVT::i32, MVT::Glue, Op, getI32Imm(~0U)); @@ -996,22 +1002,25 @@ SDNode *PPCDAGToDAGISel::Select(SDNode *N) { } case ISD::SELECT_CC: { ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(4))->get(); + EVT PtrVT = CurDAG->getTargetLoweringInfo().getPointerTy(); + bool isPPC64 = (PtrVT == MVT::i64); // Handle the setcc cases here. select_cc lhs, 0, 1, 0, cc - if (ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1))) - if (ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N->getOperand(2))) - if (ConstantSDNode *N3C = dyn_cast<ConstantSDNode>(N->getOperand(3))) - if (N1C->isNullValue() && N3C->isNullValue() && - N2C->getZExtValue() == 1ULL && CC == ISD::SETNE && - // FIXME: Implement this optzn for PPC64. - N->getValueType(0) == MVT::i32) { - SDNode *Tmp = - CurDAG->getMachineNode(PPC::ADDIC, dl, MVT::i32, MVT::Glue, - N->getOperand(0), getI32Imm(~0U)); - return CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, - SDValue(Tmp, 0), N->getOperand(0), - SDValue(Tmp, 1)); - } + if (!isPPC64) + if (ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1))) + if (ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N->getOperand(2))) + if (ConstantSDNode *N3C = dyn_cast<ConstantSDNode>(N->getOperand(3))) + if (N1C->isNullValue() && N3C->isNullValue() && + N2C->getZExtValue() == 1ULL && CC == ISD::SETNE && + // FIXME: Implement this optzn for PPC64. + N->getValueType(0) == MVT::i32) { + SDNode *Tmp = + CurDAG->getMachineNode(PPC::ADDIC, dl, MVT::i32, MVT::Glue, + N->getOperand(0), getI32Imm(~0U)); + return CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, + SDValue(Tmp, 0), N->getOperand(0), + SDValue(Tmp, 1)); + } SDValue CCReg = SelectCC(N->getOperand(0), N->getOperand(1), CC, dl); unsigned BROpc = getPredicateForSetCC(CC); diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index dbb184c1f6bb..9741a3902af7 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -125,10 +125,12 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM) setOperationAction(ISD::FCOS , MVT::f64, Expand); setOperationAction(ISD::FREM , MVT::f64, Expand); setOperationAction(ISD::FPOW , MVT::f64, Expand); + setOperationAction(ISD::FMA , MVT::f64, Expand); setOperationAction(ISD::FSIN , MVT::f32, Expand); setOperationAction(ISD::FCOS , MVT::f32, Expand); setOperationAction(ISD::FREM , MVT::f32, Expand); setOperationAction(ISD::FPOW , MVT::f32, Expand); + setOperationAction(ISD::FMA , MVT::f32, Expand); setOperationAction(ISD::FLT_ROUNDS_, MVT::i32, Custom); @@ -215,10 +217,11 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM) setOperationAction(ISD::VASTART , MVT::Other, Custom); // VAARG is custom lowered with the 32-bit SVR4 ABI. - if ( TM.getSubtarget<PPCSubtarget>().isSVR4ABI() - && !TM.getSubtarget<PPCSubtarget>().isPPC64()) + if (TM.getSubtarget<PPCSubtarget>().isSVR4ABI() + && !TM.getSubtarget<PPCSubtarget>().isPPC64()) { setOperationAction(ISD::VAARG, MVT::Other, Custom); - else + setOperationAction(ISD::VAARG, MVT::i64, Custom); + } else setOperationAction(ISD::VAARG, MVT::Other, Expand); // Use the default implementation. @@ -1262,9 +1265,107 @@ SDValue PPCTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const { SDValue PPCTargetLowering::LowerVAARG(SDValue Op, SelectionDAG &DAG, const PPCSubtarget &Subtarget) const { + SDNode *Node = Op.getNode(); + EVT VT = Node->getValueType(0); + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + SDValue InChain = Node->getOperand(0); + SDValue VAListPtr = Node->getOperand(1); + const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue(); + DebugLoc dl = Node->getDebugLoc(); + + assert(!Subtarget.isPPC64() && "LowerVAARG is PPC32 only"); + + // gpr_index + SDValue GprIndex = DAG.getExtLoad(ISD::ZEXTLOAD, dl, MVT::i32, InChain, + VAListPtr, MachinePointerInfo(SV), MVT::i8, + false, false, 0); + InChain = GprIndex.getValue(1); + + if (VT == MVT::i64) { + // Check if GprIndex is even + SDValue GprAnd = DAG.getNode(ISD::AND, dl, MVT::i32, GprIndex, + DAG.getConstant(1, MVT::i32)); + SDValue CC64 = DAG.getSetCC(dl, MVT::i32, GprAnd, + DAG.getConstant(0, MVT::i32), ISD::SETNE); + SDValue GprIndexPlusOne = DAG.getNode(ISD::ADD, dl, MVT::i32, GprIndex, + DAG.getConstant(1, MVT::i32)); + // Align GprIndex to be even if it isn't + GprIndex = DAG.getNode(ISD::SELECT, dl, MVT::i32, CC64, GprIndexPlusOne, + GprIndex); + } + + // fpr index is 1 byte after gpr + SDValue FprPtr = DAG.getNode(ISD::ADD, dl, PtrVT, VAListPtr, + DAG.getConstant(1, MVT::i32)); + + // fpr + SDValue FprIndex = DAG.getExtLoad(ISD::ZEXTLOAD, dl, MVT::i32, InChain, + FprPtr, MachinePointerInfo(SV), MVT::i8, + false, false, 0); + InChain = FprIndex.getValue(1); + + SDValue RegSaveAreaPtr = DAG.getNode(ISD::ADD, dl, PtrVT, VAListPtr, + DAG.getConstant(8, MVT::i32)); + + SDValue OverflowAreaPtr = DAG.getNode(ISD::ADD, dl, PtrVT, VAListPtr, + DAG.getConstant(4, MVT::i32)); - llvm_unreachable("VAARG not yet implemented for the SVR4 ABI!"); - return SDValue(); // Not reached + // areas + SDValue OverflowArea = DAG.getLoad(MVT::i32, dl, InChain, OverflowAreaPtr, + MachinePointerInfo(), false, false, 0); + InChain = OverflowArea.getValue(1); + + SDValue RegSaveArea = DAG.getLoad(MVT::i32, dl, InChain, RegSaveAreaPtr, + MachinePointerInfo(), false, false, 0); + InChain = RegSaveArea.getValue(1); + + // select overflow_area if index > 8 + SDValue CC = DAG.getSetCC(dl, MVT::i32, VT.isInteger() ? GprIndex : FprIndex, + DAG.getConstant(8, MVT::i32), ISD::SETLT); + + // adjustment constant gpr_index * 4/8 + SDValue RegConstant = DAG.getNode(ISD::MUL, dl, MVT::i32, + VT.isInteger() ? GprIndex : FprIndex, + DAG.getConstant(VT.isInteger() ? 4 : 8, + MVT::i32)); + + // OurReg = RegSaveArea + RegConstant + SDValue OurReg = DAG.getNode(ISD::ADD, dl, PtrVT, RegSaveArea, + RegConstant); + + // Floating types are 32 bytes into RegSaveArea + if (VT.isFloatingPoint()) + OurReg = DAG.getNode(ISD::ADD, dl, PtrVT, OurReg, + DAG.getConstant(32, MVT::i32)); + + // increase {f,g}pr_index by 1 (or 2 if VT is i64) + SDValue IndexPlus1 = DAG.getNode(ISD::ADD, dl, MVT::i32, + VT.isInteger() ? GprIndex : FprIndex, + DAG.getConstant(VT == MVT::i64 ? 2 : 1, + MVT::i32)); + + InChain = DAG.getTruncStore(InChain, dl, IndexPlus1, + VT.isInteger() ? VAListPtr : FprPtr, + MachinePointerInfo(SV), + MVT::i8, false, false, 0); + + // determine if we should load from reg_save_area or overflow_area + SDValue Result = DAG.getNode(ISD::SELECT, dl, PtrVT, CC, OurReg, OverflowArea); + + // increase overflow_area by 4/8 if gpr/fpr > 8 + SDValue OverflowAreaPlusN = DAG.getNode(ISD::ADD, dl, PtrVT, OverflowArea, + DAG.getConstant(VT.isInteger() ? 4 : 8, + MVT::i32)); + + OverflowArea = DAG.getNode(ISD::SELECT, dl, MVT::i32, CC, OverflowArea, + OverflowAreaPlusN); + + InChain = DAG.getTruncStore(InChain, dl, OverflowArea, + OverflowAreaPtr, + MachinePointerInfo(), + MVT::i32, false, false, 0); + + return DAG.getLoad(VT, dl, InChain, Result, MachinePointerInfo(), false, false, 0); } SDValue PPCTargetLowering::LowerTRAMPOLINE(SDValue Op, @@ -1870,7 +1971,11 @@ PPCTargetLowering::LowerFormalArguments_Darwin( InVals.push_back(FIN); if (ObjSize==1 || ObjSize==2) { if (GPR_idx != Num_GPR_Regs) { - unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); + unsigned VReg; + if (isPPC64) + VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass); + else + VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT); SDValue Store = DAG.getTruncStore(Val.getValue(1), dl, Val, FIN, MachinePointerInfo(), @@ -1889,7 +1994,11 @@ PPCTargetLowering::LowerFormalArguments_Darwin( // to memory. ArgVal will be address of the beginning of // the object. if (GPR_idx != Num_GPR_Regs) { - unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); + unsigned VReg; + if (isPPC64) + VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass); + else + VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); int FI = MFI->CreateFixedObject(PtrByteSize, ArgOffset, true); SDValue FIN = DAG.getFrameIndex(FI, PtrVT); SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT); @@ -2902,6 +3011,12 @@ PPCTargetLowering::LowerCall_SVR4(SDValue Chain, SDValue Callee, Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &MemOpChains[0], MemOpChains.size()); + // Set CR6 to true if this is a vararg call. + if (isVarArg) { + SDValue SetCR(DAG.getMachineNode(PPC::CRSET, dl, MVT::i32), 0); + RegsToPass.push_back(std::make_pair(unsigned(PPC::CR1EQ), SetCR)); + } + // Build a sequence of copy-to-reg nodes chained together with token chain // and flag operands which copy the outgoing args into the appropriate regs. SDValue InFlag; @@ -2911,13 +3026,6 @@ PPCTargetLowering::LowerCall_SVR4(SDValue Chain, SDValue Callee, InFlag = Chain.getValue(1); } - // Set CR6 to true if this is a vararg call. - if (isVarArg) { - SDValue SetCR(DAG.getMachineNode(PPC::CRSET, dl, MVT::i32), 0); - Chain = DAG.getCopyToReg(Chain, dl, PPC::CR1EQ, SetCR, InFlag); - InFlag = Chain.getValue(1); - } - if (isTailCall) PrepareTailCall(DAG, InFlag, Chain, dl, false, SPDiff, NumBytes, LROp, FPOp, false, TailCallArguments); @@ -4422,11 +4530,27 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { void PPCTargetLowering::ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results, SelectionDAG &DAG) const { + const TargetMachine &TM = getTargetMachine(); DebugLoc dl = N->getDebugLoc(); switch (N->getOpcode()) { default: assert(false && "Do not know how to custom type legalize this operation!"); return; + case ISD::VAARG: { + if (!TM.getSubtarget<PPCSubtarget>().isSVR4ABI() + || TM.getSubtarget<PPCSubtarget>().isPPC64()) + return; + + EVT VT = N->getValueType(0); + + if (VT == MVT::i64) { + SDValue NewNode = LowerVAARG(SDValue(N, 1), DAG, PPCSubTarget); + + Results.push_back(NewNode); + Results.push_back(NewNode.getValue(1)); + } + return; + } case ISD::FP_ROUND_INREG: { assert(N->getValueType(0) == MVT::ppcf128); assert(N->getOperand(0).getValueType() == MVT::ppcf128); @@ -4676,7 +4800,7 @@ PPCTargetLowering::EmitPartwordAtomicBinary(MachineInstr *MI, .addReg(TmpReg).addReg(MaskReg); BuildMI(BB, dl, TII->get(is64bit ? PPC::OR8 : PPC::OR), Tmp4Reg) .addReg(Tmp3Reg).addReg(Tmp2Reg); - BuildMI(BB, dl, TII->get(PPC::STWCX)) + BuildMI(BB, dl, TII->get(is64bit ? PPC::STDCX : PPC::STWCX)) .addReg(Tmp4Reg).addReg(ZeroReg).addReg(PtrReg); BuildMI(BB, dl, TII->get(PPC::BCC)) .addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(loopMBB); diff --git a/lib/Target/PowerPC/PPCInstrInfo.cpp b/lib/Target/PowerPC/PPCInstrInfo.cpp index 53b049135e24..143444fdc22b 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -12,22 +12,26 @@ //===----------------------------------------------------------------------===// #include "PPCInstrInfo.h" +#include "PPC.h" #include "PPCInstrBuilder.h" #include "PPCMachineFunctionInfo.h" #include "PPCPredicates.h" -#include "PPCGenInstrInfo.inc" #include "PPCTargetMachine.h" #include "PPCHazardRecognizers.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Target/TargetRegistry.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/MC/MCAsmInfo.h" +#include "llvm/ADT/STLExtras.h" + +#define GET_INSTRINFO_CTOR +#include "PPCGenInstrInfo.inc" namespace llvm { extern cl::opt<bool> EnablePPC32RS; // FIXME (64-bit): See PPCRegisterInfo.cpp. @@ -37,8 +41,8 @@ extern cl::opt<bool> EnablePPC64RS; // FIXME (64-bit): See PPCRegisterInfo.cpp. using namespace llvm; PPCInstrInfo::PPCInstrInfo(PPCTargetMachine &tm) - : TargetInstrInfoImpl(PPCInsts, array_lengthof(PPCInsts)), TM(tm), - RI(*TM.getSubtargetImpl(), *this) {} + : PPCGenInstrInfo(PPC::ADJCALLSTACKDOWN, PPC::ADJCALLSTACKUP), + TM(tm), RI(*TM.getSubtargetImpl(), *this) {} /// CreateTargetHazardRecognizer - Return the hazard recognizer to use for /// this target when scheduling the DAG. @@ -120,7 +124,7 @@ PPCInstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const { // destination register as well. if (Reg0 == Reg1) { // Must be two address instruction! - assert(MI->getDesc().getOperandConstraint(0, TOI::TIED_TO) && + assert(MI->getDesc().getOperandConstraint(0, MCOI::TIED_TO) && "Expecting a two-address instruction!"); Reg2IsKill = false; ChangeReg0 = true; @@ -315,12 +319,12 @@ void PPCInstrInfo::copyPhysReg(MachineBasicBlock &MBB, else llvm_unreachable("Impossible reg-to-reg copy"); - const TargetInstrDesc &TID = get(Opc); - if (TID.getNumOperands() == 3) - BuildMI(MBB, I, DL, TID, DestReg) + const MCInstrDesc &MCID = get(Opc); + if (MCID.getNumOperands() == 3) + BuildMI(MBB, I, DL, MCID, DestReg) .addReg(SrcReg).addReg(SrcReg, getKillRegState(KillSrc)); else - BuildMI(MBB, I, DL, TID, DestReg).addReg(SrcReg, getKillRegState(KillSrc)); + BuildMI(MBB, I, DL, MCID, DestReg).addReg(SrcReg, getKillRegState(KillSrc)); } bool diff --git a/lib/Target/PowerPC/PPCInstrInfo.h b/lib/Target/PowerPC/PPCInstrInfo.h index b5249ae03769..90bacc96c87e 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.h +++ b/lib/Target/PowerPC/PPCInstrInfo.h @@ -18,6 +18,9 @@ #include "llvm/Target/TargetInstrInfo.h" #include "PPCRegisterInfo.h" +#define GET_INSTRINFO_HEADER +#include "PPCGenInstrInfo.inc" + namespace llvm { /// PPCII - This namespace holds all of the PowerPC target-specific @@ -61,7 +64,7 @@ enum PPC970_Unit { } // end namespace PPCII -class PPCInstrInfo : public TargetInstrInfoImpl { +class PPCInstrInfo : public PPCGenInstrInfo { PPCTargetMachine &TM; const PPCRegisterInfo RI; diff --git a/lib/Target/PowerPC/PPCJITInfo.cpp b/lib/Target/PowerPC/PPCJITInfo.cpp index 78383e0603bd..4590f0045641 100644 --- a/lib/Target/PowerPC/PPCJITInfo.cpp +++ b/lib/Target/PowerPC/PPCJITInfo.cpp @@ -87,7 +87,7 @@ asm( // FIXME: could shrink frame // Set up a proper stack frame // FIXME Layout - // PowerPC64 ABI linkage - 24 bytes + // PowerPC32 ABI linkage - 24 bytes // parameters - 32 bytes // 13 double registers - 104 bytes // 8 int registers - 32 bytes @@ -205,11 +205,27 @@ void PPC32CompilationCallback() { #if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \ defined(__ppc64__) +#ifdef __ELF__ +asm( + ".text\n" + ".align 2\n" + ".globl PPC64CompilationCallback\n" + ".section \".opd\",\"aw\"\n" + ".align 3\n" +"PPC64CompilationCallback:\n" + ".quad .L.PPC64CompilationCallback,.TOC.@tocbase,0\n" + ".size PPC64CompilationCallback,24\n" + ".previous\n" + ".align 4\n" + ".type PPC64CompilationCallback,@function\n" +".L.PPC64CompilationCallback:\n" +#else asm( ".text\n" ".align 2\n" ".globl _PPC64CompilationCallback\n" "_PPC64CompilationCallback:\n" +#endif // Make space for 8 ints r[3-10] and 13 doubles f[1-13] and the // FIXME: need to save v[0-19] for altivec? // Set up a proper stack frame @@ -218,49 +234,55 @@ asm( // parameters - 64 bytes // 13 double registers - 104 bytes // 8 int registers - 64 bytes - "mflr r0\n" - "std r0, 16(r1)\n" - "stdu r1, -280(r1)\n" + "mflr 0\n" + "std 0, 16(1)\n" + "stdu 1, -280(1)\n" // Save all int arg registers - "std r10, 272(r1)\n" "std r9, 264(r1)\n" - "std r8, 256(r1)\n" "std r7, 248(r1)\n" - "std r6, 240(r1)\n" "std r5, 232(r1)\n" - "std r4, 224(r1)\n" "std r3, 216(r1)\n" + "std 10, 272(1)\n" "std 9, 264(1)\n" + "std 8, 256(1)\n" "std 7, 248(1)\n" + "std 6, 240(1)\n" "std 5, 232(1)\n" + "std 4, 224(1)\n" "std 3, 216(1)\n" // Save all call-clobbered FP regs. - "stfd f13, 208(r1)\n" "stfd f12, 200(r1)\n" - "stfd f11, 192(r1)\n" "stfd f10, 184(r1)\n" - "stfd f9, 176(r1)\n" "stfd f8, 168(r1)\n" - "stfd f7, 160(r1)\n" "stfd f6, 152(r1)\n" - "stfd f5, 144(r1)\n" "stfd f4, 136(r1)\n" - "stfd f3, 128(r1)\n" "stfd f2, 120(r1)\n" - "stfd f1, 112(r1)\n" + "stfd 13, 208(1)\n" "stfd 12, 200(1)\n" + "stfd 11, 192(1)\n" "stfd 10, 184(1)\n" + "stfd 9, 176(1)\n" "stfd 8, 168(1)\n" + "stfd 7, 160(1)\n" "stfd 6, 152(1)\n" + "stfd 5, 144(1)\n" "stfd 4, 136(1)\n" + "stfd 3, 128(1)\n" "stfd 2, 120(1)\n" + "stfd 1, 112(1)\n" // Arguments to Compilation Callback: // r3 - our lr (address of the call instruction in stub plus 4) // r4 - stub's lr (address of instruction that called the stub plus 4) // r5 - is64Bit - always 1. - "mr r3, r0\n" - "ld r2, 280(r1)\n" // stub's frame - "ld r4, 16(r2)\n" // stub's lr - "li r5, 1\n" // 1 == 64 bit + "mr 3, 0\n" // return address (still in r0) + "ld 5, 280(1)\n" // stub's frame + "ld 4, 16(5)\n" // stub's lr + "li 5, 1\n" // 1 == 64 bit +#ifdef __ELF__ + "bl PPCCompilationCallbackC\n" + "nop\n" +#else "bl _PPCCompilationCallbackC\n" - "mtctr r3\n" +#endif + "mtctr 3\n" // Restore all int arg registers - "ld r10, 272(r1)\n" "ld r9, 264(r1)\n" - "ld r8, 256(r1)\n" "ld r7, 248(r1)\n" - "ld r6, 240(r1)\n" "ld r5, 232(r1)\n" - "ld r4, 224(r1)\n" "ld r3, 216(r1)\n" + "ld 10, 272(1)\n" "ld 9, 264(1)\n" + "ld 8, 256(1)\n" "ld 7, 248(1)\n" + "ld 6, 240(1)\n" "ld 5, 232(1)\n" + "ld 4, 224(1)\n" "ld 3, 216(1)\n" // Restore all FP arg registers - "lfd f13, 208(r1)\n" "lfd f12, 200(r1)\n" - "lfd f11, 192(r1)\n" "lfd f10, 184(r1)\n" - "lfd f9, 176(r1)\n" "lfd f8, 168(r1)\n" - "lfd f7, 160(r1)\n" "lfd f6, 152(r1)\n" - "lfd f5, 144(r1)\n" "lfd f4, 136(r1)\n" - "lfd f3, 128(r1)\n" "lfd f2, 120(r1)\n" - "lfd f1, 112(r1)\n" + "lfd 13, 208(1)\n" "lfd 12, 200(1)\n" + "lfd 11, 192(1)\n" "lfd 10, 184(1)\n" + "lfd 9, 176(1)\n" "lfd 8, 168(1)\n" + "lfd 7, 160(1)\n" "lfd 6, 152(1)\n" + "lfd 5, 144(1)\n" "lfd 4, 136(1)\n" + "lfd 3, 128(1)\n" "lfd 2, 120(1)\n" + "lfd 1, 112(1)\n" // Pop 3 frames off the stack and branch to target - "ld r1, 280(r1)\n" - "ld r2, 16(r1)\n" - "mtlr r2\n" + "ld 1, 280(1)\n" + "ld 0, 16(1)\n" + "mtlr 0\n" + // XXX: any special TOC handling in the ELF case for JIT? "bctr\n" ); #else diff --git a/lib/Target/PowerPC/PPCMCCodeEmitter.cpp b/lib/Target/PowerPC/PPCMCCodeEmitter.cpp index 65c2c82c51a7..cf73d861fa4d 100644 --- a/lib/Target/PowerPC/PPCMCCodeEmitter.cpp +++ b/lib/Target/PowerPC/PPCMCCodeEmitter.cpp @@ -28,12 +28,10 @@ namespace { class PPCMCCodeEmitter : public MCCodeEmitter { PPCMCCodeEmitter(const PPCMCCodeEmitter &); // DO NOT IMPLEMENT void operator=(const PPCMCCodeEmitter &); // DO NOT IMPLEMENT - const TargetMachine &TM; - MCContext &Ctx; public: - PPCMCCodeEmitter(TargetMachine &tm, MCContext &ctx) - : TM(tm), Ctx(ctx) { + PPCMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti, + MCContext &ctx) { } ~PPCMCCodeEmitter() {} @@ -79,9 +77,10 @@ public: } // end anonymous namespace -MCCodeEmitter *llvm::createPPCMCCodeEmitter(const Target &, TargetMachine &TM, +MCCodeEmitter *llvm::createPPCMCCodeEmitter(const MCInstrInfo &MCII, + const MCSubtargetInfo &STI, MCContext &Ctx) { - return new PPCMCCodeEmitter(TM, Ctx); + return new PPCMCCodeEmitter(MCII, STI, Ctx); } unsigned PPCMCCodeEmitter:: diff --git a/lib/Target/PowerPC/PPCRegisterInfo.cpp b/lib/Target/PowerPC/PPCRegisterInfo.cpp index 3374e9b0b631..9c2428b92e65 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -44,6 +44,9 @@ #include "llvm/ADT/STLExtras.h" #include <cstdlib> +#define GET_REGINFO_TARGET_DESC +#include "PPCGenRegisterInfo.inc" + // FIXME (64-bit): Eventually enable by default. namespace llvm { cl::opt<bool> EnablePPC32RS("enable-ppc32-regscavenger", @@ -110,8 +113,7 @@ unsigned PPCRegisterInfo::getRegisterNumbering(unsigned RegEnum) { PPCRegisterInfo::PPCRegisterInfo(const PPCSubtarget &ST, const TargetInstrInfo &tii) - : PPCGenRegisterInfo(PPC::ADJCALLSTACKDOWN, PPC::ADJCALLSTACKUP), - Subtarget(ST), TII(tii) { + : PPCGenRegisterInfo(), Subtarget(ST), TII(tii) { ImmToIdxMap[PPC::LD] = PPC::LDX; ImmToIdxMap[PPC::STD] = PPC::STDX; ImmToIdxMap[PPC::LBZ] = PPC::LBZX; ImmToIdxMap[PPC::STB] = PPC::STBX; ImmToIdxMap[PPC::LHZ] = PPC::LHZX; ImmToIdxMap[PPC::LHA] = PPC::LHAX; @@ -504,6 +506,7 @@ void PPCRegisterInfo::lowerCRSpilling(MachineBasicBlock::iterator II, const TargetRegisterClass *RC = Subtarget.isPPC64() ? G8RC : GPRC; unsigned Reg = findScratchRegister(II, RS, RC, SPAdj); unsigned SrcReg = MI.getOperand(0).getReg(); + bool LP64 = Subtarget.isPPC64(); // We need to store the CR in the low 4-bits of the saved value. First, issue // an MFCRpsued to save all of the CRBits and, if needed, kill the SrcReg. @@ -520,7 +523,7 @@ void PPCRegisterInfo::lowerCRSpilling(MachineBasicBlock::iterator II, .addImm(0) .addImm(31); - addFrameReference(BuildMI(MBB, II, dl, TII.get(PPC::STW)) + addFrameReference(BuildMI(MBB, II, dl, TII.get(LP64 ? PPC::STW8 : PPC::STW)) .addReg(Reg, getKillRegState(MI.getOperand(1).getImm())), FrameIndex); @@ -709,5 +712,3 @@ int PPCRegisterInfo::getLLVMRegNum(unsigned RegNum, bool isEH) const { return PPCGenRegisterInfo::getLLVMRegNumFull(RegNum, Flavour); } - -#include "PPCGenRegisterInfo.inc" diff --git a/lib/Target/PowerPC/PPCRegisterInfo.h b/lib/Target/PowerPC/PPCRegisterInfo.h index 48c25625ea9b..33fe5ebcf4cd 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.h +++ b/lib/Target/PowerPC/PPCRegisterInfo.h @@ -16,9 +16,11 @@ #define POWERPC32_REGISTERINFO_H #include "PPC.h" -#include "PPCGenRegisterInfo.h.inc" #include <map> +#define GET_REGINFO_HEADER +#include "PPCGenRegisterInfo.inc" + namespace llvm { class PPCSubtarget; class TargetInstrInfo; diff --git a/lib/Target/PowerPC/PPCRegisterInfo.td b/lib/Target/PowerPC/PPCRegisterInfo.td index 3c0190199a82..1acdf4eb853b 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.td +++ b/lib/Target/PowerPC/PPCRegisterInfo.td @@ -276,15 +276,13 @@ def RM: SPR<512, "**ROUNDING MODE**">; /// Register classes // Allocate volatiles first // then nonvolatiles in reverse order since stmw/lmw save from rN to r31 -def GPRC : RegisterClass<"PPC", [i32], 32, - [R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, - R30, R29, R28, R27, R26, R25, R24, R23, R22, R21, R20, R19, R18, R17, - R16, R15, R14, R13, R31, R0, R1, LR]>; +def GPRC : RegisterClass<"PPC", [i32], 32, (add (sequence "R%u", 2, 12), + (sequence "R%u", 30, 13), + R31, R0, R1, LR)>; -def G8RC : RegisterClass<"PPC", [i64], 64, - [X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, - X30, X29, X28, X27, X26, X25, X24, X23, X22, X21, X20, X19, X18, X17, - X16, X15, X14, X31, X13, X0, X1, LR8]>; +def G8RC : RegisterClass<"PPC", [i64], 64, (add (sequence "X%u", 2, 12), + (sequence "X%u", 30, 14), + X31, X13, X0, X1, LR8)>; // Allocate volatiles first, then non-volatiles in reverse order. With the SVR4 // ABI the size of the Floating-point register save area is determined by the @@ -293,41 +291,36 @@ def G8RC : RegisterClass<"PPC", [i64], 64, // previous stack frame. By allocating non-volatiles in reverse order we make // sure that the Floating-point register save area is always as small as // possible because there aren't any unused spill slots. -def F8RC : RegisterClass<"PPC", [f64], 64, [F0, F1, F2, F3, F4, F5, F6, F7, - F8, F9, F10, F11, F12, F13, F31, F30, F29, F28, F27, F26, F25, F24, F23, - F22, F21, F20, F19, F18, F17, F16, F15, F14]>; -def F4RC : RegisterClass<"PPC", [f32], 32, [F0, F1, F2, F3, F4, F5, F6, F7, - F8, F9, F10, F11, F12, F13, F31, F30, F29, F28, F27, F26, F25, F24, F23, - F22, F21, F20, F19, F18, F17, F16, F15, F14]>; +def F8RC : RegisterClass<"PPC", [f64], 64, (add (sequence "F%u", 0, 13), + (sequence "F%u", 31, 14))>; +def F4RC : RegisterClass<"PPC", [f32], 32, (add F8RC)>; def VRRC : RegisterClass<"PPC", [v16i8,v8i16,v4i32,v4f32], 128, - [V2, V3, V4, V5, V0, V1, - V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V31, V30, - V29, V28, V27, V26, V25, V24, V23, V22, V21, V20]>; + (add V2, V3, V4, V5, V0, V1, V6, V7, V8, V9, V10, V11, + V12, V13, V14, V15, V16, V17, V18, V19, V31, V30, + V29, V28, V27, V26, V25, V24, V23, V22, V21, V20)>; def CRBITRC : RegisterClass<"PPC", [i32], 32, - [CR0LT, CR0GT, CR0EQ, CR0UN, - CR1LT, CR1GT, CR1EQ, CR1UN, - CR2LT, CR2GT, CR2EQ, CR2UN, - CR3LT, CR3GT, CR3EQ, CR3UN, - CR4LT, CR4GT, CR4EQ, CR4UN, - CR5LT, CR5GT, CR5EQ, CR5UN, - CR6LT, CR6GT, CR6EQ, CR6UN, - CR7LT, CR7GT, CR7EQ, CR7UN - ]> + (add CR0LT, CR0GT, CR0EQ, CR0UN, + CR1LT, CR1GT, CR1EQ, CR1UN, + CR2LT, CR2GT, CR2EQ, CR2UN, + CR3LT, CR3GT, CR3EQ, CR3UN, + CR4LT, CR4GT, CR4EQ, CR4UN, + CR5LT, CR5GT, CR5EQ, CR5UN, + CR6LT, CR6GT, CR6EQ, CR6UN, + CR7LT, CR7GT, CR7EQ, CR7UN)> { let CopyCost = -1; } -def CRRC : RegisterClass<"PPC", [i32], 32, [CR0, CR1, CR5, CR6, CR7, CR2, - CR3, CR4]> -{ +def CRRC : RegisterClass<"PPC", [i32], 32, (add CR0, CR1, CR5, CR6, + CR7, CR2, CR3, CR4)> { let SubRegClasses = [(CRBITRC sub_lt, sub_gt, sub_eq, sub_un)]; } -def CTRRC : RegisterClass<"PPC", [i32], 32, [CTR]>; -def CTRRC8 : RegisterClass<"PPC", [i64], 64, [CTR8]>; -def VRSAVERC : RegisterClass<"PPC", [i32], 32, [VRSAVE]>; -def CARRYRC : RegisterClass<"PPC", [i32], 32, [CARRY]> { +def CTRRC : RegisterClass<"PPC", [i32], 32, (add CTR)>; +def CTRRC8 : RegisterClass<"PPC", [i64], 64, (add CTR8)>; +def VRSAVERC : RegisterClass<"PPC", [i32], 32, (add VRSAVE)>; +def CARRYRC : RegisterClass<"PPC", [i32], 32, (add CARRY)> { let CopyCost = -1; } diff --git a/lib/Target/PowerPC/PPCSubtarget.cpp b/lib/Target/PowerPC/PPCSubtarget.cpp index 5f3aa2328f9e..5ea9b0f6596c 100644 --- a/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/lib/Target/PowerPC/PPCSubtarget.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file implements the PPC specific subclass of TargetSubtarget. +// This file implements the PPC specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// @@ -15,8 +15,13 @@ #include "PPC.h" #include "llvm/GlobalValue.h" #include "llvm/Target/TargetMachine.h" -#include "PPCGenSubtarget.inc" +#include "llvm/Target/TargetRegistry.h" #include <cstdlib> + +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "PPCGenSubtargetInfo.inc" + using namespace llvm; #if defined(__APPLE__) @@ -57,9 +62,10 @@ static const char *GetCurrentPowerPCCPU() { #endif -PPCSubtarget::PPCSubtarget(const std::string &TT, const std::string &FS, - bool is64Bit) - : StackAlignment(16) +PPCSubtarget::PPCSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, bool is64Bit) + : PPCGenSubtargetInfo(TT, CPU, FS) + , StackAlignment(16) , DarwinDirective(PPC::DIR_NONE) , IsGigaProcessor(false) , Has64BitSupport(false) @@ -73,13 +79,19 @@ PPCSubtarget::PPCSubtarget(const std::string &TT, const std::string &FS, , TargetTriple(TT) { // Determine default and user specified characteristics - std::string CPU = "generic"; + std::string CPUName = CPU; + if (CPUName.empty()) + CPUName = "generic"; #if defined(__APPLE__) - CPU = GetCurrentPowerPCCPU(); + if (CPUName == "generic") + CPUName = GetCurrentPowerPCCPU(); #endif // Parse features string. - ParseSubtargetFeatures(FS, CPU); + ParseSubtargetFeatures(CPUName, FS); + + // Initialize scheduling itinerary for the specified CPU. + InstrItins = getInstrItineraryForCPU(CPUName); // If we are generating code for ppc64, verify that options make sense. if (is64Bit) { diff --git a/lib/Target/PowerPC/PPCSubtarget.h b/lib/Target/PowerPC/PPCSubtarget.h index 8fd1a447692d..e028de6b09de 100644 --- a/lib/Target/PowerPC/PPCSubtarget.h +++ b/lib/Target/PowerPC/PPCSubtarget.h @@ -7,23 +7,26 @@ // //===----------------------------------------------------------------------===// // -// This file declares the PowerPC specific subclass of TargetSubtarget. +// This file declares the PowerPC specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #ifndef POWERPCSUBTARGET_H #define POWERPCSUBTARGET_H +#include "llvm/Target/TargetSubtargetInfo.h" +#include "llvm/MC/MCInstrItineraries.h" #include "llvm/ADT/Triple.h" -#include "llvm/Target/TargetInstrItineraries.h" -#include "llvm/Target/TargetSubtarget.h" - #include <string> +#define GET_SUBTARGETINFO_HEADER +#include "PPCGenSubtargetInfo.inc" + // GCC #defines PPC on Linux but we use it as our namespace name #undef PPC namespace llvm { +class StringRef; namespace PPC { // -m directive values. @@ -43,7 +46,7 @@ namespace PPC { class GlobalValue; class TargetMachine; -class PPCSubtarget : public TargetSubtarget { +class PPCSubtarget : public PPCGenSubtargetInfo { protected: /// stackAlignment - The minimum alignment known to hold of the stack frame on /// entry to the function and which must be maintained by every function. @@ -73,13 +76,12 @@ public: /// This constructor initializes the data members to match that /// of the specified triple. /// - PPCSubtarget(const std::string &TT, const std::string &FS, bool is64Bit); + PPCSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, bool is64Bit); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); - + void ParseSubtargetFeatures(StringRef CPU, StringRef FS); /// SetJITMode - This is called to inform the subtarget info that we are /// producing code for the JIT. @@ -104,7 +106,7 @@ public: // Note, the alignment values for f64 and i64 on ppc64 in Darwin // documentation are wrong; these are correct (i.e. "what gcc does"). return isPPC64() ? "E-p:64:64-f64:64:64-i64:64:64-f128:64:128-n32:64" - : "E-p:32:32-f64:32:64-i64:32:64-f128:64:128-n32"; + : "E-p:32:32-f64:64:64-i64:64:64-f128:64:128-n32"; } /// isPPC64 - Return true if we are generating code for 64-bit pointer mode. diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp index d27e54e56699..e0ea5adba751 100644 --- a/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "PPC.h" -#include "PPCMCAsmInfo.h" #include "PPCTargetMachine.h" #include "llvm/PassManager.h" #include "llvm/MC/MCStreamer.h" @@ -21,15 +20,6 @@ #include "llvm/Support/FormattedStream.h" using namespace llvm; -static MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) { - Triple TheTriple(TT); - bool isPPC64 = TheTriple.getArch() == Triple::ppc64; - if (TheTriple.isOSDarwin()) - return new PPCMCAsmInfoDarwin(isPPC64); - return new PPCLinuxMCAsmInfo(isPPC64); - -} - // This is duplicated code. Refactor this. static MCStreamer *createMCStreamer(const Target &T, const std::string &TT, MCContext &Ctx, TargetAsmBackend &TAB, @@ -48,9 +38,6 @@ extern "C" void LLVMInitializePowerPCTarget() { RegisterTargetMachine<PPC32TargetMachine> A(ThePPC32Target); RegisterTargetMachine<PPC64TargetMachine> B(ThePPC64Target); - RegisterAsmInfoFn C(ThePPC32Target, createMCAsmInfo); - RegisterAsmInfoFn D(ThePPC64Target, createMCAsmInfo); - // Register the MC Code Emitter TargetRegistry::RegisterCodeEmitter(ThePPC32Target, createPPCMCCodeEmitter); TargetRegistry::RegisterCodeEmitter(ThePPC64Target, createPPCMCCodeEmitter); @@ -67,9 +54,10 @@ extern "C" void LLVMInitializePowerPCTarget() { PPCTargetMachine::PPCTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS, bool is64Bit) - : LLVMTargetMachine(T, TT), - Subtarget(TT, FS, is64Bit), + : LLVMTargetMachine(T, TT, CPU, FS), + Subtarget(TT, CPU, FS, is64Bit), DataLayout(Subtarget.getTargetDataString()), InstrInfo(*this), FrameLowering(Subtarget), JITInfo(*this, is64Bit), TLInfo(*this), TSInfo(*this), @@ -88,14 +76,16 @@ PPCTargetMachine::PPCTargetMachine(const Target &T, const std::string &TT, bool PPCTargetMachine::getEnableTailMergeDefault() const { return false; } PPC32TargetMachine::PPC32TargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) - : PPCTargetMachine(T, TT, FS, false) { + : PPCTargetMachine(T, TT, CPU, FS, false) { } PPC64TargetMachine::PPC64TargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) - : PPCTargetMachine(T, TT, FS, true) { + : PPCTargetMachine(T, TT, CPU, FS, true) { } diff --git a/lib/Target/PowerPC/PPCTargetMachine.h b/lib/Target/PowerPC/PPCTargetMachine.h index 2d2498943a2d..baf07e3498f8 100644 --- a/lib/Target/PowerPC/PPCTargetMachine.h +++ b/lib/Target/PowerPC/PPCTargetMachine.h @@ -41,7 +41,8 @@ class PPCTargetMachine : public LLVMTargetMachine { public: PPCTargetMachine(const Target &T, const std::string &TT, - const std::string &FS, bool is64Bit); + const std::string &CPU, const std::string &FS, + bool is64Bit); virtual const PPCInstrInfo *getInstrInfo() const { return &InstrInfo; } virtual const PPCFrameLowering *getFrameLowering() const { @@ -77,7 +78,7 @@ public: class PPC32TargetMachine : public PPCTargetMachine { public: PPC32TargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); }; /// PPC64TargetMachine - PowerPC 64-bit target machine. @@ -85,7 +86,7 @@ public: class PPC64TargetMachine : public PPCTargetMachine { public: PPC64TargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); }; } // end namespace llvm diff --git a/lib/Target/README.txt b/lib/Target/README.txt index fcec368a213b..4cc95340890d 100644 --- a/lib/Target/README.txt +++ b/lib/Target/README.txt @@ -870,11 +870,6 @@ rshift_gt (unsigned int a) bar (); } -void neg_eq_cst(unsigned int a) { -if (-a == 123) -bar(); -} - All should simplify to a single comparison. All of these are currently not optimized with "clang -emit-llvm-bc | opt -std-compile-opts". @@ -1767,7 +1762,6 @@ case it choses instead to keep the max operation obvious. //===---------------------------------------------------------------------===// -Switch lowering generates less than ideal code for the following switch: define void @a(i32 %x) nounwind { entry: switch i32 %x, label %if.end [ @@ -1788,19 +1782,15 @@ declare void @foo() Generated code on x86-64 (other platforms give similar results): a: cmpl $5, %edi - ja .LBB0_2 - movl %edi, %eax - movl $47, %ecx - btq %rax, %rcx - jb .LBB0_3 + ja LBB2_2 + cmpl $4, %edi + jne LBB2_3 .LBB0_2: ret .LBB0_3: jmp foo # TAILCALL -The movl+movl+btq+jb could be simplified to a cmpl+jne. - -Or, if we wanted to be really clever, we could simplify the whole thing to +If we wanted to be really clever, we could simplify the whole thing to something like the following, which eliminates a branch: xorl $1, %edi cmpl $4, %edi diff --git a/lib/Target/Sparc/CMakeLists.txt b/lib/Target/Sparc/CMakeLists.txt index 6839234a4700..c77ded4b435e 100644 --- a/lib/Target/Sparc/CMakeLists.txt +++ b/lib/Target/Sparc/CMakeLists.txt @@ -1,13 +1,10 @@ set(LLVM_TARGET_DEFINITIONS Sparc.td) -tablegen(SparcGenRegisterInfo.h.inc -gen-register-desc-header) -tablegen(SparcGenRegisterNames.inc -gen-register-enums) -tablegen(SparcGenRegisterInfo.inc -gen-register-desc) -tablegen(SparcGenInstrNames.inc -gen-instr-enums) -tablegen(SparcGenInstrInfo.inc -gen-instr-desc) +tablegen(SparcGenRegisterInfo.inc -gen-register-info) +tablegen(SparcGenInstrInfo.inc -gen-instr-info) tablegen(SparcGenAsmWriter.inc -gen-asm-writer) tablegen(SparcGenDAGISel.inc -gen-dag-isel) -tablegen(SparcGenSubtarget.inc -gen-subtarget) +tablegen(SparcGenSubtargetInfo.inc -gen-subtarget) tablegen(SparcGenCallingConv.inc -gen-callingconv) add_llvm_target(SparcCodeGen @@ -18,7 +15,6 @@ add_llvm_target(SparcCodeGen SparcISelDAGToDAG.cpp SparcISelLowering.cpp SparcFrameLowering.cpp - SparcMCAsmInfo.cpp SparcRegisterInfo.cpp SparcSubtarget.cpp SparcTargetMachine.cpp @@ -26,3 +22,4 @@ add_llvm_target(SparcCodeGen ) add_subdirectory(TargetInfo) +add_subdirectory(MCTargetDesc) diff --git a/lib/Target/Sparc/DelaySlotFiller.cpp b/lib/Target/Sparc/DelaySlotFiller.cpp index 4b12852ef873..dab35e5e4e6f 100644 --- a/lib/Target/Sparc/DelaySlotFiller.cpp +++ b/lib/Target/Sparc/DelaySlotFiller.cpp @@ -298,7 +298,7 @@ bool Filler::isDelayFiller(MachineBasicBlock &MBB, return false; if (candidate->getOpcode() == SP::UNIMP) return true; - const TargetInstrDesc &prevdesc = (--candidate)->getDesc(); + const MCInstrDesc &prevdesc = (--candidate)->getDesc(); return prevdesc.hasDelaySlot(); } diff --git a/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt b/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt new file mode 100644 index 000000000000..1e8c02979887 --- /dev/null +++ b/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt @@ -0,0 +1,4 @@ +add_llvm_library(LLVMSparcDesc + SparcMCTargetDesc.cpp + SparcMCAsmInfo.cpp + ) diff --git a/lib/Target/Sparc/MCTargetDesc/Makefile b/lib/Target/Sparc/MCTargetDesc/Makefile new file mode 100644 index 000000000000..abcbe2da18ec --- /dev/null +++ b/lib/Target/Sparc/MCTargetDesc/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/Sparc/TargetDesc/Makefile ----------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +LIBRARYNAME = LLVMSparcDesc + +# Hack: we need to include 'main' target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/Sparc/SparcMCAsmInfo.cpp b/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp index d37d6d231305..6a7e0902354e 100644 --- a/lib/Target/Sparc/SparcMCAsmInfo.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp @@ -12,9 +12,16 @@ //===----------------------------------------------------------------------===// #include "SparcMCAsmInfo.h" +#include "llvm/ADT/Triple.h" + using namespace llvm; SparcELFMCAsmInfo::SparcELFMCAsmInfo(const Target &T, StringRef TT) { + IsLittleEndian = false; + Triple TheTriple(TT); + if (TheTriple.getArch() == Triple::sparcv9) + PointerSize = 8; + Data16bitsDirective = "\t.half\t"; Data32bitsDirective = "\t.word\t"; Data64bitsDirective = 0; // .xword is only supported by V9. diff --git a/lib/Target/Sparc/SparcMCAsmInfo.h b/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h index 0cb6827d2771..0cb6827d2771 100644 --- a/lib/Target/Sparc/SparcMCAsmInfo.h +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp new file mode 100644 index 000000000000..cb92a2bfd417 --- /dev/null +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp @@ -0,0 +1,57 @@ +//===-- SparcMCTargetDesc.cpp - Sparc Target Descriptions --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Sparc specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#include "SparcMCTargetDesc.h" +#include "SparcMCAsmInfo.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Target/TargetRegistry.h" + +#define GET_INSTRINFO_MC_DESC +#include "SparcGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_MC_DESC +#include "SparcGenSubtargetInfo.inc" + +#define GET_REGINFO_MC_DESC +#include "SparcGenRegisterInfo.inc" + +using namespace llvm; + +static MCInstrInfo *createSparcMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitSparcMCInstrInfo(X); + return X; +} + +extern "C" void LLVMInitializeSparcMCInstrInfo() { + TargetRegistry::RegisterMCInstrInfo(TheSparcTarget, createSparcMCInstrInfo); +} + +static MCSubtargetInfo *createSparcMCSubtargetInfo(StringRef TT, StringRef CPU, + StringRef FS) { + MCSubtargetInfo *X = new MCSubtargetInfo(); + InitSparcMCSubtargetInfo(X, TT, CPU, FS); + return X; +} + +extern "C" void LLVMInitializeSparcMCSubtargetInfo() { + TargetRegistry::RegisterMCSubtargetInfo(TheSparcTarget, + createSparcMCSubtargetInfo); +} + +extern "C" void LLVMInitializeSparcMCAsmInfo() { + RegisterMCAsmInfo<SparcELFMCAsmInfo> X(TheSparcTarget); + RegisterMCAsmInfo<SparcELFMCAsmInfo> Y(TheSparcV9Target); +} diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h new file mode 100644 index 000000000000..2fd9e3f4cbd3 --- /dev/null +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h @@ -0,0 +1,41 @@ +//===-- SparcMCTargetDesc.h - Sparc Target Descriptions ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Sparc specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#ifndef SPARCMCTARGETDESC_H +#define SPARCMCTARGETDESC_H + +namespace llvm { +class MCSubtargetInfo; +class Target; +class StringRef; + +extern Target TheSparcTarget; +extern Target TheSparcV9Target; + +} // End llvm namespace + +// Defines symbolic names for Sparc registers. This defines a mapping from +// register name to register number. +// +#define GET_REGINFO_ENUM +#include "SparcGenRegisterInfo.inc" + +// Defines symbolic names for the Sparc instructions. +// +#define GET_INSTRINFO_ENUM +#include "SparcGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "SparcGenSubtargetInfo.inc" + +#endif diff --git a/lib/Target/Sparc/Makefile b/lib/Target/Sparc/Makefile index 27942c56fb3a..4b81ada956f2 100644 --- a/lib/Target/Sparc/Makefile +++ b/lib/Target/Sparc/Makefile @@ -12,12 +12,11 @@ LIBRARYNAME = LLVMSparcCodeGen TARGET = Sparc # Make sure that tblgen is run, first thing. -BUILT_SOURCES = SparcGenRegisterInfo.h.inc SparcGenRegisterNames.inc \ - SparcGenRegisterInfo.inc SparcGenInstrNames.inc \ - SparcGenInstrInfo.inc SparcGenAsmWriter.inc \ - SparcGenDAGISel.inc SparcGenSubtarget.inc SparcGenCallingConv.inc +BUILT_SOURCES = SparcGenRegisterInfo.inc SparcGenInstrInfo.inc \ + SparcGenAsmWriter.inc SparcGenDAGISel.inc \ + SparcGenSubtargetInfo.inc SparcGenCallingConv.inc -DIRS = TargetInfo +DIRS = TargetInfo MCTargetDesc include $(LEVEL)/Makefile.common diff --git a/lib/Target/Sparc/Sparc.h b/lib/Target/Sparc/Sparc.h index a37920d80308..7b2c6141dbf8 100644 --- a/lib/Target/Sparc/Sparc.h +++ b/lib/Target/Sparc/Sparc.h @@ -15,6 +15,7 @@ #ifndef TARGET_SPARC_H #define TARGET_SPARC_H +#include "MCTargetDesc/SparcMCTargetDesc.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Target/TargetMachine.h" #include <cassert> @@ -28,21 +29,8 @@ namespace llvm { FunctionPass *createSparcDelaySlotFillerPass(TargetMachine &TM); FunctionPass *createSparcFPMoverPass(TargetMachine &TM); - extern Target TheSparcTarget; - extern Target TheSparcV9Target; - } // end namespace llvm; -// Defines symbolic names for Sparc registers. This defines a mapping from -// register name to register number. -// -#include "SparcGenRegisterNames.inc" - -// Defines symbolic names for the Sparc instructions. -// -#include "SparcGenInstrNames.inc" - - namespace llvm { // Enums corresponding to Sparc condition codes, both icc's and fcc's. These // values must be kept in sync with the ones in the .td file. diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp index 0b4612df4e43..6f30d3fd6c35 100644 --- a/lib/Target/Sparc/SparcISelLowering.cpp +++ b/lib/Target/Sparc/SparcISelLowering.cpp @@ -1,4 +1,3 @@ - //===-- SparcISelLowering.cpp - Sparc DAG Lowering Implementation ---------===// // // The LLVM Compiler Infrastructure @@ -755,9 +754,11 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM) setOperationAction(ISD::FSIN , MVT::f64, Expand); setOperationAction(ISD::FCOS , MVT::f64, Expand); setOperationAction(ISD::FREM , MVT::f64, Expand); + setOperationAction(ISD::FMA , MVT::f64, Expand); setOperationAction(ISD::FSIN , MVT::f32, Expand); setOperationAction(ISD::FCOS , MVT::f32, Expand); setOperationAction(ISD::FREM , MVT::f32, Expand); + setOperationAction(ISD::FMA , MVT::f32, Expand); setOperationAction(ISD::CTPOP, MVT::i32, Expand); setOperationAction(ISD::CTTZ , MVT::i32, Expand); setOperationAction(ISD::CTLZ , MVT::i32, Expand); @@ -1265,26 +1266,6 @@ SparcTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); } -std::vector<unsigned> SparcTargetLowering:: -getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const { - if (Constraint.size() != 1) - return std::vector<unsigned>(); - - switch (Constraint[0]) { - default: break; - case 'r': - return make_vector<unsigned>(SP::L0, SP::L1, SP::L2, SP::L3, - SP::L4, SP::L5, SP::L6, SP::L7, - SP::I0, SP::I1, SP::I2, SP::I3, - SP::I4, SP::I5, - SP::O0, SP::O1, SP::O2, SP::O3, - SP::O4, SP::O5, SP::O7, 0); - } - - return std::vector<unsigned>(); -} - bool SparcTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { // The Sparc target isn't yet aware of offsets. diff --git a/lib/Target/Sparc/SparcISelLowering.h b/lib/Target/Sparc/SparcISelLowering.h index 9ea6e16e3ac1..8a1886a856e0 100644 --- a/lib/Target/Sparc/SparcISelLowering.h +++ b/lib/Target/Sparc/SparcISelLowering.h @@ -65,9 +65,6 @@ namespace llvm { ConstraintType getConstraintType(const std::string &Constraint) const; std::pair<unsigned, const TargetRegisterClass*> getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; - std::vector<unsigned> - getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const; virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; diff --git a/lib/Target/Sparc/SparcInstrInfo.cpp b/lib/Target/Sparc/SparcInstrInfo.cpp index afa3c1f88f96..4e3ddf839985 100644 --- a/lib/Target/Sparc/SparcInstrInfo.cpp +++ b/lib/Target/Sparc/SparcInstrInfo.cpp @@ -12,19 +12,23 @@ //===----------------------------------------------------------------------===// #include "SparcInstrInfo.h" -#include "SparcSubtarget.h" #include "Sparc.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" +#include "SparcMachineFunctionInfo.h" +#include "SparcSubtarget.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetRegistry.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" + +#define GET_INSTRINFO_CTOR #include "SparcGenInstrInfo.inc" -#include "SparcMachineFunctionInfo.h" + using namespace llvm; SparcInstrInfo::SparcInstrInfo(SparcSubtarget &ST) - : TargetInstrInfoImpl(SparcInsts, array_lengthof(SparcInsts)), + : SparcGenInstrInfo(SP::ADJCALLSTACKDOWN, SP::ADJCALLSTACKUP), RI(ST, *this), Subtarget(ST) { } diff --git a/lib/Target/Sparc/SparcInstrInfo.h b/lib/Target/Sparc/SparcInstrInfo.h index b2d24f52503b..eda64efb7a03 100644 --- a/lib/Target/Sparc/SparcInstrInfo.h +++ b/lib/Target/Sparc/SparcInstrInfo.h @@ -17,6 +17,9 @@ #include "llvm/Target/TargetInstrInfo.h" #include "SparcRegisterInfo.h" +#define GET_INSTRINFO_HEADER +#include "SparcGenInstrInfo.inc" + namespace llvm { /// SPII - This namespace holds all of the target specific flags that @@ -31,7 +34,7 @@ namespace SPII { }; } -class SparcInstrInfo : public TargetInstrInfoImpl { +class SparcInstrInfo : public SparcGenInstrInfo { const SparcRegisterInfo RI; const SparcSubtarget& Subtarget; public: diff --git a/lib/Target/Sparc/SparcRegisterInfo.cpp b/lib/Target/Sparc/SparcRegisterInfo.cpp index 9fcf028fa60e..0acdd2c55d6b 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.cpp +++ b/lib/Target/Sparc/SparcRegisterInfo.cpp @@ -23,12 +23,15 @@ #include "llvm/Type.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" + +#define GET_REGINFO_TARGET_DESC +#include "SparcGenRegisterInfo.inc" + using namespace llvm; SparcRegisterInfo::SparcRegisterInfo(SparcSubtarget &st, const TargetInstrInfo &tii) - : SparcGenRegisterInfo(SP::ADJCALLSTACKDOWN, SP::ADJCALLSTACKUP), - Subtarget(st), TII(tii) { + : SparcGenRegisterInfo(), Subtarget(st), TII(tii) { } const unsigned* SparcRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) @@ -135,6 +138,3 @@ int SparcRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const { int SparcRegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const { return SparcGenRegisterInfo::getLLVMRegNumFull(DwarfRegNo,0); } - -#include "SparcGenRegisterInfo.inc" - diff --git a/lib/Target/Sparc/SparcRegisterInfo.h b/lib/Target/Sparc/SparcRegisterInfo.h index 56c8068228f0..ec9e63a686bc 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.h +++ b/lib/Target/Sparc/SparcRegisterInfo.h @@ -15,7 +15,9 @@ #define SPARCREGISTERINFO_H #include "llvm/Target/TargetRegisterInfo.h" -#include "SparcGenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "SparcGenRegisterInfo.inc" namespace llvm { diff --git a/lib/Target/Sparc/SparcRegisterInfo.td b/lib/Target/Sparc/SparcRegisterInfo.td index 0729818e85b8..cf928293c169 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.td +++ b/lib/Target/Sparc/SparcRegisterInfo.td @@ -139,23 +139,21 @@ def D15 : Rd<30, "F30", [F30, F31]>, DwarfRegNum<[87]>; // FIXME: the register order should be defined in terms of the preferred // allocation order... // -def IntRegs : RegisterClass<"SP", [i32], 32, [L0, L1, L2, L3, L4, L5, L6, L7, - I0, I1, I2, I3, I4, I5, - O0, O1, O2, O3, O4, O5, O7, - G1, - // Non-allocatable regs: - G2, G3, G4, // FIXME: OK for use only in - // applications, not libraries. - O6, // stack ptr - I6, // frame ptr - I7, // return address - G0, // constant zero - G5, G6, G7 // reserved for kernel - ]>; +def IntRegs : RegisterClass<"SP", [i32], 32, + (add L0, L1, L2, L3, L4, L5, L6, + L7, I0, I1, I2, I3, I4, I5, + O0, O1, O2, O3, O4, O5, O7, + G1, + // Non-allocatable regs: + G2, G3, G4, // FIXME: OK for use only in + // applications, not libraries. + O6, // stack ptr + I6, // frame ptr + I7, // return address + G0, // constant zero + G5, G6, G7 // reserved for kernel + )>; -def FPRegs : RegisterClass<"SP", [f32], 32, [F0, F1, F2, F3, F4, F5, F6, F7, F8, - F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, - F23, F24, F25, F26, F27, F28, F29, F30, F31]>; +def FPRegs : RegisterClass<"SP", [f32], 32, (sequence "F%u", 0, 31)>; -def DFPRegs : RegisterClass<"SP", [f64], 64, [D0, D1, D2, D3, D4, D5, D6, D7, - D8, D9, D10, D11, D12, D13, D14, D15]>; +def DFPRegs : RegisterClass<"SP", [f64], 64, (sequence "D%u", 0, 15)>; diff --git a/lib/Target/Sparc/SparcSubtarget.cpp b/lib/Target/Sparc/SparcSubtarget.cpp index ce11af1fa842..de647e8221a2 100644 --- a/lib/Target/Sparc/SparcSubtarget.cpp +++ b/lib/Target/Sparc/SparcSubtarget.cpp @@ -7,28 +7,38 @@ // //===----------------------------------------------------------------------===// // -// This file implements the SPARC specific subclass of TargetSubtarget. +// This file implements the SPARC specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #include "SparcSubtarget.h" -#include "SparcGenSubtarget.inc" +#include "Sparc.h" +#include "llvm/Target/TargetRegistry.h" + +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "SparcGenSubtargetInfo.inc" + using namespace llvm; -SparcSubtarget::SparcSubtarget(const std::string &TT, const std::string &FS, - bool is64Bit) : +SparcSubtarget::SparcSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, bool is64Bit) : + SparcGenSubtargetInfo(TT, CPU, FS), IsV9(false), V8DeprecatedInsts(false), IsVIS(false), Is64Bit(is64Bit) { // Determine default and user specified characteristics - const char *CPU = "v8"; - if (is64Bit) { - CPU = "v9"; - IsV9 = true; + std::string CPUName = CPU; + if (CPUName.empty()) { + if (is64Bit) + CPUName = "v9"; + else + CPUName = "v8"; } + IsV9 = CPUName == "v9"; // Parse features string. - ParseSubtargetFeatures(FS, CPU); + ParseSubtargetFeatures(CPUName, FS); } diff --git a/lib/Target/Sparc/SparcSubtarget.h b/lib/Target/Sparc/SparcSubtarget.h index cec0ab422bc2..00a04c3bea57 100644 --- a/lib/Target/Sparc/SparcSubtarget.h +++ b/lib/Target/Sparc/SparcSubtarget.h @@ -7,26 +7,31 @@ // //===----------------------------------------------------------------------===// // -// This file declares the SPARC specific subclass of TargetSubtarget. +// This file declares the SPARC specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #ifndef SPARC_SUBTARGET_H #define SPARC_SUBTARGET_H -#include "llvm/Target/TargetSubtarget.h" +#include "llvm/Target/TargetSubtargetInfo.h" #include <string> +#define GET_SUBTARGETINFO_HEADER +#include "SparcGenSubtargetInfo.inc" + namespace llvm { +class StringRef; -class SparcSubtarget : public TargetSubtarget { +class SparcSubtarget : public SparcGenSubtargetInfo { bool IsV9; bool V8DeprecatedInsts; bool IsVIS; bool Is64Bit; public: - SparcSubtarget(const std::string &TT, const std::string &FS, bool is64bit); + SparcSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, bool is64bit); bool isV9() const { return IsV9; } bool isVIS() const { return IsVIS; } @@ -34,8 +39,7 @@ public: /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(StringRef CPU, StringRef FS); bool is64Bit() const { return Is64Bit; } std::string getDataLayout() const { diff --git a/lib/Target/Sparc/SparcTargetMachine.cpp b/lib/Target/Sparc/SparcTargetMachine.cpp index b84eab568d29..cbe6d8754efd 100644 --- a/lib/Target/Sparc/SparcTargetMachine.cpp +++ b/lib/Target/Sparc/SparcTargetMachine.cpp @@ -11,7 +11,6 @@ //===----------------------------------------------------------------------===// #include "Sparc.h" -#include "SparcMCAsmInfo.h" #include "SparcTargetMachine.h" #include "llvm/PassManager.h" #include "llvm/Target/TargetRegistry.h" @@ -21,18 +20,15 @@ extern "C" void LLVMInitializeSparcTarget() { // Register the target. RegisterTargetMachine<SparcV8TargetMachine> X(TheSparcTarget); RegisterTargetMachine<SparcV9TargetMachine> Y(TheSparcV9Target); - - RegisterAsmInfo<SparcELFMCAsmInfo> A(TheSparcTarget); - RegisterAsmInfo<SparcELFMCAsmInfo> B(TheSparcV9Target); - } /// SparcTargetMachine ctor - Create an ILP32 architecture model /// SparcTargetMachine::SparcTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS, bool is64bit) - : LLVMTargetMachine(T, TT), - Subtarget(TT, FS, is64bit), + : LLVMTargetMachine(T, TT, CPU, FS), + Subtarget(TT, CPU, FS, is64bit), DataLayout(Subtarget.getDataLayout()), TLInfo(*this), TSInfo(*this), InstrInfo(Subtarget), FrameLowering(Subtarget) { @@ -56,12 +52,14 @@ bool SparcTargetMachine::addPreEmitPass(PassManagerBase &PM, SparcV8TargetMachine::SparcV8TargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) - : SparcTargetMachine(T, TT, FS, false) { + : SparcTargetMachine(T, TT, CPU, FS, false) { } SparcV9TargetMachine::SparcV9TargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) - : SparcTargetMachine(T, TT, FS, true) { + : SparcTargetMachine(T, TT, CPU, FS, true) { } diff --git a/lib/Target/Sparc/SparcTargetMachine.h b/lib/Target/Sparc/SparcTargetMachine.h index c4bb6bd776d4..799fc497f4ae 100644 --- a/lib/Target/Sparc/SparcTargetMachine.h +++ b/lib/Target/Sparc/SparcTargetMachine.h @@ -34,7 +34,8 @@ class SparcTargetMachine : public LLVMTargetMachine { SparcFrameLowering FrameLowering; public: SparcTargetMachine(const Target &T, const std::string &TT, - const std::string &FS, bool is64bit); + const std::string &CPU, const std::string &FS, + bool is64bit); virtual const SparcInstrInfo *getInstrInfo() const { return &InstrInfo; } virtual const TargetFrameLowering *getFrameLowering() const { @@ -62,7 +63,7 @@ public: class SparcV8TargetMachine : public SparcTargetMachine { public: SparcV8TargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); }; /// SparcV9TargetMachine - Sparc 64-bit target machine @@ -70,7 +71,7 @@ public: class SparcV9TargetMachine : public SparcTargetMachine { public: SparcV9TargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); }; } // end namespace llvm diff --git a/lib/Target/SubtargetFeature.cpp b/lib/Target/SubtargetFeature.cpp deleted file mode 100644 index e0a9de82983f..000000000000 --- a/lib/Target/SubtargetFeature.cpp +++ /dev/null @@ -1,384 +0,0 @@ -//===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the SubtargetFeature interface. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Target/SubtargetFeature.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/StringExtras.h" -#include <algorithm> -#include <cassert> -#include <cctype> -#include <cstdlib> -using namespace llvm; - -//===----------------------------------------------------------------------===// -// Static Helper Functions -//===----------------------------------------------------------------------===// - -/// hasFlag - Determine if a feature has a flag; '+' or '-' -/// -static inline bool hasFlag(const std::string &Feature) { - assert(!Feature.empty() && "Empty string"); - // Get first character - char Ch = Feature[0]; - // Check if first character is '+' or '-' flag - return Ch == '+' || Ch =='-'; -} - -/// StripFlag - Return string stripped of flag. -/// -static inline std::string StripFlag(const std::string &Feature) { - return hasFlag(Feature) ? Feature.substr(1) : Feature; -} - -/// isEnabled - Return true if enable flag; '+'. -/// -static inline bool isEnabled(const std::string &Feature) { - assert(!Feature.empty() && "Empty string"); - // Get first character - char Ch = Feature[0]; - // Check if first character is '+' for enabled - return Ch == '+'; -} - -/// PrependFlag - Return a string with a prepended flag; '+' or '-'. -/// -static inline std::string PrependFlag(const std::string &Feature, - bool IsEnabled) { - assert(!Feature.empty() && "Empty string"); - if (hasFlag(Feature)) return Feature; - return std::string(IsEnabled ? "+" : "-") + Feature; -} - -/// Split - Splits a string of comma separated items in to a vector of strings. -/// -static void Split(std::vector<std::string> &V, const std::string &S) { - // Start at beginning of string. - size_t Pos = 0; - while (true) { - // Find the next comma - size_t Comma = S.find(',', Pos); - // If no comma found then the rest of the string is used - if (Comma == std::string::npos) { - // Add string to vector - V.push_back(S.substr(Pos)); - break; - } - // Otherwise add substring to vector - V.push_back(S.substr(Pos, Comma - Pos)); - // Advance to next item - Pos = Comma + 1; - } -} - -/// Join a vector of strings to a string with a comma separating each element. -/// -static std::string Join(const std::vector<std::string> &V) { - // Start with empty string. - std::string Result; - // If the vector is not empty - if (!V.empty()) { - // Start with the CPU feature - Result = V[0]; - // For each successive feature - for (size_t i = 1; i < V.size(); i++) { - // Add a comma - Result += ","; - // Add the feature - Result += V[i]; - } - } - // Return the features string - return Result; -} - -/// Adding features. -void SubtargetFeatures::AddFeature(const std::string &String, - bool IsEnabled) { - // Don't add empty features - if (!String.empty()) { - // Convert to lowercase, prepend flag and add to vector - Features.push_back(PrependFlag(LowercaseString(String), IsEnabled)); - } -} - -/// Find KV in array using binary search. -template<typename T> const T *Find(const std::string &S, const T *A, size_t L) { - // Make the lower bound element we're looking for - T KV; - KV.Key = S.c_str(); - // Determine the end of the array - const T *Hi = A + L; - // Binary search the array - const T *F = std::lower_bound(A, Hi, KV); - // If not found then return NULL - if (F == Hi || std::string(F->Key) != S) return NULL; - // Return the found array item - return F; -} - -/// getLongestEntryLength - Return the length of the longest entry in the table. -/// -static size_t getLongestEntryLength(const SubtargetFeatureKV *Table, - size_t Size) { - size_t MaxLen = 0; - for (size_t i = 0; i < Size; i++) - MaxLen = std::max(MaxLen, std::strlen(Table[i].Key)); - return MaxLen; -} - -/// Display help for feature choices. -/// -static void Help(const SubtargetFeatureKV *CPUTable, size_t CPUTableSize, - const SubtargetFeatureKV *FeatTable, size_t FeatTableSize) { - // Determine the length of the longest CPU and Feature entries. - unsigned MaxCPULen = getLongestEntryLength(CPUTable, CPUTableSize); - unsigned MaxFeatLen = getLongestEntryLength(FeatTable, FeatTableSize); - - // Print the CPU table. - errs() << "Available CPUs for this target:\n\n"; - for (size_t i = 0; i != CPUTableSize; i++) - errs() << " " << CPUTable[i].Key - << std::string(MaxCPULen - std::strlen(CPUTable[i].Key), ' ') - << " - " << CPUTable[i].Desc << ".\n"; - errs() << "\n"; - - // Print the Feature table. - errs() << "Available features for this target:\n\n"; - for (size_t i = 0; i != FeatTableSize; i++) - errs() << " " << FeatTable[i].Key - << std::string(MaxFeatLen - std::strlen(FeatTable[i].Key), ' ') - << " - " << FeatTable[i].Desc << ".\n"; - errs() << "\n"; - - errs() << "Use +feature to enable a feature, or -feature to disable it.\n" - << "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n"; - std::exit(1); -} - -//===----------------------------------------------------------------------===// -// SubtargetFeatures Implementation -//===----------------------------------------------------------------------===// - -SubtargetFeatures::SubtargetFeatures(const std::string &Initial) { - // Break up string into separate features - Split(Features, Initial); -} - - -std::string SubtargetFeatures::getString() const { - return Join(Features); -} -void SubtargetFeatures::setString(const std::string &Initial) { - // Throw out old features - Features.clear(); - // Break up string into separate features - Split(Features, LowercaseString(Initial)); -} - - -/// setCPU - Set the CPU string. Replaces previous setting. Setting to "" -/// clears CPU. -void SubtargetFeatures::setCPU(const std::string &String) { - Features[0] = LowercaseString(String); -} - - -/// setCPUIfNone - Setting CPU string only if no string is set. -/// -void SubtargetFeatures::setCPUIfNone(const std::string &String) { - if (Features[0].empty()) setCPU(String); -} - -/// getCPU - Returns current CPU. -/// -const std::string & SubtargetFeatures::getCPU() const { - return Features[0]; -} - - -/// SetImpliedBits - For each feature that is (transitively) implied by this -/// feature, set it. -/// -static -void SetImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, - const SubtargetFeatureKV *FeatureTable, - size_t FeatureTableSize) { - for (size_t i = 0; i < FeatureTableSize; ++i) { - const SubtargetFeatureKV &FE = FeatureTable[i]; - - if (FeatureEntry->Value == FE.Value) continue; - - if (FeatureEntry->Implies & FE.Value) { - Bits |= FE.Value; - SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); - } - } -} - -/// ClearImpliedBits - For each feature that (transitively) implies this -/// feature, clear it. -/// -static -void ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, - const SubtargetFeatureKV *FeatureTable, - size_t FeatureTableSize) { - for (size_t i = 0; i < FeatureTableSize; ++i) { - const SubtargetFeatureKV &FE = FeatureTable[i]; - - if (FeatureEntry->Value == FE.Value) continue; - - if (FE.Implies & FeatureEntry->Value) { - Bits &= ~FE.Value; - ClearImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); - } - } -} - -/// getBits - Get feature bits. -/// -uint64_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable, - size_t CPUTableSize, - const SubtargetFeatureKV *FeatureTable, - size_t FeatureTableSize) { - assert(CPUTable && "missing CPU table"); - assert(FeatureTable && "missing features table"); -#ifndef NDEBUG - for (size_t i = 1; i < CPUTableSize; i++) { - assert(strcmp(CPUTable[i - 1].Key, CPUTable[i].Key) < 0 && - "CPU table is not sorted"); - } - for (size_t i = 1; i < FeatureTableSize; i++) { - assert(strcmp(FeatureTable[i - 1].Key, FeatureTable[i].Key) < 0 && - "CPU features table is not sorted"); - } -#endif - uint64_t Bits = 0; // Resulting bits - - // Check if help is needed - if (Features[0] == "help") - Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize); - - // Find CPU entry - const SubtargetFeatureKV *CPUEntry = - Find(Features[0], CPUTable, CPUTableSize); - // If there is a match - if (CPUEntry) { - // Set base feature bits - Bits = CPUEntry->Value; - - // Set the feature implied by this CPU feature, if any. - for (size_t i = 0; i < FeatureTableSize; ++i) { - const SubtargetFeatureKV &FE = FeatureTable[i]; - if (CPUEntry->Value & FE.Value) - SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); - } - } else { - errs() << "'" << Features[0] - << "' is not a recognized processor for this target" - << " (ignoring processor)\n"; - } - // Iterate through each feature - for (size_t i = 1; i < Features.size(); i++) { - const std::string &Feature = Features[i]; - - // Check for help - if (Feature == "+help") - Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize); - - // Find feature in table. - const SubtargetFeatureKV *FeatureEntry = - Find(StripFlag(Feature), FeatureTable, FeatureTableSize); - // If there is a match - if (FeatureEntry) { - // Enable/disable feature in bits - if (isEnabled(Feature)) { - Bits |= FeatureEntry->Value; - - // For each feature that this implies, set it. - SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); - } else { - Bits &= ~FeatureEntry->Value; - - // For each feature that implies this, clear it. - ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); - } - } else { - errs() << "'" << Feature - << "' is not a recognized feature for this target" - << " (ignoring feature)\n"; - } - } - - return Bits; -} - -/// Get info pointer -void *SubtargetFeatures::getInfo(const SubtargetInfoKV *Table, - size_t TableSize) { - assert(Table && "missing table"); -#ifndef NDEBUG - for (size_t i = 1; i < TableSize; i++) { - assert(strcmp(Table[i - 1].Key, Table[i].Key) < 0 && "Table is not sorted"); - } -#endif - - // Find entry - const SubtargetInfoKV *Entry = Find(Features[0], Table, TableSize); - - if (Entry) { - return Entry->Value; - } else { - errs() << "'" << Features[0] - << "' is not a recognized processor for this target" - << " (ignoring processor)\n"; - return NULL; - } -} - -/// print - Print feature string. -/// -void SubtargetFeatures::print(raw_ostream &OS) const { - for (size_t i = 0, e = Features.size(); i != e; ++i) - OS << Features[i] << " "; - OS << "\n"; -} - -/// dump - Dump feature info. -/// -void SubtargetFeatures::dump() const { - print(dbgs()); -} - -/// getDefaultSubtargetFeatures - Return a string listing the features -/// associated with the target triple. -/// -/// FIXME: This is an inelegant way of specifying the features of a -/// subtarget. It would be better if we could encode this information -/// into the IR. See <rdar://5972456>. -/// -void SubtargetFeatures::getDefaultSubtargetFeatures(const std::string &CPU, - const Triple& Triple) { - setCPU(CPU); - - if (Triple.getVendor() == Triple::Apple) { - if (Triple.getArch() == Triple::ppc) { - // powerpc-apple-* - AddFeature("altivec"); - } else if (Triple.getArch() == Triple::ppc64) { - // powerpc64-apple-* - AddFeature("64bit"); - AddFeature("altivec"); - } - } -} diff --git a/lib/Target/SystemZ/CMakeLists.txt b/lib/Target/SystemZ/CMakeLists.txt index 1f5d3552ae7e..f4bdbd8cd173 100644 --- a/lib/Target/SystemZ/CMakeLists.txt +++ b/lib/Target/SystemZ/CMakeLists.txt @@ -1,14 +1,11 @@ set(LLVM_TARGET_DEFINITIONS SystemZ.td) -tablegen(SystemZGenRegisterInfo.h.inc -gen-register-desc-header) -tablegen(SystemZGenRegisterNames.inc -gen-register-enums) -tablegen(SystemZGenRegisterInfo.inc -gen-register-desc) -tablegen(SystemZGenInstrNames.inc -gen-instr-enums) -tablegen(SystemZGenInstrInfo.inc -gen-instr-desc) +tablegen(SystemZGenRegisterInfo.inc -gen-register-info) +tablegen(SystemZGenInstrInfo.inc -gen-instr-info) tablegen(SystemZGenAsmWriter.inc -gen-asm-writer) tablegen(SystemZGenDAGISel.inc -gen-dag-isel) tablegen(SystemZGenCallingConv.inc -gen-callingconv) -tablegen(SystemZGenSubtarget.inc -gen-subtarget) +tablegen(SystemZGenSubtargetInfo.inc -gen-subtarget) add_llvm_target(SystemZCodeGen SystemZAsmPrinter.cpp @@ -16,7 +13,6 @@ add_llvm_target(SystemZCodeGen SystemZISelLowering.cpp SystemZInstrInfo.cpp SystemZFrameLowering.cpp - SystemZMCAsmInfo.cpp SystemZRegisterInfo.cpp SystemZSubtarget.cpp SystemZTargetMachine.cpp @@ -24,3 +20,4 @@ add_llvm_target(SystemZCodeGen ) add_subdirectory(TargetInfo) +add_subdirectory(MCTargetDesc) diff --git a/lib/Target/SystemZ/MCTargetDesc/CMakeLists.txt b/lib/Target/SystemZ/MCTargetDesc/CMakeLists.txt new file mode 100644 index 000000000000..2ac90164721f --- /dev/null +++ b/lib/Target/SystemZ/MCTargetDesc/CMakeLists.txt @@ -0,0 +1,7 @@ +add_llvm_library(LLVMSystemZDesc + SystemZMCTargetDesc.cpp + SystemZMCAsmInfo.cpp + ) + +# Hack: we need to include 'main' target directory to grab private headers +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BINARY_DIR}/..) diff --git a/lib/Target/SystemZ/MCTargetDesc/Makefile b/lib/Target/SystemZ/MCTargetDesc/Makefile new file mode 100644 index 000000000000..08f1a9d51fb5 --- /dev/null +++ b/lib/Target/SystemZ/MCTargetDesc/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/SystemZ/TargetDesc/Makefile --------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +LIBRARYNAME = LLVMSystemZDesc + +# Hack: we need to include 'main' target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/SystemZ/SystemZMCAsmInfo.cpp b/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp index 2dc7e7bd29bb..8540546b62d3 100644 --- a/lib/Target/SystemZ/SystemZMCAsmInfo.cpp +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp @@ -18,6 +18,8 @@ using namespace llvm; SystemZMCAsmInfo::SystemZMCAsmInfo(const Target &T, StringRef TT) { + IsLittleEndian = false; + PointerSize = 8; PrivateGlobalPrefix = ".L"; WeakRefDirective = "\t.weak\t"; PCSymbol = "."; diff --git a/lib/Target/SystemZ/SystemZMCAsmInfo.h b/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h index a6a27e2f4b6d..a6a27e2f4b6d 100644 --- a/lib/Target/SystemZ/SystemZMCAsmInfo.h +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp b/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp new file mode 100644 index 000000000000..5a826a6ef887 --- /dev/null +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp @@ -0,0 +1,58 @@ +//===-- SystemZMCTargetDesc.cpp - SystemZ Target Descriptions ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides SystemZ specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#include "SystemZMCTargetDesc.h" +#include "SystemZMCAsmInfo.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Target/TargetRegistry.h" + +#define GET_INSTRINFO_MC_DESC +#include "SystemZGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_MC_DESC +#include "SystemZGenSubtargetInfo.inc" + +#define GET_REGINFO_MC_DESC +#include "SystemZGenRegisterInfo.inc" + +using namespace llvm; + +static MCInstrInfo *createSystemZMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitSystemZMCInstrInfo(X); + return X; +} + +extern "C" void LLVMInitializeSystemZMCInstrInfo() { + TargetRegistry::RegisterMCInstrInfo(TheSystemZTarget, + createSystemZMCInstrInfo); +} + +static MCSubtargetInfo *createSystemZMCSubtargetInfo(StringRef TT, + StringRef CPU, + StringRef FS) { + MCSubtargetInfo *X = new MCSubtargetInfo(); + InitSystemZMCSubtargetInfo(X, TT, CPU, FS); + return X; +} + +extern "C" void LLVMInitializeSystemZMCSubtargetInfo() { + TargetRegistry::RegisterMCSubtargetInfo(TheSystemZTarget, + createSystemZMCSubtargetInfo); +} + +extern "C" void LLVMInitializeSystemZMCAsmInfo() { + RegisterMCAsmInfo<SystemZMCAsmInfo> X(TheSystemZTarget); +} diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.h b/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.h new file mode 100644 index 000000000000..e2ad5afd6e57 --- /dev/null +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.h @@ -0,0 +1,38 @@ +//===-- SystemZMCTargetDesc.h - SystemZ Target Descriptions -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides SystemZ specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#ifndef SYSTEMZMCTARGETDESC_H +#define SYSTEMZMCTARGETDESC_H + +namespace llvm { +class MCSubtargetInfo; +class Target; +class StringRef; + +extern Target TheSystemZTarget; + +} // End llvm namespace + +// Defines symbolic names for SystemZ registers. +// This defines a mapping from register name to register number. +#define GET_REGINFO_ENUM +#include "SystemZGenRegisterInfo.inc" + +// Defines symbolic names for the SystemZ instructions. +#define GET_INSTRINFO_ENUM +#include "SystemZGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "SystemZGenSubtargetInfo.inc" + +#endif diff --git a/lib/Target/SystemZ/Makefile b/lib/Target/SystemZ/Makefile index 6930e14c061e..6356491debeb 100644 --- a/lib/Target/SystemZ/Makefile +++ b/lib/Target/SystemZ/Makefile @@ -12,12 +12,11 @@ LIBRARYNAME = LLVMSystemZCodeGen TARGET = SystemZ # Make sure that tblgen is run, first thing. -BUILT_SOURCES = SystemZGenRegisterInfo.h.inc SystemZGenRegisterNames.inc \ - SystemZGenRegisterInfo.inc SystemZGenInstrNames.inc \ - SystemZGenInstrInfo.inc SystemZGenAsmWriter.inc \ - SystemZGenDAGISel.inc SystemZGenSubtarget.inc SystemZGenCallingConv.inc +BUILT_SOURCES = SystemZGenRegisterInfo.inc SystemZGenInstrInfo.inc \ + SystemZGenAsmWriter.inc SystemZGenDAGISel.inc \ + SystemZGenSubtargetInfo.inc SystemZGenCallingConv.inc -DIRS = TargetInfo +DIRS = TargetInfo MCTargetDesc include $(LEVEL)/Makefile.common diff --git a/lib/Target/SystemZ/SystemZ.h b/lib/Target/SystemZ/SystemZ.h index ea5240a10c9a..88960b9cc601 100644 --- a/lib/Target/SystemZ/SystemZ.h +++ b/lib/Target/SystemZ/SystemZ.h @@ -15,6 +15,7 @@ #ifndef LLVM_TARGET_SystemZ_H #define LLVM_TARGET_SystemZ_H +#include "MCTargetDesc/SystemZMCTargetDesc.h" #include "llvm/Target/TargetMachine.h" namespace llvm { @@ -47,15 +48,5 @@ namespace llvm { FunctionPass *createSystemZISelDag(SystemZTargetMachine &TM, CodeGenOpt::Level OptLevel); - extern Target TheSystemZTarget; - } // end namespace llvm; - -// Defines symbolic names for SystemZ registers. -// This defines a mapping from register name to register number. -#include "SystemZGenRegisterNames.inc" - -// Defines symbolic names for the SystemZ instructions. -#include "SystemZGenInstrNames.inc" - #endif diff --git a/lib/Target/SystemZ/SystemZISelLowering.cpp b/lib/Target/SystemZ/SystemZISelLowering.cpp index af85df53b059..871c2972a8c4 100644 --- a/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -142,6 +142,8 @@ SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) : setOperationAction(ISD::FCOS, MVT::f64, Expand); setOperationAction(ISD::FREM, MVT::f32, Expand); setOperationAction(ISD::FREM, MVT::f64, Expand); + setOperationAction(ISD::FMA, MVT::f32, Expand); + setOperationAction(ISD::FMA, MVT::f64, Expand); // We have only 64-bit bitconverts setOperationAction(ISD::BITCAST, MVT::f32, Expand); diff --git a/lib/Target/SystemZ/SystemZInstrBuilder.h b/lib/Target/SystemZ/SystemZInstrBuilder.h index 2f2ef08dece1..ab45ec5984e3 100644 --- a/lib/Target/SystemZ/SystemZInstrBuilder.h +++ b/lib/Target/SystemZ/SystemZInstrBuilder.h @@ -108,11 +108,11 @@ addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset = 0) { MachineInstr *MI = MIB; MachineFunction &MF = *MI->getParent()->getParent(); MachineFrameInfo &MFI = *MF.getFrameInfo(); - const TargetInstrDesc &TID = MI->getDesc(); + const MCInstrDesc &MCID = MI->getDesc(); unsigned Flags = 0; - if (TID.mayLoad()) + if (MCID.mayLoad()) Flags |= MachineMemOperand::MOLoad; - if (TID.mayStore()) + if (MCID.mayStore()) Flags |= MachineMemOperand::MOStore; MachineMemOperand *MMO = MF.getMachineMemOperand(MachinePointerInfo( diff --git a/lib/Target/SystemZ/SystemZInstrInfo.cpp b/lib/Target/SystemZ/SystemZInstrInfo.cpp index be5280323c34..99e2730609e8 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -16,17 +16,21 @@ #include "SystemZInstrInfo.h" #include "SystemZMachineFunctionInfo.h" #include "SystemZTargetMachine.h" -#include "SystemZGenInstrInfo.inc" #include "llvm/Function.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Target/TargetRegistry.h" #include "llvm/Support/ErrorHandling.h" + +#define GET_INSTRINFO_CTOR +#include "SystemZGenInstrInfo.inc" + using namespace llvm; SystemZInstrInfo::SystemZInstrInfo(SystemZTargetMachine &tm) - : TargetInstrInfoImpl(SystemZInsts, array_lengthof(SystemZInsts)), + : SystemZGenInstrInfo(SystemZ::ADJCALLSTACKUP, SystemZ::ADJCALLSTACKDOWN), RI(tm, *this), TM(tm) { } @@ -199,13 +203,13 @@ ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const { } bool SystemZInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const { - const TargetInstrDesc &TID = MI->getDesc(); - if (!TID.isTerminator()) return false; + const MCInstrDesc &MCID = MI->getDesc(); + if (!MCID.isTerminator()) return false; // Conditional branch is a special case. - if (TID.isBranch() && !TID.isBarrier()) + if (MCID.isBranch() && !MCID.isBarrier()) return true; - if (!TID.isPredicable()) + if (!MCID.isPredicable()) return true; return !isPredicated(MI); } @@ -343,7 +347,7 @@ SystemZInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, return Count; } -const TargetInstrDesc& +const MCInstrDesc& SystemZInstrInfo::getBrCond(SystemZCC::CondCodes CC) const { switch (CC) { default: @@ -408,7 +412,7 @@ SystemZInstrInfo::getOppositeCondition(SystemZCC::CondCodes CC) const { } } -const TargetInstrDesc& +const MCInstrDesc& SystemZInstrInfo::getLongDispOpc(unsigned Opc) const { switch (Opc) { default: diff --git a/lib/Target/SystemZ/SystemZInstrInfo.h b/lib/Target/SystemZ/SystemZInstrInfo.h index 6cb720010207..6a31e9496365 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.h +++ b/lib/Target/SystemZ/SystemZInstrInfo.h @@ -19,6 +19,9 @@ #include "llvm/ADT/IndexedMap.h" #include "llvm/Target/TargetInstrInfo.h" +#define GET_INSTRINFO_HEADER +#include "SystemZGenInstrInfo.inc" + namespace llvm { class SystemZTargetMachine; @@ -47,7 +50,7 @@ namespace SystemZII { }; } -class SystemZInstrInfo : public TargetInstrInfoImpl { +class SystemZInstrInfo : public SystemZGenInstrInfo { const SystemZRegisterInfo RI; SystemZTargetMachine &TM; public: @@ -94,10 +97,10 @@ public: SystemZCC::CondCodes getOppositeCondition(SystemZCC::CondCodes CC) const; SystemZCC::CondCodes getCondFromBranchOpc(unsigned Opc) const; - const TargetInstrDesc& getBrCond(SystemZCC::CondCodes CC) const; - const TargetInstrDesc& getLongDispOpc(unsigned Opc) const; + const MCInstrDesc& getBrCond(SystemZCC::CondCodes CC) const; + const MCInstrDesc& getLongDispOpc(unsigned Opc) const; - const TargetInstrDesc& getMemoryInstr(unsigned Opc, int64_t Offset = 0) const { + const MCInstrDesc& getMemoryInstr(unsigned Opc, int64_t Offset = 0) const { if (Offset < 0 || Offset >= 4096) return getLongDispOpc(Opc); else diff --git a/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/lib/Target/SystemZ/SystemZRegisterInfo.cpp index ed62cfff08aa..59692e883366 100644 --- a/lib/Target/SystemZ/SystemZRegisterInfo.cpp +++ b/lib/Target/SystemZ/SystemZRegisterInfo.cpp @@ -25,12 +25,15 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/ADT/BitVector.h" + +#define GET_REGINFO_TARGET_DESC +#include "SystemZGenRegisterInfo.inc" + using namespace llvm; SystemZRegisterInfo::SystemZRegisterInfo(SystemZTargetMachine &tm, const SystemZInstrInfo &tii) - : SystemZGenRegisterInfo(SystemZ::ADJCALLSTACKUP, SystemZ::ADJCALLSTACKDOWN), - TM(tm), TII(tii) { + : SystemZGenRegisterInfo(), TM(tm), TII(tii) { } const unsigned* @@ -51,10 +54,20 @@ BitVector SystemZRegisterInfo::getReservedRegs(const MachineFunction &MF) const BitVector Reserved(getNumRegs()); const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); - if (TFI->hasFP(MF)) + if (TFI->hasFP(MF)) { + // R11D is the frame pointer. Reserve all aliases. Reserved.set(SystemZ::R11D); + Reserved.set(SystemZ::R11W); + Reserved.set(SystemZ::R10P); + Reserved.set(SystemZ::R10Q); + } + Reserved.set(SystemZ::R14D); Reserved.set(SystemZ::R15D); + Reserved.set(SystemZ::R14W); + Reserved.set(SystemZ::R15W); + Reserved.set(SystemZ::R14P); + Reserved.set(SystemZ::R14Q); return Reserved; } @@ -143,6 +156,3 @@ int SystemZRegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const { assert(0 && "What is the dwarf register number"); return -1; } - - -#include "SystemZGenRegisterInfo.inc" diff --git a/lib/Target/SystemZ/SystemZRegisterInfo.h b/lib/Target/SystemZ/SystemZRegisterInfo.h index cd8f20fee617..2e262e1acc30 100644 --- a/lib/Target/SystemZ/SystemZRegisterInfo.h +++ b/lib/Target/SystemZ/SystemZRegisterInfo.h @@ -15,7 +15,9 @@ #define SystemZREGISTERINFO_H #include "llvm/Target/TargetRegisterInfo.h" -#include "SystemZGenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "SystemZGenRegisterInfo.inc" namespace llvm { diff --git a/lib/Target/SystemZ/SystemZRegisterInfo.td b/lib/Target/SystemZ/SystemZRegisterInfo.td index 9313ffdb4a0b..a24cbcf4ccd8 100644 --- a/lib/Target/SystemZ/SystemZRegisterInfo.td +++ b/lib/Target/SystemZ/SystemZRegisterInfo.td @@ -161,318 +161,45 @@ def F15L : FPRL<15, "f15", [F15S]>; // Status register def PSW : SystemZReg<"psw">; -/// Register classes -def GR32 : RegisterClass<"SystemZ", [i32], 32, - // Volatile registers - [R0W, R1W, R2W, R3W, R4W, R5W, R6W, R7W, R8W, R9W, R10W, R12W, R13W, - // Frame pointer, sometimes allocable - R11W, - // Volatile, but not allocable - R14W, R15W]> -{ - let MethodProtos = [{ - iterator allocation_order_begin(const MachineFunction &MF) const; - iterator allocation_order_end(const MachineFunction &MF) const; - }]; - let MethodBodies = [{ - static const unsigned SystemZ_REG32[] = { - SystemZ::R1W, SystemZ::R2W, SystemZ::R3W, SystemZ::R4W, - SystemZ::R5W, SystemZ::R0W, SystemZ::R12W, SystemZ::R11W, - SystemZ::R10W, SystemZ::R9W, SystemZ::R8W, SystemZ::R7W, - SystemZ::R6W, SystemZ::R14W, SystemZ::R13W - }; - static const unsigned SystemZ_REG32_nofp[] = { - SystemZ::R1W, SystemZ::R2W, SystemZ::R3W, SystemZ::R4W, - SystemZ::R5W, SystemZ::R0W, SystemZ::R12W, /* No R11W */ - SystemZ::R10W, SystemZ::R9W, SystemZ::R8W, SystemZ::R7W, - SystemZ::R6W, SystemZ::R14W, SystemZ::R13W - }; - GR32Class::iterator - GR32Class::allocation_order_begin(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const TargetFrameLowering *TFI = TM.getFrameLowering(); - if (TFI->hasFP(MF)) - return SystemZ_REG32_nofp; - else - return SystemZ_REG32; - } - GR32Class::iterator - GR32Class::allocation_order_end(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const TargetFrameLowering *TFI = TM.getFrameLowering(); - if (TFI->hasFP(MF)) - return SystemZ_REG32_nofp + (sizeof(SystemZ_REG32_nofp) / sizeof(unsigned)); - else - return SystemZ_REG32 + (sizeof(SystemZ_REG32) / sizeof(unsigned)); - } - }]; -} +/// Register classes. +/// Allocate the callee-saved R6-R12 backwards. That way they can be saved +/// together with R14 and R15 in one prolog instruction. +def GR32 : RegisterClass<"SystemZ", [i32], 32, (add (sequence "R%uW", 0, 5), + (sequence "R%uW", 15, 6))>; /// Registers used to generate address. Everything except R0. -def ADDR32 : RegisterClass<"SystemZ", [i32], 32, - // Volatile registers - [R1W, R2W, R3W, R4W, R5W, R6W, R7W, R8W, R9W, R10W, R12W, R13W, - // Frame pointer, sometimes allocable - R11W, - // Volatile, but not allocable - R14W, R15W]> -{ - let MethodProtos = [{ - iterator allocation_order_begin(const MachineFunction &MF) const; - iterator allocation_order_end(const MachineFunction &MF) const; - }]; - let MethodBodies = [{ - static const unsigned SystemZ_ADDR32[] = { - SystemZ::R1W, SystemZ::R2W, SystemZ::R3W, SystemZ::R4W, - SystemZ::R5W, /* No R0W */ SystemZ::R12W, SystemZ::R11W, - SystemZ::R10W, SystemZ::R9W, SystemZ::R8W, SystemZ::R7W, - SystemZ::R6W, SystemZ::R14W, SystemZ::R13W - }; - static const unsigned SystemZ_ADDR32_nofp[] = { - SystemZ::R1W, SystemZ::R2W, SystemZ::R3W, SystemZ::R4W, - SystemZ::R5W, /* No R0W */ SystemZ::R12W, /* No R11W */ - SystemZ::R10W, SystemZ::R9W, SystemZ::R8W, SystemZ::R7W, - SystemZ::R6W, SystemZ::R14W, SystemZ::R13W - }; - ADDR32Class::iterator - ADDR32Class::allocation_order_begin(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const TargetFrameLowering *TFI = TM.getFrameLowering(); - if (TFI->hasFP(MF)) - return SystemZ_ADDR32_nofp; - else - return SystemZ_ADDR32; - } - ADDR32Class::iterator - ADDR32Class::allocation_order_end(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const TargetFrameLowering *TFI = TM.getFrameLowering(); - if (TFI->hasFP(MF)) - return SystemZ_ADDR32_nofp + (sizeof(SystemZ_ADDR32_nofp) / sizeof(unsigned)); - else - return SystemZ_ADDR32 + (sizeof(SystemZ_ADDR32) / sizeof(unsigned)); - } - }]; -} +def ADDR32 : RegisterClass<"SystemZ", [i32], 32, (sub GR32, R0W)>; -def GR64 : RegisterClass<"SystemZ", [i64], 64, - // Volatile registers - [R0D, R1D, R2D, R3D, R4D, R5D, R6D, R7D, R8D, R9D, R10D, R12D, R13D, - // Frame pointer, sometimes allocable - R11D, - // Volatile, but not allocable - R14D, R15D]> -{ +def GR64 : RegisterClass<"SystemZ", [i64], 64, (add (sequence "R%uD", 0, 5), + (sequence "R%uD", 15, 6))> { let SubRegClasses = [(GR32 subreg_32bit)]; - let MethodProtos = [{ - iterator allocation_order_begin(const MachineFunction &MF) const; - iterator allocation_order_end(const MachineFunction &MF) const; - }]; - let MethodBodies = [{ - static const unsigned SystemZ_REG64[] = { - SystemZ::R1D, SystemZ::R2D, SystemZ::R3D, SystemZ::R4D, - SystemZ::R5D, SystemZ::R0D, SystemZ::R12D, SystemZ::R11D, - SystemZ::R10D, SystemZ::R9D, SystemZ::R8D, SystemZ::R7D, - SystemZ::R6D, SystemZ::R14D, SystemZ::R13D - }; - static const unsigned SystemZ_REG64_nofp[] = { - SystemZ::R1D, SystemZ::R2D, SystemZ::R3D, SystemZ::R4D, - SystemZ::R5D, SystemZ::R0D, SystemZ::R12D, /* No R11D */ - SystemZ::R10D, SystemZ::R9D, SystemZ::R8D, SystemZ::R7D, - SystemZ::R6D, SystemZ::R14D, SystemZ::R13D - }; - GR64Class::iterator - GR64Class::allocation_order_begin(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const TargetFrameLowering *TFI = TM.getFrameLowering(); - if (TFI->hasFP(MF)) - return SystemZ_REG64_nofp; - else - return SystemZ_REG64; - } - GR64Class::iterator - GR64Class::allocation_order_end(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const TargetFrameLowering *TFI = TM.getFrameLowering(); - if (TFI->hasFP(MF)) - return SystemZ_REG64_nofp + (sizeof(SystemZ_REG64_nofp) / sizeof(unsigned)); - else - return SystemZ_REG64 + (sizeof(SystemZ_REG64) / sizeof(unsigned)); - } - }]; } -def ADDR64 : RegisterClass<"SystemZ", [i64], 64, - // Volatile registers - [R1D, R2D, R3D, R4D, R5D, R6D, R7D, R8D, R9D, R10D, R12D, R13D, - // Frame pointer, sometimes allocable - R11D, - // Volatile, but not allocable - R14D, R15D]> -{ +def ADDR64 : RegisterClass<"SystemZ", [i64], 64, (sub GR64, R0D)> { let SubRegClasses = [(ADDR32 subreg_32bit)]; - let MethodProtos = [{ - iterator allocation_order_begin(const MachineFunction &MF) const; - iterator allocation_order_end(const MachineFunction &MF) const; - }]; - let MethodBodies = [{ - static const unsigned SystemZ_ADDR64[] = { - SystemZ::R1D, SystemZ::R2D, SystemZ::R3D, SystemZ::R4D, - SystemZ::R5D, /* No R0D */ SystemZ::R12D, SystemZ::R11D, - SystemZ::R10D, SystemZ::R9D, SystemZ::R8D, SystemZ::R7D, - SystemZ::R6D, SystemZ::R14D, SystemZ::R13D - }; - static const unsigned SystemZ_ADDR64_nofp[] = { - SystemZ::R1D, SystemZ::R2D, SystemZ::R3D, SystemZ::R4D, - SystemZ::R5D, /* No R0D */ SystemZ::R12D, /* No R11D */ - SystemZ::R10D, SystemZ::R9D, SystemZ::R8D, SystemZ::R7D, - SystemZ::R6D, SystemZ::R14D, SystemZ::R13D - }; - ADDR64Class::iterator - ADDR64Class::allocation_order_begin(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const TargetFrameLowering *TFI = TM.getFrameLowering(); - if (TFI->hasFP(MF)) - return SystemZ_ADDR64_nofp; - else - return SystemZ_ADDR64; - } - ADDR64Class::iterator - ADDR64Class::allocation_order_end(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const TargetFrameLowering *TFI = TM.getFrameLowering(); - if (TFI->hasFP(MF)) - return SystemZ_ADDR64_nofp + (sizeof(SystemZ_ADDR64_nofp) / sizeof(unsigned)); - else - return SystemZ_ADDR64 + (sizeof(SystemZ_ADDR64) / sizeof(unsigned)); - } - }]; } // Even-odd register pairs -def GR64P : RegisterClass<"SystemZ", [v2i32], 64, - [R0P, R2P, R4P, R6P, R8P, R10P, R12P, R14P]> -{ +def GR64P : RegisterClass<"SystemZ", [v2i32], 64, (add R0P, R2P, R4P, + R12P, R10P, R8P, R6P, + R14P)> { let SubRegClasses = [(GR32 subreg_32bit, subreg_odd32)]; - let MethodProtos = [{ - iterator allocation_order_begin(const MachineFunction &MF) const; - iterator allocation_order_end(const MachineFunction &MF) const; - }]; - let MethodBodies = [{ - static const unsigned SystemZ_REG64P[] = { - SystemZ::R0P, SystemZ::R2P, SystemZ::R4P, SystemZ::R10P, - SystemZ::R8P, SystemZ::R6P }; - static const unsigned SystemZ_REG64P_nofp[] = { - SystemZ::R0P, SystemZ::R2P, SystemZ::R4P, /* NO R10P */ - SystemZ::R8P, SystemZ::R6P }; - GR64PClass::iterator - GR64PClass::allocation_order_begin(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const TargetFrameLowering *TFI = TM.getFrameLowering(); - if (TFI->hasFP(MF)) - return SystemZ_REG64P_nofp; - else - return SystemZ_REG64P; - } - GR64PClass::iterator - GR64PClass::allocation_order_end(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const TargetFrameLowering *TFI = TM.getFrameLowering(); - if (TFI->hasFP(MF)) - return SystemZ_REG64P_nofp + (sizeof(SystemZ_REG64P_nofp) / sizeof(unsigned)); - else - return SystemZ_REG64P + (sizeof(SystemZ_REG64P) / sizeof(unsigned)); - } - }]; } -def GR128 : RegisterClass<"SystemZ", [v2i64], 128, - [R0Q, R2Q, R4Q, R6Q, R8Q, R10Q, R12Q, R14Q]> -{ +def GR128 : RegisterClass<"SystemZ", [v2i64], 128, (add R0Q, R2Q, R4Q, + R12Q, R10Q, R8Q, R6Q, + R14Q)> { let SubRegClasses = [(GR32 subreg_32bit, subreg_odd32), - (GR64 subreg_even, subreg_odd)]; - let MethodProtos = [{ - iterator allocation_order_begin(const MachineFunction &MF) const; - iterator allocation_order_end(const MachineFunction &MF) const; - }]; - let MethodBodies = [{ - static const unsigned SystemZ_REG128[] = { - SystemZ::R0Q, SystemZ::R2Q, SystemZ::R4Q, SystemZ::R10Q, - SystemZ::R8Q, SystemZ::R6Q }; - static const unsigned SystemZ_REG128_nofp[] = { - SystemZ::R0Q, SystemZ::R2Q, SystemZ::R4Q, /* NO R10Q */ - SystemZ::R8Q, SystemZ::R6Q }; - GR128Class::iterator - GR128Class::allocation_order_begin(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const TargetFrameLowering *TFI = TM.getFrameLowering(); - if (TFI->hasFP(MF)) - return SystemZ_REG128_nofp; - else - return SystemZ_REG128; - } - GR128Class::iterator - GR128Class::allocation_order_end(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const TargetFrameLowering *TFI = TM.getFrameLowering(); - if (TFI->hasFP(MF)) - return SystemZ_REG128_nofp + (sizeof(SystemZ_REG128_nofp) / sizeof(unsigned)); - else - return SystemZ_REG128 + (sizeof(SystemZ_REG128) / sizeof(unsigned)); - } - }]; + (GR64 subreg_even, subreg_odd)]; } -def FP32 : RegisterClass<"SystemZ", [f32], 32, - [F0S, F1S, F2S, F3S, F4S, F5S, F6S, F7S, - F8S, F9S, F10S, F11S, F12S, F13S, F14S, F15S]> { - let MethodProtos = [{ - iterator allocation_order_begin(const MachineFunction &MF) const; - iterator allocation_order_end(const MachineFunction &MF) const; - }]; - let MethodBodies = [{ - static const unsigned SystemZ_REGFP32[] = { - SystemZ::F0S, SystemZ::F2S, SystemZ::F4S, SystemZ::F6S, - SystemZ::F1S, SystemZ::F3S, SystemZ::F5S, SystemZ::F7S, - SystemZ::F8S, SystemZ::F9S, SystemZ::F10S, SystemZ::F11S, - SystemZ::F12S, SystemZ::F13S, SystemZ::F14S, SystemZ::F15S }; - FP32Class::iterator - FP32Class::allocation_order_begin(const MachineFunction &MF) const { - return SystemZ_REGFP32; - } - FP32Class::iterator - FP32Class::allocation_order_end(const MachineFunction &MF) const { - return SystemZ_REGFP32 + (sizeof(SystemZ_REGFP32) / sizeof(unsigned)); - } - }]; -} +def FP32 : RegisterClass<"SystemZ", [f32], 32, (sequence "F%uS", 0, 15)>; -def FP64 : RegisterClass<"SystemZ", [f64], 64, - [F0L, F1L, F2L, F3L, F4L, F5L, F6L, F7L, - F8L, F9L, F10L, F11L, F12L, F13L, F14L, F15L]> { +def FP64 : RegisterClass<"SystemZ", [f64], 64, (sequence "F%uL", 0, 15)> { let SubRegClasses = [(FP32 subreg_32bit)]; - let MethodProtos = [{ - iterator allocation_order_begin(const MachineFunction &MF) const; - iterator allocation_order_end(const MachineFunction &MF) const; - }]; - let MethodBodies = [{ - static const unsigned SystemZ_REGFP64[] = { - SystemZ::F0L, SystemZ::F2L, SystemZ::F4L, SystemZ::F6L, - SystemZ::F1L, SystemZ::F3L, SystemZ::F5L, SystemZ::F7L, - SystemZ::F8L, SystemZ::F9L, SystemZ::F10L, SystemZ::F11L, - SystemZ::F12L, SystemZ::F13L, SystemZ::F14L, SystemZ::F15L }; - FP64Class::iterator - FP64Class::allocation_order_begin(const MachineFunction &MF) const { - return SystemZ_REGFP64; - } - FP64Class::iterator - FP64Class::allocation_order_end(const MachineFunction &MF) const { - return SystemZ_REGFP64 + (sizeof(SystemZ_REGFP64) / sizeof(unsigned)); - } - }]; } // Status flags registers. -def CCR : RegisterClass<"SystemZ", [i64], 64, [PSW]> { +def CCR : RegisterClass<"SystemZ", [i64], 64, (add PSW)> { let CopyCost = -1; // Don't allow copying of status registers. } diff --git a/lib/Target/SystemZ/SystemZSubtarget.cpp b/lib/Target/SystemZ/SystemZSubtarget.cpp index a8b5e1f18679..b3ed06639758 100644 --- a/lib/Target/SystemZ/SystemZSubtarget.cpp +++ b/lib/Target/SystemZ/SystemZSubtarget.cpp @@ -7,25 +7,32 @@ // //===----------------------------------------------------------------------===// // -// This file implements the SystemZ specific subclass of TargetSubtarget. +// This file implements the SystemZ specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #include "SystemZSubtarget.h" #include "SystemZ.h" -#include "SystemZGenSubtarget.inc" #include "llvm/GlobalValue.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegistry.h" + +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "SystemZGenSubtargetInfo.inc" using namespace llvm; SystemZSubtarget::SystemZSubtarget(const std::string &TT, + const std::string &CPU, const std::string &FS): - HasZ10Insts(false) { - std::string CPU = "z9"; + SystemZGenSubtargetInfo(TT, CPU, FS), HasZ10Insts(false) { + std::string CPUName = CPU; + if (CPUName.empty()) + CPUName = "z9"; // Parse features string. - ParseSubtargetFeatures(FS, CPU); + ParseSubtargetFeatures(CPUName, FS); } /// True if accessing the GV requires an extra load. diff --git a/lib/Target/SystemZ/SystemZSubtarget.h b/lib/Target/SystemZ/SystemZSubtarget.h index 405d6e91b7ee..55cfd80002bc 100644 --- a/lib/Target/SystemZ/SystemZSubtarget.h +++ b/lib/Target/SystemZ/SystemZSubtarget.h @@ -7,33 +7,36 @@ // //===----------------------------------------------------------------------===// // -// This file declares the SystemZ specific subclass of TargetSubtarget. +// This file declares the SystemZ specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #ifndef LLVM_TARGET_SystemZ_SUBTARGET_H #define LLVM_TARGET_SystemZ_SUBTARGET_H -#include "llvm/Target/TargetSubtarget.h" - +#include "llvm/Target/TargetSubtargetInfo.h" #include <string> +#define GET_SUBTARGETINFO_HEADER +#include "SystemZGenSubtargetInfo.inc" + namespace llvm { class GlobalValue; +class StringRef; class TargetMachine; -class SystemZSubtarget : public TargetSubtarget { +class SystemZSubtarget : public SystemZGenSubtargetInfo { bool HasZ10Insts; public: /// This constructor initializes the data members to match that /// of the specified triple. /// - SystemZSubtarget(const std::string &TT, const std::string &FS); + SystemZSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(StringRef CPU, StringRef FS); bool isZ10() const { return HasZ10Insts; } diff --git a/lib/Target/SystemZ/SystemZTargetMachine.cpp b/lib/Target/SystemZ/SystemZTargetMachine.cpp index 160389942998..48298cc744e7 100644 --- a/lib/Target/SystemZ/SystemZTargetMachine.cpp +++ b/lib/Target/SystemZ/SystemZTargetMachine.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "SystemZMCAsmInfo.h" #include "SystemZTargetMachine.h" #include "SystemZ.h" #include "llvm/PassManager.h" @@ -17,16 +16,16 @@ using namespace llvm; extern "C" void LLVMInitializeSystemZTarget() { // Register the target. RegisterTargetMachine<SystemZTargetMachine> X(TheSystemZTarget); - RegisterAsmInfo<SystemZMCAsmInfo> Y(TheSystemZTarget); } /// SystemZTargetMachine ctor - Create an ILP64 architecture model /// SystemZTargetMachine::SystemZTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) - : LLVMTargetMachine(T, TT), - Subtarget(TT, FS), + : LLVMTargetMachine(T, TT, CPU, FS), + Subtarget(TT, CPU, FS), DataLayout("E-p:64:64:64-i8:8:16-i16:16:16-i32:32:32-i64:64:64-f32:32:32" "-f64:64:64-f128:128:128-a0:16:16-n32:64"), InstrInfo(*this), TLInfo(*this), TSInfo(*this), diff --git a/lib/Target/SystemZ/SystemZTargetMachine.h b/lib/Target/SystemZ/SystemZTargetMachine.h index 524f83d13229..e40b556c0c3c 100644 --- a/lib/Target/SystemZ/SystemZTargetMachine.h +++ b/lib/Target/SystemZ/SystemZTargetMachine.h @@ -38,7 +38,7 @@ class SystemZTargetMachine : public LLVMTargetMachine { SystemZFrameLowering FrameLowering; public: SystemZTargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); virtual const TargetFrameLowering *getFrameLowering() const { return &FrameLowering; diff --git a/lib/Target/Target.cpp b/lib/Target/Target.cpp index 0919fe42dc0e..a42ce548c895 100644 --- a/lib/Target/Target.cpp +++ b/lib/Target/Target.cpp @@ -97,10 +97,6 @@ unsigned long long LLVMOffsetOfElement(LLVMTargetDataRef TD, LLVMTypeRef StructT return unwrap(TD)->getStructLayout(STy)->getElementOffset(Element); } -void LLVMInvalidateStructLayout(LLVMTargetDataRef TD, LLVMTypeRef StructTy) { - unwrap(TD)->InvalidateStructLayoutInfo(unwrap<StructType>(StructTy)); -} - void LLVMDisposeTargetData(LLVMTargetDataRef TD) { delete unwrap(TD); } diff --git a/lib/Target/TargetAsmInfo.cpp b/lib/Target/TargetAsmInfo.cpp index 6fa5420120f5..a97b0e868989 100644 --- a/lib/Target/TargetAsmInfo.cpp +++ b/lib/Target/TargetAsmInfo.cpp @@ -17,11 +17,7 @@ using namespace llvm; TargetAsmInfo::TargetAsmInfo(const TargetMachine &TM) { TLOF = &TM.getTargetLowering()->getObjFileLowering(); - const TargetData &TD = *TM.getTargetData(); - IsLittleEndian = TD.isLittleEndian(); - PointerSize = TD.getPointerSize(); - const TargetFrameLowering &TFI = *TM.getFrameLowering(); - StackDir = TFI.getStackGrowthDirection(); + TFI = TM.getFrameLowering(); TRI = TM.getRegisterInfo(); - TFI.getInitialFrameState(InitialFrameState); + TFI->getInitialFrameState(InitialFrameState); } diff --git a/lib/Target/TargetData.cpp b/lib/Target/TargetData.cpp index 1990bc7b929c..17d022a339e6 100644 --- a/lib/Target/TargetData.cpp +++ b/lib/Target/TargetData.cpp @@ -42,6 +42,7 @@ char TargetData::ID = 0; //===----------------------------------------------------------------------===// StructLayout::StructLayout(const StructType *ST, const TargetData &TD) { + assert(!ST->isOpaque() && "Cannot get layout of opaque structs"); StructAlignment = 0; StructSize = 0; NumElements = ST->getNumElements(); @@ -313,63 +314,21 @@ unsigned TargetData::getAlignmentInfo(AlignTypeEnum AlignType, namespace { -class StructLayoutMap : public AbstractTypeUser { +class StructLayoutMap { typedef DenseMap<const StructType*, StructLayout*> LayoutInfoTy; LayoutInfoTy LayoutInfo; - void RemoveEntry(LayoutInfoTy::iterator I, bool WasAbstract) { - I->second->~StructLayout(); - free(I->second); - if (WasAbstract) - I->first->removeAbstractTypeUser(this); - LayoutInfo.erase(I); - } - - - /// refineAbstractType - The callback method invoked when an abstract type is - /// resolved to another type. An object must override this method to update - /// its internal state to reference NewType instead of OldType. - /// - virtual void refineAbstractType(const DerivedType *OldTy, - const Type *) { - LayoutInfoTy::iterator I = LayoutInfo.find(cast<const StructType>(OldTy)); - assert(I != LayoutInfo.end() && "Using type but not in map?"); - RemoveEntry(I, true); - } - - /// typeBecameConcrete - The other case which AbstractTypeUsers must be aware - /// of is when a type makes the transition from being abstract (where it has - /// clients on its AbstractTypeUsers list) to concrete (where it does not). - /// This method notifies ATU's when this occurs for a type. - /// - virtual void typeBecameConcrete(const DerivedType *AbsTy) { - LayoutInfoTy::iterator I = LayoutInfo.find(cast<const StructType>(AbsTy)); - assert(I != LayoutInfo.end() && "Using type but not in map?"); - RemoveEntry(I, true); - } - public: virtual ~StructLayoutMap() { // Remove any layouts. - for (LayoutInfoTy::iterator - I = LayoutInfo.begin(), E = LayoutInfo.end(); I != E; ++I) { - const Type *Key = I->first; + for (LayoutInfoTy::iterator I = LayoutInfo.begin(), E = LayoutInfo.end(); + I != E; ++I) { StructLayout *Value = I->second; - - if (Key->isAbstract()) - Key->removeAbstractTypeUser(this); - Value->~StructLayout(); free(Value); } } - void InvalidateEntry(const StructType *Ty) { - LayoutInfoTy::iterator I = LayoutInfo.find(Ty); - if (I == LayoutInfo.end()) return; - RemoveEntry(I, Ty->isAbstract()); - } - StructLayout *&operator[](const StructType *STy) { return LayoutInfo[STy]; } @@ -404,22 +363,9 @@ const StructLayout *TargetData::getStructLayout(const StructType *Ty) const { new (L) StructLayout(Ty, *this); - if (Ty->isAbstract()) - Ty->addAbstractTypeUser(STM); - return L; } -/// InvalidateStructLayoutInfo - TargetData speculatively caches StructLayout -/// objects. If a TargetData object is alive when types are being refined and -/// removed, this method must be called whenever a StructType is removed to -/// avoid a dangling pointer in this cache. -void TargetData::InvalidateStructLayoutInfo(const StructType *Ty) const { - if (!LayoutMap) return; // No cache. - - static_cast<StructLayoutMap*>(LayoutMap)->InvalidateEntry(Ty); -} - std::string TargetData::getStringRepresentation() const { std::string Result; raw_string_ostream OS(Result); @@ -570,7 +516,7 @@ unsigned TargetData::getPreferredTypeAlignmentShift(const Type *Ty) const { /// getIntPtrType - Return an unsigned integer type that is the same size or /// greater to the host pointer size. -const IntegerType *TargetData::getIntPtrType(LLVMContext &C) const { +IntegerType *TargetData::getIntPtrType(LLVMContext &C) const { return IntegerType::get(C, getPointerSizeInBits()); } diff --git a/lib/Target/TargetInstrInfo.cpp b/lib/Target/TargetInstrInfo.cpp index d4b76972e49a..d52ecb32cf75 100644 --- a/lib/Target/TargetInstrInfo.cpp +++ b/lib/Target/TargetInstrInfo.cpp @@ -12,44 +12,39 @@ //===----------------------------------------------------------------------===// #include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetInstrItineraries.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCInstrItineraries.h" #include "llvm/Support/ErrorHandling.h" #include <cctype> using namespace llvm; //===----------------------------------------------------------------------===// -// TargetOperandInfo +// TargetInstrInfo //===----------------------------------------------------------------------===// -/// getRegClass - Get the register class for the operand, handling resolution -/// of "symbolic" pointer register classes etc. If this is not a register -/// operand, this returns null. -const TargetRegisterClass * -TargetOperandInfo::getRegClass(const TargetRegisterInfo *TRI) const { - if (isLookupPtrRegClass()) +TargetInstrInfo::~TargetInstrInfo() { +} + +const TargetRegisterClass* +TargetInstrInfo::getRegClass(const MCInstrDesc &MCID, unsigned OpNum, + const TargetRegisterInfo *TRI) const { + if (OpNum >= MCID.getNumOperands()) + return 0; + + short RegClass = MCID.OpInfo[OpNum].RegClass; + if (MCID.OpInfo[OpNum].isLookupPtrRegClass()) return TRI->getPointerRegClass(RegClass); + // Instructions like INSERT_SUBREG do not have fixed register classes. if (RegClass < 0) return 0; + // Otherwise just look it up normally. return TRI->getRegClass(RegClass); } -//===----------------------------------------------------------------------===// -// TargetInstrInfo -//===----------------------------------------------------------------------===// - -TargetInstrInfo::TargetInstrInfo(const TargetInstrDesc* Desc, - unsigned numOpcodes) - : Descriptors(Desc), NumOpcodes(numOpcodes) { -} - -TargetInstrInfo::~TargetInstrInfo() { -} - unsigned TargetInstrInfo::getNumMicroOps(const InstrItineraryData *ItinData, const MachineInstr *MI) const { @@ -135,13 +130,13 @@ void TargetInstrInfo::insertNoop(MachineBasicBlock &MBB, bool TargetInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const { - const TargetInstrDesc &TID = MI->getDesc(); - if (!TID.isTerminator()) return false; + const MCInstrDesc &MCID = MI->getDesc(); + if (!MCID.isTerminator()) return false; // Conditional branch is a special case. - if (TID.isBranch() && !TID.isBarrier()) + if (MCID.isBranch() && !MCID.isBarrier()) return true; - if (!TID.isPredicable()) + if (!MCID.isPredicable()) return true; return !isPredicated(MI); } diff --git a/lib/Target/TargetLoweringObjectFile.cpp b/lib/Target/TargetLoweringObjectFile.cpp index 3343384791fb..703431b3806e 100644 --- a/lib/Target/TargetLoweringObjectFile.cpp +++ b/lib/Target/TargetLoweringObjectFile.cpp @@ -35,38 +35,39 @@ using namespace llvm; // Generic Code //===----------------------------------------------------------------------===// -TargetLoweringObjectFile::TargetLoweringObjectFile() : Ctx(0) { - TextSection = 0; - DataSection = 0; - BSSSection = 0; - ReadOnlySection = 0; - StaticCtorSection = 0; - StaticDtorSection = 0; - LSDASection = 0; - - CommDirectiveSupportsAlignment = true; - DwarfAbbrevSection = 0; - DwarfInfoSection = 0; - DwarfLineSection = 0; - DwarfFrameSection = 0; - DwarfPubNamesSection = 0; - DwarfPubTypesSection = 0; - DwarfDebugInlineSection = 0; - DwarfStrSection = 0; - DwarfLocSection = 0; - DwarfARangesSection = 0; - DwarfRangesSection = 0; - DwarfMacroInfoSection = 0; - - IsFunctionEHFrameSymbolPrivate = true; - SupportsWeakOmittedEHFrame = true; +TargetLoweringObjectFile::TargetLoweringObjectFile() : + Ctx(0), + TextSection(0), + DataSection(0), + BSSSection(0), + ReadOnlySection(0), + StaticCtorSection(0), + StaticDtorSection(0), + LSDASection(0), + CompactUnwindSection(0), + DwarfAbbrevSection(0), + DwarfInfoSection(0), + DwarfLineSection(0), + DwarfFrameSection(0), + DwarfPubNamesSection(0), + DwarfPubTypesSection(0), + DwarfDebugInlineSection(0), + DwarfStrSection(0), + DwarfLocSection(0), + DwarfARangesSection(0), + DwarfRangesSection(0), + DwarfMacroInfoSection(0), + TLSExtraDataSection(0), + CommDirectiveSupportsAlignment(true), + SupportsWeakOmittedEHFrame(true), + IsFunctionEHFrameSymbolPrivate(true) { } TargetLoweringObjectFile::~TargetLoweringObjectFile() { } static bool isSuitableForBSS(const GlobalVariable *GV) { - Constant *C = GV->getInitializer(); + const Constant *C = GV->getInitializer(); // Must have zero initializer. if (!C->isNullValue()) @@ -168,7 +169,7 @@ SectionKind TargetLoweringObjectFile::getKindForGlobal(const GlobalValue *GV, return SectionKind::getBSS(); } - Constant *C = GVar->getInitializer(); + const Constant *C = GVar->getInitializer(); // If the global is marked constant, we can put it into a mergable section, // a mergable string section, or general .data if it contains relocations. diff --git a/lib/Target/TargetMachine.cpp b/lib/Target/TargetMachine.cpp index 863b8114dc30..74a1f4e8da56 100644 --- a/lib/Target/TargetMachine.cpp +++ b/lib/Target/TargetMachine.cpp @@ -43,7 +43,7 @@ namespace llvm { Reloc::Model RelocationModel; CodeModel::Model CMModel; bool GuaranteedTailCallOpt; - unsigned StackAlignment; + unsigned StackAlignmentOverride; bool RealignStack; bool DisableJumpTables; bool StrongPHIElim; @@ -183,7 +183,7 @@ EnableGuaranteedTailCallOpt("tailcallopt", static cl::opt<unsigned, true> OverrideStackAlignment("stack-alignment", cl::desc("Override default stack alignment"), - cl::location(StackAlignment), + cl::location(StackAlignmentOverride), cl::init(0)); static cl::opt<bool, true> EnableRealignStack("realign-stack", @@ -216,8 +216,9 @@ FunctionSections("ffunction-sections", // TargetMachine Class // -TargetMachine::TargetMachine(const Target &T) - : TheTarget(T), AsmInfo(0), +TargetMachine::TargetMachine(const Target &T, + StringRef TT, StringRef CPU, StringRef FS) + : TheTarget(T), TargetTriple(TT), TargetCPU(CPU), TargetFS(FS), AsmInfo(0), MCRelaxAll(false), MCNoExecStack(false), MCSaveTempLabels(false), diff --git a/lib/Target/TargetRegisterInfo.cpp b/lib/Target/TargetRegisterInfo.cpp index 1c3f2dda33c7..90a8f8d8fdcc 100644 --- a/lib/Target/TargetRegisterInfo.cpp +++ b/lib/Target/TargetRegisterInfo.cpp @@ -20,21 +20,11 @@ using namespace llvm; -TargetRegisterInfo::TargetRegisterInfo(const TargetRegisterDesc *D, unsigned NR, +TargetRegisterInfo::TargetRegisterInfo(const TargetRegisterInfoDesc *ID, regclass_iterator RCB, regclass_iterator RCE, - const char *const *subregindexnames, - int CFSO, int CFDO, - const unsigned* subregs, const unsigned subregsize, - const unsigned* aliases, const unsigned aliasessize) - : SubregHash(subregs), SubregHashSize(subregsize), - AliasesHash(aliases), AliasesHashSize(aliasessize), - Desc(D), SubRegIndexNames(subregindexnames), NumRegs(NR), + const char *const *subregindexnames) + : InfoDesc(ID), SubRegIndexNames(subregindexnames), RegClassBegin(RCB), RegClassEnd(RCE) { - assert(isPhysicalRegister(NumRegs) && - "Target has too many physical registers!"); - - CallFrameSetupOpcode = CFSO; - CallFrameDestroyOpcode = CFDO; } TargetRegisterInfo::~TargetRegisterInfo() {} @@ -83,14 +73,14 @@ TargetRegisterInfo::getMinimalPhysRegClass(unsigned reg, EVT VT) const { /// registers for the specific register class. static void getAllocatableSetForRC(const MachineFunction &MF, const TargetRegisterClass *RC, BitVector &R){ - for (TargetRegisterClass::iterator I = RC->allocation_order_begin(MF), - E = RC->allocation_order_end(MF); I != E; ++I) - R.set(*I); + ArrayRef<unsigned> Order = RC->getRawAllocationOrder(MF); + for (unsigned i = 0; i != Order.size(); ++i) + R.set(Order[i]); } BitVector TargetRegisterInfo::getAllocatableSet(const MachineFunction &MF, const TargetRegisterClass *RC) const { - BitVector Allocatable(NumRegs); + BitVector Allocatable(getNumRegs()); if (RC) { getAllocatableSetForRC(MF, RC, Allocatable); } else { diff --git a/lib/Target/TargetSubtarget.cpp b/lib/Target/TargetSubtargetInfo.cpp index edb76f971533..59ffdea00ea6 100644 --- a/lib/Target/TargetSubtarget.cpp +++ b/lib/Target/TargetSubtargetInfo.cpp @@ -1,4 +1,4 @@ -//===-- TargetSubtarget.cpp - General Target Information -------------------==// +//===-- TargetSubtargetInfo.cpp - General Target Information ---------------==// // // The LLVM Compiler Infrastructure // @@ -11,18 +11,18 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Target/TargetSubtarget.h" +#include "llvm/Target/TargetSubtargetInfo.h" #include "llvm/ADT/SmallVector.h" using namespace llvm; //--------------------------------------------------------------------------- -// TargetSubtarget Class +// TargetSubtargetInfo Class // -TargetSubtarget::TargetSubtarget() {} +TargetSubtargetInfo::TargetSubtargetInfo() {} -TargetSubtarget::~TargetSubtarget() {} +TargetSubtargetInfo::~TargetSubtargetInfo() {} -bool TargetSubtarget::enablePostRAScheduler( +bool TargetSubtargetInfo::enablePostRAScheduler( CodeGenOpt::Level OptLevel, AntiDepBreakMode& Mode, RegClassVector& CriticalPathRCs) const { diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index c352bfcd8cce..d45dd352fbc4 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -15,9 +15,11 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" @@ -25,17 +27,15 @@ #include "llvm/ADT/Twine.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" + using namespace llvm; namespace { struct X86Operand; class X86ATTAsmParser : public TargetAsmParser { + MCSubtargetInfo &STI; MCAsmParser &Parser; - TargetMachine &TM; - -protected: - unsigned Is64Bit : 1; private: MCAsmParser &getParser() const { return Parser; } @@ -61,6 +61,11 @@ private: /// or %es:(%edi) in 32bit mode. bool isDstOp(X86Operand &Op); + bool is64BitMode() const { + // FIXME: Can tablegen auto-generate this? + return (STI.getFeatureBits() & X86::Mode64Bit) != 0; + } + /// @name Auto-generated Matcher Functions /// { @@ -70,12 +75,11 @@ private: /// } public: - X86ATTAsmParser(const Target &T, MCAsmParser &parser, TargetMachine &TM) - : TargetAsmParser(T), Parser(parser), TM(TM) { + X86ATTAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser) + : TargetAsmParser(), STI(sti), Parser(parser) { // Initialize the set of available features. - setAvailableFeatures(ComputeAvailableFeatures( - &TM.getSubtarget<X86Subtarget>())); + setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); } virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); @@ -84,23 +88,6 @@ public: virtual bool ParseDirective(AsmToken DirectiveID); }; - -class X86_32ATTAsmParser : public X86ATTAsmParser { -public: - X86_32ATTAsmParser(const Target &T, MCAsmParser &Parser, TargetMachine &TM) - : X86ATTAsmParser(T, Parser, TM) { - Is64Bit = false; - } -}; - -class X86_64ATTAsmParser : public X86ATTAsmParser { -public: - X86_64ATTAsmParser(const Target &T, MCAsmParser &Parser, TargetMachine &TM) - : X86ATTAsmParser(T, Parser, TM) { - Is64Bit = true; - } -}; - } // end anonymous namespace /// @name Auto-generated Match Functions @@ -155,7 +142,7 @@ struct X86Operand : public MCParsedAsmOperand { /// getEndLoc - Get the location of the last token of this operand. SMLoc getEndLoc() const { return EndLoc; } - virtual void dump(raw_ostream &OS) const {} + virtual void print(raw_ostream &OS) const {} StringRef getToken() const { assert(Kind == Token && "Invalid access!"); @@ -365,7 +352,7 @@ struct X86Operand : public MCParsedAsmOperand { } // end anonymous namespace. bool X86ATTAsmParser::isSrcOp(X86Operand &Op) { - unsigned basereg = Is64Bit ? X86::RSI : X86::ESI; + unsigned basereg = is64BitMode() ? X86::RSI : X86::ESI; return (Op.isMem() && (Op.Mem.SegReg == 0 || Op.Mem.SegReg == X86::DS) && @@ -375,7 +362,7 @@ bool X86ATTAsmParser::isSrcOp(X86Operand &Op) { } bool X86ATTAsmParser::isDstOp(X86Operand &Op) { - unsigned basereg = Is64Bit ? X86::RDI : X86::EDI; + unsigned basereg = is64BitMode() ? X86::RDI : X86::EDI; return Op.isMem() && Op.Mem.SegReg == X86::ES && isa<MCConstantExpr>(Op.Mem.Disp) && @@ -406,7 +393,7 @@ bool X86ATTAsmParser::ParseRegister(unsigned &RegNo, // FIXME: This should be done using Requires<In32BitMode> and // Requires<In64BitMode> so "eiz" usage in 64-bit instructions // can be also checked. - if (RegNo == X86::RIZ && !Is64Bit) + if (RegNo == X86::RIZ && !is64BitMode()) return Error(Tok.getLoc(), "riz register in 64-bit mode only"); // Parse "%st" as "%st(0)" and "%st(1)", which is multiple tokens. @@ -710,23 +697,6 @@ ParseInstruction(StringRef Name, SMLoc NameLoc, } } - // FIXME: Hack to recognize vpclmul<src1_quadword, src2_quadword>dq - if (PatchedName.startswith("vpclmul")) { - unsigned CLMULQuadWordSelect = StringSwitch<unsigned>( - PatchedName.slice(7, PatchedName.size() - 2)) - .Case("lqlq", 0x00) // src1[63:0], src2[63:0] - .Case("hqlq", 0x01) // src1[127:64], src2[63:0] - .Case("lqhq", 0x10) // src1[63:0], src2[127:64] - .Case("hqhq", 0x11) // src1[127:64], src2[127:64] - .Default(~0U); - if (CLMULQuadWordSelect != ~0U) { - ExtraImmOp = MCConstantExpr::Create(CLMULQuadWordSelect, - getParser().getContext()); - assert(PatchedName.endswith("dq") && "Unexpected mnemonic!"); - PatchedName = "vpclmulqdq"; - } - } - Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc)); if (ExtraImmOp) @@ -843,7 +813,7 @@ ParseInstruction(StringRef Name, SMLoc NameLoc, // Transform "movs[bwl] %ds:(%esi), %es:(%edi)" into "movs[bwl]" if (Name.startswith("movs") && Operands.size() == 3 && (Name == "movsb" || Name == "movsw" || Name == "movsl" || - (Is64Bit && Name == "movsq"))) { + (is64BitMode() && Name == "movsq"))) { X86Operand &Op = *(X86Operand*)Operands.begin()[1]; X86Operand &Op2 = *(X86Operand*)Operands.begin()[2]; if (isSrcOp(Op) && isDstOp(Op2)) { @@ -856,7 +826,7 @@ ParseInstruction(StringRef Name, SMLoc NameLoc, // Transform "lods[bwl] %ds:(%esi),{%al,%ax,%eax,%rax}" into "lods[bwl]" if (Name.startswith("lods") && Operands.size() == 3 && (Name == "lods" || Name == "lodsb" || Name == "lodsw" || - Name == "lodsl" || (Is64Bit && Name == "lodsq"))) { + Name == "lodsl" || (is64BitMode() && Name == "lodsq"))) { X86Operand *Op1 = static_cast<X86Operand*>(Operands[1]); X86Operand *Op2 = static_cast<X86Operand*>(Operands[2]); if (isSrcOp(*Op1) && Op2->isReg()) { @@ -886,7 +856,7 @@ ParseInstruction(StringRef Name, SMLoc NameLoc, // Transform "stos[bwl] {%al,%ax,%eax,%rax},%es:(%edi)" into "stos[bwl]" if (Name.startswith("stos") && Operands.size() == 3 && (Name == "stos" || Name == "stosb" || Name == "stosw" || - Name == "stosl" || (Is64Bit && Name == "stosq"))) { + Name == "stosl" || (is64BitMode() && Name == "stosq"))) { X86Operand *Op1 = static_cast<X86Operand*>(Operands[1]); X86Operand *Op2 = static_cast<X86Operand*>(Operands[2]); if (isDstOp(*Op2) && Op1->isReg()) { @@ -1161,8 +1131,8 @@ extern "C" void LLVMInitializeX86AsmLexer(); // Force static initialization. extern "C" void LLVMInitializeX86AsmParser() { - RegisterAsmParser<X86_32ATTAsmParser> X(TheX86_32Target); - RegisterAsmParser<X86_64ATTAsmParser> Y(TheX86_64Target); + RegisterAsmParser<X86ATTAsmParser> X(TheX86_32Target); + RegisterAsmParser<X86ATTAsmParser> Y(TheX86_64Target); LLVMInitializeX86AsmLexer(); } diff --git a/lib/Target/X86/CMakeLists.txt b/lib/Target/X86/CMakeLists.txt index b5fa94f12bc7..b112f9ff69bb 100644 --- a/lib/Target/X86/CMakeLists.txt +++ b/lib/Target/X86/CMakeLists.txt @@ -1,18 +1,15 @@ set(LLVM_TARGET_DEFINITIONS X86.td) -tablegen(X86GenRegisterInfo.h.inc -gen-register-desc-header) -tablegen(X86GenRegisterNames.inc -gen-register-enums) -tablegen(X86GenRegisterInfo.inc -gen-register-desc) +tablegen(X86GenRegisterInfo.inc -gen-register-info) tablegen(X86GenDisassemblerTables.inc -gen-disassembler) -tablegen(X86GenInstrNames.inc -gen-instr-enums) -tablegen(X86GenInstrInfo.inc -gen-instr-desc) +tablegen(X86GenInstrInfo.inc -gen-instr-info) tablegen(X86GenAsmWriter.inc -gen-asm-writer) tablegen(X86GenAsmWriter1.inc -gen-asm-writer -asmwriternum=1) tablegen(X86GenAsmMatcher.inc -gen-asm-matcher) tablegen(X86GenDAGISel.inc -gen-dag-isel) tablegen(X86GenFastISel.inc -gen-fast-isel) tablegen(X86GenCallingConv.inc -gen-callingconv) -tablegen(X86GenSubtarget.inc -gen-subtarget) +tablegen(X86GenSubtargetInfo.inc -gen-subtarget) tablegen(X86GenEDInfo.inc -gen-enhanced-disassembly-info) set(sources @@ -30,7 +27,6 @@ set(sources X86InstrInfo.cpp X86JITInfo.cpp X86MachObjectWriter.cpp - X86MCAsmInfo.cpp X86MCCodeEmitter.cpp X86MCInstLower.cpp X86RegisterInfo.cpp @@ -60,5 +56,6 @@ add_llvm_target(X86CodeGen ${sources}) add_subdirectory(AsmParser) add_subdirectory(Disassembler) add_subdirectory(InstPrinter) +add_subdirectory(MCTargetDesc) add_subdirectory(TargetInfo) add_subdirectory(Utils) diff --git a/lib/Target/X86/Disassembler/X86Disassembler.cpp b/lib/Target/X86/Disassembler/X86Disassembler.cpp index d8a105e7e9d2..4a0d2ec727a9 100644 --- a/lib/Target/X86/Disassembler/X86Disassembler.cpp +++ b/lib/Target/X86/Disassembler/X86Disassembler.cpp @@ -26,7 +26,8 @@ #include "llvm/Support/MemoryObject.h" #include "llvm/Support/raw_ostream.h" -#include "X86GenRegisterNames.inc" +#define GET_REGINFO_ENUM +#include "X86GenRegisterInfo.inc" #include "X86GenEDInfo.inc" using namespace llvm; diff --git a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp index 68247d2f1a5b..c37d8797b39c 100644 --- a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp +++ b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp @@ -15,30 +15,23 @@ #define DEBUG_TYPE "asm-printer" #include "X86ATTInstPrinter.h" #include "X86InstComments.h" -#include "X86Subtarget.h" +#include "MCTargetDesc/X86MCTargetDesc.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCExpr.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" -#include "X86GenInstrNames.inc" #include <map> using namespace llvm; // Include the auto-generated portion of the assembly writer. #define GET_INSTRUCTION_NAME #define PRINT_ALIAS_INSTR -#include "X86GenRegisterNames.inc" #include "X86GenAsmWriter.inc" -#undef PRINT_ALIAS_INSTR -#undef GET_INSTRUCTION_NAME -X86ATTInstPrinter::X86ATTInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI) +X86ATTInstPrinter::X86ATTInstPrinter(const MCAsmInfo &MAI) : MCInstPrinter(MAI) { - // Initialize the set of available features. - setAvailableFeatures(ComputeAvailableFeatures( - &TM.getSubtarget<X86Subtarget>())); } void X86ATTInstPrinter::printRegName(raw_ostream &OS, diff --git a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h index 5f939b61da21..5426e5cf38d9 100644 --- a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h +++ b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h @@ -19,19 +19,15 @@ namespace llvm { class MCOperand; -class X86Subtarget; -class TargetMachine; class X86ATTInstPrinter : public MCInstPrinter { public: - X86ATTInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI); + X86ATTInstPrinter(const MCAsmInfo &MAI); virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; virtual void printInst(const MCInst *MI, raw_ostream &OS); virtual StringRef getOpcodeName(unsigned Opcode) const; - // Methods used to print the alias of an instruction. - unsigned ComputeAvailableFeatures(const X86Subtarget *Subtarget) const; // Autogenerated by tblgen, returns true if we successfully printed an // alias. bool printAliasInstr(const MCInst *MI, raw_ostream &OS); diff --git a/lib/Target/X86/InstPrinter/X86InstComments.cpp b/lib/Target/X86/InstPrinter/X86InstComments.cpp index c642acc3b9a2..4e28dfe7fa81 100644 --- a/lib/Target/X86/InstPrinter/X86InstComments.cpp +++ b/lib/Target/X86/InstPrinter/X86InstComments.cpp @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// #include "X86InstComments.h" -#include "X86GenInstrNames.inc" +#include "MCTargetDesc/X86MCTargetDesc.h" #include "llvm/MC/MCInst.h" #include "llvm/Support/raw_ostream.h" #include "../Utils/X86ShuffleDecode.h" diff --git a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp index 5f581bab3906..506e26cbf7cd 100644 --- a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp +++ b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp @@ -15,13 +15,12 @@ #define DEBUG_TYPE "asm-printer" #include "X86IntelInstPrinter.h" #include "X86InstComments.h" -#include "X86Subtarget.h" +#include "MCTargetDesc/X86MCTargetDesc.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCExpr.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" -#include "X86GenInstrNames.inc" #include <cctype> using namespace llvm; diff --git a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h index c8030c3ecdac..e84a1940017d 100644 --- a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h +++ b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h @@ -20,11 +20,10 @@ namespace llvm { class MCOperand; -class TargetMachine; class X86IntelInstPrinter : public MCInstPrinter { public: - X86IntelInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI) + X86IntelInstPrinter(const MCAsmInfo &MAI) : MCInstPrinter(MAI) {} virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; diff --git a/lib/Target/X86/MCTargetDesc/CMakeLists.txt b/lib/Target/X86/MCTargetDesc/CMakeLists.txt new file mode 100644 index 000000000000..ca88f8ffd08c --- /dev/null +++ b/lib/Target/X86/MCTargetDesc/CMakeLists.txt @@ -0,0 +1,7 @@ +add_llvm_library(LLVMX86Desc + X86MCTargetDesc.cpp + X86MCAsmInfo.cpp + ) + +# Hack: we need to include 'main' target directory to grab private headers +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BINARY_DIR}/..) diff --git a/lib/Target/X86/MCTargetDesc/Makefile b/lib/Target/X86/MCTargetDesc/Makefile new file mode 100644 index 000000000000..b19774ee379e --- /dev/null +++ b/lib/Target/X86/MCTargetDesc/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/X86/TargetDesc/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +LIBRARYNAME = LLVMX86Desc + +# Hack: we need to include 'main' target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/X86/X86MCAsmInfo.cpp b/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp index 2e1ec6317601..27031005bd09 100644 --- a/lib/Target/X86/X86MCAsmInfo.cpp +++ b/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "X86MCAsmInfo.h" -#include "X86TargetMachine.h" #include "llvm/ADT/Triple.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" @@ -45,14 +44,17 @@ static const char *const x86_asm_table[] = { "{flags}", "", "{dirflag}", "", "{fpsr}", "", + "{fpcr}", "", "{cc}", "cc", 0,0}; -X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &Triple) { +X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &T) { + bool is64Bit = T.getArch() == Triple::x86_64; + if (is64Bit) + PointerSize = 8; + AsmTransCBE = x86_asm_table; AssemblerDialect = AsmWriterFlavor; - - bool is64Bit = Triple.getArch() == Triple::x86_64; TextAlignFillValue = 0x90; @@ -74,22 +76,14 @@ X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &Triple) { ExceptionsType = ExceptionHandling::DwarfCFI; } -const MCExpr * -X86_64MCAsmInfoDarwin::getExprForPersonalitySymbol(const MCSymbol *Sym, - unsigned Encoding, - MCStreamer &Streamer) const { - MCContext &Context = Streamer.getContext(); - const MCExpr *Res = - MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_GOTPCREL, Context); - const MCExpr *Four = MCConstantExpr::Create(4, Context); - return MCBinaryExpr::CreateAdd(Res, Four, Context); -} - X86_64MCAsmInfoDarwin::X86_64MCAsmInfoDarwin(const Triple &Triple) : X86MCAsmInfoDarwin(Triple) { } X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &T) { + if (T.getArch() == Triple::x86_64) + PointerSize = 8; + AsmTransCBE = x86_asm_table; AssemblerDialect = AsmWriterFlavor; @@ -114,6 +108,17 @@ X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &T) { Data64bitsDirective = 0; } +const MCExpr * +X86_64MCAsmInfoDarwin::getExprForPersonalitySymbol(const MCSymbol *Sym, + unsigned Encoding, + MCStreamer &Streamer) const { + MCContext &Context = Streamer.getContext(); + const MCExpr *Res = + MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_GOTPCREL, Context); + const MCExpr *Four = MCConstantExpr::Create(4, Context); + return MCBinaryExpr::CreateAdd(Res, Four, Context); +} + const MCSection *X86ELFMCAsmInfo:: getNonexecutableStackSection(MCContext &Ctx) const { return Ctx.getELFSection(".note.GNU-stack", ELF::SHT_PROGBITS, diff --git a/lib/Target/X86/X86MCAsmInfo.h b/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.h index 2cd4c8eb30ec..2cd4c8eb30ec 100644 --- a/lib/Target/X86/X86MCAsmInfo.h +++ b/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.h diff --git a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp new file mode 100644 index 000000000000..b77f37b03f19 --- /dev/null +++ b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp @@ -0,0 +1,185 @@ +//===-- X86MCTargetDesc.cpp - X86 Target Descriptions -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides X86 specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#include "X86MCTargetDesc.h" +#include "X86MCAsmInfo.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/Host.h" + +#define GET_REGINFO_MC_DESC +#include "X86GenRegisterInfo.inc" + +#define GET_INSTRINFO_MC_DESC +#include "X86GenInstrInfo.inc" + +#define GET_SUBTARGETINFO_MC_DESC +#include "X86GenSubtargetInfo.inc" + +using namespace llvm; + + +std::string X86_MC::ParseX86Triple(StringRef TT) { + Triple TheTriple(TT); + if (TheTriple.getArch() == Triple::x86_64) + return "+64bit-mode"; + return "-64bit-mode"; +} + +/// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in the +/// specified arguments. If we can't run cpuid on the host, return true. +bool X86_MC::GetCpuIDAndInfo(unsigned value, unsigned *rEAX, + unsigned *rEBX, unsigned *rECX, unsigned *rEDX) { +#if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64) + #if defined(__GNUC__) + // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually. + asm ("movq\t%%rbx, %%rsi\n\t" + "cpuid\n\t" + "xchgq\t%%rbx, %%rsi\n\t" + : "=a" (*rEAX), + "=S" (*rEBX), + "=c" (*rECX), + "=d" (*rEDX) + : "a" (value)); + return false; + #elif defined(_MSC_VER) + int registers[4]; + __cpuid(registers, value); + *rEAX = registers[0]; + *rEBX = registers[1]; + *rECX = registers[2]; + *rEDX = registers[3]; + return false; + #endif +#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86) + #if defined(__GNUC__) + asm ("movl\t%%ebx, %%esi\n\t" + "cpuid\n\t" + "xchgl\t%%ebx, %%esi\n\t" + : "=a" (*rEAX), + "=S" (*rEBX), + "=c" (*rECX), + "=d" (*rEDX) + : "a" (value)); + return false; + #elif defined(_MSC_VER) + __asm { + mov eax,value + cpuid + mov esi,rEAX + mov dword ptr [esi],eax + mov esi,rEBX + mov dword ptr [esi],ebx + mov esi,rECX + mov dword ptr [esi],ecx + mov esi,rEDX + mov dword ptr [esi],edx + } + return false; + #endif +#endif + return true; +} + +void X86_MC::DetectFamilyModel(unsigned EAX, unsigned &Family, + unsigned &Model) { + Family = (EAX >> 8) & 0xf; // Bits 8 - 11 + Model = (EAX >> 4) & 0xf; // Bits 4 - 7 + if (Family == 6 || Family == 0xf) { + if (Family == 0xf) + // Examine extended family ID if family ID is F. + Family += (EAX >> 20) & 0xff; // Bits 20 - 27 + // Examine extended model ID if family ID is 6 or F. + Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19 + } +} + +MCSubtargetInfo *X86_MC::createX86MCSubtargetInfo(StringRef TT, StringRef CPU, + StringRef FS) { + std::string ArchFS = X86_MC::ParseX86Triple(TT); + if (!FS.empty()) { + if (!ArchFS.empty()) + ArchFS = ArchFS + "," + FS.str(); + else + ArchFS = FS; + } + + std::string CPUName = CPU; + if (CPUName.empty()) { +#if defined (__x86_64__) || defined(__i386__) + CPUName = sys::getHostCPUName(); +#else + CPUName = "generic"; +#endif + } + + MCSubtargetInfo *X = new MCSubtargetInfo(); + InitX86MCSubtargetInfo(X, TT, CPUName, ArchFS); + return X; +} + +// Force static initialization. +extern "C" void LLVMInitializeX86MCSubtargetInfo() { + TargetRegistry::RegisterMCSubtargetInfo(TheX86_32Target, + X86_MC::createX86MCSubtargetInfo); + TargetRegistry::RegisterMCSubtargetInfo(TheX86_64Target, + X86_MC::createX86MCSubtargetInfo); +} + +static MCInstrInfo *createX86MCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitX86MCInstrInfo(X); + return X; +} + +extern "C" void LLVMInitializeX86MCInstrInfo() { + TargetRegistry::RegisterMCInstrInfo(TheX86_32Target, createX86MCInstrInfo); + TargetRegistry::RegisterMCInstrInfo(TheX86_64Target, createX86MCInstrInfo); +} + +static MCRegisterInfo *createX86MCRegisterInfo() { + MCRegisterInfo *X = new MCRegisterInfo(); + InitX86MCRegisterInfo(X); + return X; +} + +extern "C" void LLVMInitializeX86MCRegInfo() { + TargetRegistry::RegisterMCRegInfo(TheX86_32Target, createX86MCRegisterInfo); + TargetRegistry::RegisterMCRegInfo(TheX86_64Target, createX86MCRegisterInfo); +} + + +static MCAsmInfo *createX86MCAsmInfo(const Target &T, StringRef TT) { + Triple TheTriple(TT); + + if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO) { + if (TheTriple.getArch() == Triple::x86_64) + return new X86_64MCAsmInfoDarwin(TheTriple); + else + return new X86MCAsmInfoDarwin(TheTriple); + } + + if (TheTriple.isOSWindows()) + return new X86MCAsmInfoCOFF(TheTriple); + + return new X86ELFMCAsmInfo(TheTriple); +} + +extern "C" void LLVMInitializeX86MCAsmInfo() { + // Register the target asm info. + RegisterMCAsmInfoFn A(TheX86_32Target, createX86MCAsmInfo); + RegisterMCAsmInfoFn B(TheX86_64Target, createX86MCAsmInfo); +} diff --git a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h new file mode 100644 index 000000000000..89ea22b31be2 --- /dev/null +++ b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h @@ -0,0 +1,60 @@ +//===-- X86MCTargetDesc.h - X86 Target Descriptions -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides X86 specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#ifndef X86MCTARGETDESC_H +#define X86MCTARGETDESC_H + +#include <string> + +namespace llvm { +class MCSubtargetInfo; +class Target; +class StringRef; + +extern Target TheX86_32Target, TheX86_64Target; + +namespace X86_MC { + std::string ParseX86Triple(StringRef TT); + + /// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in + /// the specified arguments. If we can't run cpuid on the host, return true. + bool GetCpuIDAndInfo(unsigned value, unsigned *rEAX, + unsigned *rEBX, unsigned *rECX, unsigned *rEDX); + + void DetectFamilyModel(unsigned EAX, unsigned &Family, unsigned &Model); + + /// createARMMCSubtargetInfo - Create a X86 MCSubtargetInfo instance. + /// This is exposed so Asm parser, etc. do not need to go through + /// TargetRegistry. + MCSubtargetInfo *createX86MCSubtargetInfo(StringRef TT, StringRef CPU, + StringRef FS); +} + +} // End llvm namespace + + +// Defines symbolic names for X86 registers. This defines a mapping from +// register name to register number. +// +#define GET_REGINFO_ENUM +#include "X86GenRegisterInfo.inc" + +// Defines symbolic names for the X86 instructions. +// +#define GET_INSTRINFO_ENUM +#include "X86GenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "X86GenSubtargetInfo.inc" + +#endif diff --git a/lib/Target/X86/Makefile b/lib/Target/X86/Makefile index 12fb090d4dce..949661eb99e9 100644 --- a/lib/Target/X86/Makefile +++ b/lib/Target/X86/Makefile @@ -12,14 +12,13 @@ LIBRARYNAME = LLVMX86CodeGen TARGET = X86 # Make sure that tblgen is run, first thing. -BUILT_SOURCES = X86GenRegisterInfo.h.inc X86GenRegisterNames.inc \ - X86GenRegisterInfo.inc X86GenInstrNames.inc \ - X86GenInstrInfo.inc X86GenAsmWriter.inc X86GenAsmMatcher.inc \ +BUILT_SOURCES = X86GenRegisterInfo.inc X86GenInstrInfo.inc \ + X86GenAsmWriter.inc X86GenAsmMatcher.inc \ X86GenAsmWriter1.inc X86GenDAGISel.inc \ X86GenDisassemblerTables.inc X86GenFastISel.inc \ - X86GenCallingConv.inc X86GenSubtarget.inc \ + X86GenCallingConv.inc X86GenSubtargetInfo.inc \ X86GenEDInfo.inc -DIRS = InstPrinter AsmParser Disassembler TargetInfo Utils +DIRS = InstPrinter AsmParser Disassembler TargetInfo MCTargetDesc Utils include $(LEVEL)/Makefile.common diff --git a/lib/Target/X86/X86.h b/lib/Target/X86/X86.h index 0ca436690040..ec52dfb3e7d1 100644 --- a/lib/Target/X86/X86.h +++ b/lib/Target/X86/X86.h @@ -15,6 +15,7 @@ #ifndef TARGET_X86_H #define TARGET_X86_H +#include "MCTargetDesc/X86MCTargetDesc.h" #include "llvm/Support/DataTypes.h" #include "llvm/Target/TargetMachine.h" @@ -22,10 +23,12 @@ namespace llvm { class FunctionPass; class JITCodeEmitter; +class MachineCodeEmitter; class MCCodeEmitter; class MCContext; +class MCInstrInfo; class MCObjectWriter; -class MachineCodeEmitter; +class MCSubtargetInfo; class Target; class TargetAsmBackend; class X86TargetMachine; @@ -57,10 +60,9 @@ FunctionPass *createSSEDomainFixPass(); FunctionPass *createX86JITCodeEmitterPass(X86TargetMachine &TM, JITCodeEmitter &JCE); -MCCodeEmitter *createX86_32MCCodeEmitter(const Target &, TargetMachine &TM, - MCContext &Ctx); -MCCodeEmitter *createX86_64MCCodeEmitter(const Target &, TargetMachine &TM, - MCContext &Ctx); +MCCodeEmitter *createX86MCCodeEmitter(const MCInstrInfo &MCII, + const MCSubtargetInfo &STI, + MCContext &Ctx); TargetAsmBackend *createX86_32AsmBackend(const Target &, const std::string &); TargetAsmBackend *createX86_64AsmBackend(const Target &, const std::string &); @@ -84,17 +86,6 @@ MCObjectWriter *createX86MachObjectWriter(raw_ostream &OS, uint32_t CPUType, uint32_t CPUSubtype); -extern Target TheX86_32Target, TheX86_64Target; - } // End llvm namespace -// Defines symbolic names for X86 registers. This defines a mapping from -// register name to register number. -// -#include "X86GenRegisterNames.inc" - -// Defines symbolic names for the X86 instructions. -// -#include "X86GenInstrNames.inc" - #endif diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td index 7bb96766cceb..4ccb43fe18cc 100644 --- a/lib/Target/X86/X86.td +++ b/lib/Target/X86/X86.td @@ -17,6 +17,13 @@ include "llvm/Target/Target.td" //===----------------------------------------------------------------------===// +// X86 Subtarget state. +// + +def Mode64Bit : SubtargetFeature<"64bit-mode", "In64BitMode", "true", + "64-bit mode (x86_64)">; + +//===----------------------------------------------------------------------===// // X86 Subtarget features. //===----------------------------------------------------------------------===// diff --git a/lib/Target/X86/X86AsmBackend.cpp b/lib/Target/X86/X86AsmBackend.cpp index 4d7d96dcb36b..9b556a55efd9 100644 --- a/lib/Target/X86/X86AsmBackend.cpp +++ b/lib/Target/X86/X86AsmBackend.cpp @@ -194,6 +194,9 @@ static unsigned getRelaxedOpcodeArith(unsigned Op) { // PUSH case X86::PUSHi8: return X86::PUSHi32; + case X86::PUSHi16: return X86::PUSHi32; + case X86::PUSH64i8: return X86::PUSH64i32; + case X86::PUSH64i16: return X86::PUSH64i32; } } diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp index c2d53c4dd26c..99b4479a9fc9 100644 --- a/lib/Target/X86/X86AsmPrinter.cpp +++ b/lib/Target/X86/X86AsmPrinter.cpp @@ -709,13 +709,12 @@ void X86AsmPrinter::PrintDebugValueComment(const MachineInstr *MI, //===----------------------------------------------------------------------===// static MCInstPrinter *createX86MCInstPrinter(const Target &T, - TargetMachine &TM, unsigned SyntaxVariant, const MCAsmInfo &MAI) { if (SyntaxVariant == 0) - return new X86ATTInstPrinter(TM, MAI); + return new X86ATTInstPrinter(MAI); if (SyntaxVariant == 1) - return new X86IntelInstPrinter(TM, MAI); + return new X86IntelInstPrinter(MAI); return 0; } diff --git a/lib/Target/X86/X86CallingConv.td b/lib/Target/X86/X86CallingConv.td index 56351756e8dd..77b99056ae00 100644 --- a/lib/Target/X86/X86CallingConv.td +++ b/lib/Target/X86/X86CallingConv.td @@ -44,11 +44,11 @@ def RetCC_X86Common : CallingConv<[ // can only be used by ABI non-compliant code. This vector type is only // supported while using the AVX target feature. CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], - CCIfSubtarget<"hasAVX()", CCAssignToReg<[YMM0,YMM1,YMM2,YMM3]>>>, + CCAssignToReg<[YMM0,YMM1,YMM2,YMM3]>>, // MMX vector types are always returned in MM0. If the target doesn't have // MM0, it doesn't support these vector types. - CCIfType<[x86mmx, v1i64], CCAssignToReg<[MM0]>>, + CCIfType<[x86mmx], CCAssignToReg<[MM0]>>, // Long double types are always returned in ST0 (even with SSE). CCIfType<[f80], CCAssignToReg<[ST0, ST1]>> @@ -91,10 +91,7 @@ def RetCC_X86_64_C : CallingConv<[ CCIfType<[f32], CCAssignToReg<[XMM0, XMM1]>>, CCIfType<[f64], CCAssignToReg<[XMM0, XMM1]>>, - // MMX vector types are always returned in XMM0 except for v1i64 which is - // returned in RAX. This disagrees with ABI documentation but is bug - // compatible with gcc. - CCIfType<[v1i64], CCAssignToReg<[RAX]>>, + // MMX vector types are always returned in XMM0. CCIfType<[x86mmx], CCAssignToReg<[XMM0, XMM1]>>, CCDelegateTo<RetCC_X86Common> ]>; @@ -102,11 +99,7 @@ def RetCC_X86_64_C : CallingConv<[ // X86-Win64 C return-value convention. def RetCC_X86_Win64_C : CallingConv<[ // The X86-Win64 calling convention always returns __m64 values in RAX. - CCIfType<[x86mmx, v1i64], CCBitConvertToType<i64>>, - - // And FP in XMM0 only. - CCIfType<[f32], CCAssignToReg<[XMM0]>>, - CCIfType<[f64], CCAssignToReg<[XMM0]>>, + CCIfType<[x86mmx], CCBitConvertToType<i64>>, // Otherwise, everything is the same as 'normal' X86-64 C CC. CCDelegateTo<RetCC_X86_64_C> @@ -150,17 +143,11 @@ def CC_X86_64_C : CallingConv<[ // The 'nest' parameter, if any, is passed in R10. CCIfNest<CCAssignToReg<[R10]>>, - // The first 6 v1i64 vector arguments are passed in GPRs on Darwin. - CCIfType<[v1i64], - CCIfSubtarget<"isTargetDarwin()", - CCBitConvertToType<i64>>>, - // The first 6 integer arguments are passed in integer registers. CCIfType<[i32], CCAssignToReg<[EDI, ESI, EDX, ECX, R8D, R9D]>>, CCIfType<[i64], CCAssignToReg<[RDI, RSI, RDX, RCX, R8 , R9 ]>>, - // The first 8 MMX (except for v1i64) vector arguments are passed in XMM - // registers on Darwin. + // The first 8 MMX vector arguments are passed in XMM registers on Darwin. CCIfType<[x86mmx], CCIfSubtarget<"isTargetDarwin()", CCIfSubtarget<"hasXMMInt()", @@ -189,10 +176,7 @@ def CC_X86_64_C : CallingConv<[ // 256-bit vectors get 32-byte stack slots that are 32-byte aligned. CCIfType<[v32i8, v16i16, v8i32, v4i64, v8f32, v4f64], - CCAssignToStack<32, 32>>, - - // __m64 vectors get 8-byte stack slots that are 8-byte aligned. - CCIfType<[x86mmx,v1i64], CCAssignToStack<8, 8>> + CCAssignToStack<32, 32>> ]>; // Calling convention used on Win64 @@ -210,7 +194,7 @@ def CC_X86_Win64_C : CallingConv<[ CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], CCPassIndirect<i64>>, // The first 4 MMX vector arguments are passed in GPRs. - CCIfType<[x86mmx, v1i64], CCBitConvertToType<i64>>, + CCIfType<[x86mmx], CCBitConvertToType<i64>>, // The first 4 integer arguments are passed in integer registers. CCIfType<[i32], CCAssignToRegWithShadow<[ECX , EDX , R8D , R9D ], @@ -236,10 +220,7 @@ def CC_X86_Win64_C : CallingConv<[ // Long doubles get stack slots whose size and alignment depends on the // subtarget. - CCIfType<[f80], CCAssignToStack<0, 0>>, - - // __m64 vectors get 8-byte stack slots that are 8-byte aligned. - CCIfType<[x86mmx,v1i64], CCAssignToStack<8, 8>> + CCIfType<[f80], CCAssignToStack<0, 0>> ]>; def CC_X86_64_GHC : CallingConv<[ @@ -273,8 +254,8 @@ def CC_X86_32_Common : CallingConv<[ CCIfSubtarget<"hasXMMInt()", CCAssignToReg<[XMM0,XMM1,XMM2]>>>>>, - // The first 3 __m64 (except for v1i64) vector arguments are passed in mmx - // registers if the call is not a vararg call. + // The first 3 __m64 vector arguments are passed in mmx registers if the + // call is not a vararg call. CCIfNotVarArg<CCIfType<[x86mmx], CCAssignToReg<[MM0, MM1, MM2]>>>, @@ -306,7 +287,7 @@ def CC_X86_32_Common : CallingConv<[ // __m64 vectors get 8-byte stack slots that are 4-byte aligned. They are // passed in the parameter area. - CCIfType<[x86mmx,v1i64], CCAssignToStack<8, 4>>]>; + CCIfType<[x86mmx], CCAssignToStack<8, 4>>]>; def CC_X86_32_C : CallingConv<[ // Promote i8/i16 arguments to i32. diff --git a/lib/Target/X86/X86CodeEmitter.cpp b/lib/Target/X86/X86CodeEmitter.cpp index 421e221d205c..4b11db7c0331 100644 --- a/lib/Target/X86/X86CodeEmitter.cpp +++ b/lib/Target/X86/X86CodeEmitter.cpp @@ -68,7 +68,7 @@ namespace { return "X86 Machine Code Emitter"; } - void emitInstruction(MachineInstr &MI, const TargetInstrDesc *Desc); + void emitInstruction(MachineInstr &MI, const MCInstrDesc *Desc); void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); @@ -132,7 +132,7 @@ bool Emitter<CodeEmitter>::runOnMachineFunction(MachineFunction &MF) { MCE.StartMachineBasicBlock(MBB); for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; ++I) { - const TargetInstrDesc &Desc = I->getDesc(); + const MCInstrDesc &Desc = I->getDesc(); emitInstruction(*I, &Desc); // MOVPC32r is basically a call plus a pop instruction. if (Desc.getOpcode() == X86::MOVPC32r) @@ -150,7 +150,7 @@ bool Emitter<CodeEmitter>::runOnMachineFunction(MachineFunction &MF) { /// size, and 3) use of X86-64 extended registers. static unsigned determineREX(const MachineInstr &MI) { unsigned REX = 0; - const TargetInstrDesc &Desc = MI.getDesc(); + const MCInstrDesc &Desc = MI.getDesc(); // Pseudo instructions do not need REX prefix byte. if ((Desc.TSFlags & X86II::FormMask) == X86II::Pseudo) @@ -161,7 +161,7 @@ static unsigned determineREX(const MachineInstr &MI) { unsigned NumOps = Desc.getNumOperands(); if (NumOps) { bool isTwoAddr = NumOps > 1 && - Desc.getOperandConstraint(1, TOI::TIED_TO) != -1; + Desc.getOperandConstraint(1, MCOI::TIED_TO) != -1; // If it accesses SPL, BPL, SIL, or DIL, then it requires a 0x40 REX prefix. unsigned i = isTwoAddr ? 1 : 0; @@ -598,7 +598,7 @@ void Emitter<CodeEmitter>::emitMemModRMByte(const MachineInstr &MI, template<class CodeEmitter> void Emitter<CodeEmitter>::emitInstruction(MachineInstr &MI, - const TargetInstrDesc *Desc) { + const MCInstrDesc *Desc) { DEBUG(dbgs() << MI); // If this is a pseudo instruction, lower it. @@ -708,9 +708,9 @@ void Emitter<CodeEmitter>::emitInstruction(MachineInstr &MI, // If this is a two-address instruction, skip one of the register operands. unsigned NumOps = Desc->getNumOperands(); unsigned CurOp = 0; - if (NumOps > 1 && Desc->getOperandConstraint(1, TOI::TIED_TO) != -1) + if (NumOps > 1 && Desc->getOperandConstraint(1, MCOI::TIED_TO) != -1) ++CurOp; - else if (NumOps > 2 && Desc->getOperandConstraint(NumOps-1, TOI::TIED_TO)== 0) + else if (NumOps > 2 && Desc->getOperandConstraint(NumOps-1,MCOI::TIED_TO)== 0) // Skip the last source operand that is tied_to the dest reg. e.g. LXADD32 --NumOps; diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index f1b9972530c6..21e163a30054 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -15,6 +15,7 @@ #include "X86.h" #include "X86InstrBuilder.h" +#include "X86ISelLowering.h" #include "X86RegisterInfo.h" #include "X86Subtarget.h" #include "X86TargetMachine.h" @@ -1392,7 +1393,7 @@ bool X86FastISel::X86VisitIntrinsicCall(const IntrinsicInst &I) { assert(DI->getAddress() && "Null address should be checked earlier!"); if (!X86SelectAddress(DI->getAddress(), AM)) return false; - const TargetInstrDesc &II = TII.get(TargetOpcode::DBG_VALUE); + const MCInstrDesc &II = TII.get(TargetOpcode::DBG_VALUE); // FIXME may need to add RegState::Debug to any registers produced, // although ESP/EBP should be the only ones at the moment. addFullAddress(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II), AM). @@ -1493,7 +1494,8 @@ bool X86FastISel::DoSelectCall(const Instruction *I, const char *MemIntName) { return false; // Fast-isel doesn't know about callee-pop yet. - if (Subtarget->IsCalleePop(isVarArg, CC)) + if (X86::isCalleePop(CC, Subtarget->is64Bit(), isVarArg, + GuaranteedTailCallOpt)) return false; // Check whether the function can return without sret-demotion. @@ -1628,7 +1630,7 @@ bool X86FastISel::DoSelectCall(const Instruction *I, const char *MemIntName) { unsigned NumBytes = CCInfo.getNextStackOffset(); // Issue CALLSEQ_START - unsigned AdjStackDown = TM.getRegisterInfo()->getCallFrameSetupOpcode(); + unsigned AdjStackDown = TII.getCallFrameSetupOpcode(); BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(AdjStackDown)) .addImm(NumBytes); @@ -1801,7 +1803,7 @@ bool X86FastISel::DoSelectCall(const Instruction *I, const char *MemIntName) { MIB.addReg(RegArgs[i]); // Issue CALLSEQ_END - unsigned AdjStackUp = TM.getRegisterInfo()->getCallFrameDestroyOpcode(); + unsigned AdjStackUp = TII.getCallFrameDestroyOpcode(); unsigned NumBytesCallee = 0; if (!Subtarget->is64Bit() && CS.paramHasAttr(1, Attribute::StructRet)) NumBytesCallee = 4; @@ -1846,16 +1848,19 @@ bool X86FastISel::DoSelectCall(const Instruction *I, const char *MemIntName) { // stack, but where we prefer to use the value in xmm registers, copy it // out as F80 and use a truncate to move it from fp stack reg to xmm reg. if ((RVLocs[i].getLocReg() == X86::ST0 || - RVLocs[i].getLocReg() == X86::ST1) && - isScalarFPTypeInSSEReg(RVLocs[0].getValVT())) { - CopyVT = MVT::f80; - CopyReg = createResultReg(X86::RFP80RegisterClass); + RVLocs[i].getLocReg() == X86::ST1)) { + if (isScalarFPTypeInSSEReg(RVLocs[i].getValVT())) { + CopyVT = MVT::f80; + CopyReg = createResultReg(X86::RFP80RegisterClass); + } + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(X86::FpPOP_RETVAL), + CopyReg); + } else { + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), + CopyReg).addReg(RVLocs[i].getLocReg()); + UsedRegs.push_back(RVLocs[i].getLocReg()); } - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), - CopyReg).addReg(RVLocs[i].getLocReg()); - UsedRegs.push_back(RVLocs[i].getLocReg()); - if (CopyVT != RVLocs[i].getValVT()) { // Round the F80 the right size, which also moves to the appropriate xmm // register. This is accomplished by storing the F80 value in memory and diff --git a/lib/Target/X86/X86FloatingPoint.cpp b/lib/Target/X86/X86FloatingPoint.cpp index 325d0611817d..6eed6abd43e2 100644 --- a/lib/Target/X86/X86FloatingPoint.cpp +++ b/lib/Target/X86/X86FloatingPoint.cpp @@ -37,6 +37,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/InlineAsm.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -126,10 +127,45 @@ namespace { void bundleCFG(MachineFunction &MF); MachineBasicBlock *MBB; // Current basic block + + // The hardware keeps track of how many FP registers are live, so we have + // to model that exactly. Usually, each live register corresponds to an + // FP<n> register, but when dealing with calls, returns, and inline + // assembly, it is sometimes neccesary to have live scratch registers. unsigned Stack[8]; // FP<n> Registers in each stack slot... - unsigned RegMap[8]; // Track which stack slot contains each register unsigned StackTop; // The current top of the FP stack. + enum { + NumFPRegs = 16 // Including scratch pseudo-registers. + }; + + // For each live FP<n> register, point to its Stack[] entry. + // The first entries correspond to FP0-FP6, the rest are scratch registers + // used when we need slightly different live registers than what the + // register allocator thinks. + unsigned RegMap[NumFPRegs]; + + // Pending fixed registers - Inline assembly needs FP registers to appear + // in fixed stack slot positions. This is handled by copying FP registers + // to ST registers before the instruction, and copying back after the + // instruction. + // + // This is modeled with pending ST registers. NumPendingSTs is the number + // of ST registers (ST0-STn) we are tracking. PendingST[n] points to an FP + // register that holds the ST value. The ST registers are not moved into + // place until immediately before the instruction that needs them. + // + // It can happen that we need an ST register to be live when no FP register + // holds the value: + // + // %ST0 = COPY %FP4<kill> + // + // When that happens, we allocate a scratch FP register to hold the ST + // value. That means every register in PendingST must be live. + + unsigned NumPendingSTs; + unsigned char PendingST[8]; + // Set up our stack model to match the incoming registers to MBB. void setupBlockStack(); @@ -142,13 +178,15 @@ namespace { dbgs() << " FP" << Stack[i]; assert(RegMap[Stack[i]] == i && "Stack[] doesn't match RegMap[]!"); } + for (unsigned i = 0; i != NumPendingSTs; ++i) + dbgs() << ", ST" << i << " in FP" << unsigned(PendingST[i]); dbgs() << "\n"; } /// getSlot - Return the stack slot number a particular register number is /// in. unsigned getSlot(unsigned RegNo) const { - assert(RegNo < 8 && "Regno out of range!"); + assert(RegNo < NumFPRegs && "Regno out of range!"); return RegMap[RegNo]; } @@ -160,12 +198,17 @@ namespace { /// getScratchReg - Return an FP register that is not currently in use. unsigned getScratchReg() { - for (int i = 7; i >= 0; --i) + for (int i = NumFPRegs - 1; i >= 8; --i) if (!isLive(i)) return i; llvm_unreachable("Ran out of scratch FP registers"); } + /// isScratchReg - Returns trus if RegNo is a scratch FP register. + bool isScratchReg(unsigned RegNo) { + return RegNo > 8 && RegNo < NumFPRegs; + } + /// getStackEntry - Return the X86::FP<n> register in register ST(i). unsigned getStackEntry(unsigned STi) const { if (STi >= StackTop) @@ -181,7 +224,7 @@ namespace { // pushReg - Push the specified FP<n> register onto the stack. void pushReg(unsigned Reg) { - assert(Reg < 8 && "Register number out of range!"); + assert(Reg < NumFPRegs && "Register number out of range!"); if (StackTop >= 8) report_fatal_error("Stack overflow!"); Stack[StackTop] = Reg; @@ -236,7 +279,7 @@ namespace { /// Adjust the live registers to be the set in Mask. void adjustLiveRegs(unsigned Mask, MachineBasicBlock::iterator I); - /// Shuffle the top FixCount stack entries susch that FP reg FixStack[0] is + /// Shuffle the top FixCount stack entries such that FP reg FixStack[0] is /// st(0), FP reg FixStack[1] is st(1) etc. void shuffleStackTop(const unsigned char *FixStack, unsigned FixCount, MachineBasicBlock::iterator I); @@ -251,7 +294,14 @@ namespace { void handleCondMovFP(MachineBasicBlock::iterator &I); void handleSpecialFP(MachineBasicBlock::iterator &I); - bool translateCopy(MachineInstr*); + // Check if a COPY instruction is using FP registers. + bool isFPCopy(MachineInstr *MI) { + unsigned DstReg = MI->getOperand(0).getReg(); + unsigned SrcReg = MI->getOperand(1).getReg(); + + return X86::RFP80RegClass.contains(DstReg) || + X86::RFP80RegClass.contains(SrcReg); + } }; char FPS::ID = 0; } @@ -341,6 +391,7 @@ void FPS::bundleCFG(MachineFunction &MF) { bool FPS::processBasicBlock(MachineFunction &MF, MachineBasicBlock &BB) { bool Changed = false; MBB = &BB; + NumPendingSTs = 0; setupBlockStack(); @@ -352,7 +403,7 @@ bool FPS::processBasicBlock(MachineFunction &MF, MachineBasicBlock &BB) { if (MI->isInlineAsm()) FPInstClass = X86II::SpecialFP; - if (MI->isCopy() && translateCopy(MI)) + if (MI->isCopy() && isFPCopy(MI)) FPInstClass = X86II::SpecialFP; if (FPInstClass == X86II::NotFP) @@ -833,7 +884,7 @@ void FPS::adjustLiveRegs(unsigned Mask, MachineBasicBlock::iterator I) { // Kill registers by popping. if (Kills && I != MBB->begin()) { MachineBasicBlock::iterator I2 = llvm::prior(I); - for (;;) { + while (StackTop) { unsigned KReg = getStackEntry(0); if (!(Kills & (1 << KReg))) break; @@ -881,7 +932,8 @@ void FPS::shuffleStackTop(const unsigned char *FixStack, continue; // (Reg st0) (OldReg st0) = (Reg OldReg st0) moveToTop(Reg, I); - moveToTop(OldReg, I); + if (FixCount > 0) + moveToTop(OldReg, I); } DEBUG(dumpStack()); } @@ -1239,141 +1291,307 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) { MachineInstr *MI = I; switch (MI->getOpcode()) { default: llvm_unreachable("Unknown SpecialFP instruction!"); - case X86::FpGET_ST0_32:// Appears immediately after a call returning FP type! - case X86::FpGET_ST0_64:// Appears immediately after a call returning FP type! - case X86::FpGET_ST0_80:// Appears immediately after a call returning FP type! - assert(StackTop == 0 && "Stack should be empty after a call!"); - pushReg(getFPReg(MI->getOperand(0))); - break; - case X86::FpGET_ST1_32:// Appears immediately after a call returning FP type! - case X86::FpGET_ST1_64:// Appears immediately after a call returning FP type! - case X86::FpGET_ST1_80:{// Appears immediately after a call returning FP type! - // FpGET_ST1 should occur right after a FpGET_ST0 for a call or inline asm. - // The pattern we expect is: - // CALL - // FP1 = FpGET_ST0 - // FP4 = FpGET_ST1 - // - // At this point, we've pushed FP1 on the top of stack, so it should be - // present if it isn't dead. If it was dead, we already emitted a pop to - // remove it from the stack and StackTop = 0. - - // Push FP4 as top of stack next. - pushReg(getFPReg(MI->getOperand(0))); + case TargetOpcode::COPY: { + // We handle three kinds of copies: FP <- FP, FP <- ST, and ST <- FP. + const MachineOperand &MO1 = MI->getOperand(1); + const MachineOperand &MO0 = MI->getOperand(0); + unsigned DstST = MO0.getReg() - X86::ST0; + unsigned SrcST = MO1.getReg() - X86::ST0; + bool KillsSrc = MI->killsRegister(MO1.getReg()); + + // ST = COPY FP. Set up a pending ST register. + if (DstST < 8) { + unsigned SrcFP = getFPReg(MO1); + assert(isLive(SrcFP) && "Cannot copy dead register"); + assert(!MO0.isDead() && "Cannot copy to dead ST register"); + + // Unallocated STs are marked as the nonexistent FP255. + while (NumPendingSTs <= DstST) + PendingST[NumPendingSTs++] = NumFPRegs; + + // STi could still be live from a previous inline asm. + if (isScratchReg(PendingST[DstST])) { + DEBUG(dbgs() << "Clobbering old ST in FP" << unsigned(PendingST[DstST]) + << '\n'); + freeStackSlotBefore(MI, PendingST[DstST]); + } - // If StackTop was 0 before we pushed our operand, then ST(0) must have been - // dead. In this case, the ST(1) value is the only thing that is live, so - // it should be on the TOS (after the pop that was emitted) and is. Just - // continue in this case. - if (StackTop == 1) + // When the source is killed, allocate a scratch FP register. + if (KillsSrc) { + unsigned Slot = getSlot(SrcFP); + unsigned SR = getScratchReg(); + PendingST[DstST] = SR; + Stack[Slot] = SR; + RegMap[SR] = Slot; + } else + PendingST[DstST] = SrcFP; break; - - // Because pushReg just pushed ST(1) as TOS, we now have to swap the two top - // elements so that our accounting is correct. - unsigned RegOnTop = getStackEntry(0); - unsigned RegNo = getStackEntry(1); - - // Swap the slots the regs are in. - std::swap(RegMap[RegNo], RegMap[RegOnTop]); - - // Swap stack slot contents. - if (RegMap[RegOnTop] >= StackTop) - report_fatal_error("Access past stack top!"); - std::swap(Stack[RegMap[RegOnTop]], Stack[StackTop-1]); - break; - } - case X86::FpSET_ST0_32: - case X86::FpSET_ST0_64: - case X86::FpSET_ST0_80: { - // FpSET_ST0_80 is generated by copyRegToReg for setting up inline asm - // arguments that use an st constraint. We expect a sequence of - // instructions: Fp_SET_ST0 Fp_SET_ST1? INLINEASM - unsigned Op0 = getFPReg(MI->getOperand(0)); - - if (!MI->killsRegister(X86::FP0 + Op0)) { - // Duplicate Op0 into a temporary on the stack top. - duplicateToTop(Op0, getScratchReg(), I); - } else { - // Op0 is killed, so just swap it into position. - moveToTop(Op0, I); } - --StackTop; // "Forget" we have something on the top of stack! - break; - } - case X86::FpSET_ST1_32: - case X86::FpSET_ST1_64: - case X86::FpSET_ST1_80: { - // Set up st(1) for inline asm. We are assuming that st(0) has already been - // set up by FpSET_ST0, and our StackTop is off by one because of it. - unsigned Op0 = getFPReg(MI->getOperand(0)); - // Restore the actual StackTop from before Fp_SET_ST0. - // Note we can't handle Fp_SET_ST1 without a preceding Fp_SET_ST0, and we - // are not enforcing the constraint. - ++StackTop; - unsigned RegOnTop = getStackEntry(0); // This reg must remain in st(0). - if (!MI->killsRegister(X86::FP0 + Op0)) { - duplicateToTop(Op0, getScratchReg(), I); - moveToTop(RegOnTop, I); - } else if (getSTReg(Op0) != X86::ST1) { - // We have the wrong value at st(1). Shuffle! Untested! - moveToTop(getStackEntry(1), I); - moveToTop(Op0, I); - moveToTop(RegOnTop, I); + + // FP = COPY ST. Extract fixed stack value. + // Any instruction defining ST registers must have assigned them to a + // scratch register. + if (SrcST < 8) { + unsigned DstFP = getFPReg(MO0); + assert(!isLive(DstFP) && "Cannot copy ST to live FP register"); + assert(NumPendingSTs > SrcST && "Cannot copy from dead ST register"); + unsigned SrcFP = PendingST[SrcST]; + assert(isScratchReg(SrcFP) && "Expected ST in a scratch register"); + assert(isLive(SrcFP) && "Scratch holding ST is dead"); + + // DstFP steals the stack slot from SrcFP. + unsigned Slot = getSlot(SrcFP); + Stack[Slot] = DstFP; + RegMap[DstFP] = Slot; + + // Always treat the ST as killed. + PendingST[SrcST] = NumFPRegs; + while (NumPendingSTs && PendingST[NumPendingSTs - 1] == NumFPRegs) + --NumPendingSTs; + break; } - assert(StackTop >= 2 && "Too few live registers"); - StackTop -= 2; // "Forget" both st(0) and st(1). - break; - } - case X86::MOV_Fp3232: - case X86::MOV_Fp3264: - case X86::MOV_Fp6432: - case X86::MOV_Fp6464: - case X86::MOV_Fp3280: - case X86::MOV_Fp6480: - case X86::MOV_Fp8032: - case X86::MOV_Fp8064: - case X86::MOV_Fp8080: { - const MachineOperand &MO1 = MI->getOperand(1); - unsigned SrcReg = getFPReg(MO1); - const MachineOperand &MO0 = MI->getOperand(0); - unsigned DestReg = getFPReg(MO0); - if (MI->killsRegister(X86::FP0+SrcReg)) { + // FP <- FP copy. + unsigned DstFP = getFPReg(MO0); + unsigned SrcFP = getFPReg(MO1); + assert(isLive(SrcFP) && "Cannot copy dead register"); + if (KillsSrc) { // If the input operand is killed, we can just change the owner of the // incoming stack slot into the result. - unsigned Slot = getSlot(SrcReg); - assert(Slot < 7 && DestReg < 7 && "FpMOV operands invalid!"); - Stack[Slot] = DestReg; - RegMap[DestReg] = Slot; - + unsigned Slot = getSlot(SrcFP); + Stack[Slot] = DstFP; + RegMap[DstFP] = Slot; } else { - // For FMOV we just duplicate the specified value to a new stack slot. + // For COPY we just duplicate the specified value to a new stack slot. // This could be made better, but would require substantial changes. - duplicateToTop(SrcReg, DestReg, I); + duplicateToTop(SrcFP, DstFP, I); } + break; + } + + case X86::FpPOP_RETVAL: { + // The FpPOP_RETVAL instruction is used after calls that return a value on + // the floating point stack. We cannot model this with ST defs since CALL + // instructions have fixed clobber lists. This instruction is interpreted + // to mean that there is one more live register on the stack than we + // thought. + // + // This means that StackTop does not match the hardware stack between a + // call and the FpPOP_RETVAL instructions. We do tolerate FP instructions + // between CALL and FpPOP_RETVAL as long as they don't overflow the + // hardware stack. + unsigned DstFP = getFPReg(MI->getOperand(0)); + + // Move existing stack elements up to reflect reality. + assert(StackTop < 8 && "Stack overflowed before FpPOP_RETVAL"); + if (StackTop) { + std::copy_backward(Stack, Stack + StackTop, Stack + StackTop + 1); + for (unsigned i = 0; i != NumFPRegs; ++i) + ++RegMap[i]; } + ++StackTop; + + // DstFP is the new bottom of the stack. + Stack[0] = DstFP; + RegMap[DstFP] = 0; + + // DstFP will be killed by processBasicBlock if this was a dead def. break; + } + case TargetOpcode::INLINEASM: { // The inline asm MachineInstr currently only *uses* FP registers for the // 'f' constraint. These should be turned into the current ST(x) register - // in the machine instr. Also, any kills should be explicitly popped after - // the inline asm. - unsigned Kills = 0; + // in the machine instr. + // + // There are special rules for x87 inline assembly. The compiler must know + // exactly how many registers are popped and pushed implicitly by the asm. + // Otherwise it is not possible to restore the stack state after the inline + // asm. + // + // There are 3 kinds of input operands: + // + // 1. Popped inputs. These must appear at the stack top in ST0-STn. A + // popped input operand must be in a fixed stack slot, and it is either + // tied to an output operand, or in the clobber list. The MI has ST use + // and def operands for these inputs. + // + // 2. Fixed inputs. These inputs appear in fixed stack slots, but are + // preserved by the inline asm. The fixed stack slots must be STn-STm + // following the popped inputs. A fixed input operand cannot be tied to + // an output or appear in the clobber list. The MI has ST use operands + // and no defs for these inputs. + // + // 3. Preserved inputs. These inputs use the "f" constraint which is + // represented as an FP register. The inline asm won't change these + // stack slots. + // + // Outputs must be in ST registers, FP outputs are not allowed. Clobbered + // registers do not count as output operands. The inline asm changes the + // stack as if it popped all the popped inputs and then pushed all the + // output operands. + + // Scan the assembly for ST registers used, defined and clobbered. We can + // only tell clobbers from defs by looking at the asm descriptor. + unsigned STUses = 0, STDefs = 0, STClobbers = 0, STDeadDefs = 0; + unsigned NumOps = 0; + for (unsigned i = InlineAsm::MIOp_FirstOperand, e = MI->getNumOperands(); + i != e && MI->getOperand(i).isImm(); i += 1 + NumOps) { + unsigned Flags = MI->getOperand(i).getImm(); + NumOps = InlineAsm::getNumOperandRegisters(Flags); + if (NumOps != 1) + continue; + const MachineOperand &MO = MI->getOperand(i + 1); + if (!MO.isReg()) + continue; + unsigned STReg = MO.getReg() - X86::ST0; + if (STReg >= 8) + continue; + + switch (InlineAsm::getKind(Flags)) { + case InlineAsm::Kind_RegUse: + STUses |= (1u << STReg); + break; + case InlineAsm::Kind_RegDef: + case InlineAsm::Kind_RegDefEarlyClobber: + STDefs |= (1u << STReg); + if (MO.isDead()) + STDeadDefs |= (1u << STReg); + break; + case InlineAsm::Kind_Clobber: + STClobbers |= (1u << STReg); + break; + default: + break; + } + } + + if (STUses && !isMask_32(STUses)) + MI->emitError("fixed input regs must be last on the x87 stack"); + unsigned NumSTUses = CountTrailingOnes_32(STUses); + + // Defs must be contiguous from the stack top. ST0-STn. + if (STDefs && !isMask_32(STDefs)) { + MI->emitError("output regs must be last on the x87 stack"); + STDefs = NextPowerOf2(STDefs) - 1; + } + unsigned NumSTDefs = CountTrailingOnes_32(STDefs); + + // So must the clobbered stack slots. ST0-STm, m >= n. + if (STClobbers && !isMask_32(STDefs | STClobbers)) + MI->emitError("clobbers must be last on the x87 stack"); + + // Popped inputs are the ones that are also clobbered or defined. + unsigned STPopped = STUses & (STDefs | STClobbers); + if (STPopped && !isMask_32(STPopped)) + MI->emitError("implicitly popped regs must be last on the x87 stack"); + unsigned NumSTPopped = CountTrailingOnes_32(STPopped); + + DEBUG(dbgs() << "Asm uses " << NumSTUses << " fixed regs, pops " + << NumSTPopped << ", and defines " << NumSTDefs << " regs.\n"); + + // Scan the instruction for FP uses corresponding to "f" constraints. + // Collect FP registers to kill afer the instruction. + // Always kill all the scratch regs. + unsigned FPKills = ((1u << NumFPRegs) - 1) & ~0xff; + unsigned FPUsed = 0; for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { MachineOperand &Op = MI->getOperand(i); if (!Op.isReg() || Op.getReg() < X86::FP0 || Op.getReg() > X86::FP6) continue; - assert(Op.isUse() && "Only handle inline asm uses right now"); - + if (!Op.isUse()) + MI->emitError("illegal \"f\" output constraint"); unsigned FPReg = getFPReg(Op); - Op.setReg(getSTReg(FPReg)); - + FPUsed |= 1U << FPReg; + // If we kill this operand, make sure to pop it from the stack after the // asm. We just remember it for now, and pop them all off at the end in // a batch. if (Op.isKill()) - Kills |= 1U << FPReg; + FPKills |= 1U << FPReg; + } + + // The popped inputs will be killed by the instruction, so duplicate them + // if the FP register needs to be live after the instruction, or if it is + // used in the instruction itself. We effectively treat the popped inputs + // as early clobbers. + for (unsigned i = 0; i < NumSTPopped; ++i) { + if ((FPKills & ~FPUsed) & (1u << PendingST[i])) + continue; + unsigned SR = getScratchReg(); + duplicateToTop(PendingST[i], SR, I); + DEBUG(dbgs() << "Duplicating ST" << i << " in FP" + << unsigned(PendingST[i]) << " to avoid clobbering it.\n"); + PendingST[i] = SR; + } + + // Make sure we have a unique live register for every fixed use. Some of + // them could be undef uses, and we need to emit LD_F0 instructions. + for (unsigned i = 0; i < NumSTUses; ++i) { + if (i < NumPendingSTs && PendingST[i] < NumFPRegs) { + // Check for shared assignments. + for (unsigned j = 0; j < i; ++j) { + if (PendingST[j] != PendingST[i]) + continue; + // STi and STj are inn the same register, create a copy. + unsigned SR = getScratchReg(); + duplicateToTop(PendingST[i], SR, I); + DEBUG(dbgs() << "Duplicating ST" << i << " in FP" + << unsigned(PendingST[i]) + << " to avoid collision with ST" << j << '\n'); + PendingST[i] = SR; + } + continue; + } + unsigned SR = getScratchReg(); + DEBUG(dbgs() << "Emitting LD_F0 for ST" << i << " in FP" << SR << '\n'); + BuildMI(*MBB, I, MI->getDebugLoc(), TII->get(X86::LD_F0)); + pushReg(SR); + PendingST[i] = SR; + if (NumPendingSTs == i) + ++NumPendingSTs; + } + assert(NumPendingSTs >= NumSTUses && "Fixed registers should be assigned"); + + // Now we can rearrange the live registers to match what was requested. + shuffleStackTop(PendingST, NumPendingSTs, I); + DEBUG({dbgs() << "Before asm: "; dumpStack();}); + + // With the stack layout fixed, rewrite the FP registers. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &Op = MI->getOperand(i); + if (!Op.isReg() || Op.getReg() < X86::FP0 || Op.getReg() > X86::FP6) + continue; + unsigned FPReg = getFPReg(Op); + Op.setReg(getSTReg(FPReg)); + } + + // Simulate the inline asm popping its inputs and pushing its outputs. + StackTop -= NumSTPopped; + + // Hold the fixed output registers in scratch FP registers. They will be + // transferred to real FP registers by copies. + NumPendingSTs = 0; + for (unsigned i = 0; i < NumSTDefs; ++i) { + unsigned SR = getScratchReg(); + pushReg(SR); + FPKills &= ~(1u << SR); + } + for (unsigned i = 0; i < NumSTDefs; ++i) + PendingST[NumPendingSTs++] = getStackEntry(i); + DEBUG({dbgs() << "After asm: "; dumpStack();}); + + // If any of the ST defs were dead, pop them immediately. Our caller only + // handles dead FP defs. + MachineBasicBlock::iterator InsertPt = MI; + for (unsigned i = 0; STDefs & (1u << i); ++i) { + if (!(STDeadDefs & (1u << i))) + continue; + freeStackSlotAfter(InsertPt, PendingST[i]); + PendingST[i] = NumFPRegs; } + while (NumPendingSTs && PendingST[NumPendingSTs - 1] == NumFPRegs) + --NumPendingSTs; // If this asm kills any FP registers (is the last use of them) we must // explicitly emit pop instructions for them. Do this now after the asm has @@ -1382,16 +1600,16 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) { // // Note: this might be a non-optimal pop sequence. We might be able to do // better by trying to pop in stack order or something. - MachineBasicBlock::iterator InsertPt = MI; - while (Kills) { - unsigned FPReg = CountTrailingZeros_32(Kills); - freeStackSlotAfter(InsertPt, FPReg); - Kills &= ~(1U << FPReg); + while (FPKills) { + unsigned FPReg = CountTrailingZeros_32(FPKills); + if (isLive(FPReg)) + freeStackSlotAfter(InsertPt, FPReg); + FPKills &= ~(1U << FPReg); } // Don't delete the inline asm! return; } - + case X86::RET: case X86::RETI: // If RET has an FP register use operand, pass the first one in ST(0) and @@ -1489,33 +1707,3 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) { } else --I; } - -// Translate a COPY instruction to a pseudo-op that handleSpecialFP understands. -bool FPS::translateCopy(MachineInstr *MI) { - unsigned DstReg = MI->getOperand(0).getReg(); - unsigned SrcReg = MI->getOperand(1).getReg(); - - if (DstReg == X86::ST0) { - MI->setDesc(TII->get(X86::FpSET_ST0_80)); - MI->RemoveOperand(0); - return true; - } - if (DstReg == X86::ST1) { - MI->setDesc(TII->get(X86::FpSET_ST1_80)); - MI->RemoveOperand(0); - return true; - } - if (SrcReg == X86::ST0) { - MI->setDesc(TII->get(X86::FpGET_ST0_80)); - return true; - } - if (SrcReg == X86::ST1) { - MI->setDesc(TII->get(X86::FpGET_ST1_80)); - return true; - } - if (X86::RFP80RegClass.contains(DstReg, SrcReg)) { - MI->setDesc(TII->get(X86::MOV_Fp8080)); - return true; - } - return false; -} diff --git a/lib/Target/X86/X86FrameLowering.cpp b/lib/Target/X86/X86FrameLowering.cpp index 2e95300160d8..ed45a9a4c1c0 100644 --- a/lib/Target/X86/X86FrameLowering.cpp +++ b/lib/Target/X86/X86FrameLowering.cpp @@ -1,4 +1,4 @@ -//=======- X86FrameLowering.cpp - X86 Frame Information ------------*- C++ -*-====// +//=======- X86FrameLowering.cpp - X86 Frame Information --------*- C++ -*-====// // // The LLVM Compiler Infrastructure // @@ -23,6 +23,7 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Support/CommandLine.h" @@ -160,8 +161,10 @@ void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, Opc = isSub ? (Is64Bit ? X86::PUSH64r : X86::PUSH32r) : (Is64Bit ? X86::POP64r : X86::POP32r); - BuildMI(MBB, MBBI, DL, TII.get(Opc)) + MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII.get(Opc)) .addReg(Reg, getDefRegState(!isSub) | getUndefRegState(isSub)); + if (isSub) + MI->setFlag(MachineInstr::FrameSetup); Offset -= ThisVal; continue; } @@ -171,6 +174,8 @@ void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr) .addReg(StackPtr) .addImm(ThisVal); + if (isSub) + MI->setFlag(MachineInstr::FrameSetup); MI->getOperand(3).setIsDead(); // The EFLAGS implicit def is dead. Offset -= ThisVal; } @@ -409,7 +414,8 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const { TII.get(getSUBriOpcode(Is64Bit, -TailCallReturnAddrDelta)), StackPtr) .addReg(StackPtr) - .addImm(-TailCallReturnAddrDelta); + .addImm(-TailCallReturnAddrDelta) + .setMIFlag(MachineInstr::FrameSetup); MI->getOperand(3).setIsDead(); // The EFLAGS implicit def is dead. } @@ -447,7 +453,8 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const { // Save EBP/RBP into the appropriate stack slot. BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64r : X86::PUSH32r)) - .addReg(FramePtr, RegState::Kill); + .addReg(FramePtr, RegState::Kill) + .setMIFlag(MachineInstr::FrameSetup); if (needsFrameMoves) { // Mark the place where EBP/RBP was saved. @@ -474,7 +481,8 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const { // Update EBP with the new base value... BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr), FramePtr) - .addReg(StackPtr); + .addReg(StackPtr) + .setMIFlag(MachineInstr::FrameSetup); if (needsFrameMoves) { // Mark effective beginning of when frame pointer becomes valid. @@ -642,7 +650,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const { } void X86FrameLowering::emitEpilogue(MachineFunction &MF, - MachineBasicBlock &MBB) const { + MachineBasicBlock &MBB) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>(); const X86RegisterInfo *RegInfo = TM.getRegisterInfo(); @@ -919,7 +927,8 @@ bool X86FrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, // X86RegisterInfo::emitPrologue will handle spilling of frame register. continue; CalleeFrameSize += SlotSize; - BuildMI(MBB, MI, DL, TII.get(Opc)).addReg(Reg, RegState::Kill); + BuildMI(MBB, MI, DL, TII.get(Opc)).addReg(Reg, RegState::Kill) + .setMIFlag(MachineInstr::FrameSetup); } X86FI->setCalleeSavedFrameSize(CalleeFrameSize); @@ -1021,3 +1030,181 @@ X86FrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, FrameIdx = 0; } } + +/// permuteEncode - Create the permutation encoding used with frameless +/// stacks. It is passed the number of registers to be saved and an array of the +/// registers saved. +static uint32_t permuteEncode(unsigned SavedCount, unsigned Registers[6]) { + // The saved registers are numbered from 1 to 6. In order to encode the order + // in which they were saved, we re-number them according to their place in the + // register order. The re-numbering is relative to the last re-numbered + // register. E.g., if we have registers {6, 2, 4, 5} saved in that order: + // + // Orig Re-Num + // ---- ------ + // 6 6 + // 2 2 + // 4 3 + // 5 3 + // + bool Used[7] = { false, false, false, false, false, false, false }; + uint32_t RenumRegs[6]; + for (unsigned I = 0; I < SavedCount; ++I) { + uint32_t Renum = 0; + for (unsigned U = 1; U < 7; ++U) { + if (U == Registers[I]) + break; + if (!Used[U]) + ++Renum; + } + + Used[Registers[I]] = true; + RenumRegs[I] = Renum; + } + + // Take the renumbered values and encode them into a 10-bit number. + uint32_t permutationEncoding = 0; + switch (SavedCount) { + case 6: + permutationEncoding |= 120 * RenumRegs[0] + 24 * RenumRegs[1] + + 6 * RenumRegs[2] + 2 * RenumRegs[3] + + RenumRegs[4]; + break; + case 5: + permutationEncoding |= 120 * RenumRegs[0] + 24 * RenumRegs[1] + + 6 * RenumRegs[2] + 2 * RenumRegs[3] + + RenumRegs[4]; + break; + case 4: + permutationEncoding |= 60 * RenumRegs[0] + 12 * RenumRegs[1] + + 3 * RenumRegs[2] + RenumRegs[3]; + break; + case 3: + permutationEncoding |= 20 * RenumRegs[0] + 4 * RenumRegs[1] + + RenumRegs[2]; + break; + case 2: + permutationEncoding |= 5 * RenumRegs[0] + RenumRegs[1]; + break; + case 1: + permutationEncoding |= RenumRegs[0]; + break; + } + + return permutationEncoding; +} + +uint32_t X86FrameLowering:: +getCompactUnwindEncoding(ArrayRef<MCCFIInstruction> Instrs, + int DataAlignmentFactor, bool IsEH) const { + uint32_t Encoding = 0; + int CFAOffset = 0; + const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + unsigned SavedRegs[6] = { 0, 0, 0, 0, 0, 0 }; + unsigned SavedRegIdx = 0; + int FramePointerReg = -1; + + for (ArrayRef<MCCFIInstruction>::const_iterator + I = Instrs.begin(), E = Instrs.end(); I != E; ++I) { + const MCCFIInstruction &Inst = *I; + MCSymbol *Label = Inst.getLabel(); + + // Ignore invalid labels. + if (Label && !Label->isDefined()) continue; + + unsigned Operation = Inst.getOperation(); + if (Operation != MCCFIInstruction::Move && + Operation != MCCFIInstruction::RelMove) + // FIXME: We can't handle this frame just yet. + return 0; + + const MachineLocation &Dst = Inst.getDestination(); + const MachineLocation &Src = Inst.getSource(); + const bool IsRelative = (Operation == MCCFIInstruction::RelMove); + + if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { + if (Src.getReg() != MachineLocation::VirtualFP) { + // DW_CFA_def_cfa + assert(FramePointerReg == -1 &&"Defining more than one frame pointer?"); + if (TRI->getLLVMRegNum(Src.getReg(), IsEH) != X86::EBP && + TRI->getLLVMRegNum(Src.getReg(), IsEH) != X86::RBP) + // The frame pointer isn't EBP/RBP. Cannot make unwind information + // compact. + return 0; + FramePointerReg = TRI->getCompactUnwindRegNum(Src.getReg(), IsEH); + } // else DW_CFA_def_cfa_offset + + if (IsRelative) + CFAOffset += Src.getOffset(); + else + CFAOffset -= Src.getOffset(); + + continue; + } + + if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) { + // DW_CFA_def_cfa_register + assert(FramePointerReg == -1 && "Defining more than one frame pointer?"); + + if (TRI->getLLVMRegNum(Dst.getReg(), IsEH) != X86::EBP && + TRI->getLLVMRegNum(Dst.getReg(), IsEH) != X86::RBP) + // The frame pointer isn't EBP/RBP. Cannot make unwind information + // compact. + return 0; + + FramePointerReg = TRI->getCompactUnwindRegNum(Dst.getReg(), IsEH); + if (SavedRegIdx != 1 || SavedRegs[0] != unsigned(FramePointerReg)) + return 0; + + SavedRegs[0] = 0; + SavedRegIdx = 0; + continue; + } + + unsigned Reg = Src.getReg(); + int Offset = Dst.getOffset(); + if (IsRelative) + Offset -= CFAOffset; + Offset /= DataAlignmentFactor; + + if (Offset < 0) { + // FIXME: Handle? + // DW_CFA_offset_extended_sf + return 0; + } else if (Reg < 64) { + // DW_CFA_offset + Reg + if (SavedRegIdx >= 6) return 0; + int CURegNum = TRI->getCompactUnwindRegNum(Reg, IsEH); + if (CURegNum == -1) return 0; + SavedRegs[SavedRegIdx++] = CURegNum; + } else { + // FIXME: Handle? + // DW_CFA_offset_extended + return 0; + } + } + + // Bail if there are too many registers to encode. + if (SavedRegIdx > 6) return 0; + + // Check if the offset is too big. + CFAOffset /= 4; + if ((CFAOffset & 0xFF) != CFAOffset) + return 0; + Encoding |= (CFAOffset & 0xFF) << 16; // Size encoding. + + if (FramePointerReg != -1) { + Encoding |= 0x01000000; // EBP/RBP Unwind Frame + for (unsigned I = 0; I != SavedRegIdx; ++I) { + unsigned Reg = SavedRegs[I]; + if (Reg == unsigned(FramePointerReg)) continue; + Encoding |= (Reg & 0x7) << (I * 3); // Register encoding + } + } else { + Encoding |= 0x02000000; // Frameless unwind with small stack + Encoding |= (SavedRegIdx & 0x7) << 10; + Encoding |= permuteEncode(SavedRegIdx, SavedRegs); + } + + return Encoding; +} diff --git a/lib/Target/X86/X86FrameLowering.h b/lib/Target/X86/X86FrameLowering.h index d71108cd0586..14c31ed47cf1 100644 --- a/lib/Target/X86/X86FrameLowering.h +++ b/lib/Target/X86/X86FrameLowering.h @@ -15,6 +15,7 @@ #define X86_FRAMELOWERING_H #include "X86Subtarget.h" +#include "llvm/MC/MCDwarf.h" #include "llvm/Target/TargetFrameLowering.h" namespace llvm { @@ -58,6 +59,9 @@ public: void getInitialFrameState(std::vector<MachineMove> &Moves) const; int getFrameIndexOffset(const MachineFunction &MF, int FI) const; + + uint32_t getCompactUnwindEncoding(ArrayRef<MCCFIInstruction> Instrs, + int DataAlignmentFactor, bool IsEH) const; }; } // End llvm namespace diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index 1fcc274e0f85..2b0f283bec75 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -23,6 +23,7 @@ #include "llvm/Intrinsics.h" #include "llvm/Support/CFG.h" #include "llvm/Type.h" +#include "llvm/CodeGen/FunctionLoweringInfo.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -191,6 +192,7 @@ namespace { SDNode *SelectAtomicLoadAdd(SDNode *Node, EVT NVT); SDNode *SelectAtomicLoadArith(SDNode *Node, EVT NVT); + bool FoldOffsetIntoAddress(uint64_t Offset, X86ISelAddressMode &AM); bool MatchLoadInAddress(LoadSDNode *N, X86ISelAddressMode &AM); bool MatchWrapper(SDValue N, X86ISelAddressMode &AM); bool MatchAddress(SDValue N, X86ISelAddressMode &AM); @@ -546,6 +548,34 @@ void X86DAGToDAGISel::EmitFunctionEntryCode() { EmitSpecialCodeForMain(MF->begin(), MF->getFrameInfo()); } +static bool isDispSafeForFrameIndex(int64_t Val) { + // On 64-bit platforms, we can run into an issue where a frame index + // includes a displacement that, when added to the explicit displacement, + // will overflow the displacement field. Assuming that the frame index + // displacement fits into a 31-bit integer (which is only slightly more + // aggressive than the current fundamental assumption that it fits into + // a 32-bit integer), a 31-bit disp should always be safe. + return isInt<31>(Val); +} + +bool X86DAGToDAGISel::FoldOffsetIntoAddress(uint64_t Offset, + X86ISelAddressMode &AM) { + int64_t Val = AM.Disp + Offset; + CodeModel::Model M = TM.getCodeModel(); + if (Subtarget->is64Bit()) { + if (!X86::isOffsetSuitableForCodeModel(Val, M, + AM.hasSymbolicDisplacement())) + return true; + // In addition to the checks required for a register base, check that + // we do not try to use an unsafe Disp with a frame index. + if (AM.BaseType == X86ISelAddressMode::FrameIndexBase && + !isDispSafeForFrameIndex(Val)) + return true; + } + AM.Disp = Val; + return false; + +} bool X86DAGToDAGISel::MatchLoadInAddress(LoadSDNode *N, X86ISelAddressMode &AM){ SDValue Address = N->getOperand(1); @@ -595,18 +625,22 @@ bool X86DAGToDAGISel::MatchWrapper(SDValue N, X86ISelAddressMode &AM) { // must allow RIP. !AM.hasBaseOrIndexReg() && N.getOpcode() == X86ISD::WrapperRIP) { if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) { - int64_t Offset = AM.Disp + G->getOffset(); - if (!X86::isOffsetSuitableForCodeModel(Offset, M)) return true; + X86ISelAddressMode Backup = AM; AM.GV = G->getGlobal(); - AM.Disp = Offset; AM.SymbolFlags = G->getTargetFlags(); + if (FoldOffsetIntoAddress(G->getOffset(), AM)) { + AM = Backup; + return true; + } } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N0)) { - int64_t Offset = AM.Disp + CP->getOffset(); - if (!X86::isOffsetSuitableForCodeModel(Offset, M)) return true; + X86ISelAddressMode Backup = AM; AM.CP = CP->getConstVal(); AM.Align = CP->getAlignment(); - AM.Disp = Offset; AM.SymbolFlags = CP->getTargetFlags(); + if (FoldOffsetIntoAddress(CP->getOffset(), AM)) { + AM = Backup; + return true; + } } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(N0)) { AM.ES = S->getSymbol(); AM.SymbolFlags = S->getTargetFlags(); @@ -688,7 +722,6 @@ bool X86DAGToDAGISel::MatchAddress(SDValue N, X86ISelAddressMode &AM) { bool X86DAGToDAGISel::MatchAddressRecursively(SDValue N, X86ISelAddressMode &AM, unsigned Depth) { - bool is64Bit = Subtarget->is64Bit(); DebugLoc dl = N.getDebugLoc(); DEBUG({ dbgs() << "MatchAddress: "; @@ -698,8 +731,6 @@ bool X86DAGToDAGISel::MatchAddressRecursively(SDValue N, X86ISelAddressMode &AM, if (Depth > 5) return MatchAddressBase(N, AM); - CodeModel::Model M = TM.getCodeModel(); - // If this is already a %rip relative address, we can only merge immediates // into it. Instead of handling this in every case, we handle it here. // RIP relative addressing: %rip + 32-bit displacement! @@ -709,14 +740,9 @@ bool X86DAGToDAGISel::MatchAddressRecursively(SDValue N, X86ISelAddressMode &AM, // consistency. if (!AM.ES && AM.JT != -1) return true; - if (ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(N)) { - int64_t Val = AM.Disp + Cst->getSExtValue(); - if (X86::isOffsetSuitableForCodeModel(Val, M, - AM.hasSymbolicDisplacement())) { - AM.Disp = Val; + if (ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(N)) + if (!FoldOffsetIntoAddress(Cst->getSExtValue(), AM)) return false; - } - } return true; } @@ -724,12 +750,8 @@ bool X86DAGToDAGISel::MatchAddressRecursively(SDValue N, X86ISelAddressMode &AM, default: break; case ISD::Constant: { uint64_t Val = cast<ConstantSDNode>(N)->getSExtValue(); - if (!is64Bit || - X86::isOffsetSuitableForCodeModel(AM.Disp + Val, M, - AM.hasSymbolicDisplacement())) { - AM.Disp += Val; + if (!FoldOffsetIntoAddress(Val, AM)) return false; - } break; } @@ -745,8 +767,9 @@ bool X86DAGToDAGISel::MatchAddressRecursively(SDValue N, X86ISelAddressMode &AM, break; case ISD::FrameIndex: - if (AM.BaseType == X86ISelAddressMode::RegBase - && AM.Base_Reg.getNode() == 0) { + if (AM.BaseType == X86ISelAddressMode::RegBase && + AM.Base_Reg.getNode() == 0 && + (!Subtarget->is64Bit() || isDispSafeForFrameIndex(AM.Disp))) { AM.BaseType = X86ISelAddressMode::FrameIndexBase; AM.Base_FrameIndex = cast<FrameIndexSDNode>(N)->getIndex(); return false; @@ -775,16 +798,12 @@ bool X86DAGToDAGISel::MatchAddressRecursively(SDValue N, X86ISelAddressMode &AM, AM.IndexReg = ShVal.getNode()->getOperand(0); ConstantSDNode *AddVal = cast<ConstantSDNode>(ShVal.getNode()->getOperand(1)); - uint64_t Disp = AM.Disp + (AddVal->getSExtValue() << Val); - if (!is64Bit || - X86::isOffsetSuitableForCodeModel(Disp, M, - AM.hasSymbolicDisplacement())) - AM.Disp = Disp; - else - AM.IndexReg = ShVal; - } else { - AM.IndexReg = ShVal; + uint64_t Disp = AddVal->getSExtValue() << Val; + if (!FoldOffsetIntoAddress(Disp, AM)) + return false; } + + AM.IndexReg = ShVal; return false; } break; @@ -818,13 +837,8 @@ bool X86DAGToDAGISel::MatchAddressRecursively(SDValue N, X86ISelAddressMode &AM, Reg = MulVal.getNode()->getOperand(0); ConstantSDNode *AddVal = cast<ConstantSDNode>(MulVal.getNode()->getOperand(1)); - uint64_t Disp = AM.Disp + AddVal->getSExtValue() * - CN->getZExtValue(); - if (!is64Bit || - X86::isOffsetSuitableForCodeModel(Disp, M, - AM.hasSymbolicDisplacement())) - AM.Disp = Disp; - else + uint64_t Disp = AddVal->getSExtValue() * CN->getZExtValue(); + if (FoldOffsetIntoAddress(Disp, AM)) Reg = N.getNode()->getOperand(0); } else { Reg = N.getNode()->getOperand(0); @@ -949,19 +963,11 @@ bool X86DAGToDAGISel::MatchAddressRecursively(SDValue N, X86ISelAddressMode &AM, if (CurDAG->isBaseWithConstantOffset(N)) { X86ISelAddressMode Backup = AM; ConstantSDNode *CN = cast<ConstantSDNode>(N.getOperand(1)); - uint64_t Offset = CN->getSExtValue(); // Start with the LHS as an addr mode. if (!MatchAddressRecursively(N.getOperand(0), AM, Depth+1) && - // Address could not have picked a GV address for the displacement. - AM.GV == NULL && - // On x86-64, the resultant disp must fit in 32-bits. - (!is64Bit || - X86::isOffsetSuitableForCodeModel(AM.Disp + Offset, M, - AM.hasSymbolicDisplacement()))) { - AM.Disp += Offset; + !FoldOffsetIntoAddress(CN->getSExtValue(), AM)) return false; - } AM = Backup; } break; @@ -1351,7 +1357,7 @@ SDNode *X86DAGToDAGISel::SelectAtomicLoadAdd(SDNode *Node, EVT NVT) { bool isInc = false, isDec = false, isSub = false, isCN = false; ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val); - if (CN) { + if (CN && CN->getSExtValue() == (int32_t)CN->getSExtValue()) { isCN = true; int64_t CNVal = CN->getSExtValue(); if (CNVal == 1) @@ -1371,6 +1377,7 @@ SDNode *X86DAGToDAGISel::SelectAtomicLoadAdd(SDNode *Node, EVT NVT) { Val = Val.getOperand(1); } + DebugLoc dl = Node->getDebugLoc(); unsigned Opc = 0; switch (NVT.getSimpleVT().SimpleTy) { default: return 0; @@ -1462,7 +1469,6 @@ SDNode *X86DAGToDAGISel::SelectAtomicLoadAdd(SDNode *Node, EVT NVT) { break; } - DebugLoc dl = Node->getDebugLoc(); SDValue Undef = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, NVT), 0); MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); @@ -1579,7 +1585,7 @@ SDNode *X86DAGToDAGISel::SelectAtomicLoadArith(SDNode *Node, EVT NVT) { bool isCN = false; ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val); - if (CN) { + if (CN && (int32_t)CN->getSExtValue() == CN->getSExtValue()) { isCN = true; Val = CurDAG->getTargetConstant(CN->getSExtValue(), NVT); } @@ -1612,16 +1618,18 @@ SDNode *X86DAGToDAGISel::SelectAtomicLoadArith(SDNode *Node, EVT NVT) { Opc = AtomicOpcTbl[Op][I32]; break; case MVT::i64: + Opc = AtomicOpcTbl[Op][I64]; if (isCN) { if (immSext8(Val.getNode())) Opc = AtomicOpcTbl[Op][SextConstantI64]; else if (i64immSExt32(Val.getNode())) Opc = AtomicOpcTbl[Op][ConstantI64]; - } else - Opc = AtomicOpcTbl[Op][I64]; + } break; } + assert(Opc != 0 && "Invalid arith lock transform!"); + DebugLoc dl = Node->getDebugLoc(); SDValue Undef = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, NVT), 0); diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 294a6a74cc77..5096d9ae2edf 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -235,10 +235,16 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) // Setup Windows compiler runtime calls. setLibcallName(RTLIB::SDIV_I64, "_alldiv"); setLibcallName(RTLIB::UDIV_I64, "_aulldiv"); + setLibcallName(RTLIB::SREM_I64, "_allrem"); + setLibcallName(RTLIB::UREM_I64, "_aullrem"); + setLibcallName(RTLIB::MUL_I64, "_allmul"); setLibcallName(RTLIB::FPTOUINT_F64_I64, "_ftol2"); setLibcallName(RTLIB::FPTOUINT_F32_I64, "_ftol2"); setLibcallCallingConv(RTLIB::SDIV_I64, CallingConv::X86_StdCall); setLibcallCallingConv(RTLIB::UDIV_I64, CallingConv::X86_StdCall); + setLibcallCallingConv(RTLIB::SREM_I64, CallingConv::X86_StdCall); + setLibcallCallingConv(RTLIB::UREM_I64, CallingConv::X86_StdCall); + setLibcallCallingConv(RTLIB::MUL_I64, CallingConv::X86_StdCall); setLibcallCallingConv(RTLIB::FPTOUINT_F64_I64, CallingConv::C); setLibcallCallingConv(RTLIB::FPTOUINT_F32_I64, CallingConv::C); } @@ -646,6 +652,10 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) addLegalFPImmediate(APFloat(-1.0f)); // FLD1/FCHS } + // We don't support FMA. + setOperationAction(ISD::FMA, MVT::f64, Expand); + setOperationAction(ISD::FMA, MVT::f32, Expand); + // Long double always uses X87. if (!UseSoftFloat) { addRegisterClass(MVT::f80, X86::RFP80RegisterClass); @@ -670,6 +680,8 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) setOperationAction(ISD::FSIN , MVT::f80 , Expand); setOperationAction(ISD::FCOS , MVT::f80 , Expand); } + + setOperationAction(ISD::FMA, MVT::f80, Expand); } // Always use a library call for pow. @@ -976,7 +988,6 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) addRegisterClass(MVT::v32i8, X86::VR256RegisterClass); setOperationAction(ISD::LOAD, MVT::v8f32, Legal); - setOperationAction(ISD::LOAD, MVT::v8i32, Legal); setOperationAction(ISD::LOAD, MVT::v4f64, Legal); setOperationAction(ISD::LOAD, MVT::v4i64, Legal); @@ -994,63 +1005,58 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) setOperationAction(ISD::FSQRT, MVT::v4f64, Legal); setOperationAction(ISD::FNEG, MVT::v4f64, Custom); - // Custom lower build_vector, vector_shuffle, scalar_to_vector, - // insert_vector_elt extract_subvector and extract_vector_elt for - // 256-bit types. - for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE; - i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; - ++i) { - MVT::SimpleValueType VT = (MVT::SimpleValueType)i; - // Do not attempt to custom lower non-256-bit vectors - if (!isPowerOf2_32(MVT(VT).getVectorNumElements()) - || (MVT(VT).getSizeInBits() < 256)) - continue; - setOperationAction(ISD::BUILD_VECTOR, VT, Custom); - setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom); - setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom); - setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom); - setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom); - } - // Custom-lower insert_subvector and extract_subvector based on - // the result type. + // Custom lower several nodes for 256-bit types. for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE; - i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; - ++i) { - MVT::SimpleValueType VT = (MVT::SimpleValueType)i; - // Do not attempt to custom lower non-256-bit vectors - if (!isPowerOf2_32(MVT(VT).getVectorNumElements())) + i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) { + MVT::SimpleValueType SVT = (MVT::SimpleValueType)i; + EVT VT = SVT; + + // Extract subvector is special because the value type + // (result) is 128-bit but the source is 256-bit wide. + if (VT.is128BitVector()) + setOperationAction(ISD::EXTRACT_SUBVECTOR, SVT, Custom); + + // Do not attempt to custom lower other non-256-bit vectors + if (!VT.is256BitVector()) continue; - if (MVT(VT).getSizeInBits() == 128) { - setOperationAction(ISD::EXTRACT_SUBVECTOR, VT, Custom); - } - else if (MVT(VT).getSizeInBits() == 256) { - setOperationAction(ISD::INSERT_SUBVECTOR, VT, Custom); - } + setOperationAction(ISD::BUILD_VECTOR, SVT, Custom); + setOperationAction(ISD::VECTOR_SHUFFLE, SVT, Custom); + setOperationAction(ISD::INSERT_VECTOR_ELT, SVT, Custom); + setOperationAction(ISD::EXTRACT_VECTOR_ELT, SVT, Custom); + setOperationAction(ISD::SCALAR_TO_VECTOR, SVT, Custom); + setOperationAction(ISD::INSERT_SUBVECTOR, SVT, Custom); } // Promote v32i8, v16i16, v8i32 select, and, or, xor to v4i64. - // Don't promote loads because we need them for VPERM vector index versions. + for (unsigned i = (unsigned)MVT::v32i8; i != (unsigned)MVT::v4i64; ++i) { + MVT::SimpleValueType SVT = (MVT::SimpleValueType)i; + EVT VT = SVT; - for (unsigned VT = (unsigned)MVT::FIRST_VECTOR_VALUETYPE; - VT != (unsigned)MVT::LAST_VECTOR_VALUETYPE; - VT++) { - if (!isPowerOf2_32(MVT((MVT::SimpleValueType)VT).getVectorNumElements()) - || (MVT((MVT::SimpleValueType)VT).getSizeInBits() < 256)) + // Do not attempt to promote non-256-bit vectors + if (!VT.is256BitVector()) continue; - setOperationAction(ISD::AND, (MVT::SimpleValueType)VT, Promote); - AddPromotedToType (ISD::AND, (MVT::SimpleValueType)VT, MVT::v4i64); - setOperationAction(ISD::OR, (MVT::SimpleValueType)VT, Promote); - AddPromotedToType (ISD::OR, (MVT::SimpleValueType)VT, MVT::v4i64); - setOperationAction(ISD::XOR, (MVT::SimpleValueType)VT, Promote); - AddPromotedToType (ISD::XOR, (MVT::SimpleValueType)VT, MVT::v4i64); - //setOperationAction(ISD::LOAD, (MVT::SimpleValueType)VT, Promote); - //AddPromotedToType (ISD::LOAD, (MVT::SimpleValueType)VT, MVT::v4i64); - setOperationAction(ISD::SELECT, (MVT::SimpleValueType)VT, Promote); - AddPromotedToType (ISD::SELECT, (MVT::SimpleValueType)VT, MVT::v4i64); + + setOperationAction(ISD::AND, SVT, Promote); + AddPromotedToType (ISD::AND, SVT, MVT::v4i64); + setOperationAction(ISD::OR, SVT, Promote); + AddPromotedToType (ISD::OR, SVT, MVT::v4i64); + setOperationAction(ISD::XOR, SVT, Promote); + AddPromotedToType (ISD::XOR, SVT, MVT::v4i64); + setOperationAction(ISD::LOAD, SVT, Promote); + AddPromotedToType (ISD::LOAD, SVT, MVT::v4i64); + setOperationAction(ISD::SELECT, SVT, Promote); + AddPromotedToType (ISD::SELECT, SVT, MVT::v4i64); } } + // SIGN_EXTEND_INREGs are evaluated by the extend type. Handle the expansion + // of this type with custom code. + for (unsigned VT = (unsigned)MVT::FIRST_VECTOR_VALUETYPE; + VT != (unsigned)MVT::LAST_VECTOR_VALUETYPE; VT++) { + setOperationAction(ISD::SIGN_EXTEND_INREG, (MVT::SimpleValueType)VT, Custom); + } + // We want to custom lower some of our intrinsics. setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); @@ -1511,20 +1517,15 @@ X86TargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, // If this is a call to a function that returns an fp value on the floating // point stack, we must guarantee the the value is popped from the stack, so // a CopyFromReg is not good enough - the copy instruction may be eliminated - // if the return value is not used. We use the FpGET_ST0 instructions + // if the return value is not used. We use the FpPOP_RETVAL instruction // instead. if (VA.getLocReg() == X86::ST0 || VA.getLocReg() == X86::ST1) { // If we prefer to use the value in xmm registers, copy it out as f80 and // use a truncate to move it from fp stack reg to xmm reg. if (isScalarFPTypeInSSEReg(VA.getValVT())) CopyVT = MVT::f80; - bool isST0 = VA.getLocReg() == X86::ST0; - unsigned Opc = 0; - if (CopyVT == MVT::f32) Opc = isST0 ? X86::FpGET_ST0_32:X86::FpGET_ST1_32; - if (CopyVT == MVT::f64) Opc = isST0 ? X86::FpGET_ST0_64:X86::FpGET_ST1_64; - if (CopyVT == MVT::f80) Opc = isST0 ? X86::FpGET_ST0_80:X86::FpGET_ST1_80; SDValue Ops[] = { Chain, InFlag }; - Chain = SDValue(DAG.getMachineNode(Opc, dl, CopyVT, MVT::Other, MVT::Glue, - Ops, 2), 1); + Chain = SDValue(DAG.getMachineNode(X86::FpPOP_RETVAL, dl, CopyVT, + MVT::Other, MVT::Glue, Ops, 2), 1); Val = Chain.getValue(0); // Round the f80 to the right size, which also moves it to the appropriate @@ -1898,7 +1899,7 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain, } // Some CCs need callee pop. - if (Subtarget->IsCalleePop(isVarArg, CallConv)) { + if (X86::isCalleePop(CallConv, Is64Bit, isVarArg, GuaranteedTailCallOpt)) { FuncInfo->setBytesToPopOnReturn(StackSize); // Callee pops everything. } else { FuncInfo->setBytesToPopOnReturn(0); // Callee pops nothing. @@ -2271,6 +2272,8 @@ X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee, const GlobalValue *GV = G->getGlobal(); if (!GV->hasDLLImportLinkage()) { unsigned char OpFlags = 0; + bool ExtraLoad = false; + unsigned WrapperKind = ISD::DELETED_NODE; // On ELF targets, in both X86-64 and X86-32 mode, direct calls to // external symbols most go through the PLT in PIC mode. If the symbol @@ -2288,10 +2291,28 @@ X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee, // unless we're building with the leopard linker or later, which // automatically synthesizes these stubs. OpFlags = X86II::MO_DARWIN_STUB; + } else if (Subtarget->isPICStyleRIPRel() && + isa<Function>(GV) && + cast<Function>(GV)->hasFnAttr(Attribute::NonLazyBind)) { + // If the function is marked as non-lazy, generate an indirect call + // which loads from the GOT directly. This avoids runtime overhead + // at the cost of eager binding (and one extra byte of encoding). + OpFlags = X86II::MO_GOTPCREL; + WrapperKind = X86ISD::WrapperRIP; + ExtraLoad = true; } Callee = DAG.getTargetGlobalAddress(GV, dl, getPointerTy(), G->getOffset(), OpFlags); + + // Add a wrapper if needed. + if (WrapperKind != ISD::DELETED_NODE) + Callee = DAG.getNode(X86ISD::WrapperRIP, dl, getPointerTy(), Callee); + // Add extra indirection if needed. + if (ExtraLoad) + Callee = DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), Callee, + MachinePointerInfo::getGOT(), + false, false, 0); } } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) { unsigned char OpFlags = 0; @@ -2363,7 +2384,7 @@ X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee, // Create the CALLSEQ_END node. unsigned NumBytesForCalleeToPush; - if (Subtarget->IsCalleePop(isVarArg, CallConv)) + if (X86::isCalleePop(CallConv, Is64Bit, isVarArg, GuaranteedTailCallOpt)) NumBytesForCalleeToPush = NumBytes; // Callee pops everything else if (!Is64Bit && !IsTailCallConvention(CallConv) && IsStructRet) // If this is a call to a struct-return function, the callee @@ -2485,6 +2506,10 @@ bool MatchingStackOffset(SDValue Arg, unsigned Offset, ISD::ArgFlagsTy Flags, if (!FINode) return false; FI = FINode->getIndex(); + } else if (Arg.getOpcode() == ISD::FrameIndex && Flags.isByVal()) { + FrameIndexSDNode *FINode = cast<FrameIndexSDNode>(Arg); + FI = FINode->getIndex(); + Bytes = Flags.getByValSize(); } else return false; @@ -2536,6 +2561,11 @@ X86TargetLowering::IsEligibleForTailCallOptimization(SDValue Callee, if (isCalleeStructRet || isCallerStructRet) return false; + // An stdcall caller is expected to clean up its arguments; the callee + // isn't going to do that. + if (!CCMatch && CallerCC==CallingConv::X86_StdCall) + return false; + // Do not sibcall optimize vararg calls unless all arguments are passed via // registers. if (isVarArg && !Outs.empty()) { @@ -2672,11 +2702,6 @@ X86TargetLowering::IsEligibleForTailCallOptimization(SDValue Callee, } } - // An stdcall caller is expected to clean up its arguments; the callee - // isn't going to do that. - if (!CCMatch && CallerCC==CallingConv::X86_StdCall) - return false; - return true; } @@ -2856,6 +2881,29 @@ bool X86::isOffsetSuitableForCodeModel(int64_t Offset, CodeModel::Model M, return false; } +/// isCalleePop - Determines whether the callee is required to pop its +/// own arguments. Callee pop is necessary to support tail calls. +bool X86::isCalleePop(CallingConv::ID CallingConv, + bool is64Bit, bool IsVarArg, bool TailCallOpt) { + if (IsVarArg) + return false; + + switch (CallingConv) { + default: + return false; + case CallingConv::X86_StdCall: + return !is64Bit; + case CallingConv::X86_FastCall: + return !is64Bit; + case CallingConv::X86_ThisCall: + return !is64Bit; + case CallingConv::Fast: + return TailCallOpt; + case CallingConv::GHC: + return TailCallOpt; + } +} + /// TranslateX86CC - do a one to one translation of a ISD::CondCode to the X86 /// specific condition code, returning the condition code and the LHS/RHS of the /// comparison to make. @@ -3790,19 +3838,24 @@ static SDValue getZeroVector(EVT VT, bool HasSSE2, SelectionDAG &DAG, } /// getOnesVector - Returns a vector of specified type with all bits set. -/// +/// Always build ones vectors as <4 x i32> or <8 x i32> bitcasted to +/// their original type, ensuring they get CSE'd. static SDValue getOnesVector(EVT VT, SelectionDAG &DAG, DebugLoc dl) { assert(VT.isVector() && "Expected a vector type"); + assert((VT.is128BitVector() || VT.is256BitVector()) + && "Expected a 128-bit or 256-bit vector type"); - // Always build ones vectors as <4 x i32> or <2 x i32> bitcasted to their dest - // type. This ensures they get CSE'd. SDValue Cst = DAG.getTargetConstant(~0U, MVT::i32); + SDValue Vec; - Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, Cst, Cst, Cst, Cst); + if (VT.is256BitVector()) { + SDValue Ops[] = { Cst, Cst, Cst, Cst, Cst, Cst, Cst, Cst }; + Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v8i32, Ops, 8); + } else + Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, Cst, Cst, Cst, Cst); return DAG.getNode(ISD::BITCAST, dl, VT, Vec); } - /// NormalizeMask - V2 is a splat, modify the mask (if needed) so all elements /// that point to V2 points to its first element. static SDValue NormalizeMask(ShuffleVectorSDNode *SVOp, SelectionDAG &DAG) { @@ -4417,17 +4470,17 @@ X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const { return ConcatVectors(Lower, Upper, DAG); } - // All zero's are handled with pxor in SSE2 and above, xorps in SSE1. - // All one's are handled with pcmpeqd. In AVX, zero's are handled with - // vpxor in 128-bit and xor{pd,ps} in 256-bit, but no 256 version of pcmpeqd - // is present, so AllOnes is ignored. + // All zero's: + // - pxor (SSE2), xorps (SSE1), vpxor (128 AVX), xorp[s|d] (256 AVX) + // All one's: + // - pcmpeqd (SSE2 and 128 AVX), fallback to constant pools (256 AVX) if (ISD::isBuildVectorAllZeros(Op.getNode()) || - (Op.getValueType().getSizeInBits() != 256 && - ISD::isBuildVectorAllOnes(Op.getNode()))) { - // Canonicalize this to <4 x i32> (SSE) to + ISD::isBuildVectorAllOnes(Op.getNode())) { + // Canonicalize this to <4 x i32> or <8 x 32> (SSE) to // 1) ensure the zero vectors are CSE'd, and 2) ensure that i64 scalars are // eliminated on x86-32 hosts. - if (Op.getValueType() == MVT::v4i32) + if (Op.getValueType() == MVT::v4i32 || + Op.getValueType() == MVT::v8i32) return Op; if (ISD::isBuildVectorAllOnes(Op.getNode())) @@ -8874,8 +8927,8 @@ SDValue X86TargetLowering::LowerShift(SDValue Op, SelectionDAG &DAG) const { } // Lower SHL with variable shift amount. - // Cannot lower SHL without SSE4.1 or later. - if (!Subtarget->hasSSE41()) return SDValue(); + // Cannot lower SHL without SSE2 or later. + if (!Subtarget->hasSSE2()) return SDValue(); if (VT == MVT::v4i32 && Op->getOpcode() == ISD::SHL) { Op = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, VT, @@ -9022,13 +9075,66 @@ SDValue X86TargetLowering::LowerXALUO(SDValue Op, SelectionDAG &DAG) const { return Sum; } +SDValue X86TargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op, SelectionDAG &DAG) const{ + DebugLoc dl = Op.getDebugLoc(); + SDNode* Node = Op.getNode(); + EVT ExtraVT = cast<VTSDNode>(Node->getOperand(1))->getVT(); + EVT VT = Node->getValueType(0); + + if (Subtarget->hasSSE2() && VT.isVector()) { + unsigned BitsDiff = VT.getScalarType().getSizeInBits() - + ExtraVT.getScalarType().getSizeInBits(); + SDValue ShAmt = DAG.getConstant(BitsDiff, MVT::i32); + + unsigned SHLIntrinsicsID = 0; + unsigned SRAIntrinsicsID = 0; + switch (VT.getSimpleVT().SimpleTy) { + default: + return SDValue(); + case MVT::v2i64: { + SHLIntrinsicsID = Intrinsic::x86_sse2_pslli_q; + SRAIntrinsicsID = 0; + break; + } + case MVT::v4i32: { + SHLIntrinsicsID = Intrinsic::x86_sse2_pslli_d; + SRAIntrinsicsID = Intrinsic::x86_sse2_psrai_d; + break; + } + case MVT::v8i16: { + SHLIntrinsicsID = Intrinsic::x86_sse2_pslli_w; + SRAIntrinsicsID = Intrinsic::x86_sse2_psrai_w; + break; + } + } + + SDValue Tmp1 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, VT, + DAG.getConstant(SHLIntrinsicsID, MVT::i32), + Node->getOperand(0), ShAmt); + + // In case of 1 bit sext, no need to shr + if (ExtraVT.getScalarType().getSizeInBits() == 1) return Tmp1; + + if (SRAIntrinsicsID) { + Tmp1 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, VT, + DAG.getConstant(SRAIntrinsicsID, MVT::i32), + Tmp1, ShAmt); + } + return Tmp1; + } + + return SDValue(); +} + + SDValue X86TargetLowering::LowerMEMBARRIER(SDValue Op, SelectionDAG &DAG) const{ DebugLoc dl = Op.getDebugLoc(); - if (!Subtarget->hasSSE2()) { + // Go ahead and emit the fence on x86-64 even if we asked for no-sse2. + // There isn't any reason to disable it if the target processor supports it. + if (!Subtarget->hasSSE2() && !Subtarget->is64Bit()) { SDValue Chain = Op.getOperand(0); - SDValue Zero = DAG.getConstant(0, - Subtarget->is64Bit() ? MVT::i64 : MVT::i32); + SDValue Zero = DAG.getConstant(0, MVT::i32); SDValue Ops[] = { DAG.getRegister(X86::ESP, MVT::i32), // Base DAG.getTargetConstant(1, MVT::i8), // Scale @@ -9183,6 +9289,7 @@ static SDValue LowerADDC_ADDE_SUBC_SUBE(SDValue Op, SelectionDAG &DAG) { SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { switch (Op.getOpcode()) { default: llvm_unreachable("Should not custom lower this!"); + case ISD::SIGN_EXTEND_INREG: return LowerSIGN_EXTEND_INREG(Op,DAG); case ISD::MEMBARRIER: return LowerMEMBARRIER(Op,DAG); case ISD::ATOMIC_CMP_SWAP: return LowerCMP_SWAP(Op,DAG); case ISD::ATOMIC_LOAD_SUB: return LowerLOAD_SUB(Op,DAG); @@ -9281,6 +9388,7 @@ void X86TargetLowering::ReplaceNodeResults(SDNode *N, default: assert(false && "Do not know how to custom type legalize this operation!"); return; + case ISD::SIGN_EXTEND_INREG: case ISD::ADDC: case ISD::ADDE: case ISD::SUBC: @@ -9415,7 +9523,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { case X86ISD::PINSRB: return "X86ISD::PINSRB"; case X86ISD::PINSRW: return "X86ISD::PINSRW"; case X86ISD::PSHUFB: return "X86ISD::PSHUFB"; - case X86ISD::PANDN: return "X86ISD::PANDN"; + case X86ISD::ANDNP: return "X86ISD::ANDNP"; case X86ISD::PSIGNB: return "X86ISD::PSIGNB"; case X86ISD::PSIGNW: return "X86ISD::PSIGNW"; case X86ISD::PSIGND: return "X86ISD::PSIGND"; @@ -11766,10 +11874,12 @@ static SDValue PerformAndCombine(SDNode *N, SelectionDAG &DAG, if (R.getNode()) return R; - // Want to form PANDN nodes, in the hopes of then easily combining them with - // OR and AND nodes to form PBLEND/PSIGN. + // Want to form ANDNP nodes: + // 1) In the hopes of then easily combining them with OR and AND nodes + // to form PBLEND/PSIGN. + // 2) To match ANDN packed intrinsics EVT VT = N->getValueType(0); - if (VT != MVT::v2i64) + if (VT != MVT::v2i64 && VT != MVT::v4i64) return SDValue(); SDValue N0 = N->getOperand(0); @@ -11779,12 +11889,12 @@ static SDValue PerformAndCombine(SDNode *N, SelectionDAG &DAG, // Check LHS for vnot if (N0.getOpcode() == ISD::XOR && ISD::isBuildVectorAllOnes(N0.getOperand(1).getNode())) - return DAG.getNode(X86ISD::PANDN, DL, VT, N0.getOperand(0), N1); + return DAG.getNode(X86ISD::ANDNP, DL, VT, N0.getOperand(0), N1); // Check RHS for vnot if (N1.getOpcode() == ISD::XOR && ISD::isBuildVectorAllOnes(N1.getOperand(1).getNode())) - return DAG.getNode(X86ISD::PANDN, DL, VT, N1.getOperand(0), N0); + return DAG.getNode(X86ISD::ANDNP, DL, VT, N1.getOperand(0), N0); return SDValue(); } @@ -11810,10 +11920,10 @@ static SDValue PerformOrCombine(SDNode *N, SelectionDAG &DAG, if (Subtarget->hasSSSE3()) { if (VT == MVT::v2i64) { // Canonicalize pandn to RHS - if (N0.getOpcode() == X86ISD::PANDN) + if (N0.getOpcode() == X86ISD::ANDNP) std::swap(N0, N1); // or (and (m, x), (pandn m, y)) - if (N0.getOpcode() == ISD::AND && N1.getOpcode() == X86ISD::PANDN) { + if (N0.getOpcode() == ISD::AND && N1.getOpcode() == X86ISD::ANDNP) { SDValue Mask = N1.getOperand(0); SDValue X = N1.getOperand(1); SDValue Y; @@ -11822,7 +11932,7 @@ static SDValue PerformOrCombine(SDNode *N, SelectionDAG &DAG, if (N0.getOperand(1) == Mask) Y = N0.getOperand(0); - // Check to see if the mask appeared in both the AND and PANDN and + // Check to see if the mask appeared in both the AND and ANDNP and if (!Y.getNode()) return SDValue(); @@ -12166,8 +12276,8 @@ static SDValue PerformSETCCCombine(SDNode *N, SelectionDAG &DAG) { return SDValue(); } -static SDValue PerformSINT_TO_FPCombine(SDNode *N, SelectionDAG &DAG, const X86TargetLowering *XTLI) { - DebugLoc dl = N->getDebugLoc(); +static SDValue PerformSINT_TO_FPCombine(SDNode *N, SelectionDAG &DAG, + const X86TargetLowering *XTLI) { SDValue Op0 = N->getOperand(0); // Transform (SINT_TO_FP (i64 ...)) into an x87 operation if we have // a 32-bit target where SSE doesn't support i64->FP operations. @@ -12178,7 +12288,8 @@ static SDValue PerformSINT_TO_FPCombine(SDNode *N, SelectionDAG &DAG, const X86T ISD::isNON_EXTLoad(Op0.getNode()) && Op0.hasOneUse() && !XTLI->getSubtarget()->is64Bit() && !DAG.getTargetLoweringInfo().isTypeLegal(VT)) { - SDValue FILDChain = XTLI->BuildFILD(SDValue(N, 0), Ld->getValueType(0), Ld->getChain(), Op0, DAG); + SDValue FILDChain = XTLI->BuildFILD(SDValue(N, 0), Ld->getValueType(0), + Ld->getChain(), Op0, DAG); DAG.ReplaceAllUsesOfValueWith(Op0.getValue(1), FILDChain.getValue(1)); return FILDChain; } @@ -12549,6 +12660,7 @@ X86TargetLowering::getConstraintType(const std::string &Constraint) const { case 'y': case 'x': case 'Y': + case 'l': return C_RegisterClass; case 'a': case 'b': @@ -12832,60 +12944,6 @@ void X86TargetLowering::LowerAsmOperandForConstraint(SDValue Op, return TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); } -std::vector<unsigned> X86TargetLowering:: -getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const { - if (Constraint.size() == 1) { - // FIXME: not handling fp-stack yet! - switch (Constraint[0]) { // GCC X86 Constraint Letters - default: break; // Unknown constraint letter - case 'q': // GENERAL_REGS in 64-bit mode, Q_REGS in 32-bit mode. - if (Subtarget->is64Bit()) { - if (VT == MVT::i32) - return make_vector<unsigned>(X86::EAX, X86::EDX, X86::ECX, X86::EBX, - X86::ESI, X86::EDI, X86::R8D, X86::R9D, - X86::R10D,X86::R11D,X86::R12D, - X86::R13D,X86::R14D,X86::R15D, - X86::EBP, X86::ESP, 0); - else if (VT == MVT::i16) - return make_vector<unsigned>(X86::AX, X86::DX, X86::CX, X86::BX, - X86::SI, X86::DI, X86::R8W,X86::R9W, - X86::R10W,X86::R11W,X86::R12W, - X86::R13W,X86::R14W,X86::R15W, - X86::BP, X86::SP, 0); - else if (VT == MVT::i8) - return make_vector<unsigned>(X86::AL, X86::DL, X86::CL, X86::BL, - X86::SIL, X86::DIL, X86::R8B,X86::R9B, - X86::R10B,X86::R11B,X86::R12B, - X86::R13B,X86::R14B,X86::R15B, - X86::BPL, X86::SPL, 0); - - else if (VT == MVT::i64) - return make_vector<unsigned>(X86::RAX, X86::RDX, X86::RCX, X86::RBX, - X86::RSI, X86::RDI, X86::R8, X86::R9, - X86::R10, X86::R11, X86::R12, - X86::R13, X86::R14, X86::R15, - X86::RBP, X86::RSP, 0); - - break; - } - // 32-bit fallthrough - case 'Q': // Q_REGS - if (VT == MVT::i32) - return make_vector<unsigned>(X86::EAX, X86::EDX, X86::ECX, X86::EBX, 0); - else if (VT == MVT::i16) - return make_vector<unsigned>(X86::AX, X86::DX, X86::CX, X86::BX, 0); - else if (VT == MVT::i8) - return make_vector<unsigned>(X86::AL, X86::DL, X86::CL, X86::BL, 0); - else if (VT == MVT::i64) - return make_vector<unsigned>(X86::RAX, X86::RDX, X86::RCX, X86::RBX, 0); - break; - } - } - - return std::vector<unsigned>(); -} - std::pair<unsigned, const TargetRegisterClass*> X86TargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { @@ -12895,9 +12953,35 @@ X86TargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, // GCC Constraint Letters switch (Constraint[0]) { default: break; + // TODO: Slight differences here in allocation order and leaving + // RIP in the class. Do they matter any more here than they do + // in the normal allocation? + case 'q': // GENERAL_REGS in 64-bit mode, Q_REGS in 32-bit mode. + if (Subtarget->is64Bit()) { + if (VT == MVT::i32 || VT == MVT::f32) + return std::make_pair(0U, X86::GR32RegisterClass); + else if (VT == MVT::i16) + return std::make_pair(0U, X86::GR16RegisterClass); + else if (VT == MVT::i8 || VT == MVT::i1) + return std::make_pair(0U, X86::GR8RegisterClass); + else if (VT == MVT::i64 || VT == MVT::f64) + return std::make_pair(0U, X86::GR64RegisterClass); + break; + } + // 32-bit fallthrough + case 'Q': // Q_REGS + if (VT == MVT::i32 || VT == MVT::f32) + return std::make_pair(0U, X86::GR32_ABCDRegisterClass); + else if (VT == MVT::i16) + return std::make_pair(0U, X86::GR16_ABCDRegisterClass); + else if (VT == MVT::i8 || VT == MVT::i1) + return std::make_pair(0U, X86::GR8_ABCD_LRegisterClass); + else if (VT == MVT::i64) + return std::make_pair(0U, X86::GR64_ABCDRegisterClass); + break; case 'r': // GENERAL_REGS case 'l': // INDEX_REGS - if (VT == MVT::i8) + if (VT == MVT::i8 || VT == MVT::i1) return std::make_pair(0U, X86::GR8RegisterClass); if (VT == MVT::i16) return std::make_pair(0U, X86::GR16RegisterClass); @@ -12905,7 +12989,7 @@ X86TargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, return std::make_pair(0U, X86::GR32RegisterClass); return std::make_pair(0U, X86::GR64RegisterClass); case 'R': // LEGACY_REGS - if (VT == MVT::i8) + if (VT == MVT::i8 || VT == MVT::i1) return std::make_pair(0U, X86::GR8_NOREXRegisterClass); if (VT == MVT::i16) return std::make_pair(0U, X86::GR16_NOREXRegisterClass); diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index d61a1252304a..b6036782b865 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -169,8 +169,8 @@ namespace llvm { /// PSHUFB - Shuffle 16 8-bit values within a vector. PSHUFB, - /// PANDN - and with not'd value. - PANDN, + /// ANDNP - Bitwise Logical AND NOT of Packed FP values. + ANDNP, /// PSIGNB/W/D - Copy integer sign. PSIGNB, PSIGNW, PSIGND, @@ -466,6 +466,12 @@ namespace llvm { /// fit into displacement field of the instruction. bool isOffsetSuitableForCodeModel(int64_t Offset, CodeModel::Model M, bool hasSymbolicDisplacement = true); + + + /// isCalleePop - Determines whether the callee is required to pop its + /// own arguments. Callee pop is necessary to support tail calls. + bool isCalleePop(CallingConv::ID CallingConv, + bool is64Bit, bool IsVarArg, bool TailCallOpt); } //===--------------------------------------------------------------------===// @@ -590,10 +596,6 @@ namespace llvm { virtual ConstraintWeight getSingleConstraintMatchWeight( AsmOperandInfo &info, const char *constraint) const; - std::vector<unsigned> - getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const; - virtual const char *LowerXConstraint(EVT ConstraintVT) const; /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops @@ -823,6 +825,7 @@ namespace llvm { SDValue LowerLOAD_SUB(SDValue Op, SelectionDAG &DAG) const; SDValue LowerREADCYCLECOUNTER(SDValue Op, SelectionDAG &DAG) const; SDValue LowerMEMBARRIER(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerSIGN_EXTEND_INREG(SDValue Op, SelectionDAG &DAG) const; // Utility functions to help LowerVECTOR_SHUFFLE SDValue LowerVECTOR_SHUFFLEv8i16(SDValue Op, SelectionDAG &DAG) const; diff --git a/lib/Target/X86/X86InstrBuilder.h b/lib/Target/X86/X86InstrBuilder.h index 1ea8071053e9..0245e5c09644 100644 --- a/lib/Target/X86/X86InstrBuilder.h +++ b/lib/Target/X86/X86InstrBuilder.h @@ -150,11 +150,11 @@ addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset = 0) { MachineInstr *MI = MIB; MachineFunction &MF = *MI->getParent()->getParent(); MachineFrameInfo &MFI = *MF.getFrameInfo(); - const TargetInstrDesc &TID = MI->getDesc(); + const MCInstrDesc &MCID = MI->getDesc(); unsigned Flags = 0; - if (TID.mayLoad()) + if (MCID.mayLoad()) Flags |= MachineMemOperand::MOLoad; - if (TID.mayStore()) + if (MCID.mayStore()) Flags |= MachineMemOperand::MOStore; MachineMemOperand *MMO = MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(FI, Offset), diff --git a/lib/Target/X86/X86InstrCompiler.td b/lib/Target/X86/X86InstrCompiler.td index 33534cd82bdb..adcc747eb4b8 100644 --- a/lib/Target/X86/X86InstrCompiler.td +++ b/lib/Target/X86/X86InstrCompiler.td @@ -1368,6 +1368,11 @@ def : Pat<(store (i8 (trunc_su (srl_su GR16:$src, (i8 8)))), addr:$dst), // (shl x, 1) ==> (add x, x) +// Note that if x is undef (immediate or otherwise), we could theoretically +// end up with the two uses of x getting different values, producing a result +// where the least significant bit is not 0. However, the probability of this +// happening is considered low enough that this is officially not a +// "real problem". def : Pat<(shl GR8 :$src1, (i8 1)), (ADD8rr GR8 :$src1, GR8 :$src1)>; def : Pat<(shl GR16:$src1, (i8 1)), (ADD16rr GR16:$src1, GR16:$src1)>; def : Pat<(shl GR32:$src1, (i8 1)), (ADD32rr GR32:$src1, GR32:$src1)>; diff --git a/lib/Target/X86/X86InstrFPStack.td b/lib/Target/X86/X86InstrFPStack.td index b506f5e0b81a..7cb870fabd62 100644 --- a/lib/Target/X86/X86InstrFPStack.td +++ b/lib/Target/X86/X86InstrFPStack.td @@ -112,31 +112,8 @@ let usesCustomInserter = 1 in { // Expanded after instruction selection. // a pattern) and the FPI instruction should have emission info (e.g. opcode // encoding and asm printing info). -// Pseudo Instructions for FP stack return values. -def FpGET_ST0_32 : FpI_<(outs RFP32:$dst), (ins), SpecialFP, []>; // FPR = ST(0) -def FpGET_ST0_64 : FpI_<(outs RFP64:$dst), (ins), SpecialFP, []>; // FPR = ST(0) -def FpGET_ST0_80 : FpI_<(outs RFP80:$dst), (ins), SpecialFP, []>; // FPR = ST(0) - -// FpGET_ST1* should only be issued *after* an FpGET_ST0* has been issued when -// there are two values live out on the stack from a call or inlineasm. This -// magic is handled by the stackifier. It is not valid to emit FpGET_ST1* and -// then FpGET_ST0*. In addition, it is invalid for any FP-using operations to -// occur between them. -def FpGET_ST1_32 : FpI_<(outs RFP32:$dst), (ins), SpecialFP, []>; // FPR = ST(1) -def FpGET_ST1_64 : FpI_<(outs RFP64:$dst), (ins), SpecialFP, []>; // FPR = ST(1) -def FpGET_ST1_80 : FpI_<(outs RFP80:$dst), (ins), SpecialFP, []>; // FPR = ST(1) - -let Defs = [ST0] in { -def FpSET_ST0_32 : FpI_<(outs), (ins RFP32:$src), SpecialFP, []>; // ST(0) = FPR -def FpSET_ST0_64 : FpI_<(outs), (ins RFP64:$src), SpecialFP, []>; // ST(0) = FPR -def FpSET_ST0_80 : FpI_<(outs), (ins RFP80:$src), SpecialFP, []>; // ST(0) = FPR -} - -let Defs = [ST1] in { -def FpSET_ST1_32 : FpI_<(outs), (ins RFP32:$src), SpecialFP, []>; // ST(1) = FPR -def FpSET_ST1_64 : FpI_<(outs), (ins RFP64:$src), SpecialFP, []>; // ST(1) = FPR -def FpSET_ST1_80 : FpI_<(outs), (ins RFP80:$src), SpecialFP, []>; // ST(1) = FPR -} +// Pseudo Instruction for FP stack return values. +def FpPOP_RETVAL : FpI_<(outs RFP80:$dst), (ins), SpecialFP, []>; // FpIf32, FpIf64 - Floating Point Pseudo Instruction template. // f32 instructions can use SSE1 and are predicated on FPStackf32 == !SSE1. @@ -147,19 +124,6 @@ class FpIf32<dag outs, dag ins, FPFormat fp, list<dag> pattern> : class FpIf64<dag outs, dag ins, FPFormat fp, list<dag> pattern> : FpI_<outs, ins, fp, pattern>, Requires<[FPStackf64]>; -// Register copies. Just copies, the shortening ones do not truncate. -let neverHasSideEffects = 1 in { - def MOV_Fp3232 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src), SpecialFP, []>; - def MOV_Fp3264 : FpIf32<(outs RFP64:$dst), (ins RFP32:$src), SpecialFP, []>; - def MOV_Fp6432 : FpIf32<(outs RFP32:$dst), (ins RFP64:$src), SpecialFP, []>; - def MOV_Fp6464 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src), SpecialFP, []>; - def MOV_Fp8032 : FpIf32<(outs RFP32:$dst), (ins RFP80:$src), SpecialFP, []>; - def MOV_Fp3280 : FpIf32<(outs RFP80:$dst), (ins RFP32:$src), SpecialFP, []>; - def MOV_Fp8064 : FpIf64<(outs RFP64:$dst), (ins RFP80:$src), SpecialFP, []>; - def MOV_Fp6480 : FpIf64<(outs RFP80:$dst), (ins RFP64:$src), SpecialFP, []>; - def MOV_Fp8080 : FpI_ <(outs RFP80:$dst), (ins RFP80:$src), SpecialFP, []>; -} - // Factoring for arithmetic. multiclass FPBinary_rr<SDNode OpNode> { // Register op register -> register diff --git a/lib/Target/X86/X86InstrFormats.td b/lib/Target/X86/X86InstrFormats.td index 7daa26492274..6d89bcc29e7b 100644 --- a/lib/Target/X86/X86InstrFormats.td +++ b/lib/Target/X86/X86InstrFormats.td @@ -460,6 +460,11 @@ class AESAI<bits<8> o, Format F, dag outs, dag ins, string asm, class CLMULIi8<bits<8> o, Format F, dag outs, dag ins, string asm, list<dag>pattern> : Ii8<o, F, outs, ins, asm, pattern, SSEPackedInt>, TA, + OpSize, Requires<[HasCLMUL]>; + +class AVXCLMULIi8<bits<8> o, Format F, dag outs, dag ins, string asm, + list<dag>pattern> + : Ii8<o, F, outs, ins, asm, pattern, SSEPackedInt>, TA, OpSize, VEX_4V, Requires<[HasAVX, HasCLMUL]>; // FMA3 Instruction Templates diff --git a/lib/Target/X86/X86InstrFragmentsSIMD.td b/lib/Target/X86/X86InstrFragmentsSIMD.td index 7c9a9f7e8c50..b00109c9fa4d 100644 --- a/lib/Target/X86/X86InstrFragmentsSIMD.td +++ b/lib/Target/X86/X86InstrFragmentsSIMD.td @@ -46,8 +46,8 @@ def X86cmpsd : SDNode<"X86ISD::FSETCCsd", SDTX86Cmpsd>; def X86pshufb : SDNode<"X86ISD::PSHUFB", SDTypeProfile<1, 2, [SDTCisVT<0, v16i8>, SDTCisSameAs<0,1>, SDTCisSameAs<0,2>]>>; -def X86pandn : SDNode<"X86ISD::PANDN", - SDTypeProfile<1, 2, [SDTCisVT<0, v2i64>, SDTCisSameAs<0,1>, +def X86andnp : SDNode<"X86ISD::ANDNP", + SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0,1>, SDTCisSameAs<0,2>]>>; def X86psignb : SDNode<"X86ISD::PSIGNB", SDTypeProfile<1, 2, [SDTCisVT<0, v16i8>, SDTCisSameAs<0,1>, @@ -168,11 +168,13 @@ def ssmem : Operand<v4f32> { let PrintMethod = "printf32mem"; let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, i8imm); let ParserMatchClass = X86MemAsmOperand; + let OperandType = "OPERAND_MEMORY"; } def sdmem : Operand<v2f64> { let PrintMethod = "printf64mem"; let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, i8imm); let ParserMatchClass = X86MemAsmOperand; + let OperandType = "OPERAND_MEMORY"; } //===----------------------------------------------------------------------===// @@ -301,6 +303,7 @@ def bc_v2i64 : PatFrag<(ops node:$in), (v2i64 (bitconvert node:$in))>; // 256-bit bitconvert pattern fragments def bc_v8i32 : PatFrag<(ops node:$in), (v8i32 (bitconvert node:$in))>; +def bc_v4i64 : PatFrag<(ops node:$in), (v4i64 (bitconvert node:$in))>; def vzmovl_v2i64 : PatFrag<(ops node:$src), (bitconvert (v2i64 (X86vzmovl diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index e2016eb2d6fb..55b5835f52a7 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -13,7 +13,6 @@ #include "X86InstrInfo.h" #include "X86.h" -#include "X86GenInstrInfo.inc" #include "X86InstrBuilder.h" #include "X86MachineFunctionInfo.h" #include "X86Subtarget.h" @@ -36,6 +35,9 @@ #include "llvm/MC/MCAsmInfo.h" #include <limits> +#define GET_INSTRINFO_CTOR +#include "X86GenInstrInfo.inc" + using namespace llvm; static cl::opt<bool> @@ -52,7 +54,12 @@ ReMatPICStubLoad("remat-pic-stub-load", cl::init(false), cl::Hidden); X86InstrInfo::X86InstrInfo(X86TargetMachine &tm) - : TargetInstrInfoImpl(X86Insts, array_lengthof(X86Insts)), + : X86GenInstrInfo((tm.getSubtarget<X86Subtarget>().is64Bit() + ? X86::ADJCALLSTACKDOWN64 + : X86::ADJCALLSTACKDOWN32), + (tm.getSubtarget<X86Subtarget>().is64Bit() + ? X86::ADJCALLSTACKUP64 + : X86::ADJCALLSTACKUP32)), TM(tm), RI(tm, *this) { enum { TB_NOT_REVERSABLE = 1U << 31, @@ -293,12 +300,17 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm) { X86::MOVAPDrr, X86::MOVAPDmr, 0, 16 }, { X86::MOVAPSrr, X86::MOVAPSmr, 0, 16 }, { X86::MOVDQArr, X86::MOVDQAmr, 0, 16 }, + { X86::VMOVAPDYrr, X86::VMOVAPDYmr, 0, 32 }, + { X86::VMOVAPSYrr, X86::VMOVAPSYmr, 0, 32 }, + { X86::VMOVDQAYrr, X86::VMOVDQAYmr, 0, 32 }, { X86::MOVPDI2DIrr, X86::MOVPDI2DImr, 0, 0 }, { X86::MOVPQIto64rr,X86::MOVPQI2QImr, 0, 0 }, { X86::MOVSDto64rr, X86::MOVSDto64mr, 0, 0 }, { X86::MOVSS2DIrr, X86::MOVSS2DImr, 0, 0 }, { X86::MOVUPDrr, X86::MOVUPDmr, 0, 0 }, { X86::MOVUPSrr, X86::MOVUPSmr, 0, 0 }, + { X86::VMOVUPDYrr, X86::VMOVUPDYmr, 0, 0 }, + { X86::VMOVUPSYrr, X86::VMOVUPSYmr, 0, 0 }, { X86::MUL16r, X86::MUL16m, 1, 0 }, { X86::MUL32r, X86::MUL32m, 1, 0 }, { X86::MUL64r, X86::MUL64m, 1, 0 }, @@ -403,10 +415,13 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm) { X86::MOV8rr, X86::MOV8rm, 0 }, { X86::MOVAPDrr, X86::MOVAPDrm, 16 }, { X86::MOVAPSrr, X86::MOVAPSrm, 16 }, + { X86::VMOVAPDYrr, X86::VMOVAPDYrm, 32 }, + { X86::VMOVAPSYrr, X86::VMOVAPSYrm, 32 }, { X86::MOVDDUPrr, X86::MOVDDUPrm, 0 }, { X86::MOVDI2PDIrr, X86::MOVDI2PDIrm, 0 }, { X86::MOVDI2SSrr, X86::MOVDI2SSrm, 0 }, { X86::MOVDQArr, X86::MOVDQArm, 16 }, + { X86::VMOVDQAYrr, X86::VMOVDQAYrm, 16 }, { X86::MOVSHDUPrr, X86::MOVSHDUPrm, 16 }, { X86::MOVSLDUPrr, X86::MOVSLDUPrm, 16 }, { X86::MOVSX16rr8, X86::MOVSX16rm8, 0 }, @@ -417,6 +432,8 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm) { X86::MOVSX64rr8, X86::MOVSX64rm8, 0 }, { X86::MOVUPDrr, X86::MOVUPDrm, 16 }, { X86::MOVUPSrr, X86::MOVUPSrm, 0 }, + { X86::VMOVUPDYrr, X86::VMOVUPDYrm, 0 }, + { X86::VMOVUPSYrr, X86::VMOVUPSYrm, 0 }, { X86::MOVZDI2PDIrr, X86::MOVZDI2PDIrm, 0 }, { X86::MOVZQI2PQIrr, X86::MOVZQI2PQIrm, 0 }, { X86::MOVZPQILo2PQIrr, X86::MOVZPQILo2PQIrm, 16 }, @@ -779,6 +796,9 @@ static bool isFrameLoadOpcode(int Opcode) { case X86::MOVAPSrm: case X86::MOVAPDrm: case X86::MOVDQArm: + case X86::VMOVAPSYrm: + case X86::VMOVAPDYrm: + case X86::VMOVDQAYrm: case X86::MMX_MOVD64rm: case X86::MMX_MOVQ64rm: return true; @@ -800,6 +820,9 @@ static bool isFrameStoreOpcode(int Opcode) { case X86::MOVAPSmr: case X86::MOVAPDmr: case X86::MOVDQAmr: + case X86::VMOVAPSYmr: + case X86::VMOVAPDYmr: + case X86::VMOVDQAYmr: case X86::MMX_MOVD64mr: case X86::MMX_MOVQ64mr: case X86::MMX_MOVNTQmr: @@ -918,6 +941,10 @@ X86InstrInfo::isReallyTriviallyReMaterializable(const MachineInstr *MI, case X86::MOVUPSrm: case X86::MOVAPDrm: case X86::MOVDQArm: + case X86::VMOVAPSYrm: + case X86::VMOVUPSYrm: + case X86::VMOVAPDYrm: + case X86::VMOVDQAYrm: case X86::MMX_MOVD64rm: case X86::MMX_MOVQ64rm: case X86::FsMOVAPSrm: @@ -1689,13 +1716,13 @@ X86::CondCode X86::GetOppositeBranchCondition(X86::CondCode CC) { } bool X86InstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const { - const TargetInstrDesc &TID = MI->getDesc(); - if (!TID.isTerminator()) return false; + const MCInstrDesc &MCID = MI->getDesc(); + if (!MCID.isTerminator()) return false; // Conditional branch is a special case. - if (TID.isBranch() && !TID.isBarrier()) + if (MCID.isBranch() && !MCID.isBarrier()) return true; - if (!TID.isPredicable()) + if (!MCID.isPredicable()) return true; return !isPredicated(MI); } @@ -1789,7 +1816,6 @@ bool X86InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, .addMBB(UnCondBrIter->getOperand(0).getMBB()); BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(X86::JMP_4)) .addMBB(TargetBB); - MBB.addSuccessor(TargetBB); OldInst->eraseFromParent(); UnCondBrIter->eraseFromParent(); @@ -1968,6 +1994,8 @@ void X86InstrInfo::copyPhysReg(MachineBasicBlock &MBB, Opc = X86::MOV8rr; } else if (X86::VR128RegClass.contains(DestReg, SrcReg)) Opc = X86::MOVAPSrr; + else if (X86::VR256RegClass.contains(DestReg, SrcReg)) + Opc = X86::VMOVAPSYrr; else if (X86::VR64RegClass.contains(DestReg, SrcReg)) Opc = X86::MMX_MOVQ64rr; else @@ -2057,6 +2085,13 @@ static unsigned getLoadStoreRegOpcode(unsigned Reg, return load ? X86::MOVAPSrm : X86::MOVAPSmr; else return load ? X86::MOVUPSrm : X86::MOVUPSmr; + case 32: + assert(X86::VR256RegClass.hasSubClassEq(RC) && "Unknown 32-byte regclass"); + // If stack is realigned we can use aligned stores. + if (isStackAligned) + return load ? X86::VMOVAPSYrm : X86::VMOVAPSYmr; + else + return load ? X86::VMOVUPSYrm : X86::VMOVUPSYmr; } } @@ -2083,7 +2118,8 @@ void X86InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, const MachineFunction &MF = *MBB.getParent(); assert(MF.getFrameInfo()->getObjectSize(FrameIdx) >= RC->getSize() && "Stack slot too small for store"); - bool isAligned = (RI.getStackAlignment() >= 16) || RI.canRealignStack(MF); + bool isAligned = (TM.getFrameLowering()->getStackAlignment() >= 16) || + RI.canRealignStack(MF); unsigned Opc = getStoreRegOpcode(SrcReg, RC, isAligned, TM); DebugLoc DL = MBB.findDebugLoc(MI); addFrameReference(BuildMI(MBB, MI, DL, get(Opc)), FrameIdx) @@ -2115,7 +2151,8 @@ void X86InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const { const MachineFunction &MF = *MBB.getParent(); - bool isAligned = (RI.getStackAlignment() >= 16) || RI.canRealignStack(MF); + bool isAligned = (TM.getFrameLowering()->getStackAlignment() >= 16) || + RI.canRealignStack(MF); unsigned Opc = getLoadRegOpcode(DestReg, RC, isAligned, TM); DebugLoc DL = MBB.findDebugLoc(MI); addFrameReference(BuildMI(MBB, MI, DL, get(Opc), DestReg), FrameIdx); @@ -2224,7 +2261,7 @@ X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF, bool isTwoAddrFold = false; unsigned NumOps = MI->getDesc().getNumOperands(); bool isTwoAddr = NumOps > 1 && - MI->getDesc().getOperandConstraint(1, TOI::TIED_TO) != -1; + MI->getDesc().getOperandConstraint(1, MCOI::TIED_TO) != -1; // FIXME: AsmPrinter doesn't know how to handle // X86II::MO_GOT_ABSOLUTE_ADDRESS after folding. @@ -2273,7 +2310,7 @@ X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF, return NULL; bool NarrowToMOV32rm = false; if (Size) { - unsigned RCSize = MI->getDesc().OpInfo[i].getRegClass(&RI)->getSize(); + unsigned RCSize = getRegClass(MI->getDesc(), i, &RI)->getSize(); if (Size < RCSize) { // Check if it's safe to fold the load. If the size of the object is // narrower than the load width, then it's not. @@ -2542,7 +2579,7 @@ bool X86InstrInfo::canFoldMemoryOperand(const MachineInstr *MI, unsigned Opc = MI->getOpcode(); unsigned NumOps = MI->getDesc().getNumOperands(); bool isTwoAddr = NumOps > 1 && - MI->getDesc().getOperandConstraint(1, TOI::TIED_TO) != -1; + MI->getDesc().getOperandConstraint(1, MCOI::TIED_TO) != -1; // Folding a memory location into the two-address part of a two-address // instruction is different than folding it other places. It requires @@ -2588,9 +2625,8 @@ bool X86InstrInfo::unfoldMemoryOperand(MachineFunction &MF, MachineInstr *MI, return false; UnfoldStore &= FoldedStore; - const TargetInstrDesc &TID = get(Opc); - const TargetOperandInfo &TOI = TID.OpInfo[Index]; - const TargetRegisterClass *RC = TOI.getRegClass(&RI); + const MCInstrDesc &MCID = get(Opc); + const TargetRegisterClass *RC = getRegClass(MCID, Index, &RI); if (!MI->hasOneMemOperand() && RC == &X86::VR128RegClass && !TM.getSubtarget<X86Subtarget>().isUnalignedMemAccessFast()) @@ -2632,7 +2668,7 @@ bool X86InstrInfo::unfoldMemoryOperand(MachineFunction &MF, MachineInstr *MI, } // Emit the data processing instruction. - MachineInstr *DataMI = MF.CreateMachineInstr(TID, MI->getDebugLoc(), true); + MachineInstr *DataMI = MF.CreateMachineInstr(MCID, MI->getDebugLoc(), true); MachineInstrBuilder MIB(DataMI); if (FoldedStore) @@ -2685,7 +2721,7 @@ bool X86InstrInfo::unfoldMemoryOperand(MachineFunction &MF, MachineInstr *MI, // Emit the store instruction. if (UnfoldStore) { - const TargetRegisterClass *DstRC = TID.OpInfo[0].getRegClass(&RI); + const TargetRegisterClass *DstRC = getRegClass(MCID, 0, &RI); std::pair<MachineInstr::mmo_iterator, MachineInstr::mmo_iterator> MMOs = MF.extractStoreMemRefs(MI->memoperands_begin(), @@ -2710,9 +2746,9 @@ X86InstrInfo::unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N, unsigned Index = I->second.second & 0xf; bool FoldedLoad = I->second.second & (1 << 4); bool FoldedStore = I->second.second & (1 << 5); - const TargetInstrDesc &TID = get(Opc); - const TargetRegisterClass *RC = TID.OpInfo[Index].getRegClass(&RI); - unsigned NumDefs = TID.NumDefs; + const MCInstrDesc &MCID = get(Opc); + const TargetRegisterClass *RC = getRegClass(MCID, Index, &RI); + unsigned NumDefs = MCID.NumDefs; std::vector<SDValue> AddrOps; std::vector<SDValue> BeforeOps; std::vector<SDValue> AfterOps; @@ -2756,13 +2792,13 @@ X86InstrInfo::unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N, // Emit the data processing instruction. std::vector<EVT> VTs; const TargetRegisterClass *DstRC = 0; - if (TID.getNumDefs() > 0) { - DstRC = TID.OpInfo[0].getRegClass(&RI); + if (MCID.getNumDefs() > 0) { + DstRC = getRegClass(MCID, 0, &RI); VTs.push_back(*DstRC->vt_begin()); } for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) { EVT VT = N->getValueType(i); - if (VT != MVT::Other && i >= (unsigned)TID.getNumDefs()) + if (VT != MVT::Other && i >= (unsigned)MCID.getNumDefs()) VTs.push_back(VT); } if (Load) @@ -2845,6 +2881,11 @@ X86InstrInfo::areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, case X86::MOVAPDrm: case X86::MOVDQArm: case X86::MOVDQUrm: + case X86::VMOVAPSYrm: + case X86::VMOVUPSYrm: + case X86::VMOVAPDYrm: + case X86::VMOVDQAYrm: + case X86::VMOVDQUYrm: break; } switch (Opc2) { @@ -2867,6 +2908,11 @@ X86InstrInfo::areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, case X86::MOVAPDrm: case X86::MOVDQArm: case X86::MOVDQUrm: + case X86::VMOVAPSYrm: + case X86::VMOVUPSYrm: + case X86::VMOVAPDYrm: + case X86::VMOVDQAYrm: + case X86::VMOVDQUYrm: break; } @@ -3045,6 +3091,13 @@ static const unsigned ReplaceableInstrs[][3] = { { X86::AVX_SET0PS, X86::AVX_SET0PD, X86::AVX_SET0PI }, { X86::VXORPSrm, X86::VXORPDrm, X86::VPXORrm }, { X86::VXORPSrr, X86::VXORPDrr, X86::VPXORrr }, + // AVX 256-bit support + { X86::VMOVAPSYmr, X86::VMOVAPDYmr, X86::VMOVDQAYmr }, + { X86::VMOVAPSYrm, X86::VMOVAPDYrm, X86::VMOVDQAYrm }, + { X86::VMOVAPSYrr, X86::VMOVAPDYrr, X86::VMOVDQAYrr }, + { X86::VMOVUPSYmr, X86::VMOVUPDYmr, X86::VMOVDQUYmr }, + { X86::VMOVUPSYrm, X86::VMOVUPDYrm, X86::VMOVDQUYrm }, + { X86::VMOVNTPSYmr, X86::VMOVNTPDYmr, X86::VMOVNTDQYmr }, }; // FIXME: Some shuffle and unpack instructions have equivalents in different diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h index d8950230d83d..5f2eba34ac45 100644 --- a/lib/Target/X86/X86InstrInfo.h +++ b/lib/Target/X86/X86InstrInfo.h @@ -19,6 +19,9 @@ #include "X86RegisterInfo.h" #include "llvm/ADT/DenseMap.h" +#define GET_INSTRINFO_HEADER +#include "X86GenInstrInfo.inc" + namespace llvm { class X86RegisterInfo; class X86TargetMachine; @@ -611,7 +614,7 @@ inline static bool isMem(const MachineInstr *MI, unsigned Op) { isLeaMem(MI, Op); } -class X86InstrInfo : public TargetInstrInfoImpl { +class X86InstrInfo : public X86GenInstrInfo { X86TargetMachine &TM; const X86RegisterInfo RI; diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 8cab80824688..7eb07b0a97bd 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -251,6 +251,7 @@ class X86MemOperand<string printMethod> : Operand<iPTR> { let ParserMatchClass = X86MemAsmOperand; } +let OperandType = "OPERAND_MEMORY" in { def opaque32mem : X86MemOperand<"printopaquemem">; def opaque48mem : X86MemOperand<"printopaquemem">; def opaque80mem : X86MemOperand<"printopaquemem">; @@ -267,6 +268,7 @@ def f64mem : X86MemOperand<"printf64mem">; def f80mem : X86MemOperand<"printf80mem">; def f128mem : X86MemOperand<"printf128mem">; def f256mem : X86MemOperand<"printf256mem">; +} // A version of i8mem for use on x86-64 that uses GR64_NOREX instead of // plain GR64, so that it doesn't potentially require a REX prefix. @@ -274,6 +276,7 @@ def i8mem_NOREX : Operand<i64> { let PrintMethod = "printi8mem"; let MIOperandInfo = (ops GR64_NOREX, i8imm, GR64_NOREX_NOSP, i32imm, i8imm); let ParserMatchClass = X86MemAsmOperand; + let OperandType = "OPERAND_MEMORY"; } // GPRs available for tailcall. @@ -287,6 +290,7 @@ def i32mem_TC : Operand<i32> { let PrintMethod = "printi32mem"; let MIOperandInfo = (ops GR32_TC, i8imm, GR32_TC, i32imm, i8imm); let ParserMatchClass = X86MemAsmOperand; + let OperandType = "OPERAND_MEMORY"; } // Special i64mem for addresses of load folding tail calls. These are not @@ -297,9 +301,11 @@ def i64mem_TC : Operand<i64> { let MIOperandInfo = (ops ptr_rc_tailcall, i8imm, ptr_rc_tailcall, i32imm, i8imm); let ParserMatchClass = X86MemAsmOperand; + let OperandType = "OPERAND_MEMORY"; } -let ParserMatchClass = X86AbsMemAsmOperand, +let OperandType = "OPERAND_PCREL", + ParserMatchClass = X86AbsMemAsmOperand, PrintMethod = "print_pcrel_imm" in { def i32imm_pcrel : Operand<i32>; def i16imm_pcrel : Operand<i16>; @@ -317,6 +323,7 @@ def brtarget8 : Operand<OtherVT>; def SSECC : Operand<i8> { let PrintMethod = "printSSECC"; + let OperandType = "OPERAND_IMMEDIATE"; } class ImmSExtAsmOperandClass : AsmOperandClass { @@ -363,15 +370,18 @@ def ImmSExti64i8AsmOperand : ImmSExtAsmOperandClass { // 16-bits but only 8 bits are significant. def i16i8imm : Operand<i16> { let ParserMatchClass = ImmSExti16i8AsmOperand; + let OperandType = "OPERAND_IMMEDIATE"; } // 32-bits but only 8 bits are significant. def i32i8imm : Operand<i32> { let ParserMatchClass = ImmSExti32i8AsmOperand; + let OperandType = "OPERAND_IMMEDIATE"; } // 64-bits but only 32 bits are significant. def i64i32imm : Operand<i64> { let ParserMatchClass = ImmSExti64i32AsmOperand; + let OperandType = "OPERAND_IMMEDIATE"; } // 64-bits but only 32 bits are significant, and those bits are treated as being @@ -438,8 +448,10 @@ def HasFMA3 : Predicate<"Subtarget->hasFMA3()">; def HasFMA4 : Predicate<"Subtarget->hasFMA4()">; def FPStackf32 : Predicate<"!Subtarget->hasXMM()">; def FPStackf64 : Predicate<"!Subtarget->hasXMMInt()">; -def In32BitMode : Predicate<"!Subtarget->is64Bit()">, AssemblerPredicate; -def In64BitMode : Predicate<"Subtarget->is64Bit()">, AssemblerPredicate; +def In32BitMode : Predicate<"!Subtarget->is64Bit()">, + AssemblerPredicate<"!Mode64Bit">; +def In64BitMode : Predicate<"Subtarget->is64Bit()">, + AssemblerPredicate<"Mode64Bit">; def IsWin64 : Predicate<"Subtarget->isTargetWin64()">; def NotWin64 : Predicate<"!Subtarget->isTargetWin64()">; def SmallCode : Predicate<"TM.getCodeModel() == CodeModel::Small">; @@ -669,7 +681,7 @@ def PUSH64rmm: I<0xFF, MRM6m, (outs), (ins i64mem:$src), "push{q}\t$src", []>; } let Defs = [RSP], Uses = [RSP], neverHasSideEffects = 1, mayStore = 1 in { -def PUSH64i8 : Ii8<0x6a, RawFrm, (outs), (ins i8imm:$imm), +def PUSH64i8 : Ii8<0x6a, RawFrm, (outs), (ins i64i8imm:$imm), "push{q}\t$imm", []>; def PUSH64i16 : Ii16<0x68, RawFrm, (outs), (ins i16imm:$imm), "push{q}\t$imm", []>; diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td index b64c03a9b597..fe11d776804c 100644 --- a/lib/Target/X86/X86InstrSSE.td +++ b/lib/Target/X86/X86InstrSSE.td @@ -512,6 +512,26 @@ defm VCVTSI2SDL : sse12_vcvt_avx<0x2A, GR32, FR64, i32mem, "cvtsi2sd{l}">, XD, defm VCVTSI2SD64 : sse12_vcvt_avx<0x2A, GR64, FR64, i64mem, "cvtsi2sd{q}">, XD, VEX_4V, VEX_W; +let Predicates = [HasAVX] in { + def : Pat<(f32 (sint_to_fp (loadi32 addr:$src))), + (VCVTSI2SSrm (f32 (IMPLICIT_DEF)), addr:$src)>; + def : Pat<(f32 (sint_to_fp (loadi64 addr:$src))), + (VCVTSI2SS64rm (f32 (IMPLICIT_DEF)), addr:$src)>; + def : Pat<(f64 (sint_to_fp (loadi32 addr:$src))), + (VCVTSI2SDrm (f64 (IMPLICIT_DEF)), addr:$src)>; + def : Pat<(f64 (sint_to_fp (loadi64 addr:$src))), + (VCVTSI2SD64rm (f64 (IMPLICIT_DEF)), addr:$src)>; + + def : Pat<(f32 (sint_to_fp GR32:$src)), + (VCVTSI2SSrr (f32 (IMPLICIT_DEF)), GR32:$src)>; + def : Pat<(f32 (sint_to_fp GR64:$src)), + (VCVTSI2SS64rr (f32 (IMPLICIT_DEF)), GR64:$src)>; + def : Pat<(f64 (sint_to_fp GR32:$src)), + (VCVTSI2SDrr (f64 (IMPLICIT_DEF)), GR32:$src)>; + def : Pat<(f64 (sint_to_fp GR64:$src)), + (VCVTSI2SD64rr (f64 (IMPLICIT_DEF)), GR64:$src)>; +} + defm CVTTSS2SI : sse12_cvt_s<0x2C, FR32, GR32, fp_to_sint, f32mem, loadf32, "cvttss2si\t{$src, $dst|$dst, $src}">, XS; defm CVTTSS2SI64 : sse12_cvt_s<0x2C, FR32, GR64, fp_to_sint, f32mem, loadf32, @@ -1473,83 +1493,68 @@ let neverHasSideEffects = 1, Pattern = []<dag>, isCommutable = 0 in /// sse12_fp_packed_logical - SSE 1 & 2 packed FP logical ops /// multiclass sse12_fp_packed_logical<bits<8> opc, string OpcodeStr, - SDNode OpNode, int HasPat = 0, - list<list<dag>> Pattern = []> { + SDNode OpNode> { let Pattern = []<dag> in { defm V#NAME#PS : sse12_fp_packed_logical_rm<opc, VR128, SSEPackedSingle, !strconcat(OpcodeStr, "ps"), f128mem, - !if(HasPat, Pattern[0], // rr - [(set VR128:$dst, (v2i64 (OpNode VR128:$src1, - VR128:$src2)))]), - !if(HasPat, Pattern[2], // rm - [(set VR128:$dst, (OpNode (bc_v2i64 (v4f32 VR128:$src1)), - (memopv2i64 addr:$src2)))]), 0>, - VEX_4V; + [(set VR128:$dst, (v2i64 (OpNode VR128:$src1, VR128:$src2)))], + [(set VR128:$dst, (OpNode (bc_v2i64 (v4f32 VR128:$src1)), + (memopv2i64 addr:$src2)))], 0>, VEX_4V; defm V#NAME#PD : sse12_fp_packed_logical_rm<opc, VR128, SSEPackedDouble, !strconcat(OpcodeStr, "pd"), f128mem, - !if(HasPat, Pattern[1], // rr - [(set VR128:$dst, (OpNode (bc_v2i64 (v2f64 VR128:$src1)), - (bc_v2i64 (v2f64 - VR128:$src2))))]), - !if(HasPat, Pattern[3], // rm - [(set VR128:$dst, (OpNode (bc_v2i64 (v2f64 VR128:$src1)), - (memopv2i64 addr:$src2)))]), 0>, - OpSize, VEX_4V; + [(set VR128:$dst, (OpNode (bc_v2i64 (v2f64 VR128:$src1)), + (bc_v2i64 (v2f64 VR128:$src2))))], + [(set VR128:$dst, (OpNode (bc_v2i64 (v2f64 VR128:$src1)), + (memopv2i64 addr:$src2)))], 0>, + OpSize, VEX_4V; } let Constraints = "$src1 = $dst" in { defm PS : sse12_fp_packed_logical_rm<opc, VR128, SSEPackedSingle, !strconcat(OpcodeStr, "ps"), f128mem, - !if(HasPat, Pattern[0], // rr - [(set VR128:$dst, (v2i64 (OpNode VR128:$src1, - VR128:$src2)))]), - !if(HasPat, Pattern[2], // rm - [(set VR128:$dst, (OpNode (bc_v2i64 (v4f32 VR128:$src1)), - (memopv2i64 addr:$src2)))])>, TB; + [(set VR128:$dst, (v2i64 (OpNode VR128:$src1, VR128:$src2)))], + [(set VR128:$dst, (OpNode (bc_v2i64 (v4f32 VR128:$src1)), + (memopv2i64 addr:$src2)))]>, TB; defm PD : sse12_fp_packed_logical_rm<opc, VR128, SSEPackedDouble, !strconcat(OpcodeStr, "pd"), f128mem, - !if(HasPat, Pattern[1], // rr - [(set VR128:$dst, (OpNode (bc_v2i64 (v2f64 VR128:$src1)), - (bc_v2i64 (v2f64 - VR128:$src2))))]), - !if(HasPat, Pattern[3], // rm - [(set VR128:$dst, (OpNode (bc_v2i64 (v2f64 VR128:$src1)), - (memopv2i64 addr:$src2)))])>, - TB, OpSize; + [(set VR128:$dst, (OpNode (bc_v2i64 (v2f64 VR128:$src1)), + (bc_v2i64 (v2f64 VR128:$src2))))], + [(set VR128:$dst, (OpNode (bc_v2i64 (v2f64 VR128:$src1)), + (memopv2i64 addr:$src2)))]>, TB, OpSize; } } /// sse12_fp_packed_logical_y - AVX 256-bit SSE 1 & 2 logical ops forms /// -multiclass sse12_fp_packed_logical_y<bits<8> opc, string OpcodeStr> { +multiclass sse12_fp_packed_logical_y<bits<8> opc, string OpcodeStr, + SDNode OpNode> { defm PSY : sse12_fp_packed_logical_rm<opc, VR256, SSEPackedSingle, - !strconcat(OpcodeStr, "ps"), f256mem, [], [], 0>, VEX_4V; + !strconcat(OpcodeStr, "ps"), f256mem, + [(set VR256:$dst, (v4i64 (OpNode VR256:$src1, VR256:$src2)))], + [(set VR256:$dst, (OpNode (bc_v4i64 (v8f32 VR256:$src1)), + (memopv4i64 addr:$src2)))], 0>, VEX_4V; defm PDY : sse12_fp_packed_logical_rm<opc, VR256, SSEPackedDouble, - !strconcat(OpcodeStr, "pd"), f256mem, [], [], 0>, OpSize, VEX_4V; + !strconcat(OpcodeStr, "pd"), f256mem, + [(set VR256:$dst, (OpNode (bc_v4i64 (v4f64 VR256:$src1)), + (bc_v4i64 (v4f64 VR256:$src2))))], + [(set VR256:$dst, (OpNode (bc_v4i64 (v4f64 VR256:$src1)), + (memopv4i64 addr:$src2)))], 0>, + OpSize, VEX_4V; } // AVX 256-bit packed logical ops forms -defm VAND : sse12_fp_packed_logical_y<0x54, "and">; -defm VOR : sse12_fp_packed_logical_y<0x56, "or">; -defm VXOR : sse12_fp_packed_logical_y<0x57, "xor">; -let isCommutable = 0 in - defm VANDN : sse12_fp_packed_logical_y<0x55, "andn">; +defm VAND : sse12_fp_packed_logical_y<0x54, "and", and>; +defm VOR : sse12_fp_packed_logical_y<0x56, "or", or>; +defm VXOR : sse12_fp_packed_logical_y<0x57, "xor", xor>; +defm VANDN : sse12_fp_packed_logical_y<0x55, "andn", X86andnp>; defm AND : sse12_fp_packed_logical<0x54, "and", and>; defm OR : sse12_fp_packed_logical<0x56, "or", or>; defm XOR : sse12_fp_packed_logical<0x57, "xor", xor>; let isCommutable = 0 in - defm ANDN : sse12_fp_packed_logical<0x55, "andn", undef /* dummy */, 1, [ - // single r+r - [(set VR128:$dst, (X86pandn VR128:$src1, VR128:$src2))], - // double r+r - [], - // single r+m - [(set VR128:$dst, (X86pandn VR128:$src1, (memopv2i64 addr:$src2)))], - // double r+m - []]>; + defm ANDN : sse12_fp_packed_logical<0x55, "andn", X86andnp>; //===----------------------------------------------------------------------===// // SSE 1 & 2 - Arithmetic Instructions @@ -1991,11 +1996,11 @@ def : Pat<(alignednontemporalstore (v2i64 VR128:$src), addr:$dst), // There is no AVX form for instructions below this point def MOVNTImr : I<0xC3, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), - "movnti\t{$src, $dst|$dst, $src}", + "movnti{l}\t{$src, $dst|$dst, $src}", [(nontemporalstore (i32 GR32:$src), addr:$dst)]>, TB, Requires<[HasSSE2]>; def MOVNTI_64mr : RI<0xC3, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), - "movnti\t{$src, $dst|$dst, $src}", + "movnti{q}\t{$src, $dst|$dst, $src}", [(nontemporalstore (i64 GR64:$src), addr:$dst)]>, TB, Requires<[HasSSE2]>; } @@ -2006,13 +2011,13 @@ def MOVNTI_64mr : RI<0xC3, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), // Prefetch intrinsic. def PREFETCHT0 : PSI<0x18, MRM1m, (outs), (ins i8mem:$src), - "prefetcht0\t$src", [(prefetch addr:$src, imm, (i32 3))]>; + "prefetcht0\t$src", [(prefetch addr:$src, imm, (i32 3), (i32 1))]>; def PREFETCHT1 : PSI<0x18, MRM2m, (outs), (ins i8mem:$src), - "prefetcht1\t$src", [(prefetch addr:$src, imm, (i32 2))]>; + "prefetcht1\t$src", [(prefetch addr:$src, imm, (i32 2), (i32 1))]>; def PREFETCHT2 : PSI<0x18, MRM3m, (outs), (ins i8mem:$src), - "prefetcht2\t$src", [(prefetch addr:$src, imm, (i32 1))]>; + "prefetcht2\t$src", [(prefetch addr:$src, imm, (i32 1), (i32 1))]>; def PREFETCHNTA : PSI<0x18, MRM0m, (outs), (ins i8mem:$src), - "prefetchnta\t$src", [(prefetch addr:$src, imm, (i32 0))]>; + "prefetchnta\t$src", [(prefetch addr:$src, imm, (i32 0), (i32 1))]>; // Load, store, and memory fence def SFENCE : I<0xAE, MRM_F8, (outs), (ins), "sfence", [(int_x86_sse_sfence)]>, @@ -2037,7 +2042,10 @@ def V_SET0PI : PDI<0xEF, MRMInitReg, (outs VR128:$dst), (ins), "", } // The same as done above but for AVX. The 128-bit versions are the -// same, but re-encoded. The 256-bit does not support PI version. +// same, but re-encoded. The 256-bit does not support PI version, and +// doesn't need it because on sandy bridge the register is set to zero +// at the rename stage without using any execution unit, so SET0PSY +// and SET0PDY can be used for vector int instructions without penalty // FIXME: Change encoding to pseudo! This is blocked right now by the x86 // JIT implementatioan, it does not expand the instructions below like // X86MCInstLower does. @@ -2052,8 +2060,8 @@ def AVX_SET0PSY : PSI<0x57, MRMInitReg, (outs VR256:$dst), (ins), "", def AVX_SET0PDY : PDI<0x57, MRMInitReg, (outs VR256:$dst), (ins), "", [(set VR256:$dst, (v4f64 immAllZerosV))]>, VEX_4V; let ExeDomain = SSEPackedInt in -def AVX_SET0PI : PDI<0xEF, MRMInitReg, (outs VR128:$dst), (ins), "", - [(set VR128:$dst, (v4i32 immAllZerosV))]>; +def AVX_SET0PI : PDI<0xEF, MRMInitReg, (outs VR128:$dst), (ins), "", + [(set VR128:$dst, (v4i32 immAllZerosV))]>; } def : Pat<(v2i64 immAllZerosV), (V_SET0PI)>; @@ -2063,6 +2071,15 @@ def : Pat<(v16i8 immAllZerosV), (V_SET0PI)>; def : Pat<(f32 (vector_extract (v4f32 VR128:$src), (iPTR 0))), (f32 (EXTRACT_SUBREG (v4f32 VR128:$src), sub_ss))>; +// FIXME: According to the intel manual, DEST[127:64] <- SRC1[127:64], while +// in the non-AVX version bits 127:64 aren't touched. Find a better way to +// represent this instead of always zeroing SRC1. One possible solution is +// to represent the instruction w/ something similar as the "$src1 = $dst" +// constraint but without the tied operands. +def : Pat<(extloadf32 addr:$src), + (VCVTSS2SDrm (f32 (EXTRACT_SUBREG (AVX_SET0PS), sub_ss)), addr:$src)>, + Requires<[HasAVX, OptForSpeed]>; + //===----------------------------------------------------------------------===// // SSE 1 & 2 - Load/Store XCSR register //===----------------------------------------------------------------------===// @@ -2959,6 +2976,22 @@ def : Pat<(v4i32 (X86vzmovl (bc_v4i32 (loadv2i64 addr:$src)))), (MOVZDI2PDIrm addr:$src)>; } +// These are the correct encodings of the instructions so that we know how to +// read correct assembly, even though we continue to emit the wrong ones for +// compatibility with Darwin's buggy assembler. +def : InstAlias<"movq\t{$src, $dst|$dst, $src}", + (MOV64toPQIrr VR128:$dst, GR64:$src), 0>; +def : InstAlias<"movq\t{$src, $dst|$dst, $src}", + (MOV64toSDrr FR64:$dst, GR64:$src), 0>; +def : InstAlias<"movq\t{$src, $dst|$dst, $src}", + (MOVPQIto64rr GR64:$dst, VR128:$src), 0>; +def : InstAlias<"movq\t{$src, $dst|$dst, $src}", + (MOVSDto64rr GR64:$dst, FR64:$src), 0>; +def : InstAlias<"movq\t{$src, $dst|$dst, $src}", + (VMOVZQI2PQIrr VR128:$dst, GR64:$src), 0>; +def : InstAlias<"movq\t{$src, $dst|$dst, $src}", + (MOVZQI2PQIrr VR128:$dst, GR64:$src), 0>; + //===---------------------------------------------------------------------===// // SSE2 - Move Quadword //===---------------------------------------------------------------------===// @@ -3589,6 +3622,16 @@ let Predicates = [HasSSE2] in def : Pat<(fextend (loadf32 addr:$src)), (CVTSS2SDrm addr:$src)>; +// FIXME: According to the intel manual, DEST[127:64] <- SRC1[127:64], while +// in the non-AVX version bits 127:64 aren't touched. Find a better way to +// represent this instead of always zeroing SRC1. One possible solution is +// to represent the instruction w/ something similar as the "$src1 = $dst" +// constraint but without the tied operands. +let Predicates = [HasAVX] in + def : Pat<(fextend (loadf32 addr:$src)), + (VCVTSS2SDrm (f32 (EXTRACT_SUBREG (AVX_SET0PS), sub_ss)), + addr:$src)>; + // bit_convert let Predicates = [HasXMMInt] in { def : Pat<(v2i64 (bitconvert (v4i32 VR128:$src))), (v2i64 VR128:$src)>; @@ -3625,6 +3668,19 @@ let Predicates = [HasXMMInt] in { let Predicates = [HasAVX] in { def : Pat<(v4f64 (bitconvert (v8f32 VR256:$src))), (v4f64 VR256:$src)>; + def : Pat<(v4f64 (bitconvert (v4i64 VR256:$src))), (v4f64 VR256:$src)>; + def : Pat<(v4f64 (bitconvert (v32i8 VR256:$src))), (v4f64 VR256:$src)>; + def : Pat<(v8f32 (bitconvert (v4i64 VR256:$src))), (v8f32 VR256:$src)>; + def : Pat<(v8f32 (bitconvert (v4f64 VR256:$src))), (v8f32 VR256:$src)>; + def : Pat<(v8f32 (bitconvert (v32i8 VR256:$src))), (v8f32 VR256:$src)>; + def : Pat<(v4i64 (bitconvert (v8f32 VR256:$src))), (v4i64 VR256:$src)>; + def : Pat<(v4i64 (bitconvert (v4f64 VR256:$src))), (v4i64 VR256:$src)>; + def : Pat<(v4i64 (bitconvert (v32i8 VR256:$src))), (v4i64 VR256:$src)>; + def : Pat<(v32i8 (bitconvert (v4f64 VR256:$src))), (v32i8 VR256:$src)>; + def : Pat<(v32i8 (bitconvert (v4i64 VR256:$src))), (v32i8 VR256:$src)>; + def : Pat<(v32i8 (bitconvert (v8f32 VR256:$src))), (v32i8 VR256:$src)>; + def : Pat<(v32i8 (bitconvert (v8i32 VR256:$src))), (v32i8 VR256:$src)>; + def : Pat<(v8i32 (bitconvert (v32i8 VR256:$src))), (v8i32 VR256:$src)>; } // Move scalar to XMM zero-extended @@ -3807,6 +3863,8 @@ def : Pat<(v4i32 (fp_to_sint (v4f32 VR128:$src))), (CVTTPS2DQrr VR128:$src)>, Requires<[HasSSE2]>; // Use movaps / movups for SSE integer load / store (one byte shorter). +// The instructions selected below are then converted to MOVDQA/MOVDQU +// during the SSE domain pass. let Predicates = [HasSSE1] in { def : Pat<(alignedloadv4i32 addr:$src), (MOVAPSrm addr:$src)>; @@ -3835,8 +3893,9 @@ let Predicates = [HasSSE1] in { (MOVUPSmr addr:$dst, VR128:$src)>; } -// Use vmovaps/vmovups for AVX 128-bit integer load/store (one byte shorter). +// Use vmovaps/vmovups for AVX integer load/store. let Predicates = [HasAVX] in { + // 128-bit load/store def : Pat<(alignedloadv4i32 addr:$src), (VMOVAPSrm addr:$src)>; def : Pat<(loadv4i32 addr:$src), @@ -3862,6 +3921,24 @@ let Predicates = [HasAVX] in { (VMOVUPSmr addr:$dst, VR128:$src)>; def : Pat<(store (v16i8 VR128:$src), addr:$dst), (VMOVUPSmr addr:$dst, VR128:$src)>; + + // 256-bit load/store + def : Pat<(alignedloadv4i64 addr:$src), + (VMOVAPSYrm addr:$src)>; + def : Pat<(loadv4i64 addr:$src), + (VMOVUPSYrm addr:$src)>; + def : Pat<(alignedloadv8i32 addr:$src), + (VMOVAPSYrm addr:$src)>; + def : Pat<(loadv8i32 addr:$src), + (VMOVUPSYrm addr:$src)>; + def : Pat<(alignedstore (v4i64 VR256:$src), addr:$dst), + (VMOVAPSYmr addr:$dst, VR256:$src)>; + def : Pat<(alignedstore (v8i32 VR256:$src), addr:$dst), + (VMOVAPSYmr addr:$dst, VR256:$src)>; + def : Pat<(store (v4i64 VR256:$src), addr:$dst), + (VMOVUPSYmr addr:$dst, VR256:$src)>; + def : Pat<(store (v8i32 VR256:$src), addr:$dst), + (VMOVUPSYmr addr:$dst, VR256:$src)>; } //===----------------------------------------------------------------------===// @@ -5160,33 +5237,52 @@ def AESKEYGENASSIST128rm : AESAI<0xDF, MRMSrcMem, (outs VR128:$dst), // CLMUL Instructions //===----------------------------------------------------------------------===// -// Only the AVX version of CLMUL instructions are described here. - // Carry-less Multiplication instructions -def VPCLMULQDQrr : CLMULIi8<0x44, MRMSrcReg, (outs VR128:$dst), +let Constraints = "$src1 = $dst" in { +def PCLMULQDQrr : CLMULIi8<0x44, MRMSrcReg, (outs VR128:$dst), + (ins VR128:$src1, VR128:$src2, i8imm:$src3), + "pclmulqdq\t{$src3, $src2, $dst|$dst, $src2, $src3}", + []>; + +def PCLMULQDQrm : CLMULIi8<0x44, MRMSrcMem, (outs VR128:$dst), + (ins VR128:$src1, i128mem:$src2, i8imm:$src3), + "pclmulqdq\t{$src3, $src2, $dst|$dst, $src2, $src3}", + []>; +} + +// AVX carry-less Multiplication instructions +def VPCLMULQDQrr : AVXCLMULIi8<0x44, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2, i8imm:$src3), "vpclmulqdq\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", []>; -def VPCLMULQDQrm : CLMULIi8<0x44, MRMSrcMem, (outs VR128:$dst), +def VPCLMULQDQrm : AVXCLMULIi8<0x44, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2, i8imm:$src3), "vpclmulqdq\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", []>; -// Assembler Only -multiclass avx_vpclmul<string asm> { - def rr : I<0, Pseudo, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), - !strconcat(asm, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - []>; - - def rm : I<0, Pseudo, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2), - !strconcat(asm, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), - []>; -} -defm VPCLMULHQHQDQ : avx_vpclmul<"vpclmulhqhqdq">; -defm VPCLMULHQLQDQ : avx_vpclmul<"vpclmulhqlqdq">; -defm VPCLMULLQHQDQ : avx_vpclmul<"vpclmullqhqdq">; -defm VPCLMULLQLQDQ : avx_vpclmul<"vpclmullqlqdq">; + +multiclass pclmul_alias<string asm, int immop> { + def : InstAlias<!strconcat("pclmul", asm, + "dq {$src, $dst|$dst, $src}"), + (PCLMULQDQrr VR128:$dst, VR128:$src, immop)>; + + def : InstAlias<!strconcat("pclmul", asm, + "dq {$src, $dst|$dst, $src}"), + (PCLMULQDQrm VR128:$dst, i128mem:$src, immop)>; + + def : InstAlias<!strconcat("vpclmul", asm, + "dq {$src2, $src1, $dst|$dst, $src1, $src2}"), + (VPCLMULQDQrr VR128:$dst, VR128:$src1, VR128:$src2, immop)>; + + def : InstAlias<!strconcat("vpclmul", asm, + "dq {$src2, $src1, $dst|$dst, $src1, $src2}"), + (VPCLMULQDQrm VR128:$dst, VR128:$src1, i128mem:$src2, immop)>; +} +defm : pclmul_alias<"hqhq", 0x11>; +defm : pclmul_alias<"hqlq", 0x01>; +defm : pclmul_alias<"lqhq", 0x10>; +defm : pclmul_alias<"lqlq", 0x00>; //===----------------------------------------------------------------------===// // AVX Instructions diff --git a/lib/Target/X86/X86InstrSystem.td b/lib/Target/X86/X86InstrSystem.td index f73cff39e86d..31de878343ef 100644 --- a/lib/Target/X86/X86InstrSystem.td +++ b/lib/Target/X86/X86InstrSystem.td @@ -411,6 +411,8 @@ let Uses = [RDX, RAX, RCX] in let Defs = [RAX, RDI], Uses = [RDX, RDI] in def XSTORE : I<0xc0, RawFrm, (outs), (ins), "xstore", []>, A7; +def : InstAlias<"xstorerng", (XSTORE)>; + let Defs = [RSI, RDI], Uses = [RBX, RDX, RSI, RDI] in { def XCRYPTECB : I<0xc8, RawFrm, (outs), (ins), "xcryptecb", []>, A7; def XCRYPTCBC : I<0xd0, RawFrm, (outs), (ins), "xcryptcbc", []>, A7; diff --git a/lib/Target/X86/X86MCCodeEmitter.cpp b/lib/Target/X86/X86MCCodeEmitter.cpp index 55aceba9f270..ce8ef495c001 100644 --- a/lib/Target/X86/X86MCCodeEmitter.cpp +++ b/lib/Target/X86/X86MCCodeEmitter.cpp @@ -18,26 +18,32 @@ #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/raw_ostream.h" + using namespace llvm; namespace { class X86MCCodeEmitter : public MCCodeEmitter { X86MCCodeEmitter(const X86MCCodeEmitter &); // DO NOT IMPLEMENT void operator=(const X86MCCodeEmitter &); // DO NOT IMPLEMENT - const TargetMachine &TM; - const TargetInstrInfo &TII; + const MCInstrInfo &MCII; + const MCSubtargetInfo &STI; MCContext &Ctx; - bool Is64BitMode; public: - X86MCCodeEmitter(TargetMachine &tm, MCContext &ctx, bool is64Bit) - : TM(tm), TII(*TM.getInstrInfo()), Ctx(ctx) { - Is64BitMode = is64Bit; + X86MCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti, + MCContext &ctx) + : MCII(mcii), STI(sti), Ctx(ctx) { } ~X86MCCodeEmitter() {} + bool is64BitMode() const { + // FIXME: Can tablegen auto-generate this? + return (STI.getFeatureBits() & X86::Mode64Bit) != 0; + } + static unsigned GetX86RegNum(const MCOperand &MO) { return X86RegisterInfo::getX86RegNum(MO.getReg()); } @@ -111,7 +117,7 @@ public: SmallVectorImpl<MCFixup> &Fixups) const; void EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, - const MCInst &MI, const TargetInstrDesc &Desc, + const MCInst &MI, const MCInstrDesc &Desc, raw_ostream &OS) const; void EmitSegmentOverridePrefix(uint64_t TSFlags, unsigned &CurByte, @@ -119,23 +125,17 @@ public: raw_ostream &OS) const; void EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, - const MCInst &MI, const TargetInstrDesc &Desc, + const MCInst &MI, const MCInstrDesc &Desc, raw_ostream &OS) const; }; } // end anonymous namespace -MCCodeEmitter *llvm::createX86_32MCCodeEmitter(const Target &, - TargetMachine &TM, - MCContext &Ctx) { - return new X86MCCodeEmitter(TM, Ctx, false); -} - -MCCodeEmitter *llvm::createX86_64MCCodeEmitter(const Target &, - TargetMachine &TM, - MCContext &Ctx) { - return new X86MCCodeEmitter(TM, Ctx, true); +MCCodeEmitter *llvm::createX86MCCodeEmitter(const MCInstrInfo &MCII, + const MCSubtargetInfo &STI, + MCContext &Ctx) { + return new X86MCCodeEmitter(MCII, STI, Ctx); } /// isDisp8 - Return true if this signed displacement fits in a 8-bit @@ -245,7 +245,7 @@ void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op, // Handle %rip relative addressing. if (BaseReg == X86::RIP) { // [disp32+RIP] in X86-64 mode - assert(Is64BitMode && "Rip-relative addressing requires 64-bit mode"); + assert(is64BitMode() && "Rip-relative addressing requires 64-bit mode"); assert(IndexReg.getReg() == 0 && "Invalid rip-relative address"); EmitByte(ModRMByte(0, RegOpcodeField, 5), CurByte, OS); @@ -284,7 +284,7 @@ void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op, BaseRegNo != N86::ESP && // If there is no base register and we're in 64-bit mode, we need a SIB // byte to emit an addr that is just 'disp32' (the non-RIP relative form). - (!Is64BitMode || BaseReg != 0)) { + (!is64BitMode() || BaseReg != 0)) { if (BaseReg == 0) { // [disp32] in X86-32 mode EmitByte(ModRMByte(0, RegOpcodeField, 5), CurByte, OS); @@ -379,7 +379,7 @@ void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op, /// called VEX. void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, const MCInst &MI, - const TargetInstrDesc &Desc, + const MCInstrDesc &Desc, raw_ostream &OS) const { bool HasVEX_4V = false; if ((TSFlags >> X86II::VEXShift) & X86II::VEX_4V) @@ -586,7 +586,7 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, /// REX prefix which specifies 1) 64-bit instructions, 2) non-default operand /// size, and 3) use of X86-64 extended registers. static unsigned DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags, - const TargetInstrDesc &Desc) { + const MCInstrDesc &Desc) { unsigned REX = 0; if (TSFlags & X86II::REX_W) REX |= 1 << 3; // set REX.W @@ -596,7 +596,7 @@ static unsigned DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags, unsigned NumOps = MI.getNumOperands(); // FIXME: MCInst should explicitize the two-addrness. bool isTwoAddr = NumOps > 1 && - Desc.getOperandConstraint(1, TOI::TIED_TO) != -1; + Desc.getOperandConstraint(1, MCOI::TIED_TO) != -1; // If it accesses SPL, BPL, SIL, or DIL, then it requires a 0x40 REX prefix. unsigned i = isTwoAddr ? 1 : 0; @@ -713,7 +713,7 @@ void X86MCCodeEmitter::EmitSegmentOverridePrefix(uint64_t TSFlags, /// Not present, it is -1. void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, const MCInst &MI, - const TargetInstrDesc &Desc, + const MCInstrDesc &Desc, raw_ostream &OS) const { // Emit the lock opcode prefix as needed. @@ -729,7 +729,7 @@ void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, // Emit the address size opcode prefix as needed. if ((TSFlags & X86II::AdSize) || - (MemOperand != -1 && Is64BitMode && Is32BitMemOperand(MI, MemOperand))) + (MemOperand != -1 && is64BitMode() && Is32BitMemOperand(MI, MemOperand))) EmitByte(0x67, CurByte, OS); // Emit the operand size opcode prefix as needed. @@ -772,7 +772,7 @@ void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, // Handle REX prefix. // FIXME: Can this come before F2 etc to simplify emission? - if (Is64BitMode) { + if (is64BitMode()) { if (unsigned REX = DetermineREXPrefix(MI, TSFlags, Desc)) EmitByte(0x40 | REX, CurByte, OS); } @@ -803,7 +803,7 @@ void X86MCCodeEmitter:: EncodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups) const { unsigned Opcode = MI.getOpcode(); - const TargetInstrDesc &Desc = TII.get(Opcode); + const MCInstrDesc &Desc = MCII.get(Opcode); uint64_t TSFlags = Desc.TSFlags; // Pseudo instructions don't get encoded. @@ -814,9 +814,9 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, // FIXME: This should be handled during MCInst lowering. unsigned NumOps = Desc.getNumOperands(); unsigned CurOp = 0; - if (NumOps > 1 && Desc.getOperandConstraint(1, TOI::TIED_TO) != -1) + if (NumOps > 1 && Desc.getOperandConstraint(1, MCOI::TIED_TO) != -1) ++CurOp; - else if (NumOps > 2 && Desc.getOperandConstraint(NumOps-1, TOI::TIED_TO)== 0) + else if (NumOps > 2 && Desc.getOperandConstraint(NumOps-1, MCOI::TIED_TO)== 0) // Skip the last source operand that is tied_to the dest reg. e.g. LXADD32 --NumOps; diff --git a/lib/Target/X86/X86MCInstLower.cpp b/lib/Target/X86/X86MCInstLower.cpp index 793156ffce83..e38533555534 100644 --- a/lib/Target/X86/X86MCInstLower.cpp +++ b/lib/Target/X86/X86MCInstLower.cpp @@ -16,8 +16,8 @@ #include "X86MCInstLower.h" #include "X86AsmPrinter.h" #include "X86COFFMachineModuleInfo.h" -#include "X86MCAsmInfo.h" #include "llvm/CodeGen/MachineModuleInfoImpls.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" diff --git a/lib/Target/X86/X86MachObjectWriter.cpp b/lib/Target/X86/X86MachObjectWriter.cpp index 8f3dd3222489..37110382379e 100644 --- a/lib/Target/X86/X86MachObjectWriter.cpp +++ b/lib/Target/X86/X86MachObjectWriter.cpp @@ -8,19 +8,541 @@ //===----------------------------------------------------------------------===// #include "X86.h" +#include "X86FixupKinds.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCMachObjectWriter.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Object/MachOFormat.h" + using namespace llvm; +using namespace llvm::object; namespace { class X86MachObjectWriter : public MCMachObjectTargetWriter { + void RecordScatteredRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + unsigned Log2Size, + uint64_t &FixedValue); + void RecordTLVPRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue); + + void RecordX86Relocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue); + void RecordX86_64Relocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue); public: X86MachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype) : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype, /*UseAggressiveSymbolFolding=*/Is64Bit) {} + + void RecordRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, uint64_t &FixedValue) { + if (Writer->is64Bit()) + RecordX86_64Relocation(Writer, Asm, Layout, Fragment, Fixup, Target, + FixedValue); + else + RecordX86Relocation(Writer, Asm, Layout, Fragment, Fixup, Target, + FixedValue); + } }; } +static bool isFixupKindRIPRel(unsigned Kind) { + return Kind == X86::reloc_riprel_4byte || + Kind == X86::reloc_riprel_4byte_movq_load; +} + +static unsigned getFixupKindLog2Size(unsigned Kind) { + switch (Kind) { + default: + llvm_unreachable("invalid fixup kind!"); + case FK_PCRel_1: + case FK_Data_1: return 0; + case FK_PCRel_2: + case FK_Data_2: return 1; + case FK_PCRel_4: + // FIXME: Remove these!!! + case X86::reloc_riprel_4byte: + case X86::reloc_riprel_4byte_movq_load: + case X86::reloc_signed_4byte: + case FK_Data_4: return 2; + case FK_Data_8: return 3; + } +} + +void X86MachObjectWriter::RecordX86_64Relocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue) { + unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned IsRIPRel = isFixupKindRIPRel(Fixup.getKind()); + unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); + + // See <reloc.h>. + uint32_t FixupOffset = + Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); + uint32_t FixupAddress = + Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset(); + int64_t Value = 0; + unsigned Index = 0; + unsigned IsExtern = 0; + unsigned Type = 0; + + Value = Target.getConstant(); + + if (IsPCRel) { + // Compensate for the relocation offset, Darwin x86_64 relocations only have + // the addend and appear to have attempted to define it to be the actual + // expression addend without the PCrel bias. However, instructions with data + // following the relocation are not accommodated for (see comment below + // regarding SIGNED{1,2,4}), so it isn't exactly that either. + Value += 1LL << Log2Size; + } + + if (Target.isAbsolute()) { // constant + // SymbolNum of 0 indicates the absolute section. + Type = macho::RIT_X86_64_Unsigned; + Index = 0; + + // FIXME: I believe this is broken, I don't think the linker can understand + // it. I think it would require a local relocation, but I'm not sure if that + // would work either. The official way to get an absolute PCrel relocation + // is to use an absolute symbol (which we don't support yet). + if (IsPCRel) { + IsExtern = 1; + Type = macho::RIT_X86_64_Branch; + } + } else if (Target.getSymB()) { // A - B + constant + const MCSymbol *A = &Target.getSymA()->getSymbol(); + MCSymbolData &A_SD = Asm.getSymbolData(*A); + const MCSymbolData *A_Base = Asm.getAtom(&A_SD); + + const MCSymbol *B = &Target.getSymB()->getSymbol(); + MCSymbolData &B_SD = Asm.getSymbolData(*B); + const MCSymbolData *B_Base = Asm.getAtom(&B_SD); + + // Neither symbol can be modified. + if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None || + Target.getSymB()->getKind() != MCSymbolRefExpr::VK_None) + report_fatal_error("unsupported relocation of modified symbol"); + + // We don't support PCrel relocations of differences. Darwin 'as' doesn't + // implement most of these correctly. + if (IsPCRel) + report_fatal_error("unsupported pc-relative relocation of difference"); + + // The support for the situation where one or both of the symbols would + // require a local relocation is handled just like if the symbols were + // external. This is certainly used in the case of debug sections where the + // section has only temporary symbols and thus the symbols don't have base + // symbols. This is encoded using the section ordinal and non-extern + // relocation entries. + + // Darwin 'as' doesn't emit correct relocations for this (it ends up with a + // single SIGNED relocation); reject it for now. Except the case where both + // symbols don't have a base, equal but both NULL. + if (A_Base == B_Base && A_Base) + report_fatal_error("unsupported relocation with identical base"); + + Value += Writer->getSymbolAddress(&A_SD, Layout) - + (A_Base == NULL ? 0 : Writer->getSymbolAddress(A_Base, Layout)); + Value -= Writer->getSymbolAddress(&B_SD, Layout) - + (B_Base == NULL ? 0 : Writer->getSymbolAddress(B_Base, Layout)); + + if (A_Base) { + Index = A_Base->getIndex(); + IsExtern = 1; + } + else { + Index = A_SD.getFragment()->getParent()->getOrdinal() + 1; + IsExtern = 0; + } + Type = macho::RIT_X86_64_Unsigned; + + macho::RelocationEntry MRE; + MRE.Word0 = FixupOffset; + MRE.Word1 = ((Index << 0) | + (IsPCRel << 24) | + (Log2Size << 25) | + (IsExtern << 27) | + (Type << 28)); + Writer->addRelocation(Fragment->getParent(), MRE); + + if (B_Base) { + Index = B_Base->getIndex(); + IsExtern = 1; + } + else { + Index = B_SD.getFragment()->getParent()->getOrdinal() + 1; + IsExtern = 0; + } + Type = macho::RIT_X86_64_Subtractor; + } else { + const MCSymbol *Symbol = &Target.getSymA()->getSymbol(); + MCSymbolData &SD = Asm.getSymbolData(*Symbol); + const MCSymbolData *Base = Asm.getAtom(&SD); + + // Relocations inside debug sections always use local relocations when + // possible. This seems to be done because the debugger doesn't fully + // understand x86_64 relocation entries, and expects to find values that + // have already been fixed up. + if (Symbol->isInSection()) { + const MCSectionMachO &Section = static_cast<const MCSectionMachO&>( + Fragment->getParent()->getSection()); + if (Section.hasAttribute(MCSectionMachO::S_ATTR_DEBUG)) + Base = 0; + } + + // x86_64 almost always uses external relocations, except when there is no + // symbol to use as a base address (a local symbol with no preceding + // non-local symbol). + if (Base) { + Index = Base->getIndex(); + IsExtern = 1; + + // Add the local offset, if needed. + if (Base != &SD) + Value += Layout.getSymbolOffset(&SD) - Layout.getSymbolOffset(Base); + } else if (Symbol->isInSection() && !Symbol->isVariable()) { + // The index is the section ordinal (1-based). + Index = SD.getFragment()->getParent()->getOrdinal() + 1; + IsExtern = 0; + Value += Writer->getSymbolAddress(&SD, Layout); + + if (IsPCRel) + Value -= FixupAddress + (1 << Log2Size); + } else if (Symbol->isVariable()) { + const MCExpr *Value = Symbol->getVariableValue(); + int64_t Res; + bool isAbs = Value->EvaluateAsAbsolute(Res, Layout, + Writer->getSectionAddressMap()); + if (isAbs) { + FixedValue = Res; + return; + } else { + report_fatal_error("unsupported relocation of variable '" + + Symbol->getName() + "'"); + } + } else { + report_fatal_error("unsupported relocation of undefined symbol '" + + Symbol->getName() + "'"); + } + + MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind(); + if (IsPCRel) { + if (IsRIPRel) { + if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) { + // x86_64 distinguishes movq foo@GOTPCREL so that the linker can + // rewrite the movq to an leaq at link time if the symbol ends up in + // the same linkage unit. + if (unsigned(Fixup.getKind()) == X86::reloc_riprel_4byte_movq_load) + Type = macho::RIT_X86_64_GOTLoad; + else + Type = macho::RIT_X86_64_GOT; + } else if (Modifier == MCSymbolRefExpr::VK_TLVP) { + Type = macho::RIT_X86_64_TLV; + } else if (Modifier != MCSymbolRefExpr::VK_None) { + report_fatal_error("unsupported symbol modifier in relocation"); + } else { + Type = macho::RIT_X86_64_Signed; + + // The Darwin x86_64 relocation format has a problem where it cannot + // encode an address (L<foo> + <constant>) which is outside the atom + // containing L<foo>. Generally, this shouldn't occur but it does + // happen when we have a RIPrel instruction with data following the + // relocation entry (e.g., movb $012, L0(%rip)). Even with the PCrel + // adjustment Darwin x86_64 uses, the offset is still negative and the + // linker has no way to recognize this. + // + // To work around this, Darwin uses several special relocation types + // to indicate the offsets. However, the specification or + // implementation of these seems to also be incomplete; they should + // adjust the addend as well based on the actual encoded instruction + // (the additional bias), but instead appear to just look at the final + // offset. + switch (-(Target.getConstant() + (1LL << Log2Size))) { + case 1: Type = macho::RIT_X86_64_Signed1; break; + case 2: Type = macho::RIT_X86_64_Signed2; break; + case 4: Type = macho::RIT_X86_64_Signed4; break; + } + } + } else { + if (Modifier != MCSymbolRefExpr::VK_None) + report_fatal_error("unsupported symbol modifier in branch " + "relocation"); + + Type = macho::RIT_X86_64_Branch; + } + } else { + if (Modifier == MCSymbolRefExpr::VK_GOT) { + Type = macho::RIT_X86_64_GOT; + } else if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) { + // GOTPCREL is allowed as a modifier on non-PCrel instructions, in which + // case all we do is set the PCrel bit in the relocation entry; this is + // used with exception handling, for example. The source is required to + // include any necessary offset directly. + Type = macho::RIT_X86_64_GOT; + IsPCRel = 1; + } else if (Modifier == MCSymbolRefExpr::VK_TLVP) { + report_fatal_error("TLVP symbol modifier should have been rip-rel"); + } else if (Modifier != MCSymbolRefExpr::VK_None) + report_fatal_error("unsupported symbol modifier in relocation"); + else + Type = macho::RIT_X86_64_Unsigned; + } + } + + // x86_64 always writes custom values into the fixups. + FixedValue = Value; + + // struct relocation_info (8 bytes) + macho::RelocationEntry MRE; + MRE.Word0 = FixupOffset; + MRE.Word1 = ((Index << 0) | + (IsPCRel << 24) | + (Log2Size << 25) | + (IsExtern << 27) | + (Type << 28)); + Writer->addRelocation(Fragment->getParent(), MRE); +} + +void X86MachObjectWriter::RecordScatteredRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + unsigned Log2Size, + uint64_t &FixedValue) { + uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); + unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned Type = macho::RIT_Vanilla; + + // See <reloc.h>. + const MCSymbol *A = &Target.getSymA()->getSymbol(); + MCSymbolData *A_SD = &Asm.getSymbolData(*A); + + if (!A_SD->getFragment()) + report_fatal_error("symbol '" + A->getName() + + "' can not be undefined in a subtraction expression"); + + uint32_t Value = Writer->getSymbolAddress(A_SD, Layout); + uint64_t SecAddr = Writer->getSectionAddress(A_SD->getFragment()->getParent()); + FixedValue += SecAddr; + uint32_t Value2 = 0; + + if (const MCSymbolRefExpr *B = Target.getSymB()) { + MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); + + if (!B_SD->getFragment()) + report_fatal_error("symbol '" + B->getSymbol().getName() + + "' can not be undefined in a subtraction expression"); + + // Select the appropriate difference relocation type. + // + // Note that there is no longer any semantic difference between these two + // relocation types from the linkers point of view, this is done solely for + // pedantic compatibility with 'as'. + Type = A_SD->isExternal() ? (unsigned)macho::RIT_Difference : + (unsigned)macho::RIT_Generic_LocalDifference; + Value2 = Writer->getSymbolAddress(B_SD, Layout); + FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent()); + } + + // Relocations are written out in reverse order, so the PAIR comes first. + if (Type == macho::RIT_Difference || + Type == macho::RIT_Generic_LocalDifference) { + macho::RelocationEntry MRE; + MRE.Word0 = ((0 << 0) | + (macho::RIT_Pair << 24) | + (Log2Size << 28) | + (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value2; + Writer->addRelocation(Fragment->getParent(), MRE); + } + + macho::RelocationEntry MRE; + MRE.Word0 = ((FixupOffset << 0) | + (Type << 24) | + (Log2Size << 28) | + (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value; + Writer->addRelocation(Fragment->getParent(), MRE); +} + +void X86MachObjectWriter::RecordTLVPRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue) { + assert(Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP && + !is64Bit() && + "Should only be called with a 32-bit TLVP relocation!"); + + unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); + uint32_t Value = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); + unsigned IsPCRel = 0; + + // Get the symbol data. + MCSymbolData *SD_A = &Asm.getSymbolData(Target.getSymA()->getSymbol()); + unsigned Index = SD_A->getIndex(); + + // We're only going to have a second symbol in pic mode and it'll be a + // subtraction from the picbase. For 32-bit pic the addend is the difference + // between the picbase and the next address. For 32-bit static the addend is + // zero. + if (Target.getSymB()) { + // If this is a subtraction then we're pcrel. + uint32_t FixupAddress = + Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset(); + MCSymbolData *SD_B = &Asm.getSymbolData(Target.getSymB()->getSymbol()); + IsPCRel = 1; + FixedValue = (FixupAddress - Writer->getSymbolAddress(SD_B, Layout) + + Target.getConstant()); + FixedValue += 1ULL << Log2Size; + } else { + FixedValue = 0; + } + + // struct relocation_info (8 bytes) + macho::RelocationEntry MRE; + MRE.Word0 = Value; + MRE.Word1 = ((Index << 0) | + (IsPCRel << 24) | + (Log2Size << 25) | + (1 << 27) | // Extern + (macho::RIT_Generic_TLV << 28)); // Type + Writer->addRelocation(Fragment->getParent(), MRE); +} + +void X86MachObjectWriter::RecordX86Relocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue) { + unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); + + // If this is a 32-bit TLVP reloc it's handled a bit differently. + if (Target.getSymA() && + Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP) { + RecordTLVPRelocation(Writer, Asm, Layout, Fragment, Fixup, Target, + FixedValue); + return; + } + + // If this is a difference or a defined symbol plus an offset, then we need a + // scattered relocation entry. Differences always require scattered + // relocations. + if (Target.getSymB()) + return RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, + Target, Log2Size, FixedValue); + + // Get the symbol data, if any. + MCSymbolData *SD = 0; + if (Target.getSymA()) + SD = &Asm.getSymbolData(Target.getSymA()->getSymbol()); + + // If this is an internal relocation with an offset, it also needs a scattered + // relocation entry. + uint32_t Offset = Target.getConstant(); + if (IsPCRel) + Offset += 1 << Log2Size; + if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD)) + return RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, + Target, Log2Size, FixedValue); + + // See <reloc.h>. + uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); + unsigned Index = 0; + unsigned IsExtern = 0; + unsigned Type = 0; + + if (Target.isAbsolute()) { // constant + // SymbolNum of 0 indicates the absolute section. + // + // FIXME: Currently, these are never generated (see code below). I cannot + // find a case where they are actually emitted. + Type = macho::RIT_Vanilla; + } else { + // Resolve constant variables. + if (SD->getSymbol().isVariable()) { + int64_t Res; + if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute( + Res, Layout, Writer->getSectionAddressMap())) { + FixedValue = Res; + return; + } + } + + // Check whether we need an external or internal relocation. + if (Writer->doesSymbolRequireExternRelocation(SD)) { + IsExtern = 1; + Index = SD->getIndex(); + // For external relocations, make sure to offset the fixup value to + // compensate for the addend of the symbol address, if it was + // undefined. This occurs with weak definitions, for example. + if (!SD->Symbol->isUndefined()) + FixedValue -= Layout.getSymbolOffset(SD); + } else { + // The index is the section ordinal (1-based). + const MCSectionData &SymSD = Asm.getSectionData( + SD->getSymbol().getSection()); + Index = SymSD.getOrdinal() + 1; + FixedValue += Writer->getSectionAddress(&SymSD); + } + if (IsPCRel) + FixedValue -= Writer->getSectionAddress(Fragment->getParent()); + + Type = macho::RIT_Vanilla; + } + + // struct relocation_info (8 bytes) + macho::RelocationEntry MRE; + MRE.Word0 = FixupOffset; + MRE.Word1 = ((Index << 0) | + (IsPCRel << 24) | + (Log2Size << 25) | + (IsExtern << 27) | + (Type << 28)); + Writer->addRelocation(Fragment->getParent(), MRE); +} + MCObjectWriter *llvm::createX86MachObjectWriter(raw_ostream &OS, bool Is64Bit, uint32_t CPUType, diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index 1ad6203af2f6..f2faf59367a1 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -39,6 +39,10 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/CommandLine.h" + +#define GET_REGINFO_TARGET_DESC +#include "X86GenRegisterInfo.inc" + using namespace llvm; cl::opt<bool> @@ -49,18 +53,11 @@ ForceStackAlign("force-align-stack", X86RegisterInfo::X86RegisterInfo(X86TargetMachine &tm, const TargetInstrInfo &tii) - : X86GenRegisterInfo(tm.getSubtarget<X86Subtarget>().is64Bit() ? - X86::ADJCALLSTACKDOWN64 : - X86::ADJCALLSTACKDOWN32, - tm.getSubtarget<X86Subtarget>().is64Bit() ? - X86::ADJCALLSTACKUP64 : - X86::ADJCALLSTACKUP32), - TM(tm), TII(tii) { + : X86GenRegisterInfo(), TM(tm), TII(tii) { // Cache some information. const X86Subtarget *Subtarget = &TM.getSubtarget<X86Subtarget>(); Is64Bit = Subtarget->is64Bit(); IsWin64 = Subtarget->isTargetWin64(); - StackAlign = TM.getFrameLowering()->getStackAlignment(); if (Is64Bit) { SlotSize = 8; @@ -107,6 +104,21 @@ int X86RegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const { return X86GenRegisterInfo::getLLVMRegNumFull(DwarfRegNo, Flavour); } +/// getCompactUnwindRegNum - This function maps the register to the number for +/// compact unwind encoding. Return -1 if the register isn't valid. +int X86RegisterInfo::getCompactUnwindRegNum(unsigned RegNum, bool isEH) const { + switch (getLLVMRegNum(RegNum, isEH)) { + case X86::EBX: case X86::RBX: return 1; + case X86::ECX: case X86::R12: return 2; + case X86::EDX: case X86::R13: return 3; + case X86::EDI: case X86::R14: return 4; + case X86::ESI: case X86::R15: return 5; + case X86::EBP: case X86::RBP: return 6; + } + + return -1; +} + int X86RegisterInfo::getSEHRegNum(unsigned i) const { int reg = getX86RegNum(i); @@ -495,18 +507,6 @@ BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const { Reserved.set(X86::BPL); } - // Mark the x87 stack registers as reserved, since they don't behave normally - // with respect to liveness. We don't fully model the effects of x87 stack - // pushes and pops after stackification. - Reserved.set(X86::ST0); - Reserved.set(X86::ST1); - Reserved.set(X86::ST2); - Reserved.set(X86::ST3); - Reserved.set(X86::ST4); - Reserved.set(X86::ST5); - Reserved.set(X86::ST6); - Reserved.set(X86::ST7); - // Mark the segment registers as reserved. Reserved.set(X86::CS); Reserved.set(X86::SS); @@ -517,13 +517,20 @@ BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const { // Reserve the registers that only exist in 64-bit mode. if (!Is64Bit) { + // These 8-bit registers are part of the x86-64 extension even though their + // super-registers are old 32-bits. + Reserved.set(X86::SIL); + Reserved.set(X86::DIL); + Reserved.set(X86::BPL); + Reserved.set(X86::SPL); + for (unsigned n = 0; n != 8; ++n) { + // R8, R9, ... const unsigned GPR64[] = { X86::R8, X86::R9, X86::R10, X86::R11, X86::R12, X86::R13, X86::R14, X86::R15 }; - for (const unsigned *AI = getOverlaps(GPR64[n]); unsigned Reg = *AI; - ++AI) + for (const unsigned *AI = getOverlaps(GPR64[n]); unsigned Reg = *AI; ++AI) Reserved.set(Reg); // XMM8, XMM9, ... @@ -550,6 +557,7 @@ bool X86RegisterInfo::canRealignStack(const MachineFunction &MF) const { bool X86RegisterInfo::needsStackRealignment(const MachineFunction &MF) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); const Function *F = MF.getFunction(); + unsigned StackAlign = TM.getFrameLowering()->getStackAlignment(); bool requiresRealignment = ((MFI->getMaxAlignment() > StackAlign) || F->hasFnAttr(Attribute::StackAlignment)); @@ -608,7 +616,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); bool reseveCallFrame = TFI->hasReservedCallFrame(MF); int Opcode = I->getOpcode(); - bool isDestroy = Opcode == getCallFrameDestroyOpcode(); + bool isDestroy = Opcode == TII.getCallFrameDestroyOpcode(); DebugLoc DL = I->getDebugLoc(); uint64_t Amount = !reseveCallFrame ? I->getOperand(0).getImm() : 0; uint64_t CalleeAmt = isDestroy ? I->getOperand(1).getImm() : 0; @@ -625,16 +633,17 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, // We need to keep the stack aligned properly. To do this, we round the // amount of space needed for the outgoing arguments up to the next // alignment boundary. + unsigned StackAlign = TM.getFrameLowering()->getStackAlignment(); Amount = (Amount + StackAlign - 1) / StackAlign * StackAlign; MachineInstr *New = 0; - if (Opcode == getCallFrameSetupOpcode()) { + if (Opcode == TII.getCallFrameSetupOpcode()) { New = BuildMI(MF, DL, TII.get(getSUBriOpcode(Is64Bit, Amount)), StackPtr) .addReg(StackPtr) .addImm(Amount); } else { - assert(Opcode == getCallFrameDestroyOpcode()); + assert(Opcode == TII.getCallFrameDestroyOpcode()); // Factor out the amount the callee already popped. Amount -= CalleeAmt; @@ -657,7 +666,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, return; } - if (Opcode == getCallFrameDestroyOpcode() && CalleeAmt) { + if (Opcode == TII.getCallFrameDestroyOpcode() && CalleeAmt) { // If we are performing frame pointer elimination and if the callee pops // something off the stack pointer, add it back. We do this until we have // more advanced stack pointer tracking ability. @@ -667,6 +676,13 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, // The EFLAGS implicit def is dead. New->getOperand(3).setIsDead(); + + // We are not tracking the stack pointer adjustment by the callee, so make + // sure we restore the stack pointer immediately after the call, there may + // be spill code inserted between the CALL and ADJCALLSTACKUP instructions. + MachineBasicBlock::iterator B = MBB.begin(); + while (I != B && !llvm::prior(I)->getDesc().isCall()) + --I; MBB.insert(I, New); } } @@ -713,7 +729,10 @@ X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, if (MI.getOperand(i+3).isImm()) { // Offset is a 32-bit integer. - int Offset = FIOffset + (int)(MI.getOperand(i + 3).getImm()); + int Imm = (int)(MI.getOperand(i + 3).getImm()); + int Offset = FIOffset + Imm; + assert((!Is64Bit || isInt<32>((long long)FIOffset + Imm)) && + "Requesting 64-bit offset in 32-bit immediate!"); MI.getOperand(i + 3).ChangeToImmediate(Offset); } else { // Offset is symbolic. This is extremely rare. @@ -910,8 +929,6 @@ unsigned getX86SubSuperRegister(unsigned Reg, EVT VT, bool High) { } } -#include "X86GenRegisterInfo.inc" - namespace { struct MSAH : public MachineFunctionPass { static char ID; @@ -920,10 +937,10 @@ namespace { virtual bool runOnMachineFunction(MachineFunction &MF) { const X86TargetMachine *TM = static_cast<const X86TargetMachine *>(&MF.getTarget()); - const X86RegisterInfo *X86RI = TM->getRegisterInfo(); + const TargetFrameLowering *TFI = TM->getFrameLowering(); MachineRegisterInfo &RI = MF.getRegInfo(); X86MachineFunctionInfo *FuncInfo = MF.getInfo<X86MachineFunctionInfo>(); - unsigned StackAlignment = X86RI->getStackAlignment(); + unsigned StackAlignment = TFI->getStackAlignment(); // Be over-conservative: scan over all vreg defs and find whether vector // registers are used. If yes, there is a possibility that vector register diff --git a/lib/Target/X86/X86RegisterInfo.h b/lib/Target/X86/X86RegisterInfo.h index dd3d3dcdcce5..a12eb1297f7e 100644 --- a/lib/Target/X86/X86RegisterInfo.h +++ b/lib/Target/X86/X86RegisterInfo.h @@ -15,7 +15,9 @@ #define X86REGISTERINFO_H #include "llvm/Target/TargetRegisterInfo.h" -#include "X86GenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "X86GenRegisterInfo.inc" namespace llvm { class Type; @@ -56,10 +58,6 @@ private: /// unsigned SlotSize; - /// StackAlign - Default stack alignment. - /// - unsigned StackAlign; - /// StackPtr - X86 physical register used as stack ptr. /// unsigned StackPtr; @@ -75,8 +73,6 @@ public: /// register identifier. static unsigned getX86RegNum(unsigned RegNo); - unsigned getStackAlignment() const { return StackAlign; } - /// getDwarfRegNum - allows modification of X86GenRegisterInfo::getDwarfRegNum /// (created by TableGen) for target dependencies. int getDwarfRegNum(unsigned RegNum, bool isEH) const; @@ -85,6 +81,10 @@ public: // FIXME: This should be tablegen'd like getDwarfRegNum is int getSEHRegNum(unsigned i) const; + /// getCompactUnwindRegNum - This function maps the register to the number for + /// compact unwind encoding. Return -1 if the register isn't valid. + int getCompactUnwindRegNum(unsigned RegNum, bool isEH) const; + /// Code Generation virtual methods... /// diff --git a/lib/Target/X86/X86RegisterInfo.td b/lib/Target/X86/X86RegisterInfo.td index f1d149c3fbc7..203722a66162 100644 --- a/lib/Target/X86/X86RegisterInfo.td +++ b/lib/Target/X86/X86RegisterInfo.td @@ -206,15 +206,22 @@ let Namespace = "X86" in { def YMM15: RegisterWithSubRegs<"ymm15", [XMM15]>, DwarfRegAlias<XMM15>; } - // Floating point stack registers - def ST0 : Register<"st(0)">, DwarfRegNum<[33, 12, 11]>; - def ST1 : Register<"st(1)">, DwarfRegNum<[34, 13, 12]>; - def ST2 : Register<"st(2)">, DwarfRegNum<[35, 14, 13]>; - def ST3 : Register<"st(3)">, DwarfRegNum<[36, 15, 14]>; - def ST4 : Register<"st(4)">, DwarfRegNum<[37, 16, 15]>; - def ST5 : Register<"st(5)">, DwarfRegNum<[38, 17, 16]>; - def ST6 : Register<"st(6)">, DwarfRegNum<[39, 18, 17]>; - def ST7 : Register<"st(7)">, DwarfRegNum<[40, 19, 18]>; + class STRegister<string Name, list<Register> A> : Register<Name> { + let Aliases = A; + } + + // Floating point stack registers. These don't map one-to-one to the FP + // pseudo registers, but we still mark them as aliasing FP registers. That + // way both kinds can be live without exceeding the stack depth. ST registers + // are only live around inline assembly. + def ST0 : STRegister<"st(0)", []>, DwarfRegNum<[33, 12, 11]>; + def ST1 : STRegister<"st(1)", [FP6]>, DwarfRegNum<[34, 13, 12]>; + def ST2 : STRegister<"st(2)", [FP5]>, DwarfRegNum<[35, 14, 13]>; + def ST3 : STRegister<"st(3)", [FP4]>, DwarfRegNum<[36, 15, 14]>; + def ST4 : STRegister<"st(4)", [FP3]>, DwarfRegNum<[37, 16, 15]>; + def ST5 : STRegister<"st(5)", [FP2]>, DwarfRegNum<[38, 17, 16]>; + def ST6 : STRegister<"st(6)", [FP1]>, DwarfRegNum<[39, 18, 17]>; + def ST7 : STRegister<"st(7)", [FP0]>, DwarfRegNum<[40, 19, 18]>; // Status flags register def EFLAGS : Register<"flags">; @@ -279,58 +286,23 @@ let Namespace = "X86" in { // require a REX prefix. For example, "addb %ah, %dil" and "movzbl %ah, %r8d" // cannot be encoded. def GR8 : RegisterClass<"X86", [i8], 8, - [AL, CL, DL, AH, CH, DH, BL, BH, SIL, DIL, BPL, SPL, - R8B, R9B, R10B, R11B, R14B, R15B, R12B, R13B]> { - let MethodProtos = [{ - iterator allocation_order_begin(const MachineFunction &MF) const; - iterator allocation_order_end(const MachineFunction &MF) const; - }]; - let MethodBodies = [{ - static const unsigned X86_GR8_AO_64[] = { - X86::AL, X86::CL, X86::DL, X86::SIL, X86::DIL, - X86::R8B, X86::R9B, X86::R10B, X86::R11B, - X86::BL, X86::R14B, X86::R15B, X86::R12B, X86::R13B, X86::BPL - }; - - GR8Class::iterator - GR8Class::allocation_order_begin(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const X86Subtarget &Subtarget = TM.getSubtarget<X86Subtarget>(); - if (Subtarget.is64Bit()) - return X86_GR8_AO_64; - else - return begin(); - } - - GR8Class::iterator - GR8Class::allocation_order_end(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const TargetFrameLowering *TFI = TM.getFrameLowering(); - const X86Subtarget &Subtarget = TM.getSubtarget<X86Subtarget>(); - const X86MachineFunctionInfo *MFI = MF.getInfo<X86MachineFunctionInfo>(); - // Does the function dedicate RBP / EBP to being a frame ptr? - if (!Subtarget.is64Bit()) - // In 32-mode, none of the 8-bit registers aliases EBP or ESP. - return begin() + 8; - else if (TFI->hasFP(MF) || MFI->getReserveFP()) - // If so, don't allocate SPL or BPL. - return array_endof(X86_GR8_AO_64) - 1; - else - // If not, just don't allocate SPL. - return array_endof(X86_GR8_AO_64); - } + (add AL, CL, DL, AH, CH, DH, BL, BH, SIL, DIL, BPL, SPL, + R8B, R9B, R10B, R11B, R14B, R15B, R12B, R13B)> { + let AltOrders = [(sub GR8, AH, BH, CH, DH)]; + let AltOrderSelect = [{ + return MF.getTarget().getSubtarget<X86Subtarget>().is64Bit(); }]; } def GR16 : RegisterClass<"X86", [i16], 16, - [AX, CX, DX, SI, DI, BX, BP, SP, - R8W, R9W, R10W, R11W, R14W, R15W, R12W, R13W]> { + (add AX, CX, DX, SI, DI, BX, BP, SP, + R8W, R9W, R10W, R11W, R14W, R15W, R12W, R13W)> { let SubRegClasses = [(GR8 sub_8bit, sub_8bit_hi)]; } def GR32 : RegisterClass<"X86", [i32], 32, - [EAX, ECX, EDX, ESI, EDI, EBX, EBP, ESP, - R8D, R9D, R10D, R11D, R14D, R15D, R12D, R13D]> { + (add EAX, ECX, EDX, ESI, EDI, EBX, EBP, ESP, + R8D, R9D, R10D, R11D, R14D, R15D, R12D, R13D)> { let SubRegClasses = [(GR8 sub_8bit, sub_8bit_hi), (GR16 sub_16bit)]; } @@ -338,8 +310,8 @@ def GR32 : RegisterClass<"X86", [i32], 32, // RIP isn't really a register and it can't be used anywhere except in an // address, but it doesn't cause trouble. def GR64 : RegisterClass<"X86", [i64], 64, - [RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, - RBX, R14, R15, R12, R13, RBP, RSP, RIP]> { + (add RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, + RBX, R14, R15, R12, R13, RBP, RSP, RIP)> { let SubRegClasses = [(GR8 sub_8bit, sub_8bit_hi), (GR16 sub_16bit), (GR32 sub_32bit)]; @@ -348,16 +320,13 @@ def GR64 : RegisterClass<"X86", [i64], 64, // Segment registers for use by MOV instructions (and others) that have a // segment register as one operand. Always contain a 16-bit segment // descriptor. -def SEGMENT_REG : RegisterClass<"X86", [i16], 16, [CS, DS, SS, ES, FS, GS]>; +def SEGMENT_REG : RegisterClass<"X86", [i16], 16, (add CS, DS, SS, ES, FS, GS)>; // Debug registers. -def DEBUG_REG : RegisterClass<"X86", [i32], 32, - [DR0, DR1, DR2, DR3, DR4, DR5, DR6, DR7]>; +def DEBUG_REG : RegisterClass<"X86", [i32], 32, (sequence "DR%u", 0, 7)>; // Control registers. -def CONTROL_REG : RegisterClass<"X86", [i64], 64, - [CR0, CR1, CR2, CR3, CR4, CR5, CR6, CR7, CR8, - CR9, CR10, CR11, CR12, CR13, CR14, CR15]>; +def CONTROL_REG : RegisterClass<"X86", [i64], 64, (sequence "CR%u", 0, 15)>; // GR8_ABCD_L, GR8_ABCD_H, GR16_ABCD, GR32_ABCD, GR64_ABCD - Subclasses of // GR8, GR16, GR32, and GR64 which contain just the "a" "b", "c", and "d" @@ -365,99 +334,69 @@ def CONTROL_REG : RegisterClass<"X86", [i64], 64, // that support 8-bit subreg operations. On x86-64, GR16_ABCD, GR32_ABCD, // and GR64_ABCD are classes for registers that support 8-bit h-register // operations. -def GR8_ABCD_L : RegisterClass<"X86", [i8], 8, [AL, CL, DL, BL]>; -def GR8_ABCD_H : RegisterClass<"X86", [i8], 8, [AH, CH, DH, BH]>; -def GR16_ABCD : RegisterClass<"X86", [i16], 16, [AX, CX, DX, BX]> { +def GR8_ABCD_L : RegisterClass<"X86", [i8], 8, (add AL, CL, DL, BL)>; +def GR8_ABCD_H : RegisterClass<"X86", [i8], 8, (add AH, CH, DH, BH)>; +def GR16_ABCD : RegisterClass<"X86", [i16], 16, (add AX, CX, DX, BX)> { let SubRegClasses = [(GR8_ABCD_L sub_8bit), (GR8_ABCD_H sub_8bit_hi)]; } -def GR32_ABCD : RegisterClass<"X86", [i32], 32, [EAX, ECX, EDX, EBX]> { +def GR32_ABCD : RegisterClass<"X86", [i32], 32, (add EAX, ECX, EDX, EBX)> { let SubRegClasses = [(GR8_ABCD_L sub_8bit), (GR8_ABCD_H sub_8bit_hi), (GR16_ABCD sub_16bit)]; } -def GR64_ABCD : RegisterClass<"X86", [i64], 64, [RAX, RCX, RDX, RBX]> { +def GR64_ABCD : RegisterClass<"X86", [i64], 64, (add RAX, RCX, RDX, RBX)> { let SubRegClasses = [(GR8_ABCD_L sub_8bit), (GR8_ABCD_H sub_8bit_hi), (GR16_ABCD sub_16bit), (GR32_ABCD sub_32bit)]; } -def GR32_TC : RegisterClass<"X86", [i32], 32, [EAX, ECX, EDX]> { +def GR32_TC : RegisterClass<"X86", [i32], 32, (add EAX, ECX, EDX)> { let SubRegClasses = [(GR8 sub_8bit, sub_8bit_hi), (GR16 sub_16bit)]; } -def GR64_TC : RegisterClass<"X86", [i64], 64, [RAX, RCX, RDX, RSI, RDI, - R8, R9, R11, RIP]> { +def GR64_TC : RegisterClass<"X86", [i64], 64, (add RAX, RCX, RDX, RSI, RDI, + R8, R9, R11, RIP)> { let SubRegClasses = [(GR8 sub_8bit, sub_8bit_hi), (GR16 sub_16bit), (GR32_TC sub_32bit)]; } -def GR64_TCW64 : RegisterClass<"X86", [i64], 64, [RAX, RCX, RDX, - R8, R9, R11]>; +def GR64_TCW64 : RegisterClass<"X86", [i64], 64, (add RAX, RCX, RDX, + R8, R9, R11)>; // GR8_NOREX - GR8 registers which do not require a REX prefix. def GR8_NOREX : RegisterClass<"X86", [i8], 8, - [AL, CL, DL, AH, CH, DH, BL, BH]> { - let MethodProtos = [{ - iterator allocation_order_begin(const MachineFunction &MF) const; - iterator allocation_order_end(const MachineFunction &MF) const; - }]; - let MethodBodies = [{ - // In 64-bit mode, it's not safe to blindly allocate H registers. - static const unsigned X86_GR8_NOREX_AO_64[] = { - X86::AL, X86::CL, X86::DL, X86::BL - }; - - GR8_NOREXClass::iterator - GR8_NOREXClass::allocation_order_begin(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const X86Subtarget &Subtarget = TM.getSubtarget<X86Subtarget>(); - if (Subtarget.is64Bit()) - return X86_GR8_NOREX_AO_64; - else - return begin(); - } - - GR8_NOREXClass::iterator - GR8_NOREXClass::allocation_order_end(const MachineFunction &MF) const { - const TargetMachine &TM = MF.getTarget(); - const X86Subtarget &Subtarget = TM.getSubtarget<X86Subtarget>(); - if (Subtarget.is64Bit()) - return array_endof(X86_GR8_NOREX_AO_64); - else - return end(); - } + (add AL, CL, DL, AH, CH, DH, BL, BH)> { + let AltOrders = [(sub GR8_NOREX, AH, BH, CH, DH)]; + let AltOrderSelect = [{ + return MF.getTarget().getSubtarget<X86Subtarget>().is64Bit(); }]; } // GR16_NOREX - GR16 registers which do not require a REX prefix. def GR16_NOREX : RegisterClass<"X86", [i16], 16, - [AX, CX, DX, SI, DI, BX, BP, SP]> { + (add AX, CX, DX, SI, DI, BX, BP, SP)> { let SubRegClasses = [(GR8_NOREX sub_8bit, sub_8bit_hi)]; } // GR32_NOREX - GR32 registers which do not require a REX prefix. def GR32_NOREX : RegisterClass<"X86", [i32], 32, - [EAX, ECX, EDX, ESI, EDI, EBX, EBP, ESP]> { + (add EAX, ECX, EDX, ESI, EDI, EBX, EBP, ESP)> { let SubRegClasses = [(GR8_NOREX sub_8bit, sub_8bit_hi), (GR16_NOREX sub_16bit)]; } // GR64_NOREX - GR64 registers which do not require a REX prefix. def GR64_NOREX : RegisterClass<"X86", [i64], 64, - [RAX, RCX, RDX, RSI, RDI, RBX, RBP, RSP, RIP]> { + (add RAX, RCX, RDX, RSI, RDI, RBX, RBP, RSP, RIP)> { let SubRegClasses = [(GR8_NOREX sub_8bit, sub_8bit_hi), (GR16_NOREX sub_16bit), (GR32_NOREX sub_32bit)]; } // GR32_NOSP - GR32 registers except ESP. -def GR32_NOSP : RegisterClass<"X86", [i32], 32, - [EAX, ECX, EDX, ESI, EDI, EBX, EBP, - R8D, R9D, R10D, R11D, R14D, R15D, R12D, R13D]> { +def GR32_NOSP : RegisterClass<"X86", [i32], 32, (sub GR32, ESP)> { let SubRegClasses = [(GR8 sub_8bit, sub_8bit_hi), (GR16 sub_16bit)]; } // GR64_NOSP - GR64 registers except RSP (and RIP). -def GR64_NOSP : RegisterClass<"X86", [i64], 64, - [RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, - RBX, R14, R15, R12, R13, RBP]> { +def GR64_NOSP : RegisterClass<"X86", [i64], 64, (sub GR64, RSP, RIP)> { let SubRegClasses = [(GR8 sub_8bit, sub_8bit_hi), (GR16 sub_16bit), (GR32_NOSP sub_32bit)]; @@ -466,36 +405,30 @@ def GR64_NOSP : RegisterClass<"X86", [i64], 64, // GR32_NOREX_NOSP - GR32 registers which do not require a REX prefix except // ESP. def GR32_NOREX_NOSP : RegisterClass<"X86", [i32], 32, - [EAX, ECX, EDX, ESI, EDI, EBX, EBP]> { + (and GR32_NOREX, GR32_NOSP)> { let SubRegClasses = [(GR8_NOREX sub_8bit, sub_8bit_hi), (GR16_NOREX sub_16bit)]; } // GR64_NOREX_NOSP - GR64_NOREX registers except RSP. def GR64_NOREX_NOSP : RegisterClass<"X86", [i64], 64, - [RAX, RCX, RDX, RSI, RDI, RBX, RBP]> { + (and GR64_NOREX, GR64_NOSP)> { let SubRegClasses = [(GR8_NOREX sub_8bit, sub_8bit_hi), (GR16_NOREX sub_16bit), (GR32_NOREX_NOSP sub_32bit)]; } // A class to support the 'A' assembler constraint: EAX then EDX. -def GR32_AD : RegisterClass<"X86", [i32], 32, [EAX, EDX]> { +def GR32_AD : RegisterClass<"X86", [i32], 32, (add EAX, EDX)> { let SubRegClasses = [(GR8_ABCD_L sub_8bit), (GR8_ABCD_H sub_8bit_hi), (GR16_ABCD sub_16bit)]; } // Scalar SSE2 floating point registers. -def FR32 : RegisterClass<"X86", [f32], 32, - [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, - XMM8, XMM9, XMM10, XMM11, - XMM12, XMM13, XMM14, XMM15]>; +def FR32 : RegisterClass<"X86", [f32], 32, (sequence "XMM%u", 0, 15)>; -def FR64 : RegisterClass<"X86", [f64], 64, - [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, - XMM8, XMM9, XMM10, XMM11, - XMM12, XMM13, XMM14, XMM15]>; +def FR64 : RegisterClass<"X86", [f64], 64, (add FR32)>; // FIXME: This sets up the floating point register files as though they are f64 @@ -504,37 +437,31 @@ def FR64 : RegisterClass<"X86", [f64], 64, // faster on common hardware. In reality, this should be controlled by a // command line option or something. -def RFP32 : RegisterClass<"X86",[f32], 32, [FP0, FP1, FP2, FP3, FP4, FP5, FP6]>; -def RFP64 : RegisterClass<"X86",[f64], 32, [FP0, FP1, FP2, FP3, FP4, FP5, FP6]>; -def RFP80 : RegisterClass<"X86",[f80], 32, [FP0, FP1, FP2, FP3, FP4, FP5, FP6]>; +def RFP32 : RegisterClass<"X86",[f32], 32, (sequence "FP%u", 0, 6)>; +def RFP64 : RegisterClass<"X86",[f64], 32, (add RFP32)>; +def RFP80 : RegisterClass<"X86",[f80], 32, (add RFP32)>; // Floating point stack registers (these are not allocatable by the // register allocator - the floating point stackifier is responsible // for transforming FPn allocations to STn registers) -def RST : RegisterClass<"X86", [f80, f64, f32], 32, - [ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7]> { +def RST : RegisterClass<"X86", [f80, f64, f32], 32, (sequence "ST%u", 0, 7)> { let isAllocatable = 0; } // Generic vector registers: VR64 and VR128. -def VR64: RegisterClass<"X86", [x86mmx], 64, - [MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7]>; -def VR128 : RegisterClass<"X86", [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64],128, - [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, - XMM8, XMM9, XMM10, XMM11, - XMM12, XMM13, XMM14, XMM15]> { +def VR64: RegisterClass<"X86", [x86mmx], 64, (sequence "MM%u", 0, 7)>; +def VR128 : RegisterClass<"X86", [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], + 128, (add FR32)> { let SubRegClasses = [(FR32 sub_ss), (FR64 sub_sd)]; } def VR256 : RegisterClass<"X86", [v32i8, v8i32, v4i64, v8f32, v4f64], 256, - [YMM0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7, - YMM8, YMM9, YMM10, YMM11, - YMM12, YMM13, YMM14, YMM15]> { + (sequence "YMM%u", 0, 15)> { let SubRegClasses = [(FR32 sub_ss), (FR64 sub_sd), (VR128 sub_xmm)]; } // Status flags registers. -def CCR : RegisterClass<"X86", [i32], 32, [EFLAGS]> { +def CCR : RegisterClass<"X86", [i32], 32, (add EFLAGS)> { let CopyCost = -1; // Don't allow copying of status registers. let isAllocatable = 0; } diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp index 481e821030b3..5e6c659e5393 100644 --- a/lib/Target/X86/X86Subtarget.cpp +++ b/lib/Target/X86/X86Subtarget.cpp @@ -7,21 +7,24 @@ // //===----------------------------------------------------------------------===// // -// This file implements the X86 specific subclass of TargetSubtarget. +// This file implements the X86 specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "subtarget" #include "X86Subtarget.h" #include "X86InstrInfo.h" -#include "X86GenSubtarget.inc" #include "llvm/GlobalValue.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Host.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" #include "llvm/ADT/SmallVector.h" + +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "X86GenSubtargetInfo.inc" + using namespace llvm; #if defined(_MSC_VER) @@ -154,7 +157,7 @@ const char *X86Subtarget::getBZeroEntry() const { /// IsLegalToCallImmediateAddr - Return true if the subtarget allows calls /// to immediate address. bool X86Subtarget::IsLegalToCallImmediateAddr(const TargetMachine &TM) const { - if (Is64Bit) + if (In64BitMode) return false; return isTargetELF() || TM.getRelocationModel() == Reloc::Static; } @@ -170,73 +173,6 @@ unsigned X86Subtarget::getSpecialAddressLatency() const { return 200; } -/// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in the -/// specified arguments. If we can't run cpuid on the host, return true. -static bool GetCpuIDAndInfo(unsigned value, unsigned *rEAX, - unsigned *rEBX, unsigned *rECX, unsigned *rEDX) { -#if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64) - #if defined(__GNUC__) - // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually. - asm ("movq\t%%rbx, %%rsi\n\t" - "cpuid\n\t" - "xchgq\t%%rbx, %%rsi\n\t" - : "=a" (*rEAX), - "=S" (*rEBX), - "=c" (*rECX), - "=d" (*rEDX) - : "a" (value)); - return false; - #elif defined(_MSC_VER) - int registers[4]; - __cpuid(registers, value); - *rEAX = registers[0]; - *rEBX = registers[1]; - *rECX = registers[2]; - *rEDX = registers[3]; - return false; - #endif -#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86) - #if defined(__GNUC__) - asm ("movl\t%%ebx, %%esi\n\t" - "cpuid\n\t" - "xchgl\t%%ebx, %%esi\n\t" - : "=a" (*rEAX), - "=S" (*rEBX), - "=c" (*rECX), - "=d" (*rEDX) - : "a" (value)); - return false; - #elif defined(_MSC_VER) - __asm { - mov eax,value - cpuid - mov esi,rEAX - mov dword ptr [esi],eax - mov esi,rEBX - mov dword ptr [esi],ebx - mov esi,rECX - mov dword ptr [esi],ecx - mov esi,rEDX - mov dword ptr [esi],edx - } - return false; - #endif -#endif - return true; -} - -static void DetectFamilyModel(unsigned EAX, unsigned &Family, unsigned &Model) { - Family = (EAX >> 8) & 0xf; // Bits 8 - 11 - Model = (EAX >> 4) & 0xf; // Bits 4 - 7 - if (Family == 6 || Family == 0xf) { - if (Family == 0xf) - // Examine extended family ID if family ID is F. - Family += (EAX >> 20) & 0xff; // Bits 20 - 27 - // Examine extended model ID if family ID is 6 or F. - Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19 - } -} - void X86Subtarget::AutoDetectSubtargetFeatures() { unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; union { @@ -244,50 +180,66 @@ void X86Subtarget::AutoDetectSubtargetFeatures() { char c[12]; } text; - if (GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1)) + if (X86_MC::GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1)) return; - GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX); + X86_MC::GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX); - if ((EDX >> 15) & 1) HasCMov = true; - if ((EDX >> 23) & 1) X86SSELevel = MMX; - if ((EDX >> 25) & 1) X86SSELevel = SSE1; - if ((EDX >> 26) & 1) X86SSELevel = SSE2; - if (ECX & 0x1) X86SSELevel = SSE3; - if ((ECX >> 9) & 1) X86SSELevel = SSSE3; - if ((ECX >> 19) & 1) X86SSELevel = SSE41; - if ((ECX >> 20) & 1) X86SSELevel = SSE42; + if ((EDX >> 15) & 1) HasCMov = true; ToggleFeature(X86::FeatureCMOV); + if ((EDX >> 23) & 1) X86SSELevel = MMX; ToggleFeature(X86::FeatureMMX); + if ((EDX >> 25) & 1) X86SSELevel = SSE1; ToggleFeature(X86::FeatureSSE1); + if ((EDX >> 26) & 1) X86SSELevel = SSE2; ToggleFeature(X86::FeatureSSE2); + if (ECX & 0x1) X86SSELevel = SSE3; ToggleFeature(X86::FeatureSSE3); + if ((ECX >> 9) & 1) X86SSELevel = SSSE3; ToggleFeature(X86::FeatureSSSE3); + if ((ECX >> 19) & 1) X86SSELevel = SSE41; ToggleFeature(X86::FeatureSSE41); + if ((ECX >> 20) & 1) X86SSELevel = SSE42; ToggleFeature(X86::FeatureSSE42); // FIXME: AVX codegen support is not ready. - //if ((ECX >> 28) & 1) { HasAVX = true; X86SSELevel = NoMMXSSE; } + //if ((ECX >> 28) & 1) { HasAVX = true; } ToggleFeature(X86::FeatureAVX); bool IsIntel = memcmp(text.c, "GenuineIntel", 12) == 0; bool IsAMD = !IsIntel && memcmp(text.c, "AuthenticAMD", 12) == 0; - HasCLMUL = IsIntel && ((ECX >> 1) & 0x1); - HasFMA3 = IsIntel && ((ECX >> 12) & 0x1); - HasPOPCNT = IsIntel && ((ECX >> 23) & 0x1); - HasAES = IsIntel && ((ECX >> 25) & 0x1); + HasCLMUL = IsIntel && ((ECX >> 1) & 0x1); ToggleFeature(X86::FeatureCLMUL); + HasFMA3 = IsIntel && ((ECX >> 12) & 0x1); ToggleFeature(X86::FeatureFMA3); + HasPOPCNT = IsIntel && ((ECX >> 23) & 0x1); ToggleFeature(X86::FeaturePOPCNT); + HasAES = IsIntel && ((ECX >> 25) & 0x1); ToggleFeature(X86::FeatureAES); if (IsIntel || IsAMD) { // Determine if bit test memory instructions are slow. unsigned Family = 0; unsigned Model = 0; - DetectFamilyModel(EAX, Family, Model); - IsBTMemSlow = IsAMD || (Family == 6 && Model >= 13); + X86_MC::DetectFamilyModel(EAX, Family, Model); + if (IsAMD || (Family == 6 && Model >= 13)) { + IsBTMemSlow = true; + ToggleFeature(X86::FeatureSlowBTMem); + } // If it's Nehalem, unaligned memory access is fast. - if (Family == 15 && Model == 26) + if (Family == 15 && Model == 26) { IsUAMemFast = true; + ToggleFeature(X86::FeatureFastUAMem); + } - GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); - HasX86_64 = (EDX >> 29) & 0x1; - HasSSE4A = IsAMD && ((ECX >> 6) & 0x1); - HasFMA4 = IsAMD && ((ECX >> 16) & 0x1); + X86_MC::GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); + if ((EDX >> 29) & 0x1) { + HasX86_64 = true; + ToggleFeature(X86::Feature64Bit); + } + if (IsAMD && ((ECX >> 6) & 0x1)) { + HasSSE4A = true; + ToggleFeature(X86::FeatureSSE4A); + } + if (IsAMD && ((ECX >> 16) & 0x1)) { + HasFMA4 = true; + ToggleFeature(X86::FeatureFMA4); + } } } -X86Subtarget::X86Subtarget(const std::string &TT, const std::string &FS, - bool is64Bit) - : PICStyle(PICStyles::None) +X86Subtarget::X86Subtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, + unsigned StackAlignOverride, bool is64Bit) + : X86GenSubtargetInfo(TT, CPU, FS) + , PICStyle(PICStyles::None) , X86SSELevel(NoMMXSSE) , X863DNowLevel(NoThreeDNow) , HasCMov(false) @@ -306,73 +258,66 @@ X86Subtarget::X86Subtarget(const std::string &TT, const std::string &FS, // FIXME: this is a known good value for Yonah. How about others? , MaxInlineSizeThreshold(128) , TargetTriple(TT) - , Is64Bit(is64Bit) { - - // default to hard float ABI - if (FloatABIType == FloatABI::Default) - FloatABIType = FloatABI::Hard; - + , In64BitMode(is64Bit) { // Determine default and user specified characteristics - if (!FS.empty()) { + if (!FS.empty() || !CPU.empty()) { + std::string CPUName = CPU; + if (CPUName.empty()) { +#if defined (__x86_64__) || defined(__i386__) + CPUName = sys::getHostCPUName(); +#else + CPUName = "generic"; +#endif + } + + // Make sure 64-bit features are available in 64-bit mode. (But make sure + // SSE2 can be turned off explicitly.) + std::string FullFS = FS; + if (In64BitMode) { + if (!FullFS.empty()) + FullFS = "+64bit,+sse2," + FullFS; + else + FullFS = "+64bit,+sse2"; + } + // If feature string is not empty, parse features string. - std::string CPU = sys::getHostCPUName(); - ParseSubtargetFeatures(FS, CPU); - // All X86-64 CPUs also have SSE2, however user might request no SSE via - // -mattr, so don't force SSELevel here. - if (HasAVX) - X86SSELevel = NoMMXSSE; + ParseSubtargetFeatures(CPUName, FullFS); } else { // Otherwise, use CPUID to auto-detect feature set. AutoDetectSubtargetFeatures(); - // Make sure SSE2 is enabled; it is available on all X86-64 CPUs. - if (Is64Bit && !HasAVX && X86SSELevel < SSE2) - X86SSELevel = SSE2; - } - // If requesting codegen for X86-64, make sure that 64-bit features - // are enabled. - if (Is64Bit) { - HasX86_64 = true; + // Make sure 64-bit features are available in 64-bit mode. + if (In64BitMode) { + HasX86_64 = true; ToggleFeature(X86::Feature64Bit); + HasCMov = true; ToggleFeature(X86::FeatureCMOV); - // All 64-bit cpus have cmov support. - HasCMov = true; + if (!HasAVX && X86SSELevel < SSE2) { + X86SSELevel = SSE2; + ToggleFeature(X86::FeatureSSE1); + ToggleFeature(X86::FeatureSSE2); + } + } } + + // It's important to keep the MCSubtargetInfo feature bits in sync with + // target data structure which is shared with MC code emitter, etc. + if (In64BitMode) + ToggleFeature(X86::Mode64Bit); + + if (HasAVX) + X86SSELevel = NoMMXSSE; DEBUG(dbgs() << "Subtarget features: SSELevel " << X86SSELevel << ", 3DNowLevel " << X863DNowLevel << ", 64bit " << HasX86_64 << "\n"); - assert((!Is64Bit || HasX86_64) && + assert((!In64BitMode || HasX86_64) && "64-bit code requested on a subtarget that doesn't support it!"); // Stack alignment is 16 bytes on Darwin, FreeBSD, Linux and Solaris (both // 32 and 64 bit) and for all 64-bit targets. - if (isTargetDarwin() || isTargetFreeBSD() || isTargetLinux() || - isTargetSolaris() || Is64Bit) + if (StackAlignOverride) + stackAlignment = StackAlignOverride; + else if (isTargetDarwin() || isTargetFreeBSD() || isTargetLinux() || + isTargetSolaris() || In64BitMode) stackAlignment = 16; - - if (StackAlignment) - stackAlignment = StackAlignment; -} - -/// IsCalleePop - Determines whether the callee is required to pop its -/// own arguments. Callee pop is necessary to support tail calls. -bool X86Subtarget::IsCalleePop(bool IsVarArg, - CallingConv::ID CallingConv) const { - if (IsVarArg) - return false; - - switch (CallingConv) { - default: - return false; - case CallingConv::X86_StdCall: - return !is64Bit(); - case CallingConv::X86_FastCall: - return !is64Bit(); - case CallingConv::X86_ThisCall: - return !is64Bit(); - case CallingConv::Fast: - return GuaranteedTailCallOpt; - case CallingConv::GHC: - return GuaranteedTailCallOpt; - } } diff --git a/lib/Target/X86/X86Subtarget.h b/lib/Target/X86/X86Subtarget.h index 286a7982a699..6d22027b7aa8 100644 --- a/lib/Target/X86/X86Subtarget.h +++ b/lib/Target/X86/X86Subtarget.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file declares the X86 specific subclass of TargetSubtarget. +// This file declares the X86 specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// @@ -15,12 +15,16 @@ #define X86SUBTARGET_H #include "llvm/ADT/Triple.h" -#include "llvm/Target/TargetSubtarget.h" +#include "llvm/Target/TargetSubtargetInfo.h" #include "llvm/CallingConv.h" #include <string> +#define GET_SUBTARGETINFO_HEADER +#include "X86GenSubtargetInfo.inc" + namespace llvm { class GlobalValue; +class StringRef; class TargetMachine; /// PICStyles - The X86 backend supports a number of different styles of PIC. @@ -35,7 +39,7 @@ enum Style { }; } -class X86Subtarget : public TargetSubtarget { +class X86Subtarget : public X86GenSubtargetInfo { protected: enum X86SSEEnum { NoMMXSSE, MMX, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42 @@ -108,16 +112,17 @@ protected: Triple TargetTriple; private: - /// Is64Bit - True if the processor supports 64-bit instructions and - /// pointer size is 64 bit. - bool Is64Bit; + /// In64BitMode - True if compiling for 64-bit, false for 32-bit. + bool In64BitMode; public: /// This constructor initializes the data members to match that /// of the specified triple. /// - X86Subtarget(const std::string &TT, const std::string &FS, bool is64Bit); + X86Subtarget(const std::string &TT, const std::string &CPU, + const std::string &FS, + unsigned StackAlignOverride, bool is64Bit); /// getStackAlignment - Returns the minimum alignment known to hold of the /// stack frame on entry to the function and which must be maintained by every @@ -130,14 +135,13 @@ public: /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(StringRef CPU, StringRef FS); /// AutoDetectSubtargetFeatures - Auto-detect CPU features using CPUID /// instruction. void AutoDetectSubtargetFeatures(); - bool is64Bit() const { return Is64Bit; } + bool is64Bit() const { return In64BitMode; } PICStyles::Style getPICStyle() const { return PICStyle; } void setPICStyle(PICStyles::Style Style) { PICStyle = Style; } @@ -195,7 +199,7 @@ public: } bool isTargetWin64() const { - return Is64Bit && (isTargetMingw() || isTargetWindows()); + return In64BitMode && (isTargetMingw() || isTargetWindows()); } bool isTargetEnvMacho() const { @@ -203,7 +207,7 @@ public: } bool isTargetWin32() const { - return !Is64Bit && (isTargetMingw() || isTargetWindows()); + return !In64BitMode && (isTargetMingw() || isTargetWindows()); } bool isPICStyleSet() const { return PICStyle != PICStyles::None; } @@ -248,9 +252,6 @@ public: /// indicating the number of scheduling cycles of backscheduling that /// should be attempted. unsigned getSpecialAddressLatency() const; - - /// IsCalleePop - Test whether a function should pop its own arguments. - bool IsCalleePop(bool isVarArg, CallingConv::ID CallConv) const; }; } // End llvm namespace diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index 74833291dc7a..9cab0e089098 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -#include "X86MCAsmInfo.h" #include "X86TargetMachine.h" #include "X86.h" #include "llvm/PassManager.h" @@ -24,22 +23,6 @@ #include "llvm/Target/TargetRegistry.h" using namespace llvm; -static MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) { - Triple TheTriple(TT); - - if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO) { - if (TheTriple.getArch() == Triple::x86_64) - return new X86_64MCAsmInfoDarwin(TheTriple); - else - return new X86MCAsmInfoDarwin(TheTriple); - } - - if (TheTriple.isOSWindows()) - return new X86MCAsmInfoCOFF(TheTriple); - - return new X86ELFMCAsmInfo(TheTriple); -} - static MCStreamer *createMCStreamer(const Target &T, const std::string &TT, MCContext &Ctx, TargetAsmBackend &TAB, raw_ostream &_OS, @@ -62,15 +45,11 @@ extern "C" void LLVMInitializeX86Target() { RegisterTargetMachine<X86_32TargetMachine> X(TheX86_32Target); RegisterTargetMachine<X86_64TargetMachine> Y(TheX86_64Target); - // Register the target asm info. - RegisterAsmInfoFn A(TheX86_32Target, createMCAsmInfo); - RegisterAsmInfoFn B(TheX86_64Target, createMCAsmInfo); - // Register the code emitter. TargetRegistry::RegisterCodeEmitter(TheX86_32Target, - createX86_32MCCodeEmitter); + createX86MCCodeEmitter); TargetRegistry::RegisterCodeEmitter(TheX86_64Target, - createX86_64MCCodeEmitter); + createX86MCCodeEmitter); // Register the asm backend. TargetRegistry::RegisterAsmBackend(TheX86_32Target, @@ -87,8 +66,9 @@ extern "C" void LLVMInitializeX86Target() { X86_32TargetMachine::X86_32TargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) - : X86TargetMachine(T, TT, FS, false), + : X86TargetMachine(T, TT, CPU, FS, false), DataLayout(getSubtargetImpl()->isTargetDarwin() ? "e-p:32:32-f64:32:64-i64:32:64-f80:128:128-f128:128:128-n8:16:32" : (getSubtargetImpl()->isTargetCygMing() || @@ -103,8 +83,9 @@ X86_32TargetMachine::X86_32TargetMachine(const Target &T, const std::string &TT, X86_64TargetMachine::X86_64TargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) - : X86TargetMachine(T, TT, FS, true), + : X86TargetMachine(T, TT, CPU, FS, true), DataLayout("e-p:64:64-s:64-f64:64:64-i64:64:64-f80:128:128-f128:128:128-n8:16:32:64"), InstrInfo(*this), TSInfo(*this), @@ -115,9 +96,10 @@ X86_64TargetMachine::X86_64TargetMachine(const Target &T, const std::string &TT, /// X86TargetMachine ctor - Create an X86 target. /// X86TargetMachine::X86TargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS, bool is64Bit) - : LLVMTargetMachine(T, TT), - Subtarget(TT, FS, is64Bit), + : LLVMTargetMachine(T, TT, CPU, FS), + Subtarget(TT, CPU, FS, StackAlignmentOverride, is64Bit), FrameLowering(*this, Subtarget), ELFWriterInfo(is64Bit, true) { DefRelocModel = getRelocationModel(); @@ -182,6 +164,10 @@ X86TargetMachine::X86TargetMachine(const Target &T, const std::string &TT, // Finally, if we have "none" as our PIC style, force to static mode. if (Subtarget.getPICStyle() == PICStyles::None) setRelocationModel(Reloc::Static); + + // default to hard float ABI + if (FloatABIType == FloatABI::Default) + FloatABIType = FloatABI::Hard; } //===----------------------------------------------------------------------===// diff --git a/lib/Target/X86/X86TargetMachine.h b/lib/Target/X86/X86TargetMachine.h index 597392251e6a..885334a365fe 100644 --- a/lib/Target/X86/X86TargetMachine.h +++ b/lib/Target/X86/X86TargetMachine.h @@ -43,7 +43,8 @@ private: public: X86TargetMachine(const Target &T, const std::string &TT, - const std::string &FS, bool is64Bit); + const std::string &CPU, const std::string &FS, + bool is64Bit); virtual const X86InstrInfo *getInstrInfo() const { llvm_unreachable("getInstrInfo not implemented"); @@ -87,7 +88,7 @@ class X86_32TargetMachine : public X86TargetMachine { X86JITInfo JITInfo; public: X86_32TargetMachine(const Target &T, const std::string &M, - const std::string &FS); + const std::string &CPU, const std::string &FS); virtual const TargetData *getTargetData() const { return &DataLayout; } virtual const X86TargetLowering *getTargetLowering() const { return &TLInfo; @@ -113,7 +114,7 @@ class X86_64TargetMachine : public X86TargetMachine { X86JITInfo JITInfo; public: X86_64TargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); virtual const TargetData *getTargetData() const { return &DataLayout; } virtual const X86TargetLowering *getTargetLowering() const { return &TLInfo; diff --git a/lib/Target/XCore/CMakeLists.txt b/lib/Target/XCore/CMakeLists.txt index 9093de691582..a1d73c6b4f99 100644 --- a/lib/Target/XCore/CMakeLists.txt +++ b/lib/Target/XCore/CMakeLists.txt @@ -1,14 +1,11 @@ set(LLVM_TARGET_DEFINITIONS XCore.td) -tablegen(XCoreGenRegisterInfo.h.inc -gen-register-desc-header) -tablegen(XCoreGenRegisterNames.inc -gen-register-enums) -tablegen(XCoreGenRegisterInfo.inc -gen-register-desc) -tablegen(XCoreGenInstrNames.inc -gen-instr-enums) -tablegen(XCoreGenInstrInfo.inc -gen-instr-desc) +tablegen(XCoreGenRegisterInfo.inc -gen-register-info) +tablegen(XCoreGenInstrInfo.inc -gen-instr-info) tablegen(XCoreGenAsmWriter.inc -gen-asm-writer) tablegen(XCoreGenDAGISel.inc -gen-dag-isel) tablegen(XCoreGenCallingConv.inc -gen-callingconv) -tablegen(XCoreGenSubtarget.inc -gen-subtarget) +tablegen(XCoreGenSubtargetInfo.inc -gen-subtarget) add_llvm_target(XCoreCodeGen XCoreAsmPrinter.cpp @@ -16,7 +13,6 @@ add_llvm_target(XCoreCodeGen XCoreInstrInfo.cpp XCoreISelDAGToDAG.cpp XCoreISelLowering.cpp - XCoreMCAsmInfo.cpp XCoreRegisterInfo.cpp XCoreSubtarget.cpp XCoreTargetMachine.cpp @@ -25,3 +21,4 @@ add_llvm_target(XCoreCodeGen ) add_subdirectory(TargetInfo) +add_subdirectory(MCTargetDesc) diff --git a/lib/Target/XCore/MCTargetDesc/CMakeLists.txt b/lib/Target/XCore/MCTargetDesc/CMakeLists.txt new file mode 100644 index 000000000000..c3b3dc9e647d --- /dev/null +++ b/lib/Target/XCore/MCTargetDesc/CMakeLists.txt @@ -0,0 +1,7 @@ +add_llvm_library(LLVMXCoreDesc + XCoreMCTargetDesc.cpp + XCoreMCAsmInfo.cpp + ) + +# Hack: we need to include 'main' target directory to grab private headers +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BINARY_DIR}/..) diff --git a/lib/Target/XCore/MCTargetDesc/Makefile b/lib/Target/XCore/MCTargetDesc/Makefile new file mode 100644 index 000000000000..de61543bfe9c --- /dev/null +++ b/lib/Target/XCore/MCTargetDesc/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/XCore/TargetDesc/Makefile ----------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +LIBRARYNAME = LLVMXCoreDesc + +# Hack: we need to include 'main' target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/XCore/XCoreMCAsmInfo.cpp b/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp index 42ab1b31d57a..42ab1b31d57a 100644 --- a/lib/Target/XCore/XCoreMCAsmInfo.cpp +++ b/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp diff --git a/lib/Target/XCore/XCoreMCAsmInfo.h b/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.h index 840392263881..840392263881 100644 --- a/lib/Target/XCore/XCoreMCAsmInfo.h +++ b/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.h diff --git a/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp b/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp new file mode 100644 index 000000000000..939d97c9d87c --- /dev/null +++ b/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp @@ -0,0 +1,56 @@ +//===-- XCoreMCTargetDesc.cpp - XCore Target Descriptions -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides XCore specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#include "XCoreMCTargetDesc.h" +#include "XCoreMCAsmInfo.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Target/TargetRegistry.h" + +#define GET_INSTRINFO_MC_DESC +#include "XCoreGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_MC_DESC +#include "XCoreGenSubtargetInfo.inc" + +#define GET_REGINFO_MC_DESC +#include "XCoreGenRegisterInfo.inc" + +using namespace llvm; + +static MCInstrInfo *createXCoreMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitXCoreMCInstrInfo(X); + return X; +} + +extern "C" void LLVMInitializeXCoreMCInstrInfo() { + TargetRegistry::RegisterMCInstrInfo(TheXCoreTarget, createXCoreMCInstrInfo); +} + +static MCSubtargetInfo *createXCoreMCSubtargetInfo(StringRef TT, StringRef CPU, + StringRef FS) { + MCSubtargetInfo *X = new MCSubtargetInfo(); + InitXCoreMCSubtargetInfo(X, TT, CPU, FS); + return X; +} + +extern "C" void LLVMInitializeXCoreMCSubtargetInfo() { + TargetRegistry::RegisterMCSubtargetInfo(TheXCoreTarget, + createXCoreMCSubtargetInfo); +} + +extern "C" void LLVMInitializeXCoreMCAsmInfo() { + RegisterMCAsmInfo<XCoreMCAsmInfo> X(TheXCoreTarget); +} diff --git a/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.h b/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.h new file mode 100644 index 000000000000..3cfc3764a62c --- /dev/null +++ b/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.h @@ -0,0 +1,40 @@ +//===-- XCoreMCTargetDesc.h - XCore Target Descriptions ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides XCore specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#ifndef XCOREMCTARGETDESC_H +#define XCOREMCTARGETDESC_H + +namespace llvm { +class MCSubtargetInfo; +class Target; +class StringRef; + +extern Target TheXCoreTarget; + +} // End llvm namespace + +// Defines symbolic names for XCore registers. This defines a mapping from +// register name to register number. +// +#define GET_REGINFO_ENUM +#include "XCoreGenRegisterInfo.inc" + +// Defines symbolic names for the XCore instructions. +// +#define GET_INSTRINFO_ENUM +#include "XCoreGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "XCoreGenSubtargetInfo.inc" + +#endif diff --git a/lib/Target/XCore/Makefile b/lib/Target/XCore/Makefile index 6c1ef886031b..b823c4ed37e9 100644 --- a/lib/Target/XCore/Makefile +++ b/lib/Target/XCore/Makefile @@ -12,13 +12,12 @@ LIBRARYNAME = LLVMXCoreCodeGen TARGET = XCore # Make sure that tblgen is run, first thing. -BUILT_SOURCES = XCoreGenRegisterInfo.h.inc XCoreGenRegisterNames.inc \ - XCoreGenRegisterInfo.inc XCoreGenInstrNames.inc \ - XCoreGenInstrInfo.inc XCoreGenAsmWriter.inc \ +BUILT_SOURCES = XCoreGenRegisterInfo.inc XCoreGenInstrInfo.inc \ + XCoreGenAsmWriter.inc \ XCoreGenDAGISel.inc XCoreGenCallingConv.inc \ - XCoreGenSubtarget.inc + XCoreGenSubtargetInfo.inc -DIRS = TargetInfo +DIRS = TargetInfo MCTargetDesc include $(LEVEL)/Makefile.common diff --git a/lib/Target/XCore/XCore.h b/lib/Target/XCore/XCore.h index 8937fbe123c6..b8fb0cac319b 100644 --- a/lib/Target/XCore/XCore.h +++ b/lib/Target/XCore/XCore.h @@ -15,6 +15,7 @@ #ifndef TARGET_XCORE_H #define TARGET_XCORE_H +#include "MCTargetDesc/XCoreMCTargetDesc.h" #include "llvm/Target/TargetMachine.h" namespace llvm { @@ -25,17 +26,6 @@ namespace llvm { FunctionPass *createXCoreISelDag(XCoreTargetMachine &TM); - extern Target TheXCoreTarget; - } // end namespace llvm; -// Defines symbolic names for XCore registers. This defines a mapping from -// register name to register number. -// -#include "XCoreGenRegisterNames.inc" - -// Defines symbolic names for the XCore instructions. -// -#include "XCoreGenInstrNames.inc" - #endif diff --git a/lib/Target/XCore/XCoreAsmPrinter.cpp b/lib/Target/XCore/XCoreAsmPrinter.cpp index 8f06dd32662f..1a43714d63b9 100644 --- a/lib/Target/XCore/XCoreAsmPrinter.cpp +++ b/lib/Target/XCore/XCoreAsmPrinter.cpp @@ -16,7 +16,6 @@ #include "XCore.h" #include "XCoreInstrInfo.h" #include "XCoreSubtarget.h" -#include "XCoreMCAsmInfo.h" #include "XCoreTargetMachine.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" @@ -27,6 +26,7 @@ #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Target/Mangler.h" @@ -114,7 +114,7 @@ void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { MCSymbol *GVSym = Mang->getSymbol(GV); - Constant *C = GV->getInitializer(); + const Constant *C = GV->getInitializer(); unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType()); // Mark the start of the global diff --git a/lib/Target/XCore/XCoreISelLowering.cpp b/lib/Target/XCore/XCoreISelLowering.cpp index 8cabbbf16c35..6d040e052659 100644 --- a/lib/Target/XCore/XCoreISelLowering.cpp +++ b/lib/Target/XCore/XCoreISelLowering.cpp @@ -1591,21 +1591,18 @@ XCoreTargetLowering::isLegalAddressingMode(const AddrMode &AM, // XCore Inline Assembly Support //===----------------------------------------------------------------------===// -std::vector<unsigned> XCoreTargetLowering:: -getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const -{ - if (Constraint.size() != 1) - return std::vector<unsigned>(); - - switch (Constraint[0]) { +std::pair<unsigned, const TargetRegisterClass*> +XCoreTargetLowering:: +getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const { + if (Constraint.size() == 1) { + switch (Constraint[0]) { default : break; case 'r': - return make_vector<unsigned>(XCore::R0, XCore::R1, XCore::R2, - XCore::R3, XCore::R4, XCore::R5, - XCore::R6, XCore::R7, XCore::R8, - XCore::R9, XCore::R10, XCore::R11, 0); - break; + return std::make_pair(0U, XCore::GRRegsRegisterClass); + } } - return std::vector<unsigned>(); + // Use the default implementation in TargetLowering to convert the register + // constraint into a member of a register class. + return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); } diff --git a/lib/Target/XCore/XCoreISelLowering.h b/lib/Target/XCore/XCoreISelLowering.h index a8d67d4ad21e..9c803bef6dd2 100644 --- a/lib/Target/XCore/XCoreISelLowering.h +++ b/lib/Target/XCore/XCoreISelLowering.h @@ -148,9 +148,9 @@ namespace llvm { SDValue LowerTRAMPOLINE(SDValue Op, SelectionDAG &DAG) const; // Inline asm support - std::vector<unsigned> - getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const; + std::pair<unsigned, const TargetRegisterClass*> + getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const; // Expand specifics SDValue TryExpandADDWithMul(SDNode *Op, SelectionDAG &DAG) const; diff --git a/lib/Target/XCore/XCoreInstrInfo.cpp b/lib/Target/XCore/XCoreInstrInfo.cpp index 9cb6a7d17b5e..f90481f3fbc9 100644 --- a/lib/Target/XCore/XCoreInstrInfo.cpp +++ b/lib/Target/XCore/XCoreInstrInfo.cpp @@ -18,11 +18,14 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineLocation.h" -#include "XCoreGenInstrInfo.inc" +#include "llvm/Target/TargetRegistry.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#define GET_INSTRINFO_CTOR +#include "XCoreGenInstrInfo.inc" + namespace llvm { namespace XCore { @@ -38,7 +41,7 @@ namespace XCore { using namespace llvm; XCoreInstrInfo::XCoreInstrInfo() - : TargetInstrInfoImpl(XCoreInsts, array_lengthof(XCoreInsts)), + : XCoreGenInstrInfo(XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP), RI(*this) { } diff --git a/lib/Target/XCore/XCoreInstrInfo.h b/lib/Target/XCore/XCoreInstrInfo.h index 977fe8dd550a..840b1e163652 100644 --- a/lib/Target/XCore/XCoreInstrInfo.h +++ b/lib/Target/XCore/XCoreInstrInfo.h @@ -17,9 +17,12 @@ #include "llvm/Target/TargetInstrInfo.h" #include "XCoreRegisterInfo.h" +#define GET_INSTRINFO_HEADER +#include "XCoreGenInstrInfo.inc" + namespace llvm { -class XCoreInstrInfo : public TargetInstrInfoImpl { +class XCoreInstrInfo : public XCoreGenInstrInfo { const XCoreRegisterInfo RI; public: XCoreInstrInfo(); diff --git a/lib/Target/XCore/XCoreRegisterInfo.cpp b/lib/Target/XCore/XCoreRegisterInfo.cpp index 46c9e57c1af5..357a4a083582 100644 --- a/lib/Target/XCore/XCoreRegisterInfo.cpp +++ b/lib/Target/XCore/XCoreRegisterInfo.cpp @@ -33,11 +33,13 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#define GET_REGINFO_TARGET_DESC +#include "XCoreGenRegisterInfo.inc" + using namespace llvm; XCoreRegisterInfo::XCoreRegisterInfo(const TargetInstrInfo &tii) - : XCoreGenRegisterInfo(XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP), - TII(tii) { + : XCoreGenRegisterInfo(), TII(tii) { } // helper functions @@ -193,7 +195,16 @@ XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, #endif Offset += StackSize; - + + unsigned FrameReg = getFrameRegister(MF); + + // Special handling of DBG_VALUE instructions. + if (MI.isDebugValue()) { + MI.getOperand(i).ChangeToRegister(FrameReg, false /*isDef*/); + MI.getOperand(i+1).ChangeToImmediate(Offset); + return; + } + // fold constant into offset. Offset += MI.getOperand(i + 1).getImm(); MI.getOperand(i + 1).ChangeToImmediate(0); @@ -205,7 +216,7 @@ XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, Offset/=4; bool FP = TFI->hasFP(MF); - + unsigned Reg = MI.getOperand(0).getReg(); bool isKill = MI.getOpcode() == XCore::STWFI && MI.getOperand(0).isKill(); @@ -216,7 +227,6 @@ XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, if (FP) { bool isUs = isImmUs(Offset); - unsigned FramePtr = XCore::R10; if (!isUs) { if (!RS) @@ -228,18 +238,18 @@ XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, switch (MI.getOpcode()) { case XCore::LDWFI: BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg) - .addReg(FramePtr) + .addReg(FrameReg) .addReg(ScratchReg, RegState::Kill); break; case XCore::STWFI: BuildMI(MBB, II, dl, TII.get(XCore::STW_3r)) .addReg(Reg, getKillRegState(isKill)) - .addReg(FramePtr) + .addReg(FrameReg) .addReg(ScratchReg, RegState::Kill); break; case XCore::LDAWFI: BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg) - .addReg(FramePtr) + .addReg(FrameReg) .addReg(ScratchReg, RegState::Kill); break; default: @@ -249,18 +259,18 @@ XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, switch (MI.getOpcode()) { case XCore::LDWFI: BuildMI(MBB, II, dl, TII.get(XCore::LDW_2rus), Reg) - .addReg(FramePtr) + .addReg(FrameReg) .addImm(Offset); break; case XCore::STWFI: BuildMI(MBB, II, dl, TII.get(XCore::STW_2rus)) .addReg(Reg, getKillRegState(isKill)) - .addReg(FramePtr) + .addReg(FrameReg) .addImm(Offset); break; case XCore::LDAWFI: BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l2rus), Reg) - .addReg(FramePtr) + .addReg(FrameReg) .addImm(Offset); break; default: @@ -328,6 +338,3 @@ unsigned XCoreRegisterInfo::getFrameRegister(const MachineFunction &MF) const { unsigned XCoreRegisterInfo::getRARegister() const { return XCore::LR; } - -#include "XCoreGenRegisterInfo.inc" - diff --git a/lib/Target/XCore/XCoreRegisterInfo.h b/lib/Target/XCore/XCoreRegisterInfo.h index 7a9bc9fb8705..801d9eba2171 100644 --- a/lib/Target/XCore/XCoreRegisterInfo.h +++ b/lib/Target/XCore/XCoreRegisterInfo.h @@ -15,7 +15,9 @@ #define XCOREREGISTERINFO_H #include "llvm/Target/TargetRegisterInfo.h" -#include "XCoreGenRegisterInfo.h.inc" + +#define GET_REGINFO_HEADER +#include "XCoreGenRegisterInfo.inc" namespace llvm { diff --git a/lib/Target/XCore/XCoreRegisterInfo.td b/lib/Target/XCore/XCoreRegisterInfo.td index 09510976dd06..c3542304a4ec 100644 --- a/lib/Target/XCore/XCoreRegisterInfo.td +++ b/lib/Target/XCore/XCoreRegisterInfo.td @@ -44,13 +44,13 @@ def LR : Ri<15, "lr">, DwarfRegNum<[15]>; // def GRRegs : RegisterClass<"XCore", [i32], 32, // Return values and arguments - [R0, R1, R2, R3, + (add R0, R1, R2, R3, // Not preserved across procedure calls R11, // Callee save - R4, R5, R6, R7, R8, R9, R10]>; + R4, R5, R6, R7, R8, R9, R10)>; // Reserved -def RRegs : RegisterClass<"XCore", [i32], 32, [CP, DP, SP, LR]> { +def RRegs : RegisterClass<"XCore", [i32], 32, (add CP, DP, SP, LR)> { let isAllocatable = 0; } diff --git a/lib/Target/XCore/XCoreSubtarget.cpp b/lib/Target/XCore/XCoreSubtarget.cpp index 78a6fa5b2edb..ad069bf138a7 100644 --- a/lib/Target/XCore/XCoreSubtarget.cpp +++ b/lib/Target/XCore/XCoreSubtarget.cpp @@ -7,14 +7,22 @@ // //===----------------------------------------------------------------------===// // -// This file implements the XCore specific subclass of TargetSubtarget. +// This file implements the XCore specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #include "XCoreSubtarget.h" #include "XCore.h" +#include "llvm/Target/TargetRegistry.h" + +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "XCoreGenSubtargetInfo.inc" + using namespace llvm; -XCoreSubtarget::XCoreSubtarget(const std::string &TT, const std::string &FS) +XCoreSubtarget::XCoreSubtarget(const std::string &TT, + const std::string &CPU, const std::string &FS) + : XCoreGenSubtargetInfo(TT, CPU, FS) { } diff --git a/lib/Target/XCore/XCoreSubtarget.h b/lib/Target/XCore/XCoreSubtarget.h index f8be3ec86189..7b29fa236710 100644 --- a/lib/Target/XCore/XCoreSubtarget.h +++ b/lib/Target/XCore/XCoreSubtarget.h @@ -7,32 +7,35 @@ // //===----------------------------------------------------------------------===// // -// This file declares the XCore specific subclass of TargetSubtarget. +// This file declares the XCore specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #ifndef XCORESUBTARGET_H #define XCORESUBTARGET_H -#include "llvm/Target/TargetSubtarget.h" +#include "llvm/Target/TargetSubtargetInfo.h" #include "llvm/Target/TargetMachine.h" - #include <string> +#define GET_SUBTARGETINFO_HEADER +#include "XCoreGenSubtargetInfo.inc" + namespace llvm { +class StringRef; -class XCoreSubtarget : public TargetSubtarget { +class XCoreSubtarget : public XCoreGenSubtargetInfo { public: /// This constructor initializes the data members to match that /// of the specified triple. /// - XCoreSubtarget(const std::string &TT, const std::string &FS); + XCoreSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - std::string ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + void ParseSubtargetFeatures(StringRef CPU, StringRef FS); }; } // End llvm namespace diff --git a/lib/Target/XCore/XCoreTargetMachine.cpp b/lib/Target/XCore/XCoreTargetMachine.cpp index 30da2c896c0f..342966ae5c86 100644 --- a/lib/Target/XCore/XCoreTargetMachine.cpp +++ b/lib/Target/XCore/XCoreTargetMachine.cpp @@ -10,7 +10,6 @@ // //===----------------------------------------------------------------------===// -#include "XCoreMCAsmInfo.h" #include "XCoreTargetMachine.h" #include "XCore.h" #include "llvm/Module.h" @@ -21,9 +20,10 @@ using namespace llvm; /// XCoreTargetMachine ctor - Create an ILP32 architecture model /// XCoreTargetMachine::XCoreTargetMachine(const Target &T, const std::string &TT, + const std::string &CPU, const std::string &FS) - : LLVMTargetMachine(T, TT), - Subtarget(TT, FS), + : LLVMTargetMachine(T, TT, CPU, FS), + Subtarget(TT, CPU, FS), DataLayout("e-p:32:32:32-a0:0:32-f32:32:32-f64:32:32-i1:8:32-i8:8:32-" "i16:16:32-i32:32:32-i64:32:32-n32"), InstrInfo(), @@ -41,5 +41,4 @@ bool XCoreTargetMachine::addInstSelector(PassManagerBase &PM, // Force static initialization. extern "C" void LLVMInitializeXCoreTarget() { RegisterTargetMachine<XCoreTargetMachine> X(TheXCoreTarget); - RegisterAsmInfo<XCoreMCAsmInfo> Y(TheXCoreTarget); } diff --git a/lib/Target/XCore/XCoreTargetMachine.h b/lib/Target/XCore/XCoreTargetMachine.h index 24daadcb6bf4..6235ac3a6a1a 100644 --- a/lib/Target/XCore/XCoreTargetMachine.h +++ b/lib/Target/XCore/XCoreTargetMachine.h @@ -33,7 +33,7 @@ class XCoreTargetMachine : public LLVMTargetMachine { XCoreSelectionDAGInfo TSInfo; public: XCoreTargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &CPU, const std::string &FS); virtual const XCoreInstrInfo *getInstrInfo() const { return &InstrInfo; } virtual const XCoreFrameLowering *getFrameLowering() const { |