Try using vmov.i32 to materialize FP32 constants that can't be materialized by

vmov.f32.

llvm-svn: 153696
This commit is contained in:
Lang Hames 2012-03-29 21:56:11 +00:00
parent d66f6a3b28
commit 1a0d0ec699

View File

@ -507,7 +507,7 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
setOperationAction(ISD::FRINT, MVT::v2f64, Expand);
setOperationAction(ISD::FNEARBYINT, MVT::v2f64, Expand);
setOperationAction(ISD::FFLOOR, MVT::v2f64, Expand);
setOperationAction(ISD::FSQRT, MVT::v4f32, Expand);
setOperationAction(ISD::FSIN, MVT::v4f32, Expand);
setOperationAction(ISD::FCOS, MVT::v4f32, Expand);
@ -3672,27 +3672,6 @@ static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG) {
return Result;
}
SDValue ARMTargetLowering::LowerConstantFP(SDValue Op, SelectionDAG &DAG,
const ARMSubtarget *ST) const {
if (!ST->useNEONForSinglePrecisionFP() || !ST->hasVFP3() || ST->hasD16())
return SDValue();
ConstantFPSDNode *CFP = cast<ConstantFPSDNode>(Op);
assert(Op.getValueType() == MVT::f32 &&
"ConstantFP custom lowering should only occur for f32.");
APFloat FPVal = CFP->getValueAPF();
int ImmVal = ARM_AM::getFP32Imm(FPVal);
if (ImmVal == -1)
return SDValue();
DebugLoc DL = Op.getDebugLoc();
SDValue NewVal = DAG.getTargetConstant(ImmVal, MVT::i32);
SDValue VecConstant = DAG.getNode(ARMISD::VMOVFPIMM, DL, MVT::v2f32, NewVal);
return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, VecConstant,
DAG.getConstant(0, MVT::i32));
}
/// isNEONModifiedImm - Check if the specified splat value corresponds to a
/// valid vector constant for a NEON instruction with a "modified immediate"
/// operand (e.g., VMOV). If so, return the encoded value.
@ -3829,6 +3808,58 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef,
return DAG.getTargetConstant(EncodedVal, MVT::i32);
}
SDValue ARMTargetLowering::LowerConstantFP(SDValue Op, SelectionDAG &DAG,
const ARMSubtarget *ST) const {
if (!ST->useNEONForSinglePrecisionFP() || !ST->hasVFP3() || ST->hasD16())
return SDValue();
ConstantFPSDNode *CFP = cast<ConstantFPSDNode>(Op);
assert(Op.getValueType() == MVT::f32 &&
"ConstantFP custom lowering should only occur for f32.");
// Try splatting with a VMOV.f32...
APFloat FPVal = CFP->getValueAPF();
int ImmVal = ARM_AM::getFP32Imm(FPVal);
if (ImmVal != -1) {
DebugLoc DL = Op.getDebugLoc();
SDValue NewVal = DAG.getTargetConstant(ImmVal, MVT::i32);
SDValue VecConstant = DAG.getNode(ARMISD::VMOVFPIMM, DL, MVT::v2f32,
NewVal);
return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, VecConstant,
DAG.getConstant(0, MVT::i32));
}
// If that fails, try a VMOV.i32
EVT VMovVT;
unsigned iVal = FPVal.bitcastToAPInt().getZExtValue();
SDValue NewVal = isNEONModifiedImm(iVal, 0, 32, DAG, VMovVT, false,
VMOVModImm);
if (NewVal != SDValue()) {
DebugLoc DL = Op.getDebugLoc();
SDValue VecConstant = DAG.getNode(ARMISD::VMOVIMM, DL, VMovVT,
NewVal);
SDValue VecFConstant = DAG.getNode(ISD::BITCAST, DL, MVT::v2f32,
VecConstant);
return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, VecFConstant,
DAG.getConstant(0, MVT::i32));
}
// Finally, try a VMVN.i32
NewVal = isNEONModifiedImm(~iVal & 0xffffffff, 0, 32, DAG, VMovVT, false,
VMVNModImm);
if (NewVal != SDValue()) {
DebugLoc DL = Op.getDebugLoc();
SDValue VecConstant = DAG.getNode(ARMISD::VMVNIMM, DL, VMovVT, NewVal);
SDValue VecFConstant = DAG.getNode(ISD::BITCAST, DL, MVT::v2f32,
VecConstant);
return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, VecFConstant,
DAG.getConstant(0, MVT::i32));
}
return SDValue();
}
static bool isVEXTMask(ArrayRef<int> M, EVT VT,
bool &ReverseVEXT, unsigned &Imm) {
unsigned NumElts = VT.getVectorNumElements();
@ -5869,7 +5900,7 @@ EmitSjLjDispatchBlock(MachineInstr *MI, MachineBasicBlock *MBB) const {
BuildMI(DispatchBB, dl, TII->get(ARM::tInt_eh_sjlj_dispatchsetup));
else if (!Subtarget->hasVFP2())
BuildMI(DispatchBB, dl, TII->get(ARM::Int_eh_sjlj_dispatchsetup_nofp));
else
else
BuildMI(DispatchBB, dl, TII->get(ARM::Int_eh_sjlj_dispatchsetup));
unsigned NumLPads = LPadList.size();