mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-08 18:31:23 +00:00
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:
parent
4ea6924444
commit
45b8caf1c5
@ -14,6 +14,7 @@
|
|||||||
#include "llvm/CodeGen/SelectionDAG.h"
|
#include "llvm/CodeGen/SelectionDAG.h"
|
||||||
#include "llvm/CodeGen/MachineConstantPool.h"
|
#include "llvm/CodeGen/MachineConstantPool.h"
|
||||||
#include "llvm/CodeGen/MachineFunction.h"
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||||
#include "llvm/Target/TargetLowering.h"
|
#include "llvm/Target/TargetLowering.h"
|
||||||
#include "llvm/Target/TargetData.h"
|
#include "llvm/Target/TargetData.h"
|
||||||
#include "llvm/Target/TargetOptions.h"
|
#include "llvm/Target/TargetOptions.h"
|
||||||
@ -21,20 +22,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
using namespace llvm;
|
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
|
/// SelectionDAGLegalize - This takes an arbitrary SelectionDAG as input and
|
||||||
/// hacks on it until the target machine can handle it. This involves
|
/// 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));
|
Tmp2 = LegalizeOp(Node->getOperand(1));
|
||||||
if (Tmp1 != Node->getOperand(0) || Tmp2 != Node->getOperand(1) ||
|
if (Tmp1 != Node->getOperand(0) || Tmp2 != Node->getOperand(1) ||
|
||||||
Tmp3 != Node->getOperand(2))
|
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());
|
cast<MVTSDNode>(Node)->getExtraValueType());
|
||||||
break;
|
break;
|
||||||
case Promote:
|
case Promote:
|
||||||
@ -774,13 +761,63 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
|||||||
break;
|
break;
|
||||||
case ISD::FP_ROUND_INREG:
|
case ISD::FP_ROUND_INREG:
|
||||||
case ISD::SIGN_EXTEND_INREG:
|
case ISD::SIGN_EXTEND_INREG:
|
||||||
case ISD::ZERO_EXTEND_INREG:
|
case ISD::ZERO_EXTEND_INREG: {
|
||||||
Tmp1 = LegalizeOp(Node->getOperand(0));
|
Tmp1 = LegalizeOp(Node->getOperand(0));
|
||||||
if (Tmp1 != Node->getOperand(0))
|
MVT::ValueType ExtraVT = cast<MVTSDNode>(Node)->getExtraValueType();
|
||||||
Result = DAG.getNode(Node->getOpcode(), Node->getValueType(0), Tmp1,
|
|
||||||
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;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!Op.Val->hasOneUse())
|
if (!Op.Val->hasOneUse())
|
||||||
AddLegalizedOperand(Op, Result);
|
AddLegalizedOperand(Op, Result);
|
||||||
@ -1057,14 +1094,14 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
|
|||||||
TargetLowering::ArgListTy Args;
|
TargetLowering::ArgListTy Args;
|
||||||
for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
|
for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
|
||||||
Args.push_back(std::make_pair(Node->getOperand(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());
|
SDOperand Callee = DAG.getExternalSymbol(LibCallName, TLI.getPointerTy());
|
||||||
|
|
||||||
// We don't care about token chains for libcalls. We just use the entry
|
// 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
|
// node as our input and ignore the output chain. This allows us to place
|
||||||
// calls wherever we need them to satisfy data dependences.
|
// calls wherever we need them to satisfy data dependences.
|
||||||
SDOperand Result = TLI.LowerCallTo(DAG.getEntryNode(),
|
SDOperand Result = TLI.LowerCallTo(DAG.getEntryNode(),
|
||||||
getTypeFor(Op.getValueType()), Callee,
|
MVT::getTypeForValueType(Op.getValueType()), Callee,
|
||||||
Args, DAG).first;
|
Args, DAG).first;
|
||||||
ExpandOp(Result, Lo, Hi);
|
ExpandOp(Result, Lo, Hi);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user