Skip to content

Dead code/instructions generated to detect divide by zero #44500

Closed
@vitalyd

Description

@vitalyd

This is born out of https://users.rust-lang.org/t/division-by-nonzero/12822.

The gist is the following function:

pub fn d1(x: u64, y: u64) -> u64 { 
  x / y.saturating_add(1) 
}

generates the following x86_64 assembly:

example::d1:
  addq $1, %rsi
  movq $-1, %rcx
  cmovaeq %rsi, %rcx
  testq %rcx, %rcx
  je .LBB0_2
  xorl %edx, %edx
  movq %rdi, %rax
  divq %rcx
  retq
.LBB0_2:
  pushq %rbp
  movq %rsp, %rbp
  leaq panic_loc.2(%rip), %rdi
  callq core::panicking::panic@PLT

str.0:
  .ascii "/tmp/compiler-explorer-compiler117811-5-86yrz4.tvuxewb3xr/example.rs"

str.1:
  .ascii "attempt to divide by zero"

https://godbolt.org/g/8eh61N

As far as I can tell, that division cannot panic. If that's true, then the following inefficiences are present:

  1. The panic basic block that's generated.
  2. The testq and je instructions are essentially dead.

I don't know the innards of LLVM, but perhaps the non-zero/non-wrapping aspect isn't conveyed to LLVM here? Or perhaps it's not able to figure it out on its own based on whatever IR is given to it.

Metadata

Metadata

Assignees

Labels

A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-enhancementCategory: An issue proposing an enhancement or a PR with one.I-slowIssue: Problems and improvements with respect to performance of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions