Index: llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp =================================================================== --- llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -306,6 +306,12 @@ if (!CB || !CB->isCallee(&U)) continue; + // Don't touch builtin annotated calls. The analysis might have seen a + // (nobuiltin) implementation that allows to optimize an argument, but other + // optimizations of builtin calls might still depend on that argument. + if (CB->hasFnAttr(Attribute::Builtin)) + continue; + // Now go through all unused args and replace them with "undef". for (unsigned I = 0, E = UnusedArgs.size(); I != E; ++I) { unsigned ArgNo = UnusedArgs[I]; Index: llvm/test/Transforms/DeadArgElim/builtin_functions.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/DeadArgElim/builtin_functions.ll @@ -0,0 +1,36 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature +; RUN: opt -S -deadargelim %s | FileCheck %s + +; Function Attrs: nobuiltin nounwind uwtable mustprogress +define dso_local void @_ZdlPv(i8* %0) #0 { +; CHECK-LABEL: define {{[^@]+}}@_ZdlPv +; CHECK-SAME: (i8* [[TMP0:%.*]]) [[ATTR0:#.*]] { +; CHECK-NEXT: ret void +; + ret void +} + +; The arguments for builtin annotated call must not be replaced +define void @use_builtin_delete(i8* %p) { +; CHECK-LABEL: define {{[^@]+}}@use_builtin_delete +; CHECK-SAME: (i8* [[P:%.*]]) { +; CHECK-NEXT: call void @_ZdlPv(i8* [[P]]) [[ATTR1:#.*]] +; CHECK-NEXT: ret void +; + call void @_ZdlPv(i8* %p) #1 + ret void +} + +define void @use_other_delete(i8* %p) { +; CHECK-LABEL: define {{[^@]+}}@use_other_delete +; CHECK-SAME: (i8* [[P:%.*]]) { +; CHECK-NEXT: call void @_ZdlPv(i8* undef) [[ATTR2:#.*]] +; CHECK-NEXT: ret void +; + call void @_ZdlPv(i8* %p) #2 + ret void +} + +attributes #0 = { nobuiltin nounwind uwtable mustprogress readnone willreturn } +attributes #1 = { builtin nounwind } +attributes #2 = { nounwind }