summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorDmitry Preobrazhensky <dmitry.preobrazhensky@amd.com>2018-01-26 16:42:51 +0000
committerDmitry Preobrazhensky <dmitry.preobrazhensky@amd.com>2018-01-26 16:42:51 +0000
commit706828157f0914ca5925800a22a41a0507c78271 (patch)
treebac57b0b663aa610546409714df149eb5c003a25 /llvm/lib
parent61e07bb4814ad89405040a111a629f9e124a10ae (diff)
downloadbcm5719-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.cpp61
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;
}
OpenPOWER on IntegriCloud