| OLD | NEW |
| 1 ; This tests against a lowering error in a multiply instruction that produces | 1 ; This tests against a lowering error in a multiply instruction that produces |
| 2 ; results in a low and high register. This is usually lowered as a mul | 2 ; results in a low and high register. This is usually lowered as a mul |
| 3 ; instruction whose dest contains the low portion, and a FakeDef of the high | 3 ; instruction whose dest contains the low portion, and a FakeDef of the high |
| 4 ; portion. The problem is that if the high portion is unused (e.g. the multiply | 4 ; portion. The problem is that if the high portion is unused (e.g. the multiply |
| 5 ; is followed by a truncation), the FakeDef may be eliminated, and the register | 5 ; is followed by a truncation), the FakeDef may be eliminated, and the register |
| 6 ; allocator may assign the high register to a variable that is live across the | 6 ; allocator may assign the high register to a variable that is live across the |
| 7 ; mul instruction. This is incorrect because the mul instruction smashes the | 7 ; mul instruction. This is incorrect because the mul instruction smashes the |
| 8 ; register. | 8 ; register. |
| 9 | 9 |
| 10 ; REQUIRES: allow_dump | 10 ; REQUIRES: allow_dump |
| 11 | 11 |
| 12 ; RUN: %p2i --target x8632 -i %s --filetype=asm --args -O2 -asm-verbose \ | 12 ; RUN: %p2i --target x8632 -i %s --filetype=asm --args -O2 -asm-verbose \ |
| 13 ; RUN: --split-local-vars=0 \ |
| 13 ; RUN: --reg-use=eax,edx -reg-reserve | FileCheck --check-prefix=X8632 %s | 14 ; RUN: --reg-use=eax,edx -reg-reserve | FileCheck --check-prefix=X8632 %s |
| 14 ; RUN: %p2i --target arm32 -i %s --filetype=asm --args -O2 -asm-verbose \ | 15 ; RUN: %p2i --target arm32 -i %s --filetype=asm --args -O2 -asm-verbose \ |
| 15 ; RUN: | FileCheck --check-prefix=ARM32 %s | 16 ; RUN: | FileCheck --check-prefix=ARM32 %s |
| 16 | 17 |
| 17 define internal i32 @mul(i64 %a, i64 %b, i32 %c) { | 18 define internal i32 @mul(i64 %a, i64 %b, i32 %c) { |
| 18 ; Force an early use of %c. | 19 ; Force an early use of %c. |
| 19 store i32 %c, i32* undef, align 1 | 20 store i32 %c, i32* undef, align 1 |
| 20 %m = mul i64 %a, %b | 21 %m = mul i64 %a, %b |
| 21 %t = trunc i64 %m to i32 | 22 %t = trunc i64 %m to i32 |
| 22 ; Make many uses of %c to give it high weight. | 23 ; Make many uses of %c to give it high weight. |
| 23 %t1 = add i32 %t, %c | 24 %t1 = add i32 %t, %c |
| 24 %t2 = add i32 %t1, %c | 25 %t2 = add i32 %t1, %c |
| 25 %t3 = add i32 %t2, %c | 26 %t3 = add i32 %t2, %c |
| 26 ret i32 %t3 | 27 ret i32 %t3 |
| 27 } | 28 } |
| 28 | 29 |
| 29 ; For x8632, we want asm-verbose to print the stack offset assignment for lv$c | 30 ; For x8632, we want asm-verbose to print the stack offset assignment for lv$c |
| 30 ; ("local variable 'c'") in the prolog, and then have at least one use of lv$c | 31 ; ("local variable 'c'") in the prolog, and then have at least one use of lv$c |
| 31 ; in the body, i.e. don't register-allocate edx to %c. | 32 ; in the body, i.e. don't register-allocate edx to %c. |
| 32 | 33 |
| 33 ; X8632-LABEL: mul | 34 ; X8632-LABEL: mul |
| 34 ; X8632: lv$c = | 35 ; X8632: lv$c = |
| 35 ; X8632: lv$c | 36 ; X8632: lv$c |
| 36 | 37 |
| 37 ; For arm32, the failure would manifest as a translation error - no register | 38 ; For arm32, the failure would manifest as a translation error - no register |
| 38 ; being allocated to the high operand, so we just check for successful | 39 ; being allocated to the high operand, so we just check for successful |
| 39 ; translation. | 40 ; translation. |
| 40 | 41 |
| 41 ; ARM32-LABEL: mul | 42 ; ARM32-LABEL: mul |
| OLD | NEW |