diff options
author | Stephen Hines <srhines@google.com> | 2014-04-23 16:57:46 -0700 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-04-24 15:53:16 -0700 |
commit | 36b56886974eae4f9c5ebc96befd3e7bfe5de338 (patch) | |
tree | e6cfb69fbbd937f450eeb83bfb83b9da3b01275a /lib/Target/AArch64/AArch64InstrInfo.cpp | |
parent | 69a8640022b04415ae9fac62f8ab090601d8f889 (diff) | |
download | external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.zip external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.gz external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.bz2 |
Update to LLVM 3.5a.
Change-Id: Ifadecab779f128e62e430c2b4f6ddd84953ed617
Diffstat (limited to 'lib/Target/AArch64/AArch64InstrInfo.cpp')
-rw-r--r-- | lib/Target/AArch64/AArch64InstrInfo.cpp | 172 |
1 files changed, 156 insertions, 16 deletions
diff --git a/lib/Target/AArch64/AArch64InstrInfo.cpp b/lib/Target/AArch64/AArch64InstrInfo.cpp index 180110a..afb2034 100644 --- a/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -26,7 +26,6 @@ #include "llvm/IR/Function.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" - #include <algorithm> #define GET_INSTRINFO_CTOR_DTOR @@ -133,8 +132,29 @@ void AArch64InstrInfo::copyPhysReg(MachineBasicBlock &MBB, .addImm(16); return; } + } else if (AArch64::FPR8RegClass.contains(DestReg, SrcReg)) { + // The copy of two FPR8 registers is implemented by the copy of two FPR32 + const TargetRegisterInfo *TRI = &getRegisterInfo(); + unsigned Dst = TRI->getMatchingSuperReg(DestReg, AArch64::sub_8, + &AArch64::FPR32RegClass); + unsigned Src = TRI->getMatchingSuperReg(SrcReg, AArch64::sub_8, + &AArch64::FPR32RegClass); + BuildMI(MBB, I, DL, get(AArch64::FMOVss), Dst) + .addReg(Src); + return; + } else if (AArch64::FPR16RegClass.contains(DestReg, SrcReg)) { + // The copy of two FPR16 registers is implemented by the copy of two FPR32 + const TargetRegisterInfo *TRI = &getRegisterInfo(); + unsigned Dst = TRI->getMatchingSuperReg(DestReg, AArch64::sub_16, + &AArch64::FPR32RegClass); + unsigned Src = TRI->getMatchingSuperReg(SrcReg, AArch64::sub_16, + &AArch64::FPR32RegClass); + BuildMI(MBB, I, DL, get(AArch64::FMOVss), Dst) + .addReg(Src); + return; } else { - llvm_unreachable("Unknown register class in copyPhysReg"); + CopyPhysRegTuple(MBB, I, DL, DestReg, SrcReg); + return; } // E.g. ORR xDst, xzr, xSrc, lsl #0 @@ -144,6 +164,55 @@ void AArch64InstrInfo::copyPhysReg(MachineBasicBlock &MBB, .addImm(0); } +void AArch64InstrInfo::CopyPhysRegTuple(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + DebugLoc DL, unsigned DestReg, + unsigned SrcReg) const { + unsigned SubRegs; + bool IsQRegs; + if (AArch64::DPairRegClass.contains(DestReg, SrcReg)) { + SubRegs = 2; + IsQRegs = false; + } else if (AArch64::DTripleRegClass.contains(DestReg, SrcReg)) { + SubRegs = 3; + IsQRegs = false; + } else if (AArch64::DQuadRegClass.contains(DestReg, SrcReg)) { + SubRegs = 4; + IsQRegs = false; + } else if (AArch64::QPairRegClass.contains(DestReg, SrcReg)) { + SubRegs = 2; + IsQRegs = true; + } else if (AArch64::QTripleRegClass.contains(DestReg, SrcReg)) { + SubRegs = 3; + IsQRegs = true; + } else if (AArch64::QQuadRegClass.contains(DestReg, SrcReg)) { + SubRegs = 4; + IsQRegs = true; + } else + llvm_unreachable("Unknown register class"); + + unsigned BeginIdx = IsQRegs ? AArch64::qsub_0 : AArch64::dsub_0; + int Spacing = 1; + const TargetRegisterInfo *TRI = &getRegisterInfo(); + // Copy register tuples backward when the first Dest reg overlaps + // with SrcReg. + if (TRI->regsOverlap(SrcReg, TRI->getSubReg(DestReg, BeginIdx))) { + BeginIdx = BeginIdx + (SubRegs - 1); + Spacing = -1; + } + + unsigned Opc = IsQRegs ? AArch64::ORRvvv_16B : AArch64::ORRvvv_8B; + for (unsigned i = 0; i != SubRegs; ++i) { + unsigned Dst = TRI->getSubReg(DestReg, BeginIdx + i * Spacing); + unsigned Src = TRI->getSubReg(SrcReg, BeginIdx + i * Spacing); + assert(Dst && Src && "Bad sub-register"); + BuildMI(MBB, I, I->getDebugLoc(), get(Opc), Dst) + .addReg(Src) + .addReg(Src); + } + return; +} + /// Does the Opcode represent a conditional branch that we can remove and re-add /// at the end of a basic block? static bool isCondBranch(unsigned Opc) { @@ -418,10 +487,12 @@ AArch64InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, default: llvm_unreachable("Unknown size for regclass"); } - } else { - assert((RC->hasType(MVT::f32) || RC->hasType(MVT::f64) || - RC->hasType(MVT::f128)) - && "Expected integer or floating type for store"); + } else if (AArch64::FPR8RegClass.hasSubClassEq(RC)) { + StoreOp = AArch64::LSFP8_STR; + } else if (AArch64::FPR16RegClass.hasSubClassEq(RC)) { + StoreOp = AArch64::LSFP16_STR; + } else if (RC->hasType(MVT::f32) || RC->hasType(MVT::f64) || + RC->hasType(MVT::f128)) { switch (RC->getSize()) { case 4: StoreOp = AArch64::LSFP32_STR; break; case 8: StoreOp = AArch64::LSFP64_STR; break; @@ -429,6 +500,28 @@ AArch64InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, default: llvm_unreachable("Unknown size for regclass"); } + } else { // For a super register class has more than one sub registers + if (AArch64::DPairRegClass.hasSubClassEq(RC)) + StoreOp = AArch64::ST1x2_8B; + else if (AArch64::DTripleRegClass.hasSubClassEq(RC)) + StoreOp = AArch64::ST1x3_8B; + else if (AArch64::DQuadRegClass.hasSubClassEq(RC)) + StoreOp = AArch64::ST1x4_8B; + else if (AArch64::QPairRegClass.hasSubClassEq(RC)) + StoreOp = AArch64::ST1x2_16B; + else if (AArch64::QTripleRegClass.hasSubClassEq(RC)) + StoreOp = AArch64::ST1x3_16B; + else if (AArch64::QQuadRegClass.hasSubClassEq(RC)) + StoreOp = AArch64::ST1x4_16B; + else + llvm_unreachable("Unknown reg class"); + + MachineInstrBuilder NewMI = BuildMI(MBB, MBBI, DL, get(StoreOp)); + // Vector store has different operands from other store instructions. + NewMI.addFrameIndex(FrameIdx) + .addReg(SrcReg, getKillRegState(isKill)) + .addMemOperand(MMO); + return; } MachineInstrBuilder NewMI = BuildMI(MBB, MBBI, DL, get(StoreOp)); @@ -464,10 +557,12 @@ AArch64InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, default: llvm_unreachable("Unknown size for regclass"); } - } else { - assert((RC->hasType(MVT::f32) || RC->hasType(MVT::f64) - || RC->hasType(MVT::f128)) - && "Expected integer or floating type for store"); + } else if (AArch64::FPR8RegClass.hasSubClassEq(RC)) { + LoadOp = AArch64::LSFP8_LDR; + } else if (AArch64::FPR16RegClass.hasSubClassEq(RC)) { + LoadOp = AArch64::LSFP16_LDR; + } else if (RC->hasType(MVT::f32) || RC->hasType(MVT::f64) || + RC->hasType(MVT::f128)) { switch (RC->getSize()) { case 4: LoadOp = AArch64::LSFP32_LDR; break; case 8: LoadOp = AArch64::LSFP64_LDR; break; @@ -475,6 +570,27 @@ AArch64InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, default: llvm_unreachable("Unknown size for regclass"); } + } else { // For a super register class has more than one sub registers + if (AArch64::DPairRegClass.hasSubClassEq(RC)) + LoadOp = AArch64::LD1x2_8B; + else if (AArch64::DTripleRegClass.hasSubClassEq(RC)) + LoadOp = AArch64::LD1x3_8B; + else if (AArch64::DQuadRegClass.hasSubClassEq(RC)) + LoadOp = AArch64::LD1x4_8B; + else if (AArch64::QPairRegClass.hasSubClassEq(RC)) + LoadOp = AArch64::LD1x2_16B; + else if (AArch64::QTripleRegClass.hasSubClassEq(RC)) + LoadOp = AArch64::LD1x3_16B; + else if (AArch64::QQuadRegClass.hasSubClassEq(RC)) + LoadOp = AArch64::LD1x4_16B; + else + llvm_unreachable("Unknown reg class"); + + MachineInstrBuilder NewMI = BuildMI(MBB, MBBI, DL, get(LoadOp), DestReg); + // Vector load has different operands from other load instructions. + NewMI.addFrameIndex(FrameIdx) + .addMemOperand(MMO); + return; } MachineInstrBuilder NewMI = BuildMI(MBB, MBBI, DL, get(LoadOp), DestReg); @@ -513,7 +629,8 @@ void AArch64InstrInfo::getAddressConstraints(const MachineInstr &MI, int &AccessScale, int &MinOffset, int &MaxOffset) const { switch (MI.getOpcode()) { - default: llvm_unreachable("Unkown load/store kind"); + default: + llvm_unreachable("Unknown load/store kind"); case TargetOpcode::DBG_VALUE: AccessScale = 1; MinOffset = INT_MIN; @@ -572,6 +689,32 @@ void AArch64InstrInfo::getAddressConstraints(const MachineInstr &MI, MinOffset = -0x40 * AccessScale; MaxOffset = 0x3f * AccessScale; return; + case AArch64::LD1x2_8B: case AArch64::ST1x2_8B: + AccessScale = 16; + MinOffset = 0; + MaxOffset = 0xfff * AccessScale; + return; + case AArch64::LD1x3_8B: case AArch64::ST1x3_8B: + AccessScale = 24; + MinOffset = 0; + MaxOffset = 0xfff * AccessScale; + return; + case AArch64::LD1x4_8B: case AArch64::ST1x4_8B: + case AArch64::LD1x2_16B: case AArch64::ST1x2_16B: + AccessScale = 32; + MinOffset = 0; + MaxOffset = 0xfff * AccessScale; + return; + case AArch64::LD1x3_16B: case AArch64::ST1x3_16B: + AccessScale = 48; + MinOffset = 0; + MaxOffset = 0xfff * AccessScale; + return; + case AArch64::LD1x4_16B: case AArch64::ST1x4_16B: + AccessScale = 64; + MinOffset = 0; + MaxOffset = 0xfff * AccessScale; + return; } } @@ -587,18 +730,15 @@ unsigned AArch64InstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { if (MI.getOpcode() == AArch64::INLINEASM) return getInlineAsmLength(MI.getOperand(0).getSymbolName(), MAI); - if (MI.isLabel()) - return 0; - switch (MI.getOpcode()) { case TargetOpcode::BUNDLE: return getInstBundleLength(MI); case TargetOpcode::IMPLICIT_DEF: case TargetOpcode::KILL: - case TargetOpcode::PROLOG_LABEL: + case TargetOpcode::CFI_INSTRUCTION: case TargetOpcode::EH_LABEL: + case TargetOpcode::GC_LABEL: case TargetOpcode::DBG_VALUE: - return 0; case AArch64::TLSDESCCALL: return 0; default: |