Implement next round of Pattern ISel fixes

1. void returns
2. multiplies
3. calls

llvm-svn: 20822
This commit is contained in:
Nate Begeman 2005-03-24 23:35:30 +00:00
parent 3a9a2f9ec7
commit ad5151d785
1 changed files with 162 additions and 38 deletions

View File

@ -221,10 +221,16 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
case MVT::i1:
case MVT::i8:
case MVT::i16:
// Promote the integer to 32 bits. If the input type is signed use a
// sign extend, otherwise use a zero extend.
if (Args[i].second->isSigned())
Args[i].first = DAG.getNode(ISD::SIGN_EXTEND, MVT::i32, Args[i].first);
else
Args[i].first = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Args[i].first);
break;
case MVT::i32:
case MVT::i64:
case MVT::f64:
case MVT::f32:
case MVT::f64:
break;
}
args_to_use.push_back(Args[i].first);
@ -438,14 +444,33 @@ unsigned ISel::SelectExpr(SDOperand N) {
unsigned &Reg = ExprMap[N];
if (Reg) return Reg;
if (DestType == MVT::f64 || DestType == MVT::f32)
return SelectExprFP(N, Result);
if (N.getOpcode() != ISD::CALL)
if (N.getOpcode() != ISD::CALL && N.getOpcode() != ISD::ADD_PARTS &&
N.getOpcode() != ISD::SUB_PARTS)
Reg = Result = (N.getValueType() != MVT::Other) ?
MakeReg(N.getValueType()) : 1;
else
abort(); // FIXME: Implement Call
else {
// If this is a call instruction, make sure to prepare ALL of the result
// values as well as the chain.
if (N.getOpcode() == ISD::CALL) {
if (Node->getNumValues() == 1)
Reg = Result = 1; // Void call, just a chain.
else {
Result = MakeReg(Node->getValueType(0));
ExprMap[N.getValue(0)] = Result;
for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
ExprMap[SDOperand(Node, Node->getNumValues()-1)] = 1;
}
} else {
Result = MakeReg(Node->getValueType(0));
ExprMap[N.getValue(0)] = Result;
for (unsigned i = 1, e = N.Val->getNumValues(); i != e; ++i)
ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
}
}
if (DestType == MVT::f64 || DestType == MVT::f32)
return SelectExprFP(N, Result);
switch (opcode) {
default:
@ -482,10 +507,24 @@ unsigned ISel::SelectExpr(SDOperand N) {
case ISD::FrameIndex:
abort();
case ISD::GlobalAddress: {
GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal();
unsigned Tmp1 = MakeReg(MVT::i32);
// FIXME: R1 is incorrect, we need the getGlobalBaseReg() functionality
// from the simple isel
BuildMI(BB, PPC::LOADHiAddr, 2, Tmp1).addReg(PPC::R1).addGlobalAddress(GV);
if (GV->hasWeakLinkage() || GV->isExternal()) {
BuildMI(BB, PPC::LWZ, 2, Result).addGlobalAddress(GV).addReg(Tmp1);
} else {
BuildMI(BB, PPC::LA, 2, Result).addReg(Tmp1).addGlobalAddress(GV);
}
return Result;
}
case ISD::LOAD:
case ISD::EXTLOAD:
case ISD::ZEXTLOAD:
{
case ISD::SEXTLOAD: {
// Make sure we generate both values.
if (Result != 1)
ExprMap[N.getValue(1)] = 1; // Generate the token
@ -498,22 +537,13 @@ unsigned ISel::SelectExpr(SDOperand N) {
switch (Node->getValueType(0)) {
default: assert(0 && "Cannot load this type!");
case MVT::i1:
case MVT::i8: Opc = PPC::LBZ; break;
case MVT::i16: Opc = PPC::LHZ; break;
case MVT::i32: Opc = PPC::LWZ; break;
case MVT::i1: Opc = PPC::LBZ; Tmp3 = 0; break;
case MVT::i8: Opc = PPC::LBZ; Tmp3 = 1; break;
case MVT::i16: Opc = PPC::LHZ; Tmp3 = 0; break;
case MVT::i32: Opc = PPC::LWZ; Tmp3 = 0; break;
}
if (Address.getOpcode() == ISD::GlobalAddress) { // FIXME
BuildMI(BB, Opc, 2, Result)
.addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal())
.addReg(PPC::R1);
}
else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
BuildMI(BB, Opc, 2, Result).addConstantPoolIndex(CP->getIndex())
.addReg(PPC::R1);
}
else if(Address.getOpcode() == ISD::FrameIndex) {
if(Address.getOpcode() == ISD::FrameIndex) {
BuildMI(BB, Opc, 2, Result)
.addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
.addReg(PPC::R1);
@ -525,10 +555,93 @@ unsigned ISel::SelectExpr(SDOperand N) {
return Result;
}
case ISD::SEXTLOAD:
case ISD::GlobalAddress:
case ISD::CALL:
abort();
case ISD::CALL: {
// Lower the chain for this call.
Select(N.getOperand(0));
ExprMap[N.getValue(Node->getNumValues()-1)] = 1;
// get the virtual reg for each argument
std::vector<unsigned> VRegs;
for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
VRegs.push_back(SelectExpr(N.getOperand(i)));
// The ABI specifies that the first 32 bytes of args may be passed in GPRs,
// and that 13 FPRs may also be used for passing any floating point args.
int GPR_remaining = 8, 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
};
// move the vregs into the appropriate architected register or stack slot
for(int i = 0, e = VRegs.size(); i < e; ++i) {
unsigned OperandType = N.getOperand(i+2).getValueType();
switch(OperandType) {
default:
Node->dump();
N.getOperand(i).Val->dump();
std::cerr << "Type for " << i << " is: " <<
N.getOperand(i+2).getValueType() << "\n";
assert(0 && "Unknown value type for call");
case MVT::i1:
case MVT::i8:
case MVT::i16:
case MVT::i32:
if (GPR_remaining > 0)
BuildMI(BB, PPC::OR, 2, GPR[GPR_idx]).addReg(VRegs[i])
.addReg(VRegs[i]);
break;
case MVT::f32:
case MVT::f64:
if (FPR_remaining > 0) {
BuildMI(BB, PPC::FMR, 1, FPR[FPR_idx]).addReg(VRegs[i]);
--FPR_remaining;
}
break;
}
// All arguments consume GPRs available for argument passing
if (GPR_remaining > 0) --GPR_remaining;
if (MVT::f64 == OperandType && GPR_remaining > 0) --GPR_remaining;
}
// Emit the correct call instruction based on the type of symbol called.
if (GlobalAddressSDNode *GASD =
dyn_cast<GlobalAddressSDNode>(N.getOperand(1))) {
BuildMI(BB, PPC::CALLpcrel, 1).addGlobalAddress(GASD->getGlobal(), true);
} else if (ExternalSymbolSDNode *ESSDN =
dyn_cast<ExternalSymbolSDNode>(N.getOperand(1))) {
BuildMI(BB, PPC::CALLpcrel, 1).addExternalSymbol(ESSDN->getSymbol(), true);
} else {
Tmp1 = SelectExpr(N.getOperand(1));
BuildMI(BB, PPC::OR, 2, PPC::R12).addReg(Tmp1).addReg(Tmp1);
BuildMI(BB, PPC::MTCTR, 1).addReg(PPC::R12);
BuildMI(BB, PPC::CALLindirect, 3).addImm(20).addImm(0).addReg(PPC::R12);
}
switch (Node->getValueType(0)) {
default: assert(0 && "Unknown value type for call result!");
case MVT::Other: return 1;
case MVT::i1:
case MVT::i8:
case MVT::i16:
case MVT::i32:
BuildMI(BB, PPC::OR, 2, Result).addReg(PPC::R3);
if (Node->getValueType(1) == MVT::i32)
BuildMI(BB, PPC::OR, 2, Result+1).addReg(PPC::R4);
break;
case MVT::f32:
case MVT::f64:
BuildMI(BB, PPC::FMR, 1, Result).addReg(PPC::F1);
break;
}
return Result+N.ResNo;
}
case ISD::SIGN_EXTEND:
case ISD::SIGN_EXTEND_INREG:
@ -551,9 +664,6 @@ unsigned ISel::SelectExpr(SDOperand N) {
.addImm(Tmp2).addImm(31);
return Result;
case ISD::SETCC:
abort();
case ISD::CopyFromReg:
if (Result == 1)
Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
@ -613,14 +723,7 @@ unsigned ISel::SelectExpr(SDOperand N) {
break;
}
return Result;
case ISD::SUB:
assert (DestType == MVT::i32 && "Only do arithmetic on i32s!");
Tmp1 = SelectExpr(N.getOperand(0));
Tmp2 = SelectExpr(N.getOperand(1));
BuildMI(BB, PPC::SUBF, 2, Result).addReg(Tmp2).addReg(Tmp1);
return Result;
case ISD::AND:
case ISD::OR:
case ISD::XOR:
@ -655,8 +758,23 @@ unsigned ISel::SelectExpr(SDOperand N) {
break;
}
return Result;
case ISD::SUB:
assert (DestType == MVT::i32 && "Only do arithmetic on i32s!");
Tmp1 = SelectExpr(N.getOperand(0));
Tmp2 = SelectExpr(N.getOperand(1));
BuildMI(BB, PPC::SUBF, 2, Result).addReg(Tmp2).addReg(Tmp1);
return Result;
case ISD::MUL:
assert (DestType == MVT::i32 && "Only do arithmetic on i32s!");
Tmp1 = SelectExpr(N.getOperand(0));
Tmp2 = SelectExpr(N.getOperand(1));
BuildMI(BB, PPC::MULLW, 2, Result).addReg(Tmp2).addReg(Tmp1);
return Result;
case ISD::ADD_PARTS:
case ISD::SUB_PARTS:
case ISD::UREM:
case ISD::SREM:
case ISD::SDIV:
@ -667,6 +785,9 @@ unsigned ISel::SelectExpr(SDOperand N) {
case ISD::FP_TO_SINT:
abort();
case ISD::SETCC:
abort();
case ISD::SELECT:
abort();
@ -776,6 +897,9 @@ void ISel::Select(SDOperand N) {
BuildMI(BB, PPC::OR, 2, PPC::R3).addReg(Tmp1).addReg(Tmp1);
break;
}
case 1:
Select(N.getOperand(0));
break;
}
BuildMI(BB, PPC::BLR, 0); // Just emit a 'ret' instruction
return;