@@ -5751,6 +5751,58 @@ bool LoongArchTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
57515751 }
57525752}
57535753
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+
57545806TargetLowering::AtomicExpansionKind
57555807LoongArchTargetLowering::shouldExpandAtomicRMWInIR (AtomicRMWInst *AI) const {
57565808 // TODO: Add more AtomicRMWInst that needs to be extended.
@@ -5772,9 +5824,14 @@ LoongArchTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const {
57725824 }
57735825
57745826 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+ }
57785835
57795836 if (Size == 8 || Size == 16 )
57805837 return AtomicExpansionKind::MaskedIntrinsic;
0 commit comments