diff options
author | Jakob Stoklund Olesen <stoklund@2pi.dk> | 2012-03-29 17:22:39 +0000 |
---|---|---|
committer | Jakob Stoklund Olesen <stoklund@2pi.dk> | 2012-03-29 17:22:39 +0000 |
commit | 41e2073f623a08504e2e1e5a9fc5c9f22a03eb83 (patch) | |
tree | c4f05adc3565dc1ccd4bdfd913e4a9b091e23fdb /test/Transforms/GVN | |
parent | 73478404af7f6b6e64bdda5920ebaede6a4e7a14 (diff) | |
download | llvm-41e2073f623a08504e2e1e5a9fc5c9f22a03eb83.tar.gz llvm-41e2073f623a08504e2e1e5a9fc5c9f22a03eb83.tar.bz2 llvm-41e2073f623a08504e2e1e5a9fc5c9f22a03eb83.tar.xz |
Don't PRE compares.
CodeGenPrepare sinks compare instructions down to their uses to prevent
live flags and predicate registers across basic blocks.
PRE of a compare instruction prevents that, forcing the i1 compare
result into a general purpose register. That is usually more expensive
than the redundant compare PRE was trying to eliminate in the first
place.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153657 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/Transforms/GVN')
-rw-r--r-- | test/Transforms/GVN/pre-compare.ll | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/test/Transforms/GVN/pre-compare.ll b/test/Transforms/GVN/pre-compare.ll new file mode 100644 index 0000000000..18d0c2e108 --- /dev/null +++ b/test/Transforms/GVN/pre-compare.ll @@ -0,0 +1,68 @@ +; RUN: opt -gvn -S < %s | FileCheck %s + +; C source: +; +; void f(int x) { +; if (x != 1) +; puts (x == 2 ? "a" : "b"); +; for (;;) { +; puts("step 1"); +; if (x == 2) +; continue; +; printf("step 2: %d\n", x); +; } +; } +; +; If we PRE %cmp3, CodeGenPrepare won't be able to sink the compare down to its +; uses, and we are forced to keep both %x and %cmp3 in registers in the loop. +; +; It is just as cheap to recompute the icmp against %x as it is to compare a +; GPR against 0. On x86-64, the br i1 %cmp3 becomes: +; +; testb %r12b, %r12b +; jne LBB0_3 +; +; The sunk icmp is: +; +; cmpl $2, %ebx +; je LBB0_3 +; +; This is just as good, and it doesn't require a separate register. +; +; CHECK-NOT: phi i1 + +@.str = private unnamed_addr constant [2 x i8] c"a\00", align 1 +@.str1 = private unnamed_addr constant [2 x i8] c"b\00", align 1 +@.str2 = private unnamed_addr constant [7 x i8] c"step 1\00", align 1 +@.str3 = private unnamed_addr constant [12 x i8] c"step 2: %d\0A\00", align 1 + +define void @f(i32 %x) noreturn nounwind uwtable ssp { +entry: + %cmp = icmp eq i32 %x, 1 + br i1 %cmp, label %for.cond.preheader, label %if.then + +if.then: ; preds = %entry + %cmp1 = icmp eq i32 %x, 2 + %cond = select i1 %cmp1, i8* getelementptr inbounds ([2 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8]* @.str1, i64 0, i64 0) + %call = tail call i32 @puts(i8* %cond) nounwind + br label %for.cond.preheader + +for.cond.preheader: ; preds = %entry, %if.then + %cmp3 = icmp eq i32 %x, 2 + br label %for.cond + +for.cond: ; preds = %for.cond.backedge, %for.cond.preheader + %call2 = tail call i32 @puts(i8* getelementptr inbounds ([7 x i8]* @.str2, i64 0, i64 0)) nounwind + br i1 %cmp3, label %for.cond.backedge, label %if.end5 + +if.end5: ; preds = %for.cond + %call6 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([12 x i8]* @.str3, i64 0, i64 0), i32 %x) nounwind + br label %for.cond.backedge + +for.cond.backedge: ; preds = %if.end5, %for.cond + br label %for.cond +} + +declare i32 @puts(i8* nocapture) nounwind + +declare i32 @printf(i8* nocapture, ...) nounwind |