diff options
author | Richard Sandiford <rsandifo@linux.vnet.ibm.com> | 2013-10-01 11:26:28 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@linux.vnet.ibm.com> | 2013-10-01 11:26:28 +0000 |
commit | 55d7d83b6c9e55fa73d667660c8e90f92999385b (patch) | |
tree | 83c358210e689be038456f844dee58f1cb1bc648 /lib/Target/SystemZ/SystemZInstrInfo.cpp | |
parent | 7d0b89bedd5c8a53c71498663046b7e14bb96d6d (diff) | |
download | llvm-55d7d83b6c9e55fa73d667660c8e90f92999385b.tar.gz llvm-55d7d83b6c9e55fa73d667660c8e90f92999385b.tar.bz2 llvm-55d7d83b6c9e55fa73d667660c8e90f92999385b.tar.xz |
[SystemZ] Use upper words of GR64s for codegen
This just adds the basics necessary for allocating the upper words to
virtual registers (move, load and store). The move support is parameterised
in a way that makes it easy to handle zero extensions, but the associated
zero-extend patterns are added by a later patch.
The easiest way of testing this seemed to be add a new "h" register
constraint for high words. I don't expect the constraint to be useful
in real inline asms, but it should work, so I didn't try to hide it
behind an option.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191739 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/SystemZ/SystemZInstrInfo.cpp')
-rw-r--r-- | lib/Target/SystemZ/SystemZInstrInfo.cpp | 78 |
1 files changed, 73 insertions, 5 deletions
diff --git a/lib/Target/SystemZ/SystemZInstrInfo.cpp b/lib/Target/SystemZ/SystemZInstrInfo.cpp index ba182bf76c..798fa3349f 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -28,6 +28,15 @@ static uint64_t allOnes(unsigned int Count) { return Count == 0 ? 0 : (uint64_t(1) << (Count - 1) << 1) - 1; } +// Reg should be a 32-bit GPR. Return true if it is a high register rather +// than a low register. +static bool isHighReg(unsigned int Reg) { + if (SystemZ::GRH32BitRegClass.contains(Reg)) + return true; + assert(SystemZ::GR32BitRegClass.contains(Reg) && "Invalid GRX32"); + return false; +} + SystemZInstrInfo::SystemZInstrInfo(SystemZTargetMachine &tm) : SystemZGenInstrInfo(SystemZ::ADJCALLSTACKDOWN, SystemZ::ADJCALLSTACKUP), RI(tm), TM(tm) { @@ -82,6 +91,48 @@ void SystemZInstrInfo::splitAdjDynAlloc(MachineBasicBlock::iterator MI) const { OffsetMO.setImm(Offset); } +// MI is an RXY-style pseudo instruction. Replace it with LowOpcode +// if the first operand is a low GR32 and HighOpcode if the first operand +// is a high GR32. +void SystemZInstrInfo::expandRXYPseudo(MachineInstr *MI, unsigned LowOpcode, + unsigned HighOpcode) const { + unsigned Reg = MI->getOperand(0).getReg(); + unsigned Opcode = getOpcodeForOffset(isHighReg(Reg) ? HighOpcode : LowOpcode, + MI->getOperand(2).getImm()); + MI->setDesc(get(Opcode)); +} + +// Emit a zero-extending move from 32-bit GPR SrcReg to 32-bit GPR +// DestReg before MBBI in MBB. Use LowLowOpcode when both DestReg and SrcReg +// are low registers, otherwise use RISB[LH]G. Size is the number of bits +// taken from the low end of SrcReg (8 for LLCR, 16 for LLHR and 32 for LR). +// KillSrc is true if this move is the last use of SrcReg. +void SystemZInstrInfo::emitGRX32Move(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + DebugLoc DL, unsigned DestReg, + unsigned SrcReg, unsigned LowLowOpcode, + unsigned Size, bool KillSrc) const { + unsigned Opcode; + bool DestIsHigh = isHighReg(DestReg); + bool SrcIsHigh = isHighReg(SrcReg); + if (DestIsHigh && SrcIsHigh) + Opcode = SystemZ::RISBHH; + else if (DestIsHigh && !SrcIsHigh) + Opcode = SystemZ::RISBHL; + else if (!DestIsHigh && SrcIsHigh) + Opcode = SystemZ::RISBLH; + else { + BuildMI(MBB, MBBI, DL, get(LowLowOpcode), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)); + return; + } + unsigned Rotate = (DestIsHigh != SrcIsHigh ? 32 : 0); + BuildMI(MBB, MBBI, DL, get(Opcode), DestReg) + .addReg(DestReg, RegState::Undef) + .addReg(SrcReg, getKillRegState(KillSrc)) + .addImm(32 - Size).addImm(128 + 31).addImm(Rotate); +} + // If MI is a simple load or store for a frame object, return the register // it loads or stores and set FrameIndex to the index of the frame object. // Return 0 otherwise. @@ -460,11 +511,14 @@ SystemZInstrInfo::copyPhysReg(MachineBasicBlock &MBB, return; } + if (SystemZ::GRX32BitRegClass.contains(DestReg, SrcReg)) { + emitGRX32Move(MBB, MBBI, DL, DestReg, SrcReg, SystemZ::LR, 32, KillSrc); + return; + } + // Everything else needs only one instruction. unsigned Opcode; - if (SystemZ::GR32BitRegClass.contains(DestReg, SrcReg)) - Opcode = SystemZ::LR; - else if (SystemZ::GR64BitRegClass.contains(DestReg, SrcReg)) + if (SystemZ::GR64BitRegClass.contains(DestReg, SrcReg)) Opcode = SystemZ::LGR; else if (SystemZ::FP32BitRegClass.contains(DestReg, SrcReg)) Opcode = SystemZ::LER; @@ -601,7 +655,7 @@ SystemZInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, if (And.RegSize == 64) NewOpcode = SystemZ::RISBG; else if (TM.getSubtargetImpl()->hasHighWord()) - NewOpcode = SystemZ::RISBLG32; + NewOpcode = SystemZ::RISBLL; else // We can't use RISBG for 32-bit operations because it clobbers the // high word of the destination too. @@ -612,7 +666,7 @@ SystemZInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, Imm |= allOnes(And.RegSize) & ~(allOnes(And.ImmSize) << And.ImmLSB); unsigned Start, End; if (isRxSBGMask(Imm, And.RegSize, Start, End)) { - if (NewOpcode == SystemZ::RISBLG32) { + if (NewOpcode == SystemZ::RISBLL) { Start &= 31; End &= 31; } @@ -752,6 +806,14 @@ SystemZInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const { splitMove(MI, SystemZ::STD); return true; + case SystemZ::LMux: + expandRXYPseudo(MI, SystemZ::L, SystemZ::LFH); + return true; + + case SystemZ::STMux: + expandRXYPseudo(MI, SystemZ::ST, SystemZ::STFH); + return true; + case SystemZ::ADJDYNALLOC: splitAdjDynAlloc(MI); return true; @@ -824,6 +886,12 @@ void SystemZInstrInfo::getLoadStoreOpcodes(const TargetRegisterClass *RC, if (RC == &SystemZ::GR32BitRegClass || RC == &SystemZ::ADDR32BitRegClass) { LoadOpcode = SystemZ::L; StoreOpcode = SystemZ::ST; + } else if (RC == &SystemZ::GRH32BitRegClass) { + LoadOpcode = SystemZ::LFH; + StoreOpcode = SystemZ::STFH; + } else if (RC == &SystemZ::GRX32BitRegClass) { + LoadOpcode = SystemZ::LMux; + StoreOpcode = SystemZ::STMux; } else if (RC == &SystemZ::GR64BitRegClass || RC == &SystemZ::ADDR64BitRegClass) { LoadOpcode = SystemZ::LG; |