[llvm] c12722c - [PowerPC] Exploit RLDIMI for OR with large immediates

Qiu Chaofan via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 21 23:19:02 PDT 2020


Author: Qiu Chaofan
Date: 2020-04-22T14:16:52+08:00
New Revision: c12722cde83212581d14a6fdd6a52ebed04ac4df

URL: https://github.com/llvm/llvm-project/commit/c12722cde83212581d14a6fdd6a52ebed04ac4df
DIFF: https://github.com/llvm/llvm-project/commit/c12722cde83212581d14a6fdd6a52ebed04ac4df.diff

LOG: [PowerPC] Exploit RLDIMI for OR with large immediates

This patch exploits rldimi instruction for patterns like
`or %a, 0b000011110000`, which saves number of instructions when the
operand has only one use, compared with `li-ori-sldi-or`.

Reviewed By: nemanjai

Differential Revision: https://reviews.llvm.org/D77850

Added: 
    

Modified: 
    llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
    llvm/test/CodeGen/PowerPC/ori_imm32.ll
    llvm/test/CodeGen/PowerPC/ori_imm64.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index dd6d9249ab4d..8a5603dc274a 100644
--- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -352,6 +352,7 @@ namespace {
     bool tryAsSingleRLWINM8(SDNode *N);
     bool tryAsSingleRLWIMI(SDNode *N);
     bool tryAsPairOfRLDICL(SDNode *N);
+    bool tryAsSingleRLDIMI(SDNode *N);
 
     void PeepholePPC64();
     void PeepholePPC64ZExt();
@@ -4597,6 +4598,31 @@ bool PPCDAGToDAGISel::tryAsSingleRLDICR(SDNode *N) {
   return true;
 }
 
+bool PPCDAGToDAGISel::tryAsSingleRLDIMI(SDNode *N) {
+  assert(N->getOpcode() == ISD::OR && "ISD::OR SDNode expected");
+  uint64_t Imm64;
+  unsigned MB, ME;
+  SDValue N0 = N->getOperand(0);
+
+  // We won't get fewer instructions if the imm is 32-bit integer.
+  // rldimi requires the imm to have consecutive ones with both sides zero.
+  // Also, make sure the first Op has only one use, otherwise this may increase
+  // register pressure since rldimi is destructive.
+  if (!isInt64Immediate(N->getOperand(1).getNode(), Imm64) ||
+      isUInt<32>(Imm64) || !isRunOfOnes64(Imm64, MB, ME) || !N0.hasOneUse())
+    return false;
+
+  unsigned SH = 63 - ME;
+  SDLoc Dl(N);
+  // Use select64Imm for making LI instr instead of directly putting Imm64
+  SDValue Ops[] = {
+      N->getOperand(0),
+      SDValue(selectI64Imm(CurDAG, getI64Imm(-1, Dl).getNode()), 0),
+      getI32Imm(SH, Dl), getI32Imm(MB, Dl)};
+  CurDAG->SelectNodeTo(N, PPC::RLDIMI, MVT::i64, Ops);
+  return true;
+}
+
 // Select - Convert the specified operand from a target-independent to a
 // target-specific node if it hasn't already been changed.
 void PPCDAGToDAGISel::Select(SDNode *N) {
@@ -4844,6 +4870,11 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
       }
     }
 
+    // If this is 'or' against an imm with consecutive ones and both sides zero,
+    // try to emit rldimi
+    if (tryAsSingleRLDIMI(N))
+      return;
+
     // OR with a 32-bit immediate can be handled by ori + oris
     // without creating an immediate in a GPR.
     uint64_t Imm64 = 0;

diff  --git a/llvm/test/CodeGen/PowerPC/ori_imm32.ll b/llvm/test/CodeGen/PowerPC/ori_imm32.ll
index 245c9bdbce77..3077c4e0fe35 100644
--- a/llvm/test/CodeGen/PowerPC/ori_imm32.ll
+++ b/llvm/test/CodeGen/PowerPC/ori_imm32.ll
@@ -16,9 +16,8 @@ entry:
 define i64 @ori_test_b(i64 %a) {
 ; CHECK-LABEL: ori_test_b:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    li 4, 1
-; CHECK-NEXT:    sldi 4, 4, 32
-; CHECK-NEXT:    or 3, 3, 4
+; CHECK-NEXT:    li 4, -1
+; CHECK-NEXT:    rldimi 3, 4, 32, 31
 ; CHECK-NEXT:    blr
 entry:
   %or = or i64 %a, 4294967296

diff  --git a/llvm/test/CodeGen/PowerPC/ori_imm64.ll b/llvm/test/CodeGen/PowerPC/ori_imm64.ll
index d2ea911c6f14..b1bb42e3f805 100644
--- a/llvm/test/CodeGen/PowerPC/ori_imm64.ll
+++ b/llvm/test/CodeGen/PowerPC/ori_imm64.ll
@@ -15,10 +15,8 @@ entry:
 define i64 @ori_test_2(i64 %a) {
 ; CHECK-LABEL: ori_test_2:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    lis 4, 15
-; CHECK-NEXT:    ori 4, 4, 65535
-; CHECK-NEXT:    sldi 4, 4, 29
-; CHECK-NEXT:    or 3, 3, 4
+; CHECK-NEXT:    li 4, -1
+; CHECK-NEXT:    rldimi 3, 4, 29, 15
 ; CHECK-NEXT:    blr
 entry:
   %or = or i64 %a, 562949416550400 ; 0x1ffffe0000000
@@ -28,9 +26,8 @@ entry:
 define i64 @ori_test_3(i64 %a) {
 ; CHECK-LABEL: ori_test_3:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    lis 4, -32768
-; CHECK-NEXT:    rldicr 4, 4, 36, 63
-; CHECK-NEXT:    or 3, 3, 4
+; CHECK-NEXT:    li 4, -1
+; CHECK-NEXT:    rldimi 3, 4, 3, 28
 ; CHECK-NEXT:    blr
 entry:
   %or = or i64 %a, 68719476728 ; 0xffffffff8
@@ -50,3 +47,20 @@ entry:
   %or = or i64 %a, 17661175070719 ; 0x10101010ffff
   ret i64 %or
 }
+
+; Don't exploit rldimi if operand has multiple uses
+define i64 @test_test_5(i64 %a, i64 %b) {
+; CHECK-LABEL: test_test_5:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    li 5, 1
+; CHECK-NEXT:    sldi 5, 5, 32
+; CHECK-NEXT:    or 5, 3, 5
+; CHECK-NEXT:    add 4, 5, 4
+; CHECK-NEXT:    sub 3, 3, 4
+; CHECK-NEXT:    blr
+entry:
+  %or = or i64 %a, 4294967296
+  %add = add i64 %or, %b
+  %div = sub i64 %a, %add
+  ret i64 %div
+}


        


More information about the llvm-commits mailing list