Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[GlobalIsel] Assertion when calling GISelValueTracking::computeNumSignBits within GISelValueTracking::computeKnownBitsImpl #156289

@r41k0u

Description

@r41k0u

I came across this while working on #154413. The tests where G_ABS is performed on a G_CONSTANT were fine, but everything else failed to generate using the update_givaluetracking_test_checks script.

The mentioned PR does the following changes in GISelValueTracking::computeKnownBitsImpl:

  case TargetOpcode::G_ABS: {
    Register SrcReg = MI.getOperand(1).getReg();
    computeKnownBitsImpl(SrcReg, Known, DemandedElts, Depth + 1);
    Known = Known.abs();
    Known.Zero.setHighBits(computeNumSignBits(SrcReg, DemandedElts, Depth + 1) -
                           1);
    break;
  }

The Known.Zero.setHighBits is a fix for #94344.
If we check GISelValueTracking::computeNumSignBits:

unsigned GISelValueTracking::computeNumSignBits(Register R,
                                                const APInt &DemandedElts,
                                                unsigned Depth) {
  MachineInstr &MI = *MRI.getVRegDef(R);
  unsigned Opcode = MI.getOpcode();

  if (Opcode == TargetOpcode::G_CONSTANT)
    return MI.getOperand(1).getCImm()->getValue().getNumSignBits();

The constant case gets short-circuited at the top, but:

  // Finally, if we can prove that the top bits of the result are 0's or 1's,
  // use this information.
  KnownBits Known = getKnownBits(R, DemandedElts, Depth);
  APInt Mask;
  if (Known.isNonNegative()) { // sign bit is 0
    Mask = Known.Zero;
  } else if (Known.isNegative()) { // sign bit is 1;
    Mask = Known.One;
  } else {
    // Nothing known.
    return FirstAnswer;
  }

  // Okay, we know that the sign bit in Mask is set.  Use CLO to determine
  // the number of identical bits in the top of the input value.
  Mask <<= Mask.getBitWidth() - TyBits;
  return std::max(FirstAnswer, Mask.countl_one());
}

We have a call to GISelValueTracking::getKnownBits, which has the following assertion:

KnownBits GISelValueTracking::getKnownBits(Register R,
                                           const APInt &DemandedElts,
                                           unsigned Depth) {
  // For now, we only maintain the cache during one request.
  assert(ComputeKnownBitsCache.empty() && "Cache should have been cleared");

  KnownBits Known;
  computeKnownBitsImpl(R, Known, DemandedElts, Depth);
  ComputeKnownBitsCache.clear();
  return Known;
}

This also shows up in the stack dump of the failed assertion while running the tests:

 #8 0x0000ffffb12e00dc __assert_fail_base ./assert/assert.c:53:15
 #9 0x0000aaaab8f44de4 llvm::GISelValueTracking::getKnownBits(llvm::Register, llvm::APInt const&, unsigned int) llvm-project/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp:99:13
#10 0x0000aaaab8f4c7dc llvm::GISelValueTracking::computeNumSignBits(llvm::Register, llvm::APInt const&, unsigned int) llvm-project/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp:2049:9
#11 0x0000aaaab8f47cd4 llvm::GISelValueTracking::computeKnownBitsImpl(llvm::Register, llvm::KnownBits&, llvm::APInt const&, unsigned int) llvm-project/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp:704:27
#12 0x0000aaaab8f44e14 llvm::GISelValueTracking::getKnownBits(llvm::Register, llvm::APInt const&, unsigned int) llvm-project/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp:101:30
#13 0x0000aaaab8f44d48 llvm::GISelValueTracking::getKnownBits(llvm::Register)

I think one fix is to use GISelValueTracking::computeKnownBitsImpl instead of GISelValueTracking::getKnownBits here, which won't trigger assertions.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions