Add support for legalizing FP_ROUND_INREG, SIGN_EXTEND_INREG, and

ZERO_EXTEND_INREG for targets that don't support them.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19573 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2005-01-15 07:15:18 +00:00
parent 4ea6924444
commit 45b8caf1c5

View File

@ -14,6 +14,7 @@
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetOptions.h"
@ -21,20 +22,6 @@
#include <iostream>
using namespace llvm;
static const Type *getTypeFor(MVT::ValueType VT) {
switch (VT) {
default: assert(0 && "Unknown MVT!");
case MVT::i1: return Type::BoolTy;
case MVT::i8: return Type::UByteTy;
case MVT::i16: return Type::UShortTy;
case MVT::i32: return Type::UIntTy;
case MVT::i64: return Type::ULongTy;
case MVT::f32: return Type::FloatTy;
case MVT::f64: return Type::DoubleTy;
}
}
//===----------------------------------------------------------------------===//
/// SelectionDAGLegalize - This takes an arbitrary SelectionDAG as input and
/// hacks on it until the target machine can handle it. This involves
@ -574,7 +561,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
Tmp2 = LegalizeOp(Node->getOperand(1));
if (Tmp1 != Node->getOperand(0) || Tmp2 != Node->getOperand(1) ||
Tmp3 != Node->getOperand(2))
Result = DAG.getNode(ISD::TRUNCSTORE, MVT::Other, Tmp1, Tmp3, Tmp2,
Result = DAG.getNode(ISD::TRUNCSTORE, MVT::Other, Tmp1, Tmp2, Tmp3,
cast<MVTSDNode>(Node)->getExtraValueType());
break;
case Promote:
@ -774,13 +761,63 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
break;
case ISD::FP_ROUND_INREG:
case ISD::SIGN_EXTEND_INREG:
case ISD::ZERO_EXTEND_INREG:
case ISD::ZERO_EXTEND_INREG: {
Tmp1 = LegalizeOp(Node->getOperand(0));
if (Tmp1 != Node->getOperand(0))
Result = DAG.getNode(Node->getOpcode(), Node->getValueType(0), Tmp1,
cast<MVTSDNode>(Node)->getExtraValueType());
MVT::ValueType ExtraVT = cast<MVTSDNode>(Node)->getExtraValueType();
// If this operation is not supported, convert it to a shl/shr or load/store
// pair.
if (!TLI.isOperationSupported(Node->getOpcode(), ExtraVT)) {
// If this is an integer extend and shifts are supported, do that.
if (Node->getOpcode() == ISD::ZERO_EXTEND_INREG) {
// NOTE: we could fall back on load/store here too for targets without
// AND. However, it is doubtful that any exist.
// AND out the appropriate bits.
SDOperand Mask =
DAG.getConstant((1ULL << MVT::getSizeInBits(ExtraVT))-1,
Node->getValueType(0));
Result = DAG.getNode(ISD::AND, Node->getValueType(0),
Node->getOperand(0), Mask);
} else if (Node->getOpcode() == ISD::SIGN_EXTEND_INREG) {
// NOTE: we could fall back on load/store here too for targets without
// SAR. However, it is doubtful that any exist.
unsigned BitsDiff = MVT::getSizeInBits(Node->getValueType(0)) -
MVT::getSizeInBits(ExtraVT);
SDOperand ShiftCst = DAG.getConstant(BitsDiff, MVT::i8);
Result = DAG.getNode(ISD::SHL, Node->getValueType(0),
Node->getOperand(0), ShiftCst);
Result = DAG.getNode(ISD::SRA, Node->getValueType(0),
Result, ShiftCst);
} else if (Node->getOpcode() == ISD::FP_ROUND_INREG) {
// The only way we can lower this is to turn it into a STORETRUNC,
// EXTLOAD pair, targetting a temporary location (a stack slot).
// NOTE: there is a choice here between constantly creating new stack
// slots and always reusing the same one. We currently always create
// new ones, as reuse may inhibit scheduling.
const Type *Ty = MVT::getTypeForValueType(ExtraVT);
unsigned TySize = (unsigned)TLI.getTargetData().getTypeSize(Ty);
unsigned Align = TLI.getTargetData().getTypeAlignment(Ty);
MachineFunction &MF = DAG.getMachineFunction();
int SSFI =
MF.getFrameInfo()->CreateStackObject((unsigned)TySize, Align);
SDOperand StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy());
Result = DAG.getNode(ISD::TRUNCSTORE, MVT::Other, DAG.getEntryNode(),
Node->getOperand(0), StackSlot, ExtraVT);
Result = DAG.getNode(ISD::EXTLOAD, Node->getValueType(0),
Result, StackSlot, ExtraVT);
} else {
assert(0 && "Unknown op");
}
Result = LegalizeOp(Result);
} else {
if (Tmp1 != Node->getOperand(0))
Result = DAG.getNode(Node->getOpcode(), Node->getValueType(0), Tmp1,
ExtraVT);
}
break;
}
}
if (!Op.Val->hasOneUse())
AddLegalizedOperand(Op, Result);
@ -1057,14 +1094,14 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
TargetLowering::ArgListTy Args;
for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
Args.push_back(std::make_pair(Node->getOperand(i),
getTypeFor(Node->getOperand(i).getValueType())));
MVT::getTypeForValueType(Node->getOperand(i).getValueType())));
SDOperand Callee = DAG.getExternalSymbol(LibCallName, TLI.getPointerTy());
// We don't care about token chains for libcalls. We just use the entry
// node as our input and ignore the output chain. This allows us to place
// calls wherever we need them to satisfy data dependences.
SDOperand Result = TLI.LowerCallTo(DAG.getEntryNode(),
getTypeFor(Op.getValueType()), Callee,
MVT::getTypeForValueType(Op.getValueType()), Callee,
Args, DAG).first;
ExpandOp(Result, Lo, Hi);
}