[PATCH] D20555: [MemCpyOpt] Be conservative in the face of returns_twice calls

David Majnemer via llvm-commits llvm-commits at lists.llvm.org
Mon May 23 21:17:56 PDT 2016


majnemer created this revision.
majnemer added reviewers: rnk, eli.friedman, MatzeB, nlewycky.
majnemer added a subscriber: llvm-commits.

It is not safe to forward loads and stores around if calls to setjmp are
present: there might be a call which longjmps causing a memory location
to be initialized with an unexpected value.

This fixes PR27848.

http://reviews.llvm.org/D20555

Files:
  lib/Transforms/Scalar/MemCpyOptimizer.cpp
  test/Transforms/MemCpyOpt/pr27848.ll

Index: test/Transforms/MemCpyOpt/pr27848.ll
===================================================================
--- /dev/null
+++ test/Transforms/MemCpyOpt/pr27848.ll
@@ -0,0 +1,51 @@
+; RUN: opt -S -memcpyopt < %s | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.__jmp_buf_tag = type { [8 x i64], i32, { [16 x i64] } }
+
+; Function Attrs: noinline nounwind uwtable
+declare void @g(i32* nocapture %y, %struct.__jmp_buf_tag* %b) #0
+
+; Function Attrs: noinline nounwind uwtable
+define i32 @f() #0 {
+entry:
+  %x = alloca i32, align 4
+  %y = alloca i32, align 4
+; CHECK:      %[[x:.*]] = alloca i32, align 4
+; CHECK-NEXT: %[[y:.*]] = alloca i32, align 4
+  %b = alloca %struct.__jmp_buf_tag, align 16
+  store volatile i32 1, i32* %x, align 4
+; CHECK:      store volatile i32 1, i32* %[[x]], align 4
+; CHECK-NEXT: call i32 @_setjmp(
+  %call = call i32 @_setjmp(%struct.__jmp_buf_tag* %b) #1
+  %tobool = icmp eq i32 %call, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  %x.0 = load volatile i32, i32* %x, align 4
+; CHECK: %[[x_load_0:.*]] = load volatile i32, i32* %[[x]], align 4
+  br label %return
+
+if.end:                                           ; preds = %entry
+  call void @g(i32* nonnull %y, %struct.__jmp_buf_tag* nonnull %b)
+  %y.load = load i32, i32* %y, align 4
+  store i32 %y.load, i32* %x, align 4
+  %x.1 = load volatile i32, i32* %x, align 4
+; CHECK:      %[[y_load:.*]] = load i32, i32* %[[y]], align 4
+; CHECK-NEXT: store i32 %[[y_load]], i32* %x, align 4
+; CHECK-NEXT: %[[x_load_1:.*]] = load volatile i32, i32* %[[x]], align 4
+  br label %return
+
+return:                                           ; preds = %if.end, %if.then
+  %retval = phi i32 [ %x.0, %if.then ], [ %x.1, %if.end ]
+; CHECK:      %[[retval:.*]] = phi i32 [ %[[x_load_0]], {{.*}} ], [ %[[x_load_1]], {{.*}} ]
+; CHECK-NEXT: ret i32 %[[retval]]
+  ret i32 %retval
+}
+
+; Function Attrs: nounwind returns_twice
+declare i32 @_setjmp(%struct.__jmp_buf_tag*) #1
+
+attributes #0 = { noinline nounwind uwtable }
+attributes #1 = { nounwind returns_twice }
Index: lib/Transforms/Scalar/MemCpyOptimizer.cpp
===================================================================
--- lib/Transforms/Scalar/MemCpyOptimizer.cpp
+++ lib/Transforms/Scalar/MemCpyOptimizer.cpp
@@ -1374,6 +1374,12 @@
   if (!TLI->has(LibFunc::memset) || !TLI->has(LibFunc::memcpy))
     return false;
 
+  // It is not safe to forward loads and stores around if calls to setjmp are
+  // present: there might be a call which longjmps causing a memory location to
+  // be initialized with an unexpected value.
+  if (F.callsFunctionThatReturnsTwice())
+    return false;
+
   while (1) {
     if (!iterateOnFunction(F))
       break;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D20555.58191.patch
Type: text/x-patch
Size: 2869 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160524/aefd95a9/attachment.bin>


More information about the llvm-commits mailing list