Basic FastISel support for floating-point constants.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@55401 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dan Gohman 2008-08-27 01:09:54 +00:00
parent 96c5ea878c
commit 10df0fa73e
4 changed files with 123 additions and 1 deletions

View File

@ -20,6 +20,7 @@
namespace llvm {
class ConstantFP;
class MachineBasicBlock;
class MachineFunction;
class MachineRegisterInfo;
@ -93,6 +94,15 @@ protected:
ISD::NodeType Opcode,
unsigned Op0, uint64_t Imm);
/// FastEmit_rf - This method is called by target-independent code
/// to request that an instruction with the given type, opcode, and
/// register and floating-point immediate operands be emitted.
///
virtual unsigned FastEmit_rf(MVT::SimpleValueType VT,
MVT::SimpleValueType RetVT,
ISD::NodeType Opcode,
unsigned Op0, ConstantFP *FPImm);
/// FastEmit_rri - This method is called by target-independent code
/// to request that an instruction with the given type, opcode, and
/// register and immediate operands be emitted.
@ -111,6 +121,15 @@ protected:
unsigned Op0, uint64_t Imm,
MVT::SimpleValueType ImmType);
/// FastEmit_rf_ - This method is a wrapper of FastEmit_rf. It first tries
/// to emit an instruction with an immediate operand using FastEmit_rf.
/// If that fails, it materializes the immediate into a register and try
/// FastEmit_rr instead.
unsigned FastEmit_rf_(MVT::SimpleValueType VT,
ISD::NodeType Opcode,
unsigned Op0, ConstantFP *FPImm,
MVT::SimpleValueType ImmType);
/// FastEmit_i - This method is called by target-independent code
/// to request that an instruction with the given type, opcode, and
/// immediate operand be emitted.
@ -119,6 +138,14 @@ protected:
ISD::NodeType Opcode,
uint64_t Imm);
/// FastEmit_f - This method is called by target-independent code
/// to request that an instruction with the given type, opcode, and
/// floating-point immediate operand be emitted.
virtual unsigned FastEmit_f(MVT::SimpleValueType VT,
MVT::SimpleValueType RetVT,
ISD::NodeType Opcode,
ConstantFP *FPImm);
/// FastEmitInst_ - Emit a MachineInstr with no operands and a
/// result register in the given register class.
///
@ -146,6 +173,13 @@ protected:
const TargetRegisterClass *RC,
unsigned Op0, uint64_t Imm);
/// FastEmitInst_rf - Emit a MachineInstr with two register operands
/// and a result register in the given register class.
///
unsigned FastEmitInst_rf(unsigned MachineInstOpcode,
const TargetRegisterClass *RC,
unsigned Op0, ConstantFP *FPImm);
/// FastEmitInst_rri - Emit a MachineInstr with two register operands,
/// an immediate, and a result register in the given register class.
///

View File

