Skip to content

Commit 7ca8b31

Browse files
committed
[BOLT] Compare and Jump generation in MCPlusBuilder.
1 parent 77363f7 commit 7ca8b31

File tree

4 files changed

+145
-1
lines changed

4 files changed

+145
-1
lines changed

bolt/include/bolt/Core/MCPlusBuilder.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,6 +1714,16 @@ class MCPlusBuilder {
17141714
return {};
17151715
}
17161716

1717+
/// Create a sequence of instructions to compare contents of a register
1718+
/// \p RegNo to immediate \Imm and jump to \p Target if they are different.
1719+
virtual InstructionListType createCmpJNE(MCPhysReg RegNo, int64_t Imm,
1720+
const MCSymbol *Target,
1721+
MCContext *Ctx) const {
1722+
llvm_unreachable("not implemented");
1723+
return {};
1724+
}
1725+
1726+
17171727
/// Creates inline memcpy instruction. If \p ReturnEnd is true, then return
17181728
/// (dest + n) instead of dest.
17191729
virtual InstructionListType createInlineMemcpy(bool ReturnEnd) const {

bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1321,17 +1321,49 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
13211321

13221322
int getUncondBranchEncodingSize() const override { return 28; }
13231323

1324+
//This helper function creates the snippet of code
1325+
//that compares a register RegNo with an immedaite Imm,
1326+
//and jumps to Target if they are equal.
1327+
//cmp RegNo, #Imm
1328+
//b.eq Target
1329+
//where cmp is an for subs, which results in the code below:
1330+
//subs xzr, RegNo, #Imm
1331+
//b.eq Target.
13241332
InstructionListType createCmpJE(MCPhysReg RegNo, int64_t Imm,
13251333
const MCSymbol *Target,
13261334
MCContext *Ctx) const override {
13271335
InstructionListType Code;
13281336
Code.emplace_back(MCInstBuilder(AArch64::SUBSXri)
1329-
.addReg(RegNo)
1337+
.addReg(AArch64::XZR)
13301338
.addReg(RegNo)
13311339
.addImm(Imm)
13321340
.addImm(0));
13331341
Code.emplace_back(MCInstBuilder(AArch64::Bcc)
1342+
.addImm(AArch64CC::EQ)
1343+
.addExpr(MCSymbolRefExpr::create(
1344+
Target, MCSymbolRefExpr::VK_None, *Ctx)));
1345+
return Code;
1346+
}
1347+
1348+
//This helper function creates the snippet of code
1349+
//that compares a register RegNo with an immedaite Imm,
1350+
//and jumps to Target if they are not equal.
1351+
//cmp RegNo, #Imm
1352+
//b.ne Target
1353+
//where cmp is an for subs, which results in the code below:
1354+
//subs xzr, RegNo, #Imm
1355+
//b.ne Target.
1356+
InstructionListType createCmpJNE(MCPhysReg RegNo, int64_t Imm,
1357+
const MCSymbol *Target,
1358+
MCContext *Ctx) const override {
1359+
InstructionListType Code;
1360+
Code.emplace_back(MCInstBuilder(AArch64::SUBSXri)
1361+
.addReg(AArch64::XZR)
1362+
.addReg(RegNo)
13341363
.addImm(Imm)
1364+
.addImm(0));
1365+
Code.emplace_back(MCInstBuilder(AArch64::Bcc)
1366+
.addImm(AArch64CC::NE)
13351367
.addExpr(MCSymbolRefExpr::create(
13361368
Target, MCSymbolRefExpr::VK_None, *Ctx)));
13371369
return Code;

bolt/lib/Target/X86/X86MCPlusBuilder.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2436,6 +2436,20 @@ class X86MCPlusBuilder : public MCPlusBuilder {
24362436
return Code;
24372437
}
24382438

2439+
InstructionListType createCmpJNE(MCPhysReg RegNo, int64_t Imm,
2440+
const MCSymbol *Target,
2441+
MCContext *Ctx) const override {
2442+
InstructionListType Code;
2443+
Code.emplace_back(MCInstBuilder(X86::CMP64ri8)
2444+
.addReg(RegNo)
2445+
.addImm(Imm));
2446+
Code.emplace_back(MCInstBuilder(X86::JCC_1)
2447+
.addExpr(MCSymbolRefExpr::create(
2448+
Target, MCSymbolRefExpr::VK_None, *Ctx))
2449+
.addImm(X86::COND_NE));
2450+
return Code;
2451+
}
2452+
24392453
std::optional<Relocation>
24402454
createRelocation(const MCFixup &Fixup,
24412455
const MCAsmBackend &MAB) const override {

bolt/unittests/Core/MCPlusBuilder.cpp

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,52 @@ TEST_P(MCPlusBuilderTester, AliasSmallerX0) {
107107
testRegAliases(Triple::aarch64, AArch64::X0, AliasesX0, AliasesX0Count, true);
108108
}
109109

110+
TEST_P(MCPlusBuilderTester, AArch64_CmpJE) {
111+
if (GetParam() != Triple::aarch64)
112+
GTEST_SKIP();
113+
BinaryFunction *BF = BC->createInjectedBinaryFunction("BF", true);
114+
std::unique_ptr<BinaryBasicBlock> BB = BF->createBasicBlock();
115+
116+
InstructionListType Instrs = BC->MIB->createCmpJE(AArch64::X0, 2, BB->getLabel(), BC->Ctx.get());
117+
BB->addInstructions(Instrs.begin(), Instrs.end());
118+
BB->addSuccessor(BB.get());
119+
120+
auto II = BB->begin();
121+
ASSERT_EQ(II->getOpcode(), AArch64::SUBSXri);
122+
ASSERT_EQ(II->getOperand(0).getReg(), AArch64::XZR);
123+
ASSERT_EQ(II->getOperand(1).getReg(), AArch64::X0);
124+
ASSERT_EQ(II->getOperand(2).getImm(), 2);
125+
ASSERT_EQ(II->getOperand(3).getImm(), 0);
126+
II++;
127+
ASSERT_EQ(II->getOpcode(), AArch64::Bcc);
128+
ASSERT_EQ(II->getOperand(0).getImm(), AArch64CC::EQ);
129+
const MCSymbol *Label = BC->MIB->getTargetSymbol(*II,1);
130+
ASSERT_EQ(Label, BB->getLabel());
131+
}
132+
133+
TEST_P(MCPlusBuilderTester, AArch64_CmpJNE) {
134+
if (GetParam() != Triple::aarch64)
135+
GTEST_SKIP();
136+
BinaryFunction *BF = BC->createInjectedBinaryFunction("BF", true);
137+
std::unique_ptr<BinaryBasicBlock> BB = BF->createBasicBlock();
138+
139+
InstructionListType Instrs = BC->MIB->createCmpJNE(AArch64::X0, 2, BB->getLabel(), BC->Ctx.get());
140+
BB->addInstructions(Instrs.begin(), Instrs.end());
141+
BB->addSuccessor(BB.get());
142+
143+
auto II = BB->begin();
144+
ASSERT_EQ(II->getOpcode(), AArch64::SUBSXri);
145+
ASSERT_EQ(II->getOperand(0).getReg(), AArch64::XZR);
146+
ASSERT_EQ(II->getOperand(1).getReg(), AArch64::X0);
147+
ASSERT_EQ(II->getOperand(2).getImm(), 2);
148+
ASSERT_EQ(II->getOperand(3).getImm(), 0);
149+
II++;
150+
ASSERT_EQ(II->getOpcode(), AArch64::Bcc);
151+
ASSERT_EQ(II->getOperand(0).getImm(), AArch64CC::NE);
152+
const MCSymbol *Label = BC->MIB->getTargetSymbol(*II,1);
153+
ASSERT_EQ(Label, BB->getLabel());
154+
}
155+
110156
#endif // AARCH64_AVAILABLE
111157

112158
#ifdef X86_AVAILABLE
@@ -143,6 +189,48 @@ TEST_P(MCPlusBuilderTester, ReplaceRegWithImm) {
143189
ASSERT_EQ(II->getOperand(1).getImm(), 1);
144190
}
145191

192+
TEST_P(MCPlusBuilderTester, X86_CmpJE) {
193+
if (GetParam() != Triple::x86_64)
194+
GTEST_SKIP();
195+
BinaryFunction *BF = BC->createInjectedBinaryFunction("BF", true);
196+
std::unique_ptr<BinaryBasicBlock> BB = BF->createBasicBlock();
197+
198+
InstructionListType Instrs = BC->MIB->createCmpJE(X86::EAX, 2, BB->getLabel(), BC->Ctx.get());
199+
BB->addInstructions(Instrs.begin(), Instrs.end());
200+
BB->addSuccessor(BB.get());
201+
202+
auto II = BB->begin();
203+
ASSERT_EQ(II->getOpcode(), X86::CMP64ri8);
204+
ASSERT_EQ(II->getOperand(0).getReg(), X86::EAX);
205+
ASSERT_EQ(II->getOperand(1).getImm(), 2);
206+
II++;
207+
ASSERT_EQ(II->getOpcode(), X86::JCC_1);
208+
const MCSymbol *Label = BC->MIB->getTargetSymbol(*II,0);
209+
ASSERT_EQ(Label, BB->getLabel());
210+
ASSERT_EQ(II->getOperand(1).getImm(), X86::COND_E);
211+
}
212+
213+
TEST_P(MCPlusBuilderTester, X86_CmpJNE) {
214+
if (GetParam() != Triple::x86_64)
215+
GTEST_SKIP();
216+
BinaryFunction *BF = BC->createInjectedBinaryFunction("BF", true);
217+
std::unique_ptr<BinaryBasicBlock> BB = BF->createBasicBlock();
218+
219+
InstructionListType Instrs = BC->MIB->createCmpJNE(X86::EAX, 2, BB->getLabel(), BC->Ctx.get());
220+
BB->addInstructions(Instrs.begin(), Instrs.end());
221+
BB->addSuccessor(BB.get());
222+
223+
auto II = BB->begin();
224+
ASSERT_EQ(II->getOpcode(), X86::CMP64ri8);
225+
ASSERT_EQ(II->getOperand(0).getReg(), X86::EAX);
226+
ASSERT_EQ(II->getOperand(1).getImm(), 2);
227+
II++;
228+
ASSERT_EQ(II->getOpcode(), X86::JCC_1);
229+
const MCSymbol *Label = BC->MIB->getTargetSymbol(*II,0);
230+
ASSERT_EQ(Label, BB->getLabel());
231+
ASSERT_EQ(II->getOperand(1).getImm(), X86::COND_NE);
232+
}
233+
146234
#endif // X86_AVAILABLE
147235

148236
TEST_P(MCPlusBuilderTester, Annotation) {

0 commit comments

Comments
 (0)