blob: 469c7cf68b8434fe9083ab8a76b59d49551e136f [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
19#include "IceDefs.h"
Jan Voungb2d50842015-05-12 09:53:50 -070020#include "IceInstARM32.h"
Jan Voungb36ad9b2015-04-21 17:01:49 -070021#include "IceRegistersARM32.h"
22#include "IceTargetLowering.h"
23
John Porto385351b2015-09-16 16:11:10 -070024#include "llvm/ADT/SmallBitVector.h"
25
Jan Voungb36ad9b2015-04-21 17:01:49 -070026namespace Ice {
27
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:
Jim Stichnoth94844f12015-11-04 16:06:16 -080058 static void staticInit();
Jan Voungb36ad9b2015-04-21 17:01:49 -070059 // TODO(jvoung): return a unique_ptr.
60 static TargetARM32 *create(Cfg *Func) { return new TargetARM32(Func); }
61
John Porto4a5e6d02015-11-04 09:32:55 -080062 void initNodeForLowering(CfgNode *Node) override {
John Portoeb13acc2015-12-09 05:10:58 -080063 Computations.forgetProducers();
64 Computations.recordProducers(Node);
65 Computations.dump(Func);
John Porto4a5e6d02015-11-04 09:32:55 -080066 }
67
Jan Voungb36ad9b2015-04-21 17:01:49 -070068 void translateOm1() override;
69 void translateO2() override;
70 bool doBranchOpt(Inst *I, const CfgNode *NextNode) override;
71
72 SizeT getNumRegisters() const override { return RegARM32::Reg_NUM; }
73 Variable *getPhysicalRegister(SizeT RegNum, Type Ty = IceType_void) override;
74 IceString getRegName(SizeT RegNum, Type Ty) const override;
75 llvm::SmallBitVector getRegisterSet(RegSetMask Include,
76 RegSetMask Exclude) const override;
Jim Stichnothc59288b2015-11-09 11:38:40 -080077 const llvm::SmallBitVector &
78 getRegistersForVariable(const Variable *Var) const override {
79 RegClass RC = Var->getRegClass();
80 assert(RC < RC_Target);
81 return TypeToRegisterSet[RC];
Jan Voungb36ad9b2015-04-21 17:01:49 -070082 }
John Portobb0a5fe2015-09-04 11:23:41 -070083 const llvm::SmallBitVector &getAliasesForRegister(SizeT Reg) const override {
84 return RegisterAliases[Reg];
85 }
Jan Voungb36ad9b2015-04-21 17:01:49 -070086 bool hasFramePointer() const override { return UsesFramePointer; }
David Sehre39d0ca2015-11-06 11:25:41 -080087 void setHasFramePointer() override { UsesFramePointer = true; }
Jim Stichnothe7418712015-10-09 06:54:02 -070088 SizeT getStackReg() const override { return RegARM32::Reg_sp; }
David Sehr2f3b8ec2015-11-16 16:51:39 -080089 SizeT getFrameReg() const override { return RegARM32::Reg_fp; }
Jan Voungb36ad9b2015-04-21 17:01:49 -070090 SizeT getFrameOrStackReg() const override {
David Sehr2f3b8ec2015-11-16 16:51:39 -080091 return UsesFramePointer ? getFrameReg() : getStackReg();
Jan Voungb36ad9b2015-04-21 17:01:49 -070092 }
John Porto866b6b12015-12-03 09:45:31 -080093 int32_t getReservedTmpReg() const { return RegARM32::Reg_ip; }
Jan Voung28068ad2015-07-31 12:58:46 -070094
Jan Voungb36ad9b2015-04-21 17:01:49 -070095 size_t typeWidthInBytesOnStack(Type Ty) const override {
Andrew Scull57e12682015-09-16 11:30:19 -070096 // Round up to the next multiple of 4 bytes. In particular, i1, i8, and i16
97 // are rounded up to 4 bytes.
Jan Voungb36ad9b2015-04-21 17:01:49 -070098 return (typeWidthInBytes(Ty) + 3) & ~3;
99 }
David Sehre39d0ca2015-11-06 11:25:41 -0800100 uint32_t getStackAlignment() const override;
David Sehr2f3b8ec2015-11-16 16:51:39 -0800101 void reserveFixedAllocaArea(size_t Size, size_t Align) override {
John Porto614140e2015-11-23 11:43:13 -0800102 FixedAllocaSizeBytes = Size;
103 assert(llvm::isPowerOf2_32(Align));
104 FixedAllocaAlignBytes = Align;
105 PrologEmitsFixedAllocas = true;
David Sehr2f3b8ec2015-11-16 16:51:39 -0800106 }
107 int32_t getFrameFixedAllocaOffset() const override {
John Porto614140e2015-11-23 11:43:13 -0800108 return FixedAllocaSizeBytes - (SpillAreaSizeBytes - MaxOutArgsSizeBytes);
David Sehr2f3b8ec2015-11-16 16:51:39 -0800109 }
John Porto614140e2015-11-23 11:43:13 -0800110 uint32_t maxOutArgsSizeBytes() const override { return MaxOutArgsSizeBytes; }
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700111
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700112 bool shouldSplitToVariable64On32(Type Ty) const override {
113 return Ty == IceType_i64;
114 }
115
Andrew Scull87f80c12015-07-20 10:19:16 -0700116 // TODO(ascull): what size is best for ARM?
117 SizeT getMinJumpTableSize() const override { return 3; }
Andrew Scull86df4e92015-07-30 13:54:44 -0700118 void emitJumpTable(const Cfg *Func,
119 const InstJumpTable *JumpTable) const override;
Andrew Scull87f80c12015-07-20 10:19:16 -0700120
Jan Voungb36ad9b2015-04-21 17:01:49 -0700121 void emitVariable(const Variable *Var) const override;
Jan Voung76bb0be2015-05-14 09:26:19 -0700122
123 const char *getConstantPrefix() const final { return "#"; }
124 void emit(const ConstantUndef *C) const final;
125 void emit(const ConstantInteger32 *C) const final;
126 void emit(const ConstantInteger64 *C) const final;
127 void emit(const ConstantFloat *C) const final;
128 void emit(const ConstantDouble *C) const final;
129
Jan Voungb36ad9b2015-04-21 17:01:49 -0700130 void lowerArguments() override;
131 void addProlog(CfgNode *Node) override;
132 void addEpilog(CfgNode *Node) override;
133
Jan Voungb3401d22015-05-18 09:38:21 -0700134 Operand *loOperand(Operand *Operand);
135 Operand *hiOperand(Operand *Operand);
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700136 void finishArgumentLowering(Variable *Arg, Variable *FramePtr,
John Porto3f6b47d2015-11-19 05:42:59 -0800137 size_t BasicFrameOffset, size_t *InArgsSizeBytes);
Jan Voungb3401d22015-05-18 09:38:21 -0700138
Jan Voung6ec369e2015-06-30 11:03:15 -0700139 bool hasCPUFeature(TargetARM32Features::ARM32InstructionSet I) const {
140 return CPUFeatures.hasFeature(I);
141 }
John Portoccea7932015-11-17 04:58:36 -0800142
143 enum OperandLegalization {
John Portoccea7932015-11-17 04:58:36 -0800144 Legal_Reg = 1 << 0, /// physical register, not stack location
145 Legal_Flex = 1 << 1, /// A flexible operand2, which can hold rotated small
146 /// immediates, shifted registers, or modified fp imm.
147 Legal_Mem = 1 << 2, /// includes [r0, r1 lsl #2] as well as [sp, #12]
John Porto866b6b12015-12-03 09:45:31 -0800148 Legal_Rematerializable = 1 << 3,
149 Legal_All = ~Legal_Rematerializable,
John Portoccea7932015-11-17 04:58:36 -0800150 };
151
152 using LegalMask = uint32_t;
Jan Voung53483692015-07-16 10:47:46 -0700153 Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister);
John Portoccea7932015-11-17 04:58:36 -0800154 Operand *legalize(Operand *From, LegalMask Allowed = Legal_All,
155 int32_t RegNum = Variable::NoRegister);
156 Variable *legalizeToReg(Operand *From, int32_t RegNum = Variable::NoRegister);
157
John Porto2758bb02015-11-17 14:31:25 -0800158 OperandARM32ShAmtImm *shAmtImm(uint32_t ShAmtImm) const {
159 assert(ShAmtImm < 32);
160 return OperandARM32ShAmtImm::create(
161 Func,
162 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(ShAmtImm & 0x1F)));
163 }
164
John Portoccea7932015-11-17 04:58:36 -0800165 GlobalContext *getCtx() const { return Ctx; }
Jan Voungd062f732015-06-15 17:17:31 -0700166
Jan Voungb36ad9b2015-04-21 17:01:49 -0700167protected:
168 explicit TargetARM32(Cfg *Func);
169
170 void postLower() override;
171
John Porto7b3d9cb2015-11-11 14:26:57 -0800172 enum SafeBoolChain {
173 SBC_No,
174 SBC_Yes,
175 };
176
Jan Voungb36ad9b2015-04-21 17:01:49 -0700177 void lowerAlloca(const InstAlloca *Inst) override;
John Porto7b3d9cb2015-11-11 14:26:57 -0800178 SafeBoolChain lowerInt1Arithmetic(const InstArithmetic *Inst);
John Portoccea7932015-11-17 04:58:36 -0800179 void lowerInt64Arithmetic(InstArithmetic::OpKind Op, Variable *Dest,
180 Operand *Src0, Operand *Src1);
Jan Voungb36ad9b2015-04-21 17:01:49 -0700181 void lowerArithmetic(const InstArithmetic *Inst) override;
182 void lowerAssign(const InstAssign *Inst) override;
183 void lowerBr(const InstBr *Inst) override;
184 void lowerCall(const InstCall *Inst) override;
185 void lowerCast(const InstCast *Inst) override;
186 void lowerExtractElement(const InstExtractElement *Inst) override;
John Porto7b3d9cb2015-11-11 14:26:57 -0800187
188 /// CondWhenTrue is a helper type returned by every method in the lowering
189 /// that emits code to set the condition codes.
190 class CondWhenTrue {
191 public:
192 explicit CondWhenTrue(CondARM32::Cond T0,
193 CondARM32::Cond T1 = CondARM32::kNone)
194 : WhenTrue0(T0), WhenTrue1(T1) {
195 assert(T1 == CondARM32::kNone || T0 != CondARM32::kNone);
196 assert(T1 != T0 || T0 == CondARM32::kNone);
197 }
198 CondARM32::Cond WhenTrue0;
199 CondARM32::Cond WhenTrue1;
200
201 /// invert returns a new object with WhenTrue0 and WhenTrue1 inverted.
202 CondWhenTrue invert() const {
203 switch (WhenTrue0) {
204 default:
205 if (WhenTrue1 == CondARM32::kNone)
206 return CondWhenTrue(InstARM32::getOppositeCondition(WhenTrue0));
207 return CondWhenTrue(InstARM32::getOppositeCondition(WhenTrue0),
208 InstARM32::getOppositeCondition(WhenTrue1));
209 case CondARM32::AL:
210 return CondWhenTrue(CondARM32::kNone);
211 case CondARM32::kNone:
212 return CondWhenTrue(CondARM32::AL);
213 }
214 }
215 };
216
217 CondWhenTrue lowerFcmpCond(const InstFcmp *Instr);
John Porto4a5e6d02015-11-04 09:32:55 -0800218 void lowerFcmp(const InstFcmp *Instr) override;
John Portoccea7932015-11-17 04:58:36 -0800219 CondWhenTrue lowerInt8AndInt16IcmpCond(InstIcmp::ICond Condition,
220 Operand *Src0, Operand *Src1);
221 CondWhenTrue lowerInt32IcmpCond(InstIcmp::ICond Condition, Operand *Src0,
222 Operand *Src1);
223 CondWhenTrue lowerInt64IcmpCond(InstIcmp::ICond Condition, Operand *Src0,
224 Operand *Src1);
John Porto7b3d9cb2015-11-11 14:26:57 -0800225 CondWhenTrue lowerIcmpCond(const InstIcmp *Instr);
John Porto4a5e6d02015-11-04 09:32:55 -0800226 void lowerIcmp(const InstIcmp *Instr) override;
John Porto578f1162015-10-06 06:54:42 -0700227 void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr,
228 Operand *Val);
Jan Voungb36ad9b2015-04-21 17:01:49 -0700229 void lowerIntrinsicCall(const InstIntrinsicCall *Inst) override;
230 void lowerInsertElement(const InstInsertElement *Inst) override;
231 void lowerLoad(const InstLoad *Inst) override;
232 void lowerPhi(const InstPhi *Inst) override;
233 void lowerRet(const InstRet *Inst) override;
234 void lowerSelect(const InstSelect *Inst) override;
235 void lowerStore(const InstStore *Inst) override;
236 void lowerSwitch(const InstSwitch *Inst) override;
237 void lowerUnreachable(const InstUnreachable *Inst) override;
238 void prelowerPhis() override;
John Portof4198542015-11-20 14:17:23 -0800239 uint32_t getCallStackArgumentsSizeBytes(const InstCall *Instr) override;
John Portoc39ec102015-12-01 13:00:43 -0800240 void genTargetHelperCallFor(Inst *Instr) override;
Jan Voungb36ad9b2015-04-21 17:01:49 -0700241 void doAddressOptLoad() override;
242 void doAddressOptStore() override;
Qining Luaee5fa82015-08-20 14:59:03 -0700243 void randomlyInsertNop(float Probability,
244 RandomNumberGenerator &RNG) override;
Jan Voungb3401d22015-05-18 09:38:21 -0700245
Jan Voungbefd03a2015-06-02 11:03:03 -0700246 OperandARM32Mem *formMemoryOperand(Operand *Ptr, Type Ty);
Jan Voungb3401d22015-05-18 09:38:21 -0700247
John Porto578f1162015-10-06 06:54:42 -0700248 Variable64On32 *makeI64RegPair();
Jan Voungb3401d22015-05-18 09:38:21 -0700249 Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister);
250 static Type stackSlotType();
251 Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister);
John Porto614140e2015-11-23 11:43:13 -0800252 void alignRegisterPow2(Variable *Reg, uint32_t Align,
253 int32_t TmpRegNum = Variable::NoRegister);
Jan Voungb3401d22015-05-18 09:38:21 -0700254
Andrew Scull9612d322015-07-06 14:53:25 -0700255 /// Returns a vector in a register with the given constant entries.
Jan Voungb3401d22015-05-18 09:38:21 -0700256 Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister);
257
Qining Luaee5fa82015-08-20 14:59:03 -0700258 void
259 makeRandomRegisterPermutation(llvm::SmallVectorImpl<int32_t> &Permutation,
260 const llvm::SmallBitVector &ExcludeRegisters,
261 uint64_t Salt) const override;
Jan Voungb36ad9b2015-04-21 17:01:49 -0700262
Andrew Scull57e12682015-09-16 11:30:19 -0700263 // If a divide-by-zero check is needed, inserts a: test; branch .LSKIP; trap;
264 // .LSKIP: <continuation>. If no check is needed nothing is inserted.
Jan Voung6ec369e2015-06-30 11:03:15 -0700265 void div0Check(Type Ty, Operand *SrcLo, Operand *SrcHi);
Andrew Scull8072bae2015-09-14 16:01:26 -0700266 using ExtInstr = void (TargetARM32::*)(Variable *, Variable *,
267 CondARM32::Cond);
268 using DivInstr = void (TargetARM32::*)(Variable *, Variable *, Variable *,
269 CondARM32::Cond);
Jan Voung6ec369e2015-06-30 11:03:15 -0700270 void lowerIDivRem(Variable *Dest, Variable *T, Variable *Src0R, Operand *Src1,
John Portoc39ec102015-12-01 13:00:43 -0800271 ExtInstr ExtFunc, DivInstr DivFunc, bool IsRemainder);
Jan Voung6ec369e2015-06-30 11:03:15 -0700272
Jan Voungf645d852015-07-09 10:35:09 -0700273 void lowerCLZ(Variable *Dest, Variable *ValLo, Variable *ValHi);
274
Andrew Scull57e12682015-09-16 11:30:19 -0700275 // The following are helpers that insert lowered ARM32 instructions with
276 // minimal syntactic overhead, so that the lowering code can look as close to
277 // assembly as practical.
Jan Voung3bfd99a2015-05-22 16:35:25 -0700278 void _add(Variable *Dest, Variable *Src0, Operand *Src1,
279 CondARM32::Cond Pred = CondARM32::AL) {
280 Context.insert(InstARM32Add::create(Func, Dest, Src0, Src1, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700281 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700282 void _adds(Variable *Dest, Variable *Src0, Operand *Src1,
283 CondARM32::Cond Pred = CondARM32::AL) {
Jan Voung86ebec12015-08-09 07:58:35 -0700284 constexpr bool SetFlags = true;
Jan Voung3bfd99a2015-05-22 16:35:25 -0700285 Context.insert(
286 InstARM32Add::create(Func, Dest, Src0, Src1, Pred, SetFlags));
Jan Voung29719972015-05-19 11:24:51 -0700287 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700288 void _adc(Variable *Dest, Variable *Src0, Operand *Src1,
289 CondARM32::Cond Pred = CondARM32::AL) {
290 Context.insert(InstARM32Adc::create(Func, Dest, Src0, Src1, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700291 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700292 void _and(Variable *Dest, Variable *Src0, Operand *Src1,
293 CondARM32::Cond Pred = CondARM32::AL) {
294 Context.insert(InstARM32And::create(Func, Dest, Src0, Src1, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700295 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700296 void _asr(Variable *Dest, Variable *Src0, Operand *Src1,
297 CondARM32::Cond Pred = CondARM32::AL) {
298 Context.insert(InstARM32Asr::create(Func, Dest, Src0, Src1, Pred));
299 }
Jan Voung55500db2015-05-26 14:25:40 -0700300 void _bic(Variable *Dest, Variable *Src0, Operand *Src1,
301 CondARM32::Cond Pred = CondARM32::AL) {
302 Context.insert(InstARM32Bic::create(Func, Dest, Src0, Src1, Pred));
303 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700304 void _br(CfgNode *TargetTrue, CfgNode *TargetFalse,
305 CondARM32::Cond Condition) {
Jan Voung3bfd99a2015-05-22 16:35:25 -0700306 Context.insert(
307 InstARM32Br::create(Func, TargetTrue, TargetFalse, Condition));
Jan Voung29719972015-05-19 11:24:51 -0700308 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700309 void _br(CfgNode *Target) {
310 Context.insert(InstARM32Br::create(Func, Target));
Jan Voungb3401d22015-05-18 09:38:21 -0700311 }
Andrew Scullfdc54db2015-06-29 11:21:18 -0700312 void _br(CfgNode *Target, CondARM32::Cond Condition) {
313 Context.insert(InstARM32Br::create(Func, Target, Condition));
314 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700315 void _br(InstARM32Label *Label, CondARM32::Cond Condition) {
316 Context.insert(InstARM32Br::create(Func, Label, Condition));
317 }
John Portoccea7932015-11-17 04:58:36 -0800318 void _cmn(Variable *Src0, Operand *Src1,
319 CondARM32::Cond Pred = CondARM32::AL) {
320 Context.insert(InstARM32Cmn::create(Func, Src0, Src1, Pred));
321 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700322 void _cmp(Variable *Src0, Operand *Src1,
323 CondARM32::Cond Pred = CondARM32::AL) {
324 Context.insert(InstARM32Cmp::create(Func, Src0, Src1, Pred));
325 }
Jan Voungf645d852015-07-09 10:35:09 -0700326 void _clz(Variable *Dest, Variable *Src0,
327 CondARM32::Cond Pred = CondARM32::AL) {
328 Context.insert(InstARM32Clz::create(Func, Dest, Src0, Pred));
329 }
John Porto16991842015-10-01 15:11:23 -0700330 void _dmb() { Context.insert(InstARM32Dmb::create(Func)); }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700331 void _eor(Variable *Dest, Variable *Src0, Operand *Src1,
332 CondARM32::Cond Pred = CondARM32::AL) {
333 Context.insert(InstARM32Eor::create(Func, Dest, Src0, Src1, Pred));
334 }
John Portoba6a67c2015-09-25 15:19:45 -0700335 /// _ldr, for all your memory to Variable data moves. It handles all types
336 /// (integer, floating point, and vectors.) Addr needs to be valid for Dest's
337 /// type (e.g., no immediates for vector loads, and no index registers for fp
338 /// loads.)
Jan Voung3bfd99a2015-05-22 16:35:25 -0700339 void _ldr(Variable *Dest, OperandARM32Mem *Addr,
340 CondARM32::Cond Pred = CondARM32::AL) {
341 Context.insert(InstARM32Ldr::create(Func, Dest, Addr, Pred));
342 }
John Porto16991842015-10-01 15:11:23 -0700343 void _ldrex(Variable *Dest, OperandARM32Mem *Addr,
Jim Stichnothb36757e2015-10-05 13:55:11 -0700344 CondARM32::Cond Pred = CondARM32::AL) {
345 Context.insert(InstARM32Ldrex::create(Func, Dest, Addr, Pred));
346 if (auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest)) {
347 Context.insert(InstFakeDef::create(Func, Dest64->getLo(), Dest));
348 Context.insert(InstFakeDef::create(Func, Dest64->getHi(), Dest));
349 }
350 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700351 void _lsl(Variable *Dest, Variable *Src0, Operand *Src1,
352 CondARM32::Cond Pred = CondARM32::AL) {
353 Context.insert(InstARM32Lsl::create(Func, Dest, Src0, Src1, Pred));
354 }
John Portoccea7932015-11-17 04:58:36 -0800355 void _lsls(Variable *Dest, Variable *Src0, Operand *Src1,
356 CondARM32::Cond Pred = CondARM32::AL) {
357 constexpr bool SetFlags = true;
358 Context.insert(
359 InstARM32Lsl::create(Func, Dest, Src0, Src1, Pred, SetFlags));
360 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700361 void _lsr(Variable *Dest, Variable *Src0, Operand *Src1,
362 CondARM32::Cond Pred = CondARM32::AL) {
363 Context.insert(InstARM32Lsr::create(Func, Dest, Src0, Src1, Pred));
364 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700365 void _mla(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc,
366 CondARM32::Cond Pred = CondARM32::AL) {
367 Context.insert(InstARM32Mla::create(Func, Dest, Src0, Src1, Acc, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700368 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700369 void _mls(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc,
370 CondARM32::Cond Pred = CondARM32::AL) {
371 Context.insert(InstARM32Mls::create(Func, Dest, Src0, Src1, Acc, Pred));
372 }
John Portoba6a67c2015-09-25 15:19:45 -0700373 /// _mov, for all your Variable to Variable data movement needs. It handles
374 /// all types (integer, floating point, and vectors), as well as moves between
375 /// Core and VFP registers. This is not a panacea: you must obey the (weird,
376 /// confusing, non-uniform) rules for data moves in ARM.
377 void _mov(Variable *Dest, Operand *Src0,
378 CondARM32::Cond Pred = CondARM32::AL) {
379 // _mov used to be unique in the sense that it would create a temporary
380 // automagically if Dest was nullptr. It won't do that anymore, so we keep
381 // an assert around just in case there is some untested code path where Dest
382 // is nullptr.
383 assert(Dest != nullptr);
John Porto3f6b47d2015-11-19 05:42:59 -0800384 assert(!llvm::isa<OperandARM32Mem>(Src0));
John Portoe0b829f2015-09-28 09:50:48 -0700385 auto *Instr = InstARM32Mov::create(Func, Dest, Src0, Pred);
386
387 Context.insert(Instr);
388 if (Instr->isMultiDest()) {
389 // If Instr is multi-dest, then Dest must be a Variable64On32. We add a
390 // fake-def for Instr.DestHi here.
391 assert(llvm::isa<Variable64On32>(Dest));
392 Context.insert(InstFakeDef::create(Func, Instr->getDestHi()));
393 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700394 }
John Porto578f1162015-10-06 06:54:42 -0700395
Jim Stichnoth230d41012015-09-25 17:40:32 -0700396 void _mov_redefined(Variable *Dest, Operand *Src0,
397 CondARM32::Cond Pred = CondARM32::AL) {
John Portoe0b829f2015-09-28 09:50:48 -0700398 auto *Instr = InstARM32Mov::create(Func, Dest, Src0, Pred);
399 Instr->setDestRedefined();
400 Context.insert(Instr);
401 if (Instr->isMultiDest()) {
402 // If Instr is multi-dest, then Dest must be a Variable64On32. We add a
403 // fake-def for Instr.DestHi here.
404 assert(llvm::isa<Variable64On32>(Dest));
405 Context.insert(InstFakeDef::create(Func, Instr->getDestHi()));
406 }
Jan Voungb3401d22015-05-18 09:38:21 -0700407 }
John Porto4a5e6d02015-11-04 09:32:55 -0800408
John Porto7b3d9cb2015-11-11 14:26:57 -0800409 // --------------------------------------------------------------------------
410 // Begin bool folding machinery.
411 //
412 // There are three types of boolean lowerings handled by this target:
413 //
414 // 1) Boolean expressions leading to a boolean Variable definition
415 // ---------------------------------------------------------------
416 //
417 // Whenever a i1 Variable is live out (i.e., its live range extends beyond
418 // the defining basic block) we do not fold the operation. We instead
419 // materialize (i.e., compute) the variable normally, so that it can be used
420 // when needed. We also materialize i1 values that are not single use to
421 // avoid code duplication. These expressions are not short circuited.
422 //
423 // 2) Boolean expressions leading to a select
424 // ------------------------------------------
425 //
426 // These include boolean chains leading to a select instruction, as well as
427 // i1 Sexts. These boolean expressions are lowered to:
428 //
429 // mov T, <false value>
430 // CC <- eval(Boolean Expression)
431 // movCC T, <true value>
432 //
433 // For Sexts, <false value> is 0, and <true value> is -1.
434 //
435 // 3) Boolean expressions leading to a br i1
436 // -----------------------------------------
437 //
438 // These are the boolean chains leading to a branch. These chains are
439 // short-circuited, i.e.:
440 //
441 // A = or i1 B, C
442 // br i1 A, label %T, label %F
443 //
444 // becomes
445 //
446 // tst B
447 // jne %T
448 // tst B
449 // jne %T
450 // j %F
451 //
452 // and
453 //
454 // A = and i1 B, C
455 // br i1 A, label %T, label %F
456 //
457 // becomes
458 //
459 // tst B
460 // jeq %F
461 // tst B
462 // jeq %F
463 // j %T
464 //
465 // Arbitrarily long chains are short circuited, e.g
466 //
467 // A = or i1 B, C
468 // D = and i1 A, E
469 // F = and i1 G, H
470 // I = or i1 D, F
471 // br i1 I, label %True, label %False
472 //
473 // becomes
474 //
475 // Label[A]:
476 // tst B, 1
477 // bne Label[D]
478 // tst C, 1
479 // beq Label[I]
480 // Label[D]:
481 // tst E, 1
482 // bne %True
483 // Label[I]
484 // tst G, 1
485 // beq %False
486 // tst H, 1
487 // beq %False (bne %True)
John Porto4a5e6d02015-11-04 09:32:55 -0800488
John Porto7b3d9cb2015-11-11 14:26:57 -0800489 /// lowerInt1 materializes Boolean to a Variable.
490 SafeBoolChain lowerInt1(Variable *Dest, Operand *Boolean);
John Porto4a5e6d02015-11-04 09:32:55 -0800491
John Porto7b3d9cb2015-11-11 14:26:57 -0800492 /// lowerInt1ForSelect generates the following instruction sequence:
493 ///
494 /// mov T, FalseValue
495 /// CC <- eval(Boolean)
496 /// movCC T, TrueValue
497 /// mov Dest, T
498 ///
499 /// It is used for lowering select i1, as well as i1 Sext.
500 void lowerInt1ForSelect(Variable *Dest, Operand *Boolean, Operand *TrueValue,
501 Operand *FalseValue);
502
503 /// LowerInt1BranchTarget is used by lowerIntForBranch. It wraps a CfgNode, or
504 /// an InstARM32Label (but never both) so that, during br i1 lowering, we can
505 /// create auxiliary labels for short circuiting the condition evaluation.
506 class LowerInt1BranchTarget {
507 public:
508 explicit LowerInt1BranchTarget(CfgNode *const Target)
509 : NodeTarget(Target) {}
510 explicit LowerInt1BranchTarget(InstARM32Label *const Target)
511 : LabelTarget(Target) {}
512
513 /// createForLabelOrDuplicate will return a new LowerInt1BranchTarget that
514 /// is the exact copy of this if Label is nullptr; otherwise, the returned
515 /// object will wrap Label instead.
516 LowerInt1BranchTarget
517 createForLabelOrDuplicate(InstARM32Label *Label) const {
518 if (Label != nullptr)
519 return LowerInt1BranchTarget(Label);
520 if (NodeTarget)
521 return LowerInt1BranchTarget(NodeTarget);
522 return LowerInt1BranchTarget(LabelTarget);
John Porto4a5e6d02015-11-04 09:32:55 -0800523 }
524
John Porto7b3d9cb2015-11-11 14:26:57 -0800525 CfgNode *const NodeTarget = nullptr;
526 InstARM32Label *const LabelTarget = nullptr;
527 };
John Porto4a5e6d02015-11-04 09:32:55 -0800528
John Porto7b3d9cb2015-11-11 14:26:57 -0800529 /// LowerInt1AllowShortCircuit is a helper type used by lowerInt1ForBranch for
530 /// determining which type arithmetic is allowed to be short circuited. This
531 /// is useful for lowering
532 ///
533 /// t1 = and i1 A, B
534 /// t2 = and i1 t1, C
535 /// br i1 t2, label %False, label %True
536 ///
537 /// to
538 ///
539 /// tst A, 1
540 /// beq %False
541 /// tst B, 1
542 /// beq %False
543 /// tst C, 1
544 /// bne %True
545 /// b %False
546 ///
547 /// Without this information, short circuiting would only allow to short
548 /// circuit a single high level instruction. For example:
549 ///
550 /// t1 = or i1 A, B
551 /// t2 = and i1 t1, C
552 /// br i1 t2, label %False, label %True
553 ///
554 /// cannot be lowered to
555 ///
556 /// tst A, 1
557 /// bne %True
558 /// tst B, 1
559 /// bne %True
560 /// tst C, 1
561 /// beq %True
562 /// b %False
563 ///
564 /// It needs to be lowered to
565 ///
566 /// tst A, 1
567 /// bne Aux
568 /// tst B, 1
569 /// beq %False
570 /// Aux:
571 /// tst C, 1
572 /// bne %True
573 /// b %False
574 ///
575 /// TODO(jpp): evaluate if this kind of short circuiting hurts performance (it
576 /// might.)
577 enum LowerInt1AllowShortCircuit {
578 SC_And = 1,
579 SC_Or = 2,
580 SC_All = SC_And | SC_Or,
581 };
John Porto4a5e6d02015-11-04 09:32:55 -0800582
John Porto7b3d9cb2015-11-11 14:26:57 -0800583 /// ShortCircuitCondAndLabel wraps the condition codes that should be used
584 /// after a lowerInt1ForBranch returns to branch to the
585 /// TrueTarget/FalseTarget. If ShortCircuitLabel is not nullptr, then the
586 /// called lowerInt1forBranch created an internal (i.e., short-circuit) label
587 /// used for short circuiting.
588 class ShortCircuitCondAndLabel {
589 public:
590 explicit ShortCircuitCondAndLabel(CondWhenTrue &&C,
591 InstARM32Label *L = nullptr)
592 : Cond(std::move(C)), ShortCircuitTarget(L) {}
593 const CondWhenTrue Cond;
594 InstARM32Label *const ShortCircuitTarget;
John Porto4a5e6d02015-11-04 09:32:55 -0800595
John Porto7b3d9cb2015-11-11 14:26:57 -0800596 CondWhenTrue assertNoLabelAndReturnCond() const {
597 assert(ShortCircuitTarget == nullptr);
598 return Cond;
John Porto4a5e6d02015-11-04 09:32:55 -0800599 }
John Porto7b3d9cb2015-11-11 14:26:57 -0800600 };
John Porto4a5e6d02015-11-04 09:32:55 -0800601
John Porto7b3d9cb2015-11-11 14:26:57 -0800602 /// lowerInt1ForBranch expands Boolean, and returns the condition codes that
603 /// are to be used for branching to the branch's TrueTarget. It may return a
604 /// label that the expansion of Boolean used to short circuit the chain's
605 /// evaluation.
606 ShortCircuitCondAndLabel
607 lowerInt1ForBranch(Operand *Boolean, const LowerInt1BranchTarget &TargetTrue,
608 const LowerInt1BranchTarget &TargetFalse,
609 uint32_t ShortCircuitable);
610
611 // _br is a convenience wrapper that emits br instructions to Target.
612 void _br(const LowerInt1BranchTarget &BrTarget,
613 CondARM32::Cond Cond = CondARM32::AL) {
614 assert((BrTarget.NodeTarget == nullptr) !=
615 (BrTarget.LabelTarget == nullptr));
616 if (BrTarget.NodeTarget != nullptr)
617 _br(BrTarget.NodeTarget, Cond);
618 else
619 _br(BrTarget.LabelTarget, Cond);
620 }
621
622 // _br_short_circuit is used when lowering InstArithmetic::And and
623 // InstArithmetic::Or and a short circuit branch is needed.
624 void _br_short_circuit(const LowerInt1BranchTarget &Target,
625 const CondWhenTrue &Cond) {
626 if (Cond.WhenTrue1 != CondARM32::kNone) {
627 _br(Target, Cond.WhenTrue1);
628 }
629 if (Cond.WhenTrue0 != CondARM32::kNone) {
630 _br(Target, Cond.WhenTrue0);
John Porto4a5e6d02015-11-04 09:32:55 -0800631 }
632 }
John Porto7b3d9cb2015-11-11 14:26:57 -0800633 // End of bool folding machinery
634 // --------------------------------------------------------------------------
John Porto4a5e6d02015-11-04 09:32:55 -0800635
Andrew Scull57e12682015-09-16 11:30:19 -0700636 /// The Operand can only be a 16-bit immediate or a ConstantRelocatable (with
637 /// an upper16 relocation).
Jan Voung3bfd99a2015-05-22 16:35:25 -0700638 void _movt(Variable *Dest, Operand *Src0,
639 CondARM32::Cond Pred = CondARM32::AL) {
640 Context.insert(InstARM32Movt::create(Func, Dest, Src0, Pred));
Jan Voungb3401d22015-05-18 09:38:21 -0700641 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700642 void _movw(Variable *Dest, Operand *Src0,
643 CondARM32::Cond Pred = CondARM32::AL) {
644 Context.insert(InstARM32Movw::create(Func, Dest, Src0, Pred));
Jan Voungb3401d22015-05-18 09:38:21 -0700645 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700646 void _mul(Variable *Dest, Variable *Src0, Variable *Src1,
647 CondARM32::Cond Pred = CondARM32::AL) {
648 Context.insert(InstARM32Mul::create(Func, Dest, Src0, Src1, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700649 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700650 void _mvn(Variable *Dest, Operand *Src0,
651 CondARM32::Cond Pred = CondARM32::AL) {
652 Context.insert(InstARM32Mvn::create(Func, Dest, Src0, Pred));
Jan Voungb3401d22015-05-18 09:38:21 -0700653 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700654 void _orr(Variable *Dest, Variable *Src0, Operand *Src1,
655 CondARM32::Cond Pred = CondARM32::AL) {
656 Context.insert(InstARM32Orr::create(Func, Dest, Src0, Src1, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700657 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700658 void _orrs(Variable *Dest, Variable *Src0, Operand *Src1,
659 CondARM32::Cond Pred = CondARM32::AL) {
Jan Voung86ebec12015-08-09 07:58:35 -0700660 constexpr bool SetFlags = true;
Jan Voung6ec369e2015-06-30 11:03:15 -0700661 Context.insert(
662 InstARM32Orr::create(Func, Dest, Src0, Src1, Pred, SetFlags));
663 }
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700664 void _push(const VarList &Sources) {
665 Context.insert(InstARM32Push::create(Func, Sources));
666 }
667 void _pop(const VarList &Dests) {
668 Context.insert(InstARM32Pop::create(Func, Dests));
669 // Mark dests as modified.
670 for (Variable *Dest : Dests)
671 Context.insert(InstFakeDef::create(Func, Dest));
672 }
Jan Voungf645d852015-07-09 10:35:09 -0700673 void _rbit(Variable *Dest, Variable *Src0,
674 CondARM32::Cond Pred = CondARM32::AL) {
675 Context.insert(InstARM32Rbit::create(Func, Dest, Src0, Pred));
676 }
677 void _rev(Variable *Dest, Variable *Src0,
678 CondARM32::Cond Pred = CondARM32::AL) {
679 Context.insert(InstARM32Rev::create(Func, Dest, Src0, Pred));
680 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700681 void _ret(Variable *LR, Variable *Src0 = nullptr) {
682 Context.insert(InstARM32Ret::create(Func, LR, Src0));
683 }
John Portoccea7932015-11-17 04:58:36 -0800684 void _rscs(Variable *Dest, Variable *Src0, Operand *Src1,
685 CondARM32::Cond Pred = CondARM32::AL) {
686 constexpr bool SetFlags = true;
687 Context.insert(
688 InstARM32Rsc::create(Func, Dest, Src0, Src1, Pred, SetFlags));
689 }
690 void _rsc(Variable *Dest, Variable *Src0, Operand *Src1,
691 CondARM32::Cond Pred = CondARM32::AL) {
692 Context.insert(InstARM32Rsc::create(Func, Dest, Src0, Src1, Pred));
693 }
694 void _rsbs(Variable *Dest, Variable *Src0, Operand *Src1,
695 CondARM32::Cond Pred = CondARM32::AL) {
696 constexpr bool SetFlags = true;
697 Context.insert(
698 InstARM32Rsb::create(Func, Dest, Src0, Src1, Pred, SetFlags));
699 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700700 void _rsb(Variable *Dest, Variable *Src0, Operand *Src1,
701 CondARM32::Cond Pred = CondARM32::AL) {
702 Context.insert(InstARM32Rsb::create(Func, Dest, Src0, Src1, Pred));
703 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700704 void _sbc(Variable *Dest, Variable *Src0, Operand *Src1,
705 CondARM32::Cond Pred = CondARM32::AL) {
706 Context.insert(InstARM32Sbc::create(Func, Dest, Src0, Src1, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700707 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700708 void _sbcs(Variable *Dest, Variable *Src0, Operand *Src1,
709 CondARM32::Cond Pred = CondARM32::AL) {
Jan Voung86ebec12015-08-09 07:58:35 -0700710 constexpr bool SetFlags = true;
Jan Voung3bfd99a2015-05-22 16:35:25 -0700711 Context.insert(
712 InstARM32Sbc::create(Func, Dest, Src0, Src1, Pred, SetFlags));
713 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700714 void _sdiv(Variable *Dest, Variable *Src0, Variable *Src1,
715 CondARM32::Cond Pred = CondARM32::AL) {
716 Context.insert(InstARM32Sdiv::create(Func, Dest, Src0, Src1, Pred));
717 }
John Portoba6a67c2015-09-25 15:19:45 -0700718 /// _str, for all your Variable to memory transfers. Addr has the same
719 /// restrictions that it does in _ldr.
Jan Voungbefd03a2015-06-02 11:03:03 -0700720 void _str(Variable *Value, OperandARM32Mem *Addr,
721 CondARM32::Cond Pred = CondARM32::AL) {
722 Context.insert(InstARM32Str::create(Func, Value, Addr, Pred));
723 }
John Porto16991842015-10-01 15:11:23 -0700724 void _strex(Variable *Dest, Variable *Value, OperandARM32Mem *Addr,
725 CondARM32::Cond Pred = CondARM32::AL) {
John Porto578f1162015-10-06 06:54:42 -0700726 // strex requires Dest to be a register other than Value or Addr. This
727 // restriction is cleanly represented by adding an "early" definition of
728 // Dest (or a latter use of all the sources.)
729 Context.insert(InstFakeDef::create(Func, Dest));
John Porto16991842015-10-01 15:11:23 -0700730 if (auto *Value64 = llvm::dyn_cast<Variable64On32>(Value)) {
731 Context.insert(InstFakeUse::create(Func, Value64->getLo()));
732 Context.insert(InstFakeUse::create(Func, Value64->getHi()));
733 }
John Porto578f1162015-10-06 06:54:42 -0700734 auto *Instr = InstARM32Strex::create(Func, Dest, Value, Addr, Pred);
735 Context.insert(Instr);
736 Instr->setDestRedefined();
John Porto16991842015-10-01 15:11:23 -0700737 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700738 void _sub(Variable *Dest, Variable *Src0, Operand *Src1,
739 CondARM32::Cond Pred = CondARM32::AL) {
740 Context.insert(InstARM32Sub::create(Func, Dest, Src0, Src1, Pred));
741 }
742 void _subs(Variable *Dest, Variable *Src0, Operand *Src1,
743 CondARM32::Cond Pred = CondARM32::AL) {
Jan Voung86ebec12015-08-09 07:58:35 -0700744 constexpr bool SetFlags = true;
Jan Voung3bfd99a2015-05-22 16:35:25 -0700745 Context.insert(
746 InstARM32Sub::create(Func, Dest, Src0, Src1, Pred, SetFlags));
Jan Voung29719972015-05-19 11:24:51 -0700747 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700748 void _sxt(Variable *Dest, Variable *Src0,
749 CondARM32::Cond Pred = CondARM32::AL) {
750 Context.insert(InstARM32Sxt::create(Func, Dest, Src0, Pred));
751 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700752 void _tst(Variable *Src0, Operand *Src1,
753 CondARM32::Cond Pred = CondARM32::AL) {
754 Context.insert(InstARM32Tst::create(Func, Src0, Src1, Pred));
755 }
756 void _trap() { Context.insert(InstARM32Trap::create(Func)); }
757 void _udiv(Variable *Dest, Variable *Src0, Variable *Src1,
758 CondARM32::Cond Pred = CondARM32::AL) {
759 Context.insert(InstARM32Udiv::create(Func, Dest, Src0, Src1, Pred));
Jan Voungb2d50842015-05-12 09:53:50 -0700760 }
Jan Voung29719972015-05-19 11:24:51 -0700761 void _umull(Variable *DestLo, Variable *DestHi, Variable *Src0,
Jan Voung3bfd99a2015-05-22 16:35:25 -0700762 Variable *Src1, CondARM32::Cond Pred = CondARM32::AL) {
763 Context.insert(
764 InstARM32Umull::create(Func, DestLo, DestHi, Src0, Src1, Pred));
Andrew Scull57e12682015-09-16 11:30:19 -0700765 // Model the modification to the second dest as a fake def. Note that the
766 // def is not predicated.
Jan Voung29719972015-05-19 11:24:51 -0700767 Context.insert(InstFakeDef::create(Func, DestHi, DestLo));
768 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700769 void _uxt(Variable *Dest, Variable *Src0,
770 CondARM32::Cond Pred = CondARM32::AL) {
771 Context.insert(InstARM32Uxt::create(Func, Dest, Src0, Pred));
772 }
John Portoba6a67c2015-09-25 15:19:45 -0700773 void _vabs(Variable *Dest, Variable *Src,
774 CondARM32::Cond Pred = CondARM32::AL) {
775 Context.insert(InstARM32Vabs::create(Func, Dest, Src, Pred));
776 }
Jan Voung86ebec12015-08-09 07:58:35 -0700777 void _vadd(Variable *Dest, Variable *Src0, Variable *Src1) {
778 Context.insert(InstARM32Vadd::create(Func, Dest, Src0, Src1));
779 }
John Portoc31e2ed2015-09-11 05:17:08 -0700780 void _vcvt(Variable *Dest, Variable *Src, InstARM32Vcvt::VcvtVariant Variant,
781 CondARM32::Cond Pred = CondARM32::AL) {
782 Context.insert(InstARM32Vcvt::create(Func, Dest, Src, Variant, Pred));
783 }
Jan Voung86ebec12015-08-09 07:58:35 -0700784 void _vdiv(Variable *Dest, Variable *Src0, Variable *Src1) {
785 Context.insert(InstARM32Vdiv::create(Func, Dest, Src0, Src1));
786 }
John Porto2f5534f2015-09-18 15:59:47 -0700787 void _vcmp(Variable *Src0, Variable *Src1,
788 CondARM32::Cond Pred = CondARM32::AL) {
789 Context.insert(InstARM32Vcmp::create(Func, Src0, Src1, Pred));
790 }
John Portoccea7932015-11-17 04:58:36 -0800791 void _vcmp(Variable *Src0, OperandARM32FlexFpZero *FpZero,
792 CondARM32::Cond Pred = CondARM32::AL) {
793 Context.insert(InstARM32Vcmp::create(Func, Src0, FpZero, Pred));
794 }
John Porto3f6b47d2015-11-19 05:42:59 -0800795 void _veor(Variable *Dest, Variable *Src0, Variable *Src1) {
796 Context.insert(InstARM32Veor::create(Func, Dest, Src0, Src1));
797 }
John Porto2f5534f2015-09-18 15:59:47 -0700798 void _vmrs(CondARM32::Cond Pred = CondARM32::AL) {
799 Context.insert(InstARM32Vmrs::create(Func, Pred));
800 }
John Portoeb13acc2015-12-09 05:10:58 -0800801 void _vmla(Variable *Dest, Variable *Src0, Variable *Src1) {
802 Context.insert(InstARM32Vmla::create(Func, Dest, Src0, Src1));
803 }
804 void _vmls(Variable *Dest, Variable *Src0, Variable *Src1) {
805 Context.insert(InstARM32Vmls::create(Func, Dest, Src0, Src1));
806 }
Jan Voung86ebec12015-08-09 07:58:35 -0700807 void _vmul(Variable *Dest, Variable *Src0, Variable *Src1) {
808 Context.insert(InstARM32Vmul::create(Func, Dest, Src0, Src1));
809 }
810 void _vsqrt(Variable *Dest, Variable *Src,
811 CondARM32::Cond Pred = CondARM32::AL) {
812 Context.insert(InstARM32Vsqrt::create(Func, Dest, Src, Pred));
813 }
814 void _vsub(Variable *Dest, Variable *Src0, Variable *Src1) {
815 Context.insert(InstARM32Vsub::create(Func, Dest, Src0, Src1));
816 }
Jan Voungb2d50842015-05-12 09:53:50 -0700817
John Portof4198542015-11-20 14:17:23 -0800818 // Iterates over the CFG and determines the maximum outgoing stack arguments
John Porto614140e2015-11-23 11:43:13 -0800819 // bytes. This information is later used during addProlog() to pre-allocate
John Portof4198542015-11-20 14:17:23 -0800820 // the outargs area.
821 // TODO(jpp): This could live in the Parser, if we provided a Target-specific
822 // method that the Parser could call.
823 void findMaxStackOutArgsSize();
824
John Porto866b6b12015-12-03 09:45:31 -0800825 /// Returns true if the given Offset can be represented in a Load/Store Mem
826 /// Operand.
John Portof5f02f72015-11-09 14:52:40 -0800827 bool isLegalMemOffset(Type Ty, int32_t Offset) const;
John Porto866b6b12015-12-03 09:45:31 -0800828
829 void postLowerLegalization();
830
John Porto52b51572015-12-05 14:16:25 -0800831 /// Sandboxer defines methods for ensuring that "dangerous" operations are
832 /// masked during sandboxed code emission. For regular, non-sandboxed code
833 /// emission, its methods are simple pass-through methods.
834 ///
835 /// The Sandboxer also emits BundleLock/BundleUnlock pseudo-instructions
836 /// in the constructor/destructor during sandboxed code emission. Therefore,
837 /// it is a bad idea to create an object of this type and "keep it around."
838 /// The recommended usage is:
839 ///
840 /// AutoSandboxing(this).<<operation>>(...);
841 ///
842 /// This usage ensures that no other instructions are inadvertently added to
843 /// the bundle.
844 class Sandboxer {
845 Sandboxer() = delete;
846 Sandboxer(const Sandboxer &) = delete;
847 Sandboxer &operator=(const Sandboxer &) = delete;
848
849 public:
850 explicit Sandboxer(
851 TargetARM32 *Target,
852 InstBundleLock::Option BundleOption = InstBundleLock::Opt_None);
853 ~Sandboxer();
854
855 /// Increments sp:
856 ///
857 /// add sp, sp, AddAmount
858 /// bic sp, sp, 0xc0000000
859 ///
860 /// (for the rationale, see the ARM 32-bit Sandbox Specification.)
861 void add_sp(Operand *AddAmount);
862
863 /// Emits code to align sp to the specified alignment:
864 ///
865 /// bic/and sp, sp, Alignment
866 /// bic, sp, sp, 0xc0000000
867 void align_sp(size_t Alignment);
868
869 /// Emits a call instruction. If CallTarget is a Variable, it emits
870 ///
871 /// bic CallTarget, CallTarget, 0xc000000f
872 /// bl CallTarget
873 ///
874 /// Otherwise, it emits
875 ///
876 /// bl CallTarget
877 ///
878 /// Note: in sandboxed code calls are always emitted in addresses 12 mod 16.
879 InstARM32Call *bl(Variable *ReturnReg, Operand *CallTarget);
880
881 /// Emits a load:
882 ///
883 /// bic rBase, rBase, 0xc0000000
884 /// ldr rDest, [rBase, #Offset]
885 ///
886 /// Exception: if rBase is r9 or sp, then the load is emitted as:
887 ///
888 /// ldr rDest, [rBase, #Offset]
889 ///
890 /// because the NaCl ARM 32-bit Sandbox Specification guarantees they are
891 /// always valid.
892 void ldr(Variable *Dest, OperandARM32Mem *Mem, CondARM32::Cond Pred);
893
894 /// Emits a load exclusive:
895 ///
896 /// bic rBase, rBase, 0xc0000000
897 /// ldrex rDest, [rBase]
898 ///
899 /// Exception: if rBase is r9 or sp, then the load is emitted as:
900 ///
901 /// ldrex rDest, [rBase]
902 ///
903 /// because the NaCl ARM 32-bit Sandbox Specification guarantees they are
904 /// always valid.
905 void ldrex(Variable *Dest, OperandARM32Mem *Mem, CondARM32::Cond Pred);
906
907 /// Resets sp to Src:
908 ///
909 /// mov sp, Src
910 /// bic sp, sp, 0xc0000000
911 void reset_sp(Variable *Src);
912
913 /// Emits code to return from a function:
914 ///
915 /// bic lr, lr, 0xc000000f
916 /// bx lr
917 void ret(Variable *RetAddr, Variable *RetValue);
918
919 /// Emits a store:
920 ///
921 /// bic rBase, rBase, 0xc0000000
922 /// str rSrc, [rBase, #Offset]
923 ///
924 /// Exception: if rBase is r9 or sp, then the store is emitted as:
925 ///
926 /// str rDest, [rBase, #Offset]
927 ///
928 /// because the NaCl ARM 32-bit Sandbox Specification guarantees they are
929 /// always valid.
930 void str(Variable *Src, OperandARM32Mem *Mem, CondARM32::Cond Pred);
931
932 /// Emits a store exclusive:
933 ///
934 /// bic rBase, rBase, 0xc0000000
935 /// strex rDest, rSrc, [rBase]
936 ///
937 /// Exception: if rBase is r9 or sp, then the store is emitted as:
938 ///
939 /// strex rDest, rSrc, [rBase]
940 ///
941 /// because the NaCl ARM 32-bit Sandbox Specification guarantees they are
942 /// always valid.
943 void strex(Variable *Dest, Variable *Src, OperandARM32Mem *Mem,
944 CondARM32::Cond Pred);
945
946 /// Decrements sp:
947 ///
948 /// sub sp, sp, SubAmount
949 /// bic sp, sp, 0xc0000000
950 void sub_sp(Operand *SubAmount);
951
952 private:
953 TargetARM32 *Target;
954 };
955
John Porto866b6b12015-12-03 09:45:31 -0800956 class PostLoweringLegalizer {
957 PostLoweringLegalizer() = delete;
958 PostLoweringLegalizer(const PostLoweringLegalizer &) = delete;
959 PostLoweringLegalizer &operator=(const PostLoweringLegalizer &) = delete;
960
961 public:
962 explicit PostLoweringLegalizer(TargetARM32 *Target)
963 : Target(Target), StackOrFrameReg(Target->getPhysicalRegister(
964 Target->getFrameOrStackReg())) {}
965
966 void resetTempBaseIfClobberedBy(const Inst *Instr);
967
968 // Ensures that the TempBase register held by the this legalizer (if any) is
969 // assigned to IP.
970 void assertNoTempOrAssignedToIP() const {
971 assert(TempBaseReg == nullptr ||
972 TempBaseReg->getRegNum() == Target->getReservedTmpReg());
973 }
974
975 // Legalizes Mem. if Mem.Base is a Reamaterializable variable, Mem.Offset is
976 // fixed up.
977 OperandARM32Mem *legalizeMemOperand(OperandARM32Mem *Mem,
978 bool AllowOffsets = true);
979
980 /// Legalizes Mov if its Source (or Destination) is a spilled Variable, or
981 /// if its Source is a Rematerializable variable (this form is used in lieu
982 /// of lea, which is not available in ARM.)
983 ///
984 /// Moves to memory become store instructions, and moves from memory, loads.
985 void legalizeMov(InstARM32Mov *Mov);
986
987 private:
988 /// Creates a new Base register centered around [Base, +/- Offset].
989 Variable *newBaseRegister(Variable *Base, int32_t Offset,
990 int32_t ScratchRegNum);
991
992 /// Creates a new, legal OperandARM32Mem for accessing Base + Offset.
993 /// The returned mem operand is a legal operand for accessing memory that is
994 /// of type Ty.
995 ///
996 /// If [Base, #Offset] is encodable, then the method returns a Mem operand
997 /// expressing it. Otherwise,
998 ///
999 /// if [TempBaseReg, #Offset-TempBaseOffset] is a valid memory operand, the
1000 /// method will return that. Otherwise,
1001 ///
1002 /// a new base register ip=Base+Offset is created, and the method returns a
1003 /// memory operand expressing [ip, #0].
1004 OperandARM32Mem *createMemOperand(Type Ty, Variable *Base, int32_t Offset,
1005 bool AllowOffsets = true);
1006 TargetARM32 *const Target;
1007 Variable *const StackOrFrameReg;
1008 Variable *TempBaseReg = nullptr;
1009 int32_t TempBaseOffset = 0;
1010 };
Jan Voung28068ad2015-07-31 12:58:46 -07001011
John Porto52b51572015-12-05 14:16:25 -08001012 const bool NeedSandboxing;
Jan Voung6ec369e2015-06-30 11:03:15 -07001013 TargetARM32Features CPUFeatures;
Jim Stichnotheafb56c2015-06-22 10:35:22 -07001014 bool UsesFramePointer = false;
1015 bool NeedsStackAlignment = false;
1016 bool MaybeLeafFunc = true;
1017 size_t SpillAreaSizeBytes = 0;
John Porto614140e2015-11-23 11:43:13 -08001018 size_t FixedAllocaSizeBytes = 0;
1019 size_t FixedAllocaAlignBytes = 0;
1020 bool PrologEmitsFixedAllocas = false;
John Portof4198542015-11-20 14:17:23 -08001021 uint32_t MaxOutArgsSizeBytes = 0;
John Portobb0a5fe2015-09-04 11:23:41 -07001022 // TODO(jpp): std::array instead of array.
Jim Stichnothc59288b2015-11-09 11:38:40 -08001023 static llvm::SmallBitVector TypeToRegisterSet[RCARM32_NUM];
Jim Stichnoth94844f12015-11-04 16:06:16 -08001024 static llvm::SmallBitVector RegisterAliases[RegARM32::Reg_NUM];
1025 static llvm::SmallBitVector ScratchRegs;
Jan Voungb36ad9b2015-04-21 17:01:49 -07001026 llvm::SmallBitVector RegsUsed;
1027 VarList PhysicalRegisters[IceType_NUM];
John Portoeb13acc2015-12-09 05:10:58 -08001028 VarList PreservedGPRs;
1029 VarList PreservedSRegs;
Jan Voungb36ad9b2015-04-21 17:01:49 -07001030
Andrew Scull9612d322015-07-06 14:53:25 -07001031 /// Helper class that understands the Calling Convention and register
1032 /// assignments. The first few integer type parameters can use r0-r3,
1033 /// regardless of their position relative to the floating-point/vector
John Porto385351b2015-09-16 16:11:10 -07001034 /// arguments in the argument list. Floating-point and vector arguments
1035 /// can use q0-q3 (aka d0-d7, s0-s15). For more information on the topic,
1036 /// see the ARM Architecture Procedure Calling Standards (AAPCS).
Andrew Scull9612d322015-07-06 14:53:25 -07001037 ///
John Porto385351b2015-09-16 16:11:10 -07001038 /// Technically, arguments that can start with registers but extend beyond the
1039 /// available registers can be split between the registers and the stack.
1040 /// However, this is typically for passing GPR structs by value, and PNaCl
1041 /// transforms expand this out.
1042 ///
1043 /// At (public) function entry, the stack must be 8-byte aligned.
Jan Voungb0a8c242015-06-18 15:00:14 -07001044 class CallingConv {
1045 CallingConv(const CallingConv &) = delete;
1046 CallingConv &operator=(const CallingConv &) = delete;
1047
1048 public:
John Porto2187c842015-12-16 07:48:25 -08001049 CallingConv();
Jan Voungb0a8c242015-06-18 15:00:14 -07001050 ~CallingConv() = default;
1051
John Porto2187c842015-12-16 07:48:25 -08001052 /// argInGPR returns true if there is a GPR available for the requested
1053 /// type, and false otherwise. If it returns true, Reg is set to the
1054 /// appropriate register number. Note that, when Ty == IceType_i64, Reg will
1055 /// be an I64 register pair.
1056 bool argInGPR(Type Ty, int32_t *Reg);
Jan Voungb0a8c242015-06-18 15:00:14 -07001057
John Porto2187c842015-12-16 07:48:25 -08001058 /// argInVFP is to floating-point/vector types what argInGPR is for integer
1059 /// types.
1060 bool argInVFP(Type Ty, int32_t *Reg);
Jan Voungb0a8c242015-06-18 15:00:14 -07001061
1062 private:
John Porto2187c842015-12-16 07:48:25 -08001063 void discardUnavailableGPRsAndTheirAliases(CfgVector<SizeT> *Regs);
1064 llvm::SmallBitVector GPRegsUsed;
1065 CfgVector<SizeT> GPRArgs;
1066 CfgVector<SizeT> I64Args;
1067
1068 void discardUnavailableVFPRegs(CfgVector<SizeT> *Regs);
1069 llvm::SmallBitVector VFPRegsUsed;
1070 CfgVector<SizeT> FP32Args;
1071 CfgVector<SizeT> FP64Args;
1072 CfgVector<SizeT> Vec128Args;
Jan Voungb0a8c242015-06-18 15:00:14 -07001073 };
1074
Jan Voungb36ad9b2015-04-21 17:01:49 -07001075private:
Jim Stichnothe587d942015-06-22 15:49:04 -07001076 ~TargetARM32() override = default;
John Porto4a5e6d02015-11-04 09:32:55 -08001077
John Portof5f02f72015-11-09 14:52:40 -08001078 OperandARM32Mem *formAddressingMode(Type Ty, Cfg *Func, const Inst *LdSt,
1079 Operand *Base);
1080
John Portoc39ec102015-12-01 13:00:43 -08001081 void postambleCtpop64(const InstCall *Instr);
1082 void preambleDivRem(const InstCall *Instr);
1083 std::unordered_map<Operand *, void (TargetARM32::*)(const InstCall *Inst)>
1084 ARM32HelpersPreamble;
1085 std::unordered_map<Operand *, void (TargetARM32::*)(const InstCall *Inst)>
1086 ARM32HelpersPostamble;
1087
John Portoeb13acc2015-12-09 05:10:58 -08001088 class ComputationTracker {
John Porto4a5e6d02015-11-04 09:32:55 -08001089 public:
John Portoeb13acc2015-12-09 05:10:58 -08001090 ComputationTracker() = default;
1091 ~ComputationTracker() = default;
John Porto4a5e6d02015-11-04 09:32:55 -08001092
1093 void forgetProducers() { KnownComputations.clear(); }
1094 void recordProducers(CfgNode *Node);
1095
1096 const Inst *getProducerOf(const Operand *Opnd) const {
1097 auto *Var = llvm::dyn_cast<Variable>(Opnd);
1098 if (Var == nullptr) {
1099 return nullptr;
1100 }
1101
1102 auto Iter = KnownComputations.find(Var->getIndex());
1103 if (Iter == KnownComputations.end()) {
1104 return nullptr;
1105 }
1106
1107 return Iter->second.Instr;
1108 }
1109
1110 void dump(const Cfg *Func) const {
1111 if (!BuildDefs::dump() || !Func->isVerbose(IceV_Folding))
1112 return;
1113 OstreamLocker L(Func->getContext());
1114 Ostream &Str = Func->getContext()->getStrDump();
John Porto7b3d9cb2015-11-11 14:26:57 -08001115 Str << "foldable producer:\n";
John Porto4a5e6d02015-11-04 09:32:55 -08001116 for (const auto &Computation : KnownComputations) {
1117 Str << " ";
1118 Computation.second.Instr->dump(Func);
1119 Str << "\n";
1120 }
1121 Str << "\n";
1122 }
1123
1124 private:
John Portoeb13acc2015-12-09 05:10:58 -08001125 class ComputationEntry {
John Porto4a5e6d02015-11-04 09:32:55 -08001126 public:
John Portoeb13acc2015-12-09 05:10:58 -08001127 ComputationEntry(Inst *I, Type Ty) : Instr(I), ComputationType(Ty) {}
John Porto4a5e6d02015-11-04 09:32:55 -08001128 Inst *const Instr;
1129 // Boolean folding is disabled for variables whose live range is multi
1130 // block. We conservatively initialize IsLiveOut to true, and set it to
1131 // false once we find the end of the live range for the variable defined
1132 // by this instruction. If liveness analysis is not performed (e.g., in
1133 // Om1 mode) IsLiveOut will never be set to false, and folding will be
1134 // disabled.
1135 bool IsLiveOut = true;
John Porto7b3d9cb2015-11-11 14:26:57 -08001136 int32_t NumUses = 0;
John Portoeb13acc2015-12-09 05:10:58 -08001137 Type ComputationType;
John Porto4a5e6d02015-11-04 09:32:55 -08001138 };
1139
John Portoeb13acc2015-12-09 05:10:58 -08001140 // ComputationMap maps a Variable number to a payload identifying which
1141 // instruction defined it.
1142 using ComputationMap = std::unordered_map<SizeT, ComputationEntry>;
1143 ComputationMap KnownComputations;
John Porto4a5e6d02015-11-04 09:32:55 -08001144 };
1145
John Portoeb13acc2015-12-09 05:10:58 -08001146 ComputationTracker Computations;
John Porto614140e2015-11-23 11:43:13 -08001147
1148 // AllowTemporaryWithNoReg indicates if TargetARM32::makeReg() can be invoked
1149 // without specifying a physical register. This is needed for creating unbound
1150 // temporaries during Ice -> ARM lowering, but before register allocation.
John Porto98cc08c2015-11-24 12:30:01 -08001151 // This a safe-guard that no unbound temporaries are created during the
1152 // legalization post-passes.
John Porto614140e2015-11-23 11:43:13 -08001153 bool AllowTemporaryWithNoReg = true;
1154 // ForbidTemporaryWithoutReg is a RAII class that manages
1155 // AllowTemporaryWithNoReg.
1156 class ForbidTemporaryWithoutReg {
1157 ForbidTemporaryWithoutReg() = delete;
John Porto98cc08c2015-11-24 12:30:01 -08001158 ForbidTemporaryWithoutReg(const ForbidTemporaryWithoutReg &) = delete;
1159 ForbidTemporaryWithoutReg &
1160 operator=(const ForbidTemporaryWithoutReg &) = delete;
John Porto614140e2015-11-23 11:43:13 -08001161
1162 public:
1163 explicit ForbidTemporaryWithoutReg(TargetARM32 *Target) : Target(Target) {
1164 Target->AllowTemporaryWithNoReg = false;
1165 }
1166 ~ForbidTemporaryWithoutReg() { Target->AllowTemporaryWithNoReg = true; }
1167
1168 private:
1169 TargetARM32 *const Target;
1170 };
Jan Voungb36ad9b2015-04-21 17:01:49 -07001171};
1172
John Porto0f86d032015-06-15 07:44:27 -07001173class TargetDataARM32 final : public TargetDataLowering {
Jan Voungb36ad9b2015-04-21 17:01:49 -07001174 TargetDataARM32() = delete;
1175 TargetDataARM32(const TargetDataARM32 &) = delete;
1176 TargetDataARM32 &operator=(const TargetDataARM32 &) = delete;
1177
1178public:
Jan Voungfb792842015-06-11 15:27:50 -07001179 static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) {
1180 return std::unique_ptr<TargetDataLowering>(new TargetDataARM32(Ctx));
Jan Voungb36ad9b2015-04-21 17:01:49 -07001181 }
1182
John Porto8b1a7052015-06-17 13:20:08 -07001183 void lowerGlobals(const VariableDeclarationList &Vars,
1184 const IceString &SectionSuffix) override;
John Porto0f86d032015-06-15 07:44:27 -07001185 void lowerConstants() override;
Andrew Scull86df4e92015-07-30 13:54:44 -07001186 void lowerJumpTables() override;
Jan Voungb36ad9b2015-04-21 17:01:49 -07001187
1188protected:
1189 explicit TargetDataARM32(GlobalContext *Ctx);
1190
1191private:
Jim Stichnothe587d942015-06-22 15:49:04 -07001192 ~TargetDataARM32() override = default;
Jan Voungb36ad9b2015-04-21 17:01:49 -07001193};
1194
Jan Voungfb792842015-06-11 15:27:50 -07001195class TargetHeaderARM32 final : public TargetHeaderLowering {
1196 TargetHeaderARM32() = delete;
1197 TargetHeaderARM32(const TargetHeaderARM32 &) = delete;
1198 TargetHeaderARM32 &operator=(const TargetHeaderARM32 &) = delete;
1199
1200public:
1201 static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) {
1202 return std::unique_ptr<TargetHeaderLowering>(new TargetHeaderARM32(Ctx));
1203 }
1204
John Porto0f86d032015-06-15 07:44:27 -07001205 void lower() override;
Jan Voungfb792842015-06-11 15:27:50 -07001206
1207protected:
1208 explicit TargetHeaderARM32(GlobalContext *Ctx);
1209
1210private:
1211 ~TargetHeaderARM32() = default;
Jan Voung6ec369e2015-06-30 11:03:15 -07001212
1213 TargetARM32Features CPUFeatures;
Jan Voungfb792842015-06-11 15:27:50 -07001214};
1215
Jan Voungb36ad9b2015-04-21 17:01:49 -07001216} // end of namespace Ice
1217
1218#endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H