llvm.org GIT mirror llvm / 73f9a1d
Revert r351778: IR: Add fp operations to atomicrmw This broke the RISCV build, and even with that fixed, one of the RISCV tests behaves surprisingly differently with asserts than without, leaving there no clear test pattern to use. Generally it seems bad for hte IR to differ substantially due to asserts (as in, an alloca is used with asserts that isn't needed without!) and nothing I did simply would fix it so I'm reverting back to green. This also required reverting the RISCV build fix in r351782. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351796 91177308-0d34-0410-b5e6-96231b3b80d8 Chandler Carruth 8 months ago
26 changed file(s) with 22 addition(s) and 395 deletion(s). Raw diff Collapse all Expand all
86668666 - min
86678667 - umax
86688668 - umin
8669 - fadd
8670 - fsub
86718669
86728670 For most of these operations, the type of '' must be an integer
86738671 type whose bit width is a power of two greater than or equal to eight
86748672 and less than or equal to a target-specific size limit. For xchg, this
86758673 may also be a floating point type with the same size constraints as
8676 integers. For fadd/fsub, this must be a floating point type. The
8677 type of the '````' operand must be a pointer to that type. If
8678 the ``atomicrmw`` is marked as ``volatile``, then the optimizer is not
8679 allowed to modify the number or order of execution of this
8680 ``atomicrmw`` with other :ref:`volatile operations `.
8674 integers. The type of the '````' operand must be a pointer to
8675 that type. If the ``atomicrmw`` is marked as ``volatile``, then the
8676 optimizer is not allowed to modify the number or order of execution of
8677 this ``atomicrmw`` with other :ref:`volatile operations `.
86818678
86828679 A ``atomicrmw`` instruction can also take an optional
86838680 ":ref:`syncscope `" argument.
87038700 comparison)
87048701 - umin: ``*ptr = *ptr < val ? *ptr : val`` (using an unsigned
87058702 comparison)
8706 - fadd: ``*ptr = *ptr + val`` (using floating point arithmetic)
8707 - fsub: ``*ptr = *ptr - val`` (using floating point arithmetic)
87088703
87098704 Example:
87108705 """"""""
405405 RMW_MAX = 7,
406406 RMW_MIN = 8,
407407 RMW_UMAX = 9,
408 RMW_UMIN = 10,
409 RMW_FADD = 11,
410 RMW_FSUB = 12
408 RMW_UMIN = 10
411409 };
412410
413411 /// OverflowingBinaryOperatorOptionalFlags - Flags for serializing
17141714
17151715 /// Returns how the IR-level AtomicExpand pass should expand the given
17161716 /// AtomicRMW, if at all. Default is to never expand.
1717 virtual AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const {
1718 return RMW->isFloatingPointOperation() ?
1719 AtomicExpansionKind::CmpXChg : AtomicExpansionKind::None;
1717 virtual AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *) const {
1718 return AtomicExpansionKind::None;
17201719 }
17211720
17221721 /// On some platforms, an AtomicRMW that never actually modifies the value
723723 /// *p = old
724724 UMin,
725725
726 /// *p = old + v
727 FAdd,
728
729 /// *p = old - v
730 FSub,
731
732726 FIRST_BINOP = Xchg,
733 LAST_BINOP = FSub,
727 LAST_BINOP = UMin,
734728 BAD_BINOP
735729 };
736730
752746
753747 static StringRef getOperationName(BinOp Op);
754748
755 static bool isFPOperation(BinOp Op) {
756 switch (Op) {
757 case AtomicRMWInst::FAdd:
758 case AtomicRMWInst::FSub:
759 return true;
760 default:
761 return false;
762 }
763 }
764
765749 void setOperation(BinOp Operation) {
766750 unsigned short SubclassData = getSubclassDataFromInstruction();
767751 setInstructionSubclassData((SubclassData & 31) |
817801 /// Returns the address space of the pointer operand.
818802 unsigned getPointerAddressSpace() const {
819803 return getPointerOperand()->getType()->getPointerAddressSpace();
820 }
821
822 bool isFloatingPointOperation() const {
823 return isFPOperation(getOperation());
824804 }
825805
826806 // Methods for support type inquiry through isa, cast, and dyn_cast:
68146814 AtomicOrdering Ordering = AtomicOrdering::NotAtomic;
68156815 SyncScope::ID SSID = SyncScope::System;
68166816 bool isVolatile = false;
6817 bool IsFP = false;
68186817 AtomicRMWInst::BinOp Operation;
68196818
68206819 if (EatIfPresent(lltok::kw_volatile))
68336832 case lltok::kw_min: Operation = AtomicRMWInst::Min; break;
68346833 case lltok::kw_umax: Operation = AtomicRMWInst::UMax; break;
68356834 case lltok::kw_umin: Operation = AtomicRMWInst::UMin; break;
6836 case lltok::kw_fadd:
6837 Operation = AtomicRMWInst::FAdd;
6838 IsFP = true;
6839 break;
6840 case lltok::kw_fsub:
6841 Operation = AtomicRMWInst::FSub;
6842 IsFP = true;
6843 break;
68446835 }
68456836 Lex.Lex(); // Eat the operation.
68466837
68576848 if (cast(Ptr->getType())->getElementType() != Val->getType())
68586849 return Error(ValLoc, "atomicrmw value and pointer type do not match");
68596850
6860 if (Operation == AtomicRMWInst::Xchg) {
6861 if (!Val->getType()->isIntegerTy() &&
6862 !Val->getType()->isFloatingPointTy()) {
6863 return Error(ValLoc, "atomicrmw " +
6864 AtomicRMWInst::getOperationName(Operation) +
6865 " operand must be an integer or floating point type");
6866 }
6867 } else if (IsFP) {
6868 if (!Val->getType()->isFloatingPointTy()) {
6869 return Error(ValLoc, "atomicrmw " +
6870 AtomicRMWInst::getOperationName(Operation) +
6871 " operand must be a floating point type");
6872 }
6873 } else {
6874 if (!Val->getType()->isIntegerTy()) {
6875 return Error(ValLoc, "atomicrmw " +
6876 AtomicRMWInst::getOperationName(Operation) +
6877 " operand must be an integer");
6878 }
6851 if (Operation != AtomicRMWInst::Xchg && !Val->getType()->isIntegerTy()) {
6852 return Error(ValLoc, "atomicrmw " +
6853 AtomicRMWInst::getOperationName(Operation) +
6854 " operand must be an integer");
6855 }
6856
6857 if (Operation == AtomicRMWInst::Xchg &&
6858 !Val->getType()->isIntegerTy() &&
6859 !Val->getType()->isFloatingPointTy()) {
6860 return Error(ValLoc, "atomicrmw " +
6861 AtomicRMWInst::getOperationName(Operation) +
6862 " operand must be an integer or floating point type");
68796863 }
68806864
68816865 unsigned Size = Val->getType()->getPrimitiveSizeInBits();
10331033 case bitc::RMW_MIN: return AtomicRMWInst::Min;
10341034 case bitc::RMW_UMAX: return AtomicRMWInst::UMax;
10351035 case bitc::RMW_UMIN: return AtomicRMWInst::UMin;
1036 case bitc::RMW_FADD: return AtomicRMWInst::FAdd;
1037 case bitc::RMW_FSUB: return AtomicRMWInst::FSub;
10381036 }
10391037 }
10401038
558558 case AtomicRMWInst::Min: return bitc::RMW_MIN;
559559 case AtomicRMWInst::UMax: return bitc::RMW_UMAX;
560560 case AtomicRMWInst::UMin: return bitc::RMW_UMIN;
561 case AtomicRMWInst::FAdd: return bitc::RMW_FADD;
562 case AtomicRMWInst::FSub: return bitc::RMW_FSUB;
563561 }
564562 }
565563
548548 case AtomicRMWInst::UMin:
549549 NewVal = Builder.CreateICmpULE(Loaded, Inc);
550550 return Builder.CreateSelect(NewVal, Loaded, Inc, "new");
551 case AtomicRMWInst::FAdd:
552 return Builder.CreateFAdd(Loaded, Inc, "new");
553 case AtomicRMWInst::FSub:
554 return Builder.CreateFSub(Loaded, Inc, "new");
555551 default:
556552 llvm_unreachable("Unknown atomic op");
557553 }
15501546 case AtomicRMWInst::Min:
15511547 case AtomicRMWInst::UMax:
15521548 case AtomicRMWInst::UMin:
1553 case AtomicRMWInst::FAdd:
1554 case AtomicRMWInst::FSub:
15551549 // No atomic libcalls are available for max/min/umax/umin.
15561550 return {};
15571551 }
14061406 return "umax";
14071407 case AtomicRMWInst::UMin:
14081408 return "umin";
1409 case AtomicRMWInst::FAdd:
1410 return "fadd";
1411 case AtomicRMWInst::FSub:
1412 return "fsub";
14131409 case AtomicRMWInst::BAD_BINOP:
14141410 return "";
14151411 }
34343434 AtomicRMWInst::getOperationName(Op) +
34353435 " operand must have integer or floating point type!",
34363436 &RMWI, ElTy);
3437 } else if (AtomicRMWInst::isFPOperation(Op)) {
3438 Assert(ElTy->isFloatingPointTy(), "atomicrmw " +
3439 AtomicRMWInst::getOperationName(Op) +
3440 " operand must have floating point type!",
3441 &RMWI, ElTy);
34423437 } else {
34433438 Assert(ElTy->isIntegerTy(), "atomicrmw " +
34443439 AtomicRMWInst::getOperationName(Op) +
1159911599 // For the real atomic operations, we have ldxr/stxr up to 128 bits,
1160011600 TargetLowering::AtomicExpansionKind
1160111601 AArch64TargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const {
11602 if (AI->isFloatingPointOperation())
11603 return AtomicExpansionKind::CmpXChg;
11604
1160511602 unsigned Size = AI->getType()->getPrimitiveSizeInBits();
1160611603 if (Size > 128) return AtomicExpansionKind::None;
1160711604 // Nand not supported in LSE.
1464414644 // and up to 64 bits on the non-M profiles
1464514645 TargetLowering::AtomicExpansionKind
1464614646 ARMTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const {
14647 if (AI->isFloatingPointOperation())
14648 return AtomicExpansionKind::CmpXChg;
14649
1465014647 unsigned Size = AI->getType()->getPrimitiveSizeInBits();
1465114648 bool hasAtomicRMW = !Subtarget->isThumb() || Subtarget->hasV8MBaselineOps();
1465214649 return (Size <= (Subtarget->isMClass() ? 32U : 64U) && hasAtomicRMW)
31093109 AtomicOrdering Ord) const {
31103110 BasicBlock *BB = Builder.GetInsertBlock();
31113111 Module *M = BB->getParent()->getParent();
3112 auto PT = cast(Addr->getType());
3113 Type *Ty = PT->getElementType();
3112 Type *Ty = cast(Addr->getType())->getElementType();
31143113 unsigned SZ = Ty->getPrimitiveSizeInBits();
31153114 assert((SZ == 32 || SZ == 64) && "Only 32/64-bit atomic loads supported");
31163115 Intrinsic::ID IntID = (SZ == 32) ? Intrinsic::hexagon_L2_loadw_locked
31173116 : Intrinsic::hexagon_L4_loadd_locked;
3118
3119 PointerType *NewPtrTy
3120 = Builder.getIntNTy(SZ)->getPointerTo(PT->getAddressSpace());
3121 Addr = Builder.CreateBitCast(Addr, NewPtrTy);
3122
31233117 Value *Fn = Intrinsic::getDeclaration(M, IntID);
3124 Value *Call = Builder.CreateCall(Fn, Addr, "larx");
3125
3126 return Builder.CreateBitCast(Call, Ty);
3118 return Builder.CreateCall(Fn, Addr, "larx");
31273119 }
31283120
31293121 /// Perform a store-conditional operation to Addr. Return the status of the
31343126 Module *M = BB->getParent()->getParent();
31353127 Type *Ty = Val->getType();
31363128 unsigned SZ = Ty->getPrimitiveSizeInBits();
3137
3138 Type *CastTy = Builder.getIntNTy(SZ);
31393129 assert((SZ == 32 || SZ == 64) && "Only 32/64-bit atomic stores supported");
31403130 Intrinsic::ID IntID = (SZ == 32) ? Intrinsic::hexagon_S2_storew_locked
31413131 : Intrinsic::hexagon_S4_stored_locked;
31423132 Value *Fn = Intrinsic::getDeclaration(M, IntID);
3143
3144 unsigned AS = Addr->getType()->getPointerAddressSpace();
3145 Addr = Builder.CreateBitCast(Addr, CastTy->getPointerTo(AS));
3146 Val = Builder.CreateBitCast(Val, CastTy);
3147
31483133 Value *Call = Builder.CreateCall(Fn, {Addr, Val}, "stcx");
31493134 Value *Cmp = Builder.CreateICmpEQ(Call, Builder.getInt32(0), "");
31503135 Value *Ext = Builder.CreateZExt(Cmp, Type::getInt32Ty(M->getContext()));
17191719
17201720 TargetLowering::AtomicExpansionKind
17211721 RISCVTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const {
1722 // atomicrmw {fadd,fsub} must be expanded to use compare-exchange, as
1723 // floating point operations can't be used in an lr/sc sequence without
1724 // brekaing the forward-progress guarantee.
1725 if (AI->isFloatingPointOperation())
1726 return AtomicExpansionKind::CmpXChg;
1727
17281722 unsigned Size = AI->getType()->getPrimitiveSizeInBits();
17291723 if (Size == 8 || Size == 16)
17301724 return AtomicExpansionKind::MaskedIntrinsic;
3838 fence syncscope("device") seq_cst
3939 ret void
4040 }
41
42 define void @fp_atomics(float* %x) {
43 ; CHECK: atomicrmw fadd float* %x, float 1.000000e+00 seq_cst
44 atomicrmw fadd float* %x, float 1.0 seq_cst
45
46 ; CHECK: atomicrmw volatile fadd float* %x, float 1.000000e+00 seq_cst
47 atomicrmw volatile fadd float* %x, float 1.0 seq_cst
48
49 ret void
50 }
+0
-7
test/Assembler/invalid-atomicrmw-fadd-must-be-fp-type.ll less more
None ; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
1
2 ; CHECK: error: atomicrmw fadd operand must be a floating point type
3 define void @f(i32* %ptr) {
4 atomicrmw fadd i32* %ptr, i32 2 seq_cst
5 ret void
6 }
+0
-7
test/Assembler/invalid-atomicrmw-fsub-must-be-fp-type.ll less more
None ; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
1
2 ; CHECK: error: atomicrmw fsub operand must be a floating point type
3 define void @f(i32* %ptr) {
4 atomicrmw fsub i32* %ptr, i32 2 seq_cst
5 ret void
6 }
763763 define void @fp_atomics(float* %word) {
764764 ; CHECK: %atomicrmw.xchg = atomicrmw xchg float* %word, float 1.000000e+00 monotonic
765765 %atomicrmw.xchg = atomicrmw xchg float* %word, float 1.0 monotonic
766
767 ; CHECK: %atomicrmw.fadd = atomicrmw fadd float* %word, float 1.000000e+00 monotonic
768 %atomicrmw.fadd = atomicrmw fadd float* %word, float 1.0 monotonic
769
770 ; CHECK: %atomicrmw.fsub = atomicrmw fsub float* %word, float 1.000000e+00 monotonic
771 %atomicrmw.fsub = atomicrmw fsub float* %word, float 1.0 monotonic
772
773766 ret void
774767 }
775768
+0
-47
test/Transforms/AtomicExpand/AArch64/atomicrmw-fp.ll less more
None ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
1 ; RUN: opt -S -mtriple=aarch64-linux-gnu -atomic-expand %s | FileCheck %s
2
3 define float @test_atomicrmw_fadd_f32(float* %ptr, float %value) {
4 ; CHECK-LABEL: @test_atomicrmw_fadd_f32(
5 ; CHECK-NEXT: [[TMP1:%.*]] = load float, float* [[PTR:%.*]], align 4
6 ; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]]
7 ; CHECK: atomicrmw.start:
8 ; CHECK-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ]
9 ; CHECK-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]]
10 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float* [[PTR]] to i32*
11 ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[NEW]] to i32
12 ; CHECK-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32
13 ; CHECK-NEXT: [[TMP5:%.*]] = cmpxchg i32* [[TMP2]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst
14 ; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
15 ; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
16 ; CHECK-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to float
17 ; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
18 ; CHECK: atomicrmw.end:
19 ; CHECK-NEXT: ret float [[TMP6]]
20 ;
21 %res = atomicrmw fadd float* %ptr, float %value seq_cst
22 ret float %res
23 }
24
25 define float @test_atomicrmw_fsub_f32(float* %ptr, float %value) {
26 ; CHECK-LABEL: @test_atomicrmw_fsub_f32(
27 ; CHECK-NEXT: [[TMP1:%.*]] = load float, float* [[PTR:%.*]], align 4
28 ; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]]
29 ; CHECK: atomicrmw.start:
30 ; CHECK-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ]
31 ; CHECK-NEXT: [[NEW:%.*]] = fsub float [[LOADED]], [[VALUE:%.*]]
32 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float* [[PTR]] to i32*
33 ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[NEW]] to i32
34 ; CHECK-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32
35 ; CHECK-NEXT: [[TMP5:%.*]] = cmpxchg i32* [[TMP2]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst
36 ; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
37 ; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
38 ; CHECK-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to float
39 ; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
40 ; CHECK: atomicrmw.end:
41 ; CHECK-NEXT: ret float [[TMP6]]
42 ;
43 %res = atomicrmw fsub float* %ptr, float %value seq_cst
44 ret float %res
45 }
46
+0
-51
test/Transforms/AtomicExpand/ARM/atomicrmw-fp.ll less more
None ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
1 ; RUN: opt -S -mtriple=armv7-apple-ios7.0 -atomic-expand %s | FileCheck %s
2
3 define float @test_atomicrmw_fadd_f32(float* %ptr, float %value) {
4 ; CHECK-LABEL: @test_atomicrmw_fadd_f32(
5 ; CHECK-NEXT: call void @llvm.arm.dmb(i32 11)
6 ; CHECK-NEXT: [[TMP1:%.*]] = load float, float* [[PTR:%.*]], align 4
7 ; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]]
8 ; CHECK: atomicrmw.start:
9 ; CHECK-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ]
10 ; CHECK-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]]
11 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float* [[PTR]] to i32*
12 ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[NEW]] to i32
13 ; CHECK-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32
14 ; CHECK-NEXT: [[TMP5:%.*]] = cmpxchg i32* [[TMP2]], i32 [[TMP4]], i32 [[TMP3]] monotonic monotonic
15 ; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
16 ; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
17 ; CHECK-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to float
18 ; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
19 ; CHECK: atomicrmw.end:
20 ; CHECK-NEXT: call void @llvm.arm.dmb(i32 11)
21 ; CHECK-NEXT: ret float [[TMP6]]
22 ;
23 %res = atomicrmw fadd float* %ptr, float %value seq_cst
24 ret float %res
25 }
26
27 define float @test_atomicrmw_fsub_f32(float* %ptr, float %value) {
28 ; CHECK-LABEL: @test_atomicrmw_fsub_f32(
29 ; CHECK-NEXT: call void @llvm.arm.dmb(i32 11)
30 ; CHECK-NEXT: [[TMP1:%.*]] = load float, float* [[PTR:%.*]], align 4
31 ; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]]
32 ; CHECK: atomicrmw.start:
33 ; CHECK-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ]
34 ; CHECK-NEXT: [[NEW:%.*]] = fsub float [[LOADED]], [[VALUE:%.*]]
35 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float* [[PTR]] to i32*
36 ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[NEW]] to i32
37 ; CHECK-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32
38 ; CHECK-NEXT: [[TMP5:%.*]] = cmpxchg i32* [[TMP2]], i32 [[TMP4]], i32 [[TMP3]] monotonic monotonic
39 ; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
40 ; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
41 ; CHECK-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to float
42 ; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
43 ; CHECK: atomicrmw.end:
44 ; CHECK-NEXT: call void @llvm.arm.dmb(i32 11)
45 ; CHECK-NEXT: ret float [[TMP6]]
46 ;
47 %res = atomicrmw fsub float* %ptr, float %value seq_cst
48 ret float %res
49 }
50
+0
-47
test/Transforms/AtomicExpand/Hexagon/atomicrmw-fp.ll less more
None ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
1 ; RUN: opt -S -mtriple=hexagon-- -atomic-expand %s | FileCheck %s
2
3 define float @test_atomicrmw_fadd_f32(float* %ptr, float %value) {
4 ; CHECK-LABEL: @test_atomicrmw_fadd_f32(
5 ; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]]
6 ; CHECK: atomicrmw.start:
7 ; CHECK-NEXT: [[TMP1:%.*]] = bitcast float* [[PTR:%.*]] to i32*
8 ; CHECK-NEXT: [[LARX:%.*]] = call i32 @llvm.hexagon.L2.loadw.locked(i32* [[TMP1]])
9 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast i32 [[LARX]] to float
10 ; CHECK-NEXT: [[NEW:%.*]] = fadd float [[TMP2]], [[VALUE:%.*]]
11 ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float* [[PTR]] to i32*
12 ; CHECK-NEXT: [[TMP4:%.*]] = bitcast float [[NEW]] to i32
13 ; CHECK-NEXT: [[STCX:%.*]] = call i32 @llvm.hexagon.S2.storew.locked(i32* [[TMP3]], i32 [[TMP4]])
14 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[STCX]], 0
15 ; CHECK-NEXT: [[TMP6:%.*]] = zext i1 [[TMP5]] to i32
16 ; CHECK-NEXT: [[TRYAGAIN:%.*]] = icmp ne i32 [[TMP6]], 0
17 ; CHECK-NEXT: br i1 [[TRYAGAIN]], label [[ATOMICRMW_START]], label [[ATOMICRMW_END:%.*]]
18 ; CHECK: atomicrmw.end:
19 ; CHECK-NEXT: ret float [[TMP2]]
20 ;
21 %res = atomicrmw fadd float* %ptr, float %value seq_cst
22 ret float %res
23 }
24
25 define float @test_atomicrmw_fsub_f32(float* %ptr, float %value) {
26 ; CHECK-LABEL: @test_atomicrmw_fsub_f32(
27 ; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]]
28 ; CHECK: atomicrmw.start:
29 ; CHECK-NEXT: [[TMP1:%.*]] = bitcast float* [[PTR:%.*]] to i32*
30 ; CHECK-NEXT: [[LARX:%.*]] = call i32 @llvm.hexagon.L2.loadw.locked(i32* [[TMP1]])
31 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast i32 [[LARX]] to float
32 ; CHECK-NEXT: [[NEW:%.*]] = fsub float [[TMP2]], [[VALUE:%.*]]
33 ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float* [[PTR]] to i32*
34 ; CHECK-NEXT: [[TMP4:%.*]] = bitcast float [[NEW]] to i32
35 ; CHECK-NEXT: [[STCX:%.*]] = call i32 @llvm.hexagon.S2.storew.locked(i32* [[TMP3]], i32 [[TMP4]])
36 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[STCX]], 0
37 ; CHECK-NEXT: [[TMP6:%.*]] = zext i1 [[TMP5]] to i32
38 ; CHECK-NEXT: [[TRYAGAIN:%.*]] = icmp ne i32 [[TMP6]], 0
39 ; CHECK-NEXT: br i1 [[TRYAGAIN]], label [[ATOMICRMW_START]], label [[ATOMICRMW_END:%.*]]
40 ; CHECK: atomicrmw.end:
41 ; CHECK-NEXT: ret float [[TMP2]]
42 ;
43 %res = atomicrmw fsub float* %ptr, float %value seq_cst
44 ret float %res
45 }
46
+0
-2
test/Transforms/AtomicExpand/Hexagon/lit.local.cfg less more
None if not 'Hexagon' in config.root.targets:
1 config.unsupported = True
+0
-51
test/Transforms/AtomicExpand/Mips/atomicrmw-fp.ll less more
None ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
1 ; RUN: opt -S -mtriple=mips64-mti-linux-gnu -atomic-expand %s | FileCheck %s
2
3 define float @test_atomicrmw_fadd_f32(float* %ptr, float %value) {
4 ; CHECK-LABEL: @test_atomicrmw_fadd_f32(
5 ; CHECK-NEXT: fence seq_cst
6 ; CHECK-NEXT: [[TMP1:%.*]] = load float, float* [[PTR:%.*]], align 4
7 ; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]]
8 ; CHECK: atomicrmw.start:
9 ; CHECK-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ]
10 ; CHECK-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]]
11 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float* [[PTR]] to i32*
12 ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[NEW]] to i32
13 ; CHECK-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32
14 ; CHECK-NEXT: [[TMP5:%.*]] = cmpxchg i32* [[TMP2]], i32 [[TMP4]], i32 [[TMP3]] monotonic monotonic
15 ; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
16 ; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
17 ; CHECK-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to float
18 ; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
19 ; CHECK: atomicrmw.end:
20 ; CHECK-NEXT: fence seq_cst
21 ; CHECK-NEXT: ret float [[TMP6]]
22 ;
23 %res = atomicrmw fadd float* %ptr, float %value seq_cst
24 ret float %res
25 }
26
27 define float @test_atomicrmw_fsub_f32(float* %ptr, float %value) {
28 ; CHECK-LABEL: @test_atomicrmw_fsub_f32(
29 ; CHECK-NEXT: fence seq_cst
30 ; CHECK-NEXT: [[TMP1:%.*]] = load float, float* [[PTR:%.*]], align 4
31 ; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]]
32 ; CHECK: atomicrmw.start:
33 ; CHECK-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ]
34 ; CHECK-NEXT: [[NEW:%.*]] = fsub float [[LOADED]], [[VALUE:%.*]]
35 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float* [[PTR]] to i32*
36 ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[NEW]] to i32
37 ; CHECK-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32
38 ; CHECK-NEXT: [[TMP5:%.*]] = cmpxchg i32* [[TMP2]], i32 [[TMP4]], i32 [[TMP3]] monotonic monotonic
39 ; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
40 ; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
41 ; CHECK-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to float
42 ; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
43 ; CHECK: atomicrmw.end:
44 ; CHECK-NEXT: fence seq_cst
45 ; CHECK-NEXT: ret float [[TMP6]]
46 ;
47 %res = atomicrmw fsub float* %ptr, float %value seq_cst
48 ret float %res
49 }
50
+0
-2
test/Transforms/AtomicExpand/Mips/lit.local.cfg less more
None if not 'Mips' in config.root.targets:
1 config.unsupported = True
+0
-47
test/Transforms/AtomicExpand/RISCV/atomicrmw-fp.ll less more
None ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
1 ; RUN: opt -S -mtriple=riscv32-- -atomic-expand %s | FileCheck %s
2
3 define float @test_atomicrmw_fadd_f32(float* %ptr, float %value) {
4 ; CHECK-LABEL: @test_atomicrmw_fadd_f32(
5 ; CHECK-NEXT: [[TMP1:%.*]] = load float, float* [[PTR:%.*]], align 4
6 ; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]]
7 ; CHECK: atomicrmw.start:
8 ; CHECK-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ]
9 ; CHECK-NEXT: [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]]
10 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float* [[PTR]] to i32*
11 ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[NEW]] to i32
12 ; CHECK-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32
13 ; CHECK-NEXT: [[TMP5:%.*]] = cmpxchg i32* [[TMP2]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst
14 ; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
15 ; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
16 ; CHECK-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to float
17 ; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
18 ; CHECK: atomicrmw.end:
19 ; CHECK-NEXT: ret float [[TMP6]]
20 ;
21 %res = atomicrmw fadd float* %ptr, float %value seq_cst
22 ret float %res
23 }
24
25 define float @test_atomicrmw_fsub_f32(float* %ptr, float %value) {
26 ; CHECK-LABEL: @test_atomicrmw_fsub_f32(
27 ; CHECK-NEXT: [[TMP1:%.*]] = load float, float* [[PTR:%.*]], align 4
28 ; CHECK-NEXT: br label [[ATOMIxbCRMW_START:%.*]]
29 ; CHECK: atomicrmw.start:
30 ; CHECK-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ]
31 ; CHECK-NEXT: [[NEW:%.*]] = fsub float [[LOADED]], [[VALUE:%.*]]
32 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float* [[PTR]] to i32*
33 ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[NEW]] to i32
34 ; CHECK-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32
35 ; CHECK-NEXT: [[TMP5:%.*]] = cmpxchg i32* [[TMP2]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst
36 ; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
37 ; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
38 ; CHECK-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to float
39 ; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
40 ; CHECK: atomicrmw.end:
41 ; CHECK-NEXT: ret float [[TMP6]]
42 ;
43 %res = atomicrmw fsub float* %ptr, float %value seq_cst
44 ret float %res
45 }
46
+0
-5
test/Transforms/AtomicExpand/RISCV/lit.local.cfg less more
None config.suffixes = ['.ll']
1
2 targets = set(config.root.targets_to_build.split())
3 if not 'RISCV' in targets:
4 config.unsupported = True