Index: llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -4496,6 +4496,56 @@ CurDAG->SelectNodeTo(N, PPC::RLDICL, MVT::i64, Ops); return true; } + + // Do nothing if it is 16-bit imm as the pattern in the .td file handle + // it well with "andi.". + if (isUInt<16>(Imm64)) + return false; + + // We can do special handling for pattern like this. + // MB MB2 ME2 ME + // +----------------------+ + // |0001111100000011111000| + // +----------------------+ + MB = countLeadingZeros(Imm64); + ME = 63 - countTrailingZeros(Imm64); + // Get the invert mask of [MB, ME]. + uint64_t InvertMask = ~Imm64 & + APInt::getBitsSet(64, 63 - ME, 64 - MB).getZExtValue(); + unsigned MB2, ME2; + if (!isRunOfOnes64(InvertMask, MB2, ME2)) + return false; + // Correct the MB2 and ME2 to be the position of last '1' of the first ones, + // and the position of first '1' of the second ones. + MB2--; + ME2++; + assert(MB2 <= ME2 && "Invalid MB and ME"); + + if (MB >= 32) { + // If it is within [32, 64), we can optimize it with two rlwinm. + // MB MB2 ME2 ME MB MB2 ME2 ME + // +----------------------+ +----------------------+ + // |1111111111111111111111| -> |1111111100000011111111+ + // +----------------------+ +----------------------+ + // 0 32 64 0 32 64 + // Clear the bit (MB2, ME2) first. It is a warpping mask. + // RLWINM 0, ME2, MB2 + Val = SDValue(CurDAG->getMachineNode(PPC::RLWINM8, dl, MVT::i64, + { Val, getI64Imm(0, dl), + getI64Imm(ME2 - 32, dl), + getI64Imm(MB2 - 32, dl) }), 0); + // MB MB2 ME2 ME MB MB2 ME2 ME + // +----------------------+ +----------------------+ + // |1111111100000011111111| -> |0001111100000011111000+ + // +----------------------+ +----------------------+ + // 0 32 64 0 32 64 + // Clear the bit (ME, MB). Notice that, as RLWINM will update the bit + // [0, 31], we can only do this optimization if MB >= 32. + SDValue Ops[] = { Val, getI64Imm(0, dl), getI64Imm(MB - 32, dl), + getI64Imm(ME - 32, dl) }; + CurDAG->SelectNodeTo(N, PPC::RLWINM8, MVT::i64, Ops); + return true; + } } return false; Index: llvm/test/CodeGen/PowerPC/and-mask.ll =================================================================== --- llvm/test/CodeGen/PowerPC/and-mask.ll +++ llvm/test/CodeGen/PowerPC/and-mask.ll @@ -50,10 +50,8 @@ define i64 @test5(i64 %a) { ; CHECK-LABEL: test5: ; CHECK: # %bb.0: -; CHECK-NEXT: li 4, 0 -; CHECK-NEXT: oris 4, 4, 65472 -; CHECK-NEXT: ori 4, 4, 65535 -; CHECK-NEXT: and 3, 3, 4 +; CHECK-NEXT: rlwinm 3, 3, 0, 16, 9 +; CHECK-NEXT: rlwinm 3, 3, 0, 0, 31 ; CHECK-NEXT: blr %and = and i64 %a, 4290838527 ret i64 %and @@ -63,9 +61,8 @@ define i64 @test6(i64 %a) { ; CHECK-LABEL: test6: ; CHECK: # %bb.0: -; CHECK-NEXT: lis 4, 16320 -; CHECK-NEXT: ori 4, 4, 65504 -; CHECK-NEXT: and 3, 3, 4 +; CHECK-NEXT: rlwinm 3, 3, 0, 16, 9 +; CHECK-NEXT: rlwinm 3, 3, 0, 2, 26 ; CHECK-NEXT: blr %and = and i64 %a, 1069613024 ret i64 %and Index: llvm/test/CodeGen/PowerPC/cmpb.ll =================================================================== --- llvm/test/CodeGen/PowerPC/cmpb.ll +++ llvm/test/CodeGen/PowerPC/cmpb.ll @@ -123,11 +123,9 @@ ret i32 %or55 ; CHECK-LABEL: @test32p1 -; CHECK: li [[REG1:[0-9]+]], 0 -; CHECK: cmpb [[REG4:[0-9]+]], 4, 3 -; CHECK: oris [[REG2:[0-9]+]], [[REG1]], 65287 -; CHECK: ori [[REG3:[0-9]+]], [[REG2]], 65535 -; CHECK: and 3, [[REG4]], [[REG3]] +; CHECK: cmpb [[REG1:[0-9]+]], 4, 3 +; CHECK: rlwinm [[REG2:[0-9]+]], [[REG1]], 0, 13, 7 +; CHECK: rlwinm 3, [[REG2]], 0, 0, 31 ; CHECK: blr } @@ -147,11 +145,9 @@ ret i32 %or37 ; CHECK-LABEL: @test32p2 -; CHECK: li [[REG1:[0-9]+]], 0 -; CHECK: cmpb [[REG4:[0-9]+]], 4, 3 -; CHECK: oris [[REG2:[0-9]+]], [[REG1]], 65280 -; CHECK: ori [[REG3:[0-9]+]], [[REG2]], 65535 -; CHECK: and 3, [[REG4]], [[REG3]] +; CHECK: cmpb [[REG1:[0-9]+]], 4, 3 +; CHECK: rlwinm [[REG2:[0-9]+]], [[REG1]], 0, 16, 7 +; CHECK: rlwinm 3, [[REG2]], 0, 0, 31 ; CHECK: blr }