| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | |
| ; RUN: llc < %s -mtriple=x86_64-linux | FileCheck %s -check-prefix=CHECK -check-prefix=ENABLED | |
| ; RUN: llc --disable-x86-lea-opt < %s -mtriple=x86_64-linux | FileCheck %s -check-prefix=CHECK -check-prefix=DISABLED | |
| %struct.anon1 = type { i32, i32, i32 } | |
| %struct.anon2 = type { i32, [32 x i32], i32 } | |
| @arr1 = external global [65 x %struct.anon1], align 16 | |
| @arr2 = external global [65 x %struct.anon2], align 16 | |
| define void @test1(i64 %x) nounwind { | |
| ; ENABLED-LABEL: test1: | |
| ; ENABLED: # %bb.0: # %entry | |
| ; ENABLED-NEXT: shlq $2, %rdi | |
| ; ENABLED-NEXT: movl arr1(%rdi,%rdi,2), %ecx | |
| ; ENABLED-NEXT: leaq arr1+4(%rdi,%rdi,2), %rax | |
| ; ENABLED-NEXT: subl arr1+4(%rdi,%rdi,2), %ecx | |
| ; ENABLED-NEXT: addl arr1+8(%rdi,%rdi,2), %ecx | |
| ; ENABLED-NEXT: cmpl $2, %ecx | |
| ; ENABLED-NEXT: je .LBB0_3 | |
| ; ENABLED-NEXT: # %bb.1: # %entry | |
| ; ENABLED-NEXT: cmpl $1, %ecx | |
| ; ENABLED-NEXT: jne .LBB0_4 | |
| ; ENABLED-NEXT: # %bb.2: # %sw.bb.1 | |
| ; ENABLED-NEXT: movl $111, (%rax) | |
| ; ENABLED-NEXT: movl $222, 4(%rax) | |
| ; ENABLED-NEXT: retq | |
| ; ENABLED-NEXT: .LBB0_3: # %sw.bb.2 | |
| ; ENABLED-NEXT: movl $333, (%rax) # imm = 0x14D | |
| ; ENABLED-NEXT: movl $444, 4(%rax) # imm = 0x1BC | |
| ; ENABLED-NEXT: .LBB0_4: # %sw.epilog | |
| ; ENABLED-NEXT: retq | |
| ; | |
| ; DISABLED-LABEL: test1: | |
| ; DISABLED: # %bb.0: # %entry | |
| ; DISABLED-NEXT: shlq $2, %rdi | |
| ; DISABLED-NEXT: movl arr1(%rdi,%rdi,2), %edx | |
| ; DISABLED-NEXT: leaq arr1+4(%rdi,%rdi,2), %rax | |
| ; DISABLED-NEXT: subl arr1+4(%rdi,%rdi,2), %edx | |
| ; DISABLED-NEXT: leaq arr1+8(%rdi,%rdi,2), %rcx | |
| ; DISABLED-NEXT: addl arr1+8(%rdi,%rdi,2), %edx | |
| ; DISABLED-NEXT: cmpl $2, %edx | |
| ; DISABLED-NEXT: je .LBB0_3 | |
| ; DISABLED-NEXT: # %bb.1: # %entry | |
| ; DISABLED-NEXT: cmpl $1, %edx | |
| ; DISABLED-NEXT: jne .LBB0_4 | |
| ; DISABLED-NEXT: # %bb.2: # %sw.bb.1 | |
| ; DISABLED-NEXT: movl $111, (%rax) | |
| ; DISABLED-NEXT: movl $222, (%rcx) | |
| ; DISABLED-NEXT: retq | |
| ; DISABLED-NEXT: .LBB0_3: # %sw.bb.2 | |
| ; DISABLED-NEXT: movl $333, (%rax) # imm = 0x14D | |
| ; DISABLED-NEXT: movl $444, (%rcx) # imm = 0x1BC | |
| ; DISABLED-NEXT: .LBB0_4: # %sw.epilog | |
| ; DISABLED-NEXT: retq | |
| entry: | |
| %a = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 0 | |
| %tmp = load i32, i32* %a, align 4 | |
| %b = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 1 | |
| %tmp1 = load i32, i32* %b, align 4 | |
| %sub = sub i32 %tmp, %tmp1 | |
| %c = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 2 | |
| %tmp2 = load i32, i32* %c, align 4 | |
| %add = add nsw i32 %sub, %tmp2 | |
| switch i32 %add, label %sw.epilog [ | |
| i32 1, label %sw.bb.1 | |
| i32 2, label %sw.bb.2 | |
| ] | |
| sw.bb.1: ; preds = %entry | |
| store i32 111, i32* %b, align 4 | |
| store i32 222, i32* %c, align 4 | |
| br label %sw.epilog | |
| sw.bb.2: ; preds = %entry | |
| store i32 333, i32* %b, align 4 | |
| store i32 444, i32* %c, align 4 | |
| br label %sw.epilog | |
| sw.epilog: ; preds = %sw.bb.2, %sw.bb.1, %entry | |
| ret void | |
| } | |
| define void @test2(i64 %x) nounwind optsize { | |
| ; ENABLED-LABEL: test2: | |
| ; ENABLED: # %bb.0: # %entry | |
| ; ENABLED-NEXT: shlq $2, %rdi | |
| ; ENABLED-NEXT: leaq arr1+4(%rdi,%rdi,2), %rax | |
| ; ENABLED-NEXT: movl -4(%rax), %ecx | |
| ; ENABLED-NEXT: subl (%rax), %ecx | |
| ; ENABLED-NEXT: addl 4(%rax), %ecx | |
| ; ENABLED-NEXT: cmpl $2, %ecx | |
| ; ENABLED-NEXT: je .LBB1_3 | |
| ; ENABLED-NEXT: # %bb.1: # %entry | |
| ; ENABLED-NEXT: cmpl $1, %ecx | |
| ; ENABLED-NEXT: jne .LBB1_4 | |
| ; ENABLED-NEXT: # %bb.2: # %sw.bb.1 | |
| ; ENABLED-NEXT: movl $111, (%rax) | |
| ; ENABLED-NEXT: movl $222, 4(%rax) | |
| ; ENABLED-NEXT: retq | |
| ; ENABLED-NEXT: .LBB1_3: # %sw.bb.2 | |
| ; ENABLED-NEXT: movl $333, (%rax) # imm = 0x14D | |
| ; ENABLED-NEXT: movl $444, 4(%rax) # imm = 0x1BC | |
| ; ENABLED-NEXT: .LBB1_4: # %sw.epilog | |
| ; ENABLED-NEXT: retq | |
| ; | |
| ; DISABLED-LABEL: test2: | |
| ; DISABLED: # %bb.0: # %entry | |
| ; DISABLED-NEXT: shlq $2, %rdi | |
| ; DISABLED-NEXT: movl arr1(%rdi,%rdi,2), %edx | |
| ; DISABLED-NEXT: leaq arr1+4(%rdi,%rdi,2), %rax | |
| ; DISABLED-NEXT: subl arr1+4(%rdi,%rdi,2), %edx | |
| ; DISABLED-NEXT: leaq arr1+8(%rdi,%rdi,2), %rcx | |
| ; DISABLED-NEXT: addl arr1+8(%rdi,%rdi,2), %edx | |
| ; DISABLED-NEXT: cmpl $2, %edx | |
| ; DISABLED-NEXT: je .LBB1_3 | |
| ; DISABLED-NEXT: # %bb.1: # %entry | |
| ; DISABLED-NEXT: cmpl $1, %edx | |
| ; DISABLED-NEXT: jne .LBB1_4 | |
| ; DISABLED-NEXT: # %bb.2: # %sw.bb.1 | |
| ; DISABLED-NEXT: movl $111, (%rax) | |
| ; DISABLED-NEXT: movl $222, (%rcx) | |
| ; DISABLED-NEXT: retq | |
| ; DISABLED-NEXT: .LBB1_3: # %sw.bb.2 | |
| ; DISABLED-NEXT: movl $333, (%rax) # imm = 0x14D | |
| ; DISABLED-NEXT: movl $444, (%rcx) # imm = 0x1BC | |
| ; DISABLED-NEXT: .LBB1_4: # %sw.epilog | |
| ; DISABLED-NEXT: retq | |
| entry: | |
| %a = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 0 | |
| %tmp = load i32, i32* %a, align 4 | |
| %b = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 1 | |
| %tmp1 = load i32, i32* %b, align 4 | |
| %sub = sub i32 %tmp, %tmp1 | |
| %c = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 2 | |
| %tmp2 = load i32, i32* %c, align 4 | |
| %add = add nsw i32 %sub, %tmp2 | |
| switch i32 %add, label %sw.epilog [ | |
| i32 1, label %sw.bb.1 | |
| i32 2, label %sw.bb.2 | |
| ] | |
| sw.bb.1: ; preds = %entry | |
| store i32 111, i32* %b, align 4 | |
| store i32 222, i32* %c, align 4 | |
| br label %sw.epilog | |
| sw.bb.2: ; preds = %entry | |
| store i32 333, i32* %b, align 4 | |
| store i32 444, i32* %c, align 4 | |
| br label %sw.epilog | |
| sw.epilog: ; preds = %sw.bb.2, %sw.bb.1, %entry | |
| ret void | |
| } | |
| ; Check that LEA optimization pass takes into account a resultant address | |
| ; displacement when choosing a LEA instruction for replacing a redundant | |
| ; address recalculation. | |
| define void @test3(i64 %x) nounwind optsize { | |
| ; ENABLED-LABEL: test3: | |
| ; ENABLED: # %bb.0: # %entry | |
| ; ENABLED-NEXT: movq %rdi, %rax | |
| ; ENABLED-NEXT: shlq $7, %rax | |
| ; ENABLED-NEXT: leaq arr2+132(%rax,%rdi,8), %rcx | |
| ; ENABLED-NEXT: leaq arr2(%rax,%rdi,8), %rax | |
| ; ENABLED-NEXT: movl (%rcx), %edx | |
| ; ENABLED-NEXT: addl (%rax), %edx | |
| ; ENABLED-NEXT: cmpl $2, %edx | |
| ; ENABLED-NEXT: je .LBB2_3 | |
| ; ENABLED-NEXT: # %bb.1: # %entry | |
| ; ENABLED-NEXT: cmpl $1, %edx | |
| ; ENABLED-NEXT: jne .LBB2_4 | |
| ; ENABLED-NEXT: # %bb.2: # %sw.bb.1 | |
| ; ENABLED-NEXT: movl $111, (%rcx) | |
| ; ENABLED-NEXT: movl $222, (%rax) | |
| ; ENABLED-NEXT: retq | |
| ; ENABLED-NEXT: .LBB2_3: # %sw.bb.2 | |
| ; ENABLED-NEXT: movl $333, (%rcx) # imm = 0x14D | |
| ; ENABLED-NEXT: movl %eax, (%rax) | |
| ; ENABLED-NEXT: .LBB2_4: # %sw.epilog | |
| ; ENABLED-NEXT: retq | |
| ; | |
| ; DISABLED-LABEL: test3: | |
| ; DISABLED: # %bb.0: # %entry | |
| ; DISABLED-NEXT: movq %rdi, %rsi | |
| ; DISABLED-NEXT: shlq $7, %rsi | |
| ; DISABLED-NEXT: leaq arr2+132(%rsi,%rdi,8), %rcx | |
| ; DISABLED-NEXT: leaq arr2(%rsi,%rdi,8), %rax | |
| ; DISABLED-NEXT: movl arr2+132(%rsi,%rdi,8), %edx | |
| ; DISABLED-NEXT: addl arr2(%rsi,%rdi,8), %edx | |
| ; DISABLED-NEXT: cmpl $2, %edx | |
| ; DISABLED-NEXT: je .LBB2_3 | |
| ; DISABLED-NEXT: # %bb.1: # %entry | |
| ; DISABLED-NEXT: cmpl $1, %edx | |
| ; DISABLED-NEXT: jne .LBB2_4 | |
| ; DISABLED-NEXT: # %bb.2: # %sw.bb.1 | |
| ; DISABLED-NEXT: movl $111, (%rcx) | |
| ; DISABLED-NEXT: movl $222, (%rax) | |
| ; DISABLED-NEXT: retq | |
| ; DISABLED-NEXT: .LBB2_3: # %sw.bb.2 | |
| ; DISABLED-NEXT: movl $333, (%rcx) # imm = 0x14D | |
| ; DISABLED-NEXT: movl %eax, (%rax) | |
| ; DISABLED-NEXT: .LBB2_4: # %sw.epilog | |
| ; DISABLED-NEXT: retq | |
| entry: | |
| %a = getelementptr inbounds [65 x %struct.anon2], [65 x %struct.anon2]* @arr2, i64 0, i64 %x, i32 2 | |
| %tmp = load i32, i32* %a, align 4 | |
| %b = getelementptr inbounds [65 x %struct.anon2], [65 x %struct.anon2]* @arr2, i64 0, i64 %x, i32 0 | |
| %tmp1 = load i32, i32* %b, align 4 | |
| %add = add nsw i32 %tmp, %tmp1 | |
| switch i32 %add, label %sw.epilog [ | |
| i32 1, label %sw.bb.1 | |
| i32 2, label %sw.bb.2 | |
| ] | |
| sw.bb.1: ; preds = %entry | |
| store i32 111, i32* %a, align 4 | |
| store i32 222, i32* %b, align 4 | |
| br label %sw.epilog | |
| sw.bb.2: ; preds = %entry | |
| store i32 333, i32* %a, align 4 | |
| ; Make sure the REG3's definition LEA won't be removed as redundant. | |
| %cvt = ptrtoint i32* %b to i32 | |
| store i32 %cvt, i32* %b, align 4 | |
| br label %sw.epilog | |
| sw.epilog: ; preds = %sw.bb.2, %sw.bb.1, %entry | |
| ret void | |
| ; REG3's definition is closer to movl than REG2's, but the pass still chooses | |
| ; REG2 because it provides the resultant address displacement fitting 1 byte. | |
| } | |
| define void @test4(i64 %x) nounwind minsize { | |
| ; ENABLED-LABEL: test4: | |
| ; ENABLED: # %bb.0: # %entry | |
| ; ENABLED-NEXT: imulq $12, %rdi, %rax | |
| ; ENABLED-NEXT: leaq arr1+4(%rax), %rax | |
| ; ENABLED-NEXT: movl -4(%rax), %ecx | |
| ; ENABLED-NEXT: subl (%rax), %ecx | |
| ; ENABLED-NEXT: addl 4(%rax), %ecx | |
| ; ENABLED-NEXT: cmpl $2, %ecx | |
| ; ENABLED-NEXT: je .LBB3_3 | |
| ; ENABLED-NEXT: # %bb.1: # %entry | |
| ; ENABLED-NEXT: cmpl $1, %ecx | |
| ; ENABLED-NEXT: jne .LBB3_4 | |
| ; ENABLED-NEXT: # %bb.2: # %sw.bb.1 | |
| ; ENABLED-NEXT: movl $111, (%rax) | |
| ; ENABLED-NEXT: movl $222, 4(%rax) | |
| ; ENABLED-NEXT: retq | |
| ; ENABLED-NEXT: .LBB3_3: # %sw.bb.2 | |
| ; ENABLED-NEXT: movl $333, (%rax) # imm = 0x14D | |
| ; ENABLED-NEXT: movl $444, 4(%rax) # imm = 0x1BC | |
| ; ENABLED-NEXT: .LBB3_4: # %sw.epilog | |
| ; ENABLED-NEXT: retq | |
| ; | |
| ; DISABLED-LABEL: test4: | |
| ; DISABLED: # %bb.0: # %entry | |
| ; DISABLED-NEXT: imulq $12, %rdi, %rsi | |
| ; DISABLED-NEXT: movl arr1(%rsi), %edx | |
| ; DISABLED-NEXT: leaq arr1+4(%rsi), %rax | |
| ; DISABLED-NEXT: subl arr1+4(%rsi), %edx | |
| ; DISABLED-NEXT: leaq arr1+8(%rsi), %rcx | |
| ; DISABLED-NEXT: addl arr1+8(%rsi), %edx | |
| ; DISABLED-NEXT: cmpl $2, %edx | |
| ; DISABLED-NEXT: je .LBB3_3 | |
| ; DISABLED-NEXT: # %bb.1: # %entry | |
| ; DISABLED-NEXT: cmpl $1, %edx | |
| ; DISABLED-NEXT: jne .LBB3_4 | |
| ; DISABLED-NEXT: # %bb.2: # %sw.bb.1 | |
| ; DISABLED-NEXT: movl $111, (%rax) | |
| ; DISABLED-NEXT: movl $222, (%rcx) | |
| ; DISABLED-NEXT: retq | |
| ; DISABLED-NEXT: .LBB3_3: # %sw.bb.2 | |
| ; DISABLED-NEXT: movl $333, (%rax) # imm = 0x14D | |
| ; DISABLED-NEXT: movl $444, (%rcx) # imm = 0x1BC | |
| ; DISABLED-NEXT: .LBB3_4: # %sw.epilog | |
| ; DISABLED-NEXT: retq | |
| entry: | |
| %a = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 0 | |
| %tmp = load i32, i32* %a, align 4 | |
| %b = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 1 | |
| %tmp1 = load i32, i32* %b, align 4 | |
| %sub = sub i32 %tmp, %tmp1 | |
| %c = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 2 | |
| %tmp2 = load i32, i32* %c, align 4 | |
| %add = add nsw i32 %sub, %tmp2 | |
| switch i32 %add, label %sw.epilog [ | |
| i32 1, label %sw.bb.1 | |
| i32 2, label %sw.bb.2 | |
| ] | |
| sw.bb.1: ; preds = %entry | |
| store i32 111, i32* %b, align 4 | |
| store i32 222, i32* %c, align 4 | |
| br label %sw.epilog | |
| sw.bb.2: ; preds = %entry | |
| store i32 333, i32* %b, align 4 | |
| store i32 444, i32* %c, align 4 | |
| br label %sw.epilog | |
| sw.epilog: ; preds = %sw.bb.2, %sw.bb.1, %entry | |
| ret void | |
| } | |
| define i32 @test5(i32 %x, i32 %y) #0 { | |
| ; CHECK-LABEL: test5: | |
| ; CHECK: # %bb.0: # %entry | |
| ; CHECK-NEXT: addl %esi, %esi | |
| ; CHECK-NEXT: subl %esi, %edi | |
| ; CHECK-NEXT: movl %edi, %eax | |
| ; CHECK-NEXT: retq | |
| entry: | |
| %mul = mul nsw i32 %y, -2 | |
| %add = add nsw i32 %mul, %x | |
| ret i32 %add | |
| } | |
| define i32 @test6(i32 %x, i32 %y) #0 { | |
| ; CHECK-LABEL: test6: | |
| ; CHECK: # %bb.0: # %entry | |
| ; CHECK-NEXT: # kill: def $esi killed $esi def $rsi | |
| ; CHECK-NEXT: leal (%rsi,%rsi,2), %eax | |
| ; CHECK-NEXT: subl %eax, %edi | |
| ; CHECK-NEXT: movl %edi, %eax | |
| ; CHECK-NEXT: retq | |
| entry: | |
| %mul = mul nsw i32 %y, -3 | |
| %add = add nsw i32 %mul, %x | |
| ret i32 %add | |
| } | |
| define i32 @test7(i32 %x, i32 %y) #0 { | |
| ; CHECK-LABEL: test7: | |
| ; CHECK: # %bb.0: # %entry | |
| ; CHECK-NEXT: shll $2, %esi | |
| ; CHECK-NEXT: subl %esi, %edi | |
| ; CHECK-NEXT: movl %edi, %eax | |
| ; CHECK-NEXT: retq | |
| entry: | |
| %mul = mul nsw i32 %y, -4 | |
| %add = add nsw i32 %mul, %x | |
| ret i32 %add | |
| } | |
| define i32 @test8(i32 %x, i32 %y) #0 { | |
| ; CHECK-LABEL: test8: | |
| ; CHECK: # %bb.0: # %entry | |
| ; CHECK-NEXT: # kill: def $esi killed $esi def $rsi | |
| ; CHECK-NEXT: leal (,%rsi,4), %eax | |
| ; CHECK-NEXT: subl %edi, %eax | |
| ; CHECK-NEXT: retq | |
| entry: | |
| %mul = shl nsw i32 %y, 2 | |
| %sub = sub nsw i32 %mul, %x | |
| ret i32 %sub | |
| } | |
| define i32 @test9(i32 %x, i32 %y) #0 { | |
| ; CHECK-LABEL: test9: | |
| ; CHECK: # %bb.0: # %entry | |
| ; CHECK-NEXT: addl %esi, %esi | |
| ; CHECK-NEXT: subl %esi, %edi | |
| ; CHECK-NEXT: movl %edi, %eax | |
| ; CHECK-NEXT: retq | |
| entry: | |
| %mul = mul nsw i32 -2, %y | |
| %add = add nsw i32 %x, %mul | |
| ret i32 %add | |
| } | |
| define i32 @test10(i32 %x, i32 %y) #0 { | |
| ; CHECK-LABEL: test10: | |
| ; CHECK: # %bb.0: # %entry | |
| ; CHECK-NEXT: # kill: def $esi killed $esi def $rsi | |
| ; CHECK-NEXT: leal (%rsi,%rsi,2), %eax | |
| ; CHECK-NEXT: subl %eax, %edi | |
| ; CHECK-NEXT: movl %edi, %eax | |
| ; CHECK-NEXT: retq | |
| entry: | |
| %mul = mul nsw i32 -3, %y | |
| %add = add nsw i32 %x, %mul | |
| ret i32 %add | |
| } | |
| define i32 @test11(i32 %x, i32 %y) #0 { | |
| ; CHECK-LABEL: test11: | |
| ; CHECK: # %bb.0: # %entry | |
| ; CHECK-NEXT: shll $2, %esi | |
| ; CHECK-NEXT: subl %esi, %edi | |
| ; CHECK-NEXT: movl %edi, %eax | |
| ; CHECK-NEXT: retq | |
| entry: | |
| %mul = mul nsw i32 -4, %y | |
| %add = add nsw i32 %x, %mul | |
| ret i32 %add | |
| } | |
| define i32 @test12(i32 %x, i32 %y) #0 { | |
| ; CHECK-LABEL: test12: | |
| ; CHECK: # %bb.0: # %entry | |
| ; CHECK-NEXT: # kill: def $esi killed $esi def $rsi | |
| ; CHECK-NEXT: leal (,%rsi,4), %eax | |
| ; CHECK-NEXT: subl %edi, %eax | |
| ; CHECK-NEXT: retq | |
| entry: | |
| %mul = mul nsw i32 4, %y | |
| %sub = sub nsw i32 %mul, %x | |
| ret i32 %sub | |
| } | |
| define i64 @test13(i64 %x, i64 %y) #0 { | |
| ; CHECK-LABEL: test13: | |
| ; CHECK: # %bb.0: # %entry | |
| ; CHECK-NEXT: shlq $2, %rsi | |
| ; CHECK-NEXT: subq %rsi, %rdi | |
| ; CHECK-NEXT: movq %rdi, %rax | |
| ; CHECK-NEXT: retq | |
| entry: | |
| %mul = mul nsw i64 -4, %y | |
| %add = add nsw i64 %x, %mul | |
| ret i64 %add | |
| } | |
| define i32 @test14(i32 %x, i32 %y) #0 { | |
| ; CHECK-LABEL: test14: | |
| ; CHECK: # %bb.0: # %entry | |
| ; CHECK-NEXT: # kill: def $esi killed $esi def $rsi | |
| ; CHECK-NEXT: leal (,%rsi,4), %eax | |
| ; CHECK-NEXT: subl %edi, %eax | |
| ; CHECK-NEXT: retq | |
| entry: | |
| %mul = mul nsw i32 4, %y | |
| %sub = sub nsw i32 %mul, %x | |
| ret i32 %sub | |
| } | |
| define zeroext i16 @test15(i16 zeroext %x, i16 zeroext %y) #0 { | |
| ; CHECK-LABEL: test15: | |
| ; CHECK: # %bb.0: # %entry | |
| ; CHECK-NEXT: shll $3, %esi | |
| ; CHECK-NEXT: subl %esi, %edi | |
| ; CHECK-NEXT: movl %edi, %eax | |
| ; CHECK-NEXT: retq | |
| entry: | |
| %conv = zext i16 %x to i32 | |
| %conv1 = zext i16 %y to i32 | |
| %mul = mul nsw i32 -8, %conv1 | |
| %add = add nsw i32 %conv, %mul | |
| %conv2 = trunc i32 %add to i16 | |
| ret i16 %conv2 | |
| } | |
| attributes #0 = { norecurse nounwind optsize readnone uwtable} |