Skip to content

Commit d1fbdde

Browse files
authored
[NaryReassociate] Check to avoid introducing poison when reusing SCEVs (llvm#98156)
Drop the poison flags if possible or skip the candidate if it's not. Otherwise we'd introduce poison in places where it previously wasn't, leading to miscompiles.
1 parent 0ad9d8f commit d1fbdde

File tree

2 files changed

+56
-6
lines changed

2 files changed

+56
-6
lines changed

llvm/lib/Transforms/Scalar/NaryReassociate.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -565,14 +565,24 @@ NaryReassociatePass::findClosestMatchingDominator(const SCEV *CandidateExpr,
565565
// optimization makes the algorithm O(n).
566566
while (!Candidates.empty()) {
567567
// Candidates stores WeakTrackingVHs, so a candidate can be nullptr if it's
568-
// removed
569-
// during rewriting.
570-
if (Value *Candidate = Candidates.back()) {
568+
// removed during rewriting.
569+
if (Value *Candidate = Candidates.pop_back_val()) {
571570
Instruction *CandidateInstruction = cast<Instruction>(Candidate);
572-
if (DT->dominates(CandidateInstruction, Dominatee))
573-
return CandidateInstruction;
571+
if (!DT->dominates(CandidateInstruction, Dominatee))
572+
continue;
573+
574+
// Make sure that the instruction is safe to reuse without introducing
575+
// poison.
576+
SmallVector<Instruction *> DropPoisonGeneratingInsts;
577+
if (!SE->canReuseInstruction(CandidateExpr, CandidateInstruction,
578+
DropPoisonGeneratingInsts))
579+
continue;
580+
581+
for (Instruction *I : DropPoisonGeneratingInsts)
582+
I->dropPoisonGeneratingAnnotations();
583+
584+
return CandidateInstruction;
574585
}
575-
Candidates.pop_back();
576586
}
577587
return nullptr;
578588
}

llvm/test/Transforms/NaryReassociate/nary-gep.ll

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,44 @@ define void @no_sext_fat_pointer(ptr addrspace(2) %a, i32 %i, i32 %j) {
2121
ret void
2222
}
2323

24+
define void @or_disjoint(ptr addrspace(2) %a, i32 %i, i32 %j, i32 %k) {
25+
; CHECK-LABEL: @or_disjoint(
26+
; CHECK-NEXT: [[OR:%.*]] = or disjoint i32 [[I:%.*]], [[J:%.*]]
27+
; CHECK-NEXT: [[V2:%.*]] = getelementptr float, ptr addrspace(2) [[A:%.*]], i32 [[OR]]
28+
; CHECK-NEXT: call void @foo(ptr addrspace(2) [[V2]])
29+
; CHECK-NEXT: [[ADD1:%.*]] = add nuw nsw i32 [[I]], [[J]]
30+
; CHECK-NEXT: [[ADD2:%.*]] = add nuw nsw i32 [[ADD1]], [[K:%.*]]
31+
; CHECK-NEXT: [[V3:%.*]] = getelementptr float, ptr addrspace(2) [[A]], i32 [[ADD2]]
32+
; CHECK-NEXT: call void @foo(ptr addrspace(2) [[V3]])
33+
; CHECK-NEXT: ret void
34+
;
35+
%or = or disjoint i32 %i, %j
36+
%v2 = getelementptr float, ptr addrspace(2) %a, i32 %or
37+
call void @foo(ptr addrspace(2) %v2)
38+
%add1 = add nuw nsw i32 %i, %j
39+
%add2 = add nuw nsw i32 %add1, %k
40+
%v3 = getelementptr float, ptr addrspace(2) %a, i32 %add2
41+
call void @foo(ptr addrspace(2) %v3)
42+
ret void
43+
}
44+
45+
define void @drop_nuw_nsw(ptr addrspace(2) %a, i32 %i, i32 %j, i32 %k) {
46+
; CHECK-LABEL: @drop_nuw_nsw(
47+
; CHECK-NEXT: [[ADD0:%.*]] = add i32 [[I:%.*]], [[J:%.*]]
48+
; CHECK-NEXT: [[V2:%.*]] = getelementptr float, ptr addrspace(2) [[A:%.*]], i32 [[ADD0]]
49+
; CHECK-NEXT: call void @foo(ptr addrspace(2) [[V2]])
50+
; CHECK-NEXT: [[V3:%.*]] = getelementptr float, ptr addrspace(2) [[V2]], i32 [[K:%.*]]
51+
; CHECK-NEXT: call void @foo(ptr addrspace(2) [[V3]])
52+
; CHECK-NEXT: ret void
53+
;
54+
%add0 = add nuw nsw i32 %i, %j
55+
%v2 = getelementptr float, ptr addrspace(2) %a, i32 %add0
56+
call void @foo(ptr addrspace(2) %v2)
57+
%add1 = add i32 %i, %j
58+
%add2 = add nuw nsw i32 %add1, %k
59+
%v3 = getelementptr float, ptr addrspace(2) %a, i32 %add2
60+
call void @foo(ptr addrspace(2) %v3)
61+
ret void
62+
}
63+
2464
declare void @foo(ptr addrspace(2))

0 commit comments

Comments
 (0)