1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=thumbv6m-none-unknown-eabi -mcpu=cortex-m0 | FileCheck %s --check-prefix=ARM 3 4declare i4 @llvm.umul.fix.i4 (i4, i4, i32) 5declare i32 @llvm.umul.fix.i32 (i32, i32, i32) 6declare i64 @llvm.umul.fix.i64 (i64, i64, i32) 7 8define i32 @func(i32 %x, i32 %y) nounwind { 9; ARM-LABEL: func: 10; ARM: @ %bb.0: 11; ARM-NEXT: .save {r7, lr} 12; ARM-NEXT: push {r7, lr} 13; ARM-NEXT: mov r2, r1 14; ARM-NEXT: movs r1, #0 15; ARM-NEXT: mov r3, r1 16; ARM-NEXT: bl __aeabi_lmul 17; ARM-NEXT: lsrs r0, r0, #2 18; ARM-NEXT: lsls r1, r1, #30 19; ARM-NEXT: adds r0, r1, r0 20; ARM-NEXT: pop {r7, pc} 21 %tmp = call i32 @llvm.umul.fix.i32(i32 %x, i32 %y, i32 2) 22 ret i32 %tmp 23} 24 25define i64 @func2(i64 %x, i64 %y) nounwind { 26; ARM-LABEL: func2: 27; ARM: @ %bb.0: 28; ARM-NEXT: .save {r4, r5, r6, r7, lr} 29; ARM-NEXT: push {r4, r5, r6, r7, lr} 30; ARM-NEXT: .pad #20 31; ARM-NEXT: sub sp, #20 32; ARM-NEXT: str r3, [sp, #12] @ 4-byte Spill 33; ARM-NEXT: mov r4, r2 34; ARM-NEXT: mov r6, r1 35; ARM-NEXT: str r1, [sp, #8] @ 4-byte Spill 36; ARM-NEXT: mov r5, r0 37; ARM-NEXT: movs r7, #0 38; ARM-NEXT: mov r1, r7 39; ARM-NEXT: mov r3, r7 40; ARM-NEXT: bl __aeabi_lmul 41; ARM-NEXT: str r0, [sp, #16] @ 4-byte Spill 42; ARM-NEXT: str r1, [sp, #4] @ 4-byte Spill 43; ARM-NEXT: mov r0, r6 44; ARM-NEXT: mov r1, r7 45; ARM-NEXT: mov r2, r4 46; ARM-NEXT: mov r3, r7 47; ARM-NEXT: bl __aeabi_lmul 48; ARM-NEXT: mov r4, r1 49; ARM-NEXT: ldr r1, [sp, #4] @ 4-byte Reload 50; ARM-NEXT: adds r0, r0, r1 51; ARM-NEXT: str r0, [sp, #4] @ 4-byte Spill 52; ARM-NEXT: adcs r4, r7 53; ARM-NEXT: mov r0, r5 54; ARM-NEXT: mov r1, r7 55; ARM-NEXT: ldr r6, [sp, #12] @ 4-byte Reload 56; ARM-NEXT: mov r2, r6 57; ARM-NEXT: mov r3, r7 58; ARM-NEXT: bl __aeabi_lmul 59; ARM-NEXT: mov r5, r1 60; ARM-NEXT: ldr r1, [sp, #4] @ 4-byte Reload 61; ARM-NEXT: adds r0, r0, r1 62; ARM-NEXT: str r0, [sp, #4] @ 4-byte Spill 63; ARM-NEXT: adcs r5, r4 64; ARM-NEXT: ldr r0, [sp, #8] @ 4-byte Reload 65; ARM-NEXT: mov r1, r7 66; ARM-NEXT: mov r2, r6 67; ARM-NEXT: mov r3, r7 68; ARM-NEXT: bl __aeabi_lmul 69; ARM-NEXT: adds r0, r0, r5 70; ARM-NEXT: lsls r0, r0, #30 71; ARM-NEXT: ldr r2, [sp, #4] @ 4-byte Reload 72; ARM-NEXT: lsrs r1, r2, #2 73; ARM-NEXT: adds r1, r0, r1 74; ARM-NEXT: lsls r0, r2, #30 75; ARM-NEXT: ldr r2, [sp, #16] @ 4-byte Reload 76; ARM-NEXT: lsrs r2, r2, #2 77; ARM-NEXT: adds r0, r0, r2 78; ARM-NEXT: add sp, #20 79; ARM-NEXT: pop {r4, r5, r6, r7, pc} 80 %tmp = call i64 @llvm.umul.fix.i64(i64 %x, i64 %y, i32 2) 81 ret i64 %tmp 82} 83 84define i4 @func3(i4 %x, i4 %y) nounwind { 85; ARM-LABEL: func3: 86; ARM: @ %bb.0: 87; ARM-NEXT: .save {r7, lr} 88; ARM-NEXT: push {r7, lr} 89; ARM-NEXT: movs r2, #15 90; ARM-NEXT: ands r0, r2 91; ARM-NEXT: ands r2, r1 92; ARM-NEXT: movs r1, #0 93; ARM-NEXT: mov r3, r1 94; ARM-NEXT: bl __aeabi_lmul 95; ARM-NEXT: lsrs r0, r0, #2 96; ARM-NEXT: lsls r1, r1, #30 97; ARM-NEXT: adds r0, r1, r0 98; ARM-NEXT: pop {r7, pc} 99 %tmp = call i4 @llvm.umul.fix.i4(i4 %x, i4 %y, i32 2) 100 ret i4 %tmp 101} 102 103;; These result in regular integer multiplication 104define i32 @func4(i32 %x, i32 %y) nounwind { 105; ARM-LABEL: func4: 106; ARM: @ %bb.0: 107; ARM-NEXT: muls r0, r1, r0 108; ARM-NEXT: bx lr 109 %tmp = call i32 @llvm.umul.fix.i32(i32 %x, i32 %y, i32 0) 110 ret i32 %tmp 111} 112 113define i64 @func5(i64 %x, i64 %y) nounwind { 114; ARM-LABEL: func5: 115; ARM: @ %bb.0: 116; ARM-NEXT: .save {r7, lr} 117; ARM-NEXT: push {r7, lr} 118; ARM-NEXT: bl __aeabi_lmul 119; ARM-NEXT: pop {r7, pc} 120 %tmp = call i64 @llvm.umul.fix.i64(i64 %x, i64 %y, i32 0) 121 ret i64 %tmp 122} 123 124define i4 @func6(i4 %x, i4 %y) nounwind { 125; ARM-LABEL: func6: 126; ARM: @ %bb.0: 127; ARM-NEXT: movs r2, #15 128; ARM-NEXT: ands r1, r2 129; ARM-NEXT: ands r0, r2 130; ARM-NEXT: muls r0, r1, r0 131; ARM-NEXT: bx lr 132 %tmp = call i4 @llvm.umul.fix.i4(i4 %x, i4 %y, i32 0) 133 ret i4 %tmp 134} 135 136define i64 @func7(i64 %x, i64 %y) nounwind { 137; ARM-LABEL: func7: 138; ARM: @ %bb.0: 139; ARM-NEXT: .save {r4, r5, r6, r7, lr} 140; ARM-NEXT: push {r4, r5, r6, r7, lr} 141; ARM-NEXT: .pad #12 142; ARM-NEXT: sub sp, #12 143; ARM-NEXT: str r3, [sp, #8] @ 4-byte Spill 144; ARM-NEXT: mov r4, r2 145; ARM-NEXT: mov r5, r1 146; ARM-NEXT: str r1, [sp, #4] @ 4-byte Spill 147; ARM-NEXT: mov r7, r0 148; ARM-NEXT: movs r6, #0 149; ARM-NEXT: mov r1, r6 150; ARM-NEXT: mov r3, r6 151; ARM-NEXT: bl __aeabi_lmul 152; ARM-NEXT: str r1, [sp] @ 4-byte Spill 153; ARM-NEXT: mov r0, r5 154; ARM-NEXT: mov r1, r6 155; ARM-NEXT: mov r2, r4 156; ARM-NEXT: mov r3, r6 157; ARM-NEXT: bl __aeabi_lmul 158; ARM-NEXT: mov r4, r1 159; ARM-NEXT: ldr r1, [sp] @ 4-byte Reload 160; ARM-NEXT: adds r0, r0, r1 161; ARM-NEXT: str r0, [sp] @ 4-byte Spill 162; ARM-NEXT: adcs r4, r6 163; ARM-NEXT: mov r0, r7 164; ARM-NEXT: mov r1, r6 165; ARM-NEXT: ldr r7, [sp, #8] @ 4-byte Reload 166; ARM-NEXT: mov r2, r7 167; ARM-NEXT: mov r3, r6 168; ARM-NEXT: bl __aeabi_lmul 169; ARM-NEXT: mov r5, r1 170; ARM-NEXT: ldr r1, [sp] @ 4-byte Reload 171; ARM-NEXT: adds r0, r0, r1 172; ARM-NEXT: str r0, [sp] @ 4-byte Spill 173; ARM-NEXT: adcs r5, r4 174; ARM-NEXT: ldr r0, [sp, #4] @ 4-byte Reload 175; ARM-NEXT: mov r1, r6 176; ARM-NEXT: mov r2, r7 177; ARM-NEXT: mov r3, r6 178; ARM-NEXT: bl __aeabi_lmul 179; ARM-NEXT: adds r1, r0, r5 180; ARM-NEXT: ldr r0, [sp] @ 4-byte Reload 181; ARM-NEXT: add sp, #12 182; ARM-NEXT: pop {r4, r5, r6, r7, pc} 183 %tmp = call i64 @llvm.umul.fix.i64(i64 %x, i64 %y, i32 32) 184 ret i64 %tmp 185} 186 187define i64 @func8(i64 %x, i64 %y) nounwind { 188; ARM-LABEL: func8: 189; ARM: @ %bb.0: 190; ARM-NEXT: .save {r4, r5, r6, r7, lr} 191; ARM-NEXT: push {r4, r5, r6, r7, lr} 192; ARM-NEXT: .pad #12 193; ARM-NEXT: sub sp, #12 194; ARM-NEXT: str r3, [sp, #8] @ 4-byte Spill 195; ARM-NEXT: mov r4, r2 196; ARM-NEXT: mov r5, r1 197; ARM-NEXT: str r1, [sp, #4] @ 4-byte Spill 198; ARM-NEXT: mov r7, r0 199; ARM-NEXT: movs r6, #0 200; ARM-NEXT: mov r1, r6 201; ARM-NEXT: mov r3, r6 202; ARM-NEXT: bl __aeabi_lmul 203; ARM-NEXT: str r1, [sp] @ 4-byte Spill 204; ARM-NEXT: mov r0, r5 205; ARM-NEXT: mov r1, r6 206; ARM-NEXT: mov r2, r4 207; ARM-NEXT: mov r3, r6 208; ARM-NEXT: bl __aeabi_lmul 209; ARM-NEXT: mov r4, r1 210; ARM-NEXT: ldr r1, [sp] @ 4-byte Reload 211; ARM-NEXT: adds r0, r0, r1 212; ARM-NEXT: str r0, [sp] @ 4-byte Spill 213; ARM-NEXT: adcs r4, r6 214; ARM-NEXT: mov r0, r7 215; ARM-NEXT: mov r1, r6 216; ARM-NEXT: ldr r5, [sp, #8] @ 4-byte Reload 217; ARM-NEXT: mov r2, r5 218; ARM-NEXT: mov r3, r6 219; ARM-NEXT: bl __aeabi_lmul 220; ARM-NEXT: ldr r2, [sp] @ 4-byte Reload 221; ARM-NEXT: adds r0, r0, r2 222; ARM-NEXT: str r0, [sp] @ 4-byte Spill 223; ARM-NEXT: adcs r1, r6 224; ARM-NEXT: adds r4, r4, r1 225; ARM-NEXT: mov r7, r6 226; ARM-NEXT: adcs r7, r6 227; ARM-NEXT: ldr r0, [sp, #4] @ 4-byte Reload 228; ARM-NEXT: mov r1, r6 229; ARM-NEXT: mov r2, r5 230; ARM-NEXT: mov r3, r6 231; ARM-NEXT: bl __aeabi_lmul 232; ARM-NEXT: adds r0, r0, r4 233; ARM-NEXT: adcs r1, r7 234; ARM-NEXT: lsls r1, r1, #1 235; ARM-NEXT: lsrs r2, r0, #31 236; ARM-NEXT: adds r1, r1, r2 237; ARM-NEXT: lsls r0, r0, #1 238; ARM-NEXT: ldr r2, [sp] @ 4-byte Reload 239; ARM-NEXT: lsrs r2, r2, #31 240; ARM-NEXT: adds r0, r0, r2 241; ARM-NEXT: add sp, #12 242; ARM-NEXT: pop {r4, r5, r6, r7, pc} 243 %tmp = call i64 @llvm.umul.fix.i64(i64 %x, i64 %y, i32 63) 244 ret i64 %tmp 245} 246 247define i64 @func9(i64 %x, i64 %y) nounwind { 248; ARM-LABEL: func9: 249; ARM: @ %bb.0: 250; ARM-NEXT: .save {r4, r5, r6, r7, lr} 251; ARM-NEXT: push {r4, r5, r6, r7, lr} 252; ARM-NEXT: .pad #12 253; ARM-NEXT: sub sp, #12 254; ARM-NEXT: str r3, [sp, #8] @ 4-byte Spill 255; ARM-NEXT: mov r4, r2 256; ARM-NEXT: mov r5, r1 257; ARM-NEXT: str r1, [sp, #4] @ 4-byte Spill 258; ARM-NEXT: mov r7, r0 259; ARM-NEXT: movs r6, #0 260; ARM-NEXT: mov r1, r6 261; ARM-NEXT: mov r3, r6 262; ARM-NEXT: bl __aeabi_lmul 263; ARM-NEXT: str r1, [sp] @ 4-byte Spill 264; ARM-NEXT: mov r0, r5 265; ARM-NEXT: mov r1, r6 266; ARM-NEXT: mov r2, r4 267; ARM-NEXT: mov r3, r6 268; ARM-NEXT: bl __aeabi_lmul 269; ARM-NEXT: mov r4, r1 270; ARM-NEXT: ldr r1, [sp] @ 4-byte Reload 271; ARM-NEXT: adds r5, r0, r1 272; ARM-NEXT: adcs r4, r6 273; ARM-NEXT: mov r0, r7 274; ARM-NEXT: mov r1, r6 275; ARM-NEXT: ldr r7, [sp, #8] @ 4-byte Reload 276; ARM-NEXT: mov r2, r7 277; ARM-NEXT: mov r3, r6 278; ARM-NEXT: bl __aeabi_lmul 279; ARM-NEXT: adds r0, r0, r5 280; ARM-NEXT: adcs r1, r6 281; ARM-NEXT: adds r4, r4, r1 282; ARM-NEXT: mov r5, r6 283; ARM-NEXT: adcs r5, r6 284; ARM-NEXT: ldr r0, [sp, #4] @ 4-byte Reload 285; ARM-NEXT: mov r1, r6 286; ARM-NEXT: mov r2, r7 287; ARM-NEXT: mov r3, r6 288; ARM-NEXT: bl __aeabi_lmul 289; ARM-NEXT: adds r0, r0, r4 290; ARM-NEXT: adcs r1, r5 291; ARM-NEXT: add sp, #12 292; ARM-NEXT: pop {r4, r5, r6, r7, pc} 293 %tmp = call i64 @llvm.umul.fix.i64(i64 %x, i64 %y, i32 64) 294 ret i64 %tmp 295} 296