@ -56,6 +56,20 @@ bool FastISel::SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode,
return true;
}
// Check if the second operand is a constant float.
if (ConstantFP *CF = dyn_cast<ConstantFP>(I->getOperand(1))) {
unsigned ResultReg = FastEmit_rf_(VT.getSimpleVT(), ISDOpcode, Op0,
CF, VT.getSimpleVT());
if (ResultReg == 0)
// Target-specific code wasn't able to find a machine opcode for
// the given ISD opcode and type. Halt "fast" selection and bail.
return false;
// We successfully emitted code for the given LLVM Instruction.
ValueMap[I] = ResultReg;
return true;
}
unsigned Op1 = ValueMap[I->getOperand(1)];
if (Op1 == 0)
// Unhandled operand. Halt "fast" selection and bail.
@ -451,12 +465,23 @@ unsigned FastISel::FastEmit_i(MVT::SimpleValueType, MVT::SimpleValueType,
return 0;
}
unsigned FastISel::FastEmit_f(MVT::SimpleValueType, MVT::SimpleValueType,
ISD::NodeType, ConstantFP * /*FPImm*/) {
return 0;
}
unsigned FastISel::FastEmit_ri(MVT::SimpleValueType, MVT::SimpleValueType,
ISD::NodeType, unsigned /*Op0*/,
uint64_t /*Imm*/) {
return 0;
}
unsigned FastISel::FastEmit_rf(MVT::SimpleValueType, MVT::SimpleValueType,
ISD::NodeType, unsigned /*Op0*/,
ConstantFP * /*FPImm*/) {
return 0;
}
unsigned FastISel::FastEmit_rri(MVT::SimpleValueType, MVT::SimpleValueType,
ISD::NodeType,
unsigned /*Op0*/, unsigned /*Op1*/,
@ -483,6 +508,45 @@ unsigned FastISel::FastEmit_ri_(MVT::SimpleValueType VT, ISD::NodeType Opcode,
return FastEmit_rr(VT, VT, Opcode, Op0, MaterialReg);
}
/// FastEmit_rf_ - This method is a wrapper of FastEmit_ri. It first tries
/// to emit an instruction with a floating-point immediate operand using
/// FastEmit_rf. If that fails, it materializes the immediate into a register
/// and try FastEmit_rr instead.
unsigned FastISel::FastEmit_rf_(MVT::SimpleValueType VT, ISD::NodeType Opcode,
unsigned Op0, ConstantFP *FPImm,
MVT::SimpleValueType ImmType) {
unsigned ResultReg = 0;
// First check if immediate type is legal. If not, we can't use the rf form.
if (TLI.getOperationAction(ISD::Constant, ImmType) == TargetLowering::Legal)
ResultReg = FastEmit_rf(VT, VT, Opcode, Op0, FPImm);
if (ResultReg != 0)
return ResultReg;
// Materialize the constant in a register.
unsigned MaterialReg = FastEmit_f(ImmType, ImmType, ISD::ConstantFP, FPImm);
if (MaterialReg == 0) {
const APFloat &Flt = FPImm->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;
MaterialReg = FastEmit_r(IntVT.getSimpleVT(), VT,
ISD::SINT_TO_FP, IntegerReg);
if (MaterialReg == 0)
return 0;
}
return FastEmit_rr(VT, VT, Opcode, Op0, MaterialReg);
}
unsigned FastISel::createResultReg(const TargetRegisterClass* RC) {
return MRI.createVirtualRegister(RC);
}
@ -526,6 +590,16 @@ unsigned FastISel::FastEmitInst_ri(unsigned MachineInstOpcode,
return ResultReg;
}
unsigned FastISel::FastEmitInst_rf(unsigned MachineInstOpcode,
const TargetRegisterClass *RC,
unsigned Op0, ConstantFP *FPImm) {
unsigned ResultReg = createResultReg(RC);
const TargetInstrDesc &II = TII.get(MachineInstOpcode);
BuildMI(MBB, II, ResultReg).addReg(Op0).addFPImm(FPImm);
return ResultReg;
}
unsigned FastISel::FastEmitInst_rri(unsigned MachineInstOpcode,
const TargetRegisterClass *RC,
unsigned Op0, unsigned Op1, uint64_t Imm) {

View File

@ -35,10 +35,11 @@ fast:
%t0 = add double %r, %s
%t1 = mul double %t0, %s
%t2 = sub double %t1, %s
%t3 = add double %t2, 707.0
br label %exit
exit:
ret double %t2
ret double %t3
}
define i32 @cast(){

View File

@ -68,6 +68,11 @@ struct OperandsSignature {
Operands.push_back("i");
return true;
}
if (!InstPatNode->isLeaf() &&
InstPatNode->getOperator()->getName() == "fpimm") {
Operands.push_back("f");
return true;
}
const CodeGenRegisterClass *DstRC = 0;
@ -87,6 +92,10 @@ struct OperandsSignature {
Operands.push_back("i");
return true;
}
if (Op->getOperator()->getName() == "fpimm") {
Operands.push_back("f");
return true;
}
// For now, ignore fpimm and other non-leaf nodes.
return false;
}
@ -122,6 +131,8 @@ struct OperandsSignature {
OS << "unsigned Op" << i;
} else if (Operands[i] == "i") {
OS << "uint64_t imm" << i;
} else if (Operands[i] == "f") {
OS << "ConstantFP *f" << i;
} else {
assert("Unknown operand kind!");
abort();
@ -137,6 +148,8 @@ struct OperandsSignature {
OS << "Op" << i;
} else if (Operands[i] == "i") {
OS << "imm" << i;
} else if (Operands[i] == "f") {
OS << "f" << i;
} else {
assert("Unknown operand kind!");
abort();