[llvm] r225147 - [PowerPC] Materialize i64 constants using rotation with masking

Hal Finkel hfinkel at anl.gov
Sun Jan 4 19:41:38 PST 2015


Author: hfinkel
Date: Sun Jan  4 21:41:38 2015
New Revision: 225147

URL: http://llvm.org/viewvc/llvm-project?rev=225147&view=rev
Log:
[PowerPC] Materialize i64 constants using rotation with masking

r225135 added the ability to materialize i64 constants using rotations in order
to reduce the instruction count. Sometimes we can use a rotation only with some
extra masking, so that we take advantage of the fact that generating a bunch of
extra higher-order 1 bits is easy using li/lis.

Modified:
    llvm/trunk/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
    llvm/trunk/lib/Target/PowerPC/README.txt
    llvm/trunk/test/CodeGen/PowerPC/constants-i64.ll

Modified: llvm/trunk/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelDAGToDAG.cpp?rev=225147&r1=225146&r2=225147&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCISelDAGToDAG.cpp Sun Jan  4 21:41:38 2015
@@ -608,9 +608,23 @@ static uint64_t Rot64(uint64_t Imm, unsi
 
 static unsigned SelectInt64Count(int64_t Imm) {
   unsigned Count = SelectInt64CountDirect(Imm);
+  if (Count == 1)
+    return Count;
 
   for (unsigned r = 1; r < 63; ++r) {
-    unsigned RCount = SelectInt64CountDirect(Rot64(Imm, r)) + 1;
+    uint64_t RImm = Rot64(Imm, r);
+    unsigned RCount = SelectInt64CountDirect(RImm) + 1;
+    Count = std::min(Count, RCount);
+
+    // See comments in SelectInt64 for an explanation of the logic below.
+    unsigned LS = findLastSet(RImm);
+    if (LS != r-1)
+      continue;
+
+    uint64_t OnesMask = -(int64_t) (UINT64_C(1) << (LS+1));
+    uint64_t RImmWithOnes = RImm | OnesMask;
+
+    RCount = SelectInt64CountDirect(RImmWithOnes) + 1;
     Count = std::min(Count, RCount);
   }
 
@@ -695,13 +709,45 @@ static SDNode *SelectInt64Direct(Selecti
 
 static SDNode *SelectInt64(SelectionDAG *CurDAG, SDLoc dl, int64_t Imm) {
   unsigned Count = SelectInt64CountDirect(Imm);
+  if (Count == 1)
+    return SelectInt64Direct(CurDAG, dl, Imm);
+
   unsigned RMin = 0;
 
+  int64_t MatImm;
+  unsigned MaskEnd;
+
   for (unsigned r = 1; r < 63; ++r) {
-    unsigned RCount = SelectInt64CountDirect(Rot64(Imm, r)) + 1;
+    uint64_t RImm = Rot64(Imm, r);
+    unsigned RCount = SelectInt64CountDirect(RImm) + 1;
+    if (RCount < Count) {
+      Count = RCount;
+      RMin = r;
+      MatImm = RImm;
+      MaskEnd = 63;
+    }
+
+    // If the immediate to generate has many trailing zeros, it might be
+    // worthwhile to generate a rotated value with too many leading ones
+    // (because that's free with li/lis's sign-extension semantics), and then
+    // mask them off after rotation.
+
+    unsigned LS = findLastSet(RImm);
+    // We're adding (63-LS) higher-order ones, and we expect to mask them off
+    // after performing the inverse rotation by (64-r). So we need that:
+    //   63-LS == 64-r => LS == r-1
+    if (LS != r-1)
+      continue;
+
+    uint64_t OnesMask = -(int64_t) (UINT64_C(1) << (LS+1));
+    uint64_t RImmWithOnes = RImm | OnesMask;
+
+    RCount = SelectInt64CountDirect(RImmWithOnes) + 1;
     if (RCount < Count) {
       Count = RCount;
       RMin = r;
+      MatImm = RImmWithOnes;
+      MaskEnd = LS;
     }
   }
 
@@ -712,9 +758,9 @@ static SDNode *SelectInt64(SelectionDAG
       return CurDAG->getTargetConstant(Imm, MVT::i32);
   };
 
-  SDValue Val = SDValue(SelectInt64Direct(CurDAG, dl, Rot64(Imm, RMin)), 0);
-  return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, Val,
-                                getI32Imm(64 - RMin), getI32Imm(0));
+  SDValue Val = SDValue(SelectInt64Direct(CurDAG, dl, MatImm), 0);
+  return CurDAG->getMachineNode(PPC::RLDICR, dl, MVT::i64, Val,
+                                getI32Imm(64 - RMin), getI32Imm(MaskEnd));
 }
 
 // Select a 64-bit constant.

Modified: llvm/trunk/lib/Target/PowerPC/README.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/README.txt?rev=225147&r1=225146&r2=225147&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/README.txt (original)
+++ llvm/trunk/lib/Target/PowerPC/README.txt Sun Jan  4 21:41:38 2015
@@ -5,27 +5,6 @@ TODO:
 
 ===-------------------------------------------------------------------------===
 
-On PPC64, this:
-
-long f2 (long x) { return 0xfffffff000000000UL; }
-
-could compile into:
-
-_f2:
-	li r3,-1
-	rldicr r3,r3,0,27
-	blr
-
-we produce:
-
-_f2:
-	lis r2, 4095
-	ori r2, r2, 65535
-	sldi r3, r2, 36
-	blr 
-
-===-------------------------------------------------------------------------===
-
 This code:
 
 unsigned add32carry(unsigned sum, unsigned x) {

Modified: llvm/trunk/test/CodeGen/PowerPC/constants-i64.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/constants-i64.ll?rev=225147&r1=225146&r2=225147&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/PowerPC/constants-i64.ll (original)
+++ llvm/trunk/test/CodeGen/PowerPC/constants-i64.ll Sun Jan  4 21:41:38 2015
@@ -9,7 +9,7 @@ entry:
 
 ; CHECK-LABEL: @cn1
 ; CHECK: lis [[REG1:[0-9]+]], -1
-; CHECK: rldicl 3, [[REG1]], 48, 0
+; CHECK: rldicr 3, [[REG1]], 48, 63
 ; CHECK: blr
 }
 
@@ -20,7 +20,29 @@ entry:
 
 ; CHECK-LABEL: @cnb
 ; CHECK: lis [[REG1:[0-9]+]], -81
-; CHECK: rldicl 3, [[REG1]], 48, 0
+; CHECK: rldicr 3, [[REG1]], 48, 63
+; CHECK: blr
+}
+
+; Function Attrs: nounwind readnone
+define i64 @f2(i64 %x) #0 {
+entry:
+  ret i64 -68719476736
+
+; CHECK-LABEL: @f2
+; CHECK: li [[REG1:[0-9]+]], -1
+; CHECK: sldi 3, [[REG1]], 36
+; CHECK: blr
+}
+
+; Function Attrs: nounwind readnone
+define i64 @f2a(i64 %x) #0 {
+entry:
+  ret i64 -361850994688
+
+; CHECK-LABEL: @f2a
+; CHECK: li [[REG1:[0-9]+]], -337
+; CHECK: sldi 3, [[REG1]], 30
 ; CHECK: blr
 }
 
@@ -31,7 +53,7 @@ entry:
 
 ; CHECK-LABEL: @f2n
 ; CHECK: lis [[REG1:[0-9]+]], -4096
-; CHECK: rldicl 3, [[REG1]], 36, 0
+; CHECK: rldicr 3, [[REG1]], 36, 63
 ; CHECK: blr
 }
 
@@ -42,7 +64,7 @@ entry:
 
 ; CHECK-LABEL: @f3
 ; CHECK: lis [[REG1:[0-9]+]], -32768
-; CHECK: rldicl 3, [[REG1]], 33, 0
+; CHECK: rldicr 3, [[REG1]], 33, 63
 ; CHECK: blr
 }
 
@@ -54,11 +76,9 @@ entry:
 ; CHECK-LABEL: @cn2n
 ; CHECK: lis [[REG1:[0-9]+]], -5121
 ; CHECK: ori [[REG2:[0-9]+]], [[REG1]], 65534
-; CHECK: rldicl 3, [[REG2]], 22, 0
+; CHECK: rldicr 3, [[REG2]], 22, 63
 ; CHECK: blr
 }
 
-
 attributes #0 = { nounwind readnone }
 
-





More information about the llvm-commits mailing list