Chromium Code Reviews| 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 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 239 Context.insert(InstARM32Cmp::create(Func, Src0, Src1, Pred)); | 239 Context.insert(InstARM32Cmp::create(Func, Src0, Src1, Pred)); |
| 240 } | 240 } |
| 241 void _clz(Variable *Dest, Variable *Src0, | 241 void _clz(Variable *Dest, Variable *Src0, |
| 242 CondARM32::Cond Pred = CondARM32::AL) { | 242 CondARM32::Cond Pred = CondARM32::AL) { |
| 243 Context.insert(InstARM32Clz::create(Func, Dest, Src0, Pred)); | 243 Context.insert(InstARM32Clz::create(Func, Dest, Src0, Pred)); |
| 244 } | 244 } |
| 245 void _eor(Variable *Dest, Variable *Src0, Operand *Src1, | 245 void _eor(Variable *Dest, Variable *Src0, Operand *Src1, |
| 246 CondARM32::Cond Pred = CondARM32::AL) { | 246 CondARM32::Cond Pred = CondARM32::AL) { |
| 247 Context.insert(InstARM32Eor::create(Func, Dest, Src0, Src1, Pred)); | 247 Context.insert(InstARM32Eor::create(Func, Dest, Src0, Src1, Pred)); |
| 248 } | 248 } |
| 249 /// _ldr, for all your Variable to memory data moves. It handles all types | |
|
Jim Stichnoth
2015/09/24 05:57:14
I would describe this as "memory to Variable data
John
2015/09/24 21:28:40
Done.
| |
| 250 /// (integer, floating point, and vectors.) Addr needs to be valid for Dest's | |
| 251 /// type (e.g., no immediates for vector loads, and no index registers for fp | |
| 252 /// loads.) | |
| 249 void _ldr(Variable *Dest, OperandARM32Mem *Addr, | 253 void _ldr(Variable *Dest, OperandARM32Mem *Addr, |
| 250 CondARM32::Cond Pred = CondARM32::AL) { | 254 CondARM32::Cond Pred = CondARM32::AL) { |
| 251 Context.insert(InstARM32Ldr::create(Func, Dest, Addr, Pred)); | 255 Context.insert(InstARM32Ldr::create(Func, Dest, Addr, Pred)); |
| 252 } | 256 } |
| 253 void _lsl(Variable *Dest, Variable *Src0, Operand *Src1, | 257 void _lsl(Variable *Dest, Variable *Src0, Operand *Src1, |
| 254 CondARM32::Cond Pred = CondARM32::AL) { | 258 CondARM32::Cond Pred = CondARM32::AL) { |
| 255 Context.insert(InstARM32Lsl::create(Func, Dest, Src0, Src1, Pred)); | 259 Context.insert(InstARM32Lsl::create(Func, Dest, Src0, Src1, Pred)); |
| 256 } | 260 } |
| 257 void _lsr(Variable *Dest, Variable *Src0, Operand *Src1, | 261 void _lsr(Variable *Dest, Variable *Src0, Operand *Src1, |
| 258 CondARM32::Cond Pred = CondARM32::AL) { | 262 CondARM32::Cond Pred = CondARM32::AL) { |
| 259 Context.insert(InstARM32Lsr::create(Func, Dest, Src0, Src1, Pred)); | 263 Context.insert(InstARM32Lsr::create(Func, Dest, Src0, Src1, Pred)); |
| 260 } | 264 } |
| 261 void _mla(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc, | 265 void _mla(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc, |
| 262 CondARM32::Cond Pred = CondARM32::AL) { | 266 CondARM32::Cond Pred = CondARM32::AL) { |
| 263 Context.insert(InstARM32Mla::create(Func, Dest, Src0, Src1, Acc, Pred)); | 267 Context.insert(InstARM32Mla::create(Func, Dest, Src0, Src1, Acc, Pred)); |
| 264 } | 268 } |
| 265 void _mls(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc, | 269 void _mls(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc, |
| 266 CondARM32::Cond Pred = CondARM32::AL) { | 270 CondARM32::Cond Pred = CondARM32::AL) { |
| 267 Context.insert(InstARM32Mls::create(Func, Dest, Src0, Src1, Acc, Pred)); | 271 Context.insert(InstARM32Mls::create(Func, Dest, Src0, Src1, Acc, Pred)); |
| 268 } | 272 } |
| 269 /// If Dest=nullptr is passed in, then a new variable is created, marked as | 273 /// _mov, for all your Variable to Variable data movement needs. It handles |
| 270 /// infinite register allocation weight, and returned through the in/out Dest | 274 /// all types (integer, floating point, and vectors), as well as moves between |
| 271 /// argument. | 275 /// Core and VFP registers. This is not a panacea: you must obey the (weird, |
| 272 void _mov(Variable *&Dest, Operand *Src0, | 276 /// confusing, non-uniform) rules for data moves in ARM. |
| 273 CondARM32::Cond Pred = CondARM32::AL, | 277 /// If Dest=nullptr is passed in, then a new variable |
|
Jim Stichnoth
2015/09/24 05:57:13
Delete this part of the comment? (contradicted be
John
2015/09/24 21:28:40
Done.
| |
| 274 int32_t RegNum = Variable::NoRegister) { | 278 /// is created, marked as infinite register allocation weight, and returned |
| 275 if (Dest == nullptr) | 279 /// through the in/out Dest argument. |
| 276 Dest = makeReg(Src0->getType(), RegNum); | 280 void _mov(Variable *Dest, Operand *Src0, |
| 281 CondARM32::Cond Pred = CondARM32::AL) { | |
| 282 // _mov used to be unique in the sense that it would create a temporary | |
| 283 // automagically of Dest was nullptr. It won't do that anymore, so we keep | |
|
Jim Stichnoth
2015/09/24 05:57:13
s/of/if/
John
2015/09/24 21:28:40
Done.
| |
| 284 // an assert around just in case there is some untested code path where Dest | |
| 285 // is nullptr. | |
| 286 assert(Dest != nullptr); | |
| 277 Context.insert(InstARM32Mov::create(Func, Dest, Src0, Pred)); | 287 Context.insert(InstARM32Mov::create(Func, Dest, Src0, Pred)); |
| 278 } | 288 } |
| 279 void _mov_nonkillable(Variable *Dest, Operand *Src0, | 289 void _mov_nonkillable(Variable *Dest, Operand *Src0, |
| 280 CondARM32::Cond Pred = CondARM32::AL) { | 290 CondARM32::Cond Pred = CondARM32::AL) { |
| 281 Inst *NewInst = InstARM32Mov::create(Func, Dest, Src0, Pred); | 291 Inst *NewInst = InstARM32Mov::create(Func, Dest, Src0, Pred); |
| 282 NewInst->setDestNonKillable(); | 292 NewInst->setDestNonKillable(); |
| 283 Context.insert(NewInst); | 293 Context.insert(NewInst); |
| 284 } | 294 } |
| 285 /// The Operand can only be a 16-bit immediate or a ConstantRelocatable (with | 295 /// The Operand can only be a 16-bit immediate or a ConstantRelocatable (with |
| 286 /// an upper16 relocation). | 296 /// an upper16 relocation). |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 341 void _sbcs(Variable *Dest, Variable *Src0, Operand *Src1, | 351 void _sbcs(Variable *Dest, Variable *Src0, Operand *Src1, |
| 342 CondARM32::Cond Pred = CondARM32::AL) { | 352 CondARM32::Cond Pred = CondARM32::AL) { |
| 343 constexpr bool SetFlags = true; | 353 constexpr bool SetFlags = true; |
| 344 Context.insert( | 354 Context.insert( |
| 345 InstARM32Sbc::create(Func, Dest, Src0, Src1, Pred, SetFlags)); | 355 InstARM32Sbc::create(Func, Dest, Src0, Src1, Pred, SetFlags)); |
| 346 } | 356 } |
| 347 void _sdiv(Variable *Dest, Variable *Src0, Variable *Src1, | 357 void _sdiv(Variable *Dest, Variable *Src0, Variable *Src1, |
| 348 CondARM32::Cond Pred = CondARM32::AL) { | 358 CondARM32::Cond Pred = CondARM32::AL) { |
| 349 Context.insert(InstARM32Sdiv::create(Func, Dest, Src0, Src1, Pred)); | 359 Context.insert(InstARM32Sdiv::create(Func, Dest, Src0, Src1, Pred)); |
| 350 } | 360 } |
| 361 /// _str, for all your memory to Variable transfers. Addr has the same | |
| 362 /// restrictions that it does in _ldr. | |
| 351 void _str(Variable *Value, OperandARM32Mem *Addr, | 363 void _str(Variable *Value, OperandARM32Mem *Addr, |
| 352 CondARM32::Cond Pred = CondARM32::AL) { | 364 CondARM32::Cond Pred = CondARM32::AL) { |
| 353 Context.insert(InstARM32Str::create(Func, Value, Addr, Pred)); | 365 Context.insert(InstARM32Str::create(Func, Value, Addr, Pred)); |
| 354 } | 366 } |
| 355 void _sub(Variable *Dest, Variable *Src0, Operand *Src1, | 367 void _sub(Variable *Dest, Variable *Src0, Operand *Src1, |
| 356 CondARM32::Cond Pred = CondARM32::AL) { | 368 CondARM32::Cond Pred = CondARM32::AL) { |
| 357 Context.insert(InstARM32Sub::create(Func, Dest, Src0, Src1, Pred)); | 369 Context.insert(InstARM32Sub::create(Func, Dest, Src0, Src1, Pred)); |
| 358 } | 370 } |
| 359 void _subs(Variable *Dest, Variable *Src0, Operand *Src1, | 371 void _subs(Variable *Dest, Variable *Src0, Operand *Src1, |
| 360 CondARM32::Cond Pred = CondARM32::AL) { | 372 CondARM32::Cond Pred = CondARM32::AL) { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 380 Context.insert( | 392 Context.insert( |
| 381 InstARM32Umull::create(Func, DestLo, DestHi, Src0, Src1, Pred)); | 393 InstARM32Umull::create(Func, DestLo, DestHi, Src0, Src1, Pred)); |
| 382 // Model the modification to the second dest as a fake def. Note that the | 394 // Model the modification to the second dest as a fake def. Note that the |
| 383 // def is not predicated. | 395 // def is not predicated. |
| 384 Context.insert(InstFakeDef::create(Func, DestHi, DestLo)); | 396 Context.insert(InstFakeDef::create(Func, DestHi, DestLo)); |
| 385 } | 397 } |
| 386 void _uxt(Variable *Dest, Variable *Src0, | 398 void _uxt(Variable *Dest, Variable *Src0, |
| 387 CondARM32::Cond Pred = CondARM32::AL) { | 399 CondARM32::Cond Pred = CondARM32::AL) { |
| 388 Context.insert(InstARM32Uxt::create(Func, Dest, Src0, Pred)); | 400 Context.insert(InstARM32Uxt::create(Func, Dest, Src0, Pred)); |
| 389 } | 401 } |
| 402 void _vabs(Variable *Dest, Variable *Src, | |
| 403 CondARM32::Cond Pred = CondARM32::AL) { | |
| 404 Context.insert(InstARM32Vabs::create(Func, Dest, Src, Pred)); | |
| 405 } | |
| 390 void _vadd(Variable *Dest, Variable *Src0, Variable *Src1) { | 406 void _vadd(Variable *Dest, Variable *Src0, Variable *Src1) { |
| 391 Context.insert(InstARM32Vadd::create(Func, Dest, Src0, Src1)); | 407 Context.insert(InstARM32Vadd::create(Func, Dest, Src0, Src1)); |
| 392 } | 408 } |
| 393 void _vcvt(Variable *Dest, Variable *Src, InstARM32Vcvt::VcvtVariant Variant, | 409 void _vcvt(Variable *Dest, Variable *Src, InstARM32Vcvt::VcvtVariant Variant, |
| 394 CondARM32::Cond Pred = CondARM32::AL) { | 410 CondARM32::Cond Pred = CondARM32::AL) { |
| 395 Context.insert(InstARM32Vcvt::create(Func, Dest, Src, Variant, Pred)); | 411 Context.insert(InstARM32Vcvt::create(Func, Dest, Src, Variant, Pred)); |
| 396 } | 412 } |
| 397 void _vdiv(Variable *Dest, Variable *Src0, Variable *Src1) { | 413 void _vdiv(Variable *Dest, Variable *Src0, Variable *Src1) { |
| 398 Context.insert(InstARM32Vdiv::create(Func, Dest, Src0, Src1)); | 414 Context.insert(InstARM32Vdiv::create(Func, Dest, Src0, Src1)); |
| 399 } | 415 } |
| 400 void _vldr(Variable *Dest, OperandARM32Mem *Src, | |
| 401 CondARM32::Cond Pred = CondARM32::AL) { | |
| 402 Context.insert(InstARM32Vldr::create(Func, Dest, Src, Pred)); | |
| 403 } | |
| 404 void _vcmp(Variable *Src0, Variable *Src1, | 416 void _vcmp(Variable *Src0, Variable *Src1, |
| 405 CondARM32::Cond Pred = CondARM32::AL) { | 417 CondARM32::Cond Pred = CondARM32::AL) { |
| 406 Context.insert(InstARM32Vcmp::create(Func, Src0, Src1, Pred)); | 418 Context.insert(InstARM32Vcmp::create(Func, Src0, Src1, Pred)); |
| 407 } | 419 } |
| 408 void _vmrs(CondARM32::Cond Pred = CondARM32::AL) { | 420 void _vmrs(CondARM32::Cond Pred = CondARM32::AL) { |
| 409 Context.insert(InstARM32Vmrs::create(Func, Pred)); | 421 Context.insert(InstARM32Vmrs::create(Func, Pred)); |
| 410 } | 422 } |
| 411 // There are a whole bunch of vmov variants, to transfer within S/D/Q | |
| 412 // registers, between core integer registers and S/D, and from small | |
| 413 // immediates into S/D. For integer -> S/D/Q there is a variant which takes | |
| 414 // two integer register to fill a D, or to fill two consecutive S registers. | |
| 415 // Vmov can also be used to insert-element. E.g., | |
| 416 // "vmov.8 d0[1], r0" | |
| 417 // but insert-element is a "two-address" operation where only part of the | |
| 418 // register is modified. This cannot model that. | |
| 419 // | |
| 420 // This represents the simple single source, single dest variants only. | |
| 421 void _vmov(Variable *Dest, Operand *Src0, | |
| 422 CondARM32::Cond Pred = CondARM32::AL) { | |
| 423 Context.insert(InstARM32Vmov::create(Func, Dest, Src0, Pred)); | |
| 424 } | |
| 425 // This represents the single source, multi dest variant. | |
| 426 void _vmov(InstARM32Vmov::RegisterPair Dests, Variable *Src0) { | |
| 427 constexpr CondARM32::Cond Pred = CondARM32::AL; | |
| 428 Context.insert(InstARM32Vmov::create(Func, Dests, Src0, Pred)); | |
| 429 // The Vmov instruction created above does not define Dests._1. Therefore | |
| 430 // we add a Dest._1 = FakeDef pseudo instruction. | |
| 431 Context.insert(InstFakeDef::create(Func, Dests._1)); | |
| 432 } | |
| 433 // This represents the multi source, single dest variant. | |
| 434 void _vmov(Variable *Dest, InstARM32Vmov::RegisterPair Srcs) { | |
| 435 constexpr CondARM32::Cond Pred = CondARM32::AL; | |
| 436 Context.insert(InstARM32Vmov::create(Func, Dest, Srcs, Pred)); | |
| 437 } | |
| 438 void _vmul(Variable *Dest, Variable *Src0, Variable *Src1) { | 423 void _vmul(Variable *Dest, Variable *Src0, Variable *Src1) { |
| 439 Context.insert(InstARM32Vmul::create(Func, Dest, Src0, Src1)); | 424 Context.insert(InstARM32Vmul::create(Func, Dest, Src0, Src1)); |
| 440 } | 425 } |
| 441 void _vsqrt(Variable *Dest, Variable *Src, | 426 void _vsqrt(Variable *Dest, Variable *Src, |
| 442 CondARM32::Cond Pred = CondARM32::AL) { | 427 CondARM32::Cond Pred = CondARM32::AL) { |
| 443 Context.insert(InstARM32Vsqrt::create(Func, Dest, Src, Pred)); | 428 Context.insert(InstARM32Vsqrt::create(Func, Dest, Src, Pred)); |
| 444 } | 429 } |
| 445 void _vsub(Variable *Dest, Variable *Src0, Variable *Src1) { | 430 void _vsub(Variable *Dest, Variable *Src0, Variable *Src1) { |
| 446 Context.insert(InstARM32Vsub::create(Func, Dest, Src0, Src1)); | 431 Context.insert(InstARM32Vsub::create(Func, Dest, Src0, Src1)); |
| 447 } | 432 } |
| 448 | 433 |
| 449 /// Run a pass through stack variables and ensure that the offsets are legal. | 434 /// Run a pass through stack variables and ensure that the offsets are legal. |
| 450 /// If the offset is not legal, use a new base register that accounts for the | 435 /// If the offset is not legal, use a new base register that accounts for the |
| 451 /// offset, such that the addressing mode offset bits are now legal. | 436 /// offset, such that the addressing mode offset bits are now legal. |
| 452 void legalizeStackSlots(); | 437 void legalizeStackSlots(); |
| 453 /// Returns true if the given Offset can be represented in a stack ldr/str. | 438 /// Returns true if the given Offset can be represented in a stack ldr/str. |
| 454 bool isLegalVariableStackOffset(int32_t Offset) const; | 439 bool isLegalVariableStackOffset(Type Ty, int32_t Offset) const; |
| 455 /// Assuming Var needs its offset legalized, define a new base register | 440 /// Assuming Var needs its offset legalized, define a new base register |
| 456 /// centered on the given Var's offset and use it. | 441 /// centered on the given Var's offset and use it. |
| 457 StackVariable *legalizeVariableSlot(Variable *Var, Variable *OrigBaseReg); | 442 StackVariable *legalizeVariableSlot(Variable *Var, Variable *OrigBaseReg); |
| 458 | 443 |
| 459 TargetARM32Features CPUFeatures; | 444 TargetARM32Features CPUFeatures; |
| 460 bool UsesFramePointer = false; | 445 bool UsesFramePointer = false; |
| 461 bool NeedsStackAlignment = false; | 446 bool NeedsStackAlignment = false; |
| 462 bool MaybeLeafFunc = true; | 447 bool MaybeLeafFunc = true; |
| 463 size_t SpillAreaSizeBytes = 0; | 448 size_t SpillAreaSizeBytes = 0; |
| 464 // TODO(jpp): std::array instead of array. | 449 // TODO(jpp): std::array instead of array. |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 559 | 544 |
| 560 private: | 545 private: |
| 561 ~TargetHeaderARM32() = default; | 546 ~TargetHeaderARM32() = default; |
| 562 | 547 |
| 563 TargetARM32Features CPUFeatures; | 548 TargetARM32Features CPUFeatures; |
| 564 }; | 549 }; |
| 565 | 550 |
| 566 } // end of namespace Ice | 551 } // end of namespace Ice |
| 567 | 552 |
| 568 #endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H | 553 #endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H |
| OLD | NEW |