Index: lib/Analysis/InstructionSimplify.cpp =================================================================== --- lib/Analysis/InstructionSimplify.cpp +++ lib/Analysis/InstructionSimplify.cpp @@ -4089,6 +4089,17 @@ unsigned NumOperands = std::distance(ArgBegin, ArgEnd); Type *ReturnType = F->getReturnType(); + // We can remove a noalias intrinsic if the pointer value is undef (by + // forwarding the undef). The same goes for an address-space-zero null + // pointer. + if (IID == Intrinsic::noalias) { + Value *Arg0 = *ArgBegin; + if (isa(Arg0) || + (isa(Arg0) && + Arg0->getType()->getPointerAddressSpace() == 0)) + return Arg0; + } + // Binary Ops if (NumOperands == 2) { Value *LHS = *ArgBegin; Index: lib/Transforms/Utils/Local.cpp =================================================================== --- lib/Transforms/Utils/Local.cpp +++ lib/Transforms/Utils/Local.cpp @@ -332,6 +332,12 @@ return false; } + + // noalias intrinsics are dead if they have no uses (they're tagged as + // writing, but that is only to maintain control dependencies, not because + // they actually write anything). + if (II->getIntrinsicID() == Intrinsic::noalias) + return II->use_empty(); } if (isAllocLikeFn(I, TLI)) return true; Index: test/Transforms/InstSimplify/noalias.ll =================================================================== --- /dev/null +++ test/Transforms/InstSimplify/noalias.ll @@ -0,0 +1,34 @@ +; RUN: opt -instsimplify -S < %s | FileCheck %s + +define void @test1(i8* %ptr) { + call i8* @llvm.noalias.p0i8(i8* %ptr, metadata !1) + ret void + +; CHECK-LABEL: @test1 +; CHECK-NOT: llvm.noalias.p0i8 +; CHECK: ret void +} + +define i8* @test2a() { + %v = call i8* @llvm.noalias.p0i8(i8* null, metadata !1) + ret i8* %v + +; CHECK-LABEL: @test2a +; CHECK-NOT: llvm.noalias.p0i8 +; CHECK: ret i8* null +} + +define i8* @test2() { + %v = call i8* @llvm.noalias.p0i8(i8* undef, metadata !1) + ret i8* %v + +; CHECK-LABEL: @test2 +; CHECK-NOT: llvm.noalias.p0i8 +; CHECK: ret i8* undef +} + +declare i8* @llvm.noalias.p0i8(i8*, metadata) nounwind + +!0 = !{!0, !"some domain"} +!1 = !{!1, !0, !"some scope"} +