implement InstCombine/and-compare.ll:test1. This compiles:

typedef struct { unsigned prefix : 4; unsigned code : 4; unsigned unsigned_p : 4; } tree_common;
int foo(tree_common *a, tree_common *b) { return a->code == b->code; }

into:

_foo:
        movl 4(%esp), %eax
        movl 8(%esp), %ecx
        movl (%eax), %eax
        xorl (%ecx), %eax
        # TRUNCATE movb %al, %al
        shrb $4, %al
        testb %al, %al
        sete %al
        movzbl %al, %eax
        ret

instead of:

_foo:
        movl 8(%esp), %eax
        movb (%eax), %al
        shrb $4, %al
        movl 4(%esp), %ecx
        movb (%ecx), %cl
        shrb $4, %cl
        cmpb %al, %cl
        sete %al
        movzbl %al, %eax
        ret

saving one cycle by eliminating a shift.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31727 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2006-11-14 06:06:06 +00:00
parent 96dddd969f
commit 9c2328e5a9

View File

@ -4950,6 +4950,32 @@ Instruction *InstCombiner::visitSetCondInst(SetCondInst &I) {
return BinaryOperator::create(I.getOpcode(), B,
Constant::getNullValue(B->getType()));
}
Value *C, *D;
// (X&Z) == (Y&Z) -> (X^Y) & Z == 0
if (Op0->hasOneUse() && Op1->hasOneUse() &&
match(Op0, m_And(m_Value(A), m_Value(B))) &&
match(Op1, m_And(m_Value(C), m_Value(D)))) {
Value *X = 0, *Y = 0, *Z = 0;
if (A == C) {
X = B; Y = D; Z = A;
} else if (A == D) {
X = B; Y = C; Z = A;
} else if (B == C) {
X = A; Y = D; Z = B;
} else if (B == D) {
X = A; Y = C; Z = B;
}
if (X) { // Build (X^Y) & Z
Op1 = InsertNewInstBefore(BinaryOperator::createXor(X, Y, "tmp"), I);
Op1 = InsertNewInstBefore(BinaryOperator::createAnd(Op1, Z, "tmp"), I);
I.setOperand(0, Op1);
I.setOperand(1, Constant::getNullValue(Op1->getType()));
return &I;
}
}
}
return Changed ? &I : 0;
}