1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=thumbv6m-none-eabi | FileCheck %s --check-prefix=CHECK-T1 3; RUN: llc < %s -mtriple=thumbv7m-none-eabi | FileCheck %s --check-prefix=CHECK-T2 --check-prefix=CHECK-T2NODSP 4; RUN: llc < %s -mtriple=thumbv7em-none-eabi | FileCheck %s --check-prefix=CHECK-T2 --check-prefix=CHECK-T2DSP 5; RUN: llc < %s -mtriple=armv8a-none-eabi | FileCheck %s --check-prefix=CHECK-ARM 6 7declare i4 @llvm.ssub.sat.i4(i4, i4) 8declare i8 @llvm.ssub.sat.i8(i8, i8) 9declare i16 @llvm.ssub.sat.i16(i16, i16) 10declare i32 @llvm.ssub.sat.i32(i32, i32) 11declare i64 @llvm.ssub.sat.i64(i64, i64) 12 13define i32 @func32(i32 %x, i32 %y, i32 %z) nounwind { 14; CHECK-T1-LABEL: func32: 15; CHECK-T1: @ %bb.0: 16; CHECK-T1-NEXT: .save {r4, lr} 17; CHECK-T1-NEXT: push {r4, lr} 18; CHECK-T1-NEXT: mov r3, r0 19; CHECK-T1-NEXT: muls r1, r2, r1 20; CHECK-T1-NEXT: movs r2, #1 21; CHECK-T1-NEXT: subs r0, r0, r1 22; CHECK-T1-NEXT: mov r4, r2 23; CHECK-T1-NEXT: bmi .LBB0_2 24; CHECK-T1-NEXT: @ %bb.1: 25; CHECK-T1-NEXT: movs r4, #0 26; CHECK-T1-NEXT: .LBB0_2: 27; CHECK-T1-NEXT: cmp r4, #0 28; CHECK-T1-NEXT: bne .LBB0_4 29; CHECK-T1-NEXT: @ %bb.3: 30; CHECK-T1-NEXT: lsls r2, r2, #31 31; CHECK-T1-NEXT: cmp r3, r1 32; CHECK-T1-NEXT: bvs .LBB0_5 33; CHECK-T1-NEXT: b .LBB0_6 34; CHECK-T1-NEXT: .LBB0_4: 35; CHECK-T1-NEXT: ldr r2, .LCPI0_0 36; CHECK-T1-NEXT: cmp r3, r1 37; CHECK-T1-NEXT: bvc .LBB0_6 38; CHECK-T1-NEXT: .LBB0_5: 39; CHECK-T1-NEXT: mov r0, r2 40; CHECK-T1-NEXT: .LBB0_6: 41; CHECK-T1-NEXT: pop {r4, pc} 42; CHECK-T1-NEXT: .p2align 2 43; CHECK-T1-NEXT: @ %bb.7: 44; CHECK-T1-NEXT: .LCPI0_0: 45; CHECK-T1-NEXT: .long 2147483647 @ 0x7fffffff 46; 47; CHECK-T2NODSP-LABEL: func32: 48; CHECK-T2NODSP: @ %bb.0: 49; CHECK-T2NODSP-NEXT: .save {r7, lr} 50; CHECK-T2NODSP-NEXT: push {r7, lr} 51; CHECK-T2NODSP-NEXT: mls r12, r1, r2, r0 52; CHECK-T2NODSP-NEXT: mov.w lr, #0 53; CHECK-T2NODSP-NEXT: mov.w r3, #-2147483648 54; CHECK-T2NODSP-NEXT: muls r1, r2, r1 55; CHECK-T2NODSP-NEXT: cmp.w r12, #0 56; CHECK-T2NODSP-NEXT: it mi 57; CHECK-T2NODSP-NEXT: movmi.w lr, #1 58; CHECK-T2NODSP-NEXT: cmp.w lr, #0 59; CHECK-T2NODSP-NEXT: it ne 60; CHECK-T2NODSP-NEXT: mvnne r3, #-2147483648 61; CHECK-T2NODSP-NEXT: cmp r0, r1 62; CHECK-T2NODSP-NEXT: it vc 63; CHECK-T2NODSP-NEXT: movvc r3, r12 64; CHECK-T2NODSP-NEXT: mov r0, r3 65; CHECK-T2NODSP-NEXT: pop {r7, pc} 66; 67; CHECK-T2DSP-LABEL: func32: 68; CHECK-T2DSP: @ %bb.0: 69; CHECK-T2DSP-NEXT: muls r1, r2, r1 70; CHECK-T2DSP-NEXT: qsub r0, r0, r1 71; CHECK-T2DSP-NEXT: bx lr 72; 73; CHECK-ARM-LABEL: func32: 74; CHECK-ARM: @ %bb.0: 75; CHECK-ARM-NEXT: mul r1, r1, r2 76; CHECK-ARM-NEXT: qsub r0, r0, r1 77; CHECK-ARM-NEXT: bx lr 78 %a = mul i32 %y, %z 79 %tmp = call i32 @llvm.ssub.sat.i32(i32 %x, i32 %a) 80 ret i32 %tmp 81} 82 83define i64 @func64(i64 %x, i64 %y, i64 %z) nounwind { 84; CHECK-T1-LABEL: func64: 85; CHECK-T1: @ %bb.0: 86; CHECK-T1-NEXT: .save {r4, r5, r6, r7, lr} 87; CHECK-T1-NEXT: push {r4, r5, r6, r7, lr} 88; CHECK-T1-NEXT: .pad #4 89; CHECK-T1-NEXT: sub sp, #4 90; CHECK-T1-NEXT: ldr r5, [sp, #28] 91; CHECK-T1-NEXT: movs r2, #1 92; CHECK-T1-NEXT: movs r4, #0 93; CHECK-T1-NEXT: cmp r5, #0 94; CHECK-T1-NEXT: mov r3, r2 95; CHECK-T1-NEXT: bge .LBB1_2 96; CHECK-T1-NEXT: @ %bb.1: 97; CHECK-T1-NEXT: mov r3, r4 98; CHECK-T1-NEXT: .LBB1_2: 99; CHECK-T1-NEXT: cmp r1, #0 100; CHECK-T1-NEXT: mov r6, r2 101; CHECK-T1-NEXT: bge .LBB1_4 102; CHECK-T1-NEXT: @ %bb.3: 103; CHECK-T1-NEXT: mov r6, r4 104; CHECK-T1-NEXT: .LBB1_4: 105; CHECK-T1-NEXT: subs r3, r6, r3 106; CHECK-T1-NEXT: subs r7, r3, #1 107; CHECK-T1-NEXT: sbcs r3, r7 108; CHECK-T1-NEXT: ldr r7, [sp, #24] 109; CHECK-T1-NEXT: subs r0, r0, r7 110; CHECK-T1-NEXT: sbcs r1, r5 111; CHECK-T1-NEXT: cmp r1, #0 112; CHECK-T1-NEXT: mov r5, r2 113; CHECK-T1-NEXT: bge .LBB1_6 114; CHECK-T1-NEXT: @ %bb.5: 115; CHECK-T1-NEXT: mov r5, r4 116; CHECK-T1-NEXT: .LBB1_6: 117; CHECK-T1-NEXT: subs r4, r6, r5 118; CHECK-T1-NEXT: subs r5, r4, #1 119; CHECK-T1-NEXT: sbcs r4, r5 120; CHECK-T1-NEXT: ands r3, r4 121; CHECK-T1-NEXT: beq .LBB1_8 122; CHECK-T1-NEXT: @ %bb.7: 123; CHECK-T1-NEXT: asrs r0, r1, #31 124; CHECK-T1-NEXT: .LBB1_8: 125; CHECK-T1-NEXT: cmp r1, #0 126; CHECK-T1-NEXT: bmi .LBB1_10 127; CHECK-T1-NEXT: @ %bb.9: 128; CHECK-T1-NEXT: lsls r2, r2, #31 129; CHECK-T1-NEXT: cmp r3, #0 130; CHECK-T1-NEXT: beq .LBB1_11 131; CHECK-T1-NEXT: b .LBB1_12 132; CHECK-T1-NEXT: .LBB1_10: 133; CHECK-T1-NEXT: ldr r2, .LCPI1_0 134; CHECK-T1-NEXT: cmp r3, #0 135; CHECK-T1-NEXT: bne .LBB1_12 136; CHECK-T1-NEXT: .LBB1_11: 137; CHECK-T1-NEXT: mov r2, r1 138; CHECK-T1-NEXT: .LBB1_12: 139; CHECK-T1-NEXT: mov r1, r2 140; CHECK-T1-NEXT: add sp, #4 141; CHECK-T1-NEXT: pop {r4, r5, r6, r7, pc} 142; CHECK-T1-NEXT: .p2align 2 143; CHECK-T1-NEXT: @ %bb.13: 144; CHECK-T1-NEXT: .LCPI1_0: 145; CHECK-T1-NEXT: .long 2147483647 @ 0x7fffffff 146; 147; CHECK-T2-LABEL: func64: 148; CHECK-T2: @ %bb.0: 149; CHECK-T2-NEXT: .save {r4, lr} 150; CHECK-T2-NEXT: push {r4, lr} 151; CHECK-T2-NEXT: ldr.w r12, [sp, #12] 152; CHECK-T2-NEXT: movs r2, #0 153; CHECK-T2-NEXT: movs r3, #0 154; CHECK-T2-NEXT: ldr r4, [sp, #8] 155; CHECK-T2-NEXT: cmp.w r12, #-1 156; CHECK-T2-NEXT: it gt 157; CHECK-T2-NEXT: movgt r2, #1 158; CHECK-T2-NEXT: cmp.w r1, #-1 159; CHECK-T2-NEXT: it gt 160; CHECK-T2-NEXT: movgt r3, #1 161; CHECK-T2-NEXT: subs r2, r3, r2 162; CHECK-T2-NEXT: mov.w lr, #0 163; CHECK-T2-NEXT: it ne 164; CHECK-T2-NEXT: movne r2, #1 165; CHECK-T2-NEXT: subs r0, r0, r4 166; CHECK-T2-NEXT: sbc.w r4, r1, r12 167; CHECK-T2-NEXT: cmp.w r4, #-1 168; CHECK-T2-NEXT: it gt 169; CHECK-T2-NEXT: movgt.w lr, #1 170; CHECK-T2-NEXT: subs.w r1, r3, lr 171; CHECK-T2-NEXT: it ne 172; CHECK-T2-NEXT: movne r1, #1 173; CHECK-T2-NEXT: ands r2, r1 174; CHECK-T2-NEXT: mov.w r1, #-2147483648 175; CHECK-T2-NEXT: it ne 176; CHECK-T2-NEXT: asrne r0, r4, #31 177; CHECK-T2-NEXT: cmp r4, #0 178; CHECK-T2-NEXT: it mi 179; CHECK-T2-NEXT: mvnmi r1, #-2147483648 180; CHECK-T2-NEXT: cmp r2, #0 181; CHECK-T2-NEXT: it eq 182; CHECK-T2-NEXT: moveq r1, r4 183; CHECK-T2-NEXT: pop {r4, pc} 184; 185; CHECK-ARM-LABEL: func64: 186; CHECK-ARM: @ %bb.0: 187; CHECK-ARM-NEXT: .save {r4, r5, r11, lr} 188; CHECK-ARM-NEXT: push {r4, r5, r11, lr} 189; CHECK-ARM-NEXT: ldr lr, [sp, #20] 190; CHECK-ARM-NEXT: cmn r1, #1 191; CHECK-ARM-NEXT: mov r3, #0 192; CHECK-ARM-NEXT: mov r4, #0 193; CHECK-ARM-NEXT: movwgt r3, #1 194; CHECK-ARM-NEXT: cmn lr, #1 195; CHECK-ARM-NEXT: movwgt r4, #1 196; CHECK-ARM-NEXT: ldr r12, [sp, #16] 197; CHECK-ARM-NEXT: subs r4, r3, r4 198; CHECK-ARM-NEXT: mov r5, #0 199; CHECK-ARM-NEXT: movwne r4, #1 200; CHECK-ARM-NEXT: subs r0, r0, r12 201; CHECK-ARM-NEXT: sbc r2, r1, lr 202; CHECK-ARM-NEXT: cmn r2, #1 203; CHECK-ARM-NEXT: movwgt r5, #1 204; CHECK-ARM-NEXT: subs r1, r3, r5 205; CHECK-ARM-NEXT: movwne r1, #1 206; CHECK-ARM-NEXT: ands r3, r4, r1 207; CHECK-ARM-NEXT: asrne r0, r2, #31 208; CHECK-ARM-NEXT: mov r1, #-2147483648 209; CHECK-ARM-NEXT: cmp r2, #0 210; CHECK-ARM-NEXT: mvnmi r1, #-2147483648 211; CHECK-ARM-NEXT: cmp r3, #0 212; CHECK-ARM-NEXT: moveq r1, r2 213; CHECK-ARM-NEXT: pop {r4, r5, r11, pc} 214 %a = mul i64 %y, %z 215 %tmp = call i64 @llvm.ssub.sat.i64(i64 %x, i64 %z) 216 ret i64 %tmp 217} 218 219define signext i16 @func16(i16 signext %x, i16 signext %y, i16 signext %z) nounwind { 220; CHECK-T1-LABEL: func16: 221; CHECK-T1: @ %bb.0: 222; CHECK-T1-NEXT: muls r1, r2, r1 223; CHECK-T1-NEXT: sxth r1, r1 224; CHECK-T1-NEXT: subs r0, r0, r1 225; CHECK-T1-NEXT: ldr r1, .LCPI2_0 226; CHECK-T1-NEXT: cmp r0, r1 227; CHECK-T1-NEXT: blt .LBB2_2 228; CHECK-T1-NEXT: @ %bb.1: 229; CHECK-T1-NEXT: mov r0, r1 230; CHECK-T1-NEXT: .LBB2_2: 231; CHECK-T1-NEXT: ldr r1, .LCPI2_1 232; CHECK-T1-NEXT: cmp r0, r1 233; CHECK-T1-NEXT: bgt .LBB2_4 234; CHECK-T1-NEXT: @ %bb.3: 235; CHECK-T1-NEXT: mov r0, r1 236; CHECK-T1-NEXT: .LBB2_4: 237; CHECK-T1-NEXT: bx lr 238; CHECK-T1-NEXT: .p2align 2 239; CHECK-T1-NEXT: @ %bb.5: 240; CHECK-T1-NEXT: .LCPI2_0: 241; CHECK-T1-NEXT: .long 32767 @ 0x7fff 242; CHECK-T1-NEXT: .LCPI2_1: 243; CHECK-T1-NEXT: .long 4294934528 @ 0xffff8000 244; 245; CHECK-T2NODSP-LABEL: func16: 246; CHECK-T2NODSP: @ %bb.0: 247; CHECK-T2NODSP-NEXT: muls r1, r2, r1 248; CHECK-T2NODSP-NEXT: sxth r1, r1 249; CHECK-T2NODSP-NEXT: subs r0, r0, r1 250; CHECK-T2NODSP-NEXT: movw r1, #32767 251; CHECK-T2NODSP-NEXT: cmp r0, r1 252; CHECK-T2NODSP-NEXT: it lt 253; CHECK-T2NODSP-NEXT: movlt r1, r0 254; CHECK-T2NODSP-NEXT: movw r0, #32768 255; CHECK-T2NODSP-NEXT: movt r0, #65535 256; CHECK-T2NODSP-NEXT: cmn.w r1, #32768 257; CHECK-T2NODSP-NEXT: it gt 258; CHECK-T2NODSP-NEXT: movgt r0, r1 259; CHECK-T2NODSP-NEXT: bx lr 260; 261; CHECK-T2DSP-LABEL: func16: 262; CHECK-T2DSP: @ %bb.0: 263; CHECK-T2DSP-NEXT: muls r1, r2, r1 264; CHECK-T2DSP-NEXT: qsub16 r0, r0, r1 265; CHECK-T2DSP-NEXT: sxth r0, r0 266; CHECK-T2DSP-NEXT: bx lr 267; 268; CHECK-ARM-LABEL: func16: 269; CHECK-ARM: @ %bb.0: 270; CHECK-ARM-NEXT: smulbb r1, r1, r2 271; CHECK-ARM-NEXT: qsub16 r0, r0, r1 272; CHECK-ARM-NEXT: sxth r0, r0 273; CHECK-ARM-NEXT: bx lr 274 %a = mul i16 %y, %z 275 %tmp = call i16 @llvm.ssub.sat.i16(i16 %x, i16 %a) 276 ret i16 %tmp 277} 278 279define signext i8 @func8(i8 signext %x, i8 signext %y, i8 signext %z) nounwind { 280; CHECK-T1-LABEL: func8: 281; CHECK-T1: @ %bb.0: 282; CHECK-T1-NEXT: muls r1, r2, r1 283; CHECK-T1-NEXT: sxtb r1, r1 284; CHECK-T1-NEXT: subs r0, r0, r1 285; CHECK-T1-NEXT: movs r1, #127 286; CHECK-T1-NEXT: cmp r0, #127 287; CHECK-T1-NEXT: blt .LBB3_2 288; CHECK-T1-NEXT: @ %bb.1: 289; CHECK-T1-NEXT: mov r0, r1 290; CHECK-T1-NEXT: .LBB3_2: 291; CHECK-T1-NEXT: mvns r1, r1 292; CHECK-T1-NEXT: cmp r0, r1 293; CHECK-T1-NEXT: bgt .LBB3_4 294; CHECK-T1-NEXT: @ %bb.3: 295; CHECK-T1-NEXT: mov r0, r1 296; CHECK-T1-NEXT: .LBB3_4: 297; CHECK-T1-NEXT: bx lr 298; 299; CHECK-T2NODSP-LABEL: func8: 300; CHECK-T2NODSP: @ %bb.0: 301; CHECK-T2NODSP-NEXT: muls r1, r2, r1 302; CHECK-T2NODSP-NEXT: sxtb r1, r1 303; CHECK-T2NODSP-NEXT: subs r0, r0, r1 304; CHECK-T2NODSP-NEXT: cmp r0, #127 305; CHECK-T2NODSP-NEXT: it ge 306; CHECK-T2NODSP-NEXT: movge r0, #127 307; CHECK-T2NODSP-NEXT: cmn.w r0, #128 308; CHECK-T2NODSP-NEXT: it le 309; CHECK-T2NODSP-NEXT: mvnle r0, #127 310; CHECK-T2NODSP-NEXT: bx lr 311; 312; CHECK-T2DSP-LABEL: func8: 313; CHECK-T2DSP: @ %bb.0: 314; CHECK-T2DSP-NEXT: muls r1, r2, r1 315; CHECK-T2DSP-NEXT: qsub8 r0, r0, r1 316; CHECK-T2DSP-NEXT: sxtb r0, r0 317; CHECK-T2DSP-NEXT: bx lr 318; 319; CHECK-ARM-LABEL: func8: 320; CHECK-ARM: @ %bb.0: 321; CHECK-ARM-NEXT: smulbb r1, r1, r2 322; CHECK-ARM-NEXT: qsub8 r0, r0, r1 323; CHECK-ARM-NEXT: sxtb r0, r0 324; CHECK-ARM-NEXT: bx lr 325 %a = mul i8 %y, %z 326 %tmp = call i8 @llvm.ssub.sat.i8(i8 %x, i8 %a) 327 ret i8 %tmp 328} 329 330define signext i4 @func4(i4 signext %x, i4 signext %y, i4 signext %z) nounwind { 331; CHECK-T1-LABEL: func4: 332; CHECK-T1: @ %bb.0: 333; CHECK-T1-NEXT: muls r1, r2, r1 334; CHECK-T1-NEXT: lsls r1, r1, #28 335; CHECK-T1-NEXT: asrs r1, r1, #28 336; CHECK-T1-NEXT: subs r0, r0, r1 337; CHECK-T1-NEXT: movs r1, #7 338; CHECK-T1-NEXT: cmp r0, #7 339; CHECK-T1-NEXT: blt .LBB4_2 340; CHECK-T1-NEXT: @ %bb.1: 341; CHECK-T1-NEXT: mov r0, r1 342; CHECK-T1-NEXT: .LBB4_2: 343; CHECK-T1-NEXT: mvns r1, r1 344; CHECK-T1-NEXT: cmp r0, r1 345; CHECK-T1-NEXT: bgt .LBB4_4 346; CHECK-T1-NEXT: @ %bb.3: 347; CHECK-T1-NEXT: mov r0, r1 348; CHECK-T1-NEXT: .LBB4_4: 349; CHECK-T1-NEXT: bx lr 350; 351; CHECK-T2NODSP-LABEL: func4: 352; CHECK-T2NODSP: @ %bb.0: 353; CHECK-T2NODSP-NEXT: muls r1, r2, r1 354; CHECK-T2NODSP-NEXT: lsls r1, r1, #28 355; CHECK-T2NODSP-NEXT: sub.w r0, r0, r1, asr #28 356; CHECK-T2NODSP-NEXT: cmp r0, #7 357; CHECK-T2NODSP-NEXT: it ge 358; CHECK-T2NODSP-NEXT: movge r0, #7 359; CHECK-T2NODSP-NEXT: cmn.w r0, #8 360; CHECK-T2NODSP-NEXT: it le 361; CHECK-T2NODSP-NEXT: mvnle r0, #7 362; CHECK-T2NODSP-NEXT: bx lr 363; 364; CHECK-T2DSP-LABEL: func4: 365; CHECK-T2DSP: @ %bb.0: 366; CHECK-T2DSP-NEXT: muls r1, r2, r1 367; CHECK-T2DSP-NEXT: lsls r0, r0, #28 368; CHECK-T2DSP-NEXT: lsls r1, r1, #28 369; CHECK-T2DSP-NEXT: qsub r0, r0, r1 370; CHECK-T2DSP-NEXT: asrs r0, r0, #28 371; CHECK-T2DSP-NEXT: bx lr 372; 373; CHECK-ARM-LABEL: func4: 374; CHECK-ARM: @ %bb.0: 375; CHECK-ARM-NEXT: smulbb r1, r1, r2 376; CHECK-ARM-NEXT: lsl r0, r0, #28 377; CHECK-ARM-NEXT: lsl r1, r1, #28 378; CHECK-ARM-NEXT: qsub r0, r0, r1 379; CHECK-ARM-NEXT: asr r0, r0, #28 380; CHECK-ARM-NEXT: bx lr 381 %a = mul i4 %y, %z 382 %tmp = call i4 @llvm.ssub.sat.i4(i4 %x, i4 %a) 383 ret i4 %tmp 384} 385