-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[DropUnnecessaryAssumes] Add pass for dropping assumes #159403
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang @llvm/pr-subscribers-llvm-transforms Author: Nikita Popov (nikic) ChangesThis adds a new pass for dropping assumes that are unlikely to be useful for further optimization. It works by discarding any assumes whose affected values are one-use (which implies that they are only used by the assume, i.e. ephemeral). This pass currently runs at the start of the module optimization pipeline, that is post-inline and post-link. Before that point, it is more likely for previously "useless" assumes to become useful again, e.g. because an additional user of the value is introduced after inlining + CSE. llvm-opt-benchmark: dtcxzyw/llvm-opt-benchmark#2829 Full diff: https://github.com/llvm/llvm-project/pull/159403.diff 16 Files Affected:
diff --git a/clang/test/CodeGen/inline-asm-x86-flag-output.c b/clang/test/CodeGen/inline-asm-x86-flag-output.c
index 243dc3716ca13..330036512e705 100644
--- a/clang/test/CodeGen/inline-asm-x86-flag-output.c
+++ b/clang/test/CodeGen/inline-asm-x86-flag-output.c
@@ -389,7 +389,7 @@ int test_assume_boolean_flag(long nr, volatile long *addr) {
: "=@cca"(x), "=@ccae"(y), "=m"(*(volatile long *)(addr))
: "r"(nr)
: "cc");
- if (x)
+ if (x && y)
return 0;
return 1;
}
diff --git a/llvm/include/llvm/Transforms/Scalar/DropUnnecessaryAssumes.h b/llvm/include/llvm/Transforms/Scalar/DropUnnecessaryAssumes.h
new file mode 100644
index 0000000000000..192139cbfd94d
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Scalar/DropUnnecessaryAssumes.h
@@ -0,0 +1,28 @@
+//===------------------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Pass that drops assumes that are unlikely to be useful.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_DROPUNNECESSARYASSUMES_H
+#define LLVM_TRANSFORMS_SCALAR_DROPUNNECESSARYASSUMES_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+class DropUnnecessaryAssumesPass
+ : public PassInfoMixin<DropUnnecessaryAssumesPass> {
+public:
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_SCALAR_DROPUNNECESSARYASSUMES_H
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 8cf277657a54a..53319031b1aba 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -273,6 +273,7 @@
#include "llvm/Transforms/Scalar/DFAJumpThreading.h"
#include "llvm/Transforms/Scalar/DeadStoreElimination.h"
#include "llvm/Transforms/Scalar/DivRemPairs.h"
+#include "llvm/Transforms/Scalar/DropUnnecessaryAssumes.h"
#include "llvm/Transforms/Scalar/EarlyCSE.h"
#include "llvm/Transforms/Scalar/FlattenCFG.h"
#include "llvm/Transforms/Scalar/Float2Int.h"
diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp
index c3f35f0f5e7fa..3b75a5a83dd9a 100644
--- a/llvm/lib/Passes/PassBuilderPipelines.cpp
+++ b/llvm/lib/Passes/PassBuilderPipelines.cpp
@@ -92,6 +92,7 @@
#include "llvm/Transforms/Scalar/DFAJumpThreading.h"
#include "llvm/Transforms/Scalar/DeadStoreElimination.h"
#include "llvm/Transforms/Scalar/DivRemPairs.h"
+#include "llvm/Transforms/Scalar/DropUnnecessaryAssumes.h"
#include "llvm/Transforms/Scalar/EarlyCSE.h"
#include "llvm/Transforms/Scalar/Float2Int.h"
#include "llvm/Transforms/Scalar/GVN.h"
@@ -1498,6 +1499,9 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
invokeOptimizerEarlyEPCallbacks(MPM, Level, LTOPhase);
FunctionPassManager OptimizePM;
+ if (!isLTOPreLink(LTOPhase))
+ OptimizePM.addPass(DropUnnecessaryAssumesPass());
+
// Scheduling LoopVersioningLICM when inlining is over, because after that
// we may see more accurate aliasing. Reason to run this late is that too
// early versioning may prevent further inlining due to increase of code
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 1d015971dfbdf..924aa3eb5d492 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -425,6 +425,7 @@ FUNCTION_PASS("dot-post-dom", PostDomPrinter())
FUNCTION_PASS("dot-post-dom-only", PostDomOnlyPrinter())
FUNCTION_PASS("dse", DSEPass())
FUNCTION_PASS("dwarf-eh-prepare", DwarfEHPreparePass(TM))
+FUNCTION_PASS("drop-unnecessary-assumes", DropUnnecessaryAssumesPass())
FUNCTION_PASS("expand-large-div-rem", ExpandLargeDivRemPass(TM))
FUNCTION_PASS("expand-memcmp", ExpandMemCmpPass(TM))
FUNCTION_PASS("expand-reductions", ExpandReductionsPass())
diff --git a/llvm/lib/Transforms/Scalar/CMakeLists.txt b/llvm/lib/Transforms/Scalar/CMakeLists.txt
index 765059d0c3b20..37dbb34605646 100644
--- a/llvm/lib/Transforms/Scalar/CMakeLists.txt
+++ b/llvm/lib/Transforms/Scalar/CMakeLists.txt
@@ -11,6 +11,7 @@ add_llvm_component_library(LLVMScalarOpts
DeadStoreElimination.cpp
DFAJumpThreading.cpp
DivRemPairs.cpp
+ DropUnnecessaryAssumes.cpp
EarlyCSE.cpp
FlattenCFGPass.cpp
Float2Int.cpp
diff --git a/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp b/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
new file mode 100644
index 0000000000000..847be47a050c9
--- /dev/null
+++ b/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
@@ -0,0 +1,59 @@
+//===------------------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Scalar/DropUnnecessaryAssumes.h"
+#include "llvm/Analysis/AssumptionCache.h"
+#include "llvm/Analysis/ValueTracking.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/PatternMatch.h"
+#include "llvm/Transforms/Utils/Local.h"
+
+using namespace llvm;
+
+PreservedAnalyses
+DropUnnecessaryAssumesPass::run(Function &F, FunctionAnalysisManager &FAM) {
+ AssumptionCache &AC = FAM.getResult<AssumptionAnalysis>(F);
+ bool Changed = false;
+
+ for (AssumptionCache::ResultElem &Elem : AC.assumptions()) {
+ auto *Assume = cast_or_null<AssumeInst>(Elem.Assume);
+ if (!Assume)
+ continue;
+
+ // TODO: Handle assumes with operand bundles.
+ if (Assume->hasOperandBundles())
+ continue;
+
+ Value *Cond = Assume->getArgOperand(0);
+ // Don't drop type tests, which have special semantics.
+ if (match(Cond, PatternMatch::m_Intrinsic<Intrinsic::type_test>()))
+ continue;
+
+ SmallPtrSet<Value *, 8> Affected;
+ findValuesAffectedByCondition(Cond, /*IsAssume=*/true,
+ [&](Value *A) { Affected.insert(A); });
+
+ // If all the affected uses have only one use (part of the assume), then
+ // the assume does not provide useful information. Note that additional
+ // users may appear as a result of inlining and CSE, so we should only
+ // make this assumption late in the optimization pipeline.
+ // TODO: Handle dead cyclic usages.
+ if (!all_of(Affected, [](Value *V) { return V->hasOneUse(); }))
+ continue;
+
+ Assume->eraseFromParent();
+ RecursivelyDeleteTriviallyDeadInstructions(Cond);
+ }
+
+ if (Changed) {
+ PreservedAnalyses PA;
+ PA.preserveSet<CFGAnalyses>();
+ return PA;
+ }
+ return PreservedAnalyses::all();
+}
diff --git a/llvm/test/Other/new-pm-defaults.ll b/llvm/test/Other/new-pm-defaults.ll
index c554fdbf4c799..94e860b8ce304 100644
--- a/llvm/test/Other/new-pm-defaults.ll
+++ b/llvm/test/Other/new-pm-defaults.ll
@@ -244,6 +244,7 @@
; CHECK-O-NEXT: Running pass: ReversePostOrderFunctionAttrsPass
; CHECK-O-NEXT: Running pass: RecomputeGlobalsAAPass
; CHECK-EP-OPTIMIZER-EARLY: Running pass: NoOpModulePass
+; CHECK-DEFAULT-NEXT: Running pass: DropUnnecessaryAssumesPass
; CHECK-O-NEXT: Running pass: Float2IntPass
; CHECK-O-NEXT: Running pass: LowerConstantIntrinsicsPass on foo
; CHECK-MATRIX: Running pass: LowerMatrixIntrinsicsPass on f
diff --git a/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll
index 62bb02d9b3c40..a08a140a35166 100644
--- a/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll
@@ -167,6 +167,7 @@
; CHECK-POSTLINK-O-NEXT: Running pass: ReversePostOrderFunctionAttrsPass
; CHECK-POSTLINK-O-NEXT: Running pass: RecomputeGlobalsAAPass
; CHECK-POST-EP-OPT-EARLY-NEXT: Running pass: NoOpModulePass
+; CHECK-POSTLINK-O-NEXT: Running pass: DropUnnecessaryAssumesPass
; CHECK-POSTLINK-O-NEXT: Running pass: Float2IntPass
; CHECK-POSTLINK-O-NEXT: Running pass: LowerConstantIntrinsicsPass
; CHECK-POSTLINK-O3-NEXT: Running pass: ControlHeightReductionPass
diff --git a/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll
index 0da7a9f73bdce..d9e2dd37a7985 100644
--- a/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll
@@ -150,6 +150,7 @@
; CHECK-O-NEXT: Running pass: EliminateAvailableExternallyPass
; CHECK-O-NEXT: Running pass: ReversePostOrderFunctionAttrsPass
; CHECK-O-NEXT: Running pass: RecomputeGlobalsAAPass
+; CHECK-O-NEXT: Running pass: DropUnnecessaryAssumesPass
; CHECK-O-NEXT: Running pass: Float2IntPass
; CHECK-O-NEXT: Running pass: LowerConstantIntrinsicsPass
; CHECK-O3-NEXT: Running pass: ControlHeightReductionPass
diff --git a/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll
index 38b7890682783..2f6fa4b27d354 100644
--- a/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll
@@ -159,6 +159,7 @@
; CHECK-O-NEXT: Running pass: EliminateAvailableExternallyPass
; CHECK-O-NEXT: Running pass: ReversePostOrderFunctionAttrsPass
; CHECK-O-NEXT: Running pass: RecomputeGlobalsAAPass
+; CHECK-O-NEXT: Running pass: DropUnnecessaryAssumesPass
; CHECK-O-NEXT: Running pass: Float2IntPass
; CHECK-O-NEXT: Running pass: LowerConstantIntrinsicsPass
; CHECK-O3-NEXT: Running pass: ControlHeightReductionPass
diff --git a/llvm/test/Transforms/DropUnnecessaryAssumes/basic.ll b/llvm/test/Transforms/DropUnnecessaryAssumes/basic.ll
new file mode 100644
index 0000000000000..ea0d5d3fca8ff
--- /dev/null
+++ b/llvm/test/Transforms/DropUnnecessaryAssumes/basic.ll
@@ -0,0 +1,96 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=drop-unnecessary-assumes < %s | FileCheck %s
+
+define void @basic_dead(i32 %x) {
+; CHECK-LABEL: define void @basic_dead(
+; CHECK-SAME: i32 [[X:%.*]]) {
+; CHECK-NEXT: ret void
+;
+ %cond = icmp sge i32 %x, 0
+ call void @llvm.assume(i1 %cond)
+ ret void
+}
+
+define i32 @basic_live(i32 %x) {
+; CHECK-LABEL: define i32 @basic_live(
+; CHECK-SAME: i32 [[X:%.*]]) {
+; CHECK-NEXT: [[COND:%.*]] = icmp sge i32 [[X]], 0
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
+; CHECK-NEXT: ret i32 [[X]]
+;
+ %cond = icmp sge i32 %x, 0
+ call void @llvm.assume(i1 %cond)
+ ret i32 %x
+}
+
+; Affected value is not direct operand of the condition.
+define i32 @complex_live(i32 %x) {
+; CHECK-LABEL: define i32 @complex_live(
+; CHECK-SAME: i32 [[X:%.*]]) {
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], 1
+; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[AND]], 0
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
+; CHECK-NEXT: ret i32 [[X]]
+;
+ %and = and i32 %x, 1
+ %cond = icmp ne i32 %and, 0
+ call void @llvm.assume(i1 %cond)
+ ret i32 %x
+}
+
+; There are multiple affected values, and not all are one-use.
+define i32 @multiple_live1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @multiple_live1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[X]], [[Y]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
+; CHECK-NEXT: ret i32 [[X]]
+;
+ %cond = icmp eq i32 %x, %y
+ call void @llvm.assume(i1 %cond)
+ ret i32 %x
+}
+
+define i32 @multiple_live2(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @multiple_live2(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[X]], [[Y]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
+; CHECK-NEXT: ret i32 [[Y]]
+;
+ %cond = icmp eq i32 %x, %y
+ call void @llvm.assume(i1 %cond)
+ ret i32 %y
+}
+
+define void @operand_bundle_dead(ptr %x) {
+; CHECK-LABEL: define void @operand_bundle_dead(
+; CHECK-SAME: ptr [[X:%.*]]) {
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[X]], i64 8) ]
+; CHECK-NEXT: ret void
+;
+ call void @llvm.assume(i1 true) ["align"(ptr %x, i64 8)]
+ ret void
+}
+
+define ptr @operand_bundle_live(ptr %x) {
+; CHECK-LABEL: define ptr @operand_bundle_live(
+; CHECK-SAME: ptr [[X:%.*]]) {
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[X]], i64 8) ]
+; CHECK-NEXT: ret ptr [[X]]
+;
+ call void @llvm.assume(i1 true) ["align"(ptr %x, i64 8)]
+ ret ptr %x
+}
+
+define void @type_test(ptr %x) {
+; CHECK-LABEL: define void @type_test(
+; CHECK-SAME: ptr [[X:%.*]]) {
+; CHECK-NEXT: [[TEST:%.*]] = call i1 @llvm.type.test(ptr [[X]], metadata !"typeid")
+; CHECK-NEXT: call void @llvm.assume(i1 [[TEST]])
+; CHECK-NEXT: ret void
+;
+ %test = call i1 @llvm.type.test(ptr %x, metadata !"typeid")
+ call void @llvm.assume(i1 %test)
+ ret void
+}
diff --git a/llvm/test/Transforms/PhaseOrdering/AArch64/constraint-elimination-placement.ll b/llvm/test/Transforms/PhaseOrdering/AArch64/constraint-elimination-placement.ll
index bbdbd95c6017a..f60812f2f39be 100644
--- a/llvm/test/Transforms/PhaseOrdering/AArch64/constraint-elimination-placement.ll
+++ b/llvm/test/Transforms/PhaseOrdering/AArch64/constraint-elimination-placement.ll
@@ -98,25 +98,11 @@ define void @test2(ptr %this) #0 {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL1_I_I:%.*]] = tail call i1 @test2_fn4(i8 undef)
; CHECK-NEXT: [[CALL2_I_I:%.*]] = load i64, ptr inttoptr (i64 8 to ptr), align 8
-; CHECK-NEXT: [[COND_I_I:%.*]] = select i1 [[CALL1_I_I]], i64 [[CALL2_I_I]], i64 0
-; CHECK-NEXT: switch i64 [[COND_I_I]], label [[COMMON_RET:%.*]] [
-; CHECK-NEXT: i64 11, label [[IF_END_I:%.*]]
-; CHECK-NEXT: i64 13, label [[TEST2_FN2_EXIT12:%.*]]
-; CHECK-NEXT: i64 17, label [[IF_END_I31:%.*]]
-; CHECK-NEXT: ]
-; CHECK: if.end.i:
-; CHECK-NEXT: [[CALL8_I_I:%.*]] = tail call fastcc noundef i32 @test2_fn6()
-; CHECK-NEXT: [[TRUNC_I_I:%.*]] = trunc i32 [[CALL8_I_I]] to i8
-; CHECK-NEXT: [[CALL1_I1_I:%.*]] = tail call i1 @test2_fn4(i8 [[TRUNC_I_I]])
-; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[CALL1_I1_I]], true
-; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP0]])
-; CHECK-NEXT: br label [[COMMON_RET]]
+; CHECK-NEXT: [[COND38:%.*]] = icmp eq i64 [[CALL2_I_I]], 13
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CALL1_I_I]], i1 [[COND38]], i1 false
+; CHECK-NEXT: br i1 [[COND]], label [[TEST2_FN2_EXIT12:%.*]], label [[COMMON_RET:%.*]]
; CHECK: test2_fn2.exit12:
; CHECK-NEXT: [[CALL8_I_I8:%.*]] = tail call fastcc noundef i32 @test2_fn6()
-; CHECK-NEXT: [[TRUNC_I_I9:%.*]] = trunc i32 [[CALL8_I_I8]] to i8
-; CHECK-NEXT: [[CALL1_I1_I10:%.*]] = tail call i1 @test2_fn4(i8 [[TRUNC_I_I9]])
-; CHECK-NEXT: [[TMP1:%.*]] = xor i1 [[CALL1_I1_I10]], true
-; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP1]])
; CHECK-NEXT: [[CMP4_I11:%.*]] = icmp eq i32 [[CALL8_I_I8]], 0
; CHECK-NEXT: br i1 [[CMP4_I11]], label [[TEST2_FN2_EXIT24:%.*]], label [[COMMON_RET]]
; CHECK: common.ret:
@@ -124,13 +110,6 @@ define void @test2(ptr %this) #0 {
; CHECK: test2_fn2.exit24:
; CHECK-NEXT: store i8 0, ptr [[THIS]], align 4
; CHECK-NEXT: br label [[COMMON_RET]]
-; CHECK: if.end.i31:
-; CHECK-NEXT: [[CALL8_I_I32:%.*]] = tail call fastcc noundef i32 @test2_fn6()
-; CHECK-NEXT: [[TRUNC_I_I33:%.*]] = trunc i32 [[CALL8_I_I32]] to i8
-; CHECK-NEXT: [[CALL1_I1_I34:%.*]] = tail call i1 @test2_fn4(i8 [[TRUNC_I_I33]])
-; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[CALL1_I1_I34]], true
-; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP2]])
-; CHECK-NEXT: br label [[COMMON_RET]]
;
entry:
%call16 = call i1 @test2_fn2(ptr @.str.78)
@@ -163,10 +142,6 @@ define i1 @test2_fn2(ptr %__rhs) #0 {
; CHECK-NEXT: br i1 [[CMP2_NOT]], label [[IF_END:%.*]], label [[CLEANUP:%.*]]
; CHECK: if.end:
; CHECK-NEXT: [[CALL8_I:%.*]] = tail call fastcc noundef i32 @test2_fn6()
-; CHECK-NEXT: [[TRUNC_I:%.*]] = trunc i32 [[CALL8_I]] to i8
-; CHECK-NEXT: [[CALL1_I1:%.*]] = tail call i1 @test2_fn4(i8 [[TRUNC_I]])
-; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[CALL1_I1]], true
-; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP0]])
; CHECK-NEXT: [[CMP4:%.*]] = icmp eq i32 [[CALL8_I]], 0
; CHECK-NEXT: br label [[CLEANUP]]
; CHECK: cleanup:
@@ -210,7 +185,7 @@ cond.end: ; preds = %cond.true, %entry
define i1 @test2_fn4(i8 %bf.load) {
; CHECK-LABEL: define i1 @test2_fn4(
-; CHECK-SAME: i8 [[BF_LOAD:%.*]]) local_unnamed_addr #[[ATTR5:[0-9]+]] {
+; CHECK-SAME: i8 [[BF_LOAD:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp slt i8 [[BF_LOAD]], 0
; CHECK-NEXT: ret i1 [[TOBOOL]]
@@ -232,7 +207,7 @@ entry:
define internal i32 @test2_fn6() {
; CHECK-LABEL: define internal fastcc noundef i32 @test2_fn6(
-; CHECK-SAME: ) unnamed_addr #[[ATTR5]] {
+; CHECK-SAME: ) unnamed_addr #[[ATTR4]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i32 0
;
diff --git a/llvm/test/Transforms/PhaseOrdering/pr45682.ll b/llvm/test/Transforms/PhaseOrdering/pr45682.ll
index 46ee19178e356..50e31f1bf632d 100644
--- a/llvm/test/Transforms/PhaseOrdering/pr45682.ll
+++ b/llvm/test/Transforms/PhaseOrdering/pr45682.ll
@@ -5,8 +5,6 @@
define void @PR45682(i32 %x, i32 %y) {
; CHECK-LABEL: @PR45682(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[Y:%.*]], 0
-; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT: ret void
;
entry:
diff --git a/llvm/test/Transforms/PhaseOrdering/pr45687.ll b/llvm/test/Transforms/PhaseOrdering/pr45687.ll
index f0064b58820e4..36d7c24f2bd79 100644
--- a/llvm/test/Transforms/PhaseOrdering/pr45687.ll
+++ b/llvm/test/Transforms/PhaseOrdering/pr45687.ll
@@ -3,9 +3,6 @@
define void @PR45687(i32 %0) {
; CHECK-LABEL: @PR45687(
-; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP0:%.*]], 1
-; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 [[TMP2]], 3
-; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP3]])
; CHECK-NEXT: ret void
;
%2 = add i32 %0, 1
diff --git a/llvm/test/Transforms/PhaseOrdering/pr98799-inline-simplifycfg-ub.ll b/llvm/test/Transforms/PhaseOrdering/pr98799-inline-simplifycfg-ub.ll
index 2bb78dd5ec773..5c4ada38bd302 100644
--- a/llvm/test/Transforms/PhaseOrdering/pr98799-inline-simplifycfg-ub.ll
+++ b/llvm/test/Transforms/PhaseOrdering/pr98799-inline-simplifycfg-ub.ll
@@ -34,8 +34,6 @@ define i32 @foo(ptr %arg, i1 %arg1) {
; O2-LABEL: define i32 @foo(
; O2-SAME: ptr captures(none) [[ARG:%.*]], i1 [[ARG1:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
; O2-NEXT: [[BB:.*:]]
-; O2-NEXT: [[TMP0:%.*]] = xor i1 [[ARG1]], true
-; O2-NEXT: tail call void @llvm.assume(i1 [[TMP0]])
; O2-NEXT: [[I_I:%.*]] = load ptr, ptr [[ARG]], align 8, !nonnull [[META0:![0-9]+]], !noundef [[META0]]
; O2-NEXT: [[I3_I:%.*]] = getelementptr inbounds nuw i8, ptr [[I_I]], i64 1
; O2-NEXT: store ptr [[I3_I]], ptr [[ARG]], align 8
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
Hopefully that is one more step to allow us to make more and better use of assumes
Do you think that this pass in the future can be a good place for dropping assumes by setting eg. ranges to arguments something similar to llvm-project/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp Lines 3369 to 3384 in 6af5b41
I have tried to add handling for ranges there but there was regressions due to new uses after inlining |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could a possible follow-up drop identical assumes? If so, would it be possible to schedule this pass late? We see some redundant identical assumes in LV.
This adds a new pass for dropping assumes that are unlikely to be useful for further optimization. It works by discarding any assumes whose affected values are ephemeral (that is, only used by the assume). This pass currently runs at the start of the module optimization pipeline, that is post-inline (and post-link). Before that point, it is more likely for previously "useless" assumes to become useful again, e.g. because an additional user of the value is introduced after inlining + CSE.
4a818d7
to
27d9746
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks! I will investigate a follow-up related to my question.
The responsibility for removing redundant assumes falls largely to InstCombine, and to a lesser degree other passes that propagate assumes (like GVN, SCCP). |
I think that ideally we would do this in InstCombine, and then materialize the assume again if the instruction/function the metadata/attribute was attached to gets removed. We do this for nonnull is SROA: llvm-project/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp Lines 461 to 492 in efa7385
I hope that more aggressively dropping useless assumes will make this approach more viable... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LG. Thanks.
FYI I did a similar attempt last year to drop useless assumptions (inserted by rustc): main...dtcxzyw:llvm-project:perf/remove-dead-assume. It removes assumptions in leaf nodes of the dominator tree. Unfortunately it didn't work because SimplifyCFG may remove other edges and make them useful again.
invokeOptimizerEarlyEPCallbacks(MPM, Level, LTOPhase); | ||
|
||
FunctionPassManager OptimizePM; | ||
if (!isLTOPreLink(LTOPhase)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It deserves a comment here to explain why it only runs at post-inline and post-link.
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/88/builds/16220 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/168/builds/16217 Here is the relevant piece of the build log for the reference
|
This adds a new pass for dropping assumes that are unlikely to be useful for further optimization. It works by discarding any assumes whose affected values are one-use (which implies that they are only used by the assume, i.e. ephemeral). This pass currently runs at the start of the module optimization pipeline, that is post-inline and post-link. Before that point, it is more likely for previously "useless" assumes to become useful again, e.g. because an additional user of the value is introduced after inlining + CSE.
This adds a new pass for dropping assumes that are unlikely to be useful for further optimization. It works by discarding any assumes whose affected values are one-use (which implies that they are only used by the assume, i.e. ephemeral). This pass currently runs at the start of the module optimization pipeline, that is post-inline and post-link. Before that point, it is more likely for previously "useless" assumes to become useful again, e.g. because an additional user of the value is introduced after inlining + CSE.
llvm/llvm-project#159403 adds a pass which causes the tests in question to fail because it removes several calls to `llvm.assume(...)`. The fix at rust-lang/rust#146732 effectively neuters the test, so we may as well temporarily disable it on our side. Bug: 446928953 Change-Id: Iade597d144e68bf384076673b75f2f3f616de5b8 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6977874 Auto-Submit: Alan Zhao <[email protected]> Reviewed-by: Hans Wennborg <[email protected]> Commit-Queue: Hans Wennborg <[email protected]> Cr-Commit-Position: refs/heads/main@{#1519796}
This adds a new pass for dropping assumes that are unlikely to be useful for further optimization.
It works by discarding any assumes whose affected values are one-use (which implies that they are only used by the assume, i.e. ephemeral).
This pass currently runs at the start of the module optimization pipeline, that is post-inline and post-link. Before that point, it is more likely for previously "useless" assumes to become useful again, e.g. because an additional user of the value is introduced after inlining + CSE.
llvm-opt-benchmark: dtcxzyw/llvm-opt-benchmark#2829