mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-30 04:35:00 +00:00
generalize the pointer difference optimization to handle
a constantexpr gep on the 'base' side of the expression. This completes comment #4 in PR3351, which comes from 483.xalancbmk. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@92402 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f2ebc682d1
commit
85c1c964dc
@ -2770,21 +2770,57 @@ Value *InstCombiner::OptimizePointerDifference(Value *LHS, Value *RHS,
|
|||||||
// If LHS is a gep based on RHS or RHS is a gep based on LHS, we can optimize
|
// If LHS is a gep based on RHS or RHS is a gep based on LHS, we can optimize
|
||||||
// this.
|
// this.
|
||||||
bool Swapped;
|
bool Swapped;
|
||||||
GetElementPtrInst *GEP;
|
GetElementPtrInst *GEP = 0;
|
||||||
|
ConstantExpr *CstGEP = 0;
|
||||||
|
|
||||||
if ((GEP = dyn_cast<GetElementPtrInst>(LHS)) &&
|
// TODO: Could also optimize &A[i] - &A[j] -> "i-j", and "&A.foo[i] - &A.foo".
|
||||||
GEP->getOperand(0) == RHS)
|
// For now we require one side to be the base pointer "A" or a constant
|
||||||
Swapped = false;
|
// expression derived from it.
|
||||||
else if ((GEP = dyn_cast<GetElementPtrInst>(RHS)) &&
|
if (GetElementPtrInst *LHSGEP = dyn_cast<GetElementPtrInst>(LHS)) {
|
||||||
GEP->getOperand(0) == LHS)
|
// (gep X, ...) - X
|
||||||
Swapped = true;
|
if (LHSGEP->getOperand(0) == RHS) {
|
||||||
else
|
GEP = LHSGEP;
|
||||||
|
Swapped = false;
|
||||||
|
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(RHS)) {
|
||||||
|
// (gep X, ...) - (ce_gep X, ...)
|
||||||
|
if (CE->getOpcode() == Instruction::GetElementPtr &&
|
||||||
|
LHSGEP->getOperand(0) == CE->getOperand(0)) {
|
||||||
|
CstGEP = CE;
|
||||||
|
GEP = LHSGEP;
|
||||||
|
Swapped = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetElementPtrInst *RHSGEP = dyn_cast<GetElementPtrInst>(RHS)) {
|
||||||
|
// X - (gep X, ...)
|
||||||
|
if (RHSGEP->getOperand(0) == LHS) {
|
||||||
|
GEP = RHSGEP;
|
||||||
|
Swapped = true;
|
||||||
|
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(LHS)) {
|
||||||
|
// (ce_gep X, ...) - (gep X, ...)
|
||||||
|
if (CE->getOpcode() == Instruction::GetElementPtr &&
|
||||||
|
RHSGEP->getOperand(0) == CE->getOperand(0)) {
|
||||||
|
CstGEP = CE;
|
||||||
|
GEP = RHSGEP;
|
||||||
|
Swapped = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GEP == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// TODO: Could also optimize &A[i] - &A[j] -> "i-j".
|
|
||||||
|
|
||||||
// Emit the offset of the GEP and an intptr_t.
|
// Emit the offset of the GEP and an intptr_t.
|
||||||
Value *Result = EmitGEPOffset(GEP, *this);
|
Value *Result = EmitGEPOffset(GEP, *this);
|
||||||
|
|
||||||
|
// If we had a constant expression GEP on the other side offsetting the
|
||||||
|
// pointer, subtract it from the offset we have.
|
||||||
|
if (CstGEP) {
|
||||||
|
Value *CstOffset = EmitGEPOffset(CstGEP, *this);
|
||||||
|
Result = Builder->CreateSub(Result, CstOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// If we have p - gep(p, ...) then we have to negate the result.
|
// If we have p - gep(p, ...) then we have to negate the result.
|
||||||
if (Swapped)
|
if (Swapped)
|
||||||
|
@ -260,3 +260,16 @@ define i64 @test24b(i8* %P, i64 %A){
|
|||||||
; CHECK-NEXT: ret i64
|
; CHECK-NEXT: ret i64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
define i64 @test25(i8* %P, i64 %A){
|
||||||
|
%B = getelementptr inbounds [42 x i16]* @Arr, i64 0, i64 %A
|
||||||
|
%C = ptrtoint i16* %B to i64
|
||||||
|
%G = sub i64 %C, ptrtoint (i16* getelementptr ([42 x i16]* @Arr, i64 1, i64 0) to i64)
|
||||||
|
ret i64 %G
|
||||||
|
; CHECK: @test25
|
||||||
|
; CHECK-NEXT: shl i64 %A, 1
|
||||||
|
; CHECK-NEXT: add i64 {{.*}}, -84
|
||||||
|
; CHECK-NEXT: ret i64
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user