| ; RUN: opt < %s -S -speculative-execution \ | |
| ; RUN: -spec-exec-max-speculation-cost 4 -spec-exec-max-not-hoisted 3 \ | |
| ; RUN: | FileCheck %s | |
| ; RUN: opt < %s -S -passes='speculative-execution' \ | |
| ; RUN: -spec-exec-max-speculation-cost 4 -spec-exec-max-not-hoisted 3 \ | |
| ; RUN: | FileCheck %s | |
| target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64" | |
| ; Hoist in if-then pattern. | |
| define void @ifThen() { | |
| ; CHECK-LABEL: @ifThen( | |
| ; CHECK: %x = add i32 2, 3 | |
| ; CHECK: br i1 true | |
| br i1 true, label %a, label %b | |
| ; CHECK: a: | |
| a: | |
| %x = add i32 2, 3 | |
| ; CHECK: br label | |
| br label %b | |
| ; CHECK: b: | |
| b: | |
| ; CHECK: ret void | |
| ret void | |
| } | |
| ; Hoist in if-else pattern. | |
| define void @ifElse() { | |
| ; CHECK-LABEL: @ifElse( | |
| ; CHECK: %x = add i32 2, 3 | |
| ; CHECK: br i1 true | |
| br i1 true, label %b, label %a | |
| ; CHECK: a: | |
| a: | |
| %x = add i32 2, 3 | |
| ; CHECK: br label | |
| br label %b | |
| ; CHECK: b: | |
| b: | |
| ; CHECK: ret void | |
| ret void | |
| } | |
| ; Hoist in if-then-else pattern if it is equivalent to if-then. | |
| define void @ifElseThenAsIfThen() { | |
| ; CHECK-LABEL: @ifElseThenAsIfThen( | |
| ; CHECK: %x = add i32 2, 3 | |
| ; CHECK: br | |
| br i1 true, label %a, label %b | |
| ; CHECK: a: | |
| a: | |
| %x = add i32 2, 3 | |
| ; CHECK: br label | |
| br label %c | |
| ; CHECK: b: | |
| b: | |
| br label %c | |
| ; CHECK: c | |
| c: | |
| ret void | |
| } | |
| ; Hoist in if-then-else pattern if it is equivalent to if-else. | |
| define void @ifElseThenAsIfElse() { | |
| ; CHECK-LABEL: @ifElseThenAsIfElse( | |
| ; CHECK: %x = add i32 2, 3 | |
| ; CHECK: br | |
| br i1 true, label %b, label %a | |
| ; CHECK: a: | |
| a: | |
| %x = add i32 2, 3 | |
| ; CHECK: br label | |
| br label %c | |
| ; CHECK: b: | |
| b: | |
| br label %c | |
| ; CHECK: c | |
| c: | |
| ret void | |
| } | |
| ; Do not hoist if-then-else pattern if it is not equivalent to if-then | |
| ; or if-else. | |
| define void @ifElseThen() { | |
| ; CHECK-LABEL: @ifElseThen( | |
| ; CHECK: br | |
| br i1 true, label %a, label %b | |
| ; CHECK: a: | |
| a: | |
| ; CHECK: %x = add | |
| %x = add i32 2, 3 | |
| ; CHECK: br label | |
| br label %c | |
| ; CHECK: b: | |
| b: | |
| ; CHECK: %y = add | |
| %y = add i32 2, 3 | |
| br label %c | |
| ; CHECK: c | |
| c: | |
| ret void | |
| } | |
| ; Do not hoist loads and do not hoist an instruction past a definition of | |
| ; an operand. | |
| define void @doNotHoistPastDef() { | |
| ; CHECK-LABEL: @doNotHoistPastDef( | |
| br i1 true, label %b, label %a | |
| ; CHECK-NOT: load | |
| ; CHECK-NOT: add | |
| ; CHECK: a: | |
| a: | |
| ; CHECK: %def = load | |
| %def = load i32, i32* null | |
| ; CHECK: %use = add | |
| %use = add i32 %def, 0 | |
| br label %b | |
| ; CHECK: b: | |
| b: | |
| ret void | |
| } | |
| ; Case with nothing to speculate. | |
| define void @nothingToSpeculate() { | |
| ; CHECK-LABEL: @nothingToSpeculate( | |
| br i1 true, label %b, label %a | |
| ; CHECK: a: | |
| a: | |
| ; CHECK: %def = load | |
| %def = load i32, i32* null | |
| br label %b | |
| ; CHECK: b: | |
| b: | |
| ret void | |
| } | |
| ; Still hoist if an operand is defined before the block or is itself hoisted. | |
| define void @hoistIfNotPastDef() { | |
| ; CHECK-LABEL: @hoistIfNotPastDef( | |
| ; CHECK: %x = load | |
| %x = load i32, i32* null | |
| ; CHECK: %y = add i32 %x, 1 | |
| ; CHECK: %z = add i32 %y, 1 | |
| ; CHECK: br | |
| br i1 true, label %b, label %a | |
| ; CHECK: a: | |
| a: | |
| %y = add i32 %x, 1 | |
| %z = add i32 %y, 1 | |
| br label %b | |
| ; CHECK: b: | |
| b: | |
| ret void | |
| } | |
| ; Do not hoist if the speculation cost is too high. | |
| define void @costTooHigh() { | |
| ; CHECK-LABEL: @costTooHigh( | |
| ; CHECK: br | |
| br i1 true, label %b, label %a | |
| ; CHECK: a: | |
| a: | |
| ; CHECK: %r1 = add | |
| %r1 = add i32 1, 1 | |
| ; CHECK: %r2 = add | |
| %r2 = add i32 1, 1 | |
| ; CHECK: %r3 = add | |
| %r3 = add i32 1, 1 | |
| ; CHECK: %r4 = add | |
| %r4 = add i32 1, 1 | |
| ; CHECK: %r5 = add | |
| %r5 = add i32 1, 1 | |
| br label %b | |
| ; CHECK: b: | |
| b: | |
| ret void | |
| } | |
| ; Do not hoist if too many instructions are left behind. | |
| define void @tooMuchLeftBehind() { | |
| ; CHECK-LABEL: @tooMuchLeftBehind( | |
| ; CHECK: br | |
| br i1 true, label %b, label %a | |
| ; CHECK: a: | |
| a: | |
| ; CHECK: %x = load | |
| %x = load i32, i32* null | |
| ; CHECK: %r1 = add | |
| %r1 = add i32 %x, 1 | |
| ; CHECK: %r2 = add | |
| %r2 = add i32 %x, 1 | |
| ; CHECK: %r3 = add | |
| %r3 = add i32 %x, 1 | |
| br label %b | |
| ; CHECK: b: | |
| b: | |
| ret void | |
| } |