Skip to content

Commit 243df83

Browse files
committed
[LICM] Fix assert failure in no-allowspeculation mode
In this case the source GEP might not be hoisted even though it has invariant operands. For now just bail out, but we might need additional checks for AllowSpeculation in these special-case reassociation folds.
1 parent 3d86ab9 commit 243df83

File tree

2 files changed

+60
-3
lines changed

2 files changed

+60
-3
lines changed

llvm/lib/Transforms/Scalar/LICM.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2514,8 +2514,12 @@ static bool hoistGEP(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo,
25142514
if (!L.isLoopInvariant(SrcPtr) || !all_of(GEP->indices(), LoopInvariant))
25152515
return false;
25162516

2517-
assert(!all_of(Src->indices(), LoopInvariant) &&
2518-
"Would have been hoisted already");
2517+
// This can only happen if !AllowSpeculation, otherwise this would already be
2518+
// handled.
2519+
// FIXME: Should we respect AllowSpeculation in these reassociation folds?
2520+
// The flag exists to prevent metadata dropping, which is not relevant here.
2521+
if (all_of(Src->indices(), LoopInvariant))
2522+
return false;
25192523

25202524
// The swapped GEPs are inbounds if both original GEPs are inbounds
25212525
// and the sign of the offsets is the same. For simplicity, only

llvm/test/Transforms/LICM/gep-reassociate.ll

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2-
; RUN: opt -S -passes=licm < %s | FileCheck %s
2+
; RUN: opt -S -passes=licm < %s | FileCheck %s --check-prefixes=CHECK,SPEC
3+
; RUN: opt -S -passes='licm<no-allowspeculation>' < %s | FileCheck %s --check-prefixes=CHECK,NOSPEC
34

45
declare void @use(ptr)
56
declare i32 @get.i32()
@@ -387,3 +388,55 @@ loop:
387388
exit:
388389
ret void
389390
}
391+
392+
define void @src_already_invariant_speculation(ptr %ptr, i1 %c, i1 %c2, i64 %arg1, i64 %arg2) {
393+
; SPEC-LABEL: define void @src_already_invariant_speculation
394+
; SPEC-SAME: (ptr [[PTR:%.*]], i1 [[C:%.*]], i1 [[C2:%.*]], i64 [[ARG1:%.*]], i64 [[ARG2:%.*]]) {
395+
; SPEC-NEXT: entry:
396+
; SPEC-NEXT: [[PTR2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[ARG1]]
397+
; SPEC-NEXT: [[PTR3:%.*]] = getelementptr i8, ptr [[PTR2]], i64 [[ARG2]]
398+
; SPEC-NEXT: br label [[LOOP:%.*]]
399+
; SPEC: loop:
400+
; SPEC-NEXT: br i1 [[C2]], label [[IF:%.*]], label [[LATCH:%.*]]
401+
; SPEC: if:
402+
; SPEC-NEXT: call void @use(ptr [[PTR3]])
403+
; SPEC-NEXT: br label [[LATCH]]
404+
; SPEC: latch:
405+
; SPEC-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]]
406+
; SPEC: exit:
407+
; SPEC-NEXT: ret void
408+
;
409+
; NOSPEC-LABEL: define void @src_already_invariant_speculation
410+
; NOSPEC-SAME: (ptr [[PTR:%.*]], i1 [[C:%.*]], i1 [[C2:%.*]], i64 [[ARG1:%.*]], i64 [[ARG2:%.*]]) {
411+
; NOSPEC-NEXT: entry:
412+
; NOSPEC-NEXT: br label [[LOOP:%.*]]
413+
; NOSPEC: loop:
414+
; NOSPEC-NEXT: br i1 [[C2]], label [[IF:%.*]], label [[LATCH:%.*]]
415+
; NOSPEC: if:
416+
; NOSPEC-NEXT: [[PTR2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[ARG1]]
417+
; NOSPEC-NEXT: [[PTR3:%.*]] = getelementptr i8, ptr [[PTR2]], i64 [[ARG2]]
418+
; NOSPEC-NEXT: call void @use(ptr [[PTR3]])
419+
; NOSPEC-NEXT: br label [[LATCH]]
420+
; NOSPEC: latch:
421+
; NOSPEC-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]]
422+
; NOSPEC: exit:
423+
; NOSPEC-NEXT: ret void
424+
;
425+
entry:
426+
br label %loop
427+
428+
loop:
429+
br i1 %c2, label %if, label %latch
430+
431+
if:
432+
%ptr2 = getelementptr i8, ptr %ptr, i64 %arg1
433+
%ptr3 = getelementptr i8, ptr %ptr2, i64 %arg2
434+
call void @use(ptr %ptr3)
435+
br label %latch
436+
437+
latch:
438+
br i1 %c, label %loop, label %exit
439+
440+
exit:
441+
ret void
442+
}

0 commit comments

Comments
 (0)