mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-14 17:34:41 +00:00
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:
parent
96c5ea878c
commit
10df0fa73e
@ -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.
|
||||
///
|
||||
|
@ -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) {
|
||||
|
@ -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(){
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user