-
Notifications
You must be signed in to change notification settings - Fork 11.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[AMDGPU] Add lit() asm operand modifier for SP3 compatibility. #68839
Conversation
A literal can be optionally wrapped in a lit() expression. This does not force literal encoding for an inline immediate, but neither does SP3. The syntax is dummy for compatibility only.
@llvm/pr-subscribers-mc @llvm/pr-subscribers-backend-amdgpu Author: Stanislav Mekhanoshin (rampitec) ChangesA literal can be optionally wrapped in a lit() expression. This does not force literal encoding for an inline immediate, but neither does SP3. The syntax is dummy for compatibility only. Full diff: https://github.com/llvm/llvm-project/pull/68839.diff 2 Files Affected:
diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
index 35656bcaea1af7f..1e07e8deb560fcb 100644
--- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
+++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
@@ -75,6 +75,7 @@ class AMDGPUOperand : public MCParsedAsmOperand {
bool Abs = false;
bool Neg = false;
bool Sext = false;
+ bool Lit = false;
bool hasFPModifiers() const { return Abs || Neg; }
bool hasIntModifiers() const { return Sext; }
@@ -3005,7 +3006,7 @@ bool
AMDGPUAsmParser::isNamedOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const {
if (Token.is(AsmToken::Identifier) && NextToken.is(AsmToken::LParen)) {
const auto &str = Token.getString();
- return str == "abs" || str == "neg" || str == "sext";
+ return str == "abs" || str == "neg" || str == "sext" || str == "lit";
}
return false;
}
@@ -3094,6 +3095,7 @@ AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands,
bool AllowImm) {
bool Neg, SP3Neg;
bool Abs, SP3Abs;
+ bool Lit;
SMLoc Loc;
// Disable ambiguous constructs like '--1' etc. Should use neg(-1) instead.
@@ -3113,6 +3115,10 @@ AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands,
if (Abs && !skipToken(AsmToken::LParen, "expected left paren after abs"))
return ParseStatus::Failure;
+ Lit = trySkipId("lit");
+ if (Lit && !skipToken(AsmToken::LParen, "expected left paren after lit"))
+ return ParseStatus::Failure;
+
Loc = getLoc();
SP3Abs = trySkipToken(AsmToken::Pipe);
if (Abs && SP3Abs)
@@ -3125,7 +3131,10 @@ AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands,
Res = parseReg(Operands);
}
if (!Res.isSuccess())
- return (SP3Neg || Neg || SP3Abs || Abs) ? ParseStatus::Failure : Res;
+ return (SP3Neg || Neg || SP3Abs || Abs || Lit) ? ParseStatus::Failure : Res;
+
+ if (Lit && !Operands.back()->isImm())
+ Error(Loc, "expected immediate with lit modifier");
if (SP3Abs && !skipToken(AsmToken::Pipe, "expected vertical bar"))
return ParseStatus::Failure;
@@ -3133,12 +3142,15 @@ AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands,
return ParseStatus::Failure;
if (Neg && !skipToken(AsmToken::RParen, "expected closing parentheses"))
return ParseStatus::Failure;
+ if (Lit && !skipToken(AsmToken::RParen, "expected closing parentheses"))
+ return ParseStatus::Failure;
AMDGPUOperand::Modifiers Mods;
Mods.Abs = Abs || SP3Abs;
Mods.Neg = Neg || SP3Neg;
+ Mods.Lit = Lit;
- if (Mods.hasFPModifiers()) {
+ if (Mods.hasFPModifiers() || Lit) {
AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
if (Op.isExpr())
return Error(Op.getStartLoc(), "expected an absolute expression");
diff --git a/llvm/test/MC/AMDGPU/literals.s b/llvm/test/MC/AMDGPU/literals.s
index 8e5e8fd1886f416..910e3d82b2fc849 100644
--- a/llvm/test/MC/AMDGPU/literals.s
+++ b/llvm/test/MC/AMDGPU/literals.s
@@ -889,3 +889,39 @@ v_pk_add_f16 v255, private_base, private_limit
// NOSICIVI: :[[@LINE+2]]:{{[0-9]+}}: error: instruction not supported on this GPU
// NOGFX9: :[[@LINE+1]]:{{[0-9]+}}: error: invalid operand (violates constant bus restrictions)
v_pk_add_f16 v255, vccz, execz
+
+//---------------------------------------------------------------------------//
+// check dummy lit() syntax for sp3 compatibility.
+//---------------------------------------------------------------------------//
+
+// SICI: v_sqrt_f32_e32 v2, 0x7b ; encoding: [0xff,0x66,0x04,0x7e,0x7b,0x00,0x00,0x00]
+// GFX89: v_sqrt_f32_e32 v2, 0x7b ; encoding: [0xff,0x4e,0x04,0x7e,0x7b,0x00,0x00,0x00]
+v_sqrt_f32 v2, lit(123)
+
+// SICI: v_sqrt_f32_e32 v2, 0x7b ; encoding: [0xff,0x66,0x04,0x7e,0x7b,0x00,0x00,0x00]
+// GFX89: v_sqrt_f32_e32 v2, 0x7b ; encoding: [0xff,0x4e,0x04,0x7e,0x7b,0x00,0x00,0x00]
+v_sqrt_f32 v2, abs(lit(123))
+
+// SICI: v_sqrt_f32_e32 v2, 0x42f60000 ; encoding: [0xff,0x66,0x04,0x7e,0x00,0x00,0xf6,0x42
+// GFX89: v_sqrt_f32_e32 v2, 0x42f60000 ; encoding: [0xff,0x4e,0x04,0x7e,0x00,0x00,0xf6,0x42]
+v_sqrt_f32 v2, lit(123.0)
+
+// SICI: v_sqrt_f64_e32 v[2:3], 0x405ec000 ; encoding: [0xff,0x68,0x04,0x7e,0x00,0xc0,0x5e,0x40]
+// GFX89: v_sqrt_f64_e32 v[2:3], 0x405ec000 ; encoding: [0xff,0x50,0x04,0x7e,0x00,0xc0,0x5e,0x40]
+v_sqrt_f64 v[2:3], lit(123.0)
+
+// SICI: v_sqrt_f64_e32 v[2:3], 0x7b ; encoding: [0xff,0x68,0x04,0x7e,0x7b,0x00,0x00,0x00]
+// GFX89: v_sqrt_f64_e32 v[2:3], 0x7b ; encoding: [0xff,0x50,0x04,0x7e,0x7b,0x00,0x00,0x00]
+v_sqrt_f64 v[2:3], lit(123)
+
+// NOSICI: :[[@LINE+2]]:{{[0-9]+}}: error: expected left paren after lit
+// NOGFX89: :[[@LINE+1]]:{{[0-9]+}}: error: expected left paren after lit
+v_sqrt_f32 v2, lit 123.0
+
+// NOSICI: :[[@LINE+2]]:{{[0-9]+}}: error: expected closing parentheses
+// NOGFX89: :[[@LINE+1]]:{{[0-9]+}}: error: expected closing parentheses
+v_sqrt_f32 v2, lit(123.0
+
+// NOSICI: :[[@LINE+2]]:{{[0-9]+}}: error: expected immediate with lit modifier
+// NOGFX89: :[[@LINE+1]]:{{[0-9]+}}: error: expected immediate with lit modifier
+v_sqrt_f32 v2, lit(v1)
|
Thanks. This sounds OK to me. Really we should go one better than SP3 and force literal encoding, but I guess that is hard to implement. Do you think the disassembler should emit lit(), either for all literal operands or at least for ones that could have been encoded as inlines? Does your implementation accept |
@@ -3005,7 +3006,7 @@ bool | |||
AMDGPUAsmParser::isNamedOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const { | |||
if (Token.is(AsmToken::Identifier) && NextToken.is(AsmToken::LParen)) { | |||
const auto &str = Token.getString(); | |||
return str == "abs" || str == "neg" || str == "sext"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Today I learned that we already accept abs(...)
and neg(...)
. I had no idea!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, we do. Yet another compatibility thing. There is a special handling of the neg(abs()), the only useful combination. If we ever want to handle lit(abs()) it would need a similar special case handling.
Yes, it needs:
This could be theoretically added later, but not required for compatibility.
Unless we enforce literal encoding I do not see a reason to clutter the output.
This does not support it:
SP3 does, although there is no abs modifier used anyway. It might be possible to support, but I see no usecases. On practice people just use lit(). Actually since SP3 does not do it I see no way to check if HW even supports modifier bits with literals. So far lit() is just a sort of syntax glue. |
BTW, it does support the opposite:
It makes more sense to me: use literal and abs bit on that literal. The |
Good. I think the operand of lit() should just be a constant. It should not be allowed to include any other modifiers. |
Moreover, neg(abs()) is supported. abs(neg()) is not. Which also makes sense, as you cannot really do abs(neg()) in a non-constant case:
And then:
I.e. useful and meaningful combinations are supported. |
abs(neg(x)) could be treated as abs(x). |
It probably could, but it sounds like an user error, and then asm silently accepting this error. After all asm is not a high level language where it could be justified. I can imagine this sort of constructs created by a pre-processor, but I do not really think an asm writer expects this trap. Asm is not a tool to prevent an user to shot himself in a foot, but creating such traps is not its goal either. |
On a practical note I can see 2 use cases where it may be useful:
|
Still might be useful to allow (at some point) expressions within?
Well, we can have our own
So far I was under impression that these modifiers are supposed to designate corresponding encoding bits, just as our Otherwise, if we see these more like generic expressions, then maybe using the good old minus sign would make more sense than |
Fair point. I am happy for abs(neg(x)) to be an assembler error. |
Technically -123.0 and neg(123.0) are different things. First is a negative constant. Second is a positive constant and a modifier. But noone does it, not even SP3. |
A literal can be optionally wrapped in a lit() expression. This does not force literal encoding for an inline immediate, but neither does SP3. The syntax is dummy for compatibility only.