1; RUN: opt -S -codegenprepare %s -o - | FileCheck %s
2; This file tests the different cases what are involved when codegen prepare
3; tries to get sign/zero extension out of the way of addressing mode.
4; This tests require an actual target as addressing mode decisions depends
5; on the target.
6
7target datalayout = "e-i64:64-f80:128-s:64-n8:16:32:64-S128"
8target triple = "x86_64-apple-macosx"
9
10
11; Check that we correctly promote both operands of the promotable add.
12; CHECK-LABEL: @twoArgsPromotion
13; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i32 %arg1 to i64
14; CHECK: [[ARG2SEXT:%[a-zA-Z_0-9-]+]] = sext i32 %arg2 to i64
15; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], [[ARG2SEXT]]
16; CHECK: inttoptr i64 [[PROMOTED]] to i8*
17; CHECK: ret
18define i8 @twoArgsPromotion(i32 %arg1, i32 %arg2) {
19  %add = add nsw i32 %arg1, %arg2
20  %sextadd = sext i32 %add to i64
21  %base = inttoptr i64 %sextadd to i8*
22  %res = load i8, i8* %base
23  ret i8 %res
24}
25
26; Check that we do not promote both operands of the promotable add when
27; the instruction will not be folded into the addressing mode.
28; Otherwise, we will increase the number of instruction executed.
29; (This is a heuristic of course, because the new sext could have been
30; merged with something else.)
31; CHECK-LABEL: @twoArgsNoPromotion
32; CHECK: add nsw i32 %arg1, %arg2
33; CHECK: ret
34define i8 @twoArgsNoPromotion(i32 %arg1, i32 %arg2, i8* %base) {
35  %add = add nsw i32 %arg1, %arg2
36  %sextadd = sext i32 %add to i64
37  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
38  %res = load i8, i8* %arrayidx
39  ret i8 %res
40}
41
42; Check that we do not promote when the related instruction does not have
43; the nsw flag.
44; CHECK-LABEL: @noPromotion
45; CHECK-NOT: add i64
46; CHECK: ret
47define i8 @noPromotion(i32 %arg1, i32 %arg2, i8* %base) {
48  %add = add i32 %arg1, %arg2
49  %sextadd = sext i32 %add to i64
50  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
51  %res = load i8, i8* %arrayidx
52  ret i8 %res
53}
54
55; Check that we correctly promote constant arguments.
56; CHECK-LABEL: @oneArgPromotion
57; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i32 %arg1 to i64
58; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1
59; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
60; CHECK: ret
61define i8 @oneArgPromotion(i32 %arg1, i8* %base) {
62  %add = add nsw i32 %arg1, 1
63  %sextadd = sext i32 %add to i64
64  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
65  %res = load i8, i8* %arrayidx
66  ret i8 %res
67}
68
69; Check that we are able to merge a sign extension with a zero extension.
70; CHECK-LABEL: @oneArgPromotionZExt
71; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 %arg1 to i64
72; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1ZEXT]], 1
73; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
74; CHECK: ret
75define i8 @oneArgPromotionZExt(i8 %arg1, i8* %base) {
76  %zext = zext i8 %arg1 to i32
77  %add = add nsw i32 %zext, 1
78  %sextadd = sext i32 %add to i64
79  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
80  %res = load i8, i8* %arrayidx
81  ret i8 %res
82}
83
84; When promoting a constant zext, the IR builder returns a constant,
85; not an instruction. Make sure this is properly handled. This used
86; to crash.
87; Note: The constant zext is promoted, but does not help matching
88; more thing in the addressing mode. Therefore the modification is
89; rolled back.
90; Still, this test case exercises the desired code path.
91; CHECK-LABEL: @oneArgPromotionCstZExt
92; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 0, 1
93; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
94; CHECK: ret
95define i8 @oneArgPromotionCstZExt(i8* %base) {
96  %cst = zext i16 undef to i32
97  %add = add nsw i32 %cst, 1
98  %sextadd = sext i32 %add to i64
99  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
100  %res = load i8, i8* %arrayidx
101  ret i8 %res
102}
103
104; Check that we do not promote truncate when we cannot determine the
105; bits that are dropped.
106; CHECK-LABEL: @oneArgPromotionBlockTrunc1
107; CHECK: [[ARG1TRUNC:%[a-zA-Z_0-9-]+]] = trunc i32 %arg1 to i8
108; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i8 [[ARG1TRUNC]] to i64
109; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1
110; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
111; CHECK: ret
112define i8 @oneArgPromotionBlockTrunc1(i32 %arg1, i8* %base) {
113  %trunc = trunc i32 %arg1 to i8
114  %add = add nsw i8 %trunc, 1
115  %sextadd = sext i8 %add to i64
116  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
117  %res = load i8, i8* %arrayidx
118  ret i8 %res
119}
120
121; Check that we do not promote truncate when we cannot determine all the
122; bits that are dropped.
123; CHECK-LABEL: @oneArgPromotionBlockTrunc2
124; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i16 %arg1 to i32
125; CHECK: [[ARG1TRUNC:%[a-zA-Z_0-9-]+]] = trunc i32 [[ARG1SEXT]] to i8
126; CHECK: [[ARG1SEXT64:%[a-zA-Z_0-9-]+]] = sext i8 [[ARG1TRUNC]] to i64
127; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT64]], 1
128; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
129; CHECK: ret
130define i8 @oneArgPromotionBlockTrunc2(i16 %arg1, i8* %base) {
131  %sextarg1 = sext i16 %arg1 to i32
132  %trunc = trunc i32 %sextarg1 to i8
133  %add = add nsw i8 %trunc, 1
134  %sextadd = sext i8 %add to i64
135  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
136  %res = load i8, i8* %arrayidx
137  ret i8 %res
138}
139
140; Check that we are able to promote truncate when we know all the bits
141; that are dropped.
142; CHECK-LABEL: @oneArgPromotionPassTruncKeepSExt
143; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i1 %arg1 to i64
144; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1
145; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
146; CHECK: ret
147define i8 @oneArgPromotionPassTruncKeepSExt(i1 %arg1, i8* %base) {
148  %sextarg1 = sext i1 %arg1 to i32
149  %trunc = trunc i32 %sextarg1 to i8
150  %add = add nsw i8 %trunc, 1
151  %sextadd = sext i8 %add to i64
152  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
153  %res = load i8, i8* %arrayidx
154  ret i8 %res
155}
156
157; On X86 truncate are free. Check that we are able to promote the add
158; to be used as addressing mode and that we insert a truncate for the other
159; use.
160; CHECK-LABEL: @oneArgPromotionTruncInsert
161; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i8 %arg1 to i64
162; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1
163; CHECK: [[TRUNC:%[a-zA-Z_0-9-]+]] = trunc i64 [[PROMOTED]] to i8
164; CHECK: [[GEP:%[a-zA-Z_0-9-]+]] = getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
165; CHECK: [[LOAD:%[a-zA-Z_0-9-]+]] = load i8, i8* [[GEP]]
166; CHECK: add i8 [[LOAD]], [[TRUNC]]
167; CHECK: ret
168define i8 @oneArgPromotionTruncInsert(i8 %arg1, i8* %base) {
169  %add = add nsw i8 %arg1, 1
170  %sextadd = sext i8 %add to i64
171  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
172  %res = load i8, i8* %arrayidx
173  %finalres = add i8 %res, %add
174  ret i8 %finalres
175}
176
177; Cannot sext from a larger type than the promoted type.
178; CHECK-LABEL: @oneArgPromotionLargerType
179; CHECK: [[ARG1TRUNC:%[a-zA-Z_0-9-]+]] = trunc i128 %arg1 to i8
180; CHECK: [[ARG1SEXT64:%[a-zA-Z_0-9-]+]] = sext i8 [[ARG1TRUNC]] to i64
181; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT64]], 1
182; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
183; CHECK: ret
184define i8 @oneArgPromotionLargerType(i128 %arg1, i8* %base) {
185  %trunc = trunc i128 %arg1 to i8
186  %add = add nsw i8 %trunc, 1
187  %sextadd = sext i8 %add to i64
188  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
189  %res = load i8, i8* %arrayidx
190  %finalres = add i8 %res, %add
191  ret i8 %finalres
192}
193
194; Use same inserted trunc
195; On X86 truncate are free. Check that we are able to promote the add
196; to be used as addressing mode and that we insert a truncate for
197; *all* the other uses.
198; CHECK-LABEL: @oneArgPromotionTruncInsertSeveralUse
199; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i8 %arg1 to i64
200; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1
201; CHECK: [[TRUNC:%[a-zA-Z_0-9-]+]] = trunc i64 [[PROMOTED]] to i8
202; CHECK: [[GEP:%[a-zA-Z_0-9-]+]] = getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
203; CHECK: [[LOAD:%[a-zA-Z_0-9-]+]] = load i8, i8* [[GEP]]
204; CHECK: [[ADDRES:%[a-zA-Z_0-9-]+]] = add i8 [[LOAD]], [[TRUNC]]
205; CHECK: add i8 [[ADDRES]], [[TRUNC]]
206; CHECK: ret
207define i8 @oneArgPromotionTruncInsertSeveralUse(i8 %arg1, i8* %base) {
208  %add = add nsw i8 %arg1, 1
209  %sextadd = sext i8 %add to i64
210  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
211  %res = load i8, i8* %arrayidx
212  %almostfinalres = add i8 %res, %add
213  %finalres = add i8 %almostfinalres, %add
214  ret i8 %finalres
215}
216
217; Check that the promoted instruction is used for all uses of the original
218; sign extension.
219; CHECK-LABEL: @oneArgPromotionSExtSeveralUse
220; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i8 %arg1 to i64
221; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1
222; CHECK: [[GEP:%[a-zA-Z_0-9-]+]] = getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
223; CHECK: [[LOAD:%[a-zA-Z_0-9-]+]] = load i8, i8* [[GEP]]
224; CHECK: [[ADDRES:%[a-zA-Z_0-9-]+]] = zext i8 [[LOAD]] to i64
225; CHECK: add i64 [[ADDRES]], [[PROMOTED]]
226; CHECK: ret
227define i64 @oneArgPromotionSExtSeveralUse(i8 %arg1, i8* %base) {
228  %add = add nsw i8 %arg1, 1
229  %sextadd = sext i8 %add to i64
230  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
231  %res = load i8, i8* %arrayidx
232  %almostfinalres = zext i8 %res to i64
233  %finalres = add i64 %almostfinalres, %sextadd
234  ret i64 %finalres
235}
236
237; Check all types of rollback mechanism.
238; For this test, the sign extension stays in place.
239; However, the matching process goes until promoting both the operands
240; of the first promotable add implies.
241; At this point the rollback mechanism kicks in and restores the states
242; until the addressing mode matcher is able to match something: in that
243; case promote nothing.
244; Along the way, the promotion mechanism involves:
245; - Mutating the type of %promotableadd1 and %promotableadd2.
246; - Creating a sext for %arg1 and %arg2.
247; - Creating a trunc for a use of %promotableadd1.
248; - Replacing a bunch of uses.
249; - Setting the operands of the promoted instruction with the promoted values.
250; - Moving instruction around (mainly sext when promoting instruction).
251; Each type of those promotions has to be undo at least once during this
252; specific test.
253; CHECK-LABEL: @twoArgsPromotionNest
254; CHECK: [[ORIG:%[a-zA-Z_0-9-]+]] = add nsw i32 %arg1, %arg2
255; CHECK: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i32 [[ORIG]], [[ORIG]]
256; CHECK: [[SEXT:%[a-zA-Z_0-9-]+]] = sext i32 [[ADD]] to i64
257; CHECK: getelementptr inbounds i8, i8* %base, i64 [[SEXT]]
258; CHECK: ret
259define i8 @twoArgsPromotionNest(i32 %arg1, i32 %arg2, i8* %base) {
260  %promotableadd1 = add nsw i32 %arg1, %arg2
261  %promotableadd2 = add nsw i32 %promotableadd1, %promotableadd1
262  %sextadd = sext i32 %promotableadd2 to i64
263  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
264  %res = load i8, i8* %arrayidx
265  ret i8 %res
266}
267
268; Test the InstructionRemover undo, which was the only one not
269; kicked in the previous test.
270; The matcher first promotes the add, removes the trunc and promotes
271; the sext of arg1.
272; Then, the matcher cannot use an addressing mode r + r + r, thus it
273; rolls back.
274; CHECK-LABEL: @twoArgsNoPromotionRemove
275; CHECK: [[SEXTARG1:%[a-zA-Z_0-9-]+]] = sext i1 %arg1 to i32
276; CHECK: [[TRUNC:%[a-zA-Z_0-9-]+]] = trunc i32 [[SEXTARG1]] to i8
277; CHECK: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i8 [[TRUNC]], %arg2
278; CHECK: [[SEXT:%[a-zA-Z_0-9-]+]] = sext i8 [[ADD]] to i64
279; CHECK: getelementptr inbounds i8, i8* %base, i64 [[SEXT]]
280; CHECK: ret
281define i8 @twoArgsNoPromotionRemove(i1 %arg1, i8 %arg2, i8* %base) {
282  %sextarg1 = sext i1 %arg1 to i32
283  %trunc = trunc i32 %sextarg1 to i8
284  %add = add nsw i8 %trunc, %arg2
285  %sextadd = sext i8 %add to i64
286  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
287  %res = load i8, i8* %arrayidx
288  ret i8 %res
289}
290
291; Ensure that when the profitability checks kicks in, the IR is not modified
292; will IgnoreProfitability is on.
293; The profitabily check happens when a candidate instruction has several uses.
294; The matcher will create a new matcher for each use and check if the
295; instruction is in the list of the matched instructions of this new matcher.
296; All changes made by the new matchers must be dropped before pursuing
297; otherwise the state of the original matcher will be wrong.
298;
299; Without the profitability check, when checking for the second use of
300; arrayidx, the matcher promotes everything all the way to %arg1, %arg2.
301; Check that we did not promote anything in the final matching.
302;
303; <rdar://problem/16020230>
304; CHECK-LABEL: @checkProfitability
305; CHECK-NOT: {{%[a-zA-Z_0-9-]+}} = sext i32 %arg1 to i64
306; CHECK-NOT: {{%[a-zA-Z_0-9-]+}} = sext i32 %arg2 to i64
307; CHECK: [[SHL:%[a-zA-Z_0-9-]+]] = shl nsw i32 %arg1, 1
308; CHECK: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i32 [[SHL]], %arg2
309; CHECK: [[SEXTADD:%[a-zA-Z_0-9-]+]] = sext i32 [[ADD]] to i64
310; BB then
311; CHECK: [[BASE1:%[a-zA-Z_0-9-]+]] = inttoptr i64 [[SEXTADD]] to i32*
312; CHECK: [[BCC1:%[a-zA-Z_0-9-]+]] = bitcast i32* [[BASE1]] to i8*
313; CHECK: [[FULL1:%[a-zA-Z_0-9-]+]] = getelementptr i8, i8* [[BCC1]], i64 48
314; CHECK: [[ADDR1:%[a-zA-Z_0-9-]+]] = bitcast i8* [[FULL1]] to i32*
315; CHECK: load i32, i32* [[ADDR1]]
316; BB else
317; CHECK: [[BASE2:%[a-zA-Z_0-9-]+]] = inttoptr i64 [[SEXTADD]] to i32*
318; CHECK: [[BCC2:%[a-zA-Z_0-9-]+]] = bitcast i32* [[BASE2]] to i8*
319; CHECK: [[FULL2:%[a-zA-Z_0-9-]+]] = getelementptr i8, i8* [[BCC2]], i64 48
320; CHECK: [[ADDR2:%[a-zA-Z_0-9-]+]] = bitcast i8* [[FULL2]] to i32*
321; CHECK: load i32, i32* [[ADDR2]]
322; CHECK: ret
323define i32 @checkProfitability(i32 %arg1, i32 %arg2, i1 %test) {
324  %shl = shl nsw i32 %arg1, 1
325  %add1 = add nsw i32 %shl, %arg2
326  %sextidx1 = sext i32 %add1 to i64
327  %tmpptr = inttoptr i64 %sextidx1 to i32*
328  %arrayidx1 = getelementptr i32, i32* %tmpptr, i64 12
329  br i1 %test, label %then, label %else
330then:
331  %res1 = load i32, i32* %arrayidx1
332  br label %end
333else:
334  %res2 = load i32, i32* %arrayidx1
335  br label %end
336end:
337  %tmp = phi i32 [%res1, %then], [%res2, %else]
338  %res = add i32 %tmp, %add1
339  %addr = inttoptr i32 %res to i32*
340  %final = load i32, i32* %addr
341  ret i32 %final
342}
343
344%struct.dns_packet = type { i32, i32, %union.anon }
345%union.anon = type { i32 }
346
347@a = common global i32 0, align 4
348@b = common global i16 0, align 2
349
350; We used to crash on this function because we did not return the right
351; promoted instruction for %conv.i.
352; Make sure we generate the right code now.
353; CHECK-LABEL: @fn3
354; %conv.i is used twice and only one of its use is being promoted.
355; Use it at the starting point for the matching.
356; CHECK: %conv.i = zext i16 [[PLAIN_OPND:%[.a-zA-Z_0-9-]+]] to i32
357; CHECK-NEXT: [[PROMOTED_CONV:%[.a-zA-Z_0-9-]+]] = zext i16 [[PLAIN_OPND]] to i64
358; CHECK-NEXT: [[BASE:%[a-zA-Z_0-9-]+]] = bitcast %struct.dns_packet* %P to i8*
359; CHECK-NEXT: [[ADD:%[a-zA-Z_0-9-]+]] = getelementptr i8, i8* [[BASE]], i64 [[PROMOTED_CONV]]
360; CHECK-NEXT: [[ADDR:%[a-zA-Z_0-9-]+]] = getelementptr i8, i8* [[ADD]], i64 7
361; CHECK-NEXT: load i8, i8* [[ADDR]], align 1
362define signext i16 @fn3(%struct.dns_packet* nocapture readonly %P) {
363entry:
364  %tmp = getelementptr inbounds %struct.dns_packet, %struct.dns_packet* %P, i64 0, i32 2
365  %data.i.i = bitcast %union.anon* %tmp to [0 x i8]*
366  br label %while.body.i.i
367
368while.body.i.i:                                   ; preds = %while.body.i.i, %entry
369  %src.addr.0.i.i = phi i16 [ 0, %entry ], [ %inc.i.i, %while.body.i.i ]
370  %inc.i.i = add i16 %src.addr.0.i.i, 1
371  %idxprom.i.i = sext i16 %src.addr.0.i.i to i64
372  %arrayidx.i.i = getelementptr inbounds [0 x i8], [0 x i8]* %data.i.i, i64 0, i64 %idxprom.i.i
373  %tmp1 = load i8, i8* %arrayidx.i.i, align 1
374  %conv2.i.i = zext i8 %tmp1 to i32
375  %and.i.i = and i32 %conv2.i.i, 15
376  store i32 %and.i.i, i32* @a, align 4
377  %tobool.i.i = icmp eq i32 %and.i.i, 0
378  br i1 %tobool.i.i, label %while.body.i.i, label %fn1.exit.i
379
380fn1.exit.i:                                       ; preds = %while.body.i.i
381  %inc.i.i.lcssa = phi i16 [ %inc.i.i, %while.body.i.i ]
382  %conv.i = zext i16 %inc.i.i.lcssa to i32
383  %sub.i = add nsw i32 %conv.i, -1
384  %idxprom.i = sext i32 %sub.i to i64
385  %arrayidx.i = getelementptr inbounds [0 x i8], [0 x i8]* %data.i.i, i64 0, i64 %idxprom.i
386  %tmp2 = load i8, i8* %arrayidx.i, align 1
387  %conv2.i = sext i8 %tmp2 to i16
388  store i16 %conv2.i, i16* @b, align 2
389  %sub4.i = sub nsw i32 0, %conv.i
390  %conv5.i = zext i16 %conv2.i to i32
391  %cmp.i = icmp sgt i32 %conv5.i, %sub4.i
392  br i1 %cmp.i, label %if.then.i, label %fn2.exit
393
394if.then.i:                                        ; preds = %fn1.exit.i
395  %end.i = getelementptr inbounds %struct.dns_packet, %struct.dns_packet* %P, i64 0, i32 1
396  %tmp3 = load i32, i32* %end.i, align 4
397  %sub7.i = add i32 %tmp3, 65535
398  %conv8.i = trunc i32 %sub7.i to i16
399  br label %fn2.exit
400
401fn2.exit:                                         ; preds = %if.then.i, %fn1.exit.i
402  %retval.0.i = phi i16 [ %conv8.i, %if.then.i ], [ undef, %fn1.exit.i ]
403  ret i16 %retval.0.i
404}
405
406; Check that we do not promote an extension if the non-wrapping flag does not
407; match the kind of the extension.
408; CHECK-LABEL: @noPromotionFlag
409; CHECK: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i32 %arg1, %arg2
410; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = zext i32 [[ADD]] to i64
411; CHECK: inttoptr i64 [[PROMOTED]] to i8*
412; CHECK: ret
413define i8 @noPromotionFlag(i32 %arg1, i32 %arg2) {
414  %add = add nsw i32 %arg1, %arg2
415  %zextadd = zext i32 %add to i64
416  %base = inttoptr i64 %zextadd to i8*
417  %res = load i8, i8* %base
418  ret i8 %res
419}
420
421; Check that we correctly promote both operands of the promotable add with zext.
422; CHECK-LABEL: @twoArgsPromotionZExt
423; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i32 %arg1 to i64
424; CHECK: [[ARG2ZEXT:%[a-zA-Z_0-9-]+]] = zext i32 %arg2 to i64
425; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], [[ARG2ZEXT]]
426; CHECK: inttoptr i64 [[PROMOTED]] to i8*
427; CHECK: ret
428define i8 @twoArgsPromotionZExt(i32 %arg1, i32 %arg2) {
429  %add = add nuw i32 %arg1, %arg2
430  %zextadd = zext i32 %add to i64
431  %base = inttoptr i64 %zextadd to i8*
432  %res = load i8, i8* %base
433  ret i8 %res
434}
435
436; Check that we correctly promote constant arguments.
437; CHECK-LABEL: @oneArgPromotionNegativeCstZExt
438; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 %arg1 to i64
439; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 255
440; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
441; CHECK: ret
442define i8 @oneArgPromotionNegativeCstZExt(i8 %arg1, i8* %base) {
443  %add = add nuw i8 %arg1, -1
444  %zextadd = zext i8 %add to i64
445  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %zextadd
446  %res = load i8, i8* %arrayidx
447  ret i8 %res
448}
449
450; Check that we are able to merge two zero extensions.
451; CHECK-LABEL: @oneArgPromotionZExtZExt
452; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 %arg1 to i64
453; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 1
454; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
455; CHECK: ret
456define i8 @oneArgPromotionZExtZExt(i8 %arg1, i8* %base) {
457  %zext = zext i8 %arg1 to i32
458  %add = add nuw i32 %zext, 1
459  %zextadd = zext i32 %add to i64
460  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %zextadd
461  %res = load i8, i8* %arrayidx
462  ret i8 %res
463}
464
465; Check that we do not promote truncate when the dropped bits
466; are of a different kind.
467; CHECK-LABEL: @oneArgPromotionBlockTruncZExt
468; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i1 %arg1 to i32
469; CHECK: [[ARG1TRUNC:%[a-zA-Z_0-9-]+]] = trunc i32 [[ARG1SEXT]] to i8
470; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 [[ARG1TRUNC]] to i64
471; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 1
472; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
473; CHECK: ret
474define i8 @oneArgPromotionBlockTruncZExt(i1 %arg1, i8* %base) {
475  %sextarg1 = sext i1 %arg1 to i32
476  %trunc = trunc i32 %sextarg1 to i8
477  %add = add nuw i8 %trunc, 1
478  %zextadd = zext i8 %add to i64
479  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %zextadd
480  %res = load i8, i8* %arrayidx
481  ret i8 %res
482}
483
484; Check that we are able to promote truncate when we know all the bits
485; that are dropped.
486; CHECK-LABEL: @oneArgPromotionPassTruncZExt
487; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i1 %arg1 to i64
488; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 1
489; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
490; CHECK: ret
491define i8 @oneArgPromotionPassTruncZExt(i1 %arg1, i8* %base) {
492  %sextarg1 = zext i1 %arg1 to i32
493  %trunc = trunc i32 %sextarg1 to i8
494  %add = add nuw i8 %trunc, 1
495  %zextadd = zext i8 %add to i64
496  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %zextadd
497  %res = load i8, i8* %arrayidx
498  ret i8 %res
499}
500
501; Check that we do not promote sext with zext.
502; CHECK-LABEL: @oneArgPromotionBlockSExtZExt
503; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i1 %arg1 to i8
504; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 [[ARG1SEXT]] to i64
505; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 1
506; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
507; CHECK: ret
508define i8 @oneArgPromotionBlockSExtZExt(i1 %arg1, i8* %base) {
509  %sextarg1 = sext i1 %arg1 to i8
510  %add = add nuw i8 %sextarg1, 1
511  %zextadd = zext i8 %add to i64
512  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %zextadd
513  %res = load i8, i8* %arrayidx
514  ret i8 %res
515}
516