Implement logical and with an immediate that consists of a contiguous block

of one or more 1 bits (may wrap from least significant bit to most
significant bit) as the rlwinm rather than andi., andis., or some longer
instructons sequence.

int andn4(int z) { return z & -4; }
int clearhi(int z) { return z & 0x0000FFFF; }
int clearlo(int z) { return z & 0xFFFF0000; }
int clearmid(int z) { return z & 0x00FFFF00; }
int clearwrap(int z) { return z & 0xFF0000FF; }

_andn4:
        rlwinm r3, r3, 0, 0, 29
        blr

_clearhi:
        rlwinm r3, r3, 0, 16, 31
        blr

_clearlo:
        rlwinm r3, r3, 0, 0, 15
        blr

_clearmid:
        rlwinm r3, r3, 0, 8, 23
        blr

_clearwrap:
        rlwinm r3, r3, 0, 24, 7
        blr

llvm-svn: 16832
This commit is contained in:
Nate Begeman 2004-10-08 02:49:24 +00:00
parent eb2d1b952b
commit dfefd2f3fc

View File

@ -32,7 +32,7 @@
using namespace llvm;
namespace {
Statistic<> ShiftedImm("ppc-codegen", "Number of shifted immediates used");
Statistic<> NumClear("ppc-codegen", "Number of AND turned into mask");
/// TypeClass - Used by the PowerPC backend to group LLVM types by their basic
/// PPC Representation.
@ -499,11 +499,10 @@ bool PPC32ISel::canUseAsImmediateForOpcode(ConstantInt *CI, unsigned Opcode,
// For shifted immediates, any value with the low halfword cleared may be used
if (Shifted) {
if (((int32_t)CI->getRawValue() & 0x0000FFFF) == 0) {
++ShiftedImm;
if (((int32_t)CI->getRawValue() & 0x0000FFFF) == 0)
return true;
}
return false;
else
return false;
}
// ADDI, Compare, and non-indexed Load take SIMM
@ -2038,6 +2037,61 @@ static unsigned ExactLog2(unsigned Val) {
return Count;
}
// isRunOfOnes - returns true if Val consists of one contiguous run of 1's with
// any number of 0's on either side. the 1's are allowed to wrap from LSB to
// MSB. so 0x000FFF0, 0x0000FFFF, and 0xFF0000FF are all runs. 0x0F0F0000 is
// not, since all 1's are not contiguous.
static bool isRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME) {
bool isRun = true;
MB = 0;
ME = 0;
// look for first set bit
int i = 0;
for (; i < 32; i++) {
if ((Val & (1 << (31 - i))) != 0) {
MB = i;
ME = i;
break;
}
}
// look for last set bit
for (; i < 32; i++) {
if ((Val & (1 << (31 - i))) == 0)
break;
ME = i;
}
// look for next set bit
for (; i < 32; i++) {
if ((Val & (1 << (31 - i))) != 0)
break;
}
// if we exhausted all the bits, we found a match at this point for 0*1*0*
if (i == 32)
return true;
// since we just encountered more 1's, if it doesn't wrap around to the
// most significant bit of the word, then we did not find a match to 1*0*1* so
// exit.
if (MB != 0)
return false;
// look for last set bit
for (MB = i; i < 32; i++) {
if ((Val & (1 << (31 - i))) == 0)
break;
}
// if we exhausted all the bits, then we found a match for 1*0*1*, otherwise,
// the value is not a run of ones.
if (i == 32)
return true;
return false;
}
/// emitBinaryConstOperation - Implement simple binary operators for integral
/// types with a constant operand. Opcode is one of: 0 for Add, 1 for Sub,
/// 2 for And, 3 for Or, 4 for Xor, and 5 for Subtract-From.
@ -2070,6 +2124,16 @@ void PPC32ISel::emitBinaryConstOperation(MachineBasicBlock *MBB,
return;
}
}
if (Opcode == 2) {
unsigned MB, ME, mask = CI->getRawValue();
if (isRunOfOnes(mask, MB, ME)) {
++NumClear;
BuildMI(*MBB, IP, PPC::RLWINM, 4, DestReg).addReg(Op0Reg).addImm(0)
.addImm(MB).addImm(ME);
return;
}
}
// For Add, Sub, and SubF the instruction takes a signed immediate. For And,
// Or, and Xor, the instruction takes an unsigned immediate. There is no