diff options
Diffstat (limited to 'lib/Target/ARM/ARMISelDAGToDAG.cpp')
| -rw-r--r-- | lib/Target/ARM/ARMISelDAGToDAG.cpp | 308 |
1 files changed, 16 insertions, 292 deletions
diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index f75dd4de3f96..8d32510e2004 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -15,6 +15,7 @@ #include "ARMBaseInstrInfo.h" #include "ARMTargetMachine.h" #include "MCTargetDesc/ARMAddressingModes.h" +#include "Utils/ARMBaseInfo.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" @@ -22,6 +23,7 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/CodeGen/TargetLowering.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" @@ -31,7 +33,6 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetOptions.h" using namespace llvm; @@ -49,11 +50,6 @@ DisableShifterOp("disable-shifter-op", cl::Hidden, /// namespace { -enum AddrMode2Type { - AM2_BASE, // Simple AM2 (+-imm12) - AM2_SHOP // Shifter-op AM2 -}; - class ARMDAGToDAGISel : public SelectionDAGISel { /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can /// make the right decision when generating code for different targets. @@ -104,26 +100,6 @@ public: bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm); bool SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc); - AddrMode2Type SelectAddrMode2Worker(SDValue N, SDValue &Base, - SDValue &Offset, SDValue &Opc); - bool SelectAddrMode2Base(SDValue N, SDValue &Base, SDValue &Offset, - SDValue &Opc) { - return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_BASE; - } - - bool SelectAddrMode2ShOp(SDValue N, SDValue &Base, SDValue &Offset, - SDValue &Opc) { - return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_SHOP; - } - - bool SelectAddrMode2(SDValue N, SDValue &Base, SDValue &Offset, - SDValue &Opc) { - SelectAddrMode2Worker(N, Base, Offset, Opc); -// return SelectAddrMode2ShOp(N, Base, Offset, Opc); - // This always matches one way or another. - return true; - } - bool SelectCMOVPred(SDValue N, SDValue &Pred, SDValue &Reg) { const ConstantSDNode *CN = cast<ConstantSDNode>(N); Pred = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(N), MVT::i32); @@ -753,148 +729,6 @@ bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, return true; } - -//----- - -AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N, - SDValue &Base, - SDValue &Offset, - SDValue &Opc) { - if (N.getOpcode() == ISD::MUL && - (!(Subtarget->isLikeA9() || Subtarget->isSwift()) || N.hasOneUse())) { - if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { - // X * [3,5,9] -> X + X * [2,4,8] etc. - int RHSC = (int)RHS->getZExtValue(); - if (RHSC & 1) { - RHSC = RHSC & ~1; - ARM_AM::AddrOpc AddSub = ARM_AM::add; - if (RHSC < 0) { - AddSub = ARM_AM::sub; - RHSC = - RHSC; - } - if (isPowerOf2_32(RHSC)) { - unsigned ShAmt = Log2_32(RHSC); - Base = Offset = N.getOperand(0); - Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, - ARM_AM::lsl), - SDLoc(N), MVT::i32); - return AM2_SHOP; - } - } - } - } - - if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && - // ISD::OR that is equivalent to an ADD. - !CurDAG->isBaseWithConstantOffset(N)) { - Base = N; - if (N.getOpcode() == ISD::FrameIndex) { - int FI = cast<FrameIndexSDNode>(N)->getIndex(); - Base = CurDAG->getTargetFrameIndex( - FI, TLI->getPointerTy(CurDAG->getDataLayout())); - } else if (N.getOpcode() == ARMISD::Wrapper && - N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress && - N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol && - N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) { - Base = N.getOperand(0); - } - Offset = CurDAG->getRegister(0, MVT::i32); - Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0, - ARM_AM::no_shift), - SDLoc(N), MVT::i32); - return AM2_BASE; - } - - // Match simple R +/- imm12 operands. - if (N.getOpcode() != ISD::SUB) { - int RHSC; - if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1, - -0x1000+1, 0x1000, RHSC)) { // 12 bits. - Base = N.getOperand(0); - if (Base.getOpcode() == ISD::FrameIndex) { - int FI = cast<FrameIndexSDNode>(Base)->getIndex(); - Base = CurDAG->getTargetFrameIndex( - FI, TLI->getPointerTy(CurDAG->getDataLayout())); - } - Offset = CurDAG->getRegister(0, MVT::i32); - - ARM_AM::AddrOpc AddSub = ARM_AM::add; - if (RHSC < 0) { - AddSub = ARM_AM::sub; - RHSC = - RHSC; - } - Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC, - ARM_AM::no_shift), - SDLoc(N), MVT::i32); - return AM2_BASE; - } - } - - if ((Subtarget->isLikeA9() || Subtarget->isSwift()) && !N.hasOneUse()) { - // Compute R +/- (R << N) and reuse it. - Base = N; - Offset = CurDAG->getRegister(0, MVT::i32); - Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0, - ARM_AM::no_shift), - SDLoc(N), MVT::i32); - return AM2_BASE; - } - - // Otherwise this is R +/- [possibly shifted] R. - ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub; - ARM_AM::ShiftOpc ShOpcVal = - ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode()); - unsigned ShAmt = 0; - - Base = N.getOperand(0); - Offset = N.getOperand(1); - - if (ShOpcVal != ARM_AM::no_shift) { - // Check to see if the RHS of the shift is a constant, if not, we can't fold - // it. - if (ConstantSDNode *Sh = - dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) { - ShAmt = Sh->getZExtValue(); - if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt)) - Offset = N.getOperand(1).getOperand(0); - else { - ShAmt = 0; - ShOpcVal = ARM_AM::no_shift; - } - } else { - ShOpcVal = ARM_AM::no_shift; - } - } - - // Try matching (R shl C) + (R). - if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift && - !(Subtarget->isLikeA9() || Subtarget->isSwift() || - N.getOperand(0).hasOneUse())) { - ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode()); - if (ShOpcVal != ARM_AM::no_shift) { - // Check to see if the RHS of the shift is a constant, if not, we can't - // fold it. - if (ConstantSDNode *Sh = - dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) { - ShAmt = Sh->getZExtValue(); - if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) { - Offset = N.getOperand(0).getOperand(0); - Base = N.getOperand(1); - } else { - ShAmt = 0; - ShOpcVal = ARM_AM::no_shift; - } - } else { - ShOpcVal = ARM_AM::no_shift; - } - } - } - - Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), - SDLoc(N), MVT::i32); - return AM2_SHOP; -} - bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N, SDValue &Offset, SDValue &Opc) { unsigned Opcode = Op->getOpcode(); @@ -3764,66 +3598,10 @@ static void getIntOperandsFromRegisterString(StringRef RegString, // which mode it is to be used, e.g. usr. Returns -1 to signify that the string // was invalid. static inline int getBankedRegisterMask(StringRef RegString) { - return StringSwitch<int>(RegString.lower()) - .Case("r8_usr", 0x00) - .Case("r9_usr", 0x01) - .Case("r10_usr", 0x02) - .Case("r11_usr", 0x03) - .Case("r12_usr", 0x04) - .Case("sp_usr", 0x05) - .Case("lr_usr", 0x06) - .Case("r8_fiq", 0x08) - .Case("r9_fiq", 0x09) - .Case("r10_fiq", 0x0a) - .Case("r11_fiq", 0x0b) - .Case("r12_fiq", 0x0c) - .Case("sp_fiq", 0x0d) - .Case("lr_fiq", 0x0e) - .Case("lr_irq", 0x10) - .Case("sp_irq", 0x11) - .Case("lr_svc", 0x12) - .Case("sp_svc", 0x13) - .Case("lr_abt", 0x14) - .Case("sp_abt", 0x15) - .Case("lr_und", 0x16) - .Case("sp_und", 0x17) - .Case("lr_mon", 0x1c) - .Case("sp_mon", 0x1d) - .Case("elr_hyp", 0x1e) - .Case("sp_hyp", 0x1f) - .Case("spsr_fiq", 0x2e) - .Case("spsr_irq", 0x30) - .Case("spsr_svc", 0x32) - .Case("spsr_abt", 0x34) - .Case("spsr_und", 0x36) - .Case("spsr_mon", 0x3c) - .Case("spsr_hyp", 0x3e) - .Default(-1); -} - -// Maps a MClass special register string to its value for use in the -// t2MRS_M / t2MSR_M instruction nodes as the SYSm value operand. -// Returns -1 to signify that the string was invalid. -static inline int getMClassRegisterSYSmValueMask(StringRef RegString) { - return StringSwitch<int>(RegString.lower()) - .Case("apsr", 0x0) - .Case("iapsr", 0x1) - .Case("eapsr", 0x2) - .Case("xpsr", 0x3) - .Case("ipsr", 0x5) - .Case("epsr", 0x6) - .Case("iepsr", 0x7) - .Case("msp", 0x8) - .Case("psp", 0x9) - .Case("primask", 0x10) - .Case("basepri", 0x11) - .Case("basepri_max", 0x12) - .Case("faultmask", 0x13) - .Case("control", 0x14) - .Case("msplim", 0x0a) - .Case("psplim", 0x0b) - .Case("sp", 0x18) - .Default(-1); + auto TheReg = ARMBankedReg::lookupBankedRegByName(RegString.lower()); + if (!TheReg) + return -1; + return TheReg->Encoding; } // The flags here are common to those allowed for apsr in the A class cores and @@ -3839,58 +3617,15 @@ static inline int getMClassFlagsMask(StringRef Flags) { .Default(-1); } -static int getMClassRegisterMask(StringRef Reg, StringRef Flags, bool IsRead, - const ARMSubtarget *Subtarget) { - // Ensure that the register (without flags) was a valid M Class special - // register. - int SYSmvalue = getMClassRegisterSYSmValueMask(Reg); - if (SYSmvalue == -1) - return -1; - - // basepri, basepri_max and faultmask are only valid for V7m. - if (!Subtarget->hasV7Ops() && SYSmvalue >= 0x11 && SYSmvalue <= 0x13) - return -1; - - if (Subtarget->has8MSecExt() && Flags.lower() == "ns") { - Flags = ""; - SYSmvalue |= 0x80; - } - - if (!Subtarget->has8MSecExt() && - (SYSmvalue == 0xa || SYSmvalue == 0xb || SYSmvalue > 0x14)) - return -1; - - if (!Subtarget->hasV8MMainlineOps() && - (SYSmvalue == 0x8a || SYSmvalue == 0x8b || SYSmvalue == 0x91 || - SYSmvalue == 0x93)) - return -1; - - // If it was a read then we won't be expecting flags and so at this point - // we can return the mask. - if (IsRead) { - if (Flags.empty()) - return SYSmvalue; - else - return -1; - } - - // We know we are now handling a write so need to get the mask for the flags. - int Mask = getMClassFlagsMask(Flags); - - // Only apsr, iapsr, eapsr, xpsr can have flags. The other register values - // shouldn't have flags present. - if ((SYSmvalue < 0x4 && Mask == -1) || (SYSmvalue > 0x4 && !Flags.empty())) - return -1; - - // The _g and _nzcvqg versions are only valid if the DSP extension is - // available. - if (!Subtarget->hasDSP() && (Mask & 0x1)) +// Maps MClass special registers string to its value for use in the +// t2MRS_M/t2MSR_M instruction nodes as the SYSm value operand. +// Returns -1 to signify that the string was invalid. +static int getMClassRegisterMask(StringRef Reg, const ARMSubtarget *Subtarget) { + auto TheReg = ARMSysReg::lookupMClassSysRegByName(Reg); + const FeatureBitset &FeatureBits = Subtarget->getFeatureBits(); + if (!TheReg || !TheReg->hasRequiredFeatures(FeatureBits)) return -1; - - // The register was valid so need to put the mask in the correct place - // (the flags need to be in bits 11-10) and combine with the SYSmvalue to - // construct the operand for the instruction node. - return SYSmvalue | Mask << 10; + return (int)(TheReg->Encoding & 0xFFF); // SYSm value } static int getARClassRegisterMask(StringRef Reg, StringRef Flags) { @@ -4032,13 +3767,7 @@ bool ARMDAGToDAGISel::tryReadRegister(SDNode *N){ // is an acceptable value, so check that a mask can be constructed from the // string. if (Subtarget->isMClass()) { - StringRef Flags = "", Reg = SpecialReg; - if (Reg.endswith("_ns")) { - Flags = "ns"; - Reg = Reg.drop_back(3); - } - - int SYSmValue = getMClassRegisterMask(Reg, Flags, true, Subtarget); + int SYSmValue = getMClassRegisterMask(SpecialReg, Subtarget); if (SYSmValue == -1) return false; @@ -4149,12 +3878,7 @@ bool ARMDAGToDAGISel::tryWriteRegister(SDNode *N){ // If the target was M Class then need to validate the special register value // and retrieve the mask for use in the instruction node. if (Subtarget->isMClass()) { - // basepri_max gets split so need to correct Reg and Flags. - if (SpecialReg == "basepri_max") { - Reg = SpecialReg; - Flags = ""; - } - int SYSmValue = getMClassRegisterMask(Reg, Flags, false, Subtarget); + int SYSmValue = getMClassRegisterMask(SpecialReg, Subtarget); if (SYSmValue == -1) return false; |
