@@ -5751,6 +5751,58 @@ bool LoongArchTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
5751
5751
}
5752
5752
}
5753
5753
5754
+ void LoongArchTargetLowering::emitExpandAtomicRMW (AtomicRMWInst *AI) const {
5755
+ AtomicRMWInst::BinOp Op = AI->getOperation ();
5756
+
5757
+ assert ((Op == AtomicRMWInst::Or || Op == AtomicRMWInst::Xor ||
5758
+ Op == AtomicRMWInst::And) &&
5759
+ " Unable to expand" );
5760
+ unsigned MinWordSize = 4 ;
5761
+
5762
+ IRBuilder<> Builder (AI);
5763
+ LLVMContext &Ctx = Builder.getContext ();
5764
+ const DataLayout &DL = AI->getDataLayout ();
5765
+ Type *ValueType = AI->getType ();
5766
+ Type *WordType = Type::getIntNTy (Ctx, MinWordSize * 8 );
5767
+
5768
+ Value *Addr = AI->getPointerOperand ();
5769
+ PointerType *PtrTy = cast<PointerType>(Addr->getType ());
5770
+ IntegerType *IntTy = DL.getIndexType (Ctx, PtrTy->getAddressSpace ());
5771
+
5772
+ Value *AlignedAddr = Builder.CreateIntrinsic (
5773
+ Intrinsic::ptrmask, {PtrTy, IntTy},
5774
+ {Addr, ConstantInt::get (IntTy, ~(uint64_t )(MinWordSize - 1 ))}, nullptr ,
5775
+ " AlignedAddr" );
5776
+
5777
+ Value *AddrInt = Builder.CreatePtrToInt (Addr, IntTy);
5778
+ Value *PtrLSB = Builder.CreateAnd (AddrInt, MinWordSize - 1 , " PtrLSB" );
5779
+ Value *ShiftAmt = Builder.CreateShl (PtrLSB, 3 );
5780
+ ShiftAmt = Builder.CreateTrunc (ShiftAmt, WordType, " ShiftAmt" );
5781
+ Value *Mask = Builder.CreateShl (
5782
+ ConstantInt::get (WordType,
5783
+ (1 << (DL.getTypeStoreSize (ValueType) * 8 )) - 1 ),
5784
+ ShiftAmt, " Mask" );
5785
+ Value *Inv_Mask = Builder.CreateNot (Mask, " Inv_Mask" );
5786
+ Value *ValOperand_Shifted =
5787
+ Builder.CreateShl (Builder.CreateZExt (AI->getValOperand (), WordType),
5788
+ ShiftAmt, " ValOperand_Shifted" );
5789
+ Value *NewOperand;
5790
+ if (Op == AtomicRMWInst::And)
5791
+ NewOperand = Builder.CreateOr (ValOperand_Shifted, Inv_Mask, " AndOperand" );
5792
+ else
5793
+ NewOperand = ValOperand_Shifted;
5794
+
5795
+ AtomicRMWInst *NewAI =
5796
+ Builder.CreateAtomicRMW (Op, AlignedAddr, NewOperand, Align (MinWordSize),
5797
+ AI->getOrdering (), AI->getSyncScopeID ());
5798
+
5799
+ Value *Shift = Builder.CreateLShr (NewAI, ShiftAmt, " shifted" );
5800
+ Value *Trunc = Builder.CreateTrunc (Shift, ValueType, " extracted" );
5801
+ Value *FinalOldResult = Builder.CreateBitCast (Trunc, ValueType);
5802
+ AI->replaceAllUsesWith (FinalOldResult);
5803
+ AI->eraseFromParent ();
5804
+ }
5805
+
5754
5806
TargetLowering::AtomicExpansionKind
5755
5807
LoongArchTargetLowering::shouldExpandAtomicRMWInIR (AtomicRMWInst *AI) const {
5756
5808
// TODO: Add more AtomicRMWInst that needs to be extended.
@@ -5772,9 +5824,14 @@ LoongArchTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const {
5772
5824
}
5773
5825
5774
5826
unsigned Size = AI->getType ()->getPrimitiveSizeInBits ();
5775
- if (Subtarget.hasLAMCAS () &&
5776
- (AI->getOperation () == AtomicRMWInst::Nand || Size < 32 ))
5777
- return AtomicExpansionKind::CmpXChg;
5827
+ if (Subtarget.hasLAMCAS ()) {
5828
+ if (Size < 32 && (AI->getOperation () == AtomicRMWInst::And ||
5829
+ AI->getOperation () == AtomicRMWInst::Or ||
5830
+ AI->getOperation () == AtomicRMWInst::Xor))
5831
+ return AtomicExpansionKind::Expand;
5832
+ if ((AI->getOperation () == AtomicRMWInst::Nand || Size < 32 ))
5833
+ return AtomicExpansionKind::CmpXChg;
5834
+ }
5778
5835
5779
5836
if (Size == 8 || Size == 16 )
5780
5837
return AtomicExpansionKind::MaskedIntrinsic;
0 commit comments