mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 04:30:12 +00:00
Implement an optimization for == and != comparisons like this:
_Bool test2(int X, int Y) { return &arr[X][Y] == arr; } instead of generating this: bool %test2(int %X, int %Y) { %tmp.3.idx = mul int %X, 160 ; <int> [#uses=1] %tmp.3.idx1 = shl int %Y, ubyte 2 ; <int> [#uses=1] %tmp.3.offs2 = sub int 0, %tmp.3.idx ; <int> [#uses=1] %tmp.7 = seteq int %tmp.3.idx1, %tmp.3.offs2 ; <bool> [#uses=1] ret bool %tmp.7 } generate this: bool %test2(int %X, int %Y) { seteq int %X, 0 ; <bool>:0 [#uses=1] seteq int %Y, 0 ; <bool>:1 [#uses=1] %tmp.7 = and bool %0, %1 ; <bool> [#uses=1] ret bool %tmp.7 } This idiom occurs in C++ programs when iterating from begin() to end(), in a vector or array. For example, we now compile this: void test(int X, int Y) { for (int *i = arr; i != arr+100; ++i) foo(*i); } to this: no_exit: ; preds = %entry, %no_exit ... %exitcond = seteq uint %indvar.next, 100 ; <bool> [#uses=1] br bool %exitcond, label %return, label %no_exit instead of this: no_exit: ; preds = %entry, %no_exit ... %inc5 = getelementptr [100 x [40 x int]]* %arr, int 0, int 0, int %inc.rec ; <int*> [#uses=1] %tmp.8 = seteq int* %inc5, getelementptr ([100 x [40 x int]]* %arr, int 0, int 100, int 0) ; <bool> [#uses=1] %indvar.next = add uint %indvar, 1 ; <uint> [#uses=1] br bool %tmp.8, label %return, label %no_exit git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19536 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
18c2f13e0f
commit
e9d782b7be
@ -2149,12 +2149,53 @@ Instruction *InstCombiner::FoldGEPSetCC(User *GEPLHS, Value *RHS,
|
||||
Instruction::BinaryOps Cond,
|
||||
Instruction &I) {
|
||||
assert(dyn_castGetElementPtr(GEPLHS) && "LHS is not a getelementptr!");
|
||||
|
||||
|
||||
if (CastInst *CI = dyn_cast<CastInst>(RHS))
|
||||
if (isa<PointerType>(CI->getOperand(0)->getType()))
|
||||
RHS = CI->getOperand(0);
|
||||
|
||||
Value *PtrBase = GEPLHS->getOperand(0);
|
||||
if (PtrBase == RHS) {
|
||||
// As an optimization, we don't actually have to compute the actual value of
|
||||
// OFFSET if this is a seteq or setne comparison, just return whether each
|
||||
// index is zero or not.
|
||||
if (Cond == Instruction::SetEQ || Cond == Instruction::SetNE) {
|
||||
Instruction *InVal = 0;
|
||||
for (unsigned i = 1, e = GEPLHS->getNumOperands(); i != e; ++i) {
|
||||
bool EmitIt = true;
|
||||
if (Constant *C = dyn_cast<Constant>(GEPLHS->getOperand(i))) {
|
||||
if (isa<UndefValue>(C)) // undef index -> undef.
|
||||
return ReplaceInstUsesWith(I, UndefValue::get(I.getType()));
|
||||
if (C->isNullValue())
|
||||
EmitIt = false;
|
||||
else if (isa<ConstantInt>(C))
|
||||
return ReplaceInstUsesWith(I, // No comparison is needed here.
|
||||
ConstantBool::get(Cond == Instruction::SetNE));
|
||||
}
|
||||
|
||||
if (EmitIt) {
|
||||
Instruction *Comp =
|
||||
new SetCondInst(Cond, GEPLHS->getOperand(i),
|
||||
Constant::getNullValue(GEPLHS->getOperand(i)->getType()));
|
||||
if (InVal == 0)
|
||||
InVal = Comp;
|
||||
else {
|
||||
InVal = InsertNewInstBefore(InVal, I);
|
||||
InsertNewInstBefore(Comp, I);
|
||||
if (Cond == Instruction::SetNE) // True if any are unequal
|
||||
InVal = BinaryOperator::createOr(InVal, Comp);
|
||||
else // True if all are equal
|
||||
InVal = BinaryOperator::createAnd(InVal, Comp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (InVal)
|
||||
return InVal;
|
||||
else
|
||||
ReplaceInstUsesWith(I, // No comparison is needed here, all indexes = 0
|
||||
ConstantBool::get(Cond == Instruction::SetEQ));
|
||||
}
|
||||
|
||||
// Only lower this if the setcc is the only user of the GEP or if we expect
|
||||
// the result to fold to a constant!
|
||||
@ -2168,6 +2209,27 @@ Instruction *InstCombiner::FoldGEPSetCC(User *GEPLHS, Value *RHS,
|
||||
if (PtrBase != GEPRHS->getOperand(0))
|
||||
return 0;
|
||||
|
||||
// If one of the GEPs has all zero indices, recurse.
|
||||
bool AllZeros = true;
|
||||
for (unsigned i = 1, e = GEPLHS->getNumOperands(); i != e; ++i)
|
||||
if (!isa<Constant>(GEPLHS->getOperand(i)) ||
|
||||
!cast<Constant>(GEPLHS->getOperand(i))->isNullValue()) {
|
||||
AllZeros = false;
|
||||
break;
|
||||
}
|
||||
if (AllZeros)
|
||||
return FoldGEPSetCC(GEPRHS, GEPLHS->getOperand(0),
|
||||
SetCondInst::getSwappedCondition(Cond), I);
|
||||
AllZeros = true;
|
||||
for (unsigned i = 1, e = GEPRHS->getNumOperands(); i != e; ++i)
|
||||
if (!isa<Constant>(GEPRHS->getOperand(i)) ||
|
||||
!cast<Constant>(GEPRHS->getOperand(i))->isNullValue()) {
|
||||
AllZeros = false;
|
||||
break;
|
||||
}
|
||||
if (AllZeros)
|
||||
return FoldGEPSetCC(GEPLHS, GEPRHS->getOperand(0), Cond, I);
|
||||
|
||||
// Only lower this if the setcc is the only user of the GEP or if we expect
|
||||
// the result to fold to a constant!
|
||||
if ((isa<ConstantExpr>(GEPLHS) || GEPLHS->hasOneUse()) &&
|
||||
|
Loading…
Reference in New Issue
Block a user