Skip to content

Commit ff3523f

Browse files
authored
[IR] Drop poison-generating return attributes when necessary (#89138)
Rename has/dropPoisonGeneratingFlagsOrMetadata to has/dropPoisonGeneratingAnnotations and make it also handle nonnull, align and range return attributes on calls, similar to the existing handling for !nonnull, !align and !range metadata.
1 parent 43eb5e2 commit ff3523f

File tree

14 files changed

+95
-21
lines changed

14 files changed

+95
-21
lines changed

llvm/include/llvm/IR/Instruction.h

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -496,14 +496,24 @@ class Instruction : public User,
496496
/// Drops metadata that may generate poison.
497497
void dropPoisonGeneratingMetadata();
498498

499-
/// Return true if this instruction has poison-generating flags or metadata.
500-
bool hasPoisonGeneratingFlagsOrMetadata() const {
501-
return hasPoisonGeneratingFlags() || hasPoisonGeneratingMetadata();
499+
/// Return true if this instruction has poison-generating attribute.
500+
bool hasPoisonGeneratingReturnAttributes() const LLVM_READONLY;
501+
502+
/// Drops return attributes that may generate poison.
503+
void dropPoisonGeneratingReturnAttributes();
504+
505+
/// Return true if this instruction has poison-generating flags,
506+
/// return attributes or metadata.
507+
bool hasPoisonGeneratingAnnotations() const {
508+
return hasPoisonGeneratingFlags() ||
509+
hasPoisonGeneratingReturnAttributes() ||
510+
hasPoisonGeneratingMetadata();
502511
}
503512

504-
/// Drops flags and metadata that may generate poison.
505-
void dropPoisonGeneratingFlagsAndMetadata() {
513+
/// Drops flags, return attributes and metadata that may generate poison.
514+
void dropPoisonGeneratingAnnotations() {
506515
dropPoisonGeneratingFlags();
516+
dropPoisonGeneratingReturnAttributes();
507517
dropPoisonGeneratingMetadata();
508518
}
509519

llvm/include/llvm/IR/Operator.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,10 @@ class Operator : public User {
6464
/// to evaluate to poison despite having non-poison inputs.
6565
bool hasPoisonGeneratingFlags() const;
6666

67-
/// Return true if this operator has poison-generating flags or metadata.
68-
/// The latter is only possible for instructions.
69-
bool hasPoisonGeneratingFlagsOrMetadata() const;
67+
/// Return true if this operator has poison-generating flags,
68+
/// return attributes or metadata. The latter two is only possible for
69+
/// instructions.
70+
bool hasPoisonGeneratingAnnotations() const;
7071
};
7172

7273
/// Utility class for integer operators which may exhibit overflow - Add, Sub,

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4431,7 +4431,7 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
44314431
return nullptr;
44324432
}
44334433
Constant *Res = ConstantFoldInstOperands(I, ConstOps, Q.DL, Q.TLI);
4434-
if (DropFlags && Res && I->hasPoisonGeneratingFlagsOrMetadata())
4434+
if (DropFlags && Res && I->hasPoisonGeneratingAnnotations())
44354435
DropFlags->push_back(I);
44364436
return Res;
44374437
}

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4239,7 +4239,7 @@ bool ScalarEvolution::canReuseInstruction(
42394239
return false;
42404240

42414241
// If the instruction can't create poison, we can recurse to its operands.
4242-
if (I->hasPoisonGeneratingFlagsOrMetadata())
4242+
if (I->hasPoisonGeneratingAnnotations())
42434243
DropPoisonGeneratingInsts.push_back(I);
42444244

42454245
for (Value *Op : I->operands())

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6951,7 +6951,7 @@ static bool canCreateUndefOrPoison(const Operator *Op, UndefPoisonKind Kind,
69516951
bool ConsiderFlagsAndMetadata) {
69526952

69536953
if (ConsiderFlagsAndMetadata && includesPoison(Kind) &&
6954-
Op->hasPoisonGeneratingFlagsOrMetadata())
6954+
Op->hasPoisonGeneratingAnnotations())
69556955
return true;
69566956

69576957
unsigned Opcode = Op->getOpcode();

llvm/lib/IR/Instruction.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
#include "llvm/IR/Instruction.h"
1414
#include "llvm/ADT/DenseSet.h"
1515
#include "llvm/IR/AttributeMask.h"
16+
#include "llvm/IR/Attributes.h"
1617
#include "llvm/IR/Constants.h"
18+
#include "llvm/IR/InstrTypes.h"
1719
#include "llvm/IR/Instructions.h"
1820
#include "llvm/IR/IntrinsicInst.h"
1921
#include "llvm/IR/Intrinsics.h"
@@ -472,6 +474,27 @@ void Instruction::dropPoisonGeneratingMetadata() {
472474
eraseMetadata(LLVMContext::MD_align);
473475
}
474476

477+
bool Instruction::hasPoisonGeneratingReturnAttributes() const {
478+
if (const auto *CB = dyn_cast<CallBase>(this)) {
479+
AttributeSet RetAttrs = CB->getAttributes().getRetAttrs();
480+
return RetAttrs.hasAttribute(Attribute::Range) ||
481+
RetAttrs.hasAttribute(Attribute::Alignment) ||
482+
RetAttrs.hasAttribute(Attribute::NonNull);
483+
}
484+
return false;
485+
}
486+
487+
void Instruction::dropPoisonGeneratingReturnAttributes() {
488+
if (auto *CB = dyn_cast<CallBase>(this)) {
489+
AttributeMask AM;
490+
AM.addAttribute(Attribute::Range);
491+
AM.addAttribute(Attribute::Alignment);
492+
AM.addAttribute(Attribute::NonNull);
493+
CB->removeRetAttrs(AM);
494+
}
495+
assert(!hasPoisonGeneratingReturnAttributes() && "must be kept in sync");
496+
}
497+
475498
void Instruction::dropUBImplyingAttrsAndUnknownMetadata(
476499
ArrayRef<unsigned> KnownIDs) {
477500
dropUnknownNonDebugMetadata(KnownIDs);

llvm/lib/IR/Operator.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,12 @@ bool Operator::hasPoisonGeneratingFlags() const {
5656
}
5757
}
5858

59-
bool Operator::hasPoisonGeneratingFlagsOrMetadata() const {
59+
bool Operator::hasPoisonGeneratingAnnotations() const {
6060
if (hasPoisonGeneratingFlags())
6161
return true;
6262
auto *I = dyn_cast<Instruction>(this);
63-
return I && I->hasPoisonGeneratingMetadata();
63+
return I && (I->hasPoisonGeneratingReturnAttributes() ||
64+
I->hasPoisonGeneratingMetadata());
6465
}
6566

6667
Type *GEPOperator::getSourceElementType() const {

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1340,7 +1340,7 @@ Instruction *InstCombinerImpl::foldSelectValueEquivalence(SelectInst &Sel,
13401340
/* AllowRefinement */ false,
13411341
&DropFlags) == TrueVal) {
13421342
for (Instruction *I : DropFlags) {
1343-
I->dropPoisonGeneratingFlagsAndMetadata();
1343+
I->dropPoisonGeneratingAnnotations();
13441344
Worklist.add(I);
13451345
}
13461346

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4330,7 +4330,7 @@ InstCombinerImpl::pushFreezeToPreventPoisonFromPropagating(FreezeInst &OrigFI) {
43304330
return nullptr;
43314331
}
43324332

4333-
OrigOpInst->dropPoisonGeneratingFlagsAndMetadata();
4333+
OrigOpInst->dropPoisonGeneratingAnnotations();
43344334

43354335
// If all operands are guaranteed to be non-poison, we can drop freeze.
43364336
if (!MaybePoisonOperand)
@@ -4401,7 +4401,7 @@ Instruction *InstCombinerImpl::foldFreezeIntoRecurrence(FreezeInst &FI,
44014401
}
44024402

44034403
for (Instruction *I : DropFlags)
4404-
I->dropPoisonGeneratingFlagsAndMetadata();
4404+
I->dropPoisonGeneratingAnnotations();
44054405

44064406
if (StartNeedsFreeze) {
44074407
Builder.SetInsertPoint(StartBB->getTerminator());

llvm/lib/Transforms/Scalar/BDCE.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ static void clearAssumptionsOfUsers(Instruction *I, DemandedBits &DB) {
7575
Instruction *J = WorkList.pop_back_val();
7676

7777
// NSW, NUW, and exact are based on operands that might have changed.
78-
J->dropPoisonGeneratingFlagsAndMetadata();
78+
J->dropPoisonGeneratingAnnotations();
7979

8080
// We do not have to worry about llvm.assume, because it demands its
8181
// operand, so trivializing can't change it.

llvm/lib/Transforms/Scalar/GuardWidening.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ Value *GuardWideningImpl::freezeAndPush(Value *Orig,
699699
Worklist.push_back(U.get());
700700
}
701701
for (Instruction *I : DropPoisonFlags)
702-
I->dropPoisonGeneratingFlagsAndMetadata();
702+
I->dropPoisonGeneratingAnnotations();
703703

704704
Value *Result = Orig;
705705
for (Value *V : NeedFreeze) {

llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1522,7 +1522,7 @@ Value *SCEVExpander::expand(const SCEV *S) {
15221522
} else {
15231523
for (Instruction *I : DropPoisonGeneratingInsts) {
15241524
rememberFlags(I);
1525-
I->dropPoisonGeneratingFlagsAndMetadata();
1525+
I->dropPoisonGeneratingAnnotations();
15261526
// See if we can re-infer from first principles any of the flags we just
15271527
// dropped.
15281528
if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(I))

llvm/lib/Transforms/Utils/SimplifyIndVar.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,7 @@ bool SimplifyIndvar::eliminateIdentitySCEV(Instruction *UseInst,
768768
return false;
769769

770770
for (Instruction *I : DropPoisonGeneratingInsts)
771-
I->dropPoisonGeneratingFlagsAndMetadata();
771+
I->dropPoisonGeneratingAnnotations();
772772
}
773773

774774
LLVM_DEBUG(dbgs() << "INDVARS: Eliminated identity: " << *UseInst << '\n');

llvm/test/Transforms/InstCombine/freeze.ll

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1069,7 +1069,7 @@ define ptr @freeze_load_dereferenceable(ptr %ptr) {
10691069

10701070
define ptr @freeze_load_dereferenceable_or_null(ptr %ptr) {
10711071
; CHECK-LABEL: @freeze_load_dereferenceable_or_null(
1072-
; CHECK-NEXT: [[P:%.*]] = load ptr, ptr [[PTR:%.*]], align 8, !dereferenceable_or_null !1
1072+
; CHECK-NEXT: [[P:%.*]] = load ptr, ptr [[PTR:%.*]], align 8, !dereferenceable_or_null [[META1]]
10731073
; CHECK-NEXT: ret ptr [[P]]
10741074
;
10751075
%p = load ptr, ptr %ptr, !dereferenceable_or_null !1
@@ -1160,6 +1160,45 @@ define i32 @propagate_drop_flags_trunc(i64 %arg) {
11601160
ret i32 %v1.fr
11611161
}
11621162

1163+
declare i32 @llvm.umax.i32(i32 %a, i32 %b)
1164+
1165+
define i32 @freeze_call_with_range_attr(i32 %a) {
1166+
; CHECK-LABEL: @freeze_call_with_range_attr(
1167+
; CHECK-NEXT: [[Y:%.*]] = lshr i32 2047, [[A:%.*]]
1168+
; CHECK-NEXT: [[Y_FR:%.*]] = freeze i32 [[Y]]
1169+
; CHECK-NEXT: [[X:%.*]] = call i32 @llvm.umax.i32(i32 [[Y_FR]], i32 50)
1170+
; CHECK-NEXT: ret i32 [[X]]
1171+
;
1172+
%y = lshr i32 2047, %a
1173+
%x = call range(i32 0, 2048) i32 @llvm.umax.i32(i32 %y, i32 50)
1174+
%x.fr = freeze i32 %x
1175+
ret i32 %x.fr
1176+
}
1177+
1178+
declare ptr @llvm.ptrmask.p0.i64(ptr, i64)
1179+
1180+
define ptr @freeze_ptrmask_align(ptr %p, i64 noundef %m) {
1181+
; CHECK-LABEL: @freeze_ptrmask_align(
1182+
; CHECK-NEXT: [[P_FR:%.*]] = freeze ptr [[P:%.*]]
1183+
; CHECK-NEXT: [[MASK:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P_FR]], i64 [[M:%.*]])
1184+
; CHECK-NEXT: ret ptr [[MASK]]
1185+
;
1186+
%mask = call align(4) ptr @llvm.ptrmask.p0.i64(ptr %p, i64 %m)
1187+
%fr = freeze ptr %mask
1188+
ret ptr %fr
1189+
}
1190+
1191+
define ptr @freeze_ptrmask_nonnull(ptr %p, i64 noundef %m) {
1192+
; CHECK-LABEL: @freeze_ptrmask_nonnull(
1193+
; CHECK-NEXT: [[P_FR:%.*]] = freeze ptr [[P:%.*]]
1194+
; CHECK-NEXT: [[MASK:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P_FR]], i64 [[M:%.*]])
1195+
; CHECK-NEXT: ret ptr [[MASK]]
1196+
;
1197+
%mask = call nonnull ptr @llvm.ptrmask.p0.i64(ptr %p, i64 %m)
1198+
%fr = freeze ptr %mask
1199+
ret ptr %fr
1200+
}
1201+
11631202
!0 = !{}
11641203
!1 = !{i64 4}
11651204
!2 = !{i32 0, i32 100}

0 commit comments

Comments
 (0)