Skip to content

Commit df903ac

Browse files
committed
Optimize the code generation of createLoadImmediate for AArch64.
1 parent 73ddbd3 commit df903ac

File tree

2 files changed

+104
-8
lines changed

2 files changed

+104
-8
lines changed

bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2173,14 +2173,26 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
21732173

21742174
InstructionListType createLoadImmediate(const MCPhysReg Dest,
21752175
uint64_t Imm) const override {
2176-
InstructionListType Insts(4);
2177-
int Shift = 48;
2178-
for (int I = 0; I < 4; I++, Shift -= 16) {
2179-
Insts[I].setOpcode(AArch64::MOVKXi);
2180-
Insts[I].addOperand(MCOperand::createReg(Dest));
2181-
Insts[I].addOperand(MCOperand::createReg(Dest));
2182-
Insts[I].addOperand(MCOperand::createImm((Imm >> Shift) & 0xFFFF));
2183-
Insts[I].addOperand(MCOperand::createImm(Shift));
2176+
InstructionListType Insts;
2177+
for (int I = 0, Shift = 0; I < 4; I++, Shift += 16) {
2178+
uint16_t HalfWord = (Imm >> Shift) & 0xFFFF;
2179+
if (!HalfWord)
2180+
continue;
2181+
MCInst Inst;
2182+
if (Insts.size() == 0) {
2183+
Inst.setOpcode(AArch64::MOVZXi);
2184+
Inst.addOperand(MCOperand::createReg(Dest));
2185+
Inst.addOperand(MCOperand::createImm(HalfWord));
2186+
Inst.addOperand(MCOperand::createImm(Shift));
2187+
Insts.push_back(Inst);
2188+
} else {
2189+
Inst.setOpcode(AArch64::MOVKXi);
2190+
Inst.addOperand(MCOperand::createReg(Dest));
2191+
Inst.addOperand(MCOperand::createReg(Dest));
2192+
Inst.addOperand(MCOperand::createImm(HalfWord));
2193+
Inst.addOperand(MCOperand::createImm(Shift));
2194+
Insts.push_back(Inst);
2195+
}
21842196
}
21852197
return Insts;
21862198
}

bolt/unittests/Core/MCPlusBuilder.cpp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,90 @@ TEST_P(MCPlusBuilderTester, AArch64_CmpJNE) {
167167
ASSERT_EQ(Label, BB->getLabel());
168168
}
169169

170+
TEST_P(MCPlusBuilderTester, AArch64_LoadImm32) {
171+
if (GetParam() != Triple::aarch64)
172+
GTEST_SKIP();
173+
BinaryFunction *BF = BC->createInjectedBinaryFunction("BF", true);
174+
std::unique_ptr<BinaryBasicBlock> BB = BF->createBasicBlock();
175+
176+
InstructionListType Instrs = BC->MIB->createLoadImmediate(AArch64::X0, 2);
177+
BB->addInstructions(Instrs.begin(), Instrs.end());
178+
179+
ASSERT_EQ(BB->size(), 1);
180+
auto II = BB->begin();
181+
// mov x0, #2
182+
ASSERT_EQ(II->getOpcode(), AArch64::MOVZXi);
183+
ASSERT_EQ(II->getOperand(0).getReg(), AArch64::X0);
184+
ASSERT_EQ(II->getOperand(1).getImm(), 2);
185+
ASSERT_EQ(II->getOperand(2).getImm(), 0);
186+
}
187+
188+
TEST_P(MCPlusBuilderTester, AArch64_LoadImm64) {
189+
if (GetParam() != Triple::aarch64)
190+
GTEST_SKIP();
191+
BinaryFunction *BF = BC->createInjectedBinaryFunction("BF", true);
192+
std::unique_ptr<BinaryBasicBlock> BB = BF->createBasicBlock();
193+
194+
int64_t Imm = ((uint64_t)4) << 48 | ((uint64_t)3) << 32 | 2 << 16 | 1;
195+
InstructionListType Instrs = BC->MIB->createLoadImmediate(AArch64::X0, Imm);
196+
BB->addInstructions(Instrs.begin(), Instrs.end());
197+
198+
ASSERT_EQ(BB->size(), 4);
199+
auto II = BB->begin();
200+
// mov x0, #1
201+
ASSERT_EQ(II->getOpcode(), AArch64::MOVZXi);
202+
ASSERT_EQ(II->getOperand(0).getReg(), AArch64::X0);
203+
ASSERT_EQ(II->getOperand(1).getImm(), 1);
204+
ASSERT_EQ(II->getOperand(2).getImm(), 0);
205+
II++;
206+
// movk x0, #2, lsl #16
207+
ASSERT_EQ(II->getOpcode(), AArch64::MOVKXi);
208+
ASSERT_EQ(II->getOperand(0).getReg(), AArch64::X0);
209+
ASSERT_EQ(II->getOperand(1).getReg(), AArch64::X0);
210+
ASSERT_EQ(II->getOperand(2).getImm(), 2);
211+
ASSERT_EQ(II->getOperand(3).getImm(), 16);
212+
II++;
213+
// movk x0, #3, lsl #32
214+
ASSERT_EQ(II->getOpcode(), AArch64::MOVKXi);
215+
ASSERT_EQ(II->getOperand(0).getReg(), AArch64::X0);
216+
ASSERT_EQ(II->getOperand(1).getReg(), AArch64::X0);
217+
ASSERT_EQ(II->getOperand(2).getImm(), 3);
218+
ASSERT_EQ(II->getOperand(3).getImm(), 32);
219+
II++;
220+
// movk x0, #4, lsl #48
221+
ASSERT_EQ(II->getOpcode(), AArch64::MOVKXi);
222+
ASSERT_EQ(II->getOperand(0).getReg(), AArch64::X0);
223+
ASSERT_EQ(II->getOperand(1).getReg(), AArch64::X0);
224+
ASSERT_EQ(II->getOperand(2).getImm(), 4);
225+
ASSERT_EQ(II->getOperand(3).getImm(), 48);
226+
}
227+
228+
TEST_P(MCPlusBuilderTester, AArch64_LoadImm64Partial) {
229+
if (GetParam() != Triple::aarch64)
230+
GTEST_SKIP();
231+
BinaryFunction *BF = BC->createInjectedBinaryFunction("BF", true);
232+
std::unique_ptr<BinaryBasicBlock> BB = BF->createBasicBlock();
233+
234+
int64_t Imm = ((uint64_t)4) << 48 | 2 << 16;
235+
InstructionListType Instrs = BC->MIB->createLoadImmediate(AArch64::X0, Imm);
236+
BB->addInstructions(Instrs.begin(), Instrs.end());
237+
238+
ASSERT_EQ(BB->size(), 2);
239+
auto II = BB->begin();
240+
// mov x0, #2, lsl #16
241+
ASSERT_EQ(II->getOpcode(), AArch64::MOVZXi);
242+
ASSERT_EQ(II->getOperand(0).getReg(), AArch64::X0);
243+
ASSERT_EQ(II->getOperand(1).getImm(), 2);
244+
ASSERT_EQ(II->getOperand(2).getImm(), 16);
245+
II++;
246+
// movk x0, #4, lsl #48
247+
ASSERT_EQ(II->getOpcode(), AArch64::MOVKXi);
248+
ASSERT_EQ(II->getOperand(0).getReg(), AArch64::X0);
249+
ASSERT_EQ(II->getOperand(1).getReg(), AArch64::X0);
250+
ASSERT_EQ(II->getOperand(2).getImm(), 4);
251+
ASSERT_EQ(II->getOperand(3).getImm(), 48);
252+
}
253+
170254
TEST_P(MCPlusBuilderTester, testAccessedRegsImplicitDef) {
171255
if (GetParam() != Triple::aarch64)
172256
GTEST_SKIP();

0 commit comments

Comments
 (0)