1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -basic-aa -newgvn -S | FileCheck %s
3
4;; Most of these are borrowed from transforms/DSE/simple.ll
5;; NewGVN should be able to eliminate any stores of the same value that are actually redundnat.
6
7;; tmp5 is store of the same value to the same location as the load.
8define void @test12({ i32, i32 }* %x) nounwind  {
9; CHECK-LABEL: @test12(
10; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[X:%.*]], i32 0, i32 0
11; CHECK-NEXT:    [[TMP5:%.*]] = load i32, i32* [[TMP4]], align 4
12; CHECK-NEXT:    [[TMP7:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[X]], i32 0, i32 1
13; CHECK-NEXT:    [[TMP8:%.*]] = load i32, i32* [[TMP7]], align 4
14; CHECK-NEXT:    [[TMP17:%.*]] = sub i32 0, [[TMP8]]
15; CHECK-NEXT:    store i32 [[TMP17]], i32* [[TMP7]], align 4
16; CHECK-NEXT:    ret void
17;
18  %tmp4 = getelementptr { i32, i32 }, { i32, i32 }* %x, i32 0, i32 0
19  %tmp5 = load i32, i32* %tmp4, align 4
20  %tmp7 = getelementptr { i32, i32 }, { i32, i32 }* %x, i32 0, i32 1
21  %tmp8 = load i32, i32* %tmp7, align 4
22  %tmp17 = sub i32 0, %tmp8
23  store i32 %tmp5, i32* %tmp4, align 4
24  store i32 %tmp17, i32* %tmp7, align 4
25  ret void
26}
27; Remove redundant store if loaded value is in another block.
28define i32 @test26(i1 %c, i32* %p) {
29; CHECK-LABEL: @test26(
30; CHECK-NEXT:  entry:
31; CHECK-NEXT:    [[V:%.*]] = load i32, i32* [[P:%.*]], align 4
32; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
33; CHECK:       bb1:
34; CHECK-NEXT:    br label [[BB3:%.*]]
35; CHECK:       bb2:
36; CHECK-NEXT:    br label [[BB3]]
37; CHECK:       bb3:
38; CHECK-NEXT:    ret i32 0
39;
40entry:
41  %v = load i32, i32* %p, align 4
42  br i1 %c, label %bb1, label %bb2
43bb1:
44  br label %bb3
45bb2:
46  store i32 %v, i32* %p, align 4
47  br label %bb3
48bb3:
49  ret i32 0
50}
51
52declare void @unknown_func()
53; Remove redundant store, which is in the same loop as the load.
54define i32 @test33(i1 %c, i32* %p, i32 %i) {
55; CHECK-LABEL: @test33(
56; CHECK-NEXT:  entry:
57; CHECK-NEXT:    br label [[BB1:%.*]]
58; CHECK:       bb1:
59; CHECK-NEXT:    [[V:%.*]] = load i32, i32* [[P:%.*]], align 4
60; CHECK-NEXT:    br label [[BB2:%.*]]
61; CHECK:       bb2:
62; CHECK-NEXT:    call void @unknown_func()
63; CHECK-NEXT:    br i1 undef, label [[BB1]], label [[BB3:%.*]]
64; CHECK:       bb3:
65; CHECK-NEXT:    ret i32 0
66;
67entry:
68  br label %bb1
69bb1:
70  %v = load i32, i32* %p, align 4
71  br label %bb2
72bb2:
73  store i32 %v, i32* %p, align 4
74  ; Might read and overwrite value at %p, but doesn't matter.
75  call void @unknown_func()
76  br i1 undef, label %bb1, label %bb3
77bb3:
78  ret i32 0
79}
80