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:
Dan Gohman
2008-08-27 18:10:19 +00:00
parent 96a9999d79
commit ad368ac2b5
2 changed files with 98 additions and 138 deletions

View File

@@ -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);
}; };
} }

View File

@@ -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.