• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: opt < %s -S -early-cse | FileCheck %s
2
3
4; CHECK: @test1
5define void @test1(i8 %V, i32 *%P) {
6  %A = bitcast i64 42 to double  ;; dead
7  %B = add i32 4, 19             ;; constant folds
8  store i32 %B, i32* %P
9  ; CHECK-NEXT: store i32 23, i32* %P
10
11  %C = zext i8 %V to i32
12  %D = zext i8 %V to i32  ;; CSE
13  store volatile i32 %C, i32* %P
14  store volatile i32 %D, i32* %P
15  ; CHECK-NEXT: %C = zext i8 %V to i32
16  ; CHECK-NEXT: store volatile i32 %C
17  ; CHECK-NEXT: store volatile i32 %C
18
19  %E = add i32 %C, %C
20  %F = add i32 %C, %C
21  store volatile i32 %E, i32* %P
22  store volatile i32 %F, i32* %P
23  ; CHECK-NEXT: %E = add i32 %C, %C
24  ; CHECK-NEXT: store volatile i32 %E
25  ; CHECK-NEXT: store volatile i32 %E
26
27  %G = add nuw i32 %C, %C         ;; not a CSE with E
28  store volatile i32 %G, i32* %P
29  ; CHECK-NEXT: %G = add nuw i32 %C, %C
30  ; CHECK-NEXT: store volatile i32 %G
31  ret void
32}
33
34
35;; Simple load value numbering.
36; CHECK: @test2
37define i32 @test2(i32 *%P) {
38  %V1 = load i32* %P
39  %V2 = load i32* %P
40  %Diff = sub i32 %V1, %V2
41  ret i32 %Diff
42  ; CHECK: ret i32 0
43}
44
45;; Cross block load value numbering.
46; CHECK: @test3
47define i32 @test3(i32 *%P, i1 %Cond) {
48  %V1 = load i32* %P
49  br i1 %Cond, label %T, label %F
50T:
51  store i32 4, i32* %P
52  ret i32 42
53F:
54  %V2 = load i32* %P
55  %Diff = sub i32 %V1, %V2
56  ret i32 %Diff
57  ; CHECK: F:
58  ; CHECK: ret i32 0
59}
60
61;; Cross block load value numbering stops when stores happen.
62; CHECK: @test4
63define i32 @test4(i32 *%P, i1 %Cond) {
64  %V1 = load i32* %P
65  br i1 %Cond, label %T, label %F
66T:
67  ret i32 42
68F:
69  ; Clobbers V1
70  store i32 42, i32* %P
71
72  %V2 = load i32* %P
73  %Diff = sub i32 %V1, %V2
74  ret i32 %Diff
75  ; CHECK: F:
76  ; CHECK: ret i32 %Diff
77}
78
79declare i32 @func(i32 *%P) readonly
80
81;; Simple call CSE'ing.
82; CHECK: @test5
83define i32 @test5(i32 *%P) {
84  %V1 = call i32 @func(i32* %P)
85  %V2 = call i32 @func(i32* %P)
86  %Diff = sub i32 %V1, %V2
87  ret i32 %Diff
88  ; CHECK: ret i32 0
89}
90
91;; Trivial Store->load forwarding
92; CHECK: @test6
93define i32 @test6(i32 *%P) {
94  store i32 42, i32* %P
95  %V1 = load i32* %P
96  ret i32 %V1
97  ; CHECK: ret i32 42
98}
99
100;; Trivial dead store elimination.
101; CHECK: @test7
102define void @test7(i32 *%P) {
103  store i32 42, i32* %P
104  store i32 45, i32* %P
105  ret void
106  ; CHECK-NEXT: store i32 45
107  ; CHECK-NEXT: ret void
108}
109
110;; Readnone functions aren't invalidated by stores.
111; CHECK: @test8
112define i32 @test8(i32 *%P) {
113  %V1 = call i32 @func(i32* %P) readnone
114  store i32 4, i32* %P
115  %V2 = call i32 @func(i32* %P) readnone
116  %Diff = sub i32 %V1, %V2
117  ret i32 %Diff
118  ; CHECK: ret i32 0
119}
120
121
122