Skip to content

Commit 9671150

Browse files
committed
[IR] Add samesign flag to icmp instruction
1 parent a5dfccc commit 9671150

File tree

16 files changed

+123
-2
lines changed

16 files changed

+123
-2
lines changed

llvm/docs/LangRef.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12239,6 +12239,7 @@ Syntax:
1223912239
::
1224012240

1224112241
<result> = icmp <cond> <ty> <op1>, <op2> ; yields i1 or <N x i1>:result
12242+
<result> = icmp samesign <cond> <ty> <op1>, <op2> ; yields i1 or <N x i1>:result
1224212243

1224312244
Overview:
1224412245
"""""""""
@@ -12308,6 +12309,9 @@ If the operands are integer vectors, then they are compared element by
1230812309
element. The result is an ``i1`` vector with the same number of elements
1230912310
as the values being compared. Otherwise, the result is an ``i1``.
1231012311

12312+
If the ``samesign`` keyword is present and the operands are not of the
12313+
same sign then the result a :ref:`poison value <poisonvalues>`.
12314+
1231112315
Example:
1231212316
""""""""
1231312317

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
@@ -537,6 +537,10 @@ enum GetElementPtrOptionalFlags {
537537
GEP_NUW = 2,
538538
};
539539

540+
/// PossiblySameSignOptionalFlags - Flags for serializing
541+
/// PossiblySameSignInst's SubclassOptionalData contents.
542+
enum PossiblySameSignInstOptionalFlags { PSSI_SAME_SIGN = 0 };
543+
540544
/// Encoded AtomicOrdering values.
541545
enum AtomicOrderingCodes {
542546
ORDERING_NOTATOMIC = 0,

llvm/include/llvm/IR/InstrTypes.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,28 @@ class CmpInst : public Instruction {
10331033
}
10341034
};
10351035

1036+
/// An icmp instruction, which can be marked as "samesign", indicating that the
1037+
/// two operands have the same sign. This means that we can convert "slt/ult"
1038+
/// to "ult", which enables more optimizations.
1039+
class PossiblySameSignInst : public CmpInst {
1040+
public:
1041+
enum { SameSign = (1 << 0) };
1042+
1043+
void setSameSign(bool B) {
1044+
SubclassOptionalData = (SubclassOptionalData & ~SameSign) | (B * SameSign);
1045+
}
1046+
1047+
bool hasSameSign() const { return SubclassOptionalData & SameSign; }
1048+
1049+
static bool classof(const Instruction *I) {
1050+
return I->getOpcode() == Instruction::ICmp;
1051+
}
1052+
1053+
static bool classof(const Value *V) {
1054+
return isa<Instruction>(V) && classof(cast<Instruction>(V));
1055+
}
1056+
};
1057+
10361058
// FIXME: these are redundant if CmpInst < BinaryOperator
10371059
template <>
10381060
struct OperandTraits<CmpInst> : public FixedNumOperandTraits<CmpInst, 2> {

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
@@ -571,6 +571,7 @@ lltok::Kind LLLexer::LexIdentifier() {
571571
KEYWORD(disjoint);
572572
KEYWORD(inbounds);
573573
KEYWORD(nneg);
574+
KEYWORD(samesign);
574575
KEYWORD(inrange);
575576
KEYWORD(addrspace);
576577
KEYWORD(section);

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6950,8 +6950,14 @@ int LLParser::parseInstruction(Instruction *&Inst, BasicBlock *BB,
69506950
case lltok::kw_and:
69516951
case lltok::kw_xor:
69526952
return parseLogical(Inst, PFS, KeywordVal);
6953-
case lltok::kw_icmp:
6954-
return parseCompare(Inst, PFS, KeywordVal);
6953+
case lltok::kw_icmp: {
6954+
bool SameSign = EatIfPresent(lltok::kw_samesign);
6955+
if (parseCompare(Inst, PFS, KeywordVal))
6956+
return true;
6957+
if (SameSign)
6958+
cast<PossiblySameSignInst>(Inst)->setSameSign(true);
6959+
return false;
6960+
}
69556961
case lltok::kw_fcmp: {
69566962
FastMathFlags FMF = EatFastMathFlagsIfPresent();
69576963
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
@@ -5462,6 +5462,8 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
54625462
if (!CmpInst::isIntPredicate(PredVal))
54635463
return error("Invalid icmp predicate");
54645464
I = new ICmpInst(PredVal, LHS, RHS);
5465+
if (Record[OpNum] & (1 << bitc::PSSI_SAME_SIGN))
5466+
cast<PossiblySameSignInst>(I)->setSameSign(true);
54655467
}
54665468

54675469
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
@@ -1714,6 +1714,9 @@ static uint64_t getOptimizationFlags(const Value *V) {
17141714
Flags |= 1 << bitc::GEP_NUSW;
17151715
if (GEP->hasNoUnsignedWrap())
17161716
Flags |= 1 << bitc::GEP_NUW;
1717+
} else if (const auto *PSSI = dyn_cast<PossiblySameSignInst>(V)) {
1718+
if (PSSI->hasSameSign())
1719+
Flags |= 1 << bitc::PSSI_SAME_SIGN;
17171720
}
17181721

17191722
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 *PSSI = dyn_cast<PossiblySameSignInst>(U)) {
1437+
if (PSSI->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<PossiblySameSignInst>(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<PossiblySameSignInst>(V))
663+
if (auto *DestICmp = dyn_cast<PossiblySameSignInst>(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<PossiblySameSignInst>(V))
708+
if (auto *DestICmp = dyn_cast<PossiblySameSignInst>(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 *PSSI = dyn_cast<PossiblySameSignInst>(I))
71+
SameSign = PSSI->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 *PSSI = dyn_cast<PossiblySameSignInst>(I))
92+
PSSI->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)