//===----------------------------------------------------------------------===//
#include "X86.h"
+#include "X86InstrBuilder.h"
+#include "X86RegisterInfo.h"
#include "X86Subtarget.h"
#include "X86ISelLowering.h"
#include "llvm/GlobalValue.h"
+#include "llvm/Instructions.h"
+#include "llvm/Support/CFG.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/Statistic.h"
-#include <set>
using namespace llvm;
//===----------------------------------------------------------------------===//
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
virtual void InstructionSelectBasicBlock(SelectionDAG &DAG);
+ virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF);
+
// Include the pieces autogenerated from the target description.
#include "X86GenDAGISel.inc"
private:
SDOperand Select(SDOperand N);
- bool isFoldableLoad(SDOperand Op, SDOperand OtherOp,
- bool FloatPromoteOk = false);
bool MatchAddress(SDOperand N, X86ISelAddressMode &AM);
bool SelectAddr(SDOperand N, SDOperand &Base, SDOperand &Scale,
SDOperand &Index, SDOperand &Disp);
bool SelectLEAAddr(SDOperand N, SDOperand &Base, SDOperand &Scale,
SDOperand &Index, SDOperand &Disp);
+ bool TryFoldLoad(SDOperand N, SDOperand &Base, SDOperand &Scale,
+ SDOperand &Index, SDOperand &Disp);
inline void getAddressOperands(X86ISelAddressMode &AM, SDOperand &Base,
SDOperand &Scale, SDOperand &Index,
SDOperand &Disp) {
Base = (AM.BaseType == X86ISelAddressMode::FrameIndexBase) ?
CurDAG->getTargetFrameIndex(AM.Base.FrameIndex, MVT::i32) : AM.Base.Reg;
- Scale = getI8Imm (AM.Scale);
+ Scale = getI8Imm(AM.Scale);
Index = AM.IndexReg;
Disp = AM.GV ? CurDAG->getTargetGlobalAddress(AM.GV, MVT::i32, AM.Disp)
: getI32Imm(AM.Disp);
/// when it has created a SelectionDAG for us to codegen.
void X86DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
DEBUG(BB->dump());
+ MachineFunction::iterator FirstMBB = BB;
// Codegen the basic block.
DAG.setRoot(Select(DAG.getRoot()));
+ CodeGenMap.clear();
DAG.RemoveDeadNodes();
// Emit machine code to BB.
ScheduleAndEmitDAG(DAG);
+
+ // If we are emitting FP stack code, scan the basic block to determine if this
+ // block defines any FP values. If so, put an FP_REG_KILL instruction before
+ // the terminator of the block.
+ if (X86Vector < SSE2) {
+ // Note that FP stack instructions *are* used in SSE code when returning
+ // values, but these are not live out of the basic block, so we don't need
+ // an FP_REG_KILL in this case either.
+ bool ContainsFPCode = false;
+
+ // Scan all of the machine instructions in these MBBs, checking for FP
+ // stores.
+ MachineFunction::iterator MBBI = FirstMBB;
+ do {
+ for (MachineBasicBlock::iterator I = MBBI->begin(), E = MBBI->end();
+ !ContainsFPCode && I != E; ++I) {
+ for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op) {
+ if (I->getOperand(op).isRegister() && I->getOperand(op).isDef() &&
+ MRegisterInfo::isVirtualRegister(I->getOperand(op).getReg()) &&
+ RegMap->getRegClass(I->getOperand(0).getReg()) ==
+ X86::RFPRegisterClass) {
+ ContainsFPCode = true;
+ break;
+ }
+ }
+ }
+ } while (!ContainsFPCode && &*(MBBI++) != BB);
+
+ // Check PHI nodes in successor blocks. These PHI's will be lowered to have
+ // a copy of the input value in this block.
+ if (!ContainsFPCode) {
+ // Final check, check LLVM BB's that are successors to the LLVM BB
+ // corresponding to BB for FP PHI nodes.
+ const BasicBlock *LLVMBB = BB->getBasicBlock();
+ const PHINode *PN;
+ for (succ_const_iterator SI = succ_begin(LLVMBB), E = succ_end(LLVMBB);
+ !ContainsFPCode && SI != E; ++SI) {
+ for (BasicBlock::const_iterator II = SI->begin();
+ (PN = dyn_cast<PHINode>(II)); ++II) {
+ if (PN->getType()->isFloatingPoint()) {
+ ContainsFPCode = true;
+ break;
+ }
+ }
+ }
+ }
+
+ // Finally, if we found any FP code, emit the FP_REG_KILL instruction.
+ if (ContainsFPCode) {
+ BuildMI(*BB, BB->getFirstTerminator(), X86::FP_REG_KILL, 0);
+ ++NumFPKill;
+ }
+ }
+}
+
+/// EmitSpecialCodeForMain - Emit any code that needs to be executed only in
+/// the main function.
+static void EmitSpecialCodeForMain(MachineBasicBlock *BB,
+ MachineFrameInfo *MFI) {
+ // Switch the FPU to 64-bit precision mode for better compatibility and speed.
+ int CWFrameIdx = MFI->CreateStackObject(2, 2);
+ addFrameReference(BuildMI(BB, X86::FNSTCW16m, 4), CWFrameIdx);
+
+ // Set the high part to be 64-bit precision.
+ addFrameReference(BuildMI(BB, X86::MOV8mi, 5),
+ CWFrameIdx, 1).addImm(2);
+
+ // Reload the modified control word now.
+ addFrameReference(BuildMI(BB, X86::FLDCW16m, 4), CWFrameIdx);
+}
+
+void X86DAGToDAGISel::EmitFunctionEntryCode(Function &Fn, MachineFunction &MF) {
+ // If this is main, emit special code for main.
+ MachineBasicBlock *BB = MF.begin();
+ if (Fn.hasExternalLinkage() && Fn.getName() == "main")
+ EmitSpecialCodeForMain(BB, MF.getFrameInfo());
}
-/// FIXME: copied from X86ISelPattern.cpp
/// MatchAddress - Add the specified node to the specified addressing mode,
/// returning true if it cannot be done. This just pattern matches for the
/// addressing mode
break;
case ISD::GlobalAddress:
+ case ISD::TargetGlobalAddress:
if (AM.GV == 0) {
- GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal();
- // For Darwin, external and weak symbols are indirect, so we want to load
- // the value at address GV, not the value of GV itself. This means that
- // the GlobalAddress must be in the base or index register of the address,
- // not the GV offset field.
- if (Subtarget->getIndirectExternAndWeakGlobals() &&
- (GV->hasWeakLinkage() || GV->isExternal())) {
- break;
- } else {
- AM.GV = GV;
- return false;
- }
+ AM.GV = cast<GlobalAddressSDNode>(N)->getGlobal();
+ return false;
}
break;
bool X86DAGToDAGISel::SelectAddr(SDOperand N, SDOperand &Base, SDOperand &Scale,
SDOperand &Index, SDOperand &Disp) {
X86ISelAddressMode AM;
- if (!MatchAddress(N, AM)) {
- if (AM.BaseType == X86ISelAddressMode::RegBase) {
- if (AM.Base.Reg.Val)
+ if (MatchAddress(N, AM))
+ return false;
+
+ if (AM.BaseType == X86ISelAddressMode::RegBase) {
+ if (AM.Base.Reg.Val) {
+ if (AM.Base.Reg.getOpcode() != ISD::Register)
AM.Base.Reg = Select(AM.Base.Reg);
- else
- AM.Base.Reg = CurDAG->getRegister(0, MVT::i32);
+ } else {
+ AM.Base.Reg = CurDAG->getRegister(0, MVT::i32);
}
- if (AM.IndexReg.Val)
- AM.IndexReg = Select(AM.IndexReg);
- else
- AM.IndexReg = CurDAG->getRegister(0, MVT::i32);
-
- getAddressOperands(AM, Base, Scale, Index, Disp);
- return true;
}
+
+ if (AM.IndexReg.Val)
+ AM.IndexReg = Select(AM.IndexReg);
+ else
+ AM.IndexReg = CurDAG->getRegister(0, MVT::i32);
+
+ getAddressOperands(AM, Base, Scale, Index, Disp);
+ return true;
+}
+
+bool X86DAGToDAGISel::TryFoldLoad(SDOperand N, SDOperand &Base,
+ SDOperand &Scale, SDOperand &Index,
+ SDOperand &Disp) {
+ if (N.getOpcode() == ISD::LOAD && N.hasOneUse() &&
+ CodeGenMap.count(N.getValue(1)) == 0)
+ return SelectAddr(N.getOperand(1), Base, Scale, Index, Disp);
return false;
}
-static bool isRegister0(SDOperand Op)
-{
+static bool isRegister0(SDOperand Op) {
if (RegisterSDNode *R = dyn_cast<RegisterSDNode>(Op))
return (R->getReg() == 0);
return false;
/// SelectLEAAddr - it calls SelectAddr and determines if the maximal addressing
/// mode it matches can be cost effectively emitted as an LEA instruction.
/// For X86, it always is unless it's just a (Reg + const).
-bool X86DAGToDAGISel::SelectLEAAddr(SDOperand N, SDOperand &Base, SDOperand &Scale,
+bool X86DAGToDAGISel::SelectLEAAddr(SDOperand N, SDOperand &Base,
+ SDOperand &Scale,
SDOperand &Index, SDOperand &Disp) {
X86ISelAddressMode AM;
if (!MatchAddress(N, AM)) {
return false;
}
-/// NodeTransitivelyUsesValue - Return true if N or any of its uses uses Op.
-/// The DAG cannot have cycles in it, by definition, so the visited set is not
-/// needed to prevent infinite loops. The DAG CAN, however, have unbounded
-/// reuse, so it prevents exponential cases.
-///
-static bool NodeTransitivelyUsesValue(SDOperand N, SDOperand Op,
- std::set<SDNode*> &Visited) {
- if (N == Op) return true; // Found it.
- SDNode *Node = N.Val;
- if (Node->getNumOperands() == 0 || // Leaf?
- Node->getNodeDepth() <= Op.getNodeDepth()) return false; // Can't find it?
- if (!Visited.insert(Node).second) return false; // Already visited?
-
- // Recurse for the first N-1 operands.
- for (unsigned i = 1, e = Node->getNumOperands(); i != e; ++i)
- if (NodeTransitivelyUsesValue(Node->getOperand(i), Op, Visited))
- return true;
-
- // Tail recurse for the last operand.
- return NodeTransitivelyUsesValue(Node->getOperand(0), Op, Visited);
-}
-
-/// isFoldableLoad - Return true if this is a load instruction that can safely
-/// be folded into an operation that uses it.
-bool X86DAGToDAGISel::isFoldableLoad(SDOperand Op, SDOperand OtherOp,
- bool FloatPromoteOk) {
- if (Op.getOpcode() == ISD::LOAD) {
- // FIXME: currently can't fold constant pool indexes.
- if (isa<ConstantPoolSDNode>(Op.getOperand(1)))
- return false;
- } else if (FloatPromoteOk && Op.getOpcode() == ISD::EXTLOAD &&
- cast<VTSDNode>(Op.getOperand(3))->getVT() == MVT::f32) {
- // FIXME: currently can't fold constant pool indexes.
- if (isa<ConstantPoolSDNode>(Op.getOperand(1)))
- return false;
- } else {
- return false;
- }
-
- // If this load has already been emitted, we clearly can't fold it.
- assert(Op.ResNo == 0 && "Not a use of the value of the load?");
- if (CodeGenMap.count(Op.getValue(1))) return false;
- assert(!CodeGenMap.count(Op.getValue(0)) &&
- "Value in map but not token chain?");
- assert(!CodeGenMap.count(Op.getValue(1)) &&
- "Token lowered but value not in map?");
-
- // If there is not just one use of its value, we cannot fold.
- if (!Op.Val->hasNUsesOfValue(1, 0)) return false;
-
- // Finally, we cannot fold the load into the operation if this would induce a
- // cycle into the resultant dag. To check for this, see if OtherOp (the other
- // operand of the operation we are folding the load into) can possible use the
- // chain node defined by the load.
- if (OtherOp.Val && !Op.Val->hasNUsesOfValue(0, 1)) { // Has uses of chain?
- std::set<SDNode*> Visited;
- if (NodeTransitivelyUsesValue(OtherOp, Op.getValue(1), Visited))
- return false;
- }
- return true;
-}
-
SDOperand X86DAGToDAGISel::Select(SDOperand N) {
SDNode *Node = N.Val;
MVT::ValueType NVT = Node->getValueType(0);
- unsigned Opc;
+ unsigned Opc, MOpc;
+ unsigned Opcode = Node->getOpcode();
- if (Node->getOpcode() >= ISD::BUILTIN_OP_END)
+ if (Opcode >= ISD::BUILTIN_OP_END && Opcode < X86ISD::FIRST_NUMBER)
return N; // Already selected.
+
+ std::map<SDOperand, SDOperand>::iterator CGMI = CodeGenMap.find(N);
+ if (CGMI != CodeGenMap.end()) return CGMI->second;
- switch (Node->getOpcode()) {
+ switch (Opcode) {
default: break;
+ case ISD::MULHU:
+ case ISD::MULHS: {
+ if (Opcode == ISD::MULHU)
+ switch (NVT) {
+ default: assert(0 && "Unsupported VT!");
+ case MVT::i8: Opc = X86::MUL8r; MOpc = X86::MUL8m; break;
+ case MVT::i16: Opc = X86::MUL16r; MOpc = X86::MUL16m; break;
+ case MVT::i32: Opc = X86::MUL32r; MOpc = X86::MUL32m; break;
+ }
+ else
+ switch (NVT) {
+ default: assert(0 && "Unsupported VT!");
+ case MVT::i8: Opc = X86::IMUL8r; MOpc = X86::IMUL8m; break;
+ case MVT::i16: Opc = X86::IMUL16r; MOpc = X86::IMUL16m; break;
+ case MVT::i32: Opc = X86::IMUL32r; MOpc = X86::IMUL32m; break;
+ }
- case ISD::SHL:
- if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Node->getOperand(1))) {
- if (CN->getValue() == 1) {
- // X = SHL Y, 1 -> X = ADD Y, Y
- switch (NVT) {
- default: assert(0 && "Cannot shift this type!");
- case MVT::i8: Opc = X86::ADD8rr; break;
- case MVT::i16: Opc = X86::ADD16rr; break;
- case MVT::i32: Opc = X86::ADD32rr; break;
- }
- SDOperand Tmp0 = Select(Node->getOperand(0));
- if (Node->hasOneUse())
- return CurDAG->SelectNodeTo(Node, Opc, NVT, Tmp0, Tmp0);
- else
- return CodeGenMap[N] =
- CurDAG->getTargetNode(Opc, NVT, Tmp0, Tmp0);
+ unsigned LoReg, HiReg;
+ switch (NVT) {
+ default: assert(0 && "Unsupported VT!");
+ case MVT::i8: LoReg = X86::AL; HiReg = X86::AH; break;
+ case MVT::i16: LoReg = X86::AX; HiReg = X86::DX; break;
+ case MVT::i32: LoReg = X86::EAX; HiReg = X86::EDX; break;
+ }
+
+ SDOperand N0 = Node->getOperand(0);
+ SDOperand N1 = Node->getOperand(1);
+
+ bool foldedLoad = false;
+ SDOperand Tmp0, Tmp1, Tmp2, Tmp3;
+ foldedLoad = TryFoldLoad(N1, Tmp0, Tmp1, Tmp2, Tmp3);
+ // MULHU and MULHS are commmutative
+ if (!foldedLoad) {
+ foldedLoad = TryFoldLoad(N0, Tmp0, Tmp1, Tmp2, Tmp3);
+ if (foldedLoad) {
+ N0 = Node->getOperand(1);
+ N1 = Node->getOperand(0);
}
}
- break;
- case ISD::ANY_EXTEND: // treat any extend like zext
- case ISD::ZERO_EXTEND: {
- SDOperand N0 = N.getOperand(0);
- if (N0.getValueType() == MVT::i1) {
- // FIXME: This hack is here for zero extension casts from bool to i8.
- // This would not be needed if bools were promoted by Legalize.
- if (NVT == MVT::i8) {
- Opc = X86::MOV8rr;
- } else if (!isFoldableLoad(N0, SDOperand())) {
- switch (NVT) {
- default: assert(0 && "Cannot zero extend to this type!");
- case MVT::i16: Opc = X86::MOVZX16rr8; break;
- case MVT::i32: Opc = X86::MOVZX32rr8; break;
- }
- } else {
- switch (NVT) {
- default: assert(0 && "Cannot zero extend to this type!");
- case MVT::i16: Opc = X86::MOVZX16rm8; break;
- case MVT::i32: Opc = X86::MOVZX32rm8; break;
- }
+ SDOperand Chain = foldedLoad ? Select(N1.getOperand(0))
+ : CurDAG->getEntryNode();
- SDOperand Chain = Select(N0.getOperand(0));
- SDOperand Base, Scale, Index, Disp;
- (void) SelectAddr(N0.getOperand(1), Base, Scale, Index, Disp);
- SDOperand Result = CurDAG->getTargetNode(Opc, NVT,
- MVT::Other, Base, Scale,
- Index, Disp, Chain);
- CodeGenMap[N.getValue(0)] = Result;
- Chain = CodeGenMap[N.getValue(1)] = Result.getValue(1);
- return (N.ResNo) ? Chain : Result.getValue(0);
- }
+ SDOperand InFlag;
+ Chain = CurDAG->getCopyToReg(Chain, CurDAG->getRegister(LoReg, NVT),
+ Select(N0), InFlag);
+ InFlag = Chain.getValue(1);
- SDOperand Tmp0 = Select(Node->getOperand(0));
- if (Node->hasOneUse())
- return CurDAG->SelectNodeTo(Node, Opc, NVT, Tmp0);
- else
- return CodeGenMap[N] = CurDAG->getTargetNode(Opc, NVT, Tmp0);
+ if (foldedLoad) {
+ Chain = CurDAG->getTargetNode(MOpc, MVT::Other, MVT::Flag, Tmp0, Tmp1,
+ Tmp2, Tmp3, Chain, InFlag);
+ InFlag = Chain.getValue(1);
+ } else {
+ InFlag = CurDAG->getTargetNode(Opc, MVT::Flag, Select(N1), InFlag);
}
- // Other cases are autogenerated.
- break;
+
+ SDOperand Result = CurDAG->getCopyFromReg(Chain, HiReg, NVT, InFlag);
+ CodeGenMap[N.getValue(0)] = Result;
+ if (foldedLoad)
+ CodeGenMap[N1.getValue(1)] = Result.getValue(1);
+ return Result;
}
- case ISD::RET: {
- SDOperand Chain = Node->getOperand(0); // Token chain.
- unsigned NumOps = Node->getNumOperands();
-
- // Note: A bit of a hack / optimization... Try to delay chain selection
- // as much as possible. So it's more likely it has already been selected
- // for a real use.
- switch (NumOps) {
- default:
- assert(0 && "Unknown return instruction!");
- case 3:
- Chain = Select(Chain);
- assert(0 && "Not yet handled return instruction!");
- break;
- case 2: {
- SDOperand Val = Select(Node->getOperand(1));
- Chain = Select(Chain);
- switch (Node->getOperand(1).getValueType()) {
- default:
- assert(0 && "All other types should have been promoted!!");
- case MVT::i32:
- Chain = CurDAG->getCopyToReg(Chain, X86::EAX, Val);
- break;
- case MVT::f32:
- case MVT::f64:
- assert(0 && "Not yet handled return instruction!");
- break;
- }
+ case ISD::SDIV:
+ case ISD::UDIV:
+ case ISD::SREM:
+ case ISD::UREM: {
+ bool isSigned = Opcode == ISD::SDIV || Opcode == ISD::SREM;
+ bool isDiv = Opcode == ISD::SDIV || Opcode == ISD::UDIV;
+ if (!isSigned)
+ switch (NVT) {
+ default: assert(0 && "Unsupported VT!");
+ case MVT::i8: Opc = X86::DIV8r; MOpc = X86::DIV8m; break;
+ case MVT::i16: Opc = X86::DIV16r; MOpc = X86::DIV16m; break;
+ case MVT::i32: Opc = X86::DIV32r; MOpc = X86::DIV32m; break;
+ }
+ else
+ switch (NVT) {
+ default: assert(0 && "Unsupported VT!");
+ case MVT::i8: Opc = X86::IDIV8r; MOpc = X86::IDIV8m; break;
+ case MVT::i16: Opc = X86::IDIV16r; MOpc = X86::IDIV16m; break;
+ case MVT::i32: Opc = X86::IDIV32r; MOpc = X86::IDIV32m; break;
}
- case 1:
- Chain = Select(Chain);
- break;
+
+ unsigned LoReg, HiReg;
+ unsigned ClrOpcode, SExtOpcode;
+ switch (NVT) {
+ default: assert(0 && "Unsupported VT!");
+ case MVT::i8:
+ LoReg = X86::AL; HiReg = X86::AH;
+ ClrOpcode = X86::MOV8ri;
+ SExtOpcode = X86::CBW;
+ break;
+ case MVT::i16:
+ LoReg = X86::AX; HiReg = X86::DX;
+ ClrOpcode = X86::MOV16ri;
+ SExtOpcode = X86::CWD;
+ break;
+ case MVT::i32:
+ LoReg = X86::EAX; HiReg = X86::EDX;
+ ClrOpcode = X86::MOV32ri;
+ SExtOpcode = X86::CDQ;
+ break;
}
- if (X86Lowering.getBytesToPopOnReturn() == 0)
- return CurDAG->SelectNodeTo(Node, X86::RET, MVT::Other, Chain);
+
+ SDOperand N0 = Node->getOperand(0);
+ SDOperand N1 = Node->getOperand(1);
+
+ bool foldedLoad = false;
+ SDOperand Tmp0, Tmp1, Tmp2, Tmp3;
+ foldedLoad = TryFoldLoad(N1, Tmp0, Tmp1, Tmp2, Tmp3);
+ SDOperand Chain = foldedLoad ? Select(N1.getOperand(0))
+ : CurDAG->getEntryNode();
+
+ SDOperand InFlag;
+ Chain = CurDAG->getCopyToReg(Chain, CurDAG->getRegister(LoReg, NVT),
+ Select(N0), InFlag);
+ InFlag = Chain.getValue(1);
+
+ if (isSigned) {
+ // Sign extend the low part into the high part.
+ InFlag = CurDAG->getTargetNode(SExtOpcode, MVT::Flag, InFlag);
+ } else {
+ // Zero out the high part, effectively zero extending the input.
+ SDOperand ClrNode =
+ CurDAG->getTargetNode(ClrOpcode, NVT,
+ CurDAG->getTargetConstant(0, NVT));
+ Chain = CurDAG->getCopyToReg(Chain, CurDAG->getRegister(HiReg, NVT),
+ ClrNode, InFlag);
+ InFlag = Chain.getValue(1);
+ }
+
+ if (foldedLoad) {
+ Chain = CurDAG->getTargetNode(MOpc, MVT::Other, MVT::Flag, Tmp0, Tmp1,
+ Tmp2, Tmp3, Chain, InFlag);
+ InFlag = Chain.getValue(1);
+ } else {
+ InFlag = CurDAG->getTargetNode(Opc, MVT::Flag, Select(N1), InFlag);
+ }
+
+ SDOperand Result = CurDAG->getCopyFromReg(Chain, isDiv ? LoReg : HiReg,
+ NVT, InFlag);
+ CodeGenMap[N.getValue(0)] = Result;
+ if (foldedLoad)
+ CodeGenMap[N1.getValue(1)] = Result.getValue(1);
+ return Result;
+ }
+
+ case ISD::TRUNCATE: {
+ unsigned Reg;
+ MVT::ValueType VT;
+ switch (Node->getOperand(0).getValueType()) {
+ default: assert(0 && "Unknown truncate!");
+ case MVT::i16: Reg = X86::AX; Opc = X86::MOV16rr; VT = MVT::i16; break;
+ case MVT::i32: Reg = X86::EAX; Opc = X86::MOV32rr; VT = MVT::i32; break;
+ }
+ SDOperand Tmp0 = Select(Node->getOperand(0));
+ SDOperand Tmp1 = CurDAG->getTargetNode(Opc, VT, Tmp0);
+ SDOperand InFlag = SDOperand(0,0);
+ SDOperand Result = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
+ Reg, Tmp1, InFlag);
+ SDOperand Chain = Result.getValue(0);
+ InFlag = Result.getValue(1);
+
+ switch (NVT) {
+ default: assert(0 && "Unknown truncate!");
+ case MVT::i8: Reg = X86::AL; Opc = X86::MOV8rr; VT = MVT::i8; break;
+ case MVT::i16: Reg = X86::AX; Opc = X86::MOV16rr; VT = MVT::i16; break;
+ }
+
+ Result = CurDAG->getCopyFromReg(Chain,
+ Reg, VT, InFlag);
+ if (N.Val->hasOneUse())
+ return CurDAG->SelectNodeTo(N.Val, Opc, VT, Result);
else
- return CurDAG->SelectNodeTo(Node, X86::RET, MVT::Other,
- getI16Imm(X86Lowering.getBytesToPopOnReturn()),
- Chain);
+ return CodeGenMap[N] = CurDAG->getTargetNode(Opc, VT, Result);
+ break;
}
}