Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

segfault from selectCopy on AArch64 with LTO #53315

Closed
pnkfelix opened this issue Jan 20, 2022 · 5 comments
Closed

segfault from selectCopy on AArch64 with LTO #53315

pnkfelix opened this issue Jan 20, 2022 · 5 comments

Comments

@pnkfelix
Copy link

This bug is spawned off of rust-lang/rust#91671 (comment)

The AArch64InstructionSelector.cpp code has this line:

const RegisterBank &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);

The problem is that RBI.getRegBank can return null, and does so during rustc's use of LLVM.

You can see the problematic behavior atop this trace that I've uploaded to pernos.co, here. That trace is derived from code that I've put into a dedicated repository, here: https://github.com/pnkfelix/issue-91671-a64-doctestfail

I have not yet managed to narrow the test case down to something that I can replicate atop llc or opt alone, but I wanted to start tracking the issue here in the LLVM organization so that LLVM developers could help me narrow this down further.

@llvmbot
Copy link
Collaborator

llvmbot commented Jan 20, 2022

@llvm/issue-subscribers-backend-aarch64

@nikic
Copy link
Contributor

nikic commented Jan 21, 2022

Reduced:

; RUN: llc -O0 < %s
target triple = "aarch64-unknown-linux-gnu"

define void @test() {
  %x = call i128 @returns_arg(i128 0)
  call void @accepts_arg(i128 %x)
  ret void
}

declare i128 @returns_arg(i128 returned)
declare void @accepts_arg(i128)

@nikic
Copy link
Contributor

nikic commented Jan 21, 2022

Here's the -verify-machineinstrs output:

# After IRTranslator
# Machine code for function test: IsSSA, TracksLiveness

bb.1 (%ir-block.0):
  %1:_(s128) = G_CONSTANT i128 0
  ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
  %2:_(s64), %3:_(s64) = G_UNMERGE_VALUES %1:_(s128)
  $x0 = COPY %2:_(s64)
  $x1 = COPY %3:_(s64)
  BL @returns_arg, <regmask $fp $lr $b8 $b9 $b10 $b11 $b12 $b13 $b14 $b15 $d8 $d9 $d10 $d11 $d12 $d13 $d14 $d15 $h8 $h9 $h10 $h11 $h12 $h13 $h14 $h15 $s8 $s9 $s10 $s11 $s12 $s13 $s14 and 55 more...>, implicit-def $lr, implicit $sp, implicit $x0, implicit $x1
  %4:_(s64) = COPY %2:_(s64)
  %4:_(s64) = COPY %2:_(s64)
  %0:_(s128) = G_MERGE_VALUES %4:_(s64), %5:_(s64)
  ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
  ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
  %6:_(s64), %7:_(s64) = G_UNMERGE_VALUES %0:_(s128)
  $x0 = COPY %6:_(s64)
  $x1 = COPY %7:_(s64)
  BL @accepts_arg, <regmask $fp $lr $b8 $b9 $b10 $b11 $b12 $b13 $b14 $b15 $d8 $d9 $d10 $d11 $d12 $d13 $d14 $d15 $h8 $h9 $h10 $h11 $h12 $h13 $h14 $h15 $s8 $s9 $s10 $s11 $s12 $s13 $s14 and 53 more...>, implicit-def $lr, implicit $sp, implicit $x0, implicit $x1
  ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
  RET_ReallyLR

# End machine code for function test.

*** Bad machine code: Multiple virtual register defs in SSA form ***
- function:    test
- basic block: %bb.1  (0x891c1c0)
- instruction: %4:_(s64) = COPY %2:_(s64)
- operand 0:   %4:_

*** Bad machine code: Multiple virtual register defs in SSA form ***
- function:    test
- basic block: %bb.1  (0x891c1c0)
- instruction: %4:_(s64) = COPY %2:_(s64)
- operand 0:   %4:_

*** Bad machine code: Reading virtual register without a def ***
- function:    test
- basic block: %bb.1  (0x891c1c0)
- instruction: %0:_(s128) = G_MERGE_VALUES %4:_(s64), %5:_(s64)
- operand 2:   %5:_

@nikic
Copy link
Contributor

nikic commented Jan 21, 2022

Presumably this code:

if (!Info.OrigRet.Ty->isVoidTy()) {
CCAssignFn *RetAssignFn = TLI.CCAssignFnForReturn(Info.CallConv);
CallReturnHandler Handler(MIRBuilder, MRI, MIB);
bool UsingReturnedArg =
!OutArgs.empty() && OutArgs[0].Flags[0].isReturned();
AArch64OutgoingValueAssigner Assigner(RetAssignFn, RetAssignFn, Subtarget,
/*IsReturn*/ false);
ReturnedArgCallReturnHandler ReturnedArgHandler(MIRBuilder, MRI, MIB);
if (!determineAndHandleAssignments(
UsingReturnedArg ? ReturnedArgHandler : Handler, Assigner, InArgs,
MIRBuilder, Info.CallConv, Info.IsVarArg,
UsingReturnedArg ? OutArgs[0].Regs[0] : Register()))
return false;
}

Fails to handle values stored in multiple registers in some form.

@nikic
Copy link
Contributor

nikic commented Jan 21, 2022

Candidate patch: https://reviews.llvm.org/D117866

@nikic nikic self-assigned this Jan 21, 2022
@nikic nikic closed this as completed in 0d1308a Jan 24, 2022
nikic added a commit to rust-lang/llvm-project that referenced this issue Jan 28, 2022
The call lowering code assumed that a returned argument could only
consist of one register. Pass an ArrayRef<Register> instead of
Register to make sure that all parts get assigned.

Fixes llvm#53315.

Differential Revision: https://reviews.llvm.org/D117866
hedgar2017 pushed a commit to matter-labs/era-compiler-llvm that referenced this issue Jun 28, 2022
The call lowering code assumed that a returned argument could only
consist of one register. Pass an ArrayRef<Register> instead of
Register to make sure that all parts get assigned.

Fixes llvm/llvm-project#53315.

Differential Revision: https://reviews.llvm.org/D117866
mem-frob pushed a commit to draperlaboratory/hope-llvm-project that referenced this issue Oct 7, 2022
The call lowering code assumed that a returned argument could only
consist of one register. Pass an ArrayRef<Register> instead of
Register to make sure that all parts get assigned.

Fixes llvm/llvm-project#53315.

Differential Revision: https://reviews.llvm.org/D117866
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants