diff options
| author | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2016-11-28 13:59:22 +0000 |
|---|---|---|
| committer | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2016-11-28 13:59:22 +0000 |
| commit | 2d9e3d9d3bb8a6414fc9469f9525084a5d4b3195 (patch) | |
| tree | e691934a84e13929775ee1de562f1fb743ab8cfd /llvm/lib | |
| parent | 758399131a90a15fac6a329d3f6b2f35ea006bc7 (diff) | |
| download | bcm5719-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
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZElimCompare.cpp | 61 | ||||
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZFeatures.td | 6 | ||||
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp | 19 | ||||
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZInstrInfo.h | 4 | ||||
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZInstrInfo.td | 13 | ||||
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZScheduleZ13.td | 6 | ||||
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZScheduleZEC12.td | 6 | ||||
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZSubtarget.cpp | 4 | ||||
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZSubtarget.h | 4 |
9 files changed, 116 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; } |

