[llvm] Take poison-generating attributes into account (PR #89138)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 17 13:33:14 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Andreas Jonson (andjo403)
<details>
<summary>Changes</summary>
Split out and fixed comments from #<!-- -->88776
CC @<!-- -->nikic
---
Full diff: https://github.com/llvm/llvm-project/pull/89138.diff
14 Files Affected:
- (modified) llvm/include/llvm/IR/Instruction.h (+14-5)
- (modified) llvm/include/llvm/IR/Operator.h (+3-3)
- (modified) llvm/lib/Analysis/InstructionSimplify.cpp (+1-1)
- (modified) llvm/lib/Analysis/ScalarEvolution.cpp (+1-1)
- (modified) llvm/lib/Analysis/ValueTracking.cpp (+1-1)
- (modified) llvm/lib/IR/Instruction.cpp (+23)
- (modified) llvm/lib/IR/Operator.cpp (+3-2)
- (modified) llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp (+1-1)
- (modified) llvm/lib/Transforms/InstCombine/InstructionCombining.cpp (+2-2)
- (modified) llvm/lib/Transforms/Scalar/BDCE.cpp (+1-1)
- (modified) llvm/lib/Transforms/Scalar/GuardWidening.cpp (+1-1)
- (modified) llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp (+1-1)
- (modified) llvm/lib/Transforms/Utils/SimplifyIndVar.cpp (+1-1)
- (modified) llvm/test/Transforms/InstCombine/freeze.ll (+40-1)
``````````diff
diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h
index 6e0874c5b04f29..0c6c16eb61dd3f 100644
--- a/llvm/include/llvm/IR/Instruction.h
+++ b/llvm/include/llvm/IR/Instruction.h
@@ -496,14 +496,23 @@ class Instruction : public User,
/// Drops metadata that may generate poison.
void dropPoisonGeneratingMetadata();
- /// Return true if this instruction has poison-generating flags or metadata.
- bool hasPoisonGeneratingFlagsOrMetadata() const {
- return hasPoisonGeneratingFlags() || hasPoisonGeneratingMetadata();
+ /// Return true if this instruction has poison-generating attribute.
+ bool hasPoisonGeneratingAttribute() const LLVM_READONLY;
+
+ /// Drops attributes that may generate poison.
+ void dropPoisonGeneratingAttribute();
+
+ /// Return true if this instruction has poison-generating flags, attributes or
+ /// metadata.
+ bool hasPoisonGeneratingAnnotations() const {
+ return hasPoisonGeneratingFlags() || hasPoisonGeneratingAttribute() ||
+ hasPoisonGeneratingMetadata();
}
- /// Drops flags and metadata that may generate poison.
- void dropPoisonGeneratingFlagsAndMetadata() {
+ /// Drops flags, attributes and metadata that may generate poison.
+ void dropPoisonGeneratingAnnotations() {
dropPoisonGeneratingFlags();
+ dropPoisonGeneratingAttribute();
dropPoisonGeneratingMetadata();
}
diff --git a/llvm/include/llvm/IR/Operator.h b/llvm/include/llvm/IR/Operator.h
index e14a916b474935..860f10adab005d 100644
--- a/llvm/include/llvm/IR/Operator.h
+++ b/llvm/include/llvm/IR/Operator.h
@@ -64,9 +64,9 @@ class Operator : public User {
/// to evaluate to poison despite having non-poison inputs.
bool hasPoisonGeneratingFlags() const;
- /// Return true if this operator has poison-generating flags or metadata.
- /// The latter is only possible for instructions.
- bool hasPoisonGeneratingFlagsOrMetadata() const;
+ /// Return true if this operator has poison-generating flags, attributes or
+ /// metadata. The latter two is only possible for instructions.
+ bool hasPoisonGeneratingAnnotations() const;
};
/// Utility class for integer operators which may exhibit overflow - Add, Sub,
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 06ba5ca4c6b352..431ad37d0a9e86 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4431,7 +4431,7 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
return nullptr;
}
Constant *Res = ConstantFoldInstOperands(I, ConstOps, Q.DL, Q.TLI);
- if (DropFlags && Res && I->hasPoisonGeneratingFlagsOrMetadata())
+ if (DropFlags && Res && I->hasPoisonGeneratingAnnotations())
DropFlags->push_back(I);
return Res;
}
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 95440dda3b4c0e..93f885c5d5ad8b 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -4239,7 +4239,7 @@ bool ScalarEvolution::canReuseInstruction(
return false;
// If the instruction can't create poison, we can recurse to its operands.
- if (I->hasPoisonGeneratingFlagsOrMetadata())
+ if (I->hasPoisonGeneratingAnnotations())
DropPoisonGeneratingInsts.push_back(I);
for (Value *Op : I->operands())
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index ab2f43e1033fa1..695d0b0b1a2f87 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -6951,7 +6951,7 @@ static bool canCreateUndefOrPoison(const Operator *Op, UndefPoisonKind Kind,
bool ConsiderFlagsAndMetadata) {
if (ConsiderFlagsAndMetadata && includesPoison(Kind) &&
- Op->hasPoisonGeneratingFlagsOrMetadata())
+ Op->hasPoisonGeneratingAnnotations())
return true;
unsigned Opcode = Op->getOpcode();
diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp
index b9efe9cdcfe310..4df5ee63ac183c 100644
--- a/llvm/lib/IR/Instruction.cpp
+++ b/llvm/lib/IR/Instruction.cpp
@@ -13,7 +13,9 @@
#include "llvm/IR/Instruction.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/IR/AttributeMask.h"
+#include "llvm/IR/Attributes.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
@@ -472,6 +474,27 @@ void Instruction::dropPoisonGeneratingMetadata() {
eraseMetadata(LLVMContext::MD_align);
}
+bool Instruction::hasPoisonGeneratingAttribute() const {
+ if (const auto *CB = dyn_cast<CallBase>(this)) {
+ AttributeSet RetAttrs = CB->getAttributes().getRetAttrs();
+ return RetAttrs.hasAttribute(Attribute::Range) ||
+ RetAttrs.hasAttribute(Attribute::Alignment) ||
+ RetAttrs.hasAttribute(Attribute::NonNull);
+ }
+ return false;
+}
+
+void Instruction::dropPoisonGeneratingAttribute() {
+ if (auto *CB = dyn_cast<CallBase>(this)) {
+ AttributeMask AM;
+ AM.addAttribute(Attribute::Range);
+ AM.addAttribute(Attribute::Alignment);
+ AM.addAttribute(Attribute::NonNull);
+ CB->removeRetAttrs(AM);
+ }
+ assert(!hasPoisonGeneratingAttribute() && "must be kept in sync");
+}
+
void Instruction::dropUBImplyingAttrsAndUnknownMetadata(
ArrayRef<unsigned> KnownIDs) {
dropUnknownNonDebugMetadata(KnownIDs);
diff --git a/llvm/lib/IR/Operator.cpp b/llvm/lib/IR/Operator.cpp
index ccc624d854429c..eeefd4178ce37d 100644
--- a/llvm/lib/IR/Operator.cpp
+++ b/llvm/lib/IR/Operator.cpp
@@ -56,11 +56,12 @@ bool Operator::hasPoisonGeneratingFlags() const {
}
}
-bool Operator::hasPoisonGeneratingFlagsOrMetadata() const {
+bool Operator::hasPoisonGeneratingAnnotations() const {
if (hasPoisonGeneratingFlags())
return true;
auto *I = dyn_cast<Instruction>(this);
- return I && I->hasPoisonGeneratingMetadata();
+ return I && (I->hasPoisonGeneratingAttribute() ||
+ I->hasPoisonGeneratingMetadata());
}
Type *GEPOperator::getSourceElementType() const {
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 2d78fcee1152d7..9f6a4b2f395987 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1340,7 +1340,7 @@ Instruction *InstCombinerImpl::foldSelectValueEquivalence(SelectInst &Sel,
/* AllowRefinement */ false,
&DropFlags) == TrueVal) {
for (Instruction *I : DropFlags) {
- I->dropPoisonGeneratingFlagsAndMetadata();
+ I->dropPoisonGeneratingAnnotations();
Worklist.add(I);
}
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 5a144cc7378962..e08d0a80e76536 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -4330,7 +4330,7 @@ InstCombinerImpl::pushFreezeToPreventPoisonFromPropagating(FreezeInst &OrigFI) {
return nullptr;
}
- OrigOpInst->dropPoisonGeneratingFlagsAndMetadata();
+ OrigOpInst->dropPoisonGeneratingAnnotations();
// If all operands are guaranteed to be non-poison, we can drop freeze.
if (!MaybePoisonOperand)
@@ -4401,7 +4401,7 @@ Instruction *InstCombinerImpl::foldFreezeIntoRecurrence(FreezeInst &FI,
}
for (Instruction *I : DropFlags)
- I->dropPoisonGeneratingFlagsAndMetadata();
+ I->dropPoisonGeneratingAnnotations();
if (StartNeedsFreeze) {
Builder.SetInsertPoint(StartBB->getTerminator());
diff --git a/llvm/lib/Transforms/Scalar/BDCE.cpp b/llvm/lib/Transforms/Scalar/BDCE.cpp
index 4aa87a84f115a1..d96dbca30fdb15 100644
--- a/llvm/lib/Transforms/Scalar/BDCE.cpp
+++ b/llvm/lib/Transforms/Scalar/BDCE.cpp
@@ -75,7 +75,7 @@ static void clearAssumptionsOfUsers(Instruction *I, DemandedBits &DB) {
Instruction *J = WorkList.pop_back_val();
// NSW, NUW, and exact are based on operands that might have changed.
- J->dropPoisonGeneratingFlagsAndMetadata();
+ J->dropPoisonGeneratingAnnotations();
// We do not have to worry about llvm.assume, because it demands its
// operand, so trivializing can't change it.
diff --git a/llvm/lib/Transforms/Scalar/GuardWidening.cpp b/llvm/lib/Transforms/Scalar/GuardWidening.cpp
index d3787b28347c9e..b6498c4e36963a 100644
--- a/llvm/lib/Transforms/Scalar/GuardWidening.cpp
+++ b/llvm/lib/Transforms/Scalar/GuardWidening.cpp
@@ -699,7 +699,7 @@ Value *GuardWideningImpl::freezeAndPush(Value *Orig,
Worklist.push_back(U.get());
}
for (Instruction *I : DropPoisonFlags)
- I->dropPoisonGeneratingFlagsAndMetadata();
+ I->dropPoisonGeneratingAnnotations();
Value *Result = Orig;
for (Value *V : NeedFreeze) {
diff --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
index 74cffbc005c82d..0feea0a4233cd1 100644
--- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
+++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
@@ -1522,7 +1522,7 @@ Value *SCEVExpander::expand(const SCEV *S) {
} else {
for (Instruction *I : DropPoisonGeneratingInsts) {
rememberFlags(I);
- I->dropPoisonGeneratingFlagsAndMetadata();
+ I->dropPoisonGeneratingAnnotations();
// See if we can re-infer from first principles any of the flags we just
// dropped.
if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(I))
diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
index 31be7d62c8d1d8..912c02c2ed3ae5 100644
--- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -768,7 +768,7 @@ bool SimplifyIndvar::eliminateIdentitySCEV(Instruction *UseInst,
return false;
for (Instruction *I : DropPoisonGeneratingInsts)
- I->dropPoisonGeneratingFlagsAndMetadata();
+ I->dropPoisonGeneratingAnnotations();
}
LLVM_DEBUG(dbgs() << "INDVARS: Eliminated identity: " << *UseInst << '\n');
diff --git a/llvm/test/Transforms/InstCombine/freeze.ll b/llvm/test/Transforms/InstCombine/freeze.ll
index 668f3033ed4b73..adcf7d50f413be 100644
--- a/llvm/test/Transforms/InstCombine/freeze.ll
+++ b/llvm/test/Transforms/InstCombine/freeze.ll
@@ -1069,7 +1069,7 @@ define ptr @freeze_load_dereferenceable(ptr %ptr) {
define ptr @freeze_load_dereferenceable_or_null(ptr %ptr) {
; CHECK-LABEL: @freeze_load_dereferenceable_or_null(
-; CHECK-NEXT: [[P:%.*]] = load ptr, ptr [[PTR:%.*]], align 8, !dereferenceable_or_null !1
+; CHECK-NEXT: [[P:%.*]] = load ptr, ptr [[PTR:%.*]], align 8, !dereferenceable_or_null [[META1]]
; CHECK-NEXT: ret ptr [[P]]
;
%p = load ptr, ptr %ptr, !dereferenceable_or_null !1
@@ -1160,6 +1160,45 @@ define i32 @propagate_drop_flags_trunc(i64 %arg) {
ret i32 %v1.fr
}
+declare i32 @llvm.umax.i32(i32 %a, i32 %b)
+
+define i32 @freeze_call_with_range_attr(i32 %a) {
+; CHECK-LABEL: @freeze_call_with_range_attr(
+; CHECK-NEXT: [[Y:%.*]] = lshr i32 2047, [[A:%.*]]
+; CHECK-NEXT: [[Y_FR:%.*]] = freeze i32 [[Y]]
+; CHECK-NEXT: [[X:%.*]] = call i32 @llvm.umax.i32(i32 [[Y_FR]], i32 50)
+; CHECK-NEXT: ret i32 [[X]]
+;
+ %y = lshr i32 2047, %a
+ %x = call range(i32 0, 2048) i32 @llvm.umax.i32(i32 %y, i32 50)
+ %x.fr = freeze i32 %x
+ ret i32 %x.fr
+}
+
+declare ptr @llvm.ptrmask.p0.i64(ptr, i64)
+
+define ptr @freeze_ptrmask_align(ptr %p, i64 noundef %m) {
+; CHECK-LABEL: @freeze_ptrmask_align(
+; CHECK-NEXT: [[P_FR:%.*]] = freeze ptr [[P:%.*]]
+; CHECK-NEXT: [[MASK:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P_FR]], i64 [[M:%.*]])
+; CHECK-NEXT: ret ptr [[MASK]]
+;
+ %mask = call align(4) ptr @llvm.ptrmask.p0.i64(ptr %p, i64 %m)
+ %fr = freeze ptr %mask
+ ret ptr %fr
+}
+
+define ptr @freeze_ptrmask_nonnull(ptr %p, i64 noundef %m) {
+; CHECK-LABEL: @freeze_ptrmask_nonnull(
+; CHECK-NEXT: [[P_FR:%.*]] = freeze ptr [[P:%.*]]
+; CHECK-NEXT: [[MASK:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P_FR]], i64 [[M:%.*]])
+; CHECK-NEXT: ret ptr [[MASK]]
+;
+ %mask = call nonnull ptr @llvm.ptrmask.p0.i64(ptr %p, i64 %m)
+ %fr = freeze ptr %mask
+ ret ptr %fr
+}
+
!0 = !{}
!1 = !{i64 4}
!2 = !{i32 0, i32 100}
``````````
</details>
https://github.com/llvm/llvm-project/pull/89138
More information about the llvm-commits
mailing list