[AArch64] Make getInstSizeInBytes() use instruction size from InstrInfo.td

Currently, AArch64InstrInfo::getInstSizeInBytes() uses hard-coded
instruction size for some pseudo-instructions, while this
information should ideally be found in AArch64InstrInfo.td file (which
can be accessed via MCInstrDesc). Hence, the .td file should be updated
and no hard-coded instruction sizes should be used by
getInstSizeInBytes() anymore.

Differential Revision: https://reviews.llvm.org/D117970
This commit is contained in:
tyb0807 2022-01-22 10:31:56 +00:00
parent b00bce2a93
commit dd88f40c80
3 changed files with 128 additions and 31 deletions

View File

@ -93,9 +93,18 @@ unsigned AArch64InstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
// before the assembly printer.
unsigned NumBytes = 0;
const MCInstrDesc &Desc = MI.getDesc();
// Size should be preferably set in
// llvm/lib/Target/AArch64/AArch64InstrInfo.td (default case).
// Specific cases handle instructions of variable sizes
switch (Desc.getOpcode()) {
default:
// Anything not explicitly designated otherwise is a normal 4-byte insn.
if (Desc.getSize())
return Desc.getSize();
// Anything not explicitly designated otherwise (i.e. pseudo-instructions
// with fixed constant size but not specified in .td file) is a normal
// 4-byte insn.
NumBytes = 4;
break;
case TargetOpcode::STACKMAP:
@ -115,33 +124,9 @@ unsigned AArch64InstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
if (NumBytes == 0)
NumBytes = 4;
break;
case AArch64::TLSDESC_CALLSEQ:
// This gets lowered to an instruction sequence which takes 16 bytes
NumBytes = 16;
break;
case AArch64::SpeculationBarrierISBDSBEndBB:
// This gets lowered to 2 4-byte instructions.
NumBytes = 8;
break;
case AArch64::SpeculationBarrierSBEndBB:
// This gets lowered to 1 4-byte instructions.
NumBytes = 4;
break;
case AArch64::JumpTableDest32:
case AArch64::JumpTableDest16:
case AArch64::JumpTableDest8:
case AArch64::MOPSMemoryCopyPseudo:
case AArch64::MOPSMemoryMovePseudo:
case AArch64::MOPSMemorySetPseudo:
case AArch64::MOPSMemorySetTaggingPseudo:
NumBytes = 12;
break;
case AArch64::SPACE:
NumBytes = MI.getOperand(1).getImm();
break;
case AArch64::StoreSwiftAsyncContext:
NumBytes = 20;
break;
case TargetOpcode::BUNDLE:
NumBytes = getInstBundleLength(MI);
break;

View File

@ -780,6 +780,7 @@ def : Pat<(AArch64LOADgot texternalsym:$addr),
def : Pat<(AArch64LOADgot tconstpool:$addr),
(LOADgot tconstpool:$addr)>;
// In general these get lowered into a sequence of three 4-byte instructions.
// 32-bit jump table destination is actually only 2 instructions since we can
// use the table itself as a PC-relative base. But optimization occurs after
// branch relaxation so be pessimistic.
@ -815,8 +816,12 @@ let hasSideEffects = 1, isCodeGenOnly = 1 in {
// SpeculationBarrierEndBB must only be used after an unconditional control
// flow, i.e. after a terminator for which isBarrier is True.
let hasSideEffects = 1, isCodeGenOnly = 1, isTerminator = 1, isBarrier = 1 in {
// This gets lowered to a pair of 4-byte instructions.
let Size = 8 in
def SpeculationBarrierISBDSBEndBB
: Pseudo<(outs), (ins), []>, Sched<[]>;
// This gets lowered to a 4-byte instruction.
let Size = 4 in
def SpeculationBarrierSBEndBB
: Pseudo<(outs), (ins), []>, Sched<[]>;
}
@ -2356,7 +2361,8 @@ def EMITBKEY : Pseudo<(outs), (ins), []>, Sched<[]> {}
// FIXME: maybe the scratch register used shouldn't be fixed to X1?
// FIXME: can "hasSideEffects be dropped?
let isCall = 1, Defs = [LR, X0, X1], hasSideEffects = 1,
// This gets lowered to an instruction sequence which takes 16 bytes
let isCall = 1, Defs = [LR, X0, X1], hasSideEffects = 1, Size = 16,
isCodeGenOnly = 1 in
def TLSDESC_CALLSEQ
: Pseudo<(outs), (ins i64imm:$sym),
@ -8370,6 +8376,7 @@ def AArch64mops_memset_tagging : SDNode<"AArch64ISD::MOPS_MEMSET_TAGGING", SDT_A
def AArch64mops_memcopy : SDNode<"AArch64ISD::MOPS_MEMCOPY", SDT_AArch64mops>;
def AArch64mops_memmove : SDNode<"AArch64ISD::MOPS_MEMMOVE", SDT_AArch64mops>;
// MOPS operations always contain three 4-byte instructions
let Predicates = [HasMOPS], Defs = [NZCV], Size = 12, mayStore = 1 in {
let mayLoad = 1 in {
def MOPSMemoryCopyPseudo : Pseudo<(outs GPR64common:$Rd_wb, GPR64common:$Rs_wb, GPR64:$Rn_wb),
@ -8391,7 +8398,8 @@ let Predicates = [HasMOPS, HasMTE], Defs = [NZCV], Size = 12, mayLoad = 0, maySt
[], "$Rd = $Rd_wb,$Rn = $Rn_wb">, Sched<[]>;
}
let Defs = [X16, X17], mayStore = 1, isCodeGenOnly = 1 in
// This gets lowered into an instruction sequence of 20 bytes
let Defs = [X16, X17], mayStore = 1, isCodeGenOnly = 1, Size = 20 in
def StoreSwiftAsyncContext
: Pseudo<(outs), (ins GPR64:$ctx, GPR64sp:$base, simm9:$offset),
[]>, Sched<[]>;

View File

@ -52,6 +52,11 @@ void runChecks(
"...\n"
"---\n"
"name: sizes\n"
"jumpTable:\n"
" kind: block-address\n"
" entries:\n"
" - id: 0\n"
" blocks: [ '%bb.0' ]\n"
"body: |\n"
" bb.0:\n"
+ InputMIRSnippet.str();
@ -142,6 +147,34 @@ TEST(InstSizes, PATCHPOINT) {
});
}
TEST(InstSizes, STATEPOINT) {
std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
runChecks(TM.get(), II.get(), "",
" STATEPOINT 0, 0, 0, @sizes, 2, 0, 2, 0, 2, 0, 2, 1, 1, 8,"
" $sp, 24, 2, 0, 2, 1, 0, 0\n",
[](AArch64InstrInfo &II, MachineFunction &MF) {
auto I = MF.begin()->begin();
EXPECT_EQ(4u, II.getInstSizeInBytes(*I));
});
}
TEST(InstSizes, SPACE) {
std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
runChecks(TM.get(), II.get(), "",
" $xzr = SPACE 1024, undef $xzr\n"
" dead $xzr = SPACE 4096, $xzr\n",
[](AArch64InstrInfo &II, MachineFunction &MF) {
auto I = MF.begin()->begin();
EXPECT_EQ(1024u, II.getInstSizeInBytes(*I));
++I;
EXPECT_EQ(4096u, II.getInstSizeInBytes(*I));
});
}
TEST(InstSizes, TLSDESC_CALLSEQ) {
std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
@ -156,16 +189,87 @@ TEST(InstSizes, TLSDESC_CALLSEQ) {
});
}
TEST(InstSizes, MOPSMemorySetTaggingPseudo) {
TEST(InstSizes, StoreSwiftAsyncContext) {
std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
runChecks(
TM.get(), II.get(), "",
" StoreSwiftAsyncContext $x0, $x1, 12, implicit-def $x16, "
"implicit-def $x17\n",
[](AArch64InstrInfo &II, MachineFunction &MF) {
auto I = MF.begin()->begin();
EXPECT_EQ(20u, II.getInstSizeInBytes(*I));
});
}
TEST(InstSizes, SpeculationBarrierISBDSBEndBB) {
std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
runChecks(
TM.get(), II.get(), "",
" SpeculationBarrierISBDSBEndBB\n"
" BR $x8\n",
[](AArch64InstrInfo &II, MachineFunction &MF) {
auto I = MF.begin()->begin();
EXPECT_EQ(8u, II.getInstSizeInBytes(*I));
});
}
TEST(InstSizes, SpeculationBarrierSBEndBB) {
std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
runChecks(
TM.get(), II.get(), "",
" SpeculationBarrierSBEndBB\n"
" BR $x8\n",
[](AArch64InstrInfo &II, MachineFunction &MF) {
auto I = MF.begin()->begin();
EXPECT_EQ(4u, II.getInstSizeInBytes(*I));
});
}
TEST(InstSizes, JumpTable) {
std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
runChecks(TM.get(), II.get(), "",
" renamable $x0, dead renamable $x1 = MOPSMemorySetTaggingPseudo "
"killed renamable $x0, killed renamable $x1, killed renamable $x2, "
"implicit-def dead $nzcv\n",
" $x10, $x11 = JumpTableDest32 $x9, $x8, %jump-table.0\n"
" $x10, $x11 = JumpTableDest16 $x9, $x8, %jump-table.0\n"
" $x10, $x11 = JumpTableDest8 $x9, $x8, %jump-table.0\n",
[](AArch64InstrInfo &II, MachineFunction &MF) {
auto I = MF.begin()->begin();
EXPECT_EQ(12u, II.getInstSizeInBytes(*I));
++I;
EXPECT_EQ(12u, II.getInstSizeInBytes(*I));
++I;
EXPECT_EQ(12u, II.getInstSizeInBytes(*I));
});
}
TEST(InstSizes, MOPSMemoryPseudos) {
std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
runChecks(TM.get(), II.get(), "",
" $x0, $x1, $x2 = MOPSMemoryMovePseudo $x0, $x1, $x2, "
"implicit-def $nzcv\n"
" $x0, $x1 = MOPSMemorySetPseudo $x0, $x1, $x2, "
"implicit-def $nzcv\n"
" $x0, $x1, $x8 = MOPSMemoryCopyPseudo $x0, $x1, $x8, "
"implicit-def $nzcv\n"
" $x0, $x1 = MOPSMemorySetTaggingPseudo $x0, $x1, $x2, "
"implicit-def $nzcv\n",
[](AArch64InstrInfo &II, MachineFunction &MF) {
auto I = MF.begin()->begin();
EXPECT_EQ(12u, II.getInstSizeInBytes(*I));
++I;
EXPECT_EQ(12u, II.getInstSizeInBytes(*I));
++I;
EXPECT_EQ(12u, II.getInstSizeInBytes(*I));
++I;
EXPECT_EQ(12u, II.getInstSizeInBytes(*I));
});
}