llvm.org GIT mirror llvm / ff70002
[PGO][CHR] A bug fix. Summary: Fix a transformation bug where two scopes share a common instrution to hoist. Reviewers: davidxl Reviewed By: davidxl Subscribers: llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D61405 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@359736 91177308-0d34-0410-b5e6-96231b3b80d8 Hiroshi Yamauchi 4 months ago
2 changed file(s) with 140 addition(s) and 6 deletion(s). Raw diff Collapse all Expand all
14231423 static void hoistValue(Value *V, Instruction *HoistPoint, Region *R,
14241424 HoistStopMapTy &HoistStopMap,
14251425 DenseSet &HoistedSet,
1426 DenseSet &TrivialPHIs) {
1426 DenseSet &TrivialPHIs,
1427 DominatorTree &DT) {
14271428 auto IT = HoistStopMap.find(R);
14281429 assert(IT != HoistStopMap.end() && "Region must be in hoist stop map");
14291430 DenseSet &HoistStops = IT->second;
14431444 // Already hoisted, return.
14441445 return;
14451446 assert(isHoistableInstructionType(I) && "Unhoistable instruction type");
1447 assert(DT.getNode(I->getParent()) && "DT must contain I's block");
1448 assert(DT.getNode(HoistPoint->getParent()) &&
1449 "DT must contain HoistPoint block");
1450 if (DT.dominates(I, HoistPoint))
1451 // We are already above the hoist point. Stop here. This may be necessary
1452 // when multiple scopes would independently hoist the same
1453 // instruction. Since an outer (dominating) scope would hoist it to its
1454 // entry before an inner (dominated) scope would to its entry, the inner
1455 // scope may see the instruction already hoisted, in which case it
1456 // potentially wrong for the inner scope to hoist it and could cause bad
1457 // IR (non-dominating def), but safe to skip hoisting it instead because
1458 // it's already in a block that dominates the inner scope.
1459 return;
14461460 for (Value *Op : I->operands()) {
1447 hoistValue(Op, HoistPoint, R, HoistStopMap, HoistedSet, TrivialPHIs);
1461 hoistValue(Op, HoistPoint, R, HoistStopMap, HoistedSet, TrivialPHIs, DT);
14481462 }
14491463 I->moveBefore(HoistPoint);
14501464 HoistedSet.insert(I);
14551469 // Hoist the dependent condition values of the branches and the selects in the
14561470 // scope to the insert point.
14571471 static void hoistScopeConditions(CHRScope *Scope, Instruction *HoistPoint,
1458 DenseSet &TrivialPHIs) {
1472 DenseSet &TrivialPHIs,
1473 DominatorTree &DT) {
14591474 DenseSet HoistedSet;
14601475 for (const RegInfo &RI : Scope->CHRRegions) {
14611476 Region *R = RI.R;
14641479 if (RI.HasBranch && (IsTrueBiased || IsFalseBiased)) {
14651480 auto *BI = cast(R->getEntry()->getTerminator());
14661481 hoistValue(BI->getCondition(), HoistPoint, R, Scope->HoistStopMap,
1467 HoistedSet, TrivialPHIs);
1482 HoistedSet, TrivialPHIs, DT);
14681483 }
14691484 for (SelectInst *SI : RI.Selects) {
14701485 bool IsTrueBiased = Scope->TrueBiasedSelects.count(SI);
14721487 if (!(IsTrueBiased || IsFalseBiased))
14731488 continue;
14741489 hoistValue(SI->getCondition(), HoistPoint, R, Scope->HoistStopMap,
1475 HoistedSet, TrivialPHIs);
1490 HoistedSet, TrivialPHIs, DT);
14761491 }
14771492 }
14781493 }
17061721 #endif
17071722
17081723 // Hoist the conditional values of the branches/selects.
1709 hoistScopeConditions(Scope, PreEntryBlock->getTerminator(), TrivialPHIs);
1724 hoistScopeConditions(Scope, PreEntryBlock->getTerminator(), TrivialPHIs, DT);
17101725
17111726 #ifndef NDEBUG
17121727 assertBranchOrSelectConditionHoisted(Scope, PreEntryBlock);
18851885 ret i32 %v13
18861886 }
18871887
1888 ; Test the case where two scopes share a common instruction to hoist (%cmp.i).
1889 ; Two scopes would hoist it to their hoist points, but since the outer scope
1890 ; hoists (entry/bb6-9) it first to its hoist point, it'd be wrong (causing bad
1891 ; IR) for the inner scope (bb1-4) to hoist the same instruction to its hoist
1892 ; point.
1893 ; Roughly,
1894 ; if (j != k) {
1895 ; if (i != 2)
1896 ; foo();
1897 ; cmp.i = i == 86
1898 ; if (!cmp.i)
1899 ; foo();
1900 ; if (j != i)
1901 ; foo();
1902 ; if (!cmp.i)
1903 ; foo();
1904 ; }
1905 ; return 45;
1906 define i32 @test_chr_21(i64 %i, i64 %k, i64 %j) !prof !14 {
1907 ; CHECK-LABEL: @test_chr_21(
1908 ; CHECK-NEXT: entry:
1909 ; CHECK-NEXT: [[CMP0:%.*]] = icmp ne i64 [[J:%.*]], [[K:%.*]]
1910 ; CHECK-NEXT: [[CMP3:%.*]] = icmp ne i64 [[J]], [[I:%.*]]
1911 ; CHECK-NEXT: [[CMP_I:%.*]] = icmp ne i64 [[I]], 86
1912 ; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[CMP0]], [[CMP3]]
1913 ; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[TMP0]], [[CMP_I]]
1914 ; CHECK-NEXT: br i1 [[TMP1]], label [[BB1:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
1915 ; CHECK: bb1:
1916 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i64 [[I]], 2
1917 ; CHECK-NEXT: switch i64 [[I]], label [[BB2:%.*]] [
1918 ; CHECK-NEXT: i64 2, label [[BB3_NONCHR2:%.*]]
1919 ; CHECK-NEXT: i64 86, label [[BB2_NONCHR1:%.*]]
1920 ; CHECK-NEXT: ], !prof !20
1921 ; CHECK: bb2:
1922 ; CHECK-NEXT: call void @foo()
1923 ; CHECK-NEXT: call void @foo()
1924 ; CHECK-NEXT: br label [[BB7:%.*]]
1925 ; CHECK: bb2.nonchr1:
1926 ; CHECK-NEXT: call void @foo()
1927 ; CHECK-NEXT: br label [[BB3_NONCHR2]]
1928 ; CHECK: bb3.nonchr2:
1929 ; CHECK-NEXT: br i1 [[CMP_I]], label [[BB4_NONCHR3:%.*]], label [[BB7]], !prof !18
1930 ; CHECK: bb4.nonchr3:
1931 ; CHECK-NEXT: call void @foo()
1932 ; CHECK-NEXT: br label [[BB7]]
1933 ; CHECK: bb7:
1934 ; CHECK-NEXT: call void @foo()
1935 ; CHECK-NEXT: call void @foo()
1936 ; CHECK-NEXT: br label [[BB10:%.*]]
1937 ; CHECK: entry.split.nonchr:
1938 ; CHECK-NEXT: br i1 [[CMP0]], label [[BB1_NONCHR:%.*]], label [[BB10]], !prof !18
1939 ; CHECK: bb1.nonchr:
1940 ; CHECK-NEXT: [[CMP2_NONCHR:%.*]] = icmp eq i64 [[I]], 2
1941 ; CHECK-NEXT: br i1 [[CMP2_NONCHR]], label [[BB3_NONCHR:%.*]], label [[BB2_NONCHR:%.*]], !prof !16
1942 ; CHECK: bb3.nonchr:
1943 ; CHECK-NEXT: [[CMP_I_NONCHR:%.*]] = icmp eq i64 [[I]], 86
1944 ; CHECK-NEXT: br i1 [[CMP_I_NONCHR]], label [[BB6_NONCHR:%.*]], label [[BB4_NONCHR:%.*]], !prof !16
1945 ; CHECK: bb6.nonchr:
1946 ; CHECK-NEXT: [[CMP3_NONCHR:%.*]] = icmp eq i64 [[J]], [[I]]
1947 ; CHECK-NEXT: br i1 [[CMP3_NONCHR]], label [[BB8_NONCHR:%.*]], label [[BB7_NONCHR:%.*]], !prof !16
1948 ; CHECK: bb8.nonchr:
1949 ; CHECK-NEXT: br i1 [[CMP_I_NONCHR]], label [[BB10]], label [[BB9_NONCHR:%.*]], !prof !16
1950 ; CHECK: bb9.nonchr:
1951 ; CHECK-NEXT: call void @foo()
1952 ; CHECK-NEXT: br label [[BB10]]
1953 ; CHECK: bb7.nonchr:
1954 ; CHECK-NEXT: call void @foo()
1955 ; CHECK-NEXT: br label [[BB8_NONCHR]]
1956 ; CHECK: bb4.nonchr:
1957 ; CHECK-NEXT: call void @foo()
1958 ; CHECK-NEXT: br label [[BB6_NONCHR]]
1959 ; CHECK: bb2.nonchr:
1960 ; CHECK-NEXT: call void @foo()
1961 ; CHECK-NEXT: br label [[BB3_NONCHR]]
1962 ; CHECK: bb10:
1963 ; CHECK-NEXT: ret i32 45
1964 ;
1965 entry:
1966 %cmp0 = icmp eq i64 %j, %k
1967 br i1 %cmp0, label %bb10, label %bb1, !prof !15
1968
1969 bb1:
1970 %cmp2 = icmp eq i64 %i, 2
1971 br i1 %cmp2, label %bb3, label %bb2, !prof !15
1972
1973 bb2:
1974 call void @foo()
1975 br label %bb3
1976
1977 bb3:
1978 %cmp.i = icmp eq i64 %i, 86
1979 br i1 %cmp.i, label %bb5, label %bb4, !prof !15
1980
1981 bb4:
1982 call void @foo()
1983 br label %bb5
1984
1985 bb5:
1986 br label %bb6
1987
1988 bb6:
1989 %cmp3 = icmp eq i64 %j, %i
1990 br i1 %cmp3, label %bb8, label %bb7, !prof !15
1991
1992 bb7:
1993 call void @foo()
1994 br label %bb8
1995
1996 bb8:
1997 br i1 %cmp.i, label %bb10, label %bb9, !prof !15
1998
1999 bb9:
2000 call void @foo()
2001 br label %bb10
2002
2003 bb10:
2004 ret i32 45
2005 }
2006
18882007 !llvm.module.flags = !{!0}
18892008 !0 = !{i32 1, !"ProfileSummary", !1}
18902009 !1 = !{!2, !3, !4, !5, !6, !7, !8, !9}