Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // | 1 // |
| 2 // The Subzero Code Generator | 2 // The Subzero Code Generator |
| 3 // | 3 // |
| 4 // This file is distributed under the University of Illinois Open Source | 4 // This file is distributed under the University of Illinois Open Source |
| 5 // License. See LICENSE.TXT for details. | 5 // License. See LICENSE.TXT for details. |
| 6 // | 6 // |
| 7 //===----------------------------------------------------------------------===// | 7 //===----------------------------------------------------------------------===// |
| 8 /// | 8 /// |
| 9 /// \file | 9 /// \file |
| 10 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost | 10 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost |
| (...skipping 2292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2303 void TargetMIPS32::lowerLoad(const InstLoad *Instr) { | 2303 void TargetMIPS32::lowerLoad(const InstLoad *Instr) { |
| 2304 // A Load instruction can be treated the same as an Assign instruction, after | 2304 // A Load instruction can be treated the same as an Assign instruction, after |
| 2305 // the source operand is transformed into an OperandARM32Mem operand. | 2305 // the source operand is transformed into an OperandARM32Mem operand. |
| 2306 Type Ty = Instr->getDest()->getType(); | 2306 Type Ty = Instr->getDest()->getType(); |
| 2307 Operand *Src0 = formMemoryOperand(Instr->getSourceAddress(), Ty); | 2307 Operand *Src0 = formMemoryOperand(Instr->getSourceAddress(), Ty); |
| 2308 Variable *DestLoad = Instr->getDest(); | 2308 Variable *DestLoad = Instr->getDest(); |
| 2309 auto *Assign = InstAssign::create(Func, DestLoad, Src0); | 2309 auto *Assign = InstAssign::create(Func, DestLoad, Src0); |
| 2310 lowerAssign(Assign); | 2310 lowerAssign(Assign); |
| 2311 } | 2311 } |
| 2312 | 2312 |
| 2313 void TargetMIPS32::doAddressOptLoad() { UnimplementedError(getFlags()); } | 2313 namespace { |
| 2314 void dumpAddressOpt(const Cfg *Func, const Variable *Base, int32_t Offset, | |
| 2315 const Inst *Reason) { | |
| 2316 if (!BuildDefs::dump()) | |
| 2317 return; | |
| 2318 if (!Func->isVerbose(IceV_AddrOpt)) | |
| 2319 return; | |
| 2320 OstreamLocker _(Func->getContext()); | |
| 2321 Ostream &Str = Func->getContext()->getStrDump(); | |
| 2322 Str << "Instruction: "; | |
| 2323 Reason->dumpDecorated(Func); | |
| 2324 Str << " results in Base="; | |
| 2325 if (Base) | |
| 2326 Base->dump(Func); | |
| 2327 else | |
| 2328 Str << "<null>"; | |
| 2329 Str << ", Offset=" << Offset << "\n"; | |
| 2330 } | |
| 2331 | |
| 2332 bool matchAssign(const VariablesMetadata *VMetadata, const CfgNode *UseNode, | |
| 2333 Variable **Var, int32_t *Offset, const Inst **Reason) { | |
| 2334 // Var originates from Var=SrcVar ==> set Var:=SrcVar | |
| 2335 if (*Var == nullptr) | |
| 2336 return false; | |
| 2337 const Inst *VarAssign = VMetadata->getSingleDefinition(*Var); | |
| 2338 if (!VarAssign) | |
| 2339 return false; | |
| 2340 assert(!VMetadata->isMultiDef(*Var)); | |
| 2341 if (!llvm::isa<InstAssign>(VarAssign)) | |
| 2342 return false; | |
| 2343 | |
| 2344 const CfgNode *DefNode = VMetadata->getSingleDefinitionNode(*Var); | |
| 2345 const bool IsSingleBB = (DefNode->getIndex() == UseNode->getIndex()); | |
|
Jim Stichnoth
2016/09/09 00:08:22
Why are you adding this single-block condition?
I
jaydeep.patil
2016/09/13 06:42:25
Done.
| |
| 2346 Operand *SrcOp = VarAssign->getSrc(0); | |
| 2347 bool Optimized = false; | |
| 2348 if (auto *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) { | |
| 2349 // Ensure SrcVar stays single-BB | |
| 2350 if (!VMetadata->isMultiDef(SrcVar) || IsSingleBB == true) { | |
| 2351 Optimized = true; | |
| 2352 *Var = SrcVar; | |
| 2353 } else if (auto *Const = llvm::dyn_cast<ConstantInteger32>(SrcOp)) { | |
| 2354 int32_t MoreOffset = Const->getValue(); | |
| 2355 int32_t NewOffset = MoreOffset + *Offset; | |
| 2356 if (Utils::WouldOverflowAdd(*Offset, MoreOffset)) | |
| 2357 return false; | |
| 2358 *Var = nullptr; | |
| 2359 *Offset += NewOffset; | |
| 2360 Optimized = true; | |
| 2361 } | |
| 2362 } | |
| 2363 | |
| 2364 if (Optimized) { | |
| 2365 *Reason = VarAssign; | |
| 2366 } | |
| 2367 | |
| 2368 return Optimized; | |
| 2369 } | |
| 2370 | |
| 2371 bool isAddOrSub(const Inst *Instr, InstArithmetic::OpKind *Kind) { | |
| 2372 if (const auto *Arith = llvm::dyn_cast<InstArithmetic>(Instr)) { | |
| 2373 switch (Arith->getOp()) { | |
| 2374 default: | |
| 2375 return false; | |
| 2376 case InstArithmetic::Add: | |
| 2377 case InstArithmetic::Sub: | |
| 2378 *Kind = Arith->getOp(); | |
| 2379 return true; | |
| 2380 } | |
| 2381 } | |
| 2382 return false; | |
| 2383 } | |
| 2384 | |
| 2385 bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable **Base, | |
| 2386 int32_t *Offset, const Inst **Reason) { | |
| 2387 // Base is Base=Var+Const || Base is Base=Const+Var ==> | |
| 2388 // set Base=Var, Offset+=Const | |
| 2389 // Base is Base=Var-Const ==> | |
| 2390 // set Base=Var, Offset-=Const | |
| 2391 if (*Base == nullptr) | |
| 2392 return false; | |
| 2393 const Inst *BaseInst = VMetadata->getSingleDefinition(*Base); | |
| 2394 if (BaseInst == nullptr) { | |
| 2395 return false; | |
| 2396 } | |
| 2397 assert(!VMetadata->isMultiDef(*Base)); | |
| 2398 | |
| 2399 auto *ArithInst = llvm::dyn_cast<const InstArithmetic>(BaseInst); | |
| 2400 if (ArithInst == nullptr) | |
| 2401 return false; | |
| 2402 InstArithmetic::OpKind Kind; | |
| 2403 if (!isAddOrSub(ArithInst, &Kind)) | |
| 2404 return false; | |
| 2405 bool IsAdd = Kind == InstArithmetic::Add; | |
| 2406 Operand *Src0 = ArithInst->getSrc(0); | |
| 2407 Operand *Src1 = ArithInst->getSrc(1); | |
| 2408 auto *Var0 = llvm::dyn_cast<Variable>(Src0); | |
| 2409 auto *Var1 = llvm::dyn_cast<Variable>(Src1); | |
| 2410 auto *Const0 = llvm::dyn_cast<ConstantInteger32>(Src0); | |
| 2411 auto *Const1 = llvm::dyn_cast<ConstantInteger32>(Src1); | |
| 2412 Variable *NewBase = nullptr; | |
| 2413 int32_t NewOffset = *Offset; | |
| 2414 | |
| 2415 if (Var0 == nullptr && Const0 == nullptr) { | |
| 2416 assert(llvm::isa<ConstantRelocatable>(Src0)); | |
| 2417 return false; | |
| 2418 } | |
| 2419 | |
| 2420 if (Var1 == nullptr && Const1 == nullptr) { | |
| 2421 assert(llvm::isa<ConstantRelocatable>(Src1)); | |
| 2422 return false; | |
| 2423 } | |
| 2424 | |
| 2425 if (Var0 && Var1) | |
| 2426 // TODO(jpp): merge base/index splitting into here. | |
| 2427 return false; | |
| 2428 if (!IsAdd && Var1) | |
| 2429 return false; | |
| 2430 if (Var0) | |
| 2431 NewBase = Var0; | |
| 2432 else if (Var1) | |
| 2433 NewBase = Var1; | |
| 2434 // Compute the updated constant offset. | |
| 2435 if (Const0) { | |
| 2436 int32_t MoreOffset = IsAdd ? Const0->getValue() : -Const0->getValue(); | |
| 2437 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset)) | |
| 2438 return false; | |
| 2439 NewOffset += MoreOffset; | |
| 2440 } | |
| 2441 if (Const1) { | |
| 2442 int32_t MoreOffset = IsAdd ? Const1->getValue() : -Const1->getValue(); | |
| 2443 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset)) | |
| 2444 return false; | |
| 2445 NewOffset += MoreOffset; | |
| 2446 } | |
| 2447 | |
| 2448 // Update the computed address parameters once we are sure optimization | |
| 2449 // is valid. | |
| 2450 *Base = NewBase; | |
| 2451 *Offset = NewOffset; | |
| 2452 *Reason = BaseInst; | |
| 2453 return true; | |
| 2454 } | |
| 2455 } // end of anonymous namespace | |
| 2456 | |
| 2457 OperandMIPS32Mem *TargetMIPS32::formAddressingMode(Type Ty, Cfg *Func, | |
| 2458 const CfgNode *LdStNode, | |
| 2459 const Inst *LdSt, | |
| 2460 Operand *Base) { | |
| 2461 assert(Base != nullptr); | |
| 2462 int32_t OffsetImm = 0; | |
| 2463 | |
| 2464 Func->resetCurrentNode(); | |
| 2465 if (Func->isVerbose(IceV_AddrOpt)) { | |
| 2466 OstreamLocker _(Func->getContext()); | |
| 2467 Ostream &Str = Func->getContext()->getStrDump(); | |
| 2468 Str << "\nAddress mode formation:\t"; | |
| 2469 LdSt->dumpDecorated(Func); | |
| 2470 } | |
| 2471 | |
| 2472 if (isVectorType(Ty)) { | |
| 2473 UnimplementedError(getFlags()); | |
| 2474 return nullptr; | |
| 2475 } | |
| 2476 | |
| 2477 auto *BaseVar = llvm::dyn_cast<Variable>(Base); | |
| 2478 if (BaseVar == nullptr) | |
| 2479 return nullptr; | |
| 2480 | |
| 2481 const VariablesMetadata *VMetadata = Func->getVMetadata(); | |
| 2482 const Inst *Reason = nullptr; | |
| 2483 | |
| 2484 do { | |
| 2485 if (Reason != nullptr) { | |
| 2486 dumpAddressOpt(Func, BaseVar, OffsetImm, Reason); | |
| 2487 Reason = nullptr; | |
| 2488 } | |
| 2489 | |
| 2490 if (matchAssign(VMetadata, LdStNode, &BaseVar, &OffsetImm, &Reason)) { | |
| 2491 continue; | |
| 2492 } | |
| 2493 | |
| 2494 if (matchOffsetBase(VMetadata, &BaseVar, &OffsetImm, &Reason)) { | |
| 2495 continue; | |
| 2496 } | |
| 2497 } while (Reason); | |
| 2498 | |
| 2499 if (BaseVar == nullptr) { | |
| 2500 // We need base register rather than just OffsetImm. Move the OffsetImm to | |
| 2501 // BaseVar and form 0(BaseVar) addressing. | |
| 2502 const Type PointerType = getPointerType(); | |
| 2503 BaseVar = makeReg(PointerType); | |
| 2504 Context.insert<InstAssign>(BaseVar, Ctx->getConstantInt32(OffsetImm)); | |
| 2505 OffsetImm = 0; | |
| 2506 } else if (OffsetImm != 0) { | |
| 2507 // If the OffsetImm is more than signed 16-bit value then add it in the | |
| 2508 // BaseVar and form 0(BaseVar) addressing. | |
| 2509 const int32_t PositiveOffset = OffsetImm > 0 ? OffsetImm : -OffsetImm; | |
| 2510 const InstArithmetic::OpKind Op = | |
| 2511 OffsetImm > 0 ? InstArithmetic::Add : InstArithmetic::Sub; | |
| 2512 constexpr bool ZeroExt = false; | |
| 2513 if (!OperandMIPS32Mem::canHoldOffset(Ty, ZeroExt, OffsetImm)) { | |
| 2514 const Type PointerType = getPointerType(); | |
| 2515 Variable *T = makeReg(PointerType); | |
| 2516 Context.insert<InstArithmetic>(Op, T, BaseVar, | |
| 2517 Ctx->getConstantInt32(PositiveOffset)); | |
| 2518 BaseVar = T; | |
| 2519 OffsetImm = 0; | |
| 2520 } | |
| 2521 } | |
| 2522 | |
| 2523 assert(BaseVar != nullptr); | |
| 2524 assert(OffsetImm < 0 ? (-OffsetImm & 0x0000ffff) == -OffsetImm | |
| 2525 : (OffsetImm & 0x0000ffff) == OffsetImm); | |
| 2526 | |
| 2527 return OperandMIPS32Mem::create( | |
| 2528 Func, Ty, BaseVar, | |
| 2529 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(OffsetImm))); | |
| 2530 } | |
| 2531 | |
| 2532 void TargetMIPS32::doAddressOptLoad() { | |
| 2533 Inst *Instr = iteratorToInst(Context.getCur()); | |
| 2534 assert(llvm::isa<InstLoad>(Instr)); | |
| 2535 const CfgNode *LoadNode = Context.getNode(); | |
| 2536 Variable *Dest = Instr->getDest(); | |
| 2537 Operand *Addr = Instr->getSrc(0); | |
| 2538 if (OperandMIPS32Mem *Mem = | |
| 2539 formAddressingMode(Dest->getType(), Func, LoadNode, Instr, Addr)) { | |
| 2540 Instr->setDeleted(); | |
| 2541 Context.insert<InstLoad>(Dest, Mem); | |
| 2542 } | |
| 2543 } | |
| 2314 | 2544 |
| 2315 void TargetMIPS32::randomlyInsertNop(float Probability, | 2545 void TargetMIPS32::randomlyInsertNop(float Probability, |
| 2316 RandomNumberGenerator &RNG) { | 2546 RandomNumberGenerator &RNG) { |
| 2317 RandomNumberGeneratorWrapper RNGW(RNG); | 2547 RandomNumberGeneratorWrapper RNGW(RNG); |
| 2318 if (RNGW.getTrueWithProbability(Probability)) { | 2548 if (RNGW.getTrueWithProbability(Probability)) { |
| 2319 UnimplementedError(getFlags()); | 2549 UnimplementedError(getFlags()); |
| 2320 } | 2550 } |
| 2321 } | 2551 } |
| 2322 | 2552 |
| 2323 void TargetMIPS32::lowerPhi(const InstPhi * /*Instr*/) { | 2553 void TargetMIPS32::lowerPhi(const InstPhi * /*Instr*/) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2373 Variable *ValueHi = legalizeToReg(hiOperand(Value)); | 2603 Variable *ValueHi = legalizeToReg(hiOperand(Value)); |
| 2374 Variable *ValueLo = legalizeToReg(loOperand(Value)); | 2604 Variable *ValueLo = legalizeToReg(loOperand(Value)); |
| 2375 _sw(ValueHi, llvm::cast<OperandMIPS32Mem>(hiOperand(NewAddr))); | 2605 _sw(ValueHi, llvm::cast<OperandMIPS32Mem>(hiOperand(NewAddr))); |
| 2376 _sw(ValueLo, llvm::cast<OperandMIPS32Mem>(loOperand(NewAddr))); | 2606 _sw(ValueLo, llvm::cast<OperandMIPS32Mem>(loOperand(NewAddr))); |
| 2377 } else { | 2607 } else { |
| 2378 Variable *ValueR = legalizeToReg(Value); | 2608 Variable *ValueR = legalizeToReg(Value); |
| 2379 _sw(ValueR, NewAddr); | 2609 _sw(ValueR, NewAddr); |
| 2380 } | 2610 } |
| 2381 } | 2611 } |
| 2382 | 2612 |
| 2383 void TargetMIPS32::doAddressOptStore() { UnimplementedError(getFlags()); } | 2613 void TargetMIPS32::doAddressOptStore() { |
| 2614 Inst *Instr = iteratorToInst(Context.getCur()); | |
| 2615 assert(llvm::isa<InstStore>(Instr)); | |
| 2616 const CfgNode *StoreNode = Context.getNode(); | |
| 2617 Operand *Src = Instr->getSrc(0); | |
| 2618 Operand *Addr = Instr->getSrc(1); | |
| 2619 if (OperandMIPS32Mem *Mem = | |
| 2620 formAddressingMode(Src->getType(), Func, StoreNode, Instr, Addr)) { | |
| 2621 Instr->setDeleted(); | |
| 2622 Context.insert<InstStore>(Src, Mem); | |
| 2623 } | |
| 2624 } | |
| 2384 | 2625 |
| 2385 void TargetMIPS32::lowerSwitch(const InstSwitch *Instr) { | 2626 void TargetMIPS32::lowerSwitch(const InstSwitch *Instr) { |
| 2386 Operand *Src = Instr->getComparison(); | 2627 Operand *Src = Instr->getComparison(); |
| 2387 SizeT NumCases = Instr->getNumCases(); | 2628 SizeT NumCases = Instr->getNumCases(); |
| 2388 if (Src->getType() == IceType_i64) { | 2629 if (Src->getType() == IceType_i64) { |
| 2389 Src = legalizeUndef(Src); | 2630 Src = legalizeUndef(Src); |
| 2390 Variable *Src0Lo = legalizeToReg(loOperand(Src)); | 2631 Variable *Src0Lo = legalizeToReg(loOperand(Src)); |
| 2391 Variable *Src0Hi = legalizeToReg(hiOperand(Src)); | 2632 Variable *Src0Hi = legalizeToReg(hiOperand(Src)); |
| 2392 for (SizeT I = 0; I < NumCases; ++I) { | 2633 for (SizeT I = 0; I < NumCases; ++I) { |
| 2393 Operand *ValueLo = Ctx->getConstantInt32(Instr->getValue(I)); | 2634 Operand *ValueLo = Ctx->getConstantInt32(Instr->getValue(I)); |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2729 Str << "\t.set\t" | 2970 Str << "\t.set\t" |
| 2730 << "nomips16\n"; | 2971 << "nomips16\n"; |
| 2731 } | 2972 } |
| 2732 | 2973 |
| 2733 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; | 2974 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; |
| 2734 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; | 2975 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; |
| 2735 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; | 2976 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; |
| 2736 | 2977 |
| 2737 } // end of namespace MIPS32 | 2978 } // end of namespace MIPS32 |
| 2738 } // end of namespace Ice | 2979 } // end of namespace Ice |
| OLD | NEW |