Use cute tblgen tricks to make zap handling more powerful. Specifically,

when the dag combiner simplifies an and mask, notice this and allow those bits
to be missing from the zap mask.

This compiles Alpha/zapnot4.ll into:

        sll $16,3,$0
        zapnot $0,3,$0
        ret $31,($26),1

instead of:

        ldah $0,1($31)
        lda $0,-8($0)
        sll $16,3,$1
        and $1,$0,$0
        ret $31,($26),1

It would be *really* nice to replace the hunk of code in the
AlphaISelDAGToDAG.cpp file that matches (and (srl (x, C), c2) into
(SRL (ZAPNOTi)) with a similar pattern, but I've spent enough time poking
at alpha.  Make andrew will do this.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30875 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2006-10-11 05:13:56 +00:00
parent 3d2da9a426
commit d615ded96e
2 changed files with 70 additions and 21 deletions

View File

@ -59,19 +59,57 @@ namespace {
return x - get_ldah16(x) * IMM_MULT;
}
/// get_zapImm - Return a zap mask if X is a valid immediate for a zapnot
/// instruction (if not, return 0). Note that this code accepts partial
/// zap masks. For example (and LHS, 1) is a valid zap, as long we know
/// that the bits 1-7 of LHS are already zero. If LHS is non-null, we are
/// in checking mode. If LHS is null, we assume that the mask has already
/// been validated before.
uint64_t get_zapImm(SDOperand LHS, uint64_t Constant) {
uint64_t BitsToCheck = 0;
unsigned Result = 0;
for (unsigned i = 0; i != 8; ++i) {
if (((Constant >> 8*i) & 0xFF) == 0) {
// nothing to do.
} else {
Result |= 1 << i;
if (((Constant >> 8*i) & 0xFF) == 0xFF) {
// If the entire byte is set, zapnot the byte.
} else if (LHS.Val == 0) {
// Otherwise, if the mask was previously validated, we know its okay
// to zapnot this entire byte even though all the bits aren't set.
} else {
// Otherwise we don't know that the it's okay to zapnot this entire
// byte. Only do this iff we can prove that the missing bits are
// already null, so the bytezap doesn't need to really null them.
BitsToCheck |= ~Constant & (0xFF << 8*i);
}
}
}
// If there are missing bits in a byte (for example, X & 0xEF00), check to
// see if the missing bits (0x1000) are already known zero if not, the zap
// isn't okay to do, as it won't clear all the required bits.
if (BitsToCheck &&
!getTargetLowering().MaskedValueIsZero(LHS, BitsToCheck))
return 0;
return Result;
}
static uint64_t get_zapImm(uint64_t x) {
unsigned int build = 0;
for(int i = 0; i < 8; ++i)
{
if ((x & 0x00FF) == 0x00FF)
build |= 1 << i;
else if ((x & 0x00FF) != 0)
{ build = 0; break; }
x >>= 8;
}
unsigned build = 0;
for(int i = 0; i != 8; ++i) {
if ((x & 0x00FF) == 0x00FF)
build |= 1 << i;
else if ((x & 0x00FF) != 0)
return 0;
x >>= 8;
}
return build;
}
static uint64_t getNearPower2(uint64_t x) {
if (!x) return 0;
unsigned at = CountLeadingZeros_64(x);
@ -380,10 +418,11 @@ SDNode *AlphaDAGToDAGISel::Select(SDOperand Op) {
{
uint64_t sval = SC->getValue();
uint64_t mval = MC->getValue();
if (get_zapImm(mval)) //the result is a zap, let the autogened stuff deal
// If the result is a zap, let the autogened stuff handle it.
if (get_zapImm(N->getOperand(0), mval))
break;
// given mask X, and shift S, we want to see if there is any zap in the mask
// if we play around with the botton S bits
// given mask X, and shift S, we want to see if there is any zap in the
// mask if we play around with the botton S bits
uint64_t dontcare = (~0ULL) >> (64 - sval);
uint64_t mask = mval << sval;

View File

@ -59,8 +59,9 @@ def LL16 : SDNodeXForm<imm, [{ //lda part of constant
def LH16 : SDNodeXForm<imm, [{ //ldah part of constant (or more if too big)
return getI64Imm(get_ldah16(N->getValue()));
}]>;
def iZAPX : SDNodeXForm<imm, [{ // get imm to ZAPi
return getI64Imm(get_zapImm((uint64_t)N->getValue()));
def iZAPX : SDNodeXForm<and, [{ // get imm to ZAPi
ConstantSDNode *RHS = cast<ConstantSDNode>(N->getOperand(1));
return getI64Imm(get_zapImm(SDOperand(), RHS->getValue()));
}]>;
def nearP2X : SDNodeXForm<imm, [{
return getI64Imm(Log2_64(getNearPower2((uint64_t)N->getValue())));
@ -85,10 +86,15 @@ def immSExt16 : PatLeaf<(imm), [{ //imm fits in 16 bit sign extended field
def immSExt16int : PatLeaf<(imm), [{ //(int)imm fits in a 16 bit sign extended field
return ((int64_t)N->getValue() << 48) >> 48 == ((int64_t)N->getValue() << 32) >> 32;
}], SExt16>;
def immZAP : PatLeaf<(imm), [{ //imm is good for zapi
uint64_t build = get_zapImm((uint64_t)N->getValue());
return build != 0;
}], iZAPX>;
def zappat : PatFrag<(ops node:$LHS), (and node:$LHS, imm:$L), [{
if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
uint64_t build = get_zapImm(N->getOperand(0), (uint64_t)RHS->getValue());
return build != 0;
}
return false;
}]>;
def immFPZ : PatLeaf<(fpimm), [{ //the only fpconstant nodes are +/- 0.0
return true;
}]>;
@ -386,8 +392,12 @@ def XOR : OForm< 0x11, 0x40, "xor $RA,$RB,$RC",
def XORi : OFormL<0x11, 0x40, "xor $RA,$L,$RC",
[(set GPRC:$RC, (xor GPRC:$RA, immUExt8:$L))], s_ilog>;
def ZAPNOTi : OFormL<0x12, 0x31, "zapnot $RA,$L,$RC",
[(set GPRC:$RC, (and GPRC:$RA, immZAP:$L))], s_ishf>;
def ZAPNOTi : OFormL<0x12, 0x31, "zapnot $RA,$L,$RC", [], s_ishf>;
// Define the pattern that produces ZAPNOTi.
def : Pat<(i64 (zappat GPRC:$RA):$imm),
(ZAPNOTi GPRC:$RA, (iZAPX GPRC:$imm))>;
//Comparison, int
//So this is a waste of what this instruction can do, but it still saves something