diff options
author | Nate Begeman <natebegeman@mac.com> | 2004-10-08 02:49:24 +0000 |
---|---|---|
committer | Nate Begeman <natebegeman@mac.com> | 2004-10-08 02:49:24 +0000 |
commit | bdf69847a9448dc64c6aae9abacf65822af016eb (patch) | |
tree | 6b6356c078792a82f566f7559bf32af40f451129 /lib/Target/PowerPC/PPC32ISelSimple.cpp | |
parent | ef7dd4637bb73e3d9b3c2fc61eee23ff67c6d77d (diff) |
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
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16832 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/PowerPC/PPC32ISelSimple.cpp')
-rw-r--r-- | lib/Target/PowerPC/PPC32ISelSimple.cpp | 74 |
1 files changed, 69 insertions, 5 deletions
diff --git a/lib/Target/PowerPC/PPC32ISelSimple.cpp b/lib/Target/PowerPC/PPC32ISelSimple.cpp index e22da0fa2e..890ccb95dc 100644 --- a/lib/Target/PowerPC/PPC32ISelSimple.cpp +++ b/lib/Target/PowerPC/PPC32ISelSimple.cpp @@ -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 |