mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
[SystemZ] Allow integer AND involving high words
llvm-svn: 191762
This commit is contained in:
parent
9d3cacb101
commit
7125240faa
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -1397,6 +1397,16 @@ class StoreRXYPseudo<SDPatternOperator operator, RegisterOperand cls,
|
||||
let AccessBytes = bytes;
|
||||
}
|
||||
|
||||
// Like RotateSelectRIEf, but expanded after RA depending on the choice
|
||||
// of registers.
|
||||
class RotateSelectRIEfPseudo<RegisterOperand cls1, RegisterOperand cls2>
|
||||
: 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<RegisterOperand cls>
|
||||
|
@ -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;
|
||||
|
@ -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<and, GRX32, imm32ll16c>,
|
||||
Requires<[FeatureHighWord]>;
|
||||
def NIHMux : BinaryRIPseudo<and, GRX32, imm32lh16c>,
|
||||
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<and, GR64, imm64ll16c>;
|
||||
def NILH64 : BinaryAliasRI<and, GR64, imm64lh16c>;
|
||||
def NIHL : BinaryRI<"nihl", 0xA55, and, GR64, imm64hl16c>;
|
||||
def NIHH : BinaryRI<"nihh", 0xA54, and, GR64, imm64hh16c>;
|
||||
def NIHL64 : BinaryAliasRI<and, GR64, imm64hl16c>;
|
||||
def NIHH64 : BinaryAliasRI<and, GR64, imm64hh16c>;
|
||||
|
||||
// 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<and, GRX32, uimm32>,
|
||||
Requires<[FeatureHighWord]>;
|
||||
def NILF : BinaryRIL<"nilf", 0xC0B, and, GR32, uimm32>;
|
||||
def NIHF : BinaryRIL<"nihf", 0xC0A, and, GRH32, uimm32>;
|
||||
}
|
||||
def NILF64 : BinaryAliasRIL<and, GR64, imm64lf32c>;
|
||||
def NIHF : BinaryRIL<"nihf", 0xC0A, and, GR64, imm64hf32c>;
|
||||
def NIHF64 : BinaryAliasRIL<and, GR64, imm64hf32c>;
|
||||
}
|
||||
|
||||
// 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<GR32, GR32>, Requires<[FeatureHighWord]>;
|
||||
def RISBLH : RotateSelectAliasRIEf<GR32, GRH32>, Requires<[FeatureHighWord]>;
|
||||
def RISBHL : RotateSelectAliasRIEf<GRH32, GR32>, Requires<[FeatureHighWord]>;
|
||||
def RISBHH : RotateSelectAliasRIEf<GRH32, GRH32>, Requires<[FeatureHighWord]>;
|
||||
def RISBLG : RotateSelectRIEf<"risblg", 0xEC51, GR32, GR64>,
|
||||
Requires<[FeatureHighWord]>;
|
||||
def RISBHG : RotateSelectRIEf<"risbhg", 0xEC5D, GRH32, GR64>,
|
||||
Requires<[FeatureHighWord]>;
|
||||
def RISBMux : RotateSelectRIEfPseudo<GRX32, GRX32>, Requires<[FeatureHighWord]>;
|
||||
def RISBLL : RotateSelectAliasRIEf<GR32, GR32>, Requires<[FeatureHighWord]>;
|
||||
def RISBLH : RotateSelectAliasRIEf<GR32, GRH32>, Requires<[FeatureHighWord]>;
|
||||
def RISBHL : RotateSelectAliasRIEf<GRH32, GR32>, Requires<[FeatureHighWord]>;
|
||||
def RISBHH : RotateSelectAliasRIEf<GRH32, GRH32>, 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<atomic_load_and_32, uimm32>;
|
||||
def ATOMIC_LOAD_NGR : AtomicLoadBinaryReg64<atomic_load_and_64>;
|
||||
def ATOMIC_LOAD_NILL64 : AtomicLoadBinaryImm64<atomic_load_and_64, imm64ll16c>;
|
||||
def ATOMIC_LOAD_NILH64 : AtomicLoadBinaryImm64<atomic_load_and_64, imm64lh16c>;
|
||||
def ATOMIC_LOAD_NIHL : AtomicLoadBinaryImm64<atomic_load_and_64, imm64hl16c>;
|
||||
def ATOMIC_LOAD_NIHH : AtomicLoadBinaryImm64<atomic_load_and_64, imm64hh16c>;
|
||||
def ATOMIC_LOAD_NIHL64 : AtomicLoadBinaryImm64<atomic_load_and_64, imm64hl16c>;
|
||||
def ATOMIC_LOAD_NIHH64 : AtomicLoadBinaryImm64<atomic_load_and_64, imm64hh16c>;
|
||||
def ATOMIC_LOAD_NILF64 : AtomicLoadBinaryImm64<atomic_load_and_64, imm64lf32c>;
|
||||
def ATOMIC_LOAD_NIHF : AtomicLoadBinaryImm64<atomic_load_and_64, imm64hf32c>;
|
||||
def ATOMIC_LOAD_NIHF64 : AtomicLoadBinaryImm64<atomic_load_and_64, imm64hf32c>;
|
||||
|
||||
def ATOMIC_LOADW_OR : AtomicLoadWBinaryReg<z_atomic_loadw_or>;
|
||||
def ATOMIC_LOADW_OILH : AtomicLoadWBinaryImm<z_atomic_loadw_or, imm32lh16>;
|
||||
@ -1207,13 +1221,13 @@ def ATOMIC_LOAD_NILL64i : AtomicLoadBinaryImm64<atomic_load_nand_64,
|
||||
imm64ll16c>;
|
||||
def ATOMIC_LOAD_NILH64i : AtomicLoadBinaryImm64<atomic_load_nand_64,
|
||||
imm64lh16c>;
|
||||
def ATOMIC_LOAD_NIHLi : AtomicLoadBinaryImm64<atomic_load_nand_64,
|
||||
def ATOMIC_LOAD_NIHL64i : AtomicLoadBinaryImm64<atomic_load_nand_64,
|
||||
imm64hl16c>;
|
||||
def ATOMIC_LOAD_NIHHi : AtomicLoadBinaryImm64<atomic_load_nand_64,
|
||||
def ATOMIC_LOAD_NIHH64i : AtomicLoadBinaryImm64<atomic_load_nand_64,
|
||||
imm64hh16c>;
|
||||
def ATOMIC_LOAD_NILF64i : AtomicLoadBinaryImm64<atomic_load_nand_64,
|
||||
imm64lf32c>;
|
||||
def ATOMIC_LOAD_NIHFi : AtomicLoadBinaryImm64<atomic_load_nand_64,
|
||||
def ATOMIC_LOAD_NIHF64i : AtomicLoadBinaryImm64<atomic_load_nand_64,
|
||||
imm64hf32c>;
|
||||
|
||||
def ATOMIC_LOADW_MIN : AtomicLoadWBinaryReg<z_atomic_loadw_min>;
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user