summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp56
-rw-r--r--llvm/lib/Target/PowerPC/README.txt21
-rw-r--r--llvm/test/CodeGen/PowerPC/constants-i64.ll34
3 files changed, 78 insertions, 33 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index 868659421c7..7d7f557e433 100644
--- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -608,9 +608,23 @@ static uint64_t Rot64(uint64_t Imm, unsigned R) {
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(SelectionDAG *CurDAG, SDLoc dl, int64_t Imm) {
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 *CurDAG, SDLoc dl, int64_t Imm) {
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.
diff --git a/llvm/lib/Target/PowerPC/README.txt b/llvm/lib/Target/PowerPC/README.txt
index c5491abdbd2..45d31130b83 100644
--- a/llvm/lib/Target/PowerPC/README.txt
+++ b/llvm/lib/Target/PowerPC/README.txt
@@ -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) {
diff --git a/llvm/test/CodeGen/PowerPC/constants-i64.ll b/llvm/test/CodeGen/PowerPC/constants-i64.ll
index 6f230a159ac..5f2815e5769 100644
--- a/llvm/test/CodeGen/PowerPC/constants-i64.ll
+++ b/llvm/test/CodeGen/PowerPC/constants-i64.ll
@@ -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 }
-
OpenPOWER on IntegriCloud