Index: lib/Target/NDS32/CMakeLists.txt =================================================================== --- lib/Target/NDS32/CMakeLists.txt +++ lib/Target/NDS32/CMakeLists.txt @@ -14,6 +14,7 @@ NDS32ISelLowering.cpp NDS32MachineFunctionInfo.cpp NDS32InstrInfo.cpp + NDS32RegisterInfo.cpp NDS32TargetMachine.cpp ) Index: lib/Target/NDS32/NDS32RegisterInfo.h =================================================================== --- /dev/null +++ lib/Target/NDS32/NDS32RegisterInfo.h @@ -0,0 +1,47 @@ +//===-- NDS32RegisterInfo.h - NDS32 Register Information Impl -*- 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 NDS32 implementation of the MRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_NDS32_NDS32REGISTERINFO_H +#define LLVM_LIB_TARGET_NDS32_NDS32REGISTERINFO_H + +#include "llvm/Target/TargetRegisterInfo.h" + +#define GET_REGINFO_HEADER +#include "NDS32GenRegisterInfo.inc" + +namespace llvm { + +struct NDS32RegisterInfo : public NDS32GenRegisterInfo { +public: + NDS32RegisterInfo(); + + const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override; + const uint32_t *getCallPreservedMask(const MachineFunction &MF, + CallingConv::ID) const override; + + BitVector getReservedRegs(const MachineFunction &MF) const override; + const TargetRegisterClass* + getPointerRegClass(const MachineFunction &MF, + unsigned Kind = 0) const override; + + void eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, unsigned FIOperandNum, + RegScavenger *RS = nullptr) const override; + + // Debug information queries. + unsigned getFrameRegister(const MachineFunction &MF) const override; +}; + +} // end namespace llvm + +#endif Index: lib/Target/NDS32/NDS32RegisterInfo.cpp =================================================================== --- /dev/null +++ lib/Target/NDS32/NDS32RegisterInfo.cpp @@ -0,0 +1,228 @@ +//===-- NDS32RegisterInfo.cpp - NDS32 Register Information ----------------===// +// +// 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 NDS32 implementation of the TargetRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#include "NDS32RegisterInfo.h" +#include "NDS32.h" +#include "NDS32MachineFunctionInfo.h" +#include "NDS32TargetMachine.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/IR/Function.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" + +using namespace llvm; + +#define DEBUG_TYPE "NDS32-reg-info" + +#define GET_REGINFO_TARGET_DESC +#include "NDS32GenRegisterInfo.inc" + +NDS32RegisterInfo::NDS32RegisterInfo() + : NDS32GenRegisterInfo(NDS32::LP) {} + +const MCPhysReg* +NDS32RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { + + return CSR_V3_SaveList; +} + +const uint32_t * +NDS32RegisterInfo::getCallPreservedMask(const MachineFunction &MF, + CallingConv::ID) const { + return CSR_V3_RegMask; +} + +BitVector NDS32RegisterInfo::getReservedRegs(const MachineFunction &MF) const { + BitVector Reserved(getNumRegs()); + const NDS32FrameLowering *TFI = getFrameLowering(MF); + + Reserved.set(NDS32::R15); + Reserved.set(NDS32::R26); + Reserved.set(NDS32::R27); + + Reserved.set(NDS32::GP); + Reserved.set(NDS32::LP); + Reserved.set(NDS32::SP); + // Mark frame pointer as reserved if needed. + if (TFI->hasFP(MF)) + Reserved.set(NDS32::FP); + + return Reserved; +} + +const TargetRegisterClass * +NDS32RegisterInfo::getPointerRegClass(const MachineFunction &MF, unsigned Kind) + const { + return &NDS32::GPRRegClass; +} + +// Return true if the instruction fit +// swi37.sp/lwi37.sp/swi37/lwi37 limitation. +static bool FitFrameBase16BitLoadStore (MachineInstr &MI, unsigned BaseReg, + int64_t Offset) { + unsigned Opc = MI.getOpcode(); + + // BaseReg must be SP or FP + if (BaseReg != NDS32::SP && BaseReg != NDS32::FP) + return false; + + // Offset limitation is (imm7u << 2) + if (!isUInt<9>(Offset)) + return false; + if (Offset % 4 != 0) + return false; + + if (Opc != NDS32::SWI && Opc != NDS32::LWI) + return false; + + // Operand 0 must be low register + unsigned Reg = MI.getOperand(0).getReg(); + if (!isNDS32LowRegister (Reg)) + return false; + + return true; +} + +void +NDS32RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, unsigned FIOperandNum, + RegScavenger *RS) const { + assert(SPAdj == 0 && "Unexpected"); + + MachineInstr &MI = *II; + MachineBasicBlock &MBB = *MI.getParent(); + MachineFunction &MF = *MBB.getParent(); + MachineFrameInfo &MFI = MF.getFrameInfo(); + const NDS32FrameLowering *TFI = getFrameLowering(MF); + const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); + DebugLoc DL = MI.getDebugLoc(); + int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); + uint64_t stackSize = MF.getFrameInfo().getStackSize(); + int64_t Offset = MF.getFrameInfo().getObjectOffset(FrameIndex); + const NDS32Subtarget &Subtarget = MF.getSubtarget(); + + DEBUG(errs() << "\nFunction : " << MF.getName() << "\n"; + errs() << "<--------->\n" << MI); + DEBUG(errs() << "FrameIndex : " << FrameIndex << "\n" + << "spOffset : " << Offset << "\n" + << "stackSize : " << stackSize << "\n"); + + unsigned BasePtr = (TFI->hasFP(MF) ? NDS32::FP : NDS32::SP); + + const std::vector &CSI = MFI.getCalleeSavedInfo(); + int MinCSFI = 0; + int MaxCSFI = -1; + + if (CSI.size()) { + MinCSFI = CSI[0].getFrameIdx(); + MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); + } + // If the FrameIndex push a callee saved register, use SP as Base + // To avoid FP not setting yet when -fno-omit-frame-pointer + // E.g. + // addi $sp, $sp, -56 + // swi $fp, [$sp + (44)] <= use SP as base + // addi $fp, $sp, 0 + if (FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI) + BasePtr = NDS32::SP; + + Offset += stackSize; + + // Fold imm into offset + Offset += MI.getOperand(FIOperandNum + 1).getImm(); + + // Use R15 as temp register + unsigned Reg = NDS32::R15; + + // Transfer to 16 bit format + // if the instruction fit swi37.sp/lwi37.sp/swi37/lwi37 limitation + if (FitFrameBase16BitLoadStore (MI, BasePtr, Offset) + && Subtarget.has16Bit()) { + unsigned OpcNew; + if (MI.getOpcode() == NDS32::LWI) + OpcNew = (BasePtr == NDS32::SP) ? NDS32::LWI37SP : NDS32::LWI37; + else + OpcNew = (BasePtr == NDS32::SP) ? NDS32::SWI37SP : NDS32::SWI37; + + MI.setDesc(TII.get(OpcNew)); + MI.getOperand(FIOperandNum).ChangeToRegister(BasePtr, false); + MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); + return; + }else if (isInt<15>(Offset)) { + MI.getOperand(FIOperandNum).ChangeToRegister(BasePtr, false); + MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); + return; + } else if (isInt<20>(Offset)) { + // movi r15, Offset + BuildMI(MBB, II, DL, TII.get(NDS32::MOVI), Reg) + .addImm(Offset); + } else { + // sethi r15, hi20 (Offset) + // ori r15, lo12 (Offset) + BuildMI(MBB, II, DL, TII.get(NDS32::SETHI), Reg) + .addImm((Offset >> 12) & 0xfffff); + BuildMI(MBB, II, DL, TII.get(NDS32::ORI), Reg).addReg(Reg) + .addImm(Offset & 0xfff); + } + // Replace FI[index] to BasePtr + r15 + MI.getOperand(FIOperandNum).ChangeToRegister(BasePtr, false); + MI.getOperand(FIOperandNum + 1).ChangeToRegister(Reg, false); + + unsigned NewOpc; + + switch (MI.getOpcode()) { + case NDS32::SWI: + NewOpc = NDS32::SW; + break; + case NDS32::SHI: + NewOpc = NDS32::SH; + break; + case NDS32::SBI: + NewOpc = NDS32::SB; + break; + case NDS32::LWI: + NewOpc = NDS32::LW; + break; + case NDS32::LHI: + NewOpc = NDS32::LH; + break; + case NDS32::LBI: + NewOpc = NDS32::LB; + break; + + default: + break; + } + + if (MI.getOpcode() == NDS32::ADDI) { + // addi ra, rb, Offset => add ra, rb, r15 + MI.setDesc(TII.get(NDS32::ADD)); + } else { + // Change load/store offset to r15 + // E.g. lwi ra, [rb + Offset] => lw ra, [rb + r15 << 0] + MI.setDesc(TII.get(NewOpc)); + // We define Shift amount as one of the input operand for LW + // So add Shift amount as 0 to fit the operand definition. + MI.addOperand(MF, MachineOperand::CreateImm(0)); + } + return; +} + +unsigned NDS32RegisterInfo::getFrameRegister(const MachineFunction &MF) const { + const NDS32FrameLowering *TFI = getFrameLowering(MF); + return TFI->hasFP(MF) ? NDS32::FP : NDS32::SP; +}