summaryrefslogtreecommitdiffstats
path: root/llvm/test
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/test')
-rw-r--r--llvm/test/Transforms/EarlyCSE/conditional.ll107
-rw-r--r--llvm/test/Transforms/EarlyCSE/edge.ll174
2 files changed, 281 insertions, 0 deletions
diff --git a/llvm/test/Transforms/EarlyCSE/conditional.ll b/llvm/test/Transforms/EarlyCSE/conditional.ll
new file mode 100644
index 00000000000..5b5a74f112b
--- /dev/null
+++ b/llvm/test/Transforms/EarlyCSE/conditional.ll
@@ -0,0 +1,107 @@
+; RUN: opt -early-cse -S < %s | FileCheck %s
+
+; Can we CSE a known condition to a constant?
+define i1 @test(i8* %p) {
+; CHECK-LABEL: @test
+entry:
+ %cnd1 = icmp eq i8* %p, null
+ br i1 %cnd1, label %taken, label %untaken
+
+taken:
+; CHECK-LABEL: taken:
+; CHECK-NEXT: ret i1 true
+ %cnd2 = icmp eq i8* %p, null
+ ret i1 %cnd2
+
+untaken:
+; CHECK-LABEL: untaken:
+; CHECK-NEXT: ret i1 false
+ %cnd3 = icmp eq i8* %p, null
+ ret i1 %cnd3
+}
+
+; We can CSE the condition, but we *don't* know it's value after the merge
+define i1 @test_neg1(i8* %p) {
+; CHECK-LABEL: @test_neg1
+entry:
+ %cnd1 = icmp eq i8* %p, null
+ br i1 %cnd1, label %taken, label %untaken
+
+taken:
+ br label %merge
+
+untaken:
+ br label %merge
+
+merge:
+; CHECK-LABEL: merge:
+; CHECK-NEXT: ret i1 %cnd1
+ %cnd3 = icmp eq i8* %p, null
+ ret i1 %cnd3
+}
+
+; Check specifically for a case where we have a unique predecessor, but
+; not a single predecessor. We can not know the value of the condition here.
+define i1 @test_neg2(i8* %p) {
+; CHECK-LABEL: @test_neg2
+entry:
+ %cnd1 = icmp eq i8* %p, null
+ br i1 %cnd1, label %merge, label %merge
+
+merge:
+; CHECK-LABEL: merge:
+; CHECK-NEXT: ret i1 %cnd1
+ %cnd3 = icmp eq i8* %p, null
+ ret i1 %cnd3
+}
+
+; Replace a use rather than CSE
+define i1 @test2(i8* %p) {
+; CHECK-LABEL: @test2
+entry:
+ %cnd = icmp eq i8* %p, null
+ br i1 %cnd, label %taken, label %untaken
+
+taken:
+; CHECK-LABEL: taken:
+; CHECK-NEXT: ret i1 true
+ ret i1 %cnd
+
+untaken:
+; CHECK-LABEL: untaken:
+; CHECK-NEXT: ret i1 false
+ ret i1 %cnd
+}
+
+; Not legal to replace use given it's not dominated by edge
+define i1 @test2_neg1(i8* %p) {
+; CHECK-LABEL: @test2_neg1
+entry:
+ %cnd1 = icmp eq i8* %p, null
+ br i1 %cnd1, label %taken, label %untaken
+
+taken:
+ br label %merge
+
+untaken:
+ br label %merge
+
+merge:
+; CHECK-LABEL: merge:
+; CHECK-NEXT: ret i1 %cnd1
+ ret i1 %cnd1
+}
+
+; Another single predecessor test, but for dominated use
+define i1 @test2_neg2(i8* %p) {
+; CHECK-LABEL: @test2_neg2
+entry:
+ %cnd1 = icmp eq i8* %p, null
+ br i1 %cnd1, label %merge, label %merge
+
+merge:
+; CHECK-LABEL: merge:
+; CHECK-NEXT: ret i1 %cnd1
+ ret i1 %cnd1
+}
+
diff --git a/llvm/test/Transforms/EarlyCSE/edge.ll b/llvm/test/Transforms/EarlyCSE/edge.ll
new file mode 100644
index 00000000000..94b29260375
--- /dev/null
+++ b/llvm/test/Transforms/EarlyCSE/edge.ll
@@ -0,0 +1,174 @@
+; RUN: opt -early-cse -S < %s | FileCheck %s
+; Same as GVN/edge.ll, but updated to reflect EarlyCSE's less powerful
+; implementation. EarlyCSE doesn't yet handle uses on edges where the
+; source is dominated, but the dest is not. Nor does it reason about
+; fcmps. This file can basically be seen as a list of TODOs.
+
+define i32 @f1(i32 %x) {
+ ; CHECK-LABEL: define i32 @f1(
+bb0:
+ %cmp = icmp eq i32 %x, 0
+ br i1 %cmp, label %bb2, label %bb1
+bb1:
+ br label %bb2
+bb2:
+ %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ]
+ %foo = add i32 %cond, %x
+ ret i32 %foo
+ ; CHECK: bb2:
+ ; CHECK: %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ]
+}
+
+define i32 @f2(i32 %x) {
+ ; CHECK-LABEL: define i32 @f2(
+bb0:
+ %cmp = icmp ne i32 %x, 0
+ br i1 %cmp, label %bb1, label %bb2
+bb1:
+ br label %bb2
+bb2:
+ %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ]
+ %foo = add i32 %cond, %x
+ ret i32 %foo
+ ; CHECK: bb2:
+ ; CHECK: %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ]
+}
+
+define i32 @f3(i32 %x) {
+ ; CHECK-LABEL: define i32 @f3(
+bb0:
+ switch i32 %x, label %bb1 [ i32 0, label %bb2]
+bb1:
+ br label %bb2
+bb2:
+ %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ]
+ %foo = add i32 %cond, %x
+ ret i32 %foo
+ ; CHECK: bb2:
+ ; CHECK: %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ]
+}
+
+declare void @g(i1)
+define void @f4(i8 * %x) {
+; CHECK-LABEL: define void @f4(
+bb0:
+ %y = icmp eq i8* null, %x
+ br i1 %y, label %bb2, label %bb1
+bb1:
+ br label %bb2
+bb2:
+ %zed = icmp eq i8* null, %x
+ call void @g(i1 %zed)
+; CHECK: call void @g(i1 %y)
+ ret void
+}
+
+define double @fcmp_oeq_not_zero(double %x, double %y) {
+entry:
+ %cmp = fcmp oeq double %y, 2.0
+ br i1 %cmp, label %if, label %return
+
+if:
+ %div = fdiv double %x, %y
+ br label %return
+
+return:
+ %retval = phi double [ %div, %if ], [ %x, %entry ]
+ ret double %retval
+
+; CHECK-LABEL: define double @fcmp_oeq_not_zero(
+; CHECK: %div = fdiv double %x, %y
+}
+
+define double @fcmp_une_not_zero(double %x, double %y) {
+entry:
+ %cmp = fcmp une double %y, 2.0
+ br i1 %cmp, label %return, label %else
+
+else:
+ %div = fdiv double %x, %y
+ br label %return
+
+return:
+ %retval = phi double [ %div, %else ], [ %x, %entry ]
+ ret double %retval
+
+; CHECK-LABEL: define double @fcmp_une_not_zero(
+; CHECK: %div = fdiv double %x, %y
+}
+
+; PR22376 - We can't propagate zero constants because -0.0
+; compares equal to 0.0. If %y is -0.0 in this test case,
+; we would produce the wrong sign on the infinity return value.
+define double @fcmp_oeq_zero(double %x, double %y) {
+entry:
+ %cmp = fcmp oeq double %y, 0.0
+ br i1 %cmp, label %if, label %return
+
+if:
+ %div = fdiv double %x, %y
+ br label %return
+
+return:
+ %retval = phi double [ %div, %if ], [ %x, %entry ]
+ ret double %retval
+
+; CHECK-LABEL: define double @fcmp_oeq_zero(
+; CHECK: %div = fdiv double %x, %y
+}
+
+define double @fcmp_une_zero(double %x, double %y) {
+entry:
+ %cmp = fcmp une double %y, -0.0
+ br i1 %cmp, label %return, label %else
+
+else:
+ %div = fdiv double %x, %y
+ br label %return
+
+return:
+ %retval = phi double [ %div, %else ], [ %x, %entry ]
+ ret double %retval
+
+; CHECK-LABEL: define double @fcmp_une_zero(
+; CHECK: %div = fdiv double %x, %y
+}
+
+; We also cannot propagate a value if it's not a constant.
+; This is because the value could be 0.0 or -0.0.
+
+define double @fcmp_oeq_maybe_zero(double %x, double %y, double %z1, double %z2) {
+entry:
+ %z = fadd double %z1, %z2
+ %cmp = fcmp oeq double %y, %z
+ br i1 %cmp, label %if, label %return
+
+if:
+ %div = fdiv double %x, %z
+ br label %return
+
+return:
+ %retval = phi double [ %div, %if ], [ %x, %entry ]
+ ret double %retval
+
+; CHECK-LABEL: define double @fcmp_oeq_maybe_zero(
+; CHECK: %div = fdiv double %x, %z
+}
+
+define double @fcmp_une_maybe_zero(double %x, double %y, double %z1, double %z2) {
+entry:
+ %z = fadd double %z1, %z2
+ %cmp = fcmp une double %y, %z
+ br i1 %cmp, label %return, label %else
+
+else:
+ %div = fdiv double %x, %z
+ br label %return
+
+return:
+ %retval = phi double [ %div, %else ], [ %x, %entry ]
+ ret double %retval
+
+; CHECK-LABEL: define double @fcmp_une_maybe_zero(
+; CHECK: %div = fdiv double %x, %z
+}
OpenPOWER on IntegriCloud