Skip to content

Commit 407e789

Browse files
philnik777sahas3
authored andcommitted
[InstCombine] Always fold nonnull assumptions into operand bundles (llvm#169923)
Fixes llvm#168688
1 parent a1c2556 commit 407e789

4 files changed

Lines changed: 46 additions & 92 deletions

File tree

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3639,23 +3639,6 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
36393639
return eraseInstFromFunction(*II);
36403640
}
36413641

3642-
// assume( (load addr) != null ) -> add 'nonnull' metadata to load
3643-
// (if assume is valid at the load)
3644-
Instruction *LHS;
3645-
if (match(IIOperand, m_SpecificICmp(ICmpInst::ICMP_NE, m_Instruction(LHS),
3646-
m_Zero())) &&
3647-
LHS->getOpcode() == Instruction::Load &&
3648-
LHS->getType()->isPointerTy() &&
3649-
isValidAssumeForContext(II, LHS, &DT)) {
3650-
MDNode *MD = MDNode::get(II->getContext(), {});
3651-
LHS->setMetadata(LLVMContext::MD_nonnull, MD);
3652-
LHS->setMetadata(LLVMContext::MD_noundef, MD);
3653-
return RemoveConditionFromAssume(II);
3654-
3655-
// TODO: apply nonnull return attributes to calls and invokes
3656-
// TODO: apply range metadata for range check patterns?
3657-
}
3658-
36593642
for (unsigned Idx = 0; Idx < II->getNumOperandBundles(); Idx++) {
36603643
OperandBundleUse OBU = II->getOperandBundleAt(Idx);
36613644

@@ -3710,11 +3693,24 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
37103693
if (OBU.getTagName() == "nonnull" && OBU.Inputs.size() == 1) {
37113694
RetainedKnowledge RK = getKnowledgeFromOperandInAssume(
37123695
*cast<AssumeInst>(II), II->arg_size() + Idx);
3713-
if (!RK || RK.AttrKind != Attribute::NonNull ||
3714-
!isKnownNonZero(RK.WasOn,
3715-
getSimplifyQuery().getWithInstruction(II)))
3696+
if (!RK || RK.AttrKind != Attribute::NonNull)
37163697
continue;
3717-
return CallBase::removeOperandBundle(II, OBU.getTagID());
3698+
3699+
// Drop assume if we can prove nonnull without it
3700+
if (isKnownNonZero(RK.WasOn, getSimplifyQuery().getWithInstruction(II)))
3701+
return CallBase::removeOperandBundle(II, OBU.getTagID());
3702+
3703+
// Fold the assume into metadata if it's valid at the load
3704+
if (auto *LI = dyn_cast<LoadInst>(RK.WasOn);
3705+
LI &&
3706+
isValidAssumeForContext(II, LI, &DT, /*AllowEphemerals=*/true)) {
3707+
MDNode *MD = MDNode::get(II->getContext(), {});
3708+
LI->setMetadata(LLVMContext::MD_nonnull, MD);
3709+
LI->setMetadata(LLVMContext::MD_noundef, MD);
3710+
return CallBase::removeOperandBundle(II, OBU.getTagID());
3711+
}
3712+
3713+
// TODO: apply nonnull return attributes to calls and invokes
37183714
}
37193715
}
37203716

