Chromium Code Reviews| 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 // This file implements the TargetLoweringARM32 class, which consists almost | 10 // This file implements the TargetLoweringARM32 class, which consists almost |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 32 | 32 |
| 33 namespace { | 33 namespace { |
| 34 void UnimplementedError(const ClFlags &Flags) { | 34 void UnimplementedError(const ClFlags &Flags) { |
| 35 if (!Flags.getSkipUnimplemented()) { | 35 if (!Flags.getSkipUnimplemented()) { |
| 36 // Use llvm_unreachable instead of report_fatal_error, which gives better | 36 // Use llvm_unreachable instead of report_fatal_error, which gives better |
| 37 // stack traces. | 37 // stack traces. |
| 38 llvm_unreachable("Not yet implemented"); | 38 llvm_unreachable("Not yet implemented"); |
| 39 abort(); | 39 abort(); |
| 40 } | 40 } |
| 41 } | 41 } |
| 42 | |
| 43 // The maximum number of arguments to pass in GPR registers. | |
| 44 const uint32_t ARM32_MAX_GPR_ARG = 4; | |
| 45 | |
| 42 } // end of anonymous namespace | 46 } // end of anonymous namespace |
| 43 | 47 |
| 44 TargetARM32::TargetARM32(Cfg *Func) | 48 TargetARM32::TargetARM32(Cfg *Func) |
| 45 : TargetLowering(Func), UsesFramePointer(false) { | 49 : TargetLowering(Func), UsesFramePointer(false) { |
| 46 // TODO: Don't initialize IntegerRegisters and friends every time. | 50 // TODO: Don't initialize IntegerRegisters and friends every time. |
| 47 // Instead, initialize in some sort of static initializer for the | 51 // Instead, initialize in some sort of static initializer for the |
| 48 // class. | 52 // class. |
| 49 llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM); | 53 llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM); |
| 50 llvm::SmallBitVector FloatRegisters(RegARM32::Reg_NUM); | 54 llvm::SmallBitVector FloatRegisters(RegARM32::Reg_NUM); |
| 51 llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM); | 55 llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM); |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 268 int32_t Offset = Var->getStackOffset(); | 272 int32_t Offset = Var->getStackOffset(); |
| 269 if (!hasFramePointer()) | 273 if (!hasFramePointer()) |
| 270 Offset += getStackAdjustment(); | 274 Offset += getStackAdjustment(); |
| 271 // TODO(jvoung): Handle out of range. Perhaps we need a scratch register | 275 // TODO(jvoung): Handle out of range. Perhaps we need a scratch register |
| 272 // to materialize a larger offset. | 276 // to materialize a larger offset. |
| 273 const bool SignExt = false; | 277 const bool SignExt = false; |
| 274 if (!OperandARM32Mem::canHoldOffset(Var->getType(), SignExt, Offset)) { | 278 if (!OperandARM32Mem::canHoldOffset(Var->getType(), SignExt, Offset)) { |
| 275 llvm::report_fatal_error("Illegal stack offset"); | 279 llvm::report_fatal_error("Illegal stack offset"); |
| 276 } | 280 } |
| 277 const Type FrameSPTy = IceType_i32; | 281 const Type FrameSPTy = IceType_i32; |
| 278 Str << "[" << getRegName(getFrameOrStackReg(), FrameSPTy) << ", " << Offset | 282 Str << "[" << getRegName(getFrameOrStackReg(), FrameSPTy); |
| 279 << "]"; | 283 if (Offset != 0) { |
| 284 Str << ", " << getConstantPrefix() << Offset; | |
| 285 } | |
| 286 Str << "]"; | |
| 280 } | 287 } |
| 281 | 288 |
| 282 void TargetARM32::lowerArguments() { | 289 void TargetARM32::lowerArguments() { |
| 283 UnimplementedError(Func->getContext()->getFlags()); | 290 VarList &Args = Func->getArgs(); |
| 291 // The first few integer type parameters can use r0-r3, regardless of their | |
| 292 // position relative to the floating-point/vector arguments in the argument | |
| 293 // list. Floating-point and vector arguments can use q0-q3 (aka d0-d7, | |
| 294 // s0-s15). | |
| 295 unsigned NumGPRRegsUsed = 0; | |
| 296 | |
| 297 // For each register argument, replace Arg in the argument list with the | |
| 298 // home register. Then generate an instruction in the prolog to copy the | |
| 299 // home register to the assigned location of Arg. | |
| 300 Context.init(Func->getEntryNode()); | |
| 301 Context.setInsertPoint(Context.getCur()); | |
| 302 | |
| 303 for (SizeT I = 0, E = Args.size(); I < E; ++I) { | |
| 304 Variable *Arg = Args[I]; | |
| 305 Type Ty = Arg->getType(); | |
| 306 // TODO(jvoung): handle float/vector types. | |
| 307 if (isVectorType(Ty)) { | |
| 308 UnimplementedError(Func->getContext()->getFlags()); | |
| 309 continue; | |
| 310 } else if (isFloatingType(Ty)) { | |
| 311 UnimplementedError(Func->getContext()->getFlags()); | |
| 312 continue; | |
| 313 } else if (Ty == IceType_i64) { | |
| 314 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) | |
| 315 continue; | |
| 316 int32_t RegLo = RegARM32::Reg_r0 + NumGPRRegsUsed; | |
| 317 int32_t RegHi = 0; | |
| 318 ++NumGPRRegsUsed; | |
| 319 // Always start i64 registers at an even register, so this may end | |
| 320 // up padding away a register. | |
| 321 if (RegLo % 2 != 0) { | |
| 322 ++RegLo; | |
| 323 ++NumGPRRegsUsed; | |
| 324 } | |
| 325 // If this leaves us without room to consume another register, | |
| 326 // leave any previously speculatively consumed registers as consumed. | |
| 327 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) | |
| 328 continue; | |
| 329 RegHi = RegARM32::Reg_r0 + NumGPRRegsUsed; | |
| 330 ++NumGPRRegsUsed; | |
| 331 Variable *RegisterArg = Func->makeVariable(Ty); | |
| 332 Variable *RegisterLo = Func->makeVariable(IceType_i32); | |
| 333 Variable *RegisterHi = Func->makeVariable(IceType_i32); | |
| 334 if (ALLOW_DUMP) { | |
| 335 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); | |
| 336 RegisterLo->setName(Func, "home_reg_lo:" + Arg->getName(Func)); | |
| 337 RegisterHi->setName(Func, "home_reg_hi:" + Arg->getName(Func)); | |
| 338 } | |
| 339 RegisterLo->setRegNum(RegLo); | |
| 340 RegisterLo->setIsArg(); | |
| 341 RegisterHi->setRegNum(RegHi); | |
| 342 RegisterHi->setIsArg(); | |
| 343 RegisterArg->setLoHi(RegisterLo, RegisterHi); | |
| 344 RegisterArg->setIsArg(); | |
| 345 Arg->setIsArg(false); | |
| 346 | |
| 347 Args[I] = RegisterArg; | |
| 348 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); | |
| 349 continue; | |
| 350 } else { | |
| 351 assert(Ty == IceType_i32); | |
| 352 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) | |
| 353 continue; | |
| 354 int32_t RegNum = RegARM32::Reg_r0 + NumGPRRegsUsed; | |
| 355 ++NumGPRRegsUsed; | |
| 356 Variable *RegisterArg = Func->makeVariable(Ty); | |
| 357 if (ALLOW_DUMP) { | |
| 358 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); | |
| 359 } | |
| 360 RegisterArg->setRegNum(RegNum); | |
| 361 RegisterArg->setIsArg(); | |
| 362 Arg->setIsArg(false); | |
| 363 | |
| 364 Args[I] = RegisterArg; | |
| 365 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); | |
| 366 } | |
| 367 } | |
| 284 } | 368 } |
| 285 | 369 |
| 286 Type TargetARM32::stackSlotType() { return IceType_i32; } | 370 Type TargetARM32::stackSlotType() { return IceType_i32; } |
| 287 | 371 |
| 288 void TargetARM32::addProlog(CfgNode *Node) { | 372 void TargetARM32::addProlog(CfgNode *Node) { |
| 289 (void)Node; | 373 (void)Node; |
| 290 UnimplementedError(Func->getContext()->getFlags()); | 374 UnimplementedError(Func->getContext()->getFlags()); |
| 291 } | 375 } |
| 292 | 376 |
| 293 void TargetARM32::addEpilog(CfgNode *Node) { | 377 void TargetARM32::addEpilog(CfgNode *Node) { |
| 294 (void)Node; | 378 (void)Node; |
| 295 UnimplementedError(Func->getContext()->getFlags()); | 379 UnimplementedError(Func->getContext()->getFlags()); |
| 296 } | 380 } |
| 297 | 381 |
| 382 void TargetARM32::split64(Variable *Var) { | |
| 383 assert(Var->getType() == IceType_i64); | |
| 384 Variable *Lo = Var->getLo(); | |
| 385 Variable *Hi = Var->getHi(); | |
| 386 if (Lo) { | |
| 387 assert(Hi); | |
| 388 return; | |
| 389 } | |
| 390 assert(Hi == nullptr); | |
| 391 Lo = Func->makeVariable(IceType_i32); | |
| 392 Hi = Func->makeVariable(IceType_i32); | |
| 393 if (ALLOW_DUMP) { | |
| 394 Lo->setName(Func, Var->getName(Func) + "__lo"); | |
| 395 Hi->setName(Func, Var->getName(Func) + "__hi"); | |
| 396 } | |
| 397 Var->setLoHi(Lo, Hi); | |
| 398 if (Var->getIsArg()) { | |
| 399 Lo->setIsArg(); | |
| 400 Hi->setIsArg(); | |
| 401 } | |
| 402 } | |
| 403 | |
| 404 Operand *TargetARM32::loOperand(Operand *Operand) { | |
| 405 assert(Operand->getType() == IceType_i64); | |
| 406 if (Operand->getType() != IceType_i64) | |
| 407 return Operand; | |
| 408 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { | |
| 409 split64(Var); | |
| 410 return Var->getLo(); | |
| 411 } | |
| 412 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { | |
| 413 return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue())); | |
| 414 } | |
| 415 if (OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) { | |
| 416 // Conservatively disallow memory operands with side-effects (pre/post | |
| 417 // increment) in case of duplication. | |
| 418 assert(Mem->getAddrMode() == OperandARM32Mem::Offset || | |
| 419 Mem->getAddrMode() == OperandARM32Mem::NegOffset); | |
| 420 if (Mem->isRegReg()) { | |
| 421 return OperandARM32Mem::create(Func, IceType_i32, Mem->getBase(), | |
| 422 Mem->getIndex(), Mem->getShiftOp(), | |
| 423 Mem->getShiftAmt(), Mem->getAddrMode()); | |
| 424 } else { | |
| 425 return OperandARM32Mem::create(Func, IceType_i32, Mem->getBase(), | |
| 426 Mem->getOffset(), Mem->getAddrMode()); | |
| 427 } | |
| 428 } | |
| 429 llvm_unreachable("Unsupported operand type"); | |
| 430 return nullptr; | |
| 431 } | |
| 432 | |
| 433 Operand *TargetARM32::hiOperand(Operand *Operand) { | |
| 434 assert(Operand->getType() == IceType_i64); | |
| 435 if (Operand->getType() != IceType_i64) | |
| 436 return Operand; | |
| 437 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { | |
| 438 split64(Var); | |
| 439 return Var->getHi(); | |
| 440 } | |
| 441 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { | |
| 442 return Ctx->getConstantInt32( | |
| 443 static_cast<uint32_t>(Const->getValue() >> 32)); | |
| 444 } | |
| 445 if (OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) { | |
| 446 // Conservatively disallow memory operands with side-effects | |
| 447 // in case of duplication. | |
| 448 assert(Mem->getAddrMode() == OperandARM32Mem::Offset || | |
| 449 Mem->getAddrMode() == OperandARM32Mem::NegOffset); | |
| 450 const Type SplitType = IceType_i32; | |
| 451 if (Mem->isRegReg()) { | |
| 452 // We have to make a temp variable T, and add 4 to either Base or Index. | |
| 453 // The Index may be shifted, so adding 4 can mean something else. | |
| 454 // Thus, prefer T := Base + 4, and use T as the new Base. | |
| 455 Variable *Base = Mem->getBase(); | |
| 456 Constant *Four = Ctx->getConstantInt32(4); | |
| 457 Variable *NewBase = Func->makeVariable(Base->getType()); | |
| 458 lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add, NewBase, | |
| 459 Base, Four)); | |
| 460 return OperandARM32Mem::create(Func, SplitType, NewBase, Mem->getIndex(), | |
| 461 Mem->getShiftOp(), Mem->getShiftAmt(), | |
| 462 Mem->getAddrMode()); | |
| 463 } else { | |
| 464 Variable *Base = Mem->getBase(); | |
| 465 ConstantInteger32 *Offset = Mem->getOffset(); | |
| 466 assert(!Utils::WouldOverflowAdd(Offset->getValue(), 4)); | |
| 467 int32_t NextOffsetVal = Offset->getValue() + 4; | |
| 468 const bool SignExt = false; | |
| 469 if (!OperandARM32Mem::canHoldOffset(SplitType, SignExt, NextOffsetVal)) { | |
| 470 // We have to make a temp variable and add 4 to either Base or Offset. | |
| 471 // If we add 4 to Offset, this will convert a non-RegReg addressing | |
| 472 // mode into a RegReg addressing mode. Since NaCl sandboxing disallows | |
| 473 // RegReg addressing modes, prefer adding to base and replacing instead. | |
| 474 // Thus we leave the old offset alone. | |
| 475 Constant *Four = Ctx->getConstantInt32(4); | |
| 476 Variable *NewBase = Func->makeVariable(Base->getType()); | |
| 477 lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add, | |
| 478 NewBase, Base, Four)); | |
| 479 Base = NewBase; | |
| 480 } else { | |
| 481 Offset = | |
| 482 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(NextOffsetVal)); | |
| 483 } | |
| 484 return OperandARM32Mem::create(Func, SplitType, Base, Offset, | |
| 485 Mem->getAddrMode()); | |
| 486 } | |
| 487 } | |
| 488 llvm_unreachable("Unsupported operand type"); | |
| 489 return nullptr; | |
| 490 } | |
| 491 | |
| 298 llvm::SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include, | 492 llvm::SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include, |
| 299 RegSetMask Exclude) const { | 493 RegSetMask Exclude) const { |
| 300 llvm::SmallBitVector Registers(RegARM32::Reg_NUM); | 494 llvm::SmallBitVector Registers(RegARM32::Reg_NUM); |
| 301 | 495 |
| 302 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ | 496 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ |
| 303 isFP) \ | 497 isFP) \ |
| 304 if (scratch && (Include & RegSet_CallerSave)) \ | 498 if (scratch && (Include & RegSet_CallerSave)) \ |
| 305 Registers[RegARM32::val] = true; \ | 499 Registers[RegARM32::val] = true; \ |
| 306 if (preserved && (Include & RegSet_CalleeSave)) \ | 500 if (preserved && (Include & RegSet_CalleeSave)) \ |
| 307 Registers[RegARM32::val] = true; \ | 501 Registers[RegARM32::val] = true; \ |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 331 // adjustment operations implemented below assume that the stack is | 525 // adjustment operations implemented below assume that the stack is |
| 332 // aligned before the alloca. All the alloca code ensures that the | 526 // aligned before the alloca. All the alloca code ensures that the |
| 333 // stack alignment is preserved after the alloca. The stack alignment | 527 // stack alignment is preserved after the alloca. The stack alignment |
| 334 // restriction can be relaxed in some cases. | 528 // restriction can be relaxed in some cases. |
| 335 NeedsStackAlignment = true; | 529 NeedsStackAlignment = true; |
| 336 (void)Inst; | 530 (void)Inst; |
| 337 UnimplementedError(Func->getContext()->getFlags()); | 531 UnimplementedError(Func->getContext()->getFlags()); |
| 338 } | 532 } |
| 339 | 533 |
| 340 void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { | 534 void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { |
| 341 switch (Inst->getOp()) { | 535 Variable *Dest = Inst->getDest(); |
| 342 case InstArithmetic::_num: | 536 // TODO(jvoung): Should be able to flip Src0 and Src1 if it is easier |
| 343 llvm_unreachable("Unknown arithmetic operator"); | 537 // to legalize Src0 to flex or Src1 to flex and there is a reversible |
| 344 break; | 538 // instruction. E.g., reverse subtract with immediate, register vs |
| 345 case InstArithmetic::Add: | 539 // register, immediate. |
| 540 // Or it may be the case that the operands aren't swapped, but the | |
| 541 // bits can be flipped and a different operation applied. | |
| 542 // E.g., use BIC (bit clear) instead of AND for some masks. | |
| 543 Variable *Src0 = legalizeToVar(Inst->getSrc(0)); | |
| 544 Operand *Src1 = legalize(Inst->getSrc(1), Legal_Reg | Legal_Flex); | |
| 545 (void)Src0; | |
| 546 (void)Src1; | |
| 547 if (Dest->getType() == IceType_i64) { | |
| 346 UnimplementedError(Func->getContext()->getFlags()); | 548 UnimplementedError(Func->getContext()->getFlags()); |
| 347 break; | 549 } else if (isVectorType(Dest->getType())) { |
| 348 case InstArithmetic::And: | |
| 349 UnimplementedError(Func->getContext()->getFlags()); | 550 UnimplementedError(Func->getContext()->getFlags()); |
| 350 break; | 551 } else { // Dest->getType() is non-i64 scalar |
| 351 case InstArithmetic::Or: | 552 switch (Inst->getOp()) { |
| 352 UnimplementedError(Func->getContext()->getFlags()); | 553 case InstArithmetic::_num: |
| 353 break; | 554 llvm_unreachable("Unknown arithmetic operator"); |
| 354 case InstArithmetic::Xor: | 555 break; |
| 355 UnimplementedError(Func->getContext()->getFlags()); | 556 case InstArithmetic::Add: { |
| 356 break; | 557 UnimplementedError(Func->getContext()->getFlags()); |
| 357 case InstArithmetic::Sub: | 558 // Variable *T = makeReg(Dest->getType()); |
| 358 UnimplementedError(Func->getContext()->getFlags()); | 559 // _add(T, Src0, Src1); |
| 359 break; | 560 // _mov(Dest, T); |
| 360 case InstArithmetic::Mul: | 561 } break; |
| 361 UnimplementedError(Func->getContext()->getFlags()); | 562 case InstArithmetic::And: |
| 362 break; | 563 UnimplementedError(Func->getContext()->getFlags()); |
| 363 case InstArithmetic::Shl: | 564 break; |
| 364 UnimplementedError(Func->getContext()->getFlags()); | 565 case InstArithmetic::Or: |
| 365 break; | 566 UnimplementedError(Func->getContext()->getFlags()); |
| 366 case InstArithmetic::Lshr: | 567 break; |
| 367 UnimplementedError(Func->getContext()->getFlags()); | 568 case InstArithmetic::Xor: |
| 368 break; | 569 UnimplementedError(Func->getContext()->getFlags()); |
| 369 case InstArithmetic::Ashr: | 570 break; |
| 370 UnimplementedError(Func->getContext()->getFlags()); | 571 case InstArithmetic::Sub: |
| 371 break; | 572 UnimplementedError(Func->getContext()->getFlags()); |
| 372 case InstArithmetic::Udiv: | 573 break; |
| 373 UnimplementedError(Func->getContext()->getFlags()); | 574 case InstArithmetic::Mul: |
| 374 break; | 575 UnimplementedError(Func->getContext()->getFlags()); |
| 375 case InstArithmetic::Sdiv: | 576 break; |
| 376 UnimplementedError(Func->getContext()->getFlags()); | 577 case InstArithmetic::Shl: |
| 377 break; | 578 UnimplementedError(Func->getContext()->getFlags()); |
| 378 case InstArithmetic::Urem: | 579 break; |
| 379 UnimplementedError(Func->getContext()->getFlags()); | 580 case InstArithmetic::Lshr: |
| 380 break; | 581 UnimplementedError(Func->getContext()->getFlags()); |
| 381 case InstArithmetic::Srem: | 582 break; |
| 382 UnimplementedError(Func->getContext()->getFlags()); | 583 case InstArithmetic::Ashr: |
| 383 break; | 584 UnimplementedError(Func->getContext()->getFlags()); |
| 384 case InstArithmetic::Fadd: | 585 break; |
| 385 UnimplementedError(Func->getContext()->getFlags()); | 586 case InstArithmetic::Udiv: |
| 386 break; | 587 UnimplementedError(Func->getContext()->getFlags()); |
| 387 case InstArithmetic::Fsub: | 588 break; |
| 388 UnimplementedError(Func->getContext()->getFlags()); | 589 case InstArithmetic::Sdiv: |
| 389 break; | 590 UnimplementedError(Func->getContext()->getFlags()); |
| 390 case InstArithmetic::Fmul: | 591 break; |
| 391 UnimplementedError(Func->getContext()->getFlags()); | 592 case InstArithmetic::Urem: |
| 392 break; | 593 UnimplementedError(Func->getContext()->getFlags()); |
| 393 case InstArithmetic::Fdiv: | 594 break; |
| 394 UnimplementedError(Func->getContext()->getFlags()); | 595 case InstArithmetic::Srem: |
| 395 break; | 596 UnimplementedError(Func->getContext()->getFlags()); |
| 396 case InstArithmetic::Frem: | 597 break; |
| 397 UnimplementedError(Func->getContext()->getFlags()); | 598 case InstArithmetic::Fadd: |
| 398 break; | 599 UnimplementedError(Func->getContext()->getFlags()); |
| 600 break; | |
| 601 case InstArithmetic::Fsub: | |
| 602 UnimplementedError(Func->getContext()->getFlags()); | |
| 603 break; | |
| 604 case InstArithmetic::Fmul: | |
| 605 UnimplementedError(Func->getContext()->getFlags()); | |
| 606 break; | |
| 607 case InstArithmetic::Fdiv: | |
| 608 UnimplementedError(Func->getContext()->getFlags()); | |
| 609 break; | |
| 610 case InstArithmetic::Frem: | |
| 611 UnimplementedError(Func->getContext()->getFlags()); | |
| 612 break; | |
| 613 } | |
| 399 } | 614 } |
| 400 } | 615 } |
| 401 | 616 |
| 402 void TargetARM32::lowerAssign(const InstAssign *Inst) { | 617 void TargetARM32::lowerAssign(const InstAssign *Inst) { |
| 403 (void)Inst; | 618 Variable *Dest = Inst->getDest(); |
| 404 UnimplementedError(Func->getContext()->getFlags()); | 619 Operand *Src0 = Inst->getSrc(0); |
| 620 assert(Dest->getType() == Src0->getType()); | |
| 621 if (Dest->getType() == IceType_i64) { | |
| 622 Src0 = legalize(Src0); | |
| 623 Operand *Src0Lo = loOperand(Src0); | |
| 624 Operand *Src0Hi = hiOperand(Src0); | |
| 625 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | |
| 626 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | |
| 627 Variable *T_Lo = nullptr, *T_Hi = nullptr; | |
| 628 _mov(T_Lo, Src0Lo); | |
| 629 _mov(DestLo, T_Lo); | |
| 630 _mov(T_Hi, Src0Hi); | |
| 631 _mov(DestHi, T_Hi); | |
| 632 } else { | |
| 633 Operand *SrcR; | |
| 634 if (Dest->hasReg()) { | |
| 635 // If Dest already has a physical register, then legalize the | |
| 636 // Src operand into a Variable with the same register | |
| 637 // assignment. This is mostly a workaround for advanced phi | |
| 638 // lowering's ad-hoc register allocation which assumes no | |
| 639 // register allocation is needed when at least one of the | |
| 640 // operands is non-memory. | |
| 641 // TODO(jvoung): check this for ARM. | |
| 642 SrcR = legalize(Src0, Legal_Reg, Dest->getRegNum()); | |
| 643 } else { | |
| 644 // Dest could be a stack operand. Since we could potentially need | |
| 645 // to do a Store (and store can only have Register operands), | |
| 646 // legalize this to a register. | |
| 647 SrcR = legalize(Src0, Legal_Reg); | |
| 648 } | |
| 649 if (isVectorType(Dest->getType())) { | |
| 650 UnimplementedError(Func->getContext()->getFlags()); | |
| 651 } else { | |
| 652 _mov(Dest, SrcR); | |
| 653 } | |
| 654 } | |
| 405 } | 655 } |
| 406 | 656 |
| 407 void TargetARM32::lowerBr(const InstBr *Inst) { | 657 void TargetARM32::lowerBr(const InstBr *Inst) { |
| 408 (void)Inst; | 658 (void)Inst; |
| 409 UnimplementedError(Func->getContext()->getFlags()); | 659 UnimplementedError(Func->getContext()->getFlags()); |
| 410 } | 660 } |
| 411 | 661 |
| 412 void TargetARM32::lowerCall(const InstCall *Inst) { | 662 void TargetARM32::lowerCall(const InstCall *Inst) { |
| 413 (void)Inst; | 663 (void)Inst; |
| 414 UnimplementedError(Func->getContext()->getFlags()); | 664 UnimplementedError(Func->getContext()->getFlags()); |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 622 } | 872 } |
| 623 } | 873 } |
| 624 | 874 |
| 625 void TargetARM32::lowerPhi(const InstPhi * /*Inst*/) { | 875 void TargetARM32::lowerPhi(const InstPhi * /*Inst*/) { |
| 626 Func->setError("Phi found in regular instruction list"); | 876 Func->setError("Phi found in regular instruction list"); |
| 627 } | 877 } |
| 628 | 878 |
| 629 void TargetARM32::lowerRet(const InstRet *Inst) { | 879 void TargetARM32::lowerRet(const InstRet *Inst) { |
| 630 Variable *Reg = nullptr; | 880 Variable *Reg = nullptr; |
| 631 if (Inst->hasRetValue()) { | 881 if (Inst->hasRetValue()) { |
| 632 UnimplementedError(Func->getContext()->getFlags()); | 882 Operand *Src0 = Inst->getRetValue(); |
| 883 if (Src0->getType() == IceType_i64) { | |
| 884 Variable *R0 = legalizeToVar(loOperand(Src0), RegARM32::Reg_r0); | |
| 885 Variable *R1 = legalizeToVar(hiOperand(Src0), RegARM32::Reg_r1); | |
| 886 Reg = R0; | |
| 887 Context.insert(InstFakeUse::create(Func, R1)); | |
| 888 } else if (isScalarFloatingType(Src0->getType())) { | |
| 889 UnimplementedError(Func->getContext()->getFlags()); | |
| 890 } else if (isVectorType(Src0->getType())) { | |
| 891 UnimplementedError(Func->getContext()->getFlags()); | |
| 892 } else { | |
| 893 Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex); | |
| 894 _mov(Reg, Src0F, RegARM32::Reg_r0); | |
| 895 } | |
| 633 } | 896 } |
| 634 // Add a ret instruction even if sandboxing is enabled, because | 897 // Add a ret instruction even if sandboxing is enabled, because |
| 635 // addEpilog explicitly looks for a ret instruction as a marker for | 898 // addEpilog explicitly looks for a ret instruction as a marker for |
| 636 // where to insert the frame removal instructions. | 899 // where to insert the frame removal instructions. |
| 637 // addEpilog is responsible for restoring the "lr" register as needed | 900 // addEpilog is responsible for restoring the "lr" register as needed |
| 638 // prior to this ret instruction. | 901 // prior to this ret instruction. |
| 639 _ret(getPhysicalRegister(RegARM32::Reg_lr), Reg); | 902 _ret(getPhysicalRegister(RegARM32::Reg_lr), Reg); |
| 640 // Add a fake use of sp to make sure sp stays alive for the entire | 903 // Add a fake use of sp to make sure sp stays alive for the entire |
| 641 // function. Otherwise post-call sp adjustments get dead-code | 904 // function. Otherwise post-call sp adjustments get dead-code |
| 642 // eliminated. TODO: Are there more places where the fake use | 905 // eliminated. TODO: Are there more places where the fake use |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 659 void TargetARM32::doAddressOptStore() { | 922 void TargetARM32::doAddressOptStore() { |
| 660 UnimplementedError(Func->getContext()->getFlags()); | 923 UnimplementedError(Func->getContext()->getFlags()); |
| 661 } | 924 } |
| 662 | 925 |
| 663 void TargetARM32::lowerSwitch(const InstSwitch *Inst) { | 926 void TargetARM32::lowerSwitch(const InstSwitch *Inst) { |
| 664 (void)Inst; | 927 (void)Inst; |
| 665 UnimplementedError(Func->getContext()->getFlags()); | 928 UnimplementedError(Func->getContext()->getFlags()); |
| 666 } | 929 } |
| 667 | 930 |
| 668 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Inst*/) { | 931 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Inst*/) { |
| 669 llvm_unreachable("Not yet implemented"); | 932 UnimplementedError(Func->getContext()->getFlags()); |
| 670 } | 933 } |
| 671 | 934 |
| 672 // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to | 935 // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to |
| 673 // preserve integrity of liveness analysis. Undef values are also | 936 // preserve integrity of liveness analysis. Undef values are also |
| 674 // turned into zeroes, since loOperand() and hiOperand() don't expect | 937 // turned into zeroes, since loOperand() and hiOperand() don't expect |
| 675 // Undef input. | 938 // Undef input. |
| 676 void TargetARM32::prelowerPhis() { | 939 void TargetARM32::prelowerPhis() { |
| 677 UnimplementedError(Func->getContext()->getFlags()); | 940 UnimplementedError(Func->getContext()->getFlags()); |
| 678 } | 941 } |
| 679 | 942 |
| 680 // Lower the pre-ordered list of assignments into mov instructions. | 943 // Lower the pre-ordered list of assignments into mov instructions. |
| 681 // Also has to do some ad-hoc register allocation as necessary. | 944 // Also has to do some ad-hoc register allocation as necessary. |
| 682 void TargetARM32::lowerPhiAssignments(CfgNode *Node, | 945 void TargetARM32::lowerPhiAssignments(CfgNode *Node, |
| 683 const AssignList &Assignments) { | 946 const AssignList &Assignments) { |
| 684 (void)Node; | 947 (void)Node; |
| 685 (void)Assignments; | 948 (void)Assignments; |
| 686 UnimplementedError(Func->getContext()->getFlags()); | 949 UnimplementedError(Func->getContext()->getFlags()); |
| 687 } | 950 } |
| 688 | 951 |
| 952 Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) { | |
| 953 Variable *Reg = makeReg(Ty, RegNum); | |
| 954 UnimplementedError(Func->getContext()->getFlags()); | |
| 955 return Reg; | |
| 956 } | |
| 957 | |
| 958 // Helper for legalize() to emit the right code to lower an operand to a | |
| 959 // register of the appropriate type. | |
| 960 Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { | |
| 961 Type Ty = Src->getType(); | |
| 962 Variable *Reg = makeReg(Ty, RegNum); | |
| 963 if (isVectorType(Ty)) { | |
| 964 UnimplementedError(Func->getContext()->getFlags()); | |
| 965 } else { | |
| 966 // Mov's Src operand can really only be the flexible second operand type | |
| 967 // or a register. Users should guarantee that. | |
| 968 _mov(Reg, Src); | |
| 969 } | |
| 970 return Reg; | |
| 971 } | |
| 972 | |
| 973 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, | |
| 974 int32_t RegNum) { | |
| 975 // Assert that a physical register is allowed. To date, all calls | |
| 976 // to legalize() allow a physical register. Legal_Flex converts | |
| 977 // registers to the right type OperandARM32FlexReg as needed. | |
| 978 assert(Allowed & Legal_Reg); | |
| 979 // Go through the various types of operands: | |
| 980 // OperandARM32Mem, OperandARM32Flex, Constant, and Variable. | |
| 981 // Given the above assertion, if type of operand is not legal | |
| 982 // (e.g., OperandARM32Mem and !Legal_Mem), we can always copy | |
| 983 // to a register. | |
| 984 if (auto Mem = llvm::dyn_cast<OperandARM32Mem>(From)) { | |
| 985 // Before doing anything with a Mem operand, we need to ensure | |
| 986 // that the Base and Index components are in physical registers. | |
| 987 Variable *Base = Mem->getBase(); | |
| 988 Variable *Index = Mem->getIndex(); | |
| 989 Variable *RegBase = nullptr; | |
| 990 Variable *RegIndex = nullptr; | |
| 991 if (Base) { | |
| 992 RegBase = legalizeToVar(Base); | |
| 993 } | |
| 994 if (Index) { | |
| 995 RegIndex = legalizeToVar(Index); | |
| 996 } | |
| 997 // Create a new operand if there was a change. | |
| 998 if (Base != RegBase || Index != RegIndex) { | |
| 999 // There is only a reg +/- reg or reg + imm form. | |
| 1000 // Figure out which to re-create. | |
| 1001 if (Mem->isRegReg()) { | |
| 1002 Mem = OperandARM32Mem::create(Func, Mem->getType(), RegBase, RegIndex, | |
| 1003 Mem->getShiftOp(), Mem->getShiftAmt(), | |
| 1004 Mem->getAddrMode()); | |
| 1005 } else { | |
| 1006 Mem = OperandARM32Mem::create(Func, Mem->getType(), RegBase, | |
| 1007 Mem->getOffset(), Mem->getAddrMode()); | |
| 1008 } | |
| 1009 } | |
| 1010 if (!(Allowed & Legal_Mem)) { | |
| 1011 Type Ty = Mem->getType(); | |
| 1012 Variable *Reg = makeReg(Ty, RegNum); | |
| 1013 _ldr(Reg, Mem); | |
| 1014 From = Reg; | |
| 1015 } else { | |
| 1016 From = Mem; | |
| 1017 } | |
| 1018 return From; | |
| 1019 } | |
| 1020 | |
| 1021 if (auto Flex = llvm::dyn_cast<OperandARM32Flex>(From)) { | |
| 1022 if (!(Allowed & Legal_Flex)) { | |
| 1023 if (auto FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Flex)) { | |
| 1024 if (FlexReg->getShiftOp() == OperandARM32::kNoShift) { | |
| 1025 From = FlexReg->getReg(); | |
| 1026 // Fall through and let From be checked as a Variable below, | |
| 1027 // where it may or may not need a register. | |
| 1028 } else { | |
| 1029 return copyToReg(Flex, RegNum); | |
| 1030 } | |
| 1031 } else { | |
| 1032 return copyToReg(Flex, RegNum); | |
| 1033 } | |
| 1034 } else { | |
| 1035 return From; | |
| 1036 } | |
| 1037 } | |
| 1038 | |
| 1039 if (llvm::isa<Constant>(From)) { | |
| 1040 if (llvm::isa<ConstantUndef>(From)) { | |
| 1041 // Lower undefs to zero. Another option is to lower undefs to an | |
| 1042 // uninitialized register; however, using an uninitialized register | |
| 1043 // results in less predictable code. | |
| 1044 if (isVectorType(From->getType())) | |
| 1045 return makeVectorOfZeros(From->getType(), RegNum); | |
| 1046 From = Ctx->getConstantZero(From->getType()); | |
| 1047 } | |
| 1048 // There should be no constants of vector type (other than undef). | |
| 1049 assert(!isVectorType(From->getType())); | |
| 1050 bool CanBeFlex = Allowed & Legal_Flex; | |
| 1051 if (auto C32 = llvm::dyn_cast<ConstantInteger32>(From)) { | |
| 1052 uint32_t RotateAmt; | |
| 1053 uint32_t Immed_8; | |
| 1054 uint32_t Value = static_cast<uint32_t>(C32->getValue()); | |
| 1055 // Check if the immediate will fit in a Flexible second operand, | |
| 1056 // if a Flexible second operand is allowed. We need to know the exact | |
| 1057 // value, so that rules out relocatable constants. | |
| 1058 // Also try the inverse and use MVN if possible. | |
| 1059 if (CanBeFlex && | |
| 1060 OperandARM32FlexImm::canHoldImm(Value, &RotateAmt, &Immed_8)) { | |
| 1061 return OperandARM32FlexImm::create(Func, From->getType(), Immed_8, | |
| 1062 RotateAmt); | |
| 1063 } else if (CanBeFlex && OperandARM32FlexImm::canHoldImm( | |
| 1064 ~Value, &RotateAmt, &Immed_8)) { | |
| 1065 auto InvertedFlex = OperandARM32FlexImm::create(Func, From->getType(), | |
| 1066 Immed_8, RotateAmt); | |
| 1067 Type Ty = From->getType(); | |
| 1068 Variable *Reg = makeReg(Ty, RegNum); | |
| 1069 _mvn(Reg, InvertedFlex); | |
| 1070 return Reg; | |
| 1071 } else { | |
| 1072 // Do a movw/movt to a register. | |
| 1073 Type Ty = From->getType(); | |
| 1074 Variable *Reg = makeReg(Ty, RegNum); | |
| 1075 uint32_t UpperBits = (Value >> 16) & 0xFFFF; | |
| 1076 _movw(Reg, | |
| 1077 UpperBits != 0 ? Ctx->getConstantInt32(Value & 0xFFFF) : C32); | |
| 1078 if (UpperBits != 0) { | |
| 1079 _movt(Reg, Ctx->getConstantInt32(UpperBits)); | |
| 1080 } | |
| 1081 return Reg; | |
| 1082 } | |
| 1083 } else if (auto C = llvm::dyn_cast<ConstantRelocatable>(From)) { | |
| 1084 Type Ty = From->getType(); | |
| 1085 Variable *Reg = makeReg(Ty, RegNum); | |
| 1086 _movw(Reg, C); | |
| 1087 _movt(Reg, C); | |
| 1088 return Reg; | |
| 1089 } else { | |
| 1090 // Load floats/doubles from literal pool. | |
| 1091 UnimplementedError(Func->getContext()->getFlags()); | |
| 1092 From = copyToReg(From, RegNum); | |
| 1093 } | |
| 1094 return From; | |
| 1095 } | |
| 1096 | |
| 1097 if (auto Var = llvm::dyn_cast<Variable>(From)) { | |
| 1098 // Check if the variable is guaranteed a physical register. This | |
| 1099 // can happen either when the variable is pre-colored or when it is | |
| 1100 // assigned infinite weight. | |
| 1101 bool MustHaveRegister = (Var->hasReg() || Var->getWeight().isInf()); | |
| 1102 // We need a new physical register for the operand if: | |
| 1103 // Mem is not allowed and Var isn't guaranteed a physical | |
| 1104 // register, or | |
| 1105 // RegNum is required and Var->getRegNum() doesn't match. | |
| 1106 if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || | |
| 1107 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) { | |
| 1108 From = copyToReg(From, RegNum); | |
| 1109 } | |
| 1110 return From; | |
| 1111 } | |
| 1112 llvm_unreachable("Unhandled operand kind in legalize()"); | |
| 1113 | |
| 1114 return From; | |
| 1115 } | |
| 1116 | |
| 1117 // Provide a trivial wrapper to legalize() for this common usage. | |
| 1118 Variable *TargetARM32::legalizeToVar(Operand *From, int32_t RegNum) { | |
| 1119 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); | |
| 1120 } | |
| 1121 | |
| 1122 Variable *TargetARM32::makeReg(Type Type, int32_t RegNum) { | |
| 1123 // There aren't any 64-bit integer registers for ARM32. | |
| 1124 assert(Type != IceType_i64); | |
| 1125 Variable *Reg = Func->makeVariable(Type); | |
| 1126 if (RegNum == Variable::NoRegister) | |
| 1127 Reg->setWeightInfinite(); | |
| 1128 else | |
| 1129 Reg->setRegNum(RegNum); | |
| 1130 return Reg; | |
| 1131 } | |
| 1132 | |
| 689 void TargetARM32::postLower() { | 1133 void TargetARM32::postLower() { |
| 690 if (Ctx->getFlags().getOptLevel() == Opt_m1) | 1134 if (Ctx->getFlags().getOptLevel() == Opt_m1) |
| 691 return; | 1135 return; |
| 692 // Find two-address non-SSA instructions where Dest==Src0, and set | 1136 inferTwoAddress(); |
| 693 // the DestNonKillable flag to keep liveness analysis consistent. | |
| 694 UnimplementedError(Func->getContext()->getFlags()); | |
| 695 } | 1137 } |
| 696 | 1138 |
| 697 void TargetARM32::makeRandomRegisterPermutation( | 1139 void TargetARM32::makeRandomRegisterPermutation( |
| 698 llvm::SmallVectorImpl<int32_t> &Permutation, | 1140 llvm::SmallVectorImpl<int32_t> &Permutation, |
| 699 const llvm::SmallBitVector &ExcludeRegisters) const { | 1141 const llvm::SmallBitVector &ExcludeRegisters) const { |
| 700 (void)Permutation; | 1142 (void)Permutation; |
| 701 (void)ExcludeRegisters; | 1143 (void)ExcludeRegisters; |
| 702 UnimplementedError(Func->getContext()->getFlags()); | 1144 UnimplementedError(Func->getContext()->getFlags()); |
| 703 } | 1145 } |
| 704 | 1146 |
| 705 void TargetARM32::emit(const ConstantInteger32 *C) const { | 1147 void TargetARM32::emit(const ConstantInteger32 *C) const { |
| 706 if (!ALLOW_DUMP) | 1148 if (!ALLOW_DUMP) |
| 707 return; | 1149 return; |
| 708 Ostream &Str = Ctx->getStrEmit(); | 1150 Ostream &Str = Ctx->getStrEmit(); |
| 709 Str << getConstantPrefix() << C->getValue(); | 1151 Str << getConstantPrefix() << C->getValue(); |
| 710 } | 1152 } |
| 711 | 1153 |
| 712 void TargetARM32::emit(const ConstantInteger64 *) const { | 1154 void TargetARM32::emit(const ConstantInteger64 *) const { |
| 713 llvm::report_fatal_error("Not expecting to emit 64-bit integers"); | 1155 llvm::report_fatal_error("Not expecting to emit 64-bit integers"); |
| 714 } | 1156 } |
| 715 | 1157 |
| 716 void TargetARM32::emit(const ConstantFloat *C) const { | 1158 void TargetARM32::emit(const ConstantFloat *C) const { |
|
Jim Stichnoth
2015/05/18 02:10:52
btw this gives a warning about unused parameter C
jvoung (off chromium)
2015/05/18 16:26:47
Done.
| |
| 717 UnimplementedError(Ctx->getFlags()); | 1159 UnimplementedError(Ctx->getFlags()); |
| 718 } | 1160 } |
| 719 | 1161 |
| 720 void TargetARM32::emit(const ConstantDouble *C) const { | 1162 void TargetARM32::emit(const ConstantDouble *C) const { |
|
Jim Stichnoth
2015/05/18 02:10:52
this too
jvoung (off chromium)
2015/05/18 16:26:47
Done.
| |
| 721 UnimplementedError(Ctx->getFlags()); | 1163 UnimplementedError(Ctx->getFlags()); |
| 722 } | 1164 } |
| 723 | 1165 |
| 724 void TargetARM32::emit(const ConstantUndef *) const { | 1166 void TargetARM32::emit(const ConstantUndef *) const { |
| 725 llvm::report_fatal_error("undef value encountered by emitter."); | 1167 llvm::report_fatal_error("undef value encountered by emitter."); |
| 726 } | 1168 } |
| 727 | 1169 |
| 728 TargetDataARM32::TargetDataARM32(GlobalContext *Ctx) | 1170 TargetDataARM32::TargetDataARM32(GlobalContext *Ctx) |
| 729 : TargetDataLowering(Ctx) {} | 1171 : TargetDataLowering(Ctx) {} |
| 730 | 1172 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 753 } | 1195 } |
| 754 } | 1196 } |
| 755 | 1197 |
| 756 void TargetDataARM32::lowerConstants() const { | 1198 void TargetDataARM32::lowerConstants() const { |
| 757 if (Ctx->getFlags().getDisableTranslation()) | 1199 if (Ctx->getFlags().getDisableTranslation()) |
| 758 return; | 1200 return; |
| 759 UnimplementedError(Ctx->getFlags()); | 1201 UnimplementedError(Ctx->getFlags()); |
| 760 } | 1202 } |
| 761 | 1203 |
| 762 } // end of namespace Ice | 1204 } // end of namespace Ice |
| OLD | NEW |