| OLD | NEW |
| 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// | 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// |
| 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 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 350 case InstArithmetic::Urem: | 350 case InstArithmetic::Urem: |
| 351 TargetHelper = Ctx->getConstantExternSym(H_urem_i64); | 351 TargetHelper = Ctx->getConstantExternSym(H_urem_i64); |
| 352 break; | 352 break; |
| 353 case InstArithmetic::Srem: | 353 case InstArithmetic::Srem: |
| 354 TargetHelper = Ctx->getConstantExternSym(H_srem_i64); | 354 TargetHelper = Ctx->getConstantExternSym(H_srem_i64); |
| 355 break; | 355 break; |
| 356 } | 356 } |
| 357 assert(TargetHelper != nullptr); | 357 assert(TargetHelper != nullptr); |
| 358 ARM32HelpersPreamble[TargetHelper] = &TargetARM32::preambleDivRem; | 358 ARM32HelpersPreamble[TargetHelper] = &TargetARM32::preambleDivRem; |
| 359 constexpr SizeT MaxArgs = 2; | 359 constexpr SizeT MaxArgs = 2; |
| 360 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper, | 360 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
| 361 NoTailCall, IsTargetHelperCall); | 361 NoTailCall, IsTargetHelperCall); |
| 362 Call->addArg(Instr->getSrc(0)); | 362 Call->addArg(Instr->getSrc(0)); |
| 363 Call->addArg(Instr->getSrc(1)); | 363 Call->addArg(Instr->getSrc(1)); |
| 364 Context.insert(Call); | |
| 365 Instr->setDeleted(); | 364 Instr->setDeleted(); |
| 366 return; | 365 return; |
| 367 } | 366 } |
| 368 case IceType_i32: | 367 case IceType_i32: |
| 369 case IceType_i16: | 368 case IceType_i16: |
| 370 case IceType_i8: { | 369 case IceType_i8: { |
| 371 const bool HasHWDiv = hasCPUFeature(TargetARM32Features::HWDivArm); | 370 const bool HasHWDiv = hasCPUFeature(TargetARM32Features::HWDivArm); |
| 372 InstCast::OpKind CastKind; | 371 InstCast::OpKind CastKind; |
| 373 Operand *TargetHelper; | 372 Operand *TargetHelper; |
| 374 switch (Op) { | 373 switch (Op) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 401 // the following assert will have to be modified. | 400 // the following assert will have to be modified. |
| 402 assert(HasHWDiv); | 401 assert(HasHWDiv); |
| 403 return; | 402 return; |
| 404 } | 403 } |
| 405 Operand *Src0 = Instr->getSrc(0); | 404 Operand *Src0 = Instr->getSrc(0); |
| 406 Operand *Src1 = Instr->getSrc(1); | 405 Operand *Src1 = Instr->getSrc(1); |
| 407 if (DestTy != IceType_i32) { | 406 if (DestTy != IceType_i32) { |
| 408 // Src0 and Src1 have to be zero-, or signed-extended to i32. For Src0, | 407 // Src0 and Src1 have to be zero-, or signed-extended to i32. For Src0, |
| 409 // we just insert a InstCast right before the call to the helper. | 408 // we just insert a InstCast right before the call to the helper. |
| 410 Variable *Src0_32 = Func->makeVariable(IceType_i32); | 409 Variable *Src0_32 = Func->makeVariable(IceType_i32); |
| 411 Context.insert(InstCast::create(Func, CastKind, Src0_32, Src0)); | 410 Context.insert<InstCast>(CastKind, Src0_32, Src0); |
| 412 Src0 = Src0_32; | 411 Src0 = Src0_32; |
| 413 | 412 |
| 414 // For extending Src1, we will just insert an InstCast if Src1 is not a | 413 // For extending Src1, we will just insert an InstCast if Src1 is not a |
| 415 // Constant. If it is, then we extend it here, and not during program | 414 // Constant. If it is, then we extend it here, and not during program |
| 416 // runtime. This allows preambleDivRem to optimize-out the div-by-0 | 415 // runtime. This allows preambleDivRem to optimize-out the div-by-0 |
| 417 // check. | 416 // check. |
| 418 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Src1)) { | 417 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Src1)) { |
| 419 const int32_t ShAmt = (DestTy == IceType_i16) ? 16 : 24; | 418 const int32_t ShAmt = (DestTy == IceType_i16) ? 16 : 24; |
| 420 int32_t NewC = C->getValue(); | 419 int32_t NewC = C->getValue(); |
| 421 if (CastKind == InstCast::Zext) { | 420 if (CastKind == InstCast::Zext) { |
| 422 NewC &= ~(0x80000000l >> ShAmt); | 421 NewC &= ~(0x80000000l >> ShAmt); |
| 423 } else { | 422 } else { |
| 424 NewC = (NewC << ShAmt) >> ShAmt; | 423 NewC = (NewC << ShAmt) >> ShAmt; |
| 425 } | 424 } |
| 426 Src1 = Ctx->getConstantInt32(NewC); | 425 Src1 = Ctx->getConstantInt32(NewC); |
| 427 } else { | 426 } else { |
| 428 Variable *Src1_32 = Func->makeVariable(IceType_i32); | 427 Variable *Src1_32 = Func->makeVariable(IceType_i32); |
| 429 Context.insert(InstCast::create(Func, CastKind, Src1_32, Src1)); | 428 Context.insert<InstCast>(CastKind, Src1_32, Src1); |
| 430 Src1 = Src1_32; | 429 Src1 = Src1_32; |
| 431 } | 430 } |
| 432 } | 431 } |
| 433 assert(TargetHelper != nullptr); | 432 assert(TargetHelper != nullptr); |
| 434 ARM32HelpersPreamble[TargetHelper] = &TargetARM32::preambleDivRem; | 433 ARM32HelpersPreamble[TargetHelper] = &TargetARM32::preambleDivRem; |
| 435 constexpr SizeT MaxArgs = 2; | 434 constexpr SizeT MaxArgs = 2; |
| 436 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper, | 435 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
| 437 NoTailCall, IsTargetHelperCall); | 436 NoTailCall, IsTargetHelperCall); |
| 438 assert(Src0->getType() == IceType_i32); | 437 assert(Src0->getType() == IceType_i32); |
| 439 Call->addArg(Src0); | 438 Call->addArg(Src0); |
| 440 assert(Src1->getType() == IceType_i32); | 439 assert(Src1->getType() == IceType_i32); |
| 441 Call->addArg(Src1); | 440 Call->addArg(Src1); |
| 442 Context.insert(Call); | |
| 443 Instr->setDeleted(); | 441 Instr->setDeleted(); |
| 444 return; | 442 return; |
| 445 } | 443 } |
| 446 case IceType_f64: | 444 case IceType_f64: |
| 447 case IceType_f32: { | 445 case IceType_f32: { |
| 448 if (Op != InstArithmetic::Frem) { | 446 if (Op != InstArithmetic::Frem) { |
| 449 return; | 447 return; |
| 450 } | 448 } |
| 451 constexpr SizeT MaxArgs = 2; | 449 constexpr SizeT MaxArgs = 2; |
| 452 Operand *TargetHelper = Ctx->getConstantExternSym( | 450 Operand *TargetHelper = Ctx->getConstantExternSym( |
| 453 DestTy == IceType_f32 ? H_frem_f32 : H_frem_f64); | 451 DestTy == IceType_f32 ? H_frem_f32 : H_frem_f64); |
| 454 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper, | 452 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
| 455 NoTailCall, IsTargetHelperCall); | 453 NoTailCall, IsTargetHelperCall); |
| 456 Call->addArg(Instr->getSrc(0)); | 454 Call->addArg(Instr->getSrc(0)); |
| 457 Call->addArg(Instr->getSrc(1)); | 455 Call->addArg(Instr->getSrc(1)); |
| 458 Context.insert(Call); | |
| 459 Instr->setDeleted(); | 456 Instr->setDeleted(); |
| 460 return; | 457 return; |
| 461 } | 458 } |
| 462 } | 459 } |
| 463 llvm::report_fatal_error("Control flow should never have reached here."); | 460 llvm::report_fatal_error("Control flow should never have reached here."); |
| 464 } | 461 } |
| 465 case Inst::Cast: { | 462 case Inst::Cast: { |
| 466 Variable *Dest = Instr->getDest(); | 463 Variable *Dest = Instr->getDest(); |
| 467 Operand *Src0 = Instr->getSrc(0); | 464 Operand *Src0 = Instr->getSrc(0); |
| 468 const Type DestTy = Dest->getType(); | 465 const Type DestTy = Dest->getType(); |
| 469 const InstCast::OpKind CastKind = | 466 const InstCast::OpKind CastKind = |
| 470 llvm::cast<InstCast>(Instr)->getCastKind(); | 467 llvm::cast<InstCast>(Instr)->getCastKind(); |
| 471 switch (CastKind) { | 468 switch (CastKind) { |
| 472 default: | 469 default: |
| 473 return; | 470 return; |
| 474 case InstCast::Fptosi: | 471 case InstCast::Fptosi: |
| 475 case InstCast::Fptoui: { | 472 case InstCast::Fptoui: { |
| 476 if (DestTy != IceType_i64) { | 473 if (DestTy != IceType_i64) { |
| 477 return; | 474 return; |
| 478 } | 475 } |
| 479 const bool DestIsSigned = CastKind == InstCast::Fptosi; | 476 const bool DestIsSigned = CastKind == InstCast::Fptosi; |
| 480 const bool Src0IsF32 = isFloat32Asserting32Or64(Src0->getType()); | 477 const bool Src0IsF32 = isFloat32Asserting32Or64(Src0->getType()); |
| 481 Operand *TargetHelper = Ctx->getConstantExternSym( | 478 Operand *TargetHelper = Ctx->getConstantExternSym( |
| 482 Src0IsF32 ? (DestIsSigned ? H_fptosi_f32_i64 : H_fptoui_f32_i64) | 479 Src0IsF32 ? (DestIsSigned ? H_fptosi_f32_i64 : H_fptoui_f32_i64) |
| 483 : (DestIsSigned ? H_fptosi_f64_i64 : H_fptoui_f64_i64)); | 480 : (DestIsSigned ? H_fptosi_f64_i64 : H_fptoui_f64_i64)); |
| 484 static constexpr SizeT MaxArgs = 1; | 481 static constexpr SizeT MaxArgs = 1; |
| 485 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper, | 482 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
| 486 NoTailCall, IsTargetHelperCall); | 483 NoTailCall, IsTargetHelperCall); |
| 487 Call->addArg(Src0); | 484 Call->addArg(Src0); |
| 488 Context.insert(Call); | |
| 489 Instr->setDeleted(); | 485 Instr->setDeleted(); |
| 490 return; | 486 return; |
| 491 } | 487 } |
| 492 case InstCast::Sitofp: | 488 case InstCast::Sitofp: |
| 493 case InstCast::Uitofp: { | 489 case InstCast::Uitofp: { |
| 494 if (Src0->getType() != IceType_i64) { | 490 if (Src0->getType() != IceType_i64) { |
| 495 return; | 491 return; |
| 496 } | 492 } |
| 497 const bool SourceIsSigned = CastKind == InstCast::Sitofp; | 493 const bool SourceIsSigned = CastKind == InstCast::Sitofp; |
| 498 const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType()); | 494 const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType()); |
| 499 Operand *TargetHelper = Ctx->getConstantExternSym( | 495 Operand *TargetHelper = Ctx->getConstantExternSym( |
| 500 DestIsF32 ? (SourceIsSigned ? H_sitofp_i64_f32 : H_uitofp_i64_f32) | 496 DestIsF32 ? (SourceIsSigned ? H_sitofp_i64_f32 : H_uitofp_i64_f32) |
| 501 : (SourceIsSigned ? H_sitofp_i64_f64 : H_uitofp_i64_f64)); | 497 : (SourceIsSigned ? H_sitofp_i64_f64 : H_uitofp_i64_f64)); |
| 502 static constexpr SizeT MaxArgs = 1; | 498 static constexpr SizeT MaxArgs = 1; |
| 503 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper, | 499 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
| 504 NoTailCall, IsTargetHelperCall); | 500 NoTailCall, IsTargetHelperCall); |
| 505 Call->addArg(Src0); | 501 Call->addArg(Src0); |
| 506 Context.insert(Call); | |
| 507 Instr->setDeleted(); | 502 Instr->setDeleted(); |
| 508 return; | 503 return; |
| 509 } | 504 } |
| 510 } | 505 } |
| 511 llvm::report_fatal_error("Control flow should never have reached here."); | 506 llvm::report_fatal_error("Control flow should never have reached here."); |
| 512 } | 507 } |
| 513 case Inst::IntrinsicCall: { | 508 case Inst::IntrinsicCall: { |
| 514 Variable *Dest = Instr->getDest(); | 509 Variable *Dest = Instr->getDest(); |
| 515 auto *IntrinsicCall = llvm::cast<InstIntrinsicCall>(Instr); | 510 auto *IntrinsicCall = llvm::cast<InstIntrinsicCall>(Instr); |
| 516 Intrinsics::IntrinsicID ID = IntrinsicCall->getIntrinsicInfo().ID; | 511 Intrinsics::IntrinsicID ID = IntrinsicCall->getIntrinsicInfo().ID; |
| 517 switch (ID) { | 512 switch (ID) { |
| 518 default: | 513 default: |
| 519 return; | 514 return; |
| 520 case Intrinsics::Ctpop: { | 515 case Intrinsics::Ctpop: { |
| 521 Operand *Src0 = IntrinsicCall->getArg(0); | 516 Operand *Src0 = IntrinsicCall->getArg(0); |
| 522 Operand *TargetHelper = Ctx->getConstantExternSym( | 517 Operand *TargetHelper = Ctx->getConstantExternSym( |
| 523 isInt32Asserting32Or64(Src0->getType()) ? H_call_ctpop_i32 | 518 isInt32Asserting32Or64(Src0->getType()) ? H_call_ctpop_i32 |
| 524 : H_call_ctpop_i64); | 519 : H_call_ctpop_i64); |
| 525 static constexpr SizeT MaxArgs = 1; | 520 static constexpr SizeT MaxArgs = 1; |
| 526 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper, | 521 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
| 527 NoTailCall, IsTargetHelperCall); | 522 NoTailCall, IsTargetHelperCall); |
| 528 Call->addArg(Src0); | 523 Call->addArg(Src0); |
| 529 Context.insert(Call); | |
| 530 Instr->setDeleted(); | 524 Instr->setDeleted(); |
| 531 if (Src0->getType() == IceType_i64) { | 525 if (Src0->getType() == IceType_i64) { |
| 532 ARM32HelpersPostamble[TargetHelper] = &TargetARM32::postambleCtpop64; | 526 ARM32HelpersPostamble[TargetHelper] = &TargetARM32::postambleCtpop64; |
| 533 } | 527 } |
| 534 return; | 528 return; |
| 535 } | 529 } |
| 536 case Intrinsics::Longjmp: { | 530 case Intrinsics::Longjmp: { |
| 537 static constexpr SizeT MaxArgs = 2; | 531 static constexpr SizeT MaxArgs = 2; |
| 538 static constexpr Variable *NoDest = nullptr; | 532 static constexpr Variable *NoDest = nullptr; |
| 539 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_longjmp); | 533 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_longjmp); |
| 540 auto *Call = InstCall::create(Func, MaxArgs, NoDest, TargetHelper, | 534 auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper, |
| 541 NoTailCall, IsTargetHelperCall); | 535 NoTailCall, IsTargetHelperCall); |
| 542 Call->addArg(IntrinsicCall->getArg(0)); | 536 Call->addArg(IntrinsicCall->getArg(0)); |
| 543 Call->addArg(IntrinsicCall->getArg(1)); | 537 Call->addArg(IntrinsicCall->getArg(1)); |
| 544 Context.insert(Call); | |
| 545 Instr->setDeleted(); | 538 Instr->setDeleted(); |
| 546 return; | 539 return; |
| 547 } | 540 } |
| 548 case Intrinsics::Memcpy: { | 541 case Intrinsics::Memcpy: { |
| 549 // In the future, we could potentially emit an inline memcpy/memset, etc. | 542 // In the future, we could potentially emit an inline memcpy/memset, etc. |
| 550 // for intrinsic calls w/ a known length. | 543 // for intrinsic calls w/ a known length. |
| 551 static constexpr SizeT MaxArgs = 3; | 544 static constexpr SizeT MaxArgs = 3; |
| 552 static constexpr Variable *NoDest = nullptr; | 545 static constexpr Variable *NoDest = nullptr; |
| 553 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memcpy); | 546 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memcpy); |
| 554 auto *Call = InstCall::create(Func, MaxArgs, NoDest, TargetHelper, | 547 auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper, |
| 555 NoTailCall, IsTargetHelperCall); | 548 NoTailCall, IsTargetHelperCall); |
| 556 Call->addArg(IntrinsicCall->getArg(0)); | 549 Call->addArg(IntrinsicCall->getArg(0)); |
| 557 Call->addArg(IntrinsicCall->getArg(1)); | 550 Call->addArg(IntrinsicCall->getArg(1)); |
| 558 Call->addArg(IntrinsicCall->getArg(2)); | 551 Call->addArg(IntrinsicCall->getArg(2)); |
| 559 Context.insert(Call); | |
| 560 Instr->setDeleted(); | 552 Instr->setDeleted(); |
| 561 return; | 553 return; |
| 562 } | 554 } |
| 563 case Intrinsics::Memmove: { | 555 case Intrinsics::Memmove: { |
| 564 static constexpr SizeT MaxArgs = 3; | 556 static constexpr SizeT MaxArgs = 3; |
| 565 static constexpr Variable *NoDest = nullptr; | 557 static constexpr Variable *NoDest = nullptr; |
| 566 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memmove); | 558 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memmove); |
| 567 auto *Call = InstCall::create(Func, MaxArgs, NoDest, TargetHelper, | 559 auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper, |
| 568 NoTailCall, IsTargetHelperCall); | 560 NoTailCall, IsTargetHelperCall); |
| 569 Call->addArg(IntrinsicCall->getArg(0)); | 561 Call->addArg(IntrinsicCall->getArg(0)); |
| 570 Call->addArg(IntrinsicCall->getArg(1)); | 562 Call->addArg(IntrinsicCall->getArg(1)); |
| 571 Call->addArg(IntrinsicCall->getArg(2)); | 563 Call->addArg(IntrinsicCall->getArg(2)); |
| 572 Context.insert(Call); | |
| 573 Instr->setDeleted(); | 564 Instr->setDeleted(); |
| 574 return; | 565 return; |
| 575 } | 566 } |
| 576 case Intrinsics::Memset: { | 567 case Intrinsics::Memset: { |
| 577 // The value operand needs to be extended to a stack slot size because the | 568 // The value operand needs to be extended to a stack slot size because the |
| 578 // PNaCl ABI requires arguments to be at least 32 bits wide. | 569 // PNaCl ABI requires arguments to be at least 32 bits wide. |
| 579 Operand *ValOp = IntrinsicCall->getArg(1); | 570 Operand *ValOp = IntrinsicCall->getArg(1); |
| 580 assert(ValOp->getType() == IceType_i8); | 571 assert(ValOp->getType() == IceType_i8); |
| 581 Variable *ValExt = Func->makeVariable(stackSlotType()); | 572 Variable *ValExt = Func->makeVariable(stackSlotType()); |
| 582 Context.insert(InstCast::create(Func, InstCast::Zext, ValExt, ValOp)); | 573 Context.insert<InstCast>(InstCast::Zext, ValExt, ValOp); |
| 583 | 574 |
| 584 // Technically, ARM has its own __aeabi_memset, but we can use plain | 575 // Technically, ARM has its own __aeabi_memset, but we can use plain |
| 585 // memset too. The value and size argument need to be flipped if we ever | 576 // memset too. The value and size argument need to be flipped if we ever |
| 586 // decide to use __aeabi_memset. | 577 // decide to use __aeabi_memset. |
| 587 static constexpr SizeT MaxArgs = 3; | 578 static constexpr SizeT MaxArgs = 3; |
| 588 static constexpr Variable *NoDest = nullptr; | 579 static constexpr Variable *NoDest = nullptr; |
| 589 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memset); | 580 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memset); |
| 590 auto *Call = InstCall::create(Func, MaxArgs, NoDest, TargetHelper, | 581 auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper, |
| 591 NoTailCall, IsTargetHelperCall); | 582 NoTailCall, IsTargetHelperCall); |
| 592 Call->addArg(IntrinsicCall->getArg(0)); | 583 Call->addArg(IntrinsicCall->getArg(0)); |
| 593 Call->addArg(ValExt); | 584 Call->addArg(ValExt); |
| 594 Call->addArg(IntrinsicCall->getArg(2)); | 585 Call->addArg(IntrinsicCall->getArg(2)); |
| 595 Context.insert(Call); | |
| 596 Instr->setDeleted(); | 586 Instr->setDeleted(); |
| 597 return; | 587 return; |
| 598 } | 588 } |
| 599 case Intrinsics::NaClReadTP: { | 589 case Intrinsics::NaClReadTP: { |
| 600 if (NeedSandboxing) { | 590 if (NeedSandboxing) { |
| 601 return; | 591 return; |
| 602 } | 592 } |
| 603 static constexpr SizeT MaxArgs = 0; | 593 static constexpr SizeT MaxArgs = 0; |
| 604 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_read_tp); | 594 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_read_tp); |
| 605 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper, | 595 Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, NoTailCall, |
| 606 NoTailCall, IsTargetHelperCall); | 596 IsTargetHelperCall); |
| 607 Context.insert(Call); | |
| 608 Instr->setDeleted(); | 597 Instr->setDeleted(); |
| 609 return; | 598 return; |
| 610 } | 599 } |
| 611 case Intrinsics::Setjmp: { | 600 case Intrinsics::Setjmp: { |
| 612 static constexpr SizeT MaxArgs = 1; | 601 static constexpr SizeT MaxArgs = 1; |
| 613 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_setjmp); | 602 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_setjmp); |
| 614 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper, | 603 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
| 615 NoTailCall, IsTargetHelperCall); | 604 NoTailCall, IsTargetHelperCall); |
| 616 Call->addArg(IntrinsicCall->getArg(0)); | 605 Call->addArg(IntrinsicCall->getArg(0)); |
| 617 Context.insert(Call); | |
| 618 Instr->setDeleted(); | 606 Instr->setDeleted(); |
| 619 return; | 607 return; |
| 620 } | 608 } |
| 621 } | 609 } |
| 622 llvm::report_fatal_error("Control flow should never have reached here."); | 610 llvm::report_fatal_error("Control flow should never have reached here."); |
| 623 } | 611 } |
| 624 } | 612 } |
| 625 } | 613 } |
| 626 | 614 |
| 627 void TargetARM32::findMaxStackOutArgsSize() { | 615 void TargetARM32::findMaxStackOutArgsSize() { |
| (...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1023 default: { RegisterArg->setRegNum(RegNum); } break; | 1011 default: { RegisterArg->setRegNum(RegNum); } break; |
| 1024 case IceType_i64: { | 1012 case IceType_i64: { |
| 1025 auto *RegisterArg64 = llvm::cast<Variable64On32>(RegisterArg); | 1013 auto *RegisterArg64 = llvm::cast<Variable64On32>(RegisterArg); |
| 1026 RegisterArg64->initHiLo(Func); | 1014 RegisterArg64->initHiLo(Func); |
| 1027 RegisterArg64->getLo()->setRegNum( | 1015 RegisterArg64->getLo()->setRegNum( |
| 1028 RegARM32::getI64PairFirstGPRNum(RegNum)); | 1016 RegARM32::getI64PairFirstGPRNum(RegNum)); |
| 1029 RegisterArg64->getHi()->setRegNum( | 1017 RegisterArg64->getHi()->setRegNum( |
| 1030 RegARM32::getI64PairSecondGPRNum(RegNum)); | 1018 RegARM32::getI64PairSecondGPRNum(RegNum)); |
| 1031 } break; | 1019 } break; |
| 1032 } | 1020 } |
| 1033 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); | 1021 Context.insert<InstAssign>(Arg, RegisterArg); |
| 1034 } | 1022 } |
| 1035 } | 1023 } |
| 1036 | 1024 |
| 1037 // Helper function for addProlog(). | 1025 // Helper function for addProlog(). |
| 1038 // | 1026 // |
| 1039 // This assumes Arg is an argument passed on the stack. This sets the frame | 1027 // This assumes Arg is an argument passed on the stack. This sets the frame |
| 1040 // offset for Arg and updates InArgsSizeBytes according to Arg's width. For an | 1028 // offset for Arg and updates InArgsSizeBytes according to Arg's width. For an |
| 1041 // I64 arg that has been split into Lo and Hi components, it calls itself | 1029 // I64 arg that has been split into Lo and Hi components, it calls itself |
| 1042 // recursively on the components, taking care to handle Lo first because of the | 1030 // recursively on the components, taking care to handle Lo first because of the |
| 1043 // little-endian architecture. Lastly, this function generates an instruction | 1031 // little-endian architecture. Lastly, this function generates an instruction |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1224 _push(PreservedSRegs); | 1212 _push(PreservedSRegs); |
| 1225 if (!PreservedGPRs.empty()) | 1213 if (!PreservedGPRs.empty()) |
| 1226 _push(PreservedGPRs); | 1214 _push(PreservedGPRs); |
| 1227 | 1215 |
| 1228 // Generate "mov FP, SP" if needed. | 1216 // Generate "mov FP, SP" if needed. |
| 1229 if (UsesFramePointer) { | 1217 if (UsesFramePointer) { |
| 1230 Variable *FP = getPhysicalRegister(RegARM32::Reg_fp); | 1218 Variable *FP = getPhysicalRegister(RegARM32::Reg_fp); |
| 1231 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 1219 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| 1232 _mov(FP, SP); | 1220 _mov(FP, SP); |
| 1233 // Keep FP live for late-stage liveness analysis (e.g. asm-verbose mode). | 1221 // Keep FP live for late-stage liveness analysis (e.g. asm-verbose mode). |
| 1234 Context.insert(InstFakeUse::create(Func, FP)); | 1222 Context.insert<InstFakeUse>(FP); |
| 1235 } | 1223 } |
| 1236 | 1224 |
| 1237 // Align the variables area. SpillAreaPaddingBytes is the size of the region | 1225 // Align the variables area. SpillAreaPaddingBytes is the size of the region |
| 1238 // after the preserved registers and before the spill areas. | 1226 // after the preserved registers and before the spill areas. |
| 1239 // LocalsSlotsPaddingBytes is the amount of padding between the globals and | 1227 // LocalsSlotsPaddingBytes is the amount of padding between the globals and |
| 1240 // locals area if they are separate. | 1228 // locals area if they are separate. |
| 1241 assert(SpillAreaAlignmentBytes <= ARM32_STACK_ALIGNMENT_BYTES); | 1229 assert(SpillAreaAlignmentBytes <= ARM32_STACK_ALIGNMENT_BYTES); |
| 1242 assert(LocalsSlotsAlignmentBytes <= SpillAreaAlignmentBytes); | 1230 assert(LocalsSlotsAlignmentBytes <= SpillAreaAlignmentBytes); |
| 1243 uint32_t SpillAreaPaddingBytes = 0; | 1231 uint32_t SpillAreaPaddingBytes = 0; |
| 1244 uint32_t LocalsSlotsPaddingBytes = 0; | 1232 uint32_t LocalsSlotsPaddingBytes = 0; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1353 --InsertPoint; | 1341 --InsertPoint; |
| 1354 Context.init(Node); | 1342 Context.init(Node); |
| 1355 Context.setInsertPoint(InsertPoint); | 1343 Context.setInsertPoint(InsertPoint); |
| 1356 | 1344 |
| 1357 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 1345 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| 1358 if (UsesFramePointer) { | 1346 if (UsesFramePointer) { |
| 1359 Variable *FP = getPhysicalRegister(RegARM32::Reg_fp); | 1347 Variable *FP = getPhysicalRegister(RegARM32::Reg_fp); |
| 1360 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake | 1348 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake |
| 1361 // use of SP before the assignment of SP=FP keeps previous SP adjustments | 1349 // use of SP before the assignment of SP=FP keeps previous SP adjustments |
| 1362 // from being dead-code eliminated. | 1350 // from being dead-code eliminated. |
| 1363 Context.insert(InstFakeUse::create(Func, SP)); | 1351 Context.insert<InstFakeUse>(SP); |
| 1364 Sandboxer(this).reset_sp(FP); | 1352 Sandboxer(this).reset_sp(FP); |
| 1365 } else { | 1353 } else { |
| 1366 // add SP, SpillAreaSizeBytes | 1354 // add SP, SpillAreaSizeBytes |
| 1367 if (SpillAreaSizeBytes) { | 1355 if (SpillAreaSizeBytes) { |
| 1368 // Use the scratch register if needed to legalize the immediate. | 1356 // Use the scratch register if needed to legalize the immediate. |
| 1369 Operand *AddAmount = | 1357 Operand *AddAmount = |
| 1370 legalize(Ctx->getConstantInt32(SpillAreaSizeBytes), | 1358 legalize(Ctx->getConstantInt32(SpillAreaSizeBytes), |
| 1371 Legal_Reg | Legal_Flex, getReservedTmpReg()); | 1359 Legal_Reg | Legal_Flex, getReservedTmpReg()); |
| 1372 Sandboxer(this).add_sp(AddAmount); | 1360 Sandboxer(this).add_sp(AddAmount); |
| 1373 } | 1361 } |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1517 if (!Dest->hasReg()) { | 1505 if (!Dest->hasReg()) { |
| 1518 auto *SrcR = llvm::cast<Variable>(Src); | 1506 auto *SrcR = llvm::cast<Variable>(Src); |
| 1519 assert(SrcR->hasReg()); | 1507 assert(SrcR->hasReg()); |
| 1520 assert(!SrcR->isRematerializable()); | 1508 assert(!SrcR->isRematerializable()); |
| 1521 const int32_t Offset = Dest->getStackOffset(); | 1509 const int32_t Offset = Dest->getStackOffset(); |
| 1522 // This is a _mov(Mem(), Variable), i.e., a store. | 1510 // This is a _mov(Mem(), Variable), i.e., a store. |
| 1523 TargetARM32::Sandboxer(Target) | 1511 TargetARM32::Sandboxer(Target) |
| 1524 .str(SrcR, createMemOperand(DestTy, StackOrFrameReg, Offset), | 1512 .str(SrcR, createMemOperand(DestTy, StackOrFrameReg, Offset), |
| 1525 MovInstr->getPredicate()); | 1513 MovInstr->getPredicate()); |
| 1526 // _str() does not have a Dest, so we add a fake-def(Dest). | 1514 // _str() does not have a Dest, so we add a fake-def(Dest). |
| 1527 Target->Context.insert(InstFakeDef::create(Target->Func, Dest)); | 1515 Target->Context.insert<InstFakeDef>(Dest); |
| 1528 Legalized = true; | 1516 Legalized = true; |
| 1529 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { | 1517 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { |
| 1530 if (Var->isRematerializable()) { | 1518 if (Var->isRematerializable()) { |
| 1531 // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable). | 1519 // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable). |
| 1532 | 1520 |
| 1533 // ExtraOffset is only needed for frame-pointer based frames as we have | 1521 // ExtraOffset is only needed for frame-pointer based frames as we have |
| 1534 // to account for spill storage. | 1522 // to account for spill storage. |
| 1535 const int32_t ExtraOffset = | 1523 const int32_t ExtraOffset = |
| 1536 (static_cast<SizeT>(Var->getRegNum()) == Target->getFrameReg()) | 1524 (static_cast<SizeT>(Var->getRegNum()) == Target->getFrameReg()) |
| 1537 ? Target->getFrameFixedAllocaOffset() | 1525 ? Target->getFrameFixedAllocaOffset() |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1892 llvm::dyn_cast<ConstantInteger32>(TotalSize)) { | 1880 llvm::dyn_cast<ConstantInteger32>(TotalSize)) { |
| 1893 const uint32_t Value = | 1881 const uint32_t Value = |
| 1894 Utils::applyAlignment(ConstantTotalSize->getValue(), Alignment); | 1882 Utils::applyAlignment(ConstantTotalSize->getValue(), Alignment); |
| 1895 // Constant size alloca. | 1883 // Constant size alloca. |
| 1896 if (!UseFramePointer) { | 1884 if (!UseFramePointer) { |
| 1897 // If we don't need a Frame Pointer, this alloca has a known offset to the | 1885 // If we don't need a Frame Pointer, this alloca has a known offset to the |
| 1898 // stack pointer. We don't need adjust the stack pointer, nor assign any | 1886 // stack pointer. We don't need adjust the stack pointer, nor assign any |
| 1899 // value to Dest, as Dest is rematerializable. | 1887 // value to Dest, as Dest is rematerializable. |
| 1900 assert(Dest->isRematerializable()); | 1888 assert(Dest->isRematerializable()); |
| 1901 FixedAllocaSizeBytes += Value; | 1889 FixedAllocaSizeBytes += Value; |
| 1902 Context.insert(InstFakeDef::create(Func, Dest)); | 1890 Context.insert<InstFakeDef>(Dest); |
| 1903 return; | 1891 return; |
| 1904 } | 1892 } |
| 1905 | 1893 |
| 1906 // If a frame pointer is required, then we need to store the alloca'd result | 1894 // If a frame pointer is required, then we need to store the alloca'd result |
| 1907 // in Dest. | 1895 // in Dest. |
| 1908 Operand *SubAmountRF = | 1896 Operand *SubAmountRF = |
| 1909 legalize(Ctx->getConstantInt32(Value), Legal_Reg | Legal_Flex); | 1897 legalize(Ctx->getConstantInt32(Value), Legal_Reg | Legal_Flex); |
| 1910 Sandboxer(this).sub_sp(SubAmountRF); | 1898 Sandboxer(this).sub_sp(SubAmountRF); |
| 1911 } else { | 1899 } else { |
| 1912 // Non-constant sizes need to be adjusted to the next highest multiple of | 1900 // Non-constant sizes need to be adjusted to the next highest multiple of |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1937 return; | 1925 return; |
| 1938 Variable *SrcLoReg = legalizeToReg(SrcLo); | 1926 Variable *SrcLoReg = legalizeToReg(SrcLo); |
| 1939 switch (Ty) { | 1927 switch (Ty) { |
| 1940 default: | 1928 default: |
| 1941 llvm::report_fatal_error("Unexpected type"); | 1929 llvm::report_fatal_error("Unexpected type"); |
| 1942 case IceType_i8: | 1930 case IceType_i8: |
| 1943 case IceType_i16: { | 1931 case IceType_i16: { |
| 1944 Operand *ShAmtImm = shAmtImm(32 - getScalarIntBitWidth(Ty)); | 1932 Operand *ShAmtImm = shAmtImm(32 - getScalarIntBitWidth(Ty)); |
| 1945 Variable *T = makeReg(IceType_i32); | 1933 Variable *T = makeReg(IceType_i32); |
| 1946 _lsls(T, SrcLoReg, ShAmtImm); | 1934 _lsls(T, SrcLoReg, ShAmtImm); |
| 1947 Context.insert(InstFakeUse::create(Func, T)); | 1935 Context.insert<InstFakeUse>(T); |
| 1948 } break; | 1936 } break; |
| 1949 case IceType_i32: { | 1937 case IceType_i32: { |
| 1950 _tst(SrcLoReg, SrcLoReg); | 1938 _tst(SrcLoReg, SrcLoReg); |
| 1951 break; | 1939 break; |
| 1952 } | 1940 } |
| 1953 case IceType_i64: { | 1941 case IceType_i64: { |
| 1954 Variable *T = makeReg(IceType_i32); | 1942 Variable *T = makeReg(IceType_i32); |
| 1955 _orrs(T, SrcLoReg, legalize(SrcHi, Legal_Reg | Legal_Flex)); | 1943 _orrs(T, SrcLoReg, legalize(SrcHi, Legal_Reg | Legal_Flex)); |
| 1956 // T isn't going to be used, but we need the side-effect of setting flags | 1944 // T isn't going to be used, but we need the side-effect of setting flags |
| 1957 // from this operation. | 1945 // from this operation. |
| 1958 Context.insert(InstFakeUse::create(Func, T)); | 1946 Context.insert<InstFakeUse>(T); |
| 1959 } | 1947 } |
| 1960 } | 1948 } |
| 1961 auto *Label = InstARM32Label::create(Func, this); | 1949 auto *Label = InstARM32Label::create(Func, this); |
| 1962 _br(Label, CondARM32::NE); | 1950 _br(Label, CondARM32::NE); |
| 1963 _trap(); | 1951 _trap(); |
| 1964 Context.insert(Label); | 1952 Context.insert(Label); |
| 1965 } | 1953 } |
| 1966 | 1954 |
| 1967 void TargetARM32::lowerIDivRem(Variable *Dest, Variable *T, Variable *Src0R, | 1955 void TargetARM32::lowerIDivRem(Variable *Dest, Variable *T, Variable *Src0R, |
| 1968 Operand *Src1, ExtInstr ExtFunc, | 1956 Operand *Src1, ExtInstr ExtFunc, |
| (...skipping 735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2704 | 2692 |
| 2705 return Src == 0; | 2693 return Src == 0; |
| 2706 } | 2694 } |
| 2707 } // end of namespace StrengthReduction | 2695 } // end of namespace StrengthReduction |
| 2708 } // end of anonymous namespace | 2696 } // end of anonymous namespace |
| 2709 | 2697 |
| 2710 void TargetARM32::lowerArithmetic(const InstArithmetic *Instr) { | 2698 void TargetARM32::lowerArithmetic(const InstArithmetic *Instr) { |
| 2711 Variable *Dest = Instr->getDest(); | 2699 Variable *Dest = Instr->getDest(); |
| 2712 | 2700 |
| 2713 if (Dest->isRematerializable()) { | 2701 if (Dest->isRematerializable()) { |
| 2714 Context.insert(InstFakeDef::create(Func, Dest)); | 2702 Context.insert<InstFakeDef>(Dest); |
| 2715 return; | 2703 return; |
| 2716 } | 2704 } |
| 2717 | 2705 |
| 2718 Type DestTy = Dest->getType(); | 2706 Type DestTy = Dest->getType(); |
| 2719 if (DestTy == IceType_i1) { | 2707 if (DestTy == IceType_i1) { |
| 2720 lowerInt1Arithmetic(Instr); | 2708 lowerInt1Arithmetic(Instr); |
| 2721 return; | 2709 return; |
| 2722 } | 2710 } |
| 2723 | 2711 |
| 2724 Operand *Src0 = legalizeUndef(Instr->getSrc(0)); | 2712 Operand *Src0 = legalizeUndef(Instr->getSrc(0)); |
| 2725 Operand *Src1 = legalizeUndef(Instr->getSrc(1)); | 2713 Operand *Src1 = legalizeUndef(Instr->getSrc(1)); |
| 2726 if (DestTy == IceType_i64) { | 2714 if (DestTy == IceType_i64) { |
| 2727 lowerInt64Arithmetic(Instr->getOp(), Instr->getDest(), Src0, Src1); | 2715 lowerInt64Arithmetic(Instr->getOp(), Instr->getDest(), Src0, Src1); |
| 2728 return; | 2716 return; |
| 2729 } | 2717 } |
| 2730 | 2718 |
| 2731 if (isVectorType(DestTy)) { | 2719 if (isVectorType(DestTy)) { |
| 2732 // Add a fake def to keep liveness consistent in the meantime. | 2720 // Add a fake def to keep liveness consistent in the meantime. |
| 2733 Variable *T = makeReg(DestTy); | 2721 Variable *T = makeReg(DestTy); |
| 2734 Context.insert(InstFakeDef::create(Func, T)); | 2722 Context.insert<InstFakeDef>(T); |
| 2735 _mov(Dest, T); | 2723 _mov(Dest, T); |
| 2736 UnimplementedError(Func->getContext()->getFlags()); | 2724 UnimplementedError(Func->getContext()->getFlags()); |
| 2737 return; | 2725 return; |
| 2738 } | 2726 } |
| 2739 | 2727 |
| 2740 // DestTy is a non-i64 scalar. | 2728 // DestTy is a non-i64 scalar. |
| 2741 Variable *T = makeReg(DestTy); | 2729 Variable *T = makeReg(DestTy); |
| 2742 | 2730 |
| 2743 // * Handle div/rem separately. They require a non-legalized Src1 to inspect | 2731 // * Handle div/rem separately. They require a non-legalized Src1 to inspect |
| 2744 // whether or not Src1 is a non-zero constant. Once legalized it is more | 2732 // whether or not Src1 is a non-zero constant. Once legalized it is more |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3056 llvm::report_fatal_error( | 3044 llvm::report_fatal_error( |
| 3057 "Floating point arith should have been handled earlier."); | 3045 "Floating point arith should have been handled earlier."); |
| 3058 return; | 3046 return; |
| 3059 } | 3047 } |
| 3060 } | 3048 } |
| 3061 | 3049 |
| 3062 void TargetARM32::lowerAssign(const InstAssign *Inst) { | 3050 void TargetARM32::lowerAssign(const InstAssign *Inst) { |
| 3063 Variable *Dest = Inst->getDest(); | 3051 Variable *Dest = Inst->getDest(); |
| 3064 | 3052 |
| 3065 if (Dest->isRematerializable()) { | 3053 if (Dest->isRematerializable()) { |
| 3066 Context.insert(InstFakeDef::create(Func, Dest)); | 3054 Context.insert<InstFakeDef>(Dest); |
| 3067 return; | 3055 return; |
| 3068 } | 3056 } |
| 3069 | 3057 |
| 3070 Operand *Src0 = Inst->getSrc(0); | 3058 Operand *Src0 = Inst->getSrc(0); |
| 3071 assert(Dest->getType() == Src0->getType()); | 3059 assert(Dest->getType() == Src0->getType()); |
| 3072 if (Dest->getType() == IceType_i64) { | 3060 if (Dest->getType() == IceType_i64) { |
| 3073 Src0 = legalizeUndef(Src0); | 3061 Src0 = legalizeUndef(Src0); |
| 3074 | 3062 |
| 3075 Variable *T_Lo = makeReg(IceType_i32); | 3063 Variable *T_Lo = makeReg(IceType_i32); |
| 3076 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 3064 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3360 // Allow ConstantRelocatable to be left alone as a direct call, but force | 3348 // Allow ConstantRelocatable to be left alone as a direct call, but force |
| 3361 // other constants like ConstantInteger32 to be in a register and make it an | 3349 // other constants like ConstantInteger32 to be in a register and make it an |
| 3362 // indirect call. | 3350 // indirect call. |
| 3363 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { | 3351 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { |
| 3364 CallTarget = legalize(CallTarget, Legal_Reg); | 3352 CallTarget = legalize(CallTarget, Legal_Reg); |
| 3365 } | 3353 } |
| 3366 | 3354 |
| 3367 // Copy arguments to be passed in registers to the appropriate registers. | 3355 // Copy arguments to be passed in registers to the appropriate registers. |
| 3368 for (auto &FPArg : FPArgs) { | 3356 for (auto &FPArg : FPArgs) { |
| 3369 Variable *Reg = legalizeToReg(FPArg.first, FPArg.second); | 3357 Variable *Reg = legalizeToReg(FPArg.first, FPArg.second); |
| 3370 Context.insert(InstFakeUse::create(Func, Reg)); | 3358 Context.insert<InstFakeUse>(Reg); |
| 3371 } | 3359 } |
| 3372 for (auto &GPRArg : GPRArgs) { | 3360 for (auto &GPRArg : GPRArgs) { |
| 3373 Variable *Reg = legalizeToReg(GPRArg.first, GPRArg.second); | 3361 Variable *Reg = legalizeToReg(GPRArg.first, GPRArg.second); |
| 3374 // Generate a FakeUse of register arguments so that they do not get dead | 3362 // Generate a FakeUse of register arguments so that they do not get dead |
| 3375 // code eliminated as a result of the FakeKill of scratch registers after | 3363 // code eliminated as a result of the FakeKill of scratch registers after |
| 3376 // the call. | 3364 // the call. |
| 3377 Context.insert(InstFakeUse::create(Func, Reg)); | 3365 Context.insert<InstFakeUse>(Reg); |
| 3378 } | 3366 } |
| 3379 | 3367 |
| 3380 InstARM32Call *NewCall = | 3368 InstARM32Call *NewCall = |
| 3381 Sandboxer(this, InstBundleLock::Opt_AlignToEnd).bl(ReturnReg, CallTarget); | 3369 Sandboxer(this, InstBundleLock::Opt_AlignToEnd).bl(ReturnReg, CallTarget); |
| 3382 | 3370 |
| 3383 if (ReturnRegHi) | 3371 if (ReturnRegHi) |
| 3384 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); | 3372 Context.insert<InstFakeDef>(ReturnRegHi); |
| 3385 | 3373 |
| 3386 // Insert a register-kill pseudo instruction. | 3374 // Insert a register-kill pseudo instruction. |
| 3387 Context.insert(InstFakeKill::create(Func, NewCall)); | 3375 Context.insert<InstFakeKill>(NewCall); |
| 3388 | 3376 |
| 3389 // Generate a FakeUse to keep the call live if necessary. | 3377 // Generate a FakeUse to keep the call live if necessary. |
| 3390 if (Instr->hasSideEffects() && ReturnReg) { | 3378 if (Instr->hasSideEffects() && ReturnReg) { |
| 3391 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); | 3379 Context.insert<InstFakeUse>(ReturnReg); |
| 3392 Context.insert(FakeUse); | |
| 3393 } | 3380 } |
| 3394 | 3381 |
| 3395 if (Dest != nullptr) { | 3382 if (Dest != nullptr) { |
| 3396 // Assign the result of the call to Dest. | 3383 // Assign the result of the call to Dest. |
| 3397 if (ReturnReg != nullptr) { | 3384 if (ReturnReg != nullptr) { |
| 3398 if (ReturnRegHi) { | 3385 if (ReturnRegHi) { |
| 3399 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); | 3386 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); |
| 3400 Variable *DestLo = Dest64On32->getLo(); | 3387 Variable *DestLo = Dest64On32->getLo(); |
| 3401 Variable *DestHi = Dest64On32->getHi(); | 3388 Variable *DestHi = Dest64On32->getHi(); |
| 3402 _mov(DestLo, ReturnReg); | 3389 _mov(DestLo, ReturnReg); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 3433 InstCast::OpKind CastKind = Inst->getCastKind(); | 3420 InstCast::OpKind CastKind = Inst->getCastKind(); |
| 3434 Variable *Dest = Inst->getDest(); | 3421 Variable *Dest = Inst->getDest(); |
| 3435 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); | 3422 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
| 3436 switch (CastKind) { | 3423 switch (CastKind) { |
| 3437 default: | 3424 default: |
| 3438 Func->setError("Cast type not supported"); | 3425 Func->setError("Cast type not supported"); |
| 3439 return; | 3426 return; |
| 3440 case InstCast::Sext: { | 3427 case InstCast::Sext: { |
| 3441 if (isVectorType(Dest->getType())) { | 3428 if (isVectorType(Dest->getType())) { |
| 3442 Variable *T = makeReg(Dest->getType()); | 3429 Variable *T = makeReg(Dest->getType()); |
| 3443 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | 3430 Context.insert<InstFakeDef>(T, legalizeToReg(Src0)); |
| 3444 _mov(Dest, T); | 3431 _mov(Dest, T); |
| 3445 UnimplementedError(Func->getContext()->getFlags()); | 3432 UnimplementedError(Func->getContext()->getFlags()); |
| 3446 } else if (Dest->getType() == IceType_i64) { | 3433 } else if (Dest->getType() == IceType_i64) { |
| 3447 // t1=sxtb src; t2= mov t1 asr #31; dst.lo=t1; dst.hi=t2 | 3434 // t1=sxtb src; t2= mov t1 asr #31; dst.lo=t1; dst.hi=t2 |
| 3448 Constant *ShiftAmt = Ctx->getConstantInt32(31); | 3435 Constant *ShiftAmt = Ctx->getConstantInt32(31); |
| 3449 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 3436 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 3450 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 3437 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 3451 Variable *T_Lo = makeReg(DestLo->getType()); | 3438 Variable *T_Lo = makeReg(DestLo->getType()); |
| 3452 if (Src0->getType() == IceType_i32) { | 3439 if (Src0->getType() == IceType_i32) { |
| 3453 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); | 3440 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3481 Operand *_m1 = Ctx->getConstantInt(Dest->getType(), -1); | 3468 Operand *_m1 = Ctx->getConstantInt(Dest->getType(), -1); |
| 3482 Variable *T = makeReg(Dest->getType()); | 3469 Variable *T = makeReg(Dest->getType()); |
| 3483 lowerInt1ForSelect(T, Src0, _m1, _0); | 3470 lowerInt1ForSelect(T, Src0, _m1, _0); |
| 3484 _mov(Dest, T); | 3471 _mov(Dest, T); |
| 3485 } | 3472 } |
| 3486 break; | 3473 break; |
| 3487 } | 3474 } |
| 3488 case InstCast::Zext: { | 3475 case InstCast::Zext: { |
| 3489 if (isVectorType(Dest->getType())) { | 3476 if (isVectorType(Dest->getType())) { |
| 3490 Variable *T = makeReg(Dest->getType()); | 3477 Variable *T = makeReg(Dest->getType()); |
| 3491 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | 3478 Context.insert<InstFakeDef>(T, legalizeToReg(Src0)); |
| 3492 _mov(Dest, T); | 3479 _mov(Dest, T); |
| 3493 UnimplementedError(Func->getContext()->getFlags()); | 3480 UnimplementedError(Func->getContext()->getFlags()); |
| 3494 } else if (Dest->getType() == IceType_i64) { | 3481 } else if (Dest->getType() == IceType_i64) { |
| 3495 // t1=uxtb src; dst.lo=t1; dst.hi=0 | 3482 // t1=uxtb src; dst.lo=t1; dst.hi=0 |
| 3496 Operand *_0 = | 3483 Operand *_0 = |
| 3497 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); | 3484 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); |
| 3498 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 3485 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 3499 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 3486 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 3500 Variable *T_Lo = makeReg(DestLo->getType()); | 3487 Variable *T_Lo = makeReg(DestLo->getType()); |
| 3501 | 3488 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3537 Variable *Src0R = legalizeToReg(Src0); | 3524 Variable *Src0R = legalizeToReg(Src0); |
| 3538 Variable *T = makeReg(Dest->getType()); | 3525 Variable *T = makeReg(Dest->getType()); |
| 3539 _uxt(T, Src0R); | 3526 _uxt(T, Src0R); |
| 3540 _mov(Dest, T); | 3527 _mov(Dest, T); |
| 3541 } | 3528 } |
| 3542 break; | 3529 break; |
| 3543 } | 3530 } |
| 3544 case InstCast::Trunc: { | 3531 case InstCast::Trunc: { |
| 3545 if (isVectorType(Dest->getType())) { | 3532 if (isVectorType(Dest->getType())) { |
| 3546 Variable *T = makeReg(Dest->getType()); | 3533 Variable *T = makeReg(Dest->getType()); |
| 3547 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | 3534 Context.insert<InstFakeDef>(T, legalizeToReg(Src0)); |
| 3548 _mov(Dest, T); | 3535 _mov(Dest, T); |
| 3549 UnimplementedError(Func->getContext()->getFlags()); | 3536 UnimplementedError(Func->getContext()->getFlags()); |
| 3550 } else { | 3537 } else { |
| 3551 if (Src0->getType() == IceType_i64) | 3538 if (Src0->getType() == IceType_i64) |
| 3552 Src0 = loOperand(Src0); | 3539 Src0 = loOperand(Src0); |
| 3553 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); | 3540 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); |
| 3554 // t1 = trunc Src0RF; Dest = t1 | 3541 // t1 = trunc Src0RF; Dest = t1 |
| 3555 Variable *T = makeReg(Dest->getType()); | 3542 Variable *T = makeReg(Dest->getType()); |
| 3556 _mov(T, Src0RF); | 3543 _mov(T, Src0RF); |
| 3557 if (Dest->getType() == IceType_i1) | 3544 if (Dest->getType() == IceType_i1) |
| 3558 _and(T, T, Ctx->getConstantInt1(1)); | 3545 _and(T, T, Ctx->getConstantInt1(1)); |
| 3559 _mov(Dest, T); | 3546 _mov(Dest, T); |
| 3560 } | 3547 } |
| 3561 break; | 3548 break; |
| 3562 } | 3549 } |
| 3563 case InstCast::Fptrunc: | 3550 case InstCast::Fptrunc: |
| 3564 case InstCast::Fpext: { | 3551 case InstCast::Fpext: { |
| 3565 // fptrunc: dest.f32 = fptrunc src0.fp64 | 3552 // fptrunc: dest.f32 = fptrunc src0.fp64 |
| 3566 // fpext: dest.f64 = fptrunc src0.fp32 | 3553 // fpext: dest.f64 = fptrunc src0.fp32 |
| 3567 const bool IsTrunc = CastKind == InstCast::Fptrunc; | 3554 const bool IsTrunc = CastKind == InstCast::Fptrunc; |
| 3568 if (isVectorType(Dest->getType())) { | 3555 if (isVectorType(Dest->getType())) { |
| 3569 Variable *T = makeReg(Dest->getType()); | 3556 Variable *T = makeReg(Dest->getType()); |
| 3570 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | 3557 Context.insert<InstFakeDef>(T, legalizeToReg(Src0)); |
| 3571 _mov(Dest, T); | 3558 _mov(Dest, T); |
| 3572 UnimplementedError(Func->getContext()->getFlags()); | 3559 UnimplementedError(Func->getContext()->getFlags()); |
| 3573 break; | 3560 break; |
| 3574 } | 3561 } |
| 3575 assert(Dest->getType() == (IsTrunc ? IceType_f32 : IceType_f64)); | 3562 assert(Dest->getType() == (IsTrunc ? IceType_f32 : IceType_f64)); |
| 3576 assert(Src0->getType() == (IsTrunc ? IceType_f64 : IceType_f32)); | 3563 assert(Src0->getType() == (IsTrunc ? IceType_f64 : IceType_f32)); |
| 3577 Variable *Src0R = legalizeToReg(Src0); | 3564 Variable *Src0R = legalizeToReg(Src0); |
| 3578 Variable *T = makeReg(Dest->getType()); | 3565 Variable *T = makeReg(Dest->getType()); |
| 3579 _vcvt(T, Src0R, IsTrunc ? InstARM32Vcvt::D2s : InstARM32Vcvt::S2d); | 3566 _vcvt(T, Src0R, IsTrunc ? InstARM32Vcvt::D2s : InstARM32Vcvt::S2d); |
| 3580 _mov(Dest, T); | 3567 _mov(Dest, T); |
| 3581 break; | 3568 break; |
| 3582 } | 3569 } |
| 3583 case InstCast::Fptosi: | 3570 case InstCast::Fptosi: |
| 3584 case InstCast::Fptoui: { | 3571 case InstCast::Fptoui: { |
| 3585 if (isVectorType(Dest->getType())) { | 3572 if (isVectorType(Dest->getType())) { |
| 3586 Variable *T = makeReg(Dest->getType()); | 3573 Variable *T = makeReg(Dest->getType()); |
| 3587 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | 3574 Context.insert<InstFakeDef>(T, legalizeToReg(Src0)); |
| 3588 _mov(Dest, T); | 3575 _mov(Dest, T); |
| 3589 UnimplementedError(Func->getContext()->getFlags()); | 3576 UnimplementedError(Func->getContext()->getFlags()); |
| 3590 break; | 3577 break; |
| 3591 } | 3578 } |
| 3592 | 3579 |
| 3593 const bool DestIsSigned = CastKind == InstCast::Fptosi; | 3580 const bool DestIsSigned = CastKind == InstCast::Fptosi; |
| 3594 const bool Src0IsF32 = isFloat32Asserting32Or64(Src0->getType()); | 3581 const bool Src0IsF32 = isFloat32Asserting32Or64(Src0->getType()); |
| 3595 if (llvm::isa<Variable64On32>(Dest)) { | 3582 if (llvm::isa<Variable64On32>(Dest)) { |
| 3596 llvm::report_fatal_error("fp-to-i64 should have been pre-lowered."); | 3583 llvm::report_fatal_error("fp-to-i64 should have been pre-lowered."); |
| 3597 } | 3584 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3616 lowerCast(InstCast::create(Func, InstCast::Trunc, T_1, T)); | 3603 lowerCast(InstCast::create(Func, InstCast::Trunc, T_1, T)); |
| 3617 T = T_1; | 3604 T = T_1; |
| 3618 } | 3605 } |
| 3619 _mov(Dest, T); | 3606 _mov(Dest, T); |
| 3620 break; | 3607 break; |
| 3621 } | 3608 } |
| 3622 case InstCast::Sitofp: | 3609 case InstCast::Sitofp: |
| 3623 case InstCast::Uitofp: { | 3610 case InstCast::Uitofp: { |
| 3624 if (isVectorType(Dest->getType())) { | 3611 if (isVectorType(Dest->getType())) { |
| 3625 Variable *T = makeReg(Dest->getType()); | 3612 Variable *T = makeReg(Dest->getType()); |
| 3626 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | 3613 Context.insert<InstFakeDef>(T, legalizeToReg(Src0)); |
| 3627 _mov(Dest, T); | 3614 _mov(Dest, T); |
| 3628 UnimplementedError(Func->getContext()->getFlags()); | 3615 UnimplementedError(Func->getContext()->getFlags()); |
| 3629 break; | 3616 break; |
| 3630 } | 3617 } |
| 3631 const bool SourceIsSigned = CastKind == InstCast::Sitofp; | 3618 const bool SourceIsSigned = CastKind == InstCast::Sitofp; |
| 3632 const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType()); | 3619 const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType()); |
| 3633 if (Src0->getType() == IceType_i64) { | 3620 if (Src0->getType() == IceType_i64) { |
| 3634 llvm::report_fatal_error("i64-to-fp should have been pre-lowered."); | 3621 llvm::report_fatal_error("i64-to-fp should have been pre-lowered."); |
| 3635 } | 3622 } |
| 3636 // sitofp: | 3623 // sitofp: |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3693 case IceType_i64: { | 3680 case IceType_i64: { |
| 3694 // t0, t1 <- src0 | 3681 // t0, t1 <- src0 |
| 3695 // dest[31..0] = t0 | 3682 // dest[31..0] = t0 |
| 3696 // dest[63..32] = t1 | 3683 // dest[63..32] = t1 |
| 3697 assert(Src0->getType() == IceType_f64); | 3684 assert(Src0->getType() == IceType_f64); |
| 3698 auto *T = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); | 3685 auto *T = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); |
| 3699 T->initHiLo(Func); | 3686 T->initHiLo(Func); |
| 3700 configureBitcastTemporary(T); | 3687 configureBitcastTemporary(T); |
| 3701 Variable *Src0R = legalizeToReg(Src0); | 3688 Variable *Src0R = legalizeToReg(Src0); |
| 3702 _mov(T, Src0R); | 3689 _mov(T, Src0R); |
| 3703 Context.insert(InstFakeUse::create(Func, T->getHi())); | 3690 Context.insert<InstFakeUse>(T->getHi()); |
| 3704 Context.insert(InstFakeUse::create(Func, T->getLo())); | 3691 Context.insert<InstFakeUse>(T->getLo()); |
| 3705 lowerAssign(InstAssign::create(Func, Dest, T)); | 3692 lowerAssign(InstAssign::create(Func, Dest, T)); |
| 3706 break; | 3693 break; |
| 3707 } | 3694 } |
| 3708 case IceType_f64: { | 3695 case IceType_f64: { |
| 3709 // T0 <- lo(src) | 3696 // T0 <- lo(src) |
| 3710 // T1 <- hi(src) | 3697 // T1 <- hi(src) |
| 3711 // vmov T2, T0, T1 | 3698 // vmov T2, T0, T1 |
| 3712 // Dest <- T2 | 3699 // Dest <- T2 |
| 3713 assert(Src0->getType() == IceType_i64); | 3700 assert(Src0->getType() == IceType_i64); |
| 3714 Variable *T = makeReg(DestType); | 3701 Variable *T = makeReg(DestType); |
| 3715 auto *Src64 = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); | 3702 auto *Src64 = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); |
| 3716 Src64->initHiLo(Func); | 3703 Src64->initHiLo(Func); |
| 3717 configureBitcastTemporary(Src64); | 3704 configureBitcastTemporary(Src64); |
| 3718 lowerAssign(InstAssign::create(Func, Src64, Src0)); | 3705 lowerAssign(InstAssign::create(Func, Src64, Src0)); |
| 3719 _mov(T, Src64); | 3706 _mov(T, Src64); |
| 3720 lowerAssign(InstAssign::create(Func, Dest, T)); | 3707 lowerAssign(InstAssign::create(Func, Dest, T)); |
| 3721 break; | 3708 break; |
| 3722 } | 3709 } |
| 3723 case IceType_v4i1: | 3710 case IceType_v4i1: |
| 3724 case IceType_v8i1: | 3711 case IceType_v8i1: |
| 3725 case IceType_v16i1: | 3712 case IceType_v16i1: |
| 3726 case IceType_v8i16: | 3713 case IceType_v8i16: |
| 3727 case IceType_v16i8: | 3714 case IceType_v16i8: |
| 3728 case IceType_v4f32: | 3715 case IceType_v4f32: |
| 3729 case IceType_v4i32: { | 3716 case IceType_v4i32: { |
| 3730 // avoid liveness errors | 3717 // avoid liveness errors |
| 3731 Variable *T = makeReg(DestType); | 3718 Variable *T = makeReg(DestType); |
| 3732 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | 3719 Context.insert<InstFakeDef>(T, legalizeToReg(Src0)); |
| 3733 _mov(Dest, T); | 3720 _mov(Dest, T); |
| 3734 UnimplementedError(Func->getContext()->getFlags()); | 3721 UnimplementedError(Func->getContext()->getFlags()); |
| 3735 break; | 3722 break; |
| 3736 } | 3723 } |
| 3737 } | 3724 } |
| 3738 break; | 3725 break; |
| 3739 } | 3726 } |
| 3740 } | 3727 } |
| 3741 } | 3728 } |
| 3742 | 3729 |
| 3743 void TargetARM32::lowerExtractElement(const InstExtractElement *Inst) { | 3730 void TargetARM32::lowerExtractElement(const InstExtractElement *Inst) { |
| 3744 Variable *Dest = Inst->getDest(); | 3731 Variable *Dest = Inst->getDest(); |
| 3745 Type DestType = Dest->getType(); | 3732 Type DestType = Dest->getType(); |
| 3746 Variable *T = makeReg(DestType); | 3733 Variable *T = makeReg(DestType); |
| 3747 Context.insert(InstFakeDef::create(Func, T)); | 3734 Context.insert<InstFakeDef>(T); |
| 3748 _mov(Dest, T); | 3735 _mov(Dest, T); |
| 3749 UnimplementedError(Func->getContext()->getFlags()); | 3736 UnimplementedError(Func->getContext()->getFlags()); |
| 3750 } | 3737 } |
| 3751 | 3738 |
| 3752 namespace { | 3739 namespace { |
| 3753 // Validates FCMPARM32_TABLE's declaration w.r.t. InstFcmp::FCondition ordering | 3740 // Validates FCMPARM32_TABLE's declaration w.r.t. InstFcmp::FCondition ordering |
| 3754 // (and naming). | 3741 // (and naming). |
| 3755 enum { | 3742 enum { |
| 3756 #define X(val, CC0, CC1) _fcmp_ll_##val, | 3743 #define X(val, CC0, CC1) _fcmp_ll_##val, |
| 3757 FCMPARM32_TABLE | 3744 FCMPARM32_TABLE |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3819 assert(Condition < llvm::array_lengthof(TableFcmp)); | 3806 assert(Condition < llvm::array_lengthof(TableFcmp)); |
| 3820 return CondWhenTrue(TableFcmp[Condition].CC0, TableFcmp[Condition].CC1); | 3807 return CondWhenTrue(TableFcmp[Condition].CC0, TableFcmp[Condition].CC1); |
| 3821 } | 3808 } |
| 3822 } | 3809 } |
| 3823 } | 3810 } |
| 3824 | 3811 |
| 3825 void TargetARM32::lowerFcmp(const InstFcmp *Instr) { | 3812 void TargetARM32::lowerFcmp(const InstFcmp *Instr) { |
| 3826 Variable *Dest = Instr->getDest(); | 3813 Variable *Dest = Instr->getDest(); |
| 3827 if (isVectorType(Dest->getType())) { | 3814 if (isVectorType(Dest->getType())) { |
| 3828 Variable *T = makeReg(Dest->getType()); | 3815 Variable *T = makeReg(Dest->getType()); |
| 3829 Context.insert(InstFakeDef::create(Func, T)); | 3816 Context.insert<InstFakeDef>(T); |
| 3830 _mov(Dest, T); | 3817 _mov(Dest, T); |
| 3831 UnimplementedError(Func->getContext()->getFlags()); | 3818 UnimplementedError(Func->getContext()->getFlags()); |
| 3832 return; | 3819 return; |
| 3833 } | 3820 } |
| 3834 | 3821 |
| 3835 Variable *T = makeReg(IceType_i1); | 3822 Variable *T = makeReg(IceType_i1); |
| 3836 Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex); | 3823 Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex); |
| 3837 Operand *_0 = | 3824 Operand *_0 = |
| 3838 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); | 3825 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); |
| 3839 | 3826 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3877 if (SrcsLo.hasConstOperand()) { | 3864 if (SrcsLo.hasConstOperand()) { |
| 3878 const uint32_t ValueLo = SrcsLo.getConstantValue(); | 3865 const uint32_t ValueLo = SrcsLo.getConstantValue(); |
| 3879 const uint32_t ValueHi = SrcsHi.getConstantValue(); | 3866 const uint32_t ValueHi = SrcsHi.getConstantValue(); |
| 3880 const uint64_t Value = (static_cast<uint64_t>(ValueHi) << 32) | ValueLo; | 3867 const uint64_t Value = (static_cast<uint64_t>(ValueHi) << 32) | ValueLo; |
| 3881 if ((Condition == InstIcmp::Eq || Condition == InstIcmp::Ne) && | 3868 if ((Condition == InstIcmp::Eq || Condition == InstIcmp::Ne) && |
| 3882 Value == 0) { | 3869 Value == 0) { |
| 3883 Variable *T = makeReg(IceType_i32); | 3870 Variable *T = makeReg(IceType_i32); |
| 3884 Variable *Src0LoR = SrcsLo.src0R(this); | 3871 Variable *Src0LoR = SrcsLo.src0R(this); |
| 3885 Variable *Src0HiR = SrcsHi.src0R(this); | 3872 Variable *Src0HiR = SrcsHi.src0R(this); |
| 3886 _orrs(T, Src0LoR, Src0HiR); | 3873 _orrs(T, Src0LoR, Src0HiR); |
| 3887 Context.insert(InstFakeUse::create(Func, T)); | 3874 Context.insert<InstFakeUse>(T); |
| 3888 return CondWhenTrue(TableIcmp64[Index].C1); | 3875 return CondWhenTrue(TableIcmp64[Index].C1); |
| 3889 } | 3876 } |
| 3890 | 3877 |
| 3891 Variable *Src0RLo = SrcsLo.src0R(this); | 3878 Variable *Src0RLo = SrcsLo.src0R(this); |
| 3892 Variable *Src0RHi = SrcsHi.src0R(this); | 3879 Variable *Src0RHi = SrcsHi.src0R(this); |
| 3893 Operand *Src1RFLo = SrcsLo.src1RF(this); | 3880 Operand *Src1RFLo = SrcsLo.src1RF(this); |
| 3894 Operand *Src1RFHi = ValueLo == ValueHi ? Src1RFLo : SrcsHi.src1RF(this); | 3881 Operand *Src1RFHi = ValueLo == ValueHi ? Src1RFLo : SrcsHi.src1RF(this); |
| 3895 | 3882 |
| 3896 const bool UseRsb = TableIcmp64[Index].Swapped != SrcsLo.swappedOperands(); | 3883 const bool UseRsb = TableIcmp64[Index].Swapped != SrcsLo.swappedOperands(); |
| 3897 | 3884 |
| 3898 if (UseRsb) { | 3885 if (UseRsb) { |
| 3899 if (TableIcmp64[Index].IsSigned) { | 3886 if (TableIcmp64[Index].IsSigned) { |
| 3900 Variable *T = makeReg(IceType_i32); | 3887 Variable *T = makeReg(IceType_i32); |
| 3901 _rsbs(T, Src0RLo, Src1RFLo); | 3888 _rsbs(T, Src0RLo, Src1RFLo); |
| 3902 Context.insert(InstFakeUse::create(Func, T)); | 3889 Context.insert<InstFakeUse>(T); |
| 3903 | 3890 |
| 3904 T = makeReg(IceType_i32); | 3891 T = makeReg(IceType_i32); |
| 3905 _rscs(T, Src0RHi, Src1RFHi); | 3892 _rscs(T, Src0RHi, Src1RFHi); |
| 3906 // We need to add a FakeUse here because liveness gets mad at us (Def | 3893 // We need to add a FakeUse here because liveness gets mad at us (Def |
| 3907 // without Use.) Note that flag-setting instructions are considered to | 3894 // without Use.) Note that flag-setting instructions are considered to |
| 3908 // have side effects and, therefore, are not DCE'ed. | 3895 // have side effects and, therefore, are not DCE'ed. |
| 3909 Context.insert(InstFakeUse::create(Func, T)); | 3896 Context.insert<InstFakeUse>(T); |
| 3910 } else { | 3897 } else { |
| 3911 Variable *T = makeReg(IceType_i32); | 3898 Variable *T = makeReg(IceType_i32); |
| 3912 _rsbs(T, Src0RHi, Src1RFHi); | 3899 _rsbs(T, Src0RHi, Src1RFHi); |
| 3913 Context.insert(InstFakeUse::create(Func, T)); | 3900 Context.insert<InstFakeUse>(T); |
| 3914 | 3901 |
| 3915 T = makeReg(IceType_i32); | 3902 T = makeReg(IceType_i32); |
| 3916 _rsbs(T, Src0RLo, Src1RFLo, CondARM32::EQ); | 3903 _rsbs(T, Src0RLo, Src1RFLo, CondARM32::EQ); |
| 3917 Context.insert(InstFakeUse::create(Func, T)); | 3904 Context.insert<InstFakeUse>(T); |
| 3918 } | 3905 } |
| 3919 } else { | 3906 } else { |
| 3920 if (TableIcmp64[Index].IsSigned) { | 3907 if (TableIcmp64[Index].IsSigned) { |
| 3921 _cmp(Src0RLo, Src1RFLo); | 3908 _cmp(Src0RLo, Src1RFLo); |
| 3922 Variable *T = makeReg(IceType_i32); | 3909 Variable *T = makeReg(IceType_i32); |
| 3923 _sbcs(T, Src0RHi, Src1RFHi); | 3910 _sbcs(T, Src0RHi, Src1RFHi); |
| 3924 Context.insert(InstFakeUse::create(Func, T)); | 3911 Context.insert<InstFakeUse>(T); |
| 3925 } else { | 3912 } else { |
| 3926 _cmp(Src0RHi, Src1RFHi); | 3913 _cmp(Src0RHi, Src1RFHi); |
| 3927 _cmp(Src0RLo, Src1RFLo, CondARM32::EQ); | 3914 _cmp(Src0RLo, Src1RFLo, CondARM32::EQ); |
| 3928 } | 3915 } |
| 3929 } | 3916 } |
| 3930 | 3917 |
| 3931 return CondWhenTrue(TableIcmp64[Index].C1); | 3918 return CondWhenTrue(TableIcmp64[Index].C1); |
| 3932 } | 3919 } |
| 3933 | 3920 |
| 3934 Variable *Src0RLo, *Src0RHi; | 3921 Variable *Src0RLo, *Src0RHi; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3973 // longer sequence. | 3960 // longer sequence. |
| 3974 // | 3961 // |
| 3975 // So, we are going with the GCC version since it's usually better (except | 3962 // So, we are going with the GCC version since it's usually better (except |
| 3976 // perhaps for eq/ne). We could revisit special-casing eq/ne later. | 3963 // perhaps for eq/ne). We could revisit special-casing eq/ne later. |
| 3977 if (TableIcmp64[Index].IsSigned) { | 3964 if (TableIcmp64[Index].IsSigned) { |
| 3978 Variable *ScratchReg = makeReg(IceType_i32); | 3965 Variable *ScratchReg = makeReg(IceType_i32); |
| 3979 _cmp(Src0RLo, Src1RFLo); | 3966 _cmp(Src0RLo, Src1RFLo); |
| 3980 _sbcs(ScratchReg, Src0RHi, Src1RFHi); | 3967 _sbcs(ScratchReg, Src0RHi, Src1RFHi); |
| 3981 // ScratchReg isn't going to be used, but we need the side-effect of | 3968 // ScratchReg isn't going to be used, but we need the side-effect of |
| 3982 // setting flags from this operation. | 3969 // setting flags from this operation. |
| 3983 Context.insert(InstFakeUse::create(Func, ScratchReg)); | 3970 Context.insert<InstFakeUse>(ScratchReg); |
| 3984 } else { | 3971 } else { |
| 3985 _cmp(Src0RHi, Src1RFHi); | 3972 _cmp(Src0RHi, Src1RFHi); |
| 3986 _cmp(Src0RLo, Src1RFLo, CondARM32::EQ); | 3973 _cmp(Src0RLo, Src1RFLo, CondARM32::EQ); |
| 3987 } | 3974 } |
| 3988 return CondWhenTrue(TableIcmp64[Index].C1); | 3975 return CondWhenTrue(TableIcmp64[Index].C1); |
| 3989 } | 3976 } |
| 3990 | 3977 |
| 3991 TargetARM32::CondWhenTrue | 3978 TargetARM32::CondWhenTrue |
| 3992 TargetARM32::lowerInt32IcmpCond(InstIcmp::ICond Condition, Operand *Src0, | 3979 TargetARM32::lowerInt32IcmpCond(InstIcmp::ICond Condition, Operand *Src0, |
| 3993 Operand *Src1) { | 3980 Operand *Src1) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 4013 _cmn(Src0R, Src1F); | 4000 _cmn(Src0R, Src1F); |
| 4014 return CondWhenTrue(getIcmp32Mapping(Condition)); | 4001 return CondWhenTrue(getIcmp32Mapping(Condition)); |
| 4015 } | 4002 } |
| 4016 | 4003 |
| 4017 Operand *Src1RF = Srcs.src1RF(this); | 4004 Operand *Src1RF = Srcs.src1RF(this); |
| 4018 if (!Srcs.swappedOperands()) { | 4005 if (!Srcs.swappedOperands()) { |
| 4019 _cmp(Src0R, Src1RF); | 4006 _cmp(Src0R, Src1RF); |
| 4020 } else { | 4007 } else { |
| 4021 Variable *T = makeReg(IceType_i32); | 4008 Variable *T = makeReg(IceType_i32); |
| 4022 _rsbs(T, Src0R, Src1RF); | 4009 _rsbs(T, Src0R, Src1RF); |
| 4023 Context.insert(InstFakeUse::create(Func, T)); | 4010 Context.insert<InstFakeUse>(T); |
| 4024 } | 4011 } |
| 4025 return CondWhenTrue(getIcmp32Mapping(Condition)); | 4012 return CondWhenTrue(getIcmp32Mapping(Condition)); |
| 4026 } | 4013 } |
| 4027 | 4014 |
| 4028 TargetARM32::CondWhenTrue | 4015 TargetARM32::CondWhenTrue |
| 4029 TargetARM32::lowerInt8AndInt16IcmpCond(InstIcmp::ICond Condition, Operand *Src0, | 4016 TargetARM32::lowerInt8AndInt16IcmpCond(InstIcmp::ICond Condition, Operand *Src0, |
| 4030 Operand *Src1) { | 4017 Operand *Src1) { |
| 4031 Int32Operands Srcs(Src0, Src1); | 4018 Int32Operands Srcs(Src0, Src1); |
| 4032 const int32_t ShAmt = 32 - getScalarIntBitWidth(Src0->getType()); | 4019 const int32_t ShAmt = 32 - getScalarIntBitWidth(Src0->getType()); |
| 4033 assert(ShAmt >= 0); | 4020 assert(ShAmt >= 0); |
| 4034 | 4021 |
| 4035 if (!Srcs.hasConstOperand()) { | 4022 if (!Srcs.hasConstOperand()) { |
| 4036 Variable *Src0R = makeReg(IceType_i32); | 4023 Variable *Src0R = makeReg(IceType_i32); |
| 4037 Operand *ShAmtImm = shAmtImm(ShAmt); | 4024 Operand *ShAmtImm = shAmtImm(ShAmt); |
| 4038 _lsl(Src0R, legalizeToReg(Src0), ShAmtImm); | 4025 _lsl(Src0R, legalizeToReg(Src0), ShAmtImm); |
| 4039 | 4026 |
| 4040 Variable *Src1R = legalizeToReg(Src1); | 4027 Variable *Src1R = legalizeToReg(Src1); |
| 4041 auto *Src1F = OperandARM32FlexReg::create(Func, IceType_i32, Src1R, | 4028 auto *Src1F = OperandARM32FlexReg::create(Func, IceType_i32, Src1R, |
| 4042 OperandARM32::LSL, ShAmtImm); | 4029 OperandARM32::LSL, ShAmtImm); |
| 4043 _cmp(Src0R, Src1F); | 4030 _cmp(Src0R, Src1F); |
| 4044 return CondWhenTrue(getIcmp32Mapping(Condition)); | 4031 return CondWhenTrue(getIcmp32Mapping(Condition)); |
| 4045 } | 4032 } |
| 4046 | 4033 |
| 4047 const int32_t Value = Srcs.getConstantValue(); | 4034 const int32_t Value = Srcs.getConstantValue(); |
| 4048 if ((Condition == InstIcmp::Eq || Condition == InstIcmp::Ne) && Value == 0) { | 4035 if ((Condition == InstIcmp::Eq || Condition == InstIcmp::Ne) && Value == 0) { |
| 4049 Operand *ShAmtImm = shAmtImm(ShAmt); | 4036 Operand *ShAmtImm = shAmtImm(ShAmt); |
| 4050 Variable *T = makeReg(IceType_i32); | 4037 Variable *T = makeReg(IceType_i32); |
| 4051 _lsls(T, Srcs.src0R(this), ShAmtImm); | 4038 _lsls(T, Srcs.src0R(this), ShAmtImm); |
| 4052 Context.insert(InstFakeUse::create(Func, T)); | 4039 Context.insert<InstFakeUse>(T); |
| 4053 return CondWhenTrue(getIcmp32Mapping(Condition)); | 4040 return CondWhenTrue(getIcmp32Mapping(Condition)); |
| 4054 } | 4041 } |
| 4055 | 4042 |
| 4056 Variable *ConstR = makeReg(IceType_i32); | 4043 Variable *ConstR = makeReg(IceType_i32); |
| 4057 _mov(ConstR, | 4044 _mov(ConstR, |
| 4058 legalize(Ctx->getConstantInt32(Value << ShAmt), Legal_Reg | Legal_Flex)); | 4045 legalize(Ctx->getConstantInt32(Value << ShAmt), Legal_Reg | Legal_Flex)); |
| 4059 Operand *NonConstF = OperandARM32FlexReg::create( | 4046 Operand *NonConstF = OperandARM32FlexReg::create( |
| 4060 Func, IceType_i32, Srcs.src0R(this), OperandARM32::LSL, | 4047 Func, IceType_i32, Srcs.src0R(this), OperandARM32::LSL, |
| 4061 Ctx->getConstantInt32(ShAmt)); | 4048 Ctx->getConstantInt32(ShAmt)); |
| 4062 | 4049 |
| 4063 if (Srcs.swappedOperands()) { | 4050 if (Srcs.swappedOperands()) { |
| 4064 _cmp(ConstR, NonConstF); | 4051 _cmp(ConstR, NonConstF); |
| 4065 } else { | 4052 } else { |
| 4066 Variable *T = makeReg(IceType_i32); | 4053 Variable *T = makeReg(IceType_i32); |
| 4067 _rsbs(T, ConstR, NonConstF); | 4054 _rsbs(T, ConstR, NonConstF); |
| 4068 Context.insert(InstFakeUse::create(Func, T)); | 4055 Context.insert<InstFakeUse>(T); |
| 4069 } | 4056 } |
| 4070 return CondWhenTrue(getIcmp32Mapping(Condition)); | 4057 return CondWhenTrue(getIcmp32Mapping(Condition)); |
| 4071 } | 4058 } |
| 4072 | 4059 |
| 4073 TargetARM32::CondWhenTrue TargetARM32::lowerIcmpCond(const InstIcmp *Inst) { | 4060 TargetARM32::CondWhenTrue TargetARM32::lowerIcmpCond(const InstIcmp *Inst) { |
| 4074 assert(Inst->getSrc(0)->getType() != IceType_i1); | 4061 assert(Inst->getSrc(0)->getType() != IceType_i1); |
| 4075 assert(Inst->getSrc(1)->getType() != IceType_i1); | 4062 assert(Inst->getSrc(1)->getType() != IceType_i1); |
| 4076 | 4063 |
| 4077 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); | 4064 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
| 4078 Operand *Src1 = legalizeUndef(Inst->getSrc(1)); | 4065 Operand *Src1 = legalizeUndef(Inst->getSrc(1)); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4118 case IceType_i64: | 4105 case IceType_i64: |
| 4119 return lowerInt64IcmpCond(Condition, Src0, Src1); | 4106 return lowerInt64IcmpCond(Condition, Src0, Src1); |
| 4120 } | 4107 } |
| 4121 } | 4108 } |
| 4122 | 4109 |
| 4123 void TargetARM32::lowerIcmp(const InstIcmp *Inst) { | 4110 void TargetARM32::lowerIcmp(const InstIcmp *Inst) { |
| 4124 Variable *Dest = Inst->getDest(); | 4111 Variable *Dest = Inst->getDest(); |
| 4125 | 4112 |
| 4126 if (isVectorType(Dest->getType())) { | 4113 if (isVectorType(Dest->getType())) { |
| 4127 Variable *T = makeReg(Dest->getType()); | 4114 Variable *T = makeReg(Dest->getType()); |
| 4128 Context.insert(InstFakeDef::create(Func, T)); | 4115 Context.insert<InstFakeDef>(T); |
| 4129 _mov(Dest, T); | 4116 _mov(Dest, T); |
| 4130 UnimplementedError(Func->getContext()->getFlags()); | 4117 UnimplementedError(Func->getContext()->getFlags()); |
| 4131 return; | 4118 return; |
| 4132 } | 4119 } |
| 4133 | 4120 |
| 4134 Operand *_0 = | 4121 Operand *_0 = |
| 4135 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); | 4122 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); |
| 4136 Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex); | 4123 Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex); |
| 4137 Variable *T = makeReg(IceType_i1); | 4124 Variable *T = makeReg(IceType_i1); |
| 4138 | 4125 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4212 ValueReg = makeReg(DestTy); | 4199 ValueReg = makeReg(DestTy); |
| 4213 ValueHiReg = nullptr; | 4200 ValueHiReg = nullptr; |
| 4214 ValueLoReg = ValueReg; | 4201 ValueLoReg = ValueReg; |
| 4215 | 4202 |
| 4216 TmpReg = makeReg(DestTy); | 4203 TmpReg = makeReg(DestTy); |
| 4217 TmpHiReg = nullptr; | 4204 TmpHiReg = nullptr; |
| 4218 TmpLoReg = TmpReg; | 4205 TmpLoReg = TmpReg; |
| 4219 } | 4206 } |
| 4220 | 4207 |
| 4221 if (DestTy == IceType_i64) { | 4208 if (DestTy == IceType_i64) { |
| 4222 Context.insert(InstFakeDef::create(Func, Value)); | 4209 Context.insert<InstFakeDef>(Value); |
| 4223 } | 4210 } |
| 4224 lowerAssign(InstAssign::create(Func, Value, Val)); | 4211 lowerAssign(InstAssign::create(Func, Value, Val)); |
| 4225 | 4212 |
| 4226 Variable *PtrVar = Func->makeVariable(IceType_i32); | 4213 Variable *PtrVar = Func->makeVariable(IceType_i32); |
| 4227 lowerAssign(InstAssign::create(Func, PtrVar, Ptr)); | 4214 lowerAssign(InstAssign::create(Func, PtrVar, Ptr)); |
| 4228 | 4215 |
| 4229 _dmb(); | 4216 _dmb(); |
| 4230 Context.insert(Retry); | 4217 Context.insert(Retry); |
| 4231 Mem = formMemoryOperand(PtrVar, DestTy); | 4218 Mem = formMemoryOperand(PtrVar, DestTy); |
| 4232 if (DestTy == IceType_i64) { | 4219 if (DestTy == IceType_i64) { |
| 4233 Context.insert(InstFakeDef::create(Func, ValueReg, Value)); | 4220 Context.insert<InstFakeDef>(ValueReg, Value); |
| 4234 } | 4221 } |
| 4235 lowerAssign(InstAssign::create(Func, ValueReg, Value)); | 4222 lowerAssign(InstAssign::create(Func, ValueReg, Value)); |
| 4236 if (DestTy == IceType_i8 || DestTy == IceType_i16) { | 4223 if (DestTy == IceType_i8 || DestTy == IceType_i16) { |
| 4237 _uxt(ValueReg, ValueReg); | 4224 _uxt(ValueReg, ValueReg); |
| 4238 } | 4225 } |
| 4239 _ldrex(PtrContentsReg, Mem); | 4226 _ldrex(PtrContentsReg, Mem); |
| 4240 | 4227 |
| 4241 if (DestTy == IceType_i64) { | 4228 if (DestTy == IceType_i64) { |
| 4242 Context.insert(InstFakeDef::create(Func, TmpReg, ValueReg)); | 4229 Context.insert<InstFakeDef>(TmpReg, ValueReg); |
| 4243 } | 4230 } |
| 4244 switch (Operation) { | 4231 switch (Operation) { |
| 4245 default: | 4232 default: |
| 4246 Func->setError("Unknown AtomicRMW operation"); | 4233 Func->setError("Unknown AtomicRMW operation"); |
| 4247 return; | 4234 return; |
| 4248 case Intrinsics::AtomicAdd: | 4235 case Intrinsics::AtomicAdd: |
| 4249 if (DestTy == IceType_i64) { | 4236 if (DestTy == IceType_i64) { |
| 4250 _adds(TmpLoReg, PtrContentsLoReg, ValueLoReg); | 4237 _adds(TmpLoReg, PtrContentsLoReg, ValueLoReg); |
| 4251 _adc(TmpHiReg, PtrContentsHiReg, ValueHiReg); | 4238 _adc(TmpHiReg, PtrContentsHiReg, ValueHiReg); |
| 4252 } else { | 4239 } else { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4286 } | 4273 } |
| 4287 break; | 4274 break; |
| 4288 } | 4275 } |
| 4289 _strex(Success, TmpReg, Mem); | 4276 _strex(Success, TmpReg, Mem); |
| 4290 _cmp(Success, _0); | 4277 _cmp(Success, _0); |
| 4291 _br(Retry, CondARM32::NE); | 4278 _br(Retry, CondARM32::NE); |
| 4292 | 4279 |
| 4293 // The following fake-uses ensure that Subzero will not clobber them in the | 4280 // The following fake-uses ensure that Subzero will not clobber them in the |
| 4294 // load-linked/store-conditional loop above. We might have to spill them, but | 4281 // load-linked/store-conditional loop above. We might have to spill them, but |
| 4295 // spilling is preferable over incorrect behavior. | 4282 // spilling is preferable over incorrect behavior. |
| 4296 Context.insert(InstFakeUse::create(Func, PtrVar)); | 4283 Context.insert<InstFakeUse>(PtrVar); |
| 4297 if (auto *Value64 = llvm::dyn_cast<Variable64On32>(Value)) { | 4284 if (auto *Value64 = llvm::dyn_cast<Variable64On32>(Value)) { |
| 4298 Context.insert(InstFakeUse::create(Func, Value64->getHi())); | 4285 Context.insert<InstFakeUse>(Value64->getHi()); |
| 4299 Context.insert(InstFakeUse::create(Func, Value64->getLo())); | 4286 Context.insert<InstFakeUse>(Value64->getLo()); |
| 4300 } else { | 4287 } else { |
| 4301 Context.insert(InstFakeUse::create(Func, Value)); | 4288 Context.insert<InstFakeUse>(Value); |
| 4302 } | 4289 } |
| 4303 _dmb(); | 4290 _dmb(); |
| 4304 if (DestTy == IceType_i8 || DestTy == IceType_i16) { | 4291 if (DestTy == IceType_i8 || DestTy == IceType_i16) { |
| 4305 _uxt(PtrContentsReg, PtrContentsReg); | 4292 _uxt(PtrContentsReg, PtrContentsReg); |
| 4306 } | 4293 } |
| 4307 | 4294 |
| 4308 if (DestTy == IceType_i64) { | 4295 if (DestTy == IceType_i64) { |
| 4309 Context.insert(InstFakeUse::create(Func, PtrContentsReg)); | 4296 Context.insert<InstFakeUse>(PtrContentsReg); |
| 4310 } | 4297 } |
| 4311 lowerAssign(InstAssign::create(Func, Dest, PtrContentsReg)); | 4298 lowerAssign(InstAssign::create(Func, Dest, PtrContentsReg)); |
| 4312 if (auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest)) { | 4299 if (auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest)) { |
| 4313 Context.insert(InstFakeUse::create(Func, Dest64->getLo())); | 4300 Context.insert<InstFakeUse>(Dest64->getLo()); |
| 4314 Context.insert(InstFakeUse::create(Func, Dest64->getHi())); | 4301 Context.insert<InstFakeUse>(Dest64->getHi()); |
| 4315 } else { | 4302 } else { |
| 4316 Context.insert(InstFakeUse::create(Func, Dest)); | 4303 Context.insert<InstFakeUse>(Dest); |
| 4317 } | 4304 } |
| 4318 } | 4305 } |
| 4319 | 4306 |
| 4320 void TargetARM32::postambleCtpop64(const InstCall *Instr) { | 4307 void TargetARM32::postambleCtpop64(const InstCall *Instr) { |
| 4321 Operand *Arg0 = Instr->getArg(0); | 4308 Operand *Arg0 = Instr->getArg(0); |
| 4322 if (isInt32Asserting32Or64(Arg0->getType())) { | 4309 if (isInt32Asserting32Or64(Arg0->getType())) { |
| 4323 return; | 4310 return; |
| 4324 } | 4311 } |
| 4325 // The popcount helpers always return 32-bit values, while the intrinsic's | 4312 // The popcount helpers always return 32-bit values, while the intrinsic's |
| 4326 // signature matches some 64-bit platform's native instructions and expect to | 4313 // signature matches some 64-bit platform's native instructions and expect to |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4384 _ldrex(T, formMemoryOperand(Instr->getArg(0), IceType_i64)); | 4371 _ldrex(T, formMemoryOperand(Instr->getArg(0), IceType_i64)); |
| 4385 } else { | 4372 } else { |
| 4386 T = makeReg(DestTy); | 4373 T = makeReg(DestTy); |
| 4387 _ldr(T, formMemoryOperand(Instr->getArg(0), DestTy)); | 4374 _ldr(T, formMemoryOperand(Instr->getArg(0), DestTy)); |
| 4388 } | 4375 } |
| 4389 _dmb(); | 4376 _dmb(); |
| 4390 lowerAssign(InstAssign::create(Func, Dest, T)); | 4377 lowerAssign(InstAssign::create(Func, Dest, T)); |
| 4391 // Make sure the atomic load isn't elided when unused, by adding a FakeUse. | 4378 // Make sure the atomic load isn't elided when unused, by adding a FakeUse. |
| 4392 // Since lowerLoad may fuse the load w/ an arithmetic instruction, insert | 4379 // Since lowerLoad may fuse the load w/ an arithmetic instruction, insert |
| 4393 // the FakeUse on the last-inserted instruction's dest. | 4380 // the FakeUse on the last-inserted instruction's dest. |
| 4394 Context.insert( | 4381 Context.insert<InstFakeUse>(Context.getLastInserted()->getDest()); |
| 4395 InstFakeUse::create(Func, Context.getLastInserted()->getDest())); | |
| 4396 return; | 4382 return; |
| 4397 } | 4383 } |
| 4398 case Intrinsics::AtomicStore: { | 4384 case Intrinsics::AtomicStore: { |
| 4399 // We require the memory address to be naturally aligned. Given that is the | 4385 // We require the memory address to be naturally aligned. Given that is the |
| 4400 // case, then normal loads are atomic. | 4386 // case, then normal loads are atomic. |
| 4401 if (!Intrinsics::isMemoryOrderValid( | 4387 if (!Intrinsics::isMemoryOrderValid( |
| 4402 ID, getConstantMemoryOrder(Instr->getArg(2)))) { | 4388 ID, getConstantMemoryOrder(Instr->getArg(2)))) { |
| 4403 Func->setError("Unexpected memory ordering for AtomicStore"); | 4389 Func->setError("Unexpected memory ordering for AtomicStore"); |
| 4404 return; | 4390 return; |
| 4405 } | 4391 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 4431 auto *Retry = InstARM32Label::create(Func, this); | 4417 auto *Retry = InstARM32Label::create(Func, this); |
| 4432 Variable64On32 *NewReg = makeI64RegPair(); | 4418 Variable64On32 *NewReg = makeI64RegPair(); |
| 4433 ValueVar->initHiLo(Func); | 4419 ValueVar->initHiLo(Func); |
| 4434 ValueVar->mustNotHaveReg(); | 4420 ValueVar->mustNotHaveReg(); |
| 4435 | 4421 |
| 4436 _dmb(); | 4422 _dmb(); |
| 4437 lowerAssign(InstAssign::create(Func, ValueVar, Value)); | 4423 lowerAssign(InstAssign::create(Func, ValueVar, Value)); |
| 4438 lowerAssign(InstAssign::create(Func, AddrVar, Addr)); | 4424 lowerAssign(InstAssign::create(Func, AddrVar, Addr)); |
| 4439 | 4425 |
| 4440 Context.insert(Retry); | 4426 Context.insert(Retry); |
| 4441 Context.insert(InstFakeDef::create(Func, NewReg)); | 4427 Context.insert<InstFakeDef>(NewReg); |
| 4442 lowerAssign(InstAssign::create(Func, NewReg, ValueVar)); | 4428 lowerAssign(InstAssign::create(Func, NewReg, ValueVar)); |
| 4443 Mem = formMemoryOperand(AddrVar, IceType_i64); | 4429 Mem = formMemoryOperand(AddrVar, IceType_i64); |
| 4444 _ldrex(Tmp, Mem); | 4430 _ldrex(Tmp, Mem); |
| 4445 // This fake-use both prevents the ldrex from being dead-code eliminated, | 4431 // This fake-use both prevents the ldrex from being dead-code eliminated, |
| 4446 // while also keeping liveness happy about all defs being used. | 4432 // while also keeping liveness happy about all defs being used. |
| 4447 Context.insert( | 4433 Context.insert<InstFakeUse>(Context.getLastInserted()->getDest()); |
| 4448 InstFakeUse::create(Func, Context.getLastInserted()->getDest())); | |
| 4449 _strex(Success, NewReg, Mem); | 4434 _strex(Success, NewReg, Mem); |
| 4450 _cmp(Success, _0); | 4435 _cmp(Success, _0); |
| 4451 _br(Retry, CondARM32::NE); | 4436 _br(Retry, CondARM32::NE); |
| 4452 | 4437 |
| 4453 Context.insert(InstFakeUse::create(Func, ValueVar->getLo())); | 4438 Context.insert<InstFakeUse>(ValueVar->getLo()); |
| 4454 Context.insert(InstFakeUse::create(Func, ValueVar->getHi())); | 4439 Context.insert<InstFakeUse>(ValueVar->getHi()); |
| 4455 Context.insert(InstFakeUse::create(Func, AddrVar)); | 4440 Context.insert<InstFakeUse>(AddrVar); |
| 4456 _dmb(); | 4441 _dmb(); |
| 4457 return; | 4442 return; |
| 4458 } | 4443 } |
| 4459 // non-64-bit stores are atomically as long as the address is aligned. This | 4444 // non-64-bit stores are atomically as long as the address is aligned. This |
| 4460 // is PNaCl, so addresses are aligned. | 4445 // is PNaCl, so addresses are aligned. |
| 4461 Variable *T = makeReg(ValueTy); | 4446 Variable *T = makeReg(ValueTy); |
| 4462 | 4447 |
| 4463 _dmb(); | 4448 _dmb(); |
| 4464 lowerAssign(InstAssign::create(Func, T, Value)); | 4449 lowerAssign(InstAssign::create(Func, T, Value)); |
| 4465 _str(T, formMemoryOperand(Addr, ValueTy)); | 4450 _str(T, formMemoryOperand(Addr, ValueTy)); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4543 } else { | 4528 } else { |
| 4544 TmpReg = makeReg(DestTy); | 4529 TmpReg = makeReg(DestTy); |
| 4545 New = Func->makeVariable(DestTy); | 4530 New = Func->makeVariable(DestTy); |
| 4546 NewReg = makeReg(DestTy); | 4531 NewReg = makeReg(DestTy); |
| 4547 Expected = Func->makeVariable(DestTy); | 4532 Expected = Func->makeVariable(DestTy); |
| 4548 ExpectedReg = makeReg(DestTy); | 4533 ExpectedReg = makeReg(DestTy); |
| 4549 } | 4534 } |
| 4550 | 4535 |
| 4551 Mem = formMemoryOperand(Instr->getArg(0), DestTy); | 4536 Mem = formMemoryOperand(Instr->getArg(0), DestTy); |
| 4552 if (DestTy == IceType_i64) { | 4537 if (DestTy == IceType_i64) { |
| 4553 Context.insert(InstFakeDef::create(Func, Expected)); | 4538 Context.insert<InstFakeDef>(Expected); |
| 4554 } | 4539 } |
| 4555 lowerAssign(InstAssign::create(Func, Expected, Instr->getArg(1))); | 4540 lowerAssign(InstAssign::create(Func, Expected, Instr->getArg(1))); |
| 4556 if (DestTy == IceType_i64) { | 4541 if (DestTy == IceType_i64) { |
| 4557 Context.insert(InstFakeDef::create(Func, New)); | 4542 Context.insert<InstFakeDef>(New); |
| 4558 } | 4543 } |
| 4559 lowerAssign(InstAssign::create(Func, New, Instr->getArg(2))); | 4544 lowerAssign(InstAssign::create(Func, New, Instr->getArg(2))); |
| 4560 _dmb(); | 4545 _dmb(); |
| 4561 | 4546 |
| 4562 Context.insert(Retry); | 4547 Context.insert(Retry); |
| 4563 if (DestTy == IceType_i64) { | 4548 if (DestTy == IceType_i64) { |
| 4564 Context.insert(InstFakeDef::create(Func, ExpectedReg, Expected)); | 4549 Context.insert<InstFakeDef>(ExpectedReg, Expected); |
| 4565 } | 4550 } |
| 4566 lowerAssign(InstAssign::create(Func, ExpectedReg, Expected)); | 4551 lowerAssign(InstAssign::create(Func, ExpectedReg, Expected)); |
| 4567 if (DestTy == IceType_i64) { | 4552 if (DestTy == IceType_i64) { |
| 4568 Context.insert(InstFakeDef::create(Func, NewReg, New)); | 4553 Context.insert<InstFakeDef>(NewReg, New); |
| 4569 } | 4554 } |
| 4570 lowerAssign(InstAssign::create(Func, NewReg, New)); | 4555 lowerAssign(InstAssign::create(Func, NewReg, New)); |
| 4571 | 4556 |
| 4572 _ldrex(TmpReg, Mem); | 4557 _ldrex(TmpReg, Mem); |
| 4573 Context.insert( | 4558 Context.insert<InstFakeUse>(Context.getLastInserted()->getDest()); |
| 4574 InstFakeUse::create(Func, Context.getLastInserted()->getDest())); | |
| 4575 if (DestTy == IceType_i64) { | 4559 if (DestTy == IceType_i64) { |
| 4576 auto *TmpReg64 = llvm::cast<Variable64On32>(TmpReg); | 4560 auto *TmpReg64 = llvm::cast<Variable64On32>(TmpReg); |
| 4577 auto *ExpectedReg64 = llvm::cast<Variable64On32>(ExpectedReg); | 4561 auto *ExpectedReg64 = llvm::cast<Variable64On32>(ExpectedReg); |
| 4578 // lowerAssign above has added fake-defs for TmpReg and ExpectedReg. Let's | 4562 // lowerAssign above has added fake-defs for TmpReg and ExpectedReg. Let's |
| 4579 // keep liveness happy, shall we? | 4563 // keep liveness happy, shall we? |
| 4580 Context.insert(InstFakeUse::create(Func, TmpReg)); | 4564 Context.insert<InstFakeUse>(TmpReg); |
| 4581 Context.insert(InstFakeUse::create(Func, ExpectedReg)); | 4565 Context.insert<InstFakeUse>(ExpectedReg); |
| 4582 _cmp(TmpReg64->getHi(), ExpectedReg64->getHi()); | 4566 _cmp(TmpReg64->getHi(), ExpectedReg64->getHi()); |
| 4583 _cmp(TmpReg64->getLo(), ExpectedReg64->getLo(), CondARM32::EQ); | 4567 _cmp(TmpReg64->getLo(), ExpectedReg64->getLo(), CondARM32::EQ); |
| 4584 } else { | 4568 } else { |
| 4585 _cmp(TmpReg, ExpectedReg); | 4569 _cmp(TmpReg, ExpectedReg); |
| 4586 } | 4570 } |
| 4587 _strex(Success, NewReg, Mem, CondARM32::EQ); | 4571 _strex(Success, NewReg, Mem, CondARM32::EQ); |
| 4588 if (DestTy == IceType_i64) { | 4572 if (DestTy == IceType_i64) { |
| 4589 auto *TmpReg64 = llvm::cast<Variable64On32>(TmpReg); | 4573 auto *TmpReg64 = llvm::cast<Variable64On32>(TmpReg); |
| 4590 auto *Expected64 = llvm::cast<Variable64On32>(Expected); | 4574 auto *Expected64 = llvm::cast<Variable64On32>(Expected); |
| 4591 _mov_redefined(Expected64->getHi(), TmpReg64->getHi(), CondARM32::NE); | 4575 _mov_redefined(Expected64->getHi(), TmpReg64->getHi(), CondARM32::NE); |
| 4592 _mov_redefined(Expected64->getLo(), TmpReg64->getLo(), CondARM32::NE); | 4576 _mov_redefined(Expected64->getLo(), TmpReg64->getLo(), CondARM32::NE); |
| 4593 auto *FakeDef = InstFakeDef::create(Func, Expected, TmpReg); | 4577 Context.insert<InstFakeDef>(Expected, TmpReg); |
| 4594 Context.insert(FakeDef); | 4578 _set_dest_redefined(); |
| 4595 FakeDef->setDestRedefined(); | |
| 4596 } else { | 4579 } else { |
| 4597 _mov_redefined(Expected, TmpReg, CondARM32::NE); | 4580 _mov_redefined(Expected, TmpReg, CondARM32::NE); |
| 4598 } | 4581 } |
| 4599 _cmp(Success, _0, CondARM32::EQ); | 4582 _cmp(Success, _0, CondARM32::EQ); |
| 4600 _br(Retry, CondARM32::NE); | 4583 _br(Retry, CondARM32::NE); |
| 4601 _dmb(); | 4584 _dmb(); |
| 4602 lowerAssign(InstAssign::create(Func, Dest, Expected)); | 4585 lowerAssign(InstAssign::create(Func, Dest, Expected)); |
| 4603 Context.insert(InstFakeUse::create(Func, Expected)); | 4586 Context.insert<InstFakeUse>(Expected); |
| 4604 if (auto *New64 = llvm::dyn_cast<Variable64On32>(New)) { | 4587 if (auto *New64 = llvm::dyn_cast<Variable64On32>(New)) { |
| 4605 Context.insert(InstFakeUse::create(Func, New64->getLo())); | 4588 Context.insert<InstFakeUse>(New64->getLo()); |
| 4606 Context.insert(InstFakeUse::create(Func, New64->getHi())); | 4589 Context.insert<InstFakeUse>(New64->getHi()); |
| 4607 } else { | 4590 } else { |
| 4608 Context.insert(InstFakeUse::create(Func, New)); | 4591 Context.insert<InstFakeUse>(New); |
| 4609 } | 4592 } |
| 4610 return; | 4593 return; |
| 4611 } | 4594 } |
| 4612 case Intrinsics::AtomicRMW: { | 4595 case Intrinsics::AtomicRMW: { |
| 4613 if (!Intrinsics::isMemoryOrderValid( | 4596 if (!Intrinsics::isMemoryOrderValid( |
| 4614 ID, getConstantMemoryOrder(Instr->getArg(3)))) { | 4597 ID, getConstantMemoryOrder(Instr->getArg(3)))) { |
| 4615 Func->setError("Unexpected memory ordering for AtomicRMW"); | 4598 Func->setError("Unexpected memory ordering for AtomicRMW"); |
| 4616 return; | 4599 return; |
| 4617 } | 4600 } |
| 4618 lowerAtomicRMW( | 4601 lowerAtomicRMW( |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4690 ValLoR = T; | 4673 ValLoR = T; |
| 4691 } | 4674 } |
| 4692 lowerCLZ(Dest, ValLoR, ValHiR); | 4675 lowerCLZ(Dest, ValLoR, ValHiR); |
| 4693 return; | 4676 return; |
| 4694 } | 4677 } |
| 4695 case Intrinsics::Fabs: { | 4678 case Intrinsics::Fabs: { |
| 4696 Type DestTy = Dest->getType(); | 4679 Type DestTy = Dest->getType(); |
| 4697 Variable *T = makeReg(DestTy); | 4680 Variable *T = makeReg(DestTy); |
| 4698 if (isVectorType(DestTy)) { | 4681 if (isVectorType(DestTy)) { |
| 4699 // Add a fake def to keep liveness consistent in the meantime. | 4682 // Add a fake def to keep liveness consistent in the meantime. |
| 4700 Context.insert(InstFakeDef::create(Func, T)); | 4683 Context.insert<InstFakeDef>(T); |
| 4701 _mov(Dest, T); | 4684 _mov(Dest, T); |
| 4702 UnimplementedError(Func->getContext()->getFlags()); | 4685 UnimplementedError(Func->getContext()->getFlags()); |
| 4703 return; | 4686 return; |
| 4704 } | 4687 } |
| 4705 _vabs(T, legalizeToReg(Instr->getArg(0))); | 4688 _vabs(T, legalizeToReg(Instr->getArg(0))); |
| 4706 _mov(Dest, T); | 4689 _mov(Dest, T); |
| 4707 return; | 4690 return; |
| 4708 } | 4691 } |
| 4709 case Intrinsics::Longjmp: { | 4692 case Intrinsics::Longjmp: { |
| 4710 llvm::report_fatal_error("longjmp should have been prelowered."); | 4693 llvm::report_fatal_error("longjmp should have been prelowered."); |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5155 // [OffsetReg{, LSL Shamt}{, #OffsetImm}] is not legal in ARM, so we have to | 5138 // [OffsetReg{, LSL Shamt}{, #OffsetImm}] is not legal in ARM, so we have to |
| 5156 // legalize the addressing mode to [BaseReg, OffsetReg{, LSL Shamt}]. | 5139 // legalize the addressing mode to [BaseReg, OffsetReg{, LSL Shamt}]. |
| 5157 // Instead of a zeroed BaseReg, we initialize it with OffsetImm: | 5140 // Instead of a zeroed BaseReg, we initialize it with OffsetImm: |
| 5158 // | 5141 // |
| 5159 // [OffsetReg{, LSL Shamt}{, #OffsetImm}] -> | 5142 // [OffsetReg{, LSL Shamt}{, #OffsetImm}] -> |
| 5160 // mov BaseReg, #OffsetImm | 5143 // mov BaseReg, #OffsetImm |
| 5161 // use of [BaseReg, OffsetReg{, LSL Shamt}] | 5144 // use of [BaseReg, OffsetReg{, LSL Shamt}] |
| 5162 // | 5145 // |
| 5163 const Type PointerType = getPointerType(); | 5146 const Type PointerType = getPointerType(); |
| 5164 BaseVar = makeReg(PointerType); | 5147 BaseVar = makeReg(PointerType); |
| 5165 Context.insert( | 5148 Context.insert<InstAssign>(BaseVar, Ctx->getConstantInt32(OffsetImm)); |
| 5166 InstAssign::create(Func, BaseVar, Ctx->getConstantInt32(OffsetImm))); | |
| 5167 OffsetImm = 0; | 5149 OffsetImm = 0; |
| 5168 } else if (OffsetImm != 0) { | 5150 } else if (OffsetImm != 0) { |
| 5169 // ARM Ldr/Str instructions have limited range immediates. The formation | 5151 // ARM Ldr/Str instructions have limited range immediates. The formation |
| 5170 // loop above materialized an Immediate carelessly, so we ensure the | 5152 // loop above materialized an Immediate carelessly, so we ensure the |
| 5171 // generated offset is sane. | 5153 // generated offset is sane. |
| 5172 const int32_t PositiveOffset = OffsetImm > 0 ? OffsetImm : -OffsetImm; | 5154 const int32_t PositiveOffset = OffsetImm > 0 ? OffsetImm : -OffsetImm; |
| 5173 const InstArithmetic::OpKind Op = | 5155 const InstArithmetic::OpKind Op = |
| 5174 OffsetImm > 0 ? InstArithmetic::Add : InstArithmetic::Sub; | 5156 OffsetImm > 0 ? InstArithmetic::Add : InstArithmetic::Sub; |
| 5175 | 5157 |
| 5176 if (!CanHaveImm || !isLegalMemOffset(Ty, OffsetImm) || | 5158 if (!CanHaveImm || !isLegalMemOffset(Ty, OffsetImm) || |
| (...skipping 10 matching lines...) Expand all Loading... |
| 5187 // here and don't form any address mode. | 5169 // here and don't form any address mode. |
| 5188 return nullptr; | 5170 return nullptr; |
| 5189 } | 5171 } |
| 5190 // We formed [Base, Offset {, LSL Amnt}, #const]. Oops. Legalize it to | 5172 // We formed [Base, Offset {, LSL Amnt}, #const]. Oops. Legalize it to |
| 5191 // | 5173 // |
| 5192 // [Base, Offset, {LSL amount}, #const] -> | 5174 // [Base, Offset, {LSL amount}, #const] -> |
| 5193 // add T, Base, #const | 5175 // add T, Base, #const |
| 5194 // use of [T, Offset {, LSL amount}] | 5176 // use of [T, Offset {, LSL amount}] |
| 5195 const Type PointerType = getPointerType(); | 5177 const Type PointerType = getPointerType(); |
| 5196 Variable *T = makeReg(PointerType); | 5178 Variable *T = makeReg(PointerType); |
| 5197 Context.insert(InstArithmetic::create( | 5179 Context.insert<InstArithmetic>(Op, T, BaseVar, |
| 5198 Func, Op, T, BaseVar, Ctx->getConstantInt32(PositiveOffset))); | 5180 Ctx->getConstantInt32(PositiveOffset)); |
| 5199 BaseVar = T; | 5181 BaseVar = T; |
| 5200 OffsetImm = 0; | 5182 OffsetImm = 0; |
| 5201 } | 5183 } |
| 5202 } | 5184 } |
| 5203 | 5185 |
| 5204 assert(BaseVar != nullptr); | 5186 assert(BaseVar != nullptr); |
| 5205 assert(OffsetImm == 0 || OffsetReg == nullptr); | 5187 assert(OffsetImm == 0 || OffsetReg == nullptr); |
| 5206 assert(OffsetReg == nullptr || CanHaveIndex); | 5188 assert(OffsetReg == nullptr || CanHaveIndex); |
| 5207 assert(OffsetImm < 0 ? (ValidImmMask & -OffsetImm) == -OffsetImm | 5189 assert(OffsetImm < 0 ? (ValidImmMask & -OffsetImm) == -OffsetImm |
| 5208 : (ValidImmMask & OffsetImm) == OffsetImm); | 5190 : (ValidImmMask & OffsetImm) == OffsetImm); |
| 5209 | 5191 |
| 5210 if (OffsetReg != nullptr) { | 5192 if (OffsetReg != nullptr) { |
| 5211 Variable *OffsetR = makeReg(getPointerType()); | 5193 Variable *OffsetR = makeReg(getPointerType()); |
| 5212 Context.insert(InstAssign::create(Func, OffsetR, OffsetReg)); | 5194 Context.insert<InstAssign>(OffsetR, OffsetReg); |
| 5213 return OperandARM32Mem::create(Func, Ty, BaseVar, OffsetR, ShiftKind, | 5195 return OperandARM32Mem::create(Func, Ty, BaseVar, OffsetR, ShiftKind, |
| 5214 OffsetRegShamt); | 5196 OffsetRegShamt); |
| 5215 } | 5197 } |
| 5216 | 5198 |
| 5217 return OperandARM32Mem::create( | 5199 return OperandARM32Mem::create( |
| 5218 Func, Ty, BaseVar, | 5200 Func, Ty, BaseVar, |
| 5219 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(OffsetImm))); | 5201 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(OffsetImm))); |
| 5220 } | 5202 } |
| 5221 | 5203 |
| 5222 void TargetARM32::doAddressOptLoad() { | 5204 void TargetARM32::doAddressOptLoad() { |
| 5223 Inst *Instr = Context.getCur(); | 5205 Inst *Instr = Context.getCur(); |
| 5224 assert(llvm::isa<InstLoad>(Instr)); | 5206 assert(llvm::isa<InstLoad>(Instr)); |
| 5225 Variable *Dest = Instr->getDest(); | 5207 Variable *Dest = Instr->getDest(); |
| 5226 Operand *Addr = Instr->getSrc(0); | 5208 Operand *Addr = Instr->getSrc(0); |
| 5227 if (OperandARM32Mem *Mem = | 5209 if (OperandARM32Mem *Mem = |
| 5228 formAddressingMode(Dest->getType(), Func, Instr, Addr)) { | 5210 formAddressingMode(Dest->getType(), Func, Instr, Addr)) { |
| 5229 Instr->setDeleted(); | 5211 Instr->setDeleted(); |
| 5230 Context.insert(InstLoad::create(Func, Dest, Mem)); | 5212 Context.insert<InstLoad>(Dest, Mem); |
| 5231 } | 5213 } |
| 5232 } | 5214 } |
| 5233 | 5215 |
| 5234 void TargetARM32::randomlyInsertNop(float Probability, | 5216 void TargetARM32::randomlyInsertNop(float Probability, |
| 5235 RandomNumberGenerator &RNG) { | 5217 RandomNumberGenerator &RNG) { |
| 5236 RandomNumberGeneratorWrapper RNGW(RNG); | 5218 RandomNumberGeneratorWrapper RNGW(RNG); |
| 5237 if (RNGW.getTrueWithProbability(Probability)) { | 5219 if (RNGW.getTrueWithProbability(Probability)) { |
| 5238 UnimplementedError(Func->getContext()->getFlags()); | 5220 UnimplementedError(Func->getContext()->getFlags()); |
| 5239 } | 5221 } |
| 5240 } | 5222 } |
| 5241 | 5223 |
| 5242 void TargetARM32::lowerPhi(const InstPhi * /*Inst*/) { | 5224 void TargetARM32::lowerPhi(const InstPhi * /*Inst*/) { |
| 5243 Func->setError("Phi found in regular instruction list"); | 5225 Func->setError("Phi found in regular instruction list"); |
| 5244 } | 5226 } |
| 5245 | 5227 |
| 5246 void TargetARM32::lowerRet(const InstRet *Inst) { | 5228 void TargetARM32::lowerRet(const InstRet *Inst) { |
| 5247 Variable *Reg = nullptr; | 5229 Variable *Reg = nullptr; |
| 5248 if (Inst->hasRetValue()) { | 5230 if (Inst->hasRetValue()) { |
| 5249 Operand *Src0 = Inst->getRetValue(); | 5231 Operand *Src0 = Inst->getRetValue(); |
| 5250 Type Ty = Src0->getType(); | 5232 Type Ty = Src0->getType(); |
| 5251 if (Ty == IceType_i64) { | 5233 if (Ty == IceType_i64) { |
| 5252 Src0 = legalizeUndef(Src0); | 5234 Src0 = legalizeUndef(Src0); |
| 5253 Variable *R0 = legalizeToReg(loOperand(Src0), RegARM32::Reg_r0); | 5235 Variable *R0 = legalizeToReg(loOperand(Src0), RegARM32::Reg_r0); |
| 5254 Variable *R1 = legalizeToReg(hiOperand(Src0), RegARM32::Reg_r1); | 5236 Variable *R1 = legalizeToReg(hiOperand(Src0), RegARM32::Reg_r1); |
| 5255 Reg = R0; | 5237 Reg = R0; |
| 5256 Context.insert(InstFakeUse::create(Func, R1)); | 5238 Context.insert<InstFakeUse>(R1); |
| 5257 } else if (Ty == IceType_f32) { | 5239 } else if (Ty == IceType_f32) { |
| 5258 Variable *S0 = legalizeToReg(Src0, RegARM32::Reg_s0); | 5240 Variable *S0 = legalizeToReg(Src0, RegARM32::Reg_s0); |
| 5259 Reg = S0; | 5241 Reg = S0; |
| 5260 } else if (Ty == IceType_f64) { | 5242 } else if (Ty == IceType_f64) { |
| 5261 Variable *D0 = legalizeToReg(Src0, RegARM32::Reg_d0); | 5243 Variable *D0 = legalizeToReg(Src0, RegARM32::Reg_d0); |
| 5262 Reg = D0; | 5244 Reg = D0; |
| 5263 } else if (isVectorType(Src0->getType())) { | 5245 } else if (isVectorType(Src0->getType())) { |
| 5264 Variable *Q0 = legalizeToReg(Src0, RegARM32::Reg_q0); | 5246 Variable *Q0 = legalizeToReg(Src0, RegARM32::Reg_q0); |
| 5265 Reg = Q0; | 5247 Reg = Q0; |
| 5266 } else { | 5248 } else { |
| 5267 Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex); | 5249 Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex); |
| 5268 Reg = makeReg(Src0F->getType(), RegARM32::Reg_r0); | 5250 Reg = makeReg(Src0F->getType(), RegARM32::Reg_r0); |
| 5269 _mov(Reg, Src0F, CondARM32::AL); | 5251 _mov(Reg, Src0F, CondARM32::AL); |
| 5270 } | 5252 } |
| 5271 } | 5253 } |
| 5272 // Add a ret instruction even if sandboxing is enabled, because addEpilog | 5254 // Add a ret instruction even if sandboxing is enabled, because addEpilog |
| 5273 // explicitly looks for a ret instruction as a marker for where to insert the | 5255 // explicitly looks for a ret instruction as a marker for where to insert the |
| 5274 // frame removal instructions. addEpilog is responsible for restoring the | 5256 // frame removal instructions. addEpilog is responsible for restoring the |
| 5275 // "lr" register as needed prior to this ret instruction. | 5257 // "lr" register as needed prior to this ret instruction. |
| 5276 _ret(getPhysicalRegister(RegARM32::Reg_lr), Reg); | 5258 _ret(getPhysicalRegister(RegARM32::Reg_lr), Reg); |
| 5277 | 5259 |
| 5278 // Add a fake use of sp to make sure sp stays alive for the entire function. | 5260 // Add a fake use of sp to make sure sp stays alive for the entire function. |
| 5279 // Otherwise post-call sp adjustments get dead-code eliminated. | 5261 // Otherwise post-call sp adjustments get dead-code eliminated. |
| 5280 // TODO: Are there more places where the fake use should be inserted? E.g. | 5262 // TODO: Are there more places where the fake use should be inserted? E.g. |
| 5281 // "void f(int n){while(1) g(n);}" may not have a ret instruction. | 5263 // "void f(int n){while(1) g(n);}" may not have a ret instruction. |
| 5282 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 5264 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| 5283 Context.insert(InstFakeUse::create(Func, SP)); | 5265 Context.insert<InstFakeUse>(SP); |
| 5284 } | 5266 } |
| 5285 | 5267 |
| 5286 void TargetARM32::lowerSelect(const InstSelect *Inst) { | 5268 void TargetARM32::lowerSelect(const InstSelect *Inst) { |
| 5287 Variable *Dest = Inst->getDest(); | 5269 Variable *Dest = Inst->getDest(); |
| 5288 Type DestTy = Dest->getType(); | 5270 Type DestTy = Dest->getType(); |
| 5289 Operand *SrcT = Inst->getTrueOperand(); | 5271 Operand *SrcT = Inst->getTrueOperand(); |
| 5290 Operand *SrcF = Inst->getFalseOperand(); | 5272 Operand *SrcF = Inst->getFalseOperand(); |
| 5291 Operand *Condition = Inst->getCondition(); | 5273 Operand *Condition = Inst->getCondition(); |
| 5292 | 5274 |
| 5293 if (isVectorType(DestTy)) { | 5275 if (isVectorType(DestTy)) { |
| 5294 Variable *T = makeReg(DestTy); | 5276 Variable *T = makeReg(DestTy); |
| 5295 Context.insert(InstFakeDef::create(Func, T)); | 5277 Context.insert<InstFakeDef>(T); |
| 5296 _mov(Dest, T); | 5278 _mov(Dest, T); |
| 5297 UnimplementedError(Func->getContext()->getFlags()); | 5279 UnimplementedError(Func->getContext()->getFlags()); |
| 5298 return; | 5280 return; |
| 5299 } | 5281 } |
| 5300 | 5282 |
| 5301 lowerInt1ForSelect(Dest, Condition, legalizeUndef(SrcT), legalizeUndef(SrcF)); | 5283 lowerInt1ForSelect(Dest, Condition, legalizeUndef(SrcT), legalizeUndef(SrcF)); |
| 5302 } | 5284 } |
| 5303 | 5285 |
| 5304 void TargetARM32::lowerStore(const InstStore *Inst) { | 5286 void TargetARM32::lowerStore(const InstStore *Inst) { |
| 5305 Operand *Value = Inst->getData(); | 5287 Operand *Value = Inst->getData(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 5320 } | 5302 } |
| 5321 | 5303 |
| 5322 void TargetARM32::doAddressOptStore() { | 5304 void TargetARM32::doAddressOptStore() { |
| 5323 Inst *Instr = Context.getCur(); | 5305 Inst *Instr = Context.getCur(); |
| 5324 assert(llvm::isa<InstStore>(Instr)); | 5306 assert(llvm::isa<InstStore>(Instr)); |
| 5325 Operand *Src = Instr->getSrc(0); | 5307 Operand *Src = Instr->getSrc(0); |
| 5326 Operand *Addr = Instr->getSrc(1); | 5308 Operand *Addr = Instr->getSrc(1); |
| 5327 if (OperandARM32Mem *Mem = | 5309 if (OperandARM32Mem *Mem = |
| 5328 formAddressingMode(Src->getType(), Func, Instr, Addr)) { | 5310 formAddressingMode(Src->getType(), Func, Instr, Addr)) { |
| 5329 Instr->setDeleted(); | 5311 Instr->setDeleted(); |
| 5330 Context.insert(InstStore::create(Func, Src, Mem)); | 5312 Context.insert<InstStore>(Src, Mem); |
| 5331 } | 5313 } |
| 5332 } | 5314 } |
| 5333 | 5315 |
| 5334 void TargetARM32::lowerSwitch(const InstSwitch *Inst) { | 5316 void TargetARM32::lowerSwitch(const InstSwitch *Inst) { |
| 5335 // This implements the most naive possible lowering. | 5317 // This implements the most naive possible lowering. |
| 5336 // cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default | 5318 // cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default |
| 5337 Operand *Src0 = Inst->getComparison(); | 5319 Operand *Src0 = Inst->getComparison(); |
| 5338 SizeT NumCases = Inst->getNumCases(); | 5320 SizeT NumCases = Inst->getNumCases(); |
| 5339 if (Src0->getType() == IceType_i64) { | 5321 if (Src0->getType() == IceType_i64) { |
| 5340 Src0 = legalizeUndef(Src0); | 5322 Src0 = legalizeUndef(Src0); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5378 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Inst*/) { | 5360 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Inst*/) { |
| 5379 _trap(); | 5361 _trap(); |
| 5380 } | 5362 } |
| 5381 | 5363 |
| 5382 void TargetARM32::prelowerPhis() { | 5364 void TargetARM32::prelowerPhis() { |
| 5383 PhiLowering::prelowerPhis32Bit<TargetARM32>(this, Context.getNode(), Func); | 5365 PhiLowering::prelowerPhis32Bit<TargetARM32>(this, Context.getNode(), Func); |
| 5384 } | 5366 } |
| 5385 | 5367 |
| 5386 Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) { | 5368 Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) { |
| 5387 Variable *Reg = makeReg(Ty, RegNum); | 5369 Variable *Reg = makeReg(Ty, RegNum); |
| 5388 Context.insert(InstFakeDef::create(Func, Reg)); | 5370 Context.insert<InstFakeDef>(Reg); |
| 5389 UnimplementedError(Func->getContext()->getFlags()); | 5371 UnimplementedError(Func->getContext()->getFlags()); |
| 5390 return Reg; | 5372 return Reg; |
| 5391 } | 5373 } |
| 5392 | 5374 |
| 5393 // Helper for legalize() to emit the right code to lower an operand to a | 5375 // Helper for legalize() to emit the right code to lower an operand to a |
| 5394 // register of the appropriate type. | 5376 // register of the appropriate type. |
| 5395 Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { | 5377 Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { |
| 5396 Type Ty = Src->getType(); | 5378 Type Ty = Src->getType(); |
| 5397 Variable *Reg = makeReg(Ty, RegNum); | 5379 Variable *Reg = makeReg(Ty, RegNum); |
| 5398 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Src)) { | 5380 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Src)) { |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5552 Variable *T = makeReg(Ty, RegNum); | 5534 Variable *T = makeReg(Ty, RegNum); |
| 5553 _mov(T, | 5535 _mov(T, |
| 5554 OperandARM32FlexFpImm::create(Func, From->getType(), ModifiedImm)); | 5536 OperandARM32FlexFpImm::create(Func, From->getType(), ModifiedImm)); |
| 5555 return T; | 5537 return T; |
| 5556 } | 5538 } |
| 5557 | 5539 |
| 5558 if (Ty == IceType_f64 && isFloatingPointZero(From)) { | 5540 if (Ty == IceType_f64 && isFloatingPointZero(From)) { |
| 5559 // Use T = T ^ T to load a 64-bit fp zero. This does not work for f32 | 5541 // Use T = T ^ T to load a 64-bit fp zero. This does not work for f32 |
| 5560 // because ARM does not have a veor instruction with S registers. | 5542 // because ARM does not have a veor instruction with S registers. |
| 5561 Variable *T = makeReg(IceType_f64, RegNum); | 5543 Variable *T = makeReg(IceType_f64, RegNum); |
| 5562 Context.insert(InstFakeDef::create(Func, T)); | 5544 Context.insert<InstFakeDef>(T); |
| 5563 _veor(T, T, T); | 5545 _veor(T, T, T); |
| 5564 return T; | 5546 return T; |
| 5565 } | 5547 } |
| 5566 | 5548 |
| 5567 // Load floats/doubles from literal pool. | 5549 // Load floats/doubles from literal pool. |
| 5568 std::string Buffer; | 5550 std::string Buffer; |
| 5569 llvm::raw_string_ostream StrBuf(Buffer); | 5551 llvm::raw_string_ostream StrBuf(Buffer); |
| 5570 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx); | 5552 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx); |
| 5571 llvm::cast<Constant>(From)->setShouldBePooled(true); | 5553 llvm::cast<Constant>(From)->setShouldBePooled(true); |
| 5572 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); | 5554 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); |
| (...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6180 } | 6162 } |
| 6181 | 6163 |
| 6182 InstARM32Call *TargetARM32::Sandboxer::bl(Variable *ReturnReg, | 6164 InstARM32Call *TargetARM32::Sandboxer::bl(Variable *ReturnReg, |
| 6183 Operand *CallTarget) { | 6165 Operand *CallTarget) { |
| 6184 if (Target->NeedSandboxing) { | 6166 if (Target->NeedSandboxing) { |
| 6185 if (auto *CallTargetR = llvm::dyn_cast<Variable>(CallTarget)) { | 6167 if (auto *CallTargetR = llvm::dyn_cast<Variable>(CallTarget)) { |
| 6186 Target->_bic(CallTargetR, CallTargetR, | 6168 Target->_bic(CallTargetR, CallTargetR, |
| 6187 indirectBranchBicMask(Target->Func)); | 6169 indirectBranchBicMask(Target->Func)); |
| 6188 } | 6170 } |
| 6189 } | 6171 } |
| 6190 auto *Call = InstARM32Call::create(Target->Func, ReturnReg, CallTarget); | 6172 return Target->Context.insert<InstARM32Call>(ReturnReg, CallTarget); |
| 6191 Target->Context.insert(Call); | |
| 6192 return Call; | |
| 6193 } | 6173 } |
| 6194 | 6174 |
| 6195 void TargetARM32::Sandboxer::ldr(Variable *Dest, OperandARM32Mem *Mem, | 6175 void TargetARM32::Sandboxer::ldr(Variable *Dest, OperandARM32Mem *Mem, |
| 6196 CondARM32::Cond Pred) { | 6176 CondARM32::Cond Pred) { |
| 6197 Variable *MemBase = Mem->getBase(); | 6177 Variable *MemBase = Mem->getBase(); |
| 6198 if (Target->NeedSandboxing && baseNeedsBic(MemBase)) { | 6178 if (Target->NeedSandboxing && baseNeedsBic(MemBase)) { |
| 6199 assert(!Mem->isRegReg()); | 6179 assert(!Mem->isRegReg()); |
| 6200 Target->_bic(MemBase, MemBase, memOpBicMask(Target->Func), Pred); | 6180 Target->_bic(MemBase, MemBase, memOpBicMask(Target->Func), Pred); |
| 6201 } | 6181 } |
| 6202 Target->_ldr(Dest, Mem, Pred); | 6182 Target->_ldr(Dest, Mem, Pred); |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6443 // Technically R9 is used for TLS with Sandboxing, and we reserve it. | 6423 // Technically R9 is used for TLS with Sandboxing, and we reserve it. |
| 6444 // However, for compatibility with current NaCl LLVM, don't claim that. | 6424 // However, for compatibility with current NaCl LLVM, don't claim that. |
| 6445 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 6425 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
| 6446 } | 6426 } |
| 6447 | 6427 |
| 6448 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; | 6428 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; |
| 6449 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; | 6429 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; |
| 6450 llvm::SmallBitVector TargetARM32::ScratchRegs; | 6430 llvm::SmallBitVector TargetARM32::ScratchRegs; |
| 6451 | 6431 |
| 6452 } // end of namespace Ice | 6432 } // end of namespace Ice |
| OLD | NEW |