Skip to content

Commit b9c785a

Browse files
committed
[InstCombine] Preserve
1 parent b455e89 commit b9c785a

File tree

6 files changed

+56
-20
lines changed

6 files changed

+56
-20
lines changed

llvm/include/llvm/IR/IRBuilder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2676,6 +2676,8 @@ class IRBuilderBase {
26762676
CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue,
26772677
Value *Alignment,
26782678
Value *OffsetValue = nullptr);
2679+
2680+
CallInst *CreateDereferenceableAssumption(Value *PtrValue, unsigned Size);
26792681
};
26802682

26812683
/// This provides a uniform API for creating instructions and inserting

llvm/lib/IR/IRBuilder.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1273,6 +1273,13 @@ CallInst *IRBuilderBase::CreateAlignmentAssumption(const DataLayout &DL,
12731273
return CreateAlignmentAssumptionHelper(DL, PtrValue, Alignment, OffsetValue);
12741274
}
12751275

1276+
CallInst *IRBuilderBase::CreateDereferenceableAssumption(Value *PtrValue,
1277+
unsigned Size) {
1278+
SmallVector<Value *, 4> Vals({PtrValue, getInt64(Size)});
1279+
OperandBundleDefT<Value *> AlignOpB("dereferenceable", Vals);
1280+
return CreateAssumption(ConstantInt::getTrue(getContext()), {AlignOpB});
1281+
}
1282+
12761283
IRBuilderDefaultInserter::~IRBuilderDefaultInserter() = default;
12771284
IRBuilderCallbackInserter::~IRBuilderCallbackInserter() = default;
12781285
IRBuilderFolder::~IRBuilderFolder() = default;

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "llvm/ADT/SmallVector.h"
4141
#include "llvm/ADT/Statistic.h"
4242
#include "llvm/Analysis/AliasAnalysis.h"
43+
#include "llvm/Analysis/AssumeBundleQueries.h"
4344
#include "llvm/Analysis/AssumptionCache.h"
4445
#include "llvm/Analysis/BasicAliasAnalysis.h"
4546
#include "llvm/Analysis/BlockFrequencyInfo.h"
@@ -4872,6 +4873,16 @@ bool InstCombinerImpl::tryToSinkInstruction(Instruction *I,
48724873
/// the new position.
48734874

48744875
BasicBlock::iterator InsertPos = DestBlock->getFirstInsertionPt();
4876+
4877+
if (!CleanupAssumptions && isa<LoadInst>(I)) {
4878+
// Preserve dereferenceable at original position.
4879+
// TODO: Only need to add this extra information if I doesn't always execute
4880+
// in the new position.
4881+
Builder.SetInsertPoint(I);
4882+
Value *Ptr = I->getOperand(0);
4883+
Builder.CreateDereferenceableAssumption(
4884+
Ptr, I->getType()->getScalarSizeInBits());
4885+
}
48754886
I->moveBefore(*DestBlock, InsertPos);
48764887
++NumSunkInst;
48774888

@@ -5133,7 +5144,9 @@ bool InstCombinerImpl::run() {
51335144

51345145
for (Use &U : I->uses()) {
51355146
User *User = U.getUser();
5136-
if (User->isDroppable())
5147+
if (User->isDroppable() &&
5148+
(!I->getType()->isPointerTy() ||
5149+
!getKnowledgeForValue(I, Attribute::Dereferenceable, &AC)))
51375150
continue;
51385151
if (NumUsers > MaxSinkNumUsers)
51395152
return std::nullopt;

llvm/test/Transforms/InstCombine/assume.ll

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -316,11 +316,12 @@ define i1 @nonnull3(ptr %a, i1 %control) {
316316
;
317317
; BUNDLES-LABEL: @nonnull3(
318318
; BUNDLES-NEXT: entry:
319+
; BUNDLES-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[A:%.*]], i64 0) ]
319320
; BUNDLES-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
320321
; BUNDLES: taken:
321322
; BUNDLES-NEXT: ret i1 false
322323
; BUNDLES: not_taken:
323-
; BUNDLES-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
324+
; BUNDLES-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A]], align 8
324325
; BUNDLES-NEXT: [[RVAL_2:%.*]] = icmp sgt ptr [[LOAD]], null
325326
; BUNDLES-NEXT: ret i1 [[RVAL_2]]
326327
;
@@ -454,11 +455,12 @@ define i1 @nonnull3A(ptr %a, i1 %control) {
454455
;
455456
; BUNDLES-LABEL: @nonnull3A(
456457
; BUNDLES-NEXT: entry:
458+
; BUNDLES-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[A:%.*]], i64 0) ]
457459
; BUNDLES-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
458460
; BUNDLES: taken:
459461
; BUNDLES-NEXT: ret i1 true
460462
; BUNDLES: not_taken:
461-
; BUNDLES-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
463+
; BUNDLES-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A]], align 8
462464
; BUNDLES-NEXT: [[RVAL_2:%.*]] = icmp sgt ptr [[LOAD]], null
463465
; BUNDLES-NEXT: ret i1 [[RVAL_2]]
464466
;
@@ -478,9 +480,10 @@ not_taken:
478480
define i1 @nonnull3B(ptr %a, i1 %control) {
479481
; CHECK-LABEL: @nonnull3B(
480482
; CHECK-NEXT: entry:
483+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[A:%.*]], i64 0) ]
481484
; CHECK-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
482485
; CHECK: taken:
483-
; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
486+
; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A]], align 8
484487
; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null
485488
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) [ "nonnull"(ptr [[LOAD]]) ]
486489
; CHECK-NEXT: ret i1 [[CMP]]
@@ -504,9 +507,10 @@ declare i1 @tmp1(i1)
504507
define i1 @nonnull3C(ptr %a, i1 %control) {
505508
; CHECK-LABEL: @nonnull3C(
506509
; CHECK-NEXT: entry:
510+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[A:%.*]], i64 0) ]
507511
; CHECK-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
508512
; CHECK: taken:
509-
; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
513+
; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A]], align 8
510514
; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null
511515
; CHECK-NEXT: [[CMP2:%.*]] = call i1 @tmp1(i1 [[CMP]])
512516
; CHECK-NEXT: br label [[EXIT:%.*]]
@@ -534,9 +538,10 @@ not_taken:
534538
define i1 @nonnull3D(ptr %a, i1 %control) {
535539
; CHECK-LABEL: @nonnull3D(
536540
; CHECK-NEXT: entry:
541+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[A:%.*]], i64 0) ]
537542
; CHECK-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
538543
; CHECK: taken:
539-
; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
544+
; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A]], align 8
540545
; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null
541546
; CHECK-NEXT: [[CMP2:%.*]] = call i1 @tmp1(i1 [[CMP]])
542547
; CHECK-NEXT: br label [[EXIT:%.*]]

llvm/test/Transforms/InstCombine/select-cmp-br.ll

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ define void @test1(ptr %arg) {
1414
; CHECK-NEXT: [[M:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
1515
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[ARG]], i64 16
1616
; CHECK-NEXT: [[N:%.*]] = load ptr, ptr [[TMP1]], align 8
17+
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[M]], i64 72
18+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP2]], i64 0) ]
1719
; CHECK-NEXT: [[TMP5_NOT:%.*]] = icmp eq ptr [[M]], [[N]]
1820
; CHECK-NEXT: br i1 [[TMP5_NOT]], label [[BB8:%.*]], label [[BB10:%.*]]
1921
; CHECK: bb:
@@ -22,7 +24,6 @@ define void @test1(ptr %arg) {
2224
; CHECK-NEXT: tail call void @bar(ptr nonnull [[ARG]])
2325
; CHECK-NEXT: br label [[BB:%.*]]
2426
; CHECK: bb10:
25-
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[M]], i64 72
2627
; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP2]], align 8
2728
; CHECK-NEXT: [[TMP11:%.*]] = tail call i64 [[TMP4]](ptr nonnull [[ARG]])
2829
; CHECK-NEXT: br label [[BB]]
@@ -56,6 +57,8 @@ define void @test2(ptr %arg) {
5657
; CHECK-NEXT: [[M:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
5758
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[ARG]], i64 16
5859
; CHECK-NEXT: [[N:%.*]] = load ptr, ptr [[TMP1]], align 8
60+
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[M]], i64 72
61+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP2]], i64 0) ]
5962
; CHECK-NEXT: [[TMP5:%.*]] = icmp eq ptr [[M]], [[N]]
6063
; CHECK-NEXT: br i1 [[TMP5]], label [[BB10:%.*]], label [[BB8:%.*]]
6164
; CHECK: bb:
@@ -64,7 +67,6 @@ define void @test2(ptr %arg) {
6467
; CHECK-NEXT: tail call void @bar(ptr nonnull [[ARG]])
6568
; CHECK-NEXT: br label [[BB:%.*]]
6669
; CHECK: bb10:
67-
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[M]], i64 72
6870
; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP2]], align 8
6971
; CHECK-NEXT: [[TMP11:%.*]] = tail call i64 [[TMP4]](ptr nonnull [[ARG]])
7072
; CHECK-NEXT: br label [[BB]]
@@ -98,6 +100,8 @@ define void @test3(ptr %arg) {
98100
; CHECK-NEXT: [[M:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
99101
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[ARG]], i64 16
100102
; CHECK-NEXT: [[N:%.*]] = load ptr, ptr [[TMP1]], align 8
103+
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[M]], i64 72
104+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP2]], i64 0) ]
101105
; CHECK-NEXT: [[TMP5:%.*]] = icmp eq ptr [[M]], [[N]]
102106
; CHECK-NEXT: br i1 [[TMP5]], label [[BB8:%.*]], label [[BB10:%.*]]
103107
; CHECK: bb:
@@ -106,7 +110,6 @@ define void @test3(ptr %arg) {
106110
; CHECK-NEXT: tail call void @bar(ptr nonnull [[ARG]])
107111
; CHECK-NEXT: br label [[BB:%.*]]
108112
; CHECK: bb10:
109-
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[M]], i64 72
110113
; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP2]], align 8
111114
; CHECK-NEXT: [[TMP11:%.*]] = tail call i64 [[TMP4]](ptr nonnull [[ARG]])
112115
; CHECK-NEXT: br label [[BB]]
@@ -140,6 +143,8 @@ define void @test4(ptr %arg) {
140143
; CHECK-NEXT: [[M:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
141144
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[ARG]], i64 16
142145
; CHECK-NEXT: [[N:%.*]] = load ptr, ptr [[TMP1]], align 8
146+
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[M]], i64 72
147+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP2]], i64 0) ]
143148
; CHECK-NEXT: [[TMP5:%.*]] = icmp eq ptr [[M]], [[N]]
144149
; CHECK-NEXT: br i1 [[TMP5]], label [[BB10:%.*]], label [[BB8:%.*]]
145150
; CHECK: bb:
@@ -148,7 +153,6 @@ define void @test4(ptr %arg) {
148153
; CHECK-NEXT: tail call void @bar(ptr nonnull [[ARG]])
149154
; CHECK-NEXT: br label [[BB:%.*]]
150155
; CHECK: bb10:
151-
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[M]], i64 72
152156
; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP2]], align 8
153157
; CHECK-NEXT: [[TMP11:%.*]] = tail call i64 [[TMP4]](ptr nonnull [[ARG]])
154158
; CHECK-NEXT: br label [[BB]]

