Index: llvm/include/llvm/AsmParser/LLParser.h =================================================================== --- llvm/include/llvm/AsmParser/LLParser.h +++ llvm/include/llvm/AsmParser/LLParser.h @@ -276,6 +276,9 @@ bool parseOrdering(AtomicOrdering &Ordering); bool parseOptionalStackAlignment(unsigned &Alignment); bool parseOptionalCommaAlign(MaybeAlign &Alignment, bool &AteExtraComma); + bool parseOptionalCommaNoaliasProvenance(Value *&V, LocTy &Loc, + PerFunctionState &PFS, + bool &AteExtraComma); bool parseOptionalCommaAddrSpace(unsigned &AddrSpace, LocTy &Loc, bool &AteExtraComma); bool parseOptionalCommaInAlloca(bool &IsInAlloca); Index: llvm/include/llvm/AsmParser/LLToken.h =================================================================== --- llvm/include/llvm/AsmParser/LLToken.h +++ llvm/include/llvm/AsmParser/LLToken.h @@ -91,6 +91,7 @@ kw_deplibs, // FIXME: Remove in 4.0 kw_datalayout, kw_volatile, + kw_ptr_provenance, kw_atomic, kw_unordered, kw_monotonic, Index: llvm/lib/AsmParser/LLLexer.cpp =================================================================== --- llvm/lib/AsmParser/LLLexer.cpp +++ llvm/lib/AsmParser/LLLexer.cpp @@ -546,6 +546,7 @@ KEYWORD(deplibs); // FIXME: Remove in 4.0. KEYWORD(datalayout); KEYWORD(volatile); + KEYWORD(ptr_provenance); KEYWORD(atomic); KEYWORD(unordered); KEYWORD(monotonic); Index: llvm/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/lib/AsmParser/LLParser.cpp +++ llvm/lib/AsmParser/LLParser.cpp @@ -2321,16 +2321,20 @@ /// end. bool LLParser::parseOptionalCommaAlign(MaybeAlign &Alignment, bool &AteExtraComma) { - AteExtraComma = false; - while (EatIfPresent(lltok::comma)) { + while (AteExtraComma || EatIfPresent(lltok::comma)) { + AteExtraComma = false; // Metadata at the end is an early exit. if (Lex.getKind() == lltok::MetadataVar) { AteExtraComma = true; return false; } - if (Lex.getKind() != lltok::kw_align) + // if we get here, ptr_provenance must not be possible any more + if (Lex.getKind() == lltok::kw_ptr_provenance) return error(Lex.getLoc(), "expected metadata or 'align'"); + if (Lex.getKind() != lltok::kw_align) + return error(Lex.getLoc(), + "expected metadata or 'align' or 'ptr_provenance'"); if (parseOptionalAlignment(Alignment)) return true; @@ -2339,6 +2343,27 @@ return false; } +/// parseOptionalCommandNoaliasProvenance +/// ::= +/// ::= ',' ptr_provenance int* %3 +/// +/// This returns with AteExtraComma set to true if it ate an excess comma at the +/// end. +bool LLParser::parseOptionalCommaNoaliasProvenance( + Value *&V, LLParser::LocTy &Loc, LLParser::PerFunctionState &PFS, + bool &AteExtraComma) { + assert(AteExtraComma == false); + if (EatIfPresent(lltok::comma)) { + if (Lex.getKind() == lltok::kw_ptr_provenance) { + Lex.Lex(); + return parseTypeAndValue(V, Loc, PFS); + } + + AteExtraComma = true; + } + return false; +} + /// parseOptionalCommaAddrSpace /// ::= /// ::= ',' addrspace(1) @@ -7449,6 +7474,8 @@ /// 'singlethread'? AtomicOrdering (',' 'align' i32)? int LLParser::parseLoad(Instruction *&Inst, PerFunctionState &PFS) { Value *Val; LocTy Loc; + Value *NoaliasProvenance = nullptr; + LocTy NoaliasProvenanceLoc; MaybeAlign Alignment; bool AteExtraComma = false; bool isAtomic = false; @@ -7472,6 +7499,8 @@ parseToken(lltok::comma, "expected comma after load's type") || parseTypeAndValue(Val, Loc, PFS) || parseScopeAndOrdering(isAtomic, SSID, Ordering) || + parseOptionalCommaNoaliasProvenance( + NoaliasProvenance, NoaliasProvenanceLoc, PFS, AteExtraComma) || parseOptionalCommaAlign(Alignment, AteExtraComma)) return true; @@ -7495,7 +7524,10 @@ return error(ExplicitTypeLoc, "loading unsized types is not allowed"); if (!Alignment) Alignment = M->getDataLayout().getABITypeAlign(Ty); - Inst = new LoadInst(Ty, Val, "", isVolatile, *Alignment, Ordering, SSID); + auto *LI = new LoadInst(Ty, Val, "", isVolatile, *Alignment, Ordering, SSID); + if (NoaliasProvenance) + LI->setNoaliasProvenanceOperand(NoaliasProvenance); + Inst = LI; return AteExtraComma ? InstExtraComma : InstNormal; } @@ -7506,6 +7538,8 @@ /// 'singlethread'? AtomicOrdering (',' 'align' i32)? int LLParser::parseStore(Instruction *&Inst, PerFunctionState &PFS) { Value *Val, *Ptr; LocTy Loc, PtrLoc; + Value *NoaliasProvenance = nullptr; + LocTy NoaliasProvenanceLoc; MaybeAlign Alignment; bool AteExtraComma = false; bool isAtomic = false; @@ -7527,6 +7561,8 @@ parseToken(lltok::comma, "expected ',' after store operand") || parseTypeAndValue(Ptr, PtrLoc, PFS) || parseScopeAndOrdering(isAtomic, SSID, Ordering) || + parseOptionalCommaNoaliasProvenance( + NoaliasProvenance, NoaliasProvenanceLoc, PFS, AteExtraComma) || parseOptionalCommaAlign(Alignment, AteExtraComma)) return true; @@ -7547,7 +7583,11 @@ if (!Alignment) Alignment = M->getDataLayout().getABITypeAlign(Val->getType()); - Inst = new StoreInst(Val, Ptr, isVolatile, *Alignment, Ordering, SSID); + auto *SI = new StoreInst(Val, Ptr, isVolatile, *Alignment, Ordering, SSID); + if (NoaliasProvenance) + SI->setNoaliasProvenanceOperand(NoaliasProvenance); + Inst = SI; + return AteExtraComma ? InstExtraComma : InstNormal; } Index: llvm/test/Bitcode/loadstore_ptr_provenance.ll =================================================================== --- /dev/null +++ llvm/test/Bitcode/loadstore_ptr_provenance.ll @@ -0,0 +1,45 @@ +; RUN: opt --verify -S < %s | FileCheck %s +; Activate when bitcode support is added: +; R U N: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s +; R U N: verify-uselistorder < %s + +define i32 @f(i32* %p, i32* %q, i32* %word, i32** %base) { + ; CHECK: define i32 @f(i32* %p, i32* %q, i32* %word, i32** %base) { + store i32 42, i32* %p, ptr_provenance i32* %p + ; CHECK-NEXT: store i32 42, i32* %p, ptr_provenance i32* %p + store i32 43, i32* %q, ptr_provenance i32* %q + ; CHECK-NEXT: store i32 43, i32* %q, ptr_provenance i32* %q + %r = load i32, i32* %p, ptr_provenance i32* %p + ; CHECK-NEXT: %r = load i32, i32* %p, ptr_provenance i32* %p + + %ld.1p = load atomic i32, i32* %word monotonic, ptr_provenance i32* %word, align 4 + ; CHECK: %ld.1p = load atomic i32, i32* %word monotonic, ptr_provenance i32* %word, align 4 + %ld.2p = load atomic volatile i32, i32* %word acquire, ptr_provenance i32* %word, align 8 + ; CHECK: %ld.2p = load atomic volatile i32, i32* %word acquire, ptr_provenance i32* %word, align 8 + %ld.3p = load atomic volatile i32, i32* %word syncscope("singlethread") seq_cst, ptr_provenance i32* %word, align 16 + ; CHECK: %ld.3p = load atomic volatile i32, i32* %word syncscope("singlethread") seq_cst, ptr_provenance i32* %word, align 16 + + store atomic i32 23, i32* %word monotonic, align 4 + ; CHECK: store atomic i32 23, i32* %word monotonic, align 4 + store atomic volatile i32 24, i32* %word monotonic, align 4 + ; CHECK: store atomic volatile i32 24, i32* %word monotonic, align 4 + store atomic volatile i32 25, i32* %word syncscope("singlethread") monotonic, align 4 + ; CHECK: store atomic volatile i32 25, i32* %word syncscope("singlethread") monotonic, align 4 + + load i32*, i32** %base, ptr_provenance i32** %base, align 8, !invariant.load !0, !nontemporal !1, !nonnull !0, !dereferenceable !2, !dereferenceable_or_null !2 + ; CHECK: load i32*, i32** %base, ptr_provenance i32** %base, align 8, !invariant.load !0, !nontemporal !1, !nonnull !0, !dereferenceable !2, !dereferenceable_or_null !2 + load volatile i32*, i32** %base, ptr_provenance i32** %base, align 8, !invariant.load !0, !nontemporal !1, !nonnull !0, !dereferenceable !2, !dereferenceable_or_null !2 + ; CHECK: load volatile i32*, i32** %base, ptr_provenance i32** %base, align 8, !invariant.load !0, !nontemporal !1, !nonnull !0, !dereferenceable !2, !dereferenceable_or_null !2 + + store i32* null, i32** %base, ptr_provenance i32** %base, align 4, !nontemporal !1 + ; CHECK: store i32* null, i32** %base, ptr_provenance i32** %base, align 4, !nontemporal !1 + store volatile i32* null, i32** %base, ptr_provenance i32** %base, align 4, !nontemporal !1 + ; CHECK: store volatile i32* null, i32** %base, ptr_provenance i32** %base, align 4, !nontemporal !1 + + ret i32 %r + ; CHECK-NEXT: ret i32 %r +} + +!0 = !{i32 1} +!1 = !{} +!2 = !{i64 4}