[llvm] [WIP][SPARC] Add basic TTI implementation (PR #178843)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 30 08:45:01 PST 2026
https://github.com/koachan updated https://github.com/llvm/llvm-project/pull/178843
>From 442ef8e9d9bb60969769a5a487d1bdf689366729 Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Thu, 29 Jan 2026 18:53:40 +0700
Subject: [PATCH 1/5] [SPARC] Add basic TTI implementation
This is to inform the middle-end transform passes about the capabilities
of the processor.
This should solve two issues:
- Popcount loops now gets converted properly to `popc`, if available
(https://github.com/llvm/llvm-project/issues/171969); and
- Fixes the `find-last` test, which fails to build because LoopVectorizePass
mistakenly thinks that the backend understands vector types, when in fact
it doesn't (https://github.com/sparclinux/issues/issues/69).
---
llvm/lib/Target/Sparc/CMakeLists.txt | 3 +
llvm/lib/Target/Sparc/SparcTargetMachine.cpp | 6 +
llvm/lib/Target/Sparc/SparcTargetMachine.h | 1 +
.../Target/Sparc/SparcTargetTransformInfo.cpp | 109 ++++++++++++++++++
.../Target/Sparc/SparcTargetTransformInfo.h | 72 ++++++++++++
5 files changed, 191 insertions(+)
create mode 100644 llvm/lib/Target/Sparc/SparcTargetTransformInfo.cpp
create mode 100644 llvm/lib/Target/Sparc/SparcTargetTransformInfo.h
diff --git a/llvm/lib/Target/Sparc/CMakeLists.txt b/llvm/lib/Target/Sparc/CMakeLists.txt
index f682719ac483f..5db9dbf623858 100644
--- a/llvm/lib/Target/Sparc/CMakeLists.txt
+++ b/llvm/lib/Target/Sparc/CMakeLists.txt
@@ -30,8 +30,10 @@ add_llvm_target(SparcCodeGen
SparcSubtarget.cpp
SparcTargetMachine.cpp
SparcTargetObjectFile.cpp
+ SparcTargetTransformInfo.cpp
LINK_COMPONENTS
+ Analysis
AsmPrinter
CodeGen
CodeGenTypes
@@ -43,6 +45,7 @@ add_llvm_target(SparcCodeGen
Support
Target
TargetParser
+ TransformUtils
ADD_TO_COMPONENT
Sparc
diff --git a/llvm/lib/Target/Sparc/SparcTargetMachine.cpp b/llvm/lib/Target/Sparc/SparcTargetMachine.cpp
index 27ab57c11cf71..b9f1ad5331d4b 100644
--- a/llvm/lib/Target/Sparc/SparcTargetMachine.cpp
+++ b/llvm/lib/Target/Sparc/SparcTargetMachine.cpp
@@ -14,6 +14,7 @@
#include "Sparc.h"
#include "SparcMachineFunctionInfo.h"
#include "SparcTargetObjectFile.h"
+#include "SparcTargetTransformInfo.h"
#include "TargetInfo/SparcTargetInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/TargetPassConfig.h"
@@ -149,6 +150,11 @@ TargetPassConfig *SparcTargetMachine::createPassConfig(PassManagerBase &PM) {
return new SparcPassConfig(*this, PM);
}
+TargetTransformInfo
+SparcTargetMachine::getTargetTransformInfo(const Function &F) const {
+ return TargetTransformInfo(std::make_unique<SparcTTIImpl>(this, F));
+}
+
void SparcPassConfig::addIRPasses() {
addPass(createAtomicExpandLegacyPass());
diff --git a/llvm/lib/Target/Sparc/SparcTargetMachine.h b/llvm/lib/Target/Sparc/SparcTargetMachine.h
index e7d038c5779d4..2fbfd397325b6 100644
--- a/llvm/lib/Target/Sparc/SparcTargetMachine.h
+++ b/llvm/lib/Target/Sparc/SparcTargetMachine.h
@@ -40,6 +40,7 @@ class SparcTargetMachine : public CodeGenTargetMachineImpl {
TargetLoweringObjectFile *getObjFileLowering() const override {
return TLOF.get();
}
+ TargetTransformInfo getTargetTransformInfo(const Function &F) const override;
MachineFunctionInfo *
createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F,
diff --git a/llvm/lib/Target/Sparc/SparcTargetTransformInfo.cpp b/llvm/lib/Target/Sparc/SparcTargetTransformInfo.cpp
new file mode 100644
index 0000000000000..d0fe94fb6ff73
--- /dev/null
+++ b/llvm/lib/Target/Sparc/SparcTargetTransformInfo.cpp
@@ -0,0 +1,109 @@
+//===-- SparcTargetTransformInfo.cpp - SPARC specific TTI -----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SparcTargetTransformInfo.h"
+#include "llvm/Support/MathExtras.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "sparctti"
+
+InstructionCost
+SparcTTIImpl::getIntImmCost(const APInt &Imm, Type *Ty,
+ TTI::TargetCostKind CostKind) const {
+ assert(Ty->isIntegerTy());
+ unsigned BitSize = Ty->getPrimitiveSizeInBits();
+
+ if (BitSize <= 64) {
+ // Small constants can be folded into instruction's immediate field.
+ if (isInt<13>(Imm.getSExtValue()))
+ return TTI::TCC_Free;
+
+ // Medium constants loaded via set.
+ if (isUInt<32>(Imm.getZExtValue()))
+ return TTI::TCC_Basic;
+
+ // Large constants loaded via setx on 64-bit targets.
+ if (ST->is64Bit())
+ return 3 * TTI::TCC_Basic;
+ }
+
+ // Very large constants load from constant pool.
+ return TTI::TCC_Expensive;
+}
+
+InstructionCost SparcTTIImpl::getIntImmCostInst(unsigned Opcode, unsigned Idx,
+ const APInt &Imm, Type *Ty,
+ TTI::TargetCostKind CostKind,
+ Instruction *Inst) const {
+ assert(Ty->isIntegerTy());
+
+ switch (Opcode) {
+ case Instruction::Shl:
+ case Instruction::LShr:
+ case Instruction::AShr:
+ // Always return TCC_Free for the shift value of a shift instruction.
+ return (Idx == 1) ? TTI::TCC_Free : TTI::TCC_Basic;
+ }
+
+ // All other instructions have the same 13-bit immediate field so we can just
+ // pass it here.
+ return getIntImmCost(Imm, Ty, CostKind);
+}
+
+TargetTransformInfo::PopcntSupportKind
+SparcTTIImpl::getPopcntSupport(unsigned TyWidth) const {
+ assert(isPowerOf2_32(TyWidth) && "Type width must be power of 2");
+ if (ST->usePopc())
+ return TTI::PSK_FastHardware;
+ return TTI::PSK_Software;
+}
+
+unsigned SparcTTIImpl::getRegisterClassForType(bool Vector, Type *Ty) const {
+ if (Vector)
+ return FPRRC;
+ if (Ty &&
+ (Ty->getScalarType()->isFloatTy() || Ty->getScalarType()->isDoubleTy()))
+ return FPRRC;
+ if (Ty && (Ty->getScalarType()->isFP128Ty()))
+ return FP128RRC;
+ return GPRRC;
+}
+
+unsigned SparcTTIImpl::getNumberOfRegisters(unsigned ClassID) const {
+ switch (ClassID) {
+ case GPRRC:
+ // %g0, %g6, %g7, %o6, %i6, and %i7 are used for special purposes so we
+ // discount them here.
+ return 26;
+ case FPRRC:
+ return 32;
+ case FP128RRC:
+ return 16;
+ }
+
+ llvm_unreachable("Unsupported register class");
+}
+
+TypeSize
+SparcTTIImpl::getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const {
+ switch (K) {
+ case TargetTransformInfo::RGK_Scalar:
+ // TODO When targeting V8+ ABI, G and O registers are 64-bit.
+ return TypeSize::getFixed(ST->is64Bit() ? 64 : 32);
+ case TargetTransformInfo::RGK_FixedWidthVector:
+ // TODO We have vector capabilities as part of the VIS extensions, but the
+ // codegen doesn't currently use it. Revisit this when vector codegen is
+ // ready.
+ return TypeSize::getFixed(0);
+ case TargetTransformInfo::RGK_ScalableVector:
+ return TypeSize::getScalable(0);
+ }
+
+ llvm_unreachable("Unsupported register kind");
+}
diff --git a/llvm/lib/Target/Sparc/SparcTargetTransformInfo.h b/llvm/lib/Target/Sparc/SparcTargetTransformInfo.h
new file mode 100644
index 0000000000000..042fe498f2a76
--- /dev/null
+++ b/llvm/lib/Target/Sparc/SparcTargetTransformInfo.h
@@ -0,0 +1,72 @@
+//===-- SparcTargetTransformInfo.cpp - SPARC specific TTI--------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file a TargetTransformInfoImplBase conforming object specific to the
+/// SPARC target machine. It uses the target's detailed information to
+/// provide more precise answers to certain TTI queries, while letting the
+/// target independent and default TTI implementations handle the rest.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SPARC_SPARCTARGETTRANSFORMINFO_H
+#define LLVM_LIB_TARGET_SPARC_SPARCTARGETTRANSFORMINFO_H
+
+#include "SparcTargetMachine.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/CodeGen/BasicTTIImpl.h"
+
+namespace llvm {
+
+class SparcTTIImpl final : public BasicTTIImplBase<SparcTTIImpl> {
+ typedef BasicTTIImplBase<SparcTTIImpl> BaseT;
+ typedef TargetTransformInfo TTI;
+ friend BaseT;
+
+ const SparcSubtarget *ST;
+ const SparcTargetLowering *TLI;
+
+ const SparcSubtarget *getST() const { return ST; }
+ const SparcTargetLowering *getTLI() const { return TLI; }
+
+public:
+ explicit SparcTTIImpl(const SparcTargetMachine *TM, const Function &F)
+ : BaseT(TM, F.getDataLayout()), ST(TM->getSubtargetImpl(F)),
+ TLI(ST->getTargetLowering()) {}
+
+ /// \name Scalar TTI Implementations
+ /// @{
+ InstructionCost getIntImmCost(const APInt &Imm, Type *Ty,
+ TTI::TargetCostKind CostKind) const override;
+
+ InstructionCost getIntImmCostInst(unsigned Opcode, unsigned Idx,
+ const APInt &Imm, Type *Ty,
+ TTI::TargetCostKind CostKind,
+ Instruction *Inst = nullptr) const override;
+ InstructionCost
+ getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, const APInt &Imm,
+ Type *Ty, TTI::TargetCostKind CostKind) const override {
+ return getIntImmCost(Imm, Ty, CostKind);
+ };
+
+ TTI::PopcntSupportKind getPopcntSupport(unsigned TyWidth) const override;
+ /// @}
+
+ /// \name Vector TTI Implementations
+ /// @{
+ enum SparcRegisterClass { GPRRC, FPRRC, FP128RRC };
+ unsigned getNumberOfRegisters(unsigned ClassID) const override;
+ unsigned getRegisterClassForType(bool Vector,
+ Type *Ty = nullptr) const override;
+ TypeSize
+ getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const override;
+ /// @}
+};
+
+} // end namespace llvm
+
+#endif
>From 90e204eb7cc889121f892442d30b9dd831d45559 Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Thu, 29 Jan 2026 23:33:38 +0700
Subject: [PATCH 2/5] Make vector register amount to be zero
---
llvm/lib/Target/Sparc/SparcTargetTransformInfo.cpp | 7 ++++++-
llvm/lib/Target/Sparc/SparcTargetTransformInfo.h | 2 +-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/Sparc/SparcTargetTransformInfo.cpp b/llvm/lib/Target/Sparc/SparcTargetTransformInfo.cpp
index d0fe94fb6ff73..b1bf75d1c4899 100644
--- a/llvm/lib/Target/Sparc/SparcTargetTransformInfo.cpp
+++ b/llvm/lib/Target/Sparc/SparcTargetTransformInfo.cpp
@@ -66,7 +66,7 @@ SparcTTIImpl::getPopcntSupport(unsigned TyWidth) const {
unsigned SparcTTIImpl::getRegisterClassForType(bool Vector, Type *Ty) const {
if (Vector)
- return FPRRC;
+ return VRRC;
if (Ty &&
(Ty->getScalarType()->isFloatTy() || Ty->getScalarType()->isDoubleTy()))
return FPRRC;
@@ -85,6 +85,11 @@ unsigned SparcTTIImpl::getNumberOfRegisters(unsigned ClassID) const {
return 32;
case FP128RRC:
return 16;
+ case VRRC:
+ // TODO We have vector capabilities as part of the VIS extensions, but the
+ // codegen doesn't currently use it. Revisit this when vector codegen is
+ // ready.
+ return 0;
}
llvm_unreachable("Unsupported register class");
diff --git a/llvm/lib/Target/Sparc/SparcTargetTransformInfo.h b/llvm/lib/Target/Sparc/SparcTargetTransformInfo.h
index 042fe498f2a76..0d1048c93f7ad 100644
--- a/llvm/lib/Target/Sparc/SparcTargetTransformInfo.h
+++ b/llvm/lib/Target/Sparc/SparcTargetTransformInfo.h
@@ -58,7 +58,7 @@ class SparcTTIImpl final : public BasicTTIImplBase<SparcTTIImpl> {
/// \name Vector TTI Implementations
/// @{
- enum SparcRegisterClass { GPRRC, FPRRC, FP128RRC };
+ enum SparcRegisterClass { GPRRC, FPRRC, FP128RRC, VRRC };
unsigned getNumberOfRegisters(unsigned ClassID) const override;
unsigned getRegisterClassForType(bool Vector,
Type *Ty = nullptr) const override;
>From 53965918721520fdc8f007962593ffb40508e48c Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Fri, 30 Jan 2026 13:31:37 +0700
Subject: [PATCH 3/5] Add popcnt test
---
.../test/Transforms/LoopIdiom/Sparc/popcnt.ll | 319 ++++++++++++++++++
1 file changed, 319 insertions(+)
create mode 100644 llvm/test/Transforms/LoopIdiom/Sparc/popcnt.ll
diff --git a/llvm/test/Transforms/LoopIdiom/Sparc/popcnt.ll b/llvm/test/Transforms/LoopIdiom/Sparc/popcnt.ll
new file mode 100644
index 0000000000000..d3a5f575c8f8a
--- /dev/null
+++ b/llvm/test/Transforms/LoopIdiom/Sparc/popcnt.ll
@@ -0,0 +1,319 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes=loop-idiom -mtriple=sparcv9 -mattr=+popc -S < %s | FileCheck %s --check-prefixes=SPARC64-CPOP
+; RUN: opt -passes=loop-idiom -mtriple=sparcv9 -S < %s | FileCheck %s --check-prefixes=SPARC64-NOCPOP
+
+; Mostly copied from AMDGPU version.
+
+;To recognize this pattern:
+;int popcount(unsigned long long a) {
+; int c = 0;
+; while (a) {
+; c++;
+; a &= a - 1;
+; }
+; return c;
+;}
+;
+
+define i32 @popcount_i64(i64 %a) nounwind uwtable readnone ssp {
+; SPARC64-CPOP-LABEL: @popcount_i64(
+; SPARC64-CPOP-NEXT: entry:
+; SPARC64-CPOP-NEXT: [[TMP0:%.*]] = call i64 @llvm.ctpop.i64(i64 [[A:%.*]])
+; SPARC64-CPOP-NEXT: [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32
+; SPARC64-CPOP-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
+; SPARC64-CPOP-NEXT: br i1 [[TMP2]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
+; SPARC64-CPOP: while.body.preheader:
+; SPARC64-CPOP-NEXT: br label [[WHILE_BODY:%.*]]
+; SPARC64-CPOP: while.body:
+; SPARC64-CPOP-NEXT: [[TCPHI:%.*]] = phi i32 [ [[TMP1]], [[WHILE_BODY_PREHEADER]] ], [ [[TCDEC:%.*]], [[WHILE_BODY]] ]
+; SPARC64-CPOP-NEXT: [[C_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
+; SPARC64-CPOP-NEXT: [[A_ADDR_04:%.*]] = phi i64 [ [[AND:%.*]], [[WHILE_BODY]] ], [ [[A]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC64-CPOP-NEXT: [[INC]] = add nsw i32 [[C_05]], 1
+; SPARC64-CPOP-NEXT: [[SUB:%.*]] = add i64 [[A_ADDR_04]], -1
+; SPARC64-CPOP-NEXT: [[AND]] = and i64 [[SUB]], [[A_ADDR_04]]
+; SPARC64-CPOP-NEXT: [[TCDEC]] = sub nsw i32 [[TCPHI]], 1
+; SPARC64-CPOP-NEXT: [[TOBOOL:%.*]] = icmp sle i32 [[TCDEC]], 0
+; SPARC64-CPOP-NEXT: br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
+; SPARC64-CPOP: while.end.loopexit:
+; SPARC64-CPOP-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[TMP1]], [[WHILE_BODY]] ]
+; SPARC64-CPOP-NEXT: br label [[WHILE_END]]
+; SPARC64-CPOP: while.end:
+; SPARC64-CPOP-NEXT: [[C_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC64-CPOP-NEXT: ret i32 [[C_0_LCSSA]]
+;
+; SPARC64-NOCPOP-LABEL: @popcount_i64(
+; SPARC64-NOCPOP-NEXT: entry:
+; SPARC64-NOCPOP-NEXT: [[TOBOOL3:%.*]] = icmp eq i64 [[A:%.*]], 0
+; SPARC64-NOCPOP-NEXT: br i1 [[TOBOOL3]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
+; SPARC64-NOCPOP: while.body.preheader:
+; SPARC64-NOCPOP-NEXT: br label [[WHILE_BODY:%.*]]
+; SPARC64-NOCPOP: while.body:
+; SPARC64-NOCPOP-NEXT: [[C_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
+; SPARC64-NOCPOP-NEXT: [[A_ADDR_04:%.*]] = phi i64 [ [[AND:%.*]], [[WHILE_BODY]] ], [ [[A]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC64-NOCPOP-NEXT: [[INC]] = add nsw i32 [[C_05]], 1
+; SPARC64-NOCPOP-NEXT: [[SUB:%.*]] = add i64 [[A_ADDR_04]], -1
+; SPARC64-NOCPOP-NEXT: [[AND]] = and i64 [[SUB]], [[A_ADDR_04]]
+; SPARC64-NOCPOP-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[AND]], 0
+; SPARC64-NOCPOP-NEXT: br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
+; SPARC64-NOCPOP: while.end.loopexit:
+; SPARC64-NOCPOP-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[INC]], [[WHILE_BODY]] ]
+; SPARC64-NOCPOP-NEXT: br label [[WHILE_END]]
+; SPARC64-NOCPOP: while.end:
+; SPARC64-NOCPOP-NEXT: [[C_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC64-NOCPOP-NEXT: ret i32 [[C_0_LCSSA]]
+;
+entry:
+ %tobool3 = icmp eq i64 %a, 0
+ br i1 %tobool3, label %while.end, label %while.body
+
+while.body: ; preds = %entry, %while.body
+ %c.05 = phi i32 [ %inc, %while.body ], [ 0, %entry ]
+ %a.addr.04 = phi i64 [ %and, %while.body ], [ %a, %entry ]
+ %inc = add nsw i32 %c.05, 1
+ %sub = add i64 %a.addr.04, -1
+ %and = and i64 %sub, %a.addr.04
+ %tobool = icmp eq i64 %and, 0
+ br i1 %tobool, label %while.end, label %while.body
+
+while.end: ; preds = %while.body, %entry
+ %c.0.lcssa = phi i32 [ 0, %entry ], [ %inc, %while.body ]
+ ret i32 %c.0.lcssa
+}
+
+define i32 @popcount_i32(i32 %a) nounwind uwtable readnone ssp {
+; SPARC64-CPOP-LABEL: @popcount_i32(
+; SPARC64-CPOP-NEXT: entry:
+; SPARC64-CPOP-NEXT: [[TMP0:%.*]] = call i32 @llvm.ctpop.i32(i32 [[A:%.*]])
+; SPARC64-CPOP-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 0
+; SPARC64-CPOP-NEXT: br i1 [[TMP1]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
+; SPARC64-CPOP: while.body.preheader:
+; SPARC64-CPOP-NEXT: br label [[WHILE_BODY:%.*]]
+; SPARC64-CPOP: while.body:
+; SPARC64-CPOP-NEXT: [[TCPHI:%.*]] = phi i32 [ [[TMP0]], [[WHILE_BODY_PREHEADER]] ], [ [[TCDEC:%.*]], [[WHILE_BODY]] ]
+; SPARC64-CPOP-NEXT: [[C_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
+; SPARC64-CPOP-NEXT: [[A_ADDR_04:%.*]] = phi i32 [ [[AND:%.*]], [[WHILE_BODY]] ], [ [[A]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC64-CPOP-NEXT: [[INC]] = add nsw i32 [[C_05]], 1
+; SPARC64-CPOP-NEXT: [[SUB:%.*]] = add i32 [[A_ADDR_04]], -1
+; SPARC64-CPOP-NEXT: [[AND]] = and i32 [[SUB]], [[A_ADDR_04]]
+; SPARC64-CPOP-NEXT: [[TCDEC]] = sub nsw i32 [[TCPHI]], 1
+; SPARC64-CPOP-NEXT: [[TOBOOL:%.*]] = icmp sle i32 [[TCDEC]], 0
+; SPARC64-CPOP-NEXT: br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
+; SPARC64-CPOP: while.end.loopexit:
+; SPARC64-CPOP-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[TMP0]], [[WHILE_BODY]] ]
+; SPARC64-CPOP-NEXT: br label [[WHILE_END]]
+; SPARC64-CPOP: while.end:
+; SPARC64-CPOP-NEXT: [[C_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC64-CPOP-NEXT: ret i32 [[C_0_LCSSA]]
+;
+; SPARC64-NOCPOP-LABEL: @popcount_i32(
+; SPARC64-NOCPOP-NEXT: entry:
+; SPARC64-NOCPOP-NEXT: [[TOBOOL3:%.*]] = icmp eq i32 [[A:%.*]], 0
+; SPARC64-NOCPOP-NEXT: br i1 [[TOBOOL3]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
+; SPARC64-NOCPOP: while.body.preheader:
+; SPARC64-NOCPOP-NEXT: br label [[WHILE_BODY:%.*]]
+; SPARC64-NOCPOP: while.body:
+; SPARC64-NOCPOP-NEXT: [[C_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
+; SPARC64-NOCPOP-NEXT: [[A_ADDR_04:%.*]] = phi i32 [ [[AND:%.*]], [[WHILE_BODY]] ], [ [[A]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC64-NOCPOP-NEXT: [[INC]] = add nsw i32 [[C_05]], 1
+; SPARC64-NOCPOP-NEXT: [[SUB:%.*]] = add i32 [[A_ADDR_04]], -1
+; SPARC64-NOCPOP-NEXT: [[AND]] = and i32 [[SUB]], [[A_ADDR_04]]
+; SPARC64-NOCPOP-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[AND]], 0
+; SPARC64-NOCPOP-NEXT: br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
+; SPARC64-NOCPOP: while.end.loopexit:
+; SPARC64-NOCPOP-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[INC]], [[WHILE_BODY]] ]
+; SPARC64-NOCPOP-NEXT: br label [[WHILE_END]]
+; SPARC64-NOCPOP: while.end:
+; SPARC64-NOCPOP-NEXT: [[C_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC64-NOCPOP-NEXT: ret i32 [[C_0_LCSSA]]
+;
+entry:
+ %tobool3 = icmp eq i32 %a, 0
+ br i1 %tobool3, label %while.end, label %while.body
+
+while.body: ; preds = %entry, %while.body
+ %c.05 = phi i32 [ %inc, %while.body ], [ 0, %entry ]
+ %a.addr.04 = phi i32 [ %and, %while.body ], [ %a, %entry ]
+ %inc = add nsw i32 %c.05, 1
+ %sub = add i32 %a.addr.04, -1
+ %and = and i32 %sub, %a.addr.04
+ %tobool = icmp eq i32 %and, 0
+ br i1 %tobool, label %while.end, label %while.body
+
+while.end: ; preds = %while.body, %entry
+ %c.0.lcssa = phi i32 [ 0, %entry ], [ %inc, %while.body ]
+ ret i32 %c.0.lcssa
+}
+
+define i32 @popcount_i128(i128 %a) nounwind uwtable readnone ssp {
+; SPARC64-CPOP-LABEL: @popcount_i128(
+; SPARC64-CPOP-NEXT: entry:
+; SPARC64-CPOP-NEXT: [[TMP0:%.*]] = call i128 @llvm.ctpop.i128(i128 [[A:%.*]])
+; SPARC64-CPOP-NEXT: [[TMP1:%.*]] = trunc i128 [[TMP0]] to i32
+; SPARC64-CPOP-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
+; SPARC64-CPOP-NEXT: br i1 [[TMP2]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
+; SPARC64-CPOP: while.body.preheader:
+; SPARC64-CPOP-NEXT: br label [[WHILE_BODY:%.*]]
+; SPARC64-CPOP: while.body:
+; SPARC64-CPOP-NEXT: [[TCPHI:%.*]] = phi i32 [ [[TMP1]], [[WHILE_BODY_PREHEADER]] ], [ [[TCDEC:%.*]], [[WHILE_BODY]] ]
+; SPARC64-CPOP-NEXT: [[C_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
+; SPARC64-CPOP-NEXT: [[A_ADDR_04:%.*]] = phi i128 [ [[AND:%.*]], [[WHILE_BODY]] ], [ [[A]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC64-CPOP-NEXT: [[INC]] = add nsw i32 [[C_05]], 1
+; SPARC64-CPOP-NEXT: [[SUB:%.*]] = add i128 [[A_ADDR_04]], -1
+; SPARC64-CPOP-NEXT: [[AND]] = and i128 [[SUB]], [[A_ADDR_04]]
+; SPARC64-CPOP-NEXT: [[TCDEC]] = sub nsw i32 [[TCPHI]], 1
+; SPARC64-CPOP-NEXT: [[TOBOOL:%.*]] = icmp sle i32 [[TCDEC]], 0
+; SPARC64-CPOP-NEXT: br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
+; SPARC64-CPOP: while.end.loopexit:
+; SPARC64-CPOP-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[TMP1]], [[WHILE_BODY]] ]
+; SPARC64-CPOP-NEXT: br label [[WHILE_END]]
+; SPARC64-CPOP: while.end:
+; SPARC64-CPOP-NEXT: [[C_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC64-CPOP-NEXT: ret i32 [[C_0_LCSSA]]
+;
+; SPARC64-NOCPOP-LABEL: @popcount_i128(
+; SPARC64-NOCPOP-NEXT: entry:
+; SPARC64-NOCPOP-NEXT: [[TOBOOL3:%.*]] = icmp eq i128 [[A:%.*]], 0
+; SPARC64-NOCPOP-NEXT: br i1 [[TOBOOL3]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
+; SPARC64-NOCPOP: while.body.preheader:
+; SPARC64-NOCPOP-NEXT: br label [[WHILE_BODY:%.*]]
+; SPARC64-NOCPOP: while.body:
+; SPARC64-NOCPOP-NEXT: [[C_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
+; SPARC64-NOCPOP-NEXT: [[A_ADDR_04:%.*]] = phi i128 [ [[AND:%.*]], [[WHILE_BODY]] ], [ [[A]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC64-NOCPOP-NEXT: [[INC]] = add nsw i32 [[C_05]], 1
+; SPARC64-NOCPOP-NEXT: [[SUB:%.*]] = add i128 [[A_ADDR_04]], -1
+; SPARC64-NOCPOP-NEXT: [[AND]] = and i128 [[SUB]], [[A_ADDR_04]]
+; SPARC64-NOCPOP-NEXT: [[TOBOOL:%.*]] = icmp eq i128 [[AND]], 0
+; SPARC64-NOCPOP-NEXT: br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
+; SPARC64-NOCPOP: while.end.loopexit:
+; SPARC64-NOCPOP-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[INC]], [[WHILE_BODY]] ]
+; SPARC64-NOCPOP-NEXT: br label [[WHILE_END]]
+; SPARC64-NOCPOP: while.end:
+; SPARC64-NOCPOP-NEXT: [[C_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC64-NOCPOP-NEXT: ret i32 [[C_0_LCSSA]]
+;
+entry:
+ %tobool3 = icmp eq i128 %a, 0
+ br i1 %tobool3, label %while.end, label %while.body
+
+while.body: ; preds = %entry, %while.body
+ %c.05 = phi i32 [ %inc, %while.body ], [ 0, %entry ]
+ %a.addr.04 = phi i128 [ %and, %while.body ], [ %a, %entry ]
+ %inc = add nsw i32 %c.05, 1
+ %sub = add i128 %a.addr.04, -1
+ %and = and i128 %sub, %a.addr.04
+ %tobool = icmp eq i128 %and, 0
+ br i1 %tobool, label %while.end, label %while.body
+
+while.end: ; preds = %while.body, %entry
+ %c.0.lcssa = phi i32 [ 0, %entry ], [ %inc, %while.body ]
+ ret i32 %c.0.lcssa
+}
+
+; To recognize this pattern:
+;int popcount(unsigned long long a, int mydata1, int mydata2) {
+; int c = 0;
+; while (a) {
+; c++;
+; a &= a - 1;
+; mydata1 *= c;
+; mydata2 *= (int)a;
+; }
+; return c + mydata1 + mydata2;
+;}
+
+define i32 @popcount2(i64 %a, i32 %mydata1, i32 %mydata2) nounwind uwtable readnone ssp {
+; SPARC64-CPOP-LABEL: @popcount2(
+; SPARC64-CPOP-NEXT: entry:
+; SPARC64-CPOP-NEXT: [[TMP0:%.*]] = call i64 @llvm.ctpop.i64(i64 [[A:%.*]])
+; SPARC64-CPOP-NEXT: [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32
+; SPARC64-CPOP-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
+; SPARC64-CPOP-NEXT: br i1 [[TMP2]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
+; SPARC64-CPOP: while.body.preheader:
+; SPARC64-CPOP-NEXT: br label [[WHILE_BODY:%.*]]
+; SPARC64-CPOP: while.body:
+; SPARC64-CPOP-NEXT: [[TCPHI:%.*]] = phi i32 [ [[TMP1]], [[WHILE_BODY_PREHEADER]] ], [ [[TCDEC:%.*]], [[WHILE_BODY]] ]
+; SPARC64-CPOP-NEXT: [[C_013:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
+; SPARC64-CPOP-NEXT: [[MYDATA2_ADDR_012:%.*]] = phi i32 [ [[MUL1:%.*]], [[WHILE_BODY]] ], [ [[MYDATA2:%.*]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC64-CPOP-NEXT: [[MYDATA1_ADDR_011:%.*]] = phi i32 [ [[MUL:%.*]], [[WHILE_BODY]] ], [ [[MYDATA1:%.*]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC64-CPOP-NEXT: [[A_ADDR_010:%.*]] = phi i64 [ [[AND:%.*]], [[WHILE_BODY]] ], [ [[A]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC64-CPOP-NEXT: [[INC]] = add nsw i32 [[C_013]], 1
+; SPARC64-CPOP-NEXT: [[SUB:%.*]] = add i64 [[A_ADDR_010]], -1
+; SPARC64-CPOP-NEXT: [[AND]] = and i64 [[SUB]], [[A_ADDR_010]]
+; SPARC64-CPOP-NEXT: [[MUL]] = mul nsw i32 [[INC]], [[MYDATA1_ADDR_011]]
+; SPARC64-CPOP-NEXT: [[CONV:%.*]] = trunc i64 [[AND]] to i32
+; SPARC64-CPOP-NEXT: [[MUL1]] = mul nsw i32 [[CONV]], [[MYDATA2_ADDR_012]]
+; SPARC64-CPOP-NEXT: [[TCDEC]] = sub nsw i32 [[TCPHI]], 1
+; SPARC64-CPOP-NEXT: [[TOBOOL:%.*]] = icmp sle i32 [[TCDEC]], 0
+; SPARC64-CPOP-NEXT: br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
+; SPARC64-CPOP: while.end.loopexit:
+; SPARC64-CPOP-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[TMP1]], [[WHILE_BODY]] ]
+; SPARC64-CPOP-NEXT: [[MUL_LCSSA:%.*]] = phi i32 [ [[MUL]], [[WHILE_BODY]] ]
+; SPARC64-CPOP-NEXT: [[MUL1_LCSSA:%.*]] = phi i32 [ [[MUL1]], [[WHILE_BODY]] ]
+; SPARC64-CPOP-NEXT: br label [[WHILE_END]]
+; SPARC64-CPOP: while.end:
+; SPARC64-CPOP-NEXT: [[C_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC64-CPOP-NEXT: [[MYDATA2_ADDR_0_LCSSA:%.*]] = phi i32 [ [[MYDATA2]], [[ENTRY]] ], [ [[MUL1_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC64-CPOP-NEXT: [[MYDATA1_ADDR_0_LCSSA:%.*]] = phi i32 [ [[MYDATA1]], [[ENTRY]] ], [ [[MUL_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC64-CPOP-NEXT: [[ADD:%.*]] = add i32 [[MYDATA2_ADDR_0_LCSSA]], [[MYDATA1_ADDR_0_LCSSA]]
+; SPARC64-CPOP-NEXT: [[ADD2:%.*]] = add i32 [[ADD]], [[C_0_LCSSA]]
+; SPARC64-CPOP-NEXT: ret i32 [[ADD2]]
+;
+; SPARC64-NOCPOP-LABEL: @popcount2(
+; SPARC64-NOCPOP-NEXT: entry:
+; SPARC64-NOCPOP-NEXT: [[TOBOOL9:%.*]] = icmp eq i64 [[A:%.*]], 0
+; SPARC64-NOCPOP-NEXT: br i1 [[TOBOOL9]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
+; SPARC64-NOCPOP: while.body.preheader:
+; SPARC64-NOCPOP-NEXT: br label [[WHILE_BODY:%.*]]
+; SPARC64-NOCPOP: while.body:
+; SPARC64-NOCPOP-NEXT: [[C_013:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
+; SPARC64-NOCPOP-NEXT: [[MYDATA2_ADDR_012:%.*]] = phi i32 [ [[MUL1:%.*]], [[WHILE_BODY]] ], [ [[MYDATA2:%.*]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC64-NOCPOP-NEXT: [[MYDATA1_ADDR_011:%.*]] = phi i32 [ [[MUL:%.*]], [[WHILE_BODY]] ], [ [[MYDATA1:%.*]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC64-NOCPOP-NEXT: [[A_ADDR_010:%.*]] = phi i64 [ [[AND:%.*]], [[WHILE_BODY]] ], [ [[A]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC64-NOCPOP-NEXT: [[INC]] = add nsw i32 [[C_013]], 1
+; SPARC64-NOCPOP-NEXT: [[SUB:%.*]] = add i64 [[A_ADDR_010]], -1
+; SPARC64-NOCPOP-NEXT: [[AND]] = and i64 [[SUB]], [[A_ADDR_010]]
+; SPARC64-NOCPOP-NEXT: [[MUL]] = mul nsw i32 [[INC]], [[MYDATA1_ADDR_011]]
+; SPARC64-NOCPOP-NEXT: [[CONV:%.*]] = trunc i64 [[AND]] to i32
+; SPARC64-NOCPOP-NEXT: [[MUL1]] = mul nsw i32 [[CONV]], [[MYDATA2_ADDR_012]]
+; SPARC64-NOCPOP-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[AND]], 0
+; SPARC64-NOCPOP-NEXT: br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
+; SPARC64-NOCPOP: while.end.loopexit:
+; SPARC64-NOCPOP-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[INC]], [[WHILE_BODY]] ]
+; SPARC64-NOCPOP-NEXT: [[MUL_LCSSA:%.*]] = phi i32 [ [[MUL]], [[WHILE_BODY]] ]
+; SPARC64-NOCPOP-NEXT: [[MUL1_LCSSA:%.*]] = phi i32 [ [[MUL1]], [[WHILE_BODY]] ]
+; SPARC64-NOCPOP-NEXT: br label [[WHILE_END]]
+; SPARC64-NOCPOP: while.end:
+; SPARC64-NOCPOP-NEXT: [[C_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC64-NOCPOP-NEXT: [[MYDATA2_ADDR_0_LCSSA:%.*]] = phi i32 [ [[MYDATA2]], [[ENTRY]] ], [ [[MUL1_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC64-NOCPOP-NEXT: [[MYDATA1_ADDR_0_LCSSA:%.*]] = phi i32 [ [[MYDATA1]], [[ENTRY]] ], [ [[MUL_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC64-NOCPOP-NEXT: [[ADD:%.*]] = add i32 [[MYDATA2_ADDR_0_LCSSA]], [[MYDATA1_ADDR_0_LCSSA]]
+; SPARC64-NOCPOP-NEXT: [[ADD2:%.*]] = add i32 [[ADD]], [[C_0_LCSSA]]
+; SPARC64-NOCPOP-NEXT: ret i32 [[ADD2]]
+;
+entry:
+ %tobool9 = icmp eq i64 %a, 0
+ br i1 %tobool9, label %while.end, label %while.body
+
+while.body: ; preds = %entry, %while.body
+ %c.013 = phi i32 [ %inc, %while.body ], [ 0, %entry ]
+ %mydata2.addr.012 = phi i32 [ %mul1, %while.body ], [ %mydata2, %entry ]
+ %mydata1.addr.011 = phi i32 [ %mul, %while.body ], [ %mydata1, %entry ]
+ %a.addr.010 = phi i64 [ %and, %while.body ], [ %a, %entry ]
+ %inc = add nsw i32 %c.013, 1
+ %sub = add i64 %a.addr.010, -1
+ %and = and i64 %sub, %a.addr.010
+ %mul = mul nsw i32 %inc, %mydata1.addr.011
+ %conv = trunc i64 %and to i32
+ %mul1 = mul nsw i32 %conv, %mydata2.addr.012
+ %tobool = icmp eq i64 %and, 0
+ br i1 %tobool, label %while.end, label %while.body
+
+while.end: ; preds = %while.body, %entry
+ %c.0.lcssa = phi i32 [ 0, %entry ], [ %inc, %while.body ]
+ %mydata2.addr.0.lcssa = phi i32 [ %mydata2, %entry ], [ %mul1, %while.body ]
+ %mydata1.addr.0.lcssa = phi i32 [ %mydata1, %entry ], [ %mul, %while.body ]
+ %add = add i32 %mydata2.addr.0.lcssa, %mydata1.addr.0.lcssa
+ %add2 = add i32 %add, %c.0.lcssa
+ ret i32 %add2
+}
+
>From 06e4b7453d2cf2857c3585ba663bdba12eeeadac Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Fri, 30 Jan 2026 13:46:11 +0700
Subject: [PATCH 4/5] Add sparc32 popcnt test
---
.../test/Transforms/LoopIdiom/Sparc/popcnt.ll | 192 ++++++++++++++++++
1 file changed, 192 insertions(+)
diff --git a/llvm/test/Transforms/LoopIdiom/Sparc/popcnt.ll b/llvm/test/Transforms/LoopIdiom/Sparc/popcnt.ll
index d3a5f575c8f8a..3d4a86db1c3fc 100644
--- a/llvm/test/Transforms/LoopIdiom/Sparc/popcnt.ll
+++ b/llvm/test/Transforms/LoopIdiom/Sparc/popcnt.ll
@@ -1,5 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes=loop-idiom -mtriple=sparc -mattr=+popc -S < %s | FileCheck %s --check-prefixes=SPARC-CPOP
; RUN: opt -passes=loop-idiom -mtriple=sparcv9 -mattr=+popc -S < %s | FileCheck %s --check-prefixes=SPARC64-CPOP
+; RUN: opt -passes=loop-idiom -mtriple=sparc -S < %s | FileCheck %s --check-prefixes=SPARC-NOCPOP
; RUN: opt -passes=loop-idiom -mtriple=sparcv9 -S < %s | FileCheck %s --check-prefixes=SPARC64-NOCPOP
; Mostly copied from AMDGPU version.
@@ -16,6 +18,27 @@
;
define i32 @popcount_i64(i64 %a) nounwind uwtable readnone ssp {
+; SPARC-CPOP-LABEL: @popcount_i64(
+; SPARC-CPOP-NEXT: entry:
+; SPARC-CPOP-NEXT: [[TOBOOL3:%.*]] = icmp eq i64 [[A:%.*]], 0
+; SPARC-CPOP-NEXT: br i1 [[TOBOOL3]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
+; SPARC-CPOP: while.body.preheader:
+; SPARC-CPOP-NEXT: br label [[WHILE_BODY:%.*]]
+; SPARC-CPOP: while.body:
+; SPARC-CPOP-NEXT: [[C_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
+; SPARC-CPOP-NEXT: [[A_ADDR_04:%.*]] = phi i64 [ [[AND:%.*]], [[WHILE_BODY]] ], [ [[A]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC-CPOP-NEXT: [[INC]] = add nsw i32 [[C_05]], 1
+; SPARC-CPOP-NEXT: [[SUB:%.*]] = add i64 [[A_ADDR_04]], -1
+; SPARC-CPOP-NEXT: [[AND]] = and i64 [[SUB]], [[A_ADDR_04]]
+; SPARC-CPOP-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[AND]], 0
+; SPARC-CPOP-NEXT: br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
+; SPARC-CPOP: while.end.loopexit:
+; SPARC-CPOP-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[INC]], [[WHILE_BODY]] ]
+; SPARC-CPOP-NEXT: br label [[WHILE_END]]
+; SPARC-CPOP: while.end:
+; SPARC-CPOP-NEXT: [[C_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC-CPOP-NEXT: ret i32 [[C_0_LCSSA]]
+;
; SPARC64-CPOP-LABEL: @popcount_i64(
; SPARC64-CPOP-NEXT: entry:
; SPARC64-CPOP-NEXT: [[TMP0:%.*]] = call i64 @llvm.ctpop.i64(i64 [[A:%.*]])
@@ -41,6 +64,27 @@ define i32 @popcount_i64(i64 %a) nounwind uwtable readnone ssp {
; SPARC64-CPOP-NEXT: [[C_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
; SPARC64-CPOP-NEXT: ret i32 [[C_0_LCSSA]]
;
+; SPARC-NOCPOP-LABEL: @popcount_i64(
+; SPARC-NOCPOP-NEXT: entry:
+; SPARC-NOCPOP-NEXT: [[TOBOOL3:%.*]] = icmp eq i64 [[A:%.*]], 0
+; SPARC-NOCPOP-NEXT: br i1 [[TOBOOL3]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
+; SPARC-NOCPOP: while.body.preheader:
+; SPARC-NOCPOP-NEXT: br label [[WHILE_BODY:%.*]]
+; SPARC-NOCPOP: while.body:
+; SPARC-NOCPOP-NEXT: [[C_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
+; SPARC-NOCPOP-NEXT: [[A_ADDR_04:%.*]] = phi i64 [ [[AND:%.*]], [[WHILE_BODY]] ], [ [[A]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC-NOCPOP-NEXT: [[INC]] = add nsw i32 [[C_05]], 1
+; SPARC-NOCPOP-NEXT: [[SUB:%.*]] = add i64 [[A_ADDR_04]], -1
+; SPARC-NOCPOP-NEXT: [[AND]] = and i64 [[SUB]], [[A_ADDR_04]]
+; SPARC-NOCPOP-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[AND]], 0
+; SPARC-NOCPOP-NEXT: br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
+; SPARC-NOCPOP: while.end.loopexit:
+; SPARC-NOCPOP-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[INC]], [[WHILE_BODY]] ]
+; SPARC-NOCPOP-NEXT: br label [[WHILE_END]]
+; SPARC-NOCPOP: while.end:
+; SPARC-NOCPOP-NEXT: [[C_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC-NOCPOP-NEXT: ret i32 [[C_0_LCSSA]]
+;
; SPARC64-NOCPOP-LABEL: @popcount_i64(
; SPARC64-NOCPOP-NEXT: entry:
; SPARC64-NOCPOP-NEXT: [[TOBOOL3:%.*]] = icmp eq i64 [[A:%.*]], 0
@@ -81,6 +125,27 @@ while.end: ; preds = %while.body, %entry
}
define i32 @popcount_i32(i32 %a) nounwind uwtable readnone ssp {
+; SPARC-CPOP-LABEL: @popcount_i32(
+; SPARC-CPOP-NEXT: entry:
+; SPARC-CPOP-NEXT: [[TOBOOL3:%.*]] = icmp eq i32 [[A:%.*]], 0
+; SPARC-CPOP-NEXT: br i1 [[TOBOOL3]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
+; SPARC-CPOP: while.body.preheader:
+; SPARC-CPOP-NEXT: br label [[WHILE_BODY:%.*]]
+; SPARC-CPOP: while.body:
+; SPARC-CPOP-NEXT: [[C_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
+; SPARC-CPOP-NEXT: [[A_ADDR_04:%.*]] = phi i32 [ [[AND:%.*]], [[WHILE_BODY]] ], [ [[A]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC-CPOP-NEXT: [[INC]] = add nsw i32 [[C_05]], 1
+; SPARC-CPOP-NEXT: [[SUB:%.*]] = add i32 [[A_ADDR_04]], -1
+; SPARC-CPOP-NEXT: [[AND]] = and i32 [[SUB]], [[A_ADDR_04]]
+; SPARC-CPOP-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[AND]], 0
+; SPARC-CPOP-NEXT: br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
+; SPARC-CPOP: while.end.loopexit:
+; SPARC-CPOP-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[INC]], [[WHILE_BODY]] ]
+; SPARC-CPOP-NEXT: br label [[WHILE_END]]
+; SPARC-CPOP: while.end:
+; SPARC-CPOP-NEXT: [[C_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC-CPOP-NEXT: ret i32 [[C_0_LCSSA]]
+;
; SPARC64-CPOP-LABEL: @popcount_i32(
; SPARC64-CPOP-NEXT: entry:
; SPARC64-CPOP-NEXT: [[TMP0:%.*]] = call i32 @llvm.ctpop.i32(i32 [[A:%.*]])
@@ -105,6 +170,27 @@ define i32 @popcount_i32(i32 %a) nounwind uwtable readnone ssp {
; SPARC64-CPOP-NEXT: [[C_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
; SPARC64-CPOP-NEXT: ret i32 [[C_0_LCSSA]]
;
+; SPARC-NOCPOP-LABEL: @popcount_i32(
+; SPARC-NOCPOP-NEXT: entry:
+; SPARC-NOCPOP-NEXT: [[TOBOOL3:%.*]] = icmp eq i32 [[A:%.*]], 0
+; SPARC-NOCPOP-NEXT: br i1 [[TOBOOL3]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
+; SPARC-NOCPOP: while.body.preheader:
+; SPARC-NOCPOP-NEXT: br label [[WHILE_BODY:%.*]]
+; SPARC-NOCPOP: while.body:
+; SPARC-NOCPOP-NEXT: [[C_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
+; SPARC-NOCPOP-NEXT: [[A_ADDR_04:%.*]] = phi i32 [ [[AND:%.*]], [[WHILE_BODY]] ], [ [[A]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC-NOCPOP-NEXT: [[INC]] = add nsw i32 [[C_05]], 1
+; SPARC-NOCPOP-NEXT: [[SUB:%.*]] = add i32 [[A_ADDR_04]], -1
+; SPARC-NOCPOP-NEXT: [[AND]] = and i32 [[SUB]], [[A_ADDR_04]]
+; SPARC-NOCPOP-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[AND]], 0
+; SPARC-NOCPOP-NEXT: br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
+; SPARC-NOCPOP: while.end.loopexit:
+; SPARC-NOCPOP-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[INC]], [[WHILE_BODY]] ]
+; SPARC-NOCPOP-NEXT: br label [[WHILE_END]]
+; SPARC-NOCPOP: while.end:
+; SPARC-NOCPOP-NEXT: [[C_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC-NOCPOP-NEXT: ret i32 [[C_0_LCSSA]]
+;
; SPARC64-NOCPOP-LABEL: @popcount_i32(
; SPARC64-NOCPOP-NEXT: entry:
; SPARC64-NOCPOP-NEXT: [[TOBOOL3:%.*]] = icmp eq i32 [[A:%.*]], 0
@@ -145,6 +231,27 @@ while.end: ; preds = %while.body, %entry
}
define i32 @popcount_i128(i128 %a) nounwind uwtable readnone ssp {
+; SPARC-CPOP-LABEL: @popcount_i128(
+; SPARC-CPOP-NEXT: entry:
+; SPARC-CPOP-NEXT: [[TOBOOL3:%.*]] = icmp eq i128 [[A:%.*]], 0
+; SPARC-CPOP-NEXT: br i1 [[TOBOOL3]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
+; SPARC-CPOP: while.body.preheader:
+; SPARC-CPOP-NEXT: br label [[WHILE_BODY:%.*]]
+; SPARC-CPOP: while.body:
+; SPARC-CPOP-NEXT: [[C_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
+; SPARC-CPOP-NEXT: [[A_ADDR_04:%.*]] = phi i128 [ [[AND:%.*]], [[WHILE_BODY]] ], [ [[A]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC-CPOP-NEXT: [[INC]] = add nsw i32 [[C_05]], 1
+; SPARC-CPOP-NEXT: [[SUB:%.*]] = add i128 [[A_ADDR_04]], -1
+; SPARC-CPOP-NEXT: [[AND]] = and i128 [[SUB]], [[A_ADDR_04]]
+; SPARC-CPOP-NEXT: [[TOBOOL:%.*]] = icmp eq i128 [[AND]], 0
+; SPARC-CPOP-NEXT: br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
+; SPARC-CPOP: while.end.loopexit:
+; SPARC-CPOP-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[INC]], [[WHILE_BODY]] ]
+; SPARC-CPOP-NEXT: br label [[WHILE_END]]
+; SPARC-CPOP: while.end:
+; SPARC-CPOP-NEXT: [[C_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC-CPOP-NEXT: ret i32 [[C_0_LCSSA]]
+;
; SPARC64-CPOP-LABEL: @popcount_i128(
; SPARC64-CPOP-NEXT: entry:
; SPARC64-CPOP-NEXT: [[TMP0:%.*]] = call i128 @llvm.ctpop.i128(i128 [[A:%.*]])
@@ -170,6 +277,27 @@ define i32 @popcount_i128(i128 %a) nounwind uwtable readnone ssp {
; SPARC64-CPOP-NEXT: [[C_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
; SPARC64-CPOP-NEXT: ret i32 [[C_0_LCSSA]]
;
+; SPARC-NOCPOP-LABEL: @popcount_i128(
+; SPARC-NOCPOP-NEXT: entry:
+; SPARC-NOCPOP-NEXT: [[TOBOOL3:%.*]] = icmp eq i128 [[A:%.*]], 0
+; SPARC-NOCPOP-NEXT: br i1 [[TOBOOL3]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
+; SPARC-NOCPOP: while.body.preheader:
+; SPARC-NOCPOP-NEXT: br label [[WHILE_BODY:%.*]]
+; SPARC-NOCPOP: while.body:
+; SPARC-NOCPOP-NEXT: [[C_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
+; SPARC-NOCPOP-NEXT: [[A_ADDR_04:%.*]] = phi i128 [ [[AND:%.*]], [[WHILE_BODY]] ], [ [[A]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC-NOCPOP-NEXT: [[INC]] = add nsw i32 [[C_05]], 1
+; SPARC-NOCPOP-NEXT: [[SUB:%.*]] = add i128 [[A_ADDR_04]], -1
+; SPARC-NOCPOP-NEXT: [[AND]] = and i128 [[SUB]], [[A_ADDR_04]]
+; SPARC-NOCPOP-NEXT: [[TOBOOL:%.*]] = icmp eq i128 [[AND]], 0
+; SPARC-NOCPOP-NEXT: br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
+; SPARC-NOCPOP: while.end.loopexit:
+; SPARC-NOCPOP-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[INC]], [[WHILE_BODY]] ]
+; SPARC-NOCPOP-NEXT: br label [[WHILE_END]]
+; SPARC-NOCPOP: while.end:
+; SPARC-NOCPOP-NEXT: [[C_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC-NOCPOP-NEXT: ret i32 [[C_0_LCSSA]]
+;
; SPARC64-NOCPOP-LABEL: @popcount_i128(
; SPARC64-NOCPOP-NEXT: entry:
; SPARC64-NOCPOP-NEXT: [[TOBOOL3:%.*]] = icmp eq i128 [[A:%.*]], 0
@@ -222,6 +350,38 @@ while.end: ; preds = %while.body, %entry
;}
define i32 @popcount2(i64 %a, i32 %mydata1, i32 %mydata2) nounwind uwtable readnone ssp {
+; SPARC-CPOP-LABEL: @popcount2(
+; SPARC-CPOP-NEXT: entry:
+; SPARC-CPOP-NEXT: [[TOBOOL9:%.*]] = icmp eq i64 [[A:%.*]], 0
+; SPARC-CPOP-NEXT: br i1 [[TOBOOL9]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
+; SPARC-CPOP: while.body.preheader:
+; SPARC-CPOP-NEXT: br label [[WHILE_BODY:%.*]]
+; SPARC-CPOP: while.body:
+; SPARC-CPOP-NEXT: [[C_013:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
+; SPARC-CPOP-NEXT: [[MYDATA2_ADDR_012:%.*]] = phi i32 [ [[MUL1:%.*]], [[WHILE_BODY]] ], [ [[MYDATA2:%.*]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC-CPOP-NEXT: [[MYDATA1_ADDR_011:%.*]] = phi i32 [ [[MUL:%.*]], [[WHILE_BODY]] ], [ [[MYDATA1:%.*]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC-CPOP-NEXT: [[A_ADDR_010:%.*]] = phi i64 [ [[AND:%.*]], [[WHILE_BODY]] ], [ [[A]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC-CPOP-NEXT: [[INC]] = add nsw i32 [[C_013]], 1
+; SPARC-CPOP-NEXT: [[SUB:%.*]] = add i64 [[A_ADDR_010]], -1
+; SPARC-CPOP-NEXT: [[AND]] = and i64 [[SUB]], [[A_ADDR_010]]
+; SPARC-CPOP-NEXT: [[MUL]] = mul nsw i32 [[INC]], [[MYDATA1_ADDR_011]]
+; SPARC-CPOP-NEXT: [[CONV:%.*]] = trunc i64 [[AND]] to i32
+; SPARC-CPOP-NEXT: [[MUL1]] = mul nsw i32 [[CONV]], [[MYDATA2_ADDR_012]]
+; SPARC-CPOP-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[AND]], 0
+; SPARC-CPOP-NEXT: br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
+; SPARC-CPOP: while.end.loopexit:
+; SPARC-CPOP-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[INC]], [[WHILE_BODY]] ]
+; SPARC-CPOP-NEXT: [[MUL_LCSSA:%.*]] = phi i32 [ [[MUL]], [[WHILE_BODY]] ]
+; SPARC-CPOP-NEXT: [[MUL1_LCSSA:%.*]] = phi i32 [ [[MUL1]], [[WHILE_BODY]] ]
+; SPARC-CPOP-NEXT: br label [[WHILE_END]]
+; SPARC-CPOP: while.end:
+; SPARC-CPOP-NEXT: [[C_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC-CPOP-NEXT: [[MYDATA2_ADDR_0_LCSSA:%.*]] = phi i32 [ [[MYDATA2]], [[ENTRY]] ], [ [[MUL1_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC-CPOP-NEXT: [[MYDATA1_ADDR_0_LCSSA:%.*]] = phi i32 [ [[MYDATA1]], [[ENTRY]] ], [ [[MUL_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC-CPOP-NEXT: [[ADD:%.*]] = add i32 [[MYDATA2_ADDR_0_LCSSA]], [[MYDATA1_ADDR_0_LCSSA]]
+; SPARC-CPOP-NEXT: [[ADD2:%.*]] = add i32 [[ADD]], [[C_0_LCSSA]]
+; SPARC-CPOP-NEXT: ret i32 [[ADD2]]
+;
; SPARC64-CPOP-LABEL: @popcount2(
; SPARC64-CPOP-NEXT: entry:
; SPARC64-CPOP-NEXT: [[TMP0:%.*]] = call i64 @llvm.ctpop.i64(i64 [[A:%.*]])
@@ -258,6 +418,38 @@ define i32 @popcount2(i64 %a, i32 %mydata1, i32 %mydata2) nounwind uwtable readn
; SPARC64-CPOP-NEXT: [[ADD2:%.*]] = add i32 [[ADD]], [[C_0_LCSSA]]
; SPARC64-CPOP-NEXT: ret i32 [[ADD2]]
;
+; SPARC-NOCPOP-LABEL: @popcount2(
+; SPARC-NOCPOP-NEXT: entry:
+; SPARC-NOCPOP-NEXT: [[TOBOOL9:%.*]] = icmp eq i64 [[A:%.*]], 0
+; SPARC-NOCPOP-NEXT: br i1 [[TOBOOL9]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
+; SPARC-NOCPOP: while.body.preheader:
+; SPARC-NOCPOP-NEXT: br label [[WHILE_BODY:%.*]]
+; SPARC-NOCPOP: while.body:
+; SPARC-NOCPOP-NEXT: [[C_013:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
+; SPARC-NOCPOP-NEXT: [[MYDATA2_ADDR_012:%.*]] = phi i32 [ [[MUL1:%.*]], [[WHILE_BODY]] ], [ [[MYDATA2:%.*]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC-NOCPOP-NEXT: [[MYDATA1_ADDR_011:%.*]] = phi i32 [ [[MUL:%.*]], [[WHILE_BODY]] ], [ [[MYDATA1:%.*]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC-NOCPOP-NEXT: [[A_ADDR_010:%.*]] = phi i64 [ [[AND:%.*]], [[WHILE_BODY]] ], [ [[A]], [[WHILE_BODY_PREHEADER]] ]
+; SPARC-NOCPOP-NEXT: [[INC]] = add nsw i32 [[C_013]], 1
+; SPARC-NOCPOP-NEXT: [[SUB:%.*]] = add i64 [[A_ADDR_010]], -1
+; SPARC-NOCPOP-NEXT: [[AND]] = and i64 [[SUB]], [[A_ADDR_010]]
+; SPARC-NOCPOP-NEXT: [[MUL]] = mul nsw i32 [[INC]], [[MYDATA1_ADDR_011]]
+; SPARC-NOCPOP-NEXT: [[CONV:%.*]] = trunc i64 [[AND]] to i32
+; SPARC-NOCPOP-NEXT: [[MUL1]] = mul nsw i32 [[CONV]], [[MYDATA2_ADDR_012]]
+; SPARC-NOCPOP-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[AND]], 0
+; SPARC-NOCPOP-NEXT: br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
+; SPARC-NOCPOP: while.end.loopexit:
+; SPARC-NOCPOP-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[INC]], [[WHILE_BODY]] ]
+; SPARC-NOCPOP-NEXT: [[MUL_LCSSA:%.*]] = phi i32 [ [[MUL]], [[WHILE_BODY]] ]
+; SPARC-NOCPOP-NEXT: [[MUL1_LCSSA:%.*]] = phi i32 [ [[MUL1]], [[WHILE_BODY]] ]
+; SPARC-NOCPOP-NEXT: br label [[WHILE_END]]
+; SPARC-NOCPOP: while.end:
+; SPARC-NOCPOP-NEXT: [[C_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC-NOCPOP-NEXT: [[MYDATA2_ADDR_0_LCSSA:%.*]] = phi i32 [ [[MYDATA2]], [[ENTRY]] ], [ [[MUL1_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC-NOCPOP-NEXT: [[MYDATA1_ADDR_0_LCSSA:%.*]] = phi i32 [ [[MYDATA1]], [[ENTRY]] ], [ [[MUL_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
+; SPARC-NOCPOP-NEXT: [[ADD:%.*]] = add i32 [[MYDATA2_ADDR_0_LCSSA]], [[MYDATA1_ADDR_0_LCSSA]]
+; SPARC-NOCPOP-NEXT: [[ADD2:%.*]] = add i32 [[ADD]], [[C_0_LCSSA]]
+; SPARC-NOCPOP-NEXT: ret i32 [[ADD2]]
+;
; SPARC64-NOCPOP-LABEL: @popcount2(
; SPARC64-NOCPOP-NEXT: entry:
; SPARC64-NOCPOP-NEXT: [[TOBOOL9:%.*]] = icmp eq i64 [[A:%.*]], 0
>From 6d20706ade00a2a9747b8921cdc29e95d5c95ee5 Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Fri, 30 Jan 2026 23:44:45 +0700
Subject: [PATCH 5/5] Add lit config
---
llvm/test/Transforms/LoopIdiom/Sparc/lit.local.cfg | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 llvm/test/Transforms/LoopIdiom/Sparc/lit.local.cfg
diff --git a/llvm/test/Transforms/LoopIdiom/Sparc/lit.local.cfg b/llvm/test/Transforms/LoopIdiom/Sparc/lit.local.cfg
new file mode 100644
index 0000000000000..4f5128663c5ac
--- /dev/null
+++ b/llvm/test/Transforms/LoopIdiom/Sparc/lit.local.cfg
@@ -0,0 +1,2 @@
+if not "Sparc" in config.root.targets:
+ config.unsupported = True
More information about the llvm-commits
mailing list