From 6487854b3fb5f2caf2505906fc73b9027a0abef0 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 11 Oct 2006 05:13:56 +0000 Subject: [PATCH] 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. llvm-svn: 30875 --- llvm/lib/Target/Alpha/AlphaISelDAGToDAG.cpp | 65 ++++++++++++++++----- llvm/lib/Target/Alpha/AlphaInstrInfo.td | 26 ++++++--- 2 files changed, 70 insertions(+), 21 deletions(-) diff --git a/llvm/lib/Target/Alpha/AlphaISelDAGToDAG.cpp b/llvm/lib/Target/Alpha/AlphaISelDAGToDAG.cpp index ed66592d4017..51de4e6ba5a2 100644 --- a/llvm/lib/Target/Alpha/AlphaISelDAGToDAG.cpp +++ b/llvm/lib/Target/Alpha/AlphaISelDAGToDAG.cpp @@ -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; diff --git a/llvm/lib/Target/Alpha/AlphaInstrInfo.td b/llvm/lib/Target/Alpha/AlphaInstrInfo.td index d63d0badff5c..3f897a76c825 100644 --- a/llvm/lib/Target/Alpha/AlphaInstrInfo.td +++ b/llvm/lib/Target/Alpha/AlphaInstrInfo.td @@ -59,8 +59,9 @@ def LL16 : SDNodeXFormgetValue())); }]>; -def iZAPX : SDNodeXFormgetValue())); +def iZAPX : SDNodeXForm(N->getOperand(1)); + return getI64Imm(get_zapImm(SDOperand(), RHS->getValue())); }]>; def nearP2X : SDNodeXFormgetValue()))); @@ -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(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