summaryrefslogtreecommitdiff
path: root/test/Transforms/SimplifyCFG
diff options
context:
space:
mode:
authorBenjamin Kramer <benny.kra@googlemail.com>2011-08-26 01:22:29 +0000
committerBenjamin Kramer <benny.kra@googlemail.com>2011-08-26 01:22:29 +0000
commit98d6d2372feb2f8bb4c3941b278027499cbfc00b (patch)
treecb59e69fde14c5b6d82f15ca93ffac2204b3a510 /test/Transforms/SimplifyCFG
parent1a9a2d0d6b16cea4cf98fdce5db597008453cbd6 (diff)
downloadllvm-98d6d2372feb2f8bb4c3941b278027499cbfc00b.tar.gz
llvm-98d6d2372feb2f8bb4c3941b278027499cbfc00b.tar.bz2
llvm-98d6d2372feb2f8bb4c3941b278027499cbfc00b.tar.xz
SimplifyCFG: If we have a PHI node that can evaluate to NULL and do a load or store to the address returned by the PHI node then we can consider this incoming value as dead and remove the edge pointing there, unless there are instructions that can affect control flow executed in between.
In theory this could be extended to other instructions, eg. division by zero, but it's likely that it will "miscompile" some code because people depend on div by zero not trapping. NULL pointer dereference usually leads to a crash so we should be on the safe side. This shrinks the size of a Release clang by 16k on x86_64. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@138618 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/Transforms/SimplifyCFG')
-rw-r--r--test/Transforms/SimplifyCFG/phi-undef-loadstore.ll87
1 files changed, 87 insertions, 0 deletions
diff --git a/test/Transforms/SimplifyCFG/phi-undef-loadstore.ll b/test/Transforms/SimplifyCFG/phi-undef-loadstore.ll
new file mode 100644
index 0000000000..65d888ea01
--- /dev/null
+++ b/test/Transforms/SimplifyCFG/phi-undef-loadstore.ll
@@ -0,0 +1,87 @@
+; RUN: opt -simplifycfg -S < %s | FileCheck %s
+
+declare void @bar() nounwind
+
+define i32 @test1(i32* %a, i32 %b, i32* %c, i32 %d) nounwind {
+entry:
+ %tobool = icmp eq i32 %b, 0
+ br i1 %tobool, label %if.else, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @bar() nounwind
+ br label %if.end7
+
+if.else: ; preds = %entry
+ %tobool3 = icmp eq i32 %d, 0
+ br i1 %tobool3, label %if.end7, label %if.then4
+
+if.then4: ; preds = %if.else
+ tail call void @bar() nounwind
+ br label %if.end7
+
+if.end7: ; preds = %if.else, %if.then4, %if.then
+ %x.0 = phi i32* [ %a, %if.then ], [ %c, %if.then4 ], [ null, %if.else ]
+ %tmp9 = load i32* %x.0
+ ret i32 %tmp9
+
+; CHECK: @test1
+; CHECK: if.else:
+; CHECK: br label %if.end7
+
+; CHECK: phi i32* [ %a, %if.then ], [ %c, %if.else ]
+}
+
+define i32 @test2(i32* %a, i32 %b, i32* %c, i32 %d) nounwind {
+entry:
+ %tobool = icmp eq i32 %b, 0
+ br i1 %tobool, label %if.else, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @bar() nounwind
+ br label %if.end7
+
+if.else: ; preds = %entry
+ %tobool3 = icmp eq i32 %d, 0
+ br i1 %tobool3, label %if.end7, label %if.then4
+
+if.then4: ; preds = %if.else
+ tail call void @bar() nounwind
+ br label %if.end7
+
+if.end7: ; preds = %if.else, %if.then4, %if.then
+ %x.0 = phi i32* [ %a, %if.then ], [ null, %if.then4 ], [ null, %if.else ]
+ %tmp9 = load i32* %x.0
+ ret i32 %tmp9
+; CHECK: @test2
+; CHECK: if.else:
+; CHECK: unreachable
+
+; CHECK-NOT: phi
+}
+
+define i32 @test3(i32* %a, i32 %b, i32* %c, i32 %d) nounwind {
+entry:
+ %tobool = icmp eq i32 %b, 0
+ br i1 %tobool, label %if.else, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @bar() nounwind
+ br label %if.end7
+
+if.else: ; preds = %entry
+ %tobool3 = icmp eq i32 %d, 0
+ br i1 %tobool3, label %if.end7, label %if.then4
+
+if.then4: ; preds = %if.else
+ tail call void @bar() nounwind
+ br label %if.end7
+
+if.end7: ; preds = %if.else, %if.then4, %if.then
+ %x.0 = phi i32* [ %a, %if.then ], [ null, %if.then4 ], [ null, %if.else ]
+ tail call void @bar() nounwind
+ %tmp9 = load i32* %x.0
+ ret i32 %tmp9
+; CHECK: @test3
+; CHECK: if.end7:
+; CHECK: phi i32* [ %a, %if.then ], [ null, %if.then4 ], [ null, %if.else ]
+}