mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
Use fconsts and fconstd to materialize small fp constants.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85362 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a1eaa3c52b
commit
39382427f1
@ -3990,3 +3990,60 @@ ARMTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
|
||||
// The ARM target isn't yet aware of offsets.
|
||||
return false;
|
||||
}
|
||||
|
||||
int ARM::getVFPf32Imm(const APFloat &FPImm) {
|
||||
APInt Imm = FPImm.bitcastToAPInt();
|
||||
uint32_t Sign = Imm.lshr(31).getZExtValue() & 1;
|
||||
int32_t Exp = (Imm.lshr(23).getSExtValue() & 0xff) - 127; // -126 to 127
|
||||
int64_t Mantissa = Imm.getZExtValue() & 0x7fffff; // 23 bits
|
||||
|
||||
// We can handle 4 bits of mantissa.
|
||||
// mantissa = (16+UInt(e:f:g:h))/16.
|
||||
if (Mantissa & 0x7ffff)
|
||||
return -1;
|
||||
Mantissa >>= 19;
|
||||
if ((Mantissa & 0xf) != Mantissa)
|
||||
return -1;
|
||||
|
||||
// We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3
|
||||
if (Exp < -3 || Exp > 4)
|
||||
return -1;
|
||||
Exp = ((Exp+3) & 0x7) ^ 4;
|
||||
|
||||
return ((int)Sign << 7) | (Exp << 4) | Mantissa;
|
||||
}
|
||||
|
||||
int ARM::getVFPf64Imm(const APFloat &FPImm) {
|
||||
APInt Imm = FPImm.bitcastToAPInt();
|
||||
uint64_t Sign = Imm.lshr(63).getZExtValue() & 1;
|
||||
int64_t Exp = (Imm.lshr(52).getSExtValue() & 0x7ff) - 1023; // -1022 to 1023
|
||||
uint64_t Mantissa = Imm.getZExtValue() & 0xfffffffffffffLL;
|
||||
|
||||
// We can handle 4 bits of mantissa.
|
||||
// mantissa = (16+UInt(e:f:g:h))/16.
|
||||
if (Mantissa & 0xffffffffffffLL)
|
||||
return -1;
|
||||
Mantissa >>= 48;
|
||||
if ((Mantissa & 0xf) != Mantissa)
|
||||
return -1;
|
||||
|
||||
// We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3
|
||||
if (Exp < -3 || Exp > 4)
|
||||
return -1;
|
||||
Exp = ((Exp+3) & 0x7) ^ 4;
|
||||
|
||||
return ((int)Sign << 7) | (Exp << 4) | Mantissa;
|
||||
}
|
||||
|
||||
/// isFPImmLegal - Returns true if the target can instruction select the
|
||||
/// specified FP immediate natively. If false, the legalizer will
|
||||
/// materialize the FP immediate as a load from a constant pool.
|
||||
bool ARMTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const {
|
||||
if (!Subtarget->hasVFP3())
|
||||
return false;
|
||||
if (VT == MVT::f32)
|
||||
return ARM::getVFPf32Imm(Imm) != -1;
|
||||
if (VT == MVT::f64)
|
||||
return ARM::getVFPf64Imm(Imm) != -1;
|
||||
return false;
|
||||
}
|
||||
|
@ -137,6 +137,13 @@ namespace llvm {
|
||||
/// return the constant being splatted. The ByteSize field indicates the
|
||||
/// number of bytes of each element [1248].
|
||||
SDValue getVMOVImm(SDNode *N, unsigned ByteSize, SelectionDAG &DAG);
|
||||
|
||||
/// getVFPf32Imm / getVFPf64Imm - If the given fp immediate can be
|
||||
/// materialized with a VMOV.f32 / VMOV.f64 (i.e. fconsts / fconstd)
|
||||
/// instruction, returns its 8-bit integer representation. Otherwise,
|
||||
/// returns -1.
|
||||
int getVFPf32Imm(const APFloat &FPImm);
|
||||
int getVFPf64Imm(const APFloat &FPImm);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
@ -224,6 +231,12 @@ namespace llvm {
|
||||
|
||||
bool isShuffleMaskLegal(const SmallVectorImpl<int> &M, EVT VT) const;
|
||||
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const;
|
||||
|
||||
/// isFPImmLegal - Returns true if the target can instruction select the
|
||||
/// specified FP immediate natively. If false, the legalizer will
|
||||
/// materialize the FP immediate as a load from a constant pool.
|
||||
virtual bool isFPImmLegal(const APFloat &Imm, EVT VT) const;
|
||||
|
||||
private:
|
||||
/// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
|
||||
/// make the right decision when generating code for different targets.
|
||||
|
@ -30,6 +30,26 @@ def arm_cmpfp : SDNode<"ARMISD::CMPFP", SDT_ARMCmp, [SDNPOutFlag]>;
|
||||
def arm_cmpfp0 : SDNode<"ARMISD::CMPFPw0",SDT_CMPFP0, [SDNPOutFlag]>;
|
||||
def arm_fmdrr : SDNode<"ARMISD::FMDRR", SDT_FMDRR>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Operand Definitions.
|
||||
//
|
||||
|
||||
|
||||
def vfp_f32imm : Operand<f32>,
|
||||
PatLeaf<(f32 fpimm), [{
|
||||
return ARM::getVFPf32Imm(N->getValueAPF()) != -1;
|
||||
}]> {
|
||||
let PrintMethod = "printVFPf32ImmOperand";
|
||||
}
|
||||
|
||||
def vfp_f64imm : Operand<f64>,
|
||||
PatLeaf<(f64 fpimm), [{
|
||||
return ARM::getVFPf64Imm(N->getValueAPF()) != -1;
|
||||
}]> {
|
||||
let PrintMethod = "printVFPf64ImmOperand";
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Load / store Instructions.
|
||||
//
|
||||
@ -408,3 +428,27 @@ def FMSTAT : VFPAI<(outs), (ins), VFPMiscFrm, IIC_fpSTAT, "fmstat", "",
|
||||
let Inst{7} = 0;
|
||||
let Inst{4} = 1;
|
||||
}
|
||||
|
||||
|
||||
// Materialize FP immediates. VFP3 only.
|
||||
def FCONSTS : VFPAI<(outs SPR:$dst), (ins vfp_f32imm:$imm),
|
||||
VFPMiscFrm, IIC_VMOVImm,
|
||||
"fconsts", "\t$dst, $imm",
|
||||
[(set SPR:$dst, vfp_f32imm:$imm)]>, Requires<[HasVFP3]> {
|
||||
let Inst{27-23} = 0b11101;
|
||||
let Inst{21-20} = 0b11;
|
||||
let Inst{11-9} = 0b101;
|
||||
let Inst{8} = 0;
|
||||
let Inst{7-4} = 0b0000;
|
||||
}
|
||||
|
||||
def FCONSTD : VFPAI<(outs DPR:$dst), (ins vfp_f64imm:$imm),
|
||||
VFPMiscFrm, IIC_VMOVImm,
|
||||
"fconstd", "\t$dst, $imm",
|
||||
[(set DPR:$dst, vfp_f64imm:$imm)]>, Requires<[HasVFP3]> {
|
||||
let Inst{27-23} = 0b11101;
|
||||
let Inst{21-20} = 0b11;
|
||||
let Inst{11-9} = 0b101;
|
||||
let Inst{8} = 1;
|
||||
let Inst{7-4} = 0b0000;
|
||||
}
|
||||
|
@ -135,6 +135,8 @@ namespace {
|
||||
void printJT2BlockOperand(const MachineInstr *MI, int OpNum);
|
||||
void printTBAddrMode(const MachineInstr *MI, int OpNum);
|
||||
void printNoHashImmediate(const MachineInstr *MI, int OpNum);
|
||||
void printVFPf32ImmOperand(const MachineInstr *MI, int OpNum);
|
||||
void printVFPf64ImmOperand(const MachineInstr *MI, int OpNum);
|
||||
|
||||
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
|
||||
unsigned AsmVariant, const char *ExtraCode);
|
||||
@ -393,9 +395,11 @@ static void printSOImm(formatted_raw_ostream &O, int64_t V, bool VerboseAsm,
|
||||
if (Rot) {
|
||||
O << "#" << Imm << ", " << Rot;
|
||||
// Pretty printed version.
|
||||
if (VerboseAsm)
|
||||
O << ' ' << MAI->getCommentString()
|
||||
<< ' ' << (int)ARM_AM::rotr32(Imm, Rot);
|
||||
if (VerboseAsm) {
|
||||
O.PadToColumn(MAI->getCommentColumn());
|
||||
O << MAI->getCommentString() << ' ';
|
||||
O << (int)ARM_AM::rotr32(Imm, Rot);
|
||||
}
|
||||
} else {
|
||||
O << "#" << Imm;
|
||||
}
|
||||
@ -970,6 +974,26 @@ void ARMAsmPrinter::printNoHashImmediate(const MachineInstr *MI, int OpNum) {
|
||||
O << MI->getOperand(OpNum).getImm();
|
||||
}
|
||||
|
||||
void ARMAsmPrinter::printVFPf32ImmOperand(const MachineInstr *MI, int OpNum) {
|
||||
const ConstantFP *FP = MI->getOperand(OpNum).getFPImm();
|
||||
O << ARM::getVFPf32Imm(FP->getValueAPF());
|
||||
if (VerboseAsm) {
|
||||
O.PadToColumn(MAI->getCommentColumn());
|
||||
O << MAI->getCommentString() << ' ';
|
||||
WriteAsOperand(O, FP, /*PrintType=*/false);
|
||||
}
|
||||
}
|
||||
|
||||
void ARMAsmPrinter::printVFPf64ImmOperand(const MachineInstr *MI, int OpNum) {
|
||||
const ConstantFP *FP = MI->getOperand(OpNum).getFPImm();
|
||||
O << ARM::getVFPf64Imm(FP->getValueAPF());
|
||||
if (VerboseAsm) {
|
||||
O.PadToColumn(MAI->getCommentColumn());
|
||||
O << MAI->getCommentString() << ' ';
|
||||
WriteAsOperand(O, FP, /*PrintType=*/false);
|
||||
}
|
||||
}
|
||||
|
||||
bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
|
||||
unsigned AsmVariant, const char *ExtraCode){
|
||||
// Does this asm operand have a single letter operand modifier?
|
||||
@ -1182,7 +1206,8 @@ void ARMAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) {
|
||||
EmitAlignment(Align, GVar);
|
||||
O << name << ":";
|
||||
if (VerboseAsm) {
|
||||
O << "\t\t\t\t" << MAI->getCommentString() << ' ';
|
||||
O.PadToColumn(MAI->getCommentColumn());
|
||||
O << MAI->getCommentString() << ' ';
|
||||
WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
|
||||
}
|
||||
O << '\n';
|
||||
@ -1205,7 +1230,8 @@ void ARMAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) {
|
||||
O << "," << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
|
||||
}
|
||||
if (VerboseAsm) {
|
||||
O << "\t\t" << MAI->getCommentString() << " ";
|
||||
O.PadToColumn(MAI->getCommentColumn());
|
||||
O << MAI->getCommentString() << ' ';
|
||||
WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
|
||||
}
|
||||
O << "\n";
|
||||
@ -1243,7 +1269,8 @@ void ARMAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) {
|
||||
EmitAlignment(Align, GVar);
|
||||
O << name << ":";
|
||||
if (VerboseAsm) {
|
||||
O << "\t\t\t\t" << MAI->getCommentString() << " ";
|
||||
O.PadToColumn(MAI->getCommentColumn());
|
||||
O << MAI->getCommentString() << ' ';
|
||||
WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
|
||||
}
|
||||
O << "\n";
|
||||
|
@ -78,6 +78,8 @@ public:
|
||||
void printJT2BlockOperand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printTBAddrMode(const MCInst *MI, unsigned OpNum) {}
|
||||
void printNoHashImmediate(const MCInst *MI, unsigned OpNum);
|
||||
void printVFPf32ImmOperand(const MCInst *MI, int OpNum) {}
|
||||
void printVFPf64ImmOperand(const MCInst *MI, int OpNum) {}
|
||||
|
||||
void printPCLabel(const MCInst *MI, unsigned OpNum);
|
||||
// FIXME: Implement.
|
||||
|
33
test/CodeGen/ARM/fpconsts.ll
Normal file
33
test/CodeGen/ARM/fpconsts.ll
Normal file
@ -0,0 +1,33 @@
|
||||
; RUN: llc < %s -march=arm -mattr=+vfp3 | FileCheck %s
|
||||
|
||||
define arm_apcscc float @t1(float %x) nounwind readnone optsize {
|
||||
entry:
|
||||
; CHECK: t1:
|
||||
; CHECK: fconsts s1, 16
|
||||
%0 = fadd float %x, 4.000000e+00
|
||||
ret float %0
|
||||
}
|
||||
|
||||
define arm_apcscc double @t2(double %x) nounwind readnone optsize {
|
||||
entry:
|
||||
; CHECK: t2:
|
||||
; CHECK: fconstd d1, 8
|
||||
%0 = fadd double %x, 3.000000e+00
|
||||
ret double %0
|
||||
}
|
||||
|
||||
define arm_apcscc double @t3(double %x) nounwind readnone optsize {
|
||||
entry:
|
||||
; CHECK: t3:
|
||||
; CHECK: fconstd d1, 170
|
||||
%0 = fmul double %x, -1.300000e+01
|
||||
ret double %0
|
||||
}
|
||||
|
||||
define arm_apcscc float @t4(float %x) nounwind readnone optsize {
|
||||
entry:
|
||||
; CHECK: t4:
|
||||
; CHECK: fconsts s1, 184
|
||||
%0 = fmul float %x, -2.400000e+01
|
||||
ret float %0
|
||||
}
|
Loading…
Reference in New Issue
Block a user