Skip to content

Commit 7fb97be

Browse files
authored
[ConstraintElimination] Add eq/ne facts to signed constraint system (#121423)
Facts of eq/ne were added to unsigned system only, causing some missing optimizations. This patch adds eq/ne facts to both signed & unsigned constraint system. Fixes #117961.
1 parent ee99c4d commit 7fb97be

File tree

4 files changed

+83
-13
lines changed

4 files changed

+83
-13
lines changed

llvm/lib/Transforms/Scalar/ConstraintElimination.cpp

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,8 @@ class ConstraintInfo {
313313
/// New variables that need to be added to the system are collected in
314314
/// \p NewVariables.
315315
ConstraintTy getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
316-
SmallVectorImpl<Value *> &NewVariables) const;
316+
SmallVectorImpl<Value *> &NewVariables,
317+
bool ForceSignedSystem = false) const;
317318

318319
/// Turns a comparison of the form \p Op0 \p Pred \p Op1 into a vector of
319320
/// constraints using getConstraint. Returns an empty constraint if the result
@@ -330,6 +331,14 @@ class ConstraintInfo {
330331
void transferToOtherSystem(CmpInst::Predicate Pred, Value *A, Value *B,
331332
unsigned NumIn, unsigned NumOut,
332333
SmallVectorImpl<StackEntry> &DFSInStack);
334+
335+
private:
336+
/// Adds facts into constraint system. \p ForceSignedSystem can be set when
337+
/// the \p Pred is eq/ne, and signed constraint system is used when it's
338+
/// specified.
339+
void addFactImpl(CmpInst::Predicate Pred, Value *A, Value *B, unsigned NumIn,
340+
unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack,
341+
bool ForceSignedSystem);
333342
};
334343

