From 9cad6c8a24ea0f87953815c6005ddd52789c7dde Mon Sep 17 00:00:00 2001 From: Hal Finkel Date: Mon, 5 Jan 2015 03:41:38 +0000 Subject: [PATCH] [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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225147 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 56 +++++++++++++++++++++++--- lib/Target/PowerPC/README.txt | 21 ---------- test/CodeGen/PowerPC/constants-i64.ll | 34 ++++++++++++---- 3 files changed, 78 insertions(+), 33 deletions(-) diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 868659421c7..7d7f557e433 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/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/lib/Target/PowerPC/README.txt b/lib/Target/PowerPC/README.txt index c5491abdbd2..45d31130b83 100644 --- a/lib/Target/PowerPC/README.txt +++ b/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/test/CodeGen/PowerPC/constants-i64.ll b/test/CodeGen/PowerPC/constants-i64.ll index 6f230a159ac..5f2815e5769 100644 --- a/test/CodeGen/PowerPC/constants-i64.ll +++ b/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 } - -- 2.34.1