xref: /llvm-project/llvm/test/CodeGen/SystemZ/int-cmp-44.ll (revision a1710eb3cd5823c5d14899112ca3086acbdbe9cb)
1; Test that compares are omitted if CC already has the right value
2; (z10 version).
3;
4; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 -no-integrated-as \
5; RUN:   -verify-machineinstrs| FileCheck %s
6
7declare void @foo()
8
9; Addition provides enough for comparisons with zero if we know no
10; signed overflow happens, which is when the "nsw" flag is set.
11; First test the EQ case.
12define i32 @f1(i32 %a, i32 %b, ptr %dest) {
13; CHECK-LABEL: f1:
14; CHECK: afi %r2, 1000000
15; CHECK-NEXT: ber %r14
16; CHECK: br %r14
17entry:
18  %res = add nsw i32 %a, 1000000
19  %cmp = icmp eq i32 %res, 0
20  br i1 %cmp, label %exit, label %store
21
22store:
23  store i32 %b, ptr %dest
24  br label %exit
25
26exit:
27  ret i32 %res
28}
29
30; ...and again with NE.
31define i32 @f2(i32 %a, i32 %b, ptr %dest) {
32; CHECK-LABEL: f2:
33; CHECK: afi %r2, 1000000
34; CHECK-NEXT: blhr %r14
35; CHECK: br %r14
36entry:
37  %res = add nsw i32 %a, 1000000
38  %cmp = icmp ne i32 %res, 0
39  br i1 %cmp, label %exit, label %store
40
41store:
42  store i32 %b, ptr %dest
43  br label %exit
44
45exit:
46  ret i32 %res
47}
48
49; ...and again with SLT.
50define i32 @f3(i32 %a, i32 %b, ptr %dest) {
51; CHECK-LABEL: f3:
52; CHECK: afi %r2, 1000000
53; CHECK-NEXT: blr %r14
54entry:
55  %res = add nsw i32 %a, 1000000
56  %cmp = icmp slt i32 %res, 0
57  br i1 %cmp, label %exit, label %store
58
59store:
60  store i32 %b, ptr %dest
61  br label %exit
62
63exit:
64  ret i32 %res
65}
66
67; ...and again with SLE.
68define i32 @f4(i32 %a, i32 %b, ptr %dest) {
69; CHECK-LABEL: f4:
70; CHECK: afi %r2, 1000000
71; CHECK-NEXT: bler %r14
72entry:
73  %res = add nsw i32 %a, 1000000
74  %cmp = icmp sle i32 %res, 0
75  br i1 %cmp, label %exit, label %store
76
77store:
78  store i32 %b, ptr %dest
79  br label %exit
80
81exit:
82  ret i32 %res
83}
84
85; ...and again with SGT.
86define i32 @f5(i32 %a, i32 %b, ptr %dest) {
87; CHECK-LABEL: f5:
88; CHECK: afi %r2, 1000000
89; CHECK-NEXT: bhr %r14
90entry:
91  %res = add nsw i32 %a, 1000000
92  %cmp = icmp sgt i32 %res, 0
93  br i1 %cmp, label %exit, label %store
94
95store:
96  store i32 %b, ptr %dest
97  br label %exit
98
99exit:
100  ret i32 %res
101}
102
103; ...and again with SGE.
104define i32 @f6(i32 %a, i32 %b, ptr %dest) {
105; CHECK-LABEL: f6:
106; CHECK: afi %r2, 1000000
107; CHECK-NEXT: bher %r14
108entry:
109  %res = add nsw i32 %a, 1000000
110  %cmp = icmp sge i32 %res, 0
111  br i1 %cmp, label %exit, label %store
112
113store:
114  store i32 %b, ptr %dest
115  br label %exit
116
117exit:
118  ret i32 %res
119}
120
121; Subtraction provides in addition also enough for equality comparisons with
122; zero even without "nsw".
123define i32 @f7(i32 %a, i32 %b, ptr %dest) {
124; CHECK-LABEL: f7:
125; CHECK: s %r2, 0(%r4)
126; CHECK-NEXT: bner %r14
127; CHECK: br %r14
128entry:
129  %cur = load i32, ptr %dest
130  %res = sub i32 %a, %cur
131  %cmp = icmp ne i32 %res, 0
132  br i1 %cmp, label %exit, label %store
133
134store:
135  store i32 %b, ptr %dest
136  br label %exit
137
138exit:
139  ret i32 %res
140}
141
142; ...and again with SLT.
143define i32 @f8(i32 %a, i32 %b, ptr %dest) {
144; CHECK-LABEL: f8:
145; CHECK: s %r2, 0(%r4)
146; CHECK-NEXT: blr %r14
147entry:
148  %cur = load i32, ptr %dest
149  %res = sub nsw i32 %a, %cur
150  %cmp = icmp slt i32 %res, 0
151  br i1 %cmp, label %exit, label %store
152
153store:
154  store i32 %b, ptr %dest
155  br label %exit
156
157exit:
158  ret i32 %res
159}
160
161; Logic register-register instructions also provide enough for equality
162; comparisons with zero.
163define i32 @f9(i32 %a, i32 %b, ptr %dest) {
164; CHECK-LABEL: f9:
165; CHECK: nr %r2, %r3
166; CHECK-NEXT: blr %r14
167; CHECK: br %r14
168entry:
169  %res = and i32 %a, %b
170  %cmp = icmp ne i32 %res, 0
171  br i1 %cmp, label %exit, label %store
172
173store:
174  store i32 %b, ptr %dest
175  br label %exit
176
177exit:
178  ret i32 %res
179}
180
181; ...but not for ordered comparisons.
182define i32 @f10(i32 %a, i32 %b, ptr %dest) {
183; CHECK-LABEL: f10:
184; CHECK: nr %r2, %r3
185; CHECK-NEXT: cibl %r2, 0, 0(%r14)
186; CHECK: br %r14
187entry:
188  %res = and i32 %a, %b
189  %cmp = icmp slt i32 %res, 0
190  br i1 %cmp, label %exit, label %store
191
192store:
193  store i32 %b, ptr %dest
194  br label %exit
195
196exit:
197  ret i32 %res
198}
199
200; Logic register-immediate instructions also provide enough for equality
201; comparisons with zero if the immediate covers the whole register.
202define i32 @f11(i32 %a, i32 %b, ptr %dest) {
203; CHECK-LABEL: f11:
204; CHECK: nilf %r2, 100000001
205; CHECK-NEXT: blr %r14
206; CHECK: br %r14
207entry:
208  %res = and i32 %a, 100000001
209  %cmp = icmp ne i32 %res, 0
210  br i1 %cmp, label %exit, label %store
211
212store:
213  store i32 %b, ptr %dest
214  br label %exit
215
216exit:
217  ret i32 %res
218}
219
220; Partial logic register-immediate instructions do not provide simple
221; zero results.
222define i32 @f12(i32 %a, i32 %b, ptr %dest) {
223; CHECK-LABEL: f12:
224; CHECK: nill %r2, 65436
225; CHECK-NEXT: ciblh %r2, 0, 0(%r14)
226; CHECK: br %r14
227entry:
228  %res = and i32 %a, -100
229  %cmp = icmp ne i32 %res, 0
230  br i1 %cmp, label %exit, label %store
231
232store:
233  store i32 %b, ptr %dest
234  br label %exit
235
236exit:
237  ret i32 %res
238}
239
240; SRA provides the same CC result as a comparison with zero.
241define i32 @f13(i32 %a, i32 %b, ptr %dest) {
242; CHECK-LABEL: f13:
243; CHECK: sra %r2, 0(%r3)
244; CHECK-NEXT: ber %r14
245; CHECK: br %r14
246entry:
247  %res = ashr i32 %a, %b
248  %cmp = icmp eq i32 %res, 0
249  br i1 %cmp, label %exit, label %store
250
251store:
252  store i32 %b, ptr %dest
253  br label %exit
254
255exit:
256  ret i32 %res
257}
258
259; ...and again with NE.
260define i32 @f14(i32 %a, i32 %b, ptr %dest) {
261; CHECK-LABEL: f14:
262; CHECK: sra %r2, 0(%r3)
263; CHECK-NEXT: blhr %r14
264; CHECK: br %r14
265entry:
266  %res = ashr i32 %a, %b
267  %cmp = icmp ne i32 %res, 0
268  br i1 %cmp, label %exit, label %store
269
270store:
271  store i32 %b, ptr %dest
272  br label %exit
273
274exit:
275  ret i32 %res
276}
277
278; ...and SLT.
279define i32 @f15(i32 %a, i32 %b, ptr %dest) {
280; CHECK-LABEL: f15:
281; CHECK: sra %r2, 0(%r3)
282; CHECK-NEXT: blr %r14
283; CHECK: br %r14
284entry:
285  %res = ashr i32 %a, %b
286  %cmp = icmp slt i32 %res, 0
287  br i1 %cmp, label %exit, label %store
288
289store:
290  store i32 %b, ptr %dest
291  br label %exit
292
293exit:
294  ret i32 %res
295}
296
297; ...and SLE.
298define i32 @f16(i32 %a, i32 %b, ptr %dest) {
299; CHECK-LABEL: f16:
300; CHECK: sra %r2, 0(%r3)
301; CHECK-NEXT: bler %r14
302; CHECK: br %r14
303entry:
304  %res = ashr i32 %a, %b
305  %cmp = icmp sle i32 %res, 0
306  br i1 %cmp, label %exit, label %store
307
308store:
309  store i32 %b, ptr %dest
310  br label %exit
311
312exit:
313  ret i32 %res
314}
315
316; ...and SGT.
317define i32 @f17(i32 %a, i32 %b, ptr %dest) {
318; CHECK-LABEL: f17:
319; CHECK: sra %r2, 0(%r3)
320; CHECK-NEXT: bhr %r14
321; CHECK: br %r14
322entry:
323  %res = ashr i32 %a, %b
324  %cmp = icmp sgt i32 %res, 0
325  br i1 %cmp, label %exit, label %store
326
327store:
328  store i32 %b, ptr %dest
329  br label %exit
330
331exit:
332  ret i32 %res
333}
334
335; ...and SGE.
336define i32 @f18(i32 %a, i32 %b, ptr %dest) {
337; CHECK-LABEL: f18:
338; CHECK: sra %r2, 0(%r3)
339; CHECK-NEXT: bher %r14
340; CHECK: br %r14
341entry:
342  %res = ashr i32 %a, %b
343  %cmp = icmp sge i32 %res, 0
344  br i1 %cmp, label %exit, label %store
345
346store:
347  store i32 %b, ptr %dest
348  br label %exit
349
350exit:
351  ret i32 %res
352}
353
354; RISBG provides the same result as a comparison against zero.
355; Test the EQ case.
356define i64 @f19(i64 %a, i64 %b, ptr %dest) {
357; CHECK-LABEL: f19:
358; CHECK: risbg %r2, %r3, 0, 190, 0
359; CHECK-NEXT: ber %r14
360; CHECK: br %r14
361entry:
362  %res = and i64 %b, -2
363  %cmp = icmp eq i64 %res, 0
364  br i1 %cmp, label %exit, label %store
365
366store:
367  store i64 %b, ptr %dest
368  br label %exit
369
370exit:
371  ret i64 %res
372}
373
374; ...and the SLT case.
375define i64 @f20(i64 %a, i64 %b, ptr %dest) {
376; CHECK-LABEL: f20:
377; CHECK: risbg %r2, %r3, 0, 190, 0
378; CHECK-NEXT: blr %r14
379; CHECK: br %r14
380entry:
381  %res = and i64 %b, -2
382  %cmp = icmp slt i64 %res, 0
383  br i1 %cmp, label %exit, label %store
384
385store:
386  store i64 %b, ptr %dest
387  br label %exit
388
389exit:
390  ret i64 %res
391}
392
393; Test a case where the register we're testing is set by a non-CC-clobbering
394; instruction.
395define i32 @f21(i32 %a, i32 %b, ptr %dest) {
396; CHECK-LABEL: f21:
397; CHECK: afi %r2, 1000000
398; CHECK-NEXT: #APP
399; CHECK-NEXT: blah %r2
400; CHECK-NEXT: #NO_APP
401; CHECK-NEXT: cibe %r2, 0, 0(%r14)
402; CHECK: br %r14
403entry:
404  %add = add i32 %a, 1000000
405  %res = call i32 asm "blah $0", "=r,0" (i32 %add)
406  %cmp = icmp eq i32 %res, 0
407  br i1 %cmp, label %exit, label %store
408
409store:
410  store i32 %b, ptr %dest
411  br label %exit
412
413exit:
414  ret i32 %res
415}
416
417; ...and again with a CC-clobbering instruction.
418define i32 @f22(i32 %a, i32 %b, ptr %dest) {
419; CHECK-LABEL: f22:
420; CHECK: afi %r2, 1000000
421; CHECK-NEXT: #APP
422; CHECK-NEXT: blah %r2
423; CHECK-NEXT: #NO_APP
424; CHECK-NEXT: cibe %r2, 0, 0(%r14)
425; CHECK: br %r14
426entry:
427  %add = add i32 %a, 1000000
428  %res = call i32 asm "blah $0", "=r,0,~{cc}" (i32 %add)
429  %cmp = icmp eq i32 %res, 0
430  br i1 %cmp, label %exit, label %store
431
432store:
433  store i32 %b, ptr %dest
434  br label %exit
435
436exit:
437  ret i32 %res
438}
439
440; Check that stores do not interfere.
441define i32 @f23(i32 %a, i32 %b, ptr %dest1, ptr %dest2) {
442; CHECK-LABEL: f23:
443; CHECK: afi %r2, 1000000
444; CHECK-NEXT: st %r2, 0(%r4)
445; CHECK-NEXT: blhr %r14
446; CHECK: br %r14
447entry:
448  %res = add nsw i32 %a, 1000000
449  store i32 %res, ptr %dest1
450  %cmp = icmp ne i32 %res, 0
451  br i1 %cmp, label %exit, label %store
452
453store:
454  store i32 %b, ptr %dest2
455  br label %exit
456
457exit:
458  ret i32 %res
459}
460
461; Check that calls do interfere.
462define void @f24(ptr %ptr) {
463; CHECK-LABEL: f24:
464; CHECK: afi [[REG:%r[0-9]+]], 1000000
465; CHECK-NEXT: brasl %r14, foo@PLT
466; CHECK-NEXT: cijlh [[REG]], 0, .L{{.*}}
467; CHECK: br %r14
468entry:
469  %val = load i32, ptr %ptr
470  %xor = xor i32 %val, 1
471  %add = add i32 %xor, 1000000
472  call void @foo()
473  %cmp = icmp eq i32 %add, 0
474  br i1 %cmp, label %store, label %exit, !prof !1
475
476store:
477  store i32 %add, ptr %ptr
478  br label %exit
479
480exit:
481  ret void
482}
483
484; Check that inline asms don't interfere if they don't clobber CC.
485define void @f25(i32 %a, ptr %ptr) {
486; CHECK-LABEL: f25:
487; CHECK: afi %r2, 1000000
488; CHECK-NEXT: #APP
489; CHECK-NEXT: blah
490; CHECK-NEXT: #NO_APP
491; CHECK-NEXT: blhr %r14
492; CHECK: br %r14
493entry:
494  %add = add nsw i32 %a, 1000000
495  call void asm sideeffect "blah", "r"(i32 %add)
496  %cmp = icmp ne i32 %add, 0
497  br i1 %cmp, label %exit, label %store
498
499store:
500  store i32 %add, ptr %ptr
501  br label %exit
502
503exit:
504  ret void
505}
506
507; ...but do interfere if they do clobber CC.
508define void @f26(i32 %a, ptr %ptr) {
509; CHECK-LABEL: f26:
510; CHECK: afi %r2, 1000000
511; CHECK-NEXT: #APP
512; CHECK-NEXT: blah
513; CHECK-NEXT: #NO_APP
514; CHECK-NEXT: ciblh %r2, 0, 0(%r14)
515; CHECK: br %r14
516entry:
517  %add = add i32 %a, 1000000
518  call void asm sideeffect "blah", "r,~{cc}"(i32 %add)
519  %cmp = icmp ne i32 %add, 0
520  br i1 %cmp, label %exit, label %store
521
522store:
523  store i32 %add, ptr %ptr
524  br label %exit
525
526exit:
527  ret void
528}
529
530; Test a case where CC is set based on a different register from the
531; compare input.
532define i32 @f27(i32 %a, i32 %b, ptr %dest1, ptr %dest2) {
533; CHECK-LABEL: f27:
534; CHECK: afi %r2, 1000000
535; CHECK-NEXT: sr %r3, %r2
536; CHECK-NEXT: st %r3, 0(%r4)
537; CHECK-NEXT: cibe %r2, 0, 0(%r14)
538; CHECK: br %r14
539entry:
540  %add = add nsw i32 %a, 1000000
541  %sub = sub i32 %b, %add
542  store i32 %sub, ptr %dest1
543  %cmp = icmp eq i32 %add, 0
544  br i1 %cmp, label %exit, label %store
545
546store:
547  store i32 %sub, ptr %dest2
548  br label %exit
549
550exit:
551  ret i32 %add
552}
553
554; Make sure that we don't confuse a base register for a destination.
555define void @f28(i64 %a, ptr %dest) {
556; CHECK-LABEL: f28:
557; CHECK: xi 0(%r2), 15
558; CHECK: cgibe %r2, 0, 0(%r14)
559; CHECK: br %r14
560entry:
561  %ptr = inttoptr i64 %a to ptr
562  %val = load i8, ptr %ptr
563  %xor = xor i8 %val, 15
564  store i8 %xor, ptr %ptr
565  %cmp = icmp eq i64 %a, 0
566  br i1 %cmp, label %exit, label %store
567
568store:
569  store i64 %a, ptr %dest
570  br label %exit
571
572exit:
573  ret void
574}
575
576; Test that L gets converted to LT where useful.
577define i32 @f29(i64 %base, i64 %index, ptr %dest) {
578; CHECK-LABEL: f29:
579; CHECK: lt %r2, 0({{%r2,%r3|%r3,%r2}})
580; CHECK-NEXT: bler %r14
581; CHECK: br %r14
582entry:
583  %add = add i64 %base, %index
584  %ptr = inttoptr i64 %add to ptr
585  %res = load i32, ptr %ptr
586  %cmp = icmp sle i32 %res, 0
587  br i1 %cmp, label %exit, label %store
588
589store:
590  store i32 %res, ptr %dest
591  br label %exit
592
593exit:
594  ret i32 %res
595}
596
597; Test that LY gets converted to LT where useful.
598define i32 @f30(i64 %base, i64 %index, ptr %dest) {
599; CHECK-LABEL: f30:
600; CHECK: lt %r2, 100000({{%r2,%r3|%r3,%r2}})
601; CHECK-NEXT: bler %r14
602; CHECK: br %r14
603entry:
604  %add1 = add i64 %base, %index
605  %add2 = add i64 %add1, 100000
606  %ptr = inttoptr i64 %add2 to ptr
607  %res = load i32, ptr %ptr
608  %cmp = icmp sle i32 %res, 0
609  br i1 %cmp, label %exit, label %store
610
611store:
612  store i32 %res, ptr %dest
613  br label %exit
614
615exit:
616  ret i32 %res
617}
618
619; Test that LG gets converted to LTG where useful.
620define i64 @f31(i64 %base, i64 %index, ptr %dest) {
621; CHECK-LABEL: f31:
622; CHECK: ltg %r2, 0({{%r2,%r3|%r3,%r2}})
623; CHECK-NEXT: bher %r14
624; CHECK: br %r14
625entry:
626  %add = add i64 %base, %index
627  %ptr = inttoptr i64 %add to ptr
628  %res = load i64, ptr %ptr
629  %cmp = icmp sge i64 %res, 0
630  br i1 %cmp, label %exit, label %store
631
632store:
633  store i64 %res, ptr %dest
634  br label %exit
635
636exit:
637  ret i64 %res
638}
639
640; Test that LGF gets converted to LTGF where useful.
641define i64 @f32(i64 %base, i64 %index, ptr %dest) {
642; CHECK-LABEL: f32:
643; CHECK: ltgf %r2, 0({{%r2,%r3|%r3,%r2}})
644; CHECK-NEXT: bhr %r14
645; CHECK: br %r14
646entry:
647  %add = add i64 %base, %index
648  %ptr = inttoptr i64 %add to ptr
649  %val = load i32, ptr %ptr
650  %res = sext i32 %val to i64
651  %cmp = icmp sgt i64 %res, 0
652  br i1 %cmp, label %exit, label %store
653
654store:
655  store i64 %res, ptr %dest
656  br label %exit
657
658exit:
659  ret i64 %res
660}
661
662; Test that LR gets converted to LTR where useful.
663define i32 @f33(i32 %dummy, i32 %val, ptr %dest) {
664; CHECK-LABEL: f33:
665; CHECK: ltr %r2, %r3
666; CHECK-NEXT: #APP
667; CHECK-NEXT: blah %r2
668; CHECK-NEXT: #NO_APP
669; CHECK-NEXT: blr %r14
670; CHECK: br %r14
671entry:
672  call void asm sideeffect "blah $0", "{r2}"(i32 %val)
673  %cmp = icmp slt i32 %val, 0
674  br i1 %cmp, label %exit, label %store
675
676store:
677  store i32 %val, ptr %dest
678  br label %exit
679
680exit:
681  ret i32 %val
682}
683
684; Test that LGR gets converted to LTGR where useful.
685define i64 @f34(i64 %dummy, i64 %val, ptr %dest) {
686; CHECK-LABEL: f34:
687; CHECK: ltgr %r2, %r3
688; CHECK-NEXT: #APP
689; CHECK-NEXT: blah %r2
690; CHECK-NEXT: #NO_APP
691; CHECK-NEXT: bhr %r14
692; CHECK: br %r14
693entry:
694  call void asm sideeffect "blah $0", "{r2}"(i64 %val)
695  %cmp = icmp sgt i64 %val, 0
696  br i1 %cmp, label %exit, label %store
697
698store:
699  store i64 %val, ptr %dest
700  br label %exit
701
702exit:
703  ret i64 %val
704}
705
706; Test that LGFR gets converted to LTGFR where useful.
707define i64 @f35(i64 %dummy, i32 %val, ptr %dest) {
708; CHECK-LABEL: f35:
709; CHECK: ltgfr %r2, %r3
710; CHECK-NEXT: #APP
711; CHECK-NEXT: blah %r2
712; CHECK-NEXT: #NO_APP
713; CHECK-NEXT: bhr %r14
714; CHECK: br %r14
715entry:
716  %ext = sext i32 %val to i64
717  call void asm sideeffect "blah $0", "{r2}"(i64 %ext)
718  %cmp = icmp sgt i64 %ext, 0
719  br i1 %cmp, label %exit, label %store
720
721store:
722  store i64 %ext, ptr %dest
723  br label %exit
724
725exit:
726  ret i64 %ext
727}
728
729; Test a case where it is the source rather than destination of LR that
730; we need.
731define i32 @f36(i32 %val, i32 %dummy, ptr %dest) {
732; CHECK-LABEL: f36:
733; CHECK: ltr %r3, %r2
734; CHECK-NEXT: #APP
735; CHECK-NEXT: blah %r3
736; CHECK-NEXT: #NO_APP
737; CHECK-NEXT: blr %r14
738; CHECK: br %r14
739entry:
740  call void asm sideeffect "blah $0", "{r3}"(i32 %val)
741  %cmp = icmp slt i32 %val, 0
742  br i1 %cmp, label %exit, label %store
743
744store:
745  store i32 %val, ptr %dest
746  br label %exit
747
748exit:
749  ret i32 %val
750}
751
752; Test a case where it is the source rather than destination of LGR that
753; we need.
754define i64 @f37(i64 %val, i64 %dummy, ptr %dest) {
755; CHECK-LABEL: f37:
756; CHECK: ltgr %r3, %r2
757; CHECK-NEXT: #APP
758; CHECK-NEXT: blah %r3
759; CHECK-NEXT: #NO_APP
760; CHECK-NEXT: blr %r14
761; CHECK: br %r14
762entry:
763  call void asm sideeffect "blah $0", "{r3}"(i64 %val)
764  %cmp = icmp slt i64 %val, 0
765  br i1 %cmp, label %exit, label %store
766
767store:
768  store i64 %val, ptr %dest
769  br label %exit
770
771exit:
772  ret i64 %val
773}
774
775; Test a case where it is the source rather than destination of LGFR that
776; we need.
777define i32 @f38(i32 %val, i64 %dummy, ptr %dest) {
778; CHECK-LABEL: f38:
779; CHECK: ltgfr %r3, %r2
780; CHECK-NEXT: #APP
781; CHECK-NEXT: blah %r3
782; CHECK-NEXT: #NO_APP
783; CHECK-NEXT: blr %r14
784; CHECK: br %r14
785entry:
786  %ext = sext i32 %val to i64
787  call void asm sideeffect "blah $0", "{r3}"(i64 %ext)
788  %cmp = icmp slt i32 %val, 0
789  br i1 %cmp, label %exit, label %store
790
791store:
792  store i32 %val, ptr %dest
793  br label %exit
794
795exit:
796  ret i32 %val
797}
798
799; Test f35 for in-register extensions.
800define i64 @f39(i64 %dummy, i64 %a, ptr %dest) {
801; CHECK-LABEL: f39:
802; CHECK: ltgfr %r2, %r3
803; CHECK-NEXT: #APP
804; CHECK-NEXT: blah %r2
805; CHECK-NEXT: #NO_APP
806; CHECK-NEXT: bhr %r14
807; CHECK: br %r14
808entry:
809  %val = trunc i64 %a to i32
810  %ext = sext i32 %val to i64
811  call void asm sideeffect "blah $0", "{r2}"(i64 %ext)
812  %cmp = icmp sgt i64 %ext, 0
813  br i1 %cmp, label %exit, label %store
814
815store:
816  store i64 %ext, ptr %dest
817  br label %exit
818
819exit:
820  ret i64 %ext
821}
822
823; ...and again with what InstCombine would produce for f40.
824define i64 @f40(i64 %dummy, i64 %a, ptr %dest) {
825; CHECK-LABEL: f40:
826; CHECK: ltgfr %r2, %r3
827; CHECK-NEXT: #APP
828; CHECK-NEXT: blah %r2
829; CHECK-NEXT: #NO_APP
830; CHECK-NEXT: bhr %r14
831; CHECK: br %r14
832entry:
833  %shl = shl i64 %a, 32
834  %ext = ashr i64 %shl, 32
835  call void asm sideeffect "blah $0", "{r2}"(i64 %ext)
836  %cmp = icmp sgt i64 %shl, 0
837  br i1 %cmp, label %exit, label %store
838
839store:
840  store i64 %ext, ptr %dest
841  br label %exit
842
843exit:
844  ret i64 %ext
845}
846
847; Try a form of f7 in which the subtraction operands are compared directly.
848define i32 @f41(i32 %a, i32 %b, ptr %dest) {
849; CHECK-LABEL: f41:
850; CHECK: s %r2, 0(%r4)
851; CHECK-NEXT: bner %r14
852; CHECK: br %r14
853entry:
854  %cur = load i32, ptr %dest
855  %res = sub i32 %a, %cur
856  %cmp = icmp ne i32 %a, %cur
857  br i1 %cmp, label %exit, label %store
858
859store:
860  store i32 %b, ptr %dest
861  br label %exit
862
863exit:
864  ret i32 %res
865}
866
867; A version of f32 that tests the unextended value.
868define i64 @f42(i64 %base, i64 %index, ptr %dest) {
869; CHECK-LABEL: f42:
870; CHECK: ltgf %r2, 0({{%r2,%r3|%r3,%r2}})
871; CHECK-NEXT: bhr %r14
872; CHECK: br %r14
873entry:
874  %add = add i64 %base, %index
875  %ptr = inttoptr i64 %add to ptr
876  %val = load i32, ptr %ptr
877  %res = sext i32 %val to i64
878  %cmp = icmp sgt i32 %val, 0
879  br i1 %cmp, label %exit, label %store
880
881store:
882  store i64 %res, ptr %dest
883  br label %exit
884
885exit:
886  ret i64 %res
887}
888
889!1 = !{!"branch_weights", i32 2, i32 1}
890