@@ -5786,24 +5786,60 @@ AArch64InstructionSelector::emitConstantVector(Register Dst, Constant *CV,
5786
5786
5787
5787
if (CV->getSplatValue ()) {
5788
5788
APInt DefBits = APInt::getSplat (DstSize, CV->getUniqueInteger ());
5789
- MachineInstr *NewOp;
5790
- bool Inv = false ;
5791
- if ((NewOp = tryAdvSIMDModImm64 (Dst, DstSize, DefBits, MIRBuilder)) ||
5792
- (NewOp = tryAdvSIMDModImm32 (Dst, DstSize, DefBits, MIRBuilder, Inv)) ||
5793
- (NewOp =
5794
- tryAdvSIMDModImm321s (Dst, DstSize, DefBits, MIRBuilder, Inv)) ||
5795
- (NewOp = tryAdvSIMDModImm16 (Dst, DstSize, DefBits, MIRBuilder, Inv)) ||
5796
- (NewOp = tryAdvSIMDModImm8 (Dst, DstSize, DefBits, MIRBuilder)) ||
5797
- (NewOp = tryAdvSIMDModImmFP (Dst, DstSize, DefBits, MIRBuilder)))
5798
- return NewOp;
5789
+ auto TryMOVIWithBits = [&](APInt DefBits) -> MachineInstr * {
5790
+ MachineInstr *NewOp;
5791
+ bool Inv = false ;
5792
+ if ((NewOp = tryAdvSIMDModImm64 (Dst, DstSize, DefBits, MIRBuilder)) ||
5793
+ (NewOp =
5794
+ tryAdvSIMDModImm32 (Dst, DstSize, DefBits, MIRBuilder, Inv)) ||
5795
+ (NewOp =
5796
+ tryAdvSIMDModImm321s (Dst, DstSize, DefBits, MIRBuilder, Inv)) ||
5797
+ (NewOp =
5798
+ tryAdvSIMDModImm16 (Dst, DstSize, DefBits, MIRBuilder, Inv)) ||
5799
+ (NewOp = tryAdvSIMDModImm8 (Dst, DstSize, DefBits, MIRBuilder)) ||
5800
+ (NewOp = tryAdvSIMDModImmFP (Dst, DstSize, DefBits, MIRBuilder)))
5801
+ return NewOp;
5802
+
5803
+ DefBits = ~DefBits;
5804
+ Inv = true ;
5805
+ if ((NewOp =
5806
+ tryAdvSIMDModImm32 (Dst, DstSize, DefBits, MIRBuilder, Inv)) ||
5807
+ (NewOp =
5808
+ tryAdvSIMDModImm321s (Dst, DstSize, DefBits, MIRBuilder, Inv)) ||
5809
+ (NewOp = tryAdvSIMDModImm16 (Dst, DstSize, DefBits, MIRBuilder, Inv)))
5810
+ return NewOp;
5811
+ return nullptr ;
5812
+ };
5799
5813
5800
- DefBits = ~DefBits;
5801
- Inv = true ;
5802
- if ((NewOp = tryAdvSIMDModImm32 (Dst, DstSize, DefBits, MIRBuilder, Inv)) ||
5803
- (NewOp =
5804
- tryAdvSIMDModImm321s (Dst, DstSize, DefBits, MIRBuilder, Inv)) ||
5805
- (NewOp = tryAdvSIMDModImm16 (Dst, DstSize, DefBits, MIRBuilder, Inv)))
5814
+ if (auto *NewOp = TryMOVIWithBits (DefBits))
5806
5815
return NewOp;
5816
+
5817
+ // See if a fneg of the constant can be materialized with a MOVI, etc
5818
+ auto TryWithFNeg = [&](APInt DefBits, int NumBits,
5819
+ unsigned NegOpc) -> MachineInstr * {
5820
+ // FNegate each sub-element of the constant
5821
+ APInt Neg = APInt::getHighBitsSet (NumBits, 1 ).zext (DstSize);
5822
+ APInt NegBits (DstSize, 0 );
5823
+ unsigned NumElts = DstSize / NumBits;
5824
+ for (unsigned i = 0 ; i < NumElts; i++)
5825
+ NegBits |= Neg << (NumBits * i);
5826
+ NegBits = DefBits ^ NegBits;
5827
+
5828
+ // Try to create the new constants with MOVI, and if so generate a fneg
5829
+ // for it.
5830
+ if (auto *NewOp = TryMOVIWithBits (NegBits)) {
5831
+ Register NewDst = MRI.createVirtualRegister (&AArch64::FPR128RegClass);
5832
+ NewOp->getOperand (0 ).setReg (NewDst);
5833
+ return MIRBuilder.buildInstr (NegOpc, {Dst}, {NewDst});
5834
+ }
5835
+ return nullptr ;
5836
+ };
5837
+ MachineInstr *R;
5838
+ if ((R = TryWithFNeg (DefBits, 32 , AArch64::FNEGv4f32)) ||
5839
+ (R = TryWithFNeg (DefBits, 64 , AArch64::FNEGv2f64)) ||
5840
+ (STI.hasFullFP16 () &&
5841
+ (R = TryWithFNeg (DefBits, 16 , AArch64::FNEGv8f16))))
5842
+ return R;
5807
5843
}
5808
5844
5809
5845
auto *CPLoad = emitLoadFromConstantPool (CV, MIRBuilder);
0 commit comments