Skip to content

Commit 7d2b6f0

Browse files
authored
[IndVarSimplify] Fix poison-safety when reusing instructions (#80458)
IndVars may replace an instruction with one of its operands, if they have the same SCEV expression. However, such a replacement may be more poisonous. First, check whether the operand being poison implies that the instruction is also poison, in which case the replacement is always safe. If this fails, check whether SCEV can determine that reusing the instruction is safe, using the same check as SCEVExpander. Fixes #79861.
1 parent 6deb7cf commit 7d2b6f0

File tree

3 files changed

+22
-6
lines changed

3 files changed

+22
-6
lines changed

llvm/lib/Transforms/Utils/SimplifyIndVar.cpp

+16-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "llvm/ADT/SmallVector.h"
1717
#include "llvm/ADT/Statistic.h"
1818
#include "llvm/Analysis/LoopInfo.h"
19+
#include "llvm/Analysis/ValueTracking.h"
1920
#include "llvm/IR/Dominators.h"
2021
#include "llvm/IR/IRBuilder.h"
2122
#include "llvm/IR/Instructions.h"
@@ -713,8 +714,11 @@ bool SimplifyIndvar::replaceFloatIVWithIntegerIV(Instruction *UseInst) {
713714
bool SimplifyIndvar::eliminateIdentitySCEV(Instruction *UseInst,
714715
Instruction *IVOperand) {
715716
if (!SE->isSCEVable(UseInst->getType()) ||
716-
(UseInst->getType() != IVOperand->getType()) ||
717-
(SE->getSCEV(UseInst) != SE->getSCEV(IVOperand)))
717+
UseInst->getType() != IVOperand->getType())
718+
return false;
719+
720+
const SCEV *UseSCEV = SE->getSCEV(UseInst);
721+
if (UseSCEV != SE->getSCEV(IVOperand))
718722
return false;
719723

720724
// getSCEV(X) == getSCEV(Y) does not guarantee that X and Y are related in the
@@ -742,6 +746,16 @@ bool SimplifyIndvar::eliminateIdentitySCEV(Instruction *UseInst,
742746
if (!LI->replacementPreservesLCSSAForm(UseInst, IVOperand))
743747
return false;
744748

749+
// Make sure the operand is not more poisonous than the instruction.
750+
if (!impliesPoison(IVOperand, UseInst)) {
751+
SmallVector<Instruction *> DropPoisonGeneratingInsts;
752+
if (!SE->canReuseInstruction(UseSCEV, IVOperand, DropPoisonGeneratingInsts))
753+
return false;
754+
755+
for (Instruction *I : DropPoisonGeneratingInsts)
756+
I->dropPoisonGeneratingFlagsAndMetadata();
757+
}
758+
745759
LLVM_DEBUG(dbgs() << "INDVARS: Eliminated identity: " << *UseInst << '\n');
746760

747761
SE->forgetValue(UseInst);

llvm/test/Transforms/IndVarSimplify/pr55925.ll

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ define void @test(ptr %p) personality ptr undef {
1818
; CHECK-NEXT: [[RES:%.*]] = invoke i32 @foo(i32 returned [[TMP0]])
1919
; CHECK-NEXT: to label [[LOOP_LATCH]] unwind label [[EXIT:%.*]]
2020
; CHECK: loop.latch:
21-
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1
2221
; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INDVARS_IV]] to i32
2322
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @foo(i32 [[TMP1]])
23+
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1
2424
; CHECK-NEXT: br label [[LOOP]]
2525
; CHECK: exit:
2626
; CHECK-NEXT: [[LP:%.*]] = landingpad { ptr, i32 }
@@ -64,8 +64,8 @@ define void @test_critedge(i1 %c, ptr %p) personality ptr undef {
6464
; CHECK-NEXT: br label [[LOOP_LATCH]]
6565
; CHECK: loop.latch:
6666
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[TMP1]], [[LOOP_INVOKE]] ], [ 0, [[LOOP_OTHER]] ]
67-
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1
6867
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @foo(i32 [[PHI]])
68+
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1
6969
; CHECK-NEXT: br label [[LOOP]]
7070
; CHECK: exit:
7171
; CHECK-NEXT: [[LP:%.*]] = landingpad { ptr, i32 }

llvm/test/Transforms/IndVarSimplify/pr79861.ll

+4-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ define void @or_disjoint() {
1212
; CHECK: loop:
1313
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 2, [[ENTRY:%.*]] ], [ [[IV_DEC:%.*]], [[LOOP]] ]
1414
; CHECK-NEXT: [[OR:%.*]] = or disjoint i64 [[IV]], 1
15-
; CHECK-NEXT: call void @use(i64 [[OR]])
15+
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i64 [[IV]], 1
16+
; CHECK-NEXT: [[SEL:%.*]] = select i1 false, i64 [[OR]], i64 [[ADD]]
17+
; CHECK-NEXT: call void @use(i64 [[SEL]])
1618
; CHECK-NEXT: [[IV_DEC]] = add nsw i64 [[IV]], -1
1719
; CHECK-NEXT: [[EXIT_COND:%.*]] = icmp eq i64 [[IV_DEC]], 0
1820
; CHECK-NEXT: br i1 [[EXIT_COND]], label [[EXIT:%.*]], label [[LOOP]]
@@ -44,7 +46,7 @@ define void @add_nowrap_flags(i64 %n) {
4446
; CHECK-NEXT: br label [[LOOP:%.*]]
4547
; CHECK: loop:
4648
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_INC:%.*]], [[LOOP]] ]
47-
; CHECK-NEXT: [[ADD1:%.*]] = add nuw nsw i64 [[IV]], 123
49+
; CHECK-NEXT: [[ADD1:%.*]] = add i64 [[IV]], 123
4850
; CHECK-NEXT: call void @use(i64 [[ADD1]])
4951
; CHECK-NEXT: [[IV_INC]] = add i64 [[IV]], 1
5052
; CHECK-NEXT: [[EXIT_COND:%.*]] = icmp eq i64 [[IV_INC]], [[N]]

0 commit comments

Comments
 (0)