diff options
Diffstat (limited to 'llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp')
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 4d9abdc9a7f..47f73abebf2 100644 --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -927,7 +927,7 @@ SDOperand PPCDAGToDAGISel::Select(SDOperand Op) { break; } case ISD::AND: { - unsigned Imm; + unsigned Imm, Imm2; // If this is an and of a value rotated between 0 and 31 bits and then and'd // with a mask, emit rlwinm if (isIntImmediate(N->getOperand(1), Imm) && (isShiftedMask_32(Imm) || @@ -947,6 +947,20 @@ SDOperand PPCDAGToDAGISel::Select(SDOperand Op) { return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Val, getI32Imm(SH), getI32Imm(MB), getI32Imm(ME)); } + // ISD::OR doesn't get all the bitfield insertion fun. + // (and (or x, c1), c2) where isRunOfOnes(~(c1^c2)) is a bitfield insert + if (isIntImmediate(N->getOperand(1), Imm) && + N->getOperand(0).getOpcode() == ISD::OR && + isIntImmediate(N->getOperand(0).getOperand(1), Imm2)) { + unsigned SH, MB, ME; + Imm = ~(Imm^Imm2); + if (isRunOfOnes(Imm, MB, ME)) { + SDOperand Tmp1 = Select(N->getOperand(0).getOperand(0)); + SDOperand Tmp2 = Select(N->getOperand(0).getOperand(1)); + return CurDAG->getTargetNode(PPC::RLWIMI, MVT::i32, Tmp1, Tmp2, + getI32Imm(SH), getI32Imm(MB), getI32Imm(ME)); + } + } // Other cases are autogenerated. break; |

