Skip to content

Commit 73b4623

Browse files
committed
[IR] Add samesign flag to icmp instruction
1 parent 0dbc85a commit 73b4623

File tree

16 files changed

+112
-2
lines changed

16 files changed

+112
-2
lines changed

llvm/docs/LangRef.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12329,6 +12329,7 @@ Syntax:
1232912329
::
1233012330

1233112331
<result> = icmp <cond> <ty> <op1>, <op2> ; yields i1 or <N x i1>:result
12332+
<result> = icmp samesign <cond> <ty> <op1>, <op2> ; yields i1 or <N x i1>:result
1233212333

1233312334
Overview:
1233412335
"""""""""
@@ -12398,6 +12399,9 @@ If the operands are integer vectors, then they are compared element by
1239812399
element. The result is an ``i1`` vector with the same number of elements
1239912400
as the values being compared. Otherwise, the result is an ``i1``.
1240012401

12402+
If the ``samesign`` keyword is present and the operands are not of the
12403+
same sign then the result is a :ref:`poison value <poisonvalues>`.
12404+
1240112405
Example:
1240212406
""""""""
1240312407

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+
/// PossiblySameSignOptionalFlags - Flags for serializing
544+
/// PossiblySameSignInst's SubclassOptionalData contents.
545+
enum PossiblySameSignInstOptionalFlags { PSSI_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
@@ -1224,6 +1224,17 @@ class ICmpInst: public CmpInst {
12241224
/// Return the unsigned version of the predicate.
12251225
static Predicate getUnsignedPredicate(Predicate pred);
12261226

1227+
/// An icmp instruction, which can be marked as "samesign", indicating that
1228+
/// the two operands have the same sign. This means that we can convert
1229+
/// "slt/ult" to "ult", which enables more optimizations.
1230+
enum { SameSign = (1 << 0) };
1231+
1232+
void setSameSign(bool B) {
1233+
SubclassOptionalData = (SubclassOptionalData & ~SameSign) | (B * SameSign);
1234+
}
1235+
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(true);
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: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5482,6 +5482,8 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
54825482
if (!CmpInst::isIntPredicate(PredVal))
54835483
return error("Invalid icmp predicate");
54845484
I = new ICmpInst(PredVal, LHS, RHS);
5485+
if (Record[OpNum] & (1 << bitc::PSSI_SAME_SIGN))
5486+
cast<ICmpInst>(I)->setSameSign(true);
54855487
}
54865488

54875489
ResTypeID = getVirtualTypeID(I->getType()->getScalarType());

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::PSSI_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

llvm/lib/IR/Instruction.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,10 @@ void Instruction::dropPoisonGeneratingFlags() {
441441
cast<TruncInst>(this)->setHasNoUnsignedWrap(false);
442442
cast<TruncInst>(this)->setHasNoSignedWrap(false);
443443
break;
444+
445+
case Instruction::ICmp:
446+
cast<ICmpInst>(this)->setSameSign(false);
447+
break;
444448
}
445449

446450
if (isa<FPMathOperator>(this)) {
@@ -654,6 +658,10 @@ void Instruction::copyIRFlags(const Value *V, bool IncludeWrapFlags) {
654658
if (auto *NNI = dyn_cast<PossiblyNonNegInst>(V))
655659
if (isa<PossiblyNonNegInst>(this))
656660
setNonNeg(NNI->hasNonNeg());
661+
662+
if (auto *SrcICmp = dyn_cast<ICmpInst>(V))
663+
if (auto *DestICmp = dyn_cast<ICmpInst>(this))
664+
DestICmp->setSameSign(SrcICmp->hasSameSign());
657665
}
658666

659667
void Instruction::andIRFlags(const Value *V) {
@@ -695,6 +703,10 @@ void Instruction::andIRFlags(const Value *V) {
695703
if (auto *NNI = dyn_cast<PossiblyNonNegInst>(V))
696704
if (isa<PossiblyNonNegInst>(this))
697705
setNonNeg(hasNonNeg() && NNI->hasNonNeg());
706+
707+
if (auto *SrcICmp = dyn_cast<ICmpInst>(V))
708+
if (auto *DestICmp = dyn_cast<ICmpInst>(this))
709+
DestICmp->setSameSign(DestICmp->hasSameSign() && SrcICmp->hasSameSign());
698710
}
699711

700712
const char *Instruction::getOpcodeName(unsigned OpCode) {

llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ PoisonFlags::PoisonFlags(const Instruction *I) {
4949
Exact = false;
5050
Disjoint = false;
5151
NNeg = false;
52+
SameSign = false;
5253
GEPNW = GEPNoWrapFlags::none();
5354
if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(I)) {
5455
NUW = OBO->hasNoUnsignedWrap();
@@ -66,6 +67,8 @@ PoisonFlags::PoisonFlags(const Instruction *I) {
6667
}
6768
if (auto *GEP = dyn_cast<GetElementPtrInst>(I))
6869
GEPNW = GEP->getNoWrapFlags();
70+
if (auto *ICmp = dyn_cast<ICmpInst>(I))
71+
SameSign = ICmp->hasSameSign();
6972
}
7073

7174
void PoisonFlags::apply(Instruction *I) {
@@ -85,6 +88,8 @@ void PoisonFlags::apply(Instruction *I) {
8588
}
8689
if (auto *GEP = dyn_cast<GetElementPtrInst>(I))
8790
GEP->setNoWrapFlags(GEPNW);
91+
if (auto *ICmp = dyn_cast<ICmpInst>(I))
92+
ICmp->setSameSign(SameSign);
8893
}
8994

9095
/// ReuseOrCreateCast - Arrange for there to be a cast of V to Ty at IP,

llvm/test/Assembler/flags.ll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,18 @@ define <2 x i32> @test_trunc_both_reversed_vector(<2 x i64> %a) {
312312
ret <2 x i32> %res
313313
}
314314

315+
define i1 @test_icmp_samesign(i32 %a, i32 %b) {
316+
; CHECK: %res = icmp samesign ult i32 %a, %b
317+
%res = icmp samesign ult i32 %a, %b
318+
ret i1 %res
319+
}
320+
321+
define <2 x i1> @test_icmp_samesign2(<2 x i32> %a, <2 x i32> %b) {
322+
; CHECK: %res = icmp samesign ult <2 x i32> %a, %b
323+
%res = icmp samesign ult <2 x i32> %a, %b
324+
ret <2 x i1> %res
325+
}
326+
315327
define ptr @gep_nuw(ptr %p, i64 %idx) {
316328
; CHECK: %gep = getelementptr nuw i8, ptr %p, i64 %idx
317329
%gep = getelementptr nuw i8, ptr %p, i64 %idx

llvm/test/Bitcode/flags.ll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ second: ; preds = %first
3030
%tsv = trunc nsw <2 x i32> %aa to <2 x i16>
3131
%tusv = trunc nuw nsw <2 x i32> %aa to <2 x i16>
3232
%tv = trunc <2 x i32> %aa to <2 x i16>
33+
%ii = icmp samesign ult i32 %a, %z
34+
%iv = icmp samesign ult <2 x i32> %aa, %aa
3335
unreachable
3436

3537
first: ; preds = %entry
@@ -53,5 +55,7 @@ first: ; preds = %entry
5355
%ttsv = trunc nsw <2 x i32> %aa to <2 x i16>
5456
%ttusv = trunc nuw nsw <2 x i32> %aa to <2 x i16>
5557
%ttv = trunc <2 x i32> %aa to <2 x i16>
58+
%icm = icmp samesign ult i32 %a, %zz
59+
%icv = icmp samesign ult <2 x i32> %aa, %aa
5660
br label %second
5761
}

llvm/test/Transforms/InstCombine/freeze.ll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,6 +1182,17 @@ define ptr @propagate_drop_flags_gep_nuw(ptr %p) {
11821182
ret ptr %gep.fr
11831183
}
11841184

1185+
define i1 @propagate_drop_flags_icmp(i32 %a, i32 %b) {
1186+
; CHECK-LABEL: @propagate_drop_flags_icmp(
1187+
; CHECK-NEXT: [[A_FR:%.*]] = freeze i32 [[A:%.*]]
1188+
; CHECK-NEXT: [[RET:%.*]] = icmp ult i32 [[A_FR]], 3
1189+
; CHECK-NEXT: ret i1 [[RET]]
1190+
;
1191+
%ret = icmp samesign ult i32 %a, 3
1192+
%ret.fr = freeze i1 %ret
1193+
ret i1 %ret.fr
1194+
}
1195+
11851196
declare i32 @llvm.umax.i32(i32 %a, i32 %b)
11861197

11871198
define i32 @freeze_call_with_range_attr(i32 %a) {

llvm/test/Transforms/SimplifyCFG/HoistCode.ll

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,33 @@ F:
275275
%gep2 = getelementptr nuw i8, ptr %p, i64 1
276276
ret ptr %gep2
277277
}
278+
279+
define i1 @hoist_icmp_flags_preserve(i1 %C, i32 %x, i32 %y) {
280+
; CHECK-LABEL: @hoist_icmp_flags_preserve(
281+
; CHECK-NEXT: common.ret:
282+
; CHECK-NEXT: [[Z1:%.*]] = icmp samesign ult i32 [[X:%.*]], [[Y:%.*]]
283+
; CHECK-NEXT: ret i1 [[Z1]]
284+
;
285+
br i1 %C, label %T, label %F
286+
T:
287+
%z1 = icmp samesign ult i32 %x, %y
288+
ret i1 %z1
289+
F:
290+
%z2 = icmp samesign ult i32 %x, %y
291+
ret i1 %z2
292+
}
293+
294+
define i1 @hoist_icmp_flags_drop(i1 %C, i32 %x, i32 %y) {
295+
; CHECK-LABEL: @hoist_icmp_flags_drop(
296+
; CHECK-NEXT: common.ret:
297+
; CHECK-NEXT: [[Z1:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
298+
; CHECK-NEXT: ret i1 [[Z1]]
299+
;
300+
br i1 %C, label %T, label %F
301+
T:
302+
%z1 = icmp ult i32 %x, %y
303+
ret i1 %z1
304+
F:
305+
%z2 = icmp samesign ult i32 %x, %y
306+
ret i1 %z2
307+
}

0 commit comments

Comments
 (0)