[llvm] [CodeGen] Add preliminary plumbing for `samesign` flag (PR #112354)
Antonio Frighetto via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 22 17:42:00 PDT 2024
https://github.com/antoniofrighetto updated https://github.com/llvm/llvm-project/pull/112354
>From 276ebf5817594de082977bf67f3afa5f0f440ea7 Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Tue, 15 Oct 2024 15:08:25 +0200
Subject: [PATCH 1/4] [SelectionDAG] Add preliminary plumbing for `samesign`
Extend recently-added poison-generating IR flag to codegen as well.
---
llvm/include/llvm/CodeGen/SelectionDAGNodes.h | 14 +++++++++-----
.../CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 4 ++++
.../CodeGen/SelectionDAG/SelectionDAGDumper.cpp | 3 +++
llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp | 8 +++++++-
4 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
index 639e9311977502..bad19173683101 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -382,6 +382,7 @@ struct SDNodeFlags {
bool NoSignedWrap : 1;
bool Exact : 1;
bool Disjoint : 1;
+ bool SameSign : 1;
bool NonNeg : 1;
bool NoNaNs : 1;
bool NoInfs : 1;
@@ -404,10 +405,10 @@ struct SDNodeFlags {
/// Default constructor turns off all optimization flags.
SDNodeFlags()
: NoUnsignedWrap(false), NoSignedWrap(false), Exact(false),
- Disjoint(false), NonNeg(false), NoNaNs(false), NoInfs(false),
- NoSignedZeros(false), AllowReciprocal(false), AllowContract(false),
- ApproximateFuncs(false), AllowReassociation(false), NoFPExcept(false),
- Unpredictable(false) {}
+ Disjoint(false), SameSign(false), NonNeg(false), NoNaNs(false),
+ NoInfs(false), NoSignedZeros(false), AllowReciprocal(false),
+ AllowContract(false), ApproximateFuncs(false),
+ AllowReassociation(false), NoFPExcept(false), Unpredictable(false) {}
/// Propagate the fast-math-flags from an IR FPMathOperator.
void copyFMF(const FPMathOperator &FPMO) {
@@ -425,6 +426,7 @@ struct SDNodeFlags {
void setNoSignedWrap(bool b) { NoSignedWrap = b; }
void setExact(bool b) { Exact = b; }
void setDisjoint(bool b) { Disjoint = b; }
+ void setSameSign(bool b) { SameSign = b; }
void setNonNeg(bool b) { NonNeg = b; }
void setNoNaNs(bool b) { NoNaNs = b; }
void setNoInfs(bool b) { NoInfs = b; }
@@ -441,6 +443,7 @@ struct SDNodeFlags {
bool hasNoSignedWrap() const { return NoSignedWrap; }
bool hasExact() const { return Exact; }
bool hasDisjoint() const { return Disjoint; }
+ bool hasSameSign() const { return SameSign; }
bool hasNonNeg() const { return NonNeg; }
bool hasNoNaNs() const { return NoNaNs; }
bool hasNoInfs() const { return NoInfs; }
@@ -473,6 +476,7 @@ struct SDNodeFlags {
NoSignedWrap &= Flags.NoSignedWrap;
Exact &= Flags.Exact;
Disjoint &= Flags.Disjoint;
+ SameSign &= Flags.SameSign;
NonNeg &= Flags.NonNeg;
NoNaNs &= Flags.NoNaNs;
NoInfs &= Flags.NoInfs;
@@ -1032,7 +1036,7 @@ END_TWO_BYTE_PACK()
SDNodeFlags Flags = getFlags();
return Flags.hasNoUnsignedWrap() || Flags.hasNoSignedWrap() ||
Flags.hasExact() || Flags.hasDisjoint() || Flags.hasNonNeg() ||
- Flags.hasNoNaNs() || Flags.hasNoInfs();
+ Flags.hasNoNaNs() || Flags.hasNoInfs() || Flags.hasSameSign();
}
void setCFIType(uint32_t Type) { CFIType = Type; }
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 805b8ecf009598..35ea9419f2dd1a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3640,6 +3640,10 @@ void SelectionDAGBuilder::visitICmp(const ICmpInst &I) {
SDValue Op2 = getValue(I.getOperand(1));
ISD::CondCode Opcode = getICmpCondCode(predicate);
+ SDNodeFlags Flags;
+ Flags.setSameSign(I.hasSameSign());
+ SelectionDAG::FlagInserter FlagsInserter(DAG, Flags);
+
auto &TLI = DAG.getTargetLoweringInfo();
EVT MemVT =
TLI.getMemValueType(DAG.getDataLayout(), I.getOperand(0)->getType());
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index 56fc538172f9fc..24fc83b422147f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -651,6 +651,9 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const {
if (getFlags().hasDisjoint())
OS << " disjoint";
+ if (getFlags().hasSameSign())
+ OS << " samesign";
+
if (getFlags().hasNonNeg())
OS << " nneg";
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 40f030d7b936f7..43e6a43e820b5a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -1703,6 +1703,7 @@ bool TargetLowering::SimplifyDemandedBits(
case ISD::SETCC: {
SDValue Op0 = Op.getOperand(0);
SDValue Op1 = Op.getOperand(1);
+ SDNodeFlags Flags = Op.getNode()->getFlags();
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
// If (1) we only need the sign-bit, (2) the setcc operands are the same
// width as the setcc result, and (3) the result of a setcc conforms to 0 or
@@ -1716,8 +1717,13 @@ bool TargetLowering::SimplifyDemandedBits(
// if we don't care about FP signed-zero. The use of SETLT with FP means
// that we don't care about NaNs.
if (CC == ISD::SETLT && Op1.getValueType().isInteger() &&
- (isNullConstant(Op1) || ISD::isBuildVectorAllZeros(Op1.getNode())))
+ (isNullConstant(Op1) || ISD::isBuildVectorAllZeros(Op1.getNode()))) {
+ if (Flags.hasSameSign()) {
+ Flags.setSameSign(false);
+ Op->setFlags(Flags);
+ }
return TLO.CombineTo(Op, Op0);
+ }
// TODO: Should we check for other forms of sign-bit comparisons?
// Examples: X <= -1, X >= 0
>From a4b4f9d9e751f1a3fba7626f663a512810fef3fb Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Wed, 16 Oct 2024 12:22:08 +0200
Subject: [PATCH 2/4] !fixup extend to operator==, instremitter, mirparser
---
llvm/include/llvm/CodeGen/MachineInstr.h | 1 +
llvm/include/llvm/CodeGen/SelectionDAGNodes.h | 6 +++---
llvm/lib/CodeGen/MIRParser/MILexer.cpp | 1 +
llvm/lib/CodeGen/MIRParser/MILexer.h | 1 +
llvm/lib/CodeGen/MIRParser/MIParser.cpp | 5 ++++-
llvm/lib/CodeGen/MIRPrinter.cpp | 2 ++
llvm/lib/CodeGen/MachineInstr.cpp | 8 ++++++++
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 3 +++
8 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h
index 76a7b8662bae66..2dde32a58c016c 100644
--- a/llvm/include/llvm/CodeGen/MachineInstr.h
+++ b/llvm/include/llvm/CodeGen/MachineInstr.h
@@ -119,6 +119,7 @@ class MachineInstr
Disjoint = 1 << 19, // Each bit is zero in at least one of the inputs.
NoUSWrap = 1 << 20, // Instruction supports geps
// no unsigned signed wrap.
+ SameSign = 1 << 21, // Compare instruction has same sign.
};
private:
diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
index bad19173683101..bab17d36e8e6b5 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -458,9 +458,9 @@ struct SDNodeFlags {
bool operator==(const SDNodeFlags &Other) const {
return NoUnsignedWrap == Other.NoUnsignedWrap &&
NoSignedWrap == Other.NoSignedWrap && Exact == Other.Exact &&
- Disjoint == Other.Disjoint && NonNeg == Other.NonNeg &&
- NoNaNs == Other.NoNaNs && NoInfs == Other.NoInfs &&
- NoSignedZeros == Other.NoSignedZeros &&
+ Disjoint == Other.Disjoint && SameSign == Other.SameSign &&
+ NonNeg == Other.NonNeg && NoNaNs == Other.NoNaNs &&
+ NoInfs == Other.NoInfs && NoSignedZeros == Other.NoSignedZeros &&
AllowReciprocal == Other.AllowReciprocal &&
AllowContract == Other.AllowContract &&
ApproximateFuncs == Other.ApproximateFuncs &&
diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.cpp b/llvm/lib/CodeGen/MIRParser/MILexer.cpp
index 0809f88fde56b1..51c203ae9d9083 100644
--- a/llvm/lib/CodeGen/MIRParser/MILexer.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MILexer.cpp
@@ -216,6 +216,7 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
.Case("exact", MIToken::kw_exact)
.Case("nneg", MIToken::kw_nneg)
.Case("disjoint", MIToken::kw_disjoint)
+ .Case("samesign", MIToken::kw_samesign)
.Case("nofpexcept", MIToken::kw_nofpexcept)
.Case("unpredictable", MIToken::kw_unpredictable)
.Case("debug-location", MIToken::kw_debug_location)
diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.h b/llvm/lib/CodeGen/MIRParser/MILexer.h
index 22547483a8a86b..fd24b0b64bf9ed 100644
--- a/llvm/lib/CodeGen/MIRParser/MILexer.h
+++ b/llvm/lib/CodeGen/MIRParser/MILexer.h
@@ -77,6 +77,7 @@ struct MIToken {
kw_unpredictable,
kw_nneg,
kw_disjoint,
+ kw_samesign,
kw_debug_location,
kw_debug_instr_number,
kw_dbg_instr_ref,
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 7aaa0f409d5ef9..d0184a7387ce47 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -1476,7 +1476,8 @@ bool MIParser::parseInstruction(unsigned &OpCode, unsigned &Flags) {
Token.is(MIToken::kw_noconvergent) ||
Token.is(MIToken::kw_unpredictable) ||
Token.is(MIToken::kw_nneg) ||
- Token.is(MIToken::kw_disjoint)) {
+ Token.is(MIToken::kw_disjoint) ||
+ Token.is(MIToken::kw_samesign)) {
// clang-format on
// Mine frame and fast math flags
if (Token.is(MIToken::kw_frame_setup))
@@ -1513,6 +1514,8 @@ bool MIParser::parseInstruction(unsigned &OpCode, unsigned &Flags) {
Flags |= MachineInstr::NonNeg;
if (Token.is(MIToken::kw_disjoint))
Flags |= MachineInstr::Disjoint;
+ if (Token.is(MIToken::kw_samesign))
+ Flags |= MachineInstr::SameSign;
lex();
}
diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp
index a015cd3c2a55f9..658bbe0e577e5c 100644
--- a/llvm/lib/CodeGen/MIRPrinter.cpp
+++ b/llvm/lib/CodeGen/MIRPrinter.cpp
@@ -837,6 +837,8 @@ void MIPrinter::print(const MachineInstr &MI) {
OS << "disjoint ";
if (MI.getFlag(MachineInstr::NoUSWrap))
OS << "nusw ";
+ if (MI.getFlag(MachineInstr::SameSign))
+ OS << "samesign ";
OS << TII->getName(MI.getOpcode());
if (I < E)
diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp
index 0d78c2cafbaf63..06e28aee1d9689 100644
--- a/llvm/lib/CodeGen/MachineInstr.cpp
+++ b/llvm/lib/CodeGen/MachineInstr.cpp
@@ -620,6 +620,12 @@ uint32_t MachineInstr::copyFlagsFromInstruction(const Instruction &I) {
MIFlags |= MachineInstr::MIFlag::FmReassoc;
}
+ // Copy the samesign flag.
+ if (const auto *ICI = dyn_cast<ICmpInst>(&I)) {
+ if (ICI->hasSameSign())
+ MIFlags |= MachineInstr::MIFlag::SameSign;
+ }
+
if (I.getMetadata(LLVMContext::MD_unpredictable))
MIFlags |= MachineInstr::MIFlag::Unpredictable;
@@ -1773,6 +1779,8 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
OS << "nneg ";
if (getFlag(MachineInstr::Disjoint))
OS << "disjoint ";
+ if (getFlag(MachineInstr::SameSign))
+ OS << "samesign ";
// Print the opcode name.
if (TII)
diff --git a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
index 281d1578d0173a..9c7085cc7e7a83 100644
--- a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
@@ -1105,6 +1105,9 @@ EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned,
if (Flags.hasDisjoint())
MI->setFlag(MachineInstr::MIFlag::Disjoint);
+
+ if (Flags.hasSameSign())
+ MI->setFlag(MachineInstr::MIFlag::SameSign);
}
// Emit all of the actual operands of this instruction, adding them to the
>From 799fd9f38c7550525820ee9e9c2e719c1c1d6886 Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Fri, 18 Oct 2024 20:59:21 +0200
Subject: [PATCH 3/4] !fixup postpone set flag
---
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 35ea9419f2dd1a..5667953e3871c9 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3640,10 +3640,6 @@ void SelectionDAGBuilder::visitICmp(const ICmpInst &I) {
SDValue Op2 = getValue(I.getOperand(1));
ISD::CondCode Opcode = getICmpCondCode(predicate);
- SDNodeFlags Flags;
- Flags.setSameSign(I.hasSameSign());
- SelectionDAG::FlagInserter FlagsInserter(DAG, Flags);
-
auto &TLI = DAG.getTargetLoweringInfo();
EVT MemVT =
TLI.getMemValueType(DAG.getDataLayout(), I.getOperand(0)->getType());
@@ -3656,6 +3652,10 @@ void SelectionDAGBuilder::visitICmp(const ICmpInst &I) {
Op2 = DAG.getPtrExtOrTrunc(Op2, getCurSDLoc(), MemVT);
}
+ SDNodeFlags Flags;
+ Flags.setSameSign(I.hasSameSign());
+ SelectionDAG::FlagInserter FlagsInserter(DAG, Flags);
+
EVT DestVT = DAG.getTargetLoweringInfo().getValueType(DAG.getDataLayout(),
I.getType());
setValue(&I, DAG.getSetCC(getCurSDLoc(), DestVT, Op1, Op2, Opcode));
>From cd90fa8612c5681faf773cfc208d1053b356035a Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Wed, 23 Oct 2024 02:19:49 +0200
Subject: [PATCH 4/4] !fixup add test, drop clearing flags
---
.../CodeGen/GlobalISel/MachineIRBuilder.h | 3 +-
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 8 ++---
.../CodeGen/GlobalISel/MachineIRBuilder.cpp | 5 +--
.../CodeGen/SelectionDAG/TargetLowering.cpp | 8 +----
.../GlobalISel/irtranslator-icmp-samesign.ll | 33 +++++++++++++++++++
5 files changed, 43 insertions(+), 14 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-icmp-samesign.ll
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index 9b993482c8cc07..68a81a6f5e598a 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -1255,7 +1255,8 @@ class MachineIRBuilder {
///
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildICmp(CmpInst::Predicate Pred, const DstOp &Res,
- const SrcOp &Op0, const SrcOp &Op1);
+ const SrcOp &Op0, const SrcOp &Op1,
+ std::optional<unsigned> Flags = std::nullopt);
/// Build and insert a \p Res = G_FCMP \p Pred\p Op0, \p Op1
///
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index d0464670b292a4..097749afefe344 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -340,8 +340,11 @@ bool IRTranslator::translateCompare(const User &U,
Register Op1 = getOrCreateVReg(*U.getOperand(1));
Register Res = getOrCreateVReg(U);
CmpInst::Predicate Pred = CI->getPredicate();
+ uint32_t Flags = 0;
+ if (CI)
+ Flags = MachineInstr::copyFlagsFromInstruction(*CI);
if (CmpInst::isIntPredicate(Pred))
- MIRBuilder.buildICmp(Pred, Res, Op0, Op1);
+ MIRBuilder.buildICmp(Pred, Res, Op0, Op1, Flags);
else if (Pred == CmpInst::FCMP_FALSE)
MIRBuilder.buildCopy(
Res, getOrCreateVReg(*Constant::getNullValue(U.getType())));
@@ -349,9 +352,6 @@ bool IRTranslator::translateCompare(const User &U,
MIRBuilder.buildCopy(
Res, getOrCreateVReg(*Constant::getAllOnesValue(U.getType())));
else {
- uint32_t Flags = 0;
- if (CI)
- Flags = MachineInstr::copyFlagsFromInstruction(*CI);
MIRBuilder.buildFCmp(Pred, Res, Op0, Op1, Flags);
}
diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index 59f2fc633f5de7..15b9164247846c 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -898,8 +898,9 @@ MachineIRBuilder::buildFPTrunc(const DstOp &Res, const SrcOp &Op,
MachineInstrBuilder MachineIRBuilder::buildICmp(CmpInst::Predicate Pred,
const DstOp &Res,
const SrcOp &Op0,
- const SrcOp &Op1) {
- return buildInstr(TargetOpcode::G_ICMP, Res, {Pred, Op0, Op1});
+ const SrcOp &Op1,
+ std::optional<unsigned> Flags) {
+ return buildInstr(TargetOpcode::G_ICMP, Res, {Pred, Op0, Op1}, Flags);
}
MachineInstrBuilder MachineIRBuilder::buildFCmp(CmpInst::Predicate Pred,
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 43e6a43e820b5a..40f030d7b936f7 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -1703,7 +1703,6 @@ bool TargetLowering::SimplifyDemandedBits(
case ISD::SETCC: {
SDValue Op0 = Op.getOperand(0);
SDValue Op1 = Op.getOperand(1);
- SDNodeFlags Flags = Op.getNode()->getFlags();
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
// If (1) we only need the sign-bit, (2) the setcc operands are the same
// width as the setcc result, and (3) the result of a setcc conforms to 0 or
@@ -1717,13 +1716,8 @@ bool TargetLowering::SimplifyDemandedBits(
// if we don't care about FP signed-zero. The use of SETLT with FP means
// that we don't care about NaNs.
if (CC == ISD::SETLT && Op1.getValueType().isInteger() &&
- (isNullConstant(Op1) || ISD::isBuildVectorAllZeros(Op1.getNode()))) {
- if (Flags.hasSameSign()) {
- Flags.setSameSign(false);
- Op->setFlags(Flags);
- }
+ (isNullConstant(Op1) || ISD::isBuildVectorAllZeros(Op1.getNode())))
return TLO.CombineTo(Op, Op0);
- }
// TODO: Should we check for other forms of sign-bit comparisons?
// Examples: X <= -1, X >= 0
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-icmp-samesign.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-icmp-samesign.ll
new file mode 100644
index 00000000000000..1bf1c8d7119d16
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-icmp-samesign.ll
@@ -0,0 +1,33 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=aarch64-linux-gnu -O0 -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - 2>&1 | FileCheck %s
+
+define i1 @icmp_samesign(i32 %a, i32 %b) {
+ ; CHECK-LABEL: name: icmp_samesign
+ ; CHECK: bb.1 (%ir-block.0):
+ ; CHECK-NEXT: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
+ ; CHECK-NEXT: %2:_(s1) = samesign G_ICMP intpred(ult), [[COPY]](s32), [[COPY1]]
+ ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s8) = G_ZEXT %2(s1)
+ ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[ZEXT]](s8)
+ ; CHECK-NEXT: $w0 = COPY [[ANYEXT]](s32)
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ %res = icmp samesign ult i32 %a, %b
+ ret i1 %res
+}
+
+define <2 x i1> @icmp_samesign2(<2 x i32> %a, <2 x i32> %b) {
+ ; CHECK-LABEL: name: icmp_samesign2
+ ; CHECK: bb.1 (%ir-block.0):
+ ; CHECK-NEXT: liveins: $d0, $d1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $d1
+ ; CHECK-NEXT: %2:_(<2 x s1>) = samesign G_ICMP intpred(ult), [[COPY]](<2 x s32>), [[COPY1]]
+ ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(<2 x s32>) = G_ANYEXT %2(<2 x s1>)
+ ; CHECK-NEXT: $d0 = COPY [[ANYEXT]](<2 x s32>)
+ ; CHECK-NEXT: RET_ReallyLR implicit $d0
+ %res = icmp samesign ult <2 x i32> %a, %b
+ ret <2 x i1> %res
+}
More information about the llvm-commits
mailing list