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