llvm.org GIT mirror llvm / f03bb26
Move "atomic" and "volatile" designations on instructions after the opcode of the instruction. Note that this change affects the existing non-atomic load and store instructions; the parser now accepts both forms, and the change is noted in the release notes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137527 91177308-0d34-0410-b5e6-96231b3b80d8 Eli Friedman 8 years ago
25 changed file(s) with 168 addition(s) and 103 deletion(s). Raw diff Collapse all Expand all
45714571
45724572
Syntax:
45734573

                  
                
4574 <result> = [volatile] load <ty>* <pointer>[, align <alignment>][, !nontemporal !<index>]
4575 <result> = atomic [volatile] load <ty>* <pointer> [singlethread] <ordering>, align <alignment>
4574 <result> = load [volatile] <ty>* <pointer>[, align <alignment>][, !nontemporal !<index>]
4575 <result> = load atomic [volatile] <ty>* <pointer> [singlethread] <ordering>, align <alignment>
45764576 !<index> = !{ i32 1 }
45774577
45784578
46434643
46444644
Syntax:
46454645

                  
                
4646 [volatile] store <ty> <value>, <ty>* <pointer>[, align <alignment>][, !nontemporal !<index>] ; yields {void}
4647 atomic [volatile] store <ty> <value>, <ty>* <pointer> [singlethread] <ordering>, align <alignment> ; yields {void}
4646 store [volatile] <ty> <value>, <ty>* <pointer>[, align <alignment>][, !nontemporal !<index>] ; yields {void}
4647 store atomic [volatile] <ty> <value>, <ty>* <pointer> [singlethread] <ordering>, align <alignment> ; yields {void}
46484648
46494649
46504650
Overview:
47734773
47744774
Syntax:
47754775

                  
                
4776 [volatile] cmpxchg <ty>* <pointer>, <ty> <cmp>, <ty> <new> [singlethread] <ordering> ; yields {ty}
4776 cmpxchg [volatile] <ty>* <pointer>, <ty> <cmp>, <ty> <new> [singlethread] <ordering> ; yields {ty}
47774777
47784778
47794779
Overview:
48564856
48574857
Syntax:
48584858

                  
                
