aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-06-01 20:58:36 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-06-01 20:58:36 +0000
commitf382538d471e38a9b98f016c4caebd24c8d60b62 (patch)
treed30f3d58b1044b5355d50c17a6a96c6a0b35703a
parentee2f195dd3e40f49698ca4dc2666ec09c770e80d (diff)
downloadsrc-f382538d471e38a9b98f016c4caebd24c8d60b62.tar.gz
src-f382538d471e38a9b98f016c4caebd24c8d60b62.zip
Vendor import of llvm trunk r304460:vendor/llvm/llvm-trunk-r304460
Notes
Notes: svn path=/vendor/llvm/dist/; revision=319461 svn path=/vendor/llvm/llvm-trunk-r304460/; revision=319462; tag=vendor/llvm/llvm-trunk-r304460
-rw-r--r--docs/Vectorizers.rst6
-rw-r--r--include/llvm/Analysis/TargetTransformInfo.h7
-rw-r--r--include/llvm/Analysis/TargetTransformInfoImpl.h2
-rw-r--r--include/llvm/Analysis/ValueTracking.h2
-rw-r--r--include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h2
-rw-r--r--include/llvm/CodeGen/ISDOpcodes.h12
-rw-r--r--include/llvm/CodeGen/MIRYamlMapping.h2
-rw-r--r--include/llvm/CodeGen/MachineBasicBlock.h3
-rw-r--r--include/llvm/CodeGen/MachineConstantPool.h17
-rw-r--r--include/llvm/CodeGen/MachineFunction.h116
-rw-r--r--include/llvm/CodeGen/MachineFunctionInitializer.h6
-rw-r--r--include/llvm/CodeGen/MachineInstr.h75
-rw-r--r--include/llvm/CodeGen/MachineInstrBundleIterator.h72
-rw-r--r--include/llvm/CodeGen/MachineLoopInfo.h24
-rw-r--r--include/llvm/CodeGen/MachineModuleInfo.h36
-rw-r--r--include/llvm/CodeGen/Passes.h4
-rw-r--r--include/llvm/CodeGen/TargetPassConfig.h6
-rw-r--r--include/llvm/DebugInfo/CodeView/CodeView.h14
-rw-r--r--include/llvm/DebugInfo/CodeView/CodeViewSymbols.def (renamed from include/llvm/DebugInfo/CodeView/CVSymbolTypes.def)0
-rw-r--r--include/llvm/DebugInfo/CodeView/CodeViewTypes.def (renamed from include/llvm/DebugInfo/CodeView/TypeRecords.def)0
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolDeserializer.h13
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolRecord.h2
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h2
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolSerializer.h13
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h2
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h2
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h2
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeDeserializer.h5
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h2
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeRecord.h36
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeRecordMapping.h2
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeSerializer.h2
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeTableBuilder.h2
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h2
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h6
-rw-r--r--include/llvm/DebugInfo/DIContext.h11
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFContext.h3
-rw-r--r--include/llvm/DebugInfo/PDB/Native/RawConstants.h1
-rw-r--r--include/llvm/DebugInfo/PDB/Native/TpiHashing.h2
-rw-r--r--include/llvm/DebugInfo/PDB/PDBContext.h3
-rw-r--r--include/llvm/IR/Attributes.h197
-rw-r--r--include/llvm/IR/Function.h47
-rw-r--r--include/llvm/IR/Instructions.h18
-rw-r--r--include/llvm/InitializePasses.h1
-rw-r--r--include/llvm/Object/WindowsResource.h64
-rw-r--r--include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h91
-rw-r--r--include/llvm/ObjectYAML/CodeViewYAMLSymbols.h41
-rw-r--r--include/llvm/ObjectYAML/CodeViewYAMLTypes.h48
-rw-r--r--include/llvm/Passes/PassBuilder.h63
-rw-r--r--include/llvm/Support/ARMTargetParser.def4
-rw-r--r--include/llvm/Support/BinaryStreamReader.h8
-rw-r--r--include/llvm/Support/YAMLTraits.h38
-rw-r--r--include/llvm/TableGen/Record.h12
-rw-r--r--include/llvm/Target/TargetLowering.h12
-rw-r--r--include/llvm/Target/TargetMachine.h6
-rw-r--r--include/llvm/Transforms/IPO/ThinLTOBitcodeWriter.h41
-rw-r--r--include/llvm/Transforms/Scalar/GVN.h27
-rw-r--r--include/llvm/Transforms/Utils/CodeExtractor.h13
-rw-r--r--include/llvm/module.modulemap4
-rw-r--r--lib/Analysis/CFLGraph.h6
-rw-r--r--lib/Analysis/ConstantFolding.cpp2
-rw-r--r--lib/Analysis/EHPersonalities.cpp2
-rw-r--r--lib/Analysis/InstructionSimplify.cpp7
-rw-r--r--lib/Analysis/MemoryDependenceAnalysis.cpp1
-rw-r--r--lib/Analysis/ScalarEvolution.cpp4
-rw-r--r--lib/Analysis/TargetTransformInfo.cpp4
-rw-r--r--lib/Analysis/ValueTracking.cpp13
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp56
-rw-r--r--lib/CodeGen/AggressiveAntiDepBreaker.cpp2
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinter.cpp20
-rw-r--r--lib/CodeGen/AsmPrinter/EHStreamer.cpp2
-rw-r--r--lib/CodeGen/CMakeLists.txt1
-rw-r--r--lib/CodeGen/CodeGen.cpp1
-rw-r--r--lib/CodeGen/CodeGenPrepare.cpp612
-rw-r--r--lib/CodeGen/CriticalAntiDepBreaker.cpp2
-rw-r--r--lib/CodeGen/GlobalISel/Localizer.cpp10
-rw-r--r--lib/CodeGen/ImplicitNullChecks.cpp16
-rw-r--r--lib/CodeGen/LiveRangeShrink.cpp231
-rw-r--r--lib/CodeGen/MIRParser/MIRParser.cpp2
-rw-r--r--lib/CodeGen/MIRPrinter.cpp2
-rw-r--r--lib/CodeGen/MachineBasicBlock.cpp7
-rw-r--r--lib/CodeGen/MachineInstr.cpp86
-rw-r--r--lib/CodeGen/MachineModuleInfo.cpp65
-rw-r--r--lib/CodeGen/SelectionDAG/DAGCombiner.cpp132
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp70
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeTypes.h1
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp278
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp1
-rw-r--r--lib/CodeGen/TargetLoweringBase.cpp8
-rw-r--r--lib/CodeGen/TargetPassConfig.cpp17
-rw-r--r--lib/DebugInfo/CodeView/CVSymbolVisitor.cpp2
-rw-r--r--lib/DebugInfo/CodeView/CVTypeVisitor.cpp4
-rw-r--r--lib/DebugInfo/CodeView/EnumTables.cpp4
-rw-r--r--lib/DebugInfo/CodeView/SymbolDumper.cpp2
-rw-r--r--lib/DebugInfo/CodeView/TypeDumpVisitor.cpp4
-rw-r--r--lib/DebugInfo/DWARF/DWARFContext.cpp8
-rw-r--r--lib/DebugInfo/PDB/Native/InfoStream.cpp1
-rw-r--r--lib/DebugInfo/PDB/PDBContext.cpp3
-rw-r--r--lib/Fuzzer/test/dump_coverage.test8
-rw-r--r--lib/IR/Attributes.cpp45
-rw-r--r--lib/IR/Function.cpp64
-rw-r--r--lib/IR/Instructions.cpp32
-rw-r--r--lib/LTO/LTOBackend.cpp15
-rw-r--r--lib/MC/MCCodeView.cpp2
-rw-r--r--lib/Object/MachOObjectFile.cpp2
-rw-r--r--lib/Object/WindowsResource.cpp156
-rw-r--r--lib/ObjectYAML/CMakeLists.txt3
-rw-r--r--lib/ObjectYAML/CodeViewYAMLDebugSections.cpp127
-rw-r--r--lib/ObjectYAML/CodeViewYAMLSymbols.cpp496
-rw-r--r--lib/ObjectYAML/CodeViewYAMLTypes.cpp712
-rw-r--r--lib/ObjectYAML/LLVMBuild.txt2
-rw-r--r--lib/Passes/PassBuilder.cpp141
-rw-r--r--lib/Support/BinaryStreamReader.cpp20
-rw-r--r--lib/Support/Unix/Path.inc5
-rw-r--r--lib/TableGen/Record.cpp19
-rw-r--r--lib/TableGen/TGParser.cpp8
-rw-r--r--lib/TableGen/TGParser.h2
-rw-r--r--lib/Target/AArch64/AArch64.td2
-rw-r--r--lib/Target/AArch64/AArch64SchedM1.td340
-rw-r--r--lib/Target/AArch64/AArch64TargetMachine.cpp6
-rw-r--r--lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp55
-rw-r--r--lib/Target/AMDGPU/AMDGPUTargetMachine.cpp10
-rw-r--r--lib/Target/AMDGPU/AMDGPUTargetMachine.h5
-rw-r--r--lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp324
-rw-r--r--lib/Target/AMDGPU/DSInstructions.td6
-rw-r--r--lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp106
-rw-r--r--lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h2
-rw-r--r--lib/Target/AMDGPU/SIDefines.h40
-rw-r--r--lib/Target/AMDGPU/SIInsertWaitcnts.cpp26
-rw-r--r--lib/Target/AMDGPU/SIInstrInfo.td13
-rw-r--r--lib/Target/AMDGPU/SIRegisterInfo.h6
-rw-r--r--lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp13
-rw-r--r--lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.h6
-rw-r--r--lib/Target/ARM/ARMExpandPseudoInsts.cpp132
-rw-r--r--lib/Target/ARM/ARMFrameLowering.cpp5
-rw-r--r--lib/Target/ARM/ARMInstrThumb.td3
-rw-r--r--lib/Target/ARM/ARMInstrThumb2.td3
-rw-r--r--lib/Target/ARM/ARMTargetMachine.cpp4
-rw-r--r--lib/Target/ARM/ARMTargetMachine.h4
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp9
-rw-r--r--lib/Target/ARM/Thumb1FrameLowering.cpp9
-rw-r--r--lib/Target/AVR/AVRISelLowering.cpp4
-rw-r--r--lib/Target/AVR/AVRInstrInfo.td2
-rw-r--r--lib/Target/AVR/AVRTargetMachine.cpp4
-rw-r--r--lib/Target/AVR/AVRTargetMachine.h4
-rw-r--r--lib/Target/BPF/BPFTargetMachine.cpp4
-rw-r--r--lib/Target/BPF/CMakeLists.txt2
-rw-r--r--lib/Target/Hexagon/HexagonISelDAGToDAG.cpp189
-rw-r--r--lib/Target/Hexagon/HexagonISelLowering.cpp6
-rw-r--r--lib/Target/Hexagon/HexagonInstrInfo.cpp170
-rw-r--r--lib/Target/Hexagon/HexagonInstrInfo.h5
-rw-r--r--lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp8
-rw-r--r--lib/Target/Hexagon/HexagonPatterns.td59
-rw-r--r--lib/Target/Hexagon/HexagonTargetMachine.cpp4
-rw-r--r--lib/Target/Hexagon/HexagonVLIWPacketizer.cpp49
-rw-r--r--lib/Target/Lanai/LanaiTargetMachine.cpp4
-rw-r--r--lib/Target/Lanai/LanaiTargetMachine.h4
-rw-r--r--lib/Target/MSP430/MSP430TargetMachine.cpp4
-rw-r--r--lib/Target/Mips/Mips16FrameLowering.cpp24
-rw-r--r--lib/Target/Mips/MipsTargetMachine.cpp4
-rw-r--r--lib/Target/Mips/MipsTargetMachine.h4
-rw-r--r--lib/Target/NVPTX/NVPTXTargetMachine.cpp4
-rw-r--r--lib/Target/NVPTX/NVPTXTargetMachine.h3
-rw-r--r--lib/Target/PowerPC/PPCISelDAGToDAG.cpp298
-rw-r--r--lib/Target/PowerPC/PPCISelLowering.cpp110
-rw-r--r--lib/Target/PowerPC/PPCISelLowering.h8
-rw-r--r--lib/Target/PowerPC/PPCInstr64Bit.td12
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.cpp4
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.h1
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.td5
-rw-r--r--lib/Target/PowerPC/PPCInstrVSX.td4
-rw-r--r--lib/Target/PowerPC/PPCTargetMachine.cpp4
-rw-r--r--lib/Target/PowerPC/PPCTargetMachine.h4
-rw-r--r--lib/Target/PowerPC/PPCTargetTransformInfo.cpp20
-rw-r--r--lib/Target/PowerPC/PPCTargetTransformInfo.h1
-rw-r--r--lib/Target/RISCV/RISCVTargetMachine.cpp2
-rw-r--r--lib/Target/Sparc/SparcTargetMachine.cpp4
-rw-r--r--lib/Target/Sparc/SparcTargetMachine.h4
-rw-r--r--lib/Target/SystemZ/SystemZTargetMachine.cpp4
-rw-r--r--lib/Target/SystemZ/SystemZTargetMachine.h2
-rw-r--r--lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp4
-rw-r--r--lib/Target/X86/InstPrinter/X86InstComments.cpp4
-rw-r--r--lib/Target/X86/X86FloatingPoint.cpp34
-rw-r--r--lib/Target/X86/X86FrameLowering.cpp9
-rw-r--r--lib/Target/X86/X86ISelDAGToDAG.cpp2
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp266
-rw-r--r--lib/Target/X86/X86ISelLowering.h2
-rw-r--r--lib/Target/X86/X86InstrInfo.cpp1
-rw-r--r--lib/Target/X86/X86TargetMachine.cpp5
-rw-r--r--lib/Target/X86/X86TargetMachine.h4
-rw-r--r--lib/Target/XCore/XCoreTargetMachine.cpp4
-rw-r--r--lib/Transforms/Coroutines/CoroCleanup.cpp4
-rw-r--r--lib/Transforms/Coroutines/CoroEarly.cpp4
-rw-r--r--lib/Transforms/Coroutines/CoroElide.cpp4
-rw-r--r--lib/Transforms/Coroutines/CoroSplit.cpp4
-rw-r--r--lib/Transforms/IPO/PartialInlining.cpp23
-rw-r--r--lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp20
-rw-r--r--lib/Transforms/InstCombine/InstCombineCalls.cpp10
-rw-r--r--lib/Transforms/Instrumentation/PGOInstrumentation.cpp64
-rw-r--r--lib/Transforms/Instrumentation/SanitizerCoverage.cpp140
-rw-r--r--lib/Transforms/Scalar/CorrelatedValuePropagation.cpp9
-rw-r--r--lib/Transforms/Scalar/GVN.cpp164
-rw-r--r--lib/Transforms/Scalar/LowerExpectIntrinsic.cpp16
-rw-r--r--lib/Transforms/Scalar/NewGVN.cpp38
-rw-r--r--lib/Transforms/Utils/CodeExtractor.cpp83
-rw-r--r--lib/Transforms/Utils/PredicateInfo.cpp35
-rw-r--r--lib/Transforms/Utils/SimplifyLibCalls.cpp14
-rw-r--r--lib/Transforms/Vectorize/LoopVectorize.cpp29
-rw-r--r--test/Analysis/CFLAliasAnalysis/Andersen/struct.ll18
-rw-r--r--test/Bitcode/thinlto-function-summary-callgraph.ll13
-rw-r--r--test/CodeGen/AArch64/GlobalISel/localizer.mir49
-rw-r--r--test/CodeGen/AArch64/GlobalISel/select-pr32733.mir1
-rw-r--r--test/CodeGen/AArch64/addcarry-crash.ll23
-rw-r--r--test/CodeGen/AArch64/misched-fusion-aes.ll70
-rw-r--r--test/CodeGen/AArch64/pr33172.ll32
-rw-r--r--test/CodeGen/AMDGPU/llvm.amdgcn.ds.swizzle.ll2
-rw-r--r--test/CodeGen/AMDGPU/merge-m0.mir1
-rw-r--r--test/CodeGen/AMDGPU/sdwa-scalar-ops.mir2
-rw-r--r--test/CodeGen/AMDGPU/waitcnt-permute.mir33
-rw-r--r--test/CodeGen/ARM/cmpxchg-O0.ll9
-rw-r--r--test/CodeGen/ARM/v6-jumptable-clobber.mir2
-rw-r--r--test/CodeGen/AVR/rot.ll4
-rw-r--r--test/CodeGen/Hexagon/invalid-dotnew-attempt.mir17
-rw-r--r--test/CodeGen/Hexagon/loop-idiom/pmpy-long-loop.ll62
-rw-r--r--test/CodeGen/Hexagon/mul64-sext.ll93
-rw-r--r--test/CodeGen/MIR/Generic/multiRunPass.mir4
-rw-r--r--test/CodeGen/Mips/compactbranches/empty-block.mir1
-rw-r--r--test/CodeGen/PowerPC/expand-isel.ll15
-rw-r--r--test/CodeGen/PowerPC/logic-ops-on-compares.ll130
-rw-r--r--test/CodeGen/PowerPC/memCmpUsedInZeroEqualityComparison.ll121
-rw-r--r--test/CodeGen/PowerPC/memcmp.ll87
-rw-r--r--test/CodeGen/PowerPC/memcmpIR.ll194
-rw-r--r--test/CodeGen/PowerPC/ppc64-get-cache-line-size.ll49
-rw-r--r--test/CodeGen/PowerPC/pristine-and-livein.mir330
-rw-r--r--test/CodeGen/PowerPC/testComparesieqsll.ll134
-rw-r--r--test/CodeGen/PowerPC/testComparesiequll.ll134
-rw-r--r--test/CodeGen/PowerPC/testCompareslleqsll.ll133
-rw-r--r--test/CodeGen/PowerPC/testComparesllequll.ll133
-rw-r--r--test/CodeGen/PowerPC/vec_xxpermdi.ll307
-rw-r--r--test/CodeGen/Thumb2/tbb-removeadd.mir1
-rw-r--r--test/CodeGen/X86/2007-01-08-InstrSched.ll4
-rw-r--r--test/CodeGen/X86/GlobalISel/irtranslator-call.ll1
-rw-r--r--test/CodeGen/X86/add-of-carry.ll6
-rw-r--r--test/CodeGen/X86/addcarry.ll21
-rw-r--r--test/CodeGen/X86/avg.ll833
-rw-r--r--test/CodeGen/X86/avx.ll2
-rw-r--r--test/CodeGen/X86/avx512-cmp-kor-sequence.ll6
-rw-r--r--test/CodeGen/X86/avx512-gather-scatter-intrin.ll10
-rw-r--r--test/CodeGen/X86/avx512-intrinsics-upgrade.ll44
-rw-r--r--test/CodeGen/X86/avx512-intrinsics.ll83
-rw-r--r--test/CodeGen/X86/avx512-mask-spills.ll40
-rw-r--r--test/CodeGen/X86/avx512bw-intrinsics-upgrade.ll12
-rw-r--r--test/CodeGen/X86/avx512bw-intrinsics.ll16
-rw-r--r--test/CodeGen/X86/avx512bwvl-intrinsics-upgrade.ll24
-rw-r--r--test/CodeGen/X86/avx512cdvl-intrinsics-upgrade.ll2
-rw-r--r--test/CodeGen/X86/avx512cdvl-intrinsics.ll2
-rw-r--r--test/CodeGen/X86/avx512dq-intrinsics-upgrade.ll2
-rw-r--r--test/CodeGen/X86/avx512dq-intrinsics.ll4
-rw-r--r--test/CodeGen/X86/avx512dqvl-intrinsics-upgrade.ll10
-rw-r--r--test/CodeGen/X86/avx512dqvl-intrinsics.ll4
-rw-r--r--test/CodeGen/X86/avx512ifma-intrinsics.ll8
-rw-r--r--test/CodeGen/X86/avx512ifmavl-intrinsics.ll16
-rw-r--r--test/CodeGen/X86/avx512vl-intrinsics-upgrade.ll64
-rw-r--r--test/CodeGen/X86/avx512vl-intrinsics.ll28
-rw-r--r--test/CodeGen/X86/bitcast-and-setcc-128.ll631
-rw-r--r--test/CodeGen/X86/bitcast-and-setcc-256.ll823
-rw-r--r--test/CodeGen/X86/bitcast-setcc-128.ll637
-rw-r--r--test/CodeGen/X86/bitcast-setcc-256.ll254
-rw-r--r--test/CodeGen/X86/bswap_tree2.ll35
-rw-r--r--test/CodeGen/X86/eh-unknown.ll32
-rw-r--r--test/CodeGen/X86/fmsubadd-combine.ll8
-rw-r--r--test/CodeGen/X86/fold-tied-op.ll7
-rw-r--r--test/CodeGen/X86/fp128-i128.ll2
-rw-r--r--test/CodeGen/X86/gnu-seh-nolpads.ll34
-rw-r--r--test/CodeGen/X86/implicit-null-checks.mir22
-rw-r--r--test/CodeGen/X86/lrshrink.ll57
-rw-r--r--test/CodeGen/X86/madd.ll34
-rw-r--r--test/CodeGen/X86/misched-matrix.ll4
-rw-r--r--test/CodeGen/X86/mul-constant-i16.ll141
-rw-r--r--test/CodeGen/X86/mul-constant-i32.ll1589
-rw-r--r--test/CodeGen/X86/mul-constant-i64.ll1612
-rw-r--r--test/CodeGen/X86/oddshuffles.ll34
-rw-r--r--test/CodeGen/X86/pmul.ll55
-rw-r--r--test/CodeGen/X86/pr32284.ll206
-rw-r--r--test/CodeGen/X86/pr32610.ll40
-rw-r--r--test/CodeGen/X86/rotate.ll16
-rw-r--r--test/CodeGen/X86/sad.ll929
-rw-r--r--test/CodeGen/X86/select.ll28
-rw-r--r--test/CodeGen/X86/setcc-lowering.ll61
-rw-r--r--test/CodeGen/X86/setcc-wide-types.ll56
-rw-r--r--test/CodeGen/X86/shrink_vmul_sse.ll2
-rw-r--r--test/CodeGen/X86/sse41.ll8
-rw-r--r--test/CodeGen/X86/vector-bitreverse.ll6
-rw-r--r--test/CodeGen/X86/vector-blend.ll4
-rw-r--r--test/CodeGen/X86/x86-interleaved-access.ll14
-rw-r--r--test/CodeGen/X86/xchg-nofold.ll24
-rw-r--r--test/DebugInfo/MIR/X86/empty-inline.mir1
-rw-r--r--test/DebugInfo/omit-empty.ll1
-rw-r--r--test/Instrumentation/SanitizerCoverage/coverage-dbg.ll4
-rw-r--r--test/Instrumentation/SanitizerCoverage/coverage.ll11
-rw-r--r--test/Instrumentation/SanitizerCoverage/seh.ll1
-rw-r--r--test/MC/AMDGPU/ds-err.s90
-rw-r--r--test/MC/AMDGPU/ds.s144
-rw-r--r--test/MC/ARM/big-endian-thumb-fixup.s1
-rw-r--r--test/MC/ARM/mixed-arm-thumb-bl-fixup.ll77
-rw-r--r--test/MC/Disassembler/AMDGPU/gfx8_dasm_all.txt20
-rw-r--r--test/Other/new-pm-defaults.ll8
-rw-r--r--test/Other/new-pm-thinlto-defaults.ll221
-rw-r--r--test/ThinLTO/X86/newpm-basic.ll (renamed from test/ThinLTO/X86/error-newpm.ll)6
-rw-r--r--test/Transforms/CodeExtractor/PartialInlineAlloca.ll68
-rw-r--r--test/Transforms/CodeExtractor/PartialInlineAlloca2.ll65
-rw-r--r--test/Transforms/CodeExtractor/PartialInlineAlloca4.ll67
-rw-r--r--test/Transforms/CodeExtractor/PartialInlineAlloca5.ll67
-rw-r--r--test/Transforms/CodeExtractor/PartialInlineLiveAcross.ll61
-rw-r--r--test/Transforms/CodeExtractor/PartialInlineNoLiveOut.ll62
-rw-r--r--test/Transforms/GVN/PRE/phi-translate-2.ll105
-rw-r--r--test/Transforms/GVN/PRE/pre-gep-load.ll2
-rw-r--r--test/Transforms/GVN/PRE/pre-load.ll6
-rw-r--r--test/Transforms/Inline/AArch64/gep-cost.ll25
-rw-r--r--test/Transforms/InstCombine/ctpop.ll16
-rw-r--r--test/Transforms/InstCombine/intrinsics.ll28
-rw-r--r--test/Transforms/LoopVectorize/AArch64/no_vector_instructions.ll49
-rw-r--r--test/Transforms/LowerExpectIntrinsic/expect_nonboolean.ll104
-rw-r--r--test/Transforms/NewGVN/completeness.ll17
-rw-r--r--test/Transforms/NewGVN/pr33185.ll59
-rw-r--r--test/Transforms/PGOProfile/branch1.ll5
-rw-r--r--test/Transforms/ThinLTOBitcodeWriter/new-pm.ll9
-rw-r--r--test/Transforms/Util/PredicateInfo/condprop.ll7
-rw-r--r--test/Transforms/Util/PredicateInfo/testandor.ll27
-rw-r--r--test/tools/llvm-config/cflags.test2
-rw-r--r--test/tools/llvm-cvtres/Inputs/test_resource.rc6
-rw-r--r--test/tools/llvm-cvtres/Inputs/test_resource.resbin2200 -> 2332 bytes
-rw-r--r--test/tools/llvm-cvtres/resource.test46
-rw-r--r--tools/bugpoint/OptimizerDriver.cpp11
-rw-r--r--tools/llvm-config/BuildVariables.inc.in1
-rw-r--r--tools/llvm-config/llvm-config.cpp4
-rw-r--r--tools/llvm-cvtres/llvm-cvtres.cpp32
-rw-r--r--tools/llvm-dwarfdump/llvm-dwarfdump.cpp6
-rw-r--r--tools/llvm-objdump/MachODump.cpp5
-rw-r--r--tools/llvm-objdump/llvm-objdump.cpp5
-rw-r--r--tools/llvm-pdbdump/Analyze.cpp2
-rw-r--r--tools/llvm-pdbdump/CMakeLists.txt3
-rw-r--r--tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp2
-rw-r--r--tools/llvm-pdbdump/PdbYaml.cpp200
-rw-r--r--tools/llvm-pdbdump/PdbYaml.h207
-rw-r--r--tools/llvm-pdbdump/YAMLOutputStyle.cpp43
-rw-r--r--tools/llvm-pdbdump/YAMLOutputStyle.h2
-rw-r--r--tools/llvm-pdbdump/YamlSerializationContext.h39
-rw-r--r--tools/llvm-pdbdump/YamlSymbolDumper.cpp413
-rw-r--r--tools/llvm-pdbdump/YamlSymbolDumper.h66
-rw-r--r--tools/llvm-pdbdump/YamlTypeDumper.cpp589
-rw-r--r--tools/llvm-pdbdump/YamlTypeDumper.h116
-rw-r--r--tools/llvm-pdbdump/llvm-pdbdump.cpp17
-rw-r--r--tools/llvm-readobj/ELFDumper.cpp1
-rw-r--r--tools/obj2yaml/macho2yaml.cpp2
-rw-r--r--tools/opt/NewPMDriver.cpp15
-rw-r--r--tools/opt/NewPMDriver.h10
-rw-r--r--tools/opt/opt.cpp6
-rw-r--r--unittests/ADT/ArrayRefTest.cpp30
-rw-r--r--unittests/IR/AttributesTest.cpp7
-rw-r--r--unittests/Support/TargetParserTest.cpp4
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp45
-rw-r--r--utils/TableGen/AsmWriterEmitter.cpp46
-rw-r--r--utils/TableGen/Attributes.cpp4
-rw-r--r--utils/TableGen/CodeEmitterGen.cpp14
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp6
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.h8
-rw-r--r--utils/TableGen/CodeGenRegisters.cpp7
-rw-r--r--utils/TableGen/CodeGenRegisters.h4
-rw-r--r--utils/TableGen/CodeGenSchedule.cpp2
-rw-r--r--utils/TableGen/FixedLenDecoderEmitter.cpp15
-rw-r--r--utils/TableGen/GlobalISelEmitter.cpp2
-rw-r--r--utils/TableGen/OptParserEmitter.cpp34
-rw-r--r--utils/TableGen/RegisterBankEmitter.cpp2
-rw-r--r--utils/TableGen/RegisterInfoEmitter.cpp7
-rw-r--r--utils/TableGen/SearchableTableEmitter.cpp4
-rw-r--r--utils/TableGen/SubtargetEmitter.cpp16
-rw-r--r--utils/TableGen/X86FoldTablesEmitter.cpp4
378 files changed, 12474 insertions, 9898 deletions
diff --git a/docs/Vectorizers.rst b/docs/Vectorizers.rst
index 317271af4032..92d6200e169f 100644
--- a/docs/Vectorizers.rst
+++ b/docs/Vectorizers.rst
@@ -44,12 +44,12 @@ Users can control the vectorization SIMD width using the command line flag "-for
$ clang -mllvm -force-vector-width=8 ...
$ opt -loop-vectorize -force-vector-width=8 ...
-Users can control the unroll factor using the command line flag "-force-vector-unroll"
+Users can control the unroll factor using the command line flag "-force-vector-interleave"
.. code-block:: console
- $ clang -mllvm -force-vector-unroll=2 ...
- $ opt -loop-vectorize -force-vector-unroll=2 ...
+ $ clang -mllvm -force-vector-interleave=2 ...
+ $ opt -loop-vectorize -force-vector-interleave=2 ...
Pragma loop hint directives
^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h
index 6cbe3a1f515e..7211508e975a 100644
--- a/include/llvm/Analysis/TargetTransformInfo.h
+++ b/include/llvm/Analysis/TargetTransformInfo.h
@@ -454,6 +454,9 @@ public:
/// \brief Don't restrict interleaved unrolling to small loops.
bool enableAggressiveInterleaving(bool LoopHasReductions) const;
+ /// \brief Enable inline expansion of memcmp
+ bool expandMemCmp(Instruction *I, unsigned &MaxLoadSize) const;
+
/// \brief Enable matching of interleaved access groups.
bool enableInterleavedAccessVectorization() const;
@@ -828,6 +831,7 @@ public:
unsigned VF) = 0;
virtual bool supportsEfficientVectorElementLoadStore() = 0;
virtual bool enableAggressiveInterleaving(bool LoopHasReductions) = 0;
+ virtual bool expandMemCmp(Instruction *I, unsigned &MaxLoadSize) = 0;
virtual bool enableInterleavedAccessVectorization() = 0;
virtual bool isFPVectorizationPotentiallyUnsafe() = 0;
virtual bool allowsMisalignedMemoryAccesses(LLVMContext &Context,
@@ -1047,6 +1051,9 @@ public:
bool enableAggressiveInterleaving(bool LoopHasReductions) override {
return Impl.enableAggressiveInterleaving(LoopHasReductions);
}
+ bool expandMemCmp(Instruction *I, unsigned &MaxLoadSize) override {
+ return Impl.expandMemCmp(I, MaxLoadSize);
+ }
bool enableInterleavedAccessVectorization() override {
return Impl.enableInterleavedAccessVectorization();
}
diff --git a/include/llvm/Analysis/TargetTransformInfoImpl.h b/include/llvm/Analysis/TargetTransformInfoImpl.h
index ad1a7cb748fe..d73a60eba850 100644
--- a/include/llvm/Analysis/TargetTransformInfoImpl.h
+++ b/include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -274,6 +274,8 @@ public:
bool enableAggressiveInterleaving(bool LoopHasReductions) { return false; }
+ bool expandMemCmp(Instruction *I, unsigned &MaxLoadSize) { return false; }
+
bool enableInterleavedAccessVectorization() { return false; }
bool isFPVectorizationPotentiallyUnsafe() { return false; }
diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h
index b1ee76159c4b..612779b1ce86 100644
--- a/include/llvm/Analysis/ValueTracking.h
+++ b/include/llvm/Analysis/ValueTracking.h
@@ -85,6 +85,8 @@ template <typename T> class ArrayRef;
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
+ bool isOnlyUsedInZeroEqualityComparison(const Instruction *CxtI);
+
/// Return true if the given value is known to be non-zero when defined. For
/// vectors, return true if every element is known to be non-zero when
/// defined. For pointers, if the context instruction and dominator tree are
diff --git a/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h
index f32233b3a9e4..e3549d8988cd 100644
--- a/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h
+++ b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h
@@ -396,7 +396,7 @@ protected:
mutable DenseMap<unsigned, std::unique_ptr<const InstructionMapping>>
MapOfInstructionMappings;
- /// Create a RegisterBankInfo that can accomodate up to \p NumRegBanks
+ /// Create a RegisterBankInfo that can accommodate up to \p NumRegBanks
/// RegisterBank instances.
RegisterBankInfo(RegisterBank **RegBanks, unsigned NumRegBanks);
diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h
index 2300a106c358..bc5d2353f63e 100644
--- a/include/llvm/CodeGen/ISDOpcodes.h
+++ b/include/llvm/CodeGen/ISDOpcodes.h
@@ -410,12 +410,22 @@ namespace ISD {
/// then the result type must also be a vector type.
SETCC,
- /// Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, but
+ /// Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, and
/// op #2 is a *carry value*. This operator checks the result of
/// "LHS - RHS - Carry", and can be used to compare two wide integers:
/// (setcce lhshi rhshi (subc lhslo rhslo) cc). Only valid for integers.
+ /// FIXME: This node is deprecated in favor of SETCCCARRY.
+ /// It is kept around for now to provide a smooth transition path
+ /// toward the use of SETCCCARRY and will eventually be removed.
SETCCE,
+ /// Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, but
+ /// op #2 is a boolean indicating if there is an incoming carry. This
+ /// operator checks the result of "LHS - RHS - Carry", and can be used to
+ /// compare two wide integers: (setcce lhshi rhshi (subc lhslo rhslo) cc).
+ /// Only valid for integers.
+ SETCCCARRY,
+
/// SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded
/// integer shift operations. The operation ordering is:
/// [Lo,Hi] = op [LoLHS,HiLHS], Amt
diff --git a/include/llvm/CodeGen/MIRYamlMapping.h b/include/llvm/CodeGen/MIRYamlMapping.h
index 47b40de6fe1f..30e88fe38ac3 100644
--- a/include/llvm/CodeGen/MIRYamlMapping.h
+++ b/include/llvm/CodeGen/MIRYamlMapping.h
@@ -381,7 +381,6 @@ struct MachineFunction {
StringRef Name;
unsigned Alignment = 0;
bool ExposesReturnsTwice = false;
- bool NoVRegs;
// GISel MachineFunctionProperties.
bool Legalized = false;
bool RegBankSelected = false;
@@ -406,7 +405,6 @@ template <> struct MappingTraits<MachineFunction> {
YamlIO.mapRequired("name", MF.Name);
YamlIO.mapOptional("alignment", MF.Alignment);
YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice);
- YamlIO.mapOptional("noVRegs", MF.NoVRegs);
YamlIO.mapOptional("legalized", MF.Legalized);
YamlIO.mapOptional("regBankSelected", MF.RegBankSelected);
YamlIO.mapOptional("selected", MF.Selected);
diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h
index 8da48c379d00..26ed8bb487a2 100644
--- a/include/llvm/CodeGen/MachineBasicBlock.h
+++ b/include/llvm/CodeGen/MachineBasicBlock.h
@@ -335,6 +335,9 @@ public:
return make_range(livein_begin(), livein_end());
}
+ /// Remove entry from the livein set and return iterator to the next.
+ livein_iterator removeLiveIn(livein_iterator I);
+
/// Get the clobber mask for the start of this basic block. Funclets use this
/// to prevent register allocation across funclet transitions.
const uint32_t *getBeginClobberMask(const TargetRegisterInfo *TRI) const;
diff --git a/include/llvm/CodeGen/MachineConstantPool.h b/include/llvm/CodeGen/MachineConstantPool.h
index d2036c4a29a5..1705a0f7e59b 100644
--- a/include/llvm/CodeGen/MachineConstantPool.h
+++ b/include/llvm/CodeGen/MachineConstantPool.h
@@ -1,4 +1,4 @@
-//===-- CodeGen/MachineConstantPool.h - Abstract Constant Pool --*- C++ -*-===//
+//===- CodeGen/MachineConstantPool.h - Abstract Constant Pool ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,29 +18,28 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/MC/SectionKind.h"
-#include <cassert>
#include <climits>
#include <vector>
namespace llvm {
class Constant;
-class FoldingSetNodeID;
class DataLayout;
-class TargetMachine;
-class Type;
+class FoldingSetNodeID;
class MachineConstantPool;
class raw_ostream;
+class Type;
/// Abstract base class for all machine specific constantpool value subclasses.
///
class MachineConstantPoolValue {
virtual void anchor();
+
Type *Ty;
public:
explicit MachineConstantPoolValue(Type *ty) : Ty(ty) {}
- virtual ~MachineConstantPoolValue() {}
+ virtual ~MachineConstantPoolValue() = default;
/// getType - get type of this MachineConstantPoolValue.
///
@@ -81,6 +80,7 @@ public:
: Alignment(A) {
Val.ConstVal = V;
}
+
MachineConstantPoolEntry(MachineConstantPoolValue *V, unsigned A)
: Alignment(A) {
Val.MachineCPVal = V;
@@ -153,13 +153,12 @@ public:
/// print - Used by the MachineFunction printer to print information about
/// constant pool objects. Implemented in MachineFunction.cpp
- ///
void print(raw_ostream &OS) const;
/// dump - Call print(cerr) to be called from the debugger.
void dump() const;
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_MACHINECONSTANTPOOL_H
diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h
index 5859a4e61fdd..10125864cd90 100644
--- a/include/llvm/CodeGen/MachineFunction.h
+++ b/include/llvm/CodeGen/MachineFunction.h
@@ -1,4 +1,4 @@
-//===-- llvm/CodeGen/MachineFunction.h --------------------------*- C++ -*-===//
+//===- llvm/CodeGen/MachineFunction.h ---------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,38 +18,61 @@
#ifndef LLVM_CODEGEN_MACHINEFUNCTION_H
#define LLVM_CODEGEN_MACHINEFUNCTION_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/iterator.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/EHPersonalities.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/IR/DebugLoc.h"
+#include "llvm/IR/Instructions.h"
#include "llvm/IR/Metadata.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/ArrayRecycler.h"
+#include "llvm/Support/AtomicOrdering.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Recycler.h"
+#include <cassert>
+#include <cstdint>
+#include <memory>
+#include <utility>
+#include <vector>
namespace llvm {
-class Value;
+class BasicBlock;
+class BlockAddress;
+class DataLayout;
+class DIExpression;
+class DILocalVariable;
+class DILocation;
class Function;
-class GCModuleInfo;
-class MachineRegisterInfo;
-class MachineFrameInfo;
+class GlobalValue;
class MachineConstantPool;
+class MachineFrameInfo;
+class MachineFunction;
class MachineJumpTableInfo;
class MachineModuleInfo;
+class MachineRegisterInfo;
class MCContext;
+class MCInstrDesc;
class Pass;
class PseudoSourceValueManager;
+class raw_ostream;
+class SlotIndexes;
class TargetMachine;
-class TargetSubtargetInfo;
class TargetRegisterClass;
-struct MachinePointerInfo;
+class TargetSubtargetInfo;
struct WinEHFuncInfo;
template <> struct ilist_alloc_traits<MachineBasicBlock> {
@@ -137,27 +160,33 @@ public:
bool hasProperty(Property P) const {
return Properties[static_cast<unsigned>(P)];
}
+
MachineFunctionProperties &set(Property P) {
Properties.set(static_cast<unsigned>(P));
return *this;
}
+
MachineFunctionProperties &reset(Property P) {
Properties.reset(static_cast<unsigned>(P));
return *this;
}
+
/// Reset all the properties.
MachineFunctionProperties &reset() {
Properties.reset();
return *this;
}
+
MachineFunctionProperties &set(const MachineFunctionProperties &MFP) {
Properties |= MFP.Properties;
return *this;
}
+
MachineFunctionProperties &reset(const MachineFunctionProperties &MFP) {
Properties.reset(MFP.Properties);
return *this;
}
+
// Returns true if all properties set in V (i.e. required by a pass) are set
// in this.
bool verifyRequiredProperties(const MachineFunctionProperties &V) const {
@@ -180,18 +209,17 @@ struct SEHHandler {
const BlockAddress *RecoverBA;
};
-
/// This structure is used to retain landing pad info for the current function.
struct LandingPadInfo {
MachineBasicBlock *LandingPadBlock; // Landing pad block.
SmallVector<MCSymbol *, 1> BeginLabels; // Labels prior to invoke.
SmallVector<MCSymbol *, 1> EndLabels; // Labels after invoke.
SmallVector<SEHHandler, 1> SEHHandlers; // SEH handlers active at this lpad.
- MCSymbol *LandingPadLabel; // Label at beginning of landing pad.
- std::vector<int> TypeIds; // List of type ids (filters negative).
+ MCSymbol *LandingPadLabel = nullptr; // Label at beginning of landing pad.
+ std::vector<int> TypeIds; // List of type ids (filters negative).
explicit LandingPadInfo(MachineBasicBlock *MBB)
- : LandingPadBlock(MBB), LandingPadLabel(nullptr) {}
+ : LandingPadBlock(MBB) {}
};
class MachineFunction {
@@ -239,7 +267,7 @@ class MachineFunction {
Recycler<MachineBasicBlock> BasicBlockRecycler;
// List of machine basic blocks in function
- typedef ilist<MachineBasicBlock> BasicBlockListType;
+ using BasicBlockListType = ilist<MachineBasicBlock>;
BasicBlockListType BasicBlocks;
/// FunctionNumber - This provides a unique ID for each function emitted in
@@ -281,7 +309,7 @@ class MachineFunction {
std::vector<LandingPadInfo> LandingPads;
/// Map a landing pad's EH symbol to the call site indexes.
- DenseMap<MCSymbol*, SmallVector<unsigned, 4> > LPadToCallSiteMap;
+ DenseMap<MCSymbol*, SmallVector<unsigned, 4>> LPadToCallSiteMap;
/// Map of invoke call site index values to associated begin EH_LABEL.
DenseMap<MCSymbol*, unsigned> CallSiteMap;
@@ -303,9 +331,6 @@ class MachineFunction {
/// \}
- MachineFunction(const MachineFunction &) = delete;
- void operator=(const MachineFunction&) = delete;
-
/// Clear all the members of this MachineFunction, but the ones used
/// to initialize again the MachineFunction.
/// More specifically, this deallocates all the dynamically allocated
@@ -316,8 +341,8 @@ class MachineFunction {
/// In particular, the XXXInfo data structure.
/// \pre Fn, Target, MMI, and FunctionNumber are properly set.
void init();
-public:
+public:
struct VariableDbgInfo {
const DILocalVariable *Var;
const DIExpression *Expr;
@@ -328,11 +353,13 @@ public:
unsigned Slot, const DILocation *Loc)
: Var(Var), Expr(Expr), Slot(Slot), Loc(Loc) {}
};
- typedef SmallVector<VariableDbgInfo, 4> VariableDbgInfoMapTy;
+ using VariableDbgInfoMapTy = SmallVector<VariableDbgInfo, 4>;
VariableDbgInfoMapTy VariableDbgInfos;
MachineFunction(const Function *Fn, const TargetMachine &TM,
unsigned FunctionNum, MachineModuleInfo &MMI);
+ MachineFunction(const MachineFunction &) = delete;
+ MachineFunction &operator=(const MachineFunction &) = delete;
~MachineFunction();
/// Reset the instance as if it was just created.
@@ -350,19 +377,15 @@ public:
const DataLayout &getDataLayout() const;
/// getFunction - Return the LLVM function that this machine code represents
- ///
const Function *getFunction() const { return Fn; }
/// getName - Return the name of the corresponding LLVM function.
- ///
StringRef getName() const;
/// getFunctionNumber - Return a unique ID for the current function.
- ///
unsigned getFunctionNumber() const { return FunctionNumber; }
/// getTarget - Return the target machine this machine code is compiled with
- ///
const TargetMachine &getTarget() const { return Target; }
/// getSubtarget - Return the subtarget for which this machine code is being
@@ -378,14 +401,12 @@ public:
}
/// getRegInfo - Return information about the registers currently in use.
- ///
MachineRegisterInfo &getRegInfo() { return *RegInfo; }
const MachineRegisterInfo &getRegInfo() const { return *RegInfo; }
/// getFrameInfo - Return the frame info object for the current function.
/// This object contains information about objects allocated on the stack
/// frame of the current function in an abstract way.
- ///
MachineFrameInfo &getFrameInfo() { return *FrameInfo; }
const MachineFrameInfo &getFrameInfo() const { return *FrameInfo; }
@@ -402,7 +423,6 @@ public:
/// getConstantPool - Return the constant pool object for the current
/// function.
- ///
MachineConstantPool *getConstantPool() { return ConstantPool; }
const MachineConstantPool *getConstantPool() const { return ConstantPool; }
@@ -413,11 +433,9 @@ public:
WinEHFuncInfo *getWinEHFuncInfo() { return WinEHInfo; }
/// getAlignment - Return the alignment (log2, not bytes) of the function.
- ///
unsigned getAlignment() const { return Alignment; }
/// setAlignment - Set the alignment (log2, not bytes) of the function.
- ///
void setAlignment(unsigned A) { Alignment = A; }
/// ensureAlignment - Make sure the function is at least 1 << A bytes aligned.
@@ -487,7 +505,6 @@ public:
bool shouldSplitStack() const;
/// getNumBlockIDs - Return the number of MBB ID's allocated.
- ///
unsigned getNumBlockIDs() const { return (unsigned)MBBNumbering.size(); }
/// RenumberBlocks - This discards all of the MachineBasicBlock numbers and
@@ -499,7 +516,6 @@ public:
/// print - Print out the MachineFunction in a format suitable for debugging
/// to the specified stream.
- ///
void print(raw_ostream &OS, const SlotIndexes* = nullptr) const;
/// viewCFG - This function is meant for use from the debugger. You can just
@@ -507,7 +523,6 @@ public:
/// program, displaying the CFG of the current function with the code for each
/// basic block inside. This depends on there being a 'dot' and 'gv' program
/// in your path.
- ///
void viewCFG() const;
/// viewCFGOnly - This function is meant for use from the debugger. It works
@@ -518,7 +533,6 @@ public:
void viewCFGOnly() const;
/// dump - Print the current MachineFunction to cerr, useful for debugger use.
- ///
void dump() const;
/// Run the current MachineFunction through the machine code verifier, useful
@@ -528,10 +542,10 @@ public:
bool AbortOnError = true) const;
// Provide accessors for the MachineBasicBlock list...
- typedef BasicBlockListType::iterator iterator;
- typedef BasicBlockListType::const_iterator const_iterator;
- typedef BasicBlockListType::const_reverse_iterator const_reverse_iterator;
- typedef BasicBlockListType::reverse_iterator reverse_iterator;
+ using iterator = BasicBlockListType::iterator;
+ using const_iterator = BasicBlockListType::const_iterator;
+ using const_reverse_iterator = BasicBlockListType::const_reverse_iterator;
+ using reverse_iterator = BasicBlockListType::reverse_iterator;
/// Support for MachineBasicBlock::getNextNode().
static BasicBlockListType MachineFunction::*
@@ -590,11 +604,9 @@ public:
//===--------------------------------------------------------------------===//
// Internal functions used to automatically number MachineBasicBlocks
- //
/// \brief Adds the MBB to the internal numbering. Returns the unique number
/// assigned to the MBB.
- ///
unsigned addToMBBNumbering(MachineBasicBlock *MBB) {
MBBNumbering.push_back(MBB);
return (unsigned)MBBNumbering.size()-1;
@@ -610,7 +622,6 @@ public:
/// CreateMachineInstr - Allocate a new MachineInstr. Use this instead
/// of `new MachineInstr'.
- ///
MachineInstr *CreateMachineInstr(const MCInstrDesc &MCID, const DebugLoc &DL,
bool NoImp = false);
@@ -623,16 +634,13 @@ public:
MachineInstr *CloneMachineInstr(const MachineInstr *Orig);
/// DeleteMachineInstr - Delete the given MachineInstr.
- ///
void DeleteMachineInstr(MachineInstr *MI);
/// CreateMachineBasicBlock - Allocate a new MachineBasicBlock. Use this
/// instead of `new MachineBasicBlock'.
- ///
MachineBasicBlock *CreateMachineBasicBlock(const BasicBlock *bb = nullptr);
/// DeleteMachineBasicBlock - Delete the given MachineBasicBlock.
- ///
void DeleteMachineBasicBlock(MachineBasicBlock *MBB);
/// getMachineMemOperand - Allocate a new MachineMemOperand.
@@ -653,7 +661,7 @@ public:
MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO,
int64_t Offset, uint64_t Size);
- typedef ArrayRecycler<MachineOperand>::Capacity OperandCapacity;
+ using OperandCapacity = ArrayRecycler<MachineOperand>::Capacity;
/// Allocate an array of MachineOperands. This is only intended for use by
/// internal MachineInstr functions.
@@ -700,7 +708,6 @@ public:
//===--------------------------------------------------------------------===//
// Label Manipulation.
- //
/// getJTISymbol - Return the MCSymbol for the specified non-empty jump table.
/// If isLinkerPrivate is specified, an 'l' label is returned, otherwise a
@@ -858,13 +865,16 @@ template <> struct GraphTraits<MachineFunction*> :
static NodeRef getEntryNode(MachineFunction *F) { return &F->front(); }
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
- typedef pointer_iterator<MachineFunction::iterator> nodes_iterator;
+ using nodes_iterator = pointer_iterator<MachineFunction::iterator>;
+
static nodes_iterator nodes_begin(MachineFunction *F) {
return nodes_iterator(F->begin());
}
+
static nodes_iterator nodes_end(MachineFunction *F) {
return nodes_iterator(F->end());
}
+
static unsigned size (MachineFunction *F) { return F->size(); }
};
template <> struct GraphTraits<const MachineFunction*> :
@@ -872,37 +882,39 @@ template <> struct GraphTraits<const MachineFunction*> :
static NodeRef getEntryNode(const MachineFunction *F) { return &F->front(); }
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
- typedef pointer_iterator<MachineFunction::const_iterator> nodes_iterator;
+ using nodes_iterator = pointer_iterator<MachineFunction::const_iterator>;
+
static nodes_iterator nodes_begin(const MachineFunction *F) {
return nodes_iterator(F->begin());
}
+
static nodes_iterator nodes_end (const MachineFunction *F) {
return nodes_iterator(F->end());
}
+
static unsigned size (const MachineFunction *F) {
return F->size();
}
};
-
// Provide specializations of GraphTraits to be able to treat a function as a
// graph of basic blocks... and to walk it in inverse order. Inverse order for
// a function is considered to be when traversing the predecessor edges of a BB
// instead of the successor edges.
//
-template <> struct GraphTraits<Inverse<MachineFunction*> > :
- public GraphTraits<Inverse<MachineBasicBlock*> > {
+template <> struct GraphTraits<Inverse<MachineFunction*>> :
+ public GraphTraits<Inverse<MachineBasicBlock*>> {
static NodeRef getEntryNode(Inverse<MachineFunction *> G) {
return &G.Graph->front();
}
};
-template <> struct GraphTraits<Inverse<const MachineFunction*> > :
- public GraphTraits<Inverse<const MachineBasicBlock*> > {
+template <> struct GraphTraits<Inverse<const MachineFunction*>> :
+ public GraphTraits<Inverse<const MachineBasicBlock*>> {
static NodeRef getEntryNode(Inverse<const MachineFunction *> G) {
return &G.Graph->front();
}
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_MACHINEFUNCTION_H
diff --git a/include/llvm/CodeGen/MachineFunctionInitializer.h b/include/llvm/CodeGen/MachineFunctionInitializer.h
index c644c9783e2f..0fbcb480b1ab 100644
--- a/include/llvm/CodeGen/MachineFunctionInitializer.h
+++ b/include/llvm/CodeGen/MachineFunctionInitializer.h
@@ -1,4 +1,4 @@
-//===- MachineFunctionInitializer.h - machine function initializer ---------===//
+//=- MachineFunctionInitializer.h - machine function initializer --*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
@@ -25,7 +25,7 @@ class MachineFunctionInitializer {
virtual void anchor();
public:
- virtual ~MachineFunctionInitializer() {}
+ virtual ~MachineFunctionInitializer() = default;
/// Initialize the machine function.
///
@@ -35,4 +35,4 @@ public:
} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_MACHINEFUNCTIONINITIALIZER_H
diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h
index 8d040beff7a6..95401e98b297 100644
--- a/include/llvm/CodeGen/MachineInstr.h
+++ b/include/llvm/CodeGen/MachineInstr.h
@@ -1,4 +1,4 @@
-//===-- llvm/CodeGen/MachineInstr.h - MachineInstr class --------*- C++ -*-===//
+//===- llvm/CodeGen/MachineInstr.h - MachineInstr class ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,7 +17,6 @@
#define LLVM_CODEGEN_MACHINEINSTR_H
#include "llvm/ADT/DenseMapInfo.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator_range.h"
@@ -28,19 +27,27 @@
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/Support/ArrayRecycler.h"
#include "llvm/Target/TargetOpcodes.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <utility>
namespace llvm {
-class StringRef;
template <typename T> class ArrayRef;
-template <typename T> class SmallVectorImpl;
-class DILocalVariable;
class DIExpression;
+class DILocalVariable;
+class MachineBasicBlock;
+class MachineFunction;
+class MachineMemOperand;
+class MachineRegisterInfo;
+class ModuleSlotTracker;
+class raw_ostream;
+template <typename T> class SmallVectorImpl;
+class StringRef;
class TargetInstrInfo;
class TargetRegisterClass;
class TargetRegisterInfo;
-class MachineFunction;
-class MachineMemOperand;
//===----------------------------------------------------------------------===//
/// Representation of each machine instruction.
@@ -53,7 +60,7 @@ class MachineInstr
: public ilist_node_with_parent<MachineInstr, MachineBasicBlock,
ilist_sentinel_tracking<true>> {
public:
- typedef MachineMemOperand **mmo_iterator;
+ using mmo_iterator = MachineMemOperand **;
/// Flags to specify different kinds of comments to output in
/// assembly code. These flags carry semantic information not
@@ -72,43 +79,39 @@ public:
BundledPred = 1 << 2, // Instruction has bundled predecessors.
BundledSucc = 1 << 3 // Instruction has bundled successors.
};
+
private:
const MCInstrDesc *MCID; // Instruction descriptor.
- MachineBasicBlock *Parent; // Pointer to the owning basic block.
+ MachineBasicBlock *Parent = nullptr; // Pointer to the owning basic block.
// Operands are allocated by an ArrayRecycler.
- MachineOperand *Operands; // Pointer to the first operand.
- unsigned NumOperands; // Number of operands on instruction.
- typedef ArrayRecycler<MachineOperand>::Capacity OperandCapacity;
+ MachineOperand *Operands = nullptr; // Pointer to the first operand.
+ unsigned NumOperands = 0; // Number of operands on instruction.
+ using OperandCapacity = ArrayRecycler<MachineOperand>::Capacity;
OperandCapacity CapOperands; // Capacity of the Operands array.
- uint8_t Flags; // Various bits of additional
+ uint8_t Flags = 0; // Various bits of additional
// information about machine
// instruction.
- uint8_t AsmPrinterFlags; // Various bits of information used by
+ uint8_t AsmPrinterFlags = 0; // Various bits of information used by
// the AsmPrinter to emit helpful
// comments. This is *not* semantic
// information. Do not use this for
// anything other than to convey comment
// information to AsmPrinter.
- uint8_t NumMemRefs; // Information on memory references.
+ uint8_t NumMemRefs = 0; // Information on memory references.
// Note that MemRefs == nullptr, means 'don't know', not 'no memory access'.
// Calling code must treat missing information conservatively. If the number
// of memory operands required to be precise exceeds the maximum value of
// NumMemRefs - currently 256 - we remove the operands entirely. Note also
// that this is a non-owning reference to a shared copy on write buffer owned
// by the MachineFunction and created via MF.allocateMemRefsArray.
- mmo_iterator MemRefs;
+ mmo_iterator MemRefs = nullptr;
DebugLoc debugLoc; // Source line information.
- MachineInstr(const MachineInstr&) = delete;
- void operator=(const MachineInstr&) = delete;
- // Use MachineFunction::DeleteMachineInstr() instead.
- ~MachineInstr() = delete;
-
// Intrusive list support
friend struct ilist_traits<MachineInstr>;
friend struct ilist_callback_traits<MachineBasicBlock>;
@@ -128,6 +131,11 @@ private:
friend class MachineFunction;
public:
+ MachineInstr(const MachineInstr &) = delete;
+ MachineInstr &operator=(const MachineInstr &) = delete;
+ // Use MachineFunction::DeleteMachineInstr() instead.
+ ~MachineInstr() = delete;
+
const MachineBasicBlock* getParent() const { return Parent; }
MachineBasicBlock* getParent() { return Parent; }
@@ -178,7 +186,6 @@ public:
Flags &= ~((uint8_t)Flag);
}
-
/// Return true if MI is in a bundle (but not the first MI in a bundle).
///
/// A bundle looks like this before it's finalized:
@@ -263,7 +270,6 @@ public:
/// earlier.
///
/// If this method returns, the caller should try to recover from the error.
- ///
void emitError(StringRef Msg) const;
/// Returns the target instruction descriptor of this MachineInstr.
@@ -273,7 +279,6 @@ public:
unsigned getOpcode() const { return MCID->Opcode; }
/// Access to explicit operands of the instruction.
- ///
unsigned getNumOperands() const { return NumOperands; }
const MachineOperand& getOperand(unsigned i) const {
@@ -289,8 +294,8 @@ public:
unsigned getNumExplicitOperands() const;
/// iterator/begin/end - Iterate over all operands of a machine instruction.
- typedef MachineOperand *mop_iterator;
- typedef const MachineOperand *const_mop_iterator;
+ using mop_iterator = MachineOperand *;
+ using const_mop_iterator = const MachineOperand *;
mop_iterator operands_begin() { return Operands; }
mop_iterator operands_end() { return Operands + NumOperands; }
@@ -713,7 +718,6 @@ public:
return hasProperty(MCID::ExtraDefRegAllocReq, Type);
}
-
enum MICheckType {
CheckDefs, // Check all operands for equality
CheckKillDead, // Check all operands including kill / dead markers
@@ -767,6 +771,7 @@ public:
/// Returns true if the MachineInstr represents a label.
bool isLabel() const { return isEHLabel() || isGCLabel(); }
+
bool isCFIInstruction() const {
return getOpcode() == TargetOpcode::CFI_INSTRUCTION;
}
@@ -775,6 +780,7 @@ public:
bool isPosition() const { return isLabel() || isCFIInstruction(); }
bool isDebugValue() const { return getOpcode() == TargetOpcode::DBG_VALUE; }
+
/// A DBG_VALUE is indirect iff the first operand is a register and
/// the second operand is an immediate.
bool isIndirectDebugValue() const {
@@ -787,29 +793,38 @@ public:
bool isKill() const { return getOpcode() == TargetOpcode::KILL; }
bool isImplicitDef() const { return getOpcode()==TargetOpcode::IMPLICIT_DEF; }
bool isInlineAsm() const { return getOpcode() == TargetOpcode::INLINEASM; }
+
bool isMSInlineAsm() const {
return getOpcode() == TargetOpcode::INLINEASM && getInlineAsmDialect();
}
+
bool isStackAligningInlineAsm() const;
InlineAsm::AsmDialect getInlineAsmDialect() const;
+
bool isInsertSubreg() const {
return getOpcode() == TargetOpcode::INSERT_SUBREG;
}
+
bool isSubregToReg() const {
return getOpcode() == TargetOpcode::SUBREG_TO_REG;
}
+
bool isRegSequence() const {
return getOpcode() == TargetOpcode::REG_SEQUENCE;
}
+
bool isBundle() const {
return getOpcode() == TargetOpcode::BUNDLE;
}
+
bool isCopy() const {
return getOpcode() == TargetOpcode::COPY;
}
+
bool isFullCopy() const {
return isCopy() && !getOperand(0).getSubReg() && !getOperand(1).getSubReg();
}
+
bool isExtractSubreg() const {
return getOpcode() == TargetOpcode::EXTRACT_SUBREG;
}
@@ -978,7 +993,6 @@ public:
///
/// The flag operand is an immediate that can be decoded with methods like
/// InlineAsm::hasRegClassConstraint().
- ///
int findInlineAsmFlagIdx(unsigned OpIdx, unsigned *GroupNo = nullptr) const;
/// Compute the static register class constraint for operand OpIdx.
@@ -987,7 +1001,6 @@ public:
///
/// Returns NULL if the static register class constraint cannot be
/// determined.
- ///
const TargetRegisterClass*
getRegClassConstraint(unsigned OpIdx,
const TargetInstrInfo *TII,
@@ -1328,6 +1341,6 @@ inline raw_ostream& operator<<(raw_ostream &OS, const MachineInstr &MI) {
return OS;
}
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_MACHINEINSTR_H
diff --git a/include/llvm/CodeGen/MachineInstrBundleIterator.h b/include/llvm/CodeGen/MachineInstrBundleIterator.h
index 3104185385ea..5fe4964ff116 100644
--- a/include/llvm/CodeGen/MachineInstrBundleIterator.h
+++ b/include/llvm/CodeGen/MachineInstrBundleIterator.h
@@ -15,34 +15,37 @@
#define LLVM_CODEGEN_MACHINEINSTRBUNDLEITERATOR_H
#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/simple_ilist.h"
+#include <cassert>
#include <iterator>
+#include <type_traits>
namespace llvm {
template <class T, bool IsReverse> struct MachineInstrBundleIteratorTraits;
template <class T> struct MachineInstrBundleIteratorTraits<T, false> {
- typedef simple_ilist<T, ilist_sentinel_tracking<true>> list_type;
- typedef typename list_type::iterator instr_iterator;
- typedef typename list_type::iterator nonconst_instr_iterator;
- typedef typename list_type::const_iterator const_instr_iterator;
+ using list_type = simple_ilist<T, ilist_sentinel_tracking<true>>;
+ using instr_iterator = typename list_type::iterator;
+ using nonconst_instr_iterator = typename list_type::iterator;
+ using const_instr_iterator = typename list_type::const_iterator;
};
template <class T> struct MachineInstrBundleIteratorTraits<T, true> {
- typedef simple_ilist<T, ilist_sentinel_tracking<true>> list_type;
- typedef typename list_type::reverse_iterator instr_iterator;
- typedef typename list_type::reverse_iterator nonconst_instr_iterator;
- typedef typename list_type::const_reverse_iterator const_instr_iterator;
+ using list_type = simple_ilist<T, ilist_sentinel_tracking<true>>;
+ using instr_iterator = typename list_type::reverse_iterator;
+ using nonconst_instr_iterator = typename list_type::reverse_iterator;
+ using const_instr_iterator = typename list_type::const_reverse_iterator;
};
template <class T> struct MachineInstrBundleIteratorTraits<const T, false> {
- typedef simple_ilist<T, ilist_sentinel_tracking<true>> list_type;
- typedef typename list_type::const_iterator instr_iterator;
- typedef typename list_type::iterator nonconst_instr_iterator;
- typedef typename list_type::const_iterator const_instr_iterator;
+ using list_type = simple_ilist<T, ilist_sentinel_tracking<true>>;
+ using instr_iterator = typename list_type::const_iterator;
+ using nonconst_instr_iterator = typename list_type::iterator;
+ using const_instr_iterator = typename list_type::const_iterator;
};
template <class T> struct MachineInstrBundleIteratorTraits<const T, true> {
- typedef simple_ilist<T, ilist_sentinel_tracking<true>> list_type;
- typedef typename list_type::const_reverse_iterator instr_iterator;
- typedef typename list_type::reverse_iterator nonconst_instr_iterator;
- typedef typename list_type::const_reverse_iterator const_instr_iterator;
+ using list_type = simple_ilist<T, ilist_sentinel_tracking<true>>;
+ using instr_iterator = typename list_type::const_reverse_iterator;
+ using nonconst_instr_iterator = typename list_type::reverse_iterator;
+ using const_instr_iterator = typename list_type::const_reverse_iterator;
};
template <bool IsReverse> struct MachineInstrBundleIteratorHelper;
@@ -104,27 +107,27 @@ template <> struct MachineInstrBundleIteratorHelper<true> {
/// inside bundles (i.e. walk top level MIs only).
template <typename Ty, bool IsReverse = false>
class MachineInstrBundleIterator : MachineInstrBundleIteratorHelper<IsReverse> {
- typedef MachineInstrBundleIteratorTraits<Ty, IsReverse> Traits;
- typedef typename Traits::instr_iterator instr_iterator;
+ using Traits = MachineInstrBundleIteratorTraits<Ty, IsReverse>;
+ using instr_iterator = typename Traits::instr_iterator;
+
instr_iterator MII;
public:
- typedef typename instr_iterator::value_type value_type;
- typedef typename instr_iterator::difference_type difference_type;
- typedef typename instr_iterator::pointer pointer;
- typedef typename instr_iterator::reference reference;
- typedef std::bidirectional_iterator_tag iterator_category;
-
- typedef typename instr_iterator::const_pointer const_pointer;
- typedef typename instr_iterator::const_reference const_reference;
+ using value_type = typename instr_iterator::value_type;
+ using difference_type = typename instr_iterator::difference_type;
+ using pointer = typename instr_iterator::pointer;
+ using reference = typename instr_iterator::reference;
+ using const_pointer = typename instr_iterator::const_pointer;
+ using const_reference = typename instr_iterator::const_reference;
+ using iterator_category = std::bidirectional_iterator_tag;
private:
- typedef typename Traits::nonconst_instr_iterator nonconst_instr_iterator;
- typedef typename Traits::const_instr_iterator const_instr_iterator;
- typedef MachineInstrBundleIterator<
- typename nonconst_instr_iterator::value_type, IsReverse>
- nonconst_iterator;
- typedef MachineInstrBundleIterator<Ty, !IsReverse> reverse_iterator;
+ using nonconst_instr_iterator = typename Traits::nonconst_instr_iterator;
+ using const_instr_iterator = typename Traits::const_instr_iterator;
+ using nonconst_iterator =
+ MachineInstrBundleIterator<typename nonconst_instr_iterator::value_type,
+ IsReverse>;
+ using reverse_iterator = MachineInstrBundleIterator<Ty, !IsReverse>;
public:
MachineInstrBundleIterator(instr_iterator MI) : MII(MI) {
@@ -138,12 +141,14 @@ public:
"MachineInstrBundleIterator with a "
"bundled MI");
}
+
MachineInstrBundleIterator(pointer MI) : MII(MI) {
// FIXME: This conversion should be explicit.
assert((!MI || !MI->isBundledWithPred()) && "It's not legal to initialize "
"MachineInstrBundleIterator "
"with a bundled MI");
}
+
// Template allows conversion from const to nonconst.
template <class OtherTy>
MachineInstrBundleIterator(
@@ -151,6 +156,7 @@ public:
typename std::enable_if<std::is_convertible<OtherTy *, Ty *>::value,
void *>::type = nullptr)
: MII(I.getInstrIterator()) {}
+
MachineInstrBundleIterator() : MII(nullptr) {}
/// Explicit conversion between forward/reverse iterators.
@@ -280,4 +286,4 @@ public:
} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_MACHINEINSTRBUNDLEITERATOR_H
diff --git a/include/llvm/CodeGen/MachineLoopInfo.h b/include/llvm/CodeGen/MachineLoopInfo.h
index 5c814f22f99b..58cffaade9d2 100644
--- a/include/llvm/CodeGen/MachineLoopInfo.h
+++ b/include/llvm/CodeGen/MachineLoopInfo.h
@@ -33,6 +33,8 @@
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/IR/DebugLoc.h"
+#include "llvm/Pass.h"
namespace llvm {
@@ -71,6 +73,7 @@ public:
private:
friend class LoopInfoBase<MachineBasicBlock, MachineLoop>;
+
explicit MachineLoop(MachineBasicBlock *MBB)
: LoopBase<MachineBasicBlock, MachineLoop>(MBB) {}
};
@@ -79,11 +82,9 @@ private:
extern template class LoopInfoBase<MachineBasicBlock, MachineLoop>;
class MachineLoopInfo : public MachineFunctionPass {
- LoopInfoBase<MachineBasicBlock, MachineLoop> LI;
friend class LoopBase<MachineBasicBlock, MachineLoop>;
- void operator=(const MachineLoopInfo &) = delete;
- MachineLoopInfo(const MachineLoopInfo &) = delete;
+ LoopInfoBase<MachineBasicBlock, MachineLoop> LI;
public:
static char ID; // Pass identification, replacement for typeid
@@ -91,6 +92,8 @@ public:
MachineLoopInfo() : MachineFunctionPass(ID) {
initializeMachineLoopInfoPass(*PassRegistry::getPassRegistry());
}
+ MachineLoopInfo(const MachineLoopInfo &) = delete;
+ MachineLoopInfo &operator=(const MachineLoopInfo &) = delete;
LoopInfoBase<MachineBasicBlock, MachineLoop>& getBase() { return LI; }
@@ -103,7 +106,7 @@ public:
bool SpeculativePreheader = false) const;
/// The iterator interface to the top-level loops in the current function.
- typedef LoopInfoBase<MachineBasicBlock, MachineLoop>::iterator iterator;
+ using iterator = LoopInfoBase<MachineBasicBlock, MachineLoop>::iterator;
inline iterator begin() const { return LI.begin(); }
inline iterator end() const { return LI.end(); }
bool empty() const { return LI.empty(); }
@@ -166,11 +169,10 @@ public:
}
};
-
// Allow clients to walk the list of nested loops...
template <> struct GraphTraits<const MachineLoop*> {
- typedef const MachineLoop *NodeRef;
- typedef MachineLoopInfo::iterator ChildIteratorType;
+ using NodeRef = const MachineLoop *;
+ using ChildIteratorType = MachineLoopInfo::iterator;
static NodeRef getEntryNode(const MachineLoop *L) { return L; }
static ChildIteratorType child_begin(NodeRef N) { return N->begin(); }
@@ -178,14 +180,14 @@ template <> struct GraphTraits<const MachineLoop*> {
};
template <> struct GraphTraits<MachineLoop*> {
- typedef MachineLoop *NodeRef;
- typedef MachineLoopInfo::iterator ChildIteratorType;
+ using NodeRef = MachineLoop *;
+ using ChildIteratorType = MachineLoopInfo::iterator;
static NodeRef getEntryNode(MachineLoop *L) { return L; }
static ChildIteratorType child_begin(NodeRef N) { return N->begin(); }
static ChildIteratorType child_end(NodeRef N) { return N->end(); }
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_MACHINELOOPINFO_H
diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h
index f46ef41879d1..d4ac58c3bd22 100644
--- a/include/llvm/CodeGen/MachineModuleInfo.h
+++ b/include/llvm/CodeGen/MachineModuleInfo.h
@@ -31,35 +31,26 @@
#ifndef LLVM_CODEGEN_MACHINEMODULEINFO_H
#define LLVM_CODEGEN_MACHINEMODULEINFO_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerIntPair.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/IR/DebugLoc.h"
-#include "llvm/IR/ValueHandle.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MachineLocation.h"
#include "llvm/Pass.h"
-#include "llvm/Support/DataTypes.h"
+#include <memory>
+#include <utility>
+#include <vector>
namespace llvm {
-//===----------------------------------------------------------------------===//
-// Forward declarations.
-class BlockAddress;
+class BasicBlock;
class CallInst;
-class Constant;
-class GlobalVariable;
-class LandingPadInst;
-class MDNode;
-class MMIAddrLabelMap;
-class MachineBasicBlock;
+class Function;
class MachineFunction;
class MachineFunctionInitializer;
+class MMIAddrLabelMap;
class Module;
-class PointerType;
-class StructType;
+class TargetMachine;
//===----------------------------------------------------------------------===//
/// This class can be derived from and used by targets to hold private
@@ -69,11 +60,12 @@ class StructType;
///
class MachineModuleInfoImpl {
public:
- typedef PointerIntPair<MCSymbol*, 1, bool> StubValueTy;
+ using StubValueTy = PointerIntPair<MCSymbol *, 1, bool>;
+ using SymbolListTy = std::vector<std::pair<MCSymbol *, StubValueTy>>;
+
virtual ~MachineModuleInfoImpl();
- typedef std::vector<std::pair<MCSymbol*, StubValueTy> > SymbolListTy;
-protected:
+protected:
/// Return the entries from a DenseMap in a deterministic sorted orer.
/// Clears the map.
static SymbolListTy getSortedStubs(DenseMap<MCSymbol*, StubValueTy>&);
@@ -252,6 +244,6 @@ public:
/// which will link in MSVCRT's floating-point support.
void computeUsesVAFloatArgument(const CallInst &I, MachineModuleInfo &MMI);
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_MACHINEMODULEINFO_H
diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h
index f3e04cffcda6..3bcfc1c4254b 100644
--- a/include/llvm/CodeGen/Passes.h
+++ b/include/llvm/CodeGen/Passes.h
@@ -133,6 +133,10 @@ namespace llvm {
// instruction and update the MachineFunctionInfo with that information.
extern char &ShrinkWrapID;
+ /// LiveRangeShrink pass. Move instruction close to its definition to shrink
+ /// the definition's live range.
+ extern char &LiveRangeShrinkID;
+
/// Greedy register allocator.
extern char &RAGreedyID;
diff --git a/include/llvm/CodeGen/TargetPassConfig.h b/include/llvm/CodeGen/TargetPassConfig.h
index f0c826dc1d45..fcf1937c186e 100644
--- a/include/llvm/CodeGen/TargetPassConfig.h
+++ b/include/llvm/CodeGen/TargetPassConfig.h
@@ -22,7 +22,7 @@ namespace llvm {
class PassConfigImpl;
class ScheduleDAGInstrs;
-class TargetMachine;
+class LLVMTargetMachine;
struct MachineSchedContext;
// The old pass manager infrastructure is hidden in a legacy namespace now.
@@ -103,7 +103,7 @@ private:
bool AddingMachinePasses;
protected:
- TargetMachine *TM;
+ LLVMTargetMachine *TM;
PassConfigImpl *Impl; // Internal data structures
bool Initialized; // Flagged after all passes are configured.
@@ -120,7 +120,7 @@ protected:
bool RequireCodeGenSCCOrder;
public:
- TargetPassConfig(TargetMachine *tm, PassManagerBase &pm);
+ TargetPassConfig(LLVMTargetMachine &TM, PassManagerBase &pm);
// Dummy constructor.
TargetPassConfig();
diff --git a/include/llvm/DebugInfo/CodeView/CodeView.h b/include/llvm/DebugInfo/CodeView/CodeView.h
index 3316e71916ed..4e8c8feb7a12 100644
--- a/include/llvm/DebugInfo/CodeView/CodeView.h
+++ b/include/llvm/DebugInfo/CodeView/CodeView.h
@@ -6,6 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+//
+// Defines constants and basic types describing CodeView debug information.
+//
+//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_CODEVIEW_CODEVIEW_H
#define LLVM_DEBUGINFO_CODEVIEW_CODEVIEW_H
@@ -22,28 +26,28 @@ namespace codeview {
/// documentation and headers talk about this as the "leaf" type.
enum class TypeRecordKind : uint16_t {
#define TYPE_RECORD(lf_ename, value, name) name = value,
-#include "TypeRecords.def"
+#include "CodeViewTypes.def"
};
/// Duplicate copy of the above enum, but using the official CV names. Useful
/// for reference purposes and when dealing with unknown record types.
enum TypeLeafKind : uint16_t {
#define CV_TYPE(name, val) name = val,
-#include "TypeRecords.def"
+#include "CodeViewTypes.def"
};
/// Distinguishes individual records in the Symbols subsection of a .debug$S
/// section. Equivalent to SYM_ENUM_e in cvinfo.h.
enum class SymbolRecordKind : uint16_t {
#define SYMBOL_RECORD(lf_ename, value, name) name = value,
-#include "CVSymbolTypes.def"
+#include "CodeViewSymbols.def"
};
/// Duplicate copy of the above enum, but using the official CV names. Useful
/// for reference purposes and when dealing with unknown record types.
enum SymbolKind : uint16_t {
#define CV_SYMBOL(name, val) name = val,
-#include "CVSymbolTypes.def"
+#include "CodeViewSymbols.def"
};
#define CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(Class) \
@@ -280,7 +284,7 @@ CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(MethodOptions)
/// Equivalent to CV_LABEL_TYPE_e.
enum class LabelType : uint16_t {
Near = 0x0,
- Far = 0x4,
+ Far = 0x4,
};
/// Equivalent to CV_modifier_t.
diff --git a/include/llvm/DebugInfo/CodeView/CVSymbolTypes.def b/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def
index 32813d861d90..32813d861d90 100644
--- a/include/llvm/DebugInfo/CodeView/CVSymbolTypes.def
+++ b/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def
diff --git a/include/llvm/DebugInfo/CodeView/TypeRecords.def b/include/llvm/DebugInfo/CodeView/CodeViewTypes.def
index 8c193bb13cb7..8c193bb13cb7 100644
--- a/include/llvm/DebugInfo/CodeView/TypeRecords.def
+++ b/include/llvm/DebugInfo/CodeView/CodeViewTypes.def
diff --git a/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h b/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h
index c1a5152930ff..428ff153d5d1 100644
--- a/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h
+++ b/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h
@@ -34,6 +34,17 @@ class SymbolDeserializer : public SymbolVisitorCallbacks {
};
public:
+ template <typename T> static Error deserializeAs(CVSymbol Symbol, T &Record) {
+ SymbolDeserializer S(nullptr);
+ if (auto EC = S.visitSymbolBegin(Symbol))
+ return EC;
+ if (auto EC = S.visitKnownRecord(Symbol, Record))
+ return EC;
+ if (auto EC = S.visitSymbolEnd(Symbol))
+ return EC;
+ return Error::success();
+ }
+
explicit SymbolDeserializer(SymbolVisitorDelegate *Delegate)
: Delegate(Delegate) {}
@@ -54,7 +65,7 @@ public:
return visitKnownRecordImpl(CVR, Record); \
}
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "CVSymbolTypes.def"
+#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
private:
template <typename T> Error visitKnownRecordImpl(CVSymbol &CVR, T &Record) {
diff --git a/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/include/llvm/DebugInfo/CodeView/SymbolRecord.h
index c5a5549bf818..a3e4dff647bd 100644
--- a/include/llvm/DebugInfo/CodeView/SymbolRecord.h
+++ b/include/llvm/DebugInfo/CodeView/SymbolRecord.h
@@ -35,8 +35,6 @@ protected:
public:
SymbolRecordKind getKind() const { return Kind; }
-
-private:
SymbolRecordKind Kind;
};
diff --git a/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h b/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h
index 0a1837a0d935..5d072a3b2723 100644
--- a/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h
+++ b/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h
@@ -29,7 +29,7 @@ public:
#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
Error visitKnownRecord(CVSymbol &CVR, Name &Record) override;
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "CVSymbolTypes.def"
+#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
private:
Optional<SymbolKind> Kind;
diff --git a/include/llvm/DebugInfo/CodeView/SymbolSerializer.h b/include/llvm/DebugInfo/CodeView/SymbolSerializer.h
index f2e99bd83326..a8fe1a3ae1d0 100644
--- a/include/llvm/DebugInfo/CodeView/SymbolSerializer.h
+++ b/include/llvm/DebugInfo/CodeView/SymbolSerializer.h
@@ -45,6 +45,17 @@ class SymbolSerializer : public SymbolVisitorCallbacks {
}
public:
+ template <typename SymType>
+ static CVSymbol writeOneSymbol(SymType &Sym, BumpPtrAllocator &Storage) {
+ CVSymbol Result;
+ Result.Type = static_cast<SymbolKind>(Sym.Kind);
+ SymbolSerializer Serializer(Storage);
+ consumeError(Serializer.visitSymbolBegin(Result));
+ consumeError(Serializer.visitKnownRecord(Result, Sym));
+ consumeError(Serializer.visitSymbolEnd(Result));
+ return Result;
+ }
+
explicit SymbolSerializer(BumpPtrAllocator &Storage);
virtual Error visitSymbolBegin(CVSymbol &Record) override;
@@ -55,7 +66,7 @@ public:
return visitKnownRecordImpl(CVR, Record); \
}
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "CVSymbolTypes.def"
+#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
private:
template <typename RecordKind>
diff --git a/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h b/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h
index 96a93bf7e576..5f4205bd6e08 100644
--- a/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h
+++ b/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h
@@ -59,7 +59,7 @@ public:
return Error::success(); \
}
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
+#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
private:
std::vector<SymbolVisitorCallbacks *> Pipeline;
diff --git a/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h b/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h
index aaa9d2e85e13..2ef7eabdaa9d 100644
--- a/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h
+++ b/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h
@@ -39,7 +39,7 @@ public:
return Error::success(); \
}
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "CVSymbolTypes.def"
+#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
};
} // end namespace codeview
diff --git a/include/llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h b/include/llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h
index c064e19a7e90..77dbc91a7d38 100644
--- a/include/llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h
+++ b/include/llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h
@@ -39,7 +39,7 @@ public:
Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override;
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "TypeRecords.def"
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
private:
StringRef getTypeName(TypeIndex Index) const;
diff --git a/include/llvm/DebugInfo/CodeView/TypeDeserializer.h b/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
index a9c5cf42fc5b..965cdfd85f48 100644
--- a/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
+++ b/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
@@ -41,6 +41,7 @@ public:
TypeDeserializer() = default;
template <typename T> static Error deserializeAs(CVType &CVT, T &Record) {
+ Record.Kind = static_cast<TypeRecordKind>(CVT.kind());
MappingInfo I(CVT.content());
if (auto EC = I.Mapping.visitTypeBegin(CVT))
return EC;
@@ -75,7 +76,7 @@ public:
#define MEMBER_RECORD(EnumName, EnumVal, Name)
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "TypeRecords.def"
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
private:
template <typename RecordType>
@@ -127,7 +128,7 @@ public:
}
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "TypeRecords.def"
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
private:
template <typename RecordType>
diff --git a/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h b/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h
index 65b3a33e6548..afb8b3636361 100644
--- a/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h
+++ b/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h
@@ -58,7 +58,7 @@ public:
Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override;
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "TypeRecords.def"
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
private:
void printMemberAttributes(MemberAttributes Attrs);
diff --git a/include/llvm/DebugInfo/CodeView/TypeRecord.h b/include/llvm/DebugInfo/CodeView/TypeRecord.h
index 92745ebfcded..3a64a437aa4d 100644
--- a/include/llvm/DebugInfo/CodeView/TypeRecord.h
+++ b/include/llvm/DebugInfo/CodeView/TypeRecord.h
@@ -123,13 +123,13 @@ protected:
public:
TypeRecordKind getKind() const { return Kind; }
-private:
TypeRecordKind Kind;
};
// LF_MODIFIER
class ModifierRecord : public TypeRecord {
public:
+ ModifierRecord() = default;
explicit ModifierRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
ModifierRecord(TypeIndex ModifiedType, ModifierOptions Modifiers)
: TypeRecord(TypeRecordKind::Modifier), ModifiedType(ModifiedType),
@@ -145,6 +145,7 @@ public:
// LF_PROCEDURE
class ProcedureRecord : public TypeRecord {
public:
+ ProcedureRecord() = default;
explicit ProcedureRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
ProcedureRecord(TypeIndex ReturnType, CallingConvention CallConv,
FunctionOptions Options, uint16_t ParameterCount,
@@ -169,6 +170,7 @@ public:
// LF_MFUNCTION
class MemberFunctionRecord : public TypeRecord {
public:
+ MemberFunctionRecord() = default;
explicit MemberFunctionRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
MemberFunctionRecord(TypeIndex ReturnType, TypeIndex ClassType,
@@ -203,6 +205,7 @@ public:
// LF_LABEL
class LabelRecord : public TypeRecord {
public:
+ LabelRecord() = default;
explicit LabelRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
LabelRecord(LabelType Mode) : TypeRecord(TypeRecordKind::Label), Mode(Mode) {}
@@ -213,6 +216,7 @@ public:
// LF_MFUNC_ID
class MemberFuncIdRecord : public TypeRecord {
public:
+ MemberFuncIdRecord() = default;
explicit MemberFuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
MemberFuncIdRecord(TypeIndex ClassType, TypeIndex FunctionType,
StringRef Name)
@@ -230,6 +234,7 @@ public:
// LF_ARGLIST
class ArgListRecord : public TypeRecord {
public:
+ ArgListRecord() = default;
explicit ArgListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
ArgListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices)
@@ -243,6 +248,7 @@ public:
// LF_SUBSTR_LIST
class StringListRecord : public TypeRecord {
public:
+ StringListRecord() = default;
explicit StringListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
StringListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices)
@@ -267,6 +273,7 @@ public:
static const uint32_t PointerSizeShift = 13;
static const uint32_t PointerSizeMask = 0xFF;
+ PointerRecord() = default;
explicit PointerRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
PointerRecord(TypeIndex ReferentType, uint32_t Attrs)
@@ -341,6 +348,7 @@ private:
// LF_NESTTYPE
class NestedTypeRecord : public TypeRecord {
public:
+ NestedTypeRecord() = default;
explicit NestedTypeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
NestedTypeRecord(TypeIndex Type, StringRef Name)
: TypeRecord(TypeRecordKind::NestedType), Type(Type), Name(Name) {}
@@ -355,6 +363,7 @@ public:
// LF_FIELDLIST
class FieldListRecord : public TypeRecord {
public:
+ FieldListRecord() = default;
explicit FieldListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
explicit FieldListRecord(ArrayRef<uint8_t> Data)
: TypeRecord(TypeRecordKind::FieldList), Data(Data) {}
@@ -365,6 +374,7 @@ public:
// LF_ARRAY
class ArrayRecord : public TypeRecord {
public:
+ ArrayRecord() = default;
explicit ArrayRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
ArrayRecord(TypeIndex ElementType, TypeIndex IndexType, uint64_t Size,
StringRef Name)
@@ -384,6 +394,7 @@ public:
class TagRecord : public TypeRecord {
protected:
+ TagRecord() = default;
explicit TagRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
TagRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options,
TypeIndex FieldList, StringRef Name, StringRef UniqueName)
@@ -416,6 +427,7 @@ public:
// LF_CLASS, LF_STRUCTURE, LF_INTERFACE
class ClassRecord : public TagRecord {
public:
+ ClassRecord() = default;
explicit ClassRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
ClassRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options,
TypeIndex FieldList, TypeIndex DerivationList,
@@ -447,6 +459,7 @@ public:
// LF_UNION
struct UnionRecord : public TagRecord {
+ UnionRecord() = default;
explicit UnionRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
UnionRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList,
uint64_t Size, StringRef Name, StringRef UniqueName)
@@ -468,6 +481,7 @@ struct UnionRecord : public TagRecord {
// LF_ENUM
class EnumRecord : public TagRecord {
public:
+ EnumRecord() = default;
explicit EnumRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
EnumRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList,
StringRef Name, StringRef UniqueName, TypeIndex UnderlyingType)
@@ -482,6 +496,7 @@ public:
// LF_BITFIELD
class BitFieldRecord : public TypeRecord {
public:
+ BitFieldRecord() = default;
explicit BitFieldRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
BitFieldRecord(TypeIndex Type, uint8_t BitSize, uint8_t BitOffset)
: TypeRecord(TypeRecordKind::BitField), Type(Type), BitSize(BitSize),
@@ -498,6 +513,7 @@ public:
// LF_VTSHAPE
class VFTableShapeRecord : public TypeRecord {
public:
+ VFTableShapeRecord() = default;
explicit VFTableShapeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
explicit VFTableShapeRecord(ArrayRef<VFTableSlotKind> Slots)
: TypeRecord(TypeRecordKind::VFTableShape), SlotsRef(Slots) {}
@@ -518,6 +534,7 @@ public:
// LF_TYPESERVER2
class TypeServer2Record : public TypeRecord {
public:
+ TypeServer2Record() = default;
explicit TypeServer2Record(TypeRecordKind Kind) : TypeRecord(Kind) {}
TypeServer2Record(StringRef Guid, uint32_t Age, StringRef Name)
: TypeRecord(TypeRecordKind::TypeServer2), Guid(Guid), Age(Age),
@@ -537,6 +554,7 @@ public:
// LF_STRING_ID
class StringIdRecord : public TypeRecord {
public:
+ StringIdRecord() = default;
explicit StringIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
StringIdRecord(TypeIndex Id, StringRef String)
: TypeRecord(TypeRecordKind::StringId), Id(Id), String(String) {}
@@ -551,6 +569,7 @@ public:
// LF_FUNC_ID
class FuncIdRecord : public TypeRecord {
public:
+ FuncIdRecord() = default;
explicit FuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
FuncIdRecord(TypeIndex ParentScope, TypeIndex FunctionType, StringRef Name)
: TypeRecord(TypeRecordKind::FuncId), ParentScope(ParentScope),
@@ -570,6 +589,7 @@ public:
// LF_UDT_SRC_LINE
class UdtSourceLineRecord : public TypeRecord {
public:
+ UdtSourceLineRecord() = default;
explicit UdtSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
UdtSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, uint32_t LineNumber)
: TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT),
@@ -587,6 +607,7 @@ public:
// LF_UDT_MOD_SRC_LINE
class UdtModSourceLineRecord : public TypeRecord {
public:
+ UdtModSourceLineRecord() = default;
explicit UdtModSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
UdtModSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile,
uint32_t LineNumber, uint16_t Module)
@@ -607,6 +628,7 @@ public:
// LF_BUILDINFO
class BuildInfoRecord : public TypeRecord {
public:
+ BuildInfoRecord() = default;
explicit BuildInfoRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
BuildInfoRecord(ArrayRef<TypeIndex> ArgIndices)
: TypeRecord(TypeRecordKind::BuildInfo),
@@ -619,6 +641,7 @@ public:
// LF_VFTABLE
class VFTableRecord : public TypeRecord {
public:
+ VFTableRecord() = default;
explicit VFTableRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
VFTableRecord(TypeIndex CompleteClass, TypeIndex OverriddenVFTable,
uint32_t VFPtrOffset, StringRef Name,
@@ -646,7 +669,7 @@ public:
// LF_ONEMETHOD
class OneMethodRecord : public TypeRecord {
public:
- OneMethodRecord() : TypeRecord(TypeRecordKind::OneMethod) {}
+ OneMethodRecord() = default;
explicit OneMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
OneMethodRecord(TypeIndex Type, MemberAttributes Attrs, int32_t VFTableOffset,
StringRef Name)
@@ -678,6 +701,7 @@ public:
// LF_METHODLIST
class MethodOverloadListRecord : public TypeRecord {
public:
+ MethodOverloadListRecord() = default;
explicit MethodOverloadListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
MethodOverloadListRecord(ArrayRef<OneMethodRecord> Methods)
: TypeRecord(TypeRecordKind::MethodOverloadList), Methods(Methods) {}
@@ -689,6 +713,7 @@ public:
/// For method overload sets. LF_METHOD
class OverloadedMethodRecord : public TypeRecord {
public:
+ OverloadedMethodRecord() = default;
explicit OverloadedMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
OverloadedMethodRecord(uint16_t NumOverloads, TypeIndex MethodList,
StringRef Name)
@@ -706,6 +731,7 @@ public:
// LF_MEMBER
class DataMemberRecord : public TypeRecord {
public:
+ DataMemberRecord() = default;
explicit DataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
DataMemberRecord(MemberAttributes Attrs, TypeIndex Type, uint64_t Offset,
StringRef Name)
@@ -730,6 +756,7 @@ public:
// LF_STMEMBER
class StaticDataMemberRecord : public TypeRecord {
public:
+ StaticDataMemberRecord() = default;
explicit StaticDataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
StaticDataMemberRecord(MemberAttributes Attrs, TypeIndex Type, StringRef Name)
: TypeRecord(TypeRecordKind::StaticDataMember), Attrs(Attrs), Type(Type),
@@ -750,6 +777,7 @@ public:
// LF_ENUMERATE
class EnumeratorRecord : public TypeRecord {
public:
+ EnumeratorRecord() = default;
explicit EnumeratorRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
EnumeratorRecord(MemberAttributes Attrs, APSInt Value, StringRef Name)
: TypeRecord(TypeRecordKind::Enumerator), Attrs(Attrs),
@@ -770,6 +798,7 @@ public:
// LF_VFUNCTAB
class VFPtrRecord : public TypeRecord {
public:
+ VFPtrRecord() = default;
explicit VFPtrRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
VFPtrRecord(TypeIndex Type)
: TypeRecord(TypeRecordKind::VFPtr), Type(Type) {}
@@ -782,6 +811,7 @@ public:
// LF_BCLASS, LF_BINTERFACE
class BaseClassRecord : public TypeRecord {
public:
+ BaseClassRecord() = default;
explicit BaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
BaseClassRecord(MemberAttributes Attrs, TypeIndex Type, uint64_t Offset)
: TypeRecord(TypeRecordKind::BaseClass), Attrs(Attrs), Type(Type),
@@ -802,6 +832,7 @@ public:
// LF_VBCLASS, LF_IVBCLASS
class VirtualBaseClassRecord : public TypeRecord {
public:
+ VirtualBaseClassRecord() = default;
explicit VirtualBaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
VirtualBaseClassRecord(TypeRecordKind Kind, MemberAttributes Attrs,
TypeIndex BaseType, TypeIndex VBPtrType,
@@ -831,6 +862,7 @@ public:
/// together. The first will end in an LF_INDEX record that points to the next.
class ListContinuationRecord : public TypeRecord {
public:
+ ListContinuationRecord() = default;
explicit ListContinuationRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
ListContinuationRecord(TypeIndex ContinuationIndex)
: TypeRecord(TypeRecordKind::ListContinuation),
diff --git a/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h b/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h
index 924ca0470fad..6156223b2560 100644
--- a/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h
+++ b/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h
@@ -37,7 +37,7 @@ public:
Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override;
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "TypeRecords.def"
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
private:
Optional<TypeLeafKind> TypeKind;
diff --git a/include/llvm/DebugInfo/CodeView/TypeSerializer.h b/include/llvm/DebugInfo/CodeView/TypeSerializer.h
index 435c43f7edcb..1dee86a1da79 100644
--- a/include/llvm/DebugInfo/CodeView/TypeSerializer.h
+++ b/include/llvm/DebugInfo/CodeView/TypeSerializer.h
@@ -106,7 +106,7 @@ public:
return visitKnownMemberImpl<Name##Record>(CVR, Record); \
}
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
private:
template <typename RecordKind>
diff --git a/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h b/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
index 7bdc9ecb20cf..907ed1010e5b 100644
--- a/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
+++ b/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
@@ -13,8 +13,8 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-#include "llvm/DebugInfo/CodeView/TypeSerializer.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeSerializer.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Error.h"
#include <algorithm>
diff --git a/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h b/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h
index ed48df33249f..126fb8abb0da 100644
--- a/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h
+++ b/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h
@@ -94,7 +94,7 @@ public:
}
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
private:
template <typename T> Error visitKnownRecordImpl(CVType &CVR, T &Record) {
diff --git a/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h b/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h
index 0ea754deb425..d7a473306bc2 100644
--- a/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h
+++ b/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h
@@ -58,7 +58,11 @@ public:
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "TypeRecords.def"
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
+#undef TYPE_RECORD
+#undef TYPE_RECORD_ALIAS
+#undef MEMBER_RECORD
+#undef MEMBER_RECORD_ALIAS
};
} // end namespace codeview
diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h
index d51408122fc9..2ab1c9508522 100644
--- a/include/llvm/DebugInfo/DIContext.h
+++ b/include/llvm/DebugInfo/DIContext.h
@@ -146,6 +146,14 @@ enum DIDumpType {
DIDT_TUIndex,
};
+/// Container for dump options that control which debug information will be
+/// dumped.
+struct DIDumpOptions {
+ DIDumpType DumpType = DIDT_All;
+ bool DumpEH = false;
+ bool SummarizeTypes = false;
+};
+
class DIContext {
public:
enum DIContextKind {
@@ -158,8 +166,7 @@ public:
DIContextKind getKind() const { return Kind; }
- virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All,
- bool DumpEH = false, bool SummarizeTypes = false) = 0;
+ virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0;
virtual bool verify(raw_ostream &OS, DIDumpType DumpType = DIDT_All) {
// No verifier? Just say things went well.
diff --git a/include/llvm/DebugInfo/DWARF/DWARFContext.h b/include/llvm/DebugInfo/DWARF/DWARFContext.h
index 7fa68f3f2314..519ecf618558 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFContext.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFContext.h
@@ -105,8 +105,7 @@ public:
return DICtx->getKind() == CK_DWARF;
}
- void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All,
- bool DumpEH = false, bool SummarizeTypes = false) override;
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override;
bool verify(raw_ostream &OS, DIDumpType DumpType = DIDT_All) override;
diff --git a/include/llvm/DebugInfo/PDB/Native/RawConstants.h b/include/llvm/DebugInfo/PDB/Native/RawConstants.h
index f5d4df8feb2e..e1bd86b2870b 100644
--- a/include/llvm/DebugInfo/PDB/Native/RawConstants.h
+++ b/include/llvm/DebugInfo/PDB/Native/RawConstants.h
@@ -12,7 +12,6 @@
#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
-
#include <cstdint>
namespace llvm {
diff --git a/include/llvm/DebugInfo/PDB/Native/TpiHashing.h b/include/llvm/DebugInfo/PDB/Native/TpiHashing.h
index dd2698c354a2..156abb59a6be 100644
--- a/include/llvm/DebugInfo/PDB/Native/TpiHashing.h
+++ b/include/llvm/DebugInfo/PDB/Native/TpiHashing.h
@@ -38,7 +38,7 @@ public:
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD(EnumName, EnumVal, Name)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
private:
template <typename RecordKind>
diff --git a/include/llvm/DebugInfo/PDB/PDBContext.h b/include/llvm/DebugInfo/PDB/PDBContext.h
index 84ab8ed173cb..0ce49f5ef922 100644
--- a/include/llvm/DebugInfo/PDB/PDBContext.h
+++ b/include/llvm/DebugInfo/PDB/PDBContext.h
@@ -41,8 +41,7 @@ namespace pdb {
return DICtx->getKind() == CK_PDB;
}
- void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All,
- bool DumpEH = false, bool SummarizeTypes = false) override;
+ void dump(raw_ostream &OS, DIDumpOptions DIDumpOpts) override;
DILineInfo getLineInfoForAddress(
uint64_t Address,
diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h
index ace309ed95a4..687863857698 100644
--- a/include/llvm/IR/Attributes.h
+++ b/include/llvm/IR/Attributes.h
@@ -228,34 +228,31 @@ public:
bool operator==(const AttributeSet &O) { return SetNode == O.SetNode; }
bool operator!=(const AttributeSet &O) { return !(*this == O); }
- /// Add an argument attribute. Because
- /// attribute sets are immutable, this returns a new set.
- AttributeSet addAttribute(LLVMContext &C,
- Attribute::AttrKind Kind) const;
+ /// Add an argument attribute. Returns a new set because attribute sets are
+ /// immutable.
+ AttributeSet addAttribute(LLVMContext &C, Attribute::AttrKind Kind) const;
- /// Add a target-dependent attribute. Because
- /// attribute sets are immutable, this returns a new set.
+ /// Add a target-dependent attribute. Returns a new set because attribute sets
+ /// are immutable.
AttributeSet addAttribute(LLVMContext &C, StringRef Kind,
StringRef Value = StringRef()) const;
- /// Add attributes to the attribute set. Because
- /// attribute sets are immutable, this returns a new set.
+ /// Add attributes to the attribute set. Returns a new set because attribute
+ /// sets are immutable.
AttributeSet addAttributes(LLVMContext &C, AttributeSet AS) const;
- /// Remove the specified attribute from this set. Because
- /// attribute sets are immutable, this returns a new set.
- AttributeSet removeAttribute(LLVMContext &C,
- Attribute::AttrKind Kind) const;
+ /// Remove the specified attribute from this set. Returns a new set because
+ /// attribute sets are immutable.
+ AttributeSet removeAttribute(LLVMContext &C, Attribute::AttrKind Kind) const;
- /// Remove the specified attribute from this set. Because
- /// attribute sets are immutable, this returns a new set.
- AttributeSet removeAttribute(LLVMContext &C,
- StringRef Kind) const;
+ /// Remove the specified attribute from this set. Returns a new set because
+ /// attribute sets are immutable.
+ AttributeSet removeAttribute(LLVMContext &C, StringRef Kind) const;
- /// Remove the specified attributes from this set. Because
- /// attribute sets are immutable, this returns a new set.
+ /// Remove the specified attributes from this set. Returns a new set because
+ /// attribute sets are immutable.
AttributeSet removeAttributes(LLVMContext &C,
- const AttrBuilder &AttrsToRemove) const;
+ const AttrBuilder &AttrsToRemove) const;
/// Return the number of attributes in this set.
unsigned getNumAttributes() const;
@@ -377,73 +374,138 @@ public:
static AttributeList get(LLVMContext &C, unsigned Index,
const AttrBuilder &B);
- /// Add an argument attribute to the list. Returns a new list because
- /// attribute lists are immutable.
- AttributeList addParamAttribute(LLVMContext &C, unsigned ArgNo,
- Attribute::AttrKind Kind) const {
- return addAttribute(C, ArgNo + FirstArgIndex, Kind);
- }
-
- /// \brief Add an attribute to the attribute set at the given index. Because
- /// attribute sets are immutable, this returns a new set.
+ /// \brief Add an attribute to the attribute set at the given index.
+ /// Returns a new list because attribute lists are immutable.
AttributeList addAttribute(LLVMContext &C, unsigned Index,
Attribute::AttrKind Kind) const;
- /// \brief Add an attribute to the attribute set at the given index. Because
- /// attribute sets are immutable, this returns a new set.
+ /// \brief Add an attribute to the attribute set at the given index.
+ /// Returns a new list because attribute lists are immutable.
AttributeList addAttribute(LLVMContext &C, unsigned Index, StringRef Kind,
StringRef Value = StringRef()) const;
- /// Add an attribute to the attribute set at the given indices. Because
- /// attribute sets are immutable, this returns a new set.
- AttributeList addAttribute(LLVMContext &C, ArrayRef<unsigned> Indices,
- Attribute A) const;
+ /// Add an attribute to the attribute set at the given index.
+ /// Returns a new list because attribute lists are immutable.
+ AttributeList addAttribute(LLVMContext &C, unsigned Index, Attribute A) const;
- /// \brief Add attributes to the attribute set at the given index. Because
- /// attribute sets are immutable, this returns a new set.
+ /// \brief Add attributes to the attribute set at the given index.
+ /// Returns a new list because attribute lists are immutable.
AttributeList addAttributes(LLVMContext &C, unsigned Index,
const AttrBuilder &B) const;
+ /// Add an argument attribute to the list. Returns a new list because
+ /// attribute lists are immutable.
+ AttributeList addParamAttribute(LLVMContext &C, unsigned ArgNo,
+ Attribute::AttrKind Kind) const {
+ return addAttribute(C, ArgNo + FirstArgIndex, Kind);
+ }
+
+ /// Add an argument attribute to the list. Returns a new list because
+ /// attribute lists are immutable.
+ AttributeList addParamAttribute(LLVMContext &C, unsigned ArgNo,
+ StringRef Kind,
+ StringRef Value = StringRef()) const {
+ return addAttribute(C, ArgNo + FirstArgIndex, Kind, Value);
+ }
+
+ /// Add an attribute to the attribute list at the given arg indices. Returns a
+ /// new list because attribute lists are immutable.
+ AttributeList addParamAttribute(LLVMContext &C, ArrayRef<unsigned> ArgNos,
+ Attribute A) const;
+
+ /// Add an argument attribute to the list. Returns a new list because
+ /// attribute lists are immutable.
+ AttributeList addParamAttributes(LLVMContext &C, unsigned ArgNo,
+ const AttrBuilder &B) const {
+ return addAttributes(C, ArgNo + FirstArgIndex, B);
+ }
+
/// \brief Remove the specified attribute at the specified index from this
- /// attribute list. Because attribute lists are immutable, this returns the
- /// new list.
+ /// attribute list. Returns a new list because attribute lists are immutable.
AttributeList removeAttribute(LLVMContext &C, unsigned Index,
Attribute::AttrKind Kind) const;
/// \brief Remove the specified attribute at the specified index from this
- /// attribute list. Because attribute lists are immutable, this returns the
- /// new list.
+ /// attribute list. Returns a new list because attribute lists are immutable.
AttributeList removeAttribute(LLVMContext &C, unsigned Index,
StringRef Kind) const;
/// \brief Remove the specified attributes at the specified index from this
- /// attribute list. Because attribute lists are immutable, this returns the
- /// new list.
+ /// attribute list. Returns a new list because attribute lists are immutable.
AttributeList removeAttributes(LLVMContext &C, unsigned Index,
const AttrBuilder &AttrsToRemove) const;
/// \brief Remove all attributes at the specified index from this
- /// attribute list. Because attribute lists are immutable, this returns the
- /// new list.
+ /// attribute list. Returns a new list because attribute lists are immutable.
AttributeList removeAttributes(LLVMContext &C, unsigned Index) const;
- /// \brief Add the dereferenceable attribute to the attribute set at the given
- /// index. Because attribute sets are immutable, this returns a new set.
+ /// \brief Remove the specified attribute at the specified arg index from this
+ /// attribute list. Returns a new list because attribute lists are immutable.
+ AttributeList removeParamAttribute(LLVMContext &C, unsigned ArgNo,
+ Attribute::AttrKind Kind) const {
+ return removeAttribute(C, ArgNo + FirstArgIndex, Kind);
+ }
+
+ /// \brief Remove the specified attribute at the specified arg index from this
+ /// attribute list. Returns a new list because attribute lists are immutable.
+ AttributeList removeParamAttribute(LLVMContext &C, unsigned ArgNo,
+ StringRef Kind) const {
+ return removeAttribute(C, ArgNo + FirstArgIndex, Kind);
+ }
+
+ /// \brief Remove the specified attribute at the specified arg index from this
+ /// attribute list. Returns a new list because attribute lists are immutable.
+ AttributeList removeParamAttributes(LLVMContext &C, unsigned ArgNo,
+ const AttrBuilder &AttrsToRemove) const {
+ return removeAttributes(C, ArgNo + FirstArgIndex, AttrsToRemove);
+ }
+
+ /// \brief Remove all attributes at the specified arg index from this
+ /// attribute list. Returns a new list because attribute lists are immutable.
+ AttributeList removeParamAttributes(LLVMContext &C, unsigned ArgNo) const {
+ return removeAttributes(C, ArgNo + FirstArgIndex);
+ }
+
+ /// \Brief Add the dereferenceable attribute to the attribute set at the given
+ /// index. Returns a new list because attribute lists are immutable.
AttributeList addDereferenceableAttr(LLVMContext &C, unsigned Index,
uint64_t Bytes) const;
+ /// \Brief Add the dereferenceable attribute to the attribute set at the given
+ /// arg index. Returns a new list because attribute lists are immutable.
+ AttributeList addDereferenceableParamAttr(LLVMContext &C, unsigned ArgNo,
+ uint64_t Bytes) const {
+ return addDereferenceableAttr(C, ArgNo + FirstArgIndex, Bytes);
+ }
+
/// \brief Add the dereferenceable_or_null attribute to the attribute set at
- /// the given index. Because attribute sets are immutable, this returns a new
- /// set.
+ /// the given index. Returns a new list because attribute lists are immutable.
AttributeList addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index,
uint64_t Bytes) const;
+ /// \brief Add the dereferenceable_or_null attribute to the attribute set at
+ /// the given arg index. Returns a new list because attribute lists are
+ /// immutable.
+ AttributeList addDereferenceableOrNullParamAttr(LLVMContext &C,
+ unsigned ArgNo,
+ uint64_t Bytes) const {
+ return addDereferenceableOrNullAttr(C, ArgNo + FirstArgIndex, Bytes);
+ }
+
/// Add the allocsize attribute to the attribute set at the given index.
- /// Because attribute sets are immutable, this returns a new set.
+ /// Returns a new list because attribute lists are immutable.
AttributeList addAllocSizeAttr(LLVMContext &C, unsigned Index,
unsigned ElemSizeArg,
const Optional<unsigned> &NumElemsArg);
+ /// Add the allocsize attribute to the attribute set at the given arg index.
+ /// Returns a new list because attribute lists are immutable.
+ AttributeList addAllocSizeParamAttr(LLVMContext &C, unsigned ArgNo,
+ unsigned ElemSizeArg,
+ const Optional<unsigned> &NumElemsArg) {
+ return addAllocSizeAttr(C, ArgNo + FirstArgIndex, ElemSizeArg, NumElemsArg);
+ }
+
//===--------------------------------------------------------------------===//
// AttributeList Accessors
//===--------------------------------------------------------------------===//
@@ -473,6 +535,21 @@ public:
/// \brief Return true if attribute exists at the given index.
bool hasAttributes(unsigned Index) const;
+ /// \brief Return true if the attribute exists for the given argument
+ bool hasParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const {
+ return hasAttribute(ArgNo + FirstArgIndex, Kind);
+ }
+
+ /// \brief Return true if the attribute exists for the given argument
+ bool hasParamAttr(unsigned ArgNo, StringRef Kind) const {
+ return hasAttribute(ArgNo + FirstArgIndex, Kind);
+ }
+
+ /// \brief Return true if attributes exists for the given argument
+ bool hasParamAttrs(unsigned ArgNo) const {
+ return hasAttributes(ArgNo + FirstArgIndex);
+ }
+
/// \brief Equivalent to hasAttribute(AttributeList::FunctionIndex, Kind) but
/// may be faster.
bool hasFnAttribute(Attribute::AttrKind Kind) const;
@@ -496,6 +573,16 @@ public:
/// \brief Return the attribute object that exists at the given index.
Attribute getAttribute(unsigned Index, StringRef Kind) const;
+ /// \brief Return the attribute object that exists at the arg index.
+ Attribute getParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const {
+ return getAttribute(ArgNo + FirstArgIndex, Kind);
+ }
+
+ /// \brief Return the attribute object that exists at the given index.
+ Attribute getParamAttr(unsigned ArgNo, StringRef Kind) const {
+ return getAttribute(ArgNo + FirstArgIndex, Kind);
+ }
+
/// \brief Return the alignment of the return value.
unsigned getRetAlignment() const;
@@ -508,10 +595,22 @@ public:
/// \brief Get the number of dereferenceable bytes (or zero if unknown).
uint64_t getDereferenceableBytes(unsigned Index) const;
+ /// \brief Get the number of dereferenceable bytes (or zero if unknown) of an
+ /// arg.
+ uint64_t getParamDereferenceableBytes(unsigned ArgNo) const {
+ return getDereferenceableBytes(ArgNo + FirstArgIndex);
+ }
+
/// \brief Get the number of dereferenceable_or_null bytes (or zero if
/// unknown).
uint64_t getDereferenceableOrNullBytes(unsigned Index) const;
+ /// \brief Get the number of dereferenceable_or_null bytes (or zero if
+ /// unknown) of an arg.
+ uint64_t getParamDereferenceableOrNullBytes(unsigned ArgNo) const {
+ return getDereferenceableOrNullBytes(ArgNo + FirstArgIndex);
+ }
+
/// Get the allocsize argument numbers (or pair(0, 0) if unknown).
std::pair<unsigned, Optional<unsigned>>
getAllocSizeArgs(unsigned Index) const;
diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h
index f27e5c50a47f..29f512ddd076 100644
--- a/include/llvm/IR/Function.h
+++ b/include/llvm/IR/Function.h
@@ -214,10 +214,6 @@ public:
addAttribute(AttributeList::FunctionIndex, Attr);
}
- void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
- addAttribute(ArgNo + AttributeList::FirstArgIndex, Kind);
- }
-
/// @brief Remove function attributes from this function.
void removeFnAttr(Attribute::AttrKind Kind) {
removeAttribute(AttributeList::FunctionIndex, Kind);
@@ -229,10 +225,6 @@ public:
getContext(), AttributeList::FunctionIndex, Kind));
}
- void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
- removeAttribute(ArgNo + AttributeList::FirstArgIndex, Kind);
- }
-
/// \brief Set the entry count for this function.
///
/// Entry count is the number of times this function was executed based on
@@ -299,6 +291,15 @@ public:
/// @brief adds the attributes to the list of attributes.
void addAttributes(unsigned i, const AttrBuilder &Attrs);
+ /// @brief adds the attribute to the list of attributes for the given arg.
+ void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind);
+
+ /// @brief adds the attribute to the list of attributes for the given arg.
+ void addParamAttr(unsigned ArgNo, Attribute Attr);
+
+ /// @brief adds the attributes to the list of attributes for the given arg.
+ void addParamAttrs(unsigned ArgNo, const AttrBuilder &Attrs);
+
/// @brief removes the attribute from the list of attributes.
void removeAttribute(unsigned i, Attribute::AttrKind Kind);
@@ -308,6 +309,15 @@ public:
/// @brief removes the attributes from the list of attributes.
void removeAttributes(unsigned i, const AttrBuilder &Attrs);
+ /// @brief removes the attribute from the list of attributes.
+ void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind);
+
+ /// @brief removes the attribute from the list of attributes.
+ void removeParamAttr(unsigned ArgNo, StringRef Kind);
+
+ /// @brief removes the attribute from the list of attributes.
+ void removeParamAttrs(unsigned ArgNo, const AttrBuilder &Attrs);
+
/// @brief check if an attributes is in the list of attributes.
bool hasAttribute(unsigned i, Attribute::AttrKind Kind) const {
return getAttributes().hasAttribute(i, Kind);
@@ -329,10 +339,18 @@ public:
/// @brief adds the dereferenceable attribute to the list of attributes.
void addDereferenceableAttr(unsigned i, uint64_t Bytes);
+ /// @brief adds the dereferenceable attribute to the list of attributes for
+ /// the given arg.
+ void addDereferenceableParamAttr(unsigned ArgNo, uint64_t Bytes);
+
/// @brief adds the dereferenceable_or_null attribute to the list of
/// attributes.
void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes);
+ /// @brief adds the dereferenceable_or_null attribute to the list of
+ /// attributes for the given arg.
+ void addDereferenceableOrNullParamAttr(unsigned ArgNo, uint64_t Bytes);
+
/// @brief Extract the alignment for a call or parameter (0=unknown).
unsigned getParamAlignment(unsigned ArgNo) const {
return AttributeSets.getParamAlignment(ArgNo);
@@ -345,6 +363,12 @@ public:
return AttributeSets.getDereferenceableBytes(i);
}
+ /// @brief Extract the number of dereferenceable bytes for a parameter.
+ /// @param ArgNo Index of an argument, with 0 being the first function arg.
+ uint64_t getParamDereferenceableBytes(unsigned ArgNo) const {
+ return AttributeSets.getParamDereferenceableBytes(ArgNo);
+ }
+
/// @brief Extract the number of dereferenceable_or_null bytes for a call or
/// parameter (0=unknown).
/// @param i AttributeList index, referring to a return value or argument.
@@ -352,6 +376,13 @@ public:
return AttributeSets.getDereferenceableOrNullBytes(i);
}
+ /// @brief Extract the number of dereferenceable_or_null bytes for a
+ /// parameter.
+ /// @param ArgNo AttributeList ArgNo, referring to an argument.
+ uint64_t getParamDereferenceableOrNullBytes(unsigned ArgNo) const {
+ return AttributeSets.getParamDereferenceableOrNullBytes(ArgNo);
+ }
+
/// @brief Determine if the function does not access memory.
bool doesNotAccessMemory() const {
return hasFnAttribute(Attribute::ReadNone);
diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h
index 6fab59613dd6..1f7990b99ebe 100644
--- a/include/llvm/IR/Instructions.h
+++ b/include/llvm/IR/Instructions.h
@@ -1660,6 +1660,9 @@ public:
/// Adds the attribute to the indicated argument
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind);
+ /// Adds the attribute to the indicated argument
+ void addParamAttr(unsigned ArgNo, Attribute Attr);
+
/// removes the attribute from the list of attributes.
void removeAttribute(unsigned i, Attribute::AttrKind Kind);
@@ -1669,6 +1672,9 @@ public:
/// Removes the attribute from the given argument
void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind);
+ /// Removes the attribute from the given argument
+ void removeParamAttr(unsigned ArgNo, StringRef Kind);
+
/// adds the dereferenceable attribute to the list of attributes.
void addDereferenceableAttr(unsigned i, uint64_t Bytes);
@@ -1704,6 +1710,18 @@ public:
return getAttributes().getAttribute(i, Kind);
}
+ /// Get the attribute of a given kind from a given arg
+ Attribute getParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const {
+ assert(ArgNo < getNumArgOperands() && "Out of bounds");
+ return getAttributes().getParamAttr(ArgNo, Kind);
+ }
+
+ /// Get the attribute of a given kind from a given arg
+ Attribute getParamAttr(unsigned ArgNo, StringRef Kind) const {
+ assert(ArgNo < getNumArgOperands() && "Out of bounds");
+ return getAttributes().getParamAttr(ArgNo, Kind);
+ }
+
/// Return true if the data operand at index \p i has the attribute \p
/// A.
///
diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h
index 3ca21c15577b..5b9796d4fba6 100644
--- a/include/llvm/InitializePasses.h
+++ b/include/llvm/InitializePasses.h
@@ -188,6 +188,7 @@ void initializeLintPass(PassRegistry&);
void initializeLiveDebugValuesPass(PassRegistry&);
void initializeLiveDebugVariablesPass(PassRegistry&);
void initializeLiveIntervalsPass(PassRegistry&);
+void initializeLiveRangeShrinkPass(PassRegistry&);
void initializeLiveRegMatrixPass(PassRegistry&);
void initializeLiveStacksPass(PassRegistry&);
void initializeLiveVariablesPass(PassRegistry&);
diff --git a/include/llvm/Object/WindowsResource.h b/include/llvm/Object/WindowsResource.h
index f94ad09ce0c6..2484f551aee0 100644
--- a/include/llvm/Object/WindowsResource.h
+++ b/include/llvm/Object/WindowsResource.h
@@ -30,11 +30,18 @@
#define LLVM_INCLUDE_LLVM_OBJECT_RESFILE_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Object/Binary.h"
+#include "llvm/Object/Error.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/COFF.h"
+#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+#include <map>
namespace llvm {
namespace object {
@@ -44,23 +51,44 @@ class WindowsResource;
class ResourceEntryRef {
public:
Error moveNext(bool &End);
+ bool checkTypeString() const { return IsStringType; }
+ ArrayRef<UTF16> getTypeString() const { return Type; }
+ uint16_t getTypeID() const { return TypeID; }
+ bool checkNameString() const { return IsStringName; }
+ ArrayRef<UTF16> getNameString() const { return Name; }
+ uint16_t getNameID() const { return NameID; }
+ uint16_t getLanguage() const { return Suffix->Language; }
private:
friend class WindowsResource;
ResourceEntryRef(BinaryStreamRef Ref, const WindowsResource *Owner,
Error &Err);
+
Error loadNext();
+ struct HeaderSuffix {
+ support::ulittle32_t DataVersion;
+ support::ulittle16_t MemoryFlags;
+ support::ulittle16_t Language;
+ support::ulittle32_t Version;
+ support::ulittle32_t Characteristics;
+ };
+
BinaryStreamReader Reader;
- BinaryStreamRef HeaderBytes;
- BinaryStreamRef DataBytes;
+ bool IsStringType;
+ ArrayRef<UTF16> Type;
+ uint16_t TypeID;
+ bool IsStringName;
+ ArrayRef<UTF16> Name;
+ uint16_t NameID;
+ const HeaderSuffix *Suffix = nullptr;
+ ArrayRef<uint8_t> Data;
const WindowsResource *OwningRes = nullptr;
};
class WindowsResource : public Binary {
public:
- ~WindowsResource() override;
Expected<ResourceEntryRef> getHeadEntry();
static bool classof(const Binary *V) { return V->isWinRes(); }
@@ -76,6 +104,36 @@ private:
BinaryByteStream BBS;
};
+class WindowsResourceParser {
+public:
+ WindowsResourceParser();
+
+ Error parse(WindowsResource *WR);
+
+ void printTree() const;
+
+private:
+ class TreeNode {
+ public:
+ TreeNode() = default;
+ explicit TreeNode(ArrayRef<UTF16> Ref);
+ void addEntry(const ResourceEntryRef &Entry);
+ void print(ScopedPrinter &Writer, StringRef Name) const;
+
+ private:
+ TreeNode &addTypeNode(const ResourceEntryRef &Entry);
+ TreeNode &addNameNode(const ResourceEntryRef &Entry);
+ TreeNode &addLanguageNode(const ResourceEntryRef &Entry);
+ TreeNode &addChild(uint32_t ID);
+ TreeNode &addChild(ArrayRef<UTF16> NameRef);
+ std::vector<UTF16> Name;
+ std::map<uint32_t, std::unique_ptr<TreeNode>> IDChildren;
+ std::map<std::string, std::unique_ptr<TreeNode>> StringChildren;
+ };
+
+ TreeNode Root;
+};
+
} // namespace object
} // namespace llvm
diff --git a/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h b/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h
new file mode 100644
index 000000000000..6ddae2e2b41c
--- /dev/null
+++ b/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h
@@ -0,0 +1,91 @@
+//===- CodeViewYAMLDebugSections.h - CodeView YAMLIO debug sections -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines classes for handling the YAML representation of CodeView
+// Debug Info.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECTYAML_CODEVIEWYAMLDEBUGSECTIONS_H
+#define LLVM_OBJECTYAML_CODEVIEWYAMLDEBUGSECTIONS_H
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
+#include "llvm/ObjectYAML/YAML.h"
+
+namespace llvm {
+namespace CodeViewYAML {
+namespace detail {
+struct C13FragmentBase;
+}
+
+struct SourceLineEntry {
+ uint32_t Offset;
+ uint32_t LineStart;
+ uint32_t EndDelta;
+ bool IsStatement;
+};
+
+struct SourceColumnEntry {
+ uint16_t StartColumn;
+ uint16_t EndColumn;
+};
+
+struct SourceLineBlock {
+ StringRef FileName;
+ std::vector<SourceLineEntry> Lines;
+ std::vector<SourceColumnEntry> Columns;
+};
+
+struct HexFormattedString {
+ std::vector<uint8_t> Bytes;
+};
+
+struct SourceFileChecksumEntry {
+ StringRef FileName;
+ codeview::FileChecksumKind Kind;
+ HexFormattedString ChecksumBytes;
+};
+
+struct SourceLineInfo {
+ uint32_t RelocOffset;
+ uint32_t RelocSegment;
+ codeview::LineFlags Flags;
+ uint32_t CodeSize;
+
+ std::vector<SourceLineBlock> Blocks;
+};
+
+struct InlineeSite {
+ uint32_t Inlinee;
+ StringRef FileName;
+ uint32_t SourceLineNum;
+ std::vector<StringRef> ExtraFiles;
+};
+
+struct InlineeInfo {
+ bool HasExtraFiles;
+ std::vector<InlineeSite> Sites;
+};
+
+struct SourceFileInfo {
+ std::vector<SourceFileChecksumEntry> FileChecksums;
+ std::vector<SourceLineInfo> LineFragments;
+ std::vector<InlineeInfo> Inlinees;
+};
+
+struct C13DebugSection {
+ std::vector<detail::C13FragmentBase> Fragments;
+};
+} // namespace CodeViewYAML
+} // namespace llvm
+
+LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::SourceFileInfo)
+
+#endif
diff --git a/include/llvm/ObjectYAML/CodeViewYAMLSymbols.h b/include/llvm/ObjectYAML/CodeViewYAMLSymbols.h
new file mode 100644
index 000000000000..ee4e2ac9d404
--- /dev/null
+++ b/include/llvm/ObjectYAML/CodeViewYAMLSymbols.h
@@ -0,0 +1,41 @@
+//===- CodeViewYAMLSymbols.h - CodeView YAMLIO Symbol implementation ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines classes for handling the YAML representation of CodeView
+// Debug Info.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECTYAML_CODEVIEWYAMLSYMBOLS_H
+#define LLVM_OBJECTYAML_CODEVIEWYAMLSYMBOLS_H
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/ObjectYAML/YAML.h"
+
+namespace llvm {
+namespace CodeViewYAML {
+namespace detail {
+struct SymbolRecordBase;
+}
+
+struct SymbolRecord {
+ std::shared_ptr<detail::SymbolRecordBase> Symbol;
+
+ codeview::CVSymbol toCodeViewSymbol(BumpPtrAllocator &Allocator) const;
+ static Expected<SymbolRecord> fromCodeViewSymbol(codeview::CVSymbol Symbol);
+};
+
+} // namespace CodeViewYAML
+} // namespace llvm
+
+LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::SymbolRecord)
+LLVM_YAML_IS_SEQUENCE_VECTOR(CodeViewYAML::SymbolRecord)
+
+#endif
diff --git a/include/llvm/ObjectYAML/CodeViewYAMLTypes.h b/include/llvm/ObjectYAML/CodeViewYAMLTypes.h
new file mode 100644
index 000000000000..a57ada34a4fa
--- /dev/null
+++ b/include/llvm/ObjectYAML/CodeViewYAMLTypes.h
@@ -0,0 +1,48 @@
+//===- CodeViewYAMLTypes.h - CodeView YAMLIO Type Record implementation ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines classes for handling the YAML representation of CodeView
+// Debug Info.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECTYAML_CODEVIEWYAMLTYPES_H
+#define LLVM_OBJECTYAML_CODEVIEWYAMLTYPES_H
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/ObjectYAML/YAML.h"
+
+namespace llvm {
+namespace CodeViewYAML {
+namespace detail {
+struct LeafRecordBase;
+struct MemberRecordBase;
+}
+
+struct MemberRecord {
+ std::shared_ptr<detail::MemberRecordBase> Member;
+};
+
+struct LeafRecord {
+ std::shared_ptr<detail::LeafRecordBase> Leaf;
+
+ codeview::CVType toCodeViewRecord(BumpPtrAllocator &Allocator) const;
+ static Expected<LeafRecord> fromCodeViewRecord(codeview::CVType Type);
+};
+} // namespace CodeViewYAML
+} // namespace llvm
+
+LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::LeafRecord)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::MemberRecord)
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(CodeViewYAML::LeafRecord)
+LLVM_YAML_IS_SEQUENCE_VECTOR(CodeViewYAML::MemberRecord)
+
+#endif
diff --git a/include/llvm/Passes/PassBuilder.h b/include/llvm/Passes/PassBuilder.h
index efa36d957fbd..12b05e4ff0c5 100644
--- a/include/llvm/Passes/PassBuilder.h
+++ b/include/llvm/Passes/PassBuilder.h
@@ -192,6 +192,39 @@ public:
buildFunctionSimplificationPipeline(OptimizationLevel Level,
bool DebugLogging = false);
+ /// Construct the core LLVM module canonicalization and simplification
+ /// pipeline.
+ ///
+ /// This pipeline focuses on canonicalizing and simplifying the entire module
+ /// of IR. Much like the function simplification pipeline above, it is
+ /// suitable to run repeatedly over the IR and is not expected to destroy
+ /// important information. It does, however, perform inlining and other
+ /// heuristic based simplifications that are not strictly reversible.
+ ///
+ /// Note that \p Level cannot be `O0` here. The pipelines produced are
+ /// only intended for use when attempting to optimize code. If frontends
+ /// require some transformations for semantic reasons, they should explicitly
+ /// build them.
+ ModulePassManager
+ buildModuleSimplificationPipeline(OptimizationLevel Level,
+ bool DebugLogging = false);
+
+ /// Construct the core LLVM module optimization pipeline.
+ ///
+ /// This pipeline focuses on optimizing the execution speed of the IR. It
+ /// uses cost modeling and thresholds to balance code growth against runtime
+ /// improvements. It includes vectorization and other information destroying
+ /// transformations. It also cannot generally be run repeatedly on a module
+ /// without potentially seriously regressing either runtime performance of
+ /// the code or serious code size growth.
+ ///
+ /// Note that \p Level cannot be `O0` here. The pipelines produced are
+ /// only intended for use when attempting to optimize code. If frontends
+ /// require some transformations for semantic reasons, they should explicitly
+ /// build them.
+ ModulePassManager buildModuleOptimizationPipeline(OptimizationLevel Level,
+ bool DebugLogging = false);
+
/// Build a per-module default optimization pipeline.
///
/// This provides a good default optimization pipeline for per-module
@@ -206,6 +239,36 @@ public:
ModulePassManager buildPerModuleDefaultPipeline(OptimizationLevel Level,
bool DebugLogging = false);
+ /// Build a pre-link, ThinLTO-targeting default optimization pipeline to
+ /// a pass manager.
+ ///
+ /// This adds the pre-link optimizations tuned to prepare a module for
+ /// a ThinLTO run. It works to minimize the IR which needs to be analyzed
+ /// without making irreversible decisions which could be made better during
+ /// the LTO run.
+ ///
+ /// Note that \p Level cannot be `O0` here. The pipelines produced are
+ /// only intended for use when attempting to optimize code. If frontends
+ /// require some transformations for semantic reasons, they should explicitly
+ /// build them.
+ ModulePassManager
+ buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level,
+ bool DebugLogging = false);
+
+ /// Build an ThinLTO default optimization pipeline to a pass manager.
+ ///
+ /// This provides a good default optimization pipeline for link-time
+ /// optimization and code generation. It is particularly tuned to fit well
+ /// when IR coming into the LTO phase was first run through \c
+ /// addPreLinkLTODefaultPipeline, and the two coordinate closely.
+ ///
+ /// Note that \p Level cannot be `O0` here. The pipelines produced are
+ /// only intended for use when attempting to optimize code. If frontends
+ /// require some transformations for semantic reasons, they should explicitly
+ /// build them.
+ ModulePassManager buildThinLTODefaultPipeline(OptimizationLevel Level,
+ bool DebugLogging = false);
+
/// Build a pre-link, LTO-targeting default optimization pipeline to a pass
/// manager.
///
diff --git a/include/llvm/Support/ARMTargetParser.def b/include/llvm/Support/ARMTargetParser.def
index 32dc57a0fedf..65cb2715a6a5 100644
--- a/include/llvm/Support/ARMTargetParser.def
+++ b/include/llvm/Support/ARMTargetParser.def
@@ -206,7 +206,7 @@ ARM_CPU_NAME("cortex-a5", AK_ARMV7A, FK_NEON_VFPV4, false,
ARM_CPU_NAME("cortex-a7", AK_ARMV7A, FK_NEON_VFPV4, false,
(ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
ARM::AEK_HWDIVTHUMB))
-ARM_CPU_NAME("cortex-a8", AK_ARMV7A, FK_NEON, true, ARM::AEK_SEC)
+ARM_CPU_NAME("cortex-a8", AK_ARMV7A, FK_NEON, false, ARM::AEK_SEC)
ARM_CPU_NAME("cortex-a9", AK_ARMV7A, FK_NEON_FP16, false, (ARM::AEK_SEC | ARM::AEK_MP))
ARM_CPU_NAME("cortex-a12", AK_ARMV7A, FK_NEON_VFPV4, false,
(ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
@@ -236,7 +236,7 @@ ARM_CPU_NAME("cortex-m23", AK_ARMV8MBaseline, FK_NONE, false, ARM::AEK_NONE)
ARM_CPU_NAME("cortex-m33", AK_ARMV8MMainline, FK_FPV5_SP_D16, false, ARM::AEK_DSP)
ARM_CPU_NAME("cortex-a32", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("cortex-a35", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
-ARM_CPU_NAME("cortex-a53", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, true, ARM::AEK_CRC)
+ARM_CPU_NAME("cortex-a53", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("cortex-a57", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("cortex-a72", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("cortex-a73", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
diff --git a/include/llvm/Support/BinaryStreamReader.h b/include/llvm/Support/BinaryStreamReader.h
index 56375f41d2c0..29e8a2ab08aa 100644
--- a/include/llvm/Support/BinaryStreamReader.h
+++ b/include/llvm/Support/BinaryStreamReader.h
@@ -14,6 +14,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/BinaryStreamRef.h"
+#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/type_traits.h"
@@ -104,6 +105,13 @@ public:
/// returns an appropriate error code.
Error readCString(StringRef &Dest);
+ /// Similar to readCString, however read a null-terminated UTF16 string
+ /// instead.
+ ///
+ /// \returns a success error code if the data was successfully read, otherwise
+ /// returns an appropriate error code.
+ Error readWideString(ArrayRef<UTF16> &Dest);
+
/// Read a \p Length byte string into \p Dest. Whether a copy occurs depends
/// on the implementation of the underlying stream. Updates the stream's
/// offset to point after the newly read data.
diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h
index ffea679fab82..8949d69ce724 100644
--- a/include/llvm/Support/YAMLTraits.h
+++ b/include/llvm/Support/YAMLTraits.h
@@ -1606,6 +1606,44 @@ template <typename T> struct StdMapStringCustomMappingTraitsImpl {
} \
}
+#define LLVM_YAML_DECLARE_MAPPING_TRAITS(Type) \
+ namespace llvm { \
+ namespace yaml { \
+ template <> struct MappingTraits<Type> { \
+ static void mapping(IO &IO, Type &Obj); \
+ }; \
+ } \
+ }
+
+#define LLVM_YAML_DECLARE_ENUM_TRAITS(Type) \
+ namespace llvm { \
+ namespace yaml { \
+ template <> struct ScalarEnumerationTraits<Type> { \
+ static void enumeration(IO &io, Type &Value); \
+ }; \
+ } \
+ }
+
+#define LLVM_YAML_DECLARE_BITSET_TRAITS(Type) \
+ namespace llvm { \
+ namespace yaml { \
+ template <> struct ScalarBitSetTraits<Type> { \
+ static void bitset(IO &IO, Type &Options); \
+ }; \
+ } \
+ }
+
+#define LLVM_YAML_DECLARE_SCALAR_TRAITS(Type, MustQuote) \
+ namespace llvm { \
+ namespace yaml { \
+ template <> struct ScalarTraits<Type> { \
+ static void output(const Type &Value, void *ctx, llvm::raw_ostream &Out); \
+ static StringRef input(StringRef Scalar, void *ctxt, Type &Value); \
+ static bool mustQuote(StringRef) { return MustQuote; } \
+ }; \
+ } \
+ }
+
/// Utility for declaring that a std::vector of a particular type
/// should be considered a YAML document list.
#define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type) \
diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h
index 437f68b24e57..3c181f0e511b 100644
--- a/include/llvm/TableGen/Record.h
+++ b/include/llvm/TableGen/Record.h
@@ -1237,7 +1237,6 @@ class RecordVal {
public:
RecordVal(Init *N, RecTy *T, bool P);
- RecordVal(StringRef N, RecTy *T, bool P);
StringRef getName() const;
Init *getNameInit() const { return Name; }
@@ -1340,7 +1339,6 @@ public:
}
void setName(Init *Name); // Also updates RecordKeeper.
- void setName(StringRef Name); // Also updates RecordKeeper.
ArrayRef<SMLoc> getLoc() const { return Locs; }
@@ -1378,13 +1376,11 @@ public:
}
RecordVal *getValue(const Init *Name) {
- for (RecordVal &Val : Values)
- if (Val.Name == Name) return &Val;
- return nullptr;
+ return const_cast<RecordVal *>(static_cast<const Record *>(this)->getValue(Name));
}
RecordVal *getValue(StringRef Name) {
- return getValue(StringInit::get(Name));
+ return const_cast<RecordVal *>(static_cast<const Record *>(this)->getValue(Name));
}
void addTemplateArg(Init *Name) {
@@ -1492,7 +1488,7 @@ public:
/// its value as a string, throwing an exception if the field does not exist
/// or if the value is not a string.
///
- std::string getValueAsString(StringRef FieldName) const;
+ StringRef getValueAsString(StringRef FieldName) const;
/// This method looks up the specified field and returns
/// its value as a BitsInit, throwing an exception if the field does not exist
@@ -1522,7 +1518,7 @@ public:
/// returns its value as a vector of strings, throwing an exception if the
/// field does not exist or if the value is not the right type.
///
- std::vector<std::string> getValueAsListOfStrings(StringRef FieldName) const;
+ std::vector<StringRef> getValueAsListOfStrings(StringRef FieldName) const;
/// This method looks up the specified field and returns its
/// value as a Record, throwing an exception if the field does not exist or if
diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h
index 17182b958ecb..7258a5cc2d89 100644
--- a/include/llvm/Target/TargetLowering.h
+++ b/include/llvm/Target/TargetLowering.h
@@ -1143,6 +1143,16 @@ public:
return OptSize ? MaxStoresPerMemcpyOptSize : MaxStoresPerMemcpy;
}
+ /// Get maximum # of load operations permitted for memcmp
+ ///
+ /// This function returns the maximum number of load operations permitted
+ /// to replace a call to memcmp. The value is set by the target at the
+ /// performance threshold for such a replacement. If OptSize is true,
+ /// return the limit for functions that have OptSize attribute.
+ unsigned getMaxExpandSizeMemcmp(bool OptSize) const {
+ return OptSize ? MaxLoadsPerMemcmpOptSize : MaxLoadsPerMemcmp;
+ }
+
/// \brief Get maximum # of store operations permitted for llvm.memmove
///
/// This function returns the maximum number of store operations permitted
@@ -2330,6 +2340,8 @@ protected:
/// Maximum number of store operations that may be substituted for a call to
/// memcpy, used for functions with OptSize attribute.
unsigned MaxStoresPerMemcpyOptSize;
+ unsigned MaxLoadsPerMemcmp;
+ unsigned MaxLoadsPerMemcmpOptSize;
/// \brief Specify maximum bytes of store instructions per memmove call.
///
diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h
index 73ae2ad12988..ed390799cfc3 100644
--- a/include/llvm/Target/TargetMachine.h
+++ b/include/llvm/Target/TargetMachine.h
@@ -299,6 +299,12 @@ public:
bool addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx,
raw_pwrite_stream &OS,
bool DisableVerify = true) override;
+
+ /// Returns true if the target is expected to pass all machine verifier
+ /// checks. This is a stopgap measure to fix targets one by one. We will
+ /// remove this at some point and always enable the verifier when
+ /// EXPENSIVE_CHECKS is enabled.
+ virtual bool isMachineVerifierClean() const { return true; }
};
} // end namespace llvm
diff --git a/include/llvm/Transforms/IPO/ThinLTOBitcodeWriter.h b/include/llvm/Transforms/IPO/ThinLTOBitcodeWriter.h
new file mode 100644
index 000000000000..bf04bbfe92d8
--- /dev/null
+++ b/include/llvm/Transforms/IPO/ThinLTOBitcodeWriter.h
@@ -0,0 +1,41 @@
+//===- ThinLTOBitcodeWriter.h - Bitcode writing pass for ThinLTO ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass prepares a module containing type metadata for ThinLTO by splitting
+// it into regular and thin LTO parts if possible, and writing both parts to
+// a multi-module bitcode file. Modules that do not contain type metadata are
+// written unmodified as a single module.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_IPO_THINLTOBITCODEWRITER_H
+#define LLVM_TRANSFORMS_IPO_THINLTOBITCODEWRITER_H
+
+#include <llvm/IR/PassManager.h>
+#include <llvm/Support/raw_ostream.h>
+
+namespace llvm {
+
+class ThinLTOBitcodeWriterPass
+ : public PassInfoMixin<ThinLTOBitcodeWriterPass> {
+ raw_ostream &OS;
+ raw_ostream *ThinLinkOS;
+
+public:
+ // Writes bitcode to OS. Also write thin link file to ThinLinkOS, if
+ // it's not nullptr.
+ ThinLTOBitcodeWriterPass(raw_ostream &OS, raw_ostream *ThinLinkOS)
+ : OS(OS), ThinLinkOS(ThinLinkOS) {}
+
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
+};
+
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/Transforms/Scalar/GVN.h b/include/llvm/Transforms/Scalar/GVN.h
index 3f97789cabbc..589aaaca02fe 100644
--- a/include/llvm/Transforms/Scalar/GVN.h
+++ b/include/llvm/Transforms/Scalar/GVN.h
@@ -68,24 +68,6 @@ public:
class ValueTable {
DenseMap<Value *, uint32_t> valueNumbering;
DenseMap<Expression, uint32_t> expressionNumbering;
-
- // Expressions is the vector of Expression. ExprIdx is the mapping from
- // value number to the index of Expression in Expressions. We use it
- // instead of a DenseMap because filling such mapping is faster than
- // filling a DenseMap and the compile time is a little better.
- uint32_t nextExprNumber;
- std::vector<Expression> Expressions;
- std::vector<uint32_t> ExprIdx;
- // Value number to PHINode mapping. Used for phi-translate in scalarpre.
- DenseMap<uint32_t, PHINode *> NumberingPhi;
- // Cache for phi-translate in scalarpre.
- typedef DenseMap<std::pair<uint32_t, const BasicBlock *>, uint32_t>
- PhiTranslateMap;
- PhiTranslateMap PhiTranslateTable;
- // Map the block to reversed postorder traversal number. It is used to
- // find back edge easily.
- DenseMap<const BasicBlock *, uint32_t> BlockRPONumber;
-
AliasAnalysis *AA;
MemoryDependenceResults *MD;
DominatorTree *DT;
@@ -97,10 +79,6 @@ public:
Value *LHS, Value *RHS);
Expression createExtractvalueExpr(ExtractValueInst *EI);
uint32_t lookupOrAddCall(CallInst *C);
- uint32_t phiTranslateImpl(const BasicBlock *BB, const BasicBlock *PhiBlock,
- uint32_t Num, GVN &Gvn);
- std::pair<uint32_t, bool> assignExpNewValueNum(Expression &exp);
- bool areAllValsInBB(uint32_t num, const BasicBlock *BB, GVN &Gvn);
public:
ValueTable();
@@ -109,12 +87,9 @@ public:
~ValueTable();
uint32_t lookupOrAdd(Value *V);
- uint32_t lookup(Value *V, bool Verify = true) const;
+ uint32_t lookup(Value *V) const;
uint32_t lookupOrAddCmp(unsigned Opcode, CmpInst::Predicate Pred,
Value *LHS, Value *RHS);
- uint32_t phiTranslate(const BasicBlock *BB, const BasicBlock *PhiBlock,
- uint32_t Num, GVN &Gvn);
- void assignBlockRPONumber(Function &F);
bool exists(Value *V) const;
void add(Value *V, uint32_t num);
void clear();
diff --git a/include/llvm/Transforms/Utils/CodeExtractor.h b/include/llvm/Transforms/Utils/CodeExtractor.h
index a602498e5f22..7e23544af1ab 100644
--- a/include/llvm/Transforms/Utils/CodeExtractor.h
+++ b/include/llvm/Transforms/Utils/CodeExtractor.h
@@ -25,6 +25,7 @@ template <typename T> class ArrayRef;
class BranchProbabilityInfo;
class DominatorTree;
class Function;
+ class Instruction;
class Loop;
class Module;
class RegionNode;
@@ -103,7 +104,17 @@ template <typename T> class ArrayRef;
/// a code sequence, that sequence is modified, including changing these
/// sets, before extraction occurs. These modifications won't have any
/// significant impact on the cost however.
- void findInputsOutputs(ValueSet &Inputs, ValueSet &Outputs) const;
+ void findInputsOutputs(ValueSet &Inputs, ValueSet &Outputs,
+ const ValueSet &Allocas) const;
+ /// Find the set of allocas whose life ranges are contained within the
+ /// outlined region.
+ ///
+ /// Allocas which have life_time markers contained in the outlined region
+ /// should be pushed to the outlined function. The address bitcasts that
+ /// are used by the lifetime markers are also candidates for shrink-
+ /// wrapping. The instructions that need to be sinked are collected in
+ /// 'Allocas'.
+ void findAllocas(ValueSet &Allocas) const;
private:
void severSplitPHINodes(BasicBlock *&Header);
diff --git a/include/llvm/module.modulemap b/include/llvm/module.modulemap
index 5e15e8d49802..e0780885d159 100644
--- a/include/llvm/module.modulemap
+++ b/include/llvm/module.modulemap
@@ -95,8 +95,8 @@ module LLVM_DebugInfo_CodeView {
module * { export * }
// These are intended for (repeated) textual inclusion.
- textual header "DebugInfo/CodeView/TypeRecords.def"
- textual header "DebugInfo/CodeView/CVSymbolTypes.def"
+ textual header "DebugInfo/CodeView/CodeViewTypes.def"
+ textual header "DebugInfo/CodeView/CodeViewSymbols.def"
}
module LLVM_ExecutionEngine {
diff --git a/lib/Analysis/CFLGraph.h b/lib/Analysis/CFLGraph.h
index a8fb12b72568..54782b6bd4ad 100644
--- a/lib/Analysis/CFLGraph.h
+++ b/lib/Analysis/CFLGraph.h
@@ -210,6 +210,11 @@ template <typename CFLAA> class CFLGraphBuilder {
void addDerefEdge(Value *From, Value *To, bool IsRead) {
assert(From != nullptr && To != nullptr);
+ // FIXME: This is subtly broken, due to how we model some instructions
+ // (e.g. extractvalue, extractelement) as loads. Since those take
+ // non-pointer operands, we'll entirely skip adding edges for those.
+ //
+ // addAssignEdge seems to have a similar issue with insertvalue, etc.
if (!From->getType()->isPointerTy() || !To->getType()->isPointerTy())
return;
addNode(From);
@@ -540,6 +545,7 @@ template <typename CFLAA> class CFLGraphBuilder {
case Instruction::ExtractValue: {
auto *Ptr = CE->getOperand(0);
addLoadEdge(Ptr, CE);
+ break;
}
case Instruction::ShuffleVector: {
auto *From1 = CE->getOperand(0);
diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp
index 79517ec6a3a8..6a1af87450c9 100644
--- a/lib/Analysis/ConstantFolding.cpp
+++ b/lib/Analysis/ConstantFolding.cpp
@@ -1739,6 +1739,7 @@ Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, Type *Ty,
if ((Name == "round" && TLI->has(LibFunc_round)) ||
(Name == "roundf" && TLI->has(LibFunc_roundf)))
return ConstantFoldFP(round, V, Ty);
+ break;
case 's':
if ((Name == "sin" && TLI->has(LibFunc_sin)) ||
(Name == "sinf" && TLI->has(LibFunc_sinf)))
@@ -1807,6 +1808,7 @@ Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, Type *Ty,
dyn_cast_or_null<ConstantFP>(Op->getAggregateElement(0U)))
return ConstantFoldSSEConvertToInt(FPOp->getValueAPF(),
/*roundTowardZero=*/false, Ty);
+ LLVM_FALLTHROUGH;
case Intrinsic::x86_sse_cvttss2si:
case Intrinsic::x86_sse_cvttss2si64:
case Intrinsic::x86_sse2_cvttsd2si:
diff --git a/lib/Analysis/EHPersonalities.cpp b/lib/Analysis/EHPersonalities.cpp
index ebf0a370b0b0..b12ae9884e3d 100644
--- a/lib/Analysis/EHPersonalities.cpp
+++ b/lib/Analysis/EHPersonalities.cpp
@@ -27,8 +27,10 @@ EHPersonality llvm::classifyEHPersonality(const Value *Pers) {
return StringSwitch<EHPersonality>(F->getName())
.Case("__gnat_eh_personality", EHPersonality::GNU_Ada)
.Case("__gxx_personality_v0", EHPersonality::GNU_CXX)
+ .Case("__gxx_personality_seh0",EHPersonality::GNU_CXX)
.Case("__gxx_personality_sj0", EHPersonality::GNU_CXX_SjLj)
.Case("__gcc_personality_v0", EHPersonality::GNU_C)
+ .Case("__gcc_personality_seh0",EHPersonality::GNU_C)
.Case("__gcc_personality_sj0", EHPersonality::GNU_C_SjLj)
.Case("__objc_personality_v0", EHPersonality::GNU_ObjC)
.Case("_except_handler3", EHPersonality::MSVC_X86SEH)
diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp
index 122442bafb11..66ac847455cd 100644
--- a/lib/Analysis/InstructionSimplify.cpp
+++ b/lib/Analysis/InstructionSimplify.cpp
@@ -103,13 +103,8 @@ static bool ValueDominatesPHI(Value *V, PHINode *P, const DominatorTree *DT) {
return false;
// If we have a DominatorTree then do a precise test.
- if (DT) {
- if (!DT->isReachableFromEntry(P->getParent()))
- return true;
- if (!DT->isReachableFromEntry(I->getParent()))
- return false;
+ if (DT)
return DT->dominates(I, P);
- }
// Otherwise, if the instruction is in the entry block and is not an invoke,
// then it obviously dominates all phi nodes.
diff --git a/lib/Analysis/MemoryDependenceAnalysis.cpp b/lib/Analysis/MemoryDependenceAnalysis.cpp
index 66a0d145dcd8..188885063b39 100644
--- a/lib/Analysis/MemoryDependenceAnalysis.cpp
+++ b/lib/Analysis/MemoryDependenceAnalysis.cpp
@@ -691,6 +691,7 @@ MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom(
// load query, we can safely ignore it (scan past it).
if (isLoad)
continue;
+ LLVM_FALLTHROUGH;
default:
// Otherwise, there is a potential dependence. Return a clobber.
return MemDepResult::getClobber(Inst);
diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp
index f55ce202bcbb..d96697cafbe9 100644
--- a/lib/Analysis/ScalarEvolution.cpp
+++ b/lib/Analysis/ScalarEvolution.cpp
@@ -8182,6 +8182,7 @@ bool ScalarEvolution::isKnownPredicateViaNoOverflow(ICmpInst::Predicate Pred,
case ICmpInst::ICMP_SGE:
std::swap(LHS, RHS);
+ LLVM_FALLTHROUGH;
case ICmpInst::ICMP_SLE:
// X s<= (X + C)<nsw> if C >= 0
if (MatchBinaryAddToConst(RHS, LHS, C, SCEV::FlagNSW) && C.isNonNegative())
@@ -8195,6 +8196,7 @@ bool ScalarEvolution::isKnownPredicateViaNoOverflow(ICmpInst::Predicate Pred,
case ICmpInst::ICMP_SGT:
std::swap(LHS, RHS);
+ LLVM_FALLTHROUGH;
case ICmpInst::ICMP_SLT:
// X s< (X + C)<nsw> if C > 0
if (MatchBinaryAddToConst(RHS, LHS, C, SCEV::FlagNSW) &&
@@ -8552,6 +8554,7 @@ bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS,
if (isImpliedCondOperands(Pred, LHS, RHS, V,
getConstant(SharperMin)))
return true;
+ LLVM_FALLTHROUGH;
case ICmpInst::ICMP_SGT:
case ICmpInst::ICMP_UGT:
@@ -8566,6 +8569,7 @@ bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS,
if (isImpliedCondOperands(Pred, LHS, RHS, V, getConstant(Min)))
return true;
+ LLVM_FALLTHROUGH;
default:
// No change
diff --git a/lib/Analysis/TargetTransformInfo.cpp b/lib/Analysis/TargetTransformInfo.cpp
index 7a8d4f3be24f..ac646716476b 100644
--- a/lib/Analysis/TargetTransformInfo.cpp
+++ b/lib/Analysis/TargetTransformInfo.cpp
@@ -215,6 +215,10 @@ bool TargetTransformInfo::enableAggressiveInterleaving(bool LoopHasReductions) c
return TTIImpl->enableAggressiveInterleaving(LoopHasReductions);
}
+bool TargetTransformInfo::expandMemCmp(Instruction *I, unsigned &MaxLoadSize) const {
+ return TTIImpl->expandMemCmp(I, MaxLoadSize);
+}
+
bool TargetTransformInfo::enableInterleavedAccessVectorization() const {
return TTIImpl->enableInterleavedAccessVectorization();
}
diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp
index bd79cd56a18b..a5dceb6c2271 100644
--- a/lib/Analysis/ValueTracking.cpp
+++ b/lib/Analysis/ValueTracking.cpp
@@ -172,6 +172,18 @@ bool llvm::haveNoCommonBitsSet(const Value *LHS, const Value *RHS,
}
+bool llvm::isOnlyUsedInZeroEqualityComparison(const Instruction *CxtI) {
+ for (const User *U : CxtI->users()) {
+ if (const ICmpInst *IC = dyn_cast<ICmpInst>(U))
+ if (IC->isEquality())
+ if (Constant *C = dyn_cast<Constant>(IC->getOperand(1)))
+ if (C->isNullValue())
+ continue;
+ return false;
+ }
+ return true;
+}
+
static bool isKnownToBeAPowerOfTwo(const Value *V, bool OrZero, unsigned Depth,
const Query &Q);
@@ -2327,6 +2339,7 @@ bool llvm::ComputeMultiple(Value *V, unsigned Base, Value *&Multiple,
case Instruction::SExt:
if (!LookThroughSExt) return false;
// otherwise fall through to ZExt
+ LLVM_FALLTHROUGH;
case Instruction::ZExt:
return ComputeMultiple(I->getOperand(0), Base, Multiple,
LookThroughSExt, Depth+1);
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index c1d81ac203a1..a402b4ddd462 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -378,18 +378,10 @@ private:
ModuleToSummariesForIndex->count(ModulePath);
}
- bool hasValueId(GlobalValue::GUID ValGUID) {
- const auto &VMI = GUIDToValueIdMap.find(ValGUID);
- return VMI != GUIDToValueIdMap.end();
- }
- void assignValueId(GlobalValue::GUID ValGUID) {
- unsigned &ValueId = GUIDToValueIdMap[ValGUID];
- if (ValueId == 0)
- ValueId = ++GlobalValueId;
- }
- unsigned getValueId(GlobalValue::GUID ValGUID) {
+ Optional<unsigned> getValueId(GlobalValue::GUID ValGUID) {
auto VMI = GUIDToValueIdMap.find(ValGUID);
- assert(VMI != GUIDToValueIdMap.end());
+ if (VMI == GUIDToValueIdMap.end())
+ return None;
return VMI->second;
}
std::map<GlobalValue::GUID, unsigned> &valueIds() { return GUIDToValueIdMap; }
@@ -3413,12 +3405,6 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
Stream.EnterSubblock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID, 3);
Stream.EmitRecord(bitc::FS_VERSION, ArrayRef<uint64_t>{INDEX_VERSION});
- // Create value IDs for undefined references.
- forEachSummary([&](GVInfo I) {
- for (auto &RI : I.second->refs())
- assignValueId(RI.getGUID());
- });
-
for (const auto &GVI : valueIds()) {
Stream.EmitRecord(bitc::FS_VALUE_GUID,
ArrayRef<uint64_t>{GVI.second, GVI.first});
@@ -3492,9 +3478,9 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
GlobalValueSummary *S = I.second;
assert(S);
- assert(hasValueId(I.first));
- unsigned ValueId = getValueId(I.first);
- SummaryToValueIdMap[S] = ValueId;
+ auto ValueId = getValueId(I.first);
+ assert(ValueId);
+ SummaryToValueIdMap[S] = *ValueId;
if (auto *AS = dyn_cast<AliasSummary>(S)) {
// Will process aliases as a post-pass because the reader wants all
@@ -3504,11 +3490,14 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
}
if (auto *VS = dyn_cast<GlobalVarSummary>(S)) {
- NameVals.push_back(ValueId);
+ NameVals.push_back(*ValueId);
NameVals.push_back(Index.getModuleId(VS->modulePath()));
NameVals.push_back(getEncodedGVSummaryFlags(VS->flags()));
for (auto &RI : VS->refs()) {
- NameVals.push_back(getValueId(RI.getGUID()));
+ auto RefValueId = getValueId(RI.getGUID());
+ if (!RefValueId)
+ continue;
+ NameVals.push_back(*RefValueId);
}
// Emit the finished record.
@@ -3522,15 +3511,22 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
auto *FS = cast<FunctionSummary>(S);
writeFunctionTypeMetadataRecords(Stream, FS);
- NameVals.push_back(ValueId);
+ NameVals.push_back(*ValueId);
NameVals.push_back(Index.getModuleId(FS->modulePath()));
NameVals.push_back(getEncodedGVSummaryFlags(FS->flags()));
NameVals.push_back(FS->instCount());
- NameVals.push_back(FS->refs().size());
+ // Fill in below
+ NameVals.push_back(0);
+ unsigned Count = 0;
for (auto &RI : FS->refs()) {
- NameVals.push_back(getValueId(RI.getGUID()));
+ auto RefValueId = getValueId(RI.getGUID());
+ if (!RefValueId)
+ continue;
+ NameVals.push_back(*RefValueId);
+ Count++;
}
+ NameVals[4] = Count;
bool HasProfileData = false;
for (auto &EI : FS->calls()) {
@@ -3543,15 +3539,19 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
// If this GUID doesn't have a value id, it doesn't have a function
// summary and we don't need to record any calls to it.
GlobalValue::GUID GUID = EI.first.getGUID();
- if (!hasValueId(GUID)) {
+ auto CallValueId = getValueId(GUID);
+ if (!CallValueId) {
// For SamplePGO, the indirect call targets for local functions will
// have its original name annotated in profile. We try to find the
// corresponding PGOFuncName as the GUID.
GUID = Index.getGUIDFromOriginalID(GUID);
- if (GUID == 0 || !hasValueId(GUID))
+ if (GUID == 0)
+ continue;
+ CallValueId = getValueId(GUID);
+ if (!CallValueId)
continue;
}
- NameVals.push_back(getValueId(GUID));
+ NameVals.push_back(*CallValueId);
if (HasProfileData)
NameVals.push_back(static_cast<uint8_t>(EI.second.Hotness));
}
diff --git a/lib/CodeGen/AggressiveAntiDepBreaker.cpp b/lib/CodeGen/AggressiveAntiDepBreaker.cpp
index 43b245c66400..5abf50e5bd10 100644
--- a/lib/CodeGen/AggressiveAntiDepBreaker.cpp
+++ b/lib/CodeGen/AggressiveAntiDepBreaker.cpp
@@ -165,7 +165,7 @@ void AggressiveAntiDepBreaker::StartBlock(MachineBasicBlock *BB) {
for (const MCPhysReg *I = MF.getRegInfo().getCalleeSavedRegs(); *I;
++I) {
unsigned Reg = *I;
- if (!IsReturnBlock && !(Pristine.test(Reg) || BB->isLiveIn(Reg)))
+ if (!IsReturnBlock && !Pristine.test(Reg))
continue;
for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
unsigned AliasReg = *AI;
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index d72cf5922987..e61e22abe82a 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -949,6 +949,19 @@ void AsmPrinter::emitFrameAlloc(const MachineInstr &MI) {
MCConstantExpr::create(FrameOffset, OutContext));
}
+static bool needFuncLabelsForEHOrDebugInfo(const MachineFunction &MF,
+ MachineModuleInfo *MMI) {
+ if (!MF.getLandingPads().empty() || MF.hasEHFunclets() || MMI->hasDebugInfo())
+ return true;
+
+ // We might emit an EH table that uses function begin and end labels even if
+ // we don't have any landingpads.
+ if (!MF.getFunction()->hasPersonalityFn())
+ return false;
+ return !isNoOpWithoutInvoke(
+ classifyEHPersonality(MF.getFunction()->getPersonalityFn()));
+}
+
/// EmitFunctionBody - This method emits the body and trailer for a
/// function.
void AsmPrinter::EmitFunctionBody() {
@@ -1076,8 +1089,8 @@ void AsmPrinter::EmitFunctionBody() {
// Emit target-specific gunk after the function body.
EmitFunctionBodyEnd();
- if (!MF->getLandingPads().empty() || MMI->hasDebugInfo() ||
- MF->hasEHFunclets() || MAI->hasDotTypeDotSizeDirective()) {
+ if (needFuncLabelsForEHOrDebugInfo(*MF, MMI) ||
+ MAI->hasDotTypeDotSizeDirective()) {
// Create a symbol for the end of function.
CurrentFnEnd = createTempSymbol("func_end");
OutStreamer->EmitLabel(CurrentFnEnd);
@@ -1402,8 +1415,7 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
CurrentFnBegin = nullptr;
CurExceptionSym = nullptr;
bool NeedsLocalForSize = MAI->needsLocalForSize();
- if (!MF.getLandingPads().empty() || MMI->hasDebugInfo() ||
- MF.hasEHFunclets() || NeedsLocalForSize) {
+ if (needFuncLabelsForEHOrDebugInfo(MF, MMI) || NeedsLocalForSize) {
CurrentFnBegin = createTempSymbol("func_begin");
if (NeedsLocalForSize)
CurrentFnSymForSize = CurrentFnBegin;
diff --git a/lib/CodeGen/AsmPrinter/EHStreamer.cpp b/lib/CodeGen/AsmPrinter/EHStreamer.cpp
index 0a4a7a06cb2e..e14d5be1177a 100644
--- a/lib/CodeGen/AsmPrinter/EHStreamer.cpp
+++ b/lib/CodeGen/AsmPrinter/EHStreamer.cpp
@@ -309,7 +309,7 @@ computeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
// If some instruction between the previous try-range and the end of the
// function may throw, create a call-site entry with no landing pad for the
// region following the try-range.
- if (SawPotentiallyThrowing && !IsSJLJ && LastLabel != nullptr) {
+ if (SawPotentiallyThrowing && !IsSJLJ) {
CallSiteEntry Site = { LastLabel, nullptr, nullptr, 0 };
CallSites.push_back(Site);
}
diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt
index 2b5863aa5800..55a27e2fb79e 100644
--- a/lib/CodeGen/CMakeLists.txt
+++ b/lib/CodeGen/CMakeLists.txt
@@ -49,6 +49,7 @@ add_llvm_library(LLVMCodeGen
LivePhysRegs.cpp
LiveRangeCalc.cpp
LiveRangeEdit.cpp
+ LiveRangeShrink.cpp
LiveRegMatrix.cpp
LiveRegUnits.cpp
LiveStackAnalysis.cpp
diff --git a/lib/CodeGen/CodeGen.cpp b/lib/CodeGen/CodeGen.cpp
index 2a2715beaadc..4d30c6574b12 100644
--- a/lib/CodeGen/CodeGen.cpp
+++ b/lib/CodeGen/CodeGen.cpp
@@ -43,6 +43,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
initializeLiveDebugValuesPass(Registry);
initializeLiveDebugVariablesPass(Registry);
initializeLiveIntervalsPass(Registry);
+ initializeLiveRangeShrinkPass(Registry);
initializeLiveStacksPass(Registry);
initializeLiveVariablesPass(Registry);
initializeLocalStackSlotPassPass(Registry);
diff --git a/lib/CodeGen/CodeGenPrepare.cpp b/lib/CodeGen/CodeGenPrepare.cpp
index 4e85708efafc..568b278dd47c 100644
--- a/lib/CodeGen/CodeGenPrepare.cpp
+++ b/lib/CodeGen/CodeGenPrepare.cpp
@@ -24,12 +24,13 @@
#include "llvm/Analysis/CFG.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/ValueTracking.h"
-#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/CodeGen/Analysis.h"
+#include "llvm/CodeGen/Passes.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
@@ -60,6 +61,7 @@
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/SimplifyLibCalls.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
+
using namespace llvm;
using namespace llvm::PatternMatch;
@@ -84,6 +86,12 @@ STATISTIC(NumDbgValueMoved, "Number of debug value instructions moved");
STATISTIC(NumSelectsExpanded, "Number of selects turned into branches");
STATISTIC(NumStoreExtractExposed, "Number of store(extractelement) exposed");
+STATISTIC(NumMemCmpCalls, "Number of memcmp calls");
+STATISTIC(NumMemCmpNotConstant, "Number of memcmp calls without constant size");
+STATISTIC(NumMemCmpGreaterThanMax,
+ "Number of memcmp calls with size greater than max size");
+STATISTIC(NumMemCmpInlined, "Number of inlined memcmp calls");
+
static cl::opt<bool> DisableBranchOpts(
"disable-cgp-branch-opts", cl::Hidden, cl::init(false),
cl::desc("Disable branch optimizations in CodeGenPrepare"));
@@ -144,6 +152,11 @@ EnableTypePromotionMerge("cgp-type-promotion-merge", cl::Hidden,
cl::desc("Enable merging of redundant sexts when one is dominating"
" the other."), cl::init(true));
+static cl::opt<unsigned> MemCmpNumLoadsPerBlock(
+ "memcmp-num-loads-per-block", cl::Hidden, cl::init(1),
+ cl::desc("The number of loads per basic block for inline expansion of "
+ "memcmp that is only being compared against zero."));
+
namespace {
typedef SmallPtrSet<Instruction *, 16> SetOfInstrs;
typedef PointerIntPair<Type *, 1, bool> TypeIsSExt;
@@ -1629,6 +1642,593 @@ static bool despeculateCountZeros(IntrinsicInst *CountZeros,
return true;
}
+// This class provides helper functions to expand a memcmp library call into an
+// inline expansion.
+class MemCmpExpansion {
+ struct ResultBlock {
+ BasicBlock *BB;
+ PHINode *PhiSrc1;
+ PHINode *PhiSrc2;
+ ResultBlock();
+ };
+
+ CallInst *CI;
+ ResultBlock ResBlock;
+ unsigned MaxLoadSize;
+ unsigned NumBlocks;
+ unsigned NumBlocksNonOneByte;
+ unsigned NumLoadsPerBlock;
+ std::vector<BasicBlock *> LoadCmpBlocks;
+ BasicBlock *EndBlock;
+ PHINode *PhiRes;
+ bool IsUsedForZeroCmp;
+ int calculateNumBlocks(unsigned Size);
+ void createLoadCmpBlocks();
+ void createResultBlock();
+ void setupResultBlockPHINodes();
+ void setupEndBlockPHINodes();
+ void emitLoadCompareBlock(unsigned Index, int LoadSize, int GEPIndex,
+ bool IsLittleEndian);
+ void emitLoadCompareBlockMultipleLoads(unsigned Index, unsigned Size,
+ unsigned &NumBytesProcessed);
+ void emitLoadCompareByteBlock(unsigned Index, int GEPIndex);
+ void emitMemCmpResultBlock(bool IsLittleEndian);
+ Value *getMemCmpExpansionZeroCase(unsigned Size, bool IsLittleEndian);
+ unsigned getLoadSize(unsigned Size);
+ unsigned getNumLoads(unsigned Size);
+
+public:
+ MemCmpExpansion(CallInst *CI, unsigned MaxLoadSize,
+ unsigned NumLoadsPerBlock);
+ Value *getMemCmpExpansion(bool IsLittleEndian);
+};
+
+MemCmpExpansion::ResultBlock::ResultBlock()
+ : BB(nullptr), PhiSrc1(nullptr), PhiSrc2(nullptr) {}
+
+// Initialize the basic block structure required for expansion of memcmp call
+// with given maximum load size and memcmp size parameter.
+// This structure includes:
+// 1. A list of load compare blocks - LoadCmpBlocks.
+// 2. An EndBlock, split from original instruction point, which is the block to
+// return from.
+// 3. ResultBlock, block to branch to for early exit when a
+// LoadCmpBlock finds a difference.
+MemCmpExpansion::MemCmpExpansion(CallInst *CI, unsigned MaxLoadSize,
+ unsigned NumLoadsPerBlock)
+ : CI(CI), MaxLoadSize(MaxLoadSize), NumLoadsPerBlock(NumLoadsPerBlock) {
+
+ IRBuilder<> Builder(CI->getContext());
+
+ BasicBlock *StartBlock = CI->getParent();
+ EndBlock = StartBlock->splitBasicBlock(CI, "endblock");
+ setupEndBlockPHINodes();
+ IsUsedForZeroCmp = isOnlyUsedInZeroEqualityComparison(CI);
+
+ ConstantInt *SizeCast = dyn_cast<ConstantInt>(CI->getArgOperand(2));
+ uint64_t Size = SizeCast->getZExtValue();
+
+ // Calculate how many load compare blocks are required for an expansion of
+ // given Size.
+ NumBlocks = calculateNumBlocks(Size);
+ createResultBlock();
+
+ // If return value of memcmp is not used in a zero equality, we need to
+ // calculate which source was larger. The calculation requires the
+ // two loaded source values of each load compare block.
+ // These will be saved in the phi nodes created by setupResultBlockPHINodes.
+ if (!IsUsedForZeroCmp)
+ setupResultBlockPHINodes();
+
+ // Create the number of required load compare basic blocks.
+ createLoadCmpBlocks();
+
+ // Update the terminator added by splitBasicBlock to branch to the first
+ // LoadCmpBlock.
+ Builder.SetCurrentDebugLocation(CI->getDebugLoc());
+ StartBlock->getTerminator()->setSuccessor(0, LoadCmpBlocks[0]);
+}
+
+void MemCmpExpansion::createLoadCmpBlocks() {
+ for (unsigned i = 0; i < NumBlocks; i++) {
+ BasicBlock *BB = BasicBlock::Create(CI->getContext(), "loadbb",
+ EndBlock->getParent(), EndBlock);
+ LoadCmpBlocks.push_back(BB);
+ }
+}
+
+void MemCmpExpansion::createResultBlock() {
+ ResBlock.BB = BasicBlock::Create(CI->getContext(), "res_block",
+ EndBlock->getParent(), EndBlock);
+}
+
+// This function creates the IR instructions for loading and comparing 1 byte.
+// It loads 1 byte from each source of the memcmp paramters with the given
+// GEPIndex. It then subtracts the two loaded values and adds this result to the
+// final phi node for selecting the memcmp result.
+void MemCmpExpansion::emitLoadCompareByteBlock(unsigned Index, int GEPIndex) {
+ IRBuilder<> Builder(CI->getContext());
+
+ Value *Source1 = CI->getArgOperand(0);
+ Value *Source2 = CI->getArgOperand(1);
+
+ Builder.SetInsertPoint(LoadCmpBlocks[Index]);
+ Type *LoadSizeType = Type::getInt8Ty(CI->getContext());
+ // Cast source to LoadSizeType*
+ if (Source1->getType() != LoadSizeType)
+ Source1 = Builder.CreateBitCast(Source1, LoadSizeType->getPointerTo());
+ if (Source2->getType() != LoadSizeType)
+ Source2 = Builder.CreateBitCast(Source2, LoadSizeType->getPointerTo());
+
+ // Get the base address using the GEPIndex
+ if (GEPIndex != 0) {
+ Source1 = Builder.CreateGEP(LoadSizeType, Source1,
+ ConstantInt::get(LoadSizeType, GEPIndex));
+ Source2 = Builder.CreateGEP(LoadSizeType, Source2,
+ ConstantInt::get(LoadSizeType, GEPIndex));
+ }
+
+ Value *LoadSrc1 = Builder.CreateLoad(LoadSizeType, Source1);
+ Value *LoadSrc2 = Builder.CreateLoad(LoadSizeType, Source2);
+
+ LoadSrc1 = Builder.CreateZExt(LoadSrc1, Type::getInt32Ty(CI->getContext()));
+ LoadSrc2 = Builder.CreateZExt(LoadSrc2, Type::getInt32Ty(CI->getContext()));
+ Value *Diff = Builder.CreateSub(LoadSrc1, LoadSrc2);
+
+ PhiRes->addIncoming(Diff, LoadCmpBlocks[Index]);
+
+ if (Index < (LoadCmpBlocks.size() - 1)) {
+ // Early exit branch if difference found to EndBlock, otherwise continue to
+ // next LoadCmpBlock
+
+ Value *Cmp = Builder.CreateICmp(ICmpInst::ICMP_NE, Diff,
+ ConstantInt::get(Diff->getType(), 0));
+ BranchInst *CmpBr =
+ BranchInst::Create(EndBlock, LoadCmpBlocks[Index + 1], Cmp);
+ Builder.Insert(CmpBr);
+ } else {
+ // The last block has an unconditional branch to EndBlock
+ BranchInst *CmpBr = BranchInst::Create(EndBlock);
+ Builder.Insert(CmpBr);
+ }
+}
+
+unsigned MemCmpExpansion::getNumLoads(unsigned Size) {
+ return (Size / MaxLoadSize) + countPopulation(Size % MaxLoadSize);
+}
+
+unsigned MemCmpExpansion::getLoadSize(unsigned Size) {
+ return MinAlign(PowerOf2Floor(Size), MaxLoadSize);
+}
+
+void MemCmpExpansion::emitLoadCompareBlockMultipleLoads(
+ unsigned Index, unsigned Size, unsigned &NumBytesProcessed) {
+
+ IRBuilder<> Builder(CI->getContext());
+
+ std::vector<Value *> XorList, OrList;
+ Value *Diff;
+
+ unsigned RemainingBytes = Size - NumBytesProcessed;
+ unsigned NumLoadsRemaining = getNumLoads(RemainingBytes);
+ unsigned NumLoads = std::min(NumLoadsRemaining, NumLoadsPerBlock);
+
+ Builder.SetInsertPoint(LoadCmpBlocks[Index]);
+
+ for (unsigned i = 0; i < NumLoads; ++i) {
+ unsigned LoadSize = getLoadSize(RemainingBytes);
+ unsigned GEPIndex = NumBytesProcessed / LoadSize;
+ NumBytesProcessed += LoadSize;
+ RemainingBytes -= LoadSize;
+
+ Type *LoadSizeType = IntegerType::get(CI->getContext(), LoadSize * 8);
+ Type *MaxLoadType = IntegerType::get(CI->getContext(), MaxLoadSize * 8);
+
+ Value *Source1 = CI->getArgOperand(0);
+ Value *Source2 = CI->getArgOperand(1);
+
+ // Cast source to LoadSizeType*
+ if (Source1->getType() != LoadSizeType)
+ Source1 = Builder.CreateBitCast(Source1, LoadSizeType->getPointerTo());
+ if (Source2->getType() != LoadSizeType)
+ Source2 = Builder.CreateBitCast(Source2, LoadSizeType->getPointerTo());
+
+ // Get the base address using the GEPIndex
+ if (GEPIndex != 0) {
+ Source1 = Builder.CreateGEP(LoadSizeType, Source1,
+ ConstantInt::get(LoadSizeType, GEPIndex));
+ Source2 = Builder.CreateGEP(LoadSizeType, Source2,
+ ConstantInt::get(LoadSizeType, GEPIndex));
+ }
+
+ // Load LoadSizeType from the base address
+ Value *LoadSrc1 = Builder.CreateLoad(LoadSizeType, Source1);
+ Value *LoadSrc2 = Builder.CreateLoad(LoadSizeType, Source2);
+ if (LoadSizeType != MaxLoadType) {
+ LoadSrc1 = Builder.CreateZExtOrTrunc(LoadSrc1, MaxLoadType);
+ LoadSrc2 = Builder.CreateZExtOrTrunc(LoadSrc2, MaxLoadType);
+ }
+ Diff = Builder.CreateXor(LoadSrc1, LoadSrc2);
+ Diff = Builder.CreateZExtOrTrunc(Diff, MaxLoadType);
+ XorList.push_back(Diff);
+ }
+
+ auto pairWiseOr = [&](std::vector<Value *> &InList) -> std::vector<Value *> {
+ std::vector<Value *> OutList;
+ for (unsigned i = 0; i < InList.size() - 1; i = i + 2) {
+ Value *Or = Builder.CreateOr(InList[i], InList[i + 1]);
+ OutList.push_back(Or);
+ }
+ if (InList.size() % 2 != 0)
+ OutList.push_back(InList.back());
+ return OutList;
+ };
+
+ // Pair wise OR the XOR results
+ OrList = pairWiseOr(XorList);
+
+ // Pair wise OR the OR results until one result left
+ while (OrList.size() != 1) {
+ OrList = pairWiseOr(OrList);
+ }
+
+ Value *Cmp = Builder.CreateICmp(ICmpInst::ICMP_NE, OrList[0],
+ ConstantInt::get(Diff->getType(), 0));
+ BasicBlock *NextBB = (Index == (LoadCmpBlocks.size() - 1))
+ ? EndBlock
+ : LoadCmpBlocks[Index + 1];
+ // Early exit branch if difference found to ResultBlock, otherwise continue to
+ // next LoadCmpBlock or EndBlock.
+ BranchInst *CmpBr = BranchInst::Create(ResBlock.BB, NextBB, Cmp);
+ Builder.Insert(CmpBr);
+
+ // Add a phi edge for the last LoadCmpBlock to Endblock with a value of 0
+ // since early exit to ResultBlock was not taken (no difference was found in
+ // any of the bytes)
+ if (Index == LoadCmpBlocks.size() - 1) {
+ Value *Zero = ConstantInt::get(Type::getInt32Ty(CI->getContext()), 0);
+ PhiRes->addIncoming(Zero, LoadCmpBlocks[Index]);
+ }
+}
+
+// This function creates the IR intructions for loading and comparing using the
+// given LoadSize. It loads the number of bytes specified by LoadSize from each
+// source of the memcmp parameters. It then does a subtract to see if there was
+// a difference in the loaded values. If a difference is found, it branches
+// with an early exit to the ResultBlock for calculating which source was
+// larger. Otherwise, it falls through to the either the next LoadCmpBlock or
+// the EndBlock if this is the last LoadCmpBlock. Loading 1 byte is handled with
+// a special case through emitLoadCompareByteBlock. The special handling can
+// simply subtract the loaded values and add it to the result phi node.
+void MemCmpExpansion::emitLoadCompareBlock(unsigned Index, int LoadSize,
+ int GEPIndex, bool IsLittleEndian) {
+ if (LoadSize == 1) {
+ MemCmpExpansion::emitLoadCompareByteBlock(Index, GEPIndex);
+ return;
+ }
+
+ IRBuilder<> Builder(CI->getContext());
+
+ Type *LoadSizeType = IntegerType::get(CI->getContext(), LoadSize * 8);
+ Type *MaxLoadType = IntegerType::get(CI->getContext(), MaxLoadSize * 8);
+
+ Value *Source1 = CI->getArgOperand(0);
+ Value *Source2 = CI->getArgOperand(1);
+
+ Builder.SetInsertPoint(LoadCmpBlocks[Index]);
+ // Cast source to LoadSizeType*
+ if (Source1->getType() != LoadSizeType)
+ Source1 = Builder.CreateBitCast(Source1, LoadSizeType->getPointerTo());
+ if (Source2->getType() != LoadSizeType)
+ Source2 = Builder.CreateBitCast(Source2, LoadSizeType->getPointerTo());
+
+ // Get the base address using the GEPIndex
+ if (GEPIndex != 0) {
+ Source1 = Builder.CreateGEP(LoadSizeType, Source1,
+ ConstantInt::get(LoadSizeType, GEPIndex));
+ Source2 = Builder.CreateGEP(LoadSizeType, Source2,
+ ConstantInt::get(LoadSizeType, GEPIndex));
+ }
+
+ // Load LoadSizeType from the base address
+ Value *LoadSrc1 = Builder.CreateLoad(LoadSizeType, Source1);
+ Value *LoadSrc2 = Builder.CreateLoad(LoadSizeType, Source2);
+
+ if (IsLittleEndian) {
+ Function *F = LoadCmpBlocks[Index]->getParent();
+
+ Function *Bswap = Intrinsic::getDeclaration(F->getParent(),
+ Intrinsic::bswap, LoadSizeType);
+ LoadSrc1 = Builder.CreateCall(Bswap, LoadSrc1);
+ LoadSrc2 = Builder.CreateCall(Bswap, LoadSrc2);
+ }
+
+ if (LoadSizeType != MaxLoadType) {
+ LoadSrc1 = Builder.CreateZExtOrTrunc(LoadSrc1, MaxLoadType);
+ LoadSrc2 = Builder.CreateZExtOrTrunc(LoadSrc2, MaxLoadType);
+ }
+
+ // Add the loaded values to the phi nodes for calculating memcmp result only
+ // if result is not used in a zero equality.
+ if (!IsUsedForZeroCmp) {
+ ResBlock.PhiSrc1->addIncoming(LoadSrc1, LoadCmpBlocks[Index]);
+ ResBlock.PhiSrc2->addIncoming(LoadSrc2, LoadCmpBlocks[Index]);
+ }
+
+ Value *Diff = Builder.CreateSub(LoadSrc1, LoadSrc2);
+
+ Value *Cmp = Builder.CreateICmp(ICmpInst::ICMP_NE, Diff,
+ ConstantInt::get(Diff->getType(), 0));
+ BasicBlock *NextBB = (Index == (LoadCmpBlocks.size() - 1))
+ ? EndBlock
+ : LoadCmpBlocks[Index + 1];
+ // Early exit branch if difference found to ResultBlock, otherwise continue to
+ // next LoadCmpBlock or EndBlock.
+ BranchInst *CmpBr = BranchInst::Create(ResBlock.BB, NextBB, Cmp);
+ Builder.Insert(CmpBr);
+
+ // Add a phi edge for the last LoadCmpBlock to Endblock with a value of 0
+ // since early exit to ResultBlock was not taken (no difference was found in
+ // any of the bytes)
+ if (Index == LoadCmpBlocks.size() - 1) {
+ Value *Zero = ConstantInt::get(Type::getInt32Ty(CI->getContext()), 0);
+ PhiRes->addIncoming(Zero, LoadCmpBlocks[Index]);
+ }
+}
+
+// This function populates the ResultBlock with a sequence to calculate the
+// memcmp result. It compares the two loaded source values and returns -1 if
+// src1 < src2 and 1 if src1 > src2.
+void MemCmpExpansion::emitMemCmpResultBlock(bool IsLittleEndian) {
+ IRBuilder<> Builder(CI->getContext());
+
+ // Special case: if memcmp result is used in a zero equality, result does not
+ // need to be calculated and can simply return 1.
+ if (IsUsedForZeroCmp) {
+ BasicBlock::iterator InsertPt = ResBlock.BB->getFirstInsertionPt();
+ Builder.SetInsertPoint(ResBlock.BB, InsertPt);
+ Value *Res = ConstantInt::get(Type::getInt32Ty(CI->getContext()), 1);
+ PhiRes->addIncoming(Res, ResBlock.BB);
+ BranchInst *NewBr = BranchInst::Create(EndBlock);
+ Builder.Insert(NewBr);
+ return;
+ }
+ BasicBlock::iterator InsertPt = ResBlock.BB->getFirstInsertionPt();
+ Builder.SetInsertPoint(ResBlock.BB, InsertPt);
+
+ Value *Cmp = Builder.CreateICmp(ICmpInst::ICMP_ULT, ResBlock.PhiSrc1,
+ ResBlock.PhiSrc2);
+
+ Value *Res =
+ Builder.CreateSelect(Cmp, ConstantInt::get(Builder.getInt32Ty(), -1),
+ ConstantInt::get(Builder.getInt32Ty(), 1));
+
+ BranchInst *NewBr = BranchInst::Create(EndBlock);
+ Builder.Insert(NewBr);
+ PhiRes->addIncoming(Res, ResBlock.BB);
+}
+
+int MemCmpExpansion::calculateNumBlocks(unsigned Size) {
+ int NumBlocks = 0;
+ bool haveOneByteLoad = false;
+ unsigned RemainingSize = Size;
+ unsigned LoadSize = MaxLoadSize;
+ while (RemainingSize) {
+ if (LoadSize == 1)
+ haveOneByteLoad = true;
+ NumBlocks += RemainingSize / LoadSize;
+ RemainingSize = RemainingSize % LoadSize;
+ LoadSize = LoadSize / 2;
+ }
+ NumBlocksNonOneByte = haveOneByteLoad ? (NumBlocks - 1) : NumBlocks;
+
+ if (IsUsedForZeroCmp)
+ NumBlocks = NumBlocks / NumLoadsPerBlock +
+ (NumBlocks % NumLoadsPerBlock != 0 ? 1 : 0);
+
+ return NumBlocks;
+}
+
+void MemCmpExpansion::setupResultBlockPHINodes() {
+ IRBuilder<> Builder(CI->getContext());
+ Type *MaxLoadType = IntegerType::get(CI->getContext(), MaxLoadSize * 8);
+ Builder.SetInsertPoint(ResBlock.BB);
+ ResBlock.PhiSrc1 =
+ Builder.CreatePHI(MaxLoadType, NumBlocksNonOneByte, "phi.src1");
+ ResBlock.PhiSrc2 =
+ Builder.CreatePHI(MaxLoadType, NumBlocksNonOneByte, "phi.src2");
+}
+
+void MemCmpExpansion::setupEndBlockPHINodes() {
+ IRBuilder<> Builder(CI->getContext());
+
+ Builder.SetInsertPoint(&EndBlock->front());
+ PhiRes = Builder.CreatePHI(Type::getInt32Ty(CI->getContext()), 2, "phi.res");
+}
+
+Value *MemCmpExpansion::getMemCmpExpansionZeroCase(unsigned Size,
+ bool IsLittleEndian) {
+ unsigned NumBytesProcessed = 0;
+ // This loop populates each of the LoadCmpBlocks with IR sequence to handle
+ // multiple loads per block
+ for (unsigned i = 0; i < NumBlocks; ++i) {
+ emitLoadCompareBlockMultipleLoads(i, Size, NumBytesProcessed);
+ }
+
+ emitMemCmpResultBlock(IsLittleEndian);
+ return PhiRes;
+}
+
+// This function expands the memcmp call into an inline expansion and returns
+// the memcmp result.
+Value *MemCmpExpansion::getMemCmpExpansion(bool IsLittleEndian) {
+
+ ConstantInt *SizeCast = dyn_cast<ConstantInt>(CI->getArgOperand(2));
+ uint64_t Size = SizeCast->getZExtValue();
+
+ int LoadSize = MaxLoadSize;
+ int NumBytesToBeProcessed = Size;
+
+ if (IsUsedForZeroCmp) {
+ return getMemCmpExpansionZeroCase(Size, IsLittleEndian);
+ }
+
+ unsigned Index = 0;
+ // This loop calls emitLoadCompareBlock for comparing SizeVal bytes of the two
+ // memcmp source. It starts with loading using the maximum load size set by
+ // the target. It processes any remaining bytes using a load size which is the
+ // next smallest power of 2.
+ while (NumBytesToBeProcessed) {
+ // Calculate how many blocks we can create with the current load size
+ int NumBlocks = NumBytesToBeProcessed / LoadSize;
+ int GEPIndex = (Size - NumBytesToBeProcessed) / LoadSize;
+ NumBytesToBeProcessed = NumBytesToBeProcessed % LoadSize;
+
+ // For each NumBlocks, populate the instruction sequence for loading and
+ // comparing LoadSize bytes
+ while (NumBlocks--) {
+ emitLoadCompareBlock(Index, LoadSize, GEPIndex, IsLittleEndian);
+ Index++;
+ GEPIndex++;
+ }
+ // Get the next LoadSize to use
+ LoadSize = LoadSize / 2;
+ }
+
+ emitMemCmpResultBlock(IsLittleEndian);
+ return PhiRes;
+}
+
+// This function checks to see if an expansion of memcmp can be generated.
+// It checks for constant compare size that is less than the max inline size.
+// If an expansion cannot occur, returns false to leave as a library call.
+// Otherwise, the library call is replaced wtih new IR instruction sequence.
+/// We want to transform:
+/// %call = call signext i32 @memcmp(i8* %0, i8* %1, i64 15)
+/// To:
+/// loadbb:
+/// %0 = bitcast i32* %buffer2 to i8*
+/// %1 = bitcast i32* %buffer1 to i8*
+/// %2 = bitcast i8* %1 to i64*
+/// %3 = bitcast i8* %0 to i64*
+/// %4 = load i64, i64* %2
+/// %5 = load i64, i64* %3
+/// %6 = call i64 @llvm.bswap.i64(i64 %4)
+/// %7 = call i64 @llvm.bswap.i64(i64 %5)
+/// %8 = sub i64 %6, %7
+/// %9 = icmp ne i64 %8, 0
+/// br i1 %9, label %res_block, label %loadbb1
+/// res_block: ; preds = %loadbb2,
+/// %loadbb1, %loadbb
+/// %phi.src1 = phi i64 [ %6, %loadbb ], [ %22, %loadbb1 ], [ %36, %loadbb2 ]
+/// %phi.src2 = phi i64 [ %7, %loadbb ], [ %23, %loadbb1 ], [ %37, %loadbb2 ]
+/// %10 = icmp ult i64 %phi.src1, %phi.src2
+/// %11 = select i1 %10, i32 -1, i32 1
+/// br label %endblock
+/// loadbb1: ; preds = %loadbb
+/// %12 = bitcast i32* %buffer2 to i8*
+/// %13 = bitcast i32* %buffer1 to i8*
+/// %14 = bitcast i8* %13 to i32*
+/// %15 = bitcast i8* %12 to i32*
+/// %16 = getelementptr i32, i32* %14, i32 2
+/// %17 = getelementptr i32, i32* %15, i32 2
+/// %18 = load i32, i32* %16
+/// %19 = load i32, i32* %17
+/// %20 = call i32 @llvm.bswap.i32(i32 %18)
+/// %21 = call i32 @llvm.bswap.i32(i32 %19)
+/// %22 = zext i32 %20 to i64
+/// %23 = zext i32 %21 to i64
+/// %24 = sub i64 %22, %23
+/// %25 = icmp ne i64 %24, 0
+/// br i1 %25, label %res_block, label %loadbb2
+/// loadbb2: ; preds = %loadbb1
+/// %26 = bitcast i32* %buffer2 to i8*
+/// %27 = bitcast i32* %buffer1 to i8*
+/// %28 = bitcast i8* %27 to i16*
+/// %29 = bitcast i8* %26 to i16*
+/// %30 = getelementptr i16, i16* %28, i16 6
+/// %31 = getelementptr i16, i16* %29, i16 6
+/// %32 = load i16, i16* %30
+/// %33 = load i16, i16* %31
+/// %34 = call i16 @llvm.bswap.i16(i16 %32)
+/// %35 = call i16 @llvm.bswap.i16(i16 %33)
+/// %36 = zext i16 %34 to i64
+/// %37 = zext i16 %35 to i64
+/// %38 = sub i64 %36, %37
+/// %39 = icmp ne i64 %38, 0
+/// br i1 %39, label %res_block, label %loadbb3
+/// loadbb3: ; preds = %loadbb2
+/// %40 = bitcast i32* %buffer2 to i8*
+/// %41 = bitcast i32* %buffer1 to i8*
+/// %42 = getelementptr i8, i8* %41, i8 14
+/// %43 = getelementptr i8, i8* %40, i8 14
+/// %44 = load i8, i8* %42
+/// %45 = load i8, i8* %43
+/// %46 = zext i8 %44 to i32
+/// %47 = zext i8 %45 to i32
+/// %48 = sub i32 %46, %47
+/// br label %endblock
+/// endblock: ; preds = %res_block,
+/// %loadbb3
+/// %phi.res = phi i32 [ %48, %loadbb3 ], [ %11, %res_block ]
+/// ret i32 %phi.res
+static bool expandMemCmp(CallInst *CI, const TargetTransformInfo *TTI,
+ const TargetLowering *TLI, const DataLayout *DL) {
+ NumMemCmpCalls++;
+ IRBuilder<> Builder(CI->getContext());
+
+ // TTI call to check if target would like to expand memcmp and get the
+ // MaxLoadSize
+ unsigned MaxLoadSize;
+ if (!TTI->expandMemCmp(CI, MaxLoadSize))
+ return false;
+
+ // Early exit from expansion if -Oz
+ if (CI->getParent()->getParent()->optForMinSize()) {
+ return false;
+ }
+
+ // Early exit from expansion if size is not a constant
+ ConstantInt *SizeCast = dyn_cast<ConstantInt>(CI->getArgOperand(2));
+ if (!SizeCast) {
+ NumMemCmpNotConstant++;
+ return false;
+ }
+
+ // Early exit from expansion if size greater than max bytes to load
+ uint64_t SizeVal = SizeCast->getZExtValue();
+
+ unsigned NumLoads = 0;
+ unsigned RemainingSize = SizeVal;
+ unsigned LoadSize = MaxLoadSize;
+ while (RemainingSize) {
+ NumLoads += RemainingSize / LoadSize;
+ RemainingSize = RemainingSize % LoadSize;
+ LoadSize = LoadSize / 2;
+ }
+
+ if (NumLoads >
+ TLI->getMaxExpandSizeMemcmp(CI->getParent()->getParent()->optForSize())) {
+ NumMemCmpGreaterThanMax++;
+ return false;
+ }
+
+ NumMemCmpInlined++;
+
+ // MemCmpHelper object, creates and sets up basic blocks required for
+ // expanding memcmp with size SizeVal
+ unsigned NumLoadsPerBlock = MemCmpNumLoadsPerBlock;
+ MemCmpExpansion MemCmpHelper(CI, MaxLoadSize, NumLoadsPerBlock);
+
+ Value *Res = MemCmpHelper.getMemCmpExpansion(DL->isLittleEndian());
+
+ // Replace call with result of expansion and erarse call.
+ CI->replaceAllUsesWith(Res);
+ CI->eraseFromParent();
+
+ return true;
+}
+
bool CodeGenPrepare::optimizeCallInst(CallInst *CI, bool& ModifiedDT) {
BasicBlock *BB = CI->getParent();
@@ -1780,6 +2380,15 @@ bool CodeGenPrepare::optimizeCallInst(CallInst *CI, bool& ModifiedDT) {
CI->eraseFromParent();
return true;
}
+
+ LibFunc Func;
+ if (TLInfo->getLibFunc(*CI->getCalledFunction(), Func) &&
+ Func == LibFunc_memcmp) {
+ if (expandMemCmp(CI, TTI, TLI, DL)) {
+ ModifiedDT = true;
+ return true;
+ }
+ }
return false;
}
@@ -4927,6 +5536,7 @@ bool CodeGenPrepare::optimizeSwitchInst(SwitchInst *SI) {
return true;
}
+
namespace {
/// \brief Helper class to promote a scalar operation to a vector one.
/// This class is used to move downward extractelement transition.
diff --git a/lib/CodeGen/CriticalAntiDepBreaker.cpp b/lib/CodeGen/CriticalAntiDepBreaker.cpp
index b2d6652b075e..a3cf2846d2f5 100644
--- a/lib/CodeGen/CriticalAntiDepBreaker.cpp
+++ b/lib/CodeGen/CriticalAntiDepBreaker.cpp
@@ -74,7 +74,7 @@ void CriticalAntiDepBreaker::StartBlock(MachineBasicBlock *BB) {
for (const MCPhysReg *I = MF.getRegInfo().getCalleeSavedRegs(); *I;
++I) {
unsigned Reg = *I;
- if (!IsReturnBlock && !(Pristine.test(Reg) || BB->isLiveIn(Reg)))
+ if (!IsReturnBlock && !Pristine.test(Reg))
continue;
for (MCRegAliasIterator AI(*I, TRI, true); AI.isValid(); ++AI) {
unsigned Reg = *AI;
diff --git a/lib/CodeGen/GlobalISel/Localizer.cpp b/lib/CodeGen/GlobalISel/Localizer.cpp
index c2a568e4b452..c5d0999fe438 100644
--- a/lib/CodeGen/GlobalISel/Localizer.cpp
+++ b/lib/CodeGen/GlobalISel/Localizer.cpp
@@ -98,12 +98,10 @@ bool Localizer::runOnMachineFunction(MachineFunction &MF) {
// Create the localized instruction.
MachineInstr *LocalizedMI = MF.CloneMachineInstr(&MI);
LocalizedInstrs.insert(LocalizedMI);
- // Move it at the right place.
- MachineInstr &MIUse = *MOUse.getParent();
- if (MIUse.getParent() == InsertMBB)
- InsertMBB->insert(MIUse, LocalizedMI);
- else
- InsertMBB->insert(InsertMBB->getFirstNonPHI(), LocalizedMI);
+ // Don't try to be smart for the insertion point.
+ // There is no guarantee that the first seen use is the first
+ // use in the block.
+ InsertMBB->insert(InsertMBB->getFirstNonPHI(), LocalizedMI);
// Set a new register for the definition.
unsigned NewReg =
diff --git a/lib/CodeGen/ImplicitNullChecks.cpp b/lib/CodeGen/ImplicitNullChecks.cpp
index 24e289dd4f1b..444416a77008 100644
--- a/lib/CodeGen/ImplicitNullChecks.cpp
+++ b/lib/CodeGen/ImplicitNullChecks.cpp
@@ -607,8 +607,20 @@ MachineInstr *ImplicitNullChecks::insertFaultingInstr(
.addMBB(HandlerMBB)
.addImm(MI->getOpcode());
- for (auto &MO : MI->uses())
- MIB.add(MO);
+ for (auto &MO : MI->uses()) {
+ if (MO.isReg()) {
+ MachineOperand NewMO = MO;
+ if (MO.isUse()) {
+ NewMO.setIsKill(false);
+ } else {
+ assert(MO.isDef() && "Expected def or use");
+ NewMO.setIsDead(false);
+ }
+ MIB.add(NewMO);
+ } else {
+ MIB.add(MO);
+ }
+ }
MIB.setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
diff --git a/lib/CodeGen/LiveRangeShrink.cpp b/lib/CodeGen/LiveRangeShrink.cpp
new file mode 100644
index 000000000000..552f4b5393fe
--- /dev/null
+++ b/lib/CodeGen/LiveRangeShrink.cpp
@@ -0,0 +1,231 @@
+//===-- LiveRangeShrink.cpp - Move instructions to shrink live range ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+///===---------------------------------------------------------------------===//
+///
+/// \file
+/// This pass moves instructions close to the definition of its operands to
+/// shrink live range of the def instruction. The code motion is limited within
+/// the basic block. The moved instruction should have 1 def, and more than one
+/// uses, all of which are the only use of the def.
+///
+///===---------------------------------------------------------------------===//
+#include "llvm/ADT/Statistic.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/Support/Debug.h"
+
+#define DEBUG_TYPE "lrshrink"
+
+STATISTIC(NumInstrsHoistedToShrinkLiveRange,
+ "Number of insructions hoisted to shrink live range.");
+
+using namespace llvm;
+
+namespace {
+class LiveRangeShrink : public MachineFunctionPass {
+public:
+ static char ID;
+
+ LiveRangeShrink() : MachineFunctionPass(ID) {
+ initializeLiveRangeShrinkPass(*PassRegistry::getPassRegistry());
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesCFG();
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
+
+ StringRef getPassName() const override { return "Live Range Shrink"; }
+
+ bool runOnMachineFunction(MachineFunction &MF) override;
+};
+} // End anonymous namespace.
+
+char LiveRangeShrink::ID = 0;
+char &llvm::LiveRangeShrinkID = LiveRangeShrink::ID;
+
+INITIALIZE_PASS(LiveRangeShrink, "lrshrink", "Live Range Shrink Pass", false,
+ false)
+namespace {
+typedef DenseMap<MachineInstr *, unsigned> InstOrderMap;
+
+/// Returns \p New if it's dominated by \p Old, otherwise return \p Old.
+/// \p M maintains a map from instruction to its dominating order that satisfies
+/// M[A] > M[B] guarantees that A is dominated by B.
+/// If \p New is not in \p M, return \p Old. Otherwise if \p Old is null, return
+/// \p New.
+MachineInstr *FindDominatedInstruction(MachineInstr &New, MachineInstr *Old,
+ const InstOrderMap &M) {
+ auto NewIter = M.find(&New);
+ if (NewIter == M.end())
+ return Old;
+ if (Old == nullptr)
+ return &New;
+ unsigned OrderOld = M.find(Old)->second;
+ unsigned OrderNew = NewIter->second;
+ if (OrderOld != OrderNew)
+ return OrderOld < OrderNew ? &New : Old;
+ // OrderOld == OrderNew, we need to iterate down from Old to see if it
+ // can reach New, if yes, New is dominated by Old.
+ for (MachineInstr *I = Old->getNextNode(); M.find(I)->second == OrderNew;
+ I = I->getNextNode())
+ if (I == &New)
+ return &New;
+ return Old;
+}
+
+/// Builds Instruction to its dominating order number map \p M by traversing
+/// from instruction \p Start.
+void BuildInstOrderMap(MachineBasicBlock::iterator Start, InstOrderMap &M) {
+ M.clear();
+ unsigned i = 0;
+ for (MachineInstr &I : make_range(Start, Start->getParent()->end()))
+ M[&I] = i++;
+}
+} // end anonymous namespace
+
+bool LiveRangeShrink::runOnMachineFunction(MachineFunction &MF) {
+ if (skipFunction(*MF.getFunction()))
+ return false;
+
+ MachineRegisterInfo &MRI = MF.getRegInfo();
+
+ DEBUG(dbgs() << "**** Analysing " << MF.getName() << '\n');
+
+ InstOrderMap IOM;
+ // Map from register to instruction order (value of IOM) where the
+ // register is used last. When moving instructions up, we need to
+ // make sure all its defs (including dead def) will not cross its
+ // last use when moving up.
+ DenseMap<unsigned, std::pair<unsigned, MachineInstr *>> UseMap;
+
+ for (MachineBasicBlock &MBB : MF) {
+ if (MBB.empty())
+ continue;
+ bool SawStore = false;
+ BuildInstOrderMap(MBB.begin(), IOM);
+ UseMap.clear();
+
+ for (MachineBasicBlock::iterator Next = MBB.begin(); Next != MBB.end();) {
+ MachineInstr &MI = *Next;
+ ++Next;
+ if (MI.isPHI() || MI.isDebugValue())
+ continue;
+ if (MI.mayStore())
+ SawStore = true;
+
+ unsigned CurrentOrder = IOM[&MI];
+ unsigned Barrier = 0;
+ MachineInstr *BarrierMI = nullptr;
+ for (const MachineOperand &MO : MI.operands()) {
+ if (!MO.isReg() || MO.isDebug())
+ continue;
+ if (MO.isUse())
+ UseMap[MO.getReg()] = std::make_pair(CurrentOrder, &MI);
+ else if (MO.isDead() && UseMap.count(MO.getReg()))
+ // Barrier is the last instruction where MO get used. MI should not
+ // be moved above Barrier.
+ if (Barrier < UseMap[MO.getReg()].first) {
+ Barrier = UseMap[MO.getReg()].first;
+ BarrierMI = UseMap[MO.getReg()].second;
+ }
+ }
+
+ if (!MI.isSafeToMove(nullptr, SawStore)) {
+ // If MI has side effects, it should become a barrier for code motion.
+ // IOM is rebuild from the next instruction to prevent later
+ // instructions from being moved before this MI.
+ if (MI.hasUnmodeledSideEffects() && Next != MBB.end()) {
+ BuildInstOrderMap(Next, IOM);
+ SawStore = false;
+ }
+ continue;
+ }
+
+ const MachineOperand *DefMO = nullptr;
+ MachineInstr *Insert = nullptr;
+
+ // Number of live-ranges that will be shortened. We do not count
+ // live-ranges that are defined by a COPY as it could be coalesced later.
+ unsigned NumEligibleUse = 0;
+
+ for (const MachineOperand &MO : MI.operands()) {
+ if (!MO.isReg() || MO.isDead() || MO.isDebug())
+ continue;
+ unsigned Reg = MO.getReg();
+ // Do not move the instruction if it def/uses a physical register,
+ // unless it is a constant physical register or a noreg.
+ if (!TargetRegisterInfo::isVirtualRegister(Reg)) {
+ if (!Reg || MRI.isConstantPhysReg(Reg))
+ continue;
+ Insert = nullptr;
+ break;
+ }
+ if (MO.isDef()) {
+ // Do not move if there is more than one def.
+ if (DefMO) {
+ Insert = nullptr;
+ break;
+ }
+ DefMO = &MO;
+ } else if (MRI.hasOneNonDBGUse(Reg) && MRI.hasOneDef(Reg) && DefMO &&
+ MRI.getRegClass(DefMO->getReg()) ==
+ MRI.getRegClass(MO.getReg())) {
+ // The heuristic does not handle different register classes yet
+ // (registers of different sizes, looser/tighter constraints). This
+ // is because it needs more accurate model to handle register
+ // pressure correctly.
+ MachineInstr &DefInstr = *MRI.def_instr_begin(Reg);
+ if (!DefInstr.isCopy())
+ NumEligibleUse++;
+ Insert = FindDominatedInstruction(DefInstr, Insert, IOM);
+ } else {
+ Insert = nullptr;
+ break;
+ }
+ }
+
+ // If Barrier equals IOM[I], traverse forward to find if BarrierMI is
+ // after Insert, if yes, then we should not hoist.
+ for (MachineInstr *I = Insert; I && IOM[I] == Barrier;
+ I = I->getNextNode())
+ if (I == BarrierMI) {
+ Insert = nullptr;
+ break;
+ }
+ // Move the instruction when # of shrunk live range > 1.
+ if (DefMO && Insert && NumEligibleUse > 1 && Barrier <= IOM[Insert]) {
+ MachineBasicBlock::iterator I = std::next(Insert->getIterator());
+ // Skip all the PHI and debug instructions.
+ while (I != MBB.end() && (I->isPHI() || I->isDebugValue()))
+ I = std::next(I);
+ if (I == MI.getIterator())
+ continue;
+
+ // Update the dominator order to be the same as the insertion point.
+ // We do this to maintain a non-decreasing order without need to update
+ // all instruction orders after the insertion point.
+ unsigned NewOrder = IOM[&*I];
+ IOM[&MI] = NewOrder;
+ NumInstrsHoistedToShrinkLiveRange++;
+
+ // Find MI's debug value following MI.
+ MachineBasicBlock::iterator EndIter = std::next(MI.getIterator());
+ if (MI.getOperand(0).isReg())
+ for (; EndIter != MBB.end() && EndIter->isDebugValue() &&
+ EndIter->getOperand(0).isReg() &&
+ EndIter->getOperand(0).getReg() == MI.getOperand(0).getReg();
+ ++EndIter, ++Next)
+ IOM[&*EndIter] = NewOrder;
+ MBB.splice(I, &MBB, MI.getIterator(), EndIter);
+ }
+ }
+ }
+ return false;
+}
diff --git a/lib/CodeGen/MIRParser/MIRParser.cpp b/lib/CodeGen/MIRParser/MIRParser.cpp
index bd04acd049db..ff12297e3fc6 100644
--- a/lib/CodeGen/MIRParser/MIRParser.cpp
+++ b/lib/CodeGen/MIRParser/MIRParser.cpp
@@ -332,8 +332,6 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
MF.setAlignment(YamlMF.Alignment);
MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice);
- if (YamlMF.NoVRegs)
- MF.getProperties().set(MachineFunctionProperties::Property::NoVRegs);
if (YamlMF.Legalized)
MF.getProperties().set(MachineFunctionProperties::Property::Legalized);
if (YamlMF.RegBankSelected)
diff --git a/lib/CodeGen/MIRPrinter.cpp b/lib/CodeGen/MIRPrinter.cpp
index 6f6a67d81b0f..293fc7358b8e 100644
--- a/lib/CodeGen/MIRPrinter.cpp
+++ b/lib/CodeGen/MIRPrinter.cpp
@@ -183,8 +183,6 @@ void MIRPrinter::print(const MachineFunction &MF) {
YamlMF.Alignment = MF.getAlignment();
YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice();
- YamlMF.NoVRegs = MF.getProperties().hasProperty(
- MachineFunctionProperties::Property::NoVRegs);
YamlMF.Legalized = MF.getProperties().hasProperty(
MachineFunctionProperties::Property::Legalized);
YamlMF.RegBankSelected = MF.getProperties().hasProperty(
diff --git a/lib/CodeGen/MachineBasicBlock.cpp b/lib/CodeGen/MachineBasicBlock.cpp
index 06112723497b..590acc01008a 100644
--- a/lib/CodeGen/MachineBasicBlock.cpp
+++ b/lib/CodeGen/MachineBasicBlock.cpp
@@ -350,6 +350,13 @@ void MachineBasicBlock::removeLiveIn(MCPhysReg Reg, LaneBitmask LaneMask) {
LiveIns.erase(I);
}
+MachineBasicBlock::livein_iterator
+MachineBasicBlock::removeLiveIn(MachineBasicBlock::livein_iterator I) {
+ // Get non-const version of iterator.
+ LiveInVector::iterator LI = LiveIns.begin() + (I - LiveIns.begin());
+ return LiveIns.erase(LI);
+}
+
bool MachineBasicBlock::isLiveIn(MCPhysReg Reg, LaneBitmask LaneMask) const {
livein_iterator I = find_if(
LiveIns, [Reg](const RegisterMaskPair &LI) { return LI.PhysReg == Reg; });
diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp
index d665201a5d17..306b75dbbae7 100644
--- a/lib/CodeGen/MachineInstr.cpp
+++ b/lib/CodeGen/MachineInstr.cpp
@@ -1,4 +1,4 @@
-//===-- lib/CodeGen/MachineInstr.cpp --------------------------------------===//
+//===- lib/CodeGen/MachineInstr.cpp ---------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,21 +11,34 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Analysis/AliasAnalysis.h"
-#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/Analysis/MemoryLocation.h"
+#include "llvm/CodeGen/GlobalISel/RegisterBank.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineInstrBundle.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/IR/Constants.h"
-#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/DebugInfoMetadata.h"
+#include "llvm/IR/DebugLoc.h"
+#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
@@ -35,9 +48,13 @@
#include "llvm/IR/Value.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/LowLevelTypeImpl.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetInstrInfo.h"
@@ -45,6 +62,14 @@
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <iterator>
+#include <utility>
+
using namespace llvm;
static cl::opt<bool> PrintWholeRegMask(
@@ -256,7 +281,7 @@ bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const {
case MachineOperand::MO_GlobalAddress:
return getGlobal() == Other.getGlobal() && getOffset() == Other.getOffset();
case MachineOperand::MO_ExternalSymbol:
- return !strcmp(getSymbolName(), Other.getSymbolName()) &&
+ return strcmp(getSymbolName(), Other.getSymbolName()) == 0 &&
getOffset() == Other.getOffset();
case MachineOperand::MO_BlockAddress:
return getBlockAddress() == Other.getBlockAddress() &&
@@ -723,9 +748,7 @@ void MachineInstr::addImplicitDefUseOperands(MachineFunction &MF) {
/// the MCInstrDesc.
MachineInstr::MachineInstr(MachineFunction &MF, const MCInstrDesc &tid,
DebugLoc dl, bool NoImp)
- : MCID(&tid), Parent(nullptr), Operands(nullptr), NumOperands(0), Flags(0),
- AsmPrinterFlags(0), NumMemRefs(0), MemRefs(nullptr),
- debugLoc(std::move(dl)) {
+ : MCID(&tid), debugLoc(std::move(dl)) {
assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
// Reserve space for the expected number of operands.
@@ -742,9 +765,8 @@ MachineInstr::MachineInstr(MachineFunction &MF, const MCInstrDesc &tid,
/// MachineInstr ctor - Copies MachineInstr arg exactly
///
MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI)
- : MCID(&MI.getDesc()), Parent(nullptr), Operands(nullptr), NumOperands(0),
- Flags(0), AsmPrinterFlags(0), NumMemRefs(MI.NumMemRefs),
- MemRefs(MI.MemRefs), debugLoc(MI.getDebugLoc()) {
+ : MCID(&MI.getDesc()), NumMemRefs(MI.NumMemRefs), MemRefs(MI.MemRefs),
+ debugLoc(MI.getDebugLoc()) {
assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
CapOperands = OperandCapacity::get(MI.getNumOperands());
@@ -1633,8 +1655,8 @@ bool MachineInstr::mayAlias(AliasAnalysis *AA, MachineInstr &Other,
// memory objects. It can save compile time, and possibly catch some
// corner cases not currently covered.
- assert ((MMOa->getOffset() >= 0) && "Negative MachineMemOperand offset");
- assert ((MMOb->getOffset() >= 0) && "Negative MachineMemOperand offset");
+ assert((MMOa->getOffset() >= 0) && "Negative MachineMemOperand offset");
+ assert((MMOb->getOffset() >= 0) && "Negative MachineMemOperand offset");
int64_t MinOffset = std::min(MMOa->getOffset(), MMOb->getOffset());
int64_t Overlapa = MMOa->getSize() + MMOa->getOffset() - MinOffset;
@@ -1667,7 +1689,7 @@ bool MachineInstr::hasOrderedMemoryRef() const {
return true;
// Check if any of our memory operands are ordered.
- return any_of(memoperands(), [](const MachineMemOperand *MMO) {
+ return llvm::any_of(memoperands(), [](const MachineMemOperand *MMO) {
return !MMO->isUnordered();
});
}
@@ -1841,7 +1863,6 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
return;
// Print the rest of the operands.
- bool OmittedAnyCallClobbers = false;
bool FirstOp = true;
unsigned AsmDescOp = ~0u;
unsigned AsmOpCount = 0;
@@ -1878,31 +1899,6 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
if (MO.isReg() && TargetRegisterInfo::isVirtualRegister(MO.getReg()))
VirtRegs.push_back(MO.getReg());
- // Omit call-clobbered registers which aren't used anywhere. This makes
- // call instructions much less noisy on targets where calls clobber lots
- // of registers. Don't rely on MO.isDead() because we may be called before
- // LiveVariables is run, or we may be looking at a non-allocatable reg.
- if (MRI && isCall() &&
- MO.isReg() && MO.isImplicit() && MO.isDef()) {
- unsigned Reg = MO.getReg();
- if (TargetRegisterInfo::isPhysicalRegister(Reg)) {
- if (MRI->use_empty(Reg)) {
- bool HasAliasLive = false;
- for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
- unsigned AliasReg = *AI;
- if (!MRI->use_empty(AliasReg)) {
- HasAliasLive = true;
- break;
- }
- }
- if (!HasAliasLive) {
- OmittedAnyCallClobbers = true;
- continue;
- }
- }
- }
- }
-
if (FirstOp) FirstOp = false; else OS << ",";
OS << " ";
if (i < getDesc().NumOperands) {
@@ -1984,12 +1980,6 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
MO.print(OS, MST, TRI);
}
- // Briefly indicate whether any call clobbers were omitted.
- if (OmittedAnyCallClobbers) {
- if (!FirstOp) OS << ",";
- OS << " ...";
- }
-
bool HaveSemi = false;
const unsigned PrintableFlags = FrameSetup | FrameDestroy;
if (Flags & PrintableFlags) {
@@ -2255,8 +2245,8 @@ void MachineInstr::setPhysRegsDeadExcept(ArrayRef<unsigned> UsedRegs,
unsigned Reg = MO.getReg();
if (!TargetRegisterInfo::isPhysicalRegister(Reg)) continue;
// If there are no uses, including partial uses, the def is dead.
- if (none_of(UsedRegs,
- [&](unsigned Use) { return TRI.regsOverlap(Use, Reg); }))
+ if (llvm::none_of(UsedRegs,
+ [&](unsigned Use) { return TRI.regsOverlap(Use, Reg); }))
MO.setIsDead();
}
diff --git a/lib/CodeGen/MachineModuleInfo.cpp b/lib/CodeGen/MachineModuleInfo.cpp
index 6cf751d34e26..c1b72430e605 100644
--- a/lib/CodeGen/MachineModuleInfo.cpp
+++ b/lib/CodeGen/MachineModuleInfo.cpp
@@ -7,27 +7,34 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PostOrderIterator.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/TinyPtrVector.h"
-#include "llvm/Analysis/EHPersonalities.h"
-#include "llvm/Analysis/ValueTracking.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionInitializer.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/Passes.h"
-#include "llvm/IR/Constants.h"
+#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/DerivedTypes.h"
-#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
-#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/IR/Value.h"
+#include "llvm/IR/ValueHandle.h"
+#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSymbol.h"
-#include "llvm/Support/Dwarf.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
+#include <algorithm>
+#include <cassert>
+#include <memory>
+#include <utility>
+#include <vector>
+
using namespace llvm;
using namespace llvm::dwarf;
@@ -37,14 +44,16 @@ INITIALIZE_PASS(MachineModuleInfo, "machinemoduleinfo",
char MachineModuleInfo::ID = 0;
// Out of line virtual method.
-MachineModuleInfoImpl::~MachineModuleInfoImpl() {}
+MachineModuleInfoImpl::~MachineModuleInfoImpl() = default;
namespace llvm {
+
class MMIAddrLabelMapCallbackPtr final : CallbackVH {
- MMIAddrLabelMap *Map;
+ MMIAddrLabelMap *Map = nullptr;
+
public:
- MMIAddrLabelMapCallbackPtr() : Map(nullptr) {}
- MMIAddrLabelMapCallbackPtr(Value *V) : CallbackVH(V), Map(nullptr) {}
+ MMIAddrLabelMapCallbackPtr() = default;
+ MMIAddrLabelMapCallbackPtr(Value *V) : CallbackVH(V) {}
void setPtr(BasicBlock *BB) {
ValueHandleBase::operator=(BB);
@@ -75,11 +84,12 @@ class MMIAddrLabelMap {
/// This is a per-function list of symbols whose corresponding BasicBlock got
/// deleted. These symbols need to be emitted at some point in the file, so
/// AsmPrinter emits them after the function body.
- DenseMap<AssertingVH<Function>, std::vector<MCSymbol*> >
+ DenseMap<AssertingVH<Function>, std::vector<MCSymbol*>>
DeletedAddrLabelsNeedingEmission;
-public:
+public:
MMIAddrLabelMap(MCContext &context) : Context(context) {}
+
~MMIAddrLabelMap() {
assert(DeletedAddrLabelsNeedingEmission.empty() &&
"Some labels for deleted blocks never got emitted");
@@ -93,7 +103,8 @@ public:
void UpdateForDeletedBlock(BasicBlock *BB);
void UpdateForRAUWBlock(BasicBlock *Old, BasicBlock *New);
};
-}
+
+} // end namespace llvm
ArrayRef<MCSymbol *> MMIAddrLabelMap::getAddrLabelSymbolToEmit(BasicBlock *BB) {
assert(BB->hasAddressTaken() &&
@@ -119,7 +130,7 @@ ArrayRef<MCSymbol *> MMIAddrLabelMap::getAddrLabelSymbolToEmit(BasicBlock *BB) {
/// If we have any deleted symbols for F, return them.
void MMIAddrLabelMap::
takeDeletedSymbolsForFunction(Function *F, std::vector<MCSymbol*> &Result) {
- DenseMap<AssertingVH<Function>, std::vector<MCSymbol*> >::iterator I =
+ DenseMap<AssertingVH<Function>, std::vector<MCSymbol*>>::iterator I =
DeletedAddrLabelsNeedingEmission.find(F);
// If there are no entries for the function, just return.
@@ -130,7 +141,6 @@ takeDeletedSymbolsForFunction(Function *F, std::vector<MCSymbol*> &Result) {
DeletedAddrLabelsNeedingEmission.erase(I);
}
-
void MMIAddrLabelMap::UpdateForDeletedBlock(BasicBlock *BB) {
// If the block got deleted, there is no need for the symbol. If the symbol
// was already emitted, we can just forget about it, otherwise we need to
@@ -177,7 +187,6 @@ void MMIAddrLabelMap::UpdateForRAUWBlock(BasicBlock *Old, BasicBlock *New) {
OldEntry.Symbols.end());
}
-
void MMIAddrLabelMapCallbackPtr::deleted() {
Map->UpdateForDeletedBlock(cast<BasicBlock>(getValPtr()));
}
@@ -186,9 +195,6 @@ void MMIAddrLabelMapCallbackPtr::allUsesReplacedWith(Value *V2) {
Map->UpdateForRAUWBlock(cast<BasicBlock>(getValPtr()), cast<BasicBlock>(V2));
}
-
-//===----------------------------------------------------------------------===//
-
MachineModuleInfo::MachineModuleInfo(const TargetMachine *TM)
: ImmutablePass(ID), TM(*TM),
Context(TM->getMCAsmInfo(), TM->getMCRegisterInfo(),
@@ -196,11 +202,9 @@ MachineModuleInfo::MachineModuleInfo(const TargetMachine *TM)
initializeMachineModuleInfoPass(*PassRegistry::getPassRegistry());
}
-MachineModuleInfo::~MachineModuleInfo() {
-}
+MachineModuleInfo::~MachineModuleInfo() = default;
bool MachineModuleInfo::doInitialization(Module &M) {
-
ObjFileMMI = nullptr;
CurCallSite = 0;
DbgInfoAvailable = UsesVAFloatArgument = UsesMorestackAddr = false;
@@ -211,7 +215,6 @@ bool MachineModuleInfo::doInitialization(Module &M) {
}
bool MachineModuleInfo::doFinalization(Module &M) {
-
Personalities.clear();
delete AddrLabelSymbols;
@@ -290,10 +293,12 @@ void MachineModuleInfo::deleteMachineFunctionFor(Function &F) {
}
namespace {
+
/// This pass frees the MachineFunction object associated with a Function.
class FreeMachineFunction : public FunctionPass {
public:
static char ID;
+
FreeMachineFunction() : FunctionPass(ID) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
@@ -311,14 +316,14 @@ public:
return "Free MachineFunction";
}
};
-char FreeMachineFunction::ID;
+
} // end anonymous namespace
-namespace llvm {
-FunctionPass *createFreeMachineFunctionPass() {
+char FreeMachineFunction::ID;
+
+FunctionPass *llvm::createFreeMachineFunctionPass() {
return new FreeMachineFunction();
}
-} // end namespace llvm
//===- MMI building helpers -----------------------------------------------===//
diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index ab36bc1417ae..fb51a4eb1421 100644
--- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -280,6 +280,7 @@ namespace {
SDValue visitSELECT_CC(SDNode *N);
SDValue visitSETCC(SDNode *N);
SDValue visitSETCCE(SDNode *N);
+ SDValue visitSETCCCARRY(SDNode *N);
SDValue visitSIGN_EXTEND(SDNode *N);
SDValue visitZERO_EXTEND(SDNode *N);
SDValue visitANY_EXTEND(SDNode *N);
@@ -1457,6 +1458,7 @@ SDValue DAGCombiner::visit(SDNode *N) {
case ISD::SELECT_CC: return visitSELECT_CC(N);
case ISD::SETCC: return visitSETCC(N);
case ISD::SETCCE: return visitSETCCE(N);
+ case ISD::SETCCCARRY: return visitSETCCCARRY(N);
case ISD::SIGN_EXTEND: return visitSIGN_EXTEND(N);
case ISD::ZERO_EXTEND: return visitZERO_EXTEND(N);
case ISD::ANY_EXTEND: return visitANY_EXTEND(N);
@@ -1958,7 +1960,7 @@ SDValue DAGCombiner::visitADD(SDNode *N) {
// fold (a+b) -> (a|b) iff a and b share no bits.
if ((!LegalOperations || TLI.isOperationLegal(ISD::OR, VT)) &&
- VT.isInteger() && DAG.haveNoCommonBitsSet(N0, N1))
+ DAG.haveNoCommonBitsSet(N0, N1))
return DAG.getNode(ISD::OR, DL, VT, N0, N1);
if (SDValue Combined = visitADDLike(N0, N1, N))
@@ -1970,6 +1972,44 @@ SDValue DAGCombiner::visitADD(SDNode *N) {
return SDValue();
}
+static SDValue getAsCarry(const TargetLowering &TLI, SDValue V) {
+ bool Masked = false;
+
+ // First, peel away TRUNCATE/ZERO_EXTEND/AND nodes due to legalization.
+ while (true) {
+ if (V.getOpcode() == ISD::TRUNCATE || V.getOpcode() == ISD::ZERO_EXTEND) {
+ V = V.getOperand(0);
+ continue;
+ }
+
+ if (V.getOpcode() == ISD::AND && isOneConstant(V.getOperand(1))) {
+ Masked = true;
+ V = V.getOperand(0);
+ continue;
+ }
+
+ break;
+ }
+
+ // If this is not a carry, return.
+ if (V.getResNo() != 1)
+ return SDValue();
+
+ if (V.getOpcode() != ISD::ADDCARRY && V.getOpcode() != ISD::SUBCARRY &&
+ V.getOpcode() != ISD::UADDO && V.getOpcode() != ISD::USUBO)
+ return SDValue();
+
+ // If the result is masked, then no matter what kind of bool it is we can
+ // return. If it isn't, then we need to make sure the bool type is either 0 or
+ // 1 and not other values.
+ if (Masked ||
+ TLI.getBooleanContents(V.getValueType()) ==
+ TargetLoweringBase::ZeroOrOneBooleanContent)
+ return V;
+
+ return SDValue();
+}
+
SDValue DAGCombiner::visitADDLike(SDValue N0, SDValue N1, SDNode *LocReference) {
EVT VT = N0.getValueType();
SDLoc DL(LocReference);
@@ -2017,6 +2057,13 @@ SDValue DAGCombiner::visitADDLike(SDValue N0, SDValue N1, SDNode *LocReference)
return DAG.getNode(ISD::ADDCARRY, DL, N1->getVTList(),
N0, N1.getOperand(0), N1.getOperand(2));
+ // (add X, Carry) -> (addcarry X, 0, Carry)
+ if (TLI.isOperationLegalOrCustom(ISD::ADDCARRY, VT))
+ if (SDValue Carry = getAsCarry(TLI, N1))
+ return DAG.getNode(ISD::ADDCARRY, DL,
+ DAG.getVTList(VT, Carry.getValueType()), N0,
+ DAG.getConstant(0, DL, VT), Carry);
+
return SDValue();
}
@@ -2090,6 +2137,8 @@ SDValue DAGCombiner::visitUADDO(SDNode *N) {
}
SDValue DAGCombiner::visitUADDOLike(SDValue N0, SDValue N1, SDNode *N) {
+ auto VT = N0.getValueType();
+
// (uaddo X, (addcarry Y, 0, Carry)) -> (addcarry X, Y, Carry)
// If Y + 1 cannot overflow.
if (N1.getOpcode() == ISD::ADDCARRY && isNullConstant(N1.getOperand(1))) {
@@ -2100,6 +2149,12 @@ SDValue DAGCombiner::visitUADDOLike(SDValue N0, SDValue N1, SDNode *N) {
N1.getOperand(2));
}
+ // (uaddo X, Carry) -> (addcarry X, 0, Carry)
+ if (TLI.isOperationLegalOrCustom(ISD::ADDCARRY, VT))
+ if (SDValue Carry = getAsCarry(TLI, N1))
+ return DAG.getNode(ISD::ADDCARRY, SDLoc(N), N->getVTList(), N0,
+ DAG.getConstant(0, SDLoc(N), VT), Carry);
+
return SDValue();
}
@@ -2167,6 +2222,41 @@ SDValue DAGCombiner::visitADDCARRYLike(SDValue N0, SDValue N1, SDValue CarryIn,
return DAG.getNode(ISD::ADDCARRY, SDLoc(N), N->getVTList(),
N0.getOperand(0), N0.getOperand(1), CarryIn);
+ /**
+ * When one of the addcarry argument is itself a carry, we may be facing
+ * a diamond carry propagation. In which case we try to transform the DAG
+ * to ensure linear carry propagation if that is possible.
+ *
+ * We are trying to get:
+ * (addcarry X, 0, (addcarry A, B, Z):Carry)
+ */
+ if (auto Y = getAsCarry(TLI, N1)) {
+ /**
+ * (uaddo A, B)
+ * / \
+ * Carry Sum
+ * | \
+ * | (addcarry *, 0, Z)
+ * | /
+ * \ Carry
+ * | /
+ * (addcarry X, *, *)
+ */
+ if (Y.getOpcode() == ISD::UADDO &&
+ CarryIn.getResNo() == 1 &&
+ CarryIn.getOpcode() == ISD::ADDCARRY &&
+ isNullConstant(CarryIn.getOperand(1)) &&
+ CarryIn.getOperand(0) == Y.getValue(0)) {
+ auto NewY = DAG.getNode(ISD::ADDCARRY, SDLoc(N), Y->getVTList(),
+ Y.getOperand(0), Y.getOperand(1),
+ CarryIn.getOperand(2));
+ AddToWorklist(NewY.getNode());
+ return DAG.getNode(ISD::ADDCARRY, SDLoc(N), N->getVTList(), N0,
+ DAG.getConstant(0, SDLoc(N), N0.getValueType()),
+ NewY.getValue(1));
+ }
+ }
+
return SDValue();
}
@@ -6754,6 +6844,19 @@ SDValue DAGCombiner::visitSETCCE(SDNode *N) {
return SDValue();
}
+SDValue DAGCombiner::visitSETCCCARRY(SDNode *N) {
+ SDValue LHS = N->getOperand(0);
+ SDValue RHS = N->getOperand(1);
+ SDValue Carry = N->getOperand(2);
+ SDValue Cond = N->getOperand(3);
+
+ // If Carry is false, fold to a regular SETCC.
+ if (isNullConstant(Carry))
+ return DAG.getNode(ISD::SETCC, SDLoc(N), N->getVTList(), LHS, RHS, Cond);
+
+ return SDValue();
+}
+
/// Try to fold a sext/zext/aext dag node into a ConstantSDNode or
/// a build_vector of constants.
/// This function is called by the DAGCombiner when visiting sext/zext/aext
@@ -7124,12 +7227,11 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
SDValue ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, DL, VT, LN0->getChain(),
LN0->getBasePtr(), N0.getValueType(),
LN0->getMemOperand());
- CombineTo(N, ExtLoad);
SDValue Trunc = DAG.getNode(ISD::TRUNCATE, SDLoc(N0),
N0.getValueType(), ExtLoad);
- CombineTo(N0.getNode(), Trunc, ExtLoad.getValue(1));
ExtendSetCCUses(SetCCs, Trunc, ExtLoad, DL, ISD::SIGN_EXTEND);
- return SDValue(N, 0); // Return N so it doesn't get rechecked!
+ CombineTo(N0.getNode(), Trunc, ExtLoad.getValue(1));
+ return CombineTo(N, ExtLoad); // Return N so it doesn't get rechecked!
}
}
@@ -7185,10 +7287,9 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
SDValue Trunc = DAG.getNode(ISD::TRUNCATE,
SDLoc(N0.getOperand(0)),
N0.getOperand(0).getValueType(), ExtLoad);
- CombineTo(N, And);
- CombineTo(N0.getOperand(0).getNode(), Trunc, ExtLoad.getValue(1));
ExtendSetCCUses(SetCCs, Trunc, ExtLoad, DL, ISD::SIGN_EXTEND);
- return SDValue(N, 0); // Return N so it doesn't get rechecked!
+ CombineTo(N0.getOperand(0).getNode(), Trunc, ExtLoad.getValue(1));
+ return CombineTo(N, And); // Return N so it doesn't get rechecked!
}
}
}
@@ -7427,12 +7528,9 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
SDValue Trunc = DAG.getNode(ISD::TRUNCATE, SDLoc(N0),
N0.getValueType(), ExtLoad);
+ ExtendSetCCUses(SetCCs, Trunc, ExtLoad, SDLoc(N), ISD::ZERO_EXTEND);
CombineTo(N0.getNode(), Trunc, ExtLoad.getValue(1));
-
- ExtendSetCCUses(SetCCs, Trunc, ExtLoad, SDLoc(N),
- ISD::ZERO_EXTEND);
- CombineTo(N, ExtLoad);
- return SDValue(N, 0); // Return N so it doesn't get rechecked!
+ return CombineTo(N, ExtLoad); // Return N so it doesn't get rechecked!
}
}
@@ -7482,11 +7580,9 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
SDValue Trunc = DAG.getNode(ISD::TRUNCATE,
SDLoc(N0.getOperand(0)),
N0.getOperand(0).getValueType(), ExtLoad);
- CombineTo(N, And);
+ ExtendSetCCUses(SetCCs, Trunc, ExtLoad, DL, ISD::ZERO_EXTEND);
CombineTo(N0.getOperand(0).getNode(), Trunc, ExtLoad.getValue(1));
- ExtendSetCCUses(SetCCs, Trunc, ExtLoad, DL,
- ISD::ZERO_EXTEND);
- return SDValue(N, 0); // Return N so it doesn't get rechecked!
+ return CombineTo(N, And); // Return N so it doesn't get rechecked!
}
}
}
@@ -12777,10 +12873,10 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
}
// If we have load/store pair instructions and we only have two values,
- // don't bother.
+ // don't bother merging.
unsigned RequiredAlignment;
if (LoadNodes.size() == 2 && TLI.hasPairedLoad(MemVT, RequiredAlignment) &&
- St->getAlignment() >= RequiredAlignment) {
+ StoreNodes[0].MemNode->getAlignment() >= RequiredAlignment) {
StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + 2);
continue;
}
diff --git a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
index 92b0d2ae4015..0d5e07ded25c 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
@@ -2875,6 +2875,7 @@ bool DAGTypeLegalizer::ExpandIntegerOperand(SDNode *N, unsigned OpNo) {
case ISD::SELECT_CC: Res = ExpandIntOp_SELECT_CC(N); break;
case ISD::SETCC: Res = ExpandIntOp_SETCC(N); break;
case ISD::SETCCE: Res = ExpandIntOp_SETCCE(N); break;
+ case ISD::SETCCCARRY: Res = ExpandIntOp_SETCCCARRY(N); break;
case ISD::SINT_TO_FP: Res = ExpandIntOp_SINT_TO_FP(N); break;
case ISD::STORE: Res = ExpandIntOp_STORE(cast<StoreSDNode>(N), OpNo); break;
case ISD::TRUNCATE: Res = ExpandIntOp_TRUNCATE(N); break;
@@ -3009,14 +3010,16 @@ void DAGTypeLegalizer::IntegerExpandSetCCOperands(SDValue &NewLHS,
return;
}
- // Lower with SETCCE if the target supports it.
+ // Lower with SETCCE or SETCCCARRY if the target supports it.
+ EVT HiVT = LHSHi.getValueType();
+ EVT ExpandVT = TLI.getTypeToExpandTo(*DAG.getContext(), HiVT);
+ bool HasSETCCCARRY = TLI.isOperationLegalOrCustom(ISD::SETCCCARRY, ExpandVT);
+
// FIXME: Make all targets support this, then remove the other lowering.
- if (TLI.getOperationAction(
- ISD::SETCCE,
- TLI.getTypeToExpandTo(*DAG.getContext(), LHSLo.getValueType())) ==
- TargetLowering::Custom) {
- // SETCCE can detect < and >= directly. For > and <=, flip operands and
- // condition code.
+ if (HasSETCCCARRY ||
+ TLI.getOperationAction(ISD::SETCCE, ExpandVT) == TargetLowering::Custom) {
+ // SETCCE/SETCCCARRY can detect < and >= directly. For > and <=, flip
+ // operands and condition code.
bool FlipOperands = false;
switch (CCCode) {
case ISD::SETGT: CCCode = ISD::SETLT; FlipOperands = true; break;
@@ -3030,27 +3033,28 @@ void DAGTypeLegalizer::IntegerExpandSetCCOperands(SDValue &NewLHS,
std::swap(LHSHi, RHSHi);
}
// Perform a wide subtraction, feeding the carry from the low part into
- // SETCCE. The SETCCE operation is essentially looking at the high part of
- // the result of LHS - RHS. It is negative iff LHS < RHS. It is zero or
- // positive iff LHS >= RHS.
- SDVTList VTList = DAG.getVTList(LHSLo.getValueType(), MVT::Glue);
- SDValue LowCmp = DAG.getNode(ISD::SUBC, dl, VTList, LHSLo, RHSLo);
- SDValue Res =
- DAG.getNode(ISD::SETCCE, dl, getSetCCResultType(LHSLo.getValueType()),
- LHSHi, RHSHi, LowCmp.getValue(1), DAG.getCondCode(CCCode));
+ // SETCCE/SETCCCARRY. The SETCCE/SETCCCARRY operation is essentially
+ // looking at the high part of the result of LHS - RHS. It is negative
+ // iff LHS < RHS. It is zero or positive iff LHS >= RHS.
+ EVT LoVT = LHSLo.getValueType();
+ SDVTList VTList = DAG.getVTList(
+ LoVT, HasSETCCCARRY ? getSetCCResultType(LoVT) : MVT::Glue);
+ SDValue LowCmp = DAG.getNode(HasSETCCCARRY ? ISD::USUBO : ISD::SUBC, dl,
+ VTList, LHSLo, RHSLo);
+ SDValue Res = DAG.getNode(HasSETCCCARRY ? ISD::SETCCCARRY : ISD::SETCCE, dl,
+ getSetCCResultType(HiVT), LHSHi, RHSHi,
+ LowCmp.getValue(1), DAG.getCondCode(CCCode));
NewLHS = Res;
NewRHS = SDValue();
return;
}
- NewLHS = TLI.SimplifySetCC(getSetCCResultType(LHSHi.getValueType()),
- LHSHi, RHSHi, ISD::SETEQ, false,
- DagCombineInfo, dl);
+ NewLHS = TLI.SimplifySetCC(getSetCCResultType(HiVT), LHSHi, RHSHi, ISD::SETEQ,
+ false, DagCombineInfo, dl);
if (!NewLHS.getNode())
- NewLHS = DAG.getSetCC(dl, getSetCCResultType(LHSHi.getValueType()),
- LHSHi, RHSHi, ISD::SETEQ);
- NewLHS = DAG.getSelect(dl, LoCmp.getValueType(),
- NewLHS, LoCmp, HiCmp);
+ NewLHS =
+ DAG.getSetCC(dl, getSetCCResultType(HiVT), LHSHi, RHSHi, ISD::SETEQ);
+ NewLHS = DAG.getSelect(dl, LoCmp.getValueType(), NewLHS, LoCmp, HiCmp);
NewRHS = SDValue();
}
@@ -3103,8 +3107,8 @@ SDValue DAGTypeLegalizer::ExpandIntOp_SETCC(SDNode *N) {
}
// Otherwise, update N to have the operands specified.
- return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS,
- DAG.getCondCode(CCCode)), 0);
+ return SDValue(
+ DAG.UpdateNodeOperands(N, NewLHS, NewRHS, DAG.getCondCode(CCCode)), 0);
}
SDValue DAGTypeLegalizer::ExpandIntOp_SETCCE(SDNode *N) {
@@ -3125,6 +3129,24 @@ SDValue DAGTypeLegalizer::ExpandIntOp_SETCCE(SDNode *N) {
LowCmp.getValue(1), Cond);
}
+SDValue DAGTypeLegalizer::ExpandIntOp_SETCCCARRY(SDNode *N) {
+ SDValue LHS = N->getOperand(0);
+ SDValue RHS = N->getOperand(1);
+ SDValue Carry = N->getOperand(2);
+ SDValue Cond = N->getOperand(3);
+ SDLoc dl = SDLoc(N);
+
+ SDValue LHSLo, LHSHi, RHSLo, RHSHi;
+ GetExpandedInteger(LHS, LHSLo, LHSHi);
+ GetExpandedInteger(RHS, RHSLo, RHSHi);
+
+ // Expand to a SUBE for the low part and a smaller SETCCCARRY for the high.
+ SDVTList VTList = DAG.getVTList(LHSLo.getValueType(), Carry.getValueType());
+ SDValue LowCmp = DAG.getNode(ISD::SUBCARRY, dl, VTList, LHSLo, RHSLo, Carry);
+ return DAG.getNode(ISD::SETCCCARRY, dl, N->getValueType(0), LHSHi, RHSHi,
+ LowCmp.getValue(1), Cond);
+}
+
SDValue DAGTypeLegalizer::ExpandIntOp_Shift(SDNode *N) {
// The value being shifted is legal, but the shift amount is too big.
// It follows that either the result of the shift is undefined, or the
diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/lib/CodeGen/SelectionDAG/LegalizeTypes.h
index 4c3b514856b7..8e999188d8e1 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeTypes.h
+++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.h
@@ -381,6 +381,7 @@ private:
SDValue ExpandIntOp_SELECT_CC(SDNode *N);
SDValue ExpandIntOp_SETCC(SDNode *N);
SDValue ExpandIntOp_SETCCE(SDNode *N);
+ SDValue ExpandIntOp_SETCCCARRY(SDNode *N);
SDValue ExpandIntOp_Shift(SDNode *N);
SDValue ExpandIntOp_SINT_TO_FP(SDNode *N);
SDValue ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo);
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
index 4f4025d8ae6a..579112c9bfc8 100644
--- a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
+++ b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
@@ -226,6 +226,7 @@ private:
void UnscheduleNodeBottomUp(SUnit*);
void RestoreHazardCheckerBottomUp();
void BacktrackBottomUp(SUnit*, SUnit*);
+ SUnit *TryUnfoldSU(SUnit *);
SUnit *CopyAndMoveSuccessors(SUnit*);
void InsertCopiesAndMoveSuccs(SUnit*, unsigned,
const TargetRegisterClass*,
@@ -780,7 +781,7 @@ void ScheduleDAGRRList::ScheduleNodeBottomUp(SUnit *SU) {
}
/// CapturePred - This does the opposite of ReleasePred. Since SU is being
-/// unscheduled, incrcease the succ left count of its predecessors. Remove
+/// unscheduled, increase the succ left count of its predecessors. Remove
/// them from AvailableQueue if necessary.
void ScheduleDAGRRList::CapturePred(SDep *PredEdge) {
SUnit *PredSU = PredEdge->getSUnit();
@@ -934,6 +935,146 @@ static bool isOperandOf(const SUnit *SU, SDNode *N) {
return false;
}
+/// TryUnfold - Attempt to unfold
+SUnit *ScheduleDAGRRList::TryUnfoldSU(SUnit *SU) {
+ SDNode *N = SU->getNode();
+ // Use while over if to ease fall through.
+ SmallVector<SDNode *, 2> NewNodes;
+ if (!TII->unfoldMemoryOperand(*DAG, N, NewNodes))
+ return nullptr;
+
+ // unfolding an x86 DEC64m operation results in store, dec, load which
+ // can't be handled here so quit
+ if (NewNodes.size() == 3)
+ return nullptr;
+
+ assert(NewNodes.size() == 2 && "Expected a load folding node!");
+
+ N = NewNodes[1];
+ SDNode *LoadNode = NewNodes[0];
+ unsigned NumVals = N->getNumValues();
+ unsigned OldNumVals = SU->getNode()->getNumValues();
+
+ // LoadNode may already exist. This can happen when there is another
+ // load from the same location and producing the same type of value
+ // but it has different alignment or volatileness.
+ bool isNewLoad = true;
+ SUnit *LoadSU;
+ if (LoadNode->getNodeId() != -1) {
+ LoadSU = &SUnits[LoadNode->getNodeId()];
+ // If LoadSU has already been scheduled, we should clone it but
+ // this would negate the benefit to unfolding so just return SU.
+ if (LoadSU->isScheduled)
+ return SU;
+ isNewLoad = false;
+ } else {
+ LoadSU = CreateNewSUnit(LoadNode);
+ LoadNode->setNodeId(LoadSU->NodeNum);
+
+ InitNumRegDefsLeft(LoadSU);
+ computeLatency(LoadSU);
+ }
+
+ DEBUG(dbgs() << "Unfolding SU #" << SU->NodeNum << "\n");
+
+ // Now that we are committed to unfolding replace DAG Uses.
+ for (unsigned i = 0; i != NumVals; ++i)
+ DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), i), SDValue(N, i));
+ DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), OldNumVals - 1),
+ SDValue(LoadNode, 1));
+
+ SUnit *NewSU = CreateNewSUnit(N);
+ assert(N->getNodeId() == -1 && "Node already inserted!");
+ N->setNodeId(NewSU->NodeNum);
+
+ const MCInstrDesc &MCID = TII->get(N->getMachineOpcode());
+ for (unsigned i = 0; i != MCID.getNumOperands(); ++i) {
+ if (MCID.getOperandConstraint(i, MCOI::TIED_TO) != -1) {
+ NewSU->isTwoAddress = true;
+ break;
+ }
+ }
+ if (MCID.isCommutable())
+ NewSU->isCommutable = true;
+
+ InitNumRegDefsLeft(NewSU);
+ computeLatency(NewSU);
+
+ // Record all the edges to and from the old SU, by category.
+ SmallVector<SDep, 4> ChainPreds;
+ SmallVector<SDep, 4> ChainSuccs;
+ SmallVector<SDep, 4> LoadPreds;
+ SmallVector<SDep, 4> NodePreds;
+ SmallVector<SDep, 4> NodeSuccs;
+ for (SDep &Pred : SU->Preds) {
+ if (Pred.isCtrl())
+ ChainPreds.push_back(Pred);
+ else if (isOperandOf(Pred.getSUnit(), LoadNode))
+ LoadPreds.push_back(Pred);
+ else
+ NodePreds.push_back(Pred);
+ }
+ for (SDep &Succ : SU->Succs) {
+ if (Succ.isCtrl())
+ ChainSuccs.push_back(Succ);
+ else
+ NodeSuccs.push_back(Succ);
+ }
+
+ // Now assign edges to the newly-created nodes.
+ for (const SDep &Pred : ChainPreds) {
+ RemovePred(SU, Pred);
+ if (isNewLoad)
+ AddPred(LoadSU, Pred);
+ }
+ for (const SDep &Pred : LoadPreds) {
+ RemovePred(SU, Pred);
+ if (isNewLoad)
+ AddPred(LoadSU, Pred);
+ }
+ for (const SDep &Pred : NodePreds) {
+ RemovePred(SU, Pred);
+ AddPred(NewSU, Pred);
+ }
+ for (SDep D : NodeSuccs) {
+ SUnit *SuccDep = D.getSUnit();
+ D.setSUnit(SU);
+ RemovePred(SuccDep, D);
+ D.setSUnit(NewSU);
+ AddPred(SuccDep, D);
+ // Balance register pressure.
+ if (AvailableQueue->tracksRegPressure() && SuccDep->isScheduled &&
+ !D.isCtrl() && NewSU->NumRegDefsLeft > 0)
+ --NewSU->NumRegDefsLeft;
+ }
+ for (SDep D : ChainSuccs) {
+ SUnit *SuccDep = D.getSUnit();
+ D.setSUnit(SU);
+ RemovePred(SuccDep, D);
+ if (isNewLoad) {
+ D.setSUnit(LoadSU);
+ AddPred(SuccDep, D);
+ }
+ }
+
+ // Add a data dependency to reflect that NewSU reads the value defined
+ // by LoadSU.
+ SDep D(LoadSU, SDep::Data, 0);
+ D.setLatency(LoadSU->Latency);
+ AddPred(NewSU, D);
+
+ if (isNewLoad)
+ AvailableQueue->addNode(LoadSU);
+ AvailableQueue->addNode(NewSU);
+
+ ++NumUnfolds;
+
+ if (NewSU->NumSuccsLeft == 0)
+ NewSU->isAvailable = true;
+
+ return NewSU;
+}
+
/// CopyAndMoveSuccessors - Clone the specified node and move its scheduled
/// successors to the newly created node.
SUnit *ScheduleDAGRRList::CopyAndMoveSuccessors(SUnit *SU) {
@@ -959,135 +1100,16 @@ SUnit *ScheduleDAGRRList::CopyAndMoveSuccessors(SUnit *SU) {
return nullptr;
}
+ // If possible unfold instruction.
if (TryUnfold) {
- SmallVector<SDNode*, 2> NewNodes;
- if (!TII->unfoldMemoryOperand(*DAG, N, NewNodes))
+ SUnit *UnfoldSU = TryUnfoldSU(SU);
+ if (!UnfoldSU)
return nullptr;
-
- // unfolding an x86 DEC64m operation results in store, dec, load which
- // can't be handled here so quit
- if (NewNodes.size() == 3)
- return nullptr;
-
- DEBUG(dbgs() << "Unfolding SU #" << SU->NodeNum << "\n");
- assert(NewNodes.size() == 2 && "Expected a load folding node!");
-
- N = NewNodes[1];
- SDNode *LoadNode = NewNodes[0];
- unsigned NumVals = N->getNumValues();
- unsigned OldNumVals = SU->getNode()->getNumValues();
- for (unsigned i = 0; i != NumVals; ++i)
- DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), i), SDValue(N, i));
- DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), OldNumVals-1),
- SDValue(LoadNode, 1));
-
- // LoadNode may already exist. This can happen when there is another
- // load from the same location and producing the same type of value
- // but it has different alignment or volatileness.
- bool isNewLoad = true;
- SUnit *LoadSU;
- if (LoadNode->getNodeId() != -1) {
- LoadSU = &SUnits[LoadNode->getNodeId()];
- isNewLoad = false;
- } else {
- LoadSU = CreateNewSUnit(LoadNode);
- LoadNode->setNodeId(LoadSU->NodeNum);
-
- InitNumRegDefsLeft(LoadSU);
- computeLatency(LoadSU);
- }
-
- SUnit *NewSU = CreateNewSUnit(N);
- assert(N->getNodeId() == -1 && "Node already inserted!");
- N->setNodeId(NewSU->NodeNum);
-
- const MCInstrDesc &MCID = TII->get(N->getMachineOpcode());
- for (unsigned i = 0; i != MCID.getNumOperands(); ++i) {
- if (MCID.getOperandConstraint(i, MCOI::TIED_TO) != -1) {
- NewSU->isTwoAddress = true;
- break;
- }
- }
- if (MCID.isCommutable())
- NewSU->isCommutable = true;
-
- InitNumRegDefsLeft(NewSU);
- computeLatency(NewSU);
-
- // Record all the edges to and from the old SU, by category.
- SmallVector<SDep, 4> ChainPreds;
- SmallVector<SDep, 4> ChainSuccs;
- SmallVector<SDep, 4> LoadPreds;
- SmallVector<SDep, 4> NodePreds;
- SmallVector<SDep, 4> NodeSuccs;
- for (SDep &Pred : SU->Preds) {
- if (Pred.isCtrl())
- ChainPreds.push_back(Pred);
- else if (isOperandOf(Pred.getSUnit(), LoadNode))
- LoadPreds.push_back(Pred);
- else
- NodePreds.push_back(Pred);
- }
- for (SDep &Succ : SU->Succs) {
- if (Succ.isCtrl())
- ChainSuccs.push_back(Succ);
- else
- NodeSuccs.push_back(Succ);
- }
-
- // Now assign edges to the newly-created nodes.
- for (const SDep &Pred : ChainPreds) {
- RemovePred(SU, Pred);
- if (isNewLoad)
- AddPred(LoadSU, Pred);
- }
- for (const SDep &Pred : LoadPreds) {
- RemovePred(SU, Pred);
- if (isNewLoad)
- AddPred(LoadSU, Pred);
- }
- for (const SDep &Pred : NodePreds) {
- RemovePred(SU, Pred);
- AddPred(NewSU, Pred);
- }
- for (SDep D : NodeSuccs) {
- SUnit *SuccDep = D.getSUnit();
- D.setSUnit(SU);
- RemovePred(SuccDep, D);
- D.setSUnit(NewSU);
- AddPred(SuccDep, D);
- // Balance register pressure.
- if (AvailableQueue->tracksRegPressure() && SuccDep->isScheduled
- && !D.isCtrl() && NewSU->NumRegDefsLeft > 0)
- --NewSU->NumRegDefsLeft;
- }
- for (SDep D : ChainSuccs) {
- SUnit *SuccDep = D.getSUnit();
- D.setSUnit(SU);
- RemovePred(SuccDep, D);
- if (isNewLoad) {
- D.setSUnit(LoadSU);
- AddPred(SuccDep, D);
- }
- }
-
- // Add a data dependency to reflect that NewSU reads the value defined
- // by LoadSU.
- SDep D(LoadSU, SDep::Data, 0);
- D.setLatency(LoadSU->Latency);
- AddPred(NewSU, D);
-
- if (isNewLoad)
- AvailableQueue->addNode(LoadSU);
- AvailableQueue->addNode(NewSU);
-
- ++NumUnfolds;
-
- if (NewSU->NumSuccsLeft == 0) {
- NewSU->isAvailable = true;
- return NewSU;
- }
- SU = NewSU;
+ SU = UnfoldSU;
+ N = SU->getNode();
+ // If this can be scheduled don't bother duplicating and just return
+ if (SU->NumSuccsLeft == 0)
+ return SU;
}
DEBUG(dbgs() << " Duplicating SU #" << SU->NodeNum << "\n");
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index c37d7080f2c5..0dbd9e846aa6 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -214,6 +214,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::FPOWI: return "fpowi";
case ISD::SETCC: return "setcc";
case ISD::SETCCE: return "setcce";
+ case ISD::SETCCCARRY: return "setcccarry";
case ISD::SELECT: return "select";
case ISD::VSELECT: return "vselect";
case ISD::SELECT_CC: return "select_cc";
diff --git a/lib/CodeGen/TargetLoweringBase.cpp b/lib/CodeGen/TargetLoweringBase.cpp
index 0def5ae6d0d0..900c0318b179 100644
--- a/lib/CodeGen/TargetLoweringBase.cpp
+++ b/lib/CodeGen/TargetLoweringBase.cpp
@@ -842,9 +842,10 @@ TargetLoweringBase::TargetLoweringBase(const TargetMachine &tm) : TM(tm) {
initActions();
// Perform these initializations only once.
- MaxStoresPerMemset = MaxStoresPerMemcpy = MaxStoresPerMemmove = 8;
- MaxStoresPerMemsetOptSize = MaxStoresPerMemcpyOptSize
- = MaxStoresPerMemmoveOptSize = 4;
+ MaxStoresPerMemset = MaxStoresPerMemcpy = MaxStoresPerMemmove =
+ MaxLoadsPerMemcmp = 8;
+ MaxStoresPerMemsetOptSize = MaxStoresPerMemcpyOptSize =
+ MaxStoresPerMemmoveOptSize = MaxLoadsPerMemcmpOptSize = 4;
UseUnderscoreSetJmp = false;
UseUnderscoreLongJmp = false;
HasMultipleConditionRegisters = false;
@@ -926,6 +927,7 @@ void TargetLoweringBase::initActions() {
// ADDCARRY operations default to expand
setOperationAction(ISD::ADDCARRY, VT, Expand);
setOperationAction(ISD::SUBCARRY, VT, Expand);
+ setOperationAction(ISD::SETCCCARRY, VT, Expand);
// These default to Expand so they will be expanded to CTLZ/CTTZ by default.
setOperationAction(ISD::CTLZ_ZERO_UNDEF, VT, Expand);
diff --git a/lib/CodeGen/TargetPassConfig.cpp b/lib/CodeGen/TargetPassConfig.cpp
index 83348058eca9..72d5e995ac22 100644
--- a/lib/CodeGen/TargetPassConfig.cpp
+++ b/lib/CodeGen/TargetPassConfig.cpp
@@ -261,9 +261,9 @@ TargetPassConfig::~TargetPassConfig() {
// Out of line constructor provides default values for pass options and
// registers all common codegen passes.
-TargetPassConfig::TargetPassConfig(TargetMachine *tm, PassManagerBase &pm)
+TargetPassConfig::TargetPassConfig(LLVMTargetMachine &TM, PassManagerBase &pm)
: ImmutablePass(ID), PM(&pm), Started(true), Stopped(false),
- AddingMachinePasses(false), TM(tm), Impl(nullptr), Initialized(false),
+ AddingMachinePasses(false), TM(&TM), Impl(nullptr), Initialized(false),
DisableVerify(false), EnableTailMerge(true),
RequireCodeGenSCCOrder(false) {
@@ -282,9 +282,9 @@ TargetPassConfig::TargetPassConfig(TargetMachine *tm, PassManagerBase &pm)
substitutePass(&PostRAMachineLICMID, &MachineLICMID);
if (StringRef(PrintMachineInstrs.getValue()).equals(""))
- TM->Options.PrintMachineCode = true;
+ TM.Options.PrintMachineCode = true;
- if (TM->Options.EnableIPRA)
+ if (TM.Options.EnableIPRA)
setRequiresCodeGenSCCOrder();
}
@@ -310,7 +310,7 @@ void TargetPassConfig::insertPass(AnalysisID TargetPassID,
///
/// Targets may override this to extend TargetPassConfig.
TargetPassConfig *LLVMTargetMachine::createPassConfig(PassManagerBase &PM) {
- return new TargetPassConfig(this, PM);
+ return new TargetPassConfig(*this, PM);
}
TargetPassConfig::TargetPassConfig()
@@ -430,7 +430,12 @@ void TargetPassConfig::addPrintPass(const std::string &Banner) {
}
void TargetPassConfig::addVerifyPass(const std::string &Banner) {
- if (VerifyMachineCode)
+ bool Verify = VerifyMachineCode;
+#ifdef EXPENSIVE_CHECKS
+ if (VerifyMachineCode == cl::BOU_UNSET)
+ Verify = TM->isMachineVerifierClean();
+#endif
+ if (Verify)
PM->add(createMachineVerifierPass(Banner));
}
diff --git a/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp b/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp
index 4c78caf03477..d058f4864975 100644
--- a/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp
+++ b/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp
@@ -46,7 +46,7 @@ Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record) {
}
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
SYMBOL_RECORD(EnumVal, EnumVal, AliasName)
-#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
+#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
}
if (auto EC = Callbacks.visitSymbolEnd(Record))
diff --git a/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
index 705b548141b0..f0debd9e9702 100644
--- a/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
+++ b/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
@@ -71,7 +71,7 @@ static Error visitMemberRecord(CVMemberRecord &Record,
MEMBER_RECORD(EnumVal, EnumVal, AliasName)
#define TYPE_RECORD(EnumName, EnumVal, Name)
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
}
if (auto EC = Callbacks.visitMemberEnd(Record))
@@ -155,7 +155,7 @@ Error CVTypeVisitor::finishVisitation(CVType &Record) {
TYPE_RECORD(EnumVal, EnumVal, AliasName)
#define MEMBER_RECORD(EnumName, EnumVal, Name)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
}
if (auto EC = Callbacks.visitTypeEnd(Record))
diff --git a/lib/DebugInfo/CodeView/EnumTables.cpp b/lib/DebugInfo/CodeView/EnumTables.cpp
index 0441110c85ef..01d8ccf2d31e 100644
--- a/lib/DebugInfo/CodeView/EnumTables.cpp
+++ b/lib/DebugInfo/CodeView/EnumTables.cpp
@@ -20,13 +20,13 @@ using namespace codeview;
static const EnumEntry<SymbolKind> SymbolTypeNames[] = {
#define CV_SYMBOL(enum, val) {#enum, enum},
-#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
+#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
#undef CV_SYMBOL
};
static const EnumEntry<TypeLeafKind> TypeLeafNames[] = {
#define CV_TYPE(name, val) {#name, name},
-#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
#undef CV_TYPE
};
diff --git a/lib/DebugInfo/CodeView/SymbolDumper.cpp b/lib/DebugInfo/CodeView/SymbolDumper.cpp
index 2f5a7d256c60..3d49a7198d1a 100644
--- a/lib/DebugInfo/CodeView/SymbolDumper.cpp
+++ b/lib/DebugInfo/CodeView/SymbolDumper.cpp
@@ -41,7 +41,7 @@ public:
#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
Error visitKnownRecord(CVSymbol &CVR, Name &Record) override;
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
+#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
Error visitSymbolBegin(CVSymbol &Record) override;
Error visitSymbolEnd(CVSymbol &Record) override;
diff --git a/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp b/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp
index 84f52a055815..04b0384d8190 100644
--- a/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp
+++ b/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp
@@ -26,7 +26,7 @@ using namespace llvm::codeview;
static const EnumEntry<TypeLeafKind> LeafTypeNames[] = {
#define CV_TYPE(enum, val) {#enum, enum},
-#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
};
#define ENUM_ENTRY(enum_class, enum) \
@@ -155,7 +155,7 @@ static StringRef getLeafTypeName(TypeLeafKind LT) {
#define TYPE_RECORD(ename, value, name) \
case ename: \
return #name;
-#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
default:
break;
}
diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp
index 5ed55ce4c0dc..1be156d6ea9b 100644
--- a/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -84,8 +84,12 @@ static void dumpAccelSection(raw_ostream &OS, StringRef Name,
Accel.dump(OS);
}
-void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH,
- bool SummarizeTypes) {
+void DWARFContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts){
+
+ DIDumpType DumpType = DumpOpts.DumpType;
+ bool DumpEH = DumpOpts.DumpEH;
+ bool SummarizeTypes = DumpOpts.SummarizeTypes;
+
if (DumpType == DIDT_All || DumpType == DIDT_Abbrev) {
OS << ".debug_abbrev contents:\n";
getDebugAbbrev()->dump(OS);
diff --git a/lib/DebugInfo/PDB/Native/InfoStream.cpp b/lib/DebugInfo/PDB/Native/InfoStream.cpp
index 2a1d12e82390..7c6069652da6 100644
--- a/lib/DebugInfo/PDB/Native/InfoStream.cpp
+++ b/lib/DebugInfo/PDB/Native/InfoStream.cpp
@@ -79,6 +79,7 @@ Error InfoStream::reload() {
break;
case uint32_t(PdbRaw_FeatureSig::MinimalDebugInfo):
Features |= PdbFeatureMinimalDebugInfo;
+ break;
default:
continue;
}
diff --git a/lib/DebugInfo/PDB/PDBContext.cpp b/lib/DebugInfo/PDB/PDBContext.cpp
index 94b81ecf561e..f6b6b951ebe1 100644
--- a/lib/DebugInfo/PDB/PDBContext.cpp
+++ b/lib/DebugInfo/PDB/PDBContext.cpp
@@ -29,8 +29,7 @@ PDBContext::PDBContext(const COFFObjectFile &Object,
Session->setLoadAddress(ImageBase.get());
}
-void PDBContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH,
- bool SummarizeTypes) {}
+void PDBContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts){}
DILineInfo PDBContext::getLineInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier) {
diff --git a/lib/Fuzzer/test/dump_coverage.test b/lib/Fuzzer/test/dump_coverage.test
index 8acc8304fc60..bd85ed718e19 100644
--- a/lib/Fuzzer/test/dump_coverage.test
+++ b/lib/Fuzzer/test/dump_coverage.test
@@ -4,11 +4,11 @@ RUN: sancov -covered-functions LLVMFuzzer-NullDerefTest* %t_workdir/*.sancov | F
RUN: env ASAN_OPTIONS=coverage_dir='"%t_workdir"' LLVMFuzzer-DSOTest -dump_coverage=1 -runs=0 2>&1 | FileCheck %s --check-prefix=DSO
RUN: env ASAN_OPTIONS=coverage_dir='"%t_workdir"' not LLVMFuzzer-NullDerefTest -dump_coverage=0 2>&1 | FileCheck %s --check-prefix=NOCOV
-CHECK: SanitizerCoverage: {{.*}}LLVMFuzzer-NullDerefTest.{{.*}}.sancov {{.*}} PCs written
+CHECK: SanitizerCoverage: {{.*}}LLVMFuzzer-NullDerefTest.{{.*}}.sancov: {{.*}} PCs written
SANCOV: LLVMFuzzerTestOneInput
-DSO: SanitizerCoverage: {{.*}}LLVMFuzzer-DSOTest.{{.*}}.sancov {{.*}} PCs written
-DSO-DAG: SanitizerCoverage: {{.*}}LLVMFuzzer-DSO1.{{.*}}.sancov {{.*}} PCs written
-DSO-DAG: SanitizerCoverage: {{.*}}LLVMFuzzer-DSO2.{{.*}}.sancov {{.*}} PCs written
+DSO: SanitizerCoverage: {{.*}}LLVMFuzzer-DSOTest.{{.*}}.sancov: {{.*}} PCs written
+DSO-DAG: SanitizerCoverage: {{.*}}LLVMFuzzer-DSO1.{{.*}}.sancov: {{.*}} PCs written
+DSO-DAG: SanitizerCoverage: {{.*}}LLVMFuzzer-DSO2.{{.*}}.sancov: {{.*}} PCs written
NOCOV-NOT: SanitizerCoverage: {{.*}} PCs written
diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp
index 19b7c3027232..a76c944f0005 100644
--- a/lib/IR/Attributes.cpp
+++ b/lib/IR/Attributes.cpp
@@ -1006,6 +1006,10 @@ AttributeList AttributeList::get(LLVMContext &C,
for (AttributeList List : Attrs)
MaxSize = std::max(MaxSize, List.getNumAttrSets());
+ // If every list was empty, there is no point in merging the lists.
+ if (MaxSize == 0)
+ return AttributeList();
+
SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
for (unsigned I = 0; I < MaxSize; ++I) {
AttrBuilder CurBuilder;
@@ -1033,24 +1037,11 @@ AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index,
return addAttributes(C, Index, B);
}
-AttributeList AttributeList::addAttribute(LLVMContext &C,
- ArrayRef<unsigned> Indices,
+AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index,
Attribute A) const {
- assert(std::is_sorted(Indices.begin(), Indices.end()));
-
- SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
- unsigned MaxIndex = attrIdxToArrayIdx(Indices.back());
- if (MaxIndex >= AttrSets.size())
- AttrSets.resize(MaxIndex + 1);
-
- for (unsigned Index : Indices) {
- Index = attrIdxToArrayIdx(Index);
- AttrBuilder B(AttrSets[Index]);
- B.addAttribute(A);
- AttrSets[Index] = AttributeSet::get(C, B);
- }
-
- return getImpl(C, AttrSets);
+ AttrBuilder B;
+ B.addAttribute(A);
+ return addAttributes(C, Index, B);
}
AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned Index,
@@ -1082,6 +1073,26 @@ AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned Index,
return getImpl(C, AttrSets);
}
+AttributeList AttributeList::addParamAttribute(LLVMContext &C,
+ ArrayRef<unsigned> ArgNos,
+ Attribute A) const {
+ assert(std::is_sorted(ArgNos.begin(), ArgNos.end()));
+
+ SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
+ unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
+ if (MaxIndex >= AttrSets.size())
+ AttrSets.resize(MaxIndex + 1);
+
+ for (unsigned ArgNo : ArgNos) {
+ unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
+ AttrBuilder B(AttrSets[Index]);
+ B.addAttribute(A);
+ AttrSets[Index] = AttributeSet::get(C, B);
+ }
+
+ return getImpl(C, AttrSets);
+}
+
AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index,
Attribute::AttrKind Kind) const {
if (!hasAttribute(Index, Kind)) return *this;
diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp
index 39de4b0a97fa..fc68c0e3cad9 100644
--- a/lib/IR/Function.cpp
+++ b/lib/IR/Function.cpp
@@ -118,15 +118,13 @@ unsigned Argument::getParamAlignment() const {
uint64_t Argument::getDereferenceableBytes() const {
assert(getType()->isPointerTy() &&
"Only pointers have dereferenceable bytes");
- return getParent()->getDereferenceableBytes(getArgNo() +
- AttributeList::FirstArgIndex);
+ return getParent()->getParamDereferenceableBytes(getArgNo());
}
uint64_t Argument::getDereferenceableOrNullBytes() const {
assert(getType()->isPointerTy() &&
"Only pointers have dereferenceable bytes");
- return getParent()->getDereferenceableOrNullBytes(
- getArgNo() + AttributeList::FirstArgIndex);
+ return getParent()->getParamDereferenceableOrNullBytes(getArgNo());
}
bool Argument::hasNestAttr() const {
@@ -169,21 +167,20 @@ bool Argument::onlyReadsMemory() const {
void Argument::addAttrs(AttrBuilder &B) {
AttributeList AL = getParent()->getAttributes();
- AL = AL.addAttributes(Parent->getContext(),
- getArgNo() + AttributeList::FirstArgIndex, B);
+ AL = AL.addParamAttributes(Parent->getContext(), getArgNo(), B);
getParent()->setAttributes(AL);
}
void Argument::addAttr(Attribute::AttrKind Kind) {
- getParent()->addAttribute(getArgNo() + AttributeList::FirstArgIndex, Kind);
+ getParent()->addParamAttr(getArgNo(), Kind);
}
void Argument::addAttr(Attribute Attr) {
- getParent()->addAttribute(getArgNo() + AttributeList::FirstArgIndex, Attr);
+ getParent()->addParamAttr(getArgNo(), Attr);
}
void Argument::removeAttr(Attribute::AttrKind Kind) {
- getParent()->removeAttribute(getArgNo() + AttributeList::FirstArgIndex, Kind);
+ getParent()->removeParamAttr(getArgNo(), Kind);
}
bool Argument::hasAttribute(Attribute::AttrKind Kind) const {
@@ -365,6 +362,24 @@ void Function::addAttributes(unsigned i, const AttrBuilder &Attrs) {
setAttributes(PAL);
}
+void Function::addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
+ AttributeList PAL = getAttributes();
+ PAL = PAL.addParamAttribute(getContext(), ArgNo, Kind);
+ setAttributes(PAL);
+}
+
+void Function::addParamAttr(unsigned ArgNo, Attribute Attr) {
+ AttributeList PAL = getAttributes();
+ PAL = PAL.addParamAttribute(getContext(), ArgNo, Attr);
+ setAttributes(PAL);
+}
+
+void Function::addParamAttrs(unsigned ArgNo, const AttrBuilder &Attrs) {
+ AttributeList PAL = getAttributes();
+ PAL = PAL.addParamAttributes(getContext(), ArgNo, Attrs);
+ setAttributes(PAL);
+}
+
void Function::removeAttribute(unsigned i, Attribute::AttrKind Kind) {
AttributeList PAL = getAttributes();
PAL = PAL.removeAttribute(getContext(), i, Kind);
@@ -383,18 +398,49 @@ void Function::removeAttributes(unsigned i, const AttrBuilder &Attrs) {
setAttributes(PAL);
}
+void Function::removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
+ AttributeList PAL = getAttributes();
+ PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind);
+ setAttributes(PAL);
+}
+
+void Function::removeParamAttr(unsigned ArgNo, StringRef Kind) {
+ AttributeList PAL = getAttributes();
+ PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind);
+ setAttributes(PAL);
+}
+
+void Function::removeParamAttrs(unsigned ArgNo, const AttrBuilder &Attrs) {
+ AttributeList PAL = getAttributes();
+ PAL = PAL.removeParamAttributes(getContext(), ArgNo, Attrs);
+ setAttributes(PAL);
+}
+
void Function::addDereferenceableAttr(unsigned i, uint64_t Bytes) {
AttributeList PAL = getAttributes();
PAL = PAL.addDereferenceableAttr(getContext(), i, Bytes);
setAttributes(PAL);
}
+void Function::addDereferenceableParamAttr(unsigned ArgNo, uint64_t Bytes) {
+ AttributeList PAL = getAttributes();
+ PAL = PAL.addDereferenceableParamAttr(getContext(), ArgNo, Bytes);
+ setAttributes(PAL);
+}
+
void Function::addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes) {
AttributeList PAL = getAttributes();
PAL = PAL.addDereferenceableOrNullAttr(getContext(), i, Bytes);
setAttributes(PAL);
}
+void Function::addDereferenceableOrNullParamAttr(unsigned ArgNo,
+ uint64_t Bytes) {
+ AttributeList PAL = getAttributes();
+ PAL = PAL.addDereferenceableOrNullParamAttr(getContext(), ArgNo, Bytes);
+ setAttributes(PAL);
+}
+
const std::string &Function::getGC() const {
assert(hasGC() && "Function has no collector");
return getContext().getGC(*this);
diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp
index d7baa9ebc223..46c27331ff95 100644
--- a/lib/IR/Instructions.cpp
+++ b/lib/IR/Instructions.cpp
@@ -393,7 +393,17 @@ void CallInst::addAttribute(unsigned i, Attribute Attr) {
}
void CallInst::addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
- addAttribute(ArgNo + AttributeList::FirstArgIndex, Kind);
+ assert(ArgNo < getNumArgOperands() && "Out of bounds");
+ AttributeList PAL = getAttributes();
+ PAL = PAL.addParamAttribute(getContext(), ArgNo, Kind);
+ setAttributes(PAL);
+}
+
+void CallInst::addParamAttr(unsigned ArgNo, Attribute Attr) {
+ assert(ArgNo < getNumArgOperands() && "Out of bounds");
+ AttributeList PAL = getAttributes();
+ PAL = PAL.addParamAttribute(getContext(), ArgNo, Attr);
+ setAttributes(PAL);
}
void CallInst::removeAttribute(unsigned i, Attribute::AttrKind Kind) {
@@ -409,7 +419,17 @@ void CallInst::removeAttribute(unsigned i, StringRef Kind) {
}
void CallInst::removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
- removeAttribute(ArgNo + AttributeList::FirstArgIndex, Kind);
+ assert(ArgNo < getNumArgOperands() && "Out of bounds");
+ AttributeList PAL = getAttributes();
+ PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind);
+ setAttributes(PAL);
+}
+
+void CallInst::removeParamAttr(unsigned ArgNo, StringRef Kind) {
+ assert(ArgNo < getNumArgOperands() && "Out of bounds");
+ AttributeList PAL = getAttributes();
+ PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind);
+ setAttributes(PAL);
}
void CallInst::addDereferenceableAttr(unsigned i, uint64_t Bytes) {
@@ -808,7 +828,9 @@ void InvokeInst::addAttribute(unsigned i, Attribute Attr) {
}
void InvokeInst::addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
- addAttribute(ArgNo + AttributeList::FirstArgIndex, Kind);
+ AttributeList PAL = getAttributes();
+ PAL = PAL.addParamAttribute(getContext(), ArgNo, Kind);
+ setAttributes(PAL);
}
void InvokeInst::removeAttribute(unsigned i, Attribute::AttrKind Kind) {
@@ -824,7 +846,9 @@ void InvokeInst::removeAttribute(unsigned i, StringRef Kind) {
}
void InvokeInst::removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
- removeAttribute(ArgNo + AttributeList::FirstArgIndex, Kind);
+ AttributeList PAL = getAttributes();
+ PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind);
+ setAttributes(PAL);
}
void InvokeInst::addDereferenceableAttr(unsigned i, uint64_t Bytes) {
diff --git a/lib/LTO/LTOBackend.cpp b/lib/LTO/LTOBackend.cpp
index 668667a53562..f9c41f5c9744 100644
--- a/lib/LTO/LTOBackend.cpp
+++ b/lib/LTO/LTOBackend.cpp
@@ -136,7 +136,8 @@ createTargetMachine(Config &Conf, const Target *TheTarget, Module &M) {
Conf.CodeModel, Conf.CGOptLevel));
}
-static void runNewPMPasses(Module &Mod, TargetMachine *TM, unsigned OptLevel) {
+static void runNewPMPasses(Module &Mod, TargetMachine *TM, unsigned OptLevel,
+ bool IsThinLTO) {
PassBuilder PB(TM);
AAManager AA;
@@ -180,7 +181,10 @@ static void runNewPMPasses(Module &Mod, TargetMachine *TM, unsigned OptLevel) {
break;
}
- MPM = PB.buildLTODefaultPipeline(OL, false /* DebugLogging */);
+ if (IsThinLTO)
+ MPM = PB.buildThinLTODefaultPipeline(OL, false /* DebugLogging */);
+ else
+ MPM = PB.buildLTODefaultPipeline(OL, false /* DebugLogging */);
MPM.run(Mod, MAM);
// FIXME (davide): verify the output.
@@ -258,17 +262,12 @@ static void runOldPMPasses(Config &Conf, Module &Mod, TargetMachine *TM,
bool opt(Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod,
bool IsThinLTO, ModuleSummaryIndex *ExportSummary,
const ModuleSummaryIndex *ImportSummary) {
- // There's still no ThinLTO pipeline hooked up in the new pass manager,
- // once there is one, we can just remove this.
- if (LTOUseNewPM && IsThinLTO)
- report_fatal_error("ThinLTO not supported with the new PM yet!");
-
// FIXME: Plumb the combined index into the new pass manager.
if (!Conf.OptPipeline.empty())
runNewPMCustomPasses(Mod, TM, Conf.OptPipeline, Conf.AAPipeline,
Conf.DisableVerify);
else if (LTOUseNewPM)
- runNewPMPasses(Mod, TM, Conf.OptLevel);
+ runNewPMPasses(Mod, TM, Conf.OptLevel, IsThinLTO);
else
runOldPMPasses(Conf, Mod, TM, IsThinLTO, ExportSummary, ImportSummary);
return !Conf.PostOptModuleHook || Conf.PostOptModuleHook(Task, Mod);
diff --git a/lib/MC/MCCodeView.cpp b/lib/MC/MCCodeView.cpp
index a0a0ef312276..6c9a4f9f982d 100644
--- a/lib/MC/MCCodeView.cpp
+++ b/lib/MC/MCCodeView.cpp
@@ -12,11 +12,11 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCCodeView.h"
-#include "llvm/MC/MCAsmLayout.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCObjectStreamer.h"
#include "llvm/MC/MCValue.h"
diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp
index bfb8875f47d4..084159a61f55 100644
--- a/lib/Object/MachOObjectFile.cpp
+++ b/lib/Object/MachOObjectFile.cpp
@@ -3269,7 +3269,6 @@ void MachOBindEntry::moveNext() {
if (ImmValue) {
SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
Ordinal = SignExtended;
- LibraryOrdinalSet = true;
if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {
*E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
"special ordinal: " + Twine((int)Ordinal) + " for opcode at: "
@@ -3279,6 +3278,7 @@ void MachOBindEntry::moveNext() {
}
} else
Ordinal = 0;
+ LibraryOrdinalSet = true;
DEBUG_WITH_TYPE(
"mach-o-bind",
dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
diff --git a/lib/Object/WindowsResource.cpp b/lib/Object/WindowsResource.cpp
index b52563469094..e46d38e466a0 100644
--- a/lib/Object/WindowsResource.cpp
+++ b/lib/Object/WindowsResource.cpp
@@ -12,20 +12,23 @@
//===----------------------------------------------------------------------===//
#include "llvm/Object/WindowsResource.h"
-#include "llvm/Object/Error.h"
+#include "llvm/Support/COFF.h"
+#include <sstream>
#include <system_error>
namespace llvm {
namespace object {
-static const size_t ResourceMagicSize = 16;
-
-static const size_t NullEntrySize = 16;
-
#define RETURN_IF_ERROR(X) \
if (auto EC = X) \
return EC;
+const uint32_t MIN_HEADER_SIZE = 7 * sizeof(uint32_t) + 2 * sizeof(uint16_t);
+
+static const size_t ResourceMagicSize = 16;
+
+static const size_t NullEntrySize = 16;
+
WindowsResource::WindowsResource(MemoryBufferRef Source)
: Binary(Binary::ID_WinRes, Source) {
size_t LeadingSize = ResourceMagicSize + NullEntrySize;
@@ -33,8 +36,6 @@ WindowsResource::WindowsResource(MemoryBufferRef Source)
support::little);
}
-WindowsResource::~WindowsResource() = default;
-
Expected<std::unique_ptr<WindowsResource>>
WindowsResource::createWindowsResource(MemoryBufferRef Source) {
if (Source.getBufferSize() < ResourceMagicSize + NullEntrySize)
@@ -72,19 +73,150 @@ Error ResourceEntryRef::moveNext(bool &End) {
return Error::success();
}
+static Error readStringOrId(BinaryStreamReader &Reader, uint16_t &ID,
+ ArrayRef<UTF16> &Str, bool &IsString) {
+ uint16_t IDFlag;
+ RETURN_IF_ERROR(Reader.readInteger(IDFlag));
+ IsString = IDFlag != 0xffff;
+
+ if (IsString) {
+ Reader.setOffset(
+ Reader.getOffset() -
+ sizeof(uint16_t)); // Re-read the bytes which we used to check the flag.
+ RETURN_IF_ERROR(Reader.readWideString(Str));
+ } else
+ RETURN_IF_ERROR(Reader.readInteger(ID));
+
+ return Error::success();
+}
+
Error ResourceEntryRef::loadNext() {
uint32_t DataSize;
RETURN_IF_ERROR(Reader.readInteger(DataSize));
uint32_t HeaderSize;
RETURN_IF_ERROR(Reader.readInteger(HeaderSize));
- // The data and header size ints are themselves part of the header, so we must
- // subtract them from the size.
- RETURN_IF_ERROR(
- Reader.readStreamRef(HeaderBytes, HeaderSize - 2 * sizeof(uint32_t)));
- RETURN_IF_ERROR(Reader.readStreamRef(DataBytes, DataSize));
+
+ if (HeaderSize < MIN_HEADER_SIZE)
+ return make_error<GenericBinaryError>("Header size is too small.",
+ object_error::parse_failed);
+
+ RETURN_IF_ERROR(readStringOrId(Reader, TypeID, Type, IsStringType));
+
+ RETURN_IF_ERROR(readStringOrId(Reader, NameID, Name, IsStringName));
+
RETURN_IF_ERROR(Reader.padToAlignment(sizeof(uint32_t)));
+
+ RETURN_IF_ERROR(Reader.readObject(Suffix));
+
+ RETURN_IF_ERROR(Reader.readArray(Data, DataSize));
+
+ RETURN_IF_ERROR(Reader.padToAlignment(sizeof(uint32_t)));
+
+ return Error::success();
+}
+
+WindowsResourceParser::WindowsResourceParser() {}
+
+Error WindowsResourceParser::parse(WindowsResource *WR) {
+ auto EntryOrErr = WR->getHeadEntry();
+ if (!EntryOrErr)
+ return EntryOrErr.takeError();
+
+ ResourceEntryRef Entry = EntryOrErr.get();
+ bool End = false;
+
+ while (!End) {
+
+ Root.addEntry(Entry);
+
+ RETURN_IF_ERROR(Entry.moveNext(End));
+ }
+
return Error::success();
}
+void WindowsResourceParser::printTree() const {
+ ScopedPrinter Writer(outs());
+ Root.print(Writer, "Resource Tree");
+}
+
+void WindowsResourceParser::TreeNode::addEntry(const ResourceEntryRef &Entry) {
+ TreeNode &TypeNode = addTypeNode(Entry);
+ TreeNode &NameNode = TypeNode.addNameNode(Entry);
+ NameNode.addLanguageNode(Entry);
+}
+
+WindowsResourceParser::TreeNode::TreeNode(ArrayRef<UTF16> NameRef)
+ : Name(NameRef) {}
+
+WindowsResourceParser::TreeNode &
+WindowsResourceParser::TreeNode::addTypeNode(const ResourceEntryRef &Entry) {
+ if (Entry.checkTypeString())
+ return addChild(Entry.getTypeString());
+ else
+ return addChild(Entry.getTypeID());
+}
+
+WindowsResourceParser::TreeNode &
+WindowsResourceParser::TreeNode::addNameNode(const ResourceEntryRef &Entry) {
+ if (Entry.checkNameString())
+ return addChild(Entry.getNameString());
+ else
+ return addChild(Entry.getNameID());
+}
+
+WindowsResourceParser::TreeNode &
+WindowsResourceParser::TreeNode::addLanguageNode(
+ const ResourceEntryRef &Entry) {
+ return addChild(Entry.getLanguage());
+}
+
+WindowsResourceParser::TreeNode &
+WindowsResourceParser::TreeNode::addChild(uint32_t ID) {
+ auto Child = IDChildren.find(ID);
+ if (Child == IDChildren.end()) {
+ auto NewChild = llvm::make_unique<WindowsResourceParser::TreeNode>(ID);
+ WindowsResourceParser::TreeNode &Node = *NewChild;
+ IDChildren.emplace(ID, std::move(NewChild));
+ return Node;
+ } else
+ return *(Child->second);
+}
+
+WindowsResourceParser::TreeNode &
+WindowsResourceParser::TreeNode::addChild(ArrayRef<UTF16> NameRef) {
+ std::string NameString;
+ ArrayRef<UTF16> CorrectedName;
+ std::vector<UTF16> EndianCorrectedName;
+ if (llvm::sys::IsBigEndianHost) {
+ EndianCorrectedName.resize(NameRef.size() + 1);
+ std::copy(NameRef.begin(), NameRef.end(), EndianCorrectedName.begin() + 1);
+ EndianCorrectedName[0] = UNI_UTF16_BYTE_ORDER_MARK_SWAPPED;
+ CorrectedName = makeArrayRef(EndianCorrectedName);
+ } else
+ CorrectedName = NameRef;
+ llvm::convertUTF16ToUTF8String(CorrectedName, NameString);
+
+ auto Child = StringChildren.find(NameString);
+ if (Child == StringChildren.end()) {
+ auto NewChild = llvm::make_unique<WindowsResourceParser::TreeNode>(NameRef);
+ WindowsResourceParser::TreeNode &Node = *NewChild;
+ StringChildren.emplace(NameString, std::move(NewChild));
+ return Node;
+ } else
+ return *(Child->second);
+}
+
+void WindowsResourceParser::TreeNode::print(ScopedPrinter &Writer,
+ StringRef Name) const {
+ ListScope NodeScope(Writer, Name);
+ for (auto const &Child : StringChildren) {
+ Child.second->print(Writer, Child.first);
+ }
+ for (auto const &Child : IDChildren) {
+ Child.second->print(Writer, to_string(Child.first));
+ }
+}
+
} // namespace object
} // namespace llvm
diff --git a/lib/ObjectYAML/CMakeLists.txt b/lib/ObjectYAML/CMakeLists.txt
index 37f8fd7bce1a..7af0b9c194e6 100644
--- a/lib/ObjectYAML/CMakeLists.txt
+++ b/lib/ObjectYAML/CMakeLists.txt
@@ -1,4 +1,7 @@
add_llvm_library(LLVMObjectYAML
+ CodeViewYAMLTypes.cpp
+ CodeViewYAMLSymbols.cpp
+ CodeViewYAMLDebugSections.cpp
COFFYAML.cpp
DWARFEmitter.cpp
DWARFVisitor.cpp
diff --git a/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp b/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp
new file mode 100644
index 000000000000..f652ff57f30d
--- /dev/null
+++ b/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp
@@ -0,0 +1,127 @@
+//===- CodeViewYAMLDebugSections.cpp - CodeView YAMLIO debug sections -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines classes for handling the YAML representation of CodeView
+// Debug Info.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h"
+
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/EnumTables.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::CodeViewYAML;
+using namespace llvm::CodeViewYAML::detail;
+using namespace llvm::yaml;
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(SourceFileChecksumEntry)
+LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineEntry)
+LLVM_YAML_IS_SEQUENCE_VECTOR(SourceColumnEntry)
+LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineBlock)
+LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineInfo)
+LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeSite)
+LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeInfo)
+LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef)
+
+LLVM_YAML_DECLARE_SCALAR_TRAITS(HexFormattedString, false)
+LLVM_YAML_DECLARE_ENUM_TRAITS(FileChecksumKind)
+LLVM_YAML_DECLARE_BITSET_TRAITS(LineFlags)
+
+LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::SourceLineEntry)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::SourceColumnEntry)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::SourceFileChecksumEntry)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::SourceLineInfo)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::SourceLineBlock)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::InlineeInfo)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::InlineeSite)
+
+void ScalarBitSetTraits<LineFlags>::bitset(IO &io, LineFlags &Flags) {
+ io.bitSetCase(Flags, "HasColumnInfo", LF_HaveColumns);
+ io.enumFallback<Hex16>(Flags);
+}
+
+void ScalarEnumerationTraits<FileChecksumKind>::enumeration(
+ IO &io, FileChecksumKind &Kind) {
+ io.enumCase(Kind, "None", FileChecksumKind::None);
+ io.enumCase(Kind, "MD5", FileChecksumKind::MD5);
+ io.enumCase(Kind, "SHA1", FileChecksumKind::SHA1);
+ io.enumCase(Kind, "SHA256", FileChecksumKind::SHA256);
+}
+
+void ScalarTraits<HexFormattedString>::output(const HexFormattedString &Value,
+ void *ctx, raw_ostream &Out) {
+ StringRef Bytes(reinterpret_cast<const char *>(Value.Bytes.data()),
+ Value.Bytes.size());
+ Out << toHex(Bytes);
+}
+
+StringRef ScalarTraits<HexFormattedString>::input(StringRef Scalar, void *ctxt,
+ HexFormattedString &Value) {
+ std::string H = fromHex(Scalar);
+ Value.Bytes.assign(H.begin(), H.end());
+ return StringRef();
+}
+
+void MappingTraits<SourceLineEntry>::mapping(IO &IO, SourceLineEntry &Obj) {
+ IO.mapRequired("Offset", Obj.Offset);
+ IO.mapRequired("LineStart", Obj.LineStart);
+ IO.mapRequired("IsStatement", Obj.IsStatement);
+ IO.mapRequired("EndDelta", Obj.EndDelta);
+}
+
+void MappingTraits<SourceColumnEntry>::mapping(IO &IO, SourceColumnEntry &Obj) {
+ IO.mapRequired("StartColumn", Obj.StartColumn);
+ IO.mapRequired("EndColumn", Obj.EndColumn);
+}
+
+void MappingTraits<SourceLineBlock>::mapping(IO &IO, SourceLineBlock &Obj) {
+ IO.mapRequired("FileName", Obj.FileName);
+ IO.mapRequired("Lines", Obj.Lines);
+ IO.mapRequired("Columns", Obj.Columns);
+}
+
+void MappingTraits<SourceFileChecksumEntry>::mapping(
+ IO &IO, SourceFileChecksumEntry &Obj) {
+ IO.mapRequired("FileName", Obj.FileName);
+ IO.mapRequired("Kind", Obj.Kind);
+ IO.mapRequired("Checksum", Obj.ChecksumBytes);
+}
+
+void MappingTraits<SourceLineInfo>::mapping(IO &IO, SourceLineInfo &Obj) {
+ IO.mapRequired("CodeSize", Obj.CodeSize);
+
+ IO.mapRequired("Flags", Obj.Flags);
+ IO.mapRequired("RelocOffset", Obj.RelocOffset);
+ IO.mapRequired("RelocSegment", Obj.RelocSegment);
+ IO.mapRequired("Blocks", Obj.Blocks);
+}
+
+void MappingTraits<SourceFileInfo>::mapping(IO &IO, SourceFileInfo &Obj) {
+ IO.mapOptional("Checksums", Obj.FileChecksums);
+ IO.mapOptional("Lines", Obj.LineFragments);
+ IO.mapOptional("InlineeLines", Obj.Inlinees);
+}
+
+void MappingTraits<InlineeSite>::mapping(IO &IO, InlineeSite &Obj) {
+ IO.mapRequired("FileName", Obj.FileName);
+ IO.mapRequired("LineNum", Obj.SourceLineNum);
+ IO.mapRequired("Inlinee", Obj.Inlinee);
+ IO.mapOptional("ExtraFiles", Obj.ExtraFiles);
+}
+
+void MappingTraits<InlineeInfo>::mapping(IO &IO, InlineeInfo &Obj) {
+ IO.mapRequired("HasExtraFiles", Obj.HasExtraFiles);
+ IO.mapRequired("Sites", Obj.Sites);
+}
diff --git a/lib/ObjectYAML/CodeViewYAMLSymbols.cpp b/lib/ObjectYAML/CodeViewYAMLSymbols.cpp
new file mode 100644
index 000000000000..6e8bb5c7372c
--- /dev/null
+++ b/lib/ObjectYAML/CodeViewYAMLSymbols.cpp
@@ -0,0 +1,496 @@
+//===- CodeViewYAMLSymbols.cpp - CodeView YAMLIO Symbol implementation ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines classes for handling the YAML representation of CodeView
+// Debug Info.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ObjectYAML/CodeViewYAMLSymbols.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/EnumTables.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::CodeViewYAML;
+using namespace llvm::CodeViewYAML::detail;
+using namespace llvm::yaml;
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(TypeIndex)
+
+// We only need to declare these, the definitions are in CodeViewYAMLTypes.cpp
+LLVM_YAML_DECLARE_SCALAR_TRAITS(APSInt, false)
+LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeIndex, false)
+
+LLVM_YAML_DECLARE_ENUM_TRAITS(SymbolKind)
+
+LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym2Flags)
+LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym3Flags)
+LLVM_YAML_DECLARE_BITSET_TRAITS(ExportFlags)
+LLVM_YAML_DECLARE_BITSET_TRAITS(LocalSymFlags)
+LLVM_YAML_DECLARE_BITSET_TRAITS(ProcSymFlags)
+LLVM_YAML_DECLARE_BITSET_TRAITS(FrameProcedureOptions)
+LLVM_YAML_DECLARE_ENUM_TRAITS(CPUType)
+LLVM_YAML_DECLARE_ENUM_TRAITS(RegisterId)
+LLVM_YAML_DECLARE_ENUM_TRAITS(TrampolineType)
+LLVM_YAML_DECLARE_ENUM_TRAITS(ThunkOrdinal)
+
+void ScalarEnumerationTraits<SymbolKind>::enumeration(IO &io,
+ SymbolKind &Value) {
+ auto SymbolNames = getSymbolTypeNames();
+ for (const auto &E : SymbolNames)
+ io.enumCase(Value, E.Name.str().c_str(), E.Value);
+}
+
+void ScalarBitSetTraits<CompileSym2Flags>::bitset(IO &io,
+ CompileSym2Flags &Flags) {
+ auto FlagNames = getCompileSym2FlagNames();
+ for (const auto &E : FlagNames) {
+ io.bitSetCase(Flags, E.Name.str().c_str(),
+ static_cast<CompileSym2Flags>(E.Value));
+ }
+}
+
+void ScalarBitSetTraits<CompileSym3Flags>::bitset(IO &io,
+ CompileSym3Flags &Flags) {
+ auto FlagNames = getCompileSym3FlagNames();
+ for (const auto &E : FlagNames) {
+ io.bitSetCase(Flags, E.Name.str().c_str(),
+ static_cast<CompileSym3Flags>(E.Value));
+ }
+}
+
+void ScalarBitSetTraits<ExportFlags>::bitset(IO &io, ExportFlags &Flags) {
+ auto FlagNames = getExportSymFlagNames();
+ for (const auto &E : FlagNames) {
+ io.bitSetCase(Flags, E.Name.str().c_str(),
+ static_cast<ExportFlags>(E.Value));
+ }
+}
+
+void ScalarBitSetTraits<LocalSymFlags>::bitset(IO &io, LocalSymFlags &Flags) {
+ auto FlagNames = getLocalFlagNames();
+ for (const auto &E : FlagNames) {
+ io.bitSetCase(Flags, E.Name.str().c_str(),
+ static_cast<LocalSymFlags>(E.Value));
+ }
+}
+
+void ScalarBitSetTraits<ProcSymFlags>::bitset(IO &io, ProcSymFlags &Flags) {
+ auto FlagNames = getProcSymFlagNames();
+ for (const auto &E : FlagNames) {
+ io.bitSetCase(Flags, E.Name.str().c_str(),
+ static_cast<ProcSymFlags>(E.Value));
+ }
+}
+
+void ScalarBitSetTraits<FrameProcedureOptions>::bitset(
+ IO &io, FrameProcedureOptions &Flags) {
+ auto FlagNames = getFrameProcSymFlagNames();
+ for (const auto &E : FlagNames) {
+ io.bitSetCase(Flags, E.Name.str().c_str(),
+ static_cast<FrameProcedureOptions>(E.Value));
+ }
+}
+
+void ScalarEnumerationTraits<CPUType>::enumeration(IO &io, CPUType &Cpu) {
+ auto CpuNames = getCPUTypeNames();
+ for (const auto &E : CpuNames) {
+ io.enumCase(Cpu, E.Name.str().c_str(), static_cast<CPUType>(E.Value));
+ }
+}
+
+void ScalarEnumerationTraits<RegisterId>::enumeration(IO &io, RegisterId &Reg) {
+ auto RegNames = getRegisterNames();
+ for (const auto &E : RegNames) {
+ io.enumCase(Reg, E.Name.str().c_str(), static_cast<RegisterId>(E.Value));
+ }
+ io.enumFallback<Hex16>(Reg);
+}
+
+void ScalarEnumerationTraits<TrampolineType>::enumeration(
+ IO &io, TrampolineType &Tramp) {
+ auto TrampNames = getTrampolineNames();
+ for (const auto &E : TrampNames) {
+ io.enumCase(Tramp, E.Name.str().c_str(),
+ static_cast<TrampolineType>(E.Value));
+ }
+}
+
+void ScalarEnumerationTraits<ThunkOrdinal>::enumeration(IO &io,
+ ThunkOrdinal &Ord) {
+ auto ThunkNames = getThunkOrdinalNames();
+ for (const auto &E : ThunkNames) {
+ io.enumCase(Ord, E.Name.str().c_str(), static_cast<ThunkOrdinal>(E.Value));
+ }
+}
+
+namespace llvm {
+namespace CodeViewYAML {
+namespace detail {
+
+struct SymbolRecordBase {
+ codeview::SymbolKind Kind;
+ explicit SymbolRecordBase(codeview::SymbolKind K) : Kind(K) {}
+
+ virtual ~SymbolRecordBase() {}
+ virtual void map(yaml::IO &io) = 0;
+ virtual codeview::CVSymbol
+ toCodeViewSymbol(BumpPtrAllocator &Allocator) const = 0;
+ virtual Error fromCodeViewSymbol(codeview::CVSymbol Type) = 0;
+};
+
+template <typename T> struct SymbolRecordImpl : public SymbolRecordBase {
+ explicit SymbolRecordImpl(codeview::SymbolKind K)
+ : SymbolRecordBase(K), Symbol(static_cast<SymbolRecordKind>(K)) {}
+
+ void map(yaml::IO &io) override;
+
+ codeview::CVSymbol
+ toCodeViewSymbol(BumpPtrAllocator &Allocator) const override {
+ return SymbolSerializer::writeOneSymbol(Symbol, Allocator);
+ }
+ Error fromCodeViewSymbol(codeview::CVSymbol CVS) override {
+ return SymbolDeserializer::deserializeAs<T>(CVS, Symbol);
+ }
+
+ mutable T Symbol;
+};
+
+template <> void SymbolRecordImpl<ScopeEndSym>::map(IO &IO) {}
+
+template <> void SymbolRecordImpl<Thunk32Sym>::map(IO &IO) {
+ IO.mapRequired("Parent", Symbol.Parent);
+ IO.mapRequired("End", Symbol.End);
+ IO.mapRequired("Next", Symbol.Next);
+ IO.mapRequired("Off", Symbol.Offset);
+ IO.mapRequired("Seg", Symbol.Segment);
+ IO.mapRequired("Len", Symbol.Length);
+ IO.mapRequired("Ordinal", Symbol.Thunk);
+}
+
+template <> void SymbolRecordImpl<TrampolineSym>::map(IO &IO) {
+ IO.mapRequired("Type", Symbol.Type);
+ IO.mapRequired("Size", Symbol.Size);
+ IO.mapRequired("ThunkOff", Symbol.ThunkOffset);
+ IO.mapRequired("TargetOff", Symbol.TargetOffset);
+ IO.mapRequired("ThunkSection", Symbol.ThunkSection);
+ IO.mapRequired("TargetSection", Symbol.TargetSection);
+}
+
+template <> void SymbolRecordImpl<SectionSym>::map(IO &IO) {
+ IO.mapRequired("SectionNumber", Symbol.SectionNumber);
+ IO.mapRequired("Alignment", Symbol.Alignment);
+ IO.mapRequired("Rva", Symbol.Rva);
+ IO.mapRequired("Length", Symbol.Length);
+ IO.mapRequired("Characteristics", Symbol.Characteristics);
+ IO.mapRequired("Name", Symbol.Name);
+}
+
+template <> void SymbolRecordImpl<CoffGroupSym>::map(IO &IO) {
+ IO.mapRequired("Size", Symbol.Size);
+ IO.mapRequired("Characteristics", Symbol.Characteristics);
+ IO.mapRequired("Offset", Symbol.Offset);
+ IO.mapRequired("Segment", Symbol.Segment);
+ IO.mapRequired("Name", Symbol.Name);
+}
+
+template <> void SymbolRecordImpl<ExportSym>::map(IO &IO) {
+ IO.mapRequired("Ordinal", Symbol.Ordinal);
+ IO.mapRequired("Flags", Symbol.Flags);
+ IO.mapRequired("Name", Symbol.Name);
+}
+
+template <> void SymbolRecordImpl<ProcSym>::map(IO &IO) {
+ // TODO: Print the linkage name
+
+ IO.mapRequired("PtrParent", Symbol.Parent);
+ IO.mapRequired("PtrEnd", Symbol.End);
+ IO.mapRequired("PtrNext", Symbol.Next);
+ IO.mapRequired("CodeSize", Symbol.CodeSize);
+ IO.mapRequired("DbgStart", Symbol.DbgStart);
+ IO.mapRequired("DbgEnd", Symbol.DbgEnd);
+ IO.mapRequired("FunctionType", Symbol.FunctionType);
+ IO.mapRequired("Segment", Symbol.Segment);
+ IO.mapRequired("Flags", Symbol.Flags);
+ IO.mapRequired("DisplayName", Symbol.Name);
+}
+
+template <> void SymbolRecordImpl<RegisterSym>::map(IO &IO) {
+ IO.mapRequired("Type", Symbol.Index);
+ IO.mapRequired("Seg", Symbol.Register);
+ IO.mapRequired("Name", Symbol.Name);
+}
+
+template <> void SymbolRecordImpl<PublicSym32>::map(IO &IO) {
+ IO.mapRequired("Type", Symbol.Index);
+ IO.mapRequired("Seg", Symbol.Segment);
+ IO.mapRequired("Off", Symbol.Offset);
+ IO.mapRequired("Name", Symbol.Name);
+}
+
+template <> void SymbolRecordImpl<ProcRefSym>::map(IO &IO) {
+ IO.mapRequired("SumName", Symbol.SumName);
+ IO.mapRequired("SymOffset", Symbol.SymOffset);
+ IO.mapRequired("Mod", Symbol.Module);
+ IO.mapRequired("Name", Symbol.Name);
+}
+
+template <> void SymbolRecordImpl<EnvBlockSym>::map(IO &IO) {
+ IO.mapRequired("Entries", Symbol.Fields);
+}
+
+template <> void SymbolRecordImpl<InlineSiteSym>::map(IO &IO) {
+ IO.mapRequired("PtrParent", Symbol.Parent);
+ IO.mapRequired("PtrEnd", Symbol.End);
+ IO.mapRequired("Inlinee", Symbol.Inlinee);
+ // TODO: The binary annotations
+}
+
+template <> void SymbolRecordImpl<LocalSym>::map(IO &IO) {
+ IO.mapRequired("Type", Symbol.Type);
+ IO.mapRequired("Flags", Symbol.Flags);
+ IO.mapRequired("VarName", Symbol.Name);
+}
+
+template <> void SymbolRecordImpl<DefRangeSym>::map(IO &IO) {
+ // TODO: Print the subfields
+}
+
+template <> void SymbolRecordImpl<DefRangeSubfieldSym>::map(IO &IO) {
+ // TODO: Print the subfields
+}
+
+template <> void SymbolRecordImpl<DefRangeRegisterSym>::map(IO &IO) {
+ // TODO: Print the subfields
+}
+
+template <> void SymbolRecordImpl<DefRangeFramePointerRelSym>::map(IO &IO) {
+ // TODO: Print the subfields
+}
+
+template <> void SymbolRecordImpl<DefRangeSubfieldRegisterSym>::map(IO &IO) {
+ // TODO: Print the subfields
+}
+
+template <>
+void SymbolRecordImpl<DefRangeFramePointerRelFullScopeSym>::map(IO &IO) {
+ // TODO: Print the subfields
+}
+
+template <> void SymbolRecordImpl<DefRangeRegisterRelSym>::map(IO &IO) {
+ // TODO: Print the subfields
+}
+
+template <> void SymbolRecordImpl<BlockSym>::map(IO &IO) {
+ // TODO: Print the linkage name
+ IO.mapRequired("PtrParent", Symbol.Parent);
+ IO.mapRequired("PtrEnd", Symbol.End);
+ IO.mapRequired("CodeSize", Symbol.CodeSize);
+ IO.mapRequired("Segment", Symbol.Segment);
+ IO.mapRequired("BlockName", Symbol.Name);
+}
+
+template <> void SymbolRecordImpl<LabelSym>::map(IO &IO) {
+ // TODO: Print the linkage name
+ IO.mapRequired("Segment", Symbol.Segment);
+ IO.mapRequired("Flags", Symbol.Flags);
+ IO.mapRequired("Flags", Symbol.Flags);
+ IO.mapRequired("DisplayName", Symbol.Name);
+}
+
+template <> void SymbolRecordImpl<ObjNameSym>::map(IO &IO) {
+ IO.mapRequired("Signature", Symbol.Signature);
+ IO.mapRequired("ObjectName", Symbol.Name);
+}
+
+template <> void SymbolRecordImpl<Compile2Sym>::map(IO &IO) {
+ IO.mapRequired("Flags", Symbol.Flags);
+ IO.mapRequired("Machine", Symbol.Machine);
+ IO.mapRequired("FrontendMajor", Symbol.VersionFrontendMajor);
+ IO.mapRequired("FrontendMinor", Symbol.VersionFrontendMinor);
+ IO.mapRequired("FrontendBuild", Symbol.VersionFrontendBuild);
+ IO.mapRequired("BackendMajor", Symbol.VersionBackendMajor);
+ IO.mapRequired("BackendMinor", Symbol.VersionBackendMinor);
+ IO.mapRequired("BackendBuild", Symbol.VersionBackendBuild);
+ IO.mapRequired("Version", Symbol.Version);
+}
+
+template <> void SymbolRecordImpl<Compile3Sym>::map(IO &IO) {
+ IO.mapRequired("Flags", Symbol.Flags);
+ IO.mapRequired("Machine", Symbol.Machine);
+ IO.mapRequired("FrontendMajor", Symbol.VersionFrontendMajor);
+ IO.mapRequired("FrontendMinor", Symbol.VersionFrontendMinor);
+ IO.mapRequired("FrontendBuild", Symbol.VersionFrontendBuild);
+ IO.mapRequired("FrontendQFE", Symbol.VersionFrontendQFE);
+ IO.mapRequired("BackendMajor", Symbol.VersionBackendMajor);
+ IO.mapRequired("BackendMinor", Symbol.VersionBackendMinor);
+ IO.mapRequired("BackendBuild", Symbol.VersionBackendBuild);
+ IO.mapRequired("BackendQFE", Symbol.VersionBackendQFE);
+ IO.mapRequired("Version", Symbol.Version);
+}
+
+template <> void SymbolRecordImpl<FrameProcSym>::map(IO &IO) {
+ IO.mapRequired("TotalFrameBytes", Symbol.TotalFrameBytes);
+ IO.mapRequired("PaddingFrameBytes", Symbol.PaddingFrameBytes);
+ IO.mapRequired("OffsetToPadding", Symbol.OffsetToPadding);
+ IO.mapRequired("BytesOfCalleeSavedRegisters",
+ Symbol.BytesOfCalleeSavedRegisters);
+ IO.mapRequired("OffsetOfExceptionHandler", Symbol.OffsetOfExceptionHandler);
+ IO.mapRequired("SectionIdOfExceptionHandler",
+ Symbol.SectionIdOfExceptionHandler);
+ IO.mapRequired("Flags", Symbol.Flags);
+}
+
+template <> void SymbolRecordImpl<CallSiteInfoSym>::map(IO &IO) {
+ // TODO: Map Linkage Name
+ IO.mapRequired("Segment", Symbol.Segment);
+ IO.mapRequired("Type", Symbol.Type);
+}
+
+template <> void SymbolRecordImpl<FileStaticSym>::map(IO &IO) {
+ IO.mapRequired("Index", Symbol.Index);
+ IO.mapRequired("ModFilenameOffset", Symbol.ModFilenameOffset);
+ IO.mapRequired("Flags", Symbol.Flags);
+ IO.mapRequired("Name", Symbol.Name);
+}
+
+template <> void SymbolRecordImpl<HeapAllocationSiteSym>::map(IO &IO) {
+ // TODO: Map Linkage Name
+ IO.mapRequired("Segment", Symbol.Segment);
+ IO.mapRequired("CallInstructionSize", Symbol.CallInstructionSize);
+ IO.mapRequired("Type", Symbol.Type);
+}
+
+template <> void SymbolRecordImpl<FrameCookieSym>::map(IO &IO) {
+ // TODO: Map Linkage Name
+ IO.mapRequired("Register", Symbol.Register);
+ IO.mapRequired("CookieKind", Symbol.CookieKind);
+ IO.mapRequired("Flags", Symbol.Flags);
+}
+
+template <> void SymbolRecordImpl<CallerSym>::map(IO &IO) {
+ IO.mapRequired("FuncID", Symbol.Indices);
+}
+
+template <> void SymbolRecordImpl<UDTSym>::map(IO &IO) {
+ IO.mapRequired("Type", Symbol.Type);
+ IO.mapRequired("UDTName", Symbol.Name);
+}
+
+template <> void SymbolRecordImpl<BuildInfoSym>::map(IO &IO) {
+ IO.mapRequired("BuildId", Symbol.BuildId);
+}
+
+template <> void SymbolRecordImpl<BPRelativeSym>::map(IO &IO) {
+ IO.mapRequired("Offset", Symbol.Offset);
+ IO.mapRequired("Type", Symbol.Type);
+ IO.mapRequired("VarName", Symbol.Name);
+}
+
+template <> void SymbolRecordImpl<RegRelativeSym>::map(IO &IO) {
+ IO.mapRequired("Offset", Symbol.Offset);
+ IO.mapRequired("Type", Symbol.Type);
+ IO.mapRequired("Register", Symbol.Register);
+ IO.mapRequired("VarName", Symbol.Name);
+}
+
+template <> void SymbolRecordImpl<ConstantSym>::map(IO &IO) {
+ IO.mapRequired("Type", Symbol.Type);
+ IO.mapRequired("Value", Symbol.Value);
+ IO.mapRequired("Name", Symbol.Name);
+}
+
+template <> void SymbolRecordImpl<DataSym>::map(IO &IO) {
+ // TODO: Map linkage name
+ IO.mapRequired("Type", Symbol.Type);
+ IO.mapRequired("DisplayName", Symbol.Name);
+}
+
+template <> void SymbolRecordImpl<ThreadLocalDataSym>::map(IO &IO) {
+ // TODO: Map linkage name
+ IO.mapRequired("Type", Symbol.Type);
+ IO.mapRequired("DisplayName", Symbol.Name);
+}
+}
+}
+}
+
+CVSymbol CodeViewYAML::SymbolRecord::toCodeViewSymbol(
+ BumpPtrAllocator &Allocator) const {
+ return Symbol->toCodeViewSymbol(Allocator);
+}
+
+namespace llvm {
+namespace yaml {
+template <> struct MappingTraits<SymbolRecordBase> {
+ static void mapping(IO &io, SymbolRecordBase &Record) { Record.map(io); }
+};
+}
+}
+
+template <typename SymbolType>
+static inline Expected<CodeViewYAML::SymbolRecord>
+fromCodeViewSymbolImpl(CVSymbol Symbol) {
+ CodeViewYAML::SymbolRecord Result;
+
+ auto Impl = std::make_shared<SymbolRecordImpl<SymbolType>>(Symbol.kind());
+ if (auto EC = Impl->fromCodeViewSymbol(Symbol))
+ return std::move(EC);
+ Result.Symbol = Impl;
+ return Result;
+}
+
+Expected<CodeViewYAML::SymbolRecord>
+CodeViewYAML::SymbolRecord::fromCodeViewSymbol(CVSymbol Symbol) {
+#define SYMBOL_RECORD(EnumName, EnumVal, ClassName) \
+ case EnumName: \
+ return fromCodeViewSymbolImpl<ClassName>(Symbol);
+#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \
+ SYMBOL_RECORD(EnumName, EnumVal, ClassName)
+ switch (Symbol.kind()) {
+#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
+ default: { llvm_unreachable("Unknown symbol kind!"); }
+ }
+ return make_error<CodeViewError>(cv_error_code::corrupt_record);
+}
+
+template <typename ConcreteType>
+static void mapSymbolRecordImpl(IO &IO, const char *Class, SymbolKind Kind,
+ CodeViewYAML::SymbolRecord &Obj) {
+ if (!IO.outputting())
+ Obj.Symbol = std::make_shared<SymbolRecordImpl<ConcreteType>>(Kind);
+
+ IO.mapRequired(Class, *Obj.Symbol);
+}
+
+void MappingTraits<CodeViewYAML::SymbolRecord>::mapping(
+ IO &IO, CodeViewYAML::SymbolRecord &Obj) {
+ SymbolKind Kind;
+ if (IO.outputting())
+ Kind = Obj.Symbol->Kind;
+ IO.mapRequired("Kind", Kind);
+
+#define SYMBOL_RECORD(EnumName, EnumVal, ClassName) \
+ case EnumName: \
+ mapSymbolRecordImpl<ClassName>(IO, #ClassName, Kind, Obj); \
+ break;
+#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \
+ SYMBOL_RECORD(EnumName, EnumVal, ClassName)
+ switch (Kind) {
+#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
+ default: { llvm_unreachable("Unknown symbol kind!"); }
+ }
+}
diff --git a/lib/ObjectYAML/CodeViewYAMLTypes.cpp b/lib/ObjectYAML/CodeViewYAMLTypes.cpp
new file mode 100644
index 000000000000..4e82a299a672
--- /dev/null
+++ b/lib/ObjectYAML/CodeViewYAMLTypes.cpp
@@ -0,0 +1,712 @@
+//===- CodeViewYAMLTypes.cpp - CodeView YAMLIO types implementation -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines classes for handling the YAML representation of CodeView
+// Debug Info.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ObjectYAML/CodeViewYAMLTypes.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/EnumTables.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::CodeViewYAML;
+using namespace llvm::CodeViewYAML::detail;
+using namespace llvm::yaml;
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(OneMethodRecord)
+LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef)
+LLVM_YAML_IS_SEQUENCE_VECTOR(VFTableSlotKind)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(TypeIndex)
+
+LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeIndex, false)
+LLVM_YAML_DECLARE_SCALAR_TRAITS(APSInt, false)
+
+LLVM_YAML_DECLARE_ENUM_TRAITS(TypeLeafKind)
+LLVM_YAML_DECLARE_ENUM_TRAITS(PointerToMemberRepresentation)
+LLVM_YAML_DECLARE_ENUM_TRAITS(VFTableSlotKind)
+LLVM_YAML_DECLARE_ENUM_TRAITS(CallingConvention)
+LLVM_YAML_DECLARE_ENUM_TRAITS(PointerKind)
+LLVM_YAML_DECLARE_ENUM_TRAITS(PointerMode)
+LLVM_YAML_DECLARE_ENUM_TRAITS(HfaKind)
+LLVM_YAML_DECLARE_ENUM_TRAITS(MemberAccess)
+LLVM_YAML_DECLARE_ENUM_TRAITS(MethodKind)
+LLVM_YAML_DECLARE_ENUM_TRAITS(WindowsRTClassKind)
+LLVM_YAML_DECLARE_ENUM_TRAITS(LabelType)
+
+LLVM_YAML_DECLARE_BITSET_TRAITS(PointerOptions)
+LLVM_YAML_DECLARE_BITSET_TRAITS(ModifierOptions)
+LLVM_YAML_DECLARE_BITSET_TRAITS(FunctionOptions)
+LLVM_YAML_DECLARE_BITSET_TRAITS(ClassOptions)
+LLVM_YAML_DECLARE_BITSET_TRAITS(MethodOptions)
+
+LLVM_YAML_DECLARE_MAPPING_TRAITS(OneMethodRecord)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(MemberPointerInfo)
+
+namespace llvm {
+namespace CodeViewYAML {
+namespace detail {
+
+struct LeafRecordBase {
+ TypeLeafKind Kind;
+ explicit LeafRecordBase(TypeLeafKind K) : Kind(K) {}
+
+ virtual ~LeafRecordBase() {}
+ virtual void map(yaml::IO &io) = 0;
+ virtual CVType toCodeViewRecord(BumpPtrAllocator &Allocator) const = 0;
+ virtual Error fromCodeViewRecord(CVType Type) = 0;
+};
+
+template <typename T> struct LeafRecordImpl : public LeafRecordBase {
+ explicit LeafRecordImpl(TypeLeafKind K)
+ : LeafRecordBase(K), Record(static_cast<TypeRecordKind>(K)) {}
+
+ void map(yaml::IO &io) override;
+
+ Error fromCodeViewRecord(CVType Type) override {
+ return TypeDeserializer::deserializeAs<T>(Type, Record);
+ }
+
+ CVType toCodeViewRecord(BumpPtrAllocator &Allocator) const override {
+ TypeTableBuilder Table(Allocator);
+ Table.writeKnownType(Record);
+ return CVType(Kind, Table.records().front());
+ }
+
+ mutable T Record;
+};
+
+template <> struct LeafRecordImpl<FieldListRecord> : public LeafRecordBase {
+ explicit LeafRecordImpl(TypeLeafKind K) : LeafRecordBase(K) {}
+
+ void map(yaml::IO &io) override;
+ CVType toCodeViewRecord(BumpPtrAllocator &Allocator) const override;
+ Error fromCodeViewRecord(CVType Type) override;
+
+ std::vector<MemberRecord> Members;
+};
+
+struct MemberRecordBase {
+ TypeLeafKind Kind;
+ explicit MemberRecordBase(TypeLeafKind K) : Kind(K) {}
+
+ virtual ~MemberRecordBase() {}
+ virtual void map(yaml::IO &io) = 0;
+ virtual void writeTo(FieldListRecordBuilder &FLRB) = 0;
+};
+
+template <typename T> struct MemberRecordImpl : public MemberRecordBase {
+ explicit MemberRecordImpl(TypeLeafKind K)
+ : MemberRecordBase(K), Record(static_cast<TypeRecordKind>(K)) {}
+ void map(yaml::IO &io) override;
+
+ void writeTo(FieldListRecordBuilder &FLRB) override {
+ FLRB.writeMemberType(Record);
+ }
+
+ mutable T Record;
+};
+}
+}
+}
+
+void ScalarTraits<TypeIndex>::output(const TypeIndex &S, void *,
+ llvm::raw_ostream &OS) {
+ OS << S.getIndex();
+}
+
+StringRef ScalarTraits<TypeIndex>::input(StringRef Scalar, void *Ctx,
+ TypeIndex &S) {
+ uint32_t I;
+ StringRef Result = ScalarTraits<uint32_t>::input(Scalar, Ctx, I);
+ S.setIndex(I);
+ return Result;
+}
+
+void ScalarTraits<APSInt>::output(const APSInt &S, void *,
+ llvm::raw_ostream &OS) {
+ S.print(OS, true);
+}
+
+StringRef ScalarTraits<APSInt>::input(StringRef Scalar, void *Ctx, APSInt &S) {
+ S = APSInt(Scalar);
+ return "";
+}
+
+void ScalarEnumerationTraits<TypeLeafKind>::enumeration(IO &io,
+ TypeLeafKind &Value) {
+#define CV_TYPE(name, val) io.enumCase(Value, #name, name);
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
+#undef CV_TYPE
+}
+
+void ScalarEnumerationTraits<PointerToMemberRepresentation>::enumeration(
+ IO &IO, PointerToMemberRepresentation &Value) {
+ IO.enumCase(Value, "Unknown", PointerToMemberRepresentation::Unknown);
+ IO.enumCase(Value, "SingleInheritanceData",
+ PointerToMemberRepresentation::SingleInheritanceData);
+ IO.enumCase(Value, "MultipleInheritanceData",
+ PointerToMemberRepresentation::MultipleInheritanceData);
+ IO.enumCase(Value, "VirtualInheritanceData",
+ PointerToMemberRepresentation::VirtualInheritanceData);
+ IO.enumCase(Value, "GeneralData", PointerToMemberRepresentation::GeneralData);
+ IO.enumCase(Value, "SingleInheritanceFunction",
+ PointerToMemberRepresentation::SingleInheritanceFunction);
+ IO.enumCase(Value, "MultipleInheritanceFunction",
+ PointerToMemberRepresentation::MultipleInheritanceFunction);
+ IO.enumCase(Value, "VirtualInheritanceFunction",
+ PointerToMemberRepresentation::VirtualInheritanceFunction);
+ IO.enumCase(Value, "GeneralFunction",
+ PointerToMemberRepresentation::GeneralFunction);
+}
+
+void ScalarEnumerationTraits<VFTableSlotKind>::enumeration(
+ IO &IO, VFTableSlotKind &Kind) {
+ IO.enumCase(Kind, "Near16", VFTableSlotKind::Near16);
+ IO.enumCase(Kind, "Far16", VFTableSlotKind::Far16);
+ IO.enumCase(Kind, "This", VFTableSlotKind::This);
+ IO.enumCase(Kind, "Outer", VFTableSlotKind::Outer);
+ IO.enumCase(Kind, "Meta", VFTableSlotKind::Meta);
+ IO.enumCase(Kind, "Near", VFTableSlotKind::Near);
+ IO.enumCase(Kind, "Far", VFTableSlotKind::Far);
+}
+
+void ScalarEnumerationTraits<CallingConvention>::enumeration(
+ IO &IO, CallingConvention &Value) {
+ IO.enumCase(Value, "NearC", CallingConvention::NearC);
+ IO.enumCase(Value, "FarC", CallingConvention::FarC);
+ IO.enumCase(Value, "NearPascal", CallingConvention::NearPascal);
+ IO.enumCase(Value, "FarPascal", CallingConvention::FarPascal);
+ IO.enumCase(Value, "NearFast", CallingConvention::NearFast);
+ IO.enumCase(Value, "FarFast", CallingConvention::FarFast);
+ IO.enumCase(Value, "NearStdCall", CallingConvention::NearStdCall);
+ IO.enumCase(Value, "FarStdCall", CallingConvention::FarStdCall);
+ IO.enumCase(Value, "NearSysCall", CallingConvention::NearSysCall);
+ IO.enumCase(Value, "FarSysCall", CallingConvention::FarSysCall);
+ IO.enumCase(Value, "ThisCall", CallingConvention::ThisCall);
+ IO.enumCase(Value, "MipsCall", CallingConvention::MipsCall);
+ IO.enumCase(Value, "Generic", CallingConvention::Generic);
+ IO.enumCase(Value, "AlphaCall", CallingConvention::AlphaCall);
+ IO.enumCase(Value, "PpcCall", CallingConvention::PpcCall);
+ IO.enumCase(Value, "SHCall", CallingConvention::SHCall);
+ IO.enumCase(Value, "ArmCall", CallingConvention::ArmCall);
+ IO.enumCase(Value, "AM33Call", CallingConvention::AM33Call);
+ IO.enumCase(Value, "TriCall", CallingConvention::TriCall);
+ IO.enumCase(Value, "SH5Call", CallingConvention::SH5Call);
+ IO.enumCase(Value, "M32RCall", CallingConvention::M32RCall);
+ IO.enumCase(Value, "ClrCall", CallingConvention::ClrCall);
+ IO.enumCase(Value, "Inline", CallingConvention::Inline);
+ IO.enumCase(Value, "NearVector", CallingConvention::NearVector);
+}
+
+void ScalarEnumerationTraits<PointerKind>::enumeration(IO &IO,
+ PointerKind &Kind) {
+ IO.enumCase(Kind, "Near16", PointerKind::Near16);
+ IO.enumCase(Kind, "Far16", PointerKind::Far16);
+ IO.enumCase(Kind, "Huge16", PointerKind::Huge16);
+ IO.enumCase(Kind, "BasedOnSegment", PointerKind::BasedOnSegment);
+ IO.enumCase(Kind, "BasedOnValue", PointerKind::BasedOnValue);
+ IO.enumCase(Kind, "BasedOnSegmentValue", PointerKind::BasedOnSegmentValue);
+ IO.enumCase(Kind, "BasedOnAddress", PointerKind::BasedOnAddress);
+ IO.enumCase(Kind, "BasedOnSegmentAddress",
+ PointerKind::BasedOnSegmentAddress);
+ IO.enumCase(Kind, "BasedOnType", PointerKind::BasedOnType);
+ IO.enumCase(Kind, "BasedOnSelf", PointerKind::BasedOnSelf);
+ IO.enumCase(Kind, "Near32", PointerKind::Near32);
+ IO.enumCase(Kind, "Far32", PointerKind::Far32);
+ IO.enumCase(Kind, "Near64", PointerKind::Near64);
+}
+
+void ScalarEnumerationTraits<PointerMode>::enumeration(IO &IO,
+ PointerMode &Mode) {
+ IO.enumCase(Mode, "Pointer", PointerMode::Pointer);
+ IO.enumCase(Mode, "LValueReference", PointerMode::LValueReference);
+ IO.enumCase(Mode, "PointerToDataMember", PointerMode::PointerToDataMember);
+ IO.enumCase(Mode, "PointerToMemberFunction",
+ PointerMode::PointerToMemberFunction);
+ IO.enumCase(Mode, "RValueReference", PointerMode::RValueReference);
+}
+
+void ScalarEnumerationTraits<HfaKind>::enumeration(IO &IO, HfaKind &Value) {
+ IO.enumCase(Value, "None", HfaKind::None);
+ IO.enumCase(Value, "Float", HfaKind::Float);
+ IO.enumCase(Value, "Double", HfaKind::Double);
+ IO.enumCase(Value, "Other", HfaKind::Other);
+}
+
+void ScalarEnumerationTraits<MemberAccess>::enumeration(IO &IO,
+ MemberAccess &Access) {
+ IO.enumCase(Access, "None", MemberAccess::None);
+ IO.enumCase(Access, "Private", MemberAccess::Private);
+ IO.enumCase(Access, "Protected", MemberAccess::Protected);
+ IO.enumCase(Access, "Public", MemberAccess::Public);
+}
+
+void ScalarEnumerationTraits<MethodKind>::enumeration(IO &IO,
+ MethodKind &Kind) {
+ IO.enumCase(Kind, "Vanilla", MethodKind::Vanilla);
+ IO.enumCase(Kind, "Virtual", MethodKind::Virtual);
+ IO.enumCase(Kind, "Static", MethodKind::Static);
+ IO.enumCase(Kind, "Friend", MethodKind::Friend);
+ IO.enumCase(Kind, "IntroducingVirtual", MethodKind::IntroducingVirtual);
+ IO.enumCase(Kind, "PureVirtual", MethodKind::PureVirtual);
+ IO.enumCase(Kind, "PureIntroducingVirtual",
+ MethodKind::PureIntroducingVirtual);
+}
+
+void ScalarEnumerationTraits<WindowsRTClassKind>::enumeration(
+ IO &IO, WindowsRTClassKind &Value) {
+ IO.enumCase(Value, "None", WindowsRTClassKind::None);
+ IO.enumCase(Value, "Ref", WindowsRTClassKind::RefClass);
+ IO.enumCase(Value, "Value", WindowsRTClassKind::ValueClass);
+ IO.enumCase(Value, "Interface", WindowsRTClassKind::Interface);
+}
+
+void ScalarEnumerationTraits<LabelType>::enumeration(IO &IO, LabelType &Value) {
+ IO.enumCase(Value, "Near", LabelType::Near);
+ IO.enumCase(Value, "Far", LabelType::Far);
+}
+
+void ScalarBitSetTraits<PointerOptions>::bitset(IO &IO,
+ PointerOptions &Options) {
+ IO.bitSetCase(Options, "None", PointerOptions::None);
+ IO.bitSetCase(Options, "Flat32", PointerOptions::Flat32);
+ IO.bitSetCase(Options, "Volatile", PointerOptions::Volatile);
+ IO.bitSetCase(Options, "Const", PointerOptions::Const);
+ IO.bitSetCase(Options, "Unaligned", PointerOptions::Unaligned);
+ IO.bitSetCase(Options, "Restrict", PointerOptions::Restrict);
+ IO.bitSetCase(Options, "WinRTSmartPointer",
+ PointerOptions::WinRTSmartPointer);
+}
+
+void ScalarBitSetTraits<ModifierOptions>::bitset(IO &IO,
+ ModifierOptions &Options) {
+ IO.bitSetCase(Options, "None", ModifierOptions::None);
+ IO.bitSetCase(Options, "Const", ModifierOptions::Const);
+ IO.bitSetCase(Options, "Volatile", ModifierOptions::Volatile);
+ IO.bitSetCase(Options, "Unaligned", ModifierOptions::Unaligned);
+}
+
+void ScalarBitSetTraits<FunctionOptions>::bitset(IO &IO,
+ FunctionOptions &Options) {
+ IO.bitSetCase(Options, "None", FunctionOptions::None);
+ IO.bitSetCase(Options, "CxxReturnUdt", FunctionOptions::CxxReturnUdt);
+ IO.bitSetCase(Options, "Constructor", FunctionOptions::Constructor);
+ IO.bitSetCase(Options, "ConstructorWithVirtualBases",
+ FunctionOptions::ConstructorWithVirtualBases);
+}
+
+void ScalarBitSetTraits<ClassOptions>::bitset(IO &IO, ClassOptions &Options) {
+ IO.bitSetCase(Options, "None", ClassOptions::None);
+ IO.bitSetCase(Options, "HasConstructorOrDestructor",
+ ClassOptions::HasConstructorOrDestructor);
+ IO.bitSetCase(Options, "HasOverloadedOperator",
+ ClassOptions::HasOverloadedOperator);
+ IO.bitSetCase(Options, "Nested", ClassOptions::Nested);
+ IO.bitSetCase(Options, "ContainsNestedClass",
+ ClassOptions::ContainsNestedClass);
+ IO.bitSetCase(Options, "HasOverloadedAssignmentOperator",
+ ClassOptions::HasOverloadedAssignmentOperator);
+ IO.bitSetCase(Options, "HasConversionOperator",
+ ClassOptions::HasConversionOperator);
+ IO.bitSetCase(Options, "ForwardReference", ClassOptions::ForwardReference);
+ IO.bitSetCase(Options, "Scoped", ClassOptions::Scoped);
+ IO.bitSetCase(Options, "HasUniqueName", ClassOptions::HasUniqueName);
+ IO.bitSetCase(Options, "Sealed", ClassOptions::Sealed);
+ IO.bitSetCase(Options, "Intrinsic", ClassOptions::Intrinsic);
+}
+
+void ScalarBitSetTraits<MethodOptions>::bitset(IO &IO, MethodOptions &Options) {
+ IO.bitSetCase(Options, "None", MethodOptions::None);
+ IO.bitSetCase(Options, "Pseudo", MethodOptions::Pseudo);
+ IO.bitSetCase(Options, "NoInherit", MethodOptions::NoInherit);
+ IO.bitSetCase(Options, "NoConstruct", MethodOptions::NoConstruct);
+ IO.bitSetCase(Options, "CompilerGenerated", MethodOptions::CompilerGenerated);
+ IO.bitSetCase(Options, "Sealed", MethodOptions::Sealed);
+}
+
+void MappingTraits<MemberPointerInfo>::mapping(IO &IO, MemberPointerInfo &MPI) {
+ IO.mapRequired("ContainingType", MPI.ContainingType);
+ IO.mapRequired("Representation", MPI.Representation);
+}
+
+namespace llvm {
+namespace CodeViewYAML {
+namespace detail {
+template <> void LeafRecordImpl<ModifierRecord>::map(IO &IO) {
+ IO.mapRequired("ModifiedType", Record.ModifiedType);
+ IO.mapRequired("Modifiers", Record.Modifiers);
+}
+
+template <> void LeafRecordImpl<ProcedureRecord>::map(IO &IO) {
+ IO.mapRequired("ReturnType", Record.ReturnType);
+ IO.mapRequired("CallConv", Record.CallConv);
+ IO.mapRequired("Options", Record.Options);
+ IO.mapRequired("ParameterCount", Record.ParameterCount);
+ IO.mapRequired("ArgumentList", Record.ArgumentList);
+}
+
+template <> void LeafRecordImpl<MemberFunctionRecord>::map(IO &IO) {
+ IO.mapRequired("ReturnType", Record.ReturnType);
+ IO.mapRequired("ClassType", Record.ClassType);
+ IO.mapRequired("ThisType", Record.ThisType);
+ IO.mapRequired("CallConv", Record.CallConv);
+ IO.mapRequired("Options", Record.Options);
+ IO.mapRequired("ParameterCount", Record.ParameterCount);
+ IO.mapRequired("ArgumentList", Record.ArgumentList);
+ IO.mapRequired("ThisPointerAdjustment", Record.ThisPointerAdjustment);
+}
+
+template <> void LeafRecordImpl<LabelRecord>::map(IO &IO) {
+ IO.mapRequired("Mode", Record.Mode);
+}
+
+template <> void LeafRecordImpl<MemberFuncIdRecord>::map(IO &IO) {
+ IO.mapRequired("ClassType", Record.ClassType);
+ IO.mapRequired("FunctionType", Record.FunctionType);
+ IO.mapRequired("Name", Record.Name);
+}
+
+template <> void LeafRecordImpl<ArgListRecord>::map(IO &IO) {
+ IO.mapRequired("ArgIndices", Record.ArgIndices);
+}
+
+template <> void LeafRecordImpl<StringListRecord>::map(IO &IO) {
+ IO.mapRequired("StringIndices", Record.StringIndices);
+}
+
+template <> void LeafRecordImpl<PointerRecord>::map(IO &IO) {
+ IO.mapRequired("ReferentType", Record.ReferentType);
+ IO.mapRequired("Attrs", Record.Attrs);
+ IO.mapOptional("MemberInfo", Record.MemberInfo);
+}
+
+template <> void LeafRecordImpl<ArrayRecord>::map(IO &IO) {
+ IO.mapRequired("ElementType", Record.ElementType);
+ IO.mapRequired("IndexType", Record.IndexType);
+ IO.mapRequired("Size", Record.Size);
+ IO.mapRequired("Name", Record.Name);
+}
+
+void LeafRecordImpl<FieldListRecord>::map(IO &IO) {
+ IO.mapRequired("FieldList", Members);
+}
+}
+}
+}
+
+namespace {
+class MemberRecordConversionVisitor : public TypeVisitorCallbacks {
+public:
+ explicit MemberRecordConversionVisitor(std::vector<MemberRecord> &Records)
+ : Records(Records) {}
+
+#define TYPE_RECORD(EnumName, EnumVal, Name)
+#define MEMBER_RECORD(EnumName, EnumVal, Name) \
+ Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
+ return visitKnownMemberImpl(Record); \
+ }
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
+private:
+ template <typename T> Error visitKnownMemberImpl(T &Record) {
+ TypeLeafKind K = static_cast<TypeLeafKind>(Record.getKind());
+ auto Impl = std::make_shared<MemberRecordImpl<T>>(K);
+ Impl->Record = Record;
+ Records.push_back(MemberRecord{Impl});
+ return Error::success();
+ }
+
+ std::vector<MemberRecord> &Records;
+};
+}
+
+Error LeafRecordImpl<FieldListRecord>::fromCodeViewRecord(CVType Type) {
+ MemberRecordConversionVisitor V(Members);
+ return visitMemberRecordStream(Type.content(), V);
+}
+
+CVType LeafRecordImpl<FieldListRecord>::toCodeViewRecord(
+ BumpPtrAllocator &Allocator) const {
+ TypeTableBuilder TTB(Allocator);
+ FieldListRecordBuilder FLRB(TTB);
+ FLRB.begin();
+ for (const auto &Member : Members) {
+ Member.Member->writeTo(FLRB);
+ }
+ FLRB.end(true);
+ return CVType(Kind, TTB.records().front());
+}
+
+void MappingTraits<OneMethodRecord>::mapping(IO &io, OneMethodRecord &Record) {
+ io.mapRequired("Type", Record.Type);
+ io.mapRequired("Attrs", Record.Attrs.Attrs);
+ io.mapRequired("VFTableOffset", Record.VFTableOffset);
+ io.mapRequired("Name", Record.Name);
+}
+
+namespace llvm {
+namespace CodeViewYAML {
+namespace detail {
+template <> void LeafRecordImpl<ClassRecord>::map(IO &IO) {
+ IO.mapRequired("MemberCount", Record.MemberCount);
+ IO.mapRequired("Options", Record.Options);
+ IO.mapRequired("FieldList", Record.FieldList);
+ IO.mapRequired("Name", Record.Name);
+ IO.mapRequired("UniqueName", Record.UniqueName);
+
+ IO.mapRequired("DerivationList", Record.DerivationList);
+ IO.mapRequired("VTableShape", Record.VTableShape);
+ IO.mapRequired("Size", Record.Size);
+}
+
+template <> void LeafRecordImpl<UnionRecord>::map(IO &IO) {
+ IO.mapRequired("MemberCount", Record.MemberCount);
+ IO.mapRequired("Options", Record.Options);
+ IO.mapRequired("FieldList", Record.FieldList);
+ IO.mapRequired("Name", Record.Name);
+ IO.mapRequired("UniqueName", Record.UniqueName);
+
+ IO.mapRequired("Size", Record.Size);
+}
+
+template <> void LeafRecordImpl<EnumRecord>::map(IO &IO) {
+ IO.mapRequired("NumEnumerators", Record.MemberCount);
+ IO.mapRequired("Options", Record.Options);
+ IO.mapRequired("FieldList", Record.FieldList);
+ IO.mapRequired("Name", Record.Name);
+ IO.mapRequired("UniqueName", Record.UniqueName);
+
+ IO.mapRequired("UnderlyingType", Record.UnderlyingType);
+}
+
+template <> void LeafRecordImpl<BitFieldRecord>::map(IO &IO) {
+ IO.mapRequired("Type", Record.Type);
+ IO.mapRequired("BitSize", Record.BitSize);
+ IO.mapRequired("BitOffset", Record.BitOffset);
+}
+
+template <> void LeafRecordImpl<VFTableShapeRecord>::map(IO &IO) {
+ IO.mapRequired("Slots", Record.Slots);
+}
+
+template <> void LeafRecordImpl<TypeServer2Record>::map(IO &IO) {
+ IO.mapRequired("Guid", Record.Guid);
+ IO.mapRequired("Age", Record.Age);
+ IO.mapRequired("Name", Record.Name);
+}
+
+template <> void LeafRecordImpl<StringIdRecord>::map(IO &IO) {
+ IO.mapRequired("Id", Record.Id);
+ IO.mapRequired("String", Record.String);
+}
+
+template <> void LeafRecordImpl<FuncIdRecord>::map(IO &IO) {
+ IO.mapRequired("ParentScope", Record.ParentScope);
+ IO.mapRequired("FunctionType", Record.FunctionType);
+ IO.mapRequired("Name", Record.Name);
+}
+
+template <> void LeafRecordImpl<UdtSourceLineRecord>::map(IO &IO) {
+ IO.mapRequired("UDT", Record.UDT);
+ IO.mapRequired("SourceFile", Record.SourceFile);
+ IO.mapRequired("LineNumber", Record.LineNumber);
+}
+
+template <> void LeafRecordImpl<UdtModSourceLineRecord>::map(IO &IO) {
+ IO.mapRequired("UDT", Record.UDT);
+ IO.mapRequired("SourceFile", Record.SourceFile);
+ IO.mapRequired("LineNumber", Record.LineNumber);
+ IO.mapRequired("Module", Record.Module);
+}
+
+template <> void LeafRecordImpl<BuildInfoRecord>::map(IO &IO) {
+ IO.mapRequired("ArgIndices", Record.ArgIndices);
+}
+
+template <> void LeafRecordImpl<VFTableRecord>::map(IO &IO) {
+ IO.mapRequired("CompleteClass", Record.CompleteClass);
+ IO.mapRequired("OverriddenVFTable", Record.OverriddenVFTable);
+ IO.mapRequired("VFPtrOffset", Record.VFPtrOffset);
+ IO.mapRequired("MethodNames", Record.MethodNames);
+}
+
+template <> void LeafRecordImpl<MethodOverloadListRecord>::map(IO &IO) {
+ IO.mapRequired("Methods", Record.Methods);
+}
+
+template <> void MemberRecordImpl<OneMethodRecord>::map(IO &IO) {
+ MappingTraits<OneMethodRecord>::mapping(IO, Record);
+}
+
+template <> void MemberRecordImpl<OverloadedMethodRecord>::map(IO &IO) {
+ IO.mapRequired("NumOverloads", Record.NumOverloads);
+ IO.mapRequired("MethodList", Record.MethodList);
+ IO.mapRequired("Name", Record.Name);
+}
+
+template <> void MemberRecordImpl<NestedTypeRecord>::map(IO &IO) {
+ IO.mapRequired("Type", Record.Type);
+ IO.mapRequired("Name", Record.Name);
+}
+
+template <> void MemberRecordImpl<DataMemberRecord>::map(IO &IO) {
+ IO.mapRequired("Attrs", Record.Attrs.Attrs);
+ IO.mapRequired("Type", Record.Type);
+ IO.mapRequired("FieldOffset", Record.FieldOffset);
+ IO.mapRequired("Name", Record.Name);
+}
+
+template <> void MemberRecordImpl<StaticDataMemberRecord>::map(IO &IO) {
+ IO.mapRequired("Attrs", Record.Attrs.Attrs);
+ IO.mapRequired("Type", Record.Type);
+ IO.mapRequired("Name", Record.Name);
+}
+
+template <> void MemberRecordImpl<EnumeratorRecord>::map(IO &IO) {
+ IO.mapRequired("Attrs", Record.Attrs.Attrs);
+ IO.mapRequired("Value", Record.Value);
+ IO.mapRequired("Name", Record.Name);
+}
+
+template <> void MemberRecordImpl<VFPtrRecord>::map(IO &IO) {
+ IO.mapRequired("Type", Record.Type);
+}
+
+template <> void MemberRecordImpl<BaseClassRecord>::map(IO &IO) {
+ IO.mapRequired("Attrs", Record.Attrs.Attrs);
+ IO.mapRequired("Type", Record.Type);
+ IO.mapRequired("Offset", Record.Offset);
+}
+
+template <> void MemberRecordImpl<VirtualBaseClassRecord>::map(IO &IO) {
+ IO.mapRequired("Attrs", Record.Attrs.Attrs);
+ IO.mapRequired("BaseType", Record.BaseType);
+ IO.mapRequired("VBPtrType", Record.VBPtrType);
+ IO.mapRequired("VBPtrOffset", Record.VBPtrOffset);
+ IO.mapRequired("VTableIndex", Record.VTableIndex);
+}
+
+template <> void MemberRecordImpl<ListContinuationRecord>::map(IO &IO) {
+ IO.mapRequired("ContinuationIndex", Record.ContinuationIndex);
+}
+}
+}
+}
+
+template <typename T>
+static inline Expected<LeafRecord> fromCodeViewRecordImpl(CVType Type) {
+ LeafRecord Result;
+
+ auto Impl = std::make_shared<LeafRecordImpl<T>>(Type.kind());
+ if (auto EC = Impl->fromCodeViewRecord(Type))
+ return std::move(EC);
+ Result.Leaf = Impl;
+ return Result;
+}
+
+Expected<LeafRecord> LeafRecord::fromCodeViewRecord(CVType Type) {
+#define TYPE_RECORD(EnumName, EnumVal, ClassName) \
+ case EnumName: \
+ return fromCodeViewRecordImpl<ClassName##Record>(Type);
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \
+ TYPE_RECORD(EnumName, EnumVal, ClassName)
+#define MEMBER_RECORD(EnumName, EnumVal, ClassName)
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)
+ switch (Type.kind()) {
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
+ default: { llvm_unreachable("Unknown leaf kind!"); }
+ }
+ return make_error<CodeViewError>(cv_error_code::corrupt_record);
+}
+
+CVType LeafRecord::toCodeViewRecord(BumpPtrAllocator &Allocator) const {
+ return Leaf->toCodeViewRecord(Allocator);
+}
+
+namespace llvm {
+namespace yaml {
+template <> struct MappingTraits<LeafRecordBase> {
+ static void mapping(IO &io, LeafRecordBase &Record) { Record.map(io); }
+};
+
+template <> struct MappingTraits<MemberRecordBase> {
+ static void mapping(IO &io, MemberRecordBase &Record) { Record.map(io); }
+};
+}
+}
+
+template <typename ConcreteType>
+static void mapLeafRecordImpl(IO &IO, const char *Class, TypeLeafKind Kind,
+ LeafRecord &Obj) {
+ if (!IO.outputting())
+ Obj.Leaf = std::make_shared<LeafRecordImpl<ConcreteType>>(Kind);
+
+ if (Kind == LF_FIELDLIST)
+ Obj.Leaf->map(IO);
+ else
+ IO.mapRequired(Class, *Obj.Leaf);
+}
+
+void MappingTraits<LeafRecord>::mapping(IO &IO, LeafRecord &Obj) {
+ TypeLeafKind Kind;
+ if (IO.outputting())
+ Kind = Obj.Leaf->Kind;
+ IO.mapRequired("Kind", Kind);
+
+#define TYPE_RECORD(EnumName, EnumVal, ClassName) \
+ case EnumName: \
+ mapLeafRecordImpl<ClassName##Record>(IO, #ClassName, Kind, Obj); \
+ break;
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \
+ TYPE_RECORD(EnumName, EnumVal, ClassName)
+#define MEMBER_RECORD(EnumName, EnumVal, ClassName)
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)
+ switch (Kind) {
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
+ default: { llvm_unreachable("Unknown leaf kind!"); }
+ }
+}
+
+template <typename ConcreteType>
+static void mapMemberRecordImpl(IO &IO, const char *Class, TypeLeafKind Kind,
+ MemberRecord &Obj) {
+ if (!IO.outputting())
+ Obj.Member = std::make_shared<MemberRecordImpl<ConcreteType>>(Kind);
+
+ IO.mapRequired(Class, *Obj.Member);
+}
+
+void MappingTraits<MemberRecord>::mapping(IO &IO, MemberRecord &Obj) {
+ TypeLeafKind Kind;
+ if (IO.outputting())
+ Kind = Obj.Member->Kind;
+ IO.mapRequired("Kind", Kind);
+
+#define MEMBER_RECORD(EnumName, EnumVal, ClassName) \
+ case EnumName: \
+ mapMemberRecordImpl<ClassName##Record>(IO, #ClassName, Kind, Obj); \
+ break;
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \
+ MEMBER_RECORD(EnumName, EnumVal, ClassName)
+#define TYPE_RECORD(EnumName, EnumVal, ClassName)
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)
+ switch (Kind) {
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
+ default: { llvm_unreachable("Unknown member kind!"); }
+ }
+}
diff --git a/lib/ObjectYAML/LLVMBuild.txt b/lib/ObjectYAML/LLVMBuild.txt
index b8d1d2f1779e..44657e916a91 100644
--- a/lib/ObjectYAML/LLVMBuild.txt
+++ b/lib/ObjectYAML/LLVMBuild.txt
@@ -11,4 +11,4 @@
type = Library
name = ObjectYAML
parent = Libraries
-required_libraries = Support
+required_libraries = Support DebugInfoCodeView
diff --git a/lib/Passes/PassBuilder.cpp b/lib/Passes/PassBuilder.cpp
index abc53e97aa72..eb81e58b9b0e 100644
--- a/lib/Passes/PassBuilder.cpp
+++ b/lib/Passes/PassBuilder.cpp
@@ -164,7 +164,8 @@ static cl::opt<bool> EnableGVNHoist(
"enable-npm-gvn-hoist", cl::init(false), cl::Hidden,
cl::desc("Enable the GVN hoisting pass for the new PM (default = off)"));
-static Regex DefaultAliasRegex("^(default|lto-pre-link|lto)<(O[0123sz])>$");
+static Regex DefaultAliasRegex(
+ "^(default|thinlto-pre-link|thinlto|lto-pre-link|lto)<(O[0123sz])>$");
static bool isOptimizingForSize(PassBuilder::OptimizationLevel Level) {
switch (Level) {
@@ -345,6 +346,9 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level,
LPM2.addPass(IndVarSimplifyPass());
LPM2.addPass(LoopIdiomRecognizePass());
LPM2.addPass(LoopDeletionPass());
+ // FIXME: The old pass manager has a hack to disable loop unrolling during
+ // ThinLTO when using sample PGO. Need to either fix it or port some
+ // workaround.
LPM2.addPass(LoopUnrollPass::createFull(Level));
// We provide the opt remark emitter pass for LICM to use. We only need to do
@@ -454,14 +458,10 @@ static void addPGOInstrPasses(ModulePassManager &MPM, bool DebugLogging,
}
ModulePassManager
-PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level,
- bool DebugLogging) {
- assert(Level != O0 && "Must request optimizations for the default pipeline!");
+PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
+ bool DebugLogging) {
ModulePassManager MPM(DebugLogging);
- // Force any function attributes we want the rest of the pipeline te observe.
- MPM.addPass(ForceFunctionAttrsPass());
-
// Do basic inference of function attributes from known properties of system
// libraries and other oracles.
MPM.addPass(InferFunctionAttrsPass());
@@ -504,16 +504,16 @@ PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level,
GlobalCleanupPM.addPass(SimplifyCFGPass());
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(GlobalCleanupPM)));
- // Add all the requested passes for PGO Instrumentation, if requested.
+ // Add all the requested passes for PGO, if requested.
if (PGOOpt) {
assert(PGOOpt->RunProfileGen || PGOOpt->SamplePGO ||
!PGOOpt->ProfileUseFile.empty());
addPGOInstrPasses(MPM, DebugLogging, Level, PGOOpt->RunProfileGen,
PGOOpt->ProfileGenFile, PGOOpt->ProfileUseFile);
- }
- // Indirect call promotion that promotes intra-module targes only.
- MPM.addPass(PGOIndirectCallPromotion(false, PGOOpt && PGOOpt->SamplePGO));
+ // Indirect call promotion that promotes intra-module targes only.
+ MPM.addPass(PGOIndirectCallPromotion(false, PGOOpt && PGOOpt->SamplePGO));
+ }
// Require the GlobalsAA analysis for the module so we can query it within
// the CGSCC pipeline.
@@ -562,17 +562,30 @@ PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level,
createModuleToPostOrderCGSCCPassAdaptor(createDevirtSCCRepeatedPass(
std::move(MainCGPipeline), MaxDevirtIterations, DebugLogging)));
- // This ends the canonicalization and simplification phase of the pipeline.
- // At this point, we expect to have canonical and simple IR which we begin
- // *optimizing* for efficient execution going forward.
+ return MPM;
+}
+
+ModulePassManager
+PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
+ bool DebugLogging) {
+ ModulePassManager MPM(DebugLogging);
+
+ // Optimize globals now that the module is fully simplified.
+ MPM.addPass(GlobalOptPass());
// Run partial inlining pass to partially inline functions that have
// large bodies.
if (RunPartialInlining)
MPM.addPass(PartialInlinerPass());
- // Eliminate externally available functions now that inlining is over -- we
- // won't emit these anyways.
+ // Remove avail extern fns and globals definitions since we aren't compiling
+ // an object file for later LTO. For LTO we want to preserve these so they
+ // are eligible for inlining at link-time. Note if they are unreferenced they
+ // will be removed by GlobalDCE later, so this only impacts referenced
+ // available externally globals. Eventually they will be suppressed during
+ // codegen, but eliminating here enables more opportunity for GlobalDCE as it
+ // may make globals referenced by available external functions dead and saves
+ // running remaining passes on the eliminated functions.
MPM.addPass(EliminateAvailableExternallyPass());
// Do RPO function attribute inference across the module to forward-propagate
@@ -671,6 +684,87 @@ PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level,
}
ModulePassManager
+PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level,
+ bool DebugLogging) {
+ assert(Level != O0 && "Must request optimizations for the default pipeline!");
+
+ ModulePassManager MPM(DebugLogging);
+
+ // Force any function attributes we want the rest of the pipeline to observe.
+ MPM.addPass(ForceFunctionAttrsPass());
+
+ // Add the core simplification pipeline.
+ MPM.addPass(buildModuleSimplificationPipeline(Level, DebugLogging));
+
+ // Now add the optimization pipeline.
+ MPM.addPass(buildModuleOptimizationPipeline(Level, DebugLogging));
+
+ return MPM;
+}
+
+ModulePassManager
+PassBuilder::buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level,
+ bool DebugLogging) {
+ assert(Level != O0 && "Must request optimizations for the default pipeline!");
+
+ ModulePassManager MPM(DebugLogging);
+
+ // Force any function attributes we want the rest of the pipeline to observe.
+ MPM.addPass(ForceFunctionAttrsPass());
+
+ // If we are planning to perform ThinLTO later, we don't bloat the code with
+ // unrolling/vectorization/... now. Just simplify the module as much as we
+ // can.
+ MPM.addPass(buildModuleSimplificationPipeline(Level, DebugLogging));
+
+ // Run partial inlining pass to partially inline functions that have
+ // large bodies.
+ // FIXME: It isn't clear whether this is really the right place to run this
+ // in ThinLTO. Because there is another canonicalization and simplification
+ // phase that will run after the thin link, running this here ends up with
+ // less information than will be available later and it may grow functions in
+ // ways that aren't beneficial.
+ if (RunPartialInlining)
+ MPM.addPass(PartialInlinerPass());
+
+ // Reduce the size of the IR as much as possible.
+ MPM.addPass(GlobalOptPass());
+
+ // Rename anon globals to be able to export them in the summary.
+ MPM.addPass(NameAnonGlobalPass());
+
+ return MPM;
+}
+
+ModulePassManager
+PassBuilder::buildThinLTODefaultPipeline(OptimizationLevel Level,
+ bool DebugLogging) {
+ // FIXME: The summary index is not hooked in the new pass manager yet.
+ // When it's going to be hooked, enable WholeProgramDevirt and LowerTypeTest
+ // here.
+
+ ModulePassManager MPM(DebugLogging);
+
+ // Force any function attributes we want the rest of the pipeline to observe.
+ MPM.addPass(ForceFunctionAttrsPass());
+
+ // During the ThinLTO backend phase we perform early indirect call promotion
+ // here, before globalopt. Otherwise imported available_externally functions
+ // look unreferenced and are removed.
+ MPM.addPass(PGOIndirectCallPromotion(true /* InLTO */,
+ PGOOpt && PGOOpt->SamplePGO &&
+ !PGOOpt->ProfileUseFile.empty()));
+
+ // Add the core simplification pipeline.
+ MPM.addPass(buildModuleSimplificationPipeline(Level, DebugLogging));
+
+ // Now add the optimization pipeline.
+ MPM.addPass(buildModuleOptimizationPipeline(Level, DebugLogging));
+
+ return MPM;
+}
+
+ModulePassManager
PassBuilder::buildLTOPreLinkDefaultPipeline(OptimizationLevel Level,
bool DebugLogging) {
assert(Level != O0 && "Must request optimizations for the default pipeline!");
@@ -893,9 +987,16 @@ static Optional<int> parseDevirtPassName(StringRef Name) {
return Count;
}
+/// Tests whether a pass name starts with a valid prefix for a default pipeline
+/// alias.
+static bool startsWithDefaultPipelineAliasPrefix(StringRef Name) {
+ return Name.startswith("default") || Name.startswith("thinlto") ||
+ Name.startswith("lto");
+}
+
static bool isModulePassName(StringRef Name) {
// Manually handle aliases for pre-configured pipeline fragments.
- if (Name.startswith("default") || Name.startswith("lto"))
+ if (startsWithDefaultPipelineAliasPrefix(Name))
return DefaultAliasRegex.match(Name);
// Explicitly handle pass manager names.
@@ -1090,7 +1191,7 @@ bool PassBuilder::parseModulePass(ModulePassManager &MPM,
}
// Manually handle aliases for pre-configured pipeline fragments.
- if (Name.startswith("default") || Name.startswith("lto")) {
+ if (startsWithDefaultPipelineAliasPrefix(Name)) {
SmallVector<StringRef, 3> Matches;
if (!DefaultAliasRegex.match(Name, &Matches))
return false;
@@ -1109,6 +1210,10 @@ bool PassBuilder::parseModulePass(ModulePassManager &MPM,
if (Matches[1] == "default") {
MPM.addPass(buildPerModuleDefaultPipeline(L, DebugLogging));
+ } else if (Matches[1] == "thinlto-pre-link") {
+ MPM.addPass(buildThinLTOPreLinkDefaultPipeline(L, DebugLogging));
+ } else if (Matches[1] == "thinlto") {
+ MPM.addPass(buildThinLTODefaultPipeline(L, DebugLogging));
} else if (Matches[1] == "lto-pre-link") {
MPM.addPass(buildLTOPreLinkDefaultPipeline(L, DebugLogging));
} else {
diff --git a/lib/Support/BinaryStreamReader.cpp b/lib/Support/BinaryStreamReader.cpp
index 862232971162..bfb658cfa0b7 100644
--- a/lib/Support/BinaryStreamReader.cpp
+++ b/lib/Support/BinaryStreamReader.cpp
@@ -69,6 +69,26 @@ Error BinaryStreamReader::readCString(StringRef &Dest) {
return Error::success();
}
+Error BinaryStreamReader::readWideString(ArrayRef<UTF16> &Dest) {
+ uint32_t Length = 0;
+ uint32_t OriginalOffset = getOffset();
+ const UTF16 *C;
+ while (true) {
+ if (auto EC = readObject(C))
+ return EC;
+ if (*C == 0x0000)
+ break;
+ ++Length;
+ }
+ uint32_t NewOffset = getOffset();
+ setOffset(OriginalOffset);
+
+ if (auto EC = readArray(Dest, Length))
+ return EC;
+ setOffset(NewOffset);
+ return Error::success();
+}
+
Error BinaryStreamReader::readFixedString(StringRef &Dest, uint32_t Length) {
ArrayRef<uint8_t> Bytes;
if (auto EC = readBytes(Bytes, Length))
diff --git a/lib/Support/Unix/Path.inc b/lib/Support/Unix/Path.inc
index fa28ba1b6ab6..ce638d453c19 100644
--- a/lib/Support/Unix/Path.inc
+++ b/lib/Support/Unix/Path.inc
@@ -381,6 +381,11 @@ static bool is_local_impl(struct STATVFS &Vfs) {
#elif defined(__CYGWIN__)
// Cygwin doesn't expose this information; would need to use Win32 API.
return false;
+#elif defined(__sun)
+ // statvfs::f_basetype contains a null-terminated FSType name of the mounted target
+ StringRef fstype(Vfs.f_basetype);
+ // NFS is the only non-local fstype??
+ return !fstype.equals("nfs");
#else
return !!(STATVFS_F_FLAG(Vfs) & MNT_LOCAL);
#endif
diff --git a/lib/TableGen/Record.cpp b/lib/TableGen/Record.cpp
index f07208b1fb90..83f7147dc9f6 100644
--- a/lib/TableGen/Record.cpp
+++ b/lib/TableGen/Record.cpp
@@ -1572,12 +1572,6 @@ RecordVal::RecordVal(Init *N, RecTy *T, bool P)
assert(Value && "Cannot create unset value for current type!");
}
-RecordVal::RecordVal(StringRef N, RecTy *T, bool P)
- : Name(StringInit::get(N)), TyAndPrefix(T, P) {
- Value = UnsetInit::get()->convertInitializerTo(T);
- assert(Value && "Cannot create unset value for current type!");
-}
-
StringRef RecordVal::getName() const {
return cast<StringInit>(getNameInit())->getValue();
}
@@ -1603,8 +1597,7 @@ void Record::init() {
// Every record potentially has a def at the top. This value is
// replaced with the top-level def name at instantiation time.
- RecordVal DN("NAME", StringRecTy::get(), false);
- addValue(DN);
+ addValue(RecordVal(StringInit::get("NAME"), StringRecTy::get(), false));
}
void Record::checkName() {
@@ -1640,10 +1633,6 @@ void Record::setName(Init *NewName) {
// this. See TGParser::ParseDef and TGParser::ParseDefm.
}
-void Record::setName(StringRef Name) {
- setName(StringInit::get(Name));
-}
-
void Record::resolveReferencesTo(const RecordVal *RV) {
for (RecordVal &Value : Values) {
if (RV == &Value) // Skip resolve the same field as the given one
@@ -1714,7 +1703,7 @@ Init *Record::getValueInit(StringRef FieldName) const {
return R->getValue();
}
-std::string Record::getValueAsString(StringRef FieldName) const {
+StringRef Record::getValueAsString(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName);
if (!R || !R->getValue())
PrintFatalError(getLoc(), "Record `" + getName() +
@@ -1793,10 +1782,10 @@ Record::getValueAsListOfInts(StringRef FieldName) const {
return Ints;
}
-std::vector<std::string>
+std::vector<StringRef>
Record::getValueAsListOfStrings(StringRef FieldName) const {
ListInit *List = getValueAsListInit(FieldName);
- std::vector<std::string> Strings;
+ std::vector<StringRef> Strings;
for (Init *I : List->getValues()) {
if (StringInit *SI = dyn_cast<StringInit>(I))
Strings.push_back(SI->getValue());
diff --git a/lib/TableGen/TGParser.cpp b/lib/TableGen/TGParser.cpp
index 96015b06d798..b492cf9495c0 100644
--- a/lib/TableGen/TGParser.cpp
+++ b/lib/TableGen/TGParser.cpp
@@ -339,7 +339,7 @@ bool TGParser::ProcessForeachDefs(Record *CurRec, SMLoc Loc, IterSet &IterVals){
if (!IVal)
return Error(Loc, "foreach iterator value is untyped");
- IterRec->addValue(RecordVal(IterVar->getName(), IVal->getType(), false));
+ IterRec->addValue(RecordVal(IterVar->getNameInit(), IVal->getType(), false));
if (SetValue(IterRec.get(), Loc, IterVar->getNameInit(), None, IVal))
return Error(Loc, "when instantiating this def");
@@ -378,8 +378,8 @@ static bool isObjectStart(tgtok::TokKind K) {
/// GetNewAnonymousName - Generate a unique anonymous name that can be used as
/// an identifier.
-std::string TGParser::GetNewAnonymousName() {
- return "anonymous_" + utostr(AnonCounter++);
+Init *TGParser::GetNewAnonymousName() {
+ return StringInit::get("anonymous_" + utostr(AnonCounter++));
}
/// ParseObjectName - If an object name is specified, return it. Otherwise,
@@ -2350,7 +2350,7 @@ Record *TGParser::InstantiateMulticlassDef(MultiClass &MC, Record *DefProto,
bool IsAnonymous = false;
if (!DefmPrefix) {
- DefmPrefix = StringInit::get(GetNewAnonymousName());
+ DefmPrefix = GetNewAnonymousName();
IsAnonymous = true;
}
diff --git a/lib/TableGen/TGParser.h b/lib/TableGen/TGParser.h
index 76f7d8fe5026..1b2966c9f6c9 100644
--- a/lib/TableGen/TGParser.h
+++ b/lib/TableGen/TGParser.h
@@ -110,7 +110,7 @@ private: // Semantic analysis methods.
bool AddSubMultiClass(MultiClass *CurMC,
SubMultiClassReference &SubMultiClass);
- std::string GetNewAnonymousName();
+ Init *GetNewAnonymousName();
// IterRecord: Map an iterator name to a value.
struct IterRecord {
diff --git a/lib/Target/AArch64/AArch64.td b/lib/Target/AArch64/AArch64.td
index 4af5fef4287c..abe28460c83a 100644
--- a/lib/Target/AArch64/AArch64.td
+++ b/lib/Target/AArch64/AArch64.td
@@ -190,6 +190,7 @@ def ProcA53 : SubtargetFeature<"a53", "ARMProcFamily", "CortexA53",
FeatureCrypto,
FeatureCustomCheapAsMoveHandling,
FeatureFPARMv8,
+ FeatureFuseAES,
FeatureNEON,
FeaturePerfMon,
FeaturePostRAScheduler,
@@ -226,6 +227,7 @@ def ProcA73 : SubtargetFeature<"a73", "ARMProcFamily", "CortexA73",
FeatureCRC,
FeatureCrypto,
FeatureFPARMv8,
+ FeatureFuseAES,
FeatureNEON,
FeaturePerfMon
]>;
diff --git a/lib/Target/AArch64/AArch64SchedM1.td b/lib/Target/AArch64/AArch64SchedM1.td
index 3fbbc0be682d..3b71cf8399a0 100644
--- a/lib/Target/AArch64/AArch64SchedM1.td
+++ b/lib/Target/AArch64/AArch64SchedM1.td
@@ -23,7 +23,7 @@ def ExynosM1Model : SchedMachineModel {
let LoopMicroOpBufferSize = 24; // Based on the instruction queue size.
let LoadLatency = 4; // Optimistic load cases.
let MispredictPenalty = 14; // Minimum branch misprediction penalty.
- let CompleteModel = 0; // Use the default model otherwise.
+ let CompleteModel = 1; // Use the default model otherwise.
}
//===----------------------------------------------------------------------===//
@@ -72,14 +72,14 @@ def M1WriteC2 : SchedWriteRes<[M1UnitC]> { let Latency = 2; }
def M1WriteB1 : SchedWriteRes<[M1UnitB]> { let Latency = 1; }
def M1WriteL5 : SchedWriteRes<[M1UnitL]> { let Latency = 5; }
-def M1WriteLA : SchedWriteVariant<[SchedVar<ScaledIdxPred, [M1WriteL5,
+def M1WriteLX : SchedWriteVariant<[SchedVar<ScaledIdxPred, [M1WriteL5,
M1WriteA1]>,
SchedVar<NoSchedPred, [M1WriteL5]>]>;
def M1WriteS1 : SchedWriteRes<[M1UnitS]> { let Latency = 1; }
def M1WriteS2 : SchedWriteRes<[M1UnitS]> { let Latency = 2; }
def M1WriteS4 : SchedWriteRes<[M1UnitS]> { let Latency = 4; }
-def M1WriteSA : SchedWriteVariant<[SchedVar<ScaledIdxPred, [M1WriteS2,
+def M1WriteSX : SchedWriteVariant<[SchedVar<ScaledIdxPred, [M1WriteS2,
M1WriteA1]>,
SchedVar<NoSchedPred, [M1WriteS1]>]>;
@@ -125,13 +125,13 @@ def : WriteRes<WriteAdr, []> { let Latency = 0; }
// Load instructions.
def : WriteRes<WriteLD, [M1UnitL]> { let Latency = 4; }
def : WriteRes<WriteLDHi, [M1UnitALU]> { let Latency = 4; }
-def : SchedAlias<WriteLDIdx, M1WriteLA>;
+def : SchedAlias<WriteLDIdx, M1WriteLX>;
// Store instructions.
def : WriteRes<WriteST, [M1UnitS]> { let Latency = 1; }
def : WriteRes<WriteSTP, [M1UnitS]> { let Latency = 1; }
def : WriteRes<WriteSTX, [M1UnitS]> { let Latency = 1; }
-def : SchedAlias<WriteSTIdx, M1WriteSA>;
+def : SchedAlias<WriteSTIdx, M1WriteSX>;
// FP data instructions.
def : WriteRes<WriteF, [M1UnitFADD]> { let Latency = 3; }
@@ -231,6 +231,111 @@ def M1WriteNMISC3 : SchedWriteRes<[M1UnitNMISC]> { let Latency = 3; }
def M1WriteNMISC4 : SchedWriteRes<[M1UnitNMISC]> { let Latency = 4; }
def M1WriteTB : SchedWriteRes<[M1UnitC,
M1UnitALU]> { let Latency = 2; }
+def M1WriteVLDA : SchedWriteRes<[M1UnitL,
+ M1UnitL]> { let Latency = 6; }
+def M1WriteVLDB : SchedWriteRes<[M1UnitL,
+ M1UnitL,
+ M1UnitL]> { let Latency = 7; }
+def M1WriteVLDC : SchedWriteRes<[M1UnitL,
+ M1UnitL,
+ M1UnitL,
+ M1UnitL]> { let Latency = 8; }
+def M1WriteVLDD : SchedWriteRes<[M1UnitL,
+ M1UnitNALU]> { let Latency = 7;
+ let ResourceCycles = [2]; }
+def M1WriteVLDE : SchedWriteRes<[M1UnitL,
+ M1UnitNALU]> { let Latency = 6; }
+def M1WriteVLDF : SchedWriteRes<[M1UnitL,
+ M1UnitL]> { let Latency = 10;
+ let ResourceCycles = [5]; }
+def M1WriteVLDG : SchedWriteRes<[M1UnitL,
+ M1UnitNALU,
+ M1UnitNALU]> { let Latency = 7;
+ let ResourceCycles = [2]; }
+def M1WriteVLDH : SchedWriteRes<[M1UnitL,
+ M1UnitNALU,
+ M1UnitNALU]> { let Latency = 6; }
+def M1WriteVLDI : SchedWriteRes<[M1UnitL,
+ M1UnitL,
+ M1UnitL]> { let Latency = 12;
+ let ResourceCycles = [6]; }
+def M1WriteVLDJ : SchedWriteRes<[M1UnitL,
+ M1UnitNALU,
+ M1UnitNALU,
+ M1UnitNALU]> { let Latency = 9;
+ let ResourceCycles = [4]; }
+def M1WriteVLDK : SchedWriteRes<[M1UnitL,
+ M1UnitNALU,
+ M1UnitNALU,
+ M1UnitNALU,
+ M1UnitNALU]> { let Latency = 9;
+ let ResourceCycles = [4]; }
+def M1WriteVLDL : SchedWriteRes<[M1UnitL,
+ M1UnitNALU,
+ M1UnitNALU,
+ M1UnitNALU]> { let Latency = 7;
+ let ResourceCycles = [2]; }
+def M1WriteVLDM : SchedWriteRes<[M1UnitL,
+ M1UnitNALU,
+ M1UnitNALU,
+ M1UnitNALU,
+ M1UnitNALU]> { let Latency = 7;
+ let ResourceCycles = [2]; }
+def M1WriteVLDN : SchedWriteRes<[M1UnitL,
+ M1UnitL,
+ M1UnitL,
+ M1UnitL]> { let Latency = 14;
+ let ResourceCycles = [7]; }
+
+def M1WriteVSTA : WriteSequence<[WriteVST], 2>;
+def M1WriteVSTB : WriteSequence<[WriteVST], 3>;
+def M1WriteVSTC : WriteSequence<[WriteVST], 4>;
+def M1WriteVSTD : SchedWriteRes<[M1UnitS,
+ M1UnitFST,
+ M1UnitFST]> { let Latency = 7;
+ let ResourceCycles = [7]; }
+def M1WriteVSTE : SchedWriteRes<[M1UnitS,
+ M1UnitFST,
+ M1UnitS,
+ M1UnitFST,
+ M1UnitFST]> { let Latency = 8;
+ let ResourceCycles = [8]; }
+def M1WriteVSTF : SchedWriteRes<[M1UnitNALU,
+ M1UnitS,
+ M1UnitFST,
+ M1UnitS,
+ M1UnitFST,
+ M1UnitFST,
+ M1UnitFST]> { let Latency = 15;
+ let ResourceCycles = [15]; }
+def M1WriteVSTG : SchedWriteRes<[M1UnitNALU,
+ M1UnitS,
+ M1UnitFST,
+ M1UnitS,
+ M1UnitFST,
+ M1UnitS,
+ M1UnitFST,
+ M1UnitFST,
+ M1UnitFST]> { let Latency = 16;
+ let ResourceCycles = [16]; }
+def M1WriteVSTH : SchedWriteRes<[M1UnitNALU,
+ M1UnitS,
+ M1UnitFST,
+ M1UnitFST,
+ M1UnitFST]> { let Latency = 14;
+ let ResourceCycles = [14]; }
+def M1WriteVSTI : SchedWriteRes<[M1UnitNALU,
+ M1UnitS,
+ M1UnitFST,
+ M1UnitS,
+ M1UnitFST,
+ M1UnitS,
+ M1UnitFST,
+ M1UnitS,
+ M1UnitFST,
+ M1UnitFST,
+ M1UnitFST]> { let Latency = 17;
+ let ResourceCycles = [17]; }
// Branch instructions
def : InstRW<[M1WriteB1], (instrs Bcc)>;
@@ -360,8 +465,233 @@ def : InstRW<[M1WriteNALU2], (instregex "^(TRN|UZP)[12](v16i8|v8i16|v4i32|v2i64
def : InstRW<[M1WriteNALU1], (instregex "^ZIP[12]v")>;
// ASIMD load instructions.
+def : InstRW<[M1WriteVLDD], (instregex "LD1i(8|16|32)$")>;
+def : InstRW<[M1WriteVLDD,
+ WriteAdr], (instregex "LD1i(8|16|32)_POST$")>;
+def : InstRW<[M1WriteVLDE], (instregex "LD1i(64)$")>;
+def : InstRW<[M1WriteVLDE,
+ WriteAdr], (instregex "LD1i(64)_POST$")>;
+
+def : InstRW<[M1WriteL5], (instregex "LD1Rv(8b|4h|2s)$")>;
+def : InstRW<[M1WriteL5,
+ WriteAdr], (instregex "LD1Rv(8b|4h|2s)_POST$")>;
+def : InstRW<[M1WriteL5], (instregex "LD1Rv(1d)$")>;
+def : InstRW<[M1WriteL5,
+ WriteAdr], (instregex "LD1Rv(1d)_POST$")>;
+def : InstRW<[M1WriteL5], (instregex "LD1Rv(16b|8h|4s|2d)$")>;
+def : InstRW<[M1WriteL5,
+ WriteAdr], (instregex "LD1Rv(16b|8h|4s|2d)_POST$")>;
+
+def : InstRW<[M1WriteL5], (instregex "LD1Onev(8b|4h|2s|1d)$")>;
+def : InstRW<[M1WriteL5,
+ WriteAdr], (instregex "LD1Onev(8b|4h|2s|1d)_POST$")>;
+def : InstRW<[M1WriteL5], (instregex "LD1Onev(16b|8h|4s|2d)$")>;
+def : InstRW<[M1WriteL5,
+ WriteAdr], (instregex "LD1Onev(16b|8h|4s|2d)_POST$")>;
+def : InstRW<[M1WriteVLDA], (instregex "LD1Twov(8b|4h|2s|1d)$")>;
+def : InstRW<[M1WriteVLDA,
+ WriteAdr], (instregex "LD1Twov(8b|4h|2s|1d)_POST$")>;
+def : InstRW<[M1WriteVLDA], (instregex "LD1Twov(16b|8h|4s|2d)$")>;
+def : InstRW<[M1WriteVLDA,
+ WriteAdr], (instregex "LD1Twov(16b|8h|4s|2d)_POST$")>;
+def : InstRW<[M1WriteVLDB], (instregex "LD1Threev(8b|4h|2s|1d)$")>;
+def : InstRW<[M1WriteVLDB,
+ WriteAdr], (instregex "LD1Threev(8b|4h|2s|1d)_POST$")>;
+def : InstRW<[M1WriteVLDB], (instregex "LD1Threev(16b|8h|4s|2d)$")>;
+def : InstRW<[M1WriteVLDB,
+ WriteAdr], (instregex "LD1Threev(16b|8h|4s|2d)_POST$")>;
+def : InstRW<[M1WriteVLDC], (instregex "LD1Fourv(8b|4h|2s|1d)$")>;
+def : InstRW<[M1WriteVLDC,
+ WriteAdr], (instregex "LD1Fourv(8b|4h|2s|1d)_POST$")>;
+def : InstRW<[M1WriteVLDC], (instregex "LD1Fourv(16b|8h|4s|2d)$")>;
+def : InstRW<[M1WriteVLDC,
+ WriteAdr], (instregex "LD1Fourv(16b|8h|4s|2d)_POST$")>;
+
+def : InstRW<[M1WriteVLDG], (instregex "LD2i(8|16)$")>;
+def : InstRW<[M1WriteVLDG,
+ WriteAdr], (instregex "LD2i(8|16)_POST$")>;
+def : InstRW<[M1WriteVLDG], (instregex "LD2i(32)$")>;
+def : InstRW<[M1WriteVLDG,
+ WriteAdr], (instregex "LD2i(32)_POST$")>;
+def : InstRW<[M1WriteVLDH], (instregex "LD2i(64)$")>;
+def : InstRW<[M1WriteVLDH,
+ WriteAdr], (instregex "LD2i(64)_POST$")>;
+
+def : InstRW<[M1WriteVLDA], (instregex "LD2Rv(8b|4h|2s)$")>;
+def : InstRW<[M1WriteVLDA,
+ WriteAdr], (instregex "LD2Rv(8b|4h|2s)_POST$")>;
+def : InstRW<[M1WriteVLDA], (instregex "LD2Rv(1d)$")>;
+def : InstRW<[M1WriteVLDA,
+ WriteAdr], (instregex "LD2Rv(1d)_POST$")>;
+def : InstRW<[M1WriteVLDA], (instregex "LD2Rv(16b|8h|4s|2d)$")>;
+def : InstRW<[M1WriteVLDA,
+ WriteAdr], (instregex "LD2Rv(16b|8h|4s|2d)_POST$")>;
+
+def : InstRW<[M1WriteVLDF], (instregex "LD2Twov(8b|4h|2s)$")>;
+def : InstRW<[M1WriteVLDF,
+ WriteAdr], (instregex "LD2Twov(8b|4h|2s)_POST$")>;
+def : InstRW<[M1WriteVLDF], (instregex "LD2Twov(16b|8h|4s)$")>;
+def : InstRW<[M1WriteVLDF,
+ WriteAdr], (instregex "LD2Twov(16b|8h|4s)_POST$")>;
+def : InstRW<[M1WriteVLDF], (instregex "LD2Twov(2d)$")>;
+def : InstRW<[M1WriteVLDF,
+ WriteAdr], (instregex "LD2Twov(2d)_POST$")>;
+
+def : InstRW<[M1WriteVLDJ], (instregex "LD3i(8|16)$")>;
+def : InstRW<[M1WriteVLDJ,
+ WriteAdr], (instregex "LD3i(8|16)_POST$")>;
+def : InstRW<[M1WriteVLDJ], (instregex "LD3i(32)$")>;
+def : InstRW<[M1WriteVLDJ,
+ WriteAdr], (instregex "LD3i(32)_POST$")>;
+def : InstRW<[M1WriteVLDL], (instregex "LD3i(64)$")>;
+def : InstRW<[M1WriteVLDL,
+ WriteAdr], (instregex "LD3i(64)_POST$")>;
+
+def : InstRW<[M1WriteVLDB], (instregex "LD3Rv(8b|4h|2s)$")>;
+def : InstRW<[M1WriteVLDB,
+ WriteAdr], (instregex "LD3Rv(8b|4h|2s)_POST$")>;
+def : InstRW<[M1WriteVLDB], (instregex "LD3Rv(1d)$")>;
+def : InstRW<[M1WriteVLDB,
+ WriteAdr], (instregex "LD3Rv(1d)_POST$")>;
+def : InstRW<[M1WriteVLDB], (instregex "LD3Rv(16b|8h|4s)$")>;
+def : InstRW<[M1WriteVLDB,
+ WriteAdr], (instregex "LD3Rv(16b|8h|4s)_POST$")>;
+def : InstRW<[M1WriteVLDB], (instregex "LD3Rv(2d)$")>;
+def : InstRW<[M1WriteVLDB,
+ WriteAdr], (instregex "LD3Rv(2d)_POST$")>;
+
+def : InstRW<[M1WriteVLDI], (instregex "LD3Threev(8b|4h|2s)$")>;
+def : InstRW<[M1WriteVLDI,
+ WriteAdr], (instregex "LD3Threev(8b|4h|2s)_POST$")>;
+def : InstRW<[M1WriteVLDI], (instregex "LD3Threev(16b|8h|4s)$")>;
+def : InstRW<[M1WriteVLDI,
+ WriteAdr], (instregex "LD3Threev(16b|8h|4s)_POST$")>;
+def : InstRW<[M1WriteVLDI], (instregex "LD3Threev(2d)$")>;
+def : InstRW<[M1WriteVLDI,
+ WriteAdr], (instregex "LD3Threev(2d)_POST$")>;
+
+def : InstRW<[M1WriteVLDK], (instregex "LD4i(8|16)$")>;
+def : InstRW<[M1WriteVLDK,
+ WriteAdr], (instregex "LD4i(8|16)_POST$")>;
+def : InstRW<[M1WriteVLDK], (instregex "LD4i(32)$")>;
+def : InstRW<[M1WriteVLDK,
+ WriteAdr], (instregex "LD4i(32)_POST$")>;
+def : InstRW<[M1WriteVLDM], (instregex "LD4i(64)$")>;
+def : InstRW<[M1WriteVLDM,
+ WriteAdr], (instregex "LD4i(64)_POST$")>;
+
+def : InstRW<[M1WriteVLDC], (instregex "LD4Rv(8b|4h|2s)$")>;
+def : InstRW<[M1WriteVLDC,
+ WriteAdr], (instregex "LD4Rv(8b|4h|2s)_POST$")>;
+def : InstRW<[M1WriteVLDC], (instregex "LD4Rv(1d)$")>;
+def : InstRW<[M1WriteVLDC,
+ WriteAdr], (instregex "LD4Rv(1d)_POST$")>;
+def : InstRW<[M1WriteVLDC], (instregex "LD4Rv(16b|8h|4s)$")>;
+def : InstRW<[M1WriteVLDC,
+ WriteAdr], (instregex "LD4Rv(16b|8h|4s)_POST$")>;
+def : InstRW<[M1WriteVLDC], (instregex "LD4Rv(2d)$")>;
+def : InstRW<[M1WriteVLDC,
+ WriteAdr], (instregex "LD4Rv(2d)_POST$")>;
+
+def : InstRW<[M1WriteVLDN], (instregex "LD4Fourv(8b|4h|2s)$")>;
+def : InstRW<[M1WriteVLDN,
+ WriteAdr], (instregex "LD4Fourv(8b|4h|2s)_POST$")>;
+def : InstRW<[M1WriteVLDN], (instregex "LD4Fourv(16b|8h|4s)$")>;
+def : InstRW<[M1WriteVLDN,
+ WriteAdr], (instregex "LD4Fourv(16b|8h|4s)_POST$")>;
+def : InstRW<[M1WriteVLDN], (instregex "LD4Fourv(2d)$")>;
+def : InstRW<[M1WriteVLDN,
+ WriteAdr], (instregex "LD4Fourv(2d)_POST$")>;
// ASIMD store instructions.
+def : InstRW<[M1WriteVSTD], (instregex "ST1i(8|16|32)$")>;
+def : InstRW<[M1WriteVSTD,
+ WriteAdr], (instregex "ST1i(8|16|32)_POST$")>;
+def : InstRW<[M1WriteVSTD], (instregex "ST1i(64)$")>;
+def : InstRW<[M1WriteVSTD,
+ WriteAdr], (instregex "ST1i(64)_POST$")>;
+
+def : InstRW<[WriteVST], (instregex "ST1Onev(8b|4h|2s|1d)$")>;
+def : InstRW<[WriteVST,
+ WriteAdr], (instregex "ST1Onev(8b|4h|2s|1d)_POST$")>;
+def : InstRW<[WriteVST], (instregex "ST1Onev(16b|8h|4s|2d)$")>;
+def : InstRW<[WriteVST,
+ WriteAdr], (instregex "ST1Onev(16b|8h|4s|2d)_POST$")>;
+def : InstRW<[M1WriteVSTA], (instregex "ST1Twov(8b|4h|2s|1d)$")>;
+def : InstRW<[M1WriteVSTA,
+ WriteAdr], (instregex "ST1Twov(8b|4h|2s|1d)_POST$")>;
+def : InstRW<[M1WriteVSTA], (instregex "ST1Twov(16b|8h|4s|2d)$")>;
+def : InstRW<[M1WriteVSTA,
+ WriteAdr], (instregex "ST1Twov(16b|8h|4s|2d)_POST$")>;
+def : InstRW<[M1WriteVSTB], (instregex "ST1Threev(8b|4h|2s|1d)$")>;
+def : InstRW<[M1WriteVSTB,
+ WriteAdr], (instregex "ST1Threev(8b|4h|2s|1d)_POST$")>;
+def : InstRW<[M1WriteVSTB], (instregex "ST1Threev(16b|8h|4s|2d)$")>;
+def : InstRW<[M1WriteVSTB,
+ WriteAdr], (instregex "ST1Threev(16b|8h|4s|2d)_POST$")>;
+def : InstRW<[M1WriteVSTC], (instregex "ST1Fourv(8b|4h|2s|1d)$")>;
+def : InstRW<[M1WriteVSTC,
+ WriteAdr], (instregex "ST1Fourv(8b|4h|2s|1d)_POST$")>;
+def : InstRW<[M1WriteVSTC], (instregex "ST1Fourv(16b|8h|4s|2d)$")>;
+def : InstRW<[M1WriteVSTC,
+ WriteAdr], (instregex "ST1Fourv(16b|8h|4s|2d)_POST$")>;
+
+def : InstRW<[M1WriteVSTD], (instregex "ST2i(8|16|32)$")>;
+def : InstRW<[M1WriteVSTD,
+ WriteAdr], (instregex "ST2i(8|16|32)_POST$")>;
+def : InstRW<[M1WriteVSTD], (instregex "ST2i(64)$")>;
+def : InstRW<[M1WriteVSTD,
+ WriteAdr], (instregex "ST2i(64)_POST$")>;
+
+def : InstRW<[M1WriteVSTD], (instregex "ST2Twov(8b|4h|2s)$")>;
+def : InstRW<[M1WriteVSTD,
+ WriteAdr], (instregex "ST2Twov(8b|4h|2s)_POST$")>;
+def : InstRW<[M1WriteVSTE], (instregex "ST2Twov(16b|8h|4s)$")>;
+def : InstRW<[M1WriteVSTE,
+ WriteAdr], (instregex "ST2Twov(16b|8h|4s)_POST$")>;
+def : InstRW<[M1WriteVSTE], (instregex "ST2Twov(2d)$")>;
+def : InstRW<[M1WriteVSTE,
+ WriteAdr], (instregex "ST2Twov(2d)_POST$")>;
+
+def : InstRW<[M1WriteVSTH], (instregex "ST3i(8|16)$")>;
+def : InstRW<[M1WriteVSTH,
+ WriteAdr], (instregex "ST3i(8|16)_POST$")>;
+def : InstRW<[M1WriteVSTH], (instregex "ST3i(32)$")>;
+def : InstRW<[M1WriteVSTH,
+ WriteAdr], (instregex "ST3i(32)_POST$")>;
+def : InstRW<[M1WriteVSTF], (instregex "ST3i(64)$")>;
+def : InstRW<[M1WriteVSTF,
+ WriteAdr], (instregex "ST3i(64)_POST$")>;
+
+def : InstRW<[M1WriteVSTF], (instregex "ST3Threev(8b|4h|2s)$")>;
+def : InstRW<[M1WriteVSTF,
+ WriteAdr], (instregex "ST3Threev(8b|4h|2s)_POST$")>;
+def : InstRW<[M1WriteVSTG], (instregex "ST3Threev(16b|8h|4s)$")>;
+def : InstRW<[M1WriteVSTG,
+ WriteAdr], (instregex "ST3Threev(16b|8h|4s)_POST$")>;
+def : InstRW<[M1WriteVSTG], (instregex "ST3Threev(2d)$")>;
+def : InstRW<[M1WriteVSTG,
+ WriteAdr], (instregex "ST3Threev(2d)_POST$")>;
+
+def : InstRW<[M1WriteVSTH], (instregex "ST4i(8|16)$")>;
+def : InstRW<[M1WriteVSTH,
+ WriteAdr], (instregex "ST4i(8|16)_POST$")>;
+def : InstRW<[M1WriteVSTH], (instregex "ST4i(32)$")>;
+def : InstRW<[M1WriteVSTH,
+ WriteAdr], (instregex "ST4i(32)_POST$")>;
+def : InstRW<[M1WriteVSTF], (instregex "ST4i(64)$")>;
+def : InstRW<[M1WriteVSTF,
+ WriteAdr], (instregex "ST4i(64)_POST$")>;
+
+def : InstRW<[M1WriteVSTF], (instregex "ST4Fourv(8b|4h|2s)$")>;
+def : InstRW<[M1WriteVSTF,
+ WriteAdr], (instregex "ST4Fourv(8b|4h|2s)_POST$")>;
+def : InstRW<[M1WriteVSTI], (instregex "ST4Fourv(16b|8h|4s)$")>;
+def : InstRW<[M1WriteVSTI,
+ WriteAdr], (instregex "ST4Fourv(16b|8h|4s)_POST$")>;
+def : InstRW<[M1WriteVSTI], (instregex "ST4Fourv(2d)$")>;
+def : InstRW<[M1WriteVSTI,
+ WriteAdr], (instregex "ST4Fourv(2d)_POST$")>;
// Cryptography instructions.
def M1WriteAES : SchedWriteRes<[M1UnitNCRYPT]> { let Latency = 1; }
diff --git a/lib/Target/AArch64/AArch64TargetMachine.cpp b/lib/Target/AArch64/AArch64TargetMachine.cpp
index cb3f72a524f5..d4a8cecdb29f 100644
--- a/lib/Target/AArch64/AArch64TargetMachine.cpp
+++ b/lib/Target/AArch64/AArch64TargetMachine.cpp
@@ -256,9 +256,9 @@ namespace {
/// AArch64 Code Generator Pass Configuration Options.
class AArch64PassConfig : public TargetPassConfig {
public:
- AArch64PassConfig(AArch64TargetMachine *TM, PassManagerBase &PM)
+ AArch64PassConfig(AArch64TargetMachine &TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {
- if (TM->getOptLevel() != CodeGenOpt::None)
+ if (TM.getOptLevel() != CodeGenOpt::None)
substitutePass(&PostRASchedulerID, &PostMachineSchedulerID);
}
@@ -317,7 +317,7 @@ TargetIRAnalysis AArch64TargetMachine::getTargetIRAnalysis() {
}
TargetPassConfig *AArch64TargetMachine::createPassConfig(PassManagerBase &PM) {
- return new AArch64PassConfig(this, PM);
+ return new AArch64PassConfig(*this, PM);
}
void AArch64PassConfig::addIRPasses() {
diff --git a/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp b/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
index f473944cd528..0959014812d8 100644
--- a/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
+++ b/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
@@ -503,40 +503,37 @@ AMDGPUAsmPrinter::SIFunctionResourceInfo AMDGPUAsmPrinter::analyzeResourceUsage(
Info.HasDynamicallySizedStack = FrameInfo.hasVarSizedObjects();
Info.PrivateSegmentSize = FrameInfo.getStackSize();
- if (!FrameInfo.hasCalls()) {
- Info.UsesVCC = MRI.isPhysRegUsed(AMDGPU::VCC_LO) ||
- MRI.isPhysRegUsed(AMDGPU::VCC_HI);
-
- // If there are no calls, MachineRegisterInfo can tell us the used register
- // count easily.
-
- MCPhysReg HighestVGPRReg = AMDGPU::NoRegister;
- for (MCPhysReg Reg : reverse(AMDGPU::VGPR_32RegClass.getRegisters())) {
- if (MRI.isPhysRegUsed(Reg)) {
- HighestVGPRReg = Reg;
- break;
- }
- }
- MCPhysReg HighestSGPRReg = AMDGPU::NoRegister;
- for (MCPhysReg Reg : reverse(AMDGPU::SGPR_32RegClass.getRegisters())) {
- if (MRI.isPhysRegUsed(Reg)) {
- HighestSGPRReg = Reg;
- break;
- }
- }
+ Info.UsesVCC = MRI.isPhysRegUsed(AMDGPU::VCC_LO) ||
+ MRI.isPhysRegUsed(AMDGPU::VCC_HI);
- // We found the maximum register index. They start at 0, so add one to get the
- // number of registers.
- Info.NumVGPR = HighestVGPRReg == AMDGPU::NoRegister ? 0 :
- TRI.getHWRegIndex(HighestVGPRReg) + 1;
- Info.NumExplicitSGPR = HighestSGPRReg == AMDGPU::NoRegister ? 0 :
- TRI.getHWRegIndex(HighestSGPRReg) + 1;
+ // If there are no calls, MachineRegisterInfo can tell us the used register
+ // count easily.
- return Info;
+ MCPhysReg HighestVGPRReg = AMDGPU::NoRegister;
+ for (MCPhysReg Reg : reverse(AMDGPU::VGPR_32RegClass.getRegisters())) {
+ if (MRI.isPhysRegUsed(Reg)) {
+ HighestVGPRReg = Reg;
+ break;
+ }
}
- llvm_unreachable("calls not implemented");
+ MCPhysReg HighestSGPRReg = AMDGPU::NoRegister;
+ for (MCPhysReg Reg : reverse(AMDGPU::SGPR_32RegClass.getRegisters())) {
+ if (MRI.isPhysRegUsed(Reg)) {
+ HighestSGPRReg = Reg;
+ break;
+ }
+ }
+
+ // We found the maximum register index. They start at 0, so add one to get the
+ // number of registers.
+ Info.NumVGPR = HighestVGPRReg == AMDGPU::NoRegister ? 0 :
+ TRI.getHWRegIndex(HighestVGPRReg) + 1;
+ Info.NumExplicitSGPR = HighestSGPRReg == AMDGPU::NoRegister ? 0 :
+ TRI.getHWRegIndex(HighestSGPRReg) + 1;
+
+ return Info;
}
void AMDGPUAsmPrinter::getSIProgramInfo(SIProgramInfo &ProgInfo,
diff --git a/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp b/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
index 48827f463997..596f02ae4a64 100644
--- a/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
+++ b/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
@@ -456,7 +456,7 @@ namespace {
class AMDGPUPassConfig : public TargetPassConfig {
public:
- AMDGPUPassConfig(TargetMachine *TM, PassManagerBase &PM)
+ AMDGPUPassConfig(LLVMTargetMachine &TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {
// Exceptions and StackMaps are not supported, so these passes will never do
// anything.
@@ -487,7 +487,7 @@ public:
class R600PassConfig final : public AMDGPUPassConfig {
public:
- R600PassConfig(TargetMachine *TM, PassManagerBase &PM)
+ R600PassConfig(LLVMTargetMachine &TM, PassManagerBase &PM)
: AMDGPUPassConfig(TM, PM) {}
ScheduleDAGInstrs *createMachineScheduler(
@@ -503,7 +503,7 @@ public:
class GCNPassConfig final : public AMDGPUPassConfig {
public:
- GCNPassConfig(TargetMachine *TM, PassManagerBase &PM)
+ GCNPassConfig(LLVMTargetMachine &TM, PassManagerBase &PM)
: AMDGPUPassConfig(TM, PM) {}
GCNTargetMachine &getGCNTargetMachine() const {
@@ -682,7 +682,7 @@ void R600PassConfig::addPreEmitPass() {
}
TargetPassConfig *R600TargetMachine::createPassConfig(PassManagerBase &PM) {
- return new R600PassConfig(this, PM);
+ return new R600PassConfig(*this, PM);
}
//===----------------------------------------------------------------------===//
@@ -844,6 +844,6 @@ void GCNPassConfig::addPreEmitPass() {
}
TargetPassConfig *GCNTargetMachine::createPassConfig(PassManagerBase &PM) {
- return new GCNPassConfig(this, PM);
+ return new GCNPassConfig(*this, PM);
}
diff --git a/lib/Target/AMDGPU/AMDGPUTargetMachine.h b/lib/Target/AMDGPU/AMDGPUTargetMachine.h
index 934bf7f31bab..a3c7c1982d0a 100644
--- a/lib/Target/AMDGPU/AMDGPUTargetMachine.h
+++ b/lib/Target/AMDGPU/AMDGPUTargetMachine.h
@@ -69,7 +69,6 @@ public:
return -1;
return 0;
}
-
};
//===----------------------------------------------------------------------===//
@@ -89,6 +88,10 @@ public:
TargetPassConfig *createPassConfig(PassManagerBase &PM) override;
const R600Subtarget *getSubtargetImpl(const Function &) const override;
+
+ bool isMachineVerifierClean() const override {
+ return false;
+ }
};
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
index f5541e08e1b7..cc68c971b249 100644
--- a/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
+++ b/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
@@ -161,7 +161,8 @@ public:
ImmTyOpSel,
ImmTyOpSelHi,
ImmTyNegLo,
- ImmTyNegHi
+ ImmTyNegHi,
+ ImmTySwizzle
};
struct TokOp {
@@ -474,6 +475,7 @@ public:
bool isSWaitCnt() const;
bool isHwreg() const;
bool isSendMsg() const;
+ bool isSwizzle() const;
bool isSMRDOffset8() const;
bool isSMRDOffset20() const;
bool isSMRDLiteralOffset() const;
@@ -659,6 +661,7 @@ public:
case ImmTyOpSelHi: OS << "OpSelHi"; break;
case ImmTyNegLo: OS << "NegLo"; break;
case ImmTyNegHi: OS << "NegHi"; break;
+ case ImmTySwizzle: OS << "Swizzle"; break;
}
}
@@ -994,6 +997,12 @@ private:
bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const;
unsigned findImplicitSGPRReadInVOP(const MCInst &Inst) const;
+ bool trySkipId(const StringRef Id);
+ bool trySkipToken(const AsmToken::TokenKind Kind);
+ bool skipToken(const AsmToken::TokenKind Kind, const StringRef ErrMsg);
+ bool parseString(StringRef &Val, const StringRef ErrMsg = "expected a string");
+ bool parseExpr(int64_t &Imm);
+
public:
OperandMatchResultTy parseOptionalOperand(OperandVector &Operands);
@@ -1003,6 +1012,19 @@ public:
OperandMatchResultTy parseInterpAttr(OperandVector &Operands);
OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands);
+ bool parseSwizzleOperands(const unsigned OpNum, int64_t* Op,
+ const unsigned MinVal,
+ const unsigned MaxVal,
+ const StringRef ErrMsg);
+ OperandMatchResultTy parseSwizzleOp(OperandVector &Operands);
+ bool parseSwizzleOffset(int64_t &Imm);
+ bool parseSwizzleMacro(int64_t &Imm);
+ bool parseSwizzleQuadPerm(int64_t &Imm);
+ bool parseSwizzleBitmaskPerm(int64_t &Imm);
+ bool parseSwizzleBroadcast(int64_t &Imm);
+ bool parseSwizzleSwap(int64_t &Imm);
+ bool parseSwizzleReverse(int64_t &Imm);
+
void cvtMubuf(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false); }
void cvtMubufAtomic(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, false); }
void cvtMubufAtomicReturn(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, true); }
@@ -2785,7 +2807,13 @@ void AMDGPUAsmParser::cvtDSImpl(MCInst &Inst, const OperandVector &Operands,
OptionalIdx[Op.getImmTy()] = i;
}
- addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset);
+ AMDGPUOperand::ImmTy OffsetType =
+ (Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_si ||
+ Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_vi) ? AMDGPUOperand::ImmTySwizzle :
+ AMDGPUOperand::ImmTyOffset;
+
+ addOptionalImmOperand(Inst, Operands, OptionalIdx, OffsetType);
+
if (!IsGdsHardcoded) {
addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
}
@@ -3384,6 +3412,298 @@ bool AMDGPUOperand::isSendMsg() const {
}
//===----------------------------------------------------------------------===//
+// parser helpers
+//===----------------------------------------------------------------------===//
+
+bool
+AMDGPUAsmParser::trySkipId(const StringRef Id) {
+ if (getLexer().getKind() == AsmToken::Identifier &&
+ Parser.getTok().getString() == Id) {
+ Parser.Lex();
+ return true;
+ }
+ return false;
+}
+
+bool
+AMDGPUAsmParser::trySkipToken(const AsmToken::TokenKind Kind) {
+ if (getLexer().getKind() == Kind) {
+ Parser.Lex();
+ return true;
+ }
+ return false;
+}
+
+bool
+AMDGPUAsmParser::skipToken(const AsmToken::TokenKind Kind,
+ const StringRef ErrMsg) {
+ if (!trySkipToken(Kind)) {
+ Error(Parser.getTok().getLoc(), ErrMsg);
+ return false;
+ }
+ return true;
+}
+
+bool
+AMDGPUAsmParser::parseExpr(int64_t &Imm) {
+ return !getParser().parseAbsoluteExpression(Imm);
+}
+
+bool
+AMDGPUAsmParser::parseString(StringRef &Val, const StringRef ErrMsg) {
+ SMLoc S = Parser.getTok().getLoc();
+ if (getLexer().getKind() == AsmToken::String) {
+ Val = Parser.getTok().getStringContents();
+ Parser.Lex();
+ return true;
+ } else {
+ Error(S, ErrMsg);
+ return false;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// swizzle
+//===----------------------------------------------------------------------===//
+
+LLVM_READNONE
+static unsigned
+encodeBitmaskPerm(const unsigned AndMask,
+ const unsigned OrMask,
+ const unsigned XorMask) {
+ using namespace llvm::AMDGPU::Swizzle;
+
+ return BITMASK_PERM_ENC |
+ (AndMask << BITMASK_AND_SHIFT) |
+ (OrMask << BITMASK_OR_SHIFT) |
+ (XorMask << BITMASK_XOR_SHIFT);
+}
+
+bool
+AMDGPUAsmParser::parseSwizzleOperands(const unsigned OpNum, int64_t* Op,
+ const unsigned MinVal,
+ const unsigned MaxVal,
+ const StringRef ErrMsg) {
+ for (unsigned i = 0; i < OpNum; ++i) {
+ if (!skipToken(AsmToken::Comma, "expected a comma")){
+ return false;
+ }
+ SMLoc ExprLoc = Parser.getTok().getLoc();
+ if (!parseExpr(Op[i])) {
+ return false;
+ }
+ if (Op[i] < MinVal || Op[i] > MaxVal) {
+ Error(ExprLoc, ErrMsg);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+AMDGPUAsmParser::parseSwizzleQuadPerm(int64_t &Imm) {
+ using namespace llvm::AMDGPU::Swizzle;
+
+ int64_t Lane[LANE_NUM];
+ if (parseSwizzleOperands(LANE_NUM, Lane, 0, LANE_MAX,
+ "expected a 2-bit lane id")) {
+ Imm = QUAD_PERM_ENC;
+ for (auto i = 0; i < LANE_NUM; ++i) {
+ Imm |= Lane[i] << (LANE_SHIFT * i);
+ }
+ return true;
+ }
+ return false;
+}
+
+bool
+AMDGPUAsmParser::parseSwizzleBroadcast(int64_t &Imm) {
+ using namespace llvm::AMDGPU::Swizzle;
+
+ SMLoc S = Parser.getTok().getLoc();
+ int64_t GroupSize;
+ int64_t LaneIdx;
+
+ if (!parseSwizzleOperands(1, &GroupSize,
+ 2, 32,
+ "group size must be in the interval [2,32]")) {
+ return false;
+ }
+ if (!isPowerOf2_64(GroupSize)) {
+ Error(S, "group size must be a power of two");
+ return false;
+ }
+ if (parseSwizzleOperands(1, &LaneIdx,
+ 0, GroupSize - 1,
+ "lane id must be in the interval [0,group size - 1]")) {
+ Imm = encodeBitmaskPerm(BITMASK_MAX - GroupSize + 1, LaneIdx, 0);
+ return true;
+ }
+ return false;
+}
+
+bool
+AMDGPUAsmParser::parseSwizzleReverse(int64_t &Imm) {
+ using namespace llvm::AMDGPU::Swizzle;
+
+ SMLoc S = Parser.getTok().getLoc();
+ int64_t GroupSize;
+
+ if (!parseSwizzleOperands(1, &GroupSize,
+ 2, 32, "group size must be in the interval [2,32]")) {
+ return false;
+ }
+ if (!isPowerOf2_64(GroupSize)) {
+ Error(S, "group size must be a power of two");
+ return false;
+ }
+
+ Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize - 1);
+ return true;
+}
+
+bool
+AMDGPUAsmParser::parseSwizzleSwap(int64_t &Imm) {
+ using namespace llvm::AMDGPU::Swizzle;
+
+ SMLoc S = Parser.getTok().getLoc();
+ int64_t GroupSize;
+
+ if (!parseSwizzleOperands(1, &GroupSize,
+ 1, 16, "group size must be in the interval [1,16]")) {
+ return false;
+ }
+ if (!isPowerOf2_64(GroupSize)) {
+ Error(S, "group size must be a power of two");
+ return false;
+ }
+
+ Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize);
+ return true;
+}
+
+bool
+AMDGPUAsmParser::parseSwizzleBitmaskPerm(int64_t &Imm) {
+ using namespace llvm::AMDGPU::Swizzle;
+
+ if (!skipToken(AsmToken::Comma, "expected a comma")) {
+ return false;
+ }
+
+ StringRef Ctl;
+ SMLoc StrLoc = Parser.getTok().getLoc();
+ if (!parseString(Ctl)) {
+ return false;
+ }
+ if (Ctl.size() != BITMASK_WIDTH) {
+ Error(StrLoc, "expected a 5-character mask");
+ return false;
+ }
+
+ unsigned AndMask = 0;
+ unsigned OrMask = 0;
+ unsigned XorMask = 0;
+
+ for (size_t i = 0; i < Ctl.size(); ++i) {
+ unsigned Mask = 1 << (BITMASK_WIDTH - 1 - i);
+ switch(Ctl[i]) {
+ default:
+ Error(StrLoc, "invalid mask");
+ return false;
+ case '0':
+ break;
+ case '1':
+ OrMask |= Mask;
+ break;
+ case 'p':
+ AndMask |= Mask;
+ break;
+ case 'i':
+ AndMask |= Mask;
+ XorMask |= Mask;
+ break;
+ }
+ }
+
+ Imm = encodeBitmaskPerm(AndMask, OrMask, XorMask);
+ return true;
+}
+
+bool
+AMDGPUAsmParser::parseSwizzleOffset(int64_t &Imm) {
+
+ SMLoc OffsetLoc = Parser.getTok().getLoc();
+
+ if (!parseExpr(Imm)) {
+ return false;
+ }
+ if (!isUInt<16>(Imm)) {
+ Error(OffsetLoc, "expected a 16-bit offset");
+ return false;
+ }
+ return true;
+}
+
+bool
+AMDGPUAsmParser::parseSwizzleMacro(int64_t &Imm) {
+ using namespace llvm::AMDGPU::Swizzle;
+
+ if (skipToken(AsmToken::LParen, "expected a left parentheses")) {
+
+ SMLoc ModeLoc = Parser.getTok().getLoc();
+ bool Ok = false;
+
+ if (trySkipId(IdSymbolic[ID_QUAD_PERM])) {
+ Ok = parseSwizzleQuadPerm(Imm);
+ } else if (trySkipId(IdSymbolic[ID_BITMASK_PERM])) {
+ Ok = parseSwizzleBitmaskPerm(Imm);
+ } else if (trySkipId(IdSymbolic[ID_BROADCAST])) {
+ Ok = parseSwizzleBroadcast(Imm);
+ } else if (trySkipId(IdSymbolic[ID_SWAP])) {
+ Ok = parseSwizzleSwap(Imm);
+ } else if (trySkipId(IdSymbolic[ID_REVERSE])) {
+ Ok = parseSwizzleReverse(Imm);
+ } else {
+ Error(ModeLoc, "expected a swizzle mode");
+ }
+
+ return Ok && skipToken(AsmToken::RParen, "expected a closing parentheses");
+ }
+
+ return false;
+}
+
+OperandMatchResultTy
+AMDGPUAsmParser::parseSwizzleOp(OperandVector &Operands) {
+ SMLoc S = Parser.getTok().getLoc();
+ int64_t Imm = 0;
+
+ if (trySkipId("offset")) {
+
+ bool Ok = false;
+ if (skipToken(AsmToken::Colon, "expected a colon")) {
+ if (trySkipId("swizzle")) {
+ Ok = parseSwizzleMacro(Imm);
+ } else {
+ Ok = parseSwizzleOffset(Imm);
+ }
+ }
+
+ Operands.push_back(AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTySwizzle));
+
+ return Ok? MatchOperand_Success : MatchOperand_ParseFail;
+ } else {
+ return MatchOperand_NoMatch;
+ }
+}
+
+bool
+AMDGPUOperand::isSwizzle() const {
+ return isImmTy(ImmTySwizzle);
+}
+
+//===----------------------------------------------------------------------===//
// sopp branch targets
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/AMDGPU/DSInstructions.td b/lib/Target/AMDGPU/DSInstructions.td
index 357e18108e7e..fc516c3b39c2 100644
--- a/lib/Target/AMDGPU/DSInstructions.td
+++ b/lib/Target/AMDGPU/DSInstructions.td
@@ -145,10 +145,10 @@ class DS_1A2D_Off8_RET<string opName,
let hasPostISelHook = 1;
}
-class DS_1A_RET<string opName, RegisterClass rc = VGPR_32>
+class DS_1A_RET<string opName, RegisterClass rc = VGPR_32, Operand ofs = offset>
: DS_Pseudo<opName,
(outs rc:$vdst),
- (ins VGPR_32:$addr, offset:$offset, gds:$gds),
+ (ins VGPR_32:$addr, ofs:$offset, gds:$gds),
"$vdst, $addr$offset$gds"> {
let has_data0 = 0;
@@ -440,7 +440,7 @@ def DS_WRITE_SRC2_B32 : DS_1A<"ds_write_src2_b32">;
def DS_WRITE_SRC2_B64 : DS_1A<"ds_write_src2_b64">;
let Uses = [EXEC], mayLoad = 0, mayStore = 0, isConvergent = 1 in {
-def DS_SWIZZLE_B32 : DS_1A_RET <"ds_swizzle_b32">;
+def DS_SWIZZLE_B32 : DS_1A_RET <"ds_swizzle_b32", VGPR_32, SwizzleImm>;
}
let mayStore = 0 in {
diff --git a/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp b/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp
index a817ff3cbaf0..523eea41897e 100644
--- a/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp
+++ b/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp
@@ -1160,6 +1160,112 @@ void AMDGPUInstPrinter::printSendMsg(const MCInst *MI, unsigned OpNo,
O << SImm16; // Unknown simm16 code.
}
+static void printSwizzleBitmask(const uint16_t AndMask,
+ const uint16_t OrMask,
+ const uint16_t XorMask,
+ raw_ostream &O) {
+ using namespace llvm::AMDGPU::Swizzle;
+
+ uint16_t Probe0 = ((0 & AndMask) | OrMask) ^ XorMask;
+ uint16_t Probe1 = ((BITMASK_MASK & AndMask) | OrMask) ^ XorMask;
+
+ O << "\"";
+
+ for (unsigned Mask = 1 << (BITMASK_WIDTH - 1); Mask > 0; Mask >>= 1) {
+ uint16_t p0 = Probe0 & Mask;
+ uint16_t p1 = Probe1 & Mask;
+
+ if (p0 == p1) {
+ if (p0 == 0) {
+ O << "0";
+ } else {
+ O << "1";
+ }
+ } else {
+ if (p0 == 0) {
+ O << "p";
+ } else {
+ O << "i";
+ }
+ }
+ }
+
+ O << "\"";
+}
+
+void AMDGPUInstPrinter::printSwizzle(const MCInst *MI, unsigned OpNo,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ using namespace llvm::AMDGPU::Swizzle;
+
+ uint16_t Imm = MI->getOperand(OpNo).getImm();
+ if (Imm == 0) {
+ return;
+ }
+
+ O << " offset:";
+
+ if ((Imm & QUAD_PERM_ENC_MASK) == QUAD_PERM_ENC) {
+
+ O << "swizzle(" << IdSymbolic[ID_QUAD_PERM];
+ for (auto i = 0; i < LANE_NUM; ++i) {
+ O << ",";
+ O << formatDec(Imm & LANE_MASK);
+ Imm >>= LANE_SHIFT;
+ }
+ O << ")";
+
+ } else if ((Imm & BITMASK_PERM_ENC_MASK) == BITMASK_PERM_ENC) {
+
+ uint16_t AndMask = (Imm >> BITMASK_AND_SHIFT) & BITMASK_MASK;
+ uint16_t OrMask = (Imm >> BITMASK_OR_SHIFT) & BITMASK_MASK;
+ uint16_t XorMask = (Imm >> BITMASK_XOR_SHIFT) & BITMASK_MASK;
+
+ if (AndMask == BITMASK_MAX &&
+ OrMask == 0 &&
+ countPopulation(XorMask) == 1) {
+
+ O << "swizzle(" << IdSymbolic[ID_SWAP];
+ O << ",";
+ O << formatDec(XorMask);
+ O << ")";
+
+ } else if (AndMask == BITMASK_MAX &&
+ OrMask == 0 && XorMask > 0 &&
+ isPowerOf2_64(XorMask + 1)) {
+
+ O << "swizzle(" << IdSymbolic[ID_REVERSE];
+ O << ",";
+ O << formatDec(XorMask + 1);
+ O << ")";
+
+ } else {
+
+ uint16_t GroupSize = BITMASK_MAX - AndMask + 1;
+ if (GroupSize > 1 &&
+ isPowerOf2_64(GroupSize) &&
+ OrMask < GroupSize &&
+ XorMask == 0) {
+
+ O << "swizzle(" << IdSymbolic[ID_BROADCAST];
+ O << ",";
+ O << formatDec(GroupSize);
+ O << ",";
+ O << formatDec(OrMask);
+ O << ")";
+
+ } else {
+ O << "swizzle(" << IdSymbolic[ID_BITMASK_PERM];
+ O << ",";
+ printSwizzleBitmask(AndMask, OrMask, XorMask, O);
+ O << ")";
+ }
+ }
+ } else {
+ printU16ImmDecOperand(MI, OpNo, O);
+ }
+}
+
void AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI,
raw_ostream &O) {
diff --git a/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h b/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h
index c0b8e5c51089..c8094c4b840a 100644
--- a/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h
+++ b/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.h
@@ -193,6 +193,8 @@ private:
raw_ostream &O);
void printSendMsg(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
raw_ostream &O);
+ void printSwizzle(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
+ raw_ostream &O);
void printWaitFlag(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI, raw_ostream &O);
void printHwreg(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
diff --git a/lib/Target/AMDGPU/SIDefines.h b/lib/Target/AMDGPU/SIDefines.h
index 80967edee0ab..5cd90323ff67 100644
--- a/lib/Target/AMDGPU/SIDefines.h
+++ b/lib/Target/AMDGPU/SIDefines.h
@@ -281,6 +281,46 @@ enum WidthMinusOne { // WidthMinusOne, (5) [15:11]
} // namespace Hwreg
+namespace Swizzle { // Encoding of swizzle macro used in ds_swizzle_b32.
+
+enum Id { // id of symbolic names
+ ID_QUAD_PERM = 0,
+ ID_BITMASK_PERM,
+ ID_SWAP,
+ ID_REVERSE,
+ ID_BROADCAST
+};
+
+enum EncBits {
+
+ // swizzle mode encodings
+
+ QUAD_PERM_ENC = 0x8000,
+ QUAD_PERM_ENC_MASK = 0xFF00,
+
+ BITMASK_PERM_ENC = 0x0000,
+ BITMASK_PERM_ENC_MASK = 0x8000,
+
+ // QUAD_PERM encodings
+
+ LANE_MASK = 0x3,
+ LANE_MAX = LANE_MASK,
+ LANE_SHIFT = 2,
+ LANE_NUM = 4,
+
+ // BITMASK_PERM encodings
+
+ BITMASK_MASK = 0x1F,
+ BITMASK_MAX = BITMASK_MASK,
+ BITMASK_WIDTH = 5,
+
+ BITMASK_AND_SHIFT = 0,
+ BITMASK_OR_SHIFT = 5,
+ BITMASK_XOR_SHIFT = 10
+};
+
+} // namespace Swizzle
+
namespace SDWA {
enum SdwaSel {
diff --git a/lib/Target/AMDGPU/SIInsertWaitcnts.cpp b/lib/Target/AMDGPU/SIInsertWaitcnts.cpp
index b5e3ce3dfe3e..e22166d03e9a 100644
--- a/lib/Target/AMDGPU/SIInsertWaitcnts.cpp
+++ b/lib/Target/AMDGPU/SIInsertWaitcnts.cpp
@@ -826,7 +826,8 @@ MachineInstr *SIInsertWaitcnts::generateSWaitCntInstBefore(
// NOTE: this could be improved with knowledge of all call sites or
// with knowledge of the called routines.
if (MI.getOpcode() == AMDGPU::RETURN ||
- MI.getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG) {
+ MI.getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG ||
+ MI.getOpcode() == AMDGPU::S_SETPC_B64_return) {
for (enum InstCounterType T = VM_CNT; T < NUM_INST_CNTS;
T = (enum InstCounterType)(T + 1)) {
if (ScoreBrackets->getScoreUB(T) > ScoreBrackets->getScoreLB(T)) {
@@ -1149,8 +1150,10 @@ void SIInsertWaitcnts::updateEventWaitCntAfter(
// instruction, update the upper-bound of the appropriate counter's
// bracket and the destination operand scores.
// TODO: Use the (TSFlags & SIInstrFlags::LGKM_CNT) property everywhere.
- if (TII->isDS(Inst) && (Inst.mayLoad() || Inst.mayStore())) {
- if (TII->getNamedOperand(Inst, AMDGPU::OpName::gds)->getImm() != 0) {
+ uint64_t TSFlags = Inst.getDesc().TSFlags;
+ if (TII->isDS(Inst) && (TSFlags & SIInstrFlags::LGKM_CNT)) {
+ if (TII->getNamedOperand(Inst, AMDGPU::OpName::gds) &&
+ TII->getNamedOperand(Inst, AMDGPU::OpName::gds)->getImm() != 0) {
ScoreBrackets->updateByEvent(TII, TRI, MRI, GDS_ACCESS, Inst);
ScoreBrackets->updateByEvent(TII, TRI, MRI, GDS_GPR_LOCK, Inst);
} else {
@@ -1183,7 +1186,7 @@ void SIInsertWaitcnts::updateEventWaitCntAfter(
Inst.getOpcode() != AMDGPU::BUFFER_WBINVL1_VOL) {
ScoreBrackets->updateByEvent(TII, TRI, MRI, VMEM_ACCESS, Inst);
if ( // TODO: assumed yes -- target_info->MemWriteNeedsExpWait() &&
- (Inst.mayStore() || AMDGPU::getAtomicNoRetOp(Inst.getOpcode()))) {
+ (Inst.mayStore() || AMDGPU::getAtomicNoRetOp(Inst.getOpcode()) != -1)) {
ScoreBrackets->updateByEvent(TII, TRI, MRI, VMW_GPR_LOCK, Inst);
}
} else if (TII->isSMRD(Inst)) {
@@ -1715,6 +1718,7 @@ bool SIInsertWaitcnts::runOnMachineFunction(MachineFunction &MF) {
MRI = &MF.getRegInfo();
MLI = &getAnalysis<MachineLoopInfo>();
IV = AMDGPU::IsaInfo::getIsaVersion(ST->getFeatureBits());
+ const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
AMDGPUASI = ST->getAMDGPUAS();
HardwareLimits.VmcntMax = AMDGPU::getVmcntBitMask(IV);
@@ -1859,5 +1863,19 @@ bool SIInsertWaitcnts::runOnMachineFunction(MachineFunction &MF) {
}
}
+ if (!MFI->isEntryFunction()) {
+ // Wait for any outstanding memory operations that the input registers may
+ // depend on. We can't track them and it's better to to the wait after the
+ // costly call sequence.
+
+ // TODO: Could insert earlier and schedule more liberally with operations
+ // that only use caller preserved registers.
+ MachineBasicBlock &EntryBB = MF.front();
+ BuildMI(EntryBB, EntryBB.getFirstNonPHI(), DebugLoc(), TII->get(AMDGPU::S_WAITCNT))
+ .addImm(0);
+
+ Modified = true;
+ }
+
return Modified;
}
diff --git a/lib/Target/AMDGPU/SIInstrInfo.td b/lib/Target/AMDGPU/SIInstrInfo.td
index c5287c7f64ba..445bf79a7814 100644
--- a/lib/Target/AMDGPU/SIInstrInfo.td
+++ b/lib/Target/AMDGPU/SIInstrInfo.td
@@ -383,6 +383,14 @@ def SendMsgMatchClass : AsmOperandClass {
let RenderMethod = "addImmOperands";
}
+def SwizzleMatchClass : AsmOperandClass {
+ let Name = "Swizzle";
+ let PredicateMethod = "isSwizzle";
+ let ParserMethod = "parseSwizzleOp";
+ let RenderMethod = "addImmOperands";
+ let IsOptional = 1;
+}
+
def ExpTgtMatchClass : AsmOperandClass {
let Name = "ExpTgt";
let PredicateMethod = "isExpTgt";
@@ -395,6 +403,11 @@ def SendMsgImm : Operand<i32> {
let ParserMatchClass = SendMsgMatchClass;
}
+def SwizzleImm : Operand<i16> {
+ let PrintMethod = "printSwizzle";
+ let ParserMatchClass = SwizzleMatchClass;
+}
+
def SWaitMatchClass : AsmOperandClass {
let Name = "SWaitCnt";
let RenderMethod = "addImmOperands";
diff --git a/lib/Target/AMDGPU/SIRegisterInfo.h b/lib/Target/AMDGPU/SIRegisterInfo.h
index b91cdddc5520..a648c178101a 100644
--- a/lib/Target/AMDGPU/SIRegisterInfo.h
+++ b/lib/Target/AMDGPU/SIRegisterInfo.h
@@ -66,6 +66,12 @@ public:
const uint32_t *getCallPreservedMask(const MachineFunction &MF,
CallingConv::ID) const override;
+ // Stack access is very expensive. CSRs are also the high registers, and we
+ // want to minimize the number of used registers.
+ unsigned getCSRFirstUseCost() const override {
+ return 100;
+ }
+
unsigned getFrameRegister(const MachineFunction &MF) const override;
bool requiresRegisterScavenging(const MachineFunction &Fn) const override;
diff --git a/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp b/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp
index b6868de6a74e..03b11ae80500 100644
--- a/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp
+++ b/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp
@@ -65,5 +65,18 @@ const char* const IdSymbolic[] = {
};
} // namespace Hwreg
+
+namespace Swizzle {
+
+// This must be in sync with llvm::AMDGPU::Swizzle::Id enum members, see SIDefines.h.
+const char* const IdSymbolic[] = {
+ "QUAD_PERM",
+ "BITMASK_PERM",
+ "SWAP",
+ "REVERSE",
+ "BROADCAST",
+};
+
+} // namespace Swizzle
} // namespace AMDGPU
} // namespace llvm
diff --git a/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.h b/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.h
index b2dc2c0e364c..ebb2be22b487 100644
--- a/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.h
+++ b/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.h
@@ -25,6 +25,12 @@ namespace Hwreg { // Symbolic names for the hwreg(...) syntax.
extern const char* const IdSymbolic[];
} // namespace Hwreg
+
+namespace Swizzle { // Symbolic names for the swizzle(...) syntax.
+
+extern const char* const IdSymbolic[];
+
+} // namespace Swizzle
} // namespace AMDGPU
} // namespace llvm
diff --git a/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/lib/Target/ARM/ARMExpandPseudoInsts.cpp
index 90baabcdb652..ec49f0d37af4 100644
--- a/lib/Target/ARM/ARMExpandPseudoInsts.cpp
+++ b/lib/Target/ARM/ARMExpandPseudoInsts.cpp
@@ -757,14 +757,9 @@ void ARMExpandPseudo::ExpandMOV32BitImm(MachineBasicBlock &MBB,
MI.eraseFromParent();
}
-static void addPostLoopLiveIns(MachineBasicBlock *MBB, LivePhysRegs &LiveRegs) {
- for (auto I = LiveRegs.begin(); I != LiveRegs.end(); ++I)
- MBB->addLiveIn(*I);
-}
-
/// Expand a CMP_SWAP pseudo-inst to an ldrex/strex loop as simply as
-/// possible. This only gets used at -O0 so we don't care about efficiency of the
-/// generated code.
+/// possible. This only gets used at -O0 so we don't care about efficiency of
+/// the generated code.
bool ARMExpandPseudo::ExpandCMP_SWAP(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
unsigned LdrexOp, unsigned StrexOp,
@@ -773,16 +768,15 @@ bool ARMExpandPseudo::ExpandCMP_SWAP(MachineBasicBlock &MBB,
bool IsThumb = STI->isThumb();
MachineInstr &MI = *MBBI;
DebugLoc DL = MI.getDebugLoc();
- MachineOperand &Dest = MI.getOperand(0);
+ const MachineOperand &Dest = MI.getOperand(0);
unsigned StatusReg = MI.getOperand(1).getReg();
- MachineOperand &Addr = MI.getOperand(2);
- MachineOperand &Desired = MI.getOperand(3);
- MachineOperand &New = MI.getOperand(4);
-
- LivePhysRegs LiveRegs(TII->getRegisterInfo());
- LiveRegs.addLiveOuts(MBB);
- for (auto I = std::prev(MBB.end()); I != MBBI; --I)
- LiveRegs.stepBackward(*I);
+ bool StatusDead = MI.getOperand(1).isDead();
+ // Duplicating undef operands into 2 instructions does not guarantee the same
+ // value on both; However undef should be replaced by xzr anyway.
+ assert(!MI.getOperand(2).isUndef() && "cannot handle undef");
+ unsigned AddrReg = MI.getOperand(2).getReg();
+ unsigned DesiredReg = MI.getOperand(3).getReg();
+ unsigned NewReg = MI.getOperand(4).getReg();
MachineFunction *MF = MBB.getParent();
auto LoadCmpBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
@@ -795,25 +789,35 @@ bool ARMExpandPseudo::ExpandCMP_SWAP(MachineBasicBlock &MBB,
if (UxtOp) {
MachineInstrBuilder MIB =
- BuildMI(MBB, MBBI, DL, TII->get(UxtOp), Desired.getReg())
- .addReg(Desired.getReg(), RegState::Kill);
+ BuildMI(MBB, MBBI, DL, TII->get(UxtOp), DesiredReg)
+ .addReg(DesiredReg, RegState::Kill);
if (!IsThumb)
MIB.addImm(0);
MIB.add(predOps(ARMCC::AL));
}
// .Lloadcmp:
+ // mov wStatus, #0
// ldrex rDest, [rAddr]
// cmp rDest, rDesired
// bne .Ldone
- LoadCmpBB->addLiveIn(Addr.getReg());
- LoadCmpBB->addLiveIn(Dest.getReg());
- LoadCmpBB->addLiveIn(Desired.getReg());
- addPostLoopLiveIns(LoadCmpBB, LiveRegs);
+ if (!StatusDead) {
+ if (IsThumb) {
+ BuildMI(LoadCmpBB, DL, TII->get(ARM::tMOVi8), StatusReg)
+ .addDef(ARM::CPSR, RegState::Dead)
+ .addImm(0)
+ .add(predOps(ARMCC::AL));
+ } else {
+ BuildMI(LoadCmpBB, DL, TII->get(ARM::MOVi), StatusReg)
+ .addImm(0)
+ .add(predOps(ARMCC::AL))
+ .add(condCodeOp());
+ }
+ }
MachineInstrBuilder MIB;
MIB = BuildMI(LoadCmpBB, DL, TII->get(LdrexOp), Dest.getReg());
- MIB.addReg(Addr.getReg());
+ MIB.addReg(AddrReg);
if (LdrexOp == ARM::t2LDREX)
MIB.addImm(0); // a 32-bit Thumb ldrex (only) allows an offset.
MIB.add(predOps(ARMCC::AL));
@@ -821,7 +825,7 @@ bool ARMExpandPseudo::ExpandCMP_SWAP(MachineBasicBlock &MBB,
unsigned CMPrr = IsThumb ? ARM::tCMPhir : ARM::CMPrr;
BuildMI(LoadCmpBB, DL, TII->get(CMPrr))
.addReg(Dest.getReg(), getKillRegState(Dest.isDead()))
- .add(Desired)
+ .addReg(DesiredReg)
.add(predOps(ARMCC::AL));
unsigned Bcc = IsThumb ? ARM::tBcc : ARM::Bcc;
BuildMI(LoadCmpBB, DL, TII->get(Bcc))
@@ -835,21 +839,16 @@ bool ARMExpandPseudo::ExpandCMP_SWAP(MachineBasicBlock &MBB,
// strex rStatus, rNew, [rAddr]
// cmp rStatus, #0
// bne .Lloadcmp
- StoreBB->addLiveIn(Addr.getReg());
- StoreBB->addLiveIn(New.getReg());
- addPostLoopLiveIns(StoreBB, LiveRegs);
-
-
- MIB = BuildMI(StoreBB, DL, TII->get(StrexOp), StatusReg);
- MIB.add(New);
- MIB.add(Addr);
+ MIB = BuildMI(StoreBB, DL, TII->get(StrexOp), StatusReg)
+ .addReg(NewReg)
+ .addReg(AddrReg);
if (StrexOp == ARM::t2STREX)
MIB.addImm(0); // a 32-bit Thumb strex (only) allows an offset.
MIB.add(predOps(ARMCC::AL));
unsigned CMPri = IsThumb ? ARM::t2CMPri : ARM::CMPri;
BuildMI(StoreBB, DL, TII->get(CMPri))
- .addReg(StatusReg, RegState::Kill)
+ .addReg(StatusReg, getKillRegState(StatusDead))
.addImm(0)
.add(predOps(ARMCC::AL));
BuildMI(StoreBB, DL, TII->get(Bcc))
@@ -861,12 +860,24 @@ bool ARMExpandPseudo::ExpandCMP_SWAP(MachineBasicBlock &MBB,
DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());
DoneBB->transferSuccessors(&MBB);
- addPostLoopLiveIns(DoneBB, LiveRegs);
MBB.addSuccessor(LoadCmpBB);
NextMBBI = MBB.end();
MI.eraseFromParent();
+
+ // Recompute livein lists.
+ const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
+ LivePhysRegs LiveRegs;
+ computeLiveIns(LiveRegs, MRI, *DoneBB);
+ computeLiveIns(LiveRegs, MRI, *StoreBB);
+ computeLiveIns(LiveRegs, MRI, *LoadCmpBB);
+ // Do an extra pass around the loop to get loop carried registers right.
+ StoreBB->clearLiveIns();
+ computeLiveIns(LiveRegs, MRI, *StoreBB);
+ LoadCmpBB->clearLiveIns();
+ computeLiveIns(LiveRegs, MRI, *LoadCmpBB);
+
return true;
}
@@ -894,19 +905,19 @@ bool ARMExpandPseudo::ExpandCMP_SWAP_64(MachineBasicBlock &MBB,
DebugLoc DL = MI.getDebugLoc();
MachineOperand &Dest = MI.getOperand(0);
unsigned StatusReg = MI.getOperand(1).getReg();
- MachineOperand &Addr = MI.getOperand(2);
- MachineOperand &Desired = MI.getOperand(3);
- MachineOperand &New = MI.getOperand(4);
+ bool StatusDead = MI.getOperand(1).isDead();
+ // Duplicating undef operands into 2 instructions does not guarantee the same
+ // value on both; However undef should be replaced by xzr anyway.
+ assert(!MI.getOperand(2).isUndef() && "cannot handle undef");
+ unsigned AddrReg = MI.getOperand(2).getReg();
+ unsigned DesiredReg = MI.getOperand(3).getReg();
+ MachineOperand New = MI.getOperand(4);
+ New.setIsKill(false);
unsigned DestLo = TRI->getSubReg(Dest.getReg(), ARM::gsub_0);
unsigned DestHi = TRI->getSubReg(Dest.getReg(), ARM::gsub_1);
- unsigned DesiredLo = TRI->getSubReg(Desired.getReg(), ARM::gsub_0);
- unsigned DesiredHi = TRI->getSubReg(Desired.getReg(), ARM::gsub_1);
-
- LivePhysRegs LiveRegs(TII->getRegisterInfo());
- LiveRegs.addLiveOuts(MBB);
- for (auto I = std::prev(MBB.end()); I != MBBI; --I)
- LiveRegs.stepBackward(*I);
+ unsigned DesiredLo = TRI->getSubReg(DesiredReg, ARM::gsub_0);
+ unsigned DesiredHi = TRI->getSubReg(DesiredReg, ARM::gsub_1);
MachineFunction *MF = MBB.getParent();
auto LoadCmpBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
@@ -922,26 +933,21 @@ bool ARMExpandPseudo::ExpandCMP_SWAP_64(MachineBasicBlock &MBB,
// cmp rDestLo, rDesiredLo
// sbcs rStatus<dead>, rDestHi, rDesiredHi
// bne .Ldone
- LoadCmpBB->addLiveIn(Addr.getReg());
- LoadCmpBB->addLiveIn(Dest.getReg());
- LoadCmpBB->addLiveIn(Desired.getReg());
- addPostLoopLiveIns(LoadCmpBB, LiveRegs);
-
unsigned LDREXD = IsThumb ? ARM::t2LDREXD : ARM::LDREXD;
MachineInstrBuilder MIB;
MIB = BuildMI(LoadCmpBB, DL, TII->get(LDREXD));
addExclusiveRegPair(MIB, Dest, RegState::Define, IsThumb, TRI);
- MIB.addReg(Addr.getReg()).add(predOps(ARMCC::AL));
+ MIB.addReg(AddrReg).add(predOps(ARMCC::AL));
unsigned CMPrr = IsThumb ? ARM::tCMPhir : ARM::CMPrr;
BuildMI(LoadCmpBB, DL, TII->get(CMPrr))
.addReg(DestLo, getKillRegState(Dest.isDead()))
- .addReg(DesiredLo, getKillRegState(Desired.isDead()))
+ .addReg(DesiredLo)
.add(predOps(ARMCC::AL));
BuildMI(LoadCmpBB, DL, TII->get(CMPrr))
.addReg(DestHi, getKillRegState(Dest.isDead()))
- .addReg(DesiredHi, getKillRegState(Desired.isDead()))
+ .addReg(DesiredHi)
.addImm(ARMCC::EQ).addReg(ARM::CPSR, RegState::Kill);
unsigned Bcc = IsThumb ? ARM::tBcc : ARM::Bcc;
@@ -956,18 +962,14 @@ bool ARMExpandPseudo::ExpandCMP_SWAP_64(MachineBasicBlock &MBB,
// strexd rStatus, rNewLo, rNewHi, [rAddr]
// cmp rStatus, #0
// bne .Lloadcmp
- StoreBB->addLiveIn(Addr.getReg());
- StoreBB->addLiveIn(New.getReg());
- addPostLoopLiveIns(StoreBB, LiveRegs);
-
unsigned STREXD = IsThumb ? ARM::t2STREXD : ARM::STREXD;
MIB = BuildMI(StoreBB, DL, TII->get(STREXD), StatusReg);
addExclusiveRegPair(MIB, New, 0, IsThumb, TRI);
- MIB.add(Addr).add(predOps(ARMCC::AL));
+ MIB.addReg(AddrReg).add(predOps(ARMCC::AL));
unsigned CMPri = IsThumb ? ARM::t2CMPri : ARM::CMPri;
BuildMI(StoreBB, DL, TII->get(CMPri))
- .addReg(StatusReg, RegState::Kill)
+ .addReg(StatusReg, getKillRegState(StatusDead))
.addImm(0)
.add(predOps(ARMCC::AL));
BuildMI(StoreBB, DL, TII->get(Bcc))
@@ -979,12 +981,24 @@ bool ARMExpandPseudo::ExpandCMP_SWAP_64(MachineBasicBlock &MBB,
DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());
DoneBB->transferSuccessors(&MBB);
- addPostLoopLiveIns(DoneBB, LiveRegs);
MBB.addSuccessor(LoadCmpBB);
NextMBBI = MBB.end();
MI.eraseFromParent();
+
+ // Recompute livein lists.
+ const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
+ LivePhysRegs LiveRegs;
+ computeLiveIns(LiveRegs, MRI, *DoneBB);
+ computeLiveIns(LiveRegs, MRI, *StoreBB);
+ computeLiveIns(LiveRegs, MRI, *LoadCmpBB);
+ // Do an extra pass around the loop to get loop carried registers right.
+ StoreBB->clearLiveIns();
+ computeLiveIns(LiveRegs, MRI, *StoreBB);
+ LoadCmpBB->clearLiveIns();
+ computeLiveIns(LiveRegs, MRI, *LoadCmpBB);
+
return true;
}
diff --git a/lib/Target/ARM/ARMFrameLowering.cpp b/lib/Target/ARM/ARMFrameLowering.cpp
index 4f7a0ab4e220..c2b2502843c0 100644
--- a/lib/Target/ARM/ARMFrameLowering.cpp
+++ b/lib/Target/ARM/ARMFrameLowering.cpp
@@ -968,8 +968,9 @@ void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB,
if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
continue;
- bool isLiveIn = MF.getRegInfo().isLiveIn(Reg);
- if (!isLiveIn)
+ const MachineRegisterInfo &MRI = MF.getRegInfo();
+ bool isLiveIn = MRI.isLiveIn(Reg);
+ if (!isLiveIn && !MRI.isReserved(Reg))
MBB.addLiveIn(Reg);
// If NoGap is true, push consecutive registers and then leave the rest
// for other instructions. e.g.
diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td
index bee83dfb6f63..423f97ccacd6 100644
--- a/lib/Target/ARM/ARMInstrThumb.td
+++ b/lib/Target/ARM/ARMInstrThumb.td
@@ -1413,7 +1413,8 @@ def tLEApcrelJT : tPseudoInst<(outs tGPR:$Rd),
// Thumb-1 doesn't have the TBB or TBH instructions, but we can synthesize them
// and make use of the same compressed jump table format as Thumb-2.
-let Size = 2 in {
+let Size = 2, isBranch = 1, isTerminator = 1, isBarrier = 1,
+ isIndirectBranch = 1 in {
def tTBB_JT : tPseudoInst<(outs),
(ins tGPR:$base, tGPR:$index, i32imm:$jt, i32imm:$pclbl), 0, IIC_Br, []>,
Sched<[WriteBr]>;
diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td
index bf3d820e7b7d..45471a4e95b3 100644
--- a/lib/Target/ARM/ARMInstrThumb2.td
+++ b/lib/Target/ARM/ARMInstrThumb2.td
@@ -3494,7 +3494,8 @@ def t2B : T2I<(outs), (ins thumb_br_target:$target), IIC_Br,
let AsmMatchConverter = "cvtThumbBranches";
}
-let Size = 4, isNotDuplicable = 1, isIndirectBranch = 1 in {
+let Size = 4, isNotDuplicable = 1, isBranch = 1, isTerminator = 1,
+ isBarrier = 1, isIndirectBranch = 1 in {
// available in both v8-M.Baseline and Thumb2 targets
def t2BR_JT : t2basePseudoInst<(outs),
diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp
index c4f23c66e4ea..f5e4043882ff 100644
--- a/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/lib/Target/ARM/ARMTargetMachine.cpp
@@ -382,7 +382,7 @@ namespace {
/// ARM Code Generator Pass Configuration Options.
class ARMPassConfig : public TargetPassConfig {
public:
- ARMPassConfig(ARMBaseTargetMachine *TM, PassManagerBase &PM)
+ ARMPassConfig(ARMBaseTargetMachine &TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {}
ARMBaseTargetMachine &getARMTargetMachine() const {
@@ -419,7 +419,7 @@ INITIALIZE_PASS(ARMExecutionDepsFix, "arm-execution-deps-fix",
"ARM Execution Dependency Fix", false, false)
TargetPassConfig *ARMBaseTargetMachine::createPassConfig(PassManagerBase &PM) {
- return new ARMPassConfig(this, PM);
+ return new ARMPassConfig(*this, PM);
}
void ARMPassConfig::addIRPasses() {
diff --git a/lib/Target/ARM/ARMTargetMachine.h b/lib/Target/ARM/ARMTargetMachine.h
index e5eb27114c72..2fcee73228fe 100644
--- a/lib/Target/ARM/ARMTargetMachine.h
+++ b/lib/Target/ARM/ARMTargetMachine.h
@@ -60,6 +60,10 @@ public:
TargetLoweringObjectFile *getObjFileLowering() const override {
return TLOF.get();
}
+
+ bool isMachineVerifierClean() const override {
+ return false;
+ }
};
/// ARM/Thumb little endian target machine.
diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
index 40bf545e8322..b0d1d3fb9ef0 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
@@ -729,6 +729,15 @@ void ARMAsmBackend::processFixupValue(const MCAssembler &Asm,
// linker can handle it. GNU AS produces an error in this case.
if (Sym->isExternal() || Value >= 0x400004)
IsResolved = false;
+ // When an ARM function is called from a Thumb function, produce a
+ // relocation so the linker will use the correct branch instruction for ELF
+ // binaries.
+ if (Sym->isELF()) {
+ unsigned Type = dyn_cast<MCSymbolELF>(Sym)->getType();
+ if ((Type == ELF::STT_FUNC || Type == ELF::STT_GNU_IFUNC) &&
+ !Asm.isThumbFunc(Sym))
+ IsResolved = false;
+ }
}
// We must always generate a relocation for BL/BLX instructions if we have
// a symbol to reference, as the linker relies on knowing the destination
diff --git a/lib/Target/ARM/Thumb1FrameLowering.cpp b/lib/Target/ARM/Thumb1FrameLowering.cpp
index f917c35b9ceb..f10427e2ed57 100644
--- a/lib/Target/ARM/Thumb1FrameLowering.cpp
+++ b/lib/Target/ARM/Thumb1FrameLowering.cpp
@@ -698,13 +698,14 @@ spillCalleeSavedRegisters(MachineBasicBlock &MBB,
CopyRegs.insert(ArgReg);
// Push the low registers and lr
+ const MachineRegisterInfo &MRI = MF.getRegInfo();
if (!LoRegsToSave.empty()) {
MachineInstrBuilder MIB =
BuildMI(MBB, MI, DL, TII.get(ARM::tPUSH)).add(predOps(ARMCC::AL));
for (unsigned Reg : {ARM::R4, ARM::R5, ARM::R6, ARM::R7, ARM::LR}) {
if (LoRegsToSave.count(Reg)) {
- bool isKill = !MF.getRegInfo().isLiveIn(Reg);
- if (isKill)
+ bool isKill = !MRI.isLiveIn(Reg);
+ if (isKill && !MRI.isReserved(Reg))
MBB.addLiveIn(Reg);
MIB.addReg(Reg, getKillRegState(isKill));
@@ -746,8 +747,8 @@ spillCalleeSavedRegisters(MachineBasicBlock &MBB,
SmallVector<unsigned, 4> RegsToPush;
while (HiRegToSave != AllHighRegsEnd && CopyReg != AllCopyRegsEnd) {
if (HiRegsToSave.count(*HiRegToSave)) {
- bool isKill = !MF.getRegInfo().isLiveIn(*HiRegToSave);
- if (isKill)
+ bool isKill = !MRI.isLiveIn(*HiRegToSave);
+ if (isKill && !MRI.isReserved(*HiRegToSave))
MBB.addLiveIn(*HiRegToSave);
// Emit a MOV from the high reg to the low reg.
diff --git a/lib/Target/AVR/AVRISelLowering.cpp b/lib/Target/AVR/AVRISelLowering.cpp
index ef9c00e4b784..7d3faac1dcc2 100644
--- a/lib/Target/AVR/AVRISelLowering.cpp
+++ b/lib/Target/AVR/AVRISelLowering.cpp
@@ -1500,9 +1500,9 @@ MachineBasicBlock *AVRTargetLowering::insertShift(MachineInstr &MI,
unsigned DstReg = MI.getOperand(0).getReg();
// BB:
- // cp 0, N
+ // cpi N, 0
// breq RemBB
- BuildMI(BB, dl, TII.get(AVR::CPRdRr)).addReg(ShiftAmtSrcReg).addReg(AVR::R0);
+ BuildMI(BB, dl, TII.get(AVR::CPIRdK)).addReg(ShiftAmtSrcReg).addImm(0);
BuildMI(BB, dl, TII.get(AVR::BREQk)).addMBB(RemBB);
// LoopBB:
diff --git a/lib/Target/AVR/AVRInstrInfo.td b/lib/Target/AVR/AVRInstrInfo.td
index f10ca394f36c..5dd8b2c27b21 100644
--- a/lib/Target/AVR/AVRInstrInfo.td
+++ b/lib/Target/AVR/AVRInstrInfo.td
@@ -904,7 +904,7 @@ let Defs = [SREG] in
// Compares a register with an 8 bit immediate.
def CPIRdK : FRdK<0b0011,
(outs),
- (ins GPR8:$rd, imm_ldi8:$k),
+ (ins LD8:$rd, imm_ldi8:$k),
"cpi\t$rd, $k",
[(AVRcmp i8:$rd, imm:$k), (implicit SREG)]>;
}
diff --git a/lib/Target/AVR/AVRTargetMachine.cpp b/lib/Target/AVR/AVRTargetMachine.cpp
index fb3262916b4f..2ab0b1080c6a 100644
--- a/lib/Target/AVR/AVRTargetMachine.cpp
+++ b/lib/Target/AVR/AVRTargetMachine.cpp
@@ -57,7 +57,7 @@ namespace {
/// AVR Code Generator Pass Configuration Options.
class AVRPassConfig : public TargetPassConfig {
public:
- AVRPassConfig(AVRTargetMachine *TM, PassManagerBase &PM)
+ AVRPassConfig(AVRTargetMachine &TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {}
AVRTargetMachine &getAVRTargetMachine() const {
@@ -71,7 +71,7 @@ public:
} // namespace
TargetPassConfig *AVRTargetMachine::createPassConfig(PassManagerBase &PM) {
- return new AVRPassConfig(this, PM);
+ return new AVRPassConfig(*this, PM);
}
extern "C" void LLVMInitializeAVRTarget() {
diff --git a/lib/Target/AVR/AVRTargetMachine.h b/lib/Target/AVR/AVRTargetMachine.h
index 10345193d14a..795e94e6af03 100644
--- a/lib/Target/AVR/AVRTargetMachine.h
+++ b/lib/Target/AVR/AVRTargetMachine.h
@@ -41,6 +41,10 @@ public:
TargetPassConfig *createPassConfig(PassManagerBase &PM) override;
+ bool isMachineVerifierClean() const override {
+ return false;
+ }
+
private:
std::unique_ptr<TargetLoweringObjectFile> TLOF;
AVRSubtarget SubTarget;
diff --git a/lib/Target/BPF/BPFTargetMachine.cpp b/lib/Target/BPF/BPFTargetMachine.cpp
index 897695633e46..cf8e73540904 100644
--- a/lib/Target/BPF/BPFTargetMachine.cpp
+++ b/lib/Target/BPF/BPFTargetMachine.cpp
@@ -58,7 +58,7 @@ namespace {
// BPF Code Generator Pass Configuration Options.
class BPFPassConfig : public TargetPassConfig {
public:
- BPFPassConfig(BPFTargetMachine *TM, PassManagerBase &PM)
+ BPFPassConfig(BPFTargetMachine &TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {}
BPFTargetMachine &getBPFTargetMachine() const {
@@ -70,7 +70,7 @@ public:
}
TargetPassConfig *BPFTargetMachine::createPassConfig(PassManagerBase &PM) {
- return new BPFPassConfig(this, PM);
+ return new BPFPassConfig(*this, PM);
}
// Install an instruction selector pass using
diff --git a/lib/Target/BPF/CMakeLists.txt b/lib/Target/BPF/CMakeLists.txt
index e2654b0465df..4918653ff19d 100644
--- a/lib/Target/BPF/CMakeLists.txt
+++ b/lib/Target/BPF/CMakeLists.txt
@@ -4,7 +4,7 @@ tablegen(LLVM BPFGenRegisterInfo.inc -gen-register-info)
tablegen(LLVM BPFGenInstrInfo.inc -gen-instr-info)
tablegen(LLVM BPFGenDisassemblerTables.inc -gen-disassembler)
tablegen(LLVM BPFGenAsmWriter.inc -gen-asm-writer)
-tablegen(LLVM X86GenAsmMatcher.inc -gen-asm-matcher)
+tablegen(LLVM BPFGenAsmMatcher.inc -gen-asm-matcher)
tablegen(LLVM BPFGenDAGISel.inc -gen-dag-isel)
tablegen(LLVM BPFGenMCCodeEmitter.inc -gen-emitter)
tablegen(LLVM BPFGenCallingConv.inc -gen-callingconv)
diff --git a/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
index 8e10c521a77d..e4434136bf86 100644
--- a/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
+++ b/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
@@ -71,6 +71,9 @@ public:
return true;
}
+ bool ComplexPatternFuncMutatesDAG() const override {
+ return true;
+ }
void PreprocessISelDAG() override;
void EmitFunctionEntryCode() override;
@@ -81,6 +84,7 @@ public:
inline bool SelectAddrGP(SDValue &N, SDValue &R);
bool SelectGlobalAddress(SDValue &N, SDValue &R, bool UseGP);
bool SelectAddrFI(SDValue &N, SDValue &R);
+ bool DetectUseSxtw(SDValue &N, SDValue &R);
StringRef getPassName() const override {
return "Hexagon DAG->DAG Pattern Instruction Selection";
@@ -106,7 +110,6 @@ public:
void SelectIndexedStore(StoreSDNode *ST, const SDLoc &dl);
void SelectStore(SDNode *N);
void SelectSHL(SDNode *N);
- void SelectMul(SDNode *N);
void SelectZeroExtend(SDNode *N);
void SelectIntrinsicWChain(SDNode *N);
void SelectIntrinsicWOChain(SDNode *N);
@@ -118,7 +121,7 @@ public:
#include "HexagonGenDAGISel.inc"
private:
- bool isValueExtension(const SDValue &Val, unsigned FromBits, SDValue &Src);
+ bool keepsLowBits(const SDValue &Val, unsigned NumBits, SDValue &Src);
bool isOrEquivalentToAdd(const SDNode *N) const;
bool isAlignedMemNode(const MemSDNode *N) const;
bool isPositiveHalfWord(const SDNode *N) const;
@@ -597,90 +600,6 @@ void HexagonDAGToDAGISel::SelectStore(SDNode *N) {
SelectCode(ST);
}
-void HexagonDAGToDAGISel::SelectMul(SDNode *N) {
- SDLoc dl(N);
-
- // %conv.i = sext i32 %tmp1 to i64
- // %conv2.i = sext i32 %add to i64
- // %mul.i = mul nsw i64 %conv2.i, %conv.i
- //
- // --- match with the following ---
- //
- // %mul.i = mpy (%tmp1, %add)
- //
-
- if (N->getValueType(0) == MVT::i64) {
- // Shifting a i64 signed multiply.
- SDValue MulOp0 = N->getOperand(0);
- SDValue MulOp1 = N->getOperand(1);
-
- SDValue OP0;
- SDValue OP1;
-
- // Handle sign_extend and sextload.
- if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
- SDValue Sext0 = MulOp0.getOperand(0);
- if (Sext0.getNode()->getValueType(0) != MVT::i32) {
- SelectCode(N);
- return;
- }
- OP0 = Sext0;
- } else if (MulOp0.getOpcode() == ISD::LOAD) {
- LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode());
- if (LD->getMemoryVT() != MVT::i32 ||
- LD->getExtensionType() != ISD::SEXTLOAD ||
- LD->getAddressingMode() != ISD::UNINDEXED) {
- SelectCode(N);
- return;
- }
- SDValue Chain = LD->getChain();
- SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
- OP0 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
- MVT::Other,
- LD->getBasePtr(), TargetConst0,
- Chain), 0);
- } else {
- SelectCode(N);
- return;
- }
-
- // Same goes for the second operand.
- if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) {
- SDValue Sext1 = MulOp1.getOperand(0);
- if (Sext1.getNode()->getValueType(0) != MVT::i32) {
- SelectCode(N);
- return;
- }
- OP1 = Sext1;
- } else if (MulOp1.getOpcode() == ISD::LOAD) {
- LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode());
- if (LD->getMemoryVT() != MVT::i32 ||
- LD->getExtensionType() != ISD::SEXTLOAD ||
- LD->getAddressingMode() != ISD::UNINDEXED) {
- SelectCode(N);
- return;
- }
- SDValue Chain = LD->getChain();
- SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
- OP1 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32,
- MVT::Other,
- LD->getBasePtr(), TargetConst0,
- Chain), 0);
- } else {
- SelectCode(N);
- return;
- }
-
- // Generate a mpy instruction.
- SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_dpmpyss_s0, dl,
- MVT::i64, OP0, OP1);
- ReplaceNode(N, Result);
- return;
- }
-
- SelectCode(N);
-}
-
void HexagonDAGToDAGISel::SelectSHL(SDNode *N) {
SDLoc dl(N);
SDValue Shl_0 = N->getOperand(0);
@@ -843,7 +762,7 @@ void HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) {
SDValue V = N->getOperand(1);
SDValue U;
- if (isValueExtension(V, Bits, U)) {
+ if (keepsLowBits(V, Bits, U)) {
SDValue R = CurDAG->getNode(N->getOpcode(), SDLoc(N), N->getValueType(0),
N->getOperand(0), U);
ReplaceNode(N, R.getNode());
@@ -949,7 +868,6 @@ void HexagonDAGToDAGISel::Select(SDNode *N) {
case ISD::SHL: return SelectSHL(N);
case ISD::LOAD: return SelectLoad(N);
case ISD::STORE: return SelectStore(N);
- case ISD::MUL: return SelectMul(N);
case ISD::ZERO_EXTEND: return SelectZeroExtend(N);
case ISD::INTRINSIC_W_CHAIN: return SelectIntrinsicWChain(N);
case ISD::INTRINSIC_WO_CHAIN: return SelectIntrinsicWOChain(N);
@@ -1327,7 +1245,7 @@ void HexagonDAGToDAGISel::EmitFunctionEntryCode() {
}
// Match a frame index that can be used in an addressing mode.
-bool HexagonDAGToDAGISel::SelectAddrFI(SDValue& N, SDValue &R) {
+bool HexagonDAGToDAGISel::SelectAddrFI(SDValue &N, SDValue &R) {
if (N.getOpcode() != ISD::FrameIndex)
return false;
auto &HFI = *HST->getFrameLowering();
@@ -1388,16 +1306,83 @@ bool HexagonDAGToDAGISel::SelectGlobalAddress(SDValue &N, SDValue &R,
return false;
}
-bool HexagonDAGToDAGISel::isValueExtension(const SDValue &Val,
- unsigned FromBits, SDValue &Src) {
+bool HexagonDAGToDAGISel::DetectUseSxtw(SDValue &N, SDValue &R) {
+ // This (complex pattern) function is meant to detect a sign-extension
+ // i32->i64 on a per-operand basis. This would allow writing single
+ // patterns that would cover a number of combinations of different ways
+ // a sign-extensions could be written. For example:
+ // (mul (DetectUseSxtw x) (DetectUseSxtw y)) -> (M2_dpmpyss_s0 x y)
+ // could match either one of these:
+ // (mul (sext x) (sext_inreg y))
+ // (mul (sext-load *p) (sext_inreg y))
+ // (mul (sext_inreg x) (sext y))
+ // etc.
+ //
+ // The returned value will have type i64 and its low word will
+ // contain the value being extended. The high bits are not specified.
+ // The returned type is i64 because the original type of N was i64,
+ // but the users of this function should only use the low-word of the
+ // result, e.g.
+ // (mul sxtw:x, sxtw:y) -> (M2_dpmpyss_s0 (LoReg sxtw:x), (LoReg sxtw:y))
+
+ if (N.getValueType() != MVT::i64)
+ return false;
+ EVT SrcVT;
+ unsigned Opc = N.getOpcode();
+ switch (Opc) {
+ case ISD::SIGN_EXTEND:
+ case ISD::SIGN_EXTEND_INREG: {
+ // sext_inreg has the source type as a separate operand.
+ EVT T = Opc == ISD::SIGN_EXTEND
+ ? N.getOperand(0).getValueType()
+ : cast<VTSDNode>(N.getOperand(1))->getVT();
+ if (T.getSizeInBits() != 32)
+ return false;
+ R = N.getOperand(0);
+ break;
+ }
+ case ISD::LOAD: {
+ LoadSDNode *L = cast<LoadSDNode>(N);
+ if (L->getExtensionType() != ISD::SEXTLOAD)
+ return false;
+ // All extending loads extend to i32, so even if the value in
+ // memory is shorter than 32 bits, it will be i32 after the load.
+ if (L->getMemoryVT().getSizeInBits() > 32)
+ return false;
+ R = N;
+ break;
+ }
+ default:
+ return false;
+ }
+ EVT RT = R.getValueType();
+ if (RT == MVT::i64)
+ return true;
+ assert(RT == MVT::i32);
+ // This is only to produce a value of type i64. Do not rely on the
+ // high bits produced by this.
+ const SDLoc &dl(N);
+ SDValue Ops[] = {
+ CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID, dl, MVT::i32),
+ R, CurDAG->getTargetConstant(Hexagon::isub_hi, dl, MVT::i32),
+ R, CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32)
+ };
+ SDNode *T = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl,
+ MVT::i64, Ops);
+ R = SDValue(T, 0);
+ return true;
+}
+
+bool HexagonDAGToDAGISel::keepsLowBits(const SDValue &Val, unsigned NumBits,
+ SDValue &Src) {
unsigned Opc = Val.getOpcode();
switch (Opc) {
case ISD::SIGN_EXTEND:
case ISD::ZERO_EXTEND:
case ISD::ANY_EXTEND: {
- SDValue const &Op0 = Val.getOperand(0);
+ const SDValue &Op0 = Val.getOperand(0);
EVT T = Op0.getValueType();
- if (T.isInteger() && T.getSizeInBits() == FromBits) {
+ if (T.isInteger() && T.getSizeInBits() == NumBits) {
Src = Op0;
return true;
}
@@ -1408,23 +1393,23 @@ bool HexagonDAGToDAGISel::isValueExtension(const SDValue &Val,
case ISD::AssertZext:
if (Val.getOperand(0).getValueType().isInteger()) {
VTSDNode *T = cast<VTSDNode>(Val.getOperand(1));
- if (T->getVT().getSizeInBits() == FromBits) {
+ if (T->getVT().getSizeInBits() == NumBits) {
Src = Val.getOperand(0);
return true;
}
}
break;
case ISD::AND: {
- // Check if this is an AND with "FromBits" of lower bits set to 1.
- uint64_t FromMask = (1 << FromBits) - 1;
+ // Check if this is an AND with NumBits of lower bits set to 1.
+ uint64_t Mask = (1 << NumBits) - 1;
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
- if (C->getZExtValue() == FromMask) {
+ if (C->getZExtValue() == Mask) {
Src = Val.getOperand(1);
return true;
}
}
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
- if (C->getZExtValue() == FromMask) {
+ if (C->getZExtValue() == Mask) {
Src = Val.getOperand(0);
return true;
}
@@ -1433,16 +1418,16 @@ bool HexagonDAGToDAGISel::isValueExtension(const SDValue &Val,
}
case ISD::OR:
case ISD::XOR: {
- // OR/XOR with the lower "FromBits" bits set to 0.
- uint64_t FromMask = (1 << FromBits) - 1;
+ // OR/XOR with the lower NumBits bits set to 0.
+ uint64_t Mask = (1 << NumBits) - 1;
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) {
- if ((C->getZExtValue() & FromMask) == 0) {
+ if ((C->getZExtValue() & Mask) == 0) {
Src = Val.getOperand(1);
return true;
}
}
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) {
- if ((C->getZExtValue() & FromMask) == 0) {
+ if ((C->getZExtValue() & Mask) == 0) {
Src = Val.getOperand(0);
return true;
}
diff --git a/lib/Target/Hexagon/HexagonISelLowering.cpp b/lib/Target/Hexagon/HexagonISelLowering.cpp
index 5ecf9320d5c2..4c6c6eeafbe0 100644
--- a/lib/Target/Hexagon/HexagonISelLowering.cpp
+++ b/lib/Target/Hexagon/HexagonISelLowering.cpp
@@ -1928,11 +1928,7 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::BITREVERSE, MVT::i64, Legal);
setOperationAction(ISD::BSWAP, MVT::i32, Legal);
setOperationAction(ISD::BSWAP, MVT::i64, Legal);
-
- // We custom lower i64 to i64 mul, so that it is not considered as a legal
- // operation. There is a pattern that will match i64 mul and transform it
- // to a series of instructions.
- setOperationAction(ISD::MUL, MVT::i64, Expand);
+ setOperationAction(ISD::MUL, MVT::i64, Legal);
for (unsigned IntExpOp :
{ ISD::SDIV, ISD::UDIV, ISD::SREM, ISD::UREM,
diff --git a/lib/Target/Hexagon/HexagonInstrInfo.cpp b/lib/Target/Hexagon/HexagonInstrInfo.cpp
index 66e07c67958e..0fef91ec4d3e 100644
--- a/lib/Target/Hexagon/HexagonInstrInfo.cpp
+++ b/lib/Target/Hexagon/HexagonInstrInfo.cpp
@@ -1769,161 +1769,6 @@ bool HexagonInstrInfo::isCompoundBranchInstr(const MachineInstr &MI) const {
return getType(MI) == HexagonII::TypeCJ && MI.isBranch();
}
-bool HexagonInstrInfo::isCondInst(const MachineInstr &MI) const {
- return (MI.isBranch() && isPredicated(MI)) ||
- isConditionalTransfer(MI) ||
- isConditionalALU32(MI) ||
- isConditionalLoad(MI) ||
- // Predicated stores which don't have a .new on any operands.
- (MI.mayStore() && isPredicated(MI) && !isNewValueStore(MI) &&
- !isPredicatedNew(MI));
-}
-
-bool HexagonInstrInfo::isConditionalALU32(const MachineInstr &MI) const {
- switch (MI.getOpcode()) {
- case Hexagon::A2_paddf:
- case Hexagon::A2_paddfnew:
- case Hexagon::A2_paddif:
- case Hexagon::A2_paddifnew:
- case Hexagon::A2_paddit:
- case Hexagon::A2_padditnew:
- case Hexagon::A2_paddt:
- case Hexagon::A2_paddtnew:
- case Hexagon::A2_pandf:
- case Hexagon::A2_pandfnew:
- case Hexagon::A2_pandt:
- case Hexagon::A2_pandtnew:
- case Hexagon::A2_porf:
- case Hexagon::A2_porfnew:
- case Hexagon::A2_port:
- case Hexagon::A2_portnew:
- case Hexagon::A2_psubf:
- case Hexagon::A2_psubfnew:
- case Hexagon::A2_psubt:
- case Hexagon::A2_psubtnew:
- case Hexagon::A2_pxorf:
- case Hexagon::A2_pxorfnew:
- case Hexagon::A2_pxort:
- case Hexagon::A2_pxortnew:
- case Hexagon::A4_paslhf:
- case Hexagon::A4_paslhfnew:
- case Hexagon::A4_paslht:
- case Hexagon::A4_paslhtnew:
- case Hexagon::A4_pasrhf:
- case Hexagon::A4_pasrhfnew:
- case Hexagon::A4_pasrht:
- case Hexagon::A4_pasrhtnew:
- case Hexagon::A4_psxtbf:
- case Hexagon::A4_psxtbfnew:
- case Hexagon::A4_psxtbt:
- case Hexagon::A4_psxtbtnew:
- case Hexagon::A4_psxthf:
- case Hexagon::A4_psxthfnew:
- case Hexagon::A4_psxtht:
- case Hexagon::A4_psxthtnew:
- case Hexagon::A4_pzxtbf:
- case Hexagon::A4_pzxtbfnew:
- case Hexagon::A4_pzxtbt:
- case Hexagon::A4_pzxtbtnew:
- case Hexagon::A4_pzxthf:
- case Hexagon::A4_pzxthfnew:
- case Hexagon::A4_pzxtht:
- case Hexagon::A4_pzxthtnew:
- case Hexagon::C2_ccombinewf:
- case Hexagon::C2_ccombinewt:
- return true;
- }
- return false;
-}
-
-// FIXME - Function name and it's functionality don't match.
-// It should be renamed to hasPredNewOpcode()
-bool HexagonInstrInfo::isConditionalLoad(const MachineInstr &MI) const {
- if (!MI.getDesc().mayLoad() || !isPredicated(MI))
- return false;
-
- int PNewOpcode = Hexagon::getPredNewOpcode(MI.getOpcode());
- // Instruction with valid predicated-new opcode can be promoted to .new.
- return PNewOpcode >= 0;
-}
-
-// Returns true if an instruction is a conditional store.
-//
-// Note: It doesn't include conditional new-value stores as they can't be
-// converted to .new predicate.
-bool HexagonInstrInfo::isConditionalStore(const MachineInstr &MI) const {
- switch (MI.getOpcode()) {
- default: return false;
- case Hexagon::S4_storeirbt_io:
- case Hexagon::S4_storeirbf_io:
- case Hexagon::S4_pstorerbt_rr:
- case Hexagon::S4_pstorerbf_rr:
- case Hexagon::S2_pstorerbt_io:
- case Hexagon::S2_pstorerbf_io:
- case Hexagon::S2_pstorerbt_pi:
- case Hexagon::S2_pstorerbf_pi:
- case Hexagon::S2_pstorerdt_io:
- case Hexagon::S2_pstorerdf_io:
- case Hexagon::S4_pstorerdt_rr:
- case Hexagon::S4_pstorerdf_rr:
- case Hexagon::S2_pstorerdt_pi:
- case Hexagon::S2_pstorerdf_pi:
- case Hexagon::S2_pstorerht_io:
- case Hexagon::S2_pstorerhf_io:
- case Hexagon::S4_storeirht_io:
- case Hexagon::S4_storeirhf_io:
- case Hexagon::S4_pstorerht_rr:
- case Hexagon::S4_pstorerhf_rr:
- case Hexagon::S2_pstorerht_pi:
- case Hexagon::S2_pstorerhf_pi:
- case Hexagon::S2_pstorerit_io:
- case Hexagon::S2_pstorerif_io:
- case Hexagon::S4_storeirit_io:
- case Hexagon::S4_storeirif_io:
- case Hexagon::S4_pstorerit_rr:
- case Hexagon::S4_pstorerif_rr:
- case Hexagon::S2_pstorerit_pi:
- case Hexagon::S2_pstorerif_pi:
-
- // V4 global address store before promoting to dot new.
- case Hexagon::S4_pstorerdt_abs:
- case Hexagon::S4_pstorerdf_abs:
- case Hexagon::S4_pstorerbt_abs:
- case Hexagon::S4_pstorerbf_abs:
- case Hexagon::S4_pstorerht_abs:
- case Hexagon::S4_pstorerhf_abs:
- case Hexagon::S4_pstorerit_abs:
- case Hexagon::S4_pstorerif_abs:
- return true;
-
- // Predicated new value stores (i.e. if (p0) memw(..)=r0.new) are excluded
- // from the "Conditional Store" list. Because a predicated new value store
- // would NOT be promoted to a double dot new store.
- // This function returns yes for those stores that are predicated but not
- // yet promoted to predicate dot new instructions.
- }
-}
-
-bool HexagonInstrInfo::isConditionalTransfer(const MachineInstr &MI) const {
- switch (MI.getOpcode()) {
- case Hexagon::A2_tfrt:
- case Hexagon::A2_tfrf:
- case Hexagon::C2_cmoveit:
- case Hexagon::C2_cmoveif:
- case Hexagon::A2_tfrtnew:
- case Hexagon::A2_tfrfnew:
- case Hexagon::C2_cmovenewit:
- case Hexagon::C2_cmovenewif:
- case Hexagon::A2_tfrpt:
- case Hexagon::A2_tfrpf:
- return true;
-
- default:
- return false;
- }
- return false;
-}
-
// TODO: In order to have isExtendable for fpimm/f32Ext, we need to handle
// isFPImm and later getFPImm as well.
bool HexagonInstrInfo::isConstExtended(const MachineInstr &MI) const {
@@ -3474,6 +3319,8 @@ int HexagonInstrInfo::getDotNewOp(const MachineInstr &MI) const {
// Returns the opcode to use when converting MI, which is a conditional jump,
// into a conditional instruction which uses the .new value of the predicate.
// We also use branch probabilities to add a hint to the jump.
+// If MBPI is null, all edges will be treated as equally likely for the
+// purposes of establishing a predication hint.
int HexagonInstrInfo::getDotNewPredJumpOp(const MachineInstr &MI,
const MachineBranchProbabilityInfo *MBPI) const {
// We assume that block can have at most two successors.
@@ -3482,9 +3329,16 @@ int HexagonInstrInfo::getDotNewPredJumpOp(const MachineInstr &MI,
bool Taken = false;
const BranchProbability OneHalf(1, 2);
+ auto getEdgeProbability = [MBPI] (const MachineBasicBlock *Src,
+ const MachineBasicBlock *Dst) {
+ if (MBPI)
+ return MBPI->getEdgeProbability(Src, Dst);
+ return BranchProbability(1, Src->succ_size());
+ };
+
if (BrTarget.isMBB()) {
const MachineBasicBlock *Dst = BrTarget.getMBB();
- Taken = MBPI->getEdgeProbability(Src, Dst) >= OneHalf;
+ Taken = getEdgeProbability(Src, Dst) >= OneHalf;
} else {
// The branch target is not a basic block (most likely a function).
// Since BPI only gives probabilities for targets that are basic blocks,
@@ -3521,7 +3375,7 @@ int HexagonInstrInfo::getDotNewPredJumpOp(const MachineInstr &MI,
for (const MachineBasicBlock *SB : B.successors()) {
if (!B.isLayoutSuccessor(SB))
continue;
- Taken = MBPI->getEdgeProbability(Src, SB) < OneHalf;
+ Taken = getEdgeProbability(Src, SB) < OneHalf;
break;
}
} else {
@@ -3534,7 +3388,7 @@ int HexagonInstrInfo::getDotNewPredJumpOp(const MachineInstr &MI,
BT = Op.getMBB();
break;
}
- Taken = BT && MBPI->getEdgeProbability(Src, BT) < OneHalf;
+ Taken = BT && getEdgeProbability(Src, BT) < OneHalf;
}
} // if (!Bad)
}
diff --git a/lib/Target/Hexagon/HexagonInstrInfo.h b/lib/Target/Hexagon/HexagonInstrInfo.h
index 97b9bc954688..944d0161a7c8 100644
--- a/lib/Target/Hexagon/HexagonInstrInfo.h
+++ b/lib/Target/Hexagon/HexagonInstrInfo.h
@@ -314,11 +314,6 @@ public:
bool isAccumulator(const MachineInstr &MI) const;
bool isComplex(const MachineInstr &MI) const;
bool isCompoundBranchInstr(const MachineInstr &MI) const;
- bool isCondInst(const MachineInstr &MI) const;
- bool isConditionalALU32 (const MachineInstr &MI) const;
- bool isConditionalLoad(const MachineInstr &MI) const;
- bool isConditionalStore(const MachineInstr &MI) const;
- bool isConditionalTransfer(const MachineInstr &MI) const;
bool isConstExtended(const MachineInstr &MI) const;
bool isDeallocRet(const MachineInstr &MI) const;
bool isDependent(const MachineInstr &ProdMI,
diff --git a/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp b/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp
index e6ea67d55b43..9aa185fc85a6 100644
--- a/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp
+++ b/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp
@@ -59,6 +59,9 @@ cl::opt<bool> HexagonVolatileMemcpy("disable-hexagon-volatile-memcpy",
cl::Hidden, cl::init(false),
cl::desc("Enable Hexagon-specific memcpy for volatile destination."));
+static cl::opt<unsigned> SimplifyLimit("hlir-simplify-limit", cl::init(10000),
+ cl::Hidden, cl::desc("Maximum number of simplification steps in HLIR"));
+
static const char *HexagonVolatileMemcpyName
= "hexagon_memcpy_forward_vp4cp4n2";
@@ -477,7 +480,7 @@ Value *Simplifier::simplify(Context &C) {
WorkListType Q;
Q.push_back(C.Root);
unsigned Count = 0;
- const unsigned Limit = 100000;
+ const unsigned Limit = SimplifyLimit;
while (!Q.empty()) {
if (Count++ >= Limit)
@@ -501,8 +504,7 @@ Value *Simplifier::simplify(Context &C) {
Q.push_back(Op);
}
}
- assert(Count < Limit && "Infinite loop in HLIR/simplify?");
- return C.Root;
+ return Count < Limit ? C.Root : nullptr;
}
diff --git a/lib/Target/Hexagon/HexagonPatterns.td b/lib/Target/Hexagon/HexagonPatterns.td
index 81b5e10c1173..70ed123bc898 100644
--- a/lib/Target/Hexagon/HexagonPatterns.td
+++ b/lib/Target/Hexagon/HexagonPatterns.td
@@ -382,48 +382,42 @@ def: T_MType_acc_pat3 <M4_or_andn, and, or>;
def: T_MType_acc_pat3 <M4_and_andn, and, and>;
def: T_MType_acc_pat3 <M4_xor_andn, and, xor>;
+// This complex pattern is really only to detect various forms of
+// sign-extension i32->i64. The selected value will be of type i64
+// whose low word is the value being extended. The high word is
+// unspecified.
+def Usxtw : ComplexPattern<i64, 1, "DetectUseSxtw", [], []>;
+
def Aext64: PatFrag<(ops node:$Rs), (i64 (anyext node:$Rs))>;
-def Sext64: PatFrag<(ops node:$Rs), (i64 (sext node:$Rs))>;
def Zext64: PatFrag<(ops node:$Rs), (i64 (zext node:$Rs))>;
+def Sext64: PatLeaf<(i64 Usxtw:$Rs)>;
-// Return true if for a 32 to 64-bit sign-extended load.
-def Sext64Ld : PatLeaf<(i64 DoubleRegs:$src1), [{
- LoadSDNode *LD = dyn_cast<LoadSDNode>(N);
- if (!LD)
- return false;
- return LD->getExtensionType() == ISD::SEXTLOAD &&
- LD->getMemoryVT().getScalarType() == MVT::i32;
-}]>;
-
-def: Pat<(mul (Aext64 I32:$src1), (Aext64 I32:$src2)),
- (M2_dpmpyuu_s0 IntRegs:$src1, IntRegs:$src2)>;
-
-def: Pat<(mul (Sext64 I32:$src1), (Sext64 I32:$src2)),
- (M2_dpmpyss_s0 IntRegs:$src1, IntRegs:$src2)>;
+def: Pat<(mul (Aext64 I32:$Rs), (Aext64 I32:$Rt)),
+ (M2_dpmpyuu_s0 I32:$Rs, I32:$Rt)>;
-def: Pat<(mul Sext64Ld:$src1, Sext64Ld:$src2),
- (M2_dpmpyss_s0 (LoReg DoubleRegs:$src1), (LoReg DoubleRegs:$src2))>;
+def: Pat<(mul Sext64:$Rs, Sext64:$Rt),
+ (M2_dpmpyss_s0 (LoReg Sext64:$Rs), (LoReg Sext64:$Rt))>;
// Multiply and accumulate, use full result.
// Rxx[+-]=mpy(Rs,Rt)
-def: Pat<(add I64:$src1, (mul (Sext64 I32:$src2), (Sext64 I32:$src3))),
- (M2_dpmpyss_acc_s0 DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3)>;
+def: Pat<(add I64:$Rx, (mul Sext64:$Rs, Sext64:$Rt)),
+ (M2_dpmpyss_acc_s0 I64:$Rx, (LoReg Sext64:$Rs), (LoReg Sext64:$Rt))>;
-def: Pat<(sub I64:$src1, (mul (Sext64 I32:$src2), (Sext64 I32:$src3))),
- (M2_dpmpyss_nac_s0 DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3)>;
+def: Pat<(sub I64:$Rx, (mul Sext64:$Rs, Sext64:$Rt)),
+ (M2_dpmpyss_nac_s0 I64:$Rx, (LoReg Sext64:$Rs), (LoReg Sext64:$Rt))>;
-def: Pat<(add I64:$src1, (mul (Aext64 I32:$src2), (Aext64 I32:$src3))),
- (M2_dpmpyuu_acc_s0 DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3)>;
+def: Pat<(add I64:$Rx, (mul (Aext64 I32:$Rs), (Aext64 I32:$Rt))),
+ (M2_dpmpyuu_acc_s0 I64:$Rx, I32:$Rs, I32:$Rt)>;
-def: Pat<(add I64:$src1, (mul (Zext64 I32:$src2), (Zext64 I32:$src3))),
- (M2_dpmpyuu_acc_s0 DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3)>;
+def: Pat<(add I64:$Rx, (mul (Zext64 I32:$Rs), (Zext64 I32:$Rt))),
+ (M2_dpmpyuu_acc_s0 I64:$Rx, I32:$Rs, I32:$Rt)>;
-def: Pat<(sub I64:$src1, (mul (Aext64 I32:$src2), (Aext64 I32:$src3))),
- (M2_dpmpyuu_nac_s0 DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3)>;
+def: Pat<(sub I64:$Rx, (mul (Aext64 I32:$Rs), (Aext64 I32:$Rt))),
+ (M2_dpmpyuu_nac_s0 I64:$Rx, I32:$Rs, I32:$Rt)>;
-def: Pat<(sub I64:$src1, (mul (Zext64 I32:$src2), (Zext64 I32:$src3))),
- (M2_dpmpyuu_nac_s0 DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3)>;
+def: Pat<(sub I64:$Rx, (mul (Zext64 I32:$Rs), (Zext64 I32:$Rt))),
+ (M2_dpmpyuu_nac_s0 I64:$Rx, I32:$Rs, I32:$Rt)>;
class Storepi_pat<PatFrag Store, PatFrag Value, PatFrag Offset,
InstHexagon MI>
@@ -545,7 +539,8 @@ def: Storexm_simple_pat<truncstorei8, I64, LoReg, S2_storerb_io>;
def: Storexm_simple_pat<truncstorei16, I64, LoReg, S2_storerh_io>;
def: Storexm_simple_pat<truncstorei32, I64, LoReg, S2_storeri_io>;
-def: Pat <(Sext64 I32:$src), (A2_sxtw I32:$src)>;
+def: Pat <(i64 (sext I32:$src)), (A2_sxtw I32:$src)>;
+def: Pat <(i64 (sext_inreg I64:$src, i32)), (A2_sxtw (LoReg I64:$src))>;
def: Pat<(select (i1 (setlt I32:$src, 0)), (sub 0, I32:$src), I32:$src),
(A2_abs IntRegs:$src)>;
@@ -1159,8 +1154,8 @@ multiclass MinMax_pats_p<PatFrag Op, InstHexagon Inst, InstHexagon SwapInst> {
defm: T_MinMax_pats<Op, I64, Inst, SwapInst>;
}
-def: Pat<(add (Sext64 I32:$Rs), I64:$Rt),
- (A2_addsp IntRegs:$Rs, DoubleRegs:$Rt)>;
+def: Pat<(add Sext64:$Rs, I64:$Rt),
+ (A2_addsp (LoReg Sext64:$Rs), DoubleRegs:$Rt)>;
let AddedComplexity = 200 in {
defm: MinMax_pats_p<setge, A2_maxp, A2_minp>;
diff --git a/lib/Target/Hexagon/HexagonTargetMachine.cpp b/lib/Target/Hexagon/HexagonTargetMachine.cpp
index 8e93df6201ae..14ecf297d351 100644
--- a/lib/Target/Hexagon/HexagonTargetMachine.cpp
+++ b/lib/Target/Hexagon/HexagonTargetMachine.cpp
@@ -223,7 +223,7 @@ namespace {
/// Hexagon Code Generator Pass Configuration Options.
class HexagonPassConfig : public TargetPassConfig {
public:
- HexagonPassConfig(HexagonTargetMachine *TM, PassManagerBase &PM)
+ HexagonPassConfig(HexagonTargetMachine &TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {}
HexagonTargetMachine &getHexagonTargetMachine() const {
@@ -245,7 +245,7 @@ public:
} // namespace
TargetPassConfig *HexagonTargetMachine::createPassConfig(PassManagerBase &PM) {
- return new HexagonPassConfig(this, PM);
+ return new HexagonPassConfig(*this, PM);
}
void HexagonPassConfig::addIRPasses() {
diff --git a/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp b/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp
index cd474921d4bc..fa08afe4019d 100644
--- a/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp
+++ b/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp
@@ -273,25 +273,17 @@ bool HexagonPacketizerList::isCallDependent(const MachineInstr &MI,
if (DepReg == HRI->getFrameRegister() || DepReg == HRI->getStackRegister())
return true;
- // Check if this is a predicate dependence.
- const TargetRegisterClass* RC = HRI->getMinimalPhysRegClass(DepReg);
- if (RC == &Hexagon::PredRegsRegClass)
- return true;
-
- // Assumes that the first operand of the CALLr is the function address.
- if (HII->isIndirectCall(MI) && (DepType == SDep::Data)) {
- const MachineOperand MO = MI.getOperand(0);
- if (MO.isReg() && MO.isUse() && (MO.getReg() == DepReg))
- return true;
+ // Call-like instructions can be packetized with preceding instructions
+ // that define registers implicitly used or modified by the call. Explicit
+ // uses are still prohibited, as in the case of indirect calls:
+ // r0 = ...
+ // J2_jumpr r0
+ if (DepType == SDep::Data) {
+ for (const MachineOperand MO : MI.operands())
+ if (MO.isReg() && MO.getReg() == DepReg && !MO.isImplicit())
+ return true;
}
- if (HII->isJumpR(MI)) {
- const MachineOperand &MO = HII->isPredicated(MI) ? MI.getOperand(1)
- : MI.getOperand(0);
- assert(MO.isReg() && MO.isUse());
- if (MO.getReg() == DepReg)
- return true;
- }
return false;
}
@@ -333,11 +325,13 @@ bool HexagonPacketizerList::isNewifiable(const MachineInstr &MI,
const TargetRegisterClass *NewRC) {
// Vector stores can be predicated, and can be new-value stores, but
// they cannot be predicated on a .new predicate value.
- if (NewRC == &Hexagon::PredRegsRegClass)
+ if (NewRC == &Hexagon::PredRegsRegClass) {
if (HII->isHVXVec(MI) && MI.mayStore())
return false;
- return HII->isCondInst(MI) || HII->isJumpR(MI) || MI.isReturn() ||
- HII->mayBeNewStore(MI);
+ return HII->isPredicated(MI) && HII->getDotNewPredOp(MI, nullptr) > 0;
+ }
+ // If the class is not PredRegs, it could only apply to new-value stores.
+ return HII->mayBeNewStore(MI);
}
// Promote an instructiont to its .cur form.
@@ -760,11 +754,14 @@ bool HexagonPacketizerList::canPromoteToNewValue(const MachineInstr &MI,
return false;
}
-static bool isImplicitDependency(const MachineInstr &I, unsigned DepReg) {
+static bool isImplicitDependency(const MachineInstr &I, bool CheckDef,
+ unsigned DepReg) {
for (auto &MO : I.operands()) {
- if (MO.isRegMask() && MO.clobbersPhysReg(DepReg))
+ if (CheckDef && MO.isRegMask() && MO.clobbersPhysReg(DepReg))
return true;
- if (MO.isReg() && MO.isDef() && (MO.getReg() == DepReg) && MO.isImplicit())
+ if (!MO.isReg() || MO.getReg() != DepReg || !MO.isImplicit())
+ continue;
+ if (CheckDef == MO.isDef())
return true;
}
return false;
@@ -798,7 +795,8 @@ bool HexagonPacketizerList::canPromoteToDotNew(const MachineInstr &MI,
// If dependency is trough an implicitly defined register, we should not
// newify the use.
- if (isImplicitDependency(PI, DepReg))
+ if (isImplicitDependency(PI, true, DepReg) ||
+ isImplicitDependency(MI, false, DepReg))
return false;
const MCInstrDesc& MCID = PI.getDesc();
@@ -808,8 +806,7 @@ bool HexagonPacketizerList::canPromoteToDotNew(const MachineInstr &MI,
// predicate .new
if (RC == &Hexagon::PredRegsRegClass)
- if (HII->isCondInst(MI) || HII->isJumpR(MI) || MI.isReturn())
- return HII->predCanBeUsedAsDotNew(PI, DepReg);
+ return HII->predCanBeUsedAsDotNew(PI, DepReg);
if (RC != &Hexagon::PredRegsRegClass && !HII->mayBeNewStore(MI))
return false;
diff --git a/lib/Target/Lanai/LanaiTargetMachine.cpp b/lib/Target/Lanai/LanaiTargetMachine.cpp
index 2a9bc25d7fad..a2f005ce445a 100644
--- a/lib/Target/Lanai/LanaiTargetMachine.cpp
+++ b/lib/Target/Lanai/LanaiTargetMachine.cpp
@@ -76,7 +76,7 @@ namespace {
// Lanai Code Generator Pass Configuration Options.
class LanaiPassConfig : public TargetPassConfig {
public:
- LanaiPassConfig(LanaiTargetMachine *TM, PassManagerBase *PassManager)
+ LanaiPassConfig(LanaiTargetMachine &TM, PassManagerBase *PassManager)
: TargetPassConfig(TM, *PassManager) {}
LanaiTargetMachine &getLanaiTargetMachine() const {
@@ -91,7 +91,7 @@ public:
TargetPassConfig *
LanaiTargetMachine::createPassConfig(PassManagerBase &PassManager) {
- return new LanaiPassConfig(this, &PassManager);
+ return new LanaiPassConfig(*this, &PassManager);
}
// Install an instruction selector pass.
diff --git a/lib/Target/Lanai/LanaiTargetMachine.h b/lib/Target/Lanai/LanaiTargetMachine.h
index 5278c70d909d..083ba6fdf841 100644
--- a/lib/Target/Lanai/LanaiTargetMachine.h
+++ b/lib/Target/Lanai/LanaiTargetMachine.h
@@ -49,6 +49,10 @@ public:
TargetLoweringObjectFile *getObjFileLowering() const override {
return TLOF.get();
}
+
+ bool isMachineVerifierClean() const override {
+ return false;
+ }
};
} // namespace llvm
diff --git a/lib/Target/MSP430/MSP430TargetMachine.cpp b/lib/Target/MSP430/MSP430TargetMachine.cpp
index bebe5fa35ad4..d8fdc8ba674e 100644
--- a/lib/Target/MSP430/MSP430TargetMachine.cpp
+++ b/lib/Target/MSP430/MSP430TargetMachine.cpp
@@ -52,7 +52,7 @@ namespace {
/// MSP430 Code Generator Pass Configuration Options.
class MSP430PassConfig : public TargetPassConfig {
public:
- MSP430PassConfig(MSP430TargetMachine *TM, PassManagerBase &PM)
+ MSP430PassConfig(MSP430TargetMachine &TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {}
MSP430TargetMachine &getMSP430TargetMachine() const {
@@ -65,7 +65,7 @@ public:
} // namespace
TargetPassConfig *MSP430TargetMachine::createPassConfig(PassManagerBase &PM) {
- return new MSP430PassConfig(this, PM);
+ return new MSP430PassConfig(*this, PM);
}
bool MSP430PassConfig::addInstSelector() {
diff --git a/lib/Target/Mips/Mips16FrameLowering.cpp b/lib/Target/Mips/Mips16FrameLowering.cpp
index e7ceca9612a9..a222080f6b81 100644
--- a/lib/Target/Mips/Mips16FrameLowering.cpp
+++ b/lib/Target/Mips/Mips16FrameLowering.cpp
@@ -1,4 +1,4 @@
-//===-- Mips16FrameLowering.cpp - Mips16 Frame Information ----------------===//
+//===- Mips16FrameLowering.cpp - Mips16 Frame Information -----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,20 +11,29 @@
//
//===----------------------------------------------------------------------===//
-#include "Mips16FrameLowering.h"
#include "MCTargetDesc/MipsBaseInfo.h"
+#include "Mips16FrameLowering.h"
#include "Mips16InstrInfo.h"
#include "MipsInstrInfo.h"
#include "MipsRegisterInfo.h"
#include "MipsSubtarget.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/Function.h"
-#include "llvm/Target/TargetOptions.h"
+#include "llvm/IR/DebugLoc.h"
+#include "llvm/MC/MachineLocation.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDwarf.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Target/TargetFrameLowering.h"
+#include <cassert>
+#include <cstdint>
+#include <vector>
using namespace llvm;
@@ -63,7 +72,7 @@ void Mips16FrameLowering::emitPrologue(MachineFunction &MF,
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
- if (CSI.size()) {
+ if (!CSI.empty()) {
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(),
@@ -80,7 +89,6 @@ void Mips16FrameLowering::emitPrologue(MachineFunction &MF,
if (hasFP(MF))
BuildMI(MBB, MBBI, dl, TII.get(Mips::MoveR3216), Mips::S0)
.addReg(Mips::SP).setMIFlag(MachineInstr::FrameSetup);
-
}
void Mips16FrameLowering::emitEpilogue(MachineFunction &MF,
diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp
index 092de216e9b8..a9d6ab055892 100644
--- a/lib/Target/Mips/MipsTargetMachine.cpp
+++ b/lib/Target/Mips/MipsTargetMachine.cpp
@@ -201,7 +201,7 @@ namespace {
/// Mips Code Generator Pass Configuration Options.
class MipsPassConfig : public TargetPassConfig {
public:
- MipsPassConfig(MipsTargetMachine *TM, PassManagerBase &PM)
+ MipsPassConfig(MipsTargetMachine &TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {
// The current implementation of long branch pass requires a scratch
// register ($at) to be available before branch instructions. Tail merging
@@ -227,7 +227,7 @@ public:
} // end anonymous namespace
TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) {
- return new MipsPassConfig(this, PM);
+ return new MipsPassConfig(*this, PM);
}
void MipsPassConfig::addIRPasses() {
diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h
index 140d7133f879..a3462868cb11 100644
--- a/lib/Target/Mips/MipsTargetMachine.h
+++ b/lib/Target/Mips/MipsTargetMachine.h
@@ -66,6 +66,10 @@ public:
bool isLittleEndian() const { return isLittle; }
const MipsABIInfo &getABI() const { return ABI; }
+
+ bool isMachineVerifierClean() const override {
+ return false;
+ }
};
/// Mips32/64 big endian target machine.
diff --git a/lib/Target/NVPTX/NVPTXTargetMachine.cpp b/lib/Target/NVPTX/NVPTXTargetMachine.cpp
index ab5298d0dcfd..8dfbfece9b8e 100644
--- a/lib/Target/NVPTX/NVPTXTargetMachine.cpp
+++ b/lib/Target/NVPTX/NVPTXTargetMachine.cpp
@@ -132,7 +132,7 @@ namespace {
class NVPTXPassConfig : public TargetPassConfig {
public:
- NVPTXPassConfig(NVPTXTargetMachine *TM, PassManagerBase &PM)
+ NVPTXPassConfig(NVPTXTargetMachine &TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {}
NVPTXTargetMachine &getNVPTXTargetMachine() const {
@@ -163,7 +163,7 @@ private:
} // end anonymous namespace
TargetPassConfig *NVPTXTargetMachine::createPassConfig(PassManagerBase &PM) {
- return new NVPTXPassConfig(this, PM);
+ return new NVPTXPassConfig(*this, PM);
}
void NVPTXTargetMachine::adjustPassManager(PassManagerBuilder &Builder) {
diff --git a/lib/Target/NVPTX/NVPTXTargetMachine.h b/lib/Target/NVPTX/NVPTXTargetMachine.h
index 1ed8e3b1e935..2f3981be22f8 100644
--- a/lib/Target/NVPTX/NVPTXTargetMachine.h
+++ b/lib/Target/NVPTX/NVPTXTargetMachine.h
@@ -65,6 +65,9 @@ public:
TargetIRAnalysis getTargetIRAnalysis() override;
+ bool isMachineVerifierClean() const override {
+ return false;
+ }
}; // NVPTXTargetMachine.
class NVPTXTargetMachine32 : public NVPTXTargetMachine {
diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index 5fa7b2c6bfb1..54414457388d 100644
--- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -77,6 +77,11 @@ STATISTIC(SignExtensionsAdded,
"Number of sign extensions for compare inputs added.");
STATISTIC(ZeroExtensionsAdded,
"Number of zero extensions for compare inputs added.");
+STATISTIC(NumLogicOpsOnComparison,
+ "Number of logical ops on i1 values calculated in GPR.");
+STATISTIC(OmittedForNonExtendUses,
+ "Number of compares not eliminated as they have non-extending uses.");
+
// FIXME: Remove this once the bug has been fixed!
cl::opt<bool> ANDIGlueBug("expose-ppc-andi-glue-bug",
cl::desc("expose the ANDI glue bug on PPC"), cl::Hidden);
@@ -275,6 +280,8 @@ private:
bool trySETCC(SDNode *N);
bool tryEXTEND(SDNode *N);
+ bool tryLogicOpOfCompares(SDNode *N);
+ SDValue computeLogicOpInGPR(SDValue LogicOp);
SDValue signExtendInputIfNeeded(SDValue Input);
SDValue zeroExtendInputIfNeeded(SDValue Input);
SDValue addExtOrTrunc(SDValue NatWidthRes, ExtOrTruncConversion Conv);
@@ -282,6 +289,10 @@ private:
int64_t RHSValue, SDLoc dl);
SDValue get32BitSExtCompare(SDValue LHS, SDValue RHS, ISD::CondCode CC,
int64_t RHSValue, SDLoc dl);
+ SDValue get64BitZExtCompare(SDValue LHS, SDValue RHS, ISD::CondCode CC,
+ int64_t RHSValue, SDLoc dl);
+ SDValue get64BitSExtCompare(SDValue LHS, SDValue RHS, ISD::CondCode CC,
+ int64_t RHSValue, SDLoc dl);
SDValue getSETCCInGPR(SDValue Compare, SetccInGPROpts ConvOpts);
void PeepholePPC64();
@@ -2501,6 +2512,11 @@ bool PPCDAGToDAGISel::trySETCC(SDNode *N) {
return true;
}
+// Is this opcode a bitwise logical operation?
+static bool isLogicOp(unsigned Opc) {
+ return Opc == ISD::AND || Opc == ISD::OR || Opc == ISD::XOR;
+}
+
/// If this node is a sign/zero extension of an integer comparison,
/// it can usually be computed in GPR's rather than using comparison
/// instructions and ISEL. We only do this on 64-bit targets for now
@@ -2513,13 +2529,20 @@ bool PPCDAGToDAGISel::tryEXTEND(SDNode *N) {
N->getOpcode() == ISD::SIGN_EXTEND) &&
"Expecting a zero/sign extend node!");
- if (N->getOperand(0).getOpcode() != ISD::SETCC)
+ SDValue WideRes;
+ // If we are zero-extending the result of a logical operation on i1
+ // values, we can keep the values in GPRs.
+ if (isLogicOp(N->getOperand(0).getOpcode()) &&
+ N->getOperand(0).getValueType() == MVT::i1 &&
+ N->getOpcode() == ISD::ZERO_EXTEND)
+ WideRes = computeLogicOpInGPR(N->getOperand(0));
+ else if (N->getOperand(0).getOpcode() != ISD::SETCC)
return false;
-
- SDValue WideRes =
- getSETCCInGPR(N->getOperand(0),
- N->getOpcode() == ISD::SIGN_EXTEND ?
- SetccInGPROpts::SExtOrig : SetccInGPROpts::ZExtOrig);
+ else
+ WideRes =
+ getSETCCInGPR(N->getOperand(0),
+ N->getOpcode() == ISD::SIGN_EXTEND ?
+ SetccInGPROpts::SExtOrig : SetccInGPROpts::ZExtOrig);
if (!WideRes)
return false;
@@ -2540,6 +2563,159 @@ bool PPCDAGToDAGISel::tryEXTEND(SDNode *N) {
return true;
}
+// Lower a logical operation on i1 values into a GPR sequence if possible.
+// The result can be kept in a GPR if requested.
+// Three types of inputs can be handled:
+// - SETCC
+// - TRUNCATE
+// - Logical operation (AND/OR/XOR)
+// There is also a special case that is handled (namely a complement operation
+// achieved with xor %a, -1).
+SDValue PPCDAGToDAGISel::computeLogicOpInGPR(SDValue LogicOp) {
+ assert(isLogicOp(LogicOp.getOpcode()) &&
+ "Can only handle logic operations here.");
+ assert(LogicOp.getValueType() == MVT::i1 &&
+ "Can only handle logic operations on i1 values here.");
+ SDLoc dl(LogicOp);
+ SDValue LHS, RHS;
+
+ // Special case: xor %a, -1
+ bool IsBitwiseNegation = isBitwiseNot(LogicOp);
+
+ // Produces a GPR sequence for each operand of the binary logic operation.
+ // For SETCC, it produces the respective comparison, for TRUNCATE it truncates
+ // the value in a GPR and for logic operations, it will recursively produce
+ // a GPR sequence for the operation.
+ auto getLogicOperand = [&] (SDValue Operand) -> SDValue {
+ unsigned OperandOpcode = Operand.getOpcode();
+ if (OperandOpcode == ISD::SETCC)
+ return getSETCCInGPR(Operand, SetccInGPROpts::ZExtOrig);
+ else if (OperandOpcode == ISD::TRUNCATE) {
+ SDValue InputOp = Operand.getOperand(0);
+ EVT InVT = InputOp.getValueType();
+ return
+ SDValue(CurDAG->getMachineNode(InVT == MVT::i32 ? PPC::RLDICL_32 :
+ PPC::RLDICL, dl, InVT, InputOp,
+ getI64Imm(0, dl), getI64Imm(63, dl)), 0);
+ } else if (isLogicOp(OperandOpcode))
+ return computeLogicOpInGPR(Operand);
+ return SDValue();
+ };
+ LHS = getLogicOperand(LogicOp.getOperand(0));
+ RHS = getLogicOperand(LogicOp.getOperand(1));
+
+ // If a GPR sequence can't be produced for the LHS we can't proceed.
+ // Not producing a GPR sequence for the RHS is only a problem if this isn't
+ // a bitwise negation operation.
+ if (!LHS || (!RHS && !IsBitwiseNegation))
+ return SDValue();
+
+ NumLogicOpsOnComparison++;
+
+ // We will use the inputs as 64-bit values.
+ if (LHS.getValueType() == MVT::i32)
+ LHS = addExtOrTrunc(LHS, ExtOrTruncConversion::Ext);
+ if (!IsBitwiseNegation && RHS.getValueType() == MVT::i32)
+ RHS = addExtOrTrunc(RHS, ExtOrTruncConversion::Ext);
+
+ unsigned NewOpc;
+ switch (LogicOp.getOpcode()) {
+ default: llvm_unreachable("Unknown logic operation.");
+ case ISD::AND: NewOpc = PPC::AND8; break;
+ case ISD::OR: NewOpc = PPC::OR8; break;
+ case ISD::XOR: NewOpc = PPC::XOR8; break;
+ }
+
+ if (IsBitwiseNegation) {
+ RHS = getI64Imm(1, dl);
+ NewOpc = PPC::XORI8;
+ }
+
+ return SDValue(CurDAG->getMachineNode(NewOpc, dl, MVT::i64, LHS, RHS), 0);
+
+}
+
+/// Try performing logical operations on results of comparisons in GPRs.
+/// It is typically preferred from a performance perspective over performing
+/// the operations on individual bits in the CR. We only do this on 64-bit
+/// targets for now as the code is specialized for 64-bit (it uses 64-bit
+/// instructions and assumes 64-bit registers).
+bool PPCDAGToDAGISel::tryLogicOpOfCompares(SDNode *N) {
+ if (TM.getOptLevel() == CodeGenOpt::None || !TM.isPPC64())
+ return false;
+ if (N->getValueType(0) != MVT::i1)
+ return false;
+ assert(isLogicOp(N->getOpcode()) &&
+ "Expected a logic operation on setcc results.");
+ SDValue LoweredLogical = computeLogicOpInGPR(SDValue(N, 0));
+ if (!LoweredLogical)
+ return false;
+
+ SDLoc dl(N);
+ bool IsBitwiseNegate = LoweredLogical.getMachineOpcode() == PPC::XORI8;
+ unsigned SubRegToExtract = IsBitwiseNegate ? PPC::sub_eq : PPC::sub_gt;
+ SDValue CR0Reg = CurDAG->getRegister(PPC::CR0, MVT::i32);
+ SDValue LHS = LoweredLogical.getOperand(0);
+ SDValue RHS = LoweredLogical.getOperand(1);
+ SDValue WideOp;
+ SDValue OpToConvToRecForm;
+
+ // Look through any 32-bit to 64-bit implicit extend nodes to find the opcode
+ // that is input to the XORI.
+ if (IsBitwiseNegate &&
+ LoweredLogical.getOperand(0).getMachineOpcode() == PPC::INSERT_SUBREG)
+ OpToConvToRecForm = LoweredLogical.getOperand(0).getOperand(1);
+ else if (IsBitwiseNegate)
+ // If the input to the XORI isn't an extension, that's what we're after.
+ OpToConvToRecForm = LoweredLogical.getOperand(0);
+ else
+ // If this is not an XORI, it is a reg-reg logical op and we can convert it
+ // to record-form.
+ OpToConvToRecForm = LoweredLogical;
+
+ // Get the record-form version of the node we're looking to use to get the
+ // CR result from.
+ uint16_t NonRecOpc = OpToConvToRecForm.getMachineOpcode();
+ int NewOpc = PPCInstrInfo::getRecordFormOpcode(NonRecOpc);
+
+ // Convert the right node to record-form. This is either the logical we're
+ // looking at or it is the input node to the negation (if we're looking at
+ // a bitwise negation).
+ if (NewOpc != -1 && IsBitwiseNegate) {
+ // The input to the XORI has a record-form. Use it.
+ assert(LoweredLogical.getConstantOperandVal(1) == 1 &&
+ "Expected a PPC::XORI8 only for bitwise negation.");
+ // Emit the record-form instruction.
+ std::vector<SDValue> Ops;
+ for (int i = 0, e = OpToConvToRecForm.getNumOperands(); i < e; i++)
+ Ops.push_back(OpToConvToRecForm.getOperand(i));
+
+ WideOp =
+ SDValue(CurDAG->getMachineNode(NewOpc, dl,
+ OpToConvToRecForm.getValueType(),
+ MVT::Glue, Ops), 0);
+ } else {
+ assert((NewOpc != -1 || !IsBitwiseNegate) &&
+ "No record form available for AND8/OR8/XOR8?");
+ WideOp =
+ SDValue(CurDAG->getMachineNode(NewOpc == -1 ? PPC::ANDIo8 : NewOpc, dl,
+ MVT::i64, MVT::Glue, LHS, RHS), 0);
+ }
+
+ // Select this node to a single bit from CR0 set by the record-form node
+ // just created. For bitwise negation, use the EQ bit which is the equivalent
+ // of negating the result (i.e. it is a bit set when the result of the
+ // operation is zero).
+ SDValue SRIdxVal =
+ CurDAG->getTargetConstant(SubRegToExtract, dl, MVT::i32);
+ SDValue CRBit =
+ SDValue(CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl,
+ MVT::i1, CR0Reg, SRIdxVal,
+ WideOp.getValue(1)), 0);
+ ReplaceNode(N, CRBit.getNode());
+ return true;
+}
+
/// If the value isn't guaranteed to be sign-extended to 64-bits, extend it.
/// Useful when emitting comparison code for 32-bit values without using
/// the compare instruction (which only considers the lower 32-bits).
@@ -2677,6 +2853,77 @@ SDValue PPCDAGToDAGISel::get32BitSExtCompare(SDValue LHS, SDValue RHS,
}
}
+/// Produces a zero-extended result of comparing two 64-bit values according to
+/// the passed condition code.
+SDValue PPCDAGToDAGISel::get64BitZExtCompare(SDValue LHS, SDValue RHS,
+ ISD::CondCode CC,
+ int64_t RHSValue, SDLoc dl) {
+ bool IsRHSZero = RHSValue == 0;
+ switch (CC) {
+ default: return SDValue();
+ case ISD::SETEQ: {
+ // (zext (setcc %a, %b, seteq)) -> (lshr (ctlz (xor %a, %b)), 6)
+ // (zext (setcc %a, 0, seteq)) -> (lshr (ctlz %a), 6)
+ SDValue Xor = IsRHSZero ? LHS :
+ SDValue(CurDAG->getMachineNode(PPC::XOR8, dl, MVT::i64, LHS, RHS), 0);
+ SDValue Clz =
+ SDValue(CurDAG->getMachineNode(PPC::CNTLZD, dl, MVT::i64, Xor), 0);
+ return SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, Clz,
+ getI64Imm(58, dl), getI64Imm(63, dl)),
+ 0);
+ }
+ }
+}
+
+/// Produces a sign-extended result of comparing two 64-bit values according to
+/// the passed condition code.
+SDValue PPCDAGToDAGISel::get64BitSExtCompare(SDValue LHS, SDValue RHS,
+ ISD::CondCode CC,
+ int64_t RHSValue, SDLoc dl) {
+ bool IsRHSZero = RHSValue == 0;
+ switch (CC) {
+ default: return SDValue();
+ case ISD::SETEQ: {
+ // {addc.reg, addc.CA} = (addcarry (xor %a, %b), -1)
+ // (sext (setcc %a, %b, seteq)) -> (sube addc.reg, addc.reg, addc.CA)
+ // {addcz.reg, addcz.CA} = (addcarry %a, -1)
+ // (sext (setcc %a, 0, seteq)) -> (sube addcz.reg, addcz.reg, addcz.CA)
+ SDValue AddInput = IsRHSZero ? LHS :
+ SDValue(CurDAG->getMachineNode(PPC::XOR8, dl, MVT::i64, LHS, RHS), 0);
+ SDValue Addic =
+ SDValue(CurDAG->getMachineNode(PPC::ADDIC8, dl, MVT::i64, MVT::Glue,
+ AddInput, getI32Imm(~0U, dl)), 0);
+ return SDValue(CurDAG->getMachineNode(PPC::SUBFE8, dl, MVT::i64, Addic,
+ Addic, Addic.getValue(1)), 0);
+ }
+ }
+}
+
+/// Does this SDValue have any uses for which keeping the value in a GPR is
+/// appropriate. This is meant to be used on values that have type i1 since
+/// it is somewhat meaningless to ask if values of other types can be kept in
+/// GPR's.
+static bool allUsesExtend(SDValue Compare, SelectionDAG *CurDAG) {
+ assert(Compare.getOpcode() == ISD::SETCC &&
+ "An ISD::SETCC node required here.");
+
+ // For values that have a single use, the caller should obviously already have
+ // checked if that use is an extending use. We check the other uses here.
+ if (Compare.hasOneUse())
+ return true;
+ // We want the value in a GPR if it is being extended, used for a select, or
+ // used in logical operations.
+ for (auto CompareUse : Compare.getNode()->uses())
+ if (CompareUse->getOpcode() != ISD::SIGN_EXTEND &&
+ CompareUse->getOpcode() != ISD::ZERO_EXTEND &&
+ CompareUse->getOpcode() != ISD::SELECT &&
+ !isLogicOp(CompareUse->getOpcode())) {
+ OmittedForNonExtendUses++;
+ return false;
+ }
+ return true;
+}
+
/// Returns an equivalent of a SETCC node but with the result the same width as
/// the inputs. This can nalso be used for SELECT_CC if either the true or false
/// values is a power of two while the other is zero.
@@ -2686,6 +2933,11 @@ SDValue PPCDAGToDAGISel::getSETCCInGPR(SDValue Compare,
Compare.getOpcode() == ISD::SELECT_CC) &&
"An ISD::SETCC node required here.");
+ // Don't convert this comparison to a GPR sequence because there are uses
+ // of the i1 result (i.e. uses that require the result in the CR).
+ if ((Compare.getOpcode() == ISD::SETCC) && !allUsesExtend(Compare, CurDAG))
+ return SDValue();
+
SDValue LHS = Compare.getOperand(0);
SDValue RHS = Compare.getOperand(1);
@@ -2694,30 +2946,35 @@ SDValue PPCDAGToDAGISel::getSETCCInGPR(SDValue Compare,
ISD::CondCode CC =
cast<CondCodeSDNode>(Compare.getOperand(CCOpNum))->get();
EVT InputVT = LHS.getValueType();
- if (InputVT != MVT::i32)
+ if (InputVT != MVT::i32 && InputVT != MVT::i64)
return SDValue();
- SDLoc dl(Compare);
- ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
- int64_t RHSValue = RHSConst ? RHSConst->getSExtValue() : INT64_MAX;
-
if (ConvOpts == SetccInGPROpts::ZExtInvert ||
ConvOpts == SetccInGPROpts::SExtInvert)
CC = ISD::getSetCCInverse(CC, true);
- if (ISD::isSignedIntSetCC(CC)) {
+ bool Inputs32Bit = InputVT == MVT::i32;
+ if (ISD::isSignedIntSetCC(CC) && Inputs32Bit) {
LHS = signExtendInputIfNeeded(LHS);
RHS = signExtendInputIfNeeded(RHS);
- } else if (ISD::isUnsignedIntSetCC(CC)) {
+ } else if (ISD::isUnsignedIntSetCC(CC) && Inputs32Bit) {
LHS = zeroExtendInputIfNeeded(LHS);
RHS = zeroExtendInputIfNeeded(RHS);
}
+ SDLoc dl(Compare);
+ ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
+ int64_t RHSValue = RHSConst ? RHSConst->getSExtValue() : INT64_MAX;
bool IsSext = ConvOpts == SetccInGPROpts::SExtOrig ||
ConvOpts == SetccInGPROpts::SExtInvert;
- if (IsSext)
+
+ if (IsSext && Inputs32Bit)
return get32BitSExtCompare(LHS, RHS, CC, RHSValue, dl);
- return get32BitZExtCompare(LHS, RHS, CC, RHSValue, dl);
+ else if (Inputs32Bit)
+ return get32BitZExtCompare(LHS, RHS, CC, RHSValue, dl);
+ else if (IsSext)
+ return get64BitSExtCompare(LHS, RHS, CC, RHSValue, dl);
+ return get64BitZExtCompare(LHS, RHS, CC, RHSValue, dl);
}
void PPCDAGToDAGISel::transferMemOperands(SDNode *N, SDNode *Result) {
@@ -2906,6 +3163,9 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
}
case ISD::AND: {
+ if (tryLogicOpOfCompares(N))
+ return;
+
unsigned Imm, Imm2, SH, MB, ME;
uint64_t Imm64;
@@ -3025,6 +3285,9 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
if (tryBitfieldInsert(N))
return;
+ if (tryLogicOpOfCompares(N))
+ return;
+
short Imm;
if (N->getOperand(0)->getOpcode() == ISD::FrameIndex &&
isIntS16Immediate(N->getOperand(1), Imm)) {
@@ -3042,6 +3305,11 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
// Other cases are autogenerated.
break;
}
+ case ISD::XOR: {
+ if (tryLogicOpOfCompares(N))
+ return;
+ break;
+ }
case ISD::ADD: {
short Imm;
if (N->getOperand(0)->getOpcode() == ISD::FrameIndex &&
diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp
index 216efcc4a1ee..41ff9d903aa0 100644
--- a/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -1041,6 +1041,10 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
MaxStoresPerMemset = 128;
MaxStoresPerMemcpy = 128;
MaxStoresPerMemmove = 128;
+ MaxLoadsPerMemcmp = 128;
+ } else {
+ MaxLoadsPerMemcmp = 8;
+ MaxLoadsPerMemcmpOptSize = 4;
}
}
@@ -1112,6 +1116,7 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
case PPCISD::VPERM: return "PPCISD::VPERM";
case PPCISD::XXSPLT: return "PPCISD::XXSPLT";
case PPCISD::XXINSERT: return "PPCISD::XXINSERT";
+ case PPCISD::XXPERMDI: return "PPCISD::XXPERMDI";
case PPCISD::VECSHL: return "PPCISD::VECSHL";
case PPCISD::CMPB: return "PPCISD::CMPB";
case PPCISD::Hi: return "PPCISD::Hi";
@@ -1593,17 +1598,25 @@ bool PPC::isSplatShuffleMask(ShuffleVectorSDNode *N, unsigned EltSize) {
return true;
}
- // Check that the mask is shuffling words
-static bool isWordShuffleMask(ShuffleVectorSDNode *N) {
- for (unsigned i = 0; i < 4; ++i) {
- unsigned B0 = N->getMaskElt(i*4);
- unsigned B1 = N->getMaskElt(i*4+1);
- unsigned B2 = N->getMaskElt(i*4+2);
- unsigned B3 = N->getMaskElt(i*4+3);
- if (B0 % 4)
- return false;
- if (B1 != B0+1 || B2 != B1+1 || B3 != B2+1)
+// Check that the mask is shuffling N byte elements.
+static bool isNByteElemShuffleMask(ShuffleVectorSDNode *N, unsigned Width) {
+ assert((Width == 2 || Width == 4 || Width == 8 || Width == 16) &&
+ "Unexpected element width.");
+
+ unsigned NumOfElem = 16 / Width;
+ unsigned MaskVal[16]; // Width is never greater than 16
+ for (unsigned i = 0; i < NumOfElem; ++i) {
+ MaskVal[0] = N->getMaskElt(i * Width);
+ if (MaskVal[0] % Width) {
return false;
+ }
+
+ for (unsigned int j = 1; j < Width; ++j) {
+ MaskVal[j] = N->getMaskElt(i * Width + j);
+ if (MaskVal[j] != MaskVal[j-1] + 1) {
+ return false;
+ }
+ }
}
return true;
@@ -1611,7 +1624,7 @@ static bool isWordShuffleMask(ShuffleVectorSDNode *N) {
bool PPC::isXXINSERTWMask(ShuffleVectorSDNode *N, unsigned &ShiftElts,
unsigned &InsertAtByte, bool &Swap, bool IsLE) {
- if (!isWordShuffleMask(N))
+ if (!isNByteElemShuffleMask(N, 4))
return false;
// Now we look at mask elements 0,4,8,12
@@ -1688,7 +1701,7 @@ bool PPC::isXXSLDWIShuffleMask(ShuffleVectorSDNode *N, unsigned &ShiftElts,
bool &Swap, bool IsLE) {
assert(N->getValueType(0) == MVT::v16i8 && "Shuffle vector expects v16i8");
// Ensure each byte index of the word is consecutive.
- if (!isWordShuffleMask(N))
+ if (!isNByteElemShuffleMask(N, 4))
return false;
// Now we look at mask elements 0,4,8,12, which are the beginning of words.
@@ -1746,6 +1759,66 @@ bool PPC::isXXSLDWIShuffleMask(ShuffleVectorSDNode *N, unsigned &ShiftElts,
}
}
+/// Can node \p N be lowered to an XXPERMDI instruction? If so, set \p Swap
+/// if the inputs to the instruction should be swapped and set \p DM to the
+/// value for the immediate.
+/// Specifically, set \p Swap to true only if \p N can be lowered to XXPERMDI
+/// AND element 0 of the result comes from the first input (LE) or second input
+/// (BE). Set \p DM to the calculated result (0-3) only if \p N can be lowered.
+/// \return true iff the given mask of shuffle node \p N is a XXPERMDI shuffle
+/// mask.
+bool PPC::isXXPERMDIShuffleMask(ShuffleVectorSDNode *N, unsigned &DM,
+ bool &Swap, bool IsLE) {
+ assert(N->getValueType(0) == MVT::v16i8 && "Shuffle vector expects v16i8");
+
+ // Ensure each byte index of the double word is consecutive.
+ if (!isNByteElemShuffleMask(N, 8))
+ return false;
+
+ unsigned M0 = N->getMaskElt(0) / 8;
+ unsigned M1 = N->getMaskElt(8) / 8;
+ assert(((M0 | M1) < 4) && "A mask element out of bounds?");
+
+ // If both vector operands for the shuffle are the same vector, the mask will
+ // contain only elements from the first one and the second one will be undef.
+ if (N->getOperand(1).isUndef()) {
+ if ((M0 | M1) < 2) {
+ DM = IsLE ? (((~M1) & 1) << 1) + ((~M0) & 1) : (M0 << 1) + (M1 & 1);
+ Swap = false;
+ return true;
+ } else
+ return false;
+ }
+
+ if (IsLE) {
+ if (M0 > 1 && M1 < 2) {
+ Swap = false;
+ } else if (M0 < 2 && M1 > 1) {
+ M0 = (M0 + 2) % 4;
+ M1 = (M1 + 2) % 4;
+ Swap = true;
+ } else
+ return false;
+
+ // Note: if control flow comes here that means Swap is already set above
+ DM = (((~M1) & 1) << 1) + ((~M0) & 1);
+ return true;
+ } else { // BE
+ if (M0 < 2 && M1 > 1) {
+ Swap = false;
+ } else if (M0 > 1 && M1 < 2) {
+ M0 = (M0 + 2) % 4;
+ M1 = (M1 + 2) % 4;
+ Swap = true;
+ } else
+ return false;
+
+ // Note: if control flow comes here that means Swap is already set above
+ DM = (M0 << 1) + (M1 & 1);
+ return true;
+ }
+}
+
/// getVSPLTImmediate - Return the appropriate VSPLT* immediate to splat the
/// specified isSplatShuffleMask VECTOR_SHUFFLE mask.
@@ -7760,6 +7833,19 @@ SDValue PPCTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
return DAG.getNode(ISD::BITCAST, dl, MVT::v16i8, Shl);
}
+ if (Subtarget.hasVSX() &&
+ PPC::isXXPERMDIShuffleMask(SVOp, ShiftElts, Swap, isLittleEndian)) {
+ if (Swap)
+ std::swap(V1, V2);
+ SDValue Conv1 = DAG.getNode(ISD::BITCAST, dl, MVT::v2i64, V1);
+ SDValue Conv2 =
+ DAG.getNode(ISD::BITCAST, dl, MVT::v2i64, V2.isUndef() ? V1 : V2);
+
+ SDValue PermDI = DAG.getNode(PPCISD::XXPERMDI, dl, MVT::v2i64, Conv1, Conv2,
+ DAG.getConstant(ShiftElts, dl, MVT::i32));
+ return DAG.getNode(ISD::BITCAST, dl, MVT::v16i8, PermDI);
+ }
+
if (Subtarget.hasVSX()) {
if (V2.isUndef() && PPC::isSplatShuffleMask(SVOp, 4)) {
int SplatIdx = PPC::getVSPLTImmediate(SVOp, 4, DAG);
diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h
index 2f9eb95f6de6..7982a4a9e9fb 100644
--- a/lib/Target/PowerPC/PPCISelLowering.h
+++ b/lib/Target/PowerPC/PPCISelLowering.h
@@ -90,6 +90,10 @@ namespace llvm {
///
VECSHL,
+ /// XXPERMDI - The PPC XXPERMDI instruction
+ ///
+ XXPERMDI,
+
/// The CMPB instruction (takes two operands of i32 or i64).
CMPB,
@@ -454,6 +458,10 @@ namespace llvm {
/// for a XXSLDWI instruction.
bool isXXSLDWIShuffleMask(ShuffleVectorSDNode *N, unsigned &ShiftElts,
bool &Swap, bool IsLE);
+ /// isXXPERMDIShuffleMask - Return true if this is a shuffle mask suitable
+ /// for a XXPERMDI instruction.
+ bool isXXPERMDIShuffleMask(ShuffleVectorSDNode *N, unsigned &ShiftElts,
+ bool &Swap, bool IsLE);
/// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the
/// shift amount, otherwise return -1.
diff --git a/lib/Target/PowerPC/PPCInstr64Bit.td b/lib/Target/PowerPC/PPCInstr64Bit.td
index 165970f9678c..295590b2acf6 100644
--- a/lib/Target/PowerPC/PPCInstr64Bit.td
+++ b/lib/Target/PowerPC/PPCInstr64Bit.td
@@ -735,12 +735,12 @@ def RLDICL_32_64 : MDForm_1<30, 0,
"rldicl $rA, $rS, $SH, $MBE", IIC_IntRotateDI,
[]>, isPPC64;
// End fast-isel.
-let isCodeGenOnly = 1 in
-def RLDICL_32 : MDForm_1<30, 0,
- (outs gprc:$rA),
- (ins gprc:$rS, u6imm:$SH, u6imm:$MBE),
- "rldicl $rA, $rS, $SH, $MBE", IIC_IntRotateDI,
- []>, isPPC64;
+let Interpretation64Bit = 1, isCodeGenOnly = 1 in
+defm RLDICL_32 : MDForm_1r<30, 0,
+ (outs gprc:$rA),
+ (ins gprc:$rS, u6imm:$SH, u6imm:$MBE),
+ "rldicl", "$rA, $rS, $SH, $MBE", IIC_IntRotateDI,
+ []>, isPPC64;
defm RLDICR : MDForm_1r<30, 1,
(outs g8rc:$rA), (ins g8rc:$rS, u6imm:$SH, u6imm:$MBE),
"rldicr", "$rA, $rS, $SH, $MBE", IIC_IntRotateDI,
diff --git a/lib/Target/PowerPC/PPCInstrInfo.cpp b/lib/Target/PowerPC/PPCInstrInfo.cpp
index fd6785e963a6..f3c68c443b1b 100644
--- a/lib/Target/PowerPC/PPCInstrInfo.cpp
+++ b/lib/Target/PowerPC/PPCInstrInfo.cpp
@@ -1983,3 +1983,7 @@ PPCInstrInfo::updatedRC(const TargetRegisterClass *RC) const {
return &PPC::VSRCRegClass;
return RC;
}
+
+int PPCInstrInfo::getRecordFormOpcode(unsigned Opcode) {
+ return PPC::getRecordFormOpcode(Opcode);
+}
diff --git a/lib/Target/PowerPC/PPCInstrInfo.h b/lib/Target/PowerPC/PPCInstrInfo.h
index b30d09e03ec4..8dd4dbb60879 100644
--- a/lib/Target/PowerPC/PPCInstrInfo.h
+++ b/lib/Target/PowerPC/PPCInstrInfo.h
@@ -290,6 +290,7 @@ public:
return Reg >= PPC::V0 && Reg <= PPC::V31;
}
const TargetRegisterClass *updatedRC(const TargetRegisterClass *RC) const;
+ static int getRecordFormOpcode(unsigned Opcode);
};
}
diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td
index 26b99eced23c..8223aa655e38 100644
--- a/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/lib/Target/PowerPC/PPCInstrInfo.td
@@ -53,6 +53,10 @@ def SDT_PPCVecInsert : SDTypeProfile<1, 3, [ SDTCisVec<0>,
SDTCisVec<1>, SDTCisVec<2>, SDTCisInt<3>
]>;
+def SDT_PPCxxpermdi: SDTypeProfile<1, 3, [ SDTCisVec<0>,
+ SDTCisVec<1>, SDTCisVec<2>, SDTCisInt<3>
+]>;
+
def SDT_PPCvcmp : SDTypeProfile<1, 3, [
SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisVT<3, i32>
]>;
@@ -170,6 +174,7 @@ def PPCaddiDtprelL : SDNode<"PPCISD::ADDI_DTPREL_L", SDTIntBinOp>;
def PPCvperm : SDNode<"PPCISD::VPERM", SDT_PPCvperm, []>;
def PPCxxsplt : SDNode<"PPCISD::XXSPLT", SDT_PPCVecSplat, []>;
def PPCxxinsert : SDNode<"PPCISD::XXINSERT", SDT_PPCVecInsert, []>;
+def PPCxxpermdi : SDNode<"PPCISD::XXPERMDI", SDT_PPCxxpermdi, []>;
def PPCvecshl : SDNode<"PPCISD::VECSHL", SDT_PPCVecShift, []>;
def PPCqvfperm : SDNode<"PPCISD::QVFPERM", SDT_PPCqvfperm, []>;
diff --git a/lib/Target/PowerPC/PPCInstrVSX.td b/lib/Target/PowerPC/PPCInstrVSX.td
index 1589ab03e507..c4139ca8b7bd 100644
--- a/lib/Target/PowerPC/PPCInstrVSX.td
+++ b/lib/Target/PowerPC/PPCInstrVSX.td
@@ -843,7 +843,9 @@ let Uses = [RM] in {
def XXPERMDI : XX3Form_2<60, 10,
(outs vsrc:$XT), (ins vsrc:$XA, vsrc:$XB, u2imm:$DM),
- "xxpermdi $XT, $XA, $XB, $DM", IIC_VecPerm, []>;
+ "xxpermdi $XT, $XA, $XB, $DM", IIC_VecPerm,
+ [(set v2i64:$XT, (PPCxxpermdi v2i64:$XA, v2i64:$XB,
+ imm32SExt16:$DM))]>;
let isCodeGenOnly = 1 in
def XXPERMDIs : XX3Form_2s<60, 10, (outs vsrc:$XT), (ins vsfrc:$XA, u2imm:$DM),
"xxpermdi $XT, $XA, $XA, $DM", IIC_VecPerm, []>;
diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp
index ddae5befee3e..b9004cc8a9f5 100644
--- a/lib/Target/PowerPC/PPCTargetMachine.cpp
+++ b/lib/Target/PowerPC/PPCTargetMachine.cpp
@@ -296,7 +296,7 @@ namespace {
/// PPC Code Generator Pass Configuration Options.
class PPCPassConfig : public TargetPassConfig {
public:
- PPCPassConfig(PPCTargetMachine *TM, PassManagerBase &PM)
+ PPCPassConfig(PPCTargetMachine &TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {}
PPCTargetMachine &getPPCTargetMachine() const {
@@ -316,7 +316,7 @@ public:
} // end anonymous namespace
TargetPassConfig *PPCTargetMachine::createPassConfig(PassManagerBase &PM) {
- return new PPCPassConfig(this, PM);
+ return new PPCPassConfig(*this, PM);
}
void PPCPassConfig::addIRPasses() {
diff --git a/lib/Target/PowerPC/PPCTargetMachine.h b/lib/Target/PowerPC/PPCTargetMachine.h
index f2838351cee5..b8f5a2083d80 100644
--- a/lib/Target/PowerPC/PPCTargetMachine.h
+++ b/lib/Target/PowerPC/PPCTargetMachine.h
@@ -55,6 +55,10 @@ public:
const Triple &TT = getTargetTriple();
return (TT.getArch() == Triple::ppc64 || TT.getArch() == Triple::ppc64le);
};
+
+ bool isMachineVerifierClean() const override {
+ return false;
+ }
};
/// PowerPC 32-bit target machine.
diff --git a/lib/Target/PowerPC/PPCTargetTransformInfo.cpp b/lib/Target/PowerPC/PPCTargetTransformInfo.cpp
index 7ee1317bf72f..5559cdc5fe46 100644
--- a/lib/Target/PowerPC/PPCTargetTransformInfo.cpp
+++ b/lib/Target/PowerPC/PPCTargetTransformInfo.cpp
@@ -215,6 +215,11 @@ bool PPCTTIImpl::enableAggressiveInterleaving(bool LoopHasReductions) {
return LoopHasReductions;
}
+bool PPCTTIImpl::expandMemCmp(Instruction *I, unsigned &MaxLoadSize) {
+ MaxLoadSize = 8;
+ return true;
+}
+
bool PPCTTIImpl::enableInterleavedAccessVectorization() {
return true;
}
@@ -239,9 +244,18 @@ unsigned PPCTTIImpl::getRegisterBitWidth(bool Vector) {
}
unsigned PPCTTIImpl::getCacheLineSize() {
- // This is currently only used for the data prefetch pass which is only
- // enabled for BG/Q by default.
- return CacheLineSize;
+ // Check first if the user specified a custom line size.
+ if (CacheLineSize.getNumOccurrences() > 0)
+ return CacheLineSize;
+
+ // On P7, P8 or P9 we have a cache line size of 128.
+ unsigned Directive = ST->getDarwinDirective();
+ if (Directive == PPC::DIR_PWR7 || Directive == PPC::DIR_PWR8 ||
+ Directive == PPC::DIR_PWR9)
+ return 128;
+
+ // On other processors return a default of 64 bytes.
+ return 64;
}
unsigned PPCTTIImpl::getPrefetchDistance() {
diff --git a/lib/Target/PowerPC/PPCTargetTransformInfo.h b/lib/Target/PowerPC/PPCTargetTransformInfo.h
index 6ce70fbd8778..2e0116fee04c 100644
--- a/lib/Target/PowerPC/PPCTargetTransformInfo.h
+++ b/lib/Target/PowerPC/PPCTargetTransformInfo.h
@@ -60,6 +60,7 @@ public:
/// @{
bool enableAggressiveInterleaving(bool LoopHasReductions);
+ bool expandMemCmp(Instruction *I, unsigned &MaxLoadSize);
bool enableInterleavedAccessVectorization();
unsigned getNumberOfRegisters(bool Vector);
unsigned getRegisterBitWidth(bool Vector);
diff --git a/lib/Target/RISCV/RISCVTargetMachine.cpp b/lib/Target/RISCV/RISCVTargetMachine.cpp
index a20331cd0a3e..efdde04c582d 100644
--- a/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ b/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -56,5 +56,5 @@ RISCVTargetMachine::RISCVTargetMachine(const Target &T, const Triple &TT,
}
TargetPassConfig *RISCVTargetMachine::createPassConfig(PassManagerBase &PM) {
- return new TargetPassConfig(this, PM);
+ return new TargetPassConfig(*this, PM);
}
diff --git a/lib/Target/Sparc/SparcTargetMachine.cpp b/lib/Target/Sparc/SparcTargetMachine.cpp
index 1da4d3604304..49c67e0819f7 100644
--- a/lib/Target/Sparc/SparcTargetMachine.cpp
+++ b/lib/Target/Sparc/SparcTargetMachine.cpp
@@ -114,7 +114,7 @@ namespace {
/// Sparc Code Generator Pass Configuration Options.
class SparcPassConfig : public TargetPassConfig {
public:
- SparcPassConfig(SparcTargetMachine *TM, PassManagerBase &PM)
+ SparcPassConfig(SparcTargetMachine &TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {}
SparcTargetMachine &getSparcTargetMachine() const {
@@ -128,7 +128,7 @@ public:
} // namespace
TargetPassConfig *SparcTargetMachine::createPassConfig(PassManagerBase &PM) {
- return new SparcPassConfig(this, PM);
+ return new SparcPassConfig(*this, PM);
}
void SparcPassConfig::addIRPasses() {
diff --git a/lib/Target/Sparc/SparcTargetMachine.h b/lib/Target/Sparc/SparcTargetMachine.h
index 48193fe095be..faf714cbe2c9 100644
--- a/lib/Target/Sparc/SparcTargetMachine.h
+++ b/lib/Target/Sparc/SparcTargetMachine.h
@@ -40,6 +40,10 @@ public:
TargetLoweringObjectFile *getObjFileLowering() const override {
return TLOF.get();
}
+
+ bool isMachineVerifierClean() const override {
+ return false;
+ }
};
/// Sparc 32-bit target machine
diff --git a/lib/Target/SystemZ/SystemZTargetMachine.cpp b/lib/Target/SystemZ/SystemZTargetMachine.cpp
index ede5005fa491..f30d52f859d7 100644
--- a/lib/Target/SystemZ/SystemZTargetMachine.cpp
+++ b/lib/Target/SystemZ/SystemZTargetMachine.cpp
@@ -119,7 +119,7 @@ namespace {
/// SystemZ Code Generator Pass Configuration Options.
class SystemZPassConfig : public TargetPassConfig {
public:
- SystemZPassConfig(SystemZTargetMachine *TM, PassManagerBase &PM)
+ SystemZPassConfig(SystemZTargetMachine &TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {}
SystemZTargetMachine &getSystemZTargetMachine() const {
@@ -212,7 +212,7 @@ void SystemZPassConfig::addPreEmitPass() {
}
TargetPassConfig *SystemZTargetMachine::createPassConfig(PassManagerBase &PM) {
- return new SystemZPassConfig(this, PM);
+ return new SystemZPassConfig(*this, PM);
}
TargetIRAnalysis SystemZTargetMachine::getTargetIRAnalysis() {
diff --git a/lib/Target/SystemZ/SystemZTargetMachine.h b/lib/Target/SystemZ/SystemZTargetMachine.h
index a10ca64fa632..eb2f17a2091c 100644
--- a/lib/Target/SystemZ/SystemZTargetMachine.h
+++ b/lib/Target/SystemZ/SystemZTargetMachine.h
@@ -51,6 +51,8 @@ public:
}
bool targetSchedulesPostRAScheduling() const override { return true; };
+
+ bool isMachineVerifierClean() const override { return false; }
};
} // end namespace llvm
diff --git a/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
index b974681fb6af..d9b2b8743649 100644
--- a/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
+++ b/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
@@ -129,7 +129,7 @@ namespace {
/// WebAssembly Code Generator Pass Configuration Options.
class WebAssemblyPassConfig final : public TargetPassConfig {
public:
- WebAssemblyPassConfig(WebAssemblyTargetMachine *TM, PassManagerBase &PM)
+ WebAssemblyPassConfig(WebAssemblyTargetMachine &TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {}
WebAssemblyTargetMachine &getWebAssemblyTargetMachine() const {
@@ -154,7 +154,7 @@ TargetIRAnalysis WebAssemblyTargetMachine::getTargetIRAnalysis() {
TargetPassConfig *
WebAssemblyTargetMachine::createPassConfig(PassManagerBase &PM) {
- return new WebAssemblyPassConfig(this, PM);
+ return new WebAssemblyPassConfig(*this, PM);
}
FunctionPass *WebAssemblyPassConfig::createTargetRegisterAllocator(bool) {
diff --git a/lib/Target/X86/InstPrinter/X86InstComments.cpp b/lib/Target/X86/InstPrinter/X86InstComments.cpp
index 6e062ec59347..b5a926f915af 100644
--- a/lib/Target/X86/InstPrinter/X86InstComments.cpp
+++ b/lib/Target/X86/InstPrinter/X86InstComments.cpp
@@ -587,6 +587,7 @@ bool llvm::EmitAnyX86InstComments(const MCInst *MI, raw_ostream &OS,
case X86::VPSLLDQZ256rr:
case X86::VPSLLDQZ512rr:
Src1Name = getRegName(MI->getOperand(1).getReg());
+ LLVM_FALLTHROUGH;
case X86::VPSLLDQZ128rm:
case X86::VPSLLDQZ256rm:
case X86::VPSLLDQZ512rm:
@@ -604,6 +605,7 @@ bool llvm::EmitAnyX86InstComments(const MCInst *MI, raw_ostream &OS,
case X86::VPSRLDQZ256rr:
case X86::VPSRLDQZ512rr:
Src1Name = getRegName(MI->getOperand(1).getReg());
+ LLVM_FALLTHROUGH;
case X86::VPSRLDQZ128rm:
case X86::VPSRLDQZ256rm:
case X86::VPSRLDQZ512rm:
@@ -1091,6 +1093,7 @@ bool llvm::EmitAnyX86InstComments(const MCInst *MI, raw_ostream &OS,
CASE_AVX512_INS_COMMON(BROADCASTF32X2, Z256, r)
CASE_AVX512_INS_COMMON(BROADCASTI32X2, Z256, r)
Src1Name = getRegName(MI->getOperand(NumOperands - 1).getReg());
+ LLVM_FALLTHROUGH;
CASE_AVX512_INS_COMMON(BROADCASTF32X2, Z256, m)
CASE_AVX512_INS_COMMON(BROADCASTI32X2, Z256, m)
DecodeSubVectorBroadcast(MVT::v8f32, MVT::v2f32, ShuffleMask);
@@ -1099,6 +1102,7 @@ bool llvm::EmitAnyX86InstComments(const MCInst *MI, raw_ostream &OS,
CASE_AVX512_INS_COMMON(BROADCASTF32X2, Z, r)
CASE_AVX512_INS_COMMON(BROADCASTI32X2, Z, r)
Src1Name = getRegName(MI->getOperand(NumOperands - 1).getReg());
+ LLVM_FALLTHROUGH;
CASE_AVX512_INS_COMMON(BROADCASTF32X2, Z, m)
CASE_AVX512_INS_COMMON(BROADCASTI32X2, Z, m)
DecodeSubVectorBroadcast(MVT::v16f32, MVT::v2f32, ShuffleMask);
diff --git a/lib/Target/X86/X86FloatingPoint.cpp b/lib/Target/X86/X86FloatingPoint.cpp
index 313920e02c3e..5582526541ba 100644
--- a/lib/Target/X86/X86FloatingPoint.cpp
+++ b/lib/Target/X86/X86FloatingPoint.cpp
@@ -123,18 +123,26 @@ namespace {
EdgeBundles *Bundles;
// Return a bitmask of FP registers in block's live-in list.
- static unsigned calcLiveInMask(MachineBasicBlock *MBB) {
+ static unsigned calcLiveInMask(MachineBasicBlock *MBB, bool RemoveFPs) {
unsigned Mask = 0;
- for (const auto &LI : MBB->liveins()) {
- if (LI.PhysReg < X86::FP0 || LI.PhysReg > X86::FP6)
- continue;
- Mask |= 1 << (LI.PhysReg - X86::FP0);
+ for (MachineBasicBlock::livein_iterator I = MBB->livein_begin();
+ I != MBB->livein_end(); ) {
+ MCPhysReg Reg = I->PhysReg;
+ static_assert(X86::FP6 - X86::FP0 == 6, "sequential regnums");
+ if (Reg >= X86::FP0 && Reg <= X86::FP6) {
+ Mask |= 1 << (Reg - X86::FP0);
+ if (RemoveFPs) {
+ I = MBB->removeLiveIn(I);
+ continue;
+ }
+ }
+ ++I;
}
return Mask;
}
// Partition all the CFG edges into LiveBundles.
- void bundleCFG(MachineFunction &MF);
+ void bundleCFGRecomputeKillFlags(MachineFunction &MF);
MachineBasicBlock *MBB; // Current basic block
@@ -327,7 +335,7 @@ bool FPS::runOnMachineFunction(MachineFunction &MF) {
TII = MF.getSubtarget().getInstrInfo();
// Prepare cross-MBB liveness.
- bundleCFG(MF);
+ bundleCFGRecomputeKillFlags(MF);
StackTop = 0;
@@ -375,13 +383,15 @@ bool FPS::runOnMachineFunction(MachineFunction &MF) {
/// registers live-out from a block is identical to the live-in set of all
/// successors. This is not enforced by the normal live-in lists since
/// registers may be implicitly defined, or not used by all successors.
-void FPS::bundleCFG(MachineFunction &MF) {
+void FPS::bundleCFGRecomputeKillFlags(MachineFunction &MF) {
assert(LiveBundles.empty() && "Stale data in LiveBundles");
LiveBundles.resize(Bundles->getNumBundles());
// Gather the actual live-in masks for all MBBs.
for (MachineBasicBlock &MBB : MF) {
- const unsigned Mask = calcLiveInMask(&MBB);
+ setKillFlags(MBB);
+
+ const unsigned Mask = calcLiveInMask(&MBB, false);
if (!Mask)
continue;
// Update MBB ingoing bundle mask.
@@ -396,7 +406,6 @@ bool FPS::processBasicBlock(MachineFunction &MF, MachineBasicBlock &BB) {
bool Changed = false;
MBB = &BB;
- setKillFlags(BB);
setupBlockStack();
for (MachineBasicBlock::iterator I = BB.begin(); I != BB.end(); ++I) {
@@ -453,6 +462,7 @@ bool FPS::processBasicBlock(MachineFunction &MF, MachineBasicBlock &BB) {
unsigned Reg = DeadRegs[i];
// Check if Reg is live on the stack. An inline-asm register operand that
// is in the clobber list and marked dead might not be live on the stack.
+ static_assert(X86::FP7 - X86::FP0 == 7, "sequential FP regnumbers");
if (Reg >= X86::FP0 && Reg <= X86::FP6 && isLive(Reg-X86::FP0)) {
DEBUG(dbgs() << "Register FP#" << Reg-X86::FP0 << " is dead!\n");
freeStackSlotAfter(I, Reg-X86::FP0);
@@ -506,7 +516,6 @@ void FPS::setupBlockStack() {
// Push the fixed live-in registers.
for (unsigned i = Bundle.FixCount; i > 0; --i) {
- MBB->addLiveIn(X86::ST0+i-1);
DEBUG(dbgs() << "Live-in st(" << (i-1) << "): %FP"
<< unsigned(Bundle.FixStack[i-1]) << '\n');
pushReg(Bundle.FixStack[i-1]);
@@ -515,7 +524,8 @@ void FPS::setupBlockStack() {
// Kill off unwanted live-ins. This can happen with a critical edge.
// FIXME: We could keep these live registers around as zombies. They may need
// to be revived at the end of a short block. It might save a few instrs.
- adjustLiveRegs(calcLiveInMask(MBB), MBB->begin());
+ unsigned Mask = calcLiveInMask(MBB, /*RemoveFPs=*/true);
+ adjustLiveRegs(Mask, MBB->begin());
DEBUG(MBB->dump());
}
diff --git a/lib/Target/X86/X86FrameLowering.cpp b/lib/Target/X86/X86FrameLowering.cpp
index 331e56976db7..328a80304602 100644
--- a/lib/Target/X86/X86FrameLowering.cpp
+++ b/lib/Target/X86/X86FrameLowering.cpp
@@ -1062,6 +1062,8 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
}
if (HasFP) {
+ assert(MF.getRegInfo().isReserved(MachineFramePtr) && "FP reserved");
+
// Calculate required stack adjustment.
uint64_t FrameSize = StackSize - SlotSize;
// If required, include space for extra hidden slot for stashing base pointer.
@@ -1124,13 +1126,6 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
nullptr, DwarfFramePtr));
}
}
-
- // Mark the FramePtr as live-in in every block. Don't do this again for
- // funclet prologues.
- if (!IsFunclet) {
- for (MachineBasicBlock &EveryMBB : MF)
- EveryMBB.addLiveIn(MachineFramePtr);
- }
} else {
assert(!IsFunclet && "funclets without FPs not yet implemented");
NumBytes = StackSize - X86FI->getCalleeSavedFrameSize();
diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp
index c899f0fd5100..2a1633de0a23 100644
--- a/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -418,8 +418,6 @@ X86DAGToDAGISel::IsProfitableToFold(SDValue N, SDNode *U, SDNode *Root) const {
case X86ISD::XOR:
case X86ISD::OR:
case ISD::ADD:
- case ISD::ADDC:
- case ISD::ADDE:
case ISD::ADDCARRY:
case ISD::AND:
case ISD::OR:
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 8d78308afe9d..0a41f35f9320 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -1,3 +1,4 @@
+
//===-- X86ISelLowering.cpp - X86 DAG Lowering Implementation -------------===//
//
// The LLVM Compiler Infrastructure
@@ -80,12 +81,6 @@ static cl::opt<int> ExperimentalPrefLoopAlignment(
" of the loop header PC will be 0)."),
cl::Hidden);
-static cl::opt<bool> MulConstantOptimization(
- "mul-constant-optimization", cl::init(true),
- cl::desc("Replace 'mul x, Const' with more effective instructions like "
- "SHIFT, LEA, etc."),
- cl::Hidden);
-
/// Call this when the user attempts to do something unsupported, like
/// returning a double without SSE2 enabled on x86_64. This is not fatal, unlike
/// report_fatal_error, so calling code should attempt to recover without
@@ -317,16 +312,6 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
setOperationAction(ISD::UREM, VT, Expand);
}
- for (auto VT : { MVT::i8, MVT::i16, MVT::i32, MVT::i64 }) {
- if (VT == MVT::i64 && !Subtarget.is64Bit())
- continue;
- // Add/Sub overflow ops with MVT::Glues are lowered to EFLAGS dependences.
- setOperationAction(ISD::ADDC, VT, Custom);
- setOperationAction(ISD::ADDE, VT, Custom);
- setOperationAction(ISD::SUBC, VT, Custom);
- setOperationAction(ISD::SUBE, VT, Custom);
- }
-
setOperationAction(ISD::BR_JT , MVT::Other, Expand);
setOperationAction(ISD::BRCOND , MVT::Other, Custom);
for (auto VT : { MVT::f32, MVT::f64, MVT::f80, MVT::f128,
@@ -428,7 +413,6 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
continue;
setOperationAction(ISD::SELECT, VT, Custom);
setOperationAction(ISD::SETCC, VT, Custom);
- setOperationAction(ISD::SETCCE, VT, Custom);
}
setOperationAction(ISD::EH_RETURN , MVT::Other, Custom);
// NOTE: EH_SJLJ_SETJMP/_LONGJMP supported here is NOT intended to support
@@ -1583,6 +1567,7 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
// Support carry in as value rather than glue.
setOperationAction(ISD::ADDCARRY, VT, Custom);
setOperationAction(ISD::SUBCARRY, VT, Custom);
+ setOperationAction(ISD::SETCCCARRY, VT, Custom);
}
if (!Subtarget.is64Bit()) {
@@ -16304,6 +16289,7 @@ SDValue X86TargetLowering::EmitTest(SDValue Op, unsigned X86CC, const SDLoc &dl,
case ISD::SHL:
if (Op.getNode()->getFlags().hasNoSignedWrap())
break;
+ LLVM_FALLTHROUGH;
default:
NeedOF = true;
break;
@@ -17167,17 +17153,17 @@ static SDValue LowerVSETCC(SDValue Op, const X86Subtarget &Subtarget,
switch (SetCCOpcode) {
default: llvm_unreachable("Unexpected SETCC condition");
- case ISD::SETNE: Invert = true;
+ case ISD::SETNE: Invert = true; LLVM_FALLTHROUGH;
case ISD::SETEQ: Opc = X86ISD::PCMPEQ; break;
- case ISD::SETLT: Swap = true;
+ case ISD::SETLT: Swap = true; LLVM_FALLTHROUGH;
case ISD::SETGT: Opc = X86ISD::PCMPGT; break;
- case ISD::SETGE: Swap = true;
+ case ISD::SETGE: Swap = true; LLVM_FALLTHROUGH;
case ISD::SETLE: Opc = X86ISD::PCMPGT;
Invert = true; break;
- case ISD::SETULT: Swap = true;
+ case ISD::SETULT: Swap = true; LLVM_FALLTHROUGH;
case ISD::SETUGT: Opc = X86ISD::PCMPGT;
FlipSigns = true; break;
- case ISD::SETUGE: Swap = true;
+ case ISD::SETUGE: Swap = true; LLVM_FALLTHROUGH;
case ISD::SETULE: Opc = X86ISD::PCMPGT;
FlipSigns = true; Invert = true; break;
}
@@ -17398,19 +17384,24 @@ SDValue X86TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
return SetCC;
}
-SDValue X86TargetLowering::LowerSETCCE(SDValue Op, SelectionDAG &DAG) const {
+SDValue X86TargetLowering::LowerSETCCCARRY(SDValue Op, SelectionDAG &DAG) const {
SDValue LHS = Op.getOperand(0);
SDValue RHS = Op.getOperand(1);
SDValue Carry = Op.getOperand(2);
SDValue Cond = Op.getOperand(3);
SDLoc DL(Op);
- assert(LHS.getSimpleValueType().isInteger() && "SETCCE is integer only.");
+ assert(LHS.getSimpleValueType().isInteger() && "SETCCCARRY is integer only.");
X86::CondCode CC = TranslateIntegerX86CC(cast<CondCodeSDNode>(Cond)->get());
- assert(Carry.getOpcode() != ISD::CARRY_FALSE);
+ // Recreate the carry if needed.
+ EVT CarryVT = Carry.getValueType();
+ APInt NegOne = APInt::getAllOnesValue(CarryVT.getScalarSizeInBits());
+ Carry = DAG.getNode(X86ISD::ADD, DL, DAG.getVTList(CarryVT, MVT::i32),
+ Carry, DAG.getConstant(NegOne, DL, CarryVT));
+
SDVTList VTs = DAG.getVTList(LHS.getValueType(), MVT::i32);
- SDValue Cmp = DAG.getNode(X86ISD::SBB, DL, VTs, LHS, RHS, Carry);
+ SDValue Cmp = DAG.getNode(X86ISD::SBB, DL, VTs, LHS, RHS, Carry.getValue(1));
SDValue SetCC = getSETCC(CC, Cmp.getValue(1), DL, DAG);
if (Op.getSimpleValueType() == MVT::i1)
return DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, SetCC);
@@ -23269,32 +23260,6 @@ static SDValue LowerATOMIC_STORE(SDValue Op, SelectionDAG &DAG) {
return Op;
}
-static SDValue LowerADDC_ADDE_SUBC_SUBE(SDValue Op, SelectionDAG &DAG) {
- MVT VT = Op.getNode()->getSimpleValueType(0);
-
- // Let legalize expand this if it isn't a legal type yet.
- if (!DAG.getTargetLoweringInfo().isTypeLegal(VT))
- return SDValue();
-
- SDVTList VTs = DAG.getVTList(VT, MVT::i32);
-
- unsigned Opc;
- bool ExtraOp = false;
- switch (Op.getOpcode()) {
- default: llvm_unreachable("Invalid code");
- case ISD::ADDC: Opc = X86ISD::ADD; break;
- case ISD::ADDE: Opc = X86ISD::ADC; ExtraOp = true; break;
- case ISD::SUBC: Opc = X86ISD::SUB; break;
- case ISD::SUBE: Opc = X86ISD::SBB; ExtraOp = true; break;
- }
-
- if (!ExtraOp)
- return DAG.getNode(Opc, SDLoc(Op), VTs, Op.getOperand(0),
- Op.getOperand(1));
- return DAG.getNode(Opc, SDLoc(Op), VTs, Op.getOperand(0),
- Op.getOperand(1), Op.getOperand(2));
-}
-
static SDValue LowerADDSUBCARRY(SDValue Op, SelectionDAG &DAG) {
SDNode *N = Op.getNode();
MVT VT = N->getSimpleValueType(0);
@@ -23785,7 +23750,7 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG);
case ISD::FGETSIGN: return LowerFGETSIGN(Op, DAG);
case ISD::SETCC: return LowerSETCC(Op, DAG);
- case ISD::SETCCE: return LowerSETCCE(Op, DAG);
+ case ISD::SETCCCARRY: return LowerSETCCCARRY(Op, DAG);
case ISD::SELECT: return LowerSELECT(Op, DAG);
case ISD::BRCOND: return LowerBRCOND(Op, DAG);
case ISD::JumpTable: return LowerJumpTable(Op, DAG);
@@ -23830,10 +23795,6 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::UMULO: return LowerXALUO(Op, DAG);
case ISD::READCYCLECOUNTER: return LowerREADCYCLECOUNTER(Op, Subtarget,DAG);
case ISD::BITCAST: return LowerBITCAST(Op, Subtarget, DAG);
- case ISD::ADDC:
- case ISD::ADDE:
- case ISD::SUBC:
- case ISD::SUBE: return LowerADDC_ADDE_SUBC_SUBE(Op, DAG);
case ISD::ADDCARRY:
case ISD::SUBCARRY: return LowerADDSUBCARRY(Op, DAG);
case ISD::ADD:
@@ -28946,12 +28907,118 @@ static SDValue XFormVExtractWithShuffleIntoLoad(SDNode *N, SelectionDAG &DAG,
EltNo);
}
+// Try to match patterns such as
+// (i16 bitcast (v16i1 x))
+// ->
+// (i16 movmsk (16i8 sext (v16i1 x)))
+// before the illegal vector is scalarized on subtargets that don't have legal
+// vxi1 types.
+static SDValue combineBitcastvxi1(SelectionDAG &DAG, SDValue BitCast,
+ const X86Subtarget &Subtarget) {
+ EVT VT = BitCast.getValueType();
+ SDValue N0 = BitCast.getOperand(0);
+ EVT VecVT = N0->getValueType(0);
+
+ if (!VT.isScalarInteger() || !VecVT.isSimple())
+ return SDValue();
+
+ // With AVX512 vxi1 types are legal and we prefer using k-regs.
+ // MOVMSK is supported in SSE2 or later.
+ if (Subtarget.hasAVX512() || !Subtarget.hasSSE2())
+ return SDValue();
+
+ // There are MOVMSK flavors for types v16i8, v32i8, v4f32, v8f32, v4f64 and
+ // v8f64. So all legal 128-bit and 256-bit vectors are covered except for
+ // v8i16 and v16i16.
+ // For these two cases, we can shuffle the upper element bytes to a
+ // consecutive sequence at the start of the vector and treat the results as
+ // v16i8 or v32i8, and for v61i8 this is the prefferable solution. However,
+ // for v16i16 this is not the case, because the shuffle is expensive, so we
+ // avoid sign-exteding to this type entirely.
+ // For example, t0 := (v8i16 sext(v8i1 x)) needs to be shuffled as:
+ // (v16i8 shuffle <0,2,4,6,8,10,12,14,u,u,...,u> (v16i8 bitcast t0), undef)
+ MVT SExtVT;
+ MVT FPCastVT = MVT::INVALID_SIMPLE_VALUE_TYPE;
+ switch (VecVT.getSimpleVT().SimpleTy) {
+ default:
+ return SDValue();
+ case MVT::v2i1:
+ SExtVT = MVT::v2i64;
+ FPCastVT = MVT::v2f64;
+ break;
+ case MVT::v4i1:
+ SExtVT = MVT::v4i32;
+ FPCastVT = MVT::v4f32;
+ // For cases such as (i4 bitcast (v4i1 setcc v4i64 v1, v2))
+ // sign-extend to a 256-bit operation to avoid truncation.
+ if (N0->getOpcode() == ISD::SETCC &&
+ N0->getOperand(0)->getValueType(0).is256BitVector() &&
+ Subtarget.hasInt256()) {
+ SExtVT = MVT::v4i64;
+ FPCastVT = MVT::v4f64;
+ }
+ break;
+ case MVT::v8i1:
+ SExtVT = MVT::v8i16;
+ // For cases such as (i8 bitcast (v8i1 setcc v8i32 v1, v2)),
+ // sign-extend to a 256-bit operation to match the compare.
+ // If the setcc operand is 128-bit, prefer sign-extending to 128-bit over
+ // 256-bit because the shuffle is cheaper than sign extending the result of
+ // the compare.
+ if (N0->getOpcode() == ISD::SETCC &&
+ N0->getOperand(0)->getValueType(0).is256BitVector() &&
+ Subtarget.hasInt256()) {
+ SExtVT = MVT::v8i32;
+ FPCastVT = MVT::v8f32;
+ }
+ break;
+ case MVT::v16i1:
+ SExtVT = MVT::v16i8;
+ // For the case (i16 bitcast (v16i1 setcc v16i16 v1, v2)),
+ // it is not profitable to sign-extend to 256-bit because this will
+ // require an extra cross-lane shuffle which is more exprensive than
+ // truncating the result of the compare to 128-bits.
+ break;
+ case MVT::v32i1:
+ // TODO: Handle pre-AVX2 cases by splitting to two v16i1's.
+ if (!Subtarget.hasInt256())
+ return SDValue();
+ SExtVT = MVT::v32i8;
+ break;
+ };
+
+ SDLoc DL(BitCast);
+ SDValue V = DAG.getSExtOrTrunc(N0, DL, SExtVT);
+ if (SExtVT == MVT::v8i16) {
+ V = DAG.getBitcast(MVT::v16i8, V);
+ V = DAG.getVectorShuffle(
+ MVT::v16i8, DL, V, DAG.getUNDEF(MVT::v16i8),
+ {0, 2, 4, 6, 8, 10, 12, 14, -1, -1, -1, -1, -1, -1, -1, -1});
+ } else
+ assert(SExtVT.getScalarType() != MVT::i16 &&
+ "Vectors of i16 must be shuffled");
+ if (FPCastVT != MVT::INVALID_SIMPLE_VALUE_TYPE)
+ V = DAG.getBitcast(FPCastVT, V);
+ V = DAG.getNode(X86ISD::MOVMSK, DL, MVT::i32, V);
+ return DAG.getZExtOrTrunc(V, DL, VT);
+}
+
static SDValue combineBitcast(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
const X86Subtarget &Subtarget) {
SDValue N0 = N->getOperand(0);
EVT VT = N->getValueType(0);
EVT SrcVT = N0.getValueType();
+ // Try to match patterns such as
+ // (i16 bitcast (v16i1 x))
+ // ->
+ // (i16 movmsk (16i8 sext (v16i1 x)))
+ // before the setcc result is scalarized on subtargets that don't have legal
+ // vxi1 types.
+ if (DCI.isBeforeLegalize())
+ if (SDValue V = combineBitcastvxi1(DAG, SDValue(N, 0), Subtarget))
+ return V;
// Since MMX types are special and don't usually play with other vector types,
// it's better to handle them early to be sure we emit efficient code by
// avoiding store-load conversions.
@@ -29944,6 +30011,7 @@ static SDValue combineSelect(SDNode *N, SelectionDAG &DAG,
// Converting this to a min would handle both negative zeros and NaNs
// incorrectly, but we can swap the operands to fix both.
std::swap(LHS, RHS);
+ LLVM_FALLTHROUGH;
case ISD::SETOLT:
case ISD::SETLT:
case ISD::SETLE:
@@ -29974,6 +30042,7 @@ static SDValue combineSelect(SDNode *N, SelectionDAG &DAG,
// Converting this to a max would handle both negative zeros and NaNs
// incorrectly, but we can swap the operands to fix both.
std::swap(LHS, RHS);
+ LLVM_FALLTHROUGH;
case ISD::SETOGT:
case ISD::SETGT:
case ISD::SETGE:
@@ -30008,6 +30077,7 @@ static SDValue combineSelect(SDNode *N, SelectionDAG &DAG,
// Converting this to a min would handle both negative zeros and NaNs
// incorrectly, but we can swap the operands to fix both.
std::swap(LHS, RHS);
+ LLVM_FALLTHROUGH;
case ISD::SETOGT:
case ISD::SETGT:
case ISD::SETGE:
@@ -30036,6 +30106,7 @@ static SDValue combineSelect(SDNode *N, SelectionDAG &DAG,
// Converting this to a max would handle both negative zeros and NaNs
// incorrectly, but we can swap the operands to fix both.
std::swap(LHS, RHS);
+ LLVM_FALLTHROUGH;
case ISD::SETOLT:
case ISD::SETLT:
case ISD::SETLE:
@@ -30933,75 +31004,6 @@ static SDValue reduceVMULWidth(SDNode *N, SelectionDAG &DAG,
}
}
-static SDValue combineMulSpecial(uint64_t MulAmt, SDNode *N, SelectionDAG &DAG,
- EVT VT, SDLoc DL) {
-
- auto combineMulShlAddOrSub = [&](int Mult, int Shift, bool isAdd) {
- SDValue Result = DAG.getNode(X86ISD::MUL_IMM, DL, VT, N->getOperand(0),
- DAG.getConstant(Mult, DL, VT));
- Result = DAG.getNode(ISD::SHL, DL, VT, Result,
- DAG.getConstant(Shift, DL, MVT::i8));
- Result = DAG.getNode(isAdd ? ISD::ADD : ISD::SUB, DL, VT, N->getOperand(0),
- Result);
- return Result;
- };
-
- auto combineMulMulAddOrSub = [&](bool isAdd) {
- SDValue Result = DAG.getNode(X86ISD::MUL_IMM, DL, VT, N->getOperand(0),
- DAG.getConstant(9, DL, VT));
- Result = DAG.getNode(ISD::MUL, DL, VT, Result, DAG.getConstant(3, DL, VT));
- Result = DAG.getNode(isAdd ? ISD::ADD : ISD::SUB, DL, VT, N->getOperand(0),
- Result);
- return Result;
- };
-
- switch (MulAmt) {
- default:
- break;
- case 11:
- // mul x, 11 => add ((shl (mul x, 5), 1), x)
- return combineMulShlAddOrSub(5, 1, /*isAdd*/ true);
- case 21:
- // mul x, 21 => add ((shl (mul x, 5), 2), x)
- return combineMulShlAddOrSub(5, 2, /*isAdd*/ true);
- case 22:
- // mul x, 22 => add (add ((shl (mul x, 5), 2), x), x)
- return DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0),
- combineMulShlAddOrSub(5, 2, /*isAdd*/ true));
- case 19:
- // mul x, 19 => sub ((shl (mul x, 5), 2), x)
- return combineMulShlAddOrSub(5, 2, /*isAdd*/ false);
- case 13:
- // mul x, 13 => add ((shl (mul x, 3), 2), x)
- return combineMulShlAddOrSub(3, 2, /*isAdd*/ true);
- case 23:
- // mul x, 13 => sub ((shl (mul x, 3), 3), x)
- return combineMulShlAddOrSub(3, 3, /*isAdd*/ false);
- case 14:
- // mul x, 14 => add (add ((shl (mul x, 3), 2), x), x)
- return DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0),
- combineMulShlAddOrSub(3, 2, /*isAdd*/ true));
- case 26:
- // mul x, 26 => sub ((mul (mul x, 9), 3), x)
- return combineMulMulAddOrSub(/*isAdd*/ false);
- case 28:
- // mul x, 28 => add ((mul (mul x, 9), 3), x)
- return combineMulMulAddOrSub(/*isAdd*/ true);
- case 29:
- // mul x, 29 => add (add ((mul (mul x, 9), 3), x), x)
- return DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0),
- combineMulMulAddOrSub(/*isAdd*/ true));
- case 30:
- // mul x, 30 => sub (sub ((shl x, 5), x), x)
- return DAG.getNode(
- ISD::SUB, DL, VT, N->getOperand(0),
- DAG.getNode(ISD::SUB, DL, VT, N->getOperand(0),
- DAG.getNode(ISD::SHL, DL, VT, N->getOperand(0),
- DAG.getConstant(5, DL, MVT::i8))));
- }
- return SDValue();
-}
-
/// Optimize a single multiply with constant into two operations in order to
/// implement it with two cheaper instructions, e.g. LEA + SHL, LEA + LEA.
static SDValue combineMul(SDNode *N, SelectionDAG &DAG,
@@ -31011,8 +31013,6 @@ static SDValue combineMul(SDNode *N, SelectionDAG &DAG,
if (DCI.isBeforeLegalize() && VT.isVector())
return reduceVMULWidth(N, DAG, Subtarget);
- if (!MulConstantOptimization)
- return SDValue();
// An imul is usually smaller than the alternative sequence.
if (DAG.getMachineFunction().getFunction()->optForMinSize())
return SDValue();
@@ -31068,8 +31068,7 @@ static SDValue combineMul(SDNode *N, SelectionDAG &DAG,
else
NewMul = DAG.getNode(X86ISD::MUL_IMM, DL, VT, NewMul,
DAG.getConstant(MulAmt2, DL, VT));
- } else if (!Subtarget.slowLEA())
- NewMul = combineMulSpecial(MulAmt, N, DAG, VT, DL);
+ }
if (!NewMul) {
assert(MulAmt != 0 &&
@@ -34558,8 +34557,7 @@ static SDValue combineX86ADD(SDNode *N, SelectionDAG &DAG,
isOneConstant(Carry.getOperand(1))))
Carry = Carry.getOperand(0);
- if (Carry.getOpcode() == ISD::SETCC ||
- Carry.getOpcode() == X86ISD::SETCC ||
+ if (Carry.getOpcode() == X86ISD::SETCC ||
Carry.getOpcode() == X86ISD::SETCC_CARRY) {
if (Carry.getConstantOperandVal(0) == X86::COND_B)
return DCI.CombineTo(N, SDValue(N, 0), Carry.getOperand(1));
@@ -35126,7 +35124,7 @@ SDValue X86TargetLowering::PerformDAGCombine(SDNode *N,
case ISD::VSELECT:
case ISD::SELECT:
case X86ISD::SHRUNKBLEND: return combineSelect(N, DAG, DCI, Subtarget);
- case ISD::BITCAST: return combineBitcast(N, DAG, Subtarget);
+ case ISD::BITCAST: return combineBitcast(N, DAG, DCI, Subtarget);
case X86ISD::CMOV: return combineCMov(N, DAG, DCI, Subtarget);
case ISD::ADD: return combineAdd(N, DAG, Subtarget);
case ISD::SUB: return combineSub(N, DAG, Subtarget);
@@ -35510,6 +35508,7 @@ TargetLowering::ConstraintWeight
switch (*constraint) {
default:
weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
+ LLVM_FALLTHROUGH;
case 'R':
case 'q':
case 'Q':
@@ -35861,6 +35860,7 @@ X86TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
return std::make_pair(0U, &X86::GR64RegClass);
break;
}
+ LLVM_FALLTHROUGH;
// 32-bit fallthrough
case 'Q': // Q_REGS
if (VT == MVT::i32 || VT == MVT::f32)
diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h
index 18106c2eb394..f51b6641db2f 100644
--- a/lib/Target/X86/X86ISelLowering.h
+++ b/lib/Target/X86/X86ISelLowering.h
@@ -1163,7 +1163,7 @@ namespace llvm {
SDValue LowerToBT(SDValue And, ISD::CondCode CC, const SDLoc &dl,
SelectionDAG &DAG) const;
SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
- SDValue LowerSETCCE(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerSETCCCARRY(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerBRCOND(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp
index 33fbd41bb631..0aee30081a35 100644
--- a/lib/Target/X86/X86InstrInfo.cpp
+++ b/lib/Target/X86/X86InstrInfo.cpp
@@ -195,6 +195,7 @@ X86InstrInfo::isCoalescableExtInstr(const MachineInstr &MI,
// It's not always legal to reference the low 8-bit of the larger
// register in 32-bit mode.
return false;
+ LLVM_FALLTHROUGH;
case X86::MOVSX32rr16:
case X86::MOVZX32rr16:
case X86::MOVSX64rr16:
diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp
index 53a8e83b36fc..cb21f1bd7706 100644
--- a/lib/Target/X86/X86TargetMachine.cpp
+++ b/lib/Target/X86/X86TargetMachine.cpp
@@ -323,7 +323,7 @@ namespace {
/// X86 Code Generator Pass Configuration Options.
class X86PassConfig : public TargetPassConfig {
public:
- X86PassConfig(X86TargetMachine *TM, PassManagerBase &PM)
+ X86PassConfig(X86TargetMachine &TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {}
X86TargetMachine &getX86TargetMachine() const {
@@ -369,7 +369,7 @@ INITIALIZE_PASS(X86ExecutionDepsFix, "x86-execution-deps-fix",
"X86 Execution Dependency Fix", false, false)
TargetPassConfig *X86TargetMachine::createPassConfig(PassManagerBase &PM) {
- return new X86PassConfig(this, PM);
+ return new X86PassConfig(*this, PM);
}
void X86PassConfig::addIRPasses() {
@@ -433,6 +433,7 @@ bool X86PassConfig::addPreISel() {
void X86PassConfig::addPreRegAlloc() {
if (getOptLevel() != CodeGenOpt::None) {
+ addPass(&LiveRangeShrinkID);
addPass(createX86FixupSetCC());
addPass(createX86OptimizeLEAs());
addPass(createX86CallFrameOptimization());
diff --git a/lib/Target/X86/X86TargetMachine.h b/lib/Target/X86/X86TargetMachine.h
index cf933f52604e..1bf267d34ec2 100644
--- a/lib/Target/X86/X86TargetMachine.h
+++ b/lib/Target/X86/X86TargetMachine.h
@@ -49,6 +49,10 @@ public:
TargetLoweringObjectFile *getObjFileLowering() const override {
return TLOF.get();
}
+
+ bool isMachineVerifierClean() const override {
+ return false;
+ }
};
} // end namespace llvm
diff --git a/lib/Target/XCore/XCoreTargetMachine.cpp b/lib/Target/XCore/XCoreTargetMachine.cpp
index 2950e2efbea3..1a1cbd474888 100644
--- a/lib/Target/XCore/XCoreTargetMachine.cpp
+++ b/lib/Target/XCore/XCoreTargetMachine.cpp
@@ -54,7 +54,7 @@ namespace {
/// XCore Code Generator Pass Configuration Options.
class XCorePassConfig : public TargetPassConfig {
public:
- XCorePassConfig(XCoreTargetMachine *TM, PassManagerBase &PM)
+ XCorePassConfig(XCoreTargetMachine &TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {}
XCoreTargetMachine &getXCoreTargetMachine() const {
@@ -70,7 +70,7 @@ public:
} // end anonymous namespace
TargetPassConfig *XCoreTargetMachine::createPassConfig(PassManagerBase &PM) {
- return new XCorePassConfig(this, PM);
+ return new XCorePassConfig(*this, PM);
}
void XCorePassConfig::addIRPasses() {
diff --git a/lib/Transforms/Coroutines/CoroCleanup.cpp b/lib/Transforms/Coroutines/CoroCleanup.cpp
index 5cf2a8c25d83..359876627fce 100644
--- a/lib/Transforms/Coroutines/CoroCleanup.cpp
+++ b/lib/Transforms/Coroutines/CoroCleanup.cpp
@@ -101,7 +101,9 @@ namespace {
struct CoroCleanup : FunctionPass {
static char ID; // Pass identification, replacement for typeid
- CoroCleanup() : FunctionPass(ID) {}
+ CoroCleanup() : FunctionPass(ID) {
+ initializeCoroCleanupPass(*PassRegistry::getPassRegistry());
+ }
std::unique_ptr<Lowerer> L;
diff --git a/lib/Transforms/Coroutines/CoroEarly.cpp b/lib/Transforms/Coroutines/CoroEarly.cpp
index b52989186165..ba05896af150 100644
--- a/lib/Transforms/Coroutines/CoroEarly.cpp
+++ b/lib/Transforms/Coroutines/CoroEarly.cpp
@@ -183,7 +183,9 @@ namespace {
struct CoroEarly : public FunctionPass {
static char ID; // Pass identification, replacement for typeid.
- CoroEarly() : FunctionPass(ID) {}
+ CoroEarly() : FunctionPass(ID) {
+ initializeCoroEarlyPass(*PassRegistry::getPassRegistry());
+ }
std::unique_ptr<Lowerer> L;
diff --git a/lib/Transforms/Coroutines/CoroElide.cpp b/lib/Transforms/Coroutines/CoroElide.cpp
index acb22449142b..42fd6d746145 100644
--- a/lib/Transforms/Coroutines/CoroElide.cpp
+++ b/lib/Transforms/Coroutines/CoroElide.cpp
@@ -258,7 +258,9 @@ static bool replaceDevirtTrigger(Function &F) {
namespace {
struct CoroElide : FunctionPass {
static char ID;
- CoroElide() : FunctionPass(ID) {}
+ CoroElide() : FunctionPass(ID) {
+ initializeCoroElidePass(*PassRegistry::getPassRegistry());
+ }
std::unique_ptr<Lowerer> L;
diff --git a/lib/Transforms/Coroutines/CoroSplit.cpp b/lib/Transforms/Coroutines/CoroSplit.cpp
index cd549e4be282..613b4a7f03e9 100644
--- a/lib/Transforms/Coroutines/CoroSplit.cpp
+++ b/lib/Transforms/Coroutines/CoroSplit.cpp
@@ -681,7 +681,9 @@ namespace {
struct CoroSplit : public CallGraphSCCPass {
static char ID; // Pass identification, replacement for typeid
- CoroSplit() : CallGraphSCCPass(ID) {}
+ CoroSplit() : CallGraphSCCPass(ID) {
+ initializeCoroSplitPass(*PassRegistry::getPassRegistry());
+ }
bool Run = false;
diff --git a/lib/Transforms/IPO/PartialInlining.cpp b/lib/Transforms/IPO/PartialInlining.cpp
index 4c417f1c55eb..bc0967448cdd 100644
--- a/lib/Transforms/IPO/PartialInlining.cpp
+++ b/lib/Transforms/IPO/PartialInlining.cpp
@@ -652,12 +652,21 @@ Function *PartialInlinerImpl::unswitchFunction(Function *F) {
// only split block when necessary:
PHINode *FirstPhi = getFirstPHI(PreReturn);
unsigned NumPredsFromEntries = OI->ReturnBlockPreds.size();
+ auto IsTrivialPhi = [](PHINode *PN) -> Value * {
+ Value *CommonValue = PN->getIncomingValue(0);
+ if (all_of(PN->incoming_values(),
+ [&](Value *V) { return V == CommonValue; }))
+ return CommonValue;
+ return nullptr;
+ };
+
if (FirstPhi && FirstPhi->getNumIncomingValues() > NumPredsFromEntries + 1) {
NewReturnBlock = NewReturnBlock->splitBasicBlock(
NewReturnBlock->getFirstNonPHI()->getIterator());
BasicBlock::iterator I = PreReturn->begin();
Instruction *Ins = &NewReturnBlock->front();
+ SmallVector<Instruction *, 4> DeadPhis;
while (I != PreReturn->end()) {
PHINode *OldPhi = dyn_cast<PHINode>(I);
if (!OldPhi)
@@ -674,8 +683,22 @@ Function *PartialInlinerImpl::unswitchFunction(Function *F) {
RetPhi->addIncoming(OldPhi->getIncomingValueForBlock(NewE), NewE);
OldPhi->removeIncomingValue(NewE);
}
+
+ // After incoming values splitting, the old phi may become trivial.
+ // Keeping the trivial phi can introduce definition inside the outline
+ // region which is live-out, causing necessary overhead (load, store
+ // arg passing etc).
+ if (auto *OldPhiVal = IsTrivialPhi(OldPhi)) {
+ OldPhi->replaceAllUsesWith(OldPhiVal);
+ DeadPhis.push_back(OldPhi);
+ }
+
++I;
}
+
+ for (auto *DP : DeadPhis)
+ DP->eraseFromParent();
+
for (auto E : OI->ReturnBlockPreds) {
BasicBlock *NewE = cast<BasicBlock>(VMap[E]);
NewE->getTerminator()->replaceUsesOfWith(PreReturn, NewReturnBlock);
diff --git a/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp b/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
index 659cb9df00a2..9dede4cedd1d 100644
--- a/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
+++ b/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
@@ -6,14 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This pass prepares a module containing type metadata for ThinLTO by splitting
-// it into regular and thin LTO parts if possible, and writing both parts to
-// a multi-module bitcode file. Modules that do not contain type metadata are
-// written unmodified as a single module.
-//
-//===----------------------------------------------------------------------===//
+#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/Analysis/ModuleSummaryAnalysis.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
@@ -436,3 +430,15 @@ ModulePass *llvm::createWriteThinLTOBitcodePass(raw_ostream &Str,
raw_ostream *ThinLinkOS) {
return new WriteThinLTOBitcode(Str, ThinLinkOS);
}
+
+PreservedAnalyses
+llvm::ThinLTOBitcodeWriterPass::run(Module &M, ModuleAnalysisManager &AM) {
+ FunctionAnalysisManager &FAM =
+ AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
+ writeThinLTOBitcode(OS, ThinLinkOS,
+ [&FAM](Function &F) -> AAResults & {
+ return FAM.getResult<AAManager>(F);
+ },
+ M, &AM.getResult<ModuleSummaryIndexAnalysis>(M));
+ return PreservedAnalyses::all();
+}
diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 92a38f26dde7..b44499ec4be9 100644
--- a/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3838,24 +3838,24 @@ Instruction *InstCombiner::visitCallSite(CallSite CS) {
// Mark any parameters that are known to be non-null with the nonnull
// attribute. This is helpful for inlining calls to functions with null
// checks on their arguments.
- SmallVector<unsigned, 4> Indices;
+ SmallVector<unsigned, 4> ArgNos;
unsigned ArgNo = 0;
for (Value *V : CS.args()) {
if (V->getType()->isPointerTy() &&
!CS.paramHasAttr(ArgNo, Attribute::NonNull) &&
isKnownNonNullAt(V, CS.getInstruction(), &DT))
- Indices.push_back(ArgNo + AttributeList::FirstArgIndex);
+ ArgNos.push_back(ArgNo);
ArgNo++;
}
assert(ArgNo == CS.arg_size() && "sanity check");
- if (!Indices.empty()) {
+ if (!ArgNos.empty()) {
AttributeList AS = CS.getAttributes();
LLVMContext &Ctx = CS.getInstruction()->getContext();
- AS = AS.addAttribute(Ctx, Indices,
- Attribute::get(Ctx, Attribute::NonNull));
+ AS = AS.addParamAttribute(Ctx, ArgNos,
+ Attribute::get(Ctx, Attribute::NonNull));
CS.setAttributes(AS);
Changed = true;
}
diff --git a/lib/Transforms/Instrumentation/PGOInstrumentation.cpp b/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
index 1e30dbf6b55a..b2d95271479c 100644
--- a/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
+++ b/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
@@ -182,6 +182,14 @@ static cl::opt<bool>
cl::desc("Use this option to turn on/off "
"memory intrinsic size profiling."));
+// Emit branch probability as optimization remarks.
+static cl::opt<bool>
+ EmitBranchProbability("pgo-emit-branch-prob", cl::init(false), cl::Hidden,
+ cl::desc("When this option is on, the annotated "
+ "branch probability will be emitted as "
+ " optimization remarks: -Rpass-analysis="
+ "pgo-instr-use"));
+
// Command line option to turn on CFG dot dump after profile annotation.
// Defined in Analysis/BlockFrequencyInfo.cpp: -pgo-view-counts
extern cl::opt<bool> PGOViewCounts;
@@ -192,6 +200,39 @@ extern cl::opt<std::string> ViewBlockFreqFuncName;
namespace {
+// Return a string describing the branch condition that can be
+// used in static branch probability heuristics:
+std::string getBranchCondString(Instruction *TI) {
+ BranchInst *BI = dyn_cast<BranchInst>(TI);
+ if (!BI || !BI->isConditional())
+ return std::string();
+
+ Value *Cond = BI->getCondition();
+ ICmpInst *CI = dyn_cast<ICmpInst>(Cond);
+ if (!CI)
+ return std::string();
+
+ std::string result;
+ raw_string_ostream OS(result);
+ OS << CmpInst::getPredicateName(CI->getPredicate()) << "_";
+ CI->getOperand(0)->getType()->print(OS, true);
+
+ Value *RHS = CI->getOperand(1);
+ ConstantInt *CV = dyn_cast<ConstantInt>(RHS);
+ if (CV) {
+ if (CV->isZero())
+ OS << "_Zero";
+ else if (CV->isOne())
+ OS << "_One";
+ else if (CV->isAllOnesValue())
+ OS << "_MinusOne";
+ else
+ OS << "_Const";
+ }
+ OS.flush();
+ return result;
+}
+
/// The select instruction visitor plays three roles specified
/// by the mode. In \c VM_counting mode, it simply counts the number of
/// select instructions. In \c VM_instrument mode, it inserts code to count
@@ -1424,6 +1465,29 @@ void setProfMetadata(Module *M, Instruction *TI, ArrayRef<uint64_t> EdgeCounts,
for (const auto &W : Weights) { dbgs() << W << " "; }
dbgs() << "\n";);
TI->setMetadata(llvm::LLVMContext::MD_prof, MDB.createBranchWeights(Weights));
+ if (EmitBranchProbability) {
+ std::string BrCondStr = getBranchCondString(TI);
+ if (BrCondStr.empty())
+ return;
+
+ unsigned WSum =
+ std::accumulate(Weights.begin(), Weights.end(), 0,
+ [](unsigned w1, unsigned w2) { return w1 + w2; });
+ uint64_t TotalCount =
+ std::accumulate(EdgeCounts.begin(), EdgeCounts.end(), 0,
+ [](uint64_t c1, uint64_t c2) { return c1 + c2; });
+ BranchProbability BP(Weights[0], WSum);
+ std::string BranchProbStr;
+ raw_string_ostream OS(BranchProbStr);
+ OS << BP;
+ OS << " (total count : " << TotalCount << ")";
+ OS.flush();
+ Function *F = TI->getParent()->getParent();
+ emitOptimizationRemarkAnalysis(
+ F->getContext(), "pgo-use-annot", *F, TI->getDebugLoc(),
+ Twine(BrCondStr) +
+ " is true with probability : " + Twine(BranchProbStr));
+ }
}
template <> struct GraphTraits<PGOUseFunc *> {
diff --git a/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
index 300085eccb0c..325b64cd8b43 100644
--- a/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
+++ b/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
@@ -7,24 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// Coverage instrumentation that works with AddressSanitizer
-// and potentially with other Sanitizers.
-//
-// We create a Guard variable with the same linkage
-// as the function and inject this code into the entry block (SCK_Function)
-// or all blocks (SCK_BB):
-// if (Guard < 0) {
-// __sanitizer_cov(&Guard);
-// }
-// The accesses to Guard are atomic. The rest of the logic is
-// in __sanitizer_cov (it's fine to call it more than once).
-//
-// With SCK_Edge we also split critical edges this effectively
-// instrumenting all edges.
-//
-// This coverage implementation provides very limited data:
-// it only tells if a given function (block) was ever executed. No counters.
-// But for many use cases this is what we need and the added slowdown small.
+// Coverage instrumentation done on LLVM IR level, works with Sanitizers.
//
//===----------------------------------------------------------------------===//
@@ -56,9 +39,6 @@ using namespace llvm;
#define DEBUG_TYPE "sancov"
-static const char *const SanCovModuleInitName = "__sanitizer_cov_module_init";
-static const char *const SanCovName = "__sanitizer_cov";
-static const char *const SanCovWithCheckName = "__sanitizer_cov_with_check";
static const char *const SanCovTracePCIndirName =
"__sanitizer_cov_trace_pc_indir";
static const char *const SanCovTracePCName = "__sanitizer_cov_trace_pc";
@@ -84,12 +64,6 @@ static cl::opt<int> ClCoverageLevel(
"3: all blocks and critical edges"),
cl::Hidden, cl::init(0));
-static cl::opt<unsigned> ClCoverageBlockThreshold(