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