ARM fix encoding of VMOV.f32 and VMOV.f64 immediates.

Encode the immediate into its 8-bit form as part of isel rather than later,
which simplifies things for mapping the encoding bits, allows the removal
of the custom disassembler decoding hook, makes the operand printer trivial,
and prepares things more cleanly for handling these in the asm parser.

rdar://10211428



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@140834 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jim Grosbach 2011-09-30 00:50:06 +00:00
parent 203e0b17dd
commit 4ebbf7b8a8
8 changed files with 128 additions and 145 deletions

View File

@ -502,11 +502,19 @@ unsigned ARMFastISel::ARMMaterializeFP(const ConstantFP *CFP, EVT VT) {
// This checks to see if we can use VFP3 instructions to materialize
// a constant, otherwise we have to go through the constant pool.
if (TLI.isFPImmLegal(Val, VT)) {
unsigned Opc = is64bit ? ARM::FCONSTD : ARM::FCONSTS;
int Imm;
unsigned Opc;
if (is64bit) {
Imm = ARM_AM::getFP64Imm(Val);
Opc = ARM::FCONSTD;
} else {
Imm = ARM_AM::getFP32Imm(Val);
Opc = ARM::FCONSTS;
}
unsigned DestReg = createResultReg(TLI.getRegClassFor(VT));
AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(Opc),
DestReg)
.addFPImm(CFP));
.addImm(Imm));
return DestReg;
}

View File

@ -8176,50 +8176,6 @@ ARMTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
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;
}
bool ARM::isBitFieldInvertedMask(unsigned v) {
if (v == 0xffffffff)
return 0;
@ -8242,9 +8198,9 @@ bool ARMTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const {
if (!Subtarget->hasVFP3())
return false;
if (VT == MVT::f32)
return ARM::getVFPf32Imm(Imm) != -1;
return ARM_AM::getFP32Imm(Imm) != -1;
if (VT == MVT::f64)
return ARM::getVFPf64Imm(Imm) != -1;
return ARM_AM::getFP64Imm(Imm) != -1;
return false;
}

View File

@ -227,12 +227,6 @@ namespace llvm {
/// Define some predicates that are used for node matching.
namespace ARM {
/// 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);
bool isBitFieldInvertedMask(unsigned v);
}

View File

@ -33,18 +33,24 @@ def arm_fmdrr : SDNode<"ARMISD::VMOVDRR", SDT_VMOVDRR>;
def vfp_f32imm : Operand<f32>,
PatLeaf<(f32 fpimm), [{
return ARM::getVFPf32Imm(N->getValueAPF()) != -1;
}]> {
let PrintMethod = "printVFPf32ImmOperand";
let DecoderMethod = "DecodeVFPfpImm";
return ARM_AM::getFP32Imm(N->getValueAPF()) != -1;
}], SDNodeXForm<fpimm, [{
APFloat InVal = N->getValueAPF();
uint32_t enc = ARM_AM::getFP32Imm(InVal);
return CurDAG->getTargetConstant(enc, MVT::i32);
}]>> {
let PrintMethod = "printFPImmOperand";
}
def vfp_f64imm : Operand<f64>,
PatLeaf<(f64 fpimm), [{
return ARM::getVFPf64Imm(N->getValueAPF()) != -1;
}]> {
let PrintMethod = "printVFPf64ImmOperand";
let DecoderMethod = "DecodeVFPfpImm";
return ARM_AM::getFP64Imm(N->getValueAPF()) != -1;
}], SDNodeXForm<fpimm, [{
APFloat InVal = N->getValueAPF();
uint32_t enc = ARM_AM::getFP64Imm(InVal);
return CurDAG->getTargetConstant(enc, MVT::i32);
}]>> {
let PrintMethod = "printFPImmOperand";
}
@ -1110,45 +1116,35 @@ def FCONSTD : VFPAI<(outs DPR:$Dd), (ins vfp_f64imm:$imm),
VFPMiscFrm, IIC_fpUNA64,
"vmov", ".f64\t$Dd, $imm",
[(set DPR:$Dd, vfp_f64imm:$imm)]>, Requires<[HasVFP3]> {
// Instruction operands.
bits<5> Dd;
bits<32> imm;
bits<5> Dd;
bits<8> imm;
// Encode instruction operands.
let Inst{15-12} = Dd{3-0};
let Inst{22} = Dd{4};
let Inst{19} = imm{31}; // The immediate is handled as a float.
let Inst{18-16} = imm{25-23};
let Inst{3-0} = imm{22-19};
// Encode remaining instruction bits.
let Inst{27-23} = 0b11101;
let Inst{22} = Dd{4};
let Inst{21-20} = 0b11;
let Inst{19-16} = imm{7-4};
let Inst{15-12} = Dd{3-0};
let Inst{11-9} = 0b101;
let Inst{8} = 1; // Double precision.
let Inst{7-4} = 0b0000;
let Inst{3-0} = imm{3-0};
}
def FCONSTS : VFPAI<(outs SPR:$Sd), (ins vfp_f32imm:$imm),
VFPMiscFrm, IIC_fpUNA32,
"vmov", ".f32\t$Sd, $imm",
[(set SPR:$Sd, vfp_f32imm:$imm)]>, Requires<[HasVFP3]> {
// Instruction operands.
bits<5> Sd;
bits<32> imm;
bits<5> Sd;
bits<8> imm;
// Encode instruction operands.
let Inst{15-12} = Sd{4-1};
let Inst{22} = Sd{0};
let Inst{19} = imm{31}; // The immediate is handled as a float.
let Inst{18-16} = imm{25-23};
let Inst{3-0} = imm{22-19};
// Encode remaining instruction bits.
let Inst{27-23} = 0b11101;
let Inst{22} = Sd{0};
let Inst{21-20} = 0b11;
let Inst{19-16} = imm{7-4};
let Inst{15-12} = Sd{4-1};
let Inst{11-9} = 0b101;
let Inst{8} = 0; // Single precision.
let Inst{7-4} = 0b0000;
let Inst{3-0} = imm{3-0};
}
}