4859 [volatile] atomicrmw <operation> <ty>* <pointer>, <ty> <value> [singlethread] <ordering> ; yields {ty}
4859 atomicrmw [volatile] <operation> <ty>* <pointer>, <ty> <value> [singlethread] <ordering> ; yields {ty}
48604860
48614861
48624862
Overview:
582582
583583
  • The LowerSetJmp pass wasn't used effectively by any
  • 584584 target and has been removed.
    585
  • The syntax of volatile loads and stores in IR has been changed to
  • 586 "load volatile"/"store volatile". The old
    587 syntax ("volatile load"/"volatile store")
    588 is still accepted, but is now considered deprecated.
    585589
    586590
    587591
    29492949 case lltok::kw_tail: return ParseCall(Inst, PFS, true);
    29502950 // Memory.
    29512951 case lltok::kw_alloca: return ParseAlloc(Inst, PFS);
    2952 case lltok::kw_load: return ParseLoad(Inst, PFS, false, false);
    2953 case lltok::kw_store: return ParseStore(Inst, PFS, false, false);
    2954 case lltok::kw_cmpxchg: return ParseCmpXchg(Inst, PFS, false);
    2955 case lltok::kw_atomicrmw: return ParseAtomicRMW(Inst, PFS, false);
    2952 case lltok::kw_load: return ParseLoad(Inst, PFS, false);
    2953 case lltok::kw_store: return ParseStore(Inst, PFS, false);
    2954 case lltok::kw_cmpxchg: return ParseCmpXchg(Inst, PFS);
    2955 case lltok::kw_atomicrmw: return ParseAtomicRMW(Inst, PFS);
    29562956 case lltok::kw_fence: return ParseFence(Inst, PFS);
    2957 case lltok::kw_atomic: {
    2958 bool isVolatile = EatIfPresent(lltok::kw_volatile);
    2957 case lltok::kw_volatile:
    2958 // For compatibility; canonical location is after load
    29592959 if (EatIfPresent(lltok::kw_load))
    2960 return ParseLoad(Inst, PFS, true, isVolatile);
    2960 return ParseLoad(Inst, PFS, true);
    29612961 else if (EatIfPresent(lltok::kw_store))
    2962 return ParseStore(Inst, PFS, true, isVolatile);
    2963 }
    2964 case lltok::kw_volatile:
    2965 if (EatIfPresent(lltok::kw_load))
    2966 return ParseLoad(Inst, PFS, false, true);
    2967 else if (EatIfPresent(lltok::kw_store))
    2968 return ParseStore(Inst, PFS, false, true);
    2969 else if (EatIfPresent(lltok::kw_cmpxchg))
    2970 return ParseCmpXchg(Inst, PFS, true);
    2971 else if (EatIfPresent(lltok::kw_atomicrmw))
    2972 return ParseAtomicRMW(Inst, PFS, true);
    2962 return ParseStore(Inst, PFS, true);
    29732963 else
    29742964 return TokError("expected 'load' or 'store'");
    29752965 case lltok::kw_getelementptr: return ParseGetElementPtr(Inst, PFS);
    36933683 }
    36943684
    36953685 /// ParseLoad
    3696 /// ::= 'volatile'? 'load' TypeAndValue (',' 'align' i32)?
    3697 // ::= 'atomic' 'volatile'? 'load' TypeAndValue
    3698 // 'singlethread'? AtomicOrdering (',' 'align' i32)?
    3686 /// ::= 'load' 'volatile'? TypeAndValue (',' 'align' i32)?
    3687 /// ::= 'load' 'atomic' 'volatile'? TypeAndValue
    3688 /// 'singlethread'? AtomicOrdering (',' 'align' i32)?
    3689 /// Compatibility:
    3690 /// ::= 'volatile' 'load' TypeAndValue (',' 'align' i32)?
    36993691 int LLParser::ParseLoad(Instruction *&Inst, PerFunctionState &PFS,
    3700 bool isAtomic, bool isVolatile) {
    3692 bool isVolatile) {
    37013693 Value *Val; LocTy Loc;
    37023694 unsigned Alignment = 0;
    37033695 bool AteExtraComma = false;
    3696 bool isAtomic = false;
    37043697 AtomicOrdering Ordering = NotAtomic;
    37053698 SynchronizationScope Scope = CrossThread;
    3699
    3700 if (Lex.getKind() == lltok::kw_atomic) {
    3701 if (isVolatile)
    3702 return TokError("mixing atomic with old volatile placement");
    3703 isAtomic = true;
    3704 Lex.Lex();
    3705 }
    3706
    3707 if (Lex.getKind() == lltok::kw_volatile) {
    3708 if (isVolatile)
    3709 return TokError("duplicate volatile before and after store");
    3710 isVolatile = true;
    3711 Lex.Lex();
    3712 }
    3713
    37063714 if (ParseTypeAndValue(Val, Loc, PFS) ||
    37073715 ParseScopeAndOrdering(isAtomic, Scope, Ordering) ||
    37083716 ParseOptionalCommaAlign(Alignment, AteExtraComma))
    37213729 }
    37223730
    37233731 /// ParseStore
    3724 /// ::= 'volatile'? 'store' TypeAndValue ',' TypeAndValue (',' 'align' i32)?
    3725 /// ::= 'atomic' 'volatile'? 'store' TypeAndValue ',' TypeAndValue
    3732
    3733 /// ::= 'store' 'volatile'? TypeAndValue ',' TypeAndValue (',' 'align' i32)?
    3734 /// ::= 'store' 'atomic' 'volatile'? TypeAndValue ',' TypeAndValue
    37263735 /// 'singlethread'? AtomicOrdering (',' 'align' i32)?
    3736 /// Compatibility:
    3737 /// ::= 'volatile' 'store' TypeAndValue ',' TypeAndValue (',' 'align' i32)?
    37273738 int LLParser::ParseStore(Instruction *&Inst, PerFunctionState &PFS,
    3728 bool isAtomic, bool isVolatile) {
    3739 bool isVolatile) {
    37293740 Value *Val, *Ptr; LocTy Loc, PtrLoc;
    37303741 unsigned Alignment = 0;
    37313742 bool AteExtraComma = false;
    3743 bool isAtomic = false;
    37323744 AtomicOrdering Ordering = NotAtomic;
    37333745 SynchronizationScope Scope = CrossThread;
    3746
    3747 if (Lex.getKind() == lltok::kw_atomic) {
    3748 if (isVolatile)
    3749 return TokError("mixing atomic with old volatile placement");
    3750 isAtomic = true;
    3751 Lex.Lex();
    3752 }
    3753
    3754 if (Lex.getKind() == lltok::kw_volatile) {
    3755 if (isVolatile)
    3756 return TokError("duplicate volatile before and after store");
    3757 isVolatile = true;
    3758 Lex.Lex();
    3759 }
    3760
    37343761 if (ParseTypeAndValue(Val, Loc, PFS) ||
    37353762 ParseToken(lltok::comma, "expected ',' after store operand") ||
    37363763 ParseTypeAndValue(Ptr, PtrLoc, PFS) ||
    37543781 }
    37553782
    37563783 /// ParseCmpXchg
    3757 /// ::= 'volatile'? 'cmpxchg' TypeAndValue ',' TypeAndValue ',' TypeAndValue
    3758 /// 'singlethread'? AtomicOrdering
    3759 int LLParser::ParseCmpXchg(Instruction *&Inst, PerFunctionState &PFS,
    3760 bool isVolatile) {
    3784 /// ::= 'cmpxchg' 'volatile'? TypeAndValue ',' TypeAndValue ',' TypeAndValue
    3785 /// 'singlethread'? AtomicOrdering
    3786 int LLParser::ParseCmpXchg(Instruction *&Inst, PerFunctionState &PFS) {
    37613787 Value *Ptr, *Cmp, *New; LocTy PtrLoc, CmpLoc, NewLoc;
    37623788 bool AteExtraComma = false;
    37633789 AtomicOrdering Ordering = NotAtomic;
    37643790 SynchronizationScope Scope = CrossThread;
    3791 bool isVolatile = false;
    3792
    3793 if (EatIfPresent(lltok::kw_volatile))
    3794 isVolatile = true;
    3795
    37653796 if (ParseTypeAndValue(Ptr, PtrLoc, PFS) ||
    37663797 ParseToken(lltok::comma, "expected ',' after cmpxchg address") ||
    37673798 ParseTypeAndValue(Cmp, CmpLoc, PFS) ||
    37933824 }
    37943825
    37953826 /// ParseAtomicRMW
    3796 /// ::= 'volatile'? 'atomicrmw' BinOp TypeAndValue ',' TypeAndValue
    3797 /// 'singlethread'? AtomicOrdering
    3798 int LLParser::ParseAtomicRMW(Instruction *&Inst, PerFunctionState &PFS,
    3799 bool isVolatile) {
    3827 /// ::= 'atomicrmw' 'volatile'? BinOp TypeAndValue ',' TypeAndValue
    3828 /// 'singlethread'? AtomicOrdering
    3829 int LLParser::ParseAtomicRMW(Instruction *&Inst, PerFunctionState &PFS) {
    38003830 Value *Ptr, *Val; LocTy PtrLoc, ValLoc;
    38013831 bool AteExtraComma = false;
    38023832 AtomicOrdering Ordering = NotAtomic;
    38033833 SynchronizationScope Scope = CrossThread;
    3834 bool isVolatile = false;
    38043835 AtomicRMWInst::BinOp Operation;
    3836
    3837 if (EatIfPresent(lltok::kw_volatile))
    3838 isVolatile = true;
    3839
    38053840 switch (Lex.getKind()) {
    38063841 default: return TokError("expected binary operation in atomicrmw");
    38073842 case lltok::kw_xchg: Operation = AtomicRMWInst::Xchg; break;
    362362 bool ParseLandingPad(Instruction *&I, PerFunctionState &PFS);
    363363 bool ParseCall(Instruction *&I, PerFunctionState &PFS, bool isTail);
    364364 int ParseAlloc(Instruction *&I, PerFunctionState &PFS);
    365 int ParseLoad(Instruction *&I, PerFunctionState &PFS,
    366 bool isAtomic, bool isVolatile);
    367 int ParseStore(Instruction *&I, PerFunctionState &PFS,
    368 bool isAtomic, bool isVolatile);
    369 int ParseCmpXchg(Instruction *&I, PerFunctionState &PFS, bool isVolatile);
    370 int ParseAtomicRMW(Instruction *&I, PerFunctionState &PFS, bool isVolatile);
    365 int ParseLoad(Instruction *&I, PerFunctionState &PFS, bool isVolatile);
    366 int ParseStore(Instruction *&I, PerFunctionState &PFS, bool isVolatile);
    367 int ParseCmpXchg(Instruction *&I, PerFunctionState &PFS);
    368 int ParseAtomicRMW(Instruction *&I, PerFunctionState &PFS);
    371369 int ParseFence(Instruction *&I, PerFunctionState &PFS);
    372370 int ParseGetElementPtr(Instruction *&I, PerFunctionState &PFS);
    373371 int ParseExtractValue(Instruction *&I, PerFunctionState &PFS);
    16571657 else
    16581658 Out << '%' << SlotNum << " = ";
    16591659 }
    1660
    1661 if (isa(I) && cast(I).isTailCall())
    1662 Out << "tail ";
    1663
    1664 // Print out the opcode...
    1665 Out << I.getOpcodeName();
    16601666
    16611667 // If this is an atomic load or store, print out the atomic marker.
    16621668 if ((isa(I) && cast(I).isAtomic()) ||
    16631669 (isa(I) && cast(I).isAtomic()))
    1664 Out << "atomic ";
    1665
    1666 // If this is a volatile load or store, print out the volatile marker.
    1670 Out << " atomic";
    1671
    1672 // If this is a volatile operation, print out the volatile marker.
    16671673 if ((isa(I) && cast(I).isVolatile()) ||
    1668 (isa(I) && cast(I).isVolatile()))
    1669 Out << "volatile ";
    1670
    1671 if (isa(I) && cast(I).isTailCall())
    1672 Out << "tail ";
    1673
    1674 // Print out the opcode...
    1675 Out << I.getOpcodeName();
    1674 (isa(I) && cast(I).isVolatile()) ||
    1675 (isa(I) && cast(I).isVolatile()) ||
    1676 (isa(I) && cast(I).isVolatile()))
    1677 Out << " volatile";
    16761678
    16771679 // Print out optimization information.
    16781680 WriteOptimizationInfo(Out, &I);
    0 ; RUN: opt -S < %s | FileCheck %s
    1 ; Basic smoke test for atomic operations.
    2
    3 define void @f(i32* %x) {
    4 ; CHECK: load atomic i32* %x unordered, align 4
    5 load atomic i32* %x unordered, align 4
    6 ; CHECK: load atomic volatile i32* %x singlethread acquire, align 4
    7 load atomic volatile i32* %x singlethread acquire, align 4
    8 ; CHECK: store atomic i32 3, i32* %x release, align 4
    9 store atomic i32 3, i32* %x release, align 4
    10 ; CHECK: store atomic volatile i32 3, i32* %x singlethread monotonic, align 4
    11 store atomic volatile i32 3, i32* %x singlethread monotonic, align 4
    12 ; CHECK: cmpxchg i32* %x, i32 1, i32 0 singlethread monotonic
    13 cmpxchg i32* %x, i32 1, i32 0 singlethread monotonic
    14 ; CHECK: cmpxchg volatile i32* %x, i32 0, i32 1 acq_rel
    15 cmpxchg volatile i32* %x, i32 0, i32 1 acq_rel
    16 ; CHECK: atomicrmw add i32* %x, i32 10 seq_cst
    17 atomicrmw add i32* %x, i32 10 seq_cst
    18 ; CHECK: atomicrmw volatile xchg i32* %x, i32 10 monotonic
    19 atomicrmw volatile xchg i32* %x, i32 10 monotonic
    20 ; CHECK: fence singlethread release
    21 fence singlethread release
    22 ; CHECK: fence seq_cst
    23 fence seq_cst
    24 ret void
    25 }
    3030 entry:
    3131 %i = alloca i32, align 4
    3232 volatile store i32 10, i32* %i, align 4
    33 ; CHECK: %tmp = volatile load i32* %i, align 4
    33 ; CHECK: %tmp = load volatile i32* %i, align 4
    3434 ; CHECK-next: call void @f(i32 undef)
    3535 %tmp = volatile load i32* %i, align 4
    3636 call void @f(i32 %tmp)
    4141
    4242 define void @test4(i32* %Q) {
    4343 %a = load i32* %Q
    44 volatile store i32 %a, i32* %Q
    44 store volatile i32 %a, i32* %Q
    4545 ret void
    4646 ; CHECK: @test4
    4747 ; CHECK-NEXT: load i32
    48 ; CHECK-NEXT: volatile store
    48 ; CHECK-NEXT: store volatile
    4949 ; CHECK-NEXT: ret void
    5050 }
    5151
    5252 define void @test5(i32* %Q) {
    53 %a = volatile load i32* %Q
    53 %a = load volatile i32* %Q
    5454 store i32 %a, i32* %Q
    5555 ret void
    5656 ; CHECK: @test5
    57 ; CHECK-NEXT: volatile load
    57 ; CHECK-NEXT: load volatile
    5858 ; CHECK-NEXT: ret void
    5959 }
    6060
    1212 volatile store i32 %C, i32* %P
    1313 volatile store i32 %D, i32* %P
    1414 ; CHECK-NEXT: %C = zext i8 %V to i32
    15 ; CHECK-NEXT: volatile store i32 %C
    16 ; CHECK-NEXT: volatile store i32 %C
    15 ; CHECK-NEXT: store volatile i32 %C
    16 ; CHECK-NEXT: store volatile i32 %C
    1717
    1818 %E = add i32 %C, %C
    1919 %F = add i32 %C, %C
    2020 volatile store i32 %E, i32* %P
    2121 volatile store i32 %F, i32* %P
    2222 ; CHECK-NEXT: %E = add i32 %C, %C
    23 ; CHECK-NEXT: volatile store i32 %E
    24 ; CHECK-NEXT: volatile store i32 %E
    23 ; CHECK-NEXT: store volatile i32 %E
    24 ; CHECK-NEXT: store volatile i32 %E
    2525
    2626 %G = add nuw i32 %C, %C ;; not a CSE with E
    2727 volatile store i32 %G, i32* %P
    2828 ; CHECK-NEXT: %G = add nuw i32 %C, %C
    29 ; CHECK-NEXT: volatile store i32 %G
    29 ; CHECK-NEXT: store volatile i32 %G
    3030 ret void
    3131 }
    3232
    None ; RUN: opt < %s -globalopt -S | grep {volatile load}
    0 ; RUN: opt < %s -globalopt -S | grep {load volatile}
    11 @t0.1441 = internal global double 0x3FD5555555555555, align 8 ; [#uses=1]
    22
    33 define double @foo() nounwind {
    None ; RUN: opt < %s -instcombine -S | grep {volatile store}
    0 ; RUN: opt < %s -instcombine -S | grep {store volatile}
    11
    22 define void @test() {
    33 %votf = alloca <4 x float> ; <<4 x float>*> [#uses=1]
    None ; RUN: opt < %s -instcombine -S | grep {volatile load} | count 2
    0 ; RUN: opt < %s -instcombine -S | grep {load volatile} | count 2
    11 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
    22 target triple = "i386-apple-darwin8"
    33 @g_1 = internal global i32 0 ; [#uses=3]
    None ; RUN: opt < %s -instcombine -S | grep {volatile load} | count 2
    0 ; RUN: opt < %s -instcombine -S | grep {load volatile} | count 2
    11 ; PR2262
    22 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
    33 target triple = "i386-apple-darwin8"
    None ; RUN: opt < %s -instcombine -S | grep {volatile load} | count 2
    0 ; RUN: opt < %s -instcombine -S | grep {load volatile} | count 2
    11 ; PR2496
    22 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
    33 target triple = "i386-apple-darwin8"
    9595 }
    9696
    9797 ; CHECK: define i32 @nogep-volatile
    98 ; CHECK-NEXT: volatile load {{.*}} %pair
    98 ; CHECK-NEXT: load volatile {{.*}} %pair
    9999 ; CHECK-NEXT: extractvalue
    100100 ; CHECK-NEXT: ret
    101101 define i32 @nogep-volatile({i32, i32}* %pair) {
    151151 ret void
    152152 ; CHECK: @powi
    153153 ; CHECK: %A = fdiv double 1.0{{.*}}, %V
    154 ; CHECK: volatile store double %A,
    155 ; CHECK: volatile store double 1.0
    156 ; CHECK: volatile store double %V
    154 ; CHECK: store volatile double %A,
    155 ; CHECK: store volatile double 1.0
    156 ; CHECK: store volatile double %V
    157157 }
    158158
    159159 define i32 @cttz(i32 %a) {
    193193 ; CHECK: @cmp.simplify
    194194 ; CHECK-NEXT: entry:
    195195 ; CHECK-NEXT: %lz.cmp = icmp eq i32 %a, 0
    196 ; CHECK-NEXT: volatile store i1 %lz.cmp, i1* %c
    196 ; CHECK-NEXT: store volatile i1 %lz.cmp, i1* %c
    197197 ; CHECK-NEXT: %tz.cmp = icmp ne i32 %a, 0
    198 ; CHECK-NEXT: volatile store i1 %tz.cmp, i1* %c
    198 ; CHECK-NEXT: store volatile i1 %tz.cmp, i1* %c
    199199 ; CHECK-NEXT: %pop.cmp = icmp eq i32 %b, 0
    200 ; CHECK-NEXT: volatile store i1 %pop.cmp, i1* %c
    200 ; CHECK-NEXT: store volatile i1 %pop.cmp, i1* %c
    201201 }
    202202
    203203
    None ; RUN: opt < %s -instcombine -S | grep {volatile store}
    1 ; RUN: opt < %s -instcombine -S | grep {volatile load}
    0 ; RUN: opt < %s -instcombine -S | grep {store volatile}
    1 ; RUN: opt < %s -instcombine -S | grep {load volatile}
    22
    33 @x = weak global i32 0 ; [#uses=2]
    44
    0 ; RUN: opt < %s -jump-threading -loop-rotate -instcombine -indvars -loop-unroll -simplifycfg -S -verify-dom-info -verify-loop-info > %t
    1 ; RUN: grep {volatile store} %t | count 3
    1 ; RUN: grep {store volatile} %t | count 3
    22 ; RUN: not grep {br label} %t
    33
    44 ; Jump threading should not prevent this loop from being unrolled.
    None ; RUN: opt < %s -licm -S | grep {volatile store}
    0 ; RUN: opt < %s -licm -S | grep {store volatile}
    11 ; PR1435
    22 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64"
    33 target triple = "i686-apple-darwin8"
    1414 br label %for.body4
    1515
    1616 ; CHECK: for.body4:
    17 ; CHECK: volatile load i16* @g_39
    17 ; CHECK: load volatile i16* @g_39
    1818
    1919 for.body4:
    2020 %l_612.11 = phi i32* [ undef, %for.body4.lr.ph ], [ %call19, %for.body4 ]
    6464 br i1 true, label %Out, label %Loop
    6565
    6666 ; CHECK: Loop:
    67 ; CHECK-NEXT: volatile load
    67 ; CHECK-NEXT: load volatile
    6868
    6969 Out: ; preds = %Loop
    7070 ret void
    2424 ; CHECK: define void @test1(i8* %p) {
    2525 ; CHECK-NEXT: entry:
    2626 ; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %p) nounwind
    27 ; CHECK-NEXT: %tmp = volatile load i8** @x, align 8
    27 ; CHECK-NEXT: %tmp = load volatile i8** @x, align 8
    2828 ; CHECK-NEXT: store i8* %0, i8** @x, align 8
    2929 ; CHECK-NEXT: tail call void @objc_release(i8* %tmp) nounwind
    3030 ; CHECK-NEXT: ret void
    4444 ; CHECK-NEXT: entry:
    4545 ; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %p) nounwind
    4646 ; CHECK-NEXT: %tmp = load i8** @x, align 8
    47 ; CHECK-NEXT: volatile store i8* %0, i8** @x, align 8
    47 ; CHECK-NEXT: store volatile i8* %0, i8** @x, align 8
    4848 ; CHECK-NEXT: tail call void @objc_release(i8* %tmp) nounwind
    4949 ; CHECK-NEXT: ret void
    5050 ; CHECK-NEXT: }
    None ; RUN: opt < %s -scalarrepl -S | grep {volatile load}
    1 ; RUN: opt < %s -scalarrepl -S | grep {volatile store}
    0 ; RUN: opt < %s -scalarrepl -S | grep {load volatile}
    1 ; RUN: opt < %s -scalarrepl -S | grep {store volatile}
    22
    33 define i32 @voltest(i32 %T) {
    44 %A = alloca {i32, i32}
    1010 br i1 %0, label %bb, label %return
    1111
    1212 bb: ; preds = %entry
    13 %1 = volatile load i32* null
    13 %1 = load volatile i32* null
    1414 unreachable
    1515
    1616 br label %return
    1717 return: ; preds = %entry
    1818 ret void
    1919 ; CHECK: @test1
    20 ; CHECK: volatile load
    20 ; CHECK: load volatile
    2121 }
    2222
    2323 ; rdar://7958343
    3434 ; PR7369
    3535 define void @test3() nounwind {
    3636 entry:
    37 volatile store i32 4, i32* null
    37 store volatile i32 4, i32* null
    3838 ret void
    3939
    4040 ; CHECK: @test3
    41 ; CHECK: volatile store i32 4, i32* null
    41 ; CHECK: store volatile i32 4, i32* null
    4242 ; CHECK: ret
    4343 }
    99 define void @test(i8* %P, i8* %Q, i32 %N, i32* %IP, i1* %BP) {
    1010 %A = call i32 @memcmp( i8* %P, i8* %P, i32 %N ) ; [#uses=1]
    1111 ; CHECK-NOT: call {{.*}} memcmp
    12 ; CHECK: volatile store
    13 volatile store i32 %A, i32* %IP
    12 ; CHECK: store volatile
    13 store volatile i32 %A, i32* %IP
    1414 %B = call i32 @memcmp( i8* %P, i8* %Q, i32 0 ) ; [#uses=1]
    1515 ; CHECK-NOT: call {{.*}} memcmp
    16 ; CHECK: volatile store
    17 volatile store i32 %B, i32* %IP
    16 ; CHECK: store volatile
    17 store volatile i32 %B, i32* %IP
    1818 %C = call i32 @memcmp( i8* %P, i8* %Q, i32 1 ) ; [#uses=1]
    1919 ; CHECK: load
    2020 ; CHECK: zext
    2121 ; CHECK: load
    2222 ; CHECK: zext
    2323 ; CHECK: sub
    24 ; CHECK: volatile store
    25 volatile store i32 %C, i32* %IP
    26 %F = call i32 @memcmp(i8* getelementptr ([4 x i8]* @hel, i32 0, i32 0),
    27 i8* getelementptr ([8 x i8]* @hello_u, i32 0, i32 0),
    28 i32 3)
    24 ; CHECK: store volatile
    25 store volatile i32 %C, i32* %IP
    26 %F = call i32 @memcmp(i8* getelementptr ([4 x i8]* @hel, i32 0, i32 0),
    27 i8* getelementptr ([8 x i8]* @hello_u, i32 0, i32 0),
    28 i32 3)
    2929 ; CHECK-NOT: call {{.*}} memcmp
    30 ; CHECK: volatile store
    31 volatile store i32 %F, i32* %IP
    30 ; CHECK: store volatile
    31 store volatile i32 %F, i32* %IP
    3232 ret void
    3333 }
    3434