Skip to content

Commit f652ef3

Browse files
committed
Revert rL342465: Added function to set a register to a particular value + tests.
rL342465 is breaking the MSVC buildbots. llvm-svn: 342490
1 parent 0242689 commit f652ef3

File tree

6 files changed

+264
-314
lines changed

6 files changed

+264
-314
lines changed

llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ class AArch64LatencyBenchmarkRunner : public LatencyBenchmarkRunner {
2727
};
2828

2929
class ExegesisAArch64Target : public ExegesisTarget {
30+
std::vector<llvm::MCInst> setRegToConstant(const llvm::MCSubtargetInfo &STI,
31+
unsigned Reg) const override {
32+
llvm_unreachable("Not yet implemented");
33+
}
34+
3035
std::vector<llvm::MCInst> setRegTo(const llvm::MCSubtargetInfo &STI,
3136
const llvm::APInt &Value,
3237
unsigned Reg) const override {

llvm/tools/llvm-exegesis/lib/Assembler.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ generateSnippetSetupCode(const llvm::ArrayRef<unsigned> RegsToDef,
3434
const llvm::LLVMTargetMachine &TM, bool &IsComplete) {
3535
IsComplete = true;
3636
std::vector<llvm::MCInst> Result;
37-
// for (const unsigned Reg : RegsToDef) {
38-
// // Load a constant in the register.
39-
// const auto Code = ET.setRegToConstant(*TM.getMCSubtargetInfo(), Reg);
40-
// if (Code.empty())
41-
// IsComplete = false;
42-
// Result.insert(Result.end(), Code.begin(), Code.end());
43-
// }
37+
for (const unsigned Reg : RegsToDef) {
38+
// Load a constant in the register.
39+
const auto Code = ET.setRegToConstant(*TM.getMCSubtargetInfo(), Reg);
40+
if (Code.empty())
41+
IsComplete = false;
42+
Result.insert(Result.end(), Code.begin(), Code.end());
43+
}
4444
return Result;
4545
}
4646

llvm/tools/llvm-exegesis/lib/Target.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ namespace {
8989
// Default implementation.
9090
class ExegesisDefaultTarget : public ExegesisTarget {
9191
private:
92+
std::vector<llvm::MCInst> setRegToConstant(const llvm::MCSubtargetInfo &STI,
93+
unsigned Reg) const override {
94+
llvm_unreachable("Not yet implemented");
95+
}
96+
9297
std::vector<llvm::MCInst> setRegTo(const llvm::MCSubtargetInfo &STI,
9398
const llvm::APInt &Value,
9499
unsigned Reg) const override {

llvm/tools/llvm-exegesis/lib/Target.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ class ExegesisTarget {
3535
// Targets can use this to add target-specific passes in assembleToStream();
3636
virtual void addTargetSpecificPasses(llvm::PassManagerBase &PM) const {}
3737

38+
// Generates code to move a constant into a the given register.
39+
virtual std::vector<llvm::MCInst>
40+
setRegToConstant(const llvm::MCSubtargetInfo &STI, unsigned Reg) const = 0;
41+
3842
// Generates code to move a constant into a the given register.
3943
virtual std::vector<llvm::MCInst> setRegTo(const llvm::MCSubtargetInfo &STI,
4044
const llvm::APInt &Value,

llvm/tools/llvm-exegesis/lib/X86/Target.cpp

Lines changed: 78 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,7 @@ static unsigned GetLoadImmediateOpcode(const llvm::APInt &Value) {
115115
llvm_unreachable("Invalid Value Width");
116116
}
117117

118-
static llvm::MCInst loadImmediate(unsigned Reg, const llvm::APInt &Value,
119-
unsigned MaxBitWidth) {
120-
assert(Value.getBitWidth() <= MaxBitWidth && "Value too big to fit register");
118+
static llvm::MCInst loadImmediate(unsigned Reg, const llvm::APInt &Value) {
121119
return llvm::MCInstBuilder(GetLoadImmediateOpcode(Value))
122120
.addReg(Reg)
123121
.addImm(Value.getZExtValue());
@@ -169,59 +167,35 @@ struct ConstantInliner {
169167
explicit ConstantInliner(const llvm::APInt &Constant)
170168
: StackSize(Constant.getBitWidth() / 8) {
171169
assert(Constant.getBitWidth() % 8 == 0 && "Must be a multiple of 8");
172-
add(allocateStackSpace(StackSize));
170+
Add(allocateStackSpace(StackSize));
173171
size_t ByteOffset = 0;
174172
for (; StackSize - ByteOffset >= 4; ByteOffset += 4)
175-
add(fillStackSpace(
173+
Add(fillStackSpace(
176174
llvm::X86::MOV32mi, ByteOffset,
177175
Constant.extractBits(32, ByteOffset * 8).getZExtValue()));
178176
if (StackSize - ByteOffset >= 2) {
179-
add(fillStackSpace(
177+
Add(fillStackSpace(
180178
llvm::X86::MOV16mi, ByteOffset,
181179
Constant.extractBits(16, ByteOffset * 8).getZExtValue()));
182180
ByteOffset += 2;
183181
}
184182
if (StackSize - ByteOffset >= 1)
185-
add(fillStackSpace(
183+
Add(fillStackSpace(
186184
llvm::X86::MOV8mi, ByteOffset,
187185
Constant.extractBits(8, ByteOffset * 8).getZExtValue()));
188186
}
189187

190-
std::vector<llvm::MCInst> loadAndFinalize(unsigned Reg, unsigned Opcode,
191-
unsigned BitWidth) {
192-
assert(StackSize * 8 == BitWidth && "Value does not have the correct size");
193-
add(loadToReg(Reg, Opcode));
194-
add(releaseStackSpace(StackSize));
195-
return std::move(Instructions);
196-
}
197-
198-
std::vector<llvm::MCInst> loadX87AndFinalize(unsigned Reg, unsigned Opcode,
199-
unsigned BitWidth) {
200-
assert(StackSize * 8 == BitWidth && "Value does not have the correct size");
201-
add(llvm::MCInstBuilder(Opcode)
202-
.addReg(llvm::X86::RSP) // BaseReg
203-
.addImm(1) // ScaleAmt
204-
.addReg(0) // IndexReg
205-
.addImm(0) // Disp
206-
.addReg(0)); // Segment
207-
if (Reg != llvm::X86::ST0)
208-
add(llvm::MCInstBuilder(llvm::X86::ST_Frr).addReg(Reg));
209-
add(releaseStackSpace(StackSize));
210-
return std::move(Instructions);
188+
ConstantInliner &Add(const llvm::MCInst &Inst) {
189+
Instructions.push_back(Inst);
190+
return *this;
211191
}
212192

213-
std::vector<llvm::MCInst> popFlagAndFinalize() {
214-
assert(StackSize * 8 == 32 && "Value does not have the correct size");
215-
add(llvm::MCInstBuilder(llvm::X86::POPF64));
193+
std::vector<llvm::MCInst> finalize() {
194+
Add(releaseStackSpace(StackSize));
216195
return std::move(Instructions);
217196
}
218197

219198
private:
220-
ConstantInliner &add(const llvm::MCInst &Inst) {
221-
Instructions.push_back(Inst);
222-
return *this;
223-
}
224-
225199
const size_t StackSize;
226200
std::vector<llvm::MCInst> Instructions;
227201
};
@@ -274,46 +248,63 @@ class ExegesisX86Target : public ExegesisTarget {
274248
}
275249
}
276250

277-
std::vector<llvm::MCInst> setRegTo(const llvm::MCSubtargetInfo &STI,
278-
const llvm::APInt &Value,
279-
unsigned Reg) const override {
251+
std::vector<llvm::MCInst> setRegToConstant(const llvm::MCSubtargetInfo &STI,
252+
unsigned Reg) const override {
253+
// GPR.
280254
if (llvm::X86::GR8RegClass.contains(Reg))
281-
return {loadImmediate(Reg, Value, 8)};
255+
return {llvm::MCInstBuilder(llvm::X86::MOV8ri).addReg(Reg).addImm(1)};
282256
if (llvm::X86::GR16RegClass.contains(Reg))
283-
return {loadImmediate(Reg, Value, 16)};
257+
return {llvm::MCInstBuilder(llvm::X86::MOV16ri).addReg(Reg).addImm(1)};
284258
if (llvm::X86::GR32RegClass.contains(Reg))
285-
return {loadImmediate(Reg, Value, 32)};
259+
return {llvm::MCInstBuilder(llvm::X86::MOV32ri).addReg(Reg).addImm(1)};
286260
if (llvm::X86::GR64RegClass.contains(Reg))
287-
return {loadImmediate(Reg, Value, 64)};
288-
ConstantInliner CI(Value);
261+
return {llvm::MCInstBuilder(llvm::X86::MOV64ri32).addReg(Reg).addImm(1)};
262+
// MMX.
289263
if (llvm::X86::VR64RegClass.contains(Reg))
290-
return CI.loadAndFinalize(Reg, llvm::X86::MMX_MOVQ64rm, 64);
264+
return setVectorRegToConstant(Reg, 8, llvm::X86::MMX_MOVQ64rm);
265+
// {X,Y,Z}MM.
291266
if (llvm::X86::VR128XRegClass.contains(Reg)) {
292267
if (STI.getFeatureBits()[llvm::X86::FeatureAVX512])
293-
return CI.loadAndFinalize(Reg, llvm::X86::VMOVDQU32Z128rm, 128);
268+
return setVectorRegToConstant(Reg, 16, llvm::X86::VMOVDQU32Z128rm);
294269
if (STI.getFeatureBits()[llvm::X86::FeatureAVX])
295-
return CI.loadAndFinalize(Reg, llvm::X86::VMOVDQUrm, 128);
296-
return CI.loadAndFinalize(Reg, llvm::X86::MOVDQUrm, 128);
270+
return setVectorRegToConstant(Reg, 16, llvm::X86::VMOVDQUrm);
271+
return setVectorRegToConstant(Reg, 16, llvm::X86::MOVDQUrm);
297272
}
298273
if (llvm::X86::VR256XRegClass.contains(Reg)) {
299274
if (STI.getFeatureBits()[llvm::X86::FeatureAVX512])
300-
return CI.loadAndFinalize(Reg, llvm::X86::VMOVDQU32Z256rm, 256);
301-
if (STI.getFeatureBits()[llvm::X86::FeatureAVX])
302-
return CI.loadAndFinalize(Reg, llvm::X86::VMOVDQUYrm, 256);
275+
return setVectorRegToConstant(Reg, 32, llvm::X86::VMOVDQU32Z256rm);
276+
return setVectorRegToConstant(Reg, 32, llvm::X86::VMOVDQUYrm);
303277
}
304278
if (llvm::X86::VR512RegClass.contains(Reg))
305-
if (STI.getFeatureBits()[llvm::X86::FeatureAVX512])
306-
return CI.loadAndFinalize(Reg, llvm::X86::VMOVDQU32Zrm, 512);
307-
if (llvm::X86::RSTRegClass.contains(Reg)) {
308-
if (Value.getBitWidth() == 32)
309-
return CI.loadX87AndFinalize(Reg, llvm::X86::LD_F32m, 32);
310-
if (Value.getBitWidth() == 64)
311-
return CI.loadX87AndFinalize(Reg, llvm::X86::LD_F64m, 64);
312-
if (Value.getBitWidth() == 80)
313-
return CI.loadX87AndFinalize(Reg, llvm::X86::LD_F80m, 80);
279+
return setVectorRegToConstant(Reg, 64, llvm::X86::VMOVDQU32Zrm);
280+
// X87.
281+
if (llvm::X86::RFP32RegClass.contains(Reg) ||
282+
llvm::X86::RFP64RegClass.contains(Reg) ||
283+
llvm::X86::RFP80RegClass.contains(Reg))
284+
return setVectorRegToConstant(Reg, 8, llvm::X86::LD_Fp64m);
285+
if (Reg == llvm::X86::EFLAGS) {
286+
// Set all flags to 0 but the bits that are "reserved and set to 1".
287+
constexpr const uint32_t kImmValue = 0x00007002u;
288+
std::vector<llvm::MCInst> Result;
289+
Result.push_back(allocateStackSpace(8));
290+
Result.push_back(fillStackSpace(llvm::X86::MOV64mi32, 0, kImmValue));
291+
Result.push_back(llvm::MCInstBuilder(llvm::X86::POPF64)); // Also pops.
292+
return Result;
314293
}
315-
if (Reg == llvm::X86::EFLAGS)
316-
return CI.popFlagAndFinalize();
294+
llvm_unreachable("Not yet implemented");
295+
}
296+
297+
std::vector<llvm::MCInst> setRegTo(const llvm::MCSubtargetInfo &STI,
298+
const llvm::APInt &Value,
299+
unsigned Reg) const override {
300+
if (llvm::X86::GR8RegClass.contains(Reg) ||
301+
llvm::X86::GR16RegClass.contains(Reg) ||
302+
llvm::X86::GR32RegClass.contains(Reg) ||
303+
llvm::X86::GR64RegClass.contains(Reg))
304+
return {loadImmediate(Reg, Value)};
305+
ConstantInliner CI(Value);
306+
if (llvm::X86::VR64RegClass.contains(Reg))
307+
return CI.Add(loadToReg(Reg, llvm::X86::MMX_MOVQ64rm)).finalize();
317308
llvm_unreachable("Not yet implemented");
318309
}
319310

@@ -330,6 +321,31 @@ class ExegesisX86Target : public ExegesisTarget {
330321
bool matchesArch(llvm::Triple::ArchType Arch) const override {
331322
return Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::x86;
332323
}
324+
325+
private:
326+
// setRegToConstant() specialized for a vector register of size
327+
// `RegSizeBytes`. `RMOpcode` is the opcode used to do a memory -> vector
328+
// register load.
329+
static std::vector<llvm::MCInst>
330+
setVectorRegToConstant(const unsigned Reg, const unsigned RegSizeBytes,
331+
const unsigned RMOpcode) {
332+
// There is no instruction to directly set XMM, go through memory.
333+
// Since vector values can be interpreted as integers of various sizes (8
334+
// to 64 bits) as well as floats and double, so we chose an immediate
335+
// value that has set bits for all byte values and is a normal float/
336+
// double. 0x40404040 is ~32.5 when interpreted as a double and ~3.0f when
337+
// interpreted as a float.
338+
constexpr const uint32_t kImmValue = 0x40404040u;
339+
std::vector<llvm::MCInst> Result;
340+
Result.push_back(allocateStackSpace(RegSizeBytes));
341+
constexpr const unsigned kMov32NumBytes = 4;
342+
for (unsigned Disp = 0; Disp < RegSizeBytes; Disp += kMov32NumBytes) {
343+
Result.push_back(fillStackSpace(llvm::X86::MOV32mi, Disp, kImmValue));
344+
}
345+
Result.push_back(loadToReg(Reg, RMOpcode));
346+
Result.push_back(releaseStackSpace(RegSizeBytes));
347+
return Result;
348+
}
333349
};
334350

335351
} // namespace

0 commit comments

Comments
 (0)