diff options
author | Alexander Kornienko <alexfh@google.com> | 2013-03-14 10:51:38 +0000 |
---|---|---|
committer | Alexander Kornienko <alexfh@google.com> | 2013-03-14 10:51:38 +0000 |
commit | 647735c781c5b37061ee03d6e9e6c7dda92218e2 (patch) | |
tree | 5a5e56606d41060263048b5a5586b3d2380898ba /lib/Target/Hexagon | |
parent | 6aed25d93d1cfcde5809a73ffa7dc1b0d6396f66 (diff) | |
parent | f635ef401786c84df32090251a8cf45981ecca33 (diff) |
Updating branches/google/stable to r176857
git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/google/stable@177040 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/Hexagon')
39 files changed, 4346 insertions, 4062 deletions
diff --git a/lib/Target/Hexagon/CMakeLists.txt b/lib/Target/Hexagon/CMakeLists.txt index aee43ba517..b5b887e7c7 100644 --- a/lib/Target/Hexagon/CMakeLists.txt +++ b/lib/Target/Hexagon/CMakeLists.txt @@ -18,6 +18,7 @@ add_llvm_target(HexagonCodeGen HexagonExpandPredSpillCode.cpp HexagonFrameLowering.cpp HexagonHardwareLoops.cpp + HexagonFixupHwLoops.cpp HexagonMachineScheduler.cpp HexagonMCInstLower.cpp HexagonInstrInfo.cpp diff --git a/lib/Target/Hexagon/Hexagon.h b/lib/Target/Hexagon/Hexagon.h index 45f857bab8..dfbefc8642 100644 --- a/lib/Target/Hexagon/Hexagon.h +++ b/lib/Target/Hexagon/Hexagon.h @@ -21,14 +21,16 @@ namespace llvm { class FunctionPass; + class ModulePass; class TargetMachine; class MachineInstr; - class MCInst; + class HexagonMCInst; class HexagonAsmPrinter; class HexagonTargetMachine; class raw_ostream; - FunctionPass *createHexagonISelDag(HexagonTargetMachine &TM); + FunctionPass *createHexagonISelDag(HexagonTargetMachine &TM, + CodeGenOpt::Level OptLevel); FunctionPass *createHexagonDelaySlotFillerPass(TargetMachine &TM); FunctionPass *createHexagonFPMoverPass(TargetMachine &TM); FunctionPass *createHexagonRemoveExtendOps(HexagonTargetMachine &TM); @@ -53,7 +55,7 @@ namespace llvm { TargetAsmBackend *createHexagonAsmBackend(const Target &, const std::string &); */ - void HexagonLowerToMC(const MachineInstr *MI, MCInst &MCI, + void HexagonLowerToMC(const MachineInstr *MI, HexagonMCInst &MCI, HexagonAsmPrinter &AP); } // end namespace llvm; diff --git a/lib/Target/Hexagon/HexagonAsmPrinter.cpp b/lib/Target/Hexagon/HexagonAsmPrinter.cpp index cedb3a8303..88cd3fbace 100644 --- a/lib/Target/Hexagon/HexagonAsmPrinter.cpp +++ b/lib/Target/Hexagon/HexagonAsmPrinter.cpp @@ -14,12 +14,12 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "asm-printer" -#include "HexagonAsmPrinter.h" #include "Hexagon.h" -#include "HexagonMCInst.h" +#include "HexagonAsmPrinter.h" #include "HexagonMachineFunctionInfo.h" -#include "HexagonSubtarget.h" #include "HexagonTargetMachine.h" +#include "HexagonSubtarget.h" +#include "MCTargetDesc/HexagonMCInst.h" #include "InstPrinter/HexagonInstPrinter.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" @@ -31,9 +31,10 @@ #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/Constants.h" -#include "llvm/DataLayout.h" -#include "llvm/DerivedTypes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" @@ -41,7 +42,6 @@ #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/Module.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" @@ -220,8 +220,8 @@ void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) { assert((Size+IgnoreCount) == MI->getBundleSize() && "Corrupt Bundle!"); for (unsigned Index = 0; Index < Size; Index++) { HexagonMCInst MCI; - MCI.setStartPacket(Index == 0); - MCI.setEndPacket(Index == (Size-1)); + MCI.setPacketStart(Index == 0); + MCI.setPacketEnd(Index == (Size-1)); HexagonLowerToMC(BundleMIs[Index], MCI, *this); OutStreamer.EmitInstruction(MCI); @@ -230,8 +230,8 @@ void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) { else { HexagonMCInst MCI; if (MI->getOpcode() == Hexagon::ENDLOOP0) { - MCI.setStartPacket(true); - MCI.setEndPacket(true); + MCI.setPacketStart(true); + MCI.setPacketEnd(true); } HexagonLowerToMC(MI, MCI, *this); OutStreamer.EmitInstruction(MCI); diff --git a/lib/Target/Hexagon/HexagonAsmPrinter.h b/lib/Target/Hexagon/HexagonAsmPrinter.h index bc2af63612..bc2af63612 100755..100644 --- a/lib/Target/Hexagon/HexagonAsmPrinter.h +++ b/lib/Target/Hexagon/HexagonAsmPrinter.h diff --git a/lib/Target/Hexagon/HexagonCallingConvLower.cpp b/lib/Target/Hexagon/HexagonCallingConvLower.cpp index 1b4b0206f7..2c93d04f98 100644 --- a/lib/Target/Hexagon/HexagonCallingConvLower.cpp +++ b/lib/Target/Hexagon/HexagonCallingConvLower.cpp @@ -15,7 +15,7 @@ #include "HexagonCallingConvLower.h" #include "Hexagon.h" -#include "llvm/DataLayout.h" +#include "llvm/IR/DataLayout.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" diff --git a/lib/Target/Hexagon/HexagonFixupHwLoops.cpp b/lib/Target/Hexagon/HexagonFixupHwLoops.cpp new file mode 100644 index 0000000000..240cc95666 --- /dev/null +++ b/lib/Target/Hexagon/HexagonFixupHwLoops.cpp @@ -0,0 +1,183 @@ +//===---- HexagonFixupHwLoops.cpp - Fixup HW loops too far from LOOPn. ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// The loop start address in the LOOPn instruction is encoded as a distance +// from the LOOPn instruction itself. If the start address is too far from +// the LOOPn instruction, the loop needs to be set up manually, i.e. via +// direct transfers to SAn and LCn. +// This pass will identify and convert such LOOPn instructions to a proper +// form. +//===----------------------------------------------------------------------===// + + +#include "llvm/ADT/DenseMap.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/PassSupport.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "Hexagon.h" +#include "HexagonTargetMachine.h" + +using namespace llvm; + +namespace llvm { + void initializeHexagonFixupHwLoopsPass(PassRegistry&); +} + +namespace { + struct HexagonFixupHwLoops : public MachineFunctionPass { + public: + static char ID; + + HexagonFixupHwLoops() : MachineFunctionPass(ID) { + initializeHexagonFixupHwLoopsPass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnMachineFunction(MachineFunction &MF); + + const char *getPassName() const { return "Hexagon Hardware Loop Fixup"; } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + private: + /// \brief Maximum distance between the loop instr and the basic block. + /// Just an estimate. + static const unsigned MAX_LOOP_DISTANCE = 200; + + /// \brief Check the offset between each loop instruction and + /// the loop basic block to determine if we can use the LOOP instruction + /// or if we need to set the LC/SA registers explicitly. + bool fixupLoopInstrs(MachineFunction &MF); + + /// \brief Add the instruction to set the LC and SA registers explicitly. + void convertLoopInstr(MachineFunction &MF, + MachineBasicBlock::iterator &MII, + RegScavenger &RS); + + }; + + char HexagonFixupHwLoops::ID = 0; +} + +INITIALIZE_PASS(HexagonFixupHwLoops, "hwloopsfixup", + "Hexagon Hardware Loops Fixup", false, false) + +FunctionPass *llvm::createHexagonFixupHwLoops() { + return new HexagonFixupHwLoops(); +} + + +/// \brief Returns true if the instruction is a hardware loop instruction. +static bool isHardwareLoop(const MachineInstr *MI) { + return MI->getOpcode() == Hexagon::LOOP0_r || + MI->getOpcode() == Hexagon::LOOP0_i; +} + + +bool HexagonFixupHwLoops::runOnMachineFunction(MachineFunction &MF) { + bool Changed = fixupLoopInstrs(MF); + return Changed; +} + + +/// \brief For Hexagon, if the loop label is to far from the +/// loop instruction then we need to set the LC0 and SA0 registers +/// explicitly instead of using LOOP(start,count). This function +/// checks the distance, and generates register assignments if needed. +/// +/// This function makes two passes over the basic blocks. The first +/// pass computes the offset of the basic block from the start. +/// The second pass checks all the loop instructions. +bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) { + + // Offset of the current instruction from the start. + unsigned InstOffset = 0; + // Map for each basic block to it's first instruction. + DenseMap<MachineBasicBlock*, unsigned> BlockToInstOffset; + + // First pass - compute the offset of each basic block. + for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end(); + MBB != MBBe; ++MBB) { + BlockToInstOffset[MBB] = InstOffset; + InstOffset += (MBB->size() * 4); + } + + // Second pass - check each loop instruction to see if it needs to + // be converted. + InstOffset = 0; + bool Changed = false; + RegScavenger RS; + + // Loop over all the basic blocks. + for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end(); + MBB != MBBe; ++MBB) { + InstOffset = BlockToInstOffset[MBB]; + RS.enterBasicBlock(MBB); + + // Loop over all the instructions. + MachineBasicBlock::iterator MIE = MBB->end(); + MachineBasicBlock::iterator MII = MBB->begin(); + while (MII != MIE) { + if (isHardwareLoop(MII)) { + RS.forward(MII); + assert(MII->getOperand(0).isMBB() && + "Expect a basic block as loop operand"); + int Sub = InstOffset - BlockToInstOffset[MII->getOperand(0).getMBB()]; + unsigned Dist = Sub > 0 ? Sub : -Sub; + if (Dist > MAX_LOOP_DISTANCE) { + // Convert to explicity setting LC0 and SA0. + convertLoopInstr(MF, MII, RS); + MII = MBB->erase(MII); + Changed = true; + } else { + ++MII; + } + } else { + ++MII; + } + InstOffset += 4; + } + } + + return Changed; +} + + +/// \brief convert a loop instruction to a sequence of instructions that +/// set the LC0 and SA0 register explicitly. +void HexagonFixupHwLoops::convertLoopInstr(MachineFunction &MF, + MachineBasicBlock::iterator &MII, + RegScavenger &RS) { + const TargetInstrInfo *TII = MF.getTarget().getInstrInfo(); + MachineBasicBlock *MBB = MII->getParent(); + DebugLoc DL = MII->getDebugLoc(); + unsigned Scratch = RS.scavengeRegister(&Hexagon::IntRegsRegClass, MII, 0); + + // First, set the LC0 with the trip count. + if (MII->getOperand(1).isReg()) { + // Trip count is a register + BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0) + .addReg(MII->getOperand(1).getReg()); + } else { + // Trip count is an immediate. + BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFRI), Scratch) + .addImm(MII->getOperand(1).getImm()); + BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0) + .addReg(Scratch); + } + // Then, set the SA0 with the loop start address. + BuildMI(*MBB, MII, DL, TII->get(Hexagon::CONST32_Label), Scratch) + .addMBB(MII->getOperand(0).getMBB()); + BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::SA0) + .addReg(Scratch); +} diff --git a/lib/Target/Hexagon/HexagonFrameLowering.cpp b/lib/Target/Hexagon/HexagonFrameLowering.cpp index 29bfc6b466..d6a9329cd4 100644 --- a/lib/Target/Hexagon/HexagonFrameLowering.cpp +++ b/lib/Target/Hexagon/HexagonFrameLowering.cpp @@ -25,14 +25,14 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" -#include "llvm/Function.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Type.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MachineLocation.h" #include "llvm/Support/CommandLine.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" -#include "llvm/Type.h" using namespace llvm; @@ -327,6 +327,21 @@ bool HexagonFrameLowering::restoreCalleeSavedRegisters( return true; } +void HexagonFrameLowering:: +eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + MachineInstr &MI = *I; + + if (MI.getOpcode() == Hexagon::ADJCALLSTACKDOWN) { + // Hexagon_TODO: add code + } else if (MI.getOpcode() == Hexagon::ADJCALLSTACKUP) { + // Hexagon_TODO: add code + } else { + llvm_unreachable("Cannot handle this call frame pseudo instruction"); + } + MBB.erase(I); +} + int HexagonFrameLowering::getFrameIndexOffset(const MachineFunction &MF, int FI) const { return MF.getFrameInfo()->getObjectOffset(FI); diff --git a/lib/Target/Hexagon/HexagonFrameLowering.h b/lib/Target/Hexagon/HexagonFrameLowering.h index ad87f11e24..a62c76aaf6 100644 --- a/lib/Target/Hexagon/HexagonFrameLowering.h +++ b/lib/Target/Hexagon/HexagonFrameLowering.h @@ -35,6 +35,11 @@ public: MachineBasicBlock::iterator MI, const std::vector<CalleeSavedInfo> &CSI, const TargetRegisterInfo *TRI) const; + + void eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const; + virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, diff --git a/lib/Target/Hexagon/HexagonHardwareLoops.cpp b/lib/Target/Hexagon/HexagonHardwareLoops.cpp index d875fea575..62aed1353c 100644 --- a/lib/Target/Hexagon/HexagonHardwareLoops.cpp +++ b/lib/Target/Hexagon/HexagonHardwareLoops.cpp @@ -27,9 +27,7 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "hwloops" -#include "Hexagon.h" -#include "HexagonTargetMachine.h" -#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFunction.h" @@ -37,79 +35,194 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/CodeGen/RegisterScavenging.h" -#include "llvm/Constants.h" #include "llvm/PassSupport.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetInstrInfo.h" +#include "Hexagon.h" +#include "HexagonTargetMachine.h" + #include <algorithm> +#include <vector> using namespace llvm; +#ifndef NDEBUG +static cl::opt<int> HWLoopLimit("max-hwloop", cl::Hidden, cl::init(-1)); +#endif + STATISTIC(NumHWLoops, "Number of loops converted to hardware loops"); +namespace llvm { + void initializeHexagonHardwareLoopsPass(PassRegistry&); +} + namespace { class CountValue; struct HexagonHardwareLoops : public MachineFunctionPass { - MachineLoopInfo *MLI; - MachineRegisterInfo *MRI; - const TargetInstrInfo *TII; + MachineLoopInfo *MLI; + MachineRegisterInfo *MRI; + MachineDominatorTree *MDT; + const HexagonTargetMachine *TM; + const HexagonInstrInfo *TII; + const HexagonRegisterInfo *TRI; +#ifndef NDEBUG + static int Counter; +#endif public: - static char ID; // Pass identification, replacement for typeid + static char ID; - HexagonHardwareLoops() : MachineFunctionPass(ID) {} + HexagonHardwareLoops() : MachineFunctionPass(ID) { + initializeHexagonHardwareLoopsPass(*PassRegistry::getPassRegistry()); + } virtual bool runOnMachineFunction(MachineFunction &MF); const char *getPassName() const { return "Hexagon Hardware Loops"; } virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesCFG(); AU.addRequired<MachineDominatorTree>(); - AU.addPreserved<MachineDominatorTree>(); AU.addRequired<MachineLoopInfo>(); - AU.addPreserved<MachineLoopInfo>(); MachineFunctionPass::getAnalysisUsage(AU); } private: - /// getCanonicalInductionVariable - Check to see if the loop has a canonical - /// induction variable. - /// Should be defined in MachineLoop. Based upon version in class Loop. - const MachineInstr *getCanonicalInductionVariable(MachineLoop *L) const; - - /// getTripCount - Return a loop-invariant LLVM register indicating the - /// number of times the loop will be executed. If the trip-count cannot - /// be determined, this return null. - CountValue *getTripCount(MachineLoop *L) const; - - /// isInductionOperation - Return true if the instruction matches the - /// pattern for an opertion that defines an induction variable. - bool isInductionOperation(const MachineInstr *MI, unsigned IVReg) const; + /// Kinds of comparisons in the compare instructions. + struct Comparison { + enum Kind { + EQ = 0x01, + NE = 0x02, + L = 0x04, // Less-than property. + G = 0x08, // Greater-than property. + U = 0x40, // Unsigned property. + LTs = L, + LEs = L | EQ, + GTs = G, + GEs = G | EQ, + LTu = L | U, + LEu = L | EQ | U, + GTu = G | U, + GEu = G | EQ | U + }; + + static Kind getSwappedComparison(Kind Cmp) { + assert ((!((Cmp & L) && (Cmp & G))) && "Malformed comparison operator"); + if ((Cmp & L) || (Cmp & G)) + return (Kind)(Cmp ^ (L|G)); + return Cmp; + } + }; - /// isInvalidOperation - Return true if the instruction is not valid within - /// a hardware loop. + /// \brief Find the register that contains the loop controlling + /// induction variable. + /// If successful, it will return true and set the \p Reg, \p IVBump + /// and \p IVOp arguments. Otherwise it will return false. + /// The returned induction register is the register R that follows the + /// following induction pattern: + /// loop: + /// R = phi ..., [ R.next, LatchBlock ] + /// R.next = R + #bump + /// if (R.next < #N) goto loop + /// IVBump is the immediate value added to R, and IVOp is the instruction + /// "R.next = R + #bump". + bool findInductionRegister(MachineLoop *L, unsigned &Reg, + int64_t &IVBump, MachineInstr *&IVOp) const; + + /// \brief Analyze the statements in a loop to determine if the loop + /// has a computable trip count and, if so, return a value that represents + /// the trip count expression. + CountValue *getLoopTripCount(MachineLoop *L, + SmallVector<MachineInstr*, 2> &OldInsts); + + /// \brief Return the expression that represents the number of times + /// a loop iterates. The function takes the operands that represent the + /// loop start value, loop end value, and induction value. Based upon + /// these operands, the function attempts to compute the trip count. + /// If the trip count is not directly available (as an immediate value, + /// or a register), the function will attempt to insert computation of it + /// to the loop's preheader. + CountValue *computeCount(MachineLoop *Loop, + const MachineOperand *Start, + const MachineOperand *End, + unsigned IVReg, + int64_t IVBump, + Comparison::Kind Cmp) const; + + /// \brief Return true if the instruction is not valid within a hardware + /// loop. bool isInvalidLoopOperation(const MachineInstr *MI) const; - /// containsInavlidInstruction - Return true if the loop contains an - /// instruction that inhibits using the hardware loop. + /// \brief Return true if the loop contains an instruction that inhibits + /// using the hardware loop. bool containsInvalidInstruction(MachineLoop *L) const; - /// converToHardwareLoop - Given a loop, check if we can convert it to a - /// hardware loop. If so, then perform the conversion and return true. + /// \brief Given a loop, check if we can convert it to a hardware loop. + /// If so, then perform the conversion and return true. bool convertToHardwareLoop(MachineLoop *L); + /// \brief Return true if the instruction is now dead. + bool isDead(const MachineInstr *MI, + SmallVector<MachineInstr*, 1> &DeadPhis) const; + + /// \brief Remove the instruction if it is now dead. + void removeIfDead(MachineInstr *MI); + + /// \brief Make sure that the "bump" instruction executes before the + /// compare. We need that for the IV fixup, so that the compare + /// instruction would not use a bumped value that has not yet been + /// defined. If the instructions are out of order, try to reorder them. + bool orderBumpCompare(MachineInstr *BumpI, MachineInstr *CmpI); + + /// \brief Get the instruction that loads an immediate value into \p R, + /// or 0 if such an instruction does not exist. + MachineInstr *defWithImmediate(unsigned R); + + /// \brief Get the immediate value referenced to by \p MO, either for + /// immediate operands, or for register operands, where the register + /// was defined with an immediate value. + int64_t getImmediate(MachineOperand &MO); + + /// \brief Reset the given machine operand to now refer to a new immediate + /// value. Assumes that the operand was already referencing an immediate + /// value, either directly, or via a register. + void setImmediate(MachineOperand &MO, int64_t Val); + + /// \brief Fix the data flow of the induction varible. + /// The desired flow is: phi ---> bump -+-> comparison-in-latch. + /// | + /// +-> back to phi + /// where "bump" is the increment of the induction variable: + /// iv = iv + #const. + /// Due to some prior code transformations, the actual flow may look + /// like this: + /// phi -+-> bump ---> back to phi + /// | + /// +-> comparison-in-latch (against upper_bound-bump), + /// i.e. the comparison that controls the loop execution may be using + /// the value of the induction variable from before the increment. + /// + /// Return true if the loop's flow is the desired one (i.e. it's + /// either been fixed, or no fixing was necessary). + /// Otherwise, return false. This can happen if the induction variable + /// couldn't be identified, or if the value in the latch's comparison + /// cannot be adjusted to reflect the post-bump value. + bool fixupInductionVariable(MachineLoop *L); + + /// \brief Given a loop, if it does not have a preheader, create one. + /// Return the block that is the preheader. + MachineBasicBlock *createPreheaderForLoop(MachineLoop *L); }; char HexagonHardwareLoops::ID = 0; +#ifndef NDEBUG + int HexagonHardwareLoops::Counter = 0; +#endif - - // CountValue class - Abstraction for a trip count of a loop. A - // smaller vesrsion of the MachineOperand class without the concerns - // of changing the operand representation. + /// \brief Abstraction for a trip count of a loop. A smaller vesrsion + /// of the MachineOperand class without the concerns of changing the + /// operand representation. class CountValue { public: enum CountValueType { @@ -119,101 +232,62 @@ namespace { private: CountValueType Kind; union Values { - unsigned RegNum; - int64_t ImmVal; - Values(unsigned r) : RegNum(r) {} - Values(int64_t i) : ImmVal(i) {} + struct { + unsigned Reg; + unsigned Sub; + } R; + unsigned ImmVal; } Contents; - bool isNegative; public: - CountValue(unsigned r, bool neg) : Kind(CV_Register), Contents(r), - isNegative(neg) {} - explicit CountValue(int64_t i) : Kind(CV_Immediate), Contents(i), - isNegative(i < 0) {} - CountValueType getType() const { return Kind; } + explicit CountValue(CountValueType t, unsigned v, unsigned u = 0) { + Kind = t; + if (Kind == CV_Register) { + Contents.R.Reg = v; + Contents.R.Sub = u; + } else { + Contents.ImmVal = v; + } + } bool isReg() const { return Kind == CV_Register; } bool isImm() const { return Kind == CV_Immediate; } - bool isNeg() const { return isNegative; } unsigned getReg() const { assert(isReg() && "Wrong CountValue accessor"); - return Contents.RegNum; + return Contents.R.Reg; } - void setReg(unsigned Val) { - Contents.RegNum = Val; + unsigned getSubReg() const { + assert(isReg() && "Wrong CountValue accessor"); + return Contents.R.Sub; } - int64_t getImm() const { + unsigned getImm() const { assert(isImm() && "Wrong CountValue accessor"); - if (isNegative) { - return -Contents.ImmVal; - } return Contents.ImmVal; } - void setImm(int64_t Val) { - Contents.ImmVal = Val; - } void print(raw_ostream &OS, const TargetMachine *TM = 0) const { - if (isReg()) { OS << PrintReg(getReg()); } - if (isImm()) { OS << getImm(); } - } - }; - - struct HexagonFixupHwLoops : public MachineFunctionPass { - public: - static char ID; // Pass identification, replacement for typeid. - - HexagonFixupHwLoops() : MachineFunctionPass(ID) {} - - virtual bool runOnMachineFunction(MachineFunction &MF); - - const char *getPassName() const { return "Hexagon Hardware Loop Fixup"; } - - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesCFG(); - MachineFunctionPass::getAnalysisUsage(AU); + const TargetRegisterInfo *TRI = TM ? TM->getRegisterInfo() : 0; + if (isReg()) { OS << PrintReg(Contents.R.Reg, TRI, Contents.R.Sub); } + if (isImm()) { OS << Contents.ImmVal; } } - - private: - /// Maximum distance between the loop instr and the basic block. - /// Just an estimate. - static const unsigned MAX_LOOP_DISTANCE = 200; - - /// fixupLoopInstrs - Check the offset between each loop instruction and - /// the loop basic block to determine if we can use the LOOP instruction - /// or if we need to set the LC/SA registers explicitly. - bool fixupLoopInstrs(MachineFunction &MF); - - /// convertLoopInstr - Add the instruction to set the LC and SA registers - /// explicitly. - void convertLoopInstr(MachineFunction &MF, - MachineBasicBlock::iterator &MII, - RegScavenger &RS); - }; +} // end anonymous namespace - char HexagonFixupHwLoops::ID = 0; -} // end anonymous namespace +INITIALIZE_PASS_BEGIN(HexagonHardwareLoops, "hwloops", + "Hexagon Hardware Loops", false, false) +INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) +INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) +INITIALIZE_PASS_END(HexagonHardwareLoops, "hwloops", + "Hexagon Hardware Loops", false, false) -/// isHardwareLoop - Returns true if the instruction is a hardware loop -/// instruction. +/// \brief Returns true if the instruction is a hardware loop instruction. static bool isHardwareLoop(const MachineInstr *MI) { return MI->getOpcode() == Hexagon::LOOP0_r || MI->getOpcode() == Hexagon::LOOP0_i; } -/// isCompareEquals - Returns true if the instruction is a compare equals -/// instruction with an immediate operand. -static bool isCompareEqualsImm(const MachineInstr *MI) { - return MI->getOpcode() == Hexagon::CMPEQri; -} - - -/// createHexagonHardwareLoops - Factory for creating -/// the hardware loop phase. FunctionPass *llvm::createHexagonHardwareLoops() { return new HexagonHardwareLoops(); } @@ -224,45 +298,149 @@ bool HexagonHardwareLoops::runOnMachineFunction(MachineFunction &MF) { bool Changed = false; - // get the loop information MLI = &getAnalysis<MachineLoopInfo>(); - // get the register information MRI = &MF.getRegInfo(); - // the target specific instructio info. - TII = MF.getTarget().getInstrInfo(); + MDT = &getAnalysis<MachineDominatorTree>(); + TM = static_cast<const HexagonTargetMachine*>(&MF.getTarget()); + TII = static_cast<const HexagonInstrInfo*>(TM->getInstrInfo()); + TRI = static_cast<const HexagonRegisterInfo*>(TM->getRegisterInfo()); for (MachineLoopInfo::iterator I = MLI->begin(), E = MLI->end(); I != E; ++I) { MachineLoop *L = *I; - if (!L->getParentLoop()) { + if (!L->getParentLoop()) Changed |= convertToHardwareLoop(L); - } } return Changed; } -/// getCanonicalInductionVariable - Check to see if the loop has a canonical -/// induction variable. We check for a simple recurrence pattern - an -/// integer recurrence that decrements by one each time through the loop and -/// ends at zero. If so, return the phi node that corresponds to it. -/// -/// Based upon the similar code in LoopInfo except this code is specific to -/// the machine. -/// This method assumes that the IndVarSimplify pass has been run by 'opt'. + +bool HexagonHardwareLoops::findInductionRegister(MachineLoop *L, + unsigned &Reg, + int64_t &IVBump, + MachineInstr *&IVOp + ) const { + MachineBasicBlock *Header = L->getHeader(); + MachineBasicBlock *Preheader = L->getLoopPreheader(); + MachineBasicBlock *Latch = L->getLoopLatch(); + if (!Header || !Preheader || !Latch) + return false; + + // This pair represents an induction register together with an immediate + // value that will be added to it in each loop iteration. + typedef std::pair<unsigned,int64_t> RegisterBump; + + // Mapping: R.next -> (R, bump), where R, R.next and bump are derived + // from an induction operation + // R.next = R + bump + // where bump is an immediate value. + typedef std::map<unsigned,RegisterBump> InductionMap; + + InductionMap IndMap; + + typedef MachineBasicBlock::instr_iterator instr_iterator; + for (instr_iterator I = Header->instr_begin(), E = Header->instr_end(); + I != E && I->isPHI(); ++I) { + MachineInstr *Phi = &*I; + + // Have a PHI instruction. Get the operand that corresponds to the + // latch block, and see if is a result of an addition of form "reg+imm", + // where the "reg" is defined by the PHI node we are looking at. + for (unsigned i = 1, n = Phi->getNumOperands(); i < n; i += 2) { + if (Phi->getOperand(i+1).getMBB() != Latch) + continue; + + unsigned PhiOpReg = Phi->getOperand(i).getReg(); + MachineInstr *DI = MRI->getVRegDef(PhiOpReg); + unsigned UpdOpc = DI->getOpcode(); + bool isAdd = (UpdOpc == Hexagon::ADD_ri); + + if (isAdd) { + // If the register operand to the add is the PHI we're + // looking at, this meets the induction pattern. + unsigned IndReg = DI->getOperand(1).getReg(); + if (MRI->getVRegDef(IndReg) == Phi) { + unsigned UpdReg = DI->getOperand(0).getReg(); + int64_t V = DI->getOperand(2).getImm(); + IndMap.insert(std::make_pair(UpdReg, std::make_pair(IndReg, V))); + } + } + } // for (i) + } // for (instr) + + SmallVector<MachineOperand,2> Cond; + MachineBasicBlock *TB = 0, *FB = 0; + bool NotAnalyzed = TII->AnalyzeBranch(*Latch, TB, FB, Cond, false); + if (NotAnalyzed) + return false; + + unsigned CSz = Cond.size(); + assert (CSz == 1 || CSz == 2); + unsigned PredR = Cond[CSz-1].getReg(); + + MachineInstr *PredI = MRI->getVRegDef(PredR); + if (!PredI->isCompare()) + return false; + + unsigned CmpReg1 = 0, CmpReg2 = 0; + int CmpImm = 0, CmpMask = 0; + bool CmpAnalyzed = TII->analyzeCompare(PredI, CmpReg1, CmpReg2, + CmpMask, CmpImm); + // Fail if the compare was not analyzed, or it's not comparing a register + // with an immediate value. Not checking the mask here, since we handle + // the individual compare opcodes (including CMPb) later on. + if (!CmpAnalyzed) + return false; + + // Exactly one of the input registers to the comparison should be among + // the induction registers. + InductionMap::iterator IndMapEnd = IndMap.end(); + InductionMap::iterator F = IndMapEnd; + if (CmpReg1 != 0) { + InductionMap::iterator F1 = IndMap.find(CmpReg1); + if (F1 != IndMapEnd) + F = F1; + } + if (CmpReg2 != 0) { + InductionMap::iterator F2 = IndMap.find(CmpReg2); + if (F2 != IndMapEnd) { + if (F != IndMapEnd) + return false; + F = F2; + } + } + if (F == IndMapEnd) + return false; + + Reg = F->second.first; + IVBump = F->second.second; + IVOp = MRI->getVRegDef(F->first); + return true; +} + + +/// \brief Analyze the statements in a loop to determine if the loop has +/// a computable trip count and, if so, return a value that represents +/// the trip count expression. /// -const MachineInstr -*HexagonHardwareLoops::getCanonicalInductionVariable(MachineLoop *L) const { +/// This function iterates over the phi nodes in the loop to check for +/// induction variable patterns that are used in the calculation for +/// the number of time the loop is executed. +CountValue *HexagonHardwareLoops::getLoopTripCount(MachineLoop *L, + SmallVector<MachineInstr*, 2> &OldInsts) { MachineBasicBlock *TopMBB = L->getTopBlock(); MachineBasicBlock::pred_iterator PI = TopMBB->pred_begin(); assert(PI != TopMBB->pred_end() && "Loop must have more than one incoming edge!"); MachineBasicBlock *Backedge = *PI++; - if (PI == TopMBB->pred_end()) return 0; // dead loop + if (PI == TopMBB->pred_end()) // dead loop? + return 0; MachineBasicBlock *Incoming = *PI++; - if (PI != TopMBB->pred_end()) return 0; // multiple backedges? + if (PI != TopMBB->pred_end()) // multiple backedges? + return 0; - // make sure there is one incoming and one backedge and determine which + // Make sure there is one incoming and one backedge and determine which // is which. if (L->contains(Incoming)) { if (L->contains(Backedge)) @@ -271,139 +449,433 @@ const MachineInstr } else if (!L->contains(Backedge)) return 0; - // Loop over all of the PHI nodes, looking for a canonical induction variable: - // - The PHI node is "reg1 = PHI reg2, BB1, reg3, BB2". - // - The recurrence comes from the backedge. - // - the definition is an induction operatio.n - for (MachineBasicBlock::iterator I = TopMBB->begin(), E = TopMBB->end(); - I != E && I->isPHI(); ++I) { - const MachineInstr *MPhi = &*I; - unsigned DefReg = MPhi->getOperand(0).getReg(); - for (unsigned i = 1; i != MPhi->getNumOperands(); i += 2) { - // Check each operand for the value from the backedge. - MachineBasicBlock *MBB = MPhi->getOperand(i+1).getMBB(); - if (L->contains(MBB)) { // operands comes from the backedge - // Check if the definition is an induction operation. - const MachineInstr *DI = MRI->getVRegDef(MPhi->getOperand(i).getReg()); - if (isInductionOperation(DI, DefReg)) { - return MPhi; - } - } + // Look for the cmp instruction to determine if we can get a useful trip + // count. The trip count can be either a register or an immediate. The + // location of the value depends upon the type (reg or imm). + MachineBasicBlock *Latch = L->getLoopLatch(); + if (!Latch) + return 0; + + unsigned IVReg = 0; + int64_t IVBump = 0; + MachineInstr *IVOp; + bool FoundIV = findInductionRegister(L, IVReg, IVBump, IVOp); + if (!FoundIV) + return 0; + + MachineBasicBlock *Preheader = L->getLoopPreheader(); + + MachineOperand *InitialValue = 0; + MachineInstr *IV_Phi = MRI->getVRegDef(IVReg); + for (unsigned i = 1, n = IV_Phi->getNumOperands(); i < n; i += 2) { + MachineBasicBlock *MBB = IV_Phi->getOperand(i+1).getMBB(); + if (MBB == Preheader) + InitialValue = &IV_Phi->getOperand(i); + else if (MBB == Latch) + IVReg = IV_Phi->getOperand(i).getReg(); // Want IV reg after bump. + } + if (!InitialValue) + return 0; + + SmallVector<MachineOperand,2> Cond; + MachineBasicBlock *TB = 0, *FB = 0; + bool NotAnalyzed = TII->AnalyzeBranch(*Latch, TB, FB, Cond, false); + if (NotAnalyzed) + return 0; + + MachineBasicBlock *Header = L->getHeader(); + // TB must be non-null. If FB is also non-null, one of them must be + // the header. Otherwise, branch to TB could be exiting the loop, and + // the fall through can go to the header. + assert (TB && "Latch block without a branch?"); + assert ((!FB || TB == Header || FB == Header) && "Branches not to header?"); + if (!TB || (FB && TB != Header && FB != Header)) + return 0; + + // Branches of form "if (!P) ..." cause HexagonInstrInfo::AnalyzeBranch + // to put imm(0), followed by P in the vector Cond. + // If TB is not the header, it means that the "not-taken" path must lead + // to the header. + bool Negated = (Cond.size() > 1) ^ (TB != Header); + unsigned PredReg = Cond[Cond.size()-1].getReg(); + MachineInstr *CondI = MRI->getVRegDef(PredReg); + unsigned CondOpc = CondI->getOpcode(); + + unsigned CmpReg1 = 0, CmpReg2 = 0; + int Mask = 0, ImmValue = 0; + bool AnalyzedCmp = TII->analyzeCompare(CondI, CmpReg1, CmpReg2, + Mask, ImmValue); + if (!AnalyzedCmp) + return 0; + + // The comparison operator type determines how we compute the loop + // trip count. + OldInsts.push_back(CondI); + OldInsts.push_back(IVOp); + + // Sadly, the following code gets information based on the position + // of the operands in the compare instruction. This has to be done + // this way, because the comparisons check for a specific relationship + // between the operands (e.g. is-less-than), rather than to find out + // what relationship the operands are in (as on PPC). + Comparison::Kind Cmp; + bool isSwapped = false; + const MachineOperand &Op1 = CondI->getOperand(1); + const MachineOperand &Op2 = CondI->getOperand(2); + const MachineOperand *EndValue = 0; + + if (Op1.isReg()) { + if (Op2.isImm() || Op1.getReg() == IVReg) + EndValue = &Op2; + else { + EndValue = &Op1; + isSwapped = true; } } - return 0; -} -/// getTripCount - Return a loop-invariant LLVM value indicating the -/// number of times the loop will be executed. The trip count can -/// be either a register or a constant value. If the trip-count -/// cannot be determined, this returns null. -/// -/// We find the trip count from the phi instruction that defines the -/// induction variable. We follow the links to the CMP instruction -/// to get the trip count. -/// -/// Based upon getTripCount in LoopInfo. -/// -CountValue *HexagonHardwareLoops::getTripCount(MachineLoop *L) const { - // Check that the loop has a induction variable. - const MachineInstr *IV_Inst = getCanonicalInductionVariable(L); - if (IV_Inst == 0) return 0; - - // Canonical loops will end with a 'cmpeq_ri IV, Imm', - // if Imm is 0, get the count from the PHI opnd - // if Imm is -M, than M is the count - // Otherwise, Imm is the count - const MachineOperand *IV_Opnd; - const MachineOperand *InitialValue; - if (!L->contains(IV_Inst->getOperand(2).getMBB())) { - InitialValue = &IV_Inst->getOperand(1); - IV_Opnd = &IV_Inst->getOperand(3); - } else { - InitialValue = &IV_Inst->getOperand(3); - IV_Opnd = &IV_Inst->getOperand(1); - } - - // Look for the cmp instruction to determine if we - // can get a useful trip count. The trip count can - // be either a register or an immediate. The location - // of the value depends upon the type (reg or imm). - for (MachineRegisterInfo::reg_iterator - RI = MRI->reg_begin(IV_Opnd->getReg()), RE = MRI->reg_end(); - RI != RE; ++RI) { - IV_Opnd = &RI.getOperand(); - const MachineInstr *MI = IV_Opnd->getParent(); - if (L->contains(MI) && isCompareEqualsImm(MI)) { - const MachineOperand &MO = MI->getOperand(2); - assert(MO.isImm() && "IV Cmp Operand should be 0"); - int64_t ImmVal = MO.getImm(); - - const MachineInstr *IV_DefInstr = MRI->getVRegDef(IV_Opnd->getReg()); - assert(L->contains(IV_DefInstr->getParent()) && - "IV definition should occurs in loop"); - int64_t iv_value = IV_DefInstr->getOperand(2).getImm(); - - if (ImmVal == 0) { - // Make sure the induction variable changes by one on each iteration. - if (iv_value != 1 && iv_value != -1) { + if (!EndValue) + return 0; + + switch (CondOpc) { + case Hexagon::CMPEQri: + case Hexagon::CMPEQrr: + Cmp = !Negated ? Comparison::EQ : Comparison::NE; + break; + case Hexagon::CMPLTrr: + Cmp = !Negated ? Comparison::LTs : Comparison::GEs; + break; + case Hexagon::CMPLTUrr: + Cmp = !Negated ? Comparison::LTu : Comparison::GEu; + break; + case Hexagon::CMPGTUri: + case Hexagon::CMPGTUrr: + Cmp = !Negated ? Comparison::GTu : Comparison::LEu; + break; + case Hexagon::CMPGTri: + case Hexagon::CMPGTrr: + Cmp = !Negated ? Comparison::GTs : Comparison::LEs; + break; + // Very limited support for byte/halfword compares. + case Hexagon::CMPbEQri_V4: + case Hexagon::CMPhEQri_V4: { + if (IVBump != 1) + return 0; + + int64_t InitV, EndV; + // Since the comparisons are "ri", the EndValue should be an + // immediate. Check it just in case. + assert(EndValue->isImm() && "Unrecognized latch comparison"); + EndV = EndValue->getImm(); + // Allow InitialValue to be a register defined with an immediate. + if (InitialValue->isReg()) { + if (!defWithImmediate(InitialValue->getReg())) return 0; - } - return new CountValue(InitialValue->getReg(), iv_value > 0); + InitV = getImmediate(*InitialValue); } else { - assert(InitialValue->isReg() && "Expecting register for init value"); - const MachineInstr *DefInstr = MRI->getVRegDef(InitialValue->getReg()); - if (DefInstr && DefInstr->getOpcode() == Hexagon::TFRI) { - int64_t count = ImmVal - DefInstr->getOperand(1).getImm(); - if ((count % iv_value) != 0) { - return 0; - } - return new CountValue(count/iv_value); - } + assert(InitialValue->isImm()); + InitV = InitialValue->getImm(); + } + if (InitV >= EndV) + return 0; + if (CondOpc == Hexagon::CMPbEQri_V4) { + if (!isInt<8>(InitV) || !isInt<8>(EndV)) + return 0; + } else { // Hexagon::CMPhEQri_V4 + if (!isInt<16>(InitV) || !isInt<16>(EndV)) + return 0; } + Cmp = !Negated ? Comparison::EQ : Comparison::NE; + break; } + default: + return 0; } - return 0; + + if (isSwapped) + Cmp = Comparison::getSwappedComparison(Cmp); + + if (InitialValue->isReg()) { + unsigned R = InitialValue->getReg(); + MachineBasicBlock *DefBB = MRI->getVRegDef(R)->getParent(); + if (!MDT->properlyDominates(DefBB, Header)) + return 0; + OldInsts.push_back(MRI->getVRegDef(R)); + } + if (EndValue->isReg()) { + unsigned R = EndValue->getReg(); + MachineBasicBlock *DefBB = MRI->getVRegDef(R)->getParent(); + if (!MDT->properlyDominates(DefBB, Header)) + return 0; + } + + return computeCount(L, InitialValue, EndValue, IVReg, IVBump, Cmp); } -/// isInductionOperation - return true if the operation is matches the -/// pattern that defines an induction variable: -/// add iv, c -/// -bool -HexagonHardwareLoops::isInductionOperation(const MachineInstr *MI, - unsigned IVReg) const { - return (MI->getOpcode() == - Hexagon::ADD_ri && MI->getOperand(1).getReg() == IVReg); +/// \brief Helper function that returns the expression that represents the +/// number of times a loop iterates. The function takes the operands that +/// represent the loop start value, loop end value, and induction value. +/// Based upon these operands, the function attempts to compute the trip count. +CountValue *HexagonHardwareLoops::computeCount(MachineLoop *Loop, + const MachineOperand *Start, + const MachineOperand *End, + unsigned IVReg, + int64_t IVBump, + Comparison::Kind Cmp) const { + // Cannot handle comparison EQ, i.e. while (A == B). + if (Cmp == Comparison::EQ) + return 0; + + // Check if either the start or end values are an assignment of an immediate. + // If so, use the immediate value rather than the register. + if (Start->isReg()) { + const MachineInstr *StartValInstr = MRI->getVRegDef(Start->getReg()); + if (StartValInstr && StartValInstr->getOpcode() == Hexagon::TFRI) + Start = &StartValInstr->getOperand(1); + } + if (End->isReg()) { + const MachineInstr *EndValInstr = MRI->getVRegDef(End->getReg()); + if (EndValInstr && EndValInstr->getOpcode() == Hexagon::TFRI) + End = &EndValInstr->getOperand(1); + } + + assert (Start->isReg() || Start->isImm()); + assert (End->isReg() || End->isImm()); + + bool CmpLess = Cmp & Comparison::L; + bool CmpGreater = Cmp & Comparison::G; + bool CmpHasEqual = Cmp & Comparison::EQ; + + // Avoid certain wrap-arounds. This doesn't detect all wrap-arounds. + // If loop executes while iv is "less" with the iv value going down, then + // the iv must wrap. + if (CmpLess && IVBump < 0) + return 0; + // If loop executes while iv is "greater" with the iv value going up, then + // the iv must wrap. + if (CmpGreater && IVBump > 0) + return 0; + + if (Start->isImm() && End->isImm()) { + // Both, start and end are immediates. + int64_t StartV = Start->getImm(); + int64_t EndV = End->getImm(); + int64_t Dist = EndV - StartV; + if (Dist == 0) + return 0; + + bool Exact = (Dist % IVBump) == 0; + + if (Cmp == Comparison::NE) { + if (!Exact) + return 0; + if ((Dist < 0) ^ (IVBump < 0)) + return 0; + } + + // For comparisons that include the final value (i.e. include equality + // with the final value), we need to increase the distance by 1. + if (CmpHasEqual) + Dist = Dist > 0 ? Dist+1 : Dist-1; + + // assert (CmpLess => Dist > 0); + assert ((!CmpLess || Dist > 0) && "Loop should never iterate!"); + // assert (CmpGreater => Dist < 0); + assert ((!CmpGreater || Dist < 0) && "Loop should never iterate!"); + + // "Normalized" distance, i.e. with the bump set to +-1. + int64_t Dist1 = (IVBump > 0) ? (Dist + (IVBump-1)) / IVBump + : (-Dist + (-IVBump-1)) / (-IVBump); + assert (Dist1 > 0 && "Fishy thing. Both operands have the same sign."); + + uint64_t Count = Dist1; + + if (Count > 0xFFFFFFFFULL) + return 0; + + return new CountValue(CountValue::CV_Immediate, Count); + } + + // A general case: Start and End are some values, but the actual + // iteration count may not be available. If it is not, insert + // a computation of it into the preheader. + + // If the induction variable bump is not a power of 2, quit. + // Othwerise we'd need a general integer division. + if (!isPowerOf2_64(abs(IVBump))) + return 0; + + MachineBasicBlock *PH = Loop->getLoopPreheader(); + assert (PH && "Should have a preheader by now"); + MachineBasicBlock::iterator InsertPos = PH->getFirstTerminator(); + DebugLoc DL = (InsertPos != PH->end()) ? InsertPos->getDebugLoc() + : DebugLoc(); + + // If Start is an immediate and End is a register, the trip count + // will be "reg - imm". Hexagon's "subtract immediate" instruction + // is actually "reg + -imm". + + // If the loop IV is going downwards, i.e. if the bump is negative, + // then the iteration count (computed as End-Start) will need to be + // negated. To avoid the negation, just swap Start and End. + if (IVBump < 0) { + std::swap(Start, End); + IVBump = -IVBump; + } + // Cmp may now have a wrong direction, e.g. LEs may now be GEs. + // Signedness, and "including equality" are preserved. + + bool RegToImm = Start->isReg() && End->isImm(); // for (reg..imm) + bool RegToReg = Start->isReg() && End->isReg(); // for (reg..reg) + + int64_t StartV = 0, EndV = 0; + if (Start->isImm()) + StartV = Start->getImm(); + if (End->isImm()) + EndV = End->getImm(); + + int64_t AdjV = 0; + // To compute the iteration count, we would need this computation: + // Count = (End - Start + (IVBump-1)) / IVBump + // or, when CmpHasEqual: + // Count = (End - Start + (IVBump-1)+1) / IVBump + // The "IVBump-1" part is the adjustment (AdjV). We can avoid + // generating an instruction specifically to add it if we can adjust + // the immediate values for Start or End. + + if (CmpHasEqual) { + // Need to add 1 to the total iteration count. + if (Start->isImm()) + StartV--; + else if (End->isImm()) + EndV++; + else + AdjV += 1; + } + + if (Cmp != Comparison::NE) { + if (Start->isImm()) + StartV -= (IVBump-1); + else if (End->isImm()) + EndV += (IVBump-1); + else + AdjV += (IVBump-1); + } + + unsigned R = 0, SR = 0; + if (Start->isReg()) { + R = Start->getReg(); + SR = Start->getSubReg(); + } else { + R = End->getReg(); + SR = End->getSubReg(); + } + const TargetRegisterClass *RC = MRI->getRegClass(R); + // Hardware loops cannot handle 64-bit registers. If it's a double + // register, it has to have a subregister. + if (!SR && RC == &Hexagon::DoubleRegsRegClass) + return 0; + const TargetRegisterClass *IntRC = &Hexagon::IntRegsRegClass; + + // Compute DistR (register with the distance between Start and End). + unsigned DistR, DistSR; + + // Avoid special case, where the start value is an imm(0). + if (Start->isImm() && StartV == 0) { + DistR = End->getReg(); + DistSR = End->getSubReg(); + } else { + const MCInstrDesc &SubD = RegToReg ? TII->get(Hexagon::SUB_rr) : + (RegToImm ? TII->get(Hexagon::SUB_ri) : + TII->get(Hexagon::ADD_ri)); + unsigned SubR = MRI->createVirtualRegister(IntRC); + MachineInstrBuilder SubIB = + BuildMI(*PH, InsertPos, DL, SubD, SubR); + + if (RegToReg) { + SubIB.addReg(End->getReg(), 0, End->getSubReg()) + .addReg(Start->getReg(), 0, Start->getSubReg()); + } else if (RegToImm) { + SubIB.addImm(EndV) + .addReg(Start->getReg(), 0, Start->getSubReg()); + } else { // ImmToReg + SubIB.addReg(End->getReg(), 0, End->getSubReg()) + .addImm(-StartV); + } + DistR = SubR; + DistSR = 0; + } + + // From DistR, compute AdjR (register with the adjusted distance). + unsigned AdjR, AdjSR; + + if (AdjV == 0) { + AdjR = DistR; + AdjSR = DistSR; + } else { + // Generate CountR = ADD DistR, AdjVal + unsigned AddR = MRI->createVirtualRegister(IntRC); + const MCInstrDesc &AddD = TII->get(Hexagon::ADD_ri); + BuildMI(*PH, InsertPos, DL, AddD, AddR) + .addReg(DistR, 0, DistSR) + .addImm(AdjV); + + AdjR = AddR; + AdjSR = 0; + } + + // From AdjR, compute CountR (register with the final count). + unsigned CountR, CountSR; + + if (IVBump == 1) { + CountR = AdjR; + CountSR = AdjSR; + } else { + // The IV bump is a power of two. Log_2(IV bump) is the shift amount. + unsigned Shift = Log2_32(IVBump); + + // Generate NormR = LSR DistR, Shift. + unsigned LsrR = MRI->createVirtualRegister(IntRC); + const MCInstrDesc &LsrD = TII->get(Hexagon::LSR_ri); + BuildMI(*PH, InsertPos, DL, LsrD, LsrR) + .addReg(AdjR, 0, AdjSR) + .addImm(Shift); + + CountR = LsrR; + CountSR = 0; + } + + return new CountValue(CountValue::CV_Register, CountR, CountSR); } -/// isInvalidOperation - Return true if the operation is invalid within -/// hardware loop. -bool -HexagonHardwareLoops::isInvalidLoopOperation(const MachineInstr *MI) const { + +/// \brief Return true if the operation is invalid within hardware loop. +bool HexagonHardwareLoops::isInvalidLoopOperation( + const MachineInstr *MI) const { // call is not allowed because the callee may use a hardware loop - if (MI->getDesc().isCall()) { + if (MI->getDesc().isCall()) return true; - } + // do not allow nested hardware loops - if (isHardwareLoop(MI)) { + if (isHardwareLoop(MI)) return true; - } + // check if the instruction defines a hardware loop register for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); - if (MO.isReg() && MO.isDef() && - (MO.getReg() == Hexagon::LC0 || MO.getReg() == Hexagon::LC1 || - MO.getReg() == Hexagon::SA0 || MO.getReg() == Hexagon::SA0)) { + if (!MO.isReg() || !MO.isDef()) + continue; + unsigned R = MO.getReg(); + if (R == Hexagon::LC0 || R == Hexagon::LC1 || + R == Hexagon::SA0 || R == Hexagon::SA1) return true; - } } return false; } -/// containsInvalidInstruction - Return true if the loop contains -/// an instruction that inhibits the use of the hardware loop function. -/// + +/// \brief - Return true if the loop contains an instruction that inhibits +/// the use of the hardware loop function. bool HexagonHardwareLoops::containsInvalidInstruction(MachineLoop *L) const { const std::vector<MachineBasicBlock*> Blocks = L->getBlocks(); for (unsigned i = 0, e = Blocks.size(); i != e; ++i) { @@ -411,58 +883,184 @@ bool HexagonHardwareLoops::containsInvalidInstruction(MachineLoop *L) const { for (MachineBasicBlock::iterator MII = MBB->begin(), E = MBB->end(); MII != E; ++MII) { const MachineInstr *MI = &*MII; - if (isInvalidLoopOperation(MI)) { + if (isInvalidLoopOperation(MI)) return true; - } } } return false; } -/// converToHardwareLoop - check if the loop is a candidate for -/// converting to a hardware loop. If so, then perform the -/// transformation. + +/// \brief Returns true if the instruction is dead. This was essentially +/// copied from DeadMachineInstructionElim::isDead, but with special cases +/// for inline asm, physical registers and instructions with side effects +/// removed. +bool HexagonHardwareLoops::isDead(const MachineInstr *MI, + SmallVector<MachineInstr*, 1> &DeadPhis) const { + // Examine each operand. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isDef()) + continue; + + unsigned Reg = MO.getReg(); + if (MRI->use_nodbg_empty(Reg)) + continue; + + typedef MachineRegisterInfo::use_nodbg_iterator use_nodbg_iterator; + + // This instruction has users, but if the only user is the phi node for the + // parent block, and the only use of that phi node is this instruction, then + // this instruction is dead: both it (and the phi node) can be removed. + use_nodbg_iterator I = MRI->use_nodbg_begin(Reg); + use_nodbg_iterator End = MRI->use_nodbg_end(); + if (llvm::next(I) != End || !I.getOperand().getParent()->isPHI()) + return false; + + MachineInstr *OnePhi = I.getOperand().getParent(); + for (unsigned j = 0, f = OnePhi->getNumOperands(); j != f; ++j) { + const MachineOperand &OPO = OnePhi->getOperand(j); + if (!OPO.isReg() || !OPO.isDef()) + continue; + + unsigned OPReg = OPO.getReg(); + use_nodbg_iterator nextJ; + for (use_nodbg_iterator J = MRI->use_nodbg_begin(OPReg); + J != End; J = nextJ) { + nextJ = llvm::next(J); + MachineOperand &Use = J.getOperand(); + MachineInstr *UseMI = Use.getParent(); + + // If the phi node has a user that is not MI, bail... + if (MI != UseMI) + return false; + } + } + DeadPhis.push_back(OnePhi); + } + + // If there are no defs with uses, the instruction is dead. + return true; +} + +void HexagonHardwareLoops::removeIfDead(MachineInstr *MI) { + // This procedure was essentially copied from DeadMachineInstructionElim. + + SmallVector<MachineInstr*, 1> DeadPhis; + if (isDead(MI, DeadPhis)) { + DEBUG(dbgs() << "HW looping will remove: " << *MI); + + // It is possible that some DBG_VALUE instructions refer to this + // instruction. Examine each def operand for such references; + // if found, mark the DBG_VALUE as undef (but don't delete it). + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isDef()) + continue; + unsigned Reg = MO.getReg(); + MachineRegisterInfo::use_iterator nextI; + for (MachineRegisterInfo::use_iterator I = MRI->use_begin(Reg), + E = MRI->use_end(); I != E; I = nextI) { + nextI = llvm::next(I); // I is invalidated by the setReg + MachineOperand &Use = I.getOperand(); + MachineInstr *UseMI = Use.getParent(); + if (UseMI == MI) + continue; + if (Use.isDebug()) + UseMI->getOperand(0).setReg(0U); + // This may also be a "instr -> phi -> instr" case which can + // be removed too. + } + } + + MI->eraseFromParent(); + for (unsigned i = 0; i < DeadPhis.size(); ++i) + DeadPhis[i]->eraseFromParent(); + } +} + +/// \brief Check if the loop is a candidate for converting to a hardware +/// loop. If so, then perform the transformation. /// -/// This function works on innermost loops first. A loop can -/// be converted if it is a counting loop; either a register -/// value or an immediate. +/// This function works on innermost loops first. A loop can be converted +/// if it is a counting loop; either a register value or an immediate. /// -/// The code makes several assumptions about the representation -/// of the loop in llvm. +/// The code makes several assumptions about the representation of the loop +/// in llvm. bool HexagonHardwareLoops::convertToHardwareLoop(MachineLoop *L) { + // This is just for sanity. + assert(L->getHeader() && "Loop without a header?"); + bool Changed = false; // Process nested loops first. - for (MachineLoop::iterator I = L->begin(), E = L->end(); I != E; ++I) { + for (MachineLoop::iterator I = L->begin(), E = L->end(); I != E; ++I) Changed |= convertToHardwareLoop(*I); - } + // If a nested loop has been converted, then we can't convert this loop. - if (Changed) { + if (Changed) return Changed; + +#ifndef NDEBUG + // Stop trying after reaching the limit (if any). + int Limit = HWLoopLimit; + if (Limit >= 0) { + if (Counter >= HWLoopLimit) + return false; + Counter++; } - // Are we able to determine the trip count for the loop? - CountValue *TripCount = getTripCount(L); - if (TripCount == 0) { - return false; - } +#endif + // Does the loop contain any invalid instructions? - if (containsInvalidInstruction(L)) { + if (containsInvalidInstruction(L)) return false; - } - MachineBasicBlock *Preheader = L->getLoopPreheader(); - // No preheader means there's not place for the loop instr. - if (Preheader == 0) { + + // Is the induction variable bump feeding the latch condition? + if (!fixupInductionVariable(L)) return false; - } - MachineBasicBlock::iterator InsertPos = Preheader->getFirstTerminator(); MachineBasicBlock *LastMBB = L->getExitingBlock(); // Don't generate hw loop if the loop has more than one exit. - if (LastMBB == 0) { + if (LastMBB == 0) return false; - } + MachineBasicBlock::iterator LastI = LastMBB->getFirstTerminator(); - if (LastI == LastMBB->end()) { + if (LastI == LastMBB->end()) return false; + + // Ensure the loop has a preheader: the loop instruction will be + // placed there. + bool NewPreheader = false; + MachineBasicBlock *Preheader = L->getLoopPreheader(); + if (!Preheader) { + Preheader = createPreheaderForLoop(L); + if (!Preheader) + return false; + NewPreheader = true; + } + MachineBasicBlock::iterator InsertPos = Preheader->getFirstTerminator(); + + SmallVector<MachineInstr*, 2> OldInsts; + // Are we able to determine the trip count for the loop? + CountValue *TripCount = getLoopTripCount(L, OldInsts); + if (TripCount == 0) + return false; + + // Is the trip count available in the preheader? + if (TripCount->isReg()) { + // There will be a use of the register inserted into the preheader, + // so make sure that the register is actually defined at that point. + MachineInstr *TCDef = MRI->getVRegDef(TripCount->getReg()); + MachineBasicBlock *BBDef = TCDef->getParent(); + if (!NewPreheader) { + if (!MDT->dominates(BBDef, Preheader)) + return false; + } else { + // If we have just created a preheader, the dominator tree won't be + // aware of it. Check if the definition of the register dominates + // the header, but is not the header itself. + if (!MDT->properlyDominates(BBDef, L->getHeader())) + return false; + } } // Determine the loop start. @@ -470,53 +1068,53 @@ bool HexagonHardwareLoops::convertToHardwareLoop(MachineLoop *L) { if (L->getLoopLatch() != LastMBB) { // When the exit and latch are not the same, use the latch block as the // start. - // The loop start address is used only after the 1st iteration, and the loop - // latch may contains instrs. that need to be executed after the 1st iter. + // The loop start address is used only after the 1st iteration, and the + // loop latch may contains instrs. that need to be executed after the + // first iteration. LoopStart = L->getLoopLatch(); // Make sure the latch is a successor of the exit, otherwise it won't work. - if (!LastMBB->isSuccessor(LoopStart)) { + if (!LastMBB->isSuccessor(LoopStart)) return false; - } } - // Convert the loop to a hardware loop + // Convert the loop to a hardware loop. DEBUG(dbgs() << "Change to hardware loop at "; L->dump()); - DebugLoc InsertPosDL; + DebugLoc DL; if (InsertPos != Preheader->end()) - InsertPosDL = InsertPos->getDebugLoc(); + DL = InsertPos->getDebugLoc(); if (TripCount->isReg()) { // Create a copy of the loop count register. - MachineFunction *MF = LastMBB->getParent(); - const TargetRegisterClass *RC = - MF->getRegInfo().getRegClass(TripCount->getReg()); - unsigned CountReg = MF->getRegInfo().createVirtualRegister(RC); - BuildMI(*Preheader, InsertPos, InsertPosDL, - TII->get(TargetOpcode::COPY), CountReg).addReg(TripCount->getReg()); - if (TripCount->isNeg()) { - unsigned CountReg1 = CountReg; - CountReg = MF->getRegInfo().createVirtualRegister(RC); - BuildMI(*Preheader, InsertPos, InsertPosDL, - TII->get(Hexagon::NEG), CountReg).addReg(CountReg1); - } - + unsigned CountReg = MRI->createVirtualRegister(&Hexagon::IntRegsRegClass); + BuildMI(*Preheader, InsertPos, DL, TII->get(TargetOpcode::COPY), CountReg) + .addReg(TripCount->getReg(), 0, TripCount->getSubReg()); // Add the Loop instruction to the beginning of the loop. - BuildMI(*Preheader, InsertPos, InsertPosDL, - TII->get(Hexagon::LOOP0_r)).addMBB(LoopStart).addReg(CountReg); + BuildMI(*Preheader, InsertPos, DL, TII->get(Hexagon::LOOP0_r)) + .addMBB(LoopStart) + .addReg(CountReg); } else { - assert(TripCount->isImm() && "Expecting immedate vaule for trip count"); - // Add the Loop immediate instruction to the beginning of the loop. + assert(TripCount->isImm() && "Expecting immediate value for trip count"); + // Add the Loop immediate instruction to the beginning of the loop, + // if the immediate fits in the instructions. Otherwise, we need to + // create a new virtual register. int64_t CountImm = TripCount->getImm(); - BuildMI(*Preheader, InsertPos, InsertPosDL, - TII->get(Hexagon::LOOP0_i)).addMBB(LoopStart).addImm(CountImm); + if (!TII->isValidOffset(Hexagon::LOOP0_i, CountImm)) { + unsigned CountReg = MRI->createVirtualRegister(&Hexagon::IntRegsRegClass); + BuildMI(*Preheader, InsertPos, DL, TII->get(Hexagon::TFRI), CountReg) + .addImm(CountImm); + BuildMI(*Preheader, InsertPos, DL, TII->get(Hexagon::LOOP0_r)) + .addMBB(LoopStart).addReg(CountReg); + } else + BuildMI(*Preheader, InsertPos, DL, TII->get(Hexagon::LOOP0_i)) + .addMBB(LoopStart).addImm(CountImm); } - // Make sure the loop start always has a reference in the CFG. We need to - // create a BlockAddress operand to get this mechanism to work both the + // Make sure the loop start always has a reference in the CFG. We need + // to create a BlockAddress operand to get this mechanism to work both the // MachineBasicBlock and BasicBlock objects need the flag set. LoopStart->setHasAddressTaken(); // This line is needed to set the hasAddressTaken flag on the BasicBlock - // object + // object. BlockAddress::get(const_cast<BasicBlock *>(LoopStart->getBasicBlock())); // Replace the loop branch with an endloop instruction. @@ -529,13 +1127,12 @@ bool HexagonHardwareLoops::convertToHardwareLoop(MachineLoop *L) { // - a conditional branch to the loop start. if (LastI->getOpcode() == Hexagon::JMP_c || LastI->getOpcode() == Hexagon::JMP_cNot) { - // delete one and change/add an uncond. branch to out of the loop + // Delete one and change/add an uncond. branch to out of the loop. MachineBasicBlock *BranchTarget = LastI->getOperand(1).getMBB(); LastI = LastMBB->erase(LastI); if (!L->contains(BranchTarget)) { - if (LastI != LastMBB->end()) { - TII->RemoveBranch(*LastMBB); - } + if (LastI != LastMBB->end()) + LastI = LastMBB->erase(LastI); SmallVector<MachineOperand, 0> Cond; TII->InsertBranch(*LastMBB, BranchTarget, 0, Cond, LastIDL); } @@ -545,110 +1142,414 @@ bool HexagonHardwareLoops::convertToHardwareLoop(MachineLoop *L) { } delete TripCount; + // The induction operation and the comparison may now be + // unneeded. If these are unneeded, then remove them. + for (unsigned i = 0; i < OldInsts.size(); ++i) + removeIfDead(OldInsts[i]); + ++NumHWLoops; return true; } -/// createHexagonFixupHwLoops - Factory for creating the hardware loop -/// phase. -FunctionPass *llvm::createHexagonFixupHwLoops() { - return new HexagonFixupHwLoops(); + +bool HexagonHardwareLoops::orderBumpCompare(MachineInstr *BumpI, + MachineInstr *CmpI) { + assert (BumpI != CmpI && "Bump and compare in the same instruction?"); + + MachineBasicBlock *BB = BumpI->getParent(); + if (CmpI->getParent() != BB) + return false; + + typedef MachineBasicBlock::instr_iterator instr_iterator; + // Check if things are in order to begin with. + for (instr_iterator I = BumpI, E = BB->instr_end(); I != E; ++I) + if (&*I == CmpI) + return true; + + // Out of order. + unsigned PredR = CmpI->getOperand(0).getReg(); + bool FoundBump = false; + instr_iterator CmpIt = CmpI, NextIt = llvm::next(CmpIt); + for (instr_iterator I = NextIt, E = BB->instr_end(); I != E; ++I) { + MachineInstr *In = &*I; + for (unsigned i = 0, n = In->getNumOperands(); i < n; ++i) { + MachineOperand &MO = In->getOperand(i); + if (MO.isReg() && MO.isUse()) { + if (MO.getReg() == PredR) // Found an intervening use of PredR. + return false; + } + } + + if (In == BumpI) { + instr_iterator After = BumpI; + instr_iterator From = CmpI; + BB->splice(llvm::next(After), BB, From); + FoundBump = true; + break; + } + } + assert (FoundBump && "Cannot determine instruction order"); + return FoundBump; } -bool HexagonFixupHwLoops::runOnMachineFunction(MachineFunction &MF) { - DEBUG(dbgs() << "****** Hexagon Hardware Loop Fixup ******\n"); - bool Changed = fixupLoopInstrs(MF); - return Changed; +MachineInstr *HexagonHardwareLoops::defWithImmediate(unsigned R) { + MachineInstr *DI = MRI->getVRegDef(R); + unsigned DOpc = DI->getOpcode(); + switch (DOpc) { + case Hexagon::TFRI: + case Hexagon::TFRI64: + case Hexagon::CONST32_Int_Real: + case Hexagon::CONST64_Int_Real: + return DI; + } + return 0; } -/// fixupLoopInsts - For Hexagon, if the loop label is to far from the -/// loop instruction then we need to set the LC0 and SA0 registers -/// explicitly instead of using LOOP(start,count). This function -/// checks the distance, and generates register assignments if needed. -/// -/// This function makes two passes over the basic blocks. The first -/// pass computes the offset of the basic block from the start. -/// The second pass checks all the loop instructions. -bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) { - - // Offset of the current instruction from the start. - unsigned InstOffset = 0; - // Map for each basic block to it's first instruction. - DenseMap<MachineBasicBlock*, unsigned> BlockToInstOffset; - - // First pass - compute the offset of each basic block. - for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end(); - MBB != MBBe; ++MBB) { - BlockToInstOffset[MBB] = InstOffset; - InstOffset += (MBB->size() * 4); - } - - // Second pass - check each loop instruction to see if it needs to - // be converted. - InstOffset = 0; - bool Changed = false; - RegScavenger RS; - - // Loop over all the basic blocks. - for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end(); - MBB != MBBe; ++MBB) { - InstOffset = BlockToInstOffset[MBB]; - RS.enterBasicBlock(MBB); - - // Loop over all the instructions. - MachineBasicBlock::iterator MIE = MBB->end(); - MachineBasicBlock::iterator MII = MBB->begin(); - while (MII != MIE) { - if (isHardwareLoop(MII)) { - RS.forward(MII); - assert(MII->getOperand(0).isMBB() && - "Expect a basic block as loop operand"); - int diff = InstOffset - BlockToInstOffset[MII->getOperand(0).getMBB()]; - diff = (diff > 0 ? diff : -diff); - if ((unsigned)diff > MAX_LOOP_DISTANCE) { - // Convert to explicity setting LC0 and SA0. - convertLoopInstr(MF, MII, RS); - MII = MBB->erase(MII); - Changed = true; - } else { - ++MII; + +int64_t HexagonHardwareLoops::getImmediate(MachineOperand &MO) { + if (MO.isImm()) + return MO.getImm(); + assert(MO.isReg()); + unsigned R = MO.getReg(); + MachineInstr *DI = defWithImmediate(R); + assert(DI && "Need an immediate operand"); + // All currently supported "define-with-immediate" instructions have the + // actual immediate value in the operand(1). + int64_t v = DI->getOperand(1).getImm(); + return v; +} + + +void HexagonHardwareLoops::setImmediate(MachineOperand &MO, int64_t Val) { + if (MO.isImm()) { + MO.setImm(Val); + return; + } + + assert(MO.isReg()); + unsigned R = MO.getReg(); + MachineInstr *DI = defWithImmediate(R); + if (MRI->hasOneNonDBGUse(R)) { + // If R has only one use, then just change its defining instruction to + // the new immediate value. + DI->getOperand(1).setImm(Val); + return; + } + + const TargetRegisterClass *RC = MRI->getRegClass(R); + unsigned NewR = MRI->createVirtualRegister(RC); + MachineBasicBlock &B = *DI->getParent(); + DebugLoc DL = DI->getDebugLoc(); + BuildMI(B, DI, DL, TII->get(DI->getOpcode()), NewR) + .addImm(Val); + MO.setReg(NewR); +} + + +bool HexagonHardwareLoops::fixupInductionVariable(MachineLoop *L) { + MachineBasicBlock *Header = L->getHeader(); + MachineBasicBlock *Preheader = L->getLoopPreheader(); + MachineBasicBlock *Latch = L->getLoopLatch(); + + if (!Header || !Preheader || !Latch) + return false; + + // These data structures follow the same concept as the corresponding + // ones in findInductionRegister (where some comments are). + typedef std::pair<unsigned,int64_t> RegisterBump; + typedef std::pair<unsigned,RegisterBump> RegisterInduction; + typedef std::set<RegisterInduction> RegisterInductionSet; + + // Register candidates for induction variables, with their associated bumps. + RegisterInductionSet IndRegs; + + // Look for induction patterns: + // vreg1 = PHI ..., [ latch, vreg2 ] + // vreg2 = ADD vreg1, imm + typedef MachineBasicBlock::instr_iterator instr_iterator; + for (instr_iterator I = Header->instr_begin(), E = Header->instr_end(); + I != E && I->isPHI(); ++I) { + MachineInstr *Phi = &*I; + + // Have a PHI instruction. + for (unsigned i = 1, n = Phi->getNumOperands(); i < n; i += 2) { + if (Phi->getOperand(i+1).getMBB() != Latch) + continue; + + unsigned PhiReg = Phi->getOperand(i).getReg(); + MachineInstr *DI = MRI->getVRegDef(PhiReg); + unsigned UpdOpc = DI->getOpcode(); + bool isAdd = (UpdOpc == Hexagon::ADD_ri); + + if (isAdd) { + // If the register operand to the add/sub is the PHI we are looking + // at, this meets the induction pattern. + unsigned IndReg = DI->getOperand(1).getReg(); + if (MRI->getVRegDef(IndReg) == Phi) { + unsigned UpdReg = DI->getOperand(0).getReg(); + int64_t V = DI->getOperand(2).getImm(); + IndRegs.insert(std::make_pair(UpdReg, std::make_pair(IndReg, V))); } - } else { - ++MII; } - InstOffset += 4; + } // for (i) + } // for (instr) + + if (IndRegs.empty()) + return false; + + MachineBasicBlock *TB = 0, *FB = 0; + SmallVector<MachineOperand,2> Cond; + // AnalyzeBranch returns true if it fails to analyze branch. + bool NotAnalyzed = TII->AnalyzeBranch(*Latch, TB, FB, Cond, false); + if (NotAnalyzed) + return false; + + // Check if the latch branch is unconditional. + if (Cond.empty()) + return false; + + if (TB != Header && FB != Header) + // The latch does not go back to the header. Not a latch we know and love. + return false; + + // Expecting a predicate register as a condition. It won't be a hardware + // predicate register at this point yet, just a vreg. + // HexagonInstrInfo::AnalyzeBranch for negated branches inserts imm(0) + // into Cond, followed by the predicate register. For non-negated branches + // it's just the register. + unsigned CSz = Cond.size(); + if (CSz != 1 && CSz != 2) + return false; + + unsigned P = Cond[CSz-1].getReg(); + MachineInstr *PredDef = MRI->getVRegDef(P); + + if (!PredDef->isCompare()) + return false; + + SmallSet<unsigned,2> CmpRegs; + MachineOperand *CmpImmOp = 0; + + // Go over all operands to the compare and look for immediate and register + // operands. Assume that if the compare has a single register use and a + // single immediate operand, then the register is being compared with the + // immediate value. + for (unsigned i = 0, n = PredDef->getNumOperands(); i < n; ++i) { + MachineOperand &MO = PredDef->getOperand(i); + if (MO.isReg()) { + // Skip all implicit references. In one case there was: + // %vreg140<def> = FCMPUGT32_rr %vreg138, %vreg139, %USR<imp-use> + if (MO.isImplicit()) + continue; + if (MO.isUse()) { + unsigned R = MO.getReg(); + if (!defWithImmediate(R)) { + CmpRegs.insert(MO.getReg()); + continue; + } + // Consider the register to be the "immediate" operand. + if (CmpImmOp) + return false; + CmpImmOp = &MO; + } + } else if (MO.isImm()) { + if (CmpImmOp) // A second immediate argument? Confusing. Bail out. + return false; + CmpImmOp = &MO; } } - return Changed; + if (CmpRegs.empty()) + return false; + + // Check if the compared register follows the order we want. Fix if needed. + for (RegisterInductionSet::iterator I = IndRegs.begin(), E = IndRegs.end(); + I != E; ++I) { + // This is a success. If the register used in the comparison is one that + // we have identified as a bumped (updated) induction register, there is + // nothing to do. + if (CmpRegs.count(I->first)) + return true; + + // Otherwise, if the register being compared comes out of a PHI node, + // and has been recognized as following the induction pattern, and is + // compared against an immediate, we can fix it. + const RegisterBump &RB = I->second; + if (CmpRegs.count(RB.first)) { + if (!CmpImmOp) + return false; + + int64_t CmpImm = getImmediate(*CmpImmOp); + int64_t V = RB.second; + if (V > 0 && CmpImm+V < CmpImm) // Overflow (64-bit). + return false; + if (V < 0 && CmpImm+V > CmpImm) // Overflow (64-bit). + return false; + CmpImm += V; + // Some forms of cmp-immediate allow u9 and s10. Assume the worst case + // scenario, i.e. an 8-bit value. + if (CmpImmOp->isImm() && !isInt<8>(CmpImm)) + return false; + + // Make sure that the compare happens after the bump. Otherwise, + // after the fixup, the compare would use a yet-undefined register. + MachineInstr *BumpI = MRI->getVRegDef(I->first); + bool Order = orderBumpCompare(BumpI, PredDef); + if (!Order) + return false; + + // Finally, fix the compare instruction. + setImmediate(*CmpImmOp, CmpImm); + for (unsigned i = 0, n = PredDef->getNumOperands(); i < n; ++i) { + MachineOperand &MO = PredDef->getOperand(i); + if (MO.isReg() && MO.getReg() == RB.first) { + MO.setReg(I->first); + return true; + } + } + } + } + return false; } -/// convertLoopInstr - convert a loop instruction to a sequence of instructions -/// that set the lc and sa register explicitly. -void HexagonFixupHwLoops::convertLoopInstr(MachineFunction &MF, - MachineBasicBlock::iterator &MII, - RegScavenger &RS) { - const TargetInstrInfo *TII = MF.getTarget().getInstrInfo(); - MachineBasicBlock *MBB = MII->getParent(); - DebugLoc DL = MII->getDebugLoc(); - unsigned Scratch = RS.scavengeRegister(&Hexagon::IntRegsRegClass, MII, 0); - - // First, set the LC0 with the trip count. - if (MII->getOperand(1).isReg()) { - // Trip count is a register - BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0) - .addReg(MII->getOperand(1).getReg()); + +/// \brief Create a preheader for a given loop. +MachineBasicBlock *HexagonHardwareLoops::createPreheaderForLoop( + MachineLoop *L) { + if (MachineBasicBlock *TmpPH = L->getLoopPreheader()) + return TmpPH; + + MachineBasicBlock *Header = L->getHeader(); + MachineBasicBlock *Latch = L->getLoopLatch(); + MachineFunction *MF = Header->getParent(); + DebugLoc DL; + + if (!Latch || Header->hasAddressTaken()) + return 0; + + typedef MachineBasicBlock::instr_iterator instr_iterator; + typedef MachineBasicBlock::pred_iterator pred_iterator; + + // Verify that all existing predecessors have analyzable branches + // (or no branches at all). + typedef std::vector<MachineBasicBlock*> MBBVector; + MBBVector Preds(Header->pred_begin(), Header->pred_end()); + SmallVector<MachineOperand,2> Tmp1; + MachineBasicBlock *TB = 0, *FB = 0; + + if (TII->AnalyzeBranch(*Latch, TB, FB, Tmp1, false)) + return 0; + + for (MBBVector::iterator I = Preds.begin(), E = Preds.end(); I != E; ++I) { + MachineBasicBlock *PB = *I; + if (PB != Latch) { + bool NotAnalyzed = TII->AnalyzeBranch(*PB, TB, FB, Tmp1, false); + if (NotAnalyzed) + return 0; + } + } + + MachineBasicBlock *NewPH = MF->CreateMachineBasicBlock(); + MF->insert(Header, NewPH); + + if (Header->pred_size() > 2) { + // Ensure that the header has only two predecessors: the preheader and + // the loop latch. Any additional predecessors of the header should + // join at the newly created preheader. Inspect all PHI nodes from the + // header and create appropriate corresponding PHI nodes in the preheader. + + for (instr_iterator I = Header->instr_begin(), E = Header->instr_end(); + I != E && I->isPHI(); ++I) { + MachineInstr *PN = &*I; + + const MCInstrDesc &PD = TII->get(TargetOpcode::PHI); + MachineInstr *NewPN = MF->CreateMachineInstr(PD, DL); + NewPH->insert(NewPH->end(), NewPN); + + unsigned PR = PN->getOperand(0).getReg(); + const TargetRegisterClass *RC = MRI->getRegClass(PR); + unsigned NewPR = MRI->createVirtualRegister(RC); + NewPN->addOperand(MachineOperand::CreateReg(NewPR, true)); + + // Copy all non-latch operands of a header's PHI node to the newly + // created PHI node in the preheader. + for (unsigned i = 1, n = PN->getNumOperands(); i < n; i += 2) { + unsigned PredR = PN->getOperand(i).getReg(); + MachineBasicBlock *PredB = PN->getOperand(i+1).getMBB(); + if (PredB == Latch) + continue; + + NewPN->addOperand(MachineOperand::CreateReg(PredR, false)); + NewPN->addOperand(MachineOperand::CreateMBB(PredB)); + } + + // Remove copied operands from the old PHI node and add the value + // coming from the preheader's PHI. + for (int i = PN->getNumOperands()-2; i > 0; i -= 2) { + MachineBasicBlock *PredB = PN->getOperand(i+1).getMBB(); + if (PredB != Latch) { + PN->RemoveOperand(i+1); + PN->RemoveOperand(i); + } + } + PN->addOperand(MachineOperand::CreateReg(NewPR, false)); + PN->addOperand(MachineOperand::CreateMBB(NewPH)); + } + } else { - // Trip count is an immediate. - BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFRI), Scratch) - .addImm(MII->getOperand(1).getImm()); - BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0) - .addReg(Scratch); - } - // Then, set the SA0 with the loop start address. - BuildMI(*MBB, MII, DL, TII->get(Hexagon::CONST32_Label), Scratch) - .addMBB(MII->getOperand(0).getMBB()); - BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::SA0).addReg(Scratch); + assert(Header->pred_size() == 2); + + // The header has only two predecessors, but the non-latch predecessor + // is not a preheader (e.g. it has other successors, etc.) + // In such a case we don't need any extra PHI nodes in the new preheader, + // all we need is to adjust existing PHIs in the header to now refer to + // the new preheader. + for (instr_iterator I = Header->instr_begin(), E = Header->instr_end(); + I != E && I->isPHI(); ++I) { + MachineInstr *PN = &*I; + for (unsigned i = 1, n = PN->getNumOperands(); i < n; i += 2) { + MachineOperand &MO = PN->getOperand(i+1); + if (MO.getMBB() != Latch) + MO.setMBB(NewPH); + } + } + } + + // "Reroute" the CFG edges to link in the new preheader. + // If any of the predecessors falls through to the header, insert a branch + // to the new preheader in that place. + SmallVector<MachineOperand,1> Tmp2; + SmallVector<MachineOperand,1> EmptyCond; + + TB = FB = 0; + + for (MBBVector::iterator I = Preds.begin(), E = Preds.end(); I != E; ++I) { + MachineBasicBlock *PB = *I; + if (PB != Latch) { + Tmp2.clear(); + bool NotAnalyzed = TII->AnalyzeBranch(*PB, TB, FB, Tmp2, false); + (void)NotAnalyzed; // supress compiler warning + assert (!NotAnalyzed && "Should be analyzable!"); + if (TB != Header && (Tmp2.empty() || FB != Header)) + TII->InsertBranch(*PB, NewPH, 0, EmptyCond, DL); + PB->ReplaceUsesOfBlockWith(Header, NewPH); + } + } + + // It can happen that the latch block will fall through into the header. + // Insert an unconditional branch to the header. + TB = FB = 0; + bool LatchNotAnalyzed = TII->AnalyzeBranch(*Latch, TB, FB, Tmp2, false); + (void)LatchNotAnalyzed; // supress compiler warning + assert (!LatchNotAnalyzed && "Should be analyzable!"); + if (!TB && !FB) + TII->InsertBranch(*Latch, Header, 0, EmptyCond, DL); + + // Finally, the branch from the preheader to the header. + TII->InsertBranch(*NewPH, Header, 0, EmptyCond, DL); + NewPH->addSuccessor(Header); + + return NewPH; } diff --git a/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp index 275e135cd6..3a1c48bac9 100644 --- a/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp +++ b/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp @@ -15,18 +15,29 @@ #include "Hexagon.h" #include "HexagonISelLowering.h" #include "HexagonTargetMachine.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/CodeGen/SelectionDAGISel.h" -#include "llvm/Intrinsics.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" - using namespace llvm; +static +cl::opt<unsigned> +MaxNumOfUsesForConstExtenders("ga-max-num-uses-for-constant-extenders", + cl::Hidden, cl::init(2), + cl::desc("Maximum number of uses of a global address such that we still us a" + "constant extended instruction")); //===----------------------------------------------------------------------===// // Instruction Selector Implementation //===----------------------------------------------------------------------===// +namespace llvm { + void initializeHexagonDAGToDAGISelPass(PassRegistry&); +} + //===--------------------------------------------------------------------===// /// HexagonDAGToDAGISel - Hexagon specific code to select Hexagon machine /// instructions for SelectionDAG operations. @@ -40,19 +51,24 @@ class HexagonDAGToDAGISel : public SelectionDAGISel { // Keep a reference to HexagonTargetMachine. HexagonTargetMachine& TM; const HexagonInstrInfo *TII; - + DenseMap<const GlobalValue *, unsigned> GlobalAddressUseCountMap; public: - explicit HexagonDAGToDAGISel(HexagonTargetMachine &targetmachine) - : SelectionDAGISel(targetmachine), + explicit HexagonDAGToDAGISel(HexagonTargetMachine &targetmachine, + CodeGenOpt::Level OptLevel) + : SelectionDAGISel(targetmachine, OptLevel), Subtarget(targetmachine.getSubtarget<HexagonSubtarget>()), TM(targetmachine), TII(static_cast<const HexagonInstrInfo*>(TM.getInstrInfo())) { - + initializeHexagonDAGToDAGISelPass(*PassRegistry::getPassRegistry()); } + bool hasNumUsesBelowThresGA(SDNode *N) const; SDNode *Select(SDNode *N); // Complex Pattern Selectors. + inline bool foldGlobalAddress(SDValue &N, SDValue &R); + inline bool foldGlobalAddressGP(SDValue &N, SDValue &R); + bool foldGlobalAddressImpl(SDValue &N, SDValue &R, bool ShouldLookForGP); bool SelectADDRri(SDValue& N, SDValue &R1, SDValue &R2); bool SelectADDRriS11_0(SDValue& N, SDValue &R1, SDValue &R2); bool SelectADDRriS11_1(SDValue& N, SDValue &R1, SDValue &R2); @@ -97,7 +113,14 @@ public: SDNode *SelectAdd(SDNode *N); bool isConstExtProfitable(SDNode *N) const; - // Include the pieces autogenerated from the target description. +// XformU7ToU7M1Imm - Return a target constant decremented by 1, in range +// [1..128], used in cmpb.gtu instructions. +inline SDValue XformU7ToU7M1Imm(signed Imm) { + assert((Imm >= 1 && Imm <= 128) && "Constant out of range for cmpb op"); + return CurDAG->getTargetConstant(Imm - 1, MVT::i8); +} + +// Include the pieces autogenerated from the target description. #include "HexagonGenDAGISel.inc" }; } // end anonymous namespace @@ -106,10 +129,23 @@ public: /// createHexagonISelDag - This pass converts a legalized DAG into a /// Hexagon-specific DAG, ready for instruction scheduling. /// -FunctionPass *llvm::createHexagonISelDag(HexagonTargetMachine &TM) { - return new HexagonDAGToDAGISel(TM); +FunctionPass *llvm::createHexagonISelDag(HexagonTargetMachine &TM, + CodeGenOpt::Level OptLevel) { + return new HexagonDAGToDAGISel(TM, OptLevel); } +static void initializePassOnce(PassRegistry &Registry) { + const char *Name = "Hexagon DAG->DAG Pattern Instruction Selection"; + PassInfo *PI = new PassInfo(Name, "hexagon-isel", + &SelectionDAGISel::ID, 0, false, false); + Registry.registerPass(*PI, true); +} + +void llvm::initializeHexagonDAGToDAGISelPass(PassRegistry &Registry) { + CALL_ONCE_INITIALIZATION(initializePassOnce) +} + + static bool IsS11_0_Offset(SDNode * S) { ConstantSDNode *N = cast<ConstantSDNode>(S); @@ -608,8 +644,8 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, DebugLoc dl) { // Offset value must be within representable range // and must have correct alignment properties. if (TII->isValidAutoIncImm(StoredVT, Val)) { - SDValue Ops[] = { Value, Base, - CurDAG->getTargetConstant(Val, MVT::i32), Chain}; + SDValue Ops[] = {Base, CurDAG->getTargetConstant(Val, MVT::i32), Value, + Chain}; unsigned Opcode = 0; // Figure out the post inc version of opcode. @@ -1519,3 +1555,69 @@ bool HexagonDAGToDAGISel::isConstExtProfitable(SDNode *N) const { return (UseCount <= 1); } + +//===--------------------------------------------------------------------===// +// Return 'true' if use count of the global address is below threshold. +//===--------------------------------------------------------------------===// +bool HexagonDAGToDAGISel::hasNumUsesBelowThresGA(SDNode *N) const { + assert(N->getOpcode() == ISD::TargetGlobalAddress && + "Expecting a target global address"); + + // Always try to fold the address. + if (TM.getOptLevel() == CodeGenOpt::Aggressive) + return true; + + GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(N); + DenseMap<const GlobalValue *, unsigned>::const_iterator GI = + GlobalAddressUseCountMap.find(GA->getGlobal()); + + if (GI == GlobalAddressUseCountMap.end()) + return false; + + return GI->second <= MaxNumOfUsesForConstExtenders; +} + +//===--------------------------------------------------------------------===// +// Return true if the non GP-relative global address can be folded. +//===--------------------------------------------------------------------===// +inline bool HexagonDAGToDAGISel::foldGlobalAddress(SDValue &N, SDValue &R) { + return foldGlobalAddressImpl(N, R, false); +} + +//===--------------------------------------------------------------------===// +// Return true if the GP-relative global address can be folded. +//===--------------------------------------------------------------------===// +inline bool HexagonDAGToDAGISel::foldGlobalAddressGP(SDValue &N, SDValue &R) { + return foldGlobalAddressImpl(N, R, true); +} + +//===--------------------------------------------------------------------===// +// Fold offset of the global address if number of uses are below threshold. +//===--------------------------------------------------------------------===// +bool HexagonDAGToDAGISel::foldGlobalAddressImpl(SDValue &N, SDValue &R, + bool ShouldLookForGP) { + if (N.getOpcode() == ISD::ADD) { + SDValue N0 = N.getOperand(0); + SDValue N1 = N.getOperand(1); + if ((ShouldLookForGP && (N0.getOpcode() == HexagonISD::CONST32_GP)) || + (!ShouldLookForGP && (N0.getOpcode() == HexagonISD::CONST32))) { + ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N1); + GlobalAddressSDNode *GA = + dyn_cast<GlobalAddressSDNode>(N0.getOperand(0)); + + if (Const && GA && + (GA->getOpcode() == ISD::TargetGlobalAddress)) { + if ((N0.getOpcode() == HexagonISD::CONST32) && + !hasNumUsesBelowThresGA(GA)) + return false; + R = CurDAG->getTargetGlobalAddress(GA->getGlobal(), + Const->getDebugLoc(), + N.getValueType(), + GA->getOffset() + + (uint64_t)Const->getSExtValue()); + return true; + } + } + } + return false; +} diff --git a/lib/Target/Hexagon/HexagonISelLowering.cpp b/lib/Target/Hexagon/HexagonISelLowering.cpp index 10c54cba9f..0a8b1af21b 100644 --- a/lib/Target/Hexagon/HexagonISelLowering.cpp +++ b/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -17,7 +17,6 @@ #include "HexagonSubtarget.h" #include "HexagonTargetMachine.h" #include "HexagonTargetObjectFile.h" -#include "llvm/CallingConv.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" @@ -26,12 +25,13 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/CodeGen/ValueTypes.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Function.h" -#include "llvm/GlobalAlias.h" -#include "llvm/GlobalVariable.h" -#include "llvm/InlineAsm.h" -#include "llvm/Intrinsics.h" +#include "llvm/IR/CallingConv.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalAlias.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -103,6 +103,16 @@ CC_Hexagon_VarArg (unsigned ValNo, MVT ValVT, State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo)); return false; } + if (LocVT == MVT::i1 || LocVT == MVT::i8 || LocVT == MVT::i16) { + LocVT = MVT::i32; + ValVT = MVT::i32; + if (ArgFlags.isSExt()) + LocInfo = CCValAssign::SExt; + else if (ArgFlags.isZExt()) + LocInfo = CCValAssign::ZExt; + else + LocInfo = CCValAssign::AExt; + } if (LocVT == MVT::i32 || LocVT == MVT::f32) { ofst = State.AllocateStack(4, 4); State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo)); @@ -304,15 +314,9 @@ HexagonTargetLowering::LowerReturn(SDValue Chain, // Analyze return values of ISD::RET CCInfo.AnalyzeReturn(Outs, RetCC_Hexagon); - // If this is the first return lowered for this function, add the regs to the - // liveout set for the function. - if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { - for (unsigned i = 0; i != RVLocs.size(); ++i) - if (RVLocs[i].isRegLoc()) - DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); - } - SDValue Flag; + SmallVector<SDValue, 4> RetOps(1, Chain); + // Copy the result values into the output registers. for (unsigned i = 0; i != RVLocs.size(); ++i) { CCValAssign &VA = RVLocs[i]; @@ -321,12 +325,17 @@ HexagonTargetLowering::LowerReturn(SDValue Chain, // Guarantee that all emitted copies are stuck together with flags. Flag = Chain.getValue(1); + RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); } + RetOps[0] = Chain; // Update chain. + + // Add the flag if we have it. if (Flag.getNode()) - return DAG.getNode(HexagonISD::RET_FLAG, dl, MVT::Other, Chain, Flag); + RetOps.push_back(Flag); - return DAG.getNode(HexagonISD::RET_FLAG, dl, MVT::Other, Chain); + return DAG.getNode(HexagonISD::RET_FLAG, dl, MVT::Other, + &RetOps[0], RetOps.size()); } @@ -1016,8 +1025,8 @@ SDValue HexagonTargetLowering::LowerGLOBALADDRESS(SDValue Op, DebugLoc dl = Op.getDebugLoc(); Result = DAG.getTargetGlobalAddress(GV, dl, getPointerTy(), Offset); - HexagonTargetObjectFile &TLOF = - (HexagonTargetObjectFile&)getObjFileLowering(); + const HexagonTargetObjectFile &TLOF = + static_cast<const HexagonTargetObjectFile &>(getObjFileLowering()); if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) { return DAG.getNode(HexagonISD::CONST32_GP, dl, getPointerTy(), Result); } @@ -1025,6 +1034,14 @@ SDValue HexagonTargetLowering::LowerGLOBALADDRESS(SDValue Op, return DAG.getNode(HexagonISD::CONST32, dl, getPointerTy(), Result); } +SDValue +HexagonTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const { + const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress(); + SDValue BA_SD = DAG.getTargetBlockAddress(BA, MVT::i32); + DebugLoc dl = Op.getDebugLoc(); + return DAG.getNode(HexagonISD::CONST32_GP, dl, getPointerTy(), BA_SD); +} + //===----------------------------------------------------------------------===// // TargetLowering Implementation //===----------------------------------------------------------------------===// @@ -1053,8 +1070,8 @@ HexagonTargetLowering::HexagonTargetLowering(HexagonTargetMachine setPrefLoopAlignment(4); // Limits for inline expansion of memcpy/memmove - maxStoresPerMemcpy = 6; - maxStoresPerMemmove = 6; + MaxStoresPerMemcpy = 6; + MaxStoresPerMemmove = 6; // // Library calls for unsupported operations @@ -1298,6 +1315,7 @@ HexagonTargetLowering::HexagonTargetLowering(HexagonTargetMachine // Custom legalize GlobalAddress nodes into CONST32. setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); setOperationAction(ISD::GlobalAddress, MVT::i8, Custom); + setOperationAction(ISD::BlockAddress, MVT::i32, Custom); // Truncate action? setOperationAction(ISD::TRUNCATE, MVT::i64, Expand); @@ -1343,7 +1361,6 @@ HexagonTargetLowering::HexagonTargetLowering(HexagonTargetMachine } - setOperationAction(ISD::BR_CC, MVT::Other, Expand); setOperationAction(ISD::BRIND, MVT::Other, Expand); if (EmitJumpTables) { setOperationAction(ISD::BR_JT, MVT::Other, Custom); @@ -1353,6 +1370,9 @@ HexagonTargetLowering::HexagonTargetLowering(HexagonTargetMachine // Increase jump tables cutover to 5, was 4. setMinimumJumpTableEntries(5); + setOperationAction(ISD::BR_CC, MVT::f32, Expand); + setOperationAction(ISD::BR_CC, MVT::f64, Expand); + setOperationAction(ISD::BR_CC, MVT::i1, Expand); setOperationAction(ISD::BR_CC, MVT::i32, Expand); setOperationAction(ISD::MEMBARRIER, MVT::Other, Custom); @@ -1364,11 +1384,41 @@ HexagonTargetLowering::HexagonTargetLowering(HexagonTargetMachine setOperationAction(ISD::FSIN , MVT::f32, Expand); setOperationAction(ISD::FCOS , MVT::f32, Expand); setOperationAction(ISD::FREM , MVT::f32, Expand); + setOperationAction(ISD::FSINCOS, MVT::f64, Expand); + setOperationAction(ISD::FSINCOS, MVT::f32, Expand); + + // In V4, we have double word add/sub with carry. The problem with + // modelling this instruction is that it produces 2 results - Rdd and Px. + // To model update of Px, we will have to use Defs[p0..p3] which will + // cause any predicate live range to spill. So, we pretend we dont't + // have these instructions. + setOperationAction(ISD::ADDE, MVT::i8, Expand); + setOperationAction(ISD::ADDE, MVT::i16, Expand); + setOperationAction(ISD::ADDE, MVT::i32, Expand); + setOperationAction(ISD::ADDE, MVT::i64, Expand); + setOperationAction(ISD::SUBE, MVT::i8, Expand); + setOperationAction(ISD::SUBE, MVT::i16, Expand); + setOperationAction(ISD::SUBE, MVT::i32, Expand); + setOperationAction(ISD::SUBE, MVT::i64, Expand); + setOperationAction(ISD::ADDC, MVT::i8, Expand); + setOperationAction(ISD::ADDC, MVT::i16, Expand); + setOperationAction(ISD::ADDC, MVT::i32, Expand); + setOperationAction(ISD::ADDC, MVT::i64, Expand); + setOperationAction(ISD::SUBC, MVT::i8, Expand); + setOperationAction(ISD::SUBC, MVT::i16, Expand); + setOperationAction(ISD::SUBC, MVT::i32, Expand); + setOperationAction(ISD::SUBC, MVT::i64, Expand); + setOperationAction(ISD::CTPOP, MVT::i32, Expand); + setOperationAction(ISD::CTPOP, MVT::i64, Expand); setOperationAction(ISD::CTTZ , MVT::i32, Expand); + setOperationAction(ISD::CTTZ , MVT::i64, Expand); setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand); + setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Expand); setOperationAction(ISD::CTLZ , MVT::i32, Expand); + setOperationAction(ISD::CTLZ , MVT::i64, Expand); setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand); + setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Expand); setOperationAction(ISD::ROTL , MVT::i32, Expand); setOperationAction(ISD::ROTR , MVT::i32, Expand); setOperationAction(ISD::BSWAP, MVT::i32, Expand); @@ -1430,6 +1480,8 @@ HexagonTargetLowering::getTargetNodeName(unsigned Opcode) const { switch (Opcode) { default: return 0; case HexagonISD::CONST32: return "HexagonISD::CONST32"; + case HexagonISD::CONST32_GP: return "HexagonISD::CONST32_GP"; + case HexagonISD::CONST32_Int_Real: return "HexagonISD::CONST32_Int_Real"; case HexagonISD::ADJDYNALLOC: return "HexagonISD::ADJDYNALLOC"; case HexagonISD::CMPICC: return "HexagonISD::CMPICC"; case HexagonISD::CMPFCC: return "HexagonISD::CMPFCC"; @@ -1478,6 +1530,7 @@ HexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { case ISD::MEMBARRIER: return LowerMEMBARRIER(Op, DAG); case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG); case ISD::GlobalAddress: return LowerGLOBALADDRESS(Op, DAG); + case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); case ISD::VASTART: return LowerVASTART(Op, DAG); case ISD::BR_JT: return LowerBR_JT(Op, DAG); diff --git a/lib/Target/Hexagon/HexagonISelLowering.h b/lib/Target/Hexagon/HexagonISelLowering.h index 14254ce742..3279cc6524 100644 --- a/lib/Target/Hexagon/HexagonISelLowering.h +++ b/lib/Target/Hexagon/HexagonISelLowering.h @@ -16,8 +16,8 @@ #define Hexagon_ISELLOWERING_H #include "Hexagon.h" -#include "llvm/CallingConv.h" #include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/IR/CallingConv.h" #include "llvm/Target/TargetLowering.h" namespace llvm { @@ -27,6 +27,7 @@ namespace llvm { CONST32, CONST32_GP, // For marking data present in GP. + CONST32_Int_Real, FCONST32, SETCC, ADJDYNALLOC, @@ -52,6 +53,8 @@ namespace llvm { WrapperCP, WrapperCombineII, WrapperCombineRR, + WrapperCombineRI_V4, + WrapperCombineIR_V4, WrapperPackhl, WrapperSplatB, WrapperSplatH, @@ -104,6 +107,7 @@ namespace llvm { DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const; SDValue LowerGLOBALADDRESS(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl<SDValue> &InVals) const; diff --git a/lib/Target/Hexagon/HexagonInstrFormats.td b/lib/Target/Hexagon/HexagonInstrFormats.td index 71c620b131..587fa7d7f1 100644 --- a/lib/Target/Hexagon/HexagonInstrFormats.td +++ b/lib/Target/Hexagon/HexagonInstrFormats.td @@ -13,19 +13,19 @@ // *** Must match HexagonBaseInfo.h *** //===----------------------------------------------------------------------===// -class Type<bits<5> t> { +class IType<bits<5> t> { bits<5> Value = t; } -def TypePSEUDO : Type<0>; -def TypeALU32 : Type<1>; -def TypeCR : Type<2>; -def TypeJR : Type<3>; -def TypeJ : Type<4>; -def TypeLD : Type<5>; -def TypeST : Type<6>; -def TypeSYSTEM : Type<7>; -def TypeXTYPE : Type<8>; -def TypeMARKER : Type<31>; +def TypePSEUDO : IType<0>; +def TypeALU32 : IType<1>; +def TypeCR : IType<2>; +def TypeJR : IType<3>; +def TypeJ : IType<4>; +def TypeLD : IType<5>; +def TypeST : IType<6>; +def TypeSYSTEM : IType<7>; +def TypeXTYPE : IType<8>; +def TypeENDLOOP: IType<31>; // Maintain list of valid subtargets for each instruction. class SubTarget<bits<4> value> { @@ -44,8 +44,8 @@ def HasV5SubT : SubTarget<0x8>; def NoV5SubT : SubTarget<0x7>; // Addressing modes for load/store instructions -class AddrModeType<bits<4> value> { - bits<4> Value = value; +class AddrModeType<bits<3> value> { + bits<3> Value = value; } def NoAddrMode : AddrModeType<0>; // No addressing mode @@ -55,14 +55,35 @@ def BaseImmOffset : AddrModeType<3>; // Indirect with offset def BaseLongOffset : AddrModeType<4>; // Indirect with long offset def BaseRegOffset : AddrModeType<5>; // Indirect with register offset +class MemAccessSize<bits<3> value> { + bits<3> Value = value; +} + +def NoMemAccess : MemAccessSize<0>;// Not a memory acces instruction. +def ByteAccess : MemAccessSize<1>;// Byte access instruction (memb). +def HalfWordAccess : MemAccessSize<2>;// Half word access instruction (memh). +def WordAccess : MemAccessSize<3>;// Word access instrution (memw). +def DoubleWordAccess : MemAccessSize<4>;// Double word access instruction (memd) + + //===----------------------------------------------------------------------===// // Intruction Class Declaration + //===----------------------------------------------------------------------===// -class InstHexagon<dag outs, dag ins, string asmstr, list<dag> pattern, - string cstr, InstrItinClass itin, Type type> : Instruction { - field bits<32> Inst; +class OpcodeHexagon { + field bits<32> Inst = ?; // Default to an invalid insn. + bits<4> IClass = 0; // ICLASS + bits<2> IParse = 0; // Parse bits. + + let Inst{31-28} = IClass; + let Inst{15-14} = IParse; + + bits<1> zero = 0; +} +class InstHexagon<dag outs, dag ins, string asmstr, list<dag> pattern, + string cstr, InstrItinClass itin, IType type> + : Instruction, OpcodeHexagon { let Namespace = "Hexagon"; dag OutOperandList = outs; @@ -73,48 +94,63 @@ class InstHexagon<dag outs, dag ins, string asmstr, list<dag> pattern, let Itinerary = itin; let Size = 4; - // *** Must match HexagonBaseInfo.h *** + // *** Must match MCTargetDesc/HexagonBaseInfo.h *** + // Instruction type according to the ISA. - Type HexagonType = type; - let TSFlags{4-0} = HexagonType.Value; + IType Type = type; + let TSFlags{4-0} = Type.Value; + // Solo instructions, i.e., those that cannot be in a packet with others. - bits<1> isHexagonSolo = 0; - let TSFlags{5} = isHexagonSolo; + bits<1> isSolo = 0; + let TSFlags{5} = isSolo; + // Predicated instructions. bits<1> isPredicated = 0; let TSFlags{6} = isPredicated; + bits<1> isPredicatedFalse = 0; + let TSFlags{7} = isPredicatedFalse; bits<1> isPredicatedNew = 0; - let TSFlags{7} = isPredicatedNew; - - // Stores that can be newified. + let TSFlags{8} = isPredicatedNew; + + // New-value insn helper fields. + bits<1> isNewValue = 0; + let TSFlags{9} = isNewValue; // New-value consumer insn. + bits<1> hasNewValue = 0; + let TSFlags{10} = hasNewValue; // New-value producer insn. + bits<3> opNewValue = 0; + let TSFlags{13-11} = opNewValue; // New-value produced operand. + bits<2> opNewBits = 0; + let TSFlags{15-14} = opNewBits; // New-value opcode bits location: 0, 8, 16. bits<1> isNVStorable = 0; - let TSFlags{8} = isNVStorable; - - // New-value store instructions. + let TSFlags{16} = isNVStorable; // Store that can become new-value store. bits<1> isNVStore = 0; - let TSFlags{9} = isNVStore; + let TSFlags{17} = isNVStore; // New-value store insn. // Immediate extender helper fields. bits<1> isExtendable = 0; - let TSFlags{10} = isExtendable; // Insn may be extended. + let TSFlags{18} = isExtendable; // Insn may be extended. bits<1> isExtended = 0; - let TSFlags{11} = isExtended; // Insn must be extended. + let TSFlags{19} = isExtended; // Insn must be extended. bits<3> opExtendable = 0; - let TSFlags{14-12} = opExtendable; // Which operand may be extended. + let TSFlags{22-20} = opExtendable; // Which operand may be extended. bits<1> isExtentSigned = 0; - let TSFlags{15} = isExtentSigned; // Signed or unsigned range. + let TSFlags{23} = isExtentSigned; // Signed or unsigned range. bits<5> opExtentBits = 0; - let TSFlags{20-16} = opExtentBits; //Number of bits of range before extending. + let TSFlags{28-24} = opExtentBits; //Number of bits of range before extending. // If an instruction is valid on a subtarget (v2-v5), set the corresponding // bit from validSubTargets. v2 is the least significant bit. // By default, instruction is valid on all subtargets. SubTarget validSubTargets = HasV2SubT; - let TSFlags{24-21} = validSubTargets.Value; + let TSFlags{32-29} = validSubTargets.Value; - // Addressing mode for load/store instrutions. + // Addressing mode for load/store instructions. AddrModeType addrMode = NoAddrMode; - let TSFlags{28-25} = addrMode.Value; + let TSFlags{35-33} = addrMode.Value; + + // Memory access size for mem access instructions (load/store) + MemAccessSize accessSize = NoMemAccess; + let TSFlags{38-36} = accessSize.Value; // Fields used for relation models. string BaseOpcode = ""; @@ -124,6 +160,11 @@ class InstHexagon<dag outs, dag ins, string asmstr, list<dag> pattern, string InputType = ""; // Input is "imm" or "reg" type. string isMEMri = "false"; // Set to "true" for load/store with MEMri operand. string isFloat = "false"; // Set to "true" for the floating-point load/store. + string isBrTaken = ""; // Set to "true"/"false" for jump instructions + + let PredSense = !if(isPredicated, !if(isPredicatedFalse, "false", "true"), + ""); + let PNewValue = !if(isPredicatedNew, "new", ""); // *** Must match MCTargetDesc/HexagonBaseInfo.h *** } @@ -134,187 +175,143 @@ class InstHexagon<dag outs, dag ins, string asmstr, list<dag> pattern, // LD Instruction Class in V2/V3/V4. // Definition of the instruction class NOT CHANGED. -class LDInst<dag outs, dag ins, string asmstr, list<dag> pattern> - : InstHexagon<outs, ins, asmstr, pattern, "", LD, TypeLD> { - bits<5> rd; - bits<5> rs; - bits<13> imm13; -} +class LDInst<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : InstHexagon<outs, ins, asmstr, pattern, cstr, LD, TypeLD>; -class LDInst2<dag outs, dag ins, string asmstr, list<dag> pattern> - : InstHexagon<outs, ins, asmstr, pattern, "", LD, TypeLD> { - bits<5> rd; - bits<5> rs; - bits<13> imm13; - let mayLoad = 1; -} +let mayLoad = 1 in +class LDInst2<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : LDInst<outs, ins, asmstr, pattern, cstr>; + +class CONSTLDInst<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : LDInst<outs, ins, asmstr, pattern, cstr>; // LD Instruction Class in V2/V3/V4. // Definition of the instruction class NOT CHANGED. -class LDInstPost<dag outs, dag ins, string asmstr, list<dag> pattern, - string cstr> - : InstHexagon<outs, ins, asmstr, pattern, cstr, LD, TypeLD> { - bits<5> rd; - bits<5> rs; - bits<5> rt; - bits<13> imm13; -} +class LDInstPost<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : LDInst<outs, ins, asmstr, pattern, cstr>; + +let mayLoad = 1 in +class LD0Inst<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : LDInst<outs, ins, asmstr, pattern, cstr>; // ST Instruction Class in V2/V3 can take SLOT0 only. // ST Instruction Class in V4 can take SLOT0 & SLOT1. // Definition of the instruction class CHANGED from V2/V3 to V4. -class STInst<dag outs, dag ins, string asmstr, list<dag> pattern> - : InstHexagon<outs, ins, asmstr, pattern, "", ST, TypeST> { - bits<5> rd; - bits<5> rs; - bits<13> imm13; -} +let mayStore = 1 in +class STInst<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : InstHexagon<outs, ins, asmstr, pattern, cstr, ST, TypeST>; -class STInst2<dag outs, dag ins, string asmstr, list<dag> pattern> - : InstHexagon<outs, ins, asmstr, pattern, "", ST, TypeST> { - bits<5> rd; - bits<5> rs; - bits<13> imm13; - let mayStore = 1; -} +class STInst2<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : STInst<outs, ins, asmstr, pattern, cstr>; -// SYSTEM Instruction Class in V4 can take SLOT0 only -// In V2/V3 we used ST for this but in v4 ST can take SLOT0 or SLOT1. -class SYSInst<dag outs, dag ins, string asmstr, list<dag> pattern> - : InstHexagon<outs, ins, asmstr, pattern, "", SYS, TypeSYSTEM> { - bits<5> rd; - bits<5> rs; - bits<13> imm13; -} +let mayStore = 1 in +class ST0Inst<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : InstHexagon<outs, ins, asmstr, pattern, cstr, ST0, TypeST>; // ST Instruction Class in V2/V3 can take SLOT0 only. // ST Instruction Class in V4 can take SLOT0 & SLOT1. // Definition of the instruction class CHANGED from V2/V3 to V4. -class STInstPost<dag outs, dag ins, string asmstr, list<dag> pattern, - string cstr> - : InstHexagon<outs, ins, asmstr, pattern, cstr, ST, TypeST> { - bits<5> rd; - bits<5> rs; - bits<5> rt; - bits<13> imm13; -} +class STInstPost<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : STInst<outs, ins, asmstr, pattern, cstr>; + +// SYSTEM Instruction Class in V4 can take SLOT0 only +// In V2/V3 we used ST for this but in v4 ST can take SLOT0 or SLOT1. +class SYSInst<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : InstHexagon<outs, ins, asmstr, pattern, cstr, SYS, TypeSYSTEM>; // ALU32 Instruction Class in V2/V3/V4. // Definition of the instruction class NOT CHANGED. -class ALU32Type<dag outs, dag ins, string asmstr, list<dag> pattern> - : InstHexagon<outs, ins, asmstr, pattern, "", ALU32, TypeALU32> { - bits<5> rd; - bits<5> rs; - bits<5> rt; - bits<16> imm16; - bits<16> imm16_2; -} +class ALU32Inst<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : InstHexagon<outs, ins, asmstr, pattern, cstr, ALU32, TypeALU32>; // ALU64 Instruction Class in V2/V3. // XTYPE Instruction Class in V4. // Definition of the instruction class NOT CHANGED. // Name of the Instruction Class changed from ALU64 to XTYPE from V2/V3 to V4. -class ALU64Type<dag outs, dag ins, string asmstr, list<dag> pattern> - : InstHexagon<outs, ins, asmstr, pattern, "", ALU64, TypeXTYPE> { - bits<5> rd; - bits<5> rs; - bits<5> rt; - bits<16> imm16; - bits<16> imm16_2; -} +class ALU64Inst<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : InstHexagon<outs, ins, asmstr, pattern, cstr, ALU64, TypeXTYPE>; + +class ALU64_acc<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : ALU64Inst<outs, ins, asmstr, pattern, cstr>; -class ALU64_acc<dag outs, dag ins, string asmstr, list<dag> pattern, - string cstr> - : InstHexagon<outs, ins, asmstr, pattern, cstr, ALU64, TypeXTYPE> { - bits<5> rd; - bits<5> rs; - bits<5> rt; - bits<16> imm16; - bits<16> imm16_2; -} // M Instruction Class in V2/V3. // XTYPE Instruction Class in V4. // Definition of the instruction class NOT CHANGED. // Name of the Instruction Class changed from M to XTYPE from V2/V3 to V4. -class MInst<dag outs, dag ins, string asmstr, list<dag> pattern> - : InstHexagon<outs, ins, asmstr, pattern, "", M, TypeXTYPE> { - bits<5> rd; - bits<5> rs; - bits<5> rt; -} +class MInst<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : InstHexagon<outs, ins, asmstr, pattern, cstr, M, TypeXTYPE>; // M Instruction Class in V2/V3. // XTYPE Instruction Class in V4. // Definition of the instruction class NOT CHANGED. // Name of the Instruction Class changed from M to XTYPE from V2/V3 to V4. -class MInst_acc<dag outs, dag ins, string asmstr, list<dag> pattern, - string cstr> - : InstHexagon<outs, ins, asmstr, pattern, cstr, M, TypeXTYPE> { - bits<5> rd; - bits<5> rs; - bits<5> rt; -} +class MInst_acc<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : MInst<outs, ins, asmstr, pattern, cstr>; // S Instruction Class in V2/V3. // XTYPE Instruction Class in V4. // Definition of the instruction class NOT CHANGED. // Name of the Instruction Class changed from S to XTYPE from V2/V3 to V4. -class SInst<dag outs, dag ins, string asmstr, list<dag> pattern> - : InstHexagon<outs, ins, asmstr, pattern, "", S, TypeXTYPE> { - bits<5> rd; - bits<5> rs; - bits<5> rt; -} +class SInst<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : InstHexagon<outs, ins, asmstr, pattern, cstr, S, TypeXTYPE>; // S Instruction Class in V2/V3. // XTYPE Instruction Class in V4. // Definition of the instruction class NOT CHANGED. // Name of the Instruction Class changed from S to XTYPE from V2/V3 to V4. -class SInst_acc<dag outs, dag ins, string asmstr, list<dag> pattern, - string cstr> - : InstHexagon<outs, ins, asmstr, pattern, cstr, S, TypeXTYPE> { -// : InstHexagon<outs, ins, asmstr, pattern, cstr, S> { -// : InstHexagon<outs, ins, asmstr, pattern, cstr, !if(V4T, XTYPE_V4, S)> { - bits<5> rd; - bits<5> rs; - bits<5> rt; -} +class SInst_acc<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : SInst<outs, ins, asmstr, pattern, cstr>; // J Instruction Class in V2/V3/V4. // Definition of the instruction class NOT CHANGED. -class JType<dag outs, dag ins, string asmstr, list<dag> pattern> - : InstHexagon<outs, ins, asmstr, pattern, "", J, TypeJ> { - bits<16> imm16; -} +class JInst<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : InstHexagon<outs, ins, asmstr, pattern, cstr, J, TypeJ>; // JR Instruction Class in V2/V3/V4. // Definition of the instruction class NOT CHANGED. -class JRType<dag outs, dag ins, string asmstr, list<dag> pattern> - : InstHexagon<outs, ins, asmstr, pattern, "", JR, TypeJR> { - bits<5> rs; - bits<5> pu; // Predicate register -} +class JRInst<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : InstHexagon<outs, ins, asmstr, pattern, cstr, JR, TypeJR>; // CR Instruction Class in V2/V3/V4. // Definition of the instruction class NOT CHANGED. -class CRInst<dag outs, dag ins, string asmstr, list<dag> pattern> - : InstHexagon<outs, ins, asmstr, pattern, "", CR, TypeCR> { - bits<5> rs; - bits<10> imm10; -} +class CRInst<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : InstHexagon<outs, ins, asmstr, pattern, cstr, CR, TypeCR>; -class Marker<dag outs, dag ins, string asmstr, list<dag> pattern> - : InstHexagon<outs, ins, asmstr, pattern, "", MARKER, TypeMARKER> { - let isCodeGenOnly = 1; - let isPseudo = 1; -} +let isCodeGenOnly = 1, isPseudo = 1 in +class Endloop<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : InstHexagon<outs, ins, asmstr, pattern, cstr, ENDLOOP, TypeENDLOOP>; -class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern> - : InstHexagon<outs, ins, asmstr, pattern, "", PSEUDO, TypePSEUDO> { - let isCodeGenOnly = 1; - let isPseudo = 1; -} +let isCodeGenOnly = 1, isPseudo = 1 in +class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : InstHexagon<outs, ins, asmstr, pattern, cstr, PSEUDO, TypePSEUDO>; + +let isCodeGenOnly = 1, isPseudo = 1 in +class PseudoM<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr=""> + : InstHexagon<outs, ins, asmstr, pattern, cstr, PSEUDOM, TypePSEUDO>; //===----------------------------------------------------------------------===// // Intruction Classes Definitions - @@ -324,75 +321,52 @@ class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern> // // ALU32 patterns //. -class ALU32_rr<dag outs, dag ins, string asmstr, list<dag> pattern> - : ALU32Type<outs, ins, asmstr, pattern> { -} +class ALU32_rr<dag outs, dag ins, string asmstr, list<dag> pattern, + string cstr = ""> + : ALU32Inst<outs, ins, asmstr, pattern, cstr>; -class ALU32_ir<dag outs, dag ins, string asmstr, list<dag> pattern> - : ALU32Type<outs, ins, asmstr, pattern> { - let rt{0-4} = 0; -} +class ALU32_ir<dag outs, dag ins, string asmstr, list<dag> pattern, + string cstr = ""> + : ALU32Inst<outs, ins, asmstr, pattern, cstr>; -class ALU32_ri<dag outs, dag ins, string asmstr, list<dag> pattern> - : ALU32Type<outs, ins, asmstr, pattern> { - let rt{0-4} = 0; -} +class ALU32_ri<dag outs, dag ins, string asmstr, list<dag> pattern, + string cstr = ""> + : ALU32Inst<outs, ins, asmstr, pattern, cstr>; -class ALU32_ii<dag outs, dag ins, string asmstr, list<dag> pattern> - : ALU32Type<outs, ins, asmstr, pattern> { - let rt{0-4} = 0; -} +class ALU32_ii<dag outs, dag ins, string asmstr, list<dag> pattern, + string cstr = ""> + : ALU32Inst<outs, ins, asmstr, pattern, cstr>; // // ALU64 patterns. // -class ALU64_rr<dag outs, dag ins, string asmstr, list<dag> pattern> - : ALU64Type<outs, ins, asmstr, pattern> { -} - -class ALU64_ri<dag outs, dag ins, string asmstr, list<dag> pattern> - : ALU64Type<outs, ins, asmstr, pattern> { - let rt{0-4} = 0; -} - -// J Type Instructions. -class JInst<dag outs, dag ins, string asmstr, list<dag> pattern> - : JType<outs, ins, asmstr, pattern> { -} - -// JR type Instructions. -class JRInst<dag outs, dag ins, string asmstr, list<dag> pattern> - : JRType<outs, ins, asmstr, pattern> { -} +class ALU64_rr<dag outs, dag ins, string asmstr, list<dag> pattern, + string cstr = ""> + : ALU64Inst<outs, ins, asmstr, pattern, cstr>; +class ALU64_ri<dag outs, dag ins, string asmstr, list<dag> pattern, + string cstr = ""> + : ALU64Inst<outs, ins, asmstr, pattern, cstr>; // Post increment ST Instruction. -class STInstPI<dag outs, dag ins, string asmstr, list<dag> pattern, - string cstr> - : STInstPost<outs, ins, asmstr, pattern, cstr> { - let rt{0-4} = 0; -} +class STInstPI<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : STInst<outs, ins, asmstr, pattern, cstr>; -class STInst2PI<dag outs, dag ins, string asmstr, list<dag> pattern, - string cstr> - : STInstPost<outs, ins, asmstr, pattern, cstr> { - let rt{0-4} = 0; - let mayStore = 1; -} +let mayStore = 1 in +class STInst2PI<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : STInst<outs, ins, asmstr, pattern, cstr>; // Post increment LD Instruction. -class LDInstPI<dag outs, dag ins, string asmstr, list<dag> pattern, - string cstr> - : LDInstPost<outs, ins, asmstr, pattern, cstr> { - let rt{0-4} = 0; -} - -class LDInst2PI<dag outs, dag ins, string asmstr, list<dag> pattern, - string cstr> - : LDInstPost<outs, ins, asmstr, pattern, cstr> { - let rt{0-4} = 0; - let mayLoad = 1; -} +class LDInstPI<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : LDInst<outs, ins, asmstr, pattern, cstr>; + +let mayLoad = 1 in +class LDInst2PI<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : LDInst<outs, ins, asmstr, pattern, cstr>; //===----------------------------------------------------------------------===// // V4 Instruction Format Definitions + diff --git a/lib/Target/Hexagon/HexagonInstrFormatsV4.td b/lib/Target/Hexagon/HexagonInstrFormatsV4.td index 49741a3d1b..9fda0da916 100644 --- a/lib/Target/Hexagon/HexagonInstrFormatsV4.td +++ b/lib/Target/Hexagon/HexagonInstrFormatsV4.td @@ -17,9 +17,9 @@ // *** Must match BaseInfo.h *** //----------------------------------------------------------------------------// -def TypeMEMOP : Type<9>; -def TypeNV : Type<10>; -def TypePREFIX : Type<30>; +def TypeMEMOP : IType<9>; +def TypeNV : IType<10>; +def TypePREFIX : IType<30>; //----------------------------------------------------------------------------// // Intruction Classes Definitions + @@ -28,40 +28,39 @@ def TypePREFIX : Type<30>; // // NV type instructions. // -class NVInst_V4<dag outs, dag ins, string asmstr, list<dag> pattern> - : InstHexagon<outs, ins, asmstr, pattern, "", NV_V4, TypeNV> { - bits<5> rd; - bits<5> rs; - bits<13> imm13; -} +class NVInst<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : InstHexagon<outs, ins, asmstr, pattern, cstr, NV_V4, TypeNV>; + +class NVInst_V4<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : NVInst<outs, ins, asmstr, pattern, cstr>; // Definition of Post increment new value store. -class NVInstPost_V4<dag outs, dag ins, string asmstr, list<dag> pattern, - string cstr> - : InstHexagon<outs, ins, asmstr, pattern, cstr, NV_V4, TypeNV> { - bits<5> rd; - bits<5> rs; - bits<5> rt; - bits<13> imm13; -} +class NVInstPost_V4<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : NVInst<outs, ins, asmstr, pattern, cstr>; // Post increment ST Instruction. -class NVInstPI_V4<dag outs, dag ins, string asmstr, list<dag> pattern, - string cstr> - : NVInstPost_V4<outs, ins, asmstr, pattern, cstr> { - let rt{0-4} = 0; -} +let mayStore = 1 in +class NVInstPI_V4<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : NVInst<outs, ins, asmstr, pattern, cstr>; + +// New-value conditional branch. +class NCJInst<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : NVInst<outs, ins, asmstr, pattern, cstr>; -class MEMInst_V4<dag outs, dag ins, string asmstr, list<dag> pattern> - : InstHexagon<outs, ins, asmstr, pattern, "", MEM_V4, TypeMEMOP> { - bits<5> rd; - bits<5> rs; - bits<6> imm6; -} +let mayLoad = 1, mayStore = 1 in +class MEMInst<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : InstHexagon<outs, ins, asmstr, pattern, cstr, MEM_V4, TypeMEMOP>; -class Immext<dag outs, dag ins, string asmstr, list<dag> pattern> - : InstHexagon<outs, ins, asmstr, pattern, "", PREFIX, TypePREFIX> { - let isCodeGenOnly = 1; +class MEMInst_V4<dag outs, dag ins, string asmstr, list<dag> pattern = [], + string cstr = ""> + : MEMInst<outs, ins, asmstr, pattern, cstr>; - bits<26> imm26; -} +let isCodeGenOnly = 1 in +class EXTENDERInst<dag outs, dag ins, string asmstr, list<dag> pattern = []> + : InstHexagon<outs, ins, asmstr, pattern, "", PREFIX, TypePREFIX>; diff --git a/lib/Target/Hexagon/HexagonInstrInfo.cpp b/lib/Target/Hexagon/HexagonInstrInfo.cpp index 3b1ae098f8..4c0f93c6cd 100644 --- a/lib/Target/Hexagon/HexagonInstrInfo.cpp +++ b/lib/Target/Hexagon/HexagonInstrInfo.cpp @@ -305,6 +305,88 @@ unsigned HexagonInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { } +/// \brief For a comparison instruction, return the source registers in +/// \p SrcReg and \p SrcReg2 if having two register operands, and the value it +/// compares against in CmpValue. Return true if the comparison instruction +/// can be analyzed. +bool HexagonInstrInfo::analyzeCompare(const MachineInstr *MI, + unsigned &SrcReg, unsigned &SrcReg2, + int &Mask, int &Value) const { + unsigned Opc = MI->getOpcode(); + + // Set mask and the first source register. + switch (Opc) { + case Hexagon::CMPEHexagon4rr: + case Hexagon::CMPEQri: + case Hexagon::CMPEQrr: + case Hexagon::CMPGT64rr: + case Hexagon::CMPGTU64rr: + case Hexagon::CMPGTUri: + case Hexagon::CMPGTUrr: + case Hexagon::CMPGTri: + case Hexagon::CMPGTrr: + case Hexagon::CMPLTUrr: + case Hexagon::CMPLTrr: + SrcReg = MI->getOperand(1).getReg(); + Mask = ~0; + break; + case Hexagon::CMPbEQri_V4: + case Hexagon::CMPbEQrr_sbsb_V4: + case Hexagon::CMPbEQrr_ubub_V4: + case Hexagon::CMPbGTUri_V4: + case Hexagon::CMPbGTUrr_V4: + case Hexagon::CMPbGTrr_V4: + SrcReg = MI->getOperand(1).getReg(); + Mask = 0xFF; + break; + case Hexagon::CMPhEQri_V4: + case Hexagon::CMPhEQrr_shl_V4: + case Hexagon::CMPhEQrr_xor_V4: + case Hexagon::CMPhGTUri_V4: + case Hexagon::CMPhGTUrr_V4: + case Hexagon::CMPhGTrr_shl_V4: + SrcReg = MI->getOperand(1).getReg(); + Mask = 0xFFFF; + break; + } + + // Set the value/second source register. + switch (Opc) { + case Hexagon::CMPEHexagon4rr: + case Hexagon::CMPEQrr: + case Hexagon::CMPGT64rr: + case Hexagon::CMPGTU64rr: + case Hexagon::CMPGTUrr: + case Hexagon::CMPGTrr: + case Hexagon::CMPbEQrr_sbsb_V4: + case Hexagon::CMPbEQrr_ubub_V4: + case Hexagon::CMPbGTUrr_V4: + case Hexagon::CMPbGTrr_V4: + case Hexagon::CMPhEQrr_shl_V4: + case Hexagon::CMPhEQrr_xor_V4: + case Hexagon::CMPhGTUrr_V4: + case Hexagon::CMPhGTrr_shl_V4: + case Hexagon::CMPLTUrr: + case Hexagon::CMPLTrr: + SrcReg2 = MI->getOperand(2).getReg(); + return true; + + case Hexagon::CMPEQri: + case Hexagon::CMPGTUri: + case Hexagon::CMPGTri: + case Hexagon::CMPbEQri_V4: + case Hexagon::CMPbGTUri_V4: + case Hexagon::CMPhEQri_V4: + case Hexagon::CMPhGTUri_V4: + SrcReg2 = 0; + Value = MI->getOperand(2).getImm(); + return true; + } + + return false; +} + + void HexagonInstrInfo::copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, unsigned DestReg, unsigned SrcReg, @@ -344,6 +426,18 @@ void HexagonInstrInfo::copyPhysReg(MachineBasicBlock &MBB, BuildMI(MBB, I, DL, get(Hexagon::TFCR), DestReg).addReg(SrcReg); return; } + if (Hexagon::PredRegsRegClass.contains(SrcReg) && + Hexagon::IntRegsRegClass.contains(DestReg)) { + BuildMI(MBB, I, DL, get(Hexagon::TFR_RsPd), DestReg). + addReg(SrcReg, getKillRegState(KillSrc)); + return; + } + if (Hexagon::IntRegsRegClass.contains(SrcReg) && + Hexagon::PredRegsRegClass.contains(DestReg)) { + BuildMI(MBB, I, DL, get(Hexagon::TFR_PdRs), DestReg). + addReg(SrcReg, getKillRegState(KillSrc)); + return; + } llvm_unreachable("Unimplemented"); } @@ -463,270 +557,43 @@ unsigned HexagonInstrInfo::createVR(MachineFunction* MF, MVT VT) const { } bool HexagonInstrInfo::isExtendable(const MachineInstr *MI) const { - switch(MI->getOpcode()) { - default: return false; - // JMP_EQri - case Hexagon::JMP_EQriPt_nv_V4: - case Hexagon::JMP_EQriPnt_nv_V4: - case Hexagon::JMP_EQriNotPt_nv_V4: - case Hexagon::JMP_EQriNotPnt_nv_V4: - - // JMP_EQri - with -1 - case Hexagon::JMP_EQriPtneg_nv_V4: - case Hexagon::JMP_EQriPntneg_nv_V4: - case Hexagon::JMP_EQriNotPtneg_nv_V4: - case Hexagon::JMP_EQriNotPntneg_nv_V4: - - // JMP_EQrr - case Hexagon::JMP_EQrrPt_nv_V4: - case Hexagon::JMP_EQrrPnt_nv_V4: - case Hexagon::JMP_EQrrNotPt_nv_V4: - case Hexagon::JMP_EQrrNotPnt_nv_V4: - - // JMP_GTri - case Hexagon::JMP_GTriPt_nv_V4: - case Hexagon::JMP_GTriPnt_nv_V4: - case Hexagon::JMP_GTriNotPt_nv_V4: - case Hexagon::JMP_GTriNotPnt_nv_V4: - - // JMP_GTri - with -1 - case Hexagon::JMP_GTriPtneg_nv_V4: - case Hexagon::JMP_GTriPntneg_nv_V4: - case Hexagon::JMP_GTriNotPtneg_nv_V4: - case Hexagon::JMP_GTriNotPntneg_nv_V4: - - // JMP_GTrr - case Hexagon::JMP_GTrrPt_nv_V4: - case Hexagon::JMP_GTrrPnt_nv_V4: - case Hexagon::JMP_GTrrNotPt_nv_V4: - case Hexagon::JMP_GTrrNotPnt_nv_V4: - - // JMP_GTrrdn - case Hexagon::JMP_GTrrdnPt_nv_V4: - case Hexagon::JMP_GTrrdnPnt_nv_V4: - case Hexagon::JMP_GTrrdnNotPt_nv_V4: - case Hexagon::JMP_GTrrdnNotPnt_nv_V4: - - // JMP_GTUri - case Hexagon::JMP_GTUriPt_nv_V4: - case Hexagon::JMP_GTUriPnt_nv_V4: - case Hexagon::JMP_GTUriNotPt_nv_V4: - case Hexagon::JMP_GTUriNotPnt_nv_V4: - - // JMP_GTUrr - case Hexagon::JMP_GTUrrPt_nv_V4: - case Hexagon::JMP_GTUrrPnt_nv_V4: - case Hexagon::JMP_GTUrrNotPt_nv_V4: - case Hexagon::JMP_GTUrrNotPnt_nv_V4: + // Constant extenders are allowed only for V4 and above. + if (!Subtarget.hasV4TOps()) + return false; - // JMP_GTUrrdn - case Hexagon::JMP_GTUrrdnPt_nv_V4: - case Hexagon::JMP_GTUrrdnPnt_nv_V4: - case Hexagon::JMP_GTUrrdnNotPt_nv_V4: - case Hexagon::JMP_GTUrrdnNotPnt_nv_V4: + const MCInstrDesc &MID = MI->getDesc(); + const uint64_t F = MID.TSFlags; + if ((F >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask) + return true; - // TFR_FI + // TODO: This is largely obsolete now. Will need to be removed + // in consecutive patches. + switch(MI->getOpcode()) { + // TFR_FI Remains a special case. case Hexagon::TFR_FI: return true; + default: + return false; } + return false; } +// This returns true in two cases: +// - The OP code itself indicates that this is an extended instruction. +// - One of MOs has been marked with HMOTF_ConstExtended flag. bool HexagonInstrInfo::isExtended(const MachineInstr *MI) const { - switch(MI->getOpcode()) { - default: return false; - // JMP_EQri - case Hexagon::JMP_EQriPt_ie_nv_V4: - case Hexagon::JMP_EQriPnt_ie_nv_V4: - case Hexagon::JMP_EQriNotPt_ie_nv_V4: - case Hexagon::JMP_EQriNotPnt_ie_nv_V4: - - // JMP_EQri - with -1 - case Hexagon::JMP_EQriPtneg_ie_nv_V4: - case Hexagon::JMP_EQriPntneg_ie_nv_V4: - case Hexagon::JMP_EQriNotPtneg_ie_nv_V4: - case Hexagon::JMP_EQriNotPntneg_ie_nv_V4: - - // JMP_EQrr - case Hexagon::JMP_EQrrPt_ie_nv_V4: - case Hexagon::JMP_EQrrPnt_ie_nv_V4: - case Hexagon::JMP_EQrrNotPt_ie_nv_V4: - case Hexagon::JMP_EQrrNotPnt_ie_nv_V4: - - // JMP_GTri - case Hexagon::JMP_GTriPt_ie_nv_V4: - case Hexagon::JMP_GTriPnt_ie_nv_V4: - case Hexagon::JMP_GTriNotPt_ie_nv_V4: - case Hexagon::JMP_GTriNotPnt_ie_nv_V4: - - // JMP_GTri - with -1 - case Hexagon::JMP_GTriPtneg_ie_nv_V4: - case Hexagon::JMP_GTriPntneg_ie_nv_V4: - case Hexagon::JMP_GTriNotPtneg_ie_nv_V4: - case Hexagon::JMP_GTriNotPntneg_ie_nv_V4: - - // JMP_GTrr - case Hexagon::JMP_GTrrPt_ie_nv_V4: - case Hexagon::JMP_GTrrPnt_ie_nv_V4: - case Hexagon::JMP_GTrrNotPt_ie_nv_V4: - case Hexagon::JMP_GTrrNotPnt_ie_nv_V4: - - // JMP_GTrrdn - case Hexagon::JMP_GTrrdnPt_ie_nv_V4: - case Hexagon::JMP_GTrrdnPnt_ie_nv_V4: - case Hexagon::JMP_GTrrdnNotPt_ie_nv_V4: - case Hexagon::JMP_GTrrdnNotPnt_ie_nv_V4: - - // JMP_GTUri - case Hexagon::JMP_GTUriPt_ie_nv_V4: - case Hexagon::JMP_GTUriPnt_ie_nv_V4: - case Hexagon::JMP_GTUriNotPt_ie_nv_V4: - case Hexagon::JMP_GTUriNotPnt_ie_nv_V4: - - // JMP_GTUrr - case Hexagon::JMP_GTUrrPt_ie_nv_V4: - case Hexagon::JMP_GTUrrPnt_ie_nv_V4: - case Hexagon::JMP_GTUrrNotPt_ie_nv_V4: - case Hexagon::JMP_GTUrrNotPnt_ie_nv_V4: - - // JMP_GTUrrdn - case Hexagon::JMP_GTUrrdnPt_ie_nv_V4: - case Hexagon::JMP_GTUrrdnPnt_ie_nv_V4: - case Hexagon::JMP_GTUrrdnNotPt_ie_nv_V4: - case Hexagon::JMP_GTUrrdnNotPnt_ie_nv_V4: - - // V4 absolute set addressing. - case Hexagon::LDrid_abs_setimm_V4: - case Hexagon::LDriw_abs_setimm_V4: - case Hexagon::LDrih_abs_setimm_V4: - case Hexagon::LDrib_abs_setimm_V4: - case Hexagon::LDriuh_abs_setimm_V4: - case Hexagon::LDriub_abs_setimm_V4: - - case Hexagon::STrid_abs_setimm_V4: - case Hexagon::STrib_abs_setimm_V4: - case Hexagon::STrih_abs_setimm_V4: - case Hexagon::STriw_abs_setimm_V4: - - // V4 global address load. - case Hexagon::LDrid_GP_cPt_V4 : - case Hexagon::LDrid_GP_cNotPt_V4 : - case Hexagon::LDrid_GP_cdnPt_V4 : - case Hexagon::LDrid_GP_cdnNotPt_V4 : - case Hexagon::LDrib_GP_cPt_V4 : - case Hexagon::LDrib_GP_cNotPt_V4 : - case Hexagon::LDrib_GP_cdnPt_V4 : - case Hexagon::LDrib_GP_cdnNotPt_V4 : - case Hexagon::LDriub_GP_cPt_V4 : - case Hexagon::LDriub_GP_cNotPt_V4 : - case Hexagon::LDriub_GP_cdnPt_V4 : - case Hexagon::LDriub_GP_cdnNotPt_V4 : - case Hexagon::LDrih_GP_cPt_V4 : - case Hexagon::LDrih_GP_cNotPt_V4 : - case Hexagon::LDrih_GP_cdnPt_V4 : - case Hexagon::LDrih_GP_cdnNotPt_V4 : - case Hexagon::LDriuh_GP_cPt_V4 : - case Hexagon::LDriuh_GP_cNotPt_V4 : - case Hexagon::LDriuh_GP_cdnPt_V4 : - case Hexagon::LDriuh_GP_cdnNotPt_V4 : - case Hexagon::LDriw_GP_cPt_V4 : - case Hexagon::LDriw_GP_cNotPt_V4 : - case Hexagon::LDriw_GP_cdnPt_V4 : - case Hexagon::LDriw_GP_cdnNotPt_V4 : - case Hexagon::LDd_GP_cPt_V4 : - case Hexagon::LDd_GP_cNotPt_V4 : - case Hexagon::LDd_GP_cdnPt_V4 : - case Hexagon::LDd_GP_cdnNotPt_V4 : - case Hexagon::LDb_GP_cPt_V4 : - case Hexagon::LDb_GP_cNotPt_V4 : - case Hexagon::LDb_GP_cdnPt_V4 : - case Hexagon::LDb_GP_cdnNotPt_V4 : - case Hexagon::LDub_GP_cPt_V4 : - case Hexagon::LDub_GP_cNotPt_V4 : - case Hexagon::LDub_GP_cdnPt_V4 : - case Hexagon::LDub_GP_cdnNotPt_V4 : - case Hexagon::LDh_GP_cPt_V4 : - case Hexagon::LDh_GP_cNotPt_V4 : - case Hexagon::LDh_GP_cdnPt_V4 : - case Hexagon::LDh_GP_cdnNotPt_V4 : - case Hexagon::LDuh_GP_cPt_V4 : - case Hexagon::LDuh_GP_cNotPt_V4 : - case Hexagon::LDuh_GP_cdnPt_V4 : - case Hexagon::LDuh_GP_cdnNotPt_V4 : - case Hexagon::LDw_GP_cPt_V4 : - case Hexagon::LDw_GP_cNotPt_V4 : - case Hexagon::LDw_GP_cdnPt_V4 : - case Hexagon::LDw_GP_cdnNotPt_V4 : - - // V4 global address store. - case Hexagon::STrid_GP_cPt_V4 : - case Hexagon::STrid_GP_cNotPt_V4 : - case Hexagon::STrid_GP_cdnPt_V4 : - case Hexagon::STrid_GP_cdnNotPt_V4 : - case Hexagon::STrib_GP_cPt_V4 : - case Hexagon::STrib_GP_cNotPt_V4 : - case Hexagon::STrib_GP_cdnPt_V4 : - case Hexagon::STrib_GP_cdnNotPt_V4 : - case Hexagon::STrih_GP_cPt_V4 : - case Hexagon::STrih_GP_cNotPt_V4 : - case Hexagon::STrih_GP_cdnPt_V4 : - case Hexagon::STrih_GP_cdnNotPt_V4 : - case Hexagon::STriw_GP_cPt_V4 : - case Hexagon::STriw_GP_cNotPt_V4 : - case Hexagon::STriw_GP_cdnPt_V4 : - case Hexagon::STriw_GP_cdnNotPt_V4 : - case Hexagon::STd_GP_cPt_V4 : - case Hexagon::STd_GP_cNotPt_V4 : - case Hexagon::STd_GP_cdnPt_V4 : - case Hexagon::STd_GP_cdnNotPt_V4 : - case Hexagon::STb_GP_cPt_V4 : - case Hexagon::STb_GP_cNotPt_V4 : - case Hexagon::STb_GP_cdnPt_V4 : - case Hexagon::STb_GP_cdnNotPt_V4 : - case Hexagon::STh_GP_cPt_V4 : - case Hexagon::STh_GP_cNotPt_V4 : - case Hexagon::STh_GP_cdnPt_V4 : - case Hexagon::STh_GP_cdnNotPt_V4 : - case Hexagon::STw_GP_cPt_V4 : - case Hexagon::STw_GP_cNotPt_V4 : - case Hexagon::STw_GP_cdnPt_V4 : - case Hexagon::STw_GP_cdnNotPt_V4 : - - // V4 predicated global address new value store. - case Hexagon::STrib_GP_cPt_nv_V4 : - case Hexagon::STrib_GP_cNotPt_nv_V4 : - case Hexagon::STrib_GP_cdnPt_nv_V4 : - case Hexagon::STrib_GP_cdnNotPt_nv_V4 : - case Hexagon::STrih_GP_cPt_nv_V4 : - case Hexagon::STrih_GP_cNotPt_nv_V4 : - case Hexagon::STrih_GP_cdnPt_nv_V4 : - case Hexagon::STrih_GP_cdnNotPt_nv_V4 : - case Hexagon::STriw_GP_cPt_nv_V4 : - case Hexagon::STriw_GP_cNotPt_nv_V4 : - case Hexagon::STriw_GP_cdnPt_nv_V4 : - case Hexagon::STriw_GP_cdnNotPt_nv_V4 : - case Hexagon::STb_GP_cPt_nv_V4 : - case Hexagon::STb_GP_cNotPt_nv_V4 : - case Hexagon::STb_GP_cdnPt_nv_V4 : - case Hexagon::STb_GP_cdnNotPt_nv_V4 : - case Hexagon::STh_GP_cPt_nv_V4 : - case Hexagon::STh_GP_cNotPt_nv_V4 : - case Hexagon::STh_GP_cdnPt_nv_V4 : - case Hexagon::STh_GP_cdnNotPt_nv_V4 : - case Hexagon::STw_GP_cPt_nv_V4 : - case Hexagon::STw_GP_cNotPt_nv_V4 : - case Hexagon::STw_GP_cdnPt_nv_V4 : - case Hexagon::STw_GP_cdnNotPt_nv_V4 : - - // TFR_FI - case Hexagon::TFR_FI_immext_V4: - - // TFRI_F - case Hexagon::TFRI_f: - case Hexagon::TFRI_cPt_f: - case Hexagon::TFRI_cNotPt_f: - case Hexagon::CONST64_Float_Real: + // First check if this is permanently extended op code. + const uint64_t F = MI->getDesc().TSFlags; + if ((F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask) + return true; + // Use MO operand flags to determine if one of MI's operands + // has HMOTF_ConstExtended flag set. + for (MachineInstr::const_mop_iterator I = MI->operands_begin(), + E = MI->operands_end(); I != E; ++I) { + if (I->getTargetFlags() && HexagonII::HMOTF_ConstExtended) return true; } + return false; } bool HexagonInstrInfo::isNewValueJump(const MachineInstr *MI) const { @@ -835,258 +702,6 @@ bool HexagonInstrInfo::isNewValueJump(const MachineInstr *MI) const { } } -unsigned HexagonInstrInfo::getImmExtForm(const MachineInstr* MI) const { - switch(MI->getOpcode()) { - default: llvm_unreachable("Unknown type of instruction."); - // JMP_EQri - case Hexagon::JMP_EQriPt_nv_V4: - return Hexagon::JMP_EQriPt_ie_nv_V4; - case Hexagon::JMP_EQriNotPt_nv_V4: - return Hexagon::JMP_EQriNotPt_ie_nv_V4; - case Hexagon::JMP_EQriPnt_nv_V4: - return Hexagon::JMP_EQriPnt_ie_nv_V4; - case Hexagon::JMP_EQriNotPnt_nv_V4: - return Hexagon::JMP_EQriNotPnt_ie_nv_V4; - - // JMP_EQri -- with -1 - case Hexagon::JMP_EQriPtneg_nv_V4: - return Hexagon::JMP_EQriPtneg_ie_nv_V4; - case Hexagon::JMP_EQriNotPtneg_nv_V4: - return Hexagon::JMP_EQriNotPtneg_ie_nv_V4; - case Hexagon::JMP_EQriPntneg_nv_V4: - return Hexagon::JMP_EQriPntneg_ie_nv_V4; - case Hexagon::JMP_EQriNotPntneg_nv_V4: - return Hexagon::JMP_EQriNotPntneg_ie_nv_V4; - - // JMP_EQrr - case Hexagon::JMP_EQrrPt_nv_V4: - return Hexagon::JMP_EQrrPt_ie_nv_V4; - case Hexagon::JMP_EQrrNotPt_nv_V4: - return Hexagon::JMP_EQrrNotPt_ie_nv_V4; - case Hexagon::JMP_EQrrPnt_nv_V4: - return Hexagon::JMP_EQrrPnt_ie_nv_V4; - case Hexagon::JMP_EQrrNotPnt_nv_V4: - return Hexagon::JMP_EQrrNotPnt_ie_nv_V4; - - // JMP_GTri - case Hexagon::JMP_GTriPt_nv_V4: - return Hexagon::JMP_GTriPt_ie_nv_V4; - case Hexagon::JMP_GTriNotPt_nv_V4: - return Hexagon::JMP_GTriNotPt_ie_nv_V4; - case Hexagon::JMP_GTriPnt_nv_V4: - return Hexagon::JMP_GTriPnt_ie_nv_V4; - case Hexagon::JMP_GTriNotPnt_nv_V4: - return Hexagon::JMP_GTriNotPnt_ie_nv_V4; - - // JMP_GTri -- with -1 - case Hexagon::JMP_GTriPtneg_nv_V4: - return Hexagon::JMP_GTriPtneg_ie_nv_V4; - case Hexagon::JMP_GTriNotPtneg_nv_V4: - return Hexagon::JMP_GTriNotPtneg_ie_nv_V4; - case Hexagon::JMP_GTriPntneg_nv_V4: - return Hexagon::JMP_GTriPntneg_ie_nv_V4; - case Hexagon::JMP_GTriNotPntneg_nv_V4: - return Hexagon::JMP_GTriNotPntneg_ie_nv_V4; - - // JMP_GTrr - case Hexagon::JMP_GTrrPt_nv_V4: - return Hexagon::JMP_GTrrPt_ie_nv_V4; - case Hexagon::JMP_GTrrNotPt_nv_V4: - return Hexagon::JMP_GTrrNotPt_ie_nv_V4; - case Hexagon::JMP_GTrrPnt_nv_V4: - return Hexagon::JMP_GTrrPnt_ie_nv_V4; - case Hexagon::JMP_GTrrNotPnt_nv_V4: - return Hexagon::JMP_GTrrNotPnt_ie_nv_V4; - - // JMP_GTrrdn - case Hexagon::JMP_GTrrdnPt_nv_V4: - return Hexagon::JMP_GTrrdnPt_ie_nv_V4; - case Hexagon::JMP_GTrrdnNotPt_nv_V4: - return Hexagon::JMP_GTrrdnNotPt_ie_nv_V4; - case Hexagon::JMP_GTrrdnPnt_nv_V4: - return Hexagon::JMP_GTrrdnPnt_ie_nv_V4; - case Hexagon::JMP_GTrrdnNotPnt_nv_V4: - return Hexagon::JMP_GTrrdnNotPnt_ie_nv_V4; - - // JMP_GTUri - case Hexagon::JMP_GTUriPt_nv_V4: - return Hexagon::JMP_GTUriPt_ie_nv_V4; - case Hexagon::JMP_GTUriNotPt_nv_V4: - return Hexagon::JMP_GTUriNotPt_ie_nv_V4; - case Hexagon::JMP_GTUriPnt_nv_V4: - return Hexagon::JMP_GTUriPnt_ie_nv_V4; - case Hexagon::JMP_GTUriNotPnt_nv_V4: - return Hexagon::JMP_GTUriNotPnt_ie_nv_V4; - - // JMP_GTUrr - case Hexagon::JMP_GTUrrPt_nv_V4: - return Hexagon::JMP_GTUrrPt_ie_nv_V4; - case Hexagon::JMP_GTUrrNotPt_nv_V4: - return Hexagon::JMP_GTUrrNotPt_ie_nv_V4; - case Hexagon::JMP_GTUrrPnt_nv_V4: - return Hexagon::JMP_GTUrrPnt_ie_nv_V4; - case Hexagon::JMP_GTUrrNotPnt_nv_V4: - return Hexagon::JMP_GTUrrNotPnt_ie_nv_V4; - - // JMP_GTUrrdn - case Hexagon::JMP_GTUrrdnPt_nv_V4: - return Hexagon::JMP_GTUrrdnPt_ie_nv_V4; - case Hexagon::JMP_GTUrrdnNotPt_nv_V4: - return Hexagon::JMP_GTUrrdnNotPt_ie_nv_V4; - case Hexagon::JMP_GTUrrdnPnt_nv_V4: - return Hexagon::JMP_GTUrrdnPnt_ie_nv_V4; - case Hexagon::JMP_GTUrrdnNotPnt_nv_V4: - return Hexagon::JMP_GTUrrdnNotPnt_ie_nv_V4; - - case Hexagon::TFR_FI: - return Hexagon::TFR_FI_immext_V4; - - case Hexagon::MEMw_ADDi_indexed_MEM_V4 : - case Hexagon::MEMw_SUBi_indexed_MEM_V4 : - case Hexagon::MEMw_ADDr_indexed_MEM_V4 : - case Hexagon::MEMw_SUBr_indexed_MEM_V4 : - case Hexagon::MEMw_ANDr_indexed_MEM_V4 : - case Hexagon::MEMw_ORr_indexed_MEM_V4 : - case Hexagon::MEMw_ADDi_MEM_V4 : - case Hexagon::MEMw_SUBi_MEM_V4 : - case Hexagon::MEMw_ADDr_MEM_V4 : - case Hexagon::MEMw_SUBr_MEM_V4 : - case Hexagon::MEMw_ANDr_MEM_V4 : - case Hexagon::MEMw_ORr_MEM_V4 : - case Hexagon::MEMh_ADDi_indexed_MEM_V4 : - case Hexagon::MEMh_SUBi_indexed_MEM_V4 : - case Hexagon::MEMh_ADDr_indexed_MEM_V4 : - case Hexagon::MEMh_SUBr_indexed_MEM_V4 : - case Hexagon::MEMh_ANDr_indexed_MEM_V4 : - case Hexagon::MEMh_ORr_indexed_MEM_V4 : - case Hexagon::MEMh_ADDi_MEM_V4 : - case Hexagon::MEMh_SUBi_MEM_V4 : - case Hexagon::MEMh_ADDr_MEM_V4 : - case Hexagon::MEMh_SUBr_MEM_V4 : - case Hexagon::MEMh_ANDr_MEM_V4 : - case Hexagon::MEMh_ORr_MEM_V4 : - case Hexagon::MEMb_ADDi_indexed_MEM_V4 : - case Hexagon::MEMb_SUBi_indexed_MEM_V4 : - case Hexagon::MEMb_ADDr_indexed_MEM_V4 : - case Hexagon::MEMb_SUBr_indexed_MEM_V4 : - case Hexagon::MEMb_ANDr_indexed_MEM_V4 : - case Hexagon::MEMb_ORr_indexed_MEM_V4 : - case Hexagon::MEMb_ADDi_MEM_V4 : - case Hexagon::MEMb_SUBi_MEM_V4 : - case Hexagon::MEMb_ADDr_MEM_V4 : - case Hexagon::MEMb_SUBr_MEM_V4 : - case Hexagon::MEMb_ANDr_MEM_V4 : - case Hexagon::MEMb_ORr_MEM_V4 : - llvm_unreachable("Needs implementing."); - } -} - -unsigned HexagonInstrInfo::getNormalBranchForm(const MachineInstr* MI) const { - switch(MI->getOpcode()) { - default: llvm_unreachable("Unknown type of jump instruction."); - // JMP_EQri - case Hexagon::JMP_EQriPt_ie_nv_V4: - return Hexagon::JMP_EQriPt_nv_V4; - case Hexagon::JMP_EQriNotPt_ie_nv_V4: - return Hexagon::JMP_EQriNotPt_nv_V4; - case Hexagon::JMP_EQriPnt_ie_nv_V4: - return Hexagon::JMP_EQriPnt_nv_V4; - case Hexagon::JMP_EQriNotPnt_ie_nv_V4: - return Hexagon::JMP_EQriNotPnt_nv_V4; - - // JMP_EQri -- with -1 - case Hexagon::JMP_EQriPtneg_ie_nv_V4: - return Hexagon::JMP_EQriPtneg_nv_V4; - case Hexagon::JMP_EQriNotPtneg_ie_nv_V4: - return Hexagon::JMP_EQriNotPtneg_nv_V4; - case Hexagon::JMP_EQriPntneg_ie_nv_V4: - return Hexagon::JMP_EQriPntneg_nv_V4; - case Hexagon::JMP_EQriNotPntneg_ie_nv_V4: - return Hexagon::JMP_EQriNotPntneg_nv_V4; - - // JMP_EQrr - case Hexagon::JMP_EQrrPt_ie_nv_V4: - return Hexagon::JMP_EQrrPt_nv_V4; - case Hexagon::JMP_EQrrNotPt_ie_nv_V4: - return Hexagon::JMP_EQrrNotPt_nv_V4; - case Hexagon::JMP_EQrrPnt_ie_nv_V4: - return Hexagon::JMP_EQrrPnt_nv_V4; - case Hexagon::JMP_EQrrNotPnt_ie_nv_V4: - return Hexagon::JMP_EQrrNotPnt_nv_V4; - - // JMP_GTri - case Hexagon::JMP_GTriPt_ie_nv_V4: - return Hexagon::JMP_GTriPt_nv_V4; - case Hexagon::JMP_GTriNotPt_ie_nv_V4: - return Hexagon::JMP_GTriNotPt_nv_V4; - case Hexagon::JMP_GTriPnt_ie_nv_V4: - return Hexagon::JMP_GTriPnt_nv_V4; - case Hexagon::JMP_GTriNotPnt_ie_nv_V4: - return Hexagon::JMP_GTriNotPnt_nv_V4; - - // JMP_GTri -- with -1 - case Hexagon::JMP_GTriPtneg_ie_nv_V4: - return Hexagon::JMP_GTriPtneg_nv_V4; - case Hexagon::JMP_GTriNotPtneg_ie_nv_V4: - return Hexagon::JMP_GTriNotPtneg_nv_V4; - case Hexagon::JMP_GTriPntneg_ie_nv_V4: - return Hexagon::JMP_GTriPntneg_nv_V4; - case Hexagon::JMP_GTriNotPntneg_ie_nv_V4: - return Hexagon::JMP_GTriNotPntneg_nv_V4; - - // JMP_GTrr - case Hexagon::JMP_GTrrPt_ie_nv_V4: - return Hexagon::JMP_GTrrPt_nv_V4; - case Hexagon::JMP_GTrrNotPt_ie_nv_V4: - return Hexagon::JMP_GTrrNotPt_nv_V4; - case Hexagon::JMP_GTrrPnt_ie_nv_V4: - return Hexagon::JMP_GTrrPnt_nv_V4; - case Hexagon::JMP_GTrrNotPnt_ie_nv_V4: - return Hexagon::JMP_GTrrNotPnt_nv_V4; - - // JMP_GTrrdn - case Hexagon::JMP_GTrrdnPt_ie_nv_V4: - return Hexagon::JMP_GTrrdnPt_nv_V4; - case Hexagon::JMP_GTrrdnNotPt_ie_nv_V4: - return Hexagon::JMP_GTrrdnNotPt_nv_V4; - case Hexagon::JMP_GTrrdnPnt_ie_nv_V4: - return Hexagon::JMP_GTrrdnPnt_nv_V4; - case Hexagon::JMP_GTrrdnNotPnt_ie_nv_V4: - return Hexagon::JMP_GTrrdnNotPnt_nv_V4; - - // JMP_GTUri - case Hexagon::JMP_GTUriPt_ie_nv_V4: - return Hexagon::JMP_GTUriPt_nv_V4; - case Hexagon::JMP_GTUriNotPt_ie_nv_V4: - return Hexagon::JMP_GTUriNotPt_nv_V4; - case Hexagon::JMP_GTUriPnt_ie_nv_V4: - return Hexagon::JMP_GTUriPnt_nv_V4; - case Hexagon::JMP_GTUriNotPnt_ie_nv_V4: - return Hexagon::JMP_GTUriNotPnt_nv_V4; - - // JMP_GTUrr - case Hexagon::JMP_GTUrrPt_ie_nv_V4: - return Hexagon::JMP_GTUrrPt_nv_V4; - case Hexagon::JMP_GTUrrNotPt_ie_nv_V4: - return Hexagon::JMP_GTUrrNotPt_nv_V4; - case Hexagon::JMP_GTUrrPnt_ie_nv_V4: - return Hexagon::JMP_GTUrrPnt_nv_V4; - case Hexagon::JMP_GTUrrNotPnt_ie_nv_V4: - return Hexagon::JMP_GTUrrNotPnt_nv_V4; - - // JMP_GTUrrdn - case Hexagon::JMP_GTUrrdnPt_ie_nv_V4: - return Hexagon::JMP_GTUrrdnPt_nv_V4; - case Hexagon::JMP_GTUrrdnNotPt_ie_nv_V4: - return Hexagon::JMP_GTUrrdnNotPt_nv_V4; - case Hexagon::JMP_GTUrrdnPnt_ie_nv_V4: - return Hexagon::JMP_GTUrrdnPnt_nv_V4; - case Hexagon::JMP_GTUrrdnNotPnt_ie_nv_V4: - return Hexagon::JMP_GTUrrdnNotPnt_nv_V4; - } -} - - bool HexagonInstrInfo::isNewValueStore(const MachineInstr *MI) const { switch (MI->getOpcode()) { default: return false; @@ -1095,7 +710,6 @@ bool HexagonInstrInfo::isNewValueStore(const MachineInstr *MI) const { case Hexagon::STrib_indexed_nv_V4: case Hexagon::STrib_indexed_shl_nv_V4: case Hexagon::STrib_shl_nv_V4: - case Hexagon::STrib_GP_nv_V4: case Hexagon::STb_GP_nv_V4: case Hexagon::POST_STbri_nv_V4: case Hexagon::STrib_cPt_nv_V4: @@ -1118,10 +732,6 @@ bool HexagonInstrInfo::isNewValueStore(const MachineInstr *MI) const { case Hexagon::STb_GP_cNotPt_nv_V4: case Hexagon::STb_GP_cdnPt_nv_V4: case Hexagon::STb_GP_cdnNotPt_nv_V4: - case Hexagon::STrib_GP_cPt_nv_V4: - case Hexagon::STrib_GP_cNotPt_nv_V4: - case Hexagon::STrib_GP_cdnPt_nv_V4: - case Hexagon::STrib_GP_cdnNotPt_nv_V4: case Hexagon::STrib_abs_nv_V4: case Hexagon::STrib_abs_cPt_nv_V4: case Hexagon::STrib_abs_cdnPt_nv_V4: @@ -1138,7 +748,6 @@ bool HexagonInstrInfo::isNewValueStore(const MachineInstr *MI) const { case Hexagon::STrih_indexed_nv_V4: case Hexagon::STrih_indexed_shl_nv_V4: case Hexagon::STrih_shl_nv_V4: - case Hexagon::STrih_GP_nv_V4: case Hexagon::STh_GP_nv_V4: case Hexagon::POST_SThri_nv_V4: case Hexagon::STrih_cPt_nv_V4: @@ -1161,10 +770,6 @@ bool HexagonInstrInfo::isNewValueStore(const MachineInstr *MI) const { case Hexagon::STh_GP_cNotPt_nv_V4: case Hexagon::STh_GP_cdnPt_nv_V4: case Hexagon::STh_GP_cdnNotPt_nv_V4: - case Hexagon::STrih_GP_cPt_nv_V4: - case Hexagon::STrih_GP_cNotPt_nv_V4: - case Hexagon::STrih_GP_cdnPt_nv_V4: - case Hexagon::STrih_GP_cdnNotPt_nv_V4: case Hexagon::STrih_abs_nv_V4: case Hexagon::STrih_abs_cPt_nv_V4: case Hexagon::STrih_abs_cdnPt_nv_V4: @@ -1181,7 +786,6 @@ bool HexagonInstrInfo::isNewValueStore(const MachineInstr *MI) const { case Hexagon::STriw_indexed_nv_V4: case Hexagon::STriw_indexed_shl_nv_V4: case Hexagon::STriw_shl_nv_V4: - case Hexagon::STriw_GP_nv_V4: case Hexagon::STw_GP_nv_V4: case Hexagon::POST_STwri_nv_V4: case Hexagon::STriw_cPt_nv_V4: @@ -1204,10 +808,6 @@ bool HexagonInstrInfo::isNewValueStore(const MachineInstr *MI) const { case Hexagon::STw_GP_cNotPt_nv_V4: case Hexagon::STw_GP_cdnPt_nv_V4: case Hexagon::STw_GP_cdnNotPt_nv_V4: - case Hexagon::STriw_GP_cPt_nv_V4: - case Hexagon::STriw_GP_cNotPt_nv_V4: - case Hexagon::STriw_GP_cdnPt_nv_V4: - case Hexagon::STriw_GP_cdnNotPt_nv_V4: case Hexagon::STriw_abs_nv_V4: case Hexagon::STriw_abs_cPt_nv_V4: case Hexagon::STriw_abs_cdnPt_nv_V4: @@ -1299,6 +899,16 @@ bool HexagonInstrInfo::isPostIncrement (const MachineInstr* MI) const { } } +bool HexagonInstrInfo::isNewValueInst(const MachineInstr *MI) const { + if (isNewValueJump(MI)) + return true; + + if (isNewValueStore(MI)) + return true; + + return false; +} + bool HexagonInstrInfo::isSaveCalleeSavedRegsCall(const MachineInstr *MI) const { return MI->getOpcode() == Hexagon::SAVE_REGISTERS_CALL_V4; } @@ -1500,26 +1110,11 @@ unsigned HexagonInstrInfo::getInvertedPredicatedOpcode(const int Opc) const { return Hexagon::JMPR_cPt; // V4 indexed+scaled load. - case Hexagon::LDrid_indexed_cPt_V4: - return Hexagon::LDrid_indexed_cNotPt_V4; - case Hexagon::LDrid_indexed_cNotPt_V4: - return Hexagon::LDrid_indexed_cPt_V4; - case Hexagon::LDrid_indexed_shl_cPt_V4: return Hexagon::LDrid_indexed_shl_cNotPt_V4; case Hexagon::LDrid_indexed_shl_cNotPt_V4: return Hexagon::LDrid_indexed_shl_cPt_V4; - case Hexagon::LDrib_indexed_cPt_V4: - return Hexagon::LDrib_indexed_cNotPt_V4; - case Hexagon::LDrib_indexed_cNotPt_V4: - return Hexagon::LDrib_indexed_cPt_V4; - - case Hexagon::LDriub_indexed_cPt_V4: - return Hexagon::LDriub_indexed_cNotPt_V4; - case Hexagon::LDriub_indexed_cNotPt_V4: - return Hexagon::LDriub_indexed_cPt_V4; - case Hexagon::LDrib_indexed_shl_cPt_V4: return Hexagon::LDrib_indexed_shl_cNotPt_V4; case Hexagon::LDrib_indexed_shl_cNotPt_V4: @@ -1530,16 +1125,6 @@ unsigned HexagonInstrInfo::getInvertedPredicatedOpcode(const int Opc) const { case Hexagon::LDriub_indexed_shl_cNotPt_V4: return Hexagon::LDriub_indexed_shl_cPt_V4; - case Hexagon::LDrih_indexed_cPt_V4: - return Hexagon::LDrih_indexed_cNotPt_V4; - case Hexagon::LDrih_indexed_cNotPt_V4: - return Hexagon::LDrih_indexed_cPt_V4; - - case Hexagon::LDriuh_indexed_cPt_V4: - return Hexagon::LDriuh_indexed_cNotPt_V4; - case Hexagon::LDriuh_indexed_cNotPt_V4: - return Hexagon::LDriuh_indexed_cPt_V4; - case Hexagon::LDrih_indexed_shl_cPt_V4: return Hexagon::LDrih_indexed_shl_cNotPt_V4; case Hexagon::LDrih_indexed_shl_cNotPt_V4: @@ -1550,11 +1135,6 @@ unsigned HexagonInstrInfo::getInvertedPredicatedOpcode(const int Opc) const { case Hexagon::LDriuh_indexed_shl_cNotPt_V4: return Hexagon::LDriuh_indexed_shl_cPt_V4; - case Hexagon::LDriw_indexed_cPt_V4: - return Hexagon::LDriw_indexed_cNotPt_V4; - case Hexagon::LDriw_indexed_cNotPt_V4: - return Hexagon::LDriw_indexed_cPt_V4; - case Hexagon::LDriw_indexed_shl_cPt_V4: return Hexagon::LDriw_indexed_shl_cNotPt_V4; case Hexagon::LDriw_indexed_shl_cNotPt_V4: @@ -1680,26 +1260,6 @@ unsigned HexagonInstrInfo::getInvertedPredicatedOpcode(const int Opc) const { case Hexagon::STw_GP_cNotPt_V4: return Hexagon::STw_GP_cPt_V4; - case Hexagon::STrid_GP_cPt_V4: - return Hexagon::STrid_GP_cNotPt_V4; - case Hexagon::STrid_GP_cNotPt_V4: - return Hexagon::STrid_GP_cPt_V4; - - case Hexagon::STrib_GP_cPt_V4: - return Hexagon::STrib_GP_cNotPt_V4; - case Hexagon::STrib_GP_cNotPt_V4: - return Hexagon::STrib_GP_cPt_V4; - - case Hexagon::STrih_GP_cPt_V4: - return Hexagon::STrih_GP_cNotPt_V4; - case Hexagon::STrih_GP_cNotPt_V4: - return Hexagon::STrih_GP_cPt_V4; - - case Hexagon::STriw_GP_cPt_V4: - return Hexagon::STriw_GP_cNotPt_V4; - case Hexagon::STriw_GP_cNotPt_V4: - return Hexagon::STriw_GP_cPt_V4; - // Load. case Hexagon::LDrid_cPt: return Hexagon::LDrid_cNotPt; @@ -1965,75 +1525,26 @@ getMatchingCondBranchOpcode(int Opc, bool invertPredicate) const { Hexagon::JMPR_cNotPt; // V4 indexed+scaled load. - case Hexagon::LDrid_indexed_V4: - return !invertPredicate ? Hexagon::LDrid_indexed_cPt_V4 : - Hexagon::LDrid_indexed_cNotPt_V4; case Hexagon::LDrid_indexed_shl_V4: return !invertPredicate ? Hexagon::LDrid_indexed_shl_cPt_V4 : Hexagon::LDrid_indexed_shl_cNotPt_V4; - case Hexagon::LDrib_indexed_V4: - return !invertPredicate ? Hexagon::LDrib_indexed_cPt_V4 : - Hexagon::LDrib_indexed_cNotPt_V4; - case Hexagon::LDriub_indexed_V4: - return !invertPredicate ? Hexagon::LDriub_indexed_cPt_V4 : - Hexagon::LDriub_indexed_cNotPt_V4; - case Hexagon::LDriub_ae_indexed_V4: - return !invertPredicate ? Hexagon::LDriub_indexed_cPt_V4 : - Hexagon::LDriub_indexed_cNotPt_V4; case Hexagon::LDrib_indexed_shl_V4: return !invertPredicate ? Hexagon::LDrib_indexed_shl_cPt_V4 : Hexagon::LDrib_indexed_shl_cNotPt_V4; case Hexagon::LDriub_indexed_shl_V4: return !invertPredicate ? Hexagon::LDriub_indexed_shl_cPt_V4 : Hexagon::LDriub_indexed_shl_cNotPt_V4; - case Hexagon::LDriub_ae_indexed_shl_V4: - return !invertPredicate ? Hexagon::LDriub_indexed_shl_cPt_V4 : - Hexagon::LDriub_indexed_shl_cNotPt_V4; - case Hexagon::LDrih_indexed_V4: - return !invertPredicate ? Hexagon::LDrih_indexed_cPt_V4 : - Hexagon::LDrih_indexed_cNotPt_V4; - case Hexagon::LDriuh_indexed_V4: - return !invertPredicate ? Hexagon::LDriuh_indexed_cPt_V4 : - Hexagon::LDriuh_indexed_cNotPt_V4; - case Hexagon::LDriuh_ae_indexed_V4: - return !invertPredicate ? Hexagon::LDriuh_indexed_cPt_V4 : - Hexagon::LDriuh_indexed_cNotPt_V4; case Hexagon::LDrih_indexed_shl_V4: return !invertPredicate ? Hexagon::LDrih_indexed_shl_cPt_V4 : Hexagon::LDrih_indexed_shl_cNotPt_V4; case Hexagon::LDriuh_indexed_shl_V4: return !invertPredicate ? Hexagon::LDriuh_indexed_shl_cPt_V4 : Hexagon::LDriuh_indexed_shl_cNotPt_V4; - case Hexagon::LDriuh_ae_indexed_shl_V4: - return !invertPredicate ? Hexagon::LDriuh_indexed_shl_cPt_V4 : - Hexagon::LDriuh_indexed_shl_cNotPt_V4; - case Hexagon::LDriw_indexed_V4: - return !invertPredicate ? Hexagon::LDriw_indexed_cPt_V4 : - Hexagon::LDriw_indexed_cNotPt_V4; case Hexagon::LDriw_indexed_shl_V4: return !invertPredicate ? Hexagon::LDriw_indexed_shl_cPt_V4 : Hexagon::LDriw_indexed_shl_cNotPt_V4; // V4 Load from global address - case Hexagon::LDrid_GP_V4: - return !invertPredicate ? Hexagon::LDrid_GP_cPt_V4 : - Hexagon::LDrid_GP_cNotPt_V4; - case Hexagon::LDrib_GP_V4: - return !invertPredicate ? Hexagon::LDrib_GP_cPt_V4 : - Hexagon::LDrib_GP_cNotPt_V4; - case Hexagon::LDriub_GP_V4: - return !invertPredicate ? Hexagon::LDriub_GP_cPt_V4 : - Hexagon::LDriub_GP_cNotPt_V4; - case Hexagon::LDrih_GP_V4: - return !invertPredicate ? Hexagon::LDrih_GP_cPt_V4 : - Hexagon::LDrih_GP_cNotPt_V4; - case Hexagon::LDriuh_GP_V4: - return !invertPredicate ? Hexagon::LDriuh_GP_cPt_V4 : - Hexagon::LDriuh_GP_cNotPt_V4; - case Hexagon::LDriw_GP_V4: - return !invertPredicate ? Hexagon::LDriw_GP_cPt_V4 : - Hexagon::LDriw_GP_cNotPt_V4; - case Hexagon::LDd_GP_V4: return !invertPredicate ? Hexagon::LDd_GP_cPt_V4 : Hexagon::LDd_GP_cNotPt_V4; @@ -2116,19 +1627,6 @@ getMatchingCondBranchOpcode(int Opc, bool invertPredicate) const { Hexagon::STrid_indexed_shl_cNotPt_V4; // V4 Store to global address - case Hexagon::STrid_GP_V4: - return !invertPredicate ? Hexagon::STrid_GP_cPt_V4 : - Hexagon::STrid_GP_cNotPt_V4; - case Hexagon::STrib_GP_V4: - return !invertPredicate ? Hexagon::STrib_GP_cPt_V4 : - Hexagon::STrib_GP_cNotPt_V4; - case Hexagon::STrih_GP_V4: - return !invertPredicate ? Hexagon::STrih_GP_cPt_V4 : - Hexagon::STrih_GP_cNotPt_V4; - case Hexagon::STriw_GP_V4: - return !invertPredicate ? Hexagon::STriw_GP_cPt_V4 : - Hexagon::STriw_GP_cNotPt_V4; - case Hexagon::STd_GP_V4: return !invertPredicate ? Hexagon::STd_GP_cPt_V4 : Hexagon::STd_GP_cNotPt_V4; @@ -2215,38 +1713,141 @@ PredicateInstruction(MachineInstr *MI, assert (isPredicable(MI) && "Expected predicable instruction"); bool invertJump = (!Cond.empty() && Cond[0].isImm() && (Cond[0].getImm() == 0)); + + // This will change MI's opcode to its predicate version. + // However, its operand list is still the old one, i.e. the + // non-predicate one. MI->setDesc(get(getMatchingCondBranchOpcode(Opc, invertJump))); - // - // This assumes that the predicate is always the first operand - // in the set of inputs. - // - MI->addOperand(MI->getOperand(MI->getNumOperands()-1)); - int oper; - for (oper = MI->getNumOperands() - 3; oper >= 0; --oper) { - MachineOperand MO = MI->getOperand(oper); - if ((MO.isReg() && !MO.isUse() && !MO.isImplicit())) { - break; - } - if (MO.isReg()) { - MI->getOperand(oper+1).ChangeToRegister(MO.getReg(), MO.isDef(), - MO.isImplicit(), MO.isKill(), - MO.isDead(), MO.isUndef(), - MO.isDebug()); - } else if (MO.isImm()) { - MI->getOperand(oper+1).ChangeToImmediate(MO.getImm()); - } else { - llvm_unreachable("Unexpected operand type"); + int oper = -1; + unsigned int GAIdx = 0; + + // Indicates whether the current MI has a GlobalAddress operand + bool hasGAOpnd = false; + std::vector<MachineOperand> tmpOpnds; + + // Indicates whether we need to shift operands to right. + bool needShift = true; + + // The predicate is ALWAYS the FIRST input operand !!! + if (MI->getNumOperands() == 0) { + // The non-predicate version of MI does not take any operands, + // i.e. no outs and no ins. In this condition, the predicate + // operand will be directly placed at Operands[0]. No operand + // shift is needed. + // Example: BARRIER + needShift = false; + oper = -1; + } + else if ( MI->getOperand(MI->getNumOperands()-1).isReg() + && MI->getOperand(MI->getNumOperands()-1).isDef() + && !MI->getOperand(MI->getNumOperands()-1).isImplicit()) { + // The non-predicate version of MI does not have any input operands. + // In this condition, we extend the length of Operands[] by one and + // copy the original last operand to the newly allocated slot. + // At this moment, it is just a place holder. Later, we will put + // predicate operand directly into it. No operand shift is needed. + // Example: r0=BARRIER (this is a faked insn used here for illustration) + MI->addOperand(MI->getOperand(MI->getNumOperands()-1)); + needShift = false; + oper = MI->getNumOperands() - 2; + } + else { + // We need to right shift all input operands by one. Duplicate the + // last operand into the newly allocated slot. + MI->addOperand(MI->getOperand(MI->getNumOperands()-1)); + } + + if (needShift) + { + // Operands[ MI->getNumOperands() - 2 ] has been copied into + // Operands[ MI->getNumOperands() - 1 ], so we start from + // Operands[ MI->getNumOperands() - 3 ]. + // oper is a signed int. + // It is ok if "MI->getNumOperands()-3" is -3, -2, or -1. + for (oper = MI->getNumOperands() - 3; oper >= 0; --oper) + { + MachineOperand &MO = MI->getOperand(oper); + + // Opnd[0] Opnd[1] Opnd[2] Opnd[3] Opnd[4] Opnd[5] Opnd[6] Opnd[7] + // <Def0> <Def1> <Use0> <Use1> <ImpDef0> <ImpDef1> <ImpUse0> <ImpUse1> + // /\~ + // /||\~ + // || + // Predicate Operand here + if (MO.isReg() && !MO.isUse() && !MO.isImplicit()) { + break; + } + if (MO.isReg()) { + MI->getOperand(oper+1).ChangeToRegister(MO.getReg(), MO.isDef(), + MO.isImplicit(), MO.isKill(), + MO.isDead(), MO.isUndef(), + MO.isDebug()); + } + else if (MO.isImm()) { + MI->getOperand(oper+1).ChangeToImmediate(MO.getImm()); + } + else if (MO.isGlobal()) { + // MI can not have more than one GlobalAddress operand. + assert(hasGAOpnd == false && "MI can only have one GlobalAddress opnd"); + + // There is no member function called "ChangeToGlobalAddress" in the + // MachineOperand class (not like "ChangeToRegister" and + // "ChangeToImmediate"). So we have to remove them from Operands[] list + // first, and then add them back after we have inserted the predicate + // operand. tmpOpnds[] is to remember these operands before we remove + // them. + tmpOpnds.push_back(MO); + + // Operands[oper] is a GlobalAddress operand; + // Operands[oper+1] has been copied into Operands[oper+2]; + hasGAOpnd = true; + GAIdx = oper; + continue; + } + else { + assert(false && "Unexpected operand type"); + } } } int regPos = invertJump ? 1 : 0; MachineOperand PredMO = Cond[regPos]; + + // [oper] now points to the last explicit Def. Predicate operand must be + // located at [oper+1]. See diagram above. + // This assumes that the predicate is always the first operand, + // i.e. Operands[0+numResults], in the set of inputs + // It is better to have an assert here to check this. But I don't know how + // to write this assert because findFirstPredOperandIdx() would return -1 + if (oper < -1) oper = -1; MI->getOperand(oper+1).ChangeToRegister(PredMO.getReg(), PredMO.isDef(), PredMO.isImplicit(), PredMO.isKill(), PredMO.isDead(), PredMO.isUndef(), PredMO.isDebug()); + if (hasGAOpnd) + { + unsigned int i; + + // Operands[GAIdx] is the original GlobalAddress operand, which is + // already copied into tmpOpnds[0]. + // Operands[GAIdx] now stores a copy of Operands[GAIdx-1] + // Operands[GAIdx+1] has already been copied into Operands[GAIdx+2], + // so we start from [GAIdx+2] + for (i = GAIdx + 2; i < MI->getNumOperands(); ++i) + tmpOpnds.push_back(MI->getOperand(i)); + + // Remove all operands in range [ (GAIdx+1) ... (MI->getNumOperands()-1) ] + // It is very important that we always remove from the end of Operands[] + // MI->getNumOperands() is at least 2 if program goes to here. + for (i = MI->getNumOperands() - 1; i > GAIdx; --i) + MI->RemoveOperand(i); + + for (i = 0; i < tmpOpnds.size(); ++i) + MI->addOperand(tmpOpnds[i]); + } + return true; } @@ -2352,7 +1953,9 @@ isValidOffset(const int Opcode, const int Offset) const { switch(Opcode) { case Hexagon::LDriw: + case Hexagon::LDriw_indexed: case Hexagon::LDriw_f: + case Hexagon::STriw_indexed: case Hexagon::STriw: case Hexagon::STriw_f: assert((Offset % 4 == 0) && "Offset has incorrect alignment"); @@ -2360,8 +1963,10 @@ isValidOffset(const int Opcode, const int Offset) const { (Offset <= Hexagon_MEMW_OFFSET_MAX); case Hexagon::LDrid: + case Hexagon::LDrid_indexed: case Hexagon::LDrid_f: case Hexagon::STrid: + case Hexagon::STrid_indexed: case Hexagon::STrid_f: assert((Offset % 8 == 0) && "Offset has incorrect alignment"); return (Offset >= Hexagon_MEMD_OFFSET_MIN) && @@ -2435,6 +2040,9 @@ isValidOffset(const int Opcode, const int Offset) const { case Hexagon::LDriw_pred: return true; + case Hexagon::LOOP0_i: + return isUInt<10>(Offset); + // INLINEASM is very special. case Hexagon::INLINEASM: return true; @@ -2643,28 +2251,16 @@ isConditionalLoad (const MachineInstr* MI) const { case Hexagon::POST_LDriub_cPt : case Hexagon::POST_LDriub_cNotPt : return QRI.Subtarget.hasV4TOps(); - case Hexagon::LDrid_indexed_cPt_V4 : - case Hexagon::LDrid_indexed_cNotPt_V4 : case Hexagon::LDrid_indexed_shl_cPt_V4 : case Hexagon::LDrid_indexed_shl_cNotPt_V4 : - case Hexagon::LDrib_indexed_cPt_V4 : - case Hexagon::LDrib_indexed_cNotPt_V4 : case Hexagon::LDrib_indexed_shl_cPt_V4 : case Hexagon::LDrib_indexed_shl_cNotPt_V4 : - case Hexagon::LDriub_indexed_cPt_V4 : - case Hexagon::LDriub_indexed_cNotPt_V4 : case Hexagon::LDriub_indexed_shl_cPt_V4 : case Hexagon::LDriub_indexed_shl_cNotPt_V4 : - case Hexagon::LDrih_indexed_cPt_V4 : - case Hexagon::LDrih_indexed_cNotPt_V4 : case Hexagon::LDrih_indexed_shl_cPt_V4 : case Hexagon::LDrih_indexed_shl_cNotPt_V4 : - case Hexagon::LDriuh_indexed_cPt_V4 : - case Hexagon::LDriuh_indexed_cNotPt_V4 : case Hexagon::LDriuh_indexed_shl_cPt_V4 : case Hexagon::LDriuh_indexed_shl_cNotPt_V4 : - case Hexagon::LDriw_indexed_cPt_V4 : - case Hexagon::LDriw_indexed_cNotPt_V4 : case Hexagon::LDriw_indexed_shl_cPt_V4 : case Hexagon::LDriw_indexed_shl_cNotPt_V4 : return QRI.Subtarget.hasV4TOps(); @@ -2747,14 +2343,6 @@ isConditionalStore (const MachineInstr* MI) const { return QRI.Subtarget.hasV4TOps(); // V4 global address store before promoting to dot new. - case Hexagon::STrid_GP_cPt_V4 : - case Hexagon::STrid_GP_cNotPt_V4 : - case Hexagon::STrib_GP_cPt_V4 : - case Hexagon::STrib_GP_cNotPt_V4 : - case Hexagon::STrih_GP_cPt_V4 : - case Hexagon::STrih_GP_cNotPt_V4 : - case Hexagon::STriw_GP_cPt_V4 : - case Hexagon::STriw_GP_cNotPt_V4 : case Hexagon::STd_GP_cPt_V4 : case Hexagon::STd_GP_cNotPt_V4 : case Hexagon::STb_GP_cPt_V4 : @@ -2795,7 +2383,26 @@ isConditionalStore (const MachineInstr* MI) const { } } +unsigned HexagonInstrInfo::getAddrMode(const MachineInstr* MI) const { + const uint64_t F = MI->getDesc().TSFlags; + + return((F >> HexagonII::AddrModePos) & HexagonII::AddrModeMask); +} +/// immediateExtend - Changes the instruction in place to one using an immediate +/// extender. +void HexagonInstrInfo::immediateExtend(MachineInstr *MI) const { + assert((isExtendable(MI)||isConstExtended(MI)) && + "Instruction must be extendable"); + // Find which operand is extendable. + short ExtOpNum = getCExtOpNum(MI); + MachineOperand &MO = MI->getOperand(ExtOpNum); + // This needs to be something we understand. + assert((MO.isMBB() || MO.isImm()) && + "Branch with unknown extendable field type"); + // Mark given operand as extended. + MO.addTargetFlag(HexagonII::HMOTF_ConstExtended); +} DFAPacketizer *HexagonInstrInfo:: CreateTargetScheduleState(const TargetMachine *TM, @@ -2822,3 +2429,155 @@ bool HexagonInstrInfo::isSchedulingBoundary(const MachineInstr *MI, return false; } + +bool HexagonInstrInfo::isConstExtended(MachineInstr *MI) const { + + // Constant extenders are allowed only for V4 and above. + if (!Subtarget.hasV4TOps()) + return false; + + const uint64_t F = MI->getDesc().TSFlags; + unsigned isExtended = (F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask; + if (isExtended) // Instruction must be extended. + return true; + + unsigned isExtendable = (F >> HexagonII::ExtendablePos) + & HexagonII::ExtendableMask; + if (!isExtendable) + return false; + + short ExtOpNum = getCExtOpNum(MI); + const MachineOperand &MO = MI->getOperand(ExtOpNum); + // Use MO operand flags to determine if MO + // has the HMOTF_ConstExtended flag set. + if (MO.getTargetFlags() && HexagonII::HMOTF_ConstExtended) + return true; + // If this is a Machine BB address we are talking about, and it is + // not marked as extended, say so. + if (MO.isMBB()) + return false; + + // We could be using an instruction with an extendable immediate and shoehorn + // a global address into it. If it is a global address it will be constant + // extended. We do this for COMBINE. + // We currently only handle isGlobal() because it is the only kind of + // object we are going to end up with here for now. + // In the future we probably should add isSymbol(), etc. + if (MO.isGlobal() || MO.isSymbol()) + return true; + + // If the extendable operand is not 'Immediate' type, the instruction should + // have 'isExtended' flag set. + assert(MO.isImm() && "Extendable operand must be Immediate type"); + + int MinValue = getMinValue(MI); + int MaxValue = getMaxValue(MI); + int ImmValue = MO.getImm(); + + return (ImmValue < MinValue || ImmValue > MaxValue); +} + +// Returns true if a particular operand is extendable for an instruction. +bool HexagonInstrInfo::isOperandExtended(const MachineInstr *MI, + unsigned short OperandNum) const { + // Constant extenders are allowed only for V4 and above. + if (!Subtarget.hasV4TOps()) + return false; + + const uint64_t F = MI->getDesc().TSFlags; + + return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask) + == OperandNum; +} + +// Returns Operand Index for the constant extended instruction. +unsigned short HexagonInstrInfo::getCExtOpNum(const MachineInstr *MI) const { + const uint64_t F = MI->getDesc().TSFlags; + return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask); +} + +// Returns the min value that doesn't need to be extended. +int HexagonInstrInfo::getMinValue(const MachineInstr *MI) const { + const uint64_t F = MI->getDesc().TSFlags; + unsigned isSigned = (F >> HexagonII::ExtentSignedPos) + & HexagonII::ExtentSignedMask; + unsigned bits = (F >> HexagonII::ExtentBitsPos) + & HexagonII::ExtentBitsMask; + + if (isSigned) // if value is signed + return -1 << (bits - 1); + else + return 0; +} + +// Returns the max value that doesn't need to be extended. +int HexagonInstrInfo::getMaxValue(const MachineInstr *MI) const { + const uint64_t F = MI->getDesc().TSFlags; + unsigned isSigned = (F >> HexagonII::ExtentSignedPos) + & HexagonII::ExtentSignedMask; + unsigned bits = (F >> HexagonII::ExtentBitsPos) + & HexagonII::ExtentBitsMask; + + if (isSigned) // if value is signed + return ~(-1 << (bits - 1)); + else + return ~(-1 << bits); +} + +// Returns true if an instruction can be converted into a non-extended +// equivalent instruction. +bool HexagonInstrInfo::NonExtEquivalentExists (const MachineInstr *MI) const { + + short NonExtOpcode; + // Check if the instruction has a register form that uses register in place + // of the extended operand, if so return that as the non-extended form. + if (Hexagon::getRegForm(MI->getOpcode()) >= 0) + return true; + + if (MI->getDesc().mayLoad() || MI->getDesc().mayStore()) { + // Check addressing mode and retreive non-ext equivalent instruction. + + switch (getAddrMode(MI)) { + case HexagonII::Absolute : + // Load/store with absolute addressing mode can be converted into + // base+offset mode. + NonExtOpcode = Hexagon::getBasedWithImmOffset(MI->getOpcode()); + break; + case HexagonII::BaseImmOffset : + // Load/store with base+offset addressing mode can be converted into + // base+register offset addressing mode. However left shift operand should + // be set to 0. + NonExtOpcode = Hexagon::getBaseWithRegOffset(MI->getOpcode()); + break; + default: + return false; + } + if (NonExtOpcode < 0) + return false; + return true; + } + return false; +} + +// Returns opcode of the non-extended equivalent instruction. +short HexagonInstrInfo::getNonExtOpcode (const MachineInstr *MI) const { + + // Check if the instruction has a register form that uses register in place + // of the extended operand, if so return that as the non-extended form. + short NonExtOpcode = Hexagon::getRegForm(MI->getOpcode()); + if (NonExtOpcode >= 0) + return NonExtOpcode; + + if (MI->getDesc().mayLoad() || MI->getDesc().mayStore()) { + // Check addressing mode and retreive non-ext equivalent instruction. + switch (getAddrMode(MI)) { + case HexagonII::Absolute : + return Hexagon::getBasedWithImmOffset(MI->getOpcode()); + case HexagonII::BaseImmOffset : + return Hexagon::getBaseWithRegOffset(MI->getOpcode()); + default: + return -1; + } + } + return -1; +} diff --git a/lib/Target/Hexagon/HexagonInstrInfo.h b/lib/Target/Hexagon/HexagonInstrInfo.h index 29e3eb10f5..d2f059aa79 100644 --- a/lib/Target/Hexagon/HexagonInstrInfo.h +++ b/lib/Target/Hexagon/HexagonInstrInfo.h @@ -66,6 +66,10 @@ public: const SmallVectorImpl<MachineOperand> &Cond, DebugLoc DL) const; + virtual bool analyzeCompare(const MachineInstr *MI, + unsigned &SrcReg, unsigned &SrcReg2, + int &Mask, int &Value) const; + virtual void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, unsigned DestReg, unsigned SrcReg, @@ -165,6 +169,7 @@ public: bool isConditionalALU32 (const MachineInstr* MI) const; bool isConditionalLoad (const MachineInstr* MI) const; bool isConditionalStore(const MachineInstr* MI) const; + bool isNewValueInst(const MachineInstr* MI) const; bool isDeallocRet(const MachineInstr *MI) const; unsigned getInvertedPredicatedOpcode(const int Opc) const; bool isExtendable(const MachineInstr* MI) const; @@ -173,9 +178,18 @@ public: bool isNewValueStore(const MachineInstr* MI) const; bool isNewValueJump(const MachineInstr* MI) const; bool isNewValueJumpCandidate(const MachineInstr *MI) const; - unsigned getImmExtForm(const MachineInstr* MI) const; - unsigned getNormalBranchForm(const MachineInstr* MI) const; + + void immediateExtend(MachineInstr *MI) const; + bool isConstExtended(MachineInstr *MI) const; + unsigned getAddrMode(const MachineInstr* MI) const; + bool isOperandExtended(const MachineInstr *MI, + unsigned short OperandNum) const; + unsigned short getCExtOpNum(const MachineInstr *MI) const; + int getMinValue(const MachineInstr *MI) const; + int getMaxValue(const MachineInstr *MI) const; + bool NonExtEquivalentExists (const MachineInstr *MI) const; + short getNonExtOpcode(const MachineInstr *MI) const; private: int getMatchingCondBranchOpcode(int Opc, bool sense) const; diff --git a/lib/Target/Hexagon/HexagonInstrInfo.td b/lib/Target/Hexagon/HexagonInstrInfo.td index dc93fb6b1b..d7bab200f9 100644 --- a/lib/Target/Hexagon/HexagonInstrInfo.td +++ b/lib/Target/Hexagon/HexagonInstrInfo.td @@ -98,8 +98,8 @@ let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 8 in multiclass ALU32_Pbase<string mnemonic, bit isNot, bit isPredNew> { - let PNewValue = #!if(isPredNew, "new", "") in - def #NAME# : ALU32_rr<(outs IntRegs:$dst), + let PNewValue = !if(isPredNew, "new", "") in + def NAME : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2, IntRegs: $src3), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew,".new) $dst = ", ") $dst = ")#mnemonic#"($src2, $src3)", @@ -107,10 +107,10 @@ multiclass ALU32_Pbase<string mnemonic, bit isNot, } multiclass ALU32_Pred<string mnemonic, bit PredNot> { - let PredSense = #!if(PredNot, "false", "true") in { - defm _c#NAME# : ALU32_Pbase<mnemonic, PredNot, 0>; + let PredSense = !if(PredNot, "false", "true") in { + defm _c#NAME : ALU32_Pbase<mnemonic, PredNot, 0>; // Predicate new - defm _cdn#NAME# : ALU32_Pbase<mnemonic, PredNot, 1>; + defm _cdn#NAME : ALU32_Pbase<mnemonic, PredNot, 1>; } } @@ -118,7 +118,7 @@ let InputType = "reg" in multiclass ALU32_base<string mnemonic, string CextOp, SDNode OpNode> { let CextOpcode = CextOp, BaseOpcode = CextOp#_rr in { let isPredicable = 1 in - def #NAME# : ALU32_rr<(outs IntRegs:$dst), + def NAME : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), "$dst = "#mnemonic#"($src1, $src2)", [(set (i32 IntRegs:$dst), (OpNode (i32 IntRegs:$src1), @@ -144,8 +144,8 @@ defm SUB_rr : ALU32_base<"sub", "SUB", sub>, ImmRegRel, PredNewRel; // ALU32/ALU (ADD with register-immediate form) //===----------------------------------------------------------------------===// multiclass ALU32ri_Pbase<string mnemonic, bit isNot, bit isPredNew> { - let PNewValue = #!if(isPredNew, "new", "") in - def #NAME# : ALU32_ri<(outs IntRegs:$dst), + let PNewValue = !if(isPredNew, "new", "") in + def NAME : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2, s8Ext: $src3), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew,".new) $dst = ", ") $dst = ")#mnemonic#"($src2, #$src3)", @@ -153,10 +153,10 @@ multiclass ALU32ri_Pbase<string mnemonic, bit isNot, bit isPredNew> { } multiclass ALU32ri_Pred<string mnemonic, bit PredNot> { - let PredSense = #!if(PredNot, "false", "true") in { - defm _c#NAME# : ALU32ri_Pbase<mnemonic, PredNot, 0>; + let PredSense = !if(PredNot, "false", "true") in { + defm _c#NAME : ALU32ri_Pbase<mnemonic, PredNot, 0>; // Predicate new - defm _cdn#NAME# : ALU32ri_Pbase<mnemonic, PredNot, 1>; + defm _cdn#NAME : ALU32ri_Pbase<mnemonic, PredNot, 1>; } } @@ -165,7 +165,7 @@ multiclass ALU32ri_base<string mnemonic, string CextOp, SDNode OpNode> { let CextOpcode = CextOp, BaseOpcode = CextOp#_ri in { let opExtendable = 2, isExtentSigned = 1, opExtentBits = 16, isPredicable = 1 in - def #NAME# : ALU32_ri<(outs IntRegs:$dst), + def NAME : ALU32_ri<(outs IntRegs:$dst), (ins IntRegs:$src1, s16Ext:$src2), "$dst = "#mnemonic#"($src1, #$src2)", [(set (i32 IntRegs:$dst), (OpNode (i32 IntRegs:$src1), @@ -222,15 +222,15 @@ def SUB_ri : ALU32_ri<(outs IntRegs:$dst), multiclass TFR_Pred<bit PredNot> { - let PredSense = #!if(PredNot, "false", "true") in { - def _c#NAME# : ALU32_rr<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2), + let PredSense = !if(PredNot, "false", "true") in { + def _c#NAME : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), !if(PredNot, "if (!$src1", "if ($src1")#") $dst = $src2", []>; // Predicate new let PNewValue = "new" in - def _cdn#NAME# : ALU32_rr<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2), + def _cdn#NAME : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), !if(PredNot, "if (!$src1", "if ($src1")#".new) $dst = $src2", []>; } @@ -240,7 +240,7 @@ let InputType = "reg", neverHasSideEffects = 1 in multiclass TFR_base<string CextOp> { let CextOpcode = CextOp, BaseOpcode = CextOp in { let isPredicable = 1 in - def #NAME# : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1), + def NAME : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1), "$dst = $src1", []>; @@ -251,28 +251,55 @@ multiclass TFR_base<string CextOp> { } } +class T_TFR64_Pred<bit PredNot, bit isPredNew> + : ALU32_rr<(outs DoubleRegs:$dst), + (ins PredRegs:$src1, DoubleRegs:$src2), + !if(PredNot, "if (!$src1", "if ($src1")# + !if(isPredNew, ".new) ", ") ")#"$dst = $src2", []> +{ + bits<5> dst; + bits<2> src1; + bits<5> src2; + + let IClass = 0b1111; + let Inst{27-24} = 0b1101; + let Inst{13} = isPredNew; + let Inst{7} = PredNot; + let Inst{4-0} = dst; + let Inst{6-5} = src1; + let Inst{20-17} = src2{4-1}; + let Inst{16} = 0b1; + let Inst{12-9} = src2{4-1}; + let Inst{8} = 0b0; +} + multiclass TFR64_Pred<bit PredNot> { - let PredSense = #!if(PredNot, "false", "true") in { - def _c#NAME# : ALU32_rr<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, DoubleRegs:$src2), - !if(PredNot, "if (!$src1", "if ($src1")#") $dst = $src2", - []>; - // Predicate new + let PredSense = !if(PredNot, "false", "true") in { + def _c#NAME : T_TFR64_Pred<PredNot, 0>; + let PNewValue = "new" in - def _cdn#NAME# : ALU32_rr<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, DoubleRegs:$src2), - !if(PredNot, "if (!$src1", "if ($src1")#".new) $dst = $src2", - []>; + def _cdn#NAME : T_TFR64_Pred<PredNot, 1>; // Predicate new } } -let InputType = "reg", neverHasSideEffects = 1 in -multiclass TFR64_base<string CextOp> { - let CextOpcode = CextOp, BaseOpcode = CextOp in { +let neverHasSideEffects = 1 in +multiclass TFR64_base<string BaseName> { + let BaseOpcode = BaseName in { let isPredicable = 1 in - def #NAME# : ALU32_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1), - "$dst = $src1", - []>; + def NAME : ALU32Inst <(outs DoubleRegs:$dst), + (ins DoubleRegs:$src1), + "$dst = $src1" > { + bits<5> dst; + bits<5> src1; + + let IClass = 0b1111; + let Inst{27-23} = 0b01010; + let Inst{4-0} = dst; + let Inst{20-17} = src1{4-1}; + let Inst{16} = 0b1; + let Inst{12-9} = src1{4-1}; + let Inst{8} = 0b0; + } let isPredicated = 1 in { defm Pt : TFR64_Pred<0>; @@ -281,18 +308,17 @@ multiclass TFR64_base<string CextOp> { } } - multiclass TFRI_Pred<bit PredNot> { - let PredSense = #!if(PredNot, "false", "true") in { - def _c#NAME# : ALU32_ri<(outs IntRegs:$dst), - (ins PredRegs:$src1, s12Ext:$src2), + let isMoveImm = 1, PredSense = !if(PredNot, "false", "true") in { + def _c#NAME : ALU32_ri<(outs IntRegs:$dst), + (ins PredRegs:$src1, s12Ext:$src2), !if(PredNot, "if (!$src1", "if ($src1")#") $dst = #$src2", []>; // Predicate new let PNewValue = "new" in - def _cdn#NAME# : ALU32_rr<(outs IntRegs:$dst), - (ins PredRegs:$src1, s12Ext:$src2), + def _cdn#NAME : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, s12Ext:$src2), !if(PredNot, "if (!$src1", "if ($src1")#".new) $dst = #$src2", []>; } @@ -301,9 +327,9 @@ multiclass TFRI_Pred<bit PredNot> { let InputType = "imm", isExtendable = 1, isExtentSigned = 1 in multiclass TFRI_base<string CextOp> { let CextOpcode = CextOp, BaseOpcode = CextOp#I in { - let opExtendable = 1, opExtentBits = 16, isMoveImm = 1, isPredicable = 1, - isReMaterializable = 1 in - def #NAME# : ALU32_ri<(outs IntRegs:$dst), (ins s16Ext:$src1), + let isAsCheapAsAMove = 1 , opExtendable = 1, opExtentBits = 16, + isMoveImm = 1, isPredicable = 1, isReMaterializable = 1 in + def NAME : ALU32_ri<(outs IntRegs:$dst), (ins s16Ext:$src1), "$dst = #$src1", [(set (i32 IntRegs:$dst), s16ExtPred:$src1)]>; @@ -317,7 +343,7 @@ multiclass TFRI_base<string CextOp> { defm TFRI : TFRI_base<"TFR">, ImmRegRel, PredNewRel; defm TFR : TFR_base<"TFR">, ImmRegRel, PredNewRel; -defm TFR64 : TFR64_base<"TFR64">, ImmRegRel, PredNewRel; +defm TFR64 : TFR64_base<"TFR64">, PredNewRel; // Transfer control register. let neverHasSideEffects = 1 in @@ -808,7 +834,7 @@ let isBranch = 1, isTerminator=1, neverHasSideEffects = 1, Defs = [PC], // JR + //===----------------------------------------------------------------------===// def retflag : SDNode<"HexagonISD::RET_FLAG", SDTNone, - [SDNPHasChain, SDNPOptInGlue]>; + [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; // Jump to address from register. let isPredicable =1, isReturn = 1, isTerminator = 1, isBarrier = 1, @@ -845,19 +871,19 @@ let isReturn = 1, isTerminator = 1, isBarrier = 1, isPredicated = 1, // Load -- MEMri operand multiclass LD_MEMri_Pbase<string mnemonic, RegisterClass RC, bit isNot, bit isPredNew> { - let PNewValue = #!if(isPredNew, "new", "") in - def #NAME# : LDInst2<(outs RC:$dst), + let PNewValue = !if(isPredNew, "new", "") in + def NAME : LDInst2<(outs RC:$dst), (ins PredRegs:$src1, MEMri:$addr), - #!if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", ") ")#"$dst = "#mnemonic#"($addr)", []>; } multiclass LD_MEMri_Pred<string mnemonic, RegisterClass RC, bit PredNot> { - let PredSense = #!if(PredNot, "false", "true") in { - defm _c#NAME# : LD_MEMri_Pbase<mnemonic, RC, PredNot, 0>; + let PredSense = !if(PredNot, "false", "true") in { + defm _c#NAME : LD_MEMri_Pbase<mnemonic, RC, PredNot, 0>; // Predicate new - defm _cdn#NAME# : LD_MEMri_Pbase<mnemonic, RC, PredNot, 1>; + defm _cdn#NAME : LD_MEMri_Pbase<mnemonic, RC, PredNot, 1>; } } @@ -868,7 +894,7 @@ multiclass LD_MEMri<string mnemonic, string CextOp, RegisterClass RC, let CextOpcode = CextOp, BaseOpcode = CextOp in { let opExtendable = 2, isExtentSigned = 1, opExtentBits = ImmBits, isPredicable = 1 in - def #NAME# : LDInst2<(outs RC:$dst), (ins MEMri:$addr), + def NAME : LDInst2<(outs RC:$dst), (ins MEMri:$addr), "$dst = "#mnemonic#"($addr)", []>; @@ -911,20 +937,20 @@ def : Pat < (i64 (load ADDRriS11_3:$addr)), // Load - Base with Immediate offset addressing mode multiclass LD_Idxd_Pbase<string mnemonic, RegisterClass RC, Operand predImmOp, bit isNot, bit isPredNew> { - let PNewValue = #!if(isPredNew, "new", "") in - def #NAME# : LDInst2<(outs RC:$dst), - (ins PredRegs:$src1, IntRegs:$src2, predImmOp:$src3), - #!if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + let PNewValue = !if(isPredNew, "new", "") in + def NAME : LDInst2<(outs RC:$dst), + (ins PredRegs:$src1, IntRegs:$src2, predImmOp:$src3), + !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", ") ")#"$dst = "#mnemonic#"($src2+#$src3)", []>; } multiclass LD_Idxd_Pred<string mnemonic, RegisterClass RC, Operand predImmOp, bit PredNot> { - let PredSense = #!if(PredNot, "false", "true") in { - defm _c#NAME# : LD_Idxd_Pbase<mnemonic, RC, predImmOp, PredNot, 0>; + let PredSense = !if(PredNot, "false", "true") in { + defm _c#NAME : LD_Idxd_Pbase<mnemonic, RC, predImmOp, PredNot, 0>; // Predicate new - defm _cdn#NAME# : LD_Idxd_Pbase<mnemonic, RC, predImmOp, PredNot, 1>; + defm _cdn#NAME : LD_Idxd_Pbase<mnemonic, RC, predImmOp, PredNot, 1>; } } @@ -936,7 +962,7 @@ multiclass LD_Idxd<string mnemonic, string CextOp, RegisterClass RC, let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed in { let opExtendable = 2, isExtentSigned = 1, opExtentBits = ImmBits, isPredicable = 1, AddedComplexity = 20 in - def #NAME# : LDInst2<(outs RC:$dst), (ins IntRegs:$src1, ImmOp:$offset), + def NAME : LDInst2<(outs RC:$dst), (ins IntRegs:$src1, ImmOp:$offset), "$dst = "#mnemonic#"($src1+#$offset)", []>; @@ -990,7 +1016,7 @@ def LDrid_GP : LDInst2<(outs DoubleRegs:$dst), []>, Requires<[NoV4T]>; -let neverHasSideEffects = 1 in +let neverHasSideEffects = 1, validSubTargets = NoV4SubT in def LDd_GP : LDInst2<(outs DoubleRegs:$dst), (ins globaladdress:$global), "$dst = memd(#$global)", @@ -1005,10 +1031,10 @@ def LDd_GP : LDInst2<(outs DoubleRegs:$dst), multiclass LD_PostInc_Pbase<string mnemonic, RegisterClass RC, Operand ImmOp, bit isNot, bit isPredNew> { - let PNewValue = #!if(isPredNew, "new", "") in - def #NAME# : LDInst2PI<(outs RC:$dst, IntRegs:$dst2), + let PNewValue = !if(isPredNew, "new", "") in + def NAME : LDInst2PI<(outs RC:$dst, IntRegs:$dst2), (ins PredRegs:$src1, IntRegs:$src2, ImmOp:$offset), - #!if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", ") ")#"$dst = "#mnemonic#"($src2++#$offset)", [], "$src2 = $dst2">; @@ -1016,8 +1042,8 @@ multiclass LD_PostInc_Pbase<string mnemonic, RegisterClass RC, Operand ImmOp, multiclass LD_PostInc_Pred<string mnemonic, RegisterClass RC, Operand ImmOp, bit PredNot> { - let PredSense = #!if(PredNot, "false", "true") in { - defm _c#NAME# : LD_PostInc_Pbase<mnemonic, RC, ImmOp, PredNot, 0>; + let PredSense = !if(PredNot, "false", "true") in { + defm _c#NAME : LD_PostInc_Pbase<mnemonic, RC, ImmOp, PredNot, 0>; // Predicate new let Predicates = [HasV4T], validSubTargets = HasV4SubT in defm _cdn#NAME#_V4 : LD_PostInc_Pbase<mnemonic, RC, ImmOp, PredNot, 1>; @@ -1029,8 +1055,8 @@ multiclass LD_PostInc<string mnemonic, string BaseOp, RegisterClass RC, let BaseOpcode = "POST_"#BaseOp in { let isPredicable = 1 in - def #NAME# : LDInst2PI<(outs RC:$dst, IntRegs:$dst2), - (ins IntRegs:$src1, ImmOp:$offset), + def NAME : LDInst2PI<(outs RC:$dst, IntRegs:$dst2), + (ins IntRegs:$src1, ImmOp:$offset), "$dst = "#mnemonic#"($src1++#$offset)", [], "$src1 = $dst2">; @@ -1057,6 +1083,9 @@ let hasCtrlDep = 1, neverHasSideEffects = 1 in { PredNewRel; } +def : Pat< (i32 (extloadi1 ADDRriS11_0:$addr)), + (i32 (LDrib ADDRriS11_0:$addr)) >; + // Load byte any-extend. def : Pat < (i32 (extloadi8 ADDRriS11_0:$addr)), (i32 (LDrib ADDRriS11_0:$addr)) >; @@ -1073,14 +1102,14 @@ def LDrib_GP : LDInst2<(outs IntRegs:$dst), []>, Requires<[NoV4T]>; -let neverHasSideEffects = 1 in +let neverHasSideEffects = 1, validSubTargets = NoV4SubT in def LDb_GP : LDInst2<(outs IntRegs:$dst), (ins globaladdress:$global), "$dst = memb(#$global)", []>, Requires<[NoV4T]>; -let neverHasSideEffects = 1 in +let neverHasSideEffects = 1, validSubTargets = NoV4SubT in def LDub_GP : LDInst2<(outs IntRegs:$dst), (ins globaladdress:$global), "$dst = memub(#$global)", @@ -1101,20 +1130,21 @@ def LDrih_GP : LDInst2<(outs IntRegs:$dst), []>, Requires<[NoV4T]>; -let neverHasSideEffects = 1 in +let neverHasSideEffects = 1, validSubTargets = NoV4SubT in def LDh_GP : LDInst2<(outs IntRegs:$dst), (ins globaladdress:$global), "$dst = memh(#$global)", []>, Requires<[NoV4T]>; -let neverHasSideEffects = 1 in +let neverHasSideEffects = 1, validSubTargets = NoV4SubT in def LDuh_GP : LDInst2<(outs IntRegs:$dst), (ins globaladdress:$global), "$dst = memuh(#$global)", []>, Requires<[NoV4T]>; +let AddedComplexity = 10 in def : Pat < (i32 (zextloadi1 ADDRriS11_0:$addr)), (i32 (LDriub ADDRriS11_0:$addr))>; @@ -1138,8 +1168,9 @@ def LDriuh_GP : LDInst2<(outs IntRegs:$dst), Requires<[NoV4T]>; // Load predicate. -let Defs = [R10,R11,D5], neverHasSideEffects = 1 in -def LDriw_pred : LDInst<(outs PredRegs:$dst), +let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 13, +isPseudo = 1, Defs = [R10,R11,D5], neverHasSideEffects = 1 in +def LDriw_pred : LDInst2<(outs PredRegs:$dst), (ins MEMri:$addr), "Error; should not emit", []>; @@ -1152,7 +1183,7 @@ def LDriw_GP : LDInst2<(outs IntRegs:$dst), []>, Requires<[NoV4T]>; -let neverHasSideEffects = 1 in +let neverHasSideEffects = 1, validSubTargets = NoV4SubT in def LDw_GP : LDInst2<(outs IntRegs:$dst), (ins globaladdress:$global), "$dst = memw(#$global)", @@ -1161,7 +1192,7 @@ def LDw_GP : LDInst2<(outs IntRegs:$dst), // Deallocate stack frame. let Defs = [R29, R30, R31], Uses = [R29], neverHasSideEffects = 1 in { - def DEALLOCFRAME : LDInst2<(outs), (ins i32imm:$amt1), + def DEALLOCFRAME : LDInst2<(outs), (ins), "deallocframe", []>; } @@ -1190,57 +1221,65 @@ let Defs = [R29, R30, R31], Uses = [R29], neverHasSideEffects = 1 in { //===----------------------------------------------------------------------===// // Multiply and use lower result. // Rd=+mpyi(Rs,#u8) -def MPYI_riu : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u8Imm:$src2), +let isExtendable = 1, opExtendable = 2, isExtentSigned = 0, opExtentBits = 8 in +def MPYI_riu : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u8Ext:$src2), "$dst =+ mpyi($src1, #$src2)", [(set (i32 IntRegs:$dst), (mul (i32 IntRegs:$src1), - u8ImmPred:$src2))]>; + u8ExtPred:$src2))]>; // Rd=-mpyi(Rs,#u8) -def MPYI_rin : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, n8Imm:$src2), +def MPYI_rin : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u8Imm:$src2), "$dst =- mpyi($src1, #$src2)", - [(set (i32 IntRegs:$dst), (mul (i32 IntRegs:$src1), - n8ImmPred:$src2))]>; + [(set (i32 IntRegs:$dst), (ineg (mul (i32 IntRegs:$src1), + u8ImmPred:$src2)))]>; // Rd=mpyi(Rs,#m9) // s9 is NOT the same as m9 - but it works.. so far. // Assembler maps to either Rd=+mpyi(Rs,#u8 or Rd=-mpyi(Rs,#u8) // depending on the value of m9. See Arch Spec. -def MPYI_ri : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, s9Imm:$src2), +let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 9, +CextOpcode = "MPYI", InputType = "imm" in +def MPYI_ri : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, s9Ext:$src2), "$dst = mpyi($src1, #$src2)", [(set (i32 IntRegs:$dst), (mul (i32 IntRegs:$src1), - s9ImmPred:$src2))]>; + s9ExtPred:$src2))]>, ImmRegRel; // Rd=mpyi(Rs,Rt) +let CextOpcode = "MPYI", InputType = "reg" in def MPYI : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), "$dst = mpyi($src1, $src2)", [(set (i32 IntRegs:$dst), (mul (i32 IntRegs:$src1), - (i32 IntRegs:$src2)))]>; + (i32 IntRegs:$src2)))]>, ImmRegRel; // Rx+=mpyi(Rs,#u8) +let isExtendable = 1, opExtendable = 3, isExtentSigned = 0, opExtentBits = 8, +CextOpcode = "MPYI_acc", InputType = "imm" in def MPYI_acc_ri : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, u8Imm:$src3), + (ins IntRegs:$src1, IntRegs:$src2, u8Ext:$src3), "$dst += mpyi($src2, #$src3)", [(set (i32 IntRegs:$dst), - (add (mul (i32 IntRegs:$src2), u8ImmPred:$src3), + (add (mul (i32 IntRegs:$src2), u8ExtPred:$src3), (i32 IntRegs:$src1)))], - "$src1 = $dst">; + "$src1 = $dst">, ImmRegRel; // Rx+=mpyi(Rs,Rt) +let CextOpcode = "MPYI_acc", InputType = "reg" in def MPYI_acc_rr : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2, IntRegs:$src3), "$dst += mpyi($src2, $src3)", [(set (i32 IntRegs:$dst), (add (mul (i32 IntRegs:$src2), (i32 IntRegs:$src3)), (i32 IntRegs:$src1)))], - "$src1 = $dst">; + "$src1 = $dst">, ImmRegRel; // Rx-=mpyi(Rs,#u8) +let isExtendable = 1, opExtendable = 3, isExtentSigned = 0, opExtentBits = 8 in def MPYI_sub_ri : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, u8Imm:$src3), + (ins IntRegs:$src1, IntRegs:$src2, u8Ext:$src3), "$dst -= mpyi($src2, #$src3)", [(set (i32 IntRegs:$dst), (sub (i32 IntRegs:$src1), (mul (i32 IntRegs:$src2), - u8ImmPred:$src3)))], + u8ExtPred:$src3)))], "$src1 = $dst">; // Multiply and use upper result. @@ -1309,7 +1348,7 @@ def MPYU64_acc : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, // Rxx-=mpyu(Rs,Rt) def MPYU64_sub : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "$dst += mpyu($src2, $src3)", + "$dst -= mpyu($src2, $src3)", [(set (i64 DoubleRegs:$dst), (sub (i64 DoubleRegs:$src1), (mul (i64 (anyext (i32 IntRegs:$src2))), @@ -1317,37 +1356,43 @@ def MPYU64_sub : MInst_acc<(outs DoubleRegs:$dst), "$src1 = $dst">; +let InputType = "reg", CextOpcode = "ADD_acc" in def ADDrr_acc : MInst_acc<(outs IntRegs: $dst), (ins IntRegs:$src1, IntRegs:$src2, IntRegs:$src3), "$dst += add($src2, $src3)", [(set (i32 IntRegs:$dst), (add (add (i32 IntRegs:$src2), (i32 IntRegs:$src3)), (i32 IntRegs:$src1)))], - "$src1 = $dst">; + "$src1 = $dst">, ImmRegRel; +let isExtendable = 1, opExtendable = 3, isExtentSigned = 1, opExtentBits = 8, +InputType = "imm", CextOpcode = "ADD_acc" in def ADDri_acc : MInst_acc<(outs IntRegs: $dst), (ins IntRegs:$src1, - IntRegs:$src2, s8Imm:$src3), + IntRegs:$src2, s8Ext:$src3), "$dst += add($src2, #$src3)", [(set (i32 IntRegs:$dst), (add (add (i32 IntRegs:$src2), - s8ImmPred:$src3), + s8_16ExtPred:$src3), (i32 IntRegs:$src1)))], - "$src1 = $dst">; + "$src1 = $dst">, ImmRegRel; +let CextOpcode = "SUB_acc", InputType = "reg" in def SUBrr_acc : MInst_acc<(outs IntRegs: $dst), (ins IntRegs:$src1, IntRegs:$src2, IntRegs:$src3), "$dst -= add($src2, $src3)", [(set (i32 IntRegs:$dst), (sub (i32 IntRegs:$src1), (add (i32 IntRegs:$src2), (i32 IntRegs:$src3))))], - "$src1 = $dst">; + "$src1 = $dst">, ImmRegRel; +let isExtendable = 1, opExtendable = 3, isExtentSigned = 1, opExtentBits = 8, +CextOpcode = "SUB_acc", InputType = "imm" in def SUBri_acc : MInst_acc<(outs IntRegs: $dst), (ins IntRegs:$src1, - IntRegs:$src2, s8Imm:$src3), + IntRegs:$src2, s8Ext:$src3), "$dst -= add($src2, #$src3)", [(set (i32 IntRegs:$dst), (sub (i32 IntRegs:$src1), (add (i32 IntRegs:$src2), - s8ImmPred:$src3)))], - "$src1 = $dst">; + s8_16ExtPred:$src3)))], + "$src1 = $dst">, ImmRegRel; //===----------------------------------------------------------------------===// // MTYPE/MPYH - @@ -1393,50 +1438,86 @@ def STrid_GP : STInst2<(outs), []>, Requires<[NoV4T]>; -let neverHasSideEffects = 1 in +let neverHasSideEffects = 1, validSubTargets = NoV4SubT in def STd_GP : STInst2<(outs), (ins globaladdress:$global, DoubleRegs:$src), "memd(#$global) = $src", []>, Requires<[NoV4T]>; -let hasCtrlDep = 1, isPredicable = 1 in -def POST_STdri : STInstPI<(outs IntRegs:$dst), - (ins DoubleRegs:$src1, IntRegs:$src2, s4Imm:$offset), - "memd($src2++#$offset) = $src1", - [(set IntRegs:$dst, - (post_store (i64 DoubleRegs:$src1), (i32 IntRegs:$src2), - s4_3ImmPred:$offset))], - "$src2 = $dst">; +//===----------------------------------------------------------------------===// +// Post increment store +//===----------------------------------------------------------------------===// -// if ([!]Pv) memd(Rx++#s4:3)=Rtt -// if (Pv) memd(Rx++#s4:3)=Rtt -let AddedComplexity = 10, neverHasSideEffects = 1, - isPredicated = 1 in -def POST_STdri_cPt : STInst2PI<(outs IntRegs:$dst), - (ins PredRegs:$src1, DoubleRegs:$src2, IntRegs:$src3, - s4_3Imm:$offset), - "if ($src1) memd($src3++#$offset) = $src2", - [], - "$src3 = $dst">; - -// if (!Pv) memd(Rx++#s4:3)=Rtt -let AddedComplexity = 10, neverHasSideEffects = 1, isPredicated = 1, - isPredicated = 1 in -def POST_STdri_cNotPt : STInst2PI<(outs IntRegs:$dst), - (ins PredRegs:$src1, DoubleRegs:$src2, IntRegs:$src3, - s4_3Imm:$offset), - "if (!$src1) memd($src3++#$offset) = $src2", +multiclass ST_PostInc_Pbase<string mnemonic, RegisterClass RC, Operand ImmOp, + bit isNot, bit isPredNew> { + let PNewValue = !if(isPredNew, "new", "") in + def NAME : STInst2PI<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, ImmOp:$offset, RC:$src3), + !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + ") ")#mnemonic#"($src2++#$offset) = $src3", [], - "$src3 = $dst">; + "$src2 = $dst">; +} + +multiclass ST_PostInc_Pred<string mnemonic, RegisterClass RC, + Operand ImmOp, bit PredNot> { + let PredSense = !if(PredNot, "false", "true") in { + defm _c#NAME# : ST_PostInc_Pbase<mnemonic, RC, ImmOp, PredNot, 0>; + // Predicate new + let Predicates = [HasV4T], validSubTargets = HasV4SubT in + defm _cdn#NAME#_V4 : ST_PostInc_Pbase<mnemonic, RC, ImmOp, PredNot, 1>; + } +} + +let hasCtrlDep = 1, isNVStorable = 1, neverHasSideEffects = 1 in +multiclass ST_PostInc<string mnemonic, string BaseOp, RegisterClass RC, + Operand ImmOp> { + + let hasCtrlDep = 1, BaseOpcode = "POST_"#BaseOp in { + let isPredicable = 1 in + def NAME : STInst2PI<(outs IntRegs:$dst), + (ins IntRegs:$src1, ImmOp:$offset, RC:$src2), + #mnemonic#"($src1++#$offset) = $src2", + [], + "$src1 = $dst">; + + let isPredicated = 1 in { + defm Pt : ST_PostInc_Pred<mnemonic, RC, ImmOp, 0 >; + defm NotPt : ST_PostInc_Pred<mnemonic, RC, ImmOp, 1 >; + } + } +} + +defm POST_STbri: ST_PostInc <"memb", "STrib", IntRegs, s4_0Imm>, AddrModeRel; +defm POST_SThri: ST_PostInc <"memh", "STrih", IntRegs, s4_1Imm>, AddrModeRel; +defm POST_STwri: ST_PostInc <"memw", "STriw", IntRegs, s4_2Imm>, AddrModeRel; + +let isNVStorable = 0 in +defm POST_STdri: ST_PostInc <"memd", "STrid", DoubleRegs, s4_3Imm>, AddrModeRel; + +def : Pat<(post_truncsti8 (i32 IntRegs:$src1), IntRegs:$src2, + s4_3ImmPred:$offset), + (POST_STbri IntRegs:$src2, s4_0ImmPred:$offset, IntRegs:$src1)>; + +def : Pat<(post_truncsti16 (i32 IntRegs:$src1), IntRegs:$src2, + s4_3ImmPred:$offset), + (POST_SThri IntRegs:$src2, s4_1ImmPred:$offset, IntRegs:$src1)>; + +def : Pat<(post_store (i32 IntRegs:$src1), IntRegs:$src2, s4_2ImmPred:$offset), + (POST_STwri IntRegs:$src2, s4_1ImmPred:$offset, IntRegs:$src1)>; + +def : Pat<(post_store (i64 DoubleRegs:$src1), IntRegs:$src2, + s4_3ImmPred:$offset), + (POST_STdri IntRegs:$src2, s4_3ImmPred:$offset, DoubleRegs:$src1)>; //===----------------------------------------------------------------------===// // multiclass for the store instructions with MEMri operand. //===----------------------------------------------------------------------===// multiclass ST_MEMri_Pbase<string mnemonic, RegisterClass RC, bit isNot, bit isPredNew> { - let PNewValue = #!if(isPredNew, "new", "") in - def #NAME# : STInst2<(outs), + let PNewValue = !if(isPredNew, "new", "") in + def NAME : STInst2<(outs), (ins PredRegs:$src1, MEMri:$addr, RC: $src2), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", ") ")#mnemonic#"($addr) = $src2", @@ -1444,8 +1525,8 @@ multiclass ST_MEMri_Pbase<string mnemonic, RegisterClass RC, bit isNot, } multiclass ST_MEMri_Pred<string mnemonic, RegisterClass RC, bit PredNot> { - let PredSense = #!if(PredNot, "false", "true") in { - defm _c#NAME# : ST_MEMri_Pbase<mnemonic, RC, PredNot, 0>; + let PredSense = !if(PredNot, "false", "true") in { + defm _c#NAME : ST_MEMri_Pbase<mnemonic, RC, PredNot, 0>; // Predicate new let validSubTargets = HasV4SubT, Predicates = [HasV4T] in @@ -1460,9 +1541,9 @@ multiclass ST_MEMri<string mnemonic, string CextOp, RegisterClass RC, let CextOpcode = CextOp, BaseOpcode = CextOp in { let opExtendable = 1, isExtentSigned = 1, opExtentBits = ImmBits, isPredicable = 1 in - def #NAME# : STInst2<(outs), + def NAME : STInst2<(outs), (ins MEMri:$addr, RC:$src), - #mnemonic#"($addr) = $src", + mnemonic#"($addr) = $src", []>; let opExtendable = 2, isExtentSigned = 0, opExtentBits = PredImmBits, @@ -1501,8 +1582,8 @@ def : Pat<(store (i64 DoubleRegs:$src1), ADDRriS11_3:$addr), //===----------------------------------------------------------------------===// multiclass ST_Idxd_Pbase<string mnemonic, RegisterClass RC, Operand predImmOp, bit isNot, bit isPredNew> { - let PNewValue = #!if(isPredNew, "new", "") in - def #NAME# : STInst2<(outs), + let PNewValue = !if(isPredNew, "new", "") in + def NAME : STInst2<(outs), (ins PredRegs:$src1, IntRegs:$src2, predImmOp:$src3, RC: $src4), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", ") ")#mnemonic#"($src2+#$src3) = $src4", @@ -1511,8 +1592,8 @@ multiclass ST_Idxd_Pbase<string mnemonic, RegisterClass RC, Operand predImmOp, multiclass ST_Idxd_Pred<string mnemonic, RegisterClass RC, Operand predImmOp, bit PredNot> { - let PredSense = #!if(PredNot, "false", "true"), isPredicated = 1 in { - defm _c#NAME# : ST_Idxd_Pbase<mnemonic, RC, predImmOp, PredNot, 0>; + let PredSense = !if(PredNot, "false", "true"), isPredicated = 1 in { + defm _c#NAME : ST_Idxd_Pbase<mnemonic, RC, predImmOp, PredNot, 0>; // Predicate new let validSubTargets = HasV4SubT, Predicates = [HasV4T] in @@ -1528,9 +1609,9 @@ multiclass ST_Idxd<string mnemonic, string CextOp, RegisterClass RC, let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed in { let opExtendable = 1, isExtentSigned = 1, opExtentBits = ImmBits, isPredicable = 1 in - def #NAME# : STInst2<(outs), + def NAME : STInst2<(outs), (ins IntRegs:$src1, ImmOp:$src2, RC:$src3), - #mnemonic#"($src1+#$src2) = $src3", + mnemonic#"($src1+#$src2) = $src3", []>; let opExtendable = 2, isExtentSigned = 0, opExtentBits = PredImmBits in { @@ -1583,39 +1664,13 @@ def STrib_GP : STInst2<(outs), Requires<[NoV4T]>; // memb(#global)=Rt -let neverHasSideEffects = 1 in +let neverHasSideEffects = 1, validSubTargets = NoV4SubT in def STb_GP : STInst2<(outs), (ins globaladdress:$global, IntRegs:$src), "memb(#$global) = $src", []>, Requires<[NoV4T]>; -// memb(Rx++#s4:0)=Rt -let hasCtrlDep = 1, isPredicable = 1 in -def POST_STbri : STInstPI<(outs IntRegs:$dst), (ins IntRegs:$src1, - IntRegs:$src2, - s4Imm:$offset), - "memb($src2++#$offset) = $src1", - [(set IntRegs:$dst, - (post_truncsti8 (i32 IntRegs:$src1), (i32 IntRegs:$src2), - s4_0ImmPred:$offset))], - "$src2 = $dst">; - -// if ([!]Pv) memb(Rx++#s4:0)=Rt -// if (Pv) memb(Rx++#s4:0)=Rt -let hasCtrlDep = 1, isPredicated = 1 in -def POST_STbri_cPt : STInst2PI<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_0Imm:$offset), - "if ($src1) memb($src3++#$offset) = $src2", - [],"$src3 = $dst">; - -// if (!Pv) memb(Rx++#s4:0)=Rt -let hasCtrlDep = 1, isPredicated = 1 in -def POST_STbri_cNotPt : STInst2PI<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_0Imm:$offset), - "if (!$src1) memb($src3++#$offset) = $src2", - [],"$src3 = $dst">; - let neverHasSideEffects = 1 in def STrih_GP : STInst2<(outs), (ins globaladdress:$global, u16Imm:$offset, IntRegs:$src), @@ -1623,7 +1678,7 @@ def STrih_GP : STInst2<(outs), []>, Requires<[NoV4T]>; -let neverHasSideEffects = 1 in +let neverHasSideEffects = 1, validSubTargets = NoV4SubT in def STh_GP : STInst2<(outs), (ins globaladdress:$global, IntRegs:$src), "memh(#$global) = $src", @@ -1631,31 +1686,6 @@ def STh_GP : STInst2<(outs), Requires<[NoV4T]>; // memh(Rx++#s4:1)=Rt.H -// memh(Rx++#s4:1)=Rt -let hasCtrlDep = 1, isPredicable = 1 in -def POST_SThri : STInstPI<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, s4Imm:$offset), - "memh($src2++#$offset) = $src1", - [(set IntRegs:$dst, - (post_truncsti16 (i32 IntRegs:$src1), (i32 IntRegs:$src2), - s4_1ImmPred:$offset))], - "$src2 = $dst">; - -// if ([!]Pv) memh(Rx++#s4:1)=Rt -// if (Pv) memh(Rx++#s4:1)=Rt -let hasCtrlDep = 1, isPredicated = 1 in -def POST_SThri_cPt : STInst2PI<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_1Imm:$offset), - "if ($src1) memh($src3++#$offset) = $src2", - [],"$src3 = $dst">; - -// if (!Pv) memh(Rx++#s4:1)=Rt -let hasCtrlDep = 1, isPredicated = 1 in -def POST_SThri_cNotPt : STInst2PI<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_1Imm:$offset), - "if (!$src1) memh($src3++#$offset) = $src2", - [],"$src3 = $dst">; - // Store word. // Store predicate. @@ -1672,39 +1702,13 @@ def STriw_GP : STInst2<(outs), []>, Requires<[NoV4T]>; -let neverHasSideEffects = 1 in +let neverHasSideEffects = 1, validSubTargets = NoV4SubT in def STw_GP : STInst2<(outs), (ins globaladdress:$global, IntRegs:$src), "memw(#$global) = $src", []>, Requires<[NoV4T]>; -let hasCtrlDep = 1, isPredicable = 1 in -def POST_STwri : STInstPI<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, s4Imm:$offset), - "memw($src2++#$offset) = $src1", - [(set IntRegs:$dst, - (post_store (i32 IntRegs:$src1), (i32 IntRegs:$src2), - s4_2ImmPred:$offset))], - "$src2 = $dst">; - -// if ([!]Pv) memw(Rx++#s4:2)=Rt -// if (Pv) memw(Rx++#s4:2)=Rt -let hasCtrlDep = 1, isPredicated = 1 in -def POST_STwri_cPt : STInst2PI<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_2Imm:$offset), - "if ($src1) memw($src3++#$offset) = $src2", - [],"$src3 = $dst">; - -// if (!Pv) memw(Rx++#s4:2)=Rt -let hasCtrlDep = 1, isPredicated = 1 in -def POST_STwri_cNotPt : STInst2PI<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_2Imm:$offset), - "if (!$src1) memw($src3++#$offset) = $src2", - [],"$src3 = $dst">; - - - // Allocate stack frame. let Defs = [R29, R30], Uses = [R31, R30], neverHasSideEffects = 1 in { def ALLOCFRAME : STInst2<(outs), @@ -1907,7 +1911,7 @@ def SDHexagonBARRIER: SDTypeProfile<0, 0, []>; def HexagonBARRIER: SDNode<"HexagonISD::BARRIER", SDHexagonBARRIER, [SDNPHasChain]>; -let hasSideEffects = 1, isHexagonSolo = 1 in +let hasSideEffects = 1, isSolo = 1 in def BARRIER : SYSInst<(outs), (ins), "barrier", [(HexagonBARRIER)]>; @@ -1982,9 +1986,9 @@ def LOOP0_r : CRInst<(outs), (ins brtarget:$offset, IntRegs:$src2), let isBranch = 1, isTerminator = 1, neverHasSideEffects = 1, Defs = [PC, LC0], Uses = [SA0, LC0] in { -def ENDLOOP0 : Marker<(outs), (ins brtarget:$offset), - ":endloop0", - []>; +def ENDLOOP0 : Endloop<(outs), (ins brtarget:$offset), + ":endloop0", + []>; } // Support for generating global address. @@ -2072,6 +2076,10 @@ def CONST32_Int_Real : LDInst2<(outs IntRegs:$dst), (ins i32imm:$global), "$dst = CONST32(#$global)", [(set (i32 IntRegs:$dst), imm:$global) ]>; +// Map BlockAddress lowering to CONST32_Int_Real +def : Pat<(HexagonCONST32_GP tblockaddress:$addr), + (CONST32_Int_Real tblockaddress:$addr)>; + let isReMaterializable = 1, isMoveImm = 1 in def CONST32_Label : LDInst2<(outs IntRegs:$dst), (ins bblabel:$label), "$dst = CONST32($label)", @@ -2847,23 +2855,54 @@ def : Pat <(i32 (zext (i1 PredRegs:$src1))), // i1 -> i64 def : Pat <(i64 (zext (i1 PredRegs:$src1))), - (i64 (COMBINE_rr (TFRI 0), (MUX_ii (i1 PredRegs:$src1), 1, 0)))>; + (i64 (COMBINE_rr (TFRI 0), (MUX_ii (i1 PredRegs:$src1), 1, 0)))>, + Requires<[NoV4T]>; // i32 -> i64 def : Pat <(i64 (zext (i32 IntRegs:$src1))), - (i64 (COMBINE_rr (TFRI 0), (i32 IntRegs:$src1)))>; + (i64 (COMBINE_rr (TFRI 0), (i32 IntRegs:$src1)))>, + Requires<[NoV4T]>; // i8 -> i64 def: Pat <(i64 (zextloadi8 ADDRriS11_0:$src1)), - (i64 (COMBINE_rr (TFRI 0), (LDriub ADDRriS11_0:$src1)))>; + (i64 (COMBINE_rr (TFRI 0), (LDriub ADDRriS11_0:$src1)))>, + Requires<[NoV4T]>; + +let AddedComplexity = 20 in +def: Pat <(i64 (zextloadi8 (add (i32 IntRegs:$src1), + s11_0ExtPred:$offset))), + (i64 (COMBINE_rr (TFRI 0), (LDriub_indexed IntRegs:$src1, + s11_0ExtPred:$offset)))>, + Requires<[NoV4T]>; + +// i1 -> i64 +def: Pat <(i64 (zextloadi1 ADDRriS11_0:$src1)), + (i64 (COMBINE_rr (TFRI 0), (LDriub ADDRriS11_0:$src1)))>, + Requires<[NoV4T]>; + +let AddedComplexity = 20 in +def: Pat <(i64 (zextloadi1 (add (i32 IntRegs:$src1), + s11_0ExtPred:$offset))), + (i64 (COMBINE_rr (TFRI 0), (LDriub_indexed IntRegs:$src1, + s11_0ExtPred:$offset)))>, + Requires<[NoV4T]>; // i16 -> i64 def: Pat <(i64 (zextloadi16 ADDRriS11_1:$src1)), - (i64 (COMBINE_rr (TFRI 0), (LDriuh ADDRriS11_1:$src1)))>; + (i64 (COMBINE_rr (TFRI 0), (LDriuh ADDRriS11_1:$src1)))>, + Requires<[NoV4T]>; + +let AddedComplexity = 20 in +def: Pat <(i64 (zextloadi16 (add (i32 IntRegs:$src1), + s11_1ExtPred:$offset))), + (i64 (COMBINE_rr (TFRI 0), (LDriuh_indexed IntRegs:$src1, + s11_1ExtPred:$offset)))>, + Requires<[NoV4T]>; // i32 -> i64 def: Pat <(i64 (zextloadi32 ADDRriS11_2:$src1)), - (i64 (COMBINE_rr (TFRI 0), (LDriw ADDRriS11_2:$src1)))>; + (i64 (COMBINE_rr (TFRI 0), (LDriw ADDRriS11_2:$src1)))>, + Requires<[NoV4T]>; def: Pat <(i32 (zextloadi1 ADDRriS11_0:$src1)), (i32 (LDriw ADDRriS11_0:$src1))>; @@ -2884,15 +2923,41 @@ def : Pat <(i64 (anyext (i1 PredRegs:$src1))), // Any extended 64-bit load. // anyext i32 -> i64 def: Pat <(i64 (extloadi32 ADDRriS11_2:$src1)), - (i64 (COMBINE_rr (TFRI 0), (LDriw ADDRriS11_2:$src1)))>; + (i64 (COMBINE_rr (TFRI 0), (LDriw ADDRriS11_2:$src1)))>, + Requires<[NoV4T]>; + +// When there is an offset we should prefer the pattern below over the pattern above. +// The complexity of the above is 13 (gleaned from HexagonGenDAGIsel.inc) +// So this complexity below is comfortably higher to allow for choosing the below. +// If this is not done then we generate addresses such as +// ******************************************** +// r1 = add (r0, #4) +// r1 = memw(r1 + #0) +// instead of +// r1 = memw(r0 + #4) +// ******************************************** +let AddedComplexity = 100 in +def: Pat <(i64 (extloadi32 (i32 (add IntRegs:$src1, s11_2ExtPred:$offset)))), + (i64 (COMBINE_rr (TFRI 0), (LDriw_indexed IntRegs:$src1, + s11_2ExtPred:$offset)))>, + Requires<[NoV4T]>; // anyext i16 -> i64. def: Pat <(i64 (extloadi16 ADDRriS11_2:$src1)), - (i64 (COMBINE_rr (TFRI 0), (LDrih ADDRriS11_2:$src1)))>; + (i64 (COMBINE_rr (TFRI 0), (LDrih ADDRriS11_2:$src1)))>, + Requires<[NoV4T]>; + +let AddedComplexity = 20 in +def: Pat <(i64 (extloadi16 (add (i32 IntRegs:$src1), + s11_1ExtPred:$offset))), + (i64 (COMBINE_rr (TFRI 0), (LDrih_indexed IntRegs:$src1, + s11_1ExtPred:$offset)))>, + Requires<[NoV4T]>; // Map from Rdd = zxtw(Rs) -> Rdd = combine(0, Rs). def : Pat<(i64 (zext (i32 IntRegs:$src1))), - (i64 (COMBINE_rr (TFRI 0), (i32 IntRegs:$src1)))>; + (i64 (COMBINE_rr (TFRI 0), (i32 IntRegs:$src1)))>, + Requires<[NoV4T]>; // Multiply 64-bit unsigned and use upper result. def : Pat <(mulhu (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2)), @@ -2997,6 +3062,11 @@ def BR_JT : JRInst<(outs), (ins IntRegs:$src), "jumpr $src", [(HexagonBR_JT (i32 IntRegs:$src))]>; +let isBranch=1, isIndirectBranch=1, isTerminator=1 in +def BRIND : JRInst<(outs), (ins IntRegs:$src), + "jumpr $src", + [(brind (i32 IntRegs:$src))]>; + def HexagonWrapperJT: SDNode<"HexagonISD::WrapperJT", SDTIntUnaryOp>; def : Pat<(HexagonWrapperJT tjumptable:$dst), diff --git a/lib/Target/Hexagon/HexagonInstrInfoV4.td b/lib/Target/Hexagon/HexagonInstrInfoV4.td index ae407db029..1d0643d03b 100644 --- a/lib/Target/Hexagon/HexagonInstrInfoV4.td +++ b/lib/Target/Hexagon/HexagonInstrInfoV4.td @@ -12,10 +12,25 @@ //===----------------------------------------------------------------------===// let neverHasSideEffects = 1 in -def IMMEXT : Immext<(outs), (ins), - "/* immext #... */", - []>, - Requires<[HasV4T]>; +class T_Immext<dag ins> : + EXTENDERInst<(outs), ins, "immext(#$imm)", []>, + Requires<[HasV4T]>; + +def IMMEXT_b : T_Immext<(ins brtarget:$imm)>; +def IMMEXT_c : T_Immext<(ins calltarget:$imm)>; +def IMMEXT_g : T_Immext<(ins globaladdress:$imm)>; +def IMMEXT_i : T_Immext<(ins u26_6Imm:$imm)>; + +// Fold (add (CONST32 tglobaladdr:$addr) <offset>) into a global address. +def FoldGlobalAddr : ComplexPattern<i32, 1, "foldGlobalAddress", [], []>; + +// Fold (add (CONST32_GP tglobaladdr:$addr) <offset>) into a global address. +def FoldGlobalAddrGP : ComplexPattern<i32, 1, "foldGlobalAddressGP", [], []>; + +def NumUsesBelowThresCONST32 : PatFrag<(ops node:$addr), + (HexagonCONST32 node:$addr), [{ + return hasNumUsesBelowThresGA(N->getOperand(0).getNode()); +}]>; // Hexagon V4 Architecture spec defines 8 instruction classes: // LD ST ALU32 XTYPE J JR MEMOP NV CR SYSTEM(system is not implemented in the @@ -83,86 +98,77 @@ def IMMEXT : Immext<(outs), (ins), // Shift halfword. -let isPredicated = 1 in +let isPredicated = 1, neverHasSideEffects = 1, validSubTargets = HasV4SubT in { def ASLH_cPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if ($src1) $dst = aslh($src2)", []>, Requires<[HasV4T]>; -let isPredicated = 1 in def ASLH_cNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if (!$src1) $dst = aslh($src2)", []>, Requires<[HasV4T]>; -let isPredicated = 1 in def ASLH_cdnPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if ($src1.new) $dst = aslh($src2)", []>, Requires<[HasV4T]>; -let isPredicated = 1 in def ASLH_cdnNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if (!$src1.new) $dst = aslh($src2)", []>, Requires<[HasV4T]>; -let isPredicated = 1 in def ASRH_cPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if ($src1) $dst = asrh($src2)", []>, Requires<[HasV4T]>; -let isPredicated = 1 in def ASRH_cNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if (!$src1) $dst = asrh($src2)", []>, Requires<[HasV4T]>; -let isPredicated = 1 in def ASRH_cdnPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if ($src1.new) $dst = asrh($src2)", []>, Requires<[HasV4T]>; -let isPredicated = 1 in def ASRH_cdnNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if (!$src1.new) $dst = asrh($src2)", []>, Requires<[HasV4T]>; +} // Sign extend. -let isPredicated = 1 in +let isPredicated = 1, neverHasSideEffects = 1, validSubTargets = HasV4SubT in { def SXTB_cPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if ($src1) $dst = sxtb($src2)", []>, Requires<[HasV4T]>; -let isPredicated = 1 in def SXTB_cNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if (!$src1) $dst = sxtb($src2)", []>, Requires<[HasV4T]>; -let isPredicated = 1 in def SXTB_cdnPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if ($src1.new) $dst = sxtb($src2)", []>, Requires<[HasV4T]>; -let isPredicated = 1 in def SXTB_cdnNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if (!$src1.new) $dst = sxtb($src2)", @@ -170,100 +176,140 @@ def SXTB_cdnNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), Requires<[HasV4T]>; -let isPredicated = 1 in def SXTH_cPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if ($src1) $dst = sxth($src2)", []>, Requires<[HasV4T]>; -let isPredicated = 1 in def SXTH_cNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if (!$src1) $dst = sxth($src2)", []>, Requires<[HasV4T]>; -let isPredicated = 1 in def SXTH_cdnPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if ($src1.new) $dst = sxth($src2)", []>, Requires<[HasV4T]>; -let isPredicated = 1 in def SXTH_cdnNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if (!$src1.new) $dst = sxth($src2)", []>, Requires<[HasV4T]>; +} // Zero exten. -let neverHasSideEffects = 1, isPredicated = 1 in +let neverHasSideEffects = 1, isPredicated = 1, validSubTargets = HasV4SubT in { def ZXTB_cPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if ($src1) $dst = zxtb($src2)", []>, Requires<[HasV4T]>; -let neverHasSideEffects = 1, isPredicated = 1 in def ZXTB_cNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if (!$src1) $dst = zxtb($src2)", []>, Requires<[HasV4T]>; -let neverHasSideEffects = 1, isPredicated = 1 in def ZXTB_cdnPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if ($src1.new) $dst = zxtb($src2)", []>, Requires<[HasV4T]>; -let neverHasSideEffects = 1, isPredicated = 1 in def ZXTB_cdnNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if (!$src1.new) $dst = zxtb($src2)", []>, Requires<[HasV4T]>; -let neverHasSideEffects = 1, isPredicated = 1 in def ZXTH_cPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if ($src1) $dst = zxth($src2)", []>, Requires<[HasV4T]>; -let neverHasSideEffects = 1, isPredicated = 1 in def ZXTH_cNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if (!$src1) $dst = zxth($src2)", []>, Requires<[HasV4T]>; -let neverHasSideEffects = 1, isPredicated = 1 in def ZXTH_cdnPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if ($src1.new) $dst = zxth($src2)", []>, Requires<[HasV4T]>; -let neverHasSideEffects = 1, isPredicated = 1 in def ZXTH_cdnNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), "if (!$src1.new) $dst = zxth($src2)", []>, Requires<[HasV4T]>; +} // Generate frame index addresses. -let neverHasSideEffects = 1, isReMaterializable = 1 in +let neverHasSideEffects = 1, isReMaterializable = 1, +isExtended = 1, opExtendable = 2, validSubTargets = HasV4SubT in def TFR_FI_immext_V4 : ALU32_ri<(outs IntRegs:$dst), (ins IntRegs:$src1, s32Imm:$offset), "$dst = add($src1, ##$offset)", []>, Requires<[HasV4T]>; +// Rd=cmp.eq(Rs,#s8) +let validSubTargets = HasV4SubT, isExtendable = 1, opExtendable = 2, +isExtentSigned = 1, opExtentBits = 8 in +def V4_A4_rcmpeqi : ALU32_ri<(outs IntRegs:$Rd), + (ins IntRegs:$Rs, s8Ext:$s8), + "$Rd = cmp.eq($Rs, #$s8)", + [(set (i32 IntRegs:$Rd), + (i32 (zext (i1 (seteq (i32 IntRegs:$Rs), + s8ExtPred:$s8)))))]>, + Requires<[HasV4T]>; + +// Preserve the TSTBIT generation +def : Pat <(i32 (zext (i1 (setne (i32 (and (i32 (shl 1, (i32 IntRegs:$src2))), + (i32 IntRegs:$src1))), 0)))), + (i32 (MUX_ii (i1 (TSTBIT_rr (i32 IntRegs:$src1), (i32 IntRegs:$src2))), + 1, 0))>; + +// Interfered with tstbit generation, above pattern preserves, see : tstbit.ll +// Rd=cmp.ne(Rs,#s8) +let validSubTargets = HasV4SubT, isExtendable = 1, opExtendable = 2, +isExtentSigned = 1, opExtentBits = 8 in +def V4_A4_rcmpneqi : ALU32_ri<(outs IntRegs:$Rd), + (ins IntRegs:$Rs, s8Ext:$s8), + "$Rd = !cmp.eq($Rs, #$s8)", + [(set (i32 IntRegs:$Rd), + (i32 (zext (i1 (setne (i32 IntRegs:$Rs), + s8ExtPred:$s8)))))]>, + Requires<[HasV4T]>; + +// Rd=cmp.eq(Rs,Rt) +let validSubTargets = HasV4SubT in +def V4_A4_rcmpeq : ALU32_ri<(outs IntRegs:$Rd), + (ins IntRegs:$Rs, IntRegs:$Rt), + "$Rd = cmp.eq($Rs, $Rt)", + [(set (i32 IntRegs:$Rd), + (i32 (zext (i1 (seteq (i32 IntRegs:$Rs), + IntRegs:$Rt)))))]>, + Requires<[HasV4T]>; + +// Rd=cmp.ne(Rs,Rt) +let validSubTargets = HasV4SubT in +def V4_A4_rcmpneq : ALU32_ri<(outs IntRegs:$Rd), + (ins IntRegs:$Rs, IntRegs:$Rt), + "$Rd = !cmp.eq($Rs, $Rt)", + [(set (i32 IntRegs:$Rd), + (i32 (zext (i1 (setne (i32 IntRegs:$Rs), + IntRegs:$Rt)))))]>, + Requires<[HasV4T]>; //===----------------------------------------------------------------------===// // ALU32 - @@ -293,6 +339,19 @@ def COMBINE_Ir_V4 : ALU32_ir<(outs DoubleRegs:$dst), []>, Requires<[HasV4T]>; +def HexagonWrapperCombineRI_V4 : + SDNode<"HexagonISD::WrapperCombineRI_V4", SDTHexagonI64I32I32>; +def HexagonWrapperCombineIR_V4 : + SDNode<"HexagonISD::WrapperCombineIR_V4", SDTHexagonI64I32I32>; + +def : Pat <(HexagonWrapperCombineRI_V4 IntRegs:$r, s8ExtPred:$i), + (COMBINE_rI_V4 IntRegs:$r, s8ExtPred:$i)>, + Requires<[HasV4T]>; + +def : Pat <(HexagonWrapperCombineIR_V4 s8ExtPred:$i, IntRegs:$r), + (COMBINE_Ir_V4 s8ExtPred:$i, IntRegs:$r)>, + Requires<[HasV4T]>; + let isExtendable = 1, opExtendable = 2, isExtentSigned = 0, opExtentBits = 6, neverHasSideEffects = 1, validSubTargets = HasV4SubT in def COMBINE_iI_V4 : ALU32_ii<(outs DoubleRegs:$dst), @@ -312,127 +371,102 @@ def COMBINE_iI_V4 : ALU32_ii<(outs DoubleRegs:$dst), // These absolute set addressing mode instructions accept immediate as // an operand. We have duplicated these patterns to take global address. -let neverHasSideEffects = 1 in +let isExtended = 1, opExtendable = 2, neverHasSideEffects = 1, +validSubTargets = HasV4SubT in { def LDrid_abs_setimm_V4 : LDInst2<(outs DoubleRegs:$dst1, IntRegs:$dst2), - (ins u6Imm:$addr), - "$dst1 = memd($dst2=#$addr)", + (ins u0AlwaysExt:$addr), + "$dst1 = memd($dst2=##$addr)", []>, Requires<[HasV4T]>; // Rd=memb(Re=#U6) -let neverHasSideEffects = 1 in def LDrib_abs_setimm_V4 : LDInst2<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins u6Imm:$addr), - "$dst1 = memb($dst2=#$addr)", + (ins u0AlwaysExt:$addr), + "$dst1 = memb($dst2=##$addr)", []>, Requires<[HasV4T]>; // Rd=memh(Re=#U6) -let neverHasSideEffects = 1 in def LDrih_abs_setimm_V4 : LDInst2<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins u6Imm:$addr), - "$dst1 = memh($dst2=#$addr)", + (ins u0AlwaysExt:$addr), + "$dst1 = memh($dst2=##$addr)", []>, Requires<[HasV4T]>; // Rd=memub(Re=#U6) -let neverHasSideEffects = 1 in def LDriub_abs_setimm_V4 : LDInst2<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins u6Imm:$addr), - "$dst1 = memub($dst2=#$addr)", + (ins u0AlwaysExt:$addr), + "$dst1 = memub($dst2=##$addr)", []>, Requires<[HasV4T]>; // Rd=memuh(Re=#U6) -let neverHasSideEffects = 1 in def LDriuh_abs_setimm_V4 : LDInst2<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins u6Imm:$addr), - "$dst1 = memuh($dst2=#$addr)", + (ins u0AlwaysExt:$addr), + "$dst1 = memuh($dst2=##$addr)", []>, Requires<[HasV4T]>; // Rd=memw(Re=#U6) -let neverHasSideEffects = 1 in def LDriw_abs_setimm_V4 : LDInst2<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins u6Imm:$addr), - "$dst1 = memw($dst2=#$addr)", + (ins u0AlwaysExt:$addr), + "$dst1 = memw($dst2=##$addr)", []>, Requires<[HasV4T]>; +} // Following patterns are defined for absolute set addressing mode // instruction which take global address as operand. -let neverHasSideEffects = 1 in +let isExtended = 1, opExtendable = 2, neverHasSideEffects = 1, +validSubTargets = HasV4SubT in { def LDrid_abs_set_V4 : LDInst2<(outs DoubleRegs:$dst1, IntRegs:$dst2), - (ins globaladdress:$addr), + (ins globaladdressExt:$addr), "$dst1 = memd($dst2=##$addr)", []>, Requires<[HasV4T]>; // Rd=memb(Re=#U6) -let neverHasSideEffects = 1 in def LDrib_abs_set_V4 : LDInst2<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins globaladdress:$addr), + (ins globaladdressExt:$addr), "$dst1 = memb($dst2=##$addr)", []>, Requires<[HasV4T]>; // Rd=memh(Re=#U6) -let neverHasSideEffects = 1 in def LDrih_abs_set_V4 : LDInst2<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins globaladdress:$addr), + (ins globaladdressExt:$addr), "$dst1 = memh($dst2=##$addr)", []>, Requires<[HasV4T]>; // Rd=memub(Re=#U6) -let neverHasSideEffects = 1 in def LDriub_abs_set_V4 : LDInst2<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins globaladdress:$addr), + (ins globaladdressExt:$addr), "$dst1 = memub($dst2=##$addr)", []>, Requires<[HasV4T]>; // Rd=memuh(Re=#U6) -let neverHasSideEffects = 1 in def LDriuh_abs_set_V4 : LDInst2<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins globaladdress:$addr), + (ins globaladdressExt:$addr), "$dst1 = memuh($dst2=##$addr)", []>, Requires<[HasV4T]>; // Rd=memw(Re=#U6) -let neverHasSideEffects = 1 in def LDriw_abs_set_V4 : LDInst2<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins globaladdress:$addr), + (ins globaladdressExt:$addr), "$dst1 = memw($dst2=##$addr)", []>, Requires<[HasV4T]>; - -// Load doubleword. -// -// Make sure that in post increment load, the first operand is always the post -// increment operand. -// -// Rdd=memd(Rs+Rt<<#u2) -// Special case pattern for indexed load without offset which is easier to -// match. AddedComplexity of this pattern should be lower than base+offset load -// and lower yet than the more generic version with offset/shift below -// Similar approach is taken for all other base+index loads. -let AddedComplexity = 10, isPredicable = 1 in -def LDrid_indexed_V4 : LDInst<(outs DoubleRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2), - "$dst=memd($src1+$src2<<#0)", - [(set (i64 DoubleRegs:$dst), - (i64 (load (add (i32 IntRegs:$src1), - (i32 IntRegs:$src2)))))]>, - Requires<[HasV4T]>; +} // multiclass for load instructions with base + register offset // addressing mode multiclass ld_idxd_shl_pbase<string mnemonic, RegisterClass RC, bit isNot, bit isPredNew> { - let PNewValue = #!if(isPredNew, "new", "") in - def #NAME# : LDInst2<(outs RC:$dst), + let PNewValue = !if(isPredNew, "new", "") in + def NAME : LDInst2<(outs RC:$dst), (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$offset), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", ") ")#"$dst = "#mnemonic#"($src2+$src3<<#$offset)", @@ -440,10 +474,10 @@ multiclass ld_idxd_shl_pbase<string mnemonic, RegisterClass RC, bit isNot, } multiclass ld_idxd_shl_pred<string mnemonic, RegisterClass RC, bit PredNot> { - let PredSense = #!if(PredNot, "false", "true") in { - defm _c#NAME# : ld_idxd_shl_pbase<mnemonic, RC, PredNot, 0>; + let PredSense = !if(PredNot, "false", "true") in { + defm _c#NAME : ld_idxd_shl_pbase<mnemonic, RC, PredNot, 0>; // Predicate new - defm _cdn#NAME# : ld_idxd_shl_pbase<mnemonic, RC, PredNot, 1>; + defm _cdn#NAME : ld_idxd_shl_pbase<mnemonic, RC, PredNot, 1>; } } @@ -451,7 +485,7 @@ let neverHasSideEffects = 1 in multiclass ld_idxd_shl<string mnemonic, string CextOp, RegisterClass RC> { let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed_shl in { let isPredicable = 1 in - def #NAME#_V4 : LDInst2<(outs RC:$dst), + def NAME#_V4 : LDInst2<(outs RC:$dst), (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$offset), "$dst = "#mnemonic#"($src1+$src2<<#$offset)", []>, Requires<[HasV4T]>; @@ -525,536 +559,44 @@ def : Pat <(i64 (load (add IntRegs:$src1, Requires<[HasV4T]>; } -//// Load doubleword conditionally. -// if ([!]Pv[.new]) Rd=memd(Rs+Rt<<#u2) -// if (Pv) Rd=memd(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDrid_indexed_cPt_V4 : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if ($src1) $dst=memd($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) Rd=memd(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDrid_indexed_cdnPt_V4 : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if ($src1.new) $dst=memd($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -// if (!Pv) Rd=memd(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDrid_indexed_cNotPt_V4 : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if (!$src1) $dst=memd($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) Rd=memd(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDrid_indexed_cdnNotPt_V4 : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if (!$src1.new) $dst=memd($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -// Rdd=memd(Rt<<#u2+#U6) - -//// Load byte. -// Rd=memb(Rs+Rt<<#u2) -let AddedComplexity = 10, isPredicable = 1 in -def LDrib_indexed_V4 : LDInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2), - "$dst=memb($src1+$src2<<#0)", - [(set (i32 IntRegs:$dst), - (i32 (sextloadi8 (add (i32 IntRegs:$src1), - (i32 IntRegs:$src2)))))]>, - Requires<[HasV4T]>; -let AddedComplexity = 10, isPredicable = 1 in -def LDriub_indexed_V4 : LDInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2), - "$dst=memub($src1+$src2<<#0)", - [(set (i32 IntRegs:$dst), - (i32 (zextloadi8 (add (i32 IntRegs:$src1), - (i32 IntRegs:$src2)))))]>, - Requires<[HasV4T]>; - -let AddedComplexity = 10, isPredicable = 1 in -def LDriub_ae_indexed_V4 : LDInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2), - "$dst=memub($src1+$src2<<#0)", - [(set (i32 IntRegs:$dst), - (i32 (extloadi8 (add (i32 IntRegs:$src1), - (i32 IntRegs:$src2)))))]>, - Requires<[HasV4T]>; - -let AddedComplexity = 40, isPredicable = 1 in -def LDriub_ae_indexed_shl_V4 : LDInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$offset), - "$dst=memub($src1+$src2<<#$offset)", - [(set (i32 IntRegs:$dst), - (i32 (extloadi8 (add (i32 IntRegs:$src1), - (shl (i32 IntRegs:$src2), - u2ImmPred:$offset)))))]>, - Requires<[HasV4T]>; - -//// Load byte conditionally. -// if ([!]Pv[.new]) Rd=memb(Rs+Rt<<#u2) -// if (Pv) Rd=memb(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDrib_indexed_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if ($src1) $dst=memb($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) Rd=memb(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDrib_indexed_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if ($src1.new) $dst=memb($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -// if (!Pv) Rd=memb(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDrib_indexed_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if (!$src1) $dst=memb($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) Rd=memb(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDrib_indexed_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if (!$src1.new) $dst=memb($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -//// Load unsigned byte conditionally. -// if ([!]Pv[.new]) Rd=memub(Rs+Rt<<#u2) -// if (Pv) Rd=memub(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDriub_indexed_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if ($src1) $dst=memub($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) Rd=memub(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDriub_indexed_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if ($src1.new) $dst=memub($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -// if (!Pv) Rd=memub(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDriub_indexed_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if (!$src1) $dst=memub($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) Rd=memub(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDriub_indexed_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if (!$src1.new) $dst=memub($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -// Rd=memb(Rt<<#u2+#U6) - -//// Load halfword -// Rd=memh(Rs+Rt<<#u2) -let AddedComplexity = 10, isPredicable = 1 in -def LDrih_indexed_V4 : LDInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2), - "$dst=memh($src1+$src2<<#0)", - [(set (i32 IntRegs:$dst), - (i32 (sextloadi16 (add (i32 IntRegs:$src1), - (i32 IntRegs:$src2)))))]>, - Requires<[HasV4T]>; - -let AddedComplexity = 10, isPredicable = 1 in -def LDriuh_indexed_V4 : LDInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2), - "$dst=memuh($src1+$src2<<#0)", - [(set (i32 IntRegs:$dst), - (i32 (zextloadi16 (add (i32 IntRegs:$src1), - (i32 IntRegs:$src2)))))]>, - Requires<[HasV4T]>; - -let AddedComplexity = 10, isPredicable = 1 in -def LDriuh_ae_indexed_V4 : LDInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2), - "$dst=memuh($src1+$src2<<#0)", - [(set (i32 IntRegs:$dst), - (i32 (extloadi16 (add (i32 IntRegs:$src1), - (i32 IntRegs:$src2)))))]>, - Requires<[HasV4T]>; - -let AddedComplexity = 40, isPredicable = 1 in -def LDriuh_ae_indexed_shl_V4 : LDInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$offset), - "$dst=memuh($src1+$src2<<#$offset)", - [(set (i32 IntRegs:$dst), - (i32 (extloadi16 (add (i32 IntRegs:$src1), - (shl (i32 IntRegs:$src2), - u2ImmPred:$offset)))))]>, - Requires<[HasV4T]>; - -//// Load halfword conditionally. -// if ([!]Pv[.new]) Rd=memh(Rs+Rt<<#u2) -// if (Pv) Rd=memh(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDrih_indexed_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if ($src1) $dst=memh($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) Rd=memh(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDrih_indexed_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if ($src1.new) $dst=memh($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -// if (!Pv) Rd=memh(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDrih_indexed_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if (!$src1) $dst=memh($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) Rd=memh(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDrih_indexed_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if (!$src1.new) $dst=memh($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -//// Load unsigned halfword conditionally. -// if ([!]Pv[.new]) Rd=memuh(Rs+Rt<<#u2) -// if (Pv) Rd=memuh(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDriuh_indexed_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if ($src1) $dst=memuh($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) Rd=memuh(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDriuh_indexed_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if ($src1.new) $dst=memuh($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -// if (!Pv) Rd=memuh(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDriuh_indexed_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if (!$src1) $dst=memuh($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) Rd=memuh(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDriuh_indexed_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if (!$src1.new) $dst=memuh($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -// Rd=memh(Rt<<#u2+#U6) - -//// Load word. -// Load predicate: Fix for bug 5279. -let neverHasSideEffects = 1 in -def LDriw_pred_V4 : LDInst2<(outs PredRegs:$dst), - (ins MEMri:$addr), - "Error; should not emit", - []>, +// 'def pats' for load instruction base + register offset and +// zero immediate value. +let AddedComplexity = 10 in { +def : Pat <(i64 (load (add IntRegs:$src1, IntRegs:$src2))), + (LDrid_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, Requires<[HasV4T]>; -// Rd=memw(Re=#U6) - -// Rd=memw(Rs+Rt<<#u2) -let AddedComplexity = 10, isPredicable = 1 in -def LDriw_indexed_V4 : LDInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2), - "$dst=memw($src1+$src2<<#0)", - [(set (i32 IntRegs:$dst), - (i32 (load (add (i32 IntRegs:$src1), - (i32 IntRegs:$src2)))))]>, - Requires<[HasV4T]>; - -//// Load word conditionally. -// if ([!]Pv[.new]) Rd=memw(Rs+Rt<<#u2) -// if (Pv) Rd=memw(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDriw_indexed_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if ($src1) $dst=memw($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) Rd=memh(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDriw_indexed_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if ($src1.new) $dst=memw($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -// if (!Pv) Rd=memh(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDriw_indexed_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if (!$src1) $dst=memw($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) Rd=memh(Rs+Rt<<#u2) -let AddedComplexity = 15, isPredicated = 1 in -def LDriw_indexed_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), - "if (!$src1.new) $dst=memw($src2+$src3<<#0)", - []>, - Requires<[HasV4T]>; - -/// Load from global offset - -let isPredicable = 1, neverHasSideEffects = 1 in -def LDrid_GP_V4 : LDInst2<(outs DoubleRegs:$dst), - (ins globaladdress:$global, u16Imm:$offset), - "$dst=memd(#$global+$offset)", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrid_GP_cPt_V4 : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if ($src1) $dst=memd(##$global+$offset)", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrid_GP_cNotPt_V4 : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if (!$src1) $dst=memd(##$global+$offset)", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrid_GP_cdnPt_V4 : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if ($src1.new) $dst=memd(##$global+$offset)", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrid_GP_cdnNotPt_V4 : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if (!$src1.new) $dst=memd(##$global+$offset)", - []>, - Requires<[HasV4T]>; - -let isPredicable = 1, neverHasSideEffects = 1 in -def LDrib_GP_V4 : LDInst2<(outs IntRegs:$dst), - (ins globaladdress:$global, u16Imm:$offset), - "$dst=memb(#$global+$offset)", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrib_GP_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if ($src1) $dst=memb(##$global+$offset)", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrib_GP_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if (!$src1) $dst=memb(##$global+$offset)", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrib_GP_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if ($src1.new) $dst=memb(##$global+$offset)", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrib_GP_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if (!$src1.new) $dst=memb(##$global+$offset)", - []>, - Requires<[HasV4T]>; - - -let isPredicable = 1, neverHasSideEffects = 1 in -def LDriub_GP_V4 : LDInst2<(outs IntRegs:$dst), - (ins globaladdress:$global, u16Imm:$offset), - "$dst=memub(#$global+$offset)", - []>, - Requires<[HasV4T]>; - - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriub_GP_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if ($src1) $dst=memub(##$global+$offset)", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriub_GP_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if (!$src1) $dst=memub(##$global+$offset)", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriub_GP_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if ($src1.new) $dst=memub(##$global+$offset)", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriub_GP_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if (!$src1.new) $dst=memub(##$global+$offset)", - []>, - Requires<[HasV4T]>; - - -let isPredicable = 1, neverHasSideEffects = 1 in -def LDrih_GP_V4 : LDInst2<(outs IntRegs:$dst), - (ins globaladdress:$global, u16Imm:$offset), - "$dst=memh(#$global+$offset)", - []>, - Requires<[HasV4T]>; - - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrih_GP_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if ($src1) $dst=memh(##$global+$offset)", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrih_GP_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if (!$src1) $dst=memh(##$global+$offset)", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrih_GP_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if ($src1.new) $dst=memh(##$global+$offset)", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrih_GP_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if (!$src1.new) $dst=memh(##$global+$offset)", - []>, +def : Pat <(i32 (sextloadi8 (add IntRegs:$src1, IntRegs:$src2))), + (LDrib_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, Requires<[HasV4T]>; - -let isPredicable = 1, neverHasSideEffects = 1 in -def LDriuh_GP_V4 : LDInst2<(outs IntRegs:$dst), - (ins globaladdress:$global, u16Imm:$offset), - "$dst=memuh(#$global+$offset)", - []>, +def : Pat <(i32 (zextloadi8 (add IntRegs:$src1, IntRegs:$src2))), + (LDriub_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, Requires<[HasV4T]>; -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriuh_GP_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if ($src1) $dst=memuh(##$global+$offset)", - []>, +def : Pat <(i32 (extloadi8 (add IntRegs:$src1, IntRegs:$src2))), + (LDriub_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, Requires<[HasV4T]>; -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriuh_GP_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if (!$src1) $dst=memuh(##$global+$offset)", - []>, +def : Pat <(i32 (sextloadi16 (add IntRegs:$src1, IntRegs:$src2))), + (LDrih_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, Requires<[HasV4T]>; -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriuh_GP_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if ($src1.new) $dst=memuh(##$global+$offset)", - []>, +def : Pat <(i32 (zextloadi16 (add IntRegs:$src1, IntRegs:$src2))), + (LDriuh_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, Requires<[HasV4T]>; -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriuh_GP_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if (!$src1.new) $dst=memuh(##$global+$offset)", - []>, +def : Pat <(i32 (extloadi16 (add IntRegs:$src1, IntRegs:$src2))), + (LDriuh_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, Requires<[HasV4T]>; -let isPredicable = 1, neverHasSideEffects = 1 in -def LDriw_GP_V4 : LDInst2<(outs IntRegs:$dst), - (ins globaladdress:$global, u16Imm:$offset), - "$dst=memw(#$global+$offset)", - []>, +def : Pat <(i32 (load (add IntRegs:$src1, IntRegs:$src2))), + (LDriw_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, Requires<[HasV4T]>; +} - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriw_GP_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if ($src1) $dst=memw(##$global+$offset)", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriw_GP_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if (!$src1) $dst=memw(##$global+$offset)", - []>, - Requires<[HasV4T]>; - - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriw_GP_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if ($src1.new) $dst=memw(##$global+$offset)", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriw_GP_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset), - "if (!$src1.new) $dst=memw(##$global+$offset)", - []>, - Requires<[HasV4T]>; - - -let isPredicable = 1, neverHasSideEffects = 1 in +let isPredicable = 1, neverHasSideEffects = 1, validSubTargets = HasV4SubT in def LDd_GP_V4 : LDInst2<(outs DoubleRegs:$dst), (ins globaladdress:$global), "$dst=memd(#$global)", @@ -1062,7 +604,8 @@ def LDd_GP_V4 : LDInst2<(outs DoubleRegs:$dst), Requires<[HasV4T]>; // if (Pv) Rtt=memd(##global) -let neverHasSideEffects = 1, isPredicated = 1 in +let neverHasSideEffects = 1, isPredicated = 1, isExtended = 1, opExtendable = 2, +validSubTargets = HasV4SubT in { def LDd_GP_cPt_V4 : LDInst2<(outs DoubleRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if ($src1) $dst=memd(##$global)", @@ -1071,7 +614,6 @@ def LDd_GP_cPt_V4 : LDInst2<(outs DoubleRegs:$dst), // if (!Pv) Rtt=memd(##global) -let neverHasSideEffects = 1, isPredicated = 1 in def LDd_GP_cNotPt_V4 : LDInst2<(outs DoubleRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if (!$src1) $dst=memd(##$global)", @@ -1079,7 +621,6 @@ def LDd_GP_cNotPt_V4 : LDInst2<(outs DoubleRegs:$dst), Requires<[HasV4T]>; // if (Pv) Rtt=memd(##global) -let neverHasSideEffects = 1, isPredicated = 1 in def LDd_GP_cdnPt_V4 : LDInst2<(outs DoubleRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if ($src1.new) $dst=memd(##$global)", @@ -1088,14 +629,14 @@ def LDd_GP_cdnPt_V4 : LDInst2<(outs DoubleRegs:$dst), // if (!Pv) Rtt=memd(##global) -let neverHasSideEffects = 1, isPredicated = 1 in def LDd_GP_cdnNotPt_V4 : LDInst2<(outs DoubleRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if (!$src1.new) $dst=memd(##$global)", []>, Requires<[HasV4T]>; +} -let isPredicable = 1, neverHasSideEffects = 1 in +let isPredicable = 1, neverHasSideEffects = 1, validSubTargets = HasV4SubT in def LDb_GP_V4 : LDInst2<(outs IntRegs:$dst), (ins globaladdress:$global), "$dst=memb(#$global)", @@ -1103,7 +644,8 @@ def LDb_GP_V4 : LDInst2<(outs IntRegs:$dst), Requires<[HasV4T]>; // if (Pv) Rt=memb(##global) -let neverHasSideEffects = 1, isPredicated = 1 in +let neverHasSideEffects = 1, isPredicated = 1, isExtended = 1, opExtendable = 2, +validSubTargets = HasV4SubT in { def LDb_GP_cPt_V4 : LDInst2<(outs IntRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if ($src1) $dst=memb(##$global)", @@ -1111,7 +653,6 @@ def LDb_GP_cPt_V4 : LDInst2<(outs IntRegs:$dst), Requires<[HasV4T]>; // if (!Pv) Rt=memb(##global) -let neverHasSideEffects = 1, isPredicated = 1 in def LDb_GP_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if (!$src1) $dst=memb(##$global)", @@ -1119,7 +660,6 @@ def LDb_GP_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), Requires<[HasV4T]>; // if (Pv) Rt=memb(##global) -let neverHasSideEffects = 1, isPredicated = 1 in def LDb_GP_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if ($src1.new) $dst=memb(##$global)", @@ -1127,14 +667,14 @@ def LDb_GP_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), Requires<[HasV4T]>; // if (!Pv) Rt=memb(##global) -let neverHasSideEffects = 1, isPredicated = 1 in def LDb_GP_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if (!$src1.new) $dst=memb(##$global)", []>, Requires<[HasV4T]>; +} -let isPredicable = 1, neverHasSideEffects = 1 in +let isPredicable = 1, neverHasSideEffects = 1, validSubTargets = HasV4SubT in def LDub_GP_V4 : LDInst2<(outs IntRegs:$dst), (ins globaladdress:$global), "$dst=memub(#$global)", @@ -1142,7 +682,8 @@ def LDub_GP_V4 : LDInst2<(outs IntRegs:$dst), Requires<[HasV4T]>; // if (Pv) Rt=memub(##global) -let neverHasSideEffects = 1, isPredicated = 1 in +let neverHasSideEffects = 1, isPredicated = 1, isExtended = 1, opExtendable = 2, +validSubTargets = HasV4SubT in { def LDub_GP_cPt_V4 : LDInst2<(outs IntRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if ($src1) $dst=memub(##$global)", @@ -1151,7 +692,6 @@ def LDub_GP_cPt_V4 : LDInst2<(outs IntRegs:$dst), // if (!Pv) Rt=memub(##global) -let neverHasSideEffects = 1, isPredicated = 1 in def LDub_GP_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if (!$src1) $dst=memub(##$global)", @@ -1159,7 +699,6 @@ def LDub_GP_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), Requires<[HasV4T]>; // if (Pv) Rt=memub(##global) -let neverHasSideEffects = 1, isPredicated = 1 in def LDub_GP_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if ($src1.new) $dst=memub(##$global)", @@ -1168,14 +707,14 @@ def LDub_GP_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), // if (!Pv) Rt=memub(##global) -let neverHasSideEffects = 1, isPredicated = 1 in def LDub_GP_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if (!$src1.new) $dst=memub(##$global)", []>, Requires<[HasV4T]>; +} -let isPredicable = 1, neverHasSideEffects = 1 in +let isPredicable = 1, neverHasSideEffects = 1, validSubTargets = HasV4SubT in def LDh_GP_V4 : LDInst2<(outs IntRegs:$dst), (ins globaladdress:$global), "$dst=memh(#$global)", @@ -1183,7 +722,8 @@ def LDh_GP_V4 : LDInst2<(outs IntRegs:$dst), Requires<[HasV4T]>; // if (Pv) Rt=memh(##global) -let neverHasSideEffects = 1, isPredicated = 1 in +let neverHasSideEffects = 1, isPredicated = 1, isExtended = 1, opExtendable = 2, +validSubTargets = HasV4SubT in { def LDh_GP_cPt_V4 : LDInst2<(outs IntRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if ($src1) $dst=memh(##$global)", @@ -1191,7 +731,6 @@ def LDh_GP_cPt_V4 : LDInst2<(outs IntRegs:$dst), Requires<[HasV4T]>; // if (!Pv) Rt=memh(##global) -let neverHasSideEffects = 1, isPredicated = 1 in def LDh_GP_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if (!$src1) $dst=memh(##$global)", @@ -1199,7 +738,6 @@ def LDh_GP_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), Requires<[HasV4T]>; // if (Pv) Rt=memh(##global) -let neverHasSideEffects = 1, isPredicated = 1 in def LDh_GP_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if ($src1.new) $dst=memh(##$global)", @@ -1207,14 +745,14 @@ def LDh_GP_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), Requires<[HasV4T]>; // if (!Pv) Rt=memh(##global) -let neverHasSideEffects = 1, isPredicated = 1 in def LDh_GP_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if (!$src1.new) $dst=memh(##$global)", []>, Requires<[HasV4T]>; +} -let isPredicable = 1, neverHasSideEffects = 1 in +let isPredicable = 1, neverHasSideEffects = 1, validSubTargets = HasV4SubT in def LDuh_GP_V4 : LDInst2<(outs IntRegs:$dst), (ins globaladdress:$global), "$dst=memuh(#$global)", @@ -1222,7 +760,8 @@ def LDuh_GP_V4 : LDInst2<(outs IntRegs:$dst), Requires<[HasV4T]>; // if (Pv) Rt=memuh(##global) -let neverHasSideEffects = 1, isPredicated = 1 in +let neverHasSideEffects = 1, isPredicated = 1, isExtended = 1, opExtendable = 2, +validSubTargets = HasV4SubT in { def LDuh_GP_cPt_V4 : LDInst2<(outs IntRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if ($src1) $dst=memuh(##$global)", @@ -1230,7 +769,6 @@ def LDuh_GP_cPt_V4 : LDInst2<(outs IntRegs:$dst), Requires<[HasV4T]>; // if (!Pv) Rt=memuh(##global) -let neverHasSideEffects = 1, isPredicated = 1 in def LDuh_GP_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if (!$src1) $dst=memuh(##$global)", @@ -1238,7 +776,6 @@ def LDuh_GP_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), Requires<[HasV4T]>; // if (Pv) Rt=memuh(##global) -let neverHasSideEffects = 1, isPredicated = 1 in def LDuh_GP_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if ($src1.new) $dst=memuh(##$global)", @@ -1246,14 +783,14 @@ def LDuh_GP_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), Requires<[HasV4T]>; // if (!Pv) Rt=memuh(##global) -let neverHasSideEffects = 1, isPredicated = 1 in def LDuh_GP_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if (!$src1.new) $dst=memuh(##$global)", []>, Requires<[HasV4T]>; +} -let isPredicable = 1, neverHasSideEffects = 1 in +let isPredicable = 1, neverHasSideEffects = 1, validSubTargets = HasV4SubT in def LDw_GP_V4 : LDInst2<(outs IntRegs:$dst), (ins globaladdress:$global), "$dst=memw(#$global)", @@ -1261,7 +798,8 @@ def LDw_GP_V4 : LDInst2<(outs IntRegs:$dst), Requires<[HasV4T]>; // if (Pv) Rt=memw(##global) -let neverHasSideEffects = 1, isPredicated = 1 in +let neverHasSideEffects = 1, isPredicated = 1, isExtended = 1, opExtendable = 2, +validSubTargets = HasV4SubT in { def LDw_GP_cPt_V4 : LDInst2<(outs IntRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if ($src1) $dst=memw(##$global)", @@ -1270,7 +808,6 @@ def LDw_GP_cPt_V4 : LDInst2<(outs IntRegs:$dst), // if (!Pv) Rt=memw(##global) -let neverHasSideEffects = 1, isPredicated = 1 in def LDw_GP_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if (!$src1) $dst=memw(##$global)", @@ -1278,7 +815,6 @@ def LDw_GP_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), Requires<[HasV4T]>; // if (Pv) Rt=memw(##global) -let neverHasSideEffects = 1, isPredicated = 1 in def LDw_GP_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if ($src1.new) $dst=memw(##$global)", @@ -1287,13 +823,12 @@ def LDw_GP_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), // if (!Pv) Rt=memw(##global) -let neverHasSideEffects = 1, isPredicated = 1 in def LDw_GP_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), (ins PredRegs:$src1, globaladdress:$global), "if (!$src1.new) $dst=memw(##$global)", []>, Requires<[HasV4T]>; - +} def : Pat <(atomic_load_64 (HexagonCONST32_GP tglobaladdr:$global)), @@ -1384,83 +919,86 @@ def : Pat <(i32 (load (HexagonCONST32_GP tglobaladdr:$global))), (i32 (LDw_GP_V4 tglobaladdr:$global))>, Requires<[HasV4T]>; -def : Pat <(atomic_load_64 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset)), - (i64 (LDrid_GP_V4 tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[HasV4T]>; - -def : Pat <(atomic_load_32 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset)), - (i32 (LDriw_GP_V4 tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[HasV4T]>; - -def : Pat <(atomic_load_16 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset)), - (i32 (LDriuh_GP_V4 tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[HasV4T]>; - -def : Pat <(atomic_load_8 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset)), - (i32 (LDriub_GP_V4 tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[HasV4T]>; - -// Map from load(globaladdress + x) -> memd(#foo + x) -let AddedComplexity = 100 in -def : Pat <(i64 (load (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset))), - (i64 (LDrid_GP_V4 tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[HasV4T]>; - -// Map from load(globaladdress + x) -> memb(#foo + x) -let AddedComplexity = 100 in -def : Pat <(i32 (extloadi8 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset))), - (i32 (LDrib_GP_V4 tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[HasV4T]>; - -// Map from load(globaladdress + x) -> memb(#foo + x) -let AddedComplexity = 100 in -def : Pat <(i32 (sextloadi8 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset))), - (i32 (LDrib_GP_V4 tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[HasV4T]>; +// zext i1->i64 +def : Pat <(i64 (zext (i1 PredRegs:$src1))), + (i64 (COMBINE_Ir_V4 0, (MUX_ii (i1 PredRegs:$src1), 1, 0)))>, + Requires<[HasV4T]>; + +// zext i32->i64 +def : Pat <(i64 (zext (i32 IntRegs:$src1))), + (i64 (COMBINE_Ir_V4 0, (i32 IntRegs:$src1)))>, + Requires<[HasV4T]>; +// zext i8->i64 +def: Pat <(i64 (zextloadi8 ADDRriS11_0:$src1)), + (i64 (COMBINE_Ir_V4 0, (LDriub ADDRriS11_0:$src1)))>, + Requires<[HasV4T]>; + +let AddedComplexity = 20 in +def: Pat <(i64 (zextloadi8 (add (i32 IntRegs:$src1), + s11_0ExtPred:$offset))), + (i64 (COMBINE_Ir_V4 0, (LDriub_indexed IntRegs:$src1, + s11_0ExtPred:$offset)))>, + Requires<[HasV4T]>; + +// zext i1->i64 +def: Pat <(i64 (zextloadi1 ADDRriS11_0:$src1)), + (i64 (COMBINE_Ir_V4 0, (LDriub ADDRriS11_0:$src1)))>, + Requires<[HasV4T]>; + +let AddedComplexity = 20 in +def: Pat <(i64 (zextloadi1 (add (i32 IntRegs:$src1), + s11_0ExtPred:$offset))), + (i64 (COMBINE_Ir_V4 0, (LDriub_indexed IntRegs:$src1, + s11_0ExtPred:$offset)))>, + Requires<[HasV4T]>; + +// zext i16->i64 +def: Pat <(i64 (zextloadi16 ADDRriS11_1:$src1)), + (i64 (COMBINE_Ir_V4 0, (LDriuh ADDRriS11_1:$src1)))>, + Requires<[HasV4T]>; + +let AddedComplexity = 20 in +def: Pat <(i64 (zextloadi16 (add (i32 IntRegs:$src1), + s11_1ExtPred:$offset))), + (i64 (COMBINE_Ir_V4 0, (LDriuh_indexed IntRegs:$src1, + s11_1ExtPred:$offset)))>, + Requires<[HasV4T]>; + +// anyext i16->i64 +def: Pat <(i64 (extloadi16 ADDRriS11_2:$src1)), + (i64 (COMBINE_Ir_V4 0, (LDrih ADDRriS11_2:$src1)))>, + Requires<[HasV4T]>; + +let AddedComplexity = 20 in +def: Pat <(i64 (extloadi16 (add (i32 IntRegs:$src1), + s11_1ExtPred:$offset))), + (i64 (COMBINE_Ir_V4 0, (LDrih_indexed IntRegs:$src1, + s11_1ExtPred:$offset)))>, + Requires<[HasV4T]>; + +// zext i32->i64 +def: Pat <(i64 (zextloadi32 ADDRriS11_2:$src1)), + (i64 (COMBINE_Ir_V4 0, (LDriw ADDRriS11_2:$src1)))>, + Requires<[HasV4T]>; -// Map from load(globaladdress + x) -> memub(#foo + x) let AddedComplexity = 100 in -def : Pat <(i32 (zextloadi8 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset))), - (i32 (LDriub_GP_V4 tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[HasV4T]>; +def: Pat <(i64 (zextloadi32 (i32 (add IntRegs:$src1, s11_2ExtPred:$offset)))), + (i64 (COMBINE_Ir_V4 0, (LDriw_indexed IntRegs:$src1, + s11_2ExtPred:$offset)))>, + Requires<[HasV4T]>; -// Map from load(globaladdress + x) -> memuh(#foo + x) -let AddedComplexity = 100 in -def : Pat <(i32 (extloadi16 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset))), - (i32 (LDrih_GP_V4 tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[HasV4T]>; +// anyext i32->i64 +def: Pat <(i64 (extloadi32 ADDRriS11_2:$src1)), + (i64 (COMBINE_Ir_V4 0, (LDriw ADDRriS11_2:$src1)))>, + Requires<[HasV4T]>; -// Map from load(globaladdress + x) -> memh(#foo + x) let AddedComplexity = 100 in -def : Pat <(i32 (sextloadi16 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset))), - (i32 (LDrih_GP_V4 tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[HasV4T]>; +def: Pat <(i64 (extloadi32 (i32 (add IntRegs:$src1, s11_2ExtPred:$offset)))), + (i64 (COMBINE_Ir_V4 0, (LDriw_indexed IntRegs:$src1, + s11_2ExtPred:$offset)))>, + Requires<[HasV4T]>; -// Map from load(globaladdress + x) -> memuh(#foo + x) -let AddedComplexity = 100 in -def : Pat <(i32 (zextloadi16 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset))), - (i32 (LDriuh_GP_V4 tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[HasV4T]>; - -// Map from load(globaladdress + x) -> memw(#foo + x) -let AddedComplexity = 100 in -def : Pat <(i32 (load (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset))), - (i32 (LDriw_GP_V4 tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[HasV4T]>; - //===----------------------------------------------------------------------===// // LD - @@ -1477,69 +1015,72 @@ def : Pat <(i32 (load (add (HexagonCONST32_GP tglobaladdr:$global), /// last operand. /// -// memd(Re=#U6)=Rtt +// memd(Re=#U)=Rtt +let isExtended = 1, opExtendable = 2, validSubTargets = HasV4SubT in { def STrid_abs_setimm_V4 : STInst2<(outs IntRegs:$dst1), - (ins DoubleRegs:$src1, u6Imm:$src2), - "memd($dst1=#$src2) = $src1", + (ins DoubleRegs:$src1, u0AlwaysExt:$src2), + "memd($dst1=##$src2) = $src1", []>, Requires<[HasV4T]>; -// memb(Re=#U6)=Rs +// memb(Re=#U)=Rs def STrib_abs_setimm_V4 : STInst2<(outs IntRegs:$dst1), - (ins IntRegs:$src1, u6Imm:$src2), - "memb($dst1=#$src2) = $src1", + (ins IntRegs:$src1, u0AlwaysExt:$src2), + "memb($dst1=##$src2) = $src1", []>, Requires<[HasV4T]>; -// memh(Re=#U6)=Rs +// memh(Re=#U)=Rs def STrih_abs_setimm_V4 : STInst2<(outs IntRegs:$dst1), - (ins IntRegs:$src1, u6Imm:$src2), - "memh($dst1=#$src2) = $src1", + (ins IntRegs:$src1, u0AlwaysExt:$src2), + "memh($dst1=##$src2) = $src1", []>, Requires<[HasV4T]>; -// memw(Re=#U6)=Rs +// memw(Re=#U)=Rs def STriw_abs_setimm_V4 : STInst2<(outs IntRegs:$dst1), - (ins IntRegs:$src1, u6Imm:$src2), - "memw($dst1=#$src2) = $src1", + (ins IntRegs:$src1, u0AlwaysExt:$src2), + "memw($dst1=##$src2) = $src1", []>, Requires<[HasV4T]>; +} -// memd(Re=#U6)=Rtt +// memd(Re=#U)=Rtt +let isExtended = 1, opExtendable = 2, validSubTargets = HasV4SubT in { def STrid_abs_set_V4 : STInst2<(outs IntRegs:$dst1), - (ins DoubleRegs:$src1, globaladdress:$src2), + (ins DoubleRegs:$src1, globaladdressExt:$src2), "memd($dst1=##$src2) = $src1", []>, Requires<[HasV4T]>; -// memb(Re=#U6)=Rs +// memb(Re=#U)=Rs def STrib_abs_set_V4 : STInst2<(outs IntRegs:$dst1), - (ins IntRegs:$src1, globaladdress:$src2), + (ins IntRegs:$src1, globaladdressExt:$src2), "memb($dst1=##$src2) = $src1", []>, Requires<[HasV4T]>; -// memh(Re=#U6)=Rs +// memh(Re=#U)=Rs def STrih_abs_set_V4 : STInst2<(outs IntRegs:$dst1), - (ins IntRegs:$src1, globaladdress:$src2), + (ins IntRegs:$src1, globaladdressExt:$src2), "memh($dst1=##$src2) = $src1", []>, Requires<[HasV4T]>; -// memw(Re=#U6)=Rs +// memw(Re=#U)=Rs def STriw_abs_set_V4 : STInst2<(outs IntRegs:$dst1), - (ins IntRegs:$src1, globaladdress:$src2), + (ins IntRegs:$src1, globaladdressExt:$src2), "memw($dst1=##$src2) = $src1", []>, Requires<[HasV4T]>; - +} // multiclass for store instructions with base + register offset addressing // mode multiclass ST_Idxd_shl_Pbase<string mnemonic, RegisterClass RC, bit isNot, bit isPredNew> { - let PNewValue = #!if(isPredNew, "new", "") in - def #NAME# : STInst2<(outs), + let PNewValue = !if(isPredNew, "new", "") in + def NAME : STInst2<(outs), (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, RC:$src5), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", @@ -1549,10 +1090,10 @@ multiclass ST_Idxd_shl_Pbase<string mnemonic, RegisterClass RC, bit isNot, } multiclass ST_Idxd_shl_Pred<string mnemonic, RegisterClass RC, bit PredNot> { - let PredSense = #!if(PredNot, "false", "true") in { - defm _c#NAME# : ST_Idxd_shl_Pbase<mnemonic, RC, PredNot, 0>; + let PredSense = !if(PredNot, "false", "true") in { + defm _c#NAME : ST_Idxd_shl_Pbase<mnemonic, RC, PredNot, 0>; // Predicate new - defm _cdn#NAME# : ST_Idxd_shl_Pbase<mnemonic, RC, PredNot, 1>; + defm _cdn#NAME : ST_Idxd_shl_Pbase<mnemonic, RC, PredNot, 1>; } } @@ -1560,9 +1101,9 @@ let isNVStorable = 1 in multiclass ST_Idxd_shl<string mnemonic, string CextOp, RegisterClass RC> { let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed_shl in { let isPredicable = 1 in - def #NAME#_V4 : STInst2<(outs), + def NAME#_V4 : STInst2<(outs), (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, RC:$src4), - #mnemonic#"($src1+$src2<<#$src3) = $src4", + mnemonic#"($src1+$src2<<#$src3) = $src4", []>, Requires<[HasV4T]>; @@ -1577,8 +1118,8 @@ multiclass ST_Idxd_shl<string mnemonic, string CextOp, RegisterClass RC> { // addressing mode. multiclass ST_Idxd_shl_Pbase_nv<string mnemonic, RegisterClass RC, bit isNot, bit isPredNew> { - let PNewValue = #!if(isPredNew, "new", "") in - def #NAME#_nv_V4 : NVInst_V4<(outs), + let PNewValue = !if(isPredNew, "new", "") in + def NAME#_nv_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, RC:$src5), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", @@ -1588,10 +1129,10 @@ multiclass ST_Idxd_shl_Pbase_nv<string mnemonic, RegisterClass RC, bit isNot, } multiclass ST_Idxd_shl_Pred_nv<string mnemonic, RegisterClass RC, bit PredNot> { - let PredSense = #!if(PredNot, "false", "true") in { - defm _c#NAME# : ST_Idxd_shl_Pbase_nv<mnemonic, RC, PredNot, 0>; + let PredSense = !if(PredNot, "false", "true") in { + defm _c#NAME : ST_Idxd_shl_Pbase_nv<mnemonic, RC, PredNot, 0>; // Predicate new - defm _cdn#NAME# : ST_Idxd_shl_Pbase_nv<mnemonic, RC, PredNot, 1>; + defm _cdn#NAME : ST_Idxd_shl_Pbase_nv<mnemonic, RC, PredNot, 1>; } } @@ -1599,9 +1140,9 @@ let mayStore = 1, isNVStore = 1 in multiclass ST_Idxd_shl_nv<string mnemonic, string CextOp, RegisterClass RC> { let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed_shl in { let isPredicable = 1 in - def #NAME#_nv_V4 : NVInst_V4<(outs), + def NAME#_nv_V4 : NVInst_V4<(outs), (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, RC:$src4), - #mnemonic#"($src1+$src2<<#$src3) = $src4.new", + mnemonic#"($src1+$src2<<#$src3) = $src4.new", []>, Requires<[HasV4T]>; @@ -1652,13 +1193,14 @@ def : Pat<(store (i64 DoubleRegs:$src4), } // memd(Ru<<#u2+#U6)=Rtt -let AddedComplexity = 10 in +let isExtended = 1, opExtendable = 2, AddedComplexity = 10, +validSubTargets = HasV4SubT in def STrid_shl_V4 : STInst<(outs), - (ins IntRegs:$src1, u2Imm:$src2, u6Imm:$src3, DoubleRegs:$src4), + (ins IntRegs:$src1, u2Imm:$src2, u0AlwaysExt:$src3, DoubleRegs:$src4), "memd($src1<<#$src2+#$src3) = $src4", [(store (i64 DoubleRegs:$src4), (add (shl (i32 IntRegs:$src1), u2ImmPred:$src2), - u6ImmPred:$src3))]>, + u0AlwaysExtPred:$src3))]>, Requires<[HasV4T]>; // memd(Rx++#s4:3)=Rtt @@ -1672,50 +1214,28 @@ def STrid_shl_V4 : STInst<(outs), // if ([!]Pv[.new]) memd(#u6)=Rtt // TODO: needs to be implemented. -// if ([!]Pv[.new]) memd(Rx++#s4:3)=Rtt -// if (Pv) memd(Rx++#s4:3)=Rtt -// if (Pv.new) memd(Rx++#s4:3)=Rtt -let AddedComplexity = 10, neverHasSideEffects = 1, - isPredicated = 1 in -def POST_STdri_cdnPt_V4 : STInst2PI<(outs IntRegs:$dst), - (ins PredRegs:$src1, DoubleRegs:$src2, IntRegs:$src3, - s4_3Imm:$offset), - "if ($src1.new) memd($src3++#$offset) = $src2", - [], - "$src3 = $dst">, - Requires<[HasV4T]>; - -// if (!Pv) memd(Rx++#s4:3)=Rtt -// if (!Pv.new) memd(Rx++#s4:3)=Rtt -let AddedComplexity = 10, neverHasSideEffects = 1, - isPredicated = 1 in -def POST_STdri_cdnNotPt_V4 : STInst2PI<(outs IntRegs:$dst), - (ins PredRegs:$src1, DoubleRegs:$src2, IntRegs:$src3, - s4_3Imm:$offset), - "if (!$src1.new) memd($src3++#$offset) = $src2", - [], - "$src3 = $dst">, - Requires<[HasV4T]>; - - +//===----------------------------------------------------------------------===// // multiclass for store instructions with base + immediate offset // addressing mode and immediate stored value. +// mem[bhw](Rx++#s4:3)=#s8 +// if ([!]Pv[.new]) mem[bhw](Rx++#s4:3)=#s6 +//===----------------------------------------------------------------------===// multiclass ST_Imm_Pbase<string mnemonic, Operand OffsetOp, bit isNot, bit isPredNew> { - let PNewValue = #!if(isPredNew, "new", "") in - def #NAME# : STInst2<(outs), + let PNewValue = !if(isPredNew, "new", "") in + def NAME : STInst2<(outs), (ins PredRegs:$src1, IntRegs:$src2, OffsetOp:$src3, s6Ext:$src4), - #!if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", ") ")#mnemonic#"($src2+#$src3) = #$src4", []>, Requires<[HasV4T]>; } multiclass ST_Imm_Pred<string mnemonic, Operand OffsetOp, bit PredNot> { - let PredSense = #!if(PredNot, "false", "true") in { - defm _c#NAME# : ST_Imm_Pbase<mnemonic, OffsetOp, PredNot, 0>; + let PredSense = !if(PredNot, "false", "true") in { + defm _c#NAME : ST_Imm_Pbase<mnemonic, OffsetOp, PredNot, 0>; // Predicate new - defm _cdn#NAME# : ST_Imm_Pbase<mnemonic, OffsetOp, PredNot, 1>; + defm _cdn#NAME : ST_Imm_Pbase<mnemonic, OffsetOp, PredNot, 1>; } } @@ -1723,9 +1243,9 @@ let isExtendable = 1, isExtentSigned = 1, neverHasSideEffects = 1 in multiclass ST_Imm<string mnemonic, string CextOp, Operand OffsetOp> { let CextOpcode = CextOp, BaseOpcode = CextOp#_imm in { let opExtendable = 2, opExtentBits = 8, isPredicable = 1 in - def #NAME#_V4 : STInst2<(outs), + def NAME#_V4 : STInst2<(outs), (ins IntRegs:$src1, OffsetOp:$src2, s8Ext:$src3), - #mnemonic#"($src1+#$src2) = #$src3", + mnemonic#"($src1+#$src2) = #$src3", []>, Requires<[HasV4T]>; @@ -1738,9 +1258,9 @@ multiclass ST_Imm<string mnemonic, string CextOp, Operand OffsetOp> { let addrMode = BaseImmOffset, InputType = "imm", validSubTargets = HasV4SubT in { - defm STrib_imm : ST_Imm<"memb", "STrib", u6_0Imm>, ImmRegRel; - defm STrih_imm : ST_Imm<"memh", "STrih", u6_1Imm>, ImmRegRel; - defm STriw_imm : ST_Imm<"memw", "STriw", u6_2Imm>, ImmRegRel; + defm STrib_imm : ST_Imm<"memb", "STrib", u6_0Imm>, ImmRegRel, PredNewRel; + defm STrih_imm : ST_Imm<"memh", "STrih", u6_1Imm>, ImmRegRel, PredNewRel; + defm STriw_imm : ST_Imm<"memw", "STriw", u6_2Imm>, ImmRegRel, PredNewRel; } let Predicates = [HasV4T], AddedComplexity = 10 in { @@ -1761,13 +1281,14 @@ def : Pat <(truncstorei8 s8ExtPred:$src2, (i32 IntRegs:$src1)), Requires<[HasV4T]>; // memb(Ru<<#u2+#U6)=Rt -let AddedComplexity = 10 in +let isExtended = 1, opExtendable = 2, AddedComplexity = 10, isNVStorable = 1, +validSubTargets = HasV4SubT in def STrib_shl_V4 : STInst<(outs), - (ins IntRegs:$src1, u2Imm:$src2, u6Imm:$src3, IntRegs:$src4), + (ins IntRegs:$src1, u2Imm:$src2, u0AlwaysExt:$src3, IntRegs:$src4), "memb($src1<<#$src2+#$src3) = $src4", [(truncstorei8 (i32 IntRegs:$src4), (add (shl (i32 IntRegs:$src1), u2ImmPred:$src2), - u6ImmPred:$src3))]>, + u0AlwaysExtPred:$src3))]>, Requires<[HasV4T]>; // memb(Rx++#s4:0:circ(Mu))=Rt @@ -1777,30 +1298,6 @@ def STrib_shl_V4 : STInst<(outs), // memb(gp+#u16:0)=Rt -// Store byte conditionally. -// if ([!]Pv[.new]) memb(#u6)=Rt -// if ([!]Pv[.new]) memb(Rx++#s4:0)=Rt -// if (Pv) memb(Rx++#s4:0)=Rt -// if (Pv.new) memb(Rx++#s4:0)=Rt -let hasCtrlDep = 1, - isPredicated = 1 in -def POST_STbri_cdnPt_V4 : STInst2PI<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_0Imm:$offset), - "if ($src1.new) memb($src3++#$offset) = $src2", - [],"$src3 = $dst">, - Requires<[HasV4T]>; - -// if (!Pv) memb(Rx++#s4:0)=Rt -// if (!Pv.new) memb(Rx++#s4:0)=Rt -let hasCtrlDep = 1, - isPredicated = 1 in -def POST_STbri_cdnNotPt_V4 : STInst2PI<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_0Imm:$offset), - "if (!$src1.new) memb($src3++#$offset) = $src2", - [],"$src3 = $dst">, - Requires<[HasV4T]>; - - // Store halfword. // TODO: needs to be implemented // memh(Re=#U6)=Rt.H @@ -1815,13 +1312,14 @@ def : Pat <(truncstorei16 s8ExtPred:$src2, (i32 IntRegs:$src1)), // memh(Ru<<#u2+#U6)=Rt.H // memh(Ru<<#u2+#U6)=Rt -let AddedComplexity = 10 in +let isExtended = 1, opExtendable = 2, AddedComplexity = 10, isNVStorable = 1, +validSubTargets = HasV4SubT in def STrih_shl_V4 : STInst<(outs), - (ins IntRegs:$src1, u2Imm:$src2, u6Imm:$src3, IntRegs:$src4), + (ins IntRegs:$src1, u2Imm:$src2, u0AlwaysExt:$src3, IntRegs:$src4), "memh($src1<<#$src2+#$src3) = $src4", [(truncstorei16 (i32 IntRegs:$src4), (add (shl (i32 IntRegs:$src1), u2ImmPred:$src2), - u6ImmPred:$src3))]>, + u0AlwaysExtPred:$src3))]>, Requires<[HasV4T]>; // memh(Rx++#s4:1:circ(Mu))=Rt.H @@ -1843,28 +1341,6 @@ def STrih_shl_V4 : STInst<(outs), // if ([!]Pv[.new]) memh(Rx++#s4:1)=Rt.H // TODO: Needs to be implemented. -// if ([!]Pv[.new]) memh(Rx++#s4:1)=Rt -// if (Pv) memh(Rx++#s4:1)=Rt -// if (Pv.new) memh(Rx++#s4:1)=Rt -let hasCtrlDep = 1, - isPredicated = 1 in -def POST_SThri_cdnPt_V4 : STInst2PI<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_1Imm:$offset), - "if ($src1.new) memh($src3++#$offset) = $src2", - [],"$src3 = $dst">, - Requires<[HasV4T]>; - -// if (!Pv) memh(Rx++#s4:1)=Rt -// if (!Pv.new) memh(Rx++#s4:1)=Rt -let hasCtrlDep = 1, - isPredicated = 1 in -def POST_SThri_cdnNotPt_V4 : STInst2PI<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_1Imm:$offset), - "if (!$src1.new) memh($src3++#$offset) = $src2", - [],"$src3 = $dst">, - Requires<[HasV4T]>; - - // Store word. // memw(Re=#U6)=Rt // TODO: Needs to be implemented. @@ -1883,13 +1359,14 @@ def : Pat <(store s8ExtPred:$src2, (i32 IntRegs:$src1)), Requires<[HasV4T]>; // memw(Ru<<#u2+#U6)=Rt -let AddedComplexity = 10 in +let isExtended = 1, opExtendable = 2, AddedComplexity = 10, isNVStorable = 1, +validSubTargets = HasV4SubT in def STriw_shl_V4 : STInst<(outs), - (ins IntRegs:$src1, u2Imm:$src2, u6Imm:$src3, IntRegs:$src4), + (ins IntRegs:$src1, u2Imm:$src2, u0AlwaysExt:$src3, IntRegs:$src4), "memw($src1<<#$src2+#$src3) = $src4", [(store (i32 IntRegs:$src4), (add (shl (i32 IntRegs:$src1), u2ImmPred:$src2), - u6ImmPred:$src3))]>, + u0AlwaysExtPred:$src3))]>, Requires<[HasV4T]>; // memw(Rx++#s4:2)=Rt @@ -1900,188 +1377,9 @@ def STriw_shl_V4 : STInst<(outs), // memw(gp+#u16:2)=Rt -// if ([!]Pv[.new]) memw(Rx++#s4:2)=Rt -// if (Pv) memw(Rx++#s4:2)=Rt -// if (Pv.new) memw(Rx++#s4:2)=Rt -let hasCtrlDep = 1, - isPredicated = 1 in -def POST_STwri_cdnPt_V4 : STInst2PI<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_2Imm:$offset), - "if ($src1.new) memw($src3++#$offset) = $src2", - [],"$src3 = $dst">, - Requires<[HasV4T]>; - -// if (!Pv) memw(Rx++#s4:2)=Rt -// if (!Pv.new) memw(Rx++#s4:2)=Rt -let hasCtrlDep = 1, - isPredicated = 1 in -def POST_STwri_cdnNotPt_V4 : STInst2PI<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_2Imm:$offset), - "if (!$src1.new) memw($src3++#$offset) = $src2", - [],"$src3 = $dst">, - Requires<[HasV4T]>; - - -/// store to global address - -let isPredicable = 1, neverHasSideEffects = 1 in -def STrid_GP_V4 : STInst2<(outs), - (ins globaladdress:$global, u16Imm:$offset, DoubleRegs:$src), - "memd(#$global+$offset) = $src", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def STrid_GP_cPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - DoubleRegs:$src2), - "if ($src1) memd(##$global+$offset) = $src2", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def STrid_GP_cNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - DoubleRegs:$src2), - "if (!$src1) memd(##$global+$offset) = $src2", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def STrid_GP_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - DoubleRegs:$src2), - "if ($src1.new) memd(##$global+$offset) = $src2", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def STrid_GP_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - DoubleRegs:$src2), - "if (!$src1.new) memd(##$global+$offset) = $src2", - []>, - Requires<[HasV4T]>; - -let isPredicable = 1, neverHasSideEffects = 1 in -def STrib_GP_V4 : STInst2<(outs), - (ins globaladdress:$global, u16Imm:$offset, IntRegs:$src), - "memb(#$global+$offset) = $src", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def STrib_GP_cPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if ($src1) memb(##$global+$offset) = $src2", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def STrib_GP_cNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if (!$src1) memb(##$global+$offset) = $src2", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def STrib_GP_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if ($src1.new) memb(##$global+$offset) = $src2", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def STrib_GP_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if (!$src1.new) memb(##$global+$offset) = $src2", - []>, - Requires<[HasV4T]>; - -let isPredicable = 1, neverHasSideEffects = 1 in -def STrih_GP_V4 : STInst2<(outs), - (ins globaladdress:$global, u16Imm:$offset, IntRegs:$src), - "memh(#$global+$offset) = $src", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def STrih_GP_cPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if ($src1) memh(##$global+$offset) = $src2", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def STrih_GP_cNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if (!$src1) memh(##$global+$offset) = $src2", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def STrih_GP_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if ($src1.new) memh(##$global+$offset) = $src2", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def STrih_GP_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if (!$src1.new) memh(##$global+$offset) = $src2", - []>, - Requires<[HasV4T]>; - -let isPredicable = 1, neverHasSideEffects = 1 in -def STriw_GP_V4 : STInst2<(outs), - (ins globaladdress:$global, u16Imm:$offset, IntRegs:$src), - "memw(#$global+$offset) = $src", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def STriw_GP_cPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if ($src1) memw(##$global+$offset) = $src2", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def STriw_GP_cNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if (!$src1) memw(##$global+$offset) = $src2", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def STriw_GP_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if ($src1.new) memw(##$global+$offset) = $src2", - []>, - Requires<[HasV4T]>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def STriw_GP_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if (!$src1.new) memw(##$global+$offset) = $src2", - []>, - Requires<[HasV4T]>; - // memd(#global)=Rtt -let isPredicable = 1, neverHasSideEffects = 1 in +let isPredicable = 1, mayStore = 1, neverHasSideEffects = 1, +validSubTargets = HasV4SubT in def STd_GP_V4 : STInst2<(outs), (ins globaladdress:$global, DoubleRegs:$src), "memd(#$global) = $src", @@ -2089,7 +1387,8 @@ def STd_GP_V4 : STInst2<(outs), Requires<[HasV4T]>; // if (Pv) memd(##global) = Rtt -let neverHasSideEffects = 1, isPredicated = 1 in +let mayStore = 1, neverHasSideEffects = 1, isPredicated = 1, +isExtended = 1, opExtendable = 1, validSubTargets = HasV4SubT in { def STd_GP_cPt_V4 : STInst2<(outs), (ins PredRegs:$src1, globaladdress:$global, DoubleRegs:$src2), "if ($src1) memd(##$global) = $src2", @@ -2097,7 +1396,6 @@ def STd_GP_cPt_V4 : STInst2<(outs), Requires<[HasV4T]>; // if (!Pv) memd(##global) = Rtt -let neverHasSideEffects = 1, isPredicated = 1 in def STd_GP_cNotPt_V4 : STInst2<(outs), (ins PredRegs:$src1, globaladdress:$global, DoubleRegs:$src2), "if (!$src1) memd(##$global) = $src2", @@ -2105,7 +1403,6 @@ def STd_GP_cNotPt_V4 : STInst2<(outs), Requires<[HasV4T]>; // if (Pv) memd(##global) = Rtt -let neverHasSideEffects = 1, isPredicated = 1 in def STd_GP_cdnPt_V4 : STInst2<(outs), (ins PredRegs:$src1, globaladdress:$global, DoubleRegs:$src2), "if ($src1.new) memd(##$global) = $src2", @@ -2113,15 +1410,16 @@ def STd_GP_cdnPt_V4 : STInst2<(outs), Requires<[HasV4T]>; // if (!Pv) memd(##global) = Rtt -let neverHasSideEffects = 1, isPredicated = 1 in def STd_GP_cdnNotPt_V4 : STInst2<(outs), (ins PredRegs:$src1, globaladdress:$global, DoubleRegs:$src2), "if (!$src1.new) memd(##$global) = $src2", []>, Requires<[HasV4T]>; +} // memb(#global)=Rt -let isPredicable = 1, neverHasSideEffects = 1 in +let isPredicable = 1, neverHasSideEffects = 1, isNVStorable = 1, +validSubTargets = HasV4SubT in def STb_GP_V4 : STInst2<(outs), (ins globaladdress:$global, IntRegs:$src), "memb(#$global) = $src", @@ -2129,7 +1427,8 @@ def STb_GP_V4 : STInst2<(outs), Requires<[HasV4T]>; // if (Pv) memb(##global) = Rt -let neverHasSideEffects = 1, isPredicated = 1 in +let neverHasSideEffects = 1, isPredicated = 1, isNVStorable = 1, +isExtended = 1, opExtendable = 1, validSubTargets = HasV4SubT in { def STb_GP_cPt_V4 : STInst2<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if ($src1) memb(##$global) = $src2", @@ -2137,7 +1436,6 @@ def STb_GP_cPt_V4 : STInst2<(outs), Requires<[HasV4T]>; // if (!Pv) memb(##global) = Rt -let neverHasSideEffects = 1, isPredicated = 1 in def STb_GP_cNotPt_V4 : STInst2<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if (!$src1) memb(##$global) = $src2", @@ -2145,7 +1443,6 @@ def STb_GP_cNotPt_V4 : STInst2<(outs), Requires<[HasV4T]>; // if (Pv) memb(##global) = Rt -let neverHasSideEffects = 1, isPredicated = 1 in def STb_GP_cdnPt_V4 : STInst2<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if ($src1.new) memb(##$global) = $src2", @@ -2153,15 +1450,16 @@ def STb_GP_cdnPt_V4 : STInst2<(outs), Requires<[HasV4T]>; // if (!Pv) memb(##global) = Rt -let neverHasSideEffects = 1, isPredicated = 1 in def STb_GP_cdnNotPt_V4 : STInst2<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if (!$src1.new) memb(##$global) = $src2", []>, Requires<[HasV4T]>; +} // memh(#global)=Rt -let isPredicable = 1, neverHasSideEffects = 1 in +let isPredicable = 1, neverHasSideEffects = 1, isNVStorable = 1, +validSubTargets = HasV4SubT in def STh_GP_V4 : STInst2<(outs), (ins globaladdress:$global, IntRegs:$src), "memh(#$global) = $src", @@ -2169,7 +1467,8 @@ def STh_GP_V4 : STInst2<(outs), Requires<[HasV4T]>; // if (Pv) memh(##global) = Rt -let neverHasSideEffects = 1, isPredicated = 1 in +let neverHasSideEffects = 1, isPredicated = 1, isNVStorable = 1, +isExtended = 1, opExtendable = 1, validSubTargets = HasV4SubT in { def STh_GP_cPt_V4 : STInst2<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if ($src1) memh(##$global) = $src2", @@ -2177,7 +1476,6 @@ def STh_GP_cPt_V4 : STInst2<(outs), Requires<[HasV4T]>; // if (!Pv) memh(##global) = Rt -let neverHasSideEffects = 1, isPredicated = 1 in def STh_GP_cNotPt_V4 : STInst2<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if (!$src1) memh(##$global) = $src2", @@ -2185,7 +1483,6 @@ def STh_GP_cNotPt_V4 : STInst2<(outs), Requires<[HasV4T]>; // if (Pv) memh(##global) = Rt -let neverHasSideEffects = 1, isPredicated = 1 in def STh_GP_cdnPt_V4 : STInst2<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if ($src1.new) memh(##$global) = $src2", @@ -2193,15 +1490,16 @@ def STh_GP_cdnPt_V4 : STInst2<(outs), Requires<[HasV4T]>; // if (!Pv) memh(##global) = Rt -let neverHasSideEffects = 1, isPredicated = 1 in def STh_GP_cdnNotPt_V4 : STInst2<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if (!$src1.new) memh(##$global) = $src2", []>, Requires<[HasV4T]>; +} // memw(#global)=Rt -let isPredicable = 1, neverHasSideEffects = 1 in +let isPredicable = 1, neverHasSideEffects = 1, isNVStorable = 1, +validSubTargets = HasV4SubT in def STw_GP_V4 : STInst2<(outs), (ins globaladdress:$global, IntRegs:$src), "memw(#$global) = $src", @@ -2209,7 +1507,8 @@ def STw_GP_V4 : STInst2<(outs), Requires<[HasV4T]>; // if (Pv) memw(##global) = Rt -let neverHasSideEffects = 1, isPredicated = 1 in +let neverHasSideEffects = 1, isPredicated = 1, isNVStorable = 1, +isExtended = 1, opExtendable = 1, validSubTargets = HasV4SubT in { def STw_GP_cPt_V4 : STInst2<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if ($src1) memw(##$global) = $src2", @@ -2217,7 +1516,6 @@ def STw_GP_cPt_V4 : STInst2<(outs), Requires<[HasV4T]>; // if (!Pv) memw(##global) = Rt -let neverHasSideEffects = 1, isPredicated = 1 in def STw_GP_cNotPt_V4 : STInst2<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if (!$src1) memw(##$global) = $src2", @@ -2225,7 +1523,6 @@ def STw_GP_cNotPt_V4 : STInst2<(outs), Requires<[HasV4T]>; // if (Pv) memw(##global) = Rt -let neverHasSideEffects = 1, isPredicated = 1 in def STw_GP_cdnPt_V4 : STInst2<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if ($src1.new) memw(##$global) = $src2", @@ -2233,12 +1530,12 @@ def STw_GP_cdnPt_V4 : STInst2<(outs), Requires<[HasV4T]>; // if (!Pv) memw(##global) = Rt -let neverHasSideEffects = 1, isPredicated = 1 in def STw_GP_cdnNotPt_V4 : STInst2<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if (!$src1.new) memw(##$global) = $src2", []>, Requires<[HasV4T]>; +} // 64 bit atomic store def : Pat <(atomic_store_64 (HexagonCONST32_GP tglobaladdr:$global), @@ -2297,72 +1594,6 @@ def : Pat<(store (i32 IntRegs:$src1), (HexagonCONST32_GP tglobaladdr:$global)), (STw_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>, Requires<[HasV4T]>; -def : Pat<(atomic_store_64 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset), - (i64 DoubleRegs:$src1)), - (STrid_GP_V4 tglobaladdr:$global, u16ImmPred:$offset, - (i64 DoubleRegs:$src1))>, - Requires<[HasV4T]>; - -def : Pat<(atomic_store_32 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset), - (i32 IntRegs:$src1)), - (STriw_GP_V4 tglobaladdr:$global, u16ImmPred:$offset, - (i32 IntRegs:$src1))>, - Requires<[HasV4T]>; - -def : Pat<(atomic_store_16 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset), - (i32 IntRegs:$src1)), - (STrih_GP_V4 tglobaladdr:$global, u16ImmPred:$offset, - (i32 IntRegs:$src1))>, - Requires<[HasV4T]>; - -def : Pat<(atomic_store_8 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset), - (i32 IntRegs:$src1)), - (STrib_GP_V4 tglobaladdr:$global, u16ImmPred:$offset, - (i32 IntRegs:$src1))>, - Requires<[HasV4T]>; - -// Map from store(globaladdress + x) -> memd(#foo + x) -let AddedComplexity = 100 in -def : Pat<(store (i64 DoubleRegs:$src1), - (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset)), - (STrid_GP_V4 tglobaladdr:$global, u16ImmPred:$offset, - (i64 DoubleRegs:$src1))>, - Requires<[HasV4T]>; - -// Map from store(globaladdress + x) -> memb(#foo + x) -let AddedComplexity = 100 in -def : Pat<(truncstorei8 (i32 IntRegs:$src1), - (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset)), - (STrib_GP_V4 tglobaladdr:$global, u16ImmPred:$offset, - (i32 IntRegs:$src1))>, - Requires<[HasV4T]>; - -// Map from store(globaladdress + x) -> memh(#foo + x) -let AddedComplexity = 100 in -def : Pat<(truncstorei16 (i32 IntRegs:$src1), - (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset)), - (STrih_GP_V4 tglobaladdr:$global, u16ImmPred:$offset, - (i32 IntRegs:$src1))>, - Requires<[HasV4T]>; - -// Map from store(globaladdress + x) -> memw(#foo + x) -let AddedComplexity = 100 in -def : Pat<(store (i32 IntRegs:$src1), - (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset)), - (STriw_GP_V4 tglobaladdr:$global, u16ImmPred:$offset, - (i32 IntRegs:$src1))>, - Requires<[HasV4T]>; - - - //===----------------------------------------------------------------------=== // ST - //===----------------------------------------------------------------------=== @@ -2376,8 +1607,8 @@ def : Pat<(store (i32 IntRegs:$src1), // multiclass ST_Idxd_Pbase_nv<string mnemonic, RegisterClass RC, Operand predImmOp, bit isNot, bit isPredNew> { - let PNewValue = #!if(isPredNew, "new", "") in - def #NAME#_nv_V4 : NVInst_V4<(outs), + let PNewValue = !if(isPredNew, "new", "") in + def NAME#_nv_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, IntRegs:$src2, predImmOp:$src3, RC: $src4), !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", ") ")#mnemonic#"($src2+#$src3) = $src4.new", @@ -2387,10 +1618,10 @@ multiclass ST_Idxd_Pbase_nv<string mnemonic, RegisterClass RC, multiclass ST_Idxd_Pred_nv<string mnemonic, RegisterClass RC, Operand predImmOp, bit PredNot> { - let PredSense = #!if(PredNot, "false", "true") in { - defm _c#NAME# : ST_Idxd_Pbase_nv<mnemonic, RC, predImmOp, PredNot, 0>; + let PredSense = !if(PredNot, "false", "true") in { + defm _c#NAME : ST_Idxd_Pbase_nv<mnemonic, RC, predImmOp, PredNot, 0>; // Predicate new - defm _cdn#NAME# : ST_Idxd_Pbase_nv<mnemonic, RC, predImmOp, PredNot, 1>; + defm _cdn#NAME : ST_Idxd_Pbase_nv<mnemonic, RC, predImmOp, PredNot, 1>; } } @@ -2402,9 +1633,9 @@ multiclass ST_Idxd_nv<string mnemonic, string CextOp, RegisterClass RC, let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed in { let opExtendable = 1, isExtentSigned = 1, opExtentBits = ImmBits, isPredicable = 1 in - def #NAME#_nv_V4 : NVInst_V4<(outs), + def NAME#_nv_V4 : NVInst_V4<(outs), (ins IntRegs:$src1, ImmOp:$src2, RC:$src3), - #mnemonic#"($src1+#$src2) = $src3.new", + mnemonic#"($src1+#$src2) = $src3.new", []>, Requires<[HasV4T]>; @@ -2425,46 +1656,123 @@ let addrMode = BaseImmOffset, validSubTargets = HasV4SubT in { u6_2Ext, 13, 8>, AddrModeRel; } -// Store new-value byte. +// multiclass for new-value store instructions with base + immediate offset. +// and MEMri operand. +multiclass ST_MEMri_Pbase_nv<string mnemonic, RegisterClass RC, bit isNot, + bit isPredNew> { + let PNewValue = !if(isPredNew, "new", "") in + def NAME#_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, MEMri:$addr, RC: $src2), + !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + ") ")#mnemonic#"($addr) = $src2.new", + []>, + Requires<[HasV4T]>; +} + +multiclass ST_MEMri_Pred_nv<string mnemonic, RegisterClass RC, bit PredNot> { + let PredSense = !if(PredNot, "false", "true") in { + defm _c#NAME : ST_MEMri_Pbase_nv<mnemonic, RC, PredNot, 0>; + + // Predicate new + defm _cdn#NAME : ST_MEMri_Pbase_nv<mnemonic, RC, PredNot, 1>; + } +} -// memb(Re=#U6)=Nt.new -// memb(Rs+#s11:0)=Nt.new -let mayStore = 1, isPredicable = 1 in -def STrib_nv_V4 : NVInst_V4<(outs), (ins MEMri:$addr, IntRegs:$src1), - "memb($addr) = $src1.new", +let mayStore = 1, isNVStore = 1, isExtendable = 1, neverHasSideEffects = 1 in +multiclass ST_MEMri_nv<string mnemonic, string CextOp, RegisterClass RC, + bits<5> ImmBits, bits<5> PredImmBits> { + + let CextOpcode = CextOp, BaseOpcode = CextOp in { + let opExtendable = 1, isExtentSigned = 1, opExtentBits = ImmBits, + isPredicable = 1 in + def NAME#_nv_V4 : NVInst_V4<(outs), + (ins MEMri:$addr, RC:$src), + mnemonic#"($addr) = $src.new", []>, Requires<[HasV4T]>; + let opExtendable = 2, isExtentSigned = 0, opExtentBits = PredImmBits, + neverHasSideEffects = 1, isPredicated = 1 in { + defm Pt : ST_MEMri_Pred_nv<mnemonic, RC, 0>; + defm NotPt : ST_MEMri_Pred_nv<mnemonic, RC, 1>; + } + } +} + +let addrMode = BaseImmOffset, isMEMri = "true", validSubTargets = HasV4SubT, +mayStore = 1 in { + defm STrib: ST_MEMri_nv<"memb", "STrib", IntRegs, 11, 6>, AddrModeRel; + defm STrih: ST_MEMri_nv<"memh", "STrih", IntRegs, 12, 7>, AddrModeRel; + defm STriw: ST_MEMri_nv<"memw", "STriw", IntRegs, 13, 8>, AddrModeRel; +} + // memb(Ru<<#u2+#U6)=Nt.new -let mayStore = 1, AddedComplexity = 10 in +let isExtended = 1, opExtendable = 2, mayStore = 1, AddedComplexity = 10, +isNVStore = 1, validSubTargets = HasV4SubT in def STrib_shl_nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, u2Imm:$src2, u6Imm:$src3, IntRegs:$src4), + (ins IntRegs:$src1, u2Imm:$src2, u0AlwaysExt:$src3, IntRegs:$src4), "memb($src1<<#$src2+#$src3) = $src4.new", []>, Requires<[HasV4T]>; -// memb(Rx++#s4:0)=Nt.new -let mayStore = 1, hasCtrlDep = 1, isPredicable = 1 in -def POST_STbri_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, s4_0Imm:$offset), - "memb($src2++#$offset) = $src1.new", +//===----------------------------------------------------------------------===// +// Post increment store +// mem[bhwd](Rx++#s4:[0123])=Nt.new +//===----------------------------------------------------------------------===// + +multiclass ST_PostInc_Pbase_nv<string mnemonic, RegisterClass RC, Operand ImmOp, + bit isNot, bit isPredNew> { + let PNewValue = !if(isPredNew, "new", "") in + def NAME#_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, ImmOp:$offset, RC:$src3), + !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + ") ")#mnemonic#"($src2++#$offset) = $src3.new", [], "$src2 = $dst">, Requires<[HasV4T]>; +} + +multiclass ST_PostInc_Pred_nv<string mnemonic, RegisterClass RC, + Operand ImmOp, bit PredNot> { + let PredSense = !if(PredNot, "false", "true") in { + defm _c#NAME : ST_PostInc_Pbase_nv<mnemonic, RC, ImmOp, PredNot, 0>; + // Predicate new + let Predicates = [HasV4T], validSubTargets = HasV4SubT in + defm _cdn#NAME : ST_PostInc_Pbase_nv<mnemonic, RC, ImmOp, PredNot, 1>; + } +} + +let hasCtrlDep = 1, isNVStore = 1, neverHasSideEffects = 1 in +multiclass ST_PostInc_nv<string mnemonic, string BaseOp, RegisterClass RC, + Operand ImmOp> { + + let BaseOpcode = "POST_"#BaseOp in { + let isPredicable = 1 in + def NAME#_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), + (ins IntRegs:$src1, ImmOp:$offset, RC:$src2), + mnemonic#"($src1++#$offset) = $src2.new", + [], + "$src1 = $dst">, + Requires<[HasV4T]>; + + let isPredicated = 1 in { + defm Pt : ST_PostInc_Pred_nv<mnemonic, RC, ImmOp, 0 >; + defm NotPt : ST_PostInc_Pred_nv<mnemonic, RC, ImmOp, 1 >; + } + } +} + +let validSubTargets = HasV4SubT in { +defm POST_STbri: ST_PostInc_nv <"memb", "STrib", IntRegs, s4_0Imm>, AddrModeRel; +defm POST_SThri: ST_PostInc_nv <"memh", "STrih", IntRegs, s4_1Imm>, AddrModeRel; +defm POST_STwri: ST_PostInc_nv <"memw", "STriw", IntRegs, s4_2Imm>, AddrModeRel; +} // memb(Rx++#s4:0:circ(Mu))=Nt.new // memb(Rx++I:circ(Mu))=Nt.new // memb(Rx++Mu)=Nt.new // memb(Rx++Mu:brev)=Nt.new -// memb(gp+#u16:0)=Nt.new -let mayStore = 1, neverHasSideEffects = 1 in -def STrib_GP_nv_V4 : NVInst_V4<(outs), - (ins globaladdress:$global, u16Imm:$offset, IntRegs:$src), - "memb(#$global+$offset) = $src.new", - []>, - Requires<[HasV4T]>; - // memb(#global)=Nt.new let mayStore = 1, neverHasSideEffects = 1 in def STb_GP_nv_V4 : NVInst_V4<(outs), @@ -2473,121 +1781,20 @@ def STb_GP_nv_V4 : NVInst_V4<(outs), []>, Requires<[HasV4T]>; -// Store new-value byte conditionally. -// if ([!]Pv[.new]) memb(#u6)=Nt.new -// if (Pv) memb(Rs+#u6:0)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STrib_cPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if ($src1) memb($addr) = $src2.new", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) memb(Rs+#u6:0)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STrib_cdnPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if ($src1.new) memb($addr) = $src2.new", - []>, - Requires<[HasV4T]>; - -// if (!Pv) memb(Rs+#u6:0)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STrib_cNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if (!$src1) memb($addr) = $src2.new", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) memb(Rs+#u6:0)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STrib_cdnNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if (!$src1.new) memb($addr) = $src2.new", - []>, - Requires<[HasV4T]>; - -// if ([!]Pv[.new]) memb(Rx++#s4:0)=Nt.new -// if (Pv) memb(Rx++#s4:0)=Nt.new -let mayStore = 1, hasCtrlDep = 1, - isPredicated = 1 in -def POST_STbri_cPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_0Imm:$offset), - "if ($src1) memb($src3++#$offset) = $src2.new", - [],"$src3 = $dst">, - Requires<[HasV4T]>; - -// if (Pv.new) memb(Rx++#s4:0)=Nt.new -let mayStore = 1, hasCtrlDep = 1, - isPredicated = 1 in -def POST_STbri_cdnPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_0Imm:$offset), - "if ($src1.new) memb($src3++#$offset) = $src2.new", - [],"$src3 = $dst">, - Requires<[HasV4T]>; - -// if (!Pv) memb(Rx++#s4:0)=Nt.new -let mayStore = 1, hasCtrlDep = 1, - isPredicated = 1 in -def POST_STbri_cNotPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_0Imm:$offset), - "if (!$src1) memb($src3++#$offset) = $src2.new", - [],"$src3 = $dst">, - Requires<[HasV4T]>; - -// if (!Pv.new) memb(Rx++#s4:0)=Nt.new -let mayStore = 1, hasCtrlDep = 1, - isPredicated = 1 in -def POST_STbri_cdnNotPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_0Imm:$offset), - "if (!$src1.new) memb($src3++#$offset) = $src2.new", - [],"$src3 = $dst">, - Requires<[HasV4T]>; - - -// Store new-value halfword. -// memh(Re=#U6)=Nt.new -// memh(Rs+#s11:1)=Nt.new -let mayStore = 1, isPredicable = 1 in -def STrih_nv_V4 : NVInst_V4<(outs), (ins MEMri:$addr, IntRegs:$src1), - "memh($addr) = $src1.new", - []>, - Requires<[HasV4T]>; - // memh(Ru<<#u2+#U6)=Nt.new -let mayStore = 1, AddedComplexity = 10 in +let isExtended = 1, opExtendable = 2, mayStore = 1, AddedComplexity = 10, +isNVStore = 1, validSubTargets = HasV4SubT in def STrih_shl_nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, u2Imm:$src2, u6Imm:$src3, IntRegs:$src4), + (ins IntRegs:$src1, u2Imm:$src2, u0AlwaysExt:$src3, IntRegs:$src4), "memh($src1<<#$src2+#$src3) = $src4.new", []>, Requires<[HasV4T]>; -// memh(Rx++#s4:1)=Nt.new -let mayStore = 1, hasCtrlDep = 1, isPredicable = 1 in -def POST_SThri_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, s4_1Imm:$offset), - "memh($src2++#$offset) = $src1.new", - [], - "$src2 = $dst">, - Requires<[HasV4T]>; - // memh(Rx++#s4:1:circ(Mu))=Nt.new // memh(Rx++I:circ(Mu))=Nt.new // memh(Rx++Mu)=Nt.new // memh(Rx++Mu:brev)=Nt.new -// memh(gp+#u16:1)=Nt.new -let mayStore = 1, neverHasSideEffects = 1 in -def STrih_GP_nv_V4 : NVInst_V4<(outs), - (ins globaladdress:$global, u16Imm:$offset, IntRegs:$src), - "memh(#$global+$offset) = $src.new", - []>, - Requires<[HasV4T]>; - // memh(#global)=Nt.new let mayStore = 1, neverHasSideEffects = 1 in def STh_GP_nv_V4 : NVInst_V4<(outs), @@ -2596,215 +1803,32 @@ def STh_GP_nv_V4 : NVInst_V4<(outs), []>, Requires<[HasV4T]>; - -// Store new-value halfword conditionally. - -// if ([!]Pv[.new]) memh(#u6)=Nt.new - -// if ([!]Pv[.new]) memh(Rs+#u6:1)=Nt.new -// if (Pv) memh(Rs+#u6:1)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STrih_cPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if ($src1) memh($addr) = $src2.new", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) memh(Rs+#u6:1)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STrih_cdnPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if ($src1.new) memh($addr) = $src2.new", - []>, - Requires<[HasV4T]>; - -// if (!Pv) memh(Rs+#u6:1)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STrih_cNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if (!$src1) memh($addr) = $src2.new", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) memh(Rs+#u6:1)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STrih_cdnNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if (!$src1.new) memh($addr) = $src2.new", - []>, - Requires<[HasV4T]>; - -// if ([!]Pv[]) memh(Rx++#s4:1)=Nt.new -// if (Pv) memh(Rx++#s4:1)=Nt.new -let mayStore = 1, hasCtrlDep = 1, - isPredicated = 1 in -def POST_SThri_cPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_1Imm:$offset), - "if ($src1) memh($src3++#$offset) = $src2.new", - [],"$src3 = $dst">, - Requires<[HasV4T]>; - -// if (Pv.new) memh(Rx++#s4:1)=Nt.new -let mayStore = 1, hasCtrlDep = 1, - isPredicated = 1 in -def POST_SThri_cdnPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_1Imm:$offset), - "if ($src1.new) memh($src3++#$offset) = $src2.new", - [],"$src3 = $dst">, - Requires<[HasV4T]>; - -// if (!Pv) memh(Rx++#s4:1)=Nt.new -let mayStore = 1, hasCtrlDep = 1, - isPredicated = 1 in -def POST_SThri_cNotPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_1Imm:$offset), - "if (!$src1) memh($src3++#$offset) = $src2.new", - [],"$src3 = $dst">, - Requires<[HasV4T]>; - -// if (!Pv.new) memh(Rx++#s4:1)=Nt.new -let mayStore = 1, hasCtrlDep = 1, - isPredicated = 1 in -def POST_SThri_cdnNotPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_1Imm:$offset), - "if (!$src1.new) memh($src3++#$offset) = $src2.new", - [],"$src3 = $dst">, - Requires<[HasV4T]>; - - -// Store new-value word. - -// memw(Re=#U6)=Nt.new -// memw(Rs+#s11:2)=Nt.new -let mayStore = 1, isPredicable = 1 in -def STriw_nv_V4 : NVInst_V4<(outs), - (ins MEMri:$addr, IntRegs:$src1), - "memw($addr) = $src1.new", - []>, - Requires<[HasV4T]>; - // memw(Ru<<#u2+#U6)=Nt.new -let mayStore = 1, AddedComplexity = 10 in +let isExtended = 1, opExtendable = 2, mayStore = 1, AddedComplexity = 10, +isNVStore = 1, validSubTargets = HasV4SubT in def STriw_shl_nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, u2Imm:$src2, u6Imm:$src3, IntRegs:$src4), + (ins IntRegs:$src1, u2Imm:$src2, u0AlwaysExt:$src3, IntRegs:$src4), "memw($src1<<#$src2+#$src3) = $src4.new", []>, Requires<[HasV4T]>; -// memw(Rx++#s4:2)=Nt.new -let mayStore = 1, hasCtrlDep = 1, isPredicable = 1 in -def POST_STwri_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, s4_2Imm:$offset), - "memw($src2++#$offset) = $src1.new", - [], - "$src2 = $dst">, - Requires<[HasV4T]>; - // memw(Rx++#s4:2:circ(Mu))=Nt.new // memw(Rx++I:circ(Mu))=Nt.new // memw(Rx++Mu)=Nt.new // memw(Rx++Mu:brev)=Nt.new // memw(gp+#u16:2)=Nt.new -let mayStore = 1, neverHasSideEffects = 1 in -def STriw_GP_nv_V4 : NVInst_V4<(outs), - (ins globaladdress:$global, u16Imm:$offset, IntRegs:$src), - "memw(#$global+$offset) = $src.new", - []>, - Requires<[HasV4T]>; -let mayStore = 1, neverHasSideEffects = 1 in +let mayStore = 1, neverHasSideEffects = 1, isNVStore = 1, +validSubTargets = HasV4SubT in def STw_GP_nv_V4 : NVInst_V4<(outs), (ins globaladdress:$global, IntRegs:$src), "memw(#$global) = $src.new", []>, Requires<[HasV4T]>; -// Store new-value word conditionally. - -// if ([!]Pv[.new]) memw(#u6)=Nt.new - -// if ([!]Pv[.new]) memw(Rs+#u6:2)=Nt.new -// if (Pv) memw(Rs+#u6:2)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STriw_cPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if ($src1) memw($addr) = $src2.new", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) memw(Rs+#u6:2)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STriw_cdnPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if ($src1.new) memw($addr) = $src2.new", - []>, - Requires<[HasV4T]>; - -// if (!Pv) memw(Rs+#u6:2)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STriw_cNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if (!$src1) memw($addr) = $src2.new", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) memw(Rs+#u6:2)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STriw_cdnNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if (!$src1.new) memw($addr) = $src2.new", - []>, - Requires<[HasV4T]>; - -// if ([!]Pv[.new]) memw(Rx++#s4:2)=Nt.new -// if (Pv) memw(Rx++#s4:2)=Nt.new -let mayStore = 1, hasCtrlDep = 1, - isPredicated = 1 in -def POST_STwri_cPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_2Imm:$offset), - "if ($src1) memw($src3++#$offset) = $src2.new", - [],"$src3 = $dst">, - Requires<[HasV4T]>; - -// if (Pv.new) memw(Rx++#s4:2)=Nt.new -let mayStore = 1, hasCtrlDep = 1, - isPredicated = 1 in -def POST_STwri_cdnPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_2Imm:$offset), - "if ($src1.new) memw($src3++#$offset) = $src2.new", - [],"$src3 = $dst">, - Requires<[HasV4T]>; - -// if (!Pv) memw(Rx++#s4:2)=Nt.new -let mayStore = 1, hasCtrlDep = 1, - isPredicated = 1 in -def POST_STwri_cNotPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_2Imm:$offset), - "if (!$src1) memw($src3++#$offset) = $src2.new", - [],"$src3 = $dst">, - Requires<[HasV4T]>; - -// if (!Pv.new) memw(Rx++#s4:2)=Nt.new -let mayStore = 1, hasCtrlDep = 1, - isPredicated = 1 in -def POST_STwri_cdnNotPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_2Imm:$offset), - "if (!$src1.new) memw($src3++#$offset) = $src2.new", - [],"$src3 = $dst">, - Requires<[HasV4T]>; - - - // if (Pv) memb(##global) = Rt -let mayStore = 1, neverHasSideEffects = 1 in +let mayStore = 1, neverHasSideEffects = 1, isNVStore = 1, +isExtended = 1, opExtendable = 1, validSubTargets = HasV4SubT in { def STb_GP_cPt_nv_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if ($src1) memb(##$global) = $src2.new", @@ -2812,7 +1836,6 @@ def STb_GP_cPt_nv_V4 : NVInst_V4<(outs), Requires<[HasV4T]>; // if (!Pv) memb(##global) = Rt -let mayStore = 1, neverHasSideEffects = 1 in def STb_GP_cNotPt_nv_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if (!$src1) memb(##$global) = $src2.new", @@ -2820,7 +1843,6 @@ def STb_GP_cNotPt_nv_V4 : NVInst_V4<(outs), Requires<[HasV4T]>; // if (Pv) memb(##global) = Rt -let mayStore = 1, neverHasSideEffects = 1 in def STb_GP_cdnPt_nv_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if ($src1.new) memb(##$global) = $src2.new", @@ -2828,7 +1850,6 @@ def STb_GP_cdnPt_nv_V4 : NVInst_V4<(outs), Requires<[HasV4T]>; // if (!Pv) memb(##global) = Rt -let mayStore = 1, neverHasSideEffects = 1 in def STb_GP_cdnNotPt_nv_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if (!$src1.new) memb(##$global) = $src2.new", @@ -2836,7 +1857,6 @@ def STb_GP_cdnNotPt_nv_V4 : NVInst_V4<(outs), Requires<[HasV4T]>; // if (Pv) memh(##global) = Rt -let mayStore = 1, neverHasSideEffects = 1 in def STh_GP_cPt_nv_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if ($src1) memh(##$global) = $src2.new", @@ -2844,7 +1864,6 @@ def STh_GP_cPt_nv_V4 : NVInst_V4<(outs), Requires<[HasV4T]>; // if (!Pv) memh(##global) = Rt -let mayStore = 1, neverHasSideEffects = 1 in def STh_GP_cNotPt_nv_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if (!$src1) memh(##$global) = $src2.new", @@ -2852,7 +1871,6 @@ def STh_GP_cNotPt_nv_V4 : NVInst_V4<(outs), Requires<[HasV4T]>; // if (Pv) memh(##global) = Rt -let mayStore = 1, neverHasSideEffects = 1 in def STh_GP_cdnPt_nv_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if ($src1.new) memh(##$global) = $src2.new", @@ -2860,7 +1878,6 @@ def STh_GP_cdnPt_nv_V4 : NVInst_V4<(outs), Requires<[HasV4T]>; // if (!Pv) memh(##global) = Rt -let mayStore = 1, neverHasSideEffects = 1 in def STh_GP_cdnNotPt_nv_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if (!$src1.new) memh(##$global) = $src2.new", @@ -2868,7 +1885,6 @@ def STh_GP_cdnNotPt_nv_V4 : NVInst_V4<(outs), Requires<[HasV4T]>; // if (Pv) memw(##global) = Rt -let mayStore = 1, neverHasSideEffects = 1 in def STw_GP_cPt_nv_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if ($src1) memw(##$global) = $src2.new", @@ -2876,7 +1892,6 @@ def STw_GP_cPt_nv_V4 : NVInst_V4<(outs), Requires<[HasV4T]>; // if (!Pv) memw(##global) = Rt -let mayStore = 1, neverHasSideEffects = 1 in def STw_GP_cNotPt_nv_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if (!$src1) memw(##$global) = $src2.new", @@ -2884,7 +1899,6 @@ def STw_GP_cNotPt_nv_V4 : NVInst_V4<(outs), Requires<[HasV4T]>; // if (Pv) memw(##global) = Rt -let mayStore = 1, neverHasSideEffects = 1 in def STw_GP_cdnPt_nv_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if ($src1.new) memw(##$global) = $src2.new", @@ -2892,108 +1906,12 @@ def STw_GP_cdnPt_nv_V4 : NVInst_V4<(outs), Requires<[HasV4T]>; // if (!Pv) memw(##global) = Rt -let mayStore = 1, neverHasSideEffects = 1 in def STw_GP_cdnNotPt_nv_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), "if (!$src1.new) memw(##$global) = $src2.new", []>, Requires<[HasV4T]>; - -let mayStore = 1, neverHasSideEffects = 1 in -def STrib_GP_cPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if ($src1) memb(##$global+$offset) = $src2.new", - []>, - Requires<[HasV4T]>; - -let mayStore = 1, neverHasSideEffects = 1 in -def STrib_GP_cNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if (!$src1) memb(##$global+$offset) = $src2.new", - []>, - Requires<[HasV4T]>; - -let mayStore = 1, neverHasSideEffects = 1 in -def STrib_GP_cdnPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if ($src1.new) memb(##$global+$offset) = $src2.new", - []>, - Requires<[HasV4T]>; - -let mayStore = 1, neverHasSideEffects = 1 in -def STrib_GP_cdnNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if (!$src1.new) memb(##$global+$offset) = $src2.new", - []>, - Requires<[HasV4T]>; - -let mayStore = 1, neverHasSideEffects = 1 in -def STrih_GP_cPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if ($src1) memh(##$global+$offset) = $src2.new", - []>, - Requires<[HasV4T]>; - -let mayStore = 1, neverHasSideEffects = 1 in -def STrih_GP_cNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if (!$src1) memh(##$global+$offset) = $src2.new", - []>, - Requires<[HasV4T]>; - -let mayStore = 1, neverHasSideEffects = 1 in -def STrih_GP_cdnPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if ($src1.new) memh(##$global+$offset) = $src2.new", - []>, - Requires<[HasV4T]>; - -let mayStore = 1, neverHasSideEffects = 1 in -def STrih_GP_cdnNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if (!$src1.new) memh(##$global+$offset) = $src2.new", - []>, - Requires<[HasV4T]>; - -let mayStore = 1, neverHasSideEffects = 1 in -def STriw_GP_cPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if ($src1) memw(##$global+$offset) = $src2.new", - []>, - Requires<[HasV4T]>; - -let mayStore = 1, neverHasSideEffects = 1 in -def STriw_GP_cNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if (!$src1) memw(##$global+$offset) = $src2.new", - []>, - Requires<[HasV4T]>; - -let mayStore = 1, neverHasSideEffects = 1 in -def STriw_GP_cdnPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if ($src1.new) memw(##$global+$offset) = $src2.new", - []>, - Requires<[HasV4T]>; - -let mayStore = 1, neverHasSideEffects = 1 in -def STriw_GP_cdnNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, globaladdress:$global, u16Imm:$offset, - IntRegs:$src2), - "if (!$src1.new) memw(##$global+$offset) = $src2.new", - []>, - Requires<[HasV4T]>; +} //===----------------------------------------------------------------------===// // NV/ST - @@ -3183,31 +2101,37 @@ let isBranch = 1, isTerminator=1, neverHasSideEffects = 1, Defs = [PC] in { // Add and accumulate. // Rd=add(Rs,add(Ru,#s6)) +let isExtendable = 1, opExtendable = 3, isExtentSigned = 1, opExtentBits = 6, +validSubTargets = HasV4SubT in def ADDr_ADDri_V4 : MInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, s6Imm:$src3), + (ins IntRegs:$src1, IntRegs:$src2, s6Ext:$src3), "$dst = add($src1, add($src2, #$src3))", [(set (i32 IntRegs:$dst), (add (i32 IntRegs:$src1), (add (i32 IntRegs:$src2), - s6ImmPred:$src3)))]>, + s6_16ExtPred:$src3)))]>, Requires<[HasV4T]>; // Rd=add(Rs,sub(#s6,Ru)) +let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 6, +validSubTargets = HasV4SubT in def ADDr_SUBri_V4 : MInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, s6Imm:$src2, IntRegs:$src3), + (ins IntRegs:$src1, s6Ext:$src2, IntRegs:$src3), "$dst = add($src1, sub(#$src2, $src3))", [(set (i32 IntRegs:$dst), - (add (i32 IntRegs:$src1), (sub s6ImmPred:$src2, + (add (i32 IntRegs:$src1), (sub s6_10ExtPred:$src2, (i32 IntRegs:$src3))))]>, Requires<[HasV4T]>; // Generates the same instruction as ADDr_SUBri_V4 but matches different // pattern. // Rd=add(Rs,sub(#s6,Ru)) +let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 6, +validSubTargets = HasV4SubT in def ADDri_SUBr_V4 : MInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, s6Imm:$src2, IntRegs:$src3), + (ins IntRegs:$src1, s6Ext:$src2, IntRegs:$src3), "$dst = add($src1, sub(#$src2, $src3))", [(set (i32 IntRegs:$dst), - (sub (add (i32 IntRegs:$src1), s6ImmPred:$src2), + (sub (add (i32 IntRegs:$src1), s6_10ExtPred:$src2), (i32 IntRegs:$src3)))]>, Requires<[HasV4T]>; @@ -3221,6 +2145,7 @@ def ADDri_SUBr_V4 : MInst<(outs IntRegs:$dst), // Logical doublewords. // Rdd=and(Rtt,~Rss) +let validSubTargets = HasV4SubT in def ANDd_NOTd_V4 : MInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2), "$dst = and($src1, ~$src2)", @@ -3229,6 +2154,7 @@ def ANDd_NOTd_V4 : MInst<(outs DoubleRegs:$dst), Requires<[HasV4T]>; // Rdd=or(Rtt,~Rss) +let validSubTargets = HasV4SubT in def ORd_NOTd_V4 : MInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2), "$dst = or($src1, ~$src2)", @@ -3239,6 +2165,7 @@ def ORd_NOTd_V4 : MInst<(outs DoubleRegs:$dst), // Logical-logical doublewords. // Rxx^=xor(Rss,Rtt) +let validSubTargets = HasV4SubT in def XORd_XORdd: MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2, DoubleRegs:$src3), "$dst ^= xor($src2, $src3)", @@ -3251,17 +2178,20 @@ def XORd_XORdd: MInst_acc<(outs DoubleRegs:$dst), // Logical-logical words. // Rx=or(Ru,and(Rx,#s10)) +let isExtendable = 1, opExtendable = 3, isExtentSigned = 1, opExtentBits = 10, +validSubTargets = HasV4SubT in def ORr_ANDri_V4 : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs: $src2, s10Imm:$src3), + (ins IntRegs:$src1, IntRegs: $src2, s10Ext:$src3), "$dst = or($src1, and($src2, #$src3))", [(set (i32 IntRegs:$dst), (or (i32 IntRegs:$src1), (and (i32 IntRegs:$src2), - s10ImmPred:$src3)))], + s10ExtPred:$src3)))], "$src2 = $dst">, Requires<[HasV4T]>; // Rx[&|^]=and(Rs,Rt) // Rx&=and(Rs,Rt) +let validSubTargets = HasV4SubT in def ANDr_ANDrr_V4 : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), "$dst &= and($src2, $src3)", @@ -3272,6 +2202,7 @@ def ANDr_ANDrr_V4 : MInst_acc<(outs IntRegs:$dst), Requires<[HasV4T]>; // Rx|=and(Rs,Rt) +let validSubTargets = HasV4SubT, CextOpcode = "ORr_ANDr", InputType = "reg" in def ORr_ANDrr_V4 : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), "$dst |= and($src2, $src3)", @@ -3279,9 +2210,10 @@ def ORr_ANDrr_V4 : MInst_acc<(outs IntRegs:$dst), (or (i32 IntRegs:$src1), (and (i32 IntRegs:$src2), (i32 IntRegs:$src3))))], "$src1 = $dst">, - Requires<[HasV4T]>; + Requires<[HasV4T]>, ImmRegRel; // Rx^=and(Rs,Rt) +let validSubTargets = HasV4SubT in def XORr_ANDrr_V4 : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), "$dst ^= and($src2, $src3)", @@ -3293,6 +2225,7 @@ def XORr_ANDrr_V4 : MInst_acc<(outs IntRegs:$dst), // Rx[&|^]=and(Rs,~Rt) // Rx&=and(Rs,~Rt) +let validSubTargets = HasV4SubT in def ANDr_ANDr_NOTr_V4 : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), "$dst &= and($src2, ~$src3)", @@ -3303,6 +2236,7 @@ def ANDr_ANDr_NOTr_V4 : MInst_acc<(outs IntRegs:$dst), Requires<[HasV4T]>; // Rx|=and(Rs,~Rt) +let validSubTargets = HasV4SubT in def ORr_ANDr_NOTr_V4 : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), "$dst |= and($src2, ~$src3)", @@ -3313,6 +2247,7 @@ def ORr_ANDr_NOTr_V4 : MInst_acc<(outs IntRegs:$dst), Requires<[HasV4T]>; // Rx^=and(Rs,~Rt) +let validSubTargets = HasV4SubT in def XORr_ANDr_NOTr_V4 : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), "$dst ^= and($src2, ~$src3)", @@ -3324,6 +2259,7 @@ def XORr_ANDr_NOTr_V4 : MInst_acc<(outs IntRegs:$dst), // Rx[&|^]=or(Rs,Rt) // Rx&=or(Rs,Rt) +let validSubTargets = HasV4SubT in def ANDr_ORrr_V4 : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), "$dst &= or($src2, $src3)", @@ -3334,6 +2270,7 @@ def ANDr_ORrr_V4 : MInst_acc<(outs IntRegs:$dst), Requires<[HasV4T]>; // Rx|=or(Rs,Rt) +let validSubTargets = HasV4SubT, CextOpcode = "ORr_ORr", InputType = "reg" in def ORr_ORrr_V4 : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), "$dst |= or($src2, $src3)", @@ -3341,9 +2278,10 @@ def ORr_ORrr_V4 : MInst_acc<(outs IntRegs:$dst), (or (i32 IntRegs:$src1), (or (i32 IntRegs:$src2), (i32 IntRegs:$src3))))], "$src1 = $dst">, - Requires<[HasV4T]>; + Requires<[HasV4T]>, ImmRegRel; // Rx^=or(Rs,Rt) +let validSubTargets = HasV4SubT in def XORr_ORrr_V4 : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), "$dst ^= or($src2, $src3)", @@ -3355,6 +2293,7 @@ def XORr_ORrr_V4 : MInst_acc<(outs IntRegs:$dst), // Rx[&|^]=xor(Rs,Rt) // Rx&=xor(Rs,Rt) +let validSubTargets = HasV4SubT in def ANDr_XORrr_V4 : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), "$dst &= xor($src2, $src3)", @@ -3365,6 +2304,7 @@ def ANDr_XORrr_V4 : MInst_acc<(outs IntRegs:$dst), Requires<[HasV4T]>; // Rx|=xor(Rs,Rt) +let validSubTargets = HasV4SubT in def ORr_XORrr_V4 : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), "$dst |= xor($src2, $src3)", @@ -3375,6 +2315,7 @@ def ORr_XORrr_V4 : MInst_acc<(outs IntRegs:$dst), Requires<[HasV4T]>; // Rx^=xor(Rs,Rt) +let validSubTargets = HasV4SubT in def XORr_XORrr_V4 : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), "$dst ^= xor($src2, $src3)", @@ -3385,24 +2326,28 @@ def XORr_XORrr_V4 : MInst_acc<(outs IntRegs:$dst), Requires<[HasV4T]>; // Rx|=and(Rs,#s10) +let isExtendable = 1, opExtendable = 3, isExtentSigned = 1, opExtentBits = 10, +validSubTargets = HasV4SubT, CextOpcode = "ORr_ANDr", InputType = "imm" in def ORr_ANDri2_V4 : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs: $src2, s10Imm:$src3), + (ins IntRegs:$src1, IntRegs: $src2, s10Ext:$src3), "$dst |= and($src2, #$src3)", [(set (i32 IntRegs:$dst), (or (i32 IntRegs:$src1), (and (i32 IntRegs:$src2), - s10ImmPred:$src3)))], + s10ExtPred:$src3)))], "$src1 = $dst">, - Requires<[HasV4T]>; + Requires<[HasV4T]>, ImmRegRel; // Rx|=or(Rs,#s10) +let isExtendable = 1, opExtendable = 3, isExtentSigned = 1, opExtentBits = 10, +validSubTargets = HasV4SubT, CextOpcode = "ORr_ORr", InputType = "imm" in def ORr_ORri_V4 : MInst_acc<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs: $src2, s10Imm:$src3), + (ins IntRegs:$src1, IntRegs: $src2, s10Ext:$src3), "$dst |= or($src2, #$src3)", [(set (i32 IntRegs:$dst), (or (i32 IntRegs:$src1), (and (i32 IntRegs:$src2), - s10ImmPred:$src3)))], + s10ExtPred:$src3)))], "$src1 = $dst">, - Requires<[HasV4T]>; + Requires<[HasV4T]>, ImmRegRel; // Modulo wrap @@ -3449,25 +2394,41 @@ def ORr_ORri_V4 : MInst_acc<(outs IntRegs:$dst), // Multiply and user lower result. // Rd=add(#u6,mpyi(Rs,#U6)) +let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 6, +validSubTargets = HasV4SubT in def ADDi_MPYri_V4 : MInst<(outs IntRegs:$dst), - (ins u6Imm:$src1, IntRegs:$src2, u6Imm:$src3), + (ins u6Ext:$src1, IntRegs:$src2, u6Imm:$src3), "$dst = add(#$src1, mpyi($src2, #$src3))", [(set (i32 IntRegs:$dst), (add (mul (i32 IntRegs:$src2), u6ImmPred:$src3), - u6ImmPred:$src1))]>, + u6ExtPred:$src1))]>, Requires<[HasV4T]>; -// Rd=add(#u6,mpyi(Rs,Rt)) +// Rd=add(##,mpyi(Rs,#U6)) +def : Pat <(add (mul (i32 IntRegs:$src2), u6ImmPred:$src3), + (HexagonCONST32 tglobaladdr:$src1)), + (i32 (ADDi_MPYri_V4 tglobaladdr:$src1, IntRegs:$src2, + u6ImmPred:$src3))>; +// Rd=add(#u6,mpyi(Rs,Rt)) +let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 6, +validSubTargets = HasV4SubT, InputType = "imm", CextOpcode = "ADD_MPY" in def ADDi_MPYrr_V4 : MInst<(outs IntRegs:$dst), - (ins u6Imm:$src1, IntRegs:$src2, IntRegs:$src3), + (ins u6Ext:$src1, IntRegs:$src2, IntRegs:$src3), "$dst = add(#$src1, mpyi($src2, $src3))", [(set (i32 IntRegs:$dst), (add (mul (i32 IntRegs:$src2), (i32 IntRegs:$src3)), - u6ImmPred:$src1))]>, - Requires<[HasV4T]>; + u6ExtPred:$src1))]>, + Requires<[HasV4T]>, ImmRegRel; + +// Rd=add(##,mpyi(Rs,Rt)) +def : Pat <(add (mul (i32 IntRegs:$src2), (i32 IntRegs:$src3)), + (HexagonCONST32 tglobaladdr:$src1)), + (i32 (ADDi_MPYrr_V4 tglobaladdr:$src1, IntRegs:$src2, + IntRegs:$src3))>; // Rd=add(Ru,mpyi(#u6:2,Rs)) +let validSubTargets = HasV4SubT in def ADDr_MPYir_V4 : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u6Imm:$src2, IntRegs:$src3), "$dst = add($src1, mpyi(#$src2, $src3))", @@ -3477,15 +2438,18 @@ def ADDr_MPYir_V4 : MInst<(outs IntRegs:$dst), Requires<[HasV4T]>; // Rd=add(Ru,mpyi(Rs,#u6)) +let isExtendable = 1, opExtendable = 3, isExtentSigned = 0, opExtentBits = 6, +validSubTargets = HasV4SubT, InputType = "imm", CextOpcode = "ADD_MPY" in def ADDr_MPYri_V4 : MInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, u6Imm:$src3), + (ins IntRegs:$src1, IntRegs:$src2, u6Ext:$src3), "$dst = add($src1, mpyi($src2, #$src3))", [(set (i32 IntRegs:$dst), (add (i32 IntRegs:$src1), (mul (i32 IntRegs:$src2), - u6ImmPred:$src3)))]>, - Requires<[HasV4T]>; + u6ExtPred:$src3)))]>, + Requires<[HasV4T]>, ImmRegRel; // Rx=add(Ru,mpyi(Rx,Rs)) +let validSubTargets = HasV4SubT, InputType = "reg", CextOpcode = "ADD_MPY" in def ADDr_MPYrr_V4 : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2, IntRegs:$src3), "$dst = add($src1, mpyi($src2, $src3))", @@ -3493,7 +2457,7 @@ def ADDr_MPYrr_V4 : MInst_acc<(outs IntRegs:$dst), (add (i32 IntRegs:$src1), (mul (i32 IntRegs:$src2), (i32 IntRegs:$src3))))], "$src2 = $dst">, - Requires<[HasV4T]>; + Requires<[HasV4T]>, ImmRegRel; // Polynomial multiply words @@ -3536,92 +2500,107 @@ def ADDr_MPYrr_V4 : MInst_acc<(outs IntRegs:$dst), // Shift by immediate and accumulate. // Rx=add(#u8,asl(Rx,#U5)) +let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8, +validSubTargets = HasV4SubT in def ADDi_ASLri_V4 : MInst_acc<(outs IntRegs:$dst), - (ins u8Imm:$src1, IntRegs:$src2, u5Imm:$src3), + (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3), "$dst = add(#$src1, asl($src2, #$src3))", [(set (i32 IntRegs:$dst), (add (shl (i32 IntRegs:$src2), u5ImmPred:$src3), - u8ImmPred:$src1))], + u8ExtPred:$src1))], "$src2 = $dst">, Requires<[HasV4T]>; // Rx=add(#u8,lsr(Rx,#U5)) +let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8, +validSubTargets = HasV4SubT in def ADDi_LSRri_V4 : MInst_acc<(outs IntRegs:$dst), - (ins u8Imm:$src1, IntRegs:$src2, u5Imm:$src3), + (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3), "$dst = add(#$src1, lsr($src2, #$src3))", [(set (i32 IntRegs:$dst), (add (srl (i32 IntRegs:$src2), u5ImmPred:$src3), - u8ImmPred:$src1))], + u8ExtPred:$src1))], "$src2 = $dst">, Requires<[HasV4T]>; // Rx=sub(#u8,asl(Rx,#U5)) +let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8, +validSubTargets = HasV4SubT in def SUBi_ASLri_V4 : MInst_acc<(outs IntRegs:$dst), - (ins u8Imm:$src1, IntRegs:$src2, u5Imm:$src3), + (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3), "$dst = sub(#$src1, asl($src2, #$src3))", [(set (i32 IntRegs:$dst), (sub (shl (i32 IntRegs:$src2), u5ImmPred:$src3), - u8ImmPred:$src1))], + u8ExtPred:$src1))], "$src2 = $dst">, Requires<[HasV4T]>; // Rx=sub(#u8,lsr(Rx,#U5)) +let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8, +validSubTargets = HasV4SubT in def SUBi_LSRri_V4 : MInst_acc<(outs IntRegs:$dst), - (ins u8Imm:$src1, IntRegs:$src2, u5Imm:$src3), + (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3), "$dst = sub(#$src1, lsr($src2, #$src3))", [(set (i32 IntRegs:$dst), (sub (srl (i32 IntRegs:$src2), u5ImmPred:$src3), - u8ImmPred:$src1))], + u8ExtPred:$src1))], "$src2 = $dst">, Requires<[HasV4T]>; //Shift by immediate and logical. //Rx=and(#u8,asl(Rx,#U5)) +let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8, +validSubTargets = HasV4SubT in def ANDi_ASLri_V4 : MInst_acc<(outs IntRegs:$dst), - (ins u8Imm:$src1, IntRegs:$src2, u5Imm:$src3), + (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3), "$dst = and(#$src1, asl($src2, #$src3))", [(set (i32 IntRegs:$dst), (and (shl (i32 IntRegs:$src2), u5ImmPred:$src3), - u8ImmPred:$src1))], + u8ExtPred:$src1))], "$src2 = $dst">, Requires<[HasV4T]>; //Rx=and(#u8,lsr(Rx,#U5)) +let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8, +validSubTargets = HasV4SubT in def ANDi_LSRri_V4 : MInst_acc<(outs IntRegs:$dst), - (ins u8Imm:$src1, IntRegs:$src2, u5Imm:$src3), + (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3), "$dst = and(#$src1, lsr($src2, #$src3))", [(set (i32 IntRegs:$dst), (and (srl (i32 IntRegs:$src2), u5ImmPred:$src3), - u8ImmPred:$src1))], + u8ExtPred:$src1))], "$src2 = $dst">, Requires<[HasV4T]>; //Rx=or(#u8,asl(Rx,#U5)) -let AddedComplexity = 30 in +let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8, +AddedComplexity = 30, validSubTargets = HasV4SubT in def ORi_ASLri_V4 : MInst_acc<(outs IntRegs:$dst), - (ins u8Imm:$src1, IntRegs:$src2, u5Imm:$src3), + (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3), "$dst = or(#$src1, asl($src2, #$src3))", [(set (i32 IntRegs:$dst), (or (shl (i32 IntRegs:$src2), u5ImmPred:$src3), - u8ImmPred:$src1))], + u8ExtPred:$src1))], "$src2 = $dst">, Requires<[HasV4T]>; //Rx=or(#u8,lsr(Rx,#U5)) -let AddedComplexity = 30 in +let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, opExtentBits = 8, +AddedComplexity = 30, validSubTargets = HasV4SubT in def ORi_LSRri_V4 : MInst_acc<(outs IntRegs:$dst), - (ins u8Imm:$src1, IntRegs:$src2, u5Imm:$src3), + (ins u8Ext:$src1, IntRegs:$src2, u5Imm:$src3), "$dst = or(#$src1, lsr($src2, #$src3))", [(set (i32 IntRegs:$dst), (or (srl (i32 IntRegs:$src2), u5ImmPred:$src3), - u8ImmPred:$src1))], + u8ExtPred:$src1))], "$src2 = $dst">, Requires<[HasV4T]>; //Shift by register. //Rd=lsl(#s6,Rt) +let validSubTargets = HasV4SubT in { def LSLi_V4 : MInst<(outs IntRegs:$dst), (ins s6Imm:$src1, IntRegs:$src2), "$dst = lsl(#$src1, $src2)", [(set (i32 IntRegs:$dst), (shl s6ImmPred:$src1, @@ -3669,7 +2648,7 @@ def LSRd_rr_xor_V4 : MInst_acc<(outs DoubleRegs:$dst), (i32 IntRegs:$src3))))], "$src1 = $dst">, Requires<[HasV4T]>; - +} //===----------------------------------------------------------------------===// // XTYPE/SHIFT - @@ -4103,7 +3082,61 @@ def MEMb_ORr_MEM_V4 : MEMInst_V4<(outs), // incorrect code for negative numbers. // Pd=cmpb.eq(Rs,#u8) -let isCompare = 1 in +// p=!cmp.eq(r1,r2) +let isCompare = 1, validSubTargets = HasV4SubT in +def CMPnotEQ_rr : ALU32_rr<(outs PredRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst = !cmp.eq($src1, $src2)", + [(set (i1 PredRegs:$dst), + (setne (i32 IntRegs:$src1), (i32 IntRegs:$src2)))]>, + Requires<[HasV4T]>; + +// p=!cmp.eq(r1,#s10) +let isCompare = 1, validSubTargets = HasV4SubT in +def CMPnotEQ_ri : ALU32_ri<(outs PredRegs:$dst), + (ins IntRegs:$src1, s10Ext:$src2), + "$dst = !cmp.eq($src1, #$src2)", + [(set (i1 PredRegs:$dst), + (setne (i32 IntRegs:$src1), s10ImmPred:$src2))]>, + Requires<[HasV4T]>; + +// p=!cmp.gt(r1,r2) +let isCompare = 1, validSubTargets = HasV4SubT in +def CMPnotGT_rr : ALU32_rr<(outs PredRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst = !cmp.gt($src1, $src2)", + [(set (i1 PredRegs:$dst), + (not (setgt (i32 IntRegs:$src1), (i32 IntRegs:$src2))))]>, + Requires<[HasV4T]>; + +// p=!cmp.gt(r1,#s10) +let isCompare = 1, validSubTargets = HasV4SubT in +def CMPnotGT_ri : ALU32_ri<(outs PredRegs:$dst), + (ins IntRegs:$src1, s10Ext:$src2), + "$dst = !cmp.gt($src1, #$src2)", + [(set (i1 PredRegs:$dst), + (not (setgt (i32 IntRegs:$src1), s10ImmPred:$src2)))]>, + Requires<[HasV4T]>; + +// p=!cmp.gtu(r1,r2) +let isCompare = 1, validSubTargets = HasV4SubT in +def CMPnotGTU_rr : ALU32_rr<(outs PredRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst = !cmp.gtu($src1, $src2)", + [(set (i1 PredRegs:$dst), + (not (setugt (i32 IntRegs:$src1), (i32 IntRegs:$src2))))]>, + Requires<[HasV4T]>; + +// p=!cmp.gtu(r1,#u9) +let isCompare = 1, validSubTargets = HasV4SubT in +def CMPnotGTU_ri : ALU32_ri<(outs PredRegs:$dst), + (ins IntRegs:$src1, u9Ext:$src2), + "$dst = !cmp.gtu($src1, #$src2)", + [(set (i1 PredRegs:$dst), + (not (setugt (i32 IntRegs:$src1), u9ImmPred:$src2)))]>, + Requires<[HasV4T]>; + +let isCompare = 1, validSubTargets = HasV4SubT in def CMPbEQri_V4 : MInst<(outs PredRegs:$dst), (ins IntRegs:$src1, u8Imm:$src2), "$dst = cmpb.eq($src1, #$src2)", @@ -4111,8 +3144,14 @@ def CMPbEQri_V4 : MInst<(outs PredRegs:$dst), (seteq (and (i32 IntRegs:$src1), 255), u8ImmPred:$src2))]>, Requires<[HasV4T]>; +def : Pat <(brcond (i1 (setne (and (i32 IntRegs:$src1), 255), u8ImmPred:$src2)), + bb:$offset), + (JMP_cNot (CMPbEQri_V4 (i32 IntRegs:$src1), u8ImmPred:$src2), + bb:$offset)>, + Requires<[HasV4T]>; + // Pd=cmpb.eq(Rs,Rt) -let isCompare = 1 in +let isCompare = 1, validSubTargets = HasV4SubT in def CMPbEQrr_ubub_V4 : MInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), "$dst = cmpb.eq($src1, $src2)", @@ -4122,7 +3161,7 @@ def CMPbEQrr_ubub_V4 : MInst<(outs PredRegs:$dst), Requires<[HasV4T]>; // Pd=cmpb.eq(Rs,Rt) -let isCompare = 1 in +let isCompare = 1, validSubTargets = HasV4SubT in def CMPbEQrr_sbsb_V4 : MInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), "$dst = cmpb.eq($src1, $src2)", @@ -4132,7 +3171,7 @@ def CMPbEQrr_sbsb_V4 : MInst<(outs PredRegs:$dst), Requires<[HasV4T]>; // Pd=cmpb.gt(Rs,Rt) -let isCompare = 1 in +let isCompare = 1, validSubTargets = HasV4SubT in def CMPbGTrr_V4 : MInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), "$dst = cmpb.gt($src1, $src2)", @@ -4142,29 +3181,237 @@ def CMPbGTrr_V4 : MInst<(outs PredRegs:$dst), Requires<[HasV4T]>; // Pd=cmpb.gtu(Rs,#u7) -let isCompare = 1 in +let isExtendable = 1, opExtendable = 2, isExtentSigned = 0, opExtentBits = 7, +isCompare = 1, validSubTargets = HasV4SubT, CextOpcode = "CMPbGTU", InputType = "imm" in def CMPbGTUri_V4 : MInst<(outs PredRegs:$dst), - (ins IntRegs:$src1, u7Imm:$src2), + (ins IntRegs:$src1, u7Ext:$src2), "$dst = cmpb.gtu($src1, #$src2)", [(set (i1 PredRegs:$dst), (setugt (and (i32 IntRegs:$src1), 255), - u7ImmPred:$src2))]>, - Requires<[HasV4T]>; + u7ExtPred:$src2))]>, + Requires<[HasV4T]>, ImmRegRel; + +// SDNode for converting immediate C to C-1. +def DEC_CONST_BYTE : SDNodeXForm<imm, [{ + // Return the byte immediate const-1 as an SDNode. + int32_t imm = N->getSExtValue(); + return XformU7ToU7M1Imm(imm); +}]>; + +// For the sequence +// zext( seteq ( and(Rs, 255), u8)) +// Generate +// Pd=cmpb.eq(Rs, #u8) +// if (Pd.new) Rd=#1 +// if (!Pd.new) Rd=#0 +def : Pat <(i32 (zext (i1 (seteq (i32 (and (i32 IntRegs:$Rs), 255)), + u8ExtPred:$u8)))), + (i32 (TFR_condset_ii (i1 (CMPbEQri_V4 (i32 IntRegs:$Rs), + (u8ExtPred:$u8))), + 1, 0))>, + Requires<[HasV4T]>; + +// For the sequence +// zext( setne ( and(Rs, 255), u8)) +// Generate +// Pd=cmpb.eq(Rs, #u8) +// if (Pd.new) Rd=#0 +// if (!Pd.new) Rd=#1 +def : Pat <(i32 (zext (i1 (setne (i32 (and (i32 IntRegs:$Rs), 255)), + u8ExtPred:$u8)))), + (i32 (TFR_condset_ii (i1 (CMPbEQri_V4 (i32 IntRegs:$Rs), + (u8ExtPred:$u8))), + 0, 1))>, + Requires<[HasV4T]>; + +// For the sequence +// zext( seteq (Rs, and(Rt, 255))) +// Generate +// Pd=cmpb.eq(Rs, Rt) +// if (Pd.new) Rd=#1 +// if (!Pd.new) Rd=#0 +def : Pat <(i32 (zext (i1 (seteq (i32 IntRegs:$Rt), + (i32 (and (i32 IntRegs:$Rs), 255)))))), + (i32 (TFR_condset_ii (i1 (CMPbEQrr_ubub_V4 (i32 IntRegs:$Rs), + (i32 IntRegs:$Rt))), + 1, 0))>, + Requires<[HasV4T]>; + +// For the sequence +// zext( setne (Rs, and(Rt, 255))) +// Generate +// Pd=cmpb.eq(Rs, Rt) +// if (Pd.new) Rd=#0 +// if (!Pd.new) Rd=#1 +def : Pat <(i32 (zext (i1 (setne (i32 IntRegs:$Rt), + (i32 (and (i32 IntRegs:$Rs), 255)))))), + (i32 (TFR_condset_ii (i1 (CMPbEQrr_ubub_V4 (i32 IntRegs:$Rs), + (i32 IntRegs:$Rt))), + 0, 1))>, + Requires<[HasV4T]>; + +// For the sequence +// zext( setugt ( and(Rs, 255), u8)) +// Generate +// Pd=cmpb.gtu(Rs, #u8) +// if (Pd.new) Rd=#1 +// if (!Pd.new) Rd=#0 +def : Pat <(i32 (zext (i1 (setugt (i32 (and (i32 IntRegs:$Rs), 255)), + u8ExtPred:$u8)))), + (i32 (TFR_condset_ii (i1 (CMPbGTUri_V4 (i32 IntRegs:$Rs), + (u8ExtPred:$u8))), + 1, 0))>, + Requires<[HasV4T]>; + +// For the sequence +// zext( setugt ( and(Rs, 254), u8)) +// Generate +// Pd=cmpb.gtu(Rs, #u8) +// if (Pd.new) Rd=#1 +// if (!Pd.new) Rd=#0 +def : Pat <(i32 (zext (i1 (setugt (i32 (and (i32 IntRegs:$Rs), 254)), + u8ExtPred:$u8)))), + (i32 (TFR_condset_ii (i1 (CMPbGTUri_V4 (i32 IntRegs:$Rs), + (u8ExtPred:$u8))), + 1, 0))>, + Requires<[HasV4T]>; + +// For the sequence +// zext( setult ( Rs, Rt)) +// Generate +// Pd=cmp.ltu(Rs, Rt) +// if (Pd.new) Rd=#1 +// if (!Pd.new) Rd=#0 +// cmp.ltu(Rs, Rt) -> cmp.gtu(Rt, Rs) +def : Pat <(i32 (zext (i1 (setult (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))), + (i32 (TFR_condset_ii (i1 (CMPGTUrr (i32 IntRegs:$Rt), + (i32 IntRegs:$Rs))), + 1, 0))>, + Requires<[HasV4T]>; + +// For the sequence +// zext( setlt ( Rs, Rt)) +// Generate +// Pd=cmp.lt(Rs, Rt) +// if (Pd.new) Rd=#1 +// if (!Pd.new) Rd=#0 +// cmp.lt(Rs, Rt) -> cmp.gt(Rt, Rs) +def : Pat <(i32 (zext (i1 (setlt (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))), + (i32 (TFR_condset_ii (i1 (CMPGTrr (i32 IntRegs:$Rt), + (i32 IntRegs:$Rs))), + 1, 0))>, + Requires<[HasV4T]>; + +// For the sequence +// zext( setugt ( Rs, Rt)) +// Generate +// Pd=cmp.gtu(Rs, Rt) +// if (Pd.new) Rd=#1 +// if (!Pd.new) Rd=#0 +def : Pat <(i32 (zext (i1 (setugt (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))), + (i32 (TFR_condset_ii (i1 (CMPGTUrr (i32 IntRegs:$Rs), + (i32 IntRegs:$Rt))), + 1, 0))>, + Requires<[HasV4T]>; + +// This pattern interefers with coremark performance, not implementing at this +// time. +// For the sequence +// zext( setgt ( Rs, Rt)) +// Generate +// Pd=cmp.gt(Rs, Rt) +// if (Pd.new) Rd=#1 +// if (!Pd.new) Rd=#0 + +// For the sequence +// zext( setuge ( Rs, Rt)) +// Generate +// Pd=cmp.ltu(Rs, Rt) +// if (Pd.new) Rd=#0 +// if (!Pd.new) Rd=#1 +// cmp.ltu(Rs, Rt) -> cmp.gtu(Rt, Rs) +def : Pat <(i32 (zext (i1 (setuge (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))), + (i32 (TFR_condset_ii (i1 (CMPGTUrr (i32 IntRegs:$Rt), + (i32 IntRegs:$Rs))), + 0, 1))>, + Requires<[HasV4T]>; + +// For the sequence +// zext( setge ( Rs, Rt)) +// Generate +// Pd=cmp.lt(Rs, Rt) +// if (Pd.new) Rd=#0 +// if (!Pd.new) Rd=#1 +// cmp.lt(Rs, Rt) -> cmp.gt(Rt, Rs) +def : Pat <(i32 (zext (i1 (setge (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))), + (i32 (TFR_condset_ii (i1 (CMPGTrr (i32 IntRegs:$Rt), + (i32 IntRegs:$Rs))), + 0, 1))>, + Requires<[HasV4T]>; + +// For the sequence +// zext( setule ( Rs, Rt)) +// Generate +// Pd=cmp.gtu(Rs, Rt) +// if (Pd.new) Rd=#0 +// if (!Pd.new) Rd=#1 +def : Pat <(i32 (zext (i1 (setule (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))), + (i32 (TFR_condset_ii (i1 (CMPGTUrr (i32 IntRegs:$Rs), + (i32 IntRegs:$Rt))), + 0, 1))>, + Requires<[HasV4T]>; + +// For the sequence +// zext( setle ( Rs, Rt)) +// Generate +// Pd=cmp.gt(Rs, Rt) +// if (Pd.new) Rd=#0 +// if (!Pd.new) Rd=#1 +def : Pat <(i32 (zext (i1 (setle (i32 IntRegs:$Rs), (i32 IntRegs:$Rt))))), + (i32 (TFR_condset_ii (i1 (CMPGTrr (i32 IntRegs:$Rs), + (i32 IntRegs:$Rt))), + 0, 1))>, + Requires<[HasV4T]>; + +// For the sequence +// zext( setult ( and(Rs, 255), u8)) +// Use the isdigit transformation below + +// Generate code of the form 'mux_ii(cmpbgtu(Rdd, C-1),0,1)' +// for C code of the form r = ((c>='0') & (c<='9')) ? 1 : 0;. +// The isdigit transformation relies on two 'clever' aspects: +// 1) The data type is unsigned which allows us to eliminate a zero test after +// biasing the expression by 48. We are depending on the representation of +// the unsigned types, and semantics. +// 2) The front end has converted <= 9 into < 10 on entry to LLVM +// +// For the C code: +// retval = ((c>='0') & (c<='9')) ? 1 : 0; +// The code is transformed upstream of llvm into +// retval = (c-48) < 10 ? 1 : 0; +let AddedComplexity = 139 in +def : Pat <(i32 (zext (i1 (setult (i32 (and (i32 IntRegs:$src1), 255)), + u7StrictPosImmPred:$src2)))), + (i32 (MUX_ii (i1 (CMPbGTUri_V4 (i32 IntRegs:$src1), + (DEC_CONST_BYTE u7StrictPosImmPred:$src2))), + 0, 1))>, + Requires<[HasV4T]>; // Pd=cmpb.gtu(Rs,Rt) -let isCompare = 1 in +let isCompare = 1, validSubTargets = HasV4SubT, CextOpcode = "CMPbGTU", +InputType = "reg" in def CMPbGTUrr_V4 : MInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), "$dst = cmpb.gtu($src1, $src2)", [(set (i1 PredRegs:$dst), (setugt (and (i32 IntRegs:$src1), 255), (and (i32 IntRegs:$src2), 255)))]>, - Requires<[HasV4T]>; + Requires<[HasV4T]>, ImmRegRel; // Following instruction is not being extended as it results into the incorrect // code for negative numbers. // Signed half compare(.eq) ri. // Pd=cmph.eq(Rs,#s8) -let isCompare = 1 in +let isCompare = 1, validSubTargets = HasV4SubT in def CMPhEQri_V4 : MInst<(outs PredRegs:$dst), (ins IntRegs:$src1, s8Imm:$src2), "$dst = cmph.eq($src1, #$src2)", @@ -4178,7 +3425,7 @@ def CMPhEQri_V4 : MInst<(outs PredRegs:$dst), // r0=and(r0,#0xffff) // p0=cmp.eq(r0,#0) // Pd=cmph.eq(Rs,Rt) -let isCompare = 1 in +let isCompare = 1, validSubTargets = HasV4SubT in def CMPhEQrr_xor_V4 : MInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), "$dst = cmph.eq($src1, $src2)", @@ -4193,7 +3440,7 @@ def CMPhEQrr_xor_V4 : MInst<(outs PredRegs:$dst), // r1=asl(r1,16) // p0=cmp.eq(r0,r1) // Pd=cmph.eq(Rs,Rt) -let isCompare = 1 in +let isCompare = 1, validSubTargets = HasV4SubT in def CMPhEQrr_shl_V4 : MInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), "$dst = cmph.eq($src1, $src2)", @@ -4207,19 +3454,20 @@ used in the cmph.gt instruction. // Signed half compare(.gt) ri. // Pd=cmph.gt(Rs,#s8) -let isCompare = 1 in +let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 8, +isCompare = 1, validSubTargets = HasV4SubT in def CMPhGTri_V4 : MInst<(outs PredRegs:$dst), - (ins IntRegs:$src1, s8Imm:$src2), + (ins IntRegs:$src1, s8Ext:$src2), "$dst = cmph.gt($src1, #$src2)", [(set (i1 PredRegs:$dst), (setgt (shl (i32 IntRegs:$src1), (i32 16)), - s8ImmPred:$src2))]>, + s8ExtPred:$src2))]>, Requires<[HasV4T]>; */ // Signed half compare(.gt) rr. // Pd=cmph.gt(Rs,Rt) -let isCompare = 1 in +let isCompare = 1, validSubTargets = HasV4SubT in def CMPhGTrr_shl_V4 : MInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), "$dst = cmph.gt($src1, $src2)", @@ -4230,24 +3478,41 @@ def CMPhGTrr_shl_V4 : MInst<(outs PredRegs:$dst), // Unsigned half compare rr (.gtu). // Pd=cmph.gtu(Rs,Rt) -let isCompare = 1 in +let isCompare = 1, validSubTargets = HasV4SubT, CextOpcode = "CMPhGTU", +InputType = "reg" in def CMPhGTUrr_V4 : MInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), "$dst = cmph.gtu($src1, $src2)", [(set (i1 PredRegs:$dst), (setugt (and (i32 IntRegs:$src1), 65535), (and (i32 IntRegs:$src2), 65535)))]>, - Requires<[HasV4T]>; + Requires<[HasV4T]>, ImmRegRel; // Unsigned half compare ri (.gtu). // Pd=cmph.gtu(Rs,#u7) -let isCompare = 1 in +let isExtendable = 1, opExtendable = 2, isExtentSigned = 0, opExtentBits = 7, +isCompare = 1, validSubTargets = HasV4SubT, CextOpcode = "CMPhGTU", +InputType = "imm" in def CMPhGTUri_V4 : MInst<(outs PredRegs:$dst), - (ins IntRegs:$src1, u7Imm:$src2), + (ins IntRegs:$src1, u7Ext:$src2), "$dst = cmph.gtu($src1, #$src2)", [(set (i1 PredRegs:$dst), (setugt (and (i32 IntRegs:$src1), 65535), - u7ImmPred:$src2))]>, - Requires<[HasV4T]>; + u7ExtPred:$src2))]>, + Requires<[HasV4T]>, ImmRegRel; + +let validSubTargets = HasV4SubT in +def NTSTBIT_rr : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + "$dst = !tstbit($src1, $src2)", + [(set (i1 PredRegs:$dst), + (seteq (and (shl 1, (i32 IntRegs:$src2)), (i32 IntRegs:$src1)), 0))]>, + Requires<[HasV4T]>; + +let validSubTargets = HasV4SubT in +def NTSTBIT_ri : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), + "$dst = !tstbit($src1, $src2)", + [(set (i1 PredRegs:$dst), + (seteq (and (shl 1, u5ImmPred:$src2), (i32 IntRegs:$src1)), 0))]>, + Requires<[HasV4T]>; //===----------------------------------------------------------------------===// // XTYPE/PRED - @@ -4359,227 +3624,156 @@ let isReturn = 1, isTerminator = 1, Requires<[HasV4T]>; } - // Load/Store with absolute addressing mode // memw(#u6)=Rt -multiclass ST_abs<string OpcStr> { - let isPredicable = 1 in - def _abs_V4 : STInst2<(outs), - (ins globaladdress:$absaddr, IntRegs:$src), - !strconcat(OpcStr, "(##$absaddr) = $src"), - []>, - Requires<[HasV4T]>; - - let isPredicated = 1 in - def _abs_cPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$absaddr, IntRegs:$src2), - !strconcat("if ($src1)", - !strconcat(OpcStr, "(##$absaddr) = $src2")), - []>, - Requires<[HasV4T]>; - - let isPredicated = 1 in - def _abs_cNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$absaddr, IntRegs:$src2), - !strconcat("if (!$src1)", - !strconcat(OpcStr, "(##$absaddr) = $src2")), +multiclass ST_Abs_Predbase<string mnemonic, RegisterClass RC, bit isNot, + bit isPredNew> { + let PNewValue = !if(isPredNew, "new", "") in + def NAME#_V4 : STInst2<(outs), + (ins PredRegs:$src1, globaladdressExt:$absaddr, RC: $src2), + !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + ") ")#mnemonic#"(##$absaddr) = $src2", []>, Requires<[HasV4T]>; +} - let isPredicated = 1 in - def _abs_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$absaddr, IntRegs:$src2), - !strconcat("if ($src1.new)", - !strconcat(OpcStr, "(##$absaddr) = $src2")), - []>, - Requires<[HasV4T]>; +multiclass ST_Abs_Pred<string mnemonic, RegisterClass RC, bit PredNot> { + let PredSense = !if(PredNot, "false", "true") in { + defm _c#NAME : ST_Abs_Predbase<mnemonic, RC, PredNot, 0>; + // Predicate new + defm _cdn#NAME : ST_Abs_Predbase<mnemonic, RC, PredNot, 1>; + } +} - let isPredicated = 1 in - def _abs_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$absaddr, IntRegs:$src2), - !strconcat("if (!$src1.new)", - !strconcat(OpcStr, "(##$absaddr) = $src2")), +let isNVStorable = 1, isExtended = 1, neverHasSideEffects = 1 in +multiclass ST_Abs<string mnemonic, string CextOp, RegisterClass RC> { + let CextOpcode = CextOp, BaseOpcode = CextOp#_abs in { + let opExtendable = 0, isPredicable = 1 in + def NAME#_V4 : STInst2<(outs), + (ins globaladdressExt:$absaddr, RC:$src), + mnemonic#"(##$absaddr) = $src", []>, Requires<[HasV4T]>; - def _abs_nv_V4 : STInst2<(outs), - (ins globaladdress:$absaddr, IntRegs:$src), - !strconcat(OpcStr, "(##$absaddr) = $src.new"), - []>, - Requires<[HasV4T]>; + let opExtendable = 1, isPredicated = 1 in { + defm Pt : ST_Abs_Pred<mnemonic, RC, 0>; + defm NotPt : ST_Abs_Pred<mnemonic, RC, 1>; + } + } +} - let isPredicated = 1 in - def _abs_cPt_nv_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$absaddr, IntRegs:$src2), - !strconcat("if ($src1)", - !strconcat(OpcStr, "(##$absaddr) = $src2.new")), +multiclass ST_Abs_Predbase_nv<string mnemonic, RegisterClass RC, bit isNot, + bit isPredNew> { + let PNewValue = !if(isPredNew, "new", "") in + def NAME#_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, globaladdressExt:$absaddr, RC: $src2), + !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + ") ")#mnemonic#"(##$absaddr) = $src2.new", []>, Requires<[HasV4T]>; +} - let isPredicated = 1 in - def _abs_cNotPt_nv_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$absaddr, IntRegs:$src2), - !strconcat("if (!$src1)", - !strconcat(OpcStr, "(##$absaddr) = $src2.new")), - []>, - Requires<[HasV4T]>; +multiclass ST_Abs_Pred_nv<string mnemonic, RegisterClass RC, bit PredNot> { + let PredSense = !if(PredNot, "false", "true") in { + defm _c#NAME : ST_Abs_Predbase_nv<mnemonic, RC, PredNot, 0>; + // Predicate new + defm _cdn#NAME : ST_Abs_Predbase_nv<mnemonic, RC, PredNot, 1>; + } +} - let isPredicated = 1 in - def _abs_cdnPt_nv_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$absaddr, IntRegs:$src2), - !strconcat("if ($src1.new)", - !strconcat(OpcStr, "(##$absaddr) = $src2.new")), +let mayStore = 1, isNVStore = 1, isExtended = 1, neverHasSideEffects = 1 in +multiclass ST_Abs_nv<string mnemonic, string CextOp, RegisterClass RC> { + let CextOpcode = CextOp, BaseOpcode = CextOp#_abs in { + let opExtendable = 0, isPredicable = 1 in + def NAME#_nv_V4 : NVInst_V4<(outs), + (ins globaladdressExt:$absaddr, RC:$src), + mnemonic#"(##$absaddr) = $src.new", []>, Requires<[HasV4T]>; - let isPredicated = 1 in - def _abs_cdnNotPt_nv_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$absaddr, IntRegs:$src2), - !strconcat("if (!$src1.new)", - !strconcat(OpcStr, "(##$absaddr) = $src2.new")), - []>, - Requires<[HasV4T]>; + let opExtendable = 1, isPredicated = 1 in { + defm Pt : ST_Abs_Pred_nv<mnemonic, RC, 0>; + defm NotPt : ST_Abs_Pred_nv<mnemonic, RC, 1>; + } + } } -let AddedComplexity = 30, isPredicable = 1 in -def STrid_abs_V4 : STInst<(outs), - (ins globaladdress:$absaddr, DoubleRegs:$src), - "memd(##$absaddr) = $src", - [(store (i64 DoubleRegs:$src), - (HexagonCONST32 tglobaladdr:$absaddr))]>, - Requires<[HasV4T]>; - -let AddedComplexity = 30, isPredicated = 1 in -def STrid_abs_cPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$absaddr, DoubleRegs:$src2), - "if ($src1) memd(##$absaddr) = $src2", - []>, - Requires<[HasV4T]>; - -let AddedComplexity = 30, isPredicated = 1 in -def STrid_abs_cNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$absaddr, DoubleRegs:$src2), - "if (!$src1) memd(##$absaddr) = $src2", - []>, - Requires<[HasV4T]>; +let addrMode = Absolute in { + defm STrib_abs : ST_Abs<"memb", "STrib", IntRegs>, + ST_Abs_nv<"memb", "STrib", IntRegs>, AddrModeRel; -let AddedComplexity = 30, isPredicated = 1 in -def STrid_abs_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$absaddr, DoubleRegs:$src2), - "if ($src1.new) memd(##$absaddr) = $src2", - []>, - Requires<[HasV4T]>; + defm STrih_abs : ST_Abs<"memh", "STrih", IntRegs>, + ST_Abs_nv<"memh", "STrih", IntRegs>, AddrModeRel; -let AddedComplexity = 30, isPredicated = 1 in -def STrid_abs_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$absaddr, DoubleRegs:$src2), - "if (!$src1.new) memd(##$absaddr) = $src2", - []>, - Requires<[HasV4T]>; + defm STriw_abs : ST_Abs<"memw", "STriw", IntRegs>, + ST_Abs_nv<"memw", "STriw", IntRegs>, AddrModeRel; -defm STrib : ST_abs<"memb">; -defm STrih : ST_abs<"memh">; -defm STriw : ST_abs<"memw">; + let isNVStorable = 0 in + defm STrid_abs : ST_Abs<"memd", "STrid", DoubleRegs>, AddrModeRel; +} -let Predicates = [HasV4T], AddedComplexity = 30 in +let Predicates = [HasV4T], AddedComplexity = 30 in { def : Pat<(truncstorei8 (i32 IntRegs:$src1), (HexagonCONST32 tglobaladdr:$absaddr)), (STrib_abs_V4 tglobaladdr: $absaddr, IntRegs: $src1)>; -let Predicates = [HasV4T], AddedComplexity = 30 in def : Pat<(truncstorei16 (i32 IntRegs:$src1), (HexagonCONST32 tglobaladdr:$absaddr)), (STrih_abs_V4 tglobaladdr: $absaddr, IntRegs: $src1)>; -let Predicates = [HasV4T], AddedComplexity = 30 in def : Pat<(store (i32 IntRegs:$src1), (HexagonCONST32 tglobaladdr:$absaddr)), (STriw_abs_V4 tglobaladdr: $absaddr, IntRegs: $src1)>; +def : Pat<(store (i64 DoubleRegs:$src1), + (HexagonCONST32 tglobaladdr:$absaddr)), + (STrid_abs_V4 tglobaladdr: $absaddr, DoubleRegs: $src1)>; +} -multiclass LD_abs<string OpcStr> { - let isPredicable = 1 in - def _abs_V4 : LDInst2<(outs IntRegs:$dst), - (ins globaladdress:$absaddr), - !strconcat("$dst = ", !strconcat(OpcStr, "(##$absaddr)")), - []>, - Requires<[HasV4T]>; - - let isPredicated = 1 in - def _abs_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$absaddr), - !strconcat("if ($src1) $dst = ", - !strconcat(OpcStr, "(##$absaddr)")), +multiclass LD_Abs_Predbase<string mnemonic, RegisterClass RC, bit isNot, + bit isPredNew> { + let PNewValue = !if(isPredNew, "new", "") in + def NAME : LDInst2<(outs RC:$dst), + (ins PredRegs:$src1, globaladdressExt:$absaddr), + !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + ") ")#"$dst = "#mnemonic#"(##$absaddr)", []>, Requires<[HasV4T]>; +} - let isPredicated = 1 in - def _abs_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$absaddr), - !strconcat("if (!$src1) $dst = ", - !strconcat(OpcStr, "(##$absaddr)")), - []>, - Requires<[HasV4T]>; +multiclass LD_Abs_Pred<string mnemonic, RegisterClass RC, bit PredNot> { + let PredSense = !if(PredNot, "false", "true") in { + defm _c#NAME : LD_Abs_Predbase<mnemonic, RC, PredNot, 0>; + // Predicate new + defm _cdn#NAME : LD_Abs_Predbase<mnemonic, RC, PredNot, 1>; + } +} - let isPredicated = 1 in - def _abs_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$absaddr), - !strconcat("if ($src1.new) $dst = ", - !strconcat(OpcStr, "(##$absaddr)")), +let isExtended = 1, neverHasSideEffects = 1 in +multiclass LD_Abs<string mnemonic, string CextOp, RegisterClass RC> { + let CextOpcode = CextOp, BaseOpcode = CextOp#_abs in { + let opExtendable = 1, isPredicable = 1 in + def NAME#_V4 : LDInst2<(outs RC:$dst), + (ins globaladdressExt:$absaddr), + "$dst = "#mnemonic#"(##$absaddr)", []>, Requires<[HasV4T]>; - let isPredicated = 1 in - def _abs_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$absaddr), - !strconcat("if (!$src1.new) $dst = ", - !strconcat(OpcStr, "(##$absaddr)")), - []>, - Requires<[HasV4T]>; + let opExtendable = 2, isPredicated = 1 in { + defm Pt_V4 : LD_Abs_Pred<mnemonic, RC, 0>; + defm NotPt_V4 : LD_Abs_Pred<mnemonic, RC, 1>; + } + } } -let AddedComplexity = 30 in -def LDrid_abs_V4 : LDInst<(outs DoubleRegs:$dst), - (ins globaladdress:$absaddr), - "$dst = memd(##$absaddr)", - [(set (i64 DoubleRegs:$dst), - (load (HexagonCONST32 tglobaladdr:$absaddr)))]>, - Requires<[HasV4T]>; - -let AddedComplexity = 30, isPredicated = 1 in -def LDrid_abs_cPt_V4 : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, globaladdress:$absaddr), - "if ($src1) $dst = memd(##$absaddr)", - []>, - Requires<[HasV4T]>; - -let AddedComplexity = 30, isPredicated = 1 in -def LDrid_abs_cNotPt_V4 : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, globaladdress:$absaddr), - "if (!$src1) $dst = memd(##$absaddr)", - []>, - Requires<[HasV4T]>; - -let AddedComplexity = 30, isPredicated = 1 in -def LDrid_abs_cdnPt_V4 : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, globaladdress:$absaddr), - "if ($src1.new) $dst = memd(##$absaddr)", - []>, - Requires<[HasV4T]>; - -let AddedComplexity = 30, isPredicated = 1 in -def LDrid_abs_cdnNotPt_V4 : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, globaladdress:$absaddr), - "if (!$src1.new) $dst = memd(##$absaddr)", - []>, - Requires<[HasV4T]>; - -defm LDrib : LD_abs<"memb">; -defm LDriub : LD_abs<"memub">; -defm LDrih : LD_abs<"memh">; -defm LDriuh : LD_abs<"memuh">; -defm LDriw : LD_abs<"memw">; - +let addrMode = Absolute in { + defm LDrib_abs : LD_Abs<"memb", "LDrib", IntRegs>, AddrModeRel; + defm LDriub_abs : LD_Abs<"memub", "LDriub", IntRegs>, AddrModeRel; + defm LDrih_abs : LD_Abs<"memh", "LDrih", IntRegs>, AddrModeRel; + defm LDriuh_abs : LD_Abs<"memuh", "LDriuh", IntRegs>, AddrModeRel; + defm LDriw_abs : LD_Abs<"memw", "LDriw", IntRegs>, AddrModeRel; + defm LDrid_abs : LD_Abs<"memd", "LDrid", DoubleRegs>, AddrModeRel; +} let Predicates = [HasV4T], AddedComplexity = 30 in def : Pat<(i32 (load (HexagonCONST32 tglobaladdr:$absaddr))), @@ -4608,6 +3802,11 @@ def TFRI_V4 : ALU32_ri<(outs IntRegs:$dst), (ins globaladdress:$src1), [(set IntRegs:$dst, (HexagonCONST32 tglobaladdr:$src1))]>, Requires<[HasV4T]>; +// Transfer a block address into a register +def : Pat<(HexagonCONST32_GP tblockaddress:$src1), + (TFRI_V4 tblockaddress:$src1)>, + Requires<[HasV4T]>; + let AddedComplexity=50, neverHasSideEffects = 1, isPredicated = 1 in def TFRI_cPt_V4 : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, globaladdress:$src2), @@ -4699,172 +3898,167 @@ defm STrih_ind : ST_indirect_lo<"memh", truncstorei16>; defm STriw_ind : ST_indirect_lo<"memw", store>; // Store - absolute addressing mode: These instruction take constant -// value as the extended operand +// value as the extended operand. multiclass ST_absimm<string OpcStr> { - let isPredicable = 1 in +let isExtended = 1, opExtendable = 0, isPredicable = 1, +validSubTargets = HasV4SubT in def _abs_V4 : STInst2<(outs), - (ins u6Imm:$src1, IntRegs:$src2), - !strconcat(OpcStr, "(#$src1) = $src2"), + (ins u0AlwaysExt:$src1, IntRegs:$src2), + !strconcat(OpcStr, "(##$src1) = $src2"), []>, Requires<[HasV4T]>; - let isPredicated = 1 in +let isExtended = 1, opExtendable = 1, isPredicated = 1, +validSubTargets = HasV4SubT in { def _abs_cPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, u6Imm:$src2, IntRegs:$src3), - !strconcat("if ($src1)", !strconcat(OpcStr, "(#$src2) = $src3")), + (ins PredRegs:$src1, u0AlwaysExt:$src2, IntRegs:$src3), + !strconcat("if ($src1)", !strconcat(OpcStr, "(##$src2) = $src3")), []>, Requires<[HasV4T]>; - let isPredicated = 1 in def _abs_cNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, u6Imm:$src2, IntRegs:$src3), - !strconcat("if (!$src1)", !strconcat(OpcStr, "(#$src2) = $src3")), + (ins PredRegs:$src1, u0AlwaysExt:$src2, IntRegs:$src3), + !strconcat("if (!$src1)", !strconcat(OpcStr, "(##$src2) = $src3")), []>, Requires<[HasV4T]>; - let isPredicated = 1 in def _abs_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, u6Imm:$src2, IntRegs:$src3), + (ins PredRegs:$src1, u0AlwaysExt:$src2, IntRegs:$src3), !strconcat("if ($src1.new)", - !strconcat(OpcStr, "(#$src2) = $src3")), + !strconcat(OpcStr, "(##$src2) = $src3")), []>, Requires<[HasV4T]>; - let isPredicated = 1 in def _abs_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, u6Imm:$src2, IntRegs:$src3), + (ins PredRegs:$src1, u0AlwaysExt:$src2, IntRegs:$src3), !strconcat("if (!$src1.new)", - !strconcat(OpcStr, "(#$src2) = $src3")), + !strconcat(OpcStr, "(##$src2) = $src3")), []>, Requires<[HasV4T]>; +} - def _abs_nv_V4 : STInst2<(outs), - (ins u6Imm:$src1, IntRegs:$src2), - !strconcat(OpcStr, "(#$src1) = $src2.new"), +let isExtended = 1, opExtendable = 0, mayStore = 1, isNVStore = 1, +validSubTargets = HasV4SubT in + def _abs_nv_V4 : NVInst_V4<(outs), + (ins u0AlwaysExt:$src1, IntRegs:$src2), + !strconcat(OpcStr, "(##$src1) = $src2.new"), []>, Requires<[HasV4T]>; - let isPredicated = 1 in - def _abs_cPt_nv_V4 : STInst2<(outs), - (ins PredRegs:$src1, u6Imm:$src2, IntRegs:$src3), +let isExtended = 1, opExtendable = 1, mayStore = 1, isPredicated = 1, +isNVStore = 1, validSubTargets = HasV4SubT in { + def _abs_cPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, u0AlwaysExt:$src2, IntRegs:$src3), !strconcat("if ($src1)", - !strconcat(OpcStr, "(#$src2) = $src3.new")), + !strconcat(OpcStr, "(##$src2) = $src3.new")), []>, Requires<[HasV4T]>; - let isPredicated = 1 in - def _abs_cNotPt_nv_V4 : STInst2<(outs), - (ins PredRegs:$src1, u6Imm:$src2, IntRegs:$src3), + def _abs_cNotPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, u0AlwaysExt:$src2, IntRegs:$src3), !strconcat("if (!$src1)", - !strconcat(OpcStr, "(#$src2) = $src3.new")), + !strconcat(OpcStr, "(##$src2) = $src3.new")), []>, Requires<[HasV4T]>; - let isPredicated = 1 in - def _abs_cdnPt_nv_V4 : STInst2<(outs), - (ins PredRegs:$src1, u6Imm:$src2, IntRegs:$src3), + def _abs_cdnPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, u0AlwaysExt:$src2, IntRegs:$src3), !strconcat("if ($src1.new)", - !strconcat(OpcStr, "(#$src2) = $src3.new")), + !strconcat(OpcStr, "(##$src2) = $src3.new")), []>, Requires<[HasV4T]>; - let isPredicated = 1 in - def _abs_cdnNotPt_nv_V4 : STInst2<(outs), - (ins PredRegs:$src1, u6Imm:$src2, IntRegs:$src3), + def _abs_cdnNotPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, u0AlwaysExt:$src2, IntRegs:$src3), !strconcat("if (!$src1.new)", - !strconcat(OpcStr, "(#$src2) = $src3.new")), + !strconcat(OpcStr, "(##$src2) = $src3.new")), []>, Requires<[HasV4T]>; } +} defm STrib_imm : ST_absimm<"memb">; defm STrih_imm : ST_absimm<"memh">; defm STriw_imm : ST_absimm<"memw">; -let Predicates = [HasV4T], AddedComplexity = 30 in -def : Pat<(truncstorei8 (i32 IntRegs:$src1), u6ImmPred:$src2), - (STrib_imm_abs_V4 u6ImmPred:$src2, IntRegs: $src1)>; - -let Predicates = [HasV4T], AddedComplexity = 30 in -def : Pat<(truncstorei16 (i32 IntRegs:$src1), u6ImmPred:$src2), - (STrih_imm_abs_V4 u6ImmPred:$src2, IntRegs: $src1)>; +let Predicates = [HasV4T], AddedComplexity = 30 in { +def : Pat<(truncstorei8 (i32 IntRegs:$src1), u0AlwaysExtPred:$src2), + (STrib_imm_abs_V4 u0AlwaysExtPred:$src2, IntRegs: $src1)>; -let Predicates = [HasV4T], AddedComplexity = 30 in -def : Pat<(store (i32 IntRegs:$src1), u6ImmPred:$src2), - (STriw_imm_abs_V4 u6ImmPred:$src2, IntRegs: $src1)>; +def : Pat<(truncstorei16 (i32 IntRegs:$src1), u0AlwaysExtPred:$src2), + (STrih_imm_abs_V4 u0AlwaysExtPred:$src2, IntRegs: $src1)>; +def : Pat<(store (i32 IntRegs:$src1), u0AlwaysExtPred:$src2), + (STriw_imm_abs_V4 u0AlwaysExtPred:$src2, IntRegs: $src1)>; +} // Load - absolute addressing mode: These instruction take constant // value as the extended operand multiclass LD_absimm<string OpcStr> { - let isPredicable = 1 in +let isExtended = 1, opExtendable = 1, isPredicable = 1, +validSubTargets = HasV4SubT in def _abs_V4 : LDInst2<(outs IntRegs:$dst), - (ins u6Imm:$src), + (ins u0AlwaysExt:$src), !strconcat("$dst = ", - !strconcat(OpcStr, "(#$src)")), + !strconcat(OpcStr, "(##$src)")), []>, Requires<[HasV4T]>; - let isPredicated = 1 in +let isExtended = 1, opExtendable = 2, isPredicated = 1, +validSubTargets = HasV4SubT in { def _abs_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, u6Imm:$src2), + (ins PredRegs:$src1, u0AlwaysExt:$src2), !strconcat("if ($src1) $dst = ", - !strconcat(OpcStr, "(#$src2)")), + !strconcat(OpcStr, "(##$src2)")), []>, Requires<[HasV4T]>; - let isPredicated = 1 in def _abs_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, u6Imm:$src2), + (ins PredRegs:$src1, u0AlwaysExt:$src2), !strconcat("if (!$src1) $dst = ", - !strconcat(OpcStr, "(#$src2)")), + !strconcat(OpcStr, "(##$src2)")), []>, Requires<[HasV4T]>; - let isPredicated = 1 in def _abs_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, u6Imm:$src2), + (ins PredRegs:$src1, u0AlwaysExt:$src2), !strconcat("if ($src1.new) $dst = ", - !strconcat(OpcStr, "(#$src2)")), + !strconcat(OpcStr, "(##$src2)")), []>, Requires<[HasV4T]>; - let isPredicated = 1 in def _abs_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, u6Imm:$src2), + (ins PredRegs:$src1, u0AlwaysExt:$src2), !strconcat("if (!$src1.new) $dst = ", - !strconcat(OpcStr, "(#$src2)")), + !strconcat(OpcStr, "(##$src2)")), []>, Requires<[HasV4T]>; } +} -defm LDrib_imm : LD_absimm<"memb">; +defm LDrib_imm : LD_absimm<"memb">; defm LDriub_imm : LD_absimm<"memub">; -defm LDrih_imm : LD_absimm<"memh">; +defm LDrih_imm : LD_absimm<"memh">; defm LDriuh_imm : LD_absimm<"memuh">; -defm LDriw_imm : LD_absimm<"memw">; +defm LDriw_imm : LD_absimm<"memw">; -let Predicates = [HasV4T], AddedComplexity = 30 in -def : Pat<(i32 (load u6ImmPred:$src)), - (LDriw_imm_abs_V4 u6ImmPred:$src)>; +let Predicates = [HasV4T], AddedComplexity = 30 in { +def : Pat<(i32 (load u0AlwaysExtPred:$src)), + (LDriw_imm_abs_V4 u0AlwaysExtPred:$src)>; -let Predicates = [HasV4T], AddedComplexity=30 in -def : Pat<(i32 (sextloadi8 u6ImmPred:$src)), - (LDrib_imm_abs_V4 u6ImmPred:$src)>; +def : Pat<(i32 (sextloadi8 u0AlwaysExtPred:$src)), + (LDrib_imm_abs_V4 u0AlwaysExtPred:$src)>; -let Predicates = [HasV4T], AddedComplexity=30 in -def : Pat<(i32 (zextloadi8 u6ImmPred:$src)), - (LDriub_imm_abs_V4 u6ImmPred:$src)>; +def : Pat<(i32 (zextloadi8 u0AlwaysExtPred:$src)), + (LDriub_imm_abs_V4 u0AlwaysExtPred:$src)>; -let Predicates = [HasV4T], AddedComplexity=30 in -def : Pat<(i32 (sextloadi16 u6ImmPred:$src)), - (LDrih_imm_abs_V4 u6ImmPred:$src)>; - -let Predicates = [HasV4T], AddedComplexity=30 in -def : Pat<(i32 (zextloadi16 u6ImmPred:$src)), - (LDriuh_imm_abs_V4 u6ImmPred:$src)>; +def : Pat<(i32 (sextloadi16 u0AlwaysExtPred:$src)), + (LDrih_imm_abs_V4 u0AlwaysExtPred:$src)>; +def : Pat<(i32 (zextloadi16 u0AlwaysExtPred:$src)), + (LDriuh_imm_abs_V4 u0AlwaysExtPred:$src)>; +} // Indexed store double word - global address. // memw(Rs+#u6:2)=#S8 @@ -4886,3 +4080,109 @@ def STrih_offset_ext_V4 : STInst<(outs), [(truncstorei16 (HexagonCONST32 tglobaladdr:$src3), (add IntRegs:$src1, u6_1ImmPred:$src2))]>, Requires<[HasV4T]>; +// Map from store(globaladdress + x) -> memd(#foo + x) +let AddedComplexity = 100 in +def : Pat<(store (i64 DoubleRegs:$src1), + FoldGlobalAddrGP:$addr), + (STrid_abs_V4 FoldGlobalAddrGP:$addr, (i64 DoubleRegs:$src1))>, + Requires<[HasV4T]>; + +def : Pat<(atomic_store_64 FoldGlobalAddrGP:$addr, + (i64 DoubleRegs:$src1)), + (STrid_abs_V4 FoldGlobalAddrGP:$addr, (i64 DoubleRegs:$src1))>, + Requires<[HasV4T]>; + +// Map from store(globaladdress + x) -> memb(#foo + x) +let AddedComplexity = 100 in +def : Pat<(truncstorei8 (i32 IntRegs:$src1), FoldGlobalAddrGP:$addr), + (STrib_abs_V4 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>, + Requires<[HasV4T]>; + +def : Pat<(atomic_store_8 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1)), + (STrib_abs_V4 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>, + Requires<[HasV4T]>; + +// Map from store(globaladdress + x) -> memh(#foo + x) +let AddedComplexity = 100 in +def : Pat<(truncstorei16 (i32 IntRegs:$src1), FoldGlobalAddrGP:$addr), + (STrih_abs_V4 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>, + Requires<[HasV4T]>; + +def : Pat<(atomic_store_16 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1)), + (STrih_abs_V4 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>, + Requires<[HasV4T]>; + +// Map from store(globaladdress + x) -> memw(#foo + x) +let AddedComplexity = 100 in +def : Pat<(store (i32 IntRegs:$src1), FoldGlobalAddrGP:$addr), + (STriw_abs_V4 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>, + Requires<[HasV4T]>; + +def : Pat<(atomic_store_32 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1)), + (STriw_abs_V4 FoldGlobalAddrGP:$addr, (i32 IntRegs:$src1))>, + Requires<[HasV4T]>; + +// Map from load(globaladdress + x) -> memd(#foo + x) +let AddedComplexity = 100 in +def : Pat<(i64 (load FoldGlobalAddrGP:$addr)), + (i64 (LDrid_abs_V4 FoldGlobalAddrGP:$addr))>, + Requires<[HasV4T]>; + +def : Pat<(atomic_load_64 FoldGlobalAddrGP:$addr), + (i64 (LDrid_abs_V4 FoldGlobalAddrGP:$addr))>, + Requires<[HasV4T]>; + +// Map from load(globaladdress + x) -> memb(#foo + x) +let AddedComplexity = 100 in +def : Pat<(i32 (extloadi8 FoldGlobalAddrGP:$addr)), + (i32 (LDrib_abs_V4 FoldGlobalAddrGP:$addr))>, + Requires<[HasV4T]>; + +// Map from load(globaladdress + x) -> memb(#foo + x) +let AddedComplexity = 100 in +def : Pat<(i32 (sextloadi8 FoldGlobalAddrGP:$addr)), + (i32 (LDrib_abs_V4 FoldGlobalAddrGP:$addr))>, + Requires<[HasV4T]>; + +//let AddedComplexity = 100 in +let AddedComplexity = 100 in +def : Pat<(i32 (extloadi16 FoldGlobalAddrGP:$addr)), + (i32 (LDrih_abs_V4 FoldGlobalAddrGP:$addr))>, + Requires<[HasV4T]>; + +// Map from load(globaladdress + x) -> memh(#foo + x) +let AddedComplexity = 100 in +def : Pat<(i32 (sextloadi16 FoldGlobalAddrGP:$addr)), + (i32 (LDrih_abs_V4 FoldGlobalAddrGP:$addr))>, + Requires<[HasV4T]>; + +// Map from load(globaladdress + x) -> memuh(#foo + x) +let AddedComplexity = 100 in +def : Pat<(i32 (zextloadi16 FoldGlobalAddrGP:$addr)), + (i32 (LDriuh_abs_V4 FoldGlobalAddrGP:$addr))>, + Requires<[HasV4T]>; + +def : Pat<(atomic_load_16 FoldGlobalAddrGP:$addr), + (i32 (LDriuh_abs_V4 FoldGlobalAddrGP:$addr))>, + Requires<[HasV4T]>; + +// Map from load(globaladdress + x) -> memub(#foo + x) +let AddedComplexity = 100 in +def : Pat<(i32 (zextloadi8 FoldGlobalAddrGP:$addr)), + (i32 (LDriub_abs_V4 FoldGlobalAddrGP:$addr))>, + Requires<[HasV4T]>; + +def : Pat<(atomic_load_8 FoldGlobalAddrGP:$addr), + (i32 (LDriub_abs_V4 FoldGlobalAddrGP:$addr))>, + Requires<[HasV4T]>; + +// Map from load(globaladdress + x) -> memw(#foo + x) +let AddedComplexity = 100 in +def : Pat<(i32 (load FoldGlobalAddrGP:$addr)), + (i32 (LDriw_abs_V4 FoldGlobalAddrGP:$addr))>, + Requires<[HasV4T]>; + +def : Pat<(atomic_load_32 FoldGlobalAddrGP:$addr), + (i32 (LDriw_abs_V4 FoldGlobalAddrGP:$addr))>, + Requires<[HasV4T]>; + diff --git a/lib/Target/Hexagon/HexagonMCInstLower.cpp b/lib/Target/Hexagon/HexagonMCInstLower.cpp index dc644ad213..f011d51bd6 100644 --- a/lib/Target/Hexagon/HexagonMCInstLower.cpp +++ b/lib/Target/Hexagon/HexagonMCInstLower.cpp @@ -15,8 +15,9 @@ #include "Hexagon.h" #include "HexagonAsmPrinter.h" #include "HexagonMachineFunctionInfo.h" +#include "MCTargetDesc/HexagonMCInst.h" #include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/Constants.h" +#include "llvm/IR/Constants.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/Target/Mangler.h" @@ -38,9 +39,10 @@ static MCOperand GetSymbolRef(const MachineOperand& MO, const MCSymbol* Symbol, } // Create an MCInst from a MachineInstr -void llvm::HexagonLowerToMC(const MachineInstr* MI, MCInst& MCI, +void llvm::HexagonLowerToMC(const MachineInstr* MI, HexagonMCInst& MCI, HexagonAsmPrinter& AP) { MCI.setOpcode(MI->getOpcode()); + MCI.setDesc(MI->getDesc()); for (unsigned i = 0, e = MI->getNumOperands(); i < e; i++) { const MachineOperand &MO = MI->getOperand(i); diff --git a/lib/Target/Hexagon/HexagonMachineScheduler.cpp b/lib/Target/Hexagon/HexagonMachineScheduler.cpp index aef6830752..1388ad4f16 100644 --- a/lib/Target/Hexagon/HexagonMachineScheduler.cpp +++ b/lib/Target/Hexagon/HexagonMachineScheduler.cpp @@ -15,7 +15,8 @@ #define DEBUG_TYPE "misched" #include "HexagonMachineScheduler.h" -#include <queue> +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/IR/Function.h" using namespace llvm; @@ -152,7 +153,16 @@ void VLIWMachineScheduler::schedule() { // Postprocess the DAG to add platform specific artificial dependencies. postprocessDAG(); + SmallVector<SUnit*, 8> TopRoots, BotRoots; + findRootsAndBiasEdges(TopRoots, BotRoots); + + // Initialize the strategy before modifying the DAG. + SchedImpl->initialize(this); + // To view Height/Depth correctly, they should be accessed at least once. + // + // FIXME: SUnit::dumpAll always recompute depth and height now. The max + // depth/height could be computed directly from the roots and leaves. DEBUG(unsigned maxH = 0; for (unsigned su = 0, e = SUnits.size(); su != e; ++su) if (SUnits[su].getHeight() > maxH) @@ -166,7 +176,7 @@ void VLIWMachineScheduler::schedule() { DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su) SUnits[su].dumpAll(this)); - initQueues(); + initQueues(TopRoots, BotRoots); bool IsTopNode = false; while (SUnit *SU = SchedImpl->pickNode(IsTopNode)) { @@ -186,6 +196,7 @@ void ConvergingVLIWScheduler::initialize(ScheduleDAGMI *dag) { DAG = static_cast<VLIWMachineScheduler*>(dag); SchedModel = DAG->getSchedModel(); TRI = DAG->TRI; + Top.init(DAG, SchedModel); Bot.init(DAG, SchedModel); @@ -193,6 +204,8 @@ void ConvergingVLIWScheduler::initialize(ScheduleDAGMI *dag) { // are disabled, then these HazardRecs will be disabled. const InstrItineraryData *Itin = DAG->getSchedModel()->getInstrItineraries(); const TargetMachine &TM = DAG->MF.getTarget(); + delete Top.HazardRec; + delete Bot.HazardRec; Top.HazardRec = TM.getInstrInfo()->CreateTargetMIHazardRecognizer(Itin, DAG); Bot.HazardRec = TM.getInstrInfo()->CreateTargetMIHazardRecognizer(Itin, DAG); @@ -677,4 +690,3 @@ void ConvergingVLIWScheduler::schedNode(SUnit *SU, bool IsTopNode) { Bot.bumpNode(SU); } } - diff --git a/lib/Target/Hexagon/HexagonPeephole.cpp b/lib/Target/Hexagon/HexagonPeephole.cpp index 7195c4a8d3..576f1d7d07 100644 --- a/lib/Target/Hexagon/HexagonPeephole.cpp +++ b/lib/Target/Hexagon/HexagonPeephole.cpp @@ -45,7 +45,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" -#include "llvm/Constants.h" +#include "llvm/IR/Constants.h" #include "llvm/PassSupport.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" diff --git a/lib/Target/Hexagon/HexagonRegisterInfo.cpp b/lib/Target/Hexagon/HexagonRegisterInfo.cpp index 2985a5667b..f947dfcdf9 100644 --- a/lib/Target/Hexagon/HexagonRegisterInfo.cpp +++ b/lib/Target/Hexagon/HexagonRegisterInfo.cpp @@ -25,14 +25,14 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" -#include "llvm/Function.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Type.h" #include "llvm/MC/MachineLocation.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" -#include "llvm/Type.h" using namespace llvm; @@ -117,37 +117,15 @@ HexagonRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const { "architecture version"); } -void HexagonRegisterInfo:: -eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const { - MachineInstr &MI = *I; - - if (MI.getOpcode() == Hexagon::ADJCALLSTACKDOWN) { - // Hexagon_TODO: add code - } else if (MI.getOpcode() == Hexagon::ADJCALLSTACKUP) { - // Hexagon_TODO: add code - } else { - llvm_unreachable("Cannot handle this call frame pseudo instruction"); - } - MBB.erase(I); -} - void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, RegScavenger *RS) const { - + int SPAdj, unsigned FIOperandNum, + RegScavenger *RS) const { // // Hexagon_TODO: Do we need to enforce this for Hexagon? assert(SPAdj == 0 && "Unexpected"); - - unsigned i = 0; MachineInstr &MI = *II; - while (!MI.getOperand(i).isFI()) { - ++i; - assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); - } - - int FrameIndex = MI.getOperand(i).getIndex(); + int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); // Addressable stack objects are accessed using neg. offsets from %fp. MachineFunction &MF = *MI.getParent()->getParent(); @@ -167,8 +145,9 @@ void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset)) && !TII.isSpillPredRegOp(&MI)) { // Replace frame index with a stack pointer reference. - MI.getOperand(i).ChangeToRegister(getStackRegister(), false, false, true); - MI.getOperand(i+1).ChangeToImmediate(FrameSize+Offset); + MI.getOperand(FIOperandNum).ChangeToRegister(getStackRegister(), false, + false, true); + MI.getOperand(FIOperandNum + 1).ChangeToImmediate(FrameSize+Offset); } else { // Replace frame index with a frame pointer reference. if (!TII.isValidOffset(MI.getOpcode(), Offset)) { @@ -205,8 +184,8 @@ void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, dstReg).addReg(FrameReg).addImm(Offset); } - MI.getOperand(i).ChangeToRegister(dstReg, false, false, true); - MI.getOperand(i+1).ChangeToImmediate(0); + MI.getOperand(FIOperandNum).ChangeToRegister(dstReg, false, false,true); + MI.getOperand(FIOperandNum+1).ChangeToImmediate(0); } else if ((MI.getOpcode() == Hexagon::STriw_indexed) || (MI.getOpcode() == Hexagon::STriw) || (MI.getOpcode() == Hexagon::STrid) || @@ -233,29 +212,31 @@ void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, TII.get(Hexagon::ADD_ri), resReg).addReg(FrameReg).addImm(Offset); } - MI.getOperand(i).ChangeToRegister(resReg, false, false, true); - MI.getOperand(i+1).ChangeToImmediate(0); + MI.getOperand(FIOperandNum).ChangeToRegister(resReg, false, false,true); + MI.getOperand(FIOperandNum+1).ChangeToImmediate(0); } else if (TII.isMemOp(&MI)) { unsigned resReg = HEXAGON_RESERVED_REG_1; if (!MFI.hasVarSizedObjects() && TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset))) { - MI.getOperand(i).ChangeToRegister(getStackRegister(), false, false, - true); - MI.getOperand(i+1).ChangeToImmediate(FrameSize+Offset); + MI.getOperand(FIOperandNum).ChangeToRegister(getStackRegister(), + false, false, true); + MI.getOperand(FIOperandNum+1).ChangeToImmediate(FrameSize+Offset); } else if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) { BuildMI(*MI.getParent(), II, MI.getDebugLoc(), TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset); BuildMI(*MI.getParent(), II, MI.getDebugLoc(), TII.get(Hexagon::ADD_rr), resReg).addReg(FrameReg).addReg(resReg); - MI.getOperand(i).ChangeToRegister(resReg, false, false, true); - MI.getOperand(i+1).ChangeToImmediate(0); + MI.getOperand(FIOperandNum).ChangeToRegister(resReg, false, false, + true); + MI.getOperand(FIOperandNum+1).ChangeToImmediate(0); } else { BuildMI(*MI.getParent(), II, MI.getDebugLoc(), TII.get(Hexagon::ADD_ri), resReg).addReg(FrameReg).addImm(Offset); - MI.getOperand(i).ChangeToRegister(resReg, false, false, true); - MI.getOperand(i+1).ChangeToImmediate(0); + MI.getOperand(FIOperandNum).ChangeToRegister(resReg, false, false, + true); + MI.getOperand(FIOperandNum+1).ChangeToImmediate(0); } } else { unsigned dstReg = MI.getOperand(0).getReg(); @@ -265,14 +246,14 @@ void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, TII.get(Hexagon::ADD_rr), dstReg).addReg(FrameReg).addReg(dstReg); // Can we delete MI??? r2 = add (r2, #0). - MI.getOperand(i).ChangeToRegister(dstReg, false, false, true); - MI.getOperand(i+1).ChangeToImmediate(0); + MI.getOperand(FIOperandNum).ChangeToRegister(dstReg, false, false,true); + MI.getOperand(FIOperandNum+1).ChangeToImmediate(0); } } else { // If the offset is small enough to fit in the immediate field, directly // encode it. - MI.getOperand(i).ChangeToRegister(FrameReg, false); - MI.getOperand(i+1).ChangeToImmediate(Offset); + MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false); + MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset); } } @@ -310,58 +291,6 @@ void HexagonRegisterInfo::getInitialFrameState(std::vector<MachineMove> Moves.push_back(MachineMove(0, Dst, Src)); } -// Get the weight in units of pressure for this register class. -const RegClassWeight & -HexagonRegisterInfo::getRegClassWeight(const TargetRegisterClass *RC) const { - // Each TargetRegisterClass has a per register weight, and weight - // limit which must be less than the limits of its pressure sets. - static const RegClassWeight RCWeightTable[] = { - {1, 32}, // IntRegs - {1, 8}, // CRRegs - {1, 4}, // PredRegs - {2, 16}, // DoubleRegs - {0, 0} }; - return RCWeightTable[RC->getID()]; -} - -/// Get the number of dimensions of register pressure. -unsigned HexagonRegisterInfo::getNumRegPressureSets() const { - return 4; -} - -/// Get the name of this register unit pressure set. -const char *HexagonRegisterInfo::getRegPressureSetName(unsigned Idx) const { - static const char *const RegPressureSetName[] = { - "IntRegsRegSet", - "CRRegsRegSet", - "PredRegsRegSet", - "DoubleRegsRegSet" - }; - assert((Idx < 4) && "Index out of bounds"); - return RegPressureSetName[Idx]; -} - -/// Get the register unit pressure limit for this dimension. -/// This limit must be adjusted dynamically for reserved registers. -unsigned HexagonRegisterInfo::getRegPressureSetLimit(unsigned Idx) const { - static const int RegPressureLimit [] = { 16, 4, 2, 8 }; - assert((Idx < 4) && "Index out of bounds"); - return RegPressureLimit[Idx]; -} - -const int* -HexagonRegisterInfo::getRegClassPressureSets(const TargetRegisterClass *RC) - const { - static const int RCSetsTable[] = { - 0, -1, // IntRegs - 1, -1, // CRRegs - 2, -1, // PredRegs - 0, -1, // DoubleRegs - -1 }; - static const unsigned RCSetStartTable[] = { 0, 2, 4, 6, 0 }; - unsigned SetListStart = RCSetStartTable[RC->getID()]; - return &RCSetsTable[SetListStart]; -} unsigned HexagonRegisterInfo::getEHExceptionRegister() const { llvm_unreachable("What is the exception register"); } diff --git a/lib/Target/Hexagon/HexagonRegisterInfo.h b/lib/Target/Hexagon/HexagonRegisterInfo.h index e8f3cfb6c3..8a3f94a3fd 100644 --- a/lib/Target/Hexagon/HexagonRegisterInfo.h +++ b/lib/Target/Hexagon/HexagonRegisterInfo.h @@ -56,12 +56,9 @@ struct HexagonRegisterInfo : public HexagonGenRegisterInfo { BitVector getReservedRegs(const MachineFunction &MF) const; - void eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const; - void eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, RegScavenger *RS = NULL) const; + int SPAdj, unsigned FIOperandNum, + RegScavenger *RS = NULL) const; /// determineFrameLayout - Determine the size of the frame and maximum call /// frame size. @@ -87,11 +84,6 @@ struct HexagonRegisterInfo : public HexagonGenRegisterInfo { // Exception handling queries. unsigned getEHExceptionRegister() const; unsigned getEHHandlerRegister() const; - const RegClassWeight &getRegClassWeight(const TargetRegisterClass *RC) const; - unsigned getNumRegPressureSets() const; - const char *getRegPressureSetName(unsigned Idx) const; - unsigned getRegPressureSetLimit(unsigned Idx) const; - const int* getRegClassPressureSets(const TargetRegisterClass *RC) const; }; } // end namespace llvm diff --git a/lib/Target/Hexagon/HexagonRemoveSZExtArgs.cpp b/lib/Target/Hexagon/HexagonRemoveSZExtArgs.cpp index a4445cb4b1..34bf4eacfd 100644 --- a/lib/Target/Hexagon/HexagonRemoveSZExtArgs.cpp +++ b/lib/Target/Hexagon/HexagonRemoveSZExtArgs.cpp @@ -15,8 +15,8 @@ #include "Hexagon.h" #include "HexagonTargetMachine.h" #include "llvm/CodeGen/MachineFunctionAnalysis.h" -#include "llvm/Function.h" -#include "llvm/Instructions.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" #include "llvm/Pass.h" #include "llvm/Transforms/Scalar.h" @@ -51,7 +51,7 @@ bool HexagonRemoveExtendArgs::runOnFunction(Function &F) { unsigned Idx = 1; for (Function::arg_iterator AI = F.arg_begin(), AE = F.arg_end(); AI != AE; ++AI, ++Idx) { - if (F.getParamAttributes(Idx).hasAttribute(Attributes::SExt)) { + if (F.getAttributes().hasAttribute(Idx, Attribute::SExt)) { Argument* Arg = AI; if (!isa<PointerType>(Arg->getType())) { for (Instruction::use_iterator UI = Arg->use_begin(); diff --git a/lib/Target/Hexagon/HexagonSchedule.td b/lib/Target/Hexagon/HexagonSchedule.td index b5ff69a701..c2cfbb9710 100644 --- a/lib/Target/Hexagon/HexagonSchedule.td +++ b/lib/Target/Hexagon/HexagonSchedule.td @@ -8,10 +8,11 @@ //===----------------------------------------------------------------------===// // Functional Units -def LUNIT : FuncUnit; -def LSUNIT : FuncUnit; -def MUNIT : FuncUnit; -def SUNIT : FuncUnit; +def LSUNIT : FuncUnit; // SLOT0 +def LUNIT : FuncUnit; // SLOT1 +def MUNIT : FuncUnit; // SLOT2 +def SUNIT : FuncUnit; // SLOT3 +def LOOPUNIT : FuncUnit; // Itinerary classes def ALU32 : InstrItinClass; @@ -20,27 +21,34 @@ def CR : InstrItinClass; def J : InstrItinClass; def JR : InstrItinClass; def LD : InstrItinClass; +def LD0 : InstrItinClass; def M : InstrItinClass; def ST : InstrItinClass; +def ST0 : InstrItinClass; def S : InstrItinClass; def SYS : InstrItinClass; -def MARKER : InstrItinClass; +def ENDLOOP : InstrItinClass; def PSEUDO : InstrItinClass; +def PSEUDOM : InstrItinClass; def HexagonItineraries : - ProcessorItineraries<[LUNIT, LSUNIT, MUNIT, SUNIT], [], [ + ProcessorItineraries<[LSUNIT, LUNIT, MUNIT, SUNIT, LOOPUNIT], [], [ InstrItinData<ALU32 , [InstrStage<1, [LUNIT, LSUNIT, MUNIT, SUNIT]>]>, InstrItinData<ALU64 , [InstrStage<1, [MUNIT, SUNIT]>]>, InstrItinData<CR , [InstrStage<1, [SUNIT]>]>, InstrItinData<J , [InstrStage<1, [SUNIT, MUNIT]>]>, InstrItinData<JR , [InstrStage<1, [MUNIT]>]>, InstrItinData<LD , [InstrStage<1, [LUNIT, LSUNIT]>]>, + InstrItinData<LD0 , [InstrStage<1, [LSUNIT]>]>, InstrItinData<M , [InstrStage<1, [MUNIT, SUNIT]>]>, InstrItinData<ST , [InstrStage<1, [LSUNIT]>]>, + InstrItinData<ST0 , [InstrStage<1, [LSUNIT]>]>, InstrItinData<S , [InstrStage<1, [SUNIT, MUNIT]>]>, InstrItinData<SYS , [InstrStage<1, [LSUNIT]>]>, - InstrItinData<MARKER , [InstrStage<1, [LUNIT, LSUNIT, MUNIT, SUNIT]>]>, - InstrItinData<PSEUDO , [InstrStage<1, [LUNIT, LSUNIT, MUNIT, SUNIT]>]> + InstrItinData<ENDLOOP, [InstrStage<1, [LOOPUNIT]>]>, + InstrItinData<PSEUDO , [InstrStage<1, [LUNIT, LSUNIT, MUNIT, SUNIT]>]>, + InstrItinData<PSEUDOM, [InstrStage<1, [MUNIT, SUNIT], 0>, + InstrStage<1, [MUNIT, SUNIT]>]> ]>; def HexagonModel : SchedMachineModel { diff --git a/lib/Target/Hexagon/HexagonScheduleV4.td b/lib/Target/Hexagon/HexagonScheduleV4.td index 5668ae81e8..ef72cf4068 100644 --- a/lib/Target/Hexagon/HexagonScheduleV4.td +++ b/lib/Target/Hexagon/HexagonScheduleV4.td @@ -28,6 +28,10 @@ def SLOT0 : FuncUnit; def SLOT1 : FuncUnit; def SLOT2 : FuncUnit; def SLOT3 : FuncUnit; +// Endloop is a pseudo instruction that is encoded with 2 bits in a packet +// rather than taking an execution slot. This special unit is needed +// to schedule an ENDLOOP with 4 other instructions. +def SLOT_ENDLOOP: FuncUnit; // Itinerary classes. def NV_V4 : InstrItinClass; @@ -36,22 +40,26 @@ def MEM_V4 : InstrItinClass; def PREFIX : InstrItinClass; def HexagonItinerariesV4 : - ProcessorItineraries<[SLOT0, SLOT1, SLOT2, SLOT3], [], [ + ProcessorItineraries<[SLOT0, SLOT1, SLOT2, SLOT3, SLOT_ENDLOOP], [], [ InstrItinData<ALU32 , [InstrStage<1, [SLOT0, SLOT1, SLOT2, SLOT3]>]>, InstrItinData<ALU64 , [InstrStage<1, [SLOT2, SLOT3]>]>, InstrItinData<CR , [InstrStage<1, [SLOT3]>]>, InstrItinData<J , [InstrStage<1, [SLOT2, SLOT3]>]>, InstrItinData<JR , [InstrStage<1, [SLOT2]>]>, InstrItinData<LD , [InstrStage<1, [SLOT0, SLOT1]>]>, + InstrItinData<LD0 , [InstrStage<1, [SLOT0]>]>, InstrItinData<M , [InstrStage<1, [SLOT2, SLOT3]>]>, InstrItinData<ST , [InstrStage<1, [SLOT0, SLOT1]>]>, + InstrItinData<ST0 , [InstrStage<1, [SLOT0]>]>, InstrItinData<S , [InstrStage<1, [SLOT2, SLOT3]>]>, InstrItinData<SYS , [InstrStage<1, [SLOT0]>]>, InstrItinData<NV_V4 , [InstrStage<1, [SLOT0]>]>, InstrItinData<MEM_V4 , [InstrStage<1, [SLOT0]>]>, - InstrItinData<MARKER , [InstrStage<1, [SLOT0, SLOT1, SLOT2, SLOT3]>]>, + InstrItinData<ENDLOOP, [InstrStage<1, [SLOT_ENDLOOP]>]>, InstrItinData<PREFIX , [InstrStage<1, [SLOT0, SLOT1, SLOT2, SLOT3]>]>, - InstrItinData<PSEUDO , [InstrStage<1, [SLOT0, SLOT1, SLOT2, SLOT3]>]> + InstrItinData<PSEUDO , [InstrStage<1, [SLOT0, SLOT1, SLOT2, SLOT3]>]>, + InstrItinData<PSEUDOM, [InstrStage<1, [SLOT2, SLOT3], 0>, + InstrStage<1, [SLOT2, SLOT3]>]> ]>; def HexagonModelV4 : SchedMachineModel { diff --git a/lib/Target/Hexagon/HexagonTargetMachine.cpp b/lib/Target/Hexagon/HexagonTargetMachine.cpp index 8fc836b458..d9fef3e455 100644 --- a/lib/Target/Hexagon/HexagonTargetMachine.cpp +++ b/lib/Target/Hexagon/HexagonTargetMachine.cpp @@ -16,7 +16,7 @@ #include "HexagonISelLowering.h" #include "HexagonMachineScheduler.h" #include "llvm/CodeGen/Passes.h" -#include "llvm/Module.h" +#include "llvm/IR/Module.h" #include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/TargetRegistry.h" @@ -74,8 +74,7 @@ HexagonTargetMachine::HexagonTargetMachine(const Target &T, StringRef TT, Subtarget(TT, CPU, FS), InstrInfo(Subtarget), TLInfo(*this), TSInfo(*this), FrameLowering(Subtarget), - InstrItins(&Subtarget.getInstrItineraryData()), - STTI(&TLInfo), VTTI(&TLInfo) { + InstrItins(&Subtarget.getInstrItineraryData()) { setMCUseCFI(false); } @@ -123,7 +122,7 @@ TargetPassConfig *HexagonTargetMachine::createPassConfig(PassManagerBase &PM) { bool HexagonPassConfig::addInstSelector() { addPass(createHexagonRemoveExtendOps(getHexagonTargetMachine())); - addPass(createHexagonISelDag(getHexagonTargetMachine())); + addPass(createHexagonISelDag(getHexagonTargetMachine(), getOptLevel())); addPass(createHexagonPeephole()); return false; } diff --git a/lib/Target/Hexagon/HexagonTargetMachine.h b/lib/Target/Hexagon/HexagonTargetMachine.h index fa669a2719..cf8f9aa361 100644 --- a/lib/Target/Hexagon/HexagonTargetMachine.h +++ b/lib/Target/Hexagon/HexagonTargetMachine.h @@ -19,9 +19,8 @@ #include "HexagonInstrInfo.h" #include "HexagonSelectionDAGInfo.h" #include "HexagonSubtarget.h" -#include "llvm/DataLayout.h" +#include "llvm/IR/DataLayout.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetTransformImpl.h" namespace llvm { @@ -35,8 +34,6 @@ class HexagonTargetMachine : public LLVMTargetMachine { HexagonSelectionDAGInfo TSInfo; HexagonFrameLowering FrameLowering; const InstrItineraryData* InstrItins; - ScalarTargetTransformImpl STTI; - VectorTargetTransformImpl VTTI; public: HexagonTargetMachine(const Target &T, StringRef TT,StringRef CPU, @@ -71,14 +68,6 @@ public: return &TSInfo; } - virtual const ScalarTargetTransformInfo *getScalarTargetTransformInfo()const { - return &STTI; - } - - virtual const VectorTargetTransformInfo *getVectorTargetTransformInfo()const { - return &VTTI; - } - virtual const DataLayout *getDataLayout() const { return &DL; } static unsigned getModuleMatchQuality(const Module &M); diff --git a/lib/Target/Hexagon/HexagonTargetObjectFile.cpp b/lib/Target/Hexagon/HexagonTargetObjectFile.cpp index 2c1145f171..993fcfaed4 100644 --- a/lib/Target/Hexagon/HexagonTargetObjectFile.cpp +++ b/lib/Target/Hexagon/HexagonTargetObjectFile.cpp @@ -14,10 +14,10 @@ #include "HexagonTargetObjectFile.h" #include "HexagonSubtarget.h" #include "HexagonTargetMachine.h" -#include "llvm/DataLayout.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Function.h" -#include "llvm/GlobalVariable.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalVariable.h" #include "llvm/MC/MCContext.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ELF.h" diff --git a/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp b/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp index ab6f6cf899..866beb1688 100644 --- a/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp +++ b/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp @@ -17,35 +17,36 @@ // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "packets" -#include "Hexagon.h" -#include "HexagonMachineFunctionInfo.h" -#include "HexagonRegisterInfo.h" -#include "HexagonSubtarget.h" -#include "HexagonTargetMachine.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/DFAPacketizer.h" -#include "llvm/CodeGen/LatencyPriorityQueue.h" +#include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/MachineDominators.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunctionAnalysis.h" #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineLoopInfo.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/ScheduleDAG.h" #include "llvm/CodeGen/ScheduleDAGInstrs.h" -#include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/CodeGen/LatencyPriorityQueue.h" #include "llvm/CodeGen/SchedulerRegistry.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/MachineFunctionAnalysis.h" +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/MathExtras.h" #include "llvm/MC/MCInstrItineraries.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetRegisterInfo.h" +#include "Hexagon.h" +#include "HexagonTargetMachine.h" +#include "HexagonRegisterInfo.h" +#include "HexagonSubtarget.h" +#include "HexagonMachineFunctionInfo.h" + #include <map> using namespace llvm; @@ -241,8 +242,9 @@ static bool IsIndirectCall(MachineInstr* MI) { // reservation fail. void HexagonPacketizerList::reserveResourcesForConstExt(MachineInstr* MI) { const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; - MachineInstr *PseudoMI = MI->getParent()->getParent()->CreateMachineInstr( - QII->get(Hexagon::IMMEXT), MI->getDebugLoc()); + MachineFunction *MF = MI->getParent()->getParent(); + MachineInstr *PseudoMI = MF->CreateMachineInstr(QII->get(Hexagon::IMMEXT_i), + MI->getDebugLoc()); if (ResourceTracker->canReserveResources(PseudoMI)) { ResourceTracker->reserveResources(PseudoMI); @@ -256,10 +258,10 @@ void HexagonPacketizerList::reserveResourcesForConstExt(MachineInstr* MI) { bool HexagonPacketizerList::canReserveResourcesForConstExt(MachineInstr *MI) { const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; - assert(QII->isExtended(MI) && + assert((QII->isExtended(MI) || QII->isConstExtended(MI)) && "Should only be called for constant extended instructions"); MachineFunction *MF = MI->getParent()->getParent(); - MachineInstr *PseudoMI = MF->CreateMachineInstr(QII->get(Hexagon::IMMEXT), + MachineInstr *PseudoMI = MF->CreateMachineInstr(QII->get(Hexagon::IMMEXT_i), MI->getDebugLoc()); bool CanReserve = ResourceTracker->canReserveResources(PseudoMI); MF->DeleteMachineInstr(PseudoMI); @@ -270,8 +272,9 @@ bool HexagonPacketizerList::canReserveResourcesForConstExt(MachineInstr *MI) { // true, otherwise, return false. bool HexagonPacketizerList::tryAllocateResourcesForConstExt(MachineInstr* MI) { const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; - MachineInstr *PseudoMI = MI->getParent()->getParent()->CreateMachineInstr( - QII->get(Hexagon::IMMEXT), MI->getDebugLoc()); + MachineFunction *MF = MI->getParent()->getParent(); + MachineInstr *PseudoMI = MF->CreateMachineInstr(QII->get(Hexagon::IMMEXT_i), + MI->getDebugLoc()); if (ResourceTracker->canReserveResources(PseudoMI)) { ResourceTracker->reserveResources(PseudoMI); @@ -348,17 +351,6 @@ static bool IsControlFlow(MachineInstr* MI) { return (MI->getDesc().isTerminator() || MI->getDesc().isCall()); } -bool HexagonPacketizerList::isNewValueInst(MachineInstr* MI) { - const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; - if (QII->isNewValueJump(MI)) - return true; - - if (QII->isNewValueStore(MI)) - return true; - - return false; -} - // Function returns true if an instruction can be promoted to the new-value // store. It will always return false for v2 and v3. // It lists all the conditional and unconditional stores that can be promoted @@ -374,7 +366,6 @@ bool HexagonPacketizerList::IsNewifyStore (MachineInstr* MI) { case Hexagon::STrib_indexed: case Hexagon::STrib_indexed_shl_V4: case Hexagon::STrib_shl_V4: - case Hexagon::STrib_GP_V4: case Hexagon::STb_GP_V4: case Hexagon::POST_STbri: case Hexagon::STrib_cPt: @@ -397,17 +388,12 @@ bool HexagonPacketizerList::IsNewifyStore (MachineInstr* MI) { case Hexagon::STb_GP_cNotPt_V4: case Hexagon::STb_GP_cdnPt_V4: case Hexagon::STb_GP_cdnNotPt_V4: - case Hexagon::STrib_GP_cPt_V4: - case Hexagon::STrib_GP_cNotPt_V4: - case Hexagon::STrib_GP_cdnPt_V4: - case Hexagon::STrib_GP_cdnNotPt_V4: // store halfword case Hexagon::STrih: case Hexagon::STrih_indexed: case Hexagon::STrih_indexed_shl_V4: case Hexagon::STrih_shl_V4: - case Hexagon::STrih_GP_V4: case Hexagon::STh_GP_V4: case Hexagon::POST_SThri: case Hexagon::STrih_cPt: @@ -430,17 +416,12 @@ bool HexagonPacketizerList::IsNewifyStore (MachineInstr* MI) { case Hexagon::STh_GP_cNotPt_V4: case Hexagon::STh_GP_cdnPt_V4: case Hexagon::STh_GP_cdnNotPt_V4: - case Hexagon::STrih_GP_cPt_V4: - case Hexagon::STrih_GP_cNotPt_V4: - case Hexagon::STrih_GP_cdnPt_V4: - case Hexagon::STrih_GP_cdnNotPt_V4: // store word case Hexagon::STriw: case Hexagon::STriw_indexed: case Hexagon::STriw_indexed_shl_V4: case Hexagon::STriw_shl_V4: - case Hexagon::STriw_GP_V4: case Hexagon::STw_GP_V4: case Hexagon::POST_STwri: case Hexagon::STriw_cPt: @@ -463,10 +444,6 @@ bool HexagonPacketizerList::IsNewifyStore (MachineInstr* MI) { case Hexagon::STw_GP_cNotPt_V4: case Hexagon::STw_GP_cdnPt_V4: case Hexagon::STw_GP_cdnNotPt_V4: - case Hexagon::STriw_GP_cPt_V4: - case Hexagon::STriw_GP_cNotPt_V4: - case Hexagon::STriw_GP_cdnPt_V4: - case Hexagon::STriw_GP_cdnNotPt_V4: return QRI->Subtarget.hasV4TOps(); } return false; @@ -506,9 +483,6 @@ static int GetDotNewOp(const int opc) { case Hexagon::STrib_shl_V4: return Hexagon::STrib_shl_nv_V4; - case Hexagon::STrib_GP_V4: - return Hexagon::STrib_GP_nv_V4; - case Hexagon::STb_GP_V4: return Hexagon::STb_GP_nv_V4; @@ -575,18 +549,6 @@ static int GetDotNewOp(const int opc) { case Hexagon::STb_GP_cdnNotPt_V4: return Hexagon::STb_GP_cdnNotPt_nv_V4; - case Hexagon::STrib_GP_cPt_V4: - return Hexagon::STrib_GP_cPt_nv_V4; - - case Hexagon::STrib_GP_cNotPt_V4: - return Hexagon::STrib_GP_cNotPt_nv_V4; - - case Hexagon::STrib_GP_cdnPt_V4: - return Hexagon::STrib_GP_cdnPt_nv_V4; - - case Hexagon::STrib_GP_cdnNotPt_V4: - return Hexagon::STrib_GP_cdnNotPt_nv_V4; - // store new value halfword case Hexagon::STrih: return Hexagon::STrih_nv_V4; @@ -600,9 +562,6 @@ static int GetDotNewOp(const int opc) { case Hexagon::STrih_shl_V4: return Hexagon::STrih_shl_nv_V4; - case Hexagon::STrih_GP_V4: - return Hexagon::STrih_GP_nv_V4; - case Hexagon::STh_GP_V4: return Hexagon::STh_GP_nv_V4; @@ -669,18 +628,6 @@ static int GetDotNewOp(const int opc) { case Hexagon::STh_GP_cdnNotPt_V4: return Hexagon::STh_GP_cdnNotPt_nv_V4; - case Hexagon::STrih_GP_cPt_V4: - return Hexagon::STrih_GP_cPt_nv_V4; - - case Hexagon::STrih_GP_cNotPt_V4: - return Hexagon::STrih_GP_cNotPt_nv_V4; - - case Hexagon::STrih_GP_cdnPt_V4: - return Hexagon::STrih_GP_cdnPt_nv_V4; - - case Hexagon::STrih_GP_cdnNotPt_V4: - return Hexagon::STrih_GP_cdnNotPt_nv_V4; - // store new value word case Hexagon::STriw: return Hexagon::STriw_nv_V4; @@ -694,9 +641,6 @@ static int GetDotNewOp(const int opc) { case Hexagon::STriw_shl_V4: return Hexagon::STriw_shl_nv_V4; - case Hexagon::STriw_GP_V4: - return Hexagon::STriw_GP_nv_V4; - case Hexagon::STw_GP_V4: return Hexagon::STw_GP_nv_V4; @@ -763,17 +707,6 @@ static int GetDotNewOp(const int opc) { case Hexagon::STw_GP_cdnNotPt_V4: return Hexagon::STw_GP_cdnNotPt_nv_V4; - case Hexagon::STriw_GP_cPt_V4: - return Hexagon::STriw_GP_cPt_nv_V4; - - case Hexagon::STriw_GP_cNotPt_V4: - return Hexagon::STriw_GP_cNotPt_nv_V4; - - case Hexagon::STriw_GP_cdnPt_V4: - return Hexagon::STriw_GP_cdnPt_nv_V4; - - case Hexagon::STriw_GP_cdnNotPt_V4: - return Hexagon::STriw_GP_cdnNotPt_nv_V4; } } @@ -819,12 +752,6 @@ static int GetDotNewPredOp(const int opc) { case Hexagon::STb_GP_cNotPt_V4 : return Hexagon::STb_GP_cdnNotPt_V4; - case Hexagon::STrib_GP_cPt_V4 : - return Hexagon::STrib_GP_cdnPt_V4; - - case Hexagon::STrib_GP_cNotPt_V4 : - return Hexagon::STrib_GP_cdnNotPt_V4; - // Store doubleword conditionally case Hexagon::STrid_cPt : return Hexagon::STrid_cdnPt_V4; @@ -856,12 +783,6 @@ static int GetDotNewPredOp(const int opc) { case Hexagon::STd_GP_cNotPt_V4 : return Hexagon::STd_GP_cdnNotPt_V4; - case Hexagon::STrid_GP_cPt_V4 : - return Hexagon::STrid_GP_cdnPt_V4; - - case Hexagon::STrid_GP_cNotPt_V4 : - return Hexagon::STrid_GP_cdnNotPt_V4; - // Store halfword conditionally case Hexagon::STrih_cPt : return Hexagon::STrih_cdnPt_V4; @@ -899,12 +820,6 @@ static int GetDotNewPredOp(const int opc) { case Hexagon::STh_GP_cNotPt_V4 : return Hexagon::STh_GP_cdnNotPt_V4; - case Hexagon::STrih_GP_cPt_V4 : - return Hexagon::STrih_GP_cdnPt_V4; - - case Hexagon::STrih_GP_cNotPt_V4 : - return Hexagon::STrih_GP_cdnNotPt_V4; - // Store word conditionally case Hexagon::STriw_cPt : return Hexagon::STriw_cdnPt_V4; @@ -942,12 +857,6 @@ static int GetDotNewPredOp(const int opc) { case Hexagon::STw_GP_cNotPt_V4 : return Hexagon::STw_GP_cdnNotPt_V4; - case Hexagon::STriw_GP_cPt_V4 : - return Hexagon::STriw_GP_cdnPt_V4; - - case Hexagon::STriw_GP_cNotPt_V4 : - return Hexagon::STriw_GP_cdnNotPt_V4; - // Condtional Jumps case Hexagon::JMP_c: return Hexagon::JMP_cdnPt; @@ -1090,72 +999,36 @@ static int GetDotNewPredOp(const int opc) { // V4 indexed+scaled load - case Hexagon::LDrid_indexed_cPt_V4 : - return Hexagon::LDrid_indexed_cdnPt_V4; - - case Hexagon::LDrid_indexed_cNotPt_V4 : - return Hexagon::LDrid_indexed_cdnNotPt_V4; - case Hexagon::LDrid_indexed_shl_cPt_V4 : return Hexagon::LDrid_indexed_shl_cdnPt_V4; case Hexagon::LDrid_indexed_shl_cNotPt_V4 : return Hexagon::LDrid_indexed_shl_cdnNotPt_V4; - case Hexagon::LDrib_indexed_cPt_V4 : - return Hexagon::LDrib_indexed_cdnPt_V4; - - case Hexagon::LDrib_indexed_cNotPt_V4 : - return Hexagon::LDrib_indexed_cdnNotPt_V4; - case Hexagon::LDrib_indexed_shl_cPt_V4 : return Hexagon::LDrib_indexed_shl_cdnPt_V4; case Hexagon::LDrib_indexed_shl_cNotPt_V4 : return Hexagon::LDrib_indexed_shl_cdnNotPt_V4; - case Hexagon::LDriub_indexed_cPt_V4 : - return Hexagon::LDriub_indexed_cdnPt_V4; - - case Hexagon::LDriub_indexed_cNotPt_V4 : - return Hexagon::LDriub_indexed_cdnNotPt_V4; - case Hexagon::LDriub_indexed_shl_cPt_V4 : return Hexagon::LDriub_indexed_shl_cdnPt_V4; case Hexagon::LDriub_indexed_shl_cNotPt_V4 : return Hexagon::LDriub_indexed_shl_cdnNotPt_V4; - case Hexagon::LDrih_indexed_cPt_V4 : - return Hexagon::LDrih_indexed_cdnPt_V4; - - case Hexagon::LDrih_indexed_cNotPt_V4 : - return Hexagon::LDrih_indexed_cdnNotPt_V4; - case Hexagon::LDrih_indexed_shl_cPt_V4 : return Hexagon::LDrih_indexed_shl_cdnPt_V4; case Hexagon::LDrih_indexed_shl_cNotPt_V4 : return Hexagon::LDrih_indexed_shl_cdnNotPt_V4; - case Hexagon::LDriuh_indexed_cPt_V4 : - return Hexagon::LDriuh_indexed_cdnPt_V4; - - case Hexagon::LDriuh_indexed_cNotPt_V4 : - return Hexagon::LDriuh_indexed_cdnNotPt_V4; - case Hexagon::LDriuh_indexed_shl_cPt_V4 : return Hexagon::LDriuh_indexed_shl_cdnPt_V4; case Hexagon::LDriuh_indexed_shl_cNotPt_V4 : return Hexagon::LDriuh_indexed_shl_cdnNotPt_V4; - case Hexagon::LDriw_indexed_cPt_V4 : - return Hexagon::LDriw_indexed_cdnPt_V4; - - case Hexagon::LDriw_indexed_cNotPt_V4 : - return Hexagon::LDriw_indexed_cdnNotPt_V4; - case Hexagon::LDriw_indexed_shl_cPt_V4 : return Hexagon::LDriw_indexed_shl_cdnPt_V4; @@ -1200,42 +1073,6 @@ static int GetDotNewPredOp(const int opc) { case Hexagon::LDw_GP_cNotPt_V4: return Hexagon::LDw_GP_cdnNotPt_V4; - case Hexagon::LDrid_GP_cPt_V4: - return Hexagon::LDrid_GP_cdnPt_V4; - - case Hexagon::LDrid_GP_cNotPt_V4: - return Hexagon::LDrid_GP_cdnNotPt_V4; - - case Hexagon::LDrib_GP_cPt_V4: - return Hexagon::LDrib_GP_cdnPt_V4; - - case Hexagon::LDrib_GP_cNotPt_V4: - return Hexagon::LDrib_GP_cdnNotPt_V4; - - case Hexagon::LDriub_GP_cPt_V4: - return Hexagon::LDriub_GP_cdnPt_V4; - - case Hexagon::LDriub_GP_cNotPt_V4: - return Hexagon::LDriub_GP_cdnNotPt_V4; - - case Hexagon::LDrih_GP_cPt_V4: - return Hexagon::LDrih_GP_cdnPt_V4; - - case Hexagon::LDrih_GP_cNotPt_V4: - return Hexagon::LDrih_GP_cdnNotPt_V4; - - case Hexagon::LDriuh_GP_cPt_V4: - return Hexagon::LDriuh_GP_cdnPt_V4; - - case Hexagon::LDriuh_GP_cNotPt_V4: - return Hexagon::LDriuh_GP_cdnNotPt_V4; - - case Hexagon::LDriw_GP_cPt_V4: - return Hexagon::LDriw_GP_cdnPt_V4; - - case Hexagon::LDriw_GP_cNotPt_V4: - return Hexagon::LDriw_GP_cdnNotPt_V4; - // Conditional store new-value byte case Hexagon::STrib_cPt_nv_V4 : return Hexagon::STrib_cdnPt_nv_V4; @@ -1263,12 +1100,6 @@ static int GetDotNewPredOp(const int opc) { case Hexagon::STb_GP_cNotPt_nv_V4 : return Hexagon::STb_GP_cdnNotPt_nv_V4; - case Hexagon::STrib_GP_cPt_nv_V4 : - return Hexagon::STrib_GP_cdnPt_nv_V4; - - case Hexagon::STrib_GP_cNotPt_nv_V4 : - return Hexagon::STrib_GP_cdnNotPt_nv_V4; - // Conditional store new-value halfword case Hexagon::STrih_cPt_nv_V4 : return Hexagon::STrih_cdnPt_nv_V4; @@ -1296,12 +1127,6 @@ static int GetDotNewPredOp(const int opc) { case Hexagon::STh_GP_cNotPt_nv_V4 : return Hexagon::STh_GP_cdnNotPt_nv_V4; - case Hexagon::STrih_GP_cPt_nv_V4 : - return Hexagon::STrih_GP_cdnPt_nv_V4; - - case Hexagon::STrih_GP_cNotPt_nv_V4 : - return Hexagon::STrih_GP_cdnNotPt_nv_V4; - // Conditional store new-value word case Hexagon::STriw_cPt_nv_V4 : return Hexagon::STriw_cdnPt_nv_V4; @@ -1329,12 +1154,6 @@ static int GetDotNewPredOp(const int opc) { case Hexagon::STw_GP_cNotPt_nv_V4 : return Hexagon::STw_GP_cdnNotPt_nv_V4; - case Hexagon::STriw_GP_cPt_nv_V4 : - return Hexagon::STriw_GP_cdnPt_nv_V4; - - case Hexagon::STriw_GP_cNotPt_nv_V4 : - return Hexagon::STriw_GP_cdnNotPt_nv_V4; - // Conditional add case Hexagon::ADD_ri_cPt : return Hexagon::ADD_ri_cdnPt; @@ -1621,72 +1440,36 @@ static int GetDotOldOp(const int opc) { // V4 indexed+scaled Load - case Hexagon::LDrid_indexed_cdnPt_V4 : - return Hexagon::LDrid_indexed_cPt_V4; - - case Hexagon::LDrid_indexed_cdnNotPt_V4 : - return Hexagon::LDrid_indexed_cNotPt_V4; - case Hexagon::LDrid_indexed_shl_cdnPt_V4 : return Hexagon::LDrid_indexed_shl_cPt_V4; case Hexagon::LDrid_indexed_shl_cdnNotPt_V4 : return Hexagon::LDrid_indexed_shl_cNotPt_V4; - case Hexagon::LDrib_indexed_cdnPt_V4 : - return Hexagon::LDrib_indexed_cPt_V4; - - case Hexagon::LDrib_indexed_cdnNotPt_V4 : - return Hexagon::LDrib_indexed_cNotPt_V4; - case Hexagon::LDrib_indexed_shl_cdnPt_V4 : return Hexagon::LDrib_indexed_shl_cPt_V4; case Hexagon::LDrib_indexed_shl_cdnNotPt_V4 : return Hexagon::LDrib_indexed_shl_cNotPt_V4; - case Hexagon::LDriub_indexed_cdnPt_V4 : - return Hexagon::LDriub_indexed_cPt_V4; - - case Hexagon::LDriub_indexed_cdnNotPt_V4 : - return Hexagon::LDriub_indexed_cNotPt_V4; - case Hexagon::LDriub_indexed_shl_cdnPt_V4 : return Hexagon::LDriub_indexed_shl_cPt_V4; case Hexagon::LDriub_indexed_shl_cdnNotPt_V4 : return Hexagon::LDriub_indexed_shl_cNotPt_V4; - case Hexagon::LDrih_indexed_cdnPt_V4 : - return Hexagon::LDrih_indexed_cPt_V4; - - case Hexagon::LDrih_indexed_cdnNotPt_V4 : - return Hexagon::LDrih_indexed_cNotPt_V4; - case Hexagon::LDrih_indexed_shl_cdnPt_V4 : return Hexagon::LDrih_indexed_shl_cPt_V4; case Hexagon::LDrih_indexed_shl_cdnNotPt_V4 : return Hexagon::LDrih_indexed_shl_cNotPt_V4; - case Hexagon::LDriuh_indexed_cdnPt_V4 : - return Hexagon::LDriuh_indexed_cPt_V4; - - case Hexagon::LDriuh_indexed_cdnNotPt_V4 : - return Hexagon::LDriuh_indexed_cNotPt_V4; - case Hexagon::LDriuh_indexed_shl_cdnPt_V4 : return Hexagon::LDriuh_indexed_shl_cPt_V4; case Hexagon::LDriuh_indexed_shl_cdnNotPt_V4 : return Hexagon::LDriuh_indexed_shl_cNotPt_V4; - case Hexagon::LDriw_indexed_cdnPt_V4 : - return Hexagon::LDriw_indexed_cPt_V4; - - case Hexagon::LDriw_indexed_cdnNotPt_V4 : - return Hexagon::LDriw_indexed_cNotPt_V4; - case Hexagon::LDriw_indexed_shl_cdnPt_V4 : return Hexagon::LDriw_indexed_shl_cPt_V4; @@ -1731,42 +1514,6 @@ static int GetDotOldOp(const int opc) { case Hexagon::LDw_GP_cdnNotPt_V4: return Hexagon::LDw_GP_cNotPt_V4; - case Hexagon::LDrid_GP_cdnPt_V4: - return Hexagon::LDrid_GP_cPt_V4; - - case Hexagon::LDrid_GP_cdnNotPt_V4: - return Hexagon::LDrid_GP_cNotPt_V4; - - case Hexagon::LDrib_GP_cdnPt_V4: - return Hexagon::LDrib_GP_cPt_V4; - - case Hexagon::LDrib_GP_cdnNotPt_V4: - return Hexagon::LDrib_GP_cNotPt_V4; - - case Hexagon::LDriub_GP_cdnPt_V4: - return Hexagon::LDriub_GP_cPt_V4; - - case Hexagon::LDriub_GP_cdnNotPt_V4: - return Hexagon::LDriub_GP_cNotPt_V4; - - case Hexagon::LDrih_GP_cdnPt_V4: - return Hexagon::LDrih_GP_cPt_V4; - - case Hexagon::LDrih_GP_cdnNotPt_V4: - return Hexagon::LDrih_GP_cNotPt_V4; - - case Hexagon::LDriuh_GP_cdnPt_V4: - return Hexagon::LDriuh_GP_cPt_V4; - - case Hexagon::LDriuh_GP_cdnNotPt_V4: - return Hexagon::LDriuh_GP_cNotPt_V4; - - case Hexagon::LDriw_GP_cdnPt_V4: - return Hexagon::LDriw_GP_cPt_V4; - - case Hexagon::LDriw_GP_cdnNotPt_V4: - return Hexagon::LDriw_GP_cNotPt_V4; - // Conditional add case Hexagon::ADD_ri_cdnPt : @@ -1900,16 +1647,6 @@ static int GetDotOldOp(const int opc) { case Hexagon::STb_GP_cNotPt_nv_V4: return Hexagon::STb_GP_cNotPt_V4; - case Hexagon::STrib_GP_cdnPt_nv_V4: - case Hexagon::STrib_GP_cdnPt_V4: - case Hexagon::STrib_GP_cPt_nv_V4: - return Hexagon::STrib_GP_cPt_V4; - - case Hexagon::STrib_GP_cdnNotPt_nv_V4: - case Hexagon::STrib_GP_cdnNotPt_V4: - case Hexagon::STrib_GP_cNotPt_nv_V4: - return Hexagon::STrib_GP_cNotPt_V4; - // Store new-value byte - unconditional case Hexagon::STrib_nv_V4: return Hexagon::STrib; @@ -1923,9 +1660,6 @@ static int GetDotOldOp(const int opc) { case Hexagon::STrib_shl_nv_V4: return Hexagon::STrib_shl_V4; - case Hexagon::STrib_GP_nv_V4: - return Hexagon::STrib_GP_V4; - case Hexagon::STb_GP_nv_V4: return Hexagon::STb_GP_V4; @@ -1989,16 +1723,6 @@ static int GetDotOldOp(const int opc) { case Hexagon::STh_GP_cNotPt_nv_V4: return Hexagon::STh_GP_cNotPt_V4; - case Hexagon::STrih_GP_cdnPt_nv_V4: - case Hexagon::STrih_GP_cdnPt_V4: - case Hexagon::STrih_GP_cPt_nv_V4: - return Hexagon::STrih_GP_cPt_V4; - - case Hexagon::STrih_GP_cdnNotPt_nv_V4: - case Hexagon::STrih_GP_cdnNotPt_V4: - case Hexagon::STrih_GP_cNotPt_nv_V4: - return Hexagon::STrih_GP_cNotPt_V4; - // Store new-value halfword - unconditional case Hexagon::STrih_nv_V4: @@ -2013,9 +1737,6 @@ static int GetDotOldOp(const int opc) { case Hexagon::STrih_shl_nv_V4: return Hexagon::STrih_shl_V4; - case Hexagon::STrih_GP_nv_V4: - return Hexagon::STrih_GP_V4; - case Hexagon::STh_GP_nv_V4: return Hexagon::STh_GP_V4; @@ -2080,16 +1801,6 @@ static int GetDotOldOp(const int opc) { case Hexagon::STw_GP_cNotPt_nv_V4: return Hexagon::STw_GP_cNotPt_V4; - case Hexagon::STriw_GP_cdnPt_nv_V4: - case Hexagon::STriw_GP_cdnPt_V4: - case Hexagon::STriw_GP_cPt_nv_V4: - return Hexagon::STriw_GP_cPt_V4; - - case Hexagon::STriw_GP_cdnNotPt_nv_V4: - case Hexagon::STriw_GP_cdnNotPt_V4: - case Hexagon::STriw_GP_cNotPt_nv_V4: - return Hexagon::STriw_GP_cNotPt_V4; - // Store new-value word - unconditional case Hexagon::STriw_nv_V4: @@ -2104,9 +1815,6 @@ static int GetDotOldOp(const int opc) { case Hexagon::STriw_shl_nv_V4: return Hexagon::STriw_shl_V4; - case Hexagon::STriw_GP_nv_V4: - return Hexagon::STriw_GP_V4; - case Hexagon::STw_GP_nv_V4: return Hexagon::STw_GP_V4; @@ -2145,11 +1853,6 @@ static int GetDotOldOp(const int opc) { case Hexagon::STd_GP_cdnNotPt_V4 : return Hexagon::STd_GP_cNotPt_V4; - case Hexagon::STrid_GP_cdnPt_V4 : - return Hexagon::STrid_GP_cPt_V4; - - case Hexagon::STrid_GP_cdnNotPt_V4 : - return Hexagon::STrid_GP_cNotPt_V4; } } @@ -2247,28 +1950,16 @@ static bool GetPredicateSense(MachineInstr* MI, case Hexagon::LDriub_indexed_cdnPt : case Hexagon::POST_LDriub_cPt : case Hexagon::POST_LDriub_cdnPt_V4 : - case Hexagon::LDrid_indexed_cPt_V4 : - case Hexagon::LDrid_indexed_cdnPt_V4 : case Hexagon::LDrid_indexed_shl_cPt_V4 : case Hexagon::LDrid_indexed_shl_cdnPt_V4 : - case Hexagon::LDrib_indexed_cPt_V4 : - case Hexagon::LDrib_indexed_cdnPt_V4 : case Hexagon::LDrib_indexed_shl_cPt_V4 : case Hexagon::LDrib_indexed_shl_cdnPt_V4 : - case Hexagon::LDriub_indexed_cPt_V4 : - case Hexagon::LDriub_indexed_cdnPt_V4 : case Hexagon::LDriub_indexed_shl_cPt_V4 : case Hexagon::LDriub_indexed_shl_cdnPt_V4 : - case Hexagon::LDrih_indexed_cPt_V4 : - case Hexagon::LDrih_indexed_cdnPt_V4 : case Hexagon::LDrih_indexed_shl_cPt_V4 : case Hexagon::LDrih_indexed_shl_cdnPt_V4 : - case Hexagon::LDriuh_indexed_cPt_V4 : - case Hexagon::LDriuh_indexed_cdnPt_V4 : case Hexagon::LDriuh_indexed_shl_cPt_V4 : case Hexagon::LDriuh_indexed_shl_cdnPt_V4 : - case Hexagon::LDriw_indexed_cPt_V4 : - case Hexagon::LDriw_indexed_cdnPt_V4 : case Hexagon::LDriw_indexed_shl_cPt_V4 : case Hexagon::LDriw_indexed_shl_cdnPt_V4 : case Hexagon::ADD_ri_cPt : @@ -2297,42 +1988,22 @@ static bool GetPredicateSense(MachineInstr* MI, case Hexagon::ZXTB_cdnPt_V4 : case Hexagon::ZXTH_cPt_V4 : case Hexagon::ZXTH_cdnPt_V4 : - case Hexagon::LDrid_GP_cPt_V4 : - case Hexagon::LDrib_GP_cPt_V4 : - case Hexagon::LDriub_GP_cPt_V4 : - case Hexagon::LDrih_GP_cPt_V4 : - case Hexagon::LDriuh_GP_cPt_V4 : - case Hexagon::LDriw_GP_cPt_V4 : case Hexagon::LDd_GP_cPt_V4 : case Hexagon::LDb_GP_cPt_V4 : case Hexagon::LDub_GP_cPt_V4 : case Hexagon::LDh_GP_cPt_V4 : case Hexagon::LDuh_GP_cPt_V4 : case Hexagon::LDw_GP_cPt_V4 : - case Hexagon::STrid_GP_cPt_V4 : - case Hexagon::STrib_GP_cPt_V4 : - case Hexagon::STrih_GP_cPt_V4 : - case Hexagon::STriw_GP_cPt_V4 : case Hexagon::STd_GP_cPt_V4 : case Hexagon::STb_GP_cPt_V4 : case Hexagon::STh_GP_cPt_V4 : case Hexagon::STw_GP_cPt_V4 : - case Hexagon::LDrid_GP_cdnPt_V4 : - case Hexagon::LDrib_GP_cdnPt_V4 : - case Hexagon::LDriub_GP_cdnPt_V4 : - case Hexagon::LDrih_GP_cdnPt_V4 : - case Hexagon::LDriuh_GP_cdnPt_V4 : - case Hexagon::LDriw_GP_cdnPt_V4 : case Hexagon::LDd_GP_cdnPt_V4 : case Hexagon::LDb_GP_cdnPt_V4 : case Hexagon::LDub_GP_cdnPt_V4 : case Hexagon::LDh_GP_cdnPt_V4 : case Hexagon::LDuh_GP_cdnPt_V4 : case Hexagon::LDw_GP_cdnPt_V4 : - case Hexagon::STrid_GP_cdnPt_V4 : - case Hexagon::STrib_GP_cdnPt_V4 : - case Hexagon::STrih_GP_cdnPt_V4 : - case Hexagon::STriw_GP_cdnPt_V4 : case Hexagon::STd_GP_cdnPt_V4 : case Hexagon::STb_GP_cdnPt_V4 : case Hexagon::STh_GP_cdnPt_V4 : @@ -2418,28 +2089,16 @@ static bool GetPredicateSense(MachineInstr* MI, case Hexagon::LDriub_indexed_cdnNotPt : case Hexagon::POST_LDriub_cNotPt : case Hexagon::POST_LDriub_cdnNotPt_V4 : - case Hexagon::LDrid_indexed_cNotPt_V4 : - case Hexagon::LDrid_indexed_cdnNotPt_V4 : case Hexagon::LDrid_indexed_shl_cNotPt_V4 : case Hexagon::LDrid_indexed_shl_cdnNotPt_V4 : - case Hexagon::LDrib_indexed_cNotPt_V4 : - case Hexagon::LDrib_indexed_cdnNotPt_V4 : case Hexagon::LDrib_indexed_shl_cNotPt_V4 : case Hexagon::LDrib_indexed_shl_cdnNotPt_V4 : - case Hexagon::LDriub_indexed_cNotPt_V4 : - case Hexagon::LDriub_indexed_cdnNotPt_V4 : case Hexagon::LDriub_indexed_shl_cNotPt_V4 : case Hexagon::LDriub_indexed_shl_cdnNotPt_V4 : - case Hexagon::LDrih_indexed_cNotPt_V4 : - case Hexagon::LDrih_indexed_cdnNotPt_V4 : case Hexagon::LDrih_indexed_shl_cNotPt_V4 : case Hexagon::LDrih_indexed_shl_cdnNotPt_V4 : - case Hexagon::LDriuh_indexed_cNotPt_V4 : - case Hexagon::LDriuh_indexed_cdnNotPt_V4 : case Hexagon::LDriuh_indexed_shl_cNotPt_V4 : case Hexagon::LDriuh_indexed_shl_cdnNotPt_V4 : - case Hexagon::LDriw_indexed_cNotPt_V4 : - case Hexagon::LDriw_indexed_cdnNotPt_V4 : case Hexagon::LDriw_indexed_shl_cNotPt_V4 : case Hexagon::LDriw_indexed_shl_cdnNotPt_V4 : case Hexagon::ADD_ri_cNotPt : @@ -2469,42 +2128,22 @@ static bool GetPredicateSense(MachineInstr* MI, case Hexagon::ZXTH_cNotPt_V4 : case Hexagon::ZXTH_cdnNotPt_V4 : - case Hexagon::LDrid_GP_cNotPt_V4 : - case Hexagon::LDrib_GP_cNotPt_V4 : - case Hexagon::LDriub_GP_cNotPt_V4 : - case Hexagon::LDrih_GP_cNotPt_V4 : - case Hexagon::LDriuh_GP_cNotPt_V4 : - case Hexagon::LDriw_GP_cNotPt_V4 : case Hexagon::LDd_GP_cNotPt_V4 : case Hexagon::LDb_GP_cNotPt_V4 : case Hexagon::LDub_GP_cNotPt_V4 : case Hexagon::LDh_GP_cNotPt_V4 : case Hexagon::LDuh_GP_cNotPt_V4 : case Hexagon::LDw_GP_cNotPt_V4 : - case Hexagon::STrid_GP_cNotPt_V4 : - case Hexagon::STrib_GP_cNotPt_V4 : - case Hexagon::STrih_GP_cNotPt_V4 : - case Hexagon::STriw_GP_cNotPt_V4 : case Hexagon::STd_GP_cNotPt_V4 : case Hexagon::STb_GP_cNotPt_V4 : case Hexagon::STh_GP_cNotPt_V4 : case Hexagon::STw_GP_cNotPt_V4 : - case Hexagon::LDrid_GP_cdnNotPt_V4 : - case Hexagon::LDrib_GP_cdnNotPt_V4 : - case Hexagon::LDriub_GP_cdnNotPt_V4 : - case Hexagon::LDrih_GP_cdnNotPt_V4 : - case Hexagon::LDriuh_GP_cdnNotPt_V4 : - case Hexagon::LDriw_GP_cdnNotPt_V4 : case Hexagon::LDd_GP_cdnNotPt_V4 : case Hexagon::LDb_GP_cdnNotPt_V4 : case Hexagon::LDub_GP_cdnNotPt_V4 : case Hexagon::LDh_GP_cdnNotPt_V4 : case Hexagon::LDuh_GP_cdnNotPt_V4 : case Hexagon::LDw_GP_cdnNotPt_V4 : - case Hexagon::STrid_GP_cdnNotPt_V4 : - case Hexagon::STrib_GP_cdnNotPt_V4 : - case Hexagon::STrih_GP_cdnNotPt_V4 : - case Hexagon::STriw_GP_cdnNotPt_V4 : case Hexagon::STd_GP_cdnNotPt_V4 : case Hexagon::STb_GP_cdnNotPt_V4 : case Hexagon::STh_GP_cdnNotPt_V4 : @@ -2516,7 +2155,8 @@ static bool GetPredicateSense(MachineInstr* MI, } bool HexagonPacketizerList::isDotNewInst(MachineInstr* MI) { - if (isNewValueInst(MI)) + const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; + if (QII->isNewValueInst(MI)) return true; switch (MI->getOpcode()) { @@ -2561,28 +2201,16 @@ bool HexagonPacketizerList::isDotNewInst(MachineInstr* MI) { case Hexagon::POST_LDriub_cdnPt_V4 : case Hexagon::POST_LDriub_cdnNotPt_V4 : - case Hexagon::LDrid_indexed_cdnPt_V4 : - case Hexagon::LDrid_indexed_cdnNotPt_V4 : case Hexagon::LDrid_indexed_shl_cdnPt_V4 : case Hexagon::LDrid_indexed_shl_cdnNotPt_V4 : - case Hexagon::LDrib_indexed_cdnPt_V4 : - case Hexagon::LDrib_indexed_cdnNotPt_V4 : case Hexagon::LDrib_indexed_shl_cdnPt_V4 : case Hexagon::LDrib_indexed_shl_cdnNotPt_V4 : - case Hexagon::LDriub_indexed_cdnPt_V4 : - case Hexagon::LDriub_indexed_cdnNotPt_V4 : case Hexagon::LDriub_indexed_shl_cdnPt_V4 : case Hexagon::LDriub_indexed_shl_cdnNotPt_V4 : - case Hexagon::LDrih_indexed_cdnPt_V4 : - case Hexagon::LDrih_indexed_cdnNotPt_V4 : case Hexagon::LDrih_indexed_shl_cdnPt_V4 : case Hexagon::LDrih_indexed_shl_cdnNotPt_V4 : - case Hexagon::LDriuh_indexed_cdnPt_V4 : - case Hexagon::LDriuh_indexed_cdnNotPt_V4 : case Hexagon::LDriuh_indexed_shl_cdnPt_V4 : case Hexagon::LDriuh_indexed_shl_cdnNotPt_V4 : - case Hexagon::LDriw_indexed_cdnPt_V4 : - case Hexagon::LDriw_indexed_cdnNotPt_V4 : case Hexagon::LDriw_indexed_shl_cdnPt_V4 : case Hexagon::LDriw_indexed_shl_cdnNotPt_V4 : @@ -2678,27 +2306,7 @@ bool HexagonPacketizerList::isDotNewInst(MachineInstr* MI) { case Hexagon::LDuh_GP_cdnNotPt_V4: case Hexagon::LDw_GP_cdnPt_V4: case Hexagon::LDw_GP_cdnNotPt_V4: - case Hexagon::LDrid_GP_cdnPt_V4: - case Hexagon::LDrid_GP_cdnNotPt_V4: - case Hexagon::LDrib_GP_cdnPt_V4: - case Hexagon::LDrib_GP_cdnNotPt_V4: - case Hexagon::LDriub_GP_cdnPt_V4: - case Hexagon::LDriub_GP_cdnNotPt_V4: - case Hexagon::LDrih_GP_cdnPt_V4: - case Hexagon::LDrih_GP_cdnNotPt_V4: - case Hexagon::LDriuh_GP_cdnPt_V4: - case Hexagon::LDriuh_GP_cdnNotPt_V4: - case Hexagon::LDriw_GP_cdnPt_V4: - case Hexagon::LDriw_GP_cdnNotPt_V4: - - case Hexagon::STrid_GP_cdnPt_V4: - case Hexagon::STrid_GP_cdnNotPt_V4: - case Hexagon::STrib_GP_cdnPt_V4: - case Hexagon::STrib_GP_cdnNotPt_V4: - case Hexagon::STrih_GP_cdnPt_V4: - case Hexagon::STrih_GP_cdnNotPt_V4: - case Hexagon::STriw_GP_cdnPt_V4: - case Hexagon::STriw_GP_cdnNotPt_V4: + case Hexagon::STd_GP_cdnPt_V4: case Hexagon::STd_GP_cdnNotPt_V4: case Hexagon::STb_GP_cdnPt_V4: @@ -3276,13 +2884,13 @@ bool HexagonPacketizerList::isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) { // dealloc_return and memop always take SLOT0. // Arch spec 3.4.4.2 if (QRI->Subtarget.hasV4TOps()) { - - if (MCIDI.mayStore() && MCIDJ.mayStore() && isNewValueInst(J)) { + if (MCIDI.mayStore() && MCIDJ.mayStore() && + (QII->isNewValueInst(J) || QII->isMemOp(J) || QII->isMemOp(I))) { Dependence = true; return false; } - if ( (QII->isMemOp(J) && MCIDI.mayStore()) + if ((QII->isMemOp(J) && MCIDI.mayStore()) || (MCIDJ.mayStore() && QII->isMemOp(I)) || (QII->isMemOp(J) && QII->isMemOp(I))) { Dependence = true; @@ -3579,7 +3187,7 @@ HexagonPacketizerList::addToPacket(MachineInstr *MI) { MachineInstr *nvjMI = MII; assert(ResourceTracker->canReserveResources(MI)); ResourceTracker->reserveResources(MI); - if (QII->isExtended(MI) && + if ((QII->isExtended(MI) || QII->isConstExtended(MI)) && !tryAllocateResourcesForConstExt(MI)) { endPacket(MBB, MI); ResourceTracker->reserveResources(MI); @@ -3599,7 +3207,7 @@ HexagonPacketizerList::addToPacket(MachineInstr *MI) { && (!tryAllocateResourcesForConstExt(nvjMI) || !ResourceTracker->canReserveResources(nvjMI))) || // For non-extended instruction, no need to allocate extra 4 bytes. - (!QII->isExtended(nvjMI) && + (!QII->isExtended(nvjMI) && !ResourceTracker->canReserveResources(nvjMI))) { endPacket(MBB, MI); @@ -3615,7 +3223,7 @@ HexagonPacketizerList::addToPacket(MachineInstr *MI) { CurrentPacketMIs.push_back(MI); CurrentPacketMIs.push_back(nvjMI); } else { - if ( QII->isExtended(MI) + if ( (QII->isExtended(MI) || QII->isConstExtended(MI)) && ( !tryAllocateResourcesForConstExt(MI) || !ResourceTracker->canReserveResources(MI))) { diff --git a/lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.cpp b/lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.cpp index c700354bda..36da6dfcc3 100644 --- a/lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.cpp +++ b/lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.cpp @@ -12,14 +12,14 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "asm-printer" -#include "HexagonInstPrinter.h" -#include "Hexagon.h" #include "HexagonAsmPrinter.h" -#include "HexagonMCInst.h" +#include "Hexagon.h" +#include "HexagonInstPrinter.h" +#include "MCTargetDesc/HexagonMCInst.h" +#include "llvm/MC/MCInst.h" #include "llvm/ADT/StringExtras.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCInst.h" #include "llvm/Support/raw_ostream.h" #include <cstdio> @@ -28,6 +28,8 @@ using namespace llvm; #define GET_INSTRUCTION_NAME #include "HexagonGenAsmWriter.inc" +const char HexagonInstPrinter::PacketPadding = '\t'; + StringRef HexagonInstPrinter::getOpcodeName(unsigned Opcode) const { return MII.getName(Opcode); } @@ -43,43 +45,42 @@ void HexagonInstPrinter::printInst(const MCInst *MI, raw_ostream &O, void HexagonInstPrinter::printInst(const HexagonMCInst *MI, raw_ostream &O, StringRef Annot) { - const char packetPadding[] = " "; const char startPacket = '{', endPacket = '}'; // TODO: add outer HW loop when it's supported too. if (MI->getOpcode() == Hexagon::ENDLOOP0) { // Ending a harware loop is different from ending an regular packet. - assert(MI->isEndPacket() && "Loop end must also end the packet"); + assert(MI->isPacketEnd() && "Loop-end must also end the packet"); - if (MI->isStartPacket()) { + if (MI->isPacketStart()) { // There must be a packet to end a loop. // FIXME: when shuffling is always run, this shouldn't be needed. HexagonMCInst Nop; StringRef NoAnnot; Nop.setOpcode (Hexagon::NOP); - Nop.setStartPacket (MI->isStartPacket()); + Nop.setPacketStart (MI->isPacketStart()); printInst (&Nop, O, NoAnnot); } // Close the packet. - if (MI->isEndPacket()) - O << packetPadding << endPacket; + if (MI->isPacketEnd()) + O << PacketPadding << endPacket; printInstruction(MI, O); } else { // Prefix the insn opening the packet. - if (MI->isStartPacket()) - O << packetPadding << startPacket << '\n'; + if (MI->isPacketStart()) + O << PacketPadding << startPacket << '\n'; printInstruction(MI, O); // Suffix the insn closing the packet. - if (MI->isEndPacket()) + if (MI->isPacketEnd()) // Suffix the packet in a new line always, since the GNU assembler has // issues with a closing brace on the same line as CONST{32,64}. - O << '\n' << packetPadding << endPacket; + O << '\n' << PacketPadding << endPacket; } printAnnotation(O, Annot); @@ -102,12 +103,23 @@ void HexagonInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, void HexagonInstPrinter::printImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) const { - O << MI->getOperand(OpNo).getImm(); + const MCOperand& MO = MI->getOperand(OpNo); + + if(MO.isExpr()) { + O << *MO.getExpr(); + } else if(MO.isImm()) { + O << MI->getOperand(OpNo).getImm(); + } else { + llvm_unreachable("Unknown operand"); + } } void HexagonInstPrinter::printExtOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) const { - O << MI->getOperand(OpNo).getImm(); + const HexagonMCInst *HMCI = static_cast<const HexagonMCInst*>(MI); + if (HMCI->isConstExtended()) + O << "#"; + printOperand(MI, OpNo, O); } void HexagonInstPrinter::printUnsignedImmOperand(const MCInst *MI, diff --git a/lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.h b/lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.h index 902a32352f..d0cef683da 100644 --- a/lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.h +++ b/lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.h @@ -14,16 +14,18 @@ #ifndef HEXAGONINSTPRINTER_H #define HEXAGONINSTPRINTER_H -#include "HexagonMCInst.h" #include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCInstrInfo.h" namespace llvm { + class HexagonMCInst; + class HexagonInstPrinter : public MCInstPrinter { public: explicit HexagonInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI) - : MCInstPrinter(MAI, MII, MRI) {} + : MCInstPrinter(MAI, MII, MRI), MII(MII) {} virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot); void printInst(const HexagonMCInst *MI, raw_ostream &O, StringRef Annot); @@ -65,10 +67,19 @@ namespace llvm { void printSymbolLo(const MCInst *MI, unsigned OpNo, raw_ostream &O) const { printSymbol(MI, OpNo, O, false); } - bool isConstExtended(const MCInst *MI) const; + const MCInstrInfo &getMII() const { + return MII; + } + protected: void printSymbol(const MCInst *MI, unsigned OpNo, raw_ostream &O, bool hi) const; + + static const char PacketPadding; + + private: + const MCInstrInfo &MII; + }; } // end namespace llvm diff --git a/lib/Target/Hexagon/InstPrinter/LLVMBuild.txt b/lib/Target/Hexagon/InstPrinter/LLVMBuild.txt index 8678401fee..59849aa7e1 100644 --- a/lib/Target/Hexagon/InstPrinter/LLVMBuild.txt +++ b/lib/Target/Hexagon/InstPrinter/LLVMBuild.txt @@ -19,5 +19,5 @@ type = Library name = HexagonAsmPrinter parent = Hexagon -required_libraries = MC Support +required_libraries = HexagonDesc MC Support add_to_library_groups = Hexagon diff --git a/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt b/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt index 8e3da99404..62b9b600ce 100644 --- a/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt +++ b/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt @@ -1,6 +1,7 @@ add_llvm_library(LLVMHexagonDesc - HexagonMCTargetDesc.cpp HexagonMCAsmInfo.cpp + HexagonMCInst.cpp + HexagonMCTargetDesc.cpp ) add_dependencies(LLVMHexagonDesc HexagonCommonTableGen) diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h b/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h index 9fc826f412..d4a93b5c87 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h @@ -17,6 +17,9 @@ #ifndef HEXAGONBASEINFO_H #define HEXAGONBASEINFO_H +#include "HexagonMCTargetDesc.h" +#include "llvm/Support/ErrorHandling.h" + namespace llvm { /// HexagonII - This namespace holds all of the target specific flags that @@ -28,19 +31,19 @@ namespace HexagonII { // Insn types. // *** Must match HexagonInstrFormat*.td *** enum Type { - TypePSEUDO = 0, - TypeALU32 = 1, - TypeCR = 2, - TypeJR = 3, - TypeJ = 4, - TypeLD = 5, - TypeST = 6, - TypeSYSTEM = 7, - TypeXTYPE = 8, - TypeMEMOP = 9, - TypeNV = 10, - TypePREFIX = 30, // Such as extenders. - TypeMARKER = 31 // Such as end of a HW loop. + TypePSEUDO = 0, + TypeALU32 = 1, + TypeCR = 2, + TypeJR = 3, + TypeJ = 4, + TypeLD = 5, + TypeST = 6, + TypeSYSTEM = 7, + TypeXTYPE = 8, + TypeMEMOP = 9, + TypeNV = 10, + TypePREFIX = 30, // Such as extenders. + TypeENDLOOP = 31 // Such as end of a HW loop. }; enum SubTarget { @@ -65,6 +68,14 @@ namespace HexagonII { BaseRegOffset = 5 // Indirect with register offset }; + enum MemAccessSize { + NoMemAccess = 0, // Not a memory acces instruction. + ByteAccess = 1, // Byte access instruction (memb). + HalfWordAccess = 2, // Half word access instruction (memh). + WordAccess = 3, // Word access instrution (memw). + DoubleWordAccess = 4 // Double word access instruction (memd) + }; + // MCInstrDesc TSFlags // *** Must match HexagonInstrFormat*.td *** enum { @@ -79,49 +90,92 @@ namespace HexagonII { // Predicated instructions. PredicatedPos = 6, PredicatedMask = 0x1, - PredicatedNewPos = 7, + PredicatedFalsePos = 7, + PredicatedFalseMask = 0x1, + PredicatedNewPos = 8, PredicatedNewMask = 0x1, - // Stores that can be newified. - mayNVStorePos = 8, + // New-Value consumer instructions. + NewValuePos = 9, + NewValueMask = 0x1, + + // New-Value producer instructions. + hasNewValuePos = 10, + hasNewValueMask = 0x1, + + // Which operand consumes or produces a new value. + NewValueOpPos = 11, + NewValueOpMask = 0x7, + + // Which bits encode the new value. + NewValueBitsPos = 14, + NewValueBitsMask = 0x3, + + // Stores that can become new-value stores. + mayNVStorePos = 16, mayNVStoreMask = 0x1, - // Dot new value store instructions. - NVStorePos = 9, + // New-value store instructions. + NVStorePos = 17, NVStoreMask = 0x1, // Extendable insns. - ExtendablePos = 10, + ExtendablePos = 18, ExtendableMask = 0x1, // Insns must be extended. - ExtendedPos = 11, + ExtendedPos = 19, ExtendedMask = 0x1, // Which operand may be extended. - ExtendableOpPos = 12, + ExtendableOpPos = 20, ExtendableOpMask = 0x7, // Signed or unsigned range. - ExtentSignedPos = 15, + ExtentSignedPos = 23, ExtentSignedMask = 0x1, // Number of bits of range before extending operand. - ExtentBitsPos = 16, + ExtentBitsPos = 24, ExtentBitsMask = 0x1f, // Valid subtargets - validSubTargetPos = 21, + validSubTargetPos = 29, validSubTargetMask = 0xf, - // Addressing mode for load/store instructions - AddrModePos = 25, - AddrModeMask = 0xf + // Addressing mode for load/store instructions. + AddrModePos = 33, + AddrModeMask = 0x7, - }; + // Access size of memory access instructions (load/store). + MemAccessSizePos = 36, + MemAccesSizeMask = 0x7 + }; // *** The code above must match HexagonInstrFormat*.td *** // + // Hexagon specific MO operand flag mask. + enum HexagonMOTargetFlagVal { + //===------------------------------------------------------------------===// + // Hexagon Specific MachineOperand flags. + MO_NO_FLAG, + + HMOTF_ConstExtended = 1, + + /// MO_PCREL - On a symbol operand, indicates a PC-relative relocation + /// Used for computing a global address for PIC compilations + MO_PCREL, + + /// MO_GOT - Indicates a GOT-relative relocation + MO_GOT, + + // Low or high part of a symbol. + MO_LO16, MO_HI16, + + // Offset from the base of the SDA. + MO_GPREL + }; + } // End namespace HexagonII. } // End namespace llvm. diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.cpp new file mode 100644 index 0000000000..9260b4a276 --- /dev/null +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.cpp @@ -0,0 +1,175 @@ +//===- HexagonMCInst.cpp - Hexagon sub-class of MCInst --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class extends MCInst to allow some Hexagon VLIW annotations. +// +//===----------------------------------------------------------------------===// + +#include "HexagonInstrInfo.h" +#include "MCTargetDesc/HexagonBaseInfo.h" +#include "MCTargetDesc/HexagonMCInst.h" +#include "MCTargetDesc/HexagonMCTargetDesc.h" + +using namespace llvm; + +// Return the slots used by the insn. +unsigned HexagonMCInst::getUnits(const HexagonTargetMachine* TM) const { + const HexagonInstrInfo* QII = TM->getInstrInfo(); + const InstrItineraryData* II = TM->getInstrItineraryData(); + const InstrStage* + IS = II->beginStage(QII->get(this->getOpcode()).getSchedClass()); + + return (IS->getUnits()); +} + +// Return the Hexagon ISA class for the insn. +unsigned HexagonMCInst::getType() const { + const uint64_t F = MCID->TSFlags; + + return ((F >> HexagonII::TypePos) & HexagonII::TypeMask); +} + +// Return whether the insn is an actual insn. +bool HexagonMCInst::isCanon() const { + return (!MCID->isPseudo() && + !isPrefix() && + getType() != HexagonII::TypeENDLOOP); +} + +// Return whether the insn is a prefix. +bool HexagonMCInst::isPrefix() const { + return (getType() == HexagonII::TypePREFIX); +} + +// Return whether the insn is solo, i.e., cannot be in a packet. +bool HexagonMCInst::isSolo() const { + const uint64_t F = MCID->TSFlags; + return ((F >> HexagonII::SoloPos) & HexagonII::SoloMask); +} + +// Return whether the insn is a new-value consumer. +bool HexagonMCInst::isNewValue() const { + const uint64_t F = MCID->TSFlags; + return ((F >> HexagonII::NewValuePos) & HexagonII::NewValueMask); +} + +// Return whether the instruction is a legal new-value producer. +bool HexagonMCInst::hasNewValue() const { + const uint64_t F = MCID->TSFlags; + return ((F >> HexagonII::hasNewValuePos) & HexagonII::hasNewValueMask); +} + +// Return the operand that consumes or produces a new value. +const MCOperand& HexagonMCInst::getNewValue() const { + const uint64_t F = MCID->TSFlags; + const unsigned O = (F >> HexagonII::NewValueOpPos) & + HexagonII::NewValueOpMask; + const MCOperand& MCO = getOperand(O); + + assert ((isNewValue() || hasNewValue()) && MCO.isReg()); + return (MCO); +} + +// Return whether the instruction needs to be constant extended. +// 1) Always return true if the instruction has 'isExtended' flag set. +// +// isExtendable: +// 2) For immediate extended operands, return true only if the value is +// out-of-range. +// 3) For global address, always return true. + +bool HexagonMCInst::isConstExtended(void) const { + if (isExtended()) + return true; + + if (!isExtendable()) + return false; + + short ExtOpNum = getCExtOpNum(); + int MinValue = getMinValue(); + int MaxValue = getMaxValue(); + const MCOperand& MO = getOperand(ExtOpNum); + + // We could be using an instruction with an extendable immediate and shoehorn + // a global address into it. If it is a global address it will be constant + // extended. We do this for COMBINE. + // We currently only handle isGlobal() because it is the only kind of + // object we are going to end up with here for now. + // In the future we probably should add isSymbol(), etc. + if (MO.isExpr()) + return true; + + // If the extendable operand is not 'Immediate' type, the instruction should + // have 'isExtended' flag set. + assert(MO.isImm() && "Extendable operand must be Immediate type"); + + int ImmValue = MO.getImm(); + return (ImmValue < MinValue || ImmValue > MaxValue); +} + +// Return whether the instruction must be always extended. +bool HexagonMCInst::isExtended(void) const { + const uint64_t F = MCID->TSFlags; + return (F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask; +} + +// Return true if the instruction may be extended based on the operand value. +bool HexagonMCInst::isExtendable(void) const { + const uint64_t F = MCID->TSFlags; + return (F >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask; +} + +// Return number of bits in the constant extended operand. +unsigned HexagonMCInst::getBitCount(void) const { + const uint64_t F = MCID->TSFlags; + return ((F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask); +} + +// Return constant extended operand number. +unsigned short HexagonMCInst::getCExtOpNum(void) const { + const uint64_t F = MCID->TSFlags; + return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask); +} + +// Return whether the operand can be constant extended. +bool HexagonMCInst::isOperandExtended(const unsigned short OperandNum) const { + const uint64_t F = MCID->TSFlags; + return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask) + == OperandNum; +} + +// Return the min value that a constant extendable operand can have +// without being extended. +int HexagonMCInst::getMinValue(void) const { + const uint64_t F = MCID->TSFlags; + unsigned isSigned = (F >> HexagonII::ExtentSignedPos) + & HexagonII::ExtentSignedMask; + unsigned bits = (F >> HexagonII::ExtentBitsPos) + & HexagonII::ExtentBitsMask; + + if (isSigned) // if value is signed + return -1 << (bits - 1); + else + return 0; +} + +// Return the max value that a constant extendable operand can have +// without being extended. +int HexagonMCInst::getMaxValue(void) const { + const uint64_t F = MCID->TSFlags; + unsigned isSigned = (F >> HexagonII::ExtentSignedPos) + & HexagonII::ExtentSignedMask; + unsigned bits = (F >> HexagonII::ExtentBitsPos) + & HexagonII::ExtentBitsMask; + + if (isSigned) // if value is signed + return ~(-1 << (bits - 1)); + else + return ~(-1 << bits); +} diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.h new file mode 100644 index 0000000000..3ca71f00b2 --- /dev/null +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.h @@ -0,0 +1,100 @@ +//===- HexagonMCInst.h - Hexagon sub-class of MCInst ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class extends MCInst to allow some VLIW annotations. +// +//===----------------------------------------------------------------------===// + +#ifndef HEXAGONMCINST_H +#define HEXAGONMCINST_H + +#include "HexagonTargetMachine.h" +#include "llvm/MC/MCInst.h" + +namespace llvm { + class MCOperand; + + class HexagonMCInst: public MCInst { + // MCID is set during instruction lowering. + // It is needed in order to access TSFlags for + // use in checking MC instruction properties. + const MCInstrDesc *MCID; + + // Packet start and end markers + unsigned packetStart: 1, packetEnd: 1; + + public: + explicit HexagonMCInst(): + MCInst(), MCID(0), packetStart(0), packetEnd(0) {}; + HexagonMCInst(const MCInstrDesc& mcid): + MCInst(), MCID(&mcid), packetStart(0), packetEnd(0) {}; + + bool isPacketStart() const { return (packetStart); }; + bool isPacketEnd() const { return (packetEnd); }; + void setPacketStart(bool Y) { packetStart = Y; }; + void setPacketEnd(bool Y) { packetEnd = Y; }; + void resetPacket() { setPacketStart(false); setPacketEnd(false); }; + + // Return the slots used by the insn. + unsigned getUnits(const HexagonTargetMachine* TM) const; + + // Return the Hexagon ISA class for the insn. + unsigned getType() const; + + void setDesc(const MCInstrDesc& mcid) { MCID = &mcid; }; + const MCInstrDesc& getDesc(void) const { return *MCID; }; + + // Return whether the insn is an actual insn. + bool isCanon() const; + + // Return whether the insn is a prefix. + bool isPrefix() const; + + // Return whether the insn is solo, i.e., cannot be in a packet. + bool isSolo() const; + + // Return whether the instruction needs to be constant extended. + bool isConstExtended() const; + + // Return constant extended operand number. + unsigned short getCExtOpNum(void) const; + + // Return whether the insn is a new-value consumer. + bool isNewValue() const; + + // Return whether the instruction is a legal new-value producer. + bool hasNewValue() const; + + // Return the operand that consumes or produces a new value. + const MCOperand& getNewValue() const; + + // Return number of bits in the constant extended operand. + unsigned getBitCount(void) const; + + private: + // Return whether the instruction must be always extended. + bool isExtended() const; + + // Return true if the insn may be extended based on the operand value. + bool isExtendable() const; + + // Return true if the operand can be constant extended. + bool isOperandExtended(const unsigned short OperandNum) const; + + // Return the min value that a constant extendable operand can have + // without being extended. + int getMinValue() const; + + // Return the max value that a constant extendable operand can have + // without being extended. + int getMaxValue() const; + }; +} + +#endif diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp index 737789bbb5..6b1d2d1619 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp @@ -13,11 +13,13 @@ #include "HexagonMCTargetDesc.h" #include "HexagonMCAsmInfo.h" +#include "InstPrinter/HexagonInstPrinter.h" +#include "llvm/MC/MachineLocation.h" #include "llvm/MC/MCCodeGenInfo.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/MC/MachineLocation.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" diff --git a/lib/Target/Hexagon/TargetInfo/HexagonTargetInfo.cpp b/lib/Target/Hexagon/TargetInfo/HexagonTargetInfo.cpp index 7aa5dd3b89..40f6c8d23e 100644 --- a/lib/Target/Hexagon/TargetInfo/HexagonTargetInfo.cpp +++ b/lib/Target/Hexagon/TargetInfo/HexagonTargetInfo.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// #include "Hexagon.h" -#include "llvm/Module.h" +#include "llvm/IR/Module.h" #include "llvm/Support/TargetRegistry.h" using namespace llvm; |