// 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:
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;
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.
// 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<[]>;
}
// 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),
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),
[], "$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<[]>;
"...\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();
});
}
+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());
});
}
-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));
});
}