Index: llvm/lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -2577,18 +2577,21 @@ for (unsigned i = 0; i < CB.arg_size(); i++) { if (!CB.getArgOperand(i)->getType()->isPointerTy()) continue; - if (UsedV != CB.getArgOperand(i) && !CB.onlyReadsMemory(i)) - // A write to another memory location keeps the call live, and thus we - // must keep the alloca so that the call has somewhere to write to. - // TODO: This results in an inprecision when two values derived from the - // same alloca are passed as arguments to the same function. + if (!CB.doesNotCapture(i)) + // capture would allow the address to be read back in an untracked manner return false; + if (UsedV != CB.getArgOperand(i)) { + if (!CB.onlyReadsMemory(i)) + // A write to another memory location keeps the call live, and thus we + // must keep the alloca so that the call has somewhere to write to. + // TODO: This results in an inprecision when two values derived from the + // same alloca are passed as arguments to the same function. + return false; + continue; + } if (!CB.paramHasAttr(i, Attribute::WriteOnly)) // a read would hold the address live return false; - if (!CB.doesNotCapture(i)) - // capture would allow the address to be read back in an untracked manner - return false; } return true; } Index: llvm/test/Transforms/InstCombine/trivial-dse-calls.ll =================================================================== --- llvm/test/Transforms/InstCombine/trivial-dse-calls.ll +++ llvm/test/Transforms/InstCombine/trivial-dse-calls.ll @@ -167,4 +167,34 @@ ret i32 %res } +; Show that reading from unrelated memory is okay +define void @test_unreleated_read() { +; CHECK-LABEL: @test_unreleated_read( +; CHECK-NEXT: ret void +; + %a = alloca i32, align 4 + %a2 = alloca i32, align 4 + %bitcast = bitcast i32* %a to i8* + %bitcast2 = bitcast i32* %a2 to i8* + call void @f2(i8* nocapture writeonly %bitcast, i8* nocapture readonly %bitcast2) argmemonly nounwind willreturn + ret void +} + +; But that removing a capture of an unrelated pointer isn't okay. +define void @test_neg_unreleated_capture() { +; CHECK-LABEL: @test_neg_unreleated_capture( +; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 +; CHECK-NEXT: [[A2:%.*]] = alloca i32, align 4 +; CHECK-NEXT: [[BITCAST:%.*]] = bitcast i32* [[A]] to i8* +; CHECK-NEXT: [[BITCAST2:%.*]] = bitcast i32* [[A2]] to i8* +; CHECK-NEXT: call void @f2(i8* nocapture nonnull writeonly [[BITCAST]], i8* nonnull readonly [[BITCAST2]]) #[[ATTR1]] +; CHECK-NEXT: ret void +; + %a = alloca i32, align 4 + %a2 = alloca i32, align 4 + %bitcast = bitcast i32* %a to i8* + %bitcast2 = bitcast i32* %a2 to i8* + call void @f2(i8* nocapture writeonly %bitcast, i8* readonly %bitcast2) argmemonly nounwind willreturn + ret void +}