xref: /llvm-project/llvm/test/CodeGen/M68k/Arith/umul-with-overflow.ll (revision c4c9d4f306732c854fa88d2f30c1a22bb025d0c9)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=m68k -verify-machineinstrs | FileCheck %s
3
4define zeroext i8 @umul_i8(i8 signext %a, i8 signext %b) nounwind ssp {
5; CHECK-LABEL: umul_i8:
6; CHECK:       ; %bb.0: ; %entry
7; CHECK-NEXT:    move.b (11,%sp), %d0
8; CHECK-NEXT:    and.l #255, %d0
9; CHECK-NEXT:    move.b (7,%sp), %d1
10; CHECK-NEXT:    and.l #255, %d1
11; CHECK-NEXT:    muls %d0, %d1
12; CHECK-NEXT:    move.l %d1, %d0
13; CHECK-NEXT:    and.l #65535, %d0
14; CHECK-NEXT:    and.l #255, %d0
15; CHECK-NEXT:    rts
16entry:
17  %umul = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %a, i8 %b)
18  %cmp = extractvalue { i8, i1 } %umul, 1
19  %umul.result = extractvalue { i8, i1 } %umul, 0
20  %X = select i1 %cmp, i8 42, i8 %umul.result
21  ret i8 %X
22}
23
24define zeroext i8 @umul_i8_no_ovf(i8 signext %a, i8 signext %b) nounwind ssp {
25; CHECK-LABEL: umul_i8_no_ovf:
26; CHECK:       ; %bb.0: ; %entry
27; CHECK-NEXT:    moveq #42, %d0
28; CHECK-NEXT:    rts
29entry:
30  %umul = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %a, i8 %b)
31  %cmp = extractvalue { i8, i1 } %umul, 1
32  %umul.result = extractvalue { i8, i1 } %umul, 0
33  %X = select i1 %cmp, i8 %umul.result, i8 42
34  ret i8 %X
35}
36
37declare { i8, i1 } @llvm.umul.with.overflow.i8(i8, i8) nounwind readnone
38
39define zeroext i16 @umul_i16(i16 signext %a, i16 signext %b) nounwind ssp {
40; CHECK-LABEL: umul_i16:
41; CHECK:       ; %bb.0: ; %entry
42; CHECK-NEXT:    move.w (6,%sp), %d0
43; CHECK-NEXT:    move.w (10,%sp), %d1
44; CHECK-NEXT:    muls %d1, %d0
45; CHECK-NEXT:    and.l #65535, %d0
46; CHECK-NEXT:    rts
47entry:
48  %umul = tail call { i16, i1 } @llvm.umul.with.overflow.i16(i16 %a, i16 %b)
49  %cmp = extractvalue { i16, i1 } %umul, 1
50  %umul.result = extractvalue { i16, i1 } %umul, 0
51  %X = select i1 %cmp, i16 42, i16 %umul.result
52  ret i16 %X
53}
54
55declare { i16, i1 } @llvm.umul.with.overflow.i16(i16, i16) nounwind readnone
56
57declare {i32, i1} @llvm.umul.with.overflow.i32(i32 %a, i32 %b)
58
59define i1 @a(i32 %x)  nounwind {
60; CHECK-LABEL: a:
61; CHECK:       ; %bb.0:
62; CHECK-NEXT:    moveq #3, %d0
63; CHECK-NEXT:    move.l (4,%sp), %d1
64; CHECK-NEXT:    mulu.l %d0, %d1
65; CHECK-NEXT:    svs %d0
66; CHECK-NEXT:    rts
67  %res = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %x, i32 3)
68  %obil = extractvalue {i32, i1} %res, 1
69  ret i1 %obil
70}
71
72define i32 @test2(i32 %a, i32 %b) nounwind readnone {
73; CHECK-LABEL: test2:
74; CHECK:       ; %bb.0: ; %entry
75; CHECK-NEXT:    move.l (8,%sp), %d0
76; CHECK-NEXT:    add.l (4,%sp), %d0
77; CHECK-NEXT:    add.l %d0, %d0
78; CHECK-NEXT:    rts
79entry:
80	%tmp0 = add i32 %b, %a
81	%tmp1 = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %tmp0, i32 2)
82	%tmp2 = extractvalue { i32, i1 } %tmp1, 0
83	ret i32 %tmp2
84}
85
86; It shouldn't fallback to builtin in this scenario
87; Since we don't need the overflow bit here
88define i32 @test3(i32 %a, i32 %b) nounwind readnone {
89; CHECK-LABEL: test3:
90; CHECK:       ; %bb.0: ; %entry
91; CHECK-NEXT:    move.l (8,%sp), %d0
92; CHECK-NEXT:    add.l (4,%sp), %d0
93; CHECK-NEXT:    moveq #4, %d1
94; CHECK-NEXT:    mulu.l %d1, %d0
95; CHECK-NEXT:    rts
96entry:
97	%tmp0 = add i32 %b, %a
98	%tmp1 = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %tmp0, i32 4)
99	%tmp2 = extractvalue { i32, i1 } %tmp1, 0
100	ret i32 %tmp2
101}
102