diff options
author | Fangrui Song <i@maskray.me> | 2021-12-13 13:24:29 -0800 |
---|---|---|
committer | Tom Stellard <tstellar@redhat.com> | 2022-01-05 10:26:53 -0800 |
commit | 0d44201451f03ba907cdb268ddddfc3fa38a0ebd (patch) | |
tree | 503d2526c0d9655a5392c6b594ed0e487ce99734 /llvm | |
parent | 69fcfdedc50526a8bf9f155657865aad942b95d4 (diff) | |
download | llvm-0d44201451f03ba907cdb268ddddfc3fa38a0ebd.zip llvm-0d44201451f03ba907cdb268ddddfc3fa38a0ebd.tar.gz llvm-0d44201451f03ba907cdb268ddddfc3fa38a0ebd.tar.bz2 |
[MachineOutliner] Don't outline functions starting with PATCHABLE_FUNCTION_ENTER/FENTRL_CALL
MachineOutliner may outline a "patchable-function-entry" function whose body has
a TargetOpcode::PATCHABLE_FUNCTION_ENTER MachineInstr. This is incorrect because
the special code sequence must stay unchanged to be used at run-time.
Avoid outlining PATCHABLE_FUNCTION_ENTER. While here, avoid outlining FENTRY_CALL too
(which doesn't reproduce currently) to allow phase ordering flexibility.
Fixes #52635
Reviewed By: paquette
Differential Revision: https://reviews.llvm.org/D115614
(cherry picked from commit a6a07a514b8a084feaa7f4f15d569698b9840d83)
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/include/llvm/CodeGen/TargetInstrInfo.h | 4 | ||||
-rw-r--r-- | llvm/lib/CodeGen/TargetInstrInfo.cpp | 13 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 2 | ||||
-rw-r--r-- | llvm/test/CodeGen/AArch64/machine-outliner-patchable.ll | 114 | ||||
-rw-r--r-- | llvm/test/CodeGen/RISCV/machine-outliner-patchable.ll | 77 |
6 files changed, 208 insertions, 4 deletions
diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h index 05d0591..35c3315 100644 --- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h +++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h @@ -1922,9 +1922,7 @@ public: /// Optional target hook that returns true if \p MBB is safe to outline from, /// and returns any target-specific information in \p Flags. virtual bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB, - unsigned &Flags) const { - return true; - } + unsigned &Flags) const; /// Insert a custom frame for outlined functions. virtual void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF, diff --git a/llvm/lib/CodeGen/TargetInstrInfo.cpp b/llvm/lib/CodeGen/TargetInstrInfo.cpp index 2e4a656..4bbb5be 100644 --- a/llvm/lib/CodeGen/TargetInstrInfo.cpp +++ b/llvm/lib/CodeGen/TargetInstrInfo.cpp @@ -1417,3 +1417,16 @@ std::string TargetInstrInfo::createMIROperandComment( } TargetInstrInfo::PipelinerLoopInfo::~PipelinerLoopInfo() {} + +bool TargetInstrInfo::isMBBSafeToOutlineFrom(MachineBasicBlock &MBB, + unsigned &Flags) const { + // Some instrumentations create special TargetOpcode at the start which + // expands to special code sequences which must be present. + auto First = MBB.getFirstNonDebugInstr(); + if (First != MBB.end() && + (First->getOpcode() == TargetOpcode::FENTRY_CALL || + First->getOpcode() == TargetOpcode::PATCHABLE_FUNCTION_ENTER)) + return false; + + return true; +} diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp index 091a62a..f29bb83 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -6923,6 +6923,8 @@ bool AArch64InstrInfo::isFunctionSafeToOutlineFrom( bool AArch64InstrInfo::isMBBSafeToOutlineFrom(MachineBasicBlock &MBB, unsigned &Flags) const { + if (!TargetInstrInfo::isMBBSafeToOutlineFrom(MBB, Flags)) + return false; // Check if LR is available through all of the MBB. If it's not, then set // a flag. assert(MBB.getParent()->getRegInfo().tracksLiveness() && diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp index 2071017..7dab7a5 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -999,7 +999,7 @@ bool RISCVInstrInfo::isFunctionSafeToOutlineFrom( bool RISCVInstrInfo::isMBBSafeToOutlineFrom(MachineBasicBlock &MBB, unsigned &Flags) const { // More accurate safety checking is done in getOutliningCandidateInfo. - return true; + return TargetInstrInfo::isMBBSafeToOutlineFrom(MBB, Flags); } // Enum values indicating how an outlined call should be constructed. diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-patchable.ll b/llvm/test/CodeGen/AArch64/machine-outliner-patchable.ll new file mode 100644 index 0000000..e381b49 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/machine-outliner-patchable.ll @@ -0,0 +1,114 @@ +; RUN: llc < %s -verify-machineinstrs -enable-machine-outliner | FileCheck %s + +target triple = "aarch64-unknown-linux-gnu" + +declare void @foo(i32, i32, i32, i32) minsize + +;; TargetOpcode::FENTRY_CALL at the start of the function expands to a __fentry__ +;; call which must be present. Don't outline it. +define void @fentry0(i1 %a) nounwind "fentry-call"="true" { +; CHECK-LABEL: fentry0: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: # FEntry call +; CHECK: // %bb.1: +; CHECK-NEXT: bl OUTLINED_FUNCTION_1 +entry: + br i1 %a, label %if.then, label %if.end +if.then: + call void @foo(i32 1, i32 2, i32 3, i32 4) + br label %if.end +if.end: + call void @foo(i32 5, i32 6, i32 7, i32 8) + ret void +} + +define void @fentry1(i1 %a) nounwind "fentry-call"="true" { +; CHECK-LABEL: fentry1: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: # FEntry call +; CHECK: // %bb.1: +; CHECK-NEXT: bl OUTLINED_FUNCTION_1 +entry: + br i1 %a, label %if.then, label %if.end +if.then: + call void @foo(i32 1, i32 2, i32 3, i32 4) + br label %if.end +if.end: + call void @foo(i32 5, i32 6, i32 7, i32 8) + ret void +} + +;; TargetOpcode::PATCHABLE_FUNCTION_ENTER at the start of the function expands to +;; NOPs which must be present. Don't outline them. +define void @patchable0(i1 %a) nounwind "patchable-function-entry"="2" { +; CHECK-LABEL: patchable0: +; CHECK-NEXT: .Lfunc_begin0: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK: // %bb.1: +; CHECK-NEXT: bl OUTLINED_FUNCTION_1 +entry: + br i1 %a, label %if.then, label %if.end +if.then: + call void @foo(i32 1, i32 2, i32 3, i32 4) + br label %if.end +if.end: + call void @foo(i32 5, i32 6, i32 7, i32 8) + ret void +} + +define void @patchable1(i1 %a) nounwind "patchable-function-entry"="2" { +; CHECK-LABEL: patchable1: +; CHECK-NEXT: .Lfunc_begin1: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK: // %bb.1: +; CHECK-NEXT: bl OUTLINED_FUNCTION_1 +entry: + br i1 %a, label %if.then, label %if.end +if.then: + call void @foo(i32 1, i32 2, i32 3, i32 4) + br label %if.end +if.end: + call void @foo(i32 5, i32 6, i32 7, i32 8) + ret void +} + +;; Similar to "patchable-function-entry". +define void @xray0(i1 %a) nounwind "function-instrument"="xray-always" { +; CHECK-LABEL: xray0: +; CHECK-NEXT: .Lfunc_begin2: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: .p2align 2 +; CHECK-NEXT: .Lxray_sled_0: +; CHECK: // %bb.1: +; CHECK-NEXT: bl OUTLINED_FUNCTION_1 +entry: + br i1 %a, label %if.then, label %if.end +if.then: + call void @foo(i32 1, i32 2, i32 3, i32 4) + br label %if.end +if.end: + call void @foo(i32 5, i32 6, i32 7, i32 8) + ret void +} + +define void @xray1(i1 %a) nounwind "function-instrument"="xray-always" { +; CHECK-LABEL: xray1: +; CHECK-NEXT: .Lfunc_begin3: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: .p2align 2 +; CHECK-NEXT: .Lxray_sled_2: +; CHECK: // %bb.1: +; CHECK-NEXT: bl OUTLINED_FUNCTION_1 +entry: + br i1 %a, label %if.then, label %if.end +if.then: + call void @foo(i32 1, i32 2, i32 3, i32 4) + br label %if.end +if.end: + call void @foo(i32 5, i32 6, i32 7, i32 8) + ret void +} diff --git a/llvm/test/CodeGen/RISCV/machine-outliner-patchable.ll b/llvm/test/CodeGen/RISCV/machine-outliner-patchable.ll new file mode 100644 index 0000000..4ef3abd --- /dev/null +++ b/llvm/test/CodeGen/RISCV/machine-outliner-patchable.ll @@ -0,0 +1,77 @@ +; RUN: llc < %s -verify-machineinstrs -enable-machine-outliner | FileCheck %s + +target triple = "riscv64-unknown-linux-gnu" + +declare void @foo(i32, i32, i32, i32) minsize + +;; TargetOpcode::FENTRY_CALL at the start of the function expands to a __fentry__ +;; call which must be present. Don't outline it. +define void @fentry0(i1 %a) nounwind "fentry-call"="true" { +; CHECK-LABEL: fentry0: +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: # FEntry call +; CHECK: # %bb.1: +; CHECK-NEXT: call t0, OUTLINED_FUNCTION_1 +entry: + br i1 %a, label %if.then, label %if.end +if.then: + call void @foo(i32 1, i32 2, i32 3, i32 4) + br label %if.end +if.end: + call void @foo(i32 5, i32 6, i32 7, i32 8) + ret void +} + +define void @fentry1(i1 %a) nounwind "fentry-call"="true" { +; CHECK-LABEL: fentry1: +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: # FEntry call +; CHECK: # %bb.1: +; CHECK-NEXT: call t0, OUTLINED_FUNCTION_1 +entry: + br i1 %a, label %if.then, label %if.end +if.then: + call void @foo(i32 1, i32 2, i32 3, i32 4) + br label %if.end +if.end: + call void @foo(i32 5, i32 6, i32 7, i32 8) + ret void +} + +;; TargetOpcode::PATCHABLE_FUNCTION_ENTER at the start of the function expands to +;; NOPs which must be present. Don't outline them. +define void @patchable0(i1 %a) nounwind "patchable-function-entry"="2" { +; CHECK-LABEL: patchable0: +; CHECK-NEXT: .Lfunc_begin0: +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK: # %bb.1: +; CHECK-NEXT: call t0, OUTLINED_FUNCTION_1 +entry: + br i1 %a, label %if.then, label %if.end +if.then: + call void @foo(i32 1, i32 2, i32 3, i32 4) + br label %if.end +if.end: + call void @foo(i32 5, i32 6, i32 7, i32 8) + ret void +} + +define void @patchable1(i1 %a) nounwind "patchable-function-entry"="2" { +; CHECK-LABEL: patchable1: +; CHECK-NEXT: .Lfunc_begin1: +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK: # %bb.1: +; CHECK-NEXT: call t0, OUTLINED_FUNCTION_1 +entry: + br i1 %a, label %if.then, label %if.end +if.then: + call void @foo(i32 1, i32 2, i32 3, i32 4) + br label %if.end +if.end: + call void @foo(i32 5, i32 6, i32 7, i32 8) + ret void +} |