diff options
author | Richard Sandiford <rsandifo@linux.vnet.ibm.com> | 2013-10-01 13:02:28 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@linux.vnet.ibm.com> | 2013-10-01 13:02:28 +0000 |
commit | 4c8feae136bbb54ba09d8f8dc7e61714270f7cd5 (patch) | |
tree | 2f2a7a5e5d8a4d6f3d8f998ec3221d6ef640004c /lib | |
parent | 441aeddd56d000ff77460586961a523e41edd205 (diff) | |
download | llvm-4c8feae136bbb54ba09d8f8dc7e61714270f7cd5.tar.gz llvm-4c8feae136bbb54ba09d8f8dc7e61714270f7cd5.tar.bz2 llvm-4c8feae136bbb54ba09d8f8dc7e61714270f7cd5.tar.xz |
[SystemZ] Add patterns to load a constant into a high word (IIHF)
Similar to low words, we can use the shorter LLIHL and LLIHH if it turns
out that the other half of the GR64 isn't live.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191750 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.h | 5 | ||||
-rw-r--r-- | lib/Target/SystemZ/SystemZAsmPrinter.cpp | 6 | ||||
-rw-r--r-- | lib/Target/SystemZ/SystemZInstrFormats.td | 6 | ||||
-rw-r--r-- | lib/Target/SystemZ/SystemZInstrInfo.cpp | 24 | ||||
-rw-r--r-- | lib/Target/SystemZ/SystemZInstrInfo.h | 2 | ||||
-rw-r--r-- | lib/Target/SystemZ/SystemZInstrInfo.td | 17 | ||||
-rw-r--r-- | lib/Target/SystemZ/SystemZShortenInst.cpp | 4 |
7 files changed, 59 insertions, 5 deletions
diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.h b/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.h index 17e0e87b91..97e325b984 100644 --- a/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.h +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.h @@ -62,6 +62,11 @@ namespace SystemZMC { inline unsigned getRegAsGR32(unsigned Reg) { return GR32Regs[getFirstReg(Reg)]; } + + // Return the given register as a high GR32. + inline unsigned getRegAsGRH32(unsigned Reg) { + return GRH32Regs[getFirstReg(Reg)]; + } } MCCodeEmitter *createSystemZMCCodeEmitter(const MCInstrInfo &MCII, diff --git a/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/lib/Target/SystemZ/SystemZAsmPrinter.cpp index 9ad5c8bdc6..0a89a96862 100644 --- a/lib/Target/SystemZ/SystemZAsmPrinter.cpp +++ b/lib/Target/SystemZ/SystemZAsmPrinter.cpp @@ -82,6 +82,12 @@ void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) { .addImm(MI->getOperand(2).getImm()); break; + case SystemZ::IIHF64: + LoweredMI = MCInstBuilder(SystemZ::IIHF) + .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) + .addImm(MI->getOperand(2).getImm()); + break; + case SystemZ::RISBHH: case SystemZ::RISBHL: LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG); diff --git a/lib/Target/SystemZ/SystemZInstrFormats.td b/lib/Target/SystemZ/SystemZInstrFormats.td index 97a1578f17..c74091f594 100644 --- a/lib/Target/SystemZ/SystemZInstrFormats.td +++ b/lib/Target/SystemZ/SystemZInstrFormats.td @@ -1349,6 +1349,12 @@ class Pseudo<dag outs, dag ins, list<dag> pattern> let isCodeGenOnly = 1; } +// Like UnaryRI, but expanded after RA depending on the choice of register. +class UnaryRIPseudo<SDPatternOperator operator, RegisterOperand cls, + Immediate imm> + : Pseudo<(outs cls:$R1), (ins imm:$I2), + [(set cls:$R1, (operator imm:$I2))]>; + // Like UnaryRXY, but expanded after RA depending on the choice of registers. class UnaryRXYPseudo<string key, SDPatternOperator operator, RegisterOperand cls, bits<5> bytes, diff --git a/lib/Target/SystemZ/SystemZInstrInfo.cpp b/lib/Target/SystemZ/SystemZInstrInfo.cpp index ede1eceb8c..3abecf684d 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -91,6 +91,22 @@ void SystemZInstrInfo::splitAdjDynAlloc(MachineBasicBlock::iterator MI) const { OffsetMO.setImm(Offset); } +// MI is an RI-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. ConvertHigh is true if LowOpcode takes a signed operand +// and HighOpcode takes an unsigned 32-bit operand. In those cases, +// MI has the same kind of operand as LowOpcode, so needs to be converted +// if HighOpcode is used. +void SystemZInstrInfo::expandRIPseudo(MachineInstr *MI, unsigned LowOpcode, + unsigned HighOpcode, + bool ConvertHigh) const { + unsigned Reg = MI->getOperand(0).getReg(); + bool IsHigh = isHighReg(Reg); + MI->setDesc(get(IsHigh ? HighOpcode : LowOpcode)); + if (IsHigh && ConvertHigh) + MI->getOperand(1).setImm(uint32_t(MI->getOperand(1).getImm())); +} + // 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. @@ -857,6 +873,14 @@ SystemZInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const { expandRXYPseudo(MI, SystemZ::ST, SystemZ::STFH); return true; + case SystemZ::LHIMux: + expandRIPseudo(MI, SystemZ::LHI, SystemZ::IIHF, true); + return true; + + case SystemZ::IIFMux: + expandRIPseudo(MI, SystemZ::IILF, SystemZ::IIHF, false); + return true; + case SystemZ::ADJDYNALLOC: splitAdjDynAlloc(MI); return true; diff --git a/lib/Target/SystemZ/SystemZInstrInfo.h b/lib/Target/SystemZ/SystemZInstrInfo.h index 30f4c7dde4..06e677a9c3 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.h +++ b/lib/Target/SystemZ/SystemZInstrInfo.h @@ -116,6 +116,8 @@ class SystemZInstrInfo : public SystemZGenInstrInfo { void splitMove(MachineBasicBlock::iterator MI, unsigned NewOpcode) const; void splitAdjDynAlloc(MachineBasicBlock::iterator MI) const; + void expandRIPseudo(MachineInstr *MI, unsigned LowOpcode, + unsigned HighOpcode, bool ConvertHigh) const; void expandRXYPseudo(MachineInstr *MI, unsigned LowOpcode, unsigned HighOpcode) const; void expandZExtPseudo(MachineInstr *MI, unsigned LowOpcode, diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td index 0ce016e9ef..00229260f6 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/lib/Target/SystemZ/SystemZInstrInfo.td @@ -278,7 +278,10 @@ let Uses = [CC] in { // Immediate moves. let neverHasSideEffects = 1, isAsCheapAsAMove = 1, isMoveImm = 1, isReMaterializable = 1 in { - // 16-bit sign-extended immediates. + // 16-bit sign-extended immediates. LHIMux expands to LHI or IIHF, + // deopending on the choice of register. + def LHIMux : UnaryRIPseudo<bitconvert, GRX32, imm32sx16>, + Requires<[FeatureHighWord]>; def LHI : UnaryRI<"lhi", 0xA78, bitconvert, GR32, imm32sx16>; def LGHI : UnaryRI<"lghi", 0xA79, bitconvert, GR64, imm64sx16>; @@ -636,16 +639,20 @@ def IIHH : BinaryRI<"iihh", 0xA50, inserthh, GR64, imm64hh16>; // full-width move. (We use IILF rather than something like LLILF // for 32-bit moves because IILF leaves the upper 32 bits of the // GR64 unchanged.) -let isAsCheapAsAMove = 1, isMoveImm = 1, isReMaterializable = 1 in +let isAsCheapAsAMove = 1, isMoveImm = 1, isReMaterializable = 1 in { + def IIFMux : UnaryRIPseudo<bitconvert, GRX32, uimm32>, + Requires<[FeatureHighWord]>; def IILF : UnaryRIL<"iilf", 0xC09, bitconvert, GR32, uimm32>; + def IIHF : UnaryRIL<"iihf", 0xC08, bitconvert, GRH32, uimm32>; +} def IILF64 : BinaryAliasRIL<insertlf, GR64, imm64lf32>; -def IIHF : BinaryRIL<"iihf", 0xC08, inserthf, GR64, imm64hf32>; +def IIHF64 : BinaryAliasRIL<inserthf, GR64, imm64hf32>; // An alternative model of inserthf, with the first operand being // a zero-extended value. def : Pat<(or (zext32 GR32:$src), imm64hf32:$imm), - (IIHF (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$src, subreg_l32), - imm64hf32:$imm)>; + (IIHF64 (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$src, subreg_l32), + imm64hf32:$imm)>; //===----------------------------------------------------------------------===// // Addition diff --git a/lib/Target/SystemZ/SystemZShortenInst.cpp b/lib/Target/SystemZ/SystemZShortenInst.cpp index b480864671..537a545540 100644 --- a/lib/Target/SystemZ/SystemZShortenInst.cpp +++ b/lib/Target/SystemZ/SystemZShortenInst.cpp @@ -58,6 +58,7 @@ SystemZShortenInst::SystemZShortenInst(const SystemZTargetMachine &tm) for (unsigned I = 0; I < 16; ++I) { LowGPRs[SystemZMC::GR32Regs[I]] |= 1 << I; LowGPRs[SystemZMC::GR64Regs[I]] |= 1 << I; + HighGPRs[SystemZMC::GRH32Regs[I]] |= 1 << I; HighGPRs[SystemZMC::GR64Regs[I]] |= 1 << I; if (unsigned GR128 = SystemZMC::GR128Regs[I]) { LowGPRs[GR128] |= 3 << I; @@ -122,6 +123,9 @@ bool SystemZShortenInst::processBlock(MachineBasicBlock *MBB) { if (Opcode == SystemZ::IILF) Changed |= shortenIIF(MI, LowGPRs, LiveHigh, SystemZ::LLILL, SystemZ::LLILH); + else if (Opcode == SystemZ::IIHF) + Changed |= shortenIIF(MI, HighGPRs, LiveLow, SystemZ::LLIHL, + SystemZ::LLIHH); unsigned UsedLow = 0; unsigned UsedHigh = 0; for (MachineInstr::mop_iterator MOI = MI.operands_begin(), |