1 //===-- SystemZInstrInfo.h - SystemZ instruction information ----*- C++ -*-===//
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-exception
7 //===----------------------------------------------------------------------===//
9 // This file contains the SystemZ implementation of the TargetInstrInfo class.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZINSTRINFO_H
14 #define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZINSTRINFO_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"
25 #define GET_INSTRINFO_HEADER
26 #include "SystemZGenInstrInfo.inc"
30 class SystemZSubtarget
;
35 // See comments in SystemZInstrFormats.td.
36 SimpleBDXLoad
= (1 << 0),
37 SimpleBDXStore
= (1 << 1),
38 Has20BitOffset
= (1 << 2),
41 AccessSizeMask
= (31 << 5),
43 CCValuesMask
= (15 << 10),
45 CompareZeroCCMaskMask
= (15 << 14),
46 CompareZeroCCMaskShift
= 14,
47 CCMaskFirst
= (1 << 18),
48 CCMaskLast
= (1 << 19),
49 IsLogical
= (1 << 20),
50 CCIfNoSignedWrap
= (1 << 21)
53 static inline unsigned getAccessSize(unsigned int Flags
) {
54 return (Flags
& AccessSizeMask
) >> AccessSizeShift
;
57 static inline unsigned getCCValues(unsigned int Flags
) {
58 return (Flags
& CCValuesMask
) >> CCValuesShift
;
61 static inline unsigned getCompareZeroCCMask(unsigned int Flags
) {
62 return (Flags
& CompareZeroCCMaskMask
) >> CompareZeroCCMaskShift
;
65 // SystemZ MachineOperand target flags.
67 // Masks out the bits for the access model.
68 MO_SYMBOL_MODIFIER
= (3 << 0),
74 MO_INDNTPOFF
= (2 << 0)
77 // z/OS XPLink specific: classifies the types of
78 // accesses to the ADA (Associated Data Area).
79 // These enums contains values that overlap with the above MO_ enums,
80 // but that's fine since the above enums are used with ELF,
81 // while these values are used with z/OS.
83 MO_ADA_DATA_SYMBOL_ADDR
= 1,
84 MO_ADA_INDIRECT_FUNC_DESC
,
85 MO_ADA_DIRECT_FUNC_DESC
,
88 // Classifies a branch.
90 // An instruction that branches on the current value of CC.
93 // An instruction that peforms a 32-bit signed comparison and branches
97 // An instruction that peforms a 32-bit unsigned comparison and branches
101 // An instruction that peforms a 64-bit signed comparison and branches
105 // An instruction that peforms a 64-bit unsigned comparison and branches
109 // An instruction that decrements a 32-bit register and branches if
110 // the result is nonzero.
113 // An instruction that decrements a 64-bit register and branches if
114 // the result is nonzero.
117 // An instruction representing an asm goto statement.
121 // Information about a branch instruction.
123 // The target of the branch. In case of INLINEASM_BR, this is nullptr.
124 const MachineOperand
*Target
;
127 // The type of the branch.
130 // CCMASK_<N> is set if CC might be equal to N.
133 // CCMASK_<N> is set if the branch should be taken when CC == N.
136 Branch(BranchType type
, unsigned ccValid
, unsigned ccMask
,
137 const MachineOperand
*target
)
138 : Target(target
), Type(type
), CCValid(ccValid
), CCMask(ccMask
) {}
140 bool isIndirect() { return Target
!= nullptr && Target
->isReg(); }
141 bool hasMBBTarget() { return Target
!= nullptr && Target
->isMBB(); }
142 MachineBasicBlock
*getMBBTarget() {
143 return hasMBBTarget() ? Target
->getMBB() : nullptr;
147 // Kinds of fused compares in compare-and-* instructions. Together with type
148 // of the converted compare, this identifies the compare-and-*
150 enum FusedCompareType
{
151 // Relative branch - CRJ etc.
154 // Indirect branch, used for return - CRBReturn etc.
157 // Indirect branch, used for sibcall - CRBCall etc.
164 } // end namespace SystemZII
167 int getTwoOperandOpcode(uint16_t Opcode
);
168 int getTargetMemOpcode(uint16_t Opcode
);
170 // Return a version of comparison CC mask CCMask in which the LT and GT
171 // actions are swapped.
172 unsigned reverseCCMask(unsigned CCMask
);
174 // Create a new basic block after MBB.
175 MachineBasicBlock
*emitBlockAfter(MachineBasicBlock
*MBB
);
176 // Split MBB after MI and return the new block (the one that contains
177 // instructions after MI).
178 MachineBasicBlock
*splitBlockAfter(MachineBasicBlock::iterator MI
,
179 MachineBasicBlock
*MBB
);
180 // Split MBB before MI and return the new block (the one that contains MI).
181 MachineBasicBlock
*splitBlockBefore(MachineBasicBlock::iterator MI
,
182 MachineBasicBlock
*MBB
);
185 class SystemZInstrInfo
: public SystemZGenInstrInfo
{
186 const SystemZRegisterInfo RI
;
187 SystemZSubtarget
&STI
;
189 void splitMove(MachineBasicBlock::iterator MI
, unsigned NewOpcode
) const;
190 void splitAdjDynAlloc(MachineBasicBlock::iterator MI
) const;
191 void expandRIPseudo(MachineInstr
&MI
, unsigned LowOpcode
, unsigned HighOpcode
,
192 bool ConvertHigh
) const;
193 void expandRIEPseudo(MachineInstr
&MI
, unsigned LowOpcode
,
194 unsigned LowOpcodeK
, unsigned HighOpcode
) const;
195 void expandRXYPseudo(MachineInstr
&MI
, unsigned LowOpcode
,
196 unsigned HighOpcode
) const;
197 void expandLOCPseudo(MachineInstr
&MI
, unsigned LowOpcode
,
198 unsigned HighOpcode
) const;
199 void expandZExtPseudo(MachineInstr
&MI
, unsigned LowOpcode
,
200 unsigned Size
) const;
201 void expandLoadStackGuard(MachineInstr
*MI
) const;
204 emitGRX32Move(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
205 const DebugLoc
&DL
, unsigned DestReg
, unsigned SrcReg
,
206 unsigned LowLowOpcode
, unsigned Size
, bool KillSrc
,
207 bool UndefSrc
) const;
209 virtual void anchor();
212 /// Commutes the operands in the given instruction by changing the operands
213 /// order and/or changing the instruction's opcode and/or the immediate value
216 /// The arguments 'CommuteOpIdx1' and 'CommuteOpIdx2' specify the operands
219 /// Do not call this method for a non-commutable instruction or
220 /// non-commutable operands.
221 /// Even though the instruction is commutable, the method may still
222 /// fail to commute the operands, null pointer is returned in such cases.
223 MachineInstr
*commuteInstructionImpl(MachineInstr
&MI
, bool NewMI
,
224 unsigned CommuteOpIdx1
,
225 unsigned CommuteOpIdx2
) const override
;
228 explicit SystemZInstrInfo(SystemZSubtarget
&STI
);
230 // Override TargetInstrInfo.
231 Register
isLoadFromStackSlot(const MachineInstr
&MI
,
232 int &FrameIndex
) const override
;
233 Register
isStoreToStackSlot(const MachineInstr
&MI
,
234 int &FrameIndex
) const override
;
235 bool isStackSlotCopy(const MachineInstr
&MI
, int &DestFrameIndex
,
236 int &SrcFrameIndex
) const override
;
237 bool analyzeBranch(MachineBasicBlock
&MBB
, MachineBasicBlock
*&TBB
,
238 MachineBasicBlock
*&FBB
,
239 SmallVectorImpl
<MachineOperand
> &Cond
,
240 bool AllowModify
) const override
;
241 unsigned removeBranch(MachineBasicBlock
&MBB
,
242 int *BytesRemoved
= nullptr) const override
;
243 unsigned insertBranch(MachineBasicBlock
&MBB
, MachineBasicBlock
*TBB
,
244 MachineBasicBlock
*FBB
, ArrayRef
<MachineOperand
> Cond
,
246 int *BytesAdded
= nullptr) const override
;
247 bool analyzeCompare(const MachineInstr
&MI
, Register
&SrcReg
,
248 Register
&SrcReg2
, int64_t &Mask
,
249 int64_t &Value
) const override
;
250 bool canInsertSelect(const MachineBasicBlock
&, ArrayRef
<MachineOperand
> Cond
,
251 Register
, Register
, Register
, int &, int &,
252 int &) const override
;
253 void insertSelect(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MI
,
254 const DebugLoc
&DL
, Register DstReg
,
255 ArrayRef
<MachineOperand
> Cond
, Register TrueReg
,
256 Register FalseReg
) const override
;
257 MachineInstr
*optimizeLoadInstr(MachineInstr
&MI
,
258 const MachineRegisterInfo
*MRI
,
259 Register
&FoldAsLoadDefReg
,
260 MachineInstr
*&DefMI
) const override
;
261 bool foldImmediate(MachineInstr
&UseMI
, MachineInstr
&DefMI
, Register Reg
,
262 MachineRegisterInfo
*MRI
) const override
;
264 bool isPredicable(const MachineInstr
&MI
) const override
;
265 bool isProfitableToIfCvt(MachineBasicBlock
&MBB
, unsigned NumCycles
,
266 unsigned ExtraPredCycles
,
267 BranchProbability Probability
) const override
;
268 bool isProfitableToIfCvt(MachineBasicBlock
&TMBB
,
269 unsigned NumCyclesT
, unsigned ExtraPredCyclesT
,
270 MachineBasicBlock
&FMBB
,
271 unsigned NumCyclesF
, unsigned ExtraPredCyclesF
,
272 BranchProbability Probability
) const override
;
273 bool isProfitableToDupForIfCvt(MachineBasicBlock
&MBB
, unsigned NumCycles
,
274 BranchProbability Probability
) const override
;
275 bool PredicateInstruction(MachineInstr
&MI
,
276 ArrayRef
<MachineOperand
> Pred
) const override
;
277 void copyPhysReg(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
278 const DebugLoc
&DL
, MCRegister DestReg
, MCRegister SrcReg
,
279 bool KillSrc
, bool RenamableDest
= false,
280 bool RenamableSrc
= false) const override
;
281 void storeRegToStackSlot(MachineBasicBlock
&MBB
,
282 MachineBasicBlock::iterator MBBI
, Register SrcReg
,
283 bool isKill
, int FrameIndex
,
284 const TargetRegisterClass
*RC
,
285 const TargetRegisterInfo
*TRI
,
286 Register VReg
) const override
;
287 void loadRegFromStackSlot(MachineBasicBlock
&MBB
,
288 MachineBasicBlock::iterator MBBI
, Register DestReg
,
289 int FrameIdx
, const TargetRegisterClass
*RC
,
290 const TargetRegisterInfo
*TRI
,
291 Register VReg
) const override
;
292 MachineInstr
*convertToThreeAddress(MachineInstr
&MI
, LiveVariables
*LV
,
293 LiveIntervals
*LIS
) const override
;
295 bool useMachineCombiner() const override
{ return true; }
296 bool isAssociativeAndCommutative(const MachineInstr
&Inst
,
297 bool Invert
) const override
;
298 std::optional
<unsigned> getInverseOpcode(unsigned Opcode
) const override
;
301 foldMemoryOperandImpl(MachineFunction
&MF
, MachineInstr
&MI
,
302 ArrayRef
<unsigned> Ops
,
303 MachineBasicBlock::iterator InsertPt
, int FrameIndex
,
304 LiveIntervals
*LIS
= nullptr,
305 VirtRegMap
*VRM
= nullptr) const override
;
306 MachineInstr
*foldMemoryOperandImpl(
307 MachineFunction
&MF
, MachineInstr
&MI
, ArrayRef
<unsigned> Ops
,
308 MachineBasicBlock::iterator InsertPt
, MachineInstr
&LoadMI
,
309 LiveIntervals
*LIS
= nullptr) const override
;
310 bool expandPostRAPseudo(MachineInstr
&MBBI
) const override
;
311 bool reverseBranchCondition(SmallVectorImpl
<MachineOperand
> &Cond
) const
314 // Return the SystemZRegisterInfo, which this class owns.
315 const SystemZRegisterInfo
&getRegisterInfo() const { return RI
; }
317 // Return the size in bytes of MI.
318 unsigned getInstSizeInBytes(const MachineInstr
&MI
) const override
;
320 // Return true if MI is a conditional or unconditional branch.
321 // When returning true, set Cond to the mask of condition-code
322 // values on which the instruction will branch, and set Target
323 // to the operand that contains the branch target. This target
324 // can be a register or a basic block.
325 SystemZII::Branch
getBranchInfo(const MachineInstr
&MI
) const;
327 // Get the load and store opcodes for a given register class.
328 void getLoadStoreOpcodes(const TargetRegisterClass
*RC
,
329 unsigned &LoadOpcode
, unsigned &StoreOpcode
) const;
331 // Opcode is the opcode of an instruction that has an address operand,
332 // and the caller wants to perform that instruction's operation on an
333 // address that has displacement Offset. Return the opcode of a suitable
334 // instruction (which might be Opcode itself) or 0 if no such instruction
335 // exists. MI may be passed in order to allow examination of physical
336 // register operands (i.e. if a VR32/64 reg ended up as an FP or Vector reg).
337 unsigned getOpcodeForOffset(unsigned Opcode
, int64_t Offset
,
338 const MachineInstr
*MI
= nullptr) const;
340 // Return true if Opcode has a mapping in 12 <-> 20 bit displacements.
341 bool hasDisplacementPairInsn(unsigned Opcode
) const;
343 // If Opcode is a load instruction that has a LOAD AND TEST form,
344 // return the opcode for the testing form, otherwise return 0.
345 unsigned getLoadAndTest(unsigned Opcode
) const;
347 // Return true if ROTATE AND ... SELECTED BITS can be used to select bits
348 // Mask of the R2 operand, given that only the low BitSize bits of Mask are
349 // significant. Set Start and End to the I3 and I4 operands if so.
350 bool isRxSBGMask(uint64_t Mask
, unsigned BitSize
,
351 unsigned &Start
, unsigned &End
) const;
353 // If Opcode is a COMPARE opcode for which an associated fused COMPARE AND *
354 // operation exists, return the opcode for the latter, otherwise return 0.
355 // MI, if nonnull, is the compare instruction.
356 unsigned getFusedCompare(unsigned Opcode
,
357 SystemZII::FusedCompareType Type
,
358 const MachineInstr
*MI
= nullptr) const;
360 // Try to find all CC users of the compare instruction (MBBI) and update
361 // all of them to maintain equivalent behavior after swapping the compare
362 // operands. Return false if not all users can be conclusively found and
363 // handled. The compare instruction is *not* changed.
364 bool prepareCompareSwapOperands(MachineBasicBlock::iterator MBBI
) const;
366 // If Opcode is a LOAD opcode for with an associated LOAD AND TRAP
367 // operation exists, returh the opcode for the latter, otherwise return 0.
368 unsigned getLoadAndTrap(unsigned Opcode
) const;
370 // Emit code before MBBI in MI to move immediate value Value into
371 // physical register Reg.
372 void loadImmediate(MachineBasicBlock
&MBB
,
373 MachineBasicBlock::iterator MBBI
,
374 unsigned Reg
, uint64_t Value
) const;
376 // Perform target specific instruction verification.
377 bool verifyInstruction(const MachineInstr
&MI
,
378 StringRef
&ErrInfo
) const override
;
380 // Sometimes, it is possible for the target to tell, even without
381 // aliasing information, that two MIs access different memory
382 // addresses. This function returns true if two MIs access different
383 // memory addresses and false otherwise.
385 areMemAccessesTriviallyDisjoint(const MachineInstr
&MIa
,
386 const MachineInstr
&MIb
) const override
;
388 bool getConstValDefinedInReg(const MachineInstr
&MI
, const Register Reg
,
389 int64_t &ImmVal
) const override
;
392 } // end namespace llvm
394 #endif // LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZINSTRINFO_H