1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+slow-lea,+slow-3ops-lea,+sse,+sse2 | FileCheck %s --check-prefixes=ALL,X32 3; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+slow-lea,+slow-3ops-lea,+sse,+sse2 | FileCheck %s --check-prefixes=ALL,X64 4 5; Scalar tests. Trying to avoid LEA here, so the output is actually readable.. 6 7; add (add %x, C), %y 8; Outer 'add' is commutative - 2 variants. 9 10define i32 @sink_add_of_const_to_add0(i32 %a, i32 %b) { 11; X32-LABEL: sink_add_of_const_to_add0: 12; X32: # %bb.0: 13; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 14; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx 15; X32-NEXT: addl %ecx, %eax 16; X32-NEXT: addl $32, %eax 17; X32-NEXT: retl 18; 19; X64-LABEL: sink_add_of_const_to_add0: 20; X64: # %bb.0: 21; X64-NEXT: # kill: def $esi killed $esi def $rsi 22; X64-NEXT: # kill: def $edi killed $edi def $rdi 23; X64-NEXT: leal 32(%rdi,%rsi), %eax 24; X64-NEXT: retq 25 %t0 = add i32 %a, 32 ; constant always on RHS 26 %r = add i32 %t0, %b 27 ret i32 %r 28} 29define i32 @sink_add_of_const_to_add1(i32 %a, i32 %b) { 30; X32-LABEL: sink_add_of_const_to_add1: 31; X32: # %bb.0: 32; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 33; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx 34; X32-NEXT: addl %ecx, %eax 35; X32-NEXT: addl $32, %eax 36; X32-NEXT: retl 37; 38; X64-LABEL: sink_add_of_const_to_add1: 39; X64: # %bb.0: 40; X64-NEXT: # kill: def $esi killed $esi def $rsi 41; X64-NEXT: # kill: def $edi killed $edi def $rdi 42; X64-NEXT: leal 32(%rdi,%rsi), %eax 43; X64-NEXT: retq 44 %t0 = add i32 %a, 32 ; constant always on RHS 45 %r = add i32 %b, %t0 46 ret i32 %r 47} 48 49; add (sub %x, C), %y 50; Outer 'add' is commutative - 2 variants. 51 52define i32 @sink_sub_of_const_to_add0(i32 %a, i32 %b) { 53; X32-LABEL: sink_sub_of_const_to_add0: 54; X32: # %bb.0: 55; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 56; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx 57; X32-NEXT: addl %ecx, %eax 58; X32-NEXT: addl $-32, %eax 59; X32-NEXT: retl 60; 61; X64-LABEL: sink_sub_of_const_to_add0: 62; X64: # %bb.0: 63; X64-NEXT: # kill: def $esi killed $esi def $rsi 64; X64-NEXT: # kill: def $edi killed $edi def $rdi 65; X64-NEXT: leal -32(%rdi,%rsi), %eax 66; X64-NEXT: retq 67 %t0 = sub i32 %a, 32 68 %r = add i32 %t0, %b 69 ret i32 %r 70} 71define i32 @sink_sub_of_const_to_add1(i32 %a, i32 %b) { 72; X32-LABEL: sink_sub_of_const_to_add1: 73; X32: # %bb.0: 74; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 75; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx 76; X32-NEXT: addl %ecx, %eax 77; X32-NEXT: addl $-32, %eax 78; X32-NEXT: retl 79; 80; X64-LABEL: sink_sub_of_const_to_add1: 81; X64: # %bb.0: 82; X64-NEXT: # kill: def $esi killed $esi def $rsi 83; X64-NEXT: # kill: def $edi killed $edi def $rdi 84; X64-NEXT: leal -32(%rdi,%rsi), %eax 85; X64-NEXT: retq 86 %t0 = sub i32 %a, 32 87 %r = add i32 %b, %t0 88 ret i32 %r 89} 90 91; add (sub C, %x), %y 92; Outer 'add' is commutative - 2 variants. 93 94define i32 @sink_sub_from_const_to_add0(i32 %a, i32 %b) { 95; X32-LABEL: sink_sub_from_const_to_add0: 96; X32: # %bb.0: 97; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 98; X32-NEXT: subl {{[0-9]+}}(%esp), %eax 99; X32-NEXT: addl $32, %eax 100; X32-NEXT: retl 101; 102; X64-LABEL: sink_sub_from_const_to_add0: 103; X64: # %bb.0: 104; X64-NEXT: # kill: def $esi killed $esi def $rsi 105; X64-NEXT: subl %edi, %esi 106; X64-NEXT: leal 32(%rsi), %eax 107; X64-NEXT: retq 108 %t0 = sub i32 32, %a 109 %r = add i32 %t0, %b 110 ret i32 %r 111} 112define i32 @sink_sub_from_const_to_add1(i32 %a, i32 %b) { 113; X32-LABEL: sink_sub_from_const_to_add1: 114; X32: # %bb.0: 115; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 116; X32-NEXT: subl {{[0-9]+}}(%esp), %eax 117; X32-NEXT: addl $32, %eax 118; X32-NEXT: retl 119; 120; X64-LABEL: sink_sub_from_const_to_add1: 121; X64: # %bb.0: 122; X64-NEXT: # kill: def $esi killed $esi def $rsi 123; X64-NEXT: subl %edi, %esi 124; X64-NEXT: leal 32(%rsi), %eax 125; X64-NEXT: retq 126 %t0 = sub i32 32, %a 127 %r = add i32 %b, %t0 128 ret i32 %r 129} 130 131; sub (add %x, C), %y 132; sub %y, (add %x, C) 133 134define i32 @sink_add_of_const_to_sub(i32 %a, i32 %b) { 135; X32-LABEL: sink_add_of_const_to_sub: 136; X32: # %bb.0: 137; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 138; X32-NEXT: subl {{[0-9]+}}(%esp), %eax 139; X32-NEXT: addl $32, %eax 140; X32-NEXT: retl 141; 142; X64-LABEL: sink_add_of_const_to_sub: 143; X64: # %bb.0: 144; X64-NEXT: # kill: def $edi killed $edi def $rdi 145; X64-NEXT: subl %esi, %edi 146; X64-NEXT: leal 32(%rdi), %eax 147; X64-NEXT: retq 148 %t0 = add i32 %a, 32 ; constant always on RHS 149 %r = sub i32 %t0, %b 150 ret i32 %r 151} 152define i32 @sink_add_of_const_to_sub2(i32 %a, i32 %b) { 153; X32-LABEL: sink_add_of_const_to_sub2: 154; X32: # %bb.0: 155; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 156; X32-NEXT: subl {{[0-9]+}}(%esp), %eax 157; X32-NEXT: addl $-32, %eax 158; X32-NEXT: retl 159; 160; X64-LABEL: sink_add_of_const_to_sub2: 161; X64: # %bb.0: 162; X64-NEXT: # kill: def $esi killed $esi def $rsi 163; X64-NEXT: subl %edi, %esi 164; X64-NEXT: leal -32(%rsi), %eax 165; X64-NEXT: retq 166 %t0 = add i32 %a, 32 ; constant always on RHS 167 %r = sub i32 %b, %t0 168 ret i32 %r 169} 170 171; sub (sub %x, C), %y 172; sub %y, (sub %x, C) 173 174define i32 @sink_sub_of_const_to_sub(i32 %a, i32 %b) { 175; X32-LABEL: sink_sub_of_const_to_sub: 176; X32: # %bb.0: 177; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 178; X32-NEXT: subl {{[0-9]+}}(%esp), %eax 179; X32-NEXT: addl $-32, %eax 180; X32-NEXT: retl 181; 182; X64-LABEL: sink_sub_of_const_to_sub: 183; X64: # %bb.0: 184; X64-NEXT: # kill: def $edi killed $edi def $rdi 185; X64-NEXT: subl %esi, %edi 186; X64-NEXT: leal -32(%rdi), %eax 187; X64-NEXT: retq 188 %t0 = sub i32 %a, 32 189 %r = sub i32 %t0, %b 190 ret i32 %r 191} 192define i32 @sink_sub_of_const_to_sub2(i32 %a, i32 %b) { 193; X32-LABEL: sink_sub_of_const_to_sub2: 194; X32: # %bb.0: 195; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 196; X32-NEXT: subl {{[0-9]+}}(%esp), %eax 197; X32-NEXT: addl $32, %eax 198; X32-NEXT: retl 199; 200; X64-LABEL: sink_sub_of_const_to_sub2: 201; X64: # %bb.0: 202; X64-NEXT: # kill: def $esi killed $esi def $rsi 203; X64-NEXT: subl %edi, %esi 204; X64-NEXT: leal 32(%rsi), %eax 205; X64-NEXT: retq 206 %t0 = sub i32 %a, 32 207 %r = sub i32 %b, %t0 208 ret i32 %r 209} 210 211; sub (sub C, %x), %y 212; sub %y, (sub C, %x) 213 214define i32 @sink_sub_from_const_to_sub(i32 %a, i32 %b) { 215; X32-LABEL: sink_sub_from_const_to_sub: 216; X32: # %bb.0: 217; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx 218; X32-NEXT: addl {{[0-9]+}}(%esp), %ecx 219; X32-NEXT: movl $32, %eax 220; X32-NEXT: subl %ecx, %eax 221; X32-NEXT: retl 222; 223; X64-LABEL: sink_sub_from_const_to_sub: 224; X64: # %bb.0: 225; X64-NEXT: addl %esi, %edi 226; X64-NEXT: movl $32, %eax 227; X64-NEXT: subl %edi, %eax 228; X64-NEXT: retq 229 %t0 = sub i32 32, %a 230 %r = sub i32 %t0, %b 231 ret i32 %r 232} 233define i32 @sink_sub_from_const_to_sub2(i32 %a, i32 %b) { 234; X32-LABEL: sink_sub_from_const_to_sub2: 235; X32: # %bb.0: 236; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 237; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx 238; X32-NEXT: addl %ecx, %eax 239; X32-NEXT: addl $-32, %eax 240; X32-NEXT: retl 241; 242; X64-LABEL: sink_sub_from_const_to_sub2: 243; X64: # %bb.0: 244; X64-NEXT: # kill: def $esi killed $esi def $rsi 245; X64-NEXT: # kill: def $edi killed $edi def $rdi 246; X64-NEXT: leal -32(%rdi,%rsi), %eax 247; X64-NEXT: retq 248 %t0 = sub i32 32, %a 249 %r = sub i32 %b, %t0 250 ret i32 %r 251} 252 253;------------------------------------------------------------------------------; 254; Basic vector tests. Here it is easier to see where the constant operand is. 255;------------------------------------------------------------------------------; 256 257; add (add %x, C), %y 258; Outer 'add' is commutative - 2 variants. 259 260define <4 x i32> @vec_sink_add_of_const_to_add0(<4 x i32> %a, <4 x i32> %b) { 261; X32-LABEL: vec_sink_add_of_const_to_add0: 262; X32: # %bb.0: 263; X32-NEXT: paddd %xmm1, %xmm0 264; X32-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0 265; X32-NEXT: retl 266; 267; X64-LABEL: vec_sink_add_of_const_to_add0: 268; X64: # %bb.0: 269; X64-NEXT: paddd %xmm1, %xmm0 270; X64-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 271; X64-NEXT: retq 272 %t0 = add <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46> ; constant always on RHS 273 %r = add <4 x i32> %t0, %b 274 ret <4 x i32> %r 275} 276define <4 x i32> @vec_sink_add_of_const_to_add1(<4 x i32> %a, <4 x i32> %b) { 277; X32-LABEL: vec_sink_add_of_const_to_add1: 278; X32: # %bb.0: 279; X32-NEXT: paddd %xmm1, %xmm0 280; X32-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0 281; X32-NEXT: retl 282; 283; X64-LABEL: vec_sink_add_of_const_to_add1: 284; X64: # %bb.0: 285; X64-NEXT: paddd %xmm1, %xmm0 286; X64-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 287; X64-NEXT: retq 288 %t0 = add <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46> ; constant always on RHS 289 %r = add <4 x i32> %b, %t0 290 ret <4 x i32> %r 291} 292 293; add (sub %x, C), %y 294; Outer 'add' is commutative - 2 variants. 295 296define <4 x i32> @vec_sink_sub_of_const_to_add0(<4 x i32> %a, <4 x i32> %b) { 297; X32-LABEL: vec_sink_sub_of_const_to_add0: 298; X32: # %bb.0: 299; X32-NEXT: paddd %xmm1, %xmm0 300; X32-NEXT: psubd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0 301; X32-NEXT: retl 302; 303; X64-LABEL: vec_sink_sub_of_const_to_add0: 304; X64: # %bb.0: 305; X64-NEXT: paddd %xmm1, %xmm0 306; X64-NEXT: psubd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 307; X64-NEXT: retq 308 %t0 = sub <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46> 309 %r = add <4 x i32> %t0, %b 310 ret <4 x i32> %r 311} 312define <4 x i32> @vec_sink_sub_of_const_to_add1(<4 x i32> %a, <4 x i32> %b) { 313; X32-LABEL: vec_sink_sub_of_const_to_add1: 314; X32: # %bb.0: 315; X32-NEXT: paddd %xmm1, %xmm0 316; X32-NEXT: psubd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0 317; X32-NEXT: retl 318; 319; X64-LABEL: vec_sink_sub_of_const_to_add1: 320; X64: # %bb.0: 321; X64-NEXT: paddd %xmm1, %xmm0 322; X64-NEXT: psubd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 323; X64-NEXT: retq 324 %t0 = sub <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46> 325 %r = add <4 x i32> %b, %t0 326 ret <4 x i32> %r 327} 328 329; add (sub C, %x), %y 330; Outer 'add' is commutative - 2 variants. 331 332define <4 x i32> @vec_sink_sub_from_const_to_add0(<4 x i32> %a, <4 x i32> %b) { 333; X32-LABEL: vec_sink_sub_from_const_to_add0: 334; X32: # %bb.0: 335; X32-NEXT: psubd %xmm0, %xmm1 336; X32-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm1 337; X32-NEXT: movdqa %xmm1, %xmm0 338; X32-NEXT: retl 339; 340; X64-LABEL: vec_sink_sub_from_const_to_add0: 341; X64: # %bb.0: 342; X64-NEXT: psubd %xmm0, %xmm1 343; X64-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1 344; X64-NEXT: movdqa %xmm1, %xmm0 345; X64-NEXT: retq 346 %t0 = sub <4 x i32> <i32 42, i32 24, i32 undef, i32 46>, %a 347 %r = add <4 x i32> %t0, %b 348 ret <4 x i32> %r 349} 350define <4 x i32> @vec_sink_sub_from_const_to_add1(<4 x i32> %a, <4 x i32> %b) { 351; X32-LABEL: vec_sink_sub_from_const_to_add1: 352; X32: # %bb.0: 353; X32-NEXT: psubd %xmm0, %xmm1 354; X32-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm1 355; X32-NEXT: movdqa %xmm1, %xmm0 356; X32-NEXT: retl 357; 358; X64-LABEL: vec_sink_sub_from_const_to_add1: 359; X64: # %bb.0: 360; X64-NEXT: psubd %xmm0, %xmm1 361; X64-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1 362; X64-NEXT: movdqa %xmm1, %xmm0 363; X64-NEXT: retq 364 %t0 = sub <4 x i32> <i32 42, i32 24, i32 undef, i32 46>, %a 365 %r = add <4 x i32> %b, %t0 366 ret <4 x i32> %r 367} 368 369; sub (add %x, C), %y 370; sub %y, (add %x, C) 371 372define <4 x i32> @vec_sink_add_of_const_to_sub(<4 x i32> %a, <4 x i32> %b) { 373; X32-LABEL: vec_sink_add_of_const_to_sub: 374; X32: # %bb.0: 375; X32-NEXT: psubd %xmm1, %xmm0 376; X32-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0 377; X32-NEXT: retl 378; 379; X64-LABEL: vec_sink_add_of_const_to_sub: 380; X64: # %bb.0: 381; X64-NEXT: psubd %xmm1, %xmm0 382; X64-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 383; X64-NEXT: retq 384 %t0 = add <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46> ; constant always on RHS 385 %r = sub <4 x i32> %t0, %b 386 ret <4 x i32> %r 387} 388define <4 x i32> @vec_sink_add_of_const_to_sub2(<4 x i32> %a, <4 x i32> %b) { 389; X32-LABEL: vec_sink_add_of_const_to_sub2: 390; X32: # %bb.0: 391; X32-NEXT: psubd %xmm0, %xmm1 392; X32-NEXT: psubd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm1 393; X32-NEXT: movdqa %xmm1, %xmm0 394; X32-NEXT: retl 395; 396; X64-LABEL: vec_sink_add_of_const_to_sub2: 397; X64: # %bb.0: 398; X64-NEXT: psubd %xmm0, %xmm1 399; X64-NEXT: psubd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1 400; X64-NEXT: movdqa %xmm1, %xmm0 401; X64-NEXT: retq 402 %t0 = add <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46> ; constant always on RHS 403 %r = sub <4 x i32> %b, %t0 404 ret <4 x i32> %r 405} 406 407; sub (sub %x, C), %y 408; sub %y, (sub %x, C) 409 410define <4 x i32> @vec_sink_sub_of_const_to_sub(<4 x i32> %a, <4 x i32> %b) { 411; X32-LABEL: vec_sink_sub_of_const_to_sub: 412; X32: # %bb.0: 413; X32-NEXT: psubd %xmm1, %xmm0 414; X32-NEXT: psubd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0 415; X32-NEXT: retl 416; 417; X64-LABEL: vec_sink_sub_of_const_to_sub: 418; X64: # %bb.0: 419; X64-NEXT: psubd %xmm1, %xmm0 420; X64-NEXT: psubd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 421; X64-NEXT: retq 422 %t0 = sub <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46> 423 %r = sub <4 x i32> %t0, %b 424 ret <4 x i32> %r 425} 426define <4 x i32> @vec_sink_sub_of_const_to_sub2(<4 x i32> %a, <4 x i32> %b) { 427; X32-LABEL: vec_sink_sub_of_const_to_sub2: 428; X32: # %bb.0: 429; X32-NEXT: psubd %xmm0, %xmm1 430; X32-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm1 431; X32-NEXT: movdqa %xmm1, %xmm0 432; X32-NEXT: retl 433; 434; X64-LABEL: vec_sink_sub_of_const_to_sub2: 435; X64: # %bb.0: 436; X64-NEXT: psubd %xmm0, %xmm1 437; X64-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1 438; X64-NEXT: movdqa %xmm1, %xmm0 439; X64-NEXT: retq 440 %t0 = sub <4 x i32> %a, <i32 42, i32 24, i32 undef, i32 46> 441 %r = sub <4 x i32> %b, %t0 442 ret <4 x i32> %r 443} 444 445; sub (sub C, %x), %y 446; sub %y, (sub C, %x) 447 448define <4 x i32> @vec_sink_sub_from_const_to_sub(<4 x i32> %a, <4 x i32> %b) { 449; ALL-LABEL: vec_sink_sub_from_const_to_sub: 450; ALL: # %bb.0: 451; ALL-NEXT: movdqa {{.*#+}} xmm2 = [42,24,u,46] 452; ALL-NEXT: paddd %xmm1, %xmm0 453; ALL-NEXT: psubd %xmm0, %xmm2 454; ALL-NEXT: movdqa %xmm2, %xmm0 455; ALL-NEXT: ret{{[l|q]}} 456 %t0 = sub <4 x i32> <i32 42, i32 24, i32 undef, i32 46>, %a 457 %r = sub <4 x i32> %t0, %b 458 ret <4 x i32> %r 459} 460define <4 x i32> @vec_sink_sub_from_const_to_sub2(<4 x i32> %a, <4 x i32> %b) { 461; X32-LABEL: vec_sink_sub_from_const_to_sub2: 462; X32: # %bb.0: 463; X32-NEXT: paddd %xmm1, %xmm0 464; X32-NEXT: psubd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0 465; X32-NEXT: retl 466; 467; X64-LABEL: vec_sink_sub_from_const_to_sub2: 468; X64: # %bb.0: 469; X64-NEXT: paddd %xmm1, %xmm0 470; X64-NEXT: psubd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 471; X64-NEXT: retq 472 %t0 = sub <4 x i32> <i32 42, i32 24, i32 undef, i32 46>, %a 473 %r = sub <4 x i32> %b, %t0 474 ret <4 x i32> %r 475} 476