Index: head/devel/llvm60/Makefile =================================================================== --- head/devel/llvm60/Makefile (revision 470039) +++ head/devel/llvm60/Makefile (revision 470040) @@ -1,574 +1,574 @@ # $FreeBSD$ PORTNAME= llvm DISTVERSION= 6.0.0 -PORTREVISION= 3 +PORTREVISION= 4 CATEGORIES= devel lang MASTER_SITES= http://${PRE_}releases.llvm.org/${LLVM_RELEASE}/${RCDIR} PKGNAMESUFFIX= ${LLVM_SUFFIX} DISTNAME= ${PORTNAME}-${DISTVERSION}.src DISTFILES= ${PORTNAME}-${DISTVERSION}.src${EXTRACT_SUFX} MAINTAINER= brooks@FreeBSD.org COMMENT= LLVM and Clang LICENSE= LLVM LICENSE_NAME= LLVM Release License LICENSE_FILE= ${WRKSRC}/LICENSE.TXT LICENSE_PERMS= dist-mirror dist-sell pkg-mirror pkg-sell auto-accept LLVM_RELEASE= ${DISTVERSION:C/rc.*//} LLVM_MAJOR= ${LLVM_RELEASE:C/\.[0-9]$//} LLVM_LIB_VER= ${LLVM_MAJOR:C/\.//} RCDIR= ${DISTVERSION:S/${LLVM_RELEASE}//:C|(rc.*)|\1/|} PRE_= ${DISTVERSION:C/.*rc.*/pre/:N*[0-9]*} LLVM_SUFFIX= ${LLVM_LIB_VER} LLVM_PREFIX= ${PREFIX}/llvm${LLVM_SUFFIX} DOCSDIR= ${PREFIX}/share/doc/${PORTNAME}${LLVM_SUFFIX} DATADIR= ${PREFIX}/share/${PORTNAME}${LLVM_SUFFIX} USES= cmake:outsource compiler:c++11-lib libedit perl5 tar:xz \ shebangfix _USES_PYTHON?= python:2.7,build USES+= ${_USES_PYTHON} USE_LDCONFIG= ${LLVM_PREFIX}/lib SHEBANG_FILES= utils/lit/lit.py utils/llvm-lit/llvm-lit.in SUB_FILES= llvm-wrapper.sh SUB_LIST= LLVM_PREFIX="${LLVM_PREFIX}" LLVM_SUFFIX="${LLVM_SUFFIX}" CMAKE_INSTALL_PREFIX= ${LLVM_PREFIX} CMAKE_ARGS= -DLLVM_BUILD_LLVM_DYLIB=ON -DLLVM_LINK_LLVM_DYLIB=ON CMAKE_ARGS+= -DLLVM_ENABLE_RTTI=ON CMAKE_ARGS+= -DLLVM_DEFAULT_TARGET_TRIPLE=${CONFIGURE_TARGET} CMAKE_ARGS+= -DLLVM_HOST_TRIPLE=${CONFIGURE_TARGET} # Following commit https://github.com/kitware/cmake/commit/956054 # we need to either change the whole man-shuffle below, or simply # redefine CMAKE_INSTALL_MANDIR CMAKE_ARGS+= -DCMAKE_INSTALL_MANDIR:PATH="share/man" OPTIONS_DEFINE= CLANG DOCS EXTRAS LIT LLD LLDB OPTIONS_DEFINE_amd64= COMPILER_RT GOLD OPENMP OPTIONS_DEFINE_i386= COMPILER_RT OPTIONS_DEFAULT= CLANG EXTRAS LIT LLD LLDB OPTIONS_DEFAULT_amd64= COMPILER_RT GOLD OPENMP OPTIONS_DEFAULT_i386= COMPILER_RT OPTIONS_EXCLUDE_FreeBSD_10= LLDB OPENMP OPTIONS_SUB= yes CLANG_DESC= Build clang CLANG_EXTRA_PATCHES= ${PATCHDIR}/clang CLANG_CONFLICTS_INSTALL= clang-devel-3.[1234567]* CLANG_DISTFILES= cfe-${DISTVERSION}.src${EXTRACT_SUFX} CLANG_CMAKE_ON= -DCLANG_DEFAULT_OPENMP_RUNTIME=libomp CLANG_PORTDOCS= clang CLANG_USE= GNOME=libxml2 COMPILER_RT_DESC= Sanitizer libraries COMPILER_RT_DISTFILES= compiler-rt-${DISTVERSION}.src${EXTRACT_SUFX} COMPILER_RT_PLIST_FILES=${_COMPILER_RT_LIBS:S|^|${_CRTLIBDIR}/|} DOCS_BUILD_DEPENDS= sphinx-build:textproc/py-sphinx DOCS_PORTDOCS= llvm DOCS_CMAKE_ON= -DLLVM_ENABLE_SPHINX=ON \ -DSPHINX_WARNINGS_AS_ERRORS=OFF \ -DLLVM_BUILD_DOCS=ON DOCS_PLIST_FILES= ${MAN1SRCS:S|^|man/man1/|:S|.1$|${LLVM_SUFFIX}.1.gz|} EXTRAS_DESC= Extra clang tools EXTRAS_IMPLIES= CLANG EXTRAS_DISTFILES= clang-tools-extra-${DISTVERSION}.src${EXTRACT_SUFX} GOLD_DESC= Build the LLVM Gold plugin for LTO GOLD_CMAKE_ON= -DLLVM_BINUTILS_INCDIR=${LOCALBASE}/include GOLD_BUILD_DEPENDS= ${LOCALBASE}/bin/ld.gold:devel/binutils LIT_DESC= Install lit and FileCheck test tools LIT_VARS= _USES_PYTHON=python:2.7 LLD_DESC= Install lld, the LLVM linker LLD_DISTFILES= lld-${DISTVERSION}.src${EXTRACT_SUFX} LLDB_BUILD_DEPENDS= swig3.0:devel/swig30 LLDB_DESC= Install lldb, the LLVM debugger LLDB_DISTFILES= lldb-${DISTVERSION}.src${EXTRACT_SUFX} LLDB_IMPLIES= CLANG LLDB_VARS= _USES_PYTHON=python:2.7 OPENMP_DESC= Install libomp, the LLVM OpenMP runtime library OPENMP_DISTFILES= openmp-${DISTVERSION}.src${EXTRACT_SUFX} OPENMP_EXTRA_PATCHES= ${PATCHDIR}/openmp .if defined(WITH_DEBUG) CMAKE_BUILD_TYPE= RelWithDebInfo STRIP= .endif _CRTLIBDIR= ${LLVM_PREFIX:S|${PREFIX}/||}/lib/clang/${LLVM_RELEASE}/lib/freebsd # Emulate USE_GITHUB's ${WRKSRC_tag} to reduce diffs to ../llvm-devel .for option in CLANG COMPILER_RT EXTRAS LLD LLDB OPENMP WRKSRC_${option:tl}= ${WRKDIR}/${${option}_DISTFILES:S/${EXTRACT_SUFX}//} .endfor OPTIONS_SUB= yes PLIST_SUB+= LLVM_LIB_VER=${LLVM_LIB_VER} \ LLVM_MAJOR=${LLVM_MAJOR} \ LLVM_RELEASE=${LLVM_RELEASE} \ LLVM_SUFFIX=${LLVM_SUFFIX} COMMANDS= bugpoint \ llc \ lli \ llvm-ar \ llvm-as \ llvm-bcanalyzer \ llvm-cat \ llvm-cfi-verify \ llvm-config \ llvm-cov \ llvm-cvtres \ llvm-diff \ llvm-dis \ llvm-dlltool \ llvm-dwarfdump \ llvm-dwp \ llvm-extract \ llvm-link \ llvm-mc \ llvm-mcmarkup \ llvm-modextract \ llvm-mt \ llvm-nm \ llvm-objcopy \ llvm-objdump \ llvm-opt-report \ llvm-pdbutil \ llvm-profdata \ llvm-ranlib \ llvm-rc \ llvm-readelf \ llvm-readobj \ llvm-rtdyld \ llvm-size \ llvm-split \ llvm-stress \ llvm-strings \ llvm-symbolizer \ llvm-tblgen \ macho-dump \ opt \ sancov FIRST_COMMAND= ${COMMANDS:C/^/XXXX/1:MXXXX*:C/^XXXX//} STRIP_LIBS= BugpointPasses.so \ LLVMHello.so \ ${LIBNAME}.0 \ libLTO.so EXTRAS_COMMANDS+= \ clang-apply-replacements \ clang-change-namespace \ clang-include-fixer \ clang-modernize \ clang-query \ clang-rename \ clang-reorder-fields \ clang-tidy \ clangd \ find-all-symbols \ modularize EXTRAS_LIBS= libclangApplyReplacements \ libclangChangeNamespace \ libclangDaemon \ libclangIncludeFixer \ libclangMove \ libclangQuery \ libclangRename \ libclangReorderFields \ libclangTidy \ libclangTidyGoogleModule \ libclangTidyLLVMModule \ libclangTidyMiscModule \ libclangTidyReadabilityModule \ libclangTidyUtils \ libfindAllSymbols \ libmodernizeCore EXTRAS_PATTERN= ${EXTRAS_COMMANDS:tW:C/ */|/g}|${EXTRAS_LIBS:tW:C/ */|/g} .include # keep in sync with /usr/src/lib/clang/clang.build.mk # ----------- start of sync block ------------------ # Armv6 and armv7 uses hard float abi, unless the CPUTYPE has soft in it. # arm (for armv4 and armv5 CPUs) always uses the soft float ABI. # For all other targets, we stick with 'unknown'. .if ${ARCH:Marmv[67]*} && (!defined(CPUTYPE) || ${CPUTYPE:M*soft*} == "") TARGET_ABI= -gnueabihf .elif ${ARCH:Marm*} TARGET_ABI= -gnueabi .else TARGET_ABI= .endif CONFIGURE_TARGET:=${ARCH:C/amd64/x86_64/:C/arm64/aarch64/}-portbld-${OPSYS:tl}${OSREL}${TARGET_ABI} # ----------- end of sync block -------------------- .if ${PORT_OPTIONS:MCLANG} COMMANDS+= c-index-test \ clang \ clang++ \ clang-check \ clang-cpp \ clang-format \ clang-func-mapping \ clang-import-test \ clang-offload-bundler \ scan-build \ scan-view MAN1SRCS+= clang.1 \ scan-build.1 CLANG_PATTERN= (c-index-test|clang|scan-|Reporter.py|ScanView.py|scanview.css|sorttable.js|startfile.py|-analyzer) SHEBANG_FILES+= tools/clang/tools/scan-view/bin/scan-view \ tools/clang/tools/clang-format/git-clang-format \ tools/clang/tools/clang-format/clang-format-diff.py .endif .if ${PORT_OPTIONS:MCOMPILER_RT} COMPILER_RT_PATTERN= (_blacklist.txt|sanitizer|include.xray) .endif .if ${PORT_OPTIONS:MLIT} MAN1SRCS+= lit.1 FileCheck.1 LIT_COMMANDS= lit llvm-lit FileCheck .endif .if ${PORT_OPTIONS:MLLDB} COMMANDS+= lldb \ lldb-argdumper \ lldb-mi \ lldb-server \ lldb-test .endif .if ! ${OPTIONS_DEFINE:MCOMPILER_RT} # Hack to disable COMPILER_RT in plist of unsupported architectures PLIST_SUB+= COMPILER_RT="@comment " .else .endif .if ! ${OPTIONS_DEFINE:MGOLD} # Hack to disable GOLD in plist of unsupported architectures PLIST_SUB+= GOLD="@comment " .else .endif .if ! ${OPTIONS_DEFINE:MOPENMP} # Hack to disable OPENMP in plist of unsupported architectures PLIST_SUB+= OPENMP="@comment " .else .endif MAN1SRCS+= bugpoint.1 dsymutil.1 llc.1 lli.1 llvm-ar.1 llvm-as.1 \ llvm-bcanalyzer.1 llvm-build.1 llvm-config.1 llvm-cov.1 \ llvm-diff.1 llvm-dis.1 llvm-dwarfdump.1 \ llvm-extract.1 llvm-lib.1 llvm-link.1 llvm-nm.1 \ llvm-pdbutil.1 \ llvm-profdata.1 llvm-readobj.1 llvm-stress.1 llvm-symbolizer.1 \ opt.1 tblgen.1 .include .if ${ARCH} == "amd64" _COMPILER_RT_LIBS= \ libclang_rt.asan-preinit-x86_64.a \ libclang_rt.asan-x86_64.a \ libclang_rt.asan-x86_64.a.syms \ libclang_rt.asan-x86_64.so \ libclang_rt.asan_cxx-x86_64.a \ libclang_rt.asan_cxx-x86_64.a.syms \ libclang_rt.builtins-x86_64.a \ libclang_rt.dd-x86_64.a \ libclang_rt.dyndd-x86_64.so \ libclang_rt.lsan-x86_64.a \ libclang_rt.profile-x86_64.a \ libclang_rt.safestack-x86_64.a \ libclang_rt.stats-x86_64.a \ libclang_rt.stats_client-x86_64.a \ libclang_rt.tsan-x86_64.a \ libclang_rt.tsan-x86_64.a.syms \ libclang_rt.tsan_cxx-x86_64.a \ libclang_rt.tsan_cxx-x86_64.a.syms \ libclang_rt.ubsan_minimal-x86_64.a \ libclang_rt.ubsan_minimal-x86_64.a.syms \ libclang_rt.ubsan_minimal-x86_64.so \ libclang_rt.ubsan_standalone-x86_64.a \ libclang_rt.ubsan_standalone-x86_64.a.syms \ libclang_rt.ubsan_standalone-x86_64.so \ libclang_rt.ubsan_standalone_cxx-x86_64.a \ libclang_rt.ubsan_standalone_cxx-x86_64.a.syms .endif .if ${ARCH} == "i386" _COMPILER_RT_LIBS+= \ libclang_rt.asan-i386.a \ libclang_rt.asan-i386.so \ libclang_rt.asan-preinit-i386.a \ libclang_rt.asan_cxx-i386.a \ libclang_rt.builtins-i386.a \ libclang_rt.lsan-i386.a \ libclang_rt.profile-i386.a \ libclang_rt.safestack-i386.a \ libclang_rt.stats-i386.a \ libclang_rt.stats_client-i386.a \ libclang_rt.ubsan_minimal-i386.a \ libclang_rt.ubsan_minimal-i386.so \ libclang_rt.ubsan_standalone-i386.a \ libclang_rt.ubsan_standalone-i386.so \ libclang_rt.ubsan_standalone_cxx-i386.a .endif .if ${PORT_OPTIONS:MEXTRAS} COMMANDS+= ${EXTRAS_COMMANDS} MAN1SRCS+= extraclangtools.1 PORTDOCS+= clang-tools SHEBANG_FILES+= tools/clang/tools/extra/clang-tidy/tool/clang-tidy-diff.py \ tools/clang/tools/extra/clang-tidy/tool/run-clang-tidy.py \ tools/clang/tools/extra/include-fixer/find-all-symbols/tool/run-find-all-symbols.py .endif .if ${PORT_OPTIONS:MLLD} COMMANDS+= ld.lld \ ld64.lld \ lld \ lld-link \ wasm-ld PORTDOCS+= lld .endif .if ${OPSYS} == "FreeBSD" && ${COMPILER_TYPE} != clang CXXFLAGS+= -D_GLIBCXX_USE_C99 .endif .if ${ARCH} == "armv6" || ${ARCH} == "armv7" BUILD_DEPENDS+= ${LOCALBASE}/bin/ld:devel/binutils CONFIGURE_ENV+= COMPILER_PATH=${LOCALBASE}/bin MAKE_ENV+= COMPILER_PATH=${LOCALBASE}/bin .endif .if ${PYTHON_REL} < 3400 LLDB_BUILD_DEPENDS+= \ ${PYTHON_PKGNAMEPREFIX}enum34>0:devel/py-enum34 .endif post-extract-CLANG-on: ${MV} ${WRKSRC_clang} ${PATCH_WRKSRC}/tools/clang post-extract-EXTRAS-on: ${MV} ${WRKSRC_extras} ${PATCH_WRKSRC}/tools/clang/tools/extra post-extract-LLD-on: ${MV} ${WRKSRC_lld} ${PATCH_WRKSRC}/tools/lld post-extract-LLDB-on: ${MV} ${WRKSRC_lldb} ${PATCH_WRKSRC}/tools/lldb post-extract-OPENMP-on: ${MV} ${WRKSRC_openmp} ${PATCH_WRKSRC}/projects/openmp post-patch: ${REINPLACE_CMD} -e 's|import lit|import lit${LLVM_SUFFIX}|' \ -e 's|from lit|from lit${LLVM_SUFFIX}|' \ -e 's|lit\.|lit${LLVM_SUFFIX}.|' \ ${WRKSRC}/utils/lit/lit.py ${WRKSRC}/utils/lit/lit/*.py \ ${WRKSRC}/utils/lit/lit/formats/*.py ${REINPLACE_CMD} -e 's,/usr/local/,${LOCALBASE}/,' \ ${WRKSRC}/CMakeLists.txt post-patch-CLANG-on: ${REINPLACE_CMD} -e 's|%%LLVM_PREFIX%%|${LLVM_PREFIX}|' \ ${PATCH_WRKSRC}/tools/clang/lib/Driver/ToolChains/CommonArgs.cpp ${REINPLACE_CMD} -e 's|%%LLVM_SUFFIX%%|${LLVM_SUFFIX}|' \ ${PATCH_WRKSRC}/tools/clang/tools/clang-format/clang-format.py \ ${PATCH_WRKSRC}/tools/clang/tools/clang-format/clang-format-sublime.py \ ${PATCH_WRKSRC}/tools/clang/tools/clang-format/git-clang-format post-build-COMPILER_RT-on: ${MKDIR} ${WRKDIR}/compiler-rt-build cd ${WRKDIR}/compiler-rt-build && \ ${SETENV} ${CONFIGURE_ENV} ${CMAKE_BIN} ${CMAKE_ARGS} \ -DLLVM_CONFIG_PATH=${CONFIGURE_WRKSRC}/bin/llvm-config \ ${WRKSRC_compiler_rt} && \ ${MAKE_ENV} ${MAKE_CMD} post-install: ${RM} -r ${STAGEDIR}${LLVM_PREFIX}/include/llvm/MC/MCAnalysis ${INSTALL_SCRIPT} ${WRKDIR}/llvm-wrapper.sh \ ${STAGEDIR}${PREFIX}/bin/${FIRST_COMMAND}${LLVM_SUFFIX} .for command in ${COMMANDS:C/^/XXXX/1:NXXXX*} ${LN} -f ${STAGEDIR}${PREFIX}/bin/${FIRST_COMMAND}${LLVM_SUFFIX} \ ${STAGEDIR}${PREFIX}/bin/${command}${LLVM_SUFFIX} .endfor post-install-DOCS-on: ${MV} ${STAGEDIR}${LLVM_PREFIX}/share/doc ${STAGEDIR}${DOCSDIR} .for _man in ${MAN1SRCS} ${MV} ${STAGEDIR}${LLVM_PREFIX}/share/man/man1/${_man} \ ${STAGEDIR}${MANPREFIX}/man/man1/${_man:R}${LLVM_SUFFIX}.1 .endfor .if ! ${PORT_OPTIONS:MLIT} ${RM} ${STAGEDIR}${LLVM_PREFIX}/share/man/man1/lit.1 ${RM} ${STAGEDIR}${LLVM_PREFIX}/share/man/man1/FileCheck.1 .endif ${RMDIR} ${STAGEDIR}${LLVM_PREFIX}/share/man/man1/ ${RMDIR} ${STAGEDIR}${LLVM_PREFIX}/share/man/ .if ${PORT_OPTIONS:MCLANG} post-install-DOCS-off: ${RM} ${STAGEDIR}${LLVM_PREFIX}/share/man/man1/scan-build.1 ${RMDIR} ${STAGEDIR}${LLVM_PREFIX}/share/man/man1/ ${RMDIR} ${STAGEDIR}${LLVM_PREFIX}/share/man/ .endif post-install-LLD-on: ${RMDIR} ${STAGEDIR}${LLVM_PREFIX}/include/llvm/BinaryFormat/WasmRelocs post-install-LLDB-on: ${RMDIR} ${STAGEDIR}${LLVM_PREFIX}/include/lldb/API ${RMDIR} ${STAGEDIR}${LLVM_PREFIX}/include/lldb/Host/windows/getopt ${RMDIR} ${STAGEDIR}${LLVM_PREFIX}/include/lldb/Host/mingw ${RMDIR} ${STAGEDIR}${LLVM_PREFIX}/include/lldb/Host/msvc post-install-CLANG-on: ${LN} -f ${STAGEDIR}${LLVM_PREFIX}/bin/clang \ ${STAGEDIR}${LLVM_PREFIX}/bin/clang-cpp ${INSTALL_PROGRAM} ${WRKDIR}/.build/bin/clang-tblgen \ ${STAGEDIR}${LLVM_PREFIX}/bin/ post-install-COMPILER_RT-on: cd ${WRKDIR}/compiler-rt-build && \ ${MAKE_ENV} ${MAKE_CMD} ${INSTALL_TARGET} .if ${ARCH} == "amd64" ${RM} ${STAGEDIR}${LLVM_PREFIX}/lib/freebsd/libclang_rt*i386* .endif ${MKDIR} ${STAGEDIR}${PREFIX}/${_CRTLIBDIR} ${MV} ${STAGEDIR}${LLVM_PREFIX}/lib/freebsd/* \ ${STAGEDIR}${PREFIX}/${_CRTLIBDIR} ${RMDIR} ${STAGEDIR}${LLVM_PREFIX}/lib/freebsd post-install-LIT-on: ${INSTALL_SCRIPT} ${PATCH_WRKSRC}/utils/lit/lit.py \ ${STAGEDIR}${LLVM_PREFIX}/bin/lit ${LN} -f ${STAGEDIR}${LLVM_PREFIX}/bin/lit \ ${STAGEDIR}${LLVM_PREFIX}/bin/llvm-lit ${LN} -f ${STAGEDIR}${LLVM_PREFIX}/bin/lit \ ${STAGEDIR}${PREFIX}/bin/lit${LLVM_SUFFIX} ${LN} -f ${STAGEDIR}${LLVM_PREFIX}/bin/lit \ ${STAGEDIR}${PREFIX}/bin/llvm-lit${LLVM_SUFFIX} ${MKDIR} ${STAGEDIR}${PYTHONPREFIX_SITELIBDIR}/lit${LLVM_SUFFIX} ${MKDIR} ${STAGEDIR}${PYTHONPREFIX_SITELIBDIR}/lit${LLVM_SUFFIX}/formats ${INSTALL_DATA} ${WRKSRC}/utils/lit/lit/*.py \ ${STAGEDIR}${PYTHONPREFIX_SITELIBDIR}/lit${LLVM_SUFFIX} ${INSTALL_DATA} ${WRKSRC}/utils/lit/lit/formats/*.py \ ${STAGEDIR}${PYTHONPREFIX_SITELIBDIR}/lit${LLVM_SUFFIX}/formats ${INSTALL_PROGRAM} ${WRKDIR}/.build/bin/FileCheck \ ${STAGEDIR}${LLVM_PREFIX}/bin/ ${LN} -f ${STAGEDIR}${LLVM_PREFIX}/bin/FileCheck \ ${STAGEDIR}${PREFIX}/bin/FileCheck${LLVM_SUFFIX} TEST_CMD= '(cd ${WRKSRC}/test; ${SETENV} ${MAKE_ENV} LD_LIBRARY_PATH=${WRKSRC}/Release/lib ${MAKE_CMD} check-local-lit)' regression-test: ${BUILD_COOKIE} if [ `${ID} -u` = 0 ]; then \ ${CHOWN} -R nobody ${WRKSRC}/test; \ su -m nobody -c ${TEST_CMD}; \ else \ ${SH} -c ${TEST_CMD}; \ fi build-plist: ${RM} ${PLIST} ${PLIST}.tmp ${ECHO_CMD} "@comment >>>>> GENERATED FILE, DO NOT EDIT <<<<<" >> ${PLIST}.tmp ${ECHO_CMD} "@comment Alter build-plist target and regenerate as required" >> ${PLIST}.tmp .for command in ${COMMANDS} ${ECHO_CMD} bin/${command}%%LLVM_SUFFIX%% >> ${PLIST}.tmp .endfor .for command in ${LIT_COMMANDS} ${ECHO_CMD} %%LIT%%bin/${command}%%LLVM_SUFFIX%% >> ${PLIST}.tmp ${ECHO_CMD} %%LIT%%${LLVM_PREFIX:S|${PREFIX}/||:C|${LLVM_SUFFIX}|%%LLVM_SUFFIX%%|}/bin/${command} >> ${PLIST}.tmp .endfor ${FIND} ${STAGEDIR}${LLVM_PREFIX} -type f -o -type l | \ ${GREP} -v '[/-]lit$$' | ${GREP} -v 'FileCheck$$' | \ ${GREP} -v man/man1 | ${SED} -e 's|${STAGEDIR}${PREFIX}/||' \ -e 's|${PYTHON_SITELIBDIR:C|${PREFIX}/||}|%%PYTHON_SITELIBDIR%%|' \ -e 's|${LLVM_RELEASE}|%%LLVM_RELEASE%%|' \ -e 's|release.cmake|%%CMAKE_BUILD_TYPE%%.cmake|' \ -e 's|${LLVM_RELEASE:C/\./\\./g}|%%LLVM_RELEASE%%|' \ -e 's|${LLVM_MAJOR:C/\./\\./}|%%LLVM_MAJOR%%|' \ -e 's|${LLVM_MAJOR:C/\.//}|%%LLVM_LIB_VER%%|' \ | ${SORT} >> ${PLIST}.tmp ${FIND} ${STAGEDIR}${PYTHON_SITELIBDIR}/lit${LLVM_SUFFIX} -type f | \ ${SED} -e 's|${STAGEDIR}${PYTHON_SITELIBDIR}|%%LIT%%%%PYTHON_SITELIBDIR%%|' \ -e 's|${LLVM_RELEASE:C/\./\\./g}|%%LLVM_RELEASE%%|' \ -e 's|${LLVM_MAJOR:C/\./\\./}|%%LLVM_MAJOR%%|' \ -e 's|lit${LLVM_SUFFIX}|lit%%LLVM_SUFFIX%%|' | \ ${SORT} >> ${PLIST}.tmp ${AWK} '{ \ if ($$0 ~ /${CLANG_PATTERN}/ && $$0 !~ /(omp.h|ompt.h|${EXTRAS_PATTERN}|libclang_rt)/) {printf "%%%%CLANG%%%%"} \ if ($$0 ~ /${COMPILER_RT_PATTERN}/) \ {printf "%%%%COMPILER_RT%%%%"} \ if ($$0 ~ /(${EXTRAS_PATTERN})/) {printf "%%%%EXTRAS%%%%"} \ if ($$0 ~ /lld|wasm-ld/ && $$0 !~ /lldb/) {printf "%%%%LLD%%%%"} \ if ($$0 ~ /(argdumper|lldb|six.py)/) {printf "%%%%LLDB%%%%"} \ if ($$0 ~ /lib.*omp|omp.h|ompt.h/) {printf "%%%%OPENMP%%%%"} \ if ($$0 ~ /LLVMgold/) {printf "%%%%GOLD%%%%"} \ if ($$0 !~ /libclang_rt/) {print}}' ${PLIST}.tmp >> ${PLIST} ${ECHO_CMD} '@postexec if type ccache-update-links >/dev/null 2>&1; then ccache-update-links -v; fi' >> ${PLIST} ${ECHO_CMD} '@postunexec if type ccache-update-links >/dev/null 2>&1; then ccache-update-links -v; fi' >> ${PLIST} ${RM} ${PLIST}.tmp check-commands: .for command in ${COMMANDS} test -e ${STAGEDIR}${LLVM_PREFIX}/bin/${command} .endfor .if make(svn-patch-llvm) .if !defined(PATCH_REV) .error svn-patch-llvm requires that PATCH_REV be set .endif _PATCH_FILE=${FILESDIR}/patch-svn-${PATCH_REV} _LLVM_BASE=http://llvm.org/svn/llvm-project/llvm/trunk svn-patch-llvm: svn log -c ${PATCH_REV} ${_LLVM_BASE} >> ${_PATCH_FILE} svn diff -c ${PATCH_REV} ${_LLVM_BASE} >> ${_PATCH_FILE} .endif .if make(svn-patch-clang) .if !defined(PATCH_REV) .error svn-patch-clang requires that PATCH_REV be set .endif _PATCH_FILE=${FILESDIR}/clang/patch-svn-${PATCH_REV} _LLVM_BASE=http://llvm.org/svn/llvm-project/cfe/trunk svn-patch-clang: svn log -c ${PATCH_REV} ${_LLVM_BASE} >> ${_PATCH_FILE} svn diff -c ${PATCH_REV} ${_LLVM_BASE} | \ ${SED} -E -e 's;^(---|\+\+\+) ;\1 tools/clang/;' >> ${_PATCH_FILE} .endif .if make(svn-patch-compiler-rt) .if !defined(PATCH_REV) .error svn-patch-compiler-rt requires that PATCH_REV be set .endif _PATCH_FILE=${FILESDIR}/compiler-rt/patch-svn-${PATCH_REV} _LLVM_BASE=http://llvm.org/svn/llvm-project/compiler-rt/trunk svn-patch-compiler-rt: svn log -c ${PATCH_REV} ${_LLVM_BASE} >> ${_PATCH_FILE} svn diff -c ${PATCH_REV} ${_LLVM_BASE} | \ ${SED} -E -e 's;^(---|\+\+\+) ;\1 tools/compiler-rt/;' >> ${_PATCH_FILE} .endif .if make(svn-patch-lldb) .if !defined(PATCH_REV) .error svn-patch-lldb requires that PATCH_REV be set .endif _PATCH_FILE=${FILESDIR}/lldb/patch-svn-${PATCH_REV} _LLVM_BASE=http://llvm.org/svn/llvm-project/lldb/trunk svn-patch-lldb: svn log -c ${PATCH_REV} ${_LLVM_BASE} >> ${_PATCH_FILE} svn diff -c ${PATCH_REV} ${_LLVM_BASE} | >> ${_PATCH_FILE} .endif .include Index: head/devel/llvm60/files/patch-svn-r322325 =================================================================== --- head/devel/llvm60/files/patch-svn-r322325 (nonexistent) +++ head/devel/llvm60/files/patch-svn-r322325 (revision 470040) @@ -0,0 +1,1589 @@ +r322325: + +PeepholeOpt cleanup/refactor; NFC + +- Less unnecessary use of `auto` +- Add early `using RegSubRegPair(AndIdx) =` to avoid countless + `TargetInstrInfo::` qualifications. +- Use references instead of pointers where possible. +- Remove unused parameters. +- Rewrite the CopyRewriter class hierarchy: + - Pull out uncoalescable copy rewriting functionality into + PeepholeOptimizer class. + - Use an abstract base class to make it clear that rewriters are + independent. +- Remove unnecessary \brief in doxygen comments. +- Remove unused constructor and method from ValueTracker. +- Replace UseAdvancedTracking of ValueTracker with DisableAdvCopyOpt use. + +--- lib/CodeGen/PeepholeOptimizer.cpp.orig ++++ lib/CodeGen/PeepholeOptimizer.cpp +@@ -98,6 +98,8 @@ + #include + + using namespace llvm; ++using RegSubRegPair = TargetInstrInfo::RegSubRegPair; ++using RegSubRegPairAndIdx = TargetInstrInfo::RegSubRegPairAndIdx; + + #define DEBUG_TYPE "peephole-opt" + +@@ -110,6 +112,9 @@ + DisablePeephole("disable-peephole", cl::Hidden, cl::init(false), + cl::desc("Disable the peephole optimizer")); + ++/// Specifiy whether or not the value tracking looks through ++/// complex instructions. When this is true, the value tracker ++/// bails on everything that is not a copy or a bitcast. + static cl::opt + DisableAdvCopyOpt("disable-adv-copy-opt", cl::Hidden, cl::init(false), + cl::desc("Disable advanced copy optimization")); +@@ -132,11 +137,11 @@ + "of commuting operands")); + + +-STATISTIC(NumReuse, "Number of extension results reused"); +-STATISTIC(NumCmps, "Number of compares eliminated"); +-STATISTIC(NumImmFold, "Number of move immediate folded"); +-STATISTIC(NumLoadFold, "Number of loads folded"); +-STATISTIC(NumSelects, "Number of selects optimized"); ++STATISTIC(NumReuse, "Number of extension results reused"); ++STATISTIC(NumCmps, "Number of compares eliminated"); ++STATISTIC(NumImmFold, "Number of move immediate folded"); ++STATISTIC(NumLoadFold, "Number of loads folded"); ++STATISTIC(NumSelects, "Number of selects optimized"); + STATISTIC(NumUncoalescableCopies, "Number of uncoalescable copies optimized"); + STATISTIC(NumRewrittenCopies, "Number of copies rewritten"); + STATISTIC(NumNAPhysCopies, "Number of non-allocatable physical copies removed"); +@@ -149,9 +154,9 @@ + class PeepholeOptimizer : public MachineFunctionPass { + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; +- MachineRegisterInfo *MRI; +- MachineDominatorTree *DT; // Machine dominator tree +- MachineLoopInfo *MLI; ++ MachineRegisterInfo *MRI; ++ MachineDominatorTree *DT; // Machine dominator tree ++ MachineLoopInfo *MLI; + + public: + static char ID; // Pass identification +@@ -173,31 +178,28 @@ + } + } + +- /// \brief Track Def -> Use info used for rewriting copies. +- using RewriteMapTy = +- SmallDenseMap; ++ /// Track Def -> Use info used for rewriting copies. ++ using RewriteMapTy = SmallDenseMap; + +- /// \brief Sequence of instructions that formulate recurrence cycle. ++ /// Sequence of instructions that formulate recurrence cycle. + using RecurrenceCycle = SmallVector; + + private: +- bool optimizeCmpInstr(MachineInstr *MI, MachineBasicBlock *MBB); +- bool optimizeExtInstr(MachineInstr *MI, MachineBasicBlock *MBB, ++ bool optimizeCmpInstr(MachineInstr &MI); ++ bool optimizeExtInstr(MachineInstr &MI, MachineBasicBlock &MBB, + SmallPtrSetImpl &LocalMIs); +- bool optimizeSelect(MachineInstr *MI, ++ bool optimizeSelect(MachineInstr &MI, + SmallPtrSetImpl &LocalMIs); +- bool optimizeCondBranch(MachineInstr *MI); +- bool optimizeCoalescableCopy(MachineInstr *MI); +- bool optimizeUncoalescableCopy(MachineInstr *MI, ++ bool optimizeCondBranch(MachineInstr &MI); ++ bool optimizeCoalescableCopy(MachineInstr &MI); ++ bool optimizeUncoalescableCopy(MachineInstr &MI, + SmallPtrSetImpl &LocalMIs); + bool optimizeRecurrence(MachineInstr &PHI); +- bool findNextSource(unsigned Reg, unsigned SubReg, +- RewriteMapTy &RewriteMap); +- bool isMoveImmediate(MachineInstr *MI, ++ bool findNextSource(RegSubRegPair RegSubReg, RewriteMapTy &RewriteMap); ++ bool isMoveImmediate(MachineInstr &MI, + SmallSet &ImmDefRegs, + DenseMap &ImmDefMIs); +- bool foldImmediate(MachineInstr *MI, MachineBasicBlock *MBB, +- SmallSet &ImmDefRegs, ++ bool foldImmediate(MachineInstr &MI, SmallSet &ImmDefRegs, + DenseMap &ImmDefMIs); + + /// \brief Finds recurrence cycles, but only ones that formulated around +@@ -212,11 +214,11 @@ + /// the set \p CopySrcRegs and \p CopyMIs. If this virtual register was + /// previously seen as a copy, replace the uses of this copy with the + /// previously seen copy's destination register. +- bool foldRedundantCopy(MachineInstr *MI, ++ bool foldRedundantCopy(MachineInstr &MI, + SmallSet &CopySrcRegs, + DenseMap &CopyMIs); + +- /// \brief Is the register \p Reg a non-allocatable physical register? ++ /// Is the register \p Reg a non-allocatable physical register? + bool isNAPhysCopy(unsigned Reg); + + /// \brief If copy instruction \p MI is a non-allocatable virtual<->physical +@@ -224,11 +226,10 @@ + /// non-allocatable physical register was previously copied to a virtual + /// registered and hasn't been clobbered, the virt->phys copy can be + /// deleted. +- bool foldRedundantNAPhysCopy( +- MachineInstr *MI, ++ bool foldRedundantNAPhysCopy(MachineInstr &MI, + DenseMap &NAPhysToVirtMIs); + +- bool isLoadFoldable(MachineInstr *MI, ++ bool isLoadFoldable(MachineInstr &MI, + SmallSet &FoldAsLoadDefCandidates); + + /// \brief Check whether \p MI is understood by the register coalescer +@@ -249,10 +250,13 @@ + (MI.isRegSequenceLike() || MI.isInsertSubregLike() || + MI.isExtractSubregLike())); + } ++ ++ MachineInstr &rewriteSource(MachineInstr &CopyLike, ++ RegSubRegPair Def, RewriteMapTy &RewriteMap); + }; + +- /// \brief Helper class to hold instructions that are inside recurrence +- /// cycles. The recurrence cycle is formulated around 1) a def operand and its ++ /// Helper class to hold instructions that are inside recurrence cycles. ++ /// The recurrence cycle is formulated around 1) a def operand and its + /// tied use operand, or 2) a def operand and a use operand that is commutable + /// with another use operand which is tied to the def operand. In the latter + /// case, index of the tied use operand and the commutable use operand are +@@ -273,13 +277,13 @@ + Optional CommutePair; + }; + +- /// \brief Helper class to hold a reply for ValueTracker queries. Contains the +- /// returned sources for a given search and the instructions where the sources +- /// were tracked from. ++ /// Helper class to hold a reply for ValueTracker queries. ++ /// Contains the returned sources for a given search and the instructions ++ /// where the sources were tracked from. + class ValueTrackerResult { + private: + /// Track all sources found by one ValueTracker query. +- SmallVector RegSrcs; ++ SmallVector RegSrcs; + + /// Instruction using the sources in 'RegSrcs'. + const MachineInstr *Inst = nullptr; +@@ -302,16 +306,20 @@ + } + + void addSource(unsigned SrcReg, unsigned SrcSubReg) { +- RegSrcs.push_back(TargetInstrInfo::RegSubRegPair(SrcReg, SrcSubReg)); ++ RegSrcs.push_back(RegSubRegPair(SrcReg, SrcSubReg)); + } + + void setSource(int Idx, unsigned SrcReg, unsigned SrcSubReg) { + assert(Idx < getNumSources() && "Reg pair source out of index"); +- RegSrcs[Idx] = TargetInstrInfo::RegSubRegPair(SrcReg, SrcSubReg); ++ RegSrcs[Idx] = RegSubRegPair(SrcReg, SrcSubReg); + } + + int getNumSources() const { return RegSrcs.size(); } + ++ RegSubRegPair getSrc(int Idx) const { ++ return RegSrcs[Idx]; ++ } ++ + unsigned getSrcReg(int Idx) const { + assert(Idx < getNumSources() && "Reg source out of index"); + return RegSrcs[Idx].Reg; +@@ -367,59 +375,41 @@ + /// The register where the value can be found. + unsigned Reg; + +- /// Specifiy whether or not the value tracking looks through +- /// complex instructions. When this is false, the value tracker +- /// bails on everything that is not a copy or a bitcast. +- /// +- /// Note: This could have been implemented as a specialized version of +- /// the ValueTracker class but that would have complicated the code of +- /// the users of this class. +- bool UseAdvancedTracking; +- + /// MachineRegisterInfo used to perform tracking. + const MachineRegisterInfo &MRI; + +- /// Optional TargetInstrInfo used to perform some complex +- /// tracking. ++ /// Optional TargetInstrInfo used to perform some complex tracking. + const TargetInstrInfo *TII; + +- /// \brief Dispatcher to the right underlying implementation of +- /// getNextSource. ++ /// Dispatcher to the right underlying implementation of getNextSource. + ValueTrackerResult getNextSourceImpl(); + +- /// \brief Specialized version of getNextSource for Copy instructions. ++ /// Specialized version of getNextSource for Copy instructions. + ValueTrackerResult getNextSourceFromCopy(); + +- /// \brief Specialized version of getNextSource for Bitcast instructions. ++ /// Specialized version of getNextSource for Bitcast instructions. + ValueTrackerResult getNextSourceFromBitcast(); + +- /// \brief Specialized version of getNextSource for RegSequence +- /// instructions. ++ /// Specialized version of getNextSource for RegSequence instructions. + ValueTrackerResult getNextSourceFromRegSequence(); + +- /// \brief Specialized version of getNextSource for InsertSubreg +- /// instructions. ++ /// Specialized version of getNextSource for InsertSubreg instructions. + ValueTrackerResult getNextSourceFromInsertSubreg(); + +- /// \brief Specialized version of getNextSource for ExtractSubreg +- /// instructions. ++ /// Specialized version of getNextSource for ExtractSubreg instructions. + ValueTrackerResult getNextSourceFromExtractSubreg(); + +- /// \brief Specialized version of getNextSource for SubregToReg +- /// instructions. ++ /// Specialized version of getNextSource for SubregToReg instructions. + ValueTrackerResult getNextSourceFromSubregToReg(); + +- /// \brief Specialized version of getNextSource for PHI instructions. ++ /// Specialized version of getNextSource for PHI instructions. + ValueTrackerResult getNextSourceFromPHI(); + + public: +- /// \brief Create a ValueTracker instance for the value defined by \p Reg. ++ /// Create a ValueTracker instance for the value defined by \p Reg. + /// \p DefSubReg represents the sub register index the value tracker will + /// track. It does not need to match the sub register index used in the + /// definition of \p Reg. +- /// \p UseAdvancedTracking specifies whether or not the value tracker looks +- /// through complex instructions. By default (false), it handles only copy +- /// and bitcast instructions. + /// If \p Reg is a physical register, a value tracker constructed with + /// this constructor will not find any alternative source. + /// Indeed, when \p Reg is a physical register that constructor does not +@@ -427,46 +417,20 @@ + /// Use the next constructor to track a physical register. + ValueTracker(unsigned Reg, unsigned DefSubReg, + const MachineRegisterInfo &MRI, +- bool UseAdvancedTracking = false, + const TargetInstrInfo *TII = nullptr) +- : DefSubReg(DefSubReg), Reg(Reg), +- UseAdvancedTracking(UseAdvancedTracking), MRI(MRI), TII(TII) { ++ : DefSubReg(DefSubReg), Reg(Reg), MRI(MRI), TII(TII) { + if (!TargetRegisterInfo::isPhysicalRegister(Reg)) { + Def = MRI.getVRegDef(Reg); + DefIdx = MRI.def_begin(Reg).getOperandNo(); + } + } + +- /// \brief Create a ValueTracker instance for the value defined by +- /// the pair \p MI, \p DefIdx. +- /// Unlike the other constructor, the value tracker produced by this one +- /// may be able to find a new source when the definition is a physical +- /// register. +- /// This could be useful to rewrite target specific instructions into +- /// generic copy instructions. +- ValueTracker(const MachineInstr &MI, unsigned DefIdx, unsigned DefSubReg, +- const MachineRegisterInfo &MRI, +- bool UseAdvancedTracking = false, +- const TargetInstrInfo *TII = nullptr) +- : Def(&MI), DefIdx(DefIdx), DefSubReg(DefSubReg), +- UseAdvancedTracking(UseAdvancedTracking), MRI(MRI), TII(TII) { +- assert(DefIdx < Def->getDesc().getNumDefs() && +- Def->getOperand(DefIdx).isReg() && "Invalid definition"); +- Reg = Def->getOperand(DefIdx).getReg(); +- } +- + /// \brief Following the use-def chain, get the next available source + /// for the tracked value. + /// \return A ValueTrackerResult containing a set of registers + /// and sub registers with tracked values. A ValueTrackerResult with + /// an empty set of registers means no source was found. + ValueTrackerResult getNextSource(); +- +- /// \brief Get the last register where the initial value can be found. +- /// Initially this is the register of the definition. +- /// Then, after each successful call to getNextSource, this is the +- /// register of the last source. +- unsigned getReg() const { return Reg; } + }; + + } // end anonymous namespace +@@ -476,11 +440,11 @@ + char &llvm::PeepholeOptimizerID = PeepholeOptimizer::ID; + + INITIALIZE_PASS_BEGIN(PeepholeOptimizer, DEBUG_TYPE, +- "Peephole Optimizations", false, false) ++ "Peephole Optimizations", false, false) + INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) + INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) + INITIALIZE_PASS_END(PeepholeOptimizer, DEBUG_TYPE, +- "Peephole Optimizations", false, false) ++ "Peephole Optimizations", false, false) + + /// If instruction is a copy-like instruction, i.e. it reads a single register + /// and writes a single register and it does not modify the source, and if the +@@ -491,10 +455,10 @@ + /// the code. Since this code does not currently share EXTRACTs, just ignore all + /// debug uses. + bool PeepholeOptimizer:: +-optimizeExtInstr(MachineInstr *MI, MachineBasicBlock *MBB, ++optimizeExtInstr(MachineInstr &MI, MachineBasicBlock &MBB, + SmallPtrSetImpl &LocalMIs) { + unsigned SrcReg, DstReg, SubIdx; +- if (!TII->isCoalescableExtInstr(*MI, SrcReg, DstReg, SubIdx)) ++ if (!TII->isCoalescableExtInstr(MI, SrcReg, DstReg, SubIdx)) + return false; + + if (TargetRegisterInfo::isPhysicalRegister(DstReg) || +@@ -535,7 +499,7 @@ + bool ExtendLife = true; + for (MachineOperand &UseMO : MRI->use_nodbg_operands(SrcReg)) { + MachineInstr *UseMI = UseMO.getParent(); +- if (UseMI == MI) ++ if (UseMI == &MI) + continue; + + if (UseMI->isPHI()) { +@@ -568,7 +532,7 @@ + continue; + + MachineBasicBlock *UseMBB = UseMI->getParent(); +- if (UseMBB == MBB) { ++ if (UseMBB == &MBB) { + // Local uses that come after the extension. + if (!LocalMIs.count(UseMI)) + Uses.push_back(&UseMO); +@@ -576,7 +540,7 @@ + // Non-local uses where the result of the extension is used. Always + // replace these unless it's a PHI. + Uses.push_back(&UseMO); +- } else if (Aggressive && DT->dominates(MBB, UseMBB)) { ++ } else if (Aggressive && DT->dominates(&MBB, UseMBB)) { + // We may want to extend the live range of the extension result in order + // to replace these uses. + ExtendedUses.push_back(&UseMO); +@@ -640,19 +604,18 @@ + /// against already sets (or could be modified to set) the same flag as the + /// compare, then we can remove the comparison and use the flag from the + /// previous instruction. +-bool PeepholeOptimizer::optimizeCmpInstr(MachineInstr *MI, +- MachineBasicBlock *MBB) { ++bool PeepholeOptimizer::optimizeCmpInstr(MachineInstr &MI) { + // If this instruction is a comparison against zero and isn't comparing a + // physical register, we can try to optimize it. + unsigned SrcReg, SrcReg2; + int CmpMask, CmpValue; +- if (!TII->analyzeCompare(*MI, SrcReg, SrcReg2, CmpMask, CmpValue) || ++ if (!TII->analyzeCompare(MI, SrcReg, SrcReg2, CmpMask, CmpValue) || + TargetRegisterInfo::isPhysicalRegister(SrcReg) || + (SrcReg2 != 0 && TargetRegisterInfo::isPhysicalRegister(SrcReg2))) + return false; + + // Attempt to optimize the comparison instruction. +- if (TII->optimizeCompareInstr(*MI, SrcReg, SrcReg2, CmpMask, CmpValue, MRI)) { ++ if (TII->optimizeCompareInstr(MI, SrcReg, SrcReg2, CmpMask, CmpValue, MRI)) { + ++NumCmps; + return true; + } +@@ -661,27 +624,26 @@ + } + + /// Optimize a select instruction. +-bool PeepholeOptimizer::optimizeSelect(MachineInstr *MI, ++bool PeepholeOptimizer::optimizeSelect(MachineInstr &MI, + SmallPtrSetImpl &LocalMIs) { + unsigned TrueOp = 0; + unsigned FalseOp = 0; + bool Optimizable = false; + SmallVector Cond; +- if (TII->analyzeSelect(*MI, Cond, TrueOp, FalseOp, Optimizable)) ++ if (TII->analyzeSelect(MI, Cond, TrueOp, FalseOp, Optimizable)) + return false; + if (!Optimizable) + return false; +- if (!TII->optimizeSelect(*MI, LocalMIs)) ++ if (!TII->optimizeSelect(MI, LocalMIs)) + return false; +- MI->eraseFromParent(); ++ MI.eraseFromParent(); + ++NumSelects; + return true; + } + +-/// \brief Check if a simpler conditional branch can be +-/// generated +-bool PeepholeOptimizer::optimizeCondBranch(MachineInstr *MI) { +- return TII->optimizeCondBranch(*MI); ++/// Check if a simpler conditional branch can be generated. ++bool PeepholeOptimizer::optimizeCondBranch(MachineInstr &MI) { ++ return TII->optimizeCondBranch(MI); + } + + /// \brief Try to find the next source that share the same register file +@@ -695,30 +657,29 @@ + /// share the same register file as \p Reg and \p SubReg. The client should + /// then be capable to rewrite all intermediate PHIs to get the next source. + /// \return False if no alternative sources are available. True otherwise. +-bool PeepholeOptimizer::findNextSource(unsigned Reg, unsigned SubReg, ++bool PeepholeOptimizer::findNextSource(RegSubRegPair RegSubReg, + RewriteMapTy &RewriteMap) { + // Do not try to find a new source for a physical register. + // So far we do not have any motivating example for doing that. + // Thus, instead of maintaining untested code, we will revisit that if + // that changes at some point. ++ unsigned Reg = RegSubReg.Reg; + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + return false; + const TargetRegisterClass *DefRC = MRI->getRegClass(Reg); + +- SmallVector SrcToLook; +- TargetInstrInfo::RegSubRegPair CurSrcPair(Reg, SubReg); ++ SmallVector SrcToLook; ++ RegSubRegPair CurSrcPair = RegSubReg; + SrcToLook.push_back(CurSrcPair); + + unsigned PHICount = 0; +- while (!SrcToLook.empty() && PHICount < RewritePHILimit) { +- TargetInstrInfo::RegSubRegPair Pair = SrcToLook.pop_back_val(); ++ do { ++ CurSrcPair = SrcToLook.pop_back_val(); + // As explained above, do not handle physical registers +- if (TargetRegisterInfo::isPhysicalRegister(Pair.Reg)) ++ if (TargetRegisterInfo::isPhysicalRegister(CurSrcPair.Reg)) + return false; + +- CurSrcPair = Pair; +- ValueTracker ValTracker(CurSrcPair.Reg, CurSrcPair.SubReg, *MRI, +- !DisableAdvCopyOpt, TII); ++ ValueTracker ValTracker(CurSrcPair.Reg, CurSrcPair.SubReg, *MRI, TII); + + // Follow the chain of copies until we find a more suitable source, a phi + // or have to abort. +@@ -747,14 +708,17 @@ + unsigned NumSrcs = Res.getNumSources(); + if (NumSrcs > 1) { + PHICount++; ++ if (PHICount >= RewritePHILimit) { ++ DEBUG(dbgs() << "findNextSource: PHI limit reached\n"); ++ return false; ++ } ++ + for (unsigned i = 0; i < NumSrcs; ++i) +- SrcToLook.push_back(TargetInstrInfo::RegSubRegPair( +- Res.getSrcReg(i), Res.getSrcSubReg(i))); ++ SrcToLook.push_back(Res.getSrc(i)); + break; + } + +- CurSrcPair.Reg = Res.getSrcReg(0); +- CurSrcPair.SubReg = Res.getSrcSubReg(0); ++ CurSrcPair = Res.getSrc(0); + // Do not extend the live-ranges of physical registers as they add + // constraints to the register allocator. Moreover, if we want to extend + // the live-range of a physical register, unlike SSA virtual register, +@@ -764,7 +728,8 @@ + + // Keep following the chain if the value isn't any better yet. + const TargetRegisterClass *SrcRC = MRI->getRegClass(CurSrcPair.Reg); +- if (!TRI->shouldRewriteCopySrc(DefRC, SubReg, SrcRC, CurSrcPair.SubReg)) ++ if (!TRI->shouldRewriteCopySrc(DefRC, RegSubReg.SubReg, SrcRC, ++ CurSrcPair.SubReg)) + continue; + + // We currently cannot deal with subreg operands on PHI instructions +@@ -775,7 +740,7 @@ + // We found a suitable source, and are done with this chain. + break; + } +- } ++ } while (!SrcToLook.empty()); + + // If we did not find a more suitable source, there is nothing to optimize. + return CurSrcPair.Reg != Reg; +@@ -786,54 +751,50 @@ + /// successfully traverse a PHI instruction and find suitable sources coming + /// from its edges. By inserting a new PHI, we provide a rewritten PHI def + /// suitable to be used in a new COPY instruction. +-static MachineInstr * +-insertPHI(MachineRegisterInfo *MRI, const TargetInstrInfo *TII, +- const SmallVectorImpl &SrcRegs, +- MachineInstr *OrigPHI) { ++static MachineInstr & ++insertPHI(MachineRegisterInfo &MRI, const TargetInstrInfo &TII, ++ const SmallVectorImpl &SrcRegs, ++ MachineInstr &OrigPHI) { + assert(!SrcRegs.empty() && "No sources to create a PHI instruction?"); + +- const TargetRegisterClass *NewRC = MRI->getRegClass(SrcRegs[0].Reg); ++ const TargetRegisterClass *NewRC = MRI.getRegClass(SrcRegs[0].Reg); + // NewRC is only correct if no subregisters are involved. findNextSource() + // should have rejected those cases already. + assert(SrcRegs[0].SubReg == 0 && "should not have subreg operand"); +- unsigned NewVR = MRI->createVirtualRegister(NewRC); +- MachineBasicBlock *MBB = OrigPHI->getParent(); +- MachineInstrBuilder MIB = BuildMI(*MBB, OrigPHI, OrigPHI->getDebugLoc(), +- TII->get(TargetOpcode::PHI), NewVR); ++ unsigned NewVR = MRI.createVirtualRegister(NewRC); ++ MachineBasicBlock *MBB = OrigPHI.getParent(); ++ MachineInstrBuilder MIB = BuildMI(*MBB, &OrigPHI, OrigPHI.getDebugLoc(), ++ TII.get(TargetOpcode::PHI), NewVR); + + unsigned MBBOpIdx = 2; +- for (auto RegPair : SrcRegs) { ++ for (const RegSubRegPair &RegPair : SrcRegs) { + MIB.addReg(RegPair.Reg, 0, RegPair.SubReg); +- MIB.addMBB(OrigPHI->getOperand(MBBOpIdx).getMBB()); ++ MIB.addMBB(OrigPHI.getOperand(MBBOpIdx).getMBB()); + // Since we're extended the lifetime of RegPair.Reg, clear the + // kill flags to account for that and make RegPair.Reg reaches + // the new PHI. +- MRI->clearKillFlags(RegPair.Reg); ++ MRI.clearKillFlags(RegPair.Reg); + MBBOpIdx += 2; + } + +- return MIB; ++ return *MIB; + } + + namespace { + +-/// \brief Helper class to rewrite the arguments of a copy-like instruction. +-class CopyRewriter { ++/// Interface to query instructions amenable to copy rewriting. ++class Rewriter { + protected: +- /// The copy-like instruction. + MachineInstr &CopyLike; +- +- /// The index of the source being rewritten. +- unsigned CurrentSrcIdx = 0; +- ++ unsigned CurrentSrcIdx = 0; ///< The index of the source being rewritten. + public: +- CopyRewriter(MachineInstr &MI) : CopyLike(MI) {} +- virtual ~CopyRewriter() = default; ++ Rewriter(MachineInstr &CopyLike) : CopyLike(CopyLike) {} ++ virtual ~Rewriter() {} + + /// \brief Get the next rewritable source (SrcReg, SrcSubReg) and +- /// the related value that it affects (TrackReg, TrackSubReg). ++ /// the related value that it affects (DstReg, DstSubReg). + /// A source is considered rewritable if its register class and the +- /// register class of the related TrackReg may not be register ++ /// register class of the related DstReg may not be register + /// coalescer friendly. In other words, given a copy-like instruction + /// not all the arguments may be returned at rewritable source, since + /// some arguments are none to be register coalescer friendly. +@@ -848,137 +809,72 @@ + /// the only source this instruction has: + /// (SrcReg, SrcSubReg) = (src, srcSubIdx). + /// This source defines the whole definition, i.e., +- /// (TrackReg, TrackSubReg) = (dst, dstSubIdx). ++ /// (DstReg, DstSubReg) = (dst, dstSubIdx). + /// + /// The second and subsequent calls will return false, as there is only one + /// rewritable source. + /// + /// \return True if a rewritable source has been found, false otherwise. + /// The output arguments are valid if and only if true is returned. +- virtual bool getNextRewritableSource(unsigned &SrcReg, unsigned &SrcSubReg, +- unsigned &TrackReg, +- unsigned &TrackSubReg) { +- // If CurrentSrcIdx == 1, this means this function has already been called +- // once. CopyLike has one definition and one argument, thus, there is +- // nothing else to rewrite. +- if (!CopyLike.isCopy() || CurrentSrcIdx == 1) ++ virtual bool getNextRewritableSource(RegSubRegPair &Src, ++ RegSubRegPair &Dst) = 0; ++ ++ /// Rewrite the current source with \p NewReg and \p NewSubReg if possible. ++ /// \return True if the rewriting was possible, false otherwise. ++ virtual bool RewriteCurrentSource(unsigned NewReg, unsigned NewSubReg) = 0; ++}; ++ ++/// Rewriter for COPY instructions. ++class CopyRewriter : public Rewriter { ++public: ++ CopyRewriter(MachineInstr &MI) : Rewriter(MI) { ++ assert(MI.isCopy() && "Expected copy instruction"); ++ } ++ virtual ~CopyRewriter() = default; ++ ++ bool getNextRewritableSource(RegSubRegPair &Src, ++ RegSubRegPair &Dst) override { ++ // CurrentSrcIdx > 0 means this function has already been called. ++ if (CurrentSrcIdx > 0) + return false; + // This is the first call to getNextRewritableSource. + // Move the CurrentSrcIdx to remember that we made that call. + CurrentSrcIdx = 1; + // The rewritable source is the argument. + const MachineOperand &MOSrc = CopyLike.getOperand(1); +- SrcReg = MOSrc.getReg(); +- SrcSubReg = MOSrc.getSubReg(); ++ Src = RegSubRegPair(MOSrc.getReg(), MOSrc.getSubReg()); + // What we track are the alternative sources of the definition. + const MachineOperand &MODef = CopyLike.getOperand(0); +- TrackReg = MODef.getReg(); +- TrackSubReg = MODef.getSubReg(); ++ Dst = RegSubRegPair(MODef.getReg(), MODef.getSubReg()); + return true; + } + +- /// \brief Rewrite the current source with \p NewReg and \p NewSubReg +- /// if possible. +- /// \return True if the rewriting was possible, false otherwise. +- virtual bool RewriteCurrentSource(unsigned NewReg, unsigned NewSubReg) { +- if (!CopyLike.isCopy() || CurrentSrcIdx != 1) ++ bool RewriteCurrentSource(unsigned NewReg, unsigned NewSubReg) override { ++ if (CurrentSrcIdx != 1) + return false; + MachineOperand &MOSrc = CopyLike.getOperand(CurrentSrcIdx); + MOSrc.setReg(NewReg); + MOSrc.setSubReg(NewSubReg); + return true; + } +- +- /// \brief Given a \p Def.Reg and Def.SubReg pair, use \p RewriteMap to find +- /// the new source to use for rewrite. If \p HandleMultipleSources is true and +- /// multiple sources for a given \p Def are found along the way, we found a +- /// PHI instructions that needs to be rewritten. +- /// TODO: HandleMultipleSources should be removed once we test PHI handling +- /// with coalescable copies. +- TargetInstrInfo::RegSubRegPair +- getNewSource(MachineRegisterInfo *MRI, const TargetInstrInfo *TII, +- TargetInstrInfo::RegSubRegPair Def, +- PeepholeOptimizer::RewriteMapTy &RewriteMap, +- bool HandleMultipleSources = true) { +- TargetInstrInfo::RegSubRegPair LookupSrc(Def.Reg, Def.SubReg); +- do { +- ValueTrackerResult Res = RewriteMap.lookup(LookupSrc); +- // If there are no entries on the map, LookupSrc is the new source. +- if (!Res.isValid()) +- return LookupSrc; +- +- // There's only one source for this definition, keep searching... +- unsigned NumSrcs = Res.getNumSources(); +- if (NumSrcs == 1) { +- LookupSrc.Reg = Res.getSrcReg(0); +- LookupSrc.SubReg = Res.getSrcSubReg(0); +- continue; +- } +- +- // TODO: Remove once multiple srcs w/ coalescable copies are supported. +- if (!HandleMultipleSources) +- break; +- +- // Multiple sources, recurse into each source to find a new source +- // for it. Then, rewrite the PHI accordingly to its new edges. +- SmallVector NewPHISrcs; +- for (unsigned i = 0; i < NumSrcs; ++i) { +- TargetInstrInfo::RegSubRegPair PHISrc(Res.getSrcReg(i), +- Res.getSrcSubReg(i)); +- NewPHISrcs.push_back( +- getNewSource(MRI, TII, PHISrc, RewriteMap, HandleMultipleSources)); +- } +- +- // Build the new PHI node and return its def register as the new source. +- MachineInstr *OrigPHI = const_cast(Res.getInst()); +- MachineInstr *NewPHI = insertPHI(MRI, TII, NewPHISrcs, OrigPHI); +- DEBUG(dbgs() << "-- getNewSource\n"); +- DEBUG(dbgs() << " Replacing: " << *OrigPHI); +- DEBUG(dbgs() << " With: " << *NewPHI); +- const MachineOperand &MODef = NewPHI->getOperand(0); +- return TargetInstrInfo::RegSubRegPair(MODef.getReg(), MODef.getSubReg()); +- +- } while (true); +- +- return TargetInstrInfo::RegSubRegPair(0, 0); +- } +- +- /// \brief Rewrite the source found through \p Def, by using the \p RewriteMap +- /// and create a new COPY instruction. More info about RewriteMap in +- /// PeepholeOptimizer::findNextSource. Right now this is only used to handle +- /// Uncoalescable copies, since they are copy like instructions that aren't +- /// recognized by the register allocator. +- virtual MachineInstr * +- RewriteSource(TargetInstrInfo::RegSubRegPair Def, +- PeepholeOptimizer::RewriteMapTy &RewriteMap) { +- return nullptr; +- } + }; + + /// \brief Helper class to rewrite uncoalescable copy like instructions + /// into new COPY (coalescable friendly) instructions. +-class UncoalescableRewriter : public CopyRewriter { +-protected: +- const TargetInstrInfo &TII; +- MachineRegisterInfo &MRI; +- +- /// The number of defs in the bitcast +- unsigned NumDefs; ++class UncoalescableRewriter : public Rewriter { ++ unsigned NumDefs; ///< Number of defs in the bitcast. + + public: +- UncoalescableRewriter(MachineInstr &MI, const TargetInstrInfo &TII, +- MachineRegisterInfo &MRI) +- : CopyRewriter(MI), TII(TII), MRI(MRI) { ++ UncoalescableRewriter(MachineInstr &MI) : Rewriter(MI) { + NumDefs = MI.getDesc().getNumDefs(); + } + +- /// \brief Get the next rewritable def source (TrackReg, TrackSubReg) ++ /// \see See Rewriter::getNextRewritableSource() + /// All such sources need to be considered rewritable in order to + /// rewrite a uncoalescable copy-like instruction. This method return + /// each definition that must be checked if rewritable. +- bool getNextRewritableSource(unsigned &SrcReg, unsigned &SrcSubReg, +- unsigned &TrackReg, +- unsigned &TrackSubReg) override { ++ bool getNextRewritableSource(RegSubRegPair &Src, ++ RegSubRegPair &Dst) override { + // Find the next non-dead definition and continue from there. + if (CurrentSrcIdx == NumDefs) + return false; +@@ -990,64 +886,27 @@ + } + + // What we track are the alternative sources of the definition. ++ Src = RegSubRegPair(0, 0); + const MachineOperand &MODef = CopyLike.getOperand(CurrentSrcIdx); +- TrackReg = MODef.getReg(); +- TrackSubReg = MODef.getSubReg(); ++ Dst = RegSubRegPair(MODef.getReg(), MODef.getSubReg()); + + CurrentSrcIdx++; + return true; + } + +- /// \brief Rewrite the source found through \p Def, by using the \p RewriteMap +- /// and create a new COPY instruction. More info about RewriteMap in +- /// PeepholeOptimizer::findNextSource. Right now this is only used to handle +- /// Uncoalescable copies, since they are copy like instructions that aren't +- /// recognized by the register allocator. +- MachineInstr * +- RewriteSource(TargetInstrInfo::RegSubRegPair Def, +- PeepholeOptimizer::RewriteMapTy &RewriteMap) override { +- assert(!TargetRegisterInfo::isPhysicalRegister(Def.Reg) && +- "We do not rewrite physical registers"); +- +- // Find the new source to use in the COPY rewrite. +- TargetInstrInfo::RegSubRegPair NewSrc = +- getNewSource(&MRI, &TII, Def, RewriteMap); +- +- // Insert the COPY. +- const TargetRegisterClass *DefRC = MRI.getRegClass(Def.Reg); +- unsigned NewVR = MRI.createVirtualRegister(DefRC); +- +- MachineInstr *NewCopy = +- BuildMI(*CopyLike.getParent(), &CopyLike, CopyLike.getDebugLoc(), +- TII.get(TargetOpcode::COPY), NewVR) +- .addReg(NewSrc.Reg, 0, NewSrc.SubReg); +- +- NewCopy->getOperand(0).setSubReg(Def.SubReg); +- if (Def.SubReg) +- NewCopy->getOperand(0).setIsUndef(); +- +- DEBUG(dbgs() << "-- RewriteSource\n"); +- DEBUG(dbgs() << " Replacing: " << CopyLike); +- DEBUG(dbgs() << " With: " << *NewCopy); +- MRI.replaceRegWith(Def.Reg, NewVR); +- MRI.clearKillFlags(NewVR); +- +- // We extended the lifetime of NewSrc.Reg, clear the kill flags to +- // account for that. +- MRI.clearKillFlags(NewSrc.Reg); +- +- return NewCopy; ++ bool RewriteCurrentSource(unsigned NewReg, unsigned NewSubReg) override { ++ return false; + } + }; + +-/// \brief Specialized rewriter for INSERT_SUBREG instruction. +-class InsertSubregRewriter : public CopyRewriter { ++/// Specialized rewriter for INSERT_SUBREG instruction. ++class InsertSubregRewriter : public Rewriter { + public: +- InsertSubregRewriter(MachineInstr &MI) : CopyRewriter(MI) { ++ InsertSubregRewriter(MachineInstr &MI) : Rewriter(MI) { + assert(MI.isInsertSubreg() && "Invalid instruction"); + } + +- /// \brief See CopyRewriter::getNextRewritableSource. ++ /// \see See Rewriter::getNextRewritableSource() + /// Here CopyLike has the following form: + /// dst = INSERT_SUBREG Src1, Src2.src2SubIdx, subIdx. + /// Src1 has the same register class has dst, hence, there is +@@ -1055,29 +914,27 @@ + /// Src2.src2SubIdx, may not be register coalescer friendly. + /// Therefore, the first call to this method returns: + /// (SrcReg, SrcSubReg) = (Src2, src2SubIdx). +- /// (TrackReg, TrackSubReg) = (dst, subIdx). ++ /// (DstReg, DstSubReg) = (dst, subIdx). + /// + /// Subsequence calls will return false. +- bool getNextRewritableSource(unsigned &SrcReg, unsigned &SrcSubReg, +- unsigned &TrackReg, +- unsigned &TrackSubReg) override { ++ bool getNextRewritableSource(RegSubRegPair &Src, ++ RegSubRegPair &Dst) override { + // If we already get the only source we can rewrite, return false. + if (CurrentSrcIdx == 2) + return false; + // We are looking at v2 = INSERT_SUBREG v0, v1, sub0. + CurrentSrcIdx = 2; + const MachineOperand &MOInsertedReg = CopyLike.getOperand(2); +- SrcReg = MOInsertedReg.getReg(); +- SrcSubReg = MOInsertedReg.getSubReg(); ++ Src = RegSubRegPair(MOInsertedReg.getReg(), MOInsertedReg.getSubReg()); + const MachineOperand &MODef = CopyLike.getOperand(0); + + // We want to track something that is compatible with the + // partial definition. +- TrackReg = MODef.getReg(); + if (MODef.getSubReg()) + // Bail if we have to compose sub-register indices. + return false; +- TrackSubReg = (unsigned)CopyLike.getOperand(3).getImm(); ++ Dst = RegSubRegPair(MODef.getReg(), ++ (unsigned)CopyLike.getOperand(3).getImm()); + return true; + } + +@@ -1092,41 +949,39 @@ + } + }; + +-/// \brief Specialized rewriter for EXTRACT_SUBREG instruction. +-class ExtractSubregRewriter : public CopyRewriter { ++/// Specialized rewriter for EXTRACT_SUBREG instruction. ++class ExtractSubregRewriter : public Rewriter { + const TargetInstrInfo &TII; + + public: + ExtractSubregRewriter(MachineInstr &MI, const TargetInstrInfo &TII) +- : CopyRewriter(MI), TII(TII) { ++ : Rewriter(MI), TII(TII) { + assert(MI.isExtractSubreg() && "Invalid instruction"); + } + +- /// \brief See CopyRewriter::getNextRewritableSource. ++ /// \see Rewriter::getNextRewritableSource() + /// Here CopyLike has the following form: + /// dst.dstSubIdx = EXTRACT_SUBREG Src, subIdx. + /// There is only one rewritable source: Src.subIdx, + /// which defines dst.dstSubIdx. +- bool getNextRewritableSource(unsigned &SrcReg, unsigned &SrcSubReg, +- unsigned &TrackReg, +- unsigned &TrackSubReg) override { ++ bool getNextRewritableSource(RegSubRegPair &Src, ++ RegSubRegPair &Dst) override { + // If we already get the only source we can rewrite, return false. + if (CurrentSrcIdx == 1) + return false; + // We are looking at v1 = EXTRACT_SUBREG v0, sub0. + CurrentSrcIdx = 1; + const MachineOperand &MOExtractedReg = CopyLike.getOperand(1); +- SrcReg = MOExtractedReg.getReg(); + // If we have to compose sub-register indices, bail out. + if (MOExtractedReg.getSubReg()) + return false; + +- SrcSubReg = CopyLike.getOperand(2).getImm(); ++ Src = RegSubRegPair(MOExtractedReg.getReg(), ++ CopyLike.getOperand(2).getImm()); + + // We want to track something that is compatible with the definition. + const MachineOperand &MODef = CopyLike.getOperand(0); +- TrackReg = MODef.getReg(); +- TrackSubReg = MODef.getSubReg(); ++ Dst = RegSubRegPair(MODef.getReg(), MODef.getSubReg()); + return true; + } + +@@ -1156,14 +1011,14 @@ + } + }; + +-/// \brief Specialized rewriter for REG_SEQUENCE instruction. +-class RegSequenceRewriter : public CopyRewriter { ++/// Specialized rewriter for REG_SEQUENCE instruction. ++class RegSequenceRewriter : public Rewriter { + public: +- RegSequenceRewriter(MachineInstr &MI) : CopyRewriter(MI) { ++ RegSequenceRewriter(MachineInstr &MI) : Rewriter(MI) { + assert(MI.isRegSequence() && "Invalid instruction"); + } + +- /// \brief See CopyRewriter::getNextRewritableSource. ++ /// \see Rewriter::getNextRewritableSource() + /// Here CopyLike has the following form: + /// dst = REG_SEQUENCE Src1.src1SubIdx, subIdx1, Src2.src2SubIdx, subIdx2. + /// Each call will return a different source, walking all the available +@@ -1171,17 +1026,16 @@ + /// + /// The first call returns: + /// (SrcReg, SrcSubReg) = (Src1, src1SubIdx). +- /// (TrackReg, TrackSubReg) = (dst, subIdx1). ++ /// (DstReg, DstSubReg) = (dst, subIdx1). + /// + /// The second call returns: + /// (SrcReg, SrcSubReg) = (Src2, src2SubIdx). +- /// (TrackReg, TrackSubReg) = (dst, subIdx2). ++ /// (DstReg, DstSubReg) = (dst, subIdx2). + /// + /// And so on, until all the sources have been traversed, then + /// it returns false. +- bool getNextRewritableSource(unsigned &SrcReg, unsigned &SrcSubReg, +- unsigned &TrackReg, +- unsigned &TrackSubReg) override { ++ bool getNextRewritableSource(RegSubRegPair &Src, ++ RegSubRegPair &Dst) override { + // We are looking at v0 = REG_SEQUENCE v1, sub1, v2, sub2, etc. + + // If this is the first call, move to the first argument. +@@ -1194,17 +1048,17 @@ + return false; + } + const MachineOperand &MOInsertedReg = CopyLike.getOperand(CurrentSrcIdx); +- SrcReg = MOInsertedReg.getReg(); ++ Src.Reg = MOInsertedReg.getReg(); + // If we have to compose sub-register indices, bail out. +- if ((SrcSubReg = MOInsertedReg.getSubReg())) ++ if ((Src.SubReg = MOInsertedReg.getSubReg())) + return false; + + // We want to track something that is compatible with the related + // partial definition. +- TrackSubReg = CopyLike.getOperand(CurrentSrcIdx + 1).getImm(); ++ Dst.SubReg = CopyLike.getOperand(CurrentSrcIdx + 1).getImm(); + + const MachineOperand &MODef = CopyLike.getOperand(0); +- TrackReg = MODef.getReg(); ++ Dst.Reg = MODef.getReg(); + // If we have to compose sub-registers, bail. + return MODef.getSubReg() == 0; + } +@@ -1224,16 +1078,14 @@ + + } // end anonymous namespace + +-/// \brief Get the appropriated CopyRewriter for \p MI. +-/// \return A pointer to a dynamically allocated CopyRewriter or nullptr +-/// if no rewriter works for \p MI. +-static CopyRewriter *getCopyRewriter(MachineInstr &MI, +- const TargetInstrInfo &TII, +- MachineRegisterInfo &MRI) { ++/// Get the appropriated Rewriter for \p MI. ++/// \return A pointer to a dynamically allocated Rewriter or nullptr if no ++/// rewriter works for \p MI. ++static Rewriter *getCopyRewriter(MachineInstr &MI, const TargetInstrInfo &TII) { + // Handle uncoalescable copy-like instructions. +- if (MI.isBitcast() || (MI.isRegSequenceLike() || MI.isInsertSubregLike() || +- MI.isExtractSubregLike())) +- return new UncoalescableRewriter(MI, TII, MRI); ++ if (MI.isBitcast() || MI.isRegSequenceLike() || MI.isInsertSubregLike() || ++ MI.isExtractSubregLike()) ++ return new UncoalescableRewriter(MI); + + switch (MI.getOpcode()) { + default: +@@ -1247,53 +1099,102 @@ + case TargetOpcode::REG_SEQUENCE: + return new RegSequenceRewriter(MI); + } +- llvm_unreachable(nullptr); + } + +-/// \brief Optimize generic copy instructions to avoid cross +-/// register bank copy. The optimization looks through a chain of +-/// copies and tries to find a source that has a compatible register +-/// class. +-/// Two register classes are considered to be compatible if they share +-/// the same register bank. ++/// \brief Given a \p Def.Reg and Def.SubReg pair, use \p RewriteMap to find ++/// the new source to use for rewrite. If \p HandleMultipleSources is true and ++/// multiple sources for a given \p Def are found along the way, we found a ++/// PHI instructions that needs to be rewritten. ++/// TODO: HandleMultipleSources should be removed once we test PHI handling ++/// with coalescable copies. ++static RegSubRegPair ++getNewSource(MachineRegisterInfo *MRI, const TargetInstrInfo *TII, ++ RegSubRegPair Def, ++ const PeepholeOptimizer::RewriteMapTy &RewriteMap, ++ bool HandleMultipleSources = true) { ++ RegSubRegPair LookupSrc(Def.Reg, Def.SubReg); ++ while (true) { ++ ValueTrackerResult Res = RewriteMap.lookup(LookupSrc); ++ // If there are no entries on the map, LookupSrc is the new source. ++ if (!Res.isValid()) ++ return LookupSrc; ++ ++ // There's only one source for this definition, keep searching... ++ unsigned NumSrcs = Res.getNumSources(); ++ if (NumSrcs == 1) { ++ LookupSrc.Reg = Res.getSrcReg(0); ++ LookupSrc.SubReg = Res.getSrcSubReg(0); ++ continue; ++ } ++ ++ // TODO: Remove once multiple srcs w/ coalescable copies are supported. ++ if (!HandleMultipleSources) ++ break; ++ ++ // Multiple sources, recurse into each source to find a new source ++ // for it. Then, rewrite the PHI accordingly to its new edges. ++ SmallVector NewPHISrcs; ++ for (unsigned i = 0; i < NumSrcs; ++i) { ++ RegSubRegPair PHISrc(Res.getSrcReg(i), Res.getSrcSubReg(i)); ++ NewPHISrcs.push_back( ++ getNewSource(MRI, TII, PHISrc, RewriteMap, HandleMultipleSources)); ++ } ++ ++ // Build the new PHI node and return its def register as the new source. ++ MachineInstr &OrigPHI = const_cast(*Res.getInst()); ++ MachineInstr &NewPHI = insertPHI(*MRI, *TII, NewPHISrcs, OrigPHI); ++ DEBUG(dbgs() << "-- getNewSource\n"); ++ DEBUG(dbgs() << " Replacing: " << OrigPHI); ++ DEBUG(dbgs() << " With: " << NewPHI); ++ const MachineOperand &MODef = NewPHI.getOperand(0); ++ return RegSubRegPair(MODef.getReg(), MODef.getSubReg()); ++ } ++ ++ return RegSubRegPair(0, 0); ++} ++ ++/// Optimize generic copy instructions to avoid cross register bank copy. ++/// The optimization looks through a chain of copies and tries to find a source ++/// that has a compatible register class. ++/// Two register classes are considered to be compatible if they share the same ++/// register bank. + /// New copies issued by this optimization are register allocator + /// friendly. This optimization does not remove any copy as it may + /// overconstrain the register allocator, but replaces some operands + /// when possible. + /// \pre isCoalescableCopy(*MI) is true. + /// \return True, when \p MI has been rewritten. False otherwise. +-bool PeepholeOptimizer::optimizeCoalescableCopy(MachineInstr *MI) { +- assert(MI && isCoalescableCopy(*MI) && "Invalid argument"); +- assert(MI->getDesc().getNumDefs() == 1 && ++bool PeepholeOptimizer::optimizeCoalescableCopy(MachineInstr &MI) { ++ assert(isCoalescableCopy(MI) && "Invalid argument"); ++ assert(MI.getDesc().getNumDefs() == 1 && + "Coalescer can understand multiple defs?!"); +- const MachineOperand &MODef = MI->getOperand(0); ++ const MachineOperand &MODef = MI.getOperand(0); + // Do not rewrite physical definitions. + if (TargetRegisterInfo::isPhysicalRegister(MODef.getReg())) + return false; + + bool Changed = false; + // Get the right rewriter for the current copy. +- std::unique_ptr CpyRewriter(getCopyRewriter(*MI, *TII, *MRI)); ++ std::unique_ptr CpyRewriter(getCopyRewriter(MI, *TII)); + // If none exists, bail out. + if (!CpyRewriter) + return false; + // Rewrite each rewritable source. +- unsigned SrcReg, SrcSubReg, TrackReg, TrackSubReg; +- while (CpyRewriter->getNextRewritableSource(SrcReg, SrcSubReg, TrackReg, +- TrackSubReg)) { ++ RegSubRegPair Src; ++ RegSubRegPair TrackPair; ++ while (CpyRewriter->getNextRewritableSource(Src, TrackPair)) { + // Keep track of PHI nodes and its incoming edges when looking for sources. + RewriteMapTy RewriteMap; + // Try to find a more suitable source. If we failed to do so, or get the + // actual source, move to the next source. +- if (!findNextSource(TrackReg, TrackSubReg, RewriteMap)) ++ if (!findNextSource(TrackPair, RewriteMap)) + continue; + + // Get the new source to rewrite. TODO: Only enable handling of multiple + // sources (PHIs) once we have a motivating example and testcases for it. +- TargetInstrInfo::RegSubRegPair TrackPair(TrackReg, TrackSubReg); +- TargetInstrInfo::RegSubRegPair NewSrc = CpyRewriter->getNewSource( +- MRI, TII, TrackPair, RewriteMap, false /* multiple sources */); +- if (SrcReg == NewSrc.Reg || NewSrc.Reg == 0) ++ RegSubRegPair NewSrc = getNewSource(MRI, TII, TrackPair, RewriteMap, ++ /*HandleMultipleSources=*/false); ++ if (Src.Reg == NewSrc.Reg || NewSrc.Reg == 0) + continue; + + // Rewrite source. +@@ -1312,6 +1213,47 @@ + return Changed; + } + ++/// \brief Rewrite the source found through \p Def, by using the \p RewriteMap ++/// and create a new COPY instruction. More info about RewriteMap in ++/// PeepholeOptimizer::findNextSource. Right now this is only used to handle ++/// Uncoalescable copies, since they are copy like instructions that aren't ++/// recognized by the register allocator. ++MachineInstr & ++PeepholeOptimizer::rewriteSource(MachineInstr &CopyLike, ++ RegSubRegPair Def, RewriteMapTy &RewriteMap) { ++ assert(!TargetRegisterInfo::isPhysicalRegister(Def.Reg) && ++ "We do not rewrite physical registers"); ++ ++ // Find the new source to use in the COPY rewrite. ++ RegSubRegPair NewSrc = getNewSource(MRI, TII, Def, RewriteMap); ++ ++ // Insert the COPY. ++ const TargetRegisterClass *DefRC = MRI->getRegClass(Def.Reg); ++ unsigned NewVReg = MRI->createVirtualRegister(DefRC); ++ ++ MachineInstr *NewCopy = ++ BuildMI(*CopyLike.getParent(), &CopyLike, CopyLike.getDebugLoc(), ++ TII->get(TargetOpcode::COPY), NewVReg) ++ .addReg(NewSrc.Reg, 0, NewSrc.SubReg); ++ ++ if (Def.SubReg) { ++ NewCopy->getOperand(0).setSubReg(Def.SubReg); ++ NewCopy->getOperand(0).setIsUndef(); ++ } ++ ++ DEBUG(dbgs() << "-- RewriteSource\n"); ++ DEBUG(dbgs() << " Replacing: " << CopyLike); ++ DEBUG(dbgs() << " With: " << *NewCopy); ++ MRI->replaceRegWith(Def.Reg, NewVReg); ++ MRI->clearKillFlags(NewVReg); ++ ++ // We extended the lifetime of NewSrc.Reg, clear the kill flags to ++ // account for that. ++ MRI->clearKillFlags(NewSrc.Reg); ++ ++ return *NewCopy; ++} ++ + /// \brief Optimize copy-like instructions to create + /// register coalescer friendly instruction. + /// The optimization tries to kill-off the \p MI by looking +@@ -1324,48 +1266,40 @@ + /// been removed from its parent. + /// All COPY instructions created, are inserted in \p LocalMIs. + bool PeepholeOptimizer::optimizeUncoalescableCopy( +- MachineInstr *MI, SmallPtrSetImpl &LocalMIs) { +- assert(MI && isUncoalescableCopy(*MI) && "Invalid argument"); +- +- // Check if we can rewrite all the values defined by this instruction. +- SmallVector RewritePairs; +- // Get the right rewriter for the current copy. +- std::unique_ptr CpyRewriter(getCopyRewriter(*MI, *TII, *MRI)); +- // If none exists, bail out. +- if (!CpyRewriter) +- return false; ++ MachineInstr &MI, SmallPtrSetImpl &LocalMIs) { ++ assert(isUncoalescableCopy(MI) && "Invalid argument"); ++ UncoalescableRewriter CpyRewriter(MI); + + // Rewrite each rewritable source by generating new COPYs. This works + // differently from optimizeCoalescableCopy since it first makes sure that all + // definitions can be rewritten. + RewriteMapTy RewriteMap; +- unsigned Reg, SubReg, CopyDefReg, CopyDefSubReg; +- while (CpyRewriter->getNextRewritableSource(Reg, SubReg, CopyDefReg, +- CopyDefSubReg)) { ++ RegSubRegPair Src; ++ RegSubRegPair Def; ++ SmallVector RewritePairs; ++ while (CpyRewriter.getNextRewritableSource(Src, Def)) { + // If a physical register is here, this is probably for a good reason. + // Do not rewrite that. +- if (TargetRegisterInfo::isPhysicalRegister(CopyDefReg)) ++ if (TargetRegisterInfo::isPhysicalRegister(Def.Reg)) + return false; + + // If we do not know how to rewrite this definition, there is no point + // in trying to kill this instruction. +- TargetInstrInfo::RegSubRegPair Def(CopyDefReg, CopyDefSubReg); +- if (!findNextSource(Def.Reg, Def.SubReg, RewriteMap)) ++ if (!findNextSource(Def, RewriteMap)) + return false; + + RewritePairs.push_back(Def); + } + + // The change is possible for all defs, do it. +- for (const auto &Def : RewritePairs) { ++ for (const RegSubRegPair &Def : RewritePairs) { + // Rewrite the "copy" in a way the register coalescer understands. +- MachineInstr *NewCopy = CpyRewriter->RewriteSource(Def, RewriteMap); +- assert(NewCopy && "Should be able to always generate a new copy"); +- LocalMIs.insert(NewCopy); ++ MachineInstr &NewCopy = rewriteSource(MI, Def, RewriteMap); ++ LocalMIs.insert(&NewCopy); + } + + // MI is now dead. +- MI->eraseFromParent(); ++ MI.eraseFromParent(); + ++NumUncoalescableCopies; + return true; + } +@@ -1374,18 +1308,18 @@ + /// We only fold loads to virtual registers and the virtual register defined + /// has a single use. + bool PeepholeOptimizer::isLoadFoldable( +- MachineInstr *MI, SmallSet &FoldAsLoadDefCandidates) { +- if (!MI->canFoldAsLoad() || !MI->mayLoad()) ++ MachineInstr &MI, SmallSet &FoldAsLoadDefCandidates) { ++ if (!MI.canFoldAsLoad() || !MI.mayLoad()) + return false; +- const MCInstrDesc &MCID = MI->getDesc(); ++ const MCInstrDesc &MCID = MI.getDesc(); + if (MCID.getNumDefs() != 1) + return false; + +- unsigned Reg = MI->getOperand(0).getReg(); ++ unsigned Reg = MI.getOperand(0).getReg(); + // To reduce compilation time, we check MRI->hasOneNonDBGUse when inserting + // loads. It should be checked when processing uses of the load, since + // uses can be removed during peephole. +- if (!MI->getOperand(0).getSubReg() && ++ if (!MI.getOperand(0).getSubReg() && + TargetRegisterInfo::isVirtualRegister(Reg) && + MRI->hasOneNonDBGUse(Reg)) { + FoldAsLoadDefCandidates.insert(Reg); +@@ -1395,16 +1329,16 @@ + } + + bool PeepholeOptimizer::isMoveImmediate( +- MachineInstr *MI, SmallSet &ImmDefRegs, ++ MachineInstr &MI, SmallSet &ImmDefRegs, + DenseMap &ImmDefMIs) { +- const MCInstrDesc &MCID = MI->getDesc(); +- if (!MI->isMoveImmediate()) ++ const MCInstrDesc &MCID = MI.getDesc(); ++ if (!MI.isMoveImmediate()) + return false; + if (MCID.getNumDefs() != 1) + return false; +- unsigned Reg = MI->getOperand(0).getReg(); ++ unsigned Reg = MI.getOperand(0).getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) { +- ImmDefMIs.insert(std::make_pair(Reg, MI)); ++ ImmDefMIs.insert(std::make_pair(Reg, &MI)); + ImmDefRegs.insert(Reg); + return true; + } +@@ -1415,11 +1349,11 @@ + /// Try folding register operands that are defined by move immediate + /// instructions, i.e. a trivial constant folding optimization, if + /// and only if the def and use are in the same BB. +-bool PeepholeOptimizer::foldImmediate( +- MachineInstr *MI, MachineBasicBlock *MBB, SmallSet &ImmDefRegs, ++bool PeepholeOptimizer::foldImmediate(MachineInstr &MI, ++ SmallSet &ImmDefRegs, + DenseMap &ImmDefMIs) { +- for (unsigned i = 0, e = MI->getDesc().getNumOperands(); i != e; ++i) { +- MachineOperand &MO = MI->getOperand(i); ++ for (unsigned i = 0, e = MI.getDesc().getNumOperands(); i != e; ++i) { ++ MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || MO.isDef()) + continue; + // Ignore dead implicit defs. +@@ -1432,7 +1366,7 @@ + continue; + DenseMap::iterator II = ImmDefMIs.find(Reg); + assert(II != ImmDefMIs.end() && "couldn't find immediate definition"); +- if (TII->FoldImmediate(*MI, *II->second, Reg, MRI)) { ++ if (TII->FoldImmediate(MI, *II->second, Reg, MRI)) { + ++NumImmFold; + return true; + } +@@ -1454,28 +1388,28 @@ + // %2 = COPY %0:sub1 + // + // Should replace %2 uses with %1:sub1 +-bool PeepholeOptimizer::foldRedundantCopy( +- MachineInstr *MI, SmallSet &CopySrcRegs, ++bool PeepholeOptimizer::foldRedundantCopy(MachineInstr &MI, ++ SmallSet &CopySrcRegs, + DenseMap &CopyMIs) { +- assert(MI->isCopy() && "expected a COPY machine instruction"); ++ assert(MI.isCopy() && "expected a COPY machine instruction"); + +- unsigned SrcReg = MI->getOperand(1).getReg(); ++ unsigned SrcReg = MI.getOperand(1).getReg(); + if (!TargetRegisterInfo::isVirtualRegister(SrcReg)) + return false; + +- unsigned DstReg = MI->getOperand(0).getReg(); ++ unsigned DstReg = MI.getOperand(0).getReg(); + if (!TargetRegisterInfo::isVirtualRegister(DstReg)) + return false; + + if (CopySrcRegs.insert(SrcReg).second) { + // First copy of this reg seen. +- CopyMIs.insert(std::make_pair(SrcReg, MI)); ++ CopyMIs.insert(std::make_pair(SrcReg, &MI)); + return false; + } + + MachineInstr *PrevCopy = CopyMIs.find(SrcReg)->second; + +- unsigned SrcSubReg = MI->getOperand(1).getSubReg(); ++ unsigned SrcSubReg = MI.getOperand(1).getSubReg(); + unsigned PrevSrcSubReg = PrevCopy->getOperand(1).getSubReg(); + + // Can't replace different subregister extracts. +@@ -1504,19 +1438,19 @@ + } + + bool PeepholeOptimizer::foldRedundantNAPhysCopy( +- MachineInstr *MI, DenseMap &NAPhysToVirtMIs) { +- assert(MI->isCopy() && "expected a COPY machine instruction"); ++ MachineInstr &MI, DenseMap &NAPhysToVirtMIs) { ++ assert(MI.isCopy() && "expected a COPY machine instruction"); + + if (DisableNAPhysCopyOpt) + return false; + +- unsigned DstReg = MI->getOperand(0).getReg(); +- unsigned SrcReg = MI->getOperand(1).getReg(); ++ unsigned DstReg = MI.getOperand(0).getReg(); ++ unsigned SrcReg = MI.getOperand(1).getReg(); + if (isNAPhysCopy(SrcReg) && TargetRegisterInfo::isVirtualRegister(DstReg)) { + // %vreg = COPY %physreg + // Avoid using a datastructure which can track multiple live non-allocatable + // phys->virt copies since LLVM doesn't seem to do this. +- NAPhysToVirtMIs.insert({SrcReg, MI}); ++ NAPhysToVirtMIs.insert({SrcReg, &MI}); + return false; + } + +@@ -1528,8 +1462,7 @@ + if (PrevCopy == NAPhysToVirtMIs.end()) { + // We can't remove the copy: there was an intervening clobber of the + // non-allocatable physical register after the copy to virtual. +- DEBUG(dbgs() << "NAPhysCopy: intervening clobber forbids erasing " << *MI +- << '\n'); ++ DEBUG(dbgs() << "NAPhysCopy: intervening clobber forbids erasing " << MI); + return false; + } + +@@ -1537,7 +1470,7 @@ + if (PrevDstReg == SrcReg) { + // Remove the virt->phys copy: we saw the virtual register definition, and + // the non-allocatable physical register's state hasn't changed since then. +- DEBUG(dbgs() << "NAPhysCopy: erasing " << *MI << '\n'); ++ DEBUG(dbgs() << "NAPhysCopy: erasing " << MI); + ++NumNAPhysCopies; + return true; + } +@@ -1546,7 +1479,7 @@ + // register get a copy of the non-allocatable physical register, and we only + // track one such copy. Avoid getting confused by this new non-allocatable + // physical register definition, and remove it from the tracked copies. +- DEBUG(dbgs() << "NAPhysCopy: missed opportunity " << *MI << '\n'); ++ DEBUG(dbgs() << "NAPhysCopy: missed opportunity " << MI); + NAPhysToVirtMIs.erase(PrevCopy); + return false; + } +@@ -1611,11 +1544,11 @@ + return false; + } + +-/// \brief Phi instructions will eventually be lowered to copy instructions. If +-/// phi is in a loop header, a recurrence may formulated around the source and +-/// destination of the phi. For such case commuting operands of the instructions +-/// in the recurrence may enable coalescing of the copy instruction generated +-/// from the phi. For example, if there is a recurrence of ++/// Phi instructions will eventually be lowered to copy instructions. ++/// If phi is in a loop header, a recurrence may formulated around the source ++/// and destination of the phi. For such case commuting operands of the ++/// instructions in the recurrence may enable coalescing of the copy instruction ++/// generated from the phi. For example, if there is a recurrence of + /// + /// LoopHeader: + /// %1 = phi(%0, %100) +@@ -1725,27 +1658,25 @@ + } + + if (!MI->isCopy()) { +- for (const auto &Op : MI->operands()) { ++ for (const MachineOperand &MO : MI->operands()) { + // Visit all operands: definitions can be implicit or explicit. +- if (Op.isReg()) { +- unsigned Reg = Op.getReg(); +- if (Op.isDef() && isNAPhysCopy(Reg)) { ++ if (MO.isReg()) { ++ unsigned Reg = MO.getReg(); ++ if (MO.isDef() && isNAPhysCopy(Reg)) { + const auto &Def = NAPhysToVirtMIs.find(Reg); + if (Def != NAPhysToVirtMIs.end()) { + // A new definition of the non-allocatable physical register + // invalidates previous copies. +- DEBUG(dbgs() << "NAPhysCopy: invalidating because of " << *MI +- << '\n'); ++ DEBUG(dbgs() << "NAPhysCopy: invalidating because of " << *MI); + NAPhysToVirtMIs.erase(Def); + } + } +- } else if (Op.isRegMask()) { +- const uint32_t *RegMask = Op.getRegMask(); ++ } else if (MO.isRegMask()) { ++ const uint32_t *RegMask = MO.getRegMask(); + for (auto &RegMI : NAPhysToVirtMIs) { + unsigned Def = RegMI.first; + if (MachineOperand::clobbersPhysReg(RegMask, Def)) { +- DEBUG(dbgs() << "NAPhysCopy: invalidating because of " << *MI +- << '\n'); ++ DEBUG(dbgs() << "NAPhysCopy: invalidating because of " << *MI); + NAPhysToVirtMIs.erase(Def); + } + } +@@ -1761,58 +1692,57 @@ + // don't know what's correct anymore. + // + // FIXME: handle explicit asm clobbers. +- DEBUG(dbgs() << "NAPhysCopy: blowing away all info due to " << *MI +- << '\n'); ++ DEBUG(dbgs() << "NAPhysCopy: blowing away all info due to " << *MI); + NAPhysToVirtMIs.clear(); + } + + if ((isUncoalescableCopy(*MI) && +- optimizeUncoalescableCopy(MI, LocalMIs)) || +- (MI->isCompare() && optimizeCmpInstr(MI, &MBB)) || +- (MI->isSelect() && optimizeSelect(MI, LocalMIs))) { ++ optimizeUncoalescableCopy(*MI, LocalMIs)) || ++ (MI->isCompare() && optimizeCmpInstr(*MI)) || ++ (MI->isSelect() && optimizeSelect(*MI, LocalMIs))) { + // MI is deleted. + LocalMIs.erase(MI); + Changed = true; + continue; + } + +- if (MI->isConditionalBranch() && optimizeCondBranch(MI)) { ++ if (MI->isConditionalBranch() && optimizeCondBranch(*MI)) { + Changed = true; + continue; + } + +- if (isCoalescableCopy(*MI) && optimizeCoalescableCopy(MI)) { ++ if (isCoalescableCopy(*MI) && optimizeCoalescableCopy(*MI)) { + // MI is just rewritten. + Changed = true; + continue; + } + + if (MI->isCopy() && +- (foldRedundantCopy(MI, CopySrcRegs, CopySrcMIs) || +- foldRedundantNAPhysCopy(MI, NAPhysToVirtMIs))) { ++ (foldRedundantCopy(*MI, CopySrcRegs, CopySrcMIs) || ++ foldRedundantNAPhysCopy(*MI, NAPhysToVirtMIs))) { + LocalMIs.erase(MI); + MI->eraseFromParent(); + Changed = true; + continue; + } + +- if (isMoveImmediate(MI, ImmDefRegs, ImmDefMIs)) { ++ if (isMoveImmediate(*MI, ImmDefRegs, ImmDefMIs)) { + SeenMoveImm = true; + } else { +- Changed |= optimizeExtInstr(MI, &MBB, LocalMIs); ++ Changed |= optimizeExtInstr(*MI, MBB, LocalMIs); + // optimizeExtInstr might have created new instructions after MI + // and before the already incremented MII. Adjust MII so that the + // next iteration sees the new instructions. + MII = MI; + ++MII; + if (SeenMoveImm) +- Changed |= foldImmediate(MI, &MBB, ImmDefRegs, ImmDefMIs); ++ Changed |= foldImmediate(*MI, ImmDefRegs, ImmDefMIs); + } + + // Check whether MI is a load candidate for folding into a later + // instruction. If MI is not a candidate, check whether we can fold an + // earlier load into MI. +- if (!isLoadFoldable(MI, FoldAsLoadDefCandidates) && ++ if (!isLoadFoldable(*MI, FoldAsLoadDefCandidates) && + !FoldAsLoadDefCandidates.empty()) { + + // We visit each operand even after successfully folding a previous +@@ -1861,7 +1791,7 @@ + // the load candidates. Note: We might be able to fold *into* this + // instruction, so this needs to be after the folding logic. + if (MI->isLoadFoldBarrier()) { +- DEBUG(dbgs() << "Encountered load fold barrier on " << *MI << "\n"); ++ DEBUG(dbgs() << "Encountered load fold barrier on " << *MI); + FoldAsLoadDefCandidates.clear(); + } + } +@@ -1958,14 +1888,14 @@ + // duplicate the code from the generic TII. + return ValueTrackerResult(); + +- SmallVector RegSeqInputRegs; ++ SmallVector RegSeqInputRegs; + if (!TII->getRegSequenceInputs(*Def, DefIdx, RegSeqInputRegs)) + return ValueTrackerResult(); + + // We are looking at: + // Def = REG_SEQUENCE v0, sub0, v1, sub1, ... + // Check if one of the operand defines the subreg we are interested in. +- for (auto &RegSeqInput : RegSeqInputRegs) { ++ for (const RegSubRegPairAndIdx &RegSeqInput : RegSeqInputRegs) { + if (RegSeqInput.SubIdx == DefSubReg) { + if (RegSeqInput.SubReg) + // Bail if we have to compose sub registers. +@@ -1996,8 +1926,8 @@ + // duplicate the code from the generic TII. + return ValueTrackerResult(); + +- TargetInstrInfo::RegSubRegPair BaseReg; +- TargetInstrInfo::RegSubRegPairAndIdx InsertedReg; ++ RegSubRegPair BaseReg; ++ RegSubRegPairAndIdx InsertedReg; + if (!TII->getInsertSubregInputs(*Def, DefIdx, BaseReg, InsertedReg)) + return ValueTrackerResult(); + +@@ -2050,7 +1980,7 @@ + // duplicate the code from the generic TII. + return ValueTrackerResult(); + +- TargetInstrInfo::RegSubRegPairAndIdx ExtractSubregInputReg; ++ RegSubRegPairAndIdx ExtractSubregInputReg; + if (!TII->getExtractSubregInputs(*Def, DefIdx, ExtractSubregInputReg)) + return ValueTrackerResult(); + +@@ -2083,7 +2013,7 @@ + Def->getOperand(3).getImm()); + } + +-/// \brief Explore each PHI incoming operand and return its sources ++/// Explore each PHI incoming operand and return its sources. + ValueTrackerResult ValueTracker::getNextSourceFromPHI() { + assert(Def->isPHI() && "Invalid definition"); + ValueTrackerResult Res; +@@ -2095,7 +2025,7 @@ + + // Return all register sources for PHI instructions. + for (unsigned i = 1, e = Def->getNumOperands(); i < e; i += 2) { +- auto &MO = Def->getOperand(i); ++ const MachineOperand &MO = Def->getOperand(i); + assert(MO.isReg() && "Invalid PHI instruction"); + // We have no code to deal with undef operands. They shouldn't happen in + // normal programs anyway. +@@ -2121,7 +2051,7 @@ + return getNextSourceFromBitcast(); + // All the remaining cases involve "complex" instructions. + // Bail if we did not ask for the advanced tracking. +- if (!UseAdvancedTracking) ++ if (DisableAdvCopyOpt) + return ValueTrackerResult(); + if (Def->isRegSequence() || Def->isRegSequenceLike()) + return getNextSourceFromRegSequence(); Property changes on: head/devel/llvm60/files/patch-svn-r322325 ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property