mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-21 21:29:41 +00:00
R600/SI: Set 20-bit immediate byte offset for SMRD on VI
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@223614 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
67a6b29f1f
commit
eca8933d58
@ -2156,7 +2156,12 @@ MachineSDNode *SITargetLowering::AdjustRegClass(MachineSDNode *N,
|
|||||||
SmallVector<SDValue, 8> Ops;
|
SmallVector<SDValue, 8> Ops;
|
||||||
Ops.push_back(SDValue(RSrc, 0));
|
Ops.push_back(SDValue(RSrc, 0));
|
||||||
Ops.push_back(N->getOperand(0));
|
Ops.push_back(N->getOperand(0));
|
||||||
Ops.push_back(DAG.getConstant(Offset->getSExtValue() << 2, MVT::i32));
|
|
||||||
|
// The immediate offset is in dwords on SI and in bytes on VI.
|
||||||
|
if (Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
|
||||||
|
Ops.push_back(DAG.getConstant(Offset->getSExtValue(), MVT::i32));
|
||||||
|
else
|
||||||
|
Ops.push_back(DAG.getConstant(Offset->getSExtValue() << 2, MVT::i32));
|
||||||
|
|
||||||
// Copy remaining operands so we keep any chain and glue nodes that follow
|
// Copy remaining operands so we keep any chain and glue nodes that follow
|
||||||
// the normal operands.
|
// the normal operands.
|
||||||
|
@ -971,15 +971,19 @@ bool SIInstrInfo::isImmOperandLegal(const MachineInstr *MI, unsigned OpNo,
|
|||||||
return RI.regClassCanUseInlineConstant(OpInfo.RegClass);
|
return RI.regClassCanUseInlineConstant(OpInfo.RegClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SIInstrInfo::canFoldOffset(unsigned OffsetSize, unsigned AS) {
|
bool SIInstrInfo::canFoldOffset(unsigned OffsetSize, unsigned AS) const {
|
||||||
switch (AS) {
|
switch (AS) {
|
||||||
case AMDGPUAS::GLOBAL_ADDRESS: {
|
case AMDGPUAS::GLOBAL_ADDRESS: {
|
||||||
// MUBUF instructions a 12-bit offset in bytes.
|
// MUBUF instructions a 12-bit offset in bytes.
|
||||||
return isUInt<12>(OffsetSize);
|
return isUInt<12>(OffsetSize);
|
||||||
}
|
}
|
||||||
case AMDGPUAS::CONSTANT_ADDRESS: {
|
case AMDGPUAS::CONSTANT_ADDRESS: {
|
||||||
// SMRD instructions have an 8-bit offset in dwords.
|
// SMRD instructions have an 8-bit offset in dwords on SI and
|
||||||
return (OffsetSize % 4 == 0) && isUInt<8>(OffsetSize / 4);
|
// a 20-bit offset in bytes on VI.
|
||||||
|
if (RI.ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
|
||||||
|
return isUInt<20>(OffsetSize);
|
||||||
|
else
|
||||||
|
return (OffsetSize % 4 == 0) && isUInt<8>(OffsetSize / 4);
|
||||||
}
|
}
|
||||||
case AMDGPUAS::LOCAL_ADDRESS:
|
case AMDGPUAS::LOCAL_ADDRESS:
|
||||||
case AMDGPUAS::REGION_ADDRESS: {
|
case AMDGPUAS::REGION_ADDRESS: {
|
||||||
@ -1701,27 +1705,30 @@ void SIInstrInfo::splitSMRD(MachineInstr *MI,
|
|||||||
getNamedOperand(*MI, AMDGPU::OpName::offset);
|
getNamedOperand(*MI, AMDGPU::OpName::offset);
|
||||||
const MachineOperand *SBase = getNamedOperand(*MI, AMDGPU::OpName::sbase);
|
const MachineOperand *SBase = getNamedOperand(*MI, AMDGPU::OpName::sbase);
|
||||||
|
|
||||||
|
// The SMRD has an 8-bit offset in dwords on SI and a 20-bit offset in bytes
|
||||||
|
// on VI.
|
||||||
if (OffOp) {
|
if (OffOp) {
|
||||||
|
bool isVI = RI.ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS;
|
||||||
|
unsigned OffScale = isVI ? 1 : 4;
|
||||||
// Handle the _IMM variant
|
// Handle the _IMM variant
|
||||||
unsigned LoOffset = OffOp->getImm();
|
unsigned LoOffset = OffOp->getImm() * OffScale;
|
||||||
unsigned HiOffset = LoOffset + (HalfSize / 4);
|
unsigned HiOffset = LoOffset + HalfSize;
|
||||||
Lo = BuildMI(*MBB, MI, DL, get(HalfImmOp), RegLo)
|
Lo = BuildMI(*MBB, MI, DL, get(HalfImmOp), RegLo)
|
||||||
.addOperand(*SBase)
|
.addOperand(*SBase)
|
||||||
.addImm(LoOffset);
|
.addImm(LoOffset / OffScale);
|
||||||
|
|
||||||
if (!isUInt<8>(HiOffset)) {
|
if (!isUInt<20>(HiOffset) || (!isVI && !isUInt<8>(HiOffset / OffScale))) {
|
||||||
unsigned OffsetSGPR =
|
unsigned OffsetSGPR =
|
||||||
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
|
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
|
||||||
BuildMI(*MBB, MI, DL, get(AMDGPU::S_MOV_B32), OffsetSGPR)
|
BuildMI(*MBB, MI, DL, get(AMDGPU::S_MOV_B32), OffsetSGPR)
|
||||||
.addImm(HiOffset << 2); // The immediate offset is in dwords,
|
.addImm(HiOffset); // The offset in register is in bytes.
|
||||||
// but offset in register is in bytes.
|
|
||||||
Hi = BuildMI(*MBB, MI, DL, get(HalfSGPROp), RegHi)
|
Hi = BuildMI(*MBB, MI, DL, get(HalfSGPROp), RegHi)
|
||||||
.addOperand(*SBase)
|
.addOperand(*SBase)
|
||||||
.addReg(OffsetSGPR);
|
.addReg(OffsetSGPR);
|
||||||
} else {
|
} else {
|
||||||
Hi = BuildMI(*MBB, MI, DL, get(HalfImmOp), RegHi)
|
Hi = BuildMI(*MBB, MI, DL, get(HalfImmOp), RegHi)
|
||||||
.addOperand(*SBase)
|
.addOperand(*SBase)
|
||||||
.addImm(HiOffset);
|
.addImm(HiOffset / OffScale);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Handle the _SGPR variant
|
// Handle the _SGPR variant
|
||||||
@ -1786,10 +1793,13 @@ void SIInstrInfo::moveSMRDToVALU(MachineInstr *MI, MachineRegisterInfo &MRI) con
|
|||||||
ImmOffset = 0;
|
ImmOffset = 0;
|
||||||
} else {
|
} else {
|
||||||
assert(MI->getOperand(2).isImm());
|
assert(MI->getOperand(2).isImm());
|
||||||
// SMRD instructions take a dword offsets and MUBUF instructions
|
// SMRD instructions take a dword offsets on SI and byte offset on VI
|
||||||
// take a byte offset.
|
// and MUBUF instructions always take a byte offset.
|
||||||
ImmOffset = MI->getOperand(2).getImm() << 2;
|
ImmOffset = MI->getOperand(2).getImm();
|
||||||
|
if (RI.ST.getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS)
|
||||||
|
ImmOffset <<= 2;
|
||||||
RegOffset = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
|
RegOffset = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
|
||||||
|
|
||||||
if (isUInt<12>(ImmOffset)) {
|
if (isUInt<12>(ImmOffset)) {
|
||||||
BuildMI(*MBB, MI, MI->getDebugLoc(), get(AMDGPU::S_MOV_B32),
|
BuildMI(*MBB, MI, MI->getDebugLoc(), get(AMDGPU::S_MOV_B32),
|
||||||
RegOffset)
|
RegOffset)
|
||||||
|
@ -209,7 +209,7 @@ public:
|
|||||||
|
|
||||||
/// \brief Return true if the given offset Size in bytes can be folded into
|
/// \brief Return true if the given offset Size in bytes can be folded into
|
||||||
/// the immediate offsets of a memory instruction for the given address space.
|
/// the immediate offsets of a memory instruction for the given address space.
|
||||||
static bool canFoldOffset(unsigned OffsetSize, unsigned AS) LLVM_READNONE;
|
bool canFoldOffset(unsigned OffsetSize, unsigned AS) const;
|
||||||
|
|
||||||
/// \brief Return true if this 64-bit VALU instruction has a 32-bit encoding.
|
/// \brief Return true if this 64-bit VALU instruction has a 32-bit encoding.
|
||||||
/// This function will return false if you pass it a 32-bit instruction.
|
/// This function will return false if you pass it a 32-bit instruction.
|
||||||
|
@ -171,6 +171,10 @@ def IMM16bit : PatLeaf <(imm),
|
|||||||
[{return isUInt<16>(N->getZExtValue());}]
|
[{return isUInt<16>(N->getZExtValue());}]
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
def IMM20bit : PatLeaf <(imm),
|
||||||
|
[{return isUInt<20>(N->getZExtValue());}]
|
||||||
|
>;
|
||||||
|
|
||||||
def IMM32bit : PatLeaf <(imm),
|
def IMM32bit : PatLeaf <(imm),
|
||||||
[{return isUInt<32>(N->getZExtValue());}]
|
[{return isUInt<32>(N->getZExtValue());}]
|
||||||
>;
|
>;
|
||||||
|
@ -34,6 +34,9 @@ def isSICI : Predicate<
|
|||||||
>;
|
>;
|
||||||
def isCI : Predicate<"Subtarget.getGeneration() "
|
def isCI : Predicate<"Subtarget.getGeneration() "
|
||||||
">= AMDGPUSubtarget::SEA_ISLANDS">;
|
">= AMDGPUSubtarget::SEA_ISLANDS">;
|
||||||
|
def isVI : Predicate <
|
||||||
|
"Subtarget.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS"
|
||||||
|
>;
|
||||||
|
|
||||||
def HasFlatAddressSpace : Predicate<"Subtarget.hasFlatAddressSpace()">;
|
def HasFlatAddressSpace : Predicate<"Subtarget.hasFlatAddressSpace()">;
|
||||||
|
|
||||||
@ -1974,7 +1977,7 @@ def : Pat <
|
|||||||
|
|
||||||
multiclass SMRD_Pattern <SMRD Instr_IMM, SMRD Instr_SGPR, ValueType vt> {
|
multiclass SMRD_Pattern <SMRD Instr_IMM, SMRD Instr_SGPR, ValueType vt> {
|
||||||
|
|
||||||
// 1. Offset as 8bit DWORD immediate
|
// 1. SI-CI: Offset as 8bit DWORD immediate
|
||||||
def : Pat <
|
def : Pat <
|
||||||
(constant_load (add i64:$sbase, (i64 IMM8bitDWORD:$offset))),
|
(constant_load (add i64:$sbase, (i64 IMM8bitDWORD:$offset))),
|
||||||
(vt (Instr_IMM $sbase, (as_dword_i32imm $offset)))
|
(vt (Instr_IMM $sbase, (as_dword_i32imm $offset)))
|
||||||
@ -1993,6 +1996,28 @@ multiclass SMRD_Pattern <SMRD Instr_IMM, SMRD Instr_SGPR, ValueType vt> {
|
|||||||
>;
|
>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
multiclass SMRD_Pattern_vi <SMRD Instr_IMM, SMRD Instr_SGPR, ValueType vt> {
|
||||||
|
|
||||||
|
// 1. VI: Offset as 20bit immediate in bytes
|
||||||
|
def : Pat <
|
||||||
|
(constant_load (add i64:$sbase, (i64 IMM20bit:$offset))),
|
||||||
|
(vt (Instr_IMM $sbase, (as_i32imm $offset)))
|
||||||
|
>;
|
||||||
|
|
||||||
|
// 2. Offset loaded in an 32bit SGPR
|
||||||
|
def : Pat <
|
||||||
|
(constant_load (add i64:$sbase, (i64 IMM32bit:$offset))),
|
||||||
|
(vt (Instr_SGPR $sbase, (S_MOV_B32 (i32 (as_i32imm $offset)))))
|
||||||
|
>;
|
||||||
|
|
||||||
|
// 3. No offset at all
|
||||||
|
def : Pat <
|
||||||
|
(constant_load i64:$sbase),
|
||||||
|
(vt (Instr_IMM $sbase, 0))
|
||||||
|
>;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Predicates = [isSICI] in {
|
||||||
defm : SMRD_Pattern <S_LOAD_DWORD_IMM, S_LOAD_DWORD_SGPR, f32>;
|
defm : SMRD_Pattern <S_LOAD_DWORD_IMM, S_LOAD_DWORD_SGPR, f32>;
|
||||||
defm : SMRD_Pattern <S_LOAD_DWORD_IMM, S_LOAD_DWORD_SGPR, i32>;
|
defm : SMRD_Pattern <S_LOAD_DWORD_IMM, S_LOAD_DWORD_SGPR, i32>;
|
||||||
defm : SMRD_Pattern <S_LOAD_DWORDX2_IMM, S_LOAD_DWORDX2_SGPR, v2i32>;
|
defm : SMRD_Pattern <S_LOAD_DWORDX2_IMM, S_LOAD_DWORDX2_SGPR, v2i32>;
|
||||||
@ -2000,6 +2025,19 @@ defm : SMRD_Pattern <S_LOAD_DWORDX4_IMM, S_LOAD_DWORDX4_SGPR, v4i32>;
|
|||||||
defm : SMRD_Pattern <S_LOAD_DWORDX8_IMM, S_LOAD_DWORDX8_SGPR, v32i8>;
|
defm : SMRD_Pattern <S_LOAD_DWORDX8_IMM, S_LOAD_DWORDX8_SGPR, v32i8>;
|
||||||
defm : SMRD_Pattern <S_LOAD_DWORDX8_IMM, S_LOAD_DWORDX8_SGPR, v8i32>;
|
defm : SMRD_Pattern <S_LOAD_DWORDX8_IMM, S_LOAD_DWORDX8_SGPR, v8i32>;
|
||||||
defm : SMRD_Pattern <S_LOAD_DWORDX16_IMM, S_LOAD_DWORDX16_SGPR, v16i32>;
|
defm : SMRD_Pattern <S_LOAD_DWORDX16_IMM, S_LOAD_DWORDX16_SGPR, v16i32>;
|
||||||
|
} // End Predicates = [isSICI]
|
||||||
|
|
||||||
|
let Predicates = [isVI] in {
|
||||||
|
defm : SMRD_Pattern_vi <S_LOAD_DWORD_IMM, S_LOAD_DWORD_SGPR, f32>;
|
||||||
|
defm : SMRD_Pattern_vi <S_LOAD_DWORD_IMM, S_LOAD_DWORD_SGPR, i32>;
|
||||||
|
defm : SMRD_Pattern_vi <S_LOAD_DWORDX2_IMM, S_LOAD_DWORDX2_SGPR, v2i32>;
|
||||||
|
defm : SMRD_Pattern_vi <S_LOAD_DWORDX4_IMM, S_LOAD_DWORDX4_SGPR, v4i32>;
|
||||||
|
defm : SMRD_Pattern_vi <S_LOAD_DWORDX8_IMM, S_LOAD_DWORDX8_SGPR, v32i8>;
|
||||||
|
defm : SMRD_Pattern_vi <S_LOAD_DWORDX8_IMM, S_LOAD_DWORDX8_SGPR, v8i32>;
|
||||||
|
defm : SMRD_Pattern_vi <S_LOAD_DWORDX16_IMM, S_LOAD_DWORDX16_SGPR, v16i32>;
|
||||||
|
} // End Predicates = [isVI]
|
||||||
|
|
||||||
|
let Predicates = [isSICI] in {
|
||||||
|
|
||||||
// 1. Offset as 8bit DWORD immediate
|
// 1. Offset as 8bit DWORD immediate
|
||||||
def : Pat <
|
def : Pat <
|
||||||
@ -2007,6 +2045,8 @@ def : Pat <
|
|||||||
(S_BUFFER_LOAD_DWORD_IMM $sbase, (as_dword_i32imm $offset))
|
(S_BUFFER_LOAD_DWORD_IMM $sbase, (as_dword_i32imm $offset))
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
} // End Predicates = [isSICI]
|
||||||
|
|
||||||
// 2. Offset loaded in an 32bit SGPR
|
// 2. Offset loaded in an 32bit SGPR
|
||||||
def : Pat <
|
def : Pat <
|
||||||
(SIload_constant v4i32:$sbase, imm:$offset),
|
(SIload_constant v4i32:$sbase, imm:$offset),
|
||||||
|
@ -9,10 +9,6 @@
|
|||||||
// Instruction definitions for VI and newer.
|
// Instruction definitions for VI and newer.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
def isVI : Predicate <
|
|
||||||
"Subtarget.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS"
|
|
||||||
>;
|
|
||||||
|
|
||||||
let SubtargetPredicate = isVI in {
|
let SubtargetPredicate = isVI in {
|
||||||
|
|
||||||
def V_LDEXP_F32 : VOP3InstVI <0x288, "v_ldexp_f32", VOP_F32_F32_I32,
|
def V_LDEXP_F32 : VOP3InstVI <0x288, "v_ldexp_f32", VOP_F32_F32_I32,
|
||||||
@ -53,6 +49,16 @@ def : Pat <
|
|||||||
(V_MBCNT_LO_U32_B32 0xffffffff, 0))
|
(V_MBCNT_LO_U32_B32 0xffffffff, 0))
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// SMEM Patterns
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// 1. Offset as 8bit DWORD immediate
|
||||||
|
def : Pat <
|
||||||
|
(SIload_constant v4i32:$sbase, IMM20bit:$offset),
|
||||||
|
(S_BUFFER_LOAD_DWORD_IMM $sbase, (as_i32imm $offset))
|
||||||
|
>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// MUBUF Patterns
|
// MUBUF Patterns
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
Loading…
x
Reference in New Issue
Block a user