]> granicus.if.org Git - llvm/commitdiff
Merging r309343:
authorHans Wennborg <hans@hanshq.net>
Mon, 31 Jul 2017 16:45:02 +0000 (16:45 +0000)
committerHans Wennborg <hans@hanshq.net>
Mon, 31 Jul 2017 16:45:02 +0000 (16:45 +0000)
------------------------------------------------------------------------
r309343 | rnk | 2017-07-27 17:58:35 -0700 (Thu, 27 Jul 2017) | 16 lines

[X86] Fix latent bug in sibcall eligibility logic

The X86 tail call eligibility logic was correct when it was written, but
the addition of inalloca and argument copy elision broke its
assumptions. It was assuming that fixed stack objects were immutable.

Currently, we aim to emit a tail call if no arguments have to be
re-arranged in memory. This code would trace the outgoing argument
values back to check if they are loads from an incoming stack object.
If the stack argument is immutable, then we won't need to store it back
to the stack when we tail call.

Fortunately, stack objects track their mutability, so we can just make
the obvious check to fix the bug.

This was http://crbug.com/749826
------------------------------------------------------------------------

git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_50@309577 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86ISelLowering.cpp
test/CodeGen/X86/tail-call-mutable-memarg.ll [new file with mode: 0644]

index ba8eb8656585a7864b182066ae4a939f4462cc3a..79123c3f6f5672fd563747ca43c9177d92224038 100644 (file)
@@ -3984,6 +3984,13 @@ bool MatchingStackOffset(SDValue Arg, unsigned Offset, ISD::ArgFlagsTy Flags,
   if (Offset != MFI.getObjectOffset(FI))
     return false;
 
+  // If this is not byval, check that the argument stack object is immutable.
+  // inalloca and argument copy elision can create mutable argument stack
+  // objects. Byval objects can be mutated, but a byval call intends to pass the
+  // mutated memory.
+  if (!Flags.isByVal() && !MFI.isImmutableObjectIndex(FI))
+    return false;
+
   if (VA.getLocVT().getSizeInBits() > Arg.getValueSizeInBits()) {
     // If the argument location is wider than the argument type, check that any
     // extension flags match.
diff --git a/test/CodeGen/X86/tail-call-mutable-memarg.ll b/test/CodeGen/X86/tail-call-mutable-memarg.ll
new file mode 100644 (file)
index 0000000..491bbba
--- /dev/null
@@ -0,0 +1,42 @@
+; RUN: llc < %s | FileCheck %s
+
+; Make sure we check that forwarded memory arguments are not modified when tail
+; calling. inalloca and copy arg elimination make argument slots mutable.
+
+target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+target triple = "i386-pc-windows-msvc19.0.24215"
+
+declare x86_stdcallcc void @tail_std(i32)
+declare void @capture(i32*)
+
+define x86_thiscallcc void @inalloca(i32* %this, i32* inalloca %args) {
+entry:
+  %val = load i32, i32* %args
+  store i32 0, i32* %args
+  tail call x86_stdcallcc void @tail_std(i32 %val)
+  ret void
+}
+
+; CHECK-LABEL: _inalloca:                              # @inalloca
+; CHECK:         movl    4(%esp), %[[reg:[^ ]*]]
+; CHECK:         movl    $0, 4(%esp)
+; CHECK:         pushl   %[[reg]]
+; CHECK:         calll   _tail_std@4
+; CHECK:         retl    $4
+
+define x86_stdcallcc void @copy_elide(i32 %arg) {
+entry:
+  %arg.ptr = alloca i32
+  store i32 %arg, i32* %arg.ptr
+  call void @capture(i32* %arg.ptr)
+  tail call x86_stdcallcc void @tail_std(i32 %arg)
+  ret void
+}
+
+; CHECK-LABEL: _copy_elide@4:                          # @copy_elide
+; CHECK:         leal    {{[0-9]+}}(%esp), %[[reg:[^ ]*]]
+; CHECK:         pushl   %[[reg]]
+; CHECK:         calll   _capture
+; ...
+; CHECK:         calll   _tail_std@4
+; CHECK:         retl    $4