Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 6d27532

Browse files
authored
Merge pull request #47 from eddyb/fix-pointer-range-loops
Backport 4 commits to optimize pointer range loops better.
2 parents 786aad1 + c3eb3c7 commit 6d27532

File tree

4 files changed

+71
-3
lines changed

4 files changed

+71
-3
lines changed

lib/Analysis/InstructionSimplify.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3092,6 +3092,16 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
30923092
if (LHS->getType()->isPointerTy())
30933093
if (auto *C = computePointerICmp(Q.DL, Q.TLI, Q.DT, Pred, Q.CxtI, LHS, RHS))
30943094
return C;
3095+
if (auto *CLHS = dyn_cast<PtrToIntOperator>(LHS))
3096+
if (auto *CRHS = dyn_cast<PtrToIntOperator>(RHS))
3097+
if (Q.DL.getTypeSizeInBits(CLHS->getPointerOperandType()) ==
3098+
Q.DL.getTypeSizeInBits(CLHS->getType()) &&
3099+
Q.DL.getTypeSizeInBits(CRHS->getPointerOperandType()) ==
3100+
Q.DL.getTypeSizeInBits(CRHS->getType()))
3101+
if (auto *C = computePointerICmp(Q.DL, Q.TLI, Q.DT, Pred, Q.CxtI,
3102+
CLHS->getPointerOperand(),
3103+
CRHS->getPointerOperand()))
3104+
return C;
30953105

30963106
if (GetElementPtrInst *GLHS = dyn_cast<GetElementPtrInst>(LHS)) {
30973107
if (GEPOperator *GRHS = dyn_cast<GEPOperator>(RHS)) {
@@ -3587,6 +3597,32 @@ static Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops,
35873597
}
35883598
}
35893599

3600+
if (Q.DL.getTypeAllocSize(LastType) == 1 &&
3601+
all_of(Ops.slice(1).drop_back(1),
3602+
[](Value *Idx) { return match(Idx, m_Zero()); })) {
3603+
unsigned PtrWidth =
3604+
Q.DL.getPointerSizeInBits(Ops[0]->getType()->getPointerAddressSpace());
3605+
if (Q.DL.getTypeSizeInBits(Ops.back()->getType()) == PtrWidth) {
3606+
APInt BasePtrOffset(PtrWidth, 0);
3607+
Value *StrippedBasePtr =
3608+
Ops[0]->stripAndAccumulateInBoundsConstantOffsets(Q.DL,
3609+
BasePtrOffset);
3610+
3611+
// gep (gep V, C), (sub 0, V) -> C
3612+
if (match(Ops.back(),
3613+
m_Sub(m_Zero(), m_PtrToInt(m_Specific(StrippedBasePtr))))) {
3614+
auto *CI = ConstantInt::get(GEPTy->getContext(), BasePtrOffset);
3615+
return ConstantExpr::getIntToPtr(CI, GEPTy);
3616+
}
3617+
// gep (gep V, C), (xor V, -1) -> C-1
3618+
if (match(Ops.back(),
3619+
m_Xor(m_PtrToInt(m_Specific(StrippedBasePtr)), m_AllOnes()))) {
3620+
auto *CI = ConstantInt::get(GEPTy->getContext(), BasePtrOffset - 1);
3621+
return ConstantExpr::getIntToPtr(CI, GEPTy);
3622+
}
3623+
}
3624+
}
3625+
35903626
// Check to see if this is constant foldable.
35913627
for (unsigned i = 0, e = Ops.size(); i != e; ++i)
35923628
if (!isa<Constant>(Ops[i]))

lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1898,6 +1898,25 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
18981898
}
18991899
}
19001900

1901+
if (!GEP.isInBounds()) {
1902+
unsigned PtrWidth =
1903+
DL.getPointerSizeInBits(PtrOp->getType()->getPointerAddressSpace());
1904+
APInt BasePtrOffset(PtrWidth, 0);
1905+
Value *UnderlyingPtrOp =
1906+
PtrOp->stripAndAccumulateInBoundsConstantOffsets(DL,
1907+
BasePtrOffset);
1908+
if (auto *AI = dyn_cast<AllocaInst>(UnderlyingPtrOp)) {
1909+
if (GEP.accumulateConstantOffset(DL, BasePtrOffset) &&
1910+
BasePtrOffset.isNonNegative()) {
1911+
APInt AllocSize(PtrWidth, DL.getTypeAllocSize(AI->getAllocatedType()));
1912+
if (BasePtrOffset.ule(AllocSize)) {
1913+
return GetElementPtrInst::CreateInBounds(
1914+
PtrOp, makeArrayRef(Ops).slice(1), GEP.getName());
1915+
}
1916+
}
1917+
}
1918+
}
1919+
19011920
return nullptr;
19021921
}
19031922

test/Transforms/InstCombine/getelementptr.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ define i32 @test21() {
366366
%rval = load i32, i32* %pbobel
367367
ret i32 %rval
368368
; CHECK-LABEL: @test21(
369-
; CHECK: getelementptr %intstruct, %intstruct* %pbob1, i64 0, i32 0
369+
; CHECK: getelementptr inbounds %intstruct, %intstruct* %pbob1, i64 0, i32 0
370370
}
371371

372372

@@ -540,8 +540,8 @@ define i8* @test32(i8* %v) {
540540
%G = load i8*, i8** %F
541541
ret i8* %G
542542
; CHECK-LABEL: @test32(
543-
; CHECK: %D = getelementptr [4 x i8*], [4 x i8*]* %A, i64 0, i64 1
544-
; CHECK: %F = getelementptr [4 x i8*], [4 x i8*]* %A, i64 0, i64 2
543+
; CHECK: %D = getelementptr inbounds [4 x i8*], [4 x i8*]* %A, i64 0, i64 1
544+
; CHECK: %F = getelementptr inbounds [4 x i8*], [4 x i8*]* %A, i64 0, i64 2
545545
}
546546

547547
; PR3290

test/Transforms/InstSimplify/compare.ll

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,19 @@ define i1 @gep16(i8* %ptr, i32 %a) {
205205
; CHECK-NEXT: ret i1 false
206206
}
207207

208+
define i1 @gep17() {
209+
; CHECK-LABEL: @gep17(
210+
%alloca = alloca i32, align 4
211+
%bc = bitcast i32* %alloca to [4 x i8]*
212+
%gep1 = getelementptr inbounds i32, i32* %alloca, i32 1
213+
%pti1 = ptrtoint i32* %gep1 to i32
214+
%gep2 = getelementptr inbounds [4 x i8], [4 x i8]* %bc, i32 0, i32 1
215+
%pti2 = ptrtoint i8* %gep2 to i32
216+
%cmp = icmp ugt i32 %pti1, %pti2
217+
ret i1 %cmp
218+
; CHECK-NEXT: ret i1 true
219+
}
220+
208221
define i1 @zext(i32 %x) {
209222
; CHECK-LABEL: @zext(
210223
%e1 = zext i32 %x to i64

0 commit comments

Comments
 (0)