Skip to content

Commit aa5b6c9

Browse files
committed
[ConstraintElimination] Initial support for using info from assumes.
This patch adds initial support to use facts from @llvm.assume calls. It intentionally does not handle all possible cases to keep things simple initially. For now, the condition from an assume is made available on entry to the containing block, if the assume is guaranteed to execute. Otherwise it is only made available in the successor blocks.
1 parent dd1ec86 commit aa5b6c9

File tree

2 files changed

+47
-13
lines changed

2 files changed

+47
-13
lines changed

llvm/lib/Transforms/Scalar/ConstraintElimination.cpp

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "llvm/ADT/Statistic.h"
1919
#include "llvm/Analysis/ConstraintSystem.h"
2020
#include "llvm/Analysis/GlobalsModRef.h"
21+
#include "llvm/Analysis/ValueTracking.h"
2122
#include "llvm/IR/DataLayout.h"
2223
#include "llvm/IR/Dominators.h"
2324
#include "llvm/IR/Function.h"
@@ -268,6 +269,31 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT) {
268269
continue;
269270
WorkList.emplace_back(DT.getNode(&BB));
270271

272+
// True as long as long as the current instruction is guaranteed to execute.
273+
bool GuaranteedToExecute = true;
274+
// Scan BB for assume calls.
275+
// TODO: also use this scan to queue conditions to simplify, so we can
276+
// interleave facts from assumes and conditions to simplify in a single
277+
// basic block. And to skip another traversal of each basic block when
278+
// simplifying.
279+
for (Instruction &I : BB) {
280+
Value *Cond;
281+
// For now, just handle assumes with a single compare as condition.
282+
if (match(&I, m_Intrinsic<Intrinsic::assume>(m_Value(Cond))) &&
283+
isa<CmpInst>(Cond)) {
284+
if (GuaranteedToExecute) {
285+
// The assume is guaranteed to execute when BB is entered, hence Cond
286+
// holds on entry to BB.
287+
WorkList.emplace_back(DT.getNode(&BB), cast<CmpInst>(Cond), false);
288+
} else {
289+
// Otherwise the condition only holds in the successors.
290+
for (BasicBlock *Succ : successors(&BB))
291+
WorkList.emplace_back(DT.getNode(Succ), cast<CmpInst>(Cond), false);
292+
}
293+
}
294+
GuaranteedToExecute &= isGuaranteedToTransferExecutionToSuccessor(&I);
295+
}
296+
271297
auto *Br = dyn_cast<BranchInst>(BB.getTerminator());
272298
if (!Br || !Br->isConditional())
273299
continue;
@@ -395,8 +421,13 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT) {
395421
for (auto &E : reverse(DFSInStack))
396422
dbgs() << " C " << *E.Condition << " " << E.IsNot << "\n";
397423
});
398-
Cmp->replaceAllUsesWith(
399-
ConstantInt::getTrue(F.getParent()->getContext()));
424+
Cmp->replaceUsesWithIf(
425+
ConstantInt::getTrue(F.getParent()->getContext()), [](Use &U) {
426+
// Conditions in an assume trivially simplify to true. Skip uses
427+
// in assume calls to not destroy the available information.
428+
auto *II = dyn_cast<IntrinsicInst>(U.getUser());
429+
return !II || II->getIntrinsicID() != Intrinsic::assume;
430+
});
400431
NumCondsRemoved++;
401432
Changed = true;
402433
}

llvm/test/Transforms/ConstraintElimination/assumes.ll

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ define i1 @assume_dominates(i8 %a, i8 %b, i1 %c) {
1616
; CHECK: then:
1717
; CHECK-NEXT: [[T_1:%.*]] = icmp ule i8 [[ADD_1]], [[B]]
1818
; CHECK-NEXT: [[T_2:%.*]] = icmp ule i8 [[A]], [[B]]
19-
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[T_1]], [[T_2]]
19+
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true
2020
; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2
2121
; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]]
2222
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
2323
; CHECK-NEXT: ret i1 [[RES_2]]
2424
; CHECK: else:
2525
; CHECK-NEXT: [[T_3:%.*]] = icmp ule i8 [[ADD_1]], [[B]]
2626
; CHECK-NEXT: [[T_4:%.*]] = icmp ule i8 [[A]], [[B]]
27-
; CHECK-NEXT: [[RES_3:%.*]] = xor i1 [[T_3]], [[T_4]]
27+
; CHECK-NEXT: [[RES_3:%.*]] = xor i1 true, true
2828
; CHECK-NEXT: [[ADD_2_1:%.*]] = add nuw nsw i8 [[A]], 2
2929
; CHECK-NEXT: [[C_2:%.*]] = icmp ule i8 [[ADD_2_1]], [[B]]
3030
; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], [[C_2]]
@@ -64,15 +64,15 @@ define i1 @assume_dominates_with_may_unwind_call_before_assume(i8 %a, i8 %b, i1
6464
; CHECK: then:
6565
; CHECK-NEXT: [[T_1:%.*]] = icmp ule i8 [[ADD_1]], [[B]]
6666
; CHECK-NEXT: [[T_2:%.*]] = icmp ule i8 [[A]], [[B]]
67-
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[T_1]], [[T_2]]
67+
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true
6868
; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2
6969
; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]]
7070
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
7171
; CHECK-NEXT: ret i1 [[RES_2]]
7272
; CHECK: else:
7373
; CHECK-NEXT: [[T_3:%.*]] = icmp ule i8 [[ADD_1]], [[B]]
7474
; CHECK-NEXT: [[T_4:%.*]] = icmp ule i8 [[A]], [[B]]
75-
; CHECK-NEXT: [[RES_3:%.*]] = xor i1 [[T_3]], [[T_4]]
75+
; CHECK-NEXT: [[RES_3:%.*]] = xor i1 true, true
7676
; CHECK-NEXT: [[ADD_2_1:%.*]] = add nuw nsw i8 [[A]], 2
7777
; CHECK-NEXT: [[C_2:%.*]] = icmp ule i8 [[ADD_2_1]], [[B]]
7878
; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], [[C_2]]
@@ -113,15 +113,15 @@ define i1 @assume_dominates_with_may_unwind_call_after_assume(i8 %a, i8 %b, i1 %
113113
; CHECK: then:
114114
; CHECK-NEXT: [[T_1:%.*]] = icmp ule i8 [[ADD_1]], [[B]]
115115
; CHECK-NEXT: [[T_2:%.*]] = icmp ule i8 [[A]], [[B]]
116-
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[T_1]], [[T_2]]
116+
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true
117117
; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2
118118
; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]]
119119
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
120120
; CHECK-NEXT: ret i1 [[RES_2]]
121121
; CHECK: else:
122122
; CHECK-NEXT: [[T_3:%.*]] = icmp ule i8 [[ADD_1]], [[B]]
123123
; CHECK-NEXT: [[T_4:%.*]] = icmp ule i8 [[A]], [[B]]
124-
; CHECK-NEXT: [[RES_3:%.*]] = xor i1 [[T_3]], [[T_4]]
124+
; CHECK-NEXT: [[RES_3:%.*]] = xor i1 true, true
125125
; CHECK-NEXT: [[ADD_2_1:%.*]] = add nuw nsw i8 [[A]], 2
126126
; CHECK-NEXT: [[C_2:%.*]] = icmp ule i8 [[ADD_2_1]], [[B]]
127127
; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], [[C_2]]
@@ -159,7 +159,7 @@ define i1 @assume_single_bb(i8 %a, i8 %b, i1 %c) {
159159
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_1]])
160160
; CHECK-NEXT: [[T_1:%.*]] = icmp ule i8 [[ADD_1]], [[B]]
161161
; CHECK-NEXT: [[T_2:%.*]] = icmp ule i8 [[A]], [[B]]
162-
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[T_1]], [[T_2]]
162+
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true
163163
; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2
164164
; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]]
165165
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
@@ -186,7 +186,7 @@ define i1 @assume_same_bb(i8 %a, i8 %b, i1 %c) {
186186
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_1]])
187187
; CHECK-NEXT: [[T_1:%.*]] = icmp ule i8 [[ADD_1]], [[B]]
188188
; CHECK-NEXT: [[T_2:%.*]] = icmp ule i8 [[A]], [[B]]
189-
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[T_1]], [[T_2]]
189+
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true
190190
; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2
191191
; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]]
192192
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
@@ -231,7 +231,7 @@ define i1 @assume_same_bb2(i8 %a, i8 %b, i1 %c) {
231231
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_1]])
232232
; CHECK-NEXT: [[T_1:%.*]] = icmp ule i8 [[ADD_1]], [[B]]
233233
; CHECK-NEXT: [[T_2:%.*]] = icmp ule i8 [[A]], [[B]]
234-
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[T_1]], [[T_2]]
234+
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true
235235
; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2
236236
; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]]
237237
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
@@ -299,7 +299,7 @@ define i1 @assume_same_bb_before_may_exiting_call(i8 %a, i8 %b, i1 %c) {
299299
; CHECK-NEXT: call void @may_unwind()
300300
; CHECK-NEXT: [[T_1:%.*]] = icmp ule i8 [[ADD_1]], [[B]]
301301
; CHECK-NEXT: [[T_2:%.*]] = icmp ule i8 [[A]], [[B]]
302-
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[T_1]], [[T_2]]
302+
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true
303303
; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2
304304
; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]]
305305
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
@@ -328,7 +328,7 @@ define i1 @assume_same_bb_after_condition(i8 %a, i8 %b, i1 %c) {
328328
; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i8 [[A:%.*]], 1
329329
; CHECK-NEXT: [[T_1:%.*]] = icmp ule i8 [[ADD_1]], [[B:%.*]]
330330
; CHECK-NEXT: [[T_2:%.*]] = icmp ule i8 [[A]], [[B]]
331-
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[T_1]], [[T_2]]
331+
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true
332332
; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i8 [[A]], 2
333333
; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[ADD_2]], [[B]]
334334
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
@@ -394,6 +394,7 @@ exit:
394394
}
395395

396396
; The information of from the assume can be used to simplify %t.2.
397+
; TODO
397398
define i1 @assume_single_bb_conditions_after_assume(i8 %a, i8 %b, i1 %c) {
398399
; CHECK-LABEL: @assume_single_bb_conditions_after_assume(
399400
; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i8 [[A:%.*]], 1
@@ -425,6 +426,7 @@ define i1 @assume_single_bb_conditions_after_assume(i8 %a, i8 %b, i1 %c) {
425426
}
426427

427428
; The information of from the assume can be used to simplify %t.2.
429+
; TODO
428430
define i1 @assume_single_bb_assume_at_end_after_may_unwind(i8 %a, i8 %b, i1 %c) {
429431
; CHECK-LABEL: @assume_single_bb_assume_at_end_after_may_unwind(
430432
; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i8 [[A:%.*]], 1
@@ -457,6 +459,7 @@ define i1 @assume_single_bb_assume_at_end_after_may_unwind(i8 %a, i8 %b, i1 %c)
457459

458460
; The definition of %t.2 is before the @llvm.assume call, but all uses are
459461
; after the call. %t.2 can be simplified.
462+
; TODO
460463
define i1 @all_uses_after_assume(i8 %a, i8 %b, i1 %c) {
461464
; CHECK-LABEL: @all_uses_after_assume(
462465
; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i8 [[A:%.*]], 1

0 commit comments

Comments
 (0)