[llvm] [InstCombine] Add assumption to preserve deref info after sinking. (PR #120888)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Sun Dec 22 03:19:17 PST 2024
https://github.com/fhahn created https://github.com/llvm/llvm-project/pull/120888
None
>From 5a99a917aea901771f18951ba8b673d6b5a98a59 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Sun, 22 Dec 2024 11:16:58 +0000
Subject: [PATCH 1/2] [InstCombine] Add option to clean up some assumptions.
---
llvm/include/llvm/Transforms/InstCombine/InstCombine.h | 6 ++++++
llvm/lib/Passes/PassBuilder.cpp | 2 ++
llvm/lib/Passes/PassBuilderPipelines.cpp | 3 ++-
llvm/lib/Passes/PassRegistry.def | 2 +-
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp | 7 +++++++
llvm/lib/Transforms/InstCombine/InstCombineInternal.h | 8 ++++++--
llvm/lib/Transforms/InstCombine/InstructionCombining.cpp | 2 +-
7 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/llvm/include/llvm/Transforms/InstCombine/InstCombine.h b/llvm/include/llvm/Transforms/InstCombine/InstCombine.h
index c12d749709cd25..dd9d05cbbcf7c9 100644
--- a/llvm/include/llvm/Transforms/InstCombine/InstCombine.h
+++ b/llvm/include/llvm/Transforms/InstCombine/InstCombine.h
@@ -31,6 +31,7 @@ struct InstCombineOptions {
// Verify that a fix point has been reached after MaxIterations.
bool VerifyFixpoint = false;
unsigned MaxIterations = InstCombineDefaultMaxIterations;
+ bool CleanupAssumptions = false;
InstCombineOptions() = default;
@@ -43,6 +44,11 @@ struct InstCombineOptions {
MaxIterations = Value;
return *this;
}
+
+ InstCombineOptions &setCleanupAssumptions(bool Value) {
+ CleanupAssumptions = Value;
+ return *this;
+ }
};
class InstCombinePass : public PassInfoMixin<InstCombinePass> {
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index a936f5381137c6..6910c7977c296f 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -915,6 +915,8 @@ Expected<InstCombineOptions> parseInstCombineOptions(StringRef Params) {
ParamName).str(),
inconvertibleErrorCode());
Result.setMaxIterations((unsigned)MaxIterations.getZExtValue());
+ } else if (ParamName == "cleanup-assumptions") {
+ Result.setCleanupAssumptions(Enable);
} else {
return make_error<StringError>(
formatv("invalid InstCombine pass parameter '{0}' ", ParamName).str(),
diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp
index d737ea5ab070a9..fc47ac9d793d18 100644
--- a/llvm/lib/Passes/PassBuilderPipelines.cpp
+++ b/llvm/lib/Passes/PassBuilderPipelines.cpp
@@ -1305,7 +1305,8 @@ void PassBuilder::addVectorPasses(OptimizationLevel Level,
FPM.addPass(LoopLoadEliminationPass());
}
// Cleanup after the loop optimization passes.
- FPM.addPass(InstCombinePass());
+ FPM.addPass(
+ InstCombinePass(InstCombineOptions().setCleanupAssumptions(true)));
if (Level.getSpeedupLevel() > 1 && ExtraVectorizerPasses) {
ExtraFunctionPassManager<ShouldRunExtraVectorPasses> ExtraPasses;
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 9f0b09278edcca..78cdc3ecbfd69c 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -540,7 +540,7 @@ FUNCTION_PASS_WITH_PARAMS(
[](InstCombineOptions Opts) { return InstCombinePass(Opts); },
parseInstCombineOptions,
"no-use-loop-info;use-loop-info;no-verify-fixpoint;verify-fixpoint;"
- "max-iterations=N")
+ "max-iterations=N;cleanup-assumptions")
FUNCTION_PASS_WITH_PARAMS(
"loop-unroll", "LoopUnrollPass",
[](LoopUnrollOptions Opts) { return LoopUnrollPass(Opts); },
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index fd38738e3be80b..035536ce47ea1e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3172,6 +3172,13 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
MaybeSimplifyHint(OBU.Inputs[0]);
MaybeSimplifyHint(OBU.Inputs[1]);
}
+
+ // Try to clean up some assumption that are not very useful after this
+ // point.
+ if (CleanupAssumptions && (OBU.getTagName() == "dereferenceable")) {
+ auto *New = CallBase::removeOperandBundle(II, OBU.getTagID());
+ return New;
+ }
}
// Convert nonnull assume like:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index 3a074ee70dc487..6cfb703ed58f5c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -59,6 +59,8 @@ class User;
class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
: public InstCombiner,
public InstVisitor<InstCombinerImpl, Instruction *> {
+ bool CleanupAssumptions = false;
+
public:
InstCombinerImpl(InstructionWorklist &Worklist, BuilderTy &Builder,
bool MinimizeSize, AAResults *AA, AssumptionCache &AC,
@@ -66,9 +68,11 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
DominatorTree &DT, OptimizationRemarkEmitter &ORE,
BlockFrequencyInfo *BFI, BranchProbabilityInfo *BPI,
ProfileSummaryInfo *PSI, const DataLayout &DL,
- ReversePostOrderTraversal<BasicBlock *> &RPOT)
+ ReversePostOrderTraversal<BasicBlock *> &RPOT,
+ bool CleanupAssumptions)
: InstCombiner(Worklist, Builder, MinimizeSize, AA, AC, TLI, TTI, DT, ORE,
- BFI, BPI, PSI, DL, RPOT) {}
+ BFI, BPI, PSI, DL, RPOT),
+ CleanupAssumptions(CleanupAssumptions) {}
virtual ~InstCombinerImpl() = default;
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 934156f04f7fdd..5a11996182e7c5 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -5524,7 +5524,7 @@ static bool combineInstructionsOverFunction(
<< F.getName() << "\n");
InstCombinerImpl IC(Worklist, Builder, F.hasMinSize(), AA, AC, TLI, TTI, DT,
- ORE, BFI, BPI, PSI, DL, RPOT);
+ ORE, BFI, BPI, PSI, DL, RPOT, Opts.CleanupAssumptions);
IC.MaxArraySizeForCombine = MaxArraySize;
bool MadeChangeInThisIteration = IC.prepareWorklist(F);
MadeChangeInThisIteration |= IC.run();
>From 7b68352f3a84c1268e54a6d3ae3fa96248f9a3a6 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Sat, 21 Dec 2024 17:20:06 +0000
Subject: [PATCH 2/2] [InstCombine] Preserve
---
llvm/include/llvm/IR/IRBuilder.h | 2 ++
llvm/lib/IR/IRBuilder.cpp | 7 ++++++
.../InstCombine/InstructionCombining.cpp | 15 ++++++++++-
llvm/test/Transforms/InstCombine/assume.ll | 15 +++++++----
.../Transforms/InstCombine/select-cmp-br.ll | 12 ++++++---
.../InstCombine/sink_instruction.ll | 25 +++++++++++--------
6 files changed, 56 insertions(+), 20 deletions(-)
diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index 8cdfa27ece9378..ca349ec6f9cb96 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -2676,6 +2676,8 @@ class IRBuilderBase {
CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue,
Value *Alignment,
Value *OffsetValue = nullptr);
+
+ CallInst *CreateDereferenceableAssumption(Value *PtrValue, unsigned Size);
};
/// This provides a uniform API for creating instructions and inserting
diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp
index f340f7aafdc76f..11536fa56eee46 100644
--- a/llvm/lib/IR/IRBuilder.cpp
+++ b/llvm/lib/IR/IRBuilder.cpp
@@ -1273,6 +1273,13 @@ CallInst *IRBuilderBase::CreateAlignmentAssumption(const DataLayout &DL,
return CreateAlignmentAssumptionHelper(DL, PtrValue, Alignment, OffsetValue);
}
+CallInst *IRBuilderBase::CreateDereferenceableAssumption(Value *PtrValue,
+ unsigned Size) {
+ SmallVector<Value *, 4> Vals({PtrValue, getInt64(Size)});
+ OperandBundleDefT<Value *> AlignOpB("dereferenceable", Vals);
+ return CreateAssumption(ConstantInt::getTrue(getContext()), {AlignOpB});
+}
+
IRBuilderDefaultInserter::~IRBuilderDefaultInserter() = default;
IRBuilderCallbackInserter::~IRBuilderCallbackInserter() = default;
IRBuilderFolder::~IRBuilderFolder() = default;
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 5a11996182e7c5..72df6752e88f2c 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -40,6 +40,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Analysis/AssumeBundleQueries.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/Analysis/BlockFrequencyInfo.h"
@@ -4872,6 +4873,16 @@ bool InstCombinerImpl::tryToSinkInstruction(Instruction *I,
/// the new position.
BasicBlock::iterator InsertPos = DestBlock->getFirstInsertionPt();
+
+ if (isa<LoadInst>(I)) {
+ // Preserve dereferenceable at original position.
+ // TODO: Only need to add this extra information if I doesn't always execute
+ // in the new position.
+ Builder.SetInsertPoint(I);
+ Value *Ptr = I->getOperand(0);
+ Builder.CreateDereferenceableAssumption(
+ Ptr, I->getType()->getScalarSizeInBits());
+ }
I->moveBefore(*DestBlock, InsertPos);
++NumSunkInst;
@@ -5133,7 +5144,9 @@ bool InstCombinerImpl::run() {
for (Use &U : I->uses()) {
User *User = U.getUser();
- if (User->isDroppable())
+ if (User->isDroppable() &&
+ (!I->getType()->isPointerTy() ||
+ !getKnowledgeForValue(I, Attribute::Dereferenceable, &AC)))
continue;
if (NumUsers > MaxSinkNumUsers)
return std::nullopt;
diff --git a/llvm/test/Transforms/InstCombine/assume.ll b/llvm/test/Transforms/InstCombine/assume.ll
index 52f0adf02a3965..bc49c1459a0ebb 100644
--- a/llvm/test/Transforms/InstCombine/assume.ll
+++ b/llvm/test/Transforms/InstCombine/assume.ll
@@ -316,11 +316,12 @@ define i1 @nonnull3(ptr %a, i1 %control) {
;
; BUNDLES-LABEL: @nonnull3(
; BUNDLES-NEXT: entry:
+; BUNDLES-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[A:%.*]], i64 0) ]
; BUNDLES-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
; BUNDLES: taken:
; BUNDLES-NEXT: ret i1 false
; BUNDLES: not_taken:
-; BUNDLES-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
+; BUNDLES-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A]], align 8
; BUNDLES-NEXT: [[RVAL_2:%.*]] = icmp sgt ptr [[LOAD]], null
; BUNDLES-NEXT: ret i1 [[RVAL_2]]
;
@@ -454,11 +455,12 @@ define i1 @nonnull3A(ptr %a, i1 %control) {
;
; BUNDLES-LABEL: @nonnull3A(
; BUNDLES-NEXT: entry:
+; BUNDLES-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[A:%.*]], i64 0) ]
; BUNDLES-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
; BUNDLES: taken:
; BUNDLES-NEXT: ret i1 true
; BUNDLES: not_taken:
-; BUNDLES-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
+; BUNDLES-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A]], align 8
; BUNDLES-NEXT: [[RVAL_2:%.*]] = icmp sgt ptr [[LOAD]], null
; BUNDLES-NEXT: ret i1 [[RVAL_2]]
;
@@ -478,9 +480,10 @@ not_taken:
define i1 @nonnull3B(ptr %a, i1 %control) {
; CHECK-LABEL: @nonnull3B(
; CHECK-NEXT: entry:
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[A:%.*]], i64 0) ]
; CHECK-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
; CHECK: taken:
-; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
+; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A]], align 8
; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) [ "nonnull"(ptr [[LOAD]]) ]
; CHECK-NEXT: ret i1 [[CMP]]
@@ -504,9 +507,10 @@ declare i1 @tmp1(i1)
define i1 @nonnull3C(ptr %a, i1 %control) {
; CHECK-LABEL: @nonnull3C(
; CHECK-NEXT: entry:
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[A:%.*]], i64 0) ]
; CHECK-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
; CHECK: taken:
-; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
+; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A]], align 8
; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null
; CHECK-NEXT: [[CMP2:%.*]] = call i1 @tmp1(i1 [[CMP]])
; CHECK-NEXT: br label [[EXIT:%.*]]
@@ -534,9 +538,10 @@ not_taken:
define i1 @nonnull3D(ptr %a, i1 %control) {
; CHECK-LABEL: @nonnull3D(
; CHECK-NEXT: entry:
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[A:%.*]], i64 0) ]
; CHECK-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
; CHECK: taken:
-; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
+; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A]], align 8
; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null
; CHECK-NEXT: [[CMP2:%.*]] = call i1 @tmp1(i1 [[CMP]])
; CHECK-NEXT: br label [[EXIT:%.*]]
diff --git a/llvm/test/Transforms/InstCombine/select-cmp-br.ll b/llvm/test/Transforms/InstCombine/select-cmp-br.ll
index 2a8c19ece4b70a..98af6f4b4cc8c8 100644
--- a/llvm/test/Transforms/InstCombine/select-cmp-br.ll
+++ b/llvm/test/Transforms/InstCombine/select-cmp-br.ll
@@ -14,6 +14,8 @@ define void @test1(ptr %arg) {
; CHECK-NEXT: [[M:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[ARG]], i64 16
; CHECK-NEXT: [[N:%.*]] = load ptr, ptr [[TMP1]], align 8
+; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[M]], i64 72
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP2]], i64 0) ]
; CHECK-NEXT: [[TMP5_NOT:%.*]] = icmp eq ptr [[M]], [[N]]
; CHECK-NEXT: br i1 [[TMP5_NOT]], label [[BB8:%.*]], label [[BB10:%.*]]
; CHECK: bb:
@@ -22,7 +24,6 @@ define void @test1(ptr %arg) {
; CHECK-NEXT: tail call void @bar(ptr nonnull [[ARG]])
; CHECK-NEXT: br label [[BB:%.*]]
; CHECK: bb10:
-; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[M]], i64 72
; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP2]], align 8
; CHECK-NEXT: [[TMP11:%.*]] = tail call i64 [[TMP4]](ptr nonnull [[ARG]])
; CHECK-NEXT: br label [[BB]]
@@ -56,6 +57,8 @@ define void @test2(ptr %arg) {
; CHECK-NEXT: [[M:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[ARG]], i64 16
; CHECK-NEXT: [[N:%.*]] = load ptr, ptr [[TMP1]], align 8
+; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[M]], i64 72
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP2]], i64 0) ]
; CHECK-NEXT: [[TMP5:%.*]] = icmp eq ptr [[M]], [[N]]
; CHECK-NEXT: br i1 [[TMP5]], label [[BB10:%.*]], label [[BB8:%.*]]
; CHECK: bb:
@@ -64,7 +67,6 @@ define void @test2(ptr %arg) {
; CHECK-NEXT: tail call void @bar(ptr nonnull [[ARG]])
; CHECK-NEXT: br label [[BB:%.*]]
; CHECK: bb10:
-; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[M]], i64 72
; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP2]], align 8
; CHECK-NEXT: [[TMP11:%.*]] = tail call i64 [[TMP4]](ptr nonnull [[ARG]])
; CHECK-NEXT: br label [[BB]]
@@ -98,6 +100,8 @@ define void @test3(ptr %arg) {
; CHECK-NEXT: [[M:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[ARG]], i64 16
; CHECK-NEXT: [[N:%.*]] = load ptr, ptr [[TMP1]], align 8
+; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[M]], i64 72
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP2]], i64 0) ]
; CHECK-NEXT: [[TMP5:%.*]] = icmp eq ptr [[M]], [[N]]
; CHECK-NEXT: br i1 [[TMP5]], label [[BB8:%.*]], label [[BB10:%.*]]
; CHECK: bb:
@@ -106,7 +110,6 @@ define void @test3(ptr %arg) {
; CHECK-NEXT: tail call void @bar(ptr nonnull [[ARG]])
; CHECK-NEXT: br label [[BB:%.*]]
; CHECK: bb10:
-; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[M]], i64 72
; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP2]], align 8
; CHECK-NEXT: [[TMP11:%.*]] = tail call i64 [[TMP4]](ptr nonnull [[ARG]])
; CHECK-NEXT: br label [[BB]]
@@ -140,6 +143,8 @@ define void @test4(ptr %arg) {
; CHECK-NEXT: [[M:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[ARG]], i64 16
; CHECK-NEXT: [[N:%.*]] = load ptr, ptr [[TMP1]], align 8
+; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[M]], i64 72
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP2]], i64 0) ]
; CHECK-NEXT: [[TMP5:%.*]] = icmp eq ptr [[M]], [[N]]
; CHECK-NEXT: br i1 [[TMP5]], label [[BB10:%.*]], label [[BB8:%.*]]
; CHECK: bb:
@@ -148,7 +153,6 @@ define void @test4(ptr %arg) {
; CHECK-NEXT: tail call void @bar(ptr nonnull [[ARG]])
; CHECK-NEXT: br label [[BB:%.*]]
; CHECK: bb10:
-; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[M]], i64 72
; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP2]], align 8
; CHECK-NEXT: [[TMP11:%.*]] = tail call i64 [[TMP4]](ptr nonnull [[ARG]])
; CHECK-NEXT: br label [[BB]]
diff --git a/llvm/test/Transforms/InstCombine/sink_instruction.ll b/llvm/test/Transforms/InstCombine/sink_instruction.ll
index cb9a3069ca5fd4..bb41080f82f556 100644
--- a/llvm/test/Transforms/InstCombine/sink_instruction.ll
+++ b/llvm/test/Transforms/InstCombine/sink_instruction.ll
@@ -44,7 +44,7 @@ define i32 @test2(i32 %x) nounwind ssp "instcombine-no-verify-fixpoint" {
; CHECK: bb1:
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i32 [[X_ADDR_17]], 1
; CHECK-NEXT: [[TMP2:%.*]] = sdiv i32 [[TMP1]], [[X_ADDR_17]]
-; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 @bar() #[[ATTR3:[0-9]+]]
+; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 @bar() #[[ATTR4:[0-9]+]]
; CHECK-NEXT: br label [[BB2]]
; CHECK: bb2:
; CHECK-NEXT: [[X_ADDR_0]] = phi i32 [ [[TMP2]], [[BB1]] ], [ [[X_ADDR_17]], [[BB]] ]
@@ -84,13 +84,14 @@ declare i32 @bar()
define i32 @test3(ptr nocapture readonly %P, i32 %i) {
; CHECK-LABEL: @test3(
; CHECK-NEXT: entry:
-; CHECK-NEXT: switch i32 [[I:%.*]], label [[SW_EPILOG:%.*]] [
+; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[I:%.*]] to i64
+; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[IDXPROM]]
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARRAYIDX]], i64 32) ]
+; CHECK-NEXT: switch i32 [[I]], label [[SW_EPILOG:%.*]] [
; CHECK-NEXT: i32 5, label [[SW_BB:%.*]]
; CHECK-NEXT: i32 2, label [[SW_BB]]
; CHECK-NEXT: ]
; CHECK: sw.bb:
-; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64
-; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[IDXPROM]]
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[I]]
; CHECK-NEXT: br label [[SW_EPILOG]]
@@ -182,11 +183,12 @@ sw.epilog: ; preds = %entry, %sw.bb
define i32 @test6(ptr nocapture readonly %P, i32 %i, i1 %cond) {
; CHECK-LABEL: @test6(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[ADD:%.*]] = shl nsw i32 [[I:%.*]], 1
+; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[I:%.*]] to i64
+; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[IDXPROM]]
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARRAYIDX]], i64 32) ]
+; CHECK-NEXT: [[ADD:%.*]] = shl nsw i32 [[I]], 1
; CHECK-NEXT: br label [[DISPATCHBB:%.*]]
; CHECK: dispatchBB:
-; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64
-; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[IDXPROM]]
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
; CHECK-NEXT: switch i32 [[I]], label [[SW_BB:%.*]] [
; CHECK-NEXT: i32 5, label [[SW_EPILOG:%.*]]
@@ -277,12 +279,13 @@ abort:
define i32 @invariant_load_metadata(ptr %p, i1 %cond) {
; CHECK-LABEL: @invariant_load_metadata(
; CHECK-NEXT: entry:
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P:%.*]], i64 32) ]
; CHECK-NEXT: br i1 [[COND:%.*]], label [[BLOCK:%.*]], label [[END:%.*]]
; CHECK: block:
; CHECK-NEXT: call void @fn()
; CHECK-NEXT: br label [[END]]
; CHECK: end:
-; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[P:%.*]], align 4, !invariant.load [[META0:![0-9]+]]
+; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[P]], align 4, !invariant.load [[META0:![0-9]+]]
; CHECK-NEXT: ret i32 [[V]]
;
entry:
@@ -324,12 +327,13 @@ end:
define void @invariant_load_use_in_br(ptr %p, i1 %cond) {
; CHECK-LABEL: @invariant_load_use_in_br(
; CHECK-NEXT: entry:
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P:%.*]], i64 32) ]
; CHECK-NEXT: br i1 [[COND:%.*]], label [[TRUE_BR:%.*]], label [[FALSE_BR:%.*]]
; CHECK: true.br:
; CHECK-NEXT: call void @fn()
; CHECK-NEXT: br label [[EXIT:%.*]]
; CHECK: false.br:
-; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[P:%.*]], align 4
+; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[P]], align 4
; CHECK-NEXT: call void @fn(i32 [[VAL]])
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
@@ -353,13 +357,14 @@ exit:
define void @invariant_load_metadata_call(ptr %p, i1 %cond) {
; CHECK-LABEL: @invariant_load_metadata_call(
; CHECK-NEXT: entry:
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P:%.*]], i64 32) ]
; CHECK-NEXT: call void @fn()
; CHECK-NEXT: br i1 [[COND:%.*]], label [[TRUE_BR:%.*]], label [[FALSE_BR:%.*]]
; CHECK: true.br:
; CHECK-NEXT: call void @fn()
; CHECK-NEXT: br label [[EXIT:%.*]]
; CHECK: false.br:
-; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[P:%.*]], align 4, !invariant.load [[META0]]
+; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[P]], align 4, !invariant.load [[META0]]
; CHECK-NEXT: call void @fn(i32 [[VAL]])
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
More information about the llvm-commits
mailing list