diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp index acefd9c8fea0..9b50a3c684c1 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -966,6 +966,14 @@ SystemZInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const { expandRIPseudo(MI, SystemZ::AFI, SystemZ::AIH, false); return true; + case SystemZ::CFIMux: + expandRIPseudo(MI, SystemZ::CFI, SystemZ::CIH, false); + return true; + + case SystemZ::CLFIMux: + expandRIPseudo(MI, SystemZ::CLFI, SystemZ::CLIH, false); + return true; + case SystemZ::RISBMux: { bool DestIsHigh = isHighReg(MI->getOperand(0).getReg()); bool SrcIsHigh = isHighReg(MI->getOperand(2).getReg()); diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td index 986e77f17f92..f7dbd094fa0d 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td @@ -1076,8 +1076,13 @@ let Defs = [CC], CCValues = 0xE in { def CHI : CompareRI<"chi", 0xA7E, z_scmp, GR32, imm32sx16>; def CGHI : CompareRI<"cghi", 0xA7F, z_scmp, GR64, imm64sx16>; - // Comparison with a signed 32-bit immediate. + // Comparison with a signed 32-bit immediate. CFIMux expands to CFI or CIH, + // depending on the choice of register. + def CFIMux : CompareRIPseudo, + Requires<[FeatureHighWord]>; def CFI : CompareRIL<"cfi", 0xC2D, z_scmp, GR32, simm32>; + def CIH : CompareRIL<"cih", 0xCCD, z_scmp, GRH32, simm32>, + Requires<[FeatureHighWord]>; def CGFI : CompareRIL<"cgfi", 0xC2C, z_scmp, GR64, imm64sx32>; // Comparison with memory. @@ -1106,8 +1111,13 @@ let Defs = [CC], CCValues = 0xE, IsLogical = 1 in { def CLGFR : CompareRRE<"clgf", 0xB931, null_frag, GR64, GR32>; def CLGR : CompareRRE<"clg", 0xB921, z_ucmp, GR64, GR64>; - // Comparison with a signed 32-bit immediate. + // Comparison with an unsigned 32-bit immediate. CLFIMux expands to CLFI + // or CLIH, depending on the choice of register. + def CLFIMux : CompareRIPseudo, + Requires<[FeatureHighWord]>; def CLFI : CompareRIL<"clfi", 0xC2F, z_ucmp, GR32, uimm32>; + def CLIH : CompareRIL<"clih", 0xCCF, z_ucmp, GR32, uimm32>, + Requires<[FeatureHighWord]>; def CLGFI : CompareRIL<"clgfi", 0xC2E, z_ucmp, GR64, imm64zx32>; // Comparison with memory. diff --git a/llvm/test/CodeGen/SystemZ/asm-18.ll b/llvm/test/CodeGen/SystemZ/asm-18.ll index e16bf65c3e8b..d39de6d6550b 100644 --- a/llvm/test/CodeGen/SystemZ/asm-18.ll +++ b/llvm/test/CodeGen/SystemZ/asm-18.ll @@ -669,3 +669,37 @@ define void @f30() { call void asm sideeffect "stepd $0", "r"(i32 %add3) ret void } + +; Test large immediate comparison involving high registers. +define i32 @f31() { +; CHECK-LABEL: f31: +; CHECK: stepa [[REG1:%r[0-5]]] +; CHECK: cih [[REG1]], 1000000000 +; CHECK: stepb [[REG2:%r[0-5]]] +; CHECK: clih [[REG2]], 1000000000 +; CHECK: br %r14 + %res1 = call i32 asm "stepa $0", "=h"() + %cmp1 = icmp sle i32 %res1, 1000000000 + %sel1 = select i1 %cmp1, i32 0, i32 1 + %res2 = call i32 asm "stepb $0, $1", "=h,r"(i32 %sel1) + %cmp2 = icmp ule i32 %res2, 1000000000 + %sel2 = select i1 %cmp2, i32 0, i32 1 + ret i32 %sel2 +} + +; Test large immediate comparison involving low registers. +define i32 @f32() { +; CHECK-LABEL: f32: +; CHECK: stepa [[REG1:%r[0-5]]] +; CHECK: cfi [[REG1]], 1000000000 +; CHECK: stepb [[REG2:%r[0-5]]] +; CHECK: clfi [[REG2]], 1000000000 +; CHECK: br %r14 + %res1 = call i32 asm "stepa $0", "=r"() + %cmp1 = icmp sle i32 %res1, 1000000000 + %sel1 = select i1 %cmp1, i32 0, i32 1 + %res2 = call i32 asm "stepb $0, $1", "=r,r"(i32 %sel1) + %cmp2 = icmp ule i32 %res2, 1000000000 + %sel2 = select i1 %cmp2, i32 0, i32 1 + ret i32 %sel2 +} diff --git a/llvm/test/MC/Disassembler/SystemZ/insns.txt b/llvm/test/MC/Disassembler/SystemZ/insns.txt index 2f2e7fa0cd1c..f88531b2cdf0 100644 --- a/llvm/test/MC/Disassembler/SystemZ/insns.txt +++ b/llvm/test/MC/Disassembler/SystemZ/insns.txt @@ -1351,6 +1351,24 @@ # CHECK: chy %r15, 0 0xe3 0xf0 0x00 0x00 0x00 0x79 +# CHECK: cih %r0, -2147483648 +0xcc 0x0d 0x80 0x00 0x00 0x00 + +# CHECK: cih %r0, -1 +0xcc 0x0d 0xff 0xff 0xff 0xff + +# CHECK: cih %r0, 0 +0xcc 0x0d 0x00 0x00 0x00 0x00 + +# CHECK: cih %r0, 1 +0xcc 0x0d 0x00 0x00 0x00 0x01 + +# CHECK: cih %r0, 2147483647 +0xcc 0x0d 0x7f 0xff 0xff 0xff + +# CHECK: cih %r15, 0 +0xcc 0xfd 0x00 0x00 0x00 0x00 + # CHECK: clc 0(1), 0 0xd5 0x00 0x00 0x00 0x00 0x00 @@ -1573,6 +1591,18 @@ # CHECK: cli 4095(%r15), 42 0x95 0x2a 0xff 0xff +# CHECK: clih %r0, 0 +0xcc 0x0f 0x00 0x00 0x00 0x00 + +# CHECK: clih %r0, 1 +0xcc 0x0f 0x00 0x00 0x00 0x01 + +# CHECK: clih %r0, 4294967295 +0xcc 0x0f 0xff 0xff 0xff 0xff + +# CHECK: clih %r15, 0 +0xcc 0xff 0x00 0x00 0x00 0x00 + # CHECK: cliy -524288, 0 0xeb 0x00 0x00 0x00 0x80 0x55 diff --git a/llvm/test/MC/SystemZ/insn-bad-z196.s b/llvm/test/MC/SystemZ/insn-bad-z196.s index 24640018a523..e387f149fd12 100644 --- a/llvm/test/MC/SystemZ/insn-bad-z196.s +++ b/llvm/test/MC/SystemZ/insn-bad-z196.s @@ -32,6 +32,22 @@ aih %r0, (-1 << 31) - 1 aih %r0, (1 << 31) +#CHECK: error: invalid operand +#CHECK: cih %r0, (-1 << 31) - 1 +#CHECK: error: invalid operand +#CHECK: cih %r0, (1 << 31) + + cih %r0, (-1 << 31) - 1 + cih %r0, (1 << 31) + +#CHECK: error: invalid operand +#CHECK: clih %r0, -1 +#CHECK: error: invalid operand +#CHECK: clih %r0, (1 << 32) + + clih %r0, -1 + clih %r0, (1 << 32) + #CHECK: error: invalid operand #CHECK: fidbra %f0, 0, %f0, -1 #CHECK: error: invalid operand diff --git a/llvm/test/MC/SystemZ/insn-bad.s b/llvm/test/MC/SystemZ/insn-bad.s index eadb9f099717..8de20612caad 100644 --- a/llvm/test/MC/SystemZ/insn-bad.s +++ b/llvm/test/MC/SystemZ/insn-bad.s @@ -679,6 +679,11 @@ chy %r0, -524289 chy %r0, 524288 +#CHECK: error: {{(instruction requires: high-word)?}} +#CHECK: cih %r0, 0 + + cih %r0, 0 + #CHECK: error: invalid operand #CHECK: cij %r0, -129, 0, 0 #CHECK: error: invalid operand @@ -961,6 +966,11 @@ cli 0, -1 cli 0, 256 +#CHECK: error: {{(instruction requires: high-word)?}} +#CHECK: clih %r0, 0 + + clih %r0, 0 + #CHECK: error: invalid operand #CHECK: clij %r0, -1, 0, 0 #CHECK: error: invalid operand diff --git a/llvm/test/MC/SystemZ/insn-good-z196.s b/llvm/test/MC/SystemZ/insn-good-z196.s index 2bc27bd58a0f..93687ea81f6e 100644 --- a/llvm/test/MC/SystemZ/insn-good-z196.s +++ b/llvm/test/MC/SystemZ/insn-good-z196.s @@ -135,6 +135,30 @@ ark %r15,%r0,%r0 ark %r7,%r8,%r9 +#CHECK: cih %r0, -2147483648 # encoding: [0xcc,0x0d,0x80,0x00,0x00,0x00] +#CHECK: cih %r0, -1 # encoding: [0xcc,0x0d,0xff,0xff,0xff,0xff] +#CHECK: cih %r0, 0 # encoding: [0xcc,0x0d,0x00,0x00,0x00,0x00] +#CHECK: cih %r0, 1 # encoding: [0xcc,0x0d,0x00,0x00,0x00,0x01] +#CHECK: cih %r0, 2147483647 # encoding: [0xcc,0x0d,0x7f,0xff,0xff,0xff] +#CHECK: cih %r15, 0 # encoding: [0xcc,0xfd,0x00,0x00,0x00,0x00] + + cih %r0, -1 << 31 + cih %r0, -1 + cih %r0, 0 + cih %r0, 1 + cih %r0, (1 << 31) - 1 + cih %r15, 0 + +#CHECK: clih %r0, 0 # encoding: [0xcc,0x0f,0x00,0x00,0x00,0x00] +#CHECK: clih %r0, 1 # encoding: [0xcc,0x0f,0x00,0x00,0x00,0x01] +#CHECK: clih %r0, 4294967295 # encoding: [0xcc,0x0f,0xff,0xff,0xff,0xff] +#CHECK: clih %r15, 0 # encoding: [0xcc,0xff,0x00,0x00,0x00,0x00] + + clih %r0, 0 + clih %r0, 1 + clih %r0, (1 << 32) - 1 + clih %r15, 0 + #CHECK: fidbra %f0, 0, %f0, 0 # encoding: [0xb3,0x5f,0x00,0x00] #CHECK: fidbra %f0, 0, %f0, 15 # encoding: [0xb3,0x5f,0x0f,0x00] #CHECK: fidbra %f0, 0, %f15, 0 # encoding: [0xb3,0x5f,0x00,0x0f]