[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