Skip to content

Commit 370305c

Browse files
committed
[ConstraintElim] Opimize abs based on known constraints
1 parent d2dd4c4 commit 370305c

File tree

2 files changed

+70
-2
lines changed

2 files changed

+70
-2
lines changed

llvm/lib/Transforms/Scalar/ConstraintElimination.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,20 +1128,19 @@ void State::addInfoFor(BasicBlock &BB) {
11281128
FactOrCheck::getCheck(DT.getNode(&BB), cast<CallInst>(&I)));
11291129
break;
11301130
// Enqueue the intrinsics to add extra info.
1131+
case Intrinsic::abs:
11311132
case Intrinsic::umin:
11321133
case Intrinsic::umax:
11331134
case Intrinsic::smin:
11341135
case Intrinsic::smax:
11351136
case Intrinsic::usub_sat:
1136-
// TODO: handle llvm.abs as well
11371137
WorkList.push_back(
11381138
FactOrCheck::getCheck(DT.getNode(&BB), cast<CallInst>(&I)));
11391139
// TODO: Check if it is possible to instead only added the min/max facts
11401140
// when simplifying uses of the min/max intrinsics.
11411141
if (!isGuaranteedNotToBePoison(&I))
11421142
break;
11431143
[[fallthrough]];
1144-
case Intrinsic::abs:
11451144
case Intrinsic::uadd_sat:
11461145
WorkList.push_back(FactOrCheck::getInstFact(DT.getNode(&BB), &I));
11471146
break;
@@ -1537,6 +1536,28 @@ static bool checkAndReplaceUSubSat(SaturatingInst *I, ConstraintInfo &Info,
15371536
return false;
15381537
}
15391538

1539+
static bool checkAndReplaceAbs(IntrinsicInst *I, ConstraintInfo &Info,
1540+
SmallVectorImpl<Instruction *> &ToRemove) {
1541+
assert(I->getIntrinsicID() == Intrinsic::abs && "Expected abs intrinsic");
1542+
Value *Op = I->getOperand(0);
1543+
if (checkCondition(ICmpInst::ICMP_SGE, Op, ConstantInt::get(Op->getType(), 0),
1544+
I, Info)
1545+
.value_or(false)) {
1546+
I->replaceAllUsesWith(Op);
1547+
ToRemove.push_back(I);
1548+
return true;
1549+
}
1550+
if (checkCondition(ICmpInst::ICMP_SLT, Op, ConstantInt::get(Op->getType(), 0),
1551+
I, Info)
1552+
.value_or(false)) {
1553+
IRBuilder<> Builder(I->getParent(), I->getIterator());
1554+
I->replaceAllUsesWith(Builder.CreateNeg(Op));
1555+
ToRemove.push_back(I);
1556+
return true;
1557+
}
1558+
return false;
1559+
}
1560+
15401561
static void
15411562
removeEntryFromStack(const StackEntry &E, ConstraintInfo &Info,
15421563
Module *ReproducerModule,
@@ -1863,6 +1884,10 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
18631884
Changed |= checkAndReplaceUSubSat(SatIntr, Info, ToRemove);
18641885
else
18651886
llvm_unreachable("Unexpected intrinsic.");
1887+
} else if (auto *II = dyn_cast<IntrinsicInst>(Inst)) {
1888+
if (II->getIntrinsicID() == Intrinsic::abs) {
1889+
Changed |= checkAndReplaceAbs(II, Info, ToRemove);
1890+
}
18661891
}
18671892
continue;
18681893
}

llvm/test/Transforms/ConstraintElimination/abs.ll

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,5 +159,48 @@ define i1 @abs_is_nonnegative_constant_arg() {
159159
ret i1 %cmp
160160
}
161161

162+
define i64 @abs_assume_nonnegative(i64 %arg) {
163+
; CHECK-LABEL: define i64 @abs_assume_nonnegative(
164+
; CHECK-SAME: i64 [[ARG:%.*]]) {
165+
; CHECK-NEXT: [[PRECOND:%.*]] = icmp sge i64 [[ARG]], 0
166+
; CHECK-NEXT: call void @llvm.assume(i1 [[PRECOND]])
167+
; CHECK-NEXT: [[ABS:%.*]] = tail call i64 @llvm.abs.i64(i64 [[ARG]], i1 false)
168+
; CHECK-NEXT: ret i64 [[ABS]]
169+
;
170+
%precond = icmp sge i64 %arg, 0
171+
call void @llvm.assume(i1 %precond)
172+
%abs = tail call i64 @llvm.abs.i64(i64 %arg, i1 false)
173+
ret i64 %abs
174+
}
175+
176+
define i64 @abs_assume_negative(i64 %arg) {
177+
; CHECK-LABEL: define i64 @abs_assume_negative(
178+
; CHECK-SAME: i64 [[ARG:%.*]]) {
179+
; CHECK-NEXT: [[PRECOND:%.*]] = icmp slt i64 [[ARG]], 0
180+
; CHECK-NEXT: call void @llvm.assume(i1 [[PRECOND]])
181+
; CHECK-NEXT: [[ABS:%.*]] = tail call i64 @llvm.abs.i64(i64 [[ARG]], i1 false)
182+
; CHECK-NEXT: ret i64 [[ABS]]
183+
;
184+
%precond = icmp slt i64 %arg, 0
185+
call void @llvm.assume(i1 %precond)
186+
%abs = tail call i64 @llvm.abs.i64(i64 %arg, i1 false)
187+
ret i64 %abs
188+
}
189+
190+
; Negative test
191+
define i64 @abs_assume_unrelated(i64 %arg) {
192+
; CHECK-LABEL: define i64 @abs_assume_unrelated(
193+
; CHECK-SAME: i64 [[ARG:%.*]]) {
194+
; CHECK-NEXT: [[PRECOND:%.*]] = icmp slt i64 [[ARG]], 3
195+
; CHECK-NEXT: call void @llvm.assume(i1 [[PRECOND]])
196+
; CHECK-NEXT: [[ABS:%.*]] = tail call i64 @llvm.abs.i64(i64 [[ARG]], i1 false)
197+
; CHECK-NEXT: ret i64 [[ABS]]
198+
;
199+
%precond = icmp slt i64 %arg, 3
200+
call void @llvm.assume(i1 %precond)
201+
%abs = tail call i64 @llvm.abs.i64(i64 %arg, i1 false)
202+
ret i64 %abs
203+
}
204+
162205
declare i32 @llvm.abs.i32(i32, i1 immarg)
163206
declare void @llvm.assume(i1)

0 commit comments

Comments
 (0)