AMDGPU: Minor assembler refactoring

Fix return before else, check types for selecting
fltSemantics, refactor immediate checks.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@288715 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Matt Arsenault 2016-12-05 22:07:21 +00:00
parent cfa44507a2
commit b51e031eff

View File

@ -804,12 +804,44 @@ struct OptionalOperand {
bool (*ConvertResult)(int64_t&); bool (*ConvertResult)(int64_t&);
}; };
// May be called with integer type with equivalent bitwidth.
static const fltSemantics *getFltSemantics(MVT VT) {
switch (VT.getSizeInBits()) {
case 32:
return &APFloat::IEEEsingle;
case 64:
return &APFloat::IEEEdouble;
case 16:
return &APFloat::IEEEhalf;
default:
llvm_unreachable("unsupported fp type");
}
}
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Operand // Operand
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
static bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT) {
bool Lost;
// Convert literal to single precision
APFloat::opStatus Status = FPLiteral.convert(*getFltSemantics(VT),
APFloat::rmNearestTiesToEven,
&Lost);
// We allow precision lost but not overflow or underflow
if (Status != APFloat::opOK &&
Lost &&
((Status & APFloat::opOverflow) != 0 ||
(Status & APFloat::opUnderflow) != 0)) {
return false;
}
return true;
}
bool AMDGPUOperand::isInlinableImm(MVT type) const { bool AMDGPUOperand::isInlinableImm(MVT type) const {
if (!isImmTy(ImmTyNone)) { if (!isImmTy(ImmTyNone)) {
// Only plain immediates are inlinable (e.g. "clamp" attribute is not) // Only plain immediates are inlinable (e.g. "clamp" attribute is not)
@ -824,36 +856,28 @@ bool AMDGPUOperand::isInlinableImm(MVT type) const {
if (Imm.IsFPImm) { // We got fp literal token if (Imm.IsFPImm) { // We got fp literal token
if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
return AMDGPU::isInlinableLiteral64(Imm.Val, AsmParser->isVI()); return AMDGPU::isInlinableLiteral64(Imm.Val, AsmParser->isVI());
} else { // Expected 32-bit operand
bool lost;
APFloat FPLiteral(APFloat::IEEEdouble, Literal);
// Convert literal to single precision
APFloat::opStatus status = FPLiteral.convert(APFloat::IEEEsingle,
APFloat::rmNearestTiesToEven,
&lost);
// We allow precision lost but not overflow or underflow
if (status != APFloat::opOK &&
lost &&
((status & APFloat::opOverflow) != 0 ||
(status & APFloat::opUnderflow) != 0)) {
return false;
} }
APFloat FPLiteral(APFloat::IEEEdouble, APInt(64, Imm.Val));
if (!canLosslesslyConvertToFPType(FPLiteral, type))
return false;
// Check if single precision literal is inlinable // Check if single precision literal is inlinable
return AMDGPU::isInlinableLiteral32( return AMDGPU::isInlinableLiteral32(
static_cast<int32_t>(FPLiteral.bitcastToAPInt().getZExtValue()), static_cast<int32_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
AsmParser->isVI()); AsmParser->isVI());
} }
} else { // We got int literal token
// We got int literal token.
if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
return AMDGPU::isInlinableLiteral64(Imm.Val, AsmParser->isVI()); return AMDGPU::isInlinableLiteral64(Imm.Val, AsmParser->isVI());
} else { // Expected 32-bit operand }
return AMDGPU::isInlinableLiteral32( return AMDGPU::isInlinableLiteral32(
static_cast<int32_t>(Literal.getLoBits(32).getZExtValue()), static_cast<int32_t>(Literal.getLoBits(32).getZExtValue()),
AsmParser->isVI()); AsmParser->isVI());
} }
}
return false;
}
bool AMDGPUOperand::isLiteralImm(MVT type) const { bool AMDGPUOperand::isLiteralImm(MVT type) const {
// Check that this imediate can be added as literal // Check that this imediate can be added as literal
@ -861,45 +885,28 @@ bool AMDGPUOperand::isLiteralImm(MVT type) const {
return false; return false;
} }
APInt Literal(64, Imm.Val); if (!Imm.IsFPImm) {
// We got int literal token.
if (Imm.IsFPImm) { // We got fp literal token // FIXME: 64-bit operands can zero extend, sign extend, or pad zeroes for FP
// types.
return isUInt<32>(Imm.Val) || isInt<32>(Imm.Val);
}
// We got fp literal token
if (type == MVT::f64) { // Expected 64-bit fp operand if (type == MVT::f64) { // Expected 64-bit fp operand
// We would set low 64-bits of literal to zeroes but we accept this literals // We would set low 64-bits of literal to zeroes but we accept this literals
return true; return true;
} else if (type == MVT::i64) { // Expected 64-bit int operand }
if (type == MVT::i64) { // Expected 64-bit int operand
// We don't allow fp literals in 64-bit integer instructions. It is // We don't allow fp literals in 64-bit integer instructions. It is
// unclear how we should encode them. // unclear how we should encode them.
return false; return false;
} else { // Expected 32-bit operand
bool lost;
APFloat FPLiteral(APFloat::IEEEdouble, Literal);
// Convert literal to single precision
APFloat::opStatus status = FPLiteral.convert(APFloat::IEEEsingle,
APFloat::rmNearestTiesToEven,
&lost);
// We allow precision lost but not overflow or underflow
if (status != APFloat::opOK &&
lost &&
((status & APFloat::opOverflow) != 0 ||
(status & APFloat::opUnderflow) != 0)) {
return false;
} }
return true;
} APFloat FPLiteral(APFloat::IEEEdouble, APInt(64, Imm.Val));
} else { // We got int literal token return canLosslesslyConvertToFPType(FPLiteral, type);
APInt HiBits = Literal.getHiBits(32);
if (HiBits == 0xffffffff &&
(*Literal.getLoBits(32).getRawData() & 0x80000000) != 0) {
// If high 32 bits aren't zeroes then they all should be ones and 32nd
// bit should be set. So that this 64-bit literal is sign-extension of
// 32-bit value.
return true;
} else if (HiBits == 0) {
return true;
}
}
return false;
} }
bool AMDGPUOperand::isRegClass(unsigned RCID) const { bool AMDGPUOperand::isRegClass(unsigned RCID) const {