diff options
author | Tim Northover <tnorthover@apple.com> | 2017-07-20 22:58:38 +0000 |
---|---|---|
committer | Tim Northover <tnorthover@apple.com> | 2017-07-20 22:58:38 +0000 |
commit | 7b6d66c0c94f390105cc5f14d30330bc0eaf228d (patch) | |
tree | 035ab80c26607c3aff49cd612eaeb1e2f87700e9 /llvm/lib | |
parent | 071d77a51f333b084de7be38f37864ef5862b8c8 (diff) | |
download | bcm5719-llvm-7b6d66c0c94f390105cc5f14d30330bc0eaf228d.tar.gz bcm5719-llvm-7b6d66c0c94f390105cc5f14d30330bc0eaf228d.zip |
Recommit: GlobalISel: select G_EXTRACT and G_INSERT instructions on AArch64.
It revealed a bug in the Localizer pass which has now been fixed.
This includes the fix for SUBREG_TO_REG committed separately last time.
llvm-svn: 308688
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp index 43f3daf8a03..d32a6bd7f81 100644 --- a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp @@ -758,6 +758,55 @@ bool AArch64InstructionSelector::select(MachineInstr &I) const { constrainSelectedInstRegOperands(I, TII, TRI, RBI); return true; } + case TargetOpcode::G_EXTRACT: { + LLT SrcTy = MRI.getType(I.getOperand(1).getReg()); + // Larger extracts are vectors, same-size extracts should be something else + // by now (either split up or simplified to a COPY). + if (SrcTy.getSizeInBits() > 64 || Ty.getSizeInBits() > 32) + return false; + + I.setDesc(TII.get(AArch64::UBFMXri)); + MachineInstrBuilder(MF, I).addImm(I.getOperand(2).getImm() + + Ty.getSizeInBits() - 1); + + unsigned DstReg = MRI.createGenericVirtualRegister(LLT::scalar(64)); + BuildMI(MBB, std::next(I.getIterator()), I.getDebugLoc(), + TII.get(AArch64::COPY)) + .addDef(I.getOperand(0).getReg()) + .addUse(DstReg, 0, AArch64::sub_32); + RBI.constrainGenericRegister(I.getOperand(0).getReg(), + AArch64::GPR32RegClass, MRI); + I.getOperand(0).setReg(DstReg); + + return constrainSelectedInstRegOperands(I, TII, TRI, RBI); + } + + case TargetOpcode::G_INSERT: { + LLT SrcTy = MRI.getType(I.getOperand(2).getReg()); + // Larger inserts are vectors, same-size ones should be something else by + // now (split up or turned into COPYs). + if (Ty.getSizeInBits() > 64 || SrcTy.getSizeInBits() > 32) + return false; + + I.setDesc(TII.get(AArch64::BFMXri)); + unsigned LSB = I.getOperand(3).getImm(); + unsigned Width = MRI.getType(I.getOperand(2).getReg()).getSizeInBits(); + I.getOperand(3).setImm((64 - LSB) % 64); + MachineInstrBuilder(MF, I).addImm(Width - 1); + + unsigned SrcReg = MRI.createGenericVirtualRegister(LLT::scalar(64)); + BuildMI(MBB, I.getIterator(), I.getDebugLoc(), + TII.get(AArch64::SUBREG_TO_REG)) + .addDef(SrcReg) + .addImm(0) + .addUse(I.getOperand(2).getReg()) + .addImm(AArch64::sub_32); + RBI.constrainGenericRegister(I.getOperand(2).getReg(), + AArch64::GPR32RegClass, MRI); + I.getOperand(2).setReg(SrcReg); + + return constrainSelectedInstRegOperands(I, TII, TRI, RBI); + } case TargetOpcode::G_FRAME_INDEX: { // allocas and G_FRAME_INDEX are only supported in addrspace(0). if (Ty != LLT::pointer(0, 64)) { @@ -765,7 +814,6 @@ bool AArch64InstructionSelector::select(MachineInstr &I) const { << ", expected: " << LLT::pointer(0, 64) << '\n'); return false; } - I.setDesc(TII.get(AArch64::ADDXri)); // MOs for a #0 shifted immediate. |