Index: llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -4546,6 +4546,54 @@ CurDAG->SelectNodeTo(N, PPC::RLWINM8, MVT::i64, Ops); return true; } + + if (ME == 63) { + // If the number of trailing zeros is zero, we can optimize it with two + // rldicl. + // MB MB2 ME2 ME MB MB2 ME2 ME + // +----------------------+ +----------------------+ + // |1111111111111111111111| -> |0000001111111111111111+ + // +----------------------+ +----------------------+ + // 0 32 64 0 32 64 + // Rotate left MB2 + 1 bits and then, clear the bits (MB2, ME2) + Val = SDValue( + CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, + { Val, getI64Imm(MB2 + 1, dl), + getI64Imm(ME2 - MB2 - 1, dl) }), 0); + // MB MB2 ME2 ME MB MB2 ME2 ME + // +----------------------+ +----------------------+ + // |0000001111111111111111| -> |0001111100000011111111+ + // +----------------------+ +----------------------+ + // 0 32 64 0 32 64 + // Rotate back and then, clear the bits [0, MB) + SDValue Ops[] = { Val, getI64Imm(63 - MB2, dl), getI64Imm(MB, dl) }; + CurDAG->SelectNodeTo(N, PPC::RLDICL, MVT::i64, Ops); + return true; + } + + if (MB == 0) { + // If the number of leading zeros is zero, we can optimize it with + // rldicl + rldicr. + // MB MB2 ME2 ME MB MB2 ME2 ME + // +----------------------+ +----------------------+ + // |1111111111111111111111| -> |0000001111111111111111+ + // +----------------------+ +----------------------+ + // 0 32 64 0 32 64 + // Rotate left MB2 + 1 bits and then, clear the bits (MB2, ME2) + Val = SDValue( + CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, + { Val, getI64Imm(MB2 + 1, dl), + getI64Imm(ME2 - MB2 - 1, dl) }), 0); + // MB MB2 ME2 ME MB MB2 ME2 ME + // +----------------------+ +----------------------+ + // |0000001111111111111111| -> |1111100000011111111000+ + // +----------------------+ +----------------------+ + // 0 32 64 0 32 64 + // Rotate back and then, clear the bits (ME, 63] + SDValue Ops[] = { Val, getI64Imm(63 - MB2, dl), getI64Imm(ME, dl) }; + CurDAG->SelectNodeTo(N, PPC::RLDICR, 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 @@ -37,10 +37,8 @@ define i64 @test4(i64 %a) { ; CHECK-LABEL: test4: ; CHECK: # %bb.0: -; CHECK-NEXT: li 4, 12 -; CHECK-NEXT: sldi 4, 4, 32 -; CHECK-NEXT: ori 4, 4, 255 -; CHECK-NEXT: and 3, 3, 4 +; CHECK-NEXT: rldicl 3, 3, 30, 26 +; CHECK-NEXT: rldicl 3, 3, 34, 28 ; CHECK-NEXT: blr %and = and i64 %a, 51539607807 ret i64 %and @@ -72,12 +70,20 @@ define i64 @test7(i64 %a) { ; CHECK-LABEL: test7: ; CHECK: # %bb.0: -; CHECK-NEXT: li 4, -32767 -; CHECK-NEXT: sldi 4, 4, 32 -; CHECK-NEXT: oris 4, 4, 65024 -; CHECK-NEXT: rldicr 4, 4, 17, 63 -; CHECK-NEXT: and 3, 3, 4 +; CHECK-NEXT: rldicl 3, 3, 22, 25 +; CHECK-NEXT: rldicl 3, 3, 42, 14 ; CHECK-NEXT: blr %and = and i64 %a, 1121501860462591 ret i64 %and } + +; mask: 0xFFC0000000007800 +define i64 @test8(i64 %a) { +; CHECK-LABEL: test8: +; CHECK: # %bb.0: +; CHECK-NEXT: rldicl 3, 3, 10, 39 +; CHECK-NEXT: rldicr 3, 3, 54, 52 +; CHECK-NEXT: blr + %and = and i64 %a, 18428729675200100352 + ret i64 %and +}