Index: include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- include/llvm/Bitcode/LLVMBitCodes.h +++ include/llvm/Bitcode/LLVMBitCodes.h @@ -560,6 +560,7 @@ ATTR_KIND_WRITEONLY = 52, ATTR_KIND_SPECULATABLE = 53, ATTR_KIND_STRICT_FP = 54, + ATTR_KIND_HASSIDEEFFECTS = 55, }; enum ComdatSelectionKindCodes { Index: include/llvm/IR/Attributes.td =================================================================== --- include/llvm/IR/Attributes.td +++ include/llvm/IR/Attributes.td @@ -45,6 +45,10 @@ /// Pointer is either null or dereferenceable. def DereferenceableOrNull : EnumAttr<"dereferenceable_or_null">; +/// Function has non-modelled side effects, e.g. the use of non-modelled +/// registers. +def HasSideEffects : EnumAttr<"sideeffects">; + /// Function may only access memory that is inaccessible from IR. def InaccessibleMemOnly : EnumAttr<"inaccessiblememonly">; Index: include/llvm/IR/Function.h =================================================================== --- include/llvm/IR/Function.h +++ include/llvm/IR/Function.h @@ -483,6 +483,15 @@ addFnAttr(Attribute::Speculatable); } + // ?? Is the comment for isSpeculatable() above wrong ?? + /// @brief Determine if the call has sideeffects. + bool hasSideEffects() const { + return hasFnAttribute(Attribute::HasSideEffects); + } + void setHasSideEffects() { + addFnAttr(Attribute::HasSideEffects); + } + /// Determine if the function is known not to recurse, directly or /// indirectly. bool doesNotRecurse() const { Index: include/llvm/IR/IntrinsicsSystemZ.td =================================================================== --- include/llvm/IR/IntrinsicsSystemZ.td +++ include/llvm/IR/IntrinsicsSystemZ.td @@ -205,10 +205,10 @@ [IntrNoDuplicate]>; def int_s390_tbeginc : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], - [IntrNoDuplicate]>; + [IntrNoDuplicate, IntrWriteMem]>; def int_s390_tabort : Intrinsic<[], [llvm_i64_ty], - [IntrNoReturn, Throws]>; + [IntrNoReturn, Throws, IntrNoMem, IntrHasSideEffects]>; def int_s390_tend : GCCBuiltin<"__builtin_tend">, Intrinsic<[llvm_i32_ty], []>; @@ -217,7 +217,7 @@ Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>; def int_s390_ntstg : Intrinsic<[], [llvm_i64_ty, llvm_ptr64_ty], - [IntrArgMemOnly]>; + [IntrArgMemOnly, IntrWriteMem]>; def int_s390_ppa_txassist : GCCBuiltin<"__builtin_tx_assist">, Intrinsic<[], [llvm_i32_ty]>; @@ -260,9 +260,7 @@ def int_s390_vstl : GCCBuiltin<"__builtin_s390_vstl">, Intrinsic<[], [llvm_v16i8_ty, llvm_i32_ty, llvm_ptr_ty], - // In fact write-only but there's no property - // for that. - [IntrArgMemOnly]>; + [IntrArgMemOnly, IntrWriteMem]>; defm int_s390_vupl : SystemZUnaryExtBHWF<"vupl">; defm int_s390_vupll : SystemZUnaryExtBHF<"vupll">; @@ -413,9 +411,7 @@ def int_s390_vstrl : GCCBuiltin<"__builtin_s390_vstrl">, Intrinsic<[], [llvm_v16i8_ty, llvm_i32_ty, llvm_ptr_ty], - // In fact write-only but there's no property - // for that. - [IntrArgMemOnly]>; + [IntrArgMemOnly, IntrWriteMem]>; } //===----------------------------------------------------------------------===// @@ -426,9 +422,9 @@ let TargetPrefix = "s390" in { def int_s390_sfpc : GCCBuiltin<"__builtin_s390_sfpc">, - Intrinsic<[], [llvm_i32_ty], []>; + Intrinsic<[], [llvm_i32_ty], [IntrNoMem, IntrHasSideEffects]>; def int_s390_efpc : GCCBuiltin<"__builtin_s390_efpc">, - Intrinsic<[llvm_i32_ty], [], []>; + Intrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrHasSideEffects]>; def int_s390_tdc : Intrinsic<[llvm_i32_ty], [llvm_anyfloat_ty, llvm_i64_ty], [IntrNoMem]>; Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -1112,6 +1112,7 @@ case lltok::kw_builtin: B.addAttribute(Attribute::Builtin); break; case lltok::kw_cold: B.addAttribute(Attribute::Cold); break; case lltok::kw_convergent: B.addAttribute(Attribute::Convergent); break; + case lltok::kw_hassideeffects: B.addAttribute(Attribute::HasSideEffects); break; case lltok::kw_inaccessiblememonly: B.addAttribute(Attribute::InaccessibleMemOnly); break; case lltok::kw_inaccessiblemem_or_argmemonly: @@ -1452,6 +1453,7 @@ case lltok::kw_alwaysinline: case lltok::kw_argmemonly: case lltok::kw_builtin: + case lltok::kw_hassideeffects: case lltok::kw_inlinehint: case lltok::kw_jumptable: case lltok::kw_minsize: @@ -1544,6 +1546,7 @@ case lltok::kw_argmemonly: case lltok::kw_builtin: case lltok::kw_cold: + case lltok::kw_hassideeffects: case lltok::kw_inlinehint: case lltok::kw_jumptable: case lltok::kw_minsize: Index: lib/AsmParser/LLToken.h =================================================================== --- lib/AsmParser/LLToken.h +++ lib/AsmParser/LLToken.h @@ -179,6 +179,7 @@ kw_convergent, kw_dereferenceable, kw_dereferenceable_or_null, + kw_hassideeffects, kw_inaccessiblememonly, kw_inaccessiblemem_or_argmemonly, kw_inlinehint, Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -1156,6 +1156,7 @@ case Attribute::WriteOnly: return 1ULL << 53; case Attribute::Speculatable: return 1ULL << 54; case Attribute::StrictFP: return 1ULL << 55; + case Attribute::HasSideEffects: return 1ULL << 56; case Attribute::Dereferenceable: llvm_unreachable("dereferenceable attribute not supported in raw format"); break; @@ -1290,6 +1291,8 @@ return Attribute::Cold; case bitc::ATTR_KIND_CONVERGENT: return Attribute::Convergent; + case bitc::ATTR_KIND_HASSIDEEFFECTS: + return Attribute::HasSideEffects; case bitc::ATTR_KIND_INACCESSIBLEMEM_ONLY: return Attribute::InaccessibleMemOnly; case bitc::ATTR_KIND_INACCESSIBLEMEM_OR_ARGMEMONLY: Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -583,6 +583,8 @@ return bitc::ATTR_KIND_BY_VAL; case Attribute::Convergent: return bitc::ATTR_KIND_CONVERGENT; + case Attribute::HasSideEffects: + return bitc::ATTR_KIND_HASSIDEEFFECTS; case Attribute::InAlloca: return bitc::ATTR_KIND_IN_ALLOCA; case Attribute::Cold: Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -4194,7 +4194,7 @@ // readnone, but the lowering code will expect the chain based on the // definition. const Function *F = I.getCalledFunction(); - bool HasChain = !F->doesNotAccessMemory(); + bool HasChain = (!F->doesNotAccessMemory() || F->hasSideEffects()); bool OnlyLoad = HasChain && F->onlyReadsMemory(); // Build the operand list. Index: lib/IR/Attributes.cpp =================================================================== --- lib/IR/Attributes.cpp +++ lib/IR/Attributes.cpp @@ -259,6 +259,8 @@ return "swifterror"; if (hasAttribute(Attribute::SwiftSelf)) return "swiftself"; + if (hasAttribute(Attribute::HasSideEffects)) + return "hassideeffects"; if (hasAttribute(Attribute::InaccessibleMemOnly)) return "inaccessiblememonly"; if (hasAttribute(Attribute::InaccessibleMemOrArgMemOnly)) Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -1392,6 +1392,7 @@ case Attribute::AllocSize: case Attribute::Speculatable: case Attribute::StrictFP: + case Attribute::HasSideEffects: return true; default: break; Index: lib/Target/SystemZ/SystemZInstrFP.td =================================================================== --- lib/Target/SystemZ/SystemZInstrFP.td +++ lib/Target/SystemZ/SystemZInstrFP.td @@ -526,10 +526,12 @@ let hasSideEffects = 1 in { def EFPC : InherentRRE<"efpc", 0xB38C, GR32, int_s390_efpc>; - def STFPC : StoreInherentS<"stfpc", 0xB29C, storei, 4>; + let mayStore = 1 in + def STFPC : StoreInherentS<"stfpc", 0xB29C, storei, 4>; def SFPC : SideEffectUnaryRRE<"sfpc", 0xB384, GR32, int_s390_sfpc>; - def LFPC : SideEffectUnaryS<"lfpc", 0xB29D, loadu, 4>; + let mayLoad = 1 in + def LFPC : SideEffectUnaryS<"lfpc", 0xB29D, loadu, 4>; def SFASR : SideEffectUnaryRRE<"sfasr", 0xB385, GR32, null_frag>; def LFAS : SideEffectUnaryS<"lfas", 0xB2BD, null_frag, 4>; Index: utils/TableGen/IntrinsicEmitter.cpp =================================================================== --- utils/TableGen/IntrinsicEmitter.cpp +++ utils/TableGen/IntrinsicEmitter.cpp @@ -650,6 +650,12 @@ OS << "Attribute::Speculatable"; addComma = true; } + if (intrinsic.hasSideEffects) { + if (addComma) + OS << ","; + OS << "Attribute::HasSideEffects"; + addComma = true; + } switch (intrinsic.ModRef) { case CodeGenIntrinsic::NoMem: