diff options
Diffstat (limited to 'contrib/llvm/lib/Target/Hexagon')
48 files changed, 6940 insertions, 8532 deletions
diff --git a/contrib/llvm/lib/Target/Hexagon/Hexagon.h b/contrib/llvm/lib/Target/Hexagon/Hexagon.h index 45f857b..dfbefc8 100644 --- a/contrib/llvm/lib/Target/Hexagon/Hexagon.h +++ b/contrib/llvm/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/contrib/llvm/lib/Target/Hexagon/Hexagon.td b/contrib/llvm/lib/Target/Hexagon/Hexagon.td index 451e562..8a5ee40 100644 --- a/contrib/llvm/lib/Target/Hexagon/Hexagon.td +++ b/contrib/llvm/lib/Target/Hexagon/Hexagon.td @@ -32,6 +32,107 @@ def ArchV5 : SubtargetFeature<"v5", "HexagonArchVersion", "V5", "Hexagon v5">; //===----------------------------------------------------------------------===// +// Hexagon Instruction Predicate Definitions. +//===----------------------------------------------------------------------===// +def HasV2T : Predicate<"Subtarget.hasV2TOps()">; +def HasV2TOnly : Predicate<"Subtarget.hasV2TOpsOnly()">; +def NoV2T : Predicate<"!Subtarget.hasV2TOps()">; +def HasV3T : Predicate<"Subtarget.hasV3TOps()">; +def HasV3TOnly : Predicate<"Subtarget.hasV3TOpsOnly()">; +def NoV3T : Predicate<"!Subtarget.hasV3TOps()">; +def HasV4T : Predicate<"Subtarget.hasV4TOps()">; +def NoV4T : Predicate<"!Subtarget.hasV4TOps()">; +def HasV5T : Predicate<"Subtarget.hasV5TOps()">; +def NoV5T : Predicate<"!Subtarget.hasV5TOps()">; +def UseMEMOP : Predicate<"Subtarget.useMemOps()">; +def IEEERndNearV5T : Predicate<"Subtarget.modeIEEERndNear()">; + +//===----------------------------------------------------------------------===// +// Classes used for relation maps. +//===----------------------------------------------------------------------===// +// PredRel - Filter class used to relate non-predicated instructions with their +// predicated forms. +class PredRel; +// PredNewRel - Filter class used to relate predicated instructions with their +// predicate-new forms. +class PredNewRel: PredRel; +// ImmRegRel - Filter class used to relate instructions having reg-reg form +// with their reg-imm counterparts. +class ImmRegRel; +// NewValueRel - Filter class used to relate regular store instructions with +// their new-value store form. +class NewValueRel: PredNewRel; +// NewValueRel - Filter class used to relate load/store instructions having +// different addressing modes with each other. +class AddrModeRel: NewValueRel; + +//===----------------------------------------------------------------------===// +// Generate mapping table to relate non-predicate instructions with their +// predicated formats - true and false. +// + +def getPredOpcode : InstrMapping { + let FilterClass = "PredRel"; + // Instructions with the same BaseOpcode and isNVStore values form a row. + let RowFields = ["BaseOpcode", "isNVStore", "PNewValue"]; + // Instructions with the same predicate sense form a column. + let ColFields = ["PredSense"]; + // The key column is the unpredicated instructions. + let KeyCol = [""]; + // Value columns are PredSense=true and PredSense=false + let ValueCols = [["true"], ["false"]]; +} + +//===----------------------------------------------------------------------===// +// Generate mapping table to relate predicated instructions with their .new +// format. +// +def getPredNewOpcode : InstrMapping { + let FilterClass = "PredNewRel"; + let RowFields = ["BaseOpcode", "PredSense", "isNVStore"]; + let ColFields = ["PNewValue"]; + let KeyCol = [""]; + let ValueCols = [["new"]]; +} + +//===----------------------------------------------------------------------===// +// Generate mapping table to relate store instructions with their new-value +// format. +// +def getNewValueOpcode : InstrMapping { + let FilterClass = "NewValueRel"; + let RowFields = ["BaseOpcode", "PredSense", "PNewValue"]; + let ColFields = ["isNVStore"]; + let KeyCol = ["0"]; + let ValueCols = [["1"]]; +} + +def getBasedWithImmOffset : InstrMapping { + let FilterClass = "AddrModeRel"; + let RowFields = ["CextOpcode", "PredSense", "PNewValue", "isNVStore", + "isMEMri", "isFloat"]; + let ColFields = ["addrMode"]; + let KeyCol = ["Absolute"]; + let ValueCols = [["BaseImmOffset"]]; +} + +def getBaseWithRegOffset : InstrMapping { + let FilterClass = "AddrModeRel"; + let RowFields = ["CextOpcode", "PredSense", "PNewValue", "isNVStore"]; + let ColFields = ["addrMode"]; + let KeyCol = ["BaseImmOffset"]; + let ValueCols = [["BaseRegOffset"]]; +} + +def getRegForm : InstrMapping { + let FilterClass = "ImmRegRel"; + let RowFields = ["CextOpcode", "PredSense", "PNewValue"]; + let ColFields = ["InputType"]; + let KeyCol = ["imm"]; + let ValueCols = [["reg"]]; +} + +//===----------------------------------------------------------------------===// // Register File, Calling Conv, Instruction Descriptions //===----------------------------------------------------------------------===// include "HexagonSchedule.td" diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp index c15bce6..88cd3fb 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp @@ -17,20 +17,24 @@ #include "Hexagon.h" #include "HexagonAsmPrinter.h" #include "HexagonMachineFunctionInfo.h" -#include "HexagonMCInst.h" #include "HexagonTargetMachine.h" #include "HexagonSubtarget.h" +#include "MCTargetDesc/HexagonMCInst.h" #include "InstPrinter/HexagonInstPrinter.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Module.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Assembly/Writer.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.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" @@ -38,22 +42,18 @@ #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Target/Mangler.h" -#include "llvm/DataLayout.h" -#include "llvm/Target/TargetLoweringObjectFile.h" -#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetOptions.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringExtras.h" +#include "llvm/Target/TargetRegisterInfo.h" using namespace llvm; @@ -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/contrib/llvm/lib/Target/Hexagon/HexagonCFGOptimizer.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonCFGOptimizer.cpp index 9bca9e0..d4078ad 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonCFGOptimizer.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonCFGOptimizer.cpp @@ -7,21 +7,22 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "hexagon_cfg" -#include "HexagonTargetMachine.h" -#include "HexagonSubtarget.h" +#include "Hexagon.h" #include "HexagonMachineFunctionInfo.h" +#include "HexagonSubtarget.h" +#include "HexagonTargetMachine.h" #include "llvm/CodeGen/MachineDominators.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/Target/TargetMachine.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Support/Compiler.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" using namespace llvm; diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonCallingConvLower.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonCallingConvLower.cpp index 73f9d9a..2c93d04 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonCallingConvLower.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonCallingConvLower.cpp @@ -15,12 +15,12 @@ #include "HexagonCallingConvLower.h" #include "Hexagon.h" -#include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/DataLayout.h" -#include "llvm/Target/TargetMachine.h" +#include "llvm/IR/DataLayout.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" using namespace llvm; Hexagon_CCState::Hexagon_CCState(CallingConv::ID CC, bool isVarArg, diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonCallingConvLower.h b/contrib/llvm/lib/Target/Hexagon/HexagonCallingConvLower.h index 1f601e8..489b3a3 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonCallingConvLower.h +++ b/contrib/llvm/lib/Target/Hexagon/HexagonCallingConvLower.h @@ -17,9 +17,9 @@ #define LLVM_Hexagon_CODEGEN_CALLINGCONVLOWER_H #include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/ValueTypes.h" -#include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/CodeGen/ValueTypes.h" // // Need to handle varargs. diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp index ae2ca37..0814421 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp @@ -17,9 +17,10 @@ // //===----------------------------------------------------------------------===// -#include "HexagonTargetMachine.h" -#include "HexagonSubtarget.h" +#include "Hexagon.h" #include "HexagonMachineFunctionInfo.h" +#include "HexagonSubtarget.h" +#include "HexagonTargetMachine.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/LatencyPriorityQueue.h" #include "llvm/CodeGen/MachineDominators.h" @@ -30,12 +31,12 @@ #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/ScheduleHazardRecognizer.h" #include "llvm/CodeGen/SchedulerRegistry.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Support/Compiler.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" using namespace llvm; diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonFixupHwLoops.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonFixupHwLoops.cpp new file mode 100644 index 0000000..240cc95 --- /dev/null +++ b/contrib/llvm/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/contrib/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp index cd682df..d6a9329 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp @@ -11,28 +11,28 @@ #include "HexagonFrameLowering.h" #include "Hexagon.h" #include "HexagonInstrInfo.h" +#include "HexagonMachineFunctionInfo.h" #include "HexagonRegisterInfo.h" #include "HexagonSubtarget.h" #include "HexagonTargetMachine.h" -#include "HexagonMachineFunctionInfo.h" -#include "llvm/Function.h" -#include "llvm/Type.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" -#include "llvm/MC/MachineLocation.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/Support/CommandLine.h" using namespace llvm; @@ -166,7 +166,8 @@ bool HexagonFrameLowering::hasTailCall(MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); unsigned RetOpcode = MBBI->getOpcode(); - return RetOpcode == Hexagon::TCRETURNtg || RetOpcode == Hexagon::TCRETURNtext;} + return RetOpcode == Hexagon::TCRETURNtg || RetOpcode == Hexagon::TCRETURNtext; +} void HexagonFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { @@ -326,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/contrib/llvm/lib/Target/Hexagon/HexagonFrameLowering.h b/contrib/llvm/lib/Target/Hexagon/HexagonFrameLowering.h index ad87f11..a62c76a 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonFrameLowering.h +++ b/contrib/llvm/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/contrib/llvm/lib/Target/Hexagon/HexagonHardwareLoops.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonHardwareLoops.cpp index d756aec..1786624 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonHardwareLoops.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonHardwareLoops.cpp @@ -27,89 +27,202 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "hwloops" -#include "Hexagon.h" -#include "HexagonTargetMachine.h" -#include "llvm/Constants.h" -#include "llvm/PassSupport.h" -#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" -#include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/RegisterScavenging.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(abs64(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,126 +883,258 @@ 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()) + 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. MachineBasicBlock *LoopStart = L->getTopBlock(); 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 DL; + if (InsertPos != Preheader->end()) + 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, InsertPos->getDebugLoc(), - TII->get(TargetOpcode::COPY), CountReg).addReg(TripCount->getReg()); - if (TripCount->isNeg()) { - unsigned CountReg1 = CountReg; - CountReg = MF->getRegInfo().createVirtualRegister(RC); - BuildMI(*Preheader, InsertPos, InsertPos->getDebugLoc(), - 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, InsertPos->getDebugLoc(), - 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, InsertPos->getDebugLoc(), - 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. - DebugLoc dl = LastI->getDebugLoc(); - BuildMI(*LastMBB, LastI, dl, TII->get(Hexagon::ENDLOOP0)).addMBB(LoopStart); + DebugLoc LastIDL = LastI->getDebugLoc(); + BuildMI(*LastMBB, LastI, LastIDL, + TII->get(Hexagon::ENDLOOP0)).addMBB(LoopStart); // The loop ends with either: // - a conditional branch followed by an unconditional branch, or // - 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, dl); + TII->InsertBranch(*LastMBB, BranchTarget, 0, Cond, LastIDL); } } else { // Conditional branch to loop start; just delete it. @@ -538,110 +1142,413 @@ 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; + + // 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/contrib/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp index 5499134..8fc9ba1 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp @@ -12,20 +12,32 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "hexagon-isel" +#include "Hexagon.h" #include "HexagonISelLowering.h" #include "HexagonTargetMachine.h" -#include "llvm/Intrinsics.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/CodeGen/SelectionDAGISel.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. @@ -39,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); @@ -94,8 +111,56 @@ public: SDNode *SelectConstant(SDNode *N); SDNode *SelectConstantFP(SDNode *N); SDNode *SelectAdd(SDNode *N); + bool isConstExtProfitable(SDNode *N) const; + +// XformMskToBitPosU5Imm - Returns the bit position which +// the single bit 32 bit mask represents. +// Used in Clr and Set bit immediate memops. +SDValue XformMskToBitPosU5Imm(uint32_t Imm) { + int32_t bitPos; + bitPos = Log2_32(Imm); + assert(bitPos >= 0 && bitPos < 32 && + "Constant out of range for 32 BitPos Memops"); + return CurDAG->getTargetConstant(bitPos, MVT::i32); +} + +// XformMskToBitPosU4Imm - Returns the bit position which the single bit 16 bit +// mask represents. Used in Clr and Set bit immediate memops. +SDValue XformMskToBitPosU4Imm(uint16_t Imm) { + return XformMskToBitPosU5Imm(Imm); +} + +// XformMskToBitPosU3Imm - Returns the bit position which the single bit 8 bit +// mask represents. Used in Clr and Set bit immediate memops. +SDValue XformMskToBitPosU3Imm(uint8_t Imm) { + return XformMskToBitPosU5Imm(Imm); +} + +// Return true if there is exactly one bit set in V, i.e., if V is one of the +// following integers: 2^0, 2^1, ..., 2^31. +bool ImmIsSingleBit(uint32_t v) const { + uint32_t c = CountPopulation_64(v); + // Only return true if we counted 1 bit. + return c == 1; +} + +// XformM5ToU5Imm - Return a target constant with the specified value, of type +// i32 where the negative literal is transformed into a positive literal for +// use in -= memops. +inline SDValue XformM5ToU5Imm(signed Imm) { + assert( (Imm >= -31 && Imm <= -1) && "Constant out of range for Memops"); + return CurDAG->getTargetConstant( - Imm, MVT::i32); +} + + +// 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 the pieces autogenerated from the target description. #include "HexagonGenDAGISel.inc" }; } // end anonymous namespace @@ -104,10 +169,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); @@ -606,8 +684,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. @@ -1507,3 +1585,79 @@ SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, OutOps.push_back(Op1); return false; } + +bool HexagonDAGToDAGISel::isConstExtProfitable(SDNode *N) const { + unsigned UseCount = 0; + for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) { + UseCount++; + } + + 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/contrib/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp index 1c891f1..15858a9 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -13,17 +13,10 @@ //===----------------------------------------------------------------------===// #include "HexagonISelLowering.h" -#include "HexagonTargetMachine.h" #include "HexagonMachineFunctionInfo.h" -#include "HexagonTargetObjectFile.h" #include "HexagonSubtarget.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Function.h" -#include "llvm/InlineAsm.h" -#include "llvm/GlobalVariable.h" -#include "llvm/GlobalAlias.h" -#include "llvm/Intrinsics.h" -#include "llvm/CallingConv.h" +#include "HexagonTargetMachine.h" +#include "HexagonTargetObjectFile.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" @@ -32,6 +25,13 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/CodeGen/ValueTypes.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()); } @@ -608,7 +617,7 @@ static bool getIndexedAddressParts(SDNode *Ptr, EVT VT, // TODO: Put this function along with the other isS* functions in // HexagonISelDAGToDAG.cpp into a common file. Or better still, use the -// functions defined in HexagonImmediates.td. +// functions defined in HexagonOperands.td. static bool Is_PostInc_S4_Offset(SDNode * S, int ShiftAmount) { ConstantSDNode *N = cast<ConstantSDNode>(S); @@ -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,7 +1370,12 @@ HexagonTargetLowering::HexagonTargetLowering(HexagonTargetMachine // Increase jump tables cutover to 5, was 4. setMinimumJumpTableEntries(5); + setOperationAction(ISD::BR_CC, MVT::Other, Expand); + 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::BR_CC, MVT::i64, Expand); setOperationAction(ISD::MEMBARRIER, MVT::Other, Custom); setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); @@ -1364,11 +1386,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 +1482,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 +1532,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/contrib/llvm/lib/Target/Hexagon/HexagonISelLowering.h b/contrib/llvm/lib/Target/Hexagon/HexagonISelLowering.h index fe6c905..3279cc6 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonISelLowering.h +++ b/contrib/llvm/lib/Target/Hexagon/HexagonISelLowering.h @@ -16,9 +16,9 @@ #define Hexagon_ISELLOWERING_H #include "Hexagon.h" -#include "llvm/Target/TargetLowering.h" -#include "llvm/CallingConv.h" #include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/IR/CallingConv.h" +#include "llvm/Target/TargetLowering.h" namespace llvm { namespace HexagonISD { @@ -27,6 +27,7 @@ namespace llvm { CONST32, CONST32_GP, // For marking data present in GP. + CONST32_Int_Real, FCONST32, SETCC, ADJDYNALLOC, @@ -50,6 +51,17 @@ namespace llvm { BARRIER, // Memory barrier. WrapperJT, WrapperCP, + WrapperCombineII, + WrapperCombineRR, + WrapperCombineRI_V4, + WrapperCombineIR_V4, + WrapperPackhl, + WrapperSplatB, + WrapperSplatH, + WrapperShuffEB, + WrapperShuffEH, + WrapperShuffOB, + WrapperShuffOH, TC_RETURN }; } @@ -95,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/contrib/llvm/lib/Target/Hexagon/HexagonImmediates.td b/contrib/llvm/lib/Target/Hexagon/HexagonImmediates.td deleted file mode 100644 index 18692c4..0000000 --- a/contrib/llvm/lib/Target/Hexagon/HexagonImmediates.td +++ /dev/null @@ -1,508 +0,0 @@ -//===- HexagonImmediates.td - Hexagon immediate processing -*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illnois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// From IA64's InstrInfo file -def s32Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def s16Imm : Operand<i32> { - let PrintMethod = "printImmOperand"; -} - -def s12Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def s11Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def s11_0Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def s11_1Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def s11_2Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def s11_3Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def s10Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def s9Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def s8Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def s8Imm64 : Operand<i64> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def s6Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def s4Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def s4_0Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def s4_1Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def s4_2Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def s4_3Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def u64Imm : Operand<i64> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def u32Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def u16Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def u16_0Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def u16_1Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def u16_2Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def u11_3Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def u10Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def u9Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def u8Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def u7Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def u6Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def u6_0Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def u6_1Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def u6_2Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def u6_3Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def u5Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def u4Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def u3Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def u2Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def u1Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def n8Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def m6Imm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printImmOperand"; -} - -def nOneImm : Operand<i32> { - // For now, we use a generic print function for all operands. - let PrintMethod = "printNOneImmOperand"; -} - -// -// Immediate predicates -// -def s32ImmPred : PatLeaf<(i32 imm), [{ - // immS16 predicate - True if the immediate fits in a 16-bit sign extended - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isInt<32>(v); -}]>; - -def s32_24ImmPred : PatLeaf<(i32 imm), [{ - // s32_24ImmPred predicate - True if the immediate fits in a 32-bit sign - // extended field that is a multiple of 0x1000000. - int64_t v = (int64_t)N->getSExtValue(); - return isShiftedInt<32,24>(v); -}]>; - -def s32_16s8ImmPred : PatLeaf<(i32 imm), [{ - // s32_16s8ImmPred predicate - True if the immediate fits in a 32-bit sign - // extended field that is a multiple of 0x10000. - int64_t v = (int64_t)N->getSExtValue(); - return isShiftedInt<24,16>(v); -}]>; - -def s16ImmPred : PatLeaf<(i32 imm), [{ - // immS16 predicate - True if the immediate fits in a 16-bit sign extended - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isInt<16>(v); -}]>; - - -def s13ImmPred : PatLeaf<(i32 imm), [{ - // immS13 predicate - True if the immediate fits in a 13-bit sign extended - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isInt<13>(v); -}]>; - - -def s12ImmPred : PatLeaf<(i32 imm), [{ - // immS16 predicate - True if the immediate fits in a 16-bit sign extended - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isInt<12>(v); -}]>; - -def s11_0ImmPred : PatLeaf<(i32 imm), [{ - // immS16 predicate - True if the immediate fits in a 16-bit sign extended - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isInt<11>(v); -}]>; - - -def s11_1ImmPred : PatLeaf<(i32 imm), [{ - // immS16 predicate - True if the immediate fits in a 16-bit sign extended - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isShiftedInt<11,1>(v); -}]>; - - -def s11_2ImmPred : PatLeaf<(i32 imm), [{ - // immS16 predicate - True if the immediate fits in a 16-bit sign extended - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isShiftedInt<11,2>(v); -}]>; - - -def s11_3ImmPred : PatLeaf<(i32 imm), [{ - // immS16 predicate - True if the immediate fits in a 16-bit sign extended - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isShiftedInt<11,3>(v); -}]>; - - -def s10ImmPred : PatLeaf<(i32 imm), [{ - // s10ImmPred predicate - True if the immediate fits in a 10-bit sign extended - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isInt<10>(v); -}]>; - - -def s9ImmPred : PatLeaf<(i32 imm), [{ - // s9ImmPred predicate - True if the immediate fits in a 9-bit sign extended - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isInt<9>(v); -}]>; - - -def s8ImmPred : PatLeaf<(i32 imm), [{ - // s8ImmPred predicate - True if the immediate fits in a 8-bit sign extended - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isInt<8>(v); -}]>; - - -def s8Imm64Pred : PatLeaf<(i64 imm), [{ - // s8ImmPred predicate - True if the immediate fits in a 8-bit sign extended - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isInt<8>(v); -}]>; - - -def s6ImmPred : PatLeaf<(i32 imm), [{ - // s6ImmPred predicate - True if the immediate fits in a 6-bit sign extended - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isInt<6>(v); -}]>; - - -def s4_0ImmPred : PatLeaf<(i32 imm), [{ - // s4_0ImmPred predicate - True if the immediate fits in a 4-bit sign extended - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isInt<4>(v); -}]>; - - -def s4_1ImmPred : PatLeaf<(i32 imm), [{ - // s4_1ImmPred predicate - True if the immediate fits in a 4-bit sign extended - // field of 2. - int64_t v = (int64_t)N->getSExtValue(); - return isShiftedInt<4,1>(v); -}]>; - - -def s4_2ImmPred : PatLeaf<(i32 imm), [{ - // s4_2ImmPred predicate - True if the immediate fits in a 4-bit sign extended - // field that is a multiple of 4. - int64_t v = (int64_t)N->getSExtValue(); - return isShiftedInt<4,2>(v); -}]>; - - -def s4_3ImmPred : PatLeaf<(i32 imm), [{ - // s4_3ImmPred predicate - True if the immediate fits in a 4-bit sign extended - // field that is a multiple of 8. - int64_t v = (int64_t)N->getSExtValue(); - return isShiftedInt<4,3>(v); -}]>; - - -def u64ImmPred : PatLeaf<(i64 imm), [{ - // immS16 predicate - True if the immediate fits in a 16-bit sign extended - // field. - // Adding "N ||" to suppress gcc unused warning. - return (N || true); -}]>; - -def u32ImmPred : PatLeaf<(i32 imm), [{ - // immS16 predicate - True if the immediate fits in a 16-bit sign extended - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isUInt<32>(v); -}]>; - -def u16ImmPred : PatLeaf<(i32 imm), [{ - // u16ImmPred predicate - True if the immediate fits in a 16-bit unsigned - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isUInt<16>(v); -}]>; - -def u16_s8ImmPred : PatLeaf<(i32 imm), [{ - // u16_s8ImmPred predicate - True if the immediate fits in a 16-bit sign - // extended s8 field. - int64_t v = (int64_t)N->getSExtValue(); - return isShiftedUInt<16,8>(v); -}]>; - -def u9ImmPred : PatLeaf<(i32 imm), [{ - // u9ImmPred predicate - True if the immediate fits in a 9-bit unsigned - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isUInt<9>(v); -}]>; - - -def u8ImmPred : PatLeaf<(i32 imm), [{ - // u8ImmPred predicate - True if the immediate fits in a 8-bit unsigned - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isUInt<8>(v); -}]>; - -def u7ImmPred : PatLeaf<(i32 imm), [{ - // u7ImmPred predicate - True if the immediate fits in a 8-bit unsigned - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isUInt<7>(v); -}]>; - - -def u6ImmPred : PatLeaf<(i32 imm), [{ - // u6ImmPred predicate - True if the immediate fits in a 6-bit unsigned - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isUInt<6>(v); -}]>; - -def u6_0ImmPred : PatLeaf<(i32 imm), [{ - // u6_0ImmPred predicate - True if the immediate fits in a 6-bit unsigned - // field. Same as u6ImmPred. - int64_t v = (int64_t)N->getSExtValue(); - return isUInt<6>(v); -}]>; - -def u6_1ImmPred : PatLeaf<(i32 imm), [{ - // u6_1ImmPred predicate - True if the immediate fits in a 6-bit unsigned - // field that is 1 bit alinged - multiple of 2. - int64_t v = (int64_t)N->getSExtValue(); - return isShiftedUInt<6,1>(v); -}]>; - -def u6_2ImmPred : PatLeaf<(i32 imm), [{ - // u6_2ImmPred predicate - True if the immediate fits in a 6-bit unsigned - // field that is 2 bits alinged - multiple of 4. - int64_t v = (int64_t)N->getSExtValue(); - return isShiftedUInt<6,2>(v); -}]>; - -def u6_3ImmPred : PatLeaf<(i32 imm), [{ - // u6_3ImmPred predicate - True if the immediate fits in a 6-bit unsigned - // field that is 3 bits alinged - multiple of 8. - int64_t v = (int64_t)N->getSExtValue(); - return isShiftedUInt<6,3>(v); -}]>; - -def u5ImmPred : PatLeaf<(i32 imm), [{ - // u5ImmPred predicate - True if the immediate fits in a 5-bit unsigned - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isUInt<5>(v); -}]>; - - -def u3ImmPred : PatLeaf<(i32 imm), [{ - // u3ImmPred predicate - True if the immediate fits in a 3-bit unsigned - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isUInt<3>(v); -}]>; - - -def u2ImmPred : PatLeaf<(i32 imm), [{ - // u2ImmPred predicate - True if the immediate fits in a 2-bit unsigned - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isUInt<2>(v); -}]>; - - -def u1ImmPred : PatLeaf<(i1 imm), [{ - // u1ImmPred predicate - True if the immediate fits in a 1-bit unsigned - // field. - int64_t v = (int64_t)N->getSExtValue(); - return isUInt<1>(v); -}]>; - -def m6ImmPred : PatLeaf<(i32 imm), [{ - // m6ImmPred predicate - True if the immediate is negative and fits in - // a 6-bit negative number. - int64_t v = (int64_t)N->getSExtValue(); - return isInt<6>(v); -}]>; - -//InN means negative integers in [-(2^N - 1), 0] -def n8ImmPred : PatLeaf<(i32 imm), [{ - // n8ImmPred predicate - True if the immediate fits in a 8-bit signed - // field. - int64_t v = (int64_t)N->getSExtValue(); - return (-255 <= v && v <= 0); -}]>; - -def nOneImmPred : PatLeaf<(i32 imm), [{ - // nOneImmPred predicate - True if the immediate is -1. - int64_t v = (int64_t)N->getSExtValue(); - return (-1 == v); -}]>; - diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonInstrFormats.td b/contrib/llvm/lib/Target/Hexagon/HexagonInstrFormats.td index a64c7a1..587fa7d 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonInstrFormats.td +++ b/contrib/llvm/lib/Target/Hexagon/HexagonInstrFormats.td @@ -13,28 +13,77 @@ // *** 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> { + bits<4> Value = value; +} + +def HasV2SubT : SubTarget<0xf>; +def HasV2SubTOnly : SubTarget<0x1>; +def NoV2SubT : SubTarget<0x0>; +def HasV3SubT : SubTarget<0xe>; +def HasV3SubTOnly : SubTarget<0x2>; +def NoV3SubT : SubTarget<0x1>; +def HasV4SubT : SubTarget<0xc>; +def NoV4SubT : SubTarget<0x3>; +def HasV5SubT : SubTarget<0x8>; +def NoV5SubT : SubTarget<0x7>; + +// Addressing modes for load/store instructions +class AddrModeType<bits<3> value> { + bits<3> Value = value; +} + +def NoAddrMode : AddrModeType<0>; // No addressing mode +def Absolute : AddrModeType<1>; // Absolute addressing mode +def AbsoluteSet : AddrModeType<2>; // Absolute set addressing mode +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; @@ -45,20 +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; - - // Dot new value store instructions. + bits<1> isPredicatedFalse = 0; + let TSFlags{7} = isPredicatedFalse; + bits<1> isPredicatedNew = 0; + 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{16} = isNVStorable; // Store that can become new-value store. bits<1> isNVStore = 0; - let TSFlags{8} = isNVStore; + let TSFlags{17} = isNVStore; // New-value store insn. + + // Immediate extender helper fields. + bits<1> isExtendable = 0; + let TSFlags{18} = isExtendable; // Insn may be extended. + bits<1> isExtended = 0; + let TSFlags{19} = isExtended; // Insn must be extended. + bits<3> opExtendable = 0; + let TSFlags{22-20} = opExtendable; // Which operand may be extended. + bits<1> isExtentSigned = 0; + let TSFlags{23} = isExtentSigned; // Signed or unsigned range. + bits<5> opExtentBits = 0; + 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{32-29} = validSubTargets.Value; + + // Addressing mode for load/store instructions. + AddrModeType addrMode = NoAddrMode; + 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 = ""; @@ -66,7 +158,15 @@ class InstHexagon<dag outs, dag ins, string asmstr, list<dag> pattern, string PredSense = ""; string PNewValue = ""; string InputType = ""; // Input is "imm" or "reg" type. - // *** The code above must match HexagonBaseInfo.h *** + 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 *** } //===----------------------------------------------------------------------===// @@ -75,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 - @@ -265,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/contrib/llvm/lib/Target/Hexagon/HexagonInstrFormatsV4.td b/contrib/llvm/lib/Target/Hexagon/HexagonInstrFormatsV4.td index 49741a3..9fda0da 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonInstrFormatsV4.td +++ b/contrib/llvm/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/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp index 8435440..60b12ac 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp @@ -12,16 +12,16 @@ //===----------------------------------------------------------------------===// #include "HexagonInstrInfo.h" +#include "Hexagon.h" #include "HexagonRegisterInfo.h" #include "HexagonSubtarget.h" -#include "Hexagon.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/DFAPacketizer.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/Support/MathExtras.h" #define GET_INSTRINFO_CTOR @@ -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, @@ -314,7 +396,7 @@ void HexagonInstrInfo::copyPhysReg(MachineBasicBlock &MBB, return; } if (Hexagon::DoubleRegsRegClass.contains(SrcReg, DestReg)) { - BuildMI(MBB, I, DL, get(Hexagon::TFR_64), DestReg).addReg(SrcReg); + BuildMI(MBB, I, DL, get(Hexagon::TFR64), DestReg).addReg(SrcReg); return; } if (Hexagon::PredRegsRegClass.contains(SrcReg, DestReg)) { @@ -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"); } @@ -443,6 +537,15 @@ MachineInstr *HexagonInstrInfo::foldMemoryOperandImpl(MachineFunction &MF, return(0); } +MachineInstr* +HexagonInstrInfo::emitFrameIndexDebugValue(MachineFunction &MF, + int FrameIx, uint64_t Offset, + const MDNode *MDPtr, + DebugLoc DL) const { + MachineInstrBuilder MIB = BuildMI(MF, DL, get(Hexagon::DBG_VALUE)) + .addImm(0).addImm(Offset).addMetadata(MDPtr); + return &*MIB; +} unsigned HexagonInstrInfo::createVR(MachineFunction* MF, MVT VT) const { @@ -463,270 +566,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,264 +711,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_ADDSUBi_indexed_MEM_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_ADDSUBi_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_ADDSUBi_indexed_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_ADDSUBi_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_ADDSUBi_indexed_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_ADDSUBi_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; @@ -1101,7 +719,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: @@ -1124,10 +741,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: @@ -1144,7 +757,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: @@ -1167,10 +779,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: @@ -1187,7 +795,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: @@ -1210,10 +817,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: @@ -1305,6 +908,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; } @@ -1506,26 +1119,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: @@ -1536,16 +1134,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: @@ -1556,11 +1144,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: @@ -1686,26 +1269,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; @@ -1971,75 +1534,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; @@ -2122,19 +1636,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; @@ -2221,38 +1722,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; } @@ -2286,6 +1890,13 @@ bool HexagonInstrInfo::isPredicated(const MachineInstr *MI) const { return ((F >> HexagonII::PredicatedPos) & HexagonII::PredicatedMask); } +bool HexagonInstrInfo::isPredicatedNew(const MachineInstr *MI) const { + const uint64_t F = MI->getDesc().TSFlags; + + assert(isPredicated(MI)); + return ((F >> HexagonII::PredicatedNewPos) & HexagonII::PredicatedNewMask); +} + bool HexagonInstrInfo::DefinesPredicate(MachineInstr *MI, std::vector<MachineOperand> &Pred) const { @@ -2354,29 +1965,34 @@ isValidOffset(const int Opcode, const int Offset) const { // the given "Opcode". If "Offset" is not in the correct range, "ADD_ri" is // inserted to calculate the final address. Due to this reason, the function // assumes that the "Offset" has correct alignment. + // We used to assert if the offset was not properly aligned, however, + // there are cases where a misaligned pointer recast can cause this + // problem, and we need to allow for it. The front end warns of such + // misaligns with respect to load size. 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"); return (Offset >= Hexagon_MEMW_OFFSET_MIN) && (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) && (Offset <= Hexagon_MEMD_OFFSET_MAX); case Hexagon::LDrih: case Hexagon::LDriuh: case Hexagon::STrih: - assert((Offset % 2 == 0) && "Offset has incorrect alignment"); return (Offset >= Hexagon_MEMH_OFFSET_MIN) && (Offset <= Hexagon_MEMH_OFFSET_MAX); @@ -2391,54 +2007,28 @@ isValidOffset(const int Opcode, const int Offset) const { return (Offset >= Hexagon_ADDI_OFFSET_MIN) && (Offset <= Hexagon_ADDI_OFFSET_MAX); - case Hexagon::MEMw_ADDSUBi_indexed_MEM_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_ADDSUBi_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 : - assert ((Offset % 4) == 0 && "MEMOPw offset is not aligned correctly." ); + case Hexagon::MemOPw_ADDi_V4 : + case Hexagon::MemOPw_SUBi_V4 : + case Hexagon::MemOPw_ADDr_V4 : + case Hexagon::MemOPw_SUBr_V4 : + case Hexagon::MemOPw_ANDr_V4 : + case Hexagon::MemOPw_ORr_V4 : return (0 <= Offset && Offset <= 255); - case Hexagon::MEMh_ADDSUBi_indexed_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_ADDSUBi_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 : - assert ((Offset % 2) == 0 && "MEMOPh offset is not aligned correctly." ); + case Hexagon::MemOPh_ADDi_V4 : + case Hexagon::MemOPh_SUBi_V4 : + case Hexagon::MemOPh_ADDr_V4 : + case Hexagon::MemOPh_SUBr_V4 : + case Hexagon::MemOPh_ANDr_V4 : + case Hexagon::MemOPh_ORr_V4 : return (0 <= Offset && Offset <= 127); - case Hexagon::MEMb_ADDSUBi_indexed_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_ADDSUBi_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 : + case Hexagon::MemOPb_ADDi_V4 : + case Hexagon::MemOPb_SUBi_V4 : + case Hexagon::MemOPb_ADDr_V4 : + case Hexagon::MemOPb_SUBr_V4 : + case Hexagon::MemOPb_ANDr_V4 : + case Hexagon::MemOPb_ORr_V4 : return (0 <= Offset && Offset <= 63); // LDri_pred and STriw_pred are pseudo operations, so it has to take offset of @@ -2447,6 +2037,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; @@ -2491,50 +2084,33 @@ isMemOp(const MachineInstr *MI) const { switch (MI->getOpcode()) { default: return false; - case Hexagon::MEMw_ADDSUBi_indexed_MEM_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_ADDSUBi_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_ADDSUBi_indexed_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_ADDSUBi_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_ADDSUBi_indexed_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_ADDSUBi_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 : - return true; + case Hexagon::MemOPw_ADDi_V4 : + case Hexagon::MemOPw_SUBi_V4 : + case Hexagon::MemOPw_ADDr_V4 : + case Hexagon::MemOPw_SUBr_V4 : + case Hexagon::MemOPw_ANDr_V4 : + case Hexagon::MemOPw_ORr_V4 : + case Hexagon::MemOPh_ADDi_V4 : + case Hexagon::MemOPh_SUBi_V4 : + case Hexagon::MemOPh_ADDr_V4 : + case Hexagon::MemOPh_SUBr_V4 : + case Hexagon::MemOPh_ANDr_V4 : + case Hexagon::MemOPh_ORr_V4 : + case Hexagon::MemOPb_ADDi_V4 : + case Hexagon::MemOPb_SUBi_V4 : + case Hexagon::MemOPb_ADDr_V4 : + case Hexagon::MemOPb_SUBr_V4 : + case Hexagon::MemOPb_ANDr_V4 : + case Hexagon::MemOPb_ORr_V4 : + case Hexagon::MemOPb_SETBITi_V4: + case Hexagon::MemOPh_SETBITi_V4: + case Hexagon::MemOPw_SETBITi_V4: + case Hexagon::MemOPb_CLRBITi_V4: + case Hexagon::MemOPh_CLRBITi_V4: + case Hexagon::MemOPw_CLRBITi_V4: + return true; } + return false; } @@ -2661,28 +2237,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(); @@ -2765,14 +2329,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 : @@ -2813,7 +2369,33 @@ isConditionalStore (const MachineInstr* MI) const { } } +// Returns true, if any one of the operands is a dot new +// insn, whether it is predicated dot new or register dot new. +bool HexagonInstrInfo::isDotNewInst (const MachineInstr* MI) const { + return (isNewValueInst(MI) || + (isPredicated(MI) && isPredicatedNew(MI))); +} + +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, @@ -2840,3 +2422,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/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.h b/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.h index 2bb53f8..5df13a8 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.h +++ b/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.h @@ -16,8 +16,8 @@ #include "HexagonRegisterInfo.h" #include "MCTargetDesc/HexagonBaseInfo.h" -#include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetInstrInfo.h" #define GET_INSTRINFO_HEADER @@ -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, @@ -123,6 +127,7 @@ public: const BranchProbability &Probability) const; virtual bool isPredicated(const MachineInstr *MI) const; + virtual bool isPredicatedNew(const MachineInstr *MI) const; virtual bool DefinesPredicate(MachineInstr *MI, std::vector<MachineOperand> &Pred) const; virtual bool @@ -136,6 +141,11 @@ public: isProfitableToDupForIfCvt(MachineBasicBlock &MBB,unsigned NumCycles, const BranchProbability &Probability) const; + virtual MachineInstr *emitFrameIndexDebugValue(MachineFunction &MF, + int FrameIx, + uint64_t Offset, + const MDNode *MDPtr, + DebugLoc DL) const; virtual DFAPacketizer* CreateTargetScheduleState(const TargetMachine *TM, const ScheduleDAG *DAG) const; @@ -165,6 +175,8 @@ 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 isDotNewInst(const MachineInstr* MI) const; bool isDeallocRet(const MachineInstr *MI) const; unsigned getInvertedPredicatedOpcode(const int Opc) const; bool isExtendable(const MachineInstr* MI) const; @@ -173,9 +185,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/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.td b/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.td index 1d4a706..74dc0ca 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.td +++ b/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfo.td @@ -12,88 +12,7 @@ //===----------------------------------------------------------------------===// include "HexagonInstrFormats.td" -include "HexagonImmediates.td" - -//===----------------------------------------------------------------------===// -// Classes used for relation maps. -//===----------------------------------------------------------------------===// -// PredRel - Filter class used to relate non-predicated instructions with their -// predicated forms. -class PredRel; -// PredNewRel - Filter class used to relate predicated instructions with their -// predicate-new forms. -class PredNewRel: PredRel; -// ImmRegRel - Filter class used to relate instructions having reg-reg form -// with their reg-imm counterparts. -class ImmRegRel; -//===----------------------------------------------------------------------===// -// Hexagon Instruction Predicate Definitions. -//===----------------------------------------------------------------------===// -def HasV2T : Predicate<"Subtarget.hasV2TOps()">; -def HasV2TOnly : Predicate<"Subtarget.hasV2TOpsOnly()">; -def NoV2T : Predicate<"!Subtarget.hasV2TOps()">; -def HasV3T : Predicate<"Subtarget.hasV3TOps()">; -def HasV3TOnly : Predicate<"Subtarget.hasV3TOpsOnly()">; -def NoV3T : Predicate<"!Subtarget.hasV3TOps()">; -def HasV4T : Predicate<"Subtarget.hasV4TOps()">; -def NoV4T : Predicate<"!Subtarget.hasV4TOps()">; -def HasV5T : Predicate<"Subtarget.hasV5TOps()">; -def NoV5T : Predicate<"!Subtarget.hasV5TOps()">; -def UseMEMOP : Predicate<"Subtarget.useMemOps()">; -def IEEERndNearV5T : Predicate<"Subtarget.modeIEEERndNear()">; - -// Addressing modes. -def ADDRrr : ComplexPattern<i32, 2, "SelectADDRrr", [], []>; -def ADDRri : ComplexPattern<i32, 2, "SelectADDRri", [frameindex], []>; -def ADDRriS11_0 : ComplexPattern<i32, 2, "SelectADDRriS11_0", [frameindex], []>; -def ADDRriS11_1 : ComplexPattern<i32, 2, "SelectADDRriS11_1", [frameindex], []>; -def ADDRriS11_2 : ComplexPattern<i32, 2, "SelectADDRriS11_2", [frameindex], []>; -def ADDRriS11_3 : ComplexPattern<i32, 2, "SelectADDRriS11_3", [frameindex], []>; -def ADDRriU6_0 : ComplexPattern<i32, 2, "SelectADDRriU6_0", [frameindex], []>; -def ADDRriU6_1 : ComplexPattern<i32, 2, "SelectADDRriU6_1", [frameindex], []>; -def ADDRriU6_2 : ComplexPattern<i32, 2, "SelectADDRriU6_2", [frameindex], []>; - -// Address operands. -def MEMrr : Operand<i32> { - let PrintMethod = "printMEMrrOperand"; - let MIOperandInfo = (ops IntRegs, IntRegs); -} - -// Address operands -def MEMri : Operand<i32> { - let PrintMethod = "printMEMriOperand"; - let MIOperandInfo = (ops IntRegs, IntRegs); -} - -def MEMri_s11_2 : Operand<i32>, - ComplexPattern<i32, 2, "SelectMEMriS11_2", []> { - let PrintMethod = "printMEMriOperand"; - let MIOperandInfo = (ops IntRegs, s11Imm); -} - -def FrameIndex : Operand<i32> { - let PrintMethod = "printFrameIndexOperand"; - let MIOperandInfo = (ops IntRegs, s11Imm); -} - -let PrintMethod = "printGlobalOperand" in - def globaladdress : Operand<i32>; - -let PrintMethod = "printJumpTable" in - def jumptablebase : Operand<i32>; - -def brtarget : Operand<OtherVT>; -def calltarget : Operand<i32>; - -def bblabel : Operand<i32>; -def bbl : SDNode<"ISD::BasicBlock", SDTPtrLeaf , [], "BasicBlockSDNode">; - -def symbolHi32 : Operand<i32> { - let PrintMethod = "printSymbolHi"; -} -def symbolLo32 : Operand<i32> { - let PrintMethod = "printSymbolLo"; -} +include "HexagonOperands.td" // Multi-class for logical operators. multiclass ALU32_rr_ri<string OpcStr, SDNode OpNode> { @@ -122,40 +41,54 @@ multiclass CMP32_rr<string OpcStr, PatFrag OpNode> { (OpNode (i32 IntRegs:$b), (i32 IntRegs:$c)))]>; } -multiclass CMP32_rr_ri_s10<string OpcStr, PatFrag OpNode> { - def rr : ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$b, IntRegs:$c), - !strconcat("$dst = ", !strconcat(OpcStr, "($b, $c)")), - [(set (i1 PredRegs:$dst), - (OpNode (i32 IntRegs:$b), (i32 IntRegs:$c)))]>; - def ri : ALU32_ri<(outs PredRegs:$dst), (ins IntRegs:$b, s10Imm:$c), - !strconcat("$dst = ", !strconcat(OpcStr, "($b, #$c)")), - [(set (i1 PredRegs:$dst), - (OpNode (i32 IntRegs:$b), s10ImmPred:$c))]>; +multiclass CMP32_rr_ri_s10<string OpcStr, string CextOp, PatFrag OpNode> { + let CextOpcode = CextOp in { + let InputType = "reg" in + def rr : ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$b, IntRegs:$c), + !strconcat("$dst = ", !strconcat(OpcStr, "($b, $c)")), + [(set (i1 PredRegs:$dst), + (OpNode (i32 IntRegs:$b), (i32 IntRegs:$c)))]>; + + let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, + opExtentBits = 10, InputType = "imm" in + def ri : ALU32_ri<(outs PredRegs:$dst), (ins IntRegs:$b, s10Ext:$c), + !strconcat("$dst = ", !strconcat(OpcStr, "($b, #$c)")), + [(set (i1 PredRegs:$dst), + (OpNode (i32 IntRegs:$b), s10ExtPred:$c))]>; + } } -multiclass CMP32_rr_ri_u9<string OpcStr, PatFrag OpNode> { - def rr : ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$b, IntRegs:$c), - !strconcat("$dst = ", !strconcat(OpcStr, "($b, $c)")), - [(set (i1 PredRegs:$dst), - (OpNode (i32 IntRegs:$b), (i32 IntRegs:$c)))]>; - def ri : ALU32_ri<(outs PredRegs:$dst), (ins IntRegs:$b, u9Imm:$c), - !strconcat("$dst = ", !strconcat(OpcStr, "($b, #$c)")), - [(set (i1 PredRegs:$dst), - (OpNode (i32 IntRegs:$b), u9ImmPred:$c))]>; +multiclass CMP32_rr_ri_u9<string OpcStr, string CextOp, PatFrag OpNode> { + let CextOpcode = CextOp in { + let InputType = "reg" in + def rr : ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$b, IntRegs:$c), + !strconcat("$dst = ", !strconcat(OpcStr, "($b, $c)")), + [(set (i1 PredRegs:$dst), + (OpNode (i32 IntRegs:$b), (i32 IntRegs:$c)))]>; + + let isExtendable = 1, opExtendable = 2, isExtentSigned = 0, + opExtentBits = 9, InputType = "imm" in + def ri : ALU32_ri<(outs PredRegs:$dst), (ins IntRegs:$b, u9Ext:$c), + !strconcat("$dst = ", !strconcat(OpcStr, "($b, #$c)")), + [(set (i1 PredRegs:$dst), + (OpNode (i32 IntRegs:$b), u9ExtPred:$c))]>; + } } multiclass CMP32_ri_u8<string OpcStr, PatFrag OpNode> { - def ri : ALU32_ri<(outs PredRegs:$dst), (ins IntRegs:$b, u8Imm:$c), +let isExtendable = 1, opExtendable = 2, isExtentSigned = 0, opExtentBits = 8 in + def ri : ALU32_ri<(outs PredRegs:$dst), (ins IntRegs:$b, u8Ext:$c), !strconcat("$dst = ", !strconcat(OpcStr, "($b, #$c)")), [(set (i1 PredRegs:$dst), (OpNode (i32 IntRegs:$b), - u8ImmPred:$c))]>; + u8ExtPred:$c))]>; } multiclass CMP32_ri_s8<string OpcStr, PatFrag OpNode> { - def ri : ALU32_ri<(outs PredRegs:$dst), (ins IntRegs:$b, s8Imm:$c), +let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 8 in + def ri : ALU32_ri<(outs PredRegs:$dst), (ins IntRegs:$b, s8Ext:$c), !strconcat("$dst = ", !strconcat(OpcStr, "($b, #$c)")), [(set (i1 PredRegs:$dst), (OpNode (i32 IntRegs:$b), - s8ImmPred:$c))]>; + s8ExtPred:$c))]>; } } @@ -165,8 +98,8 @@ multiclass CMP32_ri_s8<string OpcStr, PatFrag OpNode> { 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)", @@ -174,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>; } } @@ -185,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), @@ -211,33 +144,35 @@ 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), - (ins PredRegs:$src1, IntRegs:$src2, s8Imm: $src3), + 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)", []>; } 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>; } } -let InputType = "imm" in +let isExtendable = 1, InputType = "imm" in multiclass ALU32ri_base<string mnemonic, string CextOp, SDNode OpNode> { let CextOpcode = CextOp, BaseOpcode = CextOp#_ri in { - let isPredicable = 1 in - def #NAME# : ALU32_ri<(outs IntRegs:$dst), - (ins IntRegs:$src1, s16Imm:$src2), + let opExtendable = 2, isExtentSigned = 1, opExtentBits = 16, + isPredicable = 1 in + def NAME : ALU32_ri<(outs IntRegs:$dst), + (ins IntRegs:$src1, s16Ext:$src2), "$dst = "#mnemonic#"($src1, #$src2)", [(set (i32 IntRegs:$dst), (OpNode (i32 IntRegs:$src1), - (s16ImmPred:$src2)))]>; + (s16ExtPred:$src2)))]>; - let neverHasSideEffects = 1, isPredicated = 1 in { + let opExtendable = 3, isExtentSigned = 1, opExtentBits = 8, + neverHasSideEffects = 1, isPredicated = 1 in { defm Pt : ALU32ri_Pred<mnemonic, 0>; defm NotPt : ALU32ri_Pred<mnemonic, 1>; } @@ -246,23 +181,26 @@ multiclass ALU32ri_base<string mnemonic, string CextOp, SDNode OpNode> { defm ADD_ri : ALU32ri_base<"add", "ADD", add>, ImmRegRel, PredNewRel; +let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 10, +CextOpcode = "OR", InputType = "imm" in def OR_ri : ALU32_ri<(outs IntRegs:$dst), - (ins IntRegs:$src1, s10Imm:$src2), + (ins IntRegs:$src1, s10Ext:$src2), "$dst = or($src1, #$src2)", [(set (i32 IntRegs:$dst), (or (i32 IntRegs:$src1), - s10ImmPred:$src2))]>; + s10ExtPred:$src2))]>, ImmRegRel; def NOT_rr : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1), "$dst = not($src1)", [(set (i32 IntRegs:$dst), (not (i32 IntRegs:$src1)))]>; +let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 10, +InputType = "imm", CextOpcode = "AND" in def AND_ri : ALU32_ri<(outs IntRegs:$dst), - (ins IntRegs:$src1, s10Imm:$src2), + (ins IntRegs:$src1, s10Ext:$src2), "$dst = and($src1, #$src2)", [(set (i32 IntRegs:$dst), (and (i32 IntRegs:$src1), - s10ImmPred:$src2))]>; - + s10ExtPred:$src2))]>, ImmRegRel; // Negate. def NEG : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1), "$dst = neg($src1)", @@ -274,27 +212,138 @@ def NOP : ALU32_rr<(outs), (ins), []>; // Rd32=sub(#s10,Rs32) +let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 10, +CextOpcode = "SUB", InputType = "imm" in def SUB_ri : ALU32_ri<(outs IntRegs:$dst), - (ins s10Imm:$src1, IntRegs:$src2), + (ins s10Ext:$src1, IntRegs:$src2), "$dst = sub(#$src1, $src2)", - [(set IntRegs:$dst, (sub s10ImmPred:$src1, IntRegs:$src2))]>; - -// Transfer immediate. -let isMoveImm = 1, isReMaterializable = 1, isPredicable = 1 in -def TFRI : ALU32_ri<(outs IntRegs:$dst), (ins s16Imm:$src1), - "$dst = #$src1", - [(set (i32 IntRegs:$dst), s16ImmPred:$src1)]>; - -// Transfer register. -let neverHasSideEffects = 1, isPredicable = 1 in -def TFR : ALU32_ri<(outs IntRegs:$dst), (ins IntRegs:$src1), - "$dst = $src1", - []>; + [(set IntRegs:$dst, (sub s10ExtPred:$src1, IntRegs:$src2))]>, + ImmRegRel; -let neverHasSideEffects = 1, isPredicable = 1 in -def TFR64 : ALU32_ri<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1), - "$dst = $src1", - []>; + +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), + !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), + !if(PredNot, "if (!$src1", "if ($src1")#".new) $dst = $src2", + []>; + } +} + +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), + "$dst = $src1", + []>; + + let isPredicated = 1 in { + defm Pt : TFR_Pred<0>; + defm NotPt : TFR_Pred<1>; + } + } +} + +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 : T_TFR64_Pred<PredNot, 0>; + + let PNewValue = "new" in + def _cdn#NAME : T_TFR64_Pred<PredNot, 1>; // Predicate new + } +} + +let neverHasSideEffects = 1 in +multiclass TFR64_base<string BaseName> { + let BaseOpcode = BaseName in { + let isPredicable = 1 in + 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>; + defm NotPt : TFR64_Pred<1>; + } + } +} + +multiclass TFRI_Pred<bit PredNot> { + 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), + !if(PredNot, "if (!$src1", "if ($src1")#".new) $dst = #$src2", + []>; + } +} + +let InputType = "imm", isExtendable = 1, isExtentSigned = 1 in +multiclass TFRI_base<string CextOp> { + let CextOpcode = CextOp, BaseOpcode = CextOp#I in { + 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)]>; + + let opExtendable = 2, opExtentBits = 12, neverHasSideEffects = 1, + isPredicated = 1 in { + defm Pt : TFRI_Pred<0>; + defm NotPt : TFRI_Pred<1>; + } + } +} + +defm TFRI : TFRI_base<"TFR">, ImmRegRel, PredNewRel; +defm TFR : TFR_base<"TFR">, ImmRegRel, PredNewRel; +defm TFR64 : TFR64_base<"TFR64">, PredNewRel; // Transfer control register. let neverHasSideEffects = 1 in @@ -311,17 +360,50 @@ def TFCR : CRInst<(outs CRRegs:$dst), (ins IntRegs:$src1), //===----------------------------------------------------------------------===// // Combine. -let isPredicable = 1, neverHasSideEffects = 1 in -def COMBINE_rr : ALU32_rr<(outs DoubleRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2), - "$dst = combine($src1, $src2)", - []>; -let neverHasSideEffects = 1 in -def COMBINE_ii : ALU32_ii<(outs DoubleRegs:$dst), - (ins s8Imm:$src1, s8Imm:$src2), - "$dst = combine(#$src1, #$src2)", - []>; +def SDTHexagonI64I32I32 : SDTypeProfile<1, 2, + [SDTCisVT<0, i64>, SDTCisVT<1, i32>, SDTCisSameAs<1, 2>]>; + +def HexagonWrapperCombineII : + SDNode<"HexagonISD::WrapperCombineII", SDTHexagonI64I32I32>; +def HexagonWrapperCombineRR : + SDNode<"HexagonISD::WrapperCombineRR", SDTHexagonI64I32I32>; + +// Combines the two integer registers SRC1 and SRC2 into a double register. +let isPredicable = 1 in +def COMBINE_rr : ALU32_rr<(outs DoubleRegs:$dst), (ins IntRegs:$src1, + IntRegs:$src2), + "$dst = combine($src1, $src2)", + [(set (i64 DoubleRegs:$dst), + (i64 (HexagonWrapperCombineRR (i32 IntRegs:$src1), + (i32 IntRegs:$src2))))]>; + +// Rd=combine(Rt.[HL], Rs.[HL]) +class COMBINE_halves<string A, string B>: ALU32_rr<(outs IntRegs:$dst), + (ins IntRegs:$src1, + IntRegs:$src2), + "$dst = combine($src1."# A #", $src2."# B #")", []>; + +let isPredicable = 1 in { + def COMBINE_hh : COMBINE_halves<"H", "H">; + def COMBINE_hl : COMBINE_halves<"H", "L">; + def COMBINE_lh : COMBINE_halves<"L", "H">; + def COMBINE_ll : COMBINE_halves<"L", "L">; +} + +def : Pat<(i32 (trunc (i64 (srl (i64 DoubleRegs:$a), (i32 16))))), + (COMBINE_lh (EXTRACT_SUBREG (i64 DoubleRegs:$a), subreg_hireg), + (EXTRACT_SUBREG (i64 DoubleRegs:$a), subreg_loreg))>; + +// Combines the two immediates SRC1 and SRC2 into a double register. +class COMBINE_imm<Operand imm1, Operand imm2, PatLeaf pat1, PatLeaf pat2> : + ALU32_ii<(outs DoubleRegs:$dst), (ins imm1:$src1, imm2:$src2), + "$dst = combine(#$src1, #$src2)", + [(set (i64 DoubleRegs:$dst), + (i64 (HexagonWrapperCombineII (i32 pat1:$src1), (i32 pat2:$src2))))]>; + +let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 8 in +def COMBINE_Ii : COMBINE_imm<s8Ext, s8Imm, s8ExtPred, s8ImmPred>; // Mux. def VMUX_prr64 : ALU64_rr<(outs DoubleRegs:$dst), (ins PredRegs:$src1, @@ -330,66 +412,92 @@ def VMUX_prr64 : ALU64_rr<(outs DoubleRegs:$dst), (ins PredRegs:$src1, "$dst = vmux($src1, $src2, $src3)", []>; +let CextOpcode = "MUX", InputType = "reg" in def MUX_rr : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), "$dst = mux($src1, $src2, $src3)", - [(set (i32 IntRegs:$dst), (i32 (select (i1 PredRegs:$src1), - (i32 IntRegs:$src2), - (i32 IntRegs:$src3))))]>; + [(set (i32 IntRegs:$dst), + (i32 (select (i1 PredRegs:$src1), (i32 IntRegs:$src2), + (i32 IntRegs:$src3))))]>, ImmRegRel; -def MUX_ir : ALU32_ir<(outs IntRegs:$dst), (ins PredRegs:$src1, s8Imm:$src2, +let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 8, +CextOpcode = "MUX", InputType = "imm" in +def MUX_ir : ALU32_ir<(outs IntRegs:$dst), (ins PredRegs:$src1, s8Ext:$src2, IntRegs:$src3), "$dst = mux($src1, #$src2, $src3)", - [(set (i32 IntRegs:$dst), (i32 (select (i1 PredRegs:$src1), - s8ImmPred:$src2, - (i32 IntRegs:$src3))))]>; + [(set (i32 IntRegs:$dst), + (i32 (select (i1 PredRegs:$src1), s8ExtPred:$src2, + (i32 IntRegs:$src3))))]>, ImmRegRel; +let isExtendable = 1, opExtendable = 3, isExtentSigned = 1, opExtentBits = 8, +CextOpcode = "MUX", InputType = "imm" in def MUX_ri : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2, - s8Imm:$src3), + s8Ext:$src3), "$dst = mux($src1, $src2, #$src3)", - [(set (i32 IntRegs:$dst), (i32 (select (i1 PredRegs:$src1), - (i32 IntRegs:$src2), - s8ImmPred:$src3)))]>; + [(set (i32 IntRegs:$dst), + (i32 (select (i1 PredRegs:$src1), (i32 IntRegs:$src2), + s8ExtPred:$src3)))]>, ImmRegRel; -def MUX_ii : ALU32_ii<(outs IntRegs:$dst), (ins PredRegs:$src1, s8Imm:$src2, +let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 8 in +def MUX_ii : ALU32_ii<(outs IntRegs:$dst), (ins PredRegs:$src1, s8Ext:$src2, s8Imm:$src3), "$dst = mux($src1, #$src2, #$src3)", [(set (i32 IntRegs:$dst), (i32 (select (i1 PredRegs:$src1), - s8ImmPred:$src2, + s8ExtPred:$src2, s8ImmPred:$src3)))]>; -// Shift halfword. -let isPredicable = 1 in -def ASLH : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1), - "$dst = aslh($src1)", - [(set (i32 IntRegs:$dst), (shl 16, (i32 IntRegs:$src1)))]>; +// ALU32 - aslh, asrh, sxtb, sxth, zxtb, zxth +multiclass ALU32_2op_Pbase<string mnemonic, bit isNot, bit isPredNew> { + let isPredicatedNew = isPredNew in + def NAME : ALU32Inst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew,".new) $dst = ", + ") $dst = ")#mnemonic#"($src2)">, + Requires<[HasV4T]>; +} -let isPredicable = 1 in -def ASRH : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1), - "$dst = asrh($src1)", - [(set (i32 IntRegs:$dst), (sra 16, (i32 IntRegs:$src1)))]>; +multiclass ALU32_2op_Pred<string mnemonic, bit PredNot> { + let isPredicatedFalse = PredNot in { + defm _c#NAME : ALU32_2op_Pbase<mnemonic, PredNot, 0>; + // Predicate new + defm _cdn#NAME : ALU32_2op_Pbase<mnemonic, PredNot, 1>; + } +} -// Sign extend. -let isPredicable = 1 in -def SXTB : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1), - "$dst = sxtb($src1)", - [(set (i32 IntRegs:$dst), (sext_inreg (i32 IntRegs:$src1), i8))]>; +multiclass ALU32_2op_base<string mnemonic> { + let BaseOpcode = mnemonic in { + let isPredicable = 1, neverHasSideEffects = 1 in + def NAME : ALU32Inst<(outs IntRegs:$dst), + (ins IntRegs:$src1), + "$dst = "#mnemonic#"($src1)">; + + let Predicates = [HasV4T], validSubTargets = HasV4SubT, isPredicated = 1, + neverHasSideEffects = 1 in { + defm Pt_V4 : ALU32_2op_Pred<mnemonic, 0>; + defm NotPt_V4 : ALU32_2op_Pred<mnemonic, 1>; + } + } +} -let isPredicable = 1 in -def SXTH : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1), - "$dst = sxth($src1)", - [(set (i32 IntRegs:$dst), (sext_inreg (i32 IntRegs:$src1), i16))]>; - -// Zero extend. -let isPredicable = 1, neverHasSideEffects = 1 in -def ZXTB : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1), - "$dst = zxtb($src1)", - []>; +defm ASLH : ALU32_2op_base<"aslh">, PredNewRel; +defm ASRH : ALU32_2op_base<"asrh">, PredNewRel; +defm SXTB : ALU32_2op_base<"sxtb">, PredNewRel; +defm SXTH : ALU32_2op_base<"sxth">, PredNewRel; +defm ZXTB : ALU32_2op_base<"zxtb">, PredNewRel; +defm ZXTH : ALU32_2op_base<"zxth">, PredNewRel; + +def : Pat <(shl (i32 IntRegs:$src1), (i32 16)), + (ASLH IntRegs:$src1)>; + +def : Pat <(sra (i32 IntRegs:$src1), (i32 16)), + (ASRH IntRegs:$src1)>; + +def : Pat <(sext_inreg (i32 IntRegs:$src1), i8), + (SXTB IntRegs:$src1)>; + +def : Pat <(sext_inreg (i32 IntRegs:$src1), i16), + (SXTH IntRegs:$src1)>; -let isPredicable = 1, neverHasSideEffects = 1 in -def ZXTH : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1), - "$dst = zxth($src1)", - []>; //===----------------------------------------------------------------------===// // ALU32/PERM - //===----------------------------------------------------------------------===// @@ -400,98 +508,66 @@ def ZXTH : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1), //===----------------------------------------------------------------------===// // Conditional combine. - -let neverHasSideEffects = 1, isPredicated = 1 in +let neverHasSideEffects = 1, isPredicated = 1 in { def COMBINE_rr_cPt : ALU32_rr<(outs DoubleRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), "if ($src1) $dst = combine($src2, $src3)", []>; -let neverHasSideEffects = 1, isPredicated = 1 in +let isPredicatedFalse = 1 in def COMBINE_rr_cNotPt : ALU32_rr<(outs DoubleRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), "if (!$src1) $dst = combine($src2, $src3)", []>; -let neverHasSideEffects = 1, isPredicated = 1 in +let isPredicatedNew = 1 in def COMBINE_rr_cdnPt : ALU32_rr<(outs DoubleRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), "if ($src1.new) $dst = combine($src2, $src3)", []>; -let neverHasSideEffects = 1, isPredicated = 1 in +let isPredicatedNew = 1, isPredicatedFalse = 1 in def COMBINE_rr_cdnNotPt : ALU32_rr<(outs DoubleRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), "if (!$src1.new) $dst = combine($src2, $src3)", []>; +} -// Conditional transfer. -let neverHasSideEffects = 1, isPredicated = 1 in -def TFR_cPt : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), - "if ($src1) $dst = $src2", - []>; +// Compare. +defm CMPGTU : CMP32_rr_ri_u9<"cmp.gtu", "CMPGTU", setugt>, ImmRegRel; +defm CMPGT : CMP32_rr_ri_s10<"cmp.gt", "CMPGT", setgt>, ImmRegRel; +defm CMPLT : CMP32_rr<"cmp.lt", setlt>; +defm CMPLTU : CMP32_rr<"cmp.ltu", setult>; +defm CMPEQ : CMP32_rr_ri_s10<"cmp.eq", "CMPEQ", seteq>, ImmRegRel; +defm CMPGE : CMP32_ri_s8<"cmp.ge", setge>; +defm CMPGEU : CMP32_ri_u8<"cmp.geu", setuge>; -let neverHasSideEffects = 1, isPredicated = 1 in -def TFR_cNotPt : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, - IntRegs:$src2), - "if (!$src1) $dst = $src2", - []>; +def CTLZ_rr : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1), + "$dst = cl0($src1)", + [(set (i32 IntRegs:$dst), (ctlz (i32 IntRegs:$src1)))]>; -let neverHasSideEffects = 1, isPredicated = 1 in -def TFR64_cPt : ALU32_rr<(outs DoubleRegs:$dst), (ins PredRegs:$src1, - DoubleRegs:$src2), - "if ($src1) $dst = $src2", - []>; +def CTTZ_rr : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1), + "$dst = ct0($src1)", + [(set (i32 IntRegs:$dst), (cttz (i32 IntRegs:$src1)))]>; -let neverHasSideEffects = 1, isPredicated = 1 in -def TFR64_cNotPt : ALU32_rr<(outs DoubleRegs:$dst), (ins PredRegs:$src1, - DoubleRegs:$src2), - "if (!$src1) $dst = $src2", - []>; +def CTLZ64_rr : SInst<(outs IntRegs:$dst), (ins DoubleRegs:$src1), + "$dst = cl0($src1)", + [(set (i32 IntRegs:$dst), (i32 (trunc (ctlz (i64 DoubleRegs:$src1)))))]>; -let neverHasSideEffects = 1, isPredicated = 1 in -def TFRI_cPt : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, s12Imm:$src2), - "if ($src1) $dst = #$src2", - []>; +def CTTZ64_rr : SInst<(outs IntRegs:$dst), (ins DoubleRegs:$src1), + "$dst = ct0($src1)", + [(set (i32 IntRegs:$dst), (i32 (trunc (cttz (i64 DoubleRegs:$src1)))))]>; -let neverHasSideEffects = 1, isPredicated = 1 in -def TFRI_cNotPt : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, - s12Imm:$src2), - "if (!$src1) $dst = #$src2", - []>; +def TSTBIT_rr : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + "$dst = tstbit($src1, $src2)", + [(set (i1 PredRegs:$dst), + (setne (and (shl 1, (i32 IntRegs:$src2)), (i32 IntRegs:$src1)), 0))]>; -let neverHasSideEffects = 1, isPredicated = 1 in -def TFR_cdnPt : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, - IntRegs:$src2), - "if ($src1.new) $dst = $src2", - []>; +def TSTBIT_ri : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), + "$dst = tstbit($src1, $src2)", + [(set (i1 PredRegs:$dst), + (setne (and (shl 1, (u5ImmPred:$src2)), (i32 IntRegs:$src1)), 0))]>; -let neverHasSideEffects = 1, isPredicated = 1 in -def TFR_cdnNotPt : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, - IntRegs:$src2), - "if (!$src1.new) $dst = $src2", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def TFRI_cdnPt : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, - s12Imm:$src2), - "if ($src1.new) $dst = #$src2", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def TFRI_cdnNotPt : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, - s12Imm:$src2), - "if (!$src1.new) $dst = #$src2", - []>; - -// Compare. -defm CMPGTU : CMP32_rr_ri_u9<"cmp.gtu", setugt>; -defm CMPGT : CMP32_rr_ri_s10<"cmp.gt", setgt>; -defm CMPLT : CMP32_rr<"cmp.lt", setlt>; -defm CMPLTU : CMP32_rr<"cmp.ltu", setult>; -defm CMPEQ : CMP32_rr_ri_s10<"cmp.eq", seteq>; -defm CMPGE : CMP32_ri_s8<"cmp.ge", setge>; -defm CMPGEU : CMP32_ri_u8<"cmp.geu", setuge>; //===----------------------------------------------------------------------===// // ALU32/PRED - //===----------------------------------------------------------------------===// @@ -608,11 +684,6 @@ def SUB64_rr : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, // Subtract halfword. -// Transfer register. -let neverHasSideEffects = 1 in -def TFR_64 : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1), - "$dst = $src1", - []>; //===----------------------------------------------------------------------===// // ALU64/ALU - //===----------------------------------------------------------------------===// @@ -784,7 +855,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, @@ -818,241 +889,218 @@ let isReturn = 1, isTerminator = 1, isBarrier = 1, isPredicated = 1, // LD + //===----------------------------------------------------------------------===// /// -/// Make sure that in post increment load, the first operand is always the post -/// increment operand. -/// -// Load doubleword. -let isPredicable = 1 in -def LDrid : LDInst<(outs DoubleRegs:$dst), - (ins MEMri:$addr), - "$dst = memd($addr)", - [(set (i64 DoubleRegs:$dst), (i64 (load ADDRriS11_3:$addr)))]>; - -let isPredicable = 1, AddedComplexity = 20 in -def LDrid_indexed : LDInst<(outs DoubleRegs:$dst), - (ins IntRegs:$src1, s11_3Imm:$offset), - "$dst = memd($src1+#$offset)", - [(set (i64 DoubleRegs:$dst), - (i64 (load (add (i32 IntRegs:$src1), - s11_3ImmPred:$offset))))]>; +// 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), + (ins PredRegs:$src1, MEMri:$addr), + !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + ") ")#"$dst = "#mnemonic#"($addr)", + []>; +} -let neverHasSideEffects = 1 in -def LDrid_GP : LDInst2<(outs DoubleRegs:$dst), - (ins globaladdress:$global, u16Imm:$offset), - "$dst = memd(#$global+$offset)", - []>, - Requires<[NoV4T]>; +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>; + // Predicate new + defm _cdn#NAME : LD_MEMri_Pbase<mnemonic, RC, PredNot, 1>; + } +} -let neverHasSideEffects = 1 in -def LDd_GP : LDInst2<(outs DoubleRegs:$dst), - (ins globaladdress:$global), - "$dst = memd(#$global)", - []>, - Requires<[NoV4T]>; - -let isPredicable = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in -def POST_LDrid : LDInst2PI<(outs DoubleRegs:$dst, IntRegs:$dst2), - (ins IntRegs:$src1, s4Imm:$offset), - "$dst = memd($src1++#$offset)", - [], - "$src1 = $dst2">; +let isExtendable = 1, neverHasSideEffects = 1 in +multiclass LD_MEMri<string mnemonic, string CextOp, RegisterClass RC, + bits<5> ImmBits, bits<5> PredImmBits> { -// Load doubleword conditionally. -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrid_cPt : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if ($src1) $dst = memd($addr)", - []>; + 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), + "$dst = "#mnemonic#"($addr)", + []>; + let opExtendable = 3, isExtentSigned = 0, opExtentBits = PredImmBits, + isPredicated = 1 in { + defm Pt : LD_MEMri_Pred<mnemonic, RC, 0 >; + defm NotPt : LD_MEMri_Pred<mnemonic, RC, 1 >; + } + } +} -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrid_cNotPt : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if (!$src1) $dst = memd($addr)", - []>; +let addrMode = BaseImmOffset, isMEMri = "true" in { + defm LDrib: LD_MEMri < "memb", "LDrib", IntRegs, 11, 6>, AddrModeRel; + defm LDriub: LD_MEMri < "memub" , "LDriub", IntRegs, 11, 6>, AddrModeRel; + defm LDrih: LD_MEMri < "memh", "LDrih", IntRegs, 12, 7>, AddrModeRel; + defm LDriuh: LD_MEMri < "memuh", "LDriuh", IntRegs, 12, 7>, AddrModeRel; + defm LDriw: LD_MEMri < "memw", "LDriw", IntRegs, 13, 8>, AddrModeRel; + defm LDrid: LD_MEMri < "memd", "LDrid", DoubleRegs, 14, 9>, AddrModeRel; +} -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrid_indexed_cPt : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_3Imm:$src3), - "if ($src1) $dst = memd($src2+#$src3)", - []>; +def : Pat < (i32 (sextloadi8 ADDRriS11_0:$addr)), + (LDrib ADDRriS11_0:$addr) >; -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrid_indexed_cNotPt : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_3Imm:$src3), - "if (!$src1) $dst = memd($src2+#$src3)", - []>; +def : Pat < (i32 (zextloadi8 ADDRriS11_0:$addr)), + (LDriub ADDRriS11_0:$addr) >; -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDrid_cPt : LDInst2PI<(outs DoubleRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_3Imm:$src3), - "if ($src1) $dst1 = memd($src2++#$src3)", - [], - "$src2 = $dst2">; +def : Pat < (i32 (sextloadi16 ADDRriS11_1:$addr)), + (LDrih ADDRriS11_1:$addr) >; -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDrid_cNotPt : LDInst2PI<(outs DoubleRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_3Imm:$src3), - "if (!$src1) $dst1 = memd($src2++#$src3)", - [], - "$src2 = $dst2">; +def : Pat < (i32 (zextloadi16 ADDRriS11_1:$addr)), + (LDriuh ADDRriS11_1:$addr) >; -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrid_cdnPt : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if ($src1.new) $dst = memd($addr)", - []>; +def : Pat < (i32 (load ADDRriS11_2:$addr)), + (LDriw ADDRriS11_2:$addr) >; -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrid_cdnNotPt : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if (!$src1.new) $dst = memd($addr)", - []>; +def : Pat < (i64 (load ADDRriS11_3:$addr)), + (LDrid ADDRriS11_3:$addr) >; -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrid_indexed_cdnPt : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_3Imm:$src3), - "if ($src1.new) $dst = memd($src2+#$src3)", - []>; -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrid_indexed_cdnNotPt : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_3Imm:$src3), - "if (!$src1.new) $dst = memd($src2+#$src3)", +// 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) ", + ") ")#"$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>; + // Predicate new + defm _cdn#NAME : LD_Idxd_Pbase<mnemonic, RC, predImmOp, PredNot, 1>; + } +} -// Load byte. -let isPredicable = 1 in -def LDrib : LDInst<(outs IntRegs:$dst), - (ins MEMri:$addr), - "$dst = memb($addr)", - [(set (i32 IntRegs:$dst), (i32 (sextloadi8 ADDRriS11_0:$addr)))]>; - -// Load byte any-extend. -def : Pat < (i32 (extloadi8 ADDRriS11_0:$addr)), - (i32 (LDrib ADDRriS11_0:$addr)) >; +let isExtendable = 1, neverHasSideEffects = 1 in +multiclass LD_Idxd<string mnemonic, string CextOp, RegisterClass RC, + Operand ImmOp, Operand predImmOp, bits<5> ImmBits, + bits<5> PredImmBits> { -// Indexed load byte. -let isPredicable = 1, AddedComplexity = 20 in -def LDrib_indexed : LDInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, s11_0Imm:$offset), - "$dst = memb($src1+#$offset)", - [(set (i32 IntRegs:$dst), - (i32 (sextloadi8 (add (i32 IntRegs:$src1), - s11_0ImmPred:$offset))))]>; + 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), + "$dst = "#mnemonic#"($src1+#$offset)", + []>; -// Indexed load byte any-extend. -let AddedComplexity = 20 in -def : Pat < (i32 (extloadi8 (add IntRegs:$src1, s11_0ImmPred:$offset))), - (i32 (LDrib_indexed IntRegs:$src1, s11_0ImmPred:$offset)) >; + let opExtendable = 3, isExtentSigned = 0, opExtentBits = PredImmBits, + isPredicated = 1 in { + defm Pt : LD_Idxd_Pred<mnemonic, RC, predImmOp, 0 >; + defm NotPt : LD_Idxd_Pred<mnemonic, RC, predImmOp, 1 >; + } + } +} -let neverHasSideEffects = 1 in -def LDrib_GP : LDInst2<(outs IntRegs:$dst), - (ins globaladdress:$global, u16Imm:$offset), - "$dst = memb(#$global+$offset)", - []>, - Requires<[NoV4T]>; +let addrMode = BaseImmOffset in { + defm LDrib_indexed: LD_Idxd <"memb", "LDrib", IntRegs, s11_0Ext, u6_0Ext, + 11, 6>, AddrModeRel; + defm LDriub_indexed: LD_Idxd <"memub" , "LDriub", IntRegs, s11_0Ext, u6_0Ext, + 11, 6>, AddrModeRel; + defm LDrih_indexed: LD_Idxd <"memh", "LDrih", IntRegs, s11_1Ext, u6_1Ext, + 12, 7>, AddrModeRel; + defm LDriuh_indexed: LD_Idxd <"memuh", "LDriuh", IntRegs, s11_1Ext, u6_1Ext, + 12, 7>, AddrModeRel; + defm LDriw_indexed: LD_Idxd <"memw", "LDriw", IntRegs, s11_2Ext, u6_2Ext, + 13, 8>, AddrModeRel; + defm LDrid_indexed: LD_Idxd <"memd", "LDrid", DoubleRegs, s11_3Ext, u6_3Ext, + 14, 9>, AddrModeRel; +} -let neverHasSideEffects = 1 in -def LDb_GP : LDInst2<(outs IntRegs:$dst), - (ins globaladdress:$global), - "$dst = memb(#$global)", - []>, - Requires<[NoV4T]>; +let AddedComplexity = 20 in { +def : Pat < (i32 (sextloadi8 (add IntRegs:$src1, s11_0ExtPred:$offset))), + (LDrib_indexed IntRegs:$src1, s11_0ExtPred:$offset) >; -let neverHasSideEffects = 1 in -def LDub_GP : LDInst2<(outs IntRegs:$dst), - (ins globaladdress:$global), - "$dst = memub(#$global)", - []>, - Requires<[NoV4T]>; - -let isPredicable = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in -def POST_LDrib : LDInst2PI<(outs IntRegs:$dst, IntRegs:$dst2), - (ins IntRegs:$src1, s4Imm:$offset), - "$dst = memb($src1++#$offset)", - [], - "$src1 = $dst2">; +def : Pat < (i32 (zextloadi8 (add IntRegs:$src1, s11_0ExtPred:$offset))), + (LDriub_indexed IntRegs:$src1, s11_0ExtPred:$offset) >; -// Load byte conditionally. -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrib_cPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if ($src1) $dst = memb($addr)", - []>; +def : Pat < (i32 (sextloadi16 (add IntRegs:$src1, s11_1ExtPred:$offset))), + (LDrih_indexed IntRegs:$src1, s11_1ExtPred:$offset) >; -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrib_cNotPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if (!$src1) $dst = memb($addr)", - []>; +def : Pat < (i32 (zextloadi16 (add IntRegs:$src1, s11_1ExtPred:$offset))), + (LDriuh_indexed IntRegs:$src1, s11_1ExtPred:$offset) >; -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrib_indexed_cPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3), - "if ($src1) $dst = memb($src2+#$src3)", - []>; +def : Pat < (i32 (load (add IntRegs:$src1, s11_2ExtPred:$offset))), + (LDriw_indexed IntRegs:$src1, s11_2ExtPred:$offset) >; -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrib_indexed_cNotPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3), - "if (!$src1) $dst = memb($src2+#$src3)", - []>; +def : Pat < (i64 (load (add IntRegs:$src1, s11_3ExtPred:$offset))), + (LDrid_indexed IntRegs:$src1, s11_3ExtPred:$offset) >; +} -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDrib_cPt : LDInst2PI<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_0Imm:$src3), - "if ($src1) $dst1 = memb($src2++#$src3)", - [], - "$src2 = $dst2">; +//===----------------------------------------------------------------------===// +// Post increment load +// Make sure that in post increment load, the first operand is always the post +// increment operand. +//===----------------------------------------------------------------------===// -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDrib_cNotPt : LDInst2PI<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_0Imm:$src3), - "if (!$src1) $dst1 = memb($src2++#$src3)", +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), + (ins PredRegs:$src1, IntRegs:$src2, ImmOp:$offset), + !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + ") ")#"$dst = "#mnemonic#"($src2++#$offset)", [], "$src2 = $dst2">; +} -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrib_cdnPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if ($src1.new) $dst = memb($addr)", - []>; +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>; + // Predicate new + let Predicates = [HasV4T], validSubTargets = HasV4SubT in + defm _cdn#NAME#_V4 : LD_PostInc_Pbase<mnemonic, RC, ImmOp, PredNot, 1>; + } +} -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrib_cdnNotPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if (!$src1.new) $dst = memb($addr)", - []>; +multiclass LD_PostInc<string mnemonic, string BaseOp, RegisterClass RC, + Operand ImmOp> { -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrib_indexed_cdnPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3), - "if ($src1.new) $dst = memb($src2+#$src3)", - []>; + let BaseOpcode = "POST_"#BaseOp in { + let isPredicable = 1 in + def NAME : LDInst2PI<(outs RC:$dst, IntRegs:$dst2), + (ins IntRegs:$src1, ImmOp:$offset), + "$dst = "#mnemonic#"($src1++#$offset)", + [], + "$src1 = $dst2">; + + let isPredicated = 1 in { + defm Pt : LD_PostInc_Pred<mnemonic, RC, ImmOp, 0 >; + defm NotPt : LD_PostInc_Pred<mnemonic, RC, ImmOp, 1 >; + } + } +} -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrib_indexed_cdnNotPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3), - "if (!$src1.new) $dst = memb($src2+#$src3)", - []>; +let hasCtrlDep = 1, neverHasSideEffects = 1 in { + defm POST_LDrib : LD_PostInc<"memb", "LDrib", IntRegs, s4_0Imm>, + PredNewRel; + defm POST_LDriub : LD_PostInc<"memub", "LDriub", IntRegs, s4_0Imm>, + PredNewRel; + defm POST_LDrih : LD_PostInc<"memh", "LDrih", IntRegs, s4_1Imm>, + PredNewRel; + defm POST_LDriuh : LD_PostInc<"memuh", "LDriuh", IntRegs, s4_1Imm>, + PredNewRel; + defm POST_LDriw : LD_PostInc<"memw", "LDriw", IntRegs, s4_2Imm>, + PredNewRel; + defm POST_LDrid : LD_PostInc<"memd", "LDrid", DoubleRegs, s4_3Imm>, + PredNewRel; +} +def : Pat< (i32 (extloadi1 ADDRriS11_0:$addr)), + (i32 (LDrib ADDRriS11_0:$addr)) >; -// Load halfword. -let isPredicable = 1 in -def LDrih : LDInst<(outs IntRegs:$dst), - (ins MEMri:$addr), - "$dst = memh($addr)", - [(set (i32 IntRegs:$dst), (i32 (sextloadi16 ADDRriS11_1:$addr)))]>; +// Load byte any-extend. +def : Pat < (i32 (extloadi8 ADDRriS11_0:$addr)), + (i32 (LDrib ADDRriS11_0:$addr)) >; -let isPredicable = 1, AddedComplexity = 20 in -def LDrih_indexed : LDInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, s11_1Imm:$offset), - "$dst = memh($src1+#$offset)", - [(set (i32 IntRegs:$dst), - (i32 (sextloadi16 (add (i32 IntRegs:$src1), - s11_1ImmPred:$offset))))]>; +// Indexed load byte any-extend. +let AddedComplexity = 20 in +def : Pat < (i32 (extloadi8 (add IntRegs:$src1, s11_0ImmPred:$offset))), + (i32 (LDrib_indexed IntRegs:$src1, s11_0ImmPred:$offset)) >; def : Pat < (i32 (extloadi16 ADDRriS11_1:$addr)), (i32 (LDrih ADDRriS11_1:$addr))>; @@ -1061,399 +1109,25 @@ let AddedComplexity = 20 in def : Pat < (i32 (extloadi16 (add IntRegs:$src1, s11_1ImmPred:$offset))), (i32 (LDrih_indexed IntRegs:$src1, s11_1ImmPred:$offset)) >; -let neverHasSideEffects = 1 in -def LDrih_GP : LDInst2<(outs IntRegs:$dst), - (ins globaladdress:$global, u16Imm:$offset), - "$dst = memh(#$global+$offset)", - []>, - Requires<[NoV4T]>; - -let neverHasSideEffects = 1 in -def LDh_GP : LDInst2<(outs IntRegs:$dst), - (ins globaladdress:$global), - "$dst = memh(#$global)", - []>, - Requires<[NoV4T]>; - -let neverHasSideEffects = 1 in -def LDuh_GP : LDInst2<(outs IntRegs:$dst), - (ins globaladdress:$global), - "$dst = memuh(#$global)", - []>, - Requires<[NoV4T]>; - -let isPredicable = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in -def POST_LDrih : LDInst2PI<(outs IntRegs:$dst, IntRegs:$dst2), - (ins IntRegs:$src1, s4Imm:$offset), - "$dst = memh($src1++#$offset)", - [], - "$src1 = $dst2">; - -// Load halfword conditionally. -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrih_cPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if ($src1) $dst = memh($addr)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrih_cNotPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if (!$src1) $dst = memh($addr)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrih_indexed_cPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3), - "if ($src1) $dst = memh($src2+#$src3)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrih_indexed_cNotPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3), - "if (!$src1) $dst = memh($src2+#$src3)", - []>; - -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDrih_cPt : LDInst2PI<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_1Imm:$src3), - "if ($src1) $dst1 = memh($src2++#$src3)", - [], - "$src2 = $dst2">; - -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDrih_cNotPt : LDInst2PI<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_1Imm:$src3), - "if (!$src1) $dst1 = memh($src2++#$src3)", - [], - "$src2 = $dst2">; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrih_cdnPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if ($src1.new) $dst = memh($addr)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrih_cdnNotPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if (!$src1.new) $dst = memh($addr)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrih_indexed_cdnPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3), - "if ($src1.new) $dst = memh($src2+#$src3)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDrih_indexed_cdnNotPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3), - "if (!$src1.new) $dst = memh($src2+#$src3)", - []>; - -// Load unsigned byte. -let isPredicable = 1 in -def LDriub : LDInst<(outs IntRegs:$dst), - (ins MEMri:$addr), - "$dst = memub($addr)", - [(set (i32 IntRegs:$dst), (i32 (zextloadi8 ADDRriS11_0:$addr)))]>; - +let AddedComplexity = 10 in def : Pat < (i32 (zextloadi1 ADDRriS11_0:$addr)), (i32 (LDriub ADDRriS11_0:$addr))>; -let isPredicable = 1, AddedComplexity = 20 in -def LDriub_indexed : LDInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, s11_0Imm:$offset), - "$dst = memub($src1+#$offset)", - [(set (i32 IntRegs:$dst), - (i32 (zextloadi8 (add (i32 IntRegs:$src1), - s11_0ImmPred:$offset))))]>; - let AddedComplexity = 20 in def : Pat < (i32 (zextloadi1 (add IntRegs:$src1, s11_0ImmPred:$offset))), (i32 (LDriub_indexed IntRegs:$src1, s11_0ImmPred:$offset))>; -let neverHasSideEffects = 1 in -def LDriub_GP : LDInst2<(outs IntRegs:$dst), - (ins globaladdress:$global, u16Imm:$offset), - "$dst = memub(#$global+$offset)", - []>, - Requires<[NoV4T]>; - -let isPredicable = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in -def POST_LDriub : LDInst2PI<(outs IntRegs:$dst, IntRegs:$dst2), - (ins IntRegs:$src1, s4Imm:$offset), - "$dst = memub($src1++#$offset)", - [], - "$src1 = $dst2">; - -// Load unsigned byte conditionally. -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriub_cPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if ($src1) $dst = memub($addr)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriub_cNotPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if (!$src1) $dst = memub($addr)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriub_indexed_cPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3), - "if ($src1) $dst = memub($src2+#$src3)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriub_indexed_cNotPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3), - "if (!$src1) $dst = memub($src2+#$src3)", - []>; - -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDriub_cPt : LDInst2PI<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_0Imm:$src3), - "if ($src1) $dst1 = memub($src2++#$src3)", - [], - "$src2 = $dst2">; - -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDriub_cNotPt : LDInst2PI<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_0Imm:$src3), - "if (!$src1) $dst1 = memub($src2++#$src3)", - [], - "$src2 = $dst2">; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriub_cdnPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if ($src1.new) $dst = memub($addr)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriub_cdnNotPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if (!$src1.new) $dst = memub($addr)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriub_indexed_cdnPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3), - "if ($src1.new) $dst = memub($src2+#$src3)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriub_indexed_cdnNotPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3), - "if (!$src1.new) $dst = memub($src2+#$src3)", - []>; - -// Load unsigned halfword. -let isPredicable = 1 in -def LDriuh : LDInst<(outs IntRegs:$dst), - (ins MEMri:$addr), - "$dst = memuh($addr)", - [(set (i32 IntRegs:$dst), (i32 (zextloadi16 ADDRriS11_1:$addr)))]>; - -// Indexed load unsigned halfword. -let isPredicable = 1, AddedComplexity = 20 in -def LDriuh_indexed : LDInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, s11_1Imm:$offset), - "$dst = memuh($src1+#$offset)", - [(set (i32 IntRegs:$dst), - (i32 (zextloadi16 (add (i32 IntRegs:$src1), - s11_1ImmPred:$offset))))]>; - -let neverHasSideEffects = 1 in -def LDriuh_GP : LDInst2<(outs IntRegs:$dst), - (ins globaladdress:$global, u16Imm:$offset), - "$dst = memuh(#$global+$offset)", - []>, - Requires<[NoV4T]>; - -let isPredicable = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in -def POST_LDriuh : LDInst2PI<(outs IntRegs:$dst, IntRegs:$dst2), - (ins IntRegs:$src1, s4Imm:$offset), - "$dst = memuh($src1++#$offset)", - [], - "$src1 = $dst2">; - -// Load unsigned halfword conditionally. -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriuh_cPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if ($src1) $dst = memuh($addr)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriuh_cNotPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if (!$src1) $dst = memuh($addr)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriuh_indexed_cPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3), - "if ($src1) $dst = memuh($src2+#$src3)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriuh_indexed_cNotPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3), - "if (!$src1) $dst = memuh($src2+#$src3)", - []>; - -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDriuh_cPt : LDInst2PI<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_1Imm:$src3), - "if ($src1) $dst1 = memuh($src2++#$src3)", - [], - "$src2 = $dst2">; - -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDriuh_cNotPt : LDInst2PI<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_1Imm:$src3), - "if (!$src1) $dst1 = memuh($src2++#$src3)", - [], - "$src2 = $dst2">; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriuh_cdnPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if ($src1.new) $dst = memuh($addr)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriuh_cdnNotPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if (!$src1.new) $dst = memuh($addr)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriuh_indexed_cdnPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3), - "if ($src1.new) $dst = memuh($src2+#$src3)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriuh_indexed_cdnNotPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3), - "if (!$src1.new) $dst = memuh($src2+#$src3)", - []>; - - -// Load word. -let isPredicable = 1 in -def LDriw : LDInst<(outs IntRegs:$dst), - (ins MEMri:$addr), "$dst = memw($addr)", - [(set IntRegs:$dst, (i32 (load ADDRriS11_2:$addr)))]>; - // 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", []>; -// Indexed load. -let isPredicable = 1, AddedComplexity = 20 in -def LDriw_indexed : LDInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, s11_2Imm:$offset), - "$dst = memw($src1+#$offset)", - [(set IntRegs:$dst, (i32 (load (add IntRegs:$src1, - s11_2ImmPred:$offset))))]>; - -let neverHasSideEffects = 1 in -def LDriw_GP : LDInst2<(outs IntRegs:$dst), - (ins globaladdress:$global, u16Imm:$offset), - "$dst = memw(#$global+$offset)", - []>, - Requires<[NoV4T]>; - -let neverHasSideEffects = 1 in -def LDw_GP : LDInst2<(outs IntRegs:$dst), - (ins globaladdress:$global), - "$dst = memw(#$global)", - []>, - Requires<[NoV4T]>; - -let isPredicable = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in -def POST_LDriw : LDInst2PI<(outs IntRegs:$dst, IntRegs:$dst2), - (ins IntRegs:$src1, s4Imm:$offset), - "$dst = memw($src1++#$offset)", - [], - "$src1 = $dst2">; - -// Load word conditionally. - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriw_cPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if ($src1) $dst = memw($addr)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriw_cNotPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if (!$src1) $dst = memw($addr)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriw_indexed_cPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3), - "if ($src1) $dst = memw($src2+#$src3)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriw_indexed_cNotPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3), - "if (!$src1) $dst = memw($src2+#$src3)", - []>; - -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDriw_cPt : LDInst2PI<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_2Imm:$src3), - "if ($src1) $dst1 = memw($src2++#$src3)", - [], - "$src2 = $dst2">; - -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDriw_cNotPt : LDInst2PI<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_2Imm:$src3), - "if (!$src1) $dst1 = memw($src2++#$src3)", - [], - "$src2 = $dst2">; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriw_cdnPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if ($src1.new) $dst = memw($addr)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriw_cdnNotPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, MEMri:$addr), - "if (!$src1.new) $dst = memw($addr)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriw_indexed_cdnPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3), - "if ($src1.new) $dst = memw($src2+#$src3)", - []>; - -let neverHasSideEffects = 1, isPredicated = 1 in -def LDriw_indexed_cdnNotPt : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3), - "if (!$src1.new) $dst = memw($src2+#$src3)", - []>; - // 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", []>; } @@ -1482,57 +1156,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. @@ -1601,7 +1283,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))), @@ -1609,37 +1291,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 - @@ -1670,282 +1358,219 @@ def SUBri_acc : MInst_acc<(outs IntRegs: $dst), (ins IntRegs:$src1, // ST + //===----------------------------------------------------------------------===// /// -/// Assumptions::: ****** DO NOT IGNORE ******** -/// 1. Make sure that in post increment store, the zero'th operand is always the -/// post increment operand. -/// 2. Make sure that the store value operand(Rt/Rtt) in a store is always the -/// last operand. -/// // Store doubleword. -let isPredicable = 1 in -def STrid : STInst<(outs), - (ins MEMri:$addr, DoubleRegs:$src1), - "memd($addr) = $src1", - [(store (i64 DoubleRegs:$src1), ADDRriS11_3:$addr)]>; - -// Indexed store double word. -let AddedComplexity = 10, isPredicable = 1 in -def STrid_indexed : STInst<(outs), - (ins IntRegs:$src1, s11_3Imm:$src2, DoubleRegs:$src3), - "memd($src1+#$src2) = $src3", - [(store (i64 DoubleRegs:$src3), - (add (i32 IntRegs:$src1), s11_3ImmPred:$src2))]>; -let neverHasSideEffects = 1 in -def STrid_GP : STInst2<(outs), - (ins globaladdress:$global, u16Imm:$offset, DoubleRegs:$src), - "memd(#$global+$offset) = $src", - []>, - Requires<[NoV4T]>; +//===----------------------------------------------------------------------===// +// Post increment store +//===----------------------------------------------------------------------===// -let neverHasSideEffects = 1 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))], +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", + [], "$src2 = $dst">; +} -// Store doubleword conditionally. -// if ([!]Pv) memd(Rs+#u6:3)=Rtt -// if (Pv) memd(Rs+#u6:3)=Rtt -let AddedComplexity = 10, neverHasSideEffects = 1, - isPredicated = 1 in -def STrid_cPt : STInst2<(outs), - (ins PredRegs:$src1, MEMri:$addr, DoubleRegs:$src2), - "if ($src1) memd($addr) = $src2", - []>; +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>; + } +} -// if (!Pv) memd(Rs+#u6:3)=Rtt -let AddedComplexity = 10, neverHasSideEffects = 1, - isPredicated = 1 in -def STrid_cNotPt : STInst2<(outs), - (ins PredRegs:$src1, MEMri:$addr, DoubleRegs:$src2), - "if (!$src1) memd($addr) = $src2", - []>; +let hasCtrlDep = 1, isNVStorable = 1, neverHasSideEffects = 1 in +multiclass ST_PostInc<string mnemonic, string BaseOp, RegisterClass RC, + Operand ImmOp> { -// if (Pv) memd(Rs+#u6:3)=Rtt -let AddedComplexity = 10, neverHasSideEffects = 1, - isPredicated = 1 in -def STrid_indexed_cPt : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_3Imm:$src3, - DoubleRegs:$src4), - "if ($src1) memd($src2+#$src3) = $src4", - []>; + 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 >; + } + } +} -// if (!Pv) memd(Rs+#u6:3)=Rtt -let AddedComplexity = 10, neverHasSideEffects = 1, - isPredicated = 1 in -def STrid_indexed_cNotPt : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_3Imm:$src3, - DoubleRegs:$src4), - "if (!$src1) memd($src2+#$src3) = $src4", - []>; +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; -// 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", - [], - "$src3 = $dst">; +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)>; -// Store byte. -// memb(Rs+#s11:0)=Rt -let isPredicable = 1 in -def STrib : STInst<(outs), - (ins MEMri:$addr, IntRegs:$src1), - "memb($addr) = $src1", - [(truncstorei8 (i32 IntRegs:$src1), ADDRriS11_0:$addr)]>; - -let AddedComplexity = 10, isPredicable = 1 in -def STrib_indexed : STInst<(outs), - (ins IntRegs:$src1, s11_0Imm:$src2, IntRegs:$src3), - "memb($src1+#$src2) = $src3", - [(truncstorei8 (i32 IntRegs:$src3), (add (i32 IntRegs:$src1), - s11_0ImmPred:$src2))]>; - -// memb(gp+#u16:0)=Rt -let neverHasSideEffects = 1 in -def STrib_GP : STInst2<(outs), - (ins globaladdress:$global, u16Imm:$offset, IntRegs:$src), - "memb(#$global+$offset) = $src", - []>, - Requires<[NoV4T]>; +def : Pat<(post_truncsti16 (i32 IntRegs:$src1), IntRegs:$src2, + s4_3ImmPred:$offset), + (POST_SThri IntRegs:$src2, s4_1ImmPred:$offset, IntRegs:$src1)>; -// memb(#global)=Rt -let neverHasSideEffects = 1 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">; +def : Pat<(post_store (i32 IntRegs:$src1), IntRegs:$src2, s4_2ImmPred:$offset), + (POST_STwri IntRegs:$src2, s4_1ImmPred:$offset, IntRegs:$src1)>; -// Store byte conditionally. -// if ([!]Pv) memb(Rs+#u6:0)=Rt -// if (Pv) memb(Rs+#u6:0)=Rt -let neverHasSideEffects = 1, isPredicated = 1 in -def STrib_cPt : STInst2<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if ($src1) memb($addr) = $src2", - []>; +def : Pat<(post_store (i64 DoubleRegs:$src1), IntRegs:$src2, + s4_3ImmPred:$offset), + (POST_STdri IntRegs:$src2, s4_3ImmPred:$offset, DoubleRegs:$src1)>; -// if (!Pv) memb(Rs+#u6:0)=Rt -let neverHasSideEffects = 1, isPredicated = 1 in -def STrib_cNotPt : STInst2<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if (!$src1) memb($addr) = $src2", +//===----------------------------------------------------------------------===// +// 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), + (ins PredRegs:$src1, MEMri:$addr, RC: $src2), + !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + ") ")#mnemonic#"($addr) = $src2", []>; +} -// if (Pv) memb(Rs+#u6:0)=Rt -let neverHasSideEffects = 1, isPredicated = 1 in -def STrib_indexed_cPt : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, IntRegs:$src4), - "if ($src1) memb($src2+#$src3) = $src4", - []>; +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>; -// if (!Pv) memb(Rs+#u6:0)=Rt -let neverHasSideEffects = 1, isPredicated = 1 in -def STrib_indexed_cNotPt : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, IntRegs:$src4), - "if (!$src1) memb($src2+#$src3) = $src4", - []>; + // Predicate new + let validSubTargets = HasV4SubT, Predicates = [HasV4T] in + defm _cdn#NAME#_V4 : ST_MEMri_Pbase<mnemonic, RC, PredNot, 1>; + } +} -// 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">; +let isExtendable = 1, isNVStorable = 1, neverHasSideEffects = 1 in +multiclass ST_MEMri<string mnemonic, string CextOp, RegisterClass RC, + bits<5> ImmBits, bits<5> PredImmBits> { -// 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 CextOpcode = CextOp, BaseOpcode = CextOp in { + let opExtendable = 1, isExtentSigned = 1, opExtentBits = ImmBits, + isPredicable = 1 in + def NAME : STInst2<(outs), + (ins MEMri:$addr, RC:$src), + mnemonic#"($addr) = $src", + []>; + let opExtendable = 2, isExtentSigned = 0, opExtentBits = PredImmBits, + isPredicated = 1 in { + defm Pt : ST_MEMri_Pred<mnemonic, RC, 0>; + defm NotPt : ST_MEMri_Pred<mnemonic, RC, 1>; + } + } +} -// Store halfword. -// memh(Rs+#s11:1)=Rt -let isPredicable = 1 in -def STrih : STInst<(outs), - (ins MEMri:$addr, IntRegs:$src1), - "memh($addr) = $src1", - [(truncstorei16 (i32 IntRegs:$src1), ADDRriS11_1:$addr)]>; +let addrMode = BaseImmOffset, isMEMri = "true" in { + defm STrib: ST_MEMri < "memb", "STrib", IntRegs, 11, 6>, AddrModeRel; + defm STrih: ST_MEMri < "memh", "STrih", IntRegs, 12, 7>, AddrModeRel; + defm STriw: ST_MEMri < "memw", "STriw", IntRegs, 13, 8>, AddrModeRel; + let isNVStorable = 0 in + defm STrid: ST_MEMri < "memd", "STrid", DoubleRegs, 14, 9>, AddrModeRel; +} -let AddedComplexity = 10, isPredicable = 1 in -def STrih_indexed : STInst<(outs), - (ins IntRegs:$src1, s11_1Imm:$src2, IntRegs:$src3), - "memh($src1+#$src2) = $src3", - [(truncstorei16 (i32 IntRegs:$src3), (add (i32 IntRegs:$src1), - s11_1ImmPred:$src2))]>; +def : Pat<(truncstorei8 (i32 IntRegs:$src1), ADDRriS11_0:$addr), + (STrib ADDRriS11_0:$addr, (i32 IntRegs:$src1))>; -let neverHasSideEffects = 1 in -def STrih_GP : STInst2<(outs), - (ins globaladdress:$global, u16Imm:$offset, IntRegs:$src), - "memh(#$global+$offset) = $src", - []>, - Requires<[NoV4T]>; +def : Pat<(truncstorei16 (i32 IntRegs:$src1), ADDRriS11_1:$addr), + (STrih ADDRriS11_1:$addr, (i32 IntRegs:$src1))>; -let neverHasSideEffects = 1 in -def STh_GP : STInst2<(outs), - (ins globaladdress:$global, IntRegs:$src), - "memh(#$global) = $src", - []>, - Requires<[NoV4T]>; +def : Pat<(store (i32 IntRegs:$src1), ADDRriS11_2:$addr), + (STriw ADDRriS11_2:$addr, (i32 IntRegs:$src1))>; -// 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">; +def : Pat<(store (i64 DoubleRegs:$src1), ADDRriS11_3:$addr), + (STrid ADDRriS11_3:$addr, (i64 DoubleRegs:$src1))>; -// Store halfword conditionally. -// if ([!]Pv) memh(Rs+#u6:1)=Rt -// if (Pv) memh(Rs+#u6:1)=Rt -let neverHasSideEffects = 1, isPredicated = 1 in -def STrih_cPt : STInst2<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if ($src1) memh($addr) = $src2", - []>; -// if (!Pv) memh(Rs+#u6:1)=Rt -let neverHasSideEffects = 1, isPredicated = 1 in -def STrih_cNotPt : STInst2<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if (!$src1) memh($addr) = $src2", +//===----------------------------------------------------------------------===// +// multiclass for the store instructions with base+immediate offset +// addressing mode +//===----------------------------------------------------------------------===// +multiclass ST_Idxd_Pbase<string mnemonic, RegisterClass RC, Operand predImmOp, + bit isNot, bit isPredNew> { + 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", []>; +} -// if (Pv) memh(Rs+#u6:1)=Rt -let neverHasSideEffects = 1, isPredicated = 1 in -def STrih_indexed_cPt : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, IntRegs:$src4), - "if ($src1) memh($src2+#$src3) = $src4", - []>; +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>; -// if (!Pv) memh(Rs+#u6:1)=Rt -let neverHasSideEffects = 1, isPredicated = 1 in -def STrih_indexed_cNotPt : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, IntRegs:$src4), - "if (!$src1) memh($src2+#$src3) = $src4", + // Predicate new + let validSubTargets = HasV4SubT, Predicates = [HasV4T] in + defm _cdn#NAME#_V4 : ST_Idxd_Pbase<mnemonic, RC, predImmOp, PredNot, 1>; + } +} + +let isExtendable = 1, isNVStorable = 1, neverHasSideEffects = 1 in +multiclass ST_Idxd<string mnemonic, string CextOp, RegisterClass RC, + Operand ImmOp, Operand predImmOp, bits<5> ImmBits, + bits<5> PredImmBits> { + + let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed in { + let opExtendable = 1, isExtentSigned = 1, opExtentBits = ImmBits, + isPredicable = 1 in + def NAME : STInst2<(outs), + (ins IntRegs:$src1, ImmOp:$src2, RC:$src3), + mnemonic#"($src1+#$src2) = $src3", []>; -// 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">; + let opExtendable = 2, isExtentSigned = 0, opExtentBits = PredImmBits in { + defm Pt : ST_Idxd_Pred<mnemonic, RC, predImmOp, 0>; + defm NotPt : ST_Idxd_Pred<mnemonic, RC, predImmOp, 1>; + } + } +} + +let addrMode = BaseImmOffset, InputType = "reg" in { + defm STrib_indexed: ST_Idxd < "memb", "STrib", IntRegs, s11_0Ext, + u6_0Ext, 11, 6>, AddrModeRel, ImmRegRel; + defm STrih_indexed: ST_Idxd < "memh", "STrih", IntRegs, s11_1Ext, + u6_1Ext, 12, 7>, AddrModeRel, ImmRegRel; + defm STriw_indexed: ST_Idxd < "memw", "STriw", IntRegs, s11_2Ext, + u6_2Ext, 13, 8>, AddrModeRel, ImmRegRel; + let isNVStorable = 0 in + defm STrid_indexed: ST_Idxd < "memd", "STrid", DoubleRegs, s11_3Ext, + u6_3Ext, 14, 9>, AddrModeRel; +} + +let AddedComplexity = 10 in { +def : Pat<(truncstorei8 (i32 IntRegs:$src1), (add IntRegs:$src2, + s11_0ExtPred:$offset)), + (STrib_indexed IntRegs:$src2, s11_0ImmPred:$offset, + (i32 IntRegs:$src1))>; + +def : Pat<(truncstorei16 (i32 IntRegs:$src1), (add IntRegs:$src2, + s11_1ExtPred:$offset)), + (STrih_indexed IntRegs:$src2, s11_1ImmPred:$offset, + (i32 IntRegs:$src1))>; -// 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">; +def : Pat<(store (i32 IntRegs:$src1), (add IntRegs:$src2, + s11_2ExtPred:$offset)), + (STriw_indexed IntRegs:$src2, s11_2ImmPred:$offset, + (i32 IntRegs:$src1))>; +def : Pat<(store (i64 DoubleRegs:$src1), (add IntRegs:$src2, + s11_3ExtPred:$offset)), + (STrid_indexed IntRegs:$src2, s11_3ImmPred:$offset, + (i64 DoubleRegs:$src1))>; +} + +// memh(Rx++#s4:1)=Rt.H // Store word. // Store predicate. @@ -1955,90 +1580,6 @@ def STriw_pred : STInst2<(outs), "Error; should not emit", []>; -// memw(Rs+#s11:2)=Rt -let isPredicable = 1 in -def STriw : STInst<(outs), - (ins MEMri:$addr, IntRegs:$src1), - "memw($addr) = $src1", - [(store (i32 IntRegs:$src1), ADDRriS11_2:$addr)]>; - -let AddedComplexity = 10, isPredicable = 1 in -def STriw_indexed : STInst<(outs), - (ins IntRegs:$src1, s11_2Imm:$src2, IntRegs:$src3), - "memw($src1+#$src2) = $src3", - [(store (i32 IntRegs:$src3), - (add (i32 IntRegs:$src1), s11_2ImmPred:$src2))]>; - -let neverHasSideEffects = 1 in -def STriw_GP : STInst2<(outs), - (ins globaladdress:$global, u16Imm:$offset, IntRegs:$src), - "memw(#$global+$offset) = $src", - []>, - Requires<[NoV4T]>; - -let neverHasSideEffects = 1 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">; - -// Store word conditionally. -// if ([!]Pv) memw(Rs+#u6:2)=Rt -// if (Pv) memw(Rs+#u6:2)=Rt -let neverHasSideEffects = 1, isPredicated = 1 in -def STriw_cPt : STInst2<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if ($src1) memw($addr) = $src2", - []>; - -// if (!Pv) memw(Rs+#u6:2)=Rt -let neverHasSideEffects = 1, isPredicated = 1 in -def STriw_cNotPt : STInst2<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if (!$src1) memw($addr) = $src2", - []>; - -// if (Pv) memw(Rs+#u6:2)=Rt -let neverHasSideEffects = 1, isPredicated = 1 in -def STriw_indexed_cPt : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, IntRegs:$src4), - "if ($src1) memw($src2+#$src3) = $src4", - []>; - -// if (!Pv) memw(Rs+#u6:2)=Rt -let neverHasSideEffects = 1, isPredicated = 1 in -def STriw_indexed_cNotPt : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, IntRegs:$src4), - "if (!$src1) memw($src2+#$src3) = $src4", - []>; - -// 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), @@ -2241,7 +1782,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)]>; @@ -2316,9 +1857,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. @@ -2406,6 +1947,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)", @@ -2509,68 +2054,26 @@ def : Pat<(HexagonTCRet (i32 IntRegs:$dst)), // Atomic load and store support // 8 bit atomic load -def : Pat<(atomic_load_8 (HexagonCONST32_GP tglobaladdr:$global)), - (i32 (LDub_GP tglobaladdr:$global))>, - Requires<[NoV4T]>; - -def : Pat<(atomic_load_8 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset)), - (i32 (LDriub_GP tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[NoV4T]>; - def : Pat<(atomic_load_8 ADDRriS11_0:$src1), (i32 (LDriub ADDRriS11_0:$src1))>; def : Pat<(atomic_load_8 (add (i32 IntRegs:$src1), s11_0ImmPred:$offset)), (i32 (LDriub_indexed (i32 IntRegs:$src1), s11_0ImmPred:$offset))>; - - // 16 bit atomic load -def : Pat<(atomic_load_16 (HexagonCONST32_GP tglobaladdr:$global)), - (i32 (LDuh_GP tglobaladdr:$global))>, - Requires<[NoV4T]>; - -def : Pat<(atomic_load_16 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset)), - (i32 (LDriuh_GP tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[NoV4T]>; - def : Pat<(atomic_load_16 ADDRriS11_1:$src1), (i32 (LDriuh ADDRriS11_1:$src1))>; def : Pat<(atomic_load_16 (add (i32 IntRegs:$src1), s11_1ImmPred:$offset)), (i32 (LDriuh_indexed (i32 IntRegs:$src1), s11_1ImmPred:$offset))>; - - -// 32 bit atomic load -def : Pat<(atomic_load_32 (HexagonCONST32_GP tglobaladdr:$global)), - (i32 (LDw_GP tglobaladdr:$global))>, - Requires<[NoV4T]>; - -def : Pat<(atomic_load_32 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset)), - (i32 (LDriw_GP tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[NoV4T]>; - def : Pat<(atomic_load_32 ADDRriS11_2:$src1), (i32 (LDriw ADDRriS11_2:$src1))>; def : Pat<(atomic_load_32 (add (i32 IntRegs:$src1), s11_2ImmPred:$offset)), (i32 (LDriw_indexed (i32 IntRegs:$src1), s11_2ImmPred:$offset))>; - // 64 bit atomic load -def : Pat<(atomic_load_64 (HexagonCONST32_GP tglobaladdr:$global)), - (i64 (LDd_GP tglobaladdr:$global))>, - Requires<[NoV4T]>; - -def : Pat<(atomic_load_64 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset)), - (i64 (LDrid_GP tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[NoV4T]>; - def : Pat<(atomic_load_64 ADDRriS11_3:$src1), (i64 (LDrid ADDRriS11_3:$src1))>; @@ -2578,30 +2081,6 @@ def : Pat<(atomic_load_64 (add (i32 IntRegs:$src1), s11_3ImmPred:$offset)), (i64 (LDrid_indexed (i32 IntRegs:$src1), s11_3ImmPred:$offset))>; -// 64 bit atomic store -def : Pat<(atomic_store_64 (HexagonCONST32_GP tglobaladdr:$global), - (i64 DoubleRegs:$src1)), - (STd_GP tglobaladdr:$global, (i64 DoubleRegs:$src1))>, - Requires<[NoV4T]>; - -def : Pat<(atomic_store_64 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset), - (i64 DoubleRegs:$src1)), - (STrid_GP tglobaladdr:$global, u16ImmPred:$offset, - (i64 DoubleRegs:$src1))>, Requires<[NoV4T]>; - -// 8 bit atomic store -def : Pat<(atomic_store_8 (HexagonCONST32_GP tglobaladdr:$global), - (i32 IntRegs:$src1)), - (STb_GP tglobaladdr:$global, (i32 IntRegs:$src1))>, - Requires<[NoV4T]>; - -def : Pat<(atomic_store_8 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset), - (i32 IntRegs:$src1)), - (STrib_GP tglobaladdr:$global, u16ImmPred:$offset, - (i32 IntRegs:$src1))>, Requires<[NoV4T]>; - def : Pat<(atomic_store_8 ADDRriS11_0:$src2, (i32 IntRegs:$src1)), (STrib ADDRriS11_0:$src2, (i32 IntRegs:$src1))>; @@ -2611,18 +2090,6 @@ def : Pat<(atomic_store_8 (add (i32 IntRegs:$src2), s11_0ImmPred:$offset), (i32 IntRegs:$src1))>; -// 16 bit atomic store -def : Pat<(atomic_store_16 (HexagonCONST32_GP tglobaladdr:$global), - (i32 IntRegs:$src1)), - (STh_GP tglobaladdr:$global, (i32 IntRegs:$src1))>, - Requires<[NoV4T]>; - -def : Pat<(atomic_store_16 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset), - (i32 IntRegs:$src1)), - (STrih_GP tglobaladdr:$global, u16ImmPred:$offset, - (i32 IntRegs:$src1))>, Requires<[NoV4T]>; - def : Pat<(atomic_store_16 ADDRriS11_1:$src2, (i32 IntRegs:$src1)), (STrih ADDRriS11_1:$src2, (i32 IntRegs:$src1))>; @@ -2631,20 +2098,6 @@ def : Pat<(atomic_store_16 (i32 IntRegs:$src1), (STrih_indexed (i32 IntRegs:$src2), s11_1ImmPred:$offset, (i32 IntRegs:$src1))>; - -// 32 bit atomic store -def : Pat<(atomic_store_32 (HexagonCONST32_GP tglobaladdr:$global), - (i32 IntRegs:$src1)), - (STw_GP tglobaladdr:$global, (i32 IntRegs:$src1))>, - Requires<[NoV4T]>; - -def : Pat<(atomic_store_32 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset), - (i32 IntRegs:$src1)), - (STriw_GP tglobaladdr:$global, u16ImmPred:$offset, - (i32 IntRegs:$src1))>, - Requires<[NoV4T]>; - def : Pat<(atomic_store_32 ADDRriS11_2:$src2, (i32 IntRegs:$src1)), (STriw ADDRriS11_2:$src2, (i32 IntRegs:$src1))>; @@ -2713,198 +2166,8 @@ def : Pat <(brcond (not PredRegs:$src1), bb:$offset), def : Pat <(and PredRegs:$src1, (not PredRegs:$src2)), (i1 (AND_pnotp (i1 PredRegs:$src1), (i1 PredRegs:$src2)))>; -// 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 tglobaladdr:$global, u16ImmPred:$offset, - (i64 DoubleRegs:$src1))>, Requires<[NoV4T]>; - -// Map from store(globaladdress) -> memd(#foo). -let AddedComplexity = 100 in -def : Pat <(store (i64 DoubleRegs:$src1), - (HexagonCONST32_GP tglobaladdr:$global)), - (STd_GP tglobaladdr:$global, (i64 DoubleRegs:$src1))>, - Requires<[NoV4T]>; - -// 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 tglobaladdr:$global, u16ImmPred:$offset, (i32 IntRegs:$src1))>, - Requires<[NoV4T]>; - -// Map from store(globaladdress) -> memw(#foo + 0). -let AddedComplexity = 100 in -def : Pat <(store (i32 IntRegs:$src1), (HexagonCONST32_GP tglobaladdr:$global)), - (STriw_GP tglobaladdr:$global, 0, (i32 IntRegs:$src1))>; - -// Map from store(globaladdress) -> memw(#foo). -let AddedComplexity = 100 in -def : Pat <(store (i32 IntRegs:$src1), (HexagonCONST32_GP tglobaladdr:$global)), - (STriw_GP tglobaladdr:$global, 0, (i32 IntRegs:$src1))>, - Requires<[NoV4T]>; - -// 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 tglobaladdr:$global, u16ImmPred:$offset, (i32 IntRegs:$src1))>, - Requires<[NoV4T]>; - -// Map from store(globaladdress) -> memh(#foo). -let AddedComplexity = 100 in -def : Pat <(truncstorei16 (i32 IntRegs:$src1), - (HexagonCONST32_GP tglobaladdr:$global)), - (STh_GP tglobaladdr:$global, (i32 IntRegs:$src1))>, - Requires<[NoV4T]>; - -// 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 tglobaladdr:$global, u16ImmPred:$offset, (i32 IntRegs:$src1))>, - Requires<[NoV4T]>; - -// Map from store(globaladdress) -> memb(#foo). -let AddedComplexity = 100 in -def : Pat <(truncstorei8 (i32 IntRegs:$src1), - (HexagonCONST32_GP tglobaladdr:$global)), - (STb_GP tglobaladdr:$global, (i32 IntRegs:$src1))>, - Requires<[NoV4T]>; - -// 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 tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[NoV4T]>; - -// Map from load(globaladdress) -> memw(#foo). -let AddedComplexity = 100 in -def : Pat <(i32 (load (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDw_GP tglobaladdr:$global))>, - Requires<[NoV4T]>; - -// 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 tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[NoV4T]>; - -// Map from load(globaladdress) -> memw(#foo + 0). -let AddedComplexity = 100 in -def : Pat <(i64 (load (HexagonCONST32_GP tglobaladdr:$global))), - (i64 (LDd_GP tglobaladdr:$global))>, - Requires<[NoV4T]>; - -// Map from Pd = load(globaladdress) -> Rd = memb(globaladdress), Pd = Rd. -let AddedComplexity = 100 in -def : Pat <(i1 (load (HexagonCONST32_GP tglobaladdr:$global))), - (i1 (TFR_PdRs (i32 (LDb_GP tglobaladdr:$global))))>, - Requires<[NoV4T]>; - -// Map from load(globaladdress + x) -> memh(#foo + x). -let AddedComplexity = 100 in -def : Pat <(i32 (extloadi16 (add (HexagonCONST32_GP tglobaladdr:$global), - u16ImmPred:$offset))), - (i32 (LDrih_GP tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[NoV4T]>; - -// Map from load(globaladdress + x) -> memh(#foo + x). -let AddedComplexity = 100 in -def : Pat <(i32 (sextloadi16 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDrih_GP tglobaladdr:$global, 0))>, - Requires<[NoV4T]>; - -// 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 tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[NoV4T]>; - -// Map from load(globaladdress) -> memuh(#foo). -let AddedComplexity = 100 in -def : Pat <(i32 (zextloadi16 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDriuh_GP tglobaladdr:$global, 0))>, - Requires<[NoV4T]>; - -// Map from load(globaladdress) -> memh(#foo). -let AddedComplexity = 100 in -def : Pat <(i32 (sextloadi16 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDh_GP tglobaladdr:$global))>, - Requires<[NoV4T]>; - -// Map from load(globaladdress) -> memuh(#foo). -let AddedComplexity = 100 in -def : Pat <(i32 (zextloadi16 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDuh_GP tglobaladdr:$global))>, - Requires<[NoV4T]>; - -// 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 tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[NoV4T]>; - -// 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 tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[NoV4T]>; - -// 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 tglobaladdr:$global, u16ImmPred:$offset))>, - Requires<[NoV4T]>; - -// Map from load(globaladdress) -> memb(#foo). -let AddedComplexity = 100 in -def : Pat <(i32 (extloadi8 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDb_GP tglobaladdr:$global))>, - Requires<[NoV4T]>; - -// Map from load(globaladdress) -> memb(#foo). -let AddedComplexity = 100 in -def : Pat <(i32 (sextloadi8 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDb_GP tglobaladdr:$global))>, - Requires<[NoV4T]>; - -// Map from load(globaladdress) -> memub(#foo). -let AddedComplexity = 100 in -def : Pat <(i32 (zextloadi8 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDub_GP tglobaladdr:$global))>, - Requires<[NoV4T]>; - -// When the Interprocedural Global Variable optimizer realizes that a -// certain global variable takes only two constant values, it shrinks the -// global to a boolean. Catch those loads here in the following 3 patterns. -let AddedComplexity = 100 in -def : Pat <(i32 (extloadi1 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDb_GP tglobaladdr:$global))>, - Requires<[NoV4T]>; - -let AddedComplexity = 100 in -def : Pat <(i32 (sextloadi1 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDb_GP tglobaladdr:$global))>, - Requires<[NoV4T]>; - -let AddedComplexity = 100 in -def : Pat <(i32 (zextloadi1 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDub_GP tglobaladdr:$global))>, - Requires<[NoV4T]>; - // Map from i1 loads to 32 bits. This assumes that the i1* is byte aligned. +let AddedComplexity = 10 in def : Pat <(i32 (zextloadi1 ADDRriS11_0:$addr)), (i32 (AND_rr (i32 (LDrib ADDRriS11_0:$addr)), (TFRI 0x1)))>; @@ -3020,12 +2283,6 @@ def : Pat<(truncstorei32 (i64 DoubleRegs:$src), ADDRriS11_0:$addr), def : Pat<(store (i1 -1), ADDRriS11_2:$addr), (STrib ADDRriS11_2:$addr, (TFRI 1))>; -let AddedComplexity = 100 in -// Map from i1 = constant<-1>; memw(CONST32(#foo)) = i1 -> r0 = 1; -// memw(#foo) = r0 -def : Pat<(store (i1 -1), (HexagonCONST32_GP tglobaladdr:$global)), - (STb_GP tglobaladdr:$global, (TFRI 1))>, - Requires<[NoV4T]>; // Map from i1 = constant<-1>; store i1 -> r0 = 1; store r0. def : Pat<(store (i1 -1), ADDRriS11_2:$addr), @@ -3181,23 +2438,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))>; @@ -3218,15 +2506,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)), @@ -3331,6 +2645,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), @@ -3444,32 +2763,3 @@ include "HexagonInstrInfoV5.td" //===----------------------------------------------------------------------===// // V5 Instructions - //===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Generate mapping table to relate non-predicate instructions with their -// predicated formats - true and false. -// - -def getPredOpcode : InstrMapping { - let FilterClass = "PredRel"; - // Instructions with the same BaseOpcode and isNVStore values form a row. - let RowFields = ["BaseOpcode", "isNVStore", "PNewValue"]; - // Instructions with the same predicate sense form a column. - let ColFields = ["PredSense"]; - // The key column is the unpredicated instructions. - let KeyCol = [""]; - // Value columns are PredSense=true and PredSense=false - let ValueCols = [["true"], ["false"]]; -} - -//===----------------------------------------------------------------------===// -// Generate mapping table to relate predicated instructions with their .new -// format. -// -def getPredNewOpcode : InstrMapping { - let FilterClass = "PredNewRel"; - let RowFields = ["BaseOpcode", "PredSense", "isNVStore"]; - let ColFields = ["PNewValue"]; - let KeyCol = [""]; - let ValueCols = [["new"]]; -} diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfoV4.td b/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfoV4.td index 70448fc..cd0e475 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonInstrInfoV4.td +++ b/contrib/llvm/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 @@ -80,190 +95,63 @@ def IMMEXT : Immext<(outs), (ins), //===----------------------------------------------------------------------===// // ALU32 + //===----------------------------------------------------------------------===// - -// Shift halfword. - -let isPredicated = 1 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 -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)", - []>, - 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 -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 - @@ -276,19 +164,44 @@ def TFR_FI_immext_V4 : ALU32_ri<(outs IntRegs:$dst), // Combine // Rdd=combine(Rs, #s8) -let neverHasSideEffects = 1 in -def COMBINE_ri_V4 : ALU32_ri<(outs DoubleRegs:$dst), - (ins IntRegs:$src1, s8Imm:$src2), +let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 8, + neverHasSideEffects = 1, validSubTargets = HasV4SubT in +def COMBINE_rI_V4 : ALU32_ri<(outs DoubleRegs:$dst), + (ins IntRegs:$src1, s8Ext:$src2), "$dst = combine($src1, #$src2)", []>, Requires<[HasV4T]>; + // Rdd=combine(#s8, Rs) -let neverHasSideEffects = 1 in -def COMBINE_ir_V4 : ALU32_ir<(outs DoubleRegs:$dst), - (ins s8Imm:$src1, IntRegs:$src2), +let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 8, + neverHasSideEffects = 1, validSubTargets = HasV4SubT in +def COMBINE_Ir_V4 : ALU32_ir<(outs DoubleRegs:$dst), + (ins s8Ext:$src1, IntRegs:$src2), "$dst = combine(#$src1, $src2)", []>, 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), + (ins s8Imm:$src1, u6Ext:$src2), + "$dst = combine(#$src1, #$src2)", + []>, + Requires<[HasV4T]>; + //===----------------------------------------------------------------------===// // ALU32/PERM + //===----------------------------------------------------------------------===// @@ -300,1436 +213,310 @@ def COMBINE_ir_V4 : ALU32_ir<(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]>; - -let AddedComplexity = 40, isPredicable = 1 in -def LDrid_indexed_shl_V4 : LDInst<(outs DoubleRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$offset), - "$dst=memd($src1+$src2<<#$offset)", - [(set (i64 DoubleRegs:$dst), - (i64 (load (add (i32 IntRegs:$src1), - (shl (i32 IntRegs:$src2), - u2ImmPred:$offset)))))]>, - 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]>; - -// if (Pv) Rd=memd(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDrid_indexed_shl_cPt_V4 : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if ($src1) $dst=memd($src2+$src3<<#$offset)", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) Rd=memd(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDrid_indexed_shl_cdnPt_V4 : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if ($src1.new) $dst=memd($src2+$src3<<#$offset)", - []>, - Requires<[HasV4T]>; - -// if (!Pv) Rd=memd(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDrid_indexed_shl_cNotPt_V4 : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if (!$src1) $dst=memd($src2+$src3<<#$offset)", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) Rd=memd(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDrid_indexed_shl_cdnNotPt_V4 : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if (!$src1.new) $dst=memd($src2+$src3<<#$offset)", - []>, - 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 LDrib_indexed_shl_V4 : LDInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$offset), - "$dst=memb($src1+$src2<<#$offset)", - [(set (i32 IntRegs:$dst), - (i32 (sextloadi8 (add (i32 IntRegs:$src1), - (shl (i32 IntRegs:$src2), - u2ImmPred:$offset)))))]>, - Requires<[HasV4T]>; - -let AddedComplexity = 40, isPredicable = 1 in -def LDriub_indexed_shl_V4 : LDInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$offset), - "$dst=memub($src1+$src2<<#$offset)", - [(set (i32 IntRegs:$dst), - (i32 (zextloadi8 (add (i32 IntRegs:$src1), - (shl (i32 IntRegs:$src2), - u2ImmPred:$offset)))))]>, - 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]>; - -// if (Pv) Rd=memb(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDrib_indexed_shl_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if ($src1) $dst=memb($src2+$src3<<#$offset)", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) Rd=memb(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDrib_indexed_shl_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if ($src1.new) $dst=memb($src2+$src3<<#$offset)", - []>, - Requires<[HasV4T]>; - -// if (!Pv) Rd=memb(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDrib_indexed_shl_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if (!$src1) $dst=memb($src2+$src3<<#$offset)", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) Rd=memb(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDrib_indexed_shl_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if (!$src1.new) $dst=memb($src2+$src3<<#$offset)", - []>, - 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]>; - -// if (Pv) Rd=memub(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDriub_indexed_shl_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if ($src1) $dst=memub($src2+$src3<<#$offset)", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) Rd=memub(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDriub_indexed_shl_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if ($src1.new) $dst=memub($src2+$src3<<#$offset)", - []>, - Requires<[HasV4T]>; - -// if (!Pv) Rd=memub(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDriub_indexed_shl_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if (!$src1) $dst=memub($src2+$src3<<#$offset)", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) Rd=memub(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDriub_indexed_shl_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if (!$src1.new) $dst=memub($src2+$src3<<#$offset)", - []>, - 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]>; - -// Rd=memh(Rs+Rt<<#u2) -let AddedComplexity = 40, isPredicable = 1 in -def LDrih_indexed_shl_V4 : LDInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$offset), - "$dst=memh($src1+$src2<<#$offset)", - [(set (i32 IntRegs:$dst), - (i32 (sextloadi16 (add (i32 IntRegs:$src1), - (shl (i32 IntRegs:$src2), - u2ImmPred:$offset)))))]>, - Requires<[HasV4T]>; - -let AddedComplexity = 40, isPredicable = 1 in -def LDriuh_indexed_shl_V4 : LDInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$offset), - "$dst=memuh($src1+$src2<<#$offset)", - [(set (i32 IntRegs:$dst), - (i32 (zextloadi16 (add (i32 IntRegs:$src1), - (shl (i32 IntRegs:$src2), - u2ImmPred:$offset)))))]>, - 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]>; - -// if (Pv) Rd=memh(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDrih_indexed_shl_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if ($src1) $dst=memh($src2+$src3<<#$offset)", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) Rd=memh(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDrih_indexed_shl_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if ($src1.new) $dst=memh($src2+$src3<<#$offset)", - []>, - Requires<[HasV4T]>; - -// if (!Pv) Rd=memh(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDrih_indexed_shl_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if (!$src1) $dst=memh($src2+$src3<<#$offset)", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) Rd=memh(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDrih_indexed_shl_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if (!$src1.new) $dst=memh($src2+$src3<<#$offset)", - []>, - 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]>; - -// if (Pv) Rd=memuh(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDriuh_indexed_shl_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if ($src1) $dst=memuh($src2+$src3<<#$offset)", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) Rd=memuh(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDriuh_indexed_shl_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if ($src1.new) $dst=memuh($src2+$src3<<#$offset)", - []>, - Requires<[HasV4T]>; - -// if (!Pv) Rd=memuh(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDriuh_indexed_shl_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if (!$src1) $dst=memuh($src2+$src3<<#$offset)", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) Rd=memuh(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDriuh_indexed_shl_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if (!$src1.new) $dst=memuh($src2+$src3<<#$offset)", - []>, - 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", - []>, - 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]>; - -// Rd=memw(Rs+Rt<<#u2) -let AddedComplexity = 40, isPredicable = 1 in -def LDriw_indexed_shl_V4 : LDInst<(outs IntRegs:$dst), - (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$offset), - "$dst=memw($src1+$src2<<#$offset)", - [(set (i32 IntRegs:$dst), - (i32 (load (add (i32 IntRegs:$src1), - (shl (i32 IntRegs:$src2), - u2ImmPred:$offset)))))]>, - 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]>; - -// if (Pv) Rd=memh(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDriw_indexed_shl_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if ($src1) $dst=memw($src2+$src3<<#$offset)", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) Rd=memh(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDriw_indexed_shl_cdnPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if ($src1.new) $dst=memw($src2+$src3<<#$offset)", - []>, - Requires<[HasV4T]>; - -// if (!Pv) Rd=memh(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDriw_indexed_shl_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if (!$src1) $dst=memw($src2+$src3<<#$offset)", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) Rd=memh(Rs+Rt<<#u2) -let AddedComplexity = 45, isPredicated = 1 in -def LDriw_indexed_shl_cdnNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, - u2Imm:$offset), - "if (!$src1.new) $dst=memw($src2+$src3<<#$offset)", - []>, - Requires<[HasV4T]>; - -// Rd=memw(Rt<<#u2+#U6) - - -// Post-inc Load, Predicated, Dot new - - -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDrid_cdnPt_V4 : LDInst2PI<(outs DoubleRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_3Imm:$src3), - "if ($src1.new) $dst1 = memd($src2++#$src3)", - [], - "$src2 = $dst2">, - Requires<[HasV4T]>; - -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDrid_cdnNotPt_V4 : LDInst2PI<(outs DoubleRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_3Imm:$src3), - "if (!$src1.new) $dst1 = memd($src2++#$src3)", - [], - "$src2 = $dst2">, - Requires<[HasV4T]>; - -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDrib_cdnPt_V4 : LDInst2PI<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_0Imm:$src3), - "if ($src1.new) $dst1 = memb($src2++#$src3)", - [], - "$src2 = $dst2">, - Requires<[HasV4T]>; - -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDrib_cdnNotPt_V4 : LDInst2PI<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_0Imm:$src3), - "if (!$src1.new) $dst1 = memb($src2++#$src3)", - [], - "$src2 = $dst2">, - Requires<[HasV4T]>; - -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDrih_cdnPt_V4 : LDInst2PI<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_1Imm:$src3), - "if ($src1.new) $dst1 = memh($src2++#$src3)", - [], - "$src2 = $dst2">, - Requires<[HasV4T]>; - -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDrih_cdnNotPt_V4 : LDInst2PI<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_1Imm:$src3), - "if (!$src1.new) $dst1 = memh($src2++#$src3)", - [], - "$src2 = $dst2">, - Requires<[HasV4T]>; - -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDriub_cdnPt_V4 : LDInst2PI<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_0Imm:$src3), - "if ($src1.new) $dst1 = memub($src2++#$src3)", - [], - "$src2 = $dst2">, - Requires<[HasV4T]>; - -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDriub_cdnNotPt_V4 : LDInst2PI<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_0Imm:$src3), - "if (!$src1.new) $dst1 = memub($src2++#$src3)", - [], - "$src2 = $dst2">, - Requires<[HasV4T]>; - -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDriuh_cdnPt_V4 : LDInst2PI<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_1Imm:$src3), - "if ($src1.new) $dst1 = memuh($src2++#$src3)", - [], - "$src2 = $dst2">, - Requires<[HasV4T]>; - -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDriuh_cdnNotPt_V4 : LDInst2PI<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_1Imm:$src3), - "if (!$src1.new) $dst1 = memuh($src2++#$src3)", - [], - "$src2 = $dst2">, - Requires<[HasV4T]>; - -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDriw_cdnPt_V4 : LDInst2PI<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_2Imm:$src3), - "if ($src1.new) $dst1 = memw($src2++#$src3)", - [], - "$src2 = $dst2">, - Requires<[HasV4T]>; - -let hasCtrlDep = 1, neverHasSideEffects = 1, isPredicated = 1 in -def POST_LDriw_cdnNotPt_V4 : LDInst2PI<(outs IntRegs:$dst1, IntRegs:$dst2), - (ins PredRegs:$src1, IntRegs:$src2, s4_2Imm:$src3), - "if (!$src1.new) $dst1 = memw($src2++#$src3)", - [], - "$src2 = $dst2">, - 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)", - []>, - 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)", - []>, - 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)", - []>, - 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)", - []>, - 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)", - []>, - 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)", - []>, - 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)", - []>, - 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 -def LDd_GP_V4 : LDInst2<(outs DoubleRegs:$dst), - (ins globaladdress:$global), - "$dst=memd(#$global)", - []>, - Requires<[HasV4T]>; - -// if (Pv) Rtt=memd(##global) -let neverHasSideEffects = 1, isPredicated = 1 in -def LDd_GP_cPt_V4 : LDInst2<(outs DoubleRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global), - "if ($src1) $dst=memd(##$global)", - []>, - Requires<[HasV4T]>; - - -// 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)", - []>, - 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)", - []>, - Requires<[HasV4T]>; - - -// 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 -def LDb_GP_V4 : LDInst2<(outs IntRegs:$dst), - (ins globaladdress:$global), - "$dst=memb(#$global)", - []>, - Requires<[HasV4T]>; - -// if (Pv) Rt=memb(##global) -let neverHasSideEffects = 1, isPredicated = 1 in -def LDb_GP_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global), - "if ($src1) $dst=memb(##$global)", - []>, - 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)", - []>, - 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)", - []>, - 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 -def LDub_GP_V4 : LDInst2<(outs IntRegs:$dst), - (ins globaladdress:$global), - "$dst=memub(#$global)", - []>, - Requires<[HasV4T]>; - -// if (Pv) Rt=memub(##global) -let neverHasSideEffects = 1, isPredicated = 1 in -def LDub_GP_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global), - "if ($src1) $dst=memub(##$global)", - []>, - Requires<[HasV4T]>; - - -// 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)", - []>, - 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)", - []>, - Requires<[HasV4T]>; - - -// 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 -def LDh_GP_V4 : LDInst2<(outs IntRegs:$dst), - (ins globaladdress:$global), - "$dst=memh(#$global)", - []>, - Requires<[HasV4T]>; - -// if (Pv) Rt=memh(##global) -let neverHasSideEffects = 1, isPredicated = 1 in -def LDh_GP_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global), - "if ($src1) $dst=memh(##$global)", - []>, - 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)", - []>, - 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)", - []>, - 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 -def LDuh_GP_V4 : LDInst2<(outs IntRegs:$dst), - (ins globaladdress:$global), - "$dst=memuh(#$global)", - []>, - Requires<[HasV4T]>; - -// if (Pv) Rt=memuh(##global) -let neverHasSideEffects = 1, isPredicated = 1 in -def LDuh_GP_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global), - "if ($src1) $dst=memuh(##$global)", - []>, - 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), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$offset), + !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + ") ")#"$dst = "#mnemonic#"($src2+$src3<<#$offset)", + []>, 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)", - []>, - Requires<[HasV4T]>; +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>; + // Predicate new + defm _cdn#NAME : ld_idxd_shl_pbase<mnemonic, RC, PredNot, 1>; + } +} -// 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)", - []>, - Requires<[HasV4T]>; +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), + (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$offset), + "$dst = "#mnemonic#"($src1+$src2<<#$offset)", + []>, Requires<[HasV4T]>; + + let isPredicated = 1 in { + defm Pt_V4 : ld_idxd_shl_pred<mnemonic, RC, 0 >; + defm NotPt_V4 : ld_idxd_shl_pred<mnemonic, RC, 1>; + } + } +} -// 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 addrMode = BaseRegOffset in { + defm LDrib_indexed_shl: ld_idxd_shl<"memb", "LDrib", IntRegs>, AddrModeRel; + defm LDriub_indexed_shl: ld_idxd_shl<"memub", "LDriub", IntRegs>, AddrModeRel; + defm LDrih_indexed_shl: ld_idxd_shl<"memh", "LDrih", IntRegs>, AddrModeRel; + defm LDriuh_indexed_shl: ld_idxd_shl<"memuh", "LDriuh", IntRegs>, AddrModeRel; + defm LDriw_indexed_shl: ld_idxd_shl<"memw", "LDriw", IntRegs>, AddrModeRel; + defm LDrid_indexed_shl: ld_idxd_shl<"memd", "LDrid", DoubleRegs>, AddrModeRel; +} -let isPredicable = 1, neverHasSideEffects = 1 in -def LDw_GP_V4 : LDInst2<(outs IntRegs:$dst), - (ins globaladdress:$global), - "$dst=memw(#$global)", - []>, +// 'def pats' for load instructions with base + register offset and non-zero +// immediate value. Immediate value is used to left-shift the second +// register operand. +let AddedComplexity = 40 in { +def : Pat <(i32 (sextloadi8 (add IntRegs:$src1, + (shl IntRegs:$src2, u2ImmPred:$offset)))), + (LDrib_indexed_shl_V4 IntRegs:$src1, + IntRegs:$src2, u2ImmPred:$offset)>, Requires<[HasV4T]>; -// if (Pv) Rt=memw(##global) -let neverHasSideEffects = 1, isPredicated = 1 in -def LDw_GP_cPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$global), - "if ($src1) $dst=memw(##$global)", - []>, +def : Pat <(i32 (zextloadi8 (add IntRegs:$src1, + (shl IntRegs:$src2, u2ImmPred:$offset)))), + (LDriub_indexed_shl_V4 IntRegs:$src1, + IntRegs:$src2, u2ImmPred:$offset)>, Requires<[HasV4T]>; - -// 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)", - []>, +def : Pat <(i32 (extloadi8 (add IntRegs:$src1, + (shl IntRegs:$src2, u2ImmPred:$offset)))), + (LDriub_indexed_shl_V4 IntRegs:$src1, + IntRegs:$src2, u2ImmPred:$offset)>, 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)", - []>, +def : Pat <(i32 (sextloadi16 (add IntRegs:$src1, + (shl IntRegs:$src2, u2ImmPred:$offset)))), + (LDrih_indexed_shl_V4 IntRegs:$src1, + IntRegs:$src2, u2ImmPred:$offset)>, Requires<[HasV4T]>; - -// 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)", - []>, +def : Pat <(i32 (zextloadi16 (add IntRegs:$src1, + (shl IntRegs:$src2, u2ImmPred:$offset)))), + (LDriuh_indexed_shl_V4 IntRegs:$src1, + IntRegs:$src2, u2ImmPred:$offset)>, Requires<[HasV4T]>; - - -def : Pat <(atomic_load_64 (HexagonCONST32_GP tglobaladdr:$global)), - (i64 (LDd_GP_V4 tglobaladdr:$global))>, +def : Pat <(i32 (extloadi16 (add IntRegs:$src1, + (shl IntRegs:$src2, u2ImmPred:$offset)))), + (LDriuh_indexed_shl_V4 IntRegs:$src1, + IntRegs:$src2, u2ImmPred:$offset)>, Requires<[HasV4T]>; -def : Pat <(atomic_load_32 (HexagonCONST32_GP tglobaladdr:$global)), - (i32 (LDw_GP_V4 tglobaladdr:$global))>, +def : Pat <(i32 (load (add IntRegs:$src1, + (shl IntRegs:$src2, u2ImmPred:$offset)))), + (LDriw_indexed_shl_V4 IntRegs:$src1, + IntRegs:$src2, u2ImmPred:$offset)>, Requires<[HasV4T]>; -def : Pat <(atomic_load_16 (HexagonCONST32_GP tglobaladdr:$global)), - (i32 (LDuh_GP_V4 tglobaladdr:$global))>, - Requires<[HasV4T]>; - -def : Pat <(atomic_load_8 (HexagonCONST32_GP tglobaladdr:$global)), - (i32 (LDub_GP_V4 tglobaladdr:$global))>, - Requires<[HasV4T]>; - -// Map from load(globaladdress) -> memw(#foo + 0) -let AddedComplexity = 100 in -def : Pat <(i64 (load (HexagonCONST32_GP tglobaladdr:$global))), - (i64 (LDd_GP_V4 tglobaladdr:$global))>, - Requires<[HasV4T]>; - -// Map from Pd = load(globaladdress) -> Rd = memb(globaladdress), Pd = Rd -let AddedComplexity = 100 in -def : Pat <(i1 (load (HexagonCONST32_GP tglobaladdr:$global))), - (i1 (TFR_PdRs (i32 (LDb_GP_V4 tglobaladdr:$global))))>, - Requires<[HasV4T]>; - -// When the Interprocedural Global Variable optimizer realizes that a certain -// global variable takes only two constant values, it shrinks the global to -// a boolean. Catch those loads here in the following 3 patterns. -let AddedComplexity = 100 in -def : Pat <(i32 (extloadi1 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDb_GP_V4 tglobaladdr:$global))>, - Requires<[HasV4T]>; - -let AddedComplexity = 100 in -def : Pat <(i32 (sextloadi1 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDb_GP_V4 tglobaladdr:$global))>, +def : Pat <(i64 (load (add IntRegs:$src1, + (shl IntRegs:$src2, u2ImmPred:$offset)))), + (LDrid_indexed_shl_V4 IntRegs:$src1, + IntRegs:$src2, u2ImmPred:$offset)>, Requires<[HasV4T]>; +} -// Map from load(globaladdress) -> memb(#foo) -let AddedComplexity = 100 in -def : Pat <(i32 (extloadi8 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDb_GP_V4 tglobaladdr:$global))>, - Requires<[HasV4T]>; -// Map from load(globaladdress) -> memb(#foo) -let AddedComplexity = 100 in -def : Pat <(i32 (sextloadi8 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDb_GP_V4 tglobaladdr:$global))>, +// '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]>; -let AddedComplexity = 100 in -def : Pat <(i32 (zextloadi1 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDub_GP_V4 tglobaladdr:$global))>, +def : Pat <(i32 (sextloadi8 (add IntRegs:$src1, IntRegs:$src2))), + (LDrib_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, Requires<[HasV4T]>; -// Map from load(globaladdress) -> memub(#foo) -let AddedComplexity = 100 in -def : Pat <(i32 (zextloadi8 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDub_GP_V4 tglobaladdr:$global))>, +def : Pat <(i32 (zextloadi8 (add IntRegs:$src1, IntRegs:$src2))), + (LDriub_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, Requires<[HasV4T]>; -// Map from load(globaladdress) -> memh(#foo) -let AddedComplexity = 100 in -def : Pat <(i32 (extloadi16 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDh_GP_V4 tglobaladdr:$global))>, +def : Pat <(i32 (extloadi8 (add IntRegs:$src1, IntRegs:$src2))), + (LDriub_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, Requires<[HasV4T]>; -// Map from load(globaladdress) -> memh(#foo) -let AddedComplexity = 100 in -def : Pat <(i32 (sextloadi16 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDh_GP_V4 tglobaladdr:$global))>, +def : Pat <(i32 (sextloadi16 (add IntRegs:$src1, IntRegs:$src2))), + (LDrih_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, Requires<[HasV4T]>; -// Map from load(globaladdress) -> memuh(#foo) -let AddedComplexity = 100 in -def : Pat <(i32 (zextloadi16 (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDuh_GP_V4 tglobaladdr:$global))>, +def : Pat <(i32 (zextloadi16 (add IntRegs:$src1, IntRegs:$src2))), + (LDriuh_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, Requires<[HasV4T]>; -// Map from load(globaladdress) -> memw(#foo) -let AddedComplexity = 100 in -def : Pat <(i32 (load (HexagonCONST32_GP tglobaladdr:$global))), - (i32 (LDw_GP_V4 tglobaladdr:$global))>, +def : Pat <(i32 (extloadi16 (add IntRegs:$src1, IntRegs:$src2))), + (LDriuh_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, 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))>, +def : Pat <(i32 (load (add IntRegs:$src1, IntRegs:$src2))), + (LDriw_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, 0)>, 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]>; - -// 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]>; - -// 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]>; +// 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) -> 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 (zextloadi32 (i32 (add IntRegs:$src1, s11_2ExtPred:$offset)))), + (i64 (COMBINE_Ir_V4 0, (LDriw_indexed IntRegs:$src1, + s11_2ExtPred:$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) -> 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]>; +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) -> 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]>; //===----------------------------------------------------------------------===// @@ -1747,80 +534,192 @@ 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]>; +} -// memd(Rs+Ru<<#u2)=Rtt -let AddedComplexity = 10, isPredicable = 1 in -def STrid_indexed_shl_V4 : STInst<(outs), - (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, DoubleRegs:$src4), - "memd($src1+$src2<<#$src3) = $src4", - [(store (i64 DoubleRegs:$src4), - (add (i32 IntRegs:$src1), - (shl (i32 IntRegs:$src2), u2ImmPred:$src3)))]>, +// 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), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + RC:$src5), + !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + ") ")#mnemonic#"($src2+$src3<<#$src4) = $src5", + []>, Requires<[HasV4T]>; +} + +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>; + // Predicate new + defm _cdn#NAME : ST_Idxd_shl_Pbase<mnemonic, RC, PredNot, 1>; + } +} + +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), + (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, RC:$src4), + mnemonic#"($src1+$src2<<#$src3) = $src4", + []>, + Requires<[HasV4T]>; + + let isPredicated = 1 in { + defm Pt_V4 : ST_Idxd_shl_Pred<mnemonic, RC, 0 >; + defm NotPt_V4 : ST_Idxd_shl_Pred<mnemonic, RC, 1>; + } + } +} + +// multiclass for new-value store instructions with base + register offset +// 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), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + RC:$src5), + !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + ") ")#mnemonic#"($src2+$src3<<#$src4) = $src5.new", + []>, + Requires<[HasV4T]>; +} + +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>; + // Predicate new + defm _cdn#NAME : ST_Idxd_shl_Pbase_nv<mnemonic, RC, PredNot, 1>; + } +} + +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), + (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, RC:$src4), + mnemonic#"($src1+$src2<<#$src3) = $src4.new", + []>, + Requires<[HasV4T]>; + + let isPredicated = 1 in { + defm Pt : ST_Idxd_shl_Pred_nv<mnemonic, RC, 0 >; + defm NotPt : ST_Idxd_shl_Pred_nv<mnemonic, RC, 1>; + } + } +} + +let addrMode = BaseRegOffset, neverHasSideEffects = 1, +validSubTargets = HasV4SubT in { + defm STrib_indexed_shl: ST_Idxd_shl<"memb", "STrib", IntRegs>, + ST_Idxd_shl_nv<"memb", "STrib", IntRegs>, AddrModeRel; + + defm STrih_indexed_shl: ST_Idxd_shl<"memh", "STrih", IntRegs>, + ST_Idxd_shl_nv<"memh", "STrih", IntRegs>, AddrModeRel; + + defm STriw_indexed_shl: ST_Idxd_shl<"memw", "STriw", IntRegs>, + ST_Idxd_shl_nv<"memw", "STriw", IntRegs>, AddrModeRel; + + let isNVStorable = 0 in + defm STrid_indexed_shl: ST_Idxd_shl<"memd", "STrid", DoubleRegs>, AddrModeRel; +} + +let Predicates = [HasV4T], AddedComplexity = 10 in { +def : Pat<(truncstorei8 (i32 IntRegs:$src4), + (add IntRegs:$src1, (shl IntRegs:$src2, + u2ImmPred:$src3))), + (STrib_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, + u2ImmPred:$src3, IntRegs:$src4)>; + +def : Pat<(truncstorei16 (i32 IntRegs:$src4), + (add IntRegs:$src1, (shl IntRegs:$src2, + u2ImmPred:$src3))), + (STrih_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, + u2ImmPred:$src3, IntRegs:$src4)>; + +def : Pat<(store (i32 IntRegs:$src4), + (add IntRegs:$src1, (shl IntRegs:$src2, u2ImmPred:$src3))), + (STriw_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, + u2ImmPred:$src3, IntRegs:$src4)>; + +def : Pat<(store (i64 DoubleRegs:$src4), + (add IntRegs:$src1, (shl IntRegs:$src2, u2ImmPred:$src3))), + (STrid_indexed_shl_V4 IntRegs:$src1, IntRegs:$src2, + u2ImmPred:$src3, 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 @@ -1834,143 +733,81 @@ def STrid_shl_V4 : STInst<(outs), // if ([!]Pv[.new]) memd(#u6)=Rtt // TODO: needs to be implemented. -// if ([!]Pv[.new]) memd(Rs+#u6:3)=Rtt -// if (Pv) memd(Rs+#u6:3)=Rtt -// if (Pv.new) memd(Rs+#u6:3)=Rtt -let AddedComplexity = 10, neverHasSideEffects = 1, - isPredicated = 1 in -def STrid_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, MEMri:$addr, DoubleRegs:$src2), - "if ($src1.new) memd($addr) = $src2", - []>, - Requires<[HasV4T]>; - -// if (!Pv) memd(Rs+#u6:3)=Rtt -// if (!Pv.new) memd(Rs+#u6:3)=Rtt -let AddedComplexity = 10, neverHasSideEffects = 1, - isPredicated = 1 in -def STrid_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, MEMri:$addr, DoubleRegs:$src2), - "if (!$src1.new) memd($addr) = $src2", - []>, - Requires<[HasV4T]>; - -// if (Pv) memd(Rs+#u6:3)=Rtt -// if (Pv.new) memd(Rs+#u6:3)=Rtt -let AddedComplexity = 10, neverHasSideEffects = 1, - isPredicated = 1 in -def STrid_indexed_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_3Imm:$src3, - DoubleRegs:$src4), - "if ($src1.new) memd($src2+#$src3) = $src4", +//===----------------------------------------------------------------------===// +// 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), + (ins PredRegs:$src1, IntRegs:$src2, OffsetOp:$src3, s6Ext:$src4), + !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + ") ")#mnemonic#"($src2+#$src3) = #$src4", []>, Requires<[HasV4T]>; +} -// if (!Pv) memd(Rs+#u6:3)=Rtt -// if (!Pv.new) memd(Rs+#u6:3)=Rtt -let AddedComplexity = 10, neverHasSideEffects = 1, - isPredicated = 1 in -def STrid_indexed_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_3Imm:$src3, - DoubleRegs:$src4), - "if (!$src1.new) memd($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>; + // Predicate new + defm _cdn#NAME : ST_Imm_Pbase<mnemonic, OffsetOp, PredNot, 1>; + } +} -// if ([!]Pv[.new]) memd(Rs+Ru<<#u2)=Rtt -// if (Pv) memd(Rs+Ru<<#u2)=Rtt -let AddedComplexity = 10, neverHasSideEffects = 1, - isPredicated = 1 in -def STrid_indexed_shl_cPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - DoubleRegs:$src5), - "if ($src1) memd($src2+$src3<<#$src4) = $src5", +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), + (ins IntRegs:$src1, OffsetOp:$src2, s8Ext:$src3), + mnemonic#"($src1+#$src2) = #$src3", []>, Requires<[HasV4T]>; -// if (Pv.new) memd(Rs+Ru<<#u2)=Rtt -let AddedComplexity = 10, neverHasSideEffects = 1, - isPredicated = 1 in -def STrid_indexed_shl_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - DoubleRegs:$src5), - "if ($src1.new) memd($src2+$src3<<#$src4) = $src5", - []>, - Requires<[HasV4T]>; -// if (!Pv) memd(Rs+Ru<<#u2)=Rtt -let AddedComplexity = 10, neverHasSideEffects = 1, - isPredicated = 1 in -def STrid_indexed_shl_cNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - DoubleRegs:$src5), - "if (!$src1) memd($src2+$src3<<#$src4) = $src5", - []>, - Requires<[HasV4T]>; -// if (!Pv.new) memd(Rs+Ru<<#u2)=Rtt -let AddedComplexity = 10, neverHasSideEffects = 1, - isPredicated = 1 in -def STrid_indexed_shl_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - DoubleRegs:$src5), - "if (!$src1.new) memd($src2+$src3<<#$src4) = $src5", - []>, - Requires<[HasV4T]>; + let opExtendable = 3, opExtentBits = 6, isPredicated = 1 in { + defm Pt_V4 : ST_Imm_Pred<mnemonic, OffsetOp, 0>; + defm NotPt_V4 : ST_Imm_Pred<mnemonic, OffsetOp, 1 >; + } + } +} -// 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]>; +let addrMode = BaseImmOffset, InputType = "imm", + validSubTargets = HasV4SubT in { + 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; +} -// 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]>; +let Predicates = [HasV4T], AddedComplexity = 10 in { +def: Pat<(truncstorei8 s8ExtPred:$src3, (add IntRegs:$src1, u6_0ImmPred:$src2)), + (STrib_imm_V4 IntRegs:$src1, u6_0ImmPred:$src2, s8ExtPred:$src3)>; +def: Pat<(truncstorei16 s8ExtPred:$src3, (add IntRegs:$src1, + u6_1ImmPred:$src2)), + (STrih_imm_V4 IntRegs:$src1, u6_1ImmPred:$src2, s8ExtPred:$src3)>; -// Store byte. -// memb(Rs+#u6:0)=#S8 -let AddedComplexity = 10, isPredicable = 1 in -def STrib_imm_V4 : STInst<(outs), - (ins IntRegs:$src1, u6_0Imm:$src2, s8Imm:$src3), - "memb($src1+#$src2) = #$src3", - [(truncstorei8 s8ImmPred:$src3, (add (i32 IntRegs:$src1), - u6_0ImmPred:$src2))]>, - Requires<[HasV4T]>; +def: Pat<(store s8ExtPred:$src3, (add IntRegs:$src1, u6_2ImmPred:$src2)), + (STriw_imm_V4 IntRegs:$src1, u6_2ImmPred:$src2, s8ExtPred:$src3)>; +} -// memb(Rs+Ru<<#u2)=Rt -let AddedComplexity = 10, isPredicable = 1 in -def STrib_indexed_shl_V4 : STInst<(outs), - (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, IntRegs:$src4), - "memb($src1+$src2<<#$src3) = $src4", - [(truncstorei8 (i32 IntRegs:$src4), - (add (i32 IntRegs:$src1), - (shl (i32 IntRegs:$src2), - u2ImmPred:$src3)))]>, - Requires<[HasV4T]>; +let AddedComplexity = 6 in +def : Pat <(truncstorei8 s8ExtPred:$src2, (i32 IntRegs:$src1)), + (STrib_imm_V4 IntRegs:$src1, 0, s8ExtPred:$src2)>, + 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 @@ -1980,185 +817,28 @@ def STrib_shl_V4 : STInst<(outs), // memb(gp+#u16:0)=Rt -// Store byte conditionally. -// if ([!]Pv[.new]) memb(#u6)=Rt -// if ([!]Pv[.new]) memb(Rs+#u6:0)=#S6 -// if (Pv) memb(Rs+#u6:0)=#S6 -let neverHasSideEffects = 1, - isPredicated = 1 in -def STrib_imm_cPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, s6Imm:$src4), - "if ($src1) memb($src2+#$src3) = #$src4", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) memb(Rs+#u6:0)=#S6 -let neverHasSideEffects = 1, - isPredicated = 1 in -def STrib_imm_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, s6Imm:$src4), - "if ($src1.new) memb($src2+#$src3) = #$src4", - []>, - Requires<[HasV4T]>; - -// if (!Pv) memb(Rs+#u6:0)=#S6 -let neverHasSideEffects = 1, - isPredicated = 1 in -def STrib_imm_cNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, s6Imm:$src4), - "if (!$src1) memb($src2+#$src3) = #$src4", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) memb(Rs+#u6:0)=#S6 -let neverHasSideEffects = 1, - isPredicated = 1 in -def STrib_imm_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, s6Imm:$src4), - "if (!$src1.new) memb($src2+#$src3) = #$src4", - []>, - Requires<[HasV4T]>; - -// if ([!]Pv[.new]) memb(Rs+#u6:0)=Rt -// if (Pv) memb(Rs+#u6:0)=Rt -// if (Pv.new) memb(Rs+#u6:0)=Rt -let neverHasSideEffects = 1, - isPredicated = 1 in -def STrib_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if ($src1.new) memb($addr) = $src2", - []>, - Requires<[HasV4T]>; - -// if (!Pv) memb(Rs+#u6:0)=Rt -// if (!Pv.new) memb(Rs+#u6:0)=Rt -let neverHasSideEffects = 1, - isPredicated = 1 in -def STrib_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if (!$src1.new) memb($addr) = $src2", - []>, - Requires<[HasV4T]>; - -// if (Pv) memb(Rs+#u6:0)=Rt -// if (!Pv) memb(Rs+#u6:0)=Rt -// if (Pv.new) memb(Rs+#u6:0)=Rt -let neverHasSideEffects = 1, - isPredicated = 1 in -def STrib_indexed_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, IntRegs:$src4), - "if ($src1.new) memb($src2+#$src3) = $src4", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) memb(Rs+#u6:0)=Rt -let neverHasSideEffects = 1, - isPredicated = 1 in -def STrib_indexed_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, IntRegs:$src4), - "if (!$src1.new) memb($src2+#$src3) = $src4", - []>, - Requires<[HasV4T]>; - -// if ([!]Pv[.new]) memb(Rs+Ru<<#u2)=Rt -// if (Pv) memb(Rs+Ru<<#u2)=Rt -let AddedComplexity = 10, - isPredicated = 1 in -def STrib_indexed_shl_cPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if ($src1) memb($src2+$src3<<#$src4) = $src5", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) memb(Rs+Ru<<#u2)=Rt -let AddedComplexity = 10, - isPredicated = 1 in -def STrib_indexed_shl_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if ($src1.new) memb($src2+$src3<<#$src4) = $src5", - []>, - Requires<[HasV4T]>; - -// if (!Pv) memb(Rs+Ru<<#u2)=Rt -let AddedComplexity = 10, - isPredicated = 1 in -def STrib_indexed_shl_cNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if (!$src1) memb($src2+$src3<<#$src4) = $src5", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) memb(Rs+Ru<<#u2)=Rt -let AddedComplexity = 10, - isPredicated = 1 in -def STrib_indexed_shl_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if (!$src1.new) memb($src2+$src3<<#$src4) = $src5", - []>, - Requires<[HasV4T]>; - -// 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 // memh(Rs+#s11:1)=Rt.H -// memh(Rs+#u6:1)=#S8 -let AddedComplexity = 10, isPredicable = 1 in -def STrih_imm_V4 : STInst<(outs), - (ins IntRegs:$src1, u6_1Imm:$src2, s8Imm:$src3), - "memh($src1+#$src2) = #$src3", - [(truncstorei16 s8ImmPred:$src3, (add (i32 IntRegs:$src1), - u6_1ImmPred:$src2))]>, - Requires<[HasV4T]>; +let AddedComplexity = 6 in +def : Pat <(truncstorei16 s8ExtPred:$src2, (i32 IntRegs:$src1)), + (STrih_imm_V4 IntRegs:$src1, 0, s8ExtPred:$src2)>, + Requires<[HasV4T]>; // memh(Rs+Ru<<#u2)=Rt.H // TODO: needs to be implemented. -// memh(Rs+Ru<<#u2)=Rt -let AddedComplexity = 10, isPredicable = 1 in -def STrih_indexed_shl_V4 : STInst<(outs), - (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, IntRegs:$src4), - "memh($src1+$src2<<#$src3) = $src4", - [(truncstorei16 (i32 IntRegs:$src4), - (add (i32 IntRegs:$src1), - (shl (i32 IntRegs:$src2), - u2ImmPred:$src3)))]>, - Requires<[HasV4T]>; - // 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 @@ -2173,152 +853,13 @@ def STrih_shl_V4 : STInst<(outs), // if ([!]Pv[.new]) memh(#u6)=Rt.H // if ([!]Pv[.new]) memh(#u6)=Rt -// if ([!]Pv[.new]) memh(Rs+#u6:1)=#S6 -// if (Pv) memh(Rs+#u6:1)=#S6 -let neverHasSideEffects = 1, - isPredicated = 1 in -def STrih_imm_cPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, s6Imm:$src4), - "if ($src1) memh($src2+#$src3) = #$src4", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) memh(Rs+#u6:1)=#S6 -let neverHasSideEffects = 1, - isPredicated = 1 in -def STrih_imm_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, s6Imm:$src4), - "if ($src1.new) memh($src2+#$src3) = #$src4", - []>, - Requires<[HasV4T]>; - -// if (!Pv) memh(Rs+#u6:1)=#S6 -let neverHasSideEffects = 1, - isPredicated = 1 in -def STrih_imm_cNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, s6Imm:$src4), - "if (!$src1) memh($src2+#$src3) = #$src4", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) memh(Rs+#u6:1)=#S6 -let neverHasSideEffects = 1, - isPredicated = 1 in -def STrih_imm_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, s6Imm:$src4), - "if (!$src1.new) memh($src2+#$src3) = #$src4", - []>, - Requires<[HasV4T]>; // if ([!]Pv[.new]) memh(Rs+#u6:1)=Rt.H // TODO: needs to be implemented. -// if ([!]Pv[.new]) memh(Rs+#u6:1)=Rt -// if (Pv) memh(Rs+#u6:1)=Rt -// if (Pv.new) memh(Rs+#u6:1)=Rt -let neverHasSideEffects = 1, - isPredicated = 1 in -def STrih_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if ($src1.new) memh($addr) = $src2", - []>, - Requires<[HasV4T]>; - -// if (!Pv) memh(Rs+#u6:1)=Rt -// if (!Pv.new) memh(Rs+#u6:1)=Rt -let neverHasSideEffects = 1, - isPredicated = 1 in -def STrih_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if (!$src1.new) memh($addr) = $src2", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) memh(Rs+#u6:1)=Rt -let neverHasSideEffects = 1, - isPredicated = 1 in -def STrih_indexed_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, IntRegs:$src4), - "if ($src1.new) memh($src2+#$src3) = $src4", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) memh(Rs+#u6:1)=Rt -let neverHasSideEffects = 1, - isPredicated = 1 in -def STrih_indexed_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, IntRegs:$src4), - "if (!$src1.new) memh($src2+#$src3) = $src4", - []>, - Requires<[HasV4T]>; - -// if ([!]Pv[.new]) memh(Rs+Ru<<#u2)=Rt.H -// if ([!]Pv[.new]) memh(Rs+Ru<<#u2)=Rt -// if (Pv) memh(Rs+Ru<<#u2)=Rt -let AddedComplexity = 10, - isPredicated = 1 in -def STrih_indexed_shl_cPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if ($src1) memh($src2+$src3<<#$src4) = $src5", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) memh(Rs+Ru<<#u2)=Rt -let AddedComplexity = 10, - isPredicated = 1 in -def STrih_indexed_shl_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if ($src1.new) memh($src2+$src3<<#$src4) = $src5", - []>, - Requires<[HasV4T]>; - -// if (!Pv) memh(Rs+Ru<<#u2)=Rt -let AddedComplexity = 10, - isPredicated = 1 in -def STrih_indexed_shl_cNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if (!$src1) memh($src2+$src3<<#$src4) = $src5", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) memh(Rs+Ru<<#u2)=Rt -let AddedComplexity = 10, - isPredicated = 1 in -def STrih_indexed_shl_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if (!$src1.new) memh($src2+$src3<<#$src4) = $src5", - []>, - Requires<[HasV4T]>; - // 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. @@ -2331,34 +872,20 @@ def STriw_pred_V4 : STInst2<(outs), []>, Requires<[HasV4T]>; - -// memw(Rs+#u6:2)=#S8 -let AddedComplexity = 10, isPredicable = 1 in -def STriw_imm_V4 : STInst<(outs), - (ins IntRegs:$src1, u6_2Imm:$src2, s8Imm:$src3), - "memw($src1+#$src2) = #$src3", - [(store s8ImmPred:$src3, (add (i32 IntRegs:$src1), - u6_2ImmPred:$src2))]>, - Requires<[HasV4T]>; - -// memw(Rs+Ru<<#u2)=Rt -let AddedComplexity = 10, isPredicable = 1 in -def STriw_indexed_shl_V4 : STInst<(outs), - (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, IntRegs:$src4), - "memw($src1+$src2<<#$src3) = $src4", - [(store (i32 IntRegs:$src4), (add (i32 IntRegs:$src1), - (shl (i32 IntRegs:$src2), - u2ImmPred:$src3)))]>, - Requires<[HasV4T]>; +let AddedComplexity = 6 in +def : Pat <(store s8ExtPred:$src2, (i32 IntRegs:$src1)), + (STriw_imm_V4 IntRegs:$src1, 0, s8ExtPred:$src2)>, + 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 @@ -2366,592 +893,6 @@ def STriw_shl_V4 : STInst<(outs), // memw(Rx++I:circ(Mu))=Rt // memw(Rx++Mu)=Rt // memw(Rx++Mu:brev)=Rt -// memw(gp+#u16:2)=Rt - - -// Store word conditionally. - -// if ([!]Pv[.new]) memw(Rs+#u6:2)=#S6 -// if (Pv) memw(Rs+#u6:2)=#S6 -let neverHasSideEffects = 1, - isPredicated = 1 in -def STriw_imm_cPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, s6Imm:$src4), - "if ($src1) memw($src2+#$src3) = #$src4", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) memw(Rs+#u6:2)=#S6 -let neverHasSideEffects = 1, - isPredicated = 1 in -def STriw_imm_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, s6Imm:$src4), - "if ($src1.new) memw($src2+#$src3) = #$src4", - []>, - Requires<[HasV4T]>; - -// if (!Pv) memw(Rs+#u6:2)=#S6 -let neverHasSideEffects = 1, - isPredicated = 1 in -def STriw_imm_cNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, s6Imm:$src4), - "if (!$src1) memw($src2+#$src3) = #$src4", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) memw(Rs+#u6:2)=#S6 -let neverHasSideEffects = 1, - isPredicated = 1 in -def STriw_imm_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, s6Imm:$src4), - "if (!$src1.new) memw($src2+#$src3) = #$src4", - []>, - Requires<[HasV4T]>; - -// if ([!]Pv[.new]) memw(Rs+#u6:2)=Rt -// if (Pv) memw(Rs+#u6:2)=Rt -// if (Pv.new) memw(Rs+#u6:2)=Rt -let neverHasSideEffects = 1, - isPredicated = 1 in -def STriw_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if ($src1.new) memw($addr) = $src2", - []>, - Requires<[HasV4T]>; - -// if (!Pv) memw(Rs+#u6:2)=Rt -// if (!Pv.new) memw(Rs+#u6:2)=Rt -let neverHasSideEffects = 1, - isPredicated = 1 in -def STriw_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), - "if (!$src1.new) memw($addr) = $src2", - []>, - Requires<[HasV4T]>; - -// if (Pv) memw(Rs+#u6:2)=Rt -// if (!Pv) memw(Rs+#u6:2)=Rt -// if (Pv.new) memw(Rs+#u6:2)=Rt -let neverHasSideEffects = 1, - isPredicated = 1 in -def STriw_indexed_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, IntRegs:$src4), - "if ($src1.new) memw($src2+#$src3) = $src4", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) memw(Rs+#u6:2)=Rt -let neverHasSideEffects = 1, - isPredicated = 1 in -def STriw_indexed_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, IntRegs:$src4), - "if (!$src1.new) memw($src2+#$src3) = $src4", - []>, - Requires<[HasV4T]>; - -// if ([!]Pv[.new]) memw(Rs+Ru<<#u2)=Rt -// if (Pv) memw(Rs+Ru<<#u2)=Rt -let AddedComplexity = 10, - isPredicated = 1 in -def STriw_indexed_shl_cPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if ($src1) memw($src2+$src3<<#$src4) = $src5", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) memw(Rs+Ru<<#u2)=Rt -let AddedComplexity = 10, - isPredicated = 1 in -def STriw_indexed_shl_cdnPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if ($src1.new) memw($src2+$src3<<#$src4) = $src5", - []>, - Requires<[HasV4T]>; - -// if (!Pv) memw(Rs+Ru<<#u2)=Rt -let AddedComplexity = 10, - isPredicated = 1 in -def STriw_indexed_shl_cNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if (!$src1) memw($src2+$src3<<#$src4) = $src5", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) memw(Rs+Ru<<#u2)=Rt -let AddedComplexity = 10, - isPredicated = 1 in -def STriw_indexed_shl_cdnNotPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if (!$src1.new) memw($src2+$src3<<#$src4) = $src5", - []>, - Requires<[HasV4T]>; - -// 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 -def STd_GP_V4 : STInst2<(outs), - (ins globaladdress:$global, DoubleRegs:$src), - "memd(#$global) = $src", - []>, - Requires<[HasV4T]>; - -// if (Pv) memd(##global) = Rtt -let neverHasSideEffects = 1, isPredicated = 1 in -def STd_GP_cPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$global, DoubleRegs:$src2), - "if ($src1) memd(##$global) = $src2", - []>, - 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", - []>, - 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", - []>, - 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 -def STb_GP_V4 : STInst2<(outs), - (ins globaladdress:$global, IntRegs:$src), - "memb(#$global) = $src", - []>, - Requires<[HasV4T]>; - -// if (Pv) memb(##global) = Rt -let neverHasSideEffects = 1, isPredicated = 1 in -def STb_GP_cPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), - "if ($src1) memb(##$global) = $src2", - []>, - 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", - []>, - 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", - []>, - 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 -def STh_GP_V4 : STInst2<(outs), - (ins globaladdress:$global, IntRegs:$src), - "memh(#$global) = $src", - []>, - Requires<[HasV4T]>; - -// if (Pv) memh(##global) = Rt -let neverHasSideEffects = 1, isPredicated = 1 in -def STh_GP_cPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), - "if ($src1) memh(##$global) = $src2", - []>, - 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", - []>, - 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", - []>, - 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 -def STw_GP_V4 : STInst2<(outs), - (ins globaladdress:$global, IntRegs:$src), - "memw(#$global) = $src", - []>, - Requires<[HasV4T]>; - -// if (Pv) memw(##global) = Rt -let neverHasSideEffects = 1, isPredicated = 1 in -def STw_GP_cPt_V4 : STInst2<(outs), - (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), - "if ($src1) memw(##$global) = $src2", - []>, - 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", - []>, - 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", - []>, - 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), - (i64 DoubleRegs:$src1)), - (STd_GP_V4 tglobaladdr:$global, (i64 DoubleRegs:$src1))>, - Requires<[HasV4T]>; - -// Map from store(globaladdress) -> memd(#foo) -let AddedComplexity = 100 in -def : Pat <(store (i64 DoubleRegs:$src1), - (HexagonCONST32_GP tglobaladdr:$global)), - (STd_GP_V4 tglobaladdr:$global, (i64 DoubleRegs:$src1))>, - Requires<[HasV4T]>; - -// 8 bit atomic store -def : Pat < (atomic_store_8 (HexagonCONST32_GP tglobaladdr:$global), - (i32 IntRegs:$src1)), - (STb_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>, - Requires<[HasV4T]>; - -// Map from store(globaladdress) -> memb(#foo) -let AddedComplexity = 100 in -def : Pat<(truncstorei8 (i32 IntRegs:$src1), - (HexagonCONST32_GP tglobaladdr:$global)), - (STb_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>, - Requires<[HasV4T]>; - -// Map from "i1 = constant<-1>; memw(CONST32(#foo)) = i1" -// to "r0 = 1; memw(#foo) = r0" -let AddedComplexity = 100 in -def : Pat<(store (i1 -1), (HexagonCONST32_GP tglobaladdr:$global)), - (STb_GP_V4 tglobaladdr:$global, (TFRI 1))>, - Requires<[HasV4T]>; - -def : Pat<(atomic_store_16 (HexagonCONST32_GP tglobaladdr:$global), - (i32 IntRegs:$src1)), - (STh_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>, - Requires<[HasV4T]>; - -// Map from store(globaladdress) -> memh(#foo) -let AddedComplexity = 100 in -def : Pat<(truncstorei16 (i32 IntRegs:$src1), - (HexagonCONST32_GP tglobaladdr:$global)), - (STh_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>, - Requires<[HasV4T]>; - -// 32 bit atomic store -def : Pat<(atomic_store_32 (HexagonCONST32_GP tglobaladdr:$global), - (i32 IntRegs:$src1)), - (STw_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>, - Requires<[HasV4T]>; - -// Map from store(globaladdress) -> memw(#foo) -let AddedComplexity = 100 in -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 - @@ -2962,853 +903,202 @@ def : Pat<(store (i32 IntRegs:$src1), // NV/ST + //===----------------------------------------------------------------------===// -// Store new-value byte. - -// 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", - []>, - Requires<[HasV4T]>; - -let mayStore = 1, isPredicable = 1 in -def STrib_indexed_nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, s11_0Imm:$src2, IntRegs:$src3), - "memb($src1+#$src2) = $src3.new", - []>, - Requires<[HasV4T]>; - -// memb(Rs+Ru<<#u2)=Nt.new -let mayStore = 1, AddedComplexity = 10, isPredicable = 1 in -def STrib_indexed_shl_nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, IntRegs:$src4), - "memb($src1+$src2<<#$src3) = $src4.new", - []>, - Requires<[HasV4T]>; - -// memb(Ru<<#u2+#U6)=Nt.new -let mayStore = 1, AddedComplexity = 10 in -def STrib_shl_nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, u2Imm:$src2, u6Imm:$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", - [], - "$src2 = $dst">, - Requires<[HasV4T]>; - -// 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), - (ins globaladdress:$global, IntRegs:$src), - "memb(#$global) = $src.new", +// multiclass for new-value store instructions with base + immediate offset. +// +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), + (ins PredRegs:$src1, IntRegs:$src2, predImmOp:$src3, RC: $src4), + !if(isNot, "if (!$src1", "if ($src1")#!if(isPredNew, ".new) ", + ") ")#mnemonic#"($src2+#$src3) = $src4.new", []>, 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]>; +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>; + // Predicate new + defm _cdn#NAME : ST_Idxd_Pbase_nv<mnemonic, RC, predImmOp, PredNot, 1>; + } +} -// 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]>; +let mayStore = 1, isNVStore = 1, neverHasSideEffects = 1, isExtendable = 1 in +multiclass ST_Idxd_nv<string mnemonic, string CextOp, RegisterClass RC, + Operand ImmOp, Operand predImmOp, bits<5> ImmBits, + bits<5> PredImmBits> { -// 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", + let CextOpcode = CextOp, BaseOpcode = CextOp#_indexed in { + let opExtendable = 1, isExtentSigned = 1, opExtentBits = ImmBits, + isPredicable = 1 in + def NAME#_nv_V4 : NVInst_V4<(outs), + (ins IntRegs:$src1, ImmOp:$src2, RC:$src3), + mnemonic#"($src1+#$src2) = $src3.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]>; + let opExtendable = 2, isExtentSigned = 0, opExtentBits = PredImmBits, + isPredicated = 1 in { + defm Pt : ST_Idxd_Pred_nv<mnemonic, RC, predImmOp, 0>; + defm NotPt : ST_Idxd_Pred_nv<mnemonic, RC, predImmOp, 1>; + } + } +} -// if (Pv) memb(Rs+#u6:0)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STrib_indexed_cPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, IntRegs:$src4), - "if ($src1) memb($src2+#$src3) = $src4.new", - []>, - Requires<[HasV4T]>; +let addrMode = BaseImmOffset, validSubTargets = HasV4SubT in { + defm STrib_indexed: ST_Idxd_nv<"memb", "STrib", IntRegs, s11_0Ext, + u6_0Ext, 11, 6>, AddrModeRel; + defm STrih_indexed: ST_Idxd_nv<"memh", "STrih", IntRegs, s11_1Ext, + u6_1Ext, 12, 7>, AddrModeRel; + defm STriw_indexed: ST_Idxd_nv<"memw", "STriw", IntRegs, s11_2Ext, + u6_2Ext, 13, 8>, AddrModeRel; +} -// if (Pv.new) memb(Rs+#u6:0)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STrib_indexed_cdnPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, IntRegs:$src4), - "if ($src1.new) memb($src2+#$src3) = $src4.new", +// 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]>; +} -// if (!Pv) memb(Rs+#u6:0)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STrib_indexed_cNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, IntRegs:$src4), - "if (!$src1) memb($src2+#$src3) = $src4.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>; -// if (!Pv.new) memb(Rs+#u6:0)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STrib_indexed_cdnNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, IntRegs:$src4), - "if (!$src1.new) memb($src2+#$src3) = $src4.new", - []>, - Requires<[HasV4T]>; + // Predicate new + defm _cdn#NAME : ST_MEMri_Pbase_nv<mnemonic, RC, PredNot, 1>; + } +} +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> { -// if ([!]Pv[.new]) memb(Rs+Ru<<#u2)=Nt.new -// if (Pv) memb(Rs+Ru<<#u2)=Nt.new -let mayStore = 1, AddedComplexity = 10, - isPredicated = 1 in -def STrib_indexed_shl_cPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if ($src1) memb($src2+$src3<<#$src4) = $src5.new", + 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]>; -// if (Pv.new) memb(Rs+Ru<<#u2)=Nt.new -let mayStore = 1, AddedComplexity = 10, - isPredicated = 1 in -def STrib_indexed_shl_cdnPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if ($src1.new) memb($src2+$src3<<#$src4) = $src5.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>; + } + } +} -// if (!Pv) memb(Rs+Ru<<#u2)=Nt.new -let mayStore = 1, AddedComplexity = 10, - isPredicated = 1 in -def STrib_indexed_shl_cNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if (!$src1) memb($src2+$src3<<#$src4) = $src5.new", - []>, - Requires<[HasV4T]>; +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; +} -// if (!Pv.new) memb(Rs+Ru<<#u2)=Nt.new -let mayStore = 1, AddedComplexity = 10, - isPredicated = 1 in -def STrib_indexed_shl_cdnNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if (!$src1.new) memb($src2+$src3<<#$src4) = $src5.new", +// memb(Ru<<#u2+#U6)=Nt.new +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, u0AlwaysExt:$src3, IntRegs:$src4), + "memb($src1<<#$src2+#$src3) = $src4.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]>; +//===----------------------------------------------------------------------===// +// Post increment store +// mem[bhwd](Rx++#s4:[0123])=Nt.new +//===----------------------------------------------------------------------===// -// 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">, +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>; + } +} -// 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]>; - -let mayStore = 1, isPredicable = 1 in -def STrih_indexed_nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, s11_1Imm:$src2, IntRegs:$src3), - "memh($src1+#$src2) = $src3.new", - []>, - Requires<[HasV4T]>; +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 >; + } + } +} -// memh(Rs+Ru<<#u2)=Nt.new -let mayStore = 1, AddedComplexity = 10, isPredicable = 1 in -def STrih_indexed_shl_nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, IntRegs:$src4), - "memh($src1+$src2<<#$src3) = $src4.new", - []>, - Requires<[HasV4T]>; +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 // 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), - (ins globaladdress:$global, IntRegs:$src), - "memh(#$global) = $src.new", - []>, - 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(Rs+#u6:1)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STrih_indexed_cPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, IntRegs:$src4), - "if ($src1) memh($src2+#$src3) = $src4.new", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) memh(Rs+#u6:1)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STrih_indexed_cdnPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, IntRegs:$src4), - "if ($src1.new) memh($src2+#$src3) = $src4.new", - []>, - Requires<[HasV4T]>; - -// if (!Pv) memh(Rs+#u6:1)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STrih_indexed_cNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, IntRegs:$src4), - "if (!$src1) memh($src2+#$src3) = $src4.new", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) memh(Rs+#u6:1)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STrih_indexed_cdnNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, IntRegs:$src4), - "if (!$src1.new) memh($src2+#$src3) = $src4.new", - []>, - Requires<[HasV4T]>; - -// if ([!]Pv[.new]) memh(Rs+Ru<<#u2)=Nt.new -// if (Pv) memh(Rs+Ru<<#u2)=Nt.new -let mayStore = 1, AddedComplexity = 10, - isPredicated = 1 in -def STrih_indexed_shl_cPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if ($src1) memh($src2+$src3<<#$src4) = $src5.new", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) memh(Rs+Ru<<#u2)=Nt.new -let mayStore = 1, AddedComplexity = 10, - isPredicated = 1 in -def STrih_indexed_shl_cdnPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if ($src1.new) memh($src2+$src3<<#$src4) = $src5.new", - []>, - Requires<[HasV4T]>; - -// if (!Pv) memh(Rs+Ru<<#u2)=Nt.new -let mayStore = 1, AddedComplexity = 10, - isPredicated = 1 in -def STrih_indexed_shl_cNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if (!$src1) memh($src2+$src3<<#$src4) = $src5.new", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) memh(Rs+Ru<<#u2)=Nt.new -let mayStore = 1, AddedComplexity = 10, - isPredicated = 1 in -def STrih_indexed_shl_cdnNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if (!$src1.new) memh($src2+$src3<<#$src4) = $src5.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]>; - -let mayStore = 1, isPredicable = 1 in -def STriw_indexed_nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, s11_2Imm:$src2, IntRegs:$src3), - "memw($src1+#$src2) = $src3.new", - []>, - Requires<[HasV4T]>; - -// memw(Rs+Ru<<#u2)=Nt.new -let mayStore = 1, AddedComplexity = 10, isPredicable = 1 in -def STriw_indexed_shl_nv_V4 : NVInst_V4<(outs), - (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, IntRegs:$src4), - "memw($src1+$src2<<#$src3) = $src4.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 -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) memw(Rs+#u6:2)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STriw_indexed_cPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, IntRegs:$src4), - "if ($src1) memw($src2+#$src3) = $src4.new", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) memw(Rs+#u6:2)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STriw_indexed_cdnPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, IntRegs:$src4), - "if ($src1.new) memw($src2+#$src3) = $src4.new", - []>, - Requires<[HasV4T]>; - -// if (!Pv) memw(Rs+#u6:2)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STriw_indexed_cNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, IntRegs:$src4), - "if (!$src1) memw($src2+#$src3) = $src4.new", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) memw(Rs+#u6:2)=Nt.new -let mayStore = 1, neverHasSideEffects = 1, - isPredicated = 1 in -def STriw_indexed_cdnNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, IntRegs:$src4), - "if (!$src1.new) memw($src2+#$src3) = $src4.new", - []>, - Requires<[HasV4T]>; - - -// if ([!]Pv[.new]) memw(Rs+Ru<<#u2)=Nt.new -// if (Pv) memw(Rs+Ru<<#u2)=Nt.new -let mayStore = 1, AddedComplexity = 10, - isPredicated = 1 in -def STriw_indexed_shl_cPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if ($src1) memw($src2+$src3<<#$src4) = $src5.new", - []>, - Requires<[HasV4T]>; - -// if (Pv.new) memw(Rs+Ru<<#u2)=Nt.new -let mayStore = 1, AddedComplexity = 10, - isPredicated = 1 in -def STriw_indexed_shl_cdnPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if ($src1.new) memw($src2+$src3<<#$src4) = $src5.new", - []>, - Requires<[HasV4T]>; - -// if (!Pv) memw(Rs+Ru<<#u2)=Nt.new -let mayStore = 1, AddedComplexity = 10, - isPredicated = 1 in -def STriw_indexed_shl_cNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if (!$src1) memw($src2+$src3<<#$src4) = $src5.new", - []>, - Requires<[HasV4T]>; - -// if (!Pv.new) memw(Rs+Ru<<#u2)=Nt.new -let mayStore = 1, AddedComplexity = 10, - isPredicated = 1 in -def STriw_indexed_shl_cdnNotPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, - IntRegs:$src5), - "if (!$src1.new) memw($src2+$src3<<#$src4) = $src5.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 -def STb_GP_cPt_nv_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, globaladdress:$global, IntRegs:$src2), - "if ($src1) memb(##$global) = $src2.new", - []>, - 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", - []>, - 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", - []>, - 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", - []>, - 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", - []>, - 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", - []>, - 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", - []>, - 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", - []>, - 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", - []>, - 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", - []>, - 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", - []>, - 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 - @@ -3998,31 +1288,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]>; @@ -4036,6 +1332,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)", @@ -4044,6 +1341,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)", @@ -4054,6 +1352,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)", @@ -4066,17 +1365,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)", @@ -4087,6 +1389,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)", @@ -4094,9 +1397,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)", @@ -4108,6 +1412,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)", @@ -4118,6 +1423,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)", @@ -4128,6 +1434,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)", @@ -4139,6 +1446,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)", @@ -4149,6 +1457,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)", @@ -4156,9 +1465,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)", @@ -4170,6 +1480,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)", @@ -4180,6 +1491,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)", @@ -4190,6 +1502,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)", @@ -4200,24 +1513,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 @@ -4264,25 +1581,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))", @@ -4292,15 +1625,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))", @@ -4308,7 +1644,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 @@ -4351,92 +1687,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, @@ -4484,7 +1835,7 @@ def LSRd_rr_xor_V4 : MInst_acc<(outs DoubleRegs:$dst), (i32 IntRegs:$src3))))], "$src1 = $dst">, Requires<[HasV4T]>; - +} //===----------------------------------------------------------------------===// // XTYPE/SHIFT - @@ -4494,488 +1845,367 @@ def LSRd_rr_xor_V4 : MInst_acc<(outs DoubleRegs:$dst), // MEMOP: Word, Half, Byte //===----------------------------------------------------------------------===// +def MEMOPIMM : SDNodeXForm<imm, [{ + // Call the transformation function XformM5ToU5Imm to get the negative + // immediate's positive counterpart. + int32_t imm = N->getSExtValue(); + return XformM5ToU5Imm(imm); +}]>; + +def MEMOPIMM_HALF : SDNodeXForm<imm, [{ + // -1 .. -31 represented as 65535..65515 + // assigning to a short restores our desired signed value. + // Call the transformation function XformM5ToU5Imm to get the negative + // immediate's positive counterpart. + int16_t imm = N->getSExtValue(); + return XformM5ToU5Imm(imm); +}]>; + +def MEMOPIMM_BYTE : SDNodeXForm<imm, [{ + // -1 .. -31 represented as 255..235 + // assigning to a char restores our desired signed value. + // Call the transformation function XformM5ToU5Imm to get the negative + // immediate's positive counterpart. + int8_t imm = N->getSExtValue(); + return XformM5ToU5Imm(imm); +}]>; + +def SETMEMIMM : SDNodeXForm<imm, [{ + // Return the bit position we will set [0-31]. + // As an SDNode. + int32_t imm = N->getSExtValue(); + return XformMskToBitPosU5Imm(imm); +}]>; + +def CLRMEMIMM : SDNodeXForm<imm, [{ + // Return the bit position we will clear [0-31]. + // As an SDNode. + // we bit negate the value first + int32_t imm = ~(N->getSExtValue()); + return XformMskToBitPosU5Imm(imm); +}]>; + +def SETMEMIMM_SHORT : SDNodeXForm<imm, [{ + // Return the bit position we will set [0-15]. + // As an SDNode. + int16_t imm = N->getSExtValue(); + return XformMskToBitPosU4Imm(imm); +}]>; + +def CLRMEMIMM_SHORT : SDNodeXForm<imm, [{ + // Return the bit position we will clear [0-15]. + // As an SDNode. + // we bit negate the value first + int16_t imm = ~(N->getSExtValue()); + return XformMskToBitPosU4Imm(imm); +}]>; + +def SETMEMIMM_BYTE : SDNodeXForm<imm, [{ + // Return the bit position we will set [0-7]. + // As an SDNode. + int8_t imm = N->getSExtValue(); + return XformMskToBitPosU3Imm(imm); +}]>; + +def CLRMEMIMM_BYTE : SDNodeXForm<imm, [{ + // Return the bit position we will clear [0-7]. + // As an SDNode. + // we bit negate the value first + int8_t imm = ~(N->getSExtValue()); + return XformMskToBitPosU3Imm(imm); +}]>; + //===----------------------------------------------------------------------===// -// MEMOP: Word -// -// Implemented: -// MEMw_ADDi_indexed_V4 : memw(Rs+#u6:2)+=#U5 -// MEMw_SUBi_indexed_V4 : memw(Rs+#u6:2)-=#U5 -// MEMw_ADDr_indexed_V4 : memw(Rs+#u6:2)+=Rt -// MEMw_SUBr_indexed_V4 : memw(Rs+#u6:2)-=Rt -// MEMw_CLRr_indexed_V4 : memw(Rs+#u6:2)&=Rt -// MEMw_SETr_indexed_V4 : memw(Rs+#u6:2)|=Rt -// MEMw_ADDi_V4 : memw(Rs+#u6:2)+=#U5 -// MEMw_SUBi_V4 : memw(Rs+#u6:2)-=#U5 -// MEMw_ADDr_V4 : memw(Rs+#u6:2)+=Rt -// MEMw_SUBr_V4 : memw(Rs+#u6:2)-=Rt -// MEMw_CLRr_V4 : memw(Rs+#u6:2)&=Rt -// MEMw_SETr_V4 : memw(Rs+#u6:2)|=Rt -// -// Not implemented: -// MEMw_CLRi_indexed_V4 : memw(Rs+#u6:2)=clrbit(#U5) -// MEMw_SETi_indexed_V4 : memw(Rs+#u6:2)=setbit(#U5) -// MEMw_CLRi_V4 : memw(Rs+#u6:2)=clrbit(#U5) -// MEMw_SETi_V4 : memw(Rs+#u6:2)=setbit(#U5) +// Template class for MemOp instructions with the register value. +//===----------------------------------------------------------------------===// +class MemOp_rr_base <string opc, bits<2> opcBits, Operand ImmOp, + string memOp, bits<2> memOpBits> : + MEMInst_V4<(outs), + (ins IntRegs:$base, ImmOp:$offset, IntRegs:$delta), + opc#"($base+#$offset)"#memOp#"$delta", + []>, + Requires<[HasV4T, UseMEMOP]> { + + bits<5> base; + bits<5> delta; + bits<32> offset; + bits<6> offsetBits; // memb - u6:0 , memh - u6:1, memw - u6:2 + + let offsetBits = !if (!eq(opcBits, 0b00), offset{5-0}, + !if (!eq(opcBits, 0b01), offset{6-1}, + !if (!eq(opcBits, 0b10), offset{7-2},0))); + + let IClass = 0b0011; + let Inst{27-24} = 0b1110; + let Inst{22-21} = opcBits; + let Inst{20-16} = base; + let Inst{13} = 0b0; + let Inst{12-7} = offsetBits; + let Inst{6-5} = memOpBits; + let Inst{4-0} = delta; +} + +//===----------------------------------------------------------------------===// +// Template class for MemOp instructions with the immediate value. //===----------------------------------------------------------------------===// +class MemOp_ri_base <string opc, bits<2> opcBits, Operand ImmOp, + string memOp, bits<2> memOpBits> : + MEMInst_V4 <(outs), + (ins IntRegs:$base, ImmOp:$offset, u5Imm:$delta), + opc#"($base+#$offset)"#memOp#"#$delta" + #!if(memOpBits{1},")", ""), // clrbit, setbit - include ')' + []>, + Requires<[HasV4T, UseMEMOP]> { + + bits<5> base; + bits<5> delta; + bits<32> offset; + bits<6> offsetBits; // memb - u6:0 , memh - u6:1, memw - u6:2 + + let offsetBits = !if (!eq(opcBits, 0b00), offset{5-0}, + !if (!eq(opcBits, 0b01), offset{6-1}, + !if (!eq(opcBits, 0b10), offset{7-2},0))); + + let IClass = 0b0011; + let Inst{27-24} = 0b1111; + let Inst{22-21} = opcBits; + let Inst{20-16} = base; + let Inst{13} = 0b0; + let Inst{12-7} = offsetBits; + let Inst{6-5} = memOpBits; + let Inst{4-0} = delta; +} +// multiclass to define MemOp instructions with register operand. +multiclass MemOp_rr<string opc, bits<2> opcBits, Operand ImmOp> { + def _ADD#NAME#_V4 : MemOp_rr_base <opc, opcBits, ImmOp, " += ", 0b00>; // add + def _SUB#NAME#_V4 : MemOp_rr_base <opc, opcBits, ImmOp, " -= ", 0b01>; // sub + def _AND#NAME#_V4 : MemOp_rr_base <opc, opcBits, ImmOp, " &= ", 0b10>; // and + def _OR#NAME#_V4 : MemOp_rr_base <opc, opcBits, ImmOp, " |= ", 0b11>; // or +} -// MEMw_ADDSUBi_indexed_V4: -// pseudo operation for MEMw_ADDi_indexed_V4 and -// MEMw_SUBi_indexed_V4 a later pass will change it -// to the corresponding pattern. -let AddedComplexity = 30 in -def MEMw_ADDSUBi_indexed_MEM_V4 : MEMInst_V4<(outs), - (ins IntRegs:$base, u6_2Imm:$offset, m6Imm:$addend), - "Error; should not emit", - [(store (add (load (add (i32 IntRegs:$base), u6_2ImmPred:$offset)), - m6ImmPred:$addend), - (add (i32 IntRegs:$base), u6_2ImmPred:$offset))]>, - Requires<[HasV4T, UseMEMOP]>; - -// memw(Rs+#u6:2) += #U5 -let AddedComplexity = 30 in -def MEMw_ADDi_indexed_MEM_V4 : MEMInst_V4<(outs), - (ins IntRegs:$base, u6_2Imm:$offset, u5Imm:$addend), - "memw($base+#$offset) += #$addend", - []>, - Requires<[HasV4T, UseMEMOP]>; +// multiclass to define MemOp instructions with immediate Operand. +multiclass MemOp_ri<string opc, bits<2> opcBits, Operand ImmOp> { + def _ADD#NAME#_V4 : MemOp_ri_base <opc, opcBits, ImmOp, " += ", 0b00 >; + def _SUB#NAME#_V4 : MemOp_ri_base <opc, opcBits, ImmOp, " -= ", 0b01 >; + def _CLRBIT#NAME#_V4 : MemOp_ri_base<opc, opcBits, ImmOp, " =clrbit(", 0b10>; + def _SETBIT#NAME#_V4 : MemOp_ri_base<opc, opcBits, ImmOp, " =setbit(", 0b11>; +} -// memw(Rs+#u6:2) -= #U5 -let AddedComplexity = 30 in -def MEMw_SUBi_indexed_MEM_V4 : MEMInst_V4<(outs), - (ins IntRegs:$base, u6_2Imm:$offset, u5Imm:$subend), - "memw($base+#$offset) -= #$subend", - []>, - Requires<[HasV4T, UseMEMOP]>; - -// memw(Rs+#u6:2) += Rt -let AddedComplexity = 30 in -def MEMw_ADDr_indexed_MEM_V4 : MEMInst_V4<(outs), - (ins IntRegs:$base, u6_2Imm:$offset, IntRegs:$addend), - "memw($base+#$offset) += $addend", - [(store (add (load (add (i32 IntRegs:$base), u6_2ImmPred:$offset)), - (i32 IntRegs:$addend)), - (add (i32 IntRegs:$base), u6_2ImmPred:$offset))]>, - Requires<[HasV4T, UseMEMOP]>; - -// memw(Rs+#u6:2) -= Rt -let AddedComplexity = 30 in -def MEMw_SUBr_indexed_MEM_V4 : MEMInst_V4<(outs), - (ins IntRegs:$base, u6_2Imm:$offset, IntRegs:$subend), - "memw($base+#$offset) -= $subend", - [(store (sub (load (add (i32 IntRegs:$base), u6_2ImmPred:$offset)), - (i32 IntRegs:$subend)), - (add (i32 IntRegs:$base), u6_2ImmPred:$offset))]>, - Requires<[HasV4T, UseMEMOP]>; - -// memw(Rs+#u6:2) &= Rt -let AddedComplexity = 30 in -def MEMw_ANDr_indexed_MEM_V4 : MEMInst_V4<(outs), - (ins IntRegs:$base, u6_2Imm:$offset, IntRegs:$andend), - "memw($base+#$offset) &= $andend", - [(store (and (load (add (i32 IntRegs:$base), u6_2ImmPred:$offset)), - (i32 IntRegs:$andend)), - (add (i32 IntRegs:$base), u6_2ImmPred:$offset))]>, - Requires<[HasV4T, UseMEMOP]>; - -// memw(Rs+#u6:2) |= Rt -let AddedComplexity = 30 in -def MEMw_ORr_indexed_MEM_V4 : MEMInst_V4<(outs), - (ins IntRegs:$base, u6_2Imm:$offset, IntRegs:$orend), - "memw($base+#$offset) |= $orend", - [(store (or (load (add (i32 IntRegs:$base), u6_2ImmPred:$offset)), - (i32 IntRegs:$orend)), - (add (i32 IntRegs:$base), u6_2ImmPred:$offset))]>, - Requires<[HasV4T, UseMEMOP]>; - -// MEMw_ADDSUBi_V4: -// Pseudo operation for MEMw_ADDi_V4 and MEMw_SUBi_V4 -// a later pass will change it to the right pattern. -let AddedComplexity = 30 in -def MEMw_ADDSUBi_MEM_V4 : MEMInst_V4<(outs), - (ins MEMri:$addr, m6Imm:$addend), - "Error; should not emit", - [(store (add (load ADDRriU6_2:$addr), m6ImmPred:$addend), - ADDRriU6_2:$addr)]>, - Requires<[HasV4T, UseMEMOP]>; - -// memw(Rs+#u6:2) += #U5 -let AddedComplexity = 30 in -def MEMw_ADDi_MEM_V4 : MEMInst_V4<(outs), - (ins MEMri:$addr, u5Imm:$addend), - "memw($addr) += $addend", - []>, - Requires<[HasV4T, UseMEMOP]>; +multiclass MemOp_base <string opc, bits<2> opcBits, Operand ImmOp> { + defm r : MemOp_rr <opc, opcBits, ImmOp>; + defm i : MemOp_ri <opc, opcBits, ImmOp>; +} -// memw(Rs+#u6:2) -= #U5 -let AddedComplexity = 30 in -def MEMw_SUBi_MEM_V4 : MEMInst_V4<(outs), - (ins MEMri:$addr, u5Imm:$subend), - "memw($addr) -= $subend", - []>, - Requires<[HasV4T, UseMEMOP]>; - -// memw(Rs+#u6:2) += Rt -let AddedComplexity = 30 in -def MEMw_ADDr_MEM_V4 : MEMInst_V4<(outs), - (ins MEMri:$addr, IntRegs:$addend), - "memw($addr) += $addend", - [(store (add (load ADDRriU6_2:$addr), (i32 IntRegs:$addend)), - ADDRriU6_2:$addr)]>, - Requires<[HasV4T, UseMEMOP]>; - -// memw(Rs+#u6:2) -= Rt -let AddedComplexity = 30 in -def MEMw_SUBr_MEM_V4 : MEMInst_V4<(outs), - (ins MEMri:$addr, IntRegs:$subend), - "memw($addr) -= $subend", - [(store (sub (load ADDRriU6_2:$addr), (i32 IntRegs:$subend)), - ADDRriU6_2:$addr)]>, - Requires<[HasV4T, UseMEMOP]>; - -// memw(Rs+#u6:2) &= Rt -let AddedComplexity = 30 in -def MEMw_ANDr_MEM_V4 : MEMInst_V4<(outs), - (ins MEMri:$addr, IntRegs:$andend), - "memw($addr) &= $andend", - [(store (and (load ADDRriU6_2:$addr), (i32 IntRegs:$andend)), - ADDRriU6_2:$addr)]>, - Requires<[HasV4T, UseMEMOP]>; - -// memw(Rs+#u6:2) |= Rt -let AddedComplexity = 30 in -def MEMw_ORr_MEM_V4 : MEMInst_V4<(outs), - (ins MEMri:$addr, IntRegs:$orend), - "memw($addr) |= $orend", - [(store (or (load ADDRriU6_2:$addr), (i32 IntRegs:$orend)), - ADDRriU6_2:$addr)]>, - Requires<[HasV4T, UseMEMOP]>; +// Define MemOp instructions. +let isExtendable = 1, opExtendable = 1, isExtentSigned = 0, +validSubTargets =HasV4SubT in { + let opExtentBits = 6, accessSize = ByteAccess in + defm MemOPb : MemOp_base <"memb", 0b00, u6_0Ext>; + + let opExtentBits = 7, accessSize = HalfWordAccess in + defm MemOPh : MemOp_base <"memh", 0b01, u6_1Ext>; + + let opExtentBits = 8, accessSize = WordAccess in + defm MemOPw : MemOp_base <"memw", 0b10, u6_2Ext>; +} //===----------------------------------------------------------------------===// -// MEMOP: Halfword -// -// Implemented: -// MEMh_ADDi_indexed_V4 : memw(Rs+#u6:2)+=#U5 -// MEMh_SUBi_indexed_V4 : memw(Rs+#u6:2)-=#U5 -// MEMh_ADDr_indexed_V4 : memw(Rs+#u6:2)+=Rt -// MEMh_SUBr_indexed_V4 : memw(Rs+#u6:2)-=Rt -// MEMh_CLRr_indexed_V4 : memw(Rs+#u6:2)&=Rt -// MEMh_SETr_indexed_V4 : memw(Rs+#u6:2)|=Rt -// MEMh_ADDi_V4 : memw(Rs+#u6:2)+=#U5 -// MEMh_SUBi_V4 : memw(Rs+#u6:2)-=#U5 -// MEMh_ADDr_V4 : memw(Rs+#u6:2)+=Rt -// MEMh_SUBr_V4 : memw(Rs+#u6:2)-=Rt -// MEMh_CLRr_V4 : memw(Rs+#u6:2)&=Rt -// MEMh_SETr_V4 : memw(Rs+#u6:2)|=Rt -// -// Not implemented: -// MEMh_CLRi_indexed_V4 : memw(Rs+#u6:2)=clrbit(#U5) -// MEMh_SETi_indexed_V4 : memw(Rs+#u6:2)=setbit(#U5) -// MEMh_CLRi_V4 : memw(Rs+#u6:2)=clrbit(#U5) -// MEMh_SETi_V4 : memw(Rs+#u6:2)=setbit(#U5) +// Multiclass to define 'Def Pats' for ALU operations on the memory +// Here value used for the ALU operation is an immediate value. +// mem[bh](Rs+#0) += #U5 +// mem[bh](Rs+#u6) += #U5 //===----------------------------------------------------------------------===// +multiclass MemOpi_u5Pats <PatFrag ldOp, PatFrag stOp, PatLeaf ExtPred, + InstHexagon MI, SDNode OpNode> { + let AddedComplexity = 180 in + def : Pat < (stOp (OpNode (ldOp IntRegs:$addr), u5ImmPred:$addend), + IntRegs:$addr), + (MI IntRegs:$addr, #0, u5ImmPred:$addend )>; + + let AddedComplexity = 190 in + def : Pat <(stOp (OpNode (ldOp (add IntRegs:$base, ExtPred:$offset)), + u5ImmPred:$addend), + (add IntRegs:$base, ExtPred:$offset)), + (MI IntRegs:$base, ExtPred:$offset, u5ImmPred:$addend)>; +} -// MEMh_ADDSUBi_indexed_V4: -// Pseudo operation for MEMh_ADDi_indexed_V4 and -// MEMh_SUBi_indexed_V4 a later pass will change it -// to the corresponding pattern. -let AddedComplexity = 30 in -def MEMh_ADDSUBi_indexed_MEM_V4 : MEMInst_V4<(outs), - (ins IntRegs:$base, u6_1Imm:$offset, m6Imm:$addend), - "Error; should not emit", - [(truncstorei16 (add (sextloadi16 (add (i32 IntRegs:$base), - u6_1ImmPred:$offset)), - m6ImmPred:$addend), - (add (i32 IntRegs:$base), u6_1ImmPred:$offset))]>, - Requires<[HasV4T, UseMEMOP]>; - -// memh(Rs+#u6:1) += #U5 -let AddedComplexity = 30 in -def MEMh_ADDi_indexed_MEM_V4 : MEMInst_V4<(outs), - (ins IntRegs:$base, u6_1Imm:$offset, u5Imm:$addend), - "memh($base+#$offset) += $addend", - []>, - Requires<[HasV4T, UseMEMOP]>; +multiclass MemOpi_u5ALUOp<PatFrag ldOp, PatFrag stOp, PatLeaf ExtPred, + InstHexagon addMI, InstHexagon subMI> { + defm : MemOpi_u5Pats<ldOp, stOp, ExtPred, addMI, add>; + defm : MemOpi_u5Pats<ldOp, stOp, ExtPred, subMI, sub>; +} -// memh(Rs+#u6:1) -= #U5 -let AddedComplexity = 30 in -def MEMh_SUBi_indexed_MEM_V4 : MEMInst_V4<(outs), - (ins IntRegs:$base, u6_1Imm:$offset, u5Imm:$subend), - "memh($base+#$offset) -= $subend", - []>, - Requires<[HasV4T, UseMEMOP]>; - -// memh(Rs+#u6:1) += Rt -let AddedComplexity = 30 in -def MEMh_ADDr_indexed_MEM_V4 : MEMInst_V4<(outs), - (ins IntRegs:$base, u6_1Imm:$offset, IntRegs:$addend), - "memh($base+#$offset) += $addend", - [(truncstorei16 (add (sextloadi16 (add (i32 IntRegs:$base), - u6_1ImmPred:$offset)), - (i32 IntRegs:$addend)), - (add (i32 IntRegs:$base), u6_1ImmPred:$offset))]>, - Requires<[HasV4T, UseMEMOP]>; - -// memh(Rs+#u6:1) -= Rt -let AddedComplexity = 30 in -def MEMh_SUBr_indexed_MEM_V4 : MEMInst_V4<(outs), - (ins IntRegs:$base, u6_1Imm:$offset, IntRegs:$subend), - "memh($base+#$offset) -= $subend", - [(truncstorei16 (sub (sextloadi16 (add (i32 IntRegs:$base), - u6_1ImmPred:$offset)), - (i32 IntRegs:$subend)), - (add (i32 IntRegs:$base), u6_1ImmPred:$offset))]>, - Requires<[HasV4T, UseMEMOP]>; - -// memh(Rs+#u6:1) &= Rt -let AddedComplexity = 30 in -def MEMh_ANDr_indexed_MEM_V4 : MEMInst_V4<(outs), - (ins IntRegs:$base, u6_1Imm:$offset, IntRegs:$andend), - "memh($base+#$offset) += $andend", - [(truncstorei16 (and (sextloadi16 (add (i32 IntRegs:$base), - u6_1ImmPred:$offset)), - (i32 IntRegs:$andend)), - (add (i32 IntRegs:$base), u6_1ImmPred:$offset))]>, - Requires<[HasV4T, UseMEMOP]>; - -// memh(Rs+#u6:1) |= Rt -let AddedComplexity = 30 in -def MEMh_ORr_indexed_MEM_V4 : MEMInst_V4<(outs), - (ins IntRegs:$base, u6_1Imm:$offset, IntRegs:$orend), - "memh($base+#$offset) |= $orend", - [(truncstorei16 (or (sextloadi16 (add (i32 IntRegs:$base), - u6_1ImmPred:$offset)), - (i32 IntRegs:$orend)), - (add (i32 IntRegs:$base), u6_1ImmPred:$offset))]>, - Requires<[HasV4T, UseMEMOP]>; - -// MEMh_ADDSUBi_V4: -// Pseudo operation for MEMh_ADDi_V4 and MEMh_SUBi_V4 -// a later pass will change it to the right pattern. -let AddedComplexity = 30 in -def MEMh_ADDSUBi_MEM_V4 : MEMInst_V4<(outs), - (ins MEMri:$addr, m6Imm:$addend), - "Error; should not emit", - [(truncstorei16 (add (sextloadi16 ADDRriU6_1:$addr), - m6ImmPred:$addend), ADDRriU6_1:$addr)]>, - Requires<[HasV4T, UseMEMOP]>; - -// memh(Rs+#u6:1) += #U5 -let AddedComplexity = 30 in -def MEMh_ADDi_MEM_V4 : MEMInst_V4<(outs), - (ins MEMri:$addr, u5Imm:$addend), - "memh($addr) += $addend", - []>, - Requires<[HasV4T, UseMEMOP]>; +multiclass MemOpi_u5ExtType<PatFrag ldOpByte, PatFrag ldOpHalf > { + // Half Word + defm : MemOpi_u5ALUOp <ldOpHalf, truncstorei16, u6_1ExtPred, + MemOPh_ADDi_V4, MemOPh_SUBi_V4>; + // Byte + defm : MemOpi_u5ALUOp <ldOpByte, truncstorei8, u6ExtPred, + MemOPb_ADDi_V4, MemOPb_SUBi_V4>; +} -// memh(Rs+#u6:1) -= #U5 -let AddedComplexity = 30 in -def MEMh_SUBi_MEM_V4 : MEMInst_V4<(outs), - (ins MEMri:$addr, u5Imm:$subend), - "memh($addr) -= $subend", - []>, - Requires<[HasV4T, UseMEMOP]>; - -// memh(Rs+#u6:1) += Rt -let AddedComplexity = 30 in -def MEMh_ADDr_MEM_V4 : MEMInst_V4<(outs), - (ins MEMri:$addr, IntRegs:$addend), - "memh($addr) += $addend", - [(truncstorei16 (add (sextloadi16 ADDRriU6_1:$addr), - (i32 IntRegs:$addend)), ADDRriU6_1:$addr)]>, - Requires<[HasV4T, UseMEMOP]>; - -// memh(Rs+#u6:1) -= Rt -let AddedComplexity = 30 in -def MEMh_SUBr_MEM_V4 : MEMInst_V4<(outs), - (ins MEMri:$addr, IntRegs:$subend), - "memh($addr) -= $subend", - [(truncstorei16 (sub (sextloadi16 ADDRriU6_1:$addr), - (i32 IntRegs:$subend)), ADDRriU6_1:$addr)]>, - Requires<[HasV4T, UseMEMOP]>; - -// memh(Rs+#u6:1) &= Rt -let AddedComplexity = 30 in -def MEMh_ANDr_MEM_V4 : MEMInst_V4<(outs), - (ins MEMri:$addr, IntRegs:$andend), - "memh($addr) &= $andend", - [(truncstorei16 (and (sextloadi16 ADDRriU6_1:$addr), - (i32 IntRegs:$andend)), ADDRriU6_1:$addr)]>, - Requires<[HasV4T, UseMEMOP]>; - -// memh(Rs+#u6:1) |= Rt -let AddedComplexity = 30 in -def MEMh_ORr_MEM_V4 : MEMInst_V4<(outs), - (ins MEMri:$addr, IntRegs:$orend), - "memh($addr) |= $orend", - [(truncstorei16 (or (sextloadi16 ADDRriU6_1:$addr), - (i32 IntRegs:$orend)), ADDRriU6_1:$addr)]>, - Requires<[HasV4T, UseMEMOP]>; +let Predicates = [HasV4T, UseMEMOP] in { + defm : MemOpi_u5ExtType<zextloadi8, zextloadi16>; // zero extend + defm : MemOpi_u5ExtType<sextloadi8, sextloadi16>; // sign extend + defm : MemOpi_u5ExtType<extloadi8, extloadi16>; // any extend + // Word + defm : MemOpi_u5ALUOp <load, store, u6_2ExtPred, MemOPw_ADDi_V4, + MemOPw_SUBi_V4>; +} //===----------------------------------------------------------------------===// -// MEMOP: Byte -// -// Implemented: -// MEMb_ADDi_indexed_V4 : memb(Rs+#u6:0)+=#U5 -// MEMb_SUBi_indexed_V4 : memb(Rs+#u6:0)-=#U5 -// MEMb_ADDr_indexed_V4 : memb(Rs+#u6:0)+=Rt -// MEMb_SUBr_indexed_V4 : memb(Rs+#u6:0)-=Rt -// MEMb_CLRr_indexed_V4 : memb(Rs+#u6:0)&=Rt -// MEMb_SETr_indexed_V4 : memb(Rs+#u6:0)|=Rt -// MEMb_ADDi_V4 : memb(Rs+#u6:0)+=#U5 -// MEMb_SUBi_V4 : memb(Rs+#u6:0)-=#U5 -// MEMb_ADDr_V4 : memb(Rs+#u6:0)+=Rt -// MEMb_SUBr_V4 : memb(Rs+#u6:0)-=Rt -// MEMb_CLRr_V4 : memb(Rs+#u6:0)&=Rt -// MEMb_SETr_V4 : memb(Rs+#u6:0)|=Rt -// -// Not implemented: -// MEMb_CLRi_indexed_V4 : memb(Rs+#u6:0)=clrbit(#U5) -// MEMb_SETi_indexed_V4 : memb(Rs+#u6:0)=setbit(#U5) -// MEMb_CLRi_V4 : memb(Rs+#u6:0)=clrbit(#U5) -// MEMb_SETi_V4 : memb(Rs+#u6:0)=setbit(#U5) +// multiclass to define 'Def Pats' for ALU operations on the memory. +// Here value used for the ALU operation is a negative value. +// mem[bh](Rs+#0) += #m5 +// mem[bh](Rs+#u6) += #m5 //===----------------------------------------------------------------------===// +multiclass MemOpi_m5Pats <PatFrag ldOp, PatFrag stOp, PatLeaf extPred, + PatLeaf immPred, ComplexPattern addrPred, + SDNodeXForm xformFunc, InstHexagon MI> { + let AddedComplexity = 190 in + def : Pat <(stOp (add (ldOp IntRegs:$addr), immPred:$subend), + IntRegs:$addr), + (MI IntRegs:$addr, #0, (xformFunc immPred:$subend) )>; + + let AddedComplexity = 195 in + def : Pat<(stOp (add (ldOp (add IntRegs:$base, extPred:$offset)), + immPred:$subend), + (add IntRegs:$base, extPred:$offset)), + (MI IntRegs:$base, extPred:$offset, (xformFunc immPred:$subend))>; +} -// MEMb_ADDSUBi_indexed_V4: -// Pseudo operation for MEMb_ADDi_indexed_V4 and -// MEMb_SUBi_indexed_V4 a later pass will change it -// to the corresponding pattern. -let AddedComplexity = 30 in -def MEMb_ADDSUBi_indexed_MEM_V4 : MEMInst_V4<(outs), - (ins IntRegs:$base, u6_0Imm:$offset, m6Imm:$addend), - "Error; should not emit", - [(truncstorei8 (add (sextloadi8 (add (i32 IntRegs:$base), - u6_0ImmPred:$offset)), - m6ImmPred:$addend), - (add (i32 IntRegs:$base), u6_0ImmPred:$offset))]>, - Requires<[HasV4T, UseMEMOP]>; - -// memb(Rs+#u6:0) += #U5 -let AddedComplexity = 30 in -def MEMb_ADDi_indexed_MEM_V4 : MEMInst_V4<(outs), - (ins IntRegs:$base, u6_0Imm:$offset, u5Imm:$addend), - "memb($base+#$offset) += $addend", - []>, - Requires<[HasV4T, UseMEMOP]>; +multiclass MemOpi_m5ExtType<PatFrag ldOpByte, PatFrag ldOpHalf > { + // Half Word + defm : MemOpi_m5Pats <ldOpHalf, truncstorei16, u6_1ExtPred, m5HImmPred, + ADDRriU6_1, MEMOPIMM_HALF, MemOPh_SUBi_V4>; + // Byte + defm : MemOpi_m5Pats <ldOpByte, truncstorei8, u6ExtPred, m5BImmPred, + ADDRriU6_0, MEMOPIMM_BYTE, MemOPb_SUBi_V4>; +} -// memb(Rs+#u6:0) -= #U5 -let AddedComplexity = 30 in -def MEMb_SUBi_indexed_MEM_V4 : MEMInst_V4<(outs), - (ins IntRegs:$base, u6_0Imm:$offset, u5Imm:$subend), - "memb($base+#$offset) -= $subend", - []>, - Requires<[HasV4T, UseMEMOP]>; - -// memb(Rs+#u6:0) += Rt -let AddedComplexity = 30 in -def MEMb_ADDr_indexed_MEM_V4 : MEMInst_V4<(outs), - (ins IntRegs:$base, u6_0Imm:$offset, IntRegs:$addend), - "memb($base+#$offset) += $addend", - [(truncstorei8 (add (sextloadi8 (add (i32 IntRegs:$base), - u6_0ImmPred:$offset)), - (i32 IntRegs:$addend)), - (add (i32 IntRegs:$base), u6_0ImmPred:$offset))]>, - Requires<[HasV4T, UseMEMOP]>; - -// memb(Rs+#u6:0) -= Rt -let AddedComplexity = 30 in -def MEMb_SUBr_indexed_MEM_V4 : MEMInst_V4<(outs), - (ins IntRegs:$base, u6_0Imm:$offset, IntRegs:$subend), - "memb($base+#$offset) -= $subend", - [(truncstorei8 (sub (sextloadi8 (add (i32 IntRegs:$base), - u6_0ImmPred:$offset)), - (i32 IntRegs:$subend)), - (add (i32 IntRegs:$base), u6_0ImmPred:$offset))]>, - Requires<[HasV4T, UseMEMOP]>; - -// memb(Rs+#u6:0) &= Rt -let AddedComplexity = 30 in -def MEMb_ANDr_indexed_MEM_V4 : MEMInst_V4<(outs), - (ins IntRegs:$base, u6_0Imm:$offset, IntRegs:$andend), - "memb($base+#$offset) += $andend", - [(truncstorei8 (and (sextloadi8 (add (i32 IntRegs:$base), - u6_0ImmPred:$offset)), - (i32 IntRegs:$andend)), - (add (i32 IntRegs:$base), u6_0ImmPred:$offset))]>, - Requires<[HasV4T, UseMEMOP]>; - -// memb(Rs+#u6:0) |= Rt -let AddedComplexity = 30 in -def MEMb_ORr_indexed_MEM_V4 : MEMInst_V4<(outs), - (ins IntRegs:$base, u6_0Imm:$offset, IntRegs:$orend), - "memb($base+#$offset) |= $orend", - [(truncstorei8 (or (sextloadi8 (add (i32 IntRegs:$base), - u6_0ImmPred:$offset)), - (i32 IntRegs:$orend)), - (add (i32 IntRegs:$base), u6_0ImmPred:$offset))]>, - Requires<[HasV4T, UseMEMOP]>; - -// MEMb_ADDSUBi_V4: -// Pseudo operation for MEMb_ADDi_V4 and MEMb_SUBi_V4 -// a later pass will change it to the right pattern. -let AddedComplexity = 30 in -def MEMb_ADDSUBi_MEM_V4 : MEMInst_V4<(outs), - (ins MEMri:$addr, m6Imm:$addend), - "Error; should not emit", - [(truncstorei8 (add (sextloadi8 ADDRriU6_0:$addr), - m6ImmPred:$addend), ADDRriU6_0:$addr)]>, - Requires<[HasV4T, UseMEMOP]>; - -// memb(Rs+#u6:0) += #U5 -let AddedComplexity = 30 in -def MEMb_ADDi_MEM_V4 : MEMInst_V4<(outs), - (ins MEMri:$addr, u5Imm:$addend), - "memb($addr) += $addend", - []>, - Requires<[HasV4T, UseMEMOP]>; +let Predicates = [HasV4T, UseMEMOP] in { + defm : MemOpi_m5ExtType<zextloadi8, zextloadi16>; // zero extend + defm : MemOpi_m5ExtType<sextloadi8, sextloadi16>; // sign extend + defm : MemOpi_m5ExtType<extloadi8, extloadi16>; // any extend -// memb(Rs+#u6:0) -= #U5 -let AddedComplexity = 30 in -def MEMb_SUBi_MEM_V4 : MEMInst_V4<(outs), - (ins MEMri:$addr, u5Imm:$subend), - "memb($addr) -= $subend", - []>, - Requires<[HasV4T, UseMEMOP]>; - -// memb(Rs+#u6:0) += Rt -let AddedComplexity = 30 in -def MEMb_ADDr_MEM_V4 : MEMInst_V4<(outs), - (ins MEMri:$addr, IntRegs:$addend), - "memb($addr) += $addend", - [(truncstorei8 (add (sextloadi8 ADDRriU6_0:$addr), - (i32 IntRegs:$addend)), ADDRriU6_0:$addr)]>, - Requires<[HasV4T, UseMEMOP]>; - -// memb(Rs+#u6:0) -= Rt -let AddedComplexity = 30 in -def MEMb_SUBr_MEM_V4 : MEMInst_V4<(outs), - (ins MEMri:$addr, IntRegs:$subend), - "memb($addr) -= $subend", - [(truncstorei8 (sub (sextloadi8 ADDRriU6_0:$addr), - (i32 IntRegs:$subend)), ADDRriU6_0:$addr)]>, - Requires<[HasV4T, UseMEMOP]>; - -// memb(Rs+#u6:0) &= Rt -let AddedComplexity = 30 in -def MEMb_ANDr_MEM_V4 : MEMInst_V4<(outs), - (ins MEMri:$addr, IntRegs:$andend), - "memb($addr) &= $andend", - [(truncstorei8 (and (sextloadi8 ADDRriU6_0:$addr), - (i32 IntRegs:$andend)), ADDRriU6_0:$addr)]>, - Requires<[HasV4T, UseMEMOP]>; - -// memb(Rs+#u6:0) |= Rt -let AddedComplexity = 30 in -def MEMb_ORr_MEM_V4 : MEMInst_V4<(outs), - (ins MEMri:$addr, IntRegs:$orend), - "memb($addr) |= $orend", - [(truncstorei8 (or (sextloadi8 ADDRriU6_0:$addr), - (i32 IntRegs:$orend)), ADDRriU6_0:$addr)]>, - Requires<[HasV4T, UseMEMOP]>; + // Word + defm : MemOpi_m5Pats <load, store, u6_2ExtPred, m5ImmPred, + ADDRriU6_2, MEMOPIMM, MemOPw_SUBi_V4>; +} +//===----------------------------------------------------------------------===// +// Multiclass to define 'def Pats' for bit operations on the memory. +// mem[bhw](Rs+#0) = [clrbit|setbit](#U5) +// mem[bhw](Rs+#u6) = [clrbit|setbit](#U5) +//===----------------------------------------------------------------------===// + +multiclass MemOpi_bitPats <PatFrag ldOp, PatFrag stOp, PatLeaf immPred, + PatLeaf extPred, ComplexPattern addrPred, + SDNodeXForm xformFunc, InstHexagon MI, SDNode OpNode> { + + // mem[bhw](Rs+#u6:[012]) = [clrbit|setbit](#U5) + let AddedComplexity = 250 in + def : Pat<(stOp (OpNode (ldOp (add IntRegs:$base, extPred:$offset)), + immPred:$bitend), + (add IntRegs:$base, extPred:$offset)), + (MI IntRegs:$base, extPred:$offset, (xformFunc immPred:$bitend))>; + + // mem[bhw](Rs+#0) = [clrbit|setbit](#U5) + let AddedComplexity = 225 in + def : Pat <(stOp (OpNode (ldOp addrPred:$addr), immPred:$bitend), + addrPred:$addr), + (MI IntRegs:$addr, #0, (xformFunc immPred:$bitend))>; +} + +multiclass MemOpi_bitExtType<PatFrag ldOpByte, PatFrag ldOpHalf > { + // Byte - clrbit + defm : MemOpi_bitPats<ldOpByte, truncstorei8, Clr3ImmPred, u6ExtPred, + ADDRriU6_0, CLRMEMIMM_BYTE, MemOPb_CLRBITi_V4, and>; + // Byte - setbit + defm : MemOpi_bitPats<ldOpByte, truncstorei8, Set3ImmPred, u6ExtPred, + ADDRriU6_0, SETMEMIMM_BYTE, MemOPb_SETBITi_V4, or>; + // Half Word - clrbit + defm : MemOpi_bitPats<ldOpHalf, truncstorei16, Clr4ImmPred, u6_1ExtPred, + ADDRriU6_1, CLRMEMIMM_SHORT, MemOPh_CLRBITi_V4, and>; + // Half Word - setbit + defm : MemOpi_bitPats<ldOpHalf, truncstorei16, Set4ImmPred, u6_1ExtPred, + ADDRriU6_1, SETMEMIMM_SHORT, MemOPh_SETBITi_V4, or>; +} + +let Predicates = [HasV4T, UseMEMOP] in { + // mem[bh](Rs+#0) = [clrbit|setbit](#U5) + // mem[bh](Rs+#u6:[01]) = [clrbit|setbit](#U5) + defm : MemOpi_bitExtType<zextloadi8, zextloadi16>; // zero extend + defm : MemOpi_bitExtType<sextloadi8, sextloadi16>; // sign extend + defm : MemOpi_bitExtType<extloadi8, extloadi16>; // any extend + + // memw(Rs+#0) = [clrbit|setbit](#U5) + // memw(Rs+#u6:2) = [clrbit|setbit](#U5) + defm : MemOpi_bitPats<load, store, Clr5ImmPred, u6_2ExtPred, ADDRriU6_2, + CLRMEMIMM, MemOPw_CLRBITi_V4, and>; + defm : MemOpi_bitPats<load, store, Set5ImmPred, u6_2ExtPred, ADDRriU6_2, + SETMEMIMM, MemOPw_SETBITi_V4, or>; +} + +//===----------------------------------------------------------------------===// +// Multiclass to define 'def Pats' for ALU operations on the memory +// where addend is a register. +// mem[bhw](Rs+#0) [+-&|]= Rt +// mem[bhw](Rs+#U6:[012]) [+-&|]= Rt +//===----------------------------------------------------------------------===// + +multiclass MemOpr_Pats <PatFrag ldOp, PatFrag stOp, ComplexPattern addrPred, + PatLeaf extPred, InstHexagon MI, SDNode OpNode> { + let AddedComplexity = 141 in + // mem[bhw](Rs+#0) [+-&|]= Rt + def : Pat <(stOp (OpNode (ldOp addrPred:$addr), (i32 IntRegs:$addend)), + addrPred:$addr), + (MI IntRegs:$addr, #0, (i32 IntRegs:$addend) )>; + + // mem[bhw](Rs+#U6:[012]) [+-&|]= Rt + let AddedComplexity = 150 in + def : Pat <(stOp (OpNode (ldOp (add IntRegs:$base, extPred:$offset)), + (i32 IntRegs:$orend)), + (add IntRegs:$base, extPred:$offset)), + (MI IntRegs:$base, extPred:$offset, (i32 IntRegs:$orend) )>; +} + +multiclass MemOPr_ALUOp<PatFrag ldOp, PatFrag stOp, + ComplexPattern addrPred, PatLeaf extPred, + InstHexagon addMI, InstHexagon subMI, + InstHexagon andMI, InstHexagon orMI > { + + defm : MemOpr_Pats <ldOp, stOp, addrPred, extPred, addMI, add>; + defm : MemOpr_Pats <ldOp, stOp, addrPred, extPred, subMI, sub>; + defm : MemOpr_Pats <ldOp, stOp, addrPred, extPred, andMI, and>; + defm : MemOpr_Pats <ldOp, stOp, addrPred, extPred, orMI, or>; +} + +multiclass MemOPr_ExtType<PatFrag ldOpByte, PatFrag ldOpHalf > { + // Half Word + defm : MemOPr_ALUOp <ldOpHalf, truncstorei16, ADDRriU6_1, u6_1ExtPred, + MemOPh_ADDr_V4, MemOPh_SUBr_V4, + MemOPh_ANDr_V4, MemOPh_ORr_V4>; + // Byte + defm : MemOPr_ALUOp <ldOpByte, truncstorei8, ADDRriU6_0, u6ExtPred, + MemOPb_ADDr_V4, MemOPb_SUBr_V4, + MemOPb_ANDr_V4, MemOPb_ORr_V4>; +} + +// Define 'def Pats' for MemOps with register addend. +let Predicates = [HasV4T, UseMEMOP] in { + // Byte, Half Word + defm : MemOPr_ExtType<zextloadi8, zextloadi16>; // zero extend + defm : MemOPr_ExtType<sextloadi8, sextloadi16>; // sign extend + defm : MemOPr_ExtType<extloadi8, extloadi16>; // any extend + // Word + defm : MemOPr_ALUOp <load, store, ADDRriU6_2, u6_2ExtPred, MemOPw_ADDr_V4, + MemOPw_SUBr_V4, MemOPw_ANDr_V4, MemOPw_ORr_V4 >; +} //===----------------------------------------------------------------------===// // XTYPE/PRED + @@ -4992,7 +2222,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)", @@ -5000,8 +2284,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)", @@ -5011,7 +2301,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)", @@ -5021,7 +2311,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)", @@ -5031,29 +2321,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)", @@ -5067,7 +2565,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)", @@ -5082,7 +2580,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)", @@ -5096,19 +2594,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)", @@ -5119,24 +2618,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 - @@ -5248,227 +2764,258 @@ 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)")), - []>, - Requires<[HasV4T]>; +//===----------------------------------------------------------------------===// +// multiclass for store instructions with GP-relative addressing mode. +// mem[bhwd](#global)=Rt +// if ([!]Pv[.new]) mem[bhwd](##global) = Rt +//===----------------------------------------------------------------------===// +multiclass ST_GP<string mnemonic, string BaseOp, RegisterClass RC> { + let BaseOpcode = BaseOp, isPredicable = 1 in + def NAME#_V4 : STInst2<(outs), + (ins globaladdress:$global, RC:$src), + mnemonic#"(#$global) = $src", + []>; + + // When GP-relative instructions are predicated, their addressing mode is + // changed to absolute and they are always constant extended. + let BaseOpcode = BaseOp, isExtended = 1, 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_cNotPt_V4 : LDInst2<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$absaddr), - !strconcat("if (!$src1) $dst = ", - !strconcat(OpcStr, "(##$absaddr)")), - []>, - Requires<[HasV4T]>; +let mayStore = 1, isNVStore = 1 in +multiclass ST_GP_nv<string mnemonic, string BaseOp, RegisterClass RC> { + let BaseOpcode = BaseOp, isPredicable = 1 in + def NAME#_nv_V4 : NVInst_V4<(outs), + (ins u0AlwaysExt:$global, RC:$src), + mnemonic#"(#$global) = $src.new", + []>, + Requires<[HasV4T]>; - 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)")), - []>, - Requires<[HasV4T]>; + // When GP-relative instructions are predicated, their addressing mode is + // changed to absolute and they are always constant extended. + let BaseOpcode = BaseOp, isExtended = 1, opExtendable = 1, + isPredicated = 1 in { + defm Pt : ST_Abs_Pred_nv<mnemonic, RC, 0>; + defm NotPt : ST_Abs_Pred_nv<mnemonic, RC, 1>; + } +} - 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 validSubTargets = HasV4SubT, validSubTargets = HasV4SubT in { +defm STd_GP : ST_GP <"memd", "STd_GP", DoubleRegs>, + ST_GP_nv<"memd", "STd_GP", DoubleRegs>, NewValueRel ; +defm STb_GP : ST_GP<"memb", "STb_GP", IntRegs>, + ST_GP_nv<"memb", "STb_GP", IntRegs>, NewValueRel ; +defm STh_GP : ST_GP<"memh", "STh_GP", IntRegs>, + ST_GP_nv<"memh", "STh_GP", IntRegs>, NewValueRel ; +defm STw_GP : ST_GP<"memw", "STw_GP", IntRegs>, + ST_GP_nv<"memw", "STw_GP", IntRegs>, NewValueRel ; } -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]>; +// 64 bit atomic store +def : Pat <(atomic_store_64 (HexagonCONST32_GP tglobaladdr:$global), + (i64 DoubleRegs:$src1)), + (STd_GP_V4 tglobaladdr:$global, (i64 DoubleRegs:$src1))>, + 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]>; +// Map from store(globaladdress) -> memd(#foo) +let AddedComplexity = 100 in +def : Pat <(store (i64 DoubleRegs:$src1), + (HexagonCONST32_GP tglobaladdr:$global)), + (STd_GP_V4 tglobaladdr:$global, (i64 DoubleRegs:$src1))>; -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]>; +// 8 bit atomic store +def : Pat < (atomic_store_8 (HexagonCONST32_GP tglobaladdr:$global), + (i32 IntRegs:$src1)), + (STb_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>; -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]>; +// Map from store(globaladdress) -> memb(#foo) +let AddedComplexity = 100 in +def : Pat<(truncstorei8 (i32 IntRegs:$src1), + (HexagonCONST32_GP tglobaladdr:$global)), + (STb_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>; -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]>; +// Map from "i1 = constant<-1>; memw(CONST32(#foo)) = i1" +// to "r0 = 1; memw(#foo) = r0" +let AddedComplexity = 100 in +def : Pat<(store (i1 -1), (HexagonCONST32_GP tglobaladdr:$global)), + (STb_GP_V4 tglobaladdr:$global, (TFRI 1))>; + +def : Pat<(atomic_store_16 (HexagonCONST32_GP tglobaladdr:$global), + (i32 IntRegs:$src1)), + (STh_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>; + +// Map from store(globaladdress) -> memh(#foo) +let AddedComplexity = 100 in +def : Pat<(truncstorei16 (i32 IntRegs:$src1), + (HexagonCONST32_GP tglobaladdr:$global)), + (STh_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>; + +// 32 bit atomic store +def : Pat<(atomic_store_32 (HexagonCONST32_GP tglobaladdr:$global), + (i32 IntRegs:$src1)), + (STw_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>; + +// Map from store(globaladdress) -> memw(#foo) +let AddedComplexity = 100 in +def : Pat<(store (i32 IntRegs:$src1), (HexagonCONST32_GP tglobaladdr:$global)), + (STw_GP_V4 tglobaladdr:$global, (i32 IntRegs:$src1))>; + +//===----------------------------------------------------------------------===// +// Multiclass for the load instructions with absolute addressing mode. +//===----------------------------------------------------------------------===// +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]>; +} -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">; +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 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 opExtendable = 2, isPredicated = 1 in { + defm Pt_V4 : LD_Abs_Pred<mnemonic, RC, 0>; + defm NotPt_V4 : LD_Abs_Pred<mnemonic, RC, 1>; + } + } +} + +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))), @@ -5490,6 +3037,107 @@ let Predicates = [HasV4T], AddedComplexity=30 in def : Pat<(i32 (zextloadi16 (HexagonCONST32 tglobaladdr:$absaddr))), (LDriuh_abs_V4 tglobaladdr:$absaddr)>; +//===----------------------------------------------------------------------===// +// multiclass for load instructions with GP-relative addressing mode. +// Rx=mem[bhwd](##global) +// if ([!]Pv[.new]) Rx=mem[bhwd](##global) +//===----------------------------------------------------------------------===// +let neverHasSideEffects = 1, validSubTargets = HasV4SubT in +multiclass LD_GP<string mnemonic, string BaseOp, RegisterClass RC> { + let BaseOpcode = BaseOp in { + let isPredicable = 1 in + def NAME#_V4 : LDInst2<(outs RC:$dst), + (ins globaladdress:$global), + "$dst = "#mnemonic#"(#$global)", + []>; + + let isExtended = 1, opExtendable = 2, isPredicated = 1 in { + defm Pt_V4 : LD_Abs_Pred<mnemonic, RC, 0>; + defm NotPt_V4 : LD_Abs_Pred<mnemonic, RC, 1>; + } + } +} + +defm LDd_GP : LD_GP<"memd", "LDd_GP", DoubleRegs>; +defm LDb_GP : LD_GP<"memb", "LDb_GP", IntRegs>; +defm LDub_GP : LD_GP<"memub", "LDub_GP", IntRegs>; +defm LDh_GP : LD_GP<"memh", "LDh_GP", IntRegs>; +defm LDuh_GP : LD_GP<"memuh", "LDuh_GP", IntRegs>; +defm LDw_GP : LD_GP<"memw", "LDw_GP", IntRegs>; + +def : Pat <(atomic_load_64 (HexagonCONST32_GP tglobaladdr:$global)), + (i64 (LDd_GP_V4 tglobaladdr:$global))>; + +def : Pat <(atomic_load_32 (HexagonCONST32_GP tglobaladdr:$global)), + (i32 (LDw_GP_V4 tglobaladdr:$global))>; + +def : Pat <(atomic_load_16 (HexagonCONST32_GP tglobaladdr:$global)), + (i32 (LDuh_GP_V4 tglobaladdr:$global))>; + +def : Pat <(atomic_load_8 (HexagonCONST32_GP tglobaladdr:$global)), + (i32 (LDub_GP_V4 tglobaladdr:$global))>; + +// Map from load(globaladdress) -> memw(#foo + 0) +let AddedComplexity = 100 in +def : Pat <(i64 (load (HexagonCONST32_GP tglobaladdr:$global))), + (i64 (LDd_GP_V4 tglobaladdr:$global))>; + +// Map from Pd = load(globaladdress) -> Rd = memb(globaladdress), Pd = Rd +let AddedComplexity = 100 in +def : Pat <(i1 (load (HexagonCONST32_GP tglobaladdr:$global))), + (i1 (TFR_PdRs (i32 (LDb_GP_V4 tglobaladdr:$global))))>; + +// When the Interprocedural Global Variable optimizer realizes that a certain +// global variable takes only two constant values, it shrinks the global to +// a boolean. Catch those loads here in the following 3 patterns. +let AddedComplexity = 100 in +def : Pat <(i32 (extloadi1 (HexagonCONST32_GP tglobaladdr:$global))), + (i32 (LDb_GP_V4 tglobaladdr:$global))>; + +let AddedComplexity = 100 in +def : Pat <(i32 (sextloadi1 (HexagonCONST32_GP tglobaladdr:$global))), + (i32 (LDb_GP_V4 tglobaladdr:$global))>; + +// Map from load(globaladdress) -> memb(#foo) +let AddedComplexity = 100 in +def : Pat <(i32 (extloadi8 (HexagonCONST32_GP tglobaladdr:$global))), + (i32 (LDb_GP_V4 tglobaladdr:$global))>; + +// Map from load(globaladdress) -> memb(#foo) +let AddedComplexity = 100 in +def : Pat <(i32 (sextloadi8 (HexagonCONST32_GP tglobaladdr:$global))), + (i32 (LDb_GP_V4 tglobaladdr:$global))>; + +let AddedComplexity = 100 in +def : Pat <(i32 (zextloadi1 (HexagonCONST32_GP tglobaladdr:$global))), + (i32 (LDub_GP_V4 tglobaladdr:$global))>; + +// Map from load(globaladdress) -> memub(#foo) +let AddedComplexity = 100 in +def : Pat <(i32 (zextloadi8 (HexagonCONST32_GP tglobaladdr:$global))), + (i32 (LDub_GP_V4 tglobaladdr:$global))>; + +// Map from load(globaladdress) -> memh(#foo) +let AddedComplexity = 100 in +def : Pat <(i32 (extloadi16 (HexagonCONST32_GP tglobaladdr:$global))), + (i32 (LDh_GP_V4 tglobaladdr:$global))>; + +// Map from load(globaladdress) -> memh(#foo) +let AddedComplexity = 100 in +def : Pat <(i32 (sextloadi16 (HexagonCONST32_GP tglobaladdr:$global))), + (i32 (LDh_GP_V4 tglobaladdr:$global))>; + +// Map from load(globaladdress) -> memuh(#foo) +let AddedComplexity = 100 in +def : Pat <(i32 (zextloadi16 (HexagonCONST32_GP tglobaladdr:$global))), + (i32 (LDuh_GP_V4 tglobaladdr:$global))>; + +// Map from load(globaladdress) -> memw(#foo) +let AddedComplexity = 100 in +def : Pat <(i32 (load (HexagonCONST32_GP tglobaladdr:$global))), + (i32 (LDw_GP_V4 tglobaladdr:$global))>; + + // Transfer global address into a register let AddedComplexity=50, isMoveImm = 1, isReMaterializable = 1 in def TFRI_V4 : ALU32_ri<(outs IntRegs:$dst), (ins globaladdress:$src1), @@ -5497,6 +3145,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), @@ -5588,172 +3241,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<(truncstorei8 (i32 IntRegs:$src1), u0AlwaysExtPred:$src2), + (STrib_imm_abs_V4 u0AlwaysExtPred:$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<(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 @@ -5775,3 +3423,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/contrib/llvm/lib/Target/Hexagon/HexagonMCInst.h b/contrib/llvm/lib/Target/Hexagon/HexagonMCInst.h deleted file mode 100644 index 7a16c24..0000000 --- a/contrib/llvm/lib/Target/Hexagon/HexagonMCInst.h +++ /dev/null @@ -1,41 +0,0 @@ -//===- 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 annotation. -// -//===----------------------------------------------------------------------===// - -#ifndef HEXAGONMCINST_H -#define HEXAGONMCINST_H - -#include "llvm/MC/MCInst.h" -#include "llvm/CodeGen/MachineInstr.h" - -namespace llvm { - class HexagonMCInst: public MCInst { - // Packet start and end markers - unsigned startPacket: 1, endPacket: 1; - const MachineInstr *MachineI; - public: - explicit HexagonMCInst(): MCInst(), - startPacket(0), endPacket(0) {} - - const MachineInstr* getMI() const { return MachineI; } - - void setMI(const MachineInstr *MI) { MachineI = MI; } - - bool isStartPacket() const { return (startPacket); } - bool isEndPacket() const { return (endPacket); } - - void setStartPacket(bool yes) { startPacket = yes; } - void setEndPacket(bool yes) { endPacket = yes; } - }; -} - -#endif diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonMCInstLower.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonMCInstLower.cpp index 70bddcc..f011d51 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonMCInstLower.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonMCInstLower.cpp @@ -15,8 +15,9 @@ #include "Hexagon.h" #include "HexagonAsmPrinter.h" #include "HexagonMachineFunctionInfo.h" -#include "llvm/Constants.h" +#include "MCTargetDesc/HexagonMCInst.h" #include "llvm/CodeGen/MachineBasicBlock.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/contrib/llvm/lib/Target/Hexagon/HexagonMachineScheduler.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonMachineScheduler.cpp index 0e9ef48..1388ad4 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonMachineScheduler.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonMachineScheduler.cpp @@ -15,8 +15,8 @@ #define DEBUG_TYPE "misched" #include "HexagonMachineScheduler.h" - -#include <queue> +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/IR/Function.h" using namespace llvm; @@ -153,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) @@ -167,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)) { @@ -187,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); @@ -194,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); @@ -678,4 +690,3 @@ void ConvergingVLIWScheduler::schedNode(SUnit *SU, bool IsTopNode) { Bot.bumpNode(SU); } } - diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonMachineScheduler.h b/contrib/llvm/lib/Target/Hexagon/HexagonMachineScheduler.h index fe0242a..f68dadf 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonMachineScheduler.h +++ b/contrib/llvm/lib/Target/Hexagon/HexagonMachineScheduler.h @@ -14,6 +14,9 @@ #ifndef HEXAGONASMPRINTER_H #define HEXAGONASMPRINTER_H +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/PriorityQueue.h" +#include "llvm/Analysis/AliasAnalysis.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/CodeGen/MachineScheduler.h" #include "llvm/CodeGen/Passes.h" @@ -22,14 +25,11 @@ #include "llvm/CodeGen/ResourcePriorityQueue.h" #include "llvm/CodeGen/ScheduleDAGInstrs.h" #include "llvm/CodeGen/ScheduleHazardRecognizer.h" -#include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/Target/TargetInstrInfo.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/PriorityQueue.h" +#include "llvm/Target/TargetInstrInfo.h" using namespace llvm; diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonNewValueJump.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonNewValueJump.cpp index 1e91c39..5e80e48 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonNewValueJump.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonNewValueJump.cpp @@ -22,31 +22,29 @@ // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "hexagon-nvj" -#include "llvm/PassSupport.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Debug.h" +#include "Hexagon.h" +#include "HexagonInstrInfo.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/Passes.h" -#include "llvm/CodeGen/ScheduleDAGInstrs.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/LiveVariables.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineFunctionAnalysis.h" -#include "llvm/Target/TargetMachine.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/ScheduleDAGInstrs.h" +#include "llvm/PassSupport.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.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 "HexagonInstrInfo.h" -#include "HexagonMachineFunctionInfo.h" - #include <map> - -#include "llvm/Support/CommandLine.h" using namespace llvm; STATISTIC(NumNVJGenerated, "Number of New Value Jump Instructions created"); @@ -222,7 +220,7 @@ static bool canCompareBeNewValueJump(const HexagonInstrInfo *QII, return false; } - unsigned cmpReg1, cmpOp2 = 0; // cmpOp2 assignment silences compiler warning. + unsigned cmpReg1, cmpOp2; cmpReg1 = MI->getOperand(1).getReg(); if (secondReg) { diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonOperands.td b/contrib/llvm/lib/Target/Hexagon/HexagonOperands.td new file mode 100644 index 0000000..c79d78f --- /dev/null +++ b/contrib/llvm/lib/Target/Hexagon/HexagonOperands.td @@ -0,0 +1,858 @@ +//===- HexagonOperands.td - Hexagon immediate processing -*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illnois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Immediate operands. + +let PrintMethod = "printImmOperand" in { + // f32Ext type is used to identify constant extended floating point immediates. + def f32Ext : Operand<f32>; + def s32Imm : Operand<i32>; + def s26_6Imm : Operand<i32>; + def s16Imm : Operand<i32>; + def s12Imm : Operand<i32>; + def s11Imm : Operand<i32>; + def s11_0Imm : Operand<i32>; + def s11_1Imm : Operand<i32>; + def s11_2Imm : Operand<i32>; + def s11_3Imm : Operand<i32>; + def s10Imm : Operand<i32>; + def s9Imm : Operand<i32>; + def m9Imm : Operand<i32>; + def s8Imm : Operand<i32>; + def s8Imm64 : Operand<i64>; + def s6Imm : Operand<i32>; + def s4Imm : Operand<i32>; + def s4_0Imm : Operand<i32>; + def s4_1Imm : Operand<i32>; + def s4_2Imm : Operand<i32>; + def s4_3Imm : Operand<i32>; + def u64Imm : Operand<i64>; + def u32Imm : Operand<i32>; + def u26_6Imm : Operand<i32>; + def u16Imm : Operand<i32>; + def u16_0Imm : Operand<i32>; + def u16_1Imm : Operand<i32>; + def u16_2Imm : Operand<i32>; + def u11_3Imm : Operand<i32>; + def u10Imm : Operand<i32>; + def u9Imm : Operand<i32>; + def u8Imm : Operand<i32>; + def u7Imm : Operand<i32>; + def u6Imm : Operand<i32>; + def u6_0Imm : Operand<i32>; + def u6_1Imm : Operand<i32>; + def u6_2Imm : Operand<i32>; + def u6_3Imm : Operand<i32>; + def u5Imm : Operand<i32>; + def u4Imm : Operand<i32>; + def u3Imm : Operand<i32>; + def u2Imm : Operand<i32>; + def u1Imm : Operand<i32>; + def n8Imm : Operand<i32>; + def m6Imm : Operand<i32>; +} + +let PrintMethod = "printNOneImmOperand" in +def nOneImm : Operand<i32>; + +// +// Immediate predicates +// +def s32ImmPred : PatLeaf<(i32 imm), [{ + // s32ImmPred predicate - True if the immediate fits in a 32-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<32>(v); +}]>; + +def s32_24ImmPred : PatLeaf<(i32 imm), [{ + // s32_24ImmPred predicate - True if the immediate fits in a 32-bit sign + // extended field that is a multiple of 0x1000000. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedInt<32,24>(v); +}]>; + +def s32_16s8ImmPred : PatLeaf<(i32 imm), [{ + // s32_16s8ImmPred predicate - True if the immediate fits in a 32-bit sign + // extended field that is a multiple of 0x10000. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedInt<24,16>(v); +}]>; + +def s26_6ImmPred : PatLeaf<(i32 imm), [{ + // s26_6ImmPred predicate - True if the immediate fits in a 32-bit + // sign extended field. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedInt<26,6>(v); +}]>; + + +def s16ImmPred : PatLeaf<(i32 imm), [{ + // s16ImmPred predicate - True if the immediate fits in a 16-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<16>(v); +}]>; + + +def s13ImmPred : PatLeaf<(i32 imm), [{ + // s13ImmPred predicate - True if the immediate fits in a 13-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<13>(v); +}]>; + + +def s12ImmPred : PatLeaf<(i32 imm), [{ + // s12ImmPred predicate - True if the immediate fits in a 12-bit + // sign extended field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<12>(v); +}]>; + +def s11_0ImmPred : PatLeaf<(i32 imm), [{ + // s11_0ImmPred predicate - True if the immediate fits in a 11-bit + // sign extended field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<11>(v); +}]>; + + +def s11_1ImmPred : PatLeaf<(i32 imm), [{ + // s11_1ImmPred predicate - True if the immediate fits in a 12-bit + // sign extended field and is a multiple of 2. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedInt<11,1>(v); +}]>; + + +def s11_2ImmPred : PatLeaf<(i32 imm), [{ + // s11_2ImmPred predicate - True if the immediate fits in a 13-bit + // sign extended field and is a multiple of 4. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedInt<11,2>(v); +}]>; + + +def s11_3ImmPred : PatLeaf<(i32 imm), [{ + // s11_3ImmPred predicate - True if the immediate fits in a 14-bit + // sign extended field and is a multiple of 8. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedInt<11,3>(v); +}]>; + + +def s10ImmPred : PatLeaf<(i32 imm), [{ + // s10ImmPred predicate - True if the immediate fits in a 10-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<10>(v); +}]>; + + +def s9ImmPred : PatLeaf<(i32 imm), [{ + // s9ImmPred predicate - True if the immediate fits in a 9-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<9>(v); +}]>; + +def m9ImmPred : PatLeaf<(i32 imm), [{ + // m9ImmPred predicate - True if the immediate fits in a 9-bit magnitude + // field. The range of m9 is -255 to 255. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<9>(v) && (v != -256); +}]>; + +def s8ImmPred : PatLeaf<(i32 imm), [{ + // s8ImmPred predicate - True if the immediate fits in a 8-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<8>(v); +}]>; + + +def s8Imm64Pred : PatLeaf<(i64 imm), [{ + // s8ImmPred predicate - True if the immediate fits in a 8-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<8>(v); +}]>; + + +def s6ImmPred : PatLeaf<(i32 imm), [{ + // s6ImmPred predicate - True if the immediate fits in a 6-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<6>(v); +}]>; + + +def s4_0ImmPred : PatLeaf<(i32 imm), [{ + // s4_0ImmPred predicate - True if the immediate fits in a 4-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<4>(v); +}]>; + + +def s4_1ImmPred : PatLeaf<(i32 imm), [{ + // s4_1ImmPred predicate - True if the immediate fits in a 4-bit sign extended + // field of 2. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedInt<4,1>(v); +}]>; + + +def s4_2ImmPred : PatLeaf<(i32 imm), [{ + // s4_2ImmPred predicate - True if the immediate fits in a 4-bit sign extended + // field that is a multiple of 4. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedInt<4,2>(v); +}]>; + + +def s4_3ImmPred : PatLeaf<(i32 imm), [{ + // s4_3ImmPred predicate - True if the immediate fits in a 4-bit sign extended + // field that is a multiple of 8. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedInt<4,3>(v); +}]>; + + +def u64ImmPred : PatLeaf<(i64 imm), [{ + // Adding "N ||" to suppress gcc unused warning. + return (N || true); +}]>; + +def u32ImmPred : PatLeaf<(i32 imm), [{ + // u32ImmPred predicate - True if the immediate fits in a 32-bit field. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<32>(v); +}]>; + +def u26_6ImmPred : PatLeaf<(i32 imm), [{ + // u26_6ImmPred - True if the immediate fits in a 32-bit field and + // is a multiple of 64. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedUInt<26,6>(v); +}]>; + +def u16ImmPred : PatLeaf<(i32 imm), [{ + // u16ImmPred predicate - True if the immediate fits in a 16-bit unsigned + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<16>(v); +}]>; + +def u16_s8ImmPred : PatLeaf<(i32 imm), [{ + // u16_s8ImmPred predicate - True if the immediate fits in a 16-bit sign + // extended s8 field. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedUInt<16,8>(v); +}]>; + +def u9ImmPred : PatLeaf<(i32 imm), [{ + // u9ImmPred predicate - True if the immediate fits in a 9-bit unsigned + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<9>(v); +}]>; + + +def u8ImmPred : PatLeaf<(i32 imm), [{ + // u8ImmPred predicate - True if the immediate fits in a 8-bit unsigned + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<8>(v); +}]>; + +def u7StrictPosImmPred : ImmLeaf<i32, [{ + // u7StrictPosImmPred predicate - True if the immediate fits in an 7-bit + // unsigned field and is strictly greater than 0. + return isUInt<7>(Imm) && Imm > 0; +}]>; + +def u7ImmPred : PatLeaf<(i32 imm), [{ + // u7ImmPred predicate - True if the immediate fits in a 7-bit unsigned + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<7>(v); +}]>; + + +def u6ImmPred : PatLeaf<(i32 imm), [{ + // u6ImmPred predicate - True if the immediate fits in a 6-bit unsigned + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<6>(v); +}]>; + +def u6_0ImmPred : PatLeaf<(i32 imm), [{ + // u6_0ImmPred predicate - True if the immediate fits in a 6-bit unsigned + // field. Same as u6ImmPred. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<6>(v); +}]>; + +def u6_1ImmPred : PatLeaf<(i32 imm), [{ + // u6_1ImmPred predicate - True if the immediate fits in a 7-bit unsigned + // field that is 1 bit alinged - multiple of 2. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedUInt<6,1>(v); +}]>; + +def u6_2ImmPred : PatLeaf<(i32 imm), [{ + // u6_2ImmPred predicate - True if the immediate fits in a 8-bit unsigned + // field that is 2 bits alinged - multiple of 4. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedUInt<6,2>(v); +}]>; + +def u6_3ImmPred : PatLeaf<(i32 imm), [{ + // u6_3ImmPred predicate - True if the immediate fits in a 9-bit unsigned + // field that is 3 bits alinged - multiple of 8. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedUInt<6,3>(v); +}]>; + +def u5ImmPred : PatLeaf<(i32 imm), [{ + // u5ImmPred predicate - True if the immediate fits in a 5-bit unsigned + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<5>(v); +}]>; + + +def u3ImmPred : PatLeaf<(i32 imm), [{ + // u3ImmPred predicate - True if the immediate fits in a 3-bit unsigned + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<3>(v); +}]>; + + +def u2ImmPred : PatLeaf<(i32 imm), [{ + // u2ImmPred predicate - True if the immediate fits in a 2-bit unsigned + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<2>(v); +}]>; + + +def u1ImmPred : PatLeaf<(i1 imm), [{ + // u1ImmPred predicate - True if the immediate fits in a 1-bit unsigned + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<1>(v); +}]>; + +def m5BImmPred : PatLeaf<(i32 imm), [{ + // m5BImmPred predicate - True if the (char) number is in range -1 .. -31 + // and will fit in a 5 bit field when made positive, for use in memops. + // this is specific to the zero extending of a negative by CombineInstr + int8_t v = (int8_t)N->getSExtValue(); + return (-31 <= v && v <= -1); +}]>; + +def m5HImmPred : PatLeaf<(i32 imm), [{ + // m5HImmPred predicate - True if the (short) number is in range -1 .. -31 + // and will fit in a 5 bit field when made positive, for use in memops. + // this is specific to the zero extending of a negative by CombineInstr + int16_t v = (int16_t)N->getSExtValue(); + return (-31 <= v && v <= -1); +}]>; + +def m5ImmPred : PatLeaf<(i32 imm), [{ + // m5ImmPred predicate - True if the number is in range -1 .. -31 + // and will fit in a 5 bit field when made positive, for use in memops. + int64_t v = (int64_t)N->getSExtValue(); + return (-31 <= v && v <= -1); +}]>; + +//InN means negative integers in [-(2^N - 1), 0] +def n8ImmPred : PatLeaf<(i32 imm), [{ + // n8ImmPred predicate - True if the immediate fits in a 8-bit signed + // field. + int64_t v = (int64_t)N->getSExtValue(); + return (-255 <= v && v <= 0); +}]>; + +def nOneImmPred : PatLeaf<(i32 imm), [{ + // nOneImmPred predicate - True if the immediate is -1. + int64_t v = (int64_t)N->getSExtValue(); + return (-1 == v); +}]>; + +def Set5ImmPred : PatLeaf<(i32 imm), [{ + // Set5ImmPred predicate - True if the number is in the series of values. + // [ 2^0, 2^1, ... 2^31 ] + // For use in setbit immediate. + uint32_t v = (int32_t)N->getSExtValue(); + // Constrain to 32 bits, and then check for single bit. + return ImmIsSingleBit(v); +}]>; + +def Clr5ImmPred : PatLeaf<(i32 imm), [{ + // Clr5ImmPred predicate - True if the number is in the series of + // bit negated values. + // [ 2^0, 2^1, ... 2^31 ] + // For use in clrbit immediate. + // Note: we are bit NOTing the value. + uint32_t v = ~ (int32_t)N->getSExtValue(); + // Constrain to 32 bits, and then check for single bit. + return ImmIsSingleBit(v); +}]>; + +def SetClr5ImmPred : PatLeaf<(i32 imm), [{ + // SetClr5ImmPred predicate - True if the immediate is in range 0..31. + int32_t v = (int32_t)N->getSExtValue(); + return (v >= 0 && v <= 31); +}]>; + +def Set4ImmPred : PatLeaf<(i32 imm), [{ + // Set4ImmPred predicate - True if the number is in the series of values: + // [ 2^0, 2^1, ... 2^15 ]. + // For use in setbit immediate. + uint16_t v = (int16_t)N->getSExtValue(); + // Constrain to 16 bits, and then check for single bit. + return ImmIsSingleBit(v); +}]>; + +def Clr4ImmPred : PatLeaf<(i32 imm), [{ + // Clr4ImmPred predicate - True if the number is in the series of + // bit negated values: + // [ 2^0, 2^1, ... 2^15 ]. + // For use in setbit and clrbit immediate. + uint16_t v = ~ (int16_t)N->getSExtValue(); + // Constrain to 16 bits, and then check for single bit. + return ImmIsSingleBit(v); +}]>; + +def SetClr4ImmPred : PatLeaf<(i32 imm), [{ + // SetClr4ImmPred predicate - True if the immediate is in the range 0..15. + int16_t v = (int16_t)N->getSExtValue(); + return (v >= 0 && v <= 15); +}]>; + +def Set3ImmPred : PatLeaf<(i32 imm), [{ + // Set3ImmPred predicate - True if the number is in the series of values: + // [ 2^0, 2^1, ... 2^7 ]. + // For use in setbit immediate. + uint8_t v = (int8_t)N->getSExtValue(); + // Constrain to 8 bits, and then check for single bit. + return ImmIsSingleBit(v); +}]>; + +def Clr3ImmPred : PatLeaf<(i32 imm), [{ + // Clr3ImmPred predicate - True if the number is in the series of + // bit negated values: + // [ 2^0, 2^1, ... 2^7 ]. + // For use in setbit and clrbit immediate. + uint8_t v = ~ (int8_t)N->getSExtValue(); + // Constrain to 8 bits, and then check for single bit. + return ImmIsSingleBit(v); +}]>; + +def SetClr3ImmPred : PatLeaf<(i32 imm), [{ + // SetClr3ImmPred predicate - True if the immediate is in the range 0..7. + int8_t v = (int8_t)N->getSExtValue(); + return (v >= 0 && v <= 7); +}]>; + + +// Extendable immediate operands. + +let PrintMethod = "printExtOperand" in { + def s16Ext : Operand<i32>; + def s12Ext : Operand<i32>; + def s10Ext : Operand<i32>; + def s9Ext : Operand<i32>; + def s8Ext : Operand<i32>; + def s6Ext : Operand<i32>; + def s11_0Ext : Operand<i32>; + def s11_1Ext : Operand<i32>; + def s11_2Ext : Operand<i32>; + def s11_3Ext : Operand<i32>; + def u6Ext : Operand<i32>; + def u7Ext : Operand<i32>; + def u8Ext : Operand<i32>; + def u9Ext : Operand<i32>; + def u10Ext : Operand<i32>; + def u6_0Ext : Operand<i32>; + def u6_1Ext : Operand<i32>; + def u6_2Ext : Operand<i32>; + def u6_3Ext : Operand<i32>; +} + +let PrintMethod = "printImmOperand" in +def u0AlwaysExt : Operand<i32>; + +// Predicates for constant extendable operands +def s16ExtPred : PatLeaf<(i32 imm), [{ + int64_t v = (int64_t)N->getSExtValue(); + if (!Subtarget.hasV4TOps()) + // Return true if the immediate can fit in a 16-bit sign extended field. + return isInt<16>(v); + else { + if (isInt<16>(v)) + return true; + + // Return true if extending this immediate is profitable and the value + // can fit in a 32-bit signed field. + return isConstExtProfitable(Node) && isInt<32>(v); + } +}]>; + +def s10ExtPred : PatLeaf<(i32 imm), [{ + int64_t v = (int64_t)N->getSExtValue(); + if (!Subtarget.hasV4TOps()) + // Return true if the immediate can fit in a 10-bit sign extended field. + return isInt<10>(v); + else { + if (isInt<10>(v)) + return true; + + // Return true if extending this immediate is profitable and the value + // can fit in a 32-bit signed field. + return isConstExtProfitable(Node) && isInt<32>(v); + } +}]>; + +def s9ExtPred : PatLeaf<(i32 imm), [{ + int64_t v = (int64_t)N->getSExtValue(); + if (!Subtarget.hasV4TOps()) + // Return true if the immediate can fit in a 9-bit sign extended field. + return isInt<9>(v); + else { + if (isInt<9>(v)) + return true; + + // Return true if extending this immediate is profitable and the value + // can fit in a 32-bit unsigned field. + return isConstExtProfitable(Node) && isInt<32>(v); + } +}]>; + +def s8ExtPred : PatLeaf<(i32 imm), [{ + int64_t v = (int64_t)N->getSExtValue(); + if (!Subtarget.hasV4TOps()) + // Return true if the immediate can fit in a 8-bit sign extended field. + return isInt<8>(v); + else { + if (isInt<8>(v)) + return true; + + // Return true if extending this immediate is profitable and the value + // can fit in a 32-bit signed field. + return isConstExtProfitable(Node) && isInt<32>(v); + } +}]>; + +def s8_16ExtPred : PatLeaf<(i32 imm), [{ + int64_t v = (int64_t)N->getSExtValue(); + if (!Subtarget.hasV4TOps()) + // Return true if the immediate fits in a 8-bit sign extended field. + return isInt<8>(v); + else { + if (isInt<8>(v)) + return true; + + // Return true if extending this immediate is profitable and the value + // can't fit in a 16-bit signed field. This is required to avoid + // unnecessary constant extenders. + return isConstExtProfitable(Node) && !isInt<16>(v); + } +}]>; + +def s6ExtPred : PatLeaf<(i32 imm), [{ + int64_t v = (int64_t)N->getSExtValue(); + if (!Subtarget.hasV4TOps()) + // Return true if the immediate can fit in a 6-bit sign extended field. + return isInt<6>(v); + else { + if (isInt<6>(v)) + return true; + + // Return true if extending this immediate is profitable and the value + // can fit in a 32-bit unsigned field. + return isConstExtProfitable(Node) && isInt<32>(v); + } +}]>; + +def s6_16ExtPred : PatLeaf<(i32 imm), [{ + int64_t v = (int64_t)N->getSExtValue(); + if (!Subtarget.hasV4TOps()) + // Return true if the immediate fits in a 6-bit sign extended field. + return isInt<6>(v); + else { + if (isInt<6>(v)) + return true; + + // Return true if extending this immediate is profitable and the value + // can't fit in a 16-bit signed field. This is required to avoid + // unnecessary constant extenders. + return isConstExtProfitable(Node) && !isInt<16>(v); + } +}]>; + +def s6_10ExtPred : PatLeaf<(i32 imm), [{ + int64_t v = (int64_t)N->getSExtValue(); + if (!Subtarget.hasV4TOps()) + // Return true if the immediate can fit in a 6-bit sign extended field. + return isInt<6>(v); + else { + if (isInt<6>(v)) + return true; + + // Return true if extending this immediate is profitable and the value + // can't fit in a 10-bit signed field. This is required to avoid + // unnecessary constant extenders. + return isConstExtProfitable(Node) && !isInt<10>(v); + } +}]>; + +def s11_0ExtPred : PatLeaf<(i32 imm), [{ + int64_t v = (int64_t)N->getSExtValue(); + if (!Subtarget.hasV4TOps()) + // Return true if the immediate can fit in a 11-bit sign extended field. + return isShiftedInt<11,0>(v); + else { + if (isInt<11>(v)) + return true; + + // Return true if extending this immediate is profitable and the value + // can fit in a 32-bit signed field. + return isConstExtProfitable(Node) && isInt<32>(v); + } +}]>; + +def s11_1ExtPred : PatLeaf<(i32 imm), [{ + int64_t v = (int64_t)N->getSExtValue(); + if (!Subtarget.hasV4TOps()) + // Return true if the immediate can fit in a 12-bit sign extended field and + // is 2 byte aligned. + return isShiftedInt<11,1>(v); + else { + if (isInt<12>(v)) + return isShiftedInt<11,1>(v); + + // Return true if extending this immediate is profitable and the low 1 bit + // is zero (2-byte aligned). + return isConstExtProfitable(Node) && isInt<32>(v) && ((v % 2) == 0); + } +}]>; + +def s11_2ExtPred : PatLeaf<(i32 imm), [{ + int64_t v = (int64_t)N->getSExtValue(); + if (!Subtarget.hasV4TOps()) + // Return true if the immediate can fit in a 13-bit sign extended field and + // is 4-byte aligned. + return isShiftedInt<11,2>(v); + else { + if (isInt<13>(v)) + return isShiftedInt<11,2>(v); + + // Return true if extending this immediate is profitable and the low 2-bits + // are zero (4-byte aligned). + return isConstExtProfitable(Node) && isInt<32>(v) && ((v % 4) == 0); + } +}]>; + +def s11_3ExtPred : PatLeaf<(i32 imm), [{ + int64_t v = (int64_t)N->getSExtValue(); + if (!Subtarget.hasV4TOps()) + // Return true if the immediate can fit in a 14-bit sign extended field and + // is 8-byte aligned. + return isShiftedInt<11,3>(v); + else { + if (isInt<14>(v)) + return isShiftedInt<11,3>(v); + + // Return true if extending this immediate is profitable and the low 3-bits + // are zero (8-byte aligned). + return isConstExtProfitable(Node) && isInt<32>(v) && ((v % 8) == 0); + } +}]>; + +def u0AlwaysExtPred : PatLeaf<(i32 imm), [{ + // Predicate for an unsigned 32-bit value that always needs to be extended. + if (Subtarget.hasV4TOps()) { + if (isConstExtProfitable(Node)) { + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<32>(v); + } + } + return false; +}]>; + +def u6ExtPred : PatLeaf<(i32 imm), [{ + int64_t v = (int64_t)N->getSExtValue(); + if (!Subtarget.hasV4TOps()) + // Return true if the immediate can fit in a 6-bit unsigned field. + return isUInt<6>(v); + else { + if (isUInt<6>(v)) + return true; + + // Return true if extending this immediate is profitable and the value + // can fit in a 32-bit unsigned field. + return isConstExtProfitable(Node) && isUInt<32>(v); + } +}]>; + +def u7ExtPred : PatLeaf<(i32 imm), [{ + int64_t v = (int64_t)N->getSExtValue(); + if (!Subtarget.hasV4TOps()) + // Return true if the immediate can fit in a 7-bit unsigned field. + return isUInt<7>(v); + else { + if (isUInt<7>(v)) + return true; + + // Return true if extending this immediate is profitable and the value + // can fit in a 32-bit unsigned field. + return isConstExtProfitable(Node) && isUInt<32>(v); + } +}]>; + +def u8ExtPred : PatLeaf<(i32 imm), [{ + int64_t v = (int64_t)N->getSExtValue(); + if (!Subtarget.hasV4TOps()) + // Return true if the immediate can fit in a 8-bit unsigned field. + return isUInt<8>(v); + else { + if (isUInt<8>(v)) + return true; + + // Return true if extending this immediate is profitable and the value + // can fit in a 32-bit unsigned field. + return isConstExtProfitable(Node) && isUInt<32>(v); + } +}]>; + +def u9ExtPred : PatLeaf<(i32 imm), [{ + int64_t v = (int64_t)N->getSExtValue(); + if (!Subtarget.hasV4TOps()) + // Return true if the immediate can fit in a 9-bit unsigned field. + return isUInt<9>(v); + else { + if (isUInt<9>(v)) + return true; + + // Return true if extending this immediate is profitable and the value + // can fit in a 32-bit unsigned field. + return isConstExtProfitable(Node) && isUInt<32>(v); + } +}]>; + +def u6_1ExtPred : PatLeaf<(i32 imm), [{ + int64_t v = (int64_t)N->getSExtValue(); + if (!Subtarget.hasV4TOps()) + // Return true if the immediate can fit in a 7-bit unsigned field and + // is 2-byte aligned. + return isShiftedUInt<6,1>(v); + else { + if (isUInt<7>(v)) + return isShiftedUInt<6,1>(v); + + // Return true if extending this immediate is profitable and the value + // can fit in a 32-bit unsigned field. + return isConstExtProfitable(Node) && isUInt<32>(v) && ((v % 2) == 0); + } +}]>; + +def u6_2ExtPred : PatLeaf<(i32 imm), [{ + int64_t v = (int64_t)N->getSExtValue(); + if (!Subtarget.hasV4TOps()) + // Return true if the immediate can fit in a 8-bit unsigned field and + // is 4-byte aligned. + return isShiftedUInt<6,2>(v); + else { + if (isUInt<8>(v)) + return isShiftedUInt<6,2>(v); + + // Return true if extending this immediate is profitable and the value + // can fit in a 32-bit unsigned field. + return isConstExtProfitable(Node) && isUInt<32>(v) && ((v % 4) == 0); + } +}]>; + +def u6_3ExtPred : PatLeaf<(i32 imm), [{ + int64_t v = (int64_t)N->getSExtValue(); + if (!Subtarget.hasV4TOps()) + // Return true if the immediate can fit in a 9-bit unsigned field and + // is 8-byte aligned. + return isShiftedUInt<6,3>(v); + else { + if (isUInt<9>(v)) + return isShiftedUInt<6,3>(v); + + // Return true if extending this immediate is profitable and the value + // can fit in a 32-bit unsigned field. + return isConstExtProfitable(Node) && isUInt<32>(v) && ((v % 8) == 0); + } +}]>; + +// Addressing modes. + +def ADDRrr : ComplexPattern<i32, 2, "SelectADDRrr", [], []>; +def ADDRri : ComplexPattern<i32, 2, "SelectADDRri", [frameindex], []>; +def ADDRriS11_0 : ComplexPattern<i32, 2, "SelectADDRriS11_0", [frameindex], []>; +def ADDRriS11_1 : ComplexPattern<i32, 2, "SelectADDRriS11_1", [frameindex], []>; +def ADDRriS11_2 : ComplexPattern<i32, 2, "SelectADDRriS11_2", [frameindex], []>; +def ADDRriS11_3 : ComplexPattern<i32, 2, "SelectADDRriS11_3", [frameindex], []>; +def ADDRriU6_0 : ComplexPattern<i32, 2, "SelectADDRriU6_0", [frameindex], []>; +def ADDRriU6_1 : ComplexPattern<i32, 2, "SelectADDRriU6_1", [frameindex], []>; +def ADDRriU6_2 : ComplexPattern<i32, 2, "SelectADDRriU6_2", [frameindex], []>; + +// Address operands. + +def MEMrr : Operand<i32> { + let PrintMethod = "printMEMrrOperand"; + let MIOperandInfo = (ops IntRegs, IntRegs); +} + +def MEMri : Operand<i32> { + let PrintMethod = "printMEMriOperand"; + let MIOperandInfo = (ops IntRegs, IntRegs); +} + +def MEMri_s11_2 : Operand<i32>, + ComplexPattern<i32, 2, "SelectMEMriS11_2", []> { + let PrintMethod = "printMEMriOperand"; + let MIOperandInfo = (ops IntRegs, s11Imm); +} + +def FrameIndex : Operand<i32> { + let PrintMethod = "printFrameIndexOperand"; + let MIOperandInfo = (ops IntRegs, s11Imm); +} + +let PrintMethod = "printGlobalOperand" in { + def globaladdress : Operand<i32>; + def globaladdressExt : Operand<i32>; +} + +let PrintMethod = "printJumpTable" in +def jumptablebase : Operand<i32>; + +def brtarget : Operand<OtherVT>; +def brtargetExt : Operand<OtherVT>; +def calltarget : Operand<i32>; + +def bblabel : Operand<i32>; +def bbl : SDNode<"ISD::BasicBlock", SDTPtrLeaf , [], "BasicBlockSDNode">; + +def symbolHi32 : Operand<i32> { + let PrintMethod = "printSymbolHi"; +} +def symbolLo32 : Operand<i32> { + let PrintMethod = "printSymbolLo"; +} diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonPeephole.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonPeephole.cpp index a295015..576f1d7 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonPeephole.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonPeephole.cpp @@ -38,21 +38,21 @@ #define DEBUG_TYPE "hexagon-peephole" #include "Hexagon.h" #include "HexagonTargetMachine.h" -#include "llvm/Constants.h" -#include "llvm/PassSupport.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Statistic.h" -#include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/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 "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Target/TargetInstrInfo.h" #include <algorithm> using namespace llvm; diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp index 3742486..d8b4e2f 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp @@ -17,8 +17,6 @@ #include "HexagonSubtarget.h" #include "HexagonTargetMachine.h" #include "HexagonMachineFunctionInfo.h" -#include "llvm/Function.h" -#include "llvm/Type.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -26,7 +24,10 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Type.h" #include "llvm/MC/MachineLocation.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" @@ -117,37 +118,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 +146,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 +185,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 +213,44 @@ 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); - } 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); + // use the constant extender if the instruction provides it + // and we are V4TOps. + if (Subtarget.hasV4TOps()) { + if (TII.isConstExtended(&MI)) { + MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false); + MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset); + TII.immediateExtend(&MI); + } else { + llvm_unreachable("Need to implement for memops"); + } } 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); + // Only V3 and older instructions here. + unsigned ResReg = HEXAGON_RESERVED_REG_1; + if (!MFI.hasVarSizedObjects() && + TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset))) { + MI.getOperand(FIOperandNum).ChangeToRegister(getStackRegister(), + false, false, false); + 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(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(FIOperandNum).ChangeToRegister(ResReg, false, false, + true); + MI.getOperand(FIOperandNum+1).ChangeToImmediate(0); + } } } else { unsigned dstReg = MI.getOperand(0).getReg(); @@ -265,14 +260,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 +305,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/contrib/llvm/lib/Target/Hexagon/HexagonRegisterInfo.h b/contrib/llvm/lib/Target/Hexagon/HexagonRegisterInfo.h index 8820d13..8a3f94a 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonRegisterInfo.h +++ b/contrib/llvm/lib/Target/Hexagon/HexagonRegisterInfo.h @@ -15,8 +15,8 @@ #ifndef HexagonREGISTERINFO_H #define HexagonREGISTERINFO_H -#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/MC/MachineLocation.h" +#include "llvm/Target/TargetRegisterInfo.h" #define GET_REGINFO_HEADER #include "HexagonGenRegisterInfo.inc" @@ -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/contrib/llvm/lib/Target/Hexagon/HexagonRemoveSZExtArgs.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonRemoveSZExtArgs.cpp index 4d93dd1..34bf4ea 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonRemoveSZExtArgs.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonRemoveSZExtArgs.cpp @@ -12,11 +12,12 @@ // //===----------------------------------------------------------------------===// +#include "Hexagon.h" #include "HexagonTargetMachine.h" -#include "llvm/Function.h" -#include "llvm/Instructions.h" -#include "llvm/Pass.h" #include "llvm/CodeGen/MachineFunctionAnalysis.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Pass.h" #include "llvm/Transforms/Scalar.h" using namespace llvm; @@ -50,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/contrib/llvm/lib/Target/Hexagon/HexagonSchedule.td b/contrib/llvm/lib/Target/Hexagon/HexagonSchedule.td index b5ff69a..c2cfbb9 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonSchedule.td +++ b/contrib/llvm/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/contrib/llvm/lib/Target/Hexagon/HexagonScheduleV4.td b/contrib/llvm/lib/Target/Hexagon/HexagonScheduleV4.td index 5668ae8..ef72cf40 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonScheduleV4.td +++ b/contrib/llvm/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/contrib/llvm/lib/Target/Hexagon/HexagonSplitTFRCondSets.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonSplitTFRCondSets.cpp index a81cd91..814249f 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonSplitTFRCondSets.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonSplitTFRCondSets.cpp @@ -27,24 +27,25 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "xfer" -#include "HexagonTargetMachine.h" -#include "HexagonSubtarget.h" +#include "Hexagon.h" #include "HexagonMachineFunctionInfo.h" -#include "llvm/CodeGen/Passes.h" +#include "HexagonSubtarget.h" +#include "HexagonTargetMachine.h" #include "llvm/CodeGen/LatencyPriorityQueue.h" #include "llvm/CodeGen/MachineDominators.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/ScheduleHazardRecognizer.h" #include "llvm/CodeGen/SchedulerRegistry.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Support/Compiler.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" using namespace llvm; diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonSubtarget.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonSubtarget.cpp index 4bacb8f..07d5ce1 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonSubtarget.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonSubtarget.cpp @@ -29,8 +29,16 @@ EnableV3("enable-hexagon-v3", cl::Hidden, static cl::opt<bool> EnableMemOps( "enable-hexagon-memops", - cl::Hidden, cl::ZeroOrMore, cl::ValueDisallowed, - cl::desc("Generate V4 memop instructions.")); + cl::Hidden, cl::ZeroOrMore, cl::ValueDisallowed, cl::init(true), + cl::desc( + "Generate V4 MEMOP in code generation for Hexagon target")); + +static cl::opt<bool> +DisableMemOps( + "disable-hexagon-memops", + cl::Hidden, cl::ZeroOrMore, cl::ValueDisallowed, cl::init(false), + cl::desc( + "Do not generate V4 MEMOP in code generation for Hexagon target")); static cl::opt<bool> EnableIEEERndNear( @@ -64,7 +72,10 @@ HexagonSubtarget::HexagonSubtarget(StringRef TT, StringRef CPU, StringRef FS): // Initialize scheduling itinerary for the specified CPU. InstrItins = getInstrItineraryForCPU(CPUString); - if (EnableMemOps) + // UseMemOps on by default unless disabled explicitly + if (DisableMemOps) + UseMemOps = false; + else if (EnableMemOps) UseMemOps = true; else UseMemOps = false; diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonSubtarget.h b/contrib/llvm/lib/Target/Hexagon/HexagonSubtarget.h index 5d9d6d8..76a8fba 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonSubtarget.h +++ b/contrib/llvm/lib/Target/Hexagon/HexagonSubtarget.h @@ -14,8 +14,8 @@ #ifndef Hexagon_SUBTARGET_H #define Hexagon_SUBTARGET_H -#include "llvm/Target/TargetSubtargetInfo.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetSubtargetInfo.h" #include <string> #define GET_SUBTARGETINFO_HEADER diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp index 30866e9..ce45c62 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp @@ -15,13 +15,13 @@ #include "Hexagon.h" #include "HexagonISelLowering.h" #include "HexagonMachineScheduler.h" -#include "llvm/Module.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Module.h" #include "llvm/PassManager.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" -#include "llvm/Transforms/Scalar.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/TargetRegistry.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/Transforms/Scalar.h" using namespace llvm; @@ -35,6 +35,10 @@ opt<bool> DisableHexagonMISched("disable-hexagon-misched", cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::desc("Disable Hexagon MI Scheduling")); +static cl::opt<bool> DisableHexagonCFGOpt("disable-hexagon-cfgopt", + cl::Hidden, cl::ZeroOrMore, cl::init(false), + cl::desc("Disable Hexagon CFG Optimization")); + /// HexagonTargetMachineModule - Note that this is used on hosts that /// cannot link in a library unless there are references into the /// library. In particular, it seems that it is not possible to get @@ -74,21 +78,21 @@ 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) { - setMCUseCFI(false); + InstrItins(&Subtarget.getInstrItineraryData()) { + setMCUseCFI(false); } // addPassesForOptimizations - Allow the backend (target) to add Target // Independent Optimization passes to the Pass Manager. bool HexagonTargetMachine::addPassesForOptimizations(PassManagerBase &PM) { - - PM.add(createConstantPropagationPass()); - PM.add(createLoopSimplifyPass()); - PM.add(createDeadCodeEliminationPass()); - PM.add(createConstantPropagationPass()); - PM.add(createLoopUnrollPass()); - PM.add(createLoopStrengthReducePass()); + if (getOptLevel() != CodeGenOpt::None) { + PM.add(createConstantPropagationPass()); + PM.add(createLoopSimplifyPass()); + PM.add(createDeadCodeEliminationPass()); + PM.add(createConstantPropagationPass()); + PM.add(createLoopUnrollPass()); + PM.add(createLoopStrengthReducePass()); + } return true; } @@ -122,38 +126,45 @@ TargetPassConfig *HexagonTargetMachine::createPassConfig(PassManagerBase &PM) { } bool HexagonPassConfig::addInstSelector() { - addPass(createHexagonRemoveExtendOps(getHexagonTargetMachine())); - addPass(createHexagonISelDag(getHexagonTargetMachine())); - addPass(createHexagonPeephole()); + + if (getOptLevel() != CodeGenOpt::None) + addPass(createHexagonRemoveExtendOps(getHexagonTargetMachine())); + + addPass(createHexagonISelDag(getHexagonTargetMachine(), getOptLevel())); + + if (getOptLevel() != CodeGenOpt::None) + addPass(createHexagonPeephole()); + return false; } bool HexagonPassConfig::addPreRegAlloc() { - if (!DisableHardwareLoops) { + if (!DisableHardwareLoops && getOptLevel() != CodeGenOpt::None) addPass(createHexagonHardwareLoops()); - } return false; } bool HexagonPassConfig::addPostRegAlloc() { - addPass(createHexagonCFGOptimizer(getHexagonTargetMachine())); + if (!DisableHexagonCFGOpt && getOptLevel() != CodeGenOpt::None) + addPass(createHexagonCFGOptimizer(getHexagonTargetMachine())); return true; } bool HexagonPassConfig::addPreSched2() { - addPass(&IfConverterID); + if (getOptLevel() != CodeGenOpt::None) + addPass(&IfConverterID); return true; } bool HexagonPassConfig::addPreEmitPass() { - if (!DisableHardwareLoops) { + if (!DisableHardwareLoops && getOptLevel() != CodeGenOpt::None) addPass(createHexagonFixupHwLoops()); - } - addPass(createHexagonNewValueJump()); + if (getOptLevel() != CodeGenOpt::None) + addPass(createHexagonNewValueJump()); // Expand Spill code for predicate registers. addPass(createHexagonExpandPredSpillCode(getHexagonTargetMachine())); @@ -162,7 +173,8 @@ bool HexagonPassConfig::addPreEmitPass() { addPass(createHexagonSplitTFRCondSets(getHexagonTargetMachine())); // Create Packets. - addPass(createHexagonPacketizer()); + if (getOptLevel() != CodeGenOpt::None) + addPass(createHexagonPacketizer()); return false; } diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonTargetMachine.h b/contrib/llvm/lib/Target/Hexagon/HexagonTargetMachine.h index 7a4215c..cf8f9aa 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonTargetMachine.h +++ b/contrib/llvm/lib/Target/Hexagon/HexagonTargetMachine.h @@ -14,14 +14,13 @@ #ifndef HexagonTARGETMACHINE_H #define HexagonTARGETMACHINE_H -#include "HexagonInstrInfo.h" -#include "HexagonSubtarget.h" +#include "HexagonFrameLowering.h" #include "HexagonISelLowering.h" +#include "HexagonInstrInfo.h" #include "HexagonSelectionDAGInfo.h" -#include "HexagonFrameLowering.h" +#include "HexagonSubtarget.h" +#include "llvm/IR/DataLayout.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/DataLayout.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/contrib/llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp index f4d7761..993fcfa 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp @@ -14,13 +14,13 @@ #include "HexagonTargetObjectFile.h" #include "HexagonSubtarget.h" #include "HexagonTargetMachine.h" -#include "llvm/Function.h" -#include "llvm/GlobalVariable.h" -#include "llvm/DataLayout.h" -#include "llvm/DerivedTypes.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/ELF.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/ELF.h" using namespace llvm; diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp index 3d5f685..c0d86da 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp @@ -149,7 +149,6 @@ namespace { bool canReserveResourcesForConstExt(MachineInstr *MI); void reserveResourcesForConstExt(MachineInstr* MI); bool isNewValueInst(MachineInstr* MI); - bool isDotNewInst(MachineInstr* MI); }; } @@ -242,8 +241,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); @@ -257,10 +257,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); @@ -271,8 +271,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); @@ -349,17 +350,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 @@ -375,7 +365,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: @@ -398,17 +387,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: @@ -431,17 +415,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: @@ -464,10 +443,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; @@ -507,9 +482,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; @@ -576,18 +548,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; @@ -601,9 +561,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; @@ -670,18 +627,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; @@ -695,9 +640,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; @@ -764,17 +706,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; } } @@ -820,12 +751,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; @@ -857,12 +782,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; @@ -900,12 +819,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; @@ -943,12 +856,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; @@ -1091,72 +998,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; @@ -1201,42 +1072,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; @@ -1264,12 +1099,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; @@ -1297,12 +1126,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; @@ -1330,12 +1153,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; @@ -1622,72 +1439,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; @@ -1732,42 +1513,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 : @@ -1901,16 +1646,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; @@ -1924,9 +1659,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; @@ -1990,16 +1722,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: @@ -2014,9 +1736,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; @@ -2081,16 +1800,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: @@ -2105,9 +1814,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; @@ -2146,11 +1852,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; } } @@ -2248,28 +1949,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 : @@ -2298,42 +1987,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 : @@ -2419,28 +2088,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 : @@ -2470,42 +2127,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,203 +2153,6 @@ static bool GetPredicateSense(MachineInstr* MI, return false; } -bool HexagonPacketizerList::isDotNewInst(MachineInstr* MI) { - if (isNewValueInst(MI)) - return true; - - switch (MI->getOpcode()) { - case Hexagon::TFR_cdnNotPt: - case Hexagon::TFR_cdnPt: - case Hexagon::TFRI_cdnNotPt: - case Hexagon::TFRI_cdnPt: - case Hexagon::LDrid_cdnPt : - case Hexagon::LDrid_cdnNotPt : - case Hexagon::LDrid_indexed_cdnPt : - case Hexagon::LDrid_indexed_cdnNotPt : - case Hexagon::POST_LDrid_cdnPt_V4 : - case Hexagon::POST_LDrid_cdnNotPt_V4 : - case Hexagon::LDriw_cdnPt : - case Hexagon::LDriw_cdnNotPt : - case Hexagon::LDriw_indexed_cdnPt : - case Hexagon::LDriw_indexed_cdnNotPt : - case Hexagon::POST_LDriw_cdnPt_V4 : - case Hexagon::POST_LDriw_cdnNotPt_V4 : - case Hexagon::LDrih_cdnPt : - case Hexagon::LDrih_cdnNotPt : - case Hexagon::LDrih_indexed_cdnPt : - case Hexagon::LDrih_indexed_cdnNotPt : - case Hexagon::POST_LDrih_cdnPt_V4 : - case Hexagon::POST_LDrih_cdnNotPt_V4 : - case Hexagon::LDrib_cdnPt : - case Hexagon::LDrib_cdnNotPt : - case Hexagon::LDrib_indexed_cdnPt : - case Hexagon::LDrib_indexed_cdnNotPt : - case Hexagon::POST_LDrib_cdnPt_V4 : - case Hexagon::POST_LDrib_cdnNotPt_V4 : - case Hexagon::LDriuh_cdnPt : - case Hexagon::LDriuh_cdnNotPt : - case Hexagon::LDriuh_indexed_cdnPt : - case Hexagon::LDriuh_indexed_cdnNotPt : - case Hexagon::POST_LDriuh_cdnPt_V4 : - case Hexagon::POST_LDriuh_cdnNotPt_V4 : - case Hexagon::LDriub_cdnPt : - case Hexagon::LDriub_cdnNotPt : - case Hexagon::LDriub_indexed_cdnPt : - case Hexagon::LDriub_indexed_cdnNotPt : - 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 : - -// Coditional add - case Hexagon::ADD_ri_cdnPt: - case Hexagon::ADD_ri_cdnNotPt: - case Hexagon::ADD_rr_cdnPt: - case Hexagon::ADD_rr_cdnNotPt: - - // Conditional logical operations - case Hexagon::XOR_rr_cdnPt : - case Hexagon::XOR_rr_cdnNotPt : - case Hexagon::AND_rr_cdnPt : - case Hexagon::AND_rr_cdnNotPt : - case Hexagon::OR_rr_cdnPt : - case Hexagon::OR_rr_cdnNotPt : - - // Conditonal subtract - case Hexagon::SUB_rr_cdnPt : - case Hexagon::SUB_rr_cdnNotPt : - - // Conditional combine - case Hexagon::COMBINE_rr_cdnPt : - case Hexagon::COMBINE_rr_cdnNotPt : - - // Conditional shift operations - case Hexagon::ASLH_cdnPt_V4: - case Hexagon::ASLH_cdnNotPt_V4: - case Hexagon::ASRH_cdnPt_V4: - case Hexagon::ASRH_cdnNotPt_V4: - case Hexagon::SXTB_cdnPt_V4: - case Hexagon::SXTB_cdnNotPt_V4: - case Hexagon::SXTH_cdnPt_V4: - case Hexagon::SXTH_cdnNotPt_V4: - case Hexagon::ZXTB_cdnPt_V4: - case Hexagon::ZXTB_cdnNotPt_V4: - case Hexagon::ZXTH_cdnPt_V4: - case Hexagon::ZXTH_cdnNotPt_V4: - - // Conditional stores - case Hexagon::STrib_imm_cdnPt_V4 : - case Hexagon::STrib_imm_cdnNotPt_V4 : - case Hexagon::STrib_cdnPt_V4 : - case Hexagon::STrib_cdnNotPt_V4 : - case Hexagon::STrib_indexed_cdnPt_V4 : - case Hexagon::STrib_indexed_cdnNotPt_V4 : - case Hexagon::POST_STbri_cdnPt_V4 : - case Hexagon::POST_STbri_cdnNotPt_V4 : - case Hexagon::STrib_indexed_shl_cdnPt_V4 : - case Hexagon::STrib_indexed_shl_cdnNotPt_V4 : - - // Store doubleword conditionally - case Hexagon::STrid_indexed_cdnPt_V4 : - case Hexagon::STrid_indexed_cdnNotPt_V4 : - case Hexagon::STrid_indexed_shl_cdnPt_V4 : - case Hexagon::STrid_indexed_shl_cdnNotPt_V4 : - case Hexagon::POST_STdri_cdnPt_V4 : - case Hexagon::POST_STdri_cdnNotPt_V4 : - - // Store halfword conditionally - case Hexagon::STrih_cdnPt_V4 : - case Hexagon::STrih_cdnNotPt_V4 : - case Hexagon::STrih_indexed_cdnPt_V4 : - case Hexagon::STrih_indexed_cdnNotPt_V4 : - case Hexagon::STrih_imm_cdnPt_V4 : - case Hexagon::STrih_imm_cdnNotPt_V4 : - case Hexagon::STrih_indexed_shl_cdnPt_V4 : - case Hexagon::STrih_indexed_shl_cdnNotPt_V4 : - case Hexagon::POST_SThri_cdnPt_V4 : - case Hexagon::POST_SThri_cdnNotPt_V4 : - - // Store word conditionally - case Hexagon::STriw_cdnPt_V4 : - case Hexagon::STriw_cdnNotPt_V4 : - case Hexagon::STriw_indexed_cdnPt_V4 : - case Hexagon::STriw_indexed_cdnNotPt_V4 : - case Hexagon::STriw_imm_cdnPt_V4 : - case Hexagon::STriw_imm_cdnNotPt_V4 : - case Hexagon::STriw_indexed_shl_cdnPt_V4 : - case Hexagon::STriw_indexed_shl_cdnNotPt_V4 : - case Hexagon::POST_STwri_cdnPt_V4 : - case Hexagon::POST_STwri_cdnNotPt_V4 : - - case Hexagon::LDd_GP_cdnPt_V4: - case Hexagon::LDd_GP_cdnNotPt_V4: - case Hexagon::LDb_GP_cdnPt_V4: - case Hexagon::LDb_GP_cdnNotPt_V4: - case Hexagon::LDub_GP_cdnPt_V4: - case Hexagon::LDub_GP_cdnNotPt_V4: - case Hexagon::LDh_GP_cdnPt_V4: - case Hexagon::LDh_GP_cdnNotPt_V4: - case Hexagon::LDuh_GP_cdnPt_V4: - 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: - case Hexagon::STb_GP_cdnNotPt_V4: - case Hexagon::STh_GP_cdnPt_V4: - case Hexagon::STh_GP_cdnNotPt_V4: - case Hexagon::STw_GP_cdnPt_V4: - case Hexagon::STw_GP_cdnNotPt_V4: - return true; - } - return false; -} - static MachineOperand& GetPostIncrementOperand(MachineInstr *MI, const HexagonInstrInfo *QII) { assert(QII->isPostIncrement(MI) && "Not a post increment operation."); @@ -2883,7 +2323,7 @@ bool HexagonPacketizerList::CanPromoteToNewValueStore( MachineInstr *MI, // sense, i.e, either both should be negated or both should be none negated. if (( predRegNumDst != predRegNumSrc) || - isDotNewInst(PacketMI) != isDotNewInst(MI) || + QII->isDotNewInst(PacketMI) != QII->isDotNewInst(MI) || GetPredicateSense(MI, QII) != GetPredicateSense(PacketMI, QII)) { return false; } @@ -2993,8 +2433,9 @@ bool HexagonPacketizerList::CanPromoteToDotNew( MachineInstr *MI, MachineBasicBlock::iterator &MII, const TargetRegisterClass* RC ) { - // already a dot new instruction - if (isDotNewInst(MI) && !IsNewifyStore(MI)) + const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; + // Already a dot new instruction. + if (QII->isDotNewInst(MI) && !IsNewifyStore(MI)) return false; if (!isNewifiable(MI)) @@ -3009,7 +2450,6 @@ bool HexagonPacketizerList::CanPromoteToDotNew( MachineInstr *MI, else { // Create a dot new machine instruction to see if resources can be // allocated. If not, bail out now. - const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; int NewOpcode = GetDotNewOp(MI->getOpcode()); const MCInstrDesc &desc = QII->get(NewOpcode); DebugLoc dl; @@ -3152,7 +2592,7 @@ bool HexagonPacketizerList::ArePredicatesComplements (MachineInstr* MI1, // !p0 is not complimentary to p0.new return ((MI1->getOperand(1).getReg() == MI2->getOperand(1).getReg()) && (GetPredicateSense(MI1, QII) != GetPredicateSense(MI2, QII)) && - (isDotNewInst(MI1) == isDotNewInst(MI2))); + (QII->isDotNewInst(MI1) == QII->isDotNewInst(MI2))); } // initPacketizerState - Initialize packetizer flags @@ -3277,13 +2717,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; @@ -3580,7 +3020,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); @@ -3600,7 +3040,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); @@ -3616,7 +3056,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/contrib/llvm/lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.cpp b/contrib/llvm/lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.cpp index 035afe8..36da6df 100644 --- a/contrib/llvm/lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.cpp +++ b/contrib/llvm/lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.cpp @@ -12,14 +12,14 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "asm-printer" -#include "Hexagon.h" #include "HexagonAsmPrinter.h" +#include "Hexagon.h" #include "HexagonInstPrinter.h" -#include "HexagonMCInst.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/ADT/StringExtras.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/contrib/llvm/lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.h b/contrib/llvm/lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.h index 902a323..d0cef68 100644 --- a/contrib/llvm/lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.h +++ b/contrib/llvm/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/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h b/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h index 7221e90..d4a93b5 100644 --- a/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h +++ b/contrib/llvm/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,22 +31,50 @@ 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 { + HasV2SubT = 0xf, + HasV2SubTOnly = 0x1, + NoV2SubT = 0x0, + HasV3SubT = 0xe, + HasV3SubTOnly = 0x2, + NoV3SubT = 0x1, + HasV4SubT = 0xc, + NoV4SubT = 0x3, + HasV5SubT = 0x8, + NoV5SubT = 0x7 + }; + enum AddrMode { + NoAddrMode = 0, // No addressing mode + Absolute = 1, // Absolute addressing mode + AbsoluteSet = 2, // Absolute set addressing mode + BaseImmOffset = 3, // Indirect with offset + BaseLongOffset = 4, // Indirect with long offset + 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 *** @@ -58,11 +89,93 @@ namespace HexagonII { // Predicated instructions. PredicatedPos = 6, - PredicatedMask = 0x1 + PredicatedMask = 0x1, + PredicatedFalsePos = 7, + PredicatedFalseMask = 0x1, + PredicatedNewPos = 8, + PredicatedNewMask = 0x1, + + // 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, + + // New-value store instructions. + NVStorePos = 17, + NVStoreMask = 0x1, + + // Extendable insns. + ExtendablePos = 18, + ExtendableMask = 0x1, + + // Insns must be extended. + ExtendedPos = 19, + ExtendedMask = 0x1, + + // Which operand may be extended. + ExtendableOpPos = 20, + ExtendableOpMask = 0x7, + + // Signed or unsigned range. + ExtentSignedPos = 23, + ExtentSignedMask = 0x1, + + // Number of bits of range before extending operand. + ExtentBitsPos = 24, + ExtentBitsMask = 0x1f, + + // Valid subtargets + validSubTargetPos = 29, + validSubTargetMask = 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/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp b/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp index 86f75d1..3deb8d1 100644 --- a/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp +++ b/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp @@ -31,6 +31,7 @@ HexagonMCAsmInfo::HexagonMCAsmInfo(const Target &T, StringRef TT) { AscizDirective = "\t.string\t"; WeakRefDirective = "\t.weak\t"; + SupportsDebugInformation = true; UsesELFSectionDirectiveForBSS = true; ExceptionsType = ExceptionHandling::DwarfCFI; } diff --git a/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.cpp b/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.cpp new file mode 100644 index 0000000..9260b4a --- /dev/null +++ b/contrib/llvm/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/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.h b/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.h new file mode 100644 index 0000000..3ca71f0 --- /dev/null +++ b/contrib/llvm/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/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp b/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp index 3cfa4fd..6b1d2d1 100644 --- a/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp +++ b/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp @@ -13,10 +13,12 @@ #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/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" diff --git a/contrib/llvm/lib/Target/Hexagon/TargetInfo/HexagonTargetInfo.cpp b/contrib/llvm/lib/Target/Hexagon/TargetInfo/HexagonTargetInfo.cpp index 7aa5dd3..40f6c8d 100644 --- a/contrib/llvm/lib/Target/Hexagon/TargetInfo/HexagonTargetInfo.cpp +++ b/contrib/llvm/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; |