From d138a7bb3f49cc92d0ab81ac68c63284adce2fbf Mon Sep 17 00:00:00 2001 From: Hal Finkel Date: Sun, 4 Jan 2015 12:35:03 +0000 Subject: [PATCH] [PowerPC] Materialize i64 constants using bit inversion Materializing full 64-bit constants on PPC64 can be expensive, requiring up to 5 instructions depending on the locations of the non-zero bits. Sometimes materializing the bit-reversed constant, and then flipping the bits, requires fewer instructions than the direct method. If so, do that instead. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225132 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 32 ++++++++++++++++++++++++-- test/CodeGen/PowerPC/constants-i64.ll | 20 ++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 test/CodeGen/PowerPC/constants-i64.ll diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index c6dc50143c0..2e1c1abf5b6 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -544,7 +544,7 @@ SDNode *PPCDAGToDAGISel::SelectBitfieldInsert(SDNode *N) { // Predict the number of instructions that would be generated by calling // SelectInt64(N). -static unsigned SelectInt64Count(int64_t Imm) { +static unsigned SelectInt64CountDirect(int64_t Imm) { // Assume no remaining bits. unsigned Remainder = 0; // Assume no shift required. @@ -602,9 +602,21 @@ static unsigned SelectInt64Count(int64_t Imm) { return Result; } +static unsigned SelectInt64Count(int64_t Imm) { + unsigned DirectCount = SelectInt64CountDirect(Imm); + + // If might be cheaper to materialize the bit-inverted constant, and then + // flip the bits (which takes one nor instruction). + unsigned NotDirectCount = SelectInt64CountDirect(~(uint64_t) Imm) + 1; + if (NotDirectCount < DirectCount) + return NotDirectCount; + + return DirectCount; +} + // Select a 64-bit constant. For cost-modeling purposes, SelectInt64Count // (above) needs to be kept in sync with this function. -static SDNode *SelectInt64(SelectionDAG *CurDAG, SDLoc dl, int64_t Imm) { +static SDNode *SelectInt64Direct(SelectionDAG *CurDAG, SDLoc dl, int64_t Imm) { // Assume no remaining bits. unsigned Remainder = 0; // Assume no shift required. @@ -678,6 +690,22 @@ static SDNode *SelectInt64(SelectionDAG *CurDAG, SDLoc dl, int64_t Imm) { return Result; } +static SDNode *SelectInt64(SelectionDAG *CurDAG, SDLoc dl, int64_t Imm) { + unsigned DirectCount = SelectInt64CountDirect(Imm); + + // If might be cheaper to materialize the bit-inverted constant, and then + // flip the bits (which takes one nor instruction). + unsigned NotDirectCount = SelectInt64CountDirect(~(uint64_t) Imm) + 1; + if (NotDirectCount < DirectCount) { + SDValue NotDirectVal = + SDValue(SelectInt64Direct(CurDAG, dl, ~(uint64_t) Imm), 0); + return CurDAG->getMachineNode(PPC::NOR8, dl, MVT::i64, NotDirectVal, + NotDirectVal); + } + + return SelectInt64Direct(CurDAG, dl, Imm); +} + // Select a 64-bit constant. static SDNode *SelectInt64(SelectionDAG *CurDAG, SDNode *N) { SDLoc dl(N); diff --git a/test/CodeGen/PowerPC/constants-i64.ll b/test/CodeGen/PowerPC/constants-i64.ll new file mode 100644 index 00000000000..6d9ef0888a5 --- /dev/null +++ b/test/CodeGen/PowerPC/constants-i64.ll @@ -0,0 +1,20 @@ +; RUN: llc -mcpu=ppc64 < %s | FileCheck %s +target datalayout = "E-m:e-i64:64-n32:64" +target triple = "powerpc64-unknown-linux-gnu" + +; Function Attrs: nounwind readnone +define i64 @cn1() #0 { +entry: + ret i64 281474976710655 + +; CHECK-LABEL: @cn1 +; CHECK: li [[REG1:[0-9]+]], 0 +; CHECK: ori [[REG2:[0-9]+]], [[REG1]], 65535 +; CHECK: sldi [[REG3:[0-9]+]], [[REG2]], 48 +; CHECK: nor 3, [[REG3]], [[REG3]] +; CHECK: blr +} + +attributes #0 = { nounwind readnone } + +