diff options
| author | Diana Picus <diana.picus@linaro.org> | 2017-01-25 08:10:40 +0000 |
|---|---|---|
| committer | Diana Picus <diana.picus@linaro.org> | 2017-01-25 08:10:40 +0000 |
| commit | 8b6c6bedcbad953260157903e03210249e5f4b90 (patch) | |
| tree | 0a2cecc06231fd1012076b7f1bf1ab626c019223 /llvm/lib/Target/ARM | |
| parent | 43a7759f4b67199d0e8eebfd19d5bf42a8b364b5 (diff) | |
| download | bcm5719-llvm-8b6c6bedcbad953260157903e03210249e5f4b90.tar.gz bcm5719-llvm-8b6c6bedcbad953260157903e03210249e5f4b90.zip | |
[ARM] GlobalISel: Support i8/i16 ABI extensions
At the moment, this means supporting the signext/zeroext attribute on the return
type of the function. For function arguments, signext/zeroext should be handled
by the caller, so there's nothing for us to do until we start lowering calls.
Note that this does not include support for other extensions (i8 to i16), those
will be added later.
Differential Revision: https://reviews.llvm.org/D27705
llvm-svn: 293034
Diffstat (limited to 'llvm/lib/Target/ARM')
| -rw-r--r-- | llvm/lib/Target/ARM/ARMCallLowering.cpp | 8 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMInstructionSelector.cpp | 42 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMLegalizerInfo.cpp | 6 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp | 3 |
4 files changed, 54 insertions, 5 deletions
diff --git a/llvm/lib/Target/ARM/ARMCallLowering.cpp b/llvm/lib/Target/ARM/ARMCallLowering.cpp index 16509564800..7c298cee3ed 100644 --- a/llvm/lib/Target/ARM/ARMCallLowering.cpp +++ b/llvm/lib/Target/ARM/ARMCallLowering.cpp @@ -60,11 +60,8 @@ struct FuncReturnHandler : public CallLowering::ValueHandler { assert(VA.getValVT().getSizeInBits() <= 32 && "Unsupported value size"); assert(VA.getLocVT().getSizeInBits() == 32 && "Unsupported location size"); - assert(VA.getLocInfo() != CCValAssign::SExt && - VA.getLocInfo() != CCValAssign::ZExt && - "ABI extensions not supported yet"); - - MIRBuilder.buildCopy(PhysReg, ValVReg); + unsigned ExtReg = extendRegister(ValVReg, VA); + MIRBuilder.buildCopy(PhysReg, ExtReg); MIB.addUse(PhysReg, RegState::Implicit); } @@ -156,6 +153,7 @@ struct FormalArgHandler : public CallLowering::ValueHandler { assert(VA.getValVT().getSizeInBits() <= 32 && "Unsupported value size"); assert(VA.getLocVT().getSizeInBits() == 32 && "Unsupported location size"); + // The caller should handle all necesary extensions. MIRBuilder.getMBB().addLiveIn(PhysReg); MIRBuilder.buildCopy(ValVReg, PhysReg); } diff --git a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp index 55d4f41e252..dccb8578acd 100644 --- a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp +++ b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp @@ -68,6 +68,23 @@ static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, return true; } +/// Select the opcode for simple extensions (that translate to a single SXT/UXT +/// instruction). Extension operations more complicated than that should not +/// invoke this. +static unsigned selectSimpleExtOpc(unsigned Opc, unsigned Size) { + using namespace TargetOpcode; + + assert((Size == 8 || Size == 16) && "Unsupported size"); + + if (Opc == G_SEXT) + return Size == 8 ? ARM::SXTB : ARM::SXTH; + + if (Opc == G_ZEXT) + return Size == 8 ? ARM::UXTB : ARM::UXTH; + + llvm_unreachable("Unsupported opcode"); +} + bool ARMInstructionSelector::select(MachineInstr &I) const { assert(I.getParent() && "Instruction should be in a basic block!"); assert(I.getParent()->getParent() && "Instruction should be in a function!"); @@ -87,6 +104,31 @@ bool ARMInstructionSelector::select(MachineInstr &I) const { using namespace TargetOpcode; switch (I.getOpcode()) { + case G_SEXT: + case G_ZEXT: { + LLT DstTy = MRI.getType(I.getOperand(0).getReg()); + // FIXME: Smaller destination sizes coming soon! + if (DstTy.getSizeInBits() != 32) { + DEBUG(dbgs() << "Unsupported destination size for extension"); + return false; + } + + LLT SrcTy = MRI.getType(I.getOperand(1).getReg()); + unsigned SrcSize = SrcTy.getSizeInBits(); + switch (SrcSize) { + case 8: + case 16: { + unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize); + I.setDesc(TII.get(NewOpc)); + MIB.addImm(0).add(predOps(ARMCC::AL)); + break; + } + default: + DEBUG(dbgs() << "Unsupported source size for extension"); + return false; + } + break; + } case G_ADD: I.setDesc(TII.get(ARM::ADDrr)); MIB.add(predOps(ARMCC::AL)).add(condCodeOp()); diff --git a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp index 255ea4bc719..0dfddf1bfc1 100644 --- a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp +++ b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp @@ -40,5 +40,11 @@ ARMLegalizerInfo::ARMLegalizerInfo() { for (auto Ty : {s8, s16, s32}) setAction({G_ADD, Ty}, Legal); + for (auto Op : {G_SEXT, G_ZEXT}) { + setAction({Op, s32}, Legal); + for (auto Ty : {s8, s16}) + setAction({Op, 1, Ty}, Legal); + } + computeTables(); } diff --git a/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp b/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp index b40a9ddb658..ee2daa756f0 100644 --- a/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp +++ b/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp @@ -107,6 +107,7 @@ const RegisterBank &ARMRegisterBankInfo::getRegBankFromRegClass( switch (RC.getID()) { case GPRRegClassID: + case GPRnopcRegClassID: case tGPR_and_tcGPRRegClassID: return getRegBank(ARM::GPRRegBankID); default: @@ -136,6 +137,8 @@ ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { switch (Opc) { case G_ADD: case G_LOAD: + case G_SEXT: + case G_ZEXT: // FIXME: We're abusing the fact that everything lives in a GPR for now; in // the real world we would use different mappings. OperandsMapping = &ARM::ValueMappings[0]; |

