aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@linux.vnet.ibm.com>2013-10-01 13:02:28 +0000
committerRichard Sandiford <rsandifo@linux.vnet.ibm.com>2013-10-01 13:02:28 +0000
commit4c8feae136bbb54ba09d8f8dc7e61714270f7cd5 (patch)
tree2f2a7a5e5d8a4d6f3d8f998ec3221d6ef640004c
parent441aeddd56d000ff77460586961a523e41edd205 (diff)
downloadexternal_llvm-4c8feae136bbb54ba09d8f8dc7e61714270f7cd5.zip
external_llvm-4c8feae136bbb54ba09d8f8dc7e61714270f7cd5.tar.gz
external_llvm-4c8feae136bbb54ba09d8f8dc7e61714270f7cd5.tar.bz2
[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
-rw-r--r--lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.h5
-rw-r--r--lib/Target/SystemZ/SystemZAsmPrinter.cpp6
-rw-r--r--lib/Target/SystemZ/SystemZInstrFormats.td6
-rw-r--r--lib/Target/SystemZ/SystemZInstrInfo.cpp24
-rw-r--r--lib/Target/SystemZ/SystemZInstrInfo.h2
-rw-r--r--lib/Target/SystemZ/SystemZInstrInfo.td17
-rw-r--r--lib/Target/SystemZ/SystemZShortenInst.cpp4
-rw-r--r--test/CodeGen/SystemZ/asm-18.ll57
8 files changed, 116 insertions, 5 deletions
diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.h b/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.h
index 17e0e87..97e325b 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 9ad5c8b..0a89a96 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 97a1578..c74091f 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 ede1ece..3abecf6 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 30f4c7d..06e677a 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 0ce016e..0022926 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 b480864..537a545 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(),
diff --git a/test/CodeGen/SystemZ/asm-18.ll b/test/CodeGen/SystemZ/asm-18.ll
index c2f80d9..e7e171e 100644
--- a/test/CodeGen/SystemZ/asm-18.ll
+++ b/test/CodeGen/SystemZ/asm-18.ll
@@ -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
+}