diff --git a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp --- a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -67,6 +67,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/PromoteMemToReg.h" #include #include @@ -220,6 +221,8 @@ // pass in the loaded pointers. SmallVector Args; const DataLayout &DL = F->getParent()->getDataLayout(); + SmallVector DeadArgs; + while (!F->use_empty()) { CallBase &CB = cast(*F->user_back()); assert(CB.getCalledFunction() == F); @@ -255,6 +258,9 @@ Args.push_back(LI); ArgAttrVec.push_back(AttributeSet()); } + } else { + assert(ArgsToPromote.count(&*I) && I->use_empty()); + DeadArgs.emplace_back(AI->get()); } } @@ -297,6 +303,8 @@ CB.eraseFromParent(); } + RecursivelyDeleteTriviallyDeadInstructionsPermissive(DeadArgs); + // Since we have now created the new function, splice the body of the old // function right into the new function, leaving the old rotting hulk of the // function empty. diff --git a/llvm/test/Transforms/ArgumentPromotion/propagate-remove-dead-args.ll b/llvm/test/Transforms/ArgumentPromotion/propagate-remove-dead-args.ll --- a/llvm/test/Transforms/ArgumentPromotion/propagate-remove-dead-args.ll +++ b/llvm/test/Transforms/ArgumentPromotion/propagate-remove-dead-args.ll @@ -18,18 +18,12 @@ define internal void @parent(ptr %this, ptr %p1, ptr %p2) { ; CHECK-LABEL: define internal void @parent -; CHECK-SAME: (ptr [[THIS:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]]) { +; CHECK-SAME: (ptr [[P1:%.*]], ptr [[P2:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[SRC_ELEMENT_OP_0:%.*]] = getelementptr ptr, ptr [[THIS]], i64 0 -; CHECK-NEXT: [[LOAD0:%.*]] = load ptr, ptr [[SRC_ELEMENT_OP_0]], align 8 ; CHECK-NEXT: [[P2_VAL2:%.*]] = load half, ptr [[P2]], align 2 ; CHECK-NEXT: call void @child(ptr [[P1]], half [[P2_VAL2]]) -; CHECK-NEXT: [[SRC_ELEMENT_OP_1:%.*]] = getelementptr ptr, ptr [[THIS]], i64 1 -; CHECK-NEXT: [[LOAD1:%.*]] = load ptr, ptr [[SRC_ELEMENT_OP_1]], align 8 ; CHECK-NEXT: [[P2_VAL1:%.*]] = load half, ptr [[P2]], align 2 ; CHECK-NEXT: call void @child(ptr [[P1]], half [[P2_VAL1]]) -; CHECK-NEXT: [[SRC_ELEMENT_OP_2:%.*]] = getelementptr ptr, ptr [[THIS]], i64 2 -; CHECK-NEXT: [[LOAD2:%.*]] = load ptr, ptr [[SRC_ELEMENT_OP_2]], align 8 ; CHECK-NEXT: [[P2_VAL:%.*]] = load half, ptr [[P2]], align 2 ; CHECK-NEXT: call void @child(ptr [[P1]], half [[P2_VAL]]) ; CHECK-NEXT: ret void @@ -50,10 +44,9 @@ define void @grandparent() { ; CHECK-LABEL: define void @grandparent() { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[F:%.*]] = alloca [[PTR_STRUCT:%.*]], align 8 ; CHECK-NEXT: [[XPTR:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[YPTR:%.*]] = alloca i32, align 4 -; CHECK-NEXT: call void @parent(ptr [[F]], ptr [[XPTR]], ptr [[YPTR]]) +; CHECK-NEXT: call void @parent(ptr [[XPTR]], ptr [[YPTR]]) ; CHECK-NEXT: ret void ; entry: diff --git a/llvm/test/Transforms/ArgumentPromotion/store-into-inself.ll b/llvm/test/Transforms/ArgumentPromotion/store-into-inself.ll --- a/llvm/test/Transforms/ArgumentPromotion/store-into-inself.ll +++ b/llvm/test/Transforms/ArgumentPromotion/store-into-inself.ll @@ -83,7 +83,6 @@ ; CHECK-NEXT: call void @g(ptr byval(ptr) align 4 [[S]]) #[[ATTR0]] ; CHECK-NEXT: call void @h(ptr byval(ptr) align 4 [[S]]) #[[ATTR0]] ; CHECK-NEXT: call void @k(ptr byval(ptr) align 4 [[S]]) #[[ATTR0]] -; CHECK-NEXT: [[S_VAL:%.*]] = load ptr, ptr [[S]], align 8 ; CHECK-NEXT: call void @l() #[[ATTR0]] ; CHECK-NEXT: ret i32 0 ; diff --git a/llvm/test/Transforms/PhaseOrdering/dce-after-argument-promotion-loads.ll b/llvm/test/Transforms/PhaseOrdering/dce-after-argument-promotion-loads.ll --- a/llvm/test/Transforms/PhaseOrdering/dce-after-argument-promotion-loads.ll +++ b/llvm/test/Transforms/PhaseOrdering/dce-after-argument-promotion-loads.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 ; RUN: opt -O3 -S < %s | FileCheck %s ; Arg promotion eliminates the struct argument, and eliminates dead arguments, but introduces and leaves dead loads of the eliminated dead arg in callers @@ -13,24 +13,17 @@ } define ptr @parent(ptr align 8 dereferenceable(72) %f, i16 %val1, i16 %val2, i32 %val3) align 2 { -; CHECK-LABEL: define {{[^@]+}}@parent +; CHECK-LABEL: define nonnull ptr @parent ; CHECK-SAME: (ptr readonly returned align 8 dereferenceable(72) [[F:%.*]], i16 [[VAL1:%.*]], i16 [[VAL2:%.*]], i32 [[VAL3:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] align 2 { ; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[F]], i64 64 +; CHECK-NEXT: [[F_VAL:%.*]] = load ptr, ptr [[TMP0]], align 8 ; CHECK-NEXT: [[CMP_NOT_NOT_I:%.*]] = icmp eq i32 [[VAL3]], 0 -; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_SS:%.*]], ptr [[F]], i64 0, i32 8 -; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8 -; CHECK-NEXT: br i1 [[CMP_NOT_NOT_I]], label [[IF_THEN_I:%.*]], label [[IF_ELSE_I:%.*]] -; CHECK: if.then.i: -; CHECK-NEXT: store i16 [[VAL1]], ptr [[TMP1]], align 2 -; CHECK-NEXT: [[ADD_PTR_I_I_I_I_I:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 16 -; CHECK-NEXT: br label [[BADCHILD_EXIT:%.*]] -; CHECK: if.else.i: -; CHECK-NEXT: [[ADD_PTR_I_I_I_I7_I:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 16 -; CHECK-NEXT: store i16 [[VAL1]], ptr [[ADD_PTR_I_I_I_I7_I]], align 2 -; CHECK-NEXT: br label [[BADCHILD_EXIT]] -; CHECK: badChild.exit: -; CHECK-NEXT: [[DOTSINK_I:%.*]] = phi ptr [ [[TMP1]], [[IF_ELSE_I]] ], [ [[ADD_PTR_I_I_I_I_I]], [[IF_THEN_I]] ] -; CHECK-NEXT: store i16 [[VAL2]], ptr [[DOTSINK_I]], align 2 +; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = select i1 [[CMP_NOT_NOT_I]], i16 [[VAL1]], i16 [[VAL2]] +; CHECK-NEXT: [[SPEC_SELECT2_I:%.*]] = select i1 [[CMP_NOT_NOT_I]], i16 [[VAL2]], i16 [[VAL1]] +; CHECK-NEXT: store i16 [[SPEC_SELECT_I]], ptr [[F_VAL]], align 2 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[F_VAL]], i64 16 +; CHECK-NEXT: store i16 [[SPEC_SELECT2_I]], ptr [[TMP1]], align 2 ; CHECK-NEXT: ret ptr [[F]] ; entry: