[AMDGPU] Use first operand of zext to test first bit zero (#217195)
Fix AMDGPU SAddr selection for zero-extended 32-bit offsets on targets
with signed GVS VOffset.
For DAG, function `matchExtFromI32orI32` will return valid value if
address can be `Addr:SGPR` + `Signed Offset:VGPR`, and the function is
as follow:
```c++
static SDValue matchExtFromI32orI32(SDValue Op, bool IsSigned,
const SelectionDAG *DAG) {
if (Op.getValueType() == MVT::i32)
return Op;
if (Op.getOpcode() != (IsSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND) &&
Op.getOpcode() != ISD::ANY_EXTEND &&
!(DAG->SignBitIsZero(Op) &&
Op.getOpcode() == (IsSigned ? ISD::ZERO_EXTEND : ISD::SIGN_EXTEND)))
return SDValue();
SDValue ExtSrc = Op.getOperand(0);
return (ExtSrc.getValueType() == MVT::i32) ? ExtSrc : SDValue();
}
```
Assuming:
1. Address is formed by addition, denote `Addr = add BASE, OFFSET`
2. Then `OFFSET` = `Op` under `AMDGPUDAGToDAGISel::SelectGlobalSAddr`
calling `matchExtFromI32orI32`
3. `i64 Op = zext i32 Src` which means `i64 OFFSET = zext i32 Src`
4. `Src` some how have the value of `Src = 0x80000000`
5. `IsSigned` is true if we are running under signed offset arch
With above assumption, we have:
1. Fail in `Op.getValueType() == MVT::i32`
2. `Op.getOpcode() != ISD::SIGN_EXTEND`
3. `Op.getOpcode() != ISD::ANY_EXTEND`
4. `Op.getOpcode() == ISD::ZERO_EXTEND` and since `Op` is the result of
zext, the highest bit of `Op` is zero so `DAG->SignBitIsZero(Op)` is
also true
5. `!(DAG->SignBitIsZero(Op) && Op.getOpcode() == ISD::ZERO_EXTEND)` is
false
Thus, it will pass the if check and return valid `SDValue`, which in the
end create instructions such as `(LOAD/STORE_SADDR BASE, (ZEXT Src))`
and `Src = 0x80000000`, which is actually addressing `BASE - 0x80000000`
Co-authored-by: shore <shorshen@amd.com>