Index: llvm/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/lib/Analysis/ValueTracking.cpp +++ llvm/lib/Analysis/ValueTracking.cpp @@ -5201,6 +5201,8 @@ case Instruction::CallBr: case Instruction::Invoke: { const auto *CB = cast(Op); + if (CB->hasMetadata(LLVMContext::MD_range)) + return false; return !CB->hasRetAttr(Attribute::NoUndef); } case Instruction::InsertElement: @@ -5395,7 +5397,8 @@ if (auto *I = dyn_cast(V)) if (I->hasMetadata(LLVMContext::MD_noundef) || I->hasMetadata(LLVMContext::MD_dereferenceable) || - I->hasMetadata(LLVMContext::MD_dereferenceable_or_null)) + I->hasMetadata(LLVMContext::MD_dereferenceable_or_null) || + I->hasMetadata(LLVMContext::MD_range)) return true; if (programUndefinedIfUndefOrPoison(V, PoisonOnly)) Index: llvm/test/Transforms/Attributor/dereferenceable-1.ll =================================================================== --- llvm/test/Transforms/Attributor/dereferenceable-1.ll +++ llvm/test/Transforms/Attributor/dereferenceable-1.ll @@ -376,7 +376,7 @@ define internal void @fill_range_not_inbounds(i32* %p, i64 %start){ ; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; CHECK-LABEL: define {{[^@]+}}@fill_range_not_inbounds -; CHECK-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64 [[START:%.*]]) #[[ATTR2]] { +; CHECK-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64 noundef [[START:%.*]]) #[[ATTR2]] { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[START]], 9 ; CHECK-NEXT: br label [[FOR_BODY:%.*]] @@ -412,7 +412,7 @@ define internal void @fill_range_inbounds(i32* %p, i64 %start){ ; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; CHECK-LABEL: define {{[^@]+}}@fill_range_inbounds -; CHECK-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64 [[START:%.*]]) #[[ATTR2]] { +; CHECK-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64 noundef [[START:%.*]]) #[[ATTR2]] { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[START]], 9 ; CHECK-NEXT: br label [[FOR_BODY:%.*]] @@ -450,8 +450,8 @@ ; TUNIT-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64* nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[RANGE:%.*]]) #[[ATTR3:[0-9]+]] { ; TUNIT-NEXT: entry: ; TUNIT-NEXT: [[TMP0:%.*]] = load i64, i64* [[RANGE]], align 8, !range [[RNG0:![0-9]+]] -; TUNIT-NEXT: tail call void @fill_range_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) #[[ATTR6:[0-9]+]] -; TUNIT-NEXT: tail call void @fill_range_not_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) #[[ATTR6]] +; TUNIT-NEXT: tail call void @fill_range_inbounds(i32* nocapture nofree writeonly [[P]], i64 noundef [[TMP0]]) #[[ATTR6:[0-9]+]] +; TUNIT-NEXT: tail call void @fill_range_not_inbounds(i32* nocapture nofree writeonly [[P]], i64 noundef [[TMP0]]) #[[ATTR6]] ; TUNIT-NEXT: ret void ; ; CGSCC: Function Attrs: argmemonly nofree nosync nounwind willreturn @@ -459,8 +459,8 @@ ; CGSCC-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64* nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[RANGE:%.*]]) #[[ATTR3:[0-9]+]] { ; CGSCC-NEXT: entry: ; CGSCC-NEXT: [[TMP0:%.*]] = load i64, i64* [[RANGE]], align 8, !range [[RNG0:![0-9]+]] -; CGSCC-NEXT: tail call void @fill_range_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) #[[ATTR6:[0-9]+]] -; CGSCC-NEXT: tail call void @fill_range_not_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) #[[ATTR6]] +; CGSCC-NEXT: tail call void @fill_range_inbounds(i32* nocapture nofree writeonly [[P]], i64 noundef [[TMP0]]) #[[ATTR6:[0-9]+]] +; CGSCC-NEXT: tail call void @fill_range_not_inbounds(i32* nocapture nofree writeonly [[P]], i64 noundef [[TMP0]]) #[[ATTR6]] ; CGSCC-NEXT: ret void ; entry: Index: llvm/test/Transforms/Attributor/range.ll =================================================================== --- llvm/test/Transforms/Attributor/range.ll +++ llvm/test/Transforms/Attributor/range.ll @@ -19,13 +19,13 @@ ; TUNIT: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; TUNIT-LABEL: define {{[^@]+}}@test0-range-check ; TUNIT-SAME: (i32* nocapture nofree readonly align 4 [[P:%.*]]) #[[ATTR0]] { -; TUNIT-NEXT: [[A:%.*]] = tail call i32 @test0(i32* nocapture nofree readonly align 4 [[P]]) #[[ATTR3:[0-9]+]], !range [[RNG0]] +; TUNIT-NEXT: [[A:%.*]] = tail call noundef i32 @test0(i32* nocapture nofree readonly align 4 [[P]]) #[[ATTR3:[0-9]+]], !range [[RNG0]] ; TUNIT-NEXT: ret i32 [[A]] ; ; CGSCC: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn ; CGSCC-LABEL: define {{[^@]+}}@test0-range-check ; CGSCC-SAME: (i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR1:[0-9]+]] { -; CGSCC-NEXT: [[A:%.*]] = tail call i32 @test0(i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P]]) #[[ATTR5:[0-9]+]] +; CGSCC-NEXT: [[A:%.*]] = tail call noundef i32 @test0(i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P]]) #[[ATTR5:[0-9]+]] ; CGSCC-NEXT: ret i32 [[A]] ; %a = tail call i32 @test0(i32* %p) @@ -124,64 +124,64 @@ ; CGSCC-NEXT: [[CMP_EQ_4:%.*]] = icmp eq i32 [[RET]], 1 ; CGSCC-NEXT: [[CMP_EQ_5:%.*]] = icmp eq i32 [[RET]], 0 ; CGSCC-NEXT: [[CMP_EQ_6:%.*]] = icmp eq i32 [[RET]], -1 -; CGSCC-NEXT: tail call void @use3(i1 [[CMP_EQ_1]], i1 [[CMP_EQ_2]], i1 [[CMP_EQ_3]]) -; CGSCC-NEXT: tail call void @use3(i1 [[CMP_EQ_4]], i1 [[CMP_EQ_5]], i1 [[CMP_EQ_6]]) +; CGSCC-NEXT: tail call void @use3(i1 noundef [[CMP_EQ_1]], i1 noundef [[CMP_EQ_2]], i1 noundef [[CMP_EQ_3]]) +; CGSCC-NEXT: tail call void @use3(i1 noundef [[CMP_EQ_4]], i1 noundef [[CMP_EQ_5]], i1 noundef [[CMP_EQ_6]]) ; CGSCC-NEXT: [[CMP_NE_1:%.*]] = icmp ne i32 [[RET]], 10 ; CGSCC-NEXT: [[CMP_NE_2:%.*]] = icmp ne i32 [[RET]], 9 ; CGSCC-NEXT: [[CMP_NE_3:%.*]] = icmp ne i32 [[RET]], 8 ; CGSCC-NEXT: [[CMP_NE_4:%.*]] = icmp ne i32 [[RET]], 1 ; CGSCC-NEXT: [[CMP_NE_5:%.*]] = icmp ne i32 [[RET]], 0 ; CGSCC-NEXT: [[CMP_NE_6:%.*]] = icmp ne i32 [[RET]], -1 -; CGSCC-NEXT: tail call void @use3(i1 [[CMP_NE_1]], i1 [[CMP_NE_2]], i1 [[CMP_NE_3]]) -; CGSCC-NEXT: tail call void @use3(i1 [[CMP_NE_4]], i1 [[CMP_NE_5]], i1 [[CMP_NE_6]]) +; CGSCC-NEXT: tail call void @use3(i1 noundef [[CMP_NE_1]], i1 noundef [[CMP_NE_2]], i1 noundef [[CMP_NE_3]]) +; CGSCC-NEXT: tail call void @use3(i1 noundef [[CMP_NE_4]], i1 noundef [[CMP_NE_5]], i1 noundef [[CMP_NE_6]]) ; CGSCC-NEXT: [[CMP_UGT_1:%.*]] = icmp ugt i32 [[RET]], 10 ; CGSCC-NEXT: [[CMP_UGT_2:%.*]] = icmp ugt i32 [[RET]], 9 ; CGSCC-NEXT: [[CMP_UGT_3:%.*]] = icmp ugt i32 [[RET]], 8 ; CGSCC-NEXT: [[CMP_UGT_4:%.*]] = icmp ugt i32 [[RET]], 1 ; CGSCC-NEXT: [[CMP_UGT_5:%.*]] = icmp ugt i32 [[RET]], 0 ; CGSCC-NEXT: [[CMP_UGT_6:%.*]] = icmp ugt i32 [[RET]], -1 -; CGSCC-NEXT: tail call void @use3(i1 [[CMP_UGT_1]], i1 [[CMP_UGT_2]], i1 [[CMP_UGT_3]]) -; CGSCC-NEXT: tail call void @use3(i1 [[CMP_UGT_4]], i1 [[CMP_UGT_5]], i1 [[CMP_UGT_6]]) +; CGSCC-NEXT: tail call void @use3(i1 noundef [[CMP_UGT_1]], i1 noundef [[CMP_UGT_2]], i1 noundef [[CMP_UGT_3]]) +; CGSCC-NEXT: tail call void @use3(i1 noundef [[CMP_UGT_4]], i1 noundef [[CMP_UGT_5]], i1 noundef [[CMP_UGT_6]]) ; CGSCC-NEXT: [[CMP_UGE_1:%.*]] = icmp uge i32 [[RET]], 10 ; CGSCC-NEXT: [[CMP_UGE_2:%.*]] = icmp uge i32 [[RET]], 9 ; CGSCC-NEXT: [[CMP_UGE_3:%.*]] = icmp uge i32 [[RET]], 8 ; CGSCC-NEXT: [[CMP_UGE_4:%.*]] = icmp uge i32 [[RET]], 1 ; CGSCC-NEXT: [[CMP_UGE_5:%.*]] = icmp uge i32 [[RET]], 0 ; CGSCC-NEXT: [[CMP_UGE_6:%.*]] = icmp uge i32 [[RET]], -1 -; CGSCC-NEXT: tail call void @use3(i1 [[CMP_UGE_1]], i1 [[CMP_UGE_2]], i1 [[CMP_UGE_3]]) -; CGSCC-NEXT: tail call void @use3(i1 [[CMP_UGE_4]], i1 [[CMP_UGE_5]], i1 [[CMP_UGE_6]]) +; CGSCC-NEXT: tail call void @use3(i1 noundef [[CMP_UGE_1]], i1 noundef [[CMP_UGE_2]], i1 noundef [[CMP_UGE_3]]) +; CGSCC-NEXT: tail call void @use3(i1 noundef [[CMP_UGE_4]], i1 noundef [[CMP_UGE_5]], i1 noundef [[CMP_UGE_6]]) ; CGSCC-NEXT: [[CMP_SGT_1:%.*]] = icmp sgt i32 [[RET]], 10 ; CGSCC-NEXT: [[CMP_SGT_2:%.*]] = icmp sgt i32 [[RET]], 9 ; CGSCC-NEXT: [[CMP_SGT_3:%.*]] = icmp sgt i32 [[RET]], 8 ; CGSCC-NEXT: [[CMP_SGT_4:%.*]] = icmp sgt i32 [[RET]], 1 ; CGSCC-NEXT: [[CMP_SGT_5:%.*]] = icmp sgt i32 [[RET]], 0 ; CGSCC-NEXT: [[CMP_SGT_6:%.*]] = icmp sgt i32 [[RET]], -1 -; CGSCC-NEXT: tail call void @use3(i1 [[CMP_SGT_1]], i1 [[CMP_SGT_2]], i1 [[CMP_SGT_3]]) -; CGSCC-NEXT: tail call void @use3(i1 [[CMP_SGT_4]], i1 [[CMP_SGT_5]], i1 [[CMP_SGT_6]]) +; CGSCC-NEXT: tail call void @use3(i1 noundef [[CMP_SGT_1]], i1 noundef [[CMP_SGT_2]], i1 noundef [[CMP_SGT_3]]) +; CGSCC-NEXT: tail call void @use3(i1 noundef [[CMP_SGT_4]], i1 noundef [[CMP_SGT_5]], i1 noundef [[CMP_SGT_6]]) ; CGSCC-NEXT: [[CMP_GTE_1:%.*]] = icmp sge i32 [[RET]], 10 ; CGSCC-NEXT: [[CMP_GTE_2:%.*]] = icmp sge i32 [[RET]], 9 ; CGSCC-NEXT: [[CMP_GTE_3:%.*]] = icmp sge i32 [[RET]], 8 ; CGSCC-NEXT: [[CMP_GTE_4:%.*]] = icmp sge i32 [[RET]], 1 ; CGSCC-NEXT: [[CMP_GTE_5:%.*]] = icmp sge i32 [[RET]], 0 ; CGSCC-NEXT: [[CMP_GTE_6:%.*]] = icmp sge i32 [[RET]], -1 -; CGSCC-NEXT: tail call void @use3(i1 [[CMP_GTE_1]], i1 [[CMP_GTE_2]], i1 [[CMP_GTE_3]]) -; CGSCC-NEXT: tail call void @use3(i1 [[CMP_GTE_4]], i1 [[CMP_GTE_5]], i1 [[CMP_GTE_6]]) +; CGSCC-NEXT: tail call void @use3(i1 noundef [[CMP_GTE_1]], i1 noundef [[CMP_GTE_2]], i1 noundef [[CMP_GTE_3]]) +; CGSCC-NEXT: tail call void @use3(i1 noundef [[CMP_GTE_4]], i1 noundef [[CMP_GTE_5]], i1 noundef [[CMP_GTE_6]]) ; CGSCC-NEXT: [[CMP_SLT_1:%.*]] = icmp slt i32 [[RET]], 10 ; CGSCC-NEXT: [[CMP_SLT_2:%.*]] = icmp slt i32 [[RET]], 9 ; CGSCC-NEXT: [[CMP_SLT_3:%.*]] = icmp slt i32 [[RET]], 8 ; CGSCC-NEXT: [[CMP_SLT_4:%.*]] = icmp slt i32 [[RET]], 1 ; CGSCC-NEXT: [[CMP_SLT_5:%.*]] = icmp slt i32 [[RET]], 0 ; CGSCC-NEXT: [[CMP_SLT_6:%.*]] = icmp slt i32 [[RET]], -1 -; CGSCC-NEXT: tail call void @use3(i1 [[CMP_SLT_1]], i1 [[CMP_SLT_2]], i1 [[CMP_SLT_3]]) -; CGSCC-NEXT: tail call void @use3(i1 [[CMP_SLT_4]], i1 [[CMP_SLT_5]], i1 [[CMP_SLT_6]]) +; CGSCC-NEXT: tail call void @use3(i1 noundef [[CMP_SLT_1]], i1 noundef [[CMP_SLT_2]], i1 noundef [[CMP_SLT_3]]) +; CGSCC-NEXT: tail call void @use3(i1 noundef [[CMP_SLT_4]], i1 noundef [[CMP_SLT_5]], i1 noundef [[CMP_SLT_6]]) ; CGSCC-NEXT: [[CMP_LTE_1:%.*]] = icmp sle i32 [[RET]], 10 ; CGSCC-NEXT: [[CMP_LTE_2:%.*]] = icmp sle i32 [[RET]], 9 ; CGSCC-NEXT: [[CMP_LTE_3:%.*]] = icmp sle i32 [[RET]], 8 ; CGSCC-NEXT: [[CMP_LTE_4:%.*]] = icmp sle i32 [[RET]], 1 ; CGSCC-NEXT: [[CMP_LTE_5:%.*]] = icmp sle i32 [[RET]], 0 ; CGSCC-NEXT: [[CMP_LTE_6:%.*]] = icmp sle i32 [[RET]], -1 -; CGSCC-NEXT: tail call void @use3(i1 [[CMP_LTE_1]], i1 [[CMP_LTE_2]], i1 [[CMP_LTE_3]]) -; CGSCC-NEXT: tail call void @use3(i1 [[CMP_LTE_4]], i1 [[CMP_LTE_5]], i1 [[CMP_LTE_6]]) +; CGSCC-NEXT: tail call void @use3(i1 noundef [[CMP_LTE_1]], i1 noundef [[CMP_LTE_2]], i1 noundef [[CMP_LTE_3]]) +; CGSCC-NEXT: tail call void @use3(i1 noundef [[CMP_LTE_4]], i1 noundef [[CMP_LTE_5]], i1 noundef [[CMP_LTE_6]]) ; CGSCC-NEXT: ret void ; %ret = tail call i32 @test0(i32 *%p) Index: llvm/test/Transforms/InstCombine/freeze.ll =================================================================== --- llvm/test/Transforms/InstCombine/freeze.ll +++ llvm/test/Transforms/InstCombine/freeze.ll @@ -1079,8 +1079,7 @@ define i32 @freeze_load_with_range(ptr %ptr) { ; CHECK-LABEL: @freeze_load_with_range( ; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[PTR:%.*]], align 4, !range [[RNG2:![0-9]+]] -; CHECK-NEXT: [[X_FR:%.*]] = freeze i32 [[X]] -; CHECK-NEXT: ret i32 [[X_FR]] +; CHECK-NEXT: ret i32 [[X]] ; %x = load i32, ptr %ptr, !range !2 %x.fr = freeze i32 %x @@ -1092,8 +1091,7 @@ define i32 @freeze_call_with_range() { ; CHECK-LABEL: @freeze_call_with_range( ; CHECK-NEXT: [[X:%.*]] = call i32 @foo.i32(), !range [[RNG2]] -; CHECK-NEXT: [[X_FR:%.*]] = freeze i32 [[X]] -; CHECK-NEXT: ret i32 [[X_FR]] +; CHECK-NEXT: ret i32 [[X]] ; %x = call i32 @foo.i32(), !range !2 %x.fr = freeze i32 %x