diff options
| author | bors <bors@rust-lang.org> | 2017-06-10 09:11:36 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-06-10 09:11:36 +0000 |
| commit | 995f741a0e3a57d4142c0590b3266514fa0a0e29 (patch) | |
| tree | f1f259211c1e5dd2635b06d03d511121c6571101 /src/test/run-pass/thinlto | |
| parent | e1480499b484d142dfa704ae20bd33eae518c1d0 (diff) | |
| parent | 6d86f0c018b57fcb9ca12c801939130b7f8e441e (diff) | |
| download | rust-995f741a0e3a57d4142c0590b3266514fa0a0e29.tar.gz rust-995f741a0e3a57d4142c0590b3266514fa0a0e29.zip | |
Auto merge of #42556 - scottmcm:ctz-nz, r=BurntSushi
Get LLVM to stop generating dead assembly in next_power_of_two
It turns out that LLVM can turn `@llvm.ctlz.i64(_, true)` into `@llvm.ctlz.i64(_, false)` ([`ctlz`](http://llvm.org/docs/LangRef.html#llvm-ctlz-intrinsic)) where valuable, but never does the opposite. That leads to some silly assembly getting generated in certain cases.
A contrived-but-clear example https://is.gd/VAIKuC:
```rust
fn foo(x:u64) -> u32 {
if x == 0 { return !0; }
x.leading_zeros()
}
```
Generates
```asm
testq %rdi, %rdi
je .LBB0_1
je .LBB0_3 ; <-- wha?
bsrq %rdi, %rax
xorq $63, %rax
retq
.LBB0_1:
movl $-1, %eax
retq
.LBB0_3:
movl $64, %eax ; <-- dead
retq
```
I noticed this in `next_power_of_two`, which without this PR generates the following:
```asm
cmpq $2, %rcx
jae .LBB1_2
movl $1, %eax
retq
.LBB1_2:
decq %rcx
je .LBB1_3
bsrq %rcx, %rcx
xorq $63, %rcx
jmp .LBB1_5
.LBB1_3:
movl $64, %ecx ; <-- dead
.LBB1_5:
movq $-1, %rax
shrq %cl, %rax
incq %rax
retq
```
And with this PR becomes
```asm
cmpq $2, %rcx
jae .LBB0_2
movl $1, %eax
retq
.LBB0_2:
decq %rcx
bsrq %rcx, %rcx
xorl $63, %ecx
movq $-1, %rax
shrq %cl, %rax
incq %rax
retq
```
Diffstat (limited to 'src/test/run-pass/thinlto')
0 files changed, 0 insertions, 0 deletions
