| OLD | NEW |
| 1 //===- subzero/src/IceTargetLoweringARM32.h - ARM32 lowering ----*- C++ -*-===// | 1 //===- subzero/src/IceTargetLoweringARM32.h - ARM32 lowering ----*- C++ -*-===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 /// | 9 /// |
| 10 /// \file | 10 /// \file |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 const llvm::SmallBitVector &getAliasesForRegister(SizeT Reg) const override { | 71 const llvm::SmallBitVector &getAliasesForRegister(SizeT Reg) const override { |
| 72 return RegisterAliases[Reg]; | 72 return RegisterAliases[Reg]; |
| 73 } | 73 } |
| 74 bool hasFramePointer() const override { return UsesFramePointer; } | 74 bool hasFramePointer() const override { return UsesFramePointer; } |
| 75 SizeT getFrameOrStackReg() const override { | 75 SizeT getFrameOrStackReg() const override { |
| 76 return UsesFramePointer ? RegARM32::Reg_fp : RegARM32::Reg_sp; | 76 return UsesFramePointer ? RegARM32::Reg_fp : RegARM32::Reg_sp; |
| 77 } | 77 } |
| 78 SizeT getReservedTmpReg() const { return RegARM32::Reg_ip; } | 78 SizeT getReservedTmpReg() const { return RegARM32::Reg_ip; } |
| 79 | 79 |
| 80 size_t typeWidthInBytesOnStack(Type Ty) const override { | 80 size_t typeWidthInBytesOnStack(Type Ty) const override { |
| 81 // Round up to the next multiple of 4 bytes. In particular, i1, | 81 // Round up to the next multiple of 4 bytes. In particular, i1, i8, and i16 |
| 82 // i8, and i16 are rounded up to 4 bytes. | 82 // are rounded up to 4 bytes. |
| 83 return (typeWidthInBytes(Ty) + 3) & ~3; | 83 return (typeWidthInBytes(Ty) + 3) & ~3; |
| 84 } | 84 } |
| 85 | 85 |
| 86 // TODO(ascull): what size is best for ARM? | 86 // TODO(ascull): what size is best for ARM? |
| 87 SizeT getMinJumpTableSize() const override { return 3; } | 87 SizeT getMinJumpTableSize() const override { return 3; } |
| 88 void emitJumpTable(const Cfg *Func, | 88 void emitJumpTable(const Cfg *Func, |
| 89 const InstJumpTable *JumpTable) const override; | 89 const InstJumpTable *JumpTable) const override; |
| 90 | 90 |
| 91 void emitVariable(const Variable *Var) const override; | 91 void emitVariable(const Variable *Var) const override; |
| 92 | 92 |
| 93 const char *getConstantPrefix() const final { return "#"; } | 93 const char *getConstantPrefix() const final { return "#"; } |
| 94 void emit(const ConstantUndef *C) const final; | 94 void emit(const ConstantUndef *C) const final; |
| 95 void emit(const ConstantInteger32 *C) const final; | 95 void emit(const ConstantInteger32 *C) const final; |
| 96 void emit(const ConstantInteger64 *C) const final; | 96 void emit(const ConstantInteger64 *C) const final; |
| 97 void emit(const ConstantFloat *C) const final; | 97 void emit(const ConstantFloat *C) const final; |
| 98 void emit(const ConstantDouble *C) const final; | 98 void emit(const ConstantDouble *C) const final; |
| 99 | 99 |
| 100 void lowerArguments() override; | 100 void lowerArguments() override; |
| 101 void addProlog(CfgNode *Node) override; | 101 void addProlog(CfgNode *Node) override; |
| 102 void addEpilog(CfgNode *Node) override; | 102 void addEpilog(CfgNode *Node) override; |
| 103 | 103 |
| 104 /// Ensure that a 64-bit Variable has been split into 2 32-bit | 104 /// Ensure that a 64-bit Variable has been split into 2 32-bit Variables, |
| 105 /// Variables, creating them if necessary. This is needed for all | 105 /// creating them if necessary. This is needed for all I64 operations. |
| 106 /// I64 operations. | |
| 107 void split64(Variable *Var); | 106 void split64(Variable *Var); |
| 108 Operand *loOperand(Operand *Operand); | 107 Operand *loOperand(Operand *Operand); |
| 109 Operand *hiOperand(Operand *Operand); | 108 Operand *hiOperand(Operand *Operand); |
| 110 void finishArgumentLowering(Variable *Arg, Variable *FramePtr, | 109 void finishArgumentLowering(Variable *Arg, Variable *FramePtr, |
| 111 size_t BasicFrameOffset, size_t &InArgsSizeBytes); | 110 size_t BasicFrameOffset, size_t &InArgsSizeBytes); |
| 112 | 111 |
| 113 bool hasCPUFeature(TargetARM32Features::ARM32InstructionSet I) const { | 112 bool hasCPUFeature(TargetARM32Features::ARM32InstructionSet I) const { |
| 114 return CPUFeatures.hasFeature(I); | 113 return CPUFeatures.hasFeature(I); |
| 115 } | 114 } |
| 116 Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister); | 115 Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 140 void lowerUnreachable(const InstUnreachable *Inst) override; | 139 void lowerUnreachable(const InstUnreachable *Inst) override; |
| 141 void prelowerPhis() override; | 140 void prelowerPhis() override; |
| 142 void doAddressOptLoad() override; | 141 void doAddressOptLoad() override; |
| 143 void doAddressOptStore() override; | 142 void doAddressOptStore() override; |
| 144 void randomlyInsertNop(float Probability, | 143 void randomlyInsertNop(float Probability, |
| 145 RandomNumberGenerator &RNG) override; | 144 RandomNumberGenerator &RNG) override; |
| 146 | 145 |
| 147 enum OperandLegalization { | 146 enum OperandLegalization { |
| 148 Legal_None = 0, | 147 Legal_None = 0, |
| 149 Legal_Reg = 1 << 0, /// physical register, not stack location | 148 Legal_Reg = 1 << 0, /// physical register, not stack location |
| 150 Legal_Flex = 1 << 1, /// A flexible operand2, which can hold rotated | 149 Legal_Flex = 1 << 1, /// A flexible operand2, which can hold rotated small |
| 151 /// small immediates, or shifted registers. | 150 /// immediates, or shifted registers. |
| 152 Legal_Mem = 1 << 2, /// includes [r0, r1 lsl #2] as well as [sp, #12] | 151 Legal_Mem = 1 << 2, /// includes [r0, r1 lsl #2] as well as [sp, #12] |
| 153 Legal_All = ~Legal_None | 152 Legal_All = ~Legal_None |
| 154 }; | 153 }; |
| 155 using LegalMask = uint32_t; | 154 using LegalMask = uint32_t; |
| 156 Operand *legalize(Operand *From, LegalMask Allowed = Legal_All, | 155 Operand *legalize(Operand *From, LegalMask Allowed = Legal_All, |
| 157 int32_t RegNum = Variable::NoRegister); | 156 int32_t RegNum = Variable::NoRegister); |
| 158 Variable *legalizeToReg(Operand *From, int32_t RegNum = Variable::NoRegister); | 157 Variable *legalizeToReg(Operand *From, int32_t RegNum = Variable::NoRegister); |
| 159 OperandARM32Mem *formMemoryOperand(Operand *Ptr, Type Ty); | 158 OperandARM32Mem *formMemoryOperand(Operand *Ptr, Type Ty); |
| 160 | 159 |
| 161 Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister); | 160 Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister); |
| 162 static Type stackSlotType(); | 161 static Type stackSlotType(); |
| 163 Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister); | 162 Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister); |
| 164 void alignRegisterPow2(Variable *Reg, uint32_t Align); | 163 void alignRegisterPow2(Variable *Reg, uint32_t Align); |
| 165 | 164 |
| 166 /// Returns a vector in a register with the given constant entries. | 165 /// Returns a vector in a register with the given constant entries. |
| 167 Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister); | 166 Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister); |
| 168 | 167 |
| 169 void | 168 void |
| 170 makeRandomRegisterPermutation(llvm::SmallVectorImpl<int32_t> &Permutation, | 169 makeRandomRegisterPermutation(llvm::SmallVectorImpl<int32_t> &Permutation, |
| 171 const llvm::SmallBitVector &ExcludeRegisters, | 170 const llvm::SmallBitVector &ExcludeRegisters, |
| 172 uint64_t Salt) const override; | 171 uint64_t Salt) const override; |
| 173 | 172 |
| 174 // If a divide-by-zero check is needed, inserts a: | 173 // If a divide-by-zero check is needed, inserts a: test; branch .LSKIP; trap; |
| 175 // test; branch .LSKIP; trap; .LSKIP: <continuation>. | 174 // .LSKIP: <continuation>. If no check is needed nothing is inserted. |
| 176 // If no check is needed nothing is inserted. | |
| 177 void div0Check(Type Ty, Operand *SrcLo, Operand *SrcHi); | 175 void div0Check(Type Ty, Operand *SrcLo, Operand *SrcHi); |
| 178 using ExtInstr = void (TargetARM32::*)(Variable *, Variable *, | 176 using ExtInstr = void (TargetARM32::*)(Variable *, Variable *, |
| 179 CondARM32::Cond); | 177 CondARM32::Cond); |
| 180 using DivInstr = void (TargetARM32::*)(Variable *, Variable *, Variable *, | 178 using DivInstr = void (TargetARM32::*)(Variable *, Variable *, Variable *, |
| 181 CondARM32::Cond); | 179 CondARM32::Cond); |
| 182 void lowerIDivRem(Variable *Dest, Variable *T, Variable *Src0R, Operand *Src1, | 180 void lowerIDivRem(Variable *Dest, Variable *T, Variable *Src0R, Operand *Src1, |
| 183 ExtInstr ExtFunc, DivInstr DivFunc, | 181 ExtInstr ExtFunc, DivInstr DivFunc, |
| 184 const char *DivHelperName, bool IsRemainder); | 182 const char *DivHelperName, bool IsRemainder); |
| 185 | 183 |
| 186 void lowerCLZ(Variable *Dest, Variable *ValLo, Variable *ValHi); | 184 void lowerCLZ(Variable *Dest, Variable *ValLo, Variable *ValHi); |
| 187 | 185 |
| 188 // The following are helpers that insert lowered ARM32 instructions | 186 // The following are helpers that insert lowered ARM32 instructions with |
| 189 // with minimal syntactic overhead, so that the lowering code can | 187 // minimal syntactic overhead, so that the lowering code can look as close to |
| 190 // look as close to assembly as practical. | 188 // assembly as practical. |
| 191 | 189 |
| 192 void _add(Variable *Dest, Variable *Src0, Operand *Src1, | 190 void _add(Variable *Dest, Variable *Src0, Operand *Src1, |
| 193 CondARM32::Cond Pred = CondARM32::AL) { | 191 CondARM32::Cond Pred = CondARM32::AL) { |
| 194 Context.insert(InstARM32Add::create(Func, Dest, Src0, Src1, Pred)); | 192 Context.insert(InstARM32Add::create(Func, Dest, Src0, Src1, Pred)); |
| 195 } | 193 } |
| 196 void _adds(Variable *Dest, Variable *Src0, Operand *Src1, | 194 void _adds(Variable *Dest, Variable *Src0, Operand *Src1, |
| 197 CondARM32::Cond Pred = CondARM32::AL) { | 195 CondARM32::Cond Pred = CondARM32::AL) { |
| 198 constexpr bool SetFlags = true; | 196 constexpr bool SetFlags = true; |
| 199 Context.insert( | 197 Context.insert( |
| 200 InstARM32Add::create(Func, Dest, Src0, Src1, Pred, SetFlags)); | 198 InstARM32Add::create(Func, Dest, Src0, Src1, Pred, SetFlags)); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 Context.insert(InstARM32Lsr::create(Func, Dest, Src0, Src1, Pred)); | 256 Context.insert(InstARM32Lsr::create(Func, Dest, Src0, Src1, Pred)); |
| 259 } | 257 } |
| 260 void _mla(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc, | 258 void _mla(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc, |
| 261 CondARM32::Cond Pred = CondARM32::AL) { | 259 CondARM32::Cond Pred = CondARM32::AL) { |
| 262 Context.insert(InstARM32Mla::create(Func, Dest, Src0, Src1, Acc, Pred)); | 260 Context.insert(InstARM32Mla::create(Func, Dest, Src0, Src1, Acc, Pred)); |
| 263 } | 261 } |
| 264 void _mls(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc, | 262 void _mls(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc, |
| 265 CondARM32::Cond Pred = CondARM32::AL) { | 263 CondARM32::Cond Pred = CondARM32::AL) { |
| 266 Context.insert(InstARM32Mls::create(Func, Dest, Src0, Src1, Acc, Pred)); | 264 Context.insert(InstARM32Mls::create(Func, Dest, Src0, Src1, Acc, Pred)); |
| 267 } | 265 } |
| 268 /// If Dest=nullptr is passed in, then a new variable is created, | 266 /// If Dest=nullptr is passed in, then a new variable is created, marked as |
| 269 /// marked as infinite register allocation weight, and returned | 267 /// infinite register allocation weight, and returned through the in/out Dest |
| 270 /// through the in/out Dest argument. | 268 /// argument. |
| 271 void _mov(Variable *&Dest, Operand *Src0, | 269 void _mov(Variable *&Dest, Operand *Src0, |
| 272 CondARM32::Cond Pred = CondARM32::AL, | 270 CondARM32::Cond Pred = CondARM32::AL, |
| 273 int32_t RegNum = Variable::NoRegister) { | 271 int32_t RegNum = Variable::NoRegister) { |
| 274 if (Dest == nullptr) | 272 if (Dest == nullptr) |
| 275 Dest = makeReg(Src0->getType(), RegNum); | 273 Dest = makeReg(Src0->getType(), RegNum); |
| 276 Context.insert(InstARM32Mov::create(Func, Dest, Src0, Pred)); | 274 Context.insert(InstARM32Mov::create(Func, Dest, Src0, Pred)); |
| 277 } | 275 } |
| 278 void _mov_nonkillable(Variable *Dest, Operand *Src0, | 276 void _mov_nonkillable(Variable *Dest, Operand *Src0, |
| 279 CondARM32::Cond Pred = CondARM32::AL) { | 277 CondARM32::Cond Pred = CondARM32::AL) { |
| 280 Inst *NewInst = InstARM32Mov::create(Func, Dest, Src0, Pred); | 278 Inst *NewInst = InstARM32Mov::create(Func, Dest, Src0, Pred); |
| 281 NewInst->setDestNonKillable(); | 279 NewInst->setDestNonKillable(); |
| 282 Context.insert(NewInst); | 280 Context.insert(NewInst); |
| 283 } | 281 } |
| 284 /// The Operand can only be a 16-bit immediate or a ConstantRelocatable | 282 /// The Operand can only be a 16-bit immediate or a ConstantRelocatable (with |
| 285 /// (with an upper16 relocation). | 283 /// an upper16 relocation). |
| 286 void _movt(Variable *Dest, Operand *Src0, | 284 void _movt(Variable *Dest, Operand *Src0, |
| 287 CondARM32::Cond Pred = CondARM32::AL) { | 285 CondARM32::Cond Pred = CondARM32::AL) { |
| 288 Context.insert(InstARM32Movt::create(Func, Dest, Src0, Pred)); | 286 Context.insert(InstARM32Movt::create(Func, Dest, Src0, Pred)); |
| 289 } | 287 } |
| 290 void _movw(Variable *Dest, Operand *Src0, | 288 void _movw(Variable *Dest, Operand *Src0, |
| 291 CondARM32::Cond Pred = CondARM32::AL) { | 289 CondARM32::Cond Pred = CondARM32::AL) { |
| 292 Context.insert(InstARM32Movw::create(Func, Dest, Src0, Pred)); | 290 Context.insert(InstARM32Movw::create(Func, Dest, Src0, Pred)); |
| 293 } | 291 } |
| 294 void _mul(Variable *Dest, Variable *Src0, Variable *Src1, | 292 void _mul(Variable *Dest, Variable *Src0, Variable *Src1, |
| 295 CondARM32::Cond Pred = CondARM32::AL) { | 293 CondARM32::Cond Pred = CondARM32::AL) { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 } | 369 } |
| 372 void _trap() { Context.insert(InstARM32Trap::create(Func)); } | 370 void _trap() { Context.insert(InstARM32Trap::create(Func)); } |
| 373 void _udiv(Variable *Dest, Variable *Src0, Variable *Src1, | 371 void _udiv(Variable *Dest, Variable *Src0, Variable *Src1, |
| 374 CondARM32::Cond Pred = CondARM32::AL) { | 372 CondARM32::Cond Pred = CondARM32::AL) { |
| 375 Context.insert(InstARM32Udiv::create(Func, Dest, Src0, Src1, Pred)); | 373 Context.insert(InstARM32Udiv::create(Func, Dest, Src0, Src1, Pred)); |
| 376 } | 374 } |
| 377 void _umull(Variable *DestLo, Variable *DestHi, Variable *Src0, | 375 void _umull(Variable *DestLo, Variable *DestHi, Variable *Src0, |
| 378 Variable *Src1, CondARM32::Cond Pred = CondARM32::AL) { | 376 Variable *Src1, CondARM32::Cond Pred = CondARM32::AL) { |
| 379 Context.insert( | 377 Context.insert( |
| 380 InstARM32Umull::create(Func, DestLo, DestHi, Src0, Src1, Pred)); | 378 InstARM32Umull::create(Func, DestLo, DestHi, Src0, Src1, Pred)); |
| 381 // Model the modification to the second dest as a fake def. | 379 // Model the modification to the second dest as a fake def. Note that the |
| 382 // Note that the def is not predicated. | 380 // def is not predicated. |
| 383 Context.insert(InstFakeDef::create(Func, DestHi, DestLo)); | 381 Context.insert(InstFakeDef::create(Func, DestHi, DestLo)); |
| 384 } | 382 } |
| 385 void _uxt(Variable *Dest, Variable *Src0, | 383 void _uxt(Variable *Dest, Variable *Src0, |
| 386 CondARM32::Cond Pred = CondARM32::AL) { | 384 CondARM32::Cond Pred = CondARM32::AL) { |
| 387 Context.insert(InstARM32Uxt::create(Func, Dest, Src0, Pred)); | 385 Context.insert(InstARM32Uxt::create(Func, Dest, Src0, Pred)); |
| 388 } | 386 } |
| 389 void _vadd(Variable *Dest, Variable *Src0, Variable *Src1) { | 387 void _vadd(Variable *Dest, Variable *Src0, Variable *Src1) { |
| 390 Context.insert(InstARM32Vadd::create(Func, Dest, Src0, Src1)); | 388 Context.insert(InstARM32Vadd::create(Func, Dest, Src0, Src1)); |
| 391 } | 389 } |
| 392 void _vcvt(Variable *Dest, Variable *Src, InstARM32Vcvt::VcvtVariant Variant, | 390 void _vcvt(Variable *Dest, Variable *Src, InstARM32Vcvt::VcvtVariant Variant, |
| 393 CondARM32::Cond Pred = CondARM32::AL) { | 391 CondARM32::Cond Pred = CondARM32::AL) { |
| 394 Context.insert(InstARM32Vcvt::create(Func, Dest, Src, Variant, Pred)); | 392 Context.insert(InstARM32Vcvt::create(Func, Dest, Src, Variant, Pred)); |
| 395 } | 393 } |
| 396 void _vdiv(Variable *Dest, Variable *Src0, Variable *Src1) { | 394 void _vdiv(Variable *Dest, Variable *Src0, Variable *Src1) { |
| 397 Context.insert(InstARM32Vdiv::create(Func, Dest, Src0, Src1)); | 395 Context.insert(InstARM32Vdiv::create(Func, Dest, Src0, Src1)); |
| 398 } | 396 } |
| 399 void _vldr(Variable *Dest, OperandARM32Mem *Src, | 397 void _vldr(Variable *Dest, OperandARM32Mem *Src, |
| 400 CondARM32::Cond Pred = CondARM32::AL) { | 398 CondARM32::Cond Pred = CondARM32::AL) { |
| 401 Context.insert(InstARM32Vldr::create(Func, Dest, Src, Pred)); | 399 Context.insert(InstARM32Vldr::create(Func, Dest, Src, Pred)); |
| 402 } | 400 } |
| 403 // There are a whole bunch of vmov variants, to transfer within | 401 // There are a whole bunch of vmov variants, to transfer within S/D/Q |
| 404 // S/D/Q registers, between core integer registers and S/D, | 402 // registers, between core integer registers and S/D, and from small |
| 405 // and from small immediates into S/D. | 403 // immediates into S/D. For integer -> S/D/Q there is a variant which takes |
| 406 // For integer -> S/D/Q there is a variant which takes two integer | 404 // two integer register to fill a D, or to fill two consecutive S registers. |
| 407 // register to fill a D, or to fill two consecutive S registers. | |
| 408 // Vmov can also be used to insert-element. E.g., | 405 // Vmov can also be used to insert-element. E.g., |
| 409 // "vmov.8 d0[1], r0" | 406 // "vmov.8 d0[1], r0" |
| 410 // but insert-element is a "two-address" operation where only part of the | 407 // but insert-element is a "two-address" operation where only part of the |
| 411 // register is modified. This cannot model that. | 408 // register is modified. This cannot model that. |
| 412 // | 409 // |
| 413 // This represents the simple single source, single dest variants only. | 410 // This represents the simple single source, single dest variants only. |
| 414 void _vmov(Variable *Dest, Operand *Src0) { | 411 void _vmov(Variable *Dest, Operand *Src0) { |
| 415 constexpr CondARM32::Cond Pred = CondARM32::AL; | 412 constexpr CondARM32::Cond Pred = CondARM32::AL; |
| 416 Context.insert(InstARM32Vmov::create(Func, Dest, Src0, Pred)); | 413 Context.insert(InstARM32Vmov::create(Func, Dest, Src0, Pred)); |
| 417 } | 414 } |
| 418 void _vmul(Variable *Dest, Variable *Src0, Variable *Src1) { | 415 void _vmul(Variable *Dest, Variable *Src0, Variable *Src1) { |
| 419 Context.insert(InstARM32Vmul::create(Func, Dest, Src0, Src1)); | 416 Context.insert(InstARM32Vmul::create(Func, Dest, Src0, Src1)); |
| 420 } | 417 } |
| 421 void _vsqrt(Variable *Dest, Variable *Src, | 418 void _vsqrt(Variable *Dest, Variable *Src, |
| 422 CondARM32::Cond Pred = CondARM32::AL) { | 419 CondARM32::Cond Pred = CondARM32::AL) { |
| 423 Context.insert(InstARM32Vsqrt::create(Func, Dest, Src, Pred)); | 420 Context.insert(InstARM32Vsqrt::create(Func, Dest, Src, Pred)); |
| 424 } | 421 } |
| 425 void _vsub(Variable *Dest, Variable *Src0, Variable *Src1) { | 422 void _vsub(Variable *Dest, Variable *Src0, Variable *Src1) { |
| 426 Context.insert(InstARM32Vsub::create(Func, Dest, Src0, Src1)); | 423 Context.insert(InstARM32Vsub::create(Func, Dest, Src0, Src1)); |
| 427 } | 424 } |
| 428 | 425 |
| 429 /// Run a pass through stack variables and ensure that the offsets are legal. | 426 /// Run a pass through stack variables and ensure that the offsets are legal. |
| 430 /// If the offset is not legal, use a new base register that accounts for | 427 /// If the offset is not legal, use a new base register that accounts for the |
| 431 /// the offset, such that the addressing mode offset bits are now legal. | 428 /// offset, such that the addressing mode offset bits are now legal. |
| 432 void legalizeStackSlots(); | 429 void legalizeStackSlots(); |
| 433 /// Returns true if the given Offset can be represented in a stack ldr/str. | 430 /// Returns true if the given Offset can be represented in a stack ldr/str. |
| 434 bool isLegalVariableStackOffset(int32_t Offset) const; | 431 bool isLegalVariableStackOffset(int32_t Offset) const; |
| 435 /// Assuming Var needs its offset legalized, define a new base register | 432 /// Assuming Var needs its offset legalized, define a new base register |
| 436 /// centered on the given Var's offset and use it. | 433 /// centered on the given Var's offset and use it. |
| 437 StackVariable *legalizeVariableSlot(Variable *Var, Variable *OrigBaseReg); | 434 StackVariable *legalizeVariableSlot(Variable *Var, Variable *OrigBaseReg); |
| 438 | 435 |
| 439 TargetARM32Features CPUFeatures; | 436 TargetARM32Features CPUFeatures; |
| 440 bool UsesFramePointer = false; | 437 bool UsesFramePointer = false; |
| 441 bool NeedsStackAlignment = false; | 438 bool NeedsStackAlignment = false; |
| 442 bool MaybeLeafFunc = true; | 439 bool MaybeLeafFunc = true; |
| 443 size_t SpillAreaSizeBytes = 0; | 440 size_t SpillAreaSizeBytes = 0; |
| 444 // TODO(jpp): std::array instead of array. | 441 // TODO(jpp): std::array instead of array. |
| 445 llvm::SmallBitVector TypeToRegisterSet[IceType_NUM]; | 442 llvm::SmallBitVector TypeToRegisterSet[IceType_NUM]; |
| 446 llvm::SmallBitVector RegisterAliases[RegARM32::Reg_NUM]; | 443 llvm::SmallBitVector RegisterAliases[RegARM32::Reg_NUM]; |
| 447 llvm::SmallBitVector ScratchRegs; | 444 llvm::SmallBitVector ScratchRegs; |
| 448 llvm::SmallBitVector RegsUsed; | 445 llvm::SmallBitVector RegsUsed; |
| 449 VarList PhysicalRegisters[IceType_NUM]; | 446 VarList PhysicalRegisters[IceType_NUM]; |
| 450 | 447 |
| 451 /// Helper class that understands the Calling Convention and register | 448 /// Helper class that understands the Calling Convention and register |
| 452 /// assignments. The first few integer type parameters can use r0-r3, | 449 /// assignments. The first few integer type parameters can use r0-r3, |
| 453 /// regardless of their position relative to the floating-point/vector | 450 /// regardless of their position relative to the floating-point/vector |
| 454 /// arguments in the argument list. Floating-point and vector arguments | 451 /// arguments in the argument list. Floating-point and vector arguments can |
| 455 /// can use q0-q3 (aka d0-d7, s0-s15). Technically, arguments that can | 452 /// use q0-q3 (aka d0-d7, s0-s15). Technically, arguments that can start with |
| 456 /// start with registers but extend beyond the available registers can be | 453 /// registers but extend beyond the available registers can be split between |
| 457 /// split between the registers and the stack. However, this is typically | 454 /// the registers and the stack. However, this is typically for passing GPR |
| 458 /// for passing GPR structs by value, and PNaCl transforms expand this out. | 455 /// structs by value, and PNaCl transforms expand this out. |
| 459 /// | 456 /// |
| 460 /// Also, at the point before the call, the stack must be aligned. | 457 /// Also, at the point before the call, the stack must be aligned. |
| 461 class CallingConv { | 458 class CallingConv { |
| 462 CallingConv(const CallingConv &) = delete; | 459 CallingConv(const CallingConv &) = delete; |
| 463 CallingConv &operator=(const CallingConv &) = delete; | 460 CallingConv &operator=(const CallingConv &) = delete; |
| 464 | 461 |
| 465 public: | 462 public: |
| 466 CallingConv() {} | 463 CallingConv() {} |
| 467 ~CallingConv() = default; | 464 ~CallingConv() = default; |
| 468 | 465 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 523 | 520 |
| 524 private: | 521 private: |
| 525 ~TargetHeaderARM32() = default; | 522 ~TargetHeaderARM32() = default; |
| 526 | 523 |
| 527 TargetARM32Features CPUFeatures; | 524 TargetARM32Features CPUFeatures; |
| 528 }; | 525 }; |
| 529 | 526 |
| 530 } // end of namespace Ice | 527 } // end of namespace Ice |
| 531 | 528 |
| 532 #endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H | 529 #endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H |
| OLD | NEW |