diff options
author | dim <dim@FreeBSD.org> | 2011-02-20 12:57:14 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2011-02-20 12:57:14 +0000 |
commit | cbb70ce070d220642b038ea101d9c0f9fbf860d6 (patch) | |
tree | d2b61ce94e654cb01a254d2195259db5f9cc3f3c /lib/Target/Mips | |
parent | 4ace901e87dac5bbbac78ed325e75462e48e386e (diff) | |
download | FreeBSD-src-cbb70ce070d220642b038ea101d9c0f9fbf860d6.zip FreeBSD-src-cbb70ce070d220642b038ea101d9c0f9fbf860d6.tar.gz |
Vendor import of llvm trunk r126079:
http://llvm.org/svn/llvm-project/llvm/trunk@126079
Diffstat (limited to 'lib/Target/Mips')
22 files changed, 1098 insertions, 789 deletions
diff --git a/lib/Target/Mips/AsmPrinter/CMakeLists.txt b/lib/Target/Mips/AsmPrinter/CMakeLists.txt deleted file mode 100644 index d3099d2..0000000 --- a/lib/Target/Mips/AsmPrinter/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -include_directories( - ${CMAKE_CURRENT_BINARY_DIR}/.. - ${CMAKE_CURRENT_SOURCE_DIR}/.. - ) - -add_llvm_library(LLVMMipsAsmPrinter - MipsAsmPrinter.cpp - ) -add_dependencies(LLVMMipsAsmPrinter MipsCodeGenTable_gen) diff --git a/lib/Target/Mips/AsmPrinter/Makefile b/lib/Target/Mips/AsmPrinter/Makefile deleted file mode 100644 index b1efe9b..0000000 --- a/lib/Target/Mips/AsmPrinter/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -##===- 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' Mips 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/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt index a77802a..26df1a0 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -11,10 +11,12 @@ tablegen(MipsGenCallingConv.inc -gen-callingconv) tablegen(MipsGenSubtarget.inc -gen-subtarget) add_llvm_target(MipsCodeGen + MipsAsmPrinter.cpp MipsDelaySlotFiller.cpp MipsInstrInfo.cpp MipsISelDAGToDAG.cpp MipsISelLowering.cpp + MipsFrameLowering.cpp MipsMCAsmInfo.cpp MipsRegisterInfo.cpp MipsSubtarget.cpp @@ -23,4 +25,4 @@ add_llvm_target(MipsCodeGen MipsSelectionDAGInfo.cpp ) -target_link_libraries (LLVMMipsCodeGen LLVMSelectionDAG) +add_subdirectory(TargetInfo) diff --git a/lib/Target/Mips/Makefile b/lib/Target/Mips/Makefile index 2ed8d77..d16b066 100644 --- a/lib/Target/Mips/Makefile +++ b/lib/Target/Mips/Makefile @@ -18,7 +18,7 @@ BUILT_SOURCES = MipsGenRegisterInfo.h.inc MipsGenRegisterNames.inc \ MipsGenDAGISel.inc MipsGenCallingConv.inc \ MipsGenSubtarget.inc -DIRS = AsmPrinter TargetInfo +DIRS = TargetInfo include $(LEVEL)/Makefile.common diff --git a/lib/Target/Mips/Mips.td b/lib/Target/Mips/Mips.td index a51c377..3e6437b 100644 --- a/lib/Target/Mips/Mips.td +++ b/lib/Target/Mips/Mips.td @@ -36,19 +36,15 @@ def FeatureFP64Bit : SubtargetFeature<"fp64", "IsFP64bit", "true", "Support 64-bit FP registers.">; def FeatureSingleFloat : SubtargetFeature<"single-float", "IsSingleFloat", "true", "Only supports single precision float">; -def FeatureMips1 : SubtargetFeature<"mips1", "MipsArchVersion", "Mips1", - "Mips1 ISA Support">; -def FeatureMips2 : SubtargetFeature<"mips2", "MipsArchVersion", "Mips2", - "Mips2 ISA Support">; def FeatureO32 : SubtargetFeature<"o32", "MipsABI", "O32", "Enable o32 ABI">; def FeatureEABI : SubtargetFeature<"eabi", "MipsABI", "EABI", "Enable eabi ABI">; -def FeatureVFPU : SubtargetFeature<"vfpu", "HasVFPU", +def FeatureVFPU : SubtargetFeature<"vfpu", "HasVFPU", "true", "Enable vector FPU instructions.">; -def FeatureSEInReg : SubtargetFeature<"seinreg", "HasSEInReg", "true", +def FeatureSEInReg : SubtargetFeature<"seinreg", "HasSEInReg", "true", "Enable 'signext in register' instructions.">; -def FeatureCondMov : SubtargetFeature<"condmov", "HasCondMov", "true", +def FeatureCondMov : SubtargetFeature<"condmov", "HasCondMov", "true", "Enable 'conditional move' instructions.">; def FeatureMulDivAdd : SubtargetFeature<"muldivadd", "HasMulDivAdd", "true", "Enable 'multiply add/sub' instructions.">; @@ -58,6 +54,16 @@ def FeatureSwap : SubtargetFeature<"swap", "HasSwap", "true", "Enable 'byte/half swap' instructions.">; def FeatureBitCount : SubtargetFeature<"bitcount", "HasBitCount", "true", "Enable 'count leading bits' instructions.">; +def FeatureMips1 : SubtargetFeature<"mips1", "MipsArchVersion", "Mips1", + "Mips1 ISA Support">; +def FeatureMips2 : SubtargetFeature<"mips2", "MipsArchVersion", "Mips2", + "Mips2 ISA Support">; +def FeatureMips32 : SubtargetFeature<"mips32", "MipsArchVersion", "Mips32", + "Mips32 ISA Support", + [FeatureCondMov, FeatureBitCount]>; +def FeatureMips32r2 : SubtargetFeature<"mips32r2", "MipsArchVersion", + "Mips32r2", "Mips32r2 ISA Support", + [FeatureMips32, FeatureSEInReg]>; //===----------------------------------------------------------------------===// // Mips processors supported. @@ -73,10 +79,12 @@ def : Proc<"r3000", [FeatureMips1]>; def : Proc<"mips2", [FeatureMips2]>; def : Proc<"r6000", [FeatureMips2]>; -// Allegrex is a 32bit subset of r4000, both for interger and fp registers, -// but much more similar to Mips2 than Mips3. It also contains some of -// Mips32/Mips32r2 instructions and a custom vector fpu processor. -def : Proc<"allegrex", [FeatureMips2, FeatureSingleFloat, FeatureEABI, +def : Proc<"4ke", [FeatureMips32r2]>; + +// Allegrex is a 32bit subset of r4000, both for interger and fp registers, +// but much more similar to Mips2 than Mips3. It also contains some of +// Mips32/Mips32r2 instructions and a custom vector fpu processor. +def : Proc<"allegrex", [FeatureMips2, FeatureSingleFloat, FeatureEABI, FeatureVFPU, FeatureSEInReg, FeatureCondMov, FeatureMulDivAdd, FeatureMinMax, FeatureSwap, FeatureBitCount]>; diff --git a/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 6660f6b..bd28a9b 100644 --- a/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -125,9 +125,10 @@ namespace { // Create a bitmask with all callee saved registers for CPU or Floating Point // registers. For CPU registers consider RA, GP and FP for saving if necessary. void MipsAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { - const TargetRegisterInfo &RI = *TM.getRegisterInfo(); + const TargetFrameLowering *TFI = TM.getFrameLowering(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); const MipsFunctionInfo *MipsFI = MF->getInfo<MipsFunctionInfo>(); - + // CPU and FPU Saved Registers Bitmasks unsigned int CPUBitmask = 0; unsigned int FPUBitmask = 0; @@ -145,13 +146,15 @@ void MipsAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { } // Return Address and Frame registers must also be set in CPUBitmask. - if (RI.hasFP(*MF)) + // FIXME: Do we really need hasFP() call here? When no FP is present SP is + // just returned -- will it be ok? + if (TFI->hasFP(*MF)) CPUBitmask |= (1 << MipsRegisterInfo:: - getRegisterNumbering(RI.getFrameRegister(*MF))); - - if (MFI->adjustsStack()) + getRegisterNumbering(RI->getFrameRegister(*MF))); + + if (MFI->adjustsStack()) CPUBitmask |= (1 << MipsRegisterInfo:: - getRegisterNumbering(RI.getRARegister())); + getRegisterNumbering(RI->getRARegister())); // Print CPUBitmask O << "\t.mask \t"; printHex32(CPUBitmask, O); @@ -270,12 +273,16 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, switch(MO.getTargetFlags()) { case MipsII::MO_GPREL: O << "%gp_rel("; break; case MipsII::MO_GOT_CALL: O << "%call16("; break; - case MipsII::MO_GOT: - if (MI->getOpcode() == Mips::LW) + case MipsII::MO_GOT: { + const MachineOperand &LastMO = MI->getOperand(opNum-1); + bool LastMOIsGP = LastMO.getType() == MachineOperand::MO_Register + && LastMO.getReg() == Mips::GP; + if (MI->getOpcode() == Mips::LW || LastMOIsGP) O << "%got("; else O << "%lo("; break; + } case MipsII::MO_ABS_HILO: if (MI->getOpcode() == Mips::LUi) O << "%hi("; diff --git a/lib/Target/Mips/MipsDelaySlotFiller.cpp b/lib/Target/Mips/MipsDelaySlotFiller.cpp index 597ea0d..b44a0af 100644 --- a/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -31,7 +31,7 @@ namespace { const TargetInstrInfo *TII; static char ID; - Filler(TargetMachine &tm) + Filler(TargetMachine &tm) : MachineFunctionPass(ID), TM(tm), TII(tm.getInstrInfo()) { } virtual const char *getPassName() const { @@ -55,17 +55,22 @@ namespace { /// Currently, we fill delay slots with NOPs. We assume there is only one /// delay slot per delayed instruction. bool Filler:: -runOnMachineBasicBlock(MachineBasicBlock &MBB) +runOnMachineBasicBlock(MachineBasicBlock &MBB) { bool Changed = false; - for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) - if (I->getDesc().hasDelaySlot()) { + for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) { + const TargetInstrDesc& Tid = I->getDesc(); + if (Tid.hasDelaySlot() && + (TM.getSubtarget<MipsSubtarget>().isMips1() || + Tid.isCall() || Tid.isBranch() || Tid.isReturn())) { MachineBasicBlock::iterator J = I; ++J; BuildMI(MBB, J, I->getDebugLoc(), TII->get(Mips::NOP)); ++FilledSlots; Changed = true; } + } + return Changed; } diff --git a/lib/Target/Mips/MipsFrameLowering.cpp b/lib/Target/Mips/MipsFrameLowering.cpp new file mode 100644 index 0000000..87a097a --- /dev/null +++ b/lib/Target/Mips/MipsFrameLowering.cpp @@ -0,0 +1,314 @@ +//=======- MipsFrameLowering.cpp - Mips Frame Information ------*- C++ -*-====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Mips implementation of TargetFrameLowering class. +// +//===----------------------------------------------------------------------===// + +#include "MipsFrameLowering.h" +#include "MipsInstrInfo.h" +#include "MipsMachineFunction.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/CommandLine.h" + +using namespace llvm; + + +//===----------------------------------------------------------------------===// +// +// Stack Frame Processing methods +// +----------------------------+ +// +// The stack is allocated decrementing the stack pointer on +// the first instruction of a function prologue. Once decremented, +// all stack references are done thought a positive offset +// from the stack/frame pointer, so the stack is considering +// to grow up! Otherwise terrible hacks would have to be made +// to get this stack ABI compliant :) +// +// The stack frame required by the ABI (after call): +// Offset +// +// 0 ---------- +// 4 Args to pass +// . saved $GP (used in PIC) +// . Alloca allocations +// . Local Area +// . CPU "Callee Saved" Registers +// . saved FP +// . saved RA +// . FPU "Callee Saved" Registers +// StackSize ----------- +// +// Offset - offset from sp after stack allocation on function prologue +// +// The sp is the stack pointer subtracted/added from the stack size +// at the Prologue/Epilogue +// +// References to the previous stack (to obtain arguments) are done +// with offsets that exceeds the stack size: (stacksize+(4*(num_arg-1)) +// +// Examples: +// - reference to the actual stack frame +// for any local area var there is smt like : FI >= 0, StackOffset: 4 +// sw REGX, 4(SP) +// +// - reference to previous stack frame +// suppose there's a load to the 5th arguments : FI < 0, StackOffset: 16. +// The emitted instruction will be something like: +// lw REGX, 16+StackSize(SP) +// +// Since the total stack size is unknown on LowerFormalArguments, all +// stack references (ObjectOffset) created to reference the function +// arguments, are negative numbers. This way, on eliminateFrameIndex it's +// possible to detect those references and the offsets are adjusted to +// their real location. +// +//===----------------------------------------------------------------------===// + +// hasFP - Return true if the specified function should have a dedicated frame +// pointer register. This is true if the function has variable sized allocas or +// if frame pointer elimination is disabled. +bool MipsFrameLowering::hasFP(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + return DisableFramePointerElim(MF) || MFI->hasVarSizedObjects(); +} + +void MipsFrameLowering::adjustMipsStackFrame(MachineFunction &MF) const { + MachineFrameInfo *MFI = MF.getFrameInfo(); + MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); + const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); + unsigned StackAlign = getStackAlignment(); + unsigned RegSize = STI.isGP32bit() ? 4 : 8; + bool HasGP = MipsFI->needGPSaveRestore(); + + // Min and Max CSI FrameIndex. + int MinCSFI = -1, MaxCSFI = -1; + + // See the description at MipsMachineFunction.h + int TopCPUSavedRegOff = -1, TopFPUSavedRegOff = -1; + + // Replace the dummy '0' SPOffset by the negative offsets, as explained on + // LowerFormalArguments. Leaving '0' for while is necessary to avoid the + // approach done by calculateFrameObjectOffsets to the stack frame. + MipsFI->adjustLoadArgsFI(MFI); + MipsFI->adjustStoreVarArgsFI(MFI); + + // It happens that the default stack frame allocation order does not directly + // map to the convention used for mips. So we must fix it. We move the callee + // save register slots after the local variables area, as described in the + // stack frame above. + unsigned CalleeSavedAreaSize = 0; + if (!CSI.empty()) { + MinCSFI = CSI[0].getFrameIdx(); + MaxCSFI = CSI[CSI.size()-1].getFrameIdx(); + } + for (unsigned i = 0, e = CSI.size(); i != e; ++i) + CalleeSavedAreaSize += MFI->getObjectAlignment(CSI[i].getFrameIdx()); + + unsigned StackOffset = HasGP ? (MipsFI->getGPStackOffset()+RegSize) + : (STI.isABI_O32() ? 16 : 0); + + // Adjust local variables. They should come on the stack right + // after the arguments. + int LastOffsetFI = -1; + for (int i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) { + if (i >= MinCSFI && i <= MaxCSFI) + continue; + if (MFI->isDeadObjectIndex(i)) + continue; + unsigned Offset = + StackOffset + MFI->getObjectOffset(i) - CalleeSavedAreaSize; + if (LastOffsetFI == -1) + LastOffsetFI = i; + if (Offset > MFI->getObjectOffset(LastOffsetFI)) + LastOffsetFI = i; + MFI->setObjectOffset(i, Offset); + } + + // Adjust CPU Callee Saved Registers Area. Registers RA and FP must + // be saved in this CPU Area. This whole area must be aligned to the + // default Stack Alignment requirements. + if (LastOffsetFI >= 0) + StackOffset = MFI->getObjectOffset(LastOffsetFI)+ + MFI->getObjectSize(LastOffsetFI); + StackOffset = ((StackOffset+StackAlign-1)/StackAlign*StackAlign); + + for (unsigned i = 0, e = CSI.size(); i != e ; ++i) { + unsigned Reg = CSI[i].getReg(); + if (!Mips::CPURegsRegisterClass->contains(Reg)) + break; + MFI->setObjectOffset(CSI[i].getFrameIdx(), StackOffset); + TopCPUSavedRegOff = StackOffset; + StackOffset += MFI->getObjectAlignment(CSI[i].getFrameIdx()); + } + + // Stack locations for FP and RA. If only one of them is used, + // the space must be allocated for both, otherwise no space at all. + if (hasFP(MF) || MFI->adjustsStack()) { + // FP stack location + MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true), + StackOffset); + MipsFI->setFPStackOffset(StackOffset); + TopCPUSavedRegOff = StackOffset; + StackOffset += RegSize; + + // SP stack location + MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true), + StackOffset); + MipsFI->setRAStackOffset(StackOffset); + StackOffset += RegSize; + + if (MFI->adjustsStack()) + TopCPUSavedRegOff += RegSize; + } + + StackOffset = ((StackOffset+StackAlign-1)/StackAlign*StackAlign); + + // Adjust FPU Callee Saved Registers Area. This Area must be + // aligned to the default Stack Alignment requirements. + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + if (Mips::CPURegsRegisterClass->contains(Reg)) + continue; + MFI->setObjectOffset(CSI[i].getFrameIdx(), StackOffset); + TopFPUSavedRegOff = StackOffset; + StackOffset += MFI->getObjectAlignment(CSI[i].getFrameIdx()); + } + StackOffset = ((StackOffset+StackAlign-1)/StackAlign*StackAlign); + + // Update frame info + MFI->setStackSize(StackOffset); + + // Recalculate the final tops offset. The final values must be '0' + // if there isn't a callee saved register for CPU or FPU, otherwise + // a negative offset is needed. + if (TopCPUSavedRegOff >= 0) + MipsFI->setCPUTopSavedRegOff(TopCPUSavedRegOff-StackOffset); + + if (TopFPUSavedRegOff >= 0) + MipsFI->setFPUTopSavedRegOff(TopFPUSavedRegOff-StackOffset); +} + +void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { + MachineBasicBlock &MBB = MF.front(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); + const MipsRegisterInfo *RegInfo = + static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); + const MipsInstrInfo &TII = + *static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo()); + MachineBasicBlock::iterator MBBI = MBB.begin(); + DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); + bool isPIC = (MF.getTarget().getRelocationModel() == Reloc::PIC_); + + // Get the right frame order for Mips. + adjustMipsStackFrame(MF); + + // Get the number of bytes to allocate from the FrameInfo. + unsigned StackSize = MFI->getStackSize(); + + // No need to allocate space on the stack. + if (StackSize == 0 && !MFI->adjustsStack()) return; + + int FPOffset = MipsFI->getFPStackOffset(); + int RAOffset = MipsFI->getRAStackOffset(); + + BuildMI(MBB, MBBI, dl, TII.get(Mips::NOREORDER)); + + // TODO: check need from GP here. + if (isPIC && STI.isABI_O32()) + BuildMI(MBB, MBBI, dl, TII.get(Mips::CPLOAD)) + .addReg(RegInfo->getPICCallReg()); + BuildMI(MBB, MBBI, dl, TII.get(Mips::NOMACRO)); + + // Adjust stack : addi sp, sp, (-imm) + BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDiu), Mips::SP) + .addReg(Mips::SP).addImm(-StackSize); + + // Save the return address only if the function isnt a leaf one. + // sw $ra, stack_loc($sp) + if (MFI->adjustsStack()) { + BuildMI(MBB, MBBI, dl, TII.get(Mips::SW)) + .addReg(Mips::RA).addImm(RAOffset).addReg(Mips::SP); + } + + // if framepointer enabled, save it and set it + // to point to the stack pointer + if (hasFP(MF)) { + // sw $fp,stack_loc($sp) + BuildMI(MBB, MBBI, dl, TII.get(Mips::SW)) + .addReg(Mips::FP).addImm(FPOffset).addReg(Mips::SP); + + // move $fp, $sp + BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDu), Mips::FP) + .addReg(Mips::SP).addReg(Mips::ZERO); + } + + // Restore GP from the saved stack location + if (MipsFI->needGPSaveRestore()) + BuildMI(MBB, MBBI, dl, TII.get(Mips::CPRESTORE)) + .addImm(MipsFI->getGPStackOffset()); +} + +void MipsFrameLowering::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); + const MipsInstrInfo &TII = + *static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo()); + DebugLoc dl = MBBI->getDebugLoc(); + + // Get the number of bytes from FrameInfo + int NumBytes = (int) MFI->getStackSize(); + + // Get the FI's where RA and FP are saved. + int FPOffset = MipsFI->getFPStackOffset(); + int RAOffset = MipsFI->getRAStackOffset(); + + // if framepointer enabled, restore it and restore the + // stack pointer + if (hasFP(MF)) { + // move $sp, $fp + BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDu), Mips::SP) + .addReg(Mips::FP).addReg(Mips::ZERO); + + // lw $fp,stack_loc($sp) + BuildMI(MBB, MBBI, dl, TII.get(Mips::LW), Mips::FP) + .addImm(FPOffset).addReg(Mips::SP); + } + + // Restore the return address only if the function isnt a leaf one. + // lw $ra, stack_loc($sp) + if (MFI->adjustsStack()) { + BuildMI(MBB, MBBI, dl, TII.get(Mips::LW), Mips::RA) + .addImm(RAOffset).addReg(Mips::SP); + } + + // adjust stack : insert addi sp, sp, (imm) + if (NumBytes) { + BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDiu), Mips::SP) + .addReg(Mips::SP).addImm(NumBytes); + } +} + +void MipsFrameLowering:: +processFunctionBeforeFrameFinalized(MachineFunction &MF) const { + const MipsRegisterInfo *RegInfo = + static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); + RegInfo->processFunctionBeforeFrameFinalized(MF); +} diff --git a/lib/Target/Mips/MipsFrameLowering.h b/lib/Target/Mips/MipsFrameLowering.h new file mode 100644 index 0000000..a8426c1 --- /dev/null +++ b/lib/Target/Mips/MipsFrameLowering.h @@ -0,0 +1,48 @@ +//==--- MipsFrameLowering.h - Define frame lowering for Mips --*- C++ -*---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +// +//===----------------------------------------------------------------------===// + +#ifndef ALPHA_FRAMEINFO_H +#define ALPHA_FRAMEINFO_H + +#include "Mips.h" +#include "MipsSubtarget.h" +#include "llvm/Target/TargetFrameLowering.h" + +namespace llvm { + class MipsSubtarget; + +class MipsFrameLowering : public TargetFrameLowering { +protected: + const MipsSubtarget &STI; + +public: + explicit MipsFrameLowering(const MipsSubtarget &sti) + // FIXME: Is this correct at all? + : TargetFrameLowering(StackGrowsUp, 8, 0), STI(sti) { + } + + void adjustMipsStackFrame(MachineFunction &MF) const; + + /// emitProlog/emitEpilog - These methods insert prolog and epilog code into + /// the function. + void emitPrologue(MachineFunction &MF) const; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + + bool hasFP(const MachineFunction &MF) const; + + void processFunctionBeforeFrameFinalized(MachineFunction &MF) const; +}; + +} // End llvm namespace + +#endif diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index a47cf7b..755e04d 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -84,8 +84,7 @@ private: SDNode *Select(SDNode *N); // Complex Pattern. - bool SelectAddr(SDNode *Op, SDValue N, - SDValue &Base, SDValue &Offset); + bool SelectAddr(SDValue N, SDValue &Base, SDValue &Offset); SDNode *SelectLoadFp64(SDNode *N); SDNode *SelectStoreFp64(SDNode *N); @@ -110,8 +109,7 @@ SDNode *MipsDAGToDAGISel::getGlobalBaseReg() { /// ComplexPattern used on MipsInstrInfo /// Used on Mips Load/Store instructions bool MipsDAGToDAGISel:: -SelectAddr(SDNode *Op, SDValue Addr, SDValue &Offset, SDValue &Base) -{ +SelectAddr(SDValue Addr, SDValue &Offset, SDValue &Base) { // if Address is FI, get the TargetFrameIndex. if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); @@ -193,7 +191,7 @@ SDNode *MipsDAGToDAGISel::SelectLoadFp64(SDNode *N) { SDValue N1 = N->getOperand(1); SDValue Offset0, Offset1, Base; - if (!SelectAddr(N, N1, Offset0, Base) || + if (!SelectAddr(N1, Offset0, Base) || N1.getValueType() != MVT::i32) return NULL; @@ -257,7 +255,7 @@ SDNode *MipsDAGToDAGISel::SelectStoreFp64(SDNode *N) { SDValue N2 = N->getOperand(2); SDValue Offset0, Offset1, Base; - if (!SelectAddr(N, N2, Offset0, Base) || + if (!SelectAddr(N2, Offset0, Base) || N1.getValueType() != MVT::f64 || N2.getValueType() != MVT::i32) return NULL; @@ -327,7 +325,7 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { case ISD::SUBE: case ISD::ADDE: { SDValue InFlag = Node->getOperand(2), CmpLHS; - unsigned Opc = InFlag.getOpcode(); Opc=Opc; + unsigned Opc = InFlag.getOpcode(); (void)Opc; assert(((Opc == ISD::ADDC || Opc == ISD::ADDE) || (Opc == ISD::SUBC || Opc == ISD::SUBE)) && "(ADD|SUB)E flag operand must come from (ADD|SUB)C/E insn"); @@ -351,7 +349,7 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { SDNode *AddCarry = CurDAG->getMachineNode(Mips::ADDu, dl, VT, SDValue(Carry,0), RHS); - return CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Flag, + return CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, LHS, SDValue(AddCarry,0)); } @@ -369,11 +367,11 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { else Op = (Opcode == ISD::UDIVREM ? Mips::DIVu : Mips::DIV); - SDNode *MulDiv = CurDAG->getMachineNode(Op, dl, MVT::Flag, Op1, Op2); + SDNode *MulDiv = CurDAG->getMachineNode(Op, dl, MVT::Glue, Op1, Op2); SDValue InFlag = SDValue(MulDiv, 0); SDNode *Lo = CurDAG->getMachineNode(Mips::MFLO, dl, MVT::i32, - MVT::Flag, InFlag); + MVT::Glue, InFlag); InFlag = SDValue(Lo,1); SDNode *Hi = CurDAG->getMachineNode(Mips::MFHI, dl, MVT::i32, InFlag); @@ -388,6 +386,8 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { /// Special Muls case ISD::MUL: + if (Subtarget.isMips32()) + break; case ISD::MULHS: case ISD::MULHU: { SDValue MulOp1 = Node->getOperand(0); @@ -395,7 +395,7 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { unsigned MulOp = (Opcode == ISD::MULHU ? Mips::MULTu : Mips::MULT); SDNode *MulNode = CurDAG->getMachineNode(MulOp, dl, - MVT::Flag, MulOp1, MulOp2); + MVT::Glue, MulOp1, MulOp2); SDValue InFlag = SDValue(MulNode, 0); @@ -421,7 +421,7 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { Op = (Opcode == ISD::SREM ? Mips::DIV : Mips::DIVu); MOp = Mips::MFHI; } - SDNode *Node = CurDAG->getMachineNode(Op, dl, MVT::Flag, Op1, Op2); + SDNode *Node = CurDAG->getMachineNode(Op, dl, MVT::Glue, Op1, Op2); SDValue InFlag = SDValue(Node, 0); return CurDAG->getMachineNode(MOp, dl, MVT::i32, InFlag); @@ -474,7 +474,7 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { SDValue InFlag; // Skip the incomming flag if present - if (Node->getOperand(LastOpNum).getValueType() == MVT::Flag) + if (Node->getOperand(LastOpNum).getValueType() == MVT::Glue) LastOpNum--; if ( (isa<GlobalAddressSDNode>(Callee)) || @@ -496,7 +496,7 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { Chain = CurDAG->getCopyToReg(Chain, dl, Mips::T9, Callee, InFlag); // Map the JmpLink operands to JALR - SDVTList NodeTys = CurDAG->getVTList(MVT::Other, MVT::Flag); + SDVTList NodeTys = CurDAG->getVTList(MVT::Other, MVT::Glue); SmallVector<SDValue, 8> Ops; Ops.push_back(CurDAG->getRegister(Mips::T9, MVT::i32)); diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index b0b99ba..1d7a1c0 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -41,12 +41,15 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::Lo : return "MipsISD::Lo"; case MipsISD::GPRel : return "MipsISD::GPRel"; case MipsISD::Ret : return "MipsISD::Ret"; - case MipsISD::CMov : return "MipsISD::CMov"; case MipsISD::SelectCC : return "MipsISD::SelectCC"; case MipsISD::FPSelectCC : return "MipsISD::FPSelectCC"; case MipsISD::FPBrcond : return "MipsISD::FPBrcond"; case MipsISD::FPCmp : return "MipsISD::FPCmp"; case MipsISD::FPRound : return "MipsISD::FPRound"; + case MipsISD::MAdd : return "MipsISD::MAdd"; + case MipsISD::MAddu : return "MipsISD::MAddu"; + case MipsISD::MSub : return "MipsISD::MSub"; + case MipsISD::MSubu : return "MipsISD::MSubu"; default : return NULL; } } @@ -57,7 +60,7 @@ MipsTargetLowering(MipsTargetMachine &TM) Subtarget = &TM.getSubtarget<MipsSubtarget>(); // Mips does not have i1 type, so use i32 for - // setcc operations results (slt, sgt, ...). + // setcc operations results (slt, sgt, ...). setBooleanContents(ZeroOrOneBooleanContent); // Set up the register classes @@ -69,7 +72,7 @@ MipsTargetLowering(MipsTargetMachine &TM) if (!Subtarget->isFP64bit()) addRegisterClass(MVT::f64, Mips::AFGR64RegisterClass); - // Load extented operations for i1 types must be promoted + // Load extented operations for i1 types must be promoted setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); @@ -78,9 +81,9 @@ MipsTargetLowering(MipsTargetMachine &TM) setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); setTruncStoreAction(MVT::f64, MVT::f32, Expand); - // Used by legalize types to correctly generate the setcc result. - // Without this, every float setcc comes with a AND/OR with the result, - // we don't want this, since the fpcmp result goes to a flag register, + // Used by legalize types to correctly generate the setcc result. + // Without this, every float setcc comes with a AND/OR with the result, + // we don't want this, since the fpcmp result goes to a flag register, // which is used implicitly by brcond and select operations. AddPromotedToType(ISD::SETCC, MVT::i1, MVT::i32); @@ -100,8 +103,8 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::VASTART, MVT::Other, Custom); - // We custom lower AND/OR to handle the case where the DAG contain 'ands/ors' - // with operands comming from setcc fp comparions. This is necessary since + // We custom lower AND/OR to handle the case where the DAG contain 'ands/ors' + // with operands comming from setcc fp comparions. This is necessary since // the result from these setcc are in a flag registers (FCR31). setOperationAction(ISD::AND, MVT::i32, Custom); setOperationAction(ISD::OR, MVT::i32, Custom); @@ -116,7 +119,10 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::CTPOP, MVT::i32, Expand); setOperationAction(ISD::CTTZ, MVT::i32, Expand); setOperationAction(ISD::ROTL, MVT::i32, Expand); - setOperationAction(ISD::ROTR, MVT::i32, Expand); + + if (!Subtarget->isMips32r2()) + setOperationAction(ISD::ROTR, MVT::i32, Expand); + setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); @@ -152,6 +158,9 @@ MipsTargetLowering(MipsTargetMachine &TM) if (!Subtarget->hasSwap()) setOperationAction(ISD::BSWAP, MVT::i32, Expand); + setTargetDAGCombine(ISD::ADDE); + setTargetDAGCombine(ISD::SUBE); + setStackPointerRegisterToSaveRestore(Mips::SP); computeRegisterProperties(); } @@ -165,10 +174,198 @@ unsigned MipsTargetLowering::getFunctionAlignment(const Function *) const { return 2; } +// SelectMadd - +// Transforms a subgraph in CurDAG if the following pattern is found: +// (addc multLo, Lo0), (adde multHi, Hi0), +// where, +// multHi/Lo: product of multiplication +// Lo0: initial value of Lo register +// Hi0: initial value of Hi register +// Return true if mattern matching was successful. +static bool SelectMadd(SDNode* ADDENode, SelectionDAG* CurDAG) { + // ADDENode's second operand must be a flag output of an ADDC node in order + // for the matching to be successful. + SDNode* ADDCNode = ADDENode->getOperand(2).getNode(); + + if (ADDCNode->getOpcode() != ISD::ADDC) + return false; + + SDValue MultHi = ADDENode->getOperand(0); + SDValue MultLo = ADDCNode->getOperand(0); + SDNode* MultNode = MultHi.getNode(); + unsigned MultOpc = MultHi.getOpcode(); + + // MultHi and MultLo must be generated by the same node, + if (MultLo.getNode() != MultNode) + return false; + + // and it must be a multiplication. + if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI) + return false; + + // MultLo amd MultHi must be the first and second output of MultNode + // respectively. + if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0) + return false; + + // Transform this to a MADD only if ADDENode and ADDCNode are the only users + // of the values of MultNode, in which case MultNode will be removed in later + // phases. + // If there exist users other than ADDENode or ADDCNode, this function returns + // here, which will result in MultNode being mapped to a single MULT + // instruction node rather than a pair of MULT and MADD instructions being + // produced. + if (!MultHi.hasOneUse() || !MultLo.hasOneUse()) + return false; + + SDValue Chain = CurDAG->getEntryNode(); + DebugLoc dl = ADDENode->getDebugLoc(); + + // create MipsMAdd(u) node + MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MAddu : MipsISD::MAdd; + + SDValue MAdd = CurDAG->getNode(MultOpc, dl, + MVT::Glue, + MultNode->getOperand(0),// Factor 0 + MultNode->getOperand(1),// Factor 1 + ADDCNode->getOperand(1),// Lo0 + ADDENode->getOperand(1));// Hi0 + + // create CopyFromReg nodes + SDValue CopyFromLo = CurDAG->getCopyFromReg(Chain, dl, Mips::LO, MVT::i32, + MAdd); + SDValue CopyFromHi = CurDAG->getCopyFromReg(CopyFromLo.getValue(1), dl, + Mips::HI, MVT::i32, + CopyFromLo.getValue(2)); + + // replace uses of adde and addc here + if (!SDValue(ADDCNode, 0).use_empty()) + CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDCNode, 0), CopyFromLo); + + if (!SDValue(ADDENode, 0).use_empty()) + CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDENode, 0), CopyFromHi); + + return true; +} + +// SelectMsub - +// Transforms a subgraph in CurDAG if the following pattern is found: +// (addc Lo0, multLo), (sube Hi0, multHi), +// where, +// multHi/Lo: product of multiplication +// Lo0: initial value of Lo register +// Hi0: initial value of Hi register +// Return true if mattern matching was successful. +static bool SelectMsub(SDNode* SUBENode, SelectionDAG* CurDAG) { + // SUBENode's second operand must be a flag output of an SUBC node in order + // for the matching to be successful. + SDNode* SUBCNode = SUBENode->getOperand(2).getNode(); + + if (SUBCNode->getOpcode() != ISD::SUBC) + return false; + + SDValue MultHi = SUBENode->getOperand(1); + SDValue MultLo = SUBCNode->getOperand(1); + SDNode* MultNode = MultHi.getNode(); + unsigned MultOpc = MultHi.getOpcode(); + + // MultHi and MultLo must be generated by the same node, + if (MultLo.getNode() != MultNode) + return false; + + // and it must be a multiplication. + if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI) + return false; + + // MultLo amd MultHi must be the first and second output of MultNode + // respectively. + if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0) + return false; + + // Transform this to a MSUB only if SUBENode and SUBCNode are the only users + // of the values of MultNode, in which case MultNode will be removed in later + // phases. + // If there exist users other than SUBENode or SUBCNode, this function returns + // here, which will result in MultNode being mapped to a single MULT + // instruction node rather than a pair of MULT and MSUB instructions being + // produced. + if (!MultHi.hasOneUse() || !MultLo.hasOneUse()) + return false; + + SDValue Chain = CurDAG->getEntryNode(); + DebugLoc dl = SUBENode->getDebugLoc(); + + // create MipsSub(u) node + MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MSubu : MipsISD::MSub; + + SDValue MSub = CurDAG->getNode(MultOpc, dl, + MVT::Glue, + MultNode->getOperand(0),// Factor 0 + MultNode->getOperand(1),// Factor 1 + SUBCNode->getOperand(0),// Lo0 + SUBENode->getOperand(0));// Hi0 + + // create CopyFromReg nodes + SDValue CopyFromLo = CurDAG->getCopyFromReg(Chain, dl, Mips::LO, MVT::i32, + MSub); + SDValue CopyFromHi = CurDAG->getCopyFromReg(CopyFromLo.getValue(1), dl, + Mips::HI, MVT::i32, + CopyFromLo.getValue(2)); + + // replace uses of sube and subc here + if (!SDValue(SUBCNode, 0).use_empty()) + CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBCNode, 0), CopyFromLo); + + if (!SDValue(SUBENode, 0).use_empty()) + CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBENode, 0), CopyFromHi); + + return true; +} + +static SDValue PerformADDECombine(SDNode *N, SelectionDAG& DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget* Subtarget) { + if (DCI.isBeforeLegalize()) + return SDValue(); + + if (Subtarget->isMips32() && SelectMadd(N, &DAG)) + return SDValue(N, 0); + + return SDValue(); +} + +static SDValue PerformSUBECombine(SDNode *N, SelectionDAG& DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget* Subtarget) { + if (DCI.isBeforeLegalize()) + return SDValue(); + + if (Subtarget->isMips32() && SelectMsub(N, &DAG)) + return SDValue(N, 0); + + return SDValue(); +} + +SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) + const { + SelectionDAG &DAG = DCI.DAG; + unsigned opc = N->getOpcode(); + + switch (opc) { + default: break; + case ISD::ADDE: + return PerformADDECombine(N, DAG, DCI, Subtarget); + case ISD::SUBE: + return PerformSUBECombine(N, DAG, DCI, Subtarget); + } + + return SDValue(); +} + SDValue MipsTargetLowering:: LowerOperation(SDValue Op, SelectionDAG &DAG) const { - switch (Op.getOpcode()) + switch (Op.getOpcode()) { case ISD::AND: return LowerANDOR(Op, DAG); case ISD::BRCOND: return LowerBRCOND(Op, DAG); @@ -194,7 +391,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const // MachineFunction as a live in value. It also creates a corresponding // virtual register for it. static unsigned -AddLiveIn(MachineFunction &MF, unsigned PReg, TargetRegisterClass *RC) +AddLiveIn(MachineFunction &MF, unsigned PReg, TargetRegisterClass *RC) { assert(RC->contains(PReg) && "Not the correct regclass!"); unsigned VReg = MF.getRegInfo().createVirtualRegister(RC); @@ -212,7 +409,7 @@ static Mips::FPBranchCode GetFPBranchCodeFromCond(Mips::CondCode CC) { return Mips::BRANCH_INVALID; } - + static unsigned FPBranchCodeToOpc(Mips::FPBranchCode BC) { switch(BC) { default: @@ -227,24 +424,24 @@ static unsigned FPBranchCodeToOpc(Mips::FPBranchCode BC) { static Mips::CondCode FPCondCCodeToFCC(ISD::CondCode CC) { switch (CC) { default: llvm_unreachable("Unknown fp condition code!"); - case ISD::SETEQ: + case ISD::SETEQ: case ISD::SETOEQ: return Mips::FCOND_EQ; case ISD::SETUNE: return Mips::FCOND_OGL; - case ISD::SETLT: + case ISD::SETLT: case ISD::SETOLT: return Mips::FCOND_OLT; - case ISD::SETGT: + case ISD::SETGT: case ISD::SETOGT: return Mips::FCOND_OGT; - case ISD::SETLE: - case ISD::SETOLE: return Mips::FCOND_OLE; + case ISD::SETLE: + case ISD::SETOLE: return Mips::FCOND_OLE; case ISD::SETGE: case ISD::SETOGE: return Mips::FCOND_OGE; case ISD::SETULT: return Mips::FCOND_ULT; - case ISD::SETULE: return Mips::FCOND_ULE; + case ISD::SETULE: return Mips::FCOND_ULE; case ISD::SETUGT: return Mips::FCOND_UGT; case ISD::SETUGE: return Mips::FCOND_UGE; - case ISD::SETUO: return Mips::FCOND_UN; + case ISD::SETUO: return Mips::FCOND_UN; case ISD::SETO: return Mips::FCOND_OR; - case ISD::SETNE: + case ISD::SETNE: case ISD::SETONE: return Mips::FCOND_NEQ; case ISD::SETUEQ: return Mips::FCOND_UEQ; } @@ -364,7 +561,7 @@ LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const // Emit the round instruction and bit convert to integer SDValue Trunc = DAG.getNode(MipsISD::FPRound, dl, MVT::f32, Src, CondReg.getValue(1)); - SDValue BitCvt = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Trunc); + SDValue BitCvt = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Trunc); return BitCvt; } @@ -382,11 +579,11 @@ LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const // obtain the new stack size. SDValue Sub = DAG.getNode(ISD::SUB, dl, MVT::i32, StackPointer, Size); - // The Sub result contains the new stack start address, so it + // The Sub result contains the new stack start address, so it // must be placed in the stack pointer register. Chain = DAG.getCopyToReg(StackPointer.getValue(1), dl, Mips::SP, Sub); - - // This node always has two return values: a new stack pointer + + // This node always has two return values: a new stack pointer // value and a chain SDValue Ops[2] = { Sub, Chain }; return DAG.getMergeValues(Ops, 2, dl); @@ -405,9 +602,9 @@ LowerANDOR(SDValue Op, SelectionDAG &DAG) const SDValue True = DAG.getConstant(1, MVT::i32); SDValue False = DAG.getConstant(0, MVT::i32); - SDValue LSEL = DAG.getNode(MipsISD::FPSelectCC, dl, True.getValueType(), + SDValue LSEL = DAG.getNode(MipsISD::FPSelectCC, dl, True.getValueType(), LHS, True, False, LHS.getOperand(2)); - SDValue RSEL = DAG.getNode(MipsISD::FPSelectCC, dl, True.getValueType(), + SDValue RSEL = DAG.getNode(MipsISD::FPSelectCC, dl, True.getValueType(), RHS, True, False, RHS.getOperand(2)); return DAG.getNode(Op.getOpcode(), dl, MVT::i32, LSEL, RSEL); @@ -416,7 +613,7 @@ LowerANDOR(SDValue Op, SelectionDAG &DAG) const SDValue MipsTargetLowering:: LowerBRCOND(SDValue Op, SelectionDAG &DAG) const { - // The first operand is the chain, the second is the condition, the third is + // The first operand is the chain, the second is the condition, the third is // the block to branch to if the condition is true. SDValue Chain = Op.getOperand(0); SDValue Dest = Op.getOperand(2); @@ -424,55 +621,55 @@ LowerBRCOND(SDValue Op, SelectionDAG &DAG) const if (Op.getOperand(1).getOpcode() != MipsISD::FPCmp) return Op; - + SDValue CondRes = Op.getOperand(1); SDValue CCNode = CondRes.getOperand(2); Mips::CondCode CC = (Mips::CondCode)cast<ConstantSDNode>(CCNode)->getZExtValue(); - SDValue BrCode = DAG.getConstant(GetFPBranchCodeFromCond(CC), MVT::i32); + SDValue BrCode = DAG.getConstant(GetFPBranchCodeFromCond(CC), MVT::i32); - return DAG.getNode(MipsISD::FPBrcond, dl, Op.getValueType(), Chain, BrCode, + return DAG.getNode(MipsISD::FPBrcond, dl, Op.getValueType(), Chain, BrCode, Dest, CondRes); } SDValue MipsTargetLowering:: LowerSETCC(SDValue Op, SelectionDAG &DAG) const { - // The operands to this are the left and right operands to compare (ops #0, - // and #1) and the condition code to compare them with (op #2) as a + // The operands to this are the left and right operands to compare (ops #0, + // and #1) and the condition code to compare them with (op #2) as a // CondCodeSDNode. - SDValue LHS = Op.getOperand(0); + SDValue LHS = Op.getOperand(0); SDValue RHS = Op.getOperand(1); DebugLoc dl = Op.getDebugLoc(); ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); - - return DAG.getNode(MipsISD::FPCmp, dl, Op.getValueType(), LHS, RHS, + + return DAG.getNode(MipsISD::FPCmp, dl, Op.getValueType(), LHS, RHS, DAG.getConstant(FPCondCCodeToFCC(CC), MVT::i32)); } SDValue MipsTargetLowering:: LowerSELECT(SDValue Op, SelectionDAG &DAG) const { - SDValue Cond = Op.getOperand(0); + SDValue Cond = Op.getOperand(0); SDValue True = Op.getOperand(1); SDValue False = Op.getOperand(2); DebugLoc dl = Op.getDebugLoc(); - // if the incomming condition comes from a integer compare, the select - // operation must be SelectCC or a conditional move if the subtarget + // if the incomming condition comes from a integer compare, the select + // operation must be SelectCC or a conditional move if the subtarget // supports it. if (Cond.getOpcode() != MipsISD::FPCmp) { if (Subtarget->hasCondMov() && !True.getValueType().isFloatingPoint()) return Op; - return DAG.getNode(MipsISD::SelectCC, dl, True.getValueType(), + return DAG.getNode(MipsISD::SelectCC, dl, True.getValueType(), Cond, True, False); } // if the incomming condition comes from fpcmp, the select // operation must use FPSelectCC. SDValue CCNode = Cond.getOperand(2); - return DAG.getNode(MipsISD::FPSelectCC, dl, True.getValueType(), + return DAG.getNode(MipsISD::FPSelectCC, dl, True.getValueType(), Cond, True, False, CCNode); } @@ -484,16 +681,16 @@ SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op, if (getTargetMachine().getRelocationModel() != Reloc::PIC_) { SDVTList VTs = DAG.getVTList(MVT::i32); - + MipsTargetObjectFile &TLOF = (MipsTargetObjectFile&)getObjFileLowering(); - + // %gp_rel relocation - if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) { - SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, + if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) { + SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, MipsII::MO_GPREL); SDValue GPRelNode = DAG.getNode(MipsISD::GPRel, dl, VTs, &GA, 1); SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(MVT::i32); - return DAG.getNode(ISD::ADD, dl, MVT::i32, GOT, GPRelNode); + return DAG.getNode(ISD::ADD, dl, MVT::i32, GOT, GPRelNode); } // %hi/%lo relocation SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, @@ -505,8 +702,8 @@ SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op, } else { SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, MipsII::MO_GOT); - SDValue ResNode = DAG.getLoad(MVT::i32, dl, - DAG.getEntryNode(), GA, NULL, 0, + SDValue ResNode = DAG.getLoad(MVT::i32, dl, + DAG.getEntryNode(), GA, MachinePointerInfo(), false, false, 0); // On functions and global targets not internal linked only // a load from got/GP is necessary for PIC to work. @@ -531,7 +728,7 @@ SDValue MipsTargetLowering:: LowerJumpTable(SDValue Op, SelectionDAG &DAG) const { SDValue ResNode; - SDValue HiPart; + SDValue HiPart; // FIXME there isn't actually debug info here DebugLoc dl = Op.getDebugLoc(); bool IsPIC = getTargetMachine().getRelocationModel() == Reloc::PIC_; @@ -546,7 +743,8 @@ LowerJumpTable(SDValue Op, SelectionDAG &DAG) const SDValue Ops[] = { JTI }; HiPart = DAG.getNode(MipsISD::Hi, dl, DAG.getVTList(MVT::i32), Ops, 1); } else // Emit Load from Global Pointer - HiPart = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), JTI, NULL, 0, + HiPart = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), JTI, + MachinePointerInfo(), false, false, 0); SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, JTI); @@ -565,26 +763,27 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) const DebugLoc dl = Op.getDebugLoc(); // gp_rel relocation - // FIXME: we should reference the constant pool using small data sections, + // FIXME: we should reference the constant pool using small data sections, // but the asm printer currently doens't support this feature without - // hacking it. This feature should come soon so we can uncomment the + // hacking it. This feature should come soon so we can uncomment the // stuff below. //if (IsInSmallSection(C->getType())) { // SDValue GPRelNode = DAG.getNode(MipsISD::GPRel, MVT::i32, CP); // SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(MVT::i32); - // ResNode = DAG.getNode(ISD::ADD, MVT::i32, GOT, GPRelNode); + // ResNode = DAG.getNode(ISD::ADD, MVT::i32, GOT, GPRelNode); if (getTargetMachine().getRelocationModel() != Reloc::PIC_) { - SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), + SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), N->getOffset(), MipsII::MO_ABS_HILO); SDValue HiPart = DAG.getNode(MipsISD::Hi, dl, MVT::i32, CP); SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, CP); ResNode = DAG.getNode(ISD::ADD, dl, MVT::i32, HiPart, Lo); } else { - SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), + SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), N->getOffset(), MipsII::MO_GOT); - SDValue Load = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), - CP, NULL, 0, false, false, 0); + SDValue Load = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), + CP, MachinePointerInfo::getConstantPool(), + false, false, 0); SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, CP); ResNode = DAG.getNode(ISD::ADD, dl, MVT::i32, Load, Lo); } @@ -603,7 +802,8 @@ SDValue MipsTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { // vastart just stores the address of the VarArgsFrameIndex slot into the // memory location argument. const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); - return DAG.getStore(Op.getOperand(0), dl, FI, Op.getOperand(1), SV, 0, + return DAG.getStore(Op.getOperand(0), dl, FI, Op.getOperand(1), + MachinePointerInfo(SV), false, false, 0); } @@ -614,23 +814,23 @@ SDValue MipsTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { #include "MipsGenCallingConv.inc" //===----------------------------------------------------------------------===// -// TODO: Implement a generic logic using tblgen that can support this. +// TODO: Implement a generic logic using tblgen that can support this. // Mips O32 ABI rules: // --- // i32 - Passed in A0, A1, A2, A3 and stack -// f32 - Only passed in f32 registers if no int reg has been used yet to hold +// f32 - Only passed in f32 registers if no int reg has been used yet to hold // an argument. Otherwise, passed in A1, A2, A3 and stack. -// f64 - Only passed in two aliased f32 registers if no int reg has been used -// yet to hold an argument. Otherwise, use A2, A3 and stack. If A1 is +// f64 - Only passed in two aliased f32 registers if no int reg has been used +// yet to hold an argument. Otherwise, use A2, A3 and stack. If A1 is // not used, it must be shadowed. If only A3 is avaiable, shadow it and // go to stack. //===----------------------------------------------------------------------===// -static bool CC_MipsO32(unsigned ValNo, EVT ValVT, - EVT LocVT, CCValAssign::LocInfo LocInfo, +static bool CC_MipsO32(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State) { - static const unsigned IntRegsSize=4, FloatRegsSize=2; + static const unsigned IntRegsSize=4, FloatRegsSize=2; static const unsigned IntRegs[] = { Mips::A0, Mips::A1, Mips::A2, Mips::A3 @@ -642,9 +842,15 @@ static bool CC_MipsO32(unsigned ValNo, EVT ValVT, Mips::D6, Mips::D7 }; - unsigned Reg=0; - unsigned UnallocIntReg = State.getFirstUnallocated(IntRegs, IntRegsSize); - bool IntRegUsed = (IntRegs[UnallocIntReg] != (unsigned (Mips::A0))); + unsigned Reg = 0; + static bool IntRegUsed = false; + + // This must be the first arg of the call if no regs have been allocated. + // Initialize IntRegUsed in that case. + if (IntRegs[State.getFirstUnallocated(IntRegs, IntRegsSize)] == Mips::A0 && + F32Regs[State.getFirstUnallocated(F32Regs, FloatRegsSize)] == Mips::F12 && + F64Regs[State.getFirstUnallocated(F64Regs, FloatRegsSize)] == Mips::D6) + IntRegUsed = false; // Promote i8 and i16 if (LocVT == MVT::i8 || LocVT == MVT::i16) { @@ -657,30 +863,48 @@ static bool CC_MipsO32(unsigned ValNo, EVT ValVT, LocInfo = CCValAssign::AExt; } - if (ValVT == MVT::i32 || (ValVT == MVT::f32 && IntRegUsed)) { + if (ValVT == MVT::i32) { Reg = State.AllocateReg(IntRegs, IntRegsSize); IntRegUsed = true; - LocVT = MVT::i32; - } - - if (ValVT.isFloatingPoint() && !IntRegUsed) { - if (ValVT == MVT::f32) - Reg = State.AllocateReg(F32Regs, FloatRegsSize); - else - Reg = State.AllocateReg(F64Regs, FloatRegsSize); - } + } else if (ValVT == MVT::f32) { + // An int reg has to be marked allocated regardless of whether or not + // IntRegUsed is true. + Reg = State.AllocateReg(IntRegs, IntRegsSize); - if (ValVT == MVT::f64 && IntRegUsed) { - if (UnallocIntReg != IntRegsSize) { - // If we hit register A3 as the first not allocated, we must - // mark it as allocated (shadow) and use the stack instead. - if (IntRegs[UnallocIntReg] != (unsigned (Mips::A3))) - Reg = Mips::A2; - for (;UnallocIntReg < IntRegsSize; ++UnallocIntReg) - State.AllocateReg(UnallocIntReg); - } - LocVT = MVT::i32; - } + if (IntRegUsed) { + if (Reg) // Int reg is available + LocVT = MVT::i32; + } else { + unsigned FReg = State.AllocateReg(F32Regs, FloatRegsSize); + if (FReg) // F32 reg is available + Reg = FReg; + else if (Reg) // No F32 regs are available, but an int reg is available. + LocVT = MVT::i32; + } + } else if (ValVT == MVT::f64) { + // Int regs have to be marked allocated regardless of whether or not + // IntRegUsed is true. + Reg = State.AllocateReg(IntRegs, IntRegsSize); + if (Reg == Mips::A1) + Reg = State.AllocateReg(IntRegs, IntRegsSize); + else if (Reg == Mips::A3) + Reg = 0; + State.AllocateReg(IntRegs, IntRegsSize); + + // At this point, Reg is A0, A2 or 0, and all the unavailable integer regs + // are marked as allocated. + if (IntRegUsed) { + if (Reg)// if int reg is available + LocVT = MVT::i32; + } else { + unsigned FReg = State.AllocateReg(F64Regs, FloatRegsSize); + if (FReg) // F64 reg is available. + Reg = FReg; + else if (Reg) // No F64 regs are available, but an int reg is available. + LocVT = MVT::i32; + } + } else + assert(false && "cannot handle this ValVT"); if (!Reg) { unsigned SizeInBytes = ValVT.getSizeInBits() >> 3; @@ -692,8 +916,8 @@ static bool CC_MipsO32(unsigned ValNo, EVT ValVT, return false; // CC must always match } -static bool CC_MipsO32_VarArgs(unsigned ValNo, EVT ValVT, - EVT LocVT, CCValAssign::LocInfo LocInfo, +static bool CC_MipsO32_VarArgs(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State) { static const unsigned IntRegsSize=4; @@ -736,7 +960,7 @@ static bool CC_MipsO32_VarArgs(unsigned ValNo, EVT ValVT, IntRegs[UnallocIntReg] == (unsigned (Mips::A2))) { unsigned Reg = State.AllocateReg(IntRegs, IntRegsSize); State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, MVT::i32, LocInfo)); - // Shadow the next register so it can be used + // Shadow the next register so it can be used // later to get the other 32bit part. State.AllocateReg(IntRegs, IntRegsSize); return false; @@ -786,13 +1010,13 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // To meet O32 ABI, Mips must always allocate 16 bytes on // the stack (even if less than 4 are used as arguments) if (Subtarget->isABI_O32()) { - int VTsize = EVT(MVT::i32).getSizeInBits()/8; + int VTsize = MVT(MVT::i32).getSizeInBits()/8; MFI->CreateFixedObject(VTsize, (VTsize*3), true); - CCInfo.AnalyzeCallOperands(Outs, + CCInfo.AnalyzeCallOperands(Outs, isVarArg ? CC_MipsO32_VarArgs : CC_MipsO32); } else CCInfo.AnalyzeCallOperands(Outs, CC_Mips); - + // Get a count of how many bytes are to be pushed on the stack. unsigned NumBytes = CCInfo.getNextStackOffset(); Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true)); @@ -801,7 +1025,7 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, SmallVector<std::pair<unsigned, SDValue>, 16> RegsToPass; SmallVector<SDValue, 8> MemOpChains; - // First/LastArgStackLoc contains the first/last + // First/LastArgStackLoc contains the first/last // "at stack" argument location. int LastArgStackLoc = 0; unsigned FirstStackArgLoc = (Subtarget->isABI_EABI() ? 0 : 16); @@ -814,12 +1038,12 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // Promote the value if needed. switch (VA.getLocInfo()) { default: llvm_unreachable("Unknown loc info!"); - case CCValAssign::Full: + case CCValAssign::Full: if (Subtarget->isABI_O32() && VA.isRegLoc()) { if (VA.getValVT() == MVT::f32 && VA.getLocVT() == MVT::i32) - Arg = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Arg); + Arg = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Arg); if (VA.getValVT() == MVT::f64 && VA.getLocVT() == MVT::i32) { - Arg = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i64, Arg); + Arg = DAG.getNode(ISD::BITCAST, dl, MVT::i64, Arg); SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Arg, DAG.getConstant(0, getPointerTy())); SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Arg, @@ -827,7 +1051,7 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, RegsToPass.push_back(std::make_pair(VA.getLocReg(), Lo)); RegsToPass.push_back(std::make_pair(VA.getLocReg()+1, Hi)); continue; - } + } } break; case CCValAssign::SExt: @@ -840,17 +1064,17 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); break; } - - // Arguments that can be passed on register must be kept at + + // Arguments that can be passed on register must be kept at // RegsToPass vector if (VA.isRegLoc()) { RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); continue; } - + // Register can't get to this point... assert(VA.isMemLoc()); - + // Create the frame index object for this incoming parameter // This guarantees that when allocating Local Area the firsts // 16 bytes which are alwayes reserved won't be overwritten @@ -861,50 +1085,51 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, SDValue PtrOff = DAG.getFrameIndex(FI,getPointerTy()); - // emit ISD::STORE whichs stores the + // emit ISD::STORE whichs stores the // parameter value to a stack Location - MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0, + MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, + MachinePointerInfo(), false, false, 0)); } // Transform all store nodes into one single node because all store // nodes are independent of each other. - if (!MemOpChains.empty()) - Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + if (!MemOpChains.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &MemOpChains[0], MemOpChains.size()); - // Build a sequence of copy-to-reg nodes chained together with token + // Build a sequence of copy-to-reg nodes chained together with token // chain and flag operands which copy the outgoing args into registers. // The InFlag in necessary since all emited instructions must be // stuck together. SDValue InFlag; for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { - Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, + Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, RegsToPass[i].second, InFlag); InFlag = Chain.getValue(1); } // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every - // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol - // node so that legalize doesn't hack it. + // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol + // node so that legalize doesn't hack it. unsigned char OpFlag = IsPIC ? MipsII::MO_GOT_CALL : MipsII::MO_NO_FLAG; - if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) - Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, + if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) + Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, getPointerTy(), 0, OpFlag); else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) - Callee = DAG.getTargetExternalSymbol(S->getSymbol(), + Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy(), OpFlag); // MipsJmpLink = #chain, #target_address, #opt_in_flags... - // = Chain, Callee, Reg#1, Reg#2, ... + // = Chain, Callee, Reg#1, Reg#2, ... // // Returns a chain & a flag for retval copy to use. - SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); SmallVector<SDValue, 8> Ops; Ops.push_back(Chain); Ops.push_back(Callee); - // Add argument registers to the end of the list so that they are + // Add argument registers to the end of the list so that they are // known live into the call. for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) Ops.push_back(DAG.getRegister(RegsToPass[i].first, @@ -916,17 +1141,17 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, Chain = DAG.getNode(MipsISD::JmpLink, dl, NodeTys, &Ops[0], Ops.size()); InFlag = Chain.getValue(1); - // Create a stack location to hold GP when PIC is used. This stack - // location is used on function prologue to save GP and also after all - // emited CALL's to restore GP. + // Create a stack location to hold GP when PIC is used. This stack + // location is used on function prologue to save GP and also after all + // emited CALL's to restore GP. if (IsPIC) { - // Function can have an arbitrary number of calls, so + // Function can have an arbitrary number of calls, so // hold the LastArgStackLoc with the biggest offset. int FI; MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); if (LastArgStackLoc >= MipsFI->getGPStackOffset()) { LastArgStackLoc = (!LastArgStackLoc) ? (16) : (LastArgStackLoc+4); - // Create the frame index only once. SPOffset here can be anything + // Create the frame index only once. SPOffset here can be anything // (this will be fixed on processFunctionBeforeFrameFinalized) if (MipsFI->getGPStackOffset() == -1) { FI = MFI->CreateFixedObject(4, 0, true); @@ -937,14 +1162,15 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // Reload GP value. FI = MipsFI->getGPFI(); - SDValue FIN = DAG.getFrameIndex(FI,getPointerTy()); - SDValue GPLoad = DAG.getLoad(MVT::i32, dl, Chain, FIN, NULL, 0, + SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); + SDValue GPLoad = DAG.getLoad(MVT::i32, dl, Chain, FIN, + MachinePointerInfo::getFixedStack(FI), false, false, 0); Chain = GPLoad.getValue(1); - Chain = DAG.getCopyToReg(Chain, dl, DAG.getRegister(Mips::GP, MVT::i32), + Chain = DAG.getCopyToReg(Chain, dl, DAG.getRegister(Mips::GP, MVT::i32), GPLoad, SDValue(0,0)); InFlag = Chain.getValue(1); - } + } // Create the CALLSEQ_END node. Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true), @@ -988,7 +1214,7 @@ MipsTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, // Formal Arguments Calling Convention Implementation //===----------------------------------------------------------------------===// -/// LowerFormalArguments - transform physical registers into virtual registers +/// LowerFormalArguments - transform physical registers into virtual registers /// and generate load operations for arguments places on the stack. SDValue MipsTargetLowering::LowerFormalArguments(SDValue Chain, @@ -1018,7 +1244,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, ArgLocs, *DAG.getContext()); if (Subtarget->isABI_O32()) - CCInfo.AnalyzeFormalArguments(Ins, + CCInfo.AnalyzeFormalArguments(Ins, isVarArg ? CC_MipsO32_VarArgs : CC_MipsO32); else CCInfo.AnalyzeFormalArguments(Ins, CC_Mips); @@ -1037,22 +1263,22 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, TargetRegisterClass *RC = 0; if (RegVT == MVT::i32) - RC = Mips::CPURegsRegisterClass; - else if (RegVT == MVT::f32) + RC = Mips::CPURegsRegisterClass; + else if (RegVT == MVT::f32) RC = Mips::FGR32RegisterClass; else if (RegVT == MVT::f64) { - if (!Subtarget->isSingleFloat()) + if (!Subtarget->isSingleFloat()) RC = Mips::AFGR64RegisterClass; - } else + } else llvm_unreachable("RegVT not supported by FormalArguments Lowering"); - // Transform the arguments stored on + // Transform the arguments stored on // physical registers into virtual ones unsigned Reg = AddLiveIn(DAG.getMachineFunction(), ArgRegEnd, RC); SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT); - - // If this is an 8 or 16-bit value, it has been passed promoted - // to 32 bits. Insert an assert[sz]ext to capture this, then + + // If this is an 8 or 16-bit value, it has been passed promoted + // to 32 bits. Insert an assert[sz]ext to capture this, then // truncate to the right size. if (VA.getLocInfo() != CCValAssign::Full) { unsigned Opcode = 0; @@ -1061,22 +1287,21 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, else if (VA.getLocInfo() == CCValAssign::ZExt) Opcode = ISD::AssertZext; if (Opcode) - ArgValue = DAG.getNode(Opcode, dl, RegVT, ArgValue, + ArgValue = DAG.getNode(Opcode, dl, RegVT, ArgValue, DAG.getValueType(VA.getValVT())); ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); } - // Handle O32 ABI cases: i32->f32 and (i32,i32)->f64 + // Handle O32 ABI cases: i32->f32 and (i32,i32)->f64 if (Subtarget->isABI_O32()) { - if (RegVT == MVT::i32 && VA.getValVT() == MVT::f32) - ArgValue = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, ArgValue); + if (RegVT == MVT::i32 && VA.getValVT() == MVT::f32) + ArgValue = DAG.getNode(ISD::BITCAST, dl, MVT::f32, ArgValue); if (RegVT == MVT::i32 && VA.getValVT() == MVT::f64) { - unsigned Reg2 = AddLiveIn(DAG.getMachineFunction(), + unsigned Reg2 = AddLiveIn(DAG.getMachineFunction(), VA.getLocReg()+1, RC); SDValue ArgValue2 = DAG.getCopyFromReg(Chain, dl, Reg2, RegVT); - SDValue Hi = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, ArgValue); - SDValue Lo = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, ArgValue2); - ArgValue = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::f64, Lo, Hi); + SDValue Pair = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, ArgValue2, ArgValue); + ArgValue = DAG.getNode(ISD::BITCAST, dl, MVT::f64, Pair); } } @@ -1088,13 +1313,13 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, // The last argument is not a register anymore ArgRegEnd = 0; - - // The stack pointer offset is relative to the caller stack frame. - // Since the real stack size is unknown here, a negative SPOffset + + // The stack pointer offset is relative to the caller stack frame. + // Since the real stack size is unknown here, a negative SPOffset // is used so there's a way to adjust these offsets when the stack - // size get known (on EliminateFrameIndex). A dummy SPOffset is + // size get known (on EliminateFrameIndex). A dummy SPOffset is // used instead of a direct negative address (which is recorded to - // be used on emitPrologue) to avoid mis-calc of the first stack + // be used on emitPrologue) to avoid mis-calc of the first stack // offset on PEI::calculateFrameObjectOffsets. // Arguments are always 32-bit. unsigned ArgSize = VA.getLocVT().getSizeInBits()/8; @@ -1104,7 +1329,8 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, // Create load nodes to retrieve arguments from the stack SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); - InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, NULL, 0, + InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, + MachinePointerInfo::getFixedStack(FI), false, false, 0)); } } @@ -1124,11 +1350,11 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, // To meet ABI, when VARARGS are passed on registers, the registers // must have their values written to the caller stack frame. If the last - // argument was placed in the stack, there's no need to save any register. + // argument was placed in the stack, there's no need to save any register. if ((isVarArg) && (Subtarget->isABI_O32() && ArgRegEnd)) { if (StackPtr.getNode() == 0) StackPtr = DAG.getRegister(StackReg, getPointerTy()); - + // The last register argument that must be saved is Mips::A3 TargetRegisterClass *RC = Mips::CPURegsRegisterClass; unsigned StackLoc = ArgLocs.size()-1; @@ -1140,7 +1366,8 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, int FI = MFI->CreateFixedObject(4, 0, true); MipsFI->recordStoreVarArgsFI(FI, -(4+(StackLoc*4))); SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy()); - OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, NULL, 0, + OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, + MachinePointerInfo(), false, false, 0)); // Record the frame index of the first variable argument @@ -1150,7 +1377,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, } } - // All stores are grouped in one node to allow the matching between + // All stores are grouped in one node to allow the matching between // the size of Ins and InVals. This only happens when on varg functions if (!OutChains.empty()) { OutChains.push_back(Chain); @@ -1183,7 +1410,7 @@ MipsTargetLowering::LowerReturn(SDValue Chain, // Analize return values. CCInfo.AnalyzeReturn(Outs, RetCC_Mips); - // If this is the first return lowered for this function, add + // If this is the first return lowered for this function, add // the regs to the liveout set for the function. if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { for (unsigned i = 0; i != RVLocs.size(); ++i) @@ -1198,7 +1425,7 @@ MipsTargetLowering::LowerReturn(SDValue Chain, CCValAssign &VA = RVLocs[i]; assert(VA.isRegLoc() && "Can only return in registers!"); - Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag); // guarantee that all emitted copies are @@ -1215,7 +1442,7 @@ MipsTargetLowering::LowerReturn(SDValue Chain, MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); unsigned Reg = MipsFI->getSRetReturnReg(); - if (!Reg) + if (!Reg) llvm_unreachable("sret virtual register not created in the entry block"); SDValue Val = DAG.getCopyFromReg(Chain, dl, Reg, getPointerTy()); @@ -1225,10 +1452,10 @@ MipsTargetLowering::LowerReturn(SDValue Chain, // Return on Mips is always a "jr $ra" if (Flag.getNode()) - return DAG.getNode(MipsISD::Ret, dl, MVT::Other, + return DAG.getNode(MipsISD::Ret, dl, MVT::Other, Chain, DAG.getRegister(Mips::RA, MVT::i32), Flag); else // Return Void - return DAG.getNode(MipsISD::Ret, dl, MVT::Other, + return DAG.getNode(MipsISD::Ret, dl, MVT::Other, Chain, DAG.getRegister(Mips::RA, MVT::i32)); } @@ -1239,21 +1466,21 @@ MipsTargetLowering::LowerReturn(SDValue Chain, /// getConstraintType - Given a constraint letter, return the type of /// constraint it is for this target. MipsTargetLowering::ConstraintType MipsTargetLowering:: -getConstraintType(const std::string &Constraint) const +getConstraintType(const std::string &Constraint) const { - // Mips specific constrainy + // Mips specific constrainy // GCC config/mips/constraints.md // - // 'd' : An address register. Equivalent to r - // unless generating MIPS16 code. - // 'y' : Equivalent to r; retained for - // backwards compatibility. - // 'f' : Floating Point registers. + // 'd' : An address register. Equivalent to r + // unless generating MIPS16 code. + // 'y' : Equivalent to r; retained for + // backwards compatibility. + // 'f' : Floating Point registers. if (Constraint.size() == 1) { switch (Constraint[0]) { default : break; - case 'd': - case 'y': + case 'd': + case 'y': case 'f': return C_RegisterClass; break; @@ -1262,6 +1489,37 @@ getConstraintType(const std::string &Constraint) const return TargetLowering::getConstraintType(Constraint); } +/// Examine constraint type and operand type and determine a weight value. +/// This object must already have been set up with the operand type +/// and the current alternative constraint selected. +TargetLowering::ConstraintWeight +MipsTargetLowering::getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const { + ConstraintWeight weight = CW_Invalid; + Value *CallOperandVal = info.CallOperandVal; + // If we don't have a value, we can't do a match, + // but allow it at the lowest weight. + if (CallOperandVal == NULL) + return CW_Default; + const Type *type = CallOperandVal->getType(); + // Look at the constraint type. + switch (*constraint) { + default: + weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); + break; + case 'd': + case 'y': + if (type->isIntegerTy()) + weight = CW_Register; + break; + case 'f': + if (type->isFloatTy()) + weight = CW_Register; + break; + } + return weight; +} + /// getRegClassForInlineAsmConstraint - Given a constraint letter (e.g. "r"), /// return a list of registers that can be used to satisfy the constraint. /// This should only be used for C_RegisterClass constraints. @@ -1275,7 +1533,7 @@ getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const case 'f': if (VT == MVT::f32) return std::make_pair(0U, Mips::FGR32RegisterClass); - if (VT == MVT::f64) + if (VT == MVT::f64) if ((!Subtarget->isSingleFloat()) && (!Subtarget->isFP64bit())) return std::make_pair(0U, Mips::AFGR64RegisterClass); } @@ -1293,15 +1551,15 @@ getRegClassForInlineAsmConstraint(const std::string &Constraint, if (Constraint.size() != 1) return std::vector<unsigned>(); - switch (Constraint[0]) { + switch (Constraint[0]) { default : break; case 'r': // GCC Mips Constraint Letters - case 'd': - case 'y': - return make_vector<unsigned>(Mips::T0, Mips::T1, Mips::T2, Mips::T3, - Mips::T4, Mips::T5, Mips::T6, Mips::T7, Mips::S0, Mips::S1, - Mips::S2, Mips::S3, Mips::S4, Mips::S5, Mips::S6, Mips::S7, + case 'd': + case 'y': + return make_vector<unsigned>(Mips::T0, Mips::T1, Mips::T2, Mips::T3, + Mips::T4, Mips::T5, Mips::T6, Mips::T7, Mips::S0, Mips::S1, + Mips::S2, Mips::S3, Mips::S4, Mips::S5, Mips::S6, Mips::S7, Mips::T8, 0); case 'f': @@ -1313,15 +1571,15 @@ getRegClassForInlineAsmConstraint(const std::string &Constraint, Mips::F25, Mips::F26, Mips::F27, Mips::F28, Mips::F29, Mips::F30, Mips::F31, 0); else - return make_vector<unsigned>(Mips::F2, Mips::F4, Mips::F6, Mips::F8, - Mips::F10, Mips::F20, Mips::F22, Mips::F24, Mips::F26, + return make_vector<unsigned>(Mips::F2, Mips::F4, Mips::F6, Mips::F8, + Mips::F10, Mips::F20, Mips::F22, Mips::F24, Mips::F26, Mips::F28, Mips::F30, 0); } - if (VT == MVT::f64) + if (VT == MVT::f64) if ((!Subtarget->isSingleFloat()) && (!Subtarget->isFP64bit())) - return make_vector<unsigned>(Mips::D1, Mips::D2, Mips::D3, Mips::D4, - Mips::D5, Mips::D10, Mips::D11, Mips::D12, Mips::D13, + return make_vector<unsigned>(Mips::D1, Mips::D2, Mips::D3, Mips::D4, + Mips::D5, Mips::D10, Mips::D11, Mips::D12, Mips::D13, Mips::D14, Mips::D15, 0); } return std::vector<unsigned>(); @@ -1336,5 +1594,7 @@ MipsTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { bool MipsTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { if (VT != MVT::f32 && VT != MVT::f64) return false; + if (Imm.isNegZero()) + return false; return Imm.isZero(); } diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index 460747b..9d6b9f3 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -40,9 +40,6 @@ namespace llvm { // Handle gp_rel (small data/bss sections) relocation. GPRel, - // Conditional Move - CMov, - // Select CC Pseudo Instruction SelectCC, @@ -59,7 +56,13 @@ namespace llvm { FPRound, // Return - Ret + Ret, + + // MAdd/Sub nodes + MAdd, + MAddu, + MSub, + MSubu }; } @@ -83,6 +86,8 @@ namespace llvm { /// getFunctionAlignment - Return the Log2 alignment of this function. virtual unsigned getFunctionAlignment(const Function *F) const; + + virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; private: // Subtarget Info const MipsSubtarget *Subtarget; @@ -139,6 +144,11 @@ namespace llvm { // Inline asm support ConstraintType getConstraintType(const std::string &Constraint) const; + /// Examine constraint string and operand type and determine a weight value. + /// The operand object must already have been set up with the operand type. + ConstraintWeight getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const; + std::pair<unsigned, const TargetRegisterClass*> getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; diff --git a/lib/Target/Mips/MipsInstrFPU.td b/lib/Target/Mips/MipsInstrFPU.td index cff79966d..977e0df 100644 --- a/lib/Target/Mips/MipsInstrFPU.td +++ b/lib/Target/Mips/MipsInstrFPU.td @@ -32,7 +32,7 @@ def SDT_MipsFPCmp : SDTypeProfile<1, 3, [SDTCisVT<0, i32>, def SDT_MipsFPSelectCC : SDTypeProfile<1, 4, [SDTCisInt<1>, SDTCisInt<4>, SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3>]>; -def MipsFPRound : SDNode<"MipsISD::FPRound", SDTFPRoundOp, [SDNPOptInFlag]>; +def MipsFPRound : SDNode<"MipsISD::FPRound", SDTFPRoundOp, [SDNPOptInGlue]>; def MipsFPBrcond : SDNode<"MipsISD::FPBrcond", SDT_MipsFPBrcond, [SDNPHasChain]>; def MipsFPCmp : SDNode<"MipsISD::FPCmp", SDT_MipsFPCmp>; diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index 320c5b8..b70266a 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -19,41 +19,53 @@ include "MipsInstrFormats.td" def SDT_MipsRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>; def SDT_MipsJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>; -def SDT_MipsSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 2>, +def SDT_MipsSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3>, SDTCisInt<1>]>; -def SDT_MipsCMov : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>, +def SDT_MipsCMov : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisSameAs<3, 4>, SDTCisInt<4>]>; def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>; def SDT_MipsCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; +def SDT_MipsMAddMSub : SDTypeProfile<0, 4, + [SDTCisVT<0, i32>, SDTCisSameAs<0, 1>, + SDTCisSameAs<1, 2>, + SDTCisSameAs<2, 3>]>; + // Call -def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, - [SDNPHasChain, SDNPOutFlag, SDNPOptInFlag, +def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, + [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, SDNPVariadic]>; -// Hi and Lo nodes are used to handle global addresses. Used on -// MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol +// Hi and Lo nodes are used to handle global addresses. Used on +// MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol // static model. (nothing to do with Mips Registers Hi and Lo) def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp>; def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>; def MipsGPRel : SDNode<"MipsISD::GPRel", SDTIntUnaryOp>; // Return -def MipsRet : SDNode<"MipsISD::Ret", SDT_MipsRet, [SDNPHasChain, - SDNPOptInFlag]>; +def MipsRet : SDNode<"MipsISD::Ret", SDT_MipsRet, [SDNPHasChain, + SDNPOptInGlue]>; // These are target-independent nodes, but have target-specific formats. def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_MipsCallSeqStart, - [SDNPHasChain, SDNPOutFlag]>; + [SDNPHasChain, SDNPOutGlue]>; def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeqEnd, - [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; // Select Condition Code def MipsSelectCC : SDNode<"MipsISD::SelectCC", SDT_MipsSelectCC>; -// Conditional Move -def MipsCMov : SDNode<"MipsISD::CMov", SDT_MipsCMov>; +// MAdd*/MSub* nodes +def MipsMAdd : SDNode<"MipsISD::MAdd", SDT_MipsMAddMSub, + [SDNPOptInGlue, SDNPOutGlue]>; +def MipsMAddu : SDNode<"MipsISD::MAddu", SDT_MipsMAddMSub, + [SDNPOptInGlue, SDNPOutGlue]>; +def MipsMSub : SDNode<"MipsISD::MSub", SDT_MipsMAddMSub, + [SDNPOptInGlue, SDNPOutGlue]>; +def MipsMSubu : SDNode<"MipsISD::MSubu", SDT_MipsMAddMSub, + [SDNPOptInGlue, SDNPOutGlue]>; //===----------------------------------------------------------------------===// // Mips Instruction Predicate Definitions. @@ -62,6 +74,8 @@ def HasSEInReg : Predicate<"Subtarget.hasSEInReg()">; def HasBitCount : Predicate<"Subtarget.hasBitCount()">; def HasSwap : Predicate<"Subtarget.hasSwap()">; def HasCondMov : Predicate<"Subtarget.hasCondMov()">; +def IsMips32 : Predicate<"Subtarget.isMips32()">; +def IsMips32r2 : Predicate<"Subtarget.isMips32r2()">; //===----------------------------------------------------------------------===// // Mips Operand, Complex Patterns and Transformations Definitions. @@ -126,90 +140,66 @@ def addr : ComplexPattern<iPTR, 2, "SelectAddr", [frameindex], []>; let isCommutable = 1 in class ArithR<bits<6> op, bits<6> func, string instr_asm, SDNode OpNode, InstrItinClass itin>: - FR< op, - func, - (outs CPURegs:$dst), - (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], itin>; + FR<op, func, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c), + !strconcat(instr_asm, "\t$dst, $b, $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], itin>; let isCommutable = 1 in class ArithOverflowR<bits<6> op, bits<6> func, string instr_asm>: - FR< op, - func, - (outs CPURegs:$dst), - (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [], IIAlu>; + FR<op, func, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c), + !strconcat(instr_asm, "\t$dst, $b, $c"), [], IIAlu>; // Arithmetic 2 register operands class ArithI<bits<6> op, string instr_asm, SDNode OpNode, Operand Od, PatLeaf imm_type> : - FI< op, - (outs CPURegs:$dst), - (ins CPURegs:$b, Od:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, imm_type:$c))], IIAlu>; + FI<op, (outs CPURegs:$dst), (ins CPURegs:$b, Od:$c), + !strconcat(instr_asm, "\t$dst, $b, $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, imm_type:$c))], IIAlu>; class ArithOverflowI<bits<6> op, string instr_asm, SDNode OpNode, Operand Od, PatLeaf imm_type> : - FI< op, - (outs CPURegs:$dst), - (ins CPURegs:$b, Od:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [], IIAlu>; + FI<op, (outs CPURegs:$dst), (ins CPURegs:$b, Od:$c), + !strconcat(instr_asm, "\t$dst, $b, $c"), [], IIAlu>; // Arithmetic Multiply ADD/SUB -let rd=0 in -class MArithR<bits<6> func, string instr_asm> : - FR< 0x1c, - func, - (outs CPURegs:$rs), - (ins CPURegs:$rt), - !strconcat(instr_asm, "\t$rs, $rt"), - [], IIImul>; +let rd = 0, shamt = 0, Defs = [HI, LO], Uses = [HI, LO] in +class MArithR<bits<6> func, string instr_asm, SDNode op> : + FR<0x1c, func, (outs), (ins CPURegs:$rs, CPURegs:$rt), + !strconcat(instr_asm, "\t$rs, $rt"), + [(op CPURegs:$rs, CPURegs:$rt, LO, HI)], IIImul>; // Logical class LogicR<bits<6> func, string instr_asm, SDNode OpNode>: - FR< 0x00, - func, - (outs CPURegs:$dst), - (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu>; + FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c), + !strconcat(instr_asm, "\t$dst, $b, $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu>; class LogicI<bits<6> op, string instr_asm, SDNode OpNode>: - FI< op, - (outs CPURegs:$dst), - (ins CPURegs:$b, uimm16:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt16:$c))], IIAlu>; + FI<op, (outs CPURegs:$dst), (ins CPURegs:$b, uimm16:$c), + !strconcat(instr_asm, "\t$dst, $b, $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt16:$c))], IIAlu>; class LogicNOR<bits<6> op, bits<6> func, string instr_asm>: - FR< op, - func, - (outs CPURegs:$dst), - (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (not (or CPURegs:$b, CPURegs:$c)))], IIAlu>; + FR<op, func, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c), + !strconcat(instr_asm, "\t$dst, $b, $c"), + [(set CPURegs:$dst, (not (or CPURegs:$b, CPURegs:$c)))], IIAlu>; // Shifts -let rt = 0 in -class LogicR_shift_imm<bits<6> func, string instr_asm, SDNode OpNode>: - FR< 0x00, - func, - (outs CPURegs:$dst), - (ins CPURegs:$b, shamt:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt5:$c))], IIAlu>; +class LogicR_shift_rotate_imm<bits<6> func, bits<5> _rs, string instr_asm, + SDNode OpNode>: + FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$b, shamt:$c), + !strconcat(instr_asm, "\t$dst, $b, $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt5:$c))], IIAlu> { + let rs = _rs; +} -class LogicR_shift_reg<bits<6> func, string instr_asm, SDNode OpNode>: - FR< 0x00, - func, - (outs CPURegs:$dst), - (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu>; +class LogicR_shift_rotate_reg<bits<6> func, bits<5> _shamt, string instr_asm, + SDNode OpNode>: + FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$c, CPURegs:$b), + !strconcat(instr_asm, "\t$dst, $b, $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu> { + let shamt = _shamt; +} // Load Upper Imediate class LoadUpper<bits<6> op, string instr_asm>: @@ -222,76 +212,55 @@ class LoadUpper<bits<6> op, string instr_asm>: // Memory Load/Store let canFoldAsLoad = 1, hasDelaySlot = 1 in class LoadM<bits<6> op, string instr_asm, PatFrag OpNode>: - FI< op, - (outs CPURegs:$dst), - (ins mem:$addr), - !strconcat(instr_asm, "\t$dst, $addr"), - [(set CPURegs:$dst, (OpNode addr:$addr))], IILoad>; + FI<op, (outs CPURegs:$dst), (ins mem:$addr), + !strconcat(instr_asm, "\t$dst, $addr"), + [(set CPURegs:$dst, (OpNode addr:$addr))], IILoad>; class StoreM<bits<6> op, string instr_asm, PatFrag OpNode>: - FI< op, - (outs), - (ins CPURegs:$dst, mem:$addr), - !strconcat(instr_asm, "\t$dst, $addr"), - [(OpNode CPURegs:$dst, addr:$addr)], IIStore>; + FI<op, (outs), (ins CPURegs:$dst, mem:$addr), + !strconcat(instr_asm, "\t$dst, $addr"), + [(OpNode CPURegs:$dst, addr:$addr)], IIStore>; // Conditional Branch let isBranch = 1, isTerminator=1, hasDelaySlot = 1 in { class CBranch<bits<6> op, string instr_asm, PatFrag cond_op>: - FI< op, - (outs), - (ins CPURegs:$a, CPURegs:$b, brtarget:$offset), - !strconcat(instr_asm, "\t$a, $b, $offset"), - [(brcond (cond_op CPURegs:$a, CPURegs:$b), bb:$offset)], - IIBranch>; - + FI<op, (outs), (ins CPURegs:$a, CPURegs:$b, brtarget:$offset), + !strconcat(instr_asm, "\t$a, $b, $offset"), + [(brcond (cond_op CPURegs:$a, CPURegs:$b), bb:$offset)], + IIBranch>; class CBranchZero<bits<6> op, string instr_asm, PatFrag cond_op>: - FI< op, - (outs), - (ins CPURegs:$src, brtarget:$offset), - !strconcat(instr_asm, "\t$src, $offset"), - [(brcond (cond_op CPURegs:$src, 0), bb:$offset)], - IIBranch>; + FI<op, (outs), (ins CPURegs:$src, brtarget:$offset), + !strconcat(instr_asm, "\t$src, $offset"), + [(brcond (cond_op CPURegs:$src, 0), bb:$offset)], + IIBranch>; } // SetCC class SetCC_R<bits<6> op, bits<6> func, string instr_asm, PatFrag cond_op>: - FR< op, - func, - (outs CPURegs:$dst), - (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (cond_op CPURegs:$b, CPURegs:$c))], - IIAlu>; + FR<op, func, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c), + !strconcat(instr_asm, "\t$dst, $b, $c"), + [(set CPURegs:$dst, (cond_op CPURegs:$b, CPURegs:$c))], + IIAlu>; class SetCC_I<bits<6> op, string instr_asm, PatFrag cond_op, Operand Od, PatLeaf imm_type>: - FI< op, - (outs CPURegs:$dst), - (ins CPURegs:$b, Od:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (cond_op CPURegs:$b, imm_type:$c))], - IIAlu>; + FI<op, (outs CPURegs:$dst), (ins CPURegs:$b, Od:$c), + !strconcat(instr_asm, "\t$dst, $b, $c"), + [(set CPURegs:$dst, (cond_op CPURegs:$b, imm_type:$c))], + IIAlu>; // Unconditional branch let isBranch=1, isTerminator=1, isBarrier=1, hasDelaySlot = 1 in class JumpFJ<bits<6> op, string instr_asm>: - FJ< op, - (outs), - (ins brtarget:$target), - !strconcat(instr_asm, "\t$target"), - [(br bb:$target)], IIBranch>; + FJ<op, (outs), (ins brtarget:$target), + !strconcat(instr_asm, "\t$target"), [(br bb:$target)], IIBranch>; let isBranch=1, isTerminator=1, isBarrier=1, rd=0, hasDelaySlot = 1 in class JumpFR<bits<6> op, bits<6> func, string instr_asm>: - FR< op, - func, - (outs), - (ins CPURegs:$target), - !strconcat(instr_asm, "\t$target"), - [(brind CPURegs:$target)], IIBranch>; + FR<op, func, (outs), (ins CPURegs:$target), + !strconcat(instr_asm, "\t$target"), [(brind CPURegs:$target)], IIBranch>; // Jump and Link (Call) let isCall=1, hasDelaySlot=1, @@ -299,86 +268,64 @@ let isCall=1, hasDelaySlot=1, Defs = [AT, V0, V1, A0, A1, A2, A3, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, K0, K1, D0, D1, D2, D3, D4, D5, D6, D7, D8, D9], Uses = [GP] in { class JumpLink<bits<6> op, string instr_asm>: - FJ< op, - (outs), - (ins calltarget:$target, variable_ops), - !strconcat(instr_asm, "\t$target"), - [(MipsJmpLink imm:$target)], IIBranch>; + FJ<op, (outs), (ins calltarget:$target, variable_ops), + !strconcat(instr_asm, "\t$target"), [(MipsJmpLink imm:$target)], + IIBranch>; let rd=31 in class JumpLinkReg<bits<6> op, bits<6> func, string instr_asm>: - FR< op, - func, - (outs), - (ins CPURegs:$rs, variable_ops), - !strconcat(instr_asm, "\t$rs"), - [(MipsJmpLink CPURegs:$rs)], IIBranch>; + FR<op, func, (outs), (ins CPURegs:$rs, variable_ops), + !strconcat(instr_asm, "\t$rs"), [(MipsJmpLink CPURegs:$rs)], IIBranch>; class BranchLink<string instr_asm>: - FI< 0x1, - (outs), - (ins CPURegs:$rs, brtarget:$target, variable_ops), - !strconcat(instr_asm, "\t$rs, $target"), - [], IIBranch>; + FI<0x1, (outs), (ins CPURegs:$rs, brtarget:$target, variable_ops), + !strconcat(instr_asm, "\t$rs, $target"), [], IIBranch>; } // Mul, Div class MulDiv<bits<6> func, string instr_asm, InstrItinClass itin>: - FR< 0x00, - func, - (outs), - (ins CPURegs:$a, CPURegs:$b), - !strconcat(instr_asm, "\t$a, $b"), - [], itin>; + FR<0x00, func, (outs), (ins CPURegs:$a, CPURegs:$b), + !strconcat(instr_asm, "\t$a, $b"), [], itin>; // Move from Hi/Lo class MoveFromLOHI<bits<6> func, string instr_asm>: - FR< 0x00, - func, - (outs CPURegs:$dst), - (ins), - !strconcat(instr_asm, "\t$dst"), - [], IIHiLo>; + FR<0x00, func, (outs CPURegs:$dst), (ins), + !strconcat(instr_asm, "\t$dst"), [], IIHiLo>; class MoveToLOHI<bits<6> func, string instr_asm>: - FR< 0x00, - func, - (outs), - (ins CPURegs:$src), - !strconcat(instr_asm, "\t$src"), - [], IIHiLo>; + FR<0x00, func, (outs), (ins CPURegs:$src), + !strconcat(instr_asm, "\t$src"), [], IIHiLo>; class EffectiveAddress<string instr_asm> : - FI<0x09, - (outs CPURegs:$dst), - (ins mem:$addr), - instr_asm, - [(set CPURegs:$dst, addr:$addr)], IIAlu>; + FI<0x09, (outs CPURegs:$dst), (ins mem:$addr), + instr_asm, [(set CPURegs:$dst, addr:$addr)], IIAlu>; // Count Leading Ones/Zeros in Word -class CountLeading<bits<6> func, string instr_asm, SDNode CountOp>: - FR< 0x1c, func, (outs CPURegs:$dst), (ins CPURegs:$src), - !strconcat(instr_asm, "\t$dst, $src"), - [(set CPURegs:$dst, (CountOp CPURegs:$src))], IIAlu>; +class CountLeading<bits<6> func, string instr_asm, list<dag> pattern>: + FR<0x1c, func, (outs CPURegs:$dst), (ins CPURegs:$src), + !strconcat(instr_asm, "\t$dst, $src"), pattern, IIAlu>, + Requires<[HasBitCount]> { + let shamt = 0; + let rt = rd; +} // Sign Extend in Register. class SignExtInReg<bits<6> func, string instr_asm, ValueType vt>: - FR< 0x3f, func, (outs CPURegs:$dst), (ins CPURegs:$src), - !strconcat(instr_asm, "\t$dst, $src"), - [(set CPURegs:$dst, (sext_inreg CPURegs:$src, vt))], NoItinerary>; + FR<0x3f, func, (outs CPURegs:$dst), (ins CPURegs:$src), + !strconcat(instr_asm, "\t$dst, $src"), + [(set CPURegs:$dst, (sext_inreg CPURegs:$src, vt))], NoItinerary>; // Byte Swap class ByteSwap<bits<6> func, string instr_asm>: - FR< 0x1f, func, (outs CPURegs:$dst), (ins CPURegs:$src), - !strconcat(instr_asm, "\t$dst, $src"), - [(set CPURegs:$dst, (bswap CPURegs:$src))], NoItinerary>; + FR<0x1f, func, (outs CPURegs:$dst), (ins CPURegs:$src), + !strconcat(instr_asm, "\t$dst, $src"), + [(set CPURegs:$dst, (bswap CPURegs:$src))], NoItinerary>; // Conditional Move class CondMov<bits<6> func, string instr_asm, PatLeaf MovCode>: - FR< 0x00, func, (outs CPURegs:$dst), (ins CPURegs:$F, CPURegs:$T, - CPURegs:$cond), !strconcat(instr_asm, "\t$dst, $T, $cond"), - [(set CPURegs:$dst, (MipsCMov CPURegs:$F, CPURegs:$T, - CPURegs:$cond, MovCode))], NoItinerary>; + FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$F, CPURegs:$T, + CPURegs:$cond), !strconcat(instr_asm, "\t$dst, $T, $cond"), + [], NoItinerary>; //===----------------------------------------------------------------------===// // Pseudo instructions @@ -408,13 +355,13 @@ def NOREORDER : MipsPseudo<(outs), (ins), ".set\tnoreorder", []>; def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$picreg), ".cpload\t$picreg", []>; def CPRESTORE : MipsPseudo<(outs), (ins uimm16:$loc), ".cprestore\t$loc\n", []>; -// The supported Mips ISAs dont have any instruction close to the SELECT_CC +// The supported Mips ISAs dont have any instruction close to the SELECT_CC // operation. The solution is to create a Mips pseudo SELECT_CC instruction -// (MipsSelectCC), use LowerSELECT_CC to generate this instruction and finally +// (MipsSelectCC), use LowerSELECT_CC to generate this instruction and finally // replace it for real supported nodes into EmitInstrWithCustomInserter let usesCustomInserter = 1 in { - class PseudoSelCC<RegisterClass RC, string asmstr>: - MipsPseudo<(outs RC:$dst), (ins CPURegs:$CmpRes, RC:$T, RC:$F), asmstr, + class PseudoSelCC<RegisterClass RC, string asmstr>: + MipsPseudo<(outs RC:$dst), (ins CPURegs:$CmpRes, RC:$T, RC:$F), asmstr, [(set RC:$dst, (MipsSelectCC CPURegs:$CmpRes, RC:$T, RC:$F))]>; } @@ -451,12 +398,18 @@ def XOR : LogicR<0x26, "xor", xor>; def NOR : LogicNOR<0x00, 0x27, "nor">; /// Shift Instructions -def SLL : LogicR_shift_imm<0x00, "sll", shl>; -def SRL : LogicR_shift_imm<0x02, "srl", srl>; -def SRA : LogicR_shift_imm<0x03, "sra", sra>; -def SLLV : LogicR_shift_reg<0x04, "sllv", shl>; -def SRLV : LogicR_shift_reg<0x06, "srlv", srl>; -def SRAV : LogicR_shift_reg<0x07, "srav", sra>; +def SLL : LogicR_shift_rotate_imm<0x00, 0x00, "sll", shl>; +def SRL : LogicR_shift_rotate_imm<0x02, 0x00, "srl", srl>; +def SRA : LogicR_shift_rotate_imm<0x03, 0x00, "sra", sra>; +def SLLV : LogicR_shift_rotate_reg<0x04, 0x00, "sllv", shl>; +def SRLV : LogicR_shift_rotate_reg<0x06, 0x00, "srlv", srl>; +def SRAV : LogicR_shift_rotate_reg<0x07, 0x00, "srav", sra>; + +// Rotate Instructions +let Predicates = [IsMips32r2] in { + def ROTR : LogicR_shift_rotate_imm<0x02, 0x01, "rotr", rotr>; + def ROTRV : LogicR_shift_rotate_reg<0x06, 0x01, "rotrv", rotr>; +} /// Load and Store Instructions def LB : LoadM<0x20, "lb", sextloadi8>; @@ -493,7 +446,7 @@ let isReturn=1, isTerminator=1, hasDelaySlot=1, def RET : FR <0x00, 0x02, (outs), (ins CPURegs:$target), "jr\t$target", [(MipsRet CPURegs:$target)], IIBranch>; -/// Multiply and Divide Instructions. +/// Multiply and Divide Instructions. let Defs = [HI, LO] in { def MULT : MulDiv<0x18, "mult", IIImul>; def MULTu : MulDiv<0x19, "multu", IIImul>; @@ -521,10 +474,10 @@ let Predicates = [HasSEInReg] in { } /// Count Leading -let Predicates = [HasBitCount] in { - let rt = 0 in - def CLZ : CountLeading<0b010110, "clz", ctlz>; -} +def CLZ : CountLeading<0b100000, "clz", + [(set CPURegs:$dst, (ctlz CPURegs:$src))]>; +def CLO : CountLeading<0b100001, "clo", + [(set CPURegs:$dst, (ctlz (not CPURegs:$src)))]>; /// Byte Swap let Predicates = [HasSwap] in { @@ -551,15 +504,15 @@ let addr=0 in // can be matched. It's similar to Sparc LEA_ADDRi def LEA_ADDiu : EffectiveAddress<"addiu\t$dst, ${addr:stackloc}">; -// MADD*/MSUB* are not part of MipsI either. -//def MADD : MArithR<0x00, "madd">; -//def MADDU : MArithR<0x01, "maddu">; -//def MSUB : MArithR<0x04, "msub">; -//def MSUBU : MArithR<0x05, "msubu">; +// MADD*/MSUB* +def MADD : MArithR<0, "madd", MipsMAdd>; +def MADDU : MArithR<1, "maddu", MipsMAddu>; +def MSUB : MArithR<4, "msub", MipsMSub>; +def MSUBU : MArithR<5, "msubu", MipsMSubu>; // MUL is a assembly macro in the current used ISAs. In recent ISA's // it is a real instruction. -//def MUL : ArithR<0x1c, 0x02, "mul", mul, IIImul>; +def MUL : ArithR<0x1c, 0x02, "mul", mul, IIImul>, Requires<[IsMips32]>; //===----------------------------------------------------------------------===// // Arbitrary patterns that map to one or more instructions @@ -605,9 +558,9 @@ def : Pat<(add CPURegs:$hi, (MipsLo tconstpool:$lo)), (ADDiu CPURegs:$hi, tconstpool:$lo)>; // gp_rel relocs -def : Pat<(add CPURegs:$gp, (MipsGPRel tglobaladdr:$in)), +def : Pat<(add CPURegs:$gp, (MipsGPRel tglobaladdr:$in)), (ADDiu CPURegs:$gp, tglobaladdr:$in)>; -def : Pat<(add CPURegs:$gp, (MipsGPRel tconstpool:$in)), +def : Pat<(add CPURegs:$gp, (MipsGPRel tconstpool:$in)), (ADDiu CPURegs:$gp, tconstpool:$in)>; // Mips does not have "not", so we expand our way @@ -665,9 +618,15 @@ def : Pat<(select (seteq CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F), def : Pat<(select (setne CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F), (MOVN CPURegs:$F, CPURegs:$T, (XOR CPURegs:$lhs, CPURegs:$rhs))>; -def : Pat<(select CPURegs:$cond, CPURegs:$T, CPURegs:$F), +def : Pat<(select CPURegs:$cond, CPURegs:$T, CPURegs:$F), (MOVN CPURegs:$F, CPURegs:$T, CPURegs:$cond)>; +// select patterns with got access +def : Pat<(select (setne CPURegs:$lhs, CPURegs:$rhs), + (i32 tglobaladdr:$T), CPURegs:$F), + (MOVN CPURegs:$F, (ADDiu GP, tglobaladdr:$T), + (XOR CPURegs:$lhs, CPURegs:$rhs))>; + // setcc patterns def : Pat<(seteq CPURegs:$lhs, CPURegs:$rhs), (SLTu (XOR CPURegs:$lhs, CPURegs:$rhs), 1)>; diff --git a/lib/Target/Mips/MipsMachineFunction.h b/lib/Target/Mips/MipsMachineFunction.h index 5723f9e..1e8e4fe 100644 --- a/lib/Target/Mips/MipsMachineFunction.h +++ b/lib/Target/Mips/MipsMachineFunction.h @@ -26,11 +26,11 @@ namespace llvm { class MipsFunctionInfo : public MachineFunctionInfo { private: - /// Holds for each function where on the stack the Frame Pointer must be + /// Holds for each function where on the stack the Frame Pointer must be /// saved. This is used on Prologue and Epilogue to emit FP save/restore int FPStackOffset; - /// Holds for each function where on the stack the Return Address must be + /// Holds for each function where on the stack the Return Address must be /// saved. This is used on Prologue and Epilogue to emit RA save/restore int RAStackOffset; @@ -51,22 +51,22 @@ private: : FI(FrameIndex), SPOffset(StackPointerOffset) {} }; - /// When PIC is used the GP must be saved on the stack on the function - /// prologue and must be reloaded from this stack location after every - /// call. A reference to its stack location and frame index must be kept + /// When PIC is used the GP must be saved on the stack on the function + /// prologue and must be reloaded from this stack location after every + /// call. A reference to its stack location and frame index must be kept /// to be used on emitPrologue and processFunctionBeforeFrameFinalized. MipsFIHolder GPHolder; /// On LowerFormalArguments the stack size is unknown, so the Stack - /// Pointer Offset calculation of "not in register arguments" must be - /// postponed to emitPrologue. + /// Pointer Offset calculation of "not in register arguments" must be + /// postponed to emitPrologue. SmallVector<MipsFIHolder, 16> FnLoadArgs; bool HasLoadArgs; - // When VarArgs, we must write registers back to caller stack, preserving - // on register arguments. Since the stack size is unknown on + // When VarArgs, we must write registers back to caller stack, preserving + // on register arguments. Since the stack size is unknown on // LowerFormalArguments, the Stack Pointer Offset calculation must be - // postponed to emitPrologue. + // postponed to emitPrologue. SmallVector<MipsFIHolder, 4> FnStoreVarArgs; bool HasStoreVarArgs; @@ -84,9 +84,9 @@ private: int VarArgsFrameIndex; public: - MipsFunctionInfo(MachineFunction& MF) - : FPStackOffset(0), RAStackOffset(0), CPUTopSavedRegOff(0), - FPUTopSavedRegOff(0), GPHolder(-1,-1), HasLoadArgs(false), + MipsFunctionInfo(MachineFunction& MF) + : FPStackOffset(0), RAStackOffset(0), CPUTopSavedRegOff(0), + FPUTopSavedRegOff(0), GPHolder(-1,-1), HasLoadArgs(false), HasStoreVarArgs(false), SRetReturnReg(0), GlobalBaseReg(0), VarArgsFrameIndex(0) {} @@ -110,7 +110,7 @@ public: bool needGPSaveRestore() const { return GPHolder.SPOffset != -1; } bool hasLoadArgs() const { return HasLoadArgs; } - bool hasStoreVarArgs() const { return HasStoreVarArgs; } + bool hasStoreVarArgs() const { return HasStoreVarArgs; } void recordLoadArgsFI(int FI, int SPOffset) { if (!HasLoadArgs) HasLoadArgs=true; @@ -123,12 +123,12 @@ public: void adjustLoadArgsFI(MachineFrameInfo *MFI) const { if (!hasLoadArgs()) return; - for (unsigned i = 0, e = FnLoadArgs.size(); i != e; ++i) + for (unsigned i = 0, e = FnLoadArgs.size(); i != e; ++i) MFI->setObjectOffset( FnLoadArgs[i].FI, FnLoadArgs[i].SPOffset ); } void adjustStoreVarArgsFI(MachineFrameInfo *MFI) const { - if (!hasStoreVarArgs()) return; - for (unsigned i = 0, e = FnStoreVarArgs.size(); i != e; ++i) + if (!hasStoreVarArgs()) return; + for (unsigned i = 0, e = FnStoreVarArgs.size(); i != e; ++i) MFI->setObjectOffset( FnStoreVarArgs[i].FI, FnStoreVarArgs[i].SPOffset ); } diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index 69436d2..3719e58 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -25,7 +25,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineLocation.h" -#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetInstrInfo.h" @@ -117,8 +117,7 @@ getCalleeSavedRegs(const MachineFunction *MF) const } BitVector MipsRegisterInfo:: -getReservedRegs(const MachineFunction &MF) const -{ +getReservedRegs(const MachineFunction &MF) const { BitVector Reserved(getNumRegs()); Reserved.set(Mips::ZERO); Reserved.set(Mips::AT); @@ -137,184 +136,6 @@ getReservedRegs(const MachineFunction &MF) const return Reserved; } -//===----------------------------------------------------------------------===// -// -// Stack Frame Processing methods -// +----------------------------+ -// -// The stack is allocated decrementing the stack pointer on -// the first instruction of a function prologue. Once decremented, -// all stack references are done thought a positive offset -// from the stack/frame pointer, so the stack is considering -// to grow up! Otherwise terrible hacks would have to be made -// to get this stack ABI compliant :) -// -// The stack frame required by the ABI (after call): -// Offset -// -// 0 ---------- -// 4 Args to pass -// . saved $GP (used in PIC) -// . Alloca allocations -// . Local Area -// . CPU "Callee Saved" Registers -// . saved FP -// . saved RA -// . FPU "Callee Saved" Registers -// StackSize ----------- -// -// Offset - offset from sp after stack allocation on function prologue -// -// The sp is the stack pointer subtracted/added from the stack size -// at the Prologue/Epilogue -// -// References to the previous stack (to obtain arguments) are done -// with offsets that exceeds the stack size: (stacksize+(4*(num_arg-1)) -// -// Examples: -// - reference to the actual stack frame -// for any local area var there is smt like : FI >= 0, StackOffset: 4 -// sw REGX, 4(SP) -// -// - reference to previous stack frame -// suppose there's a load to the 5th arguments : FI < 0, StackOffset: 16. -// The emitted instruction will be something like: -// lw REGX, 16+StackSize(SP) -// -// Since the total stack size is unknown on LowerFormalArguments, all -// stack references (ObjectOffset) created to reference the function -// arguments, are negative numbers. This way, on eliminateFrameIndex it's -// possible to detect those references and the offsets are adjusted to -// their real location. -// -//===----------------------------------------------------------------------===// - -void MipsRegisterInfo::adjustMipsStackFrame(MachineFunction &MF) const -{ - MachineFrameInfo *MFI = MF.getFrameInfo(); - MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); - unsigned StackAlign = MF.getTarget().getFrameInfo()->getStackAlignment(); - unsigned RegSize = Subtarget.isGP32bit() ? 4 : 8; - bool HasGP = MipsFI->needGPSaveRestore(); - - // Min and Max CSI FrameIndex. - int MinCSFI = -1, MaxCSFI = -1; - - // See the description at MipsMachineFunction.h - int TopCPUSavedRegOff = -1, TopFPUSavedRegOff = -1; - - // Replace the dummy '0' SPOffset by the negative offsets, as explained on - // LowerFormalArguments. Leaving '0' for while is necessary to avoid - // the approach done by calculateFrameObjectOffsets to the stack frame. - MipsFI->adjustLoadArgsFI(MFI); - MipsFI->adjustStoreVarArgsFI(MFI); - - // It happens that the default stack frame allocation order does not directly - // map to the convention used for mips. So we must fix it. We move the callee - // save register slots after the local variables area, as described in the - // stack frame above. - unsigned CalleeSavedAreaSize = 0; - if (!CSI.empty()) { - MinCSFI = CSI[0].getFrameIdx(); - MaxCSFI = CSI[CSI.size()-1].getFrameIdx(); - } - for (unsigned i = 0, e = CSI.size(); i != e; ++i) - CalleeSavedAreaSize += MFI->getObjectAlignment(CSI[i].getFrameIdx()); - - unsigned StackOffset = HasGP ? (MipsFI->getGPStackOffset()+RegSize) - : (Subtarget.isABI_O32() ? 16 : 0); - - // Adjust local variables. They should come on the stack right - // after the arguments. - int LastOffsetFI = -1; - for (int i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) { - if (i >= MinCSFI && i <= MaxCSFI) - continue; - if (MFI->isDeadObjectIndex(i)) - continue; - unsigned Offset = - StackOffset + MFI->getObjectOffset(i) - CalleeSavedAreaSize; - if (LastOffsetFI == -1) - LastOffsetFI = i; - if (Offset > MFI->getObjectOffset(LastOffsetFI)) - LastOffsetFI = i; - MFI->setObjectOffset(i, Offset); - } - - // Adjust CPU Callee Saved Registers Area. Registers RA and FP must - // be saved in this CPU Area. This whole area must be aligned to the - // default Stack Alignment requirements. - if (LastOffsetFI >= 0) - StackOffset = MFI->getObjectOffset(LastOffsetFI)+ - MFI->getObjectSize(LastOffsetFI); - StackOffset = ((StackOffset+StackAlign-1)/StackAlign*StackAlign); - - for (unsigned i = 0, e = CSI.size(); i != e ; ++i) { - unsigned Reg = CSI[i].getReg(); - if (!Mips::CPURegsRegisterClass->contains(Reg)) - break; - MFI->setObjectOffset(CSI[i].getFrameIdx(), StackOffset); - TopCPUSavedRegOff = StackOffset; - StackOffset += MFI->getObjectAlignment(CSI[i].getFrameIdx()); - } - - // Stack locations for FP and RA. If only one of them is used, - // the space must be allocated for both, otherwise no space at all. - if (hasFP(MF) || MFI->adjustsStack()) { - // FP stack location - MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true), - StackOffset); - MipsFI->setFPStackOffset(StackOffset); - TopCPUSavedRegOff = StackOffset; - StackOffset += RegSize; - - // SP stack location - MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true), - StackOffset); - MipsFI->setRAStackOffset(StackOffset); - StackOffset += RegSize; - - if (MFI->adjustsStack()) - TopCPUSavedRegOff += RegSize; - } - - StackOffset = ((StackOffset+StackAlign-1)/StackAlign*StackAlign); - - // Adjust FPU Callee Saved Registers Area. This Area must be - // aligned to the default Stack Alignment requirements. - for (unsigned i = 0, e = CSI.size(); i != e; ++i) { - unsigned Reg = CSI[i].getReg(); - if (Mips::CPURegsRegisterClass->contains(Reg)) - continue; - MFI->setObjectOffset(CSI[i].getFrameIdx(), StackOffset); - TopFPUSavedRegOff = StackOffset; - StackOffset += MFI->getObjectAlignment(CSI[i].getFrameIdx()); - } - StackOffset = ((StackOffset+StackAlign-1)/StackAlign*StackAlign); - - // Update frame info - MFI->setStackSize(StackOffset); - - // Recalculate the final tops offset. The final values must be '0' - // if there isn't a callee saved register for CPU or FPU, otherwise - // a negative offset is needed. - if (TopCPUSavedRegOff >= 0) - MipsFI->setCPUTopSavedRegOff(TopCPUSavedRegOff-StackOffset); - - if (TopFPUSavedRegOff >= 0) - MipsFI->setFPUTopSavedRegOff(TopFPUSavedRegOff-StackOffset); -} - -// hasFP - Return true if the specified function should have a dedicated frame -// pointer register. This is true if the function has variable sized allocas or -// if frame pointer elimination is disabled. -bool MipsRegisterInfo:: -hasFP(const MachineFunction &MF) const { - const MachineFrameInfo *MFI = MF.getFrameInfo(); - return DisableFramePointerElim(MF) || MFI->hasVarSizedObjects(); -} - // This function eliminate ADJCALLSTACKDOWN, // ADJCALLSTACKUP pseudo instructions void MipsRegisterInfo:: @@ -363,106 +184,6 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, } void MipsRegisterInfo:: -emitPrologue(MachineFunction &MF) const -{ - MachineBasicBlock &MBB = MF.front(); - MachineFrameInfo *MFI = MF.getFrameInfo(); - MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - MachineBasicBlock::iterator MBBI = MBB.begin(); - DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); - bool isPIC = (MF.getTarget().getRelocationModel() == Reloc::PIC_); - - // Get the right frame order for Mips. - adjustMipsStackFrame(MF); - - // Get the number of bytes to allocate from the FrameInfo. - unsigned StackSize = MFI->getStackSize(); - - // No need to allocate space on the stack. - if (StackSize == 0 && !MFI->adjustsStack()) return; - - int FPOffset = MipsFI->getFPStackOffset(); - int RAOffset = MipsFI->getRAStackOffset(); - - BuildMI(MBB, MBBI, dl, TII.get(Mips::NOREORDER)); - - // TODO: check need from GP here. - if (isPIC && Subtarget.isABI_O32()) - BuildMI(MBB, MBBI, dl, TII.get(Mips::CPLOAD)).addReg(getPICCallReg()); - BuildMI(MBB, MBBI, dl, TII.get(Mips::NOMACRO)); - - // Adjust stack : addi sp, sp, (-imm) - BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDiu), Mips::SP) - .addReg(Mips::SP).addImm(-StackSize); - - // Save the return address only if the function isnt a leaf one. - // sw $ra, stack_loc($sp) - if (MFI->adjustsStack()) { - BuildMI(MBB, MBBI, dl, TII.get(Mips::SW)) - .addReg(Mips::RA).addImm(RAOffset).addReg(Mips::SP); - } - - // if framepointer enabled, save it and set it - // to point to the stack pointer - if (hasFP(MF)) { - // sw $fp,stack_loc($sp) - BuildMI(MBB, MBBI, dl, TII.get(Mips::SW)) - .addReg(Mips::FP).addImm(FPOffset).addReg(Mips::SP); - - // move $fp, $sp - BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDu), Mips::FP) - .addReg(Mips::SP).addReg(Mips::ZERO); - } - - // Restore GP from the saved stack location - if (MipsFI->needGPSaveRestore()) - BuildMI(MBB, MBBI, dl, TII.get(Mips::CPRESTORE)) - .addImm(MipsFI->getGPStackOffset()); -} - -void MipsRegisterInfo:: -emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const -{ - MachineBasicBlock::iterator MBBI = prior(MBB.end()); - MachineFrameInfo *MFI = MF.getFrameInfo(); - MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - DebugLoc dl = MBBI->getDebugLoc(); - - // Get the number of bytes from FrameInfo - int NumBytes = (int) MFI->getStackSize(); - - // Get the FI's where RA and FP are saved. - int FPOffset = MipsFI->getFPStackOffset(); - int RAOffset = MipsFI->getRAStackOffset(); - - // if framepointer enabled, restore it and restore the - // stack pointer - if (hasFP(MF)) { - // move $sp, $fp - BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDu), Mips::SP) - .addReg(Mips::FP).addReg(Mips::ZERO); - - // lw $fp,stack_loc($sp) - BuildMI(MBB, MBBI, dl, TII.get(Mips::LW), Mips::FP) - .addImm(FPOffset).addReg(Mips::SP); - } - - // Restore the return address only if the function isnt a leaf one. - // lw $ra, stack_loc($sp) - if (MFI->adjustsStack()) { - BuildMI(MBB, MBBI, dl, TII.get(Mips::LW), Mips::RA) - .addImm(RAOffset).addReg(Mips::SP); - } - - // adjust stack : insert addi sp, sp, (imm) - if (NumBytes) { - BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDiu), Mips::SP) - .addReg(Mips::SP).addImm(NumBytes); - } -} - - -void MipsRegisterInfo:: processFunctionBeforeFrameFinalized(MachineFunction &MF) const { // Set the stack offset where GP must be saved/loaded from. MachineFrameInfo *MFI = MF.getFrameInfo(); @@ -478,7 +199,9 @@ getRARegister() const { unsigned MipsRegisterInfo:: getFrameRegister(const MachineFunction &MF) const { - return hasFP(MF) ? Mips::FP : Mips::SP; + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + + return TFI->hasFP(MF) ? Mips::FP : Mips::SP; } unsigned MipsRegisterInfo:: diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h index 89282f8..a7f4bf9 100644 --- a/lib/Target/Mips/MipsRegisterInfo.h +++ b/lib/Target/Mips/MipsRegisterInfo.h @@ -44,8 +44,6 @@ struct MipsRegisterInfo : public MipsGenRegisterInfo { BitVector getReservedRegs(const MachineFunction &MF) const; - bool hasFP(const MachineFunction &MF) const; - void eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const; @@ -56,9 +54,6 @@ struct MipsRegisterInfo : public MipsGenRegisterInfo { void processFunctionBeforeFrameFinalized(MachineFunction &MF) const; - void emitPrologue(MachineFunction &MF) const; - void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; - /// Debug information queries. unsigned getRARegister() const; unsigned getFrameRegister(const MachineFunction &MF) const; diff --git a/lib/Target/Mips/MipsSchedule.td b/lib/Target/Mips/MipsSchedule.td index 055ff32..49ca5d1 100644 --- a/lib/Target/Mips/MipsSchedule.td +++ b/lib/Target/Mips/MipsSchedule.td @@ -40,7 +40,7 @@ def IIPseudo : InstrItinClass; //===----------------------------------------------------------------------===// // Mips Generic instruction itineraries. //===----------------------------------------------------------------------===// -def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [ +def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [], [ InstrItinData<IIAlu , [InstrStage<1, [ALU]>]>, InstrItinData<IILoad , [InstrStage<3, [ALU]>]>, InstrItinData<IIStore , [InstrStage<1, [ALU]>]>, diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index 2d5fd22..e4f4b33 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -31,7 +31,7 @@ public: protected: enum MipsArchEnum { - Mips1, Mips2, Mips3, Mips4, Mips32, Mips32r2, Mips64, Mips64r2 + Mips1, Mips2, Mips3, Mips4, Mips32, Mips32r2 }; // Mips architecture version @@ -100,6 +100,8 @@ public: const std::string &CPU); bool isMips1() const { return MipsArchVersion == Mips1; } + bool isMips32() const { return MipsArchVersion >= Mips32; } + bool isMips32r2() const { return MipsArchVersion == Mips32r2; } bool isLittle() const { return IsLittle; } bool isFP64bit() const { return IsFP64bit; } diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp index ad3eb9e..7a2dd1f 100644 --- a/lib/Target/Mips/MipsTargetMachine.cpp +++ b/lib/Target/Mips/MipsTargetMachine.cpp @@ -30,18 +30,18 @@ extern "C" void LLVMInitializeMipsTarget() { // The stack is always 8 byte aligned // On function prologue, the stack is created by decrementing // its pointer. Once decremented, all references are done with positive -// offset from the stack/frame pointer, using StackGrowsUp enables +// offset from the stack/frame pointer, using StackGrowsUp enables // an easier handling. // Using CodeModel::Large enables different CALL behavior. MipsTargetMachine:: MipsTargetMachine(const Target &T, const std::string &TT, const std::string &FS, bool isLittle=false): LLVMTargetMachine(T, TT), - Subtarget(TT, FS, isLittle), + Subtarget(TT, FS, isLittle), DataLayout(isLittle ? std::string("e-p:32:32:32-i8:8:32-i16:16:32-n32") : - std::string("E-p:32:32:32-i8:8:32-i16:16:32-n32")), - InstrInfo(*this), - FrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0), + std::string("E-p:32:32:32-i8:8:32-i16:16:32-n32")), + InstrInfo(*this), + FrameLowering(Subtarget), TLInfo(*this), TSInfo(*this) { // Abicall enables PIC by default if (getRelocationModel() == Reloc::Default) { @@ -57,20 +57,20 @@ MipselTargetMachine(const Target &T, const std::string &TT, const std::string &FS) : MipsTargetMachine(T, TT, FS, true) {} -// Install an instruction selector pass using +// Install an instruction selector pass using // the ISelDag to gen Mips code. bool MipsTargetMachine:: -addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel) +addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { PM.add(createMipsISelDag(*this)); return false; } -// Implemented by targets that want to run passes immediately before -// machine code is emitted. return true if -print-machineinstrs should +// Implemented by targets that want to run passes immediately before +// machine code is emitted. return true if -print-machineinstrs should // print out the code after the passes. bool MipsTargetMachine:: -addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel) +addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { PM.add(createMipsDelaySlotFillerPass(*this)); return true; diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h index d63976f..43ab798 100644 --- a/lib/Target/Mips/MipsTargetMachine.h +++ b/lib/Target/Mips/MipsTargetMachine.h @@ -17,39 +17,40 @@ #include "MipsSubtarget.h" #include "MipsInstrInfo.h" #include "MipsISelLowering.h" +#include "MipsFrameLowering.h" #include "MipsSelectionDAGInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetFrameLowering.h" namespace llvm { class formatted_raw_ostream; - + class MipsTargetMachine : public LLVMTargetMachine { MipsSubtarget Subtarget; const TargetData DataLayout; // Calculates type size & alignment MipsInstrInfo InstrInfo; - TargetFrameInfo FrameInfo; + MipsFrameLowering FrameLowering; MipsTargetLowering TLInfo; MipsSelectionDAGInfo TSInfo; public: MipsTargetMachine(const Target &T, const std::string &TT, const std::string &FS, bool isLittle); - - virtual const MipsInstrInfo *getInstrInfo() const + + virtual const MipsInstrInfo *getInstrInfo() const { return &InstrInfo; } - virtual const TargetFrameInfo *getFrameInfo() const - { return &FrameInfo; } - virtual const MipsSubtarget *getSubtargetImpl() const + virtual const TargetFrameLowering *getFrameLowering() const + { return &FrameLowering; } + virtual const MipsSubtarget *getSubtargetImpl() const { return &Subtarget; } - virtual const TargetData *getTargetData() const + virtual const TargetData *getTargetData() const { return &DataLayout;} virtual const MipsRegisterInfo *getRegisterInfo() const { return &InstrInfo.getRegisterInfo(); } - virtual const MipsTargetLowering *getTargetLowering() const { + virtual const MipsTargetLowering *getTargetLowering() const { return &TLInfo; } diff --git a/lib/Target/Mips/MipsTargetObjectFile.cpp b/lib/Target/Mips/MipsTargetObjectFile.cpp index 405f419..cf5d1b5 100644 --- a/lib/Target/Mips/MipsTargetObjectFile.cpp +++ b/lib/Target/Mips/MipsTargetObjectFile.cpp @@ -16,6 +16,7 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/ELF.h" using namespace llvm; static cl::opt<unsigned> @@ -25,21 +26,21 @@ SSThreshold("mips-ssection-threshold", cl::Hidden, void MipsTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ TargetLoweringObjectFileELF::Initialize(Ctx, TM); - + SmallDataSection = - getContext().getELFSection(".sdata", MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_WRITE |MCSectionELF::SHF_ALLOC, + getContext().getELFSection(".sdata", ELF::SHT_PROGBITS, + ELF::SHF_WRITE |ELF::SHF_ALLOC, SectionKind::getDataRel()); - + SmallBSSSection = - getContext().getELFSection(".sbss", MCSectionELF::SHT_NOBITS, - MCSectionELF::SHF_WRITE |MCSectionELF::SHF_ALLOC, + getContext().getELFSection(".sbss", ELF::SHT_NOBITS, + ELF::SHF_WRITE |ELF::SHF_ALLOC, SectionKind::getBSS()); - + } -// A address must be loaded from a small section if its size is less than the -// small section size threshold. Data in this section must be addressed using +// A address must be loaded from a small section if its size is less than the +// small section size threshold. Data in this section must be addressed using // gp_rel operator. static bool IsInSmallSection(uint64_t Size) { return Size > 0 && Size <= SSThreshold; @@ -49,7 +50,7 @@ bool MipsTargetObjectFile::IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM) const { if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) return false; - + return IsGlobalInSmallSection(GV, TM, getKindForGlobal(GV, TM)); } @@ -68,11 +69,11 @@ IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM, const GlobalVariable *GVA = dyn_cast<GlobalVariable>(GV); if (!GVA) return false; - + // We can only do this for datarel or BSS objects for now. if (!Kind.isBSS() && !Kind.isDataRel()) return false; - + // If this is a internal constant string, there is a special // section for it, but not in small data/bss. if (Kind.isMergeable1ByteCString()) @@ -89,13 +90,13 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const { // TODO: Could also support "weak" symbols as well with ".gnu.linkonce.s.*" // sections? - + // Handle Small Section classification here. if (Kind.isBSS() && IsGlobalInSmallSection(GV, TM, Kind)) return SmallBSSSection; if (Kind.isDataNoRel() && IsGlobalInSmallSection(GV, TM, Kind)) return SmallDataSection; - + // Otherwise, we work the same as ELF. return TargetLoweringObjectFileELF::SelectSectionForGlobal(GV, Kind, Mang,TM); } |