* Added lowering hook for external weak global address. It inserts a load

for Darwin.
* Added lowering hook for ISD::RET. It inserts CopyToRegs for the return
  value (or store / fld / copy to ST(0) for floating point value). This
  eliminate the need to write C++ code to handle RET with variable number
  of operands.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24888 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2005-12-21 02:39:21 +00:00
parent 8de324b59c
commit b077b842b6
5 changed files with 135 additions and 22 deletions

View File

@ -173,22 +173,7 @@ bool X86DAGToDAGISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM) {
case ISD::GlobalAddress:
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())) {
AM.Base.Reg =
CurDAG->getTargetNode(X86::MOV32rm, MVT::i32, MVT::Other,
CurDAG->getRegister(0, MVT::i32),
getI8Imm(1), CurDAG->getRegister(0, MVT::i32),
CurDAG->getTargetGlobalAddress(GV, MVT::i32),
CurDAG->getEntryNode());
} else {
AM.GV = GV;
}
AM.GV = cast<GlobalAddressSDNode>(N)->getGlobal();
return false;
}
break;

View File

@ -197,6 +197,68 @@ X86TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
return LowerCCCCallTo(Chain, RetTy, isVarArg, isTailCall, Callee, Args, DAG);
}
SDOperand X86TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op,
SelectionDAG &DAG) {
if (!X86DAGIsel)
return DAG.getNode(ISD::RET, MVT::Other, Chain, Op);
SDOperand Copy;
MVT::ValueType OpVT = Op.getValueType();
switch (OpVT) {
default: assert(0 && "Unknown type to return!");
case MVT::i32:
Copy = DAG.getCopyToReg(Chain, X86::EAX, Op, SDOperand());
break;
case MVT::i64: {
SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op,
DAG.getConstant(1, MVT::i32));
SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op,
DAG.getConstant(0, MVT::i32));
Copy = DAG.getCopyToReg(Chain, X86::EAX, Hi, SDOperand());
Copy = DAG.getCopyToReg(Copy, X86::EDX, Lo, Copy.getValue(1));
break;
}
case MVT::f32:
assert(X86ScalarSSE && "MVT::f32 only legal with scalar sse fp");
// Fallthrough intended
case MVT::f64:
if (!X86ScalarSSE) {
std::vector<MVT::ValueType> Tys;
Tys.push_back(MVT::Other);
Tys.push_back(MVT::Flag);
std::vector<SDOperand> Ops;
Ops.push_back(Chain);
Ops.push_back(Op);
Copy = DAG.getNode(X86ISD::FP_SET_RESULT, Tys, Ops);
} else {
// Spill the value to memory and reload it into top of stack.
unsigned Size = MVT::getSizeInBits(OpVT)/8;
MachineFunction &MF = DAG.getMachineFunction();
int SSFI = MF.getFrameInfo()->CreateStackObject(Size, Size);
SDOperand StackSlot = DAG.getFrameIndex(SSFI, getPointerTy());
Chain = DAG.getNode(ISD::STORE, MVT::Other, Chain, Op,
StackSlot, DAG.getSrcValue(NULL));
std::vector<MVT::ValueType> Tys;
Tys.push_back(MVT::f64);
Tys.push_back(MVT::Other);
std::vector<SDOperand> Ops;
Ops.push_back(Chain);
Ops.push_back(StackSlot);
Ops.push_back(DAG.getValueType(OpVT));
Copy = DAG.getNode(X86ISD::FLD, Tys, Ops);
Tys.clear();
Tys.push_back(MVT::Other);
Tys.push_back(MVT::Flag);
Ops.clear();
Ops.push_back(Copy.getValue(1));
Ops.push_back(Copy);
Copy = DAG.getNode(X86ISD::FP_SET_RESULT, Tys, Ops);
}
break;
}
return DAG.getNode(X86ISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1));
}
//===----------------------------------------------------------------------===//
// C Calling Convention implementation
//===----------------------------------------------------------------------===//
@ -968,6 +1030,20 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
return DAG.getNode(X86ISD::BRCOND, Op.getValueType(),
Op.getOperand(0), Op.getOperand(2), CC, Cond);
}
case ISD::GlobalAddress:
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->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 (getTargetMachine().
getSubtarget<X86Subtarget>().getIndirectExternAndWeakGlobals() &&
(GV->hasWeakLinkage() || GV->isExternal()))
return DAG.getLoad(MVT::i32, DAG.getEntryNode(), Op,
DAG.getSrcValue(NULL));
else
return Op;
break;
}
}
@ -978,6 +1054,8 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
case X86ISD::FP_TO_INT16_IN_MEM: return "X86ISD::FP_TO_INT16_IN_MEM";
case X86ISD::FP_TO_INT32_IN_MEM: return "X86ISD::FP_TO_INT32_IN_MEM";
case X86ISD::FP_TO_INT64_IN_MEM: return "X86ISD::FP_TO_INT64_IN_MEM";
case X86ISD::FLD: return "X86ISD::FLD";
case X86ISD::FP_SET_RESULT: return "X86ISD::FP_SET_RESULT";
case X86ISD::CALL: return "X86ISD::CALL";
case X86ISD::TAILCALL: return "X86ISD::TAILCALL";
case X86ISD::RDTSC_DAG: return "X86ISD::RDTSC_DAG";
@ -985,5 +1063,6 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
case X86ISD::TEST: return "X86ISD::TEST";
case X86ISD::CMOV: return "X86ISD::CMOV";
case X86ISD::BRCOND: return "X86ISD::BRCOND";
case X86ISD::RET_FLAG: return "X86ISD::RET_FLAG";
}
}

View File

@ -40,6 +40,17 @@ namespace llvm {
FP_TO_INT32_IN_MEM,
FP_TO_INT64_IN_MEM,
/// FLD - This instruction implements an extending load to FP stack slots.
/// This corresponds to the X86::FLD32m / X86::FLD64m. It takes a chain
/// operand, ptr to load from, and a VALUETYPE node indicating the type
/// to load.
FLD,
/// FP_SET_RESULT - This corresponds to FpSETRESULT pseudo instrcuction
/// which copies the source operand to ST(0). It takes a chain and writes
/// a chain and a flag.
FP_SET_RESULT,
/// CALL/TAILCALL - These operations represent an abstract X86 call
/// instruction, which includes a bunch of information. In particular the
/// operands of these node are:
@ -75,6 +86,9 @@ namespace llvm {
/// X86 conditional branches.
BRCOND,
// Return with a flag operand.
RET_FLAG,
};
}
@ -113,6 +127,9 @@ namespace llvm {
bool isTailCall, SDOperand Callee, ArgListTy &Args,
SelectionDAG &DAG);
virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op,
SelectionDAG &DAG);
virtual SDOperand LowerVAStart(SDOperand Chain, SDOperand VAListP,
Value *VAListV, SelectionDAG &DAG);
virtual std::pair<SDOperand,SDOperand>

View File

@ -28,12 +28,26 @@ def SDTX86BrCond : SDTypeProfile<0, 3,
[SDTCisVT<0, OtherVT>,
SDTCisVT<1, OtherVT>, SDTCisVT<2, FlagVT>]>;
def SDTX86RetFlag : SDTypeProfile<0, 1, [SDTCisVT<0, FlagVT>]>;
def SDTX86Fld : SDTypeProfile<1, 2, [SDTCisFP<0>,
SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>]>;
def SDTX86FpSet : SDTypeProfile<0, 1, [SDTCisFP<0>]>;
def X86cmp : SDNode<"X86ISD::CMP" , SDTX86CmpTest, []>;
def X86test : SDNode<"X86ISD::TEST", SDTX86CmpTest, []>;
def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov, []>;
def X86Brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond, [SDNPHasChain]>;
def X86retflag: SDNode<"X86ISD::RET_FLAG", SDTX86RetFlag, [SDNPHasChain]>;
def X86fld : SDNode<"X86ISD::FLD", SDTX86Fld, [SDNPHasChain]>;
def X86fpset : SDNode<"X86ISD::FP_SET_RESULT",
SDTX86FpSet, [SDNPHasChain]>;
//===----------------------------------------------------------------------===//
// X86 Operand Definitions.
//
@ -274,6 +288,8 @@ let isTerminator = 1, isReturn = 1, isBarrier = 1 in
let isTerminator = 1, isReturn = 1, isBarrier = 1 in
def RETI : Ii16<0xC2, RawFrm, (ops i16imm:$amt), "ret $amt", []>;
def : Pat<(X86retflag FLAG), (RET)>;
// All branches are RawFrm, Void, Branch, and Terminators
let isBranch = 1, isTerminator = 1 in
class IBr<bits<8> opcode, dag ops, string asm, list<dag> pattern> :
@ -2188,10 +2204,21 @@ def FpDIV : FPI<0, Pseudo, TwoArgFP ,
(ops RFP:$dst, RFP:$src1, RFP:$src2), "",
[]>; // f1 = fdiv f2, f3
def FpLD32m : FPI<0xD9, MRM0m, ZeroArgFP,
(ops RFP:$dst, f32mem:$src),
"fld{s} $src",
[(set RFP:$dst, (X86fld addr:$src, f32))]>;
def FpLD64m : FPI<0xDD, MRM0m, ZeroArgFP,
(ops RFP:$dst, f64mem:$src),
"fld{l} $src",
[(set RFP:$dst, (X86fld addr:$src, f64))]>;
def FpGETRESULT : FPI<0, Pseudo, SpecialFP, (ops RFP:$dst), "", []>,
Imp<[ST0], []>; // FPR = ST(0)
def FpSETRESULT : FPI<0, Pseudo, SpecialFP, (ops RFP:$src), "", []>,
def FpSETRESULT : FPI<0, Pseudo, SpecialFP, (ops RFP:$src), "",
[(X86fpset RFP:$src)]>,
Imp<[], [ST0]>; // ST(0) = FPR
// FADD reg, mem: Before stackification, these are represented by:

View File

@ -142,6 +142,11 @@ def RST : RegisterClass<"X86", [f64], 32,
}];
}
def FLAGS_REGS : RegisterClass<"X86", [FlagVT], 32, [STATUS]> {
// FIXME:
// HACKTROCITY: define a flags reg class for things that need to take a flag.
// this should really be handled by tablgen.
let Namespace = "X86" in
def FLAG : Register<"FLAG">;
def FLAGS_REGS : RegisterClass<"X86", [FlagVT], 32, [STATUS, FLAG]> {
let Size = 32;
}