Index: llvm/lib/CodeGen/MachineOutliner.cpp =================================================================== --- llvm/lib/CodeGen/MachineOutliner.cpp +++ llvm/lib/CodeGen/MachineOutliner.cpp @@ -56,6 +56,7 @@ //===----------------------------------------------------------------------===// #include "llvm/CodeGen/MachineOutliner.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/Twine.h" #include "llvm/CodeGen/MachineFunction.h" @@ -1248,28 +1249,41 @@ // Helper lambda for adding implicit def operands to the call // instruction. It also updates call site information for moved // code. - auto CopyDefsAndUpdateCalls = [&CallInst](MachineInstr &MI) { - for (MachineOperand &MOP : MI.operands()) { + SmallSet UseRegs; + MachineBasicBlock::reverse_iterator Last = + std::next(CallInst.getReverse()); + MachineBasicBlock::reverse_iterator Iter = EndIt.getReverse(); + // Copy over the defs in the outlined range. + // First inst in outlined range <-- Anything that's defined in this + // ... .. range has to be added as an + // implicit Last inst in outlined range <-- def to the call + // instruction. Also remove call site information for outlined block + // of code. The exposed uses need to be copied in the outlined range. + for (; Iter != Last; Iter++) { + MachineInstr *MI = &*Iter; + for (MachineOperand &MOP : MI->operands()) { // Skip over anything that isn't a register. if (!MOP.isReg()) continue; // If it's a def, add it to the call instruction. - if (MOP.isDef()) + if (MOP.isDef()) { CallInst->addOperand(MachineOperand::CreateReg( MOP.getReg(), true, /* isDef = true */ true /* isImp = true */)); + if (UseRegs.count(MOP.getReg())) + UseRegs.erase(MOP.getReg()); + } else if (!MOP.isUndef()) + UseRegs.insert(MOP.getReg()); } - if (MI.shouldUpdateCallSiteInfo()) - MI.getMF()->eraseCallSiteInfo(&MI); + if (MI->shouldUpdateCallSiteInfo()) + MI->getMF()->eraseCallSiteInfo(MI); }; - // Copy over the defs in the outlined range. - // First inst in outlined range <-- Anything that's defined in this - // ... .. range has to be added as an - // implicit Last inst in outlined range <-- def to the call - // instruction. Also remove call site information for outlined block - // of code. - std::for_each(CallInst, std::next(EndIt), CopyDefsAndUpdateCalls); + for (auto I : UseRegs) + // If it's a exposed use, add it to the call instruction. + CallInst->addOperand( + MachineOperand::CreateReg(I, false, /* isDef = false */ + true /* isImp = true */)); } // Erase from the point after where the call was inserted up to, and Index: llvm/test/CodeGen/AArch64/machine-outliner-noreturn-save-lr.mir =================================================================== --- llvm/test/CodeGen/AArch64/machine-outliner-noreturn-save-lr.mir +++ llvm/test/CodeGen/AArch64/machine-outliner-noreturn-save-lr.mir @@ -27,7 +27,7 @@ ; CHECK-LABEL: name: save_lr_1 ; CHECK: liveins: $lr ; CHECK: $x0 = ORRXrs $xzr, $lr, 0 - ; CHECK: BL @OUTLINED_FUNCTION_0, implicit-def $lr, implicit $sp, implicit-def $lr, implicit-def $lr, implicit-def $w3, implicit-def $w4, implicit-def $w5, implicit-def $w6 + ; CHECK: BL @OUTLINED_FUNCTION_0, implicit-def $lr, implicit $sp, implicit-def $lr, implicit-def $w3, implicit-def $w4, implicit-def $w5, implicit-def $w6, implicit $sp, implicit $wzr, implicit $xzr, implicit $x0 ; CHECK: $lr = ORRXrs $xzr, $x0, 0 $w3 = ORRWri $wzr, 1 $w4 = ORRWri $wzr, 1 @@ -49,7 +49,7 @@ ; CHECK-LABEL: name: save_lr_2 ; CHECK: liveins: $lr ; CHECK: $x0 = ORRXrs $xzr, $lr, 0 - ; CHECK: BL @OUTLINED_FUNCTION_0, implicit-def $lr, implicit $sp, implicit-def $lr, implicit-def $lr, implicit-def $w3, implicit-def $w4, implicit-def $w5, implicit-def $w6 + ; CHECK: BL @OUTLINED_FUNCTION_0, implicit-def $lr, implicit $sp, implicit-def $lr, implicit-def $w3, implicit-def $w4, implicit-def $w5, implicit-def $w6, implicit $sp, implicit $wzr, implicit $xzr, implicit $x0 ; CHECK: $lr = ORRXrs $xzr, $x0, 0 $w3 = ORRWri $wzr, 1 $w4 = ORRWri $wzr, 1 @@ -71,7 +71,7 @@ ; CHECK-LABEL: name: save_lr_3 ; CHECK: liveins: $lr ; CHECK: $x0 = ORRXrs $xzr, $lr, 0 - ; CHECK: BL @OUTLINED_FUNCTION_0, implicit-def $lr, implicit $sp, implicit-def $lr, implicit-def $lr, implicit-def $w3, implicit-def $w4, implicit-def $w5, implicit-def $w6 + ; CHECK: BL @OUTLINED_FUNCTION_0, implicit-def $lr, implicit $sp, implicit-def $lr, implicit-def $w3, implicit-def $w4, implicit-def $w5, implicit-def $w6, implicit $sp, implicit $wzr, implicit $xzr, implicit $x0 ; CHECK: $lr = ORRXrs $xzr, $x0, 0 $w3 = ORRWri $wzr, 1 $w4 = ORRWri $wzr, 1 @@ -93,7 +93,7 @@ ; CHECK-LABEL: name: save_lr_4 ; CHECK: liveins: $lr ; CHECK: $x0 = ORRXrs $xzr, $lr, 0 - ; CHECK: BL @OUTLINED_FUNCTION_0, implicit-def $lr, implicit $sp, implicit-def $lr, implicit-def $lr, implicit-def $w3, implicit-def $w4, implicit-def $w5, implicit-def $w6 + ; CHECK: BL @OUTLINED_FUNCTION_0, implicit-def $lr, implicit $sp, implicit-def $lr, implicit-def $w3, implicit-def $w4, implicit-def $w5, implicit-def $w6, implicit $sp, implicit $wzr, implicit $xzr, implicit $x0 ; CHECK: $lr = ORRXrs $xzr, $x0, 0 $w3 = ORRWri $wzr, 1 $w4 = ORRWri $wzr, 1 Index: llvm/test/CodeGen/AArch64/machine-outliner-side-effect.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/machine-outliner-side-effect.mir @@ -0,0 +1,32 @@ +# RUN: llc -mtriple=aarch64 -run-pass=machine-outliner -verify-machineinstrs %s -o - | FileCheck %s + +# The test checks whether the compiler updates the side effect of function @OUTLINED_FUNCTION_0 by adding the use of register x20. + +--- | + declare void @spam() local_unnamed_addr + define void @baz() optsize minsize noredzone { ret void } +... +--- +name: baz +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0, $x20 + + $x0 = COPY renamable $x20 + BL @spam, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit $x0, implicit-def $sp, implicit-def $x0 + renamable $x21 = COPY $x0 + + $x0 = COPY renamable $x20 + BL @spam, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit $x0, implicit-def $sp, implicit-def $x0 + renamable $x22 = COPY $x0 + + $x0 = COPY killed renamable $x20 + BL @spam, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit $x0, implicit-def $sp, implicit-def $x0 + renamable $x3 = COPY $x0 + + RET_ReallyLR + +... + +# CHECK: BL @OUTLINED_FUNCTION_0, {{.*}}, implicit $x20, {{.*}}