@@ -3723,14 +3719,13 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
37233719
// call void @llvm.assume(i1 %A)
37243720
// into
37253721
// call void @llvm.assume(i1 true) [ "nonnull"(i32* %PTR) ]
3726-
if (EnableKnowledgeRetention &&
3727-
match(IIOperand,
3722+
if (match(IIOperand,
37283723
m_SpecificICmp(ICmpInst::ICMP_NE, m_Value(A), m_Zero())) &&
37293724
A->getType()->isPointerTy()) {
37303725
if (auto *Replacement = buildAssumeFromKnowledge(
37313726
{RetainedKnowledge{Attribute::NonNull, 0, A}}, Next, &AC, &DT)) {
37323727

3733-
Replacement->insertBefore(Next->getIterator());
3728+
InsertNewInstBefore(Replacement, Next->getIterator());
37343729
AC.registerAssumption(Replacement);
37353730
return RemoveConditionFromAssume(II);
37363731
}

llvm/test/Transforms/InstCombine/assume-icmp-null-select.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ define ptr @example2(ptr %x) {
2424
; CHECK-NEXT: [[Y:%.*]] = load ptr, ptr [[X:%.*]], align 8
2525
; CHECK-NEXT: [[Y_IS_NULL:%.*]] = icmp eq ptr [[Y]], null
2626
; CHECK-NEXT: [[RES:%.*]] = select i1 [[Y_IS_NULL]], ptr null, ptr [[X]]
27-
; CHECK-NEXT: [[NONNULL:%.*]] = icmp ne ptr [[RES]], null
28-
; CHECK-NEXT: call void @llvm.assume(i1 [[NONNULL]])
27+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[RES]]) ]
2928
; CHECK-NEXT: ret ptr [[RES]]
3029
;
3130
%y = load ptr, ptr %x, align 8

llvm/test/Transforms/InstCombine/assume-loop-align.ll

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,3 @@ declare void @llvm.assume(i1) #1
6060

6161
attributes #0 = { nounwind uwtable }
6262
attributes #1 = { nounwind }
63-

llvm/test/Transforms/InstCombine/assume.ll

Lines changed: 26 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -339,28 +339,16 @@ define i1 @nonnull2(ptr %a) {
339339
; if the assume is control dependent on something else
340340

341341
define i1 @nonnull3(ptr %a, i1 %control) {
342-
; FIXME: in the BUNDLES version we could duplicate the load and keep the assume nonnull.
343-
; DEFAULT-LABEL: @nonnull3(
344-
; DEFAULT-NEXT: entry:
345-
; DEFAULT-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
346-
; DEFAULT-NEXT: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null
347-
; DEFAULT-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
348-
; DEFAULT: taken:
349-
; DEFAULT-NEXT: tail call void @llvm.assume(i1 [[CMP]])
350-
; DEFAULT-NEXT: ret i1 false
351-
; DEFAULT: not_taken:
352-
; DEFAULT-NEXT: [[RVAL_2:%.*]] = icmp sgt ptr [[LOAD]], null
353-
; DEFAULT-NEXT: ret i1 [[RVAL_2]]
354-
;
355-
; BUNDLES-LABEL: @nonnull3(
356-
; BUNDLES-NEXT: entry:
357-
; BUNDLES-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
358-
; BUNDLES: taken:
359-
; BUNDLES-NEXT: ret i1 false
360-
; BUNDLES: not_taken:
361-
; BUNDLES-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
362-
; BUNDLES-NEXT: [[RVAL_2:%.*]] = icmp sgt ptr [[LOAD]], null
363-
; BUNDLES-NEXT: ret i1 [[RVAL_2]]
342+
; FIXME: we could duplicate the load and keep the assume nonnull.
343+
; CHECK-LABEL: @nonnull3(
344+
; CHECK-NEXT: entry:
345+
; CHECK-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
346+
; CHECK: taken:
347+
; CHECK-NEXT: ret i1 false
348+
; CHECK: not_taken:
349+
; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
350+
; CHECK-NEXT: [[RVAL_2:%.*]] = icmp sgt ptr [[LOAD]], null
351+
; CHECK-NEXT: ret i1 [[RVAL_2]]
364352
;
365353
entry:
366354
%load = load ptr, ptr %a
@@ -380,18 +368,11 @@ not_taken:
380368
; interrupted by an exception being thrown
381369

382370
define i1 @nonnull4(ptr %a) {
383-
; DEFAULT-LABEL: @nonnull4(
384-
; DEFAULT-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
385-
; DEFAULT-NEXT: tail call void @escape(ptr [[LOAD]])
386-
; DEFAULT-NEXT: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null
387-
; DEFAULT-NEXT: tail call void @llvm.assume(i1 [[CMP]])
388-
; DEFAULT-NEXT: ret i1 false
389-
;
390-
; BUNDLES-LABEL: @nonnull4(
391-
; BUNDLES-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
392-
; BUNDLES-NEXT: tail call void @escape(ptr [[LOAD]])
393-
; BUNDLES-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[LOAD]]) ]
394-
; BUNDLES-NEXT: ret i1 false
371+
; CHECK-LABEL: @nonnull4(
372+
; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
373+
; CHECK-NEXT: tail call void @escape(ptr [[LOAD]])
374+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[LOAD]]) ]
375+
; CHECK-NEXT: ret i1 false
395376
;
396377
%load = load ptr, ptr %a
397378
;; This call may throw!
@@ -515,27 +496,15 @@ define i32 @PR40940(<4 x i8> %x) {
515496
}
516497

517498
define i1 @nonnull3A(ptr %a, i1 %control) {
518-
; DEFAULT-LABEL: @nonnull3A(
519-
; DEFAULT-NEXT: entry:
520-
; DEFAULT-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
521-
; DEFAULT-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
522-
; DEFAULT: taken:
523-
; DEFAULT-NEXT: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null
524-
; DEFAULT-NEXT: call void @llvm.assume(i1 [[CMP]])
525-
; DEFAULT-NEXT: ret i1 [[CMP]]
526-
; DEFAULT: not_taken:
527-
; DEFAULT-NEXT: [[RVAL_2:%.*]] = icmp sgt ptr [[LOAD]], null
528-
; DEFAULT-NEXT: ret i1 [[RVAL_2]]
529-
;
530-
; BUNDLES-LABEL: @nonnull3A(
531-
; BUNDLES-NEXT: entry:
532-
; BUNDLES-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
533-
; BUNDLES: taken:
534-
; BUNDLES-NEXT: ret i1 true
535-
; BUNDLES: not_taken:
536-
; BUNDLES-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
537-
; BUNDLES-NEXT: [[RVAL_2:%.*]] = icmp sgt ptr [[LOAD]], null
538-
; BUNDLES-NEXT: ret i1 [[RVAL_2]]
499+
; CHECK-LABEL: @nonnull3A(
500+
; CHECK-NEXT: entry:
501+
; CHECK-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
502+
; CHECK: taken:
503+
; CHECK-NEXT: ret i1 true
504+
; CHECK: not_taken:
505+
; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
506+
; CHECK-NEXT: [[RVAL_2:%.*]] = icmp sgt ptr [[LOAD]], null
507+
; CHECK-NEXT: ret i1 [[RVAL_2]]
539508
;
540509
entry:
541510
%load = load ptr, ptr %a
@@ -635,16 +604,8 @@ not_taken:
635604
}
636605

637606
define void @nonnull_only_ephemeral_use(ptr %p) {
638-
; DEFAULT-LABEL: @nonnull_only_ephemeral_use(
639-
; DEFAULT-NEXT: [[A:%.*]] = load ptr, ptr [[P:%.*]], align 8
640-
; DEFAULT-NEXT: [[CMP:%.*]] = icmp ne ptr [[A]], null
641-
; DEFAULT-NEXT: tail call void @llvm.assume(i1 [[CMP]])
642-
; DEFAULT-NEXT: ret void
643-
;
644-
; BUNDLES-LABEL: @nonnull_only_ephemeral_use(
645-
; BUNDLES-NEXT: [[A:%.*]] = load ptr, ptr [[P:%.*]], align 8
646-
; BUNDLES-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[A]]) ]
647-
; BUNDLES-NEXT: ret void
607+
; CHECK-LABEL: @nonnull_only_ephemeral_use(
608+
; CHECK-NEXT: ret void
648609
;
649610
%a = load ptr, ptr %p
650611
%cmp = icmp ne ptr %a, null

0 commit comments

Comments
 (0)