Skip to content

Commit

Permalink
Rename invariant.group.barrier to launder.invariant.group
Browse files Browse the repository at this point in the history
Summary:
This is one of the initial commit of "RFC: Devirtualization v2" proposal:
https://docs.google.com/document/d/16GVtCpzK8sIHNc2qZz6RN8amICNBtvjWUod2SujZVEo/edit?usp=sharing

Reviewers: rsmith, amharc, kuhar, sanjoy

Subscribers: arsenm, nhaehnle, javed.absar, hiraditya, llvm-commits

Differential Revision: https://reviews.llvm.org/D45111

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@331448 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
prazek committed May 3, 2018
1 parent d0aaa15 commit 9648b46
Show file tree
Hide file tree
Showing 24 changed files with 154 additions and 127 deletions.
17 changes: 9 additions & 8 deletions docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5318,7 +5318,7 @@ The experimental ``invariant.group`` metadata may be attached to
The existence of the ``invariant.group`` metadata on the instruction tells
the optimizer that every ``load`` and ``store`` to the same pointer operand
within the same invariant group can be assumed to load or store the same
value (but see the ``llvm.invariant.group.barrier`` intrinsic which affects
value (but see the ``llvm.launder.invariant.group`` intrinsic which affects
when two pointers are considered the same). Pointers returned by bitcast or
getelementptr with only zero indices are considered the same.

Expand All @@ -5343,13 +5343,13 @@ Examples:
store i8 %unknownValue, i8* %ptr, !invariant.group !0 ; Can assume that %unknownValue == 42

call void @foo(i8* %ptr)
%newPtr2 = call i8* @llvm.invariant.group.barrier(i8* %ptr)
%d = load i8, i8* %newPtr2, !invariant.group !0 ; Can't step through invariant.group.barrier to get value of %ptr
%newPtr2 = call i8* @llvm.launder.invariant.group(i8* %ptr)
%d = load i8, i8* %newPtr2, !invariant.group !0 ; Can't step through launder.invariant.group to get value of %ptr

...
declare void @foo(i8*)
declare i8* @getPointer(i8*)
declare i8* @llvm.invariant.group.barrier(i8*)
declare i8* @llvm.launder.invariant.group(i8*)

!0 = !{!"magic ptr"}
!1 = !{!"other ptr"}
Expand Down Expand Up @@ -12908,7 +12908,7 @@ Semantics:

This intrinsic indicates that the memory is mutable again.

'``llvm.invariant.group.barrier``' Intrinsic
'``llvm.launder.invariant.group``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Syntax:
Expand All @@ -12919,12 +12919,12 @@ argument.

::

declare i8* @llvm.invariant.group.barrier.p0i8(i8* <ptr>)
declare i8* @llvm.launder.invariant.group.p0i8(i8* <ptr>)

Overview:
"""""""""

The '``llvm.invariant.group.barrier``' intrinsic can be used when an invariant
The '``llvm.launder.invariant.group``' intrinsic can be used when an invariant
established by invariant.group metadata no longer holds, to obtain a new pointer
value that does not carry the invariant information. It is an experimental
intrinsic, which means that its semantics might change in the future.
Expand All @@ -12933,14 +12933,15 @@ intrinsic, which means that its semantics might change in the future.
Arguments:
""""""""""

The ``llvm.invariant.group.barrier`` takes only one argument, which is
The ``llvm.launder.invariant.group`` takes only one argument, which is
the pointer to the memory for which the ``invariant.group`` no longer holds.

Semantics:
""""""""""

Returns another pointer that aliases its argument but which is considered different
for the purposes of ``load``/``store`` ``invariant.group`` metadata.
It does not read any accessible memory and the execution can be speculated.

.. _constrainedfp:

Expand Down
2 changes: 2 additions & 0 deletions docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ Changes to the LLVM IR
have changed. Alignment is no longer an argument, and are instead conveyed as
parameter attributes.

* invariant.group.barrier has been renamed to launder.invariant.group.

Changes to the ARM Backend
--------------------------

Expand Down
24 changes: 11 additions & 13 deletions include/llvm/IR/IRBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -1962,28 +1962,26 @@ class IRBuilder : public IRBuilderBase, public Inserter {
Name);
}

/// Create an invariant.group.barrier intrinsic call, that stops
/// optimizer to propagate equality using invariant.group metadata.
/// If Ptr type is different from pointer to i8, it's casted to pointer to i8
/// in the same address space before call and casted back to Ptr type after
/// call.
Value *CreateInvariantGroupBarrier(Value *Ptr) {
/// Create a launder.invariant.group intrinsic call. If Ptr type is
/// different from pointer to i8, it's casted to pointer to i8 in the same
/// address space before call and casted back to Ptr type after call.
Value *CreateLaunderInvariantGroup(Value *Ptr) {
assert(isa<PointerType>(Ptr->getType()) &&
"invariant.group.barrier only applies to pointers.");
"launder.invariant.group only applies to pointers.");
auto *PtrType = Ptr->getType();
auto *Int8PtrTy = getInt8PtrTy(PtrType->getPointerAddressSpace());
if (PtrType != Int8PtrTy)
Ptr = CreateBitCast(Ptr, Int8PtrTy);
Module *M = BB->getParent()->getParent();
Function *FnInvariantGroupBarrier = Intrinsic::getDeclaration(
M, Intrinsic::invariant_group_barrier, {Int8PtrTy});
Function *FnLaunderInvariantGroup = Intrinsic::getDeclaration(
M, Intrinsic::launder_invariant_group, {Int8PtrTy});

assert(FnInvariantGroupBarrier->getReturnType() == Int8PtrTy &&
FnInvariantGroupBarrier->getFunctionType()->getParamType(0) ==
assert(FnLaunderInvariantGroup->getReturnType() == Int8PtrTy &&
FnLaunderInvariantGroup->getFunctionType()->getParamType(0) ==
Int8PtrTy &&
"InvariantGroupBarrier should take and return the same type");
"LaunderInvariantGroup should take and return the same type");

CallInst *Fn = CreateCall(FnInvariantGroupBarrier, {Ptr});
CallInst *Fn = CreateCall(FnLaunderInvariantGroup, {Ptr});

if (PtrType != Int8PtrTy)
return CreateBitCast(Fn, PtrType);
Expand Down
6 changes: 3 additions & 3 deletions include/llvm/IR/Intrinsics.td
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,7 @@ def int_invariant_end : Intrinsic<[],
llvm_anyptr_ty],
[IntrArgMemOnly, NoCapture<2>]>;

// invariant.group.barrier can't be marked with 'readnone' (IntrNoMem),
// launder.invariant.group can't be marked with 'readnone' (IntrNoMem),
// because it would cause CSE of two barriers with the same argument.
// Inaccessiblememonly says that the barrier doesn't read the argument,
// but it changes state not accessible to this module. This way
Expand All @@ -722,9 +722,9 @@ def int_invariant_end : Intrinsic<[],
// it would remove barrier.
// Note that it is still experimental, which means that its semantics
// might change in the future.
def int_invariant_group_barrier : Intrinsic<[llvm_anyptr_ty],
def int_launder_invariant_group : Intrinsic<[llvm_anyptr_ty],
[LLVMMatchType<0>],
[IntrInaccessibleMemOnly]>;
[IntrInaccessibleMemOnly, IntrSpeculatable]>;

//===------------------------ Stackmap Intrinsics -------------------------===//
//
Expand Down
9 changes: 5 additions & 4 deletions include/llvm/IR/Value.h
Original file line number Diff line number Diff line change
Expand Up @@ -509,15 +509,16 @@ class Value {
static_cast<const Value *>(this)->stripPointerCasts());
}

/// Strip off pointer casts, all-zero GEPs, aliases and barriers.
/// Strip off pointer casts, all-zero GEPs, aliases and invariant group
/// info.
///
/// Returns the original uncasted value. If this is called on a non-pointer
/// value, it returns 'this'. This function should be used only in
/// Alias analysis.
const Value *stripPointerCastsAndBarriers() const;
Value *stripPointerCastsAndBarriers() {
const Value *stripPointerCastsAndInvariantGroups() const;
Value *stripPointerCastsAndInvariantGroups() {
return const_cast<Value *>(
static_cast<const Value *>(this)->stripPointerCastsAndBarriers());
static_cast<const Value *>(this)->stripPointerCastsAndInvariantGroups());
}

/// Strip off pointer casts and all-zero GEPs.
Expand Down
12 changes: 6 additions & 6 deletions lib/Analysis/BasicAliasAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -985,8 +985,8 @@ static AliasResult aliasSameBasePointerGEPs(const GEPOperator *GEP1,
const GEPOperator *GEP2,
uint64_t V2Size,
const DataLayout &DL) {
assert(GEP1->getPointerOperand()->stripPointerCastsAndBarriers() ==
GEP2->getPointerOperand()->stripPointerCastsAndBarriers() &&
assert(GEP1->getPointerOperand()->stripPointerCastsAndInvariantGroups() ==
GEP2->getPointerOperand()->stripPointerCastsAndInvariantGroups() &&
GEP1->getPointerOperandType() == GEP2->getPointerOperandType() &&
"Expected GEPs with the same pointer operand");

Expand Down Expand Up @@ -1264,8 +1264,8 @@ AliasResult BasicAAResult::aliasGEP(const GEPOperator *GEP1, uint64_t V1Size,
// If we know the two GEPs are based off of the exact same pointer (and not
// just the same underlying object), see if that tells us anything about
// the resulting pointers.
if (GEP1->getPointerOperand()->stripPointerCastsAndBarriers() ==
GEP2->getPointerOperand()->stripPointerCastsAndBarriers() &&
if (GEP1->getPointerOperand()->stripPointerCastsAndInvariantGroups() ==
GEP2->getPointerOperand()->stripPointerCastsAndInvariantGroups() &&
GEP1->getPointerOperandType() == GEP2->getPointerOperandType()) {
AliasResult R = aliasSameBasePointerGEPs(GEP1, V1Size, GEP2, V2Size, DL);
// If we couldn't find anything interesting, don't abandon just yet.
Expand Down Expand Up @@ -1578,8 +1578,8 @@ AliasResult BasicAAResult::aliasCheck(const Value *V1, uint64_t V1Size,
return NoAlias;

// Strip off any casts if they exist.
V1 = V1->stripPointerCastsAndBarriers();
V2 = V2->stripPointerCastsAndBarriers();
V1 = V1->stripPointerCastsAndInvariantGroups();
V2 = V2->stripPointerCastsAndInvariantGroups();

// If V1 or V2 is undef, the result is NoAlias because we can always pick a
// value for undef that aliases nothing in the program.
Expand Down
3 changes: 0 additions & 3 deletions lib/Analysis/MemorySSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,9 +352,6 @@ static bool isUseTriviallyOptimizableToLiveOnEntry(AliasAnalysis &AA,
const Instruction *I) {
// If the memory can't be changed, then loads of the memory can't be
// clobbered.
//
// FIXME: We should handle invariant groups, as well. It's a bit harder,
// because we need to pay close attention to invariant group barriers.
return isa<LoadInst>(I) && (I->getMetadata(LLVMContext::MD_invariant_load) ||
AA.pointsToConstantMemory(cast<LoadInst>(I)->
getPointerOperand()));
Expand Down
2 changes: 1 addition & 1 deletion lib/CodeGen/CodeGenPrepare.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1668,7 +1668,7 @@ bool CodeGenPrepare::optimizeCallInst(CallInst *CI, bool &ModifiedDT) {
InsertedInsts.insert(ExtVal);
return true;
}
case Intrinsic::invariant_group_barrier:
case Intrinsic::launder_invariant_group:
II->replaceAllUsesWith(II->getArgOperand(0));
II->eraseFromParent();
return true;
Expand Down
2 changes: 1 addition & 1 deletion lib/CodeGen/SelectionDAG/FastISel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1444,7 +1444,7 @@ bool FastISel::selectIntrinsicCall(const IntrinsicInst *II) {
updateValueMap(II, ResultReg);
return true;
}
case Intrinsic::invariant_group_barrier:
case Intrinsic::launder_invariant_group:
case Intrinsic::expect: {
unsigned ResultReg = getRegForValue(II->getArgOperand(0));
if (!ResultReg)
Expand Down
2 changes: 1 addition & 1 deletion lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5710,7 +5710,7 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
}
case Intrinsic::annotation:
case Intrinsic::ptr_annotation:
case Intrinsic::invariant_group_barrier:
case Intrinsic::launder_invariant_group:
// Drop the intrinsic, but forward the value
setValue(&I, getValue(I.getOperand(0)));
return nullptr;
Expand Down
11 changes: 11 additions & 0 deletions lib/IR/AutoUpgrade.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,17 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
return true;
}
}
if (Name.startswith("invariant.group.barrier")) {
// Rename invariant.group.barrier to launder.invariant.group
auto Args = F->getFunctionType()->params();
Type* ObjectPtr[1] = {Args[0]};
rename(F);
NewFn = Intrinsic::getDeclaration(F->getParent(),
Intrinsic::launder_invariant_group, ObjectPtr);
return true;

}

break;
}
case 'm': {
Expand Down
14 changes: 7 additions & 7 deletions lib/IR/Value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ namespace {
enum PointerStripKind {
PSK_ZeroIndices,
PSK_ZeroIndicesAndAliases,
PSK_ZeroIndicesAndAliasesAndBarriers,
PSK_ZeroIndicesAndAliasesAndInvariantGroups,
PSK_InBoundsConstantIndices,
PSK_InBounds
};
Expand All @@ -518,7 +518,7 @@ static const Value *stripPointerCastsAndOffsets(const Value *V) {
if (auto *GEP = dyn_cast<GEPOperator>(V)) {
switch (StripKind) {
case PSK_ZeroIndicesAndAliases:
case PSK_ZeroIndicesAndAliasesAndBarriers:
case PSK_ZeroIndicesAndAliasesAndInvariantGroups:
case PSK_ZeroIndices:
if (!GEP->hasAllZeroIndices())
return V;
Expand Down Expand Up @@ -546,11 +546,11 @@ static const Value *stripPointerCastsAndOffsets(const Value *V) {
V = RV;
continue;
}
// The result of invariant.group.barrier must alias it's argument,
// The result of launder.invariant.group must alias it's argument,
// but it can't be marked with returned attribute, that's why it needs
// special case.
if (StripKind == PSK_ZeroIndicesAndAliasesAndBarriers &&
CS.getIntrinsicID() == Intrinsic::invariant_group_barrier) {
if (StripKind == PSK_ZeroIndicesAndAliasesAndInvariantGroups &&
CS.getIntrinsicID() == Intrinsic::launder_invariant_group) {
V = CS.getArgOperand(0);
continue;
}
Expand All @@ -576,8 +576,8 @@ const Value *Value::stripInBoundsConstantOffsets() const {
return stripPointerCastsAndOffsets<PSK_InBoundsConstantIndices>(this);
}

const Value *Value::stripPointerCastsAndBarriers() const {
return stripPointerCastsAndOffsets<PSK_ZeroIndicesAndAliasesAndBarriers>(
const Value *Value::stripPointerCastsAndInvariantGroups() const {
return stripPointerCastsAndOffsets<PSK_ZeroIndicesAndAliasesAndInvariantGroups>(
this);
}

Expand Down
4 changes: 2 additions & 2 deletions lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ static bool isCallPromotable(CallInst *CI) {
case Intrinsic::lifetime_end:
case Intrinsic::invariant_start:
case Intrinsic::invariant_end:
case Intrinsic::invariant_group_barrier:
case Intrinsic::launder_invariant_group:
case Intrinsic::objectsize:
return true;
default:
Expand Down Expand Up @@ -878,7 +878,7 @@ bool AMDGPUPromoteAlloca::handleAlloca(AllocaInst &I, bool SufficientLDS) {
}
case Intrinsic::invariant_start:
case Intrinsic::invariant_end:
case Intrinsic::invariant_group_barrier:
case Intrinsic::launder_invariant_group:
Intr->eraseFromParent();
// FIXME: I think the invariant marker should still theoretically apply,
// but the intrinsics need to be changed to accept pointers with any
Expand Down
Loading

0 comments on commit 9648b46

Please sign in to comment.