-
Notifications
You must be signed in to change notification settings - Fork 14.8k
[TableGen] Emit integers in GlobalISelMatchTable as unsigned #153391
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
Conversation
The numbers are stored in an `uint8_t` array, either directly or via `GIMT_Encode2/4/8` macros (see `getEncodedEmitStr` and `emitEncodingMacrosDef`). Passing negative numbers only adds confusion and results in a warning for the `INT64_MIN` value (C++ parses `-9223372036854775808` as two tokens: a unary minus and an unsigned integer, triggered in llvm#151687).
And avoid unnecessary casts.
@llvm/pr-subscribers-llvm-globalisel @llvm/pr-subscribers-tablegen Author: Piotr Fusik (pfusik) ChangesThe numbers are stored in an Full diff: https://github.com/llvm/llvm-project/pull/153391.diff 3 Files Affected:
diff --git a/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td b/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
index 4a516c6e0235c..7a86b5b726a82 100644
--- a/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
+++ b/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
@@ -617,11 +617,11 @@ def MOV : I<(outs GPR32:$dst), (ins GPR32:$src1),
// R02N-NEXT: // MIs[0] Operand 2
// R02N-NEXT: GIM_RootCheckType, /*Op*/2, /*Type*/GILLT_s32,
//
-// R02C-NEXT: GIM_CheckConstantInt8, /*MI*/0, /*Op*/2, uint8_t(-2)
+// R02C-NEXT: GIM_CheckConstantInt8, /*MI*/0, /*Op*/2, 254,
// R02C-NEXT: // (xor:{ *:[i32] } GPR32:{ *:[i32] }:$src1, -2:{ *:[i32] }) => (XORI:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
// R02C-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(MyTarget::XORI),
// R02C-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // DstI[dst]
-// R02C-NEXT: GIR_AddImm8, /*InsnID*/0, /*Imm*/uint8_t(-1),
+// R02C-NEXT: GIR_AddImm8, /*InsnID*/0, /*Imm*/255,
// R02C-NEXT: GIR_RootToRootCopy, /*OpIdx*/1, // src1
// R02C-NEXT: GIR_RootConstrainSelectedInstOperands,
// R02C-NEXT: // GIR_Coverage, 2,
@@ -648,7 +648,7 @@ def XORI : I<(outs GPR32:$dst), (ins m1:$src2, GPR32:$src1),
// NOOPT-NEXT: GIM_RootCheckRegBankForClass, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::GPR32RegClassID),
// NOOPT-NEXT: // MIs[0] Operand 2
// NOOPT-NEXT: GIM_RootCheckType, /*Op*/2, /*Type*/GILLT_s32,
-// NOOPT-NEXT: GIM_CheckConstantInt8, /*MI*/0, /*Op*/2, uint8_t(-3)
+// NOOPT-NEXT: GIM_CheckConstantInt8, /*MI*/0, /*Op*/2, 253,
// NOOPT-NEXT: // (xor:{ *:[i32] } GPR32:{ *:[i32] }:$src1, -3:{ *:[i32] }) => (XOR:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
// NOOPT-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(MyTarget::XOR),
// NOOPT-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // DstI[dst]
@@ -676,11 +676,11 @@ def XOR : I<(outs GPR32:$dst), (ins Z:$src2, GPR32:$src1),
// NOOPT-NEXT: GIM_RootCheckRegBankForClass, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::GPR32RegClassID),
// NOOPT-NEXT: // MIs[0] Operand 2
// NOOPT-NEXT: GIM_RootCheckType, /*Op*/2, /*Type*/GILLT_s32,
-// NOOPT-NEXT: GIM_CheckConstantInt8, /*MI*/0, /*Op*/2, uint8_t(-4)
+// NOOPT-NEXT: GIM_CheckConstantInt8, /*MI*/0, /*Op*/2, 252,
// NOOPT-NEXT: // (xor:{ *:[i32] } GPR32:{ *:[i32] }:$src1, -4:{ *:[i32] }) => (XORlike:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
// NOOPT-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(MyTarget::XORlike),
// NOOPT-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // DstI[dst]
-// NOOPT-NEXT: GIR_AddImm8, /*InsnID*/0, /*Imm*/uint8_t(-1),
+// NOOPT-NEXT: GIR_AddImm8, /*InsnID*/0, /*Imm*/255,
// NOOPT-NEXT: GIR_AddRegister, /*InsnID*/0, GIMT_Encode2(MyTarget::R0),
// NOOPT-NEXT: GIR_RootToRootCopy, /*OpIdx*/1, // src1
// NOOPT-NEXT: GIR_RootConstrainSelectedInstOperands,
@@ -705,11 +705,11 @@ def XORlike : I<(outs GPR32:$dst), (ins m1Z:$src2, GPR32:$src1),
// NOOPT-NEXT: GIM_RootCheckRegBankForClass, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::GPR32RegClassID),
// NOOPT-NEXT: // MIs[0] Operand 2
// NOOPT-NEXT: GIM_RootCheckType, /*Op*/2, /*Type*/GILLT_s32,
-// NOOPT-NEXT: GIM_CheckConstantInt8, /*MI*/0, /*Op*/2, uint8_t(-5),
+// NOOPT-NEXT: GIM_CheckConstantInt8, /*MI*/0, /*Op*/2, 251,
// NOOPT-NEXT: // (xor:{ *:[i32] } GPR32:{ *:[i32] }:$src1, -5:{ *:[i32] }) => (XORManyDefaults:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
// NOOPT-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(MyTarget::XORManyDefaults),
// NOOPT-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // DstI[dst]
-// NOOPT-NEXT: GIR_AddImm8, /*InsnID*/0, /*Imm*/uint8_t(-1),
+// NOOPT-NEXT: GIR_AddImm8, /*InsnID*/0, /*Imm*/255,
// NOOPT-NEXT: GIR_AddRegister, /*InsnID*/0, GIMT_Encode2(MyTarget::R0),
// NOOPT-NEXT: GIR_AddRegister, /*InsnID*/0, GIMT_Encode2(MyTarget::R0),
// NOOPT-NEXT: GIR_RootToRootCopy, /*OpIdx*/1, // src1
@@ -735,7 +735,7 @@ def XORManyDefaults : I<(outs GPR32:$dst), (ins m1Z:$src3, Z:$src2, GPR32:$src1)
// NOOPT-NEXT: GIM_RootCheckRegBankForClass, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::GPR32RegClassID),
// NOOPT-NEXT: // MIs[0] Operand 2
// NOOPT-NEXT: GIM_RootCheckType, /*Op*/2, /*Type*/GILLT_s32,
-// NOOPT-NEXT: GIM_CheckConstantInt8, /*MI*/0, /*Op*/2, uint8_t(-6)
+// NOOPT-NEXT: GIM_CheckConstantInt8, /*MI*/0, /*Op*/2, 250,
// NOOPT-NEXT: // (xor:{ *:[i32] } GPR32:{ *:[i32] }:$src1, -6:{ *:[i32] }) => (XORIb:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
// NOOPT-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(MyTarget::XORIb),
// NOOPT-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // DstI[dst]
@@ -766,7 +766,7 @@ def XORIb : I<(outs GPR32:$dst), (ins mb:$src2, GPR32:$src1),
// NOOPT-NEXT: GIM_RootCheckRegBankForClass, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::GPR32RegClassID),
// NOOPT-NEXT: // MIs[0] Operand 2
// NOOPT-NEXT: GIM_RootCheckType, /*Op*/2, /*Type*/GILLT_s32,
-// NOOPT-NEXT: GIM_CheckConstantInt8, /*MI*/0, /*Op*/2, uint8_t(-1),
+// NOOPT-NEXT: GIM_CheckConstantInt8, /*MI*/0, /*Op*/2, 255,
// NOOPT-NEXT: // (xor:{ *:[i32] } GPR32:{ *:[i32] }:$Wm, -1:{ *:[i32] }) => (ORN:{ *:[i32] } R0:{ *:[i32] }, GPR32:{ *:[i32] }:$Wm)
// NOOPT-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(MyTarget::ORN),
// NOOPT-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // DstI[dst]
diff --git a/llvm/test/TableGen/GlobalISelEmitter/int64min.td b/llvm/test/TableGen/GlobalISelEmitter/int64min.td
new file mode 100644
index 0000000000000..ec80537bc3a74
--- /dev/null
+++ b/llvm/test/TableGen/GlobalISelEmitter/int64min.td
@@ -0,0 +1,30 @@
+// RUN: llvm-tblgen -gen-global-isel -optimize-match-table=false -I %p/../../../include -I %p/../Common %s | FileCheck %s
+
+include "llvm/Target/Target.td"
+include "GlobalISelEmitterCommon.td"
+
+def GPR : RegisterClass<"MyTarget", [i64], 64, (add R0)>;
+def ANDI : I<(outs GPR:$dst), (ins GPR:$src1, i64imm:$src2), []>;
+
+// CHECK-LABEL: GIM_Try, /*On fail goto*//*Label 0*/ GIMT_Encode4(59), // Rule ID 0 //
+// CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
+// CHECK-NEXT: GIM_CheckOpcode, /*MI*/0, GIMT_Encode2(TargetOpcode::G_AND),
+// CHECK-NEXT: // MIs[0] DstI[dst]
+// CHECK-NEXT: GIM_RootCheckType, /*Op*/0, /*Type*/GILLT_s64,
+// CHECK-NEXT: GIM_RootCheckRegBankForClass, /*Op*/0, /*RC*/GIMT_Encode2(MyTarget::GPRRegClassID),
+// CHECK-NEXT: // MIs[0] rs1
+// CHECK-NEXT: GIM_RootCheckType, /*Op*/1, /*Type*/GILLT_s64,
+// CHECK-NEXT: GIM_RootCheckRegBankForClass, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::GPRRegClassID),
+// CHECK-NEXT: // MIs[0] Operand 2
+// CHECK-NEXT: GIM_RootCheckType, /*Op*/2, /*Type*/GILLT_s64,
+// CHECK-NEXT: GIM_CheckConstantInt, /*MI*/0, /*Op*/2, GIMT_Encode8(9223372036854775808),
+// CHECK-NEXT: // (and:{ *:[i64] } GPR:{ *:[i64] }:$rs1, -9223372036854775808:{ *:[i64] }) => (ANDI:{ *:[i64] } GPR:{ *:[i64] }:$rs1, -9223372036854775808:{ *:[i64] })
+// CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(MyTarget::ANDI),
+// CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // DstI[dst]
+// CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/1, // rs1
+// CHECK-NEXT: GIR_AddImm, /*InsnID*/0, /*Imm*/GIMT_Encode8(9223372036854775808),
+// CHECK-NEXT: GIR_RootConstrainSelectedInstOperands,
+// CHECK-NEXT: // GIR_Coverage, 0,
+// CHECK-NEXT: GIR_EraseRootFromParent_Done,
+def : Pat<(and GPR:$rs1, 0x8000000000000000),
+ (ANDI GPR:$rs1, 0x8000000000000000)>;
diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
index 70141ba738bdb..93a236ff41ccf 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
+++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
@@ -53,26 +53,26 @@ constexpr StringLiteral EncodeMacroName = "GIMT_Encode";
void emitEncodingMacrosDef(raw_ostream &OS) {
OS << "#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__\n"
<< "#define " << EncodeMacroName << "2(Val)"
- << " uint8_t(Val), uint8_t((uint16_t)Val >> 8)\n"
+ << " uint8_t(Val), uint8_t((Val) >> 8)\n"
<< "#define " << EncodeMacroName << "4(Val)"
- << " uint8_t(Val), uint8_t((uint32_t)Val >> 8), "
- "uint8_t((uint32_t)Val >> 16), uint8_t((uint32_t)Val >> 24)\n"
+ << " uint8_t(Val), uint8_t((Val) >> 8), "
+ "uint8_t((Val) >> 16), uint8_t((Val) >> 24)\n"
<< "#define " << EncodeMacroName << "8(Val)"
- << " uint8_t(Val), uint8_t((uint64_t)Val >> 8), "
- "uint8_t((uint64_t)Val >> 16), uint8_t((uint64_t)Val >> 24), "
- "uint8_t((uint64_t)Val >> 32), uint8_t((uint64_t)Val >> 40), "
- "uint8_t((uint64_t)Val >> 48), uint8_t((uint64_t)Val >> 56)\n"
+ << " uint8_t(Val), uint8_t((Val) >> 8), "
+ "uint8_t((Val) >> 16), uint8_t((Val) >> 24), "
+ "uint8_t(uint64_t(Val) >> 32), uint8_t(uint64_t(Val) >> 40), "
+ "uint8_t(uint64_t(Val) >> 48), uint8_t(uint64_t(Val) >> 56)\n"
<< "#else\n"
<< "#define " << EncodeMacroName << "2(Val)"
- << " uint8_t((uint16_t)Val >> 8), uint8_t(Val)\n"
+ << " uint8_t((Val) >> 8), uint8_t(Val)\n"
<< "#define " << EncodeMacroName << "4(Val)"
- << " uint8_t((uint32_t)Val >> 24), uint8_t((uint32_t)Val >> 16), "
- "uint8_t((uint32_t)Val >> 8), uint8_t(Val)\n"
+ << " uint8_t((Val) >> 24), uint8_t((Val) >> 16), "
+ "uint8_t((Val) >> 8), uint8_t(Val)\n"
<< "#define " << EncodeMacroName << "8(Val)"
- << " uint8_t((uint64_t)Val >> 56), uint8_t((uint64_t)Val >> 48), "
- "uint8_t((uint64_t)Val >> 40), uint8_t((uint64_t)Val >> 32), "
- "uint8_t((uint64_t)Val >> 24), uint8_t((uint64_t)Val >> 16), "
- "uint8_t((uint64_t)Val >> 8), uint8_t(Val)\n"
+ << " uint8_t(uint64_t(Val) >> 56), uint8_t(uint64_t(Val) >> 48), "
+ "uint8_t(uint64_t(Val) >> 40), uint8_t(uint64_t(Val) >> 32), "
+ "uint8_t((Val) >> 24), uint8_t((Val) >> 16), "
+ "uint8_t((Val) >> 8), uint8_t(Val)\n"
<< "#endif\n";
}
@@ -237,9 +237,10 @@ MatchTableRecord MatchTable::NamedValue(unsigned NumBytes, StringRef Namespace,
MatchTableRecord MatchTable::IntValue(unsigned NumBytes, int64_t IntValue) {
assert(isUIntN(NumBytes * 8, IntValue) || isIntN(NumBytes * 8, IntValue));
- auto Str = llvm::to_string(IntValue);
- if (NumBytes == 1 && IntValue < 0)
- Str = "uint8_t(" + Str + ")";
+ uint64_t UIntValue = IntValue;
+ if (NumBytes < 8)
+ UIntValue &= (UINT64_C(1) << NumBytes * 8) - 1;
+ auto Str = llvm::to_string(UIntValue);
// TODO: Could optimize this directly to save the compiler some work when
// building the file
return MatchTableRecord(std::nullopt, Str, NumBytes,
|
uint64_t UIntValue = IntValue; | ||
if (NumBytes < 8) | ||
UIntValue &= (UINT64_C(1) << NumBytes * 8) - 1; | ||
auto Str = llvm::to_string(UIntValue); |
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.
auto Str = llvm::to_string(UIntValue); | |
std::string Str = llvm::to_string(UIntValue); |
We probably should be directly writing this string to the stream instead of creating the temporary
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.
We probably should be directly writing this string to the stream instead of creating the temporary
I can address that in a future PR, together with the following TODO comment of emitting the bytes directly instead of via GIMT_Encode
macros.
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/116/builds/16884 Here is the relevant piece of the build log for the reference
|
error: integer literal is too large to be represented in a signed integer type, interpreting as unsigned [-Werror,-Wimplicitly-unsigned-literal] Introduced in llvm#153391
error: integer literal is too large to be represented in a signed integer type, interpreting as unsigned [-Werror,-Wimplicitly-unsigned-literal] Introduced in #153391
The numbers are stored in an
uint8_t
array, either directlyor via
GIMT_Encode2/4/8
macros(see
getEncodedEmitStr
andemitEncodingMacrosDef
).Passing negative numbers only adds confusion and results in a warning
for the
INT64_MIN
value (C++ parses-9223372036854775808
as two tokens:a unary minus and an unsigned integer, triggered in #151687).
BTW, parenthesize parameters in
GIMT_Encode2/4/8
macrosand avoid unnecessary casts.