Files
clang-p2996/llvm/test/Transforms/NewGVN/pr31613_2.ll
Alina Sbirlea 46fb810955 [NewGVN] Use PredicateInfo info when previously used for the same ssa.copy intrinsic
Symbolic execution using PredicateInfo is only done for the ssa.copy
intrinsic. It's using two potential sources for building the expression:
1. the Value of the instruction for which the instruction is a copy of, and
2. the Value from the contraint in PredicateInfo
It's possible to get into an infinite loop when choosing between these
two, as described in PR31613.

This patch proposes performing swapping of the two values (i.e. choosing
the second one for the expression), if that same second value was chosen
before; this breaks the cycle.

In the testcases provided, where there is a contradiction between the
value from symbolic execution and assume instruction, NewGVN reduces the
assume to assume(false).

Resolves PR31613.

Differential Revision: https://reviews.llvm.org/D110907
2021-12-13 16:49:24 -08:00

142 lines
4.9 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=newgvn -S | FileCheck %s
; REQUIRES: asserts
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-grtev4-linux-gnu"
define hidden void @barrier() align 2 {
; CHECK-LABEL: @barrier(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALLG:%.*]] = tail call i64 @g()
; CHECK-NEXT: [[SEL:%.*]] = select i1 undef, i64 0, i64 [[CALLG]]
; CHECK-NEXT: [[LOADED:%.*]] = load i64, i64* null, align 8
; CHECK-NEXT: [[ADD:%.*]] = add i64 [[LOADED]], 1
; CHECK-NEXT: [[SHR17:%.*]] = lshr i64 [[ADD]], 1
; CHECK-NEXT: [[SUB:%.*]] = add nsw i64 [[SHR17]], -1
; CHECK-NEXT: br label [[FIRST:%.*]]
; CHECK: first:
; CHECK-NEXT: [[PHI_ONE:%.*]] = phi i64 [ [[SEL]], [[ENTRY:%.*]] ], [ 0, [[FIRST]] ], [ 0, [[THIRD:%.*]] ]
; CHECK-NEXT: [[CMP_PHI1_SUB:%.*]] = icmp eq i64 [[PHI_ONE]], [[SUB]]
; CHECK-NEXT: br i1 [[CMP_PHI1_SUB]], label [[SECOND:%.*]], label [[FIRST]]
; CHECK: second:
; CHECK-NEXT: br label [[THIRD]]
; CHECK: third:
; CHECK-NEXT: br i1 false, label [[SECOND]], label [[FIRST]]
;
entry:
%callg = tail call i64 @g()
%sel = select i1 undef, i64 0, i64 %callg
%loaded = load i64, i64* null, align 8
%add = add i64 %loaded, 1
%shr17 = lshr i64 %add, 1
%sub = add nsw i64 %shr17, -1
br label %first
first:
%phi_one = phi i64 [ %sel, %entry ], [ 0, %first ], [ 0, %third ]
%cmp_phi1_sub = icmp eq i64 %phi_one, %sub
br i1 %cmp_phi1_sub, label %second, label %first
second:
%phi_two = phi i64 [ %inc, %third ], [ %phi_one, %first ]
br label %third
third:
%inc = add i64 %phi_two, 1
%cmp_inc_sub = icmp eq i64 %inc, %sub
br i1 %cmp_inc_sub, label %second, label %first
}
define hidden void @barrier2() align 2 {
; CHECK-LABEL: @barrier2(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* null, align 8
; CHECK-NEXT: [[CALL9:%.*]] = tail call i64 @g()
; CHECK-NEXT: [[REM:%.*]] = select i1 undef, i64 0, i64 [[CALL9]]
; CHECK-NEXT: [[ADD:%.*]] = add i64 [[TMP0]], 1
; CHECK-NEXT: [[SHR17:%.*]] = lshr i64 [[ADD]], 1
; CHECK-NEXT: [[SUB:%.*]] = add nsw i64 [[SHR17]], -1
; CHECK-NEXT: br label [[MAINLOOP:%.*]]
; CHECK: second.exit:
; CHECK-NEXT: br label [[FIRST_EXIT:%.*]]
; CHECK: first.exit:
; CHECK-NEXT: br label [[MAINLOOP]]
; CHECK: mainloop:
; CHECK-NEXT: [[FIRSTPHI:%.*]] = phi i64 [ [[REM]], [[ENTRY:%.*]] ], [ 0, [[FIRST_EXIT]] ]
; CHECK-NEXT: [[FIRSTCMP:%.*]] = icmp eq i64 [[FIRSTPHI]], [[SUB]]
; CHECK-NEXT: br i1 [[FIRSTCMP]], label [[SECOND_PREHEADER:%.*]], label [[FIRST_EXIT]]
; CHECK: second.preheader:
; CHECK-NEXT: br label [[INNERLOOP:%.*]]
; CHECK: innerloop:
; CHECK-NEXT: br label [[CLEANUP:%.*]]
; CHECK: cleanup:
; CHECK-NEXT: br i1 false, label [[INNERLOOP]], label [[SECOND_EXIT:%.*]]
;
entry:
%0 = load i64, i64* null, align 8
%call9 = tail call i64 @g()
%rem = select i1 undef, i64 0, i64 %call9
%add = add i64 %0, 1
%shr17 = lshr i64 %add, 1
%sub = add nsw i64 %shr17, -1
br label %mainloop
second.exit: ; preds = %cleanup
br label %first.exit
first.exit: ; preds = %mainloop, %second.exit
br label %mainloop
mainloop: ; preds = %first.exit, %entry
%firstphi = phi i64 [ %rem, %entry ], [ 0, %first.exit ]
%firstcmp = icmp eq i64 %firstphi, %sub
br i1 %firstcmp, label %second.preheader, label %first.exit
second.preheader: ; preds = %mainloop
br label %innerloop
innerloop: ; preds = %cleanup, %second.preheader
%secondphi = phi i64 [ %inc, %cleanup ], [ %firstphi, %second.preheader ]
br label %cleanup
cleanup: ; preds = %innerloop
%inc = add i64 %secondphi, 1
%secondcmp = icmp eq i64 %inc, %sub
br i1 %secondcmp, label %innerloop, label %second.exit
}
declare hidden i64 @g() local_unnamed_addr align 2
define void @barrier3(i64 %arg) {
; CHECK-LABEL: @barrier3(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FIRSTLOOP:%.*]]
; CHECK: firstloop:
; CHECK-NEXT: [[PHI1:%.*]] = phi i64 [ [[ARG:%.*]], [[ENTRY:%.*]] ], [ 0, [[FIRSTLOOP]] ]
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i64 [[PHI1]], -1
; CHECK-NEXT: br i1 [[CMP1]], label [[SECONDLOOP:%.*]], label [[FIRSTLOOP]]
; CHECK: secondloop:
; CHECK-NEXT: call void @llvm.assume(i1 false)
; CHECK-NEXT: br label [[SECONDLOOP]]
;
entry:
br label %firstloop
firstloop:
%phi1 = phi i64 [ %arg, %entry ], [ 0, %firstloop ]
%cmp1 = icmp eq i64 %phi1, -1
br i1 %cmp1, label %secondloop, label %firstloop
secondloop:
%phi2 = phi i64 [ %inc, %secondloop ], [ %phi1, %firstloop ]
%inc = add i64 %phi2, 1
%cmp2 = icmp eq i64 %inc, -1
call void @llvm.assume(i1 %cmp2)
br label %secondloop
}
declare void @llvm.assume(i1)