View File

@ -204,8 +204,6 @@ static DecodeStatus DecodeShiftRight64Imm(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeTBLInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeVFPfpImm(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodePostIdxReg(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeCoprocessor(llvm::MCInst &Inst, unsigned Insn,
@ -2524,31 +2522,6 @@ static DecodeStatus DecodeTBLInstruction(llvm::MCInst &Inst, unsigned Insn,
return S;
}
static DecodeStatus DecodeVFPfpImm(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
// The immediate needs to be a fully instantiated float. However, the
// auto-generated decoder is only able to fill in some of the bits
// necessary. For instance, the 'b' bit is replicated multiple times,
// and is even present in inverted form in one bit. We do a little
// binary parsing here to fill in those missing bits, and then
// reinterpret it all as a float.
union {
uint32_t integer;
float fp;
} fp_conv;
fp_conv.integer = Val;
uint32_t b = fieldFromInstruction32(Val, 25, 1);
fp_conv.integer |= b << 26;
fp_conv.integer |= b << 27;
fp_conv.integer |= b << 28;
fp_conv.integer |= b << 29;
fp_conv.integer |= (~b & 0x1) << 30;
Inst.addOperand(MCOperand::CreateFPImm(fp_conv.fp));
return MCDisassembler::Success;
}
static DecodeStatus DecodeThumbAddSpecialReg(llvm::MCInst &Inst, uint16_t Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = MCDisassembler::Success;

View File

@ -934,39 +934,10 @@ void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
O << "]";
}
void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum,
raw_ostream &O) {
void ARMInstPrinter::printFPImmOperand(const MCInst *MI, unsigned OpNum,
raw_ostream &O) {
const MCOperand &MO = MI->getOperand(OpNum);
O << '#';
if (MO.isFPImm()) {
O << (float)MO.getFPImm();
} else {
union {
uint32_t I;
float F;
} FPUnion;
FPUnion.I = MO.getImm();
O << FPUnion.F;
}
}
void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum,
raw_ostream &O) {
const MCOperand &MO = MI->getOperand(OpNum);
O << '#';
if (MO.isFPImm()) {
O << MO.getFPImm();
} else {
// We expect the binary encoding of a floating point number here.
union {
uint64_t I;
double D;
} FPUnion;
FPUnion.I = MO.getImm();
O << FPUnion.D;
}
O << '#' << ARM_AM::getFPImmFloat(MO.getImm());
}
void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum,

View File

@ -120,8 +120,7 @@ public:
void printNoHashImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printPImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printCImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printFPImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printNEONModImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printImmPlusOneOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printRotImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);

View File

@ -14,6 +14,8 @@
#ifndef LLVM_TARGET_ARM_ARMADDRESSINGMODES_H
#define LLVM_TARGET_ARM_ARMADDRESSINGMODES_H
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
@ -574,6 +576,90 @@ namespace ARM_AM {
AMSubMode getLoadStoreMultipleSubMode(int Opcode);
//===--------------------------------------------------------------------===//
// Floating-point Immediates
//
static inline float getFPImmFloat(unsigned Imm) {
// We expect an 8-bit binary encoding of a floating-point number here.
union {
uint32_t I;
float F;
} FPUnion;
uint8_t Sign = (Imm >> 7) & 0x1;
uint8_t Exp = (Imm >> 4) & 0x7;
uint8_t Mantissa = Imm & 0xf;
// 8-bit FP iEEEE Float Encoding
// abcd efgh aBbbbbbc defgh000 00000000 00000000
//
// where B = NOT(b);
FPUnion.I = 0;
FPUnion.I |= Sign << 31;
FPUnion.I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;
FPUnion.I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;
FPUnion.I |= (Exp & 0x3) << 23;
FPUnion.I |= Mantissa << 19;
return FPUnion.F;
}
/// getFP32Imm - Return an 8-bit floating-point version of the 32-bit
/// floating-point value. If the value cannot be represented as an 8-bit
/// floating-point value, then return -1.
static inline int getFP32Imm(const APInt &Imm) {
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;
}
static inline int getFP32Imm(const APFloat &FPImm) {
return getFP32Imm(FPImm.bitcastToAPInt());
}
/// getFP64Imm - Return an 8-bit floating-point version of the 64-bit
/// floating-point value. If the value cannot be represented as an 8-bit
/// floating-point value, then return -1.
static inline int getFP64Imm(const APInt &Imm) {
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() & 0xfffffffffffffULL;
// We can handle 4 bits of mantissa.
// mantissa = (16+UInt(e:f:g:h))/16.
if (Mantissa & 0xffffffffffffULL)
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;
}
static inline int getFP64Imm(const APFloat &FPImm) {
return getFP64Imm(FPImm.bitcastToAPInt());
}
} // end namespace ARM_AM
} // end namespace llvm