diff options
author | Dmitry Preobrazhensky <dmitry.preobrazhensky@amd.com> | 2018-01-26 16:42:51 +0000 |
---|---|---|
committer | Dmitry Preobrazhensky <dmitry.preobrazhensky@amd.com> | 2018-01-26 16:42:51 +0000 |
commit | 706828157f0914ca5925800a22a41a0507c78271 (patch) | |
tree | bac57b0b663aa610546409714df149eb5c003a25 /llvm/lib | |
parent | 61e07bb4814ad89405040a111a629f9e124a10ae (diff) | |
download | bcm5719-llvm-706828157f0914ca5925800a22a41a0507c78271.tar.gz bcm5719-llvm-706828157f0914ca5925800a22a41a0507c78271.zip |
[AMDGPU][MC] Added validation of image dst/data size (must match dmask and tfe)
See bug 36000: https://bugs.llvm.org/show_bug.cgi?id=36000
Differential Revision: https://reviews.llvm.org/D42483
Reviewers: vpykhtin, artem.tamazov, arsenm
llvm-svn: 323538
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp index 7a7ed39428e..75e584f9650 100644 --- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -1037,6 +1037,8 @@ private: bool validateConstantBusLimitations(const MCInst &Inst); bool validateEarlyClobberLimitations(const MCInst &Inst); bool validateIntClampSupported(const MCInst &Inst); + bool validateMIMGAtomicDMask(const MCInst &Inst); + bool validateMIMGDataSize(const MCInst &Inst); bool usesConstantBus(const MCInst &Inst, unsigned OpIdx); bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const; unsigned findImplicitSGPRReadInVOP(const MCInst &Inst) const; @@ -2271,6 +2273,55 @@ bool AMDGPUAsmParser::validateIntClampSupported(const MCInst &Inst) { return true; } +bool AMDGPUAsmParser::validateMIMGDataSize(const MCInst &Inst) { + + const unsigned Opc = Inst.getOpcode(); + const MCInstrDesc &Desc = MII.get(Opc); + + if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0) + return true; + + // Gather4 instructions seem to have special rules not described in spec. + if (Desc.TSFlags & SIInstrFlags::Gather4) + return true; + + int VDataIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata); + int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask); + int TFEIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::tfe); + + assert(VDataIdx != -1); + assert(DMaskIdx != -1); + assert(TFEIdx != -1); + + unsigned VDataSize = AMDGPU::getRegOperandSize(getMRI(), Desc, VDataIdx); + unsigned TFESize = Inst.getOperand(TFEIdx).getImm()? 1 : 0; + unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf; + if (DMask == 0) + DMask = 1; + + return (VDataSize / 4) == countPopulation(DMask) + TFESize; +} + +bool AMDGPUAsmParser::validateMIMGAtomicDMask(const MCInst &Inst) { + + const unsigned Opc = Inst.getOpcode(); + const MCInstrDesc &Desc = MII.get(Opc); + + if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0) + return true; + if (!Desc.mayLoad() || !Desc.mayStore()) + return true; // Not atomic + + int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask); + unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf; + + // This is an incomplete check because image_atomic_cmpswap + // may only use 0x3 and 0xf while other atomic operations + // may use 0x1 and 0x3. However these limitations are + // verified when we check that dmask matches dst size. + return DMask == 0x1 || DMask == 0x3 || DMask == 0xf; +} + bool AMDGPUAsmParser::validateInstruction(const MCInst &Inst, const SMLoc &IDLoc) { if (!validateConstantBusLimitations(Inst)) { @@ -2288,6 +2339,16 @@ bool AMDGPUAsmParser::validateInstruction(const MCInst &Inst, "integer clamping is not supported on this GPU"); return false; } + if (!validateMIMGDataSize(Inst)) { + Error(IDLoc, + "image data size does not match dmask and tfe"); + return false; + } + if (!validateMIMGAtomicDMask(Inst)) { + Error(IDLoc, + "invalid atomic image dmask"); + return false; + } return true; } |