[llvm-bugs] [Bug 40365] New: InstCombine incorrectly sinks dynamic allocas into a stacksave / stackrestore region

via llvm-bugs llvm-bugs at lists.llvm.org
Thu Jan 17 11:14:40 PST 2019


https://bugs.llvm.org/show_bug.cgi?id=40365

            Bug ID: 40365
           Summary: InstCombine incorrectly sinks dynamic allocas into a
                    stacksave / stackrestore region
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: Windows NT
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: Scalar Optimizations
          Assignee: unassignedbugs at nondot.org
          Reporter: rnk at google.com
                CC: llvm-bugs at lists.llvm.org

This was originally found at https://crbug.com/922654

Instcombine makes this incorrect transformation:

$ opt -instcombine sink-inalloca.ll -S -o t2.ll

$ diff -U999 sink-inalloca.ll t2.ll
--- sink-inalloca.ll    2019-01-17 11:00:26.186621700 -0800
+++ t2.ll       2019-01-17 11:00:33.390299200 -0800
@@ -1,36 +1,36 @@
-; ModuleID = 'sink-inalloca.bc'
+; ModuleID = 'sink-inalloca.ll'
 source_filename = "sink-inalloca.ll"

 declare i32* @identity(i32*)

 declare i1 @cond()

 ; Function Attrs: nounwind
 declare i8* @llvm.stacksave() #0

 ; Function Attrs: nounwind
 declare void @llvm.stackrestore(i8*) #0

 define void @foo(i32 %x) {
 entry:
   %c1 = call i1 @cond()
   br i1 %c1, label %ret, label %nonentry

 nonentry:                                         ; preds = %entry
-  %argmem = alloca inalloca i32
   %sp = call i8* @llvm.stacksave()
   %c2 = call i1 @cond()
   br i1 %c2, label %ret, label %sinktarget

 sinktarget:                                       ; preds = %nonentry
-  %p = call i32* @identity(i32* %argmem)
-  store i32 13, i32* %p
+  %argmem = alloca inalloca i32, align 4
+  %p = call i32* @identity(i32* nonnull %argmem)
+  store i32 13, i32* %p, align 4
   call void @llvm.stackrestore(i8* %sp)
   %0 = call i32* @identity(i32* %p)
   br label %ret

 ret:                                              ; preds = %sinktarget,
%nonentry, %entry
   ret void
 }

 attributes #0 = { nounwind }

Here's a plain C version of the test case that doesn't involve inalloca:

#include <stdbool.h>
bool cond(void);
int *use(void *);
void foo(int n) {
  // need p to not be in entry block.
  if (cond()) {
    void *p = alloca(n);
    {
      int vla[n];
      if (cond())
        return;
      p = use(p);
      use(&vla[0]);
      if (cond())
        return;
    }
    use(p);
  }
}

inalloca just makes this situation much more common.

Unfortunately, we ran into this after fixing https://llvm.org/pr40118, which
prevented LLVM from optimizing away inalloca after inlining. Treating
"stackrestore" as something that can write anything into memory was a major
pessimization. Previously GVN would eliminate these stores, and the alloca
would become dead, and the stack save and stackrestore would be eliminated.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20190117/08a7afc9/attachment.html>


More information about the llvm-bugs mailing list