335344
/// Represents a (Coefficient * Variable) entry after IR decomposition.
@@ -636,8 +645,12 @@ static Decomposition decompose(Value *V,
636645

637646
ConstraintTy
638647
ConstraintInfo::getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
639-
SmallVectorImpl<Value *> &NewVariables) const {
648+
SmallVectorImpl<Value *> &NewVariables,
649+
bool ForceSignedSystem) const {
640650
assert(NewVariables.empty() && "NewVariables must be empty when passed in");
651+
assert((!ForceSignedSystem || CmpInst::isEquality(Pred)) &&
652+
"signed system can only be forced on eq/ne");
653+
641654
bool IsEq = false;
642655
bool IsNe = false;
643656

@@ -652,15 +665,15 @@ ConstraintInfo::getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
652665
break;
653666
}
654667
case CmpInst::ICMP_EQ:
655-
if (match(Op1, m_Zero())) {
668+
if (!ForceSignedSystem && match(Op1, m_Zero())) {
656669
Pred = CmpInst::ICMP_ULE;
657670
} else {
658671
IsEq = true;
659672
Pred = CmpInst::ICMP_ULE;
660673
}
661674
break;
662675
case CmpInst::ICMP_NE:
663-
if (match(Op1, m_Zero())) {
676+
if (!ForceSignedSystem && match(Op1, m_Zero())) {
664677
Pred = CmpInst::getSwappedPredicate(CmpInst::ICMP_UGT);
665678
std::swap(Op0, Op1);
666679
} else {
@@ -677,7 +690,7 @@ ConstraintInfo::getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
677690
return {};
678691

679692
SmallVector<ConditionTy, 4> Preconditions;
680-
bool IsSigned = CmpInst::isSigned(Pred);
693+
bool IsSigned = ForceSignedSystem || CmpInst::isSigned(Pred);
681694
auto &Value2Index = getValue2Index(IsSigned);
682695
auto ADec = decompose(Op0->stripPointerCastsSameRepresentation(),
683696
Preconditions, IsSigned, DL);
@@ -737,7 +750,7 @@ ConstraintInfo::getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
737750
int64_t OffsetSum;
738751
if (AddOverflow(Offset1, Offset2, OffsetSum))
739752
return {};
740-
if (Pred == (IsSigned ? CmpInst::ICMP_SLT : CmpInst::ICMP_ULT))
753+
if (Pred == CmpInst::ICMP_SLT || Pred == CmpInst::ICMP_ULT)
741754
if (AddOverflow(OffsetSum, int64_t(-1), OffsetSum))
742755
return {};
743756
R[0] = OffsetSum;
@@ -1580,10 +1593,20 @@ static bool checkOrAndOpImpliedByOther(
15801593
void ConstraintInfo::addFact(CmpInst::Predicate Pred, Value *A, Value *B,
15811594
unsigned NumIn, unsigned NumOut,
15821595
SmallVectorImpl<StackEntry> &DFSInStack) {
1596+
addFactImpl(Pred, A, B, NumIn, NumOut, DFSInStack, false);
1597+
// If the Pred is eq/ne, also add the fact to signed system.
1598+
if (CmpInst::isEquality(Pred))
1599+
addFactImpl(Pred, A, B, NumIn, NumOut, DFSInStack, true);
1600+
}
1601+
1602+
void ConstraintInfo::addFactImpl(CmpInst::Predicate Pred, Value *A, Value *B,
1603+
unsigned NumIn, unsigned NumOut,
1604+
SmallVectorImpl<StackEntry> &DFSInStack,
1605+
bool ForceSignedSystem) {
15831606
// If the constraint has a pre-condition, skip the constraint if it does not
15841607
// hold.
15851608
SmallVector<Value *> NewVariables;
1586-
auto R = getConstraint(Pred, A, B, NewVariables);
1609+
auto R = getConstraint(Pred, A, B, NewVariables, ForceSignedSystem);
15871610

15881611
// TODO: Support non-equality for facts as well.
15891612
if (!R.isValid(*this) || R.isNe())

llvm/test/Transforms/ConstraintElimination/eq.ll

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,3 +424,53 @@ bc_equal:
424424
not_eq:
425425
ret i1 false
426426
}
427+
428+
define i1 @test_eq_for_signed_cmp(i32 noundef %v0, i32 noundef %v1, i32 noundef %v2) {
429+
; CHECK-LABEL: @test_eq_for_signed_cmp(
430+
; CHECK-NEXT: entry:
431+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[V2:%.*]], [[V0:%.*]]
432+
; CHECK-NEXT: [[CMP1:%.*]] = icmp sge i32 [[V0]], [[V1:%.*]]
433+
; CHECK-NEXT: [[AND0:%.*]] = and i1 [[CMP1]], [[CMP]]
434+
; CHECK-NEXT: [[CMP4:%.*]] = icmp sgt i32 [[V1]], [[V2]]
435+
; CHECK-NEXT: [[AND1:%.*]] = and i1 false, [[AND0]]
436+
; CHECK-NEXT: ret i1 [[AND1]]
437+
;
438+
entry:
439+
%cmp = icmp eq i32 %v2, %v0
440+
%cmp1 = icmp sge i32 %v0, %v1
441+
%and0 = and i1 %cmp1, %cmp
442+
%cmp4 = icmp sgt i32 %v1, %v2
443+
%and1 = and i1 %cmp4, %and0
444+
ret i1 %and1
445+
}
446+
447+
define i1 @test_eq_for_signed_cmp_with_decompsition(i32 noundef %v0, i32 noundef %v1, i32 noundef %v2, i32 noundef %addend0, i32 noundef %addend1) {
448+
; CHECK-LABEL: @test_eq_for_signed_cmp_with_decompsition(
449+
; CHECK-NEXT: entry:
450+
; CHECK-NEXT: [[V0ADD:%.*]] = add nsw i32 [[V0:%.*]], [[ADDEND0:%.*]]
451+
; CHECK-NEXT: [[V1ADD:%.*]] = add nsw i32 [[V1:%.*]], [[ADDEND1:%.*]]
452+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[V2:%.*]], [[V0ADD]]
453+
; CHECK-NEXT: [[CMP1:%.*]] = icmp sge i32 [[V0ADD]], [[V1ADD]]
454+
; CHECK-NEXT: [[CMP2:%.*]] = icmp sge i32 [[ADDEND0]], 0
455+
; CHECK-NEXT: [[CMP3:%.*]] = icmp slt i32 [[ADDEND0]], [[ADDEND1]]
456+
; CHECK-NEXT: [[AND0:%.*]] = and i1 [[CMP1]], [[CMP]]
457+
; CHECK-NEXT: [[AND1:%.*]] = and i1 [[AND0]], [[CMP2]]
458+
; CHECK-NEXT: [[AND2:%.*]] = and i1 [[AND1]], [[CMP3]]
459+
; CHECK-NEXT: [[CMP4:%.*]] = icmp sgt i32 [[V1]], [[V2]]
460+
; CHECK-NEXT: [[AND3:%.*]] = and i1 false, [[AND2]]
461+
; CHECK-NEXT: ret i1 [[AND3]]
462+
;
463+
entry:
464+
%v0add = add nsw i32 %v0, %addend0
465+
%v1add = add nsw i32 %v1, %addend1
466+
%cmp = icmp eq i32 %v2, %v0add
467+
%cmp1 = icmp sge i32 %v0add, %v1add
468+
%cmp2 = icmp sge i32 %addend0, 0
469+
%cmp3 = icmp slt i32 %addend0, %addend1
470+
%and0 = and i1 %cmp1, %cmp
471+
%and1 = and i1 %and0, %cmp2
472+
%and2 = and i1 %and1, %cmp3
473+
%cmp4 = icmp sgt i32 %v1, %v2
474+
%and3 = and i1 %cmp4, %and2
475+
ret i1 %and3
476+
}

llvm/test/Transforms/ConstraintElimination/ne.ll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,7 @@ define i1 @test_ne_eq_0(i8 %a, i8 %b) {
7171
; CHECK-NEXT: [[RES_13:%.*]] = xor i1 [[RES_12]], false
7272
; CHECK-NEXT: [[RES_14:%.*]] = xor i1 [[RES_13]], false
7373
; CHECK-NEXT: [[RES_15:%.*]] = xor i1 [[RES_14]], false
74-
; CHECK-NEXT: [[C_12:%.*]] = icmp sgt i8 [[A]], 0
75-
; CHECK-NEXT: [[RES_16:%.*]] = xor i1 [[RES_15]], [[C_12]]
74+
; CHECK-NEXT: [[RES_16:%.*]] = xor i1 [[RES_15]], false
7675
; CHECK-NEXT: ret i1 [[RES_16]]
7776
;
7877
entry:
@@ -209,8 +208,7 @@ define i1 @test_ne_eq_1(i8 %a, i8 %b) {
209208
; CHECK-NEXT: [[RES_13:%.*]] = xor i1 [[RES_12]], true
210209
; CHECK-NEXT: [[RES_14:%.*]] = xor i1 [[RES_13]], true
211210
; CHECK-NEXT: [[RES_15:%.*]] = xor i1 [[RES_14]], false
212-
; CHECK-NEXT: [[C_12:%.*]] = icmp sgt i8 [[A]], 0
213-
; CHECK-NEXT: [[RES_16:%.*]] = xor i1 [[RES_15]], [[C_12]]
211+
; CHECK-NEXT: [[RES_16:%.*]] = xor i1 [[RES_15]], true
214212
; CHECK-NEXT: ret i1 [[RES_16]]
215213
;
216214
entry:

llvm/test/Transforms/ConstraintElimination/pr105785.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ define void @pr105785(ptr %p) {
1515
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[FOR_IND2]], 3
1616
; CHECK-NEXT: br i1 [[CMP2]], label %[[FOR_BODY3]], label %[[FOR_COND]]
1717
; CHECK: [[FOR_BODY3]]:
18-
; CHECK-NEXT: [[SCMP:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[FOR_IND]], i32 1)
19-
; CHECK-NEXT: store i32 [[SCMP]], ptr [[P]], align 4
18+
; CHECK-NEXT: store i32 -1, ptr [[P]], align 4
2019
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[FOR_IND2]], 1
2120
; CHECK-NEXT: br label %[[FOR_COND1]]
2221
; CHECK: [[FOR_END6]]:

0 commit comments

Comments
 (0)