[llvm] 8210ca0 - [SPARC] Use lzcnt to implement CTLZ when we have VIS3
via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 17 09:37:04 PDT 2025
Author: Koakuma
Date: 2025-04-17T23:37:00+07:00
New Revision: 8210ca019839fc5430b3a95d7caf5c829df3232a
URL: https://github.com/llvm/llvm-project/commit/8210ca019839fc5430b3a95d7caf5c829df3232a
DIFF: https://github.com/llvm/llvm-project/commit/8210ca019839fc5430b3a95d7caf5c829df3232a.diff
LOG: [SPARC] Use lzcnt to implement CTLZ when we have VIS3
Reviewers: s-barannikov, brad0, rorth
Reviewed By: s-barannikov
Pull Request: https://github.com/llvm/llvm-project/pull/135715
Added:
llvm/test/CodeGen/SPARC/ctlz.ll
Modified:
llvm/lib/Target/Sparc/SparcISelLowering.cpp
llvm/lib/Target/Sparc/SparcISelLowering.h
llvm/lib/Target/Sparc/SparcInstrVIS.td
Removed:
################################################################################
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 098e5f22834f4..4b61f588f18c8 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -27,6 +27,7 @@
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
+#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/DiagnosticInfo.h"
@@ -1752,8 +1753,7 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::CTPOP, MVT::i64,
Subtarget->usePopc() ? Legal : Expand);
- setOperationAction(ISD::CTTZ , MVT::i64, Expand);
- setOperationAction(ISD::CTLZ , MVT::i64, Expand);
+ setOperationAction(ISD::CTTZ, MVT::i64, Expand);
setOperationAction(ISD::BSWAP, MVT::i64, Expand);
setOperationAction(ISD::ROTL , MVT::i64, Expand);
setOperationAction(ISD::ROTR , MVT::i64, Expand);
@@ -1814,8 +1814,7 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::FSINCOS, MVT::f32, Expand);
setOperationAction(ISD::FREM , MVT::f32, Expand);
setOperationAction(ISD::FMA , MVT::f32, Expand);
- setOperationAction(ISD::CTTZ , MVT::i32, Expand);
- setOperationAction(ISD::CTLZ , MVT::i32, Expand);
+ setOperationAction(ISD::CTTZ, MVT::i32, Expand);
setOperationAction(ISD::ROTL , MVT::i32, Expand);
setOperationAction(ISD::ROTR , MVT::i32, Expand);
setOperationAction(ISD::BSWAP, MVT::i32, Expand);
@@ -1986,6 +1985,24 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
if (Subtarget->hasLeonCycleCounter())
setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Custom);
+ if (Subtarget->isVIS3()) {
+ setOperationAction(ISD::CTLZ, MVT::i32, Legal);
+ setOperationAction(ISD::CTLZ, MVT::i64, Legal);
+ setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Legal);
+ setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Legal);
+ } else if (Subtarget->usePopc()) {
+ setOperationAction(ISD::CTLZ, MVT::i32, Expand);
+ setOperationAction(ISD::CTLZ, MVT::i64, Expand);
+ setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand);
+ setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Expand);
+ } else {
+ setOperationAction(ISD::CTLZ, MVT::i32, Expand);
+ setOperationAction(ISD::CTLZ, MVT::i64, Expand);
+ setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32,
+ Subtarget->is64Bit() ? Promote : LibCall);
+ setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, LibCall);
+ }
+
setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
setMinFunctionAlignment(Align(4));
@@ -3571,6 +3588,8 @@ bool SparcTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,
Imm.isZero();
}
+bool SparcTargetLowering::isCtlzFast() const { return Subtarget->isVIS3(); }
+
// Override to disable global variable loading on Linux.
void SparcTargetLowering::insertSSPDeclarations(Module &M) const {
if (!Subtarget->isTargetLinux())
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.h b/llvm/lib/Target/Sparc/SparcISelLowering.h
index c09e465f5d05e..ef87e20094c98 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.h
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.h
@@ -210,6 +210,12 @@ namespace llvm {
bool isFPImmLegal(const APFloat &Imm, EVT VT,
bool ForCodeSize) const override;
+ bool isCtlzFast() const override;
+
+ bool isCheapToSpeculateCtlz(Type *Ty) const override {
+ return isCtlzFast();
+ }
+
bool shouldInsertFencesForAtomic(const Instruction *I) const override {
// FIXME: We insert fences for each atomics and generate
// sub-optimal code for PSO/TSO. (Approximately nobody uses any
diff --git a/llvm/lib/Target/Sparc/SparcInstrVIS.td b/llvm/lib/Target/Sparc/SparcInstrVIS.td
index ee24d8a54fe8e..78f50888b5508 100644
--- a/llvm/lib/Target/Sparc/SparcInstrVIS.td
+++ b/llvm/lib/Target/Sparc/SparcInstrVIS.td
@@ -294,4 +294,14 @@ def : Pat<(f32 fpnegimm0), (FNEGS (FZEROS))>;
// VIS3 instruction patterns.
let Predicates = [HasVIS3] in {
def : Pat<(i64 (adde i64:$lhs, i64:$rhs)), (ADDXCCC $lhs, $rhs)>;
+
+def : Pat<(i64 (ctlz i64:$src)), (LZCNT $src)>;
+def : Pat<(i64 (ctlz_zero_undef i64:$src)), (LZCNT $src)>;
+// 32-bit LZCNT.
+// The zero extension will leave us with 32 extra leading zeros,
+// so we need to compensate for it.
+// FIXME remove this when the codegen supports using 64-bit values directly
+// in V8+ mode.
+def : Pat<(i32 (ctlz i32:$src)), (ADDri (LZCNT (SRLri $src, 0)), (i32 -32))>;
+def : Pat<(i32 (ctlz_zero_undef i32:$src)), (ADDri (LZCNT (SRLri $src, 0)), (i32 -32))>;
} // Predicates = [HasVIS3]
diff --git a/llvm/test/CodeGen/SPARC/ctlz.ll b/llvm/test/CodeGen/SPARC/ctlz.ll
new file mode 100644
index 0000000000000..72505f221469e
--- /dev/null
+++ b/llvm/test/CodeGen/SPARC/ctlz.ll
@@ -0,0 +1,405 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=sparc | FileCheck %s -check-prefix=SPARC
+; RUN: llc < %s -mtriple=sparc -mattr=popc | FileCheck %s -check-prefix=SPARC-POPC
+; RUN: llc < %s -mtriple=sparc -mattr=vis3 | FileCheck %s -check-prefix=SPARC-VIS3
+; RUN: llc < %s -mtriple=sparcv9 | FileCheck %s -check-prefix=SPARC64
+; RUN: llc < %s -mtriple=sparcv9 -mattr=popc | FileCheck %s -check-prefix=SPARC64-POPC
+; RUN: llc < %s -mtriple=sparcv9 -mattr=vis3 | FileCheck %s -check-prefix=SPARC64-VIS3
+
+define i32 @i32_nopoison(i32 %x) nounwind {
+; SPARC-LABEL: i32_nopoison:
+; SPARC: ! %bb.0:
+; SPARC-NEXT: save %sp, -96, %sp
+; SPARC-NEXT: cmp %i0, 0
+; SPARC-NEXT: be .LBB0_2
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.1: ! %cond.false
+; SPARC-NEXT: call __clzsi2
+; SPARC-NEXT: mov %i0, %o0
+; SPARC-NEXT: ret
+; SPARC-NEXT: restore %g0, %o0, %o0
+; SPARC-NEXT: .LBB0_2:
+; SPARC-NEXT: ret
+; SPARC-NEXT: restore %g0, 32, %o0
+;
+; SPARC-POPC-LABEL: i32_nopoison:
+; SPARC-POPC: ! %bb.0:
+; SPARC-POPC-NEXT: save %sp, -96, %sp
+; SPARC-POPC-NEXT: cmp %i0, 0
+; SPARC-POPC-NEXT: be .LBB0_2
+; SPARC-POPC-NEXT: nop
+; SPARC-POPC-NEXT: ! %bb.1: ! %cond.false
+; SPARC-POPC-NEXT: call __clzsi2
+; SPARC-POPC-NEXT: mov %i0, %o0
+; SPARC-POPC-NEXT: ret
+; SPARC-POPC-NEXT: restore %g0, %o0, %o0
+; SPARC-POPC-NEXT: .LBB0_2:
+; SPARC-POPC-NEXT: ret
+; SPARC-POPC-NEXT: restore %g0, 32, %o0
+;
+; SPARC-VIS3-LABEL: i32_nopoison:
+; SPARC-VIS3: ! %bb.0:
+; SPARC-VIS3-NEXT: srl %o0, 0, %o0
+; SPARC-VIS3-NEXT: lzcnt %o0, %o0
+; SPARC-VIS3-NEXT: retl
+; SPARC-VIS3-NEXT: add %o0, -32, %o0
+;
+; SPARC64-LABEL: i32_nopoison:
+; SPARC64: ! %bb.0:
+; SPARC64-NEXT: save %sp, -176, %sp
+; SPARC64-NEXT: cmp %i0, 0
+; SPARC64-NEXT: be %icc, .LBB0_2
+; SPARC64-NEXT: nop
+; SPARC64-NEXT: ! %bb.1: ! %cond.false
+; SPARC64-NEXT: call __clzdi2
+; SPARC64-NEXT: sllx %i0, 32, %o0
+; SPARC64-NEXT: ret
+; SPARC64-NEXT: restore %g0, %o0, %o0
+; SPARC64-NEXT: .LBB0_2:
+; SPARC64-NEXT: ret
+; SPARC64-NEXT: restore %g0, 32, %o0
+;
+; SPARC64-POPC-LABEL: i32_nopoison:
+; SPARC64-POPC: ! %bb.0:
+; SPARC64-POPC-NEXT: cmp %o0, 0
+; SPARC64-POPC-NEXT: be %icc, .LBB0_2
+; SPARC64-POPC-NEXT: nop
+; SPARC64-POPC-NEXT: ! %bb.1: ! %cond.false
+; SPARC64-POPC-NEXT: srl %o0, 1, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: srl %o0, 2, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: srl %o0, 4, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: srl %o0, 8, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: srl %o0, 16, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: xor %o0, -1, %o0
+; SPARC64-POPC-NEXT: srl %o0, 0, %o0
+; SPARC64-POPC-NEXT: retl
+; SPARC64-POPC-NEXT: popc %o0, %o0
+; SPARC64-POPC-NEXT: .LBB0_2:
+; SPARC64-POPC-NEXT: retl
+; SPARC64-POPC-NEXT: mov 32, %o0
+;
+; SPARC64-VIS3-LABEL: i32_nopoison:
+; SPARC64-VIS3: ! %bb.0:
+; SPARC64-VIS3-NEXT: srl %o0, 0, %o0
+; SPARC64-VIS3-NEXT: lzcnt %o0, %o0
+; SPARC64-VIS3-NEXT: retl
+; SPARC64-VIS3-NEXT: add %o0, -32, %o0
+ %ret = call i32 @llvm.ctlz.i32(i32 %x, i1 false)
+ ret i32 %ret
+}
+
+define i32 @i32_poison(i32 %x) nounwind {
+; SPARC-LABEL: i32_poison:
+; SPARC: ! %bb.0:
+; SPARC-NEXT: save %sp, -96, %sp
+; SPARC-NEXT: call __clzsi2
+; SPARC-NEXT: mov %i0, %o0
+; SPARC-NEXT: ret
+; SPARC-NEXT: restore %g0, %o0, %o0
+;
+; SPARC-POPC-LABEL: i32_poison:
+; SPARC-POPC: ! %bb.0:
+; SPARC-POPC-NEXT: save %sp, -96, %sp
+; SPARC-POPC-NEXT: call __clzsi2
+; SPARC-POPC-NEXT: mov %i0, %o0
+; SPARC-POPC-NEXT: ret
+; SPARC-POPC-NEXT: restore %g0, %o0, %o0
+;
+; SPARC-VIS3-LABEL: i32_poison:
+; SPARC-VIS3: ! %bb.0:
+; SPARC-VIS3-NEXT: srl %o0, 0, %o0
+; SPARC-VIS3-NEXT: lzcnt %o0, %o0
+; SPARC-VIS3-NEXT: retl
+; SPARC-VIS3-NEXT: add %o0, -32, %o0
+;
+; SPARC64-LABEL: i32_poison:
+; SPARC64: ! %bb.0:
+; SPARC64-NEXT: save %sp, -176, %sp
+; SPARC64-NEXT: call __clzdi2
+; SPARC64-NEXT: sllx %i0, 32, %o0
+; SPARC64-NEXT: ret
+; SPARC64-NEXT: restore %g0, %o0, %o0
+;
+; SPARC64-POPC-LABEL: i32_poison:
+; SPARC64-POPC: ! %bb.0:
+; SPARC64-POPC-NEXT: srl %o0, 1, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: srl %o0, 2, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: srl %o0, 4, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: srl %o0, 8, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: srl %o0, 16, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: xor %o0, -1, %o0
+; SPARC64-POPC-NEXT: srl %o0, 0, %o0
+; SPARC64-POPC-NEXT: retl
+; SPARC64-POPC-NEXT: popc %o0, %o0
+;
+; SPARC64-VIS3-LABEL: i32_poison:
+; SPARC64-VIS3: ! %bb.0:
+; SPARC64-VIS3-NEXT: srl %o0, 0, %o0
+; SPARC64-VIS3-NEXT: lzcnt %o0, %o0
+; SPARC64-VIS3-NEXT: retl
+; SPARC64-VIS3-NEXT: add %o0, -32, %o0
+ %ret = call i32 @llvm.ctlz.i32(i32 %x, i1 true)
+ ret i32 %ret
+}
+
+define i64 @i64_nopoison(i64 %x) nounwind {
+; SPARC-LABEL: i64_nopoison:
+; SPARC: ! %bb.0:
+; SPARC-NEXT: save %sp, -96, %sp
+; SPARC-NEXT: call __clzsi2
+; SPARC-NEXT: mov %i0, %o0
+; SPARC-NEXT: cmp %i0, 0
+; SPARC-NEXT: bne .LBB2_2
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.1:
+; SPARC-NEXT: srl %i1, 1, %i0
+; SPARC-NEXT: or %i1, %i0, %i0
+; SPARC-NEXT: srl %i0, 2, %i1
+; SPARC-NEXT: or %i0, %i1, %i0
+; SPARC-NEXT: srl %i0, 4, %i1
+; SPARC-NEXT: or %i0, %i1, %i0
+; SPARC-NEXT: srl %i0, 8, %i1
+; SPARC-NEXT: or %i0, %i1, %i0
+; SPARC-NEXT: srl %i0, 16, %i1
+; SPARC-NEXT: or %i0, %i1, %i0
+; SPARC-NEXT: xor %i0, -1, %i0
+; SPARC-NEXT: srl %i0, 1, %i1
+; SPARC-NEXT: sethi 1398101, %i2
+; SPARC-NEXT: or %i2, 341, %i2
+; SPARC-NEXT: and %i1, %i2, %i1
+; SPARC-NEXT: sub %i0, %i1, %i0
+; SPARC-NEXT: sethi 838860, %i1
+; SPARC-NEXT: or %i1, 819, %i1
+; SPARC-NEXT: and %i0, %i1, %i2
+; SPARC-NEXT: srl %i0, 2, %i0
+; SPARC-NEXT: and %i0, %i1, %i0
+; SPARC-NEXT: add %i2, %i0, %i0
+; SPARC-NEXT: srl %i0, 4, %i1
+; SPARC-NEXT: add %i0, %i1, %i0
+; SPARC-NEXT: sethi 246723, %i1
+; SPARC-NEXT: or %i1, 783, %i1
+; SPARC-NEXT: and %i0, %i1, %i0
+; SPARC-NEXT: sll %i0, 8, %i1
+; SPARC-NEXT: add %i0, %i1, %i0
+; SPARC-NEXT: sll %i0, 16, %i1
+; SPARC-NEXT: add %i0, %i1, %i0
+; SPARC-NEXT: srl %i0, 24, %i0
+; SPARC-NEXT: add %i0, 32, %o0
+; SPARC-NEXT: .LBB2_2:
+; SPARC-NEXT: mov %g0, %i0
+; SPARC-NEXT: ret
+; SPARC-NEXT: restore %g0, %o0, %o1
+;
+; SPARC-POPC-LABEL: i64_nopoison:
+; SPARC-POPC: ! %bb.0:
+; SPARC-POPC-NEXT: save %sp, -96, %sp
+; SPARC-POPC-NEXT: call __clzsi2
+; SPARC-POPC-NEXT: mov %i0, %o0
+; SPARC-POPC-NEXT: cmp %i0, 0
+; SPARC-POPC-NEXT: bne .LBB2_2
+; SPARC-POPC-NEXT: nop
+; SPARC-POPC-NEXT: ! %bb.1:
+; SPARC-POPC-NEXT: srl %i1, 1, %i0
+; SPARC-POPC-NEXT: or %i1, %i0, %i0
+; SPARC-POPC-NEXT: srl %i0, 2, %i1
+; SPARC-POPC-NEXT: or %i0, %i1, %i0
+; SPARC-POPC-NEXT: srl %i0, 4, %i1
+; SPARC-POPC-NEXT: or %i0, %i1, %i0
+; SPARC-POPC-NEXT: srl %i0, 8, %i1
+; SPARC-POPC-NEXT: or %i0, %i1, %i0
+; SPARC-POPC-NEXT: srl %i0, 16, %i1
+; SPARC-POPC-NEXT: or %i0, %i1, %i0
+; SPARC-POPC-NEXT: xor %i0, -1, %i0
+; SPARC-POPC-NEXT: srl %i0, 1, %i1
+; SPARC-POPC-NEXT: sethi 1398101, %i2
+; SPARC-POPC-NEXT: or %i2, 341, %i2
+; SPARC-POPC-NEXT: and %i1, %i2, %i1
+; SPARC-POPC-NEXT: sub %i0, %i1, %i0
+; SPARC-POPC-NEXT: sethi 838860, %i1
+; SPARC-POPC-NEXT: or %i1, 819, %i1
+; SPARC-POPC-NEXT: and %i0, %i1, %i2
+; SPARC-POPC-NEXT: srl %i0, 2, %i0
+; SPARC-POPC-NEXT: and %i0, %i1, %i0
+; SPARC-POPC-NEXT: add %i2, %i0, %i0
+; SPARC-POPC-NEXT: srl %i0, 4, %i1
+; SPARC-POPC-NEXT: add %i0, %i1, %i0
+; SPARC-POPC-NEXT: sethi 246723, %i1
+; SPARC-POPC-NEXT: or %i1, 783, %i1
+; SPARC-POPC-NEXT: and %i0, %i1, %i0
+; SPARC-POPC-NEXT: sll %i0, 8, %i1
+; SPARC-POPC-NEXT: add %i0, %i1, %i0
+; SPARC-POPC-NEXT: sll %i0, 16, %i1
+; SPARC-POPC-NEXT: add %i0, %i1, %i0
+; SPARC-POPC-NEXT: srl %i0, 24, %i0
+; SPARC-POPC-NEXT: add %i0, 32, %o0
+; SPARC-POPC-NEXT: .LBB2_2:
+; SPARC-POPC-NEXT: mov %g0, %i0
+; SPARC-POPC-NEXT: ret
+; SPARC-POPC-NEXT: restore %g0, %o0, %o1
+;
+; SPARC-VIS3-LABEL: i64_nopoison:
+; SPARC-VIS3: ! %bb.0:
+; SPARC-VIS3-NEXT: cmp %o0, 0
+; SPARC-VIS3-NEXT: bne .LBB2_2
+; SPARC-VIS3-NEXT: nop
+; SPARC-VIS3-NEXT: ! %bb.1:
+; SPARC-VIS3-NEXT: srl %o1, 0, %o0
+; SPARC-VIS3-NEXT: lzcnt %o0, %o0
+; SPARC-VIS3-NEXT: add %o0, -32, %o0
+; SPARC-VIS3-NEXT: add %o0, 32, %o1
+; SPARC-VIS3-NEXT: retl
+; SPARC-VIS3-NEXT: mov %g0, %o0
+; SPARC-VIS3-NEXT: .LBB2_2:
+; SPARC-VIS3-NEXT: srl %o0, 0, %o0
+; SPARC-VIS3-NEXT: lzcnt %o0, %o0
+; SPARC-VIS3-NEXT: add %o0, -32, %o1
+; SPARC-VIS3-NEXT: retl
+; SPARC-VIS3-NEXT: mov %g0, %o0
+;
+; SPARC64-LABEL: i64_nopoison:
+; SPARC64: ! %bb.0:
+; SPARC64-NEXT: save %sp, -176, %sp
+; SPARC64-NEXT: brz %i0, .LBB2_2
+; SPARC64-NEXT: nop
+; SPARC64-NEXT: ! %bb.1: ! %cond.false
+; SPARC64-NEXT: call __clzdi2
+; SPARC64-NEXT: mov %i0, %o0
+; SPARC64-NEXT: ret
+; SPARC64-NEXT: restore %g0, %o0, %o0
+; SPARC64-NEXT: .LBB2_2:
+; SPARC64-NEXT: ret
+; SPARC64-NEXT: restore %g0, 64, %o0
+;
+; SPARC64-POPC-LABEL: i64_nopoison:
+; SPARC64-POPC: ! %bb.0:
+; SPARC64-POPC-NEXT: brz %o0, .LBB2_2
+; SPARC64-POPC-NEXT: nop
+; SPARC64-POPC-NEXT: ! %bb.1: ! %cond.false
+; SPARC64-POPC-NEXT: srlx %o0, 1, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: srlx %o0, 2, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: srlx %o0, 4, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: srlx %o0, 8, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: srlx %o0, 16, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: srlx %o0, 32, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: xor %o0, -1, %o0
+; SPARC64-POPC-NEXT: retl
+; SPARC64-POPC-NEXT: popc %o0, %o0
+; SPARC64-POPC-NEXT: .LBB2_2:
+; SPARC64-POPC-NEXT: retl
+; SPARC64-POPC-NEXT: mov 64, %o0
+;
+; SPARC64-VIS3-LABEL: i64_nopoison:
+; SPARC64-VIS3: ! %bb.0:
+; SPARC64-VIS3-NEXT: retl
+; SPARC64-VIS3-NEXT: lzcnt %o0, %o0
+ %ret = call i64 @llvm.ctlz.i64(i64 %x, i1 false)
+ ret i64 %ret
+}
+
+define i64 @i64_poison(i64 %x) nounwind {
+; SPARC-LABEL: i64_poison:
+; SPARC: ! %bb.0:
+; SPARC-NEXT: save %sp, -96, %sp
+; SPARC-NEXT: mov %i1, %o0
+; SPARC-NEXT: call __clzsi2
+; SPARC-NEXT: mov %i0, %i1
+; SPARC-NEXT: mov %o0, %i0
+; SPARC-NEXT: call __clzsi2
+; SPARC-NEXT: mov %i1, %o0
+; SPARC-NEXT: cmp %i1, 0
+; SPARC-NEXT: bne .LBB3_2
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.1:
+; SPARC-NEXT: add %i0, 32, %o0
+; SPARC-NEXT: .LBB3_2:
+; SPARC-NEXT: mov %g0, %i0
+; SPARC-NEXT: ret
+; SPARC-NEXT: restore %g0, %o0, %o1
+;
+; SPARC-POPC-LABEL: i64_poison:
+; SPARC-POPC: ! %bb.0:
+; SPARC-POPC-NEXT: save %sp, -96, %sp
+; SPARC-POPC-NEXT: mov %i1, %o0
+; SPARC-POPC-NEXT: call __clzsi2
+; SPARC-POPC-NEXT: mov %i0, %i1
+; SPARC-POPC-NEXT: mov %o0, %i0
+; SPARC-POPC-NEXT: call __clzsi2
+; SPARC-POPC-NEXT: mov %i1, %o0
+; SPARC-POPC-NEXT: cmp %i1, 0
+; SPARC-POPC-NEXT: bne .LBB3_2
+; SPARC-POPC-NEXT: nop
+; SPARC-POPC-NEXT: ! %bb.1:
+; SPARC-POPC-NEXT: add %i0, 32, %o0
+; SPARC-POPC-NEXT: .LBB3_2:
+; SPARC-POPC-NEXT: mov %g0, %i0
+; SPARC-POPC-NEXT: ret
+; SPARC-POPC-NEXT: restore %g0, %o0, %o1
+;
+; SPARC-VIS3-LABEL: i64_poison:
+; SPARC-VIS3: ! %bb.0:
+; SPARC-VIS3-NEXT: cmp %o0, 0
+; SPARC-VIS3-NEXT: bne .LBB3_2
+; SPARC-VIS3-NEXT: nop
+; SPARC-VIS3-NEXT: ! %bb.1:
+; SPARC-VIS3-NEXT: srl %o1, 0, %o0
+; SPARC-VIS3-NEXT: lzcnt %o0, %o0
+; SPARC-VIS3-NEXT: add %o0, -32, %o0
+; SPARC-VIS3-NEXT: add %o0, 32, %o1
+; SPARC-VIS3-NEXT: retl
+; SPARC-VIS3-NEXT: mov %g0, %o0
+; SPARC-VIS3-NEXT: .LBB3_2:
+; SPARC-VIS3-NEXT: srl %o0, 0, %o0
+; SPARC-VIS3-NEXT: lzcnt %o0, %o0
+; SPARC-VIS3-NEXT: add %o0, -32, %o1
+; SPARC-VIS3-NEXT: retl
+; SPARC-VIS3-NEXT: mov %g0, %o0
+;
+; SPARC64-LABEL: i64_poison:
+; SPARC64: ! %bb.0:
+; SPARC64-NEXT: save %sp, -176, %sp
+; SPARC64-NEXT: call __clzdi2
+; SPARC64-NEXT: mov %i0, %o0
+; SPARC64-NEXT: ret
+; SPARC64-NEXT: restore %g0, %o0, %o0
+;
+; SPARC64-POPC-LABEL: i64_poison:
+; SPARC64-POPC: ! %bb.0:
+; SPARC64-POPC-NEXT: srlx %o0, 1, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: srlx %o0, 2, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: srlx %o0, 4, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: srlx %o0, 8, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: srlx %o0, 16, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: srlx %o0, 32, %o1
+; SPARC64-POPC-NEXT: or %o0, %o1, %o0
+; SPARC64-POPC-NEXT: xor %o0, -1, %o0
+; SPARC64-POPC-NEXT: retl
+; SPARC64-POPC-NEXT: popc %o0, %o0
+;
+; SPARC64-VIS3-LABEL: i64_poison:
+; SPARC64-VIS3: ! %bb.0:
+; SPARC64-VIS3-NEXT: retl
+; SPARC64-VIS3-NEXT: lzcnt %o0, %o0
+ %ret = call i64 @llvm.ctlz.i64(i64 %x, i1 true)
+ ret i64 %ret
+}
More information about the llvm-commits
mailing list