Skip to content

Commit 9efb07f

Browse files
authored
[IR] Add samesign flag to icmp instruction (#111419)
Inspired by https://discourse.llvm.org/t/rfc-signedness-independent-icmps/81423
1 parent 4852120 commit 9efb07f

File tree

16 files changed

+116
-5
lines changed

16 files changed

+116
-5
lines changed

llvm/docs/LangRef.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12331,6 +12331,7 @@ Syntax:
1233112331
::
1233212332

1233312333
<result> = icmp <cond> <ty> <op1>, <op2> ; yields i1 or <N x i1>:result
12334+
<result> = icmp samesign <cond> <ty> <op1>, <op2> ; yields i1 or <N x i1>:result
1233412335

1233512336
Overview:
1233612337
"""""""""
@@ -12400,6 +12401,9 @@ If the operands are integer vectors, then they are compared element by
1240012401
element. The result is an ``i1`` vector with the same number of elements
1240112402
as the values being compared. Otherwise, the result is an ``i1``.
1240212403

12404+
If the ``samesign`` keyword is present and the operands are not of the
12405+
same sign then the result is a :ref:`poison value <poisonvalues>`.
12406+
1240312407
Example:
1240412408
""""""""
1240512409

llvm/include/llvm/AsmParser/LLToken.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ enum Kind {
114114
kw_disjoint,
115115
kw_inbounds,
116116
kw_nneg,
117+
kw_samesign,
117118
kw_inrange,
118119
kw_addrspace,
119120
kw_section,

llvm/include/llvm/Bitcode/LLVMBitCodes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,10 @@ enum GetElementPtrOptionalFlags {
540540
GEP_NUW = 2,
541541
};
542542

543+
/// ICmpOptionalFlags - Flags for serializing
544+
/// ICmpOptionalFlags's SubclassOptionalData contents.
545+
enum ICmpOptionalFlags { ICMP_SAME_SIGN = 0 };
546+
543547
/// Encoded AtomicOrdering values.
544548
enum AtomicOrderingCodes {
545549
ORDERING_NOTATOMIC = 0,

llvm/include/llvm/IR/Instructions.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,6 +1165,8 @@ class ICmpInst: public CmpInst {
11651165
"Invalid operand types for ICmp instruction");
11661166
}
11671167

1168+
enum { SameSign = (1 << 0) };
1169+
11681170
protected:
11691171
// Note: Instruction needs to be a friend here to call cloneImpl.
11701172
friend class Instruction;
@@ -1224,6 +1226,15 @@ class ICmpInst: public CmpInst {
12241226
/// Return the unsigned version of the predicate.
12251227
static Predicate getUnsignedPredicate(Predicate pred);
12261228

1229+
void setSameSign(bool B = true) {
1230+
SubclassOptionalData = (SubclassOptionalData & ~SameSign) | (B * SameSign);
1231+
}
1232+
1233+
/// An icmp instruction, which can be marked as "samesign", indicating that
1234+
/// the two operands have the same sign. This means that we can convert
1235+
/// "slt" to "ult" and vice versa, which enables more optimizations.
1236+
bool hasSameSign() const { return SubclassOptionalData & SameSign; }
1237+
12271238
/// Return true if this predicate is either EQ or NE. This also
12281239
/// tests for commutativity.
12291240
static bool isEquality(Predicate P) {

llvm/include/llvm/Transforms/Utils/ScalarEvolutionExpander.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ struct PoisonFlags {
4747
unsigned Exact : 1;
4848
unsigned Disjoint : 1;
4949
unsigned NNeg : 1;
50+
unsigned SameSign : 1;
5051
GEPNoWrapFlags GEPNW;
5152

5253
PoisonFlags(const Instruction *I);

llvm/lib/AsmParser/LLLexer.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,7 @@ lltok::Kind LLLexer::LexIdentifier() {
583583
KEYWORD(disjoint);
584584
KEYWORD(inbounds);
585585
KEYWORD(nneg);
586+
KEYWORD(samesign);
586587
KEYWORD(inrange);
587588
KEYWORD(addrspace);
588589
KEYWORD(section);

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6952,8 +6952,14 @@ int LLParser::parseInstruction(Instruction *&Inst, BasicBlock *BB,
69526952
case lltok::kw_and:
69536953
case lltok::kw_xor:
69546954
return parseLogical(Inst, PFS, KeywordVal);
6955-
case lltok::kw_icmp:
6956-
return parseCompare(Inst, PFS, KeywordVal);
6955+
case lltok::kw_icmp: {
6956+
bool SameSign = EatIfPresent(lltok::kw_samesign);
6957+
if (parseCompare(Inst, PFS, KeywordVal))
6958+
return true;
6959+
if (SameSign)
6960+
cast<ICmpInst>(Inst)->setSameSign();
6961+
return false;
6962+
}
69576963
case lltok::kw_fcmp: {
69586964
FastMathFlags FMF = EatFastMathFlagsIfPresent();
69596965
int Res = parseCompare(Inst, PFS, KeywordVal);

llvm/lib/Bitcode/Reader/BitcodeReader.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5471,9 +5471,6 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
54715471
if (IsFP && Record.size() > OpNum+1)
54725472
FMF = getDecodedFastMathFlags(Record[++OpNum]);
54735473

5474-
if (OpNum+1 != Record.size())
5475-
return error("Invalid record");
5476-
54775474
if (IsFP) {
54785475
if (!CmpInst::isFPPredicate(PredVal))
54795476
return error("Invalid fcmp predicate");
@@ -5482,8 +5479,14 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
54825479
if (!CmpInst::isIntPredicate(PredVal))
54835480
return error("Invalid icmp predicate");
54845481
I = new ICmpInst(PredVal, LHS, RHS);
5482+
if (Record.size() > OpNum + 1 &&
5483+
(Record[++OpNum] & (1 << bitc::ICMP_SAME_SIGN)))
5484+
cast<ICmpInst>(I)->setSameSign();
54855485
}
54865486

5487+
if (OpNum + 1 != Record.size())
5488+
return error("Invalid record");
5489+
54875490
ResTypeID = getVirtualTypeID(I->getType()->getScalarType());
54885491
if (LHS->getType()->isVectorTy())
54895492
ResTypeID = getVirtualTypeID(I->getType(), ResTypeID);

llvm/lib/Bitcode/Writer/BitcodeWriter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,6 +1718,9 @@ static uint64_t getOptimizationFlags(const Value *V) {
17181718
Flags |= 1 << bitc::GEP_NUSW;
17191719
if (GEP->hasNoUnsignedWrap())
17201720
Flags |= 1 << bitc::GEP_NUW;
1721+
} else if (const auto *ICmp = dyn_cast<ICmpInst>(V)) {
1722+
if (ICmp->hasSameSign())
1723+
Flags |= 1 << bitc::ICMP_SAME_SIGN;
17211724
}
17221725

17231726
return Flags;

llvm/lib/IR/AsmWriter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,6 +1433,9 @@ static void WriteOptimizationInfo(raw_ostream &Out, const User *U) {
14331433
Out << " nuw";
14341434
if (TI->hasNoSignedWrap())
14351435
Out << " nsw";
1436+
} else if (const auto *ICmp = dyn_cast<ICmpInst>(U)) {
1437+
if (ICmp->hasSameSign())
1438+
Out << " samesign";
14361439
}
14371440
}
14381441

0 commit comments

Comments
 (0)