llvm.org GIT mirror llvm / a03e767
[AMDGPU][MC] Corrected V_*QSAD* instructions to check that dest register is different than any of the src See Bug 33279: https://bugs.llvm.org//show_bug.cgi?id=33279 Reviewers: artem.tamazov, vpykhtin Differential Revision: https://reviews.llvm.org/D34003 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305915 91177308-0d34-0410-b5e6-96231b3b80d8 Dmitry Preobrazhensky 3 years ago
6 changed file(s) with 117 addition(s) and 14 deletion(s). Raw diff Collapse all Expand all
994994 void errorExpTgt();
995995 OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val);
996996
997 bool validateOperandLimitations(const MCInst &Inst);
997 bool validateInstruction(const MCInst &Inst, const SMLoc &IDLoc);
998 bool validateConstantBusLimitations(const MCInst &Inst);
999 bool validateEarlyClobberLimitations(const MCInst &Inst);
9981000 bool usesConstantBus(const MCInst &Inst, unsigned OpIdx);
9991001 bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const;
10001002 unsigned findImplicitSGPRReadInVOP(const MCInst &Inst) const;
20942096 isSGPR(mc2PseudoReg(MO.getReg()), getContext().getRegisterInfo());
20952097 }
20962098
2097 bool AMDGPUAsmParser::validateOperandLimitations(const MCInst &Inst) {
2099 bool AMDGPUAsmParser::validateConstantBusLimitations(const MCInst &Inst) {
20982100 const unsigned Opcode = Inst.getOpcode();
20992101 const MCInstrDesc &Desc = MII.get(Opcode);
21002102 unsigned ConstantBusUseCount = 0;
21462148 }
21472149
21482150 return ConstantBusUseCount <= 1;
2151 }
2152
2153 bool AMDGPUAsmParser::validateEarlyClobberLimitations(const MCInst &Inst) {
2154
2155 const unsigned Opcode = Inst.getOpcode();
2156 const MCInstrDesc &Desc = MII.get(Opcode);
2157
2158 const int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
2159 if (DstIdx == -1 ||
2160 Desc.getOperandConstraint(DstIdx, MCOI::EARLY_CLOBBER) == -1) {
2161 return true;
2162 }
2163
2164 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
2165
2166 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
2167 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
2168 const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
2169
2170 assert(DstIdx != -1);
2171 const MCOperand &Dst = Inst.getOperand(DstIdx);
2172 assert(Dst.isReg());
2173 const unsigned DstReg = mc2PseudoReg(Dst.getReg());
2174
2175 const int SrcIndices[] = { Src0Idx, Src1Idx, Src2Idx };
2176
2177 for (int SrcIdx : SrcIndices) {
2178 if (SrcIdx == -1) break;
2179 const MCOperand &Src = Inst.getOperand(SrcIdx);
2180 if (Src.isReg()) {
2181 const unsigned SrcReg = mc2PseudoReg(Src.getReg());
2182 if (isRegIntersect(DstReg, SrcReg, TRI)) {
2183 return false;
2184 }
2185 }
2186 }
2187
2188 return true;
2189 }
2190
2191 bool AMDGPUAsmParser::validateInstruction(const MCInst &Inst,
2192 const SMLoc &IDLoc) {
2193 if (!validateConstantBusLimitations(Inst)) {
2194 Error(IDLoc,
2195 "invalid operand (violates constant bus restrictions)");
2196 return false;
2197 }
2198 if (!validateEarlyClobberLimitations(Inst)) {
2199 Error(IDLoc,
2200 "destination must be different than all sources");
2201 return false;
2202 }
2203
2204 return true;
21492205 }
21502206
21512207 bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
21802236 switch (Result) {
21812237 default: break;
21822238 case Match_Success:
2183 if (!validateOperandLimitations(Inst)) {
2184 return Error(IDLoc,
2185 "invalid operand (violates constant bus restrictions)");
2239 if (!validateInstruction(Inst, IDLoc)) {
2240 return true;
21862241 }
21872242 Inst.setLoc(IDLoc);
21882243 Out.EmitInstruction(Inst, getSTI());
535535 const unsigned FirstSubReg = TRI->getSubReg(Reg, 1);
536536 return SGPRClass.contains(FirstSubReg != 0 ? FirstSubReg : Reg) ||
537537 Reg == AMDGPU::SCC;
538 }
539
540 bool isRegIntersect(unsigned Reg0, unsigned Reg1, const MCRegisterInfo* TRI) {
541
542 if (Reg0 == Reg1) {
543 return true;
544 }
545
546 unsigned SubReg0 = TRI->getSubReg(Reg0, 1);
547 if (SubReg0 == 0) {
548 return TRI->getSubRegIndex(Reg1, Reg0) > 0;
549 }
550
551 for (unsigned Idx = 2; SubReg0 > 0; ++Idx) {
552 if (isRegIntersect(Reg1, SubReg0, TRI)) {
553 return true;
554 }
555 SubReg0 = TRI->getSubReg(Reg0, Idx);
556 }
557
558 return false;
538559 }
539560
540561 unsigned getMCReg(unsigned Reg, const MCSubtargetInfo &STI) {
270270 /// \brief Is Reg - scalar register
271271 bool isSGPR(unsigned Reg, const MCRegisterInfo* TRI);
272272
273 /// \brief Is there any intersection between registers
274 bool isRegIntersect(unsigned Reg0, unsigned Reg1, const MCRegisterInfo* TRI);
275
273276 /// If \p Reg is a pseudo reg, return the correct hardware register given
274277 /// \p STI otherwise return \p Reg.
275278 unsigned getMCReg(unsigned Reg, const MCSubtargetInfo &STI);
0 // RUN: llvm-mc -arch=amdgcn -mcpu=bonaire -show-encoding %s | FileCheck %s --check-prefix=GCN --check-prefix=SICI --check-prefix=CI
11 // RUN: llvm-mc -arch=amdgcn -mcpu=tonga -show-encoding %s | FileCheck %s --check-prefix=GCN --check-prefix=CIVI --check-prefix=VI
22
3 v_mqsad_pk_u16_u8 v[0:1], s[0:1], 1, v[254:255]
4 // CI: [0x00,0x00,0xe6,0xd2,0x00,0x02,0xf9,0x07]
5 // VI: [0x00,0x00,0xe6,0xd1,0x00,0x02,0xf9,0x07]
3 v_mqsad_pk_u16_u8 v[2:3], s[0:1], 1, v[254:255]
4 // CI: [0x02,0x00,0xe6,0xd2,0x00,0x02,0xf9,0x07]
5 // VI: [0x02,0x00,0xe6,0xd1,0x00,0x02,0xf9,0x07]
66
7 v_qsad_pk_u16_u8 v[0:1], v[0:1], 1, s[0:1]
8 // CI: [0x00,0x00,0xe4,0xd2,0x00,0x03,0x01,0x00]
9 // VI: [0x00,0x00,0xe5,0xd1,0x00,0x03,0x01,0x00]
7 v_qsad_pk_u16_u8 v[2:3], v[0:1], 1, s[0:1]
8 // CI: [0x02,0x00,0xe4,0xd2,0x00,0x03,0x01,0x00]
9 // VI: [0x02,0x00,0xe5,0xd1,0x00,0x03,0x01,0x00]
88
99 v_mqsad_u32_u8 v[0:3], s[2:3], v4, v[0:3]
1010 // CHECK: error: instruction not supported on this GPU
11
12 v_mqsad_pk_u16_u8 v[0:1], v[1:2], v9, v[4:5]
13 // CHECK: error: destination must be different than all sources
14
15 v_mqsad_pk_u16_u8 v[1:2], v[1:2], v9, v[4:5]
16 // CHECK: error: destination must be different than all sources
17
18 v_mqsad_pk_u16_u8 v[2:3], v[1:2], v9, v[4:5]
19 // CHECK: error: destination must be different than all sources
20
21 v_mqsad_pk_u16_u8 v[3:4], v[0:1], v9, v[4:5]
22 // CHECK: error: destination must be different than all sources
23
24 v_mqsad_pk_u16_u8 v[4:5], v[1:2], v9, v[4:5]
25 // CHECK: error: destination must be different than all sources
26
27 v_mqsad_pk_u16_u8 v[5:6], v[1:2], v9, v[4:5]
28 // CHECK: error: destination must be different than all sources
29
30 v_mqsad_pk_u16_u8 v[8:9], v[1:2], v9, v[4:5]
31 // CHECK: error: destination must be different than all sources
32
33 v_mqsad_pk_u16_u8 v[9:10], v[1:2], v9, v[4:5]
34 // CHECK: error: destination must be different than all sources
384384 // SICI: v_mad_f32 v9, 0.5, v5, -v8 ; encoding: [0x09,0x00,0x82,0xd2,0xf0,0x0a,0x22,0x84]
385385 // VI: v_mad_f32 v9, 0.5, v5, -v8 ; encoding: [0x09,0x00,0xc1,0xd1,0xf0,0x0a,0x22,0x84]
386386
387 v_mqsad_u32_u8 v[0:3], s[2:3], v4, v[0:3]
388 // CI: v_mqsad_u32_u8 v[0:3], s[2:3], v4, v[0:3] ; encoding: [0x00,0x00,0xea,0xd2,0x02,0x08,0x02,0x04]
389 // VI: v_mqsad_u32_u8 v[0:3], s[2:3], v4, v[0:3] ; encoding: [0x00,0x00,0xe7,0xd1,0x02,0x08,0x02,0x04]
387 v_mqsad_u32_u8 v[5:8], s[2:3], v4, v[0:3]
388 // CI: v_mqsad_u32_u8 v[5:8], s[2:3], v4, v[0:3] ; encoding: [0x05,0x00,0xea,0xd2,0x02,0x08,0x02,0x04]
389 // VI: v_mqsad_u32_u8 v[5:8], s[2:3], v4, v[0:3] ; encoding: [0x05,0x00,0xe7,0xd1,0x02,0x08,0x02,0x04]
390390 // NOSI: error: instruction not supported on this GPU
391391
392392 v_mad_u64_u32 v[5:6], s[12:13], s1, 0, 0