[llvm] [SPARC][IAS] Implement Solaris Natural Instruction extension (PR #170794)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Jan 3 05:45:31 PST 2026
https://github.com/koachan updated https://github.com/llvm/llvm-project/pull/170794
>From fdc01436d512d317cfafc5857d2890e3a8dd3487 Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Thu, 20 Nov 2025 21:29:02 +0700
Subject: [PATCH 1/5] [WIP][SPARC][IAS] Implement Solaris Natural Instruction
extension
We match GCC's coverage of the extension, that is, everything except `setn`
and `setnhi`.
See also: https://docs.oracle.com/cd/E53394_01/html/E54833/gmael.html
---
.../Sparc/MCTargetDesc/SparcMCTargetDesc.cpp | 5 +-
llvm/lib/Target/Sparc/Sparc.td | 12 +-
llvm/lib/Target/Sparc/SparcInstrAliases.td | 108 +++++++++++++++---
llvm/lib/Target/Sparc/SparcInstrInfo.td | 5 +-
llvm/lib/Target/Sparc/SparcSubtarget.cpp | 7 +-
.../MC/Sparc/sparc-natural-instructions.s | 42 +++++++
6 files changed, 153 insertions(+), 26 deletions(-)
create mode 100644 llvm/test/MC/Sparc/sparc-natural-instructions.s
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
index 9fa60ee5229ba..862ba3c64958d 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
@@ -85,10 +85,13 @@ createSparcMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
MCSubtargetInfo *STI =
createSparcMCSubtargetInfoImpl(TT, CPU, /*TuneCPU=*/CPU, FS);
+ FeatureBitset Features = STI->getFeatureBits();
if (TT.isSPARC64() && !STI->hasFeature(Sparc::Feature64Bit)) {
- FeatureBitset Features = STI->getFeatureBits();
STI->setFeatureBits(Features.set(Sparc::Feature64Bit));
+ } else if (!TT.isSPARC64() && !STI->hasFeature(Sparc::Feature32Bit)) {
+ STI->setFeatureBits(Features.set(Sparc::Feature32Bit));
}
+ assert(Features.test(Sparc::Feature32Bit) != Features.test(Sparc::Feature64Bit));
return STI;
}
diff --git a/llvm/lib/Target/Sparc/Sparc.td b/llvm/lib/Target/Sparc/Sparc.td
index ecf82fab5cc41..2ef8d7e57f398 100644
--- a/llvm/lib/Target/Sparc/Sparc.td
+++ b/llvm/lib/Target/Sparc/Sparc.td
@@ -23,20 +23,15 @@ include "llvm/TableGen/SearchableTable.td"
def FeatureSoftMulDiv
: SubtargetFeature<"soft-mul-div", "UseSoftMulDiv", "true",
"Use software emulation for integer multiply and divide">;
-
def FeatureNoFSMULD
: SubtargetFeature<"no-fsmuld", "HasNoFSMULD", "true",
"Disable the fsmuld instruction.">;
def FeatureNoFMULS
: SubtargetFeature<"no-fmuls", "HasNoFMULS", "true",
"Disable the fmuls instruction.">;
-
def FeatureV9
: SubtargetFeature<"v9", "IsV9", "true",
"Enable SPARC-V9 instructions">;
-def Feature64Bit : SubtargetFeature<"64bit", "Is64Bit", "true",
- "Enable 64-bit mode", [FeatureV9]>;
-
def FeatureV8Plus
: SubtargetFeature<"v8plus", "IsV8Plus", "true",
"Enable V8+ mode, allowing use of 64-bit V9 instructions in 32-bit code">;
@@ -77,17 +72,18 @@ def FeatureLeon
def FeaturePWRPSR
: SubtargetFeature<"leonpwrpsr", "HasPWRPSR", "true",
"Enable the PWRPSR instruction">;
-
def FeatureHardQuad
: SubtargetFeature<"hard-quad-float", "HasHardQuad", "true",
"Enable quad-word floating point instructions">;
-
def UsePopc : SubtargetFeature<"popc", "UsePopc", "true",
"Use the popc (population count) instruction">;
def FeatureSoftFloat : SubtargetFeature<"soft-float", "UseSoftFloat", "true",
"Use software emulation for floating point">;
-
+def Feature32Bit : SubtargetFeature<"32bit", "Is32Bit", "true",
+ "Enable 32-bit mode">;
+def Feature64Bit : SubtargetFeature<"64bit", "Is64Bit", "true",
+ "Enable 64-bit mode", [FeatureV9]>;
//===----------------------------------------------------------------------===//
// SPARC Subtarget tuning features.
//
diff --git a/llvm/lib/Target/Sparc/SparcInstrAliases.td b/llvm/lib/Target/Sparc/SparcInstrAliases.td
index 459fd193db0ed..bc87ab2539e9c 100644
--- a/llvm/lib/Target/Sparc/SparcInstrAliases.td
+++ b/llvm/lib/Target/Sparc/SparcInstrAliases.td
@@ -101,114 +101,168 @@ multiclass int_cond_alias<string cond, int condVal> {
// b<cond> %icc, $imm
def : InstAlias<!strconcat(!strconcat("b", cond), " %icc, $imm"),
(BPICC brtarget:$imm, condVal)>, Requires<[HasV9]>;
+ def : InstAlias<!strconcat(!strconcat("b", cond), " %ncc, $imm"),
+ (BPICC brtarget:$imm, condVal)>, Requires<[HasV9, Is32Bit]>;
// b<cond>,pt %icc, $imm
def : InstAlias<!strconcat(!strconcat("b", cond), ",pt %icc, $imm"),
(BPICC brtarget:$imm, condVal)>, Requires<[HasV9]>;
+ def : InstAlias<!strconcat(!strconcat("b", cond), ",pt %ncc, $imm"),
+ (BPICC brtarget:$imm, condVal)>, Requires<[HasV9, Is32Bit]>;
// b<cond>,a %icc, $imm
def : InstAlias<!strconcat(!strconcat("b", cond), ",a %icc, $imm"),
(BPICCA brtarget:$imm, condVal)>, Requires<[HasV9]>;
+ def : InstAlias<!strconcat(!strconcat("b", cond), ",a %ncc, $imm"),
+ (BPICCA brtarget:$imm, condVal)>, Requires<[HasV9, Is32Bit]>;
// b<cond>,a,pt %icc, $imm
def : InstAlias<!strconcat(!strconcat("b", cond), ",a,pt %icc, $imm"),
(BPICCA brtarget:$imm, condVal)>, Requires<[HasV9]>;
+ def : InstAlias<!strconcat(!strconcat("b", cond), ",a,pt %ncc, $imm"),
+ (BPICCA brtarget:$imm, condVal)>, Requires<[HasV9, Is32Bit]>;
// b<cond>,pn %icc, $imm
def : InstAlias<!strconcat(!strconcat("b", cond), ",pn %icc, $imm"),
(BPICCNT brtarget:$imm, condVal)>, Requires<[HasV9]>;
+ def : InstAlias<!strconcat(!strconcat("b", cond), ",pn %ncc, $imm"),
+ (BPICCNT brtarget:$imm, condVal)>, Requires<[HasV9, Is32Bit]>;
// b<cond>,a,pn %icc, $imm
def : InstAlias<!strconcat(!strconcat("b", cond), ",a,pn %icc, $imm"),
(BPICCANT brtarget:$imm, condVal)>, Requires<[HasV9]>;
+ def : InstAlias<!strconcat(!strconcat("b", cond), ",a,pn %ncc, $imm"),
+ (BPICCANT brtarget:$imm, condVal)>, Requires<[HasV9, Is32Bit]>;
// b<cond> %xcc, $imm
def : InstAlias<!strconcat(!strconcat("b", cond), " %xcc, $imm"),
(BPXCC brtarget:$imm, condVal)>, Requires<[Is64Bit]>;
+ def : InstAlias<!strconcat(!strconcat("b", cond), " %ncc, $imm"),
+ (BPXCC brtarget:$imm, condVal)>, Requires<[Is64Bit]>;
// b<cond>,pt %xcc, $imm
def : InstAlias<!strconcat(!strconcat("b", cond), ",pt %xcc, $imm"),
(BPXCC brtarget:$imm, condVal)>, Requires<[Is64Bit]>;
+ def : InstAlias<!strconcat(!strconcat("b", cond), ",pt %ncc, $imm"),
+ (BPXCC brtarget:$imm, condVal)>, Requires<[Is64Bit]>;
// b<cond>,a %xcc, $imm
def : InstAlias<!strconcat(!strconcat("b", cond), ",a %xcc, $imm"),
(BPXCCA brtarget:$imm, condVal)>, Requires<[Is64Bit]>;
+ def : InstAlias<!strconcat(!strconcat("b", cond), ",a %ncc, $imm"),
+ (BPXCCA brtarget:$imm, condVal)>, Requires<[Is64Bit]>;
// b<cond>,a,pt %xcc, $imm
def : InstAlias<!strconcat(!strconcat("b", cond), ",a,pt %xcc, $imm"),
(BPXCCA brtarget:$imm, condVal)>, Requires<[Is64Bit]>;
+ def : InstAlias<!strconcat(!strconcat("b", cond), ",a,pt %ncc, $imm"),
+ (BPXCCA brtarget:$imm, condVal)>, Requires<[Is64Bit]>;
// b<cond>,pn %xcc, $imm
def : InstAlias<!strconcat(!strconcat("b", cond), ",pn %xcc, $imm"),
(BPXCCNT brtarget:$imm, condVal)>, Requires<[Is64Bit]>;
+ def : InstAlias<!strconcat(!strconcat("b", cond), ",pn %ncc, $imm"),
+ (BPXCCNT brtarget:$imm, condVal)>, Requires<[Is64Bit]>;
// b<cond>,a,pn %xcc, $imm
def : InstAlias<!strconcat(!strconcat("b", cond), ",a,pn %xcc, $imm"),
(BPXCCANT brtarget:$imm, condVal)>, Requires<[Is64Bit]>;
-
+ def : InstAlias<!strconcat(!strconcat("b", cond), ",a,pn %ncc, $imm"),
+ (BPXCCANT brtarget:$imm, condVal)>, Requires<[Is64Bit]>;
defm : intcond_mov_alias<cond, condVal, " %icc",
MOVICCrr, MOVICCri,
FMOVS_ICC, FMOVD_ICC>, Requires<[HasV9]>;
+ defm : intcond_mov_alias<cond, condVal, " %ncc",
+ MOVICCrr, MOVICCri,
+ FMOVS_ICC, FMOVD_ICC>, Requires<[Is32Bit, HasV9]>;
+
defm : intcond_mov_alias<cond, condVal, " %xcc",
MOVXCCrr, MOVXCCri,
FMOVS_XCC, FMOVD_XCC>, Requires<[Is64Bit]>;
+ defm : intcond_mov_alias<cond, condVal, " %ncc",
+ MOVXCCrr, MOVXCCri,
+ FMOVS_XCC, FMOVD_XCC>, Requires<[Is64Bit]>;
+
// fmovq<cond> (%icc|%xcc), $rs2, $rd
def : InstAlias<!strconcat(!strconcat("fmovq", cond), " %icc, $rs2, $rd"),
(FMOVQ_ICC QFPRegs:$rd, QFPRegs:$rs2, condVal)>,
Requires<[HasV9, HasHardQuad]>;
+ def : InstAlias<!strconcat(!strconcat("fmovq", cond), " %ncc, $rs2, $rd"),
+ (FMOVQ_ICC QFPRegs:$rd, QFPRegs:$rs2, condVal)>,
+ Requires<[HasV9, Is32Bit, HasHardQuad]>;
def : InstAlias<!strconcat(!strconcat("fmovq", cond), " %xcc, $rs2, $rd"),
(FMOVQ_XCC QFPRegs:$rd, QFPRegs:$rs2, condVal)>,
Requires<[Is64Bit, HasHardQuad]>;
+ def : InstAlias<!strconcat(!strconcat("fmovq", cond), " %ncc, $rs2, $rd"),
+ (FMOVQ_XCC QFPRegs:$rd, QFPRegs:$rs2, condVal)>,
+ Requires<[Is64Bit, HasHardQuad]>;
// t<cond> %icc, rs => t<cond> %icc, G0 + rs
def : InstAlias<!strconcat(!strconcat("t", cond), " %icc, $rs2"),
(TICCrr G0, IntRegs:$rs2, condVal)>,
Requires<[HasV9]>;
+ def : InstAlias<!strconcat(!strconcat("t", cond), " %ncc, $rs2"),
+ (TICCrr G0, IntRegs:$rs2, condVal)>,
+ Requires<[HasV9, Is32Bit]>;
+
// t<cond> %icc, rs1 + rs2
def : InstAlias<!strconcat(!strconcat("t", cond), " %icc, $rs1 + $rs2"),
(TICCrr IntRegs:$rs1, IntRegs:$rs2, condVal)>,
Requires<[HasV9]>;
-
+ def : InstAlias<!strconcat(!strconcat("t", cond), " %ncc, $rs1 + $rs2"),
+ (TICCrr IntRegs:$rs1, IntRegs:$rs2, condVal)>,
+ Requires<[HasV9, Is32Bit]>;
// t<cond> %xcc, rs => t<cond> %xcc, G0 + rs
def : InstAlias<!strconcat(!strconcat("t", cond), " %xcc, $rs2"),
(TXCCrr G0, IntRegs:$rs2, condVal)>,
Requires<[HasV9]>;
+ def : InstAlias<!strconcat(!strconcat("t", cond), " %ncc, $rs2"),
+ (TXCCrr G0, IntRegs:$rs2, condVal)>,
+ Requires<[HasV9, Is64Bit]>;
+
// t<cond> %xcc, rs1 + rs2
def : InstAlias<!strconcat(!strconcat("t", cond), " %xcc, $rs1 + $rs2"),
(TXCCrr IntRegs:$rs1, IntRegs:$rs2, condVal)>,
Requires<[HasV9]>;
-
-
- // t<cond> rs=> t<cond> %icc, G0 + rs2
- //def : InstAlias<!strconcat(!strconcat("t", cond), " $rs2"),
- // (TICCrr G0, IntRegs:$rs2, condVal)>,
- // Requires<[HasV9]>;
-
- // t<cond> rs1 + rs2 => t<cond> %icc, rs1 + rs2
- //def : InstAlias<!strconcat(!strconcat("t", cond), " $rs1 + $rs2"),
- // (TICCrr IntRegs:$rs1, IntRegs:$rs2, condVal)>,
- // Requires<[HasV9]>;
+ def : InstAlias<!strconcat(!strconcat("t", cond), " %ncc, $rs1 + $rs2"),
+ (TXCCrr IntRegs:$rs1, IntRegs:$rs2, condVal)>,
+ Requires<[HasV9, Is64Bit]>;
// t<cond> %icc, imm => t<cond> %icc, G0 + imm
def : InstAlias<!strconcat(!strconcat("t", cond), " %icc, $imm"),
(TICCri G0, i32imm:$imm, condVal)>,
Requires<[HasV9]>;
+ def : InstAlias<!strconcat(!strconcat("t", cond), " %ncc, $imm"),
+ (TICCri G0, i32imm:$imm, condVal)>,
+ Requires<[HasV9, Is32Bit]>;
+
// t<cond> %icc, rs1 + imm
def : InstAlias<!strconcat(!strconcat("t", cond), " %icc, $rs1 + $imm"),
(TICCri IntRegs:$rs1, i32imm:$imm, condVal)>,
Requires<[HasV9]>;
+ def : InstAlias<!strconcat(!strconcat("t", cond), " %ncc, $rs1 + $imm"),
+ (TICCri IntRegs:$rs1, i32imm:$imm, condVal)>,
+ Requires<[HasV9, Is32Bit]>;
+
// t<cond> %xcc, imm => t<cond> %xcc, G0 + imm
def : InstAlias<!strconcat(!strconcat("t", cond), " %xcc, $imm"),
(TXCCri G0, i32imm:$imm, condVal)>,
Requires<[HasV9]>;
+ def : InstAlias<!strconcat(!strconcat("t", cond), " %ncc, $imm"),
+ (TXCCri G0, i32imm:$imm, condVal)>,
+ Requires<[HasV9, Is64Bit]>;
+
// t<cond> %xcc, rs1 + imm
def : InstAlias<!strconcat(!strconcat("t", cond), " %xcc, $rs1 + $imm"),
(TXCCri IntRegs:$rs1, i32imm:$imm, condVal)>,
Requires<[HasV9]>;
+ def : InstAlias<!strconcat(!strconcat("t", cond), " %ncc, $rs1 + $imm"),
+ (TXCCri IntRegs:$rs1, i32imm:$imm, condVal)>,
+ Requires<[HasV9, Is64Bit]>;
// t<cond> imm => t<cond> G0 + imm
def : InstAlias<!strconcat(!strconcat("t", cond), " $imm"),
@@ -599,7 +653,8 @@ def : InstAlias<"clrh [$addr]", (STHrr MEMrr:$addr, G0), 0>;
def : InstAlias<"clrh [$addr]", (STHri MEMri:$addr, G0), 0>;
def : InstAlias<"clr [$addr]", (STrr MEMrr:$addr, G0), 0>;
def : InstAlias<"clr [$addr]", (STri MEMri:$addr, G0), 0>;
-
+def : InstAlias<"clrx [$addr]", (STXrr MEMrr:$addr, G0), 0>, Requires<[HasV9]>;
+def : InstAlias<"clrx [$addr]", (STXri MEMri:$addr, G0), 0>, Requires<[HasV9]>;
// mov reg_or_imm, rd -> or %g0, reg_or_imm, rd
def : InstAlias<"mov $rs2, $rd", (ORrr IntRegs:$rd, G0, IntRegs:$rs2)>;
@@ -701,6 +756,31 @@ def : MnemonicAlias<"addccc", "addxcc">, Requires<[HasV9]>;
def : MnemonicAlias<"subc", "subx">, Requires<[HasV9]>;
def : MnemonicAlias<"subccc", "subxcc">, Requires<[HasV9]>;
+// Solaris Natural Instructions extension
+// We match GCC's coverage of the extension; everything except setn & setnhi.
+// See also: https://docs.oracle.com/cd/E53394_01/html/E54833/gmael.html
+let Predicates = [Is32Bit] in {
+ def : MnemonicAlias<"ldn", "ld">;
+ def : MnemonicAlias<"stn", "st">;
+ def : MnemonicAlias<"ldna", "lda">;
+ def : MnemonicAlias<"stna", "sta">;
+ def : MnemonicAlias<"casn", "cas">;
+ def : MnemonicAlias<"slln", "sll">;
+ def : MnemonicAlias<"srln", "srl">;
+ def : MnemonicAlias<"sran", "sra">;
+ def : MnemonicAlias<"clrn", "clr">;
+}
+let Predicates = [Is64Bit] in {
+ def : MnemonicAlias<"ldn", "ldx">;
+ def : MnemonicAlias<"stn", "stx">;
+ def : MnemonicAlias<"ldna", "ldxa">;
+ def : MnemonicAlias<"stna", "stxa">;
+ def : MnemonicAlias<"casn", "casx">;
+ def : MnemonicAlias<"slln", "sllx">;
+ def : MnemonicAlias<"srln", "srlx">;
+ def : MnemonicAlias<"sran", "srax">;
+ def : MnemonicAlias<"clrn", "clrx">;
+}
def : InstAlias<"fcmps $rs1, $rs2", (V9FCMPS FCC0, FPRegs:$rs1, FPRegs:$rs2)>;
def : InstAlias<"fcmpd $rs1, $rs2", (V9FCMPD FCC0, DFPRegs:$rs1, DFPRegs:$rs2)>;
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td
index 107817fcab6df..2a02a10da21ec 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.td
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td
@@ -21,11 +21,12 @@ include "SparcInstrFormats.td"
//===----------------------------------------------------------------------===//
// True when generating 32-bit code.
-def Is32Bit : Predicate<"!Subtarget->is64Bit()">;
+def Is32Bit : Predicate<"!Subtarget->is64Bit()">,
+ AssemblerPredicate<(all_of Feature32Bit)>;
// True when generating 64-bit code. This also implies HasV9.
def Is64Bit : Predicate<"Subtarget->is64Bit()">,
- AssemblerPredicate<(all_of FeatureV9)>;
+ AssemblerPredicate<(all_of FeatureV9, Feature64Bit)>;
def UseSoftMulDiv : Predicate<"Subtarget->useSoftMulDiv()">,
AssemblerPredicate<(all_of FeatureSoftMulDiv)>;
diff --git a/llvm/lib/Target/Sparc/SparcSubtarget.cpp b/llvm/lib/Target/Sparc/SparcSubtarget.cpp
index 1d72d0bdada03..51e59d1a85321 100644
--- a/llvm/lib/Target/Sparc/SparcSubtarget.cpp
+++ b/llvm/lib/Target/Sparc/SparcSubtarget.cpp
@@ -40,11 +40,16 @@ SparcSubtarget &SparcSubtarget::initializeSubtargetDependencies(
// Parse features string.
ParseSubtargetFeatures(CPUName, TuneCPU, FS);
+ FeatureBitset Features = getFeatureBits();
if (!Is64Bit && TT.isSPARC64()) {
- FeatureBitset Features = getFeatureBits();
setFeatureBits(Features.set(Sparc::Feature64Bit));
Is64Bit = true;
+ } else if (!Is32Bit && !TT.isSPARC64()) {
+ setFeatureBits(Features.set(Sparc::Feature32Bit));
+ Is32Bit = true;
}
+ assert(Features.test(Sparc::Feature32Bit) != Features.test(Sparc::Feature64Bit));
+ assert(Is32Bit != Is64Bit);
// Popc is a v9-only instruction.
if (!IsV9)
diff --git a/llvm/test/MC/Sparc/sparc-natural-instructions.s b/llvm/test/MC/Sparc/sparc-natural-instructions.s
new file mode 100644
index 0000000000000..4f223497b2556
--- /dev/null
+++ b/llvm/test/MC/Sparc/sparc-natural-instructions.s
@@ -0,0 +1,42 @@
+! RUN: llvm-mc %s -triple=sparc -mcpu=v9 -show-encoding | FileCheck %s --check-prefixes=SPARC32
+! RUN: llvm-mc %s -triple=sparcv9 -mcpu=v9 -show-encoding | FileCheck %s --check-prefixes=SPARC64
+
+!! Solaris Natural Instructions.
+
+! SPARC32: .word 305419896
+! SPARC64: .xword 305419896
+.nword 0x12345678
+
+! SPARC32: ld [%o0+8], %g1 ! encoding: [0xc2,0x02,0x20,0x08]
+! SPARC64: ldx [%o0+8], %g1 ! encoding: [0xc2,0x5a,0x20,0x08]
+ldn [%o0 + 8], %g1
+! SPARC32: st %g1, [%o0+8] ! encoding: [0xc2,0x22,0x20,0x08]
+! SPARC64: stx %g1, [%o0+8] ! encoding: [0xc2,0x72,0x20,0x08]
+stn %g1, [%o0 + 8]
+! SPARC32: lda [%o0] #ASI_AIUP, %g1 ! encoding: [0xc2,0x82,0x02,0x00]
+! SPARC64: ldxa [%o0] #ASI_AIUP, %g1 ! encoding: [0xc2,0xda,0x02,0x00]
+ldna [%o0] 0x10, %g1
+! SPARC32: sta %g1, [%o0] #ASI_AIUP ! encoding: [0xc2,0xa2,0x02,0x00]
+! SPARC64: stxa %g1, [%o0] #ASI_AIUP ! encoding: [0xc2,0xf2,0x02,0x00]
+stna %g1, [%o0] 0x10
+! SPARC32: cas [%o0], %g0, %g1 ! encoding: [0xc3,0xe2,0x10,0x00]
+! SPARC64: casx [%o0], %g0, %g1 ! encoding: [0xc3,0xf2,0x10,0x00]
+casn [%o0], %g0, %g1
+! SPARC32: sll %g0, %g1, %g2 ! encoding: [0x85,0x28,0x00,0x01]
+! SPARC64: sllx %g0, %g1, %g2 ! encoding: [0x85,0x28,0x10,0x01]
+slln %g0, %g1, %g2
+! SPARC32: srl %g0, %g1, %g2 ! encoding: [0x85,0x30,0x00,0x01]
+! SPARC64: srlx %g0, %g1, %g2 ! encoding: [0x85,0x30,0x10,0x01]
+srln %g0, %g1, %g2
+! SPARC32: sra %g0, %g1, %g2 ! encoding: [0x85,0x38,0x00,0x01]
+! SPARC64: srax %g0, %g1, %g2 ! encoding: [0x85,0x38,0x10,0x01]
+sran %g0, %g1, %g2
+! SPARC32: st %g0, [%o0+8] ! encoding: [0xc0,0x22,0x20,0x08]
+! SPARC64: stx %g0, [%o0+8] ! encoding: [0xc0,0x72,0x20,0x08]
+clrn [%o0 + 8]
+
+ba %ncc, .
+ta %ncc, 0x6d
+move %ncc, %g1, %g2
+fmovse %ncc, %f0, %f1
+fmovse %ncc, %f0, %f2
>From fc7ff574995c63d959cc3846119ffa51596efa0d Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Sat, 6 Dec 2025 18:41:19 +0700
Subject: [PATCH 2/5] Fix formatting
---
llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp | 3 ++-
llvm/lib/Target/Sparc/SparcSubtarget.cpp | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
index 862ba3c64958d..3fac774f1fa60 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
@@ -91,7 +91,8 @@ createSparcMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
} else if (!TT.isSPARC64() && !STI->hasFeature(Sparc::Feature32Bit)) {
STI->setFeatureBits(Features.set(Sparc::Feature32Bit));
}
- assert(Features.test(Sparc::Feature32Bit) != Features.test(Sparc::Feature64Bit));
+ assert(Features.test(Sparc::Feature32Bit) !=
+ Features.test(Sparc::Feature64Bit));
return STI;
}
diff --git a/llvm/lib/Target/Sparc/SparcSubtarget.cpp b/llvm/lib/Target/Sparc/SparcSubtarget.cpp
index 51e59d1a85321..9d6473cc91684 100644
--- a/llvm/lib/Target/Sparc/SparcSubtarget.cpp
+++ b/llvm/lib/Target/Sparc/SparcSubtarget.cpp
@@ -48,7 +48,8 @@ SparcSubtarget &SparcSubtarget::initializeSubtargetDependencies(
setFeatureBits(Features.set(Sparc::Feature32Bit));
Is32Bit = true;
}
- assert(Features.test(Sparc::Feature32Bit) != Features.test(Sparc::Feature64Bit));
+ assert(Features.test(Sparc::Feature32Bit) !=
+ Features.test(Sparc::Feature64Bit));
assert(Is32Bit != Is64Bit);
// Popc is a v9-only instruction.
>From 6d2d6af2926b9881599735a47560ba8338b492c8 Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Thu, 1 Jan 2026 14:01:06 +0700
Subject: [PATCH 3/5] Apply suggestions
---
.../Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp | 4 ----
llvm/lib/Target/Sparc/Sparc.td | 12 ++++++++----
llvm/lib/Target/Sparc/SparcInstrInfo.td | 4 ++--
llvm/lib/Target/Sparc/SparcSubtarget.cpp | 6 ------
4 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
index 3fac774f1fa60..09e105a17e37d 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
@@ -88,11 +88,7 @@ createSparcMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
FeatureBitset Features = STI->getFeatureBits();
if (TT.isSPARC64() && !STI->hasFeature(Sparc::Feature64Bit)) {
STI->setFeatureBits(Features.set(Sparc::Feature64Bit));
- } else if (!TT.isSPARC64() && !STI->hasFeature(Sparc::Feature32Bit)) {
- STI->setFeatureBits(Features.set(Sparc::Feature32Bit));
}
- assert(Features.test(Sparc::Feature32Bit) !=
- Features.test(Sparc::Feature64Bit));
return STI;
}
diff --git a/llvm/lib/Target/Sparc/Sparc.td b/llvm/lib/Target/Sparc/Sparc.td
index 2ef8d7e57f398..ecf82fab5cc41 100644
--- a/llvm/lib/Target/Sparc/Sparc.td
+++ b/llvm/lib/Target/Sparc/Sparc.td
@@ -23,15 +23,20 @@ include "llvm/TableGen/SearchableTable.td"
def FeatureSoftMulDiv
: SubtargetFeature<"soft-mul-div", "UseSoftMulDiv", "true",
"Use software emulation for integer multiply and divide">;
+
def FeatureNoFSMULD
: SubtargetFeature<"no-fsmuld", "HasNoFSMULD", "true",
"Disable the fsmuld instruction.">;
def FeatureNoFMULS
: SubtargetFeature<"no-fmuls", "HasNoFMULS", "true",
"Disable the fmuls instruction.">;
+
def FeatureV9
: SubtargetFeature<"v9", "IsV9", "true",
"Enable SPARC-V9 instructions">;
+def Feature64Bit : SubtargetFeature<"64bit", "Is64Bit", "true",
+ "Enable 64-bit mode", [FeatureV9]>;
+
def FeatureV8Plus
: SubtargetFeature<"v8plus", "IsV8Plus", "true",
"Enable V8+ mode, allowing use of 64-bit V9 instructions in 32-bit code">;
@@ -72,18 +77,17 @@ def FeatureLeon
def FeaturePWRPSR
: SubtargetFeature<"leonpwrpsr", "HasPWRPSR", "true",
"Enable the PWRPSR instruction">;
+
def FeatureHardQuad
: SubtargetFeature<"hard-quad-float", "HasHardQuad", "true",
"Enable quad-word floating point instructions">;
+
def UsePopc : SubtargetFeature<"popc", "UsePopc", "true",
"Use the popc (population count) instruction">;
def FeatureSoftFloat : SubtargetFeature<"soft-float", "UseSoftFloat", "true",
"Use software emulation for floating point">;
-def Feature32Bit : SubtargetFeature<"32bit", "Is32Bit", "true",
- "Enable 32-bit mode">;
-def Feature64Bit : SubtargetFeature<"64bit", "Is64Bit", "true",
- "Enable 64-bit mode", [FeatureV9]>;
+
//===----------------------------------------------------------------------===//
// SPARC Subtarget tuning features.
//
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td
index 2a02a10da21ec..65d37599e6a8e 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.td
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td
@@ -22,11 +22,11 @@ include "SparcInstrFormats.td"
// True when generating 32-bit code.
def Is32Bit : Predicate<"!Subtarget->is64Bit()">,
- AssemblerPredicate<(all_of Feature32Bit)>;
+ AssemblerPredicate<(all_of (not Feature64Bit))>;
// True when generating 64-bit code. This also implies HasV9.
def Is64Bit : Predicate<"Subtarget->is64Bit()">,
- AssemblerPredicate<(all_of FeatureV9, Feature64Bit)>;
+ AssemblerPredicate<(all_of Feature64Bit)>;
def UseSoftMulDiv : Predicate<"Subtarget->useSoftMulDiv()">,
AssemblerPredicate<(all_of FeatureSoftMulDiv)>;
diff --git a/llvm/lib/Target/Sparc/SparcSubtarget.cpp b/llvm/lib/Target/Sparc/SparcSubtarget.cpp
index 9d6473cc91684..d053455243319 100644
--- a/llvm/lib/Target/Sparc/SparcSubtarget.cpp
+++ b/llvm/lib/Target/Sparc/SparcSubtarget.cpp
@@ -44,13 +44,7 @@ SparcSubtarget &SparcSubtarget::initializeSubtargetDependencies(
if (!Is64Bit && TT.isSPARC64()) {
setFeatureBits(Features.set(Sparc::Feature64Bit));
Is64Bit = true;
- } else if (!Is32Bit && !TT.isSPARC64()) {
- setFeatureBits(Features.set(Sparc::Feature32Bit));
- Is32Bit = true;
}
- assert(Features.test(Sparc::Feature32Bit) !=
- Features.test(Sparc::Feature64Bit));
- assert(Is32Bit != Is64Bit);
// Popc is a v9-only instruction.
if (!IsV9)
>From 69a5bf32c9136c0646337ff8af2991bf6b7375c7 Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Thu, 1 Jan 2026 14:54:36 +0700
Subject: [PATCH 4/5] Implement %ncc handling
---
.../Target/Sparc/AsmParser/SparcAsmParser.cpp | 6 ++++-
.../MC/Sparc/sparc-natural-instructions.s | 22 ++++++++++++++-----
2 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
index ef45d31a029d3..77b3634f4e405 100644
--- a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
+++ b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
@@ -1457,6 +1457,10 @@ SparcAsmParser::parseSparcAsmOperand(std::unique_ptr<SparcOperand> &Op) {
if (MCRegister Reg = matchRegisterName(Parser.getTok(), RegKind)) {
StringRef Name = Parser.getTok().getString();
Parser.Lex(); // Eat the identifier token.
+
+ if (Name == "ncc")
+ Name = is64Bit() ? "xcc" : "icc";
+
E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
if (Reg == Sparc::ICC && Name == "xcc")
Op = SparcOperand::CreateToken("%xcc", S);
@@ -1592,7 +1596,7 @@ MCRegister SparcAsmParser::matchRegisterName(const AsmToken &Tok,
return IntRegs[RegNo];
}
- if (Name == "xcc") {
+ if (Name == "xcc" || Name == "ncc") {
// FIXME:: check 64bit.
RegKind = SparcOperand::rk_Special;
return SP::ICC;
diff --git a/llvm/test/MC/Sparc/sparc-natural-instructions.s b/llvm/test/MC/Sparc/sparc-natural-instructions.s
index 4f223497b2556..ed295d4ff4d2e 100644
--- a/llvm/test/MC/Sparc/sparc-natural-instructions.s
+++ b/llvm/test/MC/Sparc/sparc-natural-instructions.s
@@ -3,8 +3,8 @@
!! Solaris Natural Instructions.
-! SPARC32: .word 305419896
-! SPARC64: .xword 305419896
+! SPARC32: .word 305419896
+! SPARC64: .xword 305419896
.nword 0x12345678
! SPARC32: ld [%o0+8], %g1 ! encoding: [0xc2,0x02,0x20,0x08]
@@ -19,8 +19,8 @@ ldna [%o0] 0x10, %g1
! SPARC32: sta %g1, [%o0] #ASI_AIUP ! encoding: [0xc2,0xa2,0x02,0x00]
! SPARC64: stxa %g1, [%o0] #ASI_AIUP ! encoding: [0xc2,0xf2,0x02,0x00]
stna %g1, [%o0] 0x10
-! SPARC32: cas [%o0], %g0, %g1 ! encoding: [0xc3,0xe2,0x10,0x00]
-! SPARC64: casx [%o0], %g0, %g1 ! encoding: [0xc3,0xf2,0x10,0x00]
+! SPARC32: cas [%o0], %g0, %g1 ! encoding: [0xc3,0xe2,0x10,0x00]
+! SPARC64: casx [%o0], %g0, %g1 ! encoding: [0xc3,0xf2,0x10,0x00]
casn [%o0], %g0, %g1
! SPARC32: sll %g0, %g1, %g2 ! encoding: [0x85,0x28,0x00,0x01]
! SPARC64: sllx %g0, %g1, %g2 ! encoding: [0x85,0x28,0x10,0x01]
@@ -35,8 +35,20 @@ sran %g0, %g1, %g2
! SPARC64: stx %g0, [%o0+8] ! encoding: [0xc0,0x72,0x20,0x08]
clrn [%o0 + 8]
+! SPARC32: ba %icc, .Ltmp0 ! encoding: [0x10,0b01001AAA,A,A]
+! SPARC32: ! fixup A - offset: 0, value: .Ltmp0, relocation type: 41
+! SPARC64: ba %xcc, .Ltmp0 ! encoding: [0x10,0b01101AAA,A,A]
+! SPARC64: ! fixup A - offset: 0, value: .Ltmp0, relocation type: 41
ba %ncc, .
+! SPARC32: ta %icc, 109 ! encoding: [0x91,0xd0,0x20,0x6d]
+! SPARC64: ta %xcc, 109 ! encoding: [0x91,0xd0,0x30,0x6d]
ta %ncc, 0x6d
+! SPARC32: move %icc, %g1, %g2 ! encoding: [0x85,0x64,0x40,0x01]
+! SPARC64: move %xcc, %g1, %g2 ! encoding: [0x85,0x64,0x50,0x01]
move %ncc, %g1, %g2
+! SPARC32: fmovse %icc, %f0, %f1 ! encoding: [0x83,0xa8,0x60,0x20]
+! SPARC64: fmovse %xcc, %f0, %f1 ! encoding: [0x83,0xa8,0x70,0x20]
fmovse %ncc, %f0, %f1
-fmovse %ncc, %f0, %f2
+! SPARC32: fmovde %icc, %f0, %f2 ! encoding: [0x85,0xa8,0x60,0x40]
+! SPARC64: fmovde %xcc, %f0, %f2 ! encoding: [0x85,0xa8,0x70,0x40]
+fmovde %ncc, %f0, %f2
>From 51e2dcd8c1f1635d202067cf2862f8be8cb8469b Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Sat, 3 Jan 2026 20:44:39 +0700
Subject: [PATCH 5/5] Add fmovq test
---
llvm/test/MC/Sparc/sparc-natural-instructions.s | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/llvm/test/MC/Sparc/sparc-natural-instructions.s b/llvm/test/MC/Sparc/sparc-natural-instructions.s
index ed295d4ff4d2e..71b18a2722248 100644
--- a/llvm/test/MC/Sparc/sparc-natural-instructions.s
+++ b/llvm/test/MC/Sparc/sparc-natural-instructions.s
@@ -1,5 +1,5 @@
-! RUN: llvm-mc %s -triple=sparc -mcpu=v9 -show-encoding | FileCheck %s --check-prefixes=SPARC32
-! RUN: llvm-mc %s -triple=sparcv9 -mcpu=v9 -show-encoding | FileCheck %s --check-prefixes=SPARC64
+! RUN: llvm-mc %s -triple=sparc -mcpu=v9 -mattr=+hard-quad-float -show-encoding | FileCheck %s --check-prefixes=SPARC32
+! RUN: llvm-mc %s -triple=sparcv9 -mcpu=v9 -mattr=+hard-quad-float -show-encoding | FileCheck %s --check-prefixes=SPARC64
!! Solaris Natural Instructions.
@@ -52,3 +52,6 @@ fmovse %ncc, %f0, %f1
! SPARC32: fmovde %icc, %f0, %f2 ! encoding: [0x85,0xa8,0x60,0x40]
! SPARC64: fmovde %xcc, %f0, %f2 ! encoding: [0x85,0xa8,0x70,0x40]
fmovde %ncc, %f0, %f2
+! SPARC32: fmovqe %icc, %f0, %f4 ! encoding: [0x89,0xa8,0x60,0x60]
+! SPARC64: fmovqe %xcc, %f0, %f4 ! encoding: [0x89,0xa8,0x70,0x60]
+fmovqe %ncc, %f0, %f4
More information about the llvm-commits
mailing list