[llvm-commits] CVS: llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp PPCInstrInfo.td README.txt
Nate Begeman
natebegeman at mac.com
Thu Sep 21 22:02:11 PDT 2006
Changes in directory llvm/lib/Target/PowerPC:
PPCISelDAGToDAG.cpp updated: 1.210 -> 1.211
PPCInstrInfo.td updated: 1.241 -> 1.242
README.txt updated: 1.99 -> 1.100
---
Log message:
Fold AND and ROTL more often
---
Diffs of the changes: (+62 -62)
PPCISelDAGToDAG.cpp | 66 +++++++++++++++++++++++++++++-----------------------
PPCInstrInfo.td | 24 ++++++++++++++++++
README.txt | 34 --------------------------
3 files changed, 62 insertions(+), 62 deletions(-)
Index: llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
diff -u llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp:1.210 llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp:1.211
--- llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp:1.210 Tue Sep 19 23:33:27 2006
+++ llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp Fri Sep 22 00:01:56 2006
@@ -76,6 +76,17 @@
return CurDAG->getTargetConstant(Imm, PPCLowering.getPointerTy());
}
+ /// isRunOfOnes - Returns true iff Val consists of one contiguous run of 1s
+ /// with any number of 0s on either side. The 1s are allowed to wrap from
+ /// LSB to MSB, so 0x000FFF0, 0x0000FFFF, and 0xFF0000FF are all runs.
+ /// 0x0F0F0000 is not, since all 1s are not contiguous.
+ static bool isRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME);
+
+
+ /// isRotateAndMask - Returns true if Mask and Shift can be folded into a
+ /// rotate and mask opcode and mask operation.
+ static bool isRotateAndMask(SDNode *N, unsigned Mask, bool IsShiftMask,
+ unsigned &SH, unsigned &MB, unsigned &ME);
/// getGlobalBaseReg - insert code into the entry mbb to materialize the PIC
/// base register. Return the virtual register that holds this value.
@@ -324,12 +335,7 @@
return N->getOpcode() == Opc && isInt32Immediate(N->getOperand(1).Val, Imm);
}
-
-// isRunOfOnes - Returns true iff Val consists of one contiguous run of 1s with
-// any number of 0s on either side. The 1s are allowed to wrap from LSB to
-// MSB, so 0x000FFF0, 0x0000FFFF, and 0xFF0000FF are all runs. 0x0F0F0000 is
-// not, since all 1s are not contiguous.
-static bool isRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME) {
+bool PPCDAGToDAGISel::isRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME) {
if (isShiftedMask_32(Val)) {
// look for the first non-zero bit
MB = CountLeadingZeros_32(Val);
@@ -350,10 +356,9 @@
return false;
}
-// isRotateAndMask - Returns true if Mask and Shift can be folded into a rotate
-// and mask opcode and mask operation.
-static bool isRotateAndMask(SDNode *N, unsigned Mask, bool IsShiftMask,
- unsigned &SH, unsigned &MB, unsigned &ME) {
+bool PPCDAGToDAGISel::isRotateAndMask(SDNode *N, unsigned Mask,
+ bool IsShiftMask, unsigned &SH,
+ unsigned &MB, unsigned &ME) {
// Don't even go down this path for i64, since different logic will be
// necessary for rldicl/rldicr/rldimi.
if (N->getValueType(0) != MVT::i32)
@@ -378,6 +383,8 @@
Indeterminant = ~(0xFFFFFFFFu >> Shift);
// adjust for the left rotate
Shift = 32 - Shift;
+ } else if (Opcode == ISD::ROTL) {
+ Indeterminant = 0;
} else {
return false;
}
@@ -1024,30 +1031,33 @@
break;
}
case ISD::AND: {
- unsigned Imm, Imm2;
+ unsigned Imm, Imm2, SH, MB, ME;
+
// If this is an and of a value rotated between 0 and 31 bits and then and'd
// with a mask, emit rlwinm
if (isInt32Immediate(N->getOperand(1), Imm) &&
- (isShiftedMask_32(Imm) || isShiftedMask_32(~Imm))) {
- SDOperand Val;
- unsigned SH, MB, ME;
- if (isRotateAndMask(N->getOperand(0).Val, Imm, false, SH, MB, ME)) {
- Val = N->getOperand(0).getOperand(0);
- AddToISelQueue(Val);
- } else if (Imm == 0) {
- // AND X, 0 -> 0, not "rlwinm 32".
- AddToISelQueue(N->getOperand(1));
- ReplaceUses(SDOperand(N, 0), N->getOperand(1));
- return NULL;
- } else {
- Val = N->getOperand(0);
- AddToISelQueue(Val);
- isRunOfOnes(Imm, MB, ME);
- SH = 0;
- }
+ isRotateAndMask(N->getOperand(0).Val, Imm, false, SH, MB, ME)) {
+ SDOperand Val = N->getOperand(0).getOperand(0);
+ AddToISelQueue(Val);
SDOperand Ops[] = { Val, getI32Imm(SH), getI32Imm(MB), getI32Imm(ME) };
return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4);
}
+ // If this is just a masked value where the input is not handled above, and
+ // is not a rotate-left (handled by a pattern in the .td file), emit rlwinm
+ if (isInt32Immediate(N->getOperand(1), Imm) &&
+ isRunOfOnes(Imm, MB, ME) &&
+ N->getOperand(0).getOpcode() != ISD::ROTL) {
+ SDOperand Val = N->getOperand(0);
+ AddToISelQueue(Val);
+ SDOperand Ops[] = { Val, getI32Imm(0), getI32Imm(MB), getI32Imm(ME) };
+ return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4);
+ }
+ // AND X, 0 -> 0, not "rlwinm 32".
+ if (isInt32Immediate(N->getOperand(1), Imm) && (Imm == 0)) {
+ AddToISelQueue(N->getOperand(1));
+ ReplaceUses(SDOperand(N, 0), N->getOperand(1));
+ return NULL;
+ }
// ISD::OR doesn't get all the bitfield insertion fun.
// (and (or x, c1), c2) where isRunOfOnes(~(c1^c2)) is a bitfield insert
if (isInt32Immediate(N->getOperand(1), Imm) &&
Index: llvm/lib/Target/PowerPC/PPCInstrInfo.td
diff -u llvm/lib/Target/PowerPC/PPCInstrInfo.td:1.241 llvm/lib/Target/PowerPC/PPCInstrInfo.td:1.242
--- llvm/lib/Target/PowerPC/PPCInstrInfo.td:1.241 Fri Aug 11 04:02:24 2006
+++ llvm/lib/Target/PowerPC/PPCInstrInfo.td Fri Sep 22 00:01:56 2006
@@ -129,7 +129,27 @@
signed int Val = N->getValue();
return getI32Imm((Val - (signed short)Val) >> 16);
}]>;
+def MB : SDNodeXForm<imm, [{
+ // Transformation function: get the start bit of a mask
+ unsigned mb, me;
+ (void)isRunOfOnes((unsigned)N->getValue(), mb, me);
+ return getI32Imm(mb);
+}]>;
+def ME : SDNodeXForm<imm, [{
+ // Transformation function: get the end bit of a mask
+ unsigned mb, me;
+ (void)isRunOfOnes((unsigned)N->getValue(), mb, me);
+ return getI32Imm(me);
+}]>;
+def maskimm32 : PatLeaf<(imm), [{
+ // maskImm predicate - True if immediate is a run of ones.
+ unsigned mb, me;
+ if (N->getValueType(0) == MVT::i32)
+ return isRunOfOnes((unsigned)N->getValue(), mb, me);
+ else
+ return false;
+}]>;
def immSExt16 : PatLeaf<(imm), [{
// immSExt16 predicate - True if the immediate fits in a 16-bit sign extended
@@ -923,6 +943,10 @@
def : Pat<(rotl GPRC:$in, (i32 imm:$imm)),
(RLWINM GPRC:$in, imm:$imm, 0, 31)>;
+// RLWNM
+def : Pat<(and (rotl GPRC:$in, GPRC:$sh), maskimm32:$imm),
+ (RLWNM GPRC:$in, GPRC:$sh, (MB maskimm32:$imm), (ME maskimm32:$imm))>;
+
// Calls
def : Pat<(PPCcall tglobaladdr:$dst),
(BL tglobaladdr:$dst)>;
Index: llvm/lib/Target/PowerPC/README.txt
diff -u llvm/lib/Target/PowerPC/README.txt:1.99 llvm/lib/Target/PowerPC/README.txt:1.100
--- llvm/lib/Target/PowerPC/README.txt:1.99 Wed Sep 20 01:41:56 2006
+++ llvm/lib/Target/PowerPC/README.txt Fri Sep 22 00:01:56 2006
@@ -6,40 +6,6 @@
===-------------------------------------------------------------------------===
-We only produce the rlwnm instruction for rotate instructions. We should
-at least match stuff like:
-
-unsigned rot_and(unsigned X, int Y) {
- unsigned T = (X << Y) | (X >> (32-Y));
- T &= 127;
- return T;
-}
-
-_foo3:
- rlwnm r2, r3, r4, 0, 31
- rlwinm r3, r2, 0, 25, 31
- blr
-
-... which is the basic pattern that should be written in the instr. It may
-also be useful for stuff like:
-
-long long foo2(long long X, int C) {
- return X << (C&~32);
-}
-
-which currently produces:
-
-_foo2:
- rlwinm r2, r5, 0, 27, 25
- subfic r5, r2, 32
- slw r3, r3, r2
- srw r5, r4, r5
- or r3, r3, r5
- slw r4, r4, r2
- blr
-
-===-------------------------------------------------------------------------===
-
Support 'update' load/store instructions. These are cracked on the G5, but are
still a codesize win.
More information about the llvm-commits
mailing list