mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
c5b8c59aa2
Currently SCCP does not widen PHIs, stores or along call edges (arguments/return values), but on operations that directly extend ranges (like binary operators). This means PHIs, stores and call edges are not pessimized by widening currently, while binary operators are. The main reason for widening operators initially was that opting-out for certain operations was more straight-forward in the initial implementation (and it did not matter too much, as range support initially was only implemented for a very limited set of operations. During the discussion in D78391, it was suggested to consider flipping widening to PHIs, stores and along call edges. After adding support for tracking the number of range extensions in ValueLattice, limiting the number of range extensions per value is straight forward. This patch introduces a MaxWidenSteps option to the MergeOptions, limiting the number of range extensions per value. For PHIs, it seems natural allow an extension for each (active) incoming value plus 1. For the other cases, a arbitrary limit of 10 has been chosen initially. It would potentially make sense to set it depending on the users of a function/global, but that still needs investigating. This potentially leads to more state-changes and longer compile-times. The results look quite promising (MultiSource, SPEC): Same hash: 179 (filtered out) Remaining: 58 Metric: sccp.IPNumInstRemoved Program base widen-phi diff test-suite...ks/Prolangs-C/agrep/agrep.test 58.00 82.00 41.4% test-suite...marks/SciMark2-C/scimark2.test 32.00 43.00 34.4% test-suite...rks/FreeBench/mason/mason.test 6.00 8.00 33.3% test-suite...langs-C/football/football.test 104.00 128.00 23.1% test-suite...cations/hexxagon/hexxagon.test 36.00 42.00 16.7% test-suite...CFP2000/177.mesa/177.mesa.test 214.00 249.00 16.4% test-suite...ngs-C/assembler/assembler.test 14.00 16.00 14.3% test-suite...arks/VersaBench/dbms/dbms.test 10.00 11.00 10.0% test-suite...oxyApps-C++/miniFE/miniFE.test 43.00 47.00 9.3% test-suite...ications/JM/ldecod/ldecod.test 179.00 195.00 8.9% test-suite...CFP2006/433.milc/433.milc.test 249.00 265.00 6.4% test-suite.../CINT2000/175.vpr/175.vpr.test 98.00 104.00 6.1% test-suite...peg2/mpeg2dec/mpeg2decode.test 70.00 74.00 5.7% test-suite...CFP2000/188.ammp/188.ammp.test 71.00 75.00 5.6% test-suite...ce/Benchmarks/PAQ8p/paq8p.test 111.00 117.00 5.4% test-suite...ce/Applications/Burg/burg.test 41.00 43.00 4.9% test-suite...000/197.parser/197.parser.test 66.00 69.00 4.5% test-suite...tions/lambda-0.1.3/lambda.test 23.00 24.00 4.3% test-suite...urce/Applications/lua/lua.test 301.00 313.00 4.0% test-suite...TimberWolfMC/timberwolfmc.test 76.00 79.00 3.9% test-suite...lications/ClamAV/clamscan.test 991.00 1030.00 3.9% test-suite...plications/d/make_dparser.test 53.00 55.00 3.8% test-suite...fice-ispell/office-ispell.test 83.00 86.00 3.6% test-suite...lications/obsequi/Obsequi.test 28.00 29.00 3.6% test-suite.../Prolangs-C/bison/mybison.test 56.00 58.00 3.6% test-suite.../CINT2000/254.gap/254.gap.test 170.00 176.00 3.5% test-suite.../Applications/lemon/lemon.test 30.00 31.00 3.3% test-suite.../CINT2000/176.gcc/176.gcc.test 1202.00 1240.00 3.2% test-suite...pplications/treecc/treecc.test 79.00 81.00 2.5% test-suite...chmarks/MallocBench/gs/gs.test 357.00 366.00 2.5% test-suite...eeBench/analyzer/analyzer.test 103.00 105.00 1.9% test-suite...T2006/445.gobmk/445.gobmk.test 1697.00 1724.00 1.6% test-suite...006/453.povray/453.povray.test 1812.00 1839.00 1.5% test-suite.../Benchmarks/Bullet/bullet.test 337.00 342.00 1.5% test-suite.../CINT2000/252.eon/252.eon.test 426.00 432.00 1.4% test-suite...T2000/300.twolf/300.twolf.test 214.00 217.00 1.4% test-suite...pplications/oggenc/oggenc.test 244.00 247.00 1.2% test-suite.../CINT2006/403.gcc/403.gcc.test 4008.00 4055.00 1.2% test-suite...T2006/456.hmmer/456.hmmer.test 175.00 177.00 1.1% test-suite...nal/skidmarks10/skidmarks.test 430.00 434.00 0.9% test-suite.../Applications/sgefa/sgefa.test 115.00 116.00 0.9% test-suite...006/447.dealII/447.dealII.test 1082.00 1091.00 0.8% test-suite...6/482.sphinx3/482.sphinx3.test 141.00 142.00 0.7% test-suite...ocBench/espresso/espresso.test 152.00 153.00 0.7% test-suite...3.xalancbmk/483.xalancbmk.test 4003.00 4025.00 0.5% test-suite...lications/sqlite3/sqlite3.test 548.00 551.00 0.5% test-suite...marks/7zip/7zip-benchmark.test 5522.00 5551.00 0.5% test-suite...nsumer-lame/consumer-lame.test 208.00 209.00 0.5% test-suite...:: External/Povray/povray.test 1556.00 1563.00 0.4% test-suite...000/186.crafty/186.crafty.test 298.00 299.00 0.3% test-suite.../Applications/SPASS/SPASS.test 2019.00 2025.00 0.3% test-suite...ications/JM/lencod/lencod.test 8427.00 8449.00 0.3% test-suite...6/464.h264ref/464.h264ref.test 6797.00 6813.00 0.2% test-suite...6/471.omnetpp/471.omnetpp.test 431.00 430.00 -0.2% test-suite...006/450.soplex/450.soplex.test 446.00 447.00 0.2% test-suite...0.perlbench/400.perlbench.test 1729.00 1727.00 -0.1% test-suite...000/255.vortex/255.vortex.test 3815.00 3819.00 0.1% Reviewers: efriedma, nikic, davide Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D79036
243 lines
6.8 KiB
LLVM
243 lines
6.8 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -ipsccp -S | FileCheck %s
|
|
|
|
define internal i32 @test1a(i32 %A, i32 %b) {
|
|
; CHECK-LABEL: @test1a(
|
|
; CHECK-NEXT: [[X:%.*]] = add i32 [[A:%.*]], 1
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X]], [[B:%.*]]
|
|
; CHECK-NEXT: br i1 [[C]], label [[BB_TRUE:%.*]], label [[BB_FALSE:%.*]]
|
|
; CHECK: bb.true:
|
|
; CHECK-NEXT: [[R:%.*]] = call i32 @test1a(i32 [[X]], i32 [[B]])
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
; CHECK: bb.false:
|
|
; CHECK-NEXT: ret i32 [[A]]
|
|
;
|
|
%X = add i32 %A, 1
|
|
%c = icmp eq i32 %X, %b
|
|
br i1 %c, label %bb.true, label %bb.false
|
|
|
|
bb.true:
|
|
%r = call i32 @test1a(i32 %X, i32 %b)
|
|
ret i32 %r
|
|
|
|
bb.false:
|
|
ret i32 %A
|
|
}
|
|
|
|
define i32 @test1b(i32 %b) {
|
|
; CHECK-LABEL: @test1b(
|
|
; CHECK-NEXT: [[X:%.*]] = call i32 @test1a(i32 17, i32 [[B:%.*]])
|
|
; CHECK-NEXT: ret i32 [[X]]
|
|
;
|
|
%X = call i32 @test1a( i32 17, i32 %b)
|
|
ret i32 %X
|
|
}
|
|
|
|
@Getopt.optind = internal global i32 1, align 4
|
|
|
|
define i32 @test2(i32 %a) {
|
|
; CHECK-LABEL: @test2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[LV:%.*]] = load i32, i32* @Getopt.optind, align 4
|
|
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[LV]], 1
|
|
; CHECK-NEXT: store i32 [[ADD]], i32* @Getopt.optind, align 4
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[ADD]], [[A:%.*]]
|
|
; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret i32 [[ADD]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%lv = load i32, i32* @Getopt.optind, align 4
|
|
%add = add i32 %lv, 1
|
|
store i32 %add, i32* @Getopt.optind
|
|
%c = icmp eq i32 %add, %a
|
|
br i1 %c, label %exit, label %loop
|
|
|
|
exit:
|
|
ret i32 %add
|
|
}
|
|
|
|
|
|
define internal i32 @test3a(i32 %a) {
|
|
; CHECK-LABEL: @test3a(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[RES:%.*]] = add i32 [[A:%.*]], 1
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[RES]], 1000
|
|
; CHECK-NEXT: br i1 [[C]], label [[BB_TRUE:%.*]], label [[BB_FALSE:%.*]]
|
|
; CHECK: bb.true:
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
; CHECK: bb.false:
|
|
; CHECK-NEXT: ret i32 0
|
|
;
|
|
entry:
|
|
%res = add i32 %a, 1
|
|
%c = icmp ult i32 %res, 1000
|
|
br i1 %c, label %bb.true, label %bb.false
|
|
|
|
bb.true:
|
|
ret i32 %res
|
|
|
|
bb.false:
|
|
ret i32 0
|
|
}
|
|
|
|
define i32 @test3b(i32 %a) {
|
|
; CHECK-LABEL: @test3b(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[V1:%.*]] = call i32 @test3a(i32 0)
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[V2:%.*]] = call i32 @test3a(i32 [[V1]])
|
|
; CHECK-NEXT: [[V3:%.*]] = add i32 [[V2]], 1
|
|
; CHECK-NEXT: [[V4:%.*]] = call i32 @test3a(i32 [[V3]])
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[V4]], [[A:%.*]]
|
|
; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret i32 [[V4]]
|
|
;
|
|
entry:
|
|
%v1 = call i32 @test3a(i32 0)
|
|
br label %loop
|
|
|
|
loop:
|
|
%v2 = call i32 @test3a(i32 %v1)
|
|
%v3 = add i32 %v2, 1
|
|
%v4 = call i32 @test3a(i32 %v3)
|
|
%c = icmp eq i32 %v4, %a
|
|
br i1 %c, label %exit, label %loop
|
|
|
|
exit:
|
|
ret i32 %v4
|
|
}
|
|
|
|
%struct.S = type { i32, i32 }
|
|
|
|
; Check for a range extension cycle through a struct argument.
|
|
define internal i32 @test4a(%struct.S %s) {
|
|
; CHECK-LABEL: @test4a(
|
|
; CHECK-NEXT: [[A:%.*]] = extractvalue [[STRUCT_S:%.*]] %s, 0
|
|
; CHECK-NEXT: [[B:%.*]] = extractvalue [[STRUCT_S]] %s, 1
|
|
; CHECK-NEXT: [[X:%.*]] = add i32 [[A]], 1
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X]], [[B]]
|
|
; CHECK-NEXT: br i1 [[C]], label [[BB_TRUE:%.*]], label [[BB_FALSE:%.*]]
|
|
; CHECK: bb.true:
|
|
; CHECK-NEXT: [[S2:%.*]] = insertvalue [[STRUCT_S]] %s, i32 [[X]], 0
|
|
; CHECK-NEXT: [[R:%.*]] = call i32 @test4a(%struct.S [[S2]])
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
; CHECK: bb.false:
|
|
; CHECK-NEXT: ret i32 [[A]]
|
|
;
|
|
%a = extractvalue %struct.S %s, 0
|
|
%b = extractvalue %struct.S %s, 1
|
|
|
|
%x = add i32 %a, 1
|
|
%c = icmp eq i32 %x, %b
|
|
br i1 %c, label %bb.true, label %bb.false
|
|
|
|
bb.true:
|
|
%s2 = insertvalue %struct.S %s, i32 %x, 0
|
|
%r = call i32 @test4a(%struct.S %s2)
|
|
ret i32 %r
|
|
|
|
bb.false:
|
|
ret i32 %a
|
|
}
|
|
|
|
define i32 @test4b(i32 %b) {
|
|
; CHECK-LABEL: @test4b(
|
|
; CHECK-NEXT: [[S2:%.*]] = insertvalue [[STRUCT_S:%.*]] { i32 17, i32 undef }, i32 [[B:%.*]], 1
|
|
; CHECK-NEXT: [[X:%.*]] = call i32 @test4a(%struct.S [[S2]])
|
|
; CHECK-NEXT: ret i32 [[X]]
|
|
;
|
|
%s1 = insertvalue %struct.S undef, i32 17, 0
|
|
%s2 = insertvalue %struct.S %s1, i32 %b, 1
|
|
%X = call i32 @test4a(%struct.S %s2)
|
|
ret i32 %X
|
|
}
|
|
|
|
; Check for a range extension cycle through a returned value.
|
|
|
|
define internal i32 @test5a(i8* %arg, i32 %arg1, i32 %arg2) {
|
|
; CHECK-LABEL: @test5a(
|
|
; CHECK-NEXT: bb:
|
|
; CHECK-NEXT: [[TMP:%.*]] = icmp eq i8* [[ARG:%.*]], null
|
|
; CHECK-NEXT: br i1 [[TMP]], label [[BB6:%.*]], label [[BB3:%.*]]
|
|
; CHECK: bb3:
|
|
; CHECK-NEXT: [[TMP4:%.*]] = tail call i32 @test5a(i8* [[ARG]], i32 0, i32 -1)
|
|
; CHECK-NEXT: [[TMP5:%.*]] = add nsw i32 [[TMP4]], -1
|
|
; CHECK-NEXT: ret i32 [[TMP5]]
|
|
; CHECK: bb6:
|
|
; CHECK-NEXT: ret i32 0
|
|
;
|
|
bb:
|
|
%tmp = icmp eq i8* %arg, null
|
|
br i1 %tmp, label %bb6, label %bb3
|
|
|
|
bb3: ; preds = %bb
|
|
%tmp4 = tail call i32 @test5a(i8* %arg, i32 %arg1, i32 %arg2)
|
|
%tmp5 = add nsw i32 %tmp4, %arg2
|
|
ret i32 %tmp5
|
|
|
|
bb6: ; preds = %bb
|
|
ret i32 %arg1
|
|
}
|
|
|
|
define void @test5b(i8* %ptr) {
|
|
; CHECK-LABEL: @test5b(
|
|
; CHECK-NEXT: bb:
|
|
; CHECK-NEXT: [[TMP:%.*]] = tail call i32 @test5a(i8* [[PTR:%.*]], i32 0, i32 -1)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
bb:
|
|
%tmp = tail call i32 @test5a(i8* %ptr, i32 0, i32 -1)
|
|
ret void
|
|
}
|
|
|
|
%struct = type { i32, i32 }
|
|
|
|
define internal %struct @test6a(i8* %arg, i32 %arg1, i32 %arg2) {
|
|
; CHECK-LABEL: @test6a(
|
|
; CHECK-NEXT: bb:
|
|
; CHECK-NEXT: [[TMP:%.*]] = icmp eq i8* [[ARG:%.*]], null
|
|
; CHECK-NEXT: br i1 [[TMP]], label [[BB6:%.*]], label [[BB3:%.*]]
|
|
; CHECK: bb3:
|
|
; CHECK-NEXT: [[S1:%.*]] = tail call [[STRUCT:%.*]] @test6a(i8* [[ARG]], i32 0, i32 -1)
|
|
; CHECK-NEXT: [[TMP4:%.*]] = extractvalue [[STRUCT]] %s1, 0
|
|
; CHECK-NEXT: [[TMP5:%.*]] = add nsw i32 [[TMP4]], -1
|
|
; CHECK-NEXT: [[S2:%.*]] = insertvalue [[STRUCT]] %s1, i32 [[TMP5]], 0
|
|
; CHECK-NEXT: ret [[STRUCT]] %s2
|
|
; CHECK: bb6:
|
|
; CHECK-NEXT: ret [[STRUCT]] { i32 0, i32 undef }
|
|
;
|
|
bb:
|
|
%tmp = icmp eq i8* %arg, null
|
|
br i1 %tmp, label %bb6, label %bb3
|
|
|
|
bb3: ; preds = %bb
|
|
%s1 = tail call %struct @test6a(i8* %arg, i32 %arg1, i32 %arg2)
|
|
%tmp4 = extractvalue %struct %s1, 0
|
|
%tmp5 = add nsw i32 %tmp4, %arg2
|
|
%s2 = insertvalue %struct %s1, i32 %tmp5, 0
|
|
ret %struct %s2
|
|
|
|
bb6: ; preds = %bb
|
|
%s3 = insertvalue %struct undef, i32 %arg1, 0
|
|
ret %struct %s3
|
|
}
|
|
|
|
define void @test6b(i8* %ptr) {
|
|
; CHECK-LABEL: @test6b(
|
|
; CHECK-NEXT: bb:
|
|
; CHECK-NEXT: [[TMP:%.*]] = tail call [[STRUCT:%.*]] @test6a(i8* [[PTR:%.*]], i32 0, i32 -1)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
bb:
|
|
%tmp = tail call %struct @test6a(i8* %ptr, i32 0, i32 -1)
|
|
ret void
|
|
}
|