[llvm] 7739be7 - [ArgPromotion] Remove dead code produced by removing dead arguments
Jeff Byrnes via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 23 09:47:57 PDT 2023
Author: Jeff Byrnes
Date: 2023-03-23T09:43:35-07:00
New Revision: 7739be7c6b6d017bf6b4445c5010e59314655995
URL: https://github.com/llvm/llvm-project/commit/7739be7c6b6d017bf6b4445c5010e59314655995
DIFF: https://github.com/llvm/llvm-project/commit/7739be7c6b6d017bf6b4445c5010e59314655995.diff
LOG: [ArgPromotion] Remove dead code produced by removing dead arguments
ArgPromotion currently produces phantom / dead loads. A good example of this is store-into-inself.ll. First, ArgPromo finds the promotable argument %p in @l. Then it inserts a load of %p in the caller, and passes instead the loaded value / transforms the function body. PromoteMem2Reg is able to optimize out the entire function body, resulting in an unused argument. In a subsequent ArgPromotion pass, it removes the dead argument, resulting in a dead load in the caller. These dead loads may reduce effectiveness of other transformations (e.g. SimplifyCFG, MergedLoadStoreMotion).
This patch removes loads and geps that are made dead in the caller after removal of dead args.
Differential Revision: https://reviews.llvm.org/D146327
Added:
Modified:
llvm/lib/Transforms/IPO/ArgumentPromotion.cpp
llvm/test/Transforms/ArgumentPromotion/propagate-remove-dead-args.ll
llvm/test/Transforms/ArgumentPromotion/store-into-inself.ll
llvm/test/Transforms/PhaseOrdering/dce-after-argument-promotion-loads.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp
index dd1a3b78a378c..3b1a174f5cc63 100644
--- 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 <algorithm>
#include <cassert>
@@ -220,6 +221,8 @@ doPromotion(Function *F, FunctionAnalysisManager &FAM,
// pass in the loaded pointers.
SmallVector<Value *, 16> Args;
const DataLayout &DL = F->getParent()->getDataLayout();
+ SmallVector<WeakTrackingVH, 16> DeadArgs;
+
while (!F->use_empty()) {
CallBase &CB = cast<CallBase>(*F->user_back());
assert(CB.getCalledFunction() == F);
@@ -255,6 +258,9 @@ doPromotion(Function *F, FunctionAnalysisManager &FAM,
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 @@ doPromotion(Function *F, FunctionAnalysisManager &FAM,
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
index cc1f7fb26a479..4176a8a7bc5c8 100644
--- a/llvm/test/Transforms/ArgumentPromotion/propagate-remove-dead-args.ll
+++ b/llvm/test/Transforms/ArgumentPromotion/propagate-remove-dead-args.ll
@@ -18,18 +18,12 @@ entry:
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 @@ entry:
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
index 7d7099003dc77..be94af6a0bd03 100644
--- a/llvm/test/Transforms/ArgumentPromotion/store-into-inself.ll
+++ b/llvm/test/Transforms/ArgumentPromotion/store-into-inself.ll
@@ -83,7 +83,6 @@ define i32 @main() nounwind {
; 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
index 2bdd42b3dd8ca..2fe8f39e423a5 100644
--- 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 @@ entry:
}
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:
More information about the llvm-commits
mailing list