blob: 8c1d088ddf4549bc509e0e0b32b41937df623aa5 [file] [log] [blame]
Jan Voungb36ad9b2015-04-21 17:01:49 -07001//===- subzero/src/IceTargetLoweringARM32.h - ARM32 lowering ----*- C++ -*-===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Declares the TargetLoweringARM32 class, which implements the
Andrew Scull9612d322015-07-06 14:53:25 -070012/// TargetLowering interface for the ARM 32-bit architecture.
13///
Jan Voungb36ad9b2015-04-21 17:01:49 -070014//===----------------------------------------------------------------------===//
15
16#ifndef SUBZERO_SRC_ICETARGETLOWERINGARM32_H
17#define SUBZERO_SRC_ICETARGETLOWERINGARM32_H
18
John Porto53611e22015-12-30 07:30:10 -080019#include "IceAssemblerARM32.h"
Jan Voungb36ad9b2015-04-21 17:01:49 -070020#include "IceDefs.h"
Jan Voungb2d50842015-05-12 09:53:50 -070021#include "IceInstARM32.h"
Jan Voungb36ad9b2015-04-21 17:01:49 -070022#include "IceRegistersARM32.h"
23#include "IceTargetLowering.h"
24
25namespace Ice {
John Porto4a566862016-01-04 09:33:41 -080026namespace ARM32 {
Jan Voungb36ad9b2015-04-21 17:01:49 -070027
Jan Voung6ec369e2015-06-30 11:03:15 -070028// Class encapsulating ARM cpu features / instruction set.
29class TargetARM32Features {
30 TargetARM32Features() = delete;
31 TargetARM32Features(const TargetARM32Features &) = delete;
32 TargetARM32Features &operator=(const TargetARM32Features &) = delete;
33
34public:
35 explicit TargetARM32Features(const ClFlags &Flags);
36
37 enum ARM32InstructionSet {
38 Begin,
39 // Neon is the PNaCl baseline instruction set.
40 Neon = Begin,
41 HWDivArm, // HW divide in ARM mode (not just Thumb mode).
42 End
43 };
44
45 bool hasFeature(ARM32InstructionSet I) const { return I <= InstructionSet; }
46
47private:
48 ARM32InstructionSet InstructionSet = ARM32InstructionSet::Begin;
49};
50
51// The target lowering logic for ARM32.
Jan Voungb36ad9b2015-04-21 17:01:49 -070052class TargetARM32 : public TargetLowering {
53 TargetARM32() = delete;
54 TargetARM32(const TargetARM32 &) = delete;
55 TargetARM32 &operator=(const TargetARM32 &) = delete;
56
57public:
Karl Schimpf5403f5d2016-01-15 11:07:46 -080058 static void staticInit(GlobalContext *Ctx);
Jan Voungb36ad9b2015-04-21 17:01:49 -070059 // TODO(jvoung): return a unique_ptr.
John Porto53611e22015-12-30 07:30:10 -080060 static std::unique_ptr<::Ice::TargetLowering> create(Cfg *Func) {
61 return makeUnique<TargetARM32>(Func);
62 }
63
64 std::unique_ptr<::Ice::Assembler> createAssembler() const override {
John Portodc619252016-02-10 15:57:16 -080065 const bool IsNonsfi = SandboxingType == ST_Nonsfi;
66 return makeUnique<ARM32::AssemblerARM32>(IsNonsfi);
John Porto53611e22015-12-30 07:30:10 -080067 }
Jan Voungb36ad9b2015-04-21 17:01:49 -070068
John Porto4a5e6d02015-11-04 09:32:55 -080069 void initNodeForLowering(CfgNode *Node) override {
John Portoeb13acc2015-12-09 05:10:58 -080070 Computations.forgetProducers();
71 Computations.recordProducers(Node);
72 Computations.dump(Func);
John Porto4a5e6d02015-11-04 09:32:55 -080073 }
74
Jan Voungb36ad9b2015-04-21 17:01:49 -070075 void translateOm1() override;
76 void translateO2() override;
77 bool doBranchOpt(Inst *I, const CfgNode *NextNode) override;
78
79 SizeT getNumRegisters() const override { return RegARM32::Reg_NUM; }
Jim Stichnoth8aa39662016-02-10 11:20:30 -080080 Variable *getPhysicalRegister(RegNumT RegNum,
81 Type Ty = IceType_void) override;
82 IceString getRegName(RegNumT RegNum, Type Ty) const override;
John Portoe82b5602016-02-24 15:58:55 -080083 SmallBitVector getRegisterSet(RegSetMask Include,
84 RegSetMask Exclude) const override;
85 const SmallBitVector &
Jim Stichnothc59288b2015-11-09 11:38:40 -080086 getRegistersForVariable(const Variable *Var) const override {
87 RegClass RC = Var->getRegClass();
Eric Holk658bae22016-02-08 15:22:18 -080088 switch (RC) {
89 default:
90 assert(RC < RC_Target);
91 return TypeToRegisterSet[RC];
92 case RegARM32::RCARM32_QtoS:
93 return TypeToRegisterSet[RC];
94 }
Jan Voungb36ad9b2015-04-21 17:01:49 -070095 }
John Portoe82b5602016-02-24 15:58:55 -080096 const SmallBitVector &
Jim Stichnothb40595a2016-01-29 06:14:31 -080097 getAllRegistersForVariable(const Variable *Var) const override {
98 RegClass RC = Var->getRegClass();
Eric Holk658bae22016-02-08 15:22:18 -080099 assert((RegARM32::RegClassARM32)RC < RegARM32::RCARM32_NUM);
Jim Stichnothb40595a2016-01-29 06:14:31 -0800100 return TypeToRegisterSetUnfiltered[RC];
101 }
John Portoe82b5602016-02-24 15:58:55 -0800102 const SmallBitVector &getAliasesForRegister(RegNumT Reg) const override {
John Portobb0a5fe2015-09-04 11:23:41 -0700103 return RegisterAliases[Reg];
104 }
Jan Voungb36ad9b2015-04-21 17:01:49 -0700105 bool hasFramePointer() const override { return UsesFramePointer; }
David Sehre39d0ca2015-11-06 11:25:41 -0800106 void setHasFramePointer() override { UsesFramePointer = true; }
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800107 RegNumT getStackReg() const override { return RegARM32::Reg_sp; }
108 RegNumT getFrameReg() const override { return RegARM32::Reg_fp; }
109 RegNumT getFrameOrStackReg() const override {
David Sehr2f3b8ec2015-11-16 16:51:39 -0800110 return UsesFramePointer ? getFrameReg() : getStackReg();
Jan Voungb36ad9b2015-04-21 17:01:49 -0700111 }
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800112 RegNumT getReservedTmpReg() const { return RegARM32::Reg_ip; }
Jan Voung28068ad2015-07-31 12:58:46 -0700113
Jan Voungb36ad9b2015-04-21 17:01:49 -0700114 size_t typeWidthInBytesOnStack(Type Ty) const override {
Andrew Scull57e12682015-09-16 11:30:19 -0700115 // Round up to the next multiple of 4 bytes. In particular, i1, i8, and i16
116 // are rounded up to 4 bytes.
Jan Voungb36ad9b2015-04-21 17:01:49 -0700117 return (typeWidthInBytes(Ty) + 3) & ~3;
118 }
David Sehre39d0ca2015-11-06 11:25:41 -0800119 uint32_t getStackAlignment() const override;
David Sehr2f3b8ec2015-11-16 16:51:39 -0800120 void reserveFixedAllocaArea(size_t Size, size_t Align) override {
John Porto614140e2015-11-23 11:43:13 -0800121 FixedAllocaSizeBytes = Size;
122 assert(llvm::isPowerOf2_32(Align));
123 FixedAllocaAlignBytes = Align;
124 PrologEmitsFixedAllocas = true;
David Sehr2f3b8ec2015-11-16 16:51:39 -0800125 }
126 int32_t getFrameFixedAllocaOffset() const override {
John Porto614140e2015-11-23 11:43:13 -0800127 return FixedAllocaSizeBytes - (SpillAreaSizeBytes - MaxOutArgsSizeBytes);
David Sehr2f3b8ec2015-11-16 16:51:39 -0800128 }
John Porto614140e2015-11-23 11:43:13 -0800129 uint32_t maxOutArgsSizeBytes() const override { return MaxOutArgsSizeBytes; }
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700130
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700131 bool shouldSplitToVariable64On32(Type Ty) const override {
132 return Ty == IceType_i64;
133 }
134
Andrew Scull87f80c12015-07-20 10:19:16 -0700135 // TODO(ascull): what size is best for ARM?
136 SizeT getMinJumpTableSize() const override { return 3; }
Andrew Scull86df4e92015-07-30 13:54:44 -0700137 void emitJumpTable(const Cfg *Func,
138 const InstJumpTable *JumpTable) const override;
Andrew Scull87f80c12015-07-20 10:19:16 -0700139
Jan Voungb36ad9b2015-04-21 17:01:49 -0700140 void emitVariable(const Variable *Var) const override;
Jan Voung76bb0be2015-05-14 09:26:19 -0700141
Jan Voung76bb0be2015-05-14 09:26:19 -0700142 void emit(const ConstantUndef *C) const final;
143 void emit(const ConstantInteger32 *C) const final;
144 void emit(const ConstantInteger64 *C) const final;
145 void emit(const ConstantFloat *C) const final;
146 void emit(const ConstantDouble *C) const final;
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800147 void emit(const ConstantRelocatable *C) const final;
Jan Voung76bb0be2015-05-14 09:26:19 -0700148
Jan Voungb36ad9b2015-04-21 17:01:49 -0700149 void lowerArguments() override;
150 void addProlog(CfgNode *Node) override;
151 void addEpilog(CfgNode *Node) override;
152
Jan Voungb3401d22015-05-18 09:38:21 -0700153 Operand *loOperand(Operand *Operand);
154 Operand *hiOperand(Operand *Operand);
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700155 void finishArgumentLowering(Variable *Arg, Variable *FramePtr,
John Porto3f6b47d2015-11-19 05:42:59 -0800156 size_t BasicFrameOffset, size_t *InArgsSizeBytes);
Jan Voungb3401d22015-05-18 09:38:21 -0700157
Jan Voung6ec369e2015-06-30 11:03:15 -0700158 bool hasCPUFeature(TargetARM32Features::ARM32InstructionSet I) const {
159 return CPUFeatures.hasFeature(I);
160 }
John Portoccea7932015-11-17 04:58:36 -0800161
162 enum OperandLegalization {
John Portoccea7932015-11-17 04:58:36 -0800163 Legal_Reg = 1 << 0, /// physical register, not stack location
164 Legal_Flex = 1 << 1, /// A flexible operand2, which can hold rotated small
165 /// immediates, shifted registers, or modified fp imm.
166 Legal_Mem = 1 << 2, /// includes [r0, r1 lsl #2] as well as [sp, #12]
John Porto866b6b12015-12-03 09:45:31 -0800167 Legal_Rematerializable = 1 << 3,
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800168 Legal_Default = ~Legal_Rematerializable,
John Portoccea7932015-11-17 04:58:36 -0800169 };
170
171 using LegalMask = uint32_t;
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800172 Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT());
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800173 Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800174 RegNumT RegNum = RegNumT());
175 Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT());
John Portoccea7932015-11-17 04:58:36 -0800176
John Porto2758bb02015-11-17 14:31:25 -0800177 OperandARM32ShAmtImm *shAmtImm(uint32_t ShAmtImm) const {
178 assert(ShAmtImm < 32);
179 return OperandARM32ShAmtImm::create(
180 Func,
181 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(ShAmtImm & 0x1F)));
182 }
183
John Portoccea7932015-11-17 04:58:36 -0800184 GlobalContext *getCtx() const { return Ctx; }
Jan Voungd062f732015-06-15 17:17:31 -0700185
Jan Voungb36ad9b2015-04-21 17:01:49 -0700186protected:
187 explicit TargetARM32(Cfg *Func);
188
189 void postLower() override;
190
John Porto7b3d9cb2015-11-11 14:26:57 -0800191 enum SafeBoolChain {
192 SBC_No,
193 SBC_Yes,
194 };
195
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800196 void lowerAlloca(const InstAlloca *Instr) override;
197 SafeBoolChain lowerInt1Arithmetic(const InstArithmetic *Instr);
John Portoccea7932015-11-17 04:58:36 -0800198 void lowerInt64Arithmetic(InstArithmetic::OpKind Op, Variable *Dest,
199 Operand *Src0, Operand *Src1);
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800200 void lowerArithmetic(const InstArithmetic *Instr) override;
201 void lowerAssign(const InstAssign *Instr) override;
202 void lowerBr(const InstBr *Instr) override;
203 void lowerCall(const InstCall *Instr) override;
204 void lowerCast(const InstCast *Instr) override;
205 void lowerExtractElement(const InstExtractElement *Instr) override;
John Porto7b3d9cb2015-11-11 14:26:57 -0800206
207 /// CondWhenTrue is a helper type returned by every method in the lowering
208 /// that emits code to set the condition codes.
209 class CondWhenTrue {
210 public:
211 explicit CondWhenTrue(CondARM32::Cond T0,
212 CondARM32::Cond T1 = CondARM32::kNone)
213 : WhenTrue0(T0), WhenTrue1(T1) {
214 assert(T1 == CondARM32::kNone || T0 != CondARM32::kNone);
215 assert(T1 != T0 || T0 == CondARM32::kNone);
216 }
217 CondARM32::Cond WhenTrue0;
218 CondARM32::Cond WhenTrue1;
219
220 /// invert returns a new object with WhenTrue0 and WhenTrue1 inverted.
221 CondWhenTrue invert() const {
222 switch (WhenTrue0) {
223 default:
224 if (WhenTrue1 == CondARM32::kNone)
225 return CondWhenTrue(InstARM32::getOppositeCondition(WhenTrue0));
226 return CondWhenTrue(InstARM32::getOppositeCondition(WhenTrue0),
227 InstARM32::getOppositeCondition(WhenTrue1));
228 case CondARM32::AL:
229 return CondWhenTrue(CondARM32::kNone);
230 case CondARM32::kNone:
231 return CondWhenTrue(CondARM32::AL);
232 }
233 }
234 };
235
236 CondWhenTrue lowerFcmpCond(const InstFcmp *Instr);
John Porto4a5e6d02015-11-04 09:32:55 -0800237 void lowerFcmp(const InstFcmp *Instr) override;
John Portoccea7932015-11-17 04:58:36 -0800238 CondWhenTrue lowerInt8AndInt16IcmpCond(InstIcmp::ICond Condition,
239 Operand *Src0, Operand *Src1);
240 CondWhenTrue lowerInt32IcmpCond(InstIcmp::ICond Condition, Operand *Src0,
241 Operand *Src1);
242 CondWhenTrue lowerInt64IcmpCond(InstIcmp::ICond Condition, Operand *Src0,
243 Operand *Src1);
John Porto4b6e4b42016-02-17 05:00:59 -0800244 CondWhenTrue lowerIcmpCond(InstIcmp::ICond Condition, Operand *Src0,
245 Operand *Src1);
John Porto7b3d9cb2015-11-11 14:26:57 -0800246 CondWhenTrue lowerIcmpCond(const InstIcmp *Instr);
John Porto4a5e6d02015-11-04 09:32:55 -0800247 void lowerIcmp(const InstIcmp *Instr) override;
John Porto4b6e4b42016-02-17 05:00:59 -0800248 /// Emits the basic sequence for lower-linked/store-exclusive loops:
249 ///
250 /// retry:
251 /// ldrex tmp, [Addr]
252 /// StoreValue = Operation(tmp)
253 /// strexCond success, StoreValue, [Addr]
254 /// cmpCond success, #0
255 /// bne retry
256 ///
257 /// Operation needs to return which value to strex in Addr, it must not change
258 /// the flags if Cond is not AL, and must not emit any instructions that could
259 /// end up writing to memory. Operation also needs to handle fake-defing for
260 /// i64 handling.
261 void
262 lowerLoadLinkedStoreExclusive(Type Ty, Operand *Addr,
263 std::function<Variable *(Variable *)> Operation,
264 CondARM32::Cond Cond = CondARM32::AL);
265 void lowerInt64AtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr,
266 Operand *Val);
John Porto578f1162015-10-06 06:54:42 -0700267 void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr,
268 Operand *Val);
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800269 void lowerIntrinsicCall(const InstIntrinsicCall *Instr) override;
270 void lowerInsertElement(const InstInsertElement *Instr) override;
271 void lowerLoad(const InstLoad *Instr) override;
272 void lowerPhi(const InstPhi *Instr) override;
273 void lowerRet(const InstRet *Instr) override;
274 void lowerSelect(const InstSelect *Instr) override;
275 void lowerStore(const InstStore *Instr) override;
276 void lowerSwitch(const InstSwitch *Instr) override;
277 void lowerUnreachable(const InstUnreachable *Instr) override;
Jan Voungb36ad9b2015-04-21 17:01:49 -0700278 void prelowerPhis() override;
John Portof4198542015-11-20 14:17:23 -0800279 uint32_t getCallStackArgumentsSizeBytes(const InstCall *Instr) override;
John Portoc39ec102015-12-01 13:00:43 -0800280 void genTargetHelperCallFor(Inst *Instr) override;
Jan Voungb36ad9b2015-04-21 17:01:49 -0700281 void doAddressOptLoad() override;
282 void doAddressOptStore() override;
Qining Luaee5fa82015-08-20 14:59:03 -0700283 void randomlyInsertNop(float Probability,
284 RandomNumberGenerator &RNG) override;
Jan Voungb3401d22015-05-18 09:38:21 -0700285
Jan Voungbefd03a2015-06-02 11:03:03 -0700286 OperandARM32Mem *formMemoryOperand(Operand *Ptr, Type Ty);
Jan Voungb3401d22015-05-18 09:38:21 -0700287
John Porto578f1162015-10-06 06:54:42 -0700288 Variable64On32 *makeI64RegPair();
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800289 Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT());
Jan Voungb3401d22015-05-18 09:38:21 -0700290 static Type stackSlotType();
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800291 Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT());
John Porto614140e2015-11-23 11:43:13 -0800292 void alignRegisterPow2(Variable *Reg, uint32_t Align,
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800293 RegNumT TmpRegNum = RegNumT());
Jan Voungb3401d22015-05-18 09:38:21 -0700294
Andrew Scull9612d322015-07-06 14:53:25 -0700295 /// Returns a vector in a register with the given constant entries.
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800296 Variable *makeVectorOfZeros(Type Ty, RegNumT RegNum = RegNumT());
Jan Voungb3401d22015-05-18 09:38:21 -0700297
Qining Luaee5fa82015-08-20 14:59:03 -0700298 void
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800299 makeRandomRegisterPermutation(llvm::SmallVectorImpl<RegNumT> &Permutation,
John Portoe82b5602016-02-24 15:58:55 -0800300 const SmallBitVector &ExcludeRegisters,
Qining Luaee5fa82015-08-20 14:59:03 -0700301 uint64_t Salt) const override;
Jan Voungb36ad9b2015-04-21 17:01:49 -0700302
Andrew Scull57e12682015-09-16 11:30:19 -0700303 // If a divide-by-zero check is needed, inserts a: test; branch .LSKIP; trap;
304 // .LSKIP: <continuation>. If no check is needed nothing is inserted.
Jan Voung6ec369e2015-06-30 11:03:15 -0700305 void div0Check(Type Ty, Operand *SrcLo, Operand *SrcHi);
Andrew Scull8072bae2015-09-14 16:01:26 -0700306 using ExtInstr = void (TargetARM32::*)(Variable *, Variable *,
307 CondARM32::Cond);
308 using DivInstr = void (TargetARM32::*)(Variable *, Variable *, Variable *,
309 CondARM32::Cond);
Jan Voung6ec369e2015-06-30 11:03:15 -0700310 void lowerIDivRem(Variable *Dest, Variable *T, Variable *Src0R, Operand *Src1,
John Portoc39ec102015-12-01 13:00:43 -0800311 ExtInstr ExtFunc, DivInstr DivFunc, bool IsRemainder);
Jan Voung6ec369e2015-06-30 11:03:15 -0700312
Jan Voungf645d852015-07-09 10:35:09 -0700313 void lowerCLZ(Variable *Dest, Variable *ValLo, Variable *ValHi);
314
Andrew Scull57e12682015-09-16 11:30:19 -0700315 // The following are helpers that insert lowered ARM32 instructions with
316 // minimal syntactic overhead, so that the lowering code can look as close to
317 // assembly as practical.
Jan Voung3bfd99a2015-05-22 16:35:25 -0700318 void _add(Variable *Dest, Variable *Src0, Operand *Src1,
319 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800320 Context.insert<InstARM32Add>(Dest, Src0, Src1, Pred);
Jan Voung29719972015-05-19 11:24:51 -0700321 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700322 void _adds(Variable *Dest, Variable *Src0, Operand *Src1,
323 CondARM32::Cond Pred = CondARM32::AL) {
Jan Voung86ebec12015-08-09 07:58:35 -0700324 constexpr bool SetFlags = true;
John Porto1d937a82015-12-17 06:19:34 -0800325 Context.insert<InstARM32Add>(Dest, Src0, Src1, Pred, SetFlags);
Jan Voung29719972015-05-19 11:24:51 -0700326 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700327 void _adc(Variable *Dest, Variable *Src0, Operand *Src1,
328 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800329 Context.insert<InstARM32Adc>(Dest, Src0, Src1, Pred);
Jan Voung29719972015-05-19 11:24:51 -0700330 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700331 void _and(Variable *Dest, Variable *Src0, Operand *Src1,
332 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800333 Context.insert<InstARM32And>(Dest, Src0, Src1, Pred);
Jan Voung29719972015-05-19 11:24:51 -0700334 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700335 void _asr(Variable *Dest, Variable *Src0, Operand *Src1,
336 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800337 Context.insert<InstARM32Asr>(Dest, Src0, Src1, Pred);
Jan Voung66c3d5e2015-06-04 17:02:31 -0700338 }
Jan Voung55500db2015-05-26 14:25:40 -0700339 void _bic(Variable *Dest, Variable *Src0, Operand *Src1,
340 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800341 Context.insert<InstARM32Bic>(Dest, Src0, Src1, Pred);
Jan Voung55500db2015-05-26 14:25:40 -0700342 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700343 void _br(CfgNode *TargetTrue, CfgNode *TargetFalse,
344 CondARM32::Cond Condition) {
John Porto1d937a82015-12-17 06:19:34 -0800345 Context.insert<InstARM32Br>(TargetTrue, TargetFalse, Condition);
Jan Voung29719972015-05-19 11:24:51 -0700346 }
John Porto1d937a82015-12-17 06:19:34 -0800347 void _br(CfgNode *Target) { Context.insert<InstARM32Br>(Target); }
Andrew Scullfdc54db2015-06-29 11:21:18 -0700348 void _br(CfgNode *Target, CondARM32::Cond Condition) {
John Porto1d937a82015-12-17 06:19:34 -0800349 Context.insert<InstARM32Br>(Target, Condition);
Andrew Scullfdc54db2015-06-29 11:21:18 -0700350 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700351 void _br(InstARM32Label *Label, CondARM32::Cond Condition) {
John Porto1d937a82015-12-17 06:19:34 -0800352 Context.insert<InstARM32Br>(Label, Condition);
Jan Voung6ec369e2015-06-30 11:03:15 -0700353 }
John Portoccea7932015-11-17 04:58:36 -0800354 void _cmn(Variable *Src0, Operand *Src1,
355 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800356 Context.insert<InstARM32Cmn>(Src0, Src1, Pred);
John Portoccea7932015-11-17 04:58:36 -0800357 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700358 void _cmp(Variable *Src0, Operand *Src1,
359 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800360 Context.insert<InstARM32Cmp>(Src0, Src1, Pred);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700361 }
Jan Voungf645d852015-07-09 10:35:09 -0700362 void _clz(Variable *Dest, Variable *Src0,
363 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800364 Context.insert<InstARM32Clz>(Dest, Src0, Pred);
Jan Voungf645d852015-07-09 10:35:09 -0700365 }
John Porto1d937a82015-12-17 06:19:34 -0800366 void _dmb() { Context.insert<InstARM32Dmb>(); }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700367 void _eor(Variable *Dest, Variable *Src0, Operand *Src1,
368 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800369 Context.insert<InstARM32Eor>(Dest, Src0, Src1, Pred);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700370 }
John Portoba6a67c2015-09-25 15:19:45 -0700371 /// _ldr, for all your memory to Variable data moves. It handles all types
372 /// (integer, floating point, and vectors.) Addr needs to be valid for Dest's
373 /// type (e.g., no immediates for vector loads, and no index registers for fp
374 /// loads.)
Jan Voung3bfd99a2015-05-22 16:35:25 -0700375 void _ldr(Variable *Dest, OperandARM32Mem *Addr,
376 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800377 Context.insert<InstARM32Ldr>(Dest, Addr, Pred);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700378 }
John Porto4b6e4b42016-02-17 05:00:59 -0800379 InstARM32Ldrex *_ldrex(Variable *Dest, OperandARM32Mem *Addr,
380 CondARM32::Cond Pred = CondARM32::AL) {
381 auto *Ldrex = Context.insert<InstARM32Ldrex>(Dest, Addr, Pred);
Jim Stichnothb36757e2015-10-05 13:55:11 -0700382 if (auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest)) {
John Porto1d937a82015-12-17 06:19:34 -0800383 Context.insert<InstFakeDef>(Dest64->getLo(), Dest);
384 Context.insert<InstFakeDef>(Dest64->getHi(), Dest);
Jim Stichnothb36757e2015-10-05 13:55:11 -0700385 }
John Porto4b6e4b42016-02-17 05:00:59 -0800386 return Ldrex;
Jim Stichnothb36757e2015-10-05 13:55:11 -0700387 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700388 void _lsl(Variable *Dest, Variable *Src0, Operand *Src1,
389 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800390 Context.insert<InstARM32Lsl>(Dest, Src0, Src1, Pred);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700391 }
John Portoccea7932015-11-17 04:58:36 -0800392 void _lsls(Variable *Dest, Variable *Src0, Operand *Src1,
393 CondARM32::Cond Pred = CondARM32::AL) {
394 constexpr bool SetFlags = true;
John Porto1d937a82015-12-17 06:19:34 -0800395 Context.insert<InstARM32Lsl>(Dest, Src0, Src1, Pred, SetFlags);
John Portoccea7932015-11-17 04:58:36 -0800396 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700397 void _lsr(Variable *Dest, Variable *Src0, Operand *Src1,
398 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800399 Context.insert<InstARM32Lsr>(Dest, Src0, Src1, Pred);
Jan Voung66c3d5e2015-06-04 17:02:31 -0700400 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700401 void _mla(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc,
402 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800403 Context.insert<InstARM32Mla>(Dest, Src0, Src1, Acc, Pred);
Jan Voung29719972015-05-19 11:24:51 -0700404 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700405 void _mls(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc,
406 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800407 Context.insert<InstARM32Mls>(Dest, Src0, Src1, Acc, Pred);
Jan Voung6ec369e2015-06-30 11:03:15 -0700408 }
John Portoba6a67c2015-09-25 15:19:45 -0700409 /// _mov, for all your Variable to Variable data movement needs. It handles
410 /// all types (integer, floating point, and vectors), as well as moves between
411 /// Core and VFP registers. This is not a panacea: you must obey the (weird,
412 /// confusing, non-uniform) rules for data moves in ARM.
413 void _mov(Variable *Dest, Operand *Src0,
414 CondARM32::Cond Pred = CondARM32::AL) {
415 // _mov used to be unique in the sense that it would create a temporary
416 // automagically if Dest was nullptr. It won't do that anymore, so we keep
417 // an assert around just in case there is some untested code path where Dest
418 // is nullptr.
419 assert(Dest != nullptr);
John Porto3f6b47d2015-11-19 05:42:59 -0800420 assert(!llvm::isa<OperandARM32Mem>(Src0));
John Porto1d937a82015-12-17 06:19:34 -0800421 auto *Instr = Context.insert<InstARM32Mov>(Dest, Src0, Pred);
John Portoe0b829f2015-09-28 09:50:48 -0700422
John Portoe0b829f2015-09-28 09:50:48 -0700423 if (Instr->isMultiDest()) {
424 // If Instr is multi-dest, then Dest must be a Variable64On32. We add a
425 // fake-def for Instr.DestHi here.
426 assert(llvm::isa<Variable64On32>(Dest));
John Porto1d937a82015-12-17 06:19:34 -0800427 Context.insert<InstFakeDef>(Instr->getDestHi());
John Portoe0b829f2015-09-28 09:50:48 -0700428 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700429 }
John Porto578f1162015-10-06 06:54:42 -0700430
Jim Stichnoth230d41012015-09-25 17:40:32 -0700431 void _mov_redefined(Variable *Dest, Operand *Src0,
432 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800433 auto *Instr = Context.insert<InstARM32Mov>(Dest, Src0, Pred);
John Portoe0b829f2015-09-28 09:50:48 -0700434 Instr->setDestRedefined();
John Portoe0b829f2015-09-28 09:50:48 -0700435 if (Instr->isMultiDest()) {
436 // If Instr is multi-dest, then Dest must be a Variable64On32. We add a
437 // fake-def for Instr.DestHi here.
438 assert(llvm::isa<Variable64On32>(Dest));
John Porto1d937a82015-12-17 06:19:34 -0800439 Context.insert<InstFakeDef>(Instr->getDestHi());
John Portoe0b829f2015-09-28 09:50:48 -0700440 }
Jan Voungb3401d22015-05-18 09:38:21 -0700441 }
John Porto4a5e6d02015-11-04 09:32:55 -0800442
Karl Schimpff084a572016-02-09 13:09:23 -0800443 void _nop() { Context.insert<InstARM32Nop>(); }
444
Eric Holk658bae22016-02-08 15:22:18 -0800445 // Generates a vmov instruction to extract the given index from a vector
446 // register.
447 void _extractelement(Variable *Dest, Variable *Src0, uint32_t Index,
448 CondARM32::Cond Pred = CondARM32::AL) {
449 Context.insert<InstARM32Extract>(Dest, Src0, Index, Pred);
450 }
451
452 // Generates a vmov instruction to insert a value into the given index of a
453 // vector register.
454 void _insertelement(Variable *Dest, Variable *Src0, uint32_t Index,
455 CondARM32::Cond Pred = CondARM32::AL) {
456 Context.insert<InstARM32Insert>(Dest, Src0, Index, Pred);
457 }
458
John Porto7b3d9cb2015-11-11 14:26:57 -0800459 // --------------------------------------------------------------------------
460 // Begin bool folding machinery.
461 //
462 // There are three types of boolean lowerings handled by this target:
463 //
464 // 1) Boolean expressions leading to a boolean Variable definition
465 // ---------------------------------------------------------------
466 //
467 // Whenever a i1 Variable is live out (i.e., its live range extends beyond
468 // the defining basic block) we do not fold the operation. We instead
469 // materialize (i.e., compute) the variable normally, so that it can be used
470 // when needed. We also materialize i1 values that are not single use to
471 // avoid code duplication. These expressions are not short circuited.
472 //
473 // 2) Boolean expressions leading to a select
474 // ------------------------------------------
475 //
476 // These include boolean chains leading to a select instruction, as well as
477 // i1 Sexts. These boolean expressions are lowered to:
478 //
479 // mov T, <false value>
480 // CC <- eval(Boolean Expression)
481 // movCC T, <true value>
482 //
483 // For Sexts, <false value> is 0, and <true value> is -1.
484 //
485 // 3) Boolean expressions leading to a br i1
486 // -----------------------------------------
487 //
488 // These are the boolean chains leading to a branch. These chains are
489 // short-circuited, i.e.:
490 //
491 // A = or i1 B, C
492 // br i1 A, label %T, label %F
493 //
494 // becomes
495 //
496 // tst B
497 // jne %T
498 // tst B
499 // jne %T
500 // j %F
501 //
502 // and
503 //
504 // A = and i1 B, C
505 // br i1 A, label %T, label %F
506 //
507 // becomes
508 //
509 // tst B
510 // jeq %F
511 // tst B
512 // jeq %F
513 // j %T
514 //
515 // Arbitrarily long chains are short circuited, e.g
516 //
517 // A = or i1 B, C
518 // D = and i1 A, E
519 // F = and i1 G, H
520 // I = or i1 D, F
521 // br i1 I, label %True, label %False
522 //
523 // becomes
524 //
525 // Label[A]:
526 // tst B, 1
527 // bne Label[D]
528 // tst C, 1
529 // beq Label[I]
530 // Label[D]:
531 // tst E, 1
532 // bne %True
533 // Label[I]
534 // tst G, 1
535 // beq %False
536 // tst H, 1
537 // beq %False (bne %True)
John Porto4a5e6d02015-11-04 09:32:55 -0800538
John Porto7b3d9cb2015-11-11 14:26:57 -0800539 /// lowerInt1 materializes Boolean to a Variable.
540 SafeBoolChain lowerInt1(Variable *Dest, Operand *Boolean);
John Porto4a5e6d02015-11-04 09:32:55 -0800541
John Porto7b3d9cb2015-11-11 14:26:57 -0800542 /// lowerInt1ForSelect generates the following instruction sequence:
543 ///
544 /// mov T, FalseValue
545 /// CC <- eval(Boolean)
546 /// movCC T, TrueValue
547 /// mov Dest, T
548 ///
549 /// It is used for lowering select i1, as well as i1 Sext.
550 void lowerInt1ForSelect(Variable *Dest, Operand *Boolean, Operand *TrueValue,
551 Operand *FalseValue);
552
553 /// LowerInt1BranchTarget is used by lowerIntForBranch. It wraps a CfgNode, or
554 /// an InstARM32Label (but never both) so that, during br i1 lowering, we can
555 /// create auxiliary labels for short circuiting the condition evaluation.
556 class LowerInt1BranchTarget {
557 public:
558 explicit LowerInt1BranchTarget(CfgNode *const Target)
559 : NodeTarget(Target) {}
560 explicit LowerInt1BranchTarget(InstARM32Label *const Target)
561 : LabelTarget(Target) {}
562
563 /// createForLabelOrDuplicate will return a new LowerInt1BranchTarget that
564 /// is the exact copy of this if Label is nullptr; otherwise, the returned
565 /// object will wrap Label instead.
566 LowerInt1BranchTarget
567 createForLabelOrDuplicate(InstARM32Label *Label) const {
568 if (Label != nullptr)
569 return LowerInt1BranchTarget(Label);
570 if (NodeTarget)
571 return LowerInt1BranchTarget(NodeTarget);
572 return LowerInt1BranchTarget(LabelTarget);
John Porto4a5e6d02015-11-04 09:32:55 -0800573 }
574
John Porto7b3d9cb2015-11-11 14:26:57 -0800575 CfgNode *const NodeTarget = nullptr;
576 InstARM32Label *const LabelTarget = nullptr;
577 };
John Porto4a5e6d02015-11-04 09:32:55 -0800578
John Porto7b3d9cb2015-11-11 14:26:57 -0800579 /// LowerInt1AllowShortCircuit is a helper type used by lowerInt1ForBranch for
580 /// determining which type arithmetic is allowed to be short circuited. This
581 /// is useful for lowering
582 ///
583 /// t1 = and i1 A, B
584 /// t2 = and i1 t1, C
585 /// br i1 t2, label %False, label %True
586 ///
587 /// to
588 ///
589 /// tst A, 1
590 /// beq %False
591 /// tst B, 1
592 /// beq %False
593 /// tst C, 1
594 /// bne %True
595 /// b %False
596 ///
597 /// Without this information, short circuiting would only allow to short
598 /// circuit a single high level instruction. For example:
599 ///
600 /// t1 = or i1 A, B
601 /// t2 = and i1 t1, C
602 /// br i1 t2, label %False, label %True
603 ///
604 /// cannot be lowered to
605 ///
606 /// tst A, 1
607 /// bne %True
608 /// tst B, 1
609 /// bne %True
610 /// tst C, 1
611 /// beq %True
612 /// b %False
613 ///
614 /// It needs to be lowered to
615 ///
616 /// tst A, 1
617 /// bne Aux
618 /// tst B, 1
619 /// beq %False
620 /// Aux:
621 /// tst C, 1
622 /// bne %True
623 /// b %False
624 ///
625 /// TODO(jpp): evaluate if this kind of short circuiting hurts performance (it
626 /// might.)
627 enum LowerInt1AllowShortCircuit {
628 SC_And = 1,
629 SC_Or = 2,
630 SC_All = SC_And | SC_Or,
631 };
John Porto4a5e6d02015-11-04 09:32:55 -0800632
John Porto7b3d9cb2015-11-11 14:26:57 -0800633 /// ShortCircuitCondAndLabel wraps the condition codes that should be used
634 /// after a lowerInt1ForBranch returns to branch to the
635 /// TrueTarget/FalseTarget. If ShortCircuitLabel is not nullptr, then the
636 /// called lowerInt1forBranch created an internal (i.e., short-circuit) label
637 /// used for short circuiting.
638 class ShortCircuitCondAndLabel {
639 public:
640 explicit ShortCircuitCondAndLabel(CondWhenTrue &&C,
641 InstARM32Label *L = nullptr)
642 : Cond(std::move(C)), ShortCircuitTarget(L) {}
643 const CondWhenTrue Cond;
644 InstARM32Label *const ShortCircuitTarget;
John Porto4a5e6d02015-11-04 09:32:55 -0800645
John Porto7b3d9cb2015-11-11 14:26:57 -0800646 CondWhenTrue assertNoLabelAndReturnCond() const {
647 assert(ShortCircuitTarget == nullptr);
648 return Cond;
John Porto4a5e6d02015-11-04 09:32:55 -0800649 }
John Porto7b3d9cb2015-11-11 14:26:57 -0800650 };
John Porto4a5e6d02015-11-04 09:32:55 -0800651
John Porto7b3d9cb2015-11-11 14:26:57 -0800652 /// lowerInt1ForBranch expands Boolean, and returns the condition codes that
653 /// are to be used for branching to the branch's TrueTarget. It may return a
654 /// label that the expansion of Boolean used to short circuit the chain's
655 /// evaluation.
656 ShortCircuitCondAndLabel
657 lowerInt1ForBranch(Operand *Boolean, const LowerInt1BranchTarget &TargetTrue,
658 const LowerInt1BranchTarget &TargetFalse,
659 uint32_t ShortCircuitable);
660
661 // _br is a convenience wrapper that emits br instructions to Target.
662 void _br(const LowerInt1BranchTarget &BrTarget,
663 CondARM32::Cond Cond = CondARM32::AL) {
664 assert((BrTarget.NodeTarget == nullptr) !=
665 (BrTarget.LabelTarget == nullptr));
666 if (BrTarget.NodeTarget != nullptr)
667 _br(BrTarget.NodeTarget, Cond);
668 else
669 _br(BrTarget.LabelTarget, Cond);
670 }
671
672 // _br_short_circuit is used when lowering InstArithmetic::And and
673 // InstArithmetic::Or and a short circuit branch is needed.
674 void _br_short_circuit(const LowerInt1BranchTarget &Target,
675 const CondWhenTrue &Cond) {
676 if (Cond.WhenTrue1 != CondARM32::kNone) {
677 _br(Target, Cond.WhenTrue1);
678 }
679 if (Cond.WhenTrue0 != CondARM32::kNone) {
680 _br(Target, Cond.WhenTrue0);
John Porto4a5e6d02015-11-04 09:32:55 -0800681 }
682 }
John Porto7b3d9cb2015-11-11 14:26:57 -0800683 // End of bool folding machinery
684 // --------------------------------------------------------------------------
John Porto4a5e6d02015-11-04 09:32:55 -0800685
Andrew Scull57e12682015-09-16 11:30:19 -0700686 /// The Operand can only be a 16-bit immediate or a ConstantRelocatable (with
687 /// an upper16 relocation).
Jan Voung3bfd99a2015-05-22 16:35:25 -0700688 void _movt(Variable *Dest, Operand *Src0,
689 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800690 Context.insert<InstARM32Movt>(Dest, Src0, Pred);
Jan Voungb3401d22015-05-18 09:38:21 -0700691 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700692 void _movw(Variable *Dest, Operand *Src0,
693 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800694 Context.insert<InstARM32Movw>(Dest, Src0, Pred);
Jan Voungb3401d22015-05-18 09:38:21 -0700695 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700696 void _mul(Variable *Dest, Variable *Src0, Variable *Src1,
697 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800698 Context.insert<InstARM32Mul>(Dest, Src0, Src1, Pred);
Jan Voung29719972015-05-19 11:24:51 -0700699 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700700 void _mvn(Variable *Dest, Operand *Src0,
701 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800702 Context.insert<InstARM32Mvn>(Dest, Src0, Pred);
Jan Voungb3401d22015-05-18 09:38:21 -0700703 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700704 void _orr(Variable *Dest, Variable *Src0, Operand *Src1,
705 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800706 Context.insert<InstARM32Orr>(Dest, Src0, Src1, Pred);
Jan Voung29719972015-05-19 11:24:51 -0700707 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700708 void _orrs(Variable *Dest, Variable *Src0, Operand *Src1,
709 CondARM32::Cond Pred = CondARM32::AL) {
Jan Voung86ebec12015-08-09 07:58:35 -0700710 constexpr bool SetFlags = true;
John Porto1d937a82015-12-17 06:19:34 -0800711 Context.insert<InstARM32Orr>(Dest, Src0, Src1, Pred, SetFlags);
Jan Voung6ec369e2015-06-30 11:03:15 -0700712 }
John Porto1d937a82015-12-17 06:19:34 -0800713 void _push(const VarList &Sources) { Context.insert<InstARM32Push>(Sources); }
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700714 void _pop(const VarList &Dests) {
John Porto1d937a82015-12-17 06:19:34 -0800715 Context.insert<InstARM32Pop>(Dests);
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700716 // Mark dests as modified.
717 for (Variable *Dest : Dests)
John Porto1d937a82015-12-17 06:19:34 -0800718 Context.insert<InstFakeDef>(Dest);
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700719 }
Jan Voungf645d852015-07-09 10:35:09 -0700720 void _rbit(Variable *Dest, Variable *Src0,
721 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800722 Context.insert<InstARM32Rbit>(Dest, Src0, Pred);
Jan Voungf645d852015-07-09 10:35:09 -0700723 }
724 void _rev(Variable *Dest, Variable *Src0,
725 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800726 Context.insert<InstARM32Rev>(Dest, Src0, Pred);
Jan Voungf645d852015-07-09 10:35:09 -0700727 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700728 void _ret(Variable *LR, Variable *Src0 = nullptr) {
John Porto1d937a82015-12-17 06:19:34 -0800729 Context.insert<InstARM32Ret>(LR, Src0);
Jan Voung6ec369e2015-06-30 11:03:15 -0700730 }
John Portoccea7932015-11-17 04:58:36 -0800731 void _rscs(Variable *Dest, Variable *Src0, Operand *Src1,
732 CondARM32::Cond Pred = CondARM32::AL) {
733 constexpr bool SetFlags = true;
John Porto1d937a82015-12-17 06:19:34 -0800734 Context.insert<InstARM32Rsc>(Dest, Src0, Src1, Pred, SetFlags);
John Portoccea7932015-11-17 04:58:36 -0800735 }
736 void _rsc(Variable *Dest, Variable *Src0, Operand *Src1,
737 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800738 Context.insert<InstARM32Rsc>(Dest, Src0, Src1, Pred);
John Portoccea7932015-11-17 04:58:36 -0800739 }
740 void _rsbs(Variable *Dest, Variable *Src0, Operand *Src1,
741 CondARM32::Cond Pred = CondARM32::AL) {
742 constexpr bool SetFlags = true;
John Porto1d937a82015-12-17 06:19:34 -0800743 Context.insert<InstARM32Rsb>(Dest, Src0, Src1, Pred, SetFlags);
John Portoccea7932015-11-17 04:58:36 -0800744 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700745 void _rsb(Variable *Dest, Variable *Src0, Operand *Src1,
746 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800747 Context.insert<InstARM32Rsb>(Dest, Src0, Src1, Pred);
Jan Voung66c3d5e2015-06-04 17:02:31 -0700748 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700749 void _sbc(Variable *Dest, Variable *Src0, Operand *Src1,
750 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800751 Context.insert<InstARM32Sbc>(Dest, Src0, Src1, Pred);
Jan Voung29719972015-05-19 11:24:51 -0700752 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700753 void _sbcs(Variable *Dest, Variable *Src0, Operand *Src1,
754 CondARM32::Cond Pred = CondARM32::AL) {
Jan Voung86ebec12015-08-09 07:58:35 -0700755 constexpr bool SetFlags = true;
John Porto1d937a82015-12-17 06:19:34 -0800756 Context.insert<InstARM32Sbc>(Dest, Src0, Src1, Pred, SetFlags);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700757 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700758 void _sdiv(Variable *Dest, Variable *Src0, Variable *Src1,
759 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800760 Context.insert<InstARM32Sdiv>(Dest, Src0, Src1, Pred);
Jan Voung6ec369e2015-06-30 11:03:15 -0700761 }
John Portoba6a67c2015-09-25 15:19:45 -0700762 /// _str, for all your Variable to memory transfers. Addr has the same
763 /// restrictions that it does in _ldr.
Jan Voungbefd03a2015-06-02 11:03:03 -0700764 void _str(Variable *Value, OperandARM32Mem *Addr,
765 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800766 Context.insert<InstARM32Str>(Value, Addr, Pred);
Jan Voungbefd03a2015-06-02 11:03:03 -0700767 }
John Porto16991842015-10-01 15:11:23 -0700768 void _strex(Variable *Dest, Variable *Value, OperandARM32Mem *Addr,
769 CondARM32::Cond Pred = CondARM32::AL) {
John Porto578f1162015-10-06 06:54:42 -0700770 // strex requires Dest to be a register other than Value or Addr. This
771 // restriction is cleanly represented by adding an "early" definition of
772 // Dest (or a latter use of all the sources.)
John Porto1d937a82015-12-17 06:19:34 -0800773 Context.insert<InstFakeDef>(Dest);
John Porto16991842015-10-01 15:11:23 -0700774 if (auto *Value64 = llvm::dyn_cast<Variable64On32>(Value)) {
John Porto1d937a82015-12-17 06:19:34 -0800775 Context.insert<InstFakeUse>(Value64->getLo());
776 Context.insert<InstFakeUse>(Value64->getHi());
John Porto16991842015-10-01 15:11:23 -0700777 }
John Porto1d937a82015-12-17 06:19:34 -0800778 auto *Instr = Context.insert<InstARM32Strex>(Dest, Value, Addr, Pred);
John Porto578f1162015-10-06 06:54:42 -0700779 Instr->setDestRedefined();
John Porto16991842015-10-01 15:11:23 -0700780 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700781 void _sub(Variable *Dest, Variable *Src0, Operand *Src1,
782 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800783 Context.insert<InstARM32Sub>(Dest, Src0, Src1, Pred);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700784 }
785 void _subs(Variable *Dest, Variable *Src0, Operand *Src1,
786 CondARM32::Cond Pred = CondARM32::AL) {
Jan Voung86ebec12015-08-09 07:58:35 -0700787 constexpr bool SetFlags = true;
John Porto1d937a82015-12-17 06:19:34 -0800788 Context.insert<InstARM32Sub>(Dest, Src0, Src1, Pred, SetFlags);
Jan Voung29719972015-05-19 11:24:51 -0700789 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700790 void _sxt(Variable *Dest, Variable *Src0,
791 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800792 Context.insert<InstARM32Sxt>(Dest, Src0, Pred);
Jan Voung66c3d5e2015-06-04 17:02:31 -0700793 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700794 void _tst(Variable *Src0, Operand *Src1,
795 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800796 Context.insert<InstARM32Tst>(Src0, Src1, Pred);
Jan Voung6ec369e2015-06-30 11:03:15 -0700797 }
John Porto1d937a82015-12-17 06:19:34 -0800798 void _trap() { Context.insert<InstARM32Trap>(); }
Jan Voung6ec369e2015-06-30 11:03:15 -0700799 void _udiv(Variable *Dest, Variable *Src0, Variable *Src1,
800 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800801 Context.insert<InstARM32Udiv>(Dest, Src0, Src1, Pred);
Jan Voungb2d50842015-05-12 09:53:50 -0700802 }
Jan Voung29719972015-05-19 11:24:51 -0700803 void _umull(Variable *DestLo, Variable *DestHi, Variable *Src0,
Jan Voung3bfd99a2015-05-22 16:35:25 -0700804 Variable *Src1, CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800805 Context.insert<InstARM32Umull>(DestLo, DestHi, Src0, Src1, Pred);
Andrew Scull57e12682015-09-16 11:30:19 -0700806 // Model the modification to the second dest as a fake def. Note that the
807 // def is not predicated.
John Porto1d937a82015-12-17 06:19:34 -0800808 Context.insert<InstFakeDef>(DestHi, DestLo);
Jim Stichnoth28df6ba2016-02-05 15:43:24 -0800809 Context.insert<InstFakeUse>(DestHi);
Jan Voung29719972015-05-19 11:24:51 -0700810 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700811 void _uxt(Variable *Dest, Variable *Src0,
812 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800813 Context.insert<InstARM32Uxt>(Dest, Src0, Pred);
Jan Voung66c3d5e2015-06-04 17:02:31 -0700814 }
John Portoba6a67c2015-09-25 15:19:45 -0700815 void _vabs(Variable *Dest, Variable *Src,
816 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800817 Context.insert<InstARM32Vabs>(Dest, Src, Pred);
John Portoba6a67c2015-09-25 15:19:45 -0700818 }
Jan Voung86ebec12015-08-09 07:58:35 -0700819 void _vadd(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800820 Context.insert<InstARM32Vadd>(Dest, Src0, Src1);
Jan Voung86ebec12015-08-09 07:58:35 -0700821 }
Eric Holkb58170c2016-01-27 11:18:29 -0800822 void _vand(Variable *Dest, Variable *Src0, Variable *Src1) {
823 Context.insert<InstARM32Vand>(Dest, Src0, Src1);
824 }
John Portoc31e2ed2015-09-11 05:17:08 -0700825 void _vcvt(Variable *Dest, Variable *Src, InstARM32Vcvt::VcvtVariant Variant,
826 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800827 Context.insert<InstARM32Vcvt>(Dest, Src, Variant, Pred);
John Portoc31e2ed2015-09-11 05:17:08 -0700828 }
Jan Voung86ebec12015-08-09 07:58:35 -0700829 void _vdiv(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800830 Context.insert<InstARM32Vdiv>(Dest, Src0, Src1);
Jan Voung86ebec12015-08-09 07:58:35 -0700831 }
John Porto2f5534f2015-09-18 15:59:47 -0700832 void _vcmp(Variable *Src0, Variable *Src1,
833 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800834 Context.insert<InstARM32Vcmp>(Src0, Src1, Pred);
John Porto2f5534f2015-09-18 15:59:47 -0700835 }
John Portoccea7932015-11-17 04:58:36 -0800836 void _vcmp(Variable *Src0, OperandARM32FlexFpZero *FpZero,
837 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800838 Context.insert<InstARM32Vcmp>(Src0, FpZero, Pred);
John Portoccea7932015-11-17 04:58:36 -0800839 }
John Porto3f6b47d2015-11-19 05:42:59 -0800840 void _veor(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800841 Context.insert<InstARM32Veor>(Dest, Src0, Src1);
John Porto3f6b47d2015-11-19 05:42:59 -0800842 }
John Porto2f5534f2015-09-18 15:59:47 -0700843 void _vmrs(CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800844 Context.insert<InstARM32Vmrs>(Pred);
John Porto2f5534f2015-09-18 15:59:47 -0700845 }
John Portoeb13acc2015-12-09 05:10:58 -0800846 void _vmla(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800847 Context.insert<InstARM32Vmla>(Dest, Src0, Src1);
John Portoeb13acc2015-12-09 05:10:58 -0800848 }
849 void _vmls(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800850 Context.insert<InstARM32Vmls>(Dest, Src0, Src1);
John Portoeb13acc2015-12-09 05:10:58 -0800851 }
Jan Voung86ebec12015-08-09 07:58:35 -0700852 void _vmul(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800853 Context.insert<InstARM32Vmul>(Dest, Src0, Src1);
Jan Voung86ebec12015-08-09 07:58:35 -0700854 }
Eric Holkcad0b752016-01-27 14:56:22 -0800855 void _vorr(Variable *Dest, Variable *Src0, Variable *Src1) {
856 Context.insert<InstARM32Vorr>(Dest, Src0, Src1);
857 }
Jan Voung86ebec12015-08-09 07:58:35 -0700858 void _vsqrt(Variable *Dest, Variable *Src,
859 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800860 Context.insert<InstARM32Vsqrt>(Dest, Src, Pred);
Jan Voung86ebec12015-08-09 07:58:35 -0700861 }
862 void _vsub(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800863 Context.insert<InstARM32Vsub>(Dest, Src0, Src1);
Jan Voung86ebec12015-08-09 07:58:35 -0700864 }
Jan Voungb2d50842015-05-12 09:53:50 -0700865
John Portof4198542015-11-20 14:17:23 -0800866 // Iterates over the CFG and determines the maximum outgoing stack arguments
John Porto614140e2015-11-23 11:43:13 -0800867 // bytes. This information is later used during addProlog() to pre-allocate
John Portof4198542015-11-20 14:17:23 -0800868 // the outargs area.
869 // TODO(jpp): This could live in the Parser, if we provided a Target-specific
870 // method that the Parser could call.
871 void findMaxStackOutArgsSize();
872
John Porto866b6b12015-12-03 09:45:31 -0800873 /// Returns true if the given Offset can be represented in a Load/Store Mem
874 /// Operand.
John Portof5f02f72015-11-09 14:52:40 -0800875 bool isLegalMemOffset(Type Ty, int32_t Offset) const;
John Porto866b6b12015-12-03 09:45:31 -0800876
877 void postLowerLegalization();
878
John Portodc619252016-02-10 15:57:16 -0800879 /// Manages the GotPtr variable, which is used for Nonsfi sandboxing.
880 /// @{
881 void createGotPtr();
882 void insertGotPtrInitPlaceholder();
883 VariableDeclaration *createGotRelocation(RelocOffset *AddPcReloc);
884 void materializeGotAddr(CfgNode *Node);
885 Variable *GotPtr = nullptr;
886 // TODO(jpp): use CfgLocalAllocator.
887 /// @}
888
889 /// Manages the Gotoff relocations created during the function lowering. A
890 /// single Gotoff relocation is created for each global variable used by the
891 /// function being lowered.
892 /// @{
893 // TODO(jpp): if the same global G is used in different functions, then this
894 // method will emit one G(gotoff) relocation per function.
895 IceString createGotoffRelocation(const ConstantRelocatable *CR);
John Portoe82b5602016-02-24 15:58:55 -0800896 CfgUnorderedSet<IceString> KnownGotoffs;
John Portodc619252016-02-10 15:57:16 -0800897 /// @}
898
899 /// Loads the constant relocatable Name to Register. Then invoke Finish to
900 /// finish the relocatable lowering. Finish **must** use PC in its first
901 /// emitted instruction, or the relocatable in Register will contain the wrong
902 /// value.
903 //
904 // Lowered sequence:
905 //
906 // Movw:
907 // movw Register, #:lower16:Name - (End - Movw) - 8 .
908 // Movt:
909 // movt Register, #:upper16:Name - (End - Movt) - 8 .
910 // PC = fake-def
911 // End:
912 // Finish(PC)
913 //
914 // The -8 in movw/movt above is to account for the PC value that the first
915 // instruction emitted by Finish(PC) will read.
916 void loadNamedConstantRelocatablePIC(const IceString &Name,
917 Variable *Register,
918 std::function<void(Variable *PC)> Finish,
919 bool SuppressMangling = true);
920
John Porto52b51572015-12-05 14:16:25 -0800921 /// Sandboxer defines methods for ensuring that "dangerous" operations are
922 /// masked during sandboxed code emission. For regular, non-sandboxed code
923 /// emission, its methods are simple pass-through methods.
924 ///
925 /// The Sandboxer also emits BundleLock/BundleUnlock pseudo-instructions
926 /// in the constructor/destructor during sandboxed code emission. Therefore,
927 /// it is a bad idea to create an object of this type and "keep it around."
928 /// The recommended usage is:
929 ///
930 /// AutoSandboxing(this).<<operation>>(...);
931 ///
932 /// This usage ensures that no other instructions are inadvertently added to
933 /// the bundle.
934 class Sandboxer {
935 Sandboxer() = delete;
936 Sandboxer(const Sandboxer &) = delete;
937 Sandboxer &operator=(const Sandboxer &) = delete;
938
939 public:
940 explicit Sandboxer(
941 TargetARM32 *Target,
942 InstBundleLock::Option BundleOption = InstBundleLock::Opt_None);
943 ~Sandboxer();
944
945 /// Increments sp:
946 ///
947 /// add sp, sp, AddAmount
948 /// bic sp, sp, 0xc0000000
949 ///
950 /// (for the rationale, see the ARM 32-bit Sandbox Specification.)
951 void add_sp(Operand *AddAmount);
952
953 /// Emits code to align sp to the specified alignment:
954 ///
955 /// bic/and sp, sp, Alignment
956 /// bic, sp, sp, 0xc0000000
957 void align_sp(size_t Alignment);
958
959 /// Emits a call instruction. If CallTarget is a Variable, it emits
960 ///
961 /// bic CallTarget, CallTarget, 0xc000000f
962 /// bl CallTarget
963 ///
964 /// Otherwise, it emits
965 ///
966 /// bl CallTarget
967 ///
968 /// Note: in sandboxed code calls are always emitted in addresses 12 mod 16.
969 InstARM32Call *bl(Variable *ReturnReg, Operand *CallTarget);
970
971 /// Emits a load:
972 ///
973 /// bic rBase, rBase, 0xc0000000
974 /// ldr rDest, [rBase, #Offset]
975 ///
976 /// Exception: if rBase is r9 or sp, then the load is emitted as:
977 ///
978 /// ldr rDest, [rBase, #Offset]
979 ///
980 /// because the NaCl ARM 32-bit Sandbox Specification guarantees they are
981 /// always valid.
982 void ldr(Variable *Dest, OperandARM32Mem *Mem, CondARM32::Cond Pred);
983
984 /// Emits a load exclusive:
985 ///
986 /// bic rBase, rBase, 0xc0000000
987 /// ldrex rDest, [rBase]
988 ///
989 /// Exception: if rBase is r9 or sp, then the load is emitted as:
990 ///
991 /// ldrex rDest, [rBase]
992 ///
993 /// because the NaCl ARM 32-bit Sandbox Specification guarantees they are
994 /// always valid.
995 void ldrex(Variable *Dest, OperandARM32Mem *Mem, CondARM32::Cond Pred);
996
997 /// Resets sp to Src:
998 ///
999 /// mov sp, Src
1000 /// bic sp, sp, 0xc0000000
1001 void reset_sp(Variable *Src);
1002
1003 /// Emits code to return from a function:
1004 ///
1005 /// bic lr, lr, 0xc000000f
1006 /// bx lr
1007 void ret(Variable *RetAddr, Variable *RetValue);
1008
1009 /// Emits a store:
1010 ///
1011 /// bic rBase, rBase, 0xc0000000
1012 /// str rSrc, [rBase, #Offset]
1013 ///
1014 /// Exception: if rBase is r9 or sp, then the store is emitted as:
1015 ///
1016 /// str rDest, [rBase, #Offset]
1017 ///
1018 /// because the NaCl ARM 32-bit Sandbox Specification guarantees they are
1019 /// always valid.
1020 void str(Variable *Src, OperandARM32Mem *Mem, CondARM32::Cond Pred);
1021
1022 /// Emits a store exclusive:
1023 ///
1024 /// bic rBase, rBase, 0xc0000000
1025 /// strex rDest, rSrc, [rBase]
1026 ///
1027 /// Exception: if rBase is r9 or sp, then the store is emitted as:
1028 ///
1029 /// strex rDest, rSrc, [rBase]
1030 ///
1031 /// because the NaCl ARM 32-bit Sandbox Specification guarantees they are
1032 /// always valid.
1033 void strex(Variable *Dest, Variable *Src, OperandARM32Mem *Mem,
1034 CondARM32::Cond Pred);
1035
1036 /// Decrements sp:
1037 ///
1038 /// sub sp, sp, SubAmount
1039 /// bic sp, sp, 0xc0000000
1040 void sub_sp(Operand *SubAmount);
1041
1042 private:
John Porto3bf335f2016-01-15 11:17:55 -08001043 AutoBundle Bundler;
John Porto52b51572015-12-05 14:16:25 -08001044 TargetARM32 *Target;
1045 };
1046
John Porto866b6b12015-12-03 09:45:31 -08001047 class PostLoweringLegalizer {
1048 PostLoweringLegalizer() = delete;
1049 PostLoweringLegalizer(const PostLoweringLegalizer &) = delete;
1050 PostLoweringLegalizer &operator=(const PostLoweringLegalizer &) = delete;
1051
1052 public:
1053 explicit PostLoweringLegalizer(TargetARM32 *Target)
1054 : Target(Target), StackOrFrameReg(Target->getPhysicalRegister(
1055 Target->getFrameOrStackReg())) {}
1056
1057 void resetTempBaseIfClobberedBy(const Inst *Instr);
1058
1059 // Ensures that the TempBase register held by the this legalizer (if any) is
1060 // assigned to IP.
1061 void assertNoTempOrAssignedToIP() const {
1062 assert(TempBaseReg == nullptr ||
1063 TempBaseReg->getRegNum() == Target->getReservedTmpReg());
1064 }
1065
1066 // Legalizes Mem. if Mem.Base is a Reamaterializable variable, Mem.Offset is
1067 // fixed up.
1068 OperandARM32Mem *legalizeMemOperand(OperandARM32Mem *Mem,
1069 bool AllowOffsets = true);
1070
1071 /// Legalizes Mov if its Source (or Destination) is a spilled Variable, or
1072 /// if its Source is a Rematerializable variable (this form is used in lieu
1073 /// of lea, which is not available in ARM.)
1074 ///
1075 /// Moves to memory become store instructions, and moves from memory, loads.
1076 void legalizeMov(InstARM32Mov *Mov);
1077
1078 private:
1079 /// Creates a new Base register centered around [Base, +/- Offset].
1080 Variable *newBaseRegister(Variable *Base, int32_t Offset,
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001081 RegNumT ScratchRegNum);
John Porto866b6b12015-12-03 09:45:31 -08001082
1083 /// Creates a new, legal OperandARM32Mem for accessing Base + Offset.
1084 /// The returned mem operand is a legal operand for accessing memory that is
1085 /// of type Ty.
1086 ///
1087 /// If [Base, #Offset] is encodable, then the method returns a Mem operand
1088 /// expressing it. Otherwise,
1089 ///
1090 /// if [TempBaseReg, #Offset-TempBaseOffset] is a valid memory operand, the
1091 /// method will return that. Otherwise,
1092 ///
1093 /// a new base register ip=Base+Offset is created, and the method returns a
1094 /// memory operand expressing [ip, #0].
1095 OperandARM32Mem *createMemOperand(Type Ty, Variable *Base, int32_t Offset,
1096 bool AllowOffsets = true);
1097 TargetARM32 *const Target;
1098 Variable *const StackOrFrameReg;
1099 Variable *TempBaseReg = nullptr;
1100 int32_t TempBaseOffset = 0;
1101 };
Jan Voung28068ad2015-07-31 12:58:46 -07001102
John Porto52b51572015-12-05 14:16:25 -08001103 const bool NeedSandboxing;
Jan Voung6ec369e2015-06-30 11:03:15 -07001104 TargetARM32Features CPUFeatures;
Jim Stichnotheafb56c2015-06-22 10:35:22 -07001105 bool UsesFramePointer = false;
1106 bool NeedsStackAlignment = false;
1107 bool MaybeLeafFunc = true;
1108 size_t SpillAreaSizeBytes = 0;
John Porto614140e2015-11-23 11:43:13 -08001109 size_t FixedAllocaSizeBytes = 0;
1110 size_t FixedAllocaAlignBytes = 0;
1111 bool PrologEmitsFixedAllocas = false;
John Portof4198542015-11-20 14:17:23 -08001112 uint32_t MaxOutArgsSizeBytes = 0;
John Portobb0a5fe2015-09-04 11:23:41 -07001113 // TODO(jpp): std::array instead of array.
John Portoe82b5602016-02-24 15:58:55 -08001114 static SmallBitVector TypeToRegisterSet[RegARM32::RCARM32_NUM];
1115 static SmallBitVector TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM];
1116 static SmallBitVector RegisterAliases[RegARM32::Reg_NUM];
1117 SmallBitVector RegsUsed;
Jan Voungb36ad9b2015-04-21 17:01:49 -07001118 VarList PhysicalRegisters[IceType_NUM];
John Portoeb13acc2015-12-09 05:10:58 -08001119 VarList PreservedGPRs;
1120 VarList PreservedSRegs;
Jan Voungb36ad9b2015-04-21 17:01:49 -07001121
Andrew Scull9612d322015-07-06 14:53:25 -07001122 /// Helper class that understands the Calling Convention and register
1123 /// assignments. The first few integer type parameters can use r0-r3,
1124 /// regardless of their position relative to the floating-point/vector
John Porto385351b2015-09-16 16:11:10 -07001125 /// arguments in the argument list. Floating-point and vector arguments
1126 /// can use q0-q3 (aka d0-d7, s0-s15). For more information on the topic,
1127 /// see the ARM Architecture Procedure Calling Standards (AAPCS).
Andrew Scull9612d322015-07-06 14:53:25 -07001128 ///
John Porto385351b2015-09-16 16:11:10 -07001129 /// Technically, arguments that can start with registers but extend beyond the
1130 /// available registers can be split between the registers and the stack.
1131 /// However, this is typically for passing GPR structs by value, and PNaCl
1132 /// transforms expand this out.
1133 ///
1134 /// At (public) function entry, the stack must be 8-byte aligned.
Jan Voungb0a8c242015-06-18 15:00:14 -07001135 class CallingConv {
1136 CallingConv(const CallingConv &) = delete;
1137 CallingConv &operator=(const CallingConv &) = delete;
1138
1139 public:
John Porto2187c842015-12-16 07:48:25 -08001140 CallingConv();
Jan Voungb0a8c242015-06-18 15:00:14 -07001141 ~CallingConv() = default;
1142
John Porto2187c842015-12-16 07:48:25 -08001143 /// argInGPR returns true if there is a GPR available for the requested
1144 /// type, and false otherwise. If it returns true, Reg is set to the
1145 /// appropriate register number. Note that, when Ty == IceType_i64, Reg will
1146 /// be an I64 register pair.
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001147 bool argInGPR(Type Ty, RegNumT *Reg);
Jan Voungb0a8c242015-06-18 15:00:14 -07001148
John Porto2187c842015-12-16 07:48:25 -08001149 /// argInVFP is to floating-point/vector types what argInGPR is for integer
1150 /// types.
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001151 bool argInVFP(Type Ty, RegNumT *Reg);
Jan Voungb0a8c242015-06-18 15:00:14 -07001152
1153 private:
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001154 void discardUnavailableGPRsAndTheirAliases(CfgVector<RegNumT> *Regs);
John Portoe82b5602016-02-24 15:58:55 -08001155 SmallBitVector GPRegsUsed;
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001156 CfgVector<RegNumT> GPRArgs;
1157 CfgVector<RegNumT> I64Args;
John Porto2187c842015-12-16 07:48:25 -08001158
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001159 void discardUnavailableVFPRegs(CfgVector<RegNumT> *Regs);
John Portoe82b5602016-02-24 15:58:55 -08001160 SmallBitVector VFPRegsUsed;
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001161 CfgVector<RegNumT> FP32Args;
1162 CfgVector<RegNumT> FP64Args;
1163 CfgVector<RegNumT> Vec128Args;
Jan Voungb0a8c242015-06-18 15:00:14 -07001164 };
1165
Jan Voungb36ad9b2015-04-21 17:01:49 -07001166private:
John Porto53611e22015-12-30 07:30:10 -08001167 ENABLE_MAKE_UNIQUE;
John Porto4a5e6d02015-11-04 09:32:55 -08001168
John Portof5f02f72015-11-09 14:52:40 -08001169 OperandARM32Mem *formAddressingMode(Type Ty, Cfg *Func, const Inst *LdSt,
1170 Operand *Base);
1171
John Portoc39ec102015-12-01 13:00:43 -08001172 void postambleCtpop64(const InstCall *Instr);
1173 void preambleDivRem(const InstCall *Instr);
John Portoe82b5602016-02-24 15:58:55 -08001174 CfgUnorderedMap<Operand *, void (TargetARM32::*)(const InstCall *Instr)>
John Portoc39ec102015-12-01 13:00:43 -08001175 ARM32HelpersPreamble;
John Portoe82b5602016-02-24 15:58:55 -08001176 CfgUnorderedMap<Operand *, void (TargetARM32::*)(const InstCall *Instr)>
John Portoc39ec102015-12-01 13:00:43 -08001177 ARM32HelpersPostamble;
1178
John Portoeb13acc2015-12-09 05:10:58 -08001179 class ComputationTracker {
John Porto4a5e6d02015-11-04 09:32:55 -08001180 public:
John Portoeb13acc2015-12-09 05:10:58 -08001181 ComputationTracker() = default;
1182 ~ComputationTracker() = default;
John Porto4a5e6d02015-11-04 09:32:55 -08001183
1184 void forgetProducers() { KnownComputations.clear(); }
1185 void recordProducers(CfgNode *Node);
1186
1187 const Inst *getProducerOf(const Operand *Opnd) const {
1188 auto *Var = llvm::dyn_cast<Variable>(Opnd);
1189 if (Var == nullptr) {
1190 return nullptr;
1191 }
1192
1193 auto Iter = KnownComputations.find(Var->getIndex());
1194 if (Iter == KnownComputations.end()) {
1195 return nullptr;
1196 }
1197
1198 return Iter->second.Instr;
1199 }
1200
1201 void dump(const Cfg *Func) const {
1202 if (!BuildDefs::dump() || !Func->isVerbose(IceV_Folding))
1203 return;
1204 OstreamLocker L(Func->getContext());
1205 Ostream &Str = Func->getContext()->getStrDump();
John Porto7b3d9cb2015-11-11 14:26:57 -08001206 Str << "foldable producer:\n";
John Porto4a5e6d02015-11-04 09:32:55 -08001207 for (const auto &Computation : KnownComputations) {
1208 Str << " ";
1209 Computation.second.Instr->dump(Func);
1210 Str << "\n";
1211 }
1212 Str << "\n";
1213 }
1214
1215 private:
John Portoeb13acc2015-12-09 05:10:58 -08001216 class ComputationEntry {
John Porto4a5e6d02015-11-04 09:32:55 -08001217 public:
John Portoeb13acc2015-12-09 05:10:58 -08001218 ComputationEntry(Inst *I, Type Ty) : Instr(I), ComputationType(Ty) {}
John Porto4a5e6d02015-11-04 09:32:55 -08001219 Inst *const Instr;
1220 // Boolean folding is disabled for variables whose live range is multi
1221 // block. We conservatively initialize IsLiveOut to true, and set it to
1222 // false once we find the end of the live range for the variable defined
1223 // by this instruction. If liveness analysis is not performed (e.g., in
1224 // Om1 mode) IsLiveOut will never be set to false, and folding will be
1225 // disabled.
1226 bool IsLiveOut = true;
John Porto7b3d9cb2015-11-11 14:26:57 -08001227 int32_t NumUses = 0;
John Portoeb13acc2015-12-09 05:10:58 -08001228 Type ComputationType;
John Porto4a5e6d02015-11-04 09:32:55 -08001229 };
1230
John Portoeb13acc2015-12-09 05:10:58 -08001231 // ComputationMap maps a Variable number to a payload identifying which
1232 // instruction defined it.
John Portoe82b5602016-02-24 15:58:55 -08001233 using ComputationMap = CfgUnorderedMap<SizeT, ComputationEntry>;
John Portoeb13acc2015-12-09 05:10:58 -08001234 ComputationMap KnownComputations;
John Porto4a5e6d02015-11-04 09:32:55 -08001235 };
1236
John Portoeb13acc2015-12-09 05:10:58 -08001237 ComputationTracker Computations;
John Porto614140e2015-11-23 11:43:13 -08001238
1239 // AllowTemporaryWithNoReg indicates if TargetARM32::makeReg() can be invoked
1240 // without specifying a physical register. This is needed for creating unbound
1241 // temporaries during Ice -> ARM lowering, but before register allocation.
John Porto98cc08c2015-11-24 12:30:01 -08001242 // This a safe-guard that no unbound temporaries are created during the
1243 // legalization post-passes.
John Porto614140e2015-11-23 11:43:13 -08001244 bool AllowTemporaryWithNoReg = true;
1245 // ForbidTemporaryWithoutReg is a RAII class that manages
1246 // AllowTemporaryWithNoReg.
1247 class ForbidTemporaryWithoutReg {
1248 ForbidTemporaryWithoutReg() = delete;
John Porto98cc08c2015-11-24 12:30:01 -08001249 ForbidTemporaryWithoutReg(const ForbidTemporaryWithoutReg &) = delete;
1250 ForbidTemporaryWithoutReg &
1251 operator=(const ForbidTemporaryWithoutReg &) = delete;
John Porto614140e2015-11-23 11:43:13 -08001252
1253 public:
1254 explicit ForbidTemporaryWithoutReg(TargetARM32 *Target) : Target(Target) {
1255 Target->AllowTemporaryWithNoReg = false;
1256 }
1257 ~ForbidTemporaryWithoutReg() { Target->AllowTemporaryWithNoReg = true; }
1258
1259 private:
1260 TargetARM32 *const Target;
1261 };
Jan Voungb36ad9b2015-04-21 17:01:49 -07001262};
1263
John Porto0f86d032015-06-15 07:44:27 -07001264class TargetDataARM32 final : public TargetDataLowering {
Jan Voungb36ad9b2015-04-21 17:01:49 -07001265 TargetDataARM32() = delete;
1266 TargetDataARM32(const TargetDataARM32 &) = delete;
1267 TargetDataARM32 &operator=(const TargetDataARM32 &) = delete;
1268
1269public:
Jan Voungfb792842015-06-11 15:27:50 -07001270 static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) {
1271 return std::unique_ptr<TargetDataLowering>(new TargetDataARM32(Ctx));
Jan Voungb36ad9b2015-04-21 17:01:49 -07001272 }
1273
John Porto8b1a7052015-06-17 13:20:08 -07001274 void lowerGlobals(const VariableDeclarationList &Vars,
1275 const IceString &SectionSuffix) override;
John Porto0f86d032015-06-15 07:44:27 -07001276 void lowerConstants() override;
Andrew Scull86df4e92015-07-30 13:54:44 -07001277 void lowerJumpTables() override;
Jan Voungb36ad9b2015-04-21 17:01:49 -07001278
1279protected:
1280 explicit TargetDataARM32(GlobalContext *Ctx);
1281
1282private:
Jim Stichnothe587d942015-06-22 15:49:04 -07001283 ~TargetDataARM32() override = default;
Jan Voungb36ad9b2015-04-21 17:01:49 -07001284};
1285
Jan Voungfb792842015-06-11 15:27:50 -07001286class TargetHeaderARM32 final : public TargetHeaderLowering {
1287 TargetHeaderARM32() = delete;
1288 TargetHeaderARM32(const TargetHeaderARM32 &) = delete;
1289 TargetHeaderARM32 &operator=(const TargetHeaderARM32 &) = delete;
1290
1291public:
1292 static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) {
1293 return std::unique_ptr<TargetHeaderLowering>(new TargetHeaderARM32(Ctx));
1294 }
1295
John Porto0f86d032015-06-15 07:44:27 -07001296 void lower() override;
Jan Voungfb792842015-06-11 15:27:50 -07001297
1298protected:
1299 explicit TargetHeaderARM32(GlobalContext *Ctx);
1300
1301private:
1302 ~TargetHeaderARM32() = default;
Jan Voung6ec369e2015-06-30 11:03:15 -07001303
1304 TargetARM32Features CPUFeatures;
Jan Voungfb792842015-06-11 15:27:50 -07001305};
1306
John Porto4a566862016-01-04 09:33:41 -08001307} // end of namespace ARM32
Jan Voungb36ad9b2015-04-21 17:01:49 -07001308} // end of namespace Ice
1309
1310#endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H