llvm/test/Transforms/InstCombine/sink_instruction.ll

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ define i32 @test2(i32 %x) nounwind ssp "instcombine-no-verify-fixpoint" {
4444
; CHECK: bb1:
4545
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i32 [[X_ADDR_17]], 1
4646
; CHECK-NEXT: [[TMP2:%.*]] = sdiv i32 [[TMP1]], [[X_ADDR_17]]
47-
; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 @bar() #[[ATTR3:[0-9]+]]
47+
; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 @bar() #[[ATTR4:[0-9]+]]
4848
; CHECK-NEXT: br label [[BB2]]
4949
; CHECK: bb2:
5050
; CHECK-NEXT: [[X_ADDR_0]] = phi i32 [ [[TMP2]], [[BB1]] ], [ [[X_ADDR_17]], [[BB]] ]
@@ -84,13 +84,14 @@ declare i32 @bar()
8484
define i32 @test3(ptr nocapture readonly %P, i32 %i) {
8585
; CHECK-LABEL: @test3(
8686
; CHECK-NEXT: entry:
87-
; CHECK-NEXT: switch i32 [[I:%.*]], label [[SW_EPILOG:%.*]] [
87+
; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[I:%.*]] to i64
88+
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[IDXPROM]]
89+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARRAYIDX]], i64 32) ]
90+
; CHECK-NEXT: switch i32 [[I]], label [[SW_EPILOG:%.*]] [
8891
; CHECK-NEXT: i32 5, label [[SW_BB:%.*]]
8992
; CHECK-NEXT: i32 2, label [[SW_BB]]
9093
; CHECK-NEXT: ]
9194
; CHECK: sw.bb:
92-
; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64
93-
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[IDXPROM]]
9495
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
9596
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[I]]
9697
; CHECK-NEXT: br label [[SW_EPILOG]]
@@ -182,11 +183,12 @@ sw.epilog: ; preds = %entry, %sw.bb
182183
define i32 @test6(ptr nocapture readonly %P, i32 %i, i1 %cond) {
183184
; CHECK-LABEL: @test6(
184185
; CHECK-NEXT: entry:
185-
; CHECK-NEXT: [[ADD:%.*]] = shl nsw i32 [[I:%.*]], 1
186+
; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[I:%.*]] to i64
187+
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[IDXPROM]]
188+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARRAYIDX]], i64 32) ]
189+
; CHECK-NEXT: [[ADD:%.*]] = shl nsw i32 [[I]], 1
186190
; CHECK-NEXT: br label [[DISPATCHBB:%.*]]
187191
; CHECK: dispatchBB:
188-
; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64
189-
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[IDXPROM]]
190192
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
191193
; CHECK-NEXT: switch i32 [[I]], label [[SW_BB:%.*]] [
192194
; CHECK-NEXT: i32 5, label [[SW_EPILOG:%.*]]
@@ -277,12 +279,13 @@ abort:
277279
define i32 @invariant_load_metadata(ptr %p, i1 %cond) {
278280
; CHECK-LABEL: @invariant_load_metadata(
279281
; CHECK-NEXT: entry:
282+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P:%.*]], i64 32) ]
280283
; CHECK-NEXT: br i1 [[COND:%.*]], label [[BLOCK:%.*]], label [[END:%.*]]
281284
; CHECK: block:
282285
; CHECK-NEXT: call void @fn()
283286
; CHECK-NEXT: br label [[END]]
284287
; CHECK: end:
285-
; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[P:%.*]], align 4, !invariant.load [[META0:![0-9]+]]
288+
; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[P]], align 4, !invariant.load [[META0:![0-9]+]]
286289
; CHECK-NEXT: ret i32 [[V]]
287290
;
288291
entry:
@@ -324,12 +327,13 @@ end:
324327
define void @invariant_load_use_in_br(ptr %p, i1 %cond) {
325328
; CHECK-LABEL: @invariant_load_use_in_br(
326329
; CHECK-NEXT: entry:
330+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P:%.*]], i64 32) ]
327331
; CHECK-NEXT: br i1 [[COND:%.*]], label [[TRUE_BR:%.*]], label [[FALSE_BR:%.*]]
328332
; CHECK: true.br:
329333
; CHECK-NEXT: call void @fn()
330334
; CHECK-NEXT: br label [[EXIT:%.*]]
331335
; CHECK: false.br:
332-
; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[P:%.*]], align 4
336+
; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[P]], align 4
333337
; CHECK-NEXT: call void @fn(i32 [[VAL]])
334338
; CHECK-NEXT: br label [[EXIT]]
335339
; CHECK: exit:
@@ -353,13 +357,14 @@ exit:
353357
define void @invariant_load_metadata_call(ptr %p, i1 %cond) {
354358
; CHECK-LABEL: @invariant_load_metadata_call(
355359
; CHECK-NEXT: entry:
360+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P:%.*]], i64 32) ]
356361
; CHECK-NEXT: call void @fn()
357362
; CHECK-NEXT: br i1 [[COND:%.*]], label [[TRUE_BR:%.*]], label [[FALSE_BR:%.*]]
358363
; CHECK: true.br:
359364
; CHECK-NEXT: call void @fn()
360365
; CHECK-NEXT: br label [[EXIT:%.*]]
361366
; CHECK: false.br:
362-
; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[P:%.*]], align 4, !invariant.load [[META0]]
367+
; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[P]], align 4, !invariant.load [[META0]]
363368
; CHECK-NEXT: call void @fn(i32 [[VAL]])
364369
; CHECK-NEXT: br label [[EXIT]]
365370
; CHECK: exit:

0 commit comments

Comments
 (0)