blob: d938f79dfb958c7da9fb31c86f520819943242ab [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
John Portoa1cdd572016-03-01 15:19:29 -080025#include <utility>
26
Jan Voungb36ad9b2015-04-21 17:01:49 -070027namespace Ice {
John Porto4a566862016-01-04 09:33:41 -080028namespace ARM32 {
Jan Voungb36ad9b2015-04-21 17:01:49 -070029
Jan Voung6ec369e2015-06-30 11:03:15 -070030// Class encapsulating ARM cpu features / instruction set.
31class TargetARM32Features {
32 TargetARM32Features() = delete;
33 TargetARM32Features(const TargetARM32Features &) = delete;
34 TargetARM32Features &operator=(const TargetARM32Features &) = delete;
35
36public:
37 explicit TargetARM32Features(const ClFlags &Flags);
38
39 enum ARM32InstructionSet {
40 Begin,
41 // Neon is the PNaCl baseline instruction set.
42 Neon = Begin,
43 HWDivArm, // HW divide in ARM mode (not just Thumb mode).
44 End
45 };
46
47 bool hasFeature(ARM32InstructionSet I) const { return I <= InstructionSet; }
48
49private:
50 ARM32InstructionSet InstructionSet = ARM32InstructionSet::Begin;
51};
52
53// The target lowering logic for ARM32.
Jan Voungb36ad9b2015-04-21 17:01:49 -070054class TargetARM32 : public TargetLowering {
55 TargetARM32() = delete;
56 TargetARM32(const TargetARM32 &) = delete;
57 TargetARM32 &operator=(const TargetARM32 &) = delete;
58
59public:
Karl Schimpf5403f5d2016-01-15 11:07:46 -080060 static void staticInit(GlobalContext *Ctx);
Jim Stichnoth467ffe52016-03-29 15:01:06 -070061
62 static bool shouldBePooled(const Constant *C) {
63 if (auto *ConstDouble = llvm::dyn_cast<ConstantDouble>(C)) {
64 return !Utils::isPositiveZero(ConstDouble->getValue());
65 }
66 if (llvm::isa<ConstantFloat>(C))
67 return true;
68 return false;
69 }
70
Nicolas Capens32f9cce2016-10-19 01:24:27 -040071 static ::Ice::Type getPointerType() { return ::Ice::IceType_i32; }
72
Jan Voungb36ad9b2015-04-21 17:01:49 -070073 // TODO(jvoung): return a unique_ptr.
John Porto53611e22015-12-30 07:30:10 -080074 static std::unique_ptr<::Ice::TargetLowering> create(Cfg *Func) {
75 return makeUnique<TargetARM32>(Func);
76 }
77
78 std::unique_ptr<::Ice::Assembler> createAssembler() const override {
Nicolas Capens95342282021-07-06 12:45:02 -040079 return makeUnique<ARM32::AssemblerARM32>();
John Porto53611e22015-12-30 07:30:10 -080080 }
Jan Voungb36ad9b2015-04-21 17:01:49 -070081
John Porto4a5e6d02015-11-04 09:32:55 -080082 void initNodeForLowering(CfgNode *Node) override {
John Portoeb13acc2015-12-09 05:10:58 -080083 Computations.forgetProducers();
84 Computations.recordProducers(Node);
85 Computations.dump(Func);
John Porto4a5e6d02015-11-04 09:32:55 -080086 }
87
Jan Voungb36ad9b2015-04-21 17:01:49 -070088 void translateOm1() override;
89 void translateO2() override;
90 bool doBranchOpt(Inst *I, const CfgNode *NextNode) override;
91
92 SizeT getNumRegisters() const override { return RegARM32::Reg_NUM; }
Jim Stichnoth8aa39662016-02-10 11:20:30 -080093 Variable *getPhysicalRegister(RegNumT RegNum,
94 Type Ty = IceType_void) override;
Jim Stichnoth467ffe52016-03-29 15:01:06 -070095 const char *getRegName(RegNumT RegNum, Type Ty) const override;
John Portoe82b5602016-02-24 15:58:55 -080096 SmallBitVector getRegisterSet(RegSetMask Include,
97 RegSetMask Exclude) const override;
98 const SmallBitVector &
Jim Stichnothc59288b2015-11-09 11:38:40 -080099 getRegistersForVariable(const Variable *Var) const override {
100 RegClass RC = Var->getRegClass();
Eric Holk658bae22016-02-08 15:22:18 -0800101 switch (RC) {
102 default:
103 assert(RC < RC_Target);
104 return TypeToRegisterSet[RC];
Nicolas Capens846da562021-07-06 10:55:20 -0400105 case (RegClass)RegARM32::RCARM32_QtoS:
Eric Holk658bae22016-02-08 15:22:18 -0800106 return TypeToRegisterSet[RC];
107 }
Jan Voungb36ad9b2015-04-21 17:01:49 -0700108 }
John Portoe82b5602016-02-24 15:58:55 -0800109 const SmallBitVector &
Jim Stichnothb40595a2016-01-29 06:14:31 -0800110 getAllRegistersForVariable(const Variable *Var) const override {
111 RegClass RC = Var->getRegClass();
Eric Holk658bae22016-02-08 15:22:18 -0800112 assert((RegARM32::RegClassARM32)RC < RegARM32::RCARM32_NUM);
Jim Stichnothb40595a2016-01-29 06:14:31 -0800113 return TypeToRegisterSetUnfiltered[RC];
114 }
John Portoe82b5602016-02-24 15:58:55 -0800115 const SmallBitVector &getAliasesForRegister(RegNumT Reg) const override {
John Portobb0a5fe2015-09-04 11:23:41 -0700116 return RegisterAliases[Reg];
117 }
Jan Voungb36ad9b2015-04-21 17:01:49 -0700118 bool hasFramePointer() const override { return UsesFramePointer; }
David Sehre39d0ca2015-11-06 11:25:41 -0800119 void setHasFramePointer() override { UsesFramePointer = true; }
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800120 RegNumT getStackReg() const override { return RegARM32::Reg_sp; }
121 RegNumT getFrameReg() const override { return RegARM32::Reg_fp; }
122 RegNumT getFrameOrStackReg() const override {
David Sehr2f3b8ec2015-11-16 16:51:39 -0800123 return UsesFramePointer ? getFrameReg() : getStackReg();
Jan Voungb36ad9b2015-04-21 17:01:49 -0700124 }
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800125 RegNumT getReservedTmpReg() const { return RegARM32::Reg_ip; }
Jan Voung28068ad2015-07-31 12:58:46 -0700126
Jan Voungb36ad9b2015-04-21 17:01:49 -0700127 size_t typeWidthInBytesOnStack(Type Ty) const override {
Andrew Scull57e12682015-09-16 11:30:19 -0700128 // Round up to the next multiple of 4 bytes. In particular, i1, i8, and i16
129 // are rounded up to 4 bytes.
Jan Voungb36ad9b2015-04-21 17:01:49 -0700130 return (typeWidthInBytes(Ty) + 3) & ~3;
131 }
David Sehre39d0ca2015-11-06 11:25:41 -0800132 uint32_t getStackAlignment() const override;
David Sehr2f3b8ec2015-11-16 16:51:39 -0800133 void reserveFixedAllocaArea(size_t Size, size_t Align) override {
John Porto614140e2015-11-23 11:43:13 -0800134 FixedAllocaSizeBytes = Size;
135 assert(llvm::isPowerOf2_32(Align));
136 FixedAllocaAlignBytes = Align;
137 PrologEmitsFixedAllocas = true;
David Sehr2f3b8ec2015-11-16 16:51:39 -0800138 }
139 int32_t getFrameFixedAllocaOffset() const override {
John Porto614140e2015-11-23 11:43:13 -0800140 return FixedAllocaSizeBytes - (SpillAreaSizeBytes - MaxOutArgsSizeBytes);
David Sehr2f3b8ec2015-11-16 16:51:39 -0800141 }
John Porto614140e2015-11-23 11:43:13 -0800142 uint32_t maxOutArgsSizeBytes() const override { return MaxOutArgsSizeBytes; }
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700143
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700144 bool shouldSplitToVariable64On32(Type Ty) const override {
145 return Ty == IceType_i64;
146 }
147
Andrew Scull87f80c12015-07-20 10:19:16 -0700148 // TODO(ascull): what size is best for ARM?
149 SizeT getMinJumpTableSize() const override { return 3; }
Andrew Scull86df4e92015-07-30 13:54:44 -0700150 void emitJumpTable(const Cfg *Func,
151 const InstJumpTable *JumpTable) const override;
Andrew Scull87f80c12015-07-20 10:19:16 -0700152
Jan Voungb36ad9b2015-04-21 17:01:49 -0700153 void emitVariable(const Variable *Var) const override;
Jan Voung76bb0be2015-05-14 09:26:19 -0700154
Jan Voung76bb0be2015-05-14 09:26:19 -0700155 void emit(const ConstantUndef *C) const final;
156 void emit(const ConstantInteger32 *C) const final;
157 void emit(const ConstantInteger64 *C) const final;
158 void emit(const ConstantFloat *C) const final;
159 void emit(const ConstantDouble *C) const final;
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800160 void emit(const ConstantRelocatable *C) const final;
Jan Voung76bb0be2015-05-14 09:26:19 -0700161
Jan Voungb36ad9b2015-04-21 17:01:49 -0700162 void lowerArguments() override;
163 void addProlog(CfgNode *Node) override;
164 void addEpilog(CfgNode *Node) override;
165
Jan Voungb3401d22015-05-18 09:38:21 -0700166 Operand *loOperand(Operand *Operand);
167 Operand *hiOperand(Operand *Operand);
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700168 void finishArgumentLowering(Variable *Arg, Variable *FramePtr,
John Porto3f6b47d2015-11-19 05:42:59 -0800169 size_t BasicFrameOffset, size_t *InArgsSizeBytes);
Jan Voungb3401d22015-05-18 09:38:21 -0700170
Jan Voung6ec369e2015-06-30 11:03:15 -0700171 bool hasCPUFeature(TargetARM32Features::ARM32InstructionSet I) const {
172 return CPUFeatures.hasFeature(I);
173 }
John Portoccea7932015-11-17 04:58:36 -0800174
175 enum OperandLegalization {
John Portoccea7932015-11-17 04:58:36 -0800176 Legal_Reg = 1 << 0, /// physical register, not stack location
177 Legal_Flex = 1 << 1, /// A flexible operand2, which can hold rotated small
178 /// immediates, shifted registers, or modified fp imm.
179 Legal_Mem = 1 << 2, /// includes [r0, r1 lsl #2] as well as [sp, #12]
John Porto866b6b12015-12-03 09:45:31 -0800180 Legal_Rematerializable = 1 << 3,
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800181 Legal_Default = ~Legal_Rematerializable,
John Portoccea7932015-11-17 04:58:36 -0800182 };
183
184 using LegalMask = uint32_t;
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800185 Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT());
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800186 Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800187 RegNumT RegNum = RegNumT());
188 Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT());
John Portoccea7932015-11-17 04:58:36 -0800189
John Porto2758bb02015-11-17 14:31:25 -0800190 OperandARM32ShAmtImm *shAmtImm(uint32_t ShAmtImm) const {
191 assert(ShAmtImm < 32);
192 return OperandARM32ShAmtImm::create(
193 Func,
194 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(ShAmtImm & 0x1F)));
195 }
196
John Portoccea7932015-11-17 04:58:36 -0800197 GlobalContext *getCtx() const { return Ctx; }
Jan Voungd062f732015-06-15 17:17:31 -0700198
Jan Voungb36ad9b2015-04-21 17:01:49 -0700199protected:
200 explicit TargetARM32(Cfg *Func);
201
202 void postLower() override;
203
John Porto7b3d9cb2015-11-11 14:26:57 -0800204 enum SafeBoolChain {
205 SBC_No,
206 SBC_Yes,
207 };
208
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800209 void lowerAlloca(const InstAlloca *Instr) override;
210 SafeBoolChain lowerInt1Arithmetic(const InstArithmetic *Instr);
John Portoccea7932015-11-17 04:58:36 -0800211 void lowerInt64Arithmetic(InstArithmetic::OpKind Op, Variable *Dest,
212 Operand *Src0, Operand *Src1);
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800213 void lowerArithmetic(const InstArithmetic *Instr) override;
214 void lowerAssign(const InstAssign *Instr) override;
215 void lowerBr(const InstBr *Instr) override;
216 void lowerCall(const InstCall *Instr) override;
217 void lowerCast(const InstCast *Instr) override;
218 void lowerExtractElement(const InstExtractElement *Instr) override;
John Porto7b3d9cb2015-11-11 14:26:57 -0800219
220 /// CondWhenTrue is a helper type returned by every method in the lowering
221 /// that emits code to set the condition codes.
222 class CondWhenTrue {
223 public:
224 explicit CondWhenTrue(CondARM32::Cond T0,
225 CondARM32::Cond T1 = CondARM32::kNone)
226 : WhenTrue0(T0), WhenTrue1(T1) {
227 assert(T1 == CondARM32::kNone || T0 != CondARM32::kNone);
228 assert(T1 != T0 || T0 == CondARM32::kNone);
229 }
230 CondARM32::Cond WhenTrue0;
231 CondARM32::Cond WhenTrue1;
232
233 /// invert returns a new object with WhenTrue0 and WhenTrue1 inverted.
234 CondWhenTrue invert() const {
235 switch (WhenTrue0) {
236 default:
237 if (WhenTrue1 == CondARM32::kNone)
238 return CondWhenTrue(InstARM32::getOppositeCondition(WhenTrue0));
239 return CondWhenTrue(InstARM32::getOppositeCondition(WhenTrue0),
240 InstARM32::getOppositeCondition(WhenTrue1));
241 case CondARM32::AL:
242 return CondWhenTrue(CondARM32::kNone);
243 case CondARM32::kNone:
244 return CondWhenTrue(CondARM32::AL);
245 }
246 }
247 };
248
249 CondWhenTrue lowerFcmpCond(const InstFcmp *Instr);
John Porto4a5e6d02015-11-04 09:32:55 -0800250 void lowerFcmp(const InstFcmp *Instr) override;
John Portoccea7932015-11-17 04:58:36 -0800251 CondWhenTrue lowerInt8AndInt16IcmpCond(InstIcmp::ICond Condition,
252 Operand *Src0, Operand *Src1);
253 CondWhenTrue lowerInt32IcmpCond(InstIcmp::ICond Condition, Operand *Src0,
254 Operand *Src1);
255 CondWhenTrue lowerInt64IcmpCond(InstIcmp::ICond Condition, Operand *Src0,
256 Operand *Src1);
John Porto4b6e4b42016-02-17 05:00:59 -0800257 CondWhenTrue lowerIcmpCond(InstIcmp::ICond Condition, Operand *Src0,
258 Operand *Src1);
John Porto7b3d9cb2015-11-11 14:26:57 -0800259 CondWhenTrue lowerIcmpCond(const InstIcmp *Instr);
John Porto4a5e6d02015-11-04 09:32:55 -0800260 void lowerIcmp(const InstIcmp *Instr) override;
John Porto4b6e4b42016-02-17 05:00:59 -0800261 /// Emits the basic sequence for lower-linked/store-exclusive loops:
262 ///
263 /// retry:
264 /// ldrex tmp, [Addr]
265 /// StoreValue = Operation(tmp)
266 /// strexCond success, StoreValue, [Addr]
267 /// cmpCond success, #0
268 /// bne retry
269 ///
270 /// Operation needs to return which value to strex in Addr, it must not change
271 /// the flags if Cond is not AL, and must not emit any instructions that could
272 /// end up writing to memory. Operation also needs to handle fake-defing for
273 /// i64 handling.
274 void
275 lowerLoadLinkedStoreExclusive(Type Ty, Operand *Addr,
276 std::function<Variable *(Variable *)> Operation,
277 CondARM32::Cond Cond = CondARM32::AL);
278 void lowerInt64AtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr,
279 Operand *Val);
John Porto578f1162015-10-06 06:54:42 -0700280 void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr,
281 Operand *Val);
Eric Holk67c7c412016-04-15 13:05:37 -0700282 void lowerBreakpoint(const InstBreakpoint *Instr) override;
Nicolas Capens33a77f72021-02-08 15:04:38 -0500283 void lowerIntrinsic(const InstIntrinsic *Instr) override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800284 void lowerInsertElement(const InstInsertElement *Instr) override;
285 void lowerLoad(const InstLoad *Instr) override;
286 void lowerPhi(const InstPhi *Instr) override;
287 void lowerRet(const InstRet *Instr) override;
288 void lowerSelect(const InstSelect *Instr) override;
John Portoa47c11c2016-04-21 05:53:42 -0700289 void lowerShuffleVector(const InstShuffleVector *Instr) override;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800290 void lowerStore(const InstStore *Instr) override;
291 void lowerSwitch(const InstSwitch *Instr) override;
292 void lowerUnreachable(const InstUnreachable *Instr) override;
Jan Voungb36ad9b2015-04-21 17:01:49 -0700293 void prelowerPhis() override;
John Portof4198542015-11-20 14:17:23 -0800294 uint32_t getCallStackArgumentsSizeBytes(const InstCall *Instr) override;
John Portoc39ec102015-12-01 13:00:43 -0800295 void genTargetHelperCallFor(Inst *Instr) override;
Jan Voungb36ad9b2015-04-21 17:01:49 -0700296 void doAddressOptLoad() override;
297 void doAddressOptStore() override;
Jan Voungb3401d22015-05-18 09:38:21 -0700298
Jan Voungbefd03a2015-06-02 11:03:03 -0700299 OperandARM32Mem *formMemoryOperand(Operand *Ptr, Type Ty);
Jan Voungb3401d22015-05-18 09:38:21 -0700300
John Porto578f1162015-10-06 06:54:42 -0700301 Variable64On32 *makeI64RegPair();
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800302 Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT());
Jan Voungb3401d22015-05-18 09:38:21 -0700303 static Type stackSlotType();
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800304 Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT());
John Porto614140e2015-11-23 11:43:13 -0800305 void alignRegisterPow2(Variable *Reg, uint32_t Align,
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800306 RegNumT TmpRegNum = RegNumT());
Jan Voungb3401d22015-05-18 09:38:21 -0700307
Andrew Scull9612d322015-07-06 14:53:25 -0700308 /// Returns a vector in a register with the given constant entries.
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800309 Variable *makeVectorOfZeros(Type Ty, RegNumT RegNum = RegNumT());
Jan Voungb3401d22015-05-18 09:38:21 -0700310
Andrew Scull57e12682015-09-16 11:30:19 -0700311 // If a divide-by-zero check is needed, inserts a: test; branch .LSKIP; trap;
312 // .LSKIP: <continuation>. If no check is needed nothing is inserted.
Jan Voung6ec369e2015-06-30 11:03:15 -0700313 void div0Check(Type Ty, Operand *SrcLo, Operand *SrcHi);
Andrew Scull8072bae2015-09-14 16:01:26 -0700314 using ExtInstr = void (TargetARM32::*)(Variable *, Variable *,
315 CondARM32::Cond);
316 using DivInstr = void (TargetARM32::*)(Variable *, Variable *, Variable *,
317 CondARM32::Cond);
Jan Voung6ec369e2015-06-30 11:03:15 -0700318 void lowerIDivRem(Variable *Dest, Variable *T, Variable *Src0R, Operand *Src1,
John Portoc39ec102015-12-01 13:00:43 -0800319 ExtInstr ExtFunc, DivInstr DivFunc, bool IsRemainder);
Jan Voung6ec369e2015-06-30 11:03:15 -0700320
Jan Voungf645d852015-07-09 10:35:09 -0700321 void lowerCLZ(Variable *Dest, Variable *ValLo, Variable *ValHi);
322
Andrew Scull57e12682015-09-16 11:30:19 -0700323 // The following are helpers that insert lowered ARM32 instructions with
324 // minimal syntactic overhead, so that the lowering code can look as close to
325 // assembly as practical.
Jan Voung3bfd99a2015-05-22 16:35:25 -0700326 void _add(Variable *Dest, Variable *Src0, Operand *Src1,
327 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800328 Context.insert<InstARM32Add>(Dest, Src0, Src1, Pred);
Jan Voung29719972015-05-19 11:24:51 -0700329 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700330 void _adds(Variable *Dest, Variable *Src0, Operand *Src1,
331 CondARM32::Cond Pred = CondARM32::AL) {
Jan Voung86ebec12015-08-09 07:58:35 -0700332 constexpr bool SetFlags = true;
John Porto1d937a82015-12-17 06:19:34 -0800333 Context.insert<InstARM32Add>(Dest, Src0, Src1, Pred, SetFlags);
John Porto7e6aa5a2016-03-02 15:10:19 -0800334 if (SetFlags) {
335 Context.insert<InstFakeUse>(Dest);
336 }
Jan Voung29719972015-05-19 11:24:51 -0700337 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700338 void _adc(Variable *Dest, Variable *Src0, Operand *Src1,
339 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800340 Context.insert<InstARM32Adc>(Dest, Src0, Src1, Pred);
Jan Voung29719972015-05-19 11:24:51 -0700341 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700342 void _and(Variable *Dest, Variable *Src0, Operand *Src1,
343 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800344 Context.insert<InstARM32And>(Dest, Src0, Src1, Pred);
Jan Voung29719972015-05-19 11:24:51 -0700345 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700346 void _asr(Variable *Dest, Variable *Src0, Operand *Src1,
347 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800348 Context.insert<InstARM32Asr>(Dest, Src0, Src1, Pred);
Jan Voung66c3d5e2015-06-04 17:02:31 -0700349 }
Jan Voung55500db2015-05-26 14:25:40 -0700350 void _bic(Variable *Dest, Variable *Src0, Operand *Src1,
351 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800352 Context.insert<InstARM32Bic>(Dest, Src0, Src1, Pred);
Jan Voung55500db2015-05-26 14:25:40 -0700353 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700354 void _br(CfgNode *TargetTrue, CfgNode *TargetFalse,
355 CondARM32::Cond Condition) {
John Porto1d937a82015-12-17 06:19:34 -0800356 Context.insert<InstARM32Br>(TargetTrue, TargetFalse, Condition);
Jan Voung29719972015-05-19 11:24:51 -0700357 }
John Porto1d937a82015-12-17 06:19:34 -0800358 void _br(CfgNode *Target) { Context.insert<InstARM32Br>(Target); }
Andrew Scullfdc54db2015-06-29 11:21:18 -0700359 void _br(CfgNode *Target, CondARM32::Cond Condition) {
John Porto1d937a82015-12-17 06:19:34 -0800360 Context.insert<InstARM32Br>(Target, Condition);
Andrew Scullfdc54db2015-06-29 11:21:18 -0700361 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700362 void _br(InstARM32Label *Label, CondARM32::Cond Condition) {
John Porto1d937a82015-12-17 06:19:34 -0800363 Context.insert<InstARM32Br>(Label, Condition);
Jan Voung6ec369e2015-06-30 11:03:15 -0700364 }
John Portoccea7932015-11-17 04:58:36 -0800365 void _cmn(Variable *Src0, Operand *Src1,
366 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800367 Context.insert<InstARM32Cmn>(Src0, Src1, Pred);
John Portoccea7932015-11-17 04:58:36 -0800368 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700369 void _cmp(Variable *Src0, Operand *Src1,
370 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800371 Context.insert<InstARM32Cmp>(Src0, Src1, Pred);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700372 }
Jan Voungf645d852015-07-09 10:35:09 -0700373 void _clz(Variable *Dest, Variable *Src0,
374 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800375 Context.insert<InstARM32Clz>(Dest, Src0, Pred);
Jan Voungf645d852015-07-09 10:35:09 -0700376 }
John Porto1d937a82015-12-17 06:19:34 -0800377 void _dmb() { Context.insert<InstARM32Dmb>(); }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700378 void _eor(Variable *Dest, Variable *Src0, Operand *Src1,
379 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800380 Context.insert<InstARM32Eor>(Dest, Src0, Src1, Pred);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700381 }
John Portoba6a67c2015-09-25 15:19:45 -0700382 /// _ldr, for all your memory to Variable data moves. It handles all types
383 /// (integer, floating point, and vectors.) Addr needs to be valid for Dest's
384 /// type (e.g., no immediates for vector loads, and no index registers for fp
385 /// loads.)
Jan Voung3bfd99a2015-05-22 16:35:25 -0700386 void _ldr(Variable *Dest, OperandARM32Mem *Addr,
387 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800388 Context.insert<InstARM32Ldr>(Dest, Addr, Pred);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700389 }
John Porto4b6e4b42016-02-17 05:00:59 -0800390 InstARM32Ldrex *_ldrex(Variable *Dest, OperandARM32Mem *Addr,
391 CondARM32::Cond Pred = CondARM32::AL) {
392 auto *Ldrex = Context.insert<InstARM32Ldrex>(Dest, Addr, Pred);
Jim Stichnothb36757e2015-10-05 13:55:11 -0700393 if (auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest)) {
John Porto1d937a82015-12-17 06:19:34 -0800394 Context.insert<InstFakeDef>(Dest64->getLo(), Dest);
395 Context.insert<InstFakeDef>(Dest64->getHi(), Dest);
Jim Stichnothb36757e2015-10-05 13:55:11 -0700396 }
John Porto4b6e4b42016-02-17 05:00:59 -0800397 return Ldrex;
Jim Stichnothb36757e2015-10-05 13:55:11 -0700398 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700399 void _lsl(Variable *Dest, Variable *Src0, Operand *Src1,
400 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800401 Context.insert<InstARM32Lsl>(Dest, Src0, Src1, Pred);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700402 }
John Portoccea7932015-11-17 04:58:36 -0800403 void _lsls(Variable *Dest, Variable *Src0, Operand *Src1,
404 CondARM32::Cond Pred = CondARM32::AL) {
405 constexpr bool SetFlags = true;
John Porto1d937a82015-12-17 06:19:34 -0800406 Context.insert<InstARM32Lsl>(Dest, Src0, Src1, Pred, SetFlags);
John Porto7e6aa5a2016-03-02 15:10:19 -0800407 if (SetFlags) {
408 Context.insert<InstFakeUse>(Dest);
409 }
John Portoccea7932015-11-17 04:58:36 -0800410 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700411 void _lsr(Variable *Dest, Variable *Src0, Operand *Src1,
412 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800413 Context.insert<InstARM32Lsr>(Dest, Src0, Src1, Pred);
Jan Voung66c3d5e2015-06-04 17:02:31 -0700414 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700415 void _mla(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc,
416 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800417 Context.insert<InstARM32Mla>(Dest, Src0, Src1, Acc, Pred);
Jan Voung29719972015-05-19 11:24:51 -0700418 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700419 void _mls(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc,
420 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800421 Context.insert<InstARM32Mls>(Dest, Src0, Src1, Acc, Pred);
Jan Voung6ec369e2015-06-30 11:03:15 -0700422 }
John Portoba6a67c2015-09-25 15:19:45 -0700423 /// _mov, for all your Variable to Variable data movement needs. It handles
424 /// all types (integer, floating point, and vectors), as well as moves between
425 /// Core and VFP registers. This is not a panacea: you must obey the (weird,
426 /// confusing, non-uniform) rules for data moves in ARM.
427 void _mov(Variable *Dest, Operand *Src0,
428 CondARM32::Cond Pred = CondARM32::AL) {
429 // _mov used to be unique in the sense that it would create a temporary
430 // automagically if Dest was nullptr. It won't do that anymore, so we keep
431 // an assert around just in case there is some untested code path where Dest
432 // is nullptr.
433 assert(Dest != nullptr);
John Porto3f6b47d2015-11-19 05:42:59 -0800434 assert(!llvm::isa<OperandARM32Mem>(Src0));
John Porto1d937a82015-12-17 06:19:34 -0800435 auto *Instr = Context.insert<InstARM32Mov>(Dest, Src0, Pred);
John Portoe0b829f2015-09-28 09:50:48 -0700436
John Portoe0b829f2015-09-28 09:50:48 -0700437 if (Instr->isMultiDest()) {
438 // If Instr is multi-dest, then Dest must be a Variable64On32. We add a
439 // fake-def for Instr.DestHi here.
440 assert(llvm::isa<Variable64On32>(Dest));
John Porto1d937a82015-12-17 06:19:34 -0800441 Context.insert<InstFakeDef>(Instr->getDestHi());
John Portoe0b829f2015-09-28 09:50:48 -0700442 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700443 }
John Porto578f1162015-10-06 06:54:42 -0700444
Jim Stichnoth230d41012015-09-25 17:40:32 -0700445 void _mov_redefined(Variable *Dest, Operand *Src0,
446 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800447 auto *Instr = Context.insert<InstARM32Mov>(Dest, Src0, Pred);
John Portoe0b829f2015-09-28 09:50:48 -0700448 Instr->setDestRedefined();
John Portoe0b829f2015-09-28 09:50:48 -0700449 if (Instr->isMultiDest()) {
450 // If Instr is multi-dest, then Dest must be a Variable64On32. We add a
451 // fake-def for Instr.DestHi here.
452 assert(llvm::isa<Variable64On32>(Dest));
John Porto1d937a82015-12-17 06:19:34 -0800453 Context.insert<InstFakeDef>(Instr->getDestHi());
John Portoe0b829f2015-09-28 09:50:48 -0700454 }
Jan Voungb3401d22015-05-18 09:38:21 -0700455 }
John Porto4a5e6d02015-11-04 09:32:55 -0800456
Karl Schimpff084a572016-02-09 13:09:23 -0800457 void _nop() { Context.insert<InstARM32Nop>(); }
458
Eric Holk658bae22016-02-08 15:22:18 -0800459 // Generates a vmov instruction to extract the given index from a vector
460 // register.
461 void _extractelement(Variable *Dest, Variable *Src0, uint32_t Index,
462 CondARM32::Cond Pred = CondARM32::AL) {
463 Context.insert<InstARM32Extract>(Dest, Src0, Index, Pred);
464 }
465
466 // Generates a vmov instruction to insert a value into the given index of a
467 // vector register.
468 void _insertelement(Variable *Dest, Variable *Src0, uint32_t Index,
469 CondARM32::Cond Pred = CondARM32::AL) {
470 Context.insert<InstARM32Insert>(Dest, Src0, Index, Pred);
471 }
472
John Porto7b3d9cb2015-11-11 14:26:57 -0800473 // --------------------------------------------------------------------------
474 // Begin bool folding machinery.
475 //
476 // There are three types of boolean lowerings handled by this target:
477 //
478 // 1) Boolean expressions leading to a boolean Variable definition
479 // ---------------------------------------------------------------
480 //
481 // Whenever a i1 Variable is live out (i.e., its live range extends beyond
482 // the defining basic block) we do not fold the operation. We instead
483 // materialize (i.e., compute) the variable normally, so that it can be used
484 // when needed. We also materialize i1 values that are not single use to
485 // avoid code duplication. These expressions are not short circuited.
486 //
487 // 2) Boolean expressions leading to a select
488 // ------------------------------------------
489 //
490 // These include boolean chains leading to a select instruction, as well as
491 // i1 Sexts. These boolean expressions are lowered to:
492 //
493 // mov T, <false value>
494 // CC <- eval(Boolean Expression)
495 // movCC T, <true value>
496 //
497 // For Sexts, <false value> is 0, and <true value> is -1.
498 //
499 // 3) Boolean expressions leading to a br i1
500 // -----------------------------------------
501 //
502 // These are the boolean chains leading to a branch. These chains are
503 // short-circuited, i.e.:
504 //
505 // A = or i1 B, C
506 // br i1 A, label %T, label %F
507 //
508 // becomes
509 //
510 // tst B
511 // jne %T
512 // tst B
513 // jne %T
514 // j %F
515 //
516 // and
517 //
518 // A = and i1 B, C
519 // br i1 A, label %T, label %F
520 //
521 // becomes
522 //
523 // tst B
524 // jeq %F
525 // tst B
526 // jeq %F
527 // j %T
528 //
529 // Arbitrarily long chains are short circuited, e.g
530 //
531 // A = or i1 B, C
532 // D = and i1 A, E
533 // F = and i1 G, H
534 // I = or i1 D, F
535 // br i1 I, label %True, label %False
536 //
537 // becomes
538 //
539 // Label[A]:
540 // tst B, 1
541 // bne Label[D]
542 // tst C, 1
543 // beq Label[I]
544 // Label[D]:
545 // tst E, 1
546 // bne %True
547 // Label[I]
548 // tst G, 1
549 // beq %False
550 // tst H, 1
551 // beq %False (bne %True)
John Porto4a5e6d02015-11-04 09:32:55 -0800552
John Porto7b3d9cb2015-11-11 14:26:57 -0800553 /// lowerInt1 materializes Boolean to a Variable.
554 SafeBoolChain lowerInt1(Variable *Dest, Operand *Boolean);
John Porto4a5e6d02015-11-04 09:32:55 -0800555
John Porto7b3d9cb2015-11-11 14:26:57 -0800556 /// lowerInt1ForSelect generates the following instruction sequence:
557 ///
558 /// mov T, FalseValue
559 /// CC <- eval(Boolean)
560 /// movCC T, TrueValue
561 /// mov Dest, T
562 ///
563 /// It is used for lowering select i1, as well as i1 Sext.
564 void lowerInt1ForSelect(Variable *Dest, Operand *Boolean, Operand *TrueValue,
565 Operand *FalseValue);
566
567 /// LowerInt1BranchTarget is used by lowerIntForBranch. It wraps a CfgNode, or
568 /// an InstARM32Label (but never both) so that, during br i1 lowering, we can
569 /// create auxiliary labels for short circuiting the condition evaluation.
570 class LowerInt1BranchTarget {
571 public:
572 explicit LowerInt1BranchTarget(CfgNode *const Target)
573 : NodeTarget(Target) {}
574 explicit LowerInt1BranchTarget(InstARM32Label *const Target)
575 : LabelTarget(Target) {}
576
577 /// createForLabelOrDuplicate will return a new LowerInt1BranchTarget that
578 /// is the exact copy of this if Label is nullptr; otherwise, the returned
579 /// object will wrap Label instead.
580 LowerInt1BranchTarget
581 createForLabelOrDuplicate(InstARM32Label *Label) const {
582 if (Label != nullptr)
583 return LowerInt1BranchTarget(Label);
584 if (NodeTarget)
585 return LowerInt1BranchTarget(NodeTarget);
586 return LowerInt1BranchTarget(LabelTarget);
John Porto4a5e6d02015-11-04 09:32:55 -0800587 }
588
John Porto7b3d9cb2015-11-11 14:26:57 -0800589 CfgNode *const NodeTarget = nullptr;
590 InstARM32Label *const LabelTarget = nullptr;
591 };
John Porto4a5e6d02015-11-04 09:32:55 -0800592
John Porto7b3d9cb2015-11-11 14:26:57 -0800593 /// LowerInt1AllowShortCircuit is a helper type used by lowerInt1ForBranch for
594 /// determining which type arithmetic is allowed to be short circuited. This
595 /// is useful for lowering
596 ///
597 /// t1 = and i1 A, B
598 /// t2 = and i1 t1, C
599 /// br i1 t2, label %False, label %True
600 ///
601 /// to
602 ///
603 /// tst A, 1
604 /// beq %False
605 /// tst B, 1
606 /// beq %False
607 /// tst C, 1
608 /// bne %True
609 /// b %False
610 ///
611 /// Without this information, short circuiting would only allow to short
612 /// circuit a single high level instruction. For example:
613 ///
614 /// t1 = or i1 A, B
615 /// t2 = and i1 t1, C
616 /// br i1 t2, label %False, label %True
617 ///
618 /// cannot be lowered to
619 ///
620 /// tst A, 1
621 /// bne %True
622 /// tst B, 1
623 /// bne %True
624 /// tst C, 1
625 /// beq %True
626 /// b %False
627 ///
628 /// It needs to be lowered to
629 ///
630 /// tst A, 1
631 /// bne Aux
632 /// tst B, 1
633 /// beq %False
634 /// Aux:
635 /// tst C, 1
636 /// bne %True
637 /// b %False
638 ///
639 /// TODO(jpp): evaluate if this kind of short circuiting hurts performance (it
640 /// might.)
641 enum LowerInt1AllowShortCircuit {
642 SC_And = 1,
643 SC_Or = 2,
644 SC_All = SC_And | SC_Or,
645 };
John Porto4a5e6d02015-11-04 09:32:55 -0800646
John Porto7b3d9cb2015-11-11 14:26:57 -0800647 /// ShortCircuitCondAndLabel wraps the condition codes that should be used
648 /// after a lowerInt1ForBranch returns to branch to the
649 /// TrueTarget/FalseTarget. If ShortCircuitLabel is not nullptr, then the
650 /// called lowerInt1forBranch created an internal (i.e., short-circuit) label
651 /// used for short circuiting.
652 class ShortCircuitCondAndLabel {
653 public:
654 explicit ShortCircuitCondAndLabel(CondWhenTrue &&C,
655 InstARM32Label *L = nullptr)
656 : Cond(std::move(C)), ShortCircuitTarget(L) {}
657 const CondWhenTrue Cond;
658 InstARM32Label *const ShortCircuitTarget;
John Porto4a5e6d02015-11-04 09:32:55 -0800659
John Porto7b3d9cb2015-11-11 14:26:57 -0800660 CondWhenTrue assertNoLabelAndReturnCond() const {
661 assert(ShortCircuitTarget == nullptr);
662 return Cond;
John Porto4a5e6d02015-11-04 09:32:55 -0800663 }
John Porto7b3d9cb2015-11-11 14:26:57 -0800664 };
John Porto4a5e6d02015-11-04 09:32:55 -0800665
John Porto7b3d9cb2015-11-11 14:26:57 -0800666 /// lowerInt1ForBranch expands Boolean, and returns the condition codes that
667 /// are to be used for branching to the branch's TrueTarget. It may return a
668 /// label that the expansion of Boolean used to short circuit the chain's
669 /// evaluation.
670 ShortCircuitCondAndLabel
671 lowerInt1ForBranch(Operand *Boolean, const LowerInt1BranchTarget &TargetTrue,
672 const LowerInt1BranchTarget &TargetFalse,
673 uint32_t ShortCircuitable);
674
675 // _br is a convenience wrapper that emits br instructions to Target.
676 void _br(const LowerInt1BranchTarget &BrTarget,
677 CondARM32::Cond Cond = CondARM32::AL) {
678 assert((BrTarget.NodeTarget == nullptr) !=
679 (BrTarget.LabelTarget == nullptr));
680 if (BrTarget.NodeTarget != nullptr)
681 _br(BrTarget.NodeTarget, Cond);
682 else
683 _br(BrTarget.LabelTarget, Cond);
684 }
685
686 // _br_short_circuit is used when lowering InstArithmetic::And and
687 // InstArithmetic::Or and a short circuit branch is needed.
688 void _br_short_circuit(const LowerInt1BranchTarget &Target,
689 const CondWhenTrue &Cond) {
690 if (Cond.WhenTrue1 != CondARM32::kNone) {
691 _br(Target, Cond.WhenTrue1);
692 }
693 if (Cond.WhenTrue0 != CondARM32::kNone) {
694 _br(Target, Cond.WhenTrue0);
John Porto4a5e6d02015-11-04 09:32:55 -0800695 }
696 }
John Porto7b3d9cb2015-11-11 14:26:57 -0800697 // End of bool folding machinery
698 // --------------------------------------------------------------------------
John Porto4a5e6d02015-11-04 09:32:55 -0800699
Andrew Scull57e12682015-09-16 11:30:19 -0700700 /// The Operand can only be a 16-bit immediate or a ConstantRelocatable (with
701 /// an upper16 relocation).
Jan Voung3bfd99a2015-05-22 16:35:25 -0700702 void _movt(Variable *Dest, Operand *Src0,
703 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800704 Context.insert<InstARM32Movt>(Dest, Src0, Pred);
Jan Voungb3401d22015-05-18 09:38:21 -0700705 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700706 void _movw(Variable *Dest, Operand *Src0,
707 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800708 Context.insert<InstARM32Movw>(Dest, Src0, Pred);
Jan Voungb3401d22015-05-18 09:38:21 -0700709 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700710 void _mul(Variable *Dest, Variable *Src0, Variable *Src1,
711 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800712 Context.insert<InstARM32Mul>(Dest, Src0, Src1, Pred);
Jan Voung29719972015-05-19 11:24:51 -0700713 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700714 void _mvn(Variable *Dest, Operand *Src0,
715 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800716 Context.insert<InstARM32Mvn>(Dest, Src0, Pred);
Jan Voungb3401d22015-05-18 09:38:21 -0700717 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700718 void _orr(Variable *Dest, Variable *Src0, Operand *Src1,
719 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800720 Context.insert<InstARM32Orr>(Dest, Src0, Src1, Pred);
Jan Voung29719972015-05-19 11:24:51 -0700721 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700722 void _orrs(Variable *Dest, Variable *Src0, Operand *Src1,
723 CondARM32::Cond Pred = CondARM32::AL) {
Jan Voung86ebec12015-08-09 07:58:35 -0700724 constexpr bool SetFlags = true;
John Porto1d937a82015-12-17 06:19:34 -0800725 Context.insert<InstARM32Orr>(Dest, Src0, Src1, Pred, SetFlags);
John Porto7e6aa5a2016-03-02 15:10:19 -0800726 if (SetFlags) {
727 Context.insert<InstFakeUse>(Dest);
728 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700729 }
John Porto1d937a82015-12-17 06:19:34 -0800730 void _push(const VarList &Sources) { Context.insert<InstARM32Push>(Sources); }
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700731 void _pop(const VarList &Dests) {
John Porto1d937a82015-12-17 06:19:34 -0800732 Context.insert<InstARM32Pop>(Dests);
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700733 // Mark dests as modified.
734 for (Variable *Dest : Dests)
John Porto1d937a82015-12-17 06:19:34 -0800735 Context.insert<InstFakeDef>(Dest);
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700736 }
Jan Voungf645d852015-07-09 10:35:09 -0700737 void _rbit(Variable *Dest, Variable *Src0,
738 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800739 Context.insert<InstARM32Rbit>(Dest, Src0, Pred);
Jan Voungf645d852015-07-09 10:35:09 -0700740 }
741 void _rev(Variable *Dest, Variable *Src0,
742 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800743 Context.insert<InstARM32Rev>(Dest, Src0, Pred);
Jan Voungf645d852015-07-09 10:35:09 -0700744 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700745 void _ret(Variable *LR, Variable *Src0 = nullptr) {
John Porto1d937a82015-12-17 06:19:34 -0800746 Context.insert<InstARM32Ret>(LR, Src0);
Jan Voung6ec369e2015-06-30 11:03:15 -0700747 }
John Portoccea7932015-11-17 04:58:36 -0800748 void _rscs(Variable *Dest, Variable *Src0, Operand *Src1,
749 CondARM32::Cond Pred = CondARM32::AL) {
750 constexpr bool SetFlags = true;
John Porto1d937a82015-12-17 06:19:34 -0800751 Context.insert<InstARM32Rsc>(Dest, Src0, Src1, Pred, SetFlags);
John Porto7e6aa5a2016-03-02 15:10:19 -0800752 if (SetFlags) {
753 Context.insert<InstFakeUse>(Dest);
754 }
John Portoccea7932015-11-17 04:58:36 -0800755 }
756 void _rsc(Variable *Dest, Variable *Src0, Operand *Src1,
757 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800758 Context.insert<InstARM32Rsc>(Dest, Src0, Src1, Pred);
John Portoccea7932015-11-17 04:58:36 -0800759 }
760 void _rsbs(Variable *Dest, Variable *Src0, Operand *Src1,
761 CondARM32::Cond Pred = CondARM32::AL) {
762 constexpr bool SetFlags = true;
John Porto1d937a82015-12-17 06:19:34 -0800763 Context.insert<InstARM32Rsb>(Dest, Src0, Src1, Pred, SetFlags);
John Porto7e6aa5a2016-03-02 15:10:19 -0800764 if (SetFlags) {
765 Context.insert<InstFakeUse>(Dest);
766 }
John Portoccea7932015-11-17 04:58:36 -0800767 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700768 void _rsb(Variable *Dest, Variable *Src0, Operand *Src1,
769 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800770 Context.insert<InstARM32Rsb>(Dest, Src0, Src1, Pred);
Jan Voung66c3d5e2015-06-04 17:02:31 -0700771 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700772 void _sbc(Variable *Dest, Variable *Src0, Operand *Src1,
773 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800774 Context.insert<InstARM32Sbc>(Dest, Src0, Src1, Pred);
Jan Voung29719972015-05-19 11:24:51 -0700775 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700776 void _sbcs(Variable *Dest, Variable *Src0, Operand *Src1,
777 CondARM32::Cond Pred = CondARM32::AL) {
Jan Voung86ebec12015-08-09 07:58:35 -0700778 constexpr bool SetFlags = true;
John Porto1d937a82015-12-17 06:19:34 -0800779 Context.insert<InstARM32Sbc>(Dest, Src0, Src1, Pred, SetFlags);
John Porto7e6aa5a2016-03-02 15:10:19 -0800780 if (SetFlags) {
781 Context.insert<InstFakeUse>(Dest);
782 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700783 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700784 void _sdiv(Variable *Dest, Variable *Src0, Variable *Src1,
785 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800786 Context.insert<InstARM32Sdiv>(Dest, Src0, Src1, Pred);
Jan Voung6ec369e2015-06-30 11:03:15 -0700787 }
John Portoba6a67c2015-09-25 15:19:45 -0700788 /// _str, for all your Variable to memory transfers. Addr has the same
789 /// restrictions that it does in _ldr.
Jan Voungbefd03a2015-06-02 11:03:03 -0700790 void _str(Variable *Value, OperandARM32Mem *Addr,
791 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800792 Context.insert<InstARM32Str>(Value, Addr, Pred);
Jan Voungbefd03a2015-06-02 11:03:03 -0700793 }
John Porto324334e2016-03-08 11:00:53 -0800794 InstARM32Strex *_strex(Variable *Dest, Variable *Value, OperandARM32Mem *Addr,
795 CondARM32::Cond Pred = CondARM32::AL) {
John Porto16991842015-10-01 15:11:23 -0700796 if (auto *Value64 = llvm::dyn_cast<Variable64On32>(Value)) {
John Porto1d937a82015-12-17 06:19:34 -0800797 Context.insert<InstFakeUse>(Value64->getLo());
798 Context.insert<InstFakeUse>(Value64->getHi());
John Porto16991842015-10-01 15:11:23 -0700799 }
John Porto324334e2016-03-08 11:00:53 -0800800 return Context.insert<InstARM32Strex>(Dest, Value, Addr, Pred);
John Porto16991842015-10-01 15:11:23 -0700801 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700802 void _sub(Variable *Dest, Variable *Src0, Operand *Src1,
803 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800804 Context.insert<InstARM32Sub>(Dest, Src0, Src1, Pred);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700805 }
806 void _subs(Variable *Dest, Variable *Src0, Operand *Src1,
807 CondARM32::Cond Pred = CondARM32::AL) {
Jan Voung86ebec12015-08-09 07:58:35 -0700808 constexpr bool SetFlags = true;
John Porto1d937a82015-12-17 06:19:34 -0800809 Context.insert<InstARM32Sub>(Dest, Src0, Src1, Pred, SetFlags);
John Porto7e6aa5a2016-03-02 15:10:19 -0800810 if (SetFlags) {
811 Context.insert<InstFakeUse>(Dest);
812 }
Jan Voung29719972015-05-19 11:24:51 -0700813 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700814 void _sxt(Variable *Dest, Variable *Src0,
815 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800816 Context.insert<InstARM32Sxt>(Dest, Src0, Pred);
Jan Voung66c3d5e2015-06-04 17:02:31 -0700817 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700818 void _tst(Variable *Src0, Operand *Src1,
819 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800820 Context.insert<InstARM32Tst>(Src0, Src1, Pred);
Jan Voung6ec369e2015-06-30 11:03:15 -0700821 }
John Porto1d937a82015-12-17 06:19:34 -0800822 void _trap() { Context.insert<InstARM32Trap>(); }
Jan Voung6ec369e2015-06-30 11:03:15 -0700823 void _udiv(Variable *Dest, Variable *Src0, Variable *Src1,
824 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800825 Context.insert<InstARM32Udiv>(Dest, Src0, Src1, Pred);
Jan Voungb2d50842015-05-12 09:53:50 -0700826 }
Jan Voung29719972015-05-19 11:24:51 -0700827 void _umull(Variable *DestLo, Variable *DestHi, Variable *Src0,
Jan Voung3bfd99a2015-05-22 16:35:25 -0700828 Variable *Src1, CondARM32::Cond Pred = CondARM32::AL) {
John Portoa1cdd572016-03-01 15:19:29 -0800829 // umull requires DestLo and DestHi to be assigned to different GPRs. The
830 // following lines create overlapping liveness ranges for both variables. If
831 // either one of them is live, then they are both going to be live, and thus
832 // assigned to different registers; if they are both dead, then DCE will
833 // kick in and delete the following three instructions.
834 Context.insert<InstFakeDef>(DestHi);
John Porto1d937a82015-12-17 06:19:34 -0800835 Context.insert<InstARM32Umull>(DestLo, DestHi, Src0, Src1, Pred);
John Portoa1cdd572016-03-01 15:19:29 -0800836 Context.insert<InstFakeDef>(DestHi, DestLo)->setDestRedefined();
Jim Stichnoth28df6ba2016-02-05 15:43:24 -0800837 Context.insert<InstFakeUse>(DestHi);
Jan Voung29719972015-05-19 11:24:51 -0700838 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700839 void _uxt(Variable *Dest, Variable *Src0,
840 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800841 Context.insert<InstARM32Uxt>(Dest, Src0, Pred);
Jan Voung66c3d5e2015-06-04 17:02:31 -0700842 }
John Portoba6a67c2015-09-25 15:19:45 -0700843 void _vabs(Variable *Dest, Variable *Src,
844 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800845 Context.insert<InstARM32Vabs>(Dest, Src, Pred);
John Portoba6a67c2015-09-25 15:19:45 -0700846 }
Jan Voung86ebec12015-08-09 07:58:35 -0700847 void _vadd(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800848 Context.insert<InstARM32Vadd>(Dest, Src0, Src1);
Jan Voung86ebec12015-08-09 07:58:35 -0700849 }
Eric Holkb58170c2016-01-27 11:18:29 -0800850 void _vand(Variable *Dest, Variable *Src0, Variable *Src1) {
851 Context.insert<InstARM32Vand>(Dest, Src0, Src1);
852 }
John Porto397f6022016-04-15 06:26:58 -0700853 InstARM32Vbsl *_vbsl(Variable *Dest, Variable *Src0, Variable *Src1) {
854 return Context.insert<InstARM32Vbsl>(Dest, Src0, Src1);
855 }
John Portoa4d100a2016-04-18 15:32:27 -0700856 void _vceq(Variable *Dest, Variable *Src0, Variable *Src1) {
857 Context.insert<InstARM32Vceq>(Dest, Src0, Src1);
858 }
859 InstARM32Vcge *_vcge(Variable *Dest, Variable *Src0, Variable *Src1) {
860 return Context.insert<InstARM32Vcge>(Dest, Src0, Src1);
861 }
862 InstARM32Vcgt *_vcgt(Variable *Dest, Variable *Src0, Variable *Src1) {
863 return Context.insert<InstARM32Vcgt>(Dest, Src0, Src1);
864 }
John Portoc31e2ed2015-09-11 05:17:08 -0700865 void _vcvt(Variable *Dest, Variable *Src, InstARM32Vcvt::VcvtVariant Variant,
866 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800867 Context.insert<InstARM32Vcvt>(Dest, Src, Variant, Pred);
John Portoc31e2ed2015-09-11 05:17:08 -0700868 }
Jan Voung86ebec12015-08-09 07:58:35 -0700869 void _vdiv(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800870 Context.insert<InstARM32Vdiv>(Dest, Src0, Src1);
Jan Voung86ebec12015-08-09 07:58:35 -0700871 }
John Porto2f5534f2015-09-18 15:59:47 -0700872 void _vcmp(Variable *Src0, Variable *Src1,
873 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800874 Context.insert<InstARM32Vcmp>(Src0, Src1, Pred);
John Porto2f5534f2015-09-18 15:59:47 -0700875 }
John Portoccea7932015-11-17 04:58:36 -0800876 void _vcmp(Variable *Src0, OperandARM32FlexFpZero *FpZero,
877 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800878 Context.insert<InstARM32Vcmp>(Src0, FpZero, Pred);
John Portoccea7932015-11-17 04:58:36 -0800879 }
Nicolas Capensf6951fa2017-10-02 10:44:03 -0400880 void _vdup(Variable *Dest, Variable *Src, int Idx) {
881 Context.insert<InstARM32Vdup>(Dest, Src, Idx);
882 }
John Porto3f6b47d2015-11-19 05:42:59 -0800883 void _veor(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800884 Context.insert<InstARM32Veor>(Dest, Src0, Src1);
John Porto3f6b47d2015-11-19 05:42:59 -0800885 }
Nicolas Capens675e15b2017-09-27 15:06:35 -0400886 void _vldr1d(Variable *Dest, OperandARM32Mem *Addr,
887 CondARM32::Cond Pred = CondARM32::AL) {
888 Context.insert<InstARM32Vldr1d>(Dest, Addr, Pred);
889 }
890 void _vldr1q(Variable *Dest, OperandARM32Mem *Addr,
891 CondARM32::Cond Pred = CondARM32::AL) {
892 Context.insert<InstARM32Vldr1q>(Dest, Addr, Pred);
893 }
John Porto2f5534f2015-09-18 15:59:47 -0700894 void _vmrs(CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800895 Context.insert<InstARM32Vmrs>(Pred);
John Porto2f5534f2015-09-18 15:59:47 -0700896 }
John Portoeb13acc2015-12-09 05:10:58 -0800897 void _vmla(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800898 Context.insert<InstARM32Vmla>(Dest, Src0, Src1);
John Portoeb13acc2015-12-09 05:10:58 -0800899 }
Nicolas Capens675e15b2017-09-27 15:06:35 -0400900 void _vmlap(Variable *Dest, Variable *Src0, Variable *Src1) {
901 Context.insert<InstARM32Vmlap>(Dest, Src0, Src1);
902 }
John Portoeb13acc2015-12-09 05:10:58 -0800903 void _vmls(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800904 Context.insert<InstARM32Vmls>(Dest, Src0, Src1);
John Portoeb13acc2015-12-09 05:10:58 -0800905 }
Nicolas Capensf6951fa2017-10-02 10:44:03 -0400906 void _vmovl(Variable *Dest, Variable *Src0, Variable *Src1) {
907 Context.insert<InstARM32Vmovl>(Dest, Src0, Src1);
908 }
909 void _vmovh(Variable *Dest, Variable *Src0, Variable *Src1) {
910 Context.insert<InstARM32Vmovh>(Dest, Src0, Src1);
911 }
912 void _vmovhl(Variable *Dest, Variable *Src0, Variable *Src1) {
913 Context.insert<InstARM32Vmovhl>(Dest, Src0, Src1);
914 }
915 void _vmovlh(Variable *Dest, Variable *Src0, Variable *Src1) {
916 Context.insert<InstARM32Vmovlh>(Dest, Src0, Src1);
917 }
Jan Voung86ebec12015-08-09 07:58:35 -0700918 void _vmul(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800919 Context.insert<InstARM32Vmul>(Dest, Src0, Src1);
Jan Voung86ebec12015-08-09 07:58:35 -0700920 }
Nicolas Capens675e15b2017-09-27 15:06:35 -0400921 void _vmulh(Variable *Dest, Variable *Src0, Variable *Src1, bool Unsigned) {
922 Context.insert<InstARM32Vmulh>(Dest, Src0, Src1)
923 ->setSignType(Unsigned ? InstARM32::FS_Unsigned : InstARM32::FS_Signed);
924 }
John Portoa4d100a2016-04-18 15:32:27 -0700925 void _vmvn(Variable *Dest, Variable *Src0) {
926 Context.insert<InstARM32Vmvn>(Dest, Src0, CondARM32::AL);
927 }
John Porto15e77d42016-04-13 12:57:14 -0700928 void _vneg(Variable *Dest, Variable *Src0) {
929 Context.insert<InstARM32Vneg>(Dest, Src0, CondARM32::AL)
930 ->setSignType(InstARM32::FS_Signed);
931 }
Eric Holkcad0b752016-01-27 14:56:22 -0800932 void _vorr(Variable *Dest, Variable *Src0, Variable *Src1) {
933 Context.insert<InstARM32Vorr>(Dest, Src0, Src1);
934 }
Casey Dahlinb40560b2017-06-28 13:58:58 -0700935 void _vqadd(Variable *Dest, Variable *Src0, Variable *Src1, bool Unsigned) {
936 Context.insert<InstARM32Vqadd>(Dest, Src0, Src1)
937 ->setSignType(Unsigned ? InstARM32::FS_Unsigned : InstARM32::FS_Signed);
938 }
Nicolas Capens675e15b2017-09-27 15:06:35 -0400939 void _vqmovn2(Variable *Dest, Variable *Src0, Variable *Src1, bool Unsigned,
940 bool Saturating) {
941 Context.insert<InstARM32Vqmovn2>(Dest, Src0, Src1)
942 ->setSignType(Saturating ? (Unsigned ? InstARM32::FS_Unsigned
943 : InstARM32::FS_Signed)
944 : InstARM32::FS_None);
945 }
Casey Dahlinb40560b2017-06-28 13:58:58 -0700946 void _vqsub(Variable *Dest, Variable *Src0, Variable *Src1, bool Unsigned) {
947 Context.insert<InstARM32Vqsub>(Dest, Src0, Src1)
948 ->setSignType(Unsigned ? InstARM32::FS_Unsigned : InstARM32::FS_Signed);
949 }
John Porto15e77d42016-04-13 12:57:14 -0700950 InstARM32Vshl *_vshl(Variable *Dest, Variable *Src0, Variable *Src1) {
951 return Context.insert<InstARM32Vshl>(Dest, Src0, Src1);
952 }
John Portoe88c7de2016-04-14 11:51:38 -0700953 void _vshl(Variable *Dest, Variable *Src0, ConstantInteger32 *Src1) {
954 Context.insert<InstARM32Vshl>(Dest, Src0, Src1)
955 ->setSignType(InstARM32::FS_Unsigned);
956 }
957 InstARM32Vshr *_vshr(Variable *Dest, Variable *Src0,
958 ConstantInteger32 *Src1) {
959 return Context.insert<InstARM32Vshr>(Dest, Src0, Src1);
960 }
Jan Voung86ebec12015-08-09 07:58:35 -0700961 void _vsqrt(Variable *Dest, Variable *Src,
962 CondARM32::Cond Pred = CondARM32::AL) {
John Porto1d937a82015-12-17 06:19:34 -0800963 Context.insert<InstARM32Vsqrt>(Dest, Src, Pred);
Jan Voung86ebec12015-08-09 07:58:35 -0700964 }
Nicolas Capens675e15b2017-09-27 15:06:35 -0400965 void _vstr1d(Variable *Value, OperandARM32Mem *Addr,
966 CondARM32::Cond Pred = CondARM32::AL) {
967 Context.insert<InstARM32Vstr1>(Value, Addr, Pred, 32);
968 }
969 void _vstr1q(Variable *Value, OperandARM32Mem *Addr,
970 CondARM32::Cond Pred = CondARM32::AL) {
971 Context.insert<InstARM32Vstr1>(Value, Addr, Pred, 64);
972 }
Jan Voung86ebec12015-08-09 07:58:35 -0700973 void _vsub(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800974 Context.insert<InstARM32Vsub>(Dest, Src0, Src1);
Jan Voung86ebec12015-08-09 07:58:35 -0700975 }
Nicolas Capensf6951fa2017-10-02 10:44:03 -0400976 void _vzip(Variable *Dest, Variable *Src0, Variable *Src1) {
977 Context.insert<InstARM32Vzip>(Dest, Src0, Src1);
978 }
Jan Voungb2d50842015-05-12 09:53:50 -0700979
John Portof4198542015-11-20 14:17:23 -0800980 // Iterates over the CFG and determines the maximum outgoing stack arguments
John Porto614140e2015-11-23 11:43:13 -0800981 // bytes. This information is later used during addProlog() to pre-allocate
John Portof4198542015-11-20 14:17:23 -0800982 // the outargs area.
983 // TODO(jpp): This could live in the Parser, if we provided a Target-specific
984 // method that the Parser could call.
985 void findMaxStackOutArgsSize();
986
John Porto866b6b12015-12-03 09:45:31 -0800987 /// Returns true if the given Offset can be represented in a Load/Store Mem
988 /// Operand.
John Portof5f02f72015-11-09 14:52:40 -0800989 bool isLegalMemOffset(Type Ty, int32_t Offset) const;
John Porto866b6b12015-12-03 09:45:31 -0800990
991 void postLowerLegalization();
992
John Portodc619252016-02-10 15:57:16 -0800993 /// Manages the Gotoff relocations created during the function lowering. A
994 /// single Gotoff relocation is created for each global variable used by the
995 /// function being lowered.
996 /// @{
997 // TODO(jpp): if the same global G is used in different functions, then this
998 // method will emit one G(gotoff) relocation per function.
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700999 GlobalString createGotoffRelocation(const ConstantRelocatable *CR);
1000 CfgUnorderedSet<GlobalString> KnownGotoffs;
John Portodc619252016-02-10 15:57:16 -08001001 /// @}
1002
John Porto866b6b12015-12-03 09:45:31 -08001003 class PostLoweringLegalizer {
1004 PostLoweringLegalizer() = delete;
1005 PostLoweringLegalizer(const PostLoweringLegalizer &) = delete;
1006 PostLoweringLegalizer &operator=(const PostLoweringLegalizer &) = delete;
1007
1008 public:
1009 explicit PostLoweringLegalizer(TargetARM32 *Target)
1010 : Target(Target), StackOrFrameReg(Target->getPhysicalRegister(
1011 Target->getFrameOrStackReg())) {}
1012
1013 void resetTempBaseIfClobberedBy(const Inst *Instr);
1014
1015 // Ensures that the TempBase register held by the this legalizer (if any) is
1016 // assigned to IP.
1017 void assertNoTempOrAssignedToIP() const {
1018 assert(TempBaseReg == nullptr ||
1019 TempBaseReg->getRegNum() == Target->getReservedTmpReg());
1020 }
1021
1022 // Legalizes Mem. if Mem.Base is a Reamaterializable variable, Mem.Offset is
1023 // fixed up.
1024 OperandARM32Mem *legalizeMemOperand(OperandARM32Mem *Mem,
1025 bool AllowOffsets = true);
1026
1027 /// Legalizes Mov if its Source (or Destination) is a spilled Variable, or
1028 /// if its Source is a Rematerializable variable (this form is used in lieu
1029 /// of lea, which is not available in ARM.)
1030 ///
1031 /// Moves to memory become store instructions, and moves from memory, loads.
1032 void legalizeMov(InstARM32Mov *Mov);
1033
1034 private:
1035 /// Creates a new Base register centered around [Base, +/- Offset].
1036 Variable *newBaseRegister(Variable *Base, int32_t Offset,
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001037 RegNumT ScratchRegNum);
John Porto866b6b12015-12-03 09:45:31 -08001038
1039 /// Creates a new, legal OperandARM32Mem for accessing Base + Offset.
1040 /// The returned mem operand is a legal operand for accessing memory that is
1041 /// of type Ty.
1042 ///
1043 /// If [Base, #Offset] is encodable, then the method returns a Mem operand
1044 /// expressing it. Otherwise,
1045 ///
1046 /// if [TempBaseReg, #Offset-TempBaseOffset] is a valid memory operand, the
1047 /// method will return that. Otherwise,
1048 ///
1049 /// a new base register ip=Base+Offset is created, and the method returns a
1050 /// memory operand expressing [ip, #0].
1051 OperandARM32Mem *createMemOperand(Type Ty, Variable *Base, int32_t Offset,
1052 bool AllowOffsets = true);
1053 TargetARM32 *const Target;
1054 Variable *const StackOrFrameReg;
1055 Variable *TempBaseReg = nullptr;
1056 int32_t TempBaseOffset = 0;
1057 };
Jan Voung28068ad2015-07-31 12:58:46 -07001058
Jan Voung6ec369e2015-06-30 11:03:15 -07001059 TargetARM32Features CPUFeatures;
Jim Stichnotheafb56c2015-06-22 10:35:22 -07001060 bool UsesFramePointer = false;
1061 bool NeedsStackAlignment = false;
1062 bool MaybeLeafFunc = true;
1063 size_t SpillAreaSizeBytes = 0;
John Porto614140e2015-11-23 11:43:13 -08001064 size_t FixedAllocaSizeBytes = 0;
1065 size_t FixedAllocaAlignBytes = 0;
1066 bool PrologEmitsFixedAllocas = false;
John Portof4198542015-11-20 14:17:23 -08001067 uint32_t MaxOutArgsSizeBytes = 0;
John Portobb0a5fe2015-09-04 11:23:41 -07001068 // TODO(jpp): std::array instead of array.
John Portoe82b5602016-02-24 15:58:55 -08001069 static SmallBitVector TypeToRegisterSet[RegARM32::RCARM32_NUM];
1070 static SmallBitVector TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM];
1071 static SmallBitVector RegisterAliases[RegARM32::Reg_NUM];
1072 SmallBitVector RegsUsed;
Jan Voungb36ad9b2015-04-21 17:01:49 -07001073 VarList PhysicalRegisters[IceType_NUM];
John Portoeb13acc2015-12-09 05:10:58 -08001074 VarList PreservedGPRs;
1075 VarList PreservedSRegs;
Jan Voungb36ad9b2015-04-21 17:01:49 -07001076
Andrew Scull9612d322015-07-06 14:53:25 -07001077 /// Helper class that understands the Calling Convention and register
1078 /// assignments. The first few integer type parameters can use r0-r3,
1079 /// regardless of their position relative to the floating-point/vector
John Porto385351b2015-09-16 16:11:10 -07001080 /// arguments in the argument list. Floating-point and vector arguments
1081 /// can use q0-q3 (aka d0-d7, s0-s15). For more information on the topic,
1082 /// see the ARM Architecture Procedure Calling Standards (AAPCS).
Andrew Scull9612d322015-07-06 14:53:25 -07001083 ///
John Porto385351b2015-09-16 16:11:10 -07001084 /// Technically, arguments that can start with registers but extend beyond the
1085 /// available registers can be split between the registers and the stack.
1086 /// However, this is typically for passing GPR structs by value, and PNaCl
1087 /// transforms expand this out.
1088 ///
1089 /// At (public) function entry, the stack must be 8-byte aligned.
Jan Voungb0a8c242015-06-18 15:00:14 -07001090 class CallingConv {
1091 CallingConv(const CallingConv &) = delete;
1092 CallingConv &operator=(const CallingConv &) = delete;
1093
1094 public:
John Porto2187c842015-12-16 07:48:25 -08001095 CallingConv();
Jan Voungb0a8c242015-06-18 15:00:14 -07001096 ~CallingConv() = default;
1097
John Porto2187c842015-12-16 07:48:25 -08001098 /// argInGPR returns true if there is a GPR available for the requested
1099 /// type, and false otherwise. If it returns true, Reg is set to the
1100 /// appropriate register number. Note that, when Ty == IceType_i64, Reg will
1101 /// be an I64 register pair.
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001102 bool argInGPR(Type Ty, RegNumT *Reg);
Jan Voungb0a8c242015-06-18 15:00:14 -07001103
John Porto2187c842015-12-16 07:48:25 -08001104 /// argInVFP is to floating-point/vector types what argInGPR is for integer
1105 /// types.
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001106 bool argInVFP(Type Ty, RegNumT *Reg);
Jan Voungb0a8c242015-06-18 15:00:14 -07001107
1108 private:
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001109 void discardUnavailableGPRsAndTheirAliases(CfgVector<RegNumT> *Regs);
John Portoe82b5602016-02-24 15:58:55 -08001110 SmallBitVector GPRegsUsed;
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001111 CfgVector<RegNumT> GPRArgs;
1112 CfgVector<RegNumT> I64Args;
John Porto2187c842015-12-16 07:48:25 -08001113
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001114 void discardUnavailableVFPRegs(CfgVector<RegNumT> *Regs);
John Portoe82b5602016-02-24 15:58:55 -08001115 SmallBitVector VFPRegsUsed;
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001116 CfgVector<RegNumT> FP32Args;
1117 CfgVector<RegNumT> FP64Args;
1118 CfgVector<RegNumT> Vec128Args;
Jan Voungb0a8c242015-06-18 15:00:14 -07001119 };
1120
Jan Voungb36ad9b2015-04-21 17:01:49 -07001121private:
John Porto53611e22015-12-30 07:30:10 -08001122 ENABLE_MAKE_UNIQUE;
John Porto4a5e6d02015-11-04 09:32:55 -08001123
John Portof5f02f72015-11-09 14:52:40 -08001124 OperandARM32Mem *formAddressingMode(Type Ty, Cfg *Func, const Inst *LdSt,
1125 Operand *Base);
1126
John Portoc39ec102015-12-01 13:00:43 -08001127 void postambleCtpop64(const InstCall *Instr);
1128 void preambleDivRem(const InstCall *Instr);
John Portoe82b5602016-02-24 15:58:55 -08001129 CfgUnorderedMap<Operand *, void (TargetARM32::*)(const InstCall *Instr)>
John Portoc39ec102015-12-01 13:00:43 -08001130 ARM32HelpersPreamble;
John Portoe82b5602016-02-24 15:58:55 -08001131 CfgUnorderedMap<Operand *, void (TargetARM32::*)(const InstCall *Instr)>
John Portoc39ec102015-12-01 13:00:43 -08001132 ARM32HelpersPostamble;
1133
John Portoeb13acc2015-12-09 05:10:58 -08001134 class ComputationTracker {
John Porto4a5e6d02015-11-04 09:32:55 -08001135 public:
John Portoeb13acc2015-12-09 05:10:58 -08001136 ComputationTracker() = default;
1137 ~ComputationTracker() = default;
John Porto4a5e6d02015-11-04 09:32:55 -08001138
1139 void forgetProducers() { KnownComputations.clear(); }
1140 void recordProducers(CfgNode *Node);
1141
1142 const Inst *getProducerOf(const Operand *Opnd) const {
1143 auto *Var = llvm::dyn_cast<Variable>(Opnd);
1144 if (Var == nullptr) {
1145 return nullptr;
1146 }
1147
1148 auto Iter = KnownComputations.find(Var->getIndex());
1149 if (Iter == KnownComputations.end()) {
1150 return nullptr;
1151 }
1152
1153 return Iter->second.Instr;
1154 }
1155
1156 void dump(const Cfg *Func) const {
1157 if (!BuildDefs::dump() || !Func->isVerbose(IceV_Folding))
1158 return;
1159 OstreamLocker L(Func->getContext());
1160 Ostream &Str = Func->getContext()->getStrDump();
John Porto7b3d9cb2015-11-11 14:26:57 -08001161 Str << "foldable producer:\n";
John Porto4a5e6d02015-11-04 09:32:55 -08001162 for (const auto &Computation : KnownComputations) {
1163 Str << " ";
1164 Computation.second.Instr->dump(Func);
1165 Str << "\n";
1166 }
1167 Str << "\n";
1168 }
1169
1170 private:
John Portoeb13acc2015-12-09 05:10:58 -08001171 class ComputationEntry {
John Porto4a5e6d02015-11-04 09:32:55 -08001172 public:
John Portoeb13acc2015-12-09 05:10:58 -08001173 ComputationEntry(Inst *I, Type Ty) : Instr(I), ComputationType(Ty) {}
John Porto4a5e6d02015-11-04 09:32:55 -08001174 Inst *const Instr;
1175 // Boolean folding is disabled for variables whose live range is multi
1176 // block. We conservatively initialize IsLiveOut to true, and set it to
1177 // false once we find the end of the live range for the variable defined
1178 // by this instruction. If liveness analysis is not performed (e.g., in
1179 // Om1 mode) IsLiveOut will never be set to false, and folding will be
1180 // disabled.
1181 bool IsLiveOut = true;
John Porto7b3d9cb2015-11-11 14:26:57 -08001182 int32_t NumUses = 0;
John Portoeb13acc2015-12-09 05:10:58 -08001183 Type ComputationType;
John Porto4a5e6d02015-11-04 09:32:55 -08001184 };
1185
John Portoeb13acc2015-12-09 05:10:58 -08001186 // ComputationMap maps a Variable number to a payload identifying which
1187 // instruction defined it.
John Portoe82b5602016-02-24 15:58:55 -08001188 using ComputationMap = CfgUnorderedMap<SizeT, ComputationEntry>;
John Portoeb13acc2015-12-09 05:10:58 -08001189 ComputationMap KnownComputations;
John Porto4a5e6d02015-11-04 09:32:55 -08001190 };
1191
John Portoeb13acc2015-12-09 05:10:58 -08001192 ComputationTracker Computations;
John Porto614140e2015-11-23 11:43:13 -08001193
1194 // AllowTemporaryWithNoReg indicates if TargetARM32::makeReg() can be invoked
1195 // without specifying a physical register. This is needed for creating unbound
1196 // temporaries during Ice -> ARM lowering, but before register allocation.
John Porto98cc08c2015-11-24 12:30:01 -08001197 // This a safe-guard that no unbound temporaries are created during the
1198 // legalization post-passes.
John Porto614140e2015-11-23 11:43:13 -08001199 bool AllowTemporaryWithNoReg = true;
1200 // ForbidTemporaryWithoutReg is a RAII class that manages
1201 // AllowTemporaryWithNoReg.
1202 class ForbidTemporaryWithoutReg {
1203 ForbidTemporaryWithoutReg() = delete;
John Porto98cc08c2015-11-24 12:30:01 -08001204 ForbidTemporaryWithoutReg(const ForbidTemporaryWithoutReg &) = delete;
1205 ForbidTemporaryWithoutReg &
1206 operator=(const ForbidTemporaryWithoutReg &) = delete;
John Porto614140e2015-11-23 11:43:13 -08001207
1208 public:
1209 explicit ForbidTemporaryWithoutReg(TargetARM32 *Target) : Target(Target) {
1210 Target->AllowTemporaryWithNoReg = false;
1211 }
1212 ~ForbidTemporaryWithoutReg() { Target->AllowTemporaryWithNoReg = true; }
1213
1214 private:
1215 TargetARM32 *const Target;
1216 };
Jan Voungb36ad9b2015-04-21 17:01:49 -07001217};
1218
John Porto0f86d032015-06-15 07:44:27 -07001219class TargetDataARM32 final : public TargetDataLowering {
Jan Voungb36ad9b2015-04-21 17:01:49 -07001220 TargetDataARM32() = delete;
1221 TargetDataARM32(const TargetDataARM32 &) = delete;
1222 TargetDataARM32 &operator=(const TargetDataARM32 &) = delete;
1223
1224public:
Jan Voungfb792842015-06-11 15:27:50 -07001225 static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) {
1226 return std::unique_ptr<TargetDataLowering>(new TargetDataARM32(Ctx));
Jan Voungb36ad9b2015-04-21 17:01:49 -07001227 }
1228
John Porto8b1a7052015-06-17 13:20:08 -07001229 void lowerGlobals(const VariableDeclarationList &Vars,
Jim Stichnoth467ffe52016-03-29 15:01:06 -07001230 const std::string &SectionSuffix) override;
John Porto0f86d032015-06-15 07:44:27 -07001231 void lowerConstants() override;
Andrew Scull86df4e92015-07-30 13:54:44 -07001232 void lowerJumpTables() override;
Jan Voungb36ad9b2015-04-21 17:01:49 -07001233
1234protected:
1235 explicit TargetDataARM32(GlobalContext *Ctx);
1236
1237private:
Jim Stichnothe587d942015-06-22 15:49:04 -07001238 ~TargetDataARM32() override = default;
Jan Voungb36ad9b2015-04-21 17:01:49 -07001239};
1240
Jan Voungfb792842015-06-11 15:27:50 -07001241class TargetHeaderARM32 final : public TargetHeaderLowering {
1242 TargetHeaderARM32() = delete;
1243 TargetHeaderARM32(const TargetHeaderARM32 &) = delete;
1244 TargetHeaderARM32 &operator=(const TargetHeaderARM32 &) = delete;
1245
1246public:
1247 static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) {
1248 return std::unique_ptr<TargetHeaderLowering>(new TargetHeaderARM32(Ctx));
1249 }
1250
John Porto0f86d032015-06-15 07:44:27 -07001251 void lower() override;
Jan Voungfb792842015-06-11 15:27:50 -07001252
1253protected:
1254 explicit TargetHeaderARM32(GlobalContext *Ctx);
1255
1256private:
1257 ~TargetHeaderARM32() = default;
Jan Voung6ec369e2015-06-30 11:03:15 -07001258
1259 TargetARM32Features CPUFeatures;
Jan Voungfb792842015-06-11 15:27:50 -07001260};
1261
John Porto4a566862016-01-04 09:33:41 -08001262} // end of namespace ARM32
Jan Voungb36ad9b2015-04-21 17:01:49 -07001263} // end of namespace Ice
1264
1265#endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H