From b83bf521136801c1b9ea72dc9daae9428782cc75 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Fri, 22 Nov 2013 17:28:28 +0000 Subject: [PATCH] [SystemZ] Fix TMHH and TMHL usage for z10 with -O0 I've no idea why I decided to handle TMxx differently from all the other high/low logic operations, but it was a stupid thing to do. The high registers aren't available as separate 32-bit registers on z10, so subreg_h32 can't be used on a GR64 there. I've normally been testing with z196 and with -O3 and so hadn't noticed this until now. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@195473 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/SystemZ/SystemZAsmPrinter.cpp | 30 ++++++++++---- lib/Target/SystemZ/SystemZInstrFormats.td | 7 ++++ lib/Target/SystemZ/SystemZInstrInfo.td | 9 +++-- lib/Target/SystemZ/SystemZPatterns.td | 8 ---- test/CodeGen/SystemZ/int-cmp-47.ll | 1 + test/CodeGen/SystemZ/int-cmp-49.ll | 49 +++++++++++++++++++++++ 6 files changed, 84 insertions(+), 20 deletions(-) create mode 100644 test/CodeGen/SystemZ/int-cmp-49.ll diff --git a/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/lib/Target/SystemZ/SystemZAsmPrinter.cpp index 75efdb0941a..75cbda4958a 100644 --- a/lib/Target/SystemZ/SystemZAsmPrinter.cpp +++ b/lib/Target/SystemZ/SystemZAsmPrinter.cpp @@ -29,19 +29,29 @@ using namespace llvm; // Return an RI instruction like MI with opcode Opcode, but with the // GR64 register operands turned into GR32s. static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) { - return MCInstBuilder(Opcode) - .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) - .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg())) - .addImm(MI->getOperand(2).getImm()); + if (MI->isCompare()) + return MCInstBuilder(Opcode) + .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) + .addImm(MI->getOperand(1).getImm()); + else + return MCInstBuilder(Opcode) + .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) + .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg())) + .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()); + if (MI->isCompare()) + return MCInstBuilder(Opcode) + .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) + .addImm(MI->getOperand(1).getImm()); + else + 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 @@ -112,6 +122,8 @@ void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) { LOWER_LOW(IILL); LOWER_LOW(IILH); + LOWER_LOW(TMLL); + LOWER_LOW(TMLH); LOWER_LOW(NILL); LOWER_LOW(NILH); LOWER_LOW(NILF); @@ -127,6 +139,8 @@ void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) { LOWER_HIGH(IIHL); LOWER_HIGH(IIHH); + LOWER_HIGH(TMHL); + LOWER_HIGH(TMHH); LOWER_HIGH(NIHL); LOWER_HIGH(NIHH); LOWER_HIGH(NIHF); diff --git a/lib/Target/SystemZ/SystemZInstrFormats.td b/lib/Target/SystemZ/SystemZInstrFormats.td index 353a0d3f737..a8efe165e36 100644 --- a/lib/Target/SystemZ/SystemZInstrFormats.td +++ b/lib/Target/SystemZ/SystemZInstrFormats.td @@ -1588,6 +1588,13 @@ class BinaryAliasRIL + : Alias<4, (outs), (ins cls:$R1, imm:$I2), [(operator cls:$R1, imm:$I2)]> { + let isCompare = 1; +} + // An alias of a RotateSelectRIEf, but with different register sizes. class RotateSelectAliasRIEf : Alias<6, (outs cls1:$R1), diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td index eb416036bf6..6524e442b63 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/lib/Target/SystemZ/SystemZInstrInfo.td @@ -1176,12 +1176,13 @@ let Defs = [CC] in { def TMHL : CompareRI<"tmhl", 0xA73, z_tm_reg, GRH32, imm32ll16>; def TMHH : CompareRI<"tmhh", 0xA72, z_tm_reg, GRH32, imm32lh16>; + def TMLL64 : CompareAliasRI; + def TMLH64 : CompareAliasRI; + def TMHL64 : CompareAliasRI; + def TMHH64 : CompareAliasRI; + defm TM : CompareSIPair<"tm", 0x91, 0xEB51, z_tm_mem, anyextloadi8, imm32zx8>; } -def : CompareGR64RI; -def : CompareGR64RI; -def : CompareGR64RI; -def : CompareGR64RI; //===----------------------------------------------------------------------===// // Prefetch diff --git a/lib/Target/SystemZ/SystemZPatterns.td b/lib/Target/SystemZ/SystemZPatterns.td index f3ca60b27ad..7706351e54b 100644 --- a/lib/Target/SystemZ/SystemZPatterns.td +++ b/lib/Target/SystemZ/SystemZPatterns.td @@ -112,14 +112,6 @@ multiclass CondStores64; } -// INSN performs a comparison between a 32-bit register and a constant. -// Record that it is equivalent to comparing subreg SUBREG of a GR64 with IMM. -class CompareGR64RI - : Pat<(compare GR64:$R1, imm:$I2), - (insn (EXTRACT_SUBREG GR64:$R1, subreg), - (imm.OperandTransform imm:$I2))>; - // Try to use MVC instruction INSN for a load of type LOAD followed by a store // of the same size. VT is the type of the intermediate (legalized) value and // LENGTH is the number of bytes loaded by LOAD. diff --git a/test/CodeGen/SystemZ/int-cmp-47.ll b/test/CodeGen/SystemZ/int-cmp-47.ll index c770ccdbb96..9ebcbfe525b 100644 --- a/test/CodeGen/SystemZ/int-cmp-47.ll +++ b/test/CodeGen/SystemZ/int-cmp-47.ll @@ -1,5 +1,6 @@ ; Test the use of TEST UNDER MASK for 64-bit operations. ; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s @g = global i32 0 diff --git a/test/CodeGen/SystemZ/int-cmp-49.ll b/test/CodeGen/SystemZ/int-cmp-49.ll new file mode 100644 index 00000000000..83f18a2a18a --- /dev/null +++ b/test/CodeGen/SystemZ/int-cmp-49.ll @@ -0,0 +1,49 @@ +; That that we don't try to use z196 instructions on z10 for TMHH and TMHL. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 -O0 | FileCheck %s + +@g = global i32 0 + +; Check the lowest useful TMHL value. +define void @f1(i64 %a) { +; CHECK-LABEL: f1: +; CHECK-NOT: risblg +; CHECK-NOT: risbhg +; CHECK: tmhl {{%r[0-5]}}, 1 +; CHECK-NOT: risblg +; CHECK-NOT: risbhg +; CHECK: br %r14 +entry: + %and = and i64 %a, 4294967296 + %cmp = icmp eq i64 %and, 0 + br i1 %cmp, label %exit, label %store + +store: + store i32 1, i32 *@g + br label %exit + +exit: + ret void +} + +; Check the lowest useful TMHH value. +define void @f2(i64 %a) { +; CHECK-LABEL: f2: +; CHECK-NOT: risblg +; CHECK-NOT: risbhg +; CHECK: tmhh {{%r[0-5]}}, 1 +; CHECK-NOT: risblg +; CHECK-NOT: risbhg +; CHECK: br %r14 +entry: + %and = and i64 %a, 281474976710656 + %cmp = icmp ne i64 %and, 0 + br i1 %cmp, label %exit, label %store + +store: + store i32 1, i32 *@g + br label %exit + +exit: + ret void +} -- 2.34.1