Index: lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp =================================================================== --- lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -227,6 +227,10 @@ return isInlineImm() || (isReg() && isRegClass(AMDGPU::VS_64RegClassID)); } + bool isVCM0Src32() const { + return isInlineImm() || (isReg() && isRegClass(AMDGPU::VM0_32RegClassID)); + } + bool isVSrc32() const { return isImm() || (isReg() && isRegClass(AMDGPU::VS_32RegClassID)); } Index: lib/Target/AMDGPU/SIInstrInfo.td =================================================================== --- lib/Target/AMDGPU/SIInstrInfo.td +++ lib/Target/AMDGPU/SIInstrInfo.td @@ -1168,6 +1168,14 @@ def VOP_I32_F64 : VOPProfile <[i32, f64, untyped, untyped]>; def VOP_I32_I32 : VOPProfile <[i32, i32, untyped, untyped]>; +// Special case for v_movrel*_b32 instructions which have an implicit +// m0 use. An SGPR besides m0 can't be used for src0 because of the +// constant bus restriction with the implicit use. +def VOP_I32_I32_M0 : VOPProfile <[i32, i32, untyped, untyped]> { + let Src0RC32 = VCM0Src_32; + let Src0RC64 = VCM0Src_32; +} + def VOP_F32_F32_F32 : VOPProfile <[f32, f32, f32, untyped]>; def VOP_F32_F32_I32 : VOPProfile <[f32, f32, i32, untyped]>; def VOP_F64_F64_F64 : VOPProfile <[f64, f64, f64, untyped]>; Index: lib/Target/AMDGPU/SIInstructions.td =================================================================== --- lib/Target/AMDGPU/SIInstructions.td +++ lib/Target/AMDGPU/SIInstructions.td @@ -1341,9 +1341,9 @@ } let Uses = [M0, EXEC] in { -defm V_MOVRELD_B32 : VOP1Inst , "v_movreld_b32", VOP_I32_I32>; -defm V_MOVRELS_B32 : VOP1Inst , "v_movrels_b32", VOP_I32_I32>; -defm V_MOVRELSD_B32 : VOP1Inst , "v_movrelsd_b32", VOP_I32_I32>; +defm V_MOVRELD_B32 : VOP1Inst , "v_movreld_b32", VOP_I32_I32_M0>; +defm V_MOVRELS_B32 : VOP1Inst , "v_movrels_b32", VOP_I32_I32_M0>; +defm V_MOVRELSD_B32 : VOP1Inst , "v_movrelsd_b32", VOP_I32_I32_M0>; } // End Uses = [M0, EXEC] // These instruction only exist on SI and CI Index: lib/Target/AMDGPU/SIRegisterInfo.td =================================================================== --- lib/Target/AMDGPU/SIRegisterInfo.td +++ lib/Target/AMDGPU/SIRegisterInfo.td @@ -291,6 +291,24 @@ } //===----------------------------------------------------------------------===// +// VM0_32_* Operands with an VGPR, m0 or a 32-bit immediate +//===----------------------------------------------------------------------===// + +def VM0_32 : RegisterClass<"AMDGPU", [i32, f32], 32, (add VGPR_32, M0)> { + // This is only for modeling operand constraints. + let isAllocatable = 0; +} + +// Special case for v_movrel* instructions. The encoding allows SGPRs, +// but due to the constant bus restriction, only m0 could be allowed +// (although probably not useful). +def VCM0Src_32 : RegisterOperand { + let OperandNamespace = "AMDGPU"; + let OperandType = "OPERAND_REG_IMM32"; + let ParserMatchClass = RegImmMatcher<"VCM0Src32">; +} + +//===----------------------------------------------------------------------===// // VCSrc_* Operands with an SGPR, VGPR or an inline constant //===----------------------------------------------------------------------===// Index: test/CodeGen/AMDGPU/ds_read2st64.ll =================================================================== --- test/CodeGen/AMDGPU/ds_read2st64.ll +++ test/CodeGen/AMDGPU/ds_read2st64.ll @@ -65,9 +65,9 @@ ; SI-LABEL: @simple_read2st64_f32_over_max_offset ; SI-NOT: ds_read2st64_b32 -; SI: v_add_i32_e32 [[BIGADD:v[0-9]+]], vcc, 0x10000, {{v[0-9]+}} -; SI: ds_read_b32 {{v[0-9]+}}, {{v[0-9]+}} offset:256 -; SI: ds_read_b32 {{v[0-9]+}}, [[BIGADD]] +; SI-DAG: v_add_i32_e32 [[BIGADD:v[0-9]+]], vcc, 0x10000, {{v[0-9]+}} +; SI-DAG: ds_read_b32 {{v[0-9]+}}, {{v[0-9]+}} offset:256 +; SI-DAG: ds_read_b32 {{v[0-9]+}}, [[BIGADD]] ; SI: s_endpgm define void @simple_read2st64_f32_over_max_offset(float addrspace(1)* %out, float addrspace(3)* %lds) #0 { %x.i = tail call i32 @llvm.r600.read.tidig.x() #1 Index: test/MC/AMDGPU/vop1-err.s =================================================================== --- /dev/null +++ test/MC/AMDGPU/vop1-err.s @@ -0,0 +1,58 @@ +// RUN: not llvm-mc -arch=amdgcn %s 2>&1 | FileCheck %s +// RUN: not llvm-mc -arch=amdgcn -mcpu=tonga %s 2>&1 | FileCheck %s + +// SGPR not allowed due to constant bus restriction with implicit m0 read. + +// CHECK: error: invalid operand for instruction +v_movreld_b32 v1, s0 + +// CHECK: error: invalid operand for instruction +v_movrels_b32 v1, s0 + +// CHECK: error: invalid operand for instruction +v_movrelsd_b32 v1, s0 + +// CHECK: error: invalid operand for instruction +v_movreld_b32_e32 v1, s0 + +// CHECK: error: invalid operand for instruction +v_movrels_b32_e32 v1, s0 + +// CHECK: error: invalid operand for instruction +v_movrelsd_b32_e32 v1, s0 + +// CHECK: error: invalid operand for instruction +v_movreld_b32_e64 v1, s0 + +// CHECK: error: invalid operand for instruction +v_movrels_b32_e64 v1, s0 + +// CHECK: error: invalid operand for instruction +v_movrelsd_b32_e64 v1, s0 + +// CHECK: error: invalid operand for instruction +v_movreld_b32 v1, 0x1234 + +// CHECK: error: invalid operand for instruction +v_movrels_b32 v1, 0x1234 + +// CHECK: error: invalid operand for instruction +v_movrelsd_b32 v1, 0x1234 + +// CHECK: error: invalid operand for instruction +v_movreld_b32_e32 v1, 0x1234 + +// CHECK: error: invalid operand for instruction +v_movrels_b32_e32 v1, 0x1234 + +// CHECK: error: invalid operand for instruction +v_movrelsd_b32_e32 v1, 0x1234 + +// CHECK: error: invalid operand for instruction +v_movreld_b32_e64 v1, 0x1234 + +// CHECK: error: invalid operand for instruction +v_movrels_b32_e64 v1, 0x1234 + +// CHECK: error: invalid operand for instruction +v_movrelsd_b32_e64 v1, 0x1234 Index: test/MC/AMDGPU/vop1.s =================================================================== --- test/MC/AMDGPU/vop1.s +++ test/MC/AMDGPU/vop1.s @@ -265,14 +265,38 @@ // VI: v_movreld_b32_e32 v1, v2 ; encoding: [0x02,0x6d,0x02,0x7e] v_movreld_b32 v1, v2 +// SICI: v_movreld_b32_e32 v1, m0 ; encoding: [0x7c,0x84,0x02,0x7e] +// VI: v_movreld_b32_e32 v1, m0 ; encoding: [0x7c,0x6c,0x02,0x7e] +v_movreld_b32 v1, m0 + +// SICI: v_movreld_b32_e32 v1, 7 ; encoding: [0x87,0x84,0x02,0x7e] +// VI: v_movreld_b32_e32 v1, 7 ; encoding: [0x87,0x6c,0x02,0x7e] +v_movreld_b32 v1, 7 + // SICI: v_movrels_b32_e32 v1, v2 ; encoding: [0x02,0x87,0x02,0x7e] // VI: v_movrels_b32_e32 v1, v2 ; encoding: [0x02,0x6f,0x02,0x7e] v_movrels_b32 v1, v2 +// SICI: v_movrels_b32_e32 v1, m0 ; encoding: [0x7c,0x86,0x02,0x7e] +// VI: v_movrels_b32_e32 v1, m0 ; encoding: [0x7c,0x6e,0x02,0x7e] +v_movrels_b32 v1, m0 + +// SICI: v_movrels_b32_e32 v1, 7 ; encoding: [0x87,0x86,0x02,0x7e] +// VI: v_movrels_b32_e32 v1, 7 ; encoding: [0x87,0x6e,0x02,0x7e] +v_movrels_b32 v1, 7 + // SICI: v_movrelsd_b32_e32 v1, v2 ; encoding: [0x02,0x89,0x02,0x7e] // VI: v_movrelsd_b32_e32 v1, v2 ; encoding: [0x02,0x71,0x02,0x7e] v_movrelsd_b32 v1, v2 +// SICI: v_movrelsd_b32_e32 v1, m0 ; encoding: [0x7c,0x88,0x02,0x7e] +// VI: v_movrelsd_b32_e32 v1, m0 ; encoding: [0x7c,0x70,0x02,0x7e] +v_movrelsd_b32 v1, m0 + +// SICI: v_movrelsd_b32_e32 v1, 7 ; encoding: [0x87,0x88,0x02,0x7e] +// VI: v_movrelsd_b32_e32 v1, 7 ; encoding: [0x87,0x70,0x02,0x7e] +v_movrelsd_b32 v1, 7 + // NOSI: error: instruction not supported on this GPU // NOSI: v_log_legacy_f32 v1, v2 // CI: v_log_legacy_f32_e32 v1, v2 ; encoding: [0x02,0x8b,0x02,0x7e]