@@ -2004,28 +2004,50 @@ bool AMDGPUDAGToDAGISel::SelectScratchSVAddr(SDNode *N, SDValue Addr,
20042004 return true ;
20052005}
20062006
2007+ // For unbuffered smem loads, it is illegal for the Immediate Offset to be
2008+ // negative if the resulting (Offset + (M0 or SOffset or zero) is negative.
2009+ // Handle the case where the Immediate Offset + SOffset is negative.
2010+ bool AMDGPUDAGToDAGISel::isSOffsetLegalWithImmOffset (SDValue *SOffset,
2011+ bool Imm32Only,
2012+ bool IsBuffer,
2013+ int64_t ImmOffset) const {
2014+ if (!IsBuffer && !Imm32Only && ImmOffset < 0 &&
2015+ AMDGPU::hasSMRDSignedImmOffset (*Subtarget)) {
2016+ KnownBits SKnown = CurDAG->computeKnownBits (*SOffset);
2017+ if (ImmOffset + SKnown.getMinValue ().getSExtValue () < 0 )
2018+ return false ;
2019+ }
2020+
2021+ return true ;
2022+ }
2023+
20072024// Match an immediate (if Offset is not null) or an SGPR (if SOffset is
20082025// not null) offset. If Imm32Only is true, match only 32-bit immediate
20092026// offsets available on CI.
20102027bool AMDGPUDAGToDAGISel::SelectSMRDOffset (SDValue ByteOffsetNode,
20112028 SDValue *SOffset, SDValue *Offset,
2012- bool Imm32Only, bool IsBuffer) const {
2029+ bool Imm32Only, bool IsBuffer,
2030+ bool HasSOffset,
2031+ int64_t ImmOffset) const {
20132032 assert ((!SOffset || !Offset) &&
20142033 " Cannot match both soffset and offset at the same time!" );
20152034
20162035 ConstantSDNode *C = dyn_cast<ConstantSDNode>(ByteOffsetNode);
20172036 if (!C) {
20182037 if (!SOffset)
20192038 return false ;
2039+
20202040 if (ByteOffsetNode.getValueType ().isScalarInteger () &&
20212041 ByteOffsetNode.getValueType ().getSizeInBits () == 32 ) {
20222042 *SOffset = ByteOffsetNode;
2023- return true ;
2043+ return isSOffsetLegalWithImmOffset (SOffset, Imm32Only, IsBuffer,
2044+ ImmOffset);
20242045 }
20252046 if (ByteOffsetNode.getOpcode () == ISD::ZERO_EXTEND) {
20262047 if (ByteOffsetNode.getOperand (0 ).getValueType ().getSizeInBits () == 32 ) {
20272048 *SOffset = ByteOffsetNode.getOperand (0 );
2028- return true ;
2049+ return isSOffsetLegalWithImmOffset (SOffset, Imm32Only, IsBuffer,
2050+ ImmOffset);
20292051 }
20302052 }
20312053 return false ;
@@ -2036,8 +2058,8 @@ bool AMDGPUDAGToDAGISel::SelectSMRDOffset(SDValue ByteOffsetNode,
20362058 // GFX9 and GFX10 have signed byte immediate offsets. The immediate
20372059 // offset for S_BUFFER instructions is unsigned.
20382060 int64_t ByteOffset = IsBuffer ? C->getZExtValue () : C->getSExtValue ();
2039- std::optional<int64_t > EncodedOffset =
2040- AMDGPU::getSMRDEncodedOffset ( *Subtarget, ByteOffset, IsBuffer);
2061+ std::optional<int64_t > EncodedOffset = AMDGPU::getSMRDEncodedOffset (
2062+ *Subtarget, ByteOffset, IsBuffer, HasSOffset );
20412063 if (EncodedOffset && Offset && !Imm32Only) {
20422064 *Offset = CurDAG->getTargetConstant (*EncodedOffset, SL, MVT::i32 );
20432065 return true ;
@@ -2096,13 +2118,22 @@ SDValue AMDGPUDAGToDAGISel::Expand32BitAddress(SDValue Addr) const {
20962118// true, match only 32-bit immediate offsets available on CI.
20972119bool AMDGPUDAGToDAGISel::SelectSMRDBaseOffset (SDValue Addr, SDValue &SBase,
20982120 SDValue *SOffset, SDValue *Offset,
2099- bool Imm32Only,
2100- bool IsBuffer) const {
2121+ bool Imm32Only, bool IsBuffer,
2122+ bool HasSOffset,
2123+ int64_t ImmOffset) const {
21012124 if (SOffset && Offset) {
21022125 assert (!Imm32Only && !IsBuffer);
21032126 SDValue B;
2104- return SelectSMRDBaseOffset (Addr, B, nullptr , Offset) &&
2105- SelectSMRDBaseOffset (B, SBase, SOffset, nullptr );
2127+
2128+ if (!SelectSMRDBaseOffset (Addr, B, nullptr , Offset, false , false , true ))
2129+ return false ;
2130+
2131+ int64_t ImmOff = 0 ;
2132+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(*Offset))
2133+ ImmOff = C->getSExtValue ();
2134+
2135+ return SelectSMRDBaseOffset (B, SBase, SOffset, nullptr , false , false , true ,
2136+ ImmOff);
21062137 }
21072138
21082139 // A 32-bit (address + offset) should not cause unsigned 32-bit integer
@@ -2121,11 +2152,14 @@ bool AMDGPUDAGToDAGISel::SelectSMRDBaseOffset(SDValue Addr, SDValue &SBase,
21212152 }
21222153 if (!N0 || !N1)
21232154 return false ;
2124- if (SelectSMRDOffset (N1, SOffset, Offset, Imm32Only, IsBuffer)) {
2155+
2156+ if (SelectSMRDOffset (N1, SOffset, Offset, Imm32Only, IsBuffer, HasSOffset,
2157+ ImmOffset)) {
21252158 SBase = N0;
21262159 return true ;
21272160 }
2128- if (SelectSMRDOffset (N0, SOffset, Offset, Imm32Only, IsBuffer)) {
2161+ if (SelectSMRDOffset (N0, SOffset, Offset, Imm32Only, IsBuffer, HasSOffset,
2162+ ImmOffset)) {
21292163 SBase = N1;
21302164 return true ;
21312165 }
0 commit comments