diff options
author | Tom Stellard <thomas.stellard@amd.com> | 2016-02-22 19:17:56 +0000 |
---|---|---|
committer | Tom Stellard <thomas.stellard@amd.com> | 2016-02-22 19:17:56 +0000 |
commit | d93a34f714827eeb9c84b39549402c9325085b3c (patch) | |
tree | a5dcbf61807ab3ba46eb133f023e4567ec702bfc /llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp | |
parent | 82fc153baa79c28e1fa480e9a26eb160272d4ee9 (diff) | |
download | bcm5719-llvm-d93a34f714827eeb9c84b39549402c9325085b3c.tar.gz bcm5719-llvm-d93a34f714827eeb9c84b39549402c9325085b3c.zip |
[AMDGPU][llvm-mc] Support for 32-bit inline literals
Patch by: Artem Tamazov
Summary:
Note: Support for 64-bit inline literals TBD
Added: Support of abs/neg modifiers for literals (incomplete; parsing TBD).
Added: Some TODO comments.
Reworked/clarity: rename isInlineImm() to isInlinableImm()
Reworked/robustness: disallow BitsToFloat() with undefined value in isInlinableImm()
Reworked/reuse: isSSrc32/64(), isVSrc32/64()
Tests added.
Reviewers: tstellarAMD, arsenm
Subscribers: vpykhtin, nhaustov, SamWot, arsenm
Projects: #llvm-amdgpu-spb
Differential Revision: http://reviews.llvm.org/D17204
llvm-svn: 261559
Diffstat (limited to 'llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp')
-rw-r--r-- | llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp | 91 |
1 files changed, 58 insertions, 33 deletions
diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp index 07fba8c36d0..6458955b3ef 100644 --- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -79,6 +79,7 @@ public: bool IsFPImm; ImmTy Type; int64_t Val; + int Modifiers; }; struct RegOp { @@ -109,15 +110,20 @@ public: } void addRegOrImmOperands(MCInst &Inst, unsigned N) const { - if (isReg()) + if (isRegKind()) addRegOperands(Inst, N); else addImmOperands(Inst, N); } - void addRegWithInputModsOperands(MCInst &Inst, unsigned N) const { - Inst.addOperand(MCOperand::createImm(Reg.Modifiers)); - addRegOperands(Inst, N); + void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const { + if (isRegKind()) { + Inst.addOperand(MCOperand::createImm(Reg.Modifiers)); + addRegOperands(Inst, N); + } else { + Inst.addOperand(MCOperand::createImm(Imm.Modifiers)); + addImmOperands(Inst, N); + } } void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const { @@ -143,12 +149,18 @@ public: return Kind == Immediate; } - bool isInlineImm() const { - float F = BitsToFloat(Imm.Val); - // TODO: Add 0.5pi for VI - return isImm() && ((Imm.Val <= 64 && Imm.Val >= -16) || + bool isInlinableImm() const { + if (!isImm() || Imm.Type != AMDGPUOperand::ImmTyNone /* Only plain + immediates are inlinable (e.g. "clamp" attribute is not) */ ) + return false; + // TODO: We should avoid using host float here. It would be better to + // check the float bit values which is what a few other places do. + // We've had bot failures before due to weird NaN support on mips hosts. + const float F = BitsToFloat(Imm.Val); + // TODO: Add 1/(2*pi) for VI + return (Imm.Val <= 64 && Imm.Val >= -16) || (F == 0.0 || F == 0.5 || F == -0.5 || F == 1.0 || F == -1.0 || - F == 2.0 || F == -2.0 || F == 4.0 || F == -4.0)); + F == 2.0 || F == -2.0 || F == 4.0 || F == -4.0); } bool isDSOffset0() const { @@ -178,8 +190,8 @@ public: return Kind == Register && Reg.Modifiers == 0; } - bool isRegWithInputMods() const { - return Kind == Register; + bool isRegOrImmWithInputMods() const { + return Kind == Register || isInlinableImm(); } bool isClamp() const { @@ -195,13 +207,16 @@ public: } void setModifiers(unsigned Mods) { - assert(isReg()); - Reg.Modifiers = Mods; + assert(isReg() || (isImm() && Imm.Modifiers == 0)); + if (isReg()) + Reg.Modifiers = Mods; + else + Imm.Modifiers = Mods; } bool hasModifiers() const { - assert(isRegKind()); - return Reg.Modifiers != 0; + assert(isRegKind() || isImm()); + return isRegKind() ? Reg.Modifiers != 0 : Imm.Modifiers != 0; } unsigned getReg() const override { @@ -217,36 +232,42 @@ public: } bool isSCSrc32() const { - return isInlineImm() || (isReg() && isRegClass(AMDGPU::SReg_32RegClassID)); + return isInlinableImm() || (isReg() && isRegClass(AMDGPU::SReg_32RegClassID)); } - bool isSSrc32() const { - return isImm() || (isReg() && isRegClass(AMDGPU::SReg_32RegClassID)); + bool isSCSrc64() const { + return isInlinableImm() || (isReg() && isRegClass(AMDGPU::SReg_64RegClassID)); } - bool isSSrc64() const { - return isImm() || isInlineImm() || - (isReg() && isRegClass(AMDGPU::SReg_64RegClassID)); + bool isSSrc32() const { + return isImm() || isSCSrc32(); } - bool isSCSrc64() const { - return (isReg() && isRegClass(AMDGPU::SReg_64RegClassID)) || isInlineImm(); + bool isSSrc64() const { + // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits. + // See isVSrc64(). + return isImm() || isSCSrc64(); } bool isVCSrc32() const { - return isInlineImm() || (isReg() && isRegClass(AMDGPU::VS_32RegClassID)); + return isInlinableImm() || (isReg() && isRegClass(AMDGPU::VS_32RegClassID)); } bool isVCSrc64() const { - return isInlineImm() || (isReg() && isRegClass(AMDGPU::VS_64RegClassID)); + return isInlinableImm() || (isReg() && isRegClass(AMDGPU::VS_64RegClassID)); } bool isVSrc32() const { - return isImm() || (isReg() && isRegClass(AMDGPU::VS_32RegClassID)); + return isImm() || isVCSrc32(); } bool isVSrc64() const { - return isImm() || (isReg() && isRegClass(AMDGPU::VS_64RegClassID)); + // TODO: Check if the 64-bit value (coming from assembly source) can be + // narrowed to 32 bits (in the instruction stream). That require knowledge + // of instruction type (unsigned/signed, floating or "untyped"/B64), + // see [AMD GCN3 ISA 6.3.1]. + // TODO: How 64-bit values are formed from 32-bit literals in _B64 insns? + return isImm() || isVCSrc64(); } bool isMem() const override { @@ -275,7 +296,10 @@ public: OS << "<register " << getReg() << " mods: " << Reg.Modifiers << '>'; break; case Immediate: - OS << getImm(); + if (Imm.Type != AMDGPUOperand::ImmTyNone) + OS << getImm(); + else + OS << '<' << getImm() << " mods: " << Imm.Modifiers << '>'; break; case Token: OS << '\'' << getToken() << '\''; @@ -293,6 +317,7 @@ public: Op->Imm.Val = Val; Op->Imm.IsFPImm = IsFPImm; Op->Imm.Type = Type; + Op->Imm.Modifiers = 0; Op->StartLoc = Loc; Op->EndLoc = Loc; return Op; @@ -1099,6 +1124,8 @@ static bool operandsHaveModifiers(const OperandVector &Operands) { const AMDGPUOperand &Op = ((AMDGPUOperand&)*Operands[i]); if (Op.isRegKind() && Op.hasModifiers()) return true; + if (Op.isImm() && Op.hasModifiers()) + return true; if (Op.isImm() && (Op.getImmTy() == AMDGPUOperand::ImmTyOMod || Op.getImmTy() == AMDGPUOperand::ImmTyClamp)) return true; @@ -1843,7 +1870,7 @@ AMDGPUAsmParser::parseVOP3OptionalOps(OperandVector &Operands) { // previous register operands have modifiers for (unsigned i = 2, e = Operands.size(); i != e; ++i) { AMDGPUOperand &Op = ((AMDGPUOperand&)*Operands[i]); - if (Op.isReg()) + if ((Op.isReg() || Op.isImm()) && !Op.hasModifiers()) Op.setModifiers(0); } } @@ -1892,14 +1919,12 @@ void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) { unsigned ClampIdx = 0, OModIdx = 0; for (unsigned E = Operands.size(); I != E; ++I) { AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); - if (Op.isRegWithInputMods()) { - Op.addRegWithInputModsOperands(Inst, 2); + if (Op.isRegOrImmWithInputMods()) { + Op.addRegOrImmWithInputModsOperands(Inst, 2); } else if (Op.isClamp()) { ClampIdx = I; } else if (Op.isOMod()) { OModIdx = I; - } else if (Op.isImm()) { - Op.addImmOperands(Inst, 1); } else { assert(false); } |