1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=x86_64-linux | FileCheck %s -check-prefix=CHECK -check-prefix=ENABLED 3; RUN: llc --disable-x86-lea-opt < %s -mtriple=x86_64-linux | FileCheck %s -check-prefix=CHECK -check-prefix=DISABLED 4 5%struct.anon1 = type { i32, i32, i32 } 6%struct.anon2 = type { i32, [32 x i32], i32 } 7 8@arr1 = external global [65 x %struct.anon1], align 16 9@arr2 = external global [65 x %struct.anon2], align 16 10 11define void @test1(i64 %x) nounwind { 12; ENABLED-LABEL: test1: 13; ENABLED: # %bb.0: # %entry 14; ENABLED-NEXT: shlq $2, %rdi 15; ENABLED-NEXT: movl arr1(%rdi,%rdi,2), %ecx 16; ENABLED-NEXT: leaq arr1+4(%rdi,%rdi,2), %rax 17; ENABLED-NEXT: subl arr1+4(%rdi,%rdi,2), %ecx 18; ENABLED-NEXT: addl arr1+8(%rdi,%rdi,2), %ecx 19; ENABLED-NEXT: cmpl $2, %ecx 20; ENABLED-NEXT: je .LBB0_3 21; ENABLED-NEXT: # %bb.1: # %entry 22; ENABLED-NEXT: cmpl $1, %ecx 23; ENABLED-NEXT: jne .LBB0_4 24; ENABLED-NEXT: # %bb.2: # %sw.bb.1 25; ENABLED-NEXT: movl $111, (%rax) 26; ENABLED-NEXT: movl $222, 4(%rax) 27; ENABLED-NEXT: retq 28; ENABLED-NEXT: .LBB0_3: # %sw.bb.2 29; ENABLED-NEXT: movl $333, (%rax) # imm = 0x14D 30; ENABLED-NEXT: movl $444, 4(%rax) # imm = 0x1BC 31; ENABLED-NEXT: .LBB0_4: # %sw.epilog 32; ENABLED-NEXT: retq 33; 34; DISABLED-LABEL: test1: 35; DISABLED: # %bb.0: # %entry 36; DISABLED-NEXT: shlq $2, %rdi 37; DISABLED-NEXT: movl arr1(%rdi,%rdi,2), %edx 38; DISABLED-NEXT: leaq arr1+4(%rdi,%rdi,2), %rax 39; DISABLED-NEXT: subl arr1+4(%rdi,%rdi,2), %edx 40; DISABLED-NEXT: leaq arr1+8(%rdi,%rdi,2), %rcx 41; DISABLED-NEXT: addl arr1+8(%rdi,%rdi,2), %edx 42; DISABLED-NEXT: cmpl $2, %edx 43; DISABLED-NEXT: je .LBB0_3 44; DISABLED-NEXT: # %bb.1: # %entry 45; DISABLED-NEXT: cmpl $1, %edx 46; DISABLED-NEXT: jne .LBB0_4 47; DISABLED-NEXT: # %bb.2: # %sw.bb.1 48; DISABLED-NEXT: movl $111, (%rax) 49; DISABLED-NEXT: movl $222, (%rcx) 50; DISABLED-NEXT: retq 51; DISABLED-NEXT: .LBB0_3: # %sw.bb.2 52; DISABLED-NEXT: movl $333, (%rax) # imm = 0x14D 53; DISABLED-NEXT: movl $444, (%rcx) # imm = 0x1BC 54; DISABLED-NEXT: .LBB0_4: # %sw.epilog 55; DISABLED-NEXT: retq 56entry: 57 %a = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 0 58 %tmp = load i32, i32* %a, align 4 59 %b = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 1 60 %tmp1 = load i32, i32* %b, align 4 61 %sub = sub i32 %tmp, %tmp1 62 %c = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 2 63 %tmp2 = load i32, i32* %c, align 4 64 %add = add nsw i32 %sub, %tmp2 65 switch i32 %add, label %sw.epilog [ 66 i32 1, label %sw.bb.1 67 i32 2, label %sw.bb.2 68 ] 69 70sw.bb.1: ; preds = %entry 71 store i32 111, i32* %b, align 4 72 store i32 222, i32* %c, align 4 73 br label %sw.epilog 74 75sw.bb.2: ; preds = %entry 76 store i32 333, i32* %b, align 4 77 store i32 444, i32* %c, align 4 78 br label %sw.epilog 79 80sw.epilog: ; preds = %sw.bb.2, %sw.bb.1, %entry 81 ret void 82} 83 84define void @test2(i64 %x) nounwind optsize { 85; ENABLED-LABEL: test2: 86; ENABLED: # %bb.0: # %entry 87; ENABLED-NEXT: shlq $2, %rdi 88; ENABLED-NEXT: leaq arr1+4(%rdi,%rdi,2), %rax 89; ENABLED-NEXT: movl -4(%rax), %ecx 90; ENABLED-NEXT: subl (%rax), %ecx 91; ENABLED-NEXT: addl 4(%rax), %ecx 92; ENABLED-NEXT: cmpl $2, %ecx 93; ENABLED-NEXT: je .LBB1_3 94; ENABLED-NEXT: # %bb.1: # %entry 95; ENABLED-NEXT: cmpl $1, %ecx 96; ENABLED-NEXT: jne .LBB1_4 97; ENABLED-NEXT: # %bb.2: # %sw.bb.1 98; ENABLED-NEXT: movl $111, (%rax) 99; ENABLED-NEXT: movl $222, 4(%rax) 100; ENABLED-NEXT: retq 101; ENABLED-NEXT: .LBB1_3: # %sw.bb.2 102; ENABLED-NEXT: movl $333, (%rax) # imm = 0x14D 103; ENABLED-NEXT: movl $444, 4(%rax) # imm = 0x1BC 104; ENABLED-NEXT: .LBB1_4: # %sw.epilog 105; ENABLED-NEXT: retq 106; 107; DISABLED-LABEL: test2: 108; DISABLED: # %bb.0: # %entry 109; DISABLED-NEXT: shlq $2, %rdi 110; DISABLED-NEXT: movl arr1(%rdi,%rdi,2), %edx 111; DISABLED-NEXT: leaq arr1+4(%rdi,%rdi,2), %rax 112; DISABLED-NEXT: subl arr1+4(%rdi,%rdi,2), %edx 113; DISABLED-NEXT: leaq arr1+8(%rdi,%rdi,2), %rcx 114; DISABLED-NEXT: addl arr1+8(%rdi,%rdi,2), %edx 115; DISABLED-NEXT: cmpl $2, %edx 116; DISABLED-NEXT: je .LBB1_3 117; DISABLED-NEXT: # %bb.1: # %entry 118; DISABLED-NEXT: cmpl $1, %edx 119; DISABLED-NEXT: jne .LBB1_4 120; DISABLED-NEXT: # %bb.2: # %sw.bb.1 121; DISABLED-NEXT: movl $111, (%rax) 122; DISABLED-NEXT: movl $222, (%rcx) 123; DISABLED-NEXT: retq 124; DISABLED-NEXT: .LBB1_3: # %sw.bb.2 125; DISABLED-NEXT: movl $333, (%rax) # imm = 0x14D 126; DISABLED-NEXT: movl $444, (%rcx) # imm = 0x1BC 127; DISABLED-NEXT: .LBB1_4: # %sw.epilog 128; DISABLED-NEXT: retq 129entry: 130 %a = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 0 131 %tmp = load i32, i32* %a, align 4 132 %b = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 1 133 %tmp1 = load i32, i32* %b, align 4 134 %sub = sub i32 %tmp, %tmp1 135 %c = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 2 136 %tmp2 = load i32, i32* %c, align 4 137 %add = add nsw i32 %sub, %tmp2 138 switch i32 %add, label %sw.epilog [ 139 i32 1, label %sw.bb.1 140 i32 2, label %sw.bb.2 141 ] 142 143sw.bb.1: ; preds = %entry 144 store i32 111, i32* %b, align 4 145 store i32 222, i32* %c, align 4 146 br label %sw.epilog 147 148sw.bb.2: ; preds = %entry 149 store i32 333, i32* %b, align 4 150 store i32 444, i32* %c, align 4 151 br label %sw.epilog 152 153sw.epilog: ; preds = %sw.bb.2, %sw.bb.1, %entry 154 ret void 155} 156 157; Check that LEA optimization pass takes into account a resultant address 158; displacement when choosing a LEA instruction for replacing a redundant 159; address recalculation. 160 161define void @test3(i64 %x) nounwind optsize { 162; ENABLED-LABEL: test3: 163; ENABLED: # %bb.0: # %entry 164; ENABLED-NEXT: movq %rdi, %rax 165; ENABLED-NEXT: shlq $7, %rax 166; ENABLED-NEXT: leaq arr2+132(%rax,%rdi,8), %rcx 167; ENABLED-NEXT: leaq arr2(%rax,%rdi,8), %rax 168; ENABLED-NEXT: movl (%rcx), %edx 169; ENABLED-NEXT: addl (%rax), %edx 170; ENABLED-NEXT: cmpl $2, %edx 171; ENABLED-NEXT: je .LBB2_3 172; ENABLED-NEXT: # %bb.1: # %entry 173; ENABLED-NEXT: cmpl $1, %edx 174; ENABLED-NEXT: jne .LBB2_4 175; ENABLED-NEXT: # %bb.2: # %sw.bb.1 176; ENABLED-NEXT: movl $111, (%rcx) 177; ENABLED-NEXT: movl $222, (%rax) 178; ENABLED-NEXT: retq 179; ENABLED-NEXT: .LBB2_3: # %sw.bb.2 180; ENABLED-NEXT: movl $333, (%rcx) # imm = 0x14D 181; ENABLED-NEXT: movl %eax, (%rax) 182; ENABLED-NEXT: .LBB2_4: # %sw.epilog 183; ENABLED-NEXT: retq 184; 185; DISABLED-LABEL: test3: 186; DISABLED: # %bb.0: # %entry 187; DISABLED-NEXT: movq %rdi, %rsi 188; DISABLED-NEXT: shlq $7, %rsi 189; DISABLED-NEXT: leaq arr2+132(%rsi,%rdi,8), %rcx 190; DISABLED-NEXT: leaq arr2(%rsi,%rdi,8), %rax 191; DISABLED-NEXT: movl arr2+132(%rsi,%rdi,8), %edx 192; DISABLED-NEXT: addl arr2(%rsi,%rdi,8), %edx 193; DISABLED-NEXT: cmpl $2, %edx 194; DISABLED-NEXT: je .LBB2_3 195; DISABLED-NEXT: # %bb.1: # %entry 196; DISABLED-NEXT: cmpl $1, %edx 197; DISABLED-NEXT: jne .LBB2_4 198; DISABLED-NEXT: # %bb.2: # %sw.bb.1 199; DISABLED-NEXT: movl $111, (%rcx) 200; DISABLED-NEXT: movl $222, (%rax) 201; DISABLED-NEXT: retq 202; DISABLED-NEXT: .LBB2_3: # %sw.bb.2 203; DISABLED-NEXT: movl $333, (%rcx) # imm = 0x14D 204; DISABLED-NEXT: movl %eax, (%rax) 205; DISABLED-NEXT: .LBB2_4: # %sw.epilog 206; DISABLED-NEXT: retq 207entry: 208 %a = getelementptr inbounds [65 x %struct.anon2], [65 x %struct.anon2]* @arr2, i64 0, i64 %x, i32 2 209 %tmp = load i32, i32* %a, align 4 210 %b = getelementptr inbounds [65 x %struct.anon2], [65 x %struct.anon2]* @arr2, i64 0, i64 %x, i32 0 211 %tmp1 = load i32, i32* %b, align 4 212 %add = add nsw i32 %tmp, %tmp1 213 switch i32 %add, label %sw.epilog [ 214 i32 1, label %sw.bb.1 215 i32 2, label %sw.bb.2 216 ] 217 218sw.bb.1: ; preds = %entry 219 store i32 111, i32* %a, align 4 220 store i32 222, i32* %b, align 4 221 br label %sw.epilog 222 223sw.bb.2: ; preds = %entry 224 store i32 333, i32* %a, align 4 225 ; Make sure the REG3's definition LEA won't be removed as redundant. 226 %cvt = ptrtoint i32* %b to i32 227 store i32 %cvt, i32* %b, align 4 228 br label %sw.epilog 229 230sw.epilog: ; preds = %sw.bb.2, %sw.bb.1, %entry 231 ret void 232 233; REG3's definition is closer to movl than REG2's, but the pass still chooses 234; REG2 because it provides the resultant address displacement fitting 1 byte. 235 236} 237 238define void @test4(i64 %x) nounwind minsize { 239; ENABLED-LABEL: test4: 240; ENABLED: # %bb.0: # %entry 241; ENABLED-NEXT: imulq $12, %rdi, %rax 242; ENABLED-NEXT: leaq arr1+4(%rax), %rax 243; ENABLED-NEXT: movl -4(%rax), %ecx 244; ENABLED-NEXT: subl (%rax), %ecx 245; ENABLED-NEXT: addl 4(%rax), %ecx 246; ENABLED-NEXT: cmpl $2, %ecx 247; ENABLED-NEXT: je .LBB3_3 248; ENABLED-NEXT: # %bb.1: # %entry 249; ENABLED-NEXT: cmpl $1, %ecx 250; ENABLED-NEXT: jne .LBB3_4 251; ENABLED-NEXT: # %bb.2: # %sw.bb.1 252; ENABLED-NEXT: movl $111, (%rax) 253; ENABLED-NEXT: movl $222, 4(%rax) 254; ENABLED-NEXT: retq 255; ENABLED-NEXT: .LBB3_3: # %sw.bb.2 256; ENABLED-NEXT: movl $333, (%rax) # imm = 0x14D 257; ENABLED-NEXT: movl $444, 4(%rax) # imm = 0x1BC 258; ENABLED-NEXT: .LBB3_4: # %sw.epilog 259; ENABLED-NEXT: retq 260; 261; DISABLED-LABEL: test4: 262; DISABLED: # %bb.0: # %entry 263; DISABLED-NEXT: imulq $12, %rdi, %rsi 264; DISABLED-NEXT: movl arr1(%rsi), %edx 265; DISABLED-NEXT: leaq arr1+4(%rsi), %rax 266; DISABLED-NEXT: subl arr1+4(%rsi), %edx 267; DISABLED-NEXT: leaq arr1+8(%rsi), %rcx 268; DISABLED-NEXT: addl arr1+8(%rsi), %edx 269; DISABLED-NEXT: cmpl $2, %edx 270; DISABLED-NEXT: je .LBB3_3 271; DISABLED-NEXT: # %bb.1: # %entry 272; DISABLED-NEXT: cmpl $1, %edx 273; DISABLED-NEXT: jne .LBB3_4 274; DISABLED-NEXT: # %bb.2: # %sw.bb.1 275; DISABLED-NEXT: movl $111, (%rax) 276; DISABLED-NEXT: movl $222, (%rcx) 277; DISABLED-NEXT: retq 278; DISABLED-NEXT: .LBB3_3: # %sw.bb.2 279; DISABLED-NEXT: movl $333, (%rax) # imm = 0x14D 280; DISABLED-NEXT: movl $444, (%rcx) # imm = 0x1BC 281; DISABLED-NEXT: .LBB3_4: # %sw.epilog 282; DISABLED-NEXT: retq 283entry: 284 %a = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 0 285 %tmp = load i32, i32* %a, align 4 286 %b = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 1 287 %tmp1 = load i32, i32* %b, align 4 288 %sub = sub i32 %tmp, %tmp1 289 %c = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 2 290 %tmp2 = load i32, i32* %c, align 4 291 %add = add nsw i32 %sub, %tmp2 292 switch i32 %add, label %sw.epilog [ 293 i32 1, label %sw.bb.1 294 i32 2, label %sw.bb.2 295 ] 296 297sw.bb.1: ; preds = %entry 298 store i32 111, i32* %b, align 4 299 store i32 222, i32* %c, align 4 300 br label %sw.epilog 301 302sw.bb.2: ; preds = %entry 303 store i32 333, i32* %b, align 4 304 store i32 444, i32* %c, align 4 305 br label %sw.epilog 306 307sw.epilog: ; preds = %sw.bb.2, %sw.bb.1, %entry 308 ret void 309} 310 311define i32 @test5(i32 %x, i32 %y) #0 { 312; CHECK-LABEL: test5: 313; CHECK: # %bb.0: # %entry 314; CHECK-NEXT: addl %esi, %esi 315; CHECK-NEXT: subl %esi, %edi 316; CHECK-NEXT: movl %edi, %eax 317; CHECK-NEXT: retq 318entry: 319 %mul = mul nsw i32 %y, -2 320 %add = add nsw i32 %mul, %x 321 ret i32 %add 322} 323 324define i32 @test6(i32 %x, i32 %y) #0 { 325; CHECK-LABEL: test6: 326; CHECK: # %bb.0: # %entry 327; CHECK-NEXT: # kill: def $esi killed $esi def $rsi 328; CHECK-NEXT: leal (%rsi,%rsi,2), %eax 329; CHECK-NEXT: subl %eax, %edi 330; CHECK-NEXT: movl %edi, %eax 331; CHECK-NEXT: retq 332entry: 333 %mul = mul nsw i32 %y, -3 334 %add = add nsw i32 %mul, %x 335 ret i32 %add 336} 337 338define i32 @test7(i32 %x, i32 %y) #0 { 339; CHECK-LABEL: test7: 340; CHECK: # %bb.0: # %entry 341; CHECK-NEXT: shll $2, %esi 342; CHECK-NEXT: subl %esi, %edi 343; CHECK-NEXT: movl %edi, %eax 344; CHECK-NEXT: retq 345entry: 346 %mul = mul nsw i32 %y, -4 347 %add = add nsw i32 %mul, %x 348 ret i32 %add 349} 350 351define i32 @test8(i32 %x, i32 %y) #0 { 352; CHECK-LABEL: test8: 353; CHECK: # %bb.0: # %entry 354; CHECK-NEXT: # kill: def $esi killed $esi def $rsi 355; CHECK-NEXT: leal (,%rsi,4), %eax 356; CHECK-NEXT: subl %edi, %eax 357; CHECK-NEXT: retq 358entry: 359 %mul = shl nsw i32 %y, 2 360 %sub = sub nsw i32 %mul, %x 361 ret i32 %sub 362} 363 364 365define i32 @test9(i32 %x, i32 %y) #0 { 366; CHECK-LABEL: test9: 367; CHECK: # %bb.0: # %entry 368; CHECK-NEXT: addl %esi, %esi 369; CHECK-NEXT: subl %esi, %edi 370; CHECK-NEXT: movl %edi, %eax 371; CHECK-NEXT: retq 372entry: 373 %mul = mul nsw i32 -2, %y 374 %add = add nsw i32 %x, %mul 375 ret i32 %add 376} 377 378define i32 @test10(i32 %x, i32 %y) #0 { 379; CHECK-LABEL: test10: 380; CHECK: # %bb.0: # %entry 381; CHECK-NEXT: # kill: def $esi killed $esi def $rsi 382; CHECK-NEXT: leal (%rsi,%rsi,2), %eax 383; CHECK-NEXT: subl %eax, %edi 384; CHECK-NEXT: movl %edi, %eax 385; CHECK-NEXT: retq 386entry: 387 %mul = mul nsw i32 -3, %y 388 %add = add nsw i32 %x, %mul 389 ret i32 %add 390} 391 392define i32 @test11(i32 %x, i32 %y) #0 { 393; CHECK-LABEL: test11: 394; CHECK: # %bb.0: # %entry 395; CHECK-NEXT: shll $2, %esi 396; CHECK-NEXT: subl %esi, %edi 397; CHECK-NEXT: movl %edi, %eax 398; CHECK-NEXT: retq 399entry: 400 %mul = mul nsw i32 -4, %y 401 %add = add nsw i32 %x, %mul 402 ret i32 %add 403} 404 405define i32 @test12(i32 %x, i32 %y) #0 { 406; CHECK-LABEL: test12: 407; CHECK: # %bb.0: # %entry 408; CHECK-NEXT: # kill: def $esi killed $esi def $rsi 409; CHECK-NEXT: leal (,%rsi,4), %eax 410; CHECK-NEXT: subl %edi, %eax 411; CHECK-NEXT: retq 412entry: 413 %mul = mul nsw i32 4, %y 414 %sub = sub nsw i32 %mul, %x 415 ret i32 %sub 416} 417 418define i64 @test13(i64 %x, i64 %y) #0 { 419; CHECK-LABEL: test13: 420; CHECK: # %bb.0: # %entry 421; CHECK-NEXT: shlq $2, %rsi 422; CHECK-NEXT: subq %rsi, %rdi 423; CHECK-NEXT: movq %rdi, %rax 424; CHECK-NEXT: retq 425entry: 426 %mul = mul nsw i64 -4, %y 427 %add = add nsw i64 %x, %mul 428 ret i64 %add 429} 430 431define i32 @test14(i32 %x, i32 %y) #0 { 432; CHECK-LABEL: test14: 433; CHECK: # %bb.0: # %entry 434; CHECK-NEXT: # kill: def $esi killed $esi def $rsi 435; CHECK-NEXT: leal (,%rsi,4), %eax 436; CHECK-NEXT: subl %edi, %eax 437; CHECK-NEXT: retq 438entry: 439 %mul = mul nsw i32 4, %y 440 %sub = sub nsw i32 %mul, %x 441 ret i32 %sub 442} 443 444define zeroext i16 @test15(i16 zeroext %x, i16 zeroext %y) #0 { 445; CHECK-LABEL: test15: 446; CHECK: # %bb.0: # %entry 447; CHECK-NEXT: shll $3, %esi 448; CHECK-NEXT: subl %esi, %edi 449; CHECK-NEXT: movl %edi, %eax 450; CHECK-NEXT: retq 451entry: 452 %conv = zext i16 %x to i32 453 %conv1 = zext i16 %y to i32 454 %mul = mul nsw i32 -8, %conv1 455 %add = add nsw i32 %conv, %mul 456 %conv2 = trunc i32 %add to i16 457 ret i16 %conv2 458} 459 460attributes #0 = { norecurse nounwind optsize readnone uwtable} 461