@@ -5758,24 +5758,60 @@ AArch64InstructionSelector::emitConstantVector(Register Dst, Constant *CV,
5758
5758
5759
5759
if (CV->getSplatValue ()) {
5760
5760
APInt DefBits = APInt::getSplat (DstSize, CV->getUniqueInteger ());
5761
- MachineInstr *NewOp;
5762
- bool Inv = false ;
5763
- if ((NewOp = tryAdvSIMDModImm64 (Dst, DstSize, DefBits, MIRBuilder)) ||
5764
- (NewOp = tryAdvSIMDModImm32 (Dst, DstSize, DefBits, MIRBuilder, Inv)) ||
5765
- (NewOp =
5766
- tryAdvSIMDModImm321s (Dst, DstSize, DefBits, MIRBuilder, Inv)) ||
5767
- (NewOp = tryAdvSIMDModImm16 (Dst, DstSize, DefBits, MIRBuilder, Inv)) ||
5768
- (NewOp = tryAdvSIMDModImm8 (Dst, DstSize, DefBits, MIRBuilder)) ||
5769
- (NewOp = tryAdvSIMDModImmFP (Dst, DstSize, DefBits, MIRBuilder)))
5770
- return NewOp;
5761
+ auto TryMOVIWithBits = [&](APInt DefBits) -> MachineInstr * {
5762
+ MachineInstr *NewOp;
5763
+ bool Inv = false ;
5764
+ if ((NewOp = tryAdvSIMDModImm64 (Dst, DstSize, DefBits, MIRBuilder)) ||
5765
+ (NewOp =
5766
+ tryAdvSIMDModImm32 (Dst, DstSize, DefBits, MIRBuilder, Inv)) ||
5767
+ (NewOp =
5768
+ tryAdvSIMDModImm321s (Dst, DstSize, DefBits, MIRBuilder, Inv)) ||
5769
+ (NewOp =
5770
+ tryAdvSIMDModImm16 (Dst, DstSize, DefBits, MIRBuilder, Inv)) ||
5771
+ (NewOp = tryAdvSIMDModImm8 (Dst, DstSize, DefBits, MIRBuilder)) ||
5772
+ (NewOp = tryAdvSIMDModImmFP (Dst, DstSize, DefBits, MIRBuilder)))
5773
+ return NewOp;
5774
+
5775
+ DefBits = ~DefBits;
5776
+ Inv = true ;
5777
+ if ((NewOp =
5778
+ tryAdvSIMDModImm32 (Dst, DstSize, DefBits, MIRBuilder, Inv)) ||
5779
+ (NewOp =
5780
+ tryAdvSIMDModImm321s (Dst, DstSize, DefBits, MIRBuilder, Inv)) ||
5781
+ (NewOp = tryAdvSIMDModImm16 (Dst, DstSize, DefBits, MIRBuilder, Inv)))
5782
+ return NewOp;
5783
+ return nullptr ;
5784
+ };
5771
5785
5772
- DefBits = ~DefBits;
5773
- Inv = true ;
5774
- if ((NewOp = tryAdvSIMDModImm32 (Dst, DstSize, DefBits, MIRBuilder, Inv)) ||
5775
- (NewOp =
5776
- tryAdvSIMDModImm321s (Dst, DstSize, DefBits, MIRBuilder, Inv)) ||
5777
- (NewOp = tryAdvSIMDModImm16 (Dst, DstSize, DefBits, MIRBuilder, Inv)))
5786
+ if (auto *NewOp = TryMOVIWithBits (DefBits))
5778
5787
return NewOp;
5788
+
5789
+ // See if a fneg of the constant can be materialized with a MOVI, etc
5790
+ auto TryWithFNeg = [&](APInt DefBits, int NumBits,
5791
+ unsigned NegOpc) -> MachineInstr * {
5792
+ // FNegate each sub-element of the constant
5793
+ APInt Neg = APInt::getHighBitsSet (NumBits, 1 ).zext (DstSize);
5794
+ APInt NegBits (DstSize, 0 );
5795
+ unsigned NumElts = DstSize / NumBits;
5796
+ for (unsigned i = 0 ; i < NumElts; i++)
5797
+ NegBits |= Neg << (NumBits * i);
5798
+ NegBits = DefBits ^ NegBits;
5799
+
5800
+ // Try to create the new constants with MOVI, and if so generate a fneg
5801
+ // for it.
5802
+ if (auto *NewOp = TryMOVIWithBits (NegBits)) {
5803
+ Register NewDst = MRI.createVirtualRegister (&AArch64::FPR128RegClass);
5804
+ NewOp->getOperand (0 ).setReg (NewDst);
5805
+ return MIRBuilder.buildInstr (NegOpc, {Dst}, {NewDst});
5806
+ }
5807
+ return nullptr ;
5808
+ };
5809
+ MachineInstr *R;
5810
+ if ((R = TryWithFNeg (DefBits, 32 , AArch64::FNEGv4f32)) ||
5811
+ (R = TryWithFNeg (DefBits, 64 , AArch64::FNEGv2f64)) ||
5812
+ (STI.hasFullFP16 () &&
5813
+ (R = TryWithFNeg (DefBits, 16 , AArch64::FNEGv8f16))))
5814
+ return R;
5779
5815
}
5780
5816
5781
5817
auto *CPLoad = emitLoadFromConstantPool (CV, MIRBuilder);
0 commit comments