1; RUN: opt < %s -instcombine -instcombine-infinite-loop-threshold=2 -S | FileCheck %s 2; RUN: opt < %s -instcombine -S -debugify-each | FileCheck %s 3; RUN: opt < %s -passes=instcombine -S -debugify-each | FileCheck %s 4 5declare void @llvm.experimental.guard(i1, ...) 6 7define void @test_guard_adjacent_same_cond(i1 %A) { 8; CHECK-LABEL: @test_guard_adjacent_same_cond( 9; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %A) [ "deopt"() ] 10; CHECK-NEXT: ret void 11 call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ] 12 call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ] 13 call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ] 14 call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ] 15 call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ] 16 call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ] 17 call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ] 18 call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ] 19 call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ] 20 call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ] 21 ret void 22} 23 24define void @test_guard_adjacent_diff_cond(i1 %A, i1 %B, i1 %C) { 25; CHECK-LABEL: @test_guard_adjacent_diff_cond( 26; CHECK-NEXT: %1 = and i1 %A, %B 27; CHECK-NEXT: %2 = and i1 %1, %C 28; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %2, i32 123) [ "deopt"() ] 29; CHECK-NEXT: ret void 30 call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ] 31 call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ] 32 call void(i1, ...) @llvm.experimental.guard( i1 %C, i32 789 )[ "deopt"() ] 33 ret void 34} 35 36; This version tests for the common form where the conditions are 37; between the guards 38define void @test_guard_adjacent_diff_cond2(i32 %V1, i32 %V2) { 39; CHECK-LABEL: @test_guard_adjacent_diff_cond2( 40; CHECK-NEXT: %1 = and i32 %V1, %V2 41; CHECK-NEXT: %2 = icmp slt i32 %1, 0 42; CHECK-NEXT: %and = and i32 %V1, 255 43; CHECK-NEXT: %C = icmp ult i32 %and, 129 44; CHECK-NEXT: %3 = and i1 %2, %C 45; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %3, i32 123) [ "deopt"() ] 46; CHECK-NEXT: ret void 47 %A = icmp slt i32 %V1, 0 48 call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ] 49 %B = icmp slt i32 %V2, 0 50 call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ] 51 %and = and i32 %V1, 255 52 %C = icmp sle i32 %and, 128 53 call void(i1, ...) @llvm.experimental.guard( i1 %C, i32 789 )[ "deopt"() ] 54 ret void 55} 56 57; Might not be legal to hoist the load above the first guard since the 58; guard might control dereferenceability 59define void @negative_load(i32 %V1, i32* %P) { 60; CHECK-LABEL: @negative_load 61; CHECK: @llvm.experimental.guard 62; CHECK: @llvm.experimental.guard 63 %A = icmp slt i32 %V1, 0 64 call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ] 65 %V2 = load i32, i32* %P 66 %B = icmp slt i32 %V2, 0 67 call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ] 68 ret void 69} 70 71define void @deref_load(i32 %V1, i32* dereferenceable(4) align 4 %P) { 72; CHECK-LABEL: @deref_load 73; CHECK-NEXT: %V2 = load i32, i32* %P, align 4 74; CHECK-NEXT: %1 = and i32 %V2, %V1 75; CHECK-NEXT: %2 = icmp slt i32 %1, 0 76; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %2, i32 123) [ "deopt"() ] 77 %A = icmp slt i32 %V1, 0 78 call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ] 79 %V2 = load i32, i32* %P 80 %B = icmp slt i32 %V2, 0 81 call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ] 82 ret void 83} 84 85; The divide might fault above the guard 86define void @negative_div(i32 %V1, i32 %D) { 87; CHECK-LABEL: @negative_div 88; CHECK: @llvm.experimental.guard 89; CHECK: @llvm.experimental.guard 90 %A = icmp slt i32 %V1, 0 91 call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ] 92 %V2 = udiv i32 %V1, %D 93 %B = icmp slt i32 %V2, 0 94 call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ] 95 ret void 96} 97 98; Highlight the limit of the window in a case which would otherwise be mergable 99define void @negative_window(i32 %V1, i32 %a, i32 %b, i32 %c, i32 %d) { 100; CHECK-LABEL: @negative_window 101; CHECK: @llvm.experimental.guard 102; CHECK: @llvm.experimental.guard 103 %A = icmp slt i32 %V1, 0 104 call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ] 105 %V2 = add i32 %a, %b 106 %V3 = add i32 %V2, %c 107 %V4 = add i32 %V3, %d 108 %B = icmp slt i32 %V4, 0 109 call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ] 110 ret void 111} 112 113