decompose(Value *V, SmallVector<PreconditionTy, 4> &Preconditions,
bool IsSigned, const DataLayout &DL) {
+ auto MergeResults = [&Preconditions, IsSigned,
+ DL](Value *A, Value *B,
+ bool IsSignedB) -> SmallVector<DecompEntry, 4> {
+ auto ResA = decompose(A, Preconditions, IsSigned, DL);
+ auto ResB = decompose(B, Preconditions, IsSignedB, DL);
+ if (ResA.empty() || ResB.empty())
+ return {};
+ ResA[0].Coefficient += ResB[0].Coefficient;
+ append_range(ResA, drop_begin(ResB));
+ return ResA;
+ };
+
// Decompose \p V used with a signed predicate.
if (IsSigned) {
if (auto *CI = dyn_cast<ConstantInt>(V)) {
if (canUseSExt(CI))
return {{CI->getSExtValue(), nullptr}};
}
+ Value *Op0;
+ Value *Op1;
+ if (match(V, m_NSWAdd(m_Value(Op0), m_Value(Op1))))
+ return MergeResults(Op0, Op1, IsSigned);
return {{0, nullptr}, {1, V}};
}
V = Op0;
}
- auto MergeResults = [&Preconditions, IsSigned,
- DL](Value *A, Value *B,
- bool IsSignedB) -> SmallVector<DecompEntry, 4> {
- auto ResA = decompose(A, Preconditions, IsSigned, DL);
- auto ResB = decompose(B, Preconditions, IsSignedB, DL);
- if (ResA.empty() || ResB.empty())
- return {};
- ResA[0].Coefficient += ResB[0].Coefficient;
- append_range(ResA, drop_begin(ResB));
- return ResA;
- };
Value *Op1;
ConstantInt *CI;
if (match(V, m_NUWAdd(m_Value(Op0), m_Value(Op1)))) {
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
-define void @test.not.uge.ult(i8 %start, i8 %low, i8 %high) {
+declare void @use(i1)
+
+define void @test.not.uge.ult(i8 %start, i8 %high) {
; CHECK-LABEL: @test.not.uge.ult(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[ADD_PTR_I:%.*]] = add nsw i8 [[START:%.*]], 3
ret void
}
-define void @test.not.sge.slt(i8 %start, i8 %low, i8 %high) {
+define void @test.not.sge.slt(i8 %start, i8 %high) {
; CHECK-LABEL: @test.not.sge.slt(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[ADD_PTR_I:%.*]] = add nsw i8 [[START:%.*]], 3
; CHECK-NEXT: ret void
; CHECK: if.end:
; CHECK-NEXT: [[T_0:%.*]] = icmp slt i8 [[START]], [[HIGH]]
-; CHECK-NEXT: call void @use(i1 [[T_0]])
+; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: [[START_1:%.*]] = add nsw i8 [[START]], 1
; CHECK-NEXT: [[T_1:%.*]] = icmp slt i8 [[START_1]], [[HIGH]]
-; CHECK-NEXT: call void @use(i1 [[T_1]])
+; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: [[START_2:%.*]] = add nsw i8 [[START]], 2
; CHECK-NEXT: [[T_2:%.*]] = icmp slt i8 [[START_2]], [[HIGH]]
-; CHECK-NEXT: call void @use(i1 [[T_2]])
+; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: [[START_3:%.*]] = add nsw i8 [[START]], 3
; CHECK-NEXT: [[T_3:%.*]] = icmp slt i8 [[START_3]], [[HIGH]]
-; CHECK-NEXT: call void @use(i1 [[T_3]])
+; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: [[START_4:%.*]] = add nsw i8 [[START]], 4
; CHECK-NEXT: [[C_4:%.*]] = icmp slt i8 [[START_4]], [[HIGH]]
; CHECK-NEXT: call void @use(i1 [[C_4]])
; CHECK: if.then.2:
; CHECK-NEXT: [[ADD_0:%.*]] = add nsw i8 [[A]], [[B]]
; CHECK-NEXT: [[T_0:%.*]] = icmp sge i8 [[ADD_0]], [[C]]
-; CHECK-NEXT: call void @use(i1 [[T_0]])
+; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: [[ADD_1:%.*]] = add nsw i8 [[A]], [[A]]
; CHECK-NEXT: [[T_1:%.*]] = icmp sge i8 [[ADD_0]], [[C]]
-; CHECK-NEXT: call void @use(i1 [[T_1]])
+; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: [[ADD_2:%.*]] = add nsw i8 [[A]], [[D:%.*]]
; CHECK-NEXT: [[C_4:%.*]] = icmp sge i8 [[ADD_2]], [[C]]
; CHECK-NEXT: call void @use(i1 [[C_4]])
ret void
}
-declare void @use(i1)
+define void @test.sge.slt.add.neg(i8 %start, i8 %high) {
+; CHECK-LABEL: @test.sge.slt.add.neg(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[ADD_PTR_I:%.*]] = add nsw i8 [[START:%.*]], -3
+; CHECK-NEXT: [[C_1:%.*]] = icmp slt i8 [[ADD_PTR_I]], [[HIGH:%.*]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[C_1]])
+; CHECK-NEXT: [[C_2:%.*]] = icmp slt i8 [[START]], [[HIGH]]
+; CHECK-NEXT: call void @use(i1 [[C_2]])
+; CHECK-NEXT: [[START_1:%.*]] = add nsw i8 [[START]], 1
+; CHECK-NEXT: [[C_3:%.*]] = icmp slt i8 [[START_1]], [[HIGH]]
+; CHECK-NEXT: call void @use(i1 [[C_3]])
+; CHECK-NEXT: [[START_2:%.*]] = add nsw i8 [[START]], -2
+; CHECK-NEXT: [[C_4:%.*]] = icmp slt i8 [[START_2]], [[HIGH]]
+; CHECK-NEXT: call void @use(i1 [[C_4]])
+; CHECK-NEXT: [[START_3:%.*]] = add nsw i8 [[START]], -3
+; CHECK-NEXT: [[T_1:%.*]] = icmp slt i8 [[START_3]], [[HIGH]]
+; CHECK-NEXT: call void @use(i1 true)
+; CHECK-NEXT: [[START_4:%.*]] = add nsw i8 [[START]], -4
+; CHECK-NEXT: [[T_2:%.*]] = icmp slt i8 [[START_4]], [[HIGH]]
+; CHECK-NEXT: call void @use(i1 true)
+; CHECK-NEXT: ret void
+;
+entry:
+ %add.ptr.i = add nsw i8 %start, -3
+ %c.1 = icmp slt i8 %add.ptr.i, %high
+ call void @llvm.assume(i1 %c.1)
+ %c.2 = icmp slt i8 %start, %high
+ call void @use(i1 %c.2)
+ %start.1 = add nsw i8 %start, 1
+ %c.3 = icmp slt i8 %start.1, %high
+ call void @use(i1 %c.3)
+ %start.2 = add nsw i8 %start, -2
+ %c.4 = icmp slt i8 %start.2, %high
+ call void @use(i1 %c.4)
+ %start.3 = add nsw i8 %start, -3
+ %t.1 = icmp slt i8 %start.3, %high
+ call void @use(i1 %t.1)
+ %start.4 = add nsw i8 %start, -4
+ %t.2 = icmp slt i8 %start.4, %high
+ call void @use(i1 %t.2)
+ ret void
+}
+
+declare void @llvm.assume(i1)