1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 2; RUN: llc -verify-machineinstrs -csky-no-aliases -mattr=+2e3 < %s -mtriple=csky | FileCheck %s 3; RUN: llc -verify-machineinstrs -csky-no-aliases < %s -mtriple=csky | FileCheck %s --check-prefix=GENERIC 4 5;; This file shows if a multiplication can be simplified to an addition/subtraction 6;; of left shifts. 7 8define i32 @mul_i32_4097(i32 %x) { 9; CHECK-LABEL: mul_i32_4097: 10; CHECK: # %bb.0: # %entry 11; CHECK-NEXT: lsli16 a1, a0, 12 12; CHECK-NEXT: addu16 a0, a1 13; CHECK-NEXT: rts16 14; 15; GENERIC-LABEL: mul_i32_4097: 16; GENERIC: # %bb.0: # %entry 17; GENERIC-NEXT: .cfi_def_cfa_offset 0 18; GENERIC-NEXT: subi16 sp, sp, 4 19; GENERIC-NEXT: .cfi_def_cfa_offset 4 20; GENERIC-NEXT: lsli16 a1, a0, 12 21; GENERIC-NEXT: addu16 a0, a1, a0 22; GENERIC-NEXT: addi16 sp, sp, 4 23; GENERIC-NEXT: rts16 24entry: 25 %y = mul nsw i32 %x, 4097 26 ret i32 %y 27} 28 29define i32 @mul_i32_4095(i32 %x) { 30; CHECK-LABEL: mul_i32_4095: 31; CHECK: # %bb.0: # %entry 32; CHECK-NEXT: lsli16 a1, a0, 12 33; CHECK-NEXT: subu16 a0, a1, a0 34; CHECK-NEXT: rts16 35; 36; GENERIC-LABEL: mul_i32_4095: 37; GENERIC: # %bb.0: # %entry 38; GENERIC-NEXT: .cfi_def_cfa_offset 0 39; GENERIC-NEXT: subi16 sp, sp, 4 40; GENERIC-NEXT: .cfi_def_cfa_offset 4 41; GENERIC-NEXT: lsli16 a1, a0, 12 42; GENERIC-NEXT: subu16 a0, a1, a0 43; GENERIC-NEXT: addi16 sp, sp, 4 44; GENERIC-NEXT: rts16 45entry: 46 %y = mul nsw i32 %x, 4095 47 ret i32 %y 48} 49 50define i32 @mul_i32_minus_4095(i32 %x) { 51; CHECK-LABEL: mul_i32_minus_4095: 52; CHECK: # %bb.0: # %entry 53; CHECK-NEXT: lsli16 a1, a0, 12 54; CHECK-NEXT: subu16 a0, a1 55; CHECK-NEXT: rts16 56; 57; GENERIC-LABEL: mul_i32_minus_4095: 58; GENERIC: # %bb.0: # %entry 59; GENERIC-NEXT: .cfi_def_cfa_offset 0 60; GENERIC-NEXT: subi16 sp, sp, 4 61; GENERIC-NEXT: .cfi_def_cfa_offset 4 62; GENERIC-NEXT: lsli16 a1, a0, 12 63; GENERIC-NEXT: subu16 a0, a0, a1 64; GENERIC-NEXT: addi16 sp, sp, 4 65; GENERIC-NEXT: rts16 66entry: 67 %y = mul nsw i32 %x, -4095 68 ret i32 %y 69} 70 71define i32 @mul_i32_131074(i32 %x) { 72; CHECK-LABEL: mul_i32_131074: 73; CHECK: # %bb.0: # %entry 74; CHECK-NEXT: lsli16 a1, a0, 17 75; CHECK-NEXT: ixh32 a0, a1, a0 76; CHECK-NEXT: rts16 77; 78; GENERIC-LABEL: mul_i32_131074: 79; GENERIC: # %bb.0: # %entry 80; GENERIC-NEXT: subi16 sp, sp, 4 81; GENERIC-NEXT: .cfi_def_cfa_offset 4 82; GENERIC-NEXT: st16.w l0, (sp, 0) # 4-byte Folded Spill 83; GENERIC-NEXT: .cfi_offset l0, -4 84; GENERIC-NEXT: subi16 sp, sp, 4 85; GENERIC-NEXT: .cfi_def_cfa_offset 8 86; GENERIC-NEXT: movi16 a1, 0 87; GENERIC-NEXT: lsli16 a2, a1, 24 88; GENERIC-NEXT: movi16 a3, 2 89; GENERIC-NEXT: lsli16 l0, a3, 16 90; GENERIC-NEXT: or16 l0, a2 91; GENERIC-NEXT: lsli16 a1, a1, 8 92; GENERIC-NEXT: or16 a1, l0 93; GENERIC-NEXT: or16 a1, a3 94; GENERIC-NEXT: mult16 a0, a1 95; GENERIC-NEXT: addi16 sp, sp, 4 96; GENERIC-NEXT: ld16.w l0, (sp, 0) # 4-byte Folded Reload 97; GENERIC-NEXT: addi16 sp, sp, 4 98; GENERIC-NEXT: rts16 99entry: 100 %y = mul nsw i32 %x, 131074 101 ret i32 %y 102} 103 104define i32 @mul_i32_131076(i32 %x) { 105; CHECK-LABEL: mul_i32_131076: 106; CHECK: # %bb.0: # %entry 107; CHECK-NEXT: lsli16 a1, a0, 17 108; CHECK-NEXT: ixw32 a0, a1, a0 109; CHECK-NEXT: rts16 110; 111; GENERIC-LABEL: mul_i32_131076: 112; GENERIC: # %bb.0: # %entry 113; GENERIC-NEXT: .cfi_def_cfa_offset 0 114; GENERIC-NEXT: subi16 sp, sp, 4 115; GENERIC-NEXT: .cfi_def_cfa_offset 4 116; GENERIC-NEXT: movi16 a1, 0 117; GENERIC-NEXT: lsli16 a2, a1, 24 118; GENERIC-NEXT: movi16 a3, 2 119; GENERIC-NEXT: lsli16 a3, a3, 16 120; GENERIC-NEXT: or16 a3, a2 121; GENERIC-NEXT: lsli16 a1, a1, 8 122; GENERIC-NEXT: or16 a1, a3 123; GENERIC-NEXT: movi16 a2, 4 124; GENERIC-NEXT: or16 a2, a1 125; GENERIC-NEXT: mult16 a0, a2 126; GENERIC-NEXT: addi16 sp, sp, 4 127; GENERIC-NEXT: rts16 128entry: 129 %y = mul nsw i32 %x, 131076 130 ret i32 %y 131} 132 133define i32 @mul_i32_131080(i32 %x) { 134; CHECK-LABEL: mul_i32_131080: 135; CHECK: # %bb.0: # %entry 136; CHECK-NEXT: lsli16 a1, a0, 17 137; CHECK-NEXT: ixd32 a0, a1, a0 138; CHECK-NEXT: rts16 139; 140; GENERIC-LABEL: mul_i32_131080: 141; GENERIC: # %bb.0: # %entry 142; GENERIC-NEXT: .cfi_def_cfa_offset 0 143; GENERIC-NEXT: subi16 sp, sp, 4 144; GENERIC-NEXT: .cfi_def_cfa_offset 4 145; GENERIC-NEXT: movi16 a1, 0 146; GENERIC-NEXT: lsli16 a2, a1, 24 147; GENERIC-NEXT: movi16 a3, 2 148; GENERIC-NEXT: lsli16 a3, a3, 16 149; GENERIC-NEXT: or16 a3, a2 150; GENERIC-NEXT: lsli16 a1, a1, 8 151; GENERIC-NEXT: or16 a1, a3 152; GENERIC-NEXT: movi16 a2, 8 153; GENERIC-NEXT: or16 a2, a1 154; GENERIC-NEXT: mult16 a0, a2 155; GENERIC-NEXT: addi16 sp, sp, 4 156; GENERIC-NEXT: rts16 157entry: 158 %y = mul nsw i32 %x, 131080 159 ret i32 %y 160} 161 162define i16 @mul_i16_4097(i16 %x) { 163; CHECK-LABEL: mul_i16_4097: 164; CHECK: # %bb.0: # %entry 165; CHECK-NEXT: lsli16 a1, a0, 12 166; CHECK-NEXT: addu16 a0, a1 167; CHECK-NEXT: rts16 168; 169; GENERIC-LABEL: mul_i16_4097: 170; GENERIC: # %bb.0: # %entry 171; GENERIC-NEXT: .cfi_def_cfa_offset 0 172; GENERIC-NEXT: subi16 sp, sp, 4 173; GENERIC-NEXT: .cfi_def_cfa_offset 4 174; GENERIC-NEXT: lsli16 a1, a0, 12 175; GENERIC-NEXT: addu16 a0, a1, a0 176; GENERIC-NEXT: addi16 sp, sp, 4 177; GENERIC-NEXT: rts16 178entry: 179 %y = mul nsw i16 %x, 4097 180 ret i16 %y 181} 182 183define i16 @mul_i16_4095(i16 %x) { 184; CHECK-LABEL: mul_i16_4095: 185; CHECK: # %bb.0: # %entry 186; CHECK-NEXT: lsli16 a1, a0, 12 187; CHECK-NEXT: subu16 a0, a1, a0 188; CHECK-NEXT: rts16 189; 190; GENERIC-LABEL: mul_i16_4095: 191; GENERIC: # %bb.0: # %entry 192; GENERIC-NEXT: .cfi_def_cfa_offset 0 193; GENERIC-NEXT: subi16 sp, sp, 4 194; GENERIC-NEXT: .cfi_def_cfa_offset 4 195; GENERIC-NEXT: lsli16 a1, a0, 12 196; GENERIC-NEXT: subu16 a0, a1, a0 197; GENERIC-NEXT: addi16 sp, sp, 4 198; GENERIC-NEXT: rts16 199entry: 200 %y = mul nsw i16 %x, 4095 201 ret i16 %y 202} 203 204define i16 @mul_i16_minus_4095(i16 %x) { 205; CHECK-LABEL: mul_i16_minus_4095: 206; CHECK: # %bb.0: # %entry 207; CHECK-NEXT: lsli16 a1, a0, 12 208; CHECK-NEXT: subu16 a0, a1 209; CHECK-NEXT: rts16 210; 211; GENERIC-LABEL: mul_i16_minus_4095: 212; GENERIC: # %bb.0: # %entry 213; GENERIC-NEXT: .cfi_def_cfa_offset 0 214; GENERIC-NEXT: subi16 sp, sp, 4 215; GENERIC-NEXT: .cfi_def_cfa_offset 4 216; GENERIC-NEXT: lsli16 a1, a0, 12 217; GENERIC-NEXT: subu16 a0, a0, a1 218; GENERIC-NEXT: addi16 sp, sp, 4 219; GENERIC-NEXT: rts16 220entry: 221 %y = mul nsw i16 %x, -4095 222 ret i16 %y 223} 224 225define i8 @mul_i8_65(i8 %x) { 226; CHECK-LABEL: mul_i8_65: 227; CHECK: # %bb.0: # %entry 228; CHECK-NEXT: lsli16 a1, a0, 6 229; CHECK-NEXT: addu16 a0, a1 230; CHECK-NEXT: rts16 231; 232; GENERIC-LABEL: mul_i8_65: 233; GENERIC: # %bb.0: # %entry 234; GENERIC-NEXT: .cfi_def_cfa_offset 0 235; GENERIC-NEXT: subi16 sp, sp, 4 236; GENERIC-NEXT: .cfi_def_cfa_offset 4 237; GENERIC-NEXT: lsli16 a1, a0, 6 238; GENERIC-NEXT: addu16 a0, a1, a0 239; GENERIC-NEXT: addi16 sp, sp, 4 240; GENERIC-NEXT: rts16 241entry: 242 %y = mul nsw i8 %x, 65 243 ret i8 %y 244} 245 246define i8 @mul_i8_63(i8 %x) { 247; CHECK-LABEL: mul_i8_63: 248; CHECK: # %bb.0: # %entry 249; CHECK-NEXT: lsli16 a1, a0, 6 250; CHECK-NEXT: subu16 a0, a1, a0 251; CHECK-NEXT: rts16 252; 253; GENERIC-LABEL: mul_i8_63: 254; GENERIC: # %bb.0: # %entry 255; GENERIC-NEXT: .cfi_def_cfa_offset 0 256; GENERIC-NEXT: subi16 sp, sp, 4 257; GENERIC-NEXT: .cfi_def_cfa_offset 4 258; GENERIC-NEXT: lsli16 a1, a0, 6 259; GENERIC-NEXT: subu16 a0, a1, a0 260; GENERIC-NEXT: addi16 sp, sp, 4 261; GENERIC-NEXT: rts16 262entry: 263 %y = mul nsw i8 %x, 63 264 ret i8 %y 265} 266 267define i8 @mul_i8_minus_63(i8 %x) { 268; CHECK-LABEL: mul_i8_minus_63: 269; CHECK: # %bb.0: # %entry 270; CHECK-NEXT: lsli16 a1, a0, 6 271; CHECK-NEXT: subu16 a0, a1 272; CHECK-NEXT: rts16 273; 274; GENERIC-LABEL: mul_i8_minus_63: 275; GENERIC: # %bb.0: # %entry 276; GENERIC-NEXT: .cfi_def_cfa_offset 0 277; GENERIC-NEXT: subi16 sp, sp, 4 278; GENERIC-NEXT: .cfi_def_cfa_offset 4 279; GENERIC-NEXT: lsli16 a1, a0, 6 280; GENERIC-NEXT: subu16 a0, a0, a1 281; GENERIC-NEXT: addi16 sp, sp, 4 282; GENERIC-NEXT: rts16 283entry: 284 %y = mul nsw i8 %x, -63 285 ret i8 %y 286} 287 288define i32 @mul_i32_minus_4097(i32 %x) { 289; CHECK-LABEL: mul_i32_minus_4097: 290; CHECK: # %bb.0: # %entry 291; CHECK-NEXT: movih32 a1, 65535 292; CHECK-NEXT: ori32 a1, a1, 61439 293; CHECK-NEXT: mult16 a0, a1 294; CHECK-NEXT: rts16 295; 296; GENERIC-LABEL: mul_i32_minus_4097: 297; GENERIC: # %bb.0: # %entry 298; GENERIC-NEXT: .cfi_def_cfa_offset 0 299; GENERIC-NEXT: subi16 sp, sp, 4 300; GENERIC-NEXT: .cfi_def_cfa_offset 4 301; GENERIC-NEXT: lsli16 a1, a0, 12 302; GENERIC-NEXT: addu16 a0, a1, a0 303; GENERIC-NEXT: movi16 a1, 0 304; GENERIC-NEXT: subu16 a0, a1, a0 305; GENERIC-NEXT: addi16 sp, sp, 4 306; GENERIC-NEXT: rts16 307entry: 308 %y = mul nsw i32 %x, -4097 309 ret i32 %y 310} 311 312define i16 @mul_i16_minus_4097(i16 %x) { 313; CHECK-LABEL: mul_i16_minus_4097: 314; CHECK: # %bb.0: # %entry 315; CHECK-NEXT: movih32 a1, 65535 316; CHECK-NEXT: ori32 a1, a1, 61439 317; CHECK-NEXT: mult16 a0, a1 318; CHECK-NEXT: rts16 319; 320; GENERIC-LABEL: mul_i16_minus_4097: 321; GENERIC: # %bb.0: # %entry 322; GENERIC-NEXT: .cfi_def_cfa_offset 0 323; GENERIC-NEXT: subi16 sp, sp, 4 324; GENERIC-NEXT: .cfi_def_cfa_offset 4 325; GENERIC-NEXT: lsli16 a1, a0, 12 326; GENERIC-NEXT: addu16 a0, a1, a0 327; GENERIC-NEXT: movi16 a1, 0 328; GENERIC-NEXT: subu16 a0, a1, a0 329; GENERIC-NEXT: addi16 sp, sp, 4 330; GENERIC-NEXT: rts16 331entry: 332 %y = mul nsw i16 %x, -4097 333 ret i16 %y 334} 335 336define i8 @mul_i8_minus_65(i8 %x) { 337; CHECK-LABEL: mul_i8_minus_65: 338; CHECK: # %bb.0: # %entry 339; CHECK-NEXT: movih32 a1, 65535 340; CHECK-NEXT: ori32 a1, a1, 65471 341; CHECK-NEXT: mult16 a0, a1 342; CHECK-NEXT: rts16 343; 344; GENERIC-LABEL: mul_i8_minus_65: 345; GENERIC: # %bb.0: # %entry 346; GENERIC-NEXT: .cfi_def_cfa_offset 0 347; GENERIC-NEXT: subi16 sp, sp, 4 348; GENERIC-NEXT: .cfi_def_cfa_offset 4 349; GENERIC-NEXT: lsli16 a1, a0, 6 350; GENERIC-NEXT: addu16 a0, a1, a0 351; GENERIC-NEXT: movi16 a1, 0 352; GENERIC-NEXT: subu16 a0, a1, a0 353; GENERIC-NEXT: addi16 sp, sp, 4 354; GENERIC-NEXT: rts16 355entry: 356 %y = mul nsw i8 %x, -65 357 ret i8 %y 358} 359 360;; This case can not be optimized, due to the data type exceeds. 361define i64 @mul_i64_4097(i64 %x) { 362; CHECK-LABEL: mul_i64_4097: 363; CHECK: # %bb.0: # %entry 364; CHECK-NEXT: subi16 sp, sp, 4 365; CHECK-NEXT: .cfi_def_cfa_offset 4 366; CHECK-NEXT: st32.w lr, (sp, 0) # 4-byte Folded Spill 367; CHECK-NEXT: .cfi_offset lr, -4 368; CHECK-NEXT: .cfi_def_cfa_offset 4 369; CHECK-NEXT: movi32 a2, 4097 370; CHECK-NEXT: movi16 a3, 0 371; CHECK-NEXT: jsri32 [.LCPI15_0] 372; CHECK-NEXT: ld32.w lr, (sp, 0) # 4-byte Folded Reload 373; CHECK-NEXT: addi16 sp, sp, 4 374; CHECK-NEXT: rts16 375; CHECK-NEXT: .p2align 1 376; CHECK-NEXT: # %bb.1: 377; CHECK-NEXT: .p2align 2, 0x0 378; CHECK-NEXT: .LCPI15_0: 379; CHECK-NEXT: .long __muldi3 380; 381; GENERIC-LABEL: mul_i64_4097: 382; GENERIC: # %bb.0: # %entry 383; GENERIC-NEXT: subi16 sp, sp, 8 384; GENERIC-NEXT: .cfi_def_cfa_offset 8 385; GENERIC-NEXT: st16.w l0, (sp, 4) # 4-byte Folded Spill 386; GENERIC-NEXT: st32.w lr, (sp, 0) # 4-byte Folded Spill 387; GENERIC-NEXT: .cfi_offset l0, -4 388; GENERIC-NEXT: .cfi_offset lr, -8 389; GENERIC-NEXT: subi16 sp, sp, 4 390; GENERIC-NEXT: .cfi_def_cfa_offset 12 391; GENERIC-NEXT: movi16 a2, 0 392; GENERIC-NEXT: lsli16 a3, a2, 24 393; GENERIC-NEXT: lsli16 a2, a2, 16 394; GENERIC-NEXT: or16 a2, a3 395; GENERIC-NEXT: movi16 a3, 16 396; GENERIC-NEXT: lsli16 a3, a3, 8 397; GENERIC-NEXT: or16 a3, a2 398; GENERIC-NEXT: movi16 a2, 1 399; GENERIC-NEXT: or16 a2, a3 400; GENERIC-NEXT: lrw32 l0, [.LCPI15_0] 401; GENERIC-NEXT: movi16 a3, 0 402; GENERIC-NEXT: jsr16 l0 403; GENERIC-NEXT: addi16 sp, sp, 4 404; GENERIC-NEXT: ld32.w lr, (sp, 0) # 4-byte Folded Reload 405; GENERIC-NEXT: ld16.w l0, (sp, 4) # 4-byte Folded Reload 406; GENERIC-NEXT: addi16 sp, sp, 8 407; GENERIC-NEXT: rts16 408; GENERIC-NEXT: .p2align 1 409; GENERIC-NEXT: # %bb.1: 410; GENERIC-NEXT: .p2align 2, 0x0 411; GENERIC-NEXT: .LCPI15_0: 412; GENERIC-NEXT: .long __muldi3 413entry: 414 %y = mul nsw i64 %x, 4097 415 ret i64 %y 416} 417