summaryrefslogtreecommitdiff
path: root/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
diff options
context:
space:
mode:
authorNate Begeman <natebegeman@mac.com>2006-05-07 00:23:38 +0000
committerNate Begeman <natebegeman@mac.com>2006-05-07 00:23:38 +0000
commit77f361f5b3ac6ed080d6b0f401b62cd6e08614e5 (patch)
treebdc77ee993c1086ed0e366c32e3e55aec800a295 /lib/Target/PowerPC/PPCISelDAGToDAG.cpp
parent822db93e57f9b8800268e8ba7b2cbc1234bc265c (diff)
downloadllvm-77f361f5b3ac6ed080d6b0f401b62cd6e08614e5.tar.gz
llvm-77f361f5b3ac6ed080d6b0f401b62cd6e08614e5.tar.bz2
llvm-77f361f5b3ac6ed080d6b0f401b62cd6e08614e5.tar.xz
New rlwimi implementation, which is superior to the old one. There are
still a couple missed optimizations, but we now generate all the possible rlwimis for multiple inserts into the same bitfield. More regression tests to come. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28156 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/PowerPC/PPCISelDAGToDAG.cpp')
-rw-r--r--lib/Target/PowerPC/PPCISelDAGToDAG.cpp131
1 files changed, 45 insertions, 86 deletions
diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index 10f074f6ef..26f1316899 100644
--- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -391,15 +391,7 @@ static bool isIntImmediate(SDOperand N, unsigned& Imm) {
/// SelectBitfieldInsert - turn an or of two masked values into
/// the rotate left word immediate then mask insert (rlwimi) instruction.
-/// Returns true on success, false if the caller still needs to select OR.
-///
-/// Patterns matched:
-/// 1. or shl, and 5. or and, and
-/// 2. or and, shl 6. or shl, shr
-/// 3. or shr, and 7. or shr, shl
-/// 4. or and, shr
SDNode *PPCDAGToDAGISel::SelectBitfieldInsert(SDNode *N) {
- bool IsRotate = false;
unsigned TgtMask = 0xFFFFFFFF, InsMask = 0xFFFFFFFF, SH = 0;
unsigned Value;
@@ -409,90 +401,57 @@ SDNode *PPCDAGToDAGISel::SelectBitfieldInsert(SDNode *N) {
unsigned Op0Opc = Op0.getOpcode();
unsigned Op1Opc = Op1.getOpcode();
- // Verify that we have the correct opcodes
- if (ISD::SHL != Op0Opc && ISD::SRL != Op0Opc && ISD::AND != Op0Opc)
- return false;
- if (ISD::SHL != Op1Opc && ISD::SRL != Op1Opc && ISD::AND != Op1Opc)
- return false;
+ uint64_t LKZ, LKO, RKZ, RKO;
+ TLI.ComputeMaskedBits(Op0, TgtMask, LKZ, LKO);
+ TLI.ComputeMaskedBits(Op1, TgtMask, RKZ, RKO);
- // Generate Mask value for Target
- if (isIntImmediate(Op0.getOperand(1), Value)) {
- switch(Op0Opc) {
- case ISD::SHL: TgtMask <<= Value; break;
- case ISD::SRL: TgtMask >>= Value; break;
- case ISD::AND: TgtMask &= Value; break;
+ // FIXME: rotrwi / rotlwi
+ if ((LKZ | RKZ) == 0x00000000FFFFFFFFULL) {
+ unsigned PInsMask = ~RKZ;
+ unsigned PTgtMask = ~LKZ;
+
+ // If the LHS has a foldable shift, then swap it to the RHS so that we can
+ // fold the shift into the insert.
+ if (Op0Opc == ISD::AND && Op1Opc == ISD::AND) {
+ if (Op0.getOperand(0).getOpcode() == ISD::SHL ||
+ Op0.getOperand(0).getOpcode() == ISD::SRL) {
+ if (Op1.getOperand(0).getOpcode() != ISD::SHL &&
+ Op1.getOperand(0).getOpcode() != ISD::SRL) {
+ std::swap(Op0, Op1);
+ std::swap(Op0Opc, Op1Opc);
+ std::swap(PInsMask, PTgtMask);
+ }
+ }
}
- } else {
- return 0;
- }
-
- // Generate Mask value for Insert
- if (!isIntImmediate(Op1.getOperand(1), Value))
- return 0;
-
- switch(Op1Opc) {
- case ISD::SHL:
- SH = Value;
- InsMask <<= SH;
- if (Op0Opc == ISD::SRL) IsRotate = true;
- break;
- case ISD::SRL:
- SH = Value;
- InsMask >>= SH;
- SH = 32-SH;
- if (Op0Opc == ISD::SHL) IsRotate = true;
- break;
- case ISD::AND:
- InsMask &= Value;
- break;
- }
-
- // If both of the inputs are ANDs and one of them has a logical shift by
- // constant as its input, make that AND the inserted value so that we can
- // combine the shift into the rotate part of the rlwimi instruction
- bool IsAndWithShiftOp = false;
- if (Op0Opc == ISD::AND && Op1Opc == ISD::AND) {
- if (Op1.getOperand(0).getOpcode() == ISD::SHL ||
- Op1.getOperand(0).getOpcode() == ISD::SRL) {
- if (isIntImmediate(Op1.getOperand(0).getOperand(1), Value)) {
- SH = Op1.getOperand(0).getOpcode() == ISD::SHL ? Value : 32 - Value;
- IsAndWithShiftOp = true;
+
+ unsigned MB, ME;
+ if (isRunOfOnes(PInsMask, MB, ME)) {
+ SDOperand Tmp1, Tmp2, Tmp3;
+ bool DisjointMask = (PTgtMask ^ PInsMask) == 0xFFFFFFFF;
+
+ if ((Op1Opc == ISD::SHL || Op1Opc == ISD::SRL) &&
+ isIntImmediate(Op1.getOperand(1), Value)) {
+ Op1 = Op1.getOperand(0);
+ SH = (Op1Opc == ISD::SHL) ? Value : 32 - Value;
}
- } else if (Op0.getOperand(0).getOpcode() == ISD::SHL ||
- Op0.getOperand(0).getOpcode() == ISD::SRL) {
- if (isIntImmediate(Op0.getOperand(0).getOperand(1), Value)) {
- std::swap(Op0, Op1);
- std::swap(TgtMask, InsMask);
- SH = Op1.getOperand(0).getOpcode() == ISD::SHL ? Value : 32 - Value;
- IsAndWithShiftOp = true;
+ if (Op1Opc == ISD::AND) {
+ unsigned SHOpc = Op1.getOperand(0).getOpcode();
+ if ((SHOpc == ISD::SHL || SHOpc == ISD::SRL) &&
+ isIntImmediate(Op1.getOperand(0).getOperand(1), Value)) {
+ Op1 = Op1.getOperand(0).getOperand(0);
+ SH = (SHOpc == ISD::SHL) ? Value : 32 - Value;
+ } else {
+ Op1 = Op1.getOperand(0);
+ }
}
+
+ Tmp3 = (Op0Opc == ISD::AND && DisjointMask) ? Op0.getOperand(0) : Op0;
+ Select(Tmp1, Tmp3);
+ Select(Tmp2, Op1);
+ return CurDAG->getTargetNode(PPC::RLWIMI, MVT::i32, Tmp1, Tmp2,
+ getI32Imm(SH), getI32Imm(MB), getI32Imm(ME));
}
}
-
- // Verify that the Target mask and Insert mask together form a full word mask
- // and that the Insert mask is a run of set bits (which implies both are runs
- // of set bits). Given that, Select the arguments and generate the rlwimi
- // instruction.
- unsigned MB, ME;
- if (((TgtMask & InsMask) == 0) && isRunOfOnes(InsMask, MB, ME)) {
- bool fullMask = (TgtMask ^ InsMask) == 0xFFFFFFFF;
- bool Op0IsAND = Op0Opc == ISD::AND;
- // Check for rotlwi / rotrwi here, a special case of bitfield insert
- // where both bitfield halves are sourced from the same value.
- if (IsRotate && fullMask &&
- N->getOperand(0).getOperand(0) == N->getOperand(1).getOperand(0)) {
- SDOperand Tmp;
- Select(Tmp, N->getOperand(0).getOperand(0));
- return CurDAG->getTargetNode(PPC::RLWINM, MVT::i32, Tmp,
- getI32Imm(SH), getI32Imm(0), getI32Imm(31));
- }
- SDOperand Tmp1, Tmp2;
- Select(Tmp1, ((Op0IsAND && fullMask) ? Op0.getOperand(0) : Op0));
- Select(Tmp2, (IsAndWithShiftOp ? Op1.getOperand(0).getOperand(0)
- : Op1.getOperand(0)));
- return CurDAG->getTargetNode(PPC::RLWIMI, MVT::i32, Tmp1, Tmp2,
- getI32Imm(SH), getI32Imm(MB), getI32Imm(ME));
- }
return 0;
}