diff --git a/lib/Target/SystemZ/SystemZElimCompare.cpp b/lib/Target/SystemZ/SystemZElimCompare.cpp index b292b554779..6e42e283c9f 100644 --- a/lib/Target/SystemZ/SystemZElimCompare.cpp +++ b/lib/Target/SystemZ/SystemZElimCompare.cpp @@ -28,6 +28,7 @@ using namespace llvm; #define DEBUG_TYPE "systemz-elim-compare" STATISTIC(BranchOnCounts, "Number of branch-on-count instructions"); +STATISTIC(LoadAndTraps, "Number of load-and-trap instructions"); STATISTIC(EliminatedComparisons, "Number of eliminated comparisons"); STATISTIC(FusedComparisons, "Number of fused compare-and-branch instructions"); @@ -73,6 +74,8 @@ private: Reference getRegReferences(MachineInstr &MI, unsigned Reg); bool convertToBRCT(MachineInstr &MI, MachineInstr &Compare, SmallVectorImpl &CCUsers); + bool convertToLoadAndTrap(MachineInstr &MI, MachineInstr &Compare, + SmallVectorImpl &CCUsers); bool convertToLoadAndTest(MachineInstr &MI); bool adjustCCMasksForInstr(MachineInstr &MI, MachineInstr &Compare, SmallVectorImpl &CCUsers); @@ -225,6 +228,48 @@ bool SystemZElimCompare::convertToBRCT( return true; } +// Compare compares the result of MI against zero. If MI is a suitable load +// instruction and if CCUsers is a single conditional trap on zero, eliminate +// the load and convert the branch to a load-and-trap. Return true on success. +bool SystemZElimCompare::convertToLoadAndTrap( + MachineInstr &MI, MachineInstr &Compare, + SmallVectorImpl &CCUsers) { + unsigned LATOpcode = TII->getLoadAndTrap(MI.getOpcode()); + if (!LATOpcode) + return false; + + // Check whether we have a single CondTrap that traps on zero. + if (CCUsers.size() != 1) + return false; + MachineInstr *Branch = CCUsers[0]; + if (Branch->getOpcode() != SystemZ::CondTrap || + Branch->getOperand(0).getImm() != SystemZ::CCMASK_ICMP || + Branch->getOperand(1).getImm() != SystemZ::CCMASK_CMP_EQ) + return false; + + // We already know that there are no references to the register between + // MI and Compare. Make sure that there are also no references between + // Compare and Branch. + unsigned SrcReg = getCompareSourceReg(Compare); + MachineBasicBlock::iterator MBBI = Compare, MBBE = Branch; + for (++MBBI; MBBI != MBBE; ++MBBI) + if (getRegReferences(*MBBI, SrcReg)) + return false; + + // The transformation is OK. Rebuild Branch as a load-and-trap. + MachineOperand Target(Branch->getOperand(2)); + while (Branch->getNumOperands()) + Branch->RemoveOperand(0); + Branch->setDesc(TII->get(LATOpcode)); + MachineInstrBuilder(*Branch->getParent()->getParent(), Branch) + .addOperand(MI.getOperand(0)) + .addOperand(MI.getOperand(1)) + .addOperand(MI.getOperand(2)) + .addOperand(MI.getOperand(3)); + MI.eraseFromParent(); + return true; +} + // If MI is a load instruction, try to convert it into a LOAD AND TEST. // Return true on success. bool SystemZElimCompare::convertToLoadAndTest(MachineInstr &MI) { @@ -353,11 +398,17 @@ bool SystemZElimCompare::optimizeCompareZero( MachineInstr &MI = *MBBI; if (resultTests(MI, SrcReg)) { // Try to remove both MI and Compare by converting a branch to BRCT(G). - // We don't care in this case whether CC is modified between MI and - // Compare. - if (!CCRefs.Use && !SrcRefs && convertToBRCT(MI, Compare, CCUsers)) { - BranchOnCounts += 1; - return true; + // or a load-and-trap instruction. We don't care in this case whether + // CC is modified between MI and Compare. + if (!CCRefs.Use && !SrcRefs) { + if (convertToBRCT(MI, Compare, CCUsers)) { + BranchOnCounts += 1; + return true; + } + if (convertToLoadAndTrap(MI, Compare, CCUsers)) { + LoadAndTraps += 1; + return true; + } } // Try to eliminate Compare by reusing a CC result from MI. if ((!CCRefs && convertToLoadAndTest(MI)) || diff --git a/lib/Target/SystemZ/SystemZFeatures.td b/lib/Target/SystemZ/SystemZFeatures.td index 70c51509309..0fb3c55ebe0 100644 --- a/lib/Target/SystemZ/SystemZFeatures.td +++ b/lib/Target/SystemZ/SystemZFeatures.td @@ -84,6 +84,11 @@ def Arch9NewFeatures : SystemZFeatureList<[ // //===----------------------------------------------------------------------===// +def FeatureLoadAndTrap : SystemZFeature< + "load-and-trap", "LoadAndTrap", + "Assume that the load-and-trap facility is installed" +>; + def FeatureMiscellaneousExtensions : SystemZFeature< "miscellaneous-extensions", "MiscellaneousExtensions", "Assume that the miscellaneous-extensions facility is installed" @@ -100,6 +105,7 @@ def FeatureTransactionalExecution : SystemZFeature< >; def Arch10NewFeatures : SystemZFeatureList<[ + FeatureLoadAndTrap, FeatureMiscellaneousExtensions, FeatureProcessorAssist, FeatureTransactionalExecution diff --git a/lib/Target/SystemZ/SystemZInstrInfo.cpp b/lib/Target/SystemZ/SystemZInstrInfo.cpp index 7b835b04fd3..3565d5f2c49 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -1678,6 +1678,25 @@ unsigned SystemZInstrInfo::getFusedCompare(unsigned Opcode, return 0; } +unsigned SystemZInstrInfo::getLoadAndTrap(unsigned Opcode) const { + if (!STI.hasLoadAndTrap()) + return 0; + switch (Opcode) { + case SystemZ::L: + case SystemZ::LY: + return SystemZ::LAT; + case SystemZ::LG: + return SystemZ::LGAT; + case SystemZ::LFH: + return SystemZ::LFHAT; + case SystemZ::LLGF: + return SystemZ::LLGFAT; + case SystemZ::LLGT: + return SystemZ::LLGTAT; + } + return 0; +} + void SystemZInstrInfo::loadImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned Reg, uint64_t Value) const { diff --git a/lib/Target/SystemZ/SystemZInstrInfo.h b/lib/Target/SystemZ/SystemZInstrInfo.h index aadeb6b9f1d..794b193a501 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.h +++ b/lib/Target/SystemZ/SystemZInstrInfo.h @@ -286,6 +286,10 @@ public: SystemZII::FusedCompareType Type, const MachineInstr *MI = nullptr) const; + // If Opcode is a LOAD opcode for with an associated LOAD AND TRAP + // operation exists, returh the opcode for the latter, otherwise return 0. + unsigned getLoadAndTrap(unsigned Opcode) const; + // Emit code before MBBI in MI to move immediate value Value into // physical register Reg. void loadImmediate(MachineBasicBlock &MBB, diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td index 87a70da6856..c180d405419 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/lib/Target/SystemZ/SystemZInstrInfo.td @@ -426,6 +426,13 @@ let Predicates = [FeatureLoadAndZeroRightmostByte] in { (LZRG bdxaddr20only:$src)>; } +// Load and trap. +let Predicates = [FeatureLoadAndTrap] in { + def LAT : UnaryRXY<"lat", 0xE39F, null_frag, GR32, 4>; + def LFHAT : UnaryRXY<"lfhat", 0xE3C8, null_frag, GRH32, 4>; + def LGAT : UnaryRXY<"lgat", 0xE385, null_frag, GR64, 8>; +} + // Register stores. let SimpleBDXStore = 1 in { // Expands to ST, STY or STFH, depending on the choice of register. @@ -662,6 +669,12 @@ let Predicates = [FeatureLoadAndZeroRightmostByte] in { (LLZRGF bdxaddr20only:$src)>; } +// Load and trap. +let Predicates = [FeatureLoadAndTrap] in { + def LLGFAT : UnaryRXY<"llgfat", 0xE39D, null_frag, GR64, 4>; + def LLGTAT : UnaryRXY<"llgtat", 0xE39C, null_frag, GR64, 4>; +} + //===----------------------------------------------------------------------===// // Truncations //===----------------------------------------------------------------------===// diff --git a/lib/Target/SystemZ/SystemZScheduleZ13.td b/lib/Target/SystemZ/SystemZScheduleZ13.td index c9007e59bcb..f712d2b0f9b 100644 --- a/lib/Target/SystemZ/SystemZScheduleZ13.td +++ b/lib/Target/SystemZ/SystemZScheduleZ13.td @@ -202,6 +202,9 @@ def : InstRW<[FXa], (instregex "LR(Mux)?$")>; // Load and zero rightmost byte def : InstRW<[LSU], (instregex "LZR(F|G)$")>; +// Load and trap +def : InstRW<[FXb, LSU, Lat5], (instregex "L(FH|G)?AT$")>; + // Load and test def : InstRW<[FXa, LSU, Lat5], (instregex "LT(G)?$")>; def : InstRW<[FXa], (instregex "LT(G)?R$")>; @@ -256,6 +259,9 @@ def : InstRW<[LSU], (instregex "LLG(C|H|F|T|HRL|FRL)$")>; // Load and zero rightmost byte def : InstRW<[LSU], (instregex "LLZRGF$")>; +// Load and trap +def : InstRW<[FXb, LSU, Lat5], (instregex "LLG(F|T)?AT$")>; + //===----------------------------------------------------------------------===// // Truncations //===----------------------------------------------------------------------===// diff --git a/lib/Target/SystemZ/SystemZScheduleZEC12.td b/lib/Target/SystemZ/SystemZScheduleZEC12.td index 73008749773..49353eb1d3d 100644 --- a/lib/Target/SystemZ/SystemZScheduleZEC12.td +++ b/lib/Target/SystemZ/SystemZScheduleZEC12.td @@ -175,6 +175,9 @@ def : InstRW<[FXU], (instregex "LG(F|H)I$")>; def : InstRW<[FXU], (instregex "LHI(Mux)?$")>; def : InstRW<[FXU], (instregex "LR(Mux)?$")>; +// Load and trap +def : InstRW<[FXU, LSU, Lat5], (instregex "L(FH|G)?AT$")>; + // Load and test def : InstRW<[FXU, LSU, Lat5], (instregex "LT(G)?$")>; def : InstRW<[FXU], (instregex "LT(G)?R$")>; @@ -224,6 +227,9 @@ def : InstRW<[FXU, LSU, Lat5], (instregex "LL(C|H)H$")>; def : InstRW<[LSU], (instregex "LLHRL$")>; def : InstRW<[LSU], (instregex "LLG(C|H|F|T|HRL|FRL)$")>; +// Load and trap +def : InstRW<[FXU, LSU, Lat5], (instregex "LLG(F|T)?AT$")>; + //===----------------------------------------------------------------------===// // Truncations //===----------------------------------------------------------------------===// diff --git a/lib/Target/SystemZ/SystemZSubtarget.cpp b/lib/Target/SystemZ/SystemZSubtarget.cpp index c74913219af..bf7277a6ef1 100644 --- a/lib/Target/SystemZ/SystemZSubtarget.cpp +++ b/lib/Target/SystemZ/SystemZSubtarget.cpp @@ -39,8 +39,8 @@ SystemZSubtarget::SystemZSubtarget(const Triple &TT, const std::string &CPU, HasLoadStoreOnCond(false), HasHighWord(false), HasFPExtension(false), HasPopulationCount(false), HasFastSerialization(false), HasInterlockedAccess1(false), HasMiscellaneousExtensions(false), - HasTransactionalExecution(false), HasProcessorAssist(false), - HasVector(false), HasLoadStoreOnCond2(false), + HasLoadAndTrap(false), HasTransactionalExecution(false), + HasProcessorAssist(false), HasVector(false), HasLoadStoreOnCond2(false), HasLoadAndZeroRightmostByte(false), TargetTriple(TT), InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this), TSInfo(), FrameLowering() {} diff --git a/lib/Target/SystemZ/SystemZSubtarget.h b/lib/Target/SystemZ/SystemZSubtarget.h index 9218a7831d9..8475e2edaf2 100644 --- a/lib/Target/SystemZ/SystemZSubtarget.h +++ b/lib/Target/SystemZ/SystemZSubtarget.h @@ -42,6 +42,7 @@ protected: bool HasFastSerialization; bool HasInterlockedAccess1; bool HasMiscellaneousExtensions; + bool HasLoadAndTrap; bool HasTransactionalExecution; bool HasProcessorAssist; bool HasVector; @@ -113,6 +114,9 @@ public: return HasMiscellaneousExtensions; } + // Return true if the target has the load-and-trap facility. + bool hasLoadAndTrap() const { return HasLoadAndTrap; } + // Return true if the target has the transactional-execution facility. bool hasTransactionalExecution() const { return HasTransactionalExecution; } diff --git a/test/CodeGen/SystemZ/trap-03.ll b/test/CodeGen/SystemZ/trap-03.ll new file mode 100644 index 00000000000..d3cc882add7 --- /dev/null +++ b/test/CodeGen/SystemZ/trap-03.ll @@ -0,0 +1,157 @@ +; Test load-and-trap instructions (LAT/LGAT) +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=zEC12 | FileCheck %s + +declare void @llvm.trap() + +; Check LAT with no displacement. +define i32 @f1(i32 *%ptr) { +; CHECK-LABEL: f1: +; CHECK: lat %r2, 0(%r2) +; CHECK: br %r14 +entry: + %val = load i32, i32 *%ptr + %cmp = icmp eq i32 %val, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + tail call void @llvm.trap() + unreachable + +if.end: ; preds = %entry + ret i32 %val +} + +; Check the high end of the LAT range. +define i32 @f2(i32 *%src) { +; CHECK-LABEL: f2: +; CHECK: lat %r2, 524284(%r2) +; CHECK: br %r14 + %ptr = getelementptr i32, i32 *%src, i64 131071 + %val = load i32, i32 *%ptr + %cmp = icmp eq i32 %val, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + tail call void @llvm.trap() + unreachable + +if.end: ; preds = %entry + ret i32 %val +} + +; Check the next word up, which needs separate address logic. +; Other sequences besides this one would be OK. +define i32 @f3(i32 *%src) { +; CHECK-LABEL: f3: +; CHECK: agfi %r2, 524288 +; CHECK: lat %r2, 0(%r2) +; CHECK: br %r14 + %ptr = getelementptr i32, i32 *%src, i64 131072 + %val = load i32, i32 *%ptr + %cmp = icmp eq i32 %val, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + tail call void @llvm.trap() + unreachable + +if.end: ; preds = %entry + ret i32 %val +} + +; Check that LAT allows an index. +define i32 @f4(i64 %src, i64 %index) { +; CHECK-LABEL: f4: +; CHECK: lat %r2, 524287(%r3,%r2) +; CHECK: br %r14 + %add1 = add i64 %src, %index + %add2 = add i64 %add1, 524287 + %ptr = inttoptr i64 %add2 to i32 * + %val = load i32, i32 *%ptr + %cmp = icmp eq i32 %val, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + tail call void @llvm.trap() + unreachable + +if.end: ; preds = %entry + ret i32 %val +} + +; Check LGAT with no displacement. +define i64 @f5(i64 *%ptr) { +; CHECK-LABEL: f5: +; CHECK: lgat %r2, 0(%r2) +; CHECK: br %r14 +entry: + %val = load i64, i64 *%ptr + %cmp = icmp eq i64 %val, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + tail call void @llvm.trap() + unreachable + +if.end: ; preds = %entry + ret i64 %val +} + +; Check the high end of the LGAT range. +define i64 @f6(i64 *%src) { +; CHECK-LABEL: f6: +; CHECK: lgat %r2, 524280(%r2) +; CHECK: br %r14 + %ptr = getelementptr i64, i64 *%src, i64 65535 + %val = load i64, i64 *%ptr + %cmp = icmp eq i64 %val, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + tail call void @llvm.trap() + unreachable + +if.end: ; preds = %entry + ret i64 %val +} + +; Check the next word up, which needs separate address logic. +; Other sequences besides this one would be OK. +define i64 @f7(i64 *%src) { +; CHECK-LABEL: f7: +; CHECK: agfi %r2, 524288 +; CHECK: lgat %r2, 0(%r2) +; CHECK: br %r14 + %ptr = getelementptr i64, i64 *%src, i64 65536 + %val = load i64, i64 *%ptr + %cmp = icmp eq i64 %val, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + tail call void @llvm.trap() + unreachable + +if.end: ; preds = %entry + ret i64 %val +} + +; Check that LGAT allows an index. +define i64 @f8(i64 %src, i64 %index) { +; CHECK-LABEL: f8: +; CHECK: lgat %r2, 524287(%r3,%r2) +; CHECK: br %r14 + %add1 = add i64 %src, %index + %add2 = add i64 %add1, 524287 + %ptr = inttoptr i64 %add2 to i64 * + %val = load i64, i64 *%ptr + %cmp = icmp eq i64 %val, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + tail call void @llvm.trap() + unreachable + +if.end: ; preds = %entry + ret i64 %val +} diff --git a/test/CodeGen/SystemZ/trap-04.ll b/test/CodeGen/SystemZ/trap-04.ll new file mode 100644 index 00000000000..9e7897e6321 --- /dev/null +++ b/test/CodeGen/SystemZ/trap-04.ll @@ -0,0 +1,170 @@ +; Test load-and-trap instructions (LLGFAT/LLGFTAT) +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=zEC12 | FileCheck %s + +declare void @llvm.trap() + +; Check LLGFAT with no displacement. +define i64 @f1(i32 *%ptr) { +; CHECK-LABEL: f1: +; CHECK: llgfat %r2, 0(%r2) +; CHECK: br %r14 +entry: + %val = load i32, i32 *%ptr + %ext = zext i32 %val to i64 + %cmp = icmp eq i64 %ext, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + tail call void @llvm.trap() + unreachable + +if.end: ; preds = %entry + ret i64 %ext +} + +; Check the high end of the LLGFAT range. +define i64 @f2(i32 *%src) { +; CHECK-LABEL: f2: +; CHECK: llgfat %r2, 524284(%r2) +; CHECK: br %r14 + %ptr = getelementptr i32, i32 *%src, i64 131071 + %val = load i32, i32 *%ptr + %ext = zext i32 %val to i64 + %cmp = icmp eq i64 %ext, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + tail call void @llvm.trap() + unreachable + +if.end: ; preds = %entry + ret i64 %ext +} + +; Check the next word up, which needs separate address logic. +; Other sequences besides this one would be OK. +define i64 @f3(i32 *%src) { +; CHECK-LABEL: f3: +; CHECK: agfi %r2, 524288 +; CHECK: llgfat %r2, 0(%r2) +; CHECK: br %r14 + %ptr = getelementptr i32, i32 *%src, i64 131072 + %val = load i32, i32 *%ptr + %ext = zext i32 %val to i64 + %cmp = icmp eq i64 %ext, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + tail call void @llvm.trap() + unreachable + +if.end: ; preds = %entry + ret i64 %ext +} + +; Check that LLGFAT allows an index. +define i64 @f4(i64 %src, i64 %index) { +; CHECK-LABEL: f4: +; CHECK: llgfat %r2, 524287(%r3,%r2) +; CHECK: br %r14 + %add1 = add i64 %src, %index + %add2 = add i64 %add1, 524287 + %ptr = inttoptr i64 %add2 to i32 * + %val = load i32, i32 *%ptr + %ext = zext i32 %val to i64 + %cmp = icmp eq i64 %ext, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + tail call void @llvm.trap() + unreachable + +if.end: ; preds = %entry + ret i64 %ext +} + +; Check LLGTAT with no displacement. +define i64 @f5(i32 *%ptr) { +; CHECK-LABEL: f5: +; CHECK: llgtat %r2, 0(%r2) +; CHECK: br %r14 +entry: + %val = load i32, i32 *%ptr + %ext = zext i32 %val to i64 + %and = and i64 %ext, 2147483647 + %cmp = icmp eq i64 %and, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + tail call void @llvm.trap() + unreachable + +if.end: ; preds = %entry + ret i64 %and +} + +; Check the high end of the LLGTAT range. +define i64 @f6(i32 *%src) { +; CHECK-LABEL: f6: +; CHECK: llgtat %r2, 524284(%r2) +; CHECK: br %r14 + %ptr = getelementptr i32, i32 *%src, i64 131071 + %val = load i32, i32 *%ptr + %ext = zext i32 %val to i64 + %and = and i64 %ext, 2147483647 + %cmp = icmp eq i64 %and, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + tail call void @llvm.trap() + unreachable + +if.end: ; preds = %entry + ret i64 %and +} + +; Check the next word up, which needs separate address logic. +; Other sequences besides this one would be OK. +define i64 @f7(i32 *%src) { +; CHECK-LABEL: f7: +; CHECK: agfi %r2, 524288 +; CHECK: llgtat %r2, 0(%r2) +; CHECK: br %r14 + %ptr = getelementptr i32, i32 *%src, i64 131072 + %val = load i32, i32 *%ptr + %ext = zext i32 %val to i64 + %and = and i64 %ext, 2147483647 + %cmp = icmp eq i64 %and, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + tail call void @llvm.trap() + unreachable + +if.end: ; preds = %entry + ret i64 %and +} + +; Check that LLGTAT allows an index. +define i64 @f8(i64 %src, i64 %index) { +; CHECK-LABEL: f8: +; CHECK: llgtat %r2, 524287(%r3,%r2) +; CHECK: br %r14 + %add1 = add i64 %src, %index + %add2 = add i64 %add1, 524287 + %ptr = inttoptr i64 %add2 to i32 * + %val = load i32, i32 *%ptr + %ext = zext i32 %val to i64 + %and = and i64 %ext, 2147483647 + %cmp = icmp eq i64 %and, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + tail call void @llvm.trap() + unreachable + +if.end: ; preds = %entry + ret i64 %and +} + diff --git a/test/CodeGen/SystemZ/trap-05.ll b/test/CodeGen/SystemZ/trap-05.ll new file mode 100644 index 00000000000..7aabedbfadd --- /dev/null +++ b/test/CodeGen/SystemZ/trap-05.ll @@ -0,0 +1,92 @@ +; Test load-and-trap instructions (LFHAT) +; See comments in asm-18.ll about testing high-word operations. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=zEC12 \ +; RUN: -no-integrated-as | FileCheck %s + +declare void @llvm.trap() + +; Check LAT with no displacement. +define void @f1(i32 *%ptr) { +; CHECK-LABEL: f1: +; CHECK: lfhat [[REG:%r[0-9]+]], 0(%r2) +; CHECK: stepa [[REG]] +; CHECK: br %r14 +entry: + %val = load i32, i32 *%ptr + %cmp = icmp eq i32 %val, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + tail call void @llvm.trap() + unreachable + +if.end: ; preds = %entry + call void asm sideeffect "stepa $0", "h"(i32 %val) + ret void; +} + +; Check the high end of the LAT range. +define void @f2(i32 *%src) { +; CHECK-LABEL: f2: +; CHECK: lfhat [[REG:%r[0-9]+]], 524284(%r2) +; CHECK: stepa [[REG]] +; CHECK: br %r14 + %ptr = getelementptr i32, i32 *%src, i64 131071 + %val = load i32, i32 *%ptr + %cmp = icmp eq i32 %val, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + tail call void @llvm.trap() + unreachable + +if.end: ; preds = %entry + call void asm sideeffect "stepa $0", "h"(i32 %val) + ret void; +} + +; Check the next word up, which needs separate address logic. +; Other sequences besides this one would be OK. +define void @f3(i32 *%src) { +; CHECK-LABEL: f3: +; CHECK: agfi %r2, 524288 +; CHECK: lfhat [[REG:%r[0-9]+]], 0(%r2) +; CHECK: stepa [[REG]] +; CHECK: br %r14 + %ptr = getelementptr i32, i32 *%src, i64 131072 + %val = load i32, i32 *%ptr + %cmp = icmp eq i32 %val, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + tail call void @llvm.trap() + unreachable + +if.end: ; preds = %entry + call void asm sideeffect "stepa $0", "h"(i32 %val) + ret void; +} + +; Check that LAT allows an index. +define void @f4(i64 %src, i64 %index) { +; CHECK-LABEL: f4: +; CHECK: lfhat [[REG:%r[0-9]+]], 524287(%r3,%r2) +; CHECK: stepa [[REG]] +; CHECK: br %r14 + %add1 = add i64 %src, %index + %add2 = add i64 %add1, 524287 + %ptr = inttoptr i64 %add2 to i32 * + %val = load i32, i32 *%ptr + %cmp = icmp eq i32 %val, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + tail call void @llvm.trap() + unreachable + +if.end: ; preds = %entry + call void asm sideeffect "stepa $0", "h"(i32 %val) + ret void; +} + diff --git a/test/MC/Disassembler/SystemZ/insns.txt b/test/MC/Disassembler/SystemZ/insns.txt index 1c521a512b6..b19281ae854 100644 --- a/test/MC/Disassembler/SystemZ/insns.txt +++ b/test/MC/Disassembler/SystemZ/insns.txt @@ -5188,6 +5188,36 @@ # CHECK: lfh %r15, 0 0xe3 0xf0 0x00 0x00 0x00 0xca +# CHECK: lfhat %r0, -524288 +0xe3 0x00 0x00 0x00 0x80 0xc8 + +# CHECK: lfhat %r0, -1 +0xe3 0x00 0x0f 0xff 0xff 0xc8 + +# CHECK: lfhat %r0, 0 +0xe3 0x00 0x00 0x00 0x00 0xc8 + +# CHECK: lfhat %r0, 1 +0xe3 0x00 0x00 0x01 0x00 0xc8 + +# CHECK: lfhat %r0, 524287 +0xe3 0x00 0x0f 0xff 0x7f 0xc8 + +# CHECK: lfhat %r0, 0(%r1) +0xe3 0x00 0x10 0x00 0x00 0xc8 + +# CHECK: lfhat %r0, 0(%r15) +0xe3 0x00 0xf0 0x00 0x00 0xc8 + +# CHECK: lfhat %r0, 524287(%r1,%r15) +0xe3 0x01 0xff 0xff 0x7f 0xc8 + +# CHECK: lfhat %r0, 524287(%r15,%r1) +0xe3 0x0f 0x1f 0xff 0x7f 0xc8 + +# CHECK: lfhat %r15, 0 +0xe3 0xf0 0x00 0x00 0x00 0xc8 + # CHECK: lgbr %r0, %r15 0xb9 0x06 0x00 0x0f @@ -5398,6 +5428,36 @@ # CHECK: lg %r15, 0 0xe3 0xf0 0x00 0x00 0x00 0x04 +# CHECK: lgat %r0, -524288 +0xe3 0x00 0x00 0x00 0x80 0x85 + +# CHECK: lgat %r0, -1 +0xe3 0x00 0x0f 0xff 0xff 0x85 + +# CHECK: lgat %r0, 0 +0xe3 0x00 0x00 0x00 0x00 0x85 + +# CHECK: lgat %r0, 1 +0xe3 0x00 0x00 0x01 0x00 0x85 + +# CHECK: lgat %r0, 524287 +0xe3 0x00 0x0f 0xff 0x7f 0x85 + +# CHECK: lgat %r0, 0(%r1) +0xe3 0x00 0x10 0x00 0x00 0x85 + +# CHECK: lgat %r0, 0(%r15) +0xe3 0x00 0xf0 0x00 0x00 0x85 + +# CHECK: lgat %r0, 524287(%r1,%r15) +0xe3 0x01 0xff 0xff 0x7f 0x85 + +# CHECK: lgat %r0, 524287(%r15,%r1) +0xe3 0x0f 0x1f 0xff 0x7f 0x85 + +# CHECK: lgat %r15, 0 +0xe3 0xf0 0x00 0x00 0x00 0x85 + # CHECK: lhi %r0, -32768 0xa7 0x08 0x80 0x00 @@ -5653,6 +5713,36 @@ # CHECK: llgf %r15, 0 0xe3 0xf0 0x00 0x00 0x00 0x16 +# CHECK: llgfat %r0, -524288 +0xe3 0x00 0x00 0x00 0x80 0x9d + +# CHECK: llgfat %r0, -1 +0xe3 0x00 0x0f 0xff 0xff 0x9d + +# CHECK: llgfat %r0, 0 +0xe3 0x00 0x00 0x00 0x00 0x9d + +# CHECK: llgfat %r0, 1 +0xe3 0x00 0x00 0x01 0x00 0x9d + +# CHECK: llgfat %r0, 524287 +0xe3 0x00 0x0f 0xff 0x7f 0x9d + +# CHECK: llgfat %r0, 0(%r1) +0xe3 0x00 0x10 0x00 0x00 0x9d + +# CHECK: llgfat %r0, 0(%r15) +0xe3 0x00 0xf0 0x00 0x00 0x9d + +# CHECK: llgfat %r0, 524287(%r1,%r15) +0xe3 0x01 0xff 0xff 0x7f 0x9d + +# CHECK: llgfat %r0, 524287(%r15,%r1) +0xe3 0x0f 0x1f 0xff 0x7f 0x9d + +# CHECK: llgfat %r15, 0 +0xe3 0xf0 0x00 0x00 0x00 0x9d + # CHECK: llgtr %r0, %r15 0xb9 0x17 0x00 0x0f @@ -5692,6 +5782,36 @@ # CHECK: llgt %r15, 0 0xe3 0xf0 0x00 0x00 0x00 0x17 +# CHECK: llgtat %r0, -524288 +0xe3 0x00 0x00 0x00 0x80 0x9c + +# CHECK: llgtat %r0, -1 +0xe3 0x00 0x0f 0xff 0xff 0x9c + +# CHECK: llgtat %r0, 0 +0xe3 0x00 0x00 0x00 0x00 0x9c + +# CHECK: llgtat %r0, 1 +0xe3 0x00 0x00 0x01 0x00 0x9c + +# CHECK: llgtat %r0, 524287 +0xe3 0x00 0x0f 0xff 0x7f 0x9c + +# CHECK: llgtat %r0, 0(%r1) +0xe3 0x00 0x10 0x00 0x00 0x9c + +# CHECK: llgtat %r0, 0(%r15) +0xe3 0x00 0xf0 0x00 0x00 0x9c + +# CHECK: llgtat %r0, 524287(%r1,%r15) +0xe3 0x01 0xff 0xff 0x7f 0x9c + +# CHECK: llgtat %r0, 524287(%r15,%r1) +0xe3 0x0f 0x1f 0xff 0x7f 0x9c + +# CHECK: llgtat %r15, 0 +0xe3 0xf0 0x00 0x00 0x00 0x9c + # CHECK: llghr %r0, %r15 0xb9 0x85 0x00 0x0f @@ -6502,6 +6622,36 @@ # CHECK: l %r15, 0 0x58 0xf0 0x00 0x00 +# CHECK: lat %r0, -524288 +0xe3 0x00 0x00 0x00 0x80 0x9f + +# CHECK: lat %r0, -1 +0xe3 0x00 0x0f 0xff 0xff 0x9f + +# CHECK: lat %r0, 0 +0xe3 0x00 0x00 0x00 0x00 0x9f + +# CHECK: lat %r0, 1 +0xe3 0x00 0x00 0x01 0x00 0x9f + +# CHECK: lat %r0, 524287 +0xe3 0x00 0x0f 0xff 0x7f 0x9f + +# CHECK: lat %r0, 0(%r1) +0xe3 0x00 0x10 0x00 0x00 0x9f + +# CHECK: lat %r0, 0(%r15) +0xe3 0x00 0xf0 0x00 0x00 0x9f + +# CHECK: lat %r0, 524287(%r1,%r15) +0xe3 0x01 0xff 0xff 0x7f 0x9f + +# CHECK: lat %r0, 524287(%r15,%r1) +0xe3 0x0f 0x1f 0xff 0x7f 0x9f + +# CHECK: lat %r15, 0 +0xe3 0xf0 0x00 0x00 0x00 0x9f + # CHECK: lt %r0, -524288 0xe3 0x00 0x00 0x00 0x80 0x12 diff --git a/test/MC/SystemZ/insn-bad-zEC12.s b/test/MC/SystemZ/insn-bad-zEC12.s index b86b4b86438..a88fe7ebe7a 100644 --- a/test/MC/SystemZ/insn-bad-zEC12.s +++ b/test/MC/SystemZ/insn-bad-zEC12.s @@ -54,6 +54,46 @@ clgto %r0, 0 clgtno %r0, 0 +#CHECK: error: invalid operand +#CHECK: lat %r0, -524289 +#CHECK: error: invalid operand +#CHECK: lat %r0, 524288 + + lat %r0, -524289 + lat %r0, 524288 + +#CHECK: error: invalid operand +#CHECK: lfhat %r0, -524289 +#CHECK: error: invalid operand +#CHECK: lfhat %r0, 524288 + + lfhat %r0, -524289 + lfhat %r0, 524288 + +#CHECK: error: invalid operand +#CHECK: lgat %r0, -524289 +#CHECK: error: invalid operand +#CHECK: lgat %r0, 524288 + + lgat %r0, -524289 + lgat %r0, 524288 + +#CHECK: error: invalid operand +#CHECK: llgfat %r0, -524289 +#CHECK: error: invalid operand +#CHECK: llgfat %r0, 524288 + + llgfat %r0, -524289 + llgfat %r0, 524288 + +#CHECK: error: invalid operand +#CHECK: llgtat %r0, -524289 +#CHECK: error: invalid operand +#CHECK: llgtat %r0, 524288 + + llgtat %r0, -524289 + llgtat %r0, 524288 + #CHECK: error: instruction requires: vector #CHECK: lcbb %r0, 0, 0 diff --git a/test/MC/SystemZ/insn-good-zEC12.s b/test/MC/SystemZ/insn-good-zEC12.s index b58ce702175..cb604f96d6b 100644 --- a/test/MC/SystemZ/insn-good-zEC12.s +++ b/test/MC/SystemZ/insn-good-zEC12.s @@ -66,6 +66,116 @@ clgtnl %r0, 0(%r15) clgtnh %r0, 0(%r15) +#CHECK: lat %r0, -524288 # encoding: [0xe3,0x00,0x00,0x00,0x80,0x9f] +#CHECK: lat %r0, -1 # encoding: [0xe3,0x00,0x0f,0xff,0xff,0x9f] +#CHECK: lat %r0, 0 # encoding: [0xe3,0x00,0x00,0x00,0x00,0x9f] +#CHECK: lat %r0, 1 # encoding: [0xe3,0x00,0x00,0x01,0x00,0x9f] +#CHECK: lat %r0, 524287 # encoding: [0xe3,0x00,0x0f,0xff,0x7f,0x9f] +#CHECK: lat %r0, 0(%r1) # encoding: [0xe3,0x00,0x10,0x00,0x00,0x9f] +#CHECK: lat %r0, 0(%r15) # encoding: [0xe3,0x00,0xf0,0x00,0x00,0x9f] +#CHECK: lat %r0, 524287(%r1,%r15) # encoding: [0xe3,0x01,0xff,0xff,0x7f,0x9f] +#CHECK: lat %r0, 524287(%r15,%r1) # encoding: [0xe3,0x0f,0x1f,0xff,0x7f,0x9f] +#CHECK: lat %r15, 0 # encoding: [0xe3,0xf0,0x00,0x00,0x00,0x9f] + + lat %r0, -524288 + lat %r0, -1 + lat %r0, 0 + lat %r0, 1 + lat %r0, 524287 + lat %r0, 0(%r1) + lat %r0, 0(%r15) + lat %r0, 524287(%r1,%r15) + lat %r0, 524287(%r15,%r1) + lat %r15, 0 + +#CHECK: lfhat %r0, -524288 # encoding: [0xe3,0x00,0x00,0x00,0x80,0xc8] +#CHECK: lfhat %r0, -1 # encoding: [0xe3,0x00,0x0f,0xff,0xff,0xc8] +#CHECK: lfhat %r0, 0 # encoding: [0xe3,0x00,0x00,0x00,0x00,0xc8] +#CHECK: lfhat %r0, 1 # encoding: [0xe3,0x00,0x00,0x01,0x00,0xc8] +#CHECK: lfhat %r0, 524287 # encoding: [0xe3,0x00,0x0f,0xff,0x7f,0xc8] +#CHECK: lfhat %r0, 0(%r1) # encoding: [0xe3,0x00,0x10,0x00,0x00,0xc8] +#CHECK: lfhat %r0, 0(%r15) # encoding: [0xe3,0x00,0xf0,0x00,0x00,0xc8] +#CHECK: lfhat %r0, 524287(%r1,%r15) # encoding: [0xe3,0x01,0xff,0xff,0x7f,0xc8] +#CHECK: lfhat %r0, 524287(%r15,%r1) # encoding: [0xe3,0x0f,0x1f,0xff,0x7f,0xc8] +#CHECK: lfhat %r15, 0 # encoding: [0xe3,0xf0,0x00,0x00,0x00,0xc8] + + lfhat %r0, -524288 + lfhat %r0, -1 + lfhat %r0, 0 + lfhat %r0, 1 + lfhat %r0, 524287 + lfhat %r0, 0(%r1) + lfhat %r0, 0(%r15) + lfhat %r0, 524287(%r1,%r15) + lfhat %r0, 524287(%r15,%r1) + lfhat %r15, 0 + +#CHECK: lgat %r0, -524288 # encoding: [0xe3,0x00,0x00,0x00,0x80,0x85] +#CHECK: lgat %r0, -1 # encoding: [0xe3,0x00,0x0f,0xff,0xff,0x85] +#CHECK: lgat %r0, 0 # encoding: [0xe3,0x00,0x00,0x00,0x00,0x85] +#CHECK: lgat %r0, 1 # encoding: [0xe3,0x00,0x00,0x01,0x00,0x85] +#CHECK: lgat %r0, 524287 # encoding: [0xe3,0x00,0x0f,0xff,0x7f,0x85] +#CHECK: lgat %r0, 0(%r1) # encoding: [0xe3,0x00,0x10,0x00,0x00,0x85] +#CHECK: lgat %r0, 0(%r15) # encoding: [0xe3,0x00,0xf0,0x00,0x00,0x85] +#CHECK: lgat %r0, 524287(%r1,%r15) # encoding: [0xe3,0x01,0xff,0xff,0x7f,0x85] +#CHECK: lgat %r0, 524287(%r15,%r1) # encoding: [0xe3,0x0f,0x1f,0xff,0x7f,0x85] +#CHECK: lgat %r15, 0 # encoding: [0xe3,0xf0,0x00,0x00,0x00,0x85] + + lgat %r0, -524288 + lgat %r0, -1 + lgat %r0, 0 + lgat %r0, 1 + lgat %r0, 524287 + lgat %r0, 0(%r1) + lgat %r0, 0(%r15) + lgat %r0, 524287(%r1,%r15) + lgat %r0, 524287(%r15,%r1) + lgat %r15, 0 + +#CHECK: llgfat %r0, -524288 # encoding: [0xe3,0x00,0x00,0x00,0x80,0x9d] +#CHECK: llgfat %r0, -1 # encoding: [0xe3,0x00,0x0f,0xff,0xff,0x9d] +#CHECK: llgfat %r0, 0 # encoding: [0xe3,0x00,0x00,0x00,0x00,0x9d] +#CHECK: llgfat %r0, 1 # encoding: [0xe3,0x00,0x00,0x01,0x00,0x9d] +#CHECK: llgfat %r0, 524287 # encoding: [0xe3,0x00,0x0f,0xff,0x7f,0x9d] +#CHECK: llgfat %r0, 0(%r1) # encoding: [0xe3,0x00,0x10,0x00,0x00,0x9d] +#CHECK: llgfat %r0, 0(%r15) # encoding: [0xe3,0x00,0xf0,0x00,0x00,0x9d] +#CHECK: llgfat %r0, 524287(%r1,%r15) # encoding: [0xe3,0x01,0xff,0xff,0x7f,0x9d] +#CHECK: llgfat %r0, 524287(%r15,%r1) # encoding: [0xe3,0x0f,0x1f,0xff,0x7f,0x9d] +#CHECK: llgfat %r15, 0 # encoding: [0xe3,0xf0,0x00,0x00,0x00,0x9d] + + llgfat %r0, -524288 + llgfat %r0, -1 + llgfat %r0, 0 + llgfat %r0, 1 + llgfat %r0, 524287 + llgfat %r0, 0(%r1) + llgfat %r0, 0(%r15) + llgfat %r0, 524287(%r1,%r15) + llgfat %r0, 524287(%r15,%r1) + llgfat %r15, 0 + +#CHECK: llgtat %r0, -524288 # encoding: [0xe3,0x00,0x00,0x00,0x80,0x9c] +#CHECK: llgtat %r0, -1 # encoding: [0xe3,0x00,0x0f,0xff,0xff,0x9c] +#CHECK: llgtat %r0, 0 # encoding: [0xe3,0x00,0x00,0x00,0x00,0x9c] +#CHECK: llgtat %r0, 1 # encoding: [0xe3,0x00,0x00,0x01,0x00,0x9c] +#CHECK: llgtat %r0, 524287 # encoding: [0xe3,0x00,0x0f,0xff,0x7f,0x9c] +#CHECK: llgtat %r0, 0(%r1) # encoding: [0xe3,0x00,0x10,0x00,0x00,0x9c] +#CHECK: llgtat %r0, 0(%r15) # encoding: [0xe3,0x00,0xf0,0x00,0x00,0x9c] +#CHECK: llgtat %r0, 524287(%r1,%r15) # encoding: [0xe3,0x01,0xff,0xff,0x7f,0x9c] +#CHECK: llgtat %r0, 524287(%r15,%r1) # encoding: [0xe3,0x0f,0x1f,0xff,0x7f,0x9c] +#CHECK: llgtat %r15, 0 # encoding: [0xe3,0xf0,0x00,0x00,0x00,0x9c] + + llgtat %r0, -524288 + llgtat %r0, -1 + llgtat %r0, 0 + llgtat %r0, 1 + llgtat %r0, 524287 + llgtat %r0, 0(%r1) + llgtat %r0, 0(%r15) + llgtat %r0, 524287(%r1,%r15) + llgtat %r0, 524287(%r15,%r1) + llgtat %r15, 0 + #CHECK: etnd %r0 # encoding: [0xb2,0xec,0x00,0x00] #CHECK: etnd %r15 # encoding: [0xb2,0xec,0x00,0xf0] #CHECK: etnd %r7 # encoding: [0xb2,0xec,0x00,0x70]