1; RUN: opt < %s -jump-threading -S -verify | FileCheck %s 2 3target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" 4target triple = "x86_64-unknown-linux-gnu" 5 6@a = global i32 0, align 4 7 8define void @foo(i32 %cond1, i32 %cond2) { 9; CHECK-LABEL: @foo 10; CHECK-LABEL: entry 11entry: 12 %tobool = icmp eq i32 %cond1, 0 13 br i1 %tobool, label %bb.cond2, label %bb.f1 14 15bb.f1: 16 call void @f1() 17 br label %bb.cond2 18; Verify that we branch on cond2 without checking ptr. 19; CHECK: call void @f1() 20; CHECK-NEXT: icmp eq i32 %cond2, 0 21; CHECK-NEXT: label %bb.f4, label %bb.f2 22 23bb.cond2: 24 %ptr = phi i32* [ null, %bb.f1 ], [ @a, %entry ] 25 %tobool1 = icmp eq i32 %cond2, 0 26 br i1 %tobool1, label %bb.file, label %bb.f2 27; Verify that we branch on cond2 without checking ptr. 28; CHECK: icmp eq i32 %cond2, 0 29; CHECK-NEXT: label %bb.f3, label %bb.f2 30 31bb.f2: 32 call void @f2() 33 br label %exit 34 35; Verify that we eliminate this basic block. 36; CHECK-NOT: bb.file: 37bb.file: 38 %cmp = icmp eq i32* %ptr, null 39 br i1 %cmp, label %bb.f4, label %bb.f3 40 41bb.f3: 42 call void @f3() 43 br label %exit 44 45bb.f4: 46 call void @f4() 47 br label %exit 48 49exit: 50 ret void 51} 52 53declare void @f1() 54 55declare void @f2() 56 57declare void @f3() 58 59declare void @f4() 60 61 62define void @foo2(i32 %cond1, i32 %cond2) { 63; CHECK-LABEL: @foo2 64; CHECK-LABEL: entry 65entry: 66 %tobool = icmp ne i32 %cond1, 0 67 br i1 %tobool, label %bb.f1, label %bb.f2 68 69bb.f1: 70 call void @f1() 71 br label %bb.cond2 72; Verify that we branch on cond2 without checking tobool again. 73; CHECK: call void @f1() 74; CHECK-NEXT: icmp eq i32 %cond2, 0 75; CHECK-NEXT: label %exit, label %bb.f3 76 77bb.f2: 78 call void @f2() 79 br label %bb.cond2 80; Verify that we branch on cond2 without checking tobool again. 81; CHECK: call void @f2() 82; CHECK-NEXT: icmp eq i32 %cond2, 0 83; CHECK-NEXT: label %exit, label %bb.f4 84 85bb.cond2: 86 %tobool1 = icmp eq i32 %cond2, 0 87 br i1 %tobool1, label %exit, label %bb.cond1again 88 89; Verify that we eliminate this basic block. 90; CHECK-NOT: bb.cond1again: 91bb.cond1again: 92 br i1 %tobool, label %bb.f3, label %bb.f4 93 94bb.f3: 95 call void @f3() 96 br label %exit 97 98bb.f4: 99 call void @f4() 100 br label %exit 101 102exit: 103 ret void 104} 105 106 107; Verify that we do *not* thread any edge. We used to evaluate 108; constant expressions like: 109; 110; icmp ugt i8* null, inttoptr (i64 4 to i8*) 111; 112; as "true", causing jump threading to a wrong destination. 113define void @foo3(i8* %arg1, i8* %arg2) { 114; CHECK-LABEL: @foo 115; CHECK-NOT: bb_{{[^ ]*}}.thread: 116entry: 117 %cmp1 = icmp eq i8* %arg1, null 118 br i1 %cmp1, label %bb_bar1, label %bb_end 119 120bb_bar1: 121 call void @bar(i32 1) 122 br label %bb_end 123 124bb_end: 125 %cmp2 = icmp ne i8* %arg2, null 126 br i1 %cmp2, label %bb_cont, label %bb_bar2 127 128bb_bar2: 129 call void @bar(i32 2) 130 br label %bb_exit 131 132bb_cont: 133 %cmp3 = icmp ule i8* %arg1, inttoptr (i64 4 to i8*) 134 br i1 %cmp3, label %bb_exit, label %bb_bar3 135 136bb_bar3: 137 call void @bar(i32 3) 138 br label %bb_exit 139 140bb_exit: 141 ret void 142} 143 144declare void @bar(i32) 145 146 147;; Test that we skip unconditional PredBB when threading jumps through two 148;; successive basic blocks. 149 150define i32 @foo4(i32* %0) { 151; CHECK-LABEL: @f 152; CHECK: br i1 %good, label %pred.bb, label %pred.pred.bb 153entry: 154 %size = call i64 @get_size(i32* %0) 155 %good = icmp ugt i64 %size, 3 156 br i1 %good, label %pred.bb, label %pred.pred.bb 157 158; CHECK: pred.pred.bb: 159; CHECK: br label %pred.bb 160; CHECK: pred.bb: 161; CHECK: br label %bb 162; CHECK: bb: 163pred.pred.bb: ; preds = %entry 164 call void @effect() 165 br label %pred.bb 166pred.bb: ; preds = %pred.pred.bb, %entry 167 %v = load i32, i32* %0 168 br label %bb 169 170bb: ; preds = %pred.bb 171 call void @effect1(i8* blockaddress(@foo4, %bb)) 172 br i1 %good, label %cont2, label %cont1 173 174cont1: ; preds = %bb 175 br i1 %good, label %exit, label %cont2 176cont2: ; preds = %bb 177 br label %exit 178exit: ; preds = %cont1, %cont2 179 ret i32 %v 180} 181 182declare i64 @get_size(i32*) 183declare void @effect() 184declare void @effect1(i8*) 185