[ValueTracking] Loads with !dereferenceable metadata cannot be undef/poison

A load with !dereferenceable or !dereferenceable_or_null metadata
must return a well-defined (non-undef/poison) value. Effectively
they imply !noundef. This is the same as we do for the
dereferenceable(N) attribute.

This should fix https://github.com/llvm/llvm-project/issues/55672,
or at least the specific case discussed there.

Differential Revision: https://reviews.llvm.org/D126296
This commit is contained in:
Nikita Popov 2022-05-24 15:20:01 +02:00
parent 643df8fa8e
commit 8a6698b523
2 changed files with 5 additions and 5 deletions

View File

@ -5191,7 +5191,9 @@ static bool isGuaranteedNotToBeUndefOrPoison(const Value *V,
}
if (auto *I = dyn_cast<LoadInst>(V))
if (I->getMetadata(LLVMContext::MD_noundef))
if (I->hasMetadata(LLVMContext::MD_noundef) ||
I->hasMetadata(LLVMContext::MD_dereferenceable) ||
I->hasMetadata(LLVMContext::MD_dereferenceable_or_null))
return true;
if (programUndefinedIfUndefOrPoison(V, PoisonOnly))

View File

@ -834,8 +834,7 @@ define i8* @freeze_load_noundef(i8** %ptr) {
define i8* @freeze_load_dereferenceable(i8** %ptr) {
; CHECK-LABEL: @freeze_load_dereferenceable(
; CHECK-NEXT: [[P:%.*]] = load i8*, i8** [[PTR:%.*]], align 8, !dereferenceable !1
; CHECK-NEXT: [[P_FR:%.*]] = freeze i8* [[P]]
; CHECK-NEXT: ret i8* [[P_FR]]
; CHECK-NEXT: ret i8* [[P]]
;
%p = load i8*, i8** %ptr, !dereferenceable !1
%p.fr = freeze i8* %p
@ -845,8 +844,7 @@ define i8* @freeze_load_dereferenceable(i8** %ptr) {
define i8* @freeze_load_dereferenceable_or_null(i8** %ptr) {
; CHECK-LABEL: @freeze_load_dereferenceable_or_null(
; CHECK-NEXT: [[P:%.*]] = load i8*, i8** [[PTR:%.*]], align 8, !dereferenceable_or_null !1
; CHECK-NEXT: [[P_FR:%.*]] = freeze i8* [[P]]
; CHECK-NEXT: ret i8* [[P_FR]]
; CHECK-NEXT: ret i8* [[P]]
;
%p = load i8*, i8** %ptr, !dereferenceable_or_null !1
%p.fr = freeze i8* %p