summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlrich Weigand <ulrich.weigand@de.ibm.com>2016-11-28 13:59:22 +0000
committerUlrich Weigand <ulrich.weigand@de.ibm.com>2016-11-28 13:59:22 +0000
commit2d9e3d9d3bb8a6414fc9469f9525084a5d4b3195 (patch)
treee691934a84e13929775ee1de562f1fb743ab8cfd
parent758399131a90a15fac6a329d3f6b2f35ea006bc7 (diff)
downloadbcm5719-llvm-2d9e3d9d3bb8a6414fc9469f9525084a5d4b3195.tar.gz
bcm5719-llvm-2d9e3d9d3bb8a6414fc9469f9525084a5d4b3195.zip
[SystemZ] Support load-and-trap instructions
This adds support for the instructions provided with the load-and-trap facility. llvm-svn: 288030
-rw-r--r--llvm/lib/Target/SystemZ/SystemZElimCompare.cpp61
-rw-r--r--llvm/lib/Target/SystemZ/SystemZFeatures.td6
-rw-r--r--llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp19
-rw-r--r--llvm/lib/Target/SystemZ/SystemZInstrInfo.h4
-rw-r--r--llvm/lib/Target/SystemZ/SystemZInstrInfo.td13
-rw-r--r--llvm/lib/Target/SystemZ/SystemZScheduleZ13.td6
-rw-r--r--llvm/lib/Target/SystemZ/SystemZScheduleZEC12.td6
-rw-r--r--llvm/lib/Target/SystemZ/SystemZSubtarget.cpp4
-rw-r--r--llvm/lib/Target/SystemZ/SystemZSubtarget.h4
-rw-r--r--llvm/test/CodeGen/SystemZ/trap-03.ll157
-rw-r--r--llvm/test/CodeGen/SystemZ/trap-04.ll170
-rw-r--r--llvm/test/CodeGen/SystemZ/trap-05.ll92
-rw-r--r--llvm/test/MC/Disassembler/SystemZ/insns.txt150
-rw-r--r--llvm/test/MC/SystemZ/insn-bad-zEC12.s40
-rw-r--r--llvm/test/MC/SystemZ/insn-good-zEC12.s110
15 files changed, 835 insertions, 7 deletions
diff --git a/llvm/lib/Target/SystemZ/SystemZElimCompare.cpp b/llvm/lib/Target/SystemZ/SystemZElimCompare.cpp
index b292b554779..6e42e283c9f 100644
--- a/llvm/lib/Target/SystemZ/SystemZElimCompare.cpp
+++ b/llvm/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<MachineInstr *> &CCUsers);
+ bool convertToLoadAndTrap(MachineInstr &MI, MachineInstr &Compare,
+ SmallVectorImpl<MachineInstr *> &CCUsers);
bool convertToLoadAndTest(MachineInstr &MI);
bool adjustCCMasksForInstr(MachineInstr &MI, MachineInstr &Compare,
SmallVectorImpl<MachineInstr *> &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<MachineInstr *> &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/llvm/lib/Target/SystemZ/SystemZFeatures.td b/llvm/lib/Target/SystemZ/SystemZFeatures.td
index 70c51509309..0fb3c55ebe0 100644
--- a/llvm/lib/Target/SystemZ/SystemZFeatures.td
+++ b/llvm/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/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
index 7b835b04fd3..3565d5f2c49 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
+++ b/llvm/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/llvm/lib/Target/SystemZ/SystemZInstrInfo.h b/llvm/lib/Target/SystemZ/SystemZInstrInfo.h
index aadeb6b9f1d..794b193a501 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.h
+++ b/llvm/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/llvm/lib/Target/SystemZ/SystemZInstrInfo.td b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
index 87a70da6856..c180d405419 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
+++ b/llvm/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/llvm/lib/Target/SystemZ/SystemZScheduleZ13.td b/llvm/lib/Target/SystemZ/SystemZScheduleZ13.td
index c9007e59bcb..f712d2b0f9b 100644
--- a/llvm/lib/Target/SystemZ/SystemZScheduleZ13.td
+++ b/llvm/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/llvm/lib/Target/SystemZ/SystemZScheduleZEC12.td b/llvm/lib/Target/SystemZ/SystemZScheduleZEC12.td
index 73008749773..49353eb1d3d 100644
--- a/llvm/lib/Target/SystemZ/SystemZScheduleZEC12.td
+++ b/llvm/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/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp b/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp
index c74913219af..bf7277a6ef1 100644
--- a/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp
+++ b/llvm/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/llvm/lib/Target/SystemZ/SystemZSubtarget.h b/llvm/lib/Target/SystemZ/SystemZSubtarget.h
index 9218a7831d9..8475e2edaf2 100644
--- a/llvm/lib/Target/SystemZ/SystemZSubtarget.h
+++ b/llvm/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/llvm/test/CodeGen/SystemZ/trap-03.ll b/llvm/test/CodeGen/SystemZ/trap-03.ll
new file mode 100644
index 00000000000..d3cc882add7
--- /dev/null
+++ b/llvm/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/llvm/test/CodeGen/SystemZ/trap-04.ll b/llvm/test/CodeGen/SystemZ/trap-04.ll
new file mode 100644
index 00000000000..9e7897e6321
--- /dev/null
+++ b/llvm/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/llvm/test/CodeGen/SystemZ/trap-05.ll b/llvm/test/CodeGen/SystemZ/trap-05.ll
new file mode 100644
index 00000000000..7aabedbfadd
--- /dev/null
+++ b/llvm/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/llvm/test/MC/Disassembler/SystemZ/insns.txt b/llvm/test/MC/Disassembler/SystemZ/insns.txt
index 1c521a512b6..b19281ae854 100644
--- a/llvm/test/MC/Disassembler/SystemZ/insns.txt
+++ b/llvm/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/llvm/test/MC/SystemZ/insn-bad-zEC12.s b/llvm/test/MC/SystemZ/insn-bad-zEC12.s
index b86b4b86438..a88fe7ebe7a 100644
--- a/llvm/test/MC/SystemZ/insn-bad-zEC12.s
+++ b/llvm/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/llvm/test/MC/SystemZ/insn-good-zEC12.s b/llvm/test/MC/SystemZ/insn-good-zEC12.s
index b58ce702175..cb604f96d6b 100644
--- a/llvm/test/MC/SystemZ/insn-good-zEC12.s
+++ b/llvm/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]
OpenPOWER on IntegriCloud