mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-26 09:49:48 +00:00
[TBLGEN] Fix subreg value overflow in DAGISelMatcher
Tablegen's DAGISelMatcher emits integers in a VBR format, so if an integer is below 128 it can fit into a single byte, otherwise high bit is set, next byte is used etc. MatcherTable is essentially an unsigned char table. When SelectionDAGISel parses the table it does a reverse translation. In a situation when numeric value of an integer to emit is unknown it can be emitted not as OPC_EmitInteger but as OPC_EmitStringInteger using a symbolic name of the value. In this situation the value should not exceed 127. One of the situations when OPC_EmitStringInteger is used is if we need to emit a subreg into a matcher table. However, number of subregs can exceed 127. Currently last defined subreg for AMDGPU is 192. That results in a silent bug in the ISel with matcher reading from an invalid offset. Fixed this bug to emit actual VBR encoded value for a subregs which value exceeds 127. Differential Revision: https://reviews.llvm.org/D74368
This commit is contained in:
parent
baf3a53b57
commit
f8d044bbcf
128
llvm/test/TableGen/Common/reg-with-subregs-common.td
Normal file
128
llvm/test/TableGen/Common/reg-with-subregs-common.td
Normal file
@ -0,0 +1,128 @@
|
||||
include "llvm/Target/Target.td"
|
||||
|
||||
def TestTargetInstrInfo : InstrInfo;
|
||||
|
||||
def TestTarget : Target {
|
||||
let InstructionSet = TestTargetInstrInfo;
|
||||
}
|
||||
|
||||
class Indexes<int N> {
|
||||
list<int> all = [0, 1, 2, 3, 4, 5, 6 , 7,
|
||||
8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23,
|
||||
24, 25, 26, 27, 28, 29, 30, 31];
|
||||
list<int> slice =
|
||||
!foldl([]<int>, all, acc, cur,
|
||||
!listconcat(acc, !if(!lt(cur, N), [cur], [])));
|
||||
}
|
||||
|
||||
foreach Index = 0-31 in {
|
||||
def sub#Index : SubRegIndex<32, !shl(Index, 5)>;
|
||||
}
|
||||
|
||||
foreach Size = {2,4,8,16} in {
|
||||
foreach Index = Indexes<!add(33, !mul(Size, -1))>.slice in {
|
||||
def !foldl("", Indexes<Size>.slice, acc, cur,
|
||||
!strconcat(acc#!if(!eq(acc,""),"","_"), "sub"#!add(cur, Index))) :
|
||||
SubRegIndex<!mul(Size, 32), !shl(Index, 5)> {
|
||||
let CoveringSubRegIndices =
|
||||
!foldl([]<SubRegIndex>, Indexes<Size>.slice, acc, cur,
|
||||
!listconcat(acc, [!cast<SubRegIndex>(sub#!add(cur, Index))]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach Index = 0-255 in {
|
||||
def R#Index : Register <"r"#Index>;
|
||||
}
|
||||
|
||||
def GPR32 : RegisterClass<"TestTarget", [i32], 32,
|
||||
(add (sequence "R%u", 0, 255))>;
|
||||
|
||||
def GPR64 : RegisterTuples<[sub0, sub1],
|
||||
[(decimate (shl GPR32, 0), 1),
|
||||
(decimate (shl GPR32, 1), 1)
|
||||
]>;
|
||||
|
||||
def GPR128 : RegisterTuples<[sub0, sub1, sub2, sub3],
|
||||
[
|
||||
(decimate (shl GPR32, 0), 1),
|
||||
(decimate (shl GPR32, 1), 1),
|
||||
(decimate (shl GPR32, 2), 1),
|
||||
(decimate (shl GPR32, 3), 1)
|
||||
]>;
|
||||
|
||||
def GPR256 : RegisterTuples<[sub0, sub1, sub2, sub3, sub4, sub5, sub6, sub7],
|
||||
[
|
||||
(decimate (shl GPR32, 0), 1),
|
||||
(decimate (shl GPR32, 1), 1),
|
||||
(decimate (shl GPR32, 2), 1),
|
||||
(decimate (shl GPR32, 3), 1),
|
||||
(decimate (shl GPR32, 4), 1),
|
||||
(decimate (shl GPR32, 5), 1),
|
||||
(decimate (shl GPR32, 6), 1),
|
||||
(decimate (shl GPR32, 7), 1)
|
||||
]>;
|
||||
|
||||
def GPR512 : RegisterTuples<[sub0, sub1, sub2, sub3, sub4, sub5, sub6, sub7,
|
||||
sub8, sub9, sub10, sub11, sub12, sub13, sub14, sub15],
|
||||
[
|
||||
(decimate (shl GPR32, 0), 1),
|
||||
(decimate (shl GPR32, 1), 1),
|
||||
(decimate (shl GPR32, 2), 1),
|
||||
(decimate (shl GPR32, 3), 1),
|
||||
(decimate (shl GPR32, 4), 1),
|
||||
(decimate (shl GPR32, 5), 1),
|
||||
(decimate (shl GPR32, 6), 1),
|
||||
(decimate (shl GPR32, 7), 1),
|
||||
(decimate (shl GPR32, 8), 1),
|
||||
(decimate (shl GPR32, 9), 1),
|
||||
(decimate (shl GPR32, 10), 1),
|
||||
(decimate (shl GPR32, 11), 1),
|
||||
(decimate (shl GPR32, 12), 1),
|
||||
(decimate (shl GPR32, 13), 1),
|
||||
(decimate (shl GPR32, 14), 1),
|
||||
(decimate (shl GPR32, 15), 1)
|
||||
]>;
|
||||
|
||||
def GPR1024 : RegisterTuples<[sub0, sub1, sub2, sub3, sub4, sub5, sub6, sub7,
|
||||
sub8, sub9, sub10, sub11, sub12, sub13, sub14, sub15,
|
||||
sub16, sub17, sub18, sub19, sub20, sub21, sub22, sub23,
|
||||
sub24, sub25, sub26, sub27, sub28, sub29, sub30, sub31],
|
||||
[
|
||||
(decimate (shl GPR32, 0), 1),
|
||||
(decimate (shl GPR32, 1), 1),
|
||||
(decimate (shl GPR32, 2), 1),
|
||||
(decimate (shl GPR32, 3), 1),
|
||||
(decimate (shl GPR32, 4), 1),
|
||||
(decimate (shl GPR32, 5), 1),
|
||||
(decimate (shl GPR32, 6), 1),
|
||||
(decimate (shl GPR32, 7), 1),
|
||||
(decimate (shl GPR32, 8), 1),
|
||||
(decimate (shl GPR32, 9), 1),
|
||||
(decimate (shl GPR32, 10), 1),
|
||||
(decimate (shl GPR32, 11), 1),
|
||||
(decimate (shl GPR32, 12), 1),
|
||||
(decimate (shl GPR32, 13), 1),
|
||||
(decimate (shl GPR32, 14), 1),
|
||||
(decimate (shl GPR32, 15), 1),
|
||||
(decimate (shl GPR32, 16), 1),
|
||||
(decimate (shl GPR32, 17), 1),
|
||||
(decimate (shl GPR32, 18), 1),
|
||||
(decimate (shl GPR32, 19), 1),
|
||||
(decimate (shl GPR32, 20), 1),
|
||||
(decimate (shl GPR32, 21), 1),
|
||||
(decimate (shl GPR32, 22), 1),
|
||||
(decimate (shl GPR32, 23), 1),
|
||||
(decimate (shl GPR32, 24), 1),
|
||||
(decimate (shl GPR32, 25), 1),
|
||||
(decimate (shl GPR32, 26), 1),
|
||||
(decimate (shl GPR32, 27), 1),
|
||||
(decimate (shl GPR32, 28), 1),
|
||||
(decimate (shl GPR32, 29), 1),
|
||||
(decimate (shl GPR32, 30), 1),
|
||||
(decimate (shl GPR32, 31), 1)
|
||||
]>;
|
||||
|
||||
def GPR_64 : RegisterClass<"", [v2i32], 64, (add GPR64)>;
|
||||
def GPR_1024 : RegisterClass<"", [v32i32], 1024, (add GPR1024)>;
|
14
llvm/test/TableGen/dag-isel-subregs.td
Normal file
14
llvm/test/TableGen/dag-isel-subregs.td
Normal file
@ -0,0 +1,14 @@
|
||||
// RUN: llvm-tblgen -gen-dag-isel -I %p/../../include -I %p/Common %s | FileCheck %s
|
||||
|
||||
include "reg-with-subregs-common.td"
|
||||
|
||||
// CHECK-LABEL: OPC_CheckOpcode, TARGET_VAL(ISD::EXTRACT_SUBVECTOR),
|
||||
// CHECK: OPC_CheckChild1Integer, 0,
|
||||
// CHECK: OPC_EmitInteger, MVT::i32, sub0_sub1,
|
||||
def : Pat<(v2i32 (extract_subvector v32i32:$src, (i32 0))),
|
||||
(EXTRACT_SUBREG GPR_1024:$src, sub0_sub1)>;
|
||||
|
||||
// CHECK: OPC_CheckChild1Integer, 15,
|
||||
// CHECK: OPC_EmitInteger, MVT::i32, 5|128,1/*133*/,
|
||||
def : Pat<(v2i32 (extract_subvector v32i32:$src, (i32 15))),
|
||||
(EXTRACT_SUBREG GPR_1024:$src, sub30_sub31)>;
|
@ -1220,6 +1220,12 @@ CodeGenSubRegIndex *CodeGenRegBank::getSubRegIdx(Record *Def) {
|
||||
return Idx;
|
||||
}
|
||||
|
||||
const CodeGenSubRegIndex *
|
||||
CodeGenRegBank::findSubRegIdx(const Record* Def) const {
|
||||
auto I = Def2SubRegIdx.find(Def);
|
||||
return (I == Def2SubRegIdx.end()) ? nullptr : I->second;
|
||||
}
|
||||
|
||||
CodeGenRegister *CodeGenRegBank::getReg(Record *Def) {
|
||||
CodeGenRegister *&Reg = Def2Reg[Def];
|
||||
if (Reg)
|
||||
|
@ -626,9 +626,13 @@ namespace llvm {
|
||||
return SubRegIndices;
|
||||
}
|
||||
|
||||
// Find a SubRegIndex form its Record def.
|
||||
// Find a SubRegIndex from its Record def or add to the list if it does
|
||||
// not exist there yet.
|
||||
CodeGenSubRegIndex *getSubRegIdx(Record*);
|
||||
|
||||
// Find a SubRegIndex from its Record def.
|
||||
const CodeGenSubRegIndex *findSubRegIdx(const Record* Def) const;
|
||||
|
||||
// Find or create a sub-register index representing the A+B composition.
|
||||
CodeGenSubRegIndex *getCompositeSubRegIndex(CodeGenSubRegIndex *A,
|
||||
CodeGenSubRegIndex *B);
|
||||
|
@ -619,7 +619,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
|
||||
}
|
||||
case Matcher::EmitStringInteger: {
|
||||
const std::string &Val = cast<EmitStringIntegerMatcher>(N)->getValue();
|
||||
// These should always fit into one byte.
|
||||
// These should always fit into 7 bits.
|
||||
OS << "OPC_EmitInteger, "
|
||||
<< getEnumName(cast<EmitStringIntegerMatcher>(N)->getVT()) << ", "
|
||||
<< Val << ",\n";
|
||||
|
@ -715,6 +715,18 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N,
|
||||
|
||||
// Handle a subregister index. This is used for INSERT_SUBREG etc.
|
||||
if (Def->isSubClassOf("SubRegIndex")) {
|
||||
const CodeGenRegBank &RB = CGP.getTargetInfo().getRegBank();
|
||||
// If we have more than 127 subreg indices the encoding can overflow
|
||||
// 7 bit and we cannot use StringInteger.
|
||||
if (RB.getSubRegIndices().size() > 127) {
|
||||
const CodeGenSubRegIndex *I = RB.findSubRegIdx(Def);
|
||||
assert(I && "Cannot find subreg index by name!");
|
||||
if (I->EnumValue > 127) {
|
||||
AddMatcher(new EmitIntegerMatcher(I->EnumValue, MVT::i32));
|
||||
ResultOps.push_back(NextRecordedOperandNo++);
|
||||
return;
|
||||
}
|
||||
}
|
||||
std::string Value = getQualifiedName(Def);
|
||||
AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32));
|
||||
ResultOps.push_back(NextRecordedOperandNo++);
|
||||
|
@ -173,7 +173,7 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
|
||||
std::string Namespace = SubRegIndices.front().getNamespace();
|
||||
if (!Namespace.empty())
|
||||
OS << "namespace " << Namespace << " {\n";
|
||||
OS << "enum {\n NoSubRegister,\n";
|
||||
OS << "enum : uint16_t {\n NoSubRegister,\n";
|
||||
unsigned i = 0;
|
||||
for (const auto &Idx : SubRegIndices)
|
||||
OS << " " << Idx.getName() << ",\t// " << ++i << "\n";
|
||||
|
Loading…
Reference in New Issue
Block a user