From b9dcca8265e9da01119c47e65f114c3adc972ba6 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Tue, 1 Oct 2013 14:20:41 +0000 Subject: [PATCH] [SystemZ] Allow integer AND involving high words git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191762 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/SystemZ/SystemZAsmPrinter.cpp | 3 + lib/Target/SystemZ/SystemZISelLowering.cpp | 24 +++---- lib/Target/SystemZ/SystemZInstrFormats.td | 10 +++ lib/Target/SystemZ/SystemZInstrInfo.cpp | 83 +++++++++++++--------- lib/Target/SystemZ/SystemZInstrInfo.td | 50 ++++++++----- test/CodeGen/SystemZ/asm-18.ll | 63 ++++++++++++++++ 6 files changed, 170 insertions(+), 63 deletions(-) diff --git a/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/lib/Target/SystemZ/SystemZAsmPrinter.cpp index b256ac5f054..d81180cd345 100644 --- a/lib/Target/SystemZ/SystemZAsmPrinter.cpp +++ b/lib/Target/SystemZ/SystemZAsmPrinter.cpp @@ -127,6 +127,9 @@ void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) { LOWER_HIGH(IIHL); LOWER_HIGH(IIHH); + LOWER_HIGH(NIHL); + LOWER_HIGH(NIHH); + LOWER_HIGH(NIHF); LOWER_HIGH(OIHL); LOWER_HIGH(OIHH); LOWER_HIGH(OIHF); diff --git a/lib/Target/SystemZ/SystemZISelLowering.cpp b/lib/Target/SystemZ/SystemZISelLowering.cpp index 4d3c22c6f19..23b7075ae72 100644 --- a/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -2963,14 +2963,14 @@ EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const { return emitAtomicLoadBinary(MI, MBB, SystemZ::NILL64, 64); case SystemZ::ATOMIC_LOAD_NILH64: return emitAtomicLoadBinary(MI, MBB, SystemZ::NILH64, 64); - case SystemZ::ATOMIC_LOAD_NIHL: - return emitAtomicLoadBinary(MI, MBB, SystemZ::NIHL, 64); - case SystemZ::ATOMIC_LOAD_NIHH: - return emitAtomicLoadBinary(MI, MBB, SystemZ::NIHH, 64); + case SystemZ::ATOMIC_LOAD_NIHL64: + return emitAtomicLoadBinary(MI, MBB, SystemZ::NIHL64, 64); + case SystemZ::ATOMIC_LOAD_NIHH64: + return emitAtomicLoadBinary(MI, MBB, SystemZ::NIHH64, 64); case SystemZ::ATOMIC_LOAD_NILF64: return emitAtomicLoadBinary(MI, MBB, SystemZ::NILF64, 64); - case SystemZ::ATOMIC_LOAD_NIHF: - return emitAtomicLoadBinary(MI, MBB, SystemZ::NIHF, 64); + case SystemZ::ATOMIC_LOAD_NIHF64: + return emitAtomicLoadBinary(MI, MBB, SystemZ::NIHF64, 64); case SystemZ::ATOMIC_LOADW_OR: return emitAtomicLoadBinary(MI, MBB, SystemZ::OR, 0); @@ -3032,14 +3032,14 @@ EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const { return emitAtomicLoadBinary(MI, MBB, SystemZ::NILL64, 64, true); case SystemZ::ATOMIC_LOAD_NILH64i: return emitAtomicLoadBinary(MI, MBB, SystemZ::NILH64, 64, true); - case SystemZ::ATOMIC_LOAD_NIHLi: - return emitAtomicLoadBinary(MI, MBB, SystemZ::NIHL, 64, true); - case SystemZ::ATOMIC_LOAD_NIHHi: - return emitAtomicLoadBinary(MI, MBB, SystemZ::NIHH, 64, true); + case SystemZ::ATOMIC_LOAD_NIHL64i: + return emitAtomicLoadBinary(MI, MBB, SystemZ::NIHL64, 64, true); + case SystemZ::ATOMIC_LOAD_NIHH64i: + return emitAtomicLoadBinary(MI, MBB, SystemZ::NIHH64, 64, true); case SystemZ::ATOMIC_LOAD_NILF64i: return emitAtomicLoadBinary(MI, MBB, SystemZ::NILF64, 64, true); - case SystemZ::ATOMIC_LOAD_NIHFi: - return emitAtomicLoadBinary(MI, MBB, SystemZ::NIHF, 64, true); + case SystemZ::ATOMIC_LOAD_NIHF64i: + return emitAtomicLoadBinary(MI, MBB, SystemZ::NIHF64, 64, true); case SystemZ::ATOMIC_LOADW_MIN: return emitAtomicLoadMinMax(MI, MBB, SystemZ::CR, diff --git a/lib/Target/SystemZ/SystemZInstrFormats.td b/lib/Target/SystemZ/SystemZInstrFormats.td index aa15ebd0a02..b35aea8dfeb 100644 --- a/lib/Target/SystemZ/SystemZInstrFormats.td +++ b/lib/Target/SystemZ/SystemZInstrFormats.td @@ -1397,6 +1397,16 @@ class StoreRXYPseudo + : Pseudo<(outs cls1:$R1), + (ins cls1:$R1src, cls2:$R2, uimm8:$I3, uimm8:$I4, uimm8zx6:$I5), + []> { + let Constraints = "$R1 = $R1src"; + let DisableEncoding = "$R1src"; +} + // Implements "$dst = $cc & (8 >> CC) ? $src1 : $src2", where CC is // the value of the PSW's 2-bit condition code field. class SelectWrapper diff --git a/lib/Target/SystemZ/SystemZInstrInfo.cpp b/lib/Target/SystemZ/SystemZInstrInfo.cpp index 8749f48edfe..f32cf9c527a 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -616,15 +616,15 @@ namespace { static LogicOp interpretAndImmediate(unsigned Opcode) { switch (Opcode) { - case SystemZ::NILL: return LogicOp(32, 0, 16); - case SystemZ::NILH: return LogicOp(32, 16, 16); + case SystemZ::NILMux: return LogicOp(32, 0, 16); + case SystemZ::NIHMux: return LogicOp(32, 16, 16); case SystemZ::NILL64: return LogicOp(64, 0, 16); case SystemZ::NILH64: return LogicOp(64, 16, 16); - case SystemZ::NIHL: return LogicOp(64, 32, 16); - case SystemZ::NIHH: return LogicOp(64, 48, 16); - case SystemZ::NILF: return LogicOp(32, 0, 32); + case SystemZ::NIHL64: return LogicOp(64, 32, 16); + case SystemZ::NIHH64: return LogicOp(64, 48, 16); + case SystemZ::NIFMux: return LogicOp(32, 0, 32); case SystemZ::NILF64: return LogicOp(64, 0, 32); - case SystemZ::NIHF: return LogicOp(64, 32, 32); + case SystemZ::NIHF64: return LogicOp(64, 32, 32); default: return LogicOp(); } } @@ -678,34 +678,27 @@ SystemZInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, // Try to convert an AND into an RISBG-type instruction. if (LogicOp And = interpretAndImmediate(Opcode)) { - unsigned NewOpcode; - if (And.RegSize == 64) - NewOpcode = SystemZ::RISBG; - else if (TM.getSubtargetImpl()->hasHighWord()) - NewOpcode = SystemZ::RISBLL; - else - // We can't use RISBG for 32-bit operations because it clobbers the - // high word of the destination too. - NewOpcode = 0; - if (NewOpcode) { - uint64_t Imm = MI->getOperand(2).getImm() << And.ImmLSB; - // AND IMMEDIATE leaves the other bits of the register unchanged. - Imm |= allOnes(And.RegSize) & ~(allOnes(And.ImmSize) << And.ImmLSB); - unsigned Start, End; - if (isRxSBGMask(Imm, And.RegSize, Start, End)) { - if (NewOpcode == SystemZ::RISBLL) { - Start &= 31; - End &= 31; - } - MachineOperand &Dest = MI->getOperand(0); - MachineOperand &Src = MI->getOperand(1); - MachineInstrBuilder MIB = - BuildMI(*MBB, MI, MI->getDebugLoc(), get(NewOpcode)) - .addOperand(Dest).addReg(0) - .addReg(Src.getReg(), getKillRegState(Src.isKill()), Src.getSubReg()) - .addImm(Start).addImm(End + 128).addImm(0); - return finishConvertToThreeAddress(MI, MIB, LV); + uint64_t Imm = MI->getOperand(2).getImm() << And.ImmLSB; + // AND IMMEDIATE leaves the other bits of the register unchanged. + Imm |= allOnes(And.RegSize) & ~(allOnes(And.ImmSize) << And.ImmLSB); + unsigned Start, End; + if (isRxSBGMask(Imm, And.RegSize, Start, End)) { + unsigned NewOpcode; + if (And.RegSize == 64) + NewOpcode = SystemZ::RISBG; + else { + NewOpcode = SystemZ::RISBMux; + Start &= 31; + End &= 31; } + MachineOperand &Dest = MI->getOperand(0); + MachineOperand &Src = MI->getOperand(1); + MachineInstrBuilder MIB = + BuildMI(*MBB, MI, MI->getDebugLoc(), get(NewOpcode)) + .addOperand(Dest).addReg(0) + .addReg(Src.getReg(), getKillRegState(Src.isKill()), Src.getSubReg()) + .addImm(Start).addImm(End + 128).addImm(0); + return finishConvertToThreeAddress(MI, MIB, LV); } } return 0; @@ -889,6 +882,18 @@ SystemZInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const { expandRIPseudo(MI, SystemZ::IILH, SystemZ::IIHH, false); return true; + case SystemZ::NIFMux: + expandRIPseudo(MI, SystemZ::NILF, SystemZ::NIHF, false); + return true; + + case SystemZ::NILMux: + expandRIPseudo(MI, SystemZ::NILL, SystemZ::NIHL, false); + return true; + + case SystemZ::NIHMux: + expandRIPseudo(MI, SystemZ::NILH, SystemZ::NIHH, false); + return true; + case SystemZ::OIFMux: expandRIPseudo(MI, SystemZ::OILF, SystemZ::OIHF, false); return true; @@ -905,6 +910,18 @@ SystemZInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const { expandRIPseudo(MI, SystemZ::XILF, SystemZ::XIHF, false); return true; + case SystemZ::RISBMux: { + bool DestIsHigh = isHighReg(MI->getOperand(0).getReg()); + bool SrcIsHigh = isHighReg(MI->getOperand(2).getReg()); + if (SrcIsHigh == DestIsHigh) + MI->setDesc(get(DestIsHigh ? SystemZ::RISBHH : SystemZ::RISBLL)); + else { + MI->setDesc(get(DestIsHigh ? SystemZ::RISBHL : SystemZ::RISBLH)); + MI->getOperand(5).setImm(MI->getOperand(5).getImm() ^ 32); + } + return true; + } + case SystemZ::ADJDYNALLOC: splitAdjDynAlloc(MI); return true; diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td index c468b886420..bf333b5ee8a 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/lib/Target/SystemZ/SystemZInstrInfo.td @@ -797,20 +797,33 @@ let Defs = [CC] in { let isConvertibleToThreeAddress = 1 in { // ANDs of a 16-bit immediate, leaving other bits unaffected. // The CC result only reflects the 16-bit field, not the full register. + // + // NIxMux expands to NI[LH]x, depending on the choice of register. + def NILMux : BinaryRIPseudo, + Requires<[FeatureHighWord]>; + def NIHMux : BinaryRIPseudo, + Requires<[FeatureHighWord]>; def NILL : BinaryRI<"nill", 0xA57, and, GR32, imm32ll16c>; def NILH : BinaryRI<"nilh", 0xA56, and, GR32, imm32lh16c>; + def NIHL : BinaryRI<"nihl", 0xA55, and, GRH32, imm32ll16c>; + def NIHH : BinaryRI<"nihh", 0xA54, and, GRH32, imm32lh16c>; def NILL64 : BinaryAliasRI; def NILH64 : BinaryAliasRI; - def NIHL : BinaryRI<"nihl", 0xA55, and, GR64, imm64hl16c>; - def NIHH : BinaryRI<"nihh", 0xA54, and, GR64, imm64hh16c>; + def NIHL64 : BinaryAliasRI; + def NIHH64 : BinaryAliasRI; // ANDs of a 32-bit immediate, leaving other bits unaffected. // The CC result only reflects the 32-bit field, which means we can // use it as a zero indicator for i32 operations but not otherwise. - let CCValues = 0xC, CompareZeroCCMask = 0x8 in + let CCValues = 0xC, CompareZeroCCMask = 0x8 in { + // Expands to NILF or NIHF, depending on the choice of register. + def NIFMux : BinaryRIPseudo, + Requires<[FeatureHighWord]>; def NILF : BinaryRIL<"nilf", 0xC0B, and, GR32, uimm32>; + def NIHF : BinaryRIL<"nihf", 0xC0A, and, GRH32, uimm32>; + } def NILF64 : BinaryAliasRIL; - def NIHF : BinaryRIL<"nihf", 0xC0A, and, GR64, imm64hf32c>; + def NIHF64 : BinaryAliasRIL; } // ANDs of memory. @@ -1014,14 +1027,15 @@ let Defs = [CC] in { // Forms of RISBG that only affect one word of the destination register. // They do not set CC. -def RISBLL : RotateSelectAliasRIEf, Requires<[FeatureHighWord]>; -def RISBLH : RotateSelectAliasRIEf, Requires<[FeatureHighWord]>; -def RISBHL : RotateSelectAliasRIEf, Requires<[FeatureHighWord]>; -def RISBHH : RotateSelectAliasRIEf, Requires<[FeatureHighWord]>; -def RISBLG : RotateSelectRIEf<"risblg", 0xEC51, GR32, GR64>, - Requires<[FeatureHighWord]>; -def RISBHG : RotateSelectRIEf<"risbhg", 0xEC5D, GRH32, GR64>, - Requires<[FeatureHighWord]>; +def RISBMux : RotateSelectRIEfPseudo, Requires<[FeatureHighWord]>; +def RISBLL : RotateSelectAliasRIEf, Requires<[FeatureHighWord]>; +def RISBLH : RotateSelectAliasRIEf, Requires<[FeatureHighWord]>; +def RISBHL : RotateSelectAliasRIEf, Requires<[FeatureHighWord]>; +def RISBHH : RotateSelectAliasRIEf, Requires<[FeatureHighWord]>; +def RISBLG : RotateSelectRIEf<"risblg", 0xEC51, GR32, GR64>, + Requires<[FeatureHighWord]>; +def RISBHG : RotateSelectRIEf<"risbhg", 0xEC5D, GRH32, GR64>, + Requires<[FeatureHighWord]>; // Rotate second operand left and perform a logical operation with selected // bits of the first operand. The CC result only describes the selected bits, @@ -1166,10 +1180,10 @@ def ATOMIC_LOAD_NILF : AtomicLoadBinaryImm32; def ATOMIC_LOAD_NGR : AtomicLoadBinaryReg64; def ATOMIC_LOAD_NILL64 : AtomicLoadBinaryImm64; def ATOMIC_LOAD_NILH64 : AtomicLoadBinaryImm64; -def ATOMIC_LOAD_NIHL : AtomicLoadBinaryImm64; -def ATOMIC_LOAD_NIHH : AtomicLoadBinaryImm64; +def ATOMIC_LOAD_NIHL64 : AtomicLoadBinaryImm64; +def ATOMIC_LOAD_NIHH64 : AtomicLoadBinaryImm64; def ATOMIC_LOAD_NILF64 : AtomicLoadBinaryImm64; -def ATOMIC_LOAD_NIHF : AtomicLoadBinaryImm64; +def ATOMIC_LOAD_NIHF64 : AtomicLoadBinaryImm64; def ATOMIC_LOADW_OR : AtomicLoadWBinaryReg; def ATOMIC_LOADW_OILH : AtomicLoadWBinaryImm; @@ -1207,13 +1221,13 @@ def ATOMIC_LOAD_NILL64i : AtomicLoadBinaryImm64; def ATOMIC_LOAD_NILH64i : AtomicLoadBinaryImm64; -def ATOMIC_LOAD_NIHLi : AtomicLoadBinaryImm64; -def ATOMIC_LOAD_NIHHi : AtomicLoadBinaryImm64; def ATOMIC_LOAD_NILF64i : AtomicLoadBinaryImm64; -def ATOMIC_LOAD_NIHFi : AtomicLoadBinaryImm64; def ATOMIC_LOADW_MIN : AtomicLoadWBinaryReg; diff --git a/test/CodeGen/SystemZ/asm-18.ll b/test/CodeGen/SystemZ/asm-18.ll index bec8deeb72d..0ecca7ff7cd 100644 --- a/test/CodeGen/SystemZ/asm-18.ll +++ b/test/CodeGen/SystemZ/asm-18.ll @@ -437,3 +437,66 @@ define void @f20() { call void asm sideeffect "stepd $0", "r"(i32 %xor3) ret void } + +; Test two-operand immediate AND involving high registers. +define void @f21() { +; CHECK-LABEL: f21: +; CHECK: stepa [[REG:%r[0-5]]] +; CHECK: nihh [[REG]], 4096 +; CHECK: stepb [[REG]] +; CHECK: nihl [[REG]], 57536 +; CHECK: stepc [[REG]] +; CHECK: nihf [[REG]], 12345678 +; CHECK: stepd [[REG]] +; CHECK: br %r14 + %res1 = call i32 asm "stepa $0", "=h"() + %and1 = and i32 %res1, 268500991 + %res2 = call i32 asm "stepb $0, $1", "=h,h"(i32 %and1) + %and2 = and i32 %res2, -8000 + %res3 = call i32 asm "stepc $0, $1", "=h,h"(i32 %and2) + %and3 = and i32 %res3, 12345678 + call void asm sideeffect "stepd $0", "h"(i32 %and3) + ret void +} + +; Test two-operand immediate AND involving low registers. +define void @f22() { +; CHECK-LABEL: f22: +; CHECK: stepa [[REG:%r[0-5]]] +; CHECK: nilh [[REG]], 4096 +; CHECK: stepb [[REG]] +; CHECK: nill [[REG]], 57536 +; CHECK: stepc [[REG]] +; CHECK: nilf [[REG]], 12345678 +; CHECK: stepd [[REG]] +; CHECK: br %r14 + %res1 = call i32 asm "stepa $0", "=r"() + %and1 = and i32 %res1, 268500991 + %res2 = call i32 asm "stepb $0, $1", "=r,r"(i32 %and1) + %and2 = and i32 %res2, -8000 + %res3 = call i32 asm "stepc $0, $1", "=r,r"(i32 %and2) + %and3 = and i32 %res3, 12345678 + call void asm sideeffect "stepd $0", "r"(i32 %and3) + ret void +} + +; Test three-operand immediate AND involving mixtures of low and high registers. +define i32 @f23(i32 %old) { +; CHECK-LABEL: f23: +; CHECK-DAG: risblg [[REG1:%r[0-5]]], %r2, 28, 158, 0 +; CHECK-DAG: risbhg [[REG2:%r[0-5]]], %r2, 24, 158, 32 +; CHECK: stepa %r2, [[REG1]], [[REG2]] +; CHECK-DAG: risbhg [[REG3:%r[0-5]]], [[REG2]], 25, 159, 0 +; CHECK-DAG: risblg %r2, [[REG2]], 24, 152, 32 +; CHECK: stepb [[REG2]], [[REG3]], %r2 +; CHECK: br %r14 + %and1 = and i32 %old, 14 + %and2 = and i32 %old, 254 + %res1 = call i32 asm "stepa $1, $2, $3", + "=h,r,r,0"(i32 %old, i32 %and1, i32 %and2) + %and3 = and i32 %res1, 127 + %and4 = and i32 %res1, 128 + %res2 = call i32 asm "stepb $1, $2, $3", + "=r,h,h,0"(i32 %res1, i32 %and3, i32 %and4) + ret i32 %res2 +}