diff options
Diffstat (limited to 'lib/Target')
279 files changed, 5085 insertions, 2895 deletions
diff --git a/lib/Target/ARM/ARM.h b/lib/Target/ARM/ARM.h index 8f77b04..08dc340 100644 --- a/lib/Target/ARM/ARM.h +++ b/lib/Target/ARM/ARM.h @@ -16,6 +16,7 @@ #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" @@ -23,19 +24,21 @@ namespace llvm { +class ARMAsmPrinter; class ARMBaseTargetMachine; class FunctionPass; class JITCodeEmitter; -class formatted_raw_ostream; +class MachineInstr; class MCCodeEmitter; +class MCInst; +class MCInstrInfo; class MCObjectWriter; +class MCSubtargetInfo; class TargetAsmBackend; -class MachineInstr; -class ARMAsmPrinter; -class MCInst; +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 &); @@ -55,8 +58,6 @@ FunctionPass *createMLxExpansionPass(); FunctionPass *createThumb2ITBlockPass(); FunctionPass *createThumb2SizeReductionPass(); -extern Target TheARMTarget, TheThumbTarget; - void LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, ARMAsmPrinter &AP); diff --git a/lib/Target/ARM/ARM.td b/lib/Target/ARM/ARM.td index 39a3528..cf333cc 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">; @@ -83,34 +91,24 @@ def FeatureDSPThumb2 : SubtargetFeature<"t2dsp", "Thumb2DSP", "true", 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, FeatureDSPThumb2]>; -def ArchV7A : SubtargetFeature<"v7a", "ARMArchVersion", "V7A", - "ARM v7A", - [FeatureThumb2, FeatureNEON, FeatureDB, - FeatureDSPThumb2]>; -def ArchV7M : SubtargetFeature<"v7m", "ARMArchVersion", "V7M", - "ARM v7M", - [FeatureThumb2, FeatureNoARM, FeatureDB, - FeatureHWDiv]>; -def ArchV7EM : SubtargetFeature<"v7em", "ARMArchVersion", "V7EM", - "ARM v7E-M", - [FeatureThumb2, FeatureNoARM, FeatureDB, - FeatureHWDiv, FeatureDSPThumb2, - FeatureT2XtPk]>; +// 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. @@ -119,8 +117,6 @@ def ArchV7EM : SubtargetFeature<"v7em", "ARMArchVersion", "V7EM", 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, @@ -145,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", [ArchV7EM, 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/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index 7240837..dbc3ee4 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); @@ -1069,48 +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); - return; - } - case ARM::t2LDMIA_RET: { - // As above for LDMIA_RET. Map to the tPOP instruction. - MCInst TmpInst; - LowerARMMachineInstrToMCInst(MI, TmpInst, *this); - TmpInst.setOpcode(ARM::t2LDMIA_UPD); - OutStreamer.EmitInstruction(TmpInst); - return; - } - case ARM::tPOP_RET: { - // As above for LDMIA_RET. Map to the tPOP instruction. - MCInst TmpInst; - LowerARMMachineInstrToMCInst(MI, TmpInst, *this); - TmpInst.setOpcode(ARM::tPOP); - OutStreamer.EmitInstruction(TmpInst); + // Do any auto-generated pseudo lowerings. + if (emitPseudoExpansionLowering(OutStreamer, MI)) return; - } + // 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()) { @@ -1121,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: { @@ -1159,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: { { @@ -1868,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; @@ -1954,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 5f9169e..7741fc4 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 4c9ecdf..458f7dd 100644 --- a/lib/Target/ARM/ARMBaseInfo.h +++ b/lib/Target/ARM/ARMBaseInfo.h @@ -17,22 +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. -// -#define GET_REGINFO_ENUM -#include "ARMGenRegisterInfo.inc" - -// Defines symbolic names for the ARM instructions. -// -#define GET_INSTRINFO_ENUM -#include "ARMGenInstrInfo.inc" - namespace llvm { // Enums corresponding to ARM condition codes diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index 32e9372..649bd7d 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -30,12 +30,12 @@ #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_MC_DESC #define GET_INSTRINFO_CTOR #include "ARMGenInstrInfo.inc" @@ -528,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 MCInstrDesc &MCID = MI->getDesc(); - uint64_t TSFlags = MCID.TSFlags; + 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: @@ -620,8 +608,6 @@ unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { // Otherwise, pseudo-instruction sizes are zero. return 0; } - } - } return 0; // Not reached } @@ -651,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)) @@ -661,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); } @@ -1273,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:: @@ -1294,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 diff --git a/lib/Target/ARM/ARMBaseInstrInfo.h b/lib/Target/ARM/ARMBaseInstrInfo.h index f95adc4..507e897 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/lib/Target/ARM/ARMBaseInstrInfo.h @@ -39,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 @@ -129,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, @@ -311,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; } diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index e46082d..ba42295 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -40,7 +40,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Support/CommandLine.h" -#define GET_REGINFO_MC_DESC #define GET_REGINFO_TARGET_DESC #include "ARMGenRegisterInfo.inc" diff --git a/lib/Target/ARM/ARMConstantIslandPass.cpp b/lib/Target/ARM/ARMConstantIslandPass.cpp index 309caee..f45ebdc 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; } diff --git a/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/lib/Target/ARM/ARMExpandPseudoInsts.cpp index 619c603..94b72fd 100644 --- a/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -841,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; @@ -905,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 @@ -963,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/ARMFrameLowering.cpp b/lib/Target/ARM/ARMFrameLowering.cpp index 9e943e4..381b404 100644 --- a/lib/Target/ARM/ARMFrameLowering.cpp +++ b/lib/Target/ARM/ARMFrameLowering.cpp @@ -739,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; } diff --git a/lib/Target/ARM/ARMGlobalMerge.cpp b/lib/Target/ARM/ARMGlobalMerge.cpp index 4bdd4f1..8d77b2d 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; @@ -176,8 +176,8 @@ bool ARMGlobalMerge::doInitialization(Module &M) { // Ignore fancy-aligned globals for now. unsigned Alignment = I->getAlignment(); - unsigned AllocSize = TD->getTypeAllocSize(I->getType()->getElementType()); - if (Alignment > AllocSize) + const Type *Ty = I->getType()->getElementType(); + if (Alignment > TD->getABITypeAlignment(Ty)) continue; // Ignore all 'special' globals. @@ -185,7 +185,7 @@ bool ARMGlobalMerge::doInitialization(Module &M) { I->getName().startswith(".llvm.")) continue; - if (AllocSize < 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/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 8cd9aa2..cf8c5ba 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -708,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. @@ -1637,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 @@ -2747,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; @@ -6953,6 +6960,70 @@ 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()) { @@ -6981,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: diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h index dd9df0e..980fb40 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; diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index 897d8a5..3ccf22f 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.td b/lib/Target/ARM/ARMInstrInfo.td index ed979e7..a42dd1a 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -147,35 +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; + 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()">; @@ -242,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>; @@ -299,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. @@ -316,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 @@ -323,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"; } @@ -399,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]> { @@ -421,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 @@ -439,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; @@ -932,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))]>, @@ -973,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 @@ -981,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))]>; } } @@ -1139,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}; @@ -1231,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; @@ -1250,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 @@ -1305,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. @@ -1342,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 @@ -1409,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]>; } @@ -1424,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 @@ -1561,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 */]> { @@ -1585,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! @@ -1931,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; @@ -1942,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; @@ -2007,19 +2057,14 @@ defm STM : arm_ldst_mult<"stm", 0, LdStMulFrm, IIC_iStore_m, IIC_iStore_mu>; } // neverHasSideEffects -// Load / Store Multiple Mnemonic Aliases -def : MnemonicAlias<"ldmfd", "ldmia">; -def : MnemonicAlias<"stmfd", "stmdb">; -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">; //===----------------------------------------------------------------------===// @@ -2189,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; @@ -2206,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; @@ -2241,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 { @@ -2296,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))]>; } @@ -2350,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))]>; } @@ -2565,7 +2612,7 @@ defm BIC : AsI1_bin_irs<0b1110, "bic", 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]> { @@ -2580,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))]>, @@ -2600,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; @@ -2677,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))]>, @@ -2710,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)))]>, @@ -2725,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", []>, @@ -2790,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 @@ -3193,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">; @@ -3220,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 @@ -3251,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 { @@ -3426,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)]> { @@ -3447,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)]> { @@ -3471,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; } @@ -3599,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 */, @@ -3636,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 */, @@ -3651,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; @@ -3677,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; @@ -3828,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. @@ -3993,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 977139f..0df62f4 100644 --- a/lib/Target/ARM/ARMInstrNEON.td +++ b/lib/Target/ARM/ARMInstrNEON.td @@ -4214,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), @@ -4704,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}; @@ -4721,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 4efe171..bfe83ec 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -26,10 +26,6 @@ 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>; @@ -75,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"; } @@ -98,6 +96,7 @@ def t_bltarget : Operand<i32> { def t_blxtarget : Operand<i32> { let EncoderMethod = "getThumbBLXTargetOpValue"; } +} def MemModeRegThumbAsmOperand : AsmOperandClass { let Name = "MemModeRegThumb"; @@ -361,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", []>, @@ -391,25 +369,17 @@ 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 : tPseudoInst<(outs), (ins pred:$p, reglist:$regs, variable_ops), - Size2Bytes, IIC_iPop_Br, []>; +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 // prevent stack-pointer assignments that appear immediately before calls from @@ -458,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]>; } @@ -510,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]>; } @@ -528,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]; } @@ -577,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 @@ -1055,7 +1052,7 @@ def tMOVi8 : T1sI<(outs tGPR:$Rd), (ins imm0_255:$imm8), IIC_iMOVi, let neverHasSideEffects = 1 in { def tMOVr : Thumb1pI<(outs GPR:$Rd), (ins GPR:$Rm), AddrModeNone, - Size2Bytes, IIC_iMOVr, + 2, IIC_iMOVr, "mov", "\t$Rd, $Rm", "", []>, T1Special<{1,0,?,?}> { // A8.6.97 @@ -1229,105 +1226,11 @@ 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 @@ -1337,7 +1240,7 @@ def tCDP : T1Cop<(outs), (ins p_imm:$cop, i32imm:$opc1, // 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), Size4Bytes, IIC_Br, +def tTPsoft : tPseudoInst<(outs), (ins), 4, IIC_Br, [(set R0, ARMthread_pointer)]>; //===----------------------------------------------------------------------===// @@ -1357,14 +1260,14 @@ def tTPsoft : tPseudoInst<(outs), (ins), Size4Bytes, 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]>; @@ -1477,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 eb533f8..c2c6cbc 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -716,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))]>; } } @@ -1164,10 +1164,10 @@ 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, []>; @@ -2709,14 +2709,14 @@ defm t2TEQ : T2I_cmp_irs<0b0100, "teq", let neverHasSideEffects = 1 in { def t2MOVCCr : t2PseudoInst<(outs rGPR:$Rd), (ins rGPR:$false, rGPR:$Rm, pred:$p), - Size4Bytes, IIC_iCMOVr, + 4, IIC_iCMOVr, [/*(set rGPR:$Rd, (ARMcmov rGPR:$false, rGPR:$Rm, imm:$cc, CCR:$ccr))*/]>, RegConstraint<"$false = $Rd">; let isMoveImm = 1 in def t2MOVCCi : t2PseudoInst<(outs rGPR:$Rd), (ins rGPR:$false, t2_so_imm:$imm, pred:$p), - Size4Bytes, IIC_iCMOVi, + 4, IIC_iCMOVi, [/*(set rGPR:$Rd,(ARMcmov rGPR:$false,t2_so_imm:$imm, imm:$cc, CCR:$ccr))*/]>, RegConstraint<"$false = $Rd">; @@ -2823,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> { @@ -2839,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> { @@ -2859,13 +2859,13 @@ 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, + AddrModeNone, 4, NoItinerary, "ldrexb", "\t$Rt, $addr", "", []>; def t2LDREXH : T2I_ldrex<0b01, (outs rGPR:$Rt), (ins t2addrmode_reg:$addr), - AddrModeNone, Size4Bytes, NoItinerary, + AddrModeNone, 4, NoItinerary, "ldrexh", "\t$Rt, $addr", "", []>; def t2LDREX : Thumb2I<(outs rGPR:$Rt), (ins t2addrmode_reg:$addr), - AddrModeNone, Size4Bytes, NoItinerary, + AddrModeNone, 4, NoItinerary, "ldrex", "\t$Rt, $addr", "", []> { let Inst{31-27} = 0b11101; let Inst{26-20} = 0b0000101; @@ -2880,7 +2880,7 @@ def t2LDREX : Thumb2I<(outs rGPR:$Rt), (ins t2addrmode_reg:$addr), 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; @@ -2891,14 +2891,14 @@ 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, + AddrModeNone, 4, NoItinerary, "strexb", "\t$Rd, $Rt, $addr", "", []>; def t2STREXH : T2I_strex<0b01, (outs rGPR:$Rd), (ins rGPR:$Rt, t2addrmode_reg:$addr), - AddrModeNone, Size4Bytes, NoItinerary, + 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; @@ -2917,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; @@ -2955,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]>; } @@ -2964,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]>; } @@ -2978,9 +2978,10 @@ let Defs = // 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: t2PseudoInst<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, +def t2LDMIA_RET: t2PseudoExpand<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), - Size4Bytes, IIC_iLoad_mBr, []>, + 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 { @@ -3003,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]", []> { @@ -3061,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; @@ -3145,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; @@ -3314,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; @@ -3340,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; @@ -3374,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 d2aaa97..f1f3cb9 100644 --- a/lib/Target/ARM/ARMInstrVFP.td +++ b/lib/Target/ARM/ARMInstrVFP.td @@ -873,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, @@ -990,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/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp index 4fcba11..39be3f0 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 MCInstrDesc &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 59d6050..7411b59 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/ARMSubtarget.cpp b/lib/Target/ARM/ARMSubtarget.cpp index a7010c5..1cab9e4 100644 --- a/lib/Target/ARM/ARMSubtarget.cpp +++ b/lib/Target/ARM/ARMSubtarget.cpp @@ -18,9 +18,8 @@ #include "llvm/Support/CommandLine.h" #include "llvm/ADT/SmallVector.h" -#define GET_SUBTARGETINFO_CTOR -#define GET_SUBTARGETINFO_MC_DESC #define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR #include "ARMGenSubtargetInfo.inc" using namespace llvm; @@ -37,17 +36,24 @@ StrictAlign("arm-strict-align", cl::Hidden, cl::desc("Disallow all unaligned memory accesses")); ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU, - const std::string &FS, bool isT) - : ARMGenSubtargetInfo() - , ARMArchVersion(V4) + 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) @@ -68,78 +74,25 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU, , TargetTriple(TT) , TargetABI(ARM_ABI_APCS) { // 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.empty()) CPUString = "generic"; - if (CPUString == "generic" && (FS.empty() || FS == "generic")) { - ARMArchVersion = V4T; - ARMArchFeature = "+v4t"; - } - - // 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; - - 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 (Len >= Idx+3 && TT[Idx+1] == 'e'&& TT[Idx+2] == 'm') { - ARMArchVersion = V7EM; - ARMArchFeature = "+v7em"; - } - } 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; // 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 FSWithArch = std::string(ARMArchFeature); - if (FSWithArch.empty()) - FSWithArch = FS; - else if (!FS.empty()) - FSWithArch = FSWithArch + "," + FS; - ParseSubtargetFeatures(FSWithArch, CPUString); + std::string ArchFS = ARM_MC::ParseARMTriple(TT); + if (!FS.empty()) { + if (!ArchFS.empty()) + ArchFS = ArchFS + "," + FS; + else + ArchFS = FS; + } + ParseSubtargetFeatures(CPUString, ArchFS); + + // 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; // Initialize scheduling itinerary for the specified CPU. InstrItins = getInstrItineraryForCPU(CPUString); @@ -147,11 +100,8 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU, // 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; @@ -159,7 +109,7 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU, if (!isTargetDarwin()) UseMovt = hasV6T2Ops(); else { - IsR9Reserved = ReserveR9 | (ARMArchVersion < V6); + IsR9Reserved = ReserveR9 | !HasV6Ops; UseMovt = DarwinUseMOVT && hasV6T2Ops(); } diff --git a/lib/Target/ARM/ARMSubtarget.h b/lib/Target/ARM/ARMSubtarget.h index 66e4426..c650872 100644 --- a/lib/Target/ARM/ARMSubtarget.h +++ b/lib/Target/ARM/ARMSubtarget.h @@ -14,6 +14,7 @@ #ifndef ARMSUBTARGET_H #define ARMSUBTARGET_H +#include "MCTargetDesc/ARMMCTargetDesc.h" #include "llvm/Target/TargetSubtargetInfo.h" #include "llvm/MC/MCInstrItineraries.h" #include "llvm/ADT/Triple.h" @@ -24,35 +25,31 @@ namespace llvm { class GlobalValue; +class StringRef; class ARMSubtarget : public ARMGenSubtargetInfo { protected: - enum ARMArchEnum { - V4, V4T, V5T, V5TE, V6, V6M, V6T2, V7A, V7M, V7EM - }; - 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, V7EM. - 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 @@ -70,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; @@ -161,7 +158,7 @@ protected: /// of the specified triple. /// ARMSubtarget(const std::string &TT, const std::string &CPU, - const std::string &FS, bool isThumb); + const std::string &FS); /// getMaxInlineSizeThreshold - Returns the maximum memset / memcpy size /// that still makes it profitable to inline the call. @@ -172,27 +169,28 @@ protected: } /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - void 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; } @@ -216,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; } diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp index 80e7d55..f0b176a 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); @@ -79,10 +65,9 @@ extern "C" void LLVMInitializeARMTarget() { ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, const std::string &TT, const std::string &CPU, - const std::string &FS, - bool isThumb) - : LLVMTargetMachine(T, TT), - Subtarget(TT, CPU, FS, isThumb), + const std::string &FS) + : LLVMTargetMachine(T, TT, CPU, FS), + Subtarget(TT, CPU, FS), JITInfo(), InstrItins(Subtarget.getInstrItineraryData()) { DefRelocModel = getRelocationModel(); @@ -95,7 +80,7 @@ ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, ARMTargetMachine::ARMTargetMachine(const Target &T, const std::string &TT, const std::string &CPU, const std::string &FS) - : ARMBaseTargetMachine(T, TT, CPU, 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") : @@ -113,7 +98,7 @@ 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, CPU, 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 a4a7927..bc3d46a 100644 --- a/lib/Target/ARM/ARMTargetMachine.h +++ b/lib/Target/ARM/ARMTargetMachine.h @@ -41,8 +41,7 @@ private: public: ARMBaseTargetMachine(const Target &T, const std::string &TT, - const std::string &CPU, 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; } diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 6952c38..a474127 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; } } @@ -358,6 +383,30 @@ public: 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; @@ -374,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; @@ -504,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( @@ -536,6 +598,21 @@ public: 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()); @@ -674,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); @@ -725,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); @@ -828,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()) << ">"; @@ -889,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: @@ -953,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(); @@ -974,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; } @@ -1188,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); @@ -1630,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 @@ -1790,29 +1949,32 @@ static StringRef SplitMnemonic(StringRef Mnemonic, 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("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; + // 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 @@ -1852,9 +2014,6 @@ static StringRef SplitMnemonic(StringRef Mnemonic, void ARMAsmParser:: GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, bool &CanAcceptPredicationCode) { - bool isThumbOne = TM.getSubtarget<ARMSubtarget>().isThumb1Only(); - 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" || @@ -1863,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" && !isThumbOne)) { + (Mnemonic == "mov" && !isThumbOne())) { CanAcceptCarrySet = true; } else { CanAcceptCarrySet = false; @@ -1880,7 +2039,7 @@ GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, CanAcceptPredicationCode = true; } - if (isThumb) + if (isThumb()) if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" || Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp") CanAcceptPredicationCode = false; @@ -1912,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) { @@ -2016,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") { @@ -2202,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 a261ca0..21608d0 100644 --- a/lib/Target/ARM/CMakeLists.txt +++ b/lib/Target/ARM/CMakeLists.txt @@ -4,6 +4,7 @@ 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) @@ -35,7 +36,6 @@ add_llvm_target(ARMCodeGen ARMMCCodeEmitter.cpp ARMMCExpr.cpp ARMLoadStoreOptimizer.cpp - ARMMCAsmInfo.cpp ARMMCInstLower.cpp ARMRegisterInfo.cpp ARMSelectionDAGInfo.cpp @@ -65,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 fe165b0..d89c80a 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp @@ -70,9 +70,10 @@ /// /// { ARM::CCRRegClassID, 0|(1<<MCOI::OptionalDef), 0 } /// -/// And this maps to one MCOperand with the regsiter kind of ARM::CPSR. -#define GET_INSTRINFO_MC_DESC -#include "ARMGenInstrInfo.inc" + +namespace llvm { +extern MCInstrDesc ARMInsts[]; +} using namespace llvm; @@ -3092,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 @@ -3380,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) { diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp index 8ae87f8..78d3e47 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 bde0eb9..d5f238b 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 53b4c95..53b4c95 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 90f7822..90f7822 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 0000000..f8fcf2b --- /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 0000000..74701e3 --- /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 0000000..68daf42 --- /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 0000000..448ed9d --- /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/Makefile b/lib/Target/ARM/Makefile index 51a8ac4..eb8c603 100644 --- a/lib/Target/ARM/Makefile +++ b/lib/Target/ARM/Makefile @@ -17,8 +17,9 @@ BUILT_SOURCES = ARMGenRegisterInfo.inc ARMGenInstrInfo.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 965665c..c85d1e9 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 8ba9a27..2f6842e 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 48211d8..c258870 100644 --- a/lib/Target/ARM/Thumb1FrameLowering.cpp +++ b/lib/Target/ARM/Thumb1FrameLowering.cpp @@ -273,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/Alpha/Alpha.h b/lib/Target/Alpha/Alpha.h index 435c95c..6ffaf45 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,20 +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. -// - -#define GET_REGINFO_ENUM -#include "AlphaGenRegisterInfo.inc" - -// Defines symbolic names for the Alpha instructions. -// -#define GET_INSTRINFO_ENUM -#include "AlphaGenInstrInfo.inc" - #endif diff --git a/lib/Target/Alpha/AlphaISelLowering.cpp b/lib/Target/Alpha/AlphaISelLowering.cpp index daf9555..de003fb 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); diff --git a/lib/Target/Alpha/AlphaInstrInfo.cpp b/lib/Target/Alpha/AlphaInstrInfo.cpp index c105759..4dcec8f 100644 --- a/lib/Target/Alpha/AlphaInstrInfo.cpp +++ b/lib/Target/Alpha/AlphaInstrInfo.cpp @@ -14,13 +14,13 @@ #include "Alpha.h" #include "AlphaInstrInfo.h" #include "AlphaMachineFunctionInfo.h" +#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_MC_DESC #define GET_INSTRINFO_CTOR #include "AlphaGenInstrInfo.inc" using namespace llvm; diff --git a/lib/Target/Alpha/AlphaRegisterInfo.cpp b/lib/Target/Alpha/AlphaRegisterInfo.cpp index 0289307..df8f157 100644 --- a/lib/Target/Alpha/AlphaRegisterInfo.cpp +++ b/lib/Target/Alpha/AlphaRegisterInfo.cpp @@ -34,7 +34,6 @@ #include "llvm/ADT/STLExtras.h" #include <cstdlib> -#define GET_REGINFO_MC_DESC #define GET_REGINFO_TARGET_DESC #include "AlphaGenRegisterInfo.inc" diff --git a/lib/Target/Alpha/AlphaSubtarget.cpp b/lib/Target/Alpha/AlphaSubtarget.cpp index fce65fc..624a5e2 100644 --- a/lib/Target/Alpha/AlphaSubtarget.cpp +++ b/lib/Target/Alpha/AlphaSubtarget.cpp @@ -13,23 +13,23 @@ #include "AlphaSubtarget.h" #include "Alpha.h" +#include "llvm/Target/TargetRegistry.h" -#define GET_SUBTARGETINFO_CTOR -#define GET_SUBTARGETINFO_MC_DESC #define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR #include "AlphaGenSubtargetInfo.inc" using namespace llvm; AlphaSubtarget::AlphaSubtarget(const std::string &TT, const std::string &CPU, const std::string &FS) - : AlphaGenSubtargetInfo(), HasCT(false) { + : AlphaGenSubtargetInfo(TT, CPU, FS), HasCT(false) { std::string CPUName = CPU; if (CPUName.empty()) CPUName = "generic"; // Parse features string. - ParseSubtargetFeatures(FS, CPUName); + 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 847d495..70b3116 100644 --- a/lib/Target/Alpha/AlphaSubtarget.h +++ b/lib/Target/Alpha/AlphaSubtarget.h @@ -22,6 +22,7 @@ #include "AlphaGenSubtargetInfo.inc" namespace llvm { +class StringRe; class AlphaSubtarget : public AlphaGenSubtargetInfo { protected: @@ -39,7 +40,7 @@ public: /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - void 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 e854ccd..3b65d41 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,13 +20,12 @@ 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, CPU, FS), diff --git a/lib/Target/Alpha/CMakeLists.txt b/lib/Target/Alpha/CMakeLists.txt index 3121889..a6027bb 100644 --- a/lib/Target/Alpha/CMakeLists.txt +++ b/lib/Target/Alpha/CMakeLists.txt @@ -15,7 +15,6 @@ add_llvm_target(AlphaCodeGen AlphaISelLowering.cpp AlphaFrameLowering.cpp AlphaLLRP.cpp - AlphaMCAsmInfo.cpp AlphaRegisterInfo.cpp AlphaSubtarget.cpp AlphaTargetMachine.cpp @@ -23,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 a35e884..a35e884 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 837844b..837844b 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 0000000..562052b --- /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 0000000..b0619e6 --- /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 0000000..ad0dd26 --- /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 0000000..d55175f --- /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 9409ae5..f48847a 100644 --- a/lib/Target/Alpha/Makefile +++ b/lib/Target/Alpha/Makefile @@ -16,6 +16,6 @@ BUILT_SOURCES = AlphaGenRegisterInfo.inc AlphaGenInstrInfo.inc \ AlphaGenAsmWriter.inc AlphaGenDAGISel.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 c3ee7e7..a00ff4c 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,17 +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. -#define GET_REGINFO_ENUM -#include "BlackfinGenRegisterInfo.inc" - -// Defines symbolic names for the Blackfin instructions. -#define GET_INSTRINFO_ENUM -#include "BlackfinGenInstrInfo.inc" - #endif diff --git a/lib/Target/Blackfin/BlackfinInstrInfo.cpp b/lib/Target/Blackfin/BlackfinInstrInfo.cpp index 0515a5f..d190ae7 100644 --- a/lib/Target/Blackfin/BlackfinInstrInfo.cpp +++ b/lib/Target/Blackfin/BlackfinInstrInfo.cpp @@ -14,14 +14,14 @@ #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 -#define GET_INSTRINFO_MC_DESC #include "BlackfinGenInstrInfo.inc" using namespace llvm; diff --git a/lib/Target/Blackfin/BlackfinIntrinsicInfo.cpp b/lib/Target/Blackfin/BlackfinIntrinsicInfo.cpp index 34a8d38..ae8ee9e 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 2f4a453..3a7c104 100644 --- a/lib/Target/Blackfin/BlackfinRegisterInfo.cpp +++ b/lib/Target/Blackfin/BlackfinRegisterInfo.cpp @@ -30,7 +30,6 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" -#define GET_REGINFO_MC_DESC #define GET_REGINFO_TARGET_DESC #include "BlackfinGenRegisterInfo.inc" diff --git a/lib/Target/Blackfin/BlackfinSubtarget.cpp b/lib/Target/Blackfin/BlackfinSubtarget.cpp index 9d1d481..ec919cd 100644 --- a/lib/Target/Blackfin/BlackfinSubtarget.cpp +++ b/lib/Target/Blackfin/BlackfinSubtarget.cpp @@ -12,10 +12,11 @@ //===----------------------------------------------------------------------===// #include "BlackfinSubtarget.h" +#include "Blackfin.h" +#include "llvm/Target/TargetRegistry.h" -#define GET_SUBTARGETINFO_CTOR -#define GET_SUBTARGETINFO_MC_DESC #define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR #include "BlackfinGenSubtargetInfo.inc" using namespace llvm; @@ -23,7 +24,7 @@ using namespace llvm; BlackfinSubtarget::BlackfinSubtarget(const std::string &TT, const std::string &CPU, const std::string &FS) - : BlackfinGenSubtargetInfo(), sdram(false), + : BlackfinGenSubtargetInfo(TT, CPU, FS), sdram(false), icplb(false), wa_mi_shift(false), wa_csync(false), @@ -39,5 +40,5 @@ BlackfinSubtarget::BlackfinSubtarget(const std::string &TT, if (CPUName.empty()) CPUName = "generic"; // Parse features string. - ParseSubtargetFeatures(FS, CPUName); + ParseSubtargetFeatures(CPUName, FS); } diff --git a/lib/Target/Blackfin/BlackfinSubtarget.h b/lib/Target/Blackfin/BlackfinSubtarget.h index a7d6c16..1a01a81 100644 --- a/lib/Target/Blackfin/BlackfinSubtarget.h +++ b/lib/Target/Blackfin/BlackfinSubtarget.h @@ -21,6 +21,7 @@ #include "BlackfinGenSubtargetInfo.inc" namespace llvm { +class StringRef; class BlackfinSubtarget : public BlackfinGenSubtargetInfo { bool sdram; @@ -40,8 +41,7 @@ namespace llvm { /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - void 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 477c438..a1c9f1c 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,15 +19,13 @@ 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, CPU, FS), TLInfo(*this), diff --git a/lib/Target/Blackfin/CMakeLists.txt b/lib/Target/Blackfin/CMakeLists.txt index 9df4ab0..d3f33a9 100644 --- a/lib/Target/Blackfin/CMakeLists.txt +++ b/lib/Target/Blackfin/CMakeLists.txt @@ -15,7 +15,6 @@ add_llvm_target(BlackfinCodeGen BlackfinISelDAGToDAG.cpp BlackfinISelLowering.cpp BlackfinFrameLowering.cpp - BlackfinMCAsmInfo.cpp BlackfinRegisterInfo.cpp BlackfinSubtarget.cpp BlackfinTargetMachine.cpp @@ -23,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 5b9d4a2..5b9d4a2 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 c372aa2..c372aa2 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 0000000..0fa1471 --- /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 0000000..5bffe94 --- /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 0000000..8cd924f --- /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 0000000..6b26101 --- /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 63f1543..756ac6b 100644 --- a/lib/Target/Blackfin/Makefile +++ b/lib/Target/Blackfin/Makefile @@ -17,7 +17,7 @@ BUILT_SOURCES = BlackfinGenRegisterInfo.inc BlackfinGenInstrInfo.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 ec4020e..415beb1 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. @@ -209,8 +199,8 @@ namespace { /// 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); @@ -354,6 +344,7 @@ namespace { char CWriter::ID = 0; + static std::string CBEMangle(const std::string &S) { std::string Result; @@ -369,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. @@ -466,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) @@ -554,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); @@ -594,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(), @@ -634,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!"); } @@ -1754,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); @@ -1824,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()) { @@ -2114,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"; @@ -2127,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 @@ -2175,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; @@ -2185,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"; } } @@ -2842,10 +2744,12 @@ static void printLimitValue(const IntegerType &Ty, bool isSigned, bool isMax, 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(); @@ -3261,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]; @@ -3654,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 @@ -3675,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 @@ -3699,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 88cc8eb..e64216b 100644 --- a/lib/Target/CBackend/CTargetMachine.h +++ b/lib/Target/CBackend/CTargetMachine.h @@ -22,7 +22,7 @@ namespace llvm { struct CTargetMachine : public TargetMachine { CTargetMachine(const Target &T, const std::string &TT, const std::string &CPU, const std::string &FS) - : TargetMachine(T) {} + : TargetMachine(T, TT, CPU, FS) {} virtual bool addPassesToEmitFile(PassManagerBase &PM, formatted_raw_ostream &Out, diff --git a/lib/Target/CellSPU/CMakeLists.txt b/lib/Target/CellSPU/CMakeLists.txt index 14e8208..0b94e0c 100644 --- a/lib/Target/CellSPU/CMakeLists.txt +++ b/lib/Target/CellSPU/CMakeLists.txt @@ -15,7 +15,6 @@ add_llvm_target(CellSPUCodeGen SPUISelDAGToDAG.cpp SPUISelLowering.cpp SPUFrameLowering.cpp - SPUMCAsmInfo.cpp SPURegisterInfo.cpp SPUSubtarget.cpp SPUTargetMachine.cpp @@ -24,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 0000000..85fb258 --- /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 0000000..10d9a42 --- /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 99aaeb0..8c1176a 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 7f850d3..7f850d3 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 0000000..26c5a4b --- /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/X86/MCTargetDesc/X86TargetDesc.h b/lib/Target/CellSPU/MCTargetDesc/SPUMCTargetDesc.h index 9ab622d..c5c037d 100644 --- a/lib/Target/X86/MCTargetDesc/X86TargetDesc.h +++ b/lib/Target/CellSPU/MCTargetDesc/SPUMCTargetDesc.h @@ -1,4 +1,4 @@ -//===-- X86TargetDesc.h - X86 Target Descriptions ---------------*- C++ -*-===// +//===-- SPUMCTargetDesc.h - Alpha Target Descriptions ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,28 +7,34 @@ // //===----------------------------------------------------------------------===// // -// This file provides X86 specific target descriptions. +// This file provides Alpha specific target descriptions. // //===----------------------------------------------------------------------===// -#ifndef X86TARGETDESC_H -#define X86TARGETDESC_H +#ifndef SPUMCTARGETDESC_H +#define SPUMCTARGETDESC_H namespace llvm { +class MCSubtargetInfo; class Target; +class StringRef; + +extern Target TheCellSPUTarget; -extern Target TheX86_32Target, TheX86_64Target; } // End llvm namespace -// Defines symbolic names for X86 registers. This defines a mapping from +// Define symbolic names for Cell registers. This defines a mapping from // register name to register number. // #define GET_REGINFO_ENUM -#include "X86GenRegisterInfo.inc" +#include "SPUGenRegisterInfo.inc" -// Defines symbolic names for the X86 instructions. +// Defines symbolic names for the SPU instructions. // #define GET_INSTRINFO_ENUM -#include "X86GenInstrInfo.inc" +#include "SPUGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "SPUGenSubtargetInfo.inc" #endif diff --git a/lib/Target/CellSPU/Makefile b/lib/Target/CellSPU/Makefile index c804b16..d7a8247 100644 --- a/lib/Target/CellSPU/Makefile +++ b/lib/Target/CellSPU/Makefile @@ -15,6 +15,6 @@ BUILT_SOURCES = SPUGenInstrInfo.inc SPUGenRegisterInfo.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 5c81c9a..b51fbc7 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,12 +26,6 @@ namespace llvm { FunctionPass *createSPUISelDag(SPUTargetMachine &TM); FunctionPass *createSPUNopFillerPass(SPUTargetMachine &tm); - extern Target TheCellSPUTarget; } -// Defines symbolic names for the SPU instructions. -// -#define GET_INSTRINFO_ENUM -#include "SPUGenInstrInfo.inc" - #endif /* LLVM_TARGET_IBMCELLSPU_H */ diff --git a/lib/Target/CellSPU/SPUFrameLowering.cpp b/lib/Target/CellSPU/SPUFrameLowering.cpp index 432f4a1..a3e7e73 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 9351ffd..a297d03 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 f9b5041..f0ceee2 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 93b6d4c..e67b10c 100644 --- a/lib/Target/CellSPU/SPUInstrInfo.cpp +++ b/lib/Target/CellSPU/SPUInstrInfo.cpp @@ -11,19 +11,18 @@ // //===----------------------------------------------------------------------===// -#include "SPURegisterNames.h" #include "SPUInstrInfo.h" #include "SPUInstrBuilder.h" #include "SPUTargetMachine.h" #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 -#define GET_INSTRINFO_MC_DESC #include "SPUGenInstrInfo.inc" using namespace llvm; diff --git a/lib/Target/CellSPU/SPURegisterInfo.cpp b/lib/Target/CellSPU/SPURegisterInfo.cpp index fefd141..19896c0 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,7 +42,6 @@ #include "llvm/ADT/STLExtras.h" #include <cstdlib> -#define GET_REGINFO_MC_DESC #define GET_REGINFO_TARGET_DESC #include "SPUGenRegisterInfo.inc" diff --git a/lib/Target/CellSPU/SPUSubtarget.cpp b/lib/Target/CellSPU/SPUSubtarget.cpp index 2481e3b..856dc82 100644 --- a/lib/Target/CellSPU/SPUSubtarget.cpp +++ b/lib/Target/CellSPU/SPUSubtarget.cpp @@ -13,19 +13,19 @@ #include "SPUSubtarget.h" #include "SPU.h" -#include "llvm/ADT/SmallVector.h" #include "SPURegisterInfo.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/SmallVector.h" -#define GET_SUBTARGETINFO_CTOR -#define GET_SUBTARGETINFO_MC_DESC #define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR #include "SPUGenSubtargetInfo.inc" using namespace llvm; SPUSubtarget::SPUSubtarget(const std::string &TT, const std::string &CPU, const std::string &FS) : - SPUGenSubtargetInfo(), + SPUGenSubtargetInfo(TT, CPU, FS), StackAlignment(16), ProcDirective(SPU::DEFAULT_PROC), UseLargeMem(false) @@ -35,7 +35,7 @@ SPUSubtarget::SPUSubtarget(const std::string &TT, const std::string &CPU, 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); diff --git a/lib/Target/CellSPU/SPUSubtarget.h b/lib/Target/CellSPU/SPUSubtarget.h index 19b97d3..7c4aa14 100644 --- a/lib/Target/CellSPU/SPUSubtarget.h +++ b/lib/Target/CellSPU/SPUSubtarget.h @@ -23,6 +23,7 @@ namespace llvm { class GlobalValue; + class StringRef; namespace SPU { enum { @@ -57,7 +58,7 @@ namespace llvm { /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - void 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. diff --git a/lib/Target/CellSPU/SPUTargetMachine.cpp b/lib/Target/CellSPU/SPUTargetMachine.cpp index f04e982..3542a2b 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> * @@ -36,7 +33,7 @@ SPUFrameLowering::getCalleeSaveSpillSlots(unsigned &NumEntries) const { SPUTargetMachine::SPUTargetMachine(const Target &T, const std::string &TT, const std::string &CPU,const std::string &FS) - : LLVMTargetMachine(T, TT), + : LLVMTargetMachine(T, TT, CPU, FS), Subtarget(TT, CPU, FS), DataLayout(Subtarget.getTargetDataString()), InstrInfo(*this), diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp index ae03725..10d18f6 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,22 +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(" - << 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; @@ -594,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()) @@ -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 8023e13..7322e3e 100644 --- a/lib/Target/CppBackend/CPPTargetMachine.h +++ b/lib/Target/CppBackend/CPPTargetMachine.h @@ -24,7 +24,7 @@ class formatted_raw_ostream; struct CPPTargetMachine : public TargetMachine { CPPTargetMachine(const Target &T, const std::string &TT, const std::string &CPU, const std::string &FS) - : TargetMachine(T) {} + : TargetMachine(T, TT, CPU, FS) {} virtual bool addPassesToEmitFile(PassManagerBase &PM, formatted_raw_ostream &Out, diff --git a/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp b/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp index 524f33d..eebd9d8 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 536726d..0bc5b78 100644 --- a/lib/Target/MBlaze/CMakeLists.txt +++ b/lib/Target/MBlaze/CMakeLists.txt @@ -17,7 +17,6 @@ add_llvm_target(MBlazeCodeGen MBlazeISelDAGToDAG.cpp MBlazeISelLowering.cpp MBlazeFrameLowering.cpp - MBlazeMCAsmInfo.cpp MBlazeRegisterInfo.cpp MBlazeSubtarget.cpp MBlazeTargetMachine.cpp @@ -35,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 1464274..88d80a1 100644 --- a/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp +++ b/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp @@ -27,10 +27,12 @@ // #include "MBlazeGenDecoderTables.inc" // #include "MBlazeGenRegisterNames.inc" -#define GET_INSTRINFO_MC_DESC -#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 13c4b49..eacca41 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 e9aff5b..3390794 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,28 +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. -#define GET_REGINFO_ENUM -#include "MBlazeGenRegisterInfo.inc" - -// Defines symbolic names for the MBlaze instructions. -#define GET_INSTRINFO_ENUM -#include "MBlazeGenInstrInfo.inc" - #endif diff --git a/lib/Target/MBlaze/MBlazeAsmPrinter.cpp b/lib/Target/MBlaze/MBlazeAsmPrinter.cpp index 0f0f60e..0016df5 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/MBlazeISelLowering.cpp b/lib/Target/MBlaze/MBlazeISelLowering.cpp index ba2de40..62dfdcc 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); diff --git a/lib/Target/MBlaze/MBlazeInstrInfo.cpp b/lib/Target/MBlaze/MBlazeInstrInfo.cpp index 0bd62ac..188f10a 100644 --- a/lib/Target/MBlaze/MBlazeInstrInfo.cpp +++ b/lib/Target/MBlaze/MBlazeInstrInfo.cpp @@ -14,15 +14,15 @@ #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 -#define GET_INSTRINFO_MC_DESC #include "MBlazeGenInstrInfo.inc" using namespace llvm; diff --git a/lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp b/lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp index 7e4a2f5..32d67b2 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 c573d4a..ddc636d 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 MCInstrDesc &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 441ece1..f0b201a 100644 --- a/lib/Target/MBlaze/MBlazeRegisterInfo.cpp +++ b/lib/Target/MBlaze/MBlazeRegisterInfo.cpp @@ -37,7 +37,6 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" -#define GET_REGINFO_MC_DESC #define GET_REGINFO_TARGET_DESC #include "MBlazeGenRegisterInfo.inc" diff --git a/lib/Target/MBlaze/MBlazeSubtarget.cpp b/lib/Target/MBlaze/MBlazeSubtarget.cpp index 81578ce..eda141d 100644 --- a/lib/Target/MBlaze/MBlazeSubtarget.cpp +++ b/lib/Target/MBlaze/MBlazeSubtarget.cpp @@ -15,10 +15,10 @@ #include "MBlaze.h" #include "MBlazeRegisterInfo.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Target/TargetRegistry.h" -#define GET_SUBTARGETINFO_CTOR -#define GET_SUBTARGETINFO_MC_DESC #define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR #include "MBlazeGenSubtargetInfo.inc" using namespace llvm; @@ -26,7 +26,7 @@ using namespace llvm; MBlazeSubtarget::MBlazeSubtarget(const std::string &TT, const std::string &CPU, const std::string &FS): - MBlazeGenSubtargetInfo(), + MBlazeGenSubtargetInfo(TT, CPU, FS), HasBarrel(false), HasDiv(false), HasMul(false), HasPatCmp(false), HasFPU(false), HasMul64(false), HasSqrt(false) { @@ -34,7 +34,7 @@ MBlazeSubtarget::MBlazeSubtarget(const std::string &TT, std::string CPUName = CPU; if (CPUName.empty()) CPUName = "mblaze"; - ParseSubtargetFeatures(FS, CPUName); + 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). @@ -61,4 +61,3 @@ enablePostRAScheduler(CodeGenOpt::Level OptLevel, 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 7d70040..43b0197 100644 --- a/lib/Target/MBlaze/MBlazeSubtarget.h +++ b/lib/Target/MBlaze/MBlazeSubtarget.h @@ -22,6 +22,7 @@ #include "MBlazeGenSubtargetInfo.inc" namespace llvm { +class StringRef; class MBlazeSubtarget : public MBlazeGenSubtargetInfo { @@ -46,7 +47,7 @@ public: /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - void 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. diff --git a/lib/Target/MBlaze/MBlazeTargetMachine.cpp b/lib/Target/MBlaze/MBlazeTargetMachine.cpp index 1cbd2d4..7208874 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); @@ -81,7 +69,7 @@ extern "C" void LLVMInitializeMBlazeTarget() { MBlazeTargetMachine:: MBlazeTargetMachine(const Target &T, const std::string &TT, const std::string &CPU, const std::string &FS): - LLVMTargetMachine(T, TT), + LLVMTargetMachine(T, TT, CPU, FS), Subtarget(TT, CPU, FS), DataLayout("E-p:32:32:32-i8:8:8-i16:16:16"), InstrInfo(*this), diff --git a/lib/Target/MBlaze/MCTargetDesc/CMakeLists.txt b/lib/Target/MBlaze/MCTargetDesc/CMakeLists.txt new file mode 100644 index 0000000..3d15708 --- /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 1467141..0d88466 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 e68dd58..e68dd58 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 0000000..20d6c0b --- /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 0000000..b14772e --- /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 0000000..71075ff --- /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 829122f..83c2a7d 100644 --- a/lib/Target/MBlaze/Makefile +++ b/lib/Target/MBlaze/Makefile @@ -18,7 +18,7 @@ BUILT_SOURCES = MBlazeGenRegisterInfo.inc MBlazeGenInstrInfo.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 9d156e7..33f3d44 100644 --- a/lib/Target/MSP430/CMakeLists.txt +++ b/lib/Target/MSP430/CMakeLists.txt @@ -13,7 +13,6 @@ add_llvm_target(MSP430CodeGen MSP430ISelLowering.cpp MSP430InstrInfo.cpp MSP430FrameLowering.cpp - MSP430MCAsmInfo.cpp MSP430RegisterInfo.cpp MSP430Subtarget.cpp MSP430TargetMachine.cpp @@ -24,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 63860dc..50d98b7 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 0000000..0f3ebd3 --- /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 3f44944..ad7d380 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 f3138a2..f3138a2 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 0000000..43a704d --- /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 0000000..0d8a6bd --- /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 0000000..bb85799 --- /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 854d4e4..4574ce5 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,17 +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. -#define GET_REGINFO_ENUM -#include "MSP430GenRegisterInfo.inc" - -// Defines symbolic names for the MSP430 instructions. -#define GET_INSTRINFO_ENUM -#include "MSP430GenInstrInfo.inc" - #endif diff --git a/lib/Target/MSP430/MSP430AsmPrinter.cpp b/lib/Target/MSP430/MSP430AsmPrinter.cpp index 5264d68..2042056 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 3738a98..846d093 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.cpp +++ b/lib/Target/MSP430/MSP430InstrInfo.cpp @@ -20,10 +20,10 @@ #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 -#define GET_INSTRINFO_MC_DESC #include "MSP430GenInstrInfo.inc" using namespace llvm; diff --git a/lib/Target/MSP430/MSP430RegisterInfo.cpp b/lib/Target/MSP430/MSP430RegisterInfo.cpp index da0c3c6..1cc60bb 100644 --- a/lib/Target/MSP430/MSP430RegisterInfo.cpp +++ b/lib/Target/MSP430/MSP430RegisterInfo.cpp @@ -26,7 +26,6 @@ #include "llvm/ADT/BitVector.h" #include "llvm/Support/ErrorHandling.h" -#define GET_REGINFO_MC_DESC #define GET_REGINFO_TARGET_DESC #include "MSP430GenRegisterInfo.inc" diff --git a/lib/Target/MSP430/MSP430Subtarget.cpp b/lib/Target/MSP430/MSP430Subtarget.cpp index bd8d7cd..b58c50a 100644 --- a/lib/Target/MSP430/MSP430Subtarget.cpp +++ b/lib/Target/MSP430/MSP430Subtarget.cpp @@ -13,19 +13,20 @@ #include "MSP430Subtarget.h" #include "MSP430.h" +#include "llvm/Target/TargetRegistry.h" -#define GET_SUBTARGETINFO_CTOR -#define GET_SUBTARGETINFO_MC_DESC #define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR #include "MSP430GenSubtargetInfo.inc" using namespace llvm; MSP430Subtarget::MSP430Subtarget(const std::string &TT, - const std::string &CPUIgnored, - const std::string &FS) { - std::string CPU = "generic"; + 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 ead213b..1ce5f11 100644 --- a/lib/Target/MSP430/MSP430Subtarget.h +++ b/lib/Target/MSP430/MSP430Subtarget.h @@ -22,6 +22,7 @@ #include <string> namespace llvm { +class StringRef; class MSP430Subtarget : public MSP430GenSubtargetInfo { bool ExtendedInsts; @@ -34,7 +35,7 @@ public: /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - void 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 3ee5e6a..971f512 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,13 @@ 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), + : 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"), diff --git a/lib/Target/MSP430/Makefile b/lib/Target/MSP430/Makefile index 30a4e49..82216ed 100644 --- a/lib/Target/MSP430/Makefile +++ b/lib/Target/MSP430/Makefile @@ -17,7 +17,7 @@ BUILT_SOURCES = MSP430GenRegisterInfo.inc MSP430GenInstrInfo.inc \ MSP430GenDAGISel.inc MSP430GenCallingConv.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 2c35c36..36ab1a9 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -16,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 @@ -24,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 0000000..8852fd4 --- /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 0000000..63e38ef --- /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 0000000..41c1dd3 --- /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 0000000..680208e --- /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 0000000..97de75d --- /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 0000000..7fe2086 --- /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 97ed878..5d92425 100644 --- a/lib/Target/Mips/MipsMCAsmInfo.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp @@ -12,9 +12,15 @@ //===----------------------------------------------------------------------===// #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.2byte\t"; Data32bitsDirective = "\t.4byte\t"; @@ -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 41b7192..41b7192 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 0000000..06f0d0b --- /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 0000000..3d18f11 --- /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 eafcc4a..cc4a8ae 100644 --- a/lib/Target/Mips/Makefile +++ b/lib/Target/Mips/Makefile @@ -13,11 +13,11 @@ TARGET = Mips # Make sure that tblgen is run, first thing. BUILT_SOURCES = MipsGenRegisterInfo.inc MipsGenInstrInfo.inc \ - MipsGenAsmWriter.inc \ + MipsGenAsmWriter.inc \ MipsGenDAGISel.inc MipsGenCallingConv.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 738b48c..984b5ad 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,18 +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. -#define GET_REGINFO_ENUM -#include "MipsGenRegisterInfo.inc" - -// Defines symbolic names for the Mips instructions. -#define GET_INSTRINFO_ENUM -#include "MipsGenInstrInfo.inc" - #endif diff --git a/lib/Target/Mips/Mips.td b/lib/Target/Mips/Mips.td index b79016d..433cd57 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 78f69ea..69e03bd 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -13,25 +13,25 @@ //===----------------------------------------------------------------------===// #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" @@ -42,63 +42,20 @@ 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>(); - } - - virtual const char *getPassName() const { - return "Mips Assembly Printer"; - } - - 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, - 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); - - if (MI->isDebugValue()) - PrintDebugValueComment(MI, OS); - - 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); - - virtual void EmitFunctionEntryLabel(); - void EmitStartOfAsmFile(Module &M); - virtual MachineLocation getDebugValueLocation(const MachineInstr *MI) const; +void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { + SmallString<128> Str; + raw_svector_ostream OS(Str); - void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); - }; -} // 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); +} //===----------------------------------------------------------------------===// // @@ -214,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. @@ -325,7 +282,7 @@ bool MipsAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, const MachineOperand &MO = MI->getOperand(OpNum); assert(MO.isReg() && "unexpected inline asm memory operand"); - O << "0($" << MipsAsmPrinter::getRegisterName(MO.getReg()) << ")"; + O << "0($" << MipsInstPrinter::getRegisterName(MO.getReg()) << ")"; return false; } @@ -351,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: @@ -405,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); @@ -466,7 +424,17 @@ void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, } // 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 0000000..16461ff --- /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/MipsEmitGPRestore.cpp b/lib/Target/Mips/MipsEmitGPRestore.cpp index f49d490..03d922f 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/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index 5f0c7e0..90aaeb6 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -113,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); @@ -200,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; @@ -230,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)); @@ -264,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; @@ -294,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); diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 9e47a38..b4f4b1b 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" @@ -145,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); @@ -774,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); @@ -785,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 @@ -798,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); @@ -910,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); @@ -923,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 @@ -938,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); @@ -1027,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); @@ -1046,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); @@ -1143,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); @@ -1159,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); diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index 7d39be2..0a7a7f2 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -14,13 +14,14 @@ #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 -#define GET_INSTRINFO_MC_DESC #include "MipsGenInstrInfo.inc" using namespace llvm; @@ -29,6 +30,11 @@ MipsInstrInfo::MipsInstrInfo(MipsTargetMachine &tm) : 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; } @@ -43,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(); } } @@ -64,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(); } } @@ -164,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!"); @@ -198,20 +204,20 @@ 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!"); diff --git a/lib/Target/Mips/MipsInstrInfo.h b/lib/Target/Mips/MipsInstrInfo.h index d02fdc1..4421c48 100644 --- a/lib/Target/Mips/MipsInstrInfo.h +++ b/lib/Target/Mips/MipsInstrInfo.h @@ -25,100 +25,9 @@ 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 @@ -177,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 diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index 0651322..d1a0587 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -134,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. @@ -351,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 @@ -419,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< @@ -680,13 +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:stackloc}">; +def DynAlloc : EffectiveAddress<"addiu\t$dst, $addr">; // MADD*/MSUB* def MADD : MArithR<0, "madd", MipsMAdd, 1>; diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp new file mode 100644 index 0000000..f5cc3aa --- /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 0000000..ec5201b --- /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 0000000..9a2bdae --- /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 0000000..3e69596 --- /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/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index 202a1d4..24390da 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -37,7 +37,6 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Analysis/DebugInfo.h" -#define GET_REGINFO_MC_DESC #define GET_REGINFO_TARGET_DESC #include "MipsGenRegisterInfo.inc" @@ -218,51 +217,31 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, else Offset = spOffset + stackSize; - if (MI.isDebugValue()) { - MI.getOperand(i).ChangeToRegister(FrameReg, false /*isDef*/); - MI.getOperand(i+1).ChangeToImmediate(Offset); - return; - } - - Offset += MI.getOperand(i-1).getImm(); + Offset += MI.getOperand(i+1).getImm(); DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n"); - unsigned NewReg = 0; - int NewImm = 0; - MachineBasicBlock &MBB = *MI.getParent(); - bool ATUsed; - - // 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(); + // 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:: diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp index a96f872..6eee333 100644 --- a/lib/Target/Mips/MipsSubtarget.cpp +++ b/lib/Target/Mips/MipsSubtarget.cpp @@ -13,17 +13,17 @@ #include "MipsSubtarget.h" #include "Mips.h" +#include "llvm/Target/TargetRegistry.h" -#define GET_SUBTARGETINFO_CTOR -#define GET_SUBTARGETINFO_MC_DESC #define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR #include "MipsGenSubtargetInfo.inc" using namespace llvm; MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, const std::string &FS, bool little) : - MipsGenSubtargetInfo(), + 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), @@ -35,7 +35,7 @@ MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, MipsArchVersion = Mips1; // Parse features string. - ParseSubtargetFeatures(FS, CPUName); + ParseSubtargetFeatures(CPUName, FS); // Initialize scheduling itinerary for the specified CPU. InstrItins = getInstrItineraryForCPU(CPUName); diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index ae76470..533d4af 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -22,6 +22,7 @@ #include "MipsGenSubtargetInfo.inc" namespace llvm { +class StringRef; class MipsSubtarget : public MipsGenSubtargetInfo { @@ -99,7 +100,7 @@ public: /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - void 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 88ce3b8..20b9f4e 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 @@ -37,7 +34,7 @@ MipsTargetMachine:: MipsTargetMachine(const Target &T, const std::string &TT, const std::string &CPU, const std::string &FS, bool isLittle=false): - LLVMTargetMachine(T, TT), + 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") : diff --git a/lib/Target/PTX/CMakeLists.txt b/lib/Target/PTX/CMakeLists.txt index 0e138c0..ce08916 100644 --- a/lib/Target/PTX/CMakeLists.txt +++ b/lib/Target/PTX/CMakeLists.txt @@ -13,7 +13,6 @@ add_llvm_target(PTXCodeGen PTXISelLowering.cpp PTXInstrInfo.cpp PTXFrameLowering.cpp - PTXMCAsmInfo.cpp PTXMCAsmStreamer.cpp PTXMFInfoExtract.cpp PTXRegisterInfo.cpp @@ -22,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 0000000..df0f63f --- /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 0000000..35f5a7b --- /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 b670abd..efefead 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 03f5d66..03f5d66 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 0000000..23f70bd --- /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 0000000..1003b0b --- /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 da3f915..93dd38a 100644 --- a/lib/Target/PTX/Makefile +++ b/lib/Target/PTX/Makefile @@ -19,6 +19,6 @@ BUILT_SOURCES = PTXGenAsmWriter.inc \ PTXGenRegisterInfo.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 6aaf068..28cab24 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,16 +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. -#define GET_REGINFO_ENUM -#include "PTXGenRegisterInfo.inc" - -// Defines symbolic names for the PTX instructions. -#define GET_INSTRINFO_ENUM -#include "PTXGenInstrInfo.inc" - #endif // PTX_H diff --git a/lib/Target/PTX/PTXISelLowering.cpp b/lib/Target/PTX/PTXISelLowering.cpp index 7831aa0..6fcf710 100644 --- a/lib/Target/PTX/PTXISelLowering.cpp +++ b/lib/Target/PTX/PTXISelLowering.cpp @@ -184,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::RegPredRegisterClass), - argmap_entry(MVT::i16, PTX::RegI16RegisterClass), - argmap_entry(MVT::i32, PTX::RegI32RegisterClass), - argmap_entry(MVT::i64, PTX::RegI64RegisterClass), - argmap_entry(MVT::f32, PTX::RegF32RegisterClass), - argmap_entry(MVT::f64, PTX::RegF64RegisterClass) -}; -} // end anonymous namespace - SDValue PTXTargetLowering:: LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, diff --git a/lib/Target/PTX/PTXInstrInfo.cpp b/lib/Target/PTX/PTXInstrInfo.cpp index 7f0fa8b..425265a 100644 --- a/lib/Target/PTX/PTXInstrInfo.cpp +++ b/lib/Target/PTX/PTXInstrInfo.cpp @@ -18,11 +18,11 @@ #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" #define GET_INSTRINFO_CTOR -#define GET_INSTRINFO_MC_DESC #include "PTXGenInstrInfo.inc" using namespace llvm; diff --git a/lib/Target/PTX/PTXMCAsmStreamer.cpp b/lib/Target/PTX/PTXMCAsmStreamer.cpp index 1574670..b13a3da 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/PTXRegisterInfo.cpp b/lib/Target/PTX/PTXRegisterInfo.cpp index f32c2b7..cb56ea9 100644 --- a/lib/Target/PTX/PTXRegisterInfo.cpp +++ b/lib/Target/PTX/PTXRegisterInfo.cpp @@ -17,7 +17,6 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -#define GET_REGINFO_MC_DESC #define GET_REGINFO_TARGET_DESC #include "PTXGenRegisterInfo.inc" diff --git a/lib/Target/PTX/PTXSubtarget.cpp b/lib/Target/PTX/PTXSubtarget.cpp index 5eff24a..8ec646e 100644 --- a/lib/Target/PTX/PTXSubtarget.cpp +++ b/lib/Target/PTX/PTXSubtarget.cpp @@ -12,18 +12,19 @@ //===----------------------------------------------------------------------===// #include "PTXSubtarget.h" +#include "PTX.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetRegistry.h" -#define GET_SUBTARGETINFO_CTOR -#define GET_SUBTARGETINFO_MC_DESC #define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR #include "PTXGenSubtargetInfo.inc" using namespace llvm; PTXSubtarget::PTXSubtarget(const std::string &TT, const std::string &CPU, const std::string &FS, bool is64Bit) - : PTXGenSubtargetInfo(), + : PTXGenSubtargetInfo(TT, CPU, FS), PTXTarget(PTX_COMPUTE_1_0), PTXVersion(PTX_VERSION_2_0), SupportsDouble(false), @@ -32,7 +33,7 @@ PTXSubtarget::PTXSubtarget(const std::string &TT, const std::string &CPU, std::string TARGET = CPU; if (TARGET.empty()) TARGET = "generic"; - ParseSubtargetFeatures(FS, TARGET); + ParseSubtargetFeatures(TARGET, FS); } std::string PTXSubtarget::getTargetString() const { diff --git a/lib/Target/PTX/PTXSubtarget.h b/lib/Target/PTX/PTXSubtarget.h index 913f0a2..0921f1f 100644 --- a/lib/Target/PTX/PTXSubtarget.h +++ b/lib/Target/PTX/PTXSubtarget.h @@ -20,6 +20,8 @@ #include "PTXGenSubtargetInfo.inc" namespace llvm { +class StringRef; + class PTXSubtarget : public PTXGenSubtargetInfo { public: @@ -112,8 +114,7 @@ namespace llvm { (PTXTarget >= PTX_COMPUTE_2_0 && PTXTarget < PTX_LAST_COMPUTE); } - void ParseSubtargetFeatures(const std::string &FS, - const std::string &CPU); + 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 ef648c6..ab926e0 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); } @@ -55,7 +51,7 @@ PTXTargetMachine::PTXTargetMachine(const Target &T, const std::string &CPU, const std::string &FS, bool is64Bit) - : LLVMTargetMachine(T, TT), + : LLVMTargetMachine(T, TT, CPU, FS), DataLayout(is64Bit ? DataLayout64 : DataLayout32), Subtarget(TT, CPU, FS, is64Bit), FrameLowering(Subtarget), diff --git a/lib/Target/PowerPC/CMakeLists.txt b/lib/Target/PowerPC/CMakeLists.txt index be1b525..d1dda37 100644 --- a/lib/Target/PowerPC/CMakeLists.txt +++ b/lib/Target/PowerPC/CMakeLists.txt @@ -20,7 +20,6 @@ add_llvm_target(PowerPCCodeGen PPCISelLowering.cpp PPCFrameLowering.cpp PPCJITInfo.cpp - PPCMCAsmInfo.cpp PPCMCCodeEmitter.cpp PPCMCInstLower.cpp PPCPredicates.cpp @@ -32,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 adfa0aa..d022a44 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 0000000..a1b8166 --- /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 0000000..9db6662 --- /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 2d5c880..b6dca83 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 96ae6fb..96ae6fb 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 0000000..02b887f --- /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 0000000..cee2350 --- /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 11abb97..1617b26 100644 --- a/lib/Target/PowerPC/Makefile +++ b/lib/Target/PowerPC/Makefile @@ -18,6 +18,6 @@ BUILT_SOURCES = PPCGenRegisterInfo.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 55852e6..7191dd1 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,15 +82,4 @@ namespace llvm { } // end namespace llvm; -// 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" - #endif diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp index b795db9..9de2200 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/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index b44b6c3..9741a39 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); @@ -1321,9 +1323,6 @@ SDValue PPCTargetLowering::LowerVAARG(SDValue Op, SelectionDAG &DAG, SDValue CC = DAG.getSetCC(dl, MVT::i32, VT.isInteger() ? GprIndex : FprIndex, DAG.getConstant(8, MVT::i32), ISD::SETLT); - SDValue Area = DAG.getNode(ISD::SELECT, dl, MVT::i32, CC, RegSaveArea, - OverflowArea); - // adjustment constant gpr_index * 4/8 SDValue RegConstant = DAG.getNode(ISD::MUL, dl, MVT::i32, VT.isInteger() ? GprIndex : FprIndex, diff --git a/lib/Target/PowerPC/PPCInstrInfo.cpp b/lib/Target/PowerPC/PPCInstrInfo.cpp index 5b740b9..143444f 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -12,24 +12,25 @@ //===----------------------------------------------------------------------===// #include "PPCInstrInfo.h" +#include "PPC.h" #include "PPCInstrBuilder.h" #include "PPCMachineFunctionInfo.h" #include "PPCPredicates.h" #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 -#define GET_INSTRINFO_MC_DESC #include "PPCGenInstrInfo.inc" namespace llvm { diff --git a/lib/Target/PowerPC/PPCMCCodeEmitter.cpp b/lib/Target/PowerPC/PPCMCCodeEmitter.cpp index 65c2c82..cf73d86 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 db139da..9c2428b 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -44,7 +44,6 @@ #include "llvm/ADT/STLExtras.h" #include <cstdlib> -#define GET_REGINFO_MC_DESC #define GET_REGINFO_TARGET_DESC #include "PPCGenRegisterInfo.inc" diff --git a/lib/Target/PowerPC/PPCSubtarget.cpp b/lib/Target/PowerPC/PPCSubtarget.cpp index 75ee1c0..5ea9b0f 100644 --- a/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/lib/Target/PowerPC/PPCSubtarget.cpp @@ -15,11 +15,11 @@ #include "PPC.h" #include "llvm/GlobalValue.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegistry.h" #include <cstdlib> -#define GET_SUBTARGETINFO_CTOR -#define GET_SUBTARGETINFO_MC_DESC #define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR #include "PPCGenSubtargetInfo.inc" using namespace llvm; @@ -64,7 +64,7 @@ static const char *GetCurrentPowerPCCPU() { PPCSubtarget::PPCSubtarget(const std::string &TT, const std::string &CPU, const std::string &FS, bool is64Bit) - : PPCGenSubtargetInfo() + : PPCGenSubtargetInfo(TT, CPU, FS) , StackAlignment(16) , DarwinDirective(PPC::DIR_NONE) , IsGigaProcessor(false) @@ -88,7 +88,7 @@ PPCSubtarget::PPCSubtarget(const std::string &TT, const std::string &CPU, #endif // Parse features string. - ParseSubtargetFeatures(FS, CPUName); + ParseSubtargetFeatures(CPUName, FS); // Initialize scheduling itinerary for the specified CPU. InstrItins = getInstrItineraryForCPU(CPUName); diff --git a/lib/Target/PowerPC/PPCSubtarget.h b/lib/Target/PowerPC/PPCSubtarget.h index 33b21db..e028de6 100644 --- a/lib/Target/PowerPC/PPCSubtarget.h +++ b/lib/Target/PowerPC/PPCSubtarget.h @@ -26,6 +26,7 @@ #undef PPC namespace llvm { +class StringRef; namespace PPC { // -m directive values. @@ -80,8 +81,7 @@ public: /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - void 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. @@ -106,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 09fc1e3..e0ea5ad 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); @@ -69,7 +56,7 @@ 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), + : LLVMTargetMachine(T, TT, CPU, FS), Subtarget(TT, CPU, FS, is64Bit), DataLayout(Subtarget.getTargetDataString()), InstrInfo(*this), FrameLowering(Subtarget), JITInfo(*this, is64Bit), diff --git a/lib/Target/README.txt b/lib/Target/README.txt index 4e382e8..4cc9534 100644 --- a/lib/Target/README.txt +++ b/lib/Target/README.txt @@ -1762,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 [ @@ -1783,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 e1f54fb..c77ded4 100644 --- a/lib/Target/Sparc/CMakeLists.txt +++ b/lib/Target/Sparc/CMakeLists.txt @@ -15,7 +15,6 @@ add_llvm_target(SparcCodeGen SparcISelDAGToDAG.cpp SparcISelLowering.cpp SparcFrameLowering.cpp - SparcMCAsmInfo.cpp SparcRegisterInfo.cpp SparcSubtarget.cpp SparcTargetMachine.cpp @@ -23,3 +22,4 @@ add_llvm_target(SparcCodeGen ) add_subdirectory(TargetInfo) +add_subdirectory(MCTargetDesc) diff --git a/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt b/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt new file mode 100644 index 0000000..1e8c029 --- /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 0000000..abcbe2d --- /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 d37d6d2..6a7e090 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 0cb6827..0cb6827 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 0000000..cb92a2b --- /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 0000000..2fd9e3f --- /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 89f5053..4b81ada 100644 --- a/lib/Target/Sparc/Makefile +++ b/lib/Target/Sparc/Makefile @@ -16,7 +16,7 @@ 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 d68535b..7b2c614 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,23 +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. -// -#define GET_REGINFO_ENUM -#include "SparcGenRegisterInfo.inc" - -// Defines symbolic names for the Sparc instructions. -// -#define GET_INSTRINFO_ENUM -#include "SparcGenInstrInfo.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 a2bda6c..6f30d3f 100644 --- a/lib/Target/Sparc/SparcISelLowering.cpp +++ b/lib/Target/Sparc/SparcISelLowering.cpp @@ -754,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); diff --git a/lib/Target/Sparc/SparcInstrInfo.cpp b/lib/Target/Sparc/SparcInstrInfo.cpp index 17a41f2..4e3ddf8 100644 --- a/lib/Target/Sparc/SparcInstrInfo.cpp +++ b/lib/Target/Sparc/SparcInstrInfo.cpp @@ -12,17 +12,17 @@ //===----------------------------------------------------------------------===// #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 "SparcMachineFunctionInfo.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #define GET_INSTRINFO_CTOR -#define GET_INSTRINFO_MC_DESC #include "SparcGenInstrInfo.inc" using namespace llvm; diff --git a/lib/Target/Sparc/SparcRegisterInfo.cpp b/lib/Target/Sparc/SparcRegisterInfo.cpp index 3b0b5fa..0acdd2c 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.cpp +++ b/lib/Target/Sparc/SparcRegisterInfo.cpp @@ -24,7 +24,6 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" -#define GET_REGINFO_MC_DESC #define GET_REGINFO_TARGET_DESC #include "SparcGenRegisterInfo.inc" diff --git a/lib/Target/Sparc/SparcSubtarget.cpp b/lib/Target/Sparc/SparcSubtarget.cpp index ee3cc03..de647e8 100644 --- a/lib/Target/Sparc/SparcSubtarget.cpp +++ b/lib/Target/Sparc/SparcSubtarget.cpp @@ -12,17 +12,18 @@ //===----------------------------------------------------------------------===// #include "SparcSubtarget.h" +#include "Sparc.h" +#include "llvm/Target/TargetRegistry.h" -#define GET_SUBTARGETINFO_CTOR -#define GET_SUBTARGETINFO_MC_DESC #define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR #include "SparcGenSubtargetInfo.inc" using namespace llvm; SparcSubtarget::SparcSubtarget(const std::string &TT, const std::string &CPU, const std::string &FS, bool is64Bit) : - SparcGenSubtargetInfo(), + SparcGenSubtargetInfo(TT, CPU, FS), IsV9(false), V8DeprecatedInsts(false), IsVIS(false), @@ -39,5 +40,5 @@ SparcSubtarget::SparcSubtarget(const std::string &TT, const std::string &CPU, IsV9 = CPUName == "v9"; // Parse features string. - ParseSubtargetFeatures(FS, CPUName); + ParseSubtargetFeatures(CPUName, FS); } diff --git a/lib/Target/Sparc/SparcSubtarget.h b/lib/Target/Sparc/SparcSubtarget.h index 257f22a..00a04c3 100644 --- a/lib/Target/Sparc/SparcSubtarget.h +++ b/lib/Target/Sparc/SparcSubtarget.h @@ -21,6 +21,7 @@ #include "SparcGenSubtargetInfo.inc" namespace llvm { +class StringRef; class SparcSubtarget : public SparcGenSubtargetInfo { bool IsV9; @@ -38,7 +39,7 @@ public: /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - void 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 792dd94..cbe6d87 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,10 +20,6 @@ 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 @@ -32,7 +27,7 @@ extern "C" void LLVMInitializeSparcTarget() { SparcTargetMachine::SparcTargetMachine(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), Subtarget(TT, CPU, FS, is64bit), DataLayout(Subtarget.getDataLayout()), TLInfo(*this), TSInfo(*this), InstrInfo(Subtarget), diff --git a/lib/Target/SystemZ/CMakeLists.txt b/lib/Target/SystemZ/CMakeLists.txt index 12206b9..f4bdbd8 100644 --- a/lib/Target/SystemZ/CMakeLists.txt +++ b/lib/Target/SystemZ/CMakeLists.txt @@ -13,7 +13,6 @@ add_llvm_target(SystemZCodeGen SystemZISelLowering.cpp SystemZInstrInfo.cpp SystemZFrameLowering.cpp - SystemZMCAsmInfo.cpp SystemZRegisterInfo.cpp SystemZSubtarget.cpp SystemZTargetMachine.cpp @@ -21,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 0000000..2ac9016 --- /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 0000000..08f1a9d --- /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 2dc7e7b..8540546 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 a6a27e2..a6a27e2 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 0000000..5a826a6 --- /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 0000000..e2ad5af --- /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 fa59dc6..6356491 100644 --- a/lib/Target/SystemZ/Makefile +++ b/lib/Target/SystemZ/Makefile @@ -16,7 +16,7 @@ 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 84d83c0..88960b9 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,17 +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. -#define GET_REGINFO_ENUM -#include "SystemZGenRegisterInfo.inc" - -// Defines symbolic names for the SystemZ instructions. -#define GET_INSTRINFO_ENUM -#include "SystemZGenInstrInfo.inc" - #endif diff --git a/lib/Target/SystemZ/SystemZISelLowering.cpp b/lib/Target/SystemZ/SystemZISelLowering.cpp index af85df5..871c297 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/SystemZInstrInfo.cpp b/lib/Target/SystemZ/SystemZInstrInfo.cpp index fae9a6a..99e2730 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -21,10 +21,10 @@ #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 -#define GET_INSTRINFO_MC_DESC #include "SystemZGenInstrInfo.inc" using namespace llvm; diff --git a/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/lib/Target/SystemZ/SystemZRegisterInfo.cpp index 21421a9..59692e8 100644 --- a/lib/Target/SystemZ/SystemZRegisterInfo.cpp +++ b/lib/Target/SystemZ/SystemZRegisterInfo.cpp @@ -26,7 +26,6 @@ #include "llvm/Target/TargetOptions.h" #include "llvm/ADT/BitVector.h" -#define GET_REGINFO_MC_DESC #define GET_REGINFO_TARGET_DESC #include "SystemZGenRegisterInfo.inc" diff --git a/lib/Target/SystemZ/SystemZSubtarget.cpp b/lib/Target/SystemZ/SystemZSubtarget.cpp index 4388109..b3ed066 100644 --- a/lib/Target/SystemZ/SystemZSubtarget.cpp +++ b/lib/Target/SystemZ/SystemZSubtarget.cpp @@ -15,10 +15,10 @@ #include "SystemZ.h" #include "llvm/GlobalValue.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegistry.h" -#define GET_SUBTARGETINFO_CTOR -#define GET_SUBTARGETINFO_MC_DESC #define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR #include "SystemZGenSubtargetInfo.inc" using namespace llvm; @@ -26,13 +26,13 @@ using namespace llvm; SystemZSubtarget::SystemZSubtarget(const std::string &TT, const std::string &CPU, const std::string &FS): - SystemZGenSubtargetInfo(), HasZ10Insts(false) { + SystemZGenSubtargetInfo(TT, CPU, FS), HasZ10Insts(false) { std::string CPUName = CPU; if (CPUName.empty()) CPUName = "z9"; // Parse features string. - ParseSubtargetFeatures(FS, CPUName); + 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 6ac606a..55cfd80 100644 --- a/lib/Target/SystemZ/SystemZSubtarget.h +++ b/lib/Target/SystemZ/SystemZSubtarget.h @@ -22,6 +22,7 @@ namespace llvm { class GlobalValue; +class StringRef; class TargetMachine; class SystemZSubtarget : public SystemZGenSubtargetInfo { @@ -35,7 +36,7 @@ public: /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - void 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 3329ce6..48298cc 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,7 +16,6 @@ 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 @@ -26,7 +24,7 @@ SystemZTargetMachine::SystemZTargetMachine(const Target &T, const std::string &TT, const std::string &CPU, const std::string &FS) - : LLVMTargetMachine(T, TT), + : 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"), diff --git a/lib/Target/Target.cpp b/lib/Target/Target.cpp index 0919fe4..a42ce54 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 6fa5420..a97b0e8 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 1990bc7..17d022a 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/TargetLoweringObjectFile.cpp b/lib/Target/TargetLoweringObjectFile.cpp index 9f87c07..703431b 100644 --- a/lib/Target/TargetLoweringObjectFile.cpp +++ b/lib/Target/TargetLoweringObjectFile.cpp @@ -35,32 +35,32 @@ using namespace llvm; // Generic Code //===----------------------------------------------------------------------===// -TargetLoweringObjectFile::TargetLoweringObjectFile() : Ctx(0) { - TextSection = 0; - DataSection = 0; - BSSSection = 0; - ReadOnlySection = 0; - StaticCtorSection = 0; - StaticDtorSection = 0; - LSDASection = 0; - CompactUnwindSection = 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() { diff --git a/lib/Target/TargetMachine.cpp b/lib/Target/TargetMachine.cpp index 14044f2..74a1f4e 100644 --- a/lib/Target/TargetMachine.cpp +++ b/lib/Target/TargetMachine.cpp @@ -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/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index c352bfc..d45dd35 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 633d982..b112f9f 100644 --- a/lib/Target/X86/CMakeLists.txt +++ b/lib/Target/X86/CMakeLists.txt @@ -27,7 +27,6 @@ set(sources X86InstrInfo.cpp X86JITInfo.cpp X86MachObjectWriter.cpp - X86MCAsmInfo.cpp X86MCCodeEmitter.cpp X86MCInstLower.cpp X86RegisterInfo.cpp diff --git a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp index 53738b1..c37d879 100644 --- a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp +++ b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp @@ -15,8 +15,7 @@ #define DEBUG_TYPE "asm-printer" #include "X86ATTInstPrinter.h" #include "X86InstComments.h" -#include "X86Subtarget.h" -#include "MCTargetDesc/X86TargetDesc.h" +#include "MCTargetDesc/X86MCTargetDesc.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCExpr.h" @@ -31,11 +30,8 @@ using namespace llvm; #define PRINT_ALIAS_INSTR #include "X86GenAsmWriter.inc" -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 5f939b6..5426e5c 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 5461c83..4e28dfe 100644 --- a/lib/Target/X86/InstPrinter/X86InstComments.cpp +++ b/lib/Target/X86/InstPrinter/X86InstComments.cpp @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// #include "X86InstComments.h" -#include "MCTargetDesc/X86TargetDesc.h" +#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 411d832..506e26c 100644 --- a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp +++ b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp @@ -15,8 +15,7 @@ #define DEBUG_TYPE "asm-printer" #include "X86IntelInstPrinter.h" #include "X86InstComments.h" -#include "X86Subtarget.h" -#include "MCTargetDesc/X86TargetDesc.h" +#include "MCTargetDesc/X86MCTargetDesc.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCExpr.h" diff --git a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h index c8030c3..e84a194 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 index 50be61c..ca88f8f 100644 --- a/lib/Target/X86/MCTargetDesc/CMakeLists.txt +++ b/lib/Target/X86/MCTargetDesc/CMakeLists.txt @@ -1,2 +1,7 @@ -add_llvm_library(LLVMX86Desc X86TargetDesc.cpp) +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/X86MCAsmInfo.cpp b/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp index 2e1ec63..2703100 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 2cd4c8e..2cd4c8e 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 0000000..b77f37b --- /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 0000000..89ea22b --- /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/MCTargetDesc/X86TargetDesc.cpp b/lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp deleted file mode 100644 index c7c37f6..0000000 --- a/lib/Target/X86/MCTargetDesc/X86TargetDesc.cpp +++ /dev/null @@ -1,74 +0,0 @@ -//===-- X86TargetDesc.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 "X86TargetDesc.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 "X86GenRegisterInfo.inc" - -#define GET_INSTRINFO_MC_DESC -#include "X86GenInstrInfo.inc" - -#define GET_SUBTARGETINFO_MC_DESC -#include "X86GenSubtargetInfo.inc" - -using namespace llvm; - -MCInstrInfo *createX86MCInstrInfo() { - MCInstrInfo *X = new MCInstrInfo(); - InitX86MCInstrInfo(X); - return X; -} - -MCRegisterInfo *createX86MCRegisterInfo() { - MCRegisterInfo *X = new MCRegisterInfo(); - InitX86MCRegisterInfo(X); - return X; -} - -MCSubtargetInfo *createX86MCSubtargetInfo() { - MCSubtargetInfo *X = new MCSubtargetInfo(); - InitX86MCSubtargetInfo(X); - return X; -} - -// Force static initialization. -extern "C" void LLVMInitializeX86MCInstrInfo() { - RegisterMCInstrInfo<MCInstrInfo> X(TheX86_32Target); - RegisterMCInstrInfo<MCInstrInfo> Y(TheX86_64Target); - - TargetRegistry::RegisterMCInstrInfo(TheX86_32Target, createX86MCInstrInfo); - TargetRegistry::RegisterMCInstrInfo(TheX86_64Target, createX86MCInstrInfo); -} - -extern "C" void LLVMInitializeX86MCRegInfo() { - RegisterMCRegInfo<MCRegisterInfo> X(TheX86_32Target); - RegisterMCRegInfo<MCRegisterInfo> Y(TheX86_64Target); - - TargetRegistry::RegisterMCRegInfo(TheX86_32Target, createX86MCRegisterInfo); - TargetRegistry::RegisterMCRegInfo(TheX86_64Target, createX86MCRegisterInfo); -} - -extern "C" void LLVMInitializeX86MCSubtargetInfo() { - RegisterMCSubtargetInfo<MCSubtargetInfo> X(TheX86_32Target); - RegisterMCSubtargetInfo<MCSubtargetInfo> Y(TheX86_64Target); - - TargetRegistry::RegisterMCSubtargetInfo(TheX86_32Target, - createX86MCSubtargetInfo); - TargetRegistry::RegisterMCSubtargetInfo(TheX86_64Target, - createX86MCSubtargetInfo); -} diff --git a/lib/Target/X86/X86.h b/lib/Target/X86/X86.h index 9d66c2f..ec52dfb 100644 --- a/lib/Target/X86/X86.h +++ b/lib/Target/X86/X86.h @@ -15,7 +15,7 @@ #ifndef TARGET_X86_H #define TARGET_X86_H -#include "MCTargetDesc/X86TargetDesc.h" +#include "MCTargetDesc/X86MCTargetDesc.h" #include "llvm/Support/DataTypes.h" #include "llvm/Target/TargetMachine.h" @@ -23,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; @@ -58,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 &); diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td index 7bb9676..4ccb43f 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 4d7d96d..9b556a5 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 c2d53c4..99b4479 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/X86FloatingPoint.cpp b/lib/Target/X86/X86FloatingPoint.cpp index 463cde0..6eed6ab 100644 --- a/lib/Target/X86/X86FloatingPoint.cpp +++ b/lib/Target/X86/X86FloatingPoint.cpp @@ -884,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; @@ -1467,25 +1467,24 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) { } if (STUses && !isMask_32(STUses)) - report_fatal_error("Inline asm fixed input regs" - " must be last on the x87 stack"); + 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)) - report_fatal_error("Inline asm output regs" - " must be last on the x87 stack"); + 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)) - report_fatal_error("Inline asm clobbers must be last on the x87 stack"); + 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)) - report_fatal_error("Inline asm implicitly popped regs" - " must be last on the x87 stack"); + 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 " @@ -1501,7 +1500,7 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) { if (!Op.isReg() || Op.getReg() < X86::FP0 || Op.getReg() > X86::FP6) continue; if (!Op.isUse()) - report_fatal_error("Illegal \"f\" output constraint in inline asm"); + MI->emitError("illegal \"f\" output constraint"); unsigned FPReg = getFPReg(Op); FPUsed |= 1U << FPReg; diff --git a/lib/Target/X86/X86FrameLowering.cpp b/lib/Target/X86/X86FrameLowering.cpp index cd4e954..ed45a9a 100644 --- a/lib/Target/X86/X86FrameLowering.cpp +++ b/lib/Target/X86/X86FrameLowering.cpp @@ -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" @@ -1029,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 d71108c..14c31ed 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 cc8db35..2b0f283 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -192,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); @@ -547,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); @@ -596,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(); @@ -689,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: "; @@ -699,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! @@ -710,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; } @@ -725,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; } @@ -746,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; @@ -776,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; @@ -819,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); @@ -950,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; diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 4f8b90f..5096d9a 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); @@ -3832,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) { @@ -4459,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())) @@ -8916,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, @@ -9064,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 @@ -9225,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); @@ -9323,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: @@ -9457,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"; @@ -11808,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); @@ -11821,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(); } @@ -11852,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; @@ -11864,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(); @@ -12592,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': @@ -12889,30 +12958,30 @@ X86TargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, // 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) + 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) + else if (VT == MVT::i8 || VT == MVT::i1) return std::make_pair(0U, X86::GR8RegisterClass); - else if (VT == MVT::i64) + 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) + 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) + 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); @@ -12920,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 d9c883f..b603678 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, @@ -825,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/X86InstrFormats.td b/lib/Target/X86/X86InstrFormats.td index 7daa264..6d89bcc 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 7c9a9f7..b00109c 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 702331d..55b5835 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -36,7 +36,6 @@ #include <limits> #define GET_INSTRINFO_CTOR -#define GET_INSTRINFO_MC_DESC #include "X86GenInstrInfo.inc" using namespace llvm; @@ -301,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 }, @@ -411,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 }, @@ -425,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 }, @@ -787,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; @@ -808,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: @@ -926,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: @@ -1975,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 @@ -2064,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; } } @@ -2853,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) { @@ -2875,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; } @@ -3053,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.td b/lib/Target/X86/X86InstrInfo.td index 8cab808..7eb07b0 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 0bfc5e7..fe11d77 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 @@ -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)>; @@ -3660,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 @@ -3842,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)>; @@ -3870,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), @@ -3897,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)>; } //===----------------------------------------------------------------------===// @@ -5195,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/X86MCCodeEmitter.cpp b/lib/Target/X86/X86MCCodeEmitter.cpp index 04149e7..ce8ef49 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()); } @@ -126,16 +132,10 @@ public: } // 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); @@ -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 MCInstrDesc &Desc = TII.get(Opcode); + const MCInstrDesc &Desc = MCII.get(Opcode); uint64_t TSFlags = Desc.TSFlags; // Pseudo instructions don't get encoded. diff --git a/lib/Target/X86/X86MCInstLower.cpp b/lib/Target/X86/X86MCInstLower.cpp index 793156f..e385335 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/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index d32b822..f2faf59 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -40,7 +40,6 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/CommandLine.h" -#define GET_REGINFO_MC_DESC #define GET_REGINFO_TARGET_DESC #include "X86GenRegisterInfo.inc" @@ -107,8 +106,8 @@ int X86RegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const { /// 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) const { - switch (RegNum) { +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; @@ -730,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. diff --git a/lib/Target/X86/X86RegisterInfo.h b/lib/Target/X86/X86RegisterInfo.h index a09c7ee..a12eb12 100644 --- a/lib/Target/X86/X86RegisterInfo.h +++ b/lib/Target/X86/X86RegisterInfo.h @@ -83,7 +83,7 @@ public: /// 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) const; + int getCompactUnwindRegNum(unsigned RegNum, bool isEH) const; /// Code Generation virtual methods... /// diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp index a1e6d7b..5e6c659 100644 --- a/lib/Target/X86/X86Subtarget.cpp +++ b/lib/Target/X86/X86Subtarget.cpp @@ -21,9 +21,8 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/ADT/SmallVector.h" -#define GET_SUBTARGETINFO_CTOR -#define GET_SUBTARGETINFO_MC_DESC #define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR #include "X86GenSubtargetInfo.inc" using namespace llvm; @@ -158,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; } @@ -174,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 { @@ -248,51 +180,65 @@ 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 &CPU, const std::string &FS, - bool is64Bit, unsigned StackAlignOverride) - : X86GenSubtargetInfo() + unsigned StackAlignOverride, bool is64Bit) + : X86GenSubtargetInfo(TT, CPU, FS) , PICStyle(PICStyles::None) , X86SSELevel(NoMMXSSE) , X863DNowLevel(NoThreeDNow) @@ -312,40 +258,59 @@ X86Subtarget::X86Subtarget(const std::string &TT, const std::string &CPU, // FIXME: this is a known good value for Yonah. How about others? , MaxInlineSizeThreshold(128) , TargetTriple(TT) - , Is64Bit(is64Bit) { - + , In64BitMode(is64Bit) { // Determine default and user specified characteristics - if (!CPU.empty() || !FS.empty()) { - // If feature string is not empty, parse features string. + if (!FS.empty() || !CPU.empty()) { std::string CPUName = CPU; - if (CPUName.empty()) + if (CPUName.empty()) { +#if defined (__x86_64__) || defined(__i386__) CPUName = sys::getHostCPUName(); - ParseSubtargetFeatures(FS, CPUName); - // 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; +#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. + 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 @@ -353,6 +318,6 @@ X86Subtarget::X86Subtarget(const std::string &TT, const std::string &CPU, if (StackAlignOverride) stackAlignment = StackAlignOverride; else if (isTargetDarwin() || isTargetFreeBSD() || isTargetLinux() || - isTargetSolaris() || Is64Bit) + isTargetSolaris() || In64BitMode) stackAlignment = 16; } diff --git a/lib/Target/X86/X86Subtarget.h b/lib/Target/X86/X86Subtarget.h index d49b871..6d22027 100644 --- a/lib/Target/X86/X86Subtarget.h +++ b/lib/Target/X86/X86Subtarget.h @@ -24,6 +24,7 @@ namespace llvm { class GlobalValue; +class StringRef; class TargetMachine; /// PICStyles - The X86 backend supports a number of different styles of PIC. @@ -111,9 +112,8 @@ 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: @@ -121,8 +121,8 @@ public: /// of the specified triple. /// X86Subtarget(const std::string &TT, const std::string &CPU, - const std::string &FS, bool is64Bit, - unsigned StackAlignOverride); + 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 @@ -135,13 +135,13 @@ public: /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - void 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; } @@ -199,7 +199,7 @@ public: } bool isTargetWin64() const { - return Is64Bit && (isTargetMingw() || isTargetWindows()); + return In64BitMode && (isTargetMingw() || isTargetWindows()); } bool isTargetEnvMacho() const { @@ -207,7 +207,7 @@ public: } bool isTargetWin32() const { - return !Is64Bit && (isTargetMingw() || isTargetWindows()); + return !In64BitMode && (isTargetMingw() || isTargetWindows()); } bool isPICStyleSet() const { return PICStyle != PICStyles::None; } diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index 1b6fa30..9cab0e0 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, @@ -119,8 +98,8 @@ X86_64TargetMachine::X86_64TargetMachine(const Target &T, const std::string &TT, X86TargetMachine::X86TargetMachine(const Target &T, const std::string &TT, const std::string &CPU, const std::string &FS, bool is64Bit) - : LLVMTargetMachine(T, TT), - Subtarget(TT, CPU, FS, is64Bit, StackAlignmentOverride), + : LLVMTargetMachine(T, TT, CPU, FS), + Subtarget(TT, CPU, FS, StackAlignmentOverride, is64Bit), FrameLowering(*this, Subtarget), ELFWriterInfo(is64Bit, true) { DefRelocModel = getRelocationModel(); diff --git a/lib/Target/XCore/CMakeLists.txt b/lib/Target/XCore/CMakeLists.txt index 59c7f51..a1d73c6 100644 --- a/lib/Target/XCore/CMakeLists.txt +++ b/lib/Target/XCore/CMakeLists.txt @@ -13,7 +13,6 @@ add_llvm_target(XCoreCodeGen XCoreInstrInfo.cpp XCoreISelDAGToDAG.cpp XCoreISelLowering.cpp - XCoreMCAsmInfo.cpp XCoreRegisterInfo.cpp XCoreSubtarget.cpp XCoreTargetMachine.cpp @@ -22,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 0000000..c3b3dc9 --- /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 0000000..de61543 --- /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 42ab1b3..42ab1b3 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 8403922..8403922 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 0000000..939d97c --- /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 0000000..3cfc376 --- /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 a9d9fee..b823c4e 100644 --- a/lib/Target/XCore/Makefile +++ b/lib/Target/XCore/Makefile @@ -17,7 +17,7 @@ BUILT_SOURCES = XCoreGenRegisterInfo.inc XCoreGenInstrInfo.inc \ XCoreGenDAGISel.inc XCoreGenCallingConv.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 ec4ab91..b8fb0ca 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,19 +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. -// -#define GET_REGINFO_ENUM -#include "XCoreGenRegisterInfo.inc" - -// Defines symbolic names for the XCore instructions. -// -#define GET_INSTRINFO_ENUM -#include "XCoreGenInstrInfo.inc" - #endif diff --git a/lib/Target/XCore/XCoreAsmPrinter.cpp b/lib/Target/XCore/XCoreAsmPrinter.cpp index 6df8ce0..1a43714 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" diff --git a/lib/Target/XCore/XCoreInstrInfo.cpp b/lib/Target/XCore/XCoreInstrInfo.cpp index c39571d..f90481f 100644 --- a/lib/Target/XCore/XCoreInstrInfo.cpp +++ b/lib/Target/XCore/XCoreInstrInfo.cpp @@ -18,12 +18,12 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineLocation.h" +#include "llvm/Target/TargetRegistry.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #define GET_INSTRINFO_CTOR -#define GET_INSTRINFO_MC_DESC #include "XCoreGenInstrInfo.inc" namespace llvm { diff --git a/lib/Target/XCore/XCoreRegisterInfo.cpp b/lib/Target/XCore/XCoreRegisterInfo.cpp index 2bf43b4..357a4a0 100644 --- a/lib/Target/XCore/XCoreRegisterInfo.cpp +++ b/lib/Target/XCore/XCoreRegisterInfo.cpp @@ -33,7 +33,6 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#define GET_REGINFO_MC_DESC #define GET_REGINFO_TARGET_DESC #include "XCoreGenRegisterInfo.inc" @@ -196,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); @@ -208,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(); @@ -219,7 +227,6 @@ XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, if (FP) { bool isUs = isImmUs(Offset); - unsigned FramePtr = XCore::R10; if (!isUs) { if (!RS) @@ -231,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: @@ -252,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: diff --git a/lib/Target/XCore/XCoreSubtarget.cpp b/lib/Target/XCore/XCoreSubtarget.cpp index 6485c4e..ad069bf 100644 --- a/lib/Target/XCore/XCoreSubtarget.cpp +++ b/lib/Target/XCore/XCoreSubtarget.cpp @@ -13,16 +13,16 @@ #include "XCoreSubtarget.h" #include "XCore.h" +#include "llvm/Target/TargetRegistry.h" -#define GET_SUBTARGETINFO_CTOR -#define GET_SUBTARGETINFO_MC_DESC #define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR #include "XCoreGenSubtargetInfo.inc" using namespace llvm; XCoreSubtarget::XCoreSubtarget(const std::string &TT, const std::string &CPU, const std::string &FS) - : XCoreGenSubtargetInfo() + : XCoreGenSubtargetInfo(TT, CPU, FS) { } diff --git a/lib/Target/XCore/XCoreSubtarget.h b/lib/Target/XCore/XCoreSubtarget.h index 2e52571..7b29fa2 100644 --- a/lib/Target/XCore/XCoreSubtarget.h +++ b/lib/Target/XCore/XCoreSubtarget.h @@ -22,6 +22,7 @@ #include "XCoreGenSubtargetInfo.inc" namespace llvm { +class StringRef; class XCoreSubtarget : public XCoreGenSubtargetInfo { @@ -34,7 +35,7 @@ public: /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. - void 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 542038b..342966a 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" @@ -23,7 +22,7 @@ using namespace llvm; XCoreTargetMachine::XCoreTargetMachine(const Target &T, const std::string &TT, const std::string &CPU, const std::string &FS) - : LLVMTargetMachine(T, TT), + : 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"), @@ -42,5 +41,4 @@ bool XCoreTargetMachine::addInstSelector(PassManagerBase &PM, // Force static initialization. extern "C" void LLVMInitializeXCoreTarget() { RegisterTargetMachine<XCoreTargetMachine> X(TheXCoreTarget); - RegisterAsmInfo<XCoreMCAsmInfo> Y(TheXCoreTarget); } |