Index: llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp +++ llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp @@ -1742,22 +1742,10 @@ // into two pieces that are both >= 0 or both <= 0. SDLoc DL(N); - uint64_t RemainderOffset = COffsetVal; - uint64_t ImmField = 0; - const unsigned NumBits = TII->getNumFlatOffsetBits(IsSigned); - if (IsSigned) { - // Use signed division by a power of two to truncate towards 0. - int64_t D = 1LL << (NumBits - 1); - RemainderOffset = (static_cast(COffsetVal) / D) * D; - ImmField = COffsetVal - RemainderOffset; - } else if (static_cast(COffsetVal) >= 0) { - ImmField = COffsetVal & maskTrailingOnes(NumBits); - RemainderOffset = COffsetVal - ImmField; - } - assert(TII->isLegalFLATOffset(ImmField, AS, IsSigned)); - assert(RemainderOffset + ImmField == COffsetVal); + uint64_t RemainderOffset; - OffsetVal = ImmField; + std::tie(OffsetVal, RemainderOffset) + = TII->splitFlatOffset(COffsetVal, AS, IsSigned); SDValue AddOffsetLo = getMaterializedScalarImm32(Lo_32(RemainderOffset), DL); Index: llvm/lib/Target/AMDGPU/SIInstrInfo.h =================================================================== --- llvm/lib/Target/AMDGPU/SIInstrInfo.h +++ llvm/lib/Target/AMDGPU/SIInstrInfo.h @@ -1039,6 +1039,12 @@ bool isLegalFLATOffset(int64_t Offset, unsigned AddrSpace, bool Signed) const; + /// Split \p COffsetVal into {immediate offset field, remainder offset} + /// values. + std::pair splitFlatOffset(int64_t COffsetVal, + unsigned AddrSpace, + bool IsSigned) const; + /// \brief Return a target-specific opcode if Opcode is a pseudo instruction. /// Return -1 if the target-specific opcode for the pseudo instruction does /// not exist. If Opcode is not a pseudo instruction, this is identity. Index: llvm/lib/Target/AMDGPU/SIInstrInfo.cpp =================================================================== --- llvm/lib/Target/AMDGPU/SIInstrInfo.cpp +++ llvm/lib/Target/AMDGPU/SIInstrInfo.cpp @@ -6976,6 +6976,26 @@ return Signed ? isInt<13>(Offset) :isUInt<12>(Offset); } +std::pair SIInstrInfo::splitFlatOffset(int64_t COffsetVal, + unsigned AddrSpace, + bool IsSigned) const { + int64_t RemainderOffset = COffsetVal; + int64_t ImmField = 0; + const unsigned NumBits = getNumFlatOffsetBits(IsSigned); + if (IsSigned) { + // Use signed division by a power of two to truncate towards 0. + int64_t D = 1LL << (NumBits - 1); + RemainderOffset = (static_cast(COffsetVal) / D) * D; + ImmField = COffsetVal - RemainderOffset; + } else if (static_cast(COffsetVal) >= 0) { + ImmField = COffsetVal & maskTrailingOnes(NumBits); + RemainderOffset = COffsetVal - ImmField; + } + + assert(isLegalFLATOffset(ImmField, AddrSpace, IsSigned)); + assert(RemainderOffset + ImmField == COffsetVal); + return {ImmField, RemainderOffset}; +} // This must be kept in sync with the SIEncodingFamily class in SIInstrInfo.td enum SIEncodingFamily {