Skip to content

Commit

Permalink
[InstCombine] Preserve
Browse files Browse the repository at this point in the history
  • Loading branch information
fhahn committed Dec 22, 2024
1 parent 47d5075 commit f79dc21
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 20 deletions.
2 changes: 2 additions & 0 deletions llvm/include/llvm/IR/IRBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/IR/IRBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
15 changes: 14 additions & 1 deletion llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -4872,6 +4873,16 @@ bool InstCombinerImpl::tryToSinkInstruction(Instruction *I,
/// the new position.

BasicBlock::iterator InsertPos = DestBlock->getFirstInsertionPt();

if (!CleanupAssumptions && 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;

Expand Down Expand Up @@ -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;
Expand Down
15 changes: 10 additions & 5 deletions llvm/test/Transforms/InstCombine/assume.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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]]
;
Expand Down Expand Up @@ -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]]
;
Expand All @@ -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]]
Expand All @@ -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:%.*]]
Expand Down Expand Up @@ -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:%.*]]
Expand Down
12 changes: 8 additions & 4 deletions llvm/test/Transforms/InstCombine/select-cmp-br.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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]]
Expand Down Expand Up @@ -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:
Expand All @@ -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]]
Expand Down Expand Up @@ -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:
Expand All @@ -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]]
Expand Down Expand Up @@ -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:
Expand All @@ -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]]
Expand Down
25 changes: 15 additions & 10 deletions llvm/test/Transforms/InstCombine/sink_instruction.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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]] ]
Expand Down Expand Up @@ -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]]
Expand Down Expand Up @@ -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:%.*]]
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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:
Expand Down

0 comments on commit f79dc21

Please sign in to comment.