1; RUN: opt -S -passes=gvn -enable-load-pre < %s | FileCheck %s 2 3target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 4target triple = "x86_64-unknown-linux-gnu" 5 6; These tests exercise situations when instructions that were first instructions 7; with implicit control flow get removed. We make sure that after that we don't 8; face crashes and are still able to perform PRE correctly. 9 10declare i32 @foo(i32 %arg) #0 11 12define hidden void @test_01(i32 %x, i32 %y) { 13 14; c2 only throws if c1 throws, so it can be safely removed and then PRE can 15; hoist the load out of loop. 16 17; CHECK-LABEL: @test_01 18; CHECK: entry: 19; CHECK-NEXT: %c1 = call i32 @foo(i32 %x) 20; CHECK-NEXT: %val.pre = load i32, ptr null, align 8 21; CHECK-NEXT: br label %loop 22; CHECK: loop: 23; CHECK-NEXT: %c3 = call i32 @foo(i32 %val.pre) 24; CHECK-NEXT: br label %loop 25 26entry: 27 %c1 = call i32 @foo(i32 %x) 28 br label %loop 29 30loop: 31 %c2 = call i32 @foo(i32 %x) 32 %val = load i32, ptr null, align 8 33 %c3 = call i32 @foo(i32 %val) 34 br label %loop 35} 36 37define hidden void @test_02(i32 %x, i32 %y) { 38 39; PRE is not allowed because c2 may throw. 40 41; CHECK-LABEL: @test_02 42; CHECK: entry: 43; CHECK-NEXT: %c1 = call i32 @foo(i32 %x) 44; CHECK-NEXT: br label %loop 45; CHECK: loop: 46; CHECK-NEXT: %c2 = call i32 @foo(i32 %y) 47; CHECK-NEXT: %val = load i32, ptr null, align 8 48; CHECK-NEXT: %c3 = call i32 @foo(i32 %val) 49; CHECK-NEXT: br label %loop 50 51entry: 52 %c1 = call i32 @foo(i32 %x) 53 br label %loop 54 55loop: 56 %c2 = call i32 @foo(i32 %y) 57 %val = load i32, ptr null, align 8 58 %c3 = call i32 @foo(i32 %val) 59 br label %loop 60} 61 62define hidden void @test_03(i32 %x, i32 %y) { 63 64; PRE of load is allowed because c2 only throws if c1 throws. c3 should 65; not be eliminated. c4 is eliminated because it only throws if c3 throws. 66 67; CHECK-LABEL: @test_03 68; CHECK: entry: 69; CHECK-NEXT: %c1 = call i32 @foo(i32 %x) 70; CHECK-NEXT: %val.pre = load i32, ptr null, align 8 71; CHECK-NEXT: br label %loop 72; CHECK: loop: 73; CHECK-NEXT: %c3 = call i32 @foo(i32 %y) 74; CHECK-NEXT: %c5 = call i32 @foo(i32 %val.pre) 75; CHECK-NEXT: br label %loop 76 77entry: 78 %c1 = call i32 @foo(i32 %x) 79 br label %loop 80 81loop: 82 %c2 = call i32 @foo(i32 %x) 83 %val = load i32, ptr null, align 8 84 %c3 = call i32 @foo(i32 %y) 85 %val2 = load i32, ptr null, align 8 86 %c4 = call i32 @foo(i32 %y) 87 %c5 = call i32 @foo(i32 %val) 88 br label %loop 89} 90 91define hidden void @test_04(i32 %x, i32 %y) { 92 93; PRE is not allowed even after we remove c2 because now c3 prevents us from it. 94 95; CHECK-LABEL: @test_04 96; CHECK: entry: 97; CHECK-NEXT: %c1 = call i32 @foo(i32 %x) 98; CHECK-NEXT: br label %loop 99; CHECK: loop: 100; CHECK-NEXT: %c3 = call i32 @foo(i32 %y) 101; CHECK-NEXT: %val = load i32, ptr null, align 8 102; CHECK-NEXT: %c5 = call i32 @foo(i32 %val) 103; CHECK-NEXT: br label %loop 104 105entry: 106 %c1 = call i32 @foo(i32 %x) 107 br label %loop 108 109loop: 110 %c2 = call i32 @foo(i32 %x) 111 %c3 = call i32 @foo(i32 %y) 112 %val = load i32, ptr null, align 8 113 %c4 = call i32 @foo(i32 %y) 114 %c5 = call i32 @foo(i32 %val) 115 br label %loop 116} 117 118attributes #0 = { readnone } 119