mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-26 14:15:53 +00:00
[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
This commit is contained in:
parent
441aeddd56
commit
4c8feae136
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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(),
|
||||
|
@ -230,3 +230,60 @@ define i32 @f10(i16 %val1, i16 %val2) {
|
||||
%ext4 = zext i16 %val4 to i32
|
||||
ret i32 %ext4
|
||||
}
|
||||
|
||||
; Test loads of 16-bit constants into mixtures of high and low registers.
|
||||
define void @f11() {
|
||||
; CHECK-LABEL: f11:
|
||||
; CHECK-DAG: iihf [[REG1:%r[0-5]]], 4294934529
|
||||
; CHECK-DAG: lhi [[REG2:%r[0-5]]], -32768
|
||||
; CHECK-DAG: llihl [[REG3:%r[0-5]]], 32766
|
||||
; CHECK-DAG: lhi [[REG4:%r[0-5]]], 32767
|
||||
; CHECK: blah [[REG1]], [[REG2]], [[REG3]], [[REG4]]
|
||||
; CHECK: br %r14
|
||||
call void asm sideeffect "blah $0, $1, $2, $3",
|
||||
"h,r,h,r"(i32 -32767, i32 -32768,
|
||||
i32 32766, i32 32767)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Test loads of unsigned constants into mixtures of high and low registers.
|
||||
; For stepc, we expect the h and r operands to be paired by the register
|
||||
; allocator. It doesn't really matter which comes first: LLILL/IIHF would
|
||||
; be just as good.
|
||||
define void @f12() {
|
||||
; CHECK-LABEL: f12:
|
||||
; CHECK-DAG: llihl [[REG1:%r[0-5]]], 32768
|
||||
; CHECK-DAG: llihl [[REG2:%r[0-5]]], 65535
|
||||
; CHECK-DAG: llihh [[REG3:%r[0-5]]], 1
|
||||
; CHECK-DAG: llihh [[REG4:%r[0-5]]], 65535
|
||||
; CHECK: stepa [[REG1]], [[REG2]], [[REG3]], [[REG4]]
|
||||
; CHECK-DAG: llill [[REG1:%r[0-5]]], 32769
|
||||
; CHECK-DAG: llill [[REG2:%r[0-5]]], 65534
|
||||
; CHECK-DAG: llilh [[REG3:%r[0-5]]], 2
|
||||
; CHECK-DAG: llilh [[REG4:%r[0-5]]], 65534
|
||||
; CHECK: stepb [[REG1]], [[REG2]], [[REG3]], [[REG4]]
|
||||
; CHECK-DAG: llihl [[REG1:%r[0-5]]], 32770
|
||||
; CHECK-DAG: iilf [[REG1]], 65533
|
||||
; CHECK-DAG: llihh [[REG2:%r[0-5]]], 4
|
||||
; CHECK-DAG: iilf [[REG2]], 524288
|
||||
; CHECK: stepc [[REG1]], [[REG1]], [[REG2]], [[REG2]]
|
||||
; CHECK-DAG: iihf [[REG1:%r[0-5]]], 3294967296
|
||||
; CHECK-DAG: iilf [[REG2:%r[0-5]]], 4294567296
|
||||
; CHECK-DAG: iihf [[REG3:%r[0-5]]], 1000000000
|
||||
; CHECK-DAG: iilf [[REG4:%r[0-5]]], 400000
|
||||
; CHECK: stepd [[REG1]], [[REG2]], [[REG3]], [[REG4]]
|
||||
; CHECK: br %r14
|
||||
call void asm sideeffect "stepa $0, $1, $2, $3",
|
||||
"h,h,h,h"(i32 32768, i32 65535,
|
||||
i32 65536, i32 -65536)
|
||||
call void asm sideeffect "stepb $0, $1, $2, $3",
|
||||
"r,r,r,r"(i32 32769, i32 65534,
|
||||
i32 131072, i32 -131072)
|
||||
call void asm sideeffect "stepc $0, $1, $2, $3",
|
||||
"h,r,h,r"(i32 32770, i32 65533,
|
||||
i32 262144, i32 524288)
|
||||
call void asm sideeffect "stepd $0, $1, $2, $3",
|
||||
"h,r,h,r"(i32 -1000000000, i32 -400000,
|
||||
i32 1000000000, i32 400000)
|
||||
ret void
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user