summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp')
-rw-r--r--llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp205
1 files changed, 158 insertions, 47 deletions
diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
index 453d0d91d3e..80c815e830b 100644
--- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
+++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
@@ -215,6 +215,10 @@ public:
return isRegKind() || isInlinableImm(type);
}
+ bool isRegOrImmWithInt16InputMods() const {
+ return isRegOrImmWithInputMods(MVT::i16);
+ }
+
bool isRegOrImmWithInt32InputMods() const {
return isRegOrImmWithInputMods(MVT::i32);
}
@@ -223,6 +227,10 @@ public:
return isRegOrImmWithInputMods(MVT::i64);
}
+ bool isRegOrImmWithFP16InputMods() const {
+ return isRegOrImmWithInputMods(MVT::f16);
+ }
+
bool isRegOrImmWithFP32InputMods() const {
return isRegOrImmWithInputMods(MVT::f32);
}
@@ -282,6 +290,10 @@ public:
bool isRegClass(unsigned RCID) const;
+ bool isSCSrcB16() const {
+ return isRegClass(AMDGPU::SReg_32RegClassID) || isInlinableImm(MVT::i16);
+ }
+
bool isSCSrcB32() const {
return isRegClass(AMDGPU::SReg_32RegClassID) || isInlinableImm(MVT::i32);
}
@@ -290,6 +302,10 @@ public:
return isRegClass(AMDGPU::SReg_64RegClassID) || isInlinableImm(MVT::i64);
}
+ bool isSCSrcF16() const {
+ return isRegClass(AMDGPU::SReg_32RegClassID) || isInlinableImm(MVT::f16);
+ }
+
bool isSCSrcF32() const {
return isRegClass(AMDGPU::SReg_32RegClassID) || isInlinableImm(MVT::f32);
}
@@ -302,6 +318,10 @@ public:
return isSCSrcB32() || isLiteralImm(MVT::i32) || isExpr();
}
+ bool isSSrcB16() const {
+ return isSCSrcB16() || isLiteralImm(MVT::i16);
+ }
+
bool isSSrcB64() const {
// TODO: Find out how SALU supports extension of 32-bit literals to 64 bits.
// See isVSrc64().
@@ -316,6 +336,10 @@ public:
return isSCSrcB64() || isLiteralImm(MVT::f64);
}
+ bool isSSrcF16() const {
+ return isSCSrcB16() || isLiteralImm(MVT::f16);
+ }
+
bool isVCSrcB32() const {
return isRegClass(AMDGPU::VS_32RegClassID) || isInlinableImm(MVT::i32);
}
@@ -324,6 +348,10 @@ public:
return isRegClass(AMDGPU::VS_64RegClassID) || isInlinableImm(MVT::i64);
}
+ bool isVCSrcB16() const {
+ return isRegClass(AMDGPU::VS_32RegClassID) || isInlinableImm(MVT::i16);
+ }
+
bool isVCSrcF32() const {
return isRegClass(AMDGPU::VS_32RegClassID) || isInlinableImm(MVT::f32);
}
@@ -332,6 +360,10 @@ public:
return isRegClass(AMDGPU::VS_64RegClassID) || isInlinableImm(MVT::f64);
}
+ bool isVCSrcF16() const {
+ return isRegClass(AMDGPU::VS_32RegClassID) || isInlinableImm(MVT::f16);
+ }
+
bool isVSrcB32() const {
return isVCSrcF32() || isLiteralImm(MVT::i32);
}
@@ -340,6 +372,10 @@ public:
return isVCSrcF64() || isLiteralImm(MVT::i64);
}
+ bool isVSrcB16() const {
+ return isVCSrcF16() || isLiteralImm(MVT::i16);
+ }
+
bool isVSrcF32() const {
return isVCSrcF32() || isLiteralImm(MVT::f32);
}
@@ -348,10 +384,18 @@ public:
return isVCSrcF64() || isLiteralImm(MVT::f64);
}
+ bool isVSrcF16() const {
+ return isVCSrcF16() || isLiteralImm(MVT::f16);
+ }
+
bool isKImmFP32() const {
return isLiteralImm(MVT::f32);
}
+ bool isKImmFP16() const {
+ return isLiteralImm(MVT::f16);
+ }
+
bool isMem() const override {
return false;
}
@@ -439,7 +483,16 @@ public:
void addLiteralImmOperand(MCInst &Inst, int64_t Val) const;
- void addKImmFP32Operands(MCInst &Inst, unsigned N) const;
+ template <unsigned Bitwidth>
+ void addKImmFPOperands(MCInst &Inst, unsigned N) const;
+
+ void addKImmFP16Operands(MCInst &Inst, unsigned N) const {
+ addKImmFPOperands<16>(Inst, N);
+ }
+
+ void addKImmFP32Operands(MCInst &Inst, unsigned N) const {
+ addKImmFPOperands<32>(Inst, N);
+ }
void addRegOperands(MCInst &Inst, unsigned N) const;
@@ -826,19 +879,23 @@ struct OptionalOperand {
} // end anonymous namespace
// May be called with integer type with equivalent bitwidth.
-static const fltSemantics *getFltSemantics(MVT VT) {
- switch (VT.getSizeInBits()) {
- case 32:
+static const fltSemantics *getFltSemantics(unsigned Size) {
+ switch (Size) {
+ case 4:
return &APFloat::IEEEsingle;
- case 64:
+ case 8:
return &APFloat::IEEEdouble;
- case 16:
+ case 2:
return &APFloat::IEEEhalf;
default:
llvm_unreachable("unsupported fp type");
}
}
+static const fltSemantics *getFltSemantics(MVT VT) {
+ return getFltSemantics(VT.getSizeInBits() / 8);
+}
+
//===----------------------------------------------------------------------===//
// Operand
//===----------------------------------------------------------------------===//
@@ -895,6 +952,12 @@ bool AMDGPUOperand::isInlinableImm(MVT type) const {
AsmParser->hasInv2PiInlineImm());
}
+ if (type.getScalarSizeInBits() == 16) {
+ return AMDGPU::isInlinableLiteral16(
+ static_cast<int16_t>(Literal.getLoBits(16).getSExtValue()),
+ AsmParser->hasInv2PiInlineImm());
+ }
+
return AMDGPU::isInlinableLiteral32(
static_cast<int32_t>(Literal.getLoBits(32).getZExtValue()),
AsmParser->hasInv2PiInlineImm());
@@ -909,9 +972,13 @@ bool AMDGPUOperand::isLiteralImm(MVT type) const {
if (!Imm.IsFPImm) {
// We got int literal token.
+ unsigned Size = type.getSizeInBits();
+ if (Size == 64)
+ Size = 32;
+
// FIXME: 64-bit operands can zero extend, sign extend, or pad zeroes for FP
// types.
- return isUInt<32>(Imm.Val) || isInt<32>(Imm.Val);
+ return isUIntN(Size, Imm.Val) || isIntN(Size, Imm.Val);
}
// We got fp literal token
@@ -947,7 +1014,8 @@ void AMDGPUOperand::addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers
}
}
- if (AMDGPU::isSISrcOperand(AsmParser->getMII()->get(Inst.getOpcode()), Inst.getNumOperands())) {
+ if (AMDGPU::isSISrcOperand(AsmParser->getMII()->get(Inst.getOpcode()),
+ Inst.getNumOperands())) {
addLiteralImmOperand(Inst, Val);
} else {
Inst.addOperand(MCOperand::createImm(Val));
@@ -960,69 +1028,112 @@ void AMDGPUOperand::addLiteralImmOperand(MCInst &Inst, int64_t Val) const {
// Check that this operand accepts literals
assert(AMDGPU::isSISrcOperand(InstDesc, OpNum));
- APInt Literal(64, Val);
- auto OpSize = AMDGPU::getRegOperandSize(AsmParser->getMRI(), InstDesc, OpNum); // expected operand size
+ auto OpSize = AMDGPU::getOperandSize(InstDesc, OpNum); // expected operand size
if (Imm.IsFPImm) { // We got fp literal token
- if (OpSize == 8) { // Expected 64-bit operand
- // Check if literal is inlinable
+ APInt Literal(64, Val);
+
+ switch (OpSize) {
+ case 8: {
if (AMDGPU::isInlinableLiteral64(Literal.getZExtValue(),
AsmParser->hasInv2PiInlineImm())) {
Inst.addOperand(MCOperand::createImm(Literal.getZExtValue()));
- } else if (AMDGPU::isSISrcFPOperand(InstDesc, OpNum)) { // Expected 64-bit fp operand
+ return;
+ }
+
+ // Non-inlineable
+ if (AMDGPU::isSISrcFPOperand(InstDesc, OpNum)) { // Expected 64-bit fp operand
// For fp operands we check if low 32 bits are zeros
if (Literal.getLoBits(32) != 0) {
const_cast<AMDGPUAsmParser *>(AsmParser)->Warning(Inst.getLoc(),
- "Can't encode literal as exact 64-bit"
- " floating-point operand. Low 32-bits will be"
- " set to zero");
+ "Can't encode literal as exact 64-bit floating-point operand. "
+ "Low 32-bits will be set to zero");
}
+
Inst.addOperand(MCOperand::createImm(Literal.lshr(32).getZExtValue()));
- } else {
- // We don't allow fp literals in 64-bit integer instructions. It is
- // unclear how we should encode them. This case should be checked earlier
- // in predicate methods (isLiteralImm())
- llvm_unreachable("fp literal in 64-bit integer instruction.");
+ return;
}
- } else { // Expected 32-bit operand
+
+ // We don't allow fp literals in 64-bit integer instructions. It is
+ // unclear how we should encode them. This case should be checked earlier
+ // in predicate methods (isLiteralImm())
+ llvm_unreachable("fp literal in 64-bit integer instruction.");
+ }
+ case 4:
+ case 2: {
bool lost;
APFloat FPLiteral(APFloat::IEEEdouble, Literal);
// Convert literal to single precision
- FPLiteral.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven, &lost);
+ FPLiteral.convert(*getFltSemantics(OpSize),
+ APFloat::rmNearestTiesToEven, &lost);
// We allow precision lost but not overflow or underflow. This should be
// checked earlier in isLiteralImm()
Inst.addOperand(MCOperand::createImm(FPLiteral.bitcastToAPInt().getZExtValue()));
+ return;
}
- } else { // We got int literal token
- if (OpSize == 8) { // Expected 64-bit operand
- auto LiteralVal = Literal.getZExtValue();
- if (AMDGPU::isInlinableLiteral64(LiteralVal,
- AsmParser->hasInv2PiInlineImm())) {
- Inst.addOperand(MCOperand::createImm(LiteralVal));
- return;
- }
- } else { // Expected 32-bit operand
- auto LiteralVal = static_cast<int32_t>(Literal.getLoBits(32).getZExtValue());
- if (AMDGPU::isInlinableLiteral32(LiteralVal,
- AsmParser->hasInv2PiInlineImm())) {
- Inst.addOperand(MCOperand::createImm(LiteralVal));
- return;
- }
+ default:
+ llvm_unreachable("invalid operand size");
+ }
+
+ return;
+ }
+
+ // We got int literal token.
+ // Only sign extend inline immediates.
+ // FIXME: No errors on truncation
+ switch (OpSize) {
+ case 4: {
+ if (isInt<32>(Val) &&
+ AMDGPU::isInlinableLiteral32(static_cast<int32_t>(Val),
+ AsmParser->hasInv2PiInlineImm())) {
+ Inst.addOperand(MCOperand::createImm(Val));
+ return;
}
- Inst.addOperand(MCOperand::createImm(Literal.getLoBits(32).getZExtValue()));
+
+ Inst.addOperand(MCOperand::createImm(Val & 0xffffffff));
+ return;
+ }
+ case 8: {
+ if (AMDGPU::isInlinableLiteral64(Val,
+ AsmParser->hasInv2PiInlineImm())) {
+ Inst.addOperand(MCOperand::createImm(Val));
+ return;
+ }
+
+ Inst.addOperand(MCOperand::createImm(Lo_32(Val)));
+ return;
+ }
+ case 2: {
+ if (isInt<16>(Val) &&
+ AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val),
+ AsmParser->hasInv2PiInlineImm())) {
+ Inst.addOperand(MCOperand::createImm(Val));
+ return;
+ }
+
+ Inst.addOperand(MCOperand::createImm(Val & 0xffff));
+ return;
+ }
+ default:
+ llvm_unreachable("invalid operand size");
}
}
-void AMDGPUOperand::addKImmFP32Operands(MCInst &Inst, unsigned N) const {
+template <unsigned Bitwidth>
+void AMDGPUOperand::addKImmFPOperands(MCInst &Inst, unsigned N) const {
APInt Literal(64, Imm.Val);
- if (Imm.IsFPImm) { // We got fp literal
- bool lost;
- APFloat FPLiteral(APFloat::IEEEdouble, Literal);
- FPLiteral.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven, &lost);
- Inst.addOperand(MCOperand::createImm(FPLiteral.bitcastToAPInt().getZExtValue()));
- } else { // We got int literal token
- Inst.addOperand(MCOperand::createImm(Literal.getLoBits(32).getZExtValue()));
+
+ if (!Imm.IsFPImm) {
+ // We got int literal token.
+ Inst.addOperand(MCOperand::createImm(Literal.getLoBits(Bitwidth).getZExtValue()));
+ return;
}
+
+ bool Lost;
+ APFloat FPLiteral(APFloat::IEEEdouble, Literal);
+ FPLiteral.convert(*getFltSemantics(Bitwidth / 8),
+ APFloat::rmNearestTiesToEven, &Lost);
+ Inst.addOperand(MCOperand::createImm(FPLiteral.bitcastToAPInt().getZExtValue()));
}
void AMDGPUOperand::addRegOperands(MCInst &Inst, unsigned N) const {
OpenPOWER on IntegriCloud