Skip to content

Commit 8210ca0

Browse files
authored
[SPARC] Use lzcnt to implement CTLZ when we have VIS3
Reviewers: s-barannikov, brad0, rorth Reviewed By: s-barannikov Pull Request: #135715
1 parent 1f224d8 commit 8210ca0

File tree

4 files changed

+444
-4
lines changed

4 files changed

+444
-4
lines changed

llvm/lib/Target/Sparc/SparcISelLowering.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "llvm/CodeGen/MachineRegisterInfo.h"
2828
#include "llvm/CodeGen/SelectionDAG.h"
2929
#include "llvm/CodeGen/SelectionDAGNodes.h"
30+
#include "llvm/CodeGen/TargetLowering.h"
3031
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
3132
#include "llvm/IR/DerivedTypes.h"
3233
#include "llvm/IR/DiagnosticInfo.h"
@@ -1752,8 +1753,7 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
17521753

17531754
setOperationAction(ISD::CTPOP, MVT::i64,
17541755
Subtarget->usePopc() ? Legal : Expand);
1755-
setOperationAction(ISD::CTTZ , MVT::i64, Expand);
1756-
setOperationAction(ISD::CTLZ , MVT::i64, Expand);
1756+
setOperationAction(ISD::CTTZ, MVT::i64, Expand);
17571757
setOperationAction(ISD::BSWAP, MVT::i64, Expand);
17581758
setOperationAction(ISD::ROTL , MVT::i64, Expand);
17591759
setOperationAction(ISD::ROTR , MVT::i64, Expand);
@@ -1814,8 +1814,7 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
18141814
setOperationAction(ISD::FSINCOS, MVT::f32, Expand);
18151815
setOperationAction(ISD::FREM , MVT::f32, Expand);
18161816
setOperationAction(ISD::FMA , MVT::f32, Expand);
1817-
setOperationAction(ISD::CTTZ , MVT::i32, Expand);
1818-
setOperationAction(ISD::CTLZ , MVT::i32, Expand);
1817+
setOperationAction(ISD::CTTZ, MVT::i32, Expand);
18191818
setOperationAction(ISD::ROTL , MVT::i32, Expand);
18201819
setOperationAction(ISD::ROTR , MVT::i32, Expand);
18211820
setOperationAction(ISD::BSWAP, MVT::i32, Expand);
@@ -1986,6 +1985,24 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
19861985
if (Subtarget->hasLeonCycleCounter())
19871986
setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Custom);
19881987

1988+
if (Subtarget->isVIS3()) {
1989+
setOperationAction(ISD::CTLZ, MVT::i32, Legal);
1990+
setOperationAction(ISD::CTLZ, MVT::i64, Legal);
1991+
setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Legal);
1992+
setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Legal);
1993+
} else if (Subtarget->usePopc()) {
1994+
setOperationAction(ISD::CTLZ, MVT::i32, Expand);
1995+
setOperationAction(ISD::CTLZ, MVT::i64, Expand);
1996+
setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand);
1997+
setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Expand);
1998+
} else {
1999+
setOperationAction(ISD::CTLZ, MVT::i32, Expand);
2000+
setOperationAction(ISD::CTLZ, MVT::i64, Expand);
2001+
setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32,
2002+
Subtarget->is64Bit() ? Promote : LibCall);
2003+
setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, LibCall);
2004+
}
2005+
19892006
setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
19902007

19912008
setMinFunctionAlignment(Align(4));
@@ -3571,6 +3588,8 @@ bool SparcTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,
35713588
Imm.isZero();
35723589
}
35733590

3591+
bool SparcTargetLowering::isCtlzFast() const { return Subtarget->isVIS3(); }
3592+
35743593
// Override to disable global variable loading on Linux.
35753594
void SparcTargetLowering::insertSSPDeclarations(Module &M) const {
35763595
if (!Subtarget->isTargetLinux())

llvm/lib/Target/Sparc/SparcISelLowering.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,12 @@ namespace llvm {
210210
bool isFPImmLegal(const APFloat &Imm, EVT VT,
211211
bool ForCodeSize) const override;
212212

213+
bool isCtlzFast() const override;
214+
215+
bool isCheapToSpeculateCtlz(Type *Ty) const override {
216+
return isCtlzFast();
217+
}
218+
213219
bool shouldInsertFencesForAtomic(const Instruction *I) const override {
214220
// FIXME: We insert fences for each atomics and generate
215221
// sub-optimal code for PSO/TSO. (Approximately nobody uses any

llvm/lib/Target/Sparc/SparcInstrVIS.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,4 +294,14 @@ def : Pat<(f32 fpnegimm0), (FNEGS (FZEROS))>;
294294
// VIS3 instruction patterns.
295295
let Predicates = [HasVIS3] in {
296296
def : Pat<(i64 (adde i64:$lhs, i64:$rhs)), (ADDXCCC $lhs, $rhs)>;
297+
298+
def : Pat<(i64 (ctlz i64:$src)), (LZCNT $src)>;
299+
def : Pat<(i64 (ctlz_zero_undef i64:$src)), (LZCNT $src)>;
300+
// 32-bit LZCNT.
301+
// The zero extension will leave us with 32 extra leading zeros,
302+
// so we need to compensate for it.
303+
// FIXME remove this when the codegen supports using 64-bit values directly
304+
// in V8+ mode.
305+
def : Pat<(i32 (ctlz i32:$src)), (ADDri (LZCNT (SRLri $src, 0)), (i32 -32))>;
306+
def : Pat<(i32 (ctlz_zero_undef i32:$src)), (ADDri (LZCNT (SRLri $src, 0)), (i32 -32))>;
297307
} // Predicates = [HasVIS3]

0 commit comments

Comments
 (0)