Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: src/IceTargetLoweringMIPS32.cpp

Issue 2313293002: [SubZero] Implement address optimization for MIPS (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceTargetLoweringMIPS32.h ('k') | tests_lit/llvm2ice_tests/mips-address-mode-opt.ll » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « src/IceTargetLoweringMIPS32.h ('k') | tests_lit/llvm2ice_tests/mips-address-mode-opt.ll » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698