From 0de588fd89ca7374dc91623d6627cfb98cfe3fc8 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Fri, 5 Sep 2008 21:00:03 +0000 Subject: [PATCH] Factor out code that emits load and store instructions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@55854 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86FastISel.cpp | 251 ++++++++++++++++++--------------- 1 file changed, 139 insertions(+), 112 deletions(-) diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index e63120d40e4..44fd9eaff12 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -45,6 +45,10 @@ public: #include "X86GenFastISel.inc" private: + bool X86FastEmitLoad(MVT VT, unsigned Op0, Value *V, unsigned &RR); + + bool X86FastEmitStore(MVT VT, unsigned Op0, unsigned Op1, Value *V); + bool X86SelectConstAddr(Value *V, unsigned &Op0); bool X86SelectLoad(Instruction *I); @@ -60,10 +64,133 @@ private: bool X86SelectShift(Instruction *I); bool X86SelectSelect(Instruction *I); - + unsigned TargetMaterializeConstant(Constant *C, MachineConstantPool* MCP); }; +/// X86FastEmitLoad - Emit a machine instruction to load a value of type VT. +/// The address is either pre-computed, i.e. Op0, or a GlobalAddress, i.e. V. +/// Return true and the result register by reference if it is possible. +bool X86FastISel::X86FastEmitLoad(MVT VT, unsigned Op0, Value *V, + unsigned &ResultReg) { + // Get opcode and regclass of the output for the given load instruction. + unsigned Opc = 0; + const TargetRegisterClass *RC = NULL; + switch (VT.getSimpleVT()) { + default: return false; + case MVT::i8: + Opc = X86::MOV8rm; + RC = X86::GR8RegisterClass; + break; + case MVT::i16: + Opc = X86::MOV16rm; + RC = X86::GR16RegisterClass; + break; + case MVT::i32: + Opc = X86::MOV32rm; + RC = X86::GR32RegisterClass; + break; + case MVT::i64: + // Must be in x86-64 mode. + Opc = X86::MOV64rm; + RC = X86::GR64RegisterClass; + break; + case MVT::f32: + if (Subtarget->hasSSE1()) { + Opc = X86::MOVSSrm; + RC = X86::FR32RegisterClass; + } else { + Opc = X86::LD_Fp32m; + RC = X86::RFP32RegisterClass; + } + break; + case MVT::f64: + if (Subtarget->hasSSE2()) { + Opc = X86::MOVSDrm; + RC = X86::FR64RegisterClass; + } else { + Opc = X86::LD_Fp64m; + RC = X86::RFP64RegisterClass; + } + break; + case MVT::f80: + Opc = X86::LD_Fp80m; + RC = X86::RFP80RegisterClass; + break; + } + + ResultReg = createResultReg(RC); + X86AddressMode AM; + if (Op0) + // Address is in register. + AM.Base.Reg = Op0; + else + AM.GV = cast(V); + addFullAddress(BuildMI(MBB, TII.get(Opc), ResultReg), AM); + return true; +} + +/// X86FastEmitStore - Emit a machine instruction to store a value Op0 of +/// type VT. The address is either pre-computed, i.e. Op1, or a GlobalAddress, +/// i.e. V. Return true if it is possible. +bool +X86FastISel::X86FastEmitStore(MVT VT, unsigned Op0, unsigned Op1, Value *V) { + // Get opcode and regclass of the output for the given load instruction. + unsigned Opc = 0; + const TargetRegisterClass *RC = NULL; + switch (VT.getSimpleVT()) { + default: return false; + case MVT::i8: + Opc = X86::MOV8mr; + RC = X86::GR8RegisterClass; + break; + case MVT::i16: + Opc = X86::MOV16mr; + RC = X86::GR16RegisterClass; + break; + case MVT::i32: + Opc = X86::MOV32mr; + RC = X86::GR32RegisterClass; + break; + case MVT::i64: + // Must be in x86-64 mode. + Opc = X86::MOV64mr; + RC = X86::GR64RegisterClass; + break; + case MVT::f32: + if (Subtarget->hasSSE1()) { + Opc = X86::MOVSSmr; + RC = X86::FR32RegisterClass; + } else { + Opc = X86::ST_Fp32m; + RC = X86::RFP32RegisterClass; + } + break; + case MVT::f64: + if (Subtarget->hasSSE2()) { + Opc = X86::MOVSDmr; + RC = X86::FR64RegisterClass; + } else { + Opc = X86::ST_Fp64m; + RC = X86::RFP64RegisterClass; + } + break; + case MVT::f80: + Opc = X86::ST_FP80m; + RC = X86::RFP80RegisterClass; + break; + } + + X86AddressMode AM; + if (Op1) + // Address is in register. + AM.Base.Reg = Op1; + else + AM.GV = cast(V); + addFullAddress(BuildMI(MBB, TII.get(Opc)), AM).addReg(Op0); + return true; +} + /// X86SelectConstAddr - Select and emit code to materialize constant address. /// bool X86FastISel::X86SelectConstAddr(Value *V, @@ -122,61 +249,8 @@ bool X86FastISel::X86SelectStore(Instruction* I) { // Unhandled operand. Halt "fast" selection and bail. return false; } - - // Get opcode and regclass of the output for the given load instruction. - unsigned Opc = 0; - const TargetRegisterClass *RC = NULL; - switch (VT.getSimpleVT()) { - default: return false; - case MVT::i8: - Opc = X86::MOV8mr; - RC = X86::GR8RegisterClass; - break; - case MVT::i16: - Opc = X86::MOV16mr; - RC = X86::GR16RegisterClass; - break; - case MVT::i32: - Opc = X86::MOV32mr; - RC = X86::GR32RegisterClass; - break; - case MVT::i64: - // Must be in x86-64 mode. - Opc = X86::MOV64mr; - RC = X86::GR64RegisterClass; - break; - case MVT::f32: - if (Subtarget->hasSSE1()) { - Opc = X86::MOVSSmr; - RC = X86::FR32RegisterClass; - } else { - Opc = X86::ST_Fp32m; - RC = X86::RFP32RegisterClass; - } - break; - case MVT::f64: - if (Subtarget->hasSSE2()) { - Opc = X86::MOVSDmr; - RC = X86::FR64RegisterClass; - } else { - Opc = X86::ST_Fp64m; - RC = X86::RFP64RegisterClass; - } - break; - case MVT::f80: - Opc = X86::ST_FP80m; - RC = X86::RFP80RegisterClass; - break; - } - X86AddressMode AM; - if (Op1) - // Address is in register. - AM.Base.Reg = Op1; - else - AM.GV = cast(V); - addFullAddress(BuildMI(MBB, TII.get(Opc)), AM).addReg(Op0); - return true; + return X86FastEmitStore(VT, Op0, Op1, V); } /// X86SelectLoad - Select and emit code to implement load instructions. @@ -200,67 +274,19 @@ bool X86FastISel::X86SelectLoad(Instruction *I) { unsigned Op0 = getRegForValue(V); if (Op0 == 0) { // Handle constant load address. + // FIXME: If load type is something we can't handle, this can result in + // a dead stub load instruction. if (!isa(V) || !X86SelectConstAddr(V, Op0)) // Unhandled operand. Halt "fast" selection and bail. return false; } - // Get opcode and regclass of the output for the given load instruction. - unsigned Opc = 0; - const TargetRegisterClass *RC = NULL; - switch (VT.getSimpleVT()) { - default: return false; - case MVT::i8: - Opc = X86::MOV8rm; - RC = X86::GR8RegisterClass; - break; - case MVT::i16: - Opc = X86::MOV16rm; - RC = X86::GR16RegisterClass; - break; - case MVT::i32: - Opc = X86::MOV32rm; - RC = X86::GR32RegisterClass; - break; - case MVT::i64: - // Must be in x86-64 mode. - Opc = X86::MOV64rm; - RC = X86::GR64RegisterClass; - break; - case MVT::f32: - if (Subtarget->hasSSE1()) { - Opc = X86::MOVSSrm; - RC = X86::FR32RegisterClass; - } else { - Opc = X86::LD_Fp32m; - RC = X86::RFP32RegisterClass; - } - break; - case MVT::f64: - if (Subtarget->hasSSE2()) { - Opc = X86::MOVSDrm; - RC = X86::FR64RegisterClass; - } else { - Opc = X86::LD_Fp64m; - RC = X86::RFP64RegisterClass; - } - break; - case MVT::f80: - Opc = X86::LD_Fp80m; - RC = X86::RFP80RegisterClass; - break; + unsigned ResultReg = 0; + if (X86FastEmitLoad(VT, Op0, V, ResultReg)) { + UpdateValueMap(I, ResultReg); + return true; } - - unsigned ResultReg = createResultReg(RC); - X86AddressMode AM; - if (Op0) - // Address is in register. - AM.Base.Reg = Op0; - else - AM.GV = cast(V); - addFullAddress(BuildMI(MBB, TII.get(Opc), ResultReg), AM); - UpdateValueMap(I, ResultReg); - return true; + return false; } bool X86FastISel::X86SelectCmp(Instruction *I) { @@ -621,10 +647,11 @@ unsigned X86FastISel::TargetMaterializeConstant(Constant *C, unsigned ResultReg = createResultReg(RC); if (isa(C)) { + // FIXME: If store value type is something we can't handle, this can result + // in a dead stub load instruction. if (X86SelectConstAddr(C, ResultReg)) return ResultReg; - else - return 0; + return 0; }