Issue 156289
Summary [GlobalIsel] Assertion when calling `GISelValueTracking::computeNumSignBits` within `GISelValueTracking::computeKnownBitsImpl`
Labels new issue
Assignees
Reporter 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 https://github.com/llvm/llvm-project/issues/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.
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to