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