Index: lib/CodeGen/MachineSink.cpp =================================================================== --- lib/CodeGen/MachineSink.cpp +++ lib/CodeGen/MachineSink.cpp @@ -26,6 +26,7 @@ #include "llvm/CodeGen/MachineBlockFrequencyInfo.h" #include "llvm/CodeGen/MachineBranchProbabilityInfo.h" #include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" @@ -78,6 +79,7 @@ STATISTIC(NumSplit, "Number of critical edges split"); STATISTIC(NumCoalesces, "Number of copies coalesced"); STATISTIC(NumPostRACopySink, "Number of copies sunk after RA"); +STATISTIC(NumPostRASpillSink, "Number of spills sunk after RA"); namespace { @@ -940,6 +942,8 @@ //===----------------------------------------------------------------------===// namespace { +typedef DenseMap> StackUseMapTy; + class PostRAMachineSinking : public MachineFunctionPass { public: bool runOnMachineFunction(MachineFunction &MF) override; @@ -950,6 +954,7 @@ void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesCFG(); + AU.addRequired(); MachineFunctionPass::getAnalysisUsage(AU); } @@ -959,21 +964,140 @@ } private: + const TargetRegisterInfo *TRI; + const TargetInstrInfo *TII; + const MachineFrameInfo *MFI; + const MachineDominatorTree *MDT; + /// Track which register units have been modified and used. LiveRegUnits ModifiedRegUnits, UsedRegUnits; + /// Hold the uses of stack slots. + StackUseMapTy StackUseMap; + + /// Find basic blocks where there are loads from stack slots. + bool scanLoadFromStackSlot(MachineFunction &MF); + + /// Sink register spills close to their reloads. + bool tryToSinkSpill(MachineInstr &MI, MachineBasicBlock &CurBB, + SmallPtrSetImpl &SinkableBBs); + /// Sink Copy instructions unused in the same block close to their uses in /// successors. - bool tryToSinkCopy(MachineBasicBlock &BB, MachineFunction &MF, - const TargetRegisterInfo *TRI, const TargetInstrInfo *TII); + bool tryToSinkCopy(MachineInstr &MI, MachineBasicBlock &CurBB, + SmallPtrSetImpl &SinkableBBs); + + /// Perform sinking for Copy and store to stack. + bool tryToSink(MachineBasicBlock &BB, bool EnableSinkSpill); }; } // namespace char PostRAMachineSinking::ID = 0; char &llvm::PostRAMachineSinkingID = PostRAMachineSinking::ID; -INITIALIZE_PASS(PostRAMachineSinking, "postra-machine-sink", - "PostRA Machine Sink", false, false) +INITIALIZE_PASS_BEGIN(PostRAMachineSinking, "postra-machine-sink", + "PostRA Machine Sink", false, false) +INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) +INITIALIZE_PASS_END(PostRAMachineSinking, "postra-machine-sink", + "PostRA Machine Sink", false, false) + +// Return true if there is potential path from FromMBB to any basic block which +// contains uses of FI. +static bool isReachableToUseOfFI(MachineBasicBlock *FromMBB, + StackUseMapTy &StackUseMap, int FI, + const MachineDominatorTree *MDT) { + SmallPtrSet &UseBBs = StackUseMap[FI]; + if (UseBBs.count(FromMBB)) + return true; + + if (any_of(UseBBs, [&](MachineBasicBlock *UseBB) { + return MDT->dominates(FromMBB, UseBB); + })) + return true; + + // Limit the number of blocks we visit for compile times. + // The default value (32) was chosen arbitrarily. + unsigned Limit = 32; + + DenseSet Visited; + SmallVector Worklist(FromMBB->succ_begin(), + FromMBB->succ_end()); + while (!Worklist.empty()) { + MachineBasicBlock *MBB = Worklist.pop_back_val(); + if (!Visited.insert(MBB).second) + continue; + if (UseBBs.count(MBB)) + return true; + + // If it reaches to the limit, conservatively return true (there is + // potentially a path). + if (!--Limit) + return true; + + Worklist.append(MBB->succ_begin(), MBB->succ_end()); + } + return false; +} + +static MachineBasicBlock * +getSingleReloadInSuccBB(MachineBasicBlock &CurBB, StackUseMapTy &StackUseMap, + SmallPtrSetImpl &SinkableBBs, + int FI, const MachineDominatorTree *MDT) { + // TODO: We should track access to FI just like we track the def of register. + if (StackUseMap[FI].count(&CurBB)) + return nullptr; + + MachineBasicBlock *SingleReachableSucc = nullptr; + + // Try to find a single sinkable successor from which all use of FI is + // reachable. + for (auto *SI : SinkableBBs) { + if (SI == &CurBB) + continue; + if (isReachableToUseOfFI(SI, StackUseMap, FI, MDT)) { + if (SingleReachableSucc) + return nullptr; + SingleReachableSucc = SI; + } + } + if (!SingleReachableSucc) + return nullptr; + + // Check if there is any other successor through which a use of FI is reachable. + for (MachineBasicBlock *SI : CurBB.successors()) + if (!SinkableBBs.count(SI) && isReachableToUseOfFI(SI, StackUseMap, FI, MDT)) + return nullptr; + + return SingleReachableSucc; +} + +bool PostRAMachineSinking::scanLoadFromStackSlot(MachineFunction &MF) { + StackUseMap.clear(); + for (auto &MBB : MF) + for (auto &MI : MBB) { + for (const MachineOperand &MO : MI.operands()) { + if (!MO.isFI()) + continue; + int FI = MO.getIndex(); + if (!MFI->isSpillSlotObjectIndex(FI)) + continue; + // If MMO is empty, conservatively assume that the instruction load from + // some FI. + if (MI.memoperands_empty()) + return false; + for (MachineInstr::mmo_iterator o = MI.memoperands_begin(), + oe = MI.memoperands_end(); + o != oe; ++o) + if ((*o)->isLoad()) + if (const FixedStackPseudoSourceValue *Value = + dyn_cast_or_null( + (*o)->getPseudoValue())) + if (Value->getFrameIndex() == FI) + StackUseMap[FI].insert(&MBB); + } + } + return true; +} static bool aliasWithRegsInLiveIn(MachineBasicBlock &MBB, unsigned Reg, const TargetRegisterInfo *TRI) { @@ -1025,15 +1149,15 @@ return SingleBB; } -static void clearKillFlags(MachineInstr *MI, MachineBasicBlock &CurBB, +static void clearKillFlags(MachineInstr &MI, MachineBasicBlock &CurBB, SmallVectorImpl &UsedOpsInCopy, LiveRegUnits &UsedRegUnits, const TargetRegisterInfo *TRI) { for (auto U : UsedOpsInCopy) { - MachineOperand &MO = MI->getOperand(U); + MachineOperand &MO = MI.getOperand(U); unsigned SrcReg = MO.getReg(); if (!UsedRegUnits.available(SrcReg)) { - MachineBasicBlock::iterator NI = std::next(MI->getIterator()); + MachineBasicBlock::iterator NI = std::next(MI.getIterator()); for (MachineInstr &UI : make_range(NI, CurBB.end())) { if (UI.killsRegister(SrcReg, TRI)) { UI.clearRegisterKills(SrcReg, TRI); @@ -1045,26 +1169,26 @@ } } -static void updateLiveIn(MachineInstr *MI, MachineBasicBlock *SuccBB, +static void updateLiveIn(MachineInstr &MI, MachineBasicBlock *SuccBB, SmallVectorImpl &UsedOpsInCopy, SmallVectorImpl &DefedRegsInCopy) { for (auto DefReg : DefedRegsInCopy) SuccBB->removeLiveIn(DefReg); for (auto U : UsedOpsInCopy) { - unsigned Reg = MI->getOperand(U).getReg(); + unsigned Reg = MI.getOperand(U).getReg(); if (!SuccBB->isLiveIn(Reg)) SuccBB->addLiveIn(Reg); } } -static bool hasRegisterDependency(MachineInstr *MI, +static bool hasRegisterDependency(MachineInstr &MI, SmallVectorImpl &UsedOpsInCopy, SmallVectorImpl &DefedRegsInCopy, LiveRegUnits &ModifiedRegUnits, LiveRegUnits &UsedRegUnits) { bool HasRegDependency = false; - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - MachineOperand &MO = MI->getOperand(i); + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI.getOperand(i); if (!MO.isReg()) continue; unsigned Reg = MO.getReg(); @@ -1092,16 +1216,91 @@ return HasRegDependency; } -bool PostRAMachineSinking::tryToSinkCopy(MachineBasicBlock &CurBB, - MachineFunction &MF, - const TargetRegisterInfo *TRI, - const TargetInstrInfo *TII) { +bool PostRAMachineSinking::tryToSinkSpill(MachineInstr &MI, + MachineBasicBlock &CurBB, + SmallPtrSetImpl &SinkableBBs) { + int FI; + unsigned StrValReg = TII->isStoreToStackSlot(MI, FI); + if (!StrValReg || !MFI->isSpillSlotObjectIndex(FI)) + return false; + + // Track the operand index for use in Copy. + SmallVector UsedOpsInCopy; + // Track the register number defed in Copy. + SmallVector DefedRegsInCopy; + // Don't sink the spill if it would violate a register dependency. + if (hasRegisterDependency(MI, UsedOpsInCopy, DefedRegsInCopy, + ModifiedRegUnits, UsedRegUnits)) + return false; + + MachineBasicBlock *SuccBB = + getSingleReloadInSuccBB(CurBB, StackUseMap, SinkableBBs, FI, MDT); + + if (!SuccBB) + return false; + + // Clear the kill flag if SrcReg is killed between MI and the end of the + // block. + clearKillFlags(MI, CurBB, UsedOpsInCopy, UsedRegUnits, TRI); + + // FIXME: We should collect debug values and sink them together. + MachineBasicBlock::iterator InsertPos = SuccBB->getFirstNonPHI(); + SuccBB->splice(InsertPos, &CurBB, &MI); + updateLiveIn(MI, SuccBB, UsedOpsInCopy, DefedRegsInCopy); + + ++NumPostRASpillSink; + return true; +} + +bool PostRAMachineSinking::tryToSinkCopy( + MachineInstr &MI, MachineBasicBlock &CurBB, + SmallPtrSetImpl &SinkableBBs) { + if (!MI.getOperand(0).isRenamable()) + return false; + + // Track the operand index for use in Copy. + SmallVector UsedOpsInCopy; + // Track the register number defed in Copy. + SmallVector DefedRegsInCopy; + + // Don't sink the COPY if it would violate a register dependency. + if (hasRegisterDependency(MI, UsedOpsInCopy, DefedRegsInCopy, + ModifiedRegUnits, UsedRegUnits)) + return false; + + assert((!UsedOpsInCopy.empty() && !DefedRegsInCopy.empty()) && + "Unexpect SrcReg or DefReg"); + MachineBasicBlock *SuccBB = + getSingleLiveInSuccBB(CurBB, SinkableBBs, DefedRegsInCopy, TRI); + + // Don't sink if we cannot find a single sinkable successor in which Reg + // is live-in. + if (!SuccBB) + return false; + + assert((SuccBB->pred_size() == 1 && *SuccBB->pred_begin() == &CurBB) && + + "Unexpected predecessor"); + // Clear the kill flag if SrcReg is killed between MI and the end of the + // block. + clearKillFlags(MI, CurBB, UsedOpsInCopy, UsedRegUnits, TRI); + + MachineBasicBlock::iterator InsertPos = SuccBB->getFirstNonPHI(); + SuccBB->splice(InsertPos, &CurBB, MI); + updateLiveIn(MI, SuccBB, UsedOpsInCopy, DefedRegsInCopy); + + ++NumPostRACopySink; + return true; +} + +bool PostRAMachineSinking::tryToSink(MachineBasicBlock &CurBB, + bool EnableSinkSpill) { SmallPtrSet SinkableBBs; // FIXME: For now, we sink only to a successor which has a single predecessor - // so that we can directly sink COPY instructions to the successor without - // adding any new block or branch instruction. + // so that we can directly sink instructions to the successor without adding + // any new block or branch instruction. for (MachineBasicBlock *SI : CurBB.successors()) - if (!SI->livein_empty() && SI->pred_size() == 1) + if (SI->pred_size() == 1) SinkableBBs.insert(SI); if (SinkableBBs.empty()) @@ -1115,67 +1314,46 @@ UsedRegUnits.clear(); for (auto I = CurBB.rbegin(), E = CurBB.rend(); I != E;) { - MachineInstr *MI = &*I; + MachineInstr &MI = *I; ++I; - // Do not move any instruction across function call. - if (MI->isCall()) - return false; - - if (!MI->isCopy() || !MI->getOperand(0).isRenamable()) { - LiveRegUnits::accumulateUsedDefed(*MI, ModifiedRegUnits, UsedRegUnits, - TRI); - continue; - } - - // Track the operand index for use in Copy. - SmallVector UsedOpsInCopy; - // Track the register number defed in Copy. - SmallVector DefedRegsInCopy; + // FIXME: It would be safe to use regmask and implicit operands to across a + // function call. However, for now we do not allow moving any instruction + // across function call as we are not perfectly clear if it's safe in all + // targets and calling conventions. + if (MI.isCall()) + return Changed; - // Don't sink the COPY if it would violate a register dependency. - if (hasRegisterDependency(MI, UsedOpsInCopy, DefedRegsInCopy, - ModifiedRegUnits, UsedRegUnits)) { - LiveRegUnits::accumulateUsedDefed(*MI, ModifiedRegUnits, UsedRegUnits, - TRI); - continue; - } - assert((!UsedOpsInCopy.empty() && !DefedRegsInCopy.empty()) && - "Unexpect SrcReg or DefReg"); - MachineBasicBlock *SuccBB = - getSingleLiveInSuccBB(CurBB, SinkableBBs, DefedRegsInCopy, TRI); - // Don't sink if we cannot find a single sinkable successor in which Reg - // is live-in. - if (!SuccBB) { - LiveRegUnits::accumulateUsedDefed(*MI, ModifiedRegUnits, UsedRegUnits, - TRI); - continue; + if (EnableSinkSpill && MI.mayStore()) { + if (tryToSinkSpill(MI, CurBB, SinkableBBs)) { + Changed = true; + continue; + } + } else if (MI.isCopy()) { + if (tryToSinkCopy(MI, CurBB, SinkableBBs)) { + Changed = true; + continue; + } } - assert((SuccBB->pred_size() == 1 && *SuccBB->pred_begin() == &CurBB) && - "Unexpected predecessor"); - - // Clear the kill flag if SrcReg is killed between MI and the end of the - // block. - clearKillFlags(MI, CurBB, UsedOpsInCopy, UsedRegUnits, TRI); - MachineBasicBlock::iterator InsertPos = SuccBB->getFirstNonPHI(); - SuccBB->splice(InsertPos, &CurBB, MI); - updateLiveIn(MI, SuccBB, UsedOpsInCopy, DefedRegsInCopy); - - Changed = true; - ++NumPostRACopySink; + LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, + TRI); } return Changed; } bool PostRAMachineSinking::runOnMachineFunction(MachineFunction &MF) { bool Changed = false; - const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); - const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); + TRI = MF.getSubtarget().getRegisterInfo(); + TII = MF.getSubtarget().getInstrInfo(); + MFI = &MF.getFrameInfo(); + MDT = &getAnalysis(); ModifiedRegUnits.init(*TRI); UsedRegUnits.init(*TRI); - for (auto &BB : MF) - Changed |= tryToSinkCopy(BB, MF, TRI, TII); + + bool EnableSinkSpill = scanLoadFromStackSlot(MF); + for (auto &BB : MF) + Changed |= tryToSink(BB, EnableSinkSpill); return Changed; } Index: test/CodeGen/AArch64/O3-pipeline.ll =================================================================== --- test/CodeGen/AArch64/O3-pipeline.ll +++ test/CodeGen/AArch64/O3-pipeline.ll @@ -124,8 +124,8 @@ ; CHECK-NEXT: Machine Loop Invariant Code Motion ; CHECK-NEXT: AArch64 Redundant Copy Elimination ; CHECK-NEXT: A57 FP Anti-dependency breaker -; CHECK-NEXT: PostRA Machine Sink ; CHECK-NEXT: MachineDominator Tree Construction +; CHECK-NEXT: PostRA Machine Sink ; CHECK-NEXT: Machine Natural Loop Construction ; CHECK-NEXT: Machine Block Frequency Analysis ; CHECK-NEXT: MachinePostDominator Tree Construction Index: test/CodeGen/AArch64/post-ra-machine-sink-spill.mir =================================================================== --- /dev/null +++ test/CodeGen/AArch64/post-ra-machine-sink-spill.mir @@ -0,0 +1,182 @@ +# RUN: llc -mtriple=aarch64-none-linux-gnu -run-pass=postra-machine-sink -verify-machineinstrs -o - %s | FileCheck %s + +--- +# Sink the store to stack.0 to %bb.1. +# CHECK-LABEL: name: sinkspill1 +# CHECK-LABEL: bb.0: +# CHECK-NOT: STRXui $x0, %stack.0 +# CHECK-LABEL: bb.1: +# CHECK: liveins: $x0 +# CHECK: STRXui $x0, %stack.0 +name: sinkspill1 +tracksRegLiveness: true +stack: + - { id: 0, name: '', type: spill-slot, offset: 0, size: 8, alignment: 8, + stack-id: 0, callee-saved-register: '', callee-saved-restored: true } +body: | + bb.0: + liveins: $x0 , $w1 + $w1 = SUBSWri $w1, 1, 0, implicit-def $nzcv + STRXui $x0, %stack.0, 0 :: (store 8 into %stack.0) + Bcc 11, %bb.1, implicit $nzcv + B %bb.2 + + bb.1: + $x0 = LDRXui %stack.0, 0 :: (load 8 from %stack.0) + RET $x0 + + bb.2: + $x0 = COPY $xzr + RET $x0 +... + +--- +# Sink the store to stack.0 to %bb.2. +# CHECK-LABEL: name: sinkspill2 +# CHECK-LABEL: bb.0: +# CHECK-NOT: STRXui $x0, %stack.0 +# CHECK-LABEL: bb.2: +# CHECK: liveins:{{.*}} $x0 +# CHECK: STRXui $x0, %stack.0 +name: sinkspill2 +tracksRegLiveness: true +stack: + - { id: 0, name: '', type: spill-slot, offset: 0, size: 8, alignment: 8, + stack-id: 0, callee-saved-register: '', callee-saved-restored: true } +body: | + bb.0: + liveins: $x0, $w1 + $w1 = SUBSWri $w1, 1, 0, implicit-def $nzcv + STRXui $x0, %stack.0, 0 :: (store 8 into %stack.0) + Bcc 11, %bb.2, implicit $nzcv + + bb.1: + liveins: $x0 + RET $x0 + + bb.2: + liveins: $x1 + $x0 = ADDXrr $x1, killed $x1 + + bb.3: + $x0 = LDRXui %stack.0, 0 :: (load 8 from %stack.0) + RET $x0 +... + +--- +# Sink the store to stack.0 to %bb.3. +# CHECK-LABEL: name: sinkspill3 +# CHECK-LABEL: bb.0: +# CHECK-NOT: STRXui $x0, %stack.0 +# CHECK-LABEL: bb.2: +# CHECK: liveins:{{.*}} $x0 +# CHECK-LABEL: bb.3: +# CHECK: liveins:{{.*}} $x0 +# CHECK: STRXui $x0, %stack.0 +name: sinkspill3 +tracksRegLiveness: true +stack: + - { id: 0, name: '', type: spill-slot, offset: 0, size: 8, alignment: 8, + stack-id: 0, callee-saved-register: '', callee-saved-restored: true } +body: | + bb.0: + liveins: $x0, $w1 + $w1 = SUBSWri $w1, 1, 0, implicit-def $nzcv + STRXui $x0, %stack.0, 0 :: (store 8 into %stack.0) + Bcc 11, %bb.2, implicit $nzcv + + bb.1: + liveins: $x0 + RET $x0 + + bb.2: + liveins: $x1 + $x1 = ADDXrr $x1, killed $x1 + + bb.3: + $x0 = LDRXui %stack.0, 0 :: (load 8 from %stack.0) + RET $x0 +... + +--- +# Keep the store to stack.0 in bb.0. +# CHECK-LABEL: name: donotsinkspill1 +# CHECK-LABEL: bb.0: +# CHECK: STRXui $x0, %stack.0 +name: donotsinkspill1 +tracksRegLiveness: true +stack: + - { id: 0, name: '', type: spill-slot, offset: 0, size: 8, alignment: 8, + stack-id: 0, callee-saved-register: '', callee-saved-restored: true } +body: | + bb.0: + liveins: $x0 , $w1 + $w1 = SUBSWri $w1, 1, 0, implicit-def $nzcv + STRXui $x0, %stack.0, 0 :: (store 8 into %stack.0) + Bcc 11, %bb.1, implicit $nzcv + B %bb.2 + + bb.1: + $x0 = LDRXui %stack.0, 0 :: (load 8 from %stack.0) + RET $x0 + + bb.2: + $x0 = LDRXui %stack.0, 0 :: (load 8 from %stack.0) + RET $x0 +... + +--- +# Keep the store to stack.0 in bb.0 due to register dependency on x0. +# CHECK-LABEL: name: donotsinkspill2 +# CHECK-LABEL: bb.0: +# CHECK: STRXui $x0, %stack.0 +name: donotsinkspill2 +tracksRegLiveness: true +stack: + - { id: 0, name: '', type: spill-slot, offset: 0, size: 8, alignment: 8, + stack-id: 0, callee-saved-register: '', callee-saved-restored: true } +body: | + bb.0: + liveins: $x0 , $w1 + $w1 = SUBSWri $w1, 1, 0, implicit-def $nzcv + STRXui $x0, %stack.0, 0 :: (store 8 into %stack.0) + $x0 = ADDXrr $x1, killed $x1 + Bcc 11, %bb.1, implicit $nzcv + B %bb.2 + + bb.1: + $x0 = LDRXui %stack.0, 0 :: (load 8 from %stack.0) + RET $x0 + + bb.2: + $x0 = COPY $xzr + RET $x0 +... + +--- +# Keep the store to stack.0 in bb.0 due to LDRXui in bb.0. +# CHECK-LABEL: name: donotsinkspill3 +# CHECK-LABEL: bb.0: +# CHECK: STRXui $x0, %stack.0 +name: donotsinkspill3 +tracksRegLiveness: true +stack: + - { id: 0, name: '', type: spill-slot, offset: 0, size: 8, alignment: 8, + stack-id: 0, callee-saved-register: '', callee-saved-restored: true } +body: | + bb.0: + liveins: $x0 , $w1 + $w1 = SUBSWri $w1, 1, 0, implicit-def $nzcv + STRXui $x0, %stack.0, 0 :: (store 8 into %stack.0) + $x0 = LDRXui %stack.0, 0 :: (load 8 from %stack.0) + Bcc 11, %bb.1, implicit $nzcv + B %bb.2 + + bb.1: + $x0 = LDRXui %stack.0, 0 :: (load 8 from %stack.0) + RET $x0 + + bb.2: + $x0 = COPY $xzr + RET $x0 +... Index: test/CodeGen/PowerPC/aggressive-anti-dep-breaker-subreg.ll =================================================================== --- test/CodeGen/PowerPC/aggressive-anti-dep-breaker-subreg.ll +++ test/CodeGen/PowerPC/aggressive-anti-dep-breaker-subreg.ll @@ -9,8 +9,8 @@ lnext: %elementArray = load i32*, i32** %elementArrayPtr, align 8 -; CHECK: lwz [[LDREG:[0-9]+]], 124(1) # 4-byte Folded Reload ; CHECK: # implicit-def: $x[[TEMPREG:[0-9]+]] +; CHECK: lwz [[LDREG:[0-9]+]], 124(1) # 4-byte Folded Reload %element = load i32, i32* %elementArray, align 4 ; CHECK: mr [[TEMPREG]], [[LDREG]] ; CHECK: clrldi 4, [[TEMPREG]], 32 Index: test/CodeGen/PowerPC/cc.ll =================================================================== --- test/CodeGen/PowerPC/cc.ll +++ test/CodeGen/PowerPC/cc.ll @@ -26,9 +26,9 @@ ; CHECK: sc ; CHECK: lwz [[REG3:[0-9]+]], -4(1) +; CHECK: lwz [[REG4:[0-9]+]], 8(1) ; CHECK: mtocrf 128, [[REG3]] -; CHECK: lwz [[REG4:[0-9]+]], 8(1) ; CHECK-DAG: mtocrf 32, [[REG4]] ; CHECK-DAG: mtocrf 16, [[REG4]] ; CHECK-DAG: mtocrf 8, [[REG4]] @@ -59,9 +59,9 @@ ; CHECK: sc ; CHECK: lwz [[REG3:[0-9]+]], -4(1) +; CHECK: lwz [[REG4:[0-9]+]], 8(1) ; CHECK: mtocrf 128, [[REG3]] -; CHECK: lwz [[REG4:[0-9]+]], 8(1) ; CHECK-DAG: mtocrf 32, [[REG4]] ; CHECK-DAG: mtocrf 16, [[REG4]] ; CHECK-DAG: mtocrf 8, [[REG4]] Index: test/CodeGen/X86/catchret-regmask.ll =================================================================== --- test/CodeGen/X86/catchret-regmask.ll +++ test/CodeGen/X86/catchret-regmask.ll @@ -62,12 +62,12 @@ ; CHECK-LABEL: spill_in_pad: # @spill_in_pad ; CHECK: callq throw ; CHECK: ud2 -; CHECK: movq -[[val_slot:[0-9]+]](%rbp), %rax # 8-byte Reload +; CHECK: movq %rax, -[[val_slot:[0-9]+]](%rbp) # 8-byte Spill +; CHECK: movq -[[val_slot]](%rbp), %rax # 8-byte Reload ; CHECK: retq ; CHECK: "?catch$3@?0?spill_in_pad@4HA": ; CHECK: callq getval -; CHECK: movq %rax, -[[val_slot]](%rbp) # 8-byte Spill ; CHECK: retq attributes #0 = { uwtable }