xref: /llvm-project/llvm/test/Transforms/CorrelatedValuePropagation/zext.ll (revision dc6d0773960c664eee12a1ed871fad5c81a20a12)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s
3
4declare void @use64(i64)
5
6define void @test1(i32 %n) {
7; CHECK-LABEL: @test1(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    br label [[FOR_COND:%.*]]
10; CHECK:       for.cond:
11; CHECK-NEXT:    [[A:%.*]] = phi i32 [ [[N:%.*]], [[ENTRY:%.*]] ], [ [[EXT:%.*]], [[FOR_BODY:%.*]] ]
12; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A]], -1
13; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
14; CHECK:       for.body:
15; CHECK-NEXT:    [[EXT_WIDE:%.*]] = zext nneg i32 [[A]] to i64
16; CHECK-NEXT:    call void @use64(i64 [[EXT_WIDE]])
17; CHECK-NEXT:    [[EXT]] = trunc i64 [[EXT_WIDE]] to i32
18; CHECK-NEXT:    br label [[FOR_COND]]
19; CHECK:       for.end:
20; CHECK-NEXT:    ret void
21;
22entry:
23  br label %for.cond
24
25for.cond:                                         ; preds = %for.body, %entry
26  %a = phi i32 [ %n, %entry ], [ %ext, %for.body ]
27  %cmp = icmp sgt i32 %a, -1
28  br i1 %cmp, label %for.body, label %for.end
29
30for.body:                                         ; preds = %for.cond
31  %ext.wide = zext i32 %a to i64
32  call void @use64(i64 %ext.wide)
33  %ext = trunc i64 %ext.wide to i32
34  br label %for.cond
35
36for.end:                                          ; preds = %for.cond
37  ret void
38}
39
40;; Negative test to show transform doesn't happen unless n >= 0.
41define void @test2(i32 %n) {
42; CHECK-LABEL: @test2(
43; CHECK-NEXT:  entry:
44; CHECK-NEXT:    br label [[FOR_COND:%.*]]
45; CHECK:       for.cond:
46; CHECK-NEXT:    [[A:%.*]] = phi i32 [ [[N:%.*]], [[ENTRY:%.*]] ], [ [[EXT:%.*]], [[FOR_BODY:%.*]] ]
47; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A]], -2
48; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
49; CHECK:       for.body:
50; CHECK-NEXT:    [[EXT_WIDE:%.*]] = zext i32 [[A]] to i64
51; CHECK-NEXT:    call void @use64(i64 [[EXT_WIDE]])
52; CHECK-NEXT:    [[EXT]] = trunc i64 [[EXT_WIDE]] to i32
53; CHECK-NEXT:    br label [[FOR_COND]]
54; CHECK:       for.end:
55; CHECK-NEXT:    ret void
56;
57entry:
58  br label %for.cond
59
60for.cond:                                         ; preds = %for.body, %entry
61  %a = phi i32 [ %n, %entry ], [ %ext, %for.body ]
62  %cmp = icmp sgt i32 %a, -2
63  br i1 %cmp, label %for.body, label %for.end
64
65for.body:                                         ; preds = %for.cond
66  %ext.wide = zext i32 %a to i64
67  call void @use64(i64 %ext.wide)
68  %ext = trunc i64 %ext.wide to i32
69  br label %for.cond
70
71for.end:                                          ; preds = %for.cond
72  ret void
73}
74
75;; Non looping test case.
76define void @test3(i32 %n) {
77; CHECK-LABEL: @test3(
78; CHECK-NEXT:  entry:
79; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], -1
80; CHECK-NEXT:    br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
81; CHECK:       bb:
82; CHECK-NEXT:    [[EXT_WIDE:%.*]] = zext nneg i32 [[N]] to i64
83; CHECK-NEXT:    call void @use64(i64 [[EXT_WIDE]])
84; CHECK-NEXT:    [[EXT:%.*]] = trunc i64 [[EXT_WIDE]] to i32
85; CHECK-NEXT:    br label [[EXIT]]
86; CHECK:       exit:
87; CHECK-NEXT:    ret void
88;
89entry:
90  %cmp = icmp sgt i32 %n, -1
91  br i1 %cmp, label %bb, label %exit
92
93bb:
94  %ext.wide = zext i32 %n to i64
95  call void @use64(i64 %ext.wide)
96  %ext = trunc i64 %ext.wide to i32
97  br label %exit
98
99exit:
100  ret void
101}
102
103;; Non looping negative test case.
104define void @test4(i32 %n) {
105; CHECK-LABEL: @test4(
106; CHECK-NEXT:  entry:
107; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], -2
108; CHECK-NEXT:    br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
109; CHECK:       bb:
110; CHECK-NEXT:    [[EXT_WIDE:%.*]] = zext i32 [[N]] to i64
111; CHECK-NEXT:    call void @use64(i64 [[EXT_WIDE]])
112; CHECK-NEXT:    [[EXT:%.*]] = trunc i64 [[EXT_WIDE]] to i32
113; CHECK-NEXT:    br label [[EXIT]]
114; CHECK:       exit:
115; CHECK-NEXT:    ret void
116;
117entry:
118  %cmp = icmp sgt i32 %n, -2
119  br i1 %cmp, label %bb, label %exit
120
121bb:
122  %ext.wide = zext i32 %n to i64
123  call void @use64(i64 %ext.wide)
124  %ext = trunc i64 %ext.wide to i32
125  br label %exit
126
127exit:
128  ret void
129}
130
131define i64 @may_including_undef(i1 %c.1, i1 %c.2) {
132; CHECK-LABEL: @may_including_undef(
133; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[TRUE_1:%.*]], label [[FALSE:%.*]]
134; CHECK:       true.1:
135; CHECK-NEXT:    br i1 [[C_2:%.*]], label [[TRUE_2:%.*]], label [[EXIT:%.*]]
136; CHECK:       true.2:
137; CHECK-NEXT:    br label [[EXIT]]
138; CHECK:       false:
139; CHECK-NEXT:    br label [[EXIT]]
140; CHECK:       exit:
141; CHECK-NEXT:    [[P:%.*]] = phi i32 [ 0, [[TRUE_1]] ], [ 1, [[TRUE_2]] ], [ undef, [[FALSE]] ]
142; CHECK-NEXT:    [[EXT:%.*]] = zext i32 [[P]] to i64
143; CHECK-NEXT:    ret i64 [[EXT]]
144;
145  br i1 %c.1, label %true.1, label %false
146
147true.1:
148  br i1 %c.2, label %true.2, label %exit
149
150true.2:
151  br label %exit
152
153false:
154  br label %exit
155
156exit:
157  %p = phi i32 [ 0, %true.1 ], [ 1, %true.2], [ undef, %false ]
158  %ext = zext i32 %p to i64
159  ret i64 %ext
160}
161
162define i64 @test_infer_at_use(i32 noundef %n) {
163; CHECK-LABEL: @test_infer_at_use(
164; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], -1
165; CHECK-NEXT:    [[EXT:%.*]] = zext nneg i32 [[N]] to i64
166; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], i64 [[EXT]], i64 0
167; CHECK-NEXT:    ret i64 [[SELECT]]
168;
169  %cmp = icmp sgt i32 %n, -1
170  %ext = zext i32 %n to i64
171  %select = select i1 %cmp, i64 %ext, i64 0
172  ret i64 %select
173}
174