LLVM  6.0.0svn
AArch64LegalizerInfo.cpp
Go to the documentation of this file.
1 //===- AArch64LegalizerInfo.cpp ----------------------------------*- C++ -*-==//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 /// This file implements the targeting of the Machinelegalizer class for
11 /// AArch64.
12 /// \todo This should be generated by TableGen.
13 //===----------------------------------------------------------------------===//
14 
15 #include "AArch64LegalizerInfo.h"
16 #include "AArch64Subtarget.h"
22 #include "llvm/IR/DerivedTypes.h"
23 #include "llvm/IR/Type.h"
24 
25 using namespace llvm;
26 
27 /// FIXME: The following static functions are SizeChangeStrategy functions
28 /// that are meant to temporarily mimic the behaviour of the old legalization
29 /// based on doubling/halving non-legal types as closely as possible. This is
30 /// not entirly possible as only legalizing the types that are exactly a power
31 /// of 2 times the size of the legal types would require specifying all those
32 /// sizes explicitly.
33 /// In practice, not specifying those isn't a problem, and the below functions
34 /// should disappear quickly as we add support for legalizing non-power-of-2
35 /// sized types further.
36 static void
39  for (unsigned i = 0; i < v.size(); ++i) {
40  result.push_back(v[i]);
41  if (i + 1 < v[i].first && i + 1 < v.size() &&
42  v[i + 1].first != v[i].first + 1)
43  result.push_back({v[i].first + 1, LegalizerInfo::Unsupported});
44  }
45 }
46 
49  assert(v.size() >= 1);
50  assert(v[0].first > 2);
54  auto Largest = result.back().first;
55  assert(Largest + 1 < 128);
56  result.push_back({Largest + 1, LegalizerInfo::Unsupported});
57  result.push_back({128, LegalizerInfo::NarrowScalar});
58  result.push_back({129, LegalizerInfo::Unsupported});
59  return result;
60 }
61 
64  assert(v.size() >= 1);
65  assert(v[0].first > 17);
70  auto Largest = result.back().first;
71  result.push_back({Largest + 1, LegalizerInfo::Unsupported});
72  return result;
73 }
74 
77  assert(v.size() >= 1);
78  assert(v[0].first > 9);
83  auto Largest = result.back().first;
84  result.push_back({Largest + 1, LegalizerInfo::Unsupported});
85  return result;
86 }
87 
90  assert(v.size() >= 1);
91  assert(v[0].first > 17);
97  auto Largest = result.back().first;
98  result.push_back({Largest + 1, LegalizerInfo::Unsupported});
99  return result;
100 }
101 
104  assert(v.size() >= 1);
105  assert(v[0].first > 17);
111  auto Largest = result.back().first;
112  result.push_back({Largest + 1, LegalizerInfo::NarrowScalar});
113  return result;
114 }
115 
118  assert(v.size() >= 1);
119  assert(v[0].first > 33);
126  auto Largest = result.back().first;
127  result.push_back({Largest + 1, LegalizerInfo::Unsupported});
128  return result;
129 }
130 
132  using namespace TargetOpcode;
133  const LLT p0 = LLT::pointer(0, 64);
134  const LLT s1 = LLT::scalar(1);
135  const LLT s8 = LLT::scalar(8);
136  const LLT s16 = LLT::scalar(16);
137  const LLT s32 = LLT::scalar(32);
138  const LLT s64 = LLT::scalar(64);
139  const LLT s128 = LLT::scalar(128);
140  const LLT v2s32 = LLT::vector(2, 32);
141  const LLT v4s32 = LLT::vector(4, 32);
142  const LLT v2s64 = LLT::vector(2, 64);
143 
144  for (auto Ty : {p0, s1, s8, s16, s32, s64})
145  setAction({G_IMPLICIT_DEF, Ty}, Legal);
146 
147  for (auto Ty : {s16, s32, s64, p0})
148  setAction({G_PHI, Ty}, Legal);
149 
151 
152  for (auto Ty : { s32, s64 })
153  setAction({G_BSWAP, Ty}, Legal);
154 
155  for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR, G_SHL}) {
156  // These operations naturally get the right answer when used on
157  // GPR32, even if the actual type is narrower.
158  for (auto Ty : {s32, s64, v2s32, v4s32, v2s64})
159  setAction({BinOp, Ty}, Legal);
160 
161  if (BinOp != G_ADD)
164  }
165 
166  setAction({G_GEP, p0}, Legal);
167  setAction({G_GEP, 1, s64}, Legal);
168 
170 
171  setAction({G_PTR_MASK, p0}, Legal);
172 
173  for (unsigned BinOp : {G_LSHR, G_ASHR, G_SDIV, G_UDIV}) {
174  for (auto Ty : {s32, s64})
175  setAction({BinOp, Ty}, Legal);
176 
178  }
179 
180  for (unsigned BinOp : {G_SREM, G_UREM})
181  for (auto Ty : { s1, s8, s16, s32, s64 })
182  setAction({BinOp, Ty}, Lower);
183 
184  for (unsigned Op : {G_SMULO, G_UMULO}) {
185  setAction({Op, 0, s64}, Lower);
186  setAction({Op, 1, s1}, Legal);
187  }
188 
189  for (unsigned Op : {G_UADDE, G_USUBE, G_SADDO, G_SSUBO, G_SMULH, G_UMULH}) {
190  for (auto Ty : { s32, s64 })
191  setAction({Op, Ty}, Legal);
192 
193  setAction({Op, 1, s1}, Legal);
194  }
195 
196  for (unsigned BinOp : {G_FADD, G_FSUB, G_FMA, G_FMUL, G_FDIV})
197  for (auto Ty : {s32, s64})
198  setAction({BinOp, Ty}, Legal);
199 
200  for (unsigned BinOp : {G_FREM, G_FPOW}) {
201  setAction({BinOp, s32}, Libcall);
202  setAction({BinOp, s64}, Libcall);
203  }
204 
205  for (auto Ty : {s32, s64, p0}) {
206  setAction({G_INSERT, Ty}, Legal);
207  setAction({G_INSERT, 1, Ty}, Legal);
208  }
211  for (auto Ty : {s1, s8, s16}) {
212  setAction({G_INSERT, 1, Ty}, Legal);
213  // FIXME: Can't widen the sources because that violates the constraints on
214  // G_INSERT (It seems entirely reasonable that inputs shouldn't overlap).
215  }
216 
217  for (auto Ty : {s1, s8, s16, s32, s64, p0})
218  setAction({G_EXTRACT, Ty}, Legal);
219 
220  for (auto Ty : {s32, s64})
221  setAction({G_EXTRACT, 1, Ty}, Legal);
222 
223  for (unsigned MemOp : {G_LOAD, G_STORE}) {
224  for (auto Ty : {s8, s16, s32, s64, p0, v2s32})
225  setAction({MemOp, Ty}, Legal);
226 
229 
230  // And everything's fine in addrspace 0.
231  setAction({MemOp, 1, p0}, Legal);
232  }
233 
234  // Constants
235  for (auto Ty : {s32, s64}) {
236  setAction({TargetOpcode::G_CONSTANT, Ty}, Legal);
237  setAction({TargetOpcode::G_FCONSTANT, Ty}, Legal);
238  }
239 
240  setAction({G_CONSTANT, p0}, Legal);
241 
244 
245  setAction({G_ICMP, 1, s32}, Legal);
246  setAction({G_ICMP, 1, s64}, Legal);
247  setAction({G_ICMP, 1, p0}, Legal);
248 
252 
253  setAction({G_ICMP, s32}, Legal);
254  setAction({G_FCMP, s32}, Legal);
255  setAction({G_FCMP, 1, s32}, Legal);
256  setAction({G_FCMP, 1, s64}, Legal);
257 
258  // Extensions
259  for (auto Ty : { s1, s8, s16, s32, s64 }) {
260  setAction({G_ZEXT, Ty}, Legal);
261  setAction({G_SEXT, Ty}, Legal);
262  setAction({G_ANYEXT, Ty}, Legal);
263  }
264 
265  // FP conversions
266  for (auto Ty : { s16, s32 }) {
267  setAction({G_FPTRUNC, Ty}, Legal);
268  setAction({G_FPEXT, 1, Ty}, Legal);
269  }
270 
271  for (auto Ty : { s32, s64 }) {
272  setAction({G_FPTRUNC, 1, Ty}, Legal);
273  setAction({G_FPEXT, Ty}, Legal);
274  }
275 
276  // Conversions
277  for (auto Ty : { s32, s64 }) {
278  setAction({G_FPTOSI, 0, Ty}, Legal);
279  setAction({G_FPTOUI, 0, Ty}, Legal);
280  setAction({G_SITOFP, 1, Ty}, Legal);
281  setAction({G_UITOFP, 1, Ty}, Legal);
282  }
287 
288  for (auto Ty : { s32, s64 }) {
289  setAction({G_FPTOSI, 1, Ty}, Legal);
290  setAction({G_FPTOUI, 1, Ty}, Legal);
291  setAction({G_SITOFP, 0, Ty}, Legal);
292  setAction({G_UITOFP, 0, Ty}, Legal);
293  }
294 
295  // Control-flow
296  for (auto Ty : {s1, s8, s16, s32})
297  setAction({G_BRCOND, Ty}, Legal);
298  setAction({G_BRINDIRECT, p0}, Legal);
299 
300  // Select
302 
303  for (auto Ty : {s32, s64, p0})
304  setAction({G_SELECT, Ty}, Legal);
305 
306  setAction({G_SELECT, 1, s1}, Legal);
307 
308  // Pointer-handling
309  setAction({G_FRAME_INDEX, p0}, Legal);
310  setAction({G_GLOBAL_VALUE, p0}, Legal);
311 
312  for (auto Ty : {s1, s8, s16, s32, s64})
313  setAction({G_PTRTOINT, 0, Ty}, Legal);
314 
315  setAction({G_PTRTOINT, 1, p0}, Legal);
316 
317  setAction({G_INTTOPTR, 0, p0}, Legal);
318  setAction({G_INTTOPTR, 1, s64}, Legal);
319 
320  // Casts for 32 and 64-bit width type are just copies.
321  // Same for 128-bit width type, except they are on the FPR bank.
322  for (auto Ty : {s1, s8, s16, s32, s64, s128}) {
323  setAction({G_BITCAST, 0, Ty}, Legal);
324  setAction({G_BITCAST, 1, Ty}, Legal);
325  }
326 
327  // For the sake of copying bits around, the type does not really
328  // matter as long as it fits a register.
329  for (int EltSize = 8; EltSize <= 64; EltSize *= 2) {
330  setAction({G_BITCAST, 0, LLT::vector(128/EltSize, EltSize)}, Legal);
331  setAction({G_BITCAST, 1, LLT::vector(128/EltSize, EltSize)}, Legal);
332  if (EltSize >= 64)
333  continue;
334 
335  setAction({G_BITCAST, 0, LLT::vector(64/EltSize, EltSize)}, Legal);
336  setAction({G_BITCAST, 1, LLT::vector(64/EltSize, EltSize)}, Legal);
337  if (EltSize >= 32)
338  continue;
339 
340  setAction({G_BITCAST, 0, LLT::vector(32/EltSize, EltSize)}, Legal);
341  setAction({G_BITCAST, 1, LLT::vector(32/EltSize, EltSize)}, Legal);
342  }
343 
344  setAction({G_VASTART, p0}, Legal);
345 
346  // va_list must be a pointer, but most sized types are pretty easy to handle
347  // as the destination.
348  setAction({G_VAARG, 1, p0}, Legal);
349 
350  for (auto Ty : {s8, s16, s32, s64, p0})
351  setAction({G_VAARG, Ty}, Custom);
352 
353  if (ST.hasLSE()) {
354  for (auto Ty : {s8, s16, s32, s64}) {
355  setAction({G_ATOMIC_CMPXCHG_WITH_SUCCESS, Ty}, Lower);
356  setAction({G_ATOMIC_CMPXCHG, Ty}, Legal);
357  }
358  setAction({G_ATOMIC_CMPXCHG, 1, p0}, Legal);
359 
360  for (unsigned Op :
361  {G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, G_ATOMICRMW_SUB, G_ATOMICRMW_AND,
362  G_ATOMICRMW_OR, G_ATOMICRMW_XOR, G_ATOMICRMW_MIN, G_ATOMICRMW_MAX,
363  G_ATOMICRMW_UMIN, G_ATOMICRMW_UMAX}) {
364  for (auto Ty : {s8, s16, s32, s64}) {
365  setAction({Op, Ty}, Legal);
366  }
367  setAction({Op, 1, p0}, Legal);
368  }
369  }
370 
371  // Merge/Unmerge
372  for (unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES})
373  for (int Sz : {8, 16, 32, 64, 128, 192, 256, 384, 512}) {
374  LLT ScalarTy = LLT::scalar(Sz);
375  setAction({Op, ScalarTy}, Legal);
376  setAction({Op, 1, ScalarTy}, Legal);
377  if (Sz < 32)
378  continue;
379  for (int EltSize = 8; EltSize <= 64; EltSize *= 2) {
380  if (EltSize >= Sz)
381  continue;
382  LLT VecTy = LLT::vector(Sz / EltSize, EltSize);
383  setAction({Op, VecTy}, Legal);
384  setAction({Op, 1, VecTy}, Legal);
385  }
386  }
387 
388  computeTables();
389 }
390 
393  MachineIRBuilder &MIRBuilder) const {
394  switch (MI.getOpcode()) {
395  default:
396  // No idea what to do.
397  return false;
398  case TargetOpcode::G_VAARG:
399  return legalizeVaArg(MI, MRI, MIRBuilder);
400  }
401 
402  llvm_unreachable("expected switch to return");
403 }
404 
405 bool AArch64LegalizerInfo::legalizeVaArg(MachineInstr &MI,
407  MachineIRBuilder &MIRBuilder) const {
408  MIRBuilder.setInstr(MI);
409  MachineFunction &MF = MIRBuilder.getMF();
410  unsigned Align = MI.getOperand(2).getImm();
411  unsigned Dst = MI.getOperand(0).getReg();
412  unsigned ListPtr = MI.getOperand(1).getReg();
413 
414  LLT PtrTy = MRI.getType(ListPtr);
415  LLT IntPtrTy = LLT::scalar(PtrTy.getSizeInBits());
416 
417  const unsigned PtrSize = PtrTy.getSizeInBits() / 8;
418  unsigned List = MRI.createGenericVirtualRegister(PtrTy);
419  MIRBuilder.buildLoad(
420  List, ListPtr,
422  PtrSize, /* Align = */ PtrSize));
423 
424  unsigned DstPtr;
425  if (Align > PtrSize) {
426  // Realign the list to the actual required alignment.
427  auto AlignMinus1 = MIRBuilder.buildConstant(IntPtrTy, Align - 1);
428 
429  unsigned ListTmp = MRI.createGenericVirtualRegister(PtrTy);
430  MIRBuilder.buildGEP(ListTmp, List, AlignMinus1->getOperand(0).getReg());
431 
432  DstPtr = MRI.createGenericVirtualRegister(PtrTy);
433  MIRBuilder.buildPtrMask(DstPtr, ListTmp, Log2_64(Align));
434  } else
435  DstPtr = List;
436 
437  uint64_t ValSize = MRI.getType(Dst).getSizeInBits() / 8;
438  MIRBuilder.buildLoad(
439  Dst, DstPtr,
441  ValSize, std::max(Align, PtrSize)));
442 
443  unsigned SizeReg = MRI.createGenericVirtualRegister(IntPtrTy);
444  MIRBuilder.buildConstant(SizeReg, alignTo(ValSize, PtrSize));
445 
446  unsigned NewList = MRI.createGenericVirtualRegister(PtrTy);
447  MIRBuilder.buildGEP(NewList, DstPtr, SizeReg);
448 
449  MIRBuilder.buildStore(
450  NewList, ListPtr,
452  PtrSize, /* Align = */ PtrSize));
453 
454  MI.eraseFromParent();
455  return true;
456 }
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
MachineInstrBuilder buildGEP(unsigned Res, unsigned Op0, unsigned Op1)
Build and insert Res = G_GEP Op0, Op1.
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
unsigned getReg() const
getReg - Returns the register number.
uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew=0)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
Definition: MathExtras.h:677
unsigned createGenericVirtualRegister(LLT Ty)
Create and return a new generic virtual register with low-level type Ty.
MachineInstrBuilder buildStore(unsigned Val, unsigned Addr, MachineMemOperand &MMO)
Build and insert G_STORE Val, Addr, MMO.
static LegalizerInfo::SizeAndActionsVec widen_1_narrow_128_ToLargest(const LegalizerInfo::SizeAndActionsVec &v)
void eraseFromParent()
Unlink &#39;this&#39; from the containing basic block and delete it.
std::vector< SizeAndAction > SizeAndActionsVec
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:291
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, uint64_t s, unsigned base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
This file declares the targeting of the Machinelegalizer class for AArch64.
void computeTables()
Compute any ancillary tables needed to quickly decide how an operation should be handled.
MachineFunction & getMF()
Getter for the function we currently build.
static LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
static void addAndInterleaveWithUnsupported(LegalizerInfo::SizeAndActionsVec &result, const LegalizerInfo::SizeAndActionsVec &v)
FIXME: The following static functions are SizeChangeStrategy functions that are meant to temporarily ...
The target wants to do something special with this combination of operand and type.
Definition: LegalizerInfo.h:93
unsigned const MachineRegisterInfo * MRI
AArch64LegalizerInfo(const AArch64Subtarget &ST)
MachineInstrBuilder buildPtrMask(unsigned Res, unsigned Op0, uint32_t NumBits)
Build and insert Res = G_PTR_MASK Op0, NumBits.
Helper class to build MachineInstr.
static LegalizerInfo::SizeAndActionsVec widen_1_8_16_narrowToLargest(const LegalizerInfo::SizeAndActionsVec &v)
void setInstr(MachineInstr &MI)
Set the insertion point to before MI.
static LegalizerInfo::SizeAndActionsVec widen_1_8_16_32(const LegalizerInfo::SizeAndActionsVec &v)
This class contains a discriminated union of information about pointers in memory operands...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned first
The memory access writes data.
The operation should be synthesized from multiple instructions acting on a narrower scalar base-type...
Definition: LegalizerInfo.h:64
The operation should be implemented as a call to some kind of runtime support library.
Definition: LegalizerInfo.h:89
bool legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &MIRBuilder) const override
The operation should be implemented in terms of a wider scalar base-type.
Definition: LegalizerInfo.h:69
unsigned getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
int64_t getImm() const
This file declares the MachineIRBuilder class.
The operation itself must be expressed in terms of simpler actions on this target.
Definition: LegalizerInfo.h:84
The operation is expected to be selectable directly by the target, and no transformation is necessary...
Definition: LegalizerInfo.h:59
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
The memory access reads data.
static LegalizerInfo::SizeAndActionsVec widen_1_8(const LegalizerInfo::SizeAndActionsVec &v)
Representation of each machine instruction.
Definition: MachineInstr.h:60
MachineInstrBuilder buildConstant(unsigned Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
const NodeList & List
Definition: RDFGraph.cpp:210
LLT getType(unsigned VReg) const
Get the low-level type of VReg or LLT{} if VReg is not a generic (target independent) virtual registe...
void setLegalizeScalarToDifferentSizeStrategy(const unsigned Opcode, const unsigned TypeIdx, SizeChangeStrategy S)
The setAction calls record the non-size-changing legalization actions to take on specificly-sized typ...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static LegalizerInfo::SizeAndActionsVec widen_1_8_16(const LegalizerInfo::SizeAndActionsVec &v)
static LLT pointer(uint16_t AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space (defaulting to 0).
This operation is completely unsupported on the target.
Definition: LegalizerInfo.h:97
MachineInstrBuilder buildLoad(unsigned Res, unsigned Addr, MachineMemOperand &MMO)
Build and insert Res = G_LOAD Addr, MMO.
IRTranslator LLVM IR MI
static LegalizerInfo::SizeAndActionsVec widen_16(const LegalizerInfo::SizeAndActionsVec &v)
static LLT vector(uint16_t NumElements, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:296
void setAction(const InstrAspect &Aspect, LegalizeAction Action)
More friendly way to set an action for common types that have an LLT representation.
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition: MathExtras.h:537