HexagonSplitDouble.cpp revision 314564
157416Smarkm//===--- HexagonSplitDouble.cpp -------------------------------------------===// 257416Smarkm// 357416Smarkm// The LLVM Compiler Infrastructure 457416Smarkm// 557416Smarkm// This file is distributed under the University of Illinois Open Source 657416Smarkm// License. See LICENSE.TXT for details. 757416Smarkm// 857416Smarkm//===----------------------------------------------------------------------===// 957416Smarkm 1057416Smarkm#define DEBUG_TYPE "hsdr" 1157416Smarkm 1257416Smarkm#include "HexagonInstrInfo.h" 1357416Smarkm#include "HexagonRegisterInfo.h" 1457416Smarkm#include "HexagonSubtarget.h" 1557416Smarkm#include "llvm/ADT/BitVector.h" 1657416Smarkm#include "llvm/ADT/SmallVector.h" 1757416Smarkm#include "llvm/ADT/STLExtras.h" 1857416Smarkm#include "llvm/ADT/StringRef.h" 1957416Smarkm#include "llvm/CodeGen/MachineBasicBlock.h" 2057416Smarkm#include "llvm/CodeGen/MachineFunction.h" 2157416Smarkm#include "llvm/CodeGen/MachineFunctionPass.h" 2257416Smarkm#include "llvm/CodeGen/MachineInstr.h" 2357416Smarkm#include "llvm/CodeGen/MachineInstrBuilder.h" 2457416Smarkm#include "llvm/CodeGen/MachineLoopInfo.h" 2557416Smarkm#include "llvm/CodeGen/MachineMemOperand.h" 2657416Smarkm#include "llvm/CodeGen/MachineOperand.h" 2757416Smarkm#include "llvm/CodeGen/MachineRegisterInfo.h" 2857416Smarkm#include "llvm/IR/DebugLoc.h" 2957416Smarkm#include "llvm/Pass.h" 3057416Smarkm#include "llvm/Support/CommandLine.h" 3157416Smarkm#include "llvm/Support/Compiler.h" 3257416Smarkm#include "llvm/Support/Debug.h" 3357416Smarkm#include "llvm/Support/ErrorHandling.h" 3457416Smarkm#include "llvm/Support/raw_ostream.h" 3557416Smarkm#include "llvm/Target/TargetRegisterInfo.h" 3657416Smarkm#include <algorithm> 3757416Smarkm#include <cassert> 3857416Smarkm#include <cstdint> 3957416Smarkm#include <limits> 4057416Smarkm#include <map> 4157416Smarkm#include <set> 4257416Smarkm#include <utility> 4357416Smarkm#include <vector> 4457416Smarkm 4557416Smarkmusing namespace llvm; 4657416Smarkm 4757416Smarkmnamespace llvm { 4857416Smarkm 4957416Smarkm FunctionPass *createHexagonSplitDoubleRegs(); 5057416Smarkm void initializeHexagonSplitDoubleRegsPass(PassRegistry&); 5157416Smarkm 5257416Smarkm} // end namespace llvm 5357416Smarkm 5457416Smarkmnamespace { 5557416Smarkm 5657416Smarkm static cl::opt<int> MaxHSDR("max-hsdr", cl::Hidden, cl::init(-1), 5757416Smarkm cl::desc("Maximum number of split partitions")); 5857416Smarkm static cl::opt<bool> MemRefsFixed("hsdr-no-mem", cl::Hidden, cl::init(true), 5957416Smarkm cl::desc("Do not split loads or stores")); 6057416Smarkm 6157416Smarkm class HexagonSplitDoubleRegs : public MachineFunctionPass { 6257416Smarkm public: 6357416Smarkm static char ID; 6457416Smarkm 6557416Smarkm HexagonSplitDoubleRegs() : MachineFunctionPass(ID), TRI(nullptr), 6657416Smarkm TII(nullptr) { 6757416Smarkm initializeHexagonSplitDoubleRegsPass(*PassRegistry::getPassRegistry()); 6857416Smarkm } 6957416Smarkm 7057416Smarkm StringRef getPassName() const override { 7157416Smarkm return "Hexagon Split Double Registers"; 7257416Smarkm } 7357416Smarkm 7457416Smarkm void getAnalysisUsage(AnalysisUsage &AU) const override { 7557416Smarkm AU.addRequired<MachineLoopInfo>(); 7657416Smarkm AU.addPreserved<MachineLoopInfo>(); 7757416Smarkm MachineFunctionPass::getAnalysisUsage(AU); 7857416Smarkm } 7957416Smarkm 8057416Smarkm bool runOnMachineFunction(MachineFunction &MF) override; 8157416Smarkm 8257416Smarkm private: 8357416Smarkm static const TargetRegisterClass *const DoubleRC; 8457416Smarkm 8557416Smarkm const HexagonRegisterInfo *TRI; 8657416Smarkm const HexagonInstrInfo *TII; 8757416Smarkm const MachineLoopInfo *MLI; 8857416Smarkm MachineRegisterInfo *MRI; 8957416Smarkm 9057416Smarkm typedef std::set<unsigned> USet; 9157416Smarkm typedef std::map<unsigned,USet> UUSetMap; 9257416Smarkm typedef std::pair<unsigned,unsigned> UUPair; 9357416Smarkm typedef std::map<unsigned,UUPair> UUPairMap; 9457416Smarkm typedef std::map<const MachineLoop*,USet> LoopRegMap; 9557416Smarkm 9657416Smarkm bool isInduction(unsigned Reg, LoopRegMap &IRM) const; 9757416Smarkm bool isVolatileInstr(const MachineInstr *MI) const; 9857416Smarkm bool isFixedInstr(const MachineInstr *MI) const; 9957416Smarkm void partitionRegisters(UUSetMap &P2Rs); 10057416Smarkm int32_t profit(const MachineInstr *MI) const; 10157416Smarkm bool isProfitable(const USet &Part, LoopRegMap &IRM) const; 10257416Smarkm 10357416Smarkm void collectIndRegsForLoop(const MachineLoop *L, USet &Rs); 10457416Smarkm void collectIndRegs(LoopRegMap &IRM); 10557416Smarkm 10657416Smarkm void createHalfInstr(unsigned Opc, MachineInstr *MI, 10757416Smarkm const UUPairMap &PairMap, unsigned SubR); 10857416Smarkm void splitMemRef(MachineInstr *MI, const UUPairMap &PairMap); 10957416Smarkm void splitImmediate(MachineInstr *MI, const UUPairMap &PairMap); 11057416Smarkm void splitCombine(MachineInstr *MI, const UUPairMap &PairMap); 11157416Smarkm void splitExt(MachineInstr *MI, const UUPairMap &PairMap); 11257416Smarkm void splitShift(MachineInstr *MI, const UUPairMap &PairMap); 11357416Smarkm void splitAslOr(MachineInstr *MI, const UUPairMap &PairMap); 11457416Smarkm bool splitInstr(MachineInstr *MI, const UUPairMap &PairMap); 11557416Smarkm void replaceSubregUses(MachineInstr *MI, const UUPairMap &PairMap); 11657416Smarkm void collapseRegPairs(MachineInstr *MI, const UUPairMap &PairMap); 11757416Smarkm bool splitPartition(const USet &Part); 11857416Smarkm 11957416Smarkm static int Counter; 12057416Smarkm static void dump_partition(raw_ostream&, const USet&, 12157416Smarkm const TargetRegisterInfo&); 12257416Smarkm }; 12357416Smarkm 12457416Smarkm char HexagonSplitDoubleRegs::ID; 12557416Smarkm int HexagonSplitDoubleRegs::Counter = 0; 12657416Smarkm const TargetRegisterClass *const HexagonSplitDoubleRegs::DoubleRC 12757416Smarkm = &Hexagon::DoubleRegsRegClass; 12857416Smarkm 12957416Smarkm} // end anonymous namespace 13057416Smarkm 13157416SmarkmINITIALIZE_PASS(HexagonSplitDoubleRegs, "hexagon-split-double", 13257416Smarkm "Hexagon Split Double Registers", false, false) 13357416Smarkm 13457416Smarkmvoid HexagonSplitDoubleRegs::dump_partition(raw_ostream &os, 13557416Smarkm const USet &Part, const TargetRegisterInfo &TRI) { 13657416Smarkm dbgs() << '{'; 13757416Smarkm for (auto I : Part) 13857416Smarkm dbgs() << ' ' << PrintReg(I, &TRI); 13957416Smarkm dbgs() << " }"; 14057416Smarkm} 14157416Smarkm 14257416Smarkmbool HexagonSplitDoubleRegs::isInduction(unsigned Reg, LoopRegMap &IRM) const { 14357416Smarkm for (auto I : IRM) { 14457416Smarkm const USet &Rs = I.second; 14557416Smarkm if (Rs.find(Reg) != Rs.end()) 14657416Smarkm return true; 14757416Smarkm } 14857416Smarkm return false; 14957416Smarkm} 15057416Smarkm 15157416Smarkmbool HexagonSplitDoubleRegs::isVolatileInstr(const MachineInstr *MI) const { 15257416Smarkm for (auto &I : MI->memoperands()) 15357416Smarkm if (I->isVolatile()) 15457416Smarkm return true; 15557416Smarkm return false; 15657416Smarkm} 15757416Smarkm 15857416Smarkmbool HexagonSplitDoubleRegs::isFixedInstr(const MachineInstr *MI) const { 15990926Snectar if (MI->mayLoad() || MI->mayStore()) 16057416Smarkm if (MemRefsFixed || isVolatileInstr(MI)) 16157416Smarkm return true; 16257416Smarkm if (MI->isDebugValue()) 16357416Smarkm return false; 16457416Smarkm 16557416Smarkm unsigned Opc = MI->getOpcode(); 16657416Smarkm switch (Opc) { 16757416Smarkm default: 16857416Smarkm return true; 16957416Smarkm 17057416Smarkm case TargetOpcode::PHI: 17157416Smarkm case TargetOpcode::COPY: 17257416Smarkm break; 17357416Smarkm 17457416Smarkm case Hexagon::L2_loadrd_io: 17557416Smarkm // Not handling stack stores (only reg-based addresses). 17657416Smarkm if (MI->getOperand(1).isReg()) 17757416Smarkm break; 17857416Smarkm return true; 17957416Smarkm case Hexagon::S2_storerd_io: 18057416Smarkm // Not handling stack stores (only reg-based addresses). 18157416Smarkm if (MI->getOperand(0).isReg()) 18257416Smarkm break; 18357416Smarkm return true; 18457416Smarkm case Hexagon::L2_loadrd_pi: 18557416Smarkm case Hexagon::S2_storerd_pi: 18657416Smarkm 18757416Smarkm case Hexagon::A2_tfrpi: 18857416Smarkm case Hexagon::A2_combineii: 18957416Smarkm case Hexagon::A4_combineir: 19057416Smarkm case Hexagon::A4_combineii: 191 case Hexagon::A4_combineri: 192 case Hexagon::A2_combinew: 193 case Hexagon::CONST64: 194 195 case Hexagon::A2_sxtw: 196 197 case Hexagon::A2_andp: 198 case Hexagon::A2_orp: 199 case Hexagon::A2_xorp: 200 case Hexagon::S2_asl_i_p_or: 201 case Hexagon::S2_asl_i_p: 202 case Hexagon::S2_asr_i_p: 203 case Hexagon::S2_lsr_i_p: 204 break; 205 } 206 207 for (auto &Op : MI->operands()) { 208 if (!Op.isReg()) 209 continue; 210 unsigned R = Op.getReg(); 211 if (!TargetRegisterInfo::isVirtualRegister(R)) 212 return true; 213 } 214 return false; 215} 216 217void HexagonSplitDoubleRegs::partitionRegisters(UUSetMap &P2Rs) { 218 typedef std::map<unsigned,unsigned> UUMap; 219 typedef std::vector<unsigned> UVect; 220 221 unsigned NumRegs = MRI->getNumVirtRegs(); 222 BitVector DoubleRegs(NumRegs); 223 for (unsigned i = 0; i < NumRegs; ++i) { 224 unsigned R = TargetRegisterInfo::index2VirtReg(i); 225 if (MRI->getRegClass(R) == DoubleRC) 226 DoubleRegs.set(i); 227 } 228 229 BitVector FixedRegs(NumRegs); 230 for (int x = DoubleRegs.find_first(); x >= 0; x = DoubleRegs.find_next(x)) { 231 unsigned R = TargetRegisterInfo::index2VirtReg(x); 232 MachineInstr *DefI = MRI->getVRegDef(R); 233 // In some cases a register may exist, but never be defined or used. 234 // It should never appear anywhere, but mark it as "fixed", just to be 235 // safe. 236 if (!DefI || isFixedInstr(DefI)) 237 FixedRegs.set(x); 238 } 239 240 UUSetMap AssocMap; 241 for (int x = DoubleRegs.find_first(); x >= 0; x = DoubleRegs.find_next(x)) { 242 if (FixedRegs[x]) 243 continue; 244 unsigned R = TargetRegisterInfo::index2VirtReg(x); 245 DEBUG(dbgs() << PrintReg(R, TRI) << " ~~"); 246 USet &Asc = AssocMap[R]; 247 for (auto U = MRI->use_nodbg_begin(R), Z = MRI->use_nodbg_end(); 248 U != Z; ++U) { 249 MachineOperand &Op = *U; 250 MachineInstr *UseI = Op.getParent(); 251 if (isFixedInstr(UseI)) 252 continue; 253 for (unsigned i = 0, n = UseI->getNumOperands(); i < n; ++i) { 254 MachineOperand &MO = UseI->getOperand(i); 255 // Skip non-registers or registers with subregisters. 256 if (&MO == &Op || !MO.isReg() || MO.getSubReg()) 257 continue; 258 unsigned T = MO.getReg(); 259 if (!TargetRegisterInfo::isVirtualRegister(T)) { 260 FixedRegs.set(x); 261 continue; 262 } 263 if (MRI->getRegClass(T) != DoubleRC) 264 continue; 265 unsigned u = TargetRegisterInfo::virtReg2Index(T); 266 if (FixedRegs[u]) 267 continue; 268 DEBUG(dbgs() << ' ' << PrintReg(T, TRI)); 269 Asc.insert(T); 270 // Make it symmetric. 271 AssocMap[T].insert(R); 272 } 273 } 274 DEBUG(dbgs() << '\n'); 275 } 276 277 UUMap R2P; 278 unsigned NextP = 1; 279 USet Visited; 280 for (int x = DoubleRegs.find_first(); x >= 0; x = DoubleRegs.find_next(x)) { 281 unsigned R = TargetRegisterInfo::index2VirtReg(x); 282 if (Visited.count(R)) 283 continue; 284 // Create a new partition for R. 285 unsigned ThisP = FixedRegs[x] ? 0 : NextP++; 286 UVect WorkQ; 287 WorkQ.push_back(R); 288 for (unsigned i = 0; i < WorkQ.size(); ++i) { 289 unsigned T = WorkQ[i]; 290 if (Visited.count(T)) 291 continue; 292 R2P[T] = ThisP; 293 Visited.insert(T); 294 // Add all registers associated with T. 295 USet &Asc = AssocMap[T]; 296 for (USet::iterator J = Asc.begin(), F = Asc.end(); J != F; ++J) 297 WorkQ.push_back(*J); 298 } 299 } 300 301 for (auto I : R2P) 302 P2Rs[I.second].insert(I.first); 303} 304 305static inline int32_t profitImm(unsigned Lo, unsigned Hi) { 306 int32_t P = 0; 307 bool LoZ1 = false, HiZ1 = false; 308 if (Lo == 0 || Lo == 0xFFFFFFFF) 309 P += 10, LoZ1 = true; 310 if (Hi == 0 || Hi == 0xFFFFFFFF) 311 P += 10, HiZ1 = true; 312 if (!LoZ1 && !HiZ1 && Lo == Hi) 313 P += 3; 314 return P; 315} 316 317int32_t HexagonSplitDoubleRegs::profit(const MachineInstr *MI) const { 318 unsigned ImmX = 0; 319 unsigned Opc = MI->getOpcode(); 320 switch (Opc) { 321 case TargetOpcode::PHI: 322 for (const auto &Op : MI->operands()) 323 if (!Op.getSubReg()) 324 return 0; 325 return 10; 326 case TargetOpcode::COPY: 327 if (MI->getOperand(1).getSubReg() != 0) 328 return 10; 329 return 0; 330 331 case Hexagon::L2_loadrd_io: 332 case Hexagon::S2_storerd_io: 333 return -1; 334 case Hexagon::L2_loadrd_pi: 335 case Hexagon::S2_storerd_pi: 336 return 2; 337 338 case Hexagon::A2_tfrpi: 339 case Hexagon::CONST64: { 340 uint64_t D = MI->getOperand(1).getImm(); 341 unsigned Lo = D & 0xFFFFFFFFULL; 342 unsigned Hi = D >> 32; 343 return profitImm(Lo, Hi); 344 } 345 case Hexagon::A2_combineii: 346 case Hexagon::A4_combineii: 347 return profitImm(MI->getOperand(1).getImm(), 348 MI->getOperand(2).getImm()); 349 case Hexagon::A4_combineri: 350 ImmX++; 351 case Hexagon::A4_combineir: { 352 ImmX++; 353 int64_t V = MI->getOperand(ImmX).getImm(); 354 if (V == 0 || V == -1) 355 return 10; 356 // Fall through into A2_combinew. 357 LLVM_FALLTHROUGH; 358 } 359 case Hexagon::A2_combinew: 360 return 2; 361 362 case Hexagon::A2_sxtw: 363 return 3; 364 365 case Hexagon::A2_andp: 366 case Hexagon::A2_orp: 367 case Hexagon::A2_xorp: 368 return 1; 369 370 case Hexagon::S2_asl_i_p_or: { 371 unsigned S = MI->getOperand(3).getImm(); 372 if (S == 0 || S == 32) 373 return 10; 374 return -1; 375 } 376 case Hexagon::S2_asl_i_p: 377 case Hexagon::S2_asr_i_p: 378 case Hexagon::S2_lsr_i_p: 379 unsigned S = MI->getOperand(2).getImm(); 380 if (S == 0 || S == 32) 381 return 10; 382 if (S == 16) 383 return 5; 384 if (S == 48) 385 return 7; 386 return -10; 387 } 388 389 return 0; 390} 391 392bool HexagonSplitDoubleRegs::isProfitable(const USet &Part, LoopRegMap &IRM) 393 const { 394 unsigned FixedNum = 0, SplitNum = 0, LoopPhiNum = 0; 395 int32_t TotalP = 0; 396 397 for (unsigned DR : Part) { 398 MachineInstr *DefI = MRI->getVRegDef(DR); 399 int32_t P = profit(DefI); 400 if (P == std::numeric_limits<int>::min()) 401 return false; 402 TotalP += P; 403 // Reduce the profitability of splitting induction registers. 404 if (isInduction(DR, IRM)) 405 TotalP -= 30; 406 407 for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end(); 408 U != W; ++U) { 409 MachineInstr *UseI = U->getParent(); 410 if (isFixedInstr(UseI)) { 411 FixedNum++; 412 // Calculate the cost of generating REG_SEQUENCE instructions. 413 for (auto &Op : UseI->operands()) { 414 if (Op.isReg() && Part.count(Op.getReg())) 415 if (Op.getSubReg()) 416 TotalP -= 2; 417 } 418 continue; 419 } 420 // If a register from this partition is used in a fixed instruction, 421 // and there is also a register in this partition that is used in 422 // a loop phi node, then decrease the splitting profit as this can 423 // confuse the modulo scheduler. 424 if (UseI->isPHI()) { 425 const MachineBasicBlock *PB = UseI->getParent(); 426 const MachineLoop *L = MLI->getLoopFor(PB); 427 if (L && L->getHeader() == PB) 428 LoopPhiNum++; 429 } 430 // Splittable instruction. 431 SplitNum++; 432 int32_t P = profit(UseI); 433 if (P == std::numeric_limits<int>::min()) 434 return false; 435 TotalP += P; 436 } 437 } 438 439 if (FixedNum > 0 && LoopPhiNum > 0) 440 TotalP -= 20*LoopPhiNum; 441 442 DEBUG(dbgs() << "Partition profit: " << TotalP << '\n'); 443 return TotalP > 0; 444} 445 446void HexagonSplitDoubleRegs::collectIndRegsForLoop(const MachineLoop *L, 447 USet &Rs) { 448 const MachineBasicBlock *HB = L->getHeader(); 449 const MachineBasicBlock *LB = L->getLoopLatch(); 450 if (!HB || !LB) 451 return; 452 453 // Examine the latch branch. Expect it to be a conditional branch to 454 // the header (either "br-cond header" or "br-cond exit; br header"). 455 MachineBasicBlock *TB = nullptr, *FB = nullptr; 456 MachineBasicBlock *TmpLB = const_cast<MachineBasicBlock*>(LB); 457 SmallVector<MachineOperand,2> Cond; 458 bool BadLB = TII->analyzeBranch(*TmpLB, TB, FB, Cond, false); 459 // Only analyzable conditional branches. HII::analyzeBranch will put 460 // the branch opcode as the first element of Cond, and the predicate 461 // operand as the second. 462 if (BadLB || Cond.size() != 2) 463 return; 464 // Only simple jump-conditional (with or without negation). 465 if (!TII->PredOpcodeHasJMP_c(Cond[0].getImm())) 466 return; 467 // Must go to the header. 468 if (TB != HB && FB != HB) 469 return; 470 assert(Cond[1].isReg() && "Unexpected Cond vector from analyzeBranch"); 471 // Expect a predicate register. 472 unsigned PR = Cond[1].getReg(); 473 assert(MRI->getRegClass(PR) == &Hexagon::PredRegsRegClass); 474 475 // Get the registers on which the loop controlling compare instruction 476 // depends. 477 unsigned CmpR1 = 0, CmpR2 = 0; 478 const MachineInstr *CmpI = MRI->getVRegDef(PR); 479 while (CmpI->getOpcode() == Hexagon::C2_not) 480 CmpI = MRI->getVRegDef(CmpI->getOperand(1).getReg()); 481 482 int Mask = 0, Val = 0; 483 bool OkCI = TII->analyzeCompare(*CmpI, CmpR1, CmpR2, Mask, Val); 484 if (!OkCI) 485 return; 486 // Eliminate non-double input registers. 487 if (CmpR1 && MRI->getRegClass(CmpR1) != DoubleRC) 488 CmpR1 = 0; 489 if (CmpR2 && MRI->getRegClass(CmpR2) != DoubleRC) 490 CmpR2 = 0; 491 if (!CmpR1 && !CmpR2) 492 return; 493 494 // Now examine the top of the loop: the phi nodes that could poten- 495 // tially define loop induction registers. The registers defined by 496 // such a phi node would be used in a 64-bit add, which then would 497 // be used in the loop compare instruction. 498 499 // Get the set of all double registers defined by phi nodes in the 500 // loop header. 501 typedef std::vector<unsigned> UVect; 502 UVect DP; 503 for (auto &MI : *HB) { 504 if (!MI.isPHI()) 505 break; 506 const MachineOperand &MD = MI.getOperand(0); 507 unsigned R = MD.getReg(); 508 if (MRI->getRegClass(R) == DoubleRC) 509 DP.push_back(R); 510 } 511 if (DP.empty()) 512 return; 513 514 auto NoIndOp = [this, CmpR1, CmpR2] (unsigned R) -> bool { 515 for (auto I = MRI->use_nodbg_begin(R), E = MRI->use_nodbg_end(); 516 I != E; ++I) { 517 const MachineInstr *UseI = I->getParent(); 518 if (UseI->getOpcode() != Hexagon::A2_addp) 519 continue; 520 // Get the output from the add. If it is one of the inputs to the 521 // loop-controlling compare instruction, then R is likely an induc- 522 // tion register. 523 unsigned T = UseI->getOperand(0).getReg(); 524 if (T == CmpR1 || T == CmpR2) 525 return false; 526 } 527 return true; 528 }; 529 UVect::iterator End = llvm::remove_if(DP, NoIndOp); 530 Rs.insert(DP.begin(), End); 531 Rs.insert(CmpR1); 532 Rs.insert(CmpR2); 533 534 DEBUG({ 535 dbgs() << "For loop at BB#" << HB->getNumber() << " ind regs: "; 536 dump_partition(dbgs(), Rs, *TRI); 537 dbgs() << '\n'; 538 }); 539} 540 541void HexagonSplitDoubleRegs::collectIndRegs(LoopRegMap &IRM) { 542 typedef std::vector<MachineLoop*> LoopVector; 543 LoopVector WorkQ; 544 545 for (auto I : *MLI) 546 WorkQ.push_back(I); 547 for (unsigned i = 0; i < WorkQ.size(); ++i) { 548 for (auto I : *WorkQ[i]) 549 WorkQ.push_back(I); 550 } 551 552 USet Rs; 553 for (unsigned i = 0, n = WorkQ.size(); i < n; ++i) { 554 MachineLoop *L = WorkQ[i]; 555 Rs.clear(); 556 collectIndRegsForLoop(L, Rs); 557 if (!Rs.empty()) 558 IRM.insert(std::make_pair(L, Rs)); 559 } 560} 561 562void HexagonSplitDoubleRegs::createHalfInstr(unsigned Opc, MachineInstr *MI, 563 const UUPairMap &PairMap, unsigned SubR) { 564 MachineBasicBlock &B = *MI->getParent(); 565 DebugLoc DL = MI->getDebugLoc(); 566 MachineInstr *NewI = BuildMI(B, MI, DL, TII->get(Opc)); 567 568 for (auto &Op : MI->operands()) { 569 if (!Op.isReg()) { 570 NewI->addOperand(Op); 571 continue; 572 } 573 // For register operands, set the subregister. 574 unsigned R = Op.getReg(); 575 unsigned SR = Op.getSubReg(); 576 bool isVirtReg = TargetRegisterInfo::isVirtualRegister(R); 577 bool isKill = Op.isKill(); 578 if (isVirtReg && MRI->getRegClass(R) == DoubleRC) { 579 isKill = false; 580 UUPairMap::const_iterator F = PairMap.find(R); 581 if (F == PairMap.end()) { 582 SR = SubR; 583 } else { 584 const UUPair &P = F->second; 585 R = (SubR == Hexagon::isub_lo) ? P.first : P.second; 586 SR = 0; 587 } 588 } 589 auto CO = MachineOperand::CreateReg(R, Op.isDef(), Op.isImplicit(), isKill, 590 Op.isDead(), Op.isUndef(), Op.isEarlyClobber(), SR, Op.isDebug(), 591 Op.isInternalRead()); 592 NewI->addOperand(CO); 593 } 594} 595 596void HexagonSplitDoubleRegs::splitMemRef(MachineInstr *MI, 597 const UUPairMap &PairMap) { 598 bool Load = MI->mayLoad(); 599 unsigned OrigOpc = MI->getOpcode(); 600 bool PostInc = (OrigOpc == Hexagon::L2_loadrd_pi || 601 OrigOpc == Hexagon::S2_storerd_pi); 602 MachineInstr *LowI, *HighI; 603 MachineBasicBlock &B = *MI->getParent(); 604 DebugLoc DL = MI->getDebugLoc(); 605 606 // Index of the base-address-register operand. 607 unsigned AdrX = PostInc ? (Load ? 2 : 1) 608 : (Load ? 1 : 0); 609 MachineOperand &AdrOp = MI->getOperand(AdrX); 610 unsigned RSA = getRegState(AdrOp); 611 MachineOperand &ValOp = Load ? MI->getOperand(0) 612 : (PostInc ? MI->getOperand(3) 613 : MI->getOperand(2)); 614 UUPairMap::const_iterator F = PairMap.find(ValOp.getReg()); 615 assert(F != PairMap.end()); 616 617 if (Load) { 618 const UUPair &P = F->second; 619 int64_t Off = PostInc ? 0 : MI->getOperand(2).getImm(); 620 LowI = BuildMI(B, MI, DL, TII->get(Hexagon::L2_loadri_io), P.first) 621 .addReg(AdrOp.getReg(), RSA & ~RegState::Kill, AdrOp.getSubReg()) 622 .addImm(Off); 623 HighI = BuildMI(B, MI, DL, TII->get(Hexagon::L2_loadri_io), P.second) 624 .addReg(AdrOp.getReg(), RSA & ~RegState::Kill, AdrOp.getSubReg()) 625 .addImm(Off+4); 626 } else { 627 const UUPair &P = F->second; 628 int64_t Off = PostInc ? 0 : MI->getOperand(1).getImm(); 629 LowI = BuildMI(B, MI, DL, TII->get(Hexagon::S2_storeri_io)) 630 .addReg(AdrOp.getReg(), RSA & ~RegState::Kill, AdrOp.getSubReg()) 631 .addImm(Off) 632 .addReg(P.first); 633 HighI = BuildMI(B, MI, DL, TII->get(Hexagon::S2_storeri_io)) 634 .addReg(AdrOp.getReg(), RSA & ~RegState::Kill, AdrOp.getSubReg()) 635 .addImm(Off+4) 636 .addReg(P.second); 637 } 638 639 if (PostInc) { 640 // Create the increment of the address register. 641 int64_t Inc = Load ? MI->getOperand(3).getImm() 642 : MI->getOperand(2).getImm(); 643 MachineOperand &UpdOp = Load ? MI->getOperand(1) : MI->getOperand(0); 644 const TargetRegisterClass *RC = MRI->getRegClass(UpdOp.getReg()); 645 unsigned NewR = MRI->createVirtualRegister(RC); 646 assert(!UpdOp.getSubReg() && "Def operand with subreg"); 647 BuildMI(B, MI, DL, TII->get(Hexagon::A2_addi), NewR) 648 .addReg(AdrOp.getReg(), RSA) 649 .addImm(Inc); 650 MRI->replaceRegWith(UpdOp.getReg(), NewR); 651 // The original instruction will be deleted later. 652 } 653 654 // Generate a new pair of memory-operands. 655 MachineFunction &MF = *B.getParent(); 656 for (auto &MO : MI->memoperands()) { 657 const MachinePointerInfo &Ptr = MO->getPointerInfo(); 658 MachineMemOperand::Flags F = MO->getFlags(); 659 int A = MO->getAlignment(); 660 661 auto *Tmp1 = MF.getMachineMemOperand(Ptr, F, 4/*size*/, A); 662 LowI->addMemOperand(MF, Tmp1); 663 auto *Tmp2 = MF.getMachineMemOperand(Ptr, F, 4/*size*/, std::min(A, 4)); 664 HighI->addMemOperand(MF, Tmp2); 665 } 666} 667 668void HexagonSplitDoubleRegs::splitImmediate(MachineInstr *MI, 669 const UUPairMap &PairMap) { 670 MachineOperand &Op0 = MI->getOperand(0); 671 MachineOperand &Op1 = MI->getOperand(1); 672 assert(Op0.isReg() && Op1.isImm()); 673 uint64_t V = Op1.getImm(); 674 675 MachineBasicBlock &B = *MI->getParent(); 676 DebugLoc DL = MI->getDebugLoc(); 677 UUPairMap::const_iterator F = PairMap.find(Op0.getReg()); 678 assert(F != PairMap.end()); 679 const UUPair &P = F->second; 680 681 // The operand to A2_tfrsi can only have 32 significant bits. Immediate 682 // values in MachineOperand are stored as 64-bit integers, and so the 683 // value -1 may be represented either as 64-bit -1, or 4294967295. Both 684 // will have the 32 higher bits truncated in the end, but -1 will remain 685 // as -1, while the latter may appear to be a large unsigned value 686 // requiring a constant extender. The casting to int32_t will select the 687 // former representation. (The same reasoning applies to all 32-bit 688 // values.) 689 BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), P.first) 690 .addImm(int32_t(V & 0xFFFFFFFFULL)); 691 BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), P.second) 692 .addImm(int32_t(V >> 32)); 693} 694 695void HexagonSplitDoubleRegs::splitCombine(MachineInstr *MI, 696 const UUPairMap &PairMap) { 697 MachineOperand &Op0 = MI->getOperand(0); 698 MachineOperand &Op1 = MI->getOperand(1); 699 MachineOperand &Op2 = MI->getOperand(2); 700 assert(Op0.isReg()); 701 702 MachineBasicBlock &B = *MI->getParent(); 703 DebugLoc DL = MI->getDebugLoc(); 704 UUPairMap::const_iterator F = PairMap.find(Op0.getReg()); 705 assert(F != PairMap.end()); 706 const UUPair &P = F->second; 707 708 if (Op1.isImm()) { 709 BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), P.second) 710 .addImm(Op1.getImm()); 711 } else if (Op1.isReg()) { 712 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), P.second) 713 .addReg(Op1.getReg(), getRegState(Op1), Op1.getSubReg()); 714 } else 715 llvm_unreachable("Unexpected operand"); 716 717 if (Op2.isImm()) { 718 BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), P.first) 719 .addImm(Op2.getImm()); 720 } else if (Op2.isReg()) { 721 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), P.first) 722 .addReg(Op2.getReg(), getRegState(Op2), Op2.getSubReg()); 723 } else 724 llvm_unreachable("Unexpected operand"); 725} 726 727void HexagonSplitDoubleRegs::splitExt(MachineInstr *MI, 728 const UUPairMap &PairMap) { 729 MachineOperand &Op0 = MI->getOperand(0); 730 MachineOperand &Op1 = MI->getOperand(1); 731 assert(Op0.isReg() && Op1.isReg()); 732 733 MachineBasicBlock &B = *MI->getParent(); 734 DebugLoc DL = MI->getDebugLoc(); 735 UUPairMap::const_iterator F = PairMap.find(Op0.getReg()); 736 assert(F != PairMap.end()); 737 const UUPair &P = F->second; 738 unsigned RS = getRegState(Op1); 739 740 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), P.first) 741 .addReg(Op1.getReg(), RS & ~RegState::Kill, Op1.getSubReg()); 742 BuildMI(B, MI, DL, TII->get(Hexagon::S2_asr_i_r), P.second) 743 .addReg(Op1.getReg(), RS, Op1.getSubReg()) 744 .addImm(31); 745} 746 747void HexagonSplitDoubleRegs::splitShift(MachineInstr *MI, 748 const UUPairMap &PairMap) { 749 using namespace Hexagon; 750 751 MachineOperand &Op0 = MI->getOperand(0); 752 MachineOperand &Op1 = MI->getOperand(1); 753 MachineOperand &Op2 = MI->getOperand(2); 754 assert(Op0.isReg() && Op1.isReg() && Op2.isImm()); 755 int64_t Sh64 = Op2.getImm(); 756 assert(Sh64 >= 0 && Sh64 < 64); 757 unsigned S = Sh64; 758 759 UUPairMap::const_iterator F = PairMap.find(Op0.getReg()); 760 assert(F != PairMap.end()); 761 const UUPair &P = F->second; 762 unsigned LoR = P.first; 763 unsigned HiR = P.second; 764 765 unsigned Opc = MI->getOpcode(); 766 bool Right = (Opc == S2_lsr_i_p || Opc == S2_asr_i_p); 767 bool Left = !Right; 768 bool Signed = (Opc == S2_asr_i_p); 769 770 MachineBasicBlock &B = *MI->getParent(); 771 DebugLoc DL = MI->getDebugLoc(); 772 unsigned RS = getRegState(Op1); 773 unsigned ShiftOpc = Left ? S2_asl_i_r 774 : (Signed ? S2_asr_i_r : S2_lsr_i_r); 775 unsigned LoSR = isub_lo; 776 unsigned HiSR = isub_hi; 777 778 if (S == 0) { 779 // No shift, subregister copy. 780 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), LoR) 781 .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR); 782 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), HiR) 783 .addReg(Op1.getReg(), RS, HiSR); 784 } else if (S < 32) { 785 const TargetRegisterClass *IntRC = &IntRegsRegClass; 786 unsigned TmpR = MRI->createVirtualRegister(IntRC); 787 // Expansion: 788 // Shift left: DR = shl R, #s 789 // LoR = shl R.lo, #s 790 // TmpR = extractu R.lo, #s, #32-s 791 // HiR = or (TmpR, asl(R.hi, #s)) 792 // Shift right: DR = shr R, #s 793 // HiR = shr R.hi, #s 794 // TmpR = shr R.lo, #s 795 // LoR = insert TmpR, R.hi, #s, #32-s 796 797 // Shift left: 798 // LoR = shl R.lo, #s 799 // Shift right: 800 // TmpR = shr R.lo, #s 801 802 // Make a special case for A2_aslh and A2_asrh (they are predicable as 803 // opposed to S2_asl_i_r/S2_asr_i_r). 804 if (S == 16 && Left) 805 BuildMI(B, MI, DL, TII->get(A2_aslh), LoR) 806 .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR); 807 else if (S == 16 && Signed) 808 BuildMI(B, MI, DL, TII->get(A2_asrh), TmpR) 809 .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR); 810 else 811 BuildMI(B, MI, DL, TII->get(ShiftOpc), (Left ? LoR : TmpR)) 812 .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR) 813 .addImm(S); 814 815 if (Left) { 816 // TmpR = extractu R.lo, #s, #32-s 817 BuildMI(B, MI, DL, TII->get(S2_extractu), TmpR) 818 .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR) 819 .addImm(S) 820 .addImm(32-S); 821 // HiR = or (TmpR, asl(R.hi, #s)) 822 BuildMI(B, MI, DL, TII->get(S2_asl_i_r_or), HiR) 823 .addReg(TmpR) 824 .addReg(Op1.getReg(), RS, HiSR) 825 .addImm(S); 826 } else { 827 // HiR = shr R.hi, #s 828 BuildMI(B, MI, DL, TII->get(ShiftOpc), HiR) 829 .addReg(Op1.getReg(), RS & ~RegState::Kill, HiSR) 830 .addImm(S); 831 // LoR = insert TmpR, R.hi, #s, #32-s 832 BuildMI(B, MI, DL, TII->get(S2_insert), LoR) 833 .addReg(TmpR) 834 .addReg(Op1.getReg(), RS, HiSR) 835 .addImm(S) 836 .addImm(32-S); 837 } 838 } else if (S == 32) { 839 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), (Left ? HiR : LoR)) 840 .addReg(Op1.getReg(), RS & ~RegState::Kill, (Left ? LoSR : HiSR)); 841 if (!Signed) 842 BuildMI(B, MI, DL, TII->get(A2_tfrsi), (Left ? LoR : HiR)) 843 .addImm(0); 844 else // Must be right shift. 845 BuildMI(B, MI, DL, TII->get(S2_asr_i_r), HiR) 846 .addReg(Op1.getReg(), RS, HiSR) 847 .addImm(31); 848 } else if (S < 64) { 849 S -= 32; 850 if (S == 16 && Left) 851 BuildMI(B, MI, DL, TII->get(A2_aslh), HiR) 852 .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR); 853 else if (S == 16 && Signed) 854 BuildMI(B, MI, DL, TII->get(A2_asrh), LoR) 855 .addReg(Op1.getReg(), RS & ~RegState::Kill, HiSR); 856 else 857 BuildMI(B, MI, DL, TII->get(ShiftOpc), (Left ? HiR : LoR)) 858 .addReg(Op1.getReg(), RS & ~RegState::Kill, (Left ? LoSR : HiSR)) 859 .addImm(S); 860 861 if (Signed) 862 BuildMI(B, MI, DL, TII->get(S2_asr_i_r), HiR) 863 .addReg(Op1.getReg(), RS, HiSR) 864 .addImm(31); 865 else 866 BuildMI(B, MI, DL, TII->get(A2_tfrsi), (Left ? LoR : HiR)) 867 .addImm(0); 868 } 869} 870 871void HexagonSplitDoubleRegs::splitAslOr(MachineInstr *MI, 872 const UUPairMap &PairMap) { 873 using namespace Hexagon; 874 875 MachineOperand &Op0 = MI->getOperand(0); 876 MachineOperand &Op1 = MI->getOperand(1); 877 MachineOperand &Op2 = MI->getOperand(2); 878 MachineOperand &Op3 = MI->getOperand(3); 879 assert(Op0.isReg() && Op1.isReg() && Op2.isReg() && Op3.isImm()); 880 int64_t Sh64 = Op3.getImm(); 881 assert(Sh64 >= 0 && Sh64 < 64); 882 unsigned S = Sh64; 883 884 UUPairMap::const_iterator F = PairMap.find(Op0.getReg()); 885 assert(F != PairMap.end()); 886 const UUPair &P = F->second; 887 unsigned LoR = P.first; 888 unsigned HiR = P.second; 889 890 MachineBasicBlock &B = *MI->getParent(); 891 DebugLoc DL = MI->getDebugLoc(); 892 unsigned RS1 = getRegState(Op1); 893 unsigned RS2 = getRegState(Op2); 894 const TargetRegisterClass *IntRC = &IntRegsRegClass; 895 896 unsigned LoSR = isub_lo; 897 unsigned HiSR = isub_hi; 898 899 // Op0 = S2_asl_i_p_or Op1, Op2, Op3 900 // means: Op0 = or (Op1, asl(Op2, Op3)) 901 902 // Expansion of 903 // DR = or (R1, asl(R2, #s)) 904 // 905 // LoR = or (R1.lo, asl(R2.lo, #s)) 906 // Tmp1 = extractu R2.lo, #s, #32-s 907 // Tmp2 = or R1.hi, Tmp1 908 // HiR = or (Tmp2, asl(R2.hi, #s)) 909 910 if (S == 0) { 911 // DR = or (R1, asl(R2, #0)) 912 // -> or (R1, R2) 913 // i.e. LoR = or R1.lo, R2.lo 914 // HiR = or R1.hi, R2.hi 915 BuildMI(B, MI, DL, TII->get(A2_or), LoR) 916 .addReg(Op1.getReg(), RS1 & ~RegState::Kill, LoSR) 917 .addReg(Op2.getReg(), RS2 & ~RegState::Kill, LoSR); 918 BuildMI(B, MI, DL, TII->get(A2_or), HiR) 919 .addReg(Op1.getReg(), RS1, HiSR) 920 .addReg(Op2.getReg(), RS2, HiSR); 921 } else if (S < 32) { 922 BuildMI(B, MI, DL, TII->get(S2_asl_i_r_or), LoR) 923 .addReg(Op1.getReg(), RS1 & ~RegState::Kill, LoSR) 924 .addReg(Op2.getReg(), RS2 & ~RegState::Kill, LoSR) 925 .addImm(S); 926 unsigned TmpR1 = MRI->createVirtualRegister(IntRC); 927 BuildMI(B, MI, DL, TII->get(S2_extractu), TmpR1) 928 .addReg(Op2.getReg(), RS2 & ~RegState::Kill, LoSR) 929 .addImm(S) 930 .addImm(32-S); 931 unsigned TmpR2 = MRI->createVirtualRegister(IntRC); 932 BuildMI(B, MI, DL, TII->get(A2_or), TmpR2) 933 .addReg(Op1.getReg(), RS1, HiSR) 934 .addReg(TmpR1); 935 BuildMI(B, MI, DL, TII->get(S2_asl_i_r_or), HiR) 936 .addReg(TmpR2) 937 .addReg(Op2.getReg(), RS2, HiSR) 938 .addImm(S); 939 } else if (S == 32) { 940 // DR = or (R1, asl(R2, #32)) 941 // -> or R1, R2.lo 942 // LoR = R1.lo 943 // HiR = or R1.hi, R2.lo 944 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), LoR) 945 .addReg(Op1.getReg(), RS1 & ~RegState::Kill, LoSR); 946 BuildMI(B, MI, DL, TII->get(A2_or), HiR) 947 .addReg(Op1.getReg(), RS1, HiSR) 948 .addReg(Op2.getReg(), RS2, LoSR); 949 } else if (S < 64) { 950 // DR = or (R1, asl(R2, #s)) 951 // 952 // LoR = R1:lo 953 // HiR = or (R1:hi, asl(R2:lo, #s-32)) 954 S -= 32; 955 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), LoR) 956 .addReg(Op1.getReg(), RS1 & ~RegState::Kill, LoSR); 957 BuildMI(B, MI, DL, TII->get(S2_asl_i_r_or), HiR) 958 .addReg(Op1.getReg(), RS1, HiSR) 959 .addReg(Op2.getReg(), RS2, LoSR) 960 .addImm(S); 961 } 962} 963 964bool HexagonSplitDoubleRegs::splitInstr(MachineInstr *MI, 965 const UUPairMap &PairMap) { 966 using namespace Hexagon; 967 968 DEBUG(dbgs() << "Splitting: " << *MI); 969 bool Split = false; 970 unsigned Opc = MI->getOpcode(); 971 972 switch (Opc) { 973 case TargetOpcode::PHI: 974 case TargetOpcode::COPY: { 975 unsigned DstR = MI->getOperand(0).getReg(); 976 if (MRI->getRegClass(DstR) == DoubleRC) { 977 createHalfInstr(Opc, MI, PairMap, isub_lo); 978 createHalfInstr(Opc, MI, PairMap, isub_hi); 979 Split = true; 980 } 981 break; 982 } 983 case A2_andp: 984 createHalfInstr(A2_and, MI, PairMap, isub_lo); 985 createHalfInstr(A2_and, MI, PairMap, isub_hi); 986 Split = true; 987 break; 988 case A2_orp: 989 createHalfInstr(A2_or, MI, PairMap, isub_lo); 990 createHalfInstr(A2_or, MI, PairMap, isub_hi); 991 Split = true; 992 break; 993 case A2_xorp: 994 createHalfInstr(A2_xor, MI, PairMap, isub_lo); 995 createHalfInstr(A2_xor, MI, PairMap, isub_hi); 996 Split = true; 997 break; 998 999 case L2_loadrd_io: 1000 case L2_loadrd_pi: 1001 case S2_storerd_io: 1002 case S2_storerd_pi: 1003 splitMemRef(MI, PairMap); 1004 Split = true; 1005 break; 1006 1007 case A2_tfrpi: 1008 case CONST64: 1009 splitImmediate(MI, PairMap); 1010 Split = true; 1011 break; 1012 1013 case A2_combineii: 1014 case A4_combineir: 1015 case A4_combineii: 1016 case A4_combineri: 1017 case A2_combinew: 1018 splitCombine(MI, PairMap); 1019 Split = true; 1020 break; 1021 1022 case A2_sxtw: 1023 splitExt(MI, PairMap); 1024 Split = true; 1025 break; 1026 1027 case S2_asl_i_p: 1028 case S2_asr_i_p: 1029 case S2_lsr_i_p: 1030 splitShift(MI, PairMap); 1031 Split = true; 1032 break; 1033 1034 case S2_asl_i_p_or: 1035 splitAslOr(MI, PairMap); 1036 Split = true; 1037 break; 1038 1039 default: 1040 llvm_unreachable("Instruction not splitable"); 1041 return false; 1042 } 1043 1044 return Split; 1045} 1046 1047void HexagonSplitDoubleRegs::replaceSubregUses(MachineInstr *MI, 1048 const UUPairMap &PairMap) { 1049 for (auto &Op : MI->operands()) { 1050 if (!Op.isReg() || !Op.isUse() || !Op.getSubReg()) 1051 continue; 1052 unsigned R = Op.getReg(); 1053 UUPairMap::const_iterator F = PairMap.find(R); 1054 if (F == PairMap.end()) 1055 continue; 1056 const UUPair &P = F->second; 1057 switch (Op.getSubReg()) { 1058 case Hexagon::isub_lo: 1059 Op.setReg(P.first); 1060 break; 1061 case Hexagon::isub_hi: 1062 Op.setReg(P.second); 1063 break; 1064 } 1065 Op.setSubReg(0); 1066 } 1067} 1068 1069void HexagonSplitDoubleRegs::collapseRegPairs(MachineInstr *MI, 1070 const UUPairMap &PairMap) { 1071 MachineBasicBlock &B = *MI->getParent(); 1072 DebugLoc DL = MI->getDebugLoc(); 1073 1074 for (auto &Op : MI->operands()) { 1075 if (!Op.isReg() || !Op.isUse()) 1076 continue; 1077 unsigned R = Op.getReg(); 1078 if (!TargetRegisterInfo::isVirtualRegister(R)) 1079 continue; 1080 if (MRI->getRegClass(R) != DoubleRC || Op.getSubReg()) 1081 continue; 1082 UUPairMap::const_iterator F = PairMap.find(R); 1083 if (F == PairMap.end()) 1084 continue; 1085 const UUPair &Pr = F->second; 1086 unsigned NewDR = MRI->createVirtualRegister(DoubleRC); 1087 BuildMI(B, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), NewDR) 1088 .addReg(Pr.first) 1089 .addImm(Hexagon::isub_lo) 1090 .addReg(Pr.second) 1091 .addImm(Hexagon::isub_hi); 1092 Op.setReg(NewDR); 1093 } 1094} 1095 1096bool HexagonSplitDoubleRegs::splitPartition(const USet &Part) { 1097 const TargetRegisterClass *IntRC = &Hexagon::IntRegsRegClass; 1098 typedef std::set<MachineInstr*> MISet; 1099 bool Changed = false; 1100 1101 DEBUG(dbgs() << "Splitting partition: "; dump_partition(dbgs(), Part, *TRI); 1102 dbgs() << '\n'); 1103 1104 UUPairMap PairMap; 1105 1106 MISet SplitIns; 1107 for (unsigned DR : Part) { 1108 MachineInstr *DefI = MRI->getVRegDef(DR); 1109 SplitIns.insert(DefI); 1110 1111 // Collect all instructions, including fixed ones. We won't split them, 1112 // but we need to visit them again to insert the REG_SEQUENCE instructions. 1113 for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end(); 1114 U != W; ++U) 1115 SplitIns.insert(U->getParent()); 1116 1117 unsigned LoR = MRI->createVirtualRegister(IntRC); 1118 unsigned HiR = MRI->createVirtualRegister(IntRC); 1119 DEBUG(dbgs() << "Created mapping: " << PrintReg(DR, TRI) << " -> " 1120 << PrintReg(HiR, TRI) << ':' << PrintReg(LoR, TRI) << '\n'); 1121 PairMap.insert(std::make_pair(DR, UUPair(LoR, HiR))); 1122 } 1123 1124 MISet Erase; 1125 for (auto MI : SplitIns) { 1126 if (isFixedInstr(MI)) { 1127 collapseRegPairs(MI, PairMap); 1128 } else { 1129 bool Done = splitInstr(MI, PairMap); 1130 if (Done) 1131 Erase.insert(MI); 1132 Changed |= Done; 1133 } 1134 } 1135 1136 for (unsigned DR : Part) { 1137 // Before erasing "double" instructions, revisit all uses of the double 1138 // registers in this partition, and replace all uses of them with subre- 1139 // gisters, with the corresponding single registers. 1140 MISet Uses; 1141 for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end(); 1142 U != W; ++U) 1143 Uses.insert(U->getParent()); 1144 for (auto M : Uses) 1145 replaceSubregUses(M, PairMap); 1146 } 1147 1148 for (auto MI : Erase) { 1149 MachineBasicBlock *B = MI->getParent(); 1150 B->erase(MI); 1151 } 1152 1153 return Changed; 1154} 1155 1156bool HexagonSplitDoubleRegs::runOnMachineFunction(MachineFunction &MF) { 1157 DEBUG(dbgs() << "Splitting double registers in function: " 1158 << MF.getName() << '\n'); 1159 1160 if (skipFunction(*MF.getFunction())) 1161 return false; 1162 1163 auto &ST = MF.getSubtarget<HexagonSubtarget>(); 1164 TRI = ST.getRegisterInfo(); 1165 TII = ST.getInstrInfo(); 1166 MRI = &MF.getRegInfo(); 1167 MLI = &getAnalysis<MachineLoopInfo>(); 1168 1169 UUSetMap P2Rs; 1170 LoopRegMap IRM; 1171 1172 collectIndRegs(IRM); 1173 partitionRegisters(P2Rs); 1174 1175 DEBUG({ 1176 dbgs() << "Register partitioning: (partition #0 is fixed)\n"; 1177 for (UUSetMap::iterator I = P2Rs.begin(), E = P2Rs.end(); I != E; ++I) { 1178 dbgs() << '#' << I->first << " -> "; 1179 dump_partition(dbgs(), I->second, *TRI); 1180 dbgs() << '\n'; 1181 } 1182 }); 1183 1184 bool Changed = false; 1185 int Limit = MaxHSDR; 1186 1187 for (UUSetMap::iterator I = P2Rs.begin(), E = P2Rs.end(); I != E; ++I) { 1188 if (I->first == 0) 1189 continue; 1190 if (Limit >= 0 && Counter >= Limit) 1191 break; 1192 USet &Part = I->second; 1193 DEBUG(dbgs() << "Calculating profit for partition #" << I->first << '\n'); 1194 if (!isProfitable(Part, IRM)) 1195 continue; 1196 Counter++; 1197 Changed |= splitPartition(Part); 1198 } 1199 1200 return Changed; 1201} 1202 1203FunctionPass *llvm::createHexagonSplitDoubleRegs() { 1204 return new HexagonSplitDoubleRegs(); 1205} 1206