xref: /llvm-project/llvm/test/Transforms/GVN/PRE/pre-load-implicit-cf-updates.ll (revision 23abf931386002fb9d2c11d026846475c224c641)
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