Merge llvm trunk r351319, resolve conflicts, and update FREEBSD-Xlist.

This commit is contained in:
Dimitry Andric 2019-01-20 11:41:25 +00:00
commit d9484dd61c
2298 changed files with 193347 additions and 96654 deletions

View file

@ -2,17 +2,15 @@
.arcconfig
.clang-format
.clang-tidy
.gitattributes
.gitignore
CMakeLists.txt
CODE_OWNERS.TXT
CREDITS.TXT
LLVMBuild.txt
Makefile
Makefile.common
Makefile.config.in
Makefile.rules
README.txt
autoconf/
RELEASE_TESTERS.TXT
benchmarks/
bindings/
cmake/
configure
@ -21,473 +19,485 @@ examples/
include/llvm/CMakeLists.txt
include/llvm/Config/
include/llvm/IR/CMakeLists.txt
include/llvm/Support/DataTypes.h.cmake
include/llvm/Support/CMakeLists.txt
include/llvm/Support/LICENSE.TXT
lib/Analysis/CMakeLists.txt
lib/Analysis/IPA/CMakeLists.txt
lib/Analysis/IPA/LLVMBuild.txt
lib/Analysis/IPA/Makefile
lib/Analysis/LLVMBuild.txt
lib/Analysis/Makefile
lib/Analysis/README.txt
lib/AsmParser/CMakeLists.txt
lib/AsmParser/LLVMBuild.txt
lib/AsmParser/Makefile
lib/BinaryFormat/CMakeLists.txt
lib/BinaryFormat/LLVMBuild.txt
lib/Bitcode/CMakeLists.txt
lib/Bitcode/LLVMBuild.txt
lib/Bitcode/Makefile
lib/Bitcode/Reader/CMakeLists.txt
lib/Bitcode/Reader/LLVMBuild.txt
lib/Bitcode/Reader/Makefile
lib/Bitcode/Writer/CMakeLists.txt
lib/Bitcode/Writer/LLVMBuild.txt
lib/Bitcode/Writer/Makefile
lib/CMakeLists.txt
lib/CodeGen/AsmPrinter/CMakeLists.txt
lib/CodeGen/AsmPrinter/LLVMBuild.txt
lib/CodeGen/AsmPrinter/Makefile
lib/CodeGen/CMakeLists.txt
lib/CodeGen/GlobalISel/CMakeLists.txt
lib/CodeGen/GlobalISel/LLVMBuild.txt
lib/CodeGen/LLVMBuild.txt
lib/CodeGen/Makefile
lib/CodeGen/MIRParser/CMakeLists.txt
lib/CodeGen/MIRParser/LLVMBuild.txt
lib/CodeGen/README.txt
lib/CodeGen/SelectionDAG/CMakeLists.txt
lib/CodeGen/SelectionDAG/LLVMBuild.txt
lib/CodeGen/SelectionDAG/Makefile
lib/DebugInfo/CMakeLists.txt
lib/DebugInfo/CodeView/CMakeLists.txt
lib/DebugInfo/CodeView/LLVMBuild.txt
lib/DebugInfo/DWARF/CMakeLists.txt
lib/DebugInfo/DWARF/LLVMBuild.txt
lib/DebugInfo/DWARF/Makefile
lib/DebugInfo/LLVMBuild.txt
lib/DebugInfo/Makefile
lib/DebugInfo/MSF/CMakeLists.txt
lib/DebugInfo/MSF/LLVMBuild.txt
lib/DebugInfo/PDB/CMakeLists.txt
lib/DebugInfo/PDB/LLVMBuild.txt
lib/DebugInfo/PDB/Makefile
lib/DebugInfo/Symbolize/CMakeLists.txt
lib/DebugInfo/Symbolize/LLVMBuild.txt
lib/Demangle/CMakeLists.txt
lib/Demangle/LLVMBuild.txt
lib/ExecutionEngine/CMakeLists.txt
lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt
lib/ExecutionEngine/IntelJITEvents/LLVMBuild.txt
lib/ExecutionEngine/IntelJITEvents/Makefile
lib/ExecutionEngine/Interpreter/CMakeLists.txt
lib/ExecutionEngine/Interpreter/LLVMBuild.txt
lib/ExecutionEngine/Interpreter/Makefile
lib/ExecutionEngine/LLVMBuild.txt
lib/ExecutionEngine/MCJIT/CMakeLists.txt
lib/ExecutionEngine/MCJIT/LLVMBuild.txt
lib/ExecutionEngine/MCJIT/Makefile
lib/ExecutionEngine/Makefile
lib/ExecutionEngine/OProfileJIT/CMakeLists.txt
lib/ExecutionEngine/OProfileJIT/LLVMBuild.txt
lib/ExecutionEngine/OProfileJIT/Makefile
lib/ExecutionEngine/Orc/CMakeLists.txt
lib/ExecutionEngine/Orc/LLVMBuild.txt
lib/ExecutionEngine/Orc/Makefile
lib/ExecutionEngine/PerfJITEvents/CMakeLists.txt
lib/ExecutionEngine/PerfJITEvents/LLVMBuild.txt
lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt
lib/ExecutionEngine/RuntimeDyld/LLVMBuild.txt
lib/ExecutionEngine/RuntimeDyld/Makefile
lib/FuzzMutate/CMakeLists.txt
lib/FuzzMutate/LLVMBuild.txt
lib/Fuzzer/
lib/IR/CMakeLists.txt
lib/IR/LLVMBuild.txt
lib/IR/Makefile
lib/IRReader/CMakeLists.txt
lib/IRReader/LLVMBuild.txt
lib/IRReader/Makefile
lib/LLVMBuild.txt
lib/LTO/CMakeLists.txt
lib/LTO/LLVMBuild.txt
lib/LTO/Makefile
lib/LineEditor/CMakeLists.txt
lib/LineEditor/LLVMBuild.txt
lib/LineEditor/Makefile
lib/Linker/CMakeLists.txt
lib/Linker/LLVMBuild.txt
lib/Linker/Makefile
lib/MC/CMakeLists.txt
lib/MC/LLVMBuild.txt
lib/MC/MCDisassembler/CMakeLists.txt
lib/MC/MCDisassembler/LLVMBuild.txt
lib/MC/MCDisassembler/Makefile
lib/MC/MCParser/CMakeLists.txt
lib/MC/MCParser/LLVMBuild.txt
lib/MC/MCParser/Makefile
lib/MC/Makefile
lib/Makefile
lib/MCA/CMakeLists.txt
lib/MCA/LLVMBuild.txt
lib/Object/CMakeLists.txt
lib/Object/LLVMBuild.txt
lib/Object/Makefile
lib/ObjectYAML/CMakeLists.txt
lib/ObjectYAML/LLVMBuild.txt
lib/OptRemarks/CMakeLists.txt
lib/OptRemarks/LLVMBuild.txt
lib/Option/CMakeLists.txt
lib/Option/LLVMBuild.txt
lib/Option/Makefile
lib/Passes/CMakeLists.txt
lib/Passes/LLVMBuild.txt
lib/Passes/Makefile
lib/ProfileData/CMakeLists.txt
lib/ProfileData/Coverage/CMakeLists.txt
lib/ProfileData/Coverage/LLVMBuild.txt
lib/ProfileData/LLVMBuild.txt
lib/ProfileData/Makefile
lib/Support/CMakeLists.txt
lib/Support/LLVMBuild.txt
lib/Support/Makefile
lib/Support/README.txt.system
lib/TableGen/CMakeLists.txt
lib/TableGen/LLVMBuild.txt
lib/TableGen/Makefile
lib/Target/AArch64/AsmParser/CMakeLists.txt
lib/Target/AArch64/AsmParser/LLVMBuild.txt
lib/Target/AArch64/AsmParser/Makefile
lib/Target/AArch64/CMakeLists.txt
lib/Target/AArch64/Disassembler/CMakeLists.txt
lib/Target/AArch64/Disassembler/LLVMBuild.txt
lib/Target/AArch64/Disassembler/Makefile
lib/Target/AArch64/InstPrinter/CMakeLists.txt
lib/Target/AArch64/InstPrinter/LLVMBuild.txt
lib/Target/AArch64/InstPrinter/Makefile
lib/Target/AArch64/LLVMBuild.txt
lib/Target/AArch64/MCTargetDesc/CMakeLists.txt
lib/Target/AArch64/MCTargetDesc/LLVMBuild.txt
lib/Target/AArch64/MCTargetDesc/Makefile
lib/Target/AArch64/Makefile
lib/Target/AArch64/TargetInfo/CMakeLists.txt
lib/Target/AArch64/TargetInfo/LLVMBuild.txt
lib/Target/AArch64/TargetInfo/Makefile
lib/Target/AArch64/Utils/CMakeLists.txt
lib/Target/AArch64/Utils/LLVMBuild.txt
lib/Target/AArch64/Utils/Makefile
lib/Target/AMDGPU/AsmParser/CMakeLists.txt
lib/Target/AMDGPU/AsmParser/LLVMBuild.txt
lib/Target/AMDGPU/CMakeLists.txt
lib/Target/AMDGPU/Disassembler/CMakeLists.txt
lib/Target/AMDGPU/Disassembler/LLVMBuild.txt
lib/Target/AMDGPU/InstPrinter/CMakeLists.txt
lib/Target/AMDGPU/InstPrinter/LLVMBuild.txt
lib/Target/AMDGPU/LLVMBuild.txt
lib/Target/AMDGPU/MCTargetDesc/CMakeLists.txt
lib/Target/AMDGPU/MCTargetDesc/LLVMBuild.txt
lib/Target/AMDGPU/TargetInfo/CMakeLists.txt
lib/Target/AMDGPU/TargetInfo/LLVMBuild.txt
lib/Target/AMDGPU/Utils/CMakeLists.txt
lib/Target/AMDGPU/Utils/LLVMBuild.txt
lib/Target/ARC/CMakeLists.txt
lib/Target/ARC/Disassembler/CMakeLists.txt
lib/Target/ARC/Disassembler/LLVMBuild.txt
lib/Target/ARC/InstPrinter/CMakeLists.txt
lib/Target/ARC/InstPrinter/LLVMBuild.txt
lib/Target/ARC/LLVMBuild.txt
lib/Target/ARC/MCTargetDesc/CMakeLists.txt
lib/Target/ARC/MCTargetDesc/LLVMBuild.txt
lib/Target/ARC/TargetInfo/CMakeLists.txt
lib/Target/ARC/TargetInfo/LLVMBuild.txt
lib/Target/ARM/AsmParser/CMakeLists.txt
lib/Target/ARM/AsmParser/LLVMBuild.txt
lib/Target/ARM/AsmParser/Makefile
lib/Target/ARM/CMakeLists.txt
lib/Target/ARM/Disassembler/CMakeLists.txt
lib/Target/ARM/Disassembler/LLVMBuild.txt
lib/Target/ARM/Disassembler/Makefile
lib/Target/ARM/InstPrinter/CMakeLists.txt
lib/Target/ARM/InstPrinter/LLVMBuild.txt
lib/Target/ARM/InstPrinter/Makefile
lib/Target/ARM/LLVMBuild.txt
lib/Target/ARM/MCTargetDesc/CMakeLists.txt
lib/Target/ARM/MCTargetDesc/LLVMBuild.txt
lib/Target/ARM/MCTargetDesc/Makefile
lib/Target/ARM/Makefile
lib/Target/ARM/README-Thumb.txt
lib/Target/ARM/README-Thumb2.txt
lib/Target/ARM/README.txt
lib/Target/ARM/TargetInfo/CMakeLists.txt
lib/Target/ARM/TargetInfo/LLVMBuild.txt
lib/Target/ARM/TargetInfo/Makefile
lib/Target/ARM/Utils/CMakeLists.txt
lib/Target/ARM/Utils/LLVMBuild.txt
lib/Target/AVR/AsmParser/CMakeLists.txt
lib/Target/AVR/AsmParser/LLVMBuild.txt
lib/Target/AVR/CMakeLists.txt
lib/Target/AVR/Disassembler/CMakeLists.txt
lib/Target/AVR/Disassembler/LLVMBuild.txt
lib/Target/AVR/InstPrinter/CMakeLists.txt
lib/Target/AVR/InstPrinter/LLVMBuild.txt
lib/Target/AVR/LLVMBuild.txt
lib/Target/AVR/MCTargetDesc/CMakeLists.txt
lib/Target/AVR/MCTargetDesc/LLVMBuild.txt
lib/Target/AVR/TargetInfo/CMakeLists.txt
lib/Target/AVR/TargetInfo/LLVMBuild.txt
lib/Target/BPF/AsmParser/CMakeLists.txt
lib/Target/BPF/AsmParser/LLVMBuild.txt
lib/Target/BPF/CMakeLists.txt
lib/Target/BPF/Disassembler/CMakeLists.txt
lib/Target/BPF/Disassembler/LLVMBuild.txt
lib/Target/BPF/InstPrinter/CMakeLists.txt
lib/Target/BPF/InstPrinter/LLVMBuild.txt
lib/Target/BPF/InstPrinter/Makefile
lib/Target/BPF/LLVMBuild.txt
lib/Target/BPF/MCTargetDesc/CMakeLists.txt
lib/Target/BPF/MCTargetDesc/LLVMBuild.txt
lib/Target/BPF/MCTargetDesc/Makefile
lib/Target/BPF/Makefile
lib/Target/BPF/TargetInfo/CMakeLists.txt
lib/Target/BPF/TargetInfo/LLVMBuild.txt
lib/Target/BPF/TargetInfo/Makefile
lib/Target/CMakeLists.txt
lib/Target/CppBackend/CMakeLists.txt
lib/Target/CppBackend/LLVMBuild.txt
lib/Target/CppBackend/Makefile
lib/Target/CppBackend/TargetInfo/CMakeLists.txt
lib/Target/CppBackend/TargetInfo/LLVMBuild.txt
lib/Target/CppBackend/TargetInfo/Makefile
lib/Target/Hexagon/AsmParser/CMakeLists.txt
lib/Target/Hexagon/AsmParser/LLVMBuild.txt
lib/Target/Hexagon/CMakeLists.txt
lib/Target/Hexagon/Disassembler/CMakeLists.txt
lib/Target/Hexagon/Disassembler/LLVMBuild.txt
lib/Target/Hexagon/Disassembler/Makefile
lib/Target/Hexagon/LLVMBuild.txt
lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt
lib/Target/Hexagon/MCTargetDesc/LLVMBuild.txt
lib/Target/Hexagon/MCTargetDesc/Makefile
lib/Target/Hexagon/Makefile
lib/Target/Hexagon/TargetInfo/CMakeLists.txt
lib/Target/Hexagon/TargetInfo/LLVMBuild.txt
lib/Target/Hexagon/TargetInfo/Makefile
lib/Target/LLVMBuild.txt
lib/Target/Lanai/AsmParser/CMakeLists.txt
lib/Target/Lanai/AsmParser/LLVMBuild.txt
lib/Target/Lanai/CMakeLists.txt
lib/Target/Lanai/Disassembler/CMakeLists.txt
lib/Target/Lanai/Disassembler/LLVMBuild.txt
lib/Target/Lanai/InstPrinter/CMakeLists.txt
lib/Target/Lanai/InstPrinter/LLVMBuild.txt
lib/Target/Lanai/LLVMBuild.txt
lib/Target/Lanai/MCTargetDesc/CMakeLists.txt
lib/Target/Lanai/MCTargetDesc/LLVMBuild.txt
lib/Target/Lanai/TargetInfo/CMakeLists.txt
lib/Target/Lanai/TargetInfo/LLVMBuild.txt
lib/Target/MSP430/AsmParser/CMakeLists.txt
lib/Target/MSP430/AsmParser/LLVMBuild.txt
lib/Target/MSP430/CMakeLists.txt
lib/Target/MSP430/Disassembler/CMakeLists.txt
lib/Target/MSP430/Disassembler/LLVMBuild.txt
lib/Target/MSP430/InstPrinter/CMakeLists.txt
lib/Target/MSP430/InstPrinter/LLVMBuild.txt
lib/Target/MSP430/InstPrinter/Makefile
lib/Target/MSP430/LLVMBuild.txt
lib/Target/MSP430/MCTargetDesc/CMakeLists.txt
lib/Target/MSP430/MCTargetDesc/LLVMBuild.txt
lib/Target/MSP430/MCTargetDesc/Makefile
lib/Target/MSP430/Makefile
lib/Target/MSP430/README.txt
lib/Target/MSP430/TargetInfo/CMakeLists.txt
lib/Target/MSP430/TargetInfo/LLVMBuild.txt
lib/Target/MSP430/TargetInfo/Makefile
lib/Target/Makefile
lib/Target/Mips/AsmParser/CMakeLists.txt
lib/Target/Mips/AsmParser/LLVMBuild.txt
lib/Target/Mips/AsmParser/Makefile
lib/Target/Mips/CMakeLists.txt
lib/Target/Mips/Disassembler/CMakeLists.txt
lib/Target/Mips/Disassembler/LLVMBuild.txt
lib/Target/Mips/Disassembler/Makefile
lib/Target/Mips/InstPrinter/CMakeLists.txt
lib/Target/Mips/InstPrinter/LLVMBuild.txt
lib/Target/Mips/InstPrinter/Makefile
lib/Target/Mips/LLVMBuild.txt
lib/Target/Mips/MCTargetDesc/CMakeLists.txt
lib/Target/Mips/MCTargetDesc/LLVMBuild.txt
lib/Target/Mips/MCTargetDesc/Makefile
lib/Target/Mips/Makefile
lib/Target/Mips/TargetInfo/CMakeLists.txt
lib/Target/Mips/TargetInfo/LLVMBuild.txt
lib/Target/Mips/TargetInfo/Makefile
lib/Target/NVPTX/CMakeLists.txt
lib/Target/NVPTX/InstPrinter/CMakeLists.txt
lib/Target/NVPTX/InstPrinter/LLVMBuild.txt
lib/Target/NVPTX/InstPrinter/Makefile
lib/Target/NVPTX/LLVMBuild.txt
lib/Target/NVPTX/MCTargetDesc/CMakeLists.txt
lib/Target/NVPTX/MCTargetDesc/LLVMBuild.txt
lib/Target/NVPTX/MCTargetDesc/Makefile
lib/Target/NVPTX/Makefile
lib/Target/NVPTX/TargetInfo/CMakeLists.txt
lib/Target/NVPTX/TargetInfo/LLVMBuild.txt
lib/Target/NVPTX/TargetInfo/Makefile
lib/Target/PowerPC/AsmParser/CMakeLists.txt
lib/Target/PowerPC/AsmParser/LLVMBuild.txt
lib/Target/PowerPC/AsmParser/Makefile
lib/Target/PowerPC/CMakeLists.txt
lib/Target/PowerPC/Disassembler/CMakeLists.txt
lib/Target/PowerPC/Disassembler/LLVMBuild.txt
lib/Target/PowerPC/Disassembler/Makefile
lib/Target/PowerPC/InstPrinter/CMakeLists.txt
lib/Target/PowerPC/InstPrinter/LLVMBuild.txt
lib/Target/PowerPC/InstPrinter/Makefile
lib/Target/PowerPC/LLVMBuild.txt
lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt
lib/Target/PowerPC/MCTargetDesc/LLVMBuild.txt
lib/Target/PowerPC/MCTargetDesc/Makefile
lib/Target/PowerPC/Makefile
lib/Target/PowerPC/README.txt
lib/Target/PowerPC/README_ALTIVEC.txt
lib/Target/PowerPC/TargetInfo/CMakeLists.txt
lib/Target/PowerPC/TargetInfo/LLVMBuild.txt
lib/Target/PowerPC/TargetInfo/Makefile
lib/Target/R600/AsmParser/CMakeLists.txt
lib/Target/R600/AsmParser/LLVMBuild.txt
lib/Target/R600/AsmParser/Makefile
lib/Target/R600/CMakeLists.txt
lib/Target/R600/InstPrinter/CMakeLists.txt
lib/Target/R600/InstPrinter/LLVMBuild.txt
lib/Target/R600/InstPrinter/Makefile
lib/Target/R600/LLVMBuild.txt
lib/Target/R600/MCTargetDesc/CMakeLists.txt
lib/Target/R600/MCTargetDesc/LLVMBuild.txt
lib/Target/R600/MCTargetDesc/Makefile
lib/Target/R600/Makefile
lib/Target/R600/TargetInfo/CMakeLists.txt
lib/Target/R600/TargetInfo/LLVMBuild.txt
lib/Target/R600/TargetInfo/Makefile
lib/Target/README.txt
lib/Target/RISCV/AsmParser/CMakeLists.txt
lib/Target/RISCV/AsmParser/LLVMBuild.txt
lib/Target/RISCV/CMakeLists.txt
lib/Target/RISCV/Disassembler/CMakeLists.txt
lib/Target/RISCV/Disassembler/LLVMBuild.txt
lib/Target/RISCV/InstPrinter/CMakeLists.txt
lib/Target/RISCV/InstPrinter/LLVMBuild.txt
lib/Target/RISCV/LLVMBuild.txt
lib/Target/RISCV/MCTargetDesc/CMakeLists.txt
lib/Target/RISCV/MCTargetDesc/LLVMBuild.txt
lib/Target/RISCV/TargetInfo/CMakeLists.txt
lib/Target/RISCV/TargetInfo/LLVMBuild.txt
lib/Target/RISCV/Utils/CMakeLists.txt
lib/Target/RISCV/Utils/LLVMBuild.txt
lib/Target/Sparc/AsmParser/CMakeLists.txt
lib/Target/Sparc/AsmParser/LLVMBuild.txt
lib/Target/Sparc/AsmParser/Makefile
lib/Target/Sparc/CMakeLists.txt
lib/Target/Sparc/Disassembler/CMakeLists.txt
lib/Target/Sparc/Disassembler/LLVMBuild.txt
lib/Target/Sparc/Disassembler/Makefile
lib/Target/Sparc/InstPrinter/CMakeLists.txt
lib/Target/Sparc/InstPrinter/LLVMBuild.txt
lib/Target/Sparc/InstPrinter/Makefile
lib/Target/Sparc/LLVMBuild.txt
lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
lib/Target/Sparc/MCTargetDesc/LLVMBuild.txt
lib/Target/Sparc/MCTargetDesc/Makefile
lib/Target/Sparc/Makefile
lib/Target/Sparc/README.txt
lib/Target/Sparc/TargetInfo/CMakeLists.txt
lib/Target/Sparc/TargetInfo/LLVMBuild.txt
lib/Target/Sparc/TargetInfo/Makefile
lib/Target/SystemZ/AsmParser/CMakeLists.txt
lib/Target/SystemZ/AsmParser/LLVMBuild.txt
lib/Target/SystemZ/AsmParser/Makefile
lib/Target/SystemZ/CMakeLists.txt
lib/Target/SystemZ/Disassembler/CMakeLists.txt
lib/Target/SystemZ/Disassembler/LLVMBuild.txt
lib/Target/SystemZ/Disassembler/Makefile
lib/Target/SystemZ/InstPrinter/CMakeLists.txt
lib/Target/SystemZ/InstPrinter/LLVMBuild.txt
lib/Target/SystemZ/InstPrinter/Makefile
lib/Target/SystemZ/LLVMBuild.txt
lib/Target/SystemZ/MCTargetDesc/CMakeLists.txt
lib/Target/SystemZ/MCTargetDesc/LLVMBuild.txt
lib/Target/SystemZ/MCTargetDesc/Makefile
lib/Target/SystemZ/Makefile
lib/Target/SystemZ/TargetInfo/CMakeLists.txt
lib/Target/SystemZ/TargetInfo/LLVMBuild.txt
lib/Target/SystemZ/TargetInfo/Makefile
lib/Target/WebAssembly/AsmParser/CMakeLists.txt
lib/Target/WebAssembly/AsmParser/LLVMBuild.txt
lib/Target/WebAssembly/CMakeLists.txt
lib/Target/WebAssembly/Disassembler/CMakeLists.txt
lib/Target/WebAssembly/Disassembler/LLVMBuild.txt
lib/Target/WebAssembly/InstPrinter/CMakeLists.txt
lib/Target/WebAssembly/InstPrinter/LLVMBuild.txt
lib/Target/WebAssembly/LLVMBuild.txt
lib/Target/WebAssembly/MCTargetDesc/CMakeLists.txt
lib/Target/WebAssembly/MCTargetDesc/LLVMBuild.txt
lib/Target/WebAssembly/TargetInfo/CMakeLists.txt
lib/Target/WebAssembly/TargetInfo/LLVMBuild.txt
lib/Target/X86/AsmParser/CMakeLists.txt
lib/Target/X86/AsmParser/LLVMBuild.txt
lib/Target/X86/AsmParser/Makefile
lib/Target/X86/CMakeLists.txt
lib/Target/X86/Disassembler/CMakeLists.txt
lib/Target/X86/Disassembler/LLVMBuild.txt
lib/Target/X86/Disassembler/Makefile
lib/Target/X86/InstPrinter/CMakeLists.txt
lib/Target/X86/InstPrinter/LLVMBuild.txt
lib/Target/X86/InstPrinter/Makefile
lib/Target/X86/LLVMBuild.txt
lib/Target/X86/MCTargetDesc/CMakeLists.txt
lib/Target/X86/MCTargetDesc/LLVMBuild.txt
lib/Target/X86/MCTargetDesc/Makefile
lib/Target/X86/Makefile
lib/Target/X86/README-FPStack.txt
lib/Target/X86/README-MMX.txt
lib/Target/X86/README-SSE.txt
lib/Target/X86/README-UNIMPLEMENTED.txt
lib/Target/X86/README-X86-64.txt
lib/Target/X86/README.txt
lib/Target/X86/TargetInfo/CMakeLists.txt
lib/Target/X86/TargetInfo/LLVMBuild.txt
lib/Target/X86/TargetInfo/Makefile
lib/Target/X86/Utils/CMakeLists.txt
lib/Target/X86/Utils/LLVMBuild.txt
lib/Target/X86/Utils/Makefile
lib/Target/X86/X86CompilationCallback_Win64.asm
lib/Target/XCore/CMakeLists.txt
lib/Target/XCore/Disassembler/CMakeLists.txt
lib/Target/XCore/Disassembler/LLVMBuild.txt
lib/Target/XCore/Disassembler/Makefile
lib/Target/XCore/InstPrinter/CMakeLists.txt
lib/Target/XCore/InstPrinter/LLVMBuild.txt
lib/Target/XCore/InstPrinter/Makefile
lib/Target/XCore/LLVMBuild.txt
lib/Target/XCore/MCTargetDesc/CMakeLists.txt
lib/Target/XCore/MCTargetDesc/LLVMBuild.txt
lib/Target/XCore/MCTargetDesc/Makefile
lib/Target/XCore/Makefile
lib/Target/XCore/README.txt
lib/Target/XCore/TargetInfo/CMakeLists.txt
lib/Target/XCore/TargetInfo/LLVMBuild.txt
lib/Target/XCore/TargetInfo/Makefile
lib/Testing/CMakeLists.txt
lib/Testing/LLVMBuild.txt
lib/Testing/Support/CMakeLists.txt
lib/Testing/Support/LLVMBuild.txt
lib/TextAPI/CMakeLists.txt
lib/TextAPI/LLVMBuild.txt
lib/ToolDrivers/CMakeLists.txt
lib/ToolDrivers/LLVMBuild.txt
lib/ToolDrivers/llvm-dlltool/CMakeLists.txt
lib/ToolDrivers/llvm-dlltool/LLVMBuild.txt
lib/ToolDrivers/llvm-lib/CMakeLists.txt
lib/ToolDrivers/llvm-lib/LLVMBuild.txt
lib/Transforms/AggressiveInstCombine/CMakeLists.txt
lib/Transforms/AggressiveInstCombine/LLVMBuild.txt
lib/Transforms/CMakeLists.txt
lib/Transforms/Coroutines/CMakeLists.txt
lib/Transforms/Coroutines/LLVMBuild.txt
lib/Transforms/Hello/
lib/Transforms/IPO/CMakeLists.txt
lib/Transforms/IPO/LLVMBuild.txt
lib/Transforms/IPO/Makefile
lib/Transforms/InstCombine/CMakeLists.txt
lib/Transforms/InstCombine/LLVMBuild.txt
lib/Transforms/InstCombine/Makefile
lib/Transforms/Instrumentation/CMakeLists.txt
lib/Transforms/Instrumentation/LLVMBuild.txt
lib/Transforms/Instrumentation/Makefile
lib/Transforms/LLVMBuild.txt
lib/Transforms/Makefile
lib/Transforms/ObjCARC/CMakeLists.txt
lib/Transforms/ObjCARC/LLVMBuild.txt
lib/Transforms/ObjCARC/Makefile
lib/Transforms/Scalar/CMakeLists.txt
lib/Transforms/Scalar/LLVMBuild.txt
lib/Transforms/Scalar/Makefile
lib/Transforms/Utils/CMakeLists.txt
lib/Transforms/Utils/LLVMBuild.txt
lib/Transforms/Utils/Makefile
lib/Transforms/Vectorize/CMakeLists.txt
lib/Transforms/Vectorize/LLVMBuild.txt
lib/Transforms/Vectorize/Makefile
lib/WindowsManifest/CMakeLists.txt
lib/WindowsManifest/LLVMBuild.txt
lib/XRay/CMakeLists.txt
lib/XRay/LLVMBuild.txt
llvm.spec.in
projects/
projects/CMakeLists.txt
projects/LLVMBuild.txt
resources/
runtimes/
test/
tools/CMakeLists.txt
tools/LLVMBuild.txt
tools/Makefile
tools/bugpoint-passes/
tools/bugpoint/CMakeLists.txt
tools/bugpoint/LLVMBuild.txt
tools/bugpoint/Makefile
tools/bugpoint-passes/
tools/dsymutil/
tools/gold/
tools/llc/CMakeLists.txt
tools/llc/LLVMBuild.txt
tools/llc/Makefile
tools/lli/CMakeLists.txt
tools/lli/ChildTarget/CMakeLists.txt
tools/lli/ChildTarget/LLVMBuild.txt
tools/lli/ChildTarget/Makefile
tools/lli/LLVMBuild.txt
tools/lli/Makefile
tools/llvm-ar/CMakeLists.txt
tools/llvm-ar/LLVMBuild.txt
tools/llvm-ar/Makefile
tools/llvm-ar/install_symlink.cmake
tools/llvm-as-fuzzer/
tools/llvm-as-parasitic-coverage-repro/
tools/llvm-as/CMakeLists.txt
tools/llvm-as/LLVMBuild.txt
tools/llvm-as/Makefile
tools/llvm-bcanalyzer/CMakeLists.txt
tools/llvm-bcanalyzer/LLVMBuild.txt
tools/llvm-bcanalyzer/Makefile
tools/llvm-c-test/
tools/llvm-cat/
tools/llvm-cfi-verify/
tools/llvm-config/
tools/llvm-cov/CMakeLists.txt
tools/llvm-cov/LLVMBuild.txt
tools/llvm-cov/Makefile
tools/llvm-cvtres/
tools/llvm-cxxdump/CMakeLists.txt
tools/llvm-cxxdump/LLVMBuild.txt
tools/llvm-cxxdump/Makefile
tools/llvm-cxxfilt/CMakeLists.txt
tools/llvm-cxxmap/CMakeLists.txt
tools/llvm-cxxmap/LLVMBuild.txt
tools/llvm-diff/CMakeLists.txt
tools/llvm-diff/LLVMBuild.txt
tools/llvm-diff/Makefile
tools/llvm-dis/CMakeLists.txt
tools/llvm-dis/LLVMBuild.txt
tools/llvm-dis/Makefile
tools/llvm-dwarfdump/CMakeLists.txt
tools/llvm-dwarfdump/LLVMBuild.txt
tools/llvm-dwarfdump/Makefile
tools/llvm-dwarfdump/fuzzer/
tools/llvm-dwp/
tools/llvm-elfabi/
tools/llvm-exegesis/
tools/llvm-extract/CMakeLists.txt
tools/llvm-extract/LLVMBuild.txt
tools/llvm-extract/Makefile
tools/llvm-go/
tools/llvm-isel-fuzzer/
tools/llvm-itanium-demangle-fuzzer/
tools/llvm-jitlistener/
tools/llvm-link/CMakeLists.txt
tools/llvm-link/LLVMBuild.txt
tools/llvm-link/Makefile
tools/llvm-lto/CMakeLists.txt
tools/llvm-lto/LLVMBuild.txt
tools/llvm-lto/Makefile
tools/llvm-lto2/CMakeLists.txt
tools/llvm-lto2/LLVMBuild.txt
tools/llvm-mc-assemble-fuzzer/
tools/llvm-mc-disassemble-fuzzer/
tools/llvm-mc/CMakeLists.txt
tools/llvm-mc/LLVMBuild.txt
tools/llvm-mc/Makefile
tools/llvm-mca/CMakeLists.txt
tools/llvm-mca/LLVMBuild.txt
tools/llvm-mcmarkup/
tools/llvm-microsoft-demangle-fuzzer/
tools/llvm-modextract/CMakeLists.txt
tools/llvm-modextract/LLVMBuild.txt
tools/llvm-mt/
tools/llvm-nm/CMakeLists.txt
tools/llvm-nm/LLVMBuild.txt
tools/llvm-nm/Makefile
tools/llvm-objcopy/CMakeLists.txt
tools/llvm-objcopy/LLVMBuild.txt
tools/llvm-objdump/CMakeLists.txt
tools/llvm-objdump/LLVMBuild.txt
tools/llvm-objdump/Makefile
tools/llvm-pdbdump/CMakeLists.txt
tools/llvm-pdbdump/LLVMBuild.txt
tools/llvm-pdbdump/Makefile
tools/llvm-opt-fuzzer/
tools/llvm-opt-report/
tools/llvm-pdbutil/CMakeLists.txt
tools/llvm-pdbutil/LLVMBuild.txt
tools/llvm-pdbutil/fuzzer/
tools/llvm-profdata/CMakeLists.txt
tools/llvm-profdata/LLVMBuild.txt
tools/llvm-profdata/Makefile
tools/llvm-rc/
tools/llvm-readobj/CMakeLists.txt
tools/llvm-readobj/LLVMBuild.txt
tools/llvm-readobj/Makefile
tools/llvm-rtdyld/CMakeLists.txt
tools/llvm-rtdyld/LLVMBuild.txt
tools/llvm-rtdyld/Makefile
tools/llvm-shlib/
tools/llvm-size/
tools/llvm-special-case-list-fuzzer/
tools/llvm-split/
tools/llvm-stress/CMakeLists.txt
tools/llvm-stress/LLVMBuild.txt
tools/llvm-stress/Makefile
tools/llvm-strings/
tools/llvm-symbolizer/CMakeLists.txt
tools/llvm-symbolizer/Makefile
tools/llvm-undname/
tools/llvm-vtabledump/
tools/llvm-xray/CMakeLists.txt
tools/llvm-yaml-numeric-parser-fuzzer/
tools/lto/
tools/macho-dump/CMakeLists.txt
tools/macho-dump/LLVMBuild.txt
tools/macho-dump/Makefile
tools/msbuild/
tools/obj2yaml/
tools/opt-remarks/
tools/opt-viewer/
tools/opt/CMakeLists.txt
tools/opt/LLVMBuild.txt
tools/opt/Makefile
tools/sancov/
tools/sanstats/
tools/verify-uselistorder/
tools/xcode-toolchain/
tools/yaml2obj/
unittests/
utils/DSAclean.py
@ -498,33 +508,47 @@ utils/GetRepositoryPath
utils/GetSourceVersion
utils/KillTheDoctor/
utils/LLVMBuild.txt
utils/Makefile
utils/LLVMVisualizers/
utils/Misc/
utils/PerfectShuffle/
utils/Reviewing/
utils/TableGen/CMakeLists.txt
utils/TableGen/LLVMBuild.txt
utils/TableGen/Makefile
utils/TableGen/tdtags
utils/Target/
utils/UpdateCMakeLists.pl
utils/UpdateTestChecks/
utils/abtest/
utils/abtest.py
utils/benchmark/
utils/bisect
utils/bisect-skip-count
utils/bugpoint/
utils/bugpoint_gisel_reducer.py
utils/buildit/
utils/check-each-file
utils/clang-parse-diagnostics-file
utils/codegen-diff
utils/collect_and_build_with_pgo.py
utils/count/
utils/countloc.sh
utils/create_ladder_graph.py
utils/crosstool/
utils/demangle_tree.py
utils/docker/
utils/emacs/
utils/extract_symbols.py
utils/extract_vplan.py
utils/findmisopt
utils/findoptdiff
utils/findsym.pl
utils/fpcmp/
utils/gdb-scripts/
utils/getsrcs.sh
utils/git/
utils/git-svn/
utils/gn/
utils/indirect_calls.py
utils/jedit/
utils/kate/
utils/lint/
@ -532,23 +556,33 @@ utils/lit/
utils/lldbDataFormatters.py
utils/llvm-build/
utils/llvm-compilers-check
utils/llvm-gisel-cov.py
utils/llvm-lit/
utils/llvm-native-gxx
utils/llvm.grm
utils/llvm.natvis
utils/llvmdo
utils/llvmgrep
utils/makellvm
utils/not/
utils/opt-viewer/
utils/prepare-code-coverage-artifact.py
utils/release/
utils/sanitizers/
utils/schedcover.py
utils/shuffle_fuzz.py
utils/shuffle_select_fuzz_tester.py
utils/sort_includes.py
utils/test_debuginfo.pl
utils/testgen/
utils/textmate/
utils/unicode-case-fold.py
utils/unittest/
utils/update_analyze_test_checks.py
utils/update_cc_test_checks.py
utils/update_llc_test_checks.py
utils/update_mca_test_checks.py
utils/update_mir_test_checks.py
utils/update_test_checks.py
utils/valgrind/
utils/vim/
utils/vscode/
utils/wciia.py
utils/yaml-bench/

View file

@ -4,7 +4,7 @@ LLVM Release License
University of Illinois/NCSA
Open Source License
Copyright (c) 2003-2018 University of Illinois at Urbana-Champaign.
Copyright (c) 2003-2019 University of Illinois at Urbana-Champaign.
All rights reserved.
Developed by:

View file

@ -54,6 +54,8 @@ extern "C" {
* @{
*/
/// External users depend on the following values being stable. It is not safe
/// to reorder them.
typedef enum {
/* Terminator Instructions */
LLVMRet = 1,
@ -64,6 +66,9 @@ typedef enum {
/* removed 6 due to API changes */
LLVMUnreachable = 7,
/* Standard Unary Operators */
LLVMFNeg = 66,
/* Standard Binary Operators */
LLVMAdd = 8,
LLVMFAdd = 9,
@ -515,6 +520,23 @@ void *LLVMContextGetDiagnosticContext(LLVMContextRef C);
void LLVMContextSetYieldCallback(LLVMContextRef C, LLVMYieldCallback Callback,
void *OpaqueHandle);
/**
* Retrieve whether the given context is set to discard all value names.
*
* @see LLVMContext::shouldDiscardValueNames()
*/
LLVMBool LLVMContextShouldDiscardValueNames(LLVMContextRef C);
/**
* Set whether the given context discards all value names.
*
* If true, only the names of GlobalValue objects will be available in the IR.
* This can be used to save memory and runtime, especially in release mode.
*
* @see LLVMContext::setDiscardValueNames()
*/
void LLVMContextSetDiscardValueNames(LLVMContextRef C, LLVMBool Discard);
/**
* Destroy a context instance.
*
@ -842,6 +864,63 @@ LLVMContextRef LLVMGetModuleContext(LLVMModuleRef M);
*/
LLVMTypeRef LLVMGetTypeByName(LLVMModuleRef M, const char *Name);
/**
* Obtain an iterator to the first NamedMDNode in a Module.
*
* @see llvm::Module::named_metadata_begin()
*/
LLVMNamedMDNodeRef LLVMGetFirstNamedMetadata(LLVMModuleRef M);
/**
* Obtain an iterator to the last NamedMDNode in a Module.
*
* @see llvm::Module::named_metadata_end()
*/
LLVMNamedMDNodeRef LLVMGetLastNamedMetadata(LLVMModuleRef M);
/**
* Advance a NamedMDNode iterator to the next NamedMDNode.
*
* Returns NULL if the iterator was already at the end and there are no more
* named metadata nodes.
*/
LLVMNamedMDNodeRef LLVMGetNextNamedMetadata(LLVMNamedMDNodeRef NamedMDNode);
/**
* Decrement a NamedMDNode iterator to the previous NamedMDNode.
*
* Returns NULL if the iterator was already at the beginning and there are
* no previous named metadata nodes.
*/
LLVMNamedMDNodeRef LLVMGetPreviousNamedMetadata(LLVMNamedMDNodeRef NamedMDNode);
/**
* Retrieve a NamedMDNode with the given name, returning NULL if no such
* node exists.
*
* @see llvm::Module::getNamedMetadata()
*/
LLVMNamedMDNodeRef LLVMGetNamedMetadata(LLVMModuleRef M,
const char *Name, size_t NameLen);
/**
* Retrieve a NamedMDNode with the given name, creating a new node if no such
* node exists.
*
* @see llvm::Module::getOrInsertNamedMetadata()
*/
LLVMNamedMDNodeRef LLVMGetOrInsertNamedMetadata(LLVMModuleRef M,
const char *Name,
size_t NameLen);
/**
* Retrieve the name of a NamedMDNode.
*
* @see llvm::NamedMDNode::getName()
*/
const char *LLVMGetNamedMetadataName(LLVMNamedMDNodeRef NamedMD,
size_t *NameLen);
/**
* Obtain the number of operands for named metadata in a module.
*
@ -872,6 +951,44 @@ void LLVMGetNamedMetadataOperands(LLVMModuleRef M, const char *Name,
void LLVMAddNamedMetadataOperand(LLVMModuleRef M, const char *Name,
LLVMValueRef Val);
/**
* Return the directory of the debug location for this value, which must be
* an llvm::Instruction, llvm::GlobalVariable, or llvm::Function.
*
* @see llvm::Instruction::getDebugLoc()
* @see llvm::GlobalVariable::getDebugInfo()
* @see llvm::Function::getSubprogram()
*/
const char *LLVMGetDebugLocDirectory(LLVMValueRef Val, unsigned *Length);
/**
* Return the filename of the debug location for this value, which must be
* an llvm::Instruction, llvm::GlobalVariable, or llvm::Function.
*
* @see llvm::Instruction::getDebugLoc()
* @see llvm::GlobalVariable::getDebugInfo()
* @see llvm::Function::getSubprogram()
*/
const char *LLVMGetDebugLocFilename(LLVMValueRef Val, unsigned *Length);
/**
* Return the line number of the debug location for this value, which must be
* an llvm::Instruction, llvm::GlobalVariable, or llvm::Function.
*
* @see llvm::Instruction::getDebugLoc()
* @see llvm::GlobalVariable::getDebugInfo()
* @see llvm::Function::getSubprogram()
*/
unsigned LLVMGetDebugLocLine(LLVMValueRef Val);
/**
* Return the column number of the debug location for this value, which must be
* an llvm::Instruction.
*
* @see llvm::Instruction::getDebugLoc()
*/
unsigned LLVMGetDebugLocColumn(LLVMValueRef Val);
/**
* Add a function to a module under a specified name.
*
@ -1221,6 +1338,13 @@ LLVMBool LLVMIsPackedStruct(LLVMTypeRef StructTy);
*/
LLVMBool LLVMIsOpaqueStruct(LLVMTypeRef StructTy);
/**
* Determine whether a structure is literal.
*
* @see llvm::StructType::isLiteral()
*/
LLVMBool LLVMIsLiteralStruct(LLVMTypeRef StructTy);
/**
* @}
*/
@ -1408,6 +1532,7 @@ LLVMTypeRef LLVMX86MMXType(void);
macro(ConstantVector) \
macro(GlobalValue) \
macro(GlobalAlias) \
macro(GlobalIFunc) \
macro(GlobalObject) \
macro(Function) \
macro(GlobalVariable) \
@ -1417,7 +1542,9 @@ LLVMTypeRef LLVMX86MMXType(void);
macro(CallInst) \
macro(IntrinsicInst) \
macro(DbgInfoIntrinsic) \
macro(DbgDeclareInst) \
macro(DbgVariableIntrinsic) \
macro(DbgDeclareInst) \
macro(DbgLabelInst) \
macro(MemIntrinsic) \
macro(MemCpyInst) \
macro(MemMoveInst) \
@ -1434,16 +1561,15 @@ LLVMTypeRef LLVMX86MMXType(void);
macro(SelectInst) \
macro(ShuffleVectorInst) \
macro(StoreInst) \
macro(TerminatorInst) \
macro(BranchInst) \
macro(IndirectBrInst) \
macro(InvokeInst) \
macro(ReturnInst) \
macro(SwitchInst) \
macro(UnreachableInst) \
macro(ResumeInst) \
macro(CleanupReturnInst) \
macro(CatchReturnInst) \
macro(BranchInst) \
macro(IndirectBrInst) \
macro(InvokeInst) \
macro(ReturnInst) \
macro(SwitchInst) \
macro(UnreachableInst) \
macro(ResumeInst) \
macro(CleanupReturnInst) \
macro(CatchReturnInst) \
macro(FuncletPadInst) \
macro(CatchPadInst) \
macro(CleanupPadInst) \
@ -1959,9 +2085,14 @@ LLVMValueRef LLVMConstLShr(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant);
LLVMValueRef LLVMConstAShr(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant);
LLVMValueRef LLVMConstGEP(LLVMValueRef ConstantVal,
LLVMValueRef *ConstantIndices, unsigned NumIndices);
LLVMValueRef LLVMConstGEP2(LLVMTypeRef Ty, LLVMValueRef ConstantVal,
LLVMValueRef *ConstantIndices, unsigned NumIndices);
LLVMValueRef LLVMConstInBoundsGEP(LLVMValueRef ConstantVal,
LLVMValueRef *ConstantIndices,
unsigned NumIndices);
LLVMValueRef LLVMConstInBoundsGEP2(LLVMTypeRef Ty, LLVMValueRef ConstantVal,
LLVMValueRef *ConstantIndices,
unsigned NumIndices);
LLVMValueRef LLVMConstTrunc(LLVMValueRef ConstantVal, LLVMTypeRef ToType);
LLVMValueRef LLVMConstSExt(LLVMValueRef ConstantVal, LLVMTypeRef ToType);
LLVMValueRef LLVMConstZExt(LLVMValueRef ConstantVal, LLVMTypeRef ToType);
@ -2037,6 +2168,14 @@ void LLVMSetDLLStorageClass(LLVMValueRef Global, LLVMDLLStorageClass Class);
LLVMUnnamedAddr LLVMGetUnnamedAddress(LLVMValueRef Global);
void LLVMSetUnnamedAddress(LLVMValueRef Global, LLVMUnnamedAddr UnnamedAddr);
/**
* Returns the "value type" of a global value. This differs from the formal
* type of a global value which is always a pointer type.
*
* @see llvm::GlobalValue::getValueType()
*/
LLVMTypeRef LLVMGlobalGetValueType(LLVMValueRef Global);
/** Deprecated: Use LLVMGetUnnamedAddress instead. */
LLVMBool LLVMHasUnnamedAddr(LLVMValueRef Global);
/** Deprecated: Use LLVMSetUnnamedAddress instead. */
@ -2067,6 +2206,58 @@ unsigned LLVMGetAlignment(LLVMValueRef V);
*/
void LLVMSetAlignment(LLVMValueRef V, unsigned Bytes);
/**
* Sets a metadata attachment, erasing the existing metadata attachment if
* it already exists for the given kind.
*
* @see llvm::GlobalObject::setMetadata()
*/
void LLVMGlobalSetMetadata(LLVMValueRef Global, unsigned Kind,
LLVMMetadataRef MD);
/**
* Erases a metadata attachment of the given kind if it exists.
*
* @see llvm::GlobalObject::eraseMetadata()
*/
void LLVMGlobalEraseMetadata(LLVMValueRef Global, unsigned Kind);
/**
* Removes all metadata attachments from this value.
*
* @see llvm::GlobalObject::clearMetadata()
*/
void LLVMGlobalClearMetadata(LLVMValueRef Global);
/**
* Retrieves an array of metadata entries representing the metadata attached to
* this value. The caller is responsible for freeing this array by calling
* \c LLVMDisposeValueMetadataEntries.
*
* @see llvm::GlobalObject::getAllMetadata()
*/
LLVMValueMetadataEntry *LLVMGlobalCopyAllMetadata(LLVMValueRef Value,
size_t *NumEntries);
/**
* Destroys value metadata entries.
*/
void LLVMDisposeValueMetadataEntries(LLVMValueMetadataEntry *Entries);
/**
* Returns the kind of a value metadata entry at a specific index.
*/
unsigned LLVMValueMetadataEntriesGetKind(LLVMValueMetadataEntry *Entries,
unsigned Index);
/**
* Returns the underlying metadata node of a value metadata entry at a
* specific index.
*/
LLVMMetadataRef
LLVMValueMetadataEntriesGetMetadata(LLVMValueMetadataEntry *Entries,
unsigned Index);
/**
* @}
*/
@ -2217,6 +2408,54 @@ void LLVMSetPersonalityFn(LLVMValueRef Fn, LLVMValueRef PersonalityFn);
*/
unsigned LLVMGetIntrinsicID(LLVMValueRef Fn);
/**
* Create or insert the declaration of an intrinsic. For overloaded intrinsics,
* parameter types must be provided to uniquely identify an overload.
*
* @see llvm::Intrinsic::getDeclaration()
*/
LLVMValueRef LLVMGetIntrinsicDeclaration(LLVMModuleRef Mod,
unsigned ID,
LLVMTypeRef *ParamTypes,
size_t ParamCount);
/**
* Retrieves the type of an intrinsic. For overloaded intrinsics, parameter
* types must be provided to uniquely identify an overload.
*
* @see llvm::Intrinsic::getType()
*/
LLVMTypeRef LLVMIntrinsicGetType(LLVMContextRef Ctx, unsigned ID,
LLVMTypeRef *ParamTypes, size_t ParamCount);
/**
* Retrieves the name of an intrinsic.
*
* @see llvm::Intrinsic::getName()
*/
const char *LLVMIntrinsicGetName(unsigned ID, size_t *NameLength);
/**
* Copies the name of an overloaded intrinsic identified by a given list of
* parameter types.
*
* Unlike LLVMIntrinsicGetName, the caller is responsible for freeing the
* returned string.
*
* @see llvm::Intrinsic::getName()
*/
const char *LLVMIntrinsicCopyOverloadedName(unsigned ID,
LLVMTypeRef *ParamTypes,
size_t ParamCount,
size_t *NameLength);
/**
* Obtain if the intrinsic identified by the given ID is overloaded.
*
* @see llvm::Intrinsic::isOverloaded()
*/
LLVMBool LLVMIntrinsicIsOverloaded(unsigned ID);
/**
* Obtain the calling function of a function.
*
@ -2514,7 +2753,7 @@ LLVMValueRef LLVMGetBasicBlockParent(LLVMBasicBlockRef BB);
* If the basic block does not have a terminator (it is not well-formed
* if it doesn't), then NULL is returned.
*
* The returned LLVMValueRef corresponds to a llvm::TerminatorInst.
* The returned LLVMValueRef corresponds to an llvm::Instruction.
*
* @see llvm::BasicBlock::getTerminator()
*/
@ -2572,6 +2811,14 @@ LLVMBasicBlockRef LLVMGetPreviousBasicBlock(LLVMBasicBlockRef BB);
*/
LLVMBasicBlockRef LLVMGetEntryBasicBlock(LLVMValueRef Fn);
/**
* Create a new basic block without inserting it into a function.
*
* @see llvm::BasicBlock::Create()
*/
LLVMBasicBlockRef LLVMCreateBasicBlockInContext(LLVMContextRef C,
const char *Name);
/**
* Append a basic block to the end of a function.
*
@ -2694,6 +2941,16 @@ LLVMValueRef LLVMGetMetadata(LLVMValueRef Val, unsigned KindID);
*/
void LLVMSetMetadata(LLVMValueRef Val, unsigned KindID, LLVMValueRef Node);
/**
* Returns the metadata associated with an instruction value, but filters out
* all the debug locations.
*
* @see llvm::Instruction::getAllMetadataOtherThanDebugLoc()
*/
LLVMValueMetadataEntry *
LLVMInstructionGetAllMetadataOtherThanDebugLoc(LLVMValueRef Instr,
size_t *NumEntries);
/**
* Obtain the basic block to which an instruction belongs.
*
@ -2776,6 +3033,15 @@ LLVMRealPredicate LLVMGetFCmpPredicate(LLVMValueRef Inst);
*/
LLVMValueRef LLVMInstructionClone(LLVMValueRef Inst);
/**
* Determine whether an instruction is a terminator. This routine is named to
* be compatible with historical functions that did this by querying the
* underlying C++ type.
*
* @see llvm::Instruction::isTerminator()
*/
LLVMValueRef LLVMIsATerminatorInst(LLVMValueRef Inst);
/**
* @defgroup LLVMCCoreValueInstructionCall Call Sites and Invocations
*
@ -2838,6 +3104,13 @@ void LLVMRemoveCallSiteEnumAttribute(LLVMValueRef C, LLVMAttributeIndex Idx,
void LLVMRemoveCallSiteStringAttribute(LLVMValueRef C, LLVMAttributeIndex Idx,
const char *K, unsigned KLen);
/**
* Obtain the function type called by this instruction.
*
* @see llvm::CallBase::getFunctionType()
*/
LLVMTypeRef LLVMGetCalledFunctionType(LLVMValueRef C);
/**
* Obtain the pointer to the function invoked by this instruction.
*
@ -2916,8 +3189,8 @@ void LLVMSetUnwindDest(LLVMValueRef InvokeInst, LLVMBasicBlockRef B);
/**
* @defgroup LLVMCCoreValueInstructionTerminator Terminators
*
* Functions in this group only apply to instructions that map to
* llvm::TerminatorInst instances.
* Functions in this group only apply to instructions for which
* LLVMIsATerminatorInst returns true.
*
* @{
*/
@ -2925,21 +3198,21 @@ void LLVMSetUnwindDest(LLVMValueRef InvokeInst, LLVMBasicBlockRef B);
/**
* Return the number of successors that this terminator has.
*
* @see llvm::TerminatorInst::getNumSuccessors
* @see llvm::Instruction::getNumSuccessors
*/
unsigned LLVMGetNumSuccessors(LLVMValueRef Term);
/**
* Return the specified successor.
*
* @see llvm::TerminatorInst::getSuccessor
* @see llvm::Instruction::getSuccessor
*/
LLVMBasicBlockRef LLVMGetSuccessor(LLVMValueRef Term, unsigned i);
/**
* Update the specified successor to point at the provided block.
*
* @see llvm::TerminatorInst::setSuccessor
* @see llvm::Instruction::setSuccessor
*/
void LLVMSetSuccessor(LLVMValueRef Term, unsigned i, LLVMBasicBlockRef block);
@ -3130,10 +3403,16 @@ LLVMValueRef LLVMBuildSwitch(LLVMBuilderRef, LLVMValueRef V,
LLVMBasicBlockRef Else, unsigned NumCases);
LLVMValueRef LLVMBuildIndirectBr(LLVMBuilderRef B, LLVMValueRef Addr,
unsigned NumDests);
// LLVMBuildInvoke is deprecated in favor of LLVMBuildInvoke2, in preparation
// for opaque pointer types.
LLVMValueRef LLVMBuildInvoke(LLVMBuilderRef, LLVMValueRef Fn,
LLVMValueRef *Args, unsigned NumArgs,
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
const char *Name);
LLVMValueRef LLVMBuildInvoke2(LLVMBuilderRef, LLVMTypeRef Ty, LLVMValueRef Fn,
LLVMValueRef *Args, unsigned NumArgs,
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
const char *Name);
LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef);
/* Exception Handling */
@ -3290,13 +3569,48 @@ LLVMValueRef LLVMBuildNot(LLVMBuilderRef, LLVMValueRef V, const char *Name);
LLVMValueRef LLVMBuildMalloc(LLVMBuilderRef, LLVMTypeRef Ty, const char *Name);
LLVMValueRef LLVMBuildArrayMalloc(LLVMBuilderRef, LLVMTypeRef Ty,
LLVMValueRef Val, const char *Name);
/**
* Creates and inserts a memset to the specified pointer and the
* specified value.
*
* @see llvm::IRRBuilder::CreateMemSet()
*/
LLVMValueRef LLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr,
LLVMValueRef Val, LLVMValueRef Len,
unsigned Align);
/**
* Creates and inserts a memcpy between the specified pointers.
*
* @see llvm::IRRBuilder::CreateMemCpy()
*/
LLVMValueRef LLVMBuildMemCpy(LLVMBuilderRef B,
LLVMValueRef Dst, unsigned DstAlign,
LLVMValueRef Src, unsigned SrcAlign,
LLVMValueRef Size);
/**
* Creates and inserts a memmove between the specified pointers.
*
* @see llvm::IRRBuilder::CreateMemMove()
*/
LLVMValueRef LLVMBuildMemMove(LLVMBuilderRef B,
LLVMValueRef Dst, unsigned DstAlign,
LLVMValueRef Src, unsigned SrcAlign,
LLVMValueRef Size);
LLVMValueRef LLVMBuildAlloca(LLVMBuilderRef, LLVMTypeRef Ty, const char *Name);
LLVMValueRef LLVMBuildArrayAlloca(LLVMBuilderRef, LLVMTypeRef Ty,
LLVMValueRef Val, const char *Name);
LLVMValueRef LLVMBuildFree(LLVMBuilderRef, LLVMValueRef PointerVal);
// LLVMBuildLoad is deprecated in favor of LLVMBuildLoad2, in preparation for
// opaque pointer types.
LLVMValueRef LLVMBuildLoad(LLVMBuilderRef, LLVMValueRef PointerVal,
const char *Name);
LLVMValueRef LLVMBuildLoad2(LLVMBuilderRef, LLVMTypeRef Ty,
LLVMValueRef PointerVal, const char *Name);
LLVMValueRef LLVMBuildStore(LLVMBuilderRef, LLVMValueRef Val, LLVMValueRef Ptr);
// LLVMBuildGEP, LLVMBuildInBoundsGEP, and LLVMBuildStructGEP are deprecated in
// favor of LLVMBuild*GEP2, in preparation for opaque pointer types.
LLVMValueRef LLVMBuildGEP(LLVMBuilderRef B, LLVMValueRef Pointer,
LLVMValueRef *Indices, unsigned NumIndices,
const char *Name);
@ -3305,6 +3619,15 @@ LLVMValueRef LLVMBuildInBoundsGEP(LLVMBuilderRef B, LLVMValueRef Pointer,
const char *Name);
LLVMValueRef LLVMBuildStructGEP(LLVMBuilderRef B, LLVMValueRef Pointer,
unsigned Idx, const char *Name);
LLVMValueRef LLVMBuildGEP2(LLVMBuilderRef B, LLVMTypeRef Ty,
LLVMValueRef Pointer, LLVMValueRef *Indices,
unsigned NumIndices, const char *Name);
LLVMValueRef LLVMBuildInBoundsGEP2(LLVMBuilderRef B, LLVMTypeRef Ty,
LLVMValueRef Pointer, LLVMValueRef *Indices,
unsigned NumIndices, const char *Name);
LLVMValueRef LLVMBuildStructGEP2(LLVMBuilderRef B, LLVMTypeRef Ty,
LLVMValueRef Pointer, unsigned Idx,
const char *Name);
LLVMValueRef LLVMBuildGlobalString(LLVMBuilderRef B, const char *Str,
const char *Name);
LLVMValueRef LLVMBuildGlobalStringPtr(LLVMBuilderRef B, const char *Str,
@ -3351,11 +3674,16 @@ LLVMValueRef LLVMBuildCast(LLVMBuilderRef B, LLVMOpcode Op, LLVMValueRef Val,
LLVMTypeRef DestTy, const char *Name);
LLVMValueRef LLVMBuildPointerCast(LLVMBuilderRef, LLVMValueRef Val,
LLVMTypeRef DestTy, const char *Name);
LLVMValueRef LLVMBuildIntCast(LLVMBuilderRef, LLVMValueRef Val, /*Signed cast!*/
LLVMTypeRef DestTy, const char *Name);
LLVMValueRef LLVMBuildIntCast2(LLVMBuilderRef, LLVMValueRef Val,
LLVMTypeRef DestTy, LLVMBool IsSigned,
const char *Name);
LLVMValueRef LLVMBuildFPCast(LLVMBuilderRef, LLVMValueRef Val,
LLVMTypeRef DestTy, const char *Name);
/** Deprecated: This cast is always signed. Use LLVMBuildIntCast2 instead. */
LLVMValueRef LLVMBuildIntCast(LLVMBuilderRef, LLVMValueRef Val, /*Signed cast!*/
LLVMTypeRef DestTy, const char *Name);
/* Comparisons */
LLVMValueRef LLVMBuildICmp(LLVMBuilderRef, LLVMIntPredicate Op,
LLVMValueRef LHS, LLVMValueRef RHS,
@ -3366,9 +3694,14 @@ LLVMValueRef LLVMBuildFCmp(LLVMBuilderRef, LLVMRealPredicate Op,
/* Miscellaneous instructions */
LLVMValueRef LLVMBuildPhi(LLVMBuilderRef, LLVMTypeRef Ty, const char *Name);
// LLVMBuildCall is deprecated in favor of LLVMBuildCall2, in preparation for
// opaque pointer types.
LLVMValueRef LLVMBuildCall(LLVMBuilderRef, LLVMValueRef Fn,
LLVMValueRef *Args, unsigned NumArgs,
const char *Name);
LLVMValueRef LLVMBuildCall2(LLVMBuilderRef, LLVMTypeRef, LLVMValueRef Fn,
LLVMValueRef *Args, unsigned NumArgs,
const char *Name);
LLVMValueRef LLVMBuildSelect(LLVMBuilderRef, LLVMValueRef If,
LLVMValueRef Then, LLVMValueRef Else,
const char *Name);

View file

@ -54,9 +54,12 @@ typedef enum {
LLVMDIFlagMainSubprogram = 1 << 21,
LLVMDIFlagTypePassByValue = 1 << 22,
LLVMDIFlagTypePassByReference = 1 << 23,
LLVMDIFlagFixedEnum = 1 << 24,
LLVMDIFlagEnumClass = 1 << 24,
LLVMDIFlagFixedEnum = LLVMDIFlagEnumClass, // Deprecated.
LLVMDIFlagThunk = 1 << 25,
LLVMDIFlagTrivial = 1 << 26,
LLVMDIFlagBigEndian = 1 << 27,
LLVMDIFlagLittleEndian = 1 << 28,
LLVMDIFlagIndirectVirtualBase = (1 << 2) | (1 << 5),
LLVMDIFlagAccessibility = LLVMDIFlagPrivate | LLVMDIFlagProtected |
LLVMDIFlagPublic,
@ -124,6 +127,44 @@ typedef enum {
LLVMDWARFEmissionLineTablesOnly
} LLVMDWARFEmissionKind;
/**
* The kind of metadata nodes.
*/
enum {
LLVMMDStringMetadataKind,
LLVMConstantAsMetadataMetadataKind,
LLVMLocalAsMetadataMetadataKind,
LLVMDistinctMDOperandPlaceholderMetadataKind,
LLVMMDTupleMetadataKind,
LLVMDILocationMetadataKind,
LLVMDIExpressionMetadataKind,
LLVMDIGlobalVariableExpressionMetadataKind,
LLVMGenericDINodeMetadataKind,
LLVMDISubrangeMetadataKind,
LLVMDIEnumeratorMetadataKind,
LLVMDIBasicTypeMetadataKind,
LLVMDIDerivedTypeMetadataKind,
LLVMDICompositeTypeMetadataKind,
LLVMDISubroutineTypeMetadataKind,
LLVMDIFileMetadataKind,
LLVMDICompileUnitMetadataKind,
LLVMDISubprogramMetadataKind,
LLVMDILexicalBlockMetadataKind,
LLVMDILexicalBlockFileMetadataKind,
LLVMDINamespaceMetadataKind,
LLVMDIModuleMetadataKind,
LLVMDITemplateTypeParameterMetadataKind,
LLVMDITemplateValueParameterMetadataKind,
LLVMDIGlobalVariableMetadataKind,
LLVMDILocalVariableMetadataKind,
LLVMDILabelMetadataKind,
LLVMDIObjCPropertyMetadataKind,
LLVMDIImportedEntityMetadataKind,
LLVMDIMacroMetadataKind,
LLVMDIMacroFileMetadataKind
};
typedef unsigned LLVMMetadataKind;
/**
* An LLVM DWARF type encoding.
*/
@ -531,11 +572,13 @@ LLVMDIBuilderCreateUnspecifiedType(LLVMDIBuilderRef Builder, const char *Name,
* \param NameLen Length of type name.
* \param SizeInBits Size of the type.
* \param Encoding DWARF encoding code, e.g. \c LLVMDWARFTypeEncoding_float.
* \param Flags Flags to encode optional attribute like endianity
*/
LLVMMetadataRef
LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef Builder, const char *Name,
size_t NameLen, uint64_t SizeInBits,
LLVMDWARFTypeEncoding Encoding);
LLVMDWARFTypeEncoding Encoding,
LLVMDIFlags Flags);
/**
* Create debugging information entry for a pointer.
@ -965,21 +1008,15 @@ LLVMDIBuilderCreateConstantValueExpression(LLVMDIBuilderRef Builder,
* \param Expr The location of the global relative to the attached
* GlobalVariable.
* \param Decl Reference to the corresponding declaration.
* variables.
* \param AlignInBits Variable alignment(or 0 if no alignment attr was
* specified)
*/
LLVMMetadataRef
LLVMDIBuilderCreateGlobalVariableExpression(LLVMDIBuilderRef Builder,
LLVMMetadataRef Scope,
const char *Name, size_t NameLen,
const char *Linkage, size_t LinkLen,
LLVMMetadataRef File,
unsigned LineNo,
LLVMMetadataRef Ty,
LLVMBool LocalToUnit,
LLVMMetadataRef Expr,
LLVMMetadataRef Decl,
uint32_t AlignInBits);
LLVMMetadataRef LLVMDIBuilderCreateGlobalVariableExpression(
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
size_t NameLen, const char *Linkage, size_t LinkLen, LLVMMetadataRef File,
unsigned LineNo, LLVMMetadataRef Ty, LLVMBool LocalToUnit,
LLVMMetadataRef Expr, LLVMMetadataRef Decl, uint32_t AlignInBits);
/**
* Create a new temporary \c MDNode. Suitable for use in constructing cyclic
* \c MDNode structures. A temporary \c MDNode is not uniqued, may be RAUW'd,
@ -1025,17 +1062,11 @@ void LLVMMetadataReplaceAllUsesWith(LLVMMetadataRef TempTargetMetadata,
* \param AlignInBits Variable alignment(or 0 if no alignment attr was
* specified)
*/
LLVMMetadataRef
LLVMDIBuilderCreateTempGlobalVariableFwdDecl(LLVMDIBuilderRef Builder,
LLVMMetadataRef Scope,
const char *Name, size_t NameLen,
const char *Linkage, size_t LnkLen,
LLVMMetadataRef File,
unsigned LineNo,
LLVMMetadataRef Ty,
LLVMBool LocalToUnit,
LLVMMetadataRef Decl,
uint32_t AlignInBits);
LLVMMetadataRef LLVMDIBuilderCreateTempGlobalVariableFwdDecl(
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
size_t NameLen, const char *Linkage, size_t LnkLen, LLVMMetadataRef File,
unsigned LineNo, LLVMMetadataRef Ty, LLVMBool LocalToUnit,
LLVMMetadataRef Decl, uint32_t AlignInBits);
/**
* Insert a new llvm.dbg.declare intrinsic call before the given instruction.
@ -1149,6 +1180,13 @@ LLVMMetadataRef LLVMGetSubprogram(LLVMValueRef Func);
*/
void LLVMSetSubprogram(LLVMValueRef Func, LLVMMetadataRef SP);
/**
* Obtain the enumerated type of a Metadata instance.
*
* @see llvm::Metadata::getMetadataID()
*/
LLVMMetadataKind LLVMGetMetadataKind(LLVMMetadataRef Metadata);
#ifdef __cplusplus
} /* end extern "C" */
#endif

View file

@ -0,0 +1,69 @@
/*===------- llvm-c/Error.h - llvm::Error class C Interface -------*- C -*-===*\
|* *|
|* The LLVM Compiler Infrastructure *|
|* *|
|* This file is distributed under the University of Illinois Open Source *|
|* License. See LICENSE.TXT for details. *|
|* *|
|*===----------------------------------------------------------------------===*|
|* *|
|* This file defines the C interface to LLVM's Error class. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_C_ERROR_H
#define LLVM_C_ERROR_H
#ifdef __cplusplus
extern "C" {
#endif
#define LLVMErrorSuccess 0
/**
* Opaque reference to an error instance. Null serves as the 'success' value.
*/
typedef struct LLVMOpaqueError *LLVMErrorRef;
/**
* Error type identifier.
*/
typedef const void *LLVMErrorTypeId;
/**
* Returns the type id for the given error instance, which must be a failure
* value (i.e. non-null).
*/
LLVMErrorTypeId LLVMGetErrorTypeId(LLVMErrorRef Err);
/**
* Dispose of the given error without handling it. This operation consumes the
* error, and the given LLVMErrorRef value is not usable once this call returns.
* Note: This method *only* needs to be called if the error is not being passed
* to some other consuming operation, e.g. LLVMGetErrorMessage.
*/
void LLVMConsumeError(LLVMErrorRef Err);
/**
* Returns the given string's error message. This operation consumes the error,
* and the given LLVMErrorRef value is not usable once this call returns.
* The caller is responsible for disposing of the string by calling
* LLVMDisposeErrorMessage.
*/
char *LLVMGetErrorMessage(LLVMErrorRef Err);
/**
* Dispose of the given error message.
*/
void LLVMDisposeErrorMessage(char *ErrMsg);
/**
* Returns the type id for llvm StringError.
*/
LLVMErrorTypeId LLVMGetStringErrorTypeId();
#ifdef __cplusplus
}
#endif
#endif

View file

@ -186,7 +186,7 @@ void LLVMDisposeMCJITMemoryManager(LLVMMCJITMemoryManagerRef MM);
LLVMJITEventListenerRef LLVMCreateGDBRegistrationListener(void);
LLVMJITEventListenerRef LLVMCreateIntelJITEventListener(void);
LLVMJITEventListenerRef LLVMCreateOprofileJITEventListener(void);
LLVMJITEventListenerRef LLVMCreateOProfileJITEventListener(void);
LLVMJITEventListenerRef LLVMCreatePerfJITEventListener(void);
/**

View file

@ -0,0 +1,204 @@
/*===-- llvm-c/OptRemarks.h - OptRemarks Public C Interface -------*- C -*-===*\
|* *|
|* The LLVM Compiler Infrastructure *|
|* *|
|* This file is distributed under the University of Illinois Open Source *|
|* License. See LICENSE.TXT for details. *|
|* *|
|*===----------------------------------------------------------------------===*|
|* *|
|* This header provides a public interface to an opt-remark library. *|
|* LLVM provides an implementation of this interface. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_C_OPT_REMARKS_H
#define LLVM_C_OPT_REMARKS_H
#include "llvm-c/Core.h"
#include "llvm-c/Types.h"
#ifdef __cplusplus
#include <cstddef>
extern "C" {
#else
#include <stddef.h>
#endif /* !defined(__cplusplus) */
/**
* @defgroup LLVMCOPTREMARKS OptRemarks
* @ingroup LLVMC
*
* @{
*/
#define OPT_REMARKS_API_VERSION 0
/**
* String containing a buffer and a length. The buffer is not guaranteed to be
* zero-terminated.
*
* \since OPT_REMARKS_API_VERSION=0
*/
typedef struct {
const char *Str;
uint32_t Len;
} LLVMOptRemarkStringRef;
/**
* DebugLoc containing File, Line and Column.
*
* \since OPT_REMARKS_API_VERSION=0
*/
typedef struct {
// File:
LLVMOptRemarkStringRef SourceFile;
// Line:
uint32_t SourceLineNumber;
// Column:
uint32_t SourceColumnNumber;
} LLVMOptRemarkDebugLoc;
/**
* Element of the "Args" list. The key might give more information about what
* are the semantics of the value, e.g. "Callee" will tell you that the value
* is a symbol that names a function.
*
* \since OPT_REMARKS_API_VERSION=0
*/
typedef struct {
// e.g. "Callee"
LLVMOptRemarkStringRef Key;
// e.g. "malloc"
LLVMOptRemarkStringRef Value;
// "DebugLoc": Optional
LLVMOptRemarkDebugLoc DebugLoc;
} LLVMOptRemarkArg;
/**
* One remark entry.
*
* \since OPT_REMARKS_API_VERSION=0
*/
typedef struct {
// e.g. !Missed, !Passed
LLVMOptRemarkStringRef RemarkType;
// "Pass": Required
LLVMOptRemarkStringRef PassName;
// "Name": Required
LLVMOptRemarkStringRef RemarkName;
// "Function": Required
LLVMOptRemarkStringRef FunctionName;
// "DebugLoc": Optional
LLVMOptRemarkDebugLoc DebugLoc;
// "Hotness": Optional
uint32_t Hotness;
// "Args": Optional. It is an array of `num_args` elements.
uint32_t NumArgs;
LLVMOptRemarkArg *Args;
} LLVMOptRemarkEntry;
typedef struct LLVMOptRemarkOpaqueParser *LLVMOptRemarkParserRef;
/**
* Creates a remark parser that can be used to read and parse the buffer located
* in \p Buf of size \p Size.
*
* \p Buf cannot be NULL.
*
* This function should be paired with LLVMOptRemarkParserDispose() to avoid
* leaking resources.
*
* \since OPT_REMARKS_API_VERSION=0
*/
extern LLVMOptRemarkParserRef LLVMOptRemarkParserCreate(const void *Buf,
uint64_t Size);
/**
* Returns the next remark in the file.
*
* The value pointed to by the return value is invalidated by the next call to
* LLVMOptRemarkParserGetNext().
*
* If the parser reaches the end of the buffer, the return value will be NULL.
*
* In the case of an error, the return value will be NULL, and:
*
* 1) LLVMOptRemarkParserHasError() will return `1`.
*
* 2) LLVMOptRemarkParserGetErrorMessage() will return a descriptive error
* message.
*
* An error may occur if:
*
* 1) An argument is invalid.
*
* 2) There is a YAML parsing error. This type of error aborts parsing
* immediately and returns `1`. It can occur on malformed YAML.
*
* 3) Remark parsing error. If this type of error occurs, the parser won't call
* the handler and will continue to the next one. It can occur on malformed
* remarks, like missing or extra fields in the file.
*
* Here is a quick example of the usage:
*
* ```
* LLVMOptRemarkParserRef Parser = LLVMOptRemarkParserCreate(Buf, Size);
* LLVMOptRemarkEntry *Remark = NULL;
* while ((Remark == LLVMOptRemarkParserGetNext(Parser))) {
* // use Remark
* }
* bool HasError = LLVMOptRemarkParserHasError(Parser);
* LLVMOptRemarkParserDispose(Parser);
* ```
*
* \since OPT_REMARKS_API_VERSION=0
*/
extern LLVMOptRemarkEntry *
LLVMOptRemarkParserGetNext(LLVMOptRemarkParserRef Parser);
/**
* Returns `1` if the parser encountered an error while parsing the buffer.
*
* \since OPT_REMARKS_API_VERSION=0
*/
extern LLVMBool LLVMOptRemarkParserHasError(LLVMOptRemarkParserRef Parser);
/**
* Returns a null-terminated string containing an error message.
*
* In case of no error, the result is `NULL`.
*
* The memory of the string is bound to the lifetime of \p Parser. If
* LLVMOptRemarkParserDispose() is called, the memory of the string will be
* released.
*
* \since OPT_REMARKS_API_VERSION=0
*/
extern const char *
LLVMOptRemarkParserGetErrorMessage(LLVMOptRemarkParserRef Parser);
/**
* Releases all the resources used by \p Parser.
*
* \since OPT_REMARKS_API_VERSION=0
*/
extern void LLVMOptRemarkParserDispose(LLVMOptRemarkParserRef Parser);
/**
* Returns the version of the opt-remarks dylib.
*
* \since OPT_REMARKS_API_VERSION=0
*/
extern uint32_t LLVMOptRemarkVersion(void);
/**
* @} // endgoup LLVMCOPTREMARKS
*/
#ifdef __cplusplus
}
#endif /* !defined(__cplusplus) */
#endif /* LLVM_C_OPT_REMARKS_H */

View file

@ -22,6 +22,7 @@
#ifndef LLVM_C_ORCBINDINGS_H
#define LLVM_C_ORCBINDINGS_H
#include "llvm-c/Error.h"
#include "llvm-c/Object.h"
#include "llvm-c/TargetMachine.h"
@ -36,8 +37,6 @@ typedef uint64_t (*LLVMOrcSymbolResolverFn)(const char *Name, void *LookupCtx);
typedef uint64_t (*LLVMOrcLazyCompileCallbackFn)(LLVMOrcJITStackRef JITStack,
void *CallbackCtx);
typedef enum { LLVMOrcErrSuccess = 0, LLVMOrcErrGeneric } LLVMOrcErrorCode;
/**
* Create an ORC JIT stack.
*
@ -72,43 +71,41 @@ void LLVMOrcDisposeMangledSymbol(char *MangledSymbol);
/**
* Create a lazy compile callback.
*/
LLVMOrcErrorCode
LLVMOrcCreateLazyCompileCallback(LLVMOrcJITStackRef JITStack,
LLVMOrcTargetAddress *RetAddr,
LLVMOrcLazyCompileCallbackFn Callback,
void *CallbackCtx);
LLVMErrorRef LLVMOrcCreateLazyCompileCallback(
LLVMOrcJITStackRef JITStack, LLVMOrcTargetAddress *RetAddr,
LLVMOrcLazyCompileCallbackFn Callback, void *CallbackCtx);
/**
* Create a named indirect call stub.
*/
LLVMOrcErrorCode LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack,
const char *StubName,
LLVMOrcTargetAddress InitAddr);
LLVMErrorRef LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack,
const char *StubName,
LLVMOrcTargetAddress InitAddr);
/**
* Set the pointer for the given indirect stub.
*/
LLVMOrcErrorCode LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack,
const char *StubName,
LLVMOrcTargetAddress NewAddr);
LLVMErrorRef LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack,
const char *StubName,
LLVMOrcTargetAddress NewAddr);
/**
* Add module to be eagerly compiled.
*/
LLVMOrcErrorCode
LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle, LLVMModuleRef Mod,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx);
LLVMErrorRef LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle,
LLVMModuleRef Mod,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx);
/**
* Add module to be lazily compiled one function at a time.
*/
LLVMOrcErrorCode
LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle, LLVMModuleRef Mod,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx);
LLVMErrorRef LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle,
LLVMModuleRef Mod,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx);
/**
* Add an object file.
@ -118,11 +115,11 @@ LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack,
* Clients should *not* dispose of the 'Obj' argument: the JIT will manage it
* from this call onwards.
*/
LLVMOrcErrorCode LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle,
LLVMMemoryBufferRef Obj,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx);
LLVMErrorRef LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle,
LLVMMemoryBufferRef Obj,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx);
/**
* Remove a module set from the JIT.
@ -130,29 +127,29 @@ LLVMOrcErrorCode LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack,
* This works for all modules that can be added via OrcAdd*, including object
* files.
*/
LLVMOrcErrorCode LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle H);
LLVMErrorRef LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle H);
/**
* Get symbol address from JIT instance.
*/
LLVMOrcErrorCode LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack,
LLVMOrcTargetAddress *RetAddr,
const char *SymbolName);
LLVMErrorRef LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack,
LLVMOrcTargetAddress *RetAddr,
const char *SymbolName);
/**
* Get symbol address from JIT instance, searching only the specified
* handle.
*/
LLVMOrcErrorCode LLVMOrcGetSymbolAddressIn(LLVMOrcJITStackRef JITStack,
LLVMOrcTargetAddress *RetAddr,
LLVMOrcModuleHandle H,
const char *SymbolName);
LLVMErrorRef LLVMOrcGetSymbolAddressIn(LLVMOrcJITStackRef JITStack,
LLVMOrcTargetAddress *RetAddr,
LLVMOrcModuleHandle H,
const char *SymbolName);
/**
* Dispose of an ORC JIT stack.
*/
LLVMOrcErrorCode LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack);
LLVMErrorRef LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack);
/**
* Register a JIT Event Listener.

View file

@ -39,12 +39,16 @@ typedef enum {
LLVMRelocDefault,
LLVMRelocStatic,
LLVMRelocPIC,
LLVMRelocDynamicNoPic
LLVMRelocDynamicNoPic,
LLVMRelocROPI,
LLVMRelocRWPI,
LLVMRelocROPI_RWPI
} LLVMRelocMode;
typedef enum {
LLVMCodeModelDefault,
LLVMCodeModelJITDefault,
LLVMCodeModelTiny,
LLVMCodeModelSmall,
LLVMCodeModelKernel,
LLVMCodeModelMedium,

View file

@ -0,0 +1,43 @@
/*===-- AggressiveInstCombine.h ---------------------------------*- C++ -*-===*\
|* *|
|* The LLVM Compiler Infrastructure *|
|* *|
|* This file is distributed under the University of Illinois Open Source *|
|* License. See LICENSE.TXT for details. *|
|* *|
|*===----------------------------------------------------------------------===*|
|* *|
|* This header declares the C interface to libLLVMAggressiveInstCombine.a, *|
|* which combines instructions to form fewer, simple IR instructions. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_C_TRANSFORMS_AGGRESSIVEINSTCOMBINE_H
#define LLVM_C_TRANSFORMS_AGGRESSIVEINSTCOMBINE_H
#include "llvm-c/Types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup LLVMCTransformsAggressiveInstCombine Aggressive Instruction Combining transformations
* @ingroup LLVMCTransforms
*
* @{
*/
/** See llvm::createAggressiveInstCombinerPass function. */
void LLVMAddAggressiveInstCombinerPass(LLVMPassManagerRef PM);
/**
* @}
*/
#ifdef __cplusplus
}
#endif /* defined(__cplusplus) */
#endif

View file

@ -0,0 +1,55 @@
/*===-- Coroutines.h - Coroutines Library C Interface -----------*- C++ -*-===*\
|* *|
|* The LLVM Compiler Infrastructure *|
|* *|
|* This file is distributed under the University of Illinois Open Source *|
|* License. See LICENSE.TXT for details. *|
|* *|
|*===----------------------------------------------------------------------===*|
|* *|
|* This header declares the C interface to libLLVMCoroutines.a, which *|
|* implements various scalar transformations of the LLVM IR. *|
|* *|
|* Many exotic languages can interoperate with C code but have a harder time *|
|* with C++ due to name mangling. So in addition to C, this interface enables *|
|* tools written in such languages. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_C_TRANSFORMS_COROUTINES_H
#define LLVM_C_TRANSFORMS_COROUTINES_H
#include "llvm-c/Types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup LLVMCTransformsCoroutines Coroutine transformations
* @ingroup LLVMCTransforms
*
* @{
*/
/** See llvm::createCoroEarlyPass function. */
void LLVMAddCoroEarlyPass(LLVMPassManagerRef PM);
/** See llvm::createCoroSplitPass function. */
void LLVMAddCoroSplitPass(LLVMPassManagerRef PM);
/** See llvm::createCoroElidePass function. */
void LLVMAddCoroElidePass(LLVMPassManagerRef PM);
/** See llvm::createCoroCleanupPass function. */
void LLVMAddCoroCleanupPass(LLVMPassManagerRef PM);
/**
* @}
*/
#ifdef __cplusplus
}
#endif /* defined(__cplusplus) */
#endif

View file

@ -35,9 +35,6 @@ extern "C" {
/** See llvm::createAggressiveDCEPass function. */
void LLVMAddAggressiveDCEPass(LLVMPassManagerRef PM);
/** See llvm::createAggressiveInstCombinerPass function. */
void LLVMAddAggressiveInstCombinerPass(LLVMPassManagerRef PM);
/** See llvm::createBitTrackingDCEPass function. */
void LLVMAddBitTrackingDCEPass(LLVMPassManagerRef PM);
@ -95,6 +92,9 @@ void LLVMAddLoopUnrollAndJamPass(LLVMPassManagerRef PM);
/** See llvm::createLoopUnswitchPass function. */
void LLVMAddLoopUnswitchPass(LLVMPassManagerRef PM);
/** See llvm::createLowerAtomicPass function. */
void LLVMAddLowerAtomicPass(LLVMPassManagerRef PM);
/** See llvm::createMemCpyOptPass function. */
void LLVMAddMemCpyOptPass(LLVMPassManagerRef PM);
@ -153,6 +153,9 @@ void LLVMAddScopedNoAliasAAPass(LLVMPassManagerRef PM);
/** See llvm::createBasicAliasAnalysisPass function */
void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM);
/** See llvm::createUnifyFunctionExitNodesPass function */
void LLVMAddUnifyFunctionExitNodesPass(LLVMPassManagerRef PM);
/**
* @}
*/

View file

@ -89,6 +89,20 @@ typedef struct LLVMOpaqueBasicBlock *LLVMBasicBlockRef;
*/
typedef struct LLVMOpaqueMetadata *LLVMMetadataRef;
/**
* Represents an LLVM Named Metadata Node.
*
* This models llvm::NamedMDNode.
*/
typedef struct LLVMOpaqueNamedMDNode *LLVMNamedMDNodeRef;
/**
* Represents an entry in a Global Object's metadata attachments.
*
* This models std::pair<unsigned, MDNode *>
*/
typedef struct LLVMOpaqueValueMetadataEntry LLVMValueMetadataEntry;
/**
* Represents an LLVM basic block builder.
*

View file

@ -44,7 +44,7 @@ typedef bool lto_bool_t;
* @{
*/
#define LTO_API_VERSION 22
#define LTO_API_VERSION 23
/**
* \since prior to LTO_API_VERSION=3
@ -827,6 +827,16 @@ extern void thinlto_codegen_set_cache_entry_expiration(thinlto_code_gen_t cg,
extern void thinlto_codegen_set_cache_size_bytes(thinlto_code_gen_t cg,
unsigned max_size_bytes);
/**
* Same as thinlto_codegen_set_cache_size_bytes, except the maximum size is in
* megabytes (2^20 bytes).
*
* \since LTO_API_VERSION=23
*/
extern void
thinlto_codegen_set_cache_size_megabytes(thinlto_code_gen_t cg,
unsigned max_size_megabytes);
/**
* Sets the maximum number of files in the cache directory. An unspecified
* default value will be applied. A value of 0 will be ignored.

View file

@ -870,13 +870,13 @@ public:
/// Factory for NaN values.
///
/// \param Negative - True iff the NaN generated should be negative.
/// \param type - The unspecified fill bits for creating the NaN, 0 by
/// \param payload - The unspecified fill bits for creating the NaN, 0 by
/// default. The value is truncated as necessary.
static APFloat getNaN(const fltSemantics &Sem, bool Negative = false,
unsigned type = 0) {
if (type) {
APInt fill(64, type);
return getQNaN(Sem, Negative, &fill);
uint64_t payload = 0) {
if (payload) {
APInt intPayload(64, payload);
return getQNaN(Sem, Negative, &intPayload);
} else {
return getQNaN(Sem, Negative, nullptr);
}
@ -1243,6 +1243,32 @@ inline APFloat maxnum(const APFloat &A, const APFloat &B) {
return (A.compare(B) == APFloat::cmpLessThan) ? B : A;
}
/// Implements IEEE 754-2018 minimum semantics. Returns the smaller of 2
/// arguments, propagating NaNs and treating -0 as less than +0.
LLVM_READONLY
inline APFloat minimum(const APFloat &A, const APFloat &B) {
if (A.isNaN())
return A;
if (B.isNaN())
return B;
if (A.isZero() && B.isZero() && (A.isNegative() != B.isNegative()))
return A.isNegative() ? A : B;
return (B.compare(A) == APFloat::cmpLessThan) ? B : A;
}
/// Implements IEEE 754-2018 maximum semantics. Returns the larger of 2
/// arguments, propagating NaNs and treating -0 as less than +0.
LLVM_READONLY
inline APFloat maximum(const APFloat &A, const APFloat &B) {
if (A.isNaN())
return A;
if (B.isNaN())
return B;
if (A.isZero() && B.isZero() && (A.isNegative() != B.isNegative()))
return A.isNegative() ? B : A;
return (A.compare(B) == APFloat::cmpLessThan) ? B : A;
}
} // namespace llvm
#undef APFLOAT_DISPATCH_ON_SEMANTICS

View file

@ -31,6 +31,7 @@ class raw_ostream;
template <typename T> class SmallVectorImpl;
template <typename T> class ArrayRef;
template <typename T> class Optional;
class APInt;
@ -84,7 +85,7 @@ public:
UP,
};
static const WordType WORD_MAX = ~WordType(0);
static const WordType WORDTYPE_MAX = ~WordType(0);
private:
/// This union is used to store the integer value. When the
@ -149,7 +150,7 @@ private:
unsigned WordBits = ((BitWidth-1) % APINT_BITS_PER_WORD) + 1;
// Mask out the high bits.
uint64_t mask = WORD_MAX >> (APINT_BITS_PER_WORD - WordBits);
uint64_t mask = WORDTYPE_MAX >> (APINT_BITS_PER_WORD - WordBits);
if (isSingleWord())
U.VAL &= mask;
else
@ -394,7 +395,7 @@ public:
/// This checks to see if the value has all bits of the APInt are set or not.
bool isAllOnesValue() const {
if (isSingleWord())
return U.VAL == WORD_MAX >> (APINT_BITS_PER_WORD - BitWidth);
return U.VAL == WORDTYPE_MAX >> (APINT_BITS_PER_WORD - BitWidth);
return countTrailingOnesSlowCase() == BitWidth;
}
@ -495,7 +496,7 @@ public:
assert(numBits != 0 && "numBits must be non-zero");
assert(numBits <= BitWidth && "numBits out of range");
if (isSingleWord())
return U.VAL == (WORD_MAX >> (APINT_BITS_PER_WORD - numBits));
return U.VAL == (WORDTYPE_MAX >> (APINT_BITS_PER_WORD - numBits));
unsigned Ones = countTrailingOnesSlowCase();
return (numBits == Ones) &&
((Ones + countLeadingZerosSlowCase()) == BitWidth);
@ -559,7 +560,7 @@ public:
///
/// \returns the all-ones value for an APInt of the specified bit-width.
static APInt getAllOnesValue(unsigned numBits) {
return APInt(numBits, WORD_MAX, true);
return APInt(numBits, WORDTYPE_MAX, true);
}
/// Get the '0' value.
@ -1104,6 +1105,12 @@ public:
APInt sshl_ov(const APInt &Amt, bool &Overflow) const;
APInt ushl_ov(const APInt &Amt, bool &Overflow) const;
// Operations that saturate
APInt sadd_sat(const APInt &RHS) const;
APInt uadd_sat(const APInt &RHS) const;
APInt ssub_sat(const APInt &RHS) const;
APInt usub_sat(const APInt &RHS) const;
/// Array-indexing support.
///
/// \returns the bit value at bitPosition
@ -1382,7 +1389,7 @@ public:
/// Set every bit to 1.
void setAllBits() {
if (isSingleWord())
U.VAL = WORD_MAX;
U.VAL = WORDTYPE_MAX;
else
// Set all the bits in all the words.
memset(U.pVal, -1, getNumWords() * APINT_WORD_SIZE);
@ -1394,7 +1401,7 @@ public:
///
/// Set the given bit to 1 whose position is given as "bitPosition".
void setBit(unsigned BitPosition) {
assert(BitPosition <= BitWidth && "BitPosition out of range");
assert(BitPosition < BitWidth && "BitPosition out of range");
WordType Mask = maskBit(BitPosition);
if (isSingleWord())
U.VAL |= Mask;
@ -1415,7 +1422,7 @@ public:
if (loBit == hiBit)
return;
if (loBit < APINT_BITS_PER_WORD && hiBit <= APINT_BITS_PER_WORD) {
uint64_t mask = WORD_MAX >> (APINT_BITS_PER_WORD - (hiBit - loBit));
uint64_t mask = WORDTYPE_MAX >> (APINT_BITS_PER_WORD - (hiBit - loBit));
mask <<= loBit;
if (isSingleWord())
U.VAL |= mask;
@ -1453,7 +1460,7 @@ public:
///
/// Set the given bit to 0 whose position is given as "bitPosition".
void clearBit(unsigned BitPosition) {
assert(BitPosition <= BitWidth && "BitPosition out of range");
assert(BitPosition < BitWidth && "BitPosition out of range");
WordType Mask = ~maskBit(BitPosition);
if (isSingleWord())
U.VAL &= Mask;
@ -1469,7 +1476,7 @@ public:
/// Toggle every bit to its opposite value.
void flipAllBits() {
if (isSingleWord()) {
U.VAL ^= WORD_MAX;
U.VAL ^= WORDTYPE_MAX;
clearUnusedBits();
} else {
flipAllBitsSlowCase();
@ -1758,7 +1765,7 @@ public:
/// referencing 2 in a space where 2 does no exist.
unsigned nearestLogBase2() const {
// Special case when we have a bitwidth of 1. If VAL is 1, then we
// get 0. If VAL is 0, we get WORD_MAX which gets truncated to
// get 0. If VAL is 0, we get WORDTYPE_MAX which gets truncated to
// UINT32_MAX.
if (BitWidth == 1)
return U.VAL - 1;
@ -2166,6 +2173,41 @@ APInt RoundingUDiv(const APInt &A, const APInt &B, APInt::Rounding RM);
/// Return A sign-divided by B, rounded by the given rounding mode.
APInt RoundingSDiv(const APInt &A, const APInt &B, APInt::Rounding RM);
/// Let q(n) = An^2 + Bn + C, and BW = bit width of the value range
/// (e.g. 32 for i32).
/// This function finds the smallest number n, such that
/// (a) n >= 0 and q(n) = 0, or
/// (b) n >= 1 and q(n-1) and q(n), when evaluated in the set of all
/// integers, belong to two different intervals [Rk, Rk+R),
/// where R = 2^BW, and k is an integer.
/// The idea here is to find when q(n) "overflows" 2^BW, while at the
/// same time "allowing" subtraction. In unsigned modulo arithmetic a
/// subtraction (treated as addition of negated numbers) would always
/// count as an overflow, but here we want to allow values to decrease
/// and increase as long as they are within the same interval.
/// Specifically, adding of two negative numbers should not cause an
/// overflow (as long as the magnitude does not exceed the bith width).
/// On the other hand, given a positive number, adding a negative
/// number to it can give a negative result, which would cause the
/// value to go from [-2^BW, 0) to [0, 2^BW). In that sense, zero is
/// treated as a special case of an overflow.
///
/// This function returns None if after finding k that minimizes the
/// positive solution to q(n) = kR, both solutions are contained between
/// two consecutive integers.
///
/// There are cases where q(n) > T, and q(n+1) < T (assuming evaluation
/// in arithmetic modulo 2^BW, and treating the values as signed) by the
/// virtue of *signed* overflow. This function will *not* find such an n,
/// however it may find a value of n satisfying the inequalities due to
/// an *unsigned* overflow (if the values are treated as unsigned).
/// To find a solution for a signed overflow, treat it as a problem of
/// finding an unsigned overflow with a range with of BW-1.
///
/// The returned value may have a different bit width from the input
/// coefficients.
Optional<APInt> SolveQuadraticEquationWrap(APInt A, APInt B, APInt C,
unsigned RangeWidth);
} // End of APIntOps namespace
// See friend declaration above. This additional declaration is required in

View file

@ -65,6 +65,16 @@ public:
typename std::enable_if<
llvm::conjunction<
llvm::negation<std::is_same<typename std::decay<T>::type, Any>>,
// We also disable this overload when an `Any` object can be
// converted to the parameter type because in that case, this
// constructor may combine with that conversion during overload
// resolution for determining copy constructibility, and then
// when we try to determine copy constructibility below we may
// infinitely recurse. This is being evaluated by the standards
// committee as a potential DR in `std::any` as well, but we're
// going ahead and adopting it to work-around usage of `Any` with
// types that need to be implicitly convertible from an `Any`.
llvm::negation<std::is_convertible<Any, typename std::decay<T>::type>>,
std::is_copy_constructible<typename std::decay<T>::type>>::value,
int>::type = 0>
Any(T &&Value) {

View file

@ -503,6 +503,23 @@ public:
return (*this)[Idx];
}
// Push single bit to end of vector.
void push_back(bool Val) {
unsigned OldSize = Size;
unsigned NewSize = Size + 1;
// Resize, which will insert zeros.
// If we already fit then the unused bits will be already zero.
if (NewSize > getBitCapacity())
resize(NewSize, false);
else
Size = NewSize;
// If true, set single bit.
if (Val)
set(OldSize);
}
/// Test if any common bits are set.
bool anyCommon(const BitVector &RHS) const {
unsigned ThisWords = NumBitWords(size());

View file

@ -25,6 +25,7 @@
#include <cassert>
#include <cstddef>
#include <cstring>
#include <initializer_list>
#include <iterator>
#include <new>
#include <type_traits>
@ -38,6 +39,34 @@ namespace detail {
// implementation without requiring two members.
template <typename KeyT, typename ValueT>
struct DenseMapPair : public std::pair<KeyT, ValueT> {
// FIXME: Switch to inheriting constructors when we drop support for older
// clang versions.
// NOTE: This default constructor is declared with '{}' rather than
// '= default' to work around a separate bug in clang-3.8. This can
// also go when we switch to inheriting constructors.
DenseMapPair() {}
DenseMapPair(const KeyT &Key, const ValueT &Value)
: std::pair<KeyT, ValueT>(Key, Value) {}
DenseMapPair(KeyT &&Key, ValueT &&Value)
: std::pair<KeyT, ValueT>(std::move(Key), std::move(Value)) {}
template <typename AltKeyT, typename AltValueT>
DenseMapPair(AltKeyT &&AltKey, AltValueT &&AltValue,
typename std::enable_if<
std::is_convertible<AltKeyT, KeyT>::value &&
std::is_convertible<AltValueT, ValueT>::value>::type * = 0)
: std::pair<KeyT, ValueT>(std::forward<AltKeyT>(AltKey),
std::forward<AltValueT>(AltValue)) {}
template <typename AltPairT>
DenseMapPair(AltPairT &&AltPair,
typename std::enable_if<std::is_convertible<
AltPairT, std::pair<KeyT, ValueT>>::value>::type * = 0)
: std::pair<KeyT, ValueT>(std::forward<AltPairT>(AltPair)) {}
KeyT &getFirst() { return std::pair<KeyT, ValueT>::first; }
const KeyT &getFirst() const { return std::pair<KeyT, ValueT>::first; }
ValueT &getSecond() { return std::pair<KeyT, ValueT>::second; }
@ -46,9 +75,10 @@ struct DenseMapPair : public std::pair<KeyT, ValueT> {
} // end namespace detail
template <
typename KeyT, typename ValueT, typename KeyInfoT = DenseMapInfo<KeyT>,
typename Bucket = detail::DenseMapPair<KeyT, ValueT>, bool IsConst = false>
template <typename KeyT, typename ValueT,
typename KeyInfoT = DenseMapInfo<KeyT>,
typename Bucket = llvm::detail::DenseMapPair<KeyT, ValueT>,
bool IsConst = false>
class DenseMapIterator;
template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
@ -393,7 +423,7 @@ protected:
setNumTombstones(other.getNumTombstones());
if (isPodLike<KeyT>::value && isPodLike<ValueT>::value)
memcpy(getBuckets(), other.getBuckets(),
memcpy(reinterpret_cast<void *>(getBuckets()), other.getBuckets(),
getNumBuckets() * sizeof(BucketT));
else
for (size_t i = 0; i < getNumBuckets(); ++i) {
@ -639,9 +669,43 @@ public:
}
};
/// Equality comparison for DenseMap.
///
/// Iterates over elements of LHS confirming that each (key, value) pair in LHS
/// is also in RHS, and that no additional pairs are in RHS.
/// Equivalent to N calls to RHS.find and N value comparisons. Amortized
/// complexity is linear, worst case is O(N^2) (if every hash collides).
template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
typename BucketT>
bool operator==(
const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS,
const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) {
if (LHS.size() != RHS.size())
return false;
for (auto &KV : LHS) {
auto I = RHS.find(KV.first);
if (I == RHS.end() || I->second != KV.second)
return false;
}
return true;
}
/// Inequality comparison for DenseMap.
///
/// Equivalent to !(LHS == RHS). See operator== for performance notes.
template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
typename BucketT>
bool operator!=(
const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS,
const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) {
return !(LHS == RHS);
}
template <typename KeyT, typename ValueT,
typename KeyInfoT = DenseMapInfo<KeyT>,
typename BucketT = detail::DenseMapPair<KeyT, ValueT>>
typename BucketT = llvm::detail::DenseMapPair<KeyT, ValueT>>
class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
KeyT, ValueT, KeyInfoT, BucketT> {
friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
@ -676,6 +740,11 @@ public:
this->insert(I, E);
}
DenseMap(std::initializer_list<typename BaseT::value_type> Vals) {
init(Vals.size());
this->insert(Vals.begin(), Vals.end());
}
~DenseMap() {
this->destroyAll();
operator delete(Buckets);
@ -798,7 +867,7 @@ private:
template <typename KeyT, typename ValueT, unsigned InlineBuckets = 4,
typename KeyInfoT = DenseMapInfo<KeyT>,
typename BucketT = detail::DenseMapPair<KeyT, ValueT>>
typename BucketT = llvm::detail::DenseMapPair<KeyT, ValueT>>
class SmallDenseMap
: public DenseMapBase<
SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT,

View file

@ -16,6 +16,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/type_traits.h"
#include <algorithm>
#include <cstddef>
@ -67,7 +68,7 @@ public:
explicit DenseSetImpl(unsigned InitialReserve = 0) : TheMap(InitialReserve) {}
DenseSetImpl(std::initializer_list<ValueT> Elems)
: DenseSetImpl(Elems.size()) {
: DenseSetImpl(PowerOf2Ceil(Elems.size())) {
insert(Elems.begin(), Elems.end());
}
@ -136,8 +137,8 @@ public:
public:
using difference_type = typename MapTy::const_iterator::difference_type;
using value_type = ValueT;
using pointer = value_type *;
using reference = value_type &;
using pointer = const value_type *;
using reference = const value_type &;
using iterator_category = std::forward_iterator_tag;
ConstIterator() = default;
@ -214,6 +215,34 @@ public:
}
};
/// Equality comparison for DenseSet.
///
/// Iterates over elements of LHS confirming that each element is also a member
/// of RHS, and that RHS contains no additional values.
/// Equivalent to N calls to RHS.count. Amortized complexity is linear, worst
/// case is O(N^2) (if every hash collides).
template <typename ValueT, typename MapTy, typename ValueInfoT>
bool operator==(const DenseSetImpl<ValueT, MapTy, ValueInfoT> &LHS,
const DenseSetImpl<ValueT, MapTy, ValueInfoT> &RHS) {
if (LHS.size() != RHS.size())
return false;
for (auto &E : LHS)
if (!RHS.count(E))
return false;
return true;
}
/// Inequality comparison for DenseSet.
///
/// Equivalent to !(LHS == RHS). See operator== for performance notes.
template <typename ValueT, typename MapTy, typename ValueInfoT>
bool operator!=(const DenseSetImpl<ValueT, MapTy, ValueInfoT> &LHS,
const DenseSetImpl<ValueT, MapTy, ValueInfoT> &RHS) {
return !(LHS == RHS);
}
} // end namespace detail
/// Implements a dense probed hash-table based set.

View file

@ -25,6 +25,13 @@ namespace llvm {
// GraphTraits - This class should be specialized by different graph types...
// which is why the default version is empty.
//
// This template evolved from supporting `BasicBlock` to also later supporting
// more complex types (e.g. CFG and DomTree).
//
// GraphTraits can be used to create a view over a graph interpreting it
// differently without requiring a copy of the original graph. This could
// be achieved by carrying more data in NodeRef. See LoopBodyTraits for one
// example.
template<class GraphType>
struct GraphTraits {
// Elements to provide:

View file

@ -133,7 +133,7 @@ hash_code hash_value(const std::basic_string<T> &arg);
/// undone. This makes it thread-hostile and very hard to use outside of
/// immediately on start of a simple program designed for reproducible
/// behavior.
void set_fixed_execution_hash_seed(size_t fixed_value);
void set_fixed_execution_hash_seed(uint64_t fixed_value);
// All of the implementation details of actually computing the various hash
@ -316,9 +316,9 @@ struct hash_state {
/// This variable can be set using the \see llvm::set_fixed_execution_seed
/// function. See that function for details. Do not, under any circumstances,
/// set or read this variable.
extern size_t fixed_seed_override;
extern uint64_t fixed_seed_override;
inline size_t get_execution_seed() {
inline uint64_t get_execution_seed() {
// FIXME: This needs to be a per-execution seed. This is just a placeholder
// implementation. Switching to a per-execution seed is likely to flush out
// instability bugs and so will happen as its own commit.
@ -326,8 +326,7 @@ inline size_t get_execution_seed() {
// However, if there is a fixed seed override set the first time this is
// called, return that instead of the per-execution seed.
const uint64_t seed_prime = 0xff51afd7ed558ccdULL;
static size_t seed = fixed_seed_override ? fixed_seed_override
: (size_t)seed_prime;
static uint64_t seed = fixed_seed_override ? fixed_seed_override : seed_prime;
return seed;
}
@ -402,7 +401,7 @@ bool store_and_advance(char *&buffer_ptr, char *buffer_end, const T& value,
/// combining them, this (as an optimization) directly combines the integers.
template <typename InputIteratorT>
hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) {
const size_t seed = get_execution_seed();
const uint64_t seed = get_execution_seed();
char buffer[64], *buffer_ptr = buffer;
char *const buffer_end = std::end(buffer);
while (first != last && store_and_advance(buffer_ptr, buffer_end,
@ -446,7 +445,7 @@ hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) {
template <typename ValueT>
typename std::enable_if<is_hashable_data<ValueT>::value, hash_code>::type
hash_combine_range_impl(ValueT *first, ValueT *last) {
const size_t seed = get_execution_seed();
const uint64_t seed = get_execution_seed();
const char *s_begin = reinterpret_cast<const char *>(first);
const char *s_end = reinterpret_cast<const char *>(last);
const size_t length = std::distance(s_begin, s_end);
@ -496,7 +495,7 @@ namespace detail {
struct hash_combine_recursive_helper {
char buffer[64];
hash_state state;
const size_t seed;
const uint64_t seed;
public:
/// Construct a recursive hash combining helper.

View file

@ -31,8 +31,9 @@ class ImmutableListImpl : public FoldingSetNode {
T Head;
const ImmutableListImpl* Tail;
ImmutableListImpl(const T& head, const ImmutableListImpl* tail = nullptr)
: Head(head), Tail(tail) {}
template <typename ElemT>
ImmutableListImpl(ElemT &&head, const ImmutableListImpl *tail = nullptr)
: Head(std::forward<ElemT>(head)), Tail(tail) {}
public:
ImmutableListImpl(const ImmutableListImpl &) = delete;
@ -66,6 +67,9 @@ public:
using value_type = T;
using Factory = ImmutableListFactory<T>;
static_assert(std::is_trivially_destructible<T>::value,
"T must be trivially destructible!");
private:
const ImmutableListImpl<T>* X;
@ -90,6 +94,9 @@ public:
bool operator==(const iterator& I) const { return L == I.L; }
bool operator!=(const iterator& I) const { return L != I.L; }
const value_type& operator*() const { return L->getHead(); }
const typename std::remove_reference<value_type>::type* operator->() const {
return &L->getHead();
}
ImmutableList getList() const { return L; }
};
@ -123,14 +130,14 @@ public:
bool operator==(const ImmutableList& L) const { return isEqual(L); }
/// getHead - Returns the head of the list.
const T& getHead() {
const T& getHead() const {
assert(!isEmpty() && "Cannot get the head of an empty list.");
return X->getHead();
}
/// getTail - Returns the tail of the list, which is another (possibly empty)
/// ImmutableList.
ImmutableList getTail() {
ImmutableList getTail() const {
return X ? X->getTail() : nullptr;
}
@ -166,7 +173,8 @@ public:
if (ownsAllocator()) delete &getAllocator();
}
LLVM_NODISCARD ImmutableList<T> concat(const T &Head, ImmutableList<T> Tail) {
template <typename ElemT>
LLVM_NODISCARD ImmutableList<T> concat(ElemT &&Head, ImmutableList<T> Tail) {
// Profile the new list to see if it already exists in our cache.
FoldingSetNodeID ID;
void* InsertPos;
@ -179,7 +187,7 @@ public:
// The list does not exist in our cache. Create it.
BumpPtrAllocator& A = getAllocator();
L = (ListTy*) A.Allocate<ListTy>();
new (L) ListTy(Head, TailImpl);
new (L) ListTy(std::forward<ElemT>(Head), TailImpl);
// Insert the new list into the cache.
Cache.InsertNode(L, InsertPos);
@ -188,16 +196,24 @@ public:
return L;
}
LLVM_NODISCARD ImmutableList<T> add(const T& D, ImmutableList<T> L) {
return concat(D, L);
template <typename ElemT>
LLVM_NODISCARD ImmutableList<T> add(ElemT &&Data, ImmutableList<T> L) {
return concat(std::forward<ElemT>(Data), L);
}
template <typename ...CtorArgs>
LLVM_NODISCARD ImmutableList<T> emplace(ImmutableList<T> Tail,
CtorArgs &&...Args) {
return concat(T(std::forward<CtorArgs>(Args)...), Tail);
}
ImmutableList<T> getEmptyList() const {
return ImmutableList<T>(nullptr);
}
ImmutableList<T> create(const T& X) {
return Concat(X, getEmptyList());
template <typename ElemT>
ImmutableList<T> create(ElemT &&Data) {
return concat(std::forward<ElemT>(Data), getEmptyList());
}
};

View file

@ -101,6 +101,7 @@
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/bit.h"
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/RecyclingAllocator.h"
@ -963,6 +964,7 @@ public:
private:
// The root data is either a RootLeaf or a RootBranchData instance.
LLVM_ALIGNAS(RootLeaf) LLVM_ALIGNAS(RootBranchData)
AlignedCharArrayUnion<RootLeaf, RootBranchData> data;
// Tree height.
@ -977,15 +979,10 @@ private:
// Allocator used for creating external nodes.
Allocator &allocator;
/// dataAs - Represent data as a node type without breaking aliasing rules.
/// Represent data as a node type without breaking aliasing rules.
template <typename T>
T &dataAs() const {
union {
const char *d;
T *t;
} u;
u.d = data.buffer;
return *u.t;
return *bit_cast<T *>(const_cast<char *>(data.buffer));
}
const RootLeaf &rootLeaf() const {
@ -1137,6 +1134,19 @@ public:
I.find(x);
return I;
}
/// overlaps(a, b) - Return true if the intervals in this map overlap with the
/// interval [a;b].
bool overlaps(KeyT a, KeyT b) {
assert(Traits::nonEmpty(a, b));
const_iterator I = find(a);
if (!I.valid())
return false;
// [a;b] and [x;y] overlap iff x<=b and a<=y. The find() call guarantees the
// second part (y = find(a).stop()), so it is sufficient to check the first
// one.
return !Traits::stopLess(b, I.start());
}
};
/// treeSafeLookup - Return the mapped value at x or NotFound, assuming a

View file

@ -29,7 +29,7 @@ namespace llvm {
namespace optional_detail {
/// Storage for any type.
template <typename T, bool IsPodLike> struct OptionalStorage {
template <typename T, bool = isPodLike<T>::value> struct OptionalStorage {
AlignedCharArrayUnion<T> storage;
bool hasVal = false;
@ -108,28 +108,10 @@ template <typename T, bool IsPodLike> struct OptionalStorage {
}
};
#if !defined(__GNUC__) || defined(__clang__) // GCC up to GCC7 miscompiles this.
/// Storage for trivially copyable types only.
template <typename T> struct OptionalStorage<T, true> {
AlignedCharArrayUnion<T> storage;
bool hasVal = false;
OptionalStorage() = default;
OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); }
OptionalStorage &operator=(const T &y) {
*reinterpret_cast<T *>(storage.buffer) = y;
hasVal = true;
return *this;
}
void reset() { hasVal = false; }
};
#endif
} // namespace optional_detail
template <typename T> class Optional {
optional_detail::OptionalStorage<T, isPodLike<T>::value> Storage;
optional_detail::OptionalStorage<T> Storage;
public:
using value_type = T;

View file

@ -42,6 +42,8 @@ template <typename PointerTy, unsigned IntBits, typename IntType = unsigned,
typename PtrTraits = PointerLikeTypeTraits<PointerTy>,
typename Info = PointerIntPairInfo<PointerTy, IntBits, PtrTraits>>
class PointerIntPair {
// Used by MSVC visualizer and generally helpful for debugging/visualizing.
using InfoTy = Info;
intptr_t Value = 0;
public:

View file

@ -10,6 +10,7 @@
#ifndef LLVM_ADT_POINTERSUMTYPE_H
#define LLVM_ADT_POINTERSUMTYPE_H
#include "llvm/ADT/bit.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include <cassert>
@ -58,56 +59,142 @@ template <typename TagT, typename... MemberTs> struct PointerSumTypeHelper;
/// and may be desirable to set to a state that is particularly desirable to
/// default construct.
///
/// Having a supported zero-valued tag also enables getting the address of a
/// pointer stored with that tag provided it is stored in its natural bit
/// representation. This works because in the case of a zero-valued tag, the
/// pointer's value is directly stored into this object and we can expose the
/// address of that internal storage. This is especially useful when building an
/// `ArrayRef` of a single pointer stored in a sum type.
///
/// There is no support for constructing or accessing with a dynamic tag as
/// that would fundamentally violate the type safety provided by the sum type.
template <typename TagT, typename... MemberTs> class PointerSumType {
uintptr_t Value = 0;
using HelperT = detail::PointerSumTypeHelper<TagT, MemberTs...>;
// We keep both the raw value and the min tag value's pointer in a union. When
// the minimum tag value is zero, this allows code below to cleanly expose the
// address of the zero-tag pointer instead of just the zero-tag pointer
// itself. This is especially useful when building `ArrayRef`s out of a single
// pointer. However, we have to carefully access the union due to the active
// member potentially changing. When we *store* a new value, we directly
// access the union to allow us to store using the obvious types. However,
// when we *read* a value, we copy the underlying storage out to avoid relying
// on one member or the other being active.
union StorageT {
// Ensure we get a null default constructed value. We don't use a member
// initializer because some compilers seem to not implement those correctly
// for a union.
StorageT() : Value(0) {}
uintptr_t Value;
typename HelperT::template Lookup<HelperT::MinTag>::PointerT MinTagPointer;
};
StorageT Storage;
public:
constexpr PointerSumType() = default;
/// A typed setter to a given tagged member of the sum type.
template <TagT N>
void set(typename HelperT::template Lookup<N>::PointerT Pointer) {
void *V = HelperT::template Lookup<N>::TraitsT::getAsVoidPointer(Pointer);
assert((reinterpret_cast<uintptr_t>(V) & HelperT::TagMask) == 0 &&
"Pointer is insufficiently aligned to store the discriminant!");
Storage.Value = reinterpret_cast<uintptr_t>(V) | N;
}
/// A typed constructor for a specific tagged member of the sum type.
template <TagT N>
static PointerSumType
create(typename HelperT::template Lookup<N>::PointerT Pointer) {
PointerSumType Result;
void *V = HelperT::template Lookup<N>::TraitsT::getAsVoidPointer(Pointer);
assert((reinterpret_cast<uintptr_t>(V) & HelperT::TagMask) == 0 &&
"Pointer is insufficiently aligned to store the discriminant!");
Result.Value = reinterpret_cast<uintptr_t>(V) | N;
Result.set<N>(Pointer);
return Result;
}
TagT getTag() const { return static_cast<TagT>(Value & HelperT::TagMask); }
/// Clear the value to null with the min tag type.
void clear() { set<HelperT::MinTag>(nullptr); }
TagT getTag() const {
return static_cast<TagT>(getOpaqueValue() & HelperT::TagMask);
}
template <TagT N> bool is() const { return N == getTag(); }
template <TagT N> typename HelperT::template Lookup<N>::PointerT get() const {
void *P = is<N>() ? getImpl() : nullptr;
void *P = is<N>() ? getVoidPtr() : nullptr;
return HelperT::template Lookup<N>::TraitsT::getFromVoidPointer(P);
}
template <TagT N>
typename HelperT::template Lookup<N>::PointerT cast() const {
assert(is<N>() && "This instance has a different active member.");
return HelperT::template Lookup<N>::TraitsT::getFromVoidPointer(getImpl());
return HelperT::template Lookup<N>::TraitsT::getFromVoidPointer(
getVoidPtr());
}
explicit operator bool() const { return Value & HelperT::PointerMask; }
bool operator==(const PointerSumType &R) const { return Value == R.Value; }
bool operator!=(const PointerSumType &R) const { return Value != R.Value; }
bool operator<(const PointerSumType &R) const { return Value < R.Value; }
bool operator>(const PointerSumType &R) const { return Value > R.Value; }
bool operator<=(const PointerSumType &R) const { return Value <= R.Value; }
bool operator>=(const PointerSumType &R) const { return Value >= R.Value; }
/// If the tag is zero and the pointer's value isn't changed when being
/// stored, get the address of the stored value type-punned to the zero-tag's
/// pointer type.
typename HelperT::template Lookup<HelperT::MinTag>::PointerT const *
getAddrOfZeroTagPointer() const {
return const_cast<PointerSumType *>(this)->getAddrOfZeroTagPointer();
}
uintptr_t getOpaqueValue() const { return Value; }
/// If the tag is zero and the pointer's value isn't changed when being
/// stored, get the address of the stored value type-punned to the zero-tag's
/// pointer type.
typename HelperT::template Lookup<HelperT::MinTag>::PointerT *
getAddrOfZeroTagPointer() {
static_assert(HelperT::MinTag == 0, "Non-zero minimum tag value!");
assert(is<HelperT::MinTag>() && "The active tag is not zero!");
// Store the initial value of the pointer when read out of our storage.
auto InitialPtr = get<HelperT::MinTag>();
// Now update the active member of the union to be the actual pointer-typed
// member so that accessing it indirectly through the returned address is
// valid.
Storage.MinTagPointer = InitialPtr;
// Finally, validate that this was a no-op as expected by reading it back
// out using the same underlying-storage read as above.
assert(InitialPtr == get<HelperT::MinTag>() &&
"Switching to typed storage changed the pointer returned!");
// Now we can correctly return an address to typed storage.
return &Storage.MinTagPointer;
}
explicit operator bool() const {
return getOpaqueValue() & HelperT::PointerMask;
}
bool operator==(const PointerSumType &R) const {
return getOpaqueValue() == R.getOpaqueValue();
}
bool operator!=(const PointerSumType &R) const {
return getOpaqueValue() != R.getOpaqueValue();
}
bool operator<(const PointerSumType &R) const {
return getOpaqueValue() < R.getOpaqueValue();
}
bool operator>(const PointerSumType &R) const {
return getOpaqueValue() > R.getOpaqueValue();
}
bool operator<=(const PointerSumType &R) const {
return getOpaqueValue() <= R.getOpaqueValue();
}
bool operator>=(const PointerSumType &R) const {
return getOpaqueValue() >= R.getOpaqueValue();
}
uintptr_t getOpaqueValue() const {
// Read the underlying storage of the union, regardless of the active
// member.
return bit_cast<uintptr_t>(Storage);
}
protected:
void *getImpl() const {
return reinterpret_cast<void *>(Value & HelperT::PointerMask);
void *getVoidPtr() const {
return reinterpret_cast<void *>(getOpaqueValue() & HelperT::PointerMask);
}
};
@ -151,8 +238,9 @@ struct PointerSumTypeHelper : MemberTs... {
enum { NumTagBits = Min<MemberTs::TraitsT::NumLowBitsAvailable...>::value };
// Also compute the smallest discriminant and various masks for convenience.
constexpr static TagT MinTag =
static_cast<TagT>(Min<MemberTs::Tag...>::value);
enum : uint64_t {
MinTag = Min<MemberTs::Tag...>::value,
PointerMask = static_cast<uint64_t>(-1) << NumTagBits,
TagMask = ~PointerMask
};

View file

@ -296,12 +296,15 @@ class ReversePostOrderTraversal {
public:
using rpo_iterator = typename std::vector<NodeRef>::reverse_iterator;
using const_rpo_iterator = typename std::vector<NodeRef>::const_reverse_iterator;
ReversePostOrderTraversal(GraphT G) { Initialize(GT::getEntryNode(G)); }
// Because we want a reverse post order, use reverse iterators from the vector
rpo_iterator begin() { return Blocks.rbegin(); }
const_rpo_iterator begin() const { return Blocks.crbegin(); }
rpo_iterator end() { return Blocks.rend(); }
const_rpo_iterator end() const { return Blocks.crend(); }
};
} // end namespace llvm

View file

@ -21,6 +21,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Config/abi-breaking.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
#include <cassert>
@ -70,6 +71,16 @@ template <typename B1, typename... Bn>
struct conjunction<B1, Bn...>
: std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
template <typename T> struct make_const_ptr {
using type =
typename std::add_pointer<typename std::add_const<T>::type>::type;
};
template <typename T> struct make_const_ref {
using type = typename std::add_lvalue_reference<
typename std::add_const<T>::type>::type;
};
//===----------------------------------------------------------------------===//
// Extra additions to <functional>
//===----------------------------------------------------------------------===//
@ -194,6 +205,12 @@ void adl_swap(T &&lhs, T &&rhs) noexcept(
adl_detail::adl_swap(std::forward<T>(lhs), std::forward<T>(rhs));
}
/// Test whether \p RangeOrContainer is empty. Similar to C++17 std::empty.
template <typename T>
constexpr bool empty(const T &RangeOrContainer) {
return adl_begin(RangeOrContainer) == adl_end(RangeOrContainer);
}
// mapped_iterator - This is a simple iterator adapter that causes a function to
// be applied whenever operator* is invoked on the iterator.
@ -418,9 +435,94 @@ make_filter_range(RangeT &&Range, PredicateT Pred) {
std::end(std::forward<RangeT>(Range)), Pred));
}
// forward declarations required by zip_shortest/zip_first
/// A pseudo-iterator adaptor that is designed to implement "early increment"
/// style loops.
///
/// This is *not a normal iterator* and should almost never be used directly. It
/// is intended primarily to be used with range based for loops and some range
/// algorithms.
///
/// The iterator isn't quite an `OutputIterator` or an `InputIterator` but
/// somewhere between them. The constraints of these iterators are:
///
/// - On construction or after being incremented, it is comparable and
/// dereferencable. It is *not* incrementable.
/// - After being dereferenced, it is neither comparable nor dereferencable, it
/// is only incrementable.
///
/// This means you can only dereference the iterator once, and you can only
/// increment it once between dereferences.
template <typename WrappedIteratorT>
class early_inc_iterator_impl
: public iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>,
WrappedIteratorT, std::input_iterator_tag> {
using BaseT =
iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>,
WrappedIteratorT, std::input_iterator_tag>;
using PointerT = typename std::iterator_traits<WrappedIteratorT>::pointer;
protected:
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
bool IsEarlyIncremented = false;
#endif
public:
early_inc_iterator_impl(WrappedIteratorT I) : BaseT(I) {}
using BaseT::operator*;
typename BaseT::reference operator*() {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
assert(!IsEarlyIncremented && "Cannot dereference twice!");
IsEarlyIncremented = true;
#endif
return *(this->I)++;
}
using BaseT::operator++;
early_inc_iterator_impl &operator++() {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
assert(IsEarlyIncremented && "Cannot increment before dereferencing!");
IsEarlyIncremented = false;
#endif
return *this;
}
using BaseT::operator==;
bool operator==(const early_inc_iterator_impl &RHS) const {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
assert(!IsEarlyIncremented && "Cannot compare after dereferencing!");
#endif
return BaseT::operator==(RHS);
}
};
/// Make a range that does early increment to allow mutation of the underlying
/// range without disrupting iteration.
///
/// The underlying iterator will be incremented immediately after it is
/// dereferenced, allowing deletion of the current node or insertion of nodes to
/// not disrupt iteration provided they do not invalidate the *next* iterator --
/// the current iterator can be invalidated.
///
/// This requires a very exact pattern of use that is only really suitable to
/// range based for loops and other range algorithms that explicitly guarantee
/// to dereference exactly once each element, and to increment exactly once each
/// element.
template <typename RangeT>
iterator_range<early_inc_iterator_impl<detail::IterOfRange<RangeT>>>
make_early_inc_range(RangeT &&Range) {
using EarlyIncIteratorT =
early_inc_iterator_impl<detail::IterOfRange<RangeT>>;
return make_range(EarlyIncIteratorT(std::begin(std::forward<RangeT>(Range))),
EarlyIncIteratorT(std::end(std::forward<RangeT>(Range))));
}
// forward declarations required by zip_shortest/zip_first/zip_longest
template <typename R, typename UnaryPredicate>
bool all_of(R &&range, UnaryPredicate P);
template <typename R, typename UnaryPredicate>
bool any_of(R &&range, UnaryPredicate P);
template <size_t... I> struct index_sequence;
@ -571,6 +673,132 @@ detail::zippy<detail::zip_first, T, U, Args...> zip_first(T &&t, U &&u,
std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
}
namespace detail {
template <typename Iter>
static Iter next_or_end(const Iter &I, const Iter &End) {
if (I == End)
return End;
return std::next(I);
}
template <typename Iter>
static auto deref_or_none(const Iter &I, const Iter &End)
-> llvm::Optional<typename std::remove_const<
typename std::remove_reference<decltype(*I)>::type>::type> {
if (I == End)
return None;
return *I;
}
template <typename Iter> struct ZipLongestItemType {
using type =
llvm::Optional<typename std::remove_const<typename std::remove_reference<
decltype(*std::declval<Iter>())>::type>::type>;
};
template <typename... Iters> struct ZipLongestTupleType {
using type = std::tuple<typename ZipLongestItemType<Iters>::type...>;
};
template <typename... Iters>
class zip_longest_iterator
: public iterator_facade_base<
zip_longest_iterator<Iters...>,
typename std::common_type<
std::forward_iterator_tag,
typename std::iterator_traits<Iters>::iterator_category...>::type,
typename ZipLongestTupleType<Iters...>::type,
typename std::iterator_traits<typename std::tuple_element<
0, std::tuple<Iters...>>::type>::difference_type,
typename ZipLongestTupleType<Iters...>::type *,
typename ZipLongestTupleType<Iters...>::type> {
public:
using value_type = typename ZipLongestTupleType<Iters...>::type;
private:
std::tuple<Iters...> iterators;
std::tuple<Iters...> end_iterators;
template <size_t... Ns>
bool test(const zip_longest_iterator<Iters...> &other,
index_sequence<Ns...>) const {
return llvm::any_of(
std::initializer_list<bool>{std::get<Ns>(this->iterators) !=
std::get<Ns>(other.iterators)...},
identity<bool>{});
}
template <size_t... Ns> value_type deref(index_sequence<Ns...>) const {
return value_type(
deref_or_none(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
}
template <size_t... Ns>
decltype(iterators) tup_inc(index_sequence<Ns...>) const {
return std::tuple<Iters...>(
next_or_end(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
}
public:
zip_longest_iterator(std::pair<Iters &&, Iters &&>... ts)
: iterators(std::forward<Iters>(ts.first)...),
end_iterators(std::forward<Iters>(ts.second)...) {}
value_type operator*() { return deref(index_sequence_for<Iters...>{}); }
value_type operator*() const { return deref(index_sequence_for<Iters...>{}); }
zip_longest_iterator<Iters...> &operator++() {
iterators = tup_inc(index_sequence_for<Iters...>{});
return *this;
}
bool operator==(const zip_longest_iterator<Iters...> &other) const {
return !test(other, index_sequence_for<Iters...>{});
}
};
template <typename... Args> class zip_longest_range {
public:
using iterator =
zip_longest_iterator<decltype(adl_begin(std::declval<Args>()))...>;
using iterator_category = typename iterator::iterator_category;
using value_type = typename iterator::value_type;
using difference_type = typename iterator::difference_type;
using pointer = typename iterator::pointer;
using reference = typename iterator::reference;
private:
std::tuple<Args...> ts;
template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) const {
return iterator(std::make_pair(adl_begin(std::get<Ns>(ts)),
adl_end(std::get<Ns>(ts)))...);
}
template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) const {
return iterator(std::make_pair(adl_end(std::get<Ns>(ts)),
adl_end(std::get<Ns>(ts)))...);
}
public:
zip_longest_range(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {}
iterator begin() const { return begin_impl(index_sequence_for<Args...>{}); }
iterator end() const { return end_impl(index_sequence_for<Args...>{}); }
};
} // namespace detail
/// Iterate over two or more iterators at the same time. Iteration continues
/// until all iterators reach the end. The llvm::Optional only contains a value
/// if the iterator has not reached the end.
template <typename T, typename U, typename... Args>
detail::zip_longest_range<T, U, Args...> zip_longest(T &&t, U &&u,
Args &&... args) {
return detail::zip_longest_range<T, U, Args...>(
std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
}
/// Iterator wrapper that concatenates sequences together.
///
/// This can concatenate different iterators, even with different types, into
@ -593,18 +821,20 @@ class concat_iterator
/// Note that something like iterator_range seems nice at first here, but the
/// range properties are of little benefit and end up getting in the way
/// because we need to do mutation on the current iterators.
std::tuple<std::pair<IterTs, IterTs>...> IterPairs;
std::tuple<IterTs...> Begins;
std::tuple<IterTs...> Ends;
/// Attempts to increment a specific iterator.
///
/// Returns true if it was able to increment the iterator. Returns false if
/// the iterator is already at the end iterator.
template <size_t Index> bool incrementHelper() {
auto &IterPair = std::get<Index>(IterPairs);
if (IterPair.first == IterPair.second)
auto &Begin = std::get<Index>(Begins);
auto &End = std::get<Index>(Ends);
if (Begin == End)
return false;
++IterPair.first;
++Begin;
return true;
}
@ -628,11 +858,12 @@ class concat_iterator
/// dereferences the iterator and returns the address of the resulting
/// reference.
template <size_t Index> ValueT *getHelper() const {
auto &IterPair = std::get<Index>(IterPairs);
if (IterPair.first == IterPair.second)
auto &Begin = std::get<Index>(Begins);
auto &End = std::get<Index>(Ends);
if (Begin == End)
return nullptr;
return &*IterPair.first;
return &*Begin;
}
/// Finds the first non-end iterator, dereferences, and returns the resulting
@ -659,7 +890,7 @@ public:
/// iterators.
template <typename... RangeTs>
explicit concat_iterator(RangeTs &&... Ranges)
: IterPairs({std::begin(Ranges), std::end(Ranges)}...) {}
: Begins(std::begin(Ranges)...), Ends(std::end(Ranges)...) {}
using BaseT::operator++;
@ -671,7 +902,7 @@ public:
ValueT &operator*() const { return get(index_sequence_for<IterTs...>()); }
bool operator==(const concat_iterator &RHS) const {
return IterPairs == RHS.IterPairs;
return Begins == RHS.Begins && Ends == RHS.Ends;
}
};
@ -740,6 +971,19 @@ struct less_second {
}
};
/// \brief Function object to apply a binary function to the first component of
/// a std::pair.
template<typename FuncTy>
struct on_first {
FuncTy func;
template <typename T>
auto operator()(const T &lhs, const T &rhs) const
-> decltype(func(lhs.first, rhs.first)) {
return func(lhs.first, rhs.first);
}
};
// A subset of N3658. More stuff can be added as-needed.
/// Represents a compile-time sequence of integers.
@ -877,6 +1121,10 @@ inline void sort(IteratorTy Start, IteratorTy End) {
std::sort(Start, End);
}
template <typename Container> inline void sort(Container &&C) {
llvm::sort(adl_begin(C), adl_end(C));
}
template <typename IteratorTy, typename Compare>
inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) {
#ifdef EXPENSIVE_CHECKS
@ -886,6 +1134,11 @@ inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) {
std::sort(Start, End, Comp);
}
template <typename Container, typename Compare>
inline void sort(Container &&C, Compare Comp) {
llvm::sort(adl_begin(C), adl_end(C), Comp);
}
//===----------------------------------------------------------------------===//
// Extra additions to <algorithm>
//===----------------------------------------------------------------------===//
@ -908,6 +1161,18 @@ void DeleteContainerSeconds(Container &C) {
C.clear();
}
/// Get the size of a range. This is a wrapper function around std::distance
/// which is only enabled when the operation is O(1).
template <typename R>
auto size(R &&Range, typename std::enable_if<
std::is_same<typename std::iterator_traits<decltype(
Range.begin())>::iterator_category,
std::random_access_iterator_tag>::value,
void>::type * = nullptr)
-> decltype(std::distance(Range.begin(), Range.end())) {
return std::distance(Range.begin(), Range.end());
}
/// Provide wrappers to std::for_each which take ranges instead of having to
/// pass begin/end explicitly.
template <typename R, typename UnaryPredicate>
@ -1018,6 +1283,33 @@ auto lower_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range)) {
return std::lower_bound(adl_begin(Range), adl_end(Range), I);
}
template <typename R, typename ForwardIt, typename Compare>
auto lower_bound(R &&Range, ForwardIt I, Compare C)
-> decltype(adl_begin(Range)) {
return std::lower_bound(adl_begin(Range), adl_end(Range), I, C);
}
/// Provide wrappers to std::upper_bound which take ranges instead of having to
/// pass begin/end explicitly.
template <typename R, typename ForwardIt>
auto upper_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range)) {
return std::upper_bound(adl_begin(Range), adl_end(Range), I);
}
template <typename R, typename ForwardIt, typename Compare>
auto upper_bound(R &&Range, ForwardIt I, Compare C)
-> decltype(adl_begin(Range)) {
return std::upper_bound(adl_begin(Range), adl_end(Range), I, C);
}
/// Wrapper function around std::equal to detect if all elements
/// in a container are same.
template <typename R>
bool is_splat(R &&Range) {
size_t range_size = size(Range);
return range_size != 0 && (range_size == 1 ||
std::equal(adl_begin(Range) + 1, adl_end(Range), adl_begin(Range)));
}
/// Given a range of type R, iterate the entire range and return a
/// SmallVector with elements of the vector. This is useful, for example,
/// when you want to iterate a range and then sort the results.
@ -1039,18 +1331,6 @@ void erase_if(Container &C, UnaryPredicate P) {
C.erase(remove_if(C, P), C.end());
}
/// Get the size of a range. This is a wrapper function around std::distance
/// which is only enabled when the operation is O(1).
template <typename R>
auto size(R &&Range, typename std::enable_if<
std::is_same<typename std::iterator_traits<decltype(
Range.begin())>::iterator_category,
std::random_access_iterator_tag>::value,
void>::type * = nullptr)
-> decltype(std::distance(Range.begin(), Range.end())) {
return std::distance(Range.begin(), Range.end());
}
//===----------------------------------------------------------------------===//
// Extra additions to <memory>
//===----------------------------------------------------------------------===//
@ -1263,6 +1543,40 @@ auto apply_tuple(F &&f, Tuple &&t) -> decltype(detail::apply_tuple_impl(
Indices{});
}
/// Return true if the sequence [Begin, End) has exactly N items. Runs in O(N)
/// time. Not meant for use with random-access iterators.
template <typename IterTy>
bool hasNItems(
IterTy &&Begin, IterTy &&End, unsigned N,
typename std::enable_if<
!std::is_same<
typename std::iterator_traits<typename std::remove_reference<
decltype(Begin)>::type>::iterator_category,
std::random_access_iterator_tag>::value,
void>::type * = nullptr) {
for (; N; --N, ++Begin)
if (Begin == End)
return false; // Too few.
return Begin == End;
}
/// Return true if the sequence [Begin, End) has N or more items. Runs in O(N)
/// time. Not meant for use with random-access iterators.
template <typename IterTy>
bool hasNItemsOrMore(
IterTy &&Begin, IterTy &&End, unsigned N,
typename std::enable_if<
!std::is_same<
typename std::iterator_traits<typename std::remove_reference<
decltype(Begin)>::type>::iterator_category,
std::random_access_iterator_tag>::value,
void>::type * = nullptr) {
for (; N; --N, ++Begin)
if (Begin == End)
return false; // Too few.
return true;
}
} // end namespace llvm
#endif // LLVM_ADT_STLEXTRAS_H

View file

@ -92,10 +92,6 @@ public:
};
private:
bool isSmall() const {
return X & uintptr_t(1);
}
BitVector *getPointer() const {
assert(!isSmall());
return reinterpret_cast<BitVector *>(X);
@ -186,6 +182,8 @@ public:
return make_range(set_bits_begin(), set_bits_end());
}
bool isSmall() const { return X & uintptr_t(1); }
/// Tests whether there are no bits in this bitvector.
bool empty() const {
return isSmall() ? getSmallSize() == 0 : getPointer()->empty();
@ -242,7 +240,7 @@ public:
uintptr_t Bits = getSmallBits();
if (Bits == 0)
return -1;
return NumBaseBits - countLeadingZeros(Bits);
return NumBaseBits - countLeadingZeros(Bits) - 1;
}
return getPointer()->find_last();
}
@ -265,7 +263,9 @@ public:
return -1;
uintptr_t Bits = getSmallBits();
return NumBaseBits - countLeadingOnes(Bits);
// Set unused bits.
Bits |= ~uintptr_t(0) << getSmallSize();
return NumBaseBits - countLeadingOnes(Bits) - 1;
}
return getPointer()->find_last_unset();
}
@ -465,6 +465,11 @@ public:
return (*this)[Idx];
}
// Push single bit to end of vector.
void push_back(bool Val) {
resize(size() + 1, Val);
}
/// Test if any common bits are set.
bool anyCommon(const SmallBitVector &RHS) const {
if (isSmall() && RHS.isSmall())
@ -482,10 +487,17 @@ public:
bool operator==(const SmallBitVector &RHS) const {
if (size() != RHS.size())
return false;
if (isSmall())
if (isSmall() && RHS.isSmall())
return getSmallBits() == RHS.getSmallBits();
else
else if (!isSmall() && !RHS.isSmall())
return *getPointer() == *RHS.getPointer();
else {
for (size_t i = 0, e = size(); i != e; ++i) {
if ((*this)[i] != RHS[i])
return false;
}
return true;
}
}
bool operator!=(const SmallBitVector &RHS) const {
@ -493,16 +505,19 @@ public:
}
// Intersection, union, disjoint union.
// FIXME BitVector::operator&= does not resize the LHS but this does
SmallBitVector &operator&=(const SmallBitVector &RHS) {
resize(std::max(size(), RHS.size()));
if (isSmall())
if (isSmall() && RHS.isSmall())
setSmallBits(getSmallBits() & RHS.getSmallBits());
else if (!RHS.isSmall())
else if (!isSmall() && !RHS.isSmall())
getPointer()->operator&=(*RHS.getPointer());
else {
SmallBitVector Copy = RHS;
Copy.resize(size());
getPointer()->operator&=(*Copy.getPointer());
size_t i, e;
for (i = 0, e = std::min(size(), RHS.size()); i != e; ++i)
(*this)[i] = test(i) && RHS.test(i);
for (e = size(); i != e; ++i)
reset(i);
}
return *this;
}
@ -542,28 +557,26 @@ public:
SmallBitVector &operator|=(const SmallBitVector &RHS) {
resize(std::max(size(), RHS.size()));
if (isSmall())
if (isSmall() && RHS.isSmall())
setSmallBits(getSmallBits() | RHS.getSmallBits());
else if (!RHS.isSmall())
else if (!isSmall() && !RHS.isSmall())
getPointer()->operator|=(*RHS.getPointer());
else {
SmallBitVector Copy = RHS;
Copy.resize(size());
getPointer()->operator|=(*Copy.getPointer());
for (size_t i = 0, e = RHS.size(); i != e; ++i)
(*this)[i] = test(i) || RHS.test(i);
}
return *this;
}
SmallBitVector &operator^=(const SmallBitVector &RHS) {
resize(std::max(size(), RHS.size()));
if (isSmall())
if (isSmall() && RHS.isSmall())
setSmallBits(getSmallBits() ^ RHS.getSmallBits());
else if (!RHS.isSmall())
else if (!isSmall() && !RHS.isSmall())
getPointer()->operator^=(*RHS.getPointer());
else {
SmallBitVector Copy = RHS;
Copy.resize(size());
getPointer()->operator^=(*Copy.getPointer());
for (size_t i = 0, e = RHS.size(); i != e; ++i)
(*this)[i] = test(i) != RHS.test(i);
}
return *this;
}

View file

@ -182,7 +182,7 @@ public:
/// SmallVectorTemplateBase<isPodLike = false> - This is where we put method
/// implementations that are designed to work with non-POD-like T's.
template <typename T, bool isPodLike>
template <typename T, bool = isPodLike<T>::value>
class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
protected:
SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
@ -299,7 +299,7 @@ protected:
// use memcpy here. Note that I and E are iterators and thus might be
// invalid for memcpy if they are equal.
if (I != E)
memcpy(Dest, I, (E - I) * sizeof(T));
memcpy(reinterpret_cast<void *>(Dest), I, (E - I) * sizeof(T));
}
/// Double the size of the allocated memory, guaranteeing space for at
@ -310,7 +310,7 @@ public:
void push_back(const T &Elt) {
if (LLVM_UNLIKELY(this->size() >= this->capacity()))
this->grow();
memcpy(this->end(), &Elt, sizeof(T));
memcpy(reinterpret_cast<void *>(this->end()), &Elt, sizeof(T));
this->set_size(this->size() + 1);
}
@ -320,8 +320,8 @@ public:
/// This class consists of common code factored out of the SmallVector class to
/// reduce code duplication based on the SmallVector 'N' template parameter.
template <typename T>
class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
using SuperClass = SmallVectorTemplateBase<T, isPodLike<T>::value>;
class SmallVectorImpl : public SmallVectorTemplateBase<T> {
using SuperClass = SmallVectorTemplateBase<T>;
public:
using iterator = typename SuperClass::iterator;

View file

@ -261,21 +261,33 @@ class SparseBitVector {
BITWORD_SIZE = SparseBitVectorElement<ElementSize>::BITWORD_SIZE
};
// Pointer to our current Element.
ElementListIter CurrElementIter;
ElementList Elements;
// Pointer to our current Element. This has no visible effect on the external
// state of a SparseBitVector, it's just used to improve performance in the
// common case of testing/modifying bits with similar indices.
mutable ElementListIter CurrElementIter;
// This is like std::lower_bound, except we do linear searching from the
// current position.
ElementListIter FindLowerBound(unsigned ElementIndex) {
ElementListIter FindLowerBoundImpl(unsigned ElementIndex) const {
// We cache a non-const iterator so we're forced to resort to const_cast to
// get the begin/end in the case where 'this' is const. To avoid duplication
// of code with the only difference being whether the const cast is present
// 'this' is always const in this particular function and we sort out the
// difference in FindLowerBound and FindLowerBoundConst.
ElementListIter Begin =
const_cast<SparseBitVector<ElementSize> *>(this)->Elements.begin();
ElementListIter End =
const_cast<SparseBitVector<ElementSize> *>(this)->Elements.end();
if (Elements.empty()) {
CurrElementIter = Elements.begin();
return Elements.begin();
CurrElementIter = Begin;
return CurrElementIter;
}
// Make sure our current iterator is valid.
if (CurrElementIter == Elements.end())
if (CurrElementIter == End)
--CurrElementIter;
// Search from our current iterator, either backwards or forwards,
@ -284,17 +296,23 @@ class SparseBitVector {
if (CurrElementIter->index() == ElementIndex) {
return ElementIter;
} else if (CurrElementIter->index() > ElementIndex) {
while (ElementIter != Elements.begin()
while (ElementIter != Begin
&& ElementIter->index() > ElementIndex)
--ElementIter;
} else {
while (ElementIter != Elements.end() &&
while (ElementIter != End &&
ElementIter->index() < ElementIndex)
++ElementIter;
}
CurrElementIter = ElementIter;
return ElementIter;
}
ElementListConstIter FindLowerBoundConst(unsigned ElementIndex) const {
return FindLowerBoundImpl(ElementIndex);
}
ElementListIter FindLowerBound(unsigned ElementIndex) {
return FindLowerBoundImpl(ElementIndex);
}
// Iterator to walk set bits in the bitmap. This iterator is a lot uglier
// than it would be, in order to be efficient.
@ -423,22 +441,12 @@ class SparseBitVector {
public:
using iterator = SparseBitVectorIterator;
SparseBitVector() {
CurrElementIter = Elements.begin();
}
SparseBitVector() : Elements(), CurrElementIter(Elements.begin()) {}
// SparseBitVector copy ctor.
SparseBitVector(const SparseBitVector &RHS) {
ElementListConstIter ElementIter = RHS.Elements.begin();
while (ElementIter != RHS.Elements.end()) {
Elements.push_back(SparseBitVectorElement<ElementSize>(*ElementIter));
++ElementIter;
}
CurrElementIter = Elements.begin ();
}
~SparseBitVector() = default;
SparseBitVector(const SparseBitVector &RHS)
: Elements(RHS.Elements), CurrElementIter(Elements.begin()) {}
SparseBitVector(SparseBitVector &&RHS)
: Elements(std::move(RHS.Elements)), CurrElementIter(Elements.begin()) {}
// Clear.
void clear() {
@ -450,26 +458,23 @@ public:
if (this == &RHS)
return *this;
Elements.clear();
ElementListConstIter ElementIter = RHS.Elements.begin();
while (ElementIter != RHS.Elements.end()) {
Elements.push_back(SparseBitVectorElement<ElementSize>(*ElementIter));
++ElementIter;
}
CurrElementIter = Elements.begin ();
Elements = RHS.Elements;
CurrElementIter = Elements.begin();
return *this;
}
SparseBitVector &operator=(SparseBitVector &&RHS) {
Elements = std::move(RHS.Elements);
CurrElementIter = Elements.begin();
return *this;
}
// Test, Reset, and Set a bit in the bitmap.
bool test(unsigned Idx) {
bool test(unsigned Idx) const {
if (Elements.empty())
return false;
unsigned ElementIndex = Idx / ElementSize;
ElementListIter ElementIter = FindLowerBound(ElementIndex);
ElementListConstIter ElementIter = FindLowerBoundConst(ElementIndex);
// If we can't find an element that is supposed to contain this bit, there
// is nothing more to do.

View file

@ -139,22 +139,23 @@ inline std::string utohexstr(uint64_t X, bool LowerCase = false) {
/// Convert buffer \p Input to its hexadecimal representation.
/// The returned string is double the size of \p Input.
inline std::string toHex(StringRef Input) {
inline std::string toHex(StringRef Input, bool LowerCase = false) {
static const char *const LUT = "0123456789ABCDEF";
const uint8_t Offset = LowerCase ? 32 : 0;
size_t Length = Input.size();
std::string Output;
Output.reserve(2 * Length);
for (size_t i = 0; i < Length; ++i) {
const unsigned char c = Input[i];
Output.push_back(LUT[c >> 4]);
Output.push_back(LUT[c & 15]);
Output.push_back(LUT[c >> 4] | Offset);
Output.push_back(LUT[c & 15] | Offset);
}
return Output;
}
inline std::string toHex(ArrayRef<uint8_t> Input) {
return toHex(toStringRef(Input));
inline std::string toHex(ArrayRef<uint8_t> Input, bool LowerCase = false) {
return toHex(toStringRef(Input), LowerCase);
}
inline uint8_t hexFromNibbles(char MSB, char LSB) {

View file

@ -55,12 +55,11 @@ public:
bpfel, // eBPF or extended BPF or 64-bit BPF (little endian)
bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian)
hexagon, // Hexagon: hexagon
mips, // MIPS: mips, mipsallegrex
mipsel, // MIPSEL: mipsel, mipsallegrexel
mips64, // MIPS64: mips64
mips64el, // MIPS64EL: mips64el
mips, // MIPS: mips, mipsallegrex, mipsr6
mipsel, // MIPSEL: mipsel, mipsallegrexe, mipsr6el
mips64, // MIPS64: mips64, mips64r6, mipsn32, mipsn32r6
mips64el, // MIPS64EL: mips64el, mips64r6el, mipsn32el, mipsn32r6el
msp430, // MSP430: msp430
nios2, // NIOSII: nios2
ppc, // PPC: powerpc
ppc64, // PPC64: powerpc64, ppu
ppc64le, // PPC64LE: powerpc64le
@ -101,6 +100,7 @@ public:
enum SubArchType {
NoSubArch,
ARMSubArch_v8_5a,
ARMSubArch_v8_4a,
ARMSubArch_v8_3a,
ARMSubArch_v8_2a,
@ -125,7 +125,9 @@ public:
KalimbaSubArch_v3,
KalimbaSubArch_v4,
KalimbaSubArch_v5
KalimbaSubArch_v5,
MipsSubArch_r6
};
enum VendorType {
UnknownVendor,
@ -182,7 +184,10 @@ public:
Mesa3D,
Contiki,
AMDPAL, // AMD PAL Runtime
LastOSType = AMDPAL
HermitCore, // HermitCore Unikernel/Multikernel
Hurd, // GNU/Hurd
WASI, // Experimental WebAssembly OS
LastOSType = WASI
};
enum EnvironmentType {
UnknownEnvironment,
@ -578,9 +583,20 @@ public:
return getOS() == Triple::KFreeBSD;
}
/// Tests whether the OS is Hurd.
bool isOSHurd() const {
return getOS() == Triple::Hurd;
}
/// Tests whether the OS is WASI.
bool isOSWASI() const {
return getOS() == Triple::WASI;
}
/// Tests whether the OS uses glibc.
bool isOSGlibc() const {
return (getOS() == Triple::Linux || getOS() == Triple::KFreeBSD) &&
return (getOS() == Triple::Linux || getOS() == Triple::KFreeBSD ||
getOS() == Triple::Hurd) &&
!isAndroid();
}

View file

@ -0,0 +1,59 @@
//===-- llvm/ADT/bit.h - C++20 <bit> ----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the C++20 <bit> header.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_BIT_H
#define LLVM_ADT_BIT_H
#include "llvm/Support/Compiler.h"
#include <cstring>
#include <type_traits>
namespace llvm {
// This implementation of bit_cast is different from the C++17 one in two ways:
// - It isn't constexpr because that requires compiler support.
// - It requires trivially-constructible To, to avoid UB in the implementation.
template <typename To, typename From
, typename = typename std::enable_if<sizeof(To) == sizeof(From)>::type
#if (__has_feature(is_trivially_constructible) && defined(_LIBCPP_VERSION)) || \
(defined(__GNUC__) && __GNUC__ >= 5)
, typename = typename std::is_trivially_constructible<To>::type
#elif __has_feature(is_trivially_constructible)
, typename = typename std::enable_if<__is_trivially_constructible(To)>::type
#else
// See comment below.
#endif
#if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) || \
(defined(__GNUC__) && __GNUC__ >= 5)
, typename = typename std::enable_if<std::is_trivially_copyable<To>::value>::type
, typename = typename std::enable_if<std::is_trivially_copyable<From>::value>::type
#elif __has_feature(is_trivially_copyable)
, typename = typename std::enable_if<__is_trivially_copyable(To)>::type
, typename = typename std::enable_if<__is_trivially_copyable(From)>::type
#else
// This case is GCC 4.x. clang with libc++ or libstdc++ never get here. Unlike
// llvm/Support/type_traits.h's isPodLike we don't want to provide a
// good-enough answer here: developers in that configuration will hit
// compilation failures on the bots instead of locally. That's acceptable
// because it's very few developers, and only until we move past C++11.
#endif
>
inline To bit_cast(const From &from) noexcept {
To to;
std::memcpy(&to, &from, sizeof(To));
return to;
}
} // namespace llvm
#endif

View file

@ -202,9 +202,7 @@ template <
typename ReferenceT = typename std::conditional<
std::is_same<T, typename std::iterator_traits<
WrappedIteratorT>::value_type>::value,
typename std::iterator_traits<WrappedIteratorT>::reference, T &>::type,
// Don't provide these, they are mostly to act as aliases below.
typename WrappedTraitsT = std::iterator_traits<WrappedIteratorT>>
typename std::iterator_traits<WrappedIteratorT>::reference, T &>::type>
class iterator_adaptor_base
: public iterator_facade_base<DerivedT, IteratorCategoryT, T,
DifferenceTypeT, PointerT, ReferenceT> {
@ -311,8 +309,10 @@ make_pointee_range(RangeT &&Range) {
template <typename WrappedIteratorT,
typename T = decltype(&*std::declval<WrappedIteratorT>())>
class pointer_iterator
: public iterator_adaptor_base<pointer_iterator<WrappedIteratorT, T>,
WrappedIteratorT, T> {
: public iterator_adaptor_base<
pointer_iterator<WrappedIteratorT, T>, WrappedIteratorT,
typename std::iterator_traits<WrappedIteratorT>::iterator_category,
T> {
mutable T Ptr;
public:
@ -334,6 +334,34 @@ make_pointer_range(RangeT &&Range) {
PointerIteratorT(std::end(std::forward<RangeT>(Range))));
}
// Wrapper iterator over iterator ItType, adding DataRef to the type of ItType,
// to create NodeRef = std::pair<InnerTypeOfItType, DataRef>.
template <typename ItType, typename NodeRef, typename DataRef>
class WrappedPairNodeDataIterator
: public iterator_adaptor_base<
WrappedPairNodeDataIterator<ItType, NodeRef, DataRef>, ItType,
typename std::iterator_traits<ItType>::iterator_category, NodeRef,
std::ptrdiff_t, NodeRef *, NodeRef &> {
using BaseT = iterator_adaptor_base<
WrappedPairNodeDataIterator, ItType,
typename std::iterator_traits<ItType>::iterator_category, NodeRef,
std::ptrdiff_t, NodeRef *, NodeRef &>;
const DataRef DR;
mutable NodeRef NR;
public:
WrappedPairNodeDataIterator(ItType Begin, const DataRef DR)
: BaseT(Begin), DR(DR) {
NR.first = DR;
}
NodeRef &operator*() const {
NR.second = *this->I;
return NR;
}
};
} // end namespace llvm
#endif // LLVM_ADT_ITERATOR_H

View file

@ -43,7 +43,6 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
@ -335,8 +334,7 @@ public:
/// A convenience wrapper around the primary \c alias interface.
AliasResult alias(const Value *V1, const Value *V2) {
return alias(V1, MemoryLocation::UnknownSize, V2,
MemoryLocation::UnknownSize);
return alias(V1, LocationSize::unknown(), V2, LocationSize::unknown());
}
/// A trivial helper function to check to see if the specified pointers are
@ -364,7 +362,8 @@ public:
/// A convenience wrapper around the \c isMustAlias helper interface.
bool isMustAlias(const Value *V1, const Value *V2) {
return alias(V1, 1, V2, 1) == MustAlias;
return alias(V1, LocationSize::precise(1), V2, LocationSize::precise(1)) ==
MustAlias;
}
/// Checks whether the given location points to constant memory, or if
@ -382,15 +381,15 @@ public:
/// \name Simple mod/ref information
/// @{
/// Get the ModRef info associated with a pointer argument of a callsite. The
/// Get the ModRef info associated with a pointer argument of a call. The
/// result's bits are set to indicate the allowed aliasing ModRef kinds. Note
/// that these bits do not necessarily account for the overall behavior of
/// the function, but rather only provide additional per-argument
/// information. This never sets ModRefInfo::Must.
ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx);
ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx);
/// Return the behavior of the given call site.
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS);
FunctionModRefBehavior getModRefBehavior(const CallBase *Call);
/// Return the behavior when calling the given function.
FunctionModRefBehavior getModRefBehavior(const Function *F);
@ -406,8 +405,8 @@ public:
/// property (e.g. calls to 'sin' and 'cos').
///
/// This property corresponds to the GCC 'const' attribute.
bool doesNotAccessMemory(ImmutableCallSite CS) {
return getModRefBehavior(CS) == FMRB_DoesNotAccessMemory;
bool doesNotAccessMemory(const CallBase *Call) {
return getModRefBehavior(Call) == FMRB_DoesNotAccessMemory;
}
/// Checks if the specified function is known to never read or write memory.
@ -434,8 +433,8 @@ public:
/// absence of interfering store instructions, such as CSE of strlen calls.
///
/// This property corresponds to the GCC 'pure' attribute.
bool onlyReadsMemory(ImmutableCallSite CS) {
return onlyReadsMemory(getModRefBehavior(CS));
bool onlyReadsMemory(const CallBase *Call) {
return onlyReadsMemory(getModRefBehavior(Call));
}
/// Checks if the specified function is known to only read from non-volatile
@ -500,36 +499,12 @@ public:
/// getModRefInfo (for call sites) - Return information about whether
/// a particular call site modifies or reads the specified memory location.
ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc);
ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc);
/// getModRefInfo (for call sites) - A convenience wrapper.
ModRefInfo getModRefInfo(ImmutableCallSite CS, const Value *P,
ModRefInfo getModRefInfo(const CallBase *Call, const Value *P,
LocationSize Size) {
return getModRefInfo(CS, MemoryLocation(P, Size));
}
/// getModRefInfo (for calls) - Return information about whether
/// a particular call modifies or reads the specified memory location.
ModRefInfo getModRefInfo(const CallInst *C, const MemoryLocation &Loc) {
return getModRefInfo(ImmutableCallSite(C), Loc);
}
/// getModRefInfo (for calls) - A convenience wrapper.
ModRefInfo getModRefInfo(const CallInst *C, const Value *P,
LocationSize Size) {
return getModRefInfo(C, MemoryLocation(P, Size));
}
/// getModRefInfo (for invokes) - Return information about whether
/// a particular invoke modifies or reads the specified memory location.
ModRefInfo getModRefInfo(const InvokeInst *I, const MemoryLocation &Loc) {
return getModRefInfo(ImmutableCallSite(I), Loc);
}
/// getModRefInfo (for invokes) - A convenience wrapper.
ModRefInfo getModRefInfo(const InvokeInst *I, const Value *P,
LocationSize Size) {
return getModRefInfo(I, MemoryLocation(P, Size));
return getModRefInfo(Call, MemoryLocation(P, Size));
}
/// getModRefInfo (for loads) - Return information about whether
@ -569,7 +544,7 @@ public:
/// getModRefInfo (for cmpxchges) - A convenience wrapper.
ModRefInfo getModRefInfo(const AtomicCmpXchgInst *CX, const Value *P,
unsigned Size) {
LocationSize Size) {
return getModRefInfo(CX, MemoryLocation(P, Size));
}
@ -579,7 +554,7 @@ public:
/// getModRefInfo (for atomicrmws) - A convenience wrapper.
ModRefInfo getModRefInfo(const AtomicRMWInst *RMW, const Value *P,
unsigned Size) {
LocationSize Size) {
return getModRefInfo(RMW, MemoryLocation(P, Size));
}
@ -626,8 +601,8 @@ public:
ModRefInfo getModRefInfo(const Instruction *I,
const Optional<MemoryLocation> &OptLoc) {
if (OptLoc == None) {
if (auto CS = ImmutableCallSite(I)) {
return createModRefInfo(getModRefBehavior(CS));
if (const auto *Call = dyn_cast<CallBase>(I)) {
return createModRefInfo(getModRefBehavior(Call));
}
}
@ -661,12 +636,12 @@ public:
/// Return information about whether a call and an instruction may refer to
/// the same memory locations.
ModRefInfo getModRefInfo(Instruction *I, ImmutableCallSite Call);
ModRefInfo getModRefInfo(Instruction *I, const CallBase *Call);
/// Return information about whether two call sites may refer to the same set
/// of memory locations. See the AA documentation for details:
/// http://llvm.org/docs/AliasAnalysis.html#ModRefInfo
ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2);
ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2);
/// Return information about whether a particular call site modifies
/// or reads the specified memory location \p MemLoc before instruction \p I
@ -777,25 +752,25 @@ public:
/// that these bits do not necessarily account for the overall behavior of
/// the function, but rather only provide additional per-argument
/// information.
virtual ModRefInfo getArgModRefInfo(ImmutableCallSite CS,
virtual ModRefInfo getArgModRefInfo(const CallBase *Call,
unsigned ArgIdx) = 0;
/// Return the behavior of the given call site.
virtual FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) = 0;
virtual FunctionModRefBehavior getModRefBehavior(const CallBase *Call) = 0;
/// Return the behavior when calling the given function.
virtual FunctionModRefBehavior getModRefBehavior(const Function *F) = 0;
/// getModRefInfo (for call sites) - Return information about whether
/// a particular call site modifies or reads the specified memory location.
virtual ModRefInfo getModRefInfo(ImmutableCallSite CS,
virtual ModRefInfo getModRefInfo(const CallBase *Call,
const MemoryLocation &Loc) = 0;
/// Return information about whether two call sites may refer to the same set
/// of memory locations. See the AA documentation for details:
/// http://llvm.org/docs/AliasAnalysis.html#ModRefInfo
virtual ModRefInfo getModRefInfo(ImmutableCallSite CS1,
ImmutableCallSite CS2) = 0;
virtual ModRefInfo getModRefInfo(const CallBase *Call1,
const CallBase *Call2) = 0;
/// @}
};
@ -827,26 +802,26 @@ public:
return Result.pointsToConstantMemory(Loc, OrLocal);
}
ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx) override {
return Result.getArgModRefInfo(CS, ArgIdx);
ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) override {
return Result.getArgModRefInfo(Call, ArgIdx);
}
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) override {
return Result.getModRefBehavior(CS);
FunctionModRefBehavior getModRefBehavior(const CallBase *Call) override {
return Result.getModRefBehavior(Call);
}
FunctionModRefBehavior getModRefBehavior(const Function *F) override {
return Result.getModRefBehavior(F);
}
ModRefInfo getModRefInfo(ImmutableCallSite CS,
ModRefInfo getModRefInfo(const CallBase *Call,
const MemoryLocation &Loc) override {
return Result.getModRefInfo(CS, Loc);
return Result.getModRefInfo(Call, Loc);
}
ModRefInfo getModRefInfo(ImmutableCallSite CS1,
ImmutableCallSite CS2) override {
return Result.getModRefInfo(CS1, CS2);
ModRefInfo getModRefInfo(const CallBase *Call1,
const CallBase *Call2) override {
return Result.getModRefInfo(Call1, Call2);
}
};
@ -901,25 +876,28 @@ protected:
: CurrentResult.pointsToConstantMemory(Loc, OrLocal);
}
ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx) {
return AAR ? AAR->getArgModRefInfo(CS, ArgIdx) : CurrentResult.getArgModRefInfo(CS, ArgIdx);
ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) {
return AAR ? AAR->getArgModRefInfo(Call, ArgIdx)
: CurrentResult.getArgModRefInfo(Call, ArgIdx);
}
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) {
return AAR ? AAR->getModRefBehavior(CS) : CurrentResult.getModRefBehavior(CS);
FunctionModRefBehavior getModRefBehavior(const CallBase *Call) {
return AAR ? AAR->getModRefBehavior(Call)
: CurrentResult.getModRefBehavior(Call);
}
FunctionModRefBehavior getModRefBehavior(const Function *F) {
return AAR ? AAR->getModRefBehavior(F) : CurrentResult.getModRefBehavior(F);
}
ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc) {
return AAR ? AAR->getModRefInfo(CS, Loc)
: CurrentResult.getModRefInfo(CS, Loc);
ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc) {
return AAR ? AAR->getModRefInfo(Call, Loc)
: CurrentResult.getModRefInfo(Call, Loc);
}
ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2) {
return AAR ? AAR->getModRefInfo(CS1, CS2) : CurrentResult.getModRefInfo(CS1, CS2);
ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2) {
return AAR ? AAR->getModRefInfo(Call1, Call2)
: CurrentResult.getModRefInfo(Call1, Call2);
}
};
@ -951,11 +929,11 @@ public:
return false;
}
ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx) {
ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) {
return ModRefInfo::ModRef;
}
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) {
FunctionModRefBehavior getModRefBehavior(const CallBase *Call) {
return FMRB_UnknownModRefBehavior;
}
@ -963,11 +941,11 @@ public:
return FMRB_UnknownModRefBehavior;
}
ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc) {
ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc) {
return ModRefInfo::ModRef;
}
ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2) {
ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2) {
return ModRefInfo::ModRef;
}
};
@ -1075,6 +1053,29 @@ public:
void getAnalysisUsage(AnalysisUsage &AU) const override;
};
/// A wrapper pass for external alias analyses. This just squirrels away the
/// callback used to run any analyses and register their results.
struct ExternalAAWrapperPass : ImmutablePass {
using CallbackT = std::function<void(Pass &, Function &, AAResults &)>;
CallbackT CB;
static char ID;
ExternalAAWrapperPass() : ImmutablePass(ID) {
initializeExternalAAWrapperPassPass(*PassRegistry::getPassRegistry());
}
explicit ExternalAAWrapperPass(CallbackT CB)
: ImmutablePass(ID), CB(std::move(CB)) {
initializeExternalAAWrapperPassPass(*PassRegistry::getPassRegistry());
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
};
FunctionPass *createAAResultsWrapperPass();
/// A wrapper pass around a callback which can be used to populate the

View file

@ -52,9 +52,13 @@ class AliasSet : public ilist_node<AliasSet> {
PointerRec **PrevInList = nullptr;
PointerRec *NextInList = nullptr;
AliasSet *AS = nullptr;
LocationSize Size = 0;
LocationSize Size = LocationSize::mapEmpty();
AAMDNodes AAInfo;
// Whether the size for this record has been set at all. This makes no
// guarantees about the size being known.
bool isSizeSet() const { return Size != LocationSize::mapEmpty(); }
public:
PointerRec(Value *V)
: Val(V), AAInfo(DenseMapInfo<AAMDNodes>::getEmptyKey()) {}
@ -71,9 +75,10 @@ class AliasSet : public ilist_node<AliasSet> {
bool updateSizeAndAAInfo(LocationSize NewSize, const AAMDNodes &NewAAInfo) {
bool SizeChanged = false;
if (NewSize > Size) {
Size = NewSize;
SizeChanged = true;
if (NewSize != Size) {
LocationSize OldSize = Size;
Size = isSizeSet() ? Size.unionWith(NewSize) : NewSize;
SizeChanged = OldSize != Size;
}
if (AAInfo == DenseMapInfo<AAMDNodes>::getEmptyKey())
@ -91,7 +96,10 @@ class AliasSet : public ilist_node<AliasSet> {
return SizeChanged;
}
LocationSize getSize() const { return Size; }
LocationSize getSize() const {
assert(isSizeSet() && "Getting an unset size!");
return Size;
}
/// Return the AAInfo, or null if there is no information or conflicting
/// information.
@ -175,9 +183,6 @@ class AliasSet : public ilist_node<AliasSet> {
};
unsigned Alias : 1;
/// True if this alias set contains volatile loads or stores.
unsigned Volatile : 1;
unsigned SetSize = 0;
void addRef() { ++RefCount; }
@ -203,9 +208,6 @@ public:
bool isMustAlias() const { return Alias == SetMustAlias; }
bool isMayAlias() const { return Alias == SetMayAlias; }
/// Return true if this alias set contains volatile loads or stores.
bool isVolatile() const { return Volatile; }
/// Return true if this alias set should be ignored as part of the
/// AliasSetTracker object.
bool isForwardingAliasSet() const { return Forward; }
@ -224,6 +226,10 @@ public:
// track of the list's exact size.
unsigned size() { return SetSize; }
/// If this alias set is known to contain a single instruction and *only* a
/// single unique instruction, return it. Otherwise, return nullptr.
Instruction* getUniqueInstruction();
void print(raw_ostream &OS) const;
void dump() const;
@ -264,7 +270,7 @@ private:
// Can only be created by AliasSetTracker.
AliasSet()
: PtrListEnd(&PtrList), RefCount(0), AliasAny(false), Access(NoAccess),
Alias(SetMustAlias), Volatile(false) {}
Alias(SetMustAlias) {}
PointerRec *getSomePointer() const {
return PtrList;
@ -303,8 +309,6 @@ private:
dropRef(AST);
}
void setVolatile() { Volatile = true; }
public:
/// Return true if the specified pointer "may" (or must) alias one of the
/// members in the set.
@ -379,23 +383,11 @@ public:
/// Return the alias sets that are active.
const ilist<AliasSet> &getAliasSets() const { return AliasSets; }
/// Return the alias set that the specified pointer lives in. If the New
/// argument is non-null, this method sets the value to true if a new alias
/// set is created to contain the pointer (because the pointer didn't alias
/// anything).
AliasSet &getAliasSetForPointer(Value *P, LocationSize Size,
const AAMDNodes &AAInfo);
/// Return the alias set containing the location specified if one exists,
/// otherwise return null.
AliasSet *getAliasSetForPointerIfExists(const Value *P, LocationSize Size,
const AAMDNodes &AAInfo) {
return mergeAliasSetsForPointer(P, Size, AAInfo);
}
/// Return true if the specified instruction "may" (or must) alias one of the
/// members in any of the sets.
bool containsUnknown(const Instruction *I) const;
/// Return the alias set which contains the specified memory location. If
/// the memory location aliases two or more existing alias sets, will have
/// the effect of merging those alias sets before the single resulting alias
/// set is returned.
AliasSet &getAliasSetFor(const MemoryLocation &MemLoc);
/// Return the underlying alias analysis object used by this tracker.
AliasAnalysis &getAliasAnalysis() const { return AA; }
@ -445,8 +437,7 @@ private:
return *Entry;
}
AliasSet &addPointer(Value *P, LocationSize Size, const AAMDNodes &AAInfo,
AliasSet::AccessLattice E);
AliasSet &addPointer(MemoryLocation Loc, AliasSet::AccessLattice E);
AliasSet *mergeAliasSetsForPointer(const Value *Ptr, LocationSize Size,
const AAMDNodes &AAInfo);

View file

@ -21,7 +21,7 @@
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
#include <algorithm>
@ -84,18 +84,18 @@ public:
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB);
ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc);
ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc);
ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2);
ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2);
/// Chases pointers until we find a (constant global) or not.
bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal);
/// Get the location associated with a pointer argument of a callsite.
ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx);
ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx);
/// Returns the behavior when calling the given call site.
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS);
FunctionModRefBehavior getModRefBehavior(const CallBase *Call);
/// Returns the behavior when calling the given function. For use when the
/// call site is not known.
@ -115,7 +115,7 @@ private:
unsigned ZExtBits;
unsigned SExtBits;
int64_t Scale;
APInt Scale;
bool operator==(const VariableGEPIndex &Other) const {
return V == Other.V && ZExtBits == Other.ZExtBits &&
@ -133,10 +133,10 @@ private:
// Base pointer of the GEP
const Value *Base;
// Total constant offset w.r.t the base from indexing into structs
int64_t StructOffset;
APInt StructOffset;
// Total constant offset w.r.t the base from indexing through
// pointers/arrays/vectors
int64_t OtherOffset;
APInt OtherOffset;
// Scaled variable (non-constant) indices.
SmallVector<VariableGEPIndex, 4> VarIndices;
};
@ -189,7 +189,7 @@ private:
bool
constantOffsetHeuristic(const SmallVectorImpl<VariableGEPIndex> &VarIndices,
LocationSize V1Size, LocationSize V2Size,
int64_t BaseOffset, AssumptionCache *AC,
APInt BaseOffset, AssumptionCache *AC,
DominatorTree *DT);
bool isValueEqualInPotentialCycles(const Value *V1, const Value *V2);

View file

@ -56,7 +56,7 @@ public:
const Function *getFunction() const;
const BranchProbabilityInfo *getBPI() const;
void view() const;
void view(StringRef = "BlockFrequencyDAGs") const;
/// getblockFreq - Return block frequency. Return 0 if we don't have the
/// information. Please note that initial frequency is equal to ENTRY_FREQ. It

View file

@ -25,7 +25,6 @@ class DominatorTree;
class Function;
class Instruction;
class LoopInfo;
class TerminatorInst;
/// Analyze the specified function to find all of the loop backedges in the
/// function and return them. This is a relatively cheap (compared to
@ -46,7 +45,7 @@ unsigned GetSuccessorNumber(const BasicBlock *BB, const BasicBlock *Succ);
/// edges from a block with multiple successors to a block with multiple
/// predecessors.
///
bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum,
bool isCriticalEdge(const Instruction *TI, unsigned SuccNum,
bool AllowIdenticalEdges = false);
/// Determine whether instruction 'To' is reachable from 'From',

View file

@ -150,7 +150,7 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
/// Display the raw branch weights from PGO.
std::string getEdgeAttributes(const BasicBlock *Node, succ_const_iterator I,
const Function *F) {
const TerminatorInst *TI = Node->getTerminator();
const Instruction *TI = Node->getTerminator();
if (TI->getNumSuccessors() == 1)
return "";
@ -172,8 +172,7 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
// Prepend a 'W' to indicate that this is a weight rather than the actual
// profile count (due to scaling).
Twine Attrs = "label=\"W:" + Twine(Weight->getZExtValue()) + "\"";
return Attrs.str();
return ("label=\"W:" + Twine(Weight->getZExtValue()) + "\"").str();
}
};
} // End llvm namespace

View file

@ -364,6 +364,10 @@ public:
InvalidSCCSet, nullptr, nullptr,
InlinedInternalEdges};
// Request PassInstrumentation from analysis manager, will use it to run
// instrumenting callbacks for the passes later.
PassInstrumentation PI = AM.getResult<PassInstrumentationAnalysis>(M);
PreservedAnalyses PA = PreservedAnalyses::all();
CG.buildRefSCCs();
for (auto RCI = CG.postorder_ref_scc_begin(),
@ -428,8 +432,20 @@ public:
UR.UpdatedRC = nullptr;
UR.UpdatedC = nullptr;
// Check the PassInstrumentation's BeforePass callbacks before
// running the pass, skip its execution completely if asked to
// (callback returns false).
if (!PI.runBeforePass<LazyCallGraph::SCC>(Pass, *C))
continue;
PreservedAnalyses PassPA = Pass.run(*C, CGAM, CG, UR);
if (UR.InvalidatedSCCs.count(C))
PI.runAfterPassInvalidated<LazyCallGraph::SCC>(Pass);
else
PI.runAfterPass<LazyCallGraph::SCC>(Pass, *C);
// Update the SCC and RefSCC if necessary.
C = UR.UpdatedC ? UR.UpdatedC : C;
RC = UR.UpdatedRC ? UR.UpdatedRC : RC;
@ -615,12 +631,20 @@ public:
if (CG.lookupSCC(*N) != CurrentC)
continue;
PreservedAnalyses PassPA = Pass.run(N->getFunction(), FAM);
Function &F = N->getFunction();
PassInstrumentation PI = FAM.getResult<PassInstrumentationAnalysis>(F);
if (!PI.runBeforePass<Function>(Pass, F))
continue;
PreservedAnalyses PassPA = Pass.run(F, FAM);
PI.runAfterPass<Function>(Pass, F);
// We know that the function pass couldn't have invalidated any other
// function's analyses (that's the contract of a function pass), so
// directly handle the function analysis manager's invalidation here.
FAM.invalidate(N->getFunction(), PassPA);
FAM.invalidate(F, PassPA);
// Then intersect the preserved set so that invalidation of module
// analyses will eventually occur when the module pass completes.
@ -690,6 +714,8 @@ public:
PreservedAnalyses run(LazyCallGraph::SCC &InitialC, CGSCCAnalysisManager &AM,
LazyCallGraph &CG, CGSCCUpdateResult &UR) {
PreservedAnalyses PA = PreservedAnalyses::all();
PassInstrumentation PI =
AM.getResult<PassInstrumentationAnalysis>(InitialC, CG);
// The SCC may be refined while we are running passes over it, so set up
// a pointer that we can update.
@ -733,8 +759,17 @@ public:
auto CallCounts = ScanSCC(*C, CallHandles);
for (int Iteration = 0;; ++Iteration) {
if (!PI.runBeforePass<LazyCallGraph::SCC>(Pass, *C))
continue;
PreservedAnalyses PassPA = Pass.run(*C, AM, CG, UR);
if (UR.InvalidatedSCCs.count(C))
PI.runAfterPassInvalidated<LazyCallGraph::SCC>(Pass);
else
PI.runAfterPass<LazyCallGraph::SCC>(Pass, *C);
// If the SCC structure has changed, bail immediately and let the outer
// CGSCC layer handle any iteration to reflect the refined structure.
if (UR.UpdatedC && UR.UpdatedC != C) {

View file

@ -22,6 +22,14 @@ namespace llvm {
class DominatorTree;
class OrderedBasicBlock;
/// The default value for MaxUsesToExplore argument. It's relatively small to
/// keep the cost of analysis reasonable for clients like BasicAliasAnalysis,
/// where the results can't be cached.
/// TODO: we should probably introduce a caching CaptureTracking analysis and
/// use it where possible. The caching version can use much higher limit or
/// don't have this cap at all.
unsigned constexpr DefaultMaxUsesToExplore = 20;
/// PointerMayBeCaptured - Return true if this pointer value may be captured
/// by the enclosing function (which is required to exist). This routine can
/// be expensive, so consider caching the results. The boolean ReturnCaptures
@ -29,9 +37,12 @@ namespace llvm {
/// counts as capturing it or not. The boolean StoreCaptures specified
/// whether storing the value (or part of it) into memory anywhere
/// automatically counts as capturing it or not.
/// MaxUsesToExplore specifies how many uses should the analysis explore for
/// one value before giving up due too "too many uses".
bool PointerMayBeCaptured(const Value *V,
bool ReturnCaptures,
bool StoreCaptures);
bool StoreCaptures,
unsigned MaxUsesToExplore = DefaultMaxUsesToExplore);
/// PointerMayBeCapturedBefore - Return true if this pointer value may be
/// captured by the enclosing function (which is required to exist). If a
@ -44,10 +55,13 @@ namespace llvm {
/// or not. Captures by the provided instruction are considered if the
/// final parameter is true. An ordered basic block in \p OBB could be used
/// to speed up capture-tracker queries.
/// MaxUsesToExplore specifies how many uses should the analysis explore for
/// one value before giving up due too "too many uses".
bool PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures,
bool StoreCaptures, const Instruction *I,
const DominatorTree *DT, bool IncludeI = false,
OrderedBasicBlock *OBB = nullptr);
OrderedBasicBlock *OBB = nullptr,
unsigned MaxUsesToExplore = DefaultMaxUsesToExplore);
/// This callback is used in conjunction with PointerMayBeCaptured. In
/// addition to the interface here, you'll need to provide your own getters
@ -75,7 +89,10 @@ namespace llvm {
/// PointerMayBeCaptured - Visit the value and the values derived from it and
/// find values which appear to be capturing the pointer value. This feeds
/// results into and is controlled by the CaptureTracker object.
void PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker);
/// MaxUsesToExplore specifies how many uses should the analysis explore for
/// one value before giving up due too "too many uses".
void PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker,
unsigned MaxUsesToExplore = DefaultMaxUsesToExplore);
} // end namespace llvm
#endif

View file

@ -46,19 +46,18 @@ namespace llvm {
///
unsigned getICmpCode(const ICmpInst *ICI, bool InvertPred = false);
/// This is the complement of getICmpCode, which turns an opcode and two
/// operands into either a constant true or false, or the predicate for a new
/// ICmp instruction. The sign is passed in to determine which kind of
/// predicate to use in the new icmp instruction.
/// This is the complement of getICmpCode. It turns a predicate code into
/// either a constant true or false or the predicate for a new ICmp.
/// The sign is passed in to determine which kind of predicate to use in the
/// new ICmp instruction.
/// Non-NULL return value will be a true or false constant.
/// NULL return means a new ICmp is needed. The predicate for which is output
/// in NewICmpPred.
Value *getICmpValue(bool Sign, unsigned Code, Value *LHS, Value *RHS,
CmpInst::Predicate &NewICmpPred);
/// NULL return means a new ICmp is needed. The predicate is output in Pred.
Constant *getPredForICmpCode(unsigned Code, bool Sign, Type *OpTy,
CmpInst::Predicate &Pred);
/// Return true if both predicates match sign or if at least one of them is an
/// equality comparison (which is signless).
bool PredicatesFoldable(CmpInst::Predicate p1, CmpInst::Predicate p2);
bool predicatesFoldable(CmpInst::Predicate P1, CmpInst::Predicate P2);
/// Decompose an icmp into the form ((X & Mask) pred 0) if possible. The
/// returned predicate is either == or !=. Returns false if decomposition

View file

@ -44,19 +44,30 @@ public:
F(F), AC(AC), DT(DT) {}
/// Return the bits demanded from instruction I.
///
/// For vector instructions individual vector elements are not distinguished:
/// A bit is demanded if it is demanded for any of the vector elements. The
/// size of the return value corresponds to the type size in bits of the
/// scalar type.
///
/// Instructions that do not have integer or vector of integer type are
/// accepted, but will always produce a mask with all bits set.
APInt getDemandedBits(Instruction *I);
/// Return true if, during analysis, I could not be reached.
bool isInstructionDead(Instruction *I);
/// Return whether this use is dead by means of not having any demanded bits.
bool isUseDead(Use *U);
void print(raw_ostream &OS);
private:
void performAnalysis();
void determineLiveOperandBits(const Instruction *UserI,
const Instruction *I, unsigned OperandNo,
const Value *Val, unsigned OperandNo,
const APInt &AOut, APInt &AB,
KnownBits &Known, KnownBits &Known2);
KnownBits &Known, KnownBits &Known2, bool &KnownBitsComputed);
Function &F;
AssumptionCache &AC;
@ -67,6 +78,9 @@ private:
// The set of visited instructions (non-integer-typed only).
SmallPtrSet<Instruction*, 32> Visited;
DenseMap<Instruction *, APInt> AliveBits;
// Uses with no demanded bits. If the user also has no demanded bits, the use
// might not be stored explicitly in this map, to save memory during analysis.
SmallPtrSet<Use *, 16> DeadUses;
};
class DemandedBitsWrapperPass : public FunctionPass {

View file

@ -936,6 +936,17 @@ template <typename T> class ArrayRef;
friend struct AnalysisInfoMixin<DependenceAnalysis>;
}; // class DependenceAnalysis
/// Printer pass to dump DA results.
struct DependenceAnalysisPrinterPass
: public PassInfoMixin<DependenceAnalysisPrinterPass> {
DependenceAnalysisPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
private:
raw_ostream &OS;
}; // class DependenceAnalysisPrinterPass
/// Legacy pass manager pass to access dependence information
class DependenceAnalysisWrapperPass : public FunctionPass {
public:

View file

@ -7,55 +7,199 @@
//
//===----------------------------------------------------------------------===//
//
// The divergence analysis is an LLVM pass which can be used to find out
// if a branch instruction in a GPU program is divergent or not. It can help
// branch optimizations such as jump threading and loop unswitching to make
// better decisions.
// \file
// The divergence analysis determines which instructions and branches are
// divergent given a set of divergent source instructions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_DIVERGENCE_ANALYSIS_H
#define LLVM_ANALYSIS_DIVERGENCE_ANALYSIS_H
#include "llvm/ADT/DenseSet.h"
#include "llvm/Analysis/SyncDependenceAnalysis.h"
#include "llvm/IR/Function.h"
#include "llvm/Pass.h"
#include <vector>
namespace llvm {
class Module;
class Value;
class DivergenceAnalysis : public FunctionPass {
class Instruction;
class Loop;
class raw_ostream;
class TargetTransformInfo;
/// \brief Generic divergence analysis for reducible CFGs.
///
/// This analysis propagates divergence in a data-parallel context from sources
/// of divergence to all users. It requires reducible CFGs. All assignments
/// should be in SSA form.
class DivergenceAnalysis {
public:
static char ID;
/// \brief This instance will analyze the whole function \p F or the loop \p
/// RegionLoop.
///
/// \param RegionLoop if non-null the analysis is restricted to \p RegionLoop.
/// Otherwise the whole function is analyzed.
/// \param IsLCSSAForm whether the analysis may assume that the IR in the
/// region in in LCSSA form.
DivergenceAnalysis(const Function &F, const Loop *RegionLoop,
const DominatorTree &DT, const LoopInfo &LI,
SyncDependenceAnalysis &SDA, bool IsLCSSAForm);
DivergenceAnalysis() : FunctionPass(ID) {
initializeDivergenceAnalysisPass(*PassRegistry::getPassRegistry());
}
/// \brief The loop that defines the analyzed region (if any).
const Loop *getRegionLoop() const { return RegionLoop; }
const Function &getFunction() const { return F; }
void getAnalysisUsage(AnalysisUsage &AU) const override;
/// \brief Whether \p BB is part of the region.
bool inRegion(const BasicBlock &BB) const;
/// \brief Whether \p I is part of the region.
bool inRegion(const Instruction &I) const;
bool runOnFunction(Function &F) override;
/// \brief Mark \p UniVal as a value that is always uniform.
void addUniformOverride(const Value &UniVal);
// Print all divergent branches in the function.
void print(raw_ostream &OS, const Module *) const override;
/// \brief Mark \p DivVal as a value that is always divergent.
void markDivergent(const Value &DivVal);
// Returns true if V is divergent at its definition.
//
// Even if this function returns false, V may still be divergent when used
// in a different basic block.
bool isDivergent(const Value *V) const { return DivergentValues.count(V); }
/// \brief Propagate divergence to all instructions in the region.
/// Divergence is seeded by calls to \p markDivergent.
void compute();
// Returns true if V is uniform/non-divergent.
//
// Even if this function returns true, V may still be divergent when used
// in a different basic block.
bool isUniform(const Value *V) const { return !isDivergent(V); }
/// \brief Whether any value was marked or analyzed to be divergent.
bool hasDetectedDivergence() const { return !DivergentValues.empty(); }
// Keep the analysis results uptodate by removing an erased value.
void removeValue(const Value *V) { DivergentValues.erase(V); }
/// \brief Whether \p Val will always return a uniform value regardless of its
/// operands
bool isAlwaysUniform(const Value &Val) const;
/// \brief Whether \p Val is a divergent value
bool isDivergent(const Value &Val) const;
void print(raw_ostream &OS, const Module *) const;
private:
// Stores all divergent values.
DenseSet<const Value *> DivergentValues;
};
} // End llvm namespace
bool updateTerminator(const Instruction &Term) const;
bool updatePHINode(const PHINode &Phi) const;
#endif //LLVM_ANALYSIS_DIVERGENCE_ANALYSIS_H
/// \brief Computes whether \p Inst is divergent based on the
/// divergence of its operands.
///
/// \returns Whether \p Inst is divergent.
///
/// This should only be called for non-phi, non-terminator instructions.
bool updateNormalInstruction(const Instruction &Inst) const;
/// \brief Mark users of live-out users as divergent.
///
/// \param LoopHeader the header of the divergent loop.
///
/// Marks all users of live-out values of the loop headed by \p LoopHeader
/// as divergent and puts them on the worklist.
void taintLoopLiveOuts(const BasicBlock &LoopHeader);
/// \brief Push all users of \p Val (in the region) to the worklist
void pushUsers(const Value &I);
/// \brief Push all phi nodes in @block to the worklist
void pushPHINodes(const BasicBlock &Block);
/// \brief Mark \p Block as join divergent
///
/// A block is join divergent if two threads may reach it from different
/// incoming blocks at the same time.
void markBlockJoinDivergent(const BasicBlock &Block) {
DivergentJoinBlocks.insert(&Block);
}
/// \brief Whether \p Val is divergent when read in \p ObservingBlock.
bool isTemporalDivergent(const BasicBlock &ObservingBlock,
const Value &Val) const;
/// \brief Whether \p Block is join divergent
///
/// (see markBlockJoinDivergent).
bool isJoinDivergent(const BasicBlock &Block) const {
return DivergentJoinBlocks.find(&Block) != DivergentJoinBlocks.end();
}
/// \brief Propagate control-induced divergence to users (phi nodes and
/// instructions).
//
// \param JoinBlock is a divergent loop exit or join point of two disjoint
// paths.
// \returns Whether \p JoinBlock is a divergent loop exit of \p TermLoop.
bool propagateJoinDivergence(const BasicBlock &JoinBlock,
const Loop *TermLoop);
/// \brief Propagate induced value divergence due to control divergence in \p
/// Term.
void propagateBranchDivergence(const Instruction &Term);
/// \brief Propagate divergent caused by a divergent loop exit.
///
/// \param ExitingLoop is a divergent loop.
void propagateLoopDivergence(const Loop &ExitingLoop);
private:
const Function &F;
// If regionLoop != nullptr, analysis is only performed within \p RegionLoop.
// Otw, analyze the whole function
const Loop *RegionLoop;
const DominatorTree &DT;
const LoopInfo &LI;
// Recognized divergent loops
DenseSet<const Loop *> DivergentLoops;
// The SDA links divergent branches to divergent control-flow joins.
SyncDependenceAnalysis &SDA;
// Use simplified code path for LCSSA form.
bool IsLCSSAForm;
// Set of known-uniform values.
DenseSet<const Value *> UniformOverrides;
// Blocks with joining divergent control from different predecessors.
DenseSet<const BasicBlock *> DivergentJoinBlocks;
// Detected/marked divergent values.
DenseSet<const Value *> DivergentValues;
// Internal worklist for divergence propagation.
std::vector<const Instruction *> Worklist;
};
/// \brief Divergence analysis frontend for GPU kernels.
class GPUDivergenceAnalysis {
SyncDependenceAnalysis SDA;
DivergenceAnalysis DA;
public:
/// Runs the divergence analysis on @F, a GPU kernel
GPUDivergenceAnalysis(Function &F, const DominatorTree &DT,
const PostDominatorTree &PDT, const LoopInfo &LI,
const TargetTransformInfo &TTI);
/// Whether any divergence was detected.
bool hasDivergence() const { return DA.hasDetectedDivergence(); }
/// The GPU kernel this analysis result is for
const Function &getFunction() const { return DA.getFunction(); }
/// Whether \p V is divergent.
bool isDivergent(const Value &V) const;
/// Whether \p V is uniform/non-divergent
bool isUniform(const Value &V) const { return !isDivergent(V); }
/// Print all divergent values in the kernel.
void print(raw_ostream &OS, const Module *) const;
};
} // namespace llvm
#endif // LLVM_ANALYSIS_DIVERGENCE_ANALYSIS_H

View file

@ -88,7 +88,7 @@ public:
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB);
using AAResultBase::getModRefInfo;
ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc);
ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc);
/// getModRefBehavior - Return the behavior of the specified function if
/// called from the specified call site. The call site may be null in which
@ -98,7 +98,7 @@ public:
/// getModRefBehavior - Return the behavior of the specified function if
/// called from the specified call site. The call site may be null in which
/// case the most generic behavior of this function should be returned.
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS);
FunctionModRefBehavior getModRefBehavior(const CallBase *Call);
private:
FunctionInfo *getFunctionInfo(const Function *F);
@ -113,7 +113,7 @@ private:
void CollectSCCMembership(CallGraph &CG);
bool isNonEscapingGlobalNoAlias(const GlobalValue *GV, const Value *V);
ModRefInfo getModRefInfoForArgument(ImmutableCallSite CS,
ModRefInfo getModRefInfoForArgument(const CallBase *Call,
const GlobalValue *GV);
};

View file

@ -0,0 +1,26 @@
//===-- GuardUtils.h - Utils for work with guards ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Utils that are used to perform analyzes related to guards and their
// conditions.
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_GUARDUTILS_H
#define LLVM_ANALYSIS_GUARDUTILS_H
namespace llvm {
class User;
/// Returns true iff \p U has semantics of a guard.
bool isGuard(const User *U);
} // llvm
#endif // LLVM_ANALYSIS_GUARDUTILS_H

View file

@ -0,0 +1,357 @@
//===- llvm/Analysis/IVDescriptors.h - IndVar Descriptors -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file "describes" induction and recurrence variables.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_IVDESCRIPTORS_H
#define LLVM_ANALYSIS_IVDESCRIPTORS_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/DemandedBits.h"
#include "llvm/Analysis/EHPersonalities.h"
#include "llvm/Analysis/MustExecute.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/Casting.h"
namespace llvm {
class AliasSet;
class AliasSetTracker;
class BasicBlock;
class DataLayout;
class Loop;
class LoopInfo;
class OptimizationRemarkEmitter;
class PredicatedScalarEvolution;
class PredIteratorCache;
class ScalarEvolution;
class SCEV;
class TargetLibraryInfo;
class TargetTransformInfo;
/// The RecurrenceDescriptor is used to identify recurrences variables in a
/// loop. Reduction is a special case of recurrence that has uses of the
/// recurrence variable outside the loop. The method isReductionPHI identifies
/// reductions that are basic recurrences.
///
/// Basic recurrences are defined as the summation, product, OR, AND, XOR, min,
/// or max of a set of terms. For example: for(i=0; i<n; i++) { total +=
/// array[i]; } is a summation of array elements. Basic recurrences are a
/// special case of chains of recurrences (CR). See ScalarEvolution for CR
/// references.
/// This struct holds information about recurrence variables.
class RecurrenceDescriptor {
public:
/// This enum represents the kinds of recurrences that we support.
enum RecurrenceKind {
RK_NoRecurrence, ///< Not a recurrence.
RK_IntegerAdd, ///< Sum of integers.
RK_IntegerMult, ///< Product of integers.
RK_IntegerOr, ///< Bitwise or logical OR of numbers.
RK_IntegerAnd, ///< Bitwise or logical AND of numbers.
RK_IntegerXor, ///< Bitwise or logical XOR of numbers.
RK_IntegerMinMax, ///< Min/max implemented in terms of select(cmp()).
RK_FloatAdd, ///< Sum of floats.
RK_FloatMult, ///< Product of floats.
RK_FloatMinMax ///< Min/max implemented in terms of select(cmp()).
};
// This enum represents the kind of minmax recurrence.
enum MinMaxRecurrenceKind {
MRK_Invalid,
MRK_UIntMin,
MRK_UIntMax,
MRK_SIntMin,
MRK_SIntMax,
MRK_FloatMin,
MRK_FloatMax
};
RecurrenceDescriptor() = default;
RecurrenceDescriptor(Value *Start, Instruction *Exit, RecurrenceKind K,
MinMaxRecurrenceKind MK, Instruction *UAI, Type *RT,
bool Signed, SmallPtrSetImpl<Instruction *> &CI)
: StartValue(Start), LoopExitInstr(Exit), Kind(K), MinMaxKind(MK),
UnsafeAlgebraInst(UAI), RecurrenceType(RT), IsSigned(Signed) {
CastInsts.insert(CI.begin(), CI.end());
}
/// This POD struct holds information about a potential recurrence operation.
class InstDesc {
public:
InstDesc(bool IsRecur, Instruction *I, Instruction *UAI = nullptr)
: IsRecurrence(IsRecur), PatternLastInst(I), MinMaxKind(MRK_Invalid),
UnsafeAlgebraInst(UAI) {}
InstDesc(Instruction *I, MinMaxRecurrenceKind K, Instruction *UAI = nullptr)
: IsRecurrence(true), PatternLastInst(I), MinMaxKind(K),
UnsafeAlgebraInst(UAI) {}
bool isRecurrence() { return IsRecurrence; }
bool hasUnsafeAlgebra() { return UnsafeAlgebraInst != nullptr; }
Instruction *getUnsafeAlgebraInst() { return UnsafeAlgebraInst; }
MinMaxRecurrenceKind getMinMaxKind() { return MinMaxKind; }
Instruction *getPatternInst() { return PatternLastInst; }
private:
// Is this instruction a recurrence candidate.
bool IsRecurrence;
// The last instruction in a min/max pattern (select of the select(icmp())
// pattern), or the current recurrence instruction otherwise.
Instruction *PatternLastInst;
// If this is a min/max pattern the comparison predicate.
MinMaxRecurrenceKind MinMaxKind;
// Recurrence has unsafe algebra.
Instruction *UnsafeAlgebraInst;
};
/// Returns a struct describing if the instruction 'I' can be a recurrence
/// variable of type 'Kind'. If the recurrence is a min/max pattern of
/// select(icmp()) this function advances the instruction pointer 'I' from the
/// compare instruction to the select instruction and stores this pointer in
/// 'PatternLastInst' member of the returned struct.
static InstDesc isRecurrenceInstr(Instruction *I, RecurrenceKind Kind,
InstDesc &Prev, bool HasFunNoNaNAttr);
/// Returns true if instruction I has multiple uses in Insts
static bool hasMultipleUsesOf(Instruction *I,
SmallPtrSetImpl<Instruction *> &Insts,
unsigned MaxNumUses);
/// Returns true if all uses of the instruction I is within the Set.
static bool areAllUsesIn(Instruction *I, SmallPtrSetImpl<Instruction *> &Set);
/// Returns a struct describing if the instruction if the instruction is a
/// Select(ICmp(X, Y), X, Y) instruction pattern corresponding to a min(X, Y)
/// or max(X, Y).
static InstDesc isMinMaxSelectCmpPattern(Instruction *I, InstDesc &Prev);
/// Returns a struct describing if the instruction is a
/// Select(FCmp(X, Y), (Z = X op PHINode), PHINode) instruction pattern.
static InstDesc isConditionalRdxPattern(RecurrenceKind Kind, Instruction *I);
/// Returns identity corresponding to the RecurrenceKind.
static Constant *getRecurrenceIdentity(RecurrenceKind K, Type *Tp);
/// Returns the opcode of binary operation corresponding to the
/// RecurrenceKind.
static unsigned getRecurrenceBinOp(RecurrenceKind Kind);
/// Returns true if Phi is a reduction of type Kind and adds it to the
/// RecurrenceDescriptor. If either \p DB is non-null or \p AC and \p DT are
/// non-null, the minimal bit width needed to compute the reduction will be
/// computed.
static bool AddReductionVar(PHINode *Phi, RecurrenceKind Kind, Loop *TheLoop,
bool HasFunNoNaNAttr,
RecurrenceDescriptor &RedDes,
DemandedBits *DB = nullptr,
AssumptionCache *AC = nullptr,
DominatorTree *DT = nullptr);
/// Returns true if Phi is a reduction in TheLoop. The RecurrenceDescriptor
/// is returned in RedDes. If either \p DB is non-null or \p AC and \p DT are
/// non-null, the minimal bit width needed to compute the reduction will be
/// computed.
static bool isReductionPHI(PHINode *Phi, Loop *TheLoop,
RecurrenceDescriptor &RedDes,
DemandedBits *DB = nullptr,
AssumptionCache *AC = nullptr,
DominatorTree *DT = nullptr);
/// Returns true if Phi is a first-order recurrence. A first-order recurrence
/// is a non-reduction recurrence relation in which the value of the
/// recurrence in the current loop iteration equals a value defined in the
/// previous iteration. \p SinkAfter includes pairs of instructions where the
/// first will be rescheduled to appear after the second if/when the loop is
/// vectorized. It may be augmented with additional pairs if needed in order
/// to handle Phi as a first-order recurrence.
static bool
isFirstOrderRecurrence(PHINode *Phi, Loop *TheLoop,
DenseMap<Instruction *, Instruction *> &SinkAfter,
DominatorTree *DT);
RecurrenceKind getRecurrenceKind() { return Kind; }
MinMaxRecurrenceKind getMinMaxRecurrenceKind() { return MinMaxKind; }
TrackingVH<Value> getRecurrenceStartValue() { return StartValue; }
Instruction *getLoopExitInstr() { return LoopExitInstr; }
/// Returns true if the recurrence has unsafe algebra which requires a relaxed
/// floating-point model.
bool hasUnsafeAlgebra() { return UnsafeAlgebraInst != nullptr; }
/// Returns first unsafe algebra instruction in the PHI node's use-chain.
Instruction *getUnsafeAlgebraInst() { return UnsafeAlgebraInst; }
/// Returns true if the recurrence kind is an integer kind.
static bool isIntegerRecurrenceKind(RecurrenceKind Kind);
/// Returns true if the recurrence kind is a floating point kind.
static bool isFloatingPointRecurrenceKind(RecurrenceKind Kind);
/// Returns true if the recurrence kind is an arithmetic kind.
static bool isArithmeticRecurrenceKind(RecurrenceKind Kind);
/// Returns the type of the recurrence. This type can be narrower than the
/// actual type of the Phi if the recurrence has been type-promoted.
Type *getRecurrenceType() { return RecurrenceType; }
/// Returns a reference to the instructions used for type-promoting the
/// recurrence.
SmallPtrSet<Instruction *, 8> &getCastInsts() { return CastInsts; }
/// Returns true if all source operands of the recurrence are SExtInsts.
bool isSigned() { return IsSigned; }
private:
// The starting value of the recurrence.
// It does not have to be zero!
TrackingVH<Value> StartValue;
// The instruction who's value is used outside the loop.
Instruction *LoopExitInstr = nullptr;
// The kind of the recurrence.
RecurrenceKind Kind = RK_NoRecurrence;
// If this a min/max recurrence the kind of recurrence.
MinMaxRecurrenceKind MinMaxKind = MRK_Invalid;
// First occurrence of unasfe algebra in the PHI's use-chain.
Instruction *UnsafeAlgebraInst = nullptr;
// The type of the recurrence.
Type *RecurrenceType = nullptr;
// True if all source operands of the recurrence are SExtInsts.
bool IsSigned = false;
// Instructions used for type-promoting the recurrence.
SmallPtrSet<Instruction *, 8> CastInsts;
};
/// A struct for saving information about induction variables.
class InductionDescriptor {
public:
/// This enum represents the kinds of inductions that we support.
enum InductionKind {
IK_NoInduction, ///< Not an induction variable.
IK_IntInduction, ///< Integer induction variable. Step = C.
IK_PtrInduction, ///< Pointer induction var. Step = C / sizeof(elem).
IK_FpInduction ///< Floating point induction variable.
};
public:
/// Default constructor - creates an invalid induction.
InductionDescriptor() = default;
/// Get the consecutive direction. Returns:
/// 0 - unknown or non-consecutive.
/// 1 - consecutive and increasing.
/// -1 - consecutive and decreasing.
int getConsecutiveDirection() const;
Value *getStartValue() const { return StartValue; }
InductionKind getKind() const { return IK; }
const SCEV *getStep() const { return Step; }
BinaryOperator *getInductionBinOp() const { return InductionBinOp; }
ConstantInt *getConstIntStepValue() const;
/// Returns true if \p Phi is an induction in the loop \p L. If \p Phi is an
/// induction, the induction descriptor \p D will contain the data describing
/// this induction. If by some other means the caller has a better SCEV
/// expression for \p Phi than the one returned by the ScalarEvolution
/// analysis, it can be passed through \p Expr. If the def-use chain
/// associated with the phi includes casts (that we know we can ignore
/// under proper runtime checks), they are passed through \p CastsToIgnore.
static bool
isInductionPHI(PHINode *Phi, const Loop *L, ScalarEvolution *SE,
InductionDescriptor &D, const SCEV *Expr = nullptr,
SmallVectorImpl<Instruction *> *CastsToIgnore = nullptr);
/// Returns true if \p Phi is a floating point induction in the loop \p L.
/// If \p Phi is an induction, the induction descriptor \p D will contain
/// the data describing this induction.
static bool isFPInductionPHI(PHINode *Phi, const Loop *L, ScalarEvolution *SE,
InductionDescriptor &D);
/// Returns true if \p Phi is a loop \p L induction, in the context associated
/// with the run-time predicate of PSE. If \p Assume is true, this can add
/// further SCEV predicates to \p PSE in order to prove that \p Phi is an
/// induction.
/// If \p Phi is an induction, \p D will contain the data describing this
/// induction.
static bool isInductionPHI(PHINode *Phi, const Loop *L,
PredicatedScalarEvolution &PSE,
InductionDescriptor &D, bool Assume = false);
/// Returns true if the induction type is FP and the binary operator does
/// not have the "fast-math" property. Such operation requires a relaxed FP
/// mode.
bool hasUnsafeAlgebra() {
return InductionBinOp && !cast<FPMathOperator>(InductionBinOp)->isFast();
}
/// Returns induction operator that does not have "fast-math" property
/// and requires FP unsafe mode.
Instruction *getUnsafeAlgebraInst() {
if (!InductionBinOp || cast<FPMathOperator>(InductionBinOp)->isFast())
return nullptr;
return InductionBinOp;
}
/// Returns binary opcode of the induction operator.
Instruction::BinaryOps getInductionOpcode() const {
return InductionBinOp ? InductionBinOp->getOpcode()
: Instruction::BinaryOpsEnd;
}
/// Returns a reference to the type cast instructions in the induction
/// update chain, that are redundant when guarded with a runtime
/// SCEV overflow check.
const SmallVectorImpl<Instruction *> &getCastInsts() const {
return RedundantCasts;
}
private:
/// Private constructor - used by \c isInductionPHI.
InductionDescriptor(Value *Start, InductionKind K, const SCEV *Step,
BinaryOperator *InductionBinOp = nullptr,
SmallVectorImpl<Instruction *> *Casts = nullptr);
/// Start value.
TrackingVH<Value> StartValue;
/// Induction kind.
InductionKind IK = IK_NoInduction;
/// Step value.
const SCEV *Step = nullptr;
// Instruction that advances induction variable.
BinaryOperator *InductionBinOp = nullptr;
// Instructions used for type-casts of the induction variable,
// that are redundant when guarded with a runtime SCEV overflow check.
SmallVector<Instruction *, 2> RedundantCasts;
};
} // end namespace llvm
#endif // LLVM_ANALYSIS_IVDESCRIPTORS_H

View file

@ -1,35 +0,0 @@
//===-- IndirectCallSiteVisitor.h - indirect call-sites visitor -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements defines a visitor class and a helper function that find
// all indirect call-sites in a function.
#include "llvm/IR/InstVisitor.h"
#include <vector>
namespace llvm {
// Visitor class that finds all indirect call sites.
struct PGOIndirectCallSiteVisitor
: public InstVisitor<PGOIndirectCallSiteVisitor> {
std::vector<Instruction *> IndirectCallInsts;
PGOIndirectCallSiteVisitor() {}
void visitCallSite(CallSite CS) {
if (CS.isIndirectCall())
IndirectCallInsts.push_back(CS.getInstruction());
}
};
// Helper function that finds all indirect call sites.
inline std::vector<Instruction *> findIndirectCallSites(Function &F) {
PGOIndirectCallSiteVisitor ICV;
ICV.visit(F);
return ICV.IndirectCallInsts;
}
}

View file

@ -0,0 +1,39 @@
//===-- IndirectCallVisitor.h - indirect call visitor ---------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements defines a visitor class and a helper function that find
// all indirect call-sites in a function.
#ifndef LLVM_ANALYSIS_INDIRECTCALLVISITOR_H
#define LLVM_ANALYSIS_INDIRECTCALLVISITOR_H
#include "llvm/IR/InstVisitor.h"
#include <vector>
namespace llvm {
// Visitor class that finds all indirect call.
struct PGOIndirectCallVisitor : public InstVisitor<PGOIndirectCallVisitor> {
std::vector<Instruction *> IndirectCalls;
PGOIndirectCallVisitor() {}
void visitCallBase(CallBase &Call) {
if (Call.isIndirectCall())
IndirectCalls.push_back(&Call);
}
};
// Helper function that finds all indirect call sites.
inline std::vector<Instruction *> findIndirectCalls(Function &F) {
PGOIndirectCallVisitor ICV;
ICV.visit(F);
return ICV.IndirectCalls;
}
} // namespace llvm
#endif

View file

@ -46,7 +46,6 @@ const int IndirectCallThreshold = 100;
const int CallPenalty = 25;
const int LastCallToStaticBonus = 15000;
const int ColdccPenalty = 2000;
const int NoreturnPenalty = 10000;
/// Do not inline functions which allocate this many bytes on the stack
/// when the caller is recursive.
const unsigned TotalAllocaSizeRecursiveCaller = 1024;
@ -74,8 +73,15 @@ class InlineCost {
/// The adjusted threshold against which this cost was computed.
const int Threshold;
/// Must be set for Always and Never instances.
const char *Reason = nullptr;
// Trivial constructor, interesting logic in the factory functions below.
InlineCost(int Cost, int Threshold) : Cost(Cost), Threshold(Threshold) {}
InlineCost(int Cost, int Threshold, const char *Reason = nullptr)
: Cost(Cost), Threshold(Threshold), Reason(Reason) {
assert((isVariable() || Reason) &&
"Reason must be provided for Never or Always");
}
public:
static InlineCost get(int Cost, int Threshold) {
@ -83,11 +89,11 @@ public:
assert(Cost < NeverInlineCost && "Cost crosses sentinel value");
return InlineCost(Cost, Threshold);
}
static InlineCost getAlways() {
return InlineCost(AlwaysInlineCost, 0);
static InlineCost getAlways(const char *Reason) {
return InlineCost(AlwaysInlineCost, 0, Reason);
}
static InlineCost getNever() {
return InlineCost(NeverInlineCost, 0);
static InlineCost getNever(const char *Reason) {
return InlineCost(NeverInlineCost, 0, Reason);
}
/// Test whether the inline cost is low enough for inlining.
@ -112,12 +118,30 @@ public:
return Threshold;
}
/// Get the reason of Always or Never.
const char *getReason() const {
assert((Reason || isVariable()) &&
"InlineCost reason must be set for Always or Never");
return Reason;
}
/// Get the cost delta from the threshold for inlining.
/// Only valid if the cost is of the variable kind. Returns a negative
/// value if the cost is too high to inline.
int getCostDelta() const { return Threshold - getCost(); }
};
/// InlineResult is basically true or false. For false results the message
/// describes a reason why it is decided not to inline.
struct InlineResult {
const char *message = nullptr;
InlineResult(bool result, const char *message = nullptr)
: message(result ? nullptr : (message ? message : "cost > threshold")) {}
InlineResult(const char *message = nullptr) : message(message) {}
operator bool() const { return !message; }
operator const char *() const { return message; }
};
/// Thresholds to tune inline cost analysis. The inline cost analysis decides
/// the condition to apply a threshold and applies it. Otherwise,
/// DefaultThreshold is used. If a threshold is Optional, it is applied only

View file

@ -0,0 +1,150 @@
//===-- InstructionPrecedenceTracking.h -------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Implements a class that is able to define some instructions as "special"
// (e.g. as having implicit control flow, or writing memory, or having another
// interesting property) and then efficiently answers queries of the types:
// 1. Are there any special instructions in the block of interest?
// 2. Return first of the special instructions in the given block;
// 3. Check if the given instruction is preceeded by the first special
// instruction in the same block.
// The class provides caching that allows to answer these queries quickly. The
// user must make sure that the cached data is invalidated properly whenever
// a content of some tracked block is changed.
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_INSTRUCTIONPRECEDENCETRACKING_H
#define LLVM_ANALYSIS_INSTRUCTIONPRECEDENCETRACKING_H
#include "llvm/IR/Dominators.h"
#include "llvm/Analysis/OrderedInstructions.h"
namespace llvm {
class InstructionPrecedenceTracking {
// Maps a block to the topmost special instruction in it. If the value is
// nullptr, it means that it is known that this block does not contain any
// special instructions.
DenseMap<const BasicBlock *, const Instruction *> FirstSpecialInsts;
// Allows to answer queries about precedence of instructions within one block.
OrderedInstructions OI;
// Fills information about the given block's special instructions.
void fill(const BasicBlock *BB);
#ifndef NDEBUG
/// Asserts that the cached info for \p BB is up-to-date. This helps to catch
/// the usage error of accessing a block without properly invalidating after a
/// previous transform.
void validate(const BasicBlock *BB) const;
/// Asserts whether or not the contents of this tracking is up-to-date. This
/// helps to catch the usage error of accessing a block without properly
/// invalidating after a previous transform.
void validateAll() const;
#endif
protected:
InstructionPrecedenceTracking(DominatorTree *DT)
: OI(OrderedInstructions(DT)) {}
/// Returns the topmost special instruction from the block \p BB. Returns
/// nullptr if there is no special instructions in the block.
const Instruction *getFirstSpecialInstruction(const BasicBlock *BB);
/// Returns true iff at least one instruction from the basic block \p BB is
/// special.
bool hasSpecialInstructions(const BasicBlock *BB);
/// Returns true iff the first special instruction of \p Insn's block exists
/// and dominates \p Insn.
bool isPreceededBySpecialInstruction(const Instruction *Insn);
/// A predicate that defines whether or not the instruction \p Insn is
/// considered special and needs to be tracked. Implementing this method in
/// children classes allows to implement tracking of implicit control flow,
/// memory writing instructions or any other kinds of instructions we might
/// be interested in.
virtual bool isSpecialInstruction(const Instruction *Insn) const = 0;
virtual ~InstructionPrecedenceTracking() = default;
public:
/// Notifies this tracking that we are going to insert a new instruction \p
/// Inst to the basic block \p BB. It makes all necessary updates to internal
/// caches to keep them consistent.
void insertInstructionTo(const Instruction *Inst, const BasicBlock *BB);
/// Notifies this tracking that we are going to remove the instruction \p Inst
/// It makes all necessary updates to internal caches to keep them consistent.
void removeInstruction(const Instruction *Inst);
/// Invalidates all information from this tracking.
void clear();
};
/// This class allows to keep track on instructions with implicit control flow.
/// These are instructions that may not pass execution to their successors. For
/// example, throwing calls and guards do not always do this. If we need to know
/// for sure that some instruction is guaranteed to execute if the given block
/// is reached, then we need to make sure that there is no implicit control flow
/// instruction (ICFI) preceeding it. For example, this check is required if we
/// perform PRE moving non-speculable instruction to other place.
class ImplicitControlFlowTracking : public InstructionPrecedenceTracking {
public:
ImplicitControlFlowTracking(DominatorTree *DT)
: InstructionPrecedenceTracking(DT) {}
/// Returns the topmost instruction with implicit control flow from the given
/// basic block. Returns nullptr if there is no such instructions in the block.
const Instruction *getFirstICFI(const BasicBlock *BB) {
return getFirstSpecialInstruction(BB);
}
/// Returns true if at least one instruction from the given basic block has
/// implicit control flow.
bool hasICF(const BasicBlock *BB) {
return hasSpecialInstructions(BB);
}
/// Returns true if the first ICFI of Insn's block exists and dominates Insn.
bool isDominatedByICFIFromSameBlock(const Instruction *Insn) {
return isPreceededBySpecialInstruction(Insn);
}
virtual bool isSpecialInstruction(const Instruction *Insn) const;
};
class MemoryWriteTracking : public InstructionPrecedenceTracking {
public:
MemoryWriteTracking(DominatorTree *DT) : InstructionPrecedenceTracking(DT) {}
/// Returns the topmost instruction that may write memory from the given
/// basic block. Returns nullptr if there is no such instructions in the block.
const Instruction *getFirstMemoryWrite(const BasicBlock *BB) {
return getFirstSpecialInstruction(BB);
}
/// Returns true if at least one instruction from the given basic block may
/// write memory.
bool mayWriteToMemory(const BasicBlock *BB) {
return hasSpecialInstructions(BB);
}
/// Returns true if the first memory writing instruction of Insn's block
/// exists and dominates Insn.
bool isDominatedByMemoryWriteFromSameBlock(const Instruction *Insn) {
return isPreceededBySpecialInstruction(Insn);
}
virtual bool isSpecialInstruction(const Instruction *Insn) const;
};
} // llvm
#endif // LLVM_ANALYSIS_INSTRUCTIONPRECEDENCETRACKING_H

View file

@ -32,6 +32,8 @@
#ifndef LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H
#define LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/User.h"
namespace llvm {
@ -40,7 +42,6 @@ template <typename T, typename... TArgs> class AnalysisManager;
template <class T> class ArrayRef;
class AssumptionCache;
class DominatorTree;
class Instruction;
class ImmutableCallSite;
class DataLayout;
class FastMathFlags;
@ -50,6 +51,41 @@ class Pass;
class TargetLibraryInfo;
class Type;
class Value;
class MDNode;
class BinaryOperator;
/// InstrInfoQuery provides an interface to query additional information for
/// instructions like metadata or keywords like nsw, which provides conservative
/// results if the users specified it is safe to use.
struct InstrInfoQuery {
InstrInfoQuery(bool UMD) : UseInstrInfo(UMD) {}
InstrInfoQuery() : UseInstrInfo(true) {}
bool UseInstrInfo = true;
MDNode *getMetadata(const Instruction *I, unsigned KindID) const {
if (UseInstrInfo)
return I->getMetadata(KindID);
return nullptr;
}
template <class InstT> bool hasNoUnsignedWrap(const InstT *Op) const {
if (UseInstrInfo)
return Op->hasNoUnsignedWrap();
return false;
}
template <class InstT> bool hasNoSignedWrap(const InstT *Op) const {
if (UseInstrInfo)
return Op->hasNoSignedWrap();
return false;
}
bool isExact(const BinaryOperator *Op) const {
if (UseInstrInfo && isa<PossiblyExactOperator>(Op))
return cast<PossiblyExactOperator>(Op)->isExact();
return false;
}
};
struct SimplifyQuery {
const DataLayout &DL;
@ -58,14 +94,19 @@ struct SimplifyQuery {
AssumptionCache *AC = nullptr;
const Instruction *CxtI = nullptr;
// Wrapper to query additional information for instructions like metadata or
// keywords like nsw, which provides conservative results if those cannot
// be safely used.
const InstrInfoQuery IIQ;
SimplifyQuery(const DataLayout &DL, const Instruction *CXTI = nullptr)
: DL(DL), CxtI(CXTI) {}
SimplifyQuery(const DataLayout &DL, const TargetLibraryInfo *TLI,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CXTI = nullptr)
: DL(DL), TLI(TLI), DT(DT), AC(AC), CxtI(CXTI) {}
const Instruction *CXTI = nullptr, bool UseInstrInfo = true)
: DL(DL), TLI(TLI), DT(DT), AC(AC), CxtI(CXTI), IIQ(UseInstrInfo) {}
SimplifyQuery getWithInstruction(Instruction *I) const {
SimplifyQuery Copy(*this);
Copy.CxtI = I;

View file

@ -6,7 +6,7 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// \file
/// Compute iterated dominance frontiers using a linear time algorithm.
///
/// The algorithm used here is based on:
@ -28,6 +28,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFGDiff.h"
#include "llvm/IR/Dominators.h"
namespace llvm {
@ -45,17 +46,21 @@ namespace llvm {
template <class NodeTy, bool IsPostDom>
class IDFCalculator {
public:
IDFCalculator(DominatorTreeBase<BasicBlock, IsPostDom> &DT)
: DT(DT), useLiveIn(false) {}
IDFCalculator(DominatorTreeBase<BasicBlock, IsPostDom> &DT)
: DT(DT), GD(nullptr), useLiveIn(false) {}
/// Give the IDF calculator the set of blocks in which the value is
/// defined. This is equivalent to the set of starting blocks it should be
/// calculating the IDF for (though later gets pruned based on liveness).
///
/// Note: This set *must* live for the entire lifetime of the IDF calculator.
void setDefiningBlocks(const SmallPtrSetImpl<BasicBlock *> &Blocks) {
DefBlocks = &Blocks;
}
IDFCalculator(DominatorTreeBase<BasicBlock, IsPostDom> &DT,
const GraphDiff<BasicBlock *, IsPostDom> *GD)
: DT(DT), GD(GD), useLiveIn(false) {}
/// Give the IDF calculator the set of blocks in which the value is
/// defined. This is equivalent to the set of starting blocks it should be
/// calculating the IDF for (though later gets pruned based on liveness).
///
/// Note: This set *must* live for the entire lifetime of the IDF calculator.
void setDefiningBlocks(const SmallPtrSetImpl<BasicBlock *> &Blocks) {
DefBlocks = &Blocks;
}
/// Give the IDF calculator the set of blocks in which the value is
/// live on entry to the block. This is used to prune the IDF calculation to
@ -85,6 +90,7 @@ class IDFCalculator {
private:
DominatorTreeBase<BasicBlock, IsPostDom> &DT;
const GraphDiff<BasicBlock *, IsPostDom> *GD;
bool useLiveIn;
const SmallPtrSetImpl<BasicBlock *> *LiveInBlocks;
const SmallPtrSetImpl<BasicBlock *> *DefBlocks;

View file

@ -0,0 +1,69 @@
//===- llvm/Analysis/LegacyDivergenceAnalysis.h - KernelDivergence Analysis -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// The kernel divergence analysis is an LLVM pass which can be used to find out
// if a branch instruction in a GPU program (kernel) is divergent or not. It can help
// branch optimizations such as jump threading and loop unswitching to make
// better decisions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_LEGACY_DIVERGENCE_ANALYSIS_H
#define LLVM_ANALYSIS_LEGACY_DIVERGENCE_ANALYSIS_H
#include "llvm/ADT/DenseSet.h"
#include "llvm/IR/Function.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/DivergenceAnalysis.h"
namespace llvm {
class Value;
class GPUDivergenceAnalysis;
class LegacyDivergenceAnalysis : public FunctionPass {
public:
static char ID;
LegacyDivergenceAnalysis() : FunctionPass(ID) {
initializeLegacyDivergenceAnalysisPass(*PassRegistry::getPassRegistry());
}
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnFunction(Function &F) override;
// Print all divergent branches in the function.
void print(raw_ostream &OS, const Module *) const override;
// Returns true if V is divergent at its definition.
//
// Even if this function returns false, V may still be divergent when used
// in a different basic block.
bool isDivergent(const Value *V) const;
// Returns true if V is uniform/non-divergent.
//
// Even if this function returns true, V may still be divergent when used
// in a different basic block.
bool isUniform(const Value *V) const { return !isDivergent(V); }
// Keep the analysis results uptodate by removing an erased value.
void removeValue(const Value *V) { DivergentValues.erase(V); }
private:
// Whether analysis should be performed by GPUDivergenceAnalysis.
bool shouldUseGPUDivergenceAnalysis(const Function &F) const;
// (optional) handle to new DivergenceAnalysis
std::unique_ptr<GPUDivergenceAnalysis> gpuDA;
// Stores all divergent values.
DenseSet<const Value *> DivergentValues;
};
} // End llvm namespace
#endif //LLVM_ANALYSIS_LEGACY_DIVERGENCE_ANALYSIS_H

View file

@ -97,6 +97,19 @@ public:
/// Set of potential dependent memory accesses.
typedef EquivalenceClasses<MemAccessInfo> DepCandidates;
/// Type to keep track of the status of the dependence check. The order of
/// the elements is important and has to be from most permissive to least
/// permissive.
enum class VectorizationSafetyStatus {
// Can vectorize safely without RT checks. All dependences are known to be
// safe.
Safe,
// Can possibly vectorize with RT checks to overcome unknown dependencies.
PossiblySafeWithRtChecks,
// Cannot vectorize due to known unsafe dependencies.
Unsafe,
};
/// Dependece between memory access instructions.
struct Dependence {
/// The type of the dependence.
@ -146,7 +159,7 @@ public:
Instruction *getDestination(const LoopAccessInfo &LAI) const;
/// Dependence types that don't prevent vectorization.
static bool isSafeForVectorization(DepType Type);
static VectorizationSafetyStatus isSafeForVectorization(DepType Type);
/// Lexically forward dependence.
bool isForward() const;
@ -164,8 +177,8 @@ public:
MemoryDepChecker(PredicatedScalarEvolution &PSE, const Loop *L)
: PSE(PSE), InnermostLoop(L), AccessIdx(0), MaxSafeRegisterWidth(-1U),
ShouldRetryWithRuntimeCheck(false), SafeForVectorization(true),
RecordDependences(true) {}
FoundNonConstantDistanceDependence(false),
Status(VectorizationSafetyStatus::Safe), RecordDependences(true) {}
/// Register the location (instructions are given increasing numbers)
/// of a write access.
@ -193,7 +206,9 @@ public:
/// No memory dependence was encountered that would inhibit
/// vectorization.
bool isSafeForVectorization() const { return SafeForVectorization; }
bool isSafeForVectorization() const {
return Status == VectorizationSafetyStatus::Safe;
}
/// The maximum number of bytes of a vector register we can vectorize
/// the accesses safely with.
@ -205,7 +220,10 @@ public:
/// In same cases when the dependency check fails we can still
/// vectorize the loop with a dynamic array access check.
bool shouldRetryWithRuntimeCheck() { return ShouldRetryWithRuntimeCheck; }
bool shouldRetryWithRuntimeCheck() const {
return FoundNonConstantDistanceDependence &&
Status == VectorizationSafetyStatus::PossiblySafeWithRtChecks;
}
/// Returns the memory dependences. If null is returned we exceeded
/// the MaxDependences threshold and this information is not
@ -267,11 +285,12 @@ private:
/// If we see a non-constant dependence distance we can still try to
/// vectorize this loop with runtime checks.
bool ShouldRetryWithRuntimeCheck;
bool FoundNonConstantDistanceDependence;
/// No memory dependence was encountered that would inhibit
/// vectorization.
bool SafeForVectorization;
/// Result of the dependence checks, indicating whether the checked
/// dependences are safe for vectorization, require RT checks or are known to
/// be unsafe.
VectorizationSafetyStatus Status;
//// True if Dependences reflects the dependences in the
//// loop. If false we exceeded MaxDependences and
@ -304,6 +323,11 @@ private:
/// \return false if we shouldn't vectorize at all or avoid larger
/// vectorization factors by limiting MaxSafeDepDistBytes.
bool couldPreventStoreLoadForward(uint64_t Distance, uint64_t TypeByteSize);
/// Updates the current safety status with \p S. We can go from Safe to
/// either PossiblySafeWithRtChecks or Unsafe and from
/// PossiblySafeWithRtChecks to Unsafe.
void mergeInStatus(VectorizationSafetyStatus S);
};
/// Holds information about the memory runtime legality checks to verify
@ -564,11 +588,10 @@ public:
/// Print the information about the memory accesses in the loop.
void print(raw_ostream &OS, unsigned Depth = 0) const;
/// Checks existence of store to invariant address inside loop.
/// If the loop has any store to invariant address, then it returns true,
/// else returns false.
bool hasStoreToLoopInvariantAddress() const {
return StoreToLoopInvariantAddress;
/// If the loop has memory dependence involving an invariant address, i.e. two
/// stores or a store and a load, then return true, else return false.
bool hasDependenceInvolvingLoopInvariantAddress() const {
return HasDependenceInvolvingLoopInvariantAddress;
}
/// Used to add runtime SCEV checks. Simplifies SCEV expressions and converts
@ -621,9 +644,8 @@ private:
/// Cache the result of analyzeLoop.
bool CanVecMem;
/// Indicator for storing to uniform addresses.
/// If a loop has write to a loop invariant address then it should be true.
bool StoreToLoopInvariantAddress;
/// Indicator that there are non vectorizable stores to a uniform address.
bool HasDependenceInvolvingLoopInvariantAddress;
/// The diagnostics report generated for the analysis. E.g. why we
/// couldn't analyze the loop.

View file

@ -408,6 +408,12 @@ public:
/// Verify loop structure of this loop and all nested loops.
void verifyLoopNest(DenseSet<const LoopT *> *Loops) const;
/// Returns true if the loop is annotated parallel.
///
/// Derived classes can override this method using static template
/// polymorphism.
bool isAnnotatedParallel() const { return false; }
/// Print loop with all the BBs inside it.
void print(raw_ostream &OS, unsigned Depth = 0, bool Verbose = false) const;
@ -989,6 +995,26 @@ public:
/// Function to print a loop's contents as LLVM's text IR assembly.
void printLoop(Loop &L, raw_ostream &OS, const std::string &Banner = "");
/// Find and return the loop attribute node for the attribute @p Name in
/// @p LoopID. Return nullptr if there is no such attribute.
MDNode *findOptionMDForLoopID(MDNode *LoopID, StringRef Name);
/// Find string metadata for a loop.
///
/// Returns the MDNode where the first operand is the metadata's name. The
/// following operands are the metadata's values. If no metadata with @p Name is
/// found, return nullptr.
MDNode *findOptionMDForLoop(const Loop *TheLoop, StringRef Name);
/// Return whether an MDNode might represent an access group.
///
/// Access group metadata nodes have to be distinct and empty. Being
/// always-empty ensures that it never needs to be changed (which -- because
/// MDNodes are designed immutable -- would require creating a new MDNode). Note
/// that this is not a sufficient condition: not every distinct and empty NDNode
/// is representing an access group.
bool isValidAsAccessGroup(MDNode *AccGroup);
} // End llvm namespace
#endif

View file

@ -392,7 +392,10 @@ void LoopBase<BlockT, LoopT>::verifyLoopNest(
template <class BlockT, class LoopT>
void LoopBase<BlockT, LoopT>::print(raw_ostream &OS, unsigned Depth,
bool Verbose) const {
OS.indent(Depth * 2) << "Loop at depth " << getLoopDepth() << " containing: ";
OS.indent(Depth * 2);
if (static_cast<const LoopT *>(this)->isAnnotatedParallel())
OS << "Parallel ";
OS << "Loop at depth " << getLoopDepth() << " containing: ";
BlockT *H = getHeader();
for (unsigned i = 0; i < getBlocks().size(); ++i) {
@ -640,8 +643,8 @@ void LoopInfoBase<BlockT, LoopT>::print(raw_ostream &OS) const {
template <typename T>
bool compareVectors(std::vector<T> &BB1, std::vector<T> &BB2) {
llvm::sort(BB1.begin(), BB1.end());
llvm::sort(BB2.begin(), BB2.end());
llvm::sort(BB1);
llvm::sort(BB2);
return BB1 == BB2;
}

View file

@ -37,7 +37,6 @@
namespace llvm {
class AssumptionCache;
class CallSite;
class DominatorTree;
class Function;
class Instruction;
@ -304,7 +303,7 @@ private:
/// The maximum size of the dereferences of the pointer.
///
/// May be UnknownSize if the sizes are unknown.
LocationSize Size = MemoryLocation::UnknownSize;
LocationSize Size = LocationSize::unknown();
/// The AA tags associated with dereferences of the pointer.
///
/// The members may be null if there are no tags or conflicting tags.
@ -398,7 +397,7 @@ public:
/// invalidated on the next non-local query or when an instruction is
/// removed. Clients must copy this data if they want it around longer than
/// that.
const NonLocalDepInfo &getNonLocalCallDependency(CallSite QueryCS);
const NonLocalDepInfo &getNonLocalCallDependency(CallBase *QueryCall);
/// Perform a full dependency query for an access to the QueryInst's
/// specified memory location, returning the set of instructions that either
@ -482,9 +481,9 @@ public:
void releaseMemory();
private:
MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall,
BasicBlock::iterator ScanIt,
BasicBlock *BB);
MemDepResult getCallDependencyFrom(CallBase *Call, bool isReadOnlyCall,
BasicBlock::iterator ScanIt,
BasicBlock *BB);
bool getNonLocalPointerDepFromBB(Instruction *QueryInst,
const PHITransAddr &Pointer,
const MemoryLocation &Loc, bool isLoad,

View file

@ -16,9 +16,9 @@
#ifndef LLVM_ANALYSIS_MEMORYLOCATION_H
#define LLVM_ANALYSIS_MEMORYLOCATION_H
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/IR/CallSite.h"
#include "llvm/ADT/Optional.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Metadata.h"
namespace llvm {
@ -34,8 +34,134 @@ class AnyMemIntrinsic;
class TargetLibraryInfo;
// Represents the size of a MemoryLocation. Logically, it's an
// Optional<uint64_t>, with a special UnknownSize value from `MemoryLocation`.
using LocationSize = uint64_t;
// Optional<uint63_t> that also carries a bit to represent whether the integer
// it contains, N, is 'precise'. Precise, in this context, means that we know
// that the area of storage referenced by the given MemoryLocation must be
// precisely N bytes. An imprecise value is formed as the union of two or more
// precise values, and can conservatively represent all of the values unioned
// into it. Importantly, imprecise values are an *upper-bound* on the size of a
// MemoryLocation.
//
// Concretely, a precise MemoryLocation is (%p, 4) in
// store i32 0, i32* %p
//
// Since we know that %p must be at least 4 bytes large at this point.
// Otherwise, we have UB. An example of an imprecise MemoryLocation is (%p, 4)
// at the memcpy in
//
// %n = select i1 %foo, i64 1, i64 4
// call void @llvm.memcpy.p0i8.p0i8.i64(i8* %p, i8* %baz, i64 %n, i32 1,
// i1 false)
//
// ...Since we'll copy *up to* 4 bytes into %p, but we can't guarantee that
// we'll ever actually do so.
//
// If asked to represent a pathologically large value, this will degrade to
// None.
class LocationSize {
enum : uint64_t {
Unknown = ~uint64_t(0),
ImpreciseBit = uint64_t(1) << 63,
MapEmpty = Unknown - 1,
MapTombstone = Unknown - 2,
// The maximum value we can represent without falling back to 'unknown'.
MaxValue = (MapTombstone - 1) & ~ImpreciseBit,
};
uint64_t Value;
// Hack to support implicit construction. This should disappear when the
// public LocationSize ctor goes away.
enum DirectConstruction { Direct };
constexpr LocationSize(uint64_t Raw, DirectConstruction): Value(Raw) {}
static_assert(Unknown & ImpreciseBit, "Unknown is imprecise by definition.");
public:
// FIXME: Migrate all users to construct via either `precise` or `upperBound`,
// to make it more obvious at the callsite the kind of size that they're
// providing.
//
// Since the overwhelming majority of users of this provide precise values,
// this assumes the provided value is precise.
constexpr LocationSize(uint64_t Raw)
: Value(Raw > MaxValue ? Unknown : Raw) {}
static LocationSize precise(uint64_t Value) { return LocationSize(Value); }
static LocationSize upperBound(uint64_t Value) {
// You can't go lower than 0, so give a precise result.
if (LLVM_UNLIKELY(Value == 0))
return precise(0);
if (LLVM_UNLIKELY(Value > MaxValue))
return unknown();
return LocationSize(Value | ImpreciseBit, Direct);
}
constexpr static LocationSize unknown() {
return LocationSize(Unknown, Direct);
}
// Sentinel values, generally used for maps.
constexpr static LocationSize mapTombstone() {
return LocationSize(MapTombstone, Direct);
}
constexpr static LocationSize mapEmpty() {
return LocationSize(MapEmpty, Direct);
}
// Returns a LocationSize that can correctly represent either `*this` or
// `Other`.
LocationSize unionWith(LocationSize Other) const {
if (Other == *this)
return *this;
if (!hasValue() || !Other.hasValue())
return unknown();
return upperBound(std::max(getValue(), Other.getValue()));
}
bool hasValue() const { return Value != Unknown; }
uint64_t getValue() const {
assert(hasValue() && "Getting value from an unknown LocationSize!");
return Value & ~ImpreciseBit;
}
// Returns whether or not this value is precise. Note that if a value is
// precise, it's guaranteed to not be `unknown()`.
bool isPrecise() const {
return (Value & ImpreciseBit) == 0;
}
// Convenience method to check if this LocationSize's value is 0.
bool isZero() const { return hasValue() && getValue() == 0; }
bool operator==(const LocationSize &Other) const {
return Value == Other.Value;
}
bool operator!=(const LocationSize &Other) const {
return !(*this == Other);
}
// Ordering operators are not provided, since it's unclear if there's only one
// reasonable way to compare:
// - values that don't exist against values that do, and
// - precise values to imprecise values
void print(raw_ostream &OS) const;
// Returns an opaque value that represents this LocationSize. Cannot be
// reliably converted back into a LocationSize.
uint64_t toRaw() const { return Value; }
};
inline raw_ostream &operator<<(raw_ostream &OS, LocationSize Size) {
Size.print(OS);
return OS;
}
/// Representation for a specific memory location.
///
@ -108,11 +234,15 @@ public:
static MemoryLocation getForDest(const AnyMemIntrinsic *MI);
/// Return a location representing a particular argument of a call.
static MemoryLocation getForArgument(ImmutableCallSite CS, unsigned ArgIdx,
const TargetLibraryInfo &TLI);
static MemoryLocation getForArgument(const CallBase *Call, unsigned ArgIdx,
const TargetLibraryInfo *TLI);
static MemoryLocation getForArgument(const CallBase *Call, unsigned ArgIdx,
const TargetLibraryInfo &TLI) {
return getForArgument(Call, ArgIdx, &TLI);
}
explicit MemoryLocation(const Value *Ptr = nullptr,
LocationSize Size = UnknownSize,
LocationSize Size = LocationSize::unknown(),
const AAMDNodes &AATags = AAMDNodes())
: Ptr(Ptr), Size(Size), AATags(AATags) {}
@ -139,13 +269,30 @@ public:
}
};
// Specialize DenseMapInfo for MemoryLocation.
// Specialize DenseMapInfo.
template <> struct DenseMapInfo<LocationSize> {
static inline LocationSize getEmptyKey() {
return LocationSize::mapEmpty();
}
static inline LocationSize getTombstoneKey() {
return LocationSize::mapTombstone();
}
static unsigned getHashValue(const LocationSize &Val) {
return DenseMapInfo<uint64_t>::getHashValue(Val.toRaw());
}
static bool isEqual(const LocationSize &LHS, const LocationSize &RHS) {
return LHS == RHS;
}
};
template <> struct DenseMapInfo<MemoryLocation> {
static inline MemoryLocation getEmptyKey() {
return MemoryLocation(DenseMapInfo<const Value *>::getEmptyKey(), 0);
return MemoryLocation(DenseMapInfo<const Value *>::getEmptyKey(),
DenseMapInfo<LocationSize>::getEmptyKey());
}
static inline MemoryLocation getTombstoneKey() {
return MemoryLocation(DenseMapInfo<const Value *>::getTombstoneKey(), 0);
return MemoryLocation(DenseMapInfo<const Value *>::getTombstoneKey(),
DenseMapInfo<LocationSize>::getTombstoneKey());
}
static unsigned getHashValue(const MemoryLocation &Val) {
return DenseMapInfo<const Value *>::getHashValue(Val.Ptr) ^

View file

@ -280,9 +280,10 @@ protected:
friend class MemorySSAUpdater;
MemoryUseOrDef(LLVMContext &C, MemoryAccess *DMA, unsigned Vty,
DeleteValueTy DeleteValue, Instruction *MI, BasicBlock *BB)
: MemoryAccess(C, Vty, DeleteValue, BB, 1), MemoryInstruction(MI),
OptimizedAccessAlias(MayAlias) {
DeleteValueTy DeleteValue, Instruction *MI, BasicBlock *BB,
unsigned NumOperands)
: MemoryAccess(C, Vty, DeleteValue, BB, NumOperands),
MemoryInstruction(MI), OptimizedAccessAlias(MayAlias) {
setDefiningAccess(DMA);
}
@ -308,11 +309,6 @@ private:
Optional<AliasResult> OptimizedAccessAlias;
};
template <>
struct OperandTraits<MemoryUseOrDef>
: public FixedNumOperandTraits<MemoryUseOrDef, 1> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUseOrDef, MemoryAccess)
/// Represents read-only accesses to memory
///
/// In particular, the set of Instructions that will be represented by
@ -323,7 +319,8 @@ public:
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
MemoryUse(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB)
: MemoryUseOrDef(C, DMA, MemoryUseVal, deleteMe, MI, BB) {}
: MemoryUseOrDef(C, DMA, MemoryUseVal, deleteMe, MI, BB,
/*NumOperands=*/1) {}
// allocate space for exactly one operand
void *operator new(size_t s) { return User::operator new(s, 1); }
@ -381,31 +378,33 @@ public:
MemoryDef(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB,
unsigned Ver)
: MemoryUseOrDef(C, DMA, MemoryDefVal, deleteMe, MI, BB), ID(Ver) {}
: MemoryUseOrDef(C, DMA, MemoryDefVal, deleteMe, MI, BB,
/*NumOperands=*/2),
ID(Ver) {}
// allocate space for exactly one operand
void *operator new(size_t s) { return User::operator new(s, 1); }
// allocate space for exactly two operands
void *operator new(size_t s) { return User::operator new(s, 2); }
static bool classof(const Value *MA) {
return MA->getValueID() == MemoryDefVal;
}
void setOptimized(MemoryAccess *MA) {
Optimized = MA;
OptimizedID = getDefiningAccess()->getID();
setOperand(1, MA);
OptimizedID = MA->getID();
}
MemoryAccess *getOptimized() const {
return cast_or_null<MemoryAccess>(Optimized);
return cast_or_null<MemoryAccess>(getOperand(1));
}
bool isOptimized() const {
return getOptimized() && getDefiningAccess() &&
OptimizedID == getDefiningAccess()->getID();
return getOptimized() && OptimizedID == getOptimized()->getID();
}
void resetOptimized() {
OptimizedID = INVALID_MEMORYACCESS_ID;
setOperand(1, nullptr);
}
void print(raw_ostream &OS) const;
@ -417,13 +416,34 @@ private:
const unsigned ID;
unsigned OptimizedID = INVALID_MEMORYACCESS_ID;
WeakVH Optimized;
};
template <>
struct OperandTraits<MemoryDef> : public FixedNumOperandTraits<MemoryDef, 1> {};
struct OperandTraits<MemoryDef> : public FixedNumOperandTraits<MemoryDef, 2> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryDef, MemoryAccess)
template <>
struct OperandTraits<MemoryUseOrDef> {
static Use *op_begin(MemoryUseOrDef *MUD) {
if (auto *MU = dyn_cast<MemoryUse>(MUD))
return OperandTraits<MemoryUse>::op_begin(MU);
return OperandTraits<MemoryDef>::op_begin(cast<MemoryDef>(MUD));
}
static Use *op_end(MemoryUseOrDef *MUD) {
if (auto *MU = dyn_cast<MemoryUse>(MUD))
return OperandTraits<MemoryUse>::op_end(MU);
return OperandTraits<MemoryDef>::op_end(cast<MemoryDef>(MUD));
}
static unsigned operands(const MemoryUseOrDef *MUD) {
if (const auto *MU = dyn_cast<MemoryUse>(MUD))
return OperandTraits<MemoryUse>::operands(MU);
return OperandTraits<MemoryDef>::operands(cast<MemoryDef>(MUD));
}
};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUseOrDef, MemoryAccess)
/// Represents phi nodes for memory accesses.
///
/// These have the same semantic as regular phi nodes, with the exception that
@ -684,13 +704,19 @@ public:
~MemorySSA();
MemorySSAWalker *getWalker();
MemorySSAWalker *getSkipSelfWalker();
/// Given a memory Mod/Ref'ing instruction, get the MemorySSA
/// access associated with it. If passed a basic block gets the memory phi
/// node that exists for that block, if there is one. Otherwise, this will get
/// a MemoryUseOrDef.
MemoryUseOrDef *getMemoryAccess(const Instruction *) const;
MemoryPhi *getMemoryAccess(const BasicBlock *BB) const;
MemoryUseOrDef *getMemoryAccess(const Instruction *I) const {
return cast_or_null<MemoryUseOrDef>(ValueToMemoryAccess.lookup(I));
}
MemoryPhi *getMemoryAccess(const BasicBlock *BB) const {
return cast_or_null<MemoryPhi>(ValueToMemoryAccess.lookup(cast<Value>(BB)));
}
void dump() const;
void print(raw_ostream &) const;
@ -750,6 +776,9 @@ public:
/// all uses, uses appear in the right places). This is used by unit tests.
void verifyMemorySSA() const;
/// Check clobber sanity for an access.
void checkClobberSanityAccess(const MemoryAccess *MA) const;
/// Used in various insertion functions to specify whether we are talking
/// about the beginning or end of a block.
enum InsertionPlace { Beginning, End };
@ -764,6 +793,7 @@ protected:
void verifyDomination(Function &F) const;
void verifyOrdering(Function &F) const;
void verifyDominationNumbers(const Function &F) const;
void verifyClobberSanity(const Function &F) const;
// This is used by the use optimizer and updater.
AccessList *getWritableBlockAccesses(const BasicBlock *BB) const {
@ -796,16 +826,20 @@ protected:
InsertionPlace);
void insertIntoListsBefore(MemoryAccess *, const BasicBlock *,
AccessList::iterator);
MemoryUseOrDef *createDefinedAccess(Instruction *, MemoryAccess *);
MemoryUseOrDef *createDefinedAccess(Instruction *, MemoryAccess *,
const MemoryUseOrDef *Template = nullptr);
private:
class ClobberWalkerBase;
class CachingWalker;
class SkipSelfWalker;
class OptimizeUses;
CachingWalker *getWalkerImpl();
void buildMemorySSA();
void optimizeUses();
void prepareForMoveTo(MemoryAccess *, BasicBlock *);
void verifyUseInDefs(MemoryAccess *, MemoryAccess *) const;
using AccessMap = DenseMap<const BasicBlock *, std::unique_ptr<AccessList>>;
@ -816,7 +850,8 @@ private:
void markUnreachableAsLiveOnEntry(BasicBlock *BB);
bool dominatesUse(const MemoryAccess *, const MemoryAccess *) const;
MemoryPhi *createMemoryPhi(BasicBlock *BB);
MemoryUseOrDef *createNewAccess(Instruction *);
MemoryUseOrDef *createNewAccess(Instruction *,
const MemoryUseOrDef *Template = nullptr);
MemoryAccess *findDominatingDef(BasicBlock *, enum InsertionPlace);
void placePHINodes(const SmallPtrSetImpl<BasicBlock *> &);
MemoryAccess *renameBlock(BasicBlock *, MemoryAccess *, bool);
@ -851,7 +886,9 @@ private:
mutable DenseMap<const MemoryAccess *, unsigned long> BlockNumbering;
// Memory SSA building info
std::unique_ptr<ClobberWalkerBase> WalkerBase;
std::unique_ptr<CachingWalker> Walker;
std::unique_ptr<SkipSelfWalker> SkipWalker;
unsigned NextID;
};

View file

@ -35,8 +35,11 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopIterator.h"
#include "llvm/Analysis/MemorySSA.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFGDiff.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/OperandTraits.h"
@ -45,6 +48,7 @@
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/IR/ValueMap.h"
#include "llvm/Pass.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
@ -57,6 +61,12 @@ class MemoryAccess;
class LLVMContext;
class raw_ostream;
using ValueToValueMapTy = ValueMap<const Value *, WeakTrackingVH>;
using PhiToDefMap = SmallDenseMap<MemoryPhi *, MemoryAccess *>;
using CFGUpdate = cfg::Update<BasicBlock *>;
using GraphDiffInvBBPair =
std::pair<const GraphDiff<BasicBlock *> *, Inverse<BasicBlock *>>;
class MemorySSAUpdater {
private:
MemorySSA *MSSA;
@ -70,6 +80,7 @@ private:
public:
MemorySSAUpdater(MemorySSA *MSSA) : MSSA(MSSA) {}
/// Insert a definition into the MemorySSA IR. RenameUses will rename any use
/// below the new def block (and any inserted phis). RenameUses should be set
/// to true if the definition may cause new aliases for loads below it. This
@ -89,15 +100,48 @@ public:
/// Where a mayalias b, *does* require RenameUses be set to true.
void insertDef(MemoryDef *Def, bool RenameUses = false);
void insertUse(MemoryUse *Use);
/// Update the MemoryPhi in `To` following an edge deletion between `From` and
/// `To`. If `To` becomes unreachable, a call to removeBlocks should be made.
void removeEdge(BasicBlock *From, BasicBlock *To);
/// Update the MemoryPhi in `To` to have a single incoming edge from `From`,
/// following a CFG change that replaced multiple edges (switch) with a direct
/// branch.
void removeDuplicatePhiEdgesBetween(BasicBlock *From, BasicBlock *To);
/// Update MemorySSA after a loop was cloned, given the blocks in RPO order,
/// the exit blocks and a 1:1 mapping of all blocks and instructions
/// cloned. This involves duplicating all defs and uses in the cloned blocks
/// Updating phi nodes in exit block successors is done separately.
void updateForClonedLoop(const LoopBlocksRPO &LoopBlocks,
ArrayRef<BasicBlock *> ExitBlocks,
const ValueToValueMapTy &VM,
bool IgnoreIncomingWithNoClones = false);
// Block BB was fully or partially cloned into its predecessor P1. Map
// contains the 1:1 mapping of instructions cloned and VM[BB]=P1.
void updateForClonedBlockIntoPred(BasicBlock *BB, BasicBlock *P1,
const ValueToValueMapTy &VM);
/// Update phi nodes in exit block successors following cloning. Exit blocks
/// that were not cloned don't have additional predecessors added.
void updateExitBlocksForClonedLoop(ArrayRef<BasicBlock *> ExitBlocks,
const ValueToValueMapTy &VMap,
DominatorTree &DT);
void updateExitBlocksForClonedLoop(
ArrayRef<BasicBlock *> ExitBlocks,
ArrayRef<std::unique_ptr<ValueToValueMapTy>> VMaps, DominatorTree &DT);
/// Apply CFG updates, analogous with the DT edge updates.
void applyUpdates(ArrayRef<CFGUpdate> Updates, DominatorTree &DT);
/// Apply CFG insert updates, analogous with the DT edge updates.
void applyInsertUpdates(ArrayRef<CFGUpdate> Updates, DominatorTree &DT);
void moveBefore(MemoryUseOrDef *What, MemoryUseOrDef *Where);
void moveAfter(MemoryUseOrDef *What, MemoryUseOrDef *Where);
void moveToPlace(MemoryUseOrDef *What, BasicBlock *BB,
MemorySSA::InsertionPlace Where);
/// `From` block was spliced into `From` and `To`.
/// Move all accesses from `From` to `To` starting at instruction `Start`.
/// `To` is newly created BB, so empty of MemorySSA::MemoryAccesses.
/// Edges are already updated, so successors of `To` with MPhi nodes need to
/// update incoming block.
/// `From` block was spliced into `From` and `To`. There is a CFG edge from
/// `From` to `To`. Move all accesses from `From` to `To` starting at
/// instruction `Start`. `To` is newly created BB, so empty of
/// MemorySSA::MemoryAccesses. Edges are already updated, so successors of
/// `To` with MPhi nodes need to update incoming block.
/// |------| |------|
/// | From | | From |
/// | | |------|
@ -108,12 +152,12 @@ public:
/// |------| |------|
void moveAllAfterSpliceBlocks(BasicBlock *From, BasicBlock *To,
Instruction *Start);
/// `From` block was merged into `To`. All instructions were moved and
/// `From` is an empty block with successor edges; `From` is about to be
/// deleted. Move all accesses from `From` to `To` starting at instruction
/// `Start`. `To` may have multiple successors, `From` has a single
/// predecessor. `From` may have successors with MPhi nodes, replace their
/// incoming block with `To`.
/// `From` block was merged into `To`. There is a CFG edge from `To` to
/// `From`.`To` still branches to `From`, but all instructions were moved and
/// `From` is now an empty block; `From` is about to be deleted. Move all
/// accesses from `From` to `To` starting at instruction `Start`. `To` may
/// have multiple successors, `From` has a single predecessor. `From` may have
/// successors with MPhi nodes, replace their incoming block with `To`.
/// |------| |------|
/// | To | | To |
/// |------| | |
@ -124,15 +168,14 @@ public:
/// |------| |------|
void moveAllAfterMergeBlocks(BasicBlock *From, BasicBlock *To,
Instruction *Start);
/// BasicBlock Old had New, an empty BasicBlock, added directly before it,
/// and the predecessors in Preds that used to point to Old, now point to
/// New. If New is the only predecessor, move Old's Phi, if present, to New.
/// A new empty BasicBlock (New) now branches directly to Old. Some of
/// Old's predecessors (Preds) are now branching to New instead of Old.
/// If New is the only predecessor, move Old's Phi, if present, to New.
/// Otherwise, add a new Phi in New with appropriate incoming values, and
/// update the incoming values in Old's Phi node too, if present.
void
wireOldPredecessorsToNewImmediatePredecessor(BasicBlock *Old, BasicBlock *New,
ArrayRef<BasicBlock *> Preds);
void wireOldPredecessorsToNewImmediatePredecessor(
BasicBlock *Old, BasicBlock *New, ArrayRef<BasicBlock *> Preds,
bool IdenticalEdgesWereMerged = true);
// The below are utility functions. Other than creation of accesses to pass
// to insertDef, and removeAccess to remove accesses, you should generally
// not attempt to update memoryssa yourself. It is very non-trivial to get
@ -220,6 +263,23 @@ private:
template <class RangeType>
MemoryAccess *tryRemoveTrivialPhi(MemoryPhi *Phi, RangeType &Operands);
void fixupDefs(const SmallVectorImpl<WeakVH> &);
// Clone all uses and defs from BB to NewBB given a 1:1 map of all
// instructions and blocks cloned, and a map of MemoryPhi : Definition
// (MemoryAccess Phi or Def). VMap maps old instructions to cloned
// instructions and old blocks to cloned blocks. MPhiMap, is created in the
// caller of this private method, and maps existing MemoryPhis to new
// definitions that new MemoryAccesses must point to. These definitions may
// not necessarily be MemoryPhis themselves, they may be MemoryDefs. As such,
// the map is between MemoryPhis and MemoryAccesses, where the MemoryAccesses
// may be MemoryPhis or MemoryDefs and not MemoryUses.
void cloneUsesAndDefs(BasicBlock *BB, BasicBlock *NewBB,
const ValueToValueMapTy &VMap, PhiToDefMap &MPhiMap);
template <typename Iter>
void privateUpdateExitBlocksForClonedLoop(ArrayRef<BasicBlock *> ExitBlocks,
Iter ValuesBegin, Iter ValuesEnd,
DominatorTree &DT);
void applyInsertUpdates(ArrayRef<CFGUpdate>, DominatorTree &DT,
const GraphDiff<BasicBlock *> *GD);
};
} // end namespace llvm

View file

@ -19,6 +19,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/Analysis/EHPersonalities.h"
#include "llvm/Analysis/InstructionPrecedenceTracking.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Dominators.h"
@ -31,33 +32,138 @@ class DominatorTree;
class Loop;
/// Captures loop safety information.
/// It keep information for loop & its header may throw exception or otherwise
/// It keep information for loop blocks may throw exception or otherwise
/// exit abnormaly on any iteration of the loop which might actually execute
/// at runtime. The primary way to consume this infromation is via
/// isGuaranteedToExecute below, but some callers bailout or fallback to
/// alternate reasoning if a loop contains any implicit control flow.
struct LoopSafetyInfo {
bool MayThrow = false; // The current loop contains an instruction which
// may throw.
bool HeaderMayThrow = false; // Same as previous, but specific to loop header
/// NOTE: LoopSafetyInfo contains cached information regarding loops and their
/// particular blocks. This information is only dropped on invocation of
/// computeLoopSafetyInfo. If the loop or any of its block is deleted, or if
/// any thrower instructions have been added or removed from them, or if the
/// control flow has changed, or in case of other meaningful modifications, the
/// LoopSafetyInfo needs to be recomputed. If a meaningful modifications to the
/// loop were made and the info wasn't recomputed properly, the behavior of all
/// methods except for computeLoopSafetyInfo is undefined.
class LoopSafetyInfo {
// Used to update funclet bundle operands.
DenseMap<BasicBlock *, ColorVector> BlockColors;
protected:
/// Computes block colors.
void computeBlockColors(const Loop *CurLoop);
public:
/// Returns block colors map that is used to update funclet operand bundles.
const DenseMap<BasicBlock *, ColorVector> &getBlockColors() const;
/// Copy colors of block \p Old into the block \p New.
void copyColors(BasicBlock *New, BasicBlock *Old);
/// Returns true iff the block \p BB potentially may throw exception. It can
/// be false-positive in cases when we want to avoid complex analysis.
virtual bool blockMayThrow(const BasicBlock *BB) const = 0;
/// Returns true iff any block of the loop for which this info is contains an
/// instruction that may throw or otherwise exit abnormally.
virtual bool anyBlockMayThrow() const = 0;
/// Return true if we must reach the block \p BB under assumption that the
/// loop \p CurLoop is entered.
bool allLoopPathsLeadToBlock(const Loop *CurLoop, const BasicBlock *BB,
const DominatorTree *DT) const;
/// Computes safety information for a loop checks loop body & header for
/// the possibility of may throw exception, it takes LoopSafetyInfo and loop
/// as argument. Updates safety information in LoopSafetyInfo argument.
/// Note: This is defined to clear and reinitialize an already initialized
/// LoopSafetyInfo. Some callers rely on this fact.
virtual void computeLoopSafetyInfo(const Loop *CurLoop) = 0;
/// Returns true if the instruction in a loop is guaranteed to execute at
/// least once (under the assumption that the loop is entered).
virtual bool isGuaranteedToExecute(const Instruction &Inst,
const DominatorTree *DT,
const Loop *CurLoop) const = 0;
LoopSafetyInfo() = default;
virtual ~LoopSafetyInfo() = default;
};
/// Computes safety information for a loop checks loop body & header for
/// the possibility of may throw exception, it takes LoopSafetyInfo and loop as
/// argument. Updates safety information in LoopSafetyInfo argument.
/// Note: This is defined to clear and reinitialize an already initialized
/// LoopSafetyInfo. Some callers rely on this fact.
void computeLoopSafetyInfo(LoopSafetyInfo *, Loop *);
/// Returns true if the instruction in a loop is guaranteed to execute at least
/// once (under the assumption that the loop is entered).
bool isGuaranteedToExecute(const Instruction &Inst, const DominatorTree *DT,
const Loop *CurLoop,
const LoopSafetyInfo *SafetyInfo);
/// Simple and conservative implementation of LoopSafetyInfo that can give
/// false-positive answers to its queries in order to avoid complicated
/// analysis.
class SimpleLoopSafetyInfo: public LoopSafetyInfo {
bool MayThrow = false; // The current loop contains an instruction which
// may throw.
bool HeaderMayThrow = false; // Same as previous, but specific to loop header
public:
virtual bool blockMayThrow(const BasicBlock *BB) const;
virtual bool anyBlockMayThrow() const;
virtual void computeLoopSafetyInfo(const Loop *CurLoop);
virtual bool isGuaranteedToExecute(const Instruction &Inst,
const DominatorTree *DT,
const Loop *CurLoop) const;
SimpleLoopSafetyInfo() : LoopSafetyInfo() {};
virtual ~SimpleLoopSafetyInfo() {};
};
/// This implementation of LoopSafetyInfo use ImplicitControlFlowTracking to
/// give precise answers on "may throw" queries. This implementation uses cache
/// that should be invalidated by calling the methods insertInstructionTo and
/// removeInstruction whenever we modify a basic block's contents by adding or
/// removing instructions.
class ICFLoopSafetyInfo: public LoopSafetyInfo {
bool MayThrow = false; // The current loop contains an instruction which
// may throw.
// Contains information about implicit control flow in this loop's blocks.
mutable ImplicitControlFlowTracking ICF;
// Contains information about instruction that may possibly write memory.
mutable MemoryWriteTracking MW;
public:
virtual bool blockMayThrow(const BasicBlock *BB) const;
virtual bool anyBlockMayThrow() const;
virtual void computeLoopSafetyInfo(const Loop *CurLoop);
virtual bool isGuaranteedToExecute(const Instruction &Inst,
const DominatorTree *DT,
const Loop *CurLoop) const;
/// Returns true if we could not execute a memory-modifying instruction before
/// we enter \p BB under assumption that \p CurLoop is entered.
bool doesNotWriteMemoryBefore(const BasicBlock *BB, const Loop *CurLoop)
const;
/// Returns true if we could not execute a memory-modifying instruction before
/// we execute \p I under assumption that \p CurLoop is entered.
bool doesNotWriteMemoryBefore(const Instruction &I, const Loop *CurLoop)
const;
/// Inform the safety info that we are planning to insert a new instruction
/// \p Inst into the basic block \p BB. It will make all cache updates to keep
/// it correct after this insertion.
void insertInstructionTo(const Instruction *Inst, const BasicBlock *BB);
/// Inform safety info that we are planning to remove the instruction \p Inst
/// from its block. It will make all cache updates to keep it correct after
/// this removal.
void removeInstruction(const Instruction *Inst);
ICFLoopSafetyInfo(DominatorTree *DT) : LoopSafetyInfo(), ICF(DT), MW(DT) {};
virtual ~ICFLoopSafetyInfo() {};
};
}

View file

@ -60,7 +60,7 @@ public:
FunctionModRefBehavior getModRefBehavior(const Function *F);
using AAResultBase::getModRefInfo;
ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc);
ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc);
};
/// Analysis pass providing a never-invalidated alias analysis result.

View file

@ -51,25 +51,25 @@ extern bool EnableARCOpts;
/// on.
inline bool ModuleHasARC(const Module &M) {
return
M.getNamedValue("objc_retain") ||
M.getNamedValue("objc_release") ||
M.getNamedValue("objc_autorelease") ||
M.getNamedValue("objc_retainAutoreleasedReturnValue") ||
M.getNamedValue("objc_unsafeClaimAutoreleasedReturnValue") ||
M.getNamedValue("objc_retainBlock") ||
M.getNamedValue("objc_autoreleaseReturnValue") ||
M.getNamedValue("objc_autoreleasePoolPush") ||
M.getNamedValue("objc_loadWeakRetained") ||
M.getNamedValue("objc_loadWeak") ||
M.getNamedValue("objc_destroyWeak") ||
M.getNamedValue("objc_storeWeak") ||
M.getNamedValue("objc_initWeak") ||
M.getNamedValue("objc_moveWeak") ||
M.getNamedValue("objc_copyWeak") ||
M.getNamedValue("objc_retainedObject") ||
M.getNamedValue("objc_unretainedObject") ||
M.getNamedValue("objc_unretainedPointer") ||
M.getNamedValue("clang.arc.use");
M.getNamedValue("llvm.objc.retain") ||
M.getNamedValue("llvm.objc.release") ||
M.getNamedValue("llvm.objc.autorelease") ||
M.getNamedValue("llvm.objc.retainAutoreleasedReturnValue") ||
M.getNamedValue("llvm.objc.unsafeClaimAutoreleasedReturnValue") ||
M.getNamedValue("llvm.objc.retainBlock") ||
M.getNamedValue("llvm.objc.autoreleaseReturnValue") ||
M.getNamedValue("llvm.objc.autoreleasePoolPush") ||
M.getNamedValue("llvm.objc.loadWeakRetained") ||
M.getNamedValue("llvm.objc.loadWeak") ||
M.getNamedValue("llvm.objc.destroyWeak") ||
M.getNamedValue("llvm.objc.storeWeak") ||
M.getNamedValue("llvm.objc.initWeak") ||
M.getNamedValue("llvm.objc.moveWeak") ||
M.getNamedValue("llvm.objc.copyWeak") ||
M.getNamedValue("llvm.objc.retainedObject") ||
M.getNamedValue("llvm.objc.unretainedObject") ||
M.getNamedValue("llvm.objc.unretainedPointer") ||
M.getNamedValue("llvm.objc.clang.arc.use");
}
/// This is a wrapper around getUnderlyingObject which also knows how to

View file

@ -11,6 +11,7 @@
#define LLVM_ANALYSIS_OBJCARCINSTKIND_H
#include "llvm/IR/Function.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Instructions.h"
namespace llvm {
@ -48,7 +49,7 @@ enum class ARCInstKind {
CopyWeak, ///< objc_copyWeak (derived)
DestroyWeak, ///< objc_destroyWeak (derived)
StoreStrong, ///< objc_storeStrong (derived)
IntrinsicUser, ///< clang.arc.use
IntrinsicUser, ///< llvm.objc.clang.arc.use
CallOrUser, ///< could call objc_release and/or "use" pointers
Call, ///< could call objc_release
User, ///< could "use" a pointer

View file

@ -17,8 +17,8 @@
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TRANSFORMS_UTILS_ORDEREDINSTRUCTIONS_H
#define LLVM_TRANSFORMS_UTILS_ORDEREDINSTRUCTIONS_H
#ifndef LLVM_ANALYSIS_ORDEREDINSTRUCTIONS_H
#define LLVM_ANALYSIS_ORDEREDINSTRUCTIONS_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/Analysis/OrderedBasicBlock.h"
@ -62,4 +62,4 @@ public:
} // end namespace llvm
#endif // LLVM_TRANSFORMS_UTILS_ORDEREDINSTRUCTIONS_H
#endif // LLVM_ANALYSIS_ORDEREDINSTRUCTIONS_H

View file

@ -61,10 +61,10 @@ namespace llvm {
//===--------------------------------------------------------------------===//
//
// createDivergenceAnalysisPass - This pass determines which branches in a GPU
// createLegacyDivergenceAnalysisPass - This pass determines which branches in a GPU
// program are divergent.
//
FunctionPass *createDivergenceAnalysisPass();
FunctionPass *createLegacyDivergenceAnalysisPass();
//===--------------------------------------------------------------------===//
//

View file

@ -88,6 +88,22 @@ private:
/// All values reachable from each component.
DenseMap<unsigned int, ConstValueSet> ReachableMap;
/// A CallbackVH to notify PhiValues when a value is deleted or replaced, so
/// that the cached information for that value can be cleared to avoid
/// dangling pointers to invalid values.
class PhiValuesCallbackVH final : public CallbackVH {
PhiValues *PV;
void deleted() override;
void allUsesReplacedWith(Value *New) override;
public:
PhiValuesCallbackVH(Value *V, PhiValues *PV = nullptr)
: CallbackVH(V), PV(PV) {}
};
/// A set of callbacks to the values that processPhi has seen.
DenseSet<PhiValuesCallbackVH, DenseMapInfo<Value *>> TrackedValues;
/// The function that the PhiValues is for.
const Function &F;

View file

@ -98,14 +98,14 @@ public:
bool isFunctionEntryCold(const Function *F);
/// Returns true if \p F contains only cold code.
bool isFunctionColdInCallGraph(const Function *F, BlockFrequencyInfo &BFI);
/// Returns true if \p F is a hot function.
/// Returns true if count \p C is considered hot.
bool isHotCount(uint64_t C);
/// Returns true if count \p C is considered cold.
bool isColdCount(uint64_t C);
/// Returns true if BasicBlock \p B is considered hot.
bool isHotBB(const BasicBlock *B, BlockFrequencyInfo *BFI);
/// Returns true if BasicBlock \p B is considered cold.
bool isColdBB(const BasicBlock *B, BlockFrequencyInfo *BFI);
/// Returns true if BasicBlock \p BB is considered hot.
bool isHotBlock(const BasicBlock *BB, BlockFrequencyInfo *BFI);
/// Returns true if BasicBlock \p BB is considered cold.
bool isColdBlock(const BasicBlock *BB, BlockFrequencyInfo *BFI);
/// Returns true if CallSite \p CS is considered hot.
bool isHotCallSite(const CallSite &CS, BlockFrequencyInfo *BFI);
/// Returns true if Callsite \p CS is considered cold.
@ -134,9 +134,8 @@ public:
static char ID;
ProfileSummaryInfoWrapperPass();
ProfileSummaryInfo *getPSI() {
return &*PSI;
}
ProfileSummaryInfo &getPSI() { return *PSI; }
const ProfileSummaryInfo &getPSI() const { return *PSI; }
bool doInitialization(Module &M) override;
bool doFinalization(Module &M) override;

View file

@ -1833,6 +1833,10 @@ private:
const SCEV *getOrCreateMulExpr(SmallVectorImpl<const SCEV *> &Ops,
SCEV::NoWrapFlags Flags);
// Get addrec expr already created or create a new one.
const SCEV *getOrCreateAddRecExpr(SmallVectorImpl<const SCEV *> &Ops,
const Loop *L, SCEV::NoWrapFlags Flags);
/// Return x if \p Val is f(x) where f is a 1-1 function.
const SCEV *stripInjectiveFunctions(const SCEV *Val) const;

View file

@ -16,7 +16,7 @@
#define LLVM_ANALYSIS_SCOPEDNOALIASAA_H
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
#include <memory>
@ -41,8 +41,8 @@ public:
}
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB);
ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc);
ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2);
ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc);
ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2);
private:
bool mayAliasInScopes(const MDNode *Scopes, const MDNode *NoAlias) const;

View file

@ -189,12 +189,12 @@ private:
/// getFeasibleSuccessors - Return a vector of booleans to indicate which
/// successors are reachable from a given terminator instruction.
void getFeasibleSuccessors(TerminatorInst &TI, SmallVectorImpl<bool> &Succs,
void getFeasibleSuccessors(Instruction &TI, SmallVectorImpl<bool> &Succs,
bool AggressiveUndef);
void visitInst(Instruction &I);
void visitPHINode(PHINode &I);
void visitTerminatorInst(TerminatorInst &TI);
void visitTerminator(Instruction &TI);
};
//===----------------------------------------------------------------------===//
@ -286,7 +286,7 @@ void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::markEdgeExecutable(
template <class LatticeKey, class LatticeVal, class KeyInfo>
void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::getFeasibleSuccessors(
TerminatorInst &TI, SmallVectorImpl<bool> &Succs, bool AggressiveUndef) {
Instruction &TI, SmallVectorImpl<bool> &Succs, bool AggressiveUndef) {
Succs.resize(TI.getNumSuccessors());
if (TI.getNumSuccessors() == 0)
return;
@ -330,7 +330,7 @@ void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::getFeasibleSuccessors(
return;
}
if (TI.isExceptional()) {
if (TI.isExceptionalTerminator()) {
Succs.assign(Succs.size(), true);
return;
}
@ -374,7 +374,7 @@ template <class LatticeKey, class LatticeVal, class KeyInfo>
bool SparseSolver<LatticeKey, LatticeVal, KeyInfo>::isEdgeFeasible(
BasicBlock *From, BasicBlock *To, bool AggressiveUndef) {
SmallVector<bool, 16> SuccFeasible;
TerminatorInst *TI = From->getTerminator();
Instruction *TI = From->getTerminator();
getFeasibleSuccessors(*TI, SuccFeasible, AggressiveUndef);
for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i)
@ -385,8 +385,8 @@ bool SparseSolver<LatticeKey, LatticeVal, KeyInfo>::isEdgeFeasible(
}
template <class LatticeKey, class LatticeVal, class KeyInfo>
void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::visitTerminatorInst(
TerminatorInst &TI) {
void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::visitTerminator(
Instruction &TI) {
SmallVector<bool, 16> SuccFeasible;
getFeasibleSuccessors(TI, SuccFeasible, true);
@ -465,8 +465,8 @@ void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::visitInst(Instruction &I) {
if (ChangedValue.second != LatticeFunc->getUntrackedVal())
UpdateState(ChangedValue.first, ChangedValue.second);
if (TerminatorInst *TI = dyn_cast<TerminatorInst>(&I))
visitTerminatorInst(*TI);
if (I.isTerminator())
visitTerminator(I);
}
template <class LatticeKey, class LatticeVal, class KeyInfo>

View file

@ -0,0 +1,120 @@
//===- StackSafetyAnalysis.h - Stack memory safety analysis -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Stack Safety Analysis detects allocas and arguments with safe access.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_STACKSAFETYANALYSIS_H
#define LLVM_ANALYSIS_STACKSAFETYANALYSIS_H
#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
namespace llvm {
/// Interface to access stack safety analysis results for single function.
class StackSafetyInfo {
public:
struct FunctionInfo;
private:
std::unique_ptr<FunctionInfo> Info;
public:
StackSafetyInfo();
StackSafetyInfo(FunctionInfo &&Info);
StackSafetyInfo(StackSafetyInfo &&);
StackSafetyInfo &operator=(StackSafetyInfo &&);
~StackSafetyInfo();
// TODO: Add useful for client methods.
void print(raw_ostream &O) const;
};
/// StackSafetyInfo wrapper for the new pass manager.
class StackSafetyAnalysis : public AnalysisInfoMixin<StackSafetyAnalysis> {
friend AnalysisInfoMixin<StackSafetyAnalysis>;
static AnalysisKey Key;
public:
using Result = StackSafetyInfo;
StackSafetyInfo run(Function &F, FunctionAnalysisManager &AM);
};
/// Printer pass for the \c StackSafetyAnalysis results.
class StackSafetyPrinterPass : public PassInfoMixin<StackSafetyPrinterPass> {
raw_ostream &OS;
public:
explicit StackSafetyPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
/// StackSafetyInfo wrapper for the legacy pass manager
class StackSafetyInfoWrapperPass : public FunctionPass {
StackSafetyInfo SSI;
public:
static char ID;
StackSafetyInfoWrapperPass();
const StackSafetyInfo &getResult() const { return SSI; }
void print(raw_ostream &O, const Module *M) const override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnFunction(Function &F) override;
};
using StackSafetyGlobalInfo = std::map<const GlobalValue *, StackSafetyInfo>;
/// This pass performs the global (interprocedural) stack safety analysis (new
/// pass manager).
class StackSafetyGlobalAnalysis
: public AnalysisInfoMixin<StackSafetyGlobalAnalysis> {
friend AnalysisInfoMixin<StackSafetyGlobalAnalysis>;
static AnalysisKey Key;
public:
using Result = StackSafetyGlobalInfo;
Result run(Module &M, ModuleAnalysisManager &AM);
};
/// Printer pass for the \c StackSafetyGlobalAnalysis results.
class StackSafetyGlobalPrinterPass
: public PassInfoMixin<StackSafetyGlobalPrinterPass> {
raw_ostream &OS;
public:
explicit StackSafetyGlobalPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
};
/// This pass performs the global (interprocedural) stack safety analysis
/// (legacy pass manager).
class StackSafetyGlobalInfoWrapperPass : public ModulePass {
StackSafetyGlobalInfo SSI;
public:
static char ID;
StackSafetyGlobalInfoWrapperPass();
const StackSafetyGlobalInfo &getResult() const { return SSI; }
void print(raw_ostream &O, const Module *M) const override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnModule(Module &M) override;
};
} // end namespace llvm
#endif // LLVM_ANALYSIS_STACKSAFETYANALYSIS_H

View file

@ -0,0 +1,86 @@
//===- SyncDependenceAnalysis.h - Divergent Branch Dependence -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// \file
// This file defines the SyncDependenceAnalysis class, which computes for
// every divergent branch the set of phi nodes that the branch will make
// divergent.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_SYNC_DEPENDENCE_ANALYSIS_H
#define LLVM_ANALYSIS_SYNC_DEPENDENCE_ANALYSIS_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/LoopInfo.h"
#include <memory>
namespace llvm {
class BasicBlock;
class DominatorTree;
class Loop;
class PostDominatorTree;
using ConstBlockSet = SmallPtrSet<const BasicBlock *, 4>;
/// \brief Relates points of divergent control to join points in
/// reducible CFGs.
///
/// This analysis relates points of divergent control to points of converging
/// divergent control. The analysis requires all loops to be reducible.
class SyncDependenceAnalysis {
void visitSuccessor(const BasicBlock &succBlock, const Loop *termLoop,
const BasicBlock *defBlock);
public:
bool inRegion(const BasicBlock &BB) const;
~SyncDependenceAnalysis();
SyncDependenceAnalysis(const DominatorTree &DT, const PostDominatorTree &PDT,
const LoopInfo &LI);
/// \brief Computes divergent join points and loop exits caused by branch
/// divergence in \p Term.
///
/// The set of blocks which are reachable by disjoint paths from \p Term.
/// The set also contains loop exits if there two disjoint paths:
/// one from \p Term to the loop exit and another from \p Term to the loop
/// header. Those exit blocks are added to the returned set.
/// If L is the parent loop of \p Term and an exit of L is in the returned
/// set then L is a divergent loop.
const ConstBlockSet &join_blocks(const Instruction &Term);
/// \brief Computes divergent join points and loop exits (in the surrounding
/// loop) caused by the divergent loop exits of\p Loop.
///
/// The set of blocks which are reachable by disjoint paths from the
/// loop exits of \p Loop.
/// This treats the loop as a single node in \p Loop's parent loop.
/// The returned set has the same properties as for join_blocks(TermInst&).
const ConstBlockSet &join_blocks(const Loop &Loop);
private:
static ConstBlockSet EmptyBlockSet;
ReversePostOrderTraversal<const Function *> FuncRPOT;
const DominatorTree &DT;
const PostDominatorTree &PDT;
const LoopInfo &LI;
std::map<const Loop *, std::unique_ptr<ConstBlockSet>> CachedLoopExitJoins;
std::map<const Instruction *, std::unique_ptr<ConstBlockSet>>
CachedBranchJoins;
};
} // namespace llvm
#endif // LLVM_ANALYSIS_SYNC_DEPENDENCE_ANALYSIS_H

View file

@ -36,16 +36,17 @@ public:
using EdgeRef = typename CGT::EdgeRef;
using SccTy = std::vector<NodeRef>;
using GetRelBBFreqTy = function_ref<Optional<Scaled64>(EdgeRef)>;
using GetCountTy = function_ref<uint64_t(NodeRef)>;
using AddCountTy = function_ref<void(NodeRef, uint64_t)>;
// Not all EdgeRef have information about the source of the edge. Hence
// NodeRef corresponding to the source of the EdgeRef is explicitly passed.
using GetProfCountTy = function_ref<Optional<Scaled64>(NodeRef, EdgeRef)>;
using AddCountTy = function_ref<void(NodeRef, Scaled64)>;
static void propagate(const CallGraphType &CG, GetRelBBFreqTy GetRelBBFreq,
GetCountTy GetCount, AddCountTy AddCount);
static void propagate(const CallGraphType &CG, GetProfCountTy GetProfCount,
AddCountTy AddCount);
private:
static void propagateFromSCC(const SccTy &SCC, GetRelBBFreqTy GetRelBBFreq,
GetCountTy GetCount, AddCountTy AddCount);
static void propagateFromSCC(const SccTy &SCC, GetProfCountTy GetProfCount,
AddCountTy AddCount);
};
} // namespace llvm

View file

@ -565,6 +565,30 @@ TLI_DEFINE_STRING_INTERNAL("cosl")
/// char *ctermid(char *s);
TLI_DEFINE_ENUM_INTERNAL(ctermid)
TLI_DEFINE_STRING_INTERNAL("ctermid")
/// int execl(const char *path, const char *arg, ...);
TLI_DEFINE_ENUM_INTERNAL(execl)
TLI_DEFINE_STRING_INTERNAL("execl")
/// int execle(const char *file, const char *arg, ..., char * const envp[]);
TLI_DEFINE_ENUM_INTERNAL(execle)
TLI_DEFINE_STRING_INTERNAL("execle")
/// int execlp(const char *file, const char *arg, ...);
TLI_DEFINE_ENUM_INTERNAL(execlp)
TLI_DEFINE_STRING_INTERNAL("execlp")
/// int execv(const char *path, char *const argv[]);
TLI_DEFINE_ENUM_INTERNAL(execv)
TLI_DEFINE_STRING_INTERNAL("execv")
/// int execvP(const char *file, const char *search_path, char *const argv[]);
TLI_DEFINE_ENUM_INTERNAL(execvP)
TLI_DEFINE_STRING_INTERNAL("execvP")
/// int execve(const char *filename, char *const argv[], char *const envp[]);
TLI_DEFINE_ENUM_INTERNAL(execve)
TLI_DEFINE_STRING_INTERNAL("execve")
/// int execvp(const char *file, char *const argv[]);
TLI_DEFINE_ENUM_INTERNAL(execvp)
TLI_DEFINE_STRING_INTERNAL("execvp")
/// int execvpe(const char *file, char *const argv[], char *const envp[]);
TLI_DEFINE_ENUM_INTERNAL(execvpe)
TLI_DEFINE_STRING_INTERNAL("execvpe")
/// double exp(double x);
TLI_DEFINE_ENUM_INTERNAL(exp)
TLI_DEFINE_STRING_INTERNAL("exp")
@ -709,6 +733,9 @@ TLI_DEFINE_STRING_INTERNAL("fopen")
/// FILE *fopen64(const char *filename, const char *opentype)
TLI_DEFINE_ENUM_INTERNAL(fopen64)
TLI_DEFINE_STRING_INTERNAL("fopen64")
/// int fork();
TLI_DEFINE_ENUM_INTERNAL(fork)
TLI_DEFINE_STRING_INTERNAL("fork")
/// int fprintf(FILE *stream, const char *format, ...);
TLI_DEFINE_ENUM_INTERNAL(fprintf)
TLI_DEFINE_STRING_INTERNAL("fprintf")

View file

@ -289,7 +289,7 @@ public:
/// Returns whether V is a source of divergence.
///
/// This function provides the target-dependent information for
/// the target-independent DivergenceAnalysis. DivergenceAnalysis first
/// the target-independent LegacyDivergenceAnalysis. LegacyDivergenceAnalysis first
/// builds the dependency graph, and then runs the reachability algorithm
/// starting with the sources of divergence.
bool isSourceOfDivergence(const Value *V) const;
@ -581,12 +581,21 @@ public:
struct MemCmpExpansionOptions {
// The list of available load sizes (in bytes), sorted in decreasing order.
SmallVector<unsigned, 8> LoadSizes;
// Set to true to allow overlapping loads. For example, 7-byte compares can
// be done with two 4-byte compares instead of 4+2+1-byte compares. This
// requires all loads in LoadSizes to be doable in an unaligned way.
bool AllowOverlappingLoads = false;
};
const MemCmpExpansionOptions *enableMemCmpExpansion(bool IsZeroCmp) const;
/// Enable matching of interleaved access groups.
bool enableInterleavedAccessVectorization() const;
/// Enable matching of interleaved access groups that contain predicated
/// accesses or gaps and therefore vectorized using masked
/// vector loads/stores.
bool enableMaskedInterleavedAccessVectorization() const;
/// Indicate that it is potentially unsafe to automatically vectorize
/// floating-point operations because the semantics of vector and scalar
/// floating-point semantics may differ. For example, ARM NEON v7 SIMD math
@ -739,6 +748,10 @@ public:
/// and the number of execution units in the CPU.
unsigned getMaxInterleaveFactor(unsigned VF) const;
/// Collect properties of V used in cost analysis, e.g. OP_PowerOf2.
static OperandValueKind getOperandInfo(Value *V,
OperandValueProperties &OpProps);
/// This is an approximation of reciprocal throughput of a math/logic op.
/// A higher cost indicates less expected throughput.
/// From Agner Fog's guides, reciprocal throughput is "the average number of
@ -762,7 +775,9 @@ public:
/// \return The cost of a shuffle instruction of kind Kind and of type Tp.
/// The index and subtype parameters are used by the subvector insertion and
/// extraction shuffle kinds.
/// extraction shuffle kinds to show the insert/extract point and the type of
/// the subvector being inserted/extracted.
/// NOTE: For subvector extractions Tp represents the source type.
int getShuffleCost(ShuffleKind Kind, Type *Tp, int Index = 0,
Type *SubTp = nullptr) const;
@ -817,9 +832,13 @@ public:
/// load allows gaps)
/// \p Alignment is the alignment of the memory operation
/// \p AddressSpace is address space of the pointer.
/// \p UseMaskForCond indicates if the memory access is predicated.
/// \p UseMaskForGaps indicates if gaps should be masked.
int getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor,
ArrayRef<unsigned> Indices, unsigned Alignment,
unsigned AddressSpace) const;
unsigned AddressSpace,
bool UseMaskForCond = false,
bool UseMaskForGaps = false) const;
/// Calculate the cost of performing a vector reduction.
///
@ -915,6 +934,14 @@ public:
bool areInlineCompatible(const Function *Caller,
const Function *Callee) const;
/// \returns True if the caller and callee agree on how \p Args will be passed
/// to the callee.
/// \param[out] Args The list of compatible arguments. The implementation may
/// filter out any incompatible args from this list.
bool areFunctionArgsABICompatible(const Function *Caller,
const Function *Callee,
SmallPtrSetImpl<Argument *> &Args) const;
/// The type of load/store indexing.
enum MemIndexedMode {
MIM_Unindexed, ///< No indexing.
@ -1068,6 +1095,7 @@ public:
virtual const MemCmpExpansionOptions *enableMemCmpExpansion(
bool IsZeroCmp) const = 0;
virtual bool enableInterleavedAccessVectorization() = 0;
virtual bool enableMaskedInterleavedAccessVectorization() = 0;
virtual bool isFPVectorizationPotentiallyUnsafe() = 0;
virtual bool allowsMisalignedMemoryAccesses(LLVMContext &Context,
unsigned BitWidth,
@ -1128,7 +1156,9 @@ public:
unsigned Factor,
ArrayRef<unsigned> Indices,
unsigned Alignment,
unsigned AddressSpace) = 0;
unsigned AddressSpace,
bool UseMaskForCond = false,
bool UseMaskForGaps = false) = 0;
virtual int getArithmeticReductionCost(unsigned Opcode, Type *Ty,
bool IsPairwiseForm) = 0;
virtual int getMinMaxReductionCost(Type *Ty, Type *CondTy,
@ -1157,6 +1187,9 @@ public:
unsigned RemainingBytes, unsigned SrcAlign, unsigned DestAlign) const = 0;
virtual bool areInlineCompatible(const Function *Caller,
const Function *Callee) const = 0;
virtual bool
areFunctionArgsABICompatible(const Function *Caller, const Function *Callee,
SmallPtrSetImpl<Argument *> &Args) const = 0;
virtual bool isIndexedLoadLegal(MemIndexedMode Mode, Type *Ty) const = 0;
virtual bool isIndexedStoreLegal(MemIndexedMode Mode,Type *Ty) const = 0;
virtual unsigned getLoadStoreVecRegBitWidth(unsigned AddrSpace) const = 0;
@ -1342,6 +1375,9 @@ public:
bool enableInterleavedAccessVectorization() override {
return Impl.enableInterleavedAccessVectorization();
}
bool enableMaskedInterleavedAccessVectorization() override {
return Impl.enableMaskedInterleavedAccessVectorization();
}
bool isFPVectorizationPotentiallyUnsafe() override {
return Impl.isFPVectorizationPotentiallyUnsafe();
}
@ -1467,9 +1503,11 @@ public:
}
int getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor,
ArrayRef<unsigned> Indices, unsigned Alignment,
unsigned AddressSpace) override {
unsigned AddressSpace, bool UseMaskForCond,
bool UseMaskForGaps) override {
return Impl.getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,
Alignment, AddressSpace);
Alignment, AddressSpace,
UseMaskForCond, UseMaskForGaps);
}
int getArithmeticReductionCost(unsigned Opcode, Type *Ty,
bool IsPairwiseForm) override {
@ -1530,6 +1568,11 @@ public:
const Function *Callee) const override {
return Impl.areInlineCompatible(Caller, Callee);
}
bool areFunctionArgsABICompatible(
const Function *Caller, const Function *Callee,
SmallPtrSetImpl<Argument *> &Args) const override {
return Impl.areFunctionArgsABICompatible(Caller, Callee, Args);
}
bool isIndexedLoadLegal(MemIndexedMode Mode, Type *Ty) const override {
return Impl.isIndexedLoadLegal(Mode, Ty, getDataLayout());
}

View file

@ -158,6 +158,9 @@ public:
case Intrinsic::dbg_label:
case Intrinsic::invariant_start:
case Intrinsic::invariant_end:
case Intrinsic::launder_invariant_group:
case Intrinsic::strip_invariant_group:
case Intrinsic::is_constant:
case Intrinsic::lifetime_start:
case Intrinsic::lifetime_end:
case Intrinsic::objectsize:
@ -311,6 +314,8 @@ public:
bool enableInterleavedAccessVectorization() { return false; }
bool enableMaskedInterleavedAccessVectorization() { return false; }
bool isFPVectorizationPotentiallyUnsafe() { return false; }
bool allowsMisalignedMemoryAccesses(LLVMContext &Context,
@ -448,8 +453,9 @@ public:
unsigned getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy,
unsigned Factor,
ArrayRef<unsigned> Indices,
unsigned Alignment,
unsigned AddressSpace) {
unsigned Alignment, unsigned AddressSpace,
bool UseMaskForCond = false,
bool UseMaskForGaps = false) {
return 1;
}
@ -520,6 +526,14 @@ public:
Callee->getFnAttribute("target-features"));
}
bool areFunctionArgsABICompatible(const Function *Caller, const Function *Callee,
SmallPtrSetImpl<Argument *> &Args) const {
return (Caller->getFnAttribute("target-cpu") ==
Callee->getFnAttribute("target-cpu")) &&
(Caller->getFnAttribute("target-features") ==
Callee->getFnAttribute("target-features"));
}
bool isIndexedLoadLegal(TTI::MemIndexedMode Mode, Type *Ty,
const DataLayout &DL) const {
return false;

View file

@ -17,7 +17,7 @@
#define LLVM_ANALYSIS_TYPEBASEDALIASANALYSIS_H
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
#include <memory>
@ -43,10 +43,10 @@ public:
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB);
bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal);
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS);
FunctionModRefBehavior getModRefBehavior(const CallBase *Call);
FunctionModRefBehavior getModRefBehavior(const Function *F);
ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc);
ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2);
ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc);
ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2);
private:
bool Aliases(const MDNode *A, const MDNode *B) const;

View file

@ -20,6 +20,8 @@
namespace llvm {
class DominatorTree;
/// The type of CFI jumptable needed for a function.
enum CfiFunctionLinkage {
CFL_Definition = 0,
@ -39,7 +41,8 @@ struct DevirtCallSite {
/// call sites based on the call and return them in DevirtCalls.
void findDevirtualizableCallsForTypeTest(
SmallVectorImpl<DevirtCallSite> &DevirtCalls,
SmallVectorImpl<CallInst *> &Assumes, const CallInst *CI);
SmallVectorImpl<CallInst *> &Assumes, const CallInst *CI,
DominatorTree &DT);
/// Given a call to the intrinsic \@llvm.type.checked.load, find all
/// devirtualizable call sites based on the call and return them in DevirtCalls.
@ -47,7 +50,7 @@ void findDevirtualizableCallsForTypeCheckedLoad(
SmallVectorImpl<DevirtCallSite> &DevirtCalls,
SmallVectorImpl<Instruction *> &LoadedPtrs,
SmallVectorImpl<Instruction *> &Preds, bool &HasNonCallUses,
const CallInst *CI);
const CallInst *CI, DominatorTree &DT);
}
#endif

View file

@ -55,14 +55,16 @@ class Value;
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr,
OptimizationRemarkEmitter *ORE = nullptr);
OptimizationRemarkEmitter *ORE = nullptr,
bool UseInstrInfo = true);
/// Returns the known bits rather than passing by reference.
KnownBits computeKnownBits(const Value *V, const DataLayout &DL,
unsigned Depth = 0, AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr,
OptimizationRemarkEmitter *ORE = nullptr);
OptimizationRemarkEmitter *ORE = nullptr,
bool UseInstrInfo = true);
/// Compute known bits from the range metadata.
/// \p KnownZero the set of bits that are known to be zero
@ -75,7 +77,8 @@ class Value;
const DataLayout &DL,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
const DominatorTree *DT = nullptr,
bool UseInstrInfo = true);
/// Return true if the given value is known to have exactly one bit set when
/// defined. For vectors return true if every element is known to be a power
@ -86,7 +89,8 @@ class Value;
bool OrZero = false, unsigned Depth = 0,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
const DominatorTree *DT = nullptr,
bool UseInstrInfo = true);
bool isOnlyUsedInZeroEqualityComparison(const Instruction *CxtI);
@ -99,7 +103,8 @@ class Value;
bool isKnownNonZero(const Value *V, const DataLayout &DL, unsigned Depth = 0,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
const DominatorTree *DT = nullptr,
bool UseInstrInfo = true);
/// Return true if the two given values are negation.
/// Currently can recoginze Value pair:
@ -112,28 +117,32 @@ class Value;
unsigned Depth = 0,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
const DominatorTree *DT = nullptr,
bool UseInstrInfo = true);
/// Returns true if the given value is known be positive (i.e. non-negative
/// and non-zero).
bool isKnownPositive(const Value *V, const DataLayout &DL, unsigned Depth = 0,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
const DominatorTree *DT = nullptr,
bool UseInstrInfo = true);
/// Returns true if the given value is known be negative (i.e. non-positive
/// and non-zero).
bool isKnownNegative(const Value *V, const DataLayout &DL, unsigned Depth = 0,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
const DominatorTree *DT = nullptr,
bool UseInstrInfo = true);
/// Return true if the given values are known to be non-equal when defined.
/// Supports scalar integer types only.
bool isKnownNonEqual(const Value *V1, const Value *V2, const DataLayout &DL,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr,
bool UseInstrInfo = true);
/// Return true if 'V & Mask' is known to be zero. We use this predicate to
/// simplify operations downstream. Mask is known to be zero for bits that V
@ -148,7 +157,8 @@ class Value;
const DataLayout &DL,
unsigned Depth = 0, AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
const DominatorTree *DT = nullptr,
bool UseInstrInfo = true);
/// Return the number of times the sign bit of the register is replicated into
/// the other bits. We know that at least 1 bit is always equal to the sign
@ -160,7 +170,8 @@ class Value;
unsigned ComputeNumSignBits(const Value *Op, const DataLayout &DL,
unsigned Depth = 0, AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
const DominatorTree *DT = nullptr,
bool UseInstrInfo = true);
/// This function computes the integer multiple of Base that equals V. If
/// successful, it returns true and returns the multiple in Multiple. If
@ -194,7 +205,8 @@ class Value;
/// Return true if the floating-point scalar value is not a NaN or if the
/// floating-point vector value has no NaN elements. Return false if a value
/// could ever be NaN.
bool isKnownNeverNaN(const Value *V);
bool isKnownNeverNaN(const Value *V, const TargetLibraryInfo *TLI,
unsigned Depth = 0);
/// Return true if we can prove that the specified FP value's sign bit is 0.
///
@ -209,7 +221,8 @@ class Value;
/// return the i8 value that it is represented with. This is true for all i8
/// values obviously, but is also true for i32 0, i32 -1, i16 0xF0F0, double
/// 0.0 etc. If the value can't be handled with a repeated byte store (e.g.
/// i16 0x1234), return null.
/// i16 0x1234), return null. If the value is entirely undef and padding,
/// return undef.
Value *isBytewiseValue(Value *V);
/// Given an aggregrate and an sequence of indices, see if the scalar value
@ -284,10 +297,10 @@ class Value;
/// This function returns call pointer argument that is considered the same by
/// aliasing rules. You CAN'T use it to replace one value with another.
const Value *getArgumentAliasingToReturnedPointer(ImmutableCallSite CS);
inline Value *getArgumentAliasingToReturnedPointer(CallSite CS) {
return const_cast<Value *>(
getArgumentAliasingToReturnedPointer(ImmutableCallSite(CS)));
const Value *getArgumentAliasingToReturnedPointer(const CallBase *Call);
inline Value *getArgumentAliasingToReturnedPointer(CallBase *Call) {
return const_cast<Value *>(getArgumentAliasingToReturnedPointer(
const_cast<const CallBase *>(Call)));
}
// {launder,strip}.invariant.group returns pointer that aliases its argument,
@ -296,7 +309,7 @@ class Value;
// considered as capture. The arguments are not marked as returned neither,
// because it would make it useless.
bool isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(
ImmutableCallSite CS);
const CallBase *Call);
/// This method strips off any GEP address adjustments and pointer casts from
/// the specified value, returning the original object being addressed. Note
@ -405,18 +418,21 @@ class Value;
const DataLayout &DL,
AssumptionCache *AC,
const Instruction *CxtI,
const DominatorTree *DT);
const DominatorTree *DT,
bool UseInstrInfo = true);
OverflowResult computeOverflowForSignedMul(const Value *LHS, const Value *RHS,
const DataLayout &DL,
AssumptionCache *AC,
const Instruction *CxtI,
const DominatorTree *DT);
const DominatorTree *DT,
bool UseInstrInfo = true);
OverflowResult computeOverflowForUnsignedAdd(const Value *LHS,
const Value *RHS,
const DataLayout &DL,
AssumptionCache *AC,
const Instruction *CxtI,
const DominatorTree *DT);
const DominatorTree *DT,
bool UseInstrInfo = true);
OverflowResult computeOverflowForSignedAdd(const Value *LHS, const Value *RHS,
const DataLayout &DL,
AssumptionCache *AC = nullptr,
@ -594,6 +610,12 @@ class Value;
Optional<bool> isImpliedCondition(const Value *LHS, const Value *RHS,
const DataLayout &DL, bool LHSIsTrue = true,
unsigned Depth = 0);
/// Return the boolean condition value in the context of the given instruction
/// if it is known based on dominating conditions.
Optional<bool> isImpliedByDomCondition(const Value *Cond,
const Instruction *ContextI,
const DataLayout &DL);
} // end namespace llvm
#endif // LLVM_ANALYSIS_VALUETRACKING_H

View file

@ -15,6 +15,7 @@
#define LLVM_ANALYSIS_VECTORUTILS_H
#include "llvm/ADT/MapVector.h"
#include "llvm/Analysis/LoopAccessAnalysis.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/IRBuilder.h"
@ -23,6 +24,7 @@ namespace llvm {
template <typename T> class ArrayRef;
class DemandedBits;
class GetElementPtrInst;
template <typename InstTy> class InterleaveGroup;
class Loop;
class ScalarEvolution;
class TargetTransformInfo;
@ -115,8 +117,24 @@ computeMinimumValueSizes(ArrayRef<BasicBlock*> Blocks,
DemandedBits &DB,
const TargetTransformInfo *TTI=nullptr);
/// Compute the union of two access-group lists.
///
/// If the list contains just one access group, it is returned directly. If the
/// list is empty, returns nullptr.
MDNode *uniteAccessGroups(MDNode *AccGroups1, MDNode *AccGroups2);
/// Compute the access-group list of access groups that @p Inst1 and @p Inst2
/// are both in. If either instruction does not access memory at all, it is
/// considered to be in every list.
///
/// If the list contains just one access group, it is returned directly. If the
/// list is empty, returns nullptr.
MDNode *intersectAccessGroups(const Instruction *Inst1,
const Instruction *Inst2);
/// Specifically, let Kinds = [MD_tbaa, MD_alias_scope, MD_noalias, MD_fpmath,
/// MD_nontemporal]. For K in Kinds, we get the MDNode for K from each of the
/// MD_nontemporal, MD_access_group].
/// For K in Kinds, we get the MDNode for K from each of the
/// elements of VL, compute their "intersection" (i.e., the most generic
/// metadata value that covers all of the individual values), and set I's
/// metadata for M equal to the intersection value.
@ -124,6 +142,35 @@ computeMinimumValueSizes(ArrayRef<BasicBlock*> Blocks,
/// This function always sets a (possibly null) value for each K in Kinds.
Instruction *propagateMetadata(Instruction *I, ArrayRef<Value *> VL);
/// Create a mask that filters the members of an interleave group where there
/// are gaps.
///
/// For example, the mask for \p Group with interleave-factor 3
/// and \p VF 4, that has only its first member present is:
///
/// <1,0,0,1,0,0,1,0,0,1,0,0>
///
/// Note: The result is a mask of 0's and 1's, as opposed to the other
/// create[*]Mask() utilities which create a shuffle mask (mask that
/// consists of indices).
Constant *createBitMaskForGaps(IRBuilder<> &Builder, unsigned VF,
const InterleaveGroup<Instruction> &Group);
/// Create a mask with replicated elements.
///
/// This function creates a shuffle mask for replicating each of the \p VF
/// elements in a vector \p ReplicationFactor times. It can be used to
/// transform a mask of \p VF elements into a mask of
/// \p VF * \p ReplicationFactor elements used by a predicated
/// interleaved-group of loads/stores whose Interleaved-factor ==
/// \p ReplicationFactor.
///
/// For example, the mask for \p ReplicationFactor=3 and \p VF=4 is:
///
/// <0,0,0,1,1,1,2,2,2,3,3,3>
Constant *createReplicatedMask(IRBuilder<> &Builder, unsigned ReplicationFactor,
unsigned VF);
/// Create an interleave shuffle mask.
///
/// This function creates a shuffle mask for interleaving \p NumVecs vectors of
@ -176,6 +223,381 @@ Constant *createSequentialMask(IRBuilder<> &Builder, unsigned Start,
/// elements, it will be padded with undefs.
Value *concatenateVectors(IRBuilder<> &Builder, ArrayRef<Value *> Vecs);
/// The group of interleaved loads/stores sharing the same stride and
/// close to each other.
///
/// Each member in this group has an index starting from 0, and the largest
/// index should be less than interleaved factor, which is equal to the absolute
/// value of the access's stride.
///
/// E.g. An interleaved load group of factor 4:
/// for (unsigned i = 0; i < 1024; i+=4) {
/// a = A[i]; // Member of index 0
/// b = A[i+1]; // Member of index 1
/// d = A[i+3]; // Member of index 3
/// ...
/// }
///
/// An interleaved store group of factor 4:
/// for (unsigned i = 0; i < 1024; i+=4) {
/// ...
/// A[i] = a; // Member of index 0
/// A[i+1] = b; // Member of index 1
/// A[i+2] = c; // Member of index 2
/// A[i+3] = d; // Member of index 3
/// }
///
/// Note: the interleaved load group could have gaps (missing members), but
/// the interleaved store group doesn't allow gaps.
template <typename InstTy> class InterleaveGroup {
public:
InterleaveGroup(unsigned Factor, bool Reverse, unsigned Align)
: Factor(Factor), Reverse(Reverse), Align(Align), InsertPos(nullptr) {}
InterleaveGroup(InstTy *Instr, int Stride, unsigned Align)
: Align(Align), InsertPos(Instr) {
assert(Align && "The alignment should be non-zero");
Factor = std::abs(Stride);
assert(Factor > 1 && "Invalid interleave factor");
Reverse = Stride < 0;
Members[0] = Instr;
}
bool isReverse() const { return Reverse; }
unsigned getFactor() const { return Factor; }
unsigned getAlignment() const { return Align; }
unsigned getNumMembers() const { return Members.size(); }
/// Try to insert a new member \p Instr with index \p Index and
/// alignment \p NewAlign. The index is related to the leader and it could be
/// negative if it is the new leader.
///
/// \returns false if the instruction doesn't belong to the group.
bool insertMember(InstTy *Instr, int Index, unsigned NewAlign) {
assert(NewAlign && "The new member's alignment should be non-zero");
int Key = Index + SmallestKey;
// Skip if there is already a member with the same index.
if (Members.find(Key) != Members.end())
return false;
if (Key > LargestKey) {
// The largest index is always less than the interleave factor.
if (Index >= static_cast<int>(Factor))
return false;
LargestKey = Key;
} else if (Key < SmallestKey) {
// The largest index is always less than the interleave factor.
if (LargestKey - Key >= static_cast<int>(Factor))
return false;
SmallestKey = Key;
}
// It's always safe to select the minimum alignment.
Align = std::min(Align, NewAlign);
Members[Key] = Instr;
return true;
}
/// Get the member with the given index \p Index
///
/// \returns nullptr if contains no such member.
InstTy *getMember(unsigned Index) const {
int Key = SmallestKey + Index;
auto Member = Members.find(Key);
if (Member == Members.end())
return nullptr;
return Member->second;
}
/// Get the index for the given member. Unlike the key in the member
/// map, the index starts from 0.
unsigned getIndex(const InstTy *Instr) const {
for (auto I : Members) {
if (I.second == Instr)
return I.first - SmallestKey;
}
llvm_unreachable("InterleaveGroup contains no such member");
}
InstTy *getInsertPos() const { return InsertPos; }
void setInsertPos(InstTy *Inst) { InsertPos = Inst; }
/// Add metadata (e.g. alias info) from the instructions in this group to \p
/// NewInst.
///
/// FIXME: this function currently does not add noalias metadata a'la
/// addNewMedata. To do that we need to compute the intersection of the
/// noalias info from all members.
void addMetadata(InstTy *NewInst) const;
/// Returns true if this Group requires a scalar iteration to handle gaps.
bool requiresScalarEpilogue() const {
// If the last member of the Group exists, then a scalar epilog is not
// needed for this group.
if (getMember(getFactor() - 1))
return false;
// We have a group with gaps. It therefore cannot be a group of stores,
// and it can't be a reversed access, because such groups get invalidated.
assert(!getMember(0)->mayWriteToMemory() &&
"Group should have been invalidated");
assert(!isReverse() && "Group should have been invalidated");
// This is a group of loads, with gaps, and without a last-member
return true;
}
private:
unsigned Factor; // Interleave Factor.
bool Reverse;
unsigned Align;
DenseMap<int, InstTy *> Members;
int SmallestKey = 0;
int LargestKey = 0;
// To avoid breaking dependences, vectorized instructions of an interleave
// group should be inserted at either the first load or the last store in
// program order.
//
// E.g. %even = load i32 // Insert Position
// %add = add i32 %even // Use of %even
// %odd = load i32
//
// store i32 %even
// %odd = add i32 // Def of %odd
// store i32 %odd // Insert Position
InstTy *InsertPos;
};
/// Drive the analysis of interleaved memory accesses in the loop.
///
/// Use this class to analyze interleaved accesses only when we can vectorize
/// a loop. Otherwise it's meaningless to do analysis as the vectorization
/// on interleaved accesses is unsafe.
///
/// The analysis collects interleave groups and records the relationships
/// between the member and the group in a map.
class InterleavedAccessInfo {
public:
InterleavedAccessInfo(PredicatedScalarEvolution &PSE, Loop *L,
DominatorTree *DT, LoopInfo *LI,
const LoopAccessInfo *LAI)
: PSE(PSE), TheLoop(L), DT(DT), LI(LI), LAI(LAI) {}
~InterleavedAccessInfo() { reset(); }
/// Analyze the interleaved accesses and collect them in interleave
/// groups. Substitute symbolic strides using \p Strides.
/// Consider also predicated loads/stores in the analysis if
/// \p EnableMaskedInterleavedGroup is true.
void analyzeInterleaving(bool EnableMaskedInterleavedGroup);
/// Invalidate groups, e.g., in case all blocks in loop will be predicated
/// contrary to original assumption. Although we currently prevent group
/// formation for predicated accesses, we may be able to relax this limitation
/// in the future once we handle more complicated blocks.
void reset() {
SmallPtrSet<InterleaveGroup<Instruction> *, 4> DelSet;
// Avoid releasing a pointer twice.
for (auto &I : InterleaveGroupMap)
DelSet.insert(I.second);
for (auto *Ptr : DelSet)
delete Ptr;
InterleaveGroupMap.clear();
RequiresScalarEpilogue = false;
}
/// Check if \p Instr belongs to any interleave group.
bool isInterleaved(Instruction *Instr) const {
return InterleaveGroupMap.find(Instr) != InterleaveGroupMap.end();
}
/// Get the interleave group that \p Instr belongs to.
///
/// \returns nullptr if doesn't have such group.
InterleaveGroup<Instruction> *
getInterleaveGroup(const Instruction *Instr) const {
if (InterleaveGroupMap.count(Instr))
return InterleaveGroupMap.find(Instr)->second;
return nullptr;
}
iterator_range<SmallPtrSetIterator<llvm::InterleaveGroup<Instruction> *>>
getInterleaveGroups() {
return make_range(InterleaveGroups.begin(), InterleaveGroups.end());
}
/// Returns true if an interleaved group that may access memory
/// out-of-bounds requires a scalar epilogue iteration for correctness.
bool requiresScalarEpilogue() const { return RequiresScalarEpilogue; }
/// Invalidate groups that require a scalar epilogue (due to gaps). This can
/// happen when optimizing for size forbids a scalar epilogue, and the gap
/// cannot be filtered by masking the load/store.
void invalidateGroupsRequiringScalarEpilogue();
private:
/// A wrapper around ScalarEvolution, used to add runtime SCEV checks.
/// Simplifies SCEV expressions in the context of existing SCEV assumptions.
/// The interleaved access analysis can also add new predicates (for example
/// by versioning strides of pointers).
PredicatedScalarEvolution &PSE;
Loop *TheLoop;
DominatorTree *DT;
LoopInfo *LI;
const LoopAccessInfo *LAI;
/// True if the loop may contain non-reversed interleaved groups with
/// out-of-bounds accesses. We ensure we don't speculatively access memory
/// out-of-bounds by executing at least one scalar epilogue iteration.
bool RequiresScalarEpilogue = false;
/// Holds the relationships between the members and the interleave group.
DenseMap<Instruction *, InterleaveGroup<Instruction> *> InterleaveGroupMap;
SmallPtrSet<InterleaveGroup<Instruction> *, 4> InterleaveGroups;
/// Holds dependences among the memory accesses in the loop. It maps a source
/// access to a set of dependent sink accesses.
DenseMap<Instruction *, SmallPtrSet<Instruction *, 2>> Dependences;
/// The descriptor for a strided memory access.
struct StrideDescriptor {
StrideDescriptor() = default;
StrideDescriptor(int64_t Stride, const SCEV *Scev, uint64_t Size,
unsigned Align)
: Stride(Stride), Scev(Scev), Size(Size), Align(Align) {}
// The access's stride. It is negative for a reverse access.
int64_t Stride = 0;
// The scalar expression of this access.
const SCEV *Scev = nullptr;
// The size of the memory object.
uint64_t Size = 0;
// The alignment of this access.
unsigned Align = 0;
};
/// A type for holding instructions and their stride descriptors.
using StrideEntry = std::pair<Instruction *, StrideDescriptor>;
/// Create a new interleave group with the given instruction \p Instr,
/// stride \p Stride and alignment \p Align.
///
/// \returns the newly created interleave group.
InterleaveGroup<Instruction> *
createInterleaveGroup(Instruction *Instr, int Stride, unsigned Align) {
assert(!InterleaveGroupMap.count(Instr) &&
"Already in an interleaved access group");
InterleaveGroupMap[Instr] =
new InterleaveGroup<Instruction>(Instr, Stride, Align);
InterleaveGroups.insert(InterleaveGroupMap[Instr]);
return InterleaveGroupMap[Instr];
}
/// Release the group and remove all the relationships.
void releaseGroup(InterleaveGroup<Instruction> *Group) {
for (unsigned i = 0; i < Group->getFactor(); i++)
if (Instruction *Member = Group->getMember(i))
InterleaveGroupMap.erase(Member);
InterleaveGroups.erase(Group);
delete Group;
}
/// Collect all the accesses with a constant stride in program order.
void collectConstStrideAccesses(
MapVector<Instruction *, StrideDescriptor> &AccessStrideInfo,
const ValueToValueMap &Strides);
/// Returns true if \p Stride is allowed in an interleaved group.
static bool isStrided(int Stride);
/// Returns true if \p BB is a predicated block.
bool isPredicated(BasicBlock *BB) const {
return LoopAccessInfo::blockNeedsPredication(BB, TheLoop, DT);
}
/// Returns true if LoopAccessInfo can be used for dependence queries.
bool areDependencesValid() const {
return LAI && LAI->getDepChecker().getDependences();
}
/// Returns true if memory accesses \p A and \p B can be reordered, if
/// necessary, when constructing interleaved groups.
///
/// \p A must precede \p B in program order. We return false if reordering is
/// not necessary or is prevented because \p A and \p B may be dependent.
bool canReorderMemAccessesForInterleavedGroups(StrideEntry *A,
StrideEntry *B) const {
// Code motion for interleaved accesses can potentially hoist strided loads
// and sink strided stores. The code below checks the legality of the
// following two conditions:
//
// 1. Potentially moving a strided load (B) before any store (A) that
// precedes B, or
//
// 2. Potentially moving a strided store (A) after any load or store (B)
// that A precedes.
//
// It's legal to reorder A and B if we know there isn't a dependence from A
// to B. Note that this determination is conservative since some
// dependences could potentially be reordered safely.
// A is potentially the source of a dependence.
auto *Src = A->first;
auto SrcDes = A->second;
// B is potentially the sink of a dependence.
auto *Sink = B->first;
auto SinkDes = B->second;
// Code motion for interleaved accesses can't violate WAR dependences.
// Thus, reordering is legal if the source isn't a write.
if (!Src->mayWriteToMemory())
return true;
// At least one of the accesses must be strided.
if (!isStrided(SrcDes.Stride) && !isStrided(SinkDes.Stride))
return true;
// If dependence information is not available from LoopAccessInfo,
// conservatively assume the instructions can't be reordered.
if (!areDependencesValid())
return false;
// If we know there is a dependence from source to sink, assume the
// instructions can't be reordered. Otherwise, reordering is legal.
return Dependences.find(Src) == Dependences.end() ||
!Dependences.lookup(Src).count(Sink);
}
/// Collect the dependences from LoopAccessInfo.
///
/// We process the dependences once during the interleaved access analysis to
/// enable constant-time dependence queries.
void collectDependences() {
if (!areDependencesValid())
return;
auto *Deps = LAI->getDepChecker().getDependences();
for (auto Dep : *Deps)
Dependences[Dep.getSource(*LAI)].insert(Dep.getDestination(*LAI));
}
};
} // llvm namespace
#endif

View file

@ -0,0 +1,70 @@
//===- AMDGPUMetadataVerifier.h - MsgPack Types -----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// \file
/// This is a verifier for AMDGPU HSA metadata, which can verify both
/// well-typed metadata and untyped metadata. When verifying in the non-strict
/// mode, untyped metadata is coerced into the correct type if possible.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_BINARYFORMAT_AMDGPUMETADATAVERIFIER_H
#define LLVM_BINARYFORMAT_AMDGPUMETADATAVERIFIER_H
#include "llvm/BinaryFormat/MsgPackTypes.h"
namespace llvm {
namespace AMDGPU {
namespace HSAMD {
namespace V3 {
/// Verifier for AMDGPU HSA metadata.
///
/// Operates in two modes:
///
/// In strict mode, metadata must already be well-typed.
///
/// In non-strict mode, metadata is coerced into expected types when possible.
class MetadataVerifier {
bool Strict;
bool verifyScalar(msgpack::Node &Node, msgpack::ScalarNode::ScalarKind SKind,
function_ref<bool(msgpack::ScalarNode &)> verifyValue = {});
bool verifyInteger(msgpack::Node &Node);
bool verifyArray(msgpack::Node &Node,
function_ref<bool(msgpack::Node &)> verifyNode,
Optional<size_t> Size = None);
bool verifyEntry(msgpack::MapNode &MapNode, StringRef Key, bool Required,
function_ref<bool(msgpack::Node &)> verifyNode);
bool
verifyScalarEntry(msgpack::MapNode &MapNode, StringRef Key, bool Required,
msgpack::ScalarNode::ScalarKind SKind,
function_ref<bool(msgpack::ScalarNode &)> verifyValue = {});
bool verifyIntegerEntry(msgpack::MapNode &MapNode, StringRef Key,
bool Required);
bool verifyKernelArgs(msgpack::Node &Node);
bool verifyKernel(msgpack::Node &Node);
public:
/// Construct a MetadataVerifier, specifying whether it will operate in \p
/// Strict mode.
MetadataVerifier(bool Strict) : Strict(Strict) {}
/// Verify given HSA metadata.
///
/// \returns True when successful, false when metadata is invalid.
bool verify(msgpack::Node &HSAMetadataRoot);
};
} // end namespace V3
} // end namespace HSAMD
} // end namespace AMDGPU
} // end namespace llvm
#endif // LLVM_BINARYFORMAT_AMDGPUMETADATAVERIFIER_H

View file

@ -18,9 +18,11 @@
defined HANDLE_DW_VIRTUALITY || defined HANDLE_DW_DEFAULTED || \
defined HANDLE_DW_CC || defined HANDLE_DW_LNS || defined HANDLE_DW_LNE || \
defined HANDLE_DW_LNCT || defined HANDLE_DW_MACRO || \
defined HANDLE_DW_RLE || defined HANDLE_DW_CFA || \
defined HANDLE_DW_RLE || \
(defined HANDLE_DW_CFA && defined HANDLE_DW_CFA_PRED) || \
defined HANDLE_DW_APPLE_PROPERTY || defined HANDLE_DW_UT || \
defined HANDLE_DWARF_SECTION || defined HANDLE_DW_IDX)
defined HANDLE_DWARF_SECTION || defined HANDLE_DW_IDX || \
defined HANDLE_DW_END)
#error "Missing macro definition of HANDLE_DW*"
#endif
@ -41,7 +43,7 @@
#endif
#ifndef HANDLE_DW_LANG
#define HANDLE_DW_LANG(ID, NAME, VERSION, VENDOR)
#define HANDLE_DW_LANG(ID, NAME, LOWER_BOUND, VERSION, VENDOR)
#endif
#ifndef HANDLE_DW_ATE
@ -84,6 +86,10 @@
#define HANDLE_DW_CFA(ID, NAME)
#endif
#ifndef HANDLE_DW_CFA_PRED
#define HANDLE_DW_CFA_PRED(ID, NAME, PRED)
#endif
#ifndef HANDLE_DW_APPLE_PROPERTY
#define HANDLE_DW_APPLE_PROPERTY(ID, NAME)
#endif
@ -100,6 +106,10 @@
#define HANDLE_DW_IDX(ID, NAME)
#endif
#ifndef HANDLE_DW_END
#define HANDLE_DW_END(ID, NAME)
#endif
HANDLE_DW_TAG(0x0000, null, 2, DWARF)
HANDLE_DW_TAG(0x0001, array_type, 2, DWARF)
HANDLE_DW_TAG(0x0002, class_type, 2, DWARF)
@ -622,50 +632,50 @@ HANDLE_DW_OP(0xfb, GNU_addr_index, 0, GNU)
HANDLE_DW_OP(0xfc, GNU_const_index, 0, GNU)
// DWARF languages.
HANDLE_DW_LANG(0x0001, C89, 2, DWARF)
HANDLE_DW_LANG(0x0002, C, 2, DWARF)
HANDLE_DW_LANG(0x0003, Ada83, 2, DWARF)
HANDLE_DW_LANG(0x0004, C_plus_plus, 2, DWARF)
HANDLE_DW_LANG(0x0005, Cobol74, 2, DWARF)
HANDLE_DW_LANG(0x0006, Cobol85, 2, DWARF)
HANDLE_DW_LANG(0x0007, Fortran77, 2, DWARF)
HANDLE_DW_LANG(0x0008, Fortran90, 2, DWARF)
HANDLE_DW_LANG(0x0009, Pascal83, 2, DWARF)
HANDLE_DW_LANG(0x000a, Modula2, 2, DWARF)
HANDLE_DW_LANG(0x0001, C89, 0, 2, DWARF)
HANDLE_DW_LANG(0x0002, C, 0, 2, DWARF)
HANDLE_DW_LANG(0x0003, Ada83, 1, 2, DWARF)
HANDLE_DW_LANG(0x0004, C_plus_plus, 0, 2, DWARF)
HANDLE_DW_LANG(0x0005, Cobol74, 1, 2, DWARF)
HANDLE_DW_LANG(0x0006, Cobol85, 1, 2, DWARF)
HANDLE_DW_LANG(0x0007, Fortran77, 1, 2, DWARF)
HANDLE_DW_LANG(0x0008, Fortran90, 1, 2, DWARF)
HANDLE_DW_LANG(0x0009, Pascal83, 1, 2, DWARF)
HANDLE_DW_LANG(0x000a, Modula2, 1, 2, DWARF)
// New in DWARF v3:
HANDLE_DW_LANG(0x000b, Java, 3, DWARF)
HANDLE_DW_LANG(0x000c, C99, 3, DWARF)
HANDLE_DW_LANG(0x000d, Ada95, 3, DWARF)
HANDLE_DW_LANG(0x000e, Fortran95, 3, DWARF)
HANDLE_DW_LANG(0x000f, PLI, 3, DWARF)
HANDLE_DW_LANG(0x0010, ObjC, 3, DWARF)
HANDLE_DW_LANG(0x0011, ObjC_plus_plus, 3, DWARF)
HANDLE_DW_LANG(0x0012, UPC, 3, DWARF)
HANDLE_DW_LANG(0x0013, D, 3, DWARF)
HANDLE_DW_LANG(0x000b, Java, 0, 3, DWARF)
HANDLE_DW_LANG(0x000c, C99, 0, 3, DWARF)
HANDLE_DW_LANG(0x000d, Ada95, 1, 3, DWARF)
HANDLE_DW_LANG(0x000e, Fortran95, 1, 3, DWARF)
HANDLE_DW_LANG(0x000f, PLI, 1, 3, DWARF)
HANDLE_DW_LANG(0x0010, ObjC, 0, 3, DWARF)
HANDLE_DW_LANG(0x0011, ObjC_plus_plus, 0, 3, DWARF)
HANDLE_DW_LANG(0x0012, UPC, 0, 3, DWARF)
HANDLE_DW_LANG(0x0013, D, 0, 3, DWARF)
// New in DWARF v4:
HANDLE_DW_LANG(0x0014, Python, 4, DWARF)
HANDLE_DW_LANG(0x0014, Python, 0, 4, DWARF)
// New in DWARF v5:
HANDLE_DW_LANG(0x0015, OpenCL, 5, DWARF)
HANDLE_DW_LANG(0x0016, Go, 5, DWARF)
HANDLE_DW_LANG(0x0017, Modula3, 5, DWARF)
HANDLE_DW_LANG(0x0018, Haskell, 5, DWARF)
HANDLE_DW_LANG(0x0019, C_plus_plus_03, 5, DWARF)
HANDLE_DW_LANG(0x001a, C_plus_plus_11, 5, DWARF)
HANDLE_DW_LANG(0x001b, OCaml, 5, DWARF)
HANDLE_DW_LANG(0x001c, Rust, 5, DWARF)
HANDLE_DW_LANG(0x001d, C11, 5, DWARF)
HANDLE_DW_LANG(0x001e, Swift, 5, DWARF)
HANDLE_DW_LANG(0x001f, Julia, 5, DWARF)
HANDLE_DW_LANG(0x0020, Dylan, 5, DWARF)
HANDLE_DW_LANG(0x0021, C_plus_plus_14, 5, DWARF)
HANDLE_DW_LANG(0x0022, Fortran03, 5, DWARF)
HANDLE_DW_LANG(0x0023, Fortran08, 5, DWARF)
HANDLE_DW_LANG(0x0024, RenderScript, 5, DWARF)
HANDLE_DW_LANG(0x0025, BLISS, 5, DWARF)
HANDLE_DW_LANG(0x0015, OpenCL, 0, 5, DWARF)
HANDLE_DW_LANG(0x0016, Go, 0, 5, DWARF)
HANDLE_DW_LANG(0x0017, Modula3, 1, 5, DWARF)
HANDLE_DW_LANG(0x0018, Haskell, 0, 5, DWARF)
HANDLE_DW_LANG(0x0019, C_plus_plus_03, 0, 5, DWARF)
HANDLE_DW_LANG(0x001a, C_plus_plus_11, 0, 5, DWARF)
HANDLE_DW_LANG(0x001b, OCaml, 0, 5, DWARF)
HANDLE_DW_LANG(0x001c, Rust, 0, 5, DWARF)
HANDLE_DW_LANG(0x001d, C11, 0, 5, DWARF)
HANDLE_DW_LANG(0x001e, Swift, 0, 5, DWARF)
HANDLE_DW_LANG(0x001f, Julia, 1, 5, DWARF)
HANDLE_DW_LANG(0x0020, Dylan, 0, 5, DWARF)
HANDLE_DW_LANG(0x0021, C_plus_plus_14, 0, 5, DWARF)
HANDLE_DW_LANG(0x0022, Fortran03, 1, 5, DWARF)
HANDLE_DW_LANG(0x0023, Fortran08, 1, 5, DWARF)
HANDLE_DW_LANG(0x0024, RenderScript, 0, 5, DWARF)
HANDLE_DW_LANG(0x0025, BLISS, 0, 5, DWARF)
// Vendor extensions:
HANDLE_DW_LANG(0x8001, Mips_Assembler, 0, MIPS)
HANDLE_DW_LANG(0x8e57, GOOGLE_RenderScript, 0, GOOGLE)
HANDLE_DW_LANG(0xb000, BORLAND_Delphi, 0, BORLAND)
HANDLE_DW_LANG(0x8001, Mips_Assembler, None, 0, MIPS)
HANDLE_DW_LANG(0x8e57, GOOGLE_RenderScript, 0, 0, GOOGLE)
HANDLE_DW_LANG(0xb000, BORLAND_Delphi, 0, 0, BORLAND)
// DWARF attribute type encodings.
HANDLE_DW_ATE(0x01, address, 2, DWARF)
@ -690,6 +700,11 @@ HANDLE_DW_ATE(0x10, UTF, 4, DWARF)
HANDLE_DW_ATE(0x11, UCS, 5, DWARF)
HANDLE_DW_ATE(0x12, ASCII, 5, DWARF)
// DWARF attribute endianity
HANDLE_DW_END(0x00, default)
HANDLE_DW_END(0x01, big)
HANDLE_DW_END(0x02, little)
// DWARF virtuality codes.
HANDLE_DW_VIRTUALITY(0x00, none)
HANDLE_DW_VIRTUALITY(0x01, virtual)
@ -821,9 +836,10 @@ HANDLE_DW_CFA(0x14, val_offset)
HANDLE_DW_CFA(0x15, val_offset_sf)
HANDLE_DW_CFA(0x16, val_expression)
// Vendor extensions:
HANDLE_DW_CFA(0x1d, MIPS_advance_loc8)
HANDLE_DW_CFA(0x2d, GNU_window_save)
HANDLE_DW_CFA(0x2e, GNU_args_size)
HANDLE_DW_CFA_PRED(0x1d, MIPS_advance_loc8, SELECT_MIPS64)
HANDLE_DW_CFA_PRED(0x2d, GNU_window_save, SELECT_SPARC)
HANDLE_DW_CFA_PRED(0x2d, AARCH64_negate_ra_state, SELECT_AARCH64)
HANDLE_DW_CFA_PRED(0x2e, GNU_args_size, SELECT_X86)
// Apple Objective-C Property Attributes.
// Keep this list in sync with clang's DeclSpec.h ObjCPropertyAttributeKind!
@ -863,6 +879,7 @@ HANDLE_DWARF_SECTION(DebugTypes, ".debug_types", "debug-types")
HANDLE_DWARF_SECTION(DebugLine, ".debug_line", "debug-line")
HANDLE_DWARF_SECTION(DebugLineStr, ".debug_line_str", "debug-line-str")
HANDLE_DWARF_SECTION(DebugLoc, ".debug_loc", "debug-loc")
HANDLE_DWARF_SECTION(DebugLoclists, ".debug_loclists", "debug-loclists")
HANDLE_DWARF_SECTION(DebugFrame, ".debug_frame", "debug-frame")
HANDLE_DWARF_SECTION(DebugMacro, ".debug_macro", "debug-macro")
HANDLE_DWARF_SECTION(DebugNames, ".debug_names", "debug-names")
@ -905,7 +922,9 @@ HANDLE_DW_IDX(0x05, type_hash)
#undef HANDLE_DW_MACRO
#undef HANDLE_DW_RLE
#undef HANDLE_DW_CFA
#undef HANDLE_DW_CFA_PRED
#undef HANDLE_DW_APPLE_PROPERTY
#undef HANDLE_DW_UT
#undef HANDLE_DWARF_SECTION
#undef HANDLE_DW_IDX
#undef HANDLE_DW_END

View file

@ -26,6 +26,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormatVariadicDetails.h"
#include "llvm/ADT/Triple.h"
namespace llvm {
class StringRef;
@ -150,9 +151,8 @@ enum DecimalSignEncoding {
enum EndianityEncoding {
// Endianity attribute values
DW_END_default = 0x00,
DW_END_big = 0x01,
DW_END_little = 0x02,
#define HANDLE_DW_END(ID, NAME) DW_END_##NAME = ID,
#include "llvm/BinaryFormat/Dwarf.def"
DW_END_lo_user = 0x40,
DW_END_hi_user = 0xff
};
@ -184,7 +184,8 @@ enum DefaultedMemberAttribute {
};
enum SourceLanguage {
#define HANDLE_DW_LANG(ID, NAME, VERSION, VENDOR) DW_LANG_##NAME = ID,
#define HANDLE_DW_LANG(ID, NAME, LOWER_BOUND, VERSION, VENDOR) \
DW_LANG_##NAME = ID,
#include "llvm/BinaryFormat/Dwarf.def"
DW_LANG_lo_user = 0x8000,
DW_LANG_hi_user = 0xffff
@ -273,6 +274,7 @@ enum RangeListEntries {
/// Call frame instruction encodings.
enum CallFrameInfo {
#define HANDLE_DW_CFA(ID, NAME) DW_CFA_##NAME = ID,
#define HANDLE_DW_CFA_PRED(ID, NAME, ARCH) DW_CFA_##NAME = ID,
#include "llvm/BinaryFormat/Dwarf.def"
DW_CFA_extended = 0x00,
@ -431,7 +433,7 @@ StringRef LNStandardString(unsigned Standard);
StringRef LNExtendedString(unsigned Encoding);
StringRef MacinfoString(unsigned Encoding);
StringRef RangeListEncodingString(unsigned Encoding);
StringRef CallFrameString(unsigned Encoding);
StringRef CallFrameString(unsigned Encoding, Triple::ArchType Arch);
StringRef ApplePropertyString(unsigned);
StringRef UnitTypeString(unsigned);
StringRef AtomTypeString(unsigned Atom);
@ -489,6 +491,8 @@ unsigned AttributeEncodingVendor(TypeKind E);
unsigned LanguageVendor(SourceLanguage L);
/// @}
Optional<unsigned> LanguageLowerBound(SourceLanguage L);
/// A helper struct providing information about the byte size of DW_FORM
/// values that vary in size depending on the DWARF version, address byte
/// size, or DWARF32/DWARF64.

View file

@ -582,6 +582,7 @@ enum {
EF_HEXAGON_MACH_V60 = 0x00000060, // Hexagon V60
EF_HEXAGON_MACH_V62 = 0x00000062, // Hexagon V62
EF_HEXAGON_MACH_V65 = 0x00000065, // Hexagon V65
EF_HEXAGON_MACH_V66 = 0x00000066, // Hexagon V66
// Highest ISA version flags
EF_HEXAGON_ISA_MACH = 0x00000000, // Same as specified in bits[11:0]
@ -594,6 +595,7 @@ enum {
EF_HEXAGON_ISA_V60 = 0x00000060, // Hexagon V60 ISA
EF_HEXAGON_ISA_V62 = 0x00000062, // Hexagon V62 ISA
EF_HEXAGON_ISA_V65 = 0x00000065, // Hexagon V65 ISA
EF_HEXAGON_ISA_V66 = 0x00000066, // Hexagon V66 ISA
};
// Hexagon-specific section indexes for common small data
@ -701,6 +703,7 @@ enum : unsigned {
EF_AMDGPU_MACH_AMDGCN_GFX902 = 0x02d,
EF_AMDGPU_MACH_AMDGCN_GFX904 = 0x02e,
EF_AMDGPU_MACH_AMDGCN_GFX906 = 0x02f,
EF_AMDGPU_MACH_AMDGCN_GFX909 = 0x031,
// Reserved for AMDGCN-based processors.
EF_AMDGPU_MACH_AMDGCN_RESERVED0 = 0x027,
@ -708,11 +711,14 @@ enum : unsigned {
// First/last AMDGCN-based processors.
EF_AMDGPU_MACH_AMDGCN_FIRST = EF_AMDGPU_MACH_AMDGCN_GFX600,
EF_AMDGPU_MACH_AMDGCN_LAST = EF_AMDGPU_MACH_AMDGCN_GFX906,
EF_AMDGPU_MACH_AMDGCN_LAST = EF_AMDGPU_MACH_AMDGCN_GFX909,
// Indicates if the xnack target feature is enabled for all code contained in
// the object.
// Indicates if the "xnack" target feature is enabled for all code contained
// in the object.
EF_AMDGPU_XNACK = 0x100,
// Indicates if the "sram-ecc" target feature is enabled for all code
// contained in the object.
EF_AMDGPU_SRAM_ECC = 0x200,
};
// ELF Relocation types for AMDGPU
@ -725,6 +731,38 @@ enum {
#include "ELFRelocs/BPF.def"
};
// MSP430 specific e_flags
enum : unsigned {
EF_MSP430_MACH_MSP430x11 = 11,
EF_MSP430_MACH_MSP430x11x1 = 110,
EF_MSP430_MACH_MSP430x12 = 12,
EF_MSP430_MACH_MSP430x13 = 13,
EF_MSP430_MACH_MSP430x14 = 14,
EF_MSP430_MACH_MSP430x15 = 15,
EF_MSP430_MACH_MSP430x16 = 16,
EF_MSP430_MACH_MSP430x20 = 20,
EF_MSP430_MACH_MSP430x22 = 22,
EF_MSP430_MACH_MSP430x23 = 23,
EF_MSP430_MACH_MSP430x24 = 24,
EF_MSP430_MACH_MSP430x26 = 26,
EF_MSP430_MACH_MSP430x31 = 31,
EF_MSP430_MACH_MSP430x32 = 32,
EF_MSP430_MACH_MSP430x33 = 33,
EF_MSP430_MACH_MSP430x41 = 41,
EF_MSP430_MACH_MSP430x42 = 42,
EF_MSP430_MACH_MSP430x43 = 43,
EF_MSP430_MACH_MSP430x44 = 44,
EF_MSP430_MACH_MSP430X = 45,
EF_MSP430_MACH_MSP430x46 = 46,
EF_MSP430_MACH_MSP430x47 = 47,
EF_MSP430_MACH_MSP430x54 = 54,
};
// ELF Relocation types for MSP430
enum {
#include "ELFRelocs/MSP430.def"
};
#undef ELF_RELOC
// Section header.
@ -829,6 +867,8 @@ enum : unsigned {
SHT_MIPS_DWARF = 0x7000001e, // DWARF debugging section.
SHT_MIPS_ABIFLAGS = 0x7000002a, // ABI information.
SHT_MSP430_ATTRIBUTES = 0x70000003U,
SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type.
SHT_LOUSER = 0x80000000, // Lowest type reserved for applications.
SHT_HIUSER = 0xffffffff // Highest type reserved for applications.
@ -1321,7 +1361,7 @@ enum {
GNU_PROPERTY_X86_FEATURE_1_SHSTK = 1 << 1
};
// AMDGPU specific notes.
// AMD specific notes. (Code Object V2)
enum {
// Note types with values between 0 and 9 (inclusive) are reserved.
NT_AMD_AMDGPU_HSA_METADATA = 10,
@ -1329,6 +1369,12 @@ enum {
NT_AMD_AMDGPU_PAL_METADATA = 12
};
// AMDGPU specific notes. (Code Object V3)
enum {
// Note types with values between 0 and 31 (inclusive) are reserved.
NT_AMDGPU_METADATA = 32
};
enum {
GNU_ABI_TAG_LINUX = 0,
GNU_ABI_TAG_HURD = 1,
@ -1339,6 +1385,8 @@ enum {
GNU_ABI_TAG_NACL = 6,
};
constexpr const char *ELF_NOTE_GNU = "GNU";
// Android packed relocation group flags.
enum {
RELOCATION_GROUPED_BY_INFO_FLAG = 1,

View file

@ -0,0 +1,16 @@
#ifndef ELF_RELOC
#error "ELF_RELOC must be defined"
#endif
ELF_RELOC(R_MSP430_NONE, 0)
ELF_RELOC(R_MSP430_32, 1)
ELF_RELOC(R_MSP430_10_PCREL, 2)
ELF_RELOC(R_MSP430_16, 3)
ELF_RELOC(R_MSP430_16_PCREL, 4)
ELF_RELOC(R_MSP430_16_BYTE, 5)
ELF_RELOC(R_MSP430_16_PCREL_BYTE, 6)
ELF_RELOC(R_MSP430_2X_PCREL, 7)
ELF_RELOC(R_MSP430_RL_PCREL, 8)
ELF_RELOC(R_MSP430_8, 9)
ELF_RELOC(R_MSP430_SYM_DIFF, 10)

View file

@ -486,7 +486,10 @@ enum PlatformType {
PLATFORM_IOS = 2,
PLATFORM_TVOS = 3,
PLATFORM_WATCHOS = 4,
PLATFORM_BRIDGEOS = 5
PLATFORM_BRIDGEOS = 5,
PLATFORM_IOSSIMULATOR = 7,
PLATFORM_TVOSSIMULATOR = 8,
PLATFORM_WATCHOSSIMULATOR = 9
};
// Values for tools enum in build_tool_version.

View file

@ -0,0 +1,108 @@
//===- MsgPack.def - MessagePack definitions --------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Macros for running through MessagePack enumerators.
///
//===----------------------------------------------------------------------===//
#if !( \
defined HANDLE_MP_FIRST_BYTE || defined HANDLE_MP_FIX_BITS || \
defined HANDLE_MP_FIX_BITS_MASK || defined HANDLE_MP_FIX_MAX || \
defined HANDLE_MP_FIX_LEN || defined HANDLE_MP_FIX_MIN)
#error "Missing macro definition of HANDLE_MP*"
#endif
#ifndef HANDLE_MP_FIRST_BYTE
#define HANDLE_MP_FIRST_BYTE(ID, NAME)
#endif
#ifndef HANDLE_MP_FIX_BITS
#define HANDLE_MP_FIX_BITS(ID, NAME)
#endif
#ifndef HANDLE_MP_FIX_BITS_MASK
#define HANDLE_MP_FIX_BITS_MASK(ID, NAME)
#endif
#ifndef HANDLE_MP_FIX_MAX
#define HANDLE_MP_FIX_MAX(ID, NAME)
#endif
#ifndef HANDLE_MP_FIX_LEN
#define HANDLE_MP_FIX_LEN(ID, NAME)
#endif
#ifndef HANDLE_MP_FIX_MIN
#define HANDLE_MP_FIX_MIN(ID, NAME)
#endif
HANDLE_MP_FIRST_BYTE(0xc0, Nil)
HANDLE_MP_FIRST_BYTE(0xc2, False)
HANDLE_MP_FIRST_BYTE(0xc3, True)
HANDLE_MP_FIRST_BYTE(0xc4, Bin8)
HANDLE_MP_FIRST_BYTE(0xc5, Bin16)
HANDLE_MP_FIRST_BYTE(0xc6, Bin32)
HANDLE_MP_FIRST_BYTE(0xc7, Ext8)
HANDLE_MP_FIRST_BYTE(0xc8, Ext16)
HANDLE_MP_FIRST_BYTE(0xc9, Ext32)
HANDLE_MP_FIRST_BYTE(0xca, Float32)
HANDLE_MP_FIRST_BYTE(0xcb, Float64)
HANDLE_MP_FIRST_BYTE(0xcc, UInt8)
HANDLE_MP_FIRST_BYTE(0xcd, UInt16)
HANDLE_MP_FIRST_BYTE(0xce, UInt32)
HANDLE_MP_FIRST_BYTE(0xcf, UInt64)
HANDLE_MP_FIRST_BYTE(0xd0, Int8)
HANDLE_MP_FIRST_BYTE(0xd1, Int16)
HANDLE_MP_FIRST_BYTE(0xd2, Int32)
HANDLE_MP_FIRST_BYTE(0xd3, Int64)
HANDLE_MP_FIRST_BYTE(0xd4, FixExt1)
HANDLE_MP_FIRST_BYTE(0xd5, FixExt2)
HANDLE_MP_FIRST_BYTE(0xd6, FixExt4)
HANDLE_MP_FIRST_BYTE(0xd7, FixExt8)
HANDLE_MP_FIRST_BYTE(0xd8, FixExt16)
HANDLE_MP_FIRST_BYTE(0xd9, Str8)
HANDLE_MP_FIRST_BYTE(0xda, Str16)
HANDLE_MP_FIRST_BYTE(0xdb, Str32)
HANDLE_MP_FIRST_BYTE(0xdc, Array16)
HANDLE_MP_FIRST_BYTE(0xdd, Array32)
HANDLE_MP_FIRST_BYTE(0xde, Map16)
HANDLE_MP_FIRST_BYTE(0xdf, Map32)
HANDLE_MP_FIX_BITS(0x00, PositiveInt)
HANDLE_MP_FIX_BITS(0x80, Map)
HANDLE_MP_FIX_BITS(0x90, Array)
HANDLE_MP_FIX_BITS(0xa0, String)
HANDLE_MP_FIX_BITS(0xe0, NegativeInt)
HANDLE_MP_FIX_BITS_MASK(0x80, PositiveInt)
HANDLE_MP_FIX_BITS_MASK(0xf0, Map)
HANDLE_MP_FIX_BITS_MASK(0xf0, Array)
HANDLE_MP_FIX_BITS_MASK(0xe0, String)
HANDLE_MP_FIX_BITS_MASK(0xe0, NegativeInt)
HANDLE_MP_FIX_MAX(0x7f, PositiveInt)
HANDLE_MP_FIX_MAX(0x0f, Map)
HANDLE_MP_FIX_MAX(0x0f, Array)
HANDLE_MP_FIX_MAX(0x1f, String)
HANDLE_MP_FIX_LEN(0x01, Ext1)
HANDLE_MP_FIX_LEN(0x02, Ext2)
HANDLE_MP_FIX_LEN(0x04, Ext4)
HANDLE_MP_FIX_LEN(0x08, Ext8)
HANDLE_MP_FIX_LEN(0x10, Ext16)
HANDLE_MP_FIX_MIN(-0x20, NegativeInt)
#undef HANDLE_MP_FIRST_BYTE
#undef HANDLE_MP_FIX_BITS
#undef HANDLE_MP_FIX_BITS_MASK
#undef HANDLE_MP_FIX_MAX
#undef HANDLE_MP_FIX_LEN
#undef HANDLE_MP_FIX_MIN

View file

@ -0,0 +1,93 @@
//===-- MsgPack.h - MessagePack Constants -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains constants used for implementing MessagePack support.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_BINARYFORMAT_MSGPACK_H
#define LLVM_BINARYFORMAT_MSGPACK_H
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Endian.h"
namespace llvm {
namespace msgpack {
/// The endianness of all multi-byte encoded values in MessagePack.
constexpr support::endianness Endianness = support::big;
/// The first byte identifiers of MessagePack object formats.
namespace FirstByte {
#define HANDLE_MP_FIRST_BYTE(ID, NAME) constexpr uint8_t NAME = ID;
#include "llvm/BinaryFormat/MsgPack.def"
}
/// Most significant bits used to identify "Fix" variants in MessagePack.
///
/// For example, FixStr objects encode their size in the five least significant
/// bits of their first byte, which is identified by the bit pattern "101" in
/// the three most significant bits. So FixBits::String contains 0b10100000.
///
/// A corresponding mask of the bit pattern is found in \c FixBitsMask.
namespace FixBits {
#define HANDLE_MP_FIX_BITS(ID, NAME) constexpr uint8_t NAME = ID;
#include "llvm/BinaryFormat/MsgPack.def"
}
/// Mask of bits used to identify "Fix" variants in MessagePack.
///
/// For example, FixStr objects encode their size in the five least significant
/// bits of their first byte, which is identified by the bit pattern "101" in
/// the three most significant bits. So FixBitsMask::String contains
/// 0b11100000.
///
/// The corresponding bit pattern to mask for is found in FixBits.
namespace FixBitsMask {
#define HANDLE_MP_FIX_BITS_MASK(ID, NAME) constexpr uint8_t NAME = ID;
#include "llvm/BinaryFormat/MsgPack.def"
}
/// The maximum value or size encodable in "Fix" variants of formats.
///
/// For example, FixStr objects encode their size in the five least significant
/// bits of their first byte, so the largest encodable size is 0b00011111.
namespace FixMax {
#define HANDLE_MP_FIX_MAX(ID, NAME) constexpr uint8_t NAME = ID;
#include "llvm/BinaryFormat/MsgPack.def"
}
/// The exact size encodable in "Fix" variants of formats.
///
/// The only objects for which an exact size makes sense are of Extension type.
///
/// For example, FixExt4 stores an extension type containing exactly four bytes.
namespace FixLen {
#define HANDLE_MP_FIX_LEN(ID, NAME) constexpr uint8_t NAME = ID;
#include "llvm/BinaryFormat/MsgPack.def"
}
/// The minimum value or size encodable in "Fix" variants of formats.
///
/// The only object for which a minimum makes sense is a negative FixNum.
///
/// Negative FixNum objects encode their signed integer value in one byte, but
/// they must have the pattern "111" as their three most significant bits. This
/// means all values are negative, and the smallest representable value is
/// 0b11100000.
namespace FixMin {
#define HANDLE_MP_FIX_MIN(ID, NAME) constexpr int8_t NAME = ID;
#include "llvm/BinaryFormat/MsgPack.def"
}
} // end namespace msgpack
} // end namespace llvm
#endif // LLVM_BINARYFORMAT_MSGPACK_H

View file

@ -0,0 +1,148 @@
//===- MsgPackReader.h - Simple MsgPack reader ------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This is a MessagePack reader.
///
/// See https://github.com/msgpack/msgpack/blob/master/spec.md for the full
/// standard.
///
/// Typical usage:
/// \code
/// StringRef input = GetInput();
/// msgpack::Reader MPReader(input);
/// msgpack::Object Obj;
///
/// while (MPReader.read(Obj)) {
/// switch (Obj.Kind) {
/// case msgpack::Type::Int:
// // Use Obj.Int
/// break;
/// // ...
/// }
/// }
/// \endcode
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_SUPPORT_MSGPACKREADER_H
#define LLVM_SUPPORT_MSGPACKREADER_H
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdint>
namespace llvm {
namespace msgpack {
/// MessagePack types as defined in the standard, with the exception of Integer
/// being divided into a signed Int and unsigned UInt variant in order to map
/// directly to C++ types.
///
/// The types map onto corresponding union members of the \c Object struct.
enum class Type : uint8_t {
Int,
UInt,
Nil,
Boolean,
Float,
String,
Binary,
Array,
Map,
Extension,
};
/// Extension types are composed of a user-defined type ID and an uninterpreted
/// sequence of bytes.
struct ExtensionType {
/// User-defined extension type.
int8_t Type;
/// Raw bytes of the extension object.
StringRef Bytes;
};
/// MessagePack object, represented as a tagged union of C++ types.
///
/// All types except \c Type::Nil (which has only one value, and so is
/// completely represented by the \c Kind itself) map to a exactly one union
/// member.
struct Object {
Type Kind;
union {
/// Value for \c Type::Int.
int64_t Int;
/// Value for \c Type::Uint.
uint64_t UInt;
/// Value for \c Type::Boolean.
bool Bool;
/// Value for \c Type::Float.
double Float;
/// Value for \c Type::String and \c Type::Binary.
StringRef Raw;
/// Value for \c Type::Array and \c Type::Map.
size_t Length;
/// Value for \c Type::Extension.
ExtensionType Extension;
};
Object() : Kind(Type::Int), Int(0) {}
};
/// Reads MessagePack objects from memory, one at a time.
class Reader {
public:
/// Construct a reader, keeping a reference to the \p InputBuffer.
Reader(MemoryBufferRef InputBuffer);
/// Construct a reader, keeping a reference to the \p Input.
Reader(StringRef Input);
Reader(const Reader &) = delete;
Reader &operator=(const Reader &) = delete;
/// Read one object from the input buffer, advancing past it.
///
/// The \p Obj is updated with the kind of the object read, and the
/// corresponding union member is updated.
///
/// For the collection objects (Array and Map), only the length is read, and
/// the caller must make and additional \c N calls (in the case of Array) or
/// \c N*2 calls (in the case of Map) to \c Read to retrieve the collection
/// elements.
///
/// \param [out] Obj filled with next object on success.
///
/// \returns true when object successfully read, false when at end of
/// input (and so \p Obj was not updated), otherwise an error.
Expected<bool> read(Object &Obj);
private:
MemoryBufferRef InputBuffer;
StringRef::iterator Current;
StringRef::iterator End;
size_t remainingSpace() {
// The rest of the code maintains the invariant that End >= Current, so
// that this cast is always defined behavior.
return static_cast<size_t>(End - Current);
}
template <class T> Expected<bool> readRaw(Object &Obj);
template <class T> Expected<bool> readInt(Object &Obj);
template <class T> Expected<bool> readUInt(Object &Obj);
template <class T> Expected<bool> readLength(Object &Obj);
template <class T> Expected<bool> readExt(Object &Obj);
Expected<bool> createRaw(Object &Obj, uint32_t Size);
Expected<bool> createExt(Object &Obj, uint32_t Size);
};
} // end namespace msgpack
} // end namespace llvm
#endif // LLVM_SUPPORT_MSGPACKREADER_H

View file

@ -0,0 +1,372 @@
//===- MsgPackTypes.h - MsgPack Types ---------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// \file
/// This is a data structure for representing MessagePack "documents", with
/// methods to go to and from MessagePack. The types also specialize YAMLIO
/// traits in order to go to and from YAML.
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/Optional.h"
#include "llvm/BinaryFormat/MsgPackReader.h"
#include "llvm/BinaryFormat/MsgPackWriter.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/YAMLTraits.h"
#include <vector>
#ifndef LLVM_BINARYFORMAT_MSGPACKTYPES_H
#define LLVM_BINARYFORMAT_MSGPACKTYPES_H
namespace llvm {
namespace msgpack {
class Node;
/// Short-hand for a Node pointer.
using NodePtr = std::shared_ptr<Node>;
/// Short-hand for an Optional Node pointer.
using OptNodePtr = Optional<NodePtr>;
/// Abstract base-class which can be any MessagePack type.
class Node {
public:
enum NodeKind {
NK_Scalar,
NK_Array,
NK_Map,
};
private:
virtual void anchor() = 0;
const NodeKind Kind;
static Expected<OptNodePtr> readArray(Reader &MPReader, size_t Length);
static Expected<OptNodePtr> readMap(Reader &MPReader, size_t Length);
public:
NodeKind getKind() const { return Kind; }
/// Construct a Node. Used by derived classes to track kind information.
Node(NodeKind Kind) : Kind(Kind) {}
virtual ~Node() = default;
/// Read from a MessagePack reader \p MPReader, returning an error if one is
/// encountered, or None if \p MPReader is at the end of stream, or some Node
/// pointer if some type is read.
static Expected<OptNodePtr> read(Reader &MPReader);
/// Write to a MessagePack writer \p MPWriter.
virtual void write(Writer &MPWriter) = 0;
};
/// A MessagePack scalar.
class ScalarNode : public Node {
public:
enum ScalarKind {
SK_Int,
SK_UInt,
SK_Nil,
SK_Boolean,
SK_Float,
SK_String,
SK_Binary,
};
private:
void anchor() override;
void destroy();
ScalarKind SKind;
union {
int64_t IntValue;
uint64_t UIntValue;
bool BoolValue;
double FloatValue;
std::string StringValue;
};
public:
/// Construct an Int ScalarNode.
ScalarNode(int64_t IntValue);
/// Construct an Int ScalarNode.
ScalarNode(int32_t IntValue);
/// Construct an UInt ScalarNode.
ScalarNode(uint64_t UIntValue);
/// Construct an UInt ScalarNode.
ScalarNode(uint32_t UIntValue);
/// Construct a Nil ScalarNode.
ScalarNode();
/// Construct a Boolean ScalarNode.
ScalarNode(bool BoolValue);
/// Construct a Float ScalarNode.
ScalarNode(double FloatValue);
/// Construct a String ScalarNode.
ScalarNode(StringRef StringValue);
/// Construct a String ScalarNode.
ScalarNode(const char *StringValue);
/// Construct a String ScalarNode.
ScalarNode(std::string &&StringValue);
/// Construct a Binary ScalarNode.
ScalarNode(MemoryBufferRef BinaryValue);
~ScalarNode();
ScalarNode &operator=(const ScalarNode &RHS) = delete;
/// A ScalarNode can only be move assigned.
ScalarNode &operator=(ScalarNode &&RHS);
/// Change the kind of this ScalarNode, zero initializing it to the new type.
void setScalarKind(ScalarKind SKind) {
switch (SKind) {
case SK_Int:
*this = int64_t(0);
break;
case SK_UInt:
*this = uint64_t(0);
break;
case SK_Boolean:
*this = false;
break;
case SK_Float:
*this = 0.0;
break;
case SK_String:
*this = StringRef();
break;
case SK_Binary:
*this = MemoryBufferRef("", "");
break;
case SK_Nil:
*this = ScalarNode();
break;
}
}
/// Get the current kind of ScalarNode.
ScalarKind getScalarKind() { return SKind; }
/// Get the value of an Int scalar.
///
/// \warning Assumes getScalarKind() == SK_Int
int64_t getInt() {
assert(SKind == SK_Int);
return IntValue;
}
/// Get the value of a UInt scalar.
///
/// \warning Assumes getScalarKind() == SK_UInt
uint64_t getUInt() {
assert(SKind == SK_UInt);
return UIntValue;
}
/// Get the value of an Boolean scalar.
///
/// \warning Assumes getScalarKind() == SK_Boolean
bool getBool() {
assert(SKind == SK_Boolean);
return BoolValue;
}
/// Get the value of an Float scalar.
///
/// \warning Assumes getScalarKind() == SK_Float
double getFloat() {
assert(SKind == SK_Float);
return FloatValue;
}
/// Get the value of a String scalar.
///
/// \warning Assumes getScalarKind() == SK_String
StringRef getString() {
assert(SKind == SK_String);
return StringValue;
}
/// Get the value of a Binary scalar.
///
/// \warning Assumes getScalarKind() == SK_Binary
StringRef getBinary() {
assert(SKind == SK_Binary);
return StringValue;
}
static bool classof(const Node *N) { return N->getKind() == NK_Scalar; }
void write(Writer &MPWriter) override;
/// Parse a YAML scalar of the current ScalarKind from \p ScalarStr.
///
/// \returns An empty string on success, otherwise an error message.
StringRef inputYAML(StringRef ScalarStr);
/// Output a YAML scalar of the current ScalarKind into \p OS.
void outputYAML(raw_ostream &OS) const;
/// Determine which YAML quoting type the current value would need when
/// output.
yaml::QuotingType mustQuoteYAML(StringRef ScalarStr) const;
/// Get the YAML tag for the current ScalarKind.
StringRef getYAMLTag() const;
/// Flag which affects how the type handles YAML tags when reading and
/// writing.
///
/// When false, tags are used when reading and writing. When reading, the tag
/// is used to decide the ScalarKind before parsing. When writing, the tag is
/// output along with the value.
///
/// When true, tags are ignored when reading and writing. When reading, the
/// ScalarKind is always assumed to be String. When writing, the tag is not
/// output.
bool IgnoreTag = false;
static const char *IntTag;
static const char *NilTag;
static const char *BooleanTag;
static const char *FloatTag;
static const char *StringTag;
static const char *BinaryTag;
};
class ArrayNode : public Node, public std::vector<NodePtr> {
void anchor() override;
public:
ArrayNode() : Node(NK_Array) {}
static bool classof(const Node *N) { return N->getKind() == NK_Array; }
void write(Writer &MPWriter) override {
MPWriter.writeArraySize(this->size());
for (auto &N : *this)
N->write(MPWriter);
}
};
class MapNode : public Node, public StringMap<NodePtr> {
void anchor() override;
public:
MapNode() : Node(NK_Map) {}
static bool classof(const Node *N) { return N->getKind() == NK_Map; }
void write(Writer &MPWriter) override {
MPWriter.writeMapSize(this->size());
for (auto &N : *this) {
MPWriter.write(N.first());
N.second->write(MPWriter);
}
}
};
} // end namespace msgpack
namespace yaml {
template <> struct PolymorphicTraits<msgpack::NodePtr> {
static NodeKind getKind(const msgpack::NodePtr &N) {
if (isa<msgpack::ScalarNode>(*N))
return NodeKind::Scalar;
if (isa<msgpack::MapNode>(*N))
return NodeKind::Map;
if (isa<msgpack::ArrayNode>(*N))
return NodeKind::Sequence;
llvm_unreachable("NodeKind not supported");
}
static msgpack::ScalarNode &getAsScalar(msgpack::NodePtr &N) {
if (!N || !isa<msgpack::ScalarNode>(*N))
N.reset(new msgpack::ScalarNode());
return *cast<msgpack::ScalarNode>(N.get());
}
static msgpack::MapNode &getAsMap(msgpack::NodePtr &N) {
if (!N || !isa<msgpack::MapNode>(*N))
N.reset(new msgpack::MapNode());
return *cast<msgpack::MapNode>(N.get());
}
static msgpack::ArrayNode &getAsSequence(msgpack::NodePtr &N) {
if (!N || !isa<msgpack::ArrayNode>(*N))
N.reset(new msgpack::ArrayNode());
return *cast<msgpack::ArrayNode>(N.get());
}
};
template <> struct TaggedScalarTraits<msgpack::ScalarNode> {
static void output(const msgpack::ScalarNode &S, void *Ctxt,
raw_ostream &ScalarOS, raw_ostream &TagOS) {
if (!S.IgnoreTag)
TagOS << S.getYAMLTag();
S.outputYAML(ScalarOS);
}
static StringRef input(StringRef ScalarStr, StringRef Tag, void *Ctxt,
msgpack::ScalarNode &S) {
if (Tag == msgpack::ScalarNode::IntTag) {
S.setScalarKind(msgpack::ScalarNode::SK_UInt);
if (S.inputYAML(ScalarStr) == StringRef())
return StringRef();
S.setScalarKind(msgpack::ScalarNode::SK_Int);
return S.inputYAML(ScalarStr);
}
if (S.IgnoreTag || Tag == msgpack::ScalarNode::StringTag ||
Tag == "tag:yaml.org,2002:str")
S.setScalarKind(msgpack::ScalarNode::SK_String);
else if (Tag == msgpack::ScalarNode::NilTag)
S.setScalarKind(msgpack::ScalarNode::SK_Nil);
else if (Tag == msgpack::ScalarNode::BooleanTag)
S.setScalarKind(msgpack::ScalarNode::SK_Boolean);
else if (Tag == msgpack::ScalarNode::FloatTag)
S.setScalarKind(msgpack::ScalarNode::SK_Float);
else if (Tag == msgpack::ScalarNode::StringTag)
S.setScalarKind(msgpack::ScalarNode::SK_String);
else if (Tag == msgpack::ScalarNode::BinaryTag)
S.setScalarKind(msgpack::ScalarNode::SK_Binary);
else
return "Unsupported messagepack tag";
return S.inputYAML(ScalarStr);
}
static QuotingType mustQuote(const msgpack::ScalarNode &S, StringRef Str) {
return S.mustQuoteYAML(Str);
}
};
template <> struct CustomMappingTraits<msgpack::MapNode> {
static void inputOne(IO &IO, StringRef Key, msgpack::MapNode &M) {
IO.mapRequired(Key.str().c_str(), M[Key]);
}
static void output(IO &IO, msgpack::MapNode &M) {
for (auto &N : M)
IO.mapRequired(N.getKey().str().c_str(), N.getValue());
}
};
template <> struct SequenceTraits<msgpack::ArrayNode> {
static size_t size(IO &IO, msgpack::ArrayNode &A) { return A.size(); }
static msgpack::NodePtr &element(IO &IO, msgpack::ArrayNode &A,
size_t Index) {
if (Index >= A.size())
A.resize(Index + 1);
return A[Index];
}
};
} // end namespace yaml
} // end namespace llvm
#endif // LLVM_BINARYFORMAT_MSGPACKTYPES_H

View file

@ -0,0 +1,131 @@
//===- MsgPackWriter.h - Simple MsgPack writer ------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains a MessagePack writer.
///
/// See https://github.com/msgpack/msgpack/blob/master/spec.md for the full
/// specification.
///
/// Typical usage:
/// \code
/// raw_ostream output = GetOutputStream();
/// msgpack::Writer MPWriter(output);
/// MPWriter.writeNil();
/// MPWriter.write(false);
/// MPWriter.write("string");
/// // ...
/// \endcode
///
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_SUPPORT_MSGPACKPARSER_H
#define LLVM_SUPPORT_MSGPACKPARSER_H
#include "llvm/BinaryFormat/MsgPack.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
namespace msgpack {
/// Writes MessagePack objects to an output stream, one at a time.
class Writer {
public:
/// Construct a writer, optionally enabling "Compatibility Mode" as defined
/// in the MessagePack specification.
///
/// When in \p Compatible mode, the writer will write \c Str16 formats
/// instead of \c Str8 formats, and will refuse to write any \c Bin formats.
///
/// \param OS stream to output MessagePack objects to.
/// \param Compatible when set, write in "Compatibility Mode".
Writer(raw_ostream &OS, bool Compatible = false);
Writer(const Writer &) = delete;
Writer &operator=(const Writer &) = delete;
/// Write a \em Nil to the output stream.
///
/// The output will be the \em nil format.
void writeNil();
/// Write a \em Boolean to the output stream.
///
/// The output will be a \em bool format.
void write(bool b);
/// Write a signed integer to the output stream.
///
/// The output will be in the smallest possible \em int format.
///
/// The format chosen may be for an unsigned integer.
void write(int64_t i);
/// Write an unsigned integer to the output stream.
///
/// The output will be in the smallest possible \em int format.
void write(uint64_t u);
/// Write a floating point number to the output stream.
///
/// The output will be in the smallest possible \em float format.
void write(double d);
/// Write a string to the output stream.
///
/// The output will be in the smallest possible \em str format.
void write(StringRef s);
/// Write a memory buffer to the output stream.
///
/// The output will be in the smallest possible \em bin format.
///
/// \warning Do not use this overload if in \c Compatible mode.
void write(MemoryBufferRef Buffer);
/// Write the header for an \em Array of the given size.
///
/// The output will be in the smallest possible \em array format.
//
/// The header contains an identifier for the \em array format used, as well
/// as an encoding of the size of the array.
///
/// N.B. The caller must subsequently call \c Write an additional \p Size
/// times to complete the array.
void writeArraySize(uint32_t Size);
/// Write the header for a \em Map of the given size.
///
/// The output will be in the smallest possible \em map format.
//
/// The header contains an identifier for the \em map format used, as well
/// as an encoding of the size of the map.
///
/// N.B. The caller must subsequently call \c Write and additional \c Size*2
/// times to complete the map. Each even numbered call to \c Write defines a
/// new key, and each odd numbered call defines the previous key's value.
void writeMapSize(uint32_t Size);
/// Write a typed memory buffer (an extension type) to the output stream.
///
/// The output will be in the smallest possible \em ext format.
void writeExt(int8_t Type, MemoryBufferRef Buffer);
private:
support::endian::Writer EW;
bool Compatible;
};
} // end namespace msgpack
} // end namespace llvm
#endif // LLVM_SUPPORT_MSGPACKPARSER_H

View file

@ -16,6 +16,7 @@
#define LLVM_BINARYFORMAT_WASM_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
namespace llvm {
namespace wasm {
@ -25,7 +26,7 @@ const char WasmMagic[] = {'\0', 'a', 's', 'm'};
// Wasm binary format version
const uint32_t WasmVersion = 0x1;
// Wasm linking metadata version
const uint32_t WasmMetadataVersion = 0x1;
const uint32_t WasmMetadataVersion = 0x2;
// Wasm uses a 64k page size
const uint32_t WasmPageSize = 65536;
@ -34,9 +35,12 @@ struct WasmObjectHeader {
uint32_t Version;
};
struct WasmSignature {
std::vector<uint8_t> ParamTypes;
uint8_t ReturnType;
struct WasmDylinkInfo {
uint32_t MemorySize; // Memory size in bytes
uint32_t MemoryAlignment; // P2 alignment of memory
uint32_t TableSize; // Table size in elements
uint32_t TableAlignment; // P2 alignment of table
std::vector<StringRef> Needed; // Shared library depenedencies
};
struct WasmExport {
@ -79,6 +83,18 @@ struct WasmGlobal {
StringRef SymbolName; // from the "linking" section
};
struct WasmEventType {
// Kind of event. Currently only WASM_EVENT_ATTRIBUTE_EXCEPTION is possible.
uint32_t Attribute;
uint32_t SigIndex;
};
struct WasmEvent {
uint32_t Index;
WasmEventType Type;
StringRef SymbolName; // from the "linking" section
};
struct WasmImport {
StringRef Module;
StringRef Field;
@ -88,6 +104,7 @@ struct WasmImport {
WasmGlobalType Global;
WasmTable Table;
WasmLimits Memory;
WasmEventType Event;
};
};
@ -104,8 +121,8 @@ struct WasmFunction {
uint32_t Size;
uint32_t CodeOffset; // start of Locals and Body
StringRef SymbolName; // from the "linking" section
StringRef DebugName; // from the "name" section
uint32_t Comdat; // from the "comdat info" section
StringRef DebugName; // from the "name" section
uint32_t Comdat; // from the "comdat info" section
};
struct WasmDataSegment {
@ -171,18 +188,20 @@ struct WasmLinkingData {
};
enum : unsigned {
WASM_SEC_CUSTOM = 0, // Custom / User-defined section
WASM_SEC_TYPE = 1, // Function signature declarations
WASM_SEC_IMPORT = 2, // Import declarations
WASM_SEC_FUNCTION = 3, // Function declarations
WASM_SEC_TABLE = 4, // Indirect function table and other tables
WASM_SEC_MEMORY = 5, // Memory attributes
WASM_SEC_GLOBAL = 6, // Global declarations
WASM_SEC_EXPORT = 7, // Exports
WASM_SEC_START = 8, // Start function declaration
WASM_SEC_ELEM = 9, // Elements section
WASM_SEC_CODE = 10, // Function bodies (code)
WASM_SEC_DATA = 11 // Data segments
WASM_SEC_CUSTOM = 0, // Custom / User-defined section
WASM_SEC_TYPE = 1, // Function signature declarations
WASM_SEC_IMPORT = 2, // Import declarations
WASM_SEC_FUNCTION = 3, // Function declarations
WASM_SEC_TABLE = 4, // Indirect function table and other tables
WASM_SEC_MEMORY = 5, // Memory attributes
WASM_SEC_GLOBAL = 6, // Global declarations
WASM_SEC_EXPORT = 7, // Exports
WASM_SEC_START = 8, // Start function declaration
WASM_SEC_ELEM = 9, // Elements section
WASM_SEC_CODE = 10, // Function bodies (code)
WASM_SEC_DATA = 11, // Data segments
WASM_SEC_DATACOUNT = 12, // Data segment count
WASM_SEC_EVENT = 13 // Event declarations
};
// Type immediate encodings used in various contexts.
@ -191,7 +210,8 @@ enum : unsigned {
WASM_TYPE_I64 = 0x7E,
WASM_TYPE_F32 = 0x7D,
WASM_TYPE_F64 = 0x7C,
WASM_TYPE_ANYFUNC = 0x70,
WASM_TYPE_V128 = 0x7B,
WASM_TYPE_FUNCREF = 0x70,
WASM_TYPE_EXCEPT_REF = 0x68,
WASM_TYPE_FUNC = 0x60,
WASM_TYPE_NORESULT = 0x40, // for blocks with no result values
@ -203,12 +223,13 @@ enum : unsigned {
WASM_EXTERNAL_TABLE = 0x1,
WASM_EXTERNAL_MEMORY = 0x2,
WASM_EXTERNAL_GLOBAL = 0x3,
WASM_EXTERNAL_EVENT = 0x4,
};
// Opcodes used in initializer expressions.
enum : unsigned {
WASM_OPCODE_END = 0x0b,
WASM_OPCODE_GET_GLOBAL = 0x23,
WASM_OPCODE_GLOBAL_GET = 0x23,
WASM_OPCODE_I32_CONST = 0x41,
WASM_OPCODE_I64_CONST = 0x42,
WASM_OPCODE_F32_CONST = 0x43,
@ -217,35 +238,27 @@ enum : unsigned {
enum : unsigned {
WASM_LIMITS_FLAG_HAS_MAX = 0x1,
};
// Subset of types that a value can have
enum class ValType {
I32 = WASM_TYPE_I32,
I64 = WASM_TYPE_I64,
F32 = WASM_TYPE_F32,
F64 = WASM_TYPE_F64,
EXCEPT_REF = WASM_TYPE_EXCEPT_REF,
WASM_LIMITS_FLAG_IS_SHARED = 0x2,
};
// Kind codes used in the custom "name" section
enum : unsigned {
WASM_NAMES_FUNCTION = 0x1,
WASM_NAMES_LOCAL = 0x2,
WASM_NAMES_LOCAL = 0x2,
};
// Kind codes used in the custom "linking" section
enum : unsigned {
WASM_SEGMENT_INFO = 0x5,
WASM_INIT_FUNCS = 0x6,
WASM_COMDAT_INFO = 0x7,
WASM_SYMBOL_TABLE = 0x8,
WASM_SEGMENT_INFO = 0x5,
WASM_INIT_FUNCS = 0x6,
WASM_COMDAT_INFO = 0x7,
WASM_SYMBOL_TABLE = 0x8,
};
// Kind codes used in the custom "linking" section in the WASM_COMDAT_INFO
enum : unsigned {
WASM_COMDAT_DATA = 0x0,
WASM_COMDAT_FUNCTION = 0x1,
WASM_COMDAT_DATA = 0x0,
WASM_COMDAT_FUNCTION = 0x1,
};
// Kind codes used in the custom "linking" section in the WASM_SYMBOL_TABLE
@ -254,17 +267,23 @@ enum WasmSymbolType : unsigned {
WASM_SYMBOL_TYPE_DATA = 0x1,
WASM_SYMBOL_TYPE_GLOBAL = 0x2,
WASM_SYMBOL_TYPE_SECTION = 0x3,
WASM_SYMBOL_TYPE_EVENT = 0x4,
};
const unsigned WASM_SYMBOL_BINDING_MASK = 0x3;
const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0xc;
// Kinds of event attributes.
enum WasmEventAttribute : unsigned {
WASM_EVENT_ATTRIBUTE_EXCEPTION = 0x0,
};
const unsigned WASM_SYMBOL_BINDING_GLOBAL = 0x0;
const unsigned WASM_SYMBOL_BINDING_WEAK = 0x1;
const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2;
const unsigned WASM_SYMBOL_BINDING_MASK = 0x3;
const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0xc;
const unsigned WASM_SYMBOL_BINDING_GLOBAL = 0x0;
const unsigned WASM_SYMBOL_BINDING_WEAK = 0x1;
const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2;
const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0;
const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4;
const unsigned WASM_SYMBOL_UNDEFINED = 0x10;
const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4;
const unsigned WASM_SYMBOL_UNDEFINED = 0x10;
#define WASM_RELOC(name, value) name = value,
@ -274,9 +293,32 @@ enum : unsigned {
#undef WASM_RELOC
// Subset of types that a value can have
enum class ValType {
I32 = WASM_TYPE_I32,
I64 = WASM_TYPE_I64,
F32 = WASM_TYPE_F32,
F64 = WASM_TYPE_F64,
V128 = WASM_TYPE_V128,
EXCEPT_REF = WASM_TYPE_EXCEPT_REF,
};
struct WasmSignature {
SmallVector<wasm::ValType, 1> Returns;
SmallVector<wasm::ValType, 4> Params;
// Support empty and tombstone instances, needed by DenseMap.
enum { Plain, Empty, Tombstone } State = Plain;
WasmSignature(SmallVector<wasm::ValType, 1> &&InReturns,
SmallVector<wasm::ValType, 4> &&InParams)
: Returns(InReturns), Params(InParams) {}
WasmSignature() = default;
};
// Useful comparison operators
inline bool operator==(const WasmSignature &LHS, const WasmSignature &RHS) {
return LHS.ReturnType == RHS.ReturnType && LHS.ParamTypes == RHS.ParamTypes;
return LHS.State == RHS.State && LHS.Returns == RHS.Returns &&
LHS.Params == RHS.Params;
}
inline bool operator!=(const WasmSignature &LHS, const WasmSignature &RHS) {

View file

@ -1,4 +1,3 @@
#ifndef WASM_RELOC
#error "WASM_RELOC must be defined"
#endif
@ -13,3 +12,4 @@ WASM_RELOC(R_WEBASSEMBLY_TYPE_INDEX_LEB, 6)
WASM_RELOC(R_WEBASSEMBLY_GLOBAL_INDEX_LEB, 7)
WASM_RELOC(R_WEBASSEMBLY_FUNCTION_OFFSET_I32, 8)
WASM_RELOC(R_WEBASSEMBLY_SECTION_OFFSET_I32, 9)
WASM_RELOC(R_WEBASSEMBLY_EVENT_INDEX_LEB, 10)

View file

@ -51,6 +51,7 @@ class Module;
struct BitcodeLTOInfo {
bool IsThinLTO;
bool HasSummary;
bool EnableSplitLTOUnit;
};
/// Represents a module in a bitcode file.

Some files were not shown because too many files have changed in this diff Show more