Commit e722943e authored by Matt Arsenault's avatar Matt Arsenault
Browse files

AMDGPU: Factor out large flat offset splitting

parent c80d52e6
Loading
Loading
Loading
Loading
+3 −15
Original line number Diff line number Diff line
@@ -1742,22 +1742,10 @@ bool AMDGPUDAGToDAGISel::SelectFlatOffset(SDNode *N,
        // 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<int64_t>(COffsetVal) / D) * D;
          ImmField = COffsetVal - RemainderOffset;
        } else if (static_cast<int64_t>(COffsetVal) >= 0) {
          ImmField = COffsetVal & maskTrailingOnes<uint64_t>(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);
+20 −0
Original line number Diff line number Diff line
@@ -6959,6 +6959,26 @@ bool SIInstrInfo::isLegalFLATOffset(int64_t Offset, unsigned AddrSpace,
  return Signed ? isInt<13>(Offset) :isUInt<12>(Offset);
}

std::pair<int64_t, int64_t> 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 = (COffsetVal / D) * D;
    ImmField = COffsetVal - RemainderOffset;
  } else if (COffsetVal >= 0) {
    ImmField = COffsetVal & maskTrailingOnes<uint64_t>(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 {
+6 −0
Original line number Diff line number Diff line
@@ -1039,6 +1039,12 @@ public:
  bool isLegalFLATOffset(int64_t Offset, unsigned AddrSpace,
                         bool Signed) const;

  /// Split \p COffsetVal into {immediate offset field, remainder offset}
  /// values.
  std::pair<int64_t, int64_t> 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.