[llvm] eac3e5c - [X86] Do not emit JCC to __x86_indirect_thunk

Nick Desaulniers via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 6 11:09:34 PDT 2022


Author: Joao Moreira
Date: 2022-10-06T11:09:24-07:00
New Revision: eac3e5c3fb7c121158fc4ae5117e6acb7fb5220e

URL: https://github.com/llvm/llvm-project/commit/eac3e5c3fb7c121158fc4ae5117e6acb7fb5220e
DIFF: https://github.com/llvm/llvm-project/commit/eac3e5c3fb7c121158fc4ae5117e6acb7fb5220e.diff

LOG: [X86] Do not emit JCC to __x86_indirect_thunk

Clang may optimize conditional tailcall blocks with the following layout:

cmp <condition>
je  tailcall_target
ret

When retpoline is in place, indirect calls are converted into direct calls to a retpoline thunk. When these indirect calls are tail calls, they may be subject to the above described optimization (there is no indirect JCC, but since now the jump is direct it can be made conditional). The above layout is non-ideal for the Linux kernel scenario because the branches into thunks may be patched back into indirect branches during runtime depending on the underlying CPU features, what would not be feasible if the binary is emitted with the optimized layout above.

Thus, prevent clang from emitting this it if CodeModel is Kernel.

Feature request from the respective kernel mailing list: https://lore.kernel.org/llvm/Yv3uI%2FMoJVctmBCh@worktop.programming.kicks-ass.net/

Reviewed By: nickdesaulniers, pengfei

Differential Revision: https://reviews.llvm.org/D134915

Added: 
    llvm/test/CodeGen/X86/jcc-indirect-thunk-kernel.ll

Modified: 
    llvm/lib/Target/X86/X86InstrInfo.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp
index 7ae12c090457c..65fab4bedaf55 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.cpp
+++ b/llvm/lib/Target/X86/X86InstrInfo.cpp
@@ -2942,13 +2942,26 @@ bool X86InstrInfo::isUnconditionalTailCall(const MachineInstr &MI) const {
 bool X86InstrInfo::canMakeTailCallConditional(
     SmallVectorImpl<MachineOperand> &BranchCond,
     const MachineInstr &TailCall) const {
+
+  const MachineFunction *MF = TailCall.getMF();
+
+  if (MF->getTarget().getCodeModel() == CodeModel::Kernel) {
+    // Kernel patches thunk calls in runtime, these should never be conditional.
+    const MachineOperand &Target = TailCall.getOperand(0);
+    if (Target.isSymbol()) {
+      StringRef Symbol(Target.getSymbolName());
+      // this is currently only relevant to r11/kernel indirect thunk.
+      if (Symbol.equals("__x86_indirect_thunk_r11"))
+        return false;
+    }
+  }
+
   if (TailCall.getOpcode() != X86::TCRETURNdi &&
       TailCall.getOpcode() != X86::TCRETURNdi64) {
     // Only direct calls can be done with a conditional branch.
     return false;
   }
 
-  const MachineFunction *MF = TailCall.getParent()->getParent();
   if (Subtarget.isTargetWin64() && MF->hasWinCFI()) {
     // Conditional tail calls confuse the Win64 unwinder.
     return false;

diff  --git a/llvm/test/CodeGen/X86/jcc-indirect-thunk-kernel.ll b/llvm/test/CodeGen/X86/jcc-indirect-thunk-kernel.ll
new file mode 100644
index 0000000000000..d04ae31a9cb3f
--- /dev/null
+++ b/llvm/test/CodeGen/X86/jcc-indirect-thunk-kernel.ll
@@ -0,0 +1,32 @@
+; RUN: llc < %s -O2 --code-model=kernel | FileCheck %s
+; The intent of the test is that we do not generate conditional
+; tail calls to the thunk.
+
+target triple = "x86_64-unknown-linux-gnu"
+
+define dso_local void @foo(ptr %something) #0 {
+; CHECK-LABEL: foo:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    movq (%rdi), %r11
+; CHECK-NEXT:    testq %r11, %r11
+; Make sure that a JNE was not generated instead of a JE + JMP sequence
+; CHECK-NOT:     jne
+; CHECK-NEXT:    je .LBB0_1
+; CHECK-NEXT:    bb.2: # %if.then
+; CHECK-NEXT:    jmp __x86_indirect_thunk_r11
+; CHECK-NEXT:    LBB0_1:
+; CHECK-NEXT:    retq
+entry:
+  %0 = load ptr, ptr %something, align 8
+  %tobool.not = icmp eq ptr %0, null
+  br i1 %tobool.not, label %if.end, label %if.then
+
+if.then:
+  tail call void %0()
+  br label %if.end
+
+if.end:
+  ret void
+}
+
+attributes #0 = { optsize "target-features"="+retpoline-external-thunk" }


        


More information about the llvm-commits mailing list