264 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=x86_64-unknown -verify-machineinstrs | FileCheck %s3 4; This file tests following optimization5;6; leal (%rdx,%rax), %esi7; subl %esi, %ecx8;9; can be transformed to10;11; subl %edx, %ecx12; subl %eax, %ecx13 14; C - (A + B) --> C - A - B15define i32 @test1(ptr %p, i32 %a, i32 %b, i32 %c) {16; CHECK-LABEL: test1:17; CHECK: # %bb.0: # %entry18; CHECK-NEXT: # kill: def $edx killed $edx def $rdx19; CHECK-NEXT: movl %esi, %eax20; CHECK-NEXT: subl %edx, %ecx21; CHECK-NEXT: subl %eax, %ecx22; CHECK-NEXT: movl %ecx, (%rdi)23; CHECK-NEXT: subl %edx, %eax24; CHECK-NEXT: # kill: def $eax killed $eax killed $rax25; CHECK-NEXT: retq26entry:27 %0 = add i32 %b, %a28 %sub = sub i32 %c, %029 store i32 %sub, ptr %p, align 430 %sub1 = sub i32 %a, %b31 ret i32 %sub132}33 34; (A + B) + C --> C + A + B35define i32 @test2(ptr %p, i32 %a, i32 %b, i32 %c) {36; CHECK-LABEL: test2:37; CHECK: # %bb.0: # %entry38; CHECK-NEXT: # kill: def $edx killed $edx def $rdx39; CHECK-NEXT: movl %esi, %eax40; CHECK-NEXT: addl %eax, %ecx41; CHECK-NEXT: addl %edx, %ecx42; CHECK-NEXT: movl %ecx, (%rdi)43; CHECK-NEXT: subl %edx, %eax44; CHECK-NEXT: # kill: def $eax killed $eax killed $rax45; CHECK-NEXT: retq46entry:47 %0 = add i32 %a, %b48 %1 = add i32 %c, %049 store i32 %1, ptr %p, align 450 %sub1 = sub i32 %a, %b51 ret i32 %sub152}53 54; C + (A + B) --> C + A + B55define i32 @test3(ptr %p, i32 %a, i32 %b, i32 %c) {56; CHECK-LABEL: test3:57; CHECK: # %bb.0: # %entry58; CHECK-NEXT: # kill: def $edx killed $edx def $rdx59; CHECK-NEXT: movl %esi, %eax60; CHECK-NEXT: addl %eax, %ecx61; CHECK-NEXT: addl %edx, %ecx62; CHECK-NEXT: movl %ecx, (%rdi)63; CHECK-NEXT: subl %edx, %eax64; CHECK-NEXT: # kill: def $eax killed $eax killed $rax65; CHECK-NEXT: retq66entry:67 %0 = add i32 %a, %b68 %1 = add i32 %0, %c69 store i32 %1, ptr %p, align 470 %sub1 = sub i32 %a, %b71 ret i32 %sub172}73 74; (A + B) - C75; Can't be converted to A - C + B without introduce MOV76define i32 @test4(ptr %p, i32 %a, i32 %b, i32 %c) {77; CHECK-LABEL: test4:78; CHECK: # %bb.0: # %entry79; CHECK-NEXT: # kill: def $edx killed $edx def $rdx80; CHECK-NEXT: movl %esi, %eax81; CHECK-NEXT: leal (%rdx,%rax), %esi82; CHECK-NEXT: subl %ecx, %esi83; CHECK-NEXT: movl %esi, (%rdi)84; CHECK-NEXT: subl %edx, %eax85; CHECK-NEXT: # kill: def $eax killed $eax killed $rax86; CHECK-NEXT: retq87entry:88 %0 = add i32 %b, %a89 %sub = sub i32 %0, %c90 store i32 %sub, ptr %p, align 491 %sub1 = sub i32 %a, %b92 ret i32 %sub193}94 95define i64 @test5(ptr %p, i64 %a, i64 %b, i64 %c) {96; CHECK-LABEL: test5:97; CHECK: # %bb.0: # %entry98; CHECK-NEXT: movq (%rdi), %rax99; CHECK-NEXT: subq %rdx, %rcx100; CHECK-NEXT: subq %rax, %rcx101; CHECK-NEXT: movq %rcx, (%rdi)102; CHECK-NEXT: subq %rdx, %rax103; CHECK-NEXT: retq104entry:105 %ld = load i64, ptr %p, align 8106 %0 = add i64 %b, %ld107 %sub = sub i64 %c, %0108 store i64 %sub, ptr %p, align 8109 %sub1 = sub i64 %ld, %b110 ret i64 %sub1111}112 113define i64 @test6(ptr %p, i64 %a, i64 %b, i64 %c) {114; CHECK-LABEL: test6:115; CHECK: # %bb.0: # %entry116; CHECK-NEXT: movq (%rdi), %rax117; CHECK-NEXT: addq %rdx, %rcx118; CHECK-NEXT: addq %rax, %rcx119; CHECK-NEXT: movq %rcx, (%rdi)120; CHECK-NEXT: subq %rdx, %rax121; CHECK-NEXT: retq122entry:123 %ld = load i64, ptr %p, align 8124 %0 = add i64 %b, %ld125 %1 = add i64 %0, %c126 store i64 %1, ptr %p, align 8127 %sub1 = sub i64 %ld, %b128 ret i64 %sub1129}130 131define i64 @test7(ptr %p, i64 %a, i64 %b, i64 %c) {132; CHECK-LABEL: test7:133; CHECK: # %bb.0: # %entry134; CHECK-NEXT: movq (%rdi), %rax135; CHECK-NEXT: addq %rdx, %rcx136; CHECK-NEXT: addq %rax, %rcx137; CHECK-NEXT: movq %rcx, (%rdi)138; CHECK-NEXT: subq %rdx, %rax139; CHECK-NEXT: retq140entry:141 %ld = load i64, ptr %p, align 8142 %0 = add i64 %b, %ld143 %1 = add i64 %c, %0144 store i64 %1, ptr %p, align 8145 %sub1 = sub i64 %ld, %b146 ret i64 %sub1147}148 149; The sub instruction generated flags is used by following branch,150; so it should not be transformed.151define i64 @test8(ptr %p, i64 %a, i64 %b, i64 %c) {152; CHECK-LABEL: test8:153; CHECK: # %bb.0: # %entry154; CHECK-NEXT: movq (%rdi), %rax155; CHECK-NEXT: leaq (%rdx,%rax), %rsi156; CHECK-NEXT: subq %rsi, %rcx157; CHECK-NEXT: ja .LBB7_2158; CHECK-NEXT: # %bb.1: # %then159; CHECK-NEXT: movq %rcx, (%rdi)160; CHECK-NEXT: subq %rdx, %rax161; CHECK-NEXT: retq162; CHECK-NEXT: .LBB7_2: # %else163; CHECK-NEXT: movq $0, (%rdi)164; CHECK-NEXT: subq %rdx, %rax165; CHECK-NEXT: retq166entry:167 %ld = load i64, ptr %p, align 8168 %0 = add i64 %b, %ld169 %sub = sub i64 %c, %0170 %cond = icmp ule i64 %c, %0171 br i1 %cond, label %then, label %else172 173then:174 store i64 %sub, ptr %p, align 8175 br label %endif176 177else:178 store i64 0, ptr %p, align 8179 br label %endif180 181endif:182 %sub1 = sub i64 %ld, %b183 ret i64 %sub1184}185 186; PR50615187; The sub register usage of lea dest should block the transformation.188define void @test9(i64 %p, i64 %s) {189; CHECK-LABEL: test9:190; CHECK: # %bb.0: # %entry191; CHECK-NEXT: leaq (%rsi,%rdi), %rax192; CHECK-NEXT: xorl %ecx, %ecx193; CHECK-NEXT: testl $4095, %eax # imm = 0xFFF194; CHECK-NEXT: setne %cl195; CHECK-NEXT: shll $12, %ecx196; CHECK-NEXT: addq %rax, %rcx197; CHECK-NEXT: andq $-4096, %rcx # imm = 0xF000198; CHECK-NEXT: addq %rcx, %rdi199; CHECK-NEXT: jmp bar@PLT # TAILCALL200entry:201 %add = add i64 %s, %p202 %rem = and i64 %add, 4095203 %cmp.not = icmp eq i64 %rem, 0204 %add18 = select i1 %cmp.not, i64 0, i64 4096205 %div9 = add i64 %add18, %add206 %mul = and i64 %div9, -4096207 %add2 = add i64 %mul, %p208 tail call void @bar(i64 %add2, i64 %s)209 ret void210}211 212define void @test10() {213; CHECK-LABEL: test10:214; CHECK: # %bb.0: # %entry215; CHECK-NEXT: movl (%rax), %eax216; CHECK-NEXT: movzwl (%rax), %ecx217; CHECK-NEXT: leal (%rcx,%rcx,2), %esi218; CHECK-NEXT: movl %ecx, %edi219; CHECK-NEXT: subl %ecx, %edi220; CHECK-NEXT: subl %ecx, %edi221; CHECK-NEXT: negl %esi222; CHECK-NEXT: xorl %ecx, %ecx223; CHECK-NEXT: cmpl $4, %eax224; CHECK-NEXT: movl %edi, (%rax)225; CHECK-NEXT: movl %esi, (%rax)226; CHECK-NEXT: cmovnel %eax, %ecx227; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx228; CHECK-NEXT: sarl %cl, %esi229; CHECK-NEXT: movl %esi, (%rax)230; CHECK-NEXT: retq231entry:232 %tmp = load i32, ptr undef, align 4233 %tmp3 = sdiv i32 undef, 6234 %tmp4 = load i32, ptr undef, align 4235 %tmp5 = icmp eq i32 %tmp4, 4236 %tmp6 = select i1 %tmp5, i32 %tmp3, i32 %tmp237 %tmp10 = load i16, ptr undef, align 2238 %tmp11 = zext i16 %tmp10 to i32239 %tmp13 = zext i16 undef to i32240 %tmp15 = load i16, ptr undef, align 2241 %tmp16 = zext i16 %tmp15 to i32242 %tmp19 = shl nsw i32 undef, 1243 %tmp25 = shl nsw i32 undef, 1244 %tmp26 = add nsw i32 %tmp25, %tmp13245 %tmp28 = shl nsw i32 undef, 1246 %tmp29 = add nsw i32 %tmp28, %tmp16247 %tmp30 = sub nsw i32 %tmp19, %tmp29248 %tmp31 = sub nsw i32 %tmp11, %tmp26249 %tmp32 = shl nsw i32 %tmp30, 1250 %tmp33 = add nsw i32 %tmp32, %tmp31251 store i32 %tmp33, ptr undef, align 4252 %tmp34 = mul nsw i32 %tmp31, -2253 %tmp35 = add nsw i32 %tmp34, %tmp30254 store i32 %tmp35, ptr undef, align 4255 %tmp36 = select i1 %tmp5, i32 undef, i32 undef256 %tmp38 = load i32, ptr undef, align 4257 %tmp39 = ashr i32 %tmp38, %tmp6258 store i32 %tmp39, ptr undef, align 4259 ret void260}261 262declare void @bar(i64, i64)263 264