aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorNate Begeman <natebegeman@mac.com>2004-10-08 02:49:24 +0000
committerNate Begeman <natebegeman@mac.com>2004-10-08 02:49:24 +0000
commitbdf69847a9448dc64c6aae9abacf65822af016eb (patch)
tree6b6356c078792a82f566f7559bf32af40f451129 /lib
parentef7dd4637bb73e3d9b3c2fc61eee23ff67c6d77d (diff)
downloadexternal_llvm-bdf69847a9448dc64c6aae9abacf65822af016eb.zip
external_llvm-bdf69847a9448dc64c6aae9abacf65822af016eb.tar.gz
external_llvm-bdf69847a9448dc64c6aae9abacf65822af016eb.tar.bz2
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')
-rw-r--r--lib/Target/PowerPC/PPC32ISelSimple.cpp74
1 files changed, 69 insertions, 5 deletions
diff --git a/lib/Target/PowerPC/PPC32ISelSimple.cpp b/lib/Target/PowerPC/PPC32ISelSimple.cpp
index e22da0f..890ccb9 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