aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNate Begeman <natebegeman@mac.com>2005-04-01 22:34:39 +0000
committerNate Begeman <natebegeman@mac.com>2005-04-01 22:34:39 +0000
commitfc1b1dad88a256ab5ab16dd548ad82df8efa2ca9 (patch)
treebff323ec69fda509212bf7337184b3cb8055ce78
parente6fea166c312931d01f9850754f0a9f8e9f60571 (diff)
Add ISD::UNDEF node
Teach the SelectionDAG code how to expand and promote it Have PPC32 LowerCallTo generate ISD::UNDEF for int arg regs used up by fp arguments, but not shadowing their value. This allows us to do the right thing with both fixed and vararg floating point arguments. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@20988 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h3
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeDAG.cpp24
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp1
-rw-r--r--lib/Target/PowerPC/PPCISelPattern.cpp108
4 files changed, 95 insertions, 41 deletions
diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h
index 67ceda1161..e9b54fb92c 100644
--- a/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -74,6 +74,9 @@ namespace ISD {
// out.
ImplicitDef,
+ // UNDEF - An undefined node
+ UNDEF,
+
// EXTRACT_ELEMENT - This is used to get the first or second (determined by
// a Constant, which is required to be operand #1), element of the aggregate
// value specified as operand #0. This is only for use before legalization,
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 5f8a21aca0..52449ef376 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -219,6 +219,23 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
if (Tmp1 != Node->getOperand(0))
Result = DAG.getImplicitDef(Tmp1, cast<RegSDNode>(Node)->getReg());
break;
+ case ISD::UNDEF: {
+ MVT::ValueType VT = Op.getValueType();
+ switch (TLI.getOperationAction(ISD::UNDEF, VT)) {
+ case Expand:
+ case Promote:
+ if (MVT::isInteger(VT))
+ Result = DAG.getConstant(0, VT);
+ else if (MVT::isFloatingPoint(VT))
+ Result = DAG.getConstantFP(0, VT);
+ else
+ assert(0 && "Unknown value type!");
+ break;
+ case Legal:
+ break;
+ }
+ break;
+ }
case ISD::Constant:
// We know we don't need to expand constants here, constants only have one
// value and we check that it is fine above.
@@ -1018,6 +1035,9 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) {
std::cerr << "NODE: "; Node->dump(); std::cerr << "\n";
assert(0 && "Do not know how to promote this operator!");
abort();
+ case ISD::UNDEF:
+ Result = DAG.getNode(ISD::UNDEF, NVT);
+ break;
case ISD::Constant:
Result = DAG.getNode(ISD::ZERO_EXTEND, NVT, Op);
assert(isa<ConstantSDNode>(Result) && "Didn't constant fold zext?");
@@ -1574,6 +1594,10 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
std::cerr << "NODE: "; Node->dump(); std::cerr << "\n";
assert(0 && "Do not know how to expand this operator!");
abort();
+ case ISD::UNDEF:
+ Lo = DAG.getNode(ISD::UNDEF, NVT);
+ Hi = DAG.getNode(ISD::UNDEF, NVT);
+ break;
case ISD::Constant: {
uint64_t Cst = cast<ConstantSDNode>(Node)->getValue();
Lo = DAG.getConstant(Cst, NVT);
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index edc5b8c6f5..023848a9f9 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -1112,6 +1112,7 @@ const char *SDNode::getOperationName() const {
case ISD::CopyToReg: return "CopyToReg";
case ISD::CopyFromReg: return "CopyFromReg";
case ISD::ImplicitDef: return "ImplicitDef";
+ case ISD::UNDEF: return "undef";
case ISD::ADD: return "add";
case ISD::SUB: return "sub";
diff --git a/lib/Target/PowerPC/PPCISelPattern.cpp b/lib/Target/PowerPC/PPCISelPattern.cpp
index 8ea2086787..db56384a38 100644
--- a/lib/Target/PowerPC/PPCISelPattern.cpp
+++ b/lib/Target/PowerPC/PPCISelPattern.cpp
@@ -53,7 +53,7 @@ namespace {
// PowerPC has an i16 but no i8 (or i1) SEXTLOAD
setOperationAction(ISD::SEXTLOAD, MVT::i1, Expand);
setOperationAction(ISD::SEXTLOAD, MVT::i8, Expand);
-
+
addLegalFPImmediate(+0.0); // Necessary for FSEL
addLegalFPImmediate(-0.0); //
@@ -251,15 +251,6 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
unsigned ArgOffset = 24;
unsigned GPR_remaining = 8;
unsigned FPR_remaining = 13;
- unsigned GPR_idx = 0, FPR_idx = 0;
- static const unsigned GPR[] = {
- PPC::R3, PPC::R4, PPC::R5, PPC::R6,
- PPC::R7, PPC::R8, PPC::R9, PPC::R10,
- };
- static const unsigned FPR[] = {
- PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7,
- PPC::F8, PPC::F9, PPC::F10, PPC::F11, PPC::F12, PPC::F13
- };
std::vector<SDOperand> MemOps;
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
@@ -283,10 +274,8 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
// FALL THROUGH
case MVT::i32:
if (GPR_remaining > 0) {
- args_to_use.push_back(DAG.getCopyToReg(Chain, Args[i].first,
- GPR[GPR_idx]));
+ args_to_use.push_back(Args[i].first);
--GPR_remaining;
- ++GPR_idx;
} else {
MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
Args[i].first, PtrOff));
@@ -302,13 +291,11 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
Args[i].first, DAG.getConstant(1, MVT::i32));
SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32,
Args[i].first, DAG.getConstant(0, MVT::i32));
- args_to_use.push_back(DAG.getCopyToReg(Chain, Hi, GPR[GPR_idx]));
+ args_to_use.push_back(Hi);
--GPR_remaining;
- ++GPR_idx;
if (GPR_remaining > 0) {
- args_to_use.push_back(DAG.getCopyToReg(Chain, Lo, GPR[GPR_idx]));
+ args_to_use.push_back(Lo);
--GPR_remaining;
- ++GPR_idx;
} else {
SDOperand ConstFour = DAG.getConstant(4, getPointerTy());
PtrOff = DAG.getNode(ISD::ADD, MVT::i32, PtrOff, ConstFour);
@@ -324,6 +311,8 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
case MVT::f32:
case MVT::f64:
if (FPR_remaining > 0) {
+ args_to_use.push_back(Args[i].first);
+ --FPR_remaining;
if (isVarArg) {
SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Chain,
Args[i].first, PtrOff);
@@ -332,32 +321,29 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
if (GPR_remaining > 0) {
SDOperand Load = DAG.getLoad(MVT::i32, Store, PtrOff);
MemOps.push_back(Load);
- args_to_use.push_back(DAG.getCopyToReg(Load, Load,
- GPR[GPR_idx]));
+ args_to_use.push_back(Load);
+ --GPR_remaining;
}
- if (GPR_remaining > 1 && MVT::f64 == ArgVT) {
+ if (GPR_remaining > 0 && MVT::f64 == ArgVT) {
SDOperand ConstFour = DAG.getConstant(4, getPointerTy());
PtrOff = DAG.getNode(ISD::ADD, MVT::i32, PtrOff, ConstFour);
SDOperand Load = DAG.getLoad(MVT::i32, Store, PtrOff);
MemOps.push_back(Load);
- args_to_use.push_back(DAG.getCopyToReg(Load, Load,
- GPR[GPR_idx+1]));
+ args_to_use.push_back(Load);
+ --GPR_remaining;
+ }
+ } else {
+ // If we have any FPRs remaining, we may also have GPRs remaining.
+ // Args passed in FPRs consume either 1 (f32) or 2 (f64) available
+ // GPRs.
+ if (GPR_remaining > 0) {
+ args_to_use.push_back(DAG.getNode(ISD::UNDEF, MVT::i32));
+ --GPR_remaining;
+ }
+ if (GPR_remaining > 0 && MVT::f64 == ArgVT) {
+ args_to_use.push_back(DAG.getNode(ISD::UNDEF, MVT::i32));
+ --GPR_remaining;
}
- }
- args_to_use.push_back(DAG.getCopyToReg(Chain, Args[i].first,
- FPR[FPR_idx]));
- --FPR_remaining;
- ++FPR_idx;
- // If we have any FPRs remaining, we may also have GPRs remaining.
- // Args passed in FPRs consume either 1 (f32) or 2 (f64) available
- // GPRs.
- if (GPR_remaining > 0) {
- --GPR_remaining;
- ++GPR_idx;
- }
- if (GPR_remaining > 0 && MVT::f64 == ArgVT) {
- --GPR_remaining;
- ++GPR_idx;
}
} else {
MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
@@ -909,14 +895,20 @@ unsigned ISel::SelectExpr(SDOperand N) {
}
if (DestType == MVT::f64 || DestType == MVT::f32)
- if (ISD::LOAD != opcode && ISD::EXTLOAD != opcode)
+ if (ISD::LOAD != opcode && ISD::EXTLOAD != opcode && ISD::UNDEF != opcode)
return SelectExprFP(N, Result);
switch (opcode) {
default:
Node->dump();
assert(0 && "Node not handled!\n");
-
+ case ISD::UNDEF:
+ if (Result != 1)
+ ExprMap[N.getValue(1)] = 1;
+ else
+ Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
+ BuildMI(BB, PPC::IMPLICIT_DEF, 0, Result);
+ return Result;
case ISD::DYNAMIC_STACKALLOC:
// Generate both result values. FIXME: Need a better commment here?
if (Result != 1)
@@ -1020,13 +1012,47 @@ unsigned ISel::SelectExpr(SDOperand N) {
}
case ISD::CALL: {
+ unsigned GPR_idx = 0, FPR_idx = 0;
+ static const unsigned GPR[] = {
+ PPC::R3, PPC::R4, PPC::R5, PPC::R6,
+ PPC::R7, PPC::R8, PPC::R9, PPC::R10,
+ };
+ static const unsigned FPR[] = {
+ PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7,
+ PPC::F8, PPC::F9, PPC::F10, PPC::F11, PPC::F12, PPC::F13
+ };
+
// Lower the chain for this call.
Select(N.getOperand(0));
ExprMap[N.getValue(Node->getNumValues()-1)] = 1;
+ // Load the register args to virtual regs
+ std::vector<unsigned> ArgVR;
for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
- Select(N.getOperand(i));
-
+ ArgVR.push_back(SelectExpr(N.getOperand(i)));
+
+ // Copy the virtual registers into the appropriate argument register
+ for(int i = 0, e = ArgVR.size(); i < e; ++i) {
+ switch(N.getOperand(i+2).getValueType()) {
+ default: Node->dump(); assert(0 && "Unknown value type for call");
+ case MVT::i1:
+ case MVT::i8:
+ case MVT::i16:
+ case MVT::i32:
+ assert(GPR_idx < 8 && "Too many int args");
+ if (N.getOperand(i+2).getOpcode() != ISD::UNDEF)
+ BuildMI(BB, PPC::OR,2,GPR[GPR_idx]).addReg(ArgVR[i]).addReg(ArgVR[i]);
+ ++GPR_idx;
+ break;
+ case MVT::f64:
+ case MVT::f32:
+ assert(FPR_idx < 13 && "Too many fp args");
+ BuildMI(BB, PPC::FMR, 1, FPR[FPR_idx]).addReg(ArgVR[i]);
+ ++FPR_idx;
+ break;
+ }
+ }
+
// Emit the correct call instruction based on the type of symbol called.
if (GlobalAddressSDNode *GASD =
dyn_cast<GlobalAddressSDNode>(N.getOperand(1))) {