blob: 351cb2adedf5bb458d7daacb6075d0476a64bc45 [file] [log] [blame]
Clement Courbet65130e22017-09-01 10:56:34 +00001; RUN: opt -mergeicmps -S -o - %s | FileCheck %s
2
3%"struct.std::pair" = type { i32, i32 }
4
5define zeroext i1 @opeq1(
6 %"struct.std::pair"* nocapture readonly dereferenceable(8) %a,
7 %"struct.std::pair"* nocapture readonly dereferenceable(8) %b) local_unnamed_addr #0 {
8entry:
9 %first.i = getelementptr inbounds %"struct.std::pair", %"struct.std::pair"* %a, i64 0, i32 0
10 %0 = load i32, i32* %first.i, align 4
11 %first1.i = getelementptr inbounds %"struct.std::pair", %"struct.std::pair"* %b, i64 0, i32 0
12 %1 = load i32, i32* %first1.i, align 4
13 %cmp.i = icmp eq i32 %0, %1
14 br i1 %cmp.i, label %land.rhs.i, label %opeq1.exit
15
16land.rhs.i:
17 %second.i = getelementptr inbounds %"struct.std::pair", %"struct.std::pair"* %a, i64 0, i32 1
18 %2 = load i32, i32* %second.i, align 4
19 %second2.i = getelementptr inbounds %"struct.std::pair", %"struct.std::pair"* %b, i64 0, i32 1
20 %3 = load i32, i32* %second2.i, align 4
21 %cmp3.i = icmp eq i32 %2, %3
22 br label %opeq1.exit
23
24opeq1.exit:
25 %4 = phi i1 [ false, %entry ], [ %cmp3.i, %land.rhs.i ]
26 ret i1 %4
27; CHECK-LABEL: @opeq1(
28; The entry block with zero-offset GEPs is kept, loads are removed.
29; CHECK: entry
30; CHECK: getelementptr {{.*}} i32 0
31; CHECK-NOT: load
32; CHECK: getelementptr {{.*}} i32 0
33; CHECK-NOT: load
34; The two 4 byte loads and compares are replaced with a single 8-byte memcmp.
35; CHECK: @memcmp({{.*}}8)
36; CHECK: icmp eq {{.*}} 0
37; The branch is now a direct branch; the other block has been removed.
38; CHECK: br label %opeq1.exit
39; CHECK-NOT: br
40; The phi is updated.
41; CHECK: phi i1 [ %{{[^,]*}}, %entry ]
42; CHECK-NEXT: ret
43}
44
45; Same as above, but the two blocks are in inverse order.
46define zeroext i1 @opeq1_inverse(
47 %"struct.std::pair"* nocapture readonly dereferenceable(8) %a,
48 %"struct.std::pair"* nocapture readonly dereferenceable(8) %b) local_unnamed_addr #0 {
49entry:
50 %first.i = getelementptr inbounds %"struct.std::pair", %"struct.std::pair"* %a, i64 0, i32 1
51 %0 = load i32, i32* %first.i, align 4
52 %first1.i = getelementptr inbounds %"struct.std::pair", %"struct.std::pair"* %b, i64 0, i32 1
53 %1 = load i32, i32* %first1.i, align 4
54 %cmp.i = icmp eq i32 %0, %1
55 br i1 %cmp.i, label %land.rhs.i, label %opeq1.exit
56
57land.rhs.i:
58 %second.i = getelementptr inbounds %"struct.std::pair", %"struct.std::pair"* %a, i64 0, i32 0
59 %2 = load i32, i32* %second.i, align 4
60 %second2.i = getelementptr inbounds %"struct.std::pair", %"struct.std::pair"* %b, i64 0, i32 0
61 %3 = load i32, i32* %second2.i, align 4
62 %cmp3.i = icmp eq i32 %2, %3
63 br label %opeq1.exit
64
65opeq1.exit:
66 %4 = phi i1 [ false, %entry ], [ %cmp3.i, %land.rhs.i ]
67 ret i1 %4
68; CHECK-LABEL: @opeq1_inverse(
69; The second block with zero-offset GEPs is kept, loads are removed.
70; CHECK: land.rhs.i
71; CHECK: getelementptr {{.*}} i32 0
72; CHECK-NOT: load
73; CHECK: getelementptr {{.*}} i32 0
74; CHECK-NOT: load
75; The two 4 byte loads and compares are replaced with a single 8-byte memcmp.
76; CHECK: @memcmp({{.*}}8)
77; CHECK: icmp eq {{.*}} 0
78; The branch is now a direct branch; the other block has been removed.
79; CHECK: br label %opeq1.exit
80; CHECK-NOT: br
81; The phi is updated.
82; CHECK: phi i1 [ %{{[^,]*}}, %land.rhs.i ]
83; CHECK-NEXT: ret
84}
85
86
87