forked from OSchip/llvm-project
[Attributor] Fix callsite check in AAUndefinedBehavior
This is the next patch of D86842 When we check `noundef` attribute violation at callsites, we do not have to require `nonnull` in the following two cases. 1. An argument is known to be simplified to undef 2. An argument is known to be dead Reviewed By: jdoerfert Differential Revision: https://reviews.llvm.org/D86845
This commit is contained in:
parent
7082381735
commit
a7ca9e09bd
|
@ -2019,34 +2019,35 @@ struct AAUndefinedBehaviorImpl : public AAUndefinedBehavior {
|
|||
if (idx >= Callee->arg_size())
|
||||
break;
|
||||
Value *ArgVal = CB.getArgOperand(idx);
|
||||
if (!ArgVal || !ArgVal->getType()->isPointerTy())
|
||||
continue;
|
||||
IRPosition CalleeArgumentIRP = IRPosition::callsite_argument(CB, idx);
|
||||
if (!CalleeArgumentIRP.hasAttr({Attribute::NoUndef}))
|
||||
continue;
|
||||
auto &NonNullAA = A.getAAFor<AANonNull>(*this, CalleeArgumentIRP,
|
||||
/* TrackDependence */ false);
|
||||
if (!NonNullAA.isKnownNonNull())
|
||||
continue;
|
||||
const auto &ValueSimplifyAA = A.getAAFor<AAValueSimplify>(
|
||||
*this, IRPosition::value(*ArgVal), /* TrackDependence */ false);
|
||||
Optional<Value *> SimplifiedVal =
|
||||
ValueSimplifyAA.getAssumedSimplifiedValue(A);
|
||||
|
||||
if (!ValueSimplifyAA.isKnown())
|
||||
if (!ArgVal)
|
||||
continue;
|
||||
// Here, we handle three cases.
|
||||
// (1) Not having a value means it is dead. (we can replace the value
|
||||
// with undef)
|
||||
// (2) Simplified to null pointer. The argument is a poison value and
|
||||
// violate noundef attribute.
|
||||
// (3) Simplified to undef. The argument violate noundef attriubte.
|
||||
// (2) Simplified to undef. The argument violate noundef attriubte.
|
||||
// (3) Simplified to null pointer where known to be nonnull.
|
||||
// The argument is a poison value and violate noundef attribute.
|
||||
IRPosition CalleeArgumentIRP = IRPosition::callsite_argument(CB, idx);
|
||||
if (!CalleeArgumentIRP.hasAttr({Attribute::NoUndef}))
|
||||
continue;
|
||||
auto &ValueSimplifyAA = A.getAAFor<AAValueSimplify>(
|
||||
*this, IRPosition::value(*ArgVal), /* TrackDependence */ false);
|
||||
if (!ValueSimplifyAA.isKnown())
|
||||
continue;
|
||||
Optional<Value *> SimplifiedVal =
|
||||
ValueSimplifyAA.getAssumedSimplifiedValue(A);
|
||||
if (!SimplifiedVal.hasValue() ||
|
||||
isa<ConstantPointerNull>(*SimplifiedVal.getValue()) ||
|
||||
isa<UndefValue>(*SimplifiedVal.getValue())) {
|
||||
KnownUBInsts.insert(&I);
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
if (!ArgVal->getType()->isPointerTy() ||
|
||||
!isa<ConstantPointerNull>(*SimplifiedVal.getValue()))
|
||||
continue;
|
||||
auto &NonNullAA = A.getAAFor<AANonNull>(*this, CalleeArgumentIRP,
|
||||
/* TrackDependence */ false);
|
||||
if (NonNullAA.isKnownNonNull())
|
||||
KnownUBInsts.insert(&I);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
|
|
@ -1087,3 +1087,61 @@ define void @callsite_noundef_2() {
|
|||
call void @callee_ptr_arg(i32* noundef undef)
|
||||
ret void
|
||||
}
|
||||
|
||||
define i32 @argument_noundef1(i32 noundef %c) {
|
||||
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT____-LABEL: define {{[^@]+}}@argument_noundef1
|
||||
; IS__TUNIT____-SAME: (i32 noundef returned [[C:%.*]]) [[ATTR0]] {
|
||||
; IS__TUNIT____-NEXT: ret i32 [[C]]
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@argument_noundef1
|
||||
; IS__CGSCC____-SAME: (i32 noundef returned [[C:%.*]]) [[ATTR0]] {
|
||||
; IS__CGSCC____-NEXT: ret i32 [[C]]
|
||||
;
|
||||
ret i32 %c
|
||||
}
|
||||
|
||||
define i32 @violate_noundef_nonpointer() {
|
||||
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT____-LABEL: define {{[^@]+}}@violate_noundef_nonpointer
|
||||
; IS__TUNIT____-SAME: () [[ATTR0]] {
|
||||
; IS__TUNIT____-NEXT: unreachable
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@violate_noundef_nonpointer
|
||||
; IS__CGSCC____-SAME: () [[ATTR0]] {
|
||||
; IS__CGSCC____-NEXT: unreachable
|
||||
;
|
||||
%ret = call i32 @argument_noundef1(i32 undef)
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i32* @argument_noundef2(i32* noundef %c) {
|
||||
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT____-LABEL: define {{[^@]+}}@argument_noundef2
|
||||
; IS__TUNIT____-SAME: (i32* nofree noundef readnone returned "no-capture-maybe-returned" [[C:%.*]]) [[ATTR0]] {
|
||||
; IS__TUNIT____-NEXT: ret i32* [[C]]
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@argument_noundef2
|
||||
; IS__CGSCC____-SAME: (i32* nofree noundef readnone returned "no-capture-maybe-returned" [[C:%.*]]) [[ATTR0]] {
|
||||
; IS__CGSCC____-NEXT: ret i32* [[C]]
|
||||
;
|
||||
ret i32* %c
|
||||
}
|
||||
|
||||
define i32* @violate_noundef_pointer() {
|
||||
; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
|
||||
; IS__TUNIT____-LABEL: define {{[^@]+}}@violate_noundef_pointer
|
||||
; IS__TUNIT____-SAME: () [[ATTR0]] {
|
||||
; IS__TUNIT____-NEXT: unreachable
|
||||
;
|
||||
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
||||
; IS__CGSCC____-LABEL: define {{[^@]+}}@violate_noundef_pointer
|
||||
; IS__CGSCC____-SAME: () [[ATTR0]] {
|
||||
; IS__CGSCC____-NEXT: unreachable
|
||||
;
|
||||
%ret = call i32* @argument_noundef2(i32* undef)
|
||||
ret i32* %ret
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue