@@ -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
219198private:
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