Commit fc6fda90 authored by Jin Lin's avatar Jin Lin
Browse files

Fix incorrect logic in maintaining the side-effect of compiler generated outliner functions

Summary: Fix incorrect logic in maintaining the side-effect of compiler generated outliner functions by adding the up-exposed uses.

Reviewers: paquette, tellenbach

Reviewed By: paquette

Subscribers: aemerson, lebedev.ri, hiraditya, llvm-commits, jinlin

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D71217
parent 5dadf577
Loading
Loading
Loading
Loading
+41 −18
Original line number Diff line number Diff line
@@ -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"
@@ -1245,31 +1246,53 @@ bool MachineOutliner::outline(Module &M,
      // make sure that the ranges we yank things out of aren't wrong.
      if (MBB.getParent()->getProperties().hasProperty(
              MachineFunctionProperties::Property::TracksLiveness)) {
        // Helper lambda for adding implicit def operands to the call
        // The following code is to add 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<Register, 2> UseRegs, DefRegs;
        // 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 (MachineBasicBlock::reverse_iterator Iter = EndIt.getReverse(),
             Last = std::next(CallInst.getReverse());
             Iter != Last; Iter++) {
          MachineInstr *MI = &*Iter;
          for (MachineOperand &MOP : MI->operands()) {
            // Skip over anything that isn't a register.
            if (!MOP.isReg())
              continue;

            if (MOP.isDef()) {
              // Introduce DefRegs set to skip the redundant register.
              DefRegs.insert(MOP.getReg());
              if (UseRegs.count(MOP.getReg()))
                // Since the regiester is modeled as defined,
                // it is not necessary to be put in use register set.
                UseRegs.erase(MOP.getReg());
            } else if (!MOP.isUndef()) {
              // Any register which is not undefined should
              // be put in the use register set.
              UseRegs.insert(MOP.getReg());
            }
          }
          if (MI->isCandidateForCallSiteEntry())
            MI->getMF()->eraseCallSiteInfo(MI);
        }

        for (const Register &I : DefRegs)
           // If it's a def, add it to the call instruction.
            if (MOP.isDef())
          CallInst->addOperand(MachineOperand::CreateReg(
                  MOP.getReg(), true, /* isDef = true */
                  I, true, /* isDef = true */
                  true /* isImp = true */));

        for (const Register &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 */));
          }
          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);
      }

      // Erase from the point after where the call was inserted up to, and
+4 −4
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ body: |
    ; 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 @@ body: |
    ; 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 @@ body: |
    ; 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 @@ body: |
    ; 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
+32 −0
Original line number Diff line number Diff line
# 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, {{.*}}