diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -2900,6 +2900,15 @@ return nullptr; } +static bool callPassesUndefToPassingUndefUBParam(CallBase &Call) { + for (unsigned I = 0; I < Call.arg_size(); ++I) { + if (isa(Call.getArgOperand(I)) && Call.isPassingUndefUB(I)) { + return true; + } + } + return false; +} + bool InstCombinerImpl::annotateAnyAllocSite(CallBase &Call, const TargetLibraryInfo *TLI) { // Note: We only handle cases which can't be driven from generic attributes @@ -3026,9 +3035,11 @@ // Calling a null function pointer is undefined if a null address isn't // dereferenceable. + // Passing undef/poison to any parameter where doing so is UB is undefined (of + // course). if ((isa(Callee) && !NullPointerIsDefined(Call.getFunction())) || - isa(Callee)) { + isa(Callee) || callPassesUndefToPassingUndefUBParam(Call)) { // If Call does not return void then replaceInstUsesWith poison. // This allows ValueHandlers and custom metadata to adjust itself. if (!Call.getType()->isVoidTy()) diff --git a/llvm/test/Transforms/InstCombine/call-undef.ll b/llvm/test/Transforms/InstCombine/call-undef.ll --- a/llvm/test/Transforms/InstCombine/call-undef.ll +++ b/llvm/test/Transforms/InstCombine/call-undef.ll @@ -8,7 +8,7 @@ define void @test1() { ; CHECK-LABEL: @test1( -; CHECK-NEXT: call void @c(i32 undef) +; CHECK-NEXT: store i1 true, ptr poison, align 1 ; CHECK-NEXT: ret void ; call void @c(i32 undef) @@ -17,7 +17,7 @@ define void @test2() { ; CHECK-LABEL: @test2( -; CHECK-NEXT: call void @c(i32 poison) +; CHECK-NEXT: store i1 true, ptr poison, align 1 ; CHECK-NEXT: ret void ; call void @c(i32 poison) @@ -26,7 +26,7 @@ define void @test3() { ; CHECK-LABEL: @test3( -; CHECK-NEXT: call void @e(i32 noundef undef) +; CHECK-NEXT: store i1 true, ptr poison, align 1 ; CHECK-NEXT: ret void ; call void @e(i32 noundef undef) @@ -35,7 +35,7 @@ define void @test4() { ; CHECK-LABEL: @test4( -; CHECK-NEXT: call void @e(i32 noundef poison) +; CHECK-NEXT: store i1 true, ptr poison, align 1 ; CHECK-NEXT: ret void ; call void @e(i32 noundef poison) @@ -44,7 +44,7 @@ define void @test5() { ; CHECK-LABEL: @test5( -; CHECK-NEXT: call void @d(ptr undef) +; CHECK-NEXT: store i1 true, ptr poison, align 1 ; CHECK-NEXT: ret void ; call void @d(ptr undef) @@ -53,7 +53,7 @@ define void @test6() { ; CHECK-LABEL: @test6( -; CHECK-NEXT: call void @d(ptr poison) +; CHECK-NEXT: store i1 true, ptr poison, align 1 ; CHECK-NEXT: ret void ; call void @d(ptr poison) @@ -62,7 +62,7 @@ define void @test7() { ; CHECK-LABEL: @test7( -; CHECK-NEXT: call void @f(ptr dereferenceable(1) undef) +; CHECK-NEXT: store i1 true, ptr poison, align 1 ; CHECK-NEXT: ret void ; call void @f(ptr dereferenceable(1) undef) @@ -71,7 +71,7 @@ define void @test8() { ; CHECK-LABEL: @test8( -; CHECK-NEXT: call void @f(ptr dereferenceable(1) poison) +; CHECK-NEXT: store i1 true, ptr poison, align 1 ; CHECK-NEXT: ret void ; call void @f(ptr dereferenceable(1) poison) diff --git a/llvm/test/Transforms/InstCombine/out-of-bounds-indexes.ll b/llvm/test/Transforms/InstCombine/out-of-bounds-indexes.ll --- a/llvm/test/Transforms/InstCombine/out-of-bounds-indexes.ll +++ b/llvm/test/Transforms/InstCombine/out-of-bounds-indexes.ll @@ -6,7 +6,7 @@ ; CHECK-LABEL: @test_out_of_bounds( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[AND1:%.*]] = and i32 [[A:%.*]], 3 -; CHECK-NEXT: tail call void @llvm.assume(i1 poison) +; CHECK-NEXT: store i1 true, ptr poison, align 1 ; CHECK-NEXT: ret i32 [[AND1]] ; entry: @@ -20,7 +20,7 @@ define i128 @test_non64bit(i128 %a) { ; CHECK-LABEL: @test_non64bit( ; CHECK-NEXT: [[AND1:%.*]] = and i128 [[A:%.*]], 3 -; CHECK-NEXT: tail call void @llvm.assume(i1 poison) +; CHECK-NEXT: store i1 true, ptr poison, align 1 ; CHECK-NEXT: ret i128 [[AND1]] ; %and1 = and i128 %a, 3