mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-27 12:26:08 +00:00
Add a new FastISel method, getRegForValue, which takes care of
the details of materializing constants and other values into registers, and make use of it in several places. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@55426 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -194,6 +194,9 @@ protected:
|
|||||||
uint64_t Imm);
|
uint64_t Imm);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
unsigned getRegForValue(Value *V,
|
||||||
|
DenseMap<const Value*, unsigned> &ValueMap);
|
||||||
|
|
||||||
unsigned createResultReg(const TargetRegisterClass *RC);
|
unsigned createResultReg(const TargetRegisterClass *RC);
|
||||||
|
|
||||||
bool SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode,
|
bool SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode,
|
||||||
@@ -207,11 +210,6 @@ private:
|
|||||||
|
|
||||||
bool SelectCast(Instruction *I, ISD::NodeType Opcode,
|
bool SelectCast(Instruction *I, ISD::NodeType Opcode,
|
||||||
DenseMap<const Value*, unsigned> &ValueMap);
|
DenseMap<const Value*, unsigned> &ValueMap);
|
||||||
|
|
||||||
bool SelectConstantCast(Instruction *I, ISD::NodeType Opcode,
|
|
||||||
DenseMap<const Value*, unsigned> &ValueMap);
|
|
||||||
bool SelectConstantFPCast(Instruction *I, ISD::NodeType Opcode,
|
|
||||||
DenseMap<const Value*, unsigned> &ValueMap);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,43 @@
|
|||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
unsigned FastISel::getRegForValue(Value *V, DenseMap<const Value*, unsigned> &ValueMap) {
|
||||||
|
unsigned &Reg = ValueMap[V];
|
||||||
|
if (Reg != 0)
|
||||||
|
return Reg;
|
||||||
|
|
||||||
|
MVT::SimpleValueType VT = TLI.getValueType(V->getType()).getSimpleVT();
|
||||||
|
if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
|
||||||
|
if (CI->getValue().getActiveBits() > 64)
|
||||||
|
return 0;
|
||||||
|
Reg = FastEmit_i(VT, VT, ISD::Constant, CI->getZExtValue());
|
||||||
|
} else if (ConstantFP *CF = dyn_cast<ConstantFP>(V)) {
|
||||||
|
Reg = FastEmit_f(VT, VT, ISD::ConstantFP, CF);
|
||||||
|
|
||||||
|
if (!Reg) {
|
||||||
|
const APFloat &Flt = CF->getValueAPF();
|
||||||
|
MVT IntVT = TLI.getPointerTy();
|
||||||
|
|
||||||
|
uint64_t x[2];
|
||||||
|
uint32_t IntBitWidth = IntVT.getSizeInBits();
|
||||||
|
if (Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true,
|
||||||
|
APFloat::rmTowardZero) != APFloat::opOK)
|
||||||
|
return 0;
|
||||||
|
APInt IntVal(IntBitWidth, 2, x);
|
||||||
|
|
||||||
|
unsigned IntegerReg = FastEmit_i(IntVT.getSimpleVT(), IntVT.getSimpleVT(),
|
||||||
|
ISD::Constant, IntVal.getZExtValue());
|
||||||
|
if (IntegerReg == 0)
|
||||||
|
return 0;
|
||||||
|
Reg = FastEmit_r(IntVT.getSimpleVT(), VT, ISD::SINT_TO_FP, IntegerReg);
|
||||||
|
if (Reg == 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Reg;
|
||||||
|
}
|
||||||
|
|
||||||
/// SelectBinaryOp - Select and emit code for a binary operator instruction,
|
/// SelectBinaryOp - Select and emit code for a binary operator instruction,
|
||||||
/// which has an opcode which directly corresponds to the given ISD opcode.
|
/// which has an opcode which directly corresponds to the given ISD opcode.
|
||||||
///
|
///
|
||||||
@@ -37,44 +74,39 @@ bool FastISel::SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode,
|
|||||||
if (!TLI.isTypeLegal(VT))
|
if (!TLI.isTypeLegal(VT))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
unsigned Op0 = ValueMap[I->getOperand(0)];
|
unsigned Op0 = getRegForValue(I->getOperand(0), ValueMap);
|
||||||
if (Op0 == 0)
|
if (Op0 == 0)
|
||||||
// Unhandled operand. Halt "fast" selection and bail.
|
// Unhandled operand. Halt "fast" selection and bail.
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check if the second operand is a constant and handle it appropriately.
|
// Check if the second operand is a constant and handle it appropriately.
|
||||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) {
|
if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) {
|
||||||
unsigned ResultReg = FastEmit_ri_(VT.getSimpleVT(), ISDOpcode, Op0,
|
unsigned ResultReg = FastEmit_ri(VT.getSimpleVT(), VT.getSimpleVT(),
|
||||||
CI->getZExtValue(), VT.getSimpleVT());
|
ISDOpcode, Op0, CI->getZExtValue());
|
||||||
if (ResultReg == 0)
|
if (ResultReg != 0) {
|
||||||
// Target-specific code wasn't able to find a machine opcode for
|
// We successfully emitted code for the given LLVM Instruction.
|
||||||
// the given ISD opcode and type. Halt "fast" selection and bail.
|
ValueMap[I] = ResultReg;
|
||||||
return false;
|
return true;
|
||||||
|
}
|
||||||
// We successfully emitted code for the given LLVM Instruction.
|
|
||||||
ValueMap[I] = ResultReg;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the second operand is a constant float.
|
// Check if the second operand is a constant float.
|
||||||
if (ConstantFP *CF = dyn_cast<ConstantFP>(I->getOperand(1))) {
|
if (ConstantFP *CF = dyn_cast<ConstantFP>(I->getOperand(1))) {
|
||||||
unsigned ResultReg = FastEmit_rf_(VT.getSimpleVT(), ISDOpcode, Op0,
|
unsigned ResultReg = FastEmit_rf(VT.getSimpleVT(), VT.getSimpleVT(),
|
||||||
CF, VT.getSimpleVT());
|
ISDOpcode, Op0, CF);
|
||||||
if (ResultReg == 0)
|
if (ResultReg != 0) {
|
||||||
// Target-specific code wasn't able to find a machine opcode for
|
// We successfully emitted code for the given LLVM Instruction.
|
||||||
// the given ISD opcode and type. Halt "fast" selection and bail.
|
ValueMap[I] = ResultReg;
|
||||||
return false;
|
return true;
|
||||||
|
}
|
||||||
// We successfully emitted code for the given LLVM Instruction.
|
|
||||||
ValueMap[I] = ResultReg;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned Op1 = ValueMap[I->getOperand(1)];
|
unsigned Op1 = getRegForValue(I->getOperand(1), ValueMap);
|
||||||
if (Op1 == 0)
|
if (Op1 == 0)
|
||||||
// Unhandled operand. Halt "fast" selection and bail.
|
// Unhandled operand. Halt "fast" selection and bail.
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Now we have both operands in registers. Emit the instruction.
|
||||||
unsigned ResultReg = FastEmit_rr(VT.getSimpleVT(), VT.getSimpleVT(),
|
unsigned ResultReg = FastEmit_rr(VT.getSimpleVT(), VT.getSimpleVT(),
|
||||||
ISDOpcode, Op0, Op1);
|
ISDOpcode, Op0, Op1);
|
||||||
if (ResultReg == 0)
|
if (ResultReg == 0)
|
||||||
@@ -89,7 +121,7 @@ bool FastISel::SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode,
|
|||||||
|
|
||||||
bool FastISel::SelectGetElementPtr(Instruction *I,
|
bool FastISel::SelectGetElementPtr(Instruction *I,
|
||||||
DenseMap<const Value*, unsigned> &ValueMap) {
|
DenseMap<const Value*, unsigned> &ValueMap) {
|
||||||
unsigned N = ValueMap[I->getOperand(0)];
|
unsigned N = getRegForValue(I->getOperand(0), ValueMap);
|
||||||
if (N == 0)
|
if (N == 0)
|
||||||
// Unhandled operand. Halt "fast" selection and bail.
|
// Unhandled operand. Halt "fast" selection and bail.
|
||||||
return false;
|
return false;
|
||||||
@@ -129,7 +161,7 @@ bool FastISel::SelectGetElementPtr(Instruction *I,
|
|||||||
|
|
||||||
// N = N + Idx * ElementSize;
|
// N = N + Idx * ElementSize;
|
||||||
uint64_t ElementSize = TD.getABITypeSize(Ty);
|
uint64_t ElementSize = TD.getABITypeSize(Ty);
|
||||||
unsigned IdxN = ValueMap[Idx];
|
unsigned IdxN = getRegForValue(Idx, ValueMap);
|
||||||
if (IdxN == 0)
|
if (IdxN == 0)
|
||||||
// Unhandled operand. Halt "fast" selection and bail.
|
// Unhandled operand. Halt "fast" selection and bail.
|
||||||
return false;
|
return false;
|
||||||
@@ -174,7 +206,7 @@ bool FastISel::SelectCast(Instruction *I, ISD::NodeType Opcode,
|
|||||||
// Unhandled type. Halt "fast" selection and bail.
|
// Unhandled type. Halt "fast" selection and bail.
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
unsigned InputReg = ValueMap[I->getOperand(0)];
|
unsigned InputReg = getRegForValue(I->getOperand(0), ValueMap);
|
||||||
if (!InputReg)
|
if (!InputReg)
|
||||||
// Unhandled operand. Halt "fast" selection and bail.
|
// Unhandled operand. Halt "fast" selection and bail.
|
||||||
return false;
|
return false;
|
||||||
@@ -190,11 +222,16 @@ bool FastISel::SelectCast(Instruction *I, ISD::NodeType Opcode,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FastISel::SelectConstantCast(Instruction* I, ISD::NodeType Opcode,
|
bool FastISel::SelectBitCast(Instruction *I,
|
||||||
DenseMap<const Value*, unsigned> &ValueMap) {
|
DenseMap<const Value*, unsigned> &ValueMap) {
|
||||||
// Materialize constant and convert.
|
// If the bitcast doesn't change the type, just use the operand value.
|
||||||
ConstantInt* CI = cast<ConstantInt>(I->getOperand(0));
|
if (I->getType() == I->getOperand(0)->getType()) {
|
||||||
MVT SrcVT = MVT::getMVT(CI->getType());
|
ValueMap[I] = getRegForValue(I->getOperand(0), ValueMap);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bitcasts of other values become reg-reg copies or BIT_CONVERT operators.
|
||||||
|
MVT SrcVT = MVT::getMVT(I->getOperand(0)->getType());
|
||||||
MVT DstVT = MVT::getMVT(I->getType());
|
MVT DstVT = MVT::getMVT(I->getType());
|
||||||
|
|
||||||
if (SrcVT == MVT::Other || !SrcVT.isSimple() ||
|
if (SrcVT == MVT::Other || !SrcVT.isSimple() ||
|
||||||
@@ -203,96 +240,36 @@ bool FastISel::SelectConstantCast(Instruction* I, ISD::NodeType Opcode,
|
|||||||
// Unhandled type. Halt "fast" selection and bail.
|
// Unhandled type. Halt "fast" selection and bail.
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
unsigned ResultReg1 = FastEmit_i(SrcVT.getSimpleVT(),
|
unsigned Op0 = getRegForValue(I->getOperand(0), ValueMap);
|
||||||
SrcVT.getSimpleVT(),
|
if (Op0 == 0)
|
||||||
ISD::Constant, CI->getZExtValue());
|
// Unhandled operand. Halt "fast" selection and bail.
|
||||||
if (!ResultReg1)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
unsigned ResultReg2 = FastEmit_r(SrcVT.getSimpleVT(),
|
// First, try to perform the bitcast by inserting a reg-reg copy.
|
||||||
DstVT.getSimpleVT(),
|
unsigned ResultReg = 0;
|
||||||
Opcode,
|
if (SrcVT.getSimpleVT() == DstVT.getSimpleVT()) {
|
||||||
ResultReg1);
|
TargetRegisterClass* SrcClass = TLI.getRegClassFor(SrcVT);
|
||||||
if (!ResultReg2)
|
TargetRegisterClass* DstClass = TLI.getRegClassFor(DstVT);
|
||||||
|
ResultReg = createResultReg(DstClass);
|
||||||
|
|
||||||
|
bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg,
|
||||||
|
Op0, DstClass, SrcClass);
|
||||||
|
if (!InsertedCopy)
|
||||||
|
ResultReg = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the reg-reg copy failed, select a BIT_CONVERT opcode.
|
||||||
|
if (!ResultReg)
|
||||||
|
ResultReg = FastEmit_r(SrcVT.getSimpleVT(), DstVT.getSimpleVT(),
|
||||||
|
ISD::BIT_CONVERT, Op0);
|
||||||
|
|
||||||
|
if (!ResultReg)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ValueMap[I] = ResultReg2;
|
ValueMap[I] = ResultReg;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FastISel::SelectConstantFPCast(Instruction* I, ISD::NodeType Opcode,
|
|
||||||
DenseMap<const Value*, unsigned> &ValueMap) {
|
|
||||||
// TODO: Implement casting of FP constants by materialization
|
|
||||||
// followed by conversion.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FastISel::SelectBitCast(Instruction *I,
|
|
||||||
DenseMap<const Value*, unsigned> &ValueMap) {
|
|
||||||
// BitCast consists of either an immediate to register move
|
|
||||||
// or a register to register move.
|
|
||||||
if (ConstantInt* CI = dyn_cast<ConstantInt>(I->getOperand(0))) {
|
|
||||||
if (I->getType()->isInteger()) {
|
|
||||||
MVT VT = MVT::getMVT(I->getType(), /*HandleUnknown=*/false);
|
|
||||||
unsigned result = FastEmit_i(VT.getSimpleVT(), VT.getSimpleVT(),
|
|
||||||
ISD::Constant,
|
|
||||||
CI->getZExtValue());
|
|
||||||
if (!result)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ValueMap[I] = result;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Support vector and fp constants.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isa<Constant>(I->getOperand(0))) {
|
|
||||||
// Bitcasts of non-constant values become reg-reg copies.
|
|
||||||
MVT SrcVT = MVT::getMVT(I->getOperand(0)->getType());
|
|
||||||
MVT DstVT = MVT::getMVT(I->getType());
|
|
||||||
|
|
||||||
if (SrcVT == MVT::Other || !SrcVT.isSimple() ||
|
|
||||||
DstVT == MVT::Other || !DstVT.isSimple() ||
|
|
||||||
!TLI.isTypeLegal(SrcVT) || !TLI.isTypeLegal(DstVT))
|
|
||||||
// Unhandled type. Halt "fast" selection and bail.
|
|
||||||
return false;
|
|
||||||
|
|
||||||
unsigned Op0 = ValueMap[I->getOperand(0)];
|
|
||||||
if (Op0 == 0)
|
|
||||||
// Unhandled operand. Halt "fast" selection and bail.
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// First, try to perform the bitcast by inserting a reg-reg copy.
|
|
||||||
unsigned ResultReg = 0;
|
|
||||||
if (SrcVT.getSimpleVT() == DstVT.getSimpleVT()) {
|
|
||||||
TargetRegisterClass* SrcClass = TLI.getRegClassFor(SrcVT);
|
|
||||||
TargetRegisterClass* DstClass = TLI.getRegClassFor(DstVT);
|
|
||||||
ResultReg = createResultReg(DstClass);
|
|
||||||
|
|
||||||
bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg,
|
|
||||||
Op0, DstClass, SrcClass);
|
|
||||||
if (!InsertedCopy)
|
|
||||||
ResultReg = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the reg-reg copy failed, select a BIT_CONVERT opcode.
|
|
||||||
if (!ResultReg)
|
|
||||||
ResultReg = FastEmit_r(SrcVT.getSimpleVT(), DstVT.getSimpleVT(),
|
|
||||||
ISD::BIT_CONVERT, Op0);
|
|
||||||
|
|
||||||
if (!ResultReg)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ValueMap[I] = ResultReg;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Casting a non-integral constant?
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
BasicBlock::iterator
|
BasicBlock::iterator
|
||||||
FastISel::SelectInstructions(BasicBlock::iterator Begin,
|
FastISel::SelectInstructions(BasicBlock::iterator Begin,
|
||||||
BasicBlock::iterator End,
|
BasicBlock::iterator End,
|
||||||
@@ -378,28 +355,16 @@ FastISel::SelectInstructions(BasicBlock::iterator Begin,
|
|||||||
if (!SelectBitCast(I, ValueMap)) return I; break;
|
if (!SelectBitCast(I, ValueMap)) return I; break;
|
||||||
|
|
||||||
case Instruction::FPToSI:
|
case Instruction::FPToSI:
|
||||||
if (!isa<ConstantFP>(I->getOperand(0))) {
|
if (!SelectCast(I, ISD::FP_TO_SINT, ValueMap)) return I;
|
||||||
if (!SelectCast(I, ISD::FP_TO_SINT, ValueMap)) return I;
|
|
||||||
} else
|
|
||||||
if (!SelectConstantFPCast(I, ISD::FP_TO_SINT, ValueMap)) return I;
|
|
||||||
break;
|
break;
|
||||||
case Instruction::ZExt:
|
case Instruction::ZExt:
|
||||||
if (!isa<ConstantInt>(I->getOperand(0))) {
|
if (!SelectCast(I, ISD::ZERO_EXTEND, ValueMap)) return I;
|
||||||
if (!SelectCast(I, ISD::ZERO_EXTEND, ValueMap)) return I;
|
|
||||||
} else
|
|
||||||
if (!SelectConstantCast(I, ISD::ZERO_EXTEND, ValueMap)) return I;
|
|
||||||
break;
|
break;
|
||||||
case Instruction::SExt:
|
case Instruction::SExt:
|
||||||
if (!isa<ConstantInt>(I->getOperand(0))) {
|
if (!SelectCast(I, ISD::SIGN_EXTEND, ValueMap)) return I;
|
||||||
if (!SelectCast(I, ISD::SIGN_EXTEND, ValueMap)) return I;
|
|
||||||
} else
|
|
||||||
if (!SelectConstantCast(I, ISD::SIGN_EXTEND, ValueMap)) return I;
|
|
||||||
break;
|
break;
|
||||||
case Instruction::SIToFP:
|
case Instruction::SIToFP:
|
||||||
if (!isa<ConstantInt>(I->getOperand(0))) {
|
if (!SelectCast(I, ISD::SINT_TO_FP, ValueMap)) return I;
|
||||||
if (!SelectCast(I, ISD::SINT_TO_FP, ValueMap)) return I;
|
|
||||||
} else
|
|
||||||
if (!SelectConstantCast(I, ISD::SINT_TO_FP, ValueMap)) return I;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Instruction::IntToPtr: // Deliberate fall-through.
|
case Instruction::IntToPtr: // Deliberate fall-through.
|
||||||
@@ -414,10 +379,7 @@ FastISel::SelectInstructions(BasicBlock::iterator Begin,
|
|||||||
// Unhandled operand
|
// Unhandled operand
|
||||||
return I;
|
return I;
|
||||||
} else if (DstVT.bitsGT(SrcVT)) {
|
} else if (DstVT.bitsGT(SrcVT)) {
|
||||||
if (!isa<ConstantInt>(I->getOperand(0))) {
|
if (!SelectCast(I, ISD::ZERO_EXTEND, ValueMap)) return I;
|
||||||
if (!SelectCast(I, ISD::ZERO_EXTEND, ValueMap)) return I;
|
|
||||||
} else
|
|
||||||
if (!SelectConstantCast(I, ISD::ZERO_EXTEND, ValueMap)) return I;
|
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
// TODO: Handle SrcVT > DstVT, where truncation is needed.
|
// TODO: Handle SrcVT > DstVT, where truncation is needed.
|
||||||
|
Reference in New Issue
Block a user