xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceTargetLoweringARM32.h (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceTargetLoweringARM32.h - ARM32 lowering ----*- C++ -*-===//
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker //                        The Subzero Code Generator
4*03ce13f7SAndroid Build Coastguard Worker //
5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*03ce13f7SAndroid Build Coastguard Worker //
8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*03ce13f7SAndroid Build Coastguard Worker ///
10*03ce13f7SAndroid Build Coastguard Worker /// \file
11*03ce13f7SAndroid Build Coastguard Worker /// \brief Declares the TargetLoweringARM32 class, which implements the
12*03ce13f7SAndroid Build Coastguard Worker /// TargetLowering interface for the ARM 32-bit architecture.
13*03ce13f7SAndroid Build Coastguard Worker ///
14*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*03ce13f7SAndroid Build Coastguard Worker 
16*03ce13f7SAndroid Build Coastguard Worker #ifndef SUBZERO_SRC_ICETARGETLOWERINGARM32_H
17*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_SRC_ICETARGETLOWERINGARM32_H
18*03ce13f7SAndroid Build Coastguard Worker 
19*03ce13f7SAndroid Build Coastguard Worker #include "IceAssemblerARM32.h"
20*03ce13f7SAndroid Build Coastguard Worker #include "IceDefs.h"
21*03ce13f7SAndroid Build Coastguard Worker #include "IceInstARM32.h"
22*03ce13f7SAndroid Build Coastguard Worker #include "IceRegistersARM32.h"
23*03ce13f7SAndroid Build Coastguard Worker #include "IceTargetLowering.h"
24*03ce13f7SAndroid Build Coastguard Worker 
25*03ce13f7SAndroid Build Coastguard Worker #include <utility>
26*03ce13f7SAndroid Build Coastguard Worker 
27*03ce13f7SAndroid Build Coastguard Worker namespace Ice {
28*03ce13f7SAndroid Build Coastguard Worker namespace ARM32 {
29*03ce13f7SAndroid Build Coastguard Worker 
30*03ce13f7SAndroid Build Coastguard Worker // Class encapsulating ARM cpu features / instruction set.
31*03ce13f7SAndroid Build Coastguard Worker class TargetARM32Features {
32*03ce13f7SAndroid Build Coastguard Worker   TargetARM32Features() = delete;
33*03ce13f7SAndroid Build Coastguard Worker   TargetARM32Features(const TargetARM32Features &) = delete;
34*03ce13f7SAndroid Build Coastguard Worker   TargetARM32Features &operator=(const TargetARM32Features &) = delete;
35*03ce13f7SAndroid Build Coastguard Worker 
36*03ce13f7SAndroid Build Coastguard Worker public:
37*03ce13f7SAndroid Build Coastguard Worker   explicit TargetARM32Features(const ClFlags &Flags);
38*03ce13f7SAndroid Build Coastguard Worker 
39*03ce13f7SAndroid Build Coastguard Worker   enum ARM32InstructionSet {
40*03ce13f7SAndroid Build Coastguard Worker     Begin,
41*03ce13f7SAndroid Build Coastguard Worker     // Neon is the PNaCl baseline instruction set.
42*03ce13f7SAndroid Build Coastguard Worker     Neon = Begin,
43*03ce13f7SAndroid Build Coastguard Worker     HWDivArm, // HW divide in ARM mode (not just Thumb mode).
44*03ce13f7SAndroid Build Coastguard Worker     End
45*03ce13f7SAndroid Build Coastguard Worker   };
46*03ce13f7SAndroid Build Coastguard Worker 
hasFeature(ARM32InstructionSet I)47*03ce13f7SAndroid Build Coastguard Worker   bool hasFeature(ARM32InstructionSet I) const { return I <= InstructionSet; }
48*03ce13f7SAndroid Build Coastguard Worker 
49*03ce13f7SAndroid Build Coastguard Worker private:
50*03ce13f7SAndroid Build Coastguard Worker   ARM32InstructionSet InstructionSet = ARM32InstructionSet::Begin;
51*03ce13f7SAndroid Build Coastguard Worker };
52*03ce13f7SAndroid Build Coastguard Worker 
53*03ce13f7SAndroid Build Coastguard Worker // The target lowering logic for ARM32.
54*03ce13f7SAndroid Build Coastguard Worker class TargetARM32 : public TargetLowering {
55*03ce13f7SAndroid Build Coastguard Worker   TargetARM32() = delete;
56*03ce13f7SAndroid Build Coastguard Worker   TargetARM32(const TargetARM32 &) = delete;
57*03ce13f7SAndroid Build Coastguard Worker   TargetARM32 &operator=(const TargetARM32 &) = delete;
58*03ce13f7SAndroid Build Coastguard Worker 
59*03ce13f7SAndroid Build Coastguard Worker public:
60*03ce13f7SAndroid Build Coastguard Worker   static void staticInit(GlobalContext *Ctx);
61*03ce13f7SAndroid Build Coastguard Worker 
shouldBePooled(const Constant * C)62*03ce13f7SAndroid Build Coastguard Worker   static bool shouldBePooled(const Constant *C) {
63*03ce13f7SAndroid Build Coastguard Worker     if (auto *ConstDouble = llvm::dyn_cast<ConstantDouble>(C)) {
64*03ce13f7SAndroid Build Coastguard Worker       return !Utils::isPositiveZero(ConstDouble->getValue());
65*03ce13f7SAndroid Build Coastguard Worker     }
66*03ce13f7SAndroid Build Coastguard Worker     if (llvm::isa<ConstantFloat>(C))
67*03ce13f7SAndroid Build Coastguard Worker       return true;
68*03ce13f7SAndroid Build Coastguard Worker     return false;
69*03ce13f7SAndroid Build Coastguard Worker   }
70*03ce13f7SAndroid Build Coastguard Worker 
getPointerType()71*03ce13f7SAndroid Build Coastguard Worker   static ::Ice::Type getPointerType() { return ::Ice::IceType_i32; }
72*03ce13f7SAndroid Build Coastguard Worker 
73*03ce13f7SAndroid Build Coastguard Worker   // TODO(jvoung): return a unique_ptr.
create(Cfg * Func)74*03ce13f7SAndroid Build Coastguard Worker   static std::unique_ptr<::Ice::TargetLowering> create(Cfg *Func) {
75*03ce13f7SAndroid Build Coastguard Worker     return makeUnique<TargetARM32>(Func);
76*03ce13f7SAndroid Build Coastguard Worker   }
77*03ce13f7SAndroid Build Coastguard Worker 
createAssembler()78*03ce13f7SAndroid Build Coastguard Worker   std::unique_ptr<::Ice::Assembler> createAssembler() const override {
79*03ce13f7SAndroid Build Coastguard Worker     return makeUnique<ARM32::AssemblerARM32>();
80*03ce13f7SAndroid Build Coastguard Worker   }
81*03ce13f7SAndroid Build Coastguard Worker 
initNodeForLowering(CfgNode * Node)82*03ce13f7SAndroid Build Coastguard Worker   void initNodeForLowering(CfgNode *Node) override {
83*03ce13f7SAndroid Build Coastguard Worker     Computations.forgetProducers();
84*03ce13f7SAndroid Build Coastguard Worker     Computations.recordProducers(Node);
85*03ce13f7SAndroid Build Coastguard Worker     Computations.dump(Func);
86*03ce13f7SAndroid Build Coastguard Worker   }
87*03ce13f7SAndroid Build Coastguard Worker 
88*03ce13f7SAndroid Build Coastguard Worker   void translateOm1() override;
89*03ce13f7SAndroid Build Coastguard Worker   void translateO2() override;
90*03ce13f7SAndroid Build Coastguard Worker   bool doBranchOpt(Inst *I, const CfgNode *NextNode) override;
91*03ce13f7SAndroid Build Coastguard Worker 
getNumRegisters()92*03ce13f7SAndroid Build Coastguard Worker   SizeT getNumRegisters() const override { return RegARM32::Reg_NUM; }
93*03ce13f7SAndroid Build Coastguard Worker   Variable *getPhysicalRegister(RegNumT RegNum,
94*03ce13f7SAndroid Build Coastguard Worker                                 Type Ty = IceType_void) override;
95*03ce13f7SAndroid Build Coastguard Worker   const char *getRegName(RegNumT RegNum, Type Ty) const override;
96*03ce13f7SAndroid Build Coastguard Worker   SmallBitVector getRegisterSet(RegSetMask Include,
97*03ce13f7SAndroid Build Coastguard Worker                                 RegSetMask Exclude) const override;
98*03ce13f7SAndroid Build Coastguard Worker   const SmallBitVector &
getRegistersForVariable(const Variable * Var)99*03ce13f7SAndroid Build Coastguard Worker   getRegistersForVariable(const Variable *Var) const override {
100*03ce13f7SAndroid Build Coastguard Worker     RegClass RC = Var->getRegClass();
101*03ce13f7SAndroid Build Coastguard Worker     switch (RC) {
102*03ce13f7SAndroid Build Coastguard Worker     default:
103*03ce13f7SAndroid Build Coastguard Worker       assert(RC < RC_Target);
104*03ce13f7SAndroid Build Coastguard Worker       return TypeToRegisterSet[RC];
105*03ce13f7SAndroid Build Coastguard Worker     case (RegClass)RegARM32::RCARM32_QtoS:
106*03ce13f7SAndroid Build Coastguard Worker       return TypeToRegisterSet[RC];
107*03ce13f7SAndroid Build Coastguard Worker     }
108*03ce13f7SAndroid Build Coastguard Worker   }
109*03ce13f7SAndroid Build Coastguard Worker   const SmallBitVector &
getAllRegistersForVariable(const Variable * Var)110*03ce13f7SAndroid Build Coastguard Worker   getAllRegistersForVariable(const Variable *Var) const override {
111*03ce13f7SAndroid Build Coastguard Worker     RegClass RC = Var->getRegClass();
112*03ce13f7SAndroid Build Coastguard Worker     assert((RegARM32::RegClassARM32)RC < RegARM32::RCARM32_NUM);
113*03ce13f7SAndroid Build Coastguard Worker     return TypeToRegisterSetUnfiltered[RC];
114*03ce13f7SAndroid Build Coastguard Worker   }
getAliasesForRegister(RegNumT Reg)115*03ce13f7SAndroid Build Coastguard Worker   const SmallBitVector &getAliasesForRegister(RegNumT Reg) const override {
116*03ce13f7SAndroid Build Coastguard Worker     return RegisterAliases[Reg];
117*03ce13f7SAndroid Build Coastguard Worker   }
hasFramePointer()118*03ce13f7SAndroid Build Coastguard Worker   bool hasFramePointer() const override { return UsesFramePointer; }
setHasFramePointer()119*03ce13f7SAndroid Build Coastguard Worker   void setHasFramePointer() override { UsesFramePointer = true; }
getStackReg()120*03ce13f7SAndroid Build Coastguard Worker   RegNumT getStackReg() const override { return RegARM32::Reg_sp; }
getFrameReg()121*03ce13f7SAndroid Build Coastguard Worker   RegNumT getFrameReg() const override { return RegARM32::Reg_fp; }
getFrameOrStackReg()122*03ce13f7SAndroid Build Coastguard Worker   RegNumT getFrameOrStackReg() const override {
123*03ce13f7SAndroid Build Coastguard Worker     return UsesFramePointer ? getFrameReg() : getStackReg();
124*03ce13f7SAndroid Build Coastguard Worker   }
getReservedTmpReg()125*03ce13f7SAndroid Build Coastguard Worker   RegNumT getReservedTmpReg() const { return RegARM32::Reg_ip; }
126*03ce13f7SAndroid Build Coastguard Worker 
typeWidthInBytesOnStack(Type Ty)127*03ce13f7SAndroid Build Coastguard Worker   size_t typeWidthInBytesOnStack(Type Ty) const override {
128*03ce13f7SAndroid Build Coastguard Worker     // Round up to the next multiple of 4 bytes. In particular, i1, i8, and i16
129*03ce13f7SAndroid Build Coastguard Worker     // are rounded up to 4 bytes.
130*03ce13f7SAndroid Build Coastguard Worker     return (typeWidthInBytes(Ty) + 3) & ~3;
131*03ce13f7SAndroid Build Coastguard Worker   }
132*03ce13f7SAndroid Build Coastguard Worker   uint32_t getStackAlignment() const override;
reserveFixedAllocaArea(size_t Size,size_t Align)133*03ce13f7SAndroid Build Coastguard Worker   void reserveFixedAllocaArea(size_t Size, size_t Align) override {
134*03ce13f7SAndroid Build Coastguard Worker     FixedAllocaSizeBytes = Size;
135*03ce13f7SAndroid Build Coastguard Worker     assert(llvm::isPowerOf2_32(Align));
136*03ce13f7SAndroid Build Coastguard Worker     FixedAllocaAlignBytes = Align;
137*03ce13f7SAndroid Build Coastguard Worker     PrologEmitsFixedAllocas = true;
138*03ce13f7SAndroid Build Coastguard Worker   }
getFrameFixedAllocaOffset()139*03ce13f7SAndroid Build Coastguard Worker   int32_t getFrameFixedAllocaOffset() const override {
140*03ce13f7SAndroid Build Coastguard Worker     return FixedAllocaSizeBytes - (SpillAreaSizeBytes - MaxOutArgsSizeBytes);
141*03ce13f7SAndroid Build Coastguard Worker   }
maxOutArgsSizeBytes()142*03ce13f7SAndroid Build Coastguard Worker   uint32_t maxOutArgsSizeBytes() const override { return MaxOutArgsSizeBytes; }
143*03ce13f7SAndroid Build Coastguard Worker 
shouldSplitToVariable64On32(Type Ty)144*03ce13f7SAndroid Build Coastguard Worker   bool shouldSplitToVariable64On32(Type Ty) const override {
145*03ce13f7SAndroid Build Coastguard Worker     return Ty == IceType_i64;
146*03ce13f7SAndroid Build Coastguard Worker   }
147*03ce13f7SAndroid Build Coastguard Worker 
148*03ce13f7SAndroid Build Coastguard Worker   // TODO(ascull): what size is best for ARM?
getMinJumpTableSize()149*03ce13f7SAndroid Build Coastguard Worker   SizeT getMinJumpTableSize() const override { return 3; }
150*03ce13f7SAndroid Build Coastguard Worker   void emitJumpTable(const Cfg *Func,
151*03ce13f7SAndroid Build Coastguard Worker                      const InstJumpTable *JumpTable) const override;
152*03ce13f7SAndroid Build Coastguard Worker 
153*03ce13f7SAndroid Build Coastguard Worker   void emitVariable(const Variable *Var) const override;
154*03ce13f7SAndroid Build Coastguard Worker 
155*03ce13f7SAndroid Build Coastguard Worker   void emit(const ConstantUndef *C) const final;
156*03ce13f7SAndroid Build Coastguard Worker   void emit(const ConstantInteger32 *C) const final;
157*03ce13f7SAndroid Build Coastguard Worker   void emit(const ConstantInteger64 *C) const final;
158*03ce13f7SAndroid Build Coastguard Worker   void emit(const ConstantFloat *C) const final;
159*03ce13f7SAndroid Build Coastguard Worker   void emit(const ConstantDouble *C) const final;
160*03ce13f7SAndroid Build Coastguard Worker   void emit(const ConstantRelocatable *C) const final;
161*03ce13f7SAndroid Build Coastguard Worker 
162*03ce13f7SAndroid Build Coastguard Worker   void lowerArguments() override;
163*03ce13f7SAndroid Build Coastguard Worker   void addProlog(CfgNode *Node) override;
164*03ce13f7SAndroid Build Coastguard Worker   void addEpilog(CfgNode *Node) override;
165*03ce13f7SAndroid Build Coastguard Worker 
166*03ce13f7SAndroid Build Coastguard Worker   Operand *loOperand(Operand *Operand);
167*03ce13f7SAndroid Build Coastguard Worker   Operand *hiOperand(Operand *Operand);
168*03ce13f7SAndroid Build Coastguard Worker   void finishArgumentLowering(Variable *Arg, Variable *FramePtr,
169*03ce13f7SAndroid Build Coastguard Worker                               size_t BasicFrameOffset, size_t *InArgsSizeBytes);
170*03ce13f7SAndroid Build Coastguard Worker 
hasCPUFeature(TargetARM32Features::ARM32InstructionSet I)171*03ce13f7SAndroid Build Coastguard Worker   bool hasCPUFeature(TargetARM32Features::ARM32InstructionSet I) const {
172*03ce13f7SAndroid Build Coastguard Worker     return CPUFeatures.hasFeature(I);
173*03ce13f7SAndroid Build Coastguard Worker   }
174*03ce13f7SAndroid Build Coastguard Worker 
175*03ce13f7SAndroid Build Coastguard Worker   enum OperandLegalization {
176*03ce13f7SAndroid Build Coastguard Worker     Legal_Reg = 1 << 0,  /// physical register, not stack location
177*03ce13f7SAndroid Build Coastguard Worker     Legal_Flex = 1 << 1, /// A flexible operand2, which can hold rotated small
178*03ce13f7SAndroid Build Coastguard Worker                          /// immediates, shifted registers, or modified fp imm.
179*03ce13f7SAndroid Build Coastguard Worker     Legal_Mem = 1 << 2,  /// includes [r0, r1 lsl #2] as well as [sp, #12]
180*03ce13f7SAndroid Build Coastguard Worker     Legal_Rematerializable = 1 << 3,
181*03ce13f7SAndroid Build Coastguard Worker     Legal_Default = ~Legal_Rematerializable,
182*03ce13f7SAndroid Build Coastguard Worker   };
183*03ce13f7SAndroid Build Coastguard Worker 
184*03ce13f7SAndroid Build Coastguard Worker   using LegalMask = uint32_t;
185*03ce13f7SAndroid Build Coastguard Worker   Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT());
186*03ce13f7SAndroid Build Coastguard Worker   Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
187*03ce13f7SAndroid Build Coastguard Worker                     RegNumT RegNum = RegNumT());
188*03ce13f7SAndroid Build Coastguard Worker   Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT());
189*03ce13f7SAndroid Build Coastguard Worker 
shAmtImm(uint32_t ShAmtImm)190*03ce13f7SAndroid Build Coastguard Worker   OperandARM32ShAmtImm *shAmtImm(uint32_t ShAmtImm) const {
191*03ce13f7SAndroid Build Coastguard Worker     assert(ShAmtImm < 32);
192*03ce13f7SAndroid Build Coastguard Worker     return OperandARM32ShAmtImm::create(
193*03ce13f7SAndroid Build Coastguard Worker         Func,
194*03ce13f7SAndroid Build Coastguard Worker         llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(ShAmtImm & 0x1F)));
195*03ce13f7SAndroid Build Coastguard Worker   }
196*03ce13f7SAndroid Build Coastguard Worker 
getCtx()197*03ce13f7SAndroid Build Coastguard Worker   GlobalContext *getCtx() const { return Ctx; }
198*03ce13f7SAndroid Build Coastguard Worker 
199*03ce13f7SAndroid Build Coastguard Worker protected:
200*03ce13f7SAndroid Build Coastguard Worker   explicit TargetARM32(Cfg *Func);
201*03ce13f7SAndroid Build Coastguard Worker 
202*03ce13f7SAndroid Build Coastguard Worker   void postLower() override;
203*03ce13f7SAndroid Build Coastguard Worker 
204*03ce13f7SAndroid Build Coastguard Worker   enum SafeBoolChain {
205*03ce13f7SAndroid Build Coastguard Worker     SBC_No,
206*03ce13f7SAndroid Build Coastguard Worker     SBC_Yes,
207*03ce13f7SAndroid Build Coastguard Worker   };
208*03ce13f7SAndroid Build Coastguard Worker 
209*03ce13f7SAndroid Build Coastguard Worker   void lowerAlloca(const InstAlloca *Instr) override;
210*03ce13f7SAndroid Build Coastguard Worker   SafeBoolChain lowerInt1Arithmetic(const InstArithmetic *Instr);
211*03ce13f7SAndroid Build Coastguard Worker   void lowerInt64Arithmetic(InstArithmetic::OpKind Op, Variable *Dest,
212*03ce13f7SAndroid Build Coastguard Worker                             Operand *Src0, Operand *Src1);
213*03ce13f7SAndroid Build Coastguard Worker   void lowerArithmetic(const InstArithmetic *Instr) override;
214*03ce13f7SAndroid Build Coastguard Worker   void lowerAssign(const InstAssign *Instr) override;
215*03ce13f7SAndroid Build Coastguard Worker   void lowerBr(const InstBr *Instr) override;
216*03ce13f7SAndroid Build Coastguard Worker   void lowerCall(const InstCall *Instr) override;
217*03ce13f7SAndroid Build Coastguard Worker   void lowerCast(const InstCast *Instr) override;
218*03ce13f7SAndroid Build Coastguard Worker   void lowerExtractElement(const InstExtractElement *Instr) override;
219*03ce13f7SAndroid Build Coastguard Worker 
220*03ce13f7SAndroid Build Coastguard Worker   /// CondWhenTrue is a helper type returned by every method in the lowering
221*03ce13f7SAndroid Build Coastguard Worker   /// that emits code to set the condition codes.
222*03ce13f7SAndroid Build Coastguard Worker   class CondWhenTrue {
223*03ce13f7SAndroid Build Coastguard Worker   public:
224*03ce13f7SAndroid Build Coastguard Worker     explicit CondWhenTrue(CondARM32::Cond T0,
225*03ce13f7SAndroid Build Coastguard Worker                           CondARM32::Cond T1 = CondARM32::kNone)
WhenTrue0(T0)226*03ce13f7SAndroid Build Coastguard Worker         : WhenTrue0(T0), WhenTrue1(T1) {
227*03ce13f7SAndroid Build Coastguard Worker       assert(T1 == CondARM32::kNone || T0 != CondARM32::kNone);
228*03ce13f7SAndroid Build Coastguard Worker       assert(T1 != T0 || T0 == CondARM32::kNone);
229*03ce13f7SAndroid Build Coastguard Worker     }
230*03ce13f7SAndroid Build Coastguard Worker     CondARM32::Cond WhenTrue0;
231*03ce13f7SAndroid Build Coastguard Worker     CondARM32::Cond WhenTrue1;
232*03ce13f7SAndroid Build Coastguard Worker 
233*03ce13f7SAndroid Build Coastguard Worker     /// invert returns a new object with WhenTrue0 and WhenTrue1 inverted.
invert()234*03ce13f7SAndroid Build Coastguard Worker     CondWhenTrue invert() const {
235*03ce13f7SAndroid Build Coastguard Worker       switch (WhenTrue0) {
236*03ce13f7SAndroid Build Coastguard Worker       default:
237*03ce13f7SAndroid Build Coastguard Worker         if (WhenTrue1 == CondARM32::kNone)
238*03ce13f7SAndroid Build Coastguard Worker           return CondWhenTrue(InstARM32::getOppositeCondition(WhenTrue0));
239*03ce13f7SAndroid Build Coastguard Worker         return CondWhenTrue(InstARM32::getOppositeCondition(WhenTrue0),
240*03ce13f7SAndroid Build Coastguard Worker                             InstARM32::getOppositeCondition(WhenTrue1));
241*03ce13f7SAndroid Build Coastguard Worker       case CondARM32::AL:
242*03ce13f7SAndroid Build Coastguard Worker         return CondWhenTrue(CondARM32::kNone);
243*03ce13f7SAndroid Build Coastguard Worker       case CondARM32::kNone:
244*03ce13f7SAndroid Build Coastguard Worker         return CondWhenTrue(CondARM32::AL);
245*03ce13f7SAndroid Build Coastguard Worker       }
246*03ce13f7SAndroid Build Coastguard Worker     }
247*03ce13f7SAndroid Build Coastguard Worker   };
248*03ce13f7SAndroid Build Coastguard Worker 
249*03ce13f7SAndroid Build Coastguard Worker   CondWhenTrue lowerFcmpCond(const InstFcmp *Instr);
250*03ce13f7SAndroid Build Coastguard Worker   void lowerFcmp(const InstFcmp *Instr) override;
251*03ce13f7SAndroid Build Coastguard Worker   CondWhenTrue lowerInt8AndInt16IcmpCond(InstIcmp::ICond Condition,
252*03ce13f7SAndroid Build Coastguard Worker                                          Operand *Src0, Operand *Src1);
253*03ce13f7SAndroid Build Coastguard Worker   CondWhenTrue lowerInt32IcmpCond(InstIcmp::ICond Condition, Operand *Src0,
254*03ce13f7SAndroid Build Coastguard Worker                                   Operand *Src1);
255*03ce13f7SAndroid Build Coastguard Worker   CondWhenTrue lowerInt64IcmpCond(InstIcmp::ICond Condition, Operand *Src0,
256*03ce13f7SAndroid Build Coastguard Worker                                   Operand *Src1);
257*03ce13f7SAndroid Build Coastguard Worker   CondWhenTrue lowerIcmpCond(InstIcmp::ICond Condition, Operand *Src0,
258*03ce13f7SAndroid Build Coastguard Worker                              Operand *Src1);
259*03ce13f7SAndroid Build Coastguard Worker   CondWhenTrue lowerIcmpCond(const InstIcmp *Instr);
260*03ce13f7SAndroid Build Coastguard Worker   void lowerIcmp(const InstIcmp *Instr) override;
261*03ce13f7SAndroid Build Coastguard Worker   /// Emits the basic sequence for lower-linked/store-exclusive loops:
262*03ce13f7SAndroid Build Coastguard Worker   ///
263*03ce13f7SAndroid Build Coastguard Worker   /// retry:
264*03ce13f7SAndroid Build Coastguard Worker   ///        ldrex tmp, [Addr]
265*03ce13f7SAndroid Build Coastguard Worker   ///        StoreValue = Operation(tmp)
266*03ce13f7SAndroid Build Coastguard Worker   ///        strexCond success, StoreValue, [Addr]
267*03ce13f7SAndroid Build Coastguard Worker   ///        cmpCond success, #0
268*03ce13f7SAndroid Build Coastguard Worker   ///        bne retry
269*03ce13f7SAndroid Build Coastguard Worker   ///
270*03ce13f7SAndroid Build Coastguard Worker   /// Operation needs to return which value to strex in Addr, it must not change
271*03ce13f7SAndroid Build Coastguard Worker   /// the flags if Cond is not AL, and must not emit any instructions that could
272*03ce13f7SAndroid Build Coastguard Worker   /// end up writing to memory. Operation also needs to handle fake-defing for
273*03ce13f7SAndroid Build Coastguard Worker   /// i64 handling.
274*03ce13f7SAndroid Build Coastguard Worker   void
275*03ce13f7SAndroid Build Coastguard Worker   lowerLoadLinkedStoreExclusive(Type Ty, Operand *Addr,
276*03ce13f7SAndroid Build Coastguard Worker                                 std::function<Variable *(Variable *)> Operation,
277*03ce13f7SAndroid Build Coastguard Worker                                 CondARM32::Cond Cond = CondARM32::AL);
278*03ce13f7SAndroid Build Coastguard Worker   void lowerInt64AtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr,
279*03ce13f7SAndroid Build Coastguard Worker                            Operand *Val);
280*03ce13f7SAndroid Build Coastguard Worker   void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr,
281*03ce13f7SAndroid Build Coastguard Worker                       Operand *Val);
282*03ce13f7SAndroid Build Coastguard Worker   void lowerBreakpoint(const InstBreakpoint *Instr) override;
283*03ce13f7SAndroid Build Coastguard Worker   void lowerIntrinsic(const InstIntrinsic *Instr) override;
284*03ce13f7SAndroid Build Coastguard Worker   void lowerInsertElement(const InstInsertElement *Instr) override;
285*03ce13f7SAndroid Build Coastguard Worker   void lowerLoad(const InstLoad *Instr) override;
286*03ce13f7SAndroid Build Coastguard Worker   void lowerPhi(const InstPhi *Instr) override;
287*03ce13f7SAndroid Build Coastguard Worker   void lowerRet(const InstRet *Instr) override;
288*03ce13f7SAndroid Build Coastguard Worker   void lowerSelect(const InstSelect *Instr) override;
289*03ce13f7SAndroid Build Coastguard Worker   void lowerShuffleVector(const InstShuffleVector *Instr) override;
290*03ce13f7SAndroid Build Coastguard Worker   void lowerStore(const InstStore *Instr) override;
291*03ce13f7SAndroid Build Coastguard Worker   void lowerSwitch(const InstSwitch *Instr) override;
292*03ce13f7SAndroid Build Coastguard Worker   void lowerUnreachable(const InstUnreachable *Instr) override;
293*03ce13f7SAndroid Build Coastguard Worker   void prelowerPhis() override;
294*03ce13f7SAndroid Build Coastguard Worker   uint32_t getCallStackArgumentsSizeBytes(const InstCall *Instr) override;
295*03ce13f7SAndroid Build Coastguard Worker   void genTargetHelperCallFor(Inst *Instr) override;
296*03ce13f7SAndroid Build Coastguard Worker   void doAddressOptLoad() override;
297*03ce13f7SAndroid Build Coastguard Worker   void doAddressOptStore() override;
298*03ce13f7SAndroid Build Coastguard Worker 
299*03ce13f7SAndroid Build Coastguard Worker   OperandARM32Mem *formMemoryOperand(Operand *Ptr, Type Ty);
300*03ce13f7SAndroid Build Coastguard Worker 
301*03ce13f7SAndroid Build Coastguard Worker   Variable64On32 *makeI64RegPair();
302*03ce13f7SAndroid Build Coastguard Worker   Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT());
303*03ce13f7SAndroid Build Coastguard Worker   static Type stackSlotType();
304*03ce13f7SAndroid Build Coastguard Worker   Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT());
305*03ce13f7SAndroid Build Coastguard Worker   void alignRegisterPow2(Variable *Reg, uint32_t Align,
306*03ce13f7SAndroid Build Coastguard Worker                          RegNumT TmpRegNum = RegNumT());
307*03ce13f7SAndroid Build Coastguard Worker 
308*03ce13f7SAndroid Build Coastguard Worker   /// Returns a vector in a register with the given constant entries.
309*03ce13f7SAndroid Build Coastguard Worker   Variable *makeVectorOfZeros(Type Ty, RegNumT RegNum = RegNumT());
310*03ce13f7SAndroid Build Coastguard Worker 
311*03ce13f7SAndroid Build Coastguard Worker   // If a divide-by-zero check is needed, inserts a: test; branch .LSKIP; trap;
312*03ce13f7SAndroid Build Coastguard Worker   // .LSKIP: <continuation>. If no check is needed nothing is inserted.
313*03ce13f7SAndroid Build Coastguard Worker   void div0Check(Type Ty, Operand *SrcLo, Operand *SrcHi);
314*03ce13f7SAndroid Build Coastguard Worker   using ExtInstr = void (TargetARM32::*)(Variable *, Variable *,
315*03ce13f7SAndroid Build Coastguard Worker                                          CondARM32::Cond);
316*03ce13f7SAndroid Build Coastguard Worker   using DivInstr = void (TargetARM32::*)(Variable *, Variable *, Variable *,
317*03ce13f7SAndroid Build Coastguard Worker                                          CondARM32::Cond);
318*03ce13f7SAndroid Build Coastguard Worker   void lowerIDivRem(Variable *Dest, Variable *T, Variable *Src0R, Operand *Src1,
319*03ce13f7SAndroid Build Coastguard Worker                     ExtInstr ExtFunc, DivInstr DivFunc, bool IsRemainder);
320*03ce13f7SAndroid Build Coastguard Worker 
321*03ce13f7SAndroid Build Coastguard Worker   void lowerCLZ(Variable *Dest, Variable *ValLo, Variable *ValHi);
322*03ce13f7SAndroid Build Coastguard Worker 
323*03ce13f7SAndroid Build Coastguard Worker   // The following are helpers that insert lowered ARM32 instructions with
324*03ce13f7SAndroid Build Coastguard Worker   // minimal syntactic overhead, so that the lowering code can look as close to
325*03ce13f7SAndroid Build Coastguard Worker   // assembly as practical.
326*03ce13f7SAndroid Build Coastguard Worker   void _add(Variable *Dest, Variable *Src0, Operand *Src1,
327*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
328*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Add>(Dest, Src0, Src1, Pred);
329*03ce13f7SAndroid Build Coastguard Worker   }
330*03ce13f7SAndroid Build Coastguard Worker   void _adds(Variable *Dest, Variable *Src0, Operand *Src1,
331*03ce13f7SAndroid Build Coastguard Worker              CondARM32::Cond Pred = CondARM32::AL) {
332*03ce13f7SAndroid Build Coastguard Worker     constexpr bool SetFlags = true;
333*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Add>(Dest, Src0, Src1, Pred, SetFlags);
334*03ce13f7SAndroid Build Coastguard Worker     if (SetFlags) {
335*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeUse>(Dest);
336*03ce13f7SAndroid Build Coastguard Worker     }
337*03ce13f7SAndroid Build Coastguard Worker   }
338*03ce13f7SAndroid Build Coastguard Worker   void _adc(Variable *Dest, Variable *Src0, Operand *Src1,
339*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
340*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Adc>(Dest, Src0, Src1, Pred);
341*03ce13f7SAndroid Build Coastguard Worker   }
342*03ce13f7SAndroid Build Coastguard Worker   void _and(Variable *Dest, Variable *Src0, Operand *Src1,
343*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
344*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32And>(Dest, Src0, Src1, Pred);
345*03ce13f7SAndroid Build Coastguard Worker   }
346*03ce13f7SAndroid Build Coastguard Worker   void _asr(Variable *Dest, Variable *Src0, Operand *Src1,
347*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
348*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Asr>(Dest, Src0, Src1, Pred);
349*03ce13f7SAndroid Build Coastguard Worker   }
350*03ce13f7SAndroid Build Coastguard Worker   void _bic(Variable *Dest, Variable *Src0, Operand *Src1,
351*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
352*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Bic>(Dest, Src0, Src1, Pred);
353*03ce13f7SAndroid Build Coastguard Worker   }
_br(CfgNode * TargetTrue,CfgNode * TargetFalse,CondARM32::Cond Condition)354*03ce13f7SAndroid Build Coastguard Worker   void _br(CfgNode *TargetTrue, CfgNode *TargetFalse,
355*03ce13f7SAndroid Build Coastguard Worker            CondARM32::Cond Condition) {
356*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Br>(TargetTrue, TargetFalse, Condition);
357*03ce13f7SAndroid Build Coastguard Worker   }
_br(CfgNode * Target)358*03ce13f7SAndroid Build Coastguard Worker   void _br(CfgNode *Target) { Context.insert<InstARM32Br>(Target); }
_br(CfgNode * Target,CondARM32::Cond Condition)359*03ce13f7SAndroid Build Coastguard Worker   void _br(CfgNode *Target, CondARM32::Cond Condition) {
360*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Br>(Target, Condition);
361*03ce13f7SAndroid Build Coastguard Worker   }
_br(InstARM32Label * Label,CondARM32::Cond Condition)362*03ce13f7SAndroid Build Coastguard Worker   void _br(InstARM32Label *Label, CondARM32::Cond Condition) {
363*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Br>(Label, Condition);
364*03ce13f7SAndroid Build Coastguard Worker   }
365*03ce13f7SAndroid Build Coastguard Worker   void _cmn(Variable *Src0, Operand *Src1,
366*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
367*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Cmn>(Src0, Src1, Pred);
368*03ce13f7SAndroid Build Coastguard Worker   }
369*03ce13f7SAndroid Build Coastguard Worker   void _cmp(Variable *Src0, Operand *Src1,
370*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
371*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Cmp>(Src0, Src1, Pred);
372*03ce13f7SAndroid Build Coastguard Worker   }
373*03ce13f7SAndroid Build Coastguard Worker   void _clz(Variable *Dest, Variable *Src0,
374*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
375*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Clz>(Dest, Src0, Pred);
376*03ce13f7SAndroid Build Coastguard Worker   }
_dmb()377*03ce13f7SAndroid Build Coastguard Worker   void _dmb() { Context.insert<InstARM32Dmb>(); }
378*03ce13f7SAndroid Build Coastguard Worker   void _eor(Variable *Dest, Variable *Src0, Operand *Src1,
379*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
380*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Eor>(Dest, Src0, Src1, Pred);
381*03ce13f7SAndroid Build Coastguard Worker   }
382*03ce13f7SAndroid Build Coastguard Worker   /// _ldr, for all your memory to Variable data moves. It handles all types
383*03ce13f7SAndroid Build Coastguard Worker   /// (integer, floating point, and vectors.) Addr needs to be valid for Dest's
384*03ce13f7SAndroid Build Coastguard Worker   /// type (e.g., no immediates for vector loads, and no index registers for fp
385*03ce13f7SAndroid Build Coastguard Worker   /// loads.)
386*03ce13f7SAndroid Build Coastguard Worker   void _ldr(Variable *Dest, OperandARM32Mem *Addr,
387*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
388*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Ldr>(Dest, Addr, Pred);
389*03ce13f7SAndroid Build Coastguard Worker   }
390*03ce13f7SAndroid Build Coastguard Worker   InstARM32Ldrex *_ldrex(Variable *Dest, OperandARM32Mem *Addr,
391*03ce13f7SAndroid Build Coastguard Worker                          CondARM32::Cond Pred = CondARM32::AL) {
392*03ce13f7SAndroid Build Coastguard Worker     auto *Ldrex = Context.insert<InstARM32Ldrex>(Dest, Addr, Pred);
393*03ce13f7SAndroid Build Coastguard Worker     if (auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest)) {
394*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeDef>(Dest64->getLo(), Dest);
395*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeDef>(Dest64->getHi(), Dest);
396*03ce13f7SAndroid Build Coastguard Worker     }
397*03ce13f7SAndroid Build Coastguard Worker     return Ldrex;
398*03ce13f7SAndroid Build Coastguard Worker   }
399*03ce13f7SAndroid Build Coastguard Worker   void _lsl(Variable *Dest, Variable *Src0, Operand *Src1,
400*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
401*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Lsl>(Dest, Src0, Src1, Pred);
402*03ce13f7SAndroid Build Coastguard Worker   }
403*03ce13f7SAndroid Build Coastguard Worker   void _lsls(Variable *Dest, Variable *Src0, Operand *Src1,
404*03ce13f7SAndroid Build Coastguard Worker              CondARM32::Cond Pred = CondARM32::AL) {
405*03ce13f7SAndroid Build Coastguard Worker     constexpr bool SetFlags = true;
406*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Lsl>(Dest, Src0, Src1, Pred, SetFlags);
407*03ce13f7SAndroid Build Coastguard Worker     if (SetFlags) {
408*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeUse>(Dest);
409*03ce13f7SAndroid Build Coastguard Worker     }
410*03ce13f7SAndroid Build Coastguard Worker   }
411*03ce13f7SAndroid Build Coastguard Worker   void _lsr(Variable *Dest, Variable *Src0, Operand *Src1,
412*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
413*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Lsr>(Dest, Src0, Src1, Pred);
414*03ce13f7SAndroid Build Coastguard Worker   }
415*03ce13f7SAndroid Build Coastguard Worker   void _mla(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc,
416*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
417*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Mla>(Dest, Src0, Src1, Acc, Pred);
418*03ce13f7SAndroid Build Coastguard Worker   }
419*03ce13f7SAndroid Build Coastguard Worker   void _mls(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc,
420*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
421*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Mls>(Dest, Src0, Src1, Acc, Pred);
422*03ce13f7SAndroid Build Coastguard Worker   }
423*03ce13f7SAndroid Build Coastguard Worker   /// _mov, for all your Variable to Variable data movement needs. It handles
424*03ce13f7SAndroid Build Coastguard Worker   /// all types (integer, floating point, and vectors), as well as moves between
425*03ce13f7SAndroid Build Coastguard Worker   /// Core and VFP registers. This is not a panacea: you must obey the (weird,
426*03ce13f7SAndroid Build Coastguard Worker   /// confusing, non-uniform) rules for data moves in ARM.
427*03ce13f7SAndroid Build Coastguard Worker   void _mov(Variable *Dest, Operand *Src0,
428*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
429*03ce13f7SAndroid Build Coastguard Worker     // _mov used to be unique in the sense that it would create a temporary
430*03ce13f7SAndroid Build Coastguard Worker     // automagically if Dest was nullptr. It won't do that anymore, so we keep
431*03ce13f7SAndroid Build Coastguard Worker     // an assert around just in case there is some untested code path where Dest
432*03ce13f7SAndroid Build Coastguard Worker     // is nullptr.
433*03ce13f7SAndroid Build Coastguard Worker     assert(Dest != nullptr);
434*03ce13f7SAndroid Build Coastguard Worker     assert(!llvm::isa<OperandARM32Mem>(Src0));
435*03ce13f7SAndroid Build Coastguard Worker     auto *Instr = Context.insert<InstARM32Mov>(Dest, Src0, Pred);
436*03ce13f7SAndroid Build Coastguard Worker 
437*03ce13f7SAndroid Build Coastguard Worker     if (Instr->isMultiDest()) {
438*03ce13f7SAndroid Build Coastguard Worker       // If Instr is multi-dest, then Dest must be a Variable64On32. We add a
439*03ce13f7SAndroid Build Coastguard Worker       // fake-def for Instr.DestHi here.
440*03ce13f7SAndroid Build Coastguard Worker       assert(llvm::isa<Variable64On32>(Dest));
441*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeDef>(Instr->getDestHi());
442*03ce13f7SAndroid Build Coastguard Worker     }
443*03ce13f7SAndroid Build Coastguard Worker   }
444*03ce13f7SAndroid Build Coastguard Worker 
445*03ce13f7SAndroid Build Coastguard Worker   void _mov_redefined(Variable *Dest, Operand *Src0,
446*03ce13f7SAndroid Build Coastguard Worker                       CondARM32::Cond Pred = CondARM32::AL) {
447*03ce13f7SAndroid Build Coastguard Worker     auto *Instr = Context.insert<InstARM32Mov>(Dest, Src0, Pred);
448*03ce13f7SAndroid Build Coastguard Worker     Instr->setDestRedefined();
449*03ce13f7SAndroid Build Coastguard Worker     if (Instr->isMultiDest()) {
450*03ce13f7SAndroid Build Coastguard Worker       // If Instr is multi-dest, then Dest must be a Variable64On32. We add a
451*03ce13f7SAndroid Build Coastguard Worker       // fake-def for Instr.DestHi here.
452*03ce13f7SAndroid Build Coastguard Worker       assert(llvm::isa<Variable64On32>(Dest));
453*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeDef>(Instr->getDestHi());
454*03ce13f7SAndroid Build Coastguard Worker     }
455*03ce13f7SAndroid Build Coastguard Worker   }
456*03ce13f7SAndroid Build Coastguard Worker 
_nop()457*03ce13f7SAndroid Build Coastguard Worker   void _nop() { Context.insert<InstARM32Nop>(); }
458*03ce13f7SAndroid Build Coastguard Worker 
459*03ce13f7SAndroid Build Coastguard Worker   // Generates a vmov instruction to extract the given index from a vector
460*03ce13f7SAndroid Build Coastguard Worker   // register.
461*03ce13f7SAndroid Build Coastguard Worker   void _extractelement(Variable *Dest, Variable *Src0, uint32_t Index,
462*03ce13f7SAndroid Build Coastguard Worker                        CondARM32::Cond Pred = CondARM32::AL) {
463*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Extract>(Dest, Src0, Index, Pred);
464*03ce13f7SAndroid Build Coastguard Worker   }
465*03ce13f7SAndroid Build Coastguard Worker 
466*03ce13f7SAndroid Build Coastguard Worker   // Generates a vmov instruction to insert a value into the given index of a
467*03ce13f7SAndroid Build Coastguard Worker   // vector register.
468*03ce13f7SAndroid Build Coastguard Worker   void _insertelement(Variable *Dest, Variable *Src0, uint32_t Index,
469*03ce13f7SAndroid Build Coastguard Worker                       CondARM32::Cond Pred = CondARM32::AL) {
470*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Insert>(Dest, Src0, Index, Pred);
471*03ce13f7SAndroid Build Coastguard Worker   }
472*03ce13f7SAndroid Build Coastguard Worker 
473*03ce13f7SAndroid Build Coastguard Worker   // --------------------------------------------------------------------------
474*03ce13f7SAndroid Build Coastguard Worker   // Begin bool folding machinery.
475*03ce13f7SAndroid Build Coastguard Worker   //
476*03ce13f7SAndroid Build Coastguard Worker   // There are three types of boolean lowerings handled by this target:
477*03ce13f7SAndroid Build Coastguard Worker   //
478*03ce13f7SAndroid Build Coastguard Worker   // 1) Boolean expressions leading to a boolean Variable definition
479*03ce13f7SAndroid Build Coastguard Worker   // ---------------------------------------------------------------
480*03ce13f7SAndroid Build Coastguard Worker   //
481*03ce13f7SAndroid Build Coastguard Worker   // Whenever a i1 Variable is live out (i.e., its live range extends beyond
482*03ce13f7SAndroid Build Coastguard Worker   // the defining basic block) we do not fold the operation. We instead
483*03ce13f7SAndroid Build Coastguard Worker   // materialize (i.e., compute) the variable normally, so that it can be used
484*03ce13f7SAndroid Build Coastguard Worker   // when needed. We also materialize i1 values that are not single use to
485*03ce13f7SAndroid Build Coastguard Worker   // avoid code duplication. These expressions are not short circuited.
486*03ce13f7SAndroid Build Coastguard Worker   //
487*03ce13f7SAndroid Build Coastguard Worker   // 2) Boolean expressions leading to a select
488*03ce13f7SAndroid Build Coastguard Worker   // ------------------------------------------
489*03ce13f7SAndroid Build Coastguard Worker   //
490*03ce13f7SAndroid Build Coastguard Worker   // These include boolean chains leading to a select instruction, as well as
491*03ce13f7SAndroid Build Coastguard Worker   // i1 Sexts. These boolean expressions are lowered to:
492*03ce13f7SAndroid Build Coastguard Worker   //
493*03ce13f7SAndroid Build Coastguard Worker   // mov T, <false value>
494*03ce13f7SAndroid Build Coastguard Worker   // CC <- eval(Boolean Expression)
495*03ce13f7SAndroid Build Coastguard Worker   // movCC T, <true value>
496*03ce13f7SAndroid Build Coastguard Worker   //
497*03ce13f7SAndroid Build Coastguard Worker   // For Sexts, <false value> is 0, and <true value> is -1.
498*03ce13f7SAndroid Build Coastguard Worker   //
499*03ce13f7SAndroid Build Coastguard Worker   // 3) Boolean expressions leading to a br i1
500*03ce13f7SAndroid Build Coastguard Worker   // -----------------------------------------
501*03ce13f7SAndroid Build Coastguard Worker   //
502*03ce13f7SAndroid Build Coastguard Worker   // These are the boolean chains leading to a branch. These chains are
503*03ce13f7SAndroid Build Coastguard Worker   // short-circuited, i.e.:
504*03ce13f7SAndroid Build Coastguard Worker   //
505*03ce13f7SAndroid Build Coastguard Worker   //   A = or i1 B, C
506*03ce13f7SAndroid Build Coastguard Worker   //   br i1 A, label %T, label %F
507*03ce13f7SAndroid Build Coastguard Worker   //
508*03ce13f7SAndroid Build Coastguard Worker   // becomes
509*03ce13f7SAndroid Build Coastguard Worker   //
510*03ce13f7SAndroid Build Coastguard Worker   //   tst B
511*03ce13f7SAndroid Build Coastguard Worker   //   jne %T
512*03ce13f7SAndroid Build Coastguard Worker   //   tst B
513*03ce13f7SAndroid Build Coastguard Worker   //   jne %T
514*03ce13f7SAndroid Build Coastguard Worker   //   j %F
515*03ce13f7SAndroid Build Coastguard Worker   //
516*03ce13f7SAndroid Build Coastguard Worker   // and
517*03ce13f7SAndroid Build Coastguard Worker   //
518*03ce13f7SAndroid Build Coastguard Worker   //   A = and i1 B, C
519*03ce13f7SAndroid Build Coastguard Worker   //   br i1 A, label %T, label %F
520*03ce13f7SAndroid Build Coastguard Worker   //
521*03ce13f7SAndroid Build Coastguard Worker   // becomes
522*03ce13f7SAndroid Build Coastguard Worker   //
523*03ce13f7SAndroid Build Coastguard Worker   //   tst B
524*03ce13f7SAndroid Build Coastguard Worker   //   jeq %F
525*03ce13f7SAndroid Build Coastguard Worker   //   tst B
526*03ce13f7SAndroid Build Coastguard Worker   //   jeq %F
527*03ce13f7SAndroid Build Coastguard Worker   //   j %T
528*03ce13f7SAndroid Build Coastguard Worker   //
529*03ce13f7SAndroid Build Coastguard Worker   // Arbitrarily long chains are short circuited, e.g
530*03ce13f7SAndroid Build Coastguard Worker   //
531*03ce13f7SAndroid Build Coastguard Worker   //   A = or  i1 B, C
532*03ce13f7SAndroid Build Coastguard Worker   //   D = and i1 A, E
533*03ce13f7SAndroid Build Coastguard Worker   //   F = and i1 G, H
534*03ce13f7SAndroid Build Coastguard Worker   //   I = or i1 D, F
535*03ce13f7SAndroid Build Coastguard Worker   //   br i1 I, label %True, label %False
536*03ce13f7SAndroid Build Coastguard Worker   //
537*03ce13f7SAndroid Build Coastguard Worker   // becomes
538*03ce13f7SAndroid Build Coastguard Worker   //
539*03ce13f7SAndroid Build Coastguard Worker   // Label[A]:
540*03ce13f7SAndroid Build Coastguard Worker   //   tst B, 1
541*03ce13f7SAndroid Build Coastguard Worker   //   bne Label[D]
542*03ce13f7SAndroid Build Coastguard Worker   //   tst C, 1
543*03ce13f7SAndroid Build Coastguard Worker   //   beq Label[I]
544*03ce13f7SAndroid Build Coastguard Worker   // Label[D]:
545*03ce13f7SAndroid Build Coastguard Worker   //   tst E, 1
546*03ce13f7SAndroid Build Coastguard Worker   //   bne %True
547*03ce13f7SAndroid Build Coastguard Worker   // Label[I]
548*03ce13f7SAndroid Build Coastguard Worker   //   tst G, 1
549*03ce13f7SAndroid Build Coastguard Worker   //   beq %False
550*03ce13f7SAndroid Build Coastguard Worker   //   tst H, 1
551*03ce13f7SAndroid Build Coastguard Worker   //   beq %False (bne %True)
552*03ce13f7SAndroid Build Coastguard Worker 
553*03ce13f7SAndroid Build Coastguard Worker   /// lowerInt1 materializes Boolean to a Variable.
554*03ce13f7SAndroid Build Coastguard Worker   SafeBoolChain lowerInt1(Variable *Dest, Operand *Boolean);
555*03ce13f7SAndroid Build Coastguard Worker 
556*03ce13f7SAndroid Build Coastguard Worker   /// lowerInt1ForSelect generates the following instruction sequence:
557*03ce13f7SAndroid Build Coastguard Worker   ///
558*03ce13f7SAndroid Build Coastguard Worker   ///   mov T, FalseValue
559*03ce13f7SAndroid Build Coastguard Worker   ///   CC <- eval(Boolean)
560*03ce13f7SAndroid Build Coastguard Worker   ///   movCC T, TrueValue
561*03ce13f7SAndroid Build Coastguard Worker   ///   mov Dest, T
562*03ce13f7SAndroid Build Coastguard Worker   ///
563*03ce13f7SAndroid Build Coastguard Worker   /// It is used for lowering select i1, as well as i1 Sext.
564*03ce13f7SAndroid Build Coastguard Worker   void lowerInt1ForSelect(Variable *Dest, Operand *Boolean, Operand *TrueValue,
565*03ce13f7SAndroid Build Coastguard Worker                           Operand *FalseValue);
566*03ce13f7SAndroid Build Coastguard Worker 
567*03ce13f7SAndroid Build Coastguard Worker   /// LowerInt1BranchTarget is used by lowerIntForBranch. It wraps a CfgNode, or
568*03ce13f7SAndroid Build Coastguard Worker   /// an InstARM32Label (but never both) so that, during br i1 lowering, we can
569*03ce13f7SAndroid Build Coastguard Worker   /// create auxiliary labels for short circuiting the condition evaluation.
570*03ce13f7SAndroid Build Coastguard Worker   class LowerInt1BranchTarget {
571*03ce13f7SAndroid Build Coastguard Worker   public:
LowerInt1BranchTarget(CfgNode * const Target)572*03ce13f7SAndroid Build Coastguard Worker     explicit LowerInt1BranchTarget(CfgNode *const Target)
573*03ce13f7SAndroid Build Coastguard Worker         : NodeTarget(Target) {}
LowerInt1BranchTarget(InstARM32Label * const Target)574*03ce13f7SAndroid Build Coastguard Worker     explicit LowerInt1BranchTarget(InstARM32Label *const Target)
575*03ce13f7SAndroid Build Coastguard Worker         : LabelTarget(Target) {}
576*03ce13f7SAndroid Build Coastguard Worker 
577*03ce13f7SAndroid Build Coastguard Worker     /// createForLabelOrDuplicate will return a new LowerInt1BranchTarget that
578*03ce13f7SAndroid Build Coastguard Worker     /// is the exact copy of this if Label is nullptr; otherwise, the returned
579*03ce13f7SAndroid Build Coastguard Worker     /// object will wrap Label instead.
580*03ce13f7SAndroid Build Coastguard Worker     LowerInt1BranchTarget
createForLabelOrDuplicate(InstARM32Label * Label)581*03ce13f7SAndroid Build Coastguard Worker     createForLabelOrDuplicate(InstARM32Label *Label) const {
582*03ce13f7SAndroid Build Coastguard Worker       if (Label != nullptr)
583*03ce13f7SAndroid Build Coastguard Worker         return LowerInt1BranchTarget(Label);
584*03ce13f7SAndroid Build Coastguard Worker       if (NodeTarget)
585*03ce13f7SAndroid Build Coastguard Worker         return LowerInt1BranchTarget(NodeTarget);
586*03ce13f7SAndroid Build Coastguard Worker       return LowerInt1BranchTarget(LabelTarget);
587*03ce13f7SAndroid Build Coastguard Worker     }
588*03ce13f7SAndroid Build Coastguard Worker 
589*03ce13f7SAndroid Build Coastguard Worker     CfgNode *const NodeTarget = nullptr;
590*03ce13f7SAndroid Build Coastguard Worker     InstARM32Label *const LabelTarget = nullptr;
591*03ce13f7SAndroid Build Coastguard Worker   };
592*03ce13f7SAndroid Build Coastguard Worker 
593*03ce13f7SAndroid Build Coastguard Worker   /// LowerInt1AllowShortCircuit is a helper type used by lowerInt1ForBranch for
594*03ce13f7SAndroid Build Coastguard Worker   /// determining which type arithmetic is allowed to be short circuited. This
595*03ce13f7SAndroid Build Coastguard Worker   /// is useful for lowering
596*03ce13f7SAndroid Build Coastguard Worker   ///
597*03ce13f7SAndroid Build Coastguard Worker   ///   t1 = and i1 A, B
598*03ce13f7SAndroid Build Coastguard Worker   ///   t2 = and i1 t1, C
599*03ce13f7SAndroid Build Coastguard Worker   ///   br i1 t2, label %False, label %True
600*03ce13f7SAndroid Build Coastguard Worker   ///
601*03ce13f7SAndroid Build Coastguard Worker   /// to
602*03ce13f7SAndroid Build Coastguard Worker   ///
603*03ce13f7SAndroid Build Coastguard Worker   ///   tst A, 1
604*03ce13f7SAndroid Build Coastguard Worker   ///   beq %False
605*03ce13f7SAndroid Build Coastguard Worker   ///   tst B, 1
606*03ce13f7SAndroid Build Coastguard Worker   ///   beq %False
607*03ce13f7SAndroid Build Coastguard Worker   ///   tst C, 1
608*03ce13f7SAndroid Build Coastguard Worker   ///   bne %True
609*03ce13f7SAndroid Build Coastguard Worker   ///   b %False
610*03ce13f7SAndroid Build Coastguard Worker   ///
611*03ce13f7SAndroid Build Coastguard Worker   /// Without this information, short circuiting would only allow to short
612*03ce13f7SAndroid Build Coastguard Worker   /// circuit a single high level instruction. For example:
613*03ce13f7SAndroid Build Coastguard Worker   ///
614*03ce13f7SAndroid Build Coastguard Worker   ///   t1 = or i1 A, B
615*03ce13f7SAndroid Build Coastguard Worker   ///   t2 = and i1 t1, C
616*03ce13f7SAndroid Build Coastguard Worker   ///   br i1 t2, label %False, label %True
617*03ce13f7SAndroid Build Coastguard Worker   ///
618*03ce13f7SAndroid Build Coastguard Worker   /// cannot be lowered to
619*03ce13f7SAndroid Build Coastguard Worker   ///
620*03ce13f7SAndroid Build Coastguard Worker   ///   tst A, 1
621*03ce13f7SAndroid Build Coastguard Worker   ///   bne %True
622*03ce13f7SAndroid Build Coastguard Worker   ///   tst B, 1
623*03ce13f7SAndroid Build Coastguard Worker   ///   bne %True
624*03ce13f7SAndroid Build Coastguard Worker   ///   tst C, 1
625*03ce13f7SAndroid Build Coastguard Worker   ///   beq %True
626*03ce13f7SAndroid Build Coastguard Worker   ///   b %False
627*03ce13f7SAndroid Build Coastguard Worker   ///
628*03ce13f7SAndroid Build Coastguard Worker   /// It needs to be lowered to
629*03ce13f7SAndroid Build Coastguard Worker   ///
630*03ce13f7SAndroid Build Coastguard Worker   ///   tst A, 1
631*03ce13f7SAndroid Build Coastguard Worker   ///   bne Aux
632*03ce13f7SAndroid Build Coastguard Worker   ///   tst B, 1
633*03ce13f7SAndroid Build Coastguard Worker   ///   beq %False
634*03ce13f7SAndroid Build Coastguard Worker   /// Aux:
635*03ce13f7SAndroid Build Coastguard Worker   ///   tst C, 1
636*03ce13f7SAndroid Build Coastguard Worker   ///   bne %True
637*03ce13f7SAndroid Build Coastguard Worker   ///   b %False
638*03ce13f7SAndroid Build Coastguard Worker   ///
639*03ce13f7SAndroid Build Coastguard Worker   /// TODO(jpp): evaluate if this kind of short circuiting hurts performance (it
640*03ce13f7SAndroid Build Coastguard Worker   /// might.)
641*03ce13f7SAndroid Build Coastguard Worker   enum LowerInt1AllowShortCircuit {
642*03ce13f7SAndroid Build Coastguard Worker     SC_And = 1,
643*03ce13f7SAndroid Build Coastguard Worker     SC_Or = 2,
644*03ce13f7SAndroid Build Coastguard Worker     SC_All = SC_And | SC_Or,
645*03ce13f7SAndroid Build Coastguard Worker   };
646*03ce13f7SAndroid Build Coastguard Worker 
647*03ce13f7SAndroid Build Coastguard Worker   /// ShortCircuitCondAndLabel wraps the condition codes that should be used
648*03ce13f7SAndroid Build Coastguard Worker   /// after a lowerInt1ForBranch returns to branch to the
649*03ce13f7SAndroid Build Coastguard Worker   /// TrueTarget/FalseTarget. If ShortCircuitLabel is not nullptr, then the
650*03ce13f7SAndroid Build Coastguard Worker   /// called lowerInt1forBranch created an internal (i.e., short-circuit) label
651*03ce13f7SAndroid Build Coastguard Worker   /// used for short circuiting.
652*03ce13f7SAndroid Build Coastguard Worker   class ShortCircuitCondAndLabel {
653*03ce13f7SAndroid Build Coastguard Worker   public:
654*03ce13f7SAndroid Build Coastguard Worker     explicit ShortCircuitCondAndLabel(CondWhenTrue &&C,
655*03ce13f7SAndroid Build Coastguard Worker                                       InstARM32Label *L = nullptr)
Cond(std::move (C))656*03ce13f7SAndroid Build Coastguard Worker         : Cond(std::move(C)), ShortCircuitTarget(L) {}
657*03ce13f7SAndroid Build Coastguard Worker     const CondWhenTrue Cond;
658*03ce13f7SAndroid Build Coastguard Worker     InstARM32Label *const ShortCircuitTarget;
659*03ce13f7SAndroid Build Coastguard Worker 
assertNoLabelAndReturnCond()660*03ce13f7SAndroid Build Coastguard Worker     CondWhenTrue assertNoLabelAndReturnCond() const {
661*03ce13f7SAndroid Build Coastguard Worker       assert(ShortCircuitTarget == nullptr);
662*03ce13f7SAndroid Build Coastguard Worker       return Cond;
663*03ce13f7SAndroid Build Coastguard Worker     }
664*03ce13f7SAndroid Build Coastguard Worker   };
665*03ce13f7SAndroid Build Coastguard Worker 
666*03ce13f7SAndroid Build Coastguard Worker   /// lowerInt1ForBranch expands Boolean, and returns the condition codes that
667*03ce13f7SAndroid Build Coastguard Worker   /// are to be used for branching to the branch's TrueTarget. It may return a
668*03ce13f7SAndroid Build Coastguard Worker   /// label that the expansion of Boolean used to short circuit the chain's
669*03ce13f7SAndroid Build Coastguard Worker   /// evaluation.
670*03ce13f7SAndroid Build Coastguard Worker   ShortCircuitCondAndLabel
671*03ce13f7SAndroid Build Coastguard Worker   lowerInt1ForBranch(Operand *Boolean, const LowerInt1BranchTarget &TargetTrue,
672*03ce13f7SAndroid Build Coastguard Worker                      const LowerInt1BranchTarget &TargetFalse,
673*03ce13f7SAndroid Build Coastguard Worker                      uint32_t ShortCircuitable);
674*03ce13f7SAndroid Build Coastguard Worker 
675*03ce13f7SAndroid Build Coastguard Worker   // _br is a convenience wrapper that emits br instructions to Target.
676*03ce13f7SAndroid Build Coastguard Worker   void _br(const LowerInt1BranchTarget &BrTarget,
677*03ce13f7SAndroid Build Coastguard Worker            CondARM32::Cond Cond = CondARM32::AL) {
678*03ce13f7SAndroid Build Coastguard Worker     assert((BrTarget.NodeTarget == nullptr) !=
679*03ce13f7SAndroid Build Coastguard Worker            (BrTarget.LabelTarget == nullptr));
680*03ce13f7SAndroid Build Coastguard Worker     if (BrTarget.NodeTarget != nullptr)
681*03ce13f7SAndroid Build Coastguard Worker       _br(BrTarget.NodeTarget, Cond);
682*03ce13f7SAndroid Build Coastguard Worker     else
683*03ce13f7SAndroid Build Coastguard Worker       _br(BrTarget.LabelTarget, Cond);
684*03ce13f7SAndroid Build Coastguard Worker   }
685*03ce13f7SAndroid Build Coastguard Worker 
686*03ce13f7SAndroid Build Coastguard Worker   // _br_short_circuit is used when lowering InstArithmetic::And and
687*03ce13f7SAndroid Build Coastguard Worker   // InstArithmetic::Or and a short circuit branch is needed.
_br_short_circuit(const LowerInt1BranchTarget & Target,const CondWhenTrue & Cond)688*03ce13f7SAndroid Build Coastguard Worker   void _br_short_circuit(const LowerInt1BranchTarget &Target,
689*03ce13f7SAndroid Build Coastguard Worker                          const CondWhenTrue &Cond) {
690*03ce13f7SAndroid Build Coastguard Worker     if (Cond.WhenTrue1 != CondARM32::kNone) {
691*03ce13f7SAndroid Build Coastguard Worker       _br(Target, Cond.WhenTrue1);
692*03ce13f7SAndroid Build Coastguard Worker     }
693*03ce13f7SAndroid Build Coastguard Worker     if (Cond.WhenTrue0 != CondARM32::kNone) {
694*03ce13f7SAndroid Build Coastguard Worker       _br(Target, Cond.WhenTrue0);
695*03ce13f7SAndroid Build Coastguard Worker     }
696*03ce13f7SAndroid Build Coastguard Worker   }
697*03ce13f7SAndroid Build Coastguard Worker   // End of bool folding machinery
698*03ce13f7SAndroid Build Coastguard Worker   // --------------------------------------------------------------------------
699*03ce13f7SAndroid Build Coastguard Worker 
700*03ce13f7SAndroid Build Coastguard Worker   /// The Operand can only be a 16-bit immediate or a ConstantRelocatable (with
701*03ce13f7SAndroid Build Coastguard Worker   /// an upper16 relocation).
702*03ce13f7SAndroid Build Coastguard Worker   void _movt(Variable *Dest, Operand *Src0,
703*03ce13f7SAndroid Build Coastguard Worker              CondARM32::Cond Pred = CondARM32::AL) {
704*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Movt>(Dest, Src0, Pred);
705*03ce13f7SAndroid Build Coastguard Worker   }
706*03ce13f7SAndroid Build Coastguard Worker   void _movw(Variable *Dest, Operand *Src0,
707*03ce13f7SAndroid Build Coastguard Worker              CondARM32::Cond Pred = CondARM32::AL) {
708*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Movw>(Dest, Src0, Pred);
709*03ce13f7SAndroid Build Coastguard Worker   }
710*03ce13f7SAndroid Build Coastguard Worker   void _mul(Variable *Dest, Variable *Src0, Variable *Src1,
711*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
712*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Mul>(Dest, Src0, Src1, Pred);
713*03ce13f7SAndroid Build Coastguard Worker   }
714*03ce13f7SAndroid Build Coastguard Worker   void _mvn(Variable *Dest, Operand *Src0,
715*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
716*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Mvn>(Dest, Src0, Pred);
717*03ce13f7SAndroid Build Coastguard Worker   }
718*03ce13f7SAndroid Build Coastguard Worker   void _orr(Variable *Dest, Variable *Src0, Operand *Src1,
719*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
720*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Orr>(Dest, Src0, Src1, Pred);
721*03ce13f7SAndroid Build Coastguard Worker   }
722*03ce13f7SAndroid Build Coastguard Worker   void _orrs(Variable *Dest, Variable *Src0, Operand *Src1,
723*03ce13f7SAndroid Build Coastguard Worker              CondARM32::Cond Pred = CondARM32::AL) {
724*03ce13f7SAndroid Build Coastguard Worker     constexpr bool SetFlags = true;
725*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Orr>(Dest, Src0, Src1, Pred, SetFlags);
726*03ce13f7SAndroid Build Coastguard Worker     if (SetFlags) {
727*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeUse>(Dest);
728*03ce13f7SAndroid Build Coastguard Worker     }
729*03ce13f7SAndroid Build Coastguard Worker   }
_push(const VarList & Sources)730*03ce13f7SAndroid Build Coastguard Worker   void _push(const VarList &Sources) { Context.insert<InstARM32Push>(Sources); }
_pop(const VarList & Dests)731*03ce13f7SAndroid Build Coastguard Worker   void _pop(const VarList &Dests) {
732*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Pop>(Dests);
733*03ce13f7SAndroid Build Coastguard Worker     // Mark dests as modified.
734*03ce13f7SAndroid Build Coastguard Worker     for (Variable *Dest : Dests)
735*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeDef>(Dest);
736*03ce13f7SAndroid Build Coastguard Worker   }
737*03ce13f7SAndroid Build Coastguard Worker   void _rbit(Variable *Dest, Variable *Src0,
738*03ce13f7SAndroid Build Coastguard Worker              CondARM32::Cond Pred = CondARM32::AL) {
739*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Rbit>(Dest, Src0, Pred);
740*03ce13f7SAndroid Build Coastguard Worker   }
741*03ce13f7SAndroid Build Coastguard Worker   void _rev(Variable *Dest, Variable *Src0,
742*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
743*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Rev>(Dest, Src0, Pred);
744*03ce13f7SAndroid Build Coastguard Worker   }
745*03ce13f7SAndroid Build Coastguard Worker   void _ret(Variable *LR, Variable *Src0 = nullptr) {
746*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Ret>(LR, Src0);
747*03ce13f7SAndroid Build Coastguard Worker   }
748*03ce13f7SAndroid Build Coastguard Worker   void _rscs(Variable *Dest, Variable *Src0, Operand *Src1,
749*03ce13f7SAndroid Build Coastguard Worker              CondARM32::Cond Pred = CondARM32::AL) {
750*03ce13f7SAndroid Build Coastguard Worker     constexpr bool SetFlags = true;
751*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Rsc>(Dest, Src0, Src1, Pred, SetFlags);
752*03ce13f7SAndroid Build Coastguard Worker     if (SetFlags) {
753*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeUse>(Dest);
754*03ce13f7SAndroid Build Coastguard Worker     }
755*03ce13f7SAndroid Build Coastguard Worker   }
756*03ce13f7SAndroid Build Coastguard Worker   void _rsc(Variable *Dest, Variable *Src0, Operand *Src1,
757*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
758*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Rsc>(Dest, Src0, Src1, Pred);
759*03ce13f7SAndroid Build Coastguard Worker   }
760*03ce13f7SAndroid Build Coastguard Worker   void _rsbs(Variable *Dest, Variable *Src0, Operand *Src1,
761*03ce13f7SAndroid Build Coastguard Worker              CondARM32::Cond Pred = CondARM32::AL) {
762*03ce13f7SAndroid Build Coastguard Worker     constexpr bool SetFlags = true;
763*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Rsb>(Dest, Src0, Src1, Pred, SetFlags);
764*03ce13f7SAndroid Build Coastguard Worker     if (SetFlags) {
765*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeUse>(Dest);
766*03ce13f7SAndroid Build Coastguard Worker     }
767*03ce13f7SAndroid Build Coastguard Worker   }
768*03ce13f7SAndroid Build Coastguard Worker   void _rsb(Variable *Dest, Variable *Src0, Operand *Src1,
769*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
770*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Rsb>(Dest, Src0, Src1, Pred);
771*03ce13f7SAndroid Build Coastguard Worker   }
772*03ce13f7SAndroid Build Coastguard Worker   void _sbc(Variable *Dest, Variable *Src0, Operand *Src1,
773*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
774*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Sbc>(Dest, Src0, Src1, Pred);
775*03ce13f7SAndroid Build Coastguard Worker   }
776*03ce13f7SAndroid Build Coastguard Worker   void _sbcs(Variable *Dest, Variable *Src0, Operand *Src1,
777*03ce13f7SAndroid Build Coastguard Worker              CondARM32::Cond Pred = CondARM32::AL) {
778*03ce13f7SAndroid Build Coastguard Worker     constexpr bool SetFlags = true;
779*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Sbc>(Dest, Src0, Src1, Pred, SetFlags);
780*03ce13f7SAndroid Build Coastguard Worker     if (SetFlags) {
781*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeUse>(Dest);
782*03ce13f7SAndroid Build Coastguard Worker     }
783*03ce13f7SAndroid Build Coastguard Worker   }
784*03ce13f7SAndroid Build Coastguard Worker   void _sdiv(Variable *Dest, Variable *Src0, Variable *Src1,
785*03ce13f7SAndroid Build Coastguard Worker              CondARM32::Cond Pred = CondARM32::AL) {
786*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Sdiv>(Dest, Src0, Src1, Pred);
787*03ce13f7SAndroid Build Coastguard Worker   }
788*03ce13f7SAndroid Build Coastguard Worker   /// _str, for all your Variable to memory transfers. Addr has the same
789*03ce13f7SAndroid Build Coastguard Worker   /// restrictions that it does in _ldr.
790*03ce13f7SAndroid Build Coastguard Worker   void _str(Variable *Value, OperandARM32Mem *Addr,
791*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
792*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Str>(Value, Addr, Pred);
793*03ce13f7SAndroid Build Coastguard Worker   }
794*03ce13f7SAndroid Build Coastguard Worker   InstARM32Strex *_strex(Variable *Dest, Variable *Value, OperandARM32Mem *Addr,
795*03ce13f7SAndroid Build Coastguard Worker                          CondARM32::Cond Pred = CondARM32::AL) {
796*03ce13f7SAndroid Build Coastguard Worker     if (auto *Value64 = llvm::dyn_cast<Variable64On32>(Value)) {
797*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeUse>(Value64->getLo());
798*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeUse>(Value64->getHi());
799*03ce13f7SAndroid Build Coastguard Worker     }
800*03ce13f7SAndroid Build Coastguard Worker     return Context.insert<InstARM32Strex>(Dest, Value, Addr, Pred);
801*03ce13f7SAndroid Build Coastguard Worker   }
802*03ce13f7SAndroid Build Coastguard Worker   void _sub(Variable *Dest, Variable *Src0, Operand *Src1,
803*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
804*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Sub>(Dest, Src0, Src1, Pred);
805*03ce13f7SAndroid Build Coastguard Worker   }
806*03ce13f7SAndroid Build Coastguard Worker   void _subs(Variable *Dest, Variable *Src0, Operand *Src1,
807*03ce13f7SAndroid Build Coastguard Worker              CondARM32::Cond Pred = CondARM32::AL) {
808*03ce13f7SAndroid Build Coastguard Worker     constexpr bool SetFlags = true;
809*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Sub>(Dest, Src0, Src1, Pred, SetFlags);
810*03ce13f7SAndroid Build Coastguard Worker     if (SetFlags) {
811*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeUse>(Dest);
812*03ce13f7SAndroid Build Coastguard Worker     }
813*03ce13f7SAndroid Build Coastguard Worker   }
814*03ce13f7SAndroid Build Coastguard Worker   void _sxt(Variable *Dest, Variable *Src0,
815*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
816*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Sxt>(Dest, Src0, Pred);
817*03ce13f7SAndroid Build Coastguard Worker   }
818*03ce13f7SAndroid Build Coastguard Worker   void _tst(Variable *Src0, Operand *Src1,
819*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
820*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Tst>(Src0, Src1, Pred);
821*03ce13f7SAndroid Build Coastguard Worker   }
_trap()822*03ce13f7SAndroid Build Coastguard Worker   void _trap() { Context.insert<InstARM32Trap>(); }
823*03ce13f7SAndroid Build Coastguard Worker   void _udiv(Variable *Dest, Variable *Src0, Variable *Src1,
824*03ce13f7SAndroid Build Coastguard Worker              CondARM32::Cond Pred = CondARM32::AL) {
825*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Udiv>(Dest, Src0, Src1, Pred);
826*03ce13f7SAndroid Build Coastguard Worker   }
827*03ce13f7SAndroid Build Coastguard Worker   void _umull(Variable *DestLo, Variable *DestHi, Variable *Src0,
828*03ce13f7SAndroid Build Coastguard Worker               Variable *Src1, CondARM32::Cond Pred = CondARM32::AL) {
829*03ce13f7SAndroid Build Coastguard Worker     // umull requires DestLo and DestHi to be assigned to different GPRs. The
830*03ce13f7SAndroid Build Coastguard Worker     // following lines create overlapping liveness ranges for both variables. If
831*03ce13f7SAndroid Build Coastguard Worker     // either one of them is live, then they are both going to be live, and thus
832*03ce13f7SAndroid Build Coastguard Worker     // assigned to different registers; if they are both dead, then DCE will
833*03ce13f7SAndroid Build Coastguard Worker     // kick in and delete the following three instructions.
834*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeDef>(DestHi);
835*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Umull>(DestLo, DestHi, Src0, Src1, Pred);
836*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeDef>(DestHi, DestLo)->setDestRedefined();
837*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeUse>(DestHi);
838*03ce13f7SAndroid Build Coastguard Worker   }
839*03ce13f7SAndroid Build Coastguard Worker   void _uxt(Variable *Dest, Variable *Src0,
840*03ce13f7SAndroid Build Coastguard Worker             CondARM32::Cond Pred = CondARM32::AL) {
841*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Uxt>(Dest, Src0, Pred);
842*03ce13f7SAndroid Build Coastguard Worker   }
843*03ce13f7SAndroid Build Coastguard Worker   void _vabs(Variable *Dest, Variable *Src,
844*03ce13f7SAndroid Build Coastguard Worker              CondARM32::Cond Pred = CondARM32::AL) {
845*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vabs>(Dest, Src, Pred);
846*03ce13f7SAndroid Build Coastguard Worker   }
_vadd(Variable * Dest,Variable * Src0,Variable * Src1)847*03ce13f7SAndroid Build Coastguard Worker   void _vadd(Variable *Dest, Variable *Src0, Variable *Src1) {
848*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vadd>(Dest, Src0, Src1);
849*03ce13f7SAndroid Build Coastguard Worker   }
_vand(Variable * Dest,Variable * Src0,Variable * Src1)850*03ce13f7SAndroid Build Coastguard Worker   void _vand(Variable *Dest, Variable *Src0, Variable *Src1) {
851*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vand>(Dest, Src0, Src1);
852*03ce13f7SAndroid Build Coastguard Worker   }
_vbsl(Variable * Dest,Variable * Src0,Variable * Src1)853*03ce13f7SAndroid Build Coastguard Worker   InstARM32Vbsl *_vbsl(Variable *Dest, Variable *Src0, Variable *Src1) {
854*03ce13f7SAndroid Build Coastguard Worker     return Context.insert<InstARM32Vbsl>(Dest, Src0, Src1);
855*03ce13f7SAndroid Build Coastguard Worker   }
_vceq(Variable * Dest,Variable * Src0,Variable * Src1)856*03ce13f7SAndroid Build Coastguard Worker   void _vceq(Variable *Dest, Variable *Src0, Variable *Src1) {
857*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vceq>(Dest, Src0, Src1);
858*03ce13f7SAndroid Build Coastguard Worker   }
_vcge(Variable * Dest,Variable * Src0,Variable * Src1)859*03ce13f7SAndroid Build Coastguard Worker   InstARM32Vcge *_vcge(Variable *Dest, Variable *Src0, Variable *Src1) {
860*03ce13f7SAndroid Build Coastguard Worker     return Context.insert<InstARM32Vcge>(Dest, Src0, Src1);
861*03ce13f7SAndroid Build Coastguard Worker   }
_vcgt(Variable * Dest,Variable * Src0,Variable * Src1)862*03ce13f7SAndroid Build Coastguard Worker   InstARM32Vcgt *_vcgt(Variable *Dest, Variable *Src0, Variable *Src1) {
863*03ce13f7SAndroid Build Coastguard Worker     return Context.insert<InstARM32Vcgt>(Dest, Src0, Src1);
864*03ce13f7SAndroid Build Coastguard Worker   }
865*03ce13f7SAndroid Build Coastguard Worker   void _vcvt(Variable *Dest, Variable *Src, InstARM32Vcvt::VcvtVariant Variant,
866*03ce13f7SAndroid Build Coastguard Worker              CondARM32::Cond Pred = CondARM32::AL) {
867*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vcvt>(Dest, Src, Variant, Pred);
868*03ce13f7SAndroid Build Coastguard Worker   }
_vdiv(Variable * Dest,Variable * Src0,Variable * Src1)869*03ce13f7SAndroid Build Coastguard Worker   void _vdiv(Variable *Dest, Variable *Src0, Variable *Src1) {
870*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vdiv>(Dest, Src0, Src1);
871*03ce13f7SAndroid Build Coastguard Worker   }
872*03ce13f7SAndroid Build Coastguard Worker   void _vcmp(Variable *Src0, Variable *Src1,
873*03ce13f7SAndroid Build Coastguard Worker              CondARM32::Cond Pred = CondARM32::AL) {
874*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vcmp>(Src0, Src1, Pred);
875*03ce13f7SAndroid Build Coastguard Worker   }
876*03ce13f7SAndroid Build Coastguard Worker   void _vcmp(Variable *Src0, OperandARM32FlexFpZero *FpZero,
877*03ce13f7SAndroid Build Coastguard Worker              CondARM32::Cond Pred = CondARM32::AL) {
878*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vcmp>(Src0, FpZero, Pred);
879*03ce13f7SAndroid Build Coastguard Worker   }
_vdup(Variable * Dest,Variable * Src,int Idx)880*03ce13f7SAndroid Build Coastguard Worker   void _vdup(Variable *Dest, Variable *Src, int Idx) {
881*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vdup>(Dest, Src, Idx);
882*03ce13f7SAndroid Build Coastguard Worker   }
_veor(Variable * Dest,Variable * Src0,Variable * Src1)883*03ce13f7SAndroid Build Coastguard Worker   void _veor(Variable *Dest, Variable *Src0, Variable *Src1) {
884*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Veor>(Dest, Src0, Src1);
885*03ce13f7SAndroid Build Coastguard Worker   }
886*03ce13f7SAndroid Build Coastguard Worker   void _vldr1d(Variable *Dest, OperandARM32Mem *Addr,
887*03ce13f7SAndroid Build Coastguard Worker                CondARM32::Cond Pred = CondARM32::AL) {
888*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vldr1d>(Dest, Addr, Pred);
889*03ce13f7SAndroid Build Coastguard Worker   }
890*03ce13f7SAndroid Build Coastguard Worker   void _vldr1q(Variable *Dest, OperandARM32Mem *Addr,
891*03ce13f7SAndroid Build Coastguard Worker                CondARM32::Cond Pred = CondARM32::AL) {
892*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vldr1q>(Dest, Addr, Pred);
893*03ce13f7SAndroid Build Coastguard Worker   }
894*03ce13f7SAndroid Build Coastguard Worker   void _vmrs(CondARM32::Cond Pred = CondARM32::AL) {
895*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vmrs>(Pred);
896*03ce13f7SAndroid Build Coastguard Worker   }
_vmla(Variable * Dest,Variable * Src0,Variable * Src1)897*03ce13f7SAndroid Build Coastguard Worker   void _vmla(Variable *Dest, Variable *Src0, Variable *Src1) {
898*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vmla>(Dest, Src0, Src1);
899*03ce13f7SAndroid Build Coastguard Worker   }
_vmlap(Variable * Dest,Variable * Src0,Variable * Src1)900*03ce13f7SAndroid Build Coastguard Worker   void _vmlap(Variable *Dest, Variable *Src0, Variable *Src1) {
901*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vmlap>(Dest, Src0, Src1);
902*03ce13f7SAndroid Build Coastguard Worker   }
_vmls(Variable * Dest,Variable * Src0,Variable * Src1)903*03ce13f7SAndroid Build Coastguard Worker   void _vmls(Variable *Dest, Variable *Src0, Variable *Src1) {
904*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vmls>(Dest, Src0, Src1);
905*03ce13f7SAndroid Build Coastguard Worker   }
_vmovl(Variable * Dest,Variable * Src0,Variable * Src1)906*03ce13f7SAndroid Build Coastguard Worker   void _vmovl(Variable *Dest, Variable *Src0, Variable *Src1) {
907*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vmovl>(Dest, Src0, Src1);
908*03ce13f7SAndroid Build Coastguard Worker   }
_vmovh(Variable * Dest,Variable * Src0,Variable * Src1)909*03ce13f7SAndroid Build Coastguard Worker   void _vmovh(Variable *Dest, Variable *Src0, Variable *Src1) {
910*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vmovh>(Dest, Src0, Src1);
911*03ce13f7SAndroid Build Coastguard Worker   }
_vmovhl(Variable * Dest,Variable * Src0,Variable * Src1)912*03ce13f7SAndroid Build Coastguard Worker   void _vmovhl(Variable *Dest, Variable *Src0, Variable *Src1) {
913*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vmovhl>(Dest, Src0, Src1);
914*03ce13f7SAndroid Build Coastguard Worker   }
_vmovlh(Variable * Dest,Variable * Src0,Variable * Src1)915*03ce13f7SAndroid Build Coastguard Worker   void _vmovlh(Variable *Dest, Variable *Src0, Variable *Src1) {
916*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vmovlh>(Dest, Src0, Src1);
917*03ce13f7SAndroid Build Coastguard Worker   }
_vmul(Variable * Dest,Variable * Src0,Variable * Src1)918*03ce13f7SAndroid Build Coastguard Worker   void _vmul(Variable *Dest, Variable *Src0, Variable *Src1) {
919*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vmul>(Dest, Src0, Src1);
920*03ce13f7SAndroid Build Coastguard Worker   }
_vmulh(Variable * Dest,Variable * Src0,Variable * Src1,bool Unsigned)921*03ce13f7SAndroid Build Coastguard Worker   void _vmulh(Variable *Dest, Variable *Src0, Variable *Src1, bool Unsigned) {
922*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vmulh>(Dest, Src0, Src1)
923*03ce13f7SAndroid Build Coastguard Worker         ->setSignType(Unsigned ? InstARM32::FS_Unsigned : InstARM32::FS_Signed);
924*03ce13f7SAndroid Build Coastguard Worker   }
_vmvn(Variable * Dest,Variable * Src0)925*03ce13f7SAndroid Build Coastguard Worker   void _vmvn(Variable *Dest, Variable *Src0) {
926*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vmvn>(Dest, Src0, CondARM32::AL);
927*03ce13f7SAndroid Build Coastguard Worker   }
_vneg(Variable * Dest,Variable * Src0)928*03ce13f7SAndroid Build Coastguard Worker   void _vneg(Variable *Dest, Variable *Src0) {
929*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vneg>(Dest, Src0, CondARM32::AL)
930*03ce13f7SAndroid Build Coastguard Worker         ->setSignType(InstARM32::FS_Signed);
931*03ce13f7SAndroid Build Coastguard Worker   }
_vorr(Variable * Dest,Variable * Src0,Variable * Src1)932*03ce13f7SAndroid Build Coastguard Worker   void _vorr(Variable *Dest, Variable *Src0, Variable *Src1) {
933*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vorr>(Dest, Src0, Src1);
934*03ce13f7SAndroid Build Coastguard Worker   }
_vqadd(Variable * Dest,Variable * Src0,Variable * Src1,bool Unsigned)935*03ce13f7SAndroid Build Coastguard Worker   void _vqadd(Variable *Dest, Variable *Src0, Variable *Src1, bool Unsigned) {
936*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vqadd>(Dest, Src0, Src1)
937*03ce13f7SAndroid Build Coastguard Worker         ->setSignType(Unsigned ? InstARM32::FS_Unsigned : InstARM32::FS_Signed);
938*03ce13f7SAndroid Build Coastguard Worker   }
_vqmovn2(Variable * Dest,Variable * Src0,Variable * Src1,bool Unsigned,bool Saturating)939*03ce13f7SAndroid Build Coastguard Worker   void _vqmovn2(Variable *Dest, Variable *Src0, Variable *Src1, bool Unsigned,
940*03ce13f7SAndroid Build Coastguard Worker                 bool Saturating) {
941*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vqmovn2>(Dest, Src0, Src1)
942*03ce13f7SAndroid Build Coastguard Worker         ->setSignType(Saturating ? (Unsigned ? InstARM32::FS_Unsigned
943*03ce13f7SAndroid Build Coastguard Worker                                              : InstARM32::FS_Signed)
944*03ce13f7SAndroid Build Coastguard Worker                                  : InstARM32::FS_None);
945*03ce13f7SAndroid Build Coastguard Worker   }
_vqsub(Variable * Dest,Variable * Src0,Variable * Src1,bool Unsigned)946*03ce13f7SAndroid Build Coastguard Worker   void _vqsub(Variable *Dest, Variable *Src0, Variable *Src1, bool Unsigned) {
947*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vqsub>(Dest, Src0, Src1)
948*03ce13f7SAndroid Build Coastguard Worker         ->setSignType(Unsigned ? InstARM32::FS_Unsigned : InstARM32::FS_Signed);
949*03ce13f7SAndroid Build Coastguard Worker   }
_vshl(Variable * Dest,Variable * Src0,Variable * Src1)950*03ce13f7SAndroid Build Coastguard Worker   InstARM32Vshl *_vshl(Variable *Dest, Variable *Src0, Variable *Src1) {
951*03ce13f7SAndroid Build Coastguard Worker     return Context.insert<InstARM32Vshl>(Dest, Src0, Src1);
952*03ce13f7SAndroid Build Coastguard Worker   }
_vshl(Variable * Dest,Variable * Src0,ConstantInteger32 * Src1)953*03ce13f7SAndroid Build Coastguard Worker   void _vshl(Variable *Dest, Variable *Src0, ConstantInteger32 *Src1) {
954*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vshl>(Dest, Src0, Src1)
955*03ce13f7SAndroid Build Coastguard Worker         ->setSignType(InstARM32::FS_Unsigned);
956*03ce13f7SAndroid Build Coastguard Worker   }
_vshr(Variable * Dest,Variable * Src0,ConstantInteger32 * Src1)957*03ce13f7SAndroid Build Coastguard Worker   InstARM32Vshr *_vshr(Variable *Dest, Variable *Src0,
958*03ce13f7SAndroid Build Coastguard Worker                        ConstantInteger32 *Src1) {
959*03ce13f7SAndroid Build Coastguard Worker     return Context.insert<InstARM32Vshr>(Dest, Src0, Src1);
960*03ce13f7SAndroid Build Coastguard Worker   }
961*03ce13f7SAndroid Build Coastguard Worker   void _vsqrt(Variable *Dest, Variable *Src,
962*03ce13f7SAndroid Build Coastguard Worker               CondARM32::Cond Pred = CondARM32::AL) {
963*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vsqrt>(Dest, Src, Pred);
964*03ce13f7SAndroid Build Coastguard Worker   }
965*03ce13f7SAndroid Build Coastguard Worker   void _vstr1d(Variable *Value, OperandARM32Mem *Addr,
966*03ce13f7SAndroid Build Coastguard Worker                CondARM32::Cond Pred = CondARM32::AL) {
967*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vstr1>(Value, Addr, Pred, 32);
968*03ce13f7SAndroid Build Coastguard Worker   }
969*03ce13f7SAndroid Build Coastguard Worker   void _vstr1q(Variable *Value, OperandARM32Mem *Addr,
970*03ce13f7SAndroid Build Coastguard Worker                CondARM32::Cond Pred = CondARM32::AL) {
971*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vstr1>(Value, Addr, Pred, 64);
972*03ce13f7SAndroid Build Coastguard Worker   }
_vsub(Variable * Dest,Variable * Src0,Variable * Src1)973*03ce13f7SAndroid Build Coastguard Worker   void _vsub(Variable *Dest, Variable *Src0, Variable *Src1) {
974*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vsub>(Dest, Src0, Src1);
975*03ce13f7SAndroid Build Coastguard Worker   }
_vzip(Variable * Dest,Variable * Src0,Variable * Src1)976*03ce13f7SAndroid Build Coastguard Worker   void _vzip(Variable *Dest, Variable *Src0, Variable *Src1) {
977*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstARM32Vzip>(Dest, Src0, Src1);
978*03ce13f7SAndroid Build Coastguard Worker   }
979*03ce13f7SAndroid Build Coastguard Worker 
980*03ce13f7SAndroid Build Coastguard Worker   // Iterates over the CFG and determines the maximum outgoing stack arguments
981*03ce13f7SAndroid Build Coastguard Worker   // bytes. This information is later used during addProlog() to pre-allocate
982*03ce13f7SAndroid Build Coastguard Worker   // the outargs area.
983*03ce13f7SAndroid Build Coastguard Worker   // TODO(jpp): This could live in the Parser, if we provided a Target-specific
984*03ce13f7SAndroid Build Coastguard Worker   // method that the Parser could call.
985*03ce13f7SAndroid Build Coastguard Worker   void findMaxStackOutArgsSize();
986*03ce13f7SAndroid Build Coastguard Worker 
987*03ce13f7SAndroid Build Coastguard Worker   /// Returns true if the given Offset can be represented in a Load/Store Mem
988*03ce13f7SAndroid Build Coastguard Worker   /// Operand.
989*03ce13f7SAndroid Build Coastguard Worker   bool isLegalMemOffset(Type Ty, int32_t Offset) const;
990*03ce13f7SAndroid Build Coastguard Worker 
991*03ce13f7SAndroid Build Coastguard Worker   void postLowerLegalization();
992*03ce13f7SAndroid Build Coastguard Worker 
993*03ce13f7SAndroid Build Coastguard Worker   /// Manages the Gotoff relocations created during the function lowering. A
994*03ce13f7SAndroid Build Coastguard Worker   /// single Gotoff relocation is created for each global variable used by the
995*03ce13f7SAndroid Build Coastguard Worker   /// function being lowered.
996*03ce13f7SAndroid Build Coastguard Worker   /// @{
997*03ce13f7SAndroid Build Coastguard Worker   // TODO(jpp): if the same global G is used in different functions, then this
998*03ce13f7SAndroid Build Coastguard Worker   // method will emit one G(gotoff) relocation per function.
999*03ce13f7SAndroid Build Coastguard Worker   GlobalString createGotoffRelocation(const ConstantRelocatable *CR);
1000*03ce13f7SAndroid Build Coastguard Worker   CfgUnorderedSet<GlobalString> KnownGotoffs;
1001*03ce13f7SAndroid Build Coastguard Worker   /// @}
1002*03ce13f7SAndroid Build Coastguard Worker 
1003*03ce13f7SAndroid Build Coastguard Worker   class PostLoweringLegalizer {
1004*03ce13f7SAndroid Build Coastguard Worker     PostLoweringLegalizer() = delete;
1005*03ce13f7SAndroid Build Coastguard Worker     PostLoweringLegalizer(const PostLoweringLegalizer &) = delete;
1006*03ce13f7SAndroid Build Coastguard Worker     PostLoweringLegalizer &operator=(const PostLoweringLegalizer &) = delete;
1007*03ce13f7SAndroid Build Coastguard Worker 
1008*03ce13f7SAndroid Build Coastguard Worker   public:
PostLoweringLegalizer(TargetARM32 * Target)1009*03ce13f7SAndroid Build Coastguard Worker     explicit PostLoweringLegalizer(TargetARM32 *Target)
1010*03ce13f7SAndroid Build Coastguard Worker         : Target(Target), StackOrFrameReg(Target->getPhysicalRegister(
1011*03ce13f7SAndroid Build Coastguard Worker                               Target->getFrameOrStackReg())) {}
1012*03ce13f7SAndroid Build Coastguard Worker 
1013*03ce13f7SAndroid Build Coastguard Worker     void resetTempBaseIfClobberedBy(const Inst *Instr);
1014*03ce13f7SAndroid Build Coastguard Worker 
1015*03ce13f7SAndroid Build Coastguard Worker     // Ensures that the TempBase register held by the this legalizer (if any) is
1016*03ce13f7SAndroid Build Coastguard Worker     // assigned to IP.
assertNoTempOrAssignedToIP()1017*03ce13f7SAndroid Build Coastguard Worker     void assertNoTempOrAssignedToIP() const {
1018*03ce13f7SAndroid Build Coastguard Worker       assert(TempBaseReg == nullptr ||
1019*03ce13f7SAndroid Build Coastguard Worker              TempBaseReg->getRegNum() == Target->getReservedTmpReg());
1020*03ce13f7SAndroid Build Coastguard Worker     }
1021*03ce13f7SAndroid Build Coastguard Worker 
1022*03ce13f7SAndroid Build Coastguard Worker     // Legalizes Mem. if Mem.Base is a Reamaterializable variable, Mem.Offset is
1023*03ce13f7SAndroid Build Coastguard Worker     // fixed up.
1024*03ce13f7SAndroid Build Coastguard Worker     OperandARM32Mem *legalizeMemOperand(OperandARM32Mem *Mem,
1025*03ce13f7SAndroid Build Coastguard Worker                                         bool AllowOffsets = true);
1026*03ce13f7SAndroid Build Coastguard Worker 
1027*03ce13f7SAndroid Build Coastguard Worker     /// Legalizes Mov if its Source (or Destination) is a spilled Variable, or
1028*03ce13f7SAndroid Build Coastguard Worker     /// if its Source is a Rematerializable variable (this form is used in lieu
1029*03ce13f7SAndroid Build Coastguard Worker     /// of lea, which is not available in ARM.)
1030*03ce13f7SAndroid Build Coastguard Worker     ///
1031*03ce13f7SAndroid Build Coastguard Worker     /// Moves to memory become store instructions, and moves from memory, loads.
1032*03ce13f7SAndroid Build Coastguard Worker     void legalizeMov(InstARM32Mov *Mov);
1033*03ce13f7SAndroid Build Coastguard Worker 
1034*03ce13f7SAndroid Build Coastguard Worker   private:
1035*03ce13f7SAndroid Build Coastguard Worker     /// Creates a new Base register centered around [Base, +/- Offset].
1036*03ce13f7SAndroid Build Coastguard Worker     Variable *newBaseRegister(Variable *Base, int32_t Offset,
1037*03ce13f7SAndroid Build Coastguard Worker                               RegNumT ScratchRegNum);
1038*03ce13f7SAndroid Build Coastguard Worker 
1039*03ce13f7SAndroid Build Coastguard Worker     /// Creates a new, legal OperandARM32Mem for accessing Base + Offset.
1040*03ce13f7SAndroid Build Coastguard Worker     /// The returned mem operand is a legal operand for accessing memory that is
1041*03ce13f7SAndroid Build Coastguard Worker     /// of type Ty.
1042*03ce13f7SAndroid Build Coastguard Worker     ///
1043*03ce13f7SAndroid Build Coastguard Worker     /// If [Base, #Offset] is encodable, then the method returns a Mem operand
1044*03ce13f7SAndroid Build Coastguard Worker     /// expressing it. Otherwise,
1045*03ce13f7SAndroid Build Coastguard Worker     ///
1046*03ce13f7SAndroid Build Coastguard Worker     /// if [TempBaseReg, #Offset-TempBaseOffset] is a valid memory operand, the
1047*03ce13f7SAndroid Build Coastguard Worker     /// method will return that. Otherwise,
1048*03ce13f7SAndroid Build Coastguard Worker     ///
1049*03ce13f7SAndroid Build Coastguard Worker     /// a new base register ip=Base+Offset is created, and the method returns a
1050*03ce13f7SAndroid Build Coastguard Worker     /// memory operand expressing [ip, #0].
1051*03ce13f7SAndroid Build Coastguard Worker     OperandARM32Mem *createMemOperand(Type Ty, Variable *Base, int32_t Offset,
1052*03ce13f7SAndroid Build Coastguard Worker                                       bool AllowOffsets = true);
1053*03ce13f7SAndroid Build Coastguard Worker     TargetARM32 *const Target;
1054*03ce13f7SAndroid Build Coastguard Worker     Variable *const StackOrFrameReg;
1055*03ce13f7SAndroid Build Coastguard Worker     Variable *TempBaseReg = nullptr;
1056*03ce13f7SAndroid Build Coastguard Worker     int32_t TempBaseOffset = 0;
1057*03ce13f7SAndroid Build Coastguard Worker   };
1058*03ce13f7SAndroid Build Coastguard Worker 
1059*03ce13f7SAndroid Build Coastguard Worker   TargetARM32Features CPUFeatures;
1060*03ce13f7SAndroid Build Coastguard Worker   bool UsesFramePointer = false;
1061*03ce13f7SAndroid Build Coastguard Worker   bool NeedsStackAlignment = false;
1062*03ce13f7SAndroid Build Coastguard Worker   bool MaybeLeafFunc = true;
1063*03ce13f7SAndroid Build Coastguard Worker   size_t SpillAreaSizeBytes = 0;
1064*03ce13f7SAndroid Build Coastguard Worker   size_t FixedAllocaSizeBytes = 0;
1065*03ce13f7SAndroid Build Coastguard Worker   size_t FixedAllocaAlignBytes = 0;
1066*03ce13f7SAndroid Build Coastguard Worker   bool PrologEmitsFixedAllocas = false;
1067*03ce13f7SAndroid Build Coastguard Worker   uint32_t MaxOutArgsSizeBytes = 0;
1068*03ce13f7SAndroid Build Coastguard Worker   // TODO(jpp): std::array instead of array.
1069*03ce13f7SAndroid Build Coastguard Worker   static SmallBitVector TypeToRegisterSet[RegARM32::RCARM32_NUM];
1070*03ce13f7SAndroid Build Coastguard Worker   static SmallBitVector TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM];
1071*03ce13f7SAndroid Build Coastguard Worker   static SmallBitVector RegisterAliases[RegARM32::Reg_NUM];
1072*03ce13f7SAndroid Build Coastguard Worker   SmallBitVector RegsUsed;
1073*03ce13f7SAndroid Build Coastguard Worker   VarList PhysicalRegisters[IceType_NUM];
1074*03ce13f7SAndroid Build Coastguard Worker   VarList PreservedGPRs;
1075*03ce13f7SAndroid Build Coastguard Worker   VarList PreservedSRegs;
1076*03ce13f7SAndroid Build Coastguard Worker 
1077*03ce13f7SAndroid Build Coastguard Worker   /// Helper class that understands the Calling Convention and register
1078*03ce13f7SAndroid Build Coastguard Worker   /// assignments. The first few integer type parameters can use r0-r3,
1079*03ce13f7SAndroid Build Coastguard Worker   /// regardless of their position relative to the floating-point/vector
1080*03ce13f7SAndroid Build Coastguard Worker   /// arguments in the argument list. Floating-point and vector arguments
1081*03ce13f7SAndroid Build Coastguard Worker   /// can use q0-q3 (aka d0-d7, s0-s15). For more information on the topic,
1082*03ce13f7SAndroid Build Coastguard Worker   /// see the ARM Architecture Procedure Calling Standards (AAPCS).
1083*03ce13f7SAndroid Build Coastguard Worker   ///
1084*03ce13f7SAndroid Build Coastguard Worker   /// Technically, arguments that can start with registers but extend beyond the
1085*03ce13f7SAndroid Build Coastguard Worker   /// available registers can be split between the registers and the stack.
1086*03ce13f7SAndroid Build Coastguard Worker   /// However, this is typically  for passing GPR structs by value, and PNaCl
1087*03ce13f7SAndroid Build Coastguard Worker   /// transforms expand this out.
1088*03ce13f7SAndroid Build Coastguard Worker   ///
1089*03ce13f7SAndroid Build Coastguard Worker   /// At (public) function entry, the stack must be 8-byte aligned.
1090*03ce13f7SAndroid Build Coastguard Worker   class CallingConv {
1091*03ce13f7SAndroid Build Coastguard Worker     CallingConv(const CallingConv &) = delete;
1092*03ce13f7SAndroid Build Coastguard Worker     CallingConv &operator=(const CallingConv &) = delete;
1093*03ce13f7SAndroid Build Coastguard Worker 
1094*03ce13f7SAndroid Build Coastguard Worker   public:
1095*03ce13f7SAndroid Build Coastguard Worker     CallingConv();
1096*03ce13f7SAndroid Build Coastguard Worker     ~CallingConv() = default;
1097*03ce13f7SAndroid Build Coastguard Worker 
1098*03ce13f7SAndroid Build Coastguard Worker     /// argInGPR returns true if there is a GPR available for the requested
1099*03ce13f7SAndroid Build Coastguard Worker     /// type, and false otherwise. If it returns true, Reg is set to the
1100*03ce13f7SAndroid Build Coastguard Worker     /// appropriate register number. Note that, when Ty == IceType_i64, Reg will
1101*03ce13f7SAndroid Build Coastguard Worker     /// be an I64 register pair.
1102*03ce13f7SAndroid Build Coastguard Worker     bool argInGPR(Type Ty, RegNumT *Reg);
1103*03ce13f7SAndroid Build Coastguard Worker 
1104*03ce13f7SAndroid Build Coastguard Worker     /// argInVFP is to floating-point/vector types what argInGPR is for integer
1105*03ce13f7SAndroid Build Coastguard Worker     /// types.
1106*03ce13f7SAndroid Build Coastguard Worker     bool argInVFP(Type Ty, RegNumT *Reg);
1107*03ce13f7SAndroid Build Coastguard Worker 
1108*03ce13f7SAndroid Build Coastguard Worker   private:
1109*03ce13f7SAndroid Build Coastguard Worker     void discardUnavailableGPRsAndTheirAliases(CfgVector<RegNumT> *Regs);
1110*03ce13f7SAndroid Build Coastguard Worker     SmallBitVector GPRegsUsed;
1111*03ce13f7SAndroid Build Coastguard Worker     CfgVector<RegNumT> GPRArgs;
1112*03ce13f7SAndroid Build Coastguard Worker     CfgVector<RegNumT> I64Args;
1113*03ce13f7SAndroid Build Coastguard Worker 
1114*03ce13f7SAndroid Build Coastguard Worker     void discardUnavailableVFPRegs(CfgVector<RegNumT> *Regs);
1115*03ce13f7SAndroid Build Coastguard Worker     SmallBitVector VFPRegsUsed;
1116*03ce13f7SAndroid Build Coastguard Worker     CfgVector<RegNumT> FP32Args;
1117*03ce13f7SAndroid Build Coastguard Worker     CfgVector<RegNumT> FP64Args;
1118*03ce13f7SAndroid Build Coastguard Worker     CfgVector<RegNumT> Vec128Args;
1119*03ce13f7SAndroid Build Coastguard Worker   };
1120*03ce13f7SAndroid Build Coastguard Worker 
1121*03ce13f7SAndroid Build Coastguard Worker private:
1122*03ce13f7SAndroid Build Coastguard Worker   ENABLE_MAKE_UNIQUE;
1123*03ce13f7SAndroid Build Coastguard Worker 
1124*03ce13f7SAndroid Build Coastguard Worker   OperandARM32Mem *formAddressingMode(Type Ty, Cfg *Func, const Inst *LdSt,
1125*03ce13f7SAndroid Build Coastguard Worker                                       Operand *Base);
1126*03ce13f7SAndroid Build Coastguard Worker 
1127*03ce13f7SAndroid Build Coastguard Worker   void postambleCtpop64(const InstCall *Instr);
1128*03ce13f7SAndroid Build Coastguard Worker   void preambleDivRem(const InstCall *Instr);
1129*03ce13f7SAndroid Build Coastguard Worker   CfgUnorderedMap<Operand *, void (TargetARM32::*)(const InstCall *Instr)>
1130*03ce13f7SAndroid Build Coastguard Worker       ARM32HelpersPreamble;
1131*03ce13f7SAndroid Build Coastguard Worker   CfgUnorderedMap<Operand *, void (TargetARM32::*)(const InstCall *Instr)>
1132*03ce13f7SAndroid Build Coastguard Worker       ARM32HelpersPostamble;
1133*03ce13f7SAndroid Build Coastguard Worker 
1134*03ce13f7SAndroid Build Coastguard Worker   class ComputationTracker {
1135*03ce13f7SAndroid Build Coastguard Worker   public:
1136*03ce13f7SAndroid Build Coastguard Worker     ComputationTracker() = default;
1137*03ce13f7SAndroid Build Coastguard Worker     ~ComputationTracker() = default;
1138*03ce13f7SAndroid Build Coastguard Worker 
forgetProducers()1139*03ce13f7SAndroid Build Coastguard Worker     void forgetProducers() { KnownComputations.clear(); }
1140*03ce13f7SAndroid Build Coastguard Worker     void recordProducers(CfgNode *Node);
1141*03ce13f7SAndroid Build Coastguard Worker 
getProducerOf(const Operand * Opnd)1142*03ce13f7SAndroid Build Coastguard Worker     const Inst *getProducerOf(const Operand *Opnd) const {
1143*03ce13f7SAndroid Build Coastguard Worker       auto *Var = llvm::dyn_cast<Variable>(Opnd);
1144*03ce13f7SAndroid Build Coastguard Worker       if (Var == nullptr) {
1145*03ce13f7SAndroid Build Coastguard Worker         return nullptr;
1146*03ce13f7SAndroid Build Coastguard Worker       }
1147*03ce13f7SAndroid Build Coastguard Worker 
1148*03ce13f7SAndroid Build Coastguard Worker       auto Iter = KnownComputations.find(Var->getIndex());
1149*03ce13f7SAndroid Build Coastguard Worker       if (Iter == KnownComputations.end()) {
1150*03ce13f7SAndroid Build Coastguard Worker         return nullptr;
1151*03ce13f7SAndroid Build Coastguard Worker       }
1152*03ce13f7SAndroid Build Coastguard Worker 
1153*03ce13f7SAndroid Build Coastguard Worker       return Iter->second.Instr;
1154*03ce13f7SAndroid Build Coastguard Worker     }
1155*03ce13f7SAndroid Build Coastguard Worker 
dump(const Cfg * Func)1156*03ce13f7SAndroid Build Coastguard Worker     void dump(const Cfg *Func) const {
1157*03ce13f7SAndroid Build Coastguard Worker       if (!BuildDefs::dump() || !Func->isVerbose(IceV_Folding))
1158*03ce13f7SAndroid Build Coastguard Worker         return;
1159*03ce13f7SAndroid Build Coastguard Worker       OstreamLocker L(Func->getContext());
1160*03ce13f7SAndroid Build Coastguard Worker       Ostream &Str = Func->getContext()->getStrDump();
1161*03ce13f7SAndroid Build Coastguard Worker       Str << "foldable producer:\n";
1162*03ce13f7SAndroid Build Coastguard Worker       for (const auto &Computation : KnownComputations) {
1163*03ce13f7SAndroid Build Coastguard Worker         Str << "    ";
1164*03ce13f7SAndroid Build Coastguard Worker         Computation.second.Instr->dump(Func);
1165*03ce13f7SAndroid Build Coastguard Worker         Str << "\n";
1166*03ce13f7SAndroid Build Coastguard Worker       }
1167*03ce13f7SAndroid Build Coastguard Worker       Str << "\n";
1168*03ce13f7SAndroid Build Coastguard Worker     }
1169*03ce13f7SAndroid Build Coastguard Worker 
1170*03ce13f7SAndroid Build Coastguard Worker   private:
1171*03ce13f7SAndroid Build Coastguard Worker     class ComputationEntry {
1172*03ce13f7SAndroid Build Coastguard Worker     public:
ComputationEntry(Inst * I,Type Ty)1173*03ce13f7SAndroid Build Coastguard Worker       ComputationEntry(Inst *I, Type Ty) : Instr(I), ComputationType(Ty) {}
1174*03ce13f7SAndroid Build Coastguard Worker       Inst *const Instr;
1175*03ce13f7SAndroid Build Coastguard Worker       // Boolean folding is disabled for variables whose live range is multi
1176*03ce13f7SAndroid Build Coastguard Worker       // block. We conservatively initialize IsLiveOut to true, and set it to
1177*03ce13f7SAndroid Build Coastguard Worker       // false once we find the end of the live range for the variable defined
1178*03ce13f7SAndroid Build Coastguard Worker       // by this instruction. If liveness analysis is not performed (e.g., in
1179*03ce13f7SAndroid Build Coastguard Worker       // Om1 mode) IsLiveOut will never be set to false, and folding will be
1180*03ce13f7SAndroid Build Coastguard Worker       // disabled.
1181*03ce13f7SAndroid Build Coastguard Worker       bool IsLiveOut = true;
1182*03ce13f7SAndroid Build Coastguard Worker       int32_t NumUses = 0;
1183*03ce13f7SAndroid Build Coastguard Worker       Type ComputationType;
1184*03ce13f7SAndroid Build Coastguard Worker     };
1185*03ce13f7SAndroid Build Coastguard Worker 
1186*03ce13f7SAndroid Build Coastguard Worker     // ComputationMap maps a Variable number to a payload identifying which
1187*03ce13f7SAndroid Build Coastguard Worker     // instruction defined it.
1188*03ce13f7SAndroid Build Coastguard Worker     using ComputationMap = CfgUnorderedMap<SizeT, ComputationEntry>;
1189*03ce13f7SAndroid Build Coastguard Worker     ComputationMap KnownComputations;
1190*03ce13f7SAndroid Build Coastguard Worker   };
1191*03ce13f7SAndroid Build Coastguard Worker 
1192*03ce13f7SAndroid Build Coastguard Worker   ComputationTracker Computations;
1193*03ce13f7SAndroid Build Coastguard Worker 
1194*03ce13f7SAndroid Build Coastguard Worker   // AllowTemporaryWithNoReg indicates if TargetARM32::makeReg() can be invoked
1195*03ce13f7SAndroid Build Coastguard Worker   // without specifying a physical register. This is needed for creating unbound
1196*03ce13f7SAndroid Build Coastguard Worker   // temporaries during Ice -> ARM lowering, but before register allocation.
1197*03ce13f7SAndroid Build Coastguard Worker   // This a safe-guard that no unbound temporaries are created during the
1198*03ce13f7SAndroid Build Coastguard Worker   // legalization post-passes.
1199*03ce13f7SAndroid Build Coastguard Worker   bool AllowTemporaryWithNoReg = true;
1200*03ce13f7SAndroid Build Coastguard Worker   // ForbidTemporaryWithoutReg is a RAII class that manages
1201*03ce13f7SAndroid Build Coastguard Worker   // AllowTemporaryWithNoReg.
1202*03ce13f7SAndroid Build Coastguard Worker   class ForbidTemporaryWithoutReg {
1203*03ce13f7SAndroid Build Coastguard Worker     ForbidTemporaryWithoutReg() = delete;
1204*03ce13f7SAndroid Build Coastguard Worker     ForbidTemporaryWithoutReg(const ForbidTemporaryWithoutReg &) = delete;
1205*03ce13f7SAndroid Build Coastguard Worker     ForbidTemporaryWithoutReg &
1206*03ce13f7SAndroid Build Coastguard Worker     operator=(const ForbidTemporaryWithoutReg &) = delete;
1207*03ce13f7SAndroid Build Coastguard Worker 
1208*03ce13f7SAndroid Build Coastguard Worker   public:
ForbidTemporaryWithoutReg(TargetARM32 * Target)1209*03ce13f7SAndroid Build Coastguard Worker     explicit ForbidTemporaryWithoutReg(TargetARM32 *Target) : Target(Target) {
1210*03ce13f7SAndroid Build Coastguard Worker       Target->AllowTemporaryWithNoReg = false;
1211*03ce13f7SAndroid Build Coastguard Worker     }
~ForbidTemporaryWithoutReg()1212*03ce13f7SAndroid Build Coastguard Worker     ~ForbidTemporaryWithoutReg() { Target->AllowTemporaryWithNoReg = true; }
1213*03ce13f7SAndroid Build Coastguard Worker 
1214*03ce13f7SAndroid Build Coastguard Worker   private:
1215*03ce13f7SAndroid Build Coastguard Worker     TargetARM32 *const Target;
1216*03ce13f7SAndroid Build Coastguard Worker   };
1217*03ce13f7SAndroid Build Coastguard Worker };
1218*03ce13f7SAndroid Build Coastguard Worker 
1219*03ce13f7SAndroid Build Coastguard Worker class TargetDataARM32 final : public TargetDataLowering {
1220*03ce13f7SAndroid Build Coastguard Worker   TargetDataARM32() = delete;
1221*03ce13f7SAndroid Build Coastguard Worker   TargetDataARM32(const TargetDataARM32 &) = delete;
1222*03ce13f7SAndroid Build Coastguard Worker   TargetDataARM32 &operator=(const TargetDataARM32 &) = delete;
1223*03ce13f7SAndroid Build Coastguard Worker 
1224*03ce13f7SAndroid Build Coastguard Worker public:
create(GlobalContext * Ctx)1225*03ce13f7SAndroid Build Coastguard Worker   static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) {
1226*03ce13f7SAndroid Build Coastguard Worker     return std::unique_ptr<TargetDataLowering>(new TargetDataARM32(Ctx));
1227*03ce13f7SAndroid Build Coastguard Worker   }
1228*03ce13f7SAndroid Build Coastguard Worker 
1229*03ce13f7SAndroid Build Coastguard Worker   void lowerGlobals(const VariableDeclarationList &Vars,
1230*03ce13f7SAndroid Build Coastguard Worker                     const std::string &SectionSuffix) override;
1231*03ce13f7SAndroid Build Coastguard Worker   void lowerConstants() override;
1232*03ce13f7SAndroid Build Coastguard Worker   void lowerJumpTables() override;
1233*03ce13f7SAndroid Build Coastguard Worker 
1234*03ce13f7SAndroid Build Coastguard Worker protected:
1235*03ce13f7SAndroid Build Coastguard Worker   explicit TargetDataARM32(GlobalContext *Ctx);
1236*03ce13f7SAndroid Build Coastguard Worker 
1237*03ce13f7SAndroid Build Coastguard Worker private:
1238*03ce13f7SAndroid Build Coastguard Worker   ~TargetDataARM32() override = default;
1239*03ce13f7SAndroid Build Coastguard Worker };
1240*03ce13f7SAndroid Build Coastguard Worker 
1241*03ce13f7SAndroid Build Coastguard Worker class TargetHeaderARM32 final : public TargetHeaderLowering {
1242*03ce13f7SAndroid Build Coastguard Worker   TargetHeaderARM32() = delete;
1243*03ce13f7SAndroid Build Coastguard Worker   TargetHeaderARM32(const TargetHeaderARM32 &) = delete;
1244*03ce13f7SAndroid Build Coastguard Worker   TargetHeaderARM32 &operator=(const TargetHeaderARM32 &) = delete;
1245*03ce13f7SAndroid Build Coastguard Worker 
1246*03ce13f7SAndroid Build Coastguard Worker public:
create(GlobalContext * Ctx)1247*03ce13f7SAndroid Build Coastguard Worker   static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) {
1248*03ce13f7SAndroid Build Coastguard Worker     return std::unique_ptr<TargetHeaderLowering>(new TargetHeaderARM32(Ctx));
1249*03ce13f7SAndroid Build Coastguard Worker   }
1250*03ce13f7SAndroid Build Coastguard Worker 
1251*03ce13f7SAndroid Build Coastguard Worker   void lower() override;
1252*03ce13f7SAndroid Build Coastguard Worker 
1253*03ce13f7SAndroid Build Coastguard Worker protected:
1254*03ce13f7SAndroid Build Coastguard Worker   explicit TargetHeaderARM32(GlobalContext *Ctx);
1255*03ce13f7SAndroid Build Coastguard Worker 
1256*03ce13f7SAndroid Build Coastguard Worker private:
1257*03ce13f7SAndroid Build Coastguard Worker   ~TargetHeaderARM32() = default;
1258*03ce13f7SAndroid Build Coastguard Worker 
1259*03ce13f7SAndroid Build Coastguard Worker   TargetARM32Features CPUFeatures;
1260*03ce13f7SAndroid Build Coastguard Worker };
1261*03ce13f7SAndroid Build Coastguard Worker 
1262*03ce13f7SAndroid Build Coastguard Worker } // end of namespace ARM32
1263*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice
1264*03ce13f7SAndroid Build Coastguard Worker 
1265*03ce13f7SAndroid Build Coastguard Worker #endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H
1266