+ CriticalPathRCs.push_back(isGP64bit() ?
+ &Mips::GPR64RegClass : &Mips::GPR32RegClass);
+}
+
+CodeGenOpt::Level MipsSubtarget::getOptLevelToEnablePostRAScheduler() const {
+ return CodeGenOpt::Aggressive;
+}
+
+MipsSubtarget &
+MipsSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS,
+ const TargetMachine *TM) {
+ std::string CPUName = selectMipsCPU(TargetTriple, CPU);
+
+ // Parse features string.
+ ParseSubtargetFeatures(CPUName, FS);
+ // Initialize scheduling itinerary for the specified CPU.
+ InstrItins = getInstrItineraryForCPU(CPUName);
+
+ if (InMips16Mode && !TM->Options.UseSoftFloat)
+ InMips16HardFloat = true;
+
+ return *this;
+}
+
+//FIXME: This logic for reseting the subtarget along with
+// the helper classes can probably be simplified but there are a lot of
+// cases so we will defer rewriting this to later.
+//
+void MipsSubtarget::resetSubtarget(MachineFunction *MF) {
+ bool ChangeToMips16 = false, ChangeToNoMips16 = false;
+ DEBUG(dbgs() << "resetSubtargetFeatures" << "\n");
+ AttributeSet FnAttrs = MF->getFunction()->getAttributes();
+ ChangeToMips16 = FnAttrs.hasAttribute(AttributeSet::FunctionIndex,
+ "mips16");
+ ChangeToNoMips16 = FnAttrs.hasAttribute(AttributeSet::FunctionIndex,
+ "nomips16");
+ assert (!(ChangeToMips16 & ChangeToNoMips16) &&
+ "mips16 and nomips16 specified on the same function");
+ if (ChangeToMips16) {
+ if (PreviousInMips16Mode)
+ return;
+ OverrideMode = Mips16Override;
+ PreviousInMips16Mode = true;
+ setHelperClassesMips16();
+ return;
+ } else if (ChangeToNoMips16) {
+ if (!PreviousInMips16Mode)
+ return;
+ OverrideMode = NoMips16Override;
+ PreviousInMips16Mode = false;
+ setHelperClassesMipsSE();
+ return;
+ } else {
+ if (OverrideMode == NoOverride)
+ return;
+ OverrideMode = NoOverride;
+ DEBUG(dbgs() << "back to default" << "\n");
+ if (inMips16Mode() && !PreviousInMips16Mode) {
+ setHelperClassesMips16();
+ PreviousInMips16Mode = true;
+ } else if (!inMips16Mode() && PreviousInMips16Mode) {
+ setHelperClassesMipsSE();
+ PreviousInMips16Mode = false;
+ }
+ return;
+ }
+}
+
+void MipsSubtarget::setHelperClassesMips16() {
+ InstrInfoSE.swap(InstrInfo);
+ FrameLoweringSE.swap(FrameLowering);
+ TLInfoSE.swap(TLInfo);
+ if (!InstrInfo16) {
+ InstrInfo.reset(MipsInstrInfo::create(*this));
+ FrameLowering.reset(MipsFrameLowering::create(*TM, *this));
+ TLInfo.reset(MipsTargetLowering::create(*TM, *this));
+ } else {
+ InstrInfo16.swap(InstrInfo);
+ FrameLowering16.swap(FrameLowering);
+ TLInfo16.swap(TLInfo);
+ }
+ assert(TLInfo && "null target lowering 16");
+ assert(InstrInfo && "null instr info 16");
+ assert(FrameLowering && "null frame lowering 16");
+}
+
+void MipsSubtarget::setHelperClassesMipsSE() {
+ InstrInfo16.swap(InstrInfo);
+ FrameLowering16.swap(FrameLowering);
+ TLInfo16.swap(TLInfo);
+ if (!InstrInfoSE) {
+ InstrInfo.reset(MipsInstrInfo::create(*this));
+ FrameLowering.reset(MipsFrameLowering::create(*TM, *this));
+ TLInfo.reset(MipsTargetLowering::create(*TM, *this));
+ } else {
+ InstrInfoSE.swap(InstrInfo);
+ FrameLoweringSE.swap(FrameLowering);
+ TLInfoSE.swap(TLInfo);
+ }
+ assert(TLInfo && "null target lowering in SE");
+ assert(InstrInfo && "null instr info SE");
+ assert(FrameLowering && "null frame lowering SE");
+}
+
+bool MipsSubtarget::abiUsesSoftFloat() const {
+ return TM->Options.UseSoftFloat && !InMips16HardFloat;
+}
+
+bool MipsSubtarget::useConstantIslands() {
+ DEBUG(dbgs() << "use constant islands " << Mips16ConstantIslands << "\n");
+ return Mips16ConstantIslands;
+}
+
+Reloc::Model MipsSubtarget::getRelocationModel() const {
+ return TM->getRelocationModel();