blob: 8b033ee63766077334de2153ee2abf54a6d1902b [file] [log] [blame]
Eugene Zelenko96d933d2017-07-25 23:51:02 +00001//===- AArch6464FastISel.cpp - AArch64 FastISel implementation ------------===//
Tim Northover3b0846e2014-05-24 12:50:23 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Tim Northover3b0846e2014-05-24 12:50:23 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the AArch64-specific support for the FastISel class. Some
10// of the target-specific code is generated by tablegen in the file
11// AArch64GenFastISel.inc, which is #included here.
12//
13//===----------------------------------------------------------------------===//
14
15#include "AArch64.h"
Tim Northover3c55cca2014-11-27 21:02:42 +000016#include "AArch64CallingConvention.h"
Eugene Zelenko11f69072017-01-25 00:29:26 +000017#include "AArch64RegisterInfo.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000018#include "AArch64Subtarget.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000019#include "MCTargetDesc/AArch64AddressingModes.h"
Eugene Zelenko11f69072017-01-25 00:29:26 +000020#include "Utils/AArch64BaseInfo.h"
21#include "llvm/ADT/APFloat.h"
22#include "llvm/ADT/APInt.h"
23#include "llvm/ADT/DenseMap.h"
24#include "llvm/ADT/SmallVector.h"
Juergen Ributzka50a40052014-08-01 18:39:24 +000025#include "llvm/Analysis/BranchProbabilityInfo.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000026#include "llvm/CodeGen/CallingConvLower.h"
27#include "llvm/CodeGen/FastISel.h"
28#include "llvm/CodeGen/FunctionLoweringInfo.h"
Eugene Zelenko11f69072017-01-25 00:29:26 +000029#include "llvm/CodeGen/ISDOpcodes.h"
30#include "llvm/CodeGen/MachineBasicBlock.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000031#include "llvm/CodeGen/MachineConstantPool.h"
32#include "llvm/CodeGen/MachineFrameInfo.h"
Eugene Zelenko11f69072017-01-25 00:29:26 +000033#include "llvm/CodeGen/MachineInstr.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000034#include "llvm/CodeGen/MachineInstrBuilder.h"
Eugene Zelenko11f69072017-01-25 00:29:26 +000035#include "llvm/CodeGen/MachineMemOperand.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000036#include "llvm/CodeGen/MachineRegisterInfo.h"
Eugene Zelenko11f69072017-01-25 00:29:26 +000037#include "llvm/CodeGen/RuntimeLibcalls.h"
Craig Topper2fa14362018-03-29 17:21:10 +000038#include "llvm/CodeGen/ValueTypes.h"
Eugene Zelenko11f69072017-01-25 00:29:26 +000039#include "llvm/IR/Argument.h"
40#include "llvm/IR/Attributes.h"
41#include "llvm/IR/BasicBlock.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000042#include "llvm/IR/CallingConv.h"
Eugene Zelenko11f69072017-01-25 00:29:26 +000043#include "llvm/IR/Constant.h"
44#include "llvm/IR/Constants.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000045#include "llvm/IR/DataLayout.h"
46#include "llvm/IR/DerivedTypes.h"
47#include "llvm/IR/Function.h"
48#include "llvm/IR/GetElementPtrTypeIterator.h"
Eugene Zelenko11f69072017-01-25 00:29:26 +000049#include "llvm/IR/GlobalValue.h"
50#include "llvm/IR/InstrTypes.h"
51#include "llvm/IR/Instruction.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000052#include "llvm/IR/Instructions.h"
53#include "llvm/IR/IntrinsicInst.h"
Eugene Zelenko96d933d2017-07-25 23:51:02 +000054#include "llvm/IR/Intrinsics.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000055#include "llvm/IR/Operator.h"
Eugene Zelenko11f69072017-01-25 00:29:26 +000056#include "llvm/IR/Type.h"
57#include "llvm/IR/User.h"
58#include "llvm/IR/Value.h"
59#include "llvm/MC/MCInstrDesc.h"
60#include "llvm/MC/MCRegisterInfo.h"
Rafael Espindolace4c2bc2015-06-23 12:21:54 +000061#include "llvm/MC/MCSymbol.h"
Eugene Zelenko11f69072017-01-25 00:29:26 +000062#include "llvm/Support/AtomicOrdering.h"
63#include "llvm/Support/Casting.h"
64#include "llvm/Support/CodeGen.h"
Eugene Zelenko96d933d2017-07-25 23:51:02 +000065#include "llvm/Support/Compiler.h"
Eugene Zelenko11f69072017-01-25 00:29:26 +000066#include "llvm/Support/ErrorHandling.h"
David Blaikie13e77db2018-03-23 23:58:25 +000067#include "llvm/Support/MachineValueType.h"
Eugene Zelenko11f69072017-01-25 00:29:26 +000068#include "llvm/Support/MathExtras.h"
69#include <algorithm>
70#include <cassert>
71#include <cstdint>
72#include <iterator>
73#include <utility>
74
Tim Northover3b0846e2014-05-24 12:50:23 +000075using namespace llvm;
76
77namespace {
78
Juergen Ributzkacbe802e2014-09-15 22:33:11 +000079class AArch64FastISel final : public FastISel {
Tim Northover3b0846e2014-05-24 12:50:23 +000080 class Address {
81 public:
Eugene Zelenko96d933d2017-07-25 23:51:02 +000082 using BaseKind = enum {
Tim Northover3b0846e2014-05-24 12:50:23 +000083 RegBase,
84 FrameIndexBase
Eugene Zelenko96d933d2017-07-25 23:51:02 +000085 };
Tim Northover3b0846e2014-05-24 12:50:23 +000086
87 private:
Eugene Zelenko11f69072017-01-25 00:29:26 +000088 BaseKind Kind = RegBase;
89 AArch64_AM::ShiftExtendType ExtType = AArch64_AM::InvalidShiftExtend;
Tim Northover3b0846e2014-05-24 12:50:23 +000090 union {
91 unsigned Reg;
92 int FI;
93 } Base;
Eugene Zelenko11f69072017-01-25 00:29:26 +000094 unsigned OffsetReg = 0;
95 unsigned Shift = 0;
96 int64_t Offset = 0;
97 const GlobalValue *GV = nullptr;
Tim Northover3b0846e2014-05-24 12:50:23 +000098
99 public:
Eugene Zelenko11f69072017-01-25 00:29:26 +0000100 Address() { Base.Reg = 0; }
101
Tim Northover3b0846e2014-05-24 12:50:23 +0000102 void setKind(BaseKind K) { Kind = K; }
103 BaseKind getKind() const { return Kind; }
Juergen Ributzkab46ea082014-08-19 19:44:17 +0000104 void setExtendType(AArch64_AM::ShiftExtendType E) { ExtType = E; }
105 AArch64_AM::ShiftExtendType getExtendType() const { return ExtType; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000106 bool isRegBase() const { return Kind == RegBase; }
107 bool isFIBase() const { return Kind == FrameIndexBase; }
Eugene Zelenko11f69072017-01-25 00:29:26 +0000108
Tim Northover3b0846e2014-05-24 12:50:23 +0000109 void setReg(unsigned Reg) {
110 assert(isRegBase() && "Invalid base register access!");
111 Base.Reg = Reg;
112 }
Eugene Zelenko11f69072017-01-25 00:29:26 +0000113
Tim Northover3b0846e2014-05-24 12:50:23 +0000114 unsigned getReg() const {
115 assert(isRegBase() && "Invalid base register access!");
116 return Base.Reg;
117 }
Eugene Zelenko11f69072017-01-25 00:29:26 +0000118
Juergen Ributzkab46ea082014-08-19 19:44:17 +0000119 void setOffsetReg(unsigned Reg) {
Juergen Ributzkab46ea082014-08-19 19:44:17 +0000120 OffsetReg = Reg;
121 }
Eugene Zelenko11f69072017-01-25 00:29:26 +0000122
Juergen Ributzkab46ea082014-08-19 19:44:17 +0000123 unsigned getOffsetReg() const {
Juergen Ributzkab46ea082014-08-19 19:44:17 +0000124 return OffsetReg;
125 }
Eugene Zelenko11f69072017-01-25 00:29:26 +0000126
Tim Northover3b0846e2014-05-24 12:50:23 +0000127 void setFI(unsigned FI) {
128 assert(isFIBase() && "Invalid base frame index access!");
129 Base.FI = FI;
130 }
Eugene Zelenko11f69072017-01-25 00:29:26 +0000131
Tim Northover3b0846e2014-05-24 12:50:23 +0000132 unsigned getFI() const {
133 assert(isFIBase() && "Invalid base frame index access!");
134 return Base.FI;
135 }
Eugene Zelenko11f69072017-01-25 00:29:26 +0000136
Tim Northover3b0846e2014-05-24 12:50:23 +0000137 void setOffset(int64_t O) { Offset = O; }
138 int64_t getOffset() { return Offset; }
Juergen Ributzkab46ea082014-08-19 19:44:17 +0000139 void setShift(unsigned S) { Shift = S; }
140 unsigned getShift() { return Shift; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000141
Juergen Ributzka052e6c22014-07-31 04:10:40 +0000142 void setGlobalValue(const GlobalValue *G) { GV = G; }
143 const GlobalValue *getGlobalValue() { return GV; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000144 };
145
146 /// Subtarget - Keep a pointer to the AArch64Subtarget around so that we can
147 /// make the right decision when generating code for different targets.
148 const AArch64Subtarget *Subtarget;
149 LLVMContext *Context;
150
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +0000151 bool fastLowerArguments() override;
152 bool fastLowerCall(CallLoweringInfo &CLI) override;
153 bool fastLowerIntrinsicCall(const IntrinsicInst *II) override;
Juergen Ributzka2581fa52014-07-22 23:14:58 +0000154
Tim Northover3b0846e2014-05-24 12:50:23 +0000155private:
156 // Selection routines.
Juergen Ributzkaa1148b22014-09-03 01:38:36 +0000157 bool selectAddSub(const Instruction *I);
Juergen Ributzkae1779e22014-09-15 21:27:56 +0000158 bool selectLogicalOp(const Instruction *I);
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000159 bool selectLoad(const Instruction *I);
160 bool selectStore(const Instruction *I);
161 bool selectBranch(const Instruction *I);
162 bool selectIndirectBr(const Instruction *I);
163 bool selectCmp(const Instruction *I);
164 bool selectSelect(const Instruction *I);
165 bool selectFPExt(const Instruction *I);
166 bool selectFPTrunc(const Instruction *I);
167 bool selectFPToInt(const Instruction *I, bool Signed);
168 bool selectIntToFP(const Instruction *I, bool Signed);
169 bool selectRem(const Instruction *I, unsigned ISDOpcode);
170 bool selectRet(const Instruction *I);
171 bool selectTrunc(const Instruction *I);
172 bool selectIntExt(const Instruction *I);
173 bool selectMul(const Instruction *I);
174 bool selectShift(const Instruction *I);
175 bool selectBitCast(const Instruction *I);
Juergen Ributzkaafa034f2014-09-15 22:07:49 +0000176 bool selectFRem(const Instruction *I);
Juergen Ributzkaf6430312014-09-17 21:55:55 +0000177 bool selectSDiv(const Instruction *I);
Juergen Ributzkaf82c9872014-10-15 18:58:07 +0000178 bool selectGetElementPtr(const Instruction *I);
Ahmed Bougachaa0cdd792016-07-20 21:12:32 +0000179 bool selectAtomicCmpXchg(const AtomicCmpXchgInst *I);
Tim Northover3b0846e2014-05-24 12:50:23 +0000180
181 // Utility helper routines.
182 bool isTypeLegal(Type *Ty, MVT &VT);
Juergen Ributzka6127b192014-09-15 21:27:54 +0000183 bool isTypeSupported(Type *Ty, MVT &VT, bool IsVectorAllowed = false);
Juergen Ributzka77bc09f2014-08-29 00:19:21 +0000184 bool isValueAvailable(const Value *V) const;
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000185 bool computeAddress(const Value *Obj, Address &Addr, Type *Ty = nullptr);
186 bool computeCallAddress(const Value *V, Address &Addr);
187 bool simplifyAddress(Address &Addr, MVT VT);
188 void addLoadStoreOperands(Address &Addr, const MachineInstrBuilder &MIB,
Justin Lebar0af80cd2016-07-15 18:26:59 +0000189 MachineMemOperand::Flags Flags,
190 unsigned ScaleFactor, MachineMemOperand *MMO);
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000191 bool isMemCpySmall(uint64_t Len, unsigned Alignment);
192 bool tryEmitSmallMemCpy(Address Dest, Address Src, uint64_t Len,
Tim Northover3b0846e2014-05-24 12:50:23 +0000193 unsigned Alignment);
Juergen Ributzkaad2109a2014-07-30 22:04:34 +0000194 bool foldXALUIntrinsic(AArch64CC::CondCode &CC, const Instruction *I,
195 const Value *Cond);
Juergen Ributzkacd11a282014-10-14 20:36:02 +0000196 bool optimizeIntExtLoad(const Instruction *I, MVT RetVT, MVT SrcVT);
Juergen Ributzka957a1452014-11-13 00:36:46 +0000197 bool optimizeSelect(const SelectInst *SI);
Juergen Ributzka0af310d2014-11-13 20:50:44 +0000198 std::pair<unsigned, bool> getRegForGEPIndex(const Value *Idx);
Juergen Ributzkaad2109a2014-07-30 22:04:34 +0000199
Juergen Ributzkac0886dd2014-08-19 22:29:55 +0000200 // Emit helper routines.
Juergen Ributzkaa1148b22014-09-03 01:38:36 +0000201 unsigned emitAddSub(bool UseAdd, MVT RetVT, const Value *LHS,
202 const Value *RHS, bool SetFlags = false,
203 bool WantResult = true, bool IsZExt = false);
204 unsigned emitAddSub_rr(bool UseAdd, MVT RetVT, unsigned LHSReg,
205 bool LHSIsKill, unsigned RHSReg, bool RHSIsKill,
206 bool SetFlags = false, bool WantResult = true);
207 unsigned emitAddSub_ri(bool UseAdd, MVT RetVT, unsigned LHSReg,
208 bool LHSIsKill, uint64_t Imm, bool SetFlags = false,
209 bool WantResult = true);
Juergen Ributzkafb506a42014-08-27 00:58:30 +0000210 unsigned emitAddSub_rs(bool UseAdd, MVT RetVT, unsigned LHSReg,
211 bool LHSIsKill, unsigned RHSReg, bool RHSIsKill,
212 AArch64_AM::ShiftExtendType ShiftType,
Juergen Ributzkaa1148b22014-09-03 01:38:36 +0000213 uint64_t ShiftImm, bool SetFlags = false,
214 bool WantResult = true);
Juergen Ributzkafb506a42014-08-27 00:58:30 +0000215 unsigned emitAddSub_rx(bool UseAdd, MVT RetVT, unsigned LHSReg,
216 bool LHSIsKill, unsigned RHSReg, bool RHSIsKill,
217 AArch64_AM::ShiftExtendType ExtType,
Juergen Ributzkaa1148b22014-09-03 01:38:36 +0000218 uint64_t ShiftImm, bool SetFlags = false,
219 bool WantResult = true);
Juergen Ributzkac0886dd2014-08-19 22:29:55 +0000220
Tim Northover3b0846e2014-05-24 12:50:23 +0000221 // Emit functions.
Juergen Ributzkac110c0b2014-09-30 19:59:35 +0000222 bool emitCompareAndBranch(const BranchInst *BI);
Juergen Ributzkac0886dd2014-08-19 22:29:55 +0000223 bool emitCmp(const Value *LHS, const Value *RHS, bool IsZExt);
224 bool emitICmp(MVT RetVT, const Value *LHS, const Value *RHS, bool IsZExt);
225 bool emitICmp_ri(MVT RetVT, unsigned LHSReg, bool LHSIsKill, uint64_t Imm);
226 bool emitFCmp(MVT RetVT, const Value *LHS, const Value *RHS);
Juergen Ributzkacd11a282014-10-14 20:36:02 +0000227 unsigned emitLoad(MVT VT, MVT ResultVT, Address Addr, bool WantZExt = true,
228 MachineMemOperand *MMO = nullptr);
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000229 bool emitStore(MVT VT, unsigned SrcReg, Address Addr,
Juergen Ributzkab46ea082014-08-19 19:44:17 +0000230 MachineMemOperand *MMO = nullptr);
Ahmed Bougachab0674d12016-07-20 21:12:27 +0000231 bool emitStoreRelease(MVT VT, unsigned SrcReg, unsigned AddrReg,
232 MachineMemOperand *MMO = nullptr);
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000233 unsigned emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, bool isZExt);
234 unsigned emiti1Ext(unsigned SrcReg, MVT DestVT, bool isZExt);
Juergen Ributzkaa1148b22014-09-03 01:38:36 +0000235 unsigned emitAdd(MVT RetVT, const Value *LHS, const Value *RHS,
236 bool SetFlags = false, bool WantResult = true,
237 bool IsZExt = false);
Juergen Ributzka6780f0f2014-10-15 18:58:02 +0000238 unsigned emitAdd_ri_(MVT VT, unsigned Op0, bool Op0IsKill, int64_t Imm);
Juergen Ributzkaa1148b22014-09-03 01:38:36 +0000239 unsigned emitSub(MVT RetVT, const Value *LHS, const Value *RHS,
240 bool SetFlags = false, bool WantResult = true,
241 bool IsZExt = false);
Juergen Ributzkac0886dd2014-08-19 22:29:55 +0000242 unsigned emitSubs_rr(MVT RetVT, unsigned LHSReg, bool LHSIsKill,
243 unsigned RHSReg, bool RHSIsKill, bool WantResult = true);
244 unsigned emitSubs_rs(MVT RetVT, unsigned LHSReg, bool LHSIsKill,
245 unsigned RHSReg, bool RHSIsKill,
246 AArch64_AM::ShiftExtendType ShiftType, uint64_t ShiftImm,
247 bool WantResult = true);
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +0000248 unsigned emitLogicalOp(unsigned ISDOpc, MVT RetVT, const Value *LHS,
249 const Value *RHS);
250 unsigned emitLogicalOp_ri(unsigned ISDOpc, MVT RetVT, unsigned LHSReg,
251 bool LHSIsKill, uint64_t Imm);
252 unsigned emitLogicalOp_rs(unsigned ISDOpc, MVT RetVT, unsigned LHSReg,
253 bool LHSIsKill, unsigned RHSReg, bool RHSIsKill,
254 uint64_t ShiftImm);
255 unsigned emitAnd_ri(MVT RetVT, unsigned LHSReg, bool LHSIsKill, uint64_t Imm);
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000256 unsigned emitMul_rr(MVT RetVT, unsigned Op0, bool Op0IsKill,
257 unsigned Op1, bool Op1IsKill);
258 unsigned emitSMULL_rr(MVT RetVT, unsigned Op0, bool Op0IsKill,
259 unsigned Op1, bool Op1IsKill);
260 unsigned emitUMULL_rr(MVT RetVT, unsigned Op0, bool Op0IsKill,
261 unsigned Op1, bool Op1IsKill);
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +0000262 unsigned emitLSL_rr(MVT RetVT, unsigned Op0Reg, bool Op0IsKill,
263 unsigned Op1Reg, bool Op1IsKill);
Juergen Ributzka99dd30f2014-08-27 00:58:26 +0000264 unsigned emitLSL_ri(MVT RetVT, MVT SrcVT, unsigned Op0Reg, bool Op0IsKill,
265 uint64_t Imm, bool IsZExt = true);
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +0000266 unsigned emitLSR_rr(MVT RetVT, unsigned Op0Reg, bool Op0IsKill,
267 unsigned Op1Reg, bool Op1IsKill);
Juergen Ributzka99dd30f2014-08-27 00:58:26 +0000268 unsigned emitLSR_ri(MVT RetVT, MVT SrcVT, unsigned Op0Reg, bool Op0IsKill,
269 uint64_t Imm, bool IsZExt = true);
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +0000270 unsigned emitASR_rr(MVT RetVT, unsigned Op0Reg, bool Op0IsKill,
271 unsigned Op1Reg, bool Op1IsKill);
Juergen Ributzka99dd30f2014-08-27 00:58:26 +0000272 unsigned emitASR_ri(MVT RetVT, MVT SrcVT, unsigned Op0Reg, bool Op0IsKill,
273 uint64_t Imm, bool IsZExt = false);
Tim Northover3b0846e2014-05-24 12:50:23 +0000274
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000275 unsigned materializeInt(const ConstantInt *CI, MVT VT);
276 unsigned materializeFP(const ConstantFP *CFP, MVT VT);
277 unsigned materializeGV(const GlobalValue *GV);
Tim Northover3b0846e2014-05-24 12:50:23 +0000278
279 // Call handling routines.
280private:
281 CCAssignFn *CCAssignFnForCall(CallingConv::ID CC) const;
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000282 bool processCallArgs(CallLoweringInfo &CLI, SmallVectorImpl<MVT> &ArgVTs,
Tim Northover3b0846e2014-05-24 12:50:23 +0000283 unsigned &NumBytes);
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000284 bool finishCall(CallLoweringInfo &CLI, MVT RetVT, unsigned NumBytes);
Tim Northover3b0846e2014-05-24 12:50:23 +0000285
286public:
287 // Backend specific FastISel code.
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +0000288 unsigned fastMaterializeAlloca(const AllocaInst *AI) override;
289 unsigned fastMaterializeConstant(const Constant *C) override;
290 unsigned fastMaterializeFloatZero(const ConstantFP* CF) override;
Tim Northover3b0846e2014-05-24 12:50:23 +0000291
Juergen Ributzkadbe9e172014-09-02 21:32:54 +0000292 explicit AArch64FastISel(FunctionLoweringInfo &FuncInfo,
Eric Christopher125898a2015-01-30 01:10:24 +0000293 const TargetLibraryInfo *LibInfo)
Juergen Ributzkadbe9e172014-09-02 21:32:54 +0000294 : FastISel(FuncInfo, LibInfo, /*SkipTargetIndependentISel=*/true) {
Eric Christopher125898a2015-01-30 01:10:24 +0000295 Subtarget =
296 &static_cast<const AArch64Subtarget &>(FuncInfo.MF->getSubtarget());
Juergen Ributzkadbe9e172014-09-02 21:32:54 +0000297 Context = &FuncInfo.Fn->getContext();
Tim Northover3b0846e2014-05-24 12:50:23 +0000298 }
299
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +0000300 bool fastSelectInstruction(const Instruction *I) override;
Tim Northover3b0846e2014-05-24 12:50:23 +0000301
302#include "AArch64GenFastISel.inc"
303};
304
305} // end anonymous namespace
306
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000307/// Check if the sign-/zero-extend will be a noop.
Juergen Ributzka6ac12432014-09-30 00:49:58 +0000308static bool isIntExtFree(const Instruction *I) {
309 assert((isa<ZExtInst>(I) || isa<SExtInst>(I)) &&
310 "Unexpected integer extend instruction.");
Juergen Ributzka42bf6652014-10-07 03:39:59 +0000311 assert(!I->getType()->isVectorTy() && I->getType()->isIntegerTy() &&
312 "Unexpected value type.");
Juergen Ributzka6ac12432014-09-30 00:49:58 +0000313 bool IsZExt = isa<ZExtInst>(I);
314
315 if (const auto *LI = dyn_cast<LoadInst>(I->getOperand(0)))
316 if (LI->hasOneUse())
317 return true;
318
319 if (const auto *Arg = dyn_cast<Argument>(I->getOperand(0)))
320 if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr()))
321 return true;
322
323 return false;
324}
325
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000326/// Determine the implicit scale factor that is applied by a memory
Juergen Ributzka0616d9d2014-09-30 00:49:54 +0000327/// operation for a given value type.
328static unsigned getImplicitScaleFactor(MVT VT) {
329 switch (VT.SimpleTy) {
330 default:
331 return 0; // invalid
332 case MVT::i1: // fall-through
333 case MVT::i8:
334 return 1;
335 case MVT::i16:
336 return 2;
337 case MVT::i32: // fall-through
338 case MVT::f32:
339 return 4;
340 case MVT::i64: // fall-through
341 case MVT::f64:
342 return 8;
343 }
344}
345
Tim Northover3b0846e2014-05-24 12:50:23 +0000346CCAssignFn *AArch64FastISel::CCAssignFnForCall(CallingConv::ID CC) const {
347 if (CC == CallingConv::WebKit_JS)
348 return CC_AArch64_WebKit_JS;
Greg Fitzgeraldfa78d082015-01-19 17:40:05 +0000349 if (CC == CallingConv::GHC)
350 return CC_AArch64_GHC;
Tim Northover3b0846e2014-05-24 12:50:23 +0000351 return Subtarget->isTargetDarwin() ? CC_AArch64_DarwinPCS : CC_AArch64_AAPCS;
352}
353
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +0000354unsigned AArch64FastISel::fastMaterializeAlloca(const AllocaInst *AI) {
Mehdi Amini44ede332015-07-09 02:09:04 +0000355 assert(TLI.getValueType(DL, AI->getType(), true) == MVT::i64 &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000356 "Alloca should always return a pointer.");
357
358 // Don't handle dynamic allocas.
359 if (!FuncInfo.StaticAllocaMap.count(AI))
360 return 0;
361
362 DenseMap<const AllocaInst *, int>::iterator SI =
363 FuncInfo.StaticAllocaMap.find(AI);
364
365 if (SI != FuncInfo.StaticAllocaMap.end()) {
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +0000366 unsigned ResultReg = createResultReg(&AArch64::GPR64spRegClass);
Tim Northover3b0846e2014-05-24 12:50:23 +0000367 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::ADDXri),
368 ResultReg)
369 .addFrameIndex(SI->second)
370 .addImm(0)
371 .addImm(0);
372 return ResultReg;
373 }
374
375 return 0;
376}
377
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000378unsigned AArch64FastISel::materializeInt(const ConstantInt *CI, MVT VT) {
Juergen Ributzka6bca9862014-08-15 18:55:52 +0000379 if (VT > MVT::i64)
380 return 0;
Juergen Ributzka7e23f772014-08-19 19:44:02 +0000381
382 if (!CI->isZero())
Juergen Ributzka88e32512014-09-03 20:56:59 +0000383 return fastEmit_i(VT, VT, ISD::Constant, CI->getZExtValue());
Juergen Ributzka7e23f772014-08-19 19:44:02 +0000384
385 // Create a copy from the zero register to materialize a "0" value.
386 const TargetRegisterClass *RC = (VT == MVT::i64) ? &AArch64::GPR64RegClass
387 : &AArch64::GPR32RegClass;
388 unsigned ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
389 unsigned ResultReg = createResultReg(RC);
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +0000390 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(TargetOpcode::COPY),
391 ResultReg).addReg(ZeroReg, getKillRegState(true));
Juergen Ributzka7e23f772014-08-19 19:44:02 +0000392 return ResultReg;
Juergen Ributzka6bca9862014-08-15 18:55:52 +0000393}
394
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000395unsigned AArch64FastISel::materializeFP(const ConstantFP *CFP, MVT VT) {
Juergen Ributzka1912e242014-08-25 19:58:05 +0000396 // Positive zero (+0.0) has to be materialized with a fmov from the zero
397 // register, because the immediate version of fmov cannot encode zero.
398 if (CFP->isNullValue())
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +0000399 return fastMaterializeFloatZero(CFP);
Juergen Ributzka1912e242014-08-25 19:58:05 +0000400
Tim Northover3b0846e2014-05-24 12:50:23 +0000401 if (VT != MVT::f32 && VT != MVT::f64)
402 return 0;
403
404 const APFloat Val = CFP->getValueAPF();
Juergen Ributzka6bca9862014-08-15 18:55:52 +0000405 bool Is64Bit = (VT == MVT::f64);
Tim Northover3b0846e2014-05-24 12:50:23 +0000406 // This checks to see if we can use FMOV instructions to materialize
407 // a constant, otherwise we have to materialize via the constant pool.
Adhemerval Zanellab3ccc552019-02-01 12:26:06 +0000408 int Imm =
409 Is64Bit ? AArch64_AM::getFP64Imm(Val) : AArch64_AM::getFP32Imm(Val);
410 if (Imm != -1) {
Juergen Ributzka6bca9862014-08-15 18:55:52 +0000411 unsigned Opc = Is64Bit ? AArch64::FMOVDi : AArch64::FMOVSi;
Juergen Ributzka88e32512014-09-03 20:56:59 +0000412 return fastEmitInst_i(Opc, TLI.getRegClassFor(VT), Imm);
Tim Northover3b0846e2014-05-24 12:50:23 +0000413 }
414
Juergen Ributzka23266502014-12-10 19:43:32 +0000415 // For the MachO large code model materialize the FP constant in code.
416 if (Subtarget->isTargetMachO() && TM.getCodeModel() == CodeModel::Large) {
417 unsigned Opc1 = Is64Bit ? AArch64::MOVi64imm : AArch64::MOVi32imm;
418 const TargetRegisterClass *RC = Is64Bit ?
419 &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
420
421 unsigned TmpReg = createResultReg(RC);
422 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc1), TmpReg)
423 .addImm(CFP->getValueAPF().bitcastToAPInt().getZExtValue());
424
425 unsigned ResultReg = createResultReg(TLI.getRegClassFor(VT));
426 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
427 TII.get(TargetOpcode::COPY), ResultReg)
428 .addReg(TmpReg, getKillRegState(true));
429
430 return ResultReg;
431 }
432
Tim Northover3b0846e2014-05-24 12:50:23 +0000433 // Materialize via constant pool. MachineConstantPool wants an explicit
434 // alignment.
435 unsigned Align = DL.getPrefTypeAlignment(CFP->getType());
436 if (Align == 0)
437 Align = DL.getTypeAllocSize(CFP->getType());
438
Juergen Ributzka6bca9862014-08-15 18:55:52 +0000439 unsigned CPI = MCP.getConstantPoolIndex(cast<Constant>(CFP), Align);
Tim Northover3b0846e2014-05-24 12:50:23 +0000440 unsigned ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
441 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::ADRP),
Juergen Ributzka1912e242014-08-25 19:58:05 +0000442 ADRPReg).addConstantPoolIndex(CPI, 0, AArch64II::MO_PAGE);
Tim Northover3b0846e2014-05-24 12:50:23 +0000443
Juergen Ributzka6bca9862014-08-15 18:55:52 +0000444 unsigned Opc = Is64Bit ? AArch64::LDRDui : AArch64::LDRSui;
Tim Northover3b0846e2014-05-24 12:50:23 +0000445 unsigned ResultReg = createResultReg(TLI.getRegClassFor(VT));
446 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
Juergen Ributzka1912e242014-08-25 19:58:05 +0000447 .addReg(ADRPReg)
448 .addConstantPoolIndex(CPI, 0, AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000449 return ResultReg;
450}
451
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000452unsigned AArch64FastISel::materializeGV(const GlobalValue *GV) {
Rafael Espindola59f7eba2014-05-28 18:15:43 +0000453 // We can't handle thread-local variables quickly yet.
454 if (GV->isThreadLocal())
455 return 0;
Tim Northover3b0846e2014-05-24 12:50:23 +0000456
Tim Northover391f93a2014-05-24 19:45:41 +0000457 // MachO still uses GOT for large code-model accesses, but ELF requires
458 // movz/movk sequences, which FastISel doesn't handle yet.
Petr Hosek9eb0a1e2017-04-04 19:51:53 +0000459 if (!Subtarget->useSmallAddressing() && !Subtarget->isTargetMachO())
Tim Northover391f93a2014-05-24 19:45:41 +0000460 return 0;
461
Tim Northover3b0846e2014-05-24 12:50:23 +0000462 unsigned char OpFlags = Subtarget->ClassifyGlobalReference(GV, TM);
463
Mehdi Amini44ede332015-07-09 02:09:04 +0000464 EVT DestEVT = TLI.getValueType(DL, GV->getType(), true);
Tim Northover3b0846e2014-05-24 12:50:23 +0000465 if (!DestEVT.isSimple())
466 return 0;
467
468 unsigned ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
469 unsigned ResultReg;
470
471 if (OpFlags & AArch64II::MO_GOT) {
472 // ADRP + LDRX
473 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::ADRP),
474 ADRPReg)
Martin Storsjo708498a2018-01-30 19:50:51 +0000475 .addGlobalAddress(GV, 0, AArch64II::MO_PAGE | OpFlags);
Tim Northover3b0846e2014-05-24 12:50:23 +0000476
477 ResultReg = createResultReg(&AArch64::GPR64RegClass);
478 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::LDRXui),
479 ResultReg)
Martin Storsjo708498a2018-01-30 19:50:51 +0000480 .addReg(ADRPReg)
481 .addGlobalAddress(GV, 0,
482 AArch64II::MO_PAGEOFF | AArch64II::MO_NC | OpFlags);
Tim Northover3b0846e2014-05-24 12:50:23 +0000483 } else {
484 // ADRP + ADDX
485 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::ADRP),
Juergen Ributzka6bca9862014-08-15 18:55:52 +0000486 ADRPReg)
Martin Storsjo708498a2018-01-30 19:50:51 +0000487 .addGlobalAddress(GV, 0, AArch64II::MO_PAGE | OpFlags);
Tim Northover3b0846e2014-05-24 12:50:23 +0000488
489 ResultReg = createResultReg(&AArch64::GPR64spRegClass);
490 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::ADDXri),
491 ResultReg)
Martin Storsjo708498a2018-01-30 19:50:51 +0000492 .addReg(ADRPReg)
493 .addGlobalAddress(GV, 0,
494 AArch64II::MO_PAGEOFF | AArch64II::MO_NC | OpFlags)
495 .addImm(0);
Tim Northover3b0846e2014-05-24 12:50:23 +0000496 }
497 return ResultReg;
498}
499
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +0000500unsigned AArch64FastISel::fastMaterializeConstant(const Constant *C) {
Mehdi Amini44ede332015-07-09 02:09:04 +0000501 EVT CEVT = TLI.getValueType(DL, C->getType(), true);
Tim Northover3b0846e2014-05-24 12:50:23 +0000502
503 // Only handle simple types.
504 if (!CEVT.isSimple())
505 return 0;
506 MVT VT = CEVT.getSimpleVT();
507
Juergen Ributzka6bca9862014-08-15 18:55:52 +0000508 if (const auto *CI = dyn_cast<ConstantInt>(C))
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000509 return materializeInt(CI, VT);
Juergen Ributzka6bca9862014-08-15 18:55:52 +0000510 else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C))
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000511 return materializeFP(CFP, VT);
Tim Northover3b0846e2014-05-24 12:50:23 +0000512 else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000513 return materializeGV(GV);
Tim Northover3b0846e2014-05-24 12:50:23 +0000514
515 return 0;
516}
517
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +0000518unsigned AArch64FastISel::fastMaterializeFloatZero(const ConstantFP* CFP) {
Juergen Ributzka1912e242014-08-25 19:58:05 +0000519 assert(CFP->isNullValue() &&
520 "Floating-point constant is not a positive zero.");
521 MVT VT;
522 if (!isTypeLegal(CFP->getType(), VT))
523 return 0;
524
525 if (VT != MVT::f32 && VT != MVT::f64)
526 return 0;
527
528 bool Is64Bit = (VT == MVT::f64);
529 unsigned ZReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
530 unsigned Opc = Is64Bit ? AArch64::FMOVXDr : AArch64::FMOVWSr;
Juergen Ributzka88e32512014-09-03 20:56:59 +0000531 return fastEmitInst_r(Opc, TLI.getRegClassFor(VT), ZReg, /*IsKill=*/true);
Juergen Ributzka1912e242014-08-25 19:58:05 +0000532}
533
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000534/// Check if the multiply is by a power-of-2 constant.
Juergen Ributzka22d4cd02014-09-17 19:19:31 +0000535static bool isMulPowOf2(const Value *I) {
536 if (const auto *MI = dyn_cast<MulOperator>(I)) {
537 if (const auto *C = dyn_cast<ConstantInt>(MI->getOperand(0)))
538 if (C->getValue().isPowerOf2())
539 return true;
540 if (const auto *C = dyn_cast<ConstantInt>(MI->getOperand(1)))
541 if (C->getValue().isPowerOf2())
542 return true;
543 }
544 return false;
545}
546
Tim Northover3b0846e2014-05-24 12:50:23 +0000547// Computes the address to get to an object.
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000548bool AArch64FastISel::computeAddress(const Value *Obj, Address &Addr, Type *Ty)
Juergen Ributzka843f14f2014-08-27 23:09:40 +0000549{
Tim Northover3b0846e2014-05-24 12:50:23 +0000550 const User *U = nullptr;
551 unsigned Opcode = Instruction::UserOp1;
552 if (const Instruction *I = dyn_cast<Instruction>(Obj)) {
553 // Don't walk into other basic blocks unless the object is an alloca from
554 // another block, otherwise it may not have a virtual register assigned.
555 if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
556 FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
557 Opcode = I->getOpcode();
558 U = I;
559 }
560 } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) {
561 Opcode = C->getOpcode();
562 U = C;
563 }
564
Craig Toppere3dcce92015-08-01 22:20:21 +0000565 if (auto *Ty = dyn_cast<PointerType>(Obj->getType()))
Tim Northover3b0846e2014-05-24 12:50:23 +0000566 if (Ty->getAddressSpace() > 255)
567 // Fast instruction selection doesn't support the special
568 // address spaces.
569 return false;
570
571 switch (Opcode) {
572 default:
573 break;
Eugene Zelenko11f69072017-01-25 00:29:26 +0000574 case Instruction::BitCast:
Tim Northover3b0846e2014-05-24 12:50:23 +0000575 // Look through bitcasts.
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000576 return computeAddress(U->getOperand(0), Addr, Ty);
Eugene Zelenko11f69072017-01-25 00:29:26 +0000577
578 case Instruction::IntToPtr:
Tim Northover3b0846e2014-05-24 12:50:23 +0000579 // Look past no-op inttoptrs.
Mehdi Amini44ede332015-07-09 02:09:04 +0000580 if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
581 TLI.getPointerTy(DL))
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000582 return computeAddress(U->getOperand(0), Addr, Ty);
Tim Northover3b0846e2014-05-24 12:50:23 +0000583 break;
Eugene Zelenko11f69072017-01-25 00:29:26 +0000584
585 case Instruction::PtrToInt:
Juergen Ributzka843f14f2014-08-27 23:09:40 +0000586 // Look past no-op ptrtoints.
Mehdi Amini44ede332015-07-09 02:09:04 +0000587 if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000588 return computeAddress(U->getOperand(0), Addr, Ty);
Tim Northover3b0846e2014-05-24 12:50:23 +0000589 break;
Eugene Zelenko11f69072017-01-25 00:29:26 +0000590
Tim Northover3b0846e2014-05-24 12:50:23 +0000591 case Instruction::GetElementPtr: {
592 Address SavedAddr = Addr;
593 uint64_t TmpOffset = Addr.getOffset();
594
595 // Iterate through the GEP folding the constants into offsets where
596 // we can.
Eduard Burtescu23c4d832016-01-20 00:26:52 +0000597 for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);
598 GTI != E; ++GTI) {
599 const Value *Op = GTI.getOperand();
Peter Collingbourneab85225b2016-12-02 02:24:42 +0000600 if (StructType *STy = GTI.getStructTypeOrNull()) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000601 const StructLayout *SL = DL.getStructLayout(STy);
602 unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
603 TmpOffset += SL->getElementOffset(Idx);
604 } else {
605 uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
Eugene Zelenko11f69072017-01-25 00:29:26 +0000606 while (true) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000607 if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
608 // Constant-offset addressing.
609 TmpOffset += CI->getSExtValue() * S;
610 break;
611 }
612 if (canFoldAddIntoGEP(U, Op)) {
613 // A compatible add with a constant operand. Fold the constant.
614 ConstantInt *CI =
615 cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
616 TmpOffset += CI->getSExtValue() * S;
617 // Iterate on the other operand.
618 Op = cast<AddOperator>(Op)->getOperand(0);
619 continue;
620 }
621 // Unsupported
622 goto unsupported_gep;
623 }
624 }
625 }
626
627 // Try to grab the base operand now.
628 Addr.setOffset(TmpOffset);
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000629 if (computeAddress(U->getOperand(0), Addr, Ty))
Tim Northover3b0846e2014-05-24 12:50:23 +0000630 return true;
631
632 // We failed, restore everything and try the other options.
633 Addr = SavedAddr;
634
635 unsupported_gep:
636 break;
637 }
638 case Instruction::Alloca: {
639 const AllocaInst *AI = cast<AllocaInst>(Obj);
640 DenseMap<const AllocaInst *, int>::iterator SI =
641 FuncInfo.StaticAllocaMap.find(AI);
642 if (SI != FuncInfo.StaticAllocaMap.end()) {
643 Addr.setKind(Address::FrameIndexBase);
644 Addr.setFI(SI->second);
645 return true;
646 }
647 break;
648 }
Juergen Ributzkab46ea082014-08-19 19:44:17 +0000649 case Instruction::Add: {
Juergen Ributzka5dcb33b2014-08-01 19:40:16 +0000650 // Adds of constants are common and easy enough.
Juergen Ributzkab46ea082014-08-19 19:44:17 +0000651 const Value *LHS = U->getOperand(0);
652 const Value *RHS = U->getOperand(1);
653
654 if (isa<ConstantInt>(LHS))
655 std::swap(LHS, RHS);
656
657 if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
Juergen Ributzka75b2f342014-10-07 03:40:03 +0000658 Addr.setOffset(Addr.getOffset() + CI->getSExtValue());
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000659 return computeAddress(LHS, Addr, Ty);
Juergen Ributzkab46ea082014-08-19 19:44:17 +0000660 }
661
662 Address Backup = Addr;
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000663 if (computeAddress(LHS, Addr, Ty) && computeAddress(RHS, Addr, Ty))
Juergen Ributzkab46ea082014-08-19 19:44:17 +0000664 return true;
665 Addr = Backup;
666
667 break;
668 }
Juergen Ributzka75b2f342014-10-07 03:40:03 +0000669 case Instruction::Sub: {
670 // Subs of constants are common and easy enough.
671 const Value *LHS = U->getOperand(0);
672 const Value *RHS = U->getOperand(1);
673
674 if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
675 Addr.setOffset(Addr.getOffset() - CI->getSExtValue());
676 return computeAddress(LHS, Addr, Ty);
677 }
678 break;
679 }
Juergen Ributzka92e89782014-09-19 22:23:46 +0000680 case Instruction::Shl: {
Juergen Ributzkab46ea082014-08-19 19:44:17 +0000681 if (Addr.getOffsetReg())
682 break;
683
Juergen Ributzka6ac12432014-09-30 00:49:58 +0000684 const auto *CI = dyn_cast<ConstantInt>(U->getOperand(1));
685 if (!CI)
686 break;
Juergen Ributzkab46ea082014-08-19 19:44:17 +0000687
Juergen Ributzka6ac12432014-09-30 00:49:58 +0000688 unsigned Val = CI->getZExtValue();
689 if (Val < 1 || Val > 3)
690 break;
Juergen Ributzkab46ea082014-08-19 19:44:17 +0000691
Juergen Ributzka6ac12432014-09-30 00:49:58 +0000692 uint64_t NumBytes = 0;
693 if (Ty && Ty->isSized()) {
694 uint64_t NumBits = DL.getTypeSizeInBits(Ty);
695 NumBytes = NumBits / 8;
696 if (!isPowerOf2_64(NumBits))
697 NumBytes = 0;
698 }
Juergen Ributzkab46ea082014-08-19 19:44:17 +0000699
Juergen Ributzka6ac12432014-09-30 00:49:58 +0000700 if (NumBytes != (1ULL << Val))
701 break;
Juergen Ributzkab46ea082014-08-19 19:44:17 +0000702
Juergen Ributzka6ac12432014-09-30 00:49:58 +0000703 Addr.setShift(Val);
704 Addr.setExtendType(AArch64_AM::LSL);
Juergen Ributzkab46ea082014-08-19 19:44:17 +0000705
Juergen Ributzka6ac12432014-09-30 00:49:58 +0000706 const Value *Src = U->getOperand(0);
Pete Cooperf52123b2015-05-07 19:21:36 +0000707 if (const auto *I = dyn_cast<Instruction>(Src)) {
708 if (FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
709 // Fold the zext or sext when it won't become a noop.
710 if (const auto *ZE = dyn_cast<ZExtInst>(I)) {
711 if (!isIntExtFree(ZE) &&
712 ZE->getOperand(0)->getType()->isIntegerTy(32)) {
713 Addr.setExtendType(AArch64_AM::UXTW);
714 Src = ZE->getOperand(0);
715 }
716 } else if (const auto *SE = dyn_cast<SExtInst>(I)) {
717 if (!isIntExtFree(SE) &&
718 SE->getOperand(0)->getType()->isIntegerTy(32)) {
719 Addr.setExtendType(AArch64_AM::SXTW);
720 Src = SE->getOperand(0);
721 }
722 }
Juergen Ributzka6ac12432014-09-30 00:49:58 +0000723 }
724 }
725
726 if (const auto *AI = dyn_cast<BinaryOperator>(Src))
727 if (AI->getOpcode() == Instruction::And) {
728 const Value *LHS = AI->getOperand(0);
729 const Value *RHS = AI->getOperand(1);
730
731 if (const auto *C = dyn_cast<ConstantInt>(LHS))
732 if (C->getValue() == 0xffffffff)
733 std::swap(LHS, RHS);
734
735 if (const auto *C = dyn_cast<ConstantInt>(RHS))
736 if (C->getValue() == 0xffffffff) {
737 Addr.setExtendType(AArch64_AM::UXTW);
738 unsigned Reg = getRegForValue(LHS);
739 if (!Reg)
740 return false;
741 bool RegIsKill = hasTrivialKill(LHS);
742 Reg = fastEmitInst_extractsubreg(MVT::i32, Reg, RegIsKill,
743 AArch64::sub_32);
744 Addr.setOffsetReg(Reg);
745 return true;
746 }
Juergen Ributzka92e89782014-09-19 22:23:46 +0000747 }
Juergen Ributzkab46ea082014-08-19 19:44:17 +0000748
Juergen Ributzka6ac12432014-09-30 00:49:58 +0000749 unsigned Reg = getRegForValue(Src);
750 if (!Reg)
751 return false;
752 Addr.setOffsetReg(Reg);
753 return true;
Juergen Ributzka92e89782014-09-19 22:23:46 +0000754 }
Juergen Ributzka22d4cd02014-09-17 19:19:31 +0000755 case Instruction::Mul: {
756 if (Addr.getOffsetReg())
757 break;
758
759 if (!isMulPowOf2(U))
760 break;
761
762 const Value *LHS = U->getOperand(0);
763 const Value *RHS = U->getOperand(1);
764
765 // Canonicalize power-of-2 value to the RHS.
766 if (const auto *C = dyn_cast<ConstantInt>(LHS))
767 if (C->getValue().isPowerOf2())
768 std::swap(LHS, RHS);
769
770 assert(isa<ConstantInt>(RHS) && "Expected an ConstantInt.");
771 const auto *C = cast<ConstantInt>(RHS);
772 unsigned Val = C->getValue().logBase2();
773 if (Val < 1 || Val > 3)
774 break;
775
776 uint64_t NumBytes = 0;
777 if (Ty && Ty->isSized()) {
778 uint64_t NumBits = DL.getTypeSizeInBits(Ty);
779 NumBytes = NumBits / 8;
780 if (!isPowerOf2_64(NumBits))
781 NumBytes = 0;
782 }
783
784 if (NumBytes != (1ULL << Val))
785 break;
786
787 Addr.setShift(Val);
788 Addr.setExtendType(AArch64_AM::LSL);
789
Juergen Ributzka92e89782014-09-19 22:23:46 +0000790 const Value *Src = LHS;
Pete Cooperf52123b2015-05-07 19:21:36 +0000791 if (const auto *I = dyn_cast<Instruction>(Src)) {
792 if (FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
793 // Fold the zext or sext when it won't become a noop.
794 if (const auto *ZE = dyn_cast<ZExtInst>(I)) {
795 if (!isIntExtFree(ZE) &&
796 ZE->getOperand(0)->getType()->isIntegerTy(32)) {
797 Addr.setExtendType(AArch64_AM::UXTW);
798 Src = ZE->getOperand(0);
799 }
800 } else if (const auto *SE = dyn_cast<SExtInst>(I)) {
801 if (!isIntExtFree(SE) &&
802 SE->getOperand(0)->getType()->isIntegerTy(32)) {
803 Addr.setExtendType(AArch64_AM::SXTW);
804 Src = SE->getOperand(0);
805 }
806 }
Juergen Ributzka22d4cd02014-09-17 19:19:31 +0000807 }
Juergen Ributzka92e89782014-09-19 22:23:46 +0000808 }
Juergen Ributzka22d4cd02014-09-17 19:19:31 +0000809
Juergen Ributzka92e89782014-09-19 22:23:46 +0000810 unsigned Reg = getRegForValue(Src);
Juergen Ributzka22d4cd02014-09-17 19:19:31 +0000811 if (!Reg)
812 return false;
813 Addr.setOffsetReg(Reg);
814 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000815 }
Juergen Ributzka99b77582014-09-18 05:40:41 +0000816 case Instruction::And: {
817 if (Addr.getOffsetReg())
818 break;
819
Juergen Ributzkac6f314b2014-12-09 19:44:38 +0000820 if (!Ty || DL.getTypeSizeInBits(Ty) != 8)
Juergen Ributzka99b77582014-09-18 05:40:41 +0000821 break;
822
823 const Value *LHS = U->getOperand(0);
824 const Value *RHS = U->getOperand(1);
825
826 if (const auto *C = dyn_cast<ConstantInt>(LHS))
827 if (C->getValue() == 0xffffffff)
828 std::swap(LHS, RHS);
829
Juergen Ributzka92e89782014-09-19 22:23:46 +0000830 if (const auto *C = dyn_cast<ConstantInt>(RHS))
Juergen Ributzka99b77582014-09-18 05:40:41 +0000831 if (C->getValue() == 0xffffffff) {
832 Addr.setShift(0);
833 Addr.setExtendType(AArch64_AM::LSL);
834 Addr.setExtendType(AArch64_AM::UXTW);
835
836 unsigned Reg = getRegForValue(LHS);
837 if (!Reg)
838 return false;
839 bool RegIsKill = hasTrivialKill(LHS);
840 Reg = fastEmitInst_extractsubreg(MVT::i32, Reg, RegIsKill,
841 AArch64::sub_32);
842 Addr.setOffsetReg(Reg);
843 return true;
844 }
845 break;
846 }
Juergen Ributzkaef3722d2014-10-07 03:40:06 +0000847 case Instruction::SExt:
848 case Instruction::ZExt: {
849 if (!Addr.getReg() || Addr.getOffsetReg())
850 break;
851
852 const Value *Src = nullptr;
853 // Fold the zext or sext when it won't become a noop.
854 if (const auto *ZE = dyn_cast<ZExtInst>(U)) {
855 if (!isIntExtFree(ZE) && ZE->getOperand(0)->getType()->isIntegerTy(32)) {
856 Addr.setExtendType(AArch64_AM::UXTW);
857 Src = ZE->getOperand(0);
858 }
859 } else if (const auto *SE = dyn_cast<SExtInst>(U)) {
860 if (!isIntExtFree(SE) && SE->getOperand(0)->getType()->isIntegerTy(32)) {
861 Addr.setExtendType(AArch64_AM::SXTW);
862 Src = SE->getOperand(0);
863 }
864 }
865
866 if (!Src)
867 break;
868
869 Addr.setShift(0);
870 unsigned Reg = getRegForValue(Src);
871 if (!Reg)
872 return false;
873 Addr.setOffsetReg(Reg);
874 return true;
875 }
Juergen Ributzka22d4cd02014-09-17 19:19:31 +0000876 } // end switch
Tim Northover3b0846e2014-05-24 12:50:23 +0000877
Juergen Ributzka6de054a2014-10-27 18:21:58 +0000878 if (Addr.isRegBase() && !Addr.getReg()) {
879 unsigned Reg = getRegForValue(Obj);
880 if (!Reg)
881 return false;
882 Addr.setReg(Reg);
883 return true;
Juergen Ributzkab46ea082014-08-19 19:44:17 +0000884 }
885
Juergen Ributzka6de054a2014-10-27 18:21:58 +0000886 if (!Addr.getOffsetReg()) {
887 unsigned Reg = getRegForValue(Obj);
888 if (!Reg)
889 return false;
890 Addr.setOffsetReg(Reg);
891 return true;
892 }
893
894 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +0000895}
896
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000897bool AArch64FastISel::computeCallAddress(const Value *V, Address &Addr) {
Juergen Ributzka052e6c22014-07-31 04:10:40 +0000898 const User *U = nullptr;
899 unsigned Opcode = Instruction::UserOp1;
900 bool InMBB = true;
901
902 if (const auto *I = dyn_cast<Instruction>(V)) {
903 Opcode = I->getOpcode();
904 U = I;
905 InMBB = I->getParent() == FuncInfo.MBB->getBasicBlock();
906 } else if (const auto *C = dyn_cast<ConstantExpr>(V)) {
907 Opcode = C->getOpcode();
908 U = C;
909 }
910
911 switch (Opcode) {
912 default: break;
913 case Instruction::BitCast:
914 // Look past bitcasts if its operand is in the same BB.
915 if (InMBB)
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000916 return computeCallAddress(U->getOperand(0), Addr);
Juergen Ributzka052e6c22014-07-31 04:10:40 +0000917 break;
918 case Instruction::IntToPtr:
919 // Look past no-op inttoptrs if its operand is in the same BB.
920 if (InMBB &&
Mehdi Amini44ede332015-07-09 02:09:04 +0000921 TLI.getValueType(DL, U->getOperand(0)->getType()) ==
922 TLI.getPointerTy(DL))
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000923 return computeCallAddress(U->getOperand(0), Addr);
Juergen Ributzka052e6c22014-07-31 04:10:40 +0000924 break;
925 case Instruction::PtrToInt:
926 // Look past no-op ptrtoints if its operand is in the same BB.
Mehdi Amini44ede332015-07-09 02:09:04 +0000927 if (InMBB && TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000928 return computeCallAddress(U->getOperand(0), Addr);
Juergen Ributzka052e6c22014-07-31 04:10:40 +0000929 break;
930 }
931
932 if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
933 Addr.setGlobalValue(GV);
934 return true;
935 }
936
937 // If all else fails, try to materialize the value in a register.
938 if (!Addr.getGlobalValue()) {
939 Addr.setReg(getRegForValue(V));
940 return Addr.getReg() != 0;
941 }
942
943 return false;
944}
945
Tim Northover3b0846e2014-05-24 12:50:23 +0000946bool AArch64FastISel::isTypeLegal(Type *Ty, MVT &VT) {
Mehdi Amini44ede332015-07-09 02:09:04 +0000947 EVT evt = TLI.getValueType(DL, Ty, true);
Tim Northover3b0846e2014-05-24 12:50:23 +0000948
949 // Only handle simple types.
950 if (evt == MVT::Other || !evt.isSimple())
951 return false;
952 VT = evt.getSimpleVT();
953
954 // This is a legal type, but it's not something we handle in fast-isel.
955 if (VT == MVT::f128)
956 return false;
957
958 // Handle all other legal types, i.e. a register that will directly hold this
959 // value.
960 return TLI.isTypeLegal(VT);
961}
962
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000963/// Determine if the value type is supported by FastISel.
Juergen Ributzka8a4b8be2014-09-02 22:33:53 +0000964///
965/// FastISel for AArch64 can handle more value types than are legal. This adds
966/// simple value type such as i1, i8, and i16.
Juergen Ributzka6127b192014-09-15 21:27:54 +0000967bool AArch64FastISel::isTypeSupported(Type *Ty, MVT &VT, bool IsVectorAllowed) {
968 if (Ty->isVectorTy() && !IsVectorAllowed)
Juergen Ributzka8a4b8be2014-09-02 22:33:53 +0000969 return false;
970
971 if (isTypeLegal(Ty, VT))
972 return true;
973
974 // If this is a type than can be sign or zero-extended to a basic operation
975 // go ahead and accept it now.
976 if (VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16)
977 return true;
978
979 return false;
980}
981
Juergen Ributzka77bc09f2014-08-29 00:19:21 +0000982bool AArch64FastISel::isValueAvailable(const Value *V) const {
983 if (!isa<Instruction>(V))
984 return true;
985
986 const auto *I = cast<Instruction>(V);
Eric Christopher114fa1c2016-02-29 22:50:49 +0000987 return FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB;
Juergen Ributzka77bc09f2014-08-29 00:19:21 +0000988}
989
Juergen Ributzkab9e49c72014-09-15 23:20:17 +0000990bool AArch64FastISel::simplifyAddress(Address &Addr, MVT VT) {
Juergen Ributzka0616d9d2014-09-30 00:49:54 +0000991 unsigned ScaleFactor = getImplicitScaleFactor(VT);
992 if (!ScaleFactor)
993 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +0000994
Juergen Ributzkab46ea082014-08-19 19:44:17 +0000995 bool ImmediateOffsetNeedsLowering = false;
996 bool RegisterOffsetNeedsLowering = false;
997 int64_t Offset = Addr.getOffset();
998 if (((Offset < 0) || (Offset & (ScaleFactor - 1))) && !isInt<9>(Offset))
999 ImmediateOffsetNeedsLowering = true;
1000 else if (Offset > 0 && !(Offset & (ScaleFactor - 1)) &&
1001 !isUInt<12>(Offset / ScaleFactor))
1002 ImmediateOffsetNeedsLowering = true;
1003
1004 // Cannot encode an offset register and an immediate offset in the same
1005 // instruction. Fold the immediate offset into the load/store instruction and
Benjamin Kramerdf005cb2015-08-08 18:27:36 +00001006 // emit an additional add to take care of the offset register.
Juergen Ributzka6de054a2014-10-27 18:21:58 +00001007 if (!ImmediateOffsetNeedsLowering && Addr.getOffset() && Addr.getOffsetReg())
Juergen Ributzkab46ea082014-08-19 19:44:17 +00001008 RegisterOffsetNeedsLowering = true;
1009
Juergen Ributzka3c1b2862014-08-27 21:38:33 +00001010 // Cannot encode zero register as base.
1011 if (Addr.isRegBase() && Addr.getOffsetReg() && !Addr.getReg())
1012 RegisterOffsetNeedsLowering = true;
1013
Juergen Ributzkab46ea082014-08-19 19:44:17 +00001014 // If this is a stack pointer and the offset needs to be simplified then put
Tim Northoverc141ad42014-06-10 09:52:44 +00001015 // the alloca address into a register, set the base type back to register and
1016 // continue. This should almost never happen.
Juergen Ributzka6de054a2014-10-27 18:21:58 +00001017 if ((ImmediateOffsetNeedsLowering || Addr.getOffsetReg()) && Addr.isFIBase())
1018 {
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00001019 unsigned ResultReg = createResultReg(&AArch64::GPR64spRegClass);
Tim Northoverc141ad42014-06-10 09:52:44 +00001020 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::ADDXri),
1021 ResultReg)
Juergen Ributzkab46ea082014-08-19 19:44:17 +00001022 .addFrameIndex(Addr.getFI())
1023 .addImm(0)
1024 .addImm(0);
Tim Northoverc141ad42014-06-10 09:52:44 +00001025 Addr.setKind(Address::RegBase);
1026 Addr.setReg(ResultReg);
Tim Northover3b0846e2014-05-24 12:50:23 +00001027 }
1028
Juergen Ributzkab46ea082014-08-19 19:44:17 +00001029 if (RegisterOffsetNeedsLowering) {
1030 unsigned ResultReg = 0;
Juergen Ributzkafb506a42014-08-27 00:58:30 +00001031 if (Addr.getReg()) {
1032 if (Addr.getExtendType() == AArch64_AM::SXTW ||
1033 Addr.getExtendType() == AArch64_AM::UXTW )
1034 ResultReg = emitAddSub_rx(/*UseAdd=*/true, MVT::i64, Addr.getReg(),
1035 /*TODO:IsKill=*/false, Addr.getOffsetReg(),
1036 /*TODO:IsKill=*/false, Addr.getExtendType(),
1037 Addr.getShift());
1038 else
1039 ResultReg = emitAddSub_rs(/*UseAdd=*/true, MVT::i64, Addr.getReg(),
1040 /*TODO:IsKill=*/false, Addr.getOffsetReg(),
1041 /*TODO:IsKill=*/false, AArch64_AM::LSL,
1042 Addr.getShift());
1043 } else {
1044 if (Addr.getExtendType() == AArch64_AM::UXTW)
1045 ResultReg = emitLSL_ri(MVT::i64, MVT::i32, Addr.getOffsetReg(),
1046 /*Op0IsKill=*/false, Addr.getShift(),
1047 /*IsZExt=*/true);
1048 else if (Addr.getExtendType() == AArch64_AM::SXTW)
1049 ResultReg = emitLSL_ri(MVT::i64, MVT::i32, Addr.getOffsetReg(),
1050 /*Op0IsKill=*/false, Addr.getShift(),
1051 /*IsZExt=*/false);
1052 else
1053 ResultReg = emitLSL_ri(MVT::i64, MVT::i64, Addr.getOffsetReg(),
1054 /*Op0IsKill=*/false, Addr.getShift());
1055 }
Juergen Ributzkab46ea082014-08-19 19:44:17 +00001056 if (!ResultReg)
1057 return false;
1058
1059 Addr.setReg(ResultReg);
1060 Addr.setOffsetReg(0);
1061 Addr.setShift(0);
Juergen Ributzkafb506a42014-08-27 00:58:30 +00001062 Addr.setExtendType(AArch64_AM::InvalidShiftExtend);
Juergen Ributzkab46ea082014-08-19 19:44:17 +00001063 }
1064
Tim Northover3b0846e2014-05-24 12:50:23 +00001065 // Since the offset is too large for the load/store instruction get the
1066 // reg+offset into a register.
Juergen Ributzkab46ea082014-08-19 19:44:17 +00001067 if (ImmediateOffsetNeedsLowering) {
Juergen Ributzka2fc85102014-09-18 07:04:49 +00001068 unsigned ResultReg;
Juergen Ributzka6780f0f2014-10-15 18:58:02 +00001069 if (Addr.getReg())
Juergen Ributzkaa33070c2014-09-18 05:40:47 +00001070 // Try to fold the immediate into the add instruction.
Juergen Ributzka6780f0f2014-10-15 18:58:02 +00001071 ResultReg = emitAdd_ri_(MVT::i64, Addr.getReg(), /*IsKill=*/false, Offset);
1072 else
Juergen Ributzka88e32512014-09-03 20:56:59 +00001073 ResultReg = fastEmit_i(MVT::i64, MVT::i64, ISD::Constant, Offset);
Juergen Ributzkab46ea082014-08-19 19:44:17 +00001074
1075 if (!ResultReg)
Tim Northover3b0846e2014-05-24 12:50:23 +00001076 return false;
1077 Addr.setReg(ResultReg);
1078 Addr.setOffset(0);
1079 }
1080 return true;
1081}
1082
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00001083void AArch64FastISel::addLoadStoreOperands(Address &Addr,
Tim Northover3b0846e2014-05-24 12:50:23 +00001084 const MachineInstrBuilder &MIB,
Justin Lebar0af80cd2016-07-15 18:26:59 +00001085 MachineMemOperand::Flags Flags,
Juergen Ributzkab46ea082014-08-19 19:44:17 +00001086 unsigned ScaleFactor,
1087 MachineMemOperand *MMO) {
1088 int64_t Offset = Addr.getOffset() / ScaleFactor;
Tim Northover3b0846e2014-05-24 12:50:23 +00001089 // Frame base works a bit differently. Handle it separately.
Juergen Ributzkab46ea082014-08-19 19:44:17 +00001090 if (Addr.isFIBase()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001091 int FI = Addr.getFI();
1092 // FIXME: We shouldn't be using getObjectSize/getObjectAlignment. The size
1093 // and alignment should be based on the VT.
Juergen Ributzka241fd482014-08-08 17:24:10 +00001094 MMO = FuncInfo.MF->getMachineMemOperand(
Alex Lorenze40c8a22015-08-11 23:09:45 +00001095 MachinePointerInfo::getFixedStack(*FuncInfo.MF, FI, Offset), Flags,
1096 MFI.getObjectSize(FI), MFI.getObjectAlignment(FI));
Tim Northover3b0846e2014-05-24 12:50:23 +00001097 // Now add the rest of the operands.
Juergen Ributzka241fd482014-08-08 17:24:10 +00001098 MIB.addFrameIndex(FI).addImm(Offset);
Tim Northover3b0846e2014-05-24 12:50:23 +00001099 } else {
Juergen Ributzkab46ea082014-08-19 19:44:17 +00001100 assert(Addr.isRegBase() && "Unexpected address kind.");
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00001101 const MCInstrDesc &II = MIB->getDesc();
1102 unsigned Idx = (Flags & MachineMemOperand::MOStore) ? 1 : 0;
1103 Addr.setReg(
1104 constrainOperandRegClass(II, Addr.getReg(), II.getNumDefs()+Idx));
1105 Addr.setOffsetReg(
1106 constrainOperandRegClass(II, Addr.getOffsetReg(), II.getNumDefs()+Idx+1));
Juergen Ributzkab46ea082014-08-19 19:44:17 +00001107 if (Addr.getOffsetReg()) {
1108 assert(Addr.getOffset() == 0 && "Unexpected offset");
1109 bool IsSigned = Addr.getExtendType() == AArch64_AM::SXTW ||
1110 Addr.getExtendType() == AArch64_AM::SXTX;
1111 MIB.addReg(Addr.getReg());
1112 MIB.addReg(Addr.getOffsetReg());
1113 MIB.addImm(IsSigned);
1114 MIB.addImm(Addr.getShift() != 0);
Juergen Ributzka6de054a2014-10-27 18:21:58 +00001115 } else
1116 MIB.addReg(Addr.getReg()).addImm(Offset);
Tim Northover3b0846e2014-05-24 12:50:23 +00001117 }
Juergen Ributzka241fd482014-08-08 17:24:10 +00001118
1119 if (MMO)
1120 MIB.addMemOperand(MMO);
Tim Northover3b0846e2014-05-24 12:50:23 +00001121}
1122
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001123unsigned AArch64FastISel::emitAddSub(bool UseAdd, MVT RetVT, const Value *LHS,
1124 const Value *RHS, bool SetFlags,
1125 bool WantResult, bool IsZExt) {
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001126 AArch64_AM::ShiftExtendType ExtendType = AArch64_AM::InvalidShiftExtend;
Juergen Ributzkae1bb0552014-08-20 16:34:15 +00001127 bool NeedExtend = false;
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001128 switch (RetVT.SimpleTy) {
Juergen Ributzkae1bb0552014-08-20 16:34:15 +00001129 default:
1130 return 0;
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001131 case MVT::i1:
Juergen Ributzkae1bb0552014-08-20 16:34:15 +00001132 NeedExtend = true;
1133 break;
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001134 case MVT::i8:
Juergen Ributzkae1bb0552014-08-20 16:34:15 +00001135 NeedExtend = true;
1136 ExtendType = IsZExt ? AArch64_AM::UXTB : AArch64_AM::SXTB;
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001137 break;
1138 case MVT::i16:
Juergen Ributzkae1bb0552014-08-20 16:34:15 +00001139 NeedExtend = true;
1140 ExtendType = IsZExt ? AArch64_AM::UXTH : AArch64_AM::SXTH;
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001141 break;
Juergen Ributzkae1bb0552014-08-20 16:34:15 +00001142 case MVT::i32: // fall-through
1143 case MVT::i64:
1144 break;
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001145 }
Juergen Ributzkae1bb0552014-08-20 16:34:15 +00001146 MVT SrcVT = RetVT;
1147 RetVT.SimpleTy = std::max(RetVT.SimpleTy, MVT::i32);
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001148
1149 // Canonicalize immediates to the RHS first.
Juergen Ributzka7ccebec2014-10-27 19:58:36 +00001150 if (UseAdd && isa<Constant>(LHS) && !isa<Constant>(RHS))
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001151 std::swap(LHS, RHS);
1152
Juergen Ributzka3871c692014-09-17 19:51:38 +00001153 // Canonicalize mul by power of 2 to the RHS.
1154 if (UseAdd && LHS->hasOneUse() && isValueAvailable(LHS))
1155 if (isMulPowOf2(LHS))
1156 std::swap(LHS, RHS);
1157
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001158 // Canonicalize shift immediate to the RHS.
Juergen Ributzka3871c692014-09-17 19:51:38 +00001159 if (UseAdd && LHS->hasOneUse() && isValueAvailable(LHS))
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001160 if (const auto *SI = dyn_cast<BinaryOperator>(LHS))
1161 if (isa<ConstantInt>(SI->getOperand(1)))
1162 if (SI->getOpcode() == Instruction::Shl ||
1163 SI->getOpcode() == Instruction::LShr ||
1164 SI->getOpcode() == Instruction::AShr )
1165 std::swap(LHS, RHS);
1166
1167 unsigned LHSReg = getRegForValue(LHS);
1168 if (!LHSReg)
1169 return 0;
1170 bool LHSIsKill = hasTrivialKill(LHS);
1171
Juergen Ributzkae1bb0552014-08-20 16:34:15 +00001172 if (NeedExtend)
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00001173 LHSReg = emitIntExt(SrcVT, LHSReg, RetVT, IsZExt);
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001174
1175 unsigned ResultReg = 0;
1176 if (const auto *C = dyn_cast<ConstantInt>(RHS)) {
1177 uint64_t Imm = IsZExt ? C->getZExtValue() : C->getSExtValue();
1178 if (C->isNegative())
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001179 ResultReg = emitAddSub_ri(!UseAdd, RetVT, LHSReg, LHSIsKill, -Imm,
1180 SetFlags, WantResult);
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001181 else
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001182 ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, LHSIsKill, Imm, SetFlags,
1183 WantResult);
Juergen Ributzka7ccebec2014-10-27 19:58:36 +00001184 } else if (const auto *C = dyn_cast<Constant>(RHS))
1185 if (C->isNullValue())
1186 ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, LHSIsKill, 0, SetFlags,
1187 WantResult);
1188
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001189 if (ResultReg)
1190 return ResultReg;
1191
Juergen Ributzkae1bb0552014-08-20 16:34:15 +00001192 // Only extend the RHS within the instruction if there is a valid extend type.
Juergen Ributzka3871c692014-09-17 19:51:38 +00001193 if (ExtendType != AArch64_AM::InvalidShiftExtend && RHS->hasOneUse() &&
1194 isValueAvailable(RHS)) {
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001195 if (const auto *SI = dyn_cast<BinaryOperator>(RHS))
1196 if (const auto *C = dyn_cast<ConstantInt>(SI->getOperand(1)))
1197 if ((SI->getOpcode() == Instruction::Shl) && (C->getZExtValue() < 4)) {
1198 unsigned RHSReg = getRegForValue(SI->getOperand(0));
1199 if (!RHSReg)
1200 return 0;
1201 bool RHSIsKill = hasTrivialKill(SI->getOperand(0));
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001202 return emitAddSub_rx(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg,
1203 RHSIsKill, ExtendType, C->getZExtValue(),
1204 SetFlags, WantResult);
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001205 }
1206 unsigned RHSReg = getRegForValue(RHS);
1207 if (!RHSReg)
1208 return 0;
1209 bool RHSIsKill = hasTrivialKill(RHS);
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001210 return emitAddSub_rx(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
1211 ExtendType, 0, SetFlags, WantResult);
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001212 }
1213
Juergen Ributzka3871c692014-09-17 19:51:38 +00001214 // Check if the mul can be folded into the instruction.
Juergen Ributzkab12248e2015-08-19 20:52:55 +00001215 if (RHS->hasOneUse() && isValueAvailable(RHS)) {
Juergen Ributzka3871c692014-09-17 19:51:38 +00001216 if (isMulPowOf2(RHS)) {
1217 const Value *MulLHS = cast<MulOperator>(RHS)->getOperand(0);
1218 const Value *MulRHS = cast<MulOperator>(RHS)->getOperand(1);
1219
1220 if (const auto *C = dyn_cast<ConstantInt>(MulLHS))
1221 if (C->getValue().isPowerOf2())
1222 std::swap(MulLHS, MulRHS);
1223
1224 assert(isa<ConstantInt>(MulRHS) && "Expected a ConstantInt.");
1225 uint64_t ShiftVal = cast<ConstantInt>(MulRHS)->getValue().logBase2();
1226 unsigned RHSReg = getRegForValue(MulLHS);
1227 if (!RHSReg)
1228 return 0;
1229 bool RHSIsKill = hasTrivialKill(MulLHS);
Juergen Ributzkab12248e2015-08-19 20:52:55 +00001230 ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg,
1231 RHSIsKill, AArch64_AM::LSL, ShiftVal, SetFlags,
1232 WantResult);
1233 if (ResultReg)
1234 return ResultReg;
Juergen Ributzka3871c692014-09-17 19:51:38 +00001235 }
Juergen Ributzkab12248e2015-08-19 20:52:55 +00001236 }
Juergen Ributzka3871c692014-09-17 19:51:38 +00001237
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001238 // Check if the shift can be folded into the instruction.
Juergen Ributzkab12248e2015-08-19 20:52:55 +00001239 if (RHS->hasOneUse() && isValueAvailable(RHS)) {
Juergen Ributzka77bc09f2014-08-29 00:19:21 +00001240 if (const auto *SI = dyn_cast<BinaryOperator>(RHS)) {
1241 if (const auto *C = dyn_cast<ConstantInt>(SI->getOperand(1))) {
1242 AArch64_AM::ShiftExtendType ShiftType = AArch64_AM::InvalidShiftExtend;
1243 switch (SI->getOpcode()) {
1244 default: break;
1245 case Instruction::Shl: ShiftType = AArch64_AM::LSL; break;
1246 case Instruction::LShr: ShiftType = AArch64_AM::LSR; break;
1247 case Instruction::AShr: ShiftType = AArch64_AM::ASR; break;
1248 }
1249 uint64_t ShiftVal = C->getZExtValue();
1250 if (ShiftType != AArch64_AM::InvalidShiftExtend) {
1251 unsigned RHSReg = getRegForValue(SI->getOperand(0));
1252 if (!RHSReg)
1253 return 0;
1254 bool RHSIsKill = hasTrivialKill(SI->getOperand(0));
Juergen Ributzkab12248e2015-08-19 20:52:55 +00001255 ResultReg = emitAddSub_rs(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg,
1256 RHSIsKill, ShiftType, ShiftVal, SetFlags,
1257 WantResult);
1258 if (ResultReg)
1259 return ResultReg;
Juergen Ributzka77bc09f2014-08-29 00:19:21 +00001260 }
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001261 }
1262 }
Juergen Ributzkab12248e2015-08-19 20:52:55 +00001263 }
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001264
1265 unsigned RHSReg = getRegForValue(RHS);
1266 if (!RHSReg)
1267 return 0;
1268 bool RHSIsKill = hasTrivialKill(RHS);
Juergen Ributzkae1bb0552014-08-20 16:34:15 +00001269
1270 if (NeedExtend)
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00001271 RHSReg = emitIntExt(SrcVT, RHSReg, RetVT, IsZExt);
Juergen Ributzkae1bb0552014-08-20 16:34:15 +00001272
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001273 return emitAddSub_rr(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
1274 SetFlags, WantResult);
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001275}
1276
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001277unsigned AArch64FastISel::emitAddSub_rr(bool UseAdd, MVT RetVT, unsigned LHSReg,
1278 bool LHSIsKill, unsigned RHSReg,
1279 bool RHSIsKill, bool SetFlags,
1280 bool WantResult) {
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001281 assert(LHSReg && RHSReg && "Invalid register number.");
1282
Tim Northover7a613162017-06-12 20:49:53 +00001283 if (LHSReg == AArch64::SP || LHSReg == AArch64::WSP ||
1284 RHSReg == AArch64::SP || RHSReg == AArch64::WSP)
1285 return 0;
1286
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001287 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1288 return 0;
1289
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001290 static const unsigned OpcTable[2][2][2] = {
1291 { { AArch64::SUBWrr, AArch64::SUBXrr },
1292 { AArch64::ADDWrr, AArch64::ADDXrr } },
1293 { { AArch64::SUBSWrr, AArch64::SUBSXrr },
1294 { AArch64::ADDSWrr, AArch64::ADDSXrr } }
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001295 };
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001296 bool Is64Bit = RetVT == MVT::i64;
1297 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1298 const TargetRegisterClass *RC =
1299 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001300 unsigned ResultReg;
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001301 if (WantResult)
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00001302 ResultReg = createResultReg(RC);
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001303 else
1304 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001305
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00001306 const MCInstrDesc &II = TII.get(Opc);
1307 LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
1308 RHSReg = constrainOperandRegClass(II, RHSReg, II.getNumDefs() + 1);
1309 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001310 .addReg(LHSReg, getKillRegState(LHSIsKill))
1311 .addReg(RHSReg, getKillRegState(RHSIsKill));
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001312 return ResultReg;
1313}
1314
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001315unsigned AArch64FastISel::emitAddSub_ri(bool UseAdd, MVT RetVT, unsigned LHSReg,
1316 bool LHSIsKill, uint64_t Imm,
1317 bool SetFlags, bool WantResult) {
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001318 assert(LHSReg && "Invalid register number.");
1319
1320 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1321 return 0;
1322
1323 unsigned ShiftImm;
1324 if (isUInt<12>(Imm))
1325 ShiftImm = 0;
1326 else if ((Imm & 0xfff000) == Imm) {
1327 ShiftImm = 12;
1328 Imm >>= 12;
1329 } else
1330 return 0;
1331
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001332 static const unsigned OpcTable[2][2][2] = {
1333 { { AArch64::SUBWri, AArch64::SUBXri },
1334 { AArch64::ADDWri, AArch64::ADDXri } },
1335 { { AArch64::SUBSWri, AArch64::SUBSXri },
1336 { AArch64::ADDSWri, AArch64::ADDSXri } }
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001337 };
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001338 bool Is64Bit = RetVT == MVT::i64;
1339 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1340 const TargetRegisterClass *RC;
1341 if (SetFlags)
1342 RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1343 else
1344 RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001345 unsigned ResultReg;
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001346 if (WantResult)
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00001347 ResultReg = createResultReg(RC);
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001348 else
1349 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001350
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00001351 const MCInstrDesc &II = TII.get(Opc);
1352 LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
1353 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001354 .addReg(LHSReg, getKillRegState(LHSIsKill))
1355 .addImm(Imm)
1356 .addImm(getShifterImm(AArch64_AM::LSL, ShiftImm));
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001357 return ResultReg;
1358}
1359
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001360unsigned AArch64FastISel::emitAddSub_rs(bool UseAdd, MVT RetVT, unsigned LHSReg,
1361 bool LHSIsKill, unsigned RHSReg,
1362 bool RHSIsKill,
Juergen Ributzkafb506a42014-08-27 00:58:30 +00001363 AArch64_AM::ShiftExtendType ShiftType,
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001364 uint64_t ShiftImm, bool SetFlags,
1365 bool WantResult) {
Juergen Ributzkafb506a42014-08-27 00:58:30 +00001366 assert(LHSReg && RHSReg && "Invalid register number.");
Tim Northover7a613162017-06-12 20:49:53 +00001367 assert(LHSReg != AArch64::SP && LHSReg != AArch64::WSP &&
1368 RHSReg != AArch64::SP && RHSReg != AArch64::WSP);
Juergen Ributzkafb506a42014-08-27 00:58:30 +00001369
1370 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1371 return 0;
1372
Juergen Ributzkab12248e2015-08-19 20:52:55 +00001373 // Don't deal with undefined shifts.
1374 if (ShiftImm >= RetVT.getSizeInBits())
1375 return 0;
1376
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001377 static const unsigned OpcTable[2][2][2] = {
1378 { { AArch64::SUBWrs, AArch64::SUBXrs },
1379 { AArch64::ADDWrs, AArch64::ADDXrs } },
1380 { { AArch64::SUBSWrs, AArch64::SUBSXrs },
1381 { AArch64::ADDSWrs, AArch64::ADDSXrs } }
Juergen Ributzkafb506a42014-08-27 00:58:30 +00001382 };
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001383 bool Is64Bit = RetVT == MVT::i64;
1384 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1385 const TargetRegisterClass *RC =
1386 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
Juergen Ributzkafb506a42014-08-27 00:58:30 +00001387 unsigned ResultReg;
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001388 if (WantResult)
Juergen Ributzkafb506a42014-08-27 00:58:30 +00001389 ResultReg = createResultReg(RC);
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001390 else
1391 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
Juergen Ributzkafb506a42014-08-27 00:58:30 +00001392
1393 const MCInstrDesc &II = TII.get(Opc);
1394 LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
1395 RHSReg = constrainOperandRegClass(II, RHSReg, II.getNumDefs() + 1);
1396 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
1397 .addReg(LHSReg, getKillRegState(LHSIsKill))
1398 .addReg(RHSReg, getKillRegState(RHSIsKill))
1399 .addImm(getShifterImm(ShiftType, ShiftImm));
Juergen Ributzkafb506a42014-08-27 00:58:30 +00001400 return ResultReg;
1401}
1402
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001403unsigned AArch64FastISel::emitAddSub_rx(bool UseAdd, MVT RetVT, unsigned LHSReg,
1404 bool LHSIsKill, unsigned RHSReg,
1405 bool RHSIsKill,
Juergen Ributzkafb506a42014-08-27 00:58:30 +00001406 AArch64_AM::ShiftExtendType ExtType,
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001407 uint64_t ShiftImm, bool SetFlags,
1408 bool WantResult) {
Juergen Ributzkafb506a42014-08-27 00:58:30 +00001409 assert(LHSReg && RHSReg && "Invalid register number.");
Tim Northover7a613162017-06-12 20:49:53 +00001410 assert(LHSReg != AArch64::XZR && LHSReg != AArch64::WZR &&
1411 RHSReg != AArch64::XZR && RHSReg != AArch64::WZR);
Juergen Ributzkafb506a42014-08-27 00:58:30 +00001412
1413 if (RetVT != MVT::i32 && RetVT != MVT::i64)
1414 return 0;
1415
Juergen Ributzkab12248e2015-08-19 20:52:55 +00001416 if (ShiftImm >= 4)
1417 return 0;
1418
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001419 static const unsigned OpcTable[2][2][2] = {
1420 { { AArch64::SUBWrx, AArch64::SUBXrx },
1421 { AArch64::ADDWrx, AArch64::ADDXrx } },
1422 { { AArch64::SUBSWrx, AArch64::SUBSXrx },
1423 { AArch64::ADDSWrx, AArch64::ADDSXrx } }
Juergen Ributzkafb506a42014-08-27 00:58:30 +00001424 };
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001425 bool Is64Bit = RetVT == MVT::i64;
1426 unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
1427 const TargetRegisterClass *RC = nullptr;
1428 if (SetFlags)
1429 RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
1430 else
1431 RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
Juergen Ributzkafb506a42014-08-27 00:58:30 +00001432 unsigned ResultReg;
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001433 if (WantResult)
Juergen Ributzkafb506a42014-08-27 00:58:30 +00001434 ResultReg = createResultReg(RC);
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001435 else
1436 ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
Juergen Ributzkafb506a42014-08-27 00:58:30 +00001437
1438 const MCInstrDesc &II = TII.get(Opc);
1439 LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
1440 RHSReg = constrainOperandRegClass(II, RHSReg, II.getNumDefs() + 1);
1441 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
1442 .addReg(LHSReg, getKillRegState(LHSIsKill))
1443 .addReg(RHSReg, getKillRegState(RHSIsKill))
1444 .addImm(getArithExtendImm(ExtType, ShiftImm));
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001445 return ResultReg;
1446}
1447
1448bool AArch64FastISel::emitCmp(const Value *LHS, const Value *RHS, bool IsZExt) {
1449 Type *Ty = LHS->getType();
Mehdi Amini44ede332015-07-09 02:09:04 +00001450 EVT EVT = TLI.getValueType(DL, Ty, true);
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001451 if (!EVT.isSimple())
1452 return false;
1453 MVT VT = EVT.getSimpleVT();
1454
1455 switch (VT.SimpleTy) {
1456 default:
1457 return false;
1458 case MVT::i1:
1459 case MVT::i8:
1460 case MVT::i16:
1461 case MVT::i32:
1462 case MVT::i64:
1463 return emitICmp(VT, LHS, RHS, IsZExt);
1464 case MVT::f32:
1465 case MVT::f64:
1466 return emitFCmp(VT, LHS, RHS);
1467 }
1468}
1469
1470bool AArch64FastISel::emitICmp(MVT RetVT, const Value *LHS, const Value *RHS,
1471 bool IsZExt) {
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001472 return emitSub(RetVT, LHS, RHS, /*SetFlags=*/true, /*WantResult=*/false,
1473 IsZExt) != 0;
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001474}
1475
1476bool AArch64FastISel::emitICmp_ri(MVT RetVT, unsigned LHSReg, bool LHSIsKill,
1477 uint64_t Imm) {
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001478 return emitAddSub_ri(/*UseAdd=*/false, RetVT, LHSReg, LHSIsKill, Imm,
1479 /*SetFlags=*/true, /*WantResult=*/false) != 0;
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001480}
1481
1482bool AArch64FastISel::emitFCmp(MVT RetVT, const Value *LHS, const Value *RHS) {
1483 if (RetVT != MVT::f32 && RetVT != MVT::f64)
1484 return false;
1485
1486 // Check to see if the 2nd operand is a constant that we can encode directly
1487 // in the compare.
1488 bool UseImm = false;
1489 if (const auto *CFP = dyn_cast<ConstantFP>(RHS))
1490 if (CFP->isZero() && !CFP->isNegative())
1491 UseImm = true;
1492
1493 unsigned LHSReg = getRegForValue(LHS);
1494 if (!LHSReg)
1495 return false;
1496 bool LHSIsKill = hasTrivialKill(LHS);
1497
1498 if (UseImm) {
1499 unsigned Opc = (RetVT == MVT::f64) ? AArch64::FCMPDri : AArch64::FCMPSri;
1500 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
1501 .addReg(LHSReg, getKillRegState(LHSIsKill));
1502 return true;
1503 }
1504
1505 unsigned RHSReg = getRegForValue(RHS);
1506 if (!RHSReg)
1507 return false;
1508 bool RHSIsKill = hasTrivialKill(RHS);
1509
1510 unsigned Opc = (RetVT == MVT::f64) ? AArch64::FCMPDrr : AArch64::FCMPSrr;
1511 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
1512 .addReg(LHSReg, getKillRegState(LHSIsKill))
1513 .addReg(RHSReg, getKillRegState(RHSIsKill));
1514 return true;
1515}
1516
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001517unsigned AArch64FastISel::emitAdd(MVT RetVT, const Value *LHS, const Value *RHS,
1518 bool SetFlags, bool WantResult, bool IsZExt) {
1519 return emitAddSub(/*UseAdd=*/true, RetVT, LHS, RHS, SetFlags, WantResult,
1520 IsZExt);
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001521}
1522
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00001523/// This method is a wrapper to simplify add emission.
Juergen Ributzka6780f0f2014-10-15 18:58:02 +00001524///
1525/// First try to emit an add with an immediate operand using emitAddSub_ri. If
1526/// that fails, then try to materialize the immediate into a register and use
1527/// emitAddSub_rr instead.
1528unsigned AArch64FastISel::emitAdd_ri_(MVT VT, unsigned Op0, bool Op0IsKill,
1529 int64_t Imm) {
1530 unsigned ResultReg;
1531 if (Imm < 0)
1532 ResultReg = emitAddSub_ri(false, VT, Op0, Op0IsKill, -Imm);
1533 else
1534 ResultReg = emitAddSub_ri(true, VT, Op0, Op0IsKill, Imm);
1535
1536 if (ResultReg)
1537 return ResultReg;
1538
1539 unsigned CReg = fastEmit_i(VT, VT, ISD::Constant, Imm);
1540 if (!CReg)
1541 return 0;
1542
1543 ResultReg = emitAddSub_rr(true, VT, Op0, Op0IsKill, CReg, true);
1544 return ResultReg;
1545}
1546
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001547unsigned AArch64FastISel::emitSub(MVT RetVT, const Value *LHS, const Value *RHS,
1548 bool SetFlags, bool WantResult, bool IsZExt) {
1549 return emitAddSub(/*UseAdd=*/false, RetVT, LHS, RHS, SetFlags, WantResult,
1550 IsZExt);
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001551}
1552
1553unsigned AArch64FastISel::emitSubs_rr(MVT RetVT, unsigned LHSReg,
1554 bool LHSIsKill, unsigned RHSReg,
1555 bool RHSIsKill, bool WantResult) {
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001556 return emitAddSub_rr(/*UseAdd=*/false, RetVT, LHSReg, LHSIsKill, RHSReg,
1557 RHSIsKill, /*SetFlags=*/true, WantResult);
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001558}
1559
1560unsigned AArch64FastISel::emitSubs_rs(MVT RetVT, unsigned LHSReg,
1561 bool LHSIsKill, unsigned RHSReg,
1562 bool RHSIsKill,
1563 AArch64_AM::ShiftExtendType ShiftType,
1564 uint64_t ShiftImm, bool WantResult) {
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001565 return emitAddSub_rs(/*UseAdd=*/false, RetVT, LHSReg, LHSIsKill, RHSReg,
1566 RHSIsKill, ShiftType, ShiftImm, /*SetFlags=*/true,
1567 WantResult);
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00001568}
1569
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00001570unsigned AArch64FastISel::emitLogicalOp(unsigned ISDOpc, MVT RetVT,
1571 const Value *LHS, const Value *RHS) {
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00001572 // Canonicalize immediates to the RHS first.
1573 if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS))
1574 std::swap(LHS, RHS);
1575
Juergen Ributzka3871c692014-09-17 19:51:38 +00001576 // Canonicalize mul by power-of-2 to the RHS.
1577 if (LHS->hasOneUse() && isValueAvailable(LHS))
1578 if (isMulPowOf2(LHS))
1579 std::swap(LHS, RHS);
1580
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00001581 // Canonicalize shift immediate to the RHS.
Juergen Ributzka3871c692014-09-17 19:51:38 +00001582 if (LHS->hasOneUse() && isValueAvailable(LHS))
1583 if (const auto *SI = dyn_cast<ShlOperator>(LHS))
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00001584 if (isa<ConstantInt>(SI->getOperand(1)))
Juergen Ributzka3871c692014-09-17 19:51:38 +00001585 std::swap(LHS, RHS);
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00001586
1587 unsigned LHSReg = getRegForValue(LHS);
1588 if (!LHSReg)
1589 return 0;
1590 bool LHSIsKill = hasTrivialKill(LHS);
1591
1592 unsigned ResultReg = 0;
1593 if (const auto *C = dyn_cast<ConstantInt>(RHS)) {
1594 uint64_t Imm = C->getZExtValue();
1595 ResultReg = emitLogicalOp_ri(ISDOpc, RetVT, LHSReg, LHSIsKill, Imm);
1596 }
1597 if (ResultReg)
1598 return ResultReg;
1599
Juergen Ributzka3871c692014-09-17 19:51:38 +00001600 // Check if the mul can be folded into the instruction.
Juergen Ributzkab12248e2015-08-19 20:52:55 +00001601 if (RHS->hasOneUse() && isValueAvailable(RHS)) {
Juergen Ributzka3871c692014-09-17 19:51:38 +00001602 if (isMulPowOf2(RHS)) {
1603 const Value *MulLHS = cast<MulOperator>(RHS)->getOperand(0);
1604 const Value *MulRHS = cast<MulOperator>(RHS)->getOperand(1);
1605
1606 if (const auto *C = dyn_cast<ConstantInt>(MulLHS))
1607 if (C->getValue().isPowerOf2())
1608 std::swap(MulLHS, MulRHS);
1609
1610 assert(isa<ConstantInt>(MulRHS) && "Expected a ConstantInt.");
1611 uint64_t ShiftVal = cast<ConstantInt>(MulRHS)->getValue().logBase2();
1612
1613 unsigned RHSReg = getRegForValue(MulLHS);
1614 if (!RHSReg)
1615 return 0;
1616 bool RHSIsKill = hasTrivialKill(MulLHS);
Juergen Ributzkab12248e2015-08-19 20:52:55 +00001617 ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, LHSIsKill, RHSReg,
1618 RHSIsKill, ShiftVal);
1619 if (ResultReg)
1620 return ResultReg;
Juergen Ributzka3871c692014-09-17 19:51:38 +00001621 }
Juergen Ributzkab12248e2015-08-19 20:52:55 +00001622 }
Juergen Ributzka3871c692014-09-17 19:51:38 +00001623
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00001624 // Check if the shift can be folded into the instruction.
Juergen Ributzkab12248e2015-08-19 20:52:55 +00001625 if (RHS->hasOneUse() && isValueAvailable(RHS)) {
Juergen Ributzka3871c692014-09-17 19:51:38 +00001626 if (const auto *SI = dyn_cast<ShlOperator>(RHS))
1627 if (const auto *C = dyn_cast<ConstantInt>(SI->getOperand(1))) {
1628 uint64_t ShiftVal = C->getZExtValue();
1629 unsigned RHSReg = getRegForValue(SI->getOperand(0));
1630 if (!RHSReg)
1631 return 0;
1632 bool RHSIsKill = hasTrivialKill(SI->getOperand(0));
Juergen Ributzkab12248e2015-08-19 20:52:55 +00001633 ResultReg = emitLogicalOp_rs(ISDOpc, RetVT, LHSReg, LHSIsKill, RHSReg,
1634 RHSIsKill, ShiftVal);
1635 if (ResultReg)
1636 return ResultReg;
Juergen Ributzka3871c692014-09-17 19:51:38 +00001637 }
Juergen Ributzkab12248e2015-08-19 20:52:55 +00001638 }
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00001639
1640 unsigned RHSReg = getRegForValue(RHS);
1641 if (!RHSReg)
1642 return 0;
1643 bool RHSIsKill = hasTrivialKill(RHS);
1644
Juergen Ributzka85c1f842014-09-13 23:46:28 +00001645 MVT VT = std::max(MVT::i32, RetVT.SimpleTy);
1646 ResultReg = fastEmit_rr(VT, VT, ISDOpc, LHSReg, LHSIsKill, RHSReg, RHSIsKill);
1647 if (RetVT >= MVT::i8 && RetVT <= MVT::i16) {
1648 uint64_t Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;
1649 ResultReg = emitAnd_ri(MVT::i32, ResultReg, /*IsKill=*/true, Mask);
1650 }
1651 return ResultReg;
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00001652}
1653
1654unsigned AArch64FastISel::emitLogicalOp_ri(unsigned ISDOpc, MVT RetVT,
1655 unsigned LHSReg, bool LHSIsKill,
1656 uint64_t Imm) {
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00001657 static_assert((ISD::AND + 1 == ISD::OR) && (ISD::AND + 2 == ISD::XOR),
1658 "ISD nodes are not consecutive!");
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00001659 static const unsigned OpcTable[3][2] = {
1660 { AArch64::ANDWri, AArch64::ANDXri },
1661 { AArch64::ORRWri, AArch64::ORRXri },
1662 { AArch64::EORWri, AArch64::EORXri }
1663 };
1664 const TargetRegisterClass *RC;
1665 unsigned Opc;
1666 unsigned RegSize;
Juergen Ributzkac83265a2014-08-21 18:02:25 +00001667 switch (RetVT.SimpleTy) {
1668 default:
1669 return 0;
Juergen Ributzka85c1f842014-09-13 23:46:28 +00001670 case MVT::i1:
1671 case MVT::i8:
1672 case MVT::i16:
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00001673 case MVT::i32: {
1674 unsigned Idx = ISDOpc - ISD::AND;
1675 Opc = OpcTable[Idx][0];
Juergen Ributzkac83265a2014-08-21 18:02:25 +00001676 RC = &AArch64::GPR32spRegClass;
1677 RegSize = 32;
1678 break;
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00001679 }
Juergen Ributzkac83265a2014-08-21 18:02:25 +00001680 case MVT::i64:
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00001681 Opc = OpcTable[ISDOpc - ISD::AND][1];
Juergen Ributzkac83265a2014-08-21 18:02:25 +00001682 RC = &AArch64::GPR64spRegClass;
1683 RegSize = 64;
1684 break;
1685 }
1686
1687 if (!AArch64_AM::isLogicalImmediate(Imm, RegSize))
1688 return 0;
1689
Juergen Ributzka85c1f842014-09-13 23:46:28 +00001690 unsigned ResultReg =
1691 fastEmitInst_ri(Opc, RC, LHSReg, LHSIsKill,
1692 AArch64_AM::encodeLogicalImmediate(Imm, RegSize));
1693 if (RetVT >= MVT::i8 && RetVT <= MVT::i16 && ISDOpc != ISD::AND) {
1694 uint64_t Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;
1695 ResultReg = emitAnd_ri(MVT::i32, ResultReg, /*IsKill=*/true, Mask);
1696 }
1697 return ResultReg;
Juergen Ributzkac83265a2014-08-21 18:02:25 +00001698}
1699
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00001700unsigned AArch64FastISel::emitLogicalOp_rs(unsigned ISDOpc, MVT RetVT,
1701 unsigned LHSReg, bool LHSIsKill,
1702 unsigned RHSReg, bool RHSIsKill,
1703 uint64_t ShiftImm) {
Benjamin Kramer3e9a5d32016-05-27 11:36:04 +00001704 static_assert((ISD::AND + 1 == ISD::OR) && (ISD::AND + 2 == ISD::XOR),
1705 "ISD nodes are not consecutive!");
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00001706 static const unsigned OpcTable[3][2] = {
1707 { AArch64::ANDWrs, AArch64::ANDXrs },
1708 { AArch64::ORRWrs, AArch64::ORRXrs },
1709 { AArch64::EORWrs, AArch64::EORXrs }
1710 };
Juergen Ributzkab12248e2015-08-19 20:52:55 +00001711
1712 // Don't deal with undefined shifts.
1713 if (ShiftImm >= RetVT.getSizeInBits())
1714 return 0;
1715
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00001716 const TargetRegisterClass *RC;
1717 unsigned Opc;
1718 switch (RetVT.SimpleTy) {
Juergen Ributzka85c1f842014-09-13 23:46:28 +00001719 default:
1720 return 0;
1721 case MVT::i1:
1722 case MVT::i8:
1723 case MVT::i16:
1724 case MVT::i32:
1725 Opc = OpcTable[ISDOpc - ISD::AND][0];
1726 RC = &AArch64::GPR32RegClass;
1727 break;
1728 case MVT::i64:
1729 Opc = OpcTable[ISDOpc - ISD::AND][1];
1730 RC = &AArch64::GPR64RegClass;
1731 break;
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00001732 }
Juergen Ributzka85c1f842014-09-13 23:46:28 +00001733 unsigned ResultReg =
1734 fastEmitInst_rri(Opc, RC, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
1735 AArch64_AM::getShifterImm(AArch64_AM::LSL, ShiftImm));
1736 if (RetVT >= MVT::i8 && RetVT <= MVT::i16) {
1737 uint64_t Mask = (RetVT == MVT::i8) ? 0xff : 0xffff;
1738 ResultReg = emitAnd_ri(MVT::i32, ResultReg, /*IsKill=*/true, Mask);
1739 }
1740 return ResultReg;
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00001741}
1742
1743unsigned AArch64FastISel::emitAnd_ri(MVT RetVT, unsigned LHSReg, bool LHSIsKill,
1744 uint64_t Imm) {
1745 return emitLogicalOp_ri(ISD::AND, RetVT, LHSReg, LHSIsKill, Imm);
1746}
1747
Juergen Ributzkacd11a282014-10-14 20:36:02 +00001748unsigned AArch64FastISel::emitLoad(MVT VT, MVT RetVT, Address Addr,
1749 bool WantZExt, MachineMemOperand *MMO) {
Sanjay Patel910d5da2015-07-01 17:58:53 +00001750 if (!TLI.allowsMisalignedMemoryAccesses(VT))
Evgeny Astigeevichff1f4be2015-06-15 15:48:44 +00001751 return 0;
1752
Juergen Ributzkab46ea082014-08-19 19:44:17 +00001753 // Simplify this down to something we can handle.
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00001754 if (!simplifyAddress(Addr, VT))
Juergen Ributzkacd11a282014-10-14 20:36:02 +00001755 return 0;
Juergen Ributzkab46ea082014-08-19 19:44:17 +00001756
Juergen Ributzka0616d9d2014-09-30 00:49:54 +00001757 unsigned ScaleFactor = getImplicitScaleFactor(VT);
1758 if (!ScaleFactor)
1759 llvm_unreachable("Unexpected value type.");
Juergen Ributzkab46ea082014-08-19 19:44:17 +00001760
Tim Northover3b0846e2014-05-24 12:50:23 +00001761 // Negative offsets require unscaled, 9-bit, signed immediate offsets.
1762 // Otherwise, we try using scaled, 12-bit, unsigned immediate offsets.
Juergen Ributzkab46ea082014-08-19 19:44:17 +00001763 bool UseScaled = true;
1764 if ((Addr.getOffset() < 0) || (Addr.getOffset() & (ScaleFactor - 1))) {
1765 UseScaled = false;
1766 ScaleFactor = 1;
1767 }
1768
Juergen Ributzka42bf6652014-10-07 03:39:59 +00001769 static const unsigned GPOpcTable[2][8][4] = {
Juergen Ributzka6ac12432014-09-30 00:49:58 +00001770 // Sign-extend.
Juergen Ributzka42bf6652014-10-07 03:39:59 +00001771 { { AArch64::LDURSBWi, AArch64::LDURSHWi, AArch64::LDURWi,
Juergen Ributzka6ac12432014-09-30 00:49:58 +00001772 AArch64::LDURXi },
Juergen Ributzka42bf6652014-10-07 03:39:59 +00001773 { AArch64::LDURSBXi, AArch64::LDURSHXi, AArch64::LDURSWi,
1774 AArch64::LDURXi },
1775 { AArch64::LDRSBWui, AArch64::LDRSHWui, AArch64::LDRWui,
Juergen Ributzka6ac12432014-09-30 00:49:58 +00001776 AArch64::LDRXui },
Juergen Ributzka42bf6652014-10-07 03:39:59 +00001777 { AArch64::LDRSBXui, AArch64::LDRSHXui, AArch64::LDRSWui,
1778 AArch64::LDRXui },
1779 { AArch64::LDRSBWroX, AArch64::LDRSHWroX, AArch64::LDRWroX,
Juergen Ributzka6ac12432014-09-30 00:49:58 +00001780 AArch64::LDRXroX },
Juergen Ributzka42bf6652014-10-07 03:39:59 +00001781 { AArch64::LDRSBXroX, AArch64::LDRSHXroX, AArch64::LDRSWroX,
1782 AArch64::LDRXroX },
1783 { AArch64::LDRSBWroW, AArch64::LDRSHWroW, AArch64::LDRWroW,
Juergen Ributzka6ac12432014-09-30 00:49:58 +00001784 AArch64::LDRXroW },
Juergen Ributzka42bf6652014-10-07 03:39:59 +00001785 { AArch64::LDRSBXroW, AArch64::LDRSHXroW, AArch64::LDRSWroW,
1786 AArch64::LDRXroW }
Juergen Ributzka6ac12432014-09-30 00:49:58 +00001787 },
1788 // Zero-extend.
1789 { { AArch64::LDURBBi, AArch64::LDURHHi, AArch64::LDURWi,
1790 AArch64::LDURXi },
Juergen Ributzka42bf6652014-10-07 03:39:59 +00001791 { AArch64::LDURBBi, AArch64::LDURHHi, AArch64::LDURWi,
1792 AArch64::LDURXi },
1793 { AArch64::LDRBBui, AArch64::LDRHHui, AArch64::LDRWui,
1794 AArch64::LDRXui },
Juergen Ributzka6ac12432014-09-30 00:49:58 +00001795 { AArch64::LDRBBui, AArch64::LDRHHui, AArch64::LDRWui,
1796 AArch64::LDRXui },
1797 { AArch64::LDRBBroX, AArch64::LDRHHroX, AArch64::LDRWroX,
1798 AArch64::LDRXroX },
Juergen Ributzka42bf6652014-10-07 03:39:59 +00001799 { AArch64::LDRBBroX, AArch64::LDRHHroX, AArch64::LDRWroX,
1800 AArch64::LDRXroX },
1801 { AArch64::LDRBBroW, AArch64::LDRHHroW, AArch64::LDRWroW,
1802 AArch64::LDRXroW },
Juergen Ributzka6ac12432014-09-30 00:49:58 +00001803 { AArch64::LDRBBroW, AArch64::LDRHHroW, AArch64::LDRWroW,
1804 AArch64::LDRXroW }
1805 }
1806 };
1807
1808 static const unsigned FPOpcTable[4][2] = {
1809 { AArch64::LDURSi, AArch64::LDURDi },
1810 { AArch64::LDRSui, AArch64::LDRDui },
1811 { AArch64::LDRSroX, AArch64::LDRDroX },
1812 { AArch64::LDRSroW, AArch64::LDRDroW }
Juergen Ributzkab46ea082014-08-19 19:44:17 +00001813 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001814
1815 unsigned Opc;
1816 const TargetRegisterClass *RC;
Juergen Ributzkab46ea082014-08-19 19:44:17 +00001817 bool UseRegOffset = Addr.isRegBase() && !Addr.getOffset() && Addr.getReg() &&
1818 Addr.getOffsetReg();
1819 unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;
1820 if (Addr.getExtendType() == AArch64_AM::UXTW ||
1821 Addr.getExtendType() == AArch64_AM::SXTW)
1822 Idx++;
1823
Juergen Ributzka42bf6652014-10-07 03:39:59 +00001824 bool IsRet64Bit = RetVT == MVT::i64;
Tim Northover3b0846e2014-05-24 12:50:23 +00001825 switch (VT.SimpleTy) {
Juergen Ributzka6ac12432014-09-30 00:49:58 +00001826 default:
1827 llvm_unreachable("Unexpected value type.");
1828 case MVT::i1: // Intentional fall-through.
1829 case MVT::i8:
Juergen Ributzka42bf6652014-10-07 03:39:59 +00001830 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][0];
1831 RC = (IsRet64Bit && !WantZExt) ?
1832 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
Juergen Ributzka6ac12432014-09-30 00:49:58 +00001833 break;
1834 case MVT::i16:
Juergen Ributzka42bf6652014-10-07 03:39:59 +00001835 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][1];
1836 RC = (IsRet64Bit && !WantZExt) ?
1837 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
Juergen Ributzka6ac12432014-09-30 00:49:58 +00001838 break;
1839 case MVT::i32:
Juergen Ributzka42bf6652014-10-07 03:39:59 +00001840 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][2];
1841 RC = (IsRet64Bit && !WantZExt) ?
1842 &AArch64::GPR64RegClass: &AArch64::GPR32RegClass;
Juergen Ributzka6ac12432014-09-30 00:49:58 +00001843 break;
1844 case MVT::i64:
Juergen Ributzka42bf6652014-10-07 03:39:59 +00001845 Opc = GPOpcTable[WantZExt][2 * Idx + IsRet64Bit][3];
Juergen Ributzka6ac12432014-09-30 00:49:58 +00001846 RC = &AArch64::GPR64RegClass;
1847 break;
1848 case MVT::f32:
1849 Opc = FPOpcTable[Idx][0];
1850 RC = &AArch64::FPR32RegClass;
1851 break;
1852 case MVT::f64:
1853 Opc = FPOpcTable[Idx][1];
1854 RC = &AArch64::FPR64RegClass;
1855 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001856 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001857
1858 // Create the base instruction, then add the operands.
Juergen Ributzkacd11a282014-10-14 20:36:02 +00001859 unsigned ResultReg = createResultReg(RC);
Tim Northover3b0846e2014-05-24 12:50:23 +00001860 MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1861 TII.get(Opc), ResultReg);
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00001862 addLoadStoreOperands(Addr, MIB, MachineMemOperand::MOLoad, ScaleFactor, MMO);
Tim Northover3b0846e2014-05-24 12:50:23 +00001863
Juergen Ributzkacd11a282014-10-14 20:36:02 +00001864 // Loading an i1 requires special handling.
1865 if (VT == MVT::i1) {
1866 unsigned ANDReg = emitAnd_ri(MVT::i32, ResultReg, /*IsKill=*/true, 1);
1867 assert(ANDReg && "Unexpected AND instruction emission failure.");
1868 ResultReg = ANDReg;
1869 }
1870
Juergen Ributzka42bf6652014-10-07 03:39:59 +00001871 // For zero-extending loads to 64bit we emit a 32bit load and then convert
Juergen Ributzkacd11a282014-10-14 20:36:02 +00001872 // the 32bit reg to a 64bit reg.
Juergen Ributzka42bf6652014-10-07 03:39:59 +00001873 if (WantZExt && RetVT == MVT::i64 && VT <= MVT::i32) {
1874 unsigned Reg64 = createResultReg(&AArch64::GPR64RegClass);
1875 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1876 TII.get(AArch64::SUBREG_TO_REG), Reg64)
1877 .addImm(0)
1878 .addReg(ResultReg, getKillRegState(true))
1879 .addImm(AArch64::sub_32);
1880 ResultReg = Reg64;
1881 }
Juergen Ributzkacd11a282014-10-14 20:36:02 +00001882 return ResultReg;
Tim Northover3b0846e2014-05-24 12:50:23 +00001883}
1884
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001885bool AArch64FastISel::selectAddSub(const Instruction *I) {
1886 MVT VT;
Juergen Ributzkae1779e22014-09-15 21:27:56 +00001887 if (!isTypeSupported(I->getType(), VT, /*IsVectorAllowed=*/true))
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001888 return false;
1889
Juergen Ributzkae1779e22014-09-15 21:27:56 +00001890 if (VT.isVector())
1891 return selectOperator(I, I->getOpcode());
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001892
Juergen Ributzkae1779e22014-09-15 21:27:56 +00001893 unsigned ResultReg;
1894 switch (I->getOpcode()) {
1895 default:
1896 llvm_unreachable("Unexpected instruction.");
1897 case Instruction::Add:
1898 ResultReg = emitAdd(VT, I->getOperand(0), I->getOperand(1));
1899 break;
1900 case Instruction::Sub:
1901 ResultReg = emitSub(VT, I->getOperand(0), I->getOperand(1));
1902 break;
1903 }
1904 if (!ResultReg)
1905 return false;
1906
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00001907 updateValueMap(I, ResultReg);
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00001908 return true;
1909}
1910
Juergen Ributzkae1779e22014-09-15 21:27:56 +00001911bool AArch64FastISel::selectLogicalOp(const Instruction *I) {
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00001912 MVT VT;
Juergen Ributzkae1779e22014-09-15 21:27:56 +00001913 if (!isTypeSupported(I->getType(), VT, /*IsVectorAllowed=*/true))
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00001914 return false;
1915
Juergen Ributzkae1779e22014-09-15 21:27:56 +00001916 if (VT.isVector())
1917 return selectOperator(I, I->getOpcode());
1918
1919 unsigned ResultReg;
1920 switch (I->getOpcode()) {
1921 default:
1922 llvm_unreachable("Unexpected instruction.");
1923 case Instruction::And:
1924 ResultReg = emitLogicalOp(ISD::AND, VT, I->getOperand(0), I->getOperand(1));
1925 break;
1926 case Instruction::Or:
1927 ResultReg = emitLogicalOp(ISD::OR, VT, I->getOperand(0), I->getOperand(1));
1928 break;
1929 case Instruction::Xor:
1930 ResultReg = emitLogicalOp(ISD::XOR, VT, I->getOperand(0), I->getOperand(1));
1931 break;
1932 }
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00001933 if (!ResultReg)
1934 return false;
1935
1936 updateValueMap(I, ResultReg);
1937 return true;
1938}
1939
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00001940bool AArch64FastISel::selectLoad(const Instruction *I) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001941 MVT VT;
1942 // Verify we have a legal type before going any further. Currently, we handle
1943 // simple types that will directly fit in a register (i32/f32/i64/f64) or
1944 // those that can be sign or zero-extended to a basic operation (i1/i8/i16).
Juergen Ributzka6127b192014-09-15 21:27:54 +00001945 if (!isTypeSupported(I->getType(), VT, /*IsVectorAllowed=*/true) ||
1946 cast<LoadInst>(I)->isAtomic())
Tim Northover3b0846e2014-05-24 12:50:23 +00001947 return false;
1948
Manman Ren57518142016-04-11 21:08:06 +00001949 const Value *SV = I->getOperand(0);
1950 if (TLI.supportSwiftError()) {
1951 // Swifterror values can come from either a function parameter with
1952 // swifterror attribute or an alloca with swifterror attribute.
1953 if (const Argument *Arg = dyn_cast<Argument>(SV)) {
1954 if (Arg->hasSwiftErrorAttr())
1955 return false;
1956 }
1957
1958 if (const AllocaInst *Alloca = dyn_cast<AllocaInst>(SV)) {
1959 if (Alloca->isSwiftError())
1960 return false;
1961 }
1962 }
1963
Tim Northover3b0846e2014-05-24 12:50:23 +00001964 // See if we can handle this address.
1965 Address Addr;
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00001966 if (!computeAddress(I->getOperand(0), Addr, I->getType()))
Tim Northover3b0846e2014-05-24 12:50:23 +00001967 return false;
1968
Juergen Ributzkacd11a282014-10-14 20:36:02 +00001969 // Fold the following sign-/zero-extend into the load instruction.
Juergen Ributzka6ac12432014-09-30 00:49:58 +00001970 bool WantZExt = true;
Juergen Ributzka42bf6652014-10-07 03:39:59 +00001971 MVT RetVT = VT;
Juergen Ributzkacd11a282014-10-14 20:36:02 +00001972 const Value *IntExtVal = nullptr;
Juergen Ributzka42bf6652014-10-07 03:39:59 +00001973 if (I->hasOneUse()) {
1974 if (const auto *ZE = dyn_cast<ZExtInst>(I->use_begin()->getUser())) {
Juergen Ributzkacd11a282014-10-14 20:36:02 +00001975 if (isTypeSupported(ZE->getType(), RetVT))
1976 IntExtVal = ZE;
1977 else
Juergen Ributzka42bf6652014-10-07 03:39:59 +00001978 RetVT = VT;
1979 } else if (const auto *SE = dyn_cast<SExtInst>(I->use_begin()->getUser())) {
Juergen Ributzkacd11a282014-10-14 20:36:02 +00001980 if (isTypeSupported(SE->getType(), RetVT))
1981 IntExtVal = SE;
1982 else
Juergen Ributzka42bf6652014-10-07 03:39:59 +00001983 RetVT = VT;
1984 WantZExt = false;
1985 }
1986 }
Juergen Ributzka6ac12432014-09-30 00:49:58 +00001987
Juergen Ributzkacd11a282014-10-14 20:36:02 +00001988 unsigned ResultReg =
1989 emitLoad(VT, RetVT, Addr, WantZExt, createMachineMemOperandFor(I));
1990 if (!ResultReg)
Tim Northover3b0846e2014-05-24 12:50:23 +00001991 return false;
1992
Juergen Ributzkacd11a282014-10-14 20:36:02 +00001993 // There are a few different cases we have to handle, because the load or the
1994 // sign-/zero-extend might not be selected by FastISel if we fall-back to
1995 // SelectionDAG. There is also an ordering issue when both instructions are in
1996 // different basic blocks.
1997 // 1.) The load instruction is selected by FastISel, but the integer extend
1998 // not. This usually happens when the integer extend is in a different
1999 // basic block and SelectionDAG took over for that basic block.
2000 // 2.) The load instruction is selected before the integer extend. This only
2001 // happens when the integer extend is in a different basic block.
2002 // 3.) The load instruction is selected by SelectionDAG and the integer extend
2003 // by FastISel. This happens if there are instructions between the load
2004 // and the integer extend that couldn't be selected by FastISel.
2005 if (IntExtVal) {
2006 // The integer extend hasn't been emitted yet. FastISel or SelectionDAG
2007 // could select it. Emit a copy to subreg if necessary. FastISel will remove
2008 // it when it selects the integer extend.
2009 unsigned Reg = lookUpRegForValue(IntExtVal);
Juergen Ributzkabd0c7eb2015-04-09 20:00:46 +00002010 auto *MI = MRI.getUniqueVRegDef(Reg);
2011 if (!MI) {
Juergen Ributzkacd11a282014-10-14 20:36:02 +00002012 if (RetVT == MVT::i64 && VT <= MVT::i32) {
2013 if (WantZExt) {
2014 // Delete the last emitted instruction from emitLoad (SUBREG_TO_REG).
Tim Northover256a16d2018-12-17 17:25:53 +00002015 MachineBasicBlock::iterator I(std::prev(FuncInfo.InsertPt));
2016 ResultReg = std::prev(I)->getOperand(0).getReg();
2017 removeDeadCode(I, std::next(I));
Juergen Ributzkacd11a282014-10-14 20:36:02 +00002018 } else
2019 ResultReg = fastEmitInst_extractsubreg(MVT::i32, ResultReg,
2020 /*IsKill=*/true,
2021 AArch64::sub_32);
2022 }
2023 updateValueMap(I, ResultReg);
2024 return true;
2025 }
2026
2027 // The integer extend has already been emitted - delete all the instructions
2028 // that have been emitted by the integer extend lowering code and use the
2029 // result from the load instruction directly.
Juergen Ributzkabd0c7eb2015-04-09 20:00:46 +00002030 while (MI) {
Juergen Ributzkacd11a282014-10-14 20:36:02 +00002031 Reg = 0;
2032 for (auto &Opnd : MI->uses()) {
2033 if (Opnd.isReg()) {
2034 Reg = Opnd.getReg();
2035 break;
2036 }
2037 }
Tim Northover256a16d2018-12-17 17:25:53 +00002038 MachineBasicBlock::iterator I(MI);
2039 removeDeadCode(I, std::next(I));
Juergen Ributzkabd0c7eb2015-04-09 20:00:46 +00002040 MI = nullptr;
2041 if (Reg)
2042 MI = MRI.getUniqueVRegDef(Reg);
Juergen Ributzkacd11a282014-10-14 20:36:02 +00002043 }
2044 updateValueMap(IntExtVal, ResultReg);
2045 return true;
2046 }
2047
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00002048 updateValueMap(I, ResultReg);
Tim Northover3b0846e2014-05-24 12:50:23 +00002049 return true;
2050}
2051
Ahmed Bougachab0674d12016-07-20 21:12:27 +00002052bool AArch64FastISel::emitStoreRelease(MVT VT, unsigned SrcReg,
2053 unsigned AddrReg,
2054 MachineMemOperand *MMO) {
2055 unsigned Opc;
2056 switch (VT.SimpleTy) {
2057 default: return false;
2058 case MVT::i8: Opc = AArch64::STLRB; break;
2059 case MVT::i16: Opc = AArch64::STLRH; break;
2060 case MVT::i32: Opc = AArch64::STLRW; break;
2061 case MVT::i64: Opc = AArch64::STLRX; break;
2062 }
2063
2064 const MCInstrDesc &II = TII.get(Opc);
2065 SrcReg = constrainOperandRegClass(II, SrcReg, 0);
2066 AddrReg = constrainOperandRegClass(II, AddrReg, 1);
2067 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
2068 .addReg(SrcReg)
2069 .addReg(AddrReg)
2070 .addMemOperand(MMO);
2071 return true;
2072}
2073
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00002074bool AArch64FastISel::emitStore(MVT VT, unsigned SrcReg, Address Addr,
Juergen Ributzkab46ea082014-08-19 19:44:17 +00002075 MachineMemOperand *MMO) {
Sanjay Patel910d5da2015-07-01 17:58:53 +00002076 if (!TLI.allowsMisalignedMemoryAccesses(VT))
Evgeny Astigeevichff1f4be2015-06-15 15:48:44 +00002077 return false;
2078
Juergen Ributzkab46ea082014-08-19 19:44:17 +00002079 // Simplify this down to something we can handle.
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00002080 if (!simplifyAddress(Addr, VT))
Juergen Ributzkab46ea082014-08-19 19:44:17 +00002081 return false;
2082
Juergen Ributzka0616d9d2014-09-30 00:49:54 +00002083 unsigned ScaleFactor = getImplicitScaleFactor(VT);
2084 if (!ScaleFactor)
2085 llvm_unreachable("Unexpected value type.");
Juergen Ributzkab46ea082014-08-19 19:44:17 +00002086
Tim Northover3b0846e2014-05-24 12:50:23 +00002087 // Negative offsets require unscaled, 9-bit, signed immediate offsets.
2088 // Otherwise, we try using scaled, 12-bit, unsigned immediate offsets.
Juergen Ributzkab46ea082014-08-19 19:44:17 +00002089 bool UseScaled = true;
2090 if ((Addr.getOffset() < 0) || (Addr.getOffset() & (ScaleFactor - 1))) {
2091 UseScaled = false;
Juergen Ributzka34ed4222014-08-14 17:10:54 +00002092 ScaleFactor = 1;
Juergen Ributzka34ed4222014-08-14 17:10:54 +00002093 }
2094
Juergen Ributzkab46ea082014-08-19 19:44:17 +00002095 static const unsigned OpcTable[4][6] = {
2096 { AArch64::STURBBi, AArch64::STURHHi, AArch64::STURWi, AArch64::STURXi,
2097 AArch64::STURSi, AArch64::STURDi },
2098 { AArch64::STRBBui, AArch64::STRHHui, AArch64::STRWui, AArch64::STRXui,
2099 AArch64::STRSui, AArch64::STRDui },
2100 { AArch64::STRBBroX, AArch64::STRHHroX, AArch64::STRWroX, AArch64::STRXroX,
2101 AArch64::STRSroX, AArch64::STRDroX },
2102 { AArch64::STRBBroW, AArch64::STRHHroW, AArch64::STRWroW, AArch64::STRXroW,
2103 AArch64::STRSroW, AArch64::STRDroW }
Juergen Ributzkab46ea082014-08-19 19:44:17 +00002104 };
2105
2106 unsigned Opc;
2107 bool VTIsi1 = false;
2108 bool UseRegOffset = Addr.isRegBase() && !Addr.getOffset() && Addr.getReg() &&
2109 Addr.getOffsetReg();
2110 unsigned Idx = UseRegOffset ? 2 : UseScaled ? 1 : 0;
2111 if (Addr.getExtendType() == AArch64_AM::UXTW ||
2112 Addr.getExtendType() == AArch64_AM::SXTW)
2113 Idx++;
2114
2115 switch (VT.SimpleTy) {
2116 default: llvm_unreachable("Unexpected value type.");
Simon Pilgrim8b4dc532017-07-07 13:03:28 +00002117 case MVT::i1: VTIsi1 = true; LLVM_FALLTHROUGH;
Juergen Ributzkab46ea082014-08-19 19:44:17 +00002118 case MVT::i8: Opc = OpcTable[Idx][0]; break;
2119 case MVT::i16: Opc = OpcTable[Idx][1]; break;
2120 case MVT::i32: Opc = OpcTable[Idx][2]; break;
2121 case MVT::i64: Opc = OpcTable[Idx][3]; break;
2122 case MVT::f32: Opc = OpcTable[Idx][4]; break;
2123 case MVT::f64: Opc = OpcTable[Idx][5]; break;
2124 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002125
2126 // Storing an i1 requires special handling.
Juergen Ributzka100a9b72014-08-27 21:04:52 +00002127 if (VTIsi1 && SrcReg != AArch64::WZR) {
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00002128 unsigned ANDReg = emitAnd_ri(MVT::i32, SrcReg, /*TODO:IsKill=*/false, 1);
Juergen Ributzkac83265a2014-08-21 18:02:25 +00002129 assert(ANDReg && "Unexpected AND instruction emission failure.");
Tim Northover3b0846e2014-05-24 12:50:23 +00002130 SrcReg = ANDReg;
2131 }
2132 // Create the base instruction, then add the operands.
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00002133 const MCInstrDesc &II = TII.get(Opc);
2134 SrcReg = constrainOperandRegClass(II, SrcReg, II.getNumDefs());
2135 MachineInstrBuilder MIB =
2136 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II).addReg(SrcReg);
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00002137 addLoadStoreOperands(Addr, MIB, MachineMemOperand::MOStore, ScaleFactor, MMO);
Juergen Ributzka241fd482014-08-08 17:24:10 +00002138
Tim Northover3b0846e2014-05-24 12:50:23 +00002139 return true;
2140}
2141
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00002142bool AArch64FastISel::selectStore(const Instruction *I) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002143 MVT VT;
Juergen Ributzka100a9b72014-08-27 21:04:52 +00002144 const Value *Op0 = I->getOperand(0);
Tim Northover3b0846e2014-05-24 12:50:23 +00002145 // Verify we have a legal type before going any further. Currently, we handle
2146 // simple types that will directly fit in a register (i32/f32/i64/f64) or
2147 // those that can be sign or zero-extended to a basic operation (i1/i8/i16).
Ahmed Bougachab0674d12016-07-20 21:12:27 +00002148 if (!isTypeSupported(Op0->getType(), VT, /*IsVectorAllowed=*/true))
Tim Northover3b0846e2014-05-24 12:50:23 +00002149 return false;
2150
Manman Ren57518142016-04-11 21:08:06 +00002151 const Value *PtrV = I->getOperand(1);
2152 if (TLI.supportSwiftError()) {
2153 // Swifterror values can come from either a function parameter with
2154 // swifterror attribute or an alloca with swifterror attribute.
2155 if (const Argument *Arg = dyn_cast<Argument>(PtrV)) {
2156 if (Arg->hasSwiftErrorAttr())
2157 return false;
2158 }
2159
2160 if (const AllocaInst *Alloca = dyn_cast<AllocaInst>(PtrV)) {
2161 if (Alloca->isSwiftError())
2162 return false;
2163 }
2164 }
2165
Juergen Ributzka100a9b72014-08-27 21:04:52 +00002166 // Get the value to be stored into a register. Use the zero register directly
Juergen Ributzka56b4b332014-08-27 21:40:50 +00002167 // when possible to avoid an unnecessary copy and a wasted register.
Juergen Ributzka100a9b72014-08-27 21:04:52 +00002168 unsigned SrcReg = 0;
2169 if (const auto *CI = dyn_cast<ConstantInt>(Op0)) {
2170 if (CI->isZero())
2171 SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
2172 } else if (const auto *CF = dyn_cast<ConstantFP>(Op0)) {
2173 if (CF->isZero() && !CF->isNegative()) {
2174 VT = MVT::getIntegerVT(VT.getSizeInBits());
2175 SrcReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
2176 }
2177 }
2178
2179 if (!SrcReg)
2180 SrcReg = getRegForValue(Op0);
2181
2182 if (!SrcReg)
Tim Northover3b0846e2014-05-24 12:50:23 +00002183 return false;
2184
Ahmed Bougachab0674d12016-07-20 21:12:27 +00002185 auto *SI = cast<StoreInst>(I);
2186
2187 // Try to emit a STLR for seq_cst/release.
2188 if (SI->isAtomic()) {
2189 AtomicOrdering Ord = SI->getOrdering();
2190 // The non-atomic instructions are sufficient for relaxed stores.
2191 if (isReleaseOrStronger(Ord)) {
2192 // The STLR addressing mode only supports a base reg; pass that directly.
2193 unsigned AddrReg = getRegForValue(PtrV);
2194 return emitStoreRelease(VT, SrcReg, AddrReg,
2195 createMachineMemOperandFor(I));
2196 }
2197 }
2198
Tim Northover3b0846e2014-05-24 12:50:23 +00002199 // See if we can handle this address.
2200 Address Addr;
Ahmed Bougachab0674d12016-07-20 21:12:27 +00002201 if (!computeAddress(PtrV, Addr, Op0->getType()))
Tim Northover3b0846e2014-05-24 12:50:23 +00002202 return false;
2203
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00002204 if (!emitStore(VT, SrcReg, Addr, createMachineMemOperandFor(I)))
Tim Northover3b0846e2014-05-24 12:50:23 +00002205 return false;
2206 return true;
2207}
2208
2209static AArch64CC::CondCode getCompareCC(CmpInst::Predicate Pred) {
2210 switch (Pred) {
2211 case CmpInst::FCMP_ONE:
2212 case CmpInst::FCMP_UEQ:
2213 default:
2214 // AL is our "false" for now. The other two need more compares.
2215 return AArch64CC::AL;
2216 case CmpInst::ICMP_EQ:
2217 case CmpInst::FCMP_OEQ:
2218 return AArch64CC::EQ;
2219 case CmpInst::ICMP_SGT:
2220 case CmpInst::FCMP_OGT:
2221 return AArch64CC::GT;
2222 case CmpInst::ICMP_SGE:
2223 case CmpInst::FCMP_OGE:
2224 return AArch64CC::GE;
2225 case CmpInst::ICMP_UGT:
2226 case CmpInst::FCMP_UGT:
2227 return AArch64CC::HI;
2228 case CmpInst::FCMP_OLT:
2229 return AArch64CC::MI;
2230 case CmpInst::ICMP_ULE:
2231 case CmpInst::FCMP_OLE:
2232 return AArch64CC::LS;
2233 case CmpInst::FCMP_ORD:
2234 return AArch64CC::VC;
2235 case CmpInst::FCMP_UNO:
2236 return AArch64CC::VS;
2237 case CmpInst::FCMP_UGE:
2238 return AArch64CC::PL;
2239 case CmpInst::ICMP_SLT:
2240 case CmpInst::FCMP_ULT:
2241 return AArch64CC::LT;
2242 case CmpInst::ICMP_SLE:
2243 case CmpInst::FCMP_ULE:
2244 return AArch64CC::LE;
2245 case CmpInst::FCMP_UNE:
2246 case CmpInst::ICMP_NE:
2247 return AArch64CC::NE;
2248 case CmpInst::ICMP_UGE:
2249 return AArch64CC::HS;
2250 case CmpInst::ICMP_ULT:
2251 return AArch64CC::LO;
2252 }
2253}
2254
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00002255/// Try to emit a combined compare-and-branch instruction.
Juergen Ributzkac110c0b2014-09-30 19:59:35 +00002256bool AArch64FastISel::emitCompareAndBranch(const BranchInst *BI) {
Kristof Beylse66bc1f2018-12-18 08:50:02 +00002257 // Speculation tracking/SLH assumes that optimized TB(N)Z/CB(N)Z instructions
2258 // will not be produced, as they are conditional branch instructions that do
2259 // not set flags.
2260 if (FuncInfo.MF->getFunction().hasFnAttribute(
2261 Attribute::SpeculativeLoadHardening))
2262 return false;
2263
Juergen Ributzkac110c0b2014-09-30 19:59:35 +00002264 assert(isa<CmpInst>(BI->getCondition()) && "Expected cmp instruction");
2265 const CmpInst *CI = cast<CmpInst>(BI->getCondition());
2266 CmpInst::Predicate Predicate = optimizeCmpPredicate(CI);
Juergen Ributzkad8e30c02014-09-17 18:05:34 +00002267
Juergen Ributzkac110c0b2014-09-30 19:59:35 +00002268 const Value *LHS = CI->getOperand(0);
2269 const Value *RHS = CI->getOperand(1);
2270
Juergen Ributzka90f741a2014-10-27 19:38:05 +00002271 MVT VT;
2272 if (!isTypeSupported(LHS->getType(), VT))
2273 return false;
Juergen Ributzkad8e30c02014-09-17 18:05:34 +00002274
Juergen Ributzka90f741a2014-10-27 19:38:05 +00002275 unsigned BW = VT.getSizeInBits();
2276 if (BW > 64)
Juergen Ributzkad8e30c02014-09-17 18:05:34 +00002277 return false;
2278
Juergen Ributzkac110c0b2014-09-30 19:59:35 +00002279 MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)];
2280 MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)];
Juergen Ributzkad8e30c02014-09-17 18:05:34 +00002281
Juergen Ributzkac110c0b2014-09-30 19:59:35 +00002282 // Try to take advantage of fallthrough opportunities.
2283 if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {
2284 std::swap(TBB, FBB);
2285 Predicate = CmpInst::getInversePredicate(Predicate);
2286 }
Juergen Ributzkad8e30c02014-09-17 18:05:34 +00002287
Juergen Ributzkac110c0b2014-09-30 19:59:35 +00002288 int TestBit = -1;
2289 bool IsCmpNE;
Juergen Ributzkaeb67bd82014-11-25 04:16:15 +00002290 switch (Predicate) {
2291 default:
2292 return false;
2293 case CmpInst::ICMP_EQ:
2294 case CmpInst::ICMP_NE:
2295 if (isa<Constant>(LHS) && cast<Constant>(LHS)->isNullValue())
2296 std::swap(LHS, RHS);
Juergen Ributzkac110c0b2014-09-30 19:59:35 +00002297
Juergen Ributzkaeb67bd82014-11-25 04:16:15 +00002298 if (!isa<Constant>(RHS) || !cast<Constant>(RHS)->isNullValue())
Juergen Ributzkac110c0b2014-09-30 19:59:35 +00002299 return false;
2300
2301 if (const auto *AI = dyn_cast<BinaryOperator>(LHS))
Juergen Ributzkaeae91042014-10-27 19:16:48 +00002302 if (AI->getOpcode() == Instruction::And && isValueAvailable(AI)) {
Juergen Ributzkac110c0b2014-09-30 19:59:35 +00002303 const Value *AndLHS = AI->getOperand(0);
2304 const Value *AndRHS = AI->getOperand(1);
2305
2306 if (const auto *C = dyn_cast<ConstantInt>(AndLHS))
2307 if (C->getValue().isPowerOf2())
2308 std::swap(AndLHS, AndRHS);
2309
2310 if (const auto *C = dyn_cast<ConstantInt>(AndRHS))
2311 if (C->getValue().isPowerOf2()) {
2312 TestBit = C->getValue().logBase2();
2313 LHS = AndLHS;
2314 }
2315 }
Juergen Ributzka0190fea2014-10-27 19:46:23 +00002316
2317 if (VT == MVT::i1)
2318 TestBit = 0;
2319
Juergen Ributzkac110c0b2014-09-30 19:59:35 +00002320 IsCmpNE = Predicate == CmpInst::ICMP_NE;
Juergen Ributzkaeb67bd82014-11-25 04:16:15 +00002321 break;
2322 case CmpInst::ICMP_SLT:
2323 case CmpInst::ICMP_SGE:
2324 if (!isa<Constant>(RHS) || !cast<Constant>(RHS)->isNullValue())
Juergen Ributzkac110c0b2014-09-30 19:59:35 +00002325 return false;
2326
2327 TestBit = BW - 1;
Juergen Ributzkaeb67bd82014-11-25 04:16:15 +00002328 IsCmpNE = Predicate == CmpInst::ICMP_SLT;
2329 break;
2330 case CmpInst::ICMP_SGT:
2331 case CmpInst::ICMP_SLE:
Juergen Ributzkac110c0b2014-09-30 19:59:35 +00002332 if (!isa<ConstantInt>(RHS))
2333 return false;
2334
Juergen Ributzkaeb67bd82014-11-25 04:16:15 +00002335 if (cast<ConstantInt>(RHS)->getValue() != APInt(BW, -1, true))
Juergen Ributzkac110c0b2014-09-30 19:59:35 +00002336 return false;
2337
2338 TestBit = BW - 1;
Juergen Ributzkaeb67bd82014-11-25 04:16:15 +00002339 IsCmpNE = Predicate == CmpInst::ICMP_SLE;
2340 break;
2341 } // end switch
Juergen Ributzkac110c0b2014-09-30 19:59:35 +00002342
2343 static const unsigned OpcTable[2][2][2] = {
2344 { {AArch64::CBZW, AArch64::CBZX },
2345 {AArch64::CBNZW, AArch64::CBNZX} },
2346 { {AArch64::TBZW, AArch64::TBZX },
2347 {AArch64::TBNZW, AArch64::TBNZX} }
2348 };
2349
2350 bool IsBitTest = TestBit != -1;
2351 bool Is64Bit = BW == 64;
2352 if (TestBit < 32 && TestBit >= 0)
2353 Is64Bit = false;
Juergen Ributzkaeae91042014-10-27 19:16:48 +00002354
Juergen Ributzkac110c0b2014-09-30 19:59:35 +00002355 unsigned Opc = OpcTable[IsBitTest][IsCmpNE][Is64Bit];
2356 const MCInstrDesc &II = TII.get(Opc);
2357
2358 unsigned SrcReg = getRegForValue(LHS);
2359 if (!SrcReg)
2360 return false;
2361 bool SrcIsKill = hasTrivialKill(LHS);
2362
Juergen Ributzkacd11a282014-10-14 20:36:02 +00002363 if (BW == 64 && !Is64Bit)
Juergen Ributzkac110c0b2014-09-30 19:59:35 +00002364 SrcReg = fastEmitInst_extractsubreg(MVT::i32, SrcReg, SrcIsKill,
2365 AArch64::sub_32);
Juergen Ributzkac110c0b2014-09-30 19:59:35 +00002366
Juergen Ributzka90f741a2014-10-27 19:38:05 +00002367 if ((BW < 32) && !IsBitTest)
2368 SrcReg = emitIntExt(VT, SrcReg, MVT::i32, /*IsZExt=*/true);
Oliver Stannardf7a5afc2014-10-24 09:54:41 +00002369
Juergen Ributzkac110c0b2014-09-30 19:59:35 +00002370 // Emit the combined compare and branch instruction.
Juergen Ributzkacd11a282014-10-14 20:36:02 +00002371 SrcReg = constrainOperandRegClass(II, SrcReg, II.getNumDefs());
Juergen Ributzkac110c0b2014-09-30 19:59:35 +00002372 MachineInstrBuilder MIB =
2373 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
2374 .addReg(SrcReg, getKillRegState(SrcIsKill));
2375 if (IsBitTest)
2376 MIB.addImm(TestBit);
2377 MIB.addMBB(TBB);
2378
Matthias Braun17af6072015-08-26 01:38:00 +00002379 finishCondBranch(BI->getParent(), TBB, FBB);
Juergen Ributzkac110c0b2014-09-30 19:59:35 +00002380 return true;
Juergen Ributzkad8e30c02014-09-17 18:05:34 +00002381}
2382
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00002383bool AArch64FastISel::selectBranch(const Instruction *I) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002384 const BranchInst *BI = cast<BranchInst>(I);
Juergen Ributzka31c80542014-09-03 17:58:10 +00002385 if (BI->isUnconditional()) {
2386 MachineBasicBlock *MSucc = FuncInfo.MBBMap[BI->getSuccessor(0)];
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00002387 fastEmitBranch(MSucc, BI->getDebugLoc());
Juergen Ributzka31c80542014-09-03 17:58:10 +00002388 return true;
2389 }
2390
Tim Northover3b0846e2014-05-24 12:50:23 +00002391 MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)];
2392 MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)];
2393
2394 if (const CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition())) {
Juergen Ributzkafb3e1432014-09-17 17:46:47 +00002395 if (CI->hasOneUse() && isValueAvailable(CI)) {
2396 // Try to optimize or fold the cmp.
2397 CmpInst::Predicate Predicate = optimizeCmpPredicate(CI);
2398 switch (Predicate) {
2399 default:
2400 break;
2401 case CmpInst::FCMP_FALSE:
2402 fastEmitBranch(FBB, DbgLoc);
2403 return true;
2404 case CmpInst::FCMP_TRUE:
2405 fastEmitBranch(TBB, DbgLoc);
2406 return true;
2407 }
2408
Juergen Ributzkac110c0b2014-09-30 19:59:35 +00002409 // Try to emit a combined compare-and-branch first.
2410 if (emitCompareAndBranch(BI))
2411 return true;
2412
Juergen Ributzkafb3e1432014-09-17 17:46:47 +00002413 // Try to take advantage of fallthrough opportunities.
2414 if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {
2415 std::swap(TBB, FBB);
2416 Predicate = CmpInst::getInversePredicate(Predicate);
2417 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002418
2419 // Emit the cmp.
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00002420 if (!emitCmp(CI->getOperand(0), CI->getOperand(1), CI->isUnsigned()))
Tim Northover3b0846e2014-05-24 12:50:23 +00002421 return false;
2422
Juergen Ributzkafb3e1432014-09-17 17:46:47 +00002423 // FCMP_UEQ and FCMP_ONE cannot be checked with a single branch
2424 // instruction.
Matthias Braun0d4505c2015-12-03 17:19:58 +00002425 AArch64CC::CondCode CC = getCompareCC(Predicate);
Juergen Ributzkafb3e1432014-09-17 17:46:47 +00002426 AArch64CC::CondCode ExtraCC = AArch64CC::AL;
2427 switch (Predicate) {
2428 default:
2429 break;
2430 case CmpInst::FCMP_UEQ:
2431 ExtraCC = AArch64CC::EQ;
2432 CC = AArch64CC::VS;
2433 break;
2434 case CmpInst::FCMP_ONE:
2435 ExtraCC = AArch64CC::MI;
2436 CC = AArch64CC::GT;
2437 break;
2438 }
2439 assert((CC != AArch64CC::AL) && "Unexpected condition code.");
2440
2441 // Emit the extra branch for FCMP_UEQ and FCMP_ONE.
2442 if (ExtraCC != AArch64CC::AL) {
2443 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::Bcc))
2444 .addImm(ExtraCC)
2445 .addMBB(TBB);
2446 }
2447
Tim Northover3b0846e2014-05-24 12:50:23 +00002448 // Emit the branch.
2449 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::Bcc))
2450 .addImm(CC)
2451 .addMBB(TBB);
Juergen Ributzka50a40052014-08-01 18:39:24 +00002452
Matthias Braun17af6072015-08-26 01:38:00 +00002453 finishCondBranch(BI->getParent(), TBB, FBB);
Tim Northover3b0846e2014-05-24 12:50:23 +00002454 return true;
2455 }
Juergen Ributzkafb3e1432014-09-17 17:46:47 +00002456 } else if (const auto *CI = dyn_cast<ConstantInt>(BI->getCondition())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002457 uint64_t Imm = CI->getZExtValue();
2458 MachineBasicBlock *Target = (Imm == 0) ? FBB : TBB;
2459 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::B))
2460 .addMBB(Target);
Juergen Ributzka50a40052014-08-01 18:39:24 +00002461
Cong Hou1938f2e2015-11-24 08:51:23 +00002462 // Obtain the branch probability and add the target to the successor list.
Cong Hou07eeb802015-10-27 17:59:36 +00002463 if (FuncInfo.BPI) {
Cong Hou1938f2e2015-11-24 08:51:23 +00002464 auto BranchProbability = FuncInfo.BPI->getEdgeProbability(
2465 BI->getParent(), Target->getBasicBlock());
2466 FuncInfo.MBB->addSuccessor(Target, BranchProbability);
Cong Hou07eeb802015-10-27 17:59:36 +00002467 } else
Cong Hou1938f2e2015-11-24 08:51:23 +00002468 FuncInfo.MBB->addSuccessorWithoutProb(Target);
Tim Northover3b0846e2014-05-24 12:50:23 +00002469 return true;
Matthias Braun0d4505c2015-12-03 17:19:58 +00002470 } else {
2471 AArch64CC::CondCode CC = AArch64CC::NE;
2472 if (foldXALUIntrinsic(CC, I, BI->getCondition())) {
2473 // Fake request the condition, otherwise the intrinsic might be completely
2474 // optimized away.
2475 unsigned CondReg = getRegForValue(BI->getCondition());
2476 if (!CondReg)
2477 return false;
Juergen Ributzkaad2109a2014-07-30 22:04:34 +00002478
Matthias Braun0d4505c2015-12-03 17:19:58 +00002479 // Emit the branch.
2480 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::Bcc))
2481 .addImm(CC)
2482 .addMBB(TBB);
Juergen Ributzka50a40052014-08-01 18:39:24 +00002483
Matthias Braun0d4505c2015-12-03 17:19:58 +00002484 finishCondBranch(BI->getParent(), TBB, FBB);
2485 return true;
2486 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002487 }
2488
2489 unsigned CondReg = getRegForValue(BI->getCondition());
2490 if (CondReg == 0)
2491 return false;
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00002492 bool CondRegIsKill = hasTrivialKill(BI->getCondition());
Tim Northover3b0846e2014-05-24 12:50:23 +00002493
Matthias Braun0d4505c2015-12-03 17:19:58 +00002494 // i1 conditions come as i32 values, test the lowest bit with tb(n)z.
2495 unsigned Opcode = AArch64::TBNZW;
Tim Northover3b0846e2014-05-24 12:50:23 +00002496 if (FuncInfo.MBB->isLayoutSuccessor(TBB)) {
2497 std::swap(TBB, FBB);
Matthias Braun0d4505c2015-12-03 17:19:58 +00002498 Opcode = AArch64::TBZW;
Tim Northover3b0846e2014-05-24 12:50:23 +00002499 }
2500
Matthias Braun0d4505c2015-12-03 17:19:58 +00002501 const MCInstrDesc &II = TII.get(Opcode);
2502 unsigned ConstrainedCondReg
2503 = constrainOperandRegClass(II, CondReg, II.getNumDefs());
2504 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
2505 .addReg(ConstrainedCondReg, getKillRegState(CondRegIsKill))
2506 .addImm(0)
Tim Northover3b0846e2014-05-24 12:50:23 +00002507 .addMBB(TBB);
Juergen Ributzka50a40052014-08-01 18:39:24 +00002508
Matthias Braun17af6072015-08-26 01:38:00 +00002509 finishCondBranch(BI->getParent(), TBB, FBB);
Tim Northover3b0846e2014-05-24 12:50:23 +00002510 return true;
2511}
2512
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00002513bool AArch64FastISel::selectIndirectBr(const Instruction *I) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002514 const IndirectBrInst *BI = cast<IndirectBrInst>(I);
2515 unsigned AddrReg = getRegForValue(BI->getOperand(0));
2516 if (AddrReg == 0)
2517 return false;
2518
2519 // Emit the indirect branch.
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00002520 const MCInstrDesc &II = TII.get(AArch64::BR);
2521 AddrReg = constrainOperandRegClass(II, AddrReg, II.getNumDefs());
2522 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II).addReg(AddrReg);
Tim Northover3b0846e2014-05-24 12:50:23 +00002523
2524 // Make sure the CFG is up-to-date.
Pete Cooper3ae0ee52015-08-05 17:43:01 +00002525 for (auto *Succ : BI->successors())
2526 FuncInfo.MBB->addSuccessor(FuncInfo.MBBMap[Succ]);
Tim Northover3b0846e2014-05-24 12:50:23 +00002527
2528 return true;
2529}
2530
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00002531bool AArch64FastISel::selectCmp(const Instruction *I) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002532 const CmpInst *CI = cast<CmpInst>(I);
2533
Ahmed Bougachacf49b522015-11-06 23:16:53 +00002534 // Vectors of i1 are weird: bail out.
2535 if (CI->getType()->isVectorTy())
2536 return false;
2537
Juergen Ributzka8984f482014-09-15 20:47:16 +00002538 // Try to optimize or fold the cmp.
2539 CmpInst::Predicate Predicate = optimizeCmpPredicate(CI);
2540 unsigned ResultReg = 0;
2541 switch (Predicate) {
2542 default:
2543 break;
2544 case CmpInst::FCMP_FALSE:
2545 ResultReg = createResultReg(&AArch64::GPR32RegClass);
2546 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
2547 TII.get(TargetOpcode::COPY), ResultReg)
2548 .addReg(AArch64::WZR, getKillRegState(true));
2549 break;
2550 case CmpInst::FCMP_TRUE:
2551 ResultReg = fastEmit_i(MVT::i32, MVT::i32, ISD::Constant, 1);
2552 break;
2553 }
2554
2555 if (ResultReg) {
2556 updateValueMap(I, ResultReg);
2557 return true;
2558 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002559
2560 // Emit the cmp.
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00002561 if (!emitCmp(CI->getOperand(0), CI->getOperand(1), CI->isUnsigned()))
Tim Northover3b0846e2014-05-24 12:50:23 +00002562 return false;
2563
Juergen Ributzka8984f482014-09-15 20:47:16 +00002564 ResultReg = createResultReg(&AArch64::GPR32RegClass);
2565
2566 // FCMP_UEQ and FCMP_ONE cannot be checked with a single instruction. These
2567 // condition codes are inverted, because they are used by CSINC.
2568 static unsigned CondCodeTable[2][2] = {
2569 { AArch64CC::NE, AArch64CC::VC },
2570 { AArch64CC::PL, AArch64CC::LE }
2571 };
2572 unsigned *CondCodes = nullptr;
2573 switch (Predicate) {
2574 default:
2575 break;
2576 case CmpInst::FCMP_UEQ:
2577 CondCodes = &CondCodeTable[0][0];
2578 break;
2579 case CmpInst::FCMP_ONE:
2580 CondCodes = &CondCodeTable[1][0];
2581 break;
2582 }
2583
2584 if (CondCodes) {
2585 unsigned TmpReg1 = createResultReg(&AArch64::GPR32RegClass);
2586 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::CSINCWr),
2587 TmpReg1)
2588 .addReg(AArch64::WZR, getKillRegState(true))
2589 .addReg(AArch64::WZR, getKillRegState(true))
2590 .addImm(CondCodes[0]);
2591 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::CSINCWr),
2592 ResultReg)
2593 .addReg(TmpReg1, getKillRegState(true))
2594 .addReg(AArch64::WZR, getKillRegState(true))
2595 .addImm(CondCodes[1]);
2596
2597 updateValueMap(I, ResultReg);
2598 return true;
2599 }
2600
Tim Northover3b0846e2014-05-24 12:50:23 +00002601 // Now set a register based on the comparison.
Juergen Ributzka8984f482014-09-15 20:47:16 +00002602 AArch64CC::CondCode CC = getCompareCC(Predicate);
2603 assert((CC != AArch64CC::AL) && "Unexpected condition code.");
Tim Northover3b0846e2014-05-24 12:50:23 +00002604 AArch64CC::CondCode invertedCC = getInvertedCondCode(CC);
Tim Northover3b0846e2014-05-24 12:50:23 +00002605 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::CSINCWr),
2606 ResultReg)
Juergen Ributzka8984f482014-09-15 20:47:16 +00002607 .addReg(AArch64::WZR, getKillRegState(true))
2608 .addReg(AArch64::WZR, getKillRegState(true))
Tim Northover3b0846e2014-05-24 12:50:23 +00002609 .addImm(invertedCC);
2610
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00002611 updateValueMap(I, ResultReg);
Tim Northover3b0846e2014-05-24 12:50:23 +00002612 return true;
2613}
2614
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00002615/// Optimize selects of i1 if one of the operands has a 'true' or 'false'
Juergen Ributzka957a1452014-11-13 00:36:46 +00002616/// value.
2617bool AArch64FastISel::optimizeSelect(const SelectInst *SI) {
2618 if (!SI->getType()->isIntegerTy(1))
2619 return false;
2620
2621 const Value *Src1Val, *Src2Val;
2622 unsigned Opc = 0;
2623 bool NeedExtraOp = false;
2624 if (auto *CI = dyn_cast<ConstantInt>(SI->getTrueValue())) {
2625 if (CI->isOne()) {
2626 Src1Val = SI->getCondition();
2627 Src2Val = SI->getFalseValue();
2628 Opc = AArch64::ORRWrr;
2629 } else {
2630 assert(CI->isZero());
2631 Src1Val = SI->getFalseValue();
2632 Src2Val = SI->getCondition();
2633 Opc = AArch64::BICWrr;
2634 }
2635 } else if (auto *CI = dyn_cast<ConstantInt>(SI->getFalseValue())) {
2636 if (CI->isOne()) {
2637 Src1Val = SI->getCondition();
2638 Src2Val = SI->getTrueValue();
2639 Opc = AArch64::ORRWrr;
2640 NeedExtraOp = true;
2641 } else {
2642 assert(CI->isZero());
2643 Src1Val = SI->getCondition();
2644 Src2Val = SI->getTrueValue();
2645 Opc = AArch64::ANDWrr;
2646 }
2647 }
2648
2649 if (!Opc)
2650 return false;
2651
2652 unsigned Src1Reg = getRegForValue(Src1Val);
2653 if (!Src1Reg)
2654 return false;
2655 bool Src1IsKill = hasTrivialKill(Src1Val);
2656
2657 unsigned Src2Reg = getRegForValue(Src2Val);
2658 if (!Src2Reg)
2659 return false;
2660 bool Src2IsKill = hasTrivialKill(Src2Val);
2661
2662 if (NeedExtraOp) {
2663 Src1Reg = emitLogicalOp_ri(ISD::XOR, MVT::i32, Src1Reg, Src1IsKill, 1);
2664 Src1IsKill = true;
2665 }
Quentin Colombet0de23462015-05-01 21:34:57 +00002666 unsigned ResultReg = fastEmitInst_rr(Opc, &AArch64::GPR32RegClass, Src1Reg,
Juergen Ributzka957a1452014-11-13 00:36:46 +00002667 Src1IsKill, Src2Reg, Src2IsKill);
2668 updateValueMap(SI, ResultReg);
2669 return true;
2670}
2671
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00002672bool AArch64FastISel::selectSelect(const Instruction *I) {
Juergen Ributzkad1a042a2014-11-13 00:36:38 +00002673 assert(isa<SelectInst>(I) && "Expected a select instruction.");
2674 MVT VT;
2675 if (!isTypeSupported(I->getType(), VT))
Tim Northover3b0846e2014-05-24 12:50:23 +00002676 return false;
2677
Juergen Ributzkad1a042a2014-11-13 00:36:38 +00002678 unsigned Opc;
2679 const TargetRegisterClass *RC;
2680 switch (VT.SimpleTy) {
2681 default:
Tim Northover3b0846e2014-05-24 12:50:23 +00002682 return false;
Juergen Ributzkad1a042a2014-11-13 00:36:38 +00002683 case MVT::i1:
2684 case MVT::i8:
2685 case MVT::i16:
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00002686 case MVT::i32:
Juergen Ributzkad1a042a2014-11-13 00:36:38 +00002687 Opc = AArch64::CSELWr;
2688 RC = &AArch64::GPR32RegClass;
2689 break;
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00002690 case MVT::i64:
Juergen Ributzkad1a042a2014-11-13 00:36:38 +00002691 Opc = AArch64::CSELXr;
2692 RC = &AArch64::GPR64RegClass;
2693 break;
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00002694 case MVT::f32:
Juergen Ributzkad1a042a2014-11-13 00:36:38 +00002695 Opc = AArch64::FCSELSrrr;
2696 RC = &AArch64::FPR32RegClass;
2697 break;
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00002698 case MVT::f64:
Juergen Ributzkad1a042a2014-11-13 00:36:38 +00002699 Opc = AArch64::FCSELDrrr;
2700 RC = &AArch64::FPR64RegClass;
2701 break;
Juergen Ributzka3771fbb2014-07-30 22:04:37 +00002702 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002703
Juergen Ributzkad1a042a2014-11-13 00:36:38 +00002704 const SelectInst *SI = cast<SelectInst>(I);
Juergen Ributzka3771fbb2014-07-30 22:04:37 +00002705 const Value *Cond = SI->getCondition();
Juergen Ributzka3771fbb2014-07-30 22:04:37 +00002706 AArch64CC::CondCode CC = AArch64CC::NE;
Juergen Ributzka424c5fd2014-11-13 00:36:43 +00002707 AArch64CC::CondCode ExtraCC = AArch64CC::AL;
Tim Northover3b0846e2014-05-24 12:50:23 +00002708
Juergen Ributzka957a1452014-11-13 00:36:46 +00002709 if (optimizeSelect(SI))
2710 return true;
2711
Juergen Ributzkad1a042a2014-11-13 00:36:38 +00002712 // Try to pickup the flags, so we don't have to emit another compare.
2713 if (foldXALUIntrinsic(CC, I, Cond)) {
2714 // Fake request the condition to force emission of the XALU intrinsic.
2715 unsigned CondReg = getRegForValue(Cond);
2716 if (!CondReg)
2717 return false;
Juergen Ributzka424c5fd2014-11-13 00:36:43 +00002718 } else if (isa<CmpInst>(Cond) && cast<CmpInst>(Cond)->hasOneUse() &&
2719 isValueAvailable(Cond)) {
2720 const auto *Cmp = cast<CmpInst>(Cond);
2721 // Try to optimize or fold the cmp.
2722 CmpInst::Predicate Predicate = optimizeCmpPredicate(Cmp);
2723 const Value *FoldSelect = nullptr;
2724 switch (Predicate) {
2725 default:
2726 break;
2727 case CmpInst::FCMP_FALSE:
2728 FoldSelect = SI->getFalseValue();
2729 break;
2730 case CmpInst::FCMP_TRUE:
2731 FoldSelect = SI->getTrueValue();
2732 break;
2733 }
2734
2735 if (FoldSelect) {
2736 unsigned SrcReg = getRegForValue(FoldSelect);
2737 if (!SrcReg)
2738 return false;
2739 unsigned UseReg = lookUpRegForValue(SI);
2740 if (UseReg)
2741 MRI.clearKillFlags(UseReg);
2742
2743 updateValueMap(I, SrcReg);
2744 return true;
2745 }
2746
2747 // Emit the cmp.
2748 if (!emitCmp(Cmp->getOperand(0), Cmp->getOperand(1), Cmp->isUnsigned()))
2749 return false;
2750
2751 // FCMP_UEQ and FCMP_ONE cannot be checked with a single select instruction.
2752 CC = getCompareCC(Predicate);
2753 switch (Predicate) {
2754 default:
2755 break;
2756 case CmpInst::FCMP_UEQ:
2757 ExtraCC = AArch64CC::EQ;
2758 CC = AArch64CC::VS;
2759 break;
2760 case CmpInst::FCMP_ONE:
2761 ExtraCC = AArch64CC::MI;
2762 CC = AArch64CC::GT;
2763 break;
2764 }
2765 assert((CC != AArch64CC::AL) && "Unexpected condition code.");
Juergen Ributzkad1a042a2014-11-13 00:36:38 +00002766 } else {
2767 unsigned CondReg = getRegForValue(Cond);
2768 if (!CondReg)
2769 return false;
2770 bool CondIsKill = hasTrivialKill(Cond);
Juergen Ributzka3771fbb2014-07-30 22:04:37 +00002771
Quentin Colombet329fa892015-04-30 22:27:20 +00002772 const MCInstrDesc &II = TII.get(AArch64::ANDSWri);
2773 CondReg = constrainOperandRegClass(II, CondReg, 1);
2774
Juergen Ributzkad1a042a2014-11-13 00:36:38 +00002775 // Emit a TST instruction (ANDS wzr, reg, #imm).
Quentin Colombet329fa892015-04-30 22:27:20 +00002776 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II,
Juergen Ributzkad1a042a2014-11-13 00:36:38 +00002777 AArch64::WZR)
2778 .addReg(CondReg, getKillRegState(CondIsKill))
2779 .addImm(AArch64_AM::encodeLogicalImmediate(1, 32));
Tim Northover3b0846e2014-05-24 12:50:23 +00002780 }
2781
Juergen Ributzkad1a042a2014-11-13 00:36:38 +00002782 unsigned Src1Reg = getRegForValue(SI->getTrueValue());
2783 bool Src1IsKill = hasTrivialKill(SI->getTrueValue());
Juergen Ributzka3771fbb2014-07-30 22:04:37 +00002784
Juergen Ributzkad1a042a2014-11-13 00:36:38 +00002785 unsigned Src2Reg = getRegForValue(SI->getFalseValue());
2786 bool Src2IsKill = hasTrivialKill(SI->getFalseValue());
Juergen Ributzka3771fbb2014-07-30 22:04:37 +00002787
Juergen Ributzkad1a042a2014-11-13 00:36:38 +00002788 if (!Src1Reg || !Src2Reg)
Juergen Ributzka3771fbb2014-07-30 22:04:37 +00002789 return false;
2790
Juergen Ributzka424c5fd2014-11-13 00:36:43 +00002791 if (ExtraCC != AArch64CC::AL) {
2792 Src2Reg = fastEmitInst_rri(Opc, RC, Src1Reg, Src1IsKill, Src2Reg,
2793 Src2IsKill, ExtraCC);
2794 Src2IsKill = true;
2795 }
Juergen Ributzkad1a042a2014-11-13 00:36:38 +00002796 unsigned ResultReg = fastEmitInst_rri(Opc, RC, Src1Reg, Src1IsKill, Src2Reg,
2797 Src2IsKill, CC);
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00002798 updateValueMap(I, ResultReg);
Tim Northover3b0846e2014-05-24 12:50:23 +00002799 return true;
2800}
2801
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00002802bool AArch64FastISel::selectFPExt(const Instruction *I) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002803 Value *V = I->getOperand(0);
2804 if (!I->getType()->isDoubleTy() || !V->getType()->isFloatTy())
2805 return false;
2806
2807 unsigned Op = getRegForValue(V);
2808 if (Op == 0)
2809 return false;
2810
2811 unsigned ResultReg = createResultReg(&AArch64::FPR64RegClass);
2812 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::FCVTDSr),
2813 ResultReg).addReg(Op);
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00002814 updateValueMap(I, ResultReg);
Tim Northover3b0846e2014-05-24 12:50:23 +00002815 return true;
2816}
2817
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00002818bool AArch64FastISel::selectFPTrunc(const Instruction *I) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002819 Value *V = I->getOperand(0);
2820 if (!I->getType()->isFloatTy() || !V->getType()->isDoubleTy())
2821 return false;
2822
2823 unsigned Op = getRegForValue(V);
2824 if (Op == 0)
2825 return false;
2826
2827 unsigned ResultReg = createResultReg(&AArch64::FPR32RegClass);
2828 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::FCVTSDr),
2829 ResultReg).addReg(Op);
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00002830 updateValueMap(I, ResultReg);
Tim Northover3b0846e2014-05-24 12:50:23 +00002831 return true;
2832}
2833
2834// FPToUI and FPToSI
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00002835bool AArch64FastISel::selectFPToInt(const Instruction *I, bool Signed) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002836 MVT DestVT;
2837 if (!isTypeLegal(I->getType(), DestVT) || DestVT.isVector())
2838 return false;
2839
2840 unsigned SrcReg = getRegForValue(I->getOperand(0));
2841 if (SrcReg == 0)
2842 return false;
2843
Mehdi Amini44ede332015-07-09 02:09:04 +00002844 EVT SrcVT = TLI.getValueType(DL, I->getOperand(0)->getType(), true);
I-Jui (Ray) Sung21fde382017-06-09 22:40:50 +00002845 if (SrcVT == MVT::f128 || SrcVT == MVT::f16)
Tim Northover3b0846e2014-05-24 12:50:23 +00002846 return false;
2847
2848 unsigned Opc;
2849 if (SrcVT == MVT::f64) {
2850 if (Signed)
2851 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWDr : AArch64::FCVTZSUXDr;
2852 else
2853 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWDr : AArch64::FCVTZUUXDr;
2854 } else {
2855 if (Signed)
2856 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZSUWSr : AArch64::FCVTZSUXSr;
2857 else
2858 Opc = (DestVT == MVT::i32) ? AArch64::FCVTZUUWSr : AArch64::FCVTZUUXSr;
2859 }
2860 unsigned ResultReg = createResultReg(
2861 DestVT == MVT::i32 ? &AArch64::GPR32RegClass : &AArch64::GPR64RegClass);
2862 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
2863 .addReg(SrcReg);
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00002864 updateValueMap(I, ResultReg);
Tim Northover3b0846e2014-05-24 12:50:23 +00002865 return true;
2866}
2867
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00002868bool AArch64FastISel::selectIntToFP(const Instruction *I, bool Signed) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002869 MVT DestVT;
2870 if (!isTypeLegal(I->getType(), DestVT) || DestVT.isVector())
2871 return false;
I-Jui (Ray) Sung21fde382017-06-09 22:40:50 +00002872 // Let regular ISEL handle FP16
2873 if (DestVT == MVT::f16)
2874 return false;
2875
Eugene Zelenko11f69072017-01-25 00:29:26 +00002876 assert((DestVT == MVT::f32 || DestVT == MVT::f64) &&
2877 "Unexpected value type.");
Tim Northover3b0846e2014-05-24 12:50:23 +00002878
2879 unsigned SrcReg = getRegForValue(I->getOperand(0));
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00002880 if (!SrcReg)
Tim Northover3b0846e2014-05-24 12:50:23 +00002881 return false;
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00002882 bool SrcIsKill = hasTrivialKill(I->getOperand(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00002883
Mehdi Amini44ede332015-07-09 02:09:04 +00002884 EVT SrcVT = TLI.getValueType(DL, I->getOperand(0)->getType(), true);
Tim Northover3b0846e2014-05-24 12:50:23 +00002885
2886 // Handle sign-extension.
2887 if (SrcVT == MVT::i16 || SrcVT == MVT::i8 || SrcVT == MVT::i1) {
2888 SrcReg =
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00002889 emitIntExt(SrcVT.getSimpleVT(), SrcReg, MVT::i32, /*isZExt*/ !Signed);
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00002890 if (!SrcReg)
Tim Northover3b0846e2014-05-24 12:50:23 +00002891 return false;
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00002892 SrcIsKill = true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002893 }
2894
Tim Northover3b0846e2014-05-24 12:50:23 +00002895 unsigned Opc;
2896 if (SrcVT == MVT::i64) {
2897 if (Signed)
2898 Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUXSri : AArch64::SCVTFUXDri;
2899 else
2900 Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUXSri : AArch64::UCVTFUXDri;
2901 } else {
2902 if (Signed)
2903 Opc = (DestVT == MVT::f32) ? AArch64::SCVTFUWSri : AArch64::SCVTFUWDri;
2904 else
2905 Opc = (DestVT == MVT::f32) ? AArch64::UCVTFUWSri : AArch64::UCVTFUWDri;
2906 }
2907
Juergen Ributzka88e32512014-09-03 20:56:59 +00002908 unsigned ResultReg = fastEmitInst_r(Opc, TLI.getRegClassFor(DestVT), SrcReg,
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00002909 SrcIsKill);
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00002910 updateValueMap(I, ResultReg);
Tim Northover3b0846e2014-05-24 12:50:23 +00002911 return true;
2912}
2913
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00002914bool AArch64FastISel::fastLowerArguments() {
Juergen Ributzkaa126d1e2014-08-05 05:43:48 +00002915 if (!FuncInfo.CanLowerReturn)
2916 return false;
2917
2918 const Function *F = FuncInfo.Fn;
2919 if (F->isVarArg())
2920 return false;
2921
2922 CallingConv::ID CC = F->getCallingConv();
Manman Ren66b54e92016-08-26 19:28:17 +00002923 if (CC != CallingConv::C && CC != CallingConv::Swift)
Juergen Ributzkaa126d1e2014-08-05 05:43:48 +00002924 return false;
2925
Tri Vo6c47c622018-09-22 22:17:50 +00002926 if (Subtarget->hasCustomCallingConv())
2927 return false;
2928
Juergen Ributzka59e631c2014-09-16 00:25:30 +00002929 // Only handle simple cases of up to 8 GPR and FPR each.
Juergen Ributzkaa126d1e2014-08-05 05:43:48 +00002930 unsigned GPRCnt = 0;
2931 unsigned FPRCnt = 0;
Juergen Ributzkaa126d1e2014-08-05 05:43:48 +00002932 for (auto const &Arg : F->args()) {
Reid Kleckner6652a522017-04-28 18:37:16 +00002933 if (Arg.hasAttribute(Attribute::ByVal) ||
2934 Arg.hasAttribute(Attribute::InReg) ||
2935 Arg.hasAttribute(Attribute::StructRet) ||
2936 Arg.hasAttribute(Attribute::SwiftSelf) ||
2937 Arg.hasAttribute(Attribute::SwiftError) ||
2938 Arg.hasAttribute(Attribute::Nest))
Juergen Ributzkaa126d1e2014-08-05 05:43:48 +00002939 return false;
2940
2941 Type *ArgTy = Arg.getType();
Juergen Ributzka59e631c2014-09-16 00:25:30 +00002942 if (ArgTy->isStructTy() || ArgTy->isArrayTy())
Juergen Ributzkaa126d1e2014-08-05 05:43:48 +00002943 return false;
2944
Mehdi Amini44ede332015-07-09 02:09:04 +00002945 EVT ArgVT = TLI.getValueType(DL, ArgTy);
Juergen Ributzka59e631c2014-09-16 00:25:30 +00002946 if (!ArgVT.isSimple())
2947 return false;
2948
2949 MVT VT = ArgVT.getSimpleVT().SimpleTy;
2950 if (VT.isFloatingPoint() && !Subtarget->hasFPARMv8())
2951 return false;
2952
2953 if (VT.isVector() &&
2954 (!Subtarget->hasNEON() || !Subtarget->isLittleEndian()))
2955 return false;
2956
2957 if (VT >= MVT::i1 && VT <= MVT::i64)
Juergen Ributzkaa126d1e2014-08-05 05:43:48 +00002958 ++GPRCnt;
Juergen Ributzka59e631c2014-09-16 00:25:30 +00002959 else if ((VT >= MVT::f16 && VT <= MVT::f64) || VT.is64BitVector() ||
2960 VT.is128BitVector())
Juergen Ributzkaa126d1e2014-08-05 05:43:48 +00002961 ++FPRCnt;
Juergen Ributzka59e631c2014-09-16 00:25:30 +00002962 else
2963 return false;
Juergen Ributzkaa126d1e2014-08-05 05:43:48 +00002964
2965 if (GPRCnt > 8 || FPRCnt > 8)
2966 return false;
2967 }
2968
Juergen Ributzka59e631c2014-09-16 00:25:30 +00002969 static const MCPhysReg Registers[6][8] = {
Juergen Ributzkaa126d1e2014-08-05 05:43:48 +00002970 { AArch64::W0, AArch64::W1, AArch64::W2, AArch64::W3, AArch64::W4,
2971 AArch64::W5, AArch64::W6, AArch64::W7 },
2972 { AArch64::X0, AArch64::X1, AArch64::X2, AArch64::X3, AArch64::X4,
2973 AArch64::X5, AArch64::X6, AArch64::X7 },
2974 { AArch64::H0, AArch64::H1, AArch64::H2, AArch64::H3, AArch64::H4,
2975 AArch64::H5, AArch64::H6, AArch64::H7 },
2976 { AArch64::S0, AArch64::S1, AArch64::S2, AArch64::S3, AArch64::S4,
2977 AArch64::S5, AArch64::S6, AArch64::S7 },
2978 { AArch64::D0, AArch64::D1, AArch64::D2, AArch64::D3, AArch64::D4,
Juergen Ributzka59e631c2014-09-16 00:25:30 +00002979 AArch64::D5, AArch64::D6, AArch64::D7 },
2980 { AArch64::Q0, AArch64::Q1, AArch64::Q2, AArch64::Q3, AArch64::Q4,
2981 AArch64::Q5, AArch64::Q6, AArch64::Q7 }
Juergen Ributzkaa126d1e2014-08-05 05:43:48 +00002982 };
2983
2984 unsigned GPRIdx = 0;
2985 unsigned FPRIdx = 0;
2986 for (auto const &Arg : F->args()) {
Mehdi Amini44ede332015-07-09 02:09:04 +00002987 MVT VT = TLI.getSimpleValueType(DL, Arg.getType());
Juergen Ributzkaa126d1e2014-08-05 05:43:48 +00002988 unsigned SrcReg;
Juergen Ributzka59e631c2014-09-16 00:25:30 +00002989 const TargetRegisterClass *RC;
2990 if (VT >= MVT::i1 && VT <= MVT::i32) {
2991 SrcReg = Registers[0][GPRIdx++];
2992 RC = &AArch64::GPR32RegClass;
2993 VT = MVT::i32;
2994 } else if (VT == MVT::i64) {
2995 SrcReg = Registers[1][GPRIdx++];
2996 RC = &AArch64::GPR64RegClass;
2997 } else if (VT == MVT::f16) {
2998 SrcReg = Registers[2][FPRIdx++];
2999 RC = &AArch64::FPR16RegClass;
3000 } else if (VT == MVT::f32) {
3001 SrcReg = Registers[3][FPRIdx++];
3002 RC = &AArch64::FPR32RegClass;
3003 } else if ((VT == MVT::f64) || VT.is64BitVector()) {
3004 SrcReg = Registers[4][FPRIdx++];
3005 RC = &AArch64::FPR64RegClass;
3006 } else if (VT.is128BitVector()) {
3007 SrcReg = Registers[5][FPRIdx++];
3008 RC = &AArch64::FPR128RegClass;
3009 } else
3010 llvm_unreachable("Unexpected value type.");
Juergen Ributzkaa126d1e2014-08-05 05:43:48 +00003011
Juergen Ributzkaa126d1e2014-08-05 05:43:48 +00003012 unsigned DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);
3013 // FIXME: Unfortunately it's necessary to emit a copy from the livein copy.
3014 // Without this, EmitLiveInCopies may eliminate the livein if its only
3015 // use is a bitcast (which isn't turned into an instruction).
3016 unsigned ResultReg = createResultReg(RC);
3017 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3018 TII.get(TargetOpcode::COPY), ResultReg)
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00003019 .addReg(DstReg, getKillRegState(true));
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00003020 updateValueMap(&Arg, ResultReg);
Juergen Ributzkaa126d1e2014-08-05 05:43:48 +00003021 }
3022 return true;
3023}
3024
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003025bool AArch64FastISel::processCallArgs(CallLoweringInfo &CLI,
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003026 SmallVectorImpl<MVT> &OutVTs,
3027 unsigned &NumBytes) {
3028 CallingConv::ID CC = CLI.CallConv;
Tim Northover3b0846e2014-05-24 12:50:23 +00003029 SmallVector<CCValAssign, 16> ArgLocs;
Eric Christopherb5217502014-08-06 18:45:26 +00003030 CCState CCInfo(CC, false, *FuncInfo.MF, ArgLocs, *Context);
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003031 CCInfo.AnalyzeCallOperands(OutVTs, CLI.OutFlags, CCAssignFnForCall(CC));
Tim Northover3b0846e2014-05-24 12:50:23 +00003032
3033 // Get a count of how many bytes are to be pushed on the stack.
3034 NumBytes = CCInfo.getNextStackOffset();
3035
3036 // Issue CALLSEQ_START
3037 unsigned AdjStackDown = TII.getCallFrameSetupOpcode();
3038 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AdjStackDown))
Serge Pavlovd526b132017-05-09 13:35:13 +00003039 .addImm(NumBytes).addImm(0);
Tim Northover3b0846e2014-05-24 12:50:23 +00003040
3041 // Process the args.
Pete Cooper7be8f8f2015-08-03 19:04:32 +00003042 for (CCValAssign &VA : ArgLocs) {
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003043 const Value *ArgVal = CLI.OutVals[VA.getValNo()];
3044 MVT ArgVT = OutVTs[VA.getValNo()];
3045
3046 unsigned ArgReg = getRegForValue(ArgVal);
3047 if (!ArgReg)
3048 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003049
3050 // Handle arg promotion: SExt, ZExt, AExt.
3051 switch (VA.getLocInfo()) {
3052 case CCValAssign::Full:
3053 break;
3054 case CCValAssign::SExt: {
3055 MVT DestVT = VA.getLocVT();
3056 MVT SrcVT = ArgVT;
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003057 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT, /*isZExt=*/false);
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003058 if (!ArgReg)
Tim Northover3b0846e2014-05-24 12:50:23 +00003059 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003060 break;
3061 }
3062 case CCValAssign::AExt:
3063 // Intentional fall-through.
3064 case CCValAssign::ZExt: {
3065 MVT DestVT = VA.getLocVT();
3066 MVT SrcVT = ArgVT;
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003067 ArgReg = emitIntExt(SrcVT, ArgReg, DestVT, /*isZExt=*/true);
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003068 if (!ArgReg)
Tim Northover3b0846e2014-05-24 12:50:23 +00003069 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003070 break;
3071 }
3072 default:
3073 llvm_unreachable("Unknown arg promotion!");
3074 }
3075
3076 // Now copy/store arg to correct locations.
3077 if (VA.isRegLoc() && !VA.needsCustom()) {
3078 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003079 TII.get(TargetOpcode::COPY), VA.getLocReg()).addReg(ArgReg);
3080 CLI.OutRegs.push_back(VA.getLocReg());
Tim Northover3b0846e2014-05-24 12:50:23 +00003081 } else if (VA.needsCustom()) {
3082 // FIXME: Handle custom args.
3083 return false;
3084 } else {
3085 assert(VA.isMemLoc() && "Assuming store on stack.");
3086
Juergen Ributzka39032672014-07-31 00:11:11 +00003087 // Don't emit stores for undef values.
3088 if (isa<UndefValue>(ArgVal))
3089 continue;
3090
Tim Northover3b0846e2014-05-24 12:50:23 +00003091 // Need to store on the stack.
Tim Northover6890add2014-06-03 13:54:53 +00003092 unsigned ArgSize = (ArgVT.getSizeInBits() + 7) / 8;
Tim Northover3b0846e2014-05-24 12:50:23 +00003093
3094 unsigned BEAlign = 0;
3095 if (ArgSize < 8 && !Subtarget->isLittleEndian())
3096 BEAlign = 8 - ArgSize;
3097
3098 Address Addr;
3099 Addr.setKind(Address::RegBase);
3100 Addr.setReg(AArch64::SP);
3101 Addr.setOffset(VA.getLocMemOffset() + BEAlign);
3102
Juergen Ributzka241fd482014-08-08 17:24:10 +00003103 unsigned Alignment = DL.getABITypeAlignment(ArgVal->getType());
3104 MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand(
Alex Lorenze40c8a22015-08-11 23:09:45 +00003105 MachinePointerInfo::getStack(*FuncInfo.MF, Addr.getOffset()),
3106 MachineMemOperand::MOStore, ArgVT.getStoreSize(), Alignment);
Juergen Ributzka241fd482014-08-08 17:24:10 +00003107
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003108 if (!emitStore(ArgVT, ArgReg, Addr, MMO))
Tim Northover3b0846e2014-05-24 12:50:23 +00003109 return false;
3110 }
3111 }
3112 return true;
3113}
3114
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003115bool AArch64FastISel::finishCall(CallLoweringInfo &CLI, MVT RetVT,
Juergen Ributzka1b014502014-07-23 20:03:13 +00003116 unsigned NumBytes) {
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003117 CallingConv::ID CC = CLI.CallConv;
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003118
Tim Northover3b0846e2014-05-24 12:50:23 +00003119 // Issue CALLSEQ_END
3120 unsigned AdjStackUp = TII.getCallFrameDestroyOpcode();
3121 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AdjStackUp))
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003122 .addImm(NumBytes).addImm(0);
Tim Northover3b0846e2014-05-24 12:50:23 +00003123
3124 // Now the return value.
3125 if (RetVT != MVT::isVoid) {
3126 SmallVector<CCValAssign, 16> RVLocs;
Eric Christopherb5217502014-08-06 18:45:26 +00003127 CCState CCInfo(CC, false, *FuncInfo.MF, RVLocs, *Context);
Tim Northover3b0846e2014-05-24 12:50:23 +00003128 CCInfo.AnalyzeCallResult(RetVT, CCAssignFnForCall(CC));
3129
3130 // Only handle a single return value.
3131 if (RVLocs.size() != 1)
3132 return false;
3133
3134 // Copy all of the result registers out of their specified physreg.
3135 MVT CopyVT = RVLocs[0].getValVT();
Pete Cooper19d704d2015-04-16 21:19:36 +00003136
3137 // TODO: Handle big-endian results
3138 if (CopyVT.isVector() && !Subtarget->isLittleEndian())
3139 return false;
3140
Tim Northover3b0846e2014-05-24 12:50:23 +00003141 unsigned ResultReg = createResultReg(TLI.getRegClassFor(CopyVT));
3142 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003143 TII.get(TargetOpcode::COPY), ResultReg)
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00003144 .addReg(RVLocs[0].getLocReg());
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003145 CLI.InRegs.push_back(RVLocs[0].getLocReg());
Tim Northover3b0846e2014-05-24 12:50:23 +00003146
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003147 CLI.ResultReg = ResultReg;
3148 CLI.NumResultRegs = 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00003149 }
3150
3151 return true;
3152}
3153
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00003154bool AArch64FastISel::fastLowerCall(CallLoweringInfo &CLI) {
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003155 CallingConv::ID CC = CLI.CallConv;
Akira Hatanakab74db092014-08-13 23:23:58 +00003156 bool IsTailCall = CLI.IsTailCall;
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003157 bool IsVarArg = CLI.IsVarArg;
3158 const Value *Callee = CLI.Callee;
Rafael Espindolace4c2bc2015-06-23 12:21:54 +00003159 MCSymbol *Symbol = CLI.Symbol;
Tim Northover3b0846e2014-05-24 12:50:23 +00003160
Rafael Espindolace4c2bc2015-06-23 12:21:54 +00003161 if (!Callee && !Symbol)
Juergen Ributzkaafa034f2014-09-15 22:07:49 +00003162 return false;
3163
Akira Hatanakab74db092014-08-13 23:23:58 +00003164 // Allow SelectionDAG isel to handle tail calls.
3165 if (IsTailCall)
3166 return false;
3167
Juergen Ributzka052e6c22014-07-31 04:10:40 +00003168 CodeModel::Model CM = TM.getCodeModel();
Petr Hosek9eb0a1e2017-04-04 19:51:53 +00003169 // Only support the small-addressing and large code models.
3170 if (CM != CodeModel::Large && !Subtarget->useSmallAddressing())
Juergen Ributzka052e6c22014-07-31 04:10:40 +00003171 return false;
3172
3173 // FIXME: Add large code model support for ELF.
3174 if (CM == CodeModel::Large && !Subtarget->isTargetMachO())
Tim Northover3b0846e2014-05-24 12:50:23 +00003175 return false;
3176
Tim Northover3b0846e2014-05-24 12:50:23 +00003177 // Let SDISel handle vararg functions.
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003178 if (IsVarArg)
Tim Northover3b0846e2014-05-24 12:50:23 +00003179 return false;
3180
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003181 // FIXME: Only handle *simple* calls for now.
Tim Northover3b0846e2014-05-24 12:50:23 +00003182 MVT RetVT;
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003183 if (CLI.RetTy->isVoidTy())
Tim Northover3b0846e2014-05-24 12:50:23 +00003184 RetVT = MVT::isVoid;
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003185 else if (!isTypeLegal(CLI.RetTy, RetVT))
Tim Northover3b0846e2014-05-24 12:50:23 +00003186 return false;
3187
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003188 for (auto Flag : CLI.OutFlags)
Manman Renf46262e2016-03-29 17:37:21 +00003189 if (Flag.isInReg() || Flag.isSRet() || Flag.isNest() || Flag.isByVal() ||
Manman Ren57518142016-04-11 21:08:06 +00003190 Flag.isSwiftSelf() || Flag.isSwiftError())
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003191 return false;
3192
Tim Northover3b0846e2014-05-24 12:50:23 +00003193 // Set up the argument vectors.
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003194 SmallVector<MVT, 16> OutVTs;
3195 OutVTs.reserve(CLI.OutVals.size());
Tim Northover3b0846e2014-05-24 12:50:23 +00003196
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003197 for (auto *Val : CLI.OutVals) {
3198 MVT VT;
3199 if (!isTypeLegal(Val->getType(), VT) &&
3200 !(VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16))
Tim Northover3b0846e2014-05-24 12:50:23 +00003201 return false;
3202
3203 // We don't handle vector parameters yet.
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003204 if (VT.isVector() || VT.getSizeInBits() > 64)
Tim Northover3b0846e2014-05-24 12:50:23 +00003205 return false;
3206
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003207 OutVTs.push_back(VT);
Tim Northover3b0846e2014-05-24 12:50:23 +00003208 }
3209
Juergen Ributzka052e6c22014-07-31 04:10:40 +00003210 Address Addr;
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003211 if (Callee && !computeCallAddress(Callee, Addr))
Juergen Ributzka052e6c22014-07-31 04:10:40 +00003212 return false;
3213
Tim Northover3b0846e2014-05-24 12:50:23 +00003214 // Handle the arguments now that we've gotten them.
Tim Northover3b0846e2014-05-24 12:50:23 +00003215 unsigned NumBytes;
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003216 if (!processCallArgs(CLI, OutVTs, NumBytes))
Tim Northover3b0846e2014-05-24 12:50:23 +00003217 return false;
3218
Nick Desaulniers287a3be2018-09-07 20:58:57 +00003219 const AArch64RegisterInfo *RegInfo = Subtarget->getRegisterInfo();
3220 if (RegInfo->isAnyArgRegReserved(*MF))
3221 RegInfo->emitReservedArgRegCallError(*MF);
3222
Tim Northover3b0846e2014-05-24 12:50:23 +00003223 // Issue the call.
3224 MachineInstrBuilder MIB;
Petr Hosek9eb0a1e2017-04-04 19:51:53 +00003225 if (Subtarget->useSmallAddressing()) {
Juergen Ributzkac5c1c602014-08-29 23:48:06 +00003226 const MCInstrDesc &II = TII.get(Addr.getReg() ? AArch64::BLR : AArch64::BL);
3227 MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II);
Rafael Espindolace4c2bc2015-06-23 12:21:54 +00003228 if (Symbol)
3229 MIB.addSym(Symbol, 0);
Juergen Ributzka052e6c22014-07-31 04:10:40 +00003230 else if (Addr.getGlobalValue())
3231 MIB.addGlobalAddress(Addr.getGlobalValue(), 0, 0);
Juergen Ributzkac5c1c602014-08-29 23:48:06 +00003232 else if (Addr.getReg()) {
3233 unsigned Reg = constrainOperandRegClass(II, Addr.getReg(), 0);
3234 MIB.addReg(Reg);
3235 } else
Juergen Ributzka052e6c22014-07-31 04:10:40 +00003236 return false;
3237 } else {
3238 unsigned CallReg = 0;
Rafael Espindolace4c2bc2015-06-23 12:21:54 +00003239 if (Symbol) {
Juergen Ributzka052e6c22014-07-31 04:10:40 +00003240 unsigned ADRPReg = createResultReg(&AArch64::GPR64commonRegClass);
3241 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::ADRP),
3242 ADRPReg)
Rafael Espindolace4c2bc2015-06-23 12:21:54 +00003243 .addSym(Symbol, AArch64II::MO_GOT | AArch64II::MO_PAGE);
Juergen Ributzka052e6c22014-07-31 04:10:40 +00003244
3245 CallReg = createResultReg(&AArch64::GPR64RegClass);
Rafael Espindolace4c2bc2015-06-23 12:21:54 +00003246 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3247 TII.get(AArch64::LDRXui), CallReg)
3248 .addReg(ADRPReg)
3249 .addSym(Symbol,
3250 AArch64II::MO_GOT | AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003251 } else if (Addr.getGlobalValue())
3252 CallReg = materializeGV(Addr.getGlobalValue());
3253 else if (Addr.getReg())
Juergen Ributzka052e6c22014-07-31 04:10:40 +00003254 CallReg = Addr.getReg();
3255
3256 if (!CallReg)
3257 return false;
3258
Juergen Ributzkac5c1c602014-08-29 23:48:06 +00003259 const MCInstrDesc &II = TII.get(AArch64::BLR);
3260 CallReg = constrainOperandRegClass(II, CallReg, 0);
3261 MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II).addReg(CallReg);
Juergen Ributzka052e6c22014-07-31 04:10:40 +00003262 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003263
3264 // Add implicit physical register uses to the call.
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003265 for (auto Reg : CLI.OutRegs)
3266 MIB.addReg(Reg, RegState::Implicit);
Tim Northover3b0846e2014-05-24 12:50:23 +00003267
3268 // Add a register mask with the call-preserved registers.
3269 // Proper defs for return values will be added by setPhysRegsDeadExcept().
Eric Christopher9deb75d2015-03-11 22:42:13 +00003270 MIB.addRegMask(TRI.getCallPreservedMask(*FuncInfo.MF, CC));
Tim Northover3b0846e2014-05-24 12:50:23 +00003271
Juergen Ributzka052e6c22014-07-31 04:10:40 +00003272 CLI.Call = MIB;
3273
Tim Northover3b0846e2014-05-24 12:50:23 +00003274 // Finish off the call including any return values.
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003275 return finishCall(CLI, RetVT, NumBytes);
Tim Northover3b0846e2014-05-24 12:50:23 +00003276}
3277
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003278bool AArch64FastISel::isMemCpySmall(uint64_t Len, unsigned Alignment) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003279 if (Alignment)
3280 return Len / Alignment <= 4;
3281 else
3282 return Len < 32;
3283}
3284
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003285bool AArch64FastISel::tryEmitSmallMemCpy(Address Dest, Address Src,
Tim Northover3b0846e2014-05-24 12:50:23 +00003286 uint64_t Len, unsigned Alignment) {
3287 // Make sure we don't bloat code by inlining very large memcpy's.
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003288 if (!isMemCpySmall(Len, Alignment))
Tim Northover3b0846e2014-05-24 12:50:23 +00003289 return false;
3290
3291 int64_t UnscaledOffset = 0;
3292 Address OrigDest = Dest;
3293 Address OrigSrc = Src;
3294
3295 while (Len) {
3296 MVT VT;
3297 if (!Alignment || Alignment >= 8) {
3298 if (Len >= 8)
3299 VT = MVT::i64;
3300 else if (Len >= 4)
3301 VT = MVT::i32;
3302 else if (Len >= 2)
3303 VT = MVT::i16;
3304 else {
3305 VT = MVT::i8;
3306 }
3307 } else {
3308 // Bound based on alignment.
3309 if (Len >= 4 && Alignment == 4)
3310 VT = MVT::i32;
3311 else if (Len >= 2 && Alignment == 2)
3312 VT = MVT::i16;
3313 else {
3314 VT = MVT::i8;
3315 }
3316 }
3317
Juergen Ributzkacd11a282014-10-14 20:36:02 +00003318 unsigned ResultReg = emitLoad(VT, VT, Src);
3319 if (!ResultReg)
Tim Northoverc19445d2014-06-10 09:52:40 +00003320 return false;
3321
Juergen Ributzkacd11a282014-10-14 20:36:02 +00003322 if (!emitStore(VT, ResultReg, Dest))
Tim Northoverc19445d2014-06-10 09:52:40 +00003323 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003324
3325 int64_t Size = VT.getSizeInBits() / 8;
3326 Len -= Size;
3327 UnscaledOffset += Size;
3328
3329 // We need to recompute the unscaled offset for each iteration.
3330 Dest.setOffset(OrigDest.getOffset() + UnscaledOffset);
3331 Src.setOffset(OrigSrc.getOffset() + UnscaledOffset);
3332 }
3333
3334 return true;
3335}
3336
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00003337/// Check if it is possible to fold the condition from the XALU intrinsic
Juergen Ributzkaad2109a2014-07-30 22:04:34 +00003338/// into the user. The condition code will only be updated on success.
3339bool AArch64FastISel::foldXALUIntrinsic(AArch64CC::CondCode &CC,
3340 const Instruction *I,
3341 const Value *Cond) {
3342 if (!isa<ExtractValueInst>(Cond))
3343 return false;
3344
3345 const auto *EV = cast<ExtractValueInst>(Cond);
3346 if (!isa<IntrinsicInst>(EV->getAggregateOperand()))
3347 return false;
3348
3349 const auto *II = cast<IntrinsicInst>(EV->getAggregateOperand());
3350 MVT RetVT;
3351 const Function *Callee = II->getCalledFunction();
3352 Type *RetTy =
3353 cast<StructType>(Callee->getReturnType())->getTypeAtIndex(0U);
3354 if (!isTypeLegal(RetTy, RetVT))
3355 return false;
3356
3357 if (RetVT != MVT::i32 && RetVT != MVT::i64)
3358 return false;
3359
Juergen Ributzka0f307672014-09-18 07:26:26 +00003360 const Value *LHS = II->getArgOperand(0);
3361 const Value *RHS = II->getArgOperand(1);
3362
3363 // Canonicalize immediate to the RHS.
3364 if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS) &&
3365 isCommutativeIntrinsic(II))
3366 std::swap(LHS, RHS);
3367
3368 // Simplify multiplies.
Pete Cooper9e1d3352015-05-20 17:16:39 +00003369 Intrinsic::ID IID = II->getIntrinsicID();
Juergen Ributzka0f307672014-09-18 07:26:26 +00003370 switch (IID) {
3371 default:
3372 break;
3373 case Intrinsic::smul_with_overflow:
3374 if (const auto *C = dyn_cast<ConstantInt>(RHS))
3375 if (C->getValue() == 2)
3376 IID = Intrinsic::sadd_with_overflow;
3377 break;
3378 case Intrinsic::umul_with_overflow:
3379 if (const auto *C = dyn_cast<ConstantInt>(RHS))
3380 if (C->getValue() == 2)
3381 IID = Intrinsic::uadd_with_overflow;
3382 break;
3383 }
3384
Juergen Ributzkaad2109a2014-07-30 22:04:34 +00003385 AArch64CC::CondCode TmpCC;
Juergen Ributzka0f307672014-09-18 07:26:26 +00003386 switch (IID) {
3387 default:
3388 return false;
3389 case Intrinsic::sadd_with_overflow:
3390 case Intrinsic::ssub_with_overflow:
3391 TmpCC = AArch64CC::VS;
3392 break;
3393 case Intrinsic::uadd_with_overflow:
3394 TmpCC = AArch64CC::HS;
3395 break;
3396 case Intrinsic::usub_with_overflow:
3397 TmpCC = AArch64CC::LO;
3398 break;
3399 case Intrinsic::smul_with_overflow:
3400 case Intrinsic::umul_with_overflow:
3401 TmpCC = AArch64CC::NE;
3402 break;
Juergen Ributzkaad2109a2014-07-30 22:04:34 +00003403 }
3404
3405 // Check if both instructions are in the same basic block.
Juergen Ributzkafb3e1432014-09-17 17:46:47 +00003406 if (!isValueAvailable(II))
Juergen Ributzkaad2109a2014-07-30 22:04:34 +00003407 return false;
3408
3409 // Make sure nothing is in the way
Duncan P. N. Exon Smithd3b9df02015-10-13 20:02:15 +00003410 BasicBlock::const_iterator Start(I);
3411 BasicBlock::const_iterator End(II);
Juergen Ributzkaad2109a2014-07-30 22:04:34 +00003412 for (auto Itr = std::prev(Start); Itr != End; --Itr) {
3413 // We only expect extractvalue instructions between the intrinsic and the
3414 // instruction to be selected.
3415 if (!isa<ExtractValueInst>(Itr))
3416 return false;
3417
3418 // Check that the extractvalue operand comes from the intrinsic.
3419 const auto *EVI = cast<ExtractValueInst>(Itr);
3420 if (EVI->getAggregateOperand() != II)
3421 return false;
3422 }
3423
3424 CC = TmpCC;
3425 return true;
3426}
3427
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00003428bool AArch64FastISel::fastLowerIntrinsicCall(const IntrinsicInst *II) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003429 // FIXME: Handle more intrinsics.
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003430 switch (II->getIntrinsicID()) {
Juergen Ributzka5d6c43e2014-07-25 17:47:14 +00003431 default: return false;
3432 case Intrinsic::frameaddress: {
Matthias Braun941a7052016-07-28 18:40:00 +00003433 MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
3434 MFI.setFrameAddressIsTaken(true);
Juergen Ributzka5d6c43e2014-07-25 17:47:14 +00003435
Eric Christophercf965f22017-03-31 23:12:24 +00003436 const AArch64RegisterInfo *RegInfo = Subtarget->getRegisterInfo();
Juergen Ributzka5d6c43e2014-07-25 17:47:14 +00003437 unsigned FramePtr = RegInfo->getFrameRegister(*(FuncInfo.MF));
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00003438 unsigned SrcReg = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3439 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3440 TII.get(TargetOpcode::COPY), SrcReg).addReg(FramePtr);
Juergen Ributzka5d6c43e2014-07-25 17:47:14 +00003441 // Recursively load frame address
3442 // ldr x0, [fp]
3443 // ldr x0, [x0]
3444 // ldr x0, [x0]
3445 // ...
3446 unsigned DestReg;
3447 unsigned Depth = cast<ConstantInt>(II->getOperand(0))->getZExtValue();
3448 while (Depth--) {
Juergen Ributzka88e32512014-09-03 20:56:59 +00003449 DestReg = fastEmitInst_ri(AArch64::LDRXui, &AArch64::GPR64RegClass,
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00003450 SrcReg, /*IsKill=*/true, 0);
3451 assert(DestReg && "Unexpected LDR instruction emission failure.");
Juergen Ributzka5d6c43e2014-07-25 17:47:14 +00003452 SrcReg = DestReg;
3453 }
3454
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00003455 updateValueMap(II, SrcReg);
Juergen Ributzka5d6c43e2014-07-25 17:47:14 +00003456 return true;
3457 }
Mandeep Singh Grang547a0d72018-11-01 23:22:25 +00003458 case Intrinsic::sponentry: {
3459 MachineFrameInfo &MFI = FuncInfo.MF->getFrameInfo();
3460
3461 // SP = FP + Fixed Object + 16
3462 int FI = MFI.CreateFixedObject(4, 0, false);
3463 unsigned ResultReg = createResultReg(&AArch64::GPR64spRegClass);
3464 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3465 TII.get(AArch64::ADDXri), ResultReg)
3466 .addFrameIndex(FI)
3467 .addImm(0)
3468 .addImm(0);
3469
3470 updateValueMap(II, ResultReg);
3471 return true;
3472 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003473 case Intrinsic::memcpy:
3474 case Intrinsic::memmove: {
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003475 const auto *MTI = cast<MemTransferInst>(II);
Tim Northover3b0846e2014-05-24 12:50:23 +00003476 // Don't handle volatile.
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003477 if (MTI->isVolatile())
Tim Northover3b0846e2014-05-24 12:50:23 +00003478 return false;
3479
Juergen Ributzka843f14f2014-08-27 23:09:40 +00003480 // Disable inlining for memmove before calls to ComputeAddress. Otherwise,
Tim Northover3b0846e2014-05-24 12:50:23 +00003481 // we would emit dead code because we don't currently handle memmoves.
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003482 bool IsMemCpy = (II->getIntrinsicID() == Intrinsic::memcpy);
3483 if (isa<ConstantInt>(MTI->getLength()) && IsMemCpy) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003484 // Small memcpy's are common enough that we want to do them without a call
3485 // if possible.
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003486 uint64_t Len = cast<ConstantInt>(MTI->getLength())->getZExtValue();
Daniel Neilson4a58b4b2018-02-09 21:49:29 +00003487 unsigned Alignment = MinAlign(MTI->getDestAlignment(),
3488 MTI->getSourceAlignment());
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003489 if (isMemCpySmall(Len, Alignment)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003490 Address Dest, Src;
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003491 if (!computeAddress(MTI->getRawDest(), Dest) ||
3492 !computeAddress(MTI->getRawSource(), Src))
Tim Northover3b0846e2014-05-24 12:50:23 +00003493 return false;
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003494 if (tryEmitSmallMemCpy(Dest, Src, Len, Alignment))
Tim Northover3b0846e2014-05-24 12:50:23 +00003495 return true;
3496 }
3497 }
3498
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003499 if (!MTI->getLength()->getType()->isIntegerTy(64))
Tim Northover3b0846e2014-05-24 12:50:23 +00003500 return false;
3501
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003502 if (MTI->getSourceAddressSpace() > 255 || MTI->getDestAddressSpace() > 255)
Tim Northover3b0846e2014-05-24 12:50:23 +00003503 // Fast instruction selection doesn't support the special
3504 // address spaces.
3505 return false;
3506
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003507 const char *IntrMemName = isa<MemCpyInst>(II) ? "memcpy" : "memmove";
Daniel Neilson1e687242018-01-19 17:13:12 +00003508 return lowerCallTo(II, IntrMemName, II->getNumArgOperands() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003509 }
3510 case Intrinsic::memset: {
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003511 const MemSetInst *MSI = cast<MemSetInst>(II);
Tim Northover3b0846e2014-05-24 12:50:23 +00003512 // Don't handle volatile.
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003513 if (MSI->isVolatile())
Tim Northover3b0846e2014-05-24 12:50:23 +00003514 return false;
3515
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003516 if (!MSI->getLength()->getType()->isIntegerTy(64))
Tim Northover3b0846e2014-05-24 12:50:23 +00003517 return false;
3518
Juergen Ributzka2581fa52014-07-22 23:14:58 +00003519 if (MSI->getDestAddressSpace() > 255)
Tim Northover3b0846e2014-05-24 12:50:23 +00003520 // Fast instruction selection doesn't support the special
3521 // address spaces.
3522 return false;
3523
Daniel Neilson1e687242018-01-19 17:13:12 +00003524 return lowerCallTo(II, "memset", II->getNumArgOperands() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003525 }
Juergen Ributzka993224a2014-09-15 22:33:06 +00003526 case Intrinsic::sin:
3527 case Intrinsic::cos:
3528 case Intrinsic::pow: {
3529 MVT RetVT;
3530 if (!isTypeLegal(II->getType(), RetVT))
3531 return false;
3532
3533 if (RetVT != MVT::f32 && RetVT != MVT::f64)
3534 return false;
3535
3536 static const RTLIB::Libcall LibCallTable[3][2] = {
3537 { RTLIB::SIN_F32, RTLIB::SIN_F64 },
3538 { RTLIB::COS_F32, RTLIB::COS_F64 },
3539 { RTLIB::POW_F32, RTLIB::POW_F64 }
3540 };
3541 RTLIB::Libcall LC;
3542 bool Is64Bit = RetVT == MVT::f64;
3543 switch (II->getIntrinsicID()) {
3544 default:
3545 llvm_unreachable("Unexpected intrinsic.");
3546 case Intrinsic::sin:
3547 LC = LibCallTable[0][Is64Bit];
3548 break;
3549 case Intrinsic::cos:
3550 LC = LibCallTable[1][Is64Bit];
3551 break;
3552 case Intrinsic::pow:
3553 LC = LibCallTable[2][Is64Bit];
3554 break;
3555 }
3556
3557 ArgListTy Args;
3558 Args.reserve(II->getNumArgOperands());
3559
3560 // Populate the argument list.
3561 for (auto &Arg : II->arg_operands()) {
3562 ArgListEntry Entry;
3563 Entry.Val = Arg;
3564 Entry.Ty = Arg->getType();
3565 Args.push_back(Entry);
3566 }
3567
3568 CallLoweringInfo CLI;
Rafael Espindolace4c2bc2015-06-23 12:21:54 +00003569 MCContext &Ctx = MF->getContext();
3570 CLI.setCallee(DL, Ctx, TLI.getLibcallCallingConv(LC), II->getType(),
Juergen Ributzka993224a2014-09-15 22:33:06 +00003571 TLI.getLibcallName(LC), std::move(Args));
3572 if (!lowerCallTo(CLI))
3573 return false;
3574 updateValueMap(II, CLI.ResultReg);
3575 return true;
3576 }
Juergen Ributzka89441b02014-11-11 23:10:44 +00003577 case Intrinsic::fabs: {
3578 MVT VT;
3579 if (!isTypeLegal(II->getType(), VT))
3580 return false;
3581
3582 unsigned Opc;
3583 switch (VT.SimpleTy) {
3584 default:
3585 return false;
3586 case MVT::f32:
3587 Opc = AArch64::FABSSr;
3588 break;
3589 case MVT::f64:
3590 Opc = AArch64::FABSDr;
3591 break;
3592 }
3593 unsigned SrcReg = getRegForValue(II->getOperand(0));
3594 if (!SrcReg)
3595 return false;
3596 bool SrcRegIsKill = hasTrivialKill(II->getOperand(0));
3597 unsigned ResultReg = createResultReg(TLI.getRegClassFor(VT));
3598 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
3599 .addReg(SrcReg, getKillRegState(SrcRegIsKill));
3600 updateValueMap(II, ResultReg);
3601 return true;
3602 }
Eugene Zelenko11f69072017-01-25 00:29:26 +00003603 case Intrinsic::trap:
Tim Northover3b0846e2014-05-24 12:50:23 +00003604 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::BRK))
3605 .addImm(1);
3606 return true;
Eugene Zelenko11f69072017-01-25 00:29:26 +00003607
Juergen Ributzka130e77e2014-07-31 06:25:33 +00003608 case Intrinsic::sqrt: {
3609 Type *RetTy = II->getCalledFunction()->getReturnType();
3610
3611 MVT VT;
3612 if (!isTypeLegal(RetTy, VT))
3613 return false;
3614
3615 unsigned Op0Reg = getRegForValue(II->getOperand(0));
3616 if (!Op0Reg)
3617 return false;
3618 bool Op0IsKill = hasTrivialKill(II->getOperand(0));
3619
Juergen Ributzka88e32512014-09-03 20:56:59 +00003620 unsigned ResultReg = fastEmit_r(VT, VT, ISD::FSQRT, Op0Reg, Op0IsKill);
Juergen Ributzka130e77e2014-07-31 06:25:33 +00003621 if (!ResultReg)
3622 return false;
3623
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00003624 updateValueMap(II, ResultReg);
Juergen Ributzka130e77e2014-07-31 06:25:33 +00003625 return true;
3626 }
Juergen Ributzkad43da752014-07-30 22:04:31 +00003627 case Intrinsic::sadd_with_overflow:
3628 case Intrinsic::uadd_with_overflow:
3629 case Intrinsic::ssub_with_overflow:
3630 case Intrinsic::usub_with_overflow:
3631 case Intrinsic::smul_with_overflow:
3632 case Intrinsic::umul_with_overflow: {
3633 // This implements the basic lowering of the xalu with overflow intrinsics.
3634 const Function *Callee = II->getCalledFunction();
3635 auto *Ty = cast<StructType>(Callee->getReturnType());
3636 Type *RetTy = Ty->getTypeAtIndex(0U);
Juergen Ributzkad43da752014-07-30 22:04:31 +00003637
3638 MVT VT;
3639 if (!isTypeLegal(RetTy, VT))
3640 return false;
3641
3642 if (VT != MVT::i32 && VT != MVT::i64)
3643 return false;
3644
3645 const Value *LHS = II->getArgOperand(0);
3646 const Value *RHS = II->getArgOperand(1);
3647 // Canonicalize immediate to the RHS.
3648 if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS) &&
3649 isCommutativeIntrinsic(II))
3650 std::swap(LHS, RHS);
3651
Juergen Ributzka2964b832014-09-18 07:04:54 +00003652 // Simplify multiplies.
Pete Cooper9e1d3352015-05-20 17:16:39 +00003653 Intrinsic::ID IID = II->getIntrinsicID();
Juergen Ributzka2964b832014-09-18 07:04:54 +00003654 switch (IID) {
3655 default:
3656 break;
3657 case Intrinsic::smul_with_overflow:
3658 if (const auto *C = dyn_cast<ConstantInt>(RHS))
3659 if (C->getValue() == 2) {
3660 IID = Intrinsic::sadd_with_overflow;
3661 RHS = LHS;
3662 }
3663 break;
3664 case Intrinsic::umul_with_overflow:
3665 if (const auto *C = dyn_cast<ConstantInt>(RHS))
3666 if (C->getValue() == 2) {
3667 IID = Intrinsic::uadd_with_overflow;
3668 RHS = LHS;
3669 }
3670 break;
3671 }
3672
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00003673 unsigned ResultReg1 = 0, ResultReg2 = 0, MulReg = 0;
Juergen Ributzkad43da752014-07-30 22:04:31 +00003674 AArch64CC::CondCode CC = AArch64CC::Invalid;
Juergen Ributzka2964b832014-09-18 07:04:54 +00003675 switch (IID) {
Juergen Ributzkad43da752014-07-30 22:04:31 +00003676 default: llvm_unreachable("Unexpected intrinsic!");
3677 case Intrinsic::sadd_with_overflow:
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00003678 ResultReg1 = emitAdd(VT, LHS, RHS, /*SetFlags=*/true);
3679 CC = AArch64CC::VS;
3680 break;
Juergen Ributzkad43da752014-07-30 22:04:31 +00003681 case Intrinsic::uadd_with_overflow:
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00003682 ResultReg1 = emitAdd(VT, LHS, RHS, /*SetFlags=*/true);
3683 CC = AArch64CC::HS;
3684 break;
Juergen Ributzkad43da752014-07-30 22:04:31 +00003685 case Intrinsic::ssub_with_overflow:
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00003686 ResultReg1 = emitSub(VT, LHS, RHS, /*SetFlags=*/true);
3687 CC = AArch64CC::VS;
3688 break;
Juergen Ributzkad43da752014-07-30 22:04:31 +00003689 case Intrinsic::usub_with_overflow:
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00003690 ResultReg1 = emitSub(VT, LHS, RHS, /*SetFlags=*/true);
3691 CC = AArch64CC::LO;
3692 break;
Juergen Ributzkad43da752014-07-30 22:04:31 +00003693 case Intrinsic::smul_with_overflow: {
3694 CC = AArch64CC::NE;
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00003695 unsigned LHSReg = getRegForValue(LHS);
3696 if (!LHSReg)
3697 return false;
3698 bool LHSIsKill = hasTrivialKill(LHS);
3699
3700 unsigned RHSReg = getRegForValue(RHS);
Juergen Ributzka82ecc7f2014-08-01 01:25:55 +00003701 if (!RHSReg)
3702 return false;
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00003703 bool RHSIsKill = hasTrivialKill(RHS);
Juergen Ributzka82ecc7f2014-08-01 01:25:55 +00003704
Juergen Ributzkad43da752014-07-30 22:04:31 +00003705 if (VT == MVT::i32) {
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003706 MulReg = emitSMULL_rr(MVT::i64, LHSReg, LHSIsKill, RHSReg, RHSIsKill);
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00003707 unsigned ShiftReg = emitLSR_ri(MVT::i64, MVT::i64, MulReg,
3708 /*IsKill=*/false, 32);
Juergen Ributzka88e32512014-09-03 20:56:59 +00003709 MulReg = fastEmitInst_extractsubreg(VT, MulReg, /*IsKill=*/true,
Juergen Ributzkad43da752014-07-30 22:04:31 +00003710 AArch64::sub_32);
Juergen Ributzka88e32512014-09-03 20:56:59 +00003711 ShiftReg = fastEmitInst_extractsubreg(VT, ShiftReg, /*IsKill=*/true,
Juergen Ributzkad43da752014-07-30 22:04:31 +00003712 AArch64::sub_32);
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00003713 emitSubs_rs(VT, ShiftReg, /*IsKill=*/true, MulReg, /*IsKill=*/false,
3714 AArch64_AM::ASR, 31, /*WantResult=*/false);
Juergen Ributzkad43da752014-07-30 22:04:31 +00003715 } else {
3716 assert(VT == MVT::i64 && "Unexpected value type.");
Quentin Colombet9df2fa22015-05-01 20:57:11 +00003717 // LHSReg and RHSReg cannot be killed by this Mul, since they are
3718 // reused in the next instruction.
3719 MulReg = emitMul_rr(VT, LHSReg, /*IsKill=*/false, RHSReg,
3720 /*IsKill=*/false);
Juergen Ributzka88e32512014-09-03 20:56:59 +00003721 unsigned SMULHReg = fastEmit_rr(VT, VT, ISD::MULHS, LHSReg, LHSIsKill,
Juergen Ributzkad43da752014-07-30 22:04:31 +00003722 RHSReg, RHSIsKill);
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00003723 emitSubs_rs(VT, SMULHReg, /*IsKill=*/true, MulReg, /*IsKill=*/false,
3724 AArch64_AM::ASR, 63, /*WantResult=*/false);
Juergen Ributzkad43da752014-07-30 22:04:31 +00003725 }
3726 break;
3727 }
3728 case Intrinsic::umul_with_overflow: {
3729 CC = AArch64CC::NE;
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00003730 unsigned LHSReg = getRegForValue(LHS);
3731 if (!LHSReg)
3732 return false;
3733 bool LHSIsKill = hasTrivialKill(LHS);
3734
3735 unsigned RHSReg = getRegForValue(RHS);
Juergen Ributzka82ecc7f2014-08-01 01:25:55 +00003736 if (!RHSReg)
3737 return false;
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00003738 bool RHSIsKill = hasTrivialKill(RHS);
Juergen Ributzka82ecc7f2014-08-01 01:25:55 +00003739
Juergen Ributzkad43da752014-07-30 22:04:31 +00003740 if (VT == MVT::i32) {
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003741 MulReg = emitUMULL_rr(MVT::i64, LHSReg, LHSIsKill, RHSReg, RHSIsKill);
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00003742 emitSubs_rs(MVT::i64, AArch64::XZR, /*IsKill=*/true, MulReg,
3743 /*IsKill=*/false, AArch64_AM::LSR, 32,
3744 /*WantResult=*/false);
Juergen Ributzka88e32512014-09-03 20:56:59 +00003745 MulReg = fastEmitInst_extractsubreg(VT, MulReg, /*IsKill=*/true,
Juergen Ributzkad43da752014-07-30 22:04:31 +00003746 AArch64::sub_32);
3747 } else {
3748 assert(VT == MVT::i64 && "Unexpected value type.");
Quentin Colombet9df2fa22015-05-01 20:57:11 +00003749 // LHSReg and RHSReg cannot be killed by this Mul, since they are
3750 // reused in the next instruction.
3751 MulReg = emitMul_rr(VT, LHSReg, /*IsKill=*/false, RHSReg,
3752 /*IsKill=*/false);
Juergen Ributzka88e32512014-09-03 20:56:59 +00003753 unsigned UMULHReg = fastEmit_rr(VT, VT, ISD::MULHU, LHSReg, LHSIsKill,
Juergen Ributzkad43da752014-07-30 22:04:31 +00003754 RHSReg, RHSIsKill);
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00003755 emitSubs_rr(VT, AArch64::XZR, /*IsKill=*/true, UMULHReg,
3756 /*IsKill=*/false, /*WantResult=*/false);
Juergen Ributzkad43da752014-07-30 22:04:31 +00003757 }
3758 break;
3759 }
3760 }
3761
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00003762 if (MulReg) {
3763 ResultReg1 = createResultReg(TLI.getRegClassFor(VT));
Juergen Ributzkad43da752014-07-30 22:04:31 +00003764 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00003765 TII.get(TargetOpcode::COPY), ResultReg1).addReg(MulReg);
3766 }
Juergen Ributzkad43da752014-07-30 22:04:31 +00003767
Matthias Braunc0ef7862018-09-21 15:47:41 +00003768 if (!ResultReg1)
3769 return false;
3770
Juergen Ributzka88e32512014-09-03 20:56:59 +00003771 ResultReg2 = fastEmitInst_rri(AArch64::CSINCWr, &AArch64::GPR32RegClass,
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00003772 AArch64::WZR, /*IsKill=*/true, AArch64::WZR,
3773 /*IsKill=*/true, getInvertedCondCode(CC));
Jingyue Wu4938e272014-10-04 03:50:10 +00003774 (void)ResultReg2;
Juergen Ributzkac0886dd2014-08-19 22:29:55 +00003775 assert((ResultReg1 + 1) == ResultReg2 &&
3776 "Nonconsecutive result registers.");
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00003777 updateValueMap(II, ResultReg1, 2);
Juergen Ributzkad43da752014-07-30 22:04:31 +00003778 return true;
3779 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003780 }
3781 return false;
3782}
3783
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003784bool AArch64FastISel::selectRet(const Instruction *I) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003785 const ReturnInst *Ret = cast<ReturnInst>(I);
3786 const Function &F = *I->getParent()->getParent();
3787
3788 if (!FuncInfo.CanLowerReturn)
3789 return false;
3790
3791 if (F.isVarArg())
3792 return false;
3793
Manman Ren57518142016-04-11 21:08:06 +00003794 if (TLI.supportSwiftError() &&
3795 F.getAttributes().hasAttrSomewhere(Attribute::SwiftError))
3796 return false;
3797
Manman Rencbe4f942015-12-16 21:04:19 +00003798 if (TLI.supportSplitCSR(FuncInfo.MF))
3799 return false;
3800
Tim Northover3b0846e2014-05-24 12:50:23 +00003801 // Build a list of return value registers.
3802 SmallVector<unsigned, 4> RetRegs;
3803
3804 if (Ret->getNumOperands() > 0) {
3805 CallingConv::ID CC = F.getCallingConv();
3806 SmallVector<ISD::OutputArg, 4> Outs;
Matt Arsenault81920b02018-07-28 13:25:19 +00003807 GetReturnInfo(CC, F.getReturnType(), F.getAttributes(), Outs, TLI, DL);
Tim Northover3b0846e2014-05-24 12:50:23 +00003808
3809 // Analyze operands of the call, assigning locations to each operand.
3810 SmallVector<CCValAssign, 16> ValLocs;
Eric Christopherb5217502014-08-06 18:45:26 +00003811 CCState CCInfo(CC, F.isVarArg(), *FuncInfo.MF, ValLocs, I->getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003812 CCAssignFn *RetCC = CC == CallingConv::WebKit_JS ? RetCC_AArch64_WebKit_JS
3813 : RetCC_AArch64_AAPCS;
3814 CCInfo.AnalyzeReturn(Outs, RetCC);
3815
3816 // Only handle a single return value for now.
3817 if (ValLocs.size() != 1)
3818 return false;
3819
3820 CCValAssign &VA = ValLocs[0];
3821 const Value *RV = Ret->getOperand(0);
3822
3823 // Don't bother handling odd stuff for now.
Juergen Ributzkade47c472014-09-15 23:40:10 +00003824 if ((VA.getLocInfo() != CCValAssign::Full) &&
3825 (VA.getLocInfo() != CCValAssign::BCvt))
Tim Northover3b0846e2014-05-24 12:50:23 +00003826 return false;
Juergen Ributzkade47c472014-09-15 23:40:10 +00003827
Tim Northover3b0846e2014-05-24 12:50:23 +00003828 // Only handle register returns for now.
3829 if (!VA.isRegLoc())
3830 return false;
Juergen Ributzkade47c472014-09-15 23:40:10 +00003831
Tim Northover3b0846e2014-05-24 12:50:23 +00003832 unsigned Reg = getRegForValue(RV);
3833 if (Reg == 0)
3834 return false;
3835
3836 unsigned SrcReg = Reg + VA.getValNo();
3837 unsigned DestReg = VA.getLocReg();
3838 // Avoid a cross-class copy. This is very unlikely.
3839 if (!MRI.getRegClass(SrcReg)->contains(DestReg))
3840 return false;
3841
Mehdi Amini44ede332015-07-09 02:09:04 +00003842 EVT RVEVT = TLI.getValueType(DL, RV->getType());
Tim Northover3b0846e2014-05-24 12:50:23 +00003843 if (!RVEVT.isSimple())
3844 return false;
3845
3846 // Vectors (of > 1 lane) in big endian need tricky handling.
Juergen Ributzkade47c472014-09-15 23:40:10 +00003847 if (RVEVT.isVector() && RVEVT.getVectorNumElements() > 1 &&
3848 !Subtarget->isLittleEndian())
Tim Northover3b0846e2014-05-24 12:50:23 +00003849 return false;
3850
3851 MVT RVVT = RVEVT.getSimpleVT();
3852 if (RVVT == MVT::f128)
3853 return false;
Juergen Ributzkade47c472014-09-15 23:40:10 +00003854
Tim Northover3b0846e2014-05-24 12:50:23 +00003855 MVT DestVT = VA.getValVT();
3856 // Special handling for extended integers.
3857 if (RVVT != DestVT) {
3858 if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16)
3859 return false;
3860
3861 if (!Outs[0].Flags.isZExt() && !Outs[0].Flags.isSExt())
3862 return false;
3863
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003864 bool IsZExt = Outs[0].Flags.isZExt();
3865 SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt);
Tim Northover3b0846e2014-05-24 12:50:23 +00003866 if (SrcReg == 0)
3867 return false;
3868 }
3869
3870 // Make the copy.
3871 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3872 TII.get(TargetOpcode::COPY), DestReg).addReg(SrcReg);
3873
3874 // Add register to return instruction.
3875 RetRegs.push_back(VA.getLocReg());
3876 }
3877
3878 MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3879 TII.get(AArch64::RET_ReallyLR));
Pete Cooper7be8f8f2015-08-03 19:04:32 +00003880 for (unsigned RetReg : RetRegs)
3881 MIB.addReg(RetReg, RegState::Implicit);
Tim Northover3b0846e2014-05-24 12:50:23 +00003882 return true;
3883}
3884
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003885bool AArch64FastISel::selectTrunc(const Instruction *I) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003886 Type *DestTy = I->getType();
3887 Value *Op = I->getOperand(0);
3888 Type *SrcTy = Op->getType();
3889
Mehdi Amini44ede332015-07-09 02:09:04 +00003890 EVT SrcEVT = TLI.getValueType(DL, SrcTy, true);
3891 EVT DestEVT = TLI.getValueType(DL, DestTy, true);
Tim Northover3b0846e2014-05-24 12:50:23 +00003892 if (!SrcEVT.isSimple())
3893 return false;
3894 if (!DestEVT.isSimple())
3895 return false;
3896
3897 MVT SrcVT = SrcEVT.getSimpleVT();
3898 MVT DestVT = DestEVT.getSimpleVT();
3899
3900 if (SrcVT != MVT::i64 && SrcVT != MVT::i32 && SrcVT != MVT::i16 &&
3901 SrcVT != MVT::i8)
3902 return false;
3903 if (DestVT != MVT::i32 && DestVT != MVT::i16 && DestVT != MVT::i8 &&
3904 DestVT != MVT::i1)
3905 return false;
3906
3907 unsigned SrcReg = getRegForValue(Op);
3908 if (!SrcReg)
3909 return false;
Juergen Ributzkac83265a2014-08-21 18:02:25 +00003910 bool SrcIsKill = hasTrivialKill(Op);
Tim Northover3b0846e2014-05-24 12:50:23 +00003911
Juergen Ributzka9f54dbe2015-08-06 22:13:48 +00003912 // If we're truncating from i64 to a smaller non-legal type then generate an
3913 // AND. Otherwise, we know the high bits are undefined and a truncate only
3914 // generate a COPY. We cannot mark the source register also as result
3915 // register, because this can incorrectly transfer the kill flag onto the
3916 // source register.
3917 unsigned ResultReg;
Juergen Ributzka63649852015-07-25 02:16:53 +00003918 if (SrcVT == MVT::i64) {
Juergen Ributzka9f54dbe2015-08-06 22:13:48 +00003919 uint64_t Mask = 0;
3920 switch (DestVT.SimpleTy) {
3921 default:
3922 // Trunc i64 to i32 is handled by the target-independent fast-isel.
3923 return false;
3924 case MVT::i1:
3925 Mask = 0x1;
3926 break;
3927 case MVT::i8:
3928 Mask = 0xff;
3929 break;
3930 case MVT::i16:
3931 Mask = 0xffff;
3932 break;
3933 }
Juergen Ributzka63649852015-07-25 02:16:53 +00003934 // Issue an extract_subreg to get the lower 32-bits.
Juergen Ributzka9f54dbe2015-08-06 22:13:48 +00003935 unsigned Reg32 = fastEmitInst_extractsubreg(MVT::i32, SrcReg, SrcIsKill,
3936 AArch64::sub_32);
3937 // Create the AND instruction which performs the actual truncation.
3938 ResultReg = emitAnd_ri(MVT::i32, Reg32, /*IsKill=*/true, Mask);
3939 assert(ResultReg && "Unexpected AND instruction emission failure.");
3940 } else {
3941 ResultReg = createResultReg(&AArch64::GPR32RegClass);
3942 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3943 TII.get(TargetOpcode::COPY), ResultReg)
3944 .addReg(SrcReg, getKillRegState(SrcIsKill));
Juergen Ributzka63649852015-07-25 02:16:53 +00003945 }
3946
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00003947 updateValueMap(I, ResultReg);
Tim Northover3b0846e2014-05-24 12:50:23 +00003948 return true;
3949}
3950
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003951unsigned AArch64FastISel::emiti1Ext(unsigned SrcReg, MVT DestVT, bool IsZExt) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003952 assert((DestVT == MVT::i8 || DestVT == MVT::i16 || DestVT == MVT::i32 ||
3953 DestVT == MVT::i64) &&
3954 "Unexpected value type.");
3955 // Handle i8 and i16 as i32.
3956 if (DestVT == MVT::i8 || DestVT == MVT::i16)
3957 DestVT = MVT::i32;
3958
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003959 if (IsZExt) {
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00003960 unsigned ResultReg = emitAnd_ri(MVT::i32, SrcReg, /*TODO:IsKill=*/false, 1);
Juergen Ributzkac83265a2014-08-21 18:02:25 +00003961 assert(ResultReg && "Unexpected AND instruction emission failure.");
Tim Northover3b0846e2014-05-24 12:50:23 +00003962 if (DestVT == MVT::i64) {
3963 // We're ZExt i1 to i64. The ANDWri Wd, Ws, #1 implicitly clears the
3964 // upper 32 bits. Emit a SUBREG_TO_REG to extend from Wd to Xd.
3965 unsigned Reg64 = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3966 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
3967 TII.get(AArch64::SUBREG_TO_REG), Reg64)
3968 .addImm(0)
3969 .addReg(ResultReg)
3970 .addImm(AArch64::sub_32);
3971 ResultReg = Reg64;
3972 }
3973 return ResultReg;
3974 } else {
3975 if (DestVT == MVT::i64) {
3976 // FIXME: We're SExt i1 to i64.
3977 return 0;
3978 }
Juergen Ributzka88e32512014-09-03 20:56:59 +00003979 return fastEmitInst_rii(AArch64::SBFMWri, &AArch64::GPR32RegClass, SrcReg,
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00003980 /*TODO:IsKill=*/false, 0, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00003981 }
3982}
3983
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00003984unsigned AArch64FastISel::emitMul_rr(MVT RetVT, unsigned Op0, bool Op0IsKill,
Juergen Ributzkaad3b0902014-07-30 22:04:25 +00003985 unsigned Op1, bool Op1IsKill) {
3986 unsigned Opc, ZReg;
3987 switch (RetVT.SimpleTy) {
3988 default: return 0;
3989 case MVT::i8:
3990 case MVT::i16:
3991 case MVT::i32:
3992 RetVT = MVT::i32;
3993 Opc = AArch64::MADDWrrr; ZReg = AArch64::WZR; break;
3994 case MVT::i64:
3995 Opc = AArch64::MADDXrrr; ZReg = AArch64::XZR; break;
3996 }
3997
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00003998 const TargetRegisterClass *RC =
3999 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
Juergen Ributzka88e32512014-09-03 20:56:59 +00004000 return fastEmitInst_rrr(Opc, RC, Op0, Op0IsKill, Op1, Op1IsKill,
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00004001 /*IsKill=*/ZReg, true);
Juergen Ributzkaad3b0902014-07-30 22:04:25 +00004002}
4003
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004004unsigned AArch64FastISel::emitSMULL_rr(MVT RetVT, unsigned Op0, bool Op0IsKill,
Juergen Ributzkaad3b0902014-07-30 22:04:25 +00004005 unsigned Op1, bool Op1IsKill) {
4006 if (RetVT != MVT::i64)
4007 return 0;
4008
Juergen Ributzka88e32512014-09-03 20:56:59 +00004009 return fastEmitInst_rrr(AArch64::SMADDLrrr, &AArch64::GPR64RegClass,
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00004010 Op0, Op0IsKill, Op1, Op1IsKill,
4011 AArch64::XZR, /*IsKill=*/true);
Juergen Ributzkaad3b0902014-07-30 22:04:25 +00004012}
4013
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004014unsigned AArch64FastISel::emitUMULL_rr(MVT RetVT, unsigned Op0, bool Op0IsKill,
Juergen Ributzkaad3b0902014-07-30 22:04:25 +00004015 unsigned Op1, bool Op1IsKill) {
4016 if (RetVT != MVT::i64)
4017 return 0;
4018
Juergen Ributzka88e32512014-09-03 20:56:59 +00004019 return fastEmitInst_rrr(AArch64::UMADDLrrr, &AArch64::GPR64RegClass,
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00004020 Op0, Op0IsKill, Op1, Op1IsKill,
4021 AArch64::XZR, /*IsKill=*/true);
Juergen Ributzkaad3b0902014-07-30 22:04:25 +00004022}
4023
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +00004024unsigned AArch64FastISel::emitLSL_rr(MVT RetVT, unsigned Op0Reg, bool Op0IsKill,
4025 unsigned Op1Reg, bool Op1IsKill) {
4026 unsigned Opc = 0;
4027 bool NeedTrunc = false;
4028 uint64_t Mask = 0;
4029 switch (RetVT.SimpleTy) {
4030 default: return 0;
4031 case MVT::i8: Opc = AArch64::LSLVWr; NeedTrunc = true; Mask = 0xff; break;
4032 case MVT::i16: Opc = AArch64::LSLVWr; NeedTrunc = true; Mask = 0xffff; break;
4033 case MVT::i32: Opc = AArch64::LSLVWr; break;
4034 case MVT::i64: Opc = AArch64::LSLVXr; break;
4035 }
4036
4037 const TargetRegisterClass *RC =
4038 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4039 if (NeedTrunc) {
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00004040 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Op1IsKill, Mask);
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +00004041 Op1IsKill = true;
4042 }
Juergen Ributzka88e32512014-09-03 20:56:59 +00004043 unsigned ResultReg = fastEmitInst_rr(Opc, RC, Op0Reg, Op0IsKill, Op1Reg,
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +00004044 Op1IsKill);
4045 if (NeedTrunc)
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00004046 ResultReg = emitAnd_ri(MVT::i32, ResultReg, /*IsKill=*/true, Mask);
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +00004047 return ResultReg;
4048}
4049
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004050unsigned AArch64FastISel::emitLSL_ri(MVT RetVT, MVT SrcVT, unsigned Op0,
4051 bool Op0IsKill, uint64_t Shift,
Juergen Ributzkacdda9302014-11-18 21:20:17 +00004052 bool IsZExt) {
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004053 assert(RetVT.SimpleTy >= SrcVT.SimpleTy &&
4054 "Unexpected source/return type pair.");
Juergen Ributzka27e959d2014-09-22 21:08:53 +00004055 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4056 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4057 "Unexpected source value type.");
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004058 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4059 RetVT == MVT::i64) && "Unexpected return value type.");
Juergen Ributzkaa75cb112014-07-30 22:04:22 +00004060
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004061 bool Is64Bit = (RetVT == MVT::i64);
4062 unsigned RegSize = Is64Bit ? 64 : 32;
4063 unsigned DstBits = RetVT.getSizeInBits();
4064 unsigned SrcBits = SrcVT.getSizeInBits();
Juergen Ributzka4328fd92014-11-18 19:58:59 +00004065 const TargetRegisterClass *RC =
4066 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4067
4068 // Just emit a copy for "zero" shifts.
4069 if (Shift == 0) {
Juergen Ributzkacdda9302014-11-18 21:20:17 +00004070 if (RetVT == SrcVT) {
4071 unsigned ResultReg = createResultReg(RC);
4072 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4073 TII.get(TargetOpcode::COPY), ResultReg)
4074 .addReg(Op0, getKillRegState(Op0IsKill));
4075 return ResultReg;
4076 } else
4077 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
Juergen Ributzka4328fd92014-11-18 19:58:59 +00004078 }
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004079
4080 // Don't deal with undefined shifts.
4081 if (Shift >= DstBits)
4082 return 0;
4083
4084 // For immediate shifts we can fold the zero-/sign-extension into the shift.
4085 // {S|U}BFM Wd, Wn, #r, #s
4086 // Wd<32+s-r,32-r> = Wn<s:0> when r > s
4087
4088 // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
4089 // %2 = shl i16 %1, 4
4090 // Wd<32+7-28,32-28> = Wn<7:0> <- clamp s to 7
4091 // 0b1111_1111_1111_1111__1111_1010_1010_0000 sext
4092 // 0b0000_0000_0000_0000__0000_0101_0101_0000 sext | zext
4093 // 0b0000_0000_0000_0000__0000_1010_1010_0000 zext
4094
4095 // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
4096 // %2 = shl i16 %1, 8
4097 // Wd<32+7-24,32-24> = Wn<7:0>
4098 // 0b1111_1111_1111_1111__1010_1010_0000_0000 sext
4099 // 0b0000_0000_0000_0000__0101_0101_0000_0000 sext | zext
4100 // 0b0000_0000_0000_0000__1010_1010_0000_0000 zext
4101
4102 // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
4103 // %2 = shl i16 %1, 12
4104 // Wd<32+3-20,32-20> = Wn<3:0>
4105 // 0b1111_1111_1111_1111__1010_0000_0000_0000 sext
4106 // 0b0000_0000_0000_0000__0101_0000_0000_0000 sext | zext
4107 // 0b0000_0000_0000_0000__1010_0000_0000_0000 zext
4108
4109 unsigned ImmR = RegSize - Shift;
4110 // Limit the width to the length of the source type.
4111 unsigned ImmS = std::min<unsigned>(SrcBits - 1, DstBits - 1 - Shift);
4112 static const unsigned OpcTable[2][2] = {
4113 {AArch64::SBFMWri, AArch64::SBFMXri},
4114 {AArch64::UBFMWri, AArch64::UBFMXri}
4115 };
Juergen Ributzkacdda9302014-11-18 21:20:17 +00004116 unsigned Opc = OpcTable[IsZExt][Is64Bit];
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004117 if (SrcVT.SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4118 unsigned TmpReg = MRI.createVirtualRegister(RC);
4119 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4120 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4121 .addImm(0)
4122 .addReg(Op0, getKillRegState(Op0IsKill))
4123 .addImm(AArch64::sub_32);
4124 Op0 = TmpReg;
4125 Op0IsKill = true;
4126 }
Juergen Ributzka88e32512014-09-03 20:56:59 +00004127 return fastEmitInst_rii(Opc, RC, Op0, Op0IsKill, ImmR, ImmS);
Juergen Ributzkaa75cb112014-07-30 22:04:22 +00004128}
4129
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +00004130unsigned AArch64FastISel::emitLSR_rr(MVT RetVT, unsigned Op0Reg, bool Op0IsKill,
4131 unsigned Op1Reg, bool Op1IsKill) {
4132 unsigned Opc = 0;
4133 bool NeedTrunc = false;
4134 uint64_t Mask = 0;
4135 switch (RetVT.SimpleTy) {
4136 default: return 0;
4137 case MVT::i8: Opc = AArch64::LSRVWr; NeedTrunc = true; Mask = 0xff; break;
4138 case MVT::i16: Opc = AArch64::LSRVWr; NeedTrunc = true; Mask = 0xffff; break;
4139 case MVT::i32: Opc = AArch64::LSRVWr; break;
4140 case MVT::i64: Opc = AArch64::LSRVXr; break;
4141 }
4142
4143 const TargetRegisterClass *RC =
4144 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4145 if (NeedTrunc) {
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00004146 Op0Reg = emitAnd_ri(MVT::i32, Op0Reg, Op0IsKill, Mask);
4147 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Op1IsKill, Mask);
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +00004148 Op0IsKill = Op1IsKill = true;
4149 }
Juergen Ributzka88e32512014-09-03 20:56:59 +00004150 unsigned ResultReg = fastEmitInst_rr(Opc, RC, Op0Reg, Op0IsKill, Op1Reg,
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +00004151 Op1IsKill);
4152 if (NeedTrunc)
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00004153 ResultReg = emitAnd_ri(MVT::i32, ResultReg, /*IsKill=*/true, Mask);
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +00004154 return ResultReg;
4155}
4156
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004157unsigned AArch64FastISel::emitLSR_ri(MVT RetVT, MVT SrcVT, unsigned Op0,
4158 bool Op0IsKill, uint64_t Shift,
4159 bool IsZExt) {
4160 assert(RetVT.SimpleTy >= SrcVT.SimpleTy &&
4161 "Unexpected source/return type pair.");
Chad Rosiere16d16a2014-11-18 22:38:42 +00004162 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4163 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4164 "Unexpected source value type.");
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004165 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4166 RetVT == MVT::i64) && "Unexpected return value type.");
4167
4168 bool Is64Bit = (RetVT == MVT::i64);
4169 unsigned RegSize = Is64Bit ? 64 : 32;
4170 unsigned DstBits = RetVT.getSizeInBits();
4171 unsigned SrcBits = SrcVT.getSizeInBits();
Juergen Ributzka4328fd92014-11-18 19:58:59 +00004172 const TargetRegisterClass *RC =
4173 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4174
4175 // Just emit a copy for "zero" shifts.
4176 if (Shift == 0) {
Juergen Ributzkacdda9302014-11-18 21:20:17 +00004177 if (RetVT == SrcVT) {
4178 unsigned ResultReg = createResultReg(RC);
4179 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4180 TII.get(TargetOpcode::COPY), ResultReg)
4181 .addReg(Op0, getKillRegState(Op0IsKill));
4182 return ResultReg;
4183 } else
4184 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
Juergen Ributzka4328fd92014-11-18 19:58:59 +00004185 }
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004186
4187 // Don't deal with undefined shifts.
4188 if (Shift >= DstBits)
4189 return 0;
4190
4191 // For immediate shifts we can fold the zero-/sign-extension into the shift.
4192 // {S|U}BFM Wd, Wn, #r, #s
4193 // Wd<s-r:0> = Wn<s:r> when r <= s
4194
4195 // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
4196 // %2 = lshr i16 %1, 4
4197 // Wd<7-4:0> = Wn<7:4>
4198 // 0b0000_0000_0000_0000__0000_1111_1111_1010 sext
4199 // 0b0000_0000_0000_0000__0000_0000_0000_0101 sext | zext
4200 // 0b0000_0000_0000_0000__0000_0000_0000_1010 zext
4201
4202 // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
4203 // %2 = lshr i16 %1, 8
4204 // Wd<7-7,0> = Wn<7:7>
4205 // 0b0000_0000_0000_0000__0000_0000_1111_1111 sext
4206 // 0b0000_0000_0000_0000__0000_0000_0000_0000 sext
4207 // 0b0000_0000_0000_0000__0000_0000_0000_0000 zext
4208
4209 // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
4210 // %2 = lshr i16 %1, 12
4211 // Wd<7-7,0> = Wn<7:7> <- clamp r to 7
4212 // 0b0000_0000_0000_0000__0000_0000_0000_1111 sext
4213 // 0b0000_0000_0000_0000__0000_0000_0000_0000 sext
4214 // 0b0000_0000_0000_0000__0000_0000_0000_0000 zext
4215
4216 if (Shift >= SrcBits && IsZExt)
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004217 return materializeInt(ConstantInt::get(*Context, APInt(RegSize, 0)), RetVT);
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004218
4219 // It is not possible to fold a sign-extend into the LShr instruction. In this
4220 // case emit a sign-extend.
4221 if (!IsZExt) {
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004222 Op0 = emitIntExt(SrcVT, Op0, RetVT, IsZExt);
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004223 if (!Op0)
4224 return 0;
4225 Op0IsKill = true;
4226 SrcVT = RetVT;
4227 SrcBits = SrcVT.getSizeInBits();
4228 IsZExt = true;
Juergen Ributzkaa75cb112014-07-30 22:04:22 +00004229 }
4230
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004231 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4232 unsigned ImmS = SrcBits - 1;
4233 static const unsigned OpcTable[2][2] = {
4234 {AArch64::SBFMWri, AArch64::SBFMXri},
4235 {AArch64::UBFMWri, AArch64::UBFMXri}
4236 };
4237 unsigned Opc = OpcTable[IsZExt][Is64Bit];
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004238 if (SrcVT.SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4239 unsigned TmpReg = MRI.createVirtualRegister(RC);
4240 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4241 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4242 .addImm(0)
4243 .addReg(Op0, getKillRegState(Op0IsKill))
4244 .addImm(AArch64::sub_32);
4245 Op0 = TmpReg;
4246 Op0IsKill = true;
4247 }
Juergen Ributzka88e32512014-09-03 20:56:59 +00004248 return fastEmitInst_rii(Opc, RC, Op0, Op0IsKill, ImmR, ImmS);
Juergen Ributzkaa75cb112014-07-30 22:04:22 +00004249}
4250
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +00004251unsigned AArch64FastISel::emitASR_rr(MVT RetVT, unsigned Op0Reg, bool Op0IsKill,
4252 unsigned Op1Reg, bool Op1IsKill) {
4253 unsigned Opc = 0;
4254 bool NeedTrunc = false;
4255 uint64_t Mask = 0;
4256 switch (RetVT.SimpleTy) {
4257 default: return 0;
4258 case MVT::i8: Opc = AArch64::ASRVWr; NeedTrunc = true; Mask = 0xff; break;
4259 case MVT::i16: Opc = AArch64::ASRVWr; NeedTrunc = true; Mask = 0xffff; break;
4260 case MVT::i32: Opc = AArch64::ASRVWr; break;
4261 case MVT::i64: Opc = AArch64::ASRVXr; break;
4262 }
4263
4264 const TargetRegisterClass *RC =
4265 (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4266 if (NeedTrunc) {
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004267 Op0Reg = emitIntExt(RetVT, Op0Reg, MVT::i32, /*IsZExt=*/false);
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00004268 Op1Reg = emitAnd_ri(MVT::i32, Op1Reg, Op1IsKill, Mask);
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +00004269 Op0IsKill = Op1IsKill = true;
4270 }
Juergen Ributzka88e32512014-09-03 20:56:59 +00004271 unsigned ResultReg = fastEmitInst_rr(Opc, RC, Op0Reg, Op0IsKill, Op1Reg,
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +00004272 Op1IsKill);
4273 if (NeedTrunc)
Juergen Ributzka1dbc15f2014-09-04 01:29:18 +00004274 ResultReg = emitAnd_ri(MVT::i32, ResultReg, /*IsKill=*/true, Mask);
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +00004275 return ResultReg;
4276}
4277
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004278unsigned AArch64FastISel::emitASR_ri(MVT RetVT, MVT SrcVT, unsigned Op0,
4279 bool Op0IsKill, uint64_t Shift,
4280 bool IsZExt) {
4281 assert(RetVT.SimpleTy >= SrcVT.SimpleTy &&
4282 "Unexpected source/return type pair.");
Chad Rosierc2508812014-11-18 22:41:49 +00004283 assert((SrcVT == MVT::i1 || SrcVT == MVT::i8 || SrcVT == MVT::i16 ||
4284 SrcVT == MVT::i32 || SrcVT == MVT::i64) &&
4285 "Unexpected source value type.");
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004286 assert((RetVT == MVT::i8 || RetVT == MVT::i16 || RetVT == MVT::i32 ||
4287 RetVT == MVT::i64) && "Unexpected return value type.");
Juergen Ributzkaa75cb112014-07-30 22:04:22 +00004288
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004289 bool Is64Bit = (RetVT == MVT::i64);
4290 unsigned RegSize = Is64Bit ? 64 : 32;
4291 unsigned DstBits = RetVT.getSizeInBits();
4292 unsigned SrcBits = SrcVT.getSizeInBits();
Juergen Ributzka4328fd92014-11-18 19:58:59 +00004293 const TargetRegisterClass *RC =
4294 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
4295
4296 // Just emit a copy for "zero" shifts.
4297 if (Shift == 0) {
Juergen Ributzkacdda9302014-11-18 21:20:17 +00004298 if (RetVT == SrcVT) {
4299 unsigned ResultReg = createResultReg(RC);
4300 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4301 TII.get(TargetOpcode::COPY), ResultReg)
4302 .addReg(Op0, getKillRegState(Op0IsKill));
4303 return ResultReg;
4304 } else
4305 return emitIntExt(SrcVT, Op0, RetVT, IsZExt);
Juergen Ributzka4328fd92014-11-18 19:58:59 +00004306 }
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004307
4308 // Don't deal with undefined shifts.
4309 if (Shift >= DstBits)
4310 return 0;
4311
4312 // For immediate shifts we can fold the zero-/sign-extension into the shift.
4313 // {S|U}BFM Wd, Wn, #r, #s
4314 // Wd<s-r:0> = Wn<s:r> when r <= s
4315
4316 // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
4317 // %2 = ashr i16 %1, 4
4318 // Wd<7-4:0> = Wn<7:4>
4319 // 0b1111_1111_1111_1111__1111_1111_1111_1010 sext
4320 // 0b0000_0000_0000_0000__0000_0000_0000_0101 sext | zext
4321 // 0b0000_0000_0000_0000__0000_0000_0000_1010 zext
4322
4323 // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
4324 // %2 = ashr i16 %1, 8
4325 // Wd<7-7,0> = Wn<7:7>
4326 // 0b1111_1111_1111_1111__1111_1111_1111_1111 sext
4327 // 0b0000_0000_0000_0000__0000_0000_0000_0000 sext
4328 // 0b0000_0000_0000_0000__0000_0000_0000_0000 zext
4329
4330 // %1 = {s|z}ext i8 {0b1010_1010|0b0101_0101} to i16
4331 // %2 = ashr i16 %1, 12
4332 // Wd<7-7,0> = Wn<7:7> <- clamp r to 7
4333 // 0b1111_1111_1111_1111__1111_1111_1111_1111 sext
4334 // 0b0000_0000_0000_0000__0000_0000_0000_0000 sext
4335 // 0b0000_0000_0000_0000__0000_0000_0000_0000 zext
4336
4337 if (Shift >= SrcBits && IsZExt)
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004338 return materializeInt(ConstantInt::get(*Context, APInt(RegSize, 0)), RetVT);
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004339
4340 unsigned ImmR = std::min<unsigned>(SrcBits - 1, Shift);
4341 unsigned ImmS = SrcBits - 1;
4342 static const unsigned OpcTable[2][2] = {
4343 {AArch64::SBFMWri, AArch64::SBFMXri},
4344 {AArch64::UBFMWri, AArch64::UBFMXri}
4345 };
4346 unsigned Opc = OpcTable[IsZExt][Is64Bit];
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004347 if (SrcVT.SimpleTy <= MVT::i32 && RetVT == MVT::i64) {
4348 unsigned TmpReg = MRI.createVirtualRegister(RC);
4349 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4350 TII.get(AArch64::SUBREG_TO_REG), TmpReg)
4351 .addImm(0)
4352 .addReg(Op0, getKillRegState(Op0IsKill))
4353 .addImm(AArch64::sub_32);
4354 Op0 = TmpReg;
4355 Op0IsKill = true;
4356 }
Juergen Ributzka88e32512014-09-03 20:56:59 +00004357 return fastEmitInst_rii(Opc, RC, Op0, Op0IsKill, ImmR, ImmS);
Juergen Ributzkaa75cb112014-07-30 22:04:22 +00004358}
4359
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004360unsigned AArch64FastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
4361 bool IsZExt) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004362 assert(DestVT != MVT::i1 && "ZeroExt/SignExt an i1?");
Louis Gerbarg4c5b4052014-07-07 21:37:51 +00004363
Louis Gerbarg1ce0c37bf2014-07-09 17:54:32 +00004364 // FastISel does not have plumbing to deal with extensions where the SrcVT or
4365 // DestVT are odd things, so test to make sure that they are both types we can
4366 // handle (i1/i8/i16/i32 for SrcVT and i8/i16/i32/i64 for DestVT), otherwise
4367 // bail out to SelectionDAG.
4368 if (((DestVT != MVT::i8) && (DestVT != MVT::i16) &&
4369 (DestVT != MVT::i32) && (DestVT != MVT::i64)) ||
4370 ((SrcVT != MVT::i1) && (SrcVT != MVT::i8) &&
4371 (SrcVT != MVT::i16) && (SrcVT != MVT::i32)))
Louis Gerbarg4c5b4052014-07-07 21:37:51 +00004372 return 0;
4373
Tim Northover3b0846e2014-05-24 12:50:23 +00004374 unsigned Opc;
4375 unsigned Imm = 0;
4376
4377 switch (SrcVT.SimpleTy) {
4378 default:
4379 return 0;
4380 case MVT::i1:
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004381 return emiti1Ext(SrcReg, DestVT, IsZExt);
Tim Northover3b0846e2014-05-24 12:50:23 +00004382 case MVT::i8:
4383 if (DestVT == MVT::i64)
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004384 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
Tim Northover3b0846e2014-05-24 12:50:23 +00004385 else
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004386 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
Tim Northover3b0846e2014-05-24 12:50:23 +00004387 Imm = 7;
4388 break;
4389 case MVT::i16:
4390 if (DestVT == MVT::i64)
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004391 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
Tim Northover3b0846e2014-05-24 12:50:23 +00004392 else
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004393 Opc = IsZExt ? AArch64::UBFMWri : AArch64::SBFMWri;
Tim Northover3b0846e2014-05-24 12:50:23 +00004394 Imm = 15;
4395 break;
4396 case MVT::i32:
4397 assert(DestVT == MVT::i64 && "IntExt i32 to i32?!?");
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004398 Opc = IsZExt ? AArch64::UBFMXri : AArch64::SBFMXri;
Tim Northover3b0846e2014-05-24 12:50:23 +00004399 Imm = 31;
4400 break;
4401 }
4402
4403 // Handle i8 and i16 as i32.
4404 if (DestVT == MVT::i8 || DestVT == MVT::i16)
4405 DestVT = MVT::i32;
4406 else if (DestVT == MVT::i64) {
4407 unsigned Src64 = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4408 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4409 TII.get(AArch64::SUBREG_TO_REG), Src64)
4410 .addImm(0)
4411 .addReg(SrcReg)
4412 .addImm(AArch64::sub_32);
4413 SrcReg = Src64;
4414 }
4415
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00004416 const TargetRegisterClass *RC =
4417 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
Juergen Ributzka88e32512014-09-03 20:56:59 +00004418 return fastEmitInst_rii(Opc, RC, SrcReg, /*TODO:IsKill=*/false, 0, Imm);
Tim Northover3b0846e2014-05-24 12:50:23 +00004419}
4420
Juergen Ributzkacd11a282014-10-14 20:36:02 +00004421static bool isZExtLoad(const MachineInstr *LI) {
4422 switch (LI->getOpcode()) {
4423 default:
4424 return false;
4425 case AArch64::LDURBBi:
4426 case AArch64::LDURHHi:
4427 case AArch64::LDURWi:
4428 case AArch64::LDRBBui:
4429 case AArch64::LDRHHui:
4430 case AArch64::LDRWui:
4431 case AArch64::LDRBBroX:
4432 case AArch64::LDRHHroX:
4433 case AArch64::LDRWroX:
4434 case AArch64::LDRBBroW:
4435 case AArch64::LDRHHroW:
4436 case AArch64::LDRWroW:
4437 return true;
4438 }
4439}
4440
4441static bool isSExtLoad(const MachineInstr *LI) {
4442 switch (LI->getOpcode()) {
4443 default:
4444 return false;
4445 case AArch64::LDURSBWi:
4446 case AArch64::LDURSHWi:
4447 case AArch64::LDURSBXi:
4448 case AArch64::LDURSHXi:
4449 case AArch64::LDURSWi:
4450 case AArch64::LDRSBWui:
4451 case AArch64::LDRSHWui:
4452 case AArch64::LDRSBXui:
4453 case AArch64::LDRSHXui:
4454 case AArch64::LDRSWui:
4455 case AArch64::LDRSBWroX:
4456 case AArch64::LDRSHWroX:
4457 case AArch64::LDRSBXroX:
4458 case AArch64::LDRSHXroX:
4459 case AArch64::LDRSWroX:
4460 case AArch64::LDRSBWroW:
4461 case AArch64::LDRSHWroW:
4462 case AArch64::LDRSBXroW:
4463 case AArch64::LDRSHXroW:
4464 case AArch64::LDRSWroW:
4465 return true;
4466 }
4467}
4468
4469bool AArch64FastISel::optimizeIntExtLoad(const Instruction *I, MVT RetVT,
4470 MVT SrcVT) {
4471 const auto *LI = dyn_cast<LoadInst>(I->getOperand(0));
4472 if (!LI || !LI->hasOneUse())
4473 return false;
4474
4475 // Check if the load instruction has already been selected.
4476 unsigned Reg = lookUpRegForValue(LI);
4477 if (!Reg)
4478 return false;
4479
4480 MachineInstr *MI = MRI.getUniqueVRegDef(Reg);
4481 if (!MI)
4482 return false;
4483
4484 // Check if the correct load instruction has been emitted - SelectionDAG might
4485 // have emitted a zero-extending load, but we need a sign-extending load.
4486 bool IsZExt = isa<ZExtInst>(I);
4487 const auto *LoadMI = MI;
4488 if (LoadMI->getOpcode() == TargetOpcode::COPY &&
4489 LoadMI->getOperand(1).getSubReg() == AArch64::sub_32) {
4490 unsigned LoadReg = MI->getOperand(1).getReg();
4491 LoadMI = MRI.getUniqueVRegDef(LoadReg);
4492 assert(LoadMI && "Expected valid instruction");
4493 }
4494 if (!(IsZExt && isZExtLoad(LoadMI)) && !(!IsZExt && isSExtLoad(LoadMI)))
4495 return false;
4496
4497 // Nothing to be done.
4498 if (RetVT != MVT::i64 || SrcVT > MVT::i32) {
4499 updateValueMap(I, Reg);
4500 return true;
4501 }
4502
4503 if (IsZExt) {
4504 unsigned Reg64 = createResultReg(&AArch64::GPR64RegClass);
4505 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4506 TII.get(AArch64::SUBREG_TO_REG), Reg64)
4507 .addImm(0)
4508 .addReg(Reg, getKillRegState(true))
4509 .addImm(AArch64::sub_32);
4510 Reg = Reg64;
4511 } else {
4512 assert((MI->getOpcode() == TargetOpcode::COPY &&
4513 MI->getOperand(1).getSubReg() == AArch64::sub_32) &&
4514 "Expected copy instruction");
4515 Reg = MI->getOperand(1).getReg();
Tim Northover256a16d2018-12-17 17:25:53 +00004516 MachineBasicBlock::iterator I(MI);
4517 removeDeadCode(I, std::next(I));
Juergen Ributzkacd11a282014-10-14 20:36:02 +00004518 }
4519 updateValueMap(I, Reg);
4520 return true;
4521}
4522
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004523bool AArch64FastISel::selectIntExt(const Instruction *I) {
Juergen Ributzka6ac12432014-09-30 00:49:58 +00004524 assert((isa<ZExtInst>(I) || isa<SExtInst>(I)) &&
4525 "Unexpected integer extend instruction.");
4526 MVT RetVT;
4527 MVT SrcVT;
4528 if (!isTypeSupported(I->getType(), RetVT))
4529 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004530
Juergen Ributzka6ac12432014-09-30 00:49:58 +00004531 if (!isTypeSupported(I->getOperand(0)->getType(), SrcVT))
4532 return false;
4533
Juergen Ributzkacd11a282014-10-14 20:36:02 +00004534 // Try to optimize already sign-/zero-extended values from load instructions.
4535 if (optimizeIntExtLoad(I, RetVT, SrcVT))
4536 return true;
4537
Juergen Ributzka6ac12432014-09-30 00:49:58 +00004538 unsigned SrcReg = getRegForValue(I->getOperand(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00004539 if (!SrcReg)
4540 return false;
Juergen Ributzka42bf6652014-10-07 03:39:59 +00004541 bool SrcIsKill = hasTrivialKill(I->getOperand(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00004542
Juergen Ributzkacd11a282014-10-14 20:36:02 +00004543 // Try to optimize already sign-/zero-extended values from function arguments.
Juergen Ributzka42bf6652014-10-07 03:39:59 +00004544 bool IsZExt = isa<ZExtInst>(I);
4545 if (const auto *Arg = dyn_cast<Argument>(I->getOperand(0))) {
4546 if ((IsZExt && Arg->hasZExtAttr()) || (!IsZExt && Arg->hasSExtAttr())) {
4547 if (RetVT == MVT::i64 && SrcVT != MVT::i64) {
4548 unsigned ResultReg = createResultReg(&AArch64::GPR64RegClass);
4549 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4550 TII.get(AArch64::SUBREG_TO_REG), ResultReg)
4551 .addImm(0)
4552 .addReg(SrcReg, getKillRegState(SrcIsKill))
4553 .addImm(AArch64::sub_32);
4554 SrcReg = ResultReg;
4555 }
Juergen Ributzkaea5870a2014-11-10 21:05:31 +00004556 // Conservatively clear all kill flags from all uses, because we are
4557 // replacing a sign-/zero-extend instruction at IR level with a nop at MI
4558 // level. The result of the instruction at IR level might have been
4559 // trivially dead, which is now not longer true.
4560 unsigned UseReg = lookUpRegForValue(I);
4561 if (UseReg)
4562 MRI.clearKillFlags(UseReg);
4563
Juergen Ributzka42bf6652014-10-07 03:39:59 +00004564 updateValueMap(I, SrcReg);
4565 return true;
4566 }
4567 }
Juergen Ributzka51f53262014-08-05 05:43:44 +00004568
Juergen Ributzka42bf6652014-10-07 03:39:59 +00004569 unsigned ResultReg = emitIntExt(SrcVT, SrcReg, RetVT, IsZExt);
Juergen Ributzka51f53262014-08-05 05:43:44 +00004570 if (!ResultReg)
Tim Northover3b0846e2014-05-24 12:50:23 +00004571 return false;
Juergen Ributzka51f53262014-08-05 05:43:44 +00004572
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00004573 updateValueMap(I, ResultReg);
Tim Northover3b0846e2014-05-24 12:50:23 +00004574 return true;
4575}
4576
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004577bool AArch64FastISel::selectRem(const Instruction *I, unsigned ISDOpcode) {
Mehdi Amini44ede332015-07-09 02:09:04 +00004578 EVT DestEVT = TLI.getValueType(DL, I->getType(), true);
Tim Northover3b0846e2014-05-24 12:50:23 +00004579 if (!DestEVT.isSimple())
4580 return false;
4581
4582 MVT DestVT = DestEVT.getSimpleVT();
4583 if (DestVT != MVT::i64 && DestVT != MVT::i32)
4584 return false;
4585
4586 unsigned DivOpc;
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004587 bool Is64bit = (DestVT == MVT::i64);
Tim Northover3b0846e2014-05-24 12:50:23 +00004588 switch (ISDOpcode) {
4589 default:
4590 return false;
4591 case ISD::SREM:
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004592 DivOpc = Is64bit ? AArch64::SDIVXr : AArch64::SDIVWr;
Tim Northover3b0846e2014-05-24 12:50:23 +00004593 break;
4594 case ISD::UREM:
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004595 DivOpc = Is64bit ? AArch64::UDIVXr : AArch64::UDIVWr;
Tim Northover3b0846e2014-05-24 12:50:23 +00004596 break;
4597 }
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004598 unsigned MSubOpc = Is64bit ? AArch64::MSUBXrrr : AArch64::MSUBWrrr;
Tim Northover3b0846e2014-05-24 12:50:23 +00004599 unsigned Src0Reg = getRegForValue(I->getOperand(0));
4600 if (!Src0Reg)
4601 return false;
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00004602 bool Src0IsKill = hasTrivialKill(I->getOperand(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00004603
4604 unsigned Src1Reg = getRegForValue(I->getOperand(1));
4605 if (!Src1Reg)
4606 return false;
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00004607 bool Src1IsKill = hasTrivialKill(I->getOperand(1));
Tim Northover3b0846e2014-05-24 12:50:23 +00004608
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00004609 const TargetRegisterClass *RC =
4610 (DestVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
Juergen Ributzka88e32512014-09-03 20:56:59 +00004611 unsigned QuotReg = fastEmitInst_rr(DivOpc, RC, Src0Reg, /*IsKill=*/false,
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00004612 Src1Reg, /*IsKill=*/false);
4613 assert(QuotReg && "Unexpected DIV instruction emission failure.");
Tim Northover3b0846e2014-05-24 12:50:23 +00004614 // The remainder is computed as numerator - (quotient * denominator) using the
4615 // MSUB instruction.
Juergen Ributzka88e32512014-09-03 20:56:59 +00004616 unsigned ResultReg = fastEmitInst_rrr(MSubOpc, RC, QuotReg, /*IsKill=*/true,
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00004617 Src1Reg, Src1IsKill, Src0Reg,
4618 Src0IsKill);
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00004619 updateValueMap(I, ResultReg);
Tim Northover3b0846e2014-05-24 12:50:23 +00004620 return true;
4621}
4622
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004623bool AArch64FastISel::selectMul(const Instruction *I) {
Juergen Ributzkac611d722014-09-17 20:35:41 +00004624 MVT VT;
4625 if (!isTypeSupported(I->getType(), VT, /*IsVectorAllowed=*/true))
Tim Northover3b0846e2014-05-24 12:50:23 +00004626 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004627
Juergen Ributzkac611d722014-09-17 20:35:41 +00004628 if (VT.isVector())
4629 return selectBinaryOp(I, ISD::MUL);
4630
4631 const Value *Src0 = I->getOperand(0);
4632 const Value *Src1 = I->getOperand(1);
4633 if (const auto *C = dyn_cast<ConstantInt>(Src0))
4634 if (C->getValue().isPowerOf2())
4635 std::swap(Src0, Src1);
4636
4637 // Try to simplify to a shift instruction.
4638 if (const auto *C = dyn_cast<ConstantInt>(Src1))
4639 if (C->getValue().isPowerOf2()) {
4640 uint64_t ShiftVal = C->getValue().logBase2();
4641 MVT SrcVT = VT;
4642 bool IsZExt = true;
4643 if (const auto *ZExt = dyn_cast<ZExtInst>(Src0)) {
Juergen Ributzka6ac12432014-09-30 00:49:58 +00004644 if (!isIntExtFree(ZExt)) {
4645 MVT VT;
4646 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), VT)) {
4647 SrcVT = VT;
4648 IsZExt = true;
4649 Src0 = ZExt->getOperand(0);
4650 }
Juergen Ributzkac611d722014-09-17 20:35:41 +00004651 }
4652 } else if (const auto *SExt = dyn_cast<SExtInst>(Src0)) {
Juergen Ributzka6ac12432014-09-30 00:49:58 +00004653 if (!isIntExtFree(SExt)) {
4654 MVT VT;
4655 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), VT)) {
4656 SrcVT = VT;
4657 IsZExt = false;
4658 Src0 = SExt->getOperand(0);
4659 }
Juergen Ributzkac611d722014-09-17 20:35:41 +00004660 }
4661 }
4662
4663 unsigned Src0Reg = getRegForValue(Src0);
4664 if (!Src0Reg)
4665 return false;
4666 bool Src0IsKill = hasTrivialKill(Src0);
4667
4668 unsigned ResultReg =
4669 emitLSL_ri(VT, SrcVT, Src0Reg, Src0IsKill, ShiftVal, IsZExt);
4670
4671 if (ResultReg) {
4672 updateValueMap(I, ResultReg);
4673 return true;
4674 }
4675 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004676
Tim Northover3b0846e2014-05-24 12:50:23 +00004677 unsigned Src0Reg = getRegForValue(I->getOperand(0));
4678 if (!Src0Reg)
4679 return false;
Juergen Ributzkaad3b0902014-07-30 22:04:25 +00004680 bool Src0IsKill = hasTrivialKill(I->getOperand(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00004681
4682 unsigned Src1Reg = getRegForValue(I->getOperand(1));
4683 if (!Src1Reg)
4684 return false;
Juergen Ributzkaad3b0902014-07-30 22:04:25 +00004685 bool Src1IsKill = hasTrivialKill(I->getOperand(1));
Tim Northover3b0846e2014-05-24 12:50:23 +00004686
Juergen Ributzkac611d722014-09-17 20:35:41 +00004687 unsigned ResultReg = emitMul_rr(VT, Src0Reg, Src0IsKill, Src1Reg, Src1IsKill);
Juergen Ributzkaad3b0902014-07-30 22:04:25 +00004688
4689 if (!ResultReg)
4690 return false;
4691
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00004692 updateValueMap(I, ResultReg);
Tim Northover3b0846e2014-05-24 12:50:23 +00004693 return true;
4694}
4695
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004696bool AArch64FastISel::selectShift(const Instruction *I) {
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004697 MVT RetVT;
Juergen Ributzkae1779e22014-09-15 21:27:56 +00004698 if (!isTypeSupported(I->getType(), RetVT, /*IsVectorAllowed=*/true))
Juergen Ributzkaa75cb112014-07-30 22:04:22 +00004699 return false;
Juergen Ributzkaa75cb112014-07-30 22:04:22 +00004700
Juergen Ributzkae1779e22014-09-15 21:27:56 +00004701 if (RetVT.isVector())
4702 return selectOperator(I, I->getOpcode());
4703
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +00004704 if (const auto *C = dyn_cast<ConstantInt>(I->getOperand(1))) {
4705 unsigned ResultReg = 0;
4706 uint64_t ShiftVal = C->getZExtValue();
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004707 MVT SrcVT = RetVT;
David Blaikie186d2cb2015-03-24 16:24:01 +00004708 bool IsZExt = I->getOpcode() != Instruction::AShr;
Juergen Ributzka77bc09f2014-08-29 00:19:21 +00004709 const Value *Op0 = I->getOperand(0);
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004710 if (const auto *ZExt = dyn_cast<ZExtInst>(Op0)) {
Juergen Ributzka6ac12432014-09-30 00:49:58 +00004711 if (!isIntExtFree(ZExt)) {
4712 MVT TmpVT;
4713 if (isValueAvailable(ZExt) && isTypeSupported(ZExt->getSrcTy(), TmpVT)) {
4714 SrcVT = TmpVT;
4715 IsZExt = true;
4716 Op0 = ZExt->getOperand(0);
4717 }
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004718 }
4719 } else if (const auto *SExt = dyn_cast<SExtInst>(Op0)) {
Juergen Ributzka6ac12432014-09-30 00:49:58 +00004720 if (!isIntExtFree(SExt)) {
4721 MVT TmpVT;
4722 if (isValueAvailable(SExt) && isTypeSupported(SExt->getSrcTy(), TmpVT)) {
4723 SrcVT = TmpVT;
4724 IsZExt = false;
4725 Op0 = SExt->getOperand(0);
4726 }
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004727 }
4728 }
4729
4730 unsigned Op0Reg = getRegForValue(Op0);
4731 if (!Op0Reg)
4732 return false;
4733 bool Op0IsKill = hasTrivialKill(Op0);
4734
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +00004735 switch (I->getOpcode()) {
4736 default: llvm_unreachable("Unexpected instruction.");
4737 case Instruction::Shl:
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004738 ResultReg = emitLSL_ri(RetVT, SrcVT, Op0Reg, Op0IsKill, ShiftVal, IsZExt);
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +00004739 break;
4740 case Instruction::AShr:
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004741 ResultReg = emitASR_ri(RetVT, SrcVT, Op0Reg, Op0IsKill, ShiftVal, IsZExt);
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +00004742 break;
4743 case Instruction::LShr:
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004744 ResultReg = emitLSR_ri(RetVT, SrcVT, Op0Reg, Op0IsKill, ShiftVal, IsZExt);
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +00004745 break;
4746 }
4747 if (!ResultReg)
4748 return false;
Juergen Ributzkaa75cb112014-07-30 22:04:22 +00004749
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00004750 updateValueMap(I, ResultReg);
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +00004751 return true;
4752 }
4753
Juergen Ributzka99dd30f2014-08-27 00:58:26 +00004754 unsigned Op0Reg = getRegForValue(I->getOperand(0));
4755 if (!Op0Reg)
4756 return false;
4757 bool Op0IsKill = hasTrivialKill(I->getOperand(0));
4758
Juergen Ributzka0e0b4c12014-08-21 23:06:07 +00004759 unsigned Op1Reg = getRegForValue(I->getOperand(1));
4760 if (!Op1Reg)
4761 return false;
4762 bool Op1IsKill = hasTrivialKill(I->getOperand(1));
4763
4764 unsigned ResultReg = 0;
4765 switch (I->getOpcode()) {
4766 default: llvm_unreachable("Unexpected instruction.");
4767 case Instruction::Shl:
4768 ResultReg = emitLSL_rr(RetVT, Op0Reg, Op0IsKill, Op1Reg, Op1IsKill);
4769 break;
4770 case Instruction::AShr:
4771 ResultReg = emitASR_rr(RetVT, Op0Reg, Op0IsKill, Op1Reg, Op1IsKill);
4772 break;
4773 case Instruction::LShr:
4774 ResultReg = emitLSR_rr(RetVT, Op0Reg, Op0IsKill, Op1Reg, Op1IsKill);
4775 break;
Juergen Ributzkaa75cb112014-07-30 22:04:22 +00004776 }
4777
4778 if (!ResultReg)
4779 return false;
4780
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00004781 updateValueMap(I, ResultReg);
Juergen Ributzkaa75cb112014-07-30 22:04:22 +00004782 return true;
4783}
4784
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00004785bool AArch64FastISel::selectBitCast(const Instruction *I) {
Juergen Ributzkac537bd22014-07-31 06:25:37 +00004786 MVT RetVT, SrcVT;
4787
4788 if (!isTypeLegal(I->getOperand(0)->getType(), SrcVT))
4789 return false;
4790 if (!isTypeLegal(I->getType(), RetVT))
4791 return false;
4792
4793 unsigned Opc;
4794 if (RetVT == MVT::f32 && SrcVT == MVT::i32)
4795 Opc = AArch64::FMOVWSr;
4796 else if (RetVT == MVT::f64 && SrcVT == MVT::i64)
4797 Opc = AArch64::FMOVXDr;
4798 else if (RetVT == MVT::i32 && SrcVT == MVT::f32)
4799 Opc = AArch64::FMOVSWr;
4800 else if (RetVT == MVT::i64 && SrcVT == MVT::f64)
4801 Opc = AArch64::FMOVDXr;
4802 else
4803 return false;
4804
Juergen Ributzkaaddb75a2014-08-21 20:57:57 +00004805 const TargetRegisterClass *RC = nullptr;
4806 switch (RetVT.SimpleTy) {
4807 default: llvm_unreachable("Unexpected value type.");
4808 case MVT::i32: RC = &AArch64::GPR32RegClass; break;
4809 case MVT::i64: RC = &AArch64::GPR64RegClass; break;
4810 case MVT::f32: RC = &AArch64::FPR32RegClass; break;
4811 case MVT::f64: RC = &AArch64::FPR64RegClass; break;
4812 }
Juergen Ributzkac537bd22014-07-31 06:25:37 +00004813 unsigned Op0Reg = getRegForValue(I->getOperand(0));
4814 if (!Op0Reg)
4815 return false;
4816 bool Op0IsKill = hasTrivialKill(I->getOperand(0));
Juergen Ributzka88e32512014-09-03 20:56:59 +00004817 unsigned ResultReg = fastEmitInst_r(Opc, RC, Op0Reg, Op0IsKill);
Juergen Ributzkac537bd22014-07-31 06:25:37 +00004818
4819 if (!ResultReg)
4820 return false;
4821
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00004822 updateValueMap(I, ResultReg);
Juergen Ributzkac537bd22014-07-31 06:25:37 +00004823 return true;
4824}
4825
Juergen Ributzkaafa034f2014-09-15 22:07:49 +00004826bool AArch64FastISel::selectFRem(const Instruction *I) {
4827 MVT RetVT;
4828 if (!isTypeLegal(I->getType(), RetVT))
4829 return false;
4830
4831 RTLIB::Libcall LC;
4832 switch (RetVT.SimpleTy) {
4833 default:
4834 return false;
4835 case MVT::f32:
4836 LC = RTLIB::REM_F32;
4837 break;
4838 case MVT::f64:
4839 LC = RTLIB::REM_F64;
4840 break;
4841 }
4842
4843 ArgListTy Args;
4844 Args.reserve(I->getNumOperands());
4845
4846 // Populate the argument list.
4847 for (auto &Arg : I->operands()) {
4848 ArgListEntry Entry;
4849 Entry.Val = Arg;
4850 Entry.Ty = Arg->getType();
4851 Args.push_back(Entry);
4852 }
4853
4854 CallLoweringInfo CLI;
Rafael Espindolace4c2bc2015-06-23 12:21:54 +00004855 MCContext &Ctx = MF->getContext();
4856 CLI.setCallee(DL, Ctx, TLI.getLibcallCallingConv(LC), I->getType(),
Juergen Ributzkaafa034f2014-09-15 22:07:49 +00004857 TLI.getLibcallName(LC), std::move(Args));
4858 if (!lowerCallTo(CLI))
4859 return false;
4860 updateValueMap(I, CLI.ResultReg);
4861 return true;
4862}
4863
Juergen Ributzkaf6430312014-09-17 21:55:55 +00004864bool AArch64FastISel::selectSDiv(const Instruction *I) {
4865 MVT VT;
4866 if (!isTypeLegal(I->getType(), VT))
4867 return false;
4868
4869 if (!isa<ConstantInt>(I->getOperand(1)))
4870 return selectBinaryOp(I, ISD::SDIV);
4871
4872 const APInt &C = cast<ConstantInt>(I->getOperand(1))->getValue();
4873 if ((VT != MVT::i32 && VT != MVT::i64) || !C ||
4874 !(C.isPowerOf2() || (-C).isPowerOf2()))
4875 return selectBinaryOp(I, ISD::SDIV);
4876
4877 unsigned Lg2 = C.countTrailingZeros();
4878 unsigned Src0Reg = getRegForValue(I->getOperand(0));
4879 if (!Src0Reg)
4880 return false;
4881 bool Src0IsKill = hasTrivialKill(I->getOperand(0));
4882
4883 if (cast<BinaryOperator>(I)->isExact()) {
4884 unsigned ResultReg = emitASR_ri(VT, VT, Src0Reg, Src0IsKill, Lg2);
4885 if (!ResultReg)
4886 return false;
4887 updateValueMap(I, ResultReg);
4888 return true;
4889 }
4890
Juergen Ributzka03a06112014-10-16 16:41:15 +00004891 int64_t Pow2MinusOne = (1ULL << Lg2) - 1;
4892 unsigned AddReg = emitAdd_ri_(VT, Src0Reg, /*IsKill=*/false, Pow2MinusOne);
Juergen Ributzkaf6430312014-09-17 21:55:55 +00004893 if (!AddReg)
4894 return false;
4895
4896 // (Src0 < 0) ? Pow2 - 1 : 0;
4897 if (!emitICmp_ri(VT, Src0Reg, /*IsKill=*/false, 0))
4898 return false;
4899
4900 unsigned SelectOpc;
4901 const TargetRegisterClass *RC;
4902 if (VT == MVT::i64) {
4903 SelectOpc = AArch64::CSELXr;
4904 RC = &AArch64::GPR64RegClass;
4905 } else {
4906 SelectOpc = AArch64::CSELWr;
4907 RC = &AArch64::GPR32RegClass;
4908 }
4909 unsigned SelectReg =
4910 fastEmitInst_rri(SelectOpc, RC, AddReg, /*IsKill=*/true, Src0Reg,
4911 Src0IsKill, AArch64CC::LT);
4912 if (!SelectReg)
4913 return false;
4914
4915 // Divide by Pow2 --> ashr. If we're dividing by a negative value we must also
4916 // negate the result.
4917 unsigned ZeroReg = (VT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
4918 unsigned ResultReg;
4919 if (C.isNegative())
4920 ResultReg = emitAddSub_rs(/*UseAdd=*/false, VT, ZeroReg, /*IsKill=*/true,
4921 SelectReg, /*IsKill=*/true, AArch64_AM::ASR, Lg2);
4922 else
4923 ResultReg = emitASR_ri(VT, VT, SelectReg, /*IsKill=*/true, Lg2);
4924
4925 if (!ResultReg)
4926 return false;
4927
4928 updateValueMap(I, ResultReg);
4929 return true;
4930}
4931
Juergen Ributzka0af310d2014-11-13 20:50:44 +00004932/// This is mostly a copy of the existing FastISel getRegForGEPIndex code. We
4933/// have to duplicate it for AArch64, because otherwise we would fail during the
4934/// sign-extend emission.
4935std::pair<unsigned, bool> AArch64FastISel::getRegForGEPIndex(const Value *Idx) {
4936 unsigned IdxN = getRegForValue(Idx);
4937 if (IdxN == 0)
4938 // Unhandled operand. Halt "fast" selection and bail.
4939 return std::pair<unsigned, bool>(0, false);
4940
4941 bool IdxNIsKill = hasTrivialKill(Idx);
4942
4943 // If the index is smaller or larger than intptr_t, truncate or extend it.
Mehdi Amini44ede332015-07-09 02:09:04 +00004944 MVT PtrVT = TLI.getPointerTy(DL);
Juergen Ributzka0af310d2014-11-13 20:50:44 +00004945 EVT IdxVT = EVT::getEVT(Idx->getType(), /*HandleUnknown=*/false);
4946 if (IdxVT.bitsLT(PtrVT)) {
4947 IdxN = emitIntExt(IdxVT.getSimpleVT(), IdxN, PtrVT, /*IsZExt=*/false);
4948 IdxNIsKill = true;
4949 } else if (IdxVT.bitsGT(PtrVT))
4950 llvm_unreachable("AArch64 FastISel doesn't support types larger than i64");
4951 return std::pair<unsigned, bool>(IdxN, IdxNIsKill);
4952}
4953
Juergen Ributzkaf82c9872014-10-15 18:58:07 +00004954/// This is mostly a copy of the existing FastISel GEP code, but we have to
4955/// duplicate it for AArch64, because otherwise we would bail out even for
4956/// simple cases. This is because the standard fastEmit functions don't cover
4957/// MUL at all and ADD is lowered very inefficientily.
4958bool AArch64FastISel::selectGetElementPtr(const Instruction *I) {
4959 unsigned N = getRegForValue(I->getOperand(0));
4960 if (!N)
4961 return false;
4962 bool NIsKill = hasTrivialKill(I->getOperand(0));
4963
4964 // Keep a running tab of the total offset to coalesce multiple N = N + Offset
4965 // into a single N = N + TotalOffset.
4966 uint64_t TotalOffs = 0;
Mehdi Amini44ede332015-07-09 02:09:04 +00004967 MVT VT = TLI.getPointerTy(DL);
Eduard Burtescu23c4d832016-01-20 00:26:52 +00004968 for (gep_type_iterator GTI = gep_type_begin(I), E = gep_type_end(I);
4969 GTI != E; ++GTI) {
4970 const Value *Idx = GTI.getOperand();
Peter Collingbourneab85225b2016-12-02 02:24:42 +00004971 if (auto *StTy = GTI.getStructTypeOrNull()) {
Juergen Ributzkaf82c9872014-10-15 18:58:07 +00004972 unsigned Field = cast<ConstantInt>(Idx)->getZExtValue();
4973 // N = N + Offset
4974 if (Field)
4975 TotalOffs += DL.getStructLayout(StTy)->getElementOffset(Field);
Juergen Ributzkaf82c9872014-10-15 18:58:07 +00004976 } else {
Eduard Burtescu23c4d832016-01-20 00:26:52 +00004977 Type *Ty = GTI.getIndexedType();
4978
Juergen Ributzkaf82c9872014-10-15 18:58:07 +00004979 // If this is a constant subscript, handle it quickly.
4980 if (const auto *CI = dyn_cast<ConstantInt>(Idx)) {
4981 if (CI->isZero())
4982 continue;
4983 // N = N + Offset
4984 TotalOffs +=
4985 DL.getTypeAllocSize(Ty) * cast<ConstantInt>(CI)->getSExtValue();
4986 continue;
4987 }
4988 if (TotalOffs) {
4989 N = emitAdd_ri_(VT, N, NIsKill, TotalOffs);
4990 if (!N)
4991 return false;
4992 NIsKill = true;
4993 TotalOffs = 0;
4994 }
4995
4996 // N = N + Idx * ElementSize;
4997 uint64_t ElementSize = DL.getTypeAllocSize(Ty);
4998 std::pair<unsigned, bool> Pair = getRegForGEPIndex(Idx);
4999 unsigned IdxN = Pair.first;
5000 bool IdxNIsKill = Pair.second;
5001 if (!IdxN)
5002 return false;
5003
5004 if (ElementSize != 1) {
5005 unsigned C = fastEmit_i(VT, VT, ISD::Constant, ElementSize);
5006 if (!C)
5007 return false;
5008 IdxN = emitMul_rr(VT, IdxN, IdxNIsKill, C, true);
5009 if (!IdxN)
5010 return false;
5011 IdxNIsKill = true;
5012 }
5013 N = fastEmit_rr(VT, VT, ISD::ADD, N, NIsKill, IdxN, IdxNIsKill);
5014 if (!N)
5015 return false;
5016 }
5017 }
5018 if (TotalOffs) {
5019 N = emitAdd_ri_(VT, N, NIsKill, TotalOffs);
5020 if (!N)
5021 return false;
5022 }
5023 updateValueMap(I, N);
5024 return true;
5025}
5026
Ahmed Bougachaa0cdd792016-07-20 21:12:32 +00005027bool AArch64FastISel::selectAtomicCmpXchg(const AtomicCmpXchgInst *I) {
5028 assert(TM.getOptLevel() == CodeGenOpt::None &&
5029 "cmpxchg survived AtomicExpand at optlevel > -O0");
5030
5031 auto *RetPairTy = cast<StructType>(I->getType());
5032 Type *RetTy = RetPairTy->getTypeAtIndex(0U);
5033 assert(RetPairTy->getTypeAtIndex(1U)->isIntegerTy(1) &&
5034 "cmpxchg has a non-i1 status result");
5035
5036 MVT VT;
5037 if (!isTypeLegal(RetTy, VT))
5038 return false;
5039
5040 const TargetRegisterClass *ResRC;
Tim Northover1021d892016-08-02 20:22:36 +00005041 unsigned Opc, CmpOpc;
Ahmed Bougachaa0cdd792016-07-20 21:12:32 +00005042 // This only supports i32/i64, because i8/i16 aren't legal, and the generic
5043 // extractvalue selection doesn't support that.
5044 if (VT == MVT::i32) {
5045 Opc = AArch64::CMP_SWAP_32;
Tim Northover1021d892016-08-02 20:22:36 +00005046 CmpOpc = AArch64::SUBSWrs;
Ahmed Bougachaa0cdd792016-07-20 21:12:32 +00005047 ResRC = &AArch64::GPR32RegClass;
5048 } else if (VT == MVT::i64) {
5049 Opc = AArch64::CMP_SWAP_64;
Tim Northover1021d892016-08-02 20:22:36 +00005050 CmpOpc = AArch64::SUBSXrs;
Ahmed Bougachaa0cdd792016-07-20 21:12:32 +00005051 ResRC = &AArch64::GPR64RegClass;
5052 } else {
5053 return false;
5054 }
5055
5056 const MCInstrDesc &II = TII.get(Opc);
5057
5058 const unsigned AddrReg = constrainOperandRegClass(
5059 II, getRegForValue(I->getPointerOperand()), II.getNumDefs());
5060 const unsigned DesiredReg = constrainOperandRegClass(
5061 II, getRegForValue(I->getCompareOperand()), II.getNumDefs() + 1);
5062 const unsigned NewReg = constrainOperandRegClass(
5063 II, getRegForValue(I->getNewValOperand()), II.getNumDefs() + 2);
5064
5065 const unsigned ResultReg1 = createResultReg(ResRC);
5066 const unsigned ResultReg2 = createResultReg(&AArch64::GPR32RegClass);
Tim Northover1021d892016-08-02 20:22:36 +00005067 const unsigned ScratchReg = createResultReg(&AArch64::GPR32RegClass);
Ahmed Bougachaa0cdd792016-07-20 21:12:32 +00005068
5069 // FIXME: MachineMemOperand doesn't support cmpxchg yet.
5070 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
Tim Northover1021d892016-08-02 20:22:36 +00005071 .addDef(ResultReg1)
5072 .addDef(ScratchReg)
5073 .addUse(AddrReg)
5074 .addUse(DesiredReg)
5075 .addUse(NewReg);
5076
5077 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(CmpOpc))
5078 .addDef(VT == MVT::i32 ? AArch64::WZR : AArch64::XZR)
5079 .addUse(ResultReg1)
5080 .addUse(DesiredReg)
5081 .addImm(0);
5082
5083 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::CSINCWr))
5084 .addDef(ResultReg2)
5085 .addUse(AArch64::WZR)
5086 .addUse(AArch64::WZR)
5087 .addImm(AArch64CC::NE);
Ahmed Bougachaa0cdd792016-07-20 21:12:32 +00005088
5089 assert((ResultReg1 + 1) == ResultReg2 && "Nonconsecutive result registers.");
5090 updateValueMap(I, ResultReg1, 2);
5091 return true;
5092}
5093
Juergen Ributzka5b8bb4d2014-09-03 20:56:52 +00005094bool AArch64FastISel::fastSelectInstruction(const Instruction *I) {
Tim Northover3b0846e2014-05-24 12:50:23 +00005095 switch (I->getOpcode()) {
5096 default:
Juergen Ributzka30c02e32014-09-04 01:29:21 +00005097 break;
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005098 case Instruction::Add:
Juergen Ributzkaa1148b22014-09-03 01:38:36 +00005099 case Instruction::Sub:
Quentin Colombet35a47012017-04-01 01:26:17 +00005100 return selectAddSub(I);
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005101 case Instruction::Mul:
Quentin Colombet35a47012017-04-01 01:26:17 +00005102 return selectMul(I);
Juergen Ributzkaf6430312014-09-17 21:55:55 +00005103 case Instruction::SDiv:
Quentin Colombet35a47012017-04-01 01:26:17 +00005104 return selectSDiv(I);
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005105 case Instruction::SRem:
Juergen Ributzka7a76c242014-09-03 18:46:45 +00005106 if (!selectBinaryOp(I, ISD::SREM))
Quentin Colombet35a47012017-04-01 01:26:17 +00005107 return selectRem(I, ISD::SREM);
5108 return true;
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005109 case Instruction::URem:
Juergen Ributzka7a76c242014-09-03 18:46:45 +00005110 if (!selectBinaryOp(I, ISD::UREM))
Quentin Colombet35a47012017-04-01 01:26:17 +00005111 return selectRem(I, ISD::UREM);
5112 return true;
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005113 case Instruction::Shl:
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005114 case Instruction::LShr:
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005115 case Instruction::AShr:
Quentin Colombet35a47012017-04-01 01:26:17 +00005116 return selectShift(I);
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005117 case Instruction::And:
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005118 case Instruction::Or:
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005119 case Instruction::Xor:
Quentin Colombet35a47012017-04-01 01:26:17 +00005120 return selectLogicalOp(I);
Juergen Ributzka31c80542014-09-03 17:58:10 +00005121 case Instruction::Br:
Quentin Colombet35a47012017-04-01 01:26:17 +00005122 return selectBranch(I);
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005123 case Instruction::IndirectBr:
Quentin Colombet35a47012017-04-01 01:26:17 +00005124 return selectIndirectBr(I);
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005125 case Instruction::BitCast:
Juergen Ributzka7a76c242014-09-03 18:46:45 +00005126 if (!FastISel::selectBitCast(I))
Quentin Colombet35a47012017-04-01 01:26:17 +00005127 return selectBitCast(I);
5128 return true;
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005129 case Instruction::FPToSI:
Juergen Ributzka7a76c242014-09-03 18:46:45 +00005130 if (!selectCast(I, ISD::FP_TO_SINT))
Quentin Colombet35a47012017-04-01 01:26:17 +00005131 return selectFPToInt(I, /*Signed=*/true);
5132 return true;
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005133 case Instruction::FPToUI:
Quentin Colombet35a47012017-04-01 01:26:17 +00005134 return selectFPToInt(I, /*Signed=*/false);
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005135 case Instruction::ZExt:
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005136 case Instruction::SExt:
Quentin Colombet35a47012017-04-01 01:26:17 +00005137 return selectIntExt(I);
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005138 case Instruction::Trunc:
Juergen Ributzka7a76c242014-09-03 18:46:45 +00005139 if (!selectCast(I, ISD::TRUNCATE))
Quentin Colombet35a47012017-04-01 01:26:17 +00005140 return selectTrunc(I);
5141 return true;
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005142 case Instruction::FPExt:
Quentin Colombet35a47012017-04-01 01:26:17 +00005143 return selectFPExt(I);
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005144 case Instruction::FPTrunc:
Quentin Colombet35a47012017-04-01 01:26:17 +00005145 return selectFPTrunc(I);
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005146 case Instruction::SIToFP:
Juergen Ributzka7a76c242014-09-03 18:46:45 +00005147 if (!selectCast(I, ISD::SINT_TO_FP))
Quentin Colombet35a47012017-04-01 01:26:17 +00005148 return selectIntToFP(I, /*Signed=*/true);
5149 return true;
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005150 case Instruction::UIToFP:
Quentin Colombet35a47012017-04-01 01:26:17 +00005151 return selectIntToFP(I, /*Signed=*/false);
Tim Northover3b0846e2014-05-24 12:50:23 +00005152 case Instruction::Load:
Quentin Colombet35a47012017-04-01 01:26:17 +00005153 return selectLoad(I);
Tim Northover3b0846e2014-05-24 12:50:23 +00005154 case Instruction::Store:
Quentin Colombet35a47012017-04-01 01:26:17 +00005155 return selectStore(I);
Tim Northover3b0846e2014-05-24 12:50:23 +00005156 case Instruction::FCmp:
5157 case Instruction::ICmp:
Quentin Colombet35a47012017-04-01 01:26:17 +00005158 return selectCmp(I);
Tim Northover3b0846e2014-05-24 12:50:23 +00005159 case Instruction::Select:
Quentin Colombet35a47012017-04-01 01:26:17 +00005160 return selectSelect(I);
Tim Northover3b0846e2014-05-24 12:50:23 +00005161 case Instruction::Ret:
Quentin Colombet35a47012017-04-01 01:26:17 +00005162 return selectRet(I);
Juergen Ributzkaafa034f2014-09-15 22:07:49 +00005163 case Instruction::FRem:
Quentin Colombet35a47012017-04-01 01:26:17 +00005164 return selectFRem(I);
Juergen Ributzkaf82c9872014-10-15 18:58:07 +00005165 case Instruction::GetElementPtr:
Quentin Colombet35a47012017-04-01 01:26:17 +00005166 return selectGetElementPtr(I);
Ahmed Bougachaa0cdd792016-07-20 21:12:32 +00005167 case Instruction::AtomicCmpXchg:
Quentin Colombet35a47012017-04-01 01:26:17 +00005168 return selectAtomicCmpXchg(cast<AtomicCmpXchgInst>(I));
Tim Northover3b0846e2014-05-24 12:50:23 +00005169 }
Juergen Ributzkadbe9e172014-09-02 21:32:54 +00005170
Adrian Prantl0e6694d2017-12-19 22:05:25 +00005171 // fall-back to target-independent instruction selection.
5172 return selectOperator(I, I->getOpcode());
Tim Northover3b0846e2014-05-24 12:50:23 +00005173}
5174
5175namespace llvm {
Eugene Zelenko11f69072017-01-25 00:29:26 +00005176
5177FastISel *AArch64::createFastISel(FunctionLoweringInfo &FuncInfo,
Juergen Ributzkab9e49c72014-09-15 23:20:17 +00005178 const TargetLibraryInfo *LibInfo) {
5179 return new AArch64FastISel(FuncInfo, LibInfo);
Tim Northover3b0846e2014-05-24 12:50:23 +00005180}
Eugene Zelenko11f69072017-01-25 00:29:26 +00005181
5182} // end namespace llvm