400 lines · c
1//===-- SystemZInstrInfo.h - SystemZ instruction information ----*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the SystemZ implementation of the TargetInstrInfo class.10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZINSTRINFO_H14#define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZINSTRINFO_H15 16#include "SystemZ.h"17#include "SystemZRegisterInfo.h"18#include "llvm/ADT/ArrayRef.h"19#include "llvm/CodeGen/MachineBasicBlock.h"20#include "llvm/CodeGen/MachineFunction.h"21#include "llvm/CodeGen/MachineInstrBuilder.h"22#include "llvm/CodeGen/TargetInstrInfo.h"23#include <cstdint>24 25#define GET_INSTRINFO_HEADER26#include "SystemZGenInstrInfo.inc"27 28namespace llvm {29 30class SystemZSubtarget;31 32namespace SystemZII {33 34enum {35 // See comments in SystemZInstrFormats.td.36 SimpleBDXLoad = (1 << 0),37 SimpleBDXStore = (1 << 1),38 Has20BitOffset = (1 << 2),39 HasIndex = (1 << 3),40 Is128Bit = (1 << 4),41 AccessSizeMask = (31 << 5),42 AccessSizeShift = 5,43 CCValuesMask = (15 << 10),44 CCValuesShift = 10,45 CompareZeroCCMaskMask = (15 << 14),46 CompareZeroCCMaskShift = 14,47 CCMaskFirst = (1 << 18),48 CCMaskLast = (1 << 19),49 IsLogical = (1 << 20),50 CCIfNoSignedWrap = (1 << 21)51};52 53static inline unsigned getAccessSize(unsigned int Flags) {54 return (Flags & AccessSizeMask) >> AccessSizeShift;55}56 57static inline unsigned getCCValues(unsigned int Flags) {58 return (Flags & CCValuesMask) >> CCValuesShift;59}60 61static inline unsigned getCompareZeroCCMask(unsigned int Flags) {62 return (Flags & CompareZeroCCMaskMask) >> CompareZeroCCMaskShift;63}64 65// SystemZ MachineOperand target flags.66enum {67 // Masks out the bits for the access model.68 MO_SYMBOL_MODIFIER = (3 << 0),69 70 // @GOT (aka @GOTENT)71 MO_GOT = (1 << 0),72 73 // @INDNTPOFF74 MO_INDNTPOFF = (2 << 0),75 76 // z/OS XPLink specific: classifies the types of77 // accesses to the ADA (Associated Data Area).78 MO_ADA_DATA_SYMBOL_ADDR = (1 << 2),79 MO_ADA_INDIRECT_FUNC_DESC = (2 << 2),80 MO_ADA_DIRECT_FUNC_DESC = (3 << 2),81};82 83// Classifies a branch.84enum BranchType {85 // An instruction that branches on the current value of CC.86 BranchNormal,87 88 // An instruction that peforms a 32-bit signed comparison and branches89 // on the result.90 BranchC,91 92 // An instruction that peforms a 32-bit unsigned comparison and branches93 // on the result.94 BranchCL,95 96 // An instruction that peforms a 64-bit signed comparison and branches97 // on the result.98 BranchCG,99 100 // An instruction that peforms a 64-bit unsigned comparison and branches101 // on the result.102 BranchCLG,103 104 // An instruction that decrements a 32-bit register and branches if105 // the result is nonzero.106 BranchCT,107 108 // An instruction that decrements a 64-bit register and branches if109 // the result is nonzero.110 BranchCTG,111 112 // An instruction representing an asm goto statement.113 AsmGoto114};115 116// Information about a branch instruction.117class Branch {118 // The target of the branch. In case of INLINEASM_BR, this is nullptr.119 const MachineOperand *Target;120 121public:122 // The type of the branch.123 BranchType Type;124 125 // CCMASK_<N> is set if CC might be equal to N.126 unsigned CCValid;127 128 // CCMASK_<N> is set if the branch should be taken when CC == N.129 unsigned CCMask;130 131 Branch(BranchType type, unsigned ccValid, unsigned ccMask,132 const MachineOperand *target)133 : Target(target), Type(type), CCValid(ccValid), CCMask(ccMask) {}134 135 bool isIndirect() { return Target != nullptr && Target->isReg(); }136 bool hasMBBTarget() { return Target != nullptr && Target->isMBB(); }137 MachineBasicBlock *getMBBTarget() {138 return hasMBBTarget() ? Target->getMBB() : nullptr;139 }140};141 142// Kinds of fused compares in compare-and-* instructions. Together with type143// of the converted compare, this identifies the compare-and-*144// instruction.145enum FusedCompareType {146 // Relative branch - CRJ etc.147 CompareAndBranch,148 149 // Indirect branch, used for return - CRBReturn etc.150 CompareAndReturn,151 152 // Indirect branch, used for sibcall - CRBCall etc.153 CompareAndSibcall,154 155 // Trap156 CompareAndTrap157};158 159} // end namespace SystemZII160 161namespace SystemZ {162int getTwoOperandOpcode(uint16_t Opcode);163int getTargetMemOpcode(uint16_t Opcode);164 165// Return a version of comparison CC mask CCMask in which the LT and GT166// actions are swapped.167unsigned reverseCCMask(unsigned CCMask);168 169// Create a new basic block after MBB.170MachineBasicBlock *emitBlockAfter(MachineBasicBlock *MBB);171// Split MBB after MI and return the new block (the one that contains172// instructions after MI).173MachineBasicBlock *splitBlockAfter(MachineBasicBlock::iterator MI,174 MachineBasicBlock *MBB);175// Split MBB before MI and return the new block (the one that contains MI).176MachineBasicBlock *splitBlockBefore(MachineBasicBlock::iterator MI,177 MachineBasicBlock *MBB);178}179 180class SystemZInstrInfo : public SystemZGenInstrInfo {181 const SystemZRegisterInfo RI;182 const SystemZSubtarget &STI;183 184 void splitMove(MachineBasicBlock::iterator MI, unsigned NewOpcode) const;185 void splitAdjDynAlloc(MachineBasicBlock::iterator MI) const;186 void expandRIPseudo(MachineInstr &MI, unsigned LowOpcode, unsigned HighOpcode,187 bool ConvertHigh) const;188 void expandRIEPseudo(MachineInstr &MI, unsigned LowOpcode,189 unsigned LowOpcodeK, unsigned HighOpcode) const;190 void expandRXYPseudo(MachineInstr &MI, unsigned LowOpcode,191 unsigned HighOpcode) const;192 void expandLOCPseudo(MachineInstr &MI, unsigned LowOpcode,193 unsigned HighOpcode) const;194 void expandZExtPseudo(MachineInstr &MI, unsigned LowOpcode,195 unsigned Size) const;196 void expandLoadStackGuard(MachineInstr *MI) const;197 198 MachineInstrBuilder199 emitGRX32Move(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,200 const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,201 unsigned LowLowOpcode, unsigned Size, bool KillSrc,202 bool UndefSrc) const;203 204 virtual void anchor();205 206protected:207 /// Commutes the operands in the given instruction by changing the operands208 /// order and/or changing the instruction's opcode and/or the immediate value209 /// operand.210 ///211 /// The arguments 'CommuteOpIdx1' and 'CommuteOpIdx2' specify the operands212 /// to be commuted.213 ///214 /// Do not call this method for a non-commutable instruction or215 /// non-commutable operands.216 /// Even though the instruction is commutable, the method may still217 /// fail to commute the operands, null pointer is returned in such cases.218 MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI,219 unsigned CommuteOpIdx1,220 unsigned CommuteOpIdx2) const override;221 222public:223 explicit SystemZInstrInfo(const SystemZSubtarget &STI);224 225 // Override TargetInstrInfo.226 Register isLoadFromStackSlot(const MachineInstr &MI,227 int &FrameIndex) const override;228 Register isStoreToStackSlot(const MachineInstr &MI,229 int &FrameIndex) const override;230 Register isLoadFromStackSlotPostFE(const MachineInstr &MI,231 int &FrameIndex) const override;232 Register isStoreToStackSlotPostFE(const MachineInstr &MI,233 int &FrameIndex) const override;234 bool isStackSlotCopy(const MachineInstr &MI, int &DestFrameIndex,235 int &SrcFrameIndex) const override;236 bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,237 MachineBasicBlock *&FBB,238 SmallVectorImpl<MachineOperand> &Cond,239 bool AllowModify) const override;240 unsigned removeBranch(MachineBasicBlock &MBB,241 int *BytesRemoved = nullptr) const override;242 unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,243 MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,244 const DebugLoc &DL,245 int *BytesAdded = nullptr) const override;246 bool analyzeCompare(const MachineInstr &MI, Register &SrcReg,247 Register &SrcReg2, int64_t &Mask,248 int64_t &Value) const override;249 bool canInsertSelect(const MachineBasicBlock &, ArrayRef<MachineOperand> Cond,250 Register, Register, Register, int &, int &,251 int &) const override;252 void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,253 const DebugLoc &DL, Register DstReg,254 ArrayRef<MachineOperand> Cond, Register TrueReg,255 Register FalseReg) const override;256 bool foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg,257 MachineRegisterInfo *MRI) const override;258 259 bool isPredicable(const MachineInstr &MI) const override;260 bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCycles,261 unsigned ExtraPredCycles,262 BranchProbability Probability) const override;263 bool isProfitableToIfCvt(MachineBasicBlock &TMBB,264 unsigned NumCyclesT, unsigned ExtraPredCyclesT,265 MachineBasicBlock &FMBB,266 unsigned NumCyclesF, unsigned ExtraPredCyclesF,267 BranchProbability Probability) const override;268 bool isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCycles,269 BranchProbability Probability) const override;270 bool PredicateInstruction(MachineInstr &MI,271 ArrayRef<MachineOperand> Pred) const override;272 void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,273 const DebugLoc &DL, Register DestReg, Register SrcReg,274 bool KillSrc, bool RenamableDest = false,275 bool RenamableSrc = false) const override;276 void storeRegToStackSlot(277 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg,278 bool isKill, int FrameIndex, const TargetRegisterClass *RC,279 280 Register VReg,281 MachineInstr::MIFlag Flags = MachineInstr::NoFlags) const override;282 void loadRegFromStackSlot(283 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,284 Register DestReg, int FrameIdx, const TargetRegisterClass *RC,285 286 Register VReg,287 MachineInstr::MIFlag Flags = MachineInstr::NoFlags) const override;288 MachineInstr *convertToThreeAddress(MachineInstr &MI, LiveVariables *LV,289 LiveIntervals *LIS) const override;290 291 bool useMachineCombiner() const override { return true; }292 bool isAssociativeAndCommutative(const MachineInstr &Inst,293 bool Invert) const override;294 std::optional<unsigned> getInverseOpcode(unsigned Opcode) const override;295 296 MachineInstr *297 foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI,298 ArrayRef<unsigned> Ops,299 MachineBasicBlock::iterator InsertPt, int FrameIndex,300 LiveIntervals *LIS = nullptr,301 VirtRegMap *VRM = nullptr) const override;302 MachineInstr *foldMemoryOperandImpl(303 MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops,304 MachineBasicBlock::iterator InsertPt, MachineInstr &LoadMI,305 LiveIntervals *LIS = nullptr) const override;306 bool expandPostRAPseudo(MachineInstr &MBBI) const override;307 bool reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const308 override;309 310 // Return the SystemZRegisterInfo, which this class owns.311 const SystemZRegisterInfo &getRegisterInfo() const { return RI; }312 313 // Return the size in bytes of MI.314 unsigned getInstSizeInBytes(const MachineInstr &MI) const override;315 316 // Return true if MI is a conditional or unconditional branch.317 // When returning true, set Cond to the mask of condition-code318 // values on which the instruction will branch, and set Target319 // to the operand that contains the branch target. This target320 // can be a register or a basic block.321 SystemZII::Branch getBranchInfo(const MachineInstr &MI) const;322 323 // Get the load and store opcodes for a given register class.324 void getLoadStoreOpcodes(const TargetRegisterClass *RC,325 unsigned &LoadOpcode, unsigned &StoreOpcode) const;326 327 // Opcode is the opcode of an instruction that has an address operand,328 // and the caller wants to perform that instruction's operation on an329 // address that has displacement Offset. Return the opcode of a suitable330 // instruction (which might be Opcode itself) or 0 if no such instruction331 // exists. MI may be passed in order to allow examination of physical332 // register operands (i.e. if a VR32/64 reg ended up as an FP or Vector reg).333 unsigned getOpcodeForOffset(unsigned Opcode, int64_t Offset,334 const MachineInstr *MI = nullptr) const;335 336 // Return true if Opcode has a mapping in 12 <-> 20 bit displacements.337 bool hasDisplacementPairInsn(unsigned Opcode) const;338 339 // If Opcode is a load instruction that has a LOAD AND TEST form,340 // return the opcode for the testing form, otherwise return 0.341 unsigned getLoadAndTest(unsigned Opcode) const;342 343 // Return true if ROTATE AND ... SELECTED BITS can be used to select bits344 // Mask of the R2 operand, given that only the low BitSize bits of Mask are345 // significant. Set Start and End to the I3 and I4 operands if so.346 bool isRxSBGMask(uint64_t Mask, unsigned BitSize,347 unsigned &Start, unsigned &End) const;348 349 // If Opcode is a COMPARE opcode for which an associated fused COMPARE AND *350 // operation exists, return the opcode for the latter, otherwise return 0.351 // MI, if nonnull, is the compare instruction.352 unsigned getFusedCompare(unsigned Opcode,353 SystemZII::FusedCompareType Type,354 const MachineInstr *MI = nullptr) const;355 356 // Try to find all CC users of the compare instruction (MBBI) and update357 // all of them to maintain equivalent behavior after swapping the compare358 // operands. Return false if not all users can be conclusively found and359 // handled. The compare instruction is *not* changed.360 bool prepareCompareSwapOperands(MachineBasicBlock::iterator MBBI) const;361 362 // If Opcode is a LOAD opcode for with an associated LOAD AND TRAP363 // operation exists, returh the opcode for the latter, otherwise return 0.364 unsigned getLoadAndTrap(unsigned Opcode) const;365 366 // Emit code before MBBI in MI to move immediate value Value into367 // physical register Reg.368 void loadImmediate(MachineBasicBlock &MBB,369 MachineBasicBlock::iterator MBBI,370 unsigned Reg, uint64_t Value) const;371 372 // Perform target specific instruction verification.373 bool verifyInstruction(const MachineInstr &MI,374 StringRef &ErrInfo) const override;375 376 // Sometimes, it is possible for the target to tell, even without377 // aliasing information, that two MIs access different memory378 // addresses. This function returns true if two MIs access different379 // memory addresses and false otherwise.380 bool381 areMemAccessesTriviallyDisjoint(const MachineInstr &MIa,382 const MachineInstr &MIb) const override;383 384 bool getConstValDefinedInReg(const MachineInstr &MI, const Register Reg,385 int64_t &ImmVal) const override;386 387 std::optional<DestSourcePair>388 isCopyInstrImpl(const MachineInstr &MI) const override;389 390 std::pair<unsigned, unsigned>391 decomposeMachineOperandsTargetFlags(unsigned TF) const override;392 393 ArrayRef<std::pair<unsigned, const char *>>394 getSerializableDirectMachineOperandTargetFlags() const override;395};396 397} // end namespace llvm398 399#endif // LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZINSTRINFO_H400