1; RUN: opt < %s -S -speculative-execution \ 2; RUN: -spec-exec-max-speculation-cost 4 -spec-exec-max-not-hoisted 3 \ 3; RUN: | FileCheck %s 4 5target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64" 6 7; Hoist in if-then pattern. 8define void @ifThen() { 9; CHECK-LABEL: @ifThen( 10; CHECK: %x = add i32 2, 3 11; CHECK: br i1 true 12 br i1 true, label %a, label %b 13; CHECK: a: 14a: 15 %x = add i32 2, 3 16; CHECK: br label 17 br label %b 18; CHECK: b: 19b: 20; CHECK: ret void 21 ret void 22} 23 24; Hoist in if-else pattern. 25define void @ifElse() { 26; CHECK-LABEL: @ifElse( 27; CHECK: %x = add i32 2, 3 28; CHECK: br i1 true 29 br i1 true, label %b, label %a 30; CHECK: a: 31a: 32 %x = add i32 2, 3 33; CHECK: br label 34 br label %b 35; CHECK: b: 36b: 37; CHECK: ret void 38 ret void 39} 40 41; Hoist in if-then-else pattern if it is equivalent to if-then. 42define void @ifElseThenAsIfThen() { 43; CHECK-LABEL: @ifElseThenAsIfThen( 44; CHECK: %x = add i32 2, 3 45; CHECK: br 46 br i1 true, label %a, label %b 47; CHECK: a: 48a: 49 %x = add i32 2, 3 50; CHECK: br label 51 br label %c 52; CHECK: b: 53b: 54 br label %c 55; CHECK: c 56c: 57 ret void 58} 59 60; Hoist in if-then-else pattern if it is equivalent to if-else. 61define void @ifElseThenAsIfElse() { 62; CHECK-LABEL: @ifElseThenAsIfElse( 63; CHECK: %x = add i32 2, 3 64; CHECK: br 65 br i1 true, label %b, label %a 66; CHECK: a: 67a: 68 %x = add i32 2, 3 69; CHECK: br label 70 br label %c 71; CHECK: b: 72b: 73 br label %c 74; CHECK: c 75c: 76 ret void 77} 78 79; Do not hoist if-then-else pattern if it is not equivalent to if-then 80; or if-else. 81define void @ifElseThen() { 82; CHECK-LABEL: @ifElseThen( 83; CHECK: br 84 br i1 true, label %a, label %b 85; CHECK: a: 86a: 87; CHECK: %x = add 88 %x = add i32 2, 3 89; CHECK: br label 90 br label %c 91; CHECK: b: 92b: 93; CHECK: %y = add 94 %y = add i32 2, 3 95 br label %c 96; CHECK: c 97c: 98 ret void 99} 100 101; Do not hoist loads and do not hoist an instruction past a definition of 102; an operand. 103define void @doNotHoistPastDef() { 104; CHECK-LABEL: @doNotHoistPastDef( 105 br i1 true, label %b, label %a 106; CHECK-NOT: load 107; CHECK-NOT: add 108; CHECK: a: 109a: 110; CHECK: %def = load 111 %def = load i32, i32* null 112; CHECK: %use = add 113 %use = add i32 %def, 0 114 br label %b 115; CHECK: b: 116b: 117 ret void 118} 119 120; Case with nothing to speculate. 121define void @nothingToSpeculate() { 122; CHECK-LABEL: @nothingToSpeculate( 123 br i1 true, label %b, label %a 124; CHECK: a: 125a: 126; CHECK: %def = load 127 %def = load i32, i32* null 128 br label %b 129; CHECK: b: 130b: 131 ret void 132} 133 134; Still hoist if an operand is defined before the block or is itself hoisted. 135define void @hoistIfNotPastDef() { 136; CHECK-LABEL: @hoistIfNotPastDef( 137; CHECK: %x = load 138 %x = load i32, i32* null 139; CHECK: %y = add i32 %x, 1 140; CHECK: %z = add i32 %y, 1 141; CHECK: br 142 br i1 true, label %b, label %a 143; CHECK: a: 144a: 145 %y = add i32 %x, 1 146 %z = add i32 %y, 1 147 br label %b 148; CHECK: b: 149b: 150 ret void 151} 152 153; Do not hoist if the speculation cost is too high. 154define void @costTooHigh() { 155; CHECK-LABEL: @costTooHigh( 156; CHECK: br 157 br i1 true, label %b, label %a 158; CHECK: a: 159a: 160; CHECK: %r1 = add 161 %r1 = add i32 1, 1 162; CHECK: %r2 = add 163 %r2 = add i32 1, 1 164; CHECK: %r3 = add 165 %r3 = add i32 1, 1 166; CHECK: %r4 = add 167 %r4 = add i32 1, 1 168; CHECK: %r5 = add 169 %r5 = add i32 1, 1 170 br label %b 171; CHECK: b: 172b: 173 ret void 174} 175 176; Do not hoist if too many instructions are left behind. 177define void @tooMuchLeftBehind() { 178; CHECK-LABEL: @tooMuchLeftBehind( 179; CHECK: br 180 br i1 true, label %b, label %a 181; CHECK: a: 182a: 183; CHECK: %x = load 184 %x = load i32, i32* null 185; CHECK: %r1 = add 186 %r1 = add i32 %x, 1 187; CHECK: %r2 = add 188 %r2 = add i32 %x, 1 189; CHECK: %r3 = add 190 %r3 = add i32 %x, 1 191 br label %b 192; CHECK: b: 193b: 194 ret void 195} 196