From 645d250b84fe0d097e7813b980ae58daeca2c2e6 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Tue, 1 Oct 2013 13:18:56 +0000 Subject: [PATCH] [SystemZ] Allow integer insertions with a high-word destination git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191753 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/SystemZ/SystemZAsmPrinter.cpp | 17 ++++++++++ lib/Target/SystemZ/SystemZInstrFormats.td | 8 +++++ lib/Target/SystemZ/SystemZInstrInfo.cpp | 8 +++++ lib/Target/SystemZ/SystemZInstrInfo.td | 12 +++++-- test/CodeGen/SystemZ/asm-18.ll | 38 +++++++++++++++++++++++ 5 files changed, 81 insertions(+), 2 deletions(-) diff --git a/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/lib/Target/SystemZ/SystemZAsmPrinter.cpp index 0a89a96862e..cb019494fd5 100644 --- a/lib/Target/SystemZ/SystemZAsmPrinter.cpp +++ b/lib/Target/SystemZ/SystemZAsmPrinter.cpp @@ -35,6 +35,15 @@ static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) { .addImm(MI->getOperand(2).getImm()); } +// Return an RI instruction like MI with opcode Opcode, but with the +// GR64 register operands turned into GRH32s. +static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) { + return MCInstBuilder(Opcode) + .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) + .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg())) + .addImm(MI->getOperand(2).getImm()); +} + // Return an RI instruction like MI with opcode Opcode, but with the // R2 register turned into a GR64. static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) { @@ -113,6 +122,14 @@ void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) { #undef LOWER_LOW +#define LOWER_HIGH(NAME) \ + case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break + + LOWER_HIGH(IIHL); + LOWER_HIGH(IIHH); + +#undef LOWER_HIGH + default: Lower.lower(MI, LoweredMI); break; diff --git a/lib/Target/SystemZ/SystemZInstrFormats.td b/lib/Target/SystemZ/SystemZInstrFormats.td index c74091f5948..aa15ebd0a02 100644 --- a/lib/Target/SystemZ/SystemZInstrFormats.td +++ b/lib/Target/SystemZ/SystemZInstrFormats.td @@ -1378,6 +1378,14 @@ class UnaryRRPseudo + : Pseudo<(outs cls:$R1), (ins cls:$R1src, imm:$I2), + [(set cls:$R1, (operator cls:$R1src, imm:$I2))]> { + let Constraints = "$R1 = $R1src"; +} + // Like StoreRXY, but expanded after RA depending on the choice of registers. class StoreRXYPseudo bytes, AddressingMode mode = bdxaddr20only> diff --git a/lib/Target/SystemZ/SystemZInstrInfo.cpp b/lib/Target/SystemZ/SystemZInstrInfo.cpp index 3abecf684dd..90de3daed17 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -881,6 +881,14 @@ SystemZInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const { expandRIPseudo(MI, SystemZ::IILF, SystemZ::IIHF, false); return true; + case SystemZ::IILMux: + expandRIPseudo(MI, SystemZ::IILL, SystemZ::IIHL, false); + return true; + + case SystemZ::IIHMux: + expandRIPseudo(MI, SystemZ::IILH, SystemZ::IIHH, false); + return true; + case SystemZ::ADJDYNALLOC: splitAdjDynAlloc(MI); return true; diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td index ac1ca3ce18b..e19cc27b296 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/lib/Target/SystemZ/SystemZInstrInfo.td @@ -629,12 +629,20 @@ defm : InsertMem<"inserti8", ICY, GR64, azextloadi8, bdxaddr20pair>; // Insertions of a 16-bit immediate, leaving other bits unaffected. // We don't have or_as_insert equivalents of these operations because // OI is available instead. +// +// IIxMux expands to II[LH]x, depending on the choice of register. +def IILMux : BinaryRIPseudo, + Requires<[FeatureHighWord]>; +def IIHMux : BinaryRIPseudo, + Requires<[FeatureHighWord]>; def IILL : BinaryRI<"iill", 0xA53, insertll, GR32, imm32ll16>; def IILH : BinaryRI<"iilh", 0xA52, insertlh, GR32, imm32lh16>; +def IIHL : BinaryRI<"iihl", 0xA51, insertll, GRH32, imm32ll16>; +def IIHH : BinaryRI<"iihh", 0xA50, insertlh, GRH32, imm32lh16>; def IILL64 : BinaryAliasRI; def IILH64 : BinaryAliasRI; -def IIHL : BinaryRI<"iihl", 0xA51, inserthl, GR64, imm64hl16>; -def IIHH : BinaryRI<"iihh", 0xA50, inserthh, GR64, imm64hh16>; +def IIHL64 : BinaryAliasRI; +def IIHH64 : BinaryAliasRI; // ...likewise for 32-bit immediates. For GR32s this is a general // full-width move. (We use IILF rather than something like LLILF diff --git a/test/CodeGen/SystemZ/asm-18.ll b/test/CodeGen/SystemZ/asm-18.ll index 6126b50c171..fc71895cd78 100644 --- a/test/CodeGen/SystemZ/asm-18.ll +++ b/test/CodeGen/SystemZ/asm-18.ll @@ -315,3 +315,41 @@ define void @f14(i32 %x, i32 %y) { call void asm sideeffect "blah $0", "r"(i32 %val) ret void } + +; Test immediate insertion involving high registers. +define void @f15() { +; CHECK-LABEL: f15: +; CHECK: stepa [[REG:%r[0-5]]] +; CHECK: iihh [[REG]], 4660 +; CHECK: stepb [[REG]] +; CHECK: iihl [[REG]], 34661 +; CHECK: stepc [[REG]] +; CHECK: br %r14 + %res1 = call i32 asm "stepa $0", "=h"() + %and1 = and i32 %res1, 65535 + %or1 = or i32 %and1, 305397760 + %res2 = call i32 asm "stepb $0, $1", "=h,h"(i32 %or1) + %and2 = and i32 %res2, -65536 + %or2 = or i32 %and2, 34661 + call void asm sideeffect "stepc $0", "h"(i32 %or2) + ret void +} + +; Test immediate insertion involving low registers. +define void @f16() { +; CHECK-LABEL: f16: +; CHECK: stepa [[REG:%r[0-5]]] +; CHECK: iilh [[REG]], 4660 +; CHECK: stepb [[REG]] +; CHECK: iill [[REG]], 34661 +; CHECK: stepc [[REG]] +; CHECK: br %r14 + %res1 = call i32 asm "stepa $0", "=r"() + %and1 = and i32 %res1, 65535 + %or1 = or i32 %and1, 305397760 + %res2 = call i32 asm "stepb $0, $1", "=r,r"(i32 %or1) + %and2 = and i32 %res2, -65536 + %or2 = or i32 %and2, 34661 + call void asm sideeffect "stepc $0", "r"(i32 %or2) + ret void +} -- 2.34.1