[llvm] [SPARC] Use op-then-neg instructions when we have VIS3 (PR #138603)
via llvm-commits
llvm-commits at lists.llvm.org
Mon May 5 15:32:51 PDT 2025
https://github.com/koachan created https://github.com/llvm/llvm-project/pull/138603
This is for manual re-merging of PR #135717 since that PR was merged to the wrong base branch.
>From af1ab680ab0b30cbdeed06f76c9879ecdb33e94b Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Tue, 15 Apr 2025 07:46:10 +0700
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20change?=
=?UTF-8?q?s=20to=20main=20this=20commit=20is=20based=20on?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.5
[skip ci]
---
llvm/lib/Target/Sparc/SparcISelLowering.cpp | 34 +++-
llvm/lib/Target/Sparc/SparcISelLowering.h | 3 +
llvm/lib/Target/Sparc/SparcInstr64Bit.td | 2 +
llvm/lib/Target/Sparc/SparcInstrVIS.td | 56 +++++-
llvm/test/CodeGen/SPARC/2011-01-11-CC.ll | 118 ++++++++++++
llvm/test/CodeGen/SPARC/bitcast.ll | 139 ++++++++++++++
llvm/test/CodeGen/SPARC/ctlz.ll | 171 ++++++++++++++++++
llvm/test/CodeGen/SPARC/float-constants.ll | 115 ++++++++++++
llvm/test/CodeGen/SPARC/multiply-extension.ll | 59 ++++++
.../SPARC/smulo-128-legalisation-lowering.ll | 44 +++++
.../SPARC/umulo-128-legalisation-lowering.ll | 33 ++++
11 files changed, 758 insertions(+), 16 deletions(-)
create mode 100644 llvm/test/CodeGen/SPARC/bitcast.ll
create mode 100644 llvm/test/CodeGen/SPARC/ctlz.ll
create mode 100644 llvm/test/CodeGen/SPARC/multiply-extension.ll
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 85b8750d40f46..98fcaba86fee0 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -1704,8 +1704,10 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::FP16_TO_FP, MVT::f128, Expand);
setOperationAction(ISD::FP_TO_FP16, MVT::f128, Expand);
- setOperationAction(ISD::BITCAST, MVT::f32, Expand);
- setOperationAction(ISD::BITCAST, MVT::i32, Expand);
+ setOperationAction(ISD::BITCAST, MVT::f32,
+ Subtarget->isVIS3() ? Legal : Expand);
+ setOperationAction(ISD::BITCAST, MVT::i32,
+ Subtarget->isVIS3() ? Legal : Expand);
// Sparc has no select or setcc: expand to SELECT_CC.
setOperationAction(ISD::SELECT, MVT::i32, Expand);
@@ -1737,9 +1739,16 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::SUBC, MVT::i32, Legal);
setOperationAction(ISD::SUBE, MVT::i32, Legal);
+ if (Subtarget->isVIS3()) {
+ setOperationAction(ISD::ADDC, MVT::i64, Legal);
+ setOperationAction(ISD::ADDE, MVT::i64, Legal);
+ }
+
if (Subtarget->is64Bit()) {
- setOperationAction(ISD::BITCAST, MVT::f64, Expand);
- setOperationAction(ISD::BITCAST, MVT::i64, Expand);
+ setOperationAction(ISD::BITCAST, MVT::f64,
+ Subtarget->isVIS3() ? Legal : Expand);
+ setOperationAction(ISD::BITCAST, MVT::i64,
+ Subtarget->isVIS3() ? Legal : Expand);
setOperationAction(ISD::SELECT, MVT::i64, Expand);
setOperationAction(ISD::SETCC, MVT::i64, Expand);
setOperationAction(ISD::BR_CC, MVT::i64, Custom);
@@ -1748,7 +1757,8 @@ 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::CTLZ, MVT::i64,
+ Subtarget->isVIS3() ? Legal : Expand);
setOperationAction(ISD::BSWAP, MVT::i64, Expand);
setOperationAction(ISD::ROTL , MVT::i64, Expand);
setOperationAction(ISD::ROTR , MVT::i64, Expand);
@@ -1810,7 +1820,7 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
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::CTLZ, MVT::i32, Subtarget->isVIS3() ? Legal : Expand);
setOperationAction(ISD::ROTL , MVT::i32, Expand);
setOperationAction(ISD::ROTR , MVT::i32, Expand);
setOperationAction(ISD::BSWAP, MVT::i32, Expand);
@@ -1849,8 +1859,10 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
if (Subtarget->is64Bit()) {
setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand);
setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand);
- setOperationAction(ISD::MULHU, MVT::i64, Expand);
- setOperationAction(ISD::MULHS, MVT::i64, Expand);
+ setOperationAction(ISD::MULHU, MVT::i64,
+ Subtarget->isVIS3() ? Legal : Expand);
+ setOperationAction(ISD::MULHS, MVT::i64,
+ Subtarget->isVIS3() ? Legal : Expand);
setOperationAction(ISD::SHL_PARTS, MVT::i64, Expand);
setOperationAction(ISD::SRA_PARTS, MVT::i64, Expand);
@@ -3560,6 +3572,12 @@ bool SparcTargetLowering::useLoadStackGuardNode(const Module &M) const {
return true;
}
+bool SparcTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,
+ bool ForCodeSize) const {
+ return Subtarget->isVIS() && (VT == MVT::f32 || VT == MVT::f64) &&
+ Imm.isZero();
+}
+
// 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 1bee5f4cfe84d..c09e465f5d05e 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.h
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.h
@@ -207,6 +207,9 @@ namespace llvm {
return VT != MVT::f128;
}
+ bool isFPImmLegal(const APFloat &Imm, EVT VT,
+ bool ForCodeSize) const override;
+
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/SparcInstr64Bit.td b/llvm/lib/Target/Sparc/SparcInstr64Bit.td
index 56fab2f26a19e..000612534e89d 100644
--- a/llvm/lib/Target/Sparc/SparcInstr64Bit.td
+++ b/llvm/lib/Target/Sparc/SparcInstr64Bit.td
@@ -157,9 +157,11 @@ def : Pat<(and i64:$lhs, (not i64:$rhs)), (ANDNrr $lhs, $rhs)>;
def : Pat<(or i64:$lhs, (not i64:$rhs)), (ORNrr $lhs, $rhs)>;
def : Pat<(not (xor i64:$lhs, i64:$rhs)), (XNORrr $lhs, $rhs)>;
+def : Pat<(addc i64:$lhs, i64:$rhs), (ADDCCrr $lhs, $rhs)>, Requires<[HasVIS3]>;
def : Pat<(add i64:$lhs, i64:$rhs), (ADDrr $lhs, $rhs)>;
def : Pat<(sub i64:$lhs, i64:$rhs), (SUBrr $lhs, $rhs)>;
+def : Pat<(addc i64:$lhs, (i64 simm13:$rhs)), (ADDCCri $lhs, imm:$rhs)>, Requires<[HasVIS3]>;
def : Pat<(add i64:$lhs, (i64 simm13:$rhs)), (ADDri $lhs, imm:$rhs)>;
def : Pat<(sub i64:$lhs, (i64 simm13:$rhs)), (SUBri $lhs, imm:$rhs)>;
diff --git a/llvm/lib/Target/Sparc/SparcInstrVIS.td b/llvm/lib/Target/Sparc/SparcInstrVIS.td
index 8ce8f37f34040..b806f0c413899 100644
--- a/llvm/lib/Target/Sparc/SparcInstrVIS.td
+++ b/llvm/lib/Target/Sparc/SparcInstrVIS.td
@@ -45,10 +45,10 @@ class VISInst2<bits<9> opfval, string OpcStr, RegisterClass RC = DFPRegs>
!strconcat(OpcStr, " $rs2, $rd")>;
// For VIS Instructions with only rd operand.
-let Constraints = "$rd = $f", rs1 = 0, rs2 = 0 in
+let rs1 = 0, rs2 = 0 in
class VISInstD<bits<9> opfval, string OpcStr, RegisterClass RC = DFPRegs>
: VISInstFormat<opfval,
- (outs RC:$rd), (ins RC:$f),
+ (outs RC:$rd), (ins),
!strconcat(OpcStr, " $rd")>;
// VIS 1 Instructions
@@ -259,14 +259,14 @@ def LZCNT : VISInstFormat<0b000010111, (outs I64Regs:$rd),
(ins I64Regs:$rs2), "lzcnt $rs2, $rd">;
let rs1 = 0 in {
-def MOVSTOSW : VISInstFormat<0b100010011, (outs I64Regs:$rd),
- (ins DFPRegs:$rs2), "movstosw $rs2, $rd">;
-def MOVSTOUW : VISInstFormat<0b100010001, (outs I64Regs:$rd),
- (ins DFPRegs:$rs2), "movstouw $rs2, $rd">;
+def MOVSTOSW : VISInstFormat<0b100010011, (outs IntRegs:$rd),
+ (ins FPRegs:$rs2), "movstosw $rs2, $rd">;
+def MOVSTOUW : VISInstFormat<0b100010001, (outs IntRegs:$rd),
+ (ins FPRegs:$rs2), "movstouw $rs2, $rd">;
def MOVDTOX : VISInstFormat<0b100010000, (outs I64Regs:$rd),
(ins DFPRegs:$rs2), "movdtox $rs2, $rd">;
-def MOVWTOS : VISInstFormat<0b100011001, (outs DFPRegs:$rd),
- (ins I64Regs:$rs2), "movwtos $rs2, $rd">;
+def MOVWTOS : VISInstFormat<0b100011001, (outs FPRegs:$rd),
+ (ins IntRegs:$rs2), "movwtos $rs2, $rd">;
def MOVXTOD : VISInstFormat<0b100011000, (outs DFPRegs:$rd),
(ins I64Regs:$rs2), "movxtod $rs2, $rd">;
}
@@ -277,3 +277,43 @@ def UMULXHI : VISInst<0b000010110, "umulxhi", I64Regs>;
def XMULX : VISInst<0b100010101, "xmulx", I64Regs>;
def XMULXHI : VISInst<0b100010110, "xmulxhi", I64Regs>;
} // Predicates = [IsVIS3]
+
+// FP immediate patterns.
+def fpimm0 : PatLeaf<(fpimm), [{return N->isExactlyValue(+0.0);}]>;
+def fpnegimm0 : PatLeaf<(fpimm), [{return N->isExactlyValue(-0.0);}]>;
+
+// VIS instruction patterns.
+let Predicates = [HasVIS] in {
+// Zero immediate.
+def : Pat<(f64 fpimm0), (FZERO)>;
+def : Pat<(f32 fpimm0), (FZEROS)>;
+def : Pat<(f64 fpnegimm0), (FNEGD (FZERO))>;
+def : Pat<(f32 fpnegimm0), (FNEGS (FZEROS))>;
+} // Predicates = [HasVIS]
+
+// VIS3 instruction patterns.
+let Predicates = [HasVIS3] in {
+def : Pat<(i64 (adde i64:$lhs, i64:$rhs)), (ADDXCCC $lhs, $rhs)>;
+
+def : Pat<(i64 (mulhu i64:$lhs, i64:$rhs)), (UMULXHI $lhs, $rhs)>;
+// Signed "MULXHI".
+// Based on the formula presented in OSA2011 ยง7.140, but with bitops to select
+// the values to be added.
+def : Pat<(i64 (mulhs i64:$lhs, i64:$rhs)),
+ (SUBrr (UMULXHI $lhs, $rhs),
+ (ADDrr (ANDrr (SRAXri $lhs, 63), $rhs),
+ (ANDrr (SRAXri $rhs, 63), $lhs)))>;
+
+def : Pat<(i64 (ctlz 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.
+def : Pat<(i32 (ctlz i32:$src)), (ADDri (LZCNT (SRLri $src, 0)), (i32 -32))>;
+
+def : Pat<(i32 (bitconvert f32:$src)), (MOVSTOUW $src)>;
+def : Pat<(i64 (zext (i32 (bitconvert f32:$src)))), (MOVSTOUW $src)>;
+def : Pat<(i64 (sext (i32 (bitconvert f32:$src)))), (MOVSTOSW $src)>;
+def : Pat<(f32 (bitconvert i32:$src)), (MOVWTOS $src)>;
+def : Pat<(i64 (bitconvert f64:$src)), (MOVDTOX $src)>;
+def : Pat<(f64 (bitconvert i64:$src)), (MOVXTOD $src)>;
+} // Predicates = [HasVIS3]
diff --git a/llvm/test/CodeGen/SPARC/2011-01-11-CC.ll b/llvm/test/CodeGen/SPARC/2011-01-11-CC.ll
index 1560bc687b7dd..e05c47bfee766 100644
--- a/llvm/test/CodeGen/SPARC/2011-01-11-CC.ll
+++ b/llvm/test/CodeGen/SPARC/2011-01-11-CC.ll
@@ -2,6 +2,7 @@
; RUN: llc -mtriple=sparc %s -o - | FileCheck %s -check-prefix=V8
; RUN: llc -mtriple=sparc -mattr=v9 %s -o - | FileCheck %s -check-prefix=V9
; RUN: llc -mtriple=sparc64-unknown-linux %s -o - | FileCheck %s -check-prefix=SPARC64
+; RUN: llc -mtriple=sparc64-unknown-linux -mattr=vis3 %s -o - | FileCheck %s -check-prefix=SPARC64-VIS3
define i32 @test_addx(i64 %a, i64 %b, i64 %c) nounwind {
; V8-LABEL: test_addx:
@@ -60,6 +61,15 @@ define i32 @test_addx(i64 %a, i64 %b, i64 %c) nounwind {
; SPARC64-NEXT: movgu %xcc, 1, %o3
; SPARC64-NEXT: retl
; SPARC64-NEXT: srl %o3, 0, %o0
+;
+; SPARC64-VIS3-LABEL: test_addx:
+; SPARC64-VIS3: ! %bb.0: ! %entry
+; SPARC64-VIS3-NEXT: mov %g0, %o3
+; SPARC64-VIS3-NEXT: add %o0, %o1, %o0
+; SPARC64-VIS3-NEXT: cmp %o0, %o2
+; SPARC64-VIS3-NEXT: movgu %xcc, 1, %o3
+; SPARC64-VIS3-NEXT: retl
+; SPARC64-VIS3-NEXT: srl %o3, 0, %o0
entry:
%0 = add i64 %a, %b
%1 = icmp ugt i64 %0, %c
@@ -92,6 +102,13 @@ define i32 @test_select_int_icc(i32 %a, i32 %b, i32 %c) nounwind {
; SPARC64-NEXT: move %icc, %o1, %o2
; SPARC64-NEXT: retl
; SPARC64-NEXT: mov %o2, %o0
+;
+; SPARC64-VIS3-LABEL: test_select_int_icc:
+; SPARC64-VIS3: ! %bb.0: ! %entry
+; SPARC64-VIS3-NEXT: cmp %o0, 0
+; SPARC64-VIS3-NEXT: move %icc, %o1, %o2
+; SPARC64-VIS3-NEXT: retl
+; SPARC64-VIS3-NEXT: mov %o2, %o0
entry:
%0 = icmp eq i32 %a, 0
%1 = select i1 %0, i32 %b, i32 %c
@@ -133,6 +150,13 @@ define float @test_select_fp_icc(i32 %a, float %f1, float %f2) nounwind {
; SPARC64-NEXT: cmp %o0, 0
; SPARC64-NEXT: retl
; SPARC64-NEXT: fmovse %icc, %f3, %f0
+;
+; SPARC64-VIS3-LABEL: test_select_fp_icc:
+; SPARC64-VIS3: ! %bb.0: ! %entry
+; SPARC64-VIS3-NEXT: fmovs %f5, %f0
+; SPARC64-VIS3-NEXT: cmp %o0, 0
+; SPARC64-VIS3-NEXT: retl
+; SPARC64-VIS3-NEXT: fmovse %icc, %f3, %f0
entry:
%0 = icmp eq i32 %a, 0
%1 = select i1 %0, float %f1, float %f2
@@ -182,6 +206,13 @@ define double @test_select_dfp_icc(i32 %a, double %f1, double %f2) nounwind {
; SPARC64-NEXT: cmp %o0, 0
; SPARC64-NEXT: retl
; SPARC64-NEXT: fmovde %icc, %f2, %f0
+;
+; SPARC64-VIS3-LABEL: test_select_dfp_icc:
+; SPARC64-VIS3: ! %bb.0: ! %entry
+; SPARC64-VIS3-NEXT: fmovd %f4, %f0
+; SPARC64-VIS3-NEXT: cmp %o0, 0
+; SPARC64-VIS3-NEXT: retl
+; SPARC64-VIS3-NEXT: fmovde %icc, %f2, %f0
entry:
%0 = icmp eq i32 %a, 0
%1 = select i1 %0, double %f1, double %f2
@@ -229,6 +260,17 @@ define i32 @test_select_int_fcc(float %f, i32 %a, i32 %b) nounwind {
; SPARC64-NEXT: fcmps %fcc0, %f1, %f0
; SPARC64-NEXT: retl
; SPARC64-NEXT: movne %fcc0, %o1, %o0
+;
+; SPARC64-VIS3-LABEL: test_select_int_fcc:
+; SPARC64-VIS3: ! %bb.0: ! %entry
+; SPARC64-VIS3-NEXT: sethi %h44(.LCPI4_0), %o0
+; SPARC64-VIS3-NEXT: add %o0, %m44(.LCPI4_0), %o0
+; SPARC64-VIS3-NEXT: sllx %o0, 12, %o0
+; SPARC64-VIS3-NEXT: ld [%o0+%l44(.LCPI4_0)], %f0
+; SPARC64-VIS3-NEXT: mov %o2, %o0
+; SPARC64-VIS3-NEXT: fcmps %fcc0, %f1, %f0
+; SPARC64-VIS3-NEXT: retl
+; SPARC64-VIS3-NEXT: movne %fcc0, %o1, %o0
entry:
%0 = fcmp une float %f, 0.000000e+00
%a.b = select i1 %0, i32 %a, i32 %b
@@ -284,6 +326,17 @@ define float @test_select_fp_fcc(float %f, float %f1, float %f2) nounwind {
; SPARC64-NEXT: fcmps %fcc0, %f1, %f2
; SPARC64-NEXT: retl
; SPARC64-NEXT: fmovsne %fcc0, %f3, %f0
+;
+; SPARC64-VIS3-LABEL: test_select_fp_fcc:
+; SPARC64-VIS3: ! %bb.0: ! %entry
+; SPARC64-VIS3-NEXT: sethi %h44(.LCPI5_0), %o0
+; SPARC64-VIS3-NEXT: add %o0, %m44(.LCPI5_0), %o0
+; SPARC64-VIS3-NEXT: sllx %o0, 12, %o0
+; SPARC64-VIS3-NEXT: ld [%o0+%l44(.LCPI5_0)], %f2
+; SPARC64-VIS3-NEXT: fmovs %f5, %f0
+; SPARC64-VIS3-NEXT: fcmps %fcc0, %f1, %f2
+; SPARC64-VIS3-NEXT: retl
+; SPARC64-VIS3-NEXT: fmovsne %fcc0, %f3, %f0
entry:
%0 = fcmp une float %f, 0.000000e+00
%1 = select i1 %0, float %f1, float %f2
@@ -352,6 +405,18 @@ define double @test_select_dfp_fcc(double %f, double %f1, double %f2) nounwind {
; SPARC64-NEXT: fmovd %f4, %f0
; SPARC64-NEXT: retl
; SPARC64-NEXT: nop
+;
+; SPARC64-VIS3-LABEL: test_select_dfp_fcc:
+; SPARC64-VIS3: ! %bb.0: ! %entry
+; SPARC64-VIS3-NEXT: sethi %h44(.LCPI6_0), %o0
+; SPARC64-VIS3-NEXT: add %o0, %m44(.LCPI6_0), %o0
+; SPARC64-VIS3-NEXT: sllx %o0, 12, %o0
+; SPARC64-VIS3-NEXT: ldd [%o0+%l44(.LCPI6_0)], %f6
+; SPARC64-VIS3-NEXT: fcmpd %fcc0, %f0, %f6
+; SPARC64-VIS3-NEXT: fmovdne %fcc0, %f2, %f4
+; SPARC64-VIS3-NEXT: fmovd %f4, %f0
+; SPARC64-VIS3-NEXT: retl
+; SPARC64-VIS3-NEXT: nop
entry:
%0 = fcmp une double %f, 0.000000e+00
%1 = select i1 %0, double %f1, double %f2
@@ -453,6 +518,31 @@ define i32 @test_float_cc(double %a, double %b, i32 %c, i32 %d) nounwind {
; SPARC64-NEXT: ! %bb.4: ! %exit.0
; SPARC64-NEXT: retl
; SPARC64-NEXT: mov %g0, %o0
+;
+; SPARC64-VIS3-LABEL: test_float_cc:
+; SPARC64-VIS3: ! %bb.0: ! %entry
+; SPARC64-VIS3-NEXT: sethi %h44(.LCPI7_0), %o0
+; SPARC64-VIS3-NEXT: add %o0, %m44(.LCPI7_0), %o0
+; SPARC64-VIS3-NEXT: sllx %o0, 12, %o0
+; SPARC64-VIS3-NEXT: ldd [%o0+%l44(.LCPI7_0)], %f4
+; SPARC64-VIS3-NEXT: fcmpd %fcc0, %f0, %f4
+; SPARC64-VIS3-NEXT: fbuge %fcc0, .LBB7_3
+; SPARC64-VIS3-NEXT: nop
+; SPARC64-VIS3-NEXT: ! %bb.1: ! %loop.2
+; SPARC64-VIS3-NEXT: fcmpd %fcc0, %f2, %f4
+; SPARC64-VIS3-NEXT: fbule %fcc0, .LBB7_3
+; SPARC64-VIS3-NEXT: nop
+; SPARC64-VIS3-NEXT: ! %bb.2: ! %exit.1
+; SPARC64-VIS3-NEXT: retl
+; SPARC64-VIS3-NEXT: mov 1, %o0
+; SPARC64-VIS3-NEXT: .LBB7_3: ! %loop
+; SPARC64-VIS3-NEXT: ! =>This Inner Loop Header: Depth=1
+; SPARC64-VIS3-NEXT: cmp %o2, 10
+; SPARC64-VIS3-NEXT: be %icc, .LBB7_3
+; SPARC64-VIS3-NEXT: nop
+; SPARC64-VIS3-NEXT: ! %bb.4: ! %exit.0
+; SPARC64-VIS3-NEXT: retl
+; SPARC64-VIS3-NEXT: mov %g0, %o0
entry:
%0 = fcmp uge double %a, 0.000000e+00
br i1 %0, label %loop, label %loop.2
@@ -558,6 +648,34 @@ define void @test_adde_sube(ptr %a, ptr %b, ptr %sum, ptr %diff) nounwind {
; SPARC64-NEXT: stx %i0, [%i3]
; SPARC64-NEXT: ret
; SPARC64-NEXT: restore
+;
+; SPARC64-VIS3-LABEL: test_adde_sube:
+; SPARC64-VIS3: .register %g2, #scratch
+; SPARC64-VIS3-NEXT: ! %bb.0: ! %entry
+; SPARC64-VIS3-NEXT: save %sp, -128, %sp
+; SPARC64-VIS3-NEXT: ldx [%i0+8], %i4
+; SPARC64-VIS3-NEXT: ldx [%i0], %i5
+; SPARC64-VIS3-NEXT: ldx [%i1+8], %g2
+; SPARC64-VIS3-NEXT: ldx [%i1], %i1
+; SPARC64-VIS3-NEXT: addcc %i4, %g2, %g2
+; SPARC64-VIS3-NEXT: addxccc %i5, %i1, %i1
+; SPARC64-VIS3-NEXT: stx %i1, [%i2]
+; SPARC64-VIS3-NEXT: stx %g2, [%i2+8]
+; SPARC64-VIS3-NEXT: !APP
+; SPARC64-VIS3-NEXT: !NO_APP
+; SPARC64-VIS3-NEXT: ldx [%i0+8], %i1
+; SPARC64-VIS3-NEXT: mov %g0, %i2
+; SPARC64-VIS3-NEXT: ldx [%i0], %i0
+; SPARC64-VIS3-NEXT: cmp %i4, %i1
+; SPARC64-VIS3-NEXT: movcs %xcc, 1, %i2
+; SPARC64-VIS3-NEXT: srl %i2, 0, %i2
+; SPARC64-VIS3-NEXT: sub %i5, %i0, %i0
+; SPARC64-VIS3-NEXT: sub %i0, %i2, %i0
+; SPARC64-VIS3-NEXT: sub %i4, %i1, %i1
+; SPARC64-VIS3-NEXT: stx %i1, [%i3+8]
+; SPARC64-VIS3-NEXT: stx %i0, [%i3]
+; SPARC64-VIS3-NEXT: ret
+; SPARC64-VIS3-NEXT: restore
entry:
%0 = bitcast ptr %a to ptr
%1 = bitcast ptr %b to ptr
diff --git a/llvm/test/CodeGen/SPARC/bitcast.ll b/llvm/test/CodeGen/SPARC/bitcast.ll
new file mode 100644
index 0000000000000..d5fb994a0f0fe
--- /dev/null
+++ b/llvm/test/CodeGen/SPARC/bitcast.ll
@@ -0,0 +1,139 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=sparcv9 | FileCheck %s -check-prefix=V9
+; RUN: llc < %s -mtriple=sparcv9 -mattr=vis3 | FileCheck %s -check-prefix=VIS3
+
+define i32 @stow(float %0) nounwind {
+; V9-LABEL: stow:
+; V9: ! %bb.0:
+; V9-NEXT: add %sp, -144, %sp
+; V9-NEXT: st %f1, [%sp+2187]
+; V9-NEXT: ld [%sp+2187], %o0
+; V9-NEXT: retl
+; V9-NEXT: add %sp, 144, %sp
+;
+; VIS3-LABEL: stow:
+; VIS3: ! %bb.0:
+; VIS3-NEXT: retl
+; VIS3-NEXT: movstouw %f1, %o0
+ %2 = bitcast float %0 to i32
+ ret i32 %2
+}
+
+define zeroext i32 @stouw(float %0) nounwind {
+; V9-LABEL: stouw:
+; V9: ! %bb.0:
+; V9-NEXT: add %sp, -144, %sp
+; V9-NEXT: st %f1, [%sp+2187]
+; V9-NEXT: ld [%sp+2187], %o0
+; V9-NEXT: retl
+; V9-NEXT: add %sp, 144, %sp
+;
+; VIS3-LABEL: stouw:
+; VIS3: ! %bb.0:
+; VIS3-NEXT: retl
+; VIS3-NEXT: movstouw %f1, %o0
+ %2 = bitcast float %0 to i32
+ ret i32 %2
+}
+
+define signext i32 @stosw(float %0) nounwind {
+; V9-LABEL: stosw:
+; V9: ! %bb.0:
+; V9-NEXT: add %sp, -144, %sp
+; V9-NEXT: st %f1, [%sp+2187]
+; V9-NEXT: ldsw [%sp+2187], %o0
+; V9-NEXT: retl
+; V9-NEXT: add %sp, 144, %sp
+;
+; VIS3-LABEL: stosw:
+; VIS3: ! %bb.0:
+; VIS3-NEXT: retl
+; VIS3-NEXT: movstosw %f1, %o0
+ %2 = bitcast float %0 to i32
+ ret i32 %2
+}
+
+define float @wtos(i32 %0) nounwind {
+; V9-LABEL: wtos:
+; V9: ! %bb.0:
+; V9-NEXT: add %sp, -144, %sp
+; V9-NEXT: st %o0, [%sp+2187]
+; V9-NEXT: ld [%sp+2187], %f0
+; V9-NEXT: retl
+; V9-NEXT: add %sp, 144, %sp
+;
+; VIS3-LABEL: wtos:
+; VIS3: ! %bb.0:
+; VIS3-NEXT: retl
+; VIS3-NEXT: movwtos %o0, %f0
+ %2 = bitcast i32 %0 to float
+ ret float %2
+}
+
+define float @uwtos(i32 zeroext %0) nounwind {
+; V9-LABEL: uwtos:
+; V9: ! %bb.0:
+; V9-NEXT: add %sp, -144, %sp
+; V9-NEXT: st %o0, [%sp+2187]
+; V9-NEXT: ld [%sp+2187], %f0
+; V9-NEXT: retl
+; V9-NEXT: add %sp, 144, %sp
+;
+; VIS3-LABEL: uwtos:
+; VIS3: ! %bb.0:
+; VIS3-NEXT: retl
+; VIS3-NEXT: movwtos %o0, %f0
+ %2 = bitcast i32 %0 to float
+ ret float %2
+}
+
+define float @swtos(i32 signext %0) nounwind {
+; V9-LABEL: swtos:
+; V9: ! %bb.0:
+; V9-NEXT: add %sp, -144, %sp
+; V9-NEXT: st %o0, [%sp+2187]
+; V9-NEXT: ld [%sp+2187], %f0
+; V9-NEXT: retl
+; V9-NEXT: add %sp, 144, %sp
+;
+; VIS3-LABEL: swtos:
+; VIS3: ! %bb.0:
+; VIS3-NEXT: retl
+; VIS3-NEXT: movwtos %o0, %f0
+ %2 = bitcast i32 %0 to float
+ ret float %2
+}
+
+define i64 @dtox(double %0) nounwind {
+; V9-LABEL: dtox:
+; V9: ! %bb.0:
+; V9-NEXT: add %sp, -144, %sp
+; V9-NEXT: std %f0, [%sp+2183]
+; V9-NEXT: ldx [%sp+2183], %o0
+; V9-NEXT: retl
+; V9-NEXT: add %sp, 144, %sp
+;
+; VIS3-LABEL: dtox:
+; VIS3: ! %bb.0:
+; VIS3-NEXT: retl
+; VIS3-NEXT: movdtox %f0, %o0
+ %2 = bitcast double %0 to i64
+ ret i64 %2
+}
+
+define double @xtod(i64 %0) nounwind {
+; V9-LABEL: xtod:
+; V9: ! %bb.0:
+; V9-NEXT: add %sp, -144, %sp
+; V9-NEXT: stx %o0, [%sp+2183]
+; V9-NEXT: ldd [%sp+2183], %f0
+; V9-NEXT: retl
+; V9-NEXT: add %sp, 144, %sp
+;
+; VIS3-LABEL: xtod:
+; VIS3: ! %bb.0:
+; VIS3-NEXT: retl
+; VIS3-NEXT: movxtod %o0, %f0
+ %2 = bitcast i64 %0 to double
+ ret double %2
+}
diff --git a/llvm/test/CodeGen/SPARC/ctlz.ll b/llvm/test/CodeGen/SPARC/ctlz.ll
new file mode 100644
index 0000000000000..3b2fc0dbfd4a3
--- /dev/null
+++ b/llvm/test/CodeGen/SPARC/ctlz.ll
@@ -0,0 +1,171 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=sparcv9 | FileCheck %s -check-prefix=V9
+; RUN: llc < %s -mtriple=sparcv9 -mattr=popc | FileCheck %s -check-prefix=POPC
+; RUN: llc < %s -mtriple=sparcv9 -mattr=vis3 | FileCheck %s -check-prefix=VIS3
+
+define i32 @f(i32 %x) nounwind {
+; V9-LABEL: f:
+; V9: ! %bb.0: ! %entry
+; V9-NEXT: srl %o0, 1, %o1
+; V9-NEXT: or %o0, %o1, %o1
+; V9-NEXT: srl %o1, 2, %o2
+; V9-NEXT: or %o1, %o2, %o1
+; V9-NEXT: srl %o1, 4, %o2
+; V9-NEXT: or %o1, %o2, %o1
+; V9-NEXT: srl %o1, 8, %o2
+; V9-NEXT: or %o1, %o2, %o1
+; V9-NEXT: srl %o1, 16, %o2
+; V9-NEXT: or %o1, %o2, %o1
+; V9-NEXT: xor %o1, -1, %o1
+; V9-NEXT: srl %o1, 1, %o2
+; V9-NEXT: sethi 1398101, %o3
+; V9-NEXT: or %o3, 341, %o3
+; V9-NEXT: and %o2, %o3, %o2
+; V9-NEXT: sub %o1, %o2, %o1
+; V9-NEXT: sethi 838860, %o2
+; V9-NEXT: or %o2, 819, %o2
+; V9-NEXT: and %o1, %o2, %o3
+; V9-NEXT: srl %o1, 2, %o1
+; V9-NEXT: and %o1, %o2, %o1
+; V9-NEXT: add %o3, %o1, %o1
+; V9-NEXT: srl %o1, 4, %o2
+; V9-NEXT: add %o1, %o2, %o1
+; V9-NEXT: sethi 246723, %o2
+; V9-NEXT: or %o2, 783, %o2
+; V9-NEXT: and %o1, %o2, %o1
+; V9-NEXT: sll %o1, 8, %o2
+; V9-NEXT: add %o1, %o2, %o1
+; V9-NEXT: sll %o1, 16, %o2
+; V9-NEXT: add %o1, %o2, %o1
+; V9-NEXT: srl %o1, 24, %o1
+; V9-NEXT: cmp %o0, 0
+; V9-NEXT: move %icc, 0, %o1
+; V9-NEXT: retl
+; V9-NEXT: mov %o1, %o0
+;
+; POPC-LABEL: f:
+; POPC: ! %bb.0: ! %entry
+; POPC-NEXT: srl %o0, 1, %o1
+; POPC-NEXT: or %o0, %o1, %o1
+; POPC-NEXT: srl %o1, 2, %o2
+; POPC-NEXT: or %o1, %o2, %o1
+; POPC-NEXT: srl %o1, 4, %o2
+; POPC-NEXT: or %o1, %o2, %o1
+; POPC-NEXT: srl %o1, 8, %o2
+; POPC-NEXT: or %o1, %o2, %o1
+; POPC-NEXT: srl %o1, 16, %o2
+; POPC-NEXT: or %o1, %o2, %o1
+; POPC-NEXT: xor %o1, -1, %o1
+; POPC-NEXT: srl %o1, 0, %o1
+; POPC-NEXT: popc %o1, %o1
+; POPC-NEXT: cmp %o0, 0
+; POPC-NEXT: move %icc, 0, %o1
+; POPC-NEXT: retl
+; POPC-NEXT: mov %o1, %o0
+;
+; VIS3-LABEL: f:
+; VIS3: ! %bb.0: ! %entry
+; VIS3-NEXT: srl %o0, 0, %o1
+; VIS3-NEXT: lzcnt %o1, %o1
+; VIS3-NEXT: add %o1, -32, %o1
+; VIS3-NEXT: cmp %o0, 0
+; VIS3-NEXT: move %icc, 0, %o1
+; VIS3-NEXT: retl
+; VIS3-NEXT: mov %o1, %o0
+entry:
+ %0 = call i32 @llvm.ctlz.i32(i32 %x, i1 true)
+ %1 = icmp eq i32 %x, 0
+ %2 = select i1 %1, i32 0, i32 %0
+ %3 = trunc i32 %2 to i8
+ %conv = zext i8 %3 to i32
+ ret i32 %conv
+}
+
+define i64 @g(i64 %x) nounwind {
+; V9-LABEL: g:
+; V9: ! %bb.0: ! %entry
+; V9-NEXT: srlx %o0, 1, %o1
+; V9-NEXT: or %o0, %o1, %o1
+; V9-NEXT: srlx %o1, 2, %o2
+; V9-NEXT: or %o1, %o2, %o1
+; V9-NEXT: srlx %o1, 4, %o2
+; V9-NEXT: or %o1, %o2, %o1
+; V9-NEXT: srlx %o1, 8, %o2
+; V9-NEXT: or %o1, %o2, %o1
+; V9-NEXT: srlx %o1, 16, %o2
+; V9-NEXT: or %o1, %o2, %o1
+; V9-NEXT: srlx %o1, 32, %o2
+; V9-NEXT: or %o1, %o2, %o1
+; V9-NEXT: xor %o1, -1, %o1
+; V9-NEXT: srlx %o1, 1, %o2
+; V9-NEXT: sethi 1398101, %o3
+; V9-NEXT: or %o3, 341, %o3
+; V9-NEXT: sllx %o3, 32, %o4
+; V9-NEXT: or %o4, %o3, %o3
+; V9-NEXT: and %o2, %o3, %o2
+; V9-NEXT: sub %o1, %o2, %o1
+; V9-NEXT: sethi 838860, %o2
+; V9-NEXT: or %o2, 819, %o2
+; V9-NEXT: sllx %o2, 32, %o3
+; V9-NEXT: or %o3, %o2, %o2
+; V9-NEXT: and %o1, %o2, %o3
+; V9-NEXT: srlx %o1, 2, %o1
+; V9-NEXT: and %o1, %o2, %o1
+; V9-NEXT: add %o3, %o1, %o1
+; V9-NEXT: srlx %o1, 4, %o2
+; V9-NEXT: add %o1, %o2, %o1
+; V9-NEXT: sethi 246723, %o2
+; V9-NEXT: or %o2, 783, %o2
+; V9-NEXT: sllx %o2, 32, %o3
+; V9-NEXT: or %o3, %o2, %o2
+; V9-NEXT: and %o1, %o2, %o1
+; V9-NEXT: sethi 16448, %o2
+; V9-NEXT: or %o2, 257, %o2
+; V9-NEXT: sllx %o2, 32, %o3
+; V9-NEXT: or %o3, %o2, %o2
+; V9-NEXT: mulx %o1, %o2, %o1
+; V9-NEXT: srlx %o1, 56, %o1
+; V9-NEXT: movrz %o0, 0, %o1
+; V9-NEXT: retl
+; V9-NEXT: mov %o1, %o0
+;
+; POPC-LABEL: g:
+; POPC: ! %bb.0: ! %entry
+; POPC-NEXT: srlx %o0, 1, %o1
+; POPC-NEXT: or %o0, %o1, %o1
+; POPC-NEXT: srlx %o1, 2, %o2
+; POPC-NEXT: or %o1, %o2, %o1
+; POPC-NEXT: srlx %o1, 4, %o2
+; POPC-NEXT: or %o1, %o2, %o1
+; POPC-NEXT: srlx %o1, 8, %o2
+; POPC-NEXT: or %o1, %o2, %o1
+; POPC-NEXT: srlx %o1, 16, %o2
+; POPC-NEXT: or %o1, %o2, %o1
+; POPC-NEXT: srlx %o1, 32, %o2
+; POPC-NEXT: or %o1, %o2, %o1
+; POPC-NEXT: xor %o1, -1, %o1
+; POPC-NEXT: popc %o1, %o1
+; POPC-NEXT: movrz %o0, 0, %o1
+; POPC-NEXT: retl
+; POPC-NEXT: mov %o1, %o0
+;
+; VIS3-LABEL: g:
+; VIS3: ! %bb.0: ! %entry
+; VIS3-NEXT: lzcnt %o0, %o1
+; VIS3-NEXT: movrz %o0, 0, %o1
+; VIS3-NEXT: retl
+; VIS3-NEXT: mov %o1, %o0
+entry:
+ %0 = call i64 @llvm.ctlz.i64(i64 %x, i1 true)
+ %1 = icmp eq i64 %x, 0
+ %2 = select i1 %1, i64 0, i64 %0
+ %3 = trunc i64 %2 to i32
+ %conv = zext i32 %3 to i64
+ ret i64 %conv
+}
+
+; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn
+declare i32 @llvm.ctlz.i32(i32, i1 immarg) #0
+declare i64 @llvm.ctlz.i64(i64, i1 immarg) #0
+
+attributes #0 = { nocallback nofree nosync nounwind readnone speculatable willreturn }
diff --git a/llvm/test/CodeGen/SPARC/float-constants.ll b/llvm/test/CodeGen/SPARC/float-constants.ll
index b04ec68ed3d7e..440c75bfca9f9 100644
--- a/llvm/test/CodeGen/SPARC/float-constants.ll
+++ b/llvm/test/CodeGen/SPARC/float-constants.ll
@@ -1,6 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
; RUN: llc < %s -mtriple=sparc | FileCheck %s
; RUN: llc < %s -mtriple=sparcel | FileCheck %s --check-prefix=CHECK-LE
+; RUN: llc < %s -mtriple=sparcv9 -mattr=+vis | FileCheck %s --check-prefix=CHECK-VIS
;; Bitcast should not do a runtime conversion, but rather emit a
;; constant into integer registers directly.
@@ -17,6 +18,12 @@ define <2 x i32> @bitcast() nounwind {
; CHECK-LE-NEXT: sethi 1049856, %o1
; CHECK-LE-NEXT: retl
; CHECK-LE-NEXT: mov %g0, %o0
+;
+; CHECK-VIS-LABEL: bitcast:
+; CHECK-VIS: ! %bb.0:
+; CHECK-VIS-NEXT: sethi 1049856, %o0
+; CHECK-VIS-NEXT: retl
+; CHECK-VIS-NEXT: mov %g0, %o1
%1 = bitcast double 5.0 to <2 x i32>
ret <2 x i32> %1
}
@@ -43,6 +50,17 @@ define void @test_call() nounwind {
; CHECK-LE-NEXT: mov %g0, %o0
; CHECK-LE-NEXT: ret
; CHECK-LE-NEXT: restore
+;
+; CHECK-VIS-LABEL: test_call:
+; CHECK-VIS: ! %bb.0:
+; CHECK-VIS-NEXT: save %sp, -176, %sp
+; CHECK-VIS-NEXT: sethi %h44(.LCPI1_0), %i0
+; CHECK-VIS-NEXT: add %i0, %m44(.LCPI1_0), %i0
+; CHECK-VIS-NEXT: sllx %i0, 12, %i0
+; CHECK-VIS-NEXT: call a
+; CHECK-VIS-NEXT: ldd [%i0+%l44(.LCPI1_0)], %f0
+; CHECK-VIS-NEXT: ret
+; CHECK-VIS-NEXT: restore
call void @a(double 5.0)
ret void
}
@@ -75,6 +93,103 @@ define double @test_intrins_call() nounwind {
; CHECK-LE-NEXT: mov %o1, %o3
; CHECK-LE-NEXT: ret
; CHECK-LE-NEXT: restore
+;
+; CHECK-VIS-LABEL: test_intrins_call:
+; CHECK-VIS: ! %bb.0:
+; CHECK-VIS-NEXT: save %sp, -176, %sp
+; CHECK-VIS-NEXT: sethi %h44(.LCPI2_0), %i0
+; CHECK-VIS-NEXT: add %i0, %m44(.LCPI2_0), %i0
+; CHECK-VIS-NEXT: sllx %i0, 12, %i0
+; CHECK-VIS-NEXT: ldd [%i0+%l44(.LCPI2_0)], %f0
+; CHECK-VIS-NEXT: fmovd %f0, %f2
+; CHECK-VIS-NEXT: call pow
+; CHECK-VIS-NEXT: nop
+; CHECK-VIS-NEXT: ret
+; CHECK-VIS-NEXT: restore
%1 = call double @llvm.pow.f64(double 2.0, double 2.0)
ret double %1
}
+
+;; When we have VIS, f32/f64 zero constant should be materialized from fzero/fzeros.
+
+define double @pos_zero_double() nounwind {
+; CHECK-LABEL: pos_zero_double:
+; CHECK: ! %bb.0:
+; CHECK-NEXT: sethi %hi(.LCPI3_0), %o0
+; CHECK-NEXT: retl
+; CHECK-NEXT: ldd [%o0+%lo(.LCPI3_0)], %f0
+;
+; CHECK-LE-LABEL: pos_zero_double:
+; CHECK-LE: ! %bb.0:
+; CHECK-LE-NEXT: sethi %hi(.LCPI3_0), %o0
+; CHECK-LE-NEXT: retl
+; CHECK-LE-NEXT: ldd [%o0+%lo(.LCPI3_0)], %f0
+;
+; CHECK-VIS-LABEL: pos_zero_double:
+; CHECK-VIS: ! %bb.0:
+; CHECK-VIS-NEXT: retl
+; CHECK-VIS-NEXT: fzero %f0
+ ret double +0.0
+}
+
+define double @neg_zero_double() nounwind {
+; CHECK-LABEL: neg_zero_double:
+; CHECK: ! %bb.0:
+; CHECK-NEXT: sethi %hi(.LCPI4_0), %o0
+; CHECK-NEXT: retl
+; CHECK-NEXT: ldd [%o0+%lo(.LCPI4_0)], %f0
+;
+; CHECK-LE-LABEL: neg_zero_double:
+; CHECK-LE: ! %bb.0:
+; CHECK-LE-NEXT: sethi %hi(.LCPI4_0), %o0
+; CHECK-LE-NEXT: retl
+; CHECK-LE-NEXT: ldd [%o0+%lo(.LCPI4_0)], %f0
+;
+; CHECK-VIS-LABEL: neg_zero_double:
+; CHECK-VIS: ! %bb.0:
+; CHECK-VIS-NEXT: fzero %f0
+; CHECK-VIS-NEXT: retl
+; CHECK-VIS-NEXT: fnegd %f0, %f0
+ ret double -0.0
+}
+
+define float @pos_zero_float() nounwind {
+; CHECK-LABEL: pos_zero_float:
+; CHECK: ! %bb.0:
+; CHECK-NEXT: sethi %hi(.LCPI5_0), %o0
+; CHECK-NEXT: retl
+; CHECK-NEXT: ld [%o0+%lo(.LCPI5_0)], %f0
+;
+; CHECK-LE-LABEL: pos_zero_float:
+; CHECK-LE: ! %bb.0:
+; CHECK-LE-NEXT: sethi %hi(.LCPI5_0), %o0
+; CHECK-LE-NEXT: retl
+; CHECK-LE-NEXT: ld [%o0+%lo(.LCPI5_0)], %f0
+;
+; CHECK-VIS-LABEL: pos_zero_float:
+; CHECK-VIS: ! %bb.0:
+; CHECK-VIS-NEXT: retl
+; CHECK-VIS-NEXT: fzeros %f0
+ ret float +0.0
+}
+
+define float @neg_zero_float() nounwind {
+; CHECK-LABEL: neg_zero_float:
+; CHECK: ! %bb.0:
+; CHECK-NEXT: sethi %hi(.LCPI6_0), %o0
+; CHECK-NEXT: retl
+; CHECK-NEXT: ld [%o0+%lo(.LCPI6_0)], %f0
+;
+; CHECK-LE-LABEL: neg_zero_float:
+; CHECK-LE: ! %bb.0:
+; CHECK-LE-NEXT: sethi %hi(.LCPI6_0), %o0
+; CHECK-LE-NEXT: retl
+; CHECK-LE-NEXT: ld [%o0+%lo(.LCPI6_0)], %f0
+;
+; CHECK-VIS-LABEL: neg_zero_float:
+; CHECK-VIS: ! %bb.0:
+; CHECK-VIS-NEXT: fzeros %f0
+; CHECK-VIS-NEXT: retl
+; CHECK-VIS-NEXT: fnegs %f0, %f0
+ ret float -0.0
+}
diff --git a/llvm/test/CodeGen/SPARC/multiply-extension.ll b/llvm/test/CodeGen/SPARC/multiply-extension.ll
new file mode 100644
index 0000000000000..4d752ff101ca2
--- /dev/null
+++ b/llvm/test/CodeGen/SPARC/multiply-extension.ll
@@ -0,0 +1,59 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=sparcv9 | FileCheck %s -check-prefix=V9
+; RUN: llc < %s -mtriple=sparcv9 -mattr=+vis3 | FileCheck %s -check-prefix=VIS3
+
+define i128 @signed_multiply_extend(i64 %0, i64 %1) nounwind {
+; V9-LABEL: signed_multiply_extend:
+; V9: ! %bb.0:
+; V9-NEXT: save %sp, -176, %sp
+; V9-NEXT: srax %i0, 63, %o2
+; V9-NEXT: srax %i1, 63, %o0
+; V9-NEXT: mov %i1, %o1
+; V9-NEXT: call __multi3
+; V9-NEXT: mov %i0, %o3
+; V9-NEXT: mov %o0, %i0
+; V9-NEXT: ret
+; V9-NEXT: restore %g0, %o1, %o1
+;
+; VIS3-LABEL: signed_multiply_extend:
+; VIS3: ! %bb.0:
+; VIS3-NEXT: srax %o0, 63, %o2
+; VIS3-NEXT: and %o2, %o1, %o2
+; VIS3-NEXT: srax %o1, 63, %o3
+; VIS3-NEXT: and %o3, %o0, %o3
+; VIS3-NEXT: add %o3, %o2, %o2
+; VIS3-NEXT: umulxhi %o1, %o0, %o3
+; VIS3-NEXT: sub %o3, %o2, %o2
+; VIS3-NEXT: mulx %o1, %o0, %o1
+; VIS3-NEXT: retl
+; VIS3-NEXT: mov %o2, %o0
+ %3 = sext i64 %0 to i128
+ %4 = sext i64 %1 to i128
+ %5 = mul nsw i128 %4, %3
+ ret i128 %5
+}
+
+define i128 @unsigned_multiply_extend(i64 %0, i64 %1) nounwind {
+; V9-LABEL: unsigned_multiply_extend:
+; V9: ! %bb.0:
+; V9-NEXT: save %sp, -176, %sp
+; V9-NEXT: mov %g0, %o0
+; V9-NEXT: mov %i1, %o1
+; V9-NEXT: mov %g0, %o2
+; V9-NEXT: call __multi3
+; V9-NEXT: mov %i0, %o3
+; V9-NEXT: mov %o0, %i0
+; V9-NEXT: ret
+; V9-NEXT: restore %g0, %o1, %o1
+;
+; VIS3-LABEL: unsigned_multiply_extend:
+; VIS3: ! %bb.0:
+; VIS3-NEXT: umulxhi %o1, %o0, %o2
+; VIS3-NEXT: mulx %o1, %o0, %o1
+; VIS3-NEXT: retl
+; VIS3-NEXT: mov %o2, %o0
+ %3 = zext i64 %0 to i128
+ %4 = zext i64 %1 to i128
+ %5 = mul nuw i128 %4, %3
+ ret i128 %5
+}
diff --git a/llvm/test/CodeGen/SPARC/smulo-128-legalisation-lowering.ll b/llvm/test/CodeGen/SPARC/smulo-128-legalisation-lowering.ll
index 07e4c408a3ff0..1e5ab7922de08 100644
--- a/llvm/test/CodeGen/SPARC/smulo-128-legalisation-lowering.ll
+++ b/llvm/test/CodeGen/SPARC/smulo-128-legalisation-lowering.ll
@@ -1,6 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=sparc-unknown-linux-gnu | FileCheck %s --check-prefixes=SPARC
; RUN: llc < %s -mtriple=sparc64-unknown-linux-gnu | FileCheck %s --check-prefixes=SPARC64
+; RUN: llc < %s -mtriple=sparc64-unknown-linux-gnu -mattr=vis3 | FileCheck %s --check-prefixes=SPARC64-VIS3
define { i128, i8 } @muloti_test(i128 %l, i128 %r) nounwind {
; SPARC-LABEL: muloti_test:
@@ -213,6 +214,49 @@ define { i128, i8 } @muloti_test(i128 %l, i128 %r) nounwind {
; SPARC64-NEXT: srl %i3, 0, %i2
; SPARC64-NEXT: ret
; SPARC64-NEXT: restore
+;
+; SPARC64-VIS3-LABEL: muloti_test:
+; SPARC64-VIS3: .register %g2, #scratch
+; SPARC64-VIS3-NEXT: .register %g3, #scratch
+; SPARC64-VIS3-NEXT: ! %bb.0: ! %start
+; SPARC64-VIS3-NEXT: save %sp, -128, %sp
+; SPARC64-VIS3-NEXT: mov %g0, %i5
+; SPARC64-VIS3-NEXT: umulxhi %i0, %i3, %i4
+; SPARC64-VIS3-NEXT: srax %i0, 63, %g2
+; SPARC64-VIS3-NEXT: mulx %g2, %i3, %g3
+; SPARC64-VIS3-NEXT: add %i4, %g3, %i4
+; SPARC64-VIS3-NEXT: umulxhi %i1, %i3, %g3
+; SPARC64-VIS3-NEXT: mulx %i0, %i3, %g4
+; SPARC64-VIS3-NEXT: addcc %g4, %g3, %g3
+; SPARC64-VIS3-NEXT: addxccc %i4, %g0, %g4
+; SPARC64-VIS3-NEXT: umulxhi %i1, %i2, %i4
+; SPARC64-VIS3-NEXT: srax %i2, 63, %g5
+; SPARC64-VIS3-NEXT: mulx %i1, %g5, %l0
+; SPARC64-VIS3-NEXT: add %i4, %l0, %l0
+; SPARC64-VIS3-NEXT: mulx %i1, %i2, %i4
+; SPARC64-VIS3-NEXT: addcc %i4, %g3, %i4
+; SPARC64-VIS3-NEXT: addxccc %l0, %g0, %g3
+; SPARC64-VIS3-NEXT: srax %g3, 63, %l0
+; SPARC64-VIS3-NEXT: addcc %g4, %g3, %g3
+; SPARC64-VIS3-NEXT: srax %g4, 63, %g4
+; SPARC64-VIS3-NEXT: addxccc %g4, %l0, %g4
+; SPARC64-VIS3-NEXT: and %g5, %i0, %g5
+; SPARC64-VIS3-NEXT: and %g2, %i2, %g2
+; SPARC64-VIS3-NEXT: add %g2, %g5, %g2
+; SPARC64-VIS3-NEXT: umulxhi %i0, %i2, %g5
+; SPARC64-VIS3-NEXT: sub %g5, %g2, %g2
+; SPARC64-VIS3-NEXT: mulx %i0, %i2, %i0
+; SPARC64-VIS3-NEXT: addcc %i0, %g3, %i0
+; SPARC64-VIS3-NEXT: addxccc %g2, %g4, %i2
+; SPARC64-VIS3-NEXT: srax %i4, 63, %g2
+; SPARC64-VIS3-NEXT: xor %i2, %g2, %i2
+; SPARC64-VIS3-NEXT: xor %i0, %g2, %i0
+; SPARC64-VIS3-NEXT: or %i0, %i2, %i0
+; SPARC64-VIS3-NEXT: movrnz %i0, 1, %i5
+; SPARC64-VIS3-NEXT: mulx %i1, %i3, %i1
+; SPARC64-VIS3-NEXT: srl %i5, 0, %i2
+; SPARC64-VIS3-NEXT: ret
+; SPARC64-VIS3-NEXT: restore %g0, %i4, %o0
start:
%0 = tail call { i128, i1 } @llvm.smul.with.overflow.i128(i128 %l, i128 %r)
%1 = extractvalue { i128, i1 } %0, 0
diff --git a/llvm/test/CodeGen/SPARC/umulo-128-legalisation-lowering.ll b/llvm/test/CodeGen/SPARC/umulo-128-legalisation-lowering.ll
index 01383a00c2619..3bdb45ae51a93 100644
--- a/llvm/test/CodeGen/SPARC/umulo-128-legalisation-lowering.ll
+++ b/llvm/test/CodeGen/SPARC/umulo-128-legalisation-lowering.ll
@@ -1,6 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=sparc-unknown-linux-gnu | FileCheck %s --check-prefixes=SPARC
; RUN: llc < %s -mtriple=sparc64-unknown-linux-gnu | FileCheck %s --check-prefixes=SPARC64
+; RUN: llc < %s -mtriple=sparc64-unknown-linux-gnu -mattr=vis3 | FileCheck %s --check-prefixes=SPARC64-VIS3
define { i128, i8 } @muloti_test(i128 %l, i128 %r) nounwind {
; SPARC-LABEL: muloti_test:
@@ -199,6 +200,38 @@ define { i128, i8 } @muloti_test(i128 %l, i128 %r) nounwind {
; SPARC64-NEXT: mov %i1, %i0
; SPARC64-NEXT: ret
; SPARC64-NEXT: restore %g0, %o1, %o1
+;
+; SPARC64-VIS3-LABEL: muloti_test:
+; SPARC64-VIS3: .register %g2, #scratch
+; SPARC64-VIS3-NEXT: .register %g3, #scratch
+; SPARC64-VIS3-NEXT: ! %bb.0: ! %start
+; SPARC64-VIS3-NEXT: save %sp, -128, %sp
+; SPARC64-VIS3-NEXT: mov %g0, %i5
+; SPARC64-VIS3-NEXT: mov %g0, %g2
+; SPARC64-VIS3-NEXT: mov %g0, %g3
+; SPARC64-VIS3-NEXT: mov %g0, %g4
+; SPARC64-VIS3-NEXT: mov %g0, %g5
+; SPARC64-VIS3-NEXT: mulx %i2, %i1, %i4
+; SPARC64-VIS3-NEXT: mulx %i0, %i3, %l0
+; SPARC64-VIS3-NEXT: add %l0, %i4, %i4
+; SPARC64-VIS3-NEXT: umulxhi %i1, %i3, %l0
+; SPARC64-VIS3-NEXT: add %l0, %i4, %i4
+; SPARC64-VIS3-NEXT: cmp %i4, %l0
+; SPARC64-VIS3-NEXT: movrnz %i2, 1, %g2
+; SPARC64-VIS3-NEXT: movrnz %i0, 1, %g3
+; SPARC64-VIS3-NEXT: and %g3, %g2, %g2
+; SPARC64-VIS3-NEXT: umulxhi %i0, %i3, %i0
+; SPARC64-VIS3-NEXT: movrnz %i0, 1, %g4
+; SPARC64-VIS3-NEXT: movcs %xcc, 1, %i5
+; SPARC64-VIS3-NEXT: or %g2, %g4, %i0
+; SPARC64-VIS3-NEXT: umulxhi %i2, %i1, %i2
+; SPARC64-VIS3-NEXT: movrnz %i2, 1, %g5
+; SPARC64-VIS3-NEXT: or %i0, %g5, %i0
+; SPARC64-VIS3-NEXT: or %i0, %i5, %i0
+; SPARC64-VIS3-NEXT: mulx %i1, %i3, %i1
+; SPARC64-VIS3-NEXT: srl %i0, 0, %i2
+; SPARC64-VIS3-NEXT: ret
+; SPARC64-VIS3-NEXT: restore %g0, %i4, %o0
start:
%0 = tail call { i128, i1 } @llvm.umul.with.overflow.i128(i128 %l, i128 %r)
%1 = extractvalue { i128, i1 } %0, 0
More information about the llvm-commits
mailing list