Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang/test/CodeGen/inline-asm-x86-flag-output.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
27 changes: 27 additions & 0 deletions llvm/include/llvm/Transforms/Scalar/DropUnnecessaryAssumes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//===------------------------------------------------------------*- 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 {

struct DropUnnecessaryAssumesPass
: public PassInfoMixin<DropUnnecessaryAssumesPass> {
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};

} // end namespace llvm

#endif // LLVM_TRANSFORMS_SCALAR_DROPUNNECESSARYASSUMES_H
1 change: 1 addition & 0 deletions llvm/lib/Passes/PassBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Passes/PassBuilderPipelines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -1498,6 +1499,9 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
invokeOptimizerEarlyEPCallbacks(MPM, Level, LTOPhase);

FunctionPassManager OptimizePM;
if (!isLTOPreLink(LTOPhase))
Copy link
Member

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.

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
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Passes/PassRegistry.def
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Transforms/Scalar/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ add_llvm_component_library(LLVMScalarOpts
DeadStoreElimination.cpp
DFAJumpThreading.cpp
DivRemPairs.cpp
DropUnnecessaryAssumes.cpp
EarlyCSE.cpp
FlattenCFGPass.cpp
Float2Int.cpp
Expand Down
62 changes: 62 additions & 0 deletions llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//===------------------------------------------------------------*- 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;
using namespace llvm::PatternMatch;

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, 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.
// TODO: Handle multiple dead assumes on the same value.
if (!all_of(Affected, match_fn(m_OneUse(m_Value()))))
continue;

Assume->eraseFromParent();
RecursivelyDeleteTriviallyDeadInstructions(Cond);
Changed = true;
}

if (Changed) {
PreservedAnalyses PA;
PA.preserveSet<CFGAnalyses>();
return PA;
}
return PreservedAnalyses::all();
}
1 change: 1 addition & 0 deletions llvm/test/Other/new-pm-defaults.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions llvm/test/Other/new-pm-thinlto-postlink-defaults.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
96 changes: 96 additions & 0 deletions llvm/test/Transforms/DropUnnecessaryAssumes/basic.ll
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,39 +98,18 @@ 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:
; CHECK-NEXT: ret void
; 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)
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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]]
Expand All @@ -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
;
Expand Down
2 changes: 0 additions & 2 deletions llvm/test/Transforms/PhaseOrdering/pr45682.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
3 changes: 0 additions & 3 deletions llvm/test/Transforms/PhaseOrdering/pr45687.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down