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.smul.fix.i4 (i4, i4, i32) 5declare i32 @llvm.smul.fix.i32 (i32, i32, i32) 6declare i64 @llvm.smul.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: asrs r1, r0, #31 15; ARM-NEXT: asrs r3, r2, #31 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.smul.fix.i32(i32 %x, i32 %y, i32 2) 22 ret i32 %tmp 23} 24 25define i64 @func2(i64 %x, i64 %y) { 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, #16] @ 4-byte Spill 33; ARM-NEXT: mov r7, r2 34; ARM-NEXT: mov r2, r1 35; ARM-NEXT: str r1, [sp, #12] @ 4-byte Spill 36; ARM-NEXT: mov r5, r0 37; ARM-NEXT: asrs r1, r1, #31 38; ARM-NEXT: str r1, [sp, #8] @ 4-byte Spill 39; ARM-NEXT: movs r4, #0 40; ARM-NEXT: mov r0, r2 41; ARM-NEXT: mov r2, r7 42; ARM-NEXT: mov r3, r4 43; ARM-NEXT: bl __aeabi_lmul 44; ARM-NEXT: str r0, [sp] @ 4-byte Spill 45; ARM-NEXT: mov r6, r1 46; ARM-NEXT: mov r0, r5 47; ARM-NEXT: mov r1, r4 48; ARM-NEXT: mov r2, r7 49; ARM-NEXT: mov r3, r4 50; ARM-NEXT: bl __aeabi_lmul 51; ARM-NEXT: str r0, [sp, #4] @ 4-byte Spill 52; ARM-NEXT: ldr r0, [sp] @ 4-byte Reload 53; ARM-NEXT: adds r0, r0, r1 54; ARM-NEXT: str r0, [sp] @ 4-byte Spill 55; ARM-NEXT: adcs r6, r4 56; ARM-NEXT: ldr r2, [sp, #16] @ 4-byte Reload 57; ARM-NEXT: asrs r7, r2, #31 58; ARM-NEXT: mov r0, r5 59; ARM-NEXT: mov r1, r4 60; ARM-NEXT: mov r3, r7 61; ARM-NEXT: bl __aeabi_lmul 62; ARM-NEXT: mov r4, r1 63; ARM-NEXT: ldr r1, [sp] @ 4-byte Reload 64; ARM-NEXT: adds r5, r0, r1 65; ARM-NEXT: adcs r4, r6 66; ARM-NEXT: ldr r0, [sp, #12] @ 4-byte Reload 67; ARM-NEXT: ldr r1, [sp, #8] @ 4-byte Reload 68; ARM-NEXT: ldr r2, [sp, #16] @ 4-byte Reload 69; ARM-NEXT: mov r3, r7 70; ARM-NEXT: bl __aeabi_lmul 71; ARM-NEXT: adds r0, r0, r4 72; ARM-NEXT: lsls r0, r0, #30 73; ARM-NEXT: lsrs r1, r5, #2 74; ARM-NEXT: adds r1, r0, r1 75; ARM-NEXT: lsls r0, r5, #30 76; ARM-NEXT: ldr r2, [sp, #4] @ 4-byte Reload 77; ARM-NEXT: lsrs r2, r2, #2 78; ARM-NEXT: adds r0, r0, r2 79; ARM-NEXT: add sp, #20 80; ARM-NEXT: pop {r4, r5, r6, r7, pc} 81 %tmp = call i64 @llvm.smul.fix.i64(i64 %x, i64 %y, i32 2) 82 ret i64 %tmp 83} 84 85define i4 @func3(i4 %x, i4 %y) nounwind { 86; ARM-LABEL: func3: 87; ARM: @ %bb.0: 88; ARM-NEXT: .save {r4, lr} 89; ARM-NEXT: push {r4, lr} 90; ARM-NEXT: lsls r2, r0, #28 91; ARM-NEXT: asrs r0, r2, #28 92; ARM-NEXT: asrs r4, r2, #31 93; ARM-NEXT: lsls r1, r1, #28 94; ARM-NEXT: asrs r2, r1, #28 95; ARM-NEXT: asrs r3, r1, #31 96; ARM-NEXT: mov r1, r4 97; ARM-NEXT: bl __aeabi_lmul 98; ARM-NEXT: lsrs r0, r0, #2 99; ARM-NEXT: lsls r1, r1, #30 100; ARM-NEXT: adds r0, r1, r0 101; ARM-NEXT: pop {r4, pc} 102 %tmp = call i4 @llvm.smul.fix.i4(i4 %x, i4 %y, i32 2) 103 ret i4 %tmp 104} 105 106;; These result in regular integer multiplication 107define i32 @func4(i32 %x, i32 %y) nounwind { 108; ARM-LABEL: func4: 109; ARM: @ %bb.0: 110; ARM-NEXT: muls r0, r1, r0 111; ARM-NEXT: bx lr 112 %tmp = call i32 @llvm.smul.fix.i32(i32 %x, i32 %y, i32 0) 113 ret i32 %tmp 114} 115 116define i64 @func5(i64 %x, i64 %y) { 117; ARM-LABEL: func5: 118; ARM: @ %bb.0: 119; ARM-NEXT: .save {r7, lr} 120; ARM-NEXT: push {r7, lr} 121; ARM-NEXT: bl __aeabi_lmul 122; ARM-NEXT: pop {r7, pc} 123 %tmp = call i64 @llvm.smul.fix.i64(i64 %x, i64 %y, i32 0) 124 ret i64 %tmp 125} 126 127define i4 @func6(i4 %x, i4 %y) nounwind { 128; ARM-LABEL: func6: 129; ARM: @ %bb.0: 130; ARM-NEXT: lsls r1, r1, #28 131; ARM-NEXT: asrs r1, r1, #28 132; ARM-NEXT: lsls r0, r0, #28 133; ARM-NEXT: asrs r0, r0, #28 134; ARM-NEXT: muls r0, r1, r0 135; ARM-NEXT: bx lr 136 %tmp = call i4 @llvm.smul.fix.i4(i4 %x, i4 %y, i32 0) 137 ret i4 %tmp 138} 139 140define i64 @func7(i64 %x, i64 %y) nounwind { 141; ARM-LABEL: func7: 142; ARM: @ %bb.0: 143; ARM-NEXT: .save {r4, r5, r6, r7, lr} 144; ARM-NEXT: push {r4, r5, r6, r7, lr} 145; ARM-NEXT: .pad #20 146; ARM-NEXT: sub sp, #20 147; ARM-NEXT: str r3, [sp, #16] @ 4-byte Spill 148; ARM-NEXT: mov r7, r2 149; ARM-NEXT: mov r2, r1 150; ARM-NEXT: str r1, [sp, #8] @ 4-byte Spill 151; ARM-NEXT: mov r5, r0 152; ARM-NEXT: asrs r1, r1, #31 153; ARM-NEXT: str r1, [sp, #12] @ 4-byte Spill 154; ARM-NEXT: movs r4, #0 155; ARM-NEXT: mov r0, r2 156; ARM-NEXT: mov r2, r7 157; ARM-NEXT: mov r3, r4 158; ARM-NEXT: bl __aeabi_lmul 159; ARM-NEXT: str r0, [sp, #4] @ 4-byte Spill 160; ARM-NEXT: mov r6, r1 161; ARM-NEXT: mov r0, r5 162; ARM-NEXT: mov r1, r4 163; ARM-NEXT: mov r2, r7 164; ARM-NEXT: mov r3, r4 165; ARM-NEXT: bl __aeabi_lmul 166; ARM-NEXT: ldr r0, [sp, #4] @ 4-byte Reload 167; ARM-NEXT: adds r0, r0, r1 168; ARM-NEXT: str r0, [sp, #4] @ 4-byte Spill 169; ARM-NEXT: adcs r6, r4 170; ARM-NEXT: ldr r2, [sp, #16] @ 4-byte Reload 171; ARM-NEXT: asrs r7, r2, #31 172; ARM-NEXT: mov r0, r5 173; ARM-NEXT: mov r1, r4 174; ARM-NEXT: mov r3, r7 175; ARM-NEXT: bl __aeabi_lmul 176; ARM-NEXT: mov r4, r1 177; ARM-NEXT: ldr r1, [sp, #4] @ 4-byte Reload 178; ARM-NEXT: adds r5, r0, r1 179; ARM-NEXT: adcs r4, r6 180; ARM-NEXT: add r2, sp, #8 181; ARM-NEXT: ldm r2, {r0, r1, r2} @ 12-byte Folded Reload 182; ARM-NEXT: mov r3, r7 183; ARM-NEXT: bl __aeabi_lmul 184; ARM-NEXT: adds r1, r0, r4 185; ARM-NEXT: mov r0, r5 186; ARM-NEXT: add sp, #20 187; ARM-NEXT: pop {r4, r5, r6, r7, pc} 188 %tmp = call i64 @llvm.smul.fix.i64(i64 %x, i64 %y, i32 32) 189 ret i64 %tmp 190} 191 192define i64 @func8(i64 %x, i64 %y) nounwind { 193; ARM-LABEL: func8: 194; ARM: @ %bb.0: 195; ARM-NEXT: .save {r4, r5, r6, r7, lr} 196; ARM-NEXT: push {r4, r5, r6, r7, lr} 197; ARM-NEXT: .pad #20 198; ARM-NEXT: sub sp, #20 199; ARM-NEXT: str r3, [sp, #16] @ 4-byte Spill 200; ARM-NEXT: mov r4, r2 201; ARM-NEXT: mov r2, r1 202; ARM-NEXT: str r1, [sp, #8] @ 4-byte Spill 203; ARM-NEXT: mov r5, r0 204; ARM-NEXT: asrs r1, r1, #31 205; ARM-NEXT: str r1, [sp, #12] @ 4-byte Spill 206; ARM-NEXT: movs r7, #0 207; ARM-NEXT: mov r0, r2 208; ARM-NEXT: mov r2, r4 209; ARM-NEXT: mov r3, r7 210; ARM-NEXT: bl __aeabi_lmul 211; ARM-NEXT: str r0, [sp, #4] @ 4-byte Spill 212; ARM-NEXT: mov r6, r1 213; ARM-NEXT: mov r0, r5 214; ARM-NEXT: mov r1, r7 215; ARM-NEXT: mov r2, r4 216; ARM-NEXT: mov r3, r7 217; ARM-NEXT: bl __aeabi_lmul 218; ARM-NEXT: ldr r0, [sp, #4] @ 4-byte Reload 219; ARM-NEXT: adds r0, r0, r1 220; ARM-NEXT: str r0, [sp] @ 4-byte Spill 221; ARM-NEXT: adcs r6, r7 222; ARM-NEXT: asrs r0, r6, #31 223; ARM-NEXT: str r0, [sp, #4] @ 4-byte Spill 224; ARM-NEXT: ldr r2, [sp, #16] @ 4-byte Reload 225; ARM-NEXT: asrs r4, r2, #31 226; ARM-NEXT: mov r0, r5 227; ARM-NEXT: mov r1, r7 228; ARM-NEXT: mov r3, r4 229; ARM-NEXT: bl __aeabi_lmul 230; ARM-NEXT: ldr r2, [sp] @ 4-byte Reload 231; ARM-NEXT: adds r5, r0, r2 232; ARM-NEXT: adcs r1, r7 233; ARM-NEXT: asrs r7, r1, #31 234; ARM-NEXT: adds r6, r6, r1 235; ARM-NEXT: ldr r0, [sp, #4] @ 4-byte Reload 236; ARM-NEXT: adcs r7, r0 237; ARM-NEXT: add r2, sp, #8 238; ARM-NEXT: ldm r2, {r0, r1, r2} @ 12-byte Folded Reload 239; ARM-NEXT: mov r3, r4 240; ARM-NEXT: bl __aeabi_lmul 241; ARM-NEXT: adds r0, r0, r6 242; ARM-NEXT: adcs r1, r7 243; ARM-NEXT: lsls r1, r1, #1 244; ARM-NEXT: lsrs r2, r0, #31 245; ARM-NEXT: adds r1, r1, r2 246; ARM-NEXT: lsls r0, r0, #1 247; ARM-NEXT: lsrs r2, r5, #31 248; ARM-NEXT: adds r0, r0, r2 249; ARM-NEXT: add sp, #20 250; ARM-NEXT: pop {r4, r5, r6, r7, pc} 251 %tmp = call i64 @llvm.smul.fix.i64(i64 %x, i64 %y, i32 63) 252 ret i64 %tmp 253} 254