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-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file contains the SystemZ implementation of the TargetInstrInfo class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZINSTRINFO_H |
14 | #define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZINSTRINFO_H |
15 | |
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 |
26 | #include "SystemZGenInstrInfo.inc" |
27 | |
28 | namespace llvm { |
29 | |
30 | class SystemZSubtarget; |
31 | |
32 | namespace SystemZII { |
33 | |
34 | enum { |
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 | |
53 | static inline unsigned getAccessSize(unsigned int Flags) { |
54 | return (Flags & AccessSizeMask) >> AccessSizeShift; |
55 | } |
56 | |
57 | static inline unsigned getCCValues(unsigned int Flags) { |
58 | return (Flags & CCValuesMask) >> CCValuesShift; |
59 | } |
60 | |
61 | static inline unsigned getCompareZeroCCMask(unsigned int Flags) { |
62 | return (Flags & CompareZeroCCMaskMask) >> CompareZeroCCMaskShift; |
63 | } |
64 | |
65 | // SystemZ MachineOperand target flags. |
66 | enum { |
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 | // @INDNTPOFF |
74 | MO_INDNTPOFF = (2 << 0) |
75 | }; |
76 | |
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. |
82 | enum { |
83 | MO_ADA_DATA_SYMBOL_ADDR = 1, |
84 | MO_ADA_INDIRECT_FUNC_DESC, |
85 | MO_ADA_DIRECT_FUNC_DESC, |
86 | }; |
87 | |
88 | // Classifies a branch. |
89 | enum BranchType { |
90 | // An instruction that branches on the current value of CC. |
91 | BranchNormal, |
92 | |
93 | // An instruction that peforms a 32-bit signed comparison and branches |
94 | // on the result. |
95 | BranchC, |
96 | |
97 | // An instruction that peforms a 32-bit unsigned comparison and branches |
98 | // on the result. |
99 | BranchCL, |
100 | |
101 | // An instruction that peforms a 64-bit signed comparison and branches |
102 | // on the result. |
103 | BranchCG, |
104 | |
105 | // An instruction that peforms a 64-bit unsigned comparison and branches |
106 | // on the result. |
107 | BranchCLG, |
108 | |
109 | // An instruction that decrements a 32-bit register and branches if |
110 | // the result is nonzero. |
111 | BranchCT, |
112 | |
113 | // An instruction that decrements a 64-bit register and branches if |
114 | // the result is nonzero. |
115 | BranchCTG, |
116 | |
117 | // An instruction representing an asm goto statement. |
118 | AsmGoto |
119 | }; |
120 | |
121 | // Information about a branch instruction. |
122 | class Branch { |
123 | // The target of the branch. In case of INLINEASM_BR, this is nullptr. |
124 | const MachineOperand *Target; |
125 | |
126 | public: |
127 | // The type of the branch. |
128 | BranchType Type; |
129 | |
130 | // CCMASK_<N> is set if CC might be equal to N. |
131 | unsigned CCValid; |
132 | |
133 | // CCMASK_<N> is set if the branch should be taken when CC == N. |
134 | unsigned CCMask; |
135 | |
136 | Branch(BranchType type, unsigned ccValid, unsigned ccMask, |
137 | const MachineOperand *target) |
138 | : Target(target), Type(type), CCValid(ccValid), CCMask(ccMask) {} |
139 | |
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; |
144 | } |
145 | }; |
146 | |
147 | // Kinds of fused compares in compare-and-* instructions. Together with type |
148 | // of the converted compare, this identifies the compare-and-* |
149 | // instruction. |
150 | enum FusedCompareType { |
151 | // Relative branch - CRJ etc. |
152 | CompareAndBranch, |
153 | |
154 | // Indirect branch, used for return - CRBReturn etc. |
155 | CompareAndReturn, |
156 | |
157 | // Indirect branch, used for sibcall - CRBCall etc. |
158 | CompareAndSibcall, |
159 | |
160 | // Trap |
161 | CompareAndTrap |
162 | }; |
163 | |
164 | } // end namespace SystemZII |
165 | |
166 | namespace SystemZ { |
167 | int getTwoOperandOpcode(uint16_t Opcode); |
168 | int getTargetMemOpcode(uint16_t Opcode); |
169 | |
170 | // Return a version of comparison CC mask CCMask in which the LT and GT |
171 | // actions are swapped. |
172 | unsigned reverseCCMask(unsigned CCMask); |
173 | |
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); |
183 | } |
184 | |
185 | class SystemZInstrInfo : public SystemZGenInstrInfo { |
186 | const SystemZRegisterInfo RI; |
187 | SystemZSubtarget &STI; |
188 | |
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; |
202 | |
203 | MachineInstrBuilder |
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; |
208 | |
209 | virtual void anchor(); |
210 | |
211 | protected: |
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 |
214 | /// operand. |
215 | /// |
216 | /// The arguments 'CommuteOpIdx1' and 'CommuteOpIdx2' specify the operands |
217 | /// to be commuted. |
218 | /// |
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; |
226 | |
227 | public: |
228 | explicit SystemZInstrInfo(SystemZSubtarget &STI); |
229 | |
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, |
245 | const DebugLoc &DL, |
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; |
263 | |
264 | bool isPredicable(const MachineInstr &MI) const override; |
265 | bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, |
266 | unsigned , |
267 | BranchProbability Probability) const override; |
268 | bool isProfitableToIfCvt(MachineBasicBlock &TMBB, |
269 | unsigned NumCyclesT, unsigned , |
270 | MachineBasicBlock &FMBB, |
271 | unsigned NumCyclesF, unsigned , |
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) const override; |
280 | void storeRegToStackSlot(MachineBasicBlock &MBB, |
281 | MachineBasicBlock::iterator MBBI, Register SrcReg, |
282 | bool isKill, int FrameIndex, |
283 | const TargetRegisterClass *RC, |
284 | const TargetRegisterInfo *TRI, |
285 | Register VReg) const override; |
286 | void loadRegFromStackSlot(MachineBasicBlock &MBB, |
287 | MachineBasicBlock::iterator MBBI, Register DestReg, |
288 | int FrameIdx, const TargetRegisterClass *RC, |
289 | const TargetRegisterInfo *TRI, |
290 | Register VReg) const override; |
291 | MachineInstr *convertToThreeAddress(MachineInstr &MI, LiveVariables *LV, |
292 | LiveIntervals *LIS) const override; |
293 | |
294 | bool useMachineCombiner() const override { return true; } |
295 | bool isAssociativeAndCommutative(const MachineInstr &Inst, |
296 | bool Invert) const override; |
297 | std::optional<unsigned> getInverseOpcode(unsigned Opcode) const override; |
298 | |
299 | MachineInstr * |
300 | foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, |
301 | ArrayRef<unsigned> Ops, |
302 | MachineBasicBlock::iterator InsertPt, int FrameIndex, |
303 | LiveIntervals *LIS = nullptr, |
304 | VirtRegMap *VRM = nullptr) const override; |
305 | MachineInstr *foldMemoryOperandImpl( |
306 | MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops, |
307 | MachineBasicBlock::iterator InsertPt, MachineInstr &LoadMI, |
308 | LiveIntervals *LIS = nullptr) const override; |
309 | bool expandPostRAPseudo(MachineInstr &MBBI) const override; |
310 | bool reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const |
311 | override; |
312 | |
313 | // Return the SystemZRegisterInfo, which this class owns. |
314 | const SystemZRegisterInfo &getRegisterInfo() const { return RI; } |
315 | |
316 | // Return the size in bytes of MI. |
317 | unsigned getInstSizeInBytes(const MachineInstr &MI) const override; |
318 | |
319 | // Return true if MI is a conditional or unconditional branch. |
320 | // When returning true, set Cond to the mask of condition-code |
321 | // values on which the instruction will branch, and set Target |
322 | // to the operand that contains the branch target. This target |
323 | // can be a register or a basic block. |
324 | SystemZII::Branch getBranchInfo(const MachineInstr &MI) const; |
325 | |
326 | // Get the load and store opcodes for a given register class. |
327 | void getLoadStoreOpcodes(const TargetRegisterClass *RC, |
328 | unsigned &LoadOpcode, unsigned &StoreOpcode) const; |
329 | |
330 | // Opcode is the opcode of an instruction that has an address operand, |
331 | // and the caller wants to perform that instruction's operation on an |
332 | // address that has displacement Offset. Return the opcode of a suitable |
333 | // instruction (which might be Opcode itself) or 0 if no such instruction |
334 | // exists. MI may be passed in order to allow examination of physical |
335 | // register operands (i.e. if a VR32/64 reg ended up as an FP or Vector reg). |
336 | unsigned getOpcodeForOffset(unsigned Opcode, int64_t Offset, |
337 | const MachineInstr *MI = nullptr) const; |
338 | |
339 | // Return true if Opcode has a mapping in 12 <-> 20 bit displacements. |
340 | bool hasDisplacementPairInsn(unsigned Opcode) const; |
341 | |
342 | // If Opcode is a load instruction that has a LOAD AND TEST form, |
343 | // return the opcode for the testing form, otherwise return 0. |
344 | unsigned getLoadAndTest(unsigned Opcode) const; |
345 | |
346 | // Return true if ROTATE AND ... SELECTED BITS can be used to select bits |
347 | // Mask of the R2 operand, given that only the low BitSize bits of Mask are |
348 | // significant. Set Start and End to the I3 and I4 operands if so. |
349 | bool isRxSBGMask(uint64_t Mask, unsigned BitSize, |
350 | unsigned &Start, unsigned &End) const; |
351 | |
352 | // If Opcode is a COMPARE opcode for which an associated fused COMPARE AND * |
353 | // operation exists, return the opcode for the latter, otherwise return 0. |
354 | // MI, if nonnull, is the compare instruction. |
355 | unsigned getFusedCompare(unsigned Opcode, |
356 | SystemZII::FusedCompareType Type, |
357 | const MachineInstr *MI = nullptr) const; |
358 | |
359 | // Try to find all CC users of the compare instruction (MBBI) and update |
360 | // all of them to maintain equivalent behavior after swapping the compare |
361 | // operands. Return false if not all users can be conclusively found and |
362 | // handled. The compare instruction is *not* changed. |
363 | bool prepareCompareSwapOperands(MachineBasicBlock::iterator MBBI) const; |
364 | |
365 | // If Opcode is a LOAD opcode for with an associated LOAD AND TRAP |
366 | // operation exists, returh the opcode for the latter, otherwise return 0. |
367 | unsigned getLoadAndTrap(unsigned Opcode) const; |
368 | |
369 | // Emit code before MBBI in MI to move immediate value Value into |
370 | // physical register Reg. |
371 | void loadImmediate(MachineBasicBlock &MBB, |
372 | MachineBasicBlock::iterator MBBI, |
373 | unsigned Reg, uint64_t Value) const; |
374 | |
375 | // Perform target specific instruction verification. |
376 | bool verifyInstruction(const MachineInstr &MI, |
377 | StringRef &ErrInfo) const override; |
378 | |
379 | // Sometimes, it is possible for the target to tell, even without |
380 | // aliasing information, that two MIs access different memory |
381 | // addresses. This function returns true if two MIs access different |
382 | // memory addresses and false otherwise. |
383 | bool |
384 | areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, |
385 | const MachineInstr &MIb) const override; |
386 | |
387 | bool getConstValDefinedInReg(const MachineInstr &MI, const Register Reg, |
388 | int64_t &ImmVal) const override; |
389 | }; |
390 | |
391 | } // end namespace llvm |
392 | |
393 | #endif // LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZINSTRINFO_H |